@ ilcavero совершенно верно.
Я реализовал нечто похожее на это. В моем коде предполагается, что разрешающие связи типа «конфронтация» не могут быть запущены, если (а) все игроки не сыграли друг с другом и (б) один игрок не выиграл все матчи или один игрок не проиграл все матчи между связанными командами.
Это утверждение if позволяет избежать таких проблем:
- Алиса победила Боба
- Боб бил Карла
- Карл победил Алису
Алиса должна быть впереди Боба и позади Карла. Боб должен быть впереди Карла и позади Алисы, но Алиса должна быть позади Карла. Это ломает. Это также позволяет избежать наказания или вознаграждения кого-либо за матч, в котором он не играл.
Код разрешает связи, которые выглядят следующим образом:
- Алиса победила Боба
- Алиса победила Карла
- Карл победил Боба
Сначала мы можем удалить Алису, которая победила других игроков, и расположить ее над связанными командами:
- Алиса
- Боб и Карл
Поскольку Боб проиграл Карлу, мы можем снять его с галстука и поместить его в позицию под галстуком (который в этот момент был бы просто Карлом). Разрешение на:
- Алиса
- Карл
- Bob
Я сохраняю ранжирование в такой структуре, как при сортировке ($ this-> sortedTeams):
[
1 => [$id => $team, $id => $team, $id = $team], // 3 teams tied for first position.
4 => [$id => $team], // One team in 4th position.
5 => [$id => $team, $id => $team] // 2 teams tied in 5th position.
]
Вот код в моем классе TeamSorter, который имеет дело с личным сравнением:
private function headToHead() {
foreach ($this->findTies() as $position)
$this->headToHeadThisPosition($position);
ksort($this->sortedTeams);
}
private function headToHeadThisPosition($position) {
// Teams that are tied.
$teams = $this->sortedTeams[$position];
// Every team must play every other team, or head to head doesn't work.
if (!$this->tiedTeamsHaveAllPlayedEachother($teams)) return;
// If we have a winner, it assumes $position, and other(s) assume
// $positon + 1, moving away from first place.
if ($winner_nid = $this->tiedPositionHasWinner($teams))
$position = $this->removeFromTie('winner', $winner_nid, $position);
// If we have a loser, it assumes $position + 1 (moving away from first
// place), other(s) stay at $position.
if ($loser_nid = $this->tiedPositionHasLoser($teams))
$this->removeFromTie('loser', $loser_nid, $position);
// Recursively call this function if we might resolve a tie at $position
// before going on to the next position.
if ($this->recursionNeeded($position))
$this->headToHeadThisPosition($position);
}
private function recursionNeeded($position) {
$teams = $this->sortedTeams[$position];
return
count($this->sortedTeams[$position]) > 1
&&
$this->tiedTeamsHaveAllPlayedEachother($this->sortedTeams[$position])
&&
$this->tiedPositionHasWinner($this->sortedTeams[$position]);
}