libpairtwo/src/Player.php

418 lines
10 KiB
PHP
Raw Normal View History

2019-02-01 15:53:39 +01:00
<?php
2020-08-02 21:51:59 +02:00
2019-02-01 15:53:39 +01:00
/**
* Class Player
*
* Class for a player of the tournament
*
2020-08-02 21:51:59 +02:00
* @author Jeroen De Meerleer <schaak@jeroened.be>
* @category Main
* @package Libpairtwo
* @copyright Copyright (c) 2018-2019 Jeroen De Meerleer <schaak@jeroened.be>
2019-02-01 15:53:39 +01:00
*/
2019-03-20 17:33:09 +01:00
namespace JeroenED\Libpairtwo;
2019-02-01 15:53:39 +01:00
2020-11-22 17:13:13 +01:00
use DateTime;
use JeroenED\Libpairtwo\Enums\Gender;
2019-09-28 10:33:59 +02:00
use JeroenED\Libpairtwo\Enums\Title;
2019-02-01 15:53:39 +01:00
2019-05-01 16:04:37 +02:00
/**
* Class Player
*
* Class for a player of the tournament
*
2020-08-02 21:51:59 +02:00
* @author Jeroen De Meerleer <schaak@jeroened.be>
* @category Main
* @package Libpairtwo
* @copyright Copyright (c) 2018-2019 Jeroen De Meerleer <schaak@jeroened.be>
2019-05-01 16:04:37 +02:00
*/
class Player
2019-02-01 15:53:39 +01:00
{
2019-11-17 01:20:15 +01:00
/**
2020-11-22 17:13:13 +01:00
* Binary data that was read out of the pairing file
2019-11-17 01:20:15 +01:00
*
2020-11-22 17:13:13 +01:00
* @var bool|DateTime|int|string[]
2019-11-17 01:20:15 +01:00
*/
2020-11-22 17:13:13 +01:00
private $BinaryData;
2019-11-17 01:20:15 +01:00
/**
2020-11-22 17:13:13 +01:00
* The category the player belongs to
2019-11-17 01:20:15 +01:00
*
2020-11-22 17:13:13 +01:00
* @var string
2019-11-17 01:20:15 +01:00
*/
2020-11-22 17:13:13 +01:00
public $Category;
2019-11-17 01:20:15 +01:00
/**
* Birthday of the player
*
* @var DateTime
*/
public $DateOfBirth;
2019-11-17 01:20:15 +01:00
/**
2020-11-22 17:13:13 +01:00
* The Elos for the player. Possible keys are, but not limited to nation and fide
2019-11-17 01:20:15 +01:00
*
2020-11-22 17:13:13 +01:00
* @var int[]
2019-11-17 01:20:15 +01:00
*/
2020-11-22 17:13:13 +01:00
public $Elos;
2019-11-17 01:20:15 +01:00
/**
2020-11-22 17:13:13 +01:00
* The gender of the player. Possible values contain Male, Female and Neutral
2019-11-17 01:20:15 +01:00
*
2020-11-22 17:13:13 +01:00
* @var Gender
2019-11-17 01:20:15 +01:00
*/
2020-11-22 17:13:13 +01:00
public $Gender;
2019-11-17 01:20:15 +01:00
/**
2020-11-22 17:13:13 +01:00
* The player ids for the player. Possible keys are, but not limited to nation and fide
2019-11-17 01:20:15 +01:00
*
2020-11-22 17:13:13 +01:00
* @var int[]
2019-11-17 01:20:15 +01:00
*/
2020-11-22 17:13:13 +01:00
public $Ids;
// TODO: Implement categories
2019-11-17 01:20:15 +01:00
/**
2020-11-22 17:13:13 +01:00
* Name of the player
2019-11-17 01:20:15 +01:00
*
2020-11-22 17:13:13 +01:00
* @var string
2019-11-17 01:20:15 +01:00
*/
2020-11-22 17:13:13 +01:00
public $Name;
2019-11-17 01:20:15 +01:00
/**
2020-11-22 17:13:13 +01:00
* The nation the player belongs to. Be noted this does not actually mean this is his main nationality. A player
* can be signed USCF but may be Italian
2019-11-17 01:20:15 +01:00
*
2020-11-22 17:13:13 +01:00
* @var string
2019-11-17 01:20:15 +01:00
*/
2020-11-22 17:13:13 +01:00
public $Nation;
2019-11-17 01:20:15 +01:00
/**
* The pairings of the player
*
* @var Pairing[]
*/
public $Pairings = [];
2019-11-17 01:20:15 +01:00
/**
2020-11-22 17:13:13 +01:00
* Tiebreak points of the player. These values are calculated when Tournament->Ranking is called
2019-11-17 01:20:15 +01:00
*
2020-11-22 17:13:13 +01:00
* @var float[]
2019-11-17 01:20:15 +01:00
*/
2020-11-22 17:13:13 +01:00
public $Tiebreaks = [];
2019-11-17 01:20:15 +01:00
2020-11-22 17:13:13 +01:00
/**
* The title of the player. Possible values can be GM, IM, IA, etc.
*
* @var Title
*/
public $Title;
2019-04-20 16:55:39 +02:00
/**
2020-11-22 17:13:13 +01:00
* Returns the performance rating of the player
2019-04-20 16:55:39 +02:00
*
2020-11-22 17:13:13 +01:00
* WARNING: Calculation currently incorrect. Uses the rule of 400 as temporary solution
*
* @param $type
* @param $unratedElo
*
* @return float
2019-04-20 16:55:39 +02:00
*/
2020-11-22 17:13:13 +01:00
public function Performance(string $type, int $unratedElo): float
2019-04-20 16:55:39 +02:00
{
2020-11-22 17:13:13 +01:00
$total = 0;
$opponents = 0;
foreach ($this->Pairings as $pairing) {
if (array_search($pairing->Result, Constants::NOTPLAYED) === false) {
$opponentElo = $pairing->Opponent->getElo($type);
$opponentElo = $opponentElo != 0 ? $opponentElo : $unratedElo;
if (array_search($pairing->Result, Constants::WON) !== false) {
$total += $opponentElo + 400;
} elseif (array_search($pairing->Result, Constants::LOST) !== false) {
$total += $opponentElo - 400;
} elseif (array_search($pairing->Result, Constants::DRAW) !== false) {
$total += $opponentElo;
}
$opponents++;
}
}
return round($total / $opponents);
2019-04-20 16:55:39 +02:00
}
2019-05-01 16:04:37 +02:00
/**
* Returns an array of Player objects where name matches $search
*
2020-11-22 17:13:13 +01:00
* @param string $search
* @param Tournament $tournament
*
2019-05-01 16:04:37 +02:00
* @return Player[]
*/
2019-11-16 14:46:01 +01:00
public static function PlayersByName(string $search, Tournament $tournament): array
2019-05-01 16:04:37 +02:00
{
2020-08-02 21:51:59 +02:00
/**
2020-11-22 17:13:13 +01:00
* @var Player[]
*/
$players = $tournament->Players;
2019-05-01 16:04:37 +02:00
2020-08-02 21:51:59 +02:00
/**
2020-11-22 17:13:13 +01:00
* @var Player[]
*/
2019-05-01 16:04:37 +02:00
$return = [];
foreach ($players as $player) {
if (fnmatch($search, $player->Name)) {
2019-05-01 16:04:37 +02:00
$return[] = $player;
}
}
return $return;
}
2019-05-29 18:09:19 +02:00
/**
2020-11-22 17:13:13 +01:00
* Magic method to read out several fields. If field was not found it is being searched in the binary data fields
2020-08-02 21:51:59 +02:00
*
2020-11-22 17:13:13 +01:00
* @param string $key
2019-06-20 14:53:26 +02:00
*
2020-11-22 17:13:13 +01:00
* @return bool|DateTime|int|string|null
2019-05-29 18:09:19 +02:00
*/
2020-11-22 17:13:13 +01:00
public function __get(string $key)
2019-05-29 18:09:19 +02:00
{
2020-11-22 17:13:13 +01:00
if ($key == 'PlayedGames') {
return $this->playedGames();
} elseif ($key == 'NoOfWins') {
return $this->noOfWins();
} elseif ($key == 'Opponents') {
return $this->opponents();
} elseif (isset($this->BinaryData[ $key ])) {
return $this->BinaryData[ $key ];
}
2019-05-29 18:09:19 +02:00
2020-11-22 17:13:13 +01:00
return null;
2019-05-29 18:09:19 +02:00
}
/**
2020-11-22 17:13:13 +01:00
* Sets binary data that is read out the pairing file but is not needed immediately
2019-06-20 14:53:26 +02:00
*
2020-11-22 17:13:13 +01:00
* @param string $key
* @param bool|int|DateTime|string $value
2019-05-29 18:09:19 +02:00
*/
2020-11-22 17:13:13 +01:00
public function __set(string $key, $value): void
2019-05-29 18:09:19 +02:00
{
2020-11-22 17:13:13 +01:00
$this->BinaryData[ $key ] = $value;
2019-05-29 18:09:19 +02:00
}
2019-05-30 21:01:30 +02:00
/**
2020-11-22 17:13:13 +01:00
* Adds a pairing to the tournament
2019-06-20 14:53:26 +02:00
*
2020-11-22 17:13:13 +01:00
* @param Pairing $pairing
2019-05-30 21:01:30 +02:00
*/
2020-11-22 17:13:13 +01:00
public function addPairing(Pairing $pairing): void
2019-05-30 21:01:30 +02:00
{
2020-11-22 17:13:13 +01:00
$newArray = $this->Pairings;
$newArray[] = $pairing;
$this->Pairings = $newArray;
2019-05-30 21:01:30 +02:00
}
/**
* Returns the points of the player after round $round
2019-06-20 14:53:26 +02:00
*
* 1 Point is awarded for winning
* 0.5 points are awarded for draw
* 0 points are awarded for loss
2019-06-20 14:53:26 +02:00
*
2020-11-22 17:13:13 +01:00
* @param int $round
*
2019-05-30 21:33:27 +02:00
* @return float
2019-05-30 21:01:30 +02:00
*/
public function calculatePoints(int $round = -1): float
2019-05-30 21:01:30 +02:00
{
$points = 0;
2020-08-02 21:51:59 +02:00
foreach ($this->Pairings as $key => $pairing) {
2019-12-22 18:15:25 +01:00
if ($key < $round || $round == -1) {
2020-08-02 21:51:59 +02:00
if (array_search($pairing->Result, Constants::WON) !== false) {
$points = $points + 1;
2020-08-02 21:51:59 +02:00
} elseif (array_search($pairing->Result, Constants::DRAW) !== false) {
$points = $points + 0.5;
}
2019-05-30 21:01:30 +02:00
}
}
2019-05-30 21:10:31 +02:00
return $points;
}
2020-11-22 17:13:13 +01:00
/**
* Returns the points of the player that should be used for tiebreaking systems.
*
* 1 Point is awarded for winning
* 0.5 points are awarded for draw
* 0.5 points for not played
*
* @return float
*/
public function calculatePointsForTiebreaks(): float
{
$points = 0;
foreach ($this->Pairings as $pairing) {
2020-08-02 21:51:59 +02:00
if (array_search($pairing->Result, Constants::NOTPLAYED) !== false) {
$points = $points + 0.5;
2020-08-02 21:51:59 +02:00
} elseif (array_search($pairing->Result, Constants::WON) !== false) {
$points = $points + 1;
2020-08-02 21:51:59 +02:00
} elseif (array_search($pairing->Result, Constants::DRAW) !== false) {
$points = $points + 0.5;
}
}
2020-11-22 17:13:13 +01:00
return $points;
}
2020-11-22 17:13:13 +01:00
2019-05-30 21:10:31 +02:00
/**
2020-11-22 17:13:13 +01:00
* Returns the points of a virtual player as described in the Fide Handbook C.02 chapter 13.15.2.
2019-06-20 14:53:26 +02:00
*
2020-11-22 17:13:13 +01:00
* Return the same score for all rounds until $byeround and added with a half point for each subsequent round
*
* @param int $byeround
2019-06-20 14:53:26 +02:00
*
2020-08-02 21:51:59 +02:00
* @return float
2019-05-30 21:10:31 +02:00
*/
2020-11-22 17:13:13 +01:00
public function calculatePointsForVirtualPlayer(int $byeround): float
2019-05-30 21:10:31 +02:00
{
2020-11-22 17:13:13 +01:00
$points = $this->calculatePoints($byeround);
foreach (array_slice($this->Pairings, $byeround + 1) as $key => $pairing) {
$points += 0.5;
2019-05-30 21:10:31 +02:00
}
2019-06-05 13:23:16 +02:00
2020-11-22 17:13:13 +01:00
return $points;
}
2019-06-05 13:23:16 +02:00
/**
2020-11-22 17:13:13 +01:00
* Returns the elo of elotype for the player
*
* @param string $type
2019-06-20 14:53:26 +02:00
*
2019-06-05 13:23:16 +02:00
* @return int
*/
2020-11-22 17:13:13 +01:00
public function getElo(string $type): int
2019-06-05 13:23:16 +02:00
{
2020-11-22 17:13:13 +01:00
return $this->Elos[ $type ];
}
/**
* Returns the identifier of type for the player
*
* Common possible values are Fide or National
*
* @param string $type
*
* @return string
*/
public function getId(string $type): string
{
return $this->Ids[ $type ];
2019-06-05 13:23:16 +02:00
}
2019-12-25 13:43:36 +01:00
/**
* Returns if player has played against all players of the array
*
2020-11-22 17:13:13 +01:00
* @param Player[] $players
*
2019-12-25 13:43:36 +01:00
* @return bool
*/
public function hasPlayedAllPlayersOfArray(array $players): bool
{
$ownkey = array_search($this, $players);
if ($ownkey !== false) {
2020-11-22 17:13:13 +01:00
unset($players[ $ownkey ]);
2019-12-25 13:43:36 +01:00
}
$total = 0;
foreach ($players as $player) {
if (array_search($player, $this->Opponents) !== false) {
$total++;
}
}
return $total == count($players);
}
2020-11-22 17:13:13 +01:00
/**
* Returns the number of won matches for the player
*
* @return int
*/
private function noOfWins(): int
{
$wins = 0;
foreach ($this->Pairings as $pairing) {
if (array_search($pairing->Result, Constants::WON) !== false) {
$wins++;
}
}
return $wins;
}
2019-12-25 13:43:36 +01:00
/**
* Returns all opponents of $this
*
* @return Player[]
*/
2019-12-26 20:33:53 +01:00
private function opponents()
{
2020-11-22 17:13:13 +01:00
$return = [];
2019-12-25 13:43:36 +01:00
foreach ($this->Pairings as $pairing) {
if (!empty($pairing->Opponent)) {
$return[] = $pairing->Opponent;
}
}
2020-11-22 17:13:13 +01:00
2019-12-25 13:43:36 +01:00
return $return;
}
/**
2020-11-22 17:13:13 +01:00
* Returns the number of played games of the player
2019-06-20 14:53:26 +02:00
*
2020-11-22 17:13:13 +01:00
* @return int
*/
2020-11-22 17:13:13 +01:00
private function playedGames(): int
{
2020-11-22 17:13:13 +01:00
$total = 0;
foreach ($this->Pairings as $pairing) {
if (array_search($pairing->Result, Constants::PLAYED) !== false) {
$total++;
}
2019-09-25 14:38:44 +02:00
}
2020-11-22 17:13:13 +01:00
return $total;
}
/**
2020-11-22 17:13:13 +01:00
* Sets the elo of elotype for the player
2019-06-20 14:53:26 +02:00
*
2020-11-22 17:13:13 +01:00
* @param string $type
* @param int $value
*/
2020-11-22 17:13:13 +01:00
public function setElo(string $type, int $value): void
{
$currentElos = $this->Elos;
$currentElos[ $type ] = $value;
$this->Elos = $currentElos;
}
/**
* Sets the identifier of type for the player
*
* Common possible values are Fide or National
*
* @param string $type
* @param string $value
*/
public function setId(string $type, string $value): void
{
2020-11-22 17:13:13 +01:00
$currentIds = $this->Ids;
$currentIds[ $type ] = $value;
$this->Ids = $currentIds;
}
2019-02-11 17:37:30 +01:00
}