diff --git a/src/Readers/Pairtwo6.php b/src/Readers/Pairtwo6.php index 5a1ad96..558949d 100644 --- a/src/Readers/Pairtwo6.php +++ b/src/Readers/Pairtwo6.php @@ -306,7 +306,7 @@ class Pairtwo6 extends Pairtwo6Model implements ReaderInterface $offset += $length; $length = 4; - $ids['fide'] = $this->readData('Int', substr($swscontents, $offset, $length)); + $ids['world'] = $this->readData('Int', substr($swscontents, $offset, $length)); $offset += $length; $length = 4; @@ -314,7 +314,7 @@ class Pairtwo6 extends Pairtwo6Model implements ReaderInterface $offset += $length; $length = 4; - $elos['kbsb'] = $this->readData('Int', substr($swscontents, $offset, $length)); + $elos['home'] = $this->readData('Int', substr($swscontents, $offset, $length)); $offset += $length; $length = 4; @@ -322,7 +322,7 @@ class Pairtwo6 extends Pairtwo6Model implements ReaderInterface $offset += $length; $length = 4; - $ids['kbsb'] = $this->readData('Int', substr($swscontents, $offset, $length)); + $ids['home'] = $this->readData('Int', substr($swscontents, $offset, $length)); $offset += $length; $length = 4; @@ -346,7 +346,7 @@ class Pairtwo6 extends Pairtwo6Model implements ReaderInterface $offset += $length; $length = 4; - $elos['fide'] = $this->readData('Int', substr($swscontents, $offset, $length)); + $elos['world'] = $this->readData('Int', substr($swscontents, $offset, $length)); $offset += $length; $length = 1; diff --git a/src/Tiebreaks.php b/src/Tiebreaks.php index 0c88693..1670315 100644 --- a/src/Tiebreaks.php +++ b/src/Tiebreaks.php @@ -9,105 +9,152 @@ use JeroenED\Libpairtwo\Enums\Result; abstract class Tiebreaks extends Tournament { + private const Won = [ Result::won, Result::wonforfait, Result::wonbye, Result::wonadjourned ]; + private const Draw = [ Result::draw, Result::drawadjourned]; + private const Lost = [ Result::absent, Result::bye, Result::lost, Result::adjourned ]; + private const NotPlayed = [ Result::bye, Result::wonbye, Result::absent ]; + private const Black = [ Color::black ]; + private const White = [ Color::white ]; + /** - * @param int $key * @param Player $player - * @return float + * @return float|null */ - protected function calculateKeizer(int $key, Player $player): float + protected function calculateKeizer(Player $player): ?float { - $currentTiebreaks = $player->getTiebreaks(); - $currentTiebreaks[$key] = $player->getBinaryData('ScoreAmerican'); - $player->setTiebreaks($currentTiebreaks); - return $currentTiebreaks[$key]; - } - - /** - * @param int $key - * @param Player $player - * @return float - */ - protected function calculateAmerican(int $key, Player $player): float - { - $currentTiebreaks = $player->getTiebreaks(); - $currentTiebreaks[$key] = $player->getBinaryData('ScoreAmerican'); - $player->setTiebreaks($currentTiebreaks); - return $currentTiebreaks[$key]; + return $player->getBinaryData('ScoreAmerican'); } /** - * @param int $key * @param Player $player - * @return float + * @return float|null */ - protected function calculatePoints(int $key, Player $player): float + protected function calculateAmerican(Player $player): ?float { - $currentTiebreaks = $player->getTiebreaks(); - $currentTiebreaks[$key] = $player->getBinaryData('Points'); - $player->setTiebreaks($currentTiebreaks); - return $currentTiebreaks[$key]; + return $player->getBinaryData('ScoreAmerican'); } /** - * @param int $key * @param Player $player - * @return float + * @return float|null */ - protected function calculateBaumbach(int $key, Player $player): float + protected function calculatePoints(Player $player): ?float + { + $points = 0; + foreach ($player->getPairings() as $pairing) { + if (array_search($pairing->getResult(), self::Won) !== false) { + $points = $points + 1; + } elseif (array_search($pairing->getResult(), self::Draw) !== false) { + $points = $points + 0.5; + } + } + return $points; + } + + + /** + * @param Player $player + * @return float|null + */ + protected function calculateBaumbach(Player $player): ?float { - $wonArray = [Result::won, Result::wonadjourned, Result::wonbye, Result::wonforfait]; $totalwins = 0; foreach ($player->getPairings() as $pairing) { - if (array_search($pairing->getResult(), $wonArray) !== false) { + if (array_search($pairing->getResult(), self::Won) !== false) { $totalwins++; } } - $currentTiebreaks = $player->getTiebreaks(); - $currentTiebreaks[$key] = $totalwins; - $player->setTiebreaks($currentTiebreaks); - return $currentTiebreaks[$key]; + return $totalwins; + } + + + /** + * @param Player $player + * @return float|null + */ + protected function calculateBlackPlayed(Player $player): ?float + { + $totalwins = 0; + foreach ($player->getPairings() as $pairing) { + if (array_search($pairing->getColor(), self::Black) !== false) { + $totalwins++; + } + } + return $totalwins; } /** - * @param int $key * @param Player $player - * @return float + * @return float|null */ - protected function calculateBlackPlayed(int $key, Player $player): float + protected function calculateBlackWin(Player $player): ?float { - $blackArray = [Color::black]; $totalwins = 0; foreach ($player->getPairings() as $pairing) { - if (array_search($pairing->getColor(), $blackArray) !== false) { + if (array_search($pairing->getColor(), self::Black) !== false && array_search($pairing->getResult(), Self::Won) !== false) { $totalwins++; } } - $currentTiebreaks = $player->getTiebreaks(); - $currentTiebreaks[$key] = $totalwins; - $player->setTiebreaks($currentTiebreaks); - return $currentTiebreaks[$key]; + return $totalwins; } + + /** + * @param Player $player + * @param array $opponents * @param int $key + * @return float|null + */ + protected function calculateMutualResult(Player $player, array $opponents, int $key): ?float + { + $interestingplayers = $opponents; + if ($key != 0) { + $interestingplayers = []; + foreach ($opponents as $opponent) { + if (($opponent->getTiebreaks()[$key - 1] == $player->getTiebreaks()[$key - 1]) && ($player != $opponent)) { + $interestingplayers[] = $opponent; + } + } + } + $points = 0; + $totalmatches = 0; + foreach ($player->getPairings() as $pairing) { + if (array_search($pairing->getOpponent(), $interestingplayers) !== false) { + if (array_search($pairing->getResult(), self::Won) !== false) { + $points = $points + 1; + } elseif (array_search($pairing->getResult(), self::Draw) !== false) { + $points = $points + 0.5; + } + $totalmatches++; + } + } + if ($totalmatches != count($interestingplayers)) { + $points = null; + } + return $points; + } + + /** * @param Player $player * @return float */ - protected function calculateBlackWin(int $key, Player $player): float + protected function calculateAverageRating(Player $player) { - $wonArray = [Result::won, Result::wonadjourned, Result::wonbye, Result::wonforfait]; - $blackArray = [Color::black]; - $totalwins = 0; - foreach ($player->getPairings() as $pairing) { - if (array_search($pairing->getColor(), $blackArray) !== false && array_search($pairing->getResult(), $wonArray) !== false) { - $totalwins++; + $pairings = $player->getPairings(); + $totalrating = 0; + $totalopponents = 0; + foreach ($pairings as $pairing) { + if (array_search($pairing->getResult(), self::NotPlayed) === false) { + $toadd = $pairing->getOpponent()->getElos()['home']; + if ($toadd != 0) { + $totalrating += $toadd; + $totalopponents++; + } } } - $currentTiebreaks = $player->getTiebreaks(); - $currentTiebreaks[$key] = $totalwins; - $player->setTiebreaks($currentTiebreaks); - return $currentTiebreaks[$key]; + return round($totalrating / $totalopponents); } } diff --git a/src/Tournament.php b/src/Tournament.php index b0d696d..333c36a 100644 --- a/src/Tournament.php +++ b/src/Tournament.php @@ -207,54 +207,115 @@ class Tournament extends Tiebreaks public function getRanking() { $players = $this->getPlayers(); - - usort($players, array($this, "SortTiebreak")); - - return $players; + foreach ($this->getTiebreaks() as $tbkey=>$tiebreak) { + foreach ($players as $pkey => $player) { + $break = $this->calculateTiebreak($tiebreak, $player, $tbkey); + $tiebreaks = $player->getTiebreaks(); + $tiebreaks[$tbkey] = $break; + $player->setTiebreaks($tiebreaks); + $this->updatePlayer($pkey, $player); + } + } + $sortedplayers[0] = $players; + foreach ($this->getTiebreaks() as $tbkey=>$tiebreak) { + $newgroupkey = 0; + $tosortplayers = $sortedplayers; + $sortedplayers = []; + foreach ($tosortplayers as $groupkey=>$sortedplayerselem) { + usort($tosortplayers[$groupkey], $this->SortTiebreak($tbkey)); + foreach ($tosortplayers[$groupkey] as $playerkey => $player) { + if (!is_null($player->getTiebreaks()[$tbkey])) { + if ($playerkey != 0) { + $newgroupkey++; + if ($player->getTiebreaks()[$tbkey] == $tosortplayers[$groupkey][$playerkey - 1]->getTiebreaks()[$tbkey]) { + $newgroupkey--; + } + } + } + $sortedplayers[$newgroupkey][] = $player; + } + $newgroupkey++; + } + } + $finalarray = []; + foreach ($sortedplayers as $sort1) { + foreach ($sort1 as $player) { + $finalarray[] = $player; + } + } + return $finalarray; } /** * @param Player $a * @param Player $b - * @return int + * @return \Closure */ - private function sortTiebreak(Player $a, Player $b) + + private function sortTiebreak(int $key) { - $result = 0; - foreach ($this->getTiebreaks() as $key=>$tiebreak) { - $result = $this->CalculateTiebreak($key, $b, $a) - $this->CalculateTiebreak($key, $a, $b); - if ($result != 0) { - return $result; + return function (Player $a, Player $b) use ($key) { + if (($b->getTiebreaks()[$key] == $a->getTiebreaks()[$key]) || ($a->getTiebreaks()[$key] === false) || ($b->getTiebreaks()[$key] === false)) { + return 0; } - } + return ($b->getTiebreaks()[$key] > $a->getTiebreaks()[$key]) ? +1 : -1; + }; } /** - * @return float + * @return float|bool */ - private function calculateTiebreak(int $key, Player $player, Player $opponent): float + private function calculateTiebreak(Tiebreak $tiebreak, Player $player, int $tbkey = 0): ?float { - $tiebreak = $this->getTiebreaks()[$key]; switch ($tiebreak) { case Tiebreak::Keizer: - return $this->calculateKeizer($key, $player); + return $this->calculateKeizer($player); break; case Tiebreak::American: - return $this->calculateAmerican($key, $player); + return $this->calculateAmerican($player); break; case Tiebreak::Points: - return $this->calculatePoints($key, $player); + return $this->calculatePoints($player); break; case Tiebreak::Baumbach: - return $this->calculateBaumbach($key, $player); + return $this->calculateBaumbach($player); break; case Tiebreak::BlackPlayed: - return $this->calculateBlackPlayed($key, $player); + return $this->calculateBlackPlayed($player); break; case Tiebreak::BlackWin: - return $this->calculateBlackWin($key, $player); + return $this->calculateBlackWin($player); break; + case Tiebreak::Between: + return $this->calculateMutualResult($player, $this->getPlayers(), $tbkey); + break; + case Tiebreak::Aro: + return $this->calculateAverageRating($player); + break; + default: + return null; } } + + /** + * Return the average rating for tournament + * + * @return int + */ + public function getAverageElo(): int + { + $totalrating = 0; + $players = 0; + foreach ($this->getPlayers() as $player) { + $toadd = $player->getElos()['home']; + if ($toadd == 0) { + $toadd = $this->getNonRatedElo(); + } + + $totalrating += $toadd; + $players++; + } + return intdiv($totalrating, $players); + } } diff --git a/tests/ReadSws_test.php b/tests/ReadSws_test.php index aff1dde..628ae18 100644 --- a/tests/ReadSws_test.php +++ b/tests/ReadSws_test.php @@ -46,21 +46,21 @@ echo "Place: " . $sws->getTournament()->getOrganiserPlace() . PHP_EOL; echo "Unrated-Elo: " . $sws->getTournament()->getNonRatedElo() . PHP_EOL; echo "Federation: " . $sws->getTournament()->getFederation() . PHP_EOL; echo "Organiser: " . $sws->getTournament()->getOrganiserClubNo() . PHP_EOL; -echo "Fide Elo P1: " . $sws->getTournament()->getPlayerById(0)->getElos()['fide'] . PHP_EOL; -echo "Fide Elo P2: " . $sws->getTournament()->getPlayerById(1)->getElos()['fide'] . PHP_EOL; -echo "Fide Elo P3: " . $sws->getTournament()->getPlayerById(2)->getElos()['fide'] . PHP_EOL; -echo "KBSB Elo P1: " . $sws->getTournament()->getPlayerById(0)->getElos()['kbsb'] . PHP_EOL; -echo "KBSB Elo P2: " . $sws->getTournament()->getPlayerById(1)->getElos()['kbsb'] . PHP_EOL; -echo "KBSB Elo P3: " . $sws->getTournament()->getPlayerById(2)->getElos()['kbsb'] . PHP_EOL; +echo "Fide Elo P1: " . $sws->getTournament()->getPlayerById(0)->getElos()['world'] . PHP_EOL; +echo "Fide Elo P2: " . $sws->getTournament()->getPlayerById(1)->getElos()['world'] . PHP_EOL; +echo "Fide Elo P3: " . $sws->getTournament()->getPlayerById(2)->getElos()['world'] . PHP_EOL; +echo "KBSB Elo P1: " . $sws->getTournament()->getPlayerById(0)->getElos()['home'] . PHP_EOL; +echo "KBSB Elo P2: " . $sws->getTournament()->getPlayerById(1)->getElos()['home'] . PHP_EOL; +echo "KBSB Elo P3: " . $sws->getTournament()->getPlayerById(2)->getElos()['home'] . PHP_EOL; echo "Name P1: " . $sws->getTournament()->getPlayerById(0)->getName() . PHP_EOL; echo "Name P2: " . $sws->getTournament()->getPlayerById(1)->getName() . PHP_EOL; echo "Name P3: " . $sws->getTournament()->getPlayerById(2)->getName() . PHP_EOL; echo "Gender P1: " . $sws->getTournament()->getPlayerById(0)->getGender()->getKey() . PHP_EOL; echo "Gender P2: " . $sws->getTournament()->getPlayerById(1)->getGender()->getKey() . PHP_EOL; echo "Gender P3: " . $sws->getTournament()->getPlayerById(2)->getGender()->getKey() . PHP_EOL; -echo "Absent P1: " . $sws->getTournament()->getPlayerById(0)->getBinaryData("absent") . PHP_EOL; -echo "Absent P2: " . $sws->getTournament()->getPlayerById(1)->getBinaryData("absent") . PHP_EOL; -echo "Absent P3: " . $sws->getTournament()->getPlayerById(2)->getBinaryData("absent") . PHP_EOL; +echo "Absent P1: " . $sws->getTournament()->getPlayerById(0)->getBinaryData("Absent") . PHP_EOL; +echo "Absent P2: " . $sws->getTournament()->getPlayerById(1)->getBinaryData("Absent") . PHP_EOL; +echo "Absent P3: " . $sws->getTournament()->getPlayerById(2)->getBinaryData("Absent") . PHP_EOL; echo "Date Round 1: " . $sws->getTournament()->getRoundByNo(0)->getDate()->format('d/m/Y') . PHP_EOL; echo "Date Round 2: " . $sws->getTournament()->getRoundByNo(1)->getDate()->format('d/m/Y') . PHP_EOL; echo "Date Round 3: " . $sws->getTournament()->getRoundByNo(2)->getDate()->format('d/m/Y') . PHP_EOL; @@ -73,6 +73,7 @@ echo "Player Pairing 3: " . $sws->getTournament()->getPairings()[2]->getPlayer() echo "Tiebreak 1: " . $sws->getTournament()->getTiebreaks()[0]->getValue() . PHP_EOL; echo "Tiebreak 2: " . $sws->getTournament()->getTiebreaks()[1]->getValue() . PHP_EOL; echo "Tiebreak 3: " . $sws->getTournament()->getTiebreaks()[2]->getValue() . PHP_EOL; +echo "Average Elo: " . $sws->getTournament()->getAverageElo() . PHP_EOL; foreach ($sws->getTournament()->getRanking() as $player) { - echo $player->getName() . ' ' . implode(' ', $player->getTiebreaks()) . PHP_EOL; + echo $player->getName() . '(' . $player->getElos()['home'] . ') ' . implode(' ', $player->getTiebreaks()) . PHP_EOL; }