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    }