Мне нужна твоя помощь.Сейчас я занимаюсь разработкой приложения, которое будет следить за лигой 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));
}
Пожалуйста, помогите: -)