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 }