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    }