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.pairing;
020
021 import java.util.Arrays;
022 import java.util.Random;
023
024 import org.apache.log4j.Logger;
025
026 import de.spieleck.app.turn.Game;
027 import de.spieleck.app.turn.Player;
028 import de.spieleck.app.turn.SplittingMode;
029 import de.spieleck.app.turn.PlayerRegistry;
030
031 /**
032 * This is a first strategy which heuristically solves basic problems.
033 * The basic problems are:
034 * <ul>
035 * <li>Give every player as many different opponents as possible.</li>
036 * <li>Give every player as many big tables as possible.</li>
037 * </ul>
038 * Note: This class kind of fails to give every player the optimal
039 * number of players as often as possible, when the optimal number is
040 * smaller than the non optimal ones. That is the case for Skat, where
041 * optimal tables are 3 player and 4 players are a compromise, but the
042 * programm would try to maximise the number of 4 player tables players
043 * get.
044 *
045 * <p><a href="$URL: https://svn.sourceforge.net/svnroot/jtourney/src/de/spieleck/app/turn/pairing/MixingPairing1.java $">$URL: https://svn.sourceforge.net/svnroot/jtourney/src/de/spieleck/app/turn/pairing/MixingPairing1.java $</a></p>
046 *
047 * @author Frank S. Nestel
048 * @author $Author: nestefan $
049 * @version $Revision: 2 $ $Date: 2006-03-20 14:33:27 +0100 (Mo, 20 Mrz 2006) $ $Author: nestefan $
050 */
051 public class MixingPairing1
052 extends BasePairing
053 {
054 private final static Logger L = Logger.getLogger(MixingPairing1.class);
055
056 public Game[] pairing(int round, PlayerRegistry pRegistry, SplittingMode sm)
057 {
058 Player[] standing = pRegistry.getActivePlayers();
059 int n = standing.length;
060 WrappedPlayer[] wps = new WrappedPlayer[n];
061 for(int i = 0; i < n; i++)
062 wps[i] = new WrappedPlayer(standing[i]);
063 Arrays.sort(wps);
064 if (L.isDebugEnabled()) for(int i = 0; i < wps.length; i++) L.debug(" "+i+". "+wps[i].p+" "+wps[i].differentOpponents+" "+wps[i].opponents+" "+wps[i].offset);
065 int[] splitting = sm.split(n);
066 int gameSize = splitting.length - 1;
067 int gameCount = sum(splitting);
068 int k = 0;
069 GameImpl[] res = new GameImpl[gameCount];
070 while ( k < gameCount )
071 {
072 while ( splitting[gameSize] == 0 )
073 gameSize--;
074 GameImpl g = new GameImpl(k+1);
075 while ( g.size() < gameSize )
076 {
077 Arrays.sort(wps, 0, n);
078 WrappedPlayer wp = (WrappedPlayer) wps[0];
079 g.add(wp.p);
080 wps[0] = wps[--n];
081 for(int i = 1; i < n; i++)
082 {
083 int c = wp.p.getPlayedAgainst(wps[i].p);
084 wps[i].offset += c * c;
085 }
086 }
087 for(int i = 0; i < n; i++)
088 wps[i].offset = 0;
089 splitting[gameSize]--;
090 res[k++] = g;
091 }
092 return res;
093 }
094
095 public String toString()
096 {
097 return "MixingPairing1";
098 }
099
100 private static class WrappedPlayer
101 implements Comparable
102 {
103 Player p;
104 int offset = 0;
105 int differentOpponents = 0;
106 int opponents = 0;
107
108 public WrappedPlayer(Player p)
109 {
110 this.p = p;
111 Player[] opps = p.getRegistry().getPlayers();
112 for(int i = 0; i < opps.length; i++)
113 {
114 int c = p.getPlayedAgainst(opps[i]);
115 if ( c > 0 )
116 {
117 differentOpponents++;
118 opponents += c;
119 }
120 }
121 }
122
123 public int compareTo(Object o)
124 {
125 if ( !(o instanceof WrappedPlayer) )
126 {
127 return -1;
128 }
129 int h;
130 WrappedPlayer p2 = (WrappedPlayer) o;
131 h = offset - p2.offset;
132 if ( h != 0 )
133 return h;
134 h = differentOpponents - p2.differentOpponents;
135 if ( h != 0 )
136 return h;
137 h = opponents - p2.opponents;
138 if ( h != 0 )
139 return h;
140 return p.compareTo(p2);
141 }
142 }
143 }