Делаем обрезки для игроков в формате лиги :-) - PullRequest
0 голосов
/ 06 октября 2018

Мне нужна твоя помощь.Сейчас я занимаюсь разработкой приложения, которое будет следить за лигой Warhammer 40k: -)

Я изо всех сил пытаюсь создать паринги для текущего раунда.В целом: будет 12 раундов, где каждый игрок сыграет одну игру против нарисованного противника.Игроки не могут играть дважды против одного и того же противника, если они не сыграли всех других возможных игроков.Более того, если количество игроков нечетное в каждом раунде, то разные игроки приостанавливают текущий раунд (поэтому количество игроков четное).

Итак, у меня есть следующее:

Создать перестановку для всех возможных пар.В таблице SQL parings я храню все возможные пары.Как видите, есть два «вспомогательных» столбца = isUsed, которые я использую, чтобы отслеживать, воспроизводился ли этот анализ, и столбец round_num, который является внешним ключом для столбца раунда (для отслеживания обработок в каждом раунде).Метод ниже довольно простой рекурсивный.

private function drawAllParings($players, $parings = [])

{
  global $parings;

  $playerA = $players->shift();

  foreach ($players as $item) {
    $paring = new Paring;
    $paring->PlayerA_id = $playerA->id;
    $paring->PlayerB_id = $item->id;
    $parings[] = $paring;
  }

  if ($players->count() != 1) {
    $this->drawAllParings($players, $parings);
  }

  return $parings;
}

Создание нового раунда. Что является наиболее важной частью здесь, это присвоение паузе игрока, если количество игроков нечетное.Я назначаю его в столбец pausing_player_id.Я также даю игроку флаг, чтобы он сделал паузу.Если все игроки сделали паузу, я просто перезагружаю столбец players.PlayerPause

public function store(Request $request)
    {
        $lastRound = Round::orderBy('id', 'desc')->first();

        if (!empty($lastRound) && $lastRound->parings->count() == 0) {
          return Redirect::back()->withErrors(['Round could not be created because your previous round has no parings.']);
        }

        $round = new Round;

        //Get number of all players in db
        $playersCount = Player::count();

        if ($playersCount % 2 != 0) {
          $playerToPause = $this->getPausingPlayer();
          $round->pausing_player_id = $playerToPause->id;
          $player = Player::where('id', $round->pausing_player_id)->first();
          $player->PlayerPause = 1;
          $player->save();
        }else{
          $round->pausing_player_id = NULL;
        }

        if (empty($lastRound)) {
          $round->round_num = 1;
        }else{
          $round->round_num = $lastRound->round_num  + 1;
        }

        if ($round->save()) {
          Session::flash('success', 'Round was added');
          return redirect()->route('rounds.index');
        }else{
          return Redirect::back()->withErrors(['Round could not be created. Please contact administrator.']);
        }
    }

public function getPausingPlayer()
    {
      $playerToPause = Player::where('PlayerPause', 0)->first();

      // If there are no players that can pause, reset them.
      if (empty($playerToPause)) {
        $this->resetPause();
        $playerToPause = Player::where('PlayerPause', 0)->first();
      }
      return $playerToPause;
    }

Выбор таблицы из parings таблицы для этого раунда.Имейте в виду, что один игрок не может сыграть дважды в этом раунде и не может сыграть дважды против одного и того же противника, если он не сыграл всех остальных противников.То, чего я достиг до сих пор, это создание 3 раундов, то есть 15 парингов.После этого сценарий не может выбрать более 3 партингов из таблицы parings.Я полагаю, что проблема заключается в приостановке игрока, потому что в каждом раунде у нас есть другой игрок, и он «берет» игрока, который подходит другому игроку, как парирование.Не могли бы вы объяснить мне алгоритм, который должен мне помочь?

Вот мой метод розыгрыша:

public function draw()
    {

      $round = Round::orderby('id', 'desc')->first();

      if (empty($round)) {
        return new ErrorResource(['error' => 'Create Round to make parings']);
      }

      if (Player::all()->isEmpty()) {
        return new ErrorResource(['error' => 'Add Players to make parings']);
      }

      if (Round::all()->isEmpty()) {
        return new ErrorResource(['error' => 'Create Round to make parings']);
      }

      if ($round->parings->count() != 0) {
        return new ErrorResource(['error' => 'You can not generate parings for this round. Create new round']);
      }

      //Get players to play

      if (isset($round->pausing_player_id)) {
        $players = Player::where('id', '!=', $round->pausing_player_id)->get();
      }else{
        $players = Player::all();
      }

      // $parings is output container 
      $parings = [];

      // Select first player
      $playerA = $players->shift();

      // Container for players that has been used in this round
      $usedPlayersId = [];


       // Loop that selects paring from database.
        while ($players->count()) {
        $paring = Paring::where('isUsed', 0)
                        ->where('PlayerA_id', '!=', $round->pausing_player_id)
                        ->where('PlayerB_id', '!=', $round->pausing_player_id)
                        ->whereNotIn('PlayerA_id', $usedPlayersId)
                        ->whereNotIn('PlayerB_id', $usedPlayersId)
                        ->where(function($query) use($playerA) {
                          $query->where('PlayerA_id', $playerA->id)
                                ->orWhere('PlayerB_id', $playerA->id);
                        })
                        ->first();
        $usedPlayersId[] = $playerA->id;
        $playerB = '';
        $players = $players->reject(function($item, $key) use(&$paring, &$usedPlayersId){
          if ($item->id == $paring->PlayerA_id || $item->id == $paring->PlayerB_id) {
            $usedPlayersId[] = $item->id;
            return true;
          }
        });
        $playerA = $players->shift();
        $parings[] = $paring;
      }

      return new ParingCollection(collect($parings));

    }

Пожалуйста, помогите: -)

...