Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Added recursive function for finding best pairings

  • Loading branch information...
commit 8ddded45c7c5738e1b6d8cea15b574bcaa99e263 1 parent db4d85c
Khelldar authored November 17, 2011
6  application/controllers/mtgdc.php
@@ -81,6 +81,12 @@ public function newDraft() {
81 81
     }
82 82
 
83 83
     public function round() {
  84
+        //check if GET -- if it is, start round 1 or recover 
  85
+        //if draft object in session is higher than round 1
  86
+        
  87
+        //check if POST -- if it is, then incremement round 
  88
+        //and do matchmaking
  89
+        
84 90
         session_start();
85 91
         //TODO - check for valid session / data, handle appropriately.
86 92
         $draft = $_SESSION['draft'];
416  application/models/draft_model.php
@@ -10,7 +10,7 @@ class Draft_model extends CI_Model
10 10
     var $roundNumber;
11 11
     var $players;
12 12
     var $droppedPlayers;
13  
-    
  13
+    var $maxNumberOfRounds;
14 14
 
15 15
     function __construct()
16 16
     {
@@ -46,10 +46,10 @@ function dropPlayer($id)
46 46
             }
47 47
         }
48 48
     }
49  
-    
  49
+
50 50
     function updateScores($score)
51 51
     {
52  
-        
  52
+
53 53
         foreach($this->players as $index => $player)
54 54
         {
55 55
             $player->updateScore($score[$player->id]);
@@ -62,190 +62,322 @@ function sortForMatchMaking()
62 62
         if($this->roundNumber == 0)
63 63
         {
64 64
             $this->players = $this->sortForFirstRound($this->players);
65  
-        } else
  65
+        } 
  66
+        else
66 67
         {
  68
+            $players = $this->players;
67 69
             //order the players by their current ranking in draft
68  
-            $this->players = $this->sortByRanking($this->players);
  70
+            $players = $this->sortByRanking($players);
  71
+            
  72
+            //if there's an odd number of people, find out who needs the bye
  73
+            if(count($players) % 2 == 1)
  74
+            {
  75
+                for($i = count($players) - 1; $i >= 0; $i--)
  76
+                {
  77
+                    if($players[$i]->byeCount == 0)
  78
+                    {
  79
+                        $mrBye = $players[$i];
  80
+                        $mrBye->byeCount++;
  81
+                        unset($players[$i]);
  82
+                        $players = array_values($players); //be sure to reindex!
  83
+                        break;
  84
+                    }
  85
+                }
  86
+            }
  87
+            
69 88
             //now resort them taking oponents played into consideration
70  
-            $this->players = $this->sortForRound($this->players);
  89
+            $pairingOptions = array();
  90
+            $this->findPairingOptions($players, array(), $pairingOptions);
  91
+
  92
+            $shortestDistancePairings = $this->findShortest($pairingOptions);
  93
+            
  94
+            $matchmakingList = array();
  95
+            foreach($shortestDistancePairings as $pair)
  96
+            {
  97
+                array_push($pair->player1->opponents, $pair->player2->id);
  98
+                array_push($pair->player2->opponents, $pair->player1->id);
  99
+                
  100
+                array_push($matchmakingList, $pair->player1);
  101
+                array_push($matchmakingList, $pair->player2);
  102
+                
  103
+            }
  104
+            if(isset($mrBye))
  105
+            {
  106
+                array_push($matchmakingList, $mrBye);
  107
+            }
  108
+            
  109
+            $this->players = $matchmakingList;    
71 110
         }
72 111
         $this->roundNumber++;
73 112
     }
  113
+    
  114
+    function calculateDistance($pairs)
  115
+    {
  116
+        
  117
+        $sum = 0;
  118
+        foreach($pairs as $pair)
  119
+        {
  120
+            $sum += $pair->distance;
  121
+        }
  122
+        
  123
+        return $sum;
  124
+    }
74 125
 
75  
-    function sortForRound($players)
  126
+    function findShortest($pairingSets)
76 127
     {
77  
-        $toBeChecked = $players;
78  
-        $ret = array();
  128
+        $shortest = $pairingSets[0];
  129
+        $shortestDistance = $this->calculateDistance($shortest);
  130
+        $isFirst = true;
  131
+        foreach($pairingSets as $index => $pairings)
  132
+        {
  133
+            if($isFirst)
  134
+            {
  135
+                $isFirst = false;
  136
+                continue;
  137
+            }
  138
+            
  139
+            $tempShortest = $this->calculateDistance($pairings);
  140
+            if($tempShortest < $shortestDistance)
  141
+            {
  142
+                $shortestDistance = $tempShortest;
  143
+                $shortest = $pairings;
  144
+            }
  145
+        }
  146
+        
  147
+        return $shortest;
  148
+    }
79 149
 
80  
-        //if there's an odd number, find the lowest ranked person 
81  
-        //that has not had a bye and set them as the one to get it
82  
-        if(count($toBeChecked) % 2 == 1)
  150
+        function findPairingOptions($toBeChecked, $pairings, &$pairingOptions)
83 151
         {
84  
-            for($i = count($toBeChecked)-1; $i >= 0; $i--)
  152
+            //check to see if who just got paired together is invalid
  153
+            //only do this if there are actually pairings
  154
+            if(count($pairings) != 0)
85 155
             {
86  
-                if($toBeChecked[$i]->byeCount == 0)
  156
+                if(!$pairings[count($pairings) - 1]->isValid())
87 157
                 {
88  
-                    $mrBye = $toBeChecked[$i];
89  
-                    unset($toBeChecked[$i]);
90  
-                    $toBeChecked = array_values($toBeChecked); //be sure to reindex!
91  
-                    break;
  158
+                    return;
92 159
                 }
93 160
             }
  161
+
  162
+            //Yay! we found a valid combination of pairings
  163
+            if(count($toBeChecked) == 0)
  164
+            {
  165
+                array_push($pairingOptions, $pairings);
  166
+            }
  167
+
  168
+            $distance = 1; //the index of the person to try and match up
  169
+            while($distance < count($toBeChecked))
  170
+            {
  171
+                //the pairing to try
  172
+                $tempPair = new Pair($toBeChecked[0], $toBeChecked[$distance]);
  173
+                $nextToBePairted = $pairings;
  174
+                array_push($nextToBePairted, $tempPair);
  175
+
  176
+                //set up the array minus the two we just paired up
  177
+                $nextToBeChecked = $toBeChecked;
  178
+                unset($nextToBeChecked[0]);
  179
+                unset($nextToBeChecked[$distance]);
  180
+
  181
+                //down the rabbit hole we go
  182
+                $this->findPairingOptions(array_values($nextToBeChecked), $nextToBePairted, $pairingOptions);
  183
+
  184
+                //keep trying more combinations
  185
+                $distance++;
  186
+            }
94 187
         }
95  
-        
96  
-        while(count($toBeChecked) > 0)
  188
+
  189
+        function sortForRound($players)
97 190
         {
98  
-            $highestPlayer = $toBeChecked[0];
99  
-            $highestIndex = 0;
100  
-            $isFirst = true;
101  
-            foreach($toBeChecked as $index => $player)
  191
+            $toBeChecked = $players;
  192
+            $ret = array();
  193
+
  194
+            //if there's an odd number, find the lowest ranked person 
  195
+            //that has not had a bye and set them as the one to get it
  196
+            if(count($toBeChecked) % 2 == 1)
102 197
             {
103  
-                if($isFirst)
  198
+                for($i = count($toBeChecked) - 1; $i >= 0; $i--)
104 199
                 {
105  
-                    $isFirst = false;
106  
-                    continue;
  200
+                    if($toBeChecked[$i]->byeCount == 0)
  201
+                    {
  202
+                        $mrBye = $toBeChecked[$i];
  203
+                        unset($toBeChecked[$i]);
  204
+                        $toBeChecked = array_values($toBeChecked); //be sure to reindex!
  205
+                        break;
  206
+                    }
107 207
                 }
108  
-                
109  
-                if(!$highestPlayer->hasPlayed($player))
  208
+            }
  209
+
  210
+            while(count($toBeChecked) > 0)
  211
+            {
  212
+                $highestPlayer = $toBeChecked[0];
  213
+                $highestIndex = 0;
  214
+                $isFirst = true;
  215
+                foreach($toBeChecked as $index => $player)
110 216
                 {
111  
-                    //update oponents list of the two paired players
112  
-                    array_push($highestPlayer->opponents, $player->id);
113  
-                    array_push($player->opponents, $highestPlayer->id);
114  
-                    
115  
-                    array_push($ret, $highestPlayer);
116  
-                    array_push($ret, $player);
117  
-                    
118  
-                    unset($toBeChecked[0]);
119  
-                    unset($toBeChecked[$index]);
120  
-                    
121  
-                    $toBeChecked = array_values($toBeChecked);
122  
-                    break;
  217
+                    if($isFirst)
  218
+                    {
  219
+                        $isFirst = false;
  220
+                        continue;
  221
+                    }
  222
+
  223
+                    if(!$highestPlayer->hasPlayed($player))
  224
+                    {
  225
+                        //update oponents list of the two paired players
  226
+                        array_push($highestPlayer->opponents, $player->id);
  227
+                        array_push($player->opponents, $highestPlayer->id);
  228
+
  229
+                        array_push($ret, $highestPlayer);
  230
+                        array_push($ret, $player);
  231
+
  232
+                        unset($toBeChecked[0]);
  233
+                        unset($toBeChecked[$index]);
  234
+
  235
+                        $toBeChecked = array_values($toBeChecked);
  236
+                        break;
  237
+                    }
123 238
                 }
124 239
             }
125  
-        }
126  
-        
127  
-        if(isset($mrBye))
128  
-        {
129  
-            array_push($ret, $mrBye);
130  
-        }
131  
-        
132  
-        return $ret;
133  
-    }
134 240
 
135  
-    function sortForFirstRound($players)
136  
-    {
137  
-        $toBeChecked = $players;
138  
-        $ret = array();
  241
+            if(isset($mrBye))
  242
+            {
  243
+                array_push($ret, $mrBye);
  244
+            }
139 245
 
140  
-        //checking to see if there's an odd number of people
141  
-        if(count($toBeChecked) % 2 == 1)
142  
-        {
143  
-            //pick a number between 0 and one less than the total number of people
144  
-            //this numbe is the index of the person who gets the bye
145  
-            $rand = rand(0, count($toBeChecked) - 1);
146  
-            $mrBye = $toBeChecked[$rand];
147  
-            unset($toBeChecked[$rand]);
148  
-            $toBeChecked = array_values($toBeChecked); //be sure to reindex!
  246
+            return $ret;
149 247
         }
150 248
 
151  
-        while(count($toBeChecked) > 0)
  249
+        function sortForFirstRound($players)
152 250
         {
153  
-            //calculate the distatnce to the opponent
154  
-            $halfOfArray = count($toBeChecked) / 2;
  251
+            $toBeChecked = $players;
  252
+            $ret = array();
155 253
 
156  
-            //update opponents list of the two players that are getting paired
157  
-            array_push($toBeChecked[0]->opponents, $toBeChecked[$halfOfArray]->id);
158  
-            array_push($toBeChecked[$halfOfArray]->opponents, $toBeChecked[0]->id);
159  
-            
160  
-            //push the two people on to the return list.
161  
-            //By being next to each other that means they are playing
162  
-            array_push($ret, $toBeChecked[0]);
163  
-            array_push($ret, $toBeChecked[$halfOfArray]);
  254
+            //checking to see if there's an odd number of people
  255
+            if(count($toBeChecked) % 2 == 1)
  256
+            {
  257
+                //pick a number between 0 and one less than the total number of people
  258
+                //this numbe is the index of the person who gets the bye
  259
+                $rand = rand(0, count($toBeChecked) - 1);
  260
+                $mrBye = $toBeChecked[$rand];
  261
+                $mrBye->byeCount++;
  262
+                unset($toBeChecked[$rand]);
  263
+                $toBeChecked = array_values($toBeChecked); //be sure to reindex!
  264
+            }
  265
+
  266
+            while(count($toBeChecked) > 0)
  267
+            {
  268
+                //calculate the distatnce to the opponent
  269
+                $halfOfArray = count($toBeChecked) / 2;
164 270
 
165  
-            //remove both of those pople from the first list
166  
-            unset($toBeChecked[0]);
167  
-            unset($toBeChecked[$halfOfArray]);
  271
+                //update opponents list of the two players that are getting paired
  272
+                array_push($toBeChecked[0]->opponents, $toBeChecked[$halfOfArray]->id);
  273
+                array_push($toBeChecked[$halfOfArray]->opponents, $toBeChecked[0]->id);
168 274
 
169  
-            //reindex the array
170  
-            $toBeChecked = array_values($toBeChecked);
171  
-        }
  275
+                //push the two people on to the return list.
  276
+                //By being next to each other that means they are playing
  277
+                array_push($ret, $toBeChecked[0]);
  278
+                array_push($ret, $toBeChecked[$halfOfArray]);
172 279
 
173  
-        //last but not least, add the guy who got the bye (if there was one)
174  
-        if(isset($mrBye))
175  
-        {
176  
-            array_push($ret, $mrBye);
177  
-        }
  280
+                //remove both of those pople from the first list
  281
+                unset($toBeChecked[0]);
  282
+                unset($toBeChecked[$halfOfArray]);
178 283
 
179  
-        return $ret;
180  
-    }
  284
+                //reindex the array
  285
+                $toBeChecked = array_values($toBeChecked);
  286
+            }
181 287
 
182  
-    function sortByRanking($players)
183  
-    {
184  
-        $toBeChecked = $players;
185  
-        $ret = array();
  288
+            //last but not least, add the guy who got the bye (if there was one)
  289
+            if(isset($mrBye))
  290
+            {
  291
+                array_push($ret, $mrBye);
  292
+            }
186 293
 
  294
+            return $ret;
  295
+        }
187 296
 
188  
-        while(count($toBeChecked) > 0)
  297
+        function sortByRanking($players)
189 298
         {
190  
-            $highestPlayer = $toBeChecked[0];
191  
-            $highestIndex = 0;
192  
-            $isFirst = true;
193  
-            foreach($toBeChecked as $index => $player)
  299
+            $toBeChecked = $players;
  300
+            $ret = array();
  301
+
  302
+
  303
+            while(count($toBeChecked) > 0)
194 304
             {
195  
-                if($isFirst)
  305
+                $highestPlayer = $toBeChecked[0];
  306
+                $highestIndex = 0;
  307
+                $isFirst = true;
  308
+                foreach($toBeChecked as $index => $player)
196 309
                 {
197  
-                    $isFirst = false;
198  
-                    continue;
199  
-                }
  310
+                    if($isFirst)
  311
+                    {
  312
+                        $isFirst = false;
  313
+                        continue;
  314
+                    }
200 315
 
201  
-                if($player->isHigherThan($highestPlayer))
202  
-                {
203  
-                    $highestPlayer = $player;
204  
-                    $highestIndex = $index;
  316
+                    if($player->isHigherThan($highestPlayer))
  317
+                    {
  318
+                        $highestPlayer = $player;
  319
+                        $highestIndex = $index;
  320
+                    }
205 321
                 }
  322
+
  323
+                //add the highest ranked player to the back of the return list
  324
+                array_push($ret, $highestPlayer);
  325
+                //remove the highest ranked player from the list of things that still need to be checked
  326
+                unset($toBeChecked[$highestIndex]);
  327
+                //reindex the array
  328
+                $toBeChecked = array_values($toBeChecked);
206 329
             }
  330
+            return $ret;
  331
+        }
  332
+
  333
+        //deletes the current draft players and throws these in.
  334
+        //the state is the start of round 2
  335
+        function generateTestPlayers()
  336
+        {
  337
+            $players = array();
  338
+
  339
+            $this->addPlayer("Ted");
  340
+            $this->addPlayer("Frank");
  341
+            $this->addPlayer("Bill");
  342
+            $this->addPlayer("Charlie");
  343
+            $this->addPlayer("Wilson");
  344
+
  345
+            $this->players[0]->matchPoints = 3;
  346
+            $this->players[1]->matchPoints = 0;
  347
+            $this->players[2]->matchPoints = 3;
  348
+            $this->players[3]->matchPoints = 0;
  349
+            $this->players[4]->matchPoints = 3;
  350
+
  351
+            array_push($this->players[0]->opponents, $this->players[1]->id);
  352
+            array_push($this->players[1]->opponents, $this->players[0]->id);
207 353
 
208  
-            //add the highest ranked player to the back of the return list
209  
-            array_push($ret, $highestPlayer);
210  
-            //remove the highest ranked player from the list of things that still need to be checked
211  
-            unset($toBeChecked[$highestIndex]);
212  
-            //reindex the array
213  
-            $toBeChecked = array_values($toBeChecked);
  354
+            array_push($this->players[2]->opponents, $this->players[3]->id);
  355
+            array_push($this->players[3]->opponents, $this->players[2]->id);
  356
+
  357
+            $this->players[4]->byeCount = 1;
214 358
         }
215  
-        return $ret;
  359
+
216 360
     }
217  
-    
218  
-    
219  
-    //deletes the current draft players and throws these in.
220  
-    //the state is the start of round 2
221  
-    function generateTestPlayers()
  361
+
  362
+    class Pair
222 363
     {
223  
-        $players = array();
224  
-        
225  
-        $this->addPlayer("Ted");
226  
-        $this->addPlayer("Frank");
227  
-        $this->addPlayer("Bill");
228  
-        $this->addPlayer("Charlie");
229  
-        $this->addPlayer("Wilson");
230  
-        
231  
-        $this->players[0]->matchPoints = 3;
232  
-        $this->players[1]->matchPoints = 0;
233  
-        $this->players[2]->matchPoints = 3;
234  
-        $this->players[3]->matchPoints = 0;
235  
-        $this->players[4]->matchPoints = 3;
236  
-        
237  
-        array_push($this->players[0]->opponents, $this->players[1]->id);
238  
-        array_push($this->players[1]->opponents, $this->players[0]->id);
239  
-        
240  
-        array_push($this->players[2]->opponents, $this->players[3]->id);
241  
-        array_push($this->players[3]->opponents, $this->players[2]->id);
242  
-        
243  
-        $this->players[4]->byeCount = 1;
244  
-        
245  
-        
246  
- 
247  
-    }
248 364
 
249  
-}
  365
+        var $player1;
  366
+        var $player2;
  367
+        var $distance;
  368
+
  369
+        function __construct($player1, $player2)
  370
+        {
  371
+            $this->player1 = $player1;
  372
+            $this->player2 = $player2;
  373
+            $this->distance = abs($player1->matchPoints - $player2->matchPoints);
  374
+        }
  375
+
  376
+        function isValid()
  377
+        {
  378
+            return!$this->player1->hasPlayed($this->player2);
  379
+        }
  380
+
  381
+    }
250 382
 
251 383
 ?>

0 notes on commit 8ddded4

Please sign in to comment.
Something went wrong with that request. Please try again.