2015-05-27 2 views
0

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

Код выглядит следующим образом;

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

  • user_1 VS user_2
  • User_3 VS User_4
  • user_2 VS user_1
  • User_4 VS User_3

Как вы с последние два светильника отличаются друг от друга; но то же самое!

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

+0

создать копию массива, найти пары в этом. Найдя пару, удалите их из копии, затем найдите следующую пару. Продолжайте до исчерпания. –

+0

Спасибо @ Mike'Pomax'Kamermans. Когда вы предлагаете мне это сделать? Во время создания циклического создания или при рендеринге данных для вывода вида? – Alex

+0

лучший способ избежать этого - использовать упорядоченные пары, то есть пары, которые упорядочены, то есть для каждой пары (p1, p2) p1

ответ

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; 
      } 

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