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 }