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.scoring;
020    
021    import java.util.Arrays;
022    
023    import de.spieleck.app.turn.PlayerGameScore;
024    import de.spieleck.app.turn.PlayerScore;
025    
026    /**
027     * A ScoringMode for a match of Zoff.
028     * <br />
029     * During a match of this card games a player obtains both
030     * a score and a rank. The rank is the major scoring component,
031     * since it depends on the score, but has an additional rule to
032     * avoid ties. The table score is however retained for tie breaking
033     * of the tournament ranking.
034     *
035     * <p><a href="$URL: https://svn.sourceforge.net/svnroot/jtourney/src/de/spieleck/app/turn/scoring/Zoff.java $">$URL: https://svn.sourceforge.net/svnroot/jtourney/src/de/spieleck/app/turn/scoring/Zoff.java $</a></p>
036     *
037     * @author Frank S. Nestel
038     * @author $Author: nestefan $
039     * @version $Revision: 2 $ $Date: 2006-03-20 14:33:27 +0100 (Mo, 20 Mrz 2006) $ $Author: nestefan $
040     */
041    public class Zoff
042        extends BaseScoring
043    {
044        public PlayerGameScore parseRawScore(String line)
045        {
046            int i = line.indexOf(" ");
047            if ( i == -1 )
048                throw new RuntimeException("Illegal Zoff score <"+line+">.");
049            int rank = Integer.parseInt(line.substring(0,i).trim());
050            double score = Double.parseDouble(line.substring(i+1).trim());
051            return new ZoffScore(rank, score);
052        }
053    
054        public String checkScore(PlayerGameScore[] pgs)
055        {
056            double[] scores = new double[pgs.length];
057            for(int i = 0; i < pgs.length; i++)
058            {
059                ZoffScore in = (ZoffScore) pgs[i];
060                scores[i] = in.score;
061            }
062            Arrays.sort(scores);
063            boolean check[] = new boolean[pgs.length + 1];
064            for(int i = 0; i < pgs.length; i++)
065            {
066                ZoffScore in = (ZoffScore) pgs[i];
067                int rank = (int) Math.round(in.rank);
068                if ( check[rank] )
069                    return "Rank "+rank+" given twice.";
070                check[rank] = true;
071                if ( in.score != scores[pgs.length - rank] )
072                    return "Score, Rank mismatch : "+in;
073            }
074            for(int i = 0; i < pgs.length; i++)
075            {
076                int rank = i + 1;
077                if ( !check[rank] )
078                    return "Rank "+rank+" missing.";
079            }
080            return null;
081        }
082    
083        public PlayerGameScore[] adjustScore(PlayerGameScore[] pgs)
084        {
085            double h = 0.0;
086            ZoffScore[] in = new ZoffScore[pgs.length];
087            for(int i = 0; i < pgs.length; i++)
088            {
089                in[i] = (ZoffScore) pgs[i];
090                int rank = (int) Math.round(in[i].rank);
091                h += in[i].rank;
092            }
093            h /= pgs.length;
094            ZoffScore[] res = new ZoffScore[pgs.length];
095            for(int i = 0; i < pgs.length; i++)
096                res[i] = new ZoffScore(h - in[i].rank, in[i].score);
097            return res;
098        }
099    
100        public PlayerGameScore zeroScore()
101        {
102            return new ZoffScore(0,0);
103        }
104    
105        public PlayerScore addPlayers(PlayerScore ps, PlayerScore pgs)
106        {
107            ZoffScore psz = (ZoffScore) ps;
108            ZoffScore pgsz = (ZoffScore) pgs;
109            return new ZoffScore(psz.rank + pgsz.rank, psz.score + pgsz.score);
110        }
111    
112        public static class ZoffScore
113            implements PlayerGameScore, PlayerScore
114        {
115            // Note: Rank could have been integer, but for implementation
116            // Lazyness and simplicity in this case we don't mind.
117            private double rank, score;
118    
119            public ZoffScore(double rank, double score)
120            {
121                this.rank = rank;
122                this.score = score;
123            }
124    
125            public int compareTo(Object o)
126            {
127                if ( ! ( o instanceof ZoffScore ) ) 
128                    return -1;
129                ZoffScore oz = (ZoffScore) o;
130                double delta = oz.rank - this.rank;
131                if ( delta > 0.0 )
132                    return -1;
133                else if ( delta < 0.0 )
134                    return +1;
135                delta = this.score - oz.score;
136                if ( delta > 0.0 )
137                    return +1;
138                else if ( delta < 0.0 )
139                    return -1;
140                return 0;
141            }
142    
143            public String toString()
144            {
145                return Integer.toString((int)rank)+" "+Double.toString(score);
146            }
147        }
148    
149        public String toString()
150        {
151            return "Zoff";
152        }
153    }