алгоритм — генерация циклического перебора PHP создает «дубликаты»

Я реализовал генератор циклического перебора в PHP, чтобы создавать матчи между пользователями в лиге. Это соответствует всем пользователям в лиге и сопоставляет их друг с другом в течение каждой недели игры.

Код выглядит так;

    /**
* 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;

}

Функция generateFixtures передается пользователям лиги, самой лиге и количеству недель.

Проблема в том, что это создает «дубликаты» для каждого прибора, поскольку, по сути, существует представление от каждого пользователя — например;

Gameweek 1

  • Пользователь_1 VS Пользователь_2
  • Пользователь_3 VS Пользователь_4
  • Пользователь_2 VS Пользователь_1
  • Пользователь_4 VS Пользователь_3

Как видите, последние два светильника там разные; но так же!

Мой вопрос заключается в том, является ли это проблемой с циклическим циклом или я мог / должен отфильтровать эти дубликаты, когда вытащил их через контроллер / представление

0

Решение

Это не самое элегантное решение, но в момент ввода данных в базу данных я могу проверить, существует ли уже противоположное тому, что должно быть создано;

            foreach($fixtures as $key => $val) {
if($key != 0) {
//loop through the values to create an entry for each
foreach($val as $opponent) {
//check if the opposite of each entry already exists
if(!LeagueFixture::where('gameweek', $gameweek)
->where('league_id', $league)
->where('user_id', $opponent[0])
->where('opponent_id', $key)
->exists()) {
//if not, we can create the entry as usual
LeagueFixture::firstOrCreate([
'gameweek' => $gameweek,
'league_id' => $league,
'user_id' => $key,
'opponent_id' => $opponent[0],
]);
}
$gameweek = $gameweek+1;
}
}
$gameweek = 1;
}

Сейчас это самое простое решение для меня … хотя данные генерируются в указанном циклическом цикле (и вы могли бы легко утверждать, что это было бы плохой практикой), дублированные данные никогда не попадают в мою базу данных

0

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]