001 /////////////////////////////////////////////////////////////////////////////// 002 // Copyright (c) 2006, Frank S. Nestel, All Rights Reserved. 003 // 004 // This library is free software; you can redistribute it and/or 005 // modify it under the terms of the GNU Lesser General Public 006 // License as published by the Free Software Foundation; either 007 // version 2.1 of the License, or (at your option) any later version. 008 // 009 // This library is distributed in the hope that it will be useful, 010 // but WITHOUT ANY WARRANTY; without even the implied warranty of 011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 012 // GNU General Public License for more details. 013 // 014 // You should have received a copy of the GNU Lesser General Public 015 // License along with this program; if not, write to the Free Software 016 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 017 /////////////////////////////////////////////////////////////////////////////// 018 019 package de.spieleck.app.turn; 020 021 import java.util.ArrayList; 022 import java.util.Iterator; 023 024 import gnu.trove.TIntObjectHashMap; 025 import gnu.trove.TIntObjectIterator; 026 import gnu.trove.TObjectIntHashMap; 027 028 import org.apache.log4j.Logger; 029 030 /** 031 * This class could have named "Participant" for higher abstraction, 032 * it contains information about name and scoring. 033 * <br/> 034 * While for many tournaments a player might be a person, for a team 035 * bridge tournament, the Player class would probably reflect a pair 036 * of persons. But I didn't care to implement Bridge anyway. 037 * <br/> 038 * XXX The fact that the StandardPlayerRegistry is a embedded class 039 * within Player, is quirky and might change sometime. 040 * 041 * <p><a href="$URL: https://svn.sourceforge.net/svnroot/jtourney/src/de/spieleck/app/turn/Player.java $">$URL: https://svn.sourceforge.net/svnroot/jtourney/src/de/spieleck/app/turn/Player.java $</a></p> 042 * 043 * @author Frank S. Nestel 044 * @author $Author: nestefan $ 045 * @version $Revision: 2 $ $Date: 2006-03-20 14:33:27 +0100 (Mo, 20 Mrz 2006) $ $Author: nestefan $ 046 */ 047 public class Player 048 implements Comparable 049 { 050 private final static Logger L = Logger.getLogger(Player.class); 051 private int id; 052 053 private String nameLang; 054 055 private String nameKurz; 056 057 private String remark; 058 059 private PlayerScore score; 060 061 private PlayerScore fineScore = null; 062 063 private boolean active = true; 064 065 private PlayerRegistry registry; 066 067 private ArrayList<GameResult> gameResults = new ArrayList<GameResult>(); 068 069 private TObjectIntHashMap opponents = new TObjectIntHashMap(); 070 071 private Player(int id, String nameKurz, String nameLang, String remark) 072 { 073 this.id = id; 074 this.nameLang = nameLang; 075 // XXX This convention is ugly, isn't it? 076 char ch0 = nameKurz.charAt(0); 077 if ( ch0 == '-' ) 078 { 079 this.nameKurz = nameKurz.substring(1); 080 active = false; 081 } 082 else if ( ch0 == '+' ) 083 { 084 this.nameKurz = nameKurz.substring(1); 085 } 086 else 087 { 088 this.nameKurz = nameKurz; 089 } 090 this.remark = remark; 091 } 092 093 public void setScore(PlayerScore ps) 094 { 095 this.score = ps; 096 if(L.isDebugEnabled()) L.debug(this+".setScore("+ps+") fineScore="+fineScore); 097 this.fineScore = null; 098 Iterator<GameResult> iter = results(); 099 while ( iter.hasNext() ) 100 { 101 Iterator<Player> i2 = iter.next().players(); 102 while ( i2.hasNext() ) 103 { 104 Player p = i2.next(); 105 if(p.fineScore != null && L.isDebugEnabled()) L.debug(" - clear.fineScore:"+this+" "+p+", "+p.fineScore); 106 p.fineScore = null; 107 } 108 } 109 } 110 111 public PlayerScore getScore() 112 { 113 return score; 114 } 115 116 public PlayerScore getFineScore() 117 { 118 if(L.isDebugEnabled())L.debug(this+".getFineScore "+fineScore); 119 if ( fineScore == null ) 120 { 121 ScoringMode sm = getRegistry().getScoringMode(); 122 fineScore = getRegistry().getScoringMode().initialValue(); 123 Iterator<GameResult> iter = results(); 124 while ( iter.hasNext() ) 125 { 126 Iterator<Player> i2 = iter.next().players(); 127 while ( i2.hasNext() ) 128 { 129 fineScore = sm.addPlayers(fineScore, i2.next().getScore()); 130 } 131 } 132 } 133 return fineScore; 134 } 135 136 private void setRegistry(PlayerRegistry reg) 137 { 138 this.registry = reg; 139 } 140 141 public PlayerRegistry getRegistry() 142 { 143 return registry; 144 } 145 146 public void addResult(GameResult result) 147 { 148 gameResults.add(result); 149 Iterator<Player> players = result.players(); 150 int count = 0; 151 while ( players.hasNext() ) 152 { 153 Player p = players.next(); 154 if ( p != this ) 155 { 156 if ( !opponents.increment(p) ) 157 opponents.put(p, 1); 158 } 159 } 160 } 161 162 public int getPlayedAgainst(Player p) 163 { 164 return opponents.get(p); 165 } 166 167 public Iterator<GameResult> results() 168 { 169 return gameResults.iterator(); 170 } 171 172 public int getId() 173 { 174 return id; 175 } 176 177 public boolean isActive() 178 { 179 return active; 180 } 181 182 public String getNameLang() 183 { 184 return nameLang; 185 } 186 187 public String getNameKurz() 188 { 189 return nameKurz; 190 } 191 192 public String getRemark() 193 { 194 return remark; 195 } 196 197 public String toString() 198 { 199 return "("+id+":"+nameKurz+")"; 200 } 201 202 public int compareTo(Object o) 203 { 204 if ( ! (o instanceof Player) ) 205 return -1; 206 Player sh = (Player) o; 207 int h = sh.getScore().compareTo(getScore()); 208 if ( h == 0 ) 209 { 210 h = sh.getFineScore().compareTo(getFineScore()); 211 } 212 return h; 213 } 214 215 public static class StandardPlayerRegistry 216 implements PlayerRegistry 217 { 218 private TIntObjectHashMap reg = new TIntObjectHashMap(); 219 220 private ScoringMode scoringMode; 221 222 private int sid; 223 224 public StandardPlayerRegistry(ScoringMode scoringMode) 225 { 226 this.scoringMode = scoringMode; 227 } 228 229 public int count() 230 { 231 return reg.size(); 232 } 233 234 public ScoringMode getScoringMode() 235 { 236 return scoringMode; 237 } 238 239 public Player getPlayer(int id) 240 { 241 return (Player) reg.get(id); 242 } 243 244 public Player[] getPlayers() 245 { 246 // doesn't work return (Player[]) reg.getValues(); 247 int n = reg.size(); 248 Player[] ap = new Player[n]; 249 TIntObjectIterator it = reg.iterator(); 250 int i = 0; 251 while ( it.hasNext() ) 252 { 253 it.advance(); 254 Player p = (Player) it.value(); 255 ap[i++] = p; 256 } 257 return ap; 258 } 259 260 public int activeCount() 261 { 262 TIntObjectIterator it = reg.iterator(); 263 int ac = 0; 264 while ( it.hasNext() ) 265 { 266 it.advance(); 267 Player p = (Player) it.value(); 268 if ( p.isActive() ) 269 ac++; 270 } 271 return ac; 272 } 273 274 public Player[] getActivePlayers() 275 { 276 int n = activeCount(); 277 Player[] ap = new Player[n]; 278 TIntObjectIterator it = reg.iterator(); 279 int i = 0; 280 while ( it.hasNext() ) 281 { 282 it.advance(); 283 Player p = (Player) it.value(); 284 if ( p.isActive() ) 285 ap[i++] = p; 286 } 287 return ap; 288 } 289 290 public Player registerPlayer(String nameKurz, String nameLang, String remark) 291 { 292 int pid = sid++; 293 Player p = new Player(pid, nameKurz, nameLang, remark); 294 p.setScore(scoringMode.initialValue()); 295 p.setRegistry(this); 296 reg.put(pid, p); 297 return p; 298 } 299 } 300 }