mirror of
https://github.com/JeroenED/libpairtwo.git
synced 2024-11-22 06:26:57 +01:00
Merge branch 'task/more-tiebreaks' into develop
This commit is contained in:
commit
f5b0fd024d
17
src/Constants.php
Normal file
17
src/Constants.php
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
|
||||||
|
namespace JeroenED\Libpairtwo;
|
||||||
|
|
||||||
|
use JeroenED\Libpairtwo\Enums\Color;
|
||||||
|
use JeroenED\Libpairtwo\Enums\Result;
|
||||||
|
|
||||||
|
class Constants
|
||||||
|
{
|
||||||
|
const Won = [ Result::won, Result::wonforfait, Result::wonbye, Result::wonadjourned ];
|
||||||
|
const Draw = [ Result::draw, Result::drawadjourned];
|
||||||
|
const Lost = [ Result::absent, Result::bye, Result::lost, Result::adjourned ];
|
||||||
|
const NotPlayed = [ Result::bye, Result::wonbye, Result::absent ];
|
||||||
|
const Black = [ Color::black ];
|
||||||
|
const White = [ Color::white ];
|
||||||
|
}
|
@ -96,4 +96,57 @@ class Player extends PlayerModel
|
|||||||
$this->setIds($currentIds);
|
$this->setIds($currentIds);
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public function getNoOfWins()
|
||||||
|
{
|
||||||
|
$wins = 0;
|
||||||
|
foreach ($this->getPairings() as $pairing) {
|
||||||
|
if (array_search($pairing->getResult(), Constants::Won) !== false) {
|
||||||
|
$wins++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $wins;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return float
|
||||||
|
*/
|
||||||
|
public function getPoints(): float
|
||||||
|
{
|
||||||
|
$points = 0;
|
||||||
|
foreach ($this->getPairings() as $pairing) {
|
||||||
|
if (array_search($pairing->getResult(), Constants::Won) !== false) {
|
||||||
|
$points = $points + 1;
|
||||||
|
} elseif (array_search($pairing->getResult(), Constants::Draw) !== false) {
|
||||||
|
$points = $points + 0.5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $points;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public function getPerformance(): int
|
||||||
|
{
|
||||||
|
$total = 0;
|
||||||
|
$opponents = 0;
|
||||||
|
foreach ($this->getPairings() as $pairing) {
|
||||||
|
if (array_search($pairing->getResult(), Constants::Notplayed)) {
|
||||||
|
if (array_search(self::Won, $pairing->getResult())) {
|
||||||
|
$total += $pairing->getOpponent()->getElo('home') + 400;
|
||||||
|
} elseif (array_search(self::Lost, $pairing->getResult())) {
|
||||||
|
$total += $pairing->getOpponent()->getElo('home') - 400;
|
||||||
|
} elseif (array_search(self::Draw, $pairing->getResult())) {
|
||||||
|
$total += $pairing->getOpponent()->getElo('home');
|
||||||
|
}
|
||||||
|
$opponents++;
|
||||||
|
}
|
||||||
|
return round($total / $opponents);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,13 +9,6 @@ use JeroenED\Libpairtwo\Enums\Result;
|
|||||||
|
|
||||||
abstract class Tiebreaks extends Tournament
|
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 Player $player
|
* @param Player $player
|
||||||
@ -43,15 +36,7 @@ abstract class Tiebreaks extends Tournament
|
|||||||
*/
|
*/
|
||||||
protected function calculatePoints(Player $player): ?float
|
protected function calculatePoints(Player $player): ?float
|
||||||
{
|
{
|
||||||
$points = 0;
|
return $player->getPoints();
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -63,7 +48,7 @@ abstract class Tiebreaks extends Tournament
|
|||||||
{
|
{
|
||||||
$totalwins = 0;
|
$totalwins = 0;
|
||||||
foreach ($player->getPairings() as $pairing) {
|
foreach ($player->getPairings() as $pairing) {
|
||||||
if (array_search($pairing->getResult(), self::Won) !== false) {
|
if (array_search($pairing->getResult(), Constants::Won) !== false) {
|
||||||
$totalwins++;
|
$totalwins++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -79,7 +64,7 @@ abstract class Tiebreaks extends Tournament
|
|||||||
{
|
{
|
||||||
$totalwins = 0;
|
$totalwins = 0;
|
||||||
foreach ($player->getPairings() as $pairing) {
|
foreach ($player->getPairings() as $pairing) {
|
||||||
if (array_search($pairing->getColor(), self::Black) !== false) {
|
if (array_search($pairing->getColor(), Constants::Black) !== false) {
|
||||||
$totalwins++;
|
$totalwins++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -94,7 +79,7 @@ abstract class Tiebreaks extends Tournament
|
|||||||
{
|
{
|
||||||
$totalwins = 0;
|
$totalwins = 0;
|
||||||
foreach ($player->getPairings() as $pairing) {
|
foreach ($player->getPairings() as $pairing) {
|
||||||
if (array_search($pairing->getColor(), self::Black) !== false && array_search($pairing->getResult(), Self::Won) !== false) {
|
if (array_search($pairing->getColor(), Constants::Black) !== false && array_search($pairing->getResult(), Constants::Won) !== false) {
|
||||||
$totalwins++;
|
$totalwins++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -123,9 +108,9 @@ abstract class Tiebreaks extends Tournament
|
|||||||
$totalmatches = 0;
|
$totalmatches = 0;
|
||||||
foreach ($player->getPairings() as $pairing) {
|
foreach ($player->getPairings() as $pairing) {
|
||||||
if (array_search($pairing->getOpponent(), $interestingplayers) !== false) {
|
if (array_search($pairing->getOpponent(), $interestingplayers) !== false) {
|
||||||
if (array_search($pairing->getResult(), self::Won) !== false) {
|
if (array_search($pairing->getResult(), Constants::Won) !== false) {
|
||||||
$points = $points + 1;
|
$points = $points + 1;
|
||||||
} elseif (array_search($pairing->getResult(), self::Draw) !== false) {
|
} elseif (array_search($pairing->getResult(), Constants::Draw) !== false) {
|
||||||
$points = $points + 0.5;
|
$points = $points + 0.5;
|
||||||
}
|
}
|
||||||
$totalmatches++;
|
$totalmatches++;
|
||||||
@ -137,18 +122,20 @@ abstract class Tiebreaks extends Tournament
|
|||||||
return $points;
|
return $points;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Player $player
|
* @param Player $player
|
||||||
|
* @param int $cut
|
||||||
* @return float
|
* @return float
|
||||||
*/
|
*/
|
||||||
protected function calculateAverageRating(Player $player, int $cut = 0)
|
protected function calculateAverageRating(Player $player, int $cut = 0): ?float
|
||||||
{
|
{
|
||||||
$pairings = $player->getPairings();
|
$pairings = $player->getPairings();
|
||||||
$totalrating = 0;
|
$totalrating = 0;
|
||||||
$totalopponents = 0;
|
$totalopponents = 0;
|
||||||
$allratings = [];
|
$allratings = [];
|
||||||
foreach ($pairings as $pairing) {
|
foreach ($pairings as $pairing) {
|
||||||
if (array_search($pairing->getResult(), self::NotPlayed) === false) {
|
if (array_search($pairing->getResult(), Constants::NotPlayed) === false) {
|
||||||
$toadd = $pairing->getOpponent()->getElos()['home'];
|
$toadd = $pairing->getOpponent()->getElos()['home'];
|
||||||
if ($toadd != 0) {
|
if ($toadd != 0) {
|
||||||
$allratings[] = $toadd;
|
$allratings[] = $toadd;
|
||||||
@ -159,4 +146,135 @@ abstract class Tiebreaks extends Tournament
|
|||||||
$allratings = array_slice($allratings, $cut);
|
$allratings = array_slice($allratings, $cut);
|
||||||
return round(array_sum($allratings) / count($allratings));
|
return round(array_sum($allratings) / count($allratings));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Player $player
|
||||||
|
* @param int $cut
|
||||||
|
* @return float|null
|
||||||
|
*/
|
||||||
|
protected function calculateAveragePerformance(Player $player, int $cut = 0): ?float
|
||||||
|
{
|
||||||
|
$pairings = $player->getPairings();
|
||||||
|
$allratings = [];
|
||||||
|
foreach ($pairings as $pairing) {
|
||||||
|
if (array_search($pairing->getResult(), Constants::NotPlayed) === false) {
|
||||||
|
$toadd = $pairing->getOpponent()->getPerformance();
|
||||||
|
if ($toadd != 0) {
|
||||||
|
$allratings[] = $toadd;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sort($allratings);
|
||||||
|
$allratings = array_slice($allratings, $cut);
|
||||||
|
return round(array_sum($allratings) / count($allratings));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Player $player
|
||||||
|
* @param int $cut
|
||||||
|
* @return float|null
|
||||||
|
*/
|
||||||
|
protected function calculateKoya(Player $player, int $cut = 50): ?float
|
||||||
|
{
|
||||||
|
$tiebreak = 0;
|
||||||
|
foreach ($player->getPairings() as $plkey => $plpairing) {
|
||||||
|
if (($plpairing->getOpponent()->getNoOfWins() / count($plpairing->getOpponent()->getPairings()) * 100) >= $cut) {
|
||||||
|
$tiebreak += $plpairing->getOpponent()->getNoOfWins();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $tiebreak;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Player $player
|
||||||
|
* @param int $cutlowest
|
||||||
|
* @param int $cuthighest
|
||||||
|
* @return float|null
|
||||||
|
*/
|
||||||
|
protected function calculateBuchholz(Player $player, int $cutlowest = 0, int $cuthighest = 0): ?float
|
||||||
|
{
|
||||||
|
$tiebreak = 0;
|
||||||
|
$intpairings = $player->getPairings();
|
||||||
|
|
||||||
|
usort($intpairings, function ($a, $b) {
|
||||||
|
if ($b->getOpponent()->getElo('home') == $a->getOpponent()->getElo('home')) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return ($b->getOpponent()->getElo('home') > $a->getOpponent()->getElo('home')) ? 1 : -1;
|
||||||
|
});
|
||||||
|
|
||||||
|
array_splice($intpairings, $cutlowest);
|
||||||
|
array_splice($intpairings, 0 - $cuthighest);
|
||||||
|
|
||||||
|
foreach ($intpairings as $intkey => $intpairing) {
|
||||||
|
$tiebreak += $intpairing->getOpponent()->getPoints();
|
||||||
|
}
|
||||||
|
return $tiebreak;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Player $player
|
||||||
|
* @return float|null
|
||||||
|
*/
|
||||||
|
protected function calculateSonneborn(Player $player): ?float
|
||||||
|
{
|
||||||
|
$tiebreak = 0;
|
||||||
|
foreach ($player->getPairings() as $key => $pairing) {
|
||||||
|
if (array_search($pairing->getResult(), Constants::Won) !== false) {
|
||||||
|
$tiebreak += $pairing->getOpponent()->getPoints();
|
||||||
|
} elseif (array_search($pairing->getResult(), Constants::draw) !== false) {
|
||||||
|
$tiebreak += $pairing->getOpponent()->getPoints() / 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $tiebreak;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Player $player
|
||||||
|
* @return float|null
|
||||||
|
*/
|
||||||
|
protected function calculateKashdan(Player $player): ?float
|
||||||
|
{
|
||||||
|
$tiebreak = 0;
|
||||||
|
foreach ($player->getPairings() as $pairing) {
|
||||||
|
$toadd = 0;
|
||||||
|
if (array_search($pairing->getResult(), Constants::Won) !== false) {
|
||||||
|
$toadd = 3;
|
||||||
|
} elseif (array_search($pairing->getResult(), Constants::Draw) !== false) {
|
||||||
|
$toadd = 2;
|
||||||
|
} elseif (array_search($pairing->getResult(), Constants::Lost) !== false) {
|
||||||
|
$toadd = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (array_search(Constants::NotPlayed, $pairing->getResult()) !== false) {
|
||||||
|
$toadd = 0;
|
||||||
|
}
|
||||||
|
$tiebreak += $toadd;
|
||||||
|
}
|
||||||
|
return $tiebreak;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Player $player
|
||||||
|
* @return float|null
|
||||||
|
*/
|
||||||
|
protected function calculateCumulative(Player $player): ?float
|
||||||
|
{
|
||||||
|
$tiebreak = 0;
|
||||||
|
foreach ($player->getPairings() as $pairing) {
|
||||||
|
$toadd = 0;
|
||||||
|
if (array_search($pairing->getResult(), Constants::Won) !== false) {
|
||||||
|
$toadd = 1;
|
||||||
|
} elseif (array_search($pairing->getResult(), Constants::Draw) !== false) {
|
||||||
|
$toadd = 0.5;
|
||||||
|
}
|
||||||
|
$tiebreak += $tiebreak + $toadd;
|
||||||
|
}
|
||||||
|
return $tiebreak;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -296,6 +296,30 @@ class Tournament extends Tiebreaks
|
|||||||
case Tiebreak::AroCut:
|
case Tiebreak::AroCut:
|
||||||
return $this->calculateAverageRating($player, 1);
|
return $this->calculateAverageRating($player, 1);
|
||||||
break;
|
break;
|
||||||
|
case Tiebreak::Koya:
|
||||||
|
return $this->calculateKoya($player);
|
||||||
|
break;
|
||||||
|
case Tiebreak::Buchholz:
|
||||||
|
return $this->calculateBuchholz($player);
|
||||||
|
break;
|
||||||
|
case Tiebreak::BuchholzCut:
|
||||||
|
return $this->calculateBuchholz($player, 1);
|
||||||
|
break;
|
||||||
|
case Tiebreak::BuchholzMed:
|
||||||
|
return $this->calculateBuchholz($player, 1, 1);
|
||||||
|
break;
|
||||||
|
case Tiebreak::Sonneborn:
|
||||||
|
return $this->calculateSonneborn($player);
|
||||||
|
break;
|
||||||
|
case Tiebreak::Kashdan:
|
||||||
|
return $this->calculateKashdan($player);
|
||||||
|
break;
|
||||||
|
case Tiebreak::Cumulative:
|
||||||
|
return $this->calculateCumulative($player);
|
||||||
|
break;
|
||||||
|
case Tiebreak::Performance:
|
||||||
|
return $this->calculateAveragePerformance($player);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user