I have implemented a round robin generator in PHP to create fixtures between users in a league. This matches all the users in a league and pits them against each other for each gameweek.
The code looks like this;
/**
* Rotates an array for the round robin algorithm
*/
function round_robin_array($array)
{
// we always keep index 0
$top = array_shift($array);
$last = array_pop($array);
$rotate = [$last];
foreach ($array as $_value) {
$rotate[] = $_value;
}
array_unshift($rotate, $top);
return $rotate;
}
/**
* Runs a round robin to make a schedule.
*/
function round_robin($users, $weeks)
{
$schedule = [];
$count = count($users);
foreach ($users as $_u) {
$schedule[$_u] = array_fill(0, $weeks, []);
}
for ($i=0;$i<$weeks;$i++) {
for ($a=0;$a<($count / 2) + 1;$a++) {
$vs = $users[$a];
$opp = $users[($count - $a) - 1];
$at = rand(0,4);
$pg = [$opp, $at];
$og = [$vs, $at];
$schedule[$vs][$i] = $pg;
$schedule[$opp][$i] = $og;
}
$users = $this->round_robin_array($users);
}
return $schedule;
}
public function generateFixtures($league, $users, $weeks)
{
$array = [];
foreach($users as $user) {
array_push($array, $user['id']);
}
if(count($array) % 2 != 0) {
array_push($array, '0');
}
$fixtures = $this->round_robin($array, $weeks);
$gameweek = 1;
foreach($fixtures as $key => $val) {
if($key != 0) {
foreach($val as $opponent) {
LeagueFixture::firstOrCreate([
'gameweek' => $gameweek,
'league_id' => $league,
'user_id' => $key,
'opponent_id' => $opponent[0],
]);
$gameweek = $gameweek+1;
}
}
$gameweek = 1;
}
return $fixtures;
}
The generateFixtures function is passed the users of the league, the league itself and the number of weeks.
The problem is this creates 'duplicates' for each fixture as there is essentially a view from each user - for example;
Gameweek 1
- User_1 VS User_2
- User_3 VS User_4
- User_2 VS User_1
- User_4 VS User_3
As you can see, the last two fixtures there are different; but the same!
My question is whether this is a problem with the round robin or whether i could/should filter out these duplicates when pulling them through in the controller/view