Skip to content

Commit

Permalink
Now calculates the new rating instead of the rating change
Browse files Browse the repository at this point in the history
  • Loading branch information
lindelius committed Sep 1, 2018
1 parent 1bbbd78 commit 448392d
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 63 deletions.
33 changes: 13 additions & 20 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,21 +8,23 @@ PHP implementation of the [FIDE Rating System](https://www.fide.com/fide/handboo

## Installation

In order to install this library, issue the following command from your project's root folder:
In order to install this library, issue the following Composer command from your project's root folder:

```
composer require "lindelius/php-fide=^0.2"
composer require "lindelius/php-fide=^0.3"
```

## Usage

First of all, implement the `Lindelius\FIDE\Contestant` interface in your ladder participant model (the object holding rating information about a given contestant in a given ladder or tournament)
First of all, implement the `Lindelius\FIDE\Contestant` interface in your ladder participant model (the object holding rating information about a given contestant in a given ladder or tournament).

```php
use Lindelius\FIDE\Contestant;

/**
* Class Team
*/
class Team implements \Lindelius\FIDE\Contestant
class Team implements Contestant
{
/**
* @return int
Expand Down Expand Up @@ -50,26 +52,17 @@ class Team implements \Lindelius\FIDE\Contestant
}
```

then use the static `Lindelius\FIDE\RatingSystem::calculateRatingChange()` method to calculate the contestants rating changes after each match.
Then, use the static `Lindelius\FIDE\RatingSystem::calculateNewRating()` method to calculate the new ratings for the contestants after each match.

```php
use Lindelius\FIDE\RatingSystem;

/**
* Calculate rating changes.
*
* `$outcome` should be the outcome for `$contestant` and must be either of the
* constants defined in the `Lindelius\FIDE\RatingSystem` class.
* Calculate the new rating for both contestants.
*
* @var Team $contestant
* @var Team $opponent
*/
$contestantRatingChange = RatingSystem::calculateRatingChange($contestant, $opponent, $outcome);
$opponentRatingChange = RatingSystem::calculateRatingChange($opponent, $contestant, -$outcome);

/**
* Set the contestants new ratings by adding the calculated rating changes to
* their current ratings.
*/
$contestantNewRating = $contestant->currentRating() + $contestantRatingChange;
$opponentNewRating = $opponent->currentRating() + $opponentRatingChange;

// TODO: Save the new ratings
$contestant->rating = RatingSystem::calculateNewRating($contestant, $opponent, RatingSystem::WON);
$opponent->rating = RatingSystem::calculateNewRating($opponent, $contestant, RatingSystem::LOST);
```
32 changes: 21 additions & 11 deletions src/RatingSystem.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,20 +26,23 @@ class RatingSystem
const LOST = -1;

/**
* Calculates the rating change for a given contestant versus a given
* opponent with a given outcome.
* Calculates the new rating for a given contestant versus a given opponent
* with a given outcome.
*
* @param Contestant $contestant
* @param Contestant $opponent
* @param int $outcome
* @param int|null $k
* @return int
*/
public static function calculateRatingChange(Contestant $contestant, Contestant $opponent, $outcome, $k = null)
public static function calculateNewRating(Contestant $contestant, Contestant $opponent, $outcome, $k = null)
{
$isHigherRated = $contestant->getCurrentRating() >= $opponent->getCurrentRating();
$ratingDifference = static::getRatingDifference($contestant, $opponent);
$scoreProbability = static::getScoreProbability($ratingDifference, $isHigherRated);
$isHigherRated = $contestant->getCurrentRating() >= $opponent->getCurrentRating();

$scoreProbability = static::getScoreProbability(
static::getRatingDifference($contestant, $opponent),
$isHigherRated
);

if (!is_int($k)) {
if ($contestant->getTotalMatchesPlayed() < 30) {
Expand All @@ -59,17 +62,20 @@ public static function calculateRatingChange(Contestant $contestant, Contestant
$score = 0;
}

return (int) round(($score - $scoreProbability) * $k);
$ratingChange = (int) round(($score - $scoreProbability) * $k);

return $contestant->getCurrentRating() + $ratingChange;
}

/**
* Gets the absolute rating difference between given contestants.
* Gets the absolute rating difference between a given contestant and a
* given opponent.
*
* @param Contestant $contestant
* @param Contestant $opponent
* @return int
*/
protected static function getRatingDifference(Contestant $contestant, Contestant $opponent)
private static function getRatingDifference(Contestant $contestant, Contestant $opponent)
{
return min(
abs($contestant->getCurrentRating() - $opponent->getCurrentRating()),
Expand All @@ -84,7 +90,7 @@ protected static function getRatingDifference(Contestant $contestant, Contestant
* @param bool $isHigherRated
* @return float
*/
protected static function getScoreProbability($ratingDifference, $isHigherRated = true)
private static function getScoreProbability($ratingDifference, $isHigherRated)
{
$ratingDifferences = [
0 => 50,
Expand Down Expand Up @@ -150,6 +156,10 @@ protected static function getScoreProbability($ratingDifference, $isHigherRated
}
}

return (float) ($isHigherRated ? $finalScoreProbability : 1 - $finalScoreProbability);
if (!$isHigherRated) {
$finalScoreProbability = 1 - $finalScoreProbability;
}

return (float) $finalScoreProbability;
}
}
64 changes: 32 additions & 32 deletions tests/RatingSystemTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,19 +38,19 @@ public function equallySkilledContestantProvider()
new Team(1000, 1000, 35),
new Team(1000, 1000, 35),
RatingSystem::DRAW,
0,
1000,
],
'equally skilled lost' => [
new Team(1000, 1000, 35),
new Team(1000, 1000, 35),
RatingSystem::LOST,
-10,
990,
],
'equally skilled won' => [
new Team(1000, 1000, 35),
new Team(1000, 1000, 35),
RatingSystem::WON,
10,
1010,
],

/**
Expand All @@ -60,19 +60,19 @@ public function equallySkilledContestantProvider()
new Team(1000, 1000, 10),
new Team(1000, 1000, 10),
RatingSystem::DRAW,
0,
1000,
],
'equally skilled rookie lost' => [
new Team(1000, 1000, 10),
new Team(1000, 1000, 10),
RatingSystem::LOST,
-20,
980,
],
'equally skilled rookie won' => [
new Team(1000, 1000, 10),
new Team(1000, 1000, 10),
RatingSystem::WON,
20,
1020,
],

/**
Expand All @@ -83,19 +83,19 @@ public function equallySkilledContestantProvider()
new Team(2200, 2400, 100),
new Team(2200, 2200, 75),
RatingSystem::DRAW,
0,
2200,
],
'equally skilled elite lost' => [
new Team(2200, 2400, 100),
new Team(2200, 2200, 75),
RatingSystem::LOST,
-5,
2195,
],
'equally skilled elite won' => [
new Team(2200, 2400, 100),
new Team(2200, 2200, 75),
RatingSystem::WON,
5,
2205,
],

];
Expand All @@ -114,19 +114,19 @@ public function higherSkilledContestantProvider()
new Team(2000, 2000, 75),
new Team(1000, 1000, 35),
RatingSystem::DRAW,
-8,
1992,
],
'higher skilled lost' => [
new Team(2000, 2000, 75),
new Team(1000, 1000, 35),
RatingSystem::LOST,
-18,
1982,
],
'higher skilled won' => [
new Team(2000, 2000, 75),
new Team(1000, 1000, 35),
RatingSystem::WON,
2,
2002,
],

/**
Expand All @@ -136,19 +136,19 @@ public function higherSkilledContestantProvider()
new Team(1100, 1100, 20),
new Team(1000, 1000, 10),
RatingSystem::DRAW,
-6,
1094,
],
'higher skilled rookie lost' => [
new Team(1100, 1100, 20),
new Team(1000, 1000, 10),
RatingSystem::LOST,
-26,
1074,
],
'higher skilled rookie won' => [
new Team(1100, 1100, 20),
new Team(1000, 1000, 10),
RatingSystem::WON,
14,
1114,
],

/**
Expand All @@ -159,19 +159,19 @@ public function higherSkilledContestantProvider()
new Team(2400, 2400, 100),
new Team(2200, 2200, 75),
RatingSystem::DRAW,
-3,
2397,
],
'higher skilled elite lost' => [
new Team(2400, 2400, 100),
new Team(2200, 2200, 75),
RatingSystem::LOST,
-8,
2392,
],
'higher skilled elite won' => [
new Team(2400, 2400, 100),
new Team(2200, 2200, 75),
RatingSystem::WON,
2,
2402,
],

];
Expand All @@ -190,19 +190,19 @@ public function lowerSkilledContestantProvider()
new Team(1000, 1000, 35),
new Team(2000, 2000, 75),
RatingSystem::DRAW,
8,
1008,
],
'lower skilled lost' => [
new Team(1000, 1000, 35),
new Team(2000, 2000, 75),
RatingSystem::LOST,
-2,
998,
],
'lower skilled won' => [
new Team(1000, 1000, 35),
new Team(2000, 2000, 75),
RatingSystem::WON,
18,
1018,
],

/**
Expand All @@ -212,19 +212,19 @@ public function lowerSkilledContestantProvider()
new Team(1000, 1000, 10),
new Team(2000, 2000, 75),
RatingSystem::DRAW,
17,
1017,
],
'lower skilled rookie lost' => [
new Team(1000, 1000, 10),
new Team(2000, 2000, 75),
RatingSystem::LOST,
-3,
997,
],
'lower skilled rookie won' => [
new Team(1000, 1000, 10),
new Team(2000, 2000, 75),
RatingSystem::WON,
37,
1037,
],

/**
Expand All @@ -235,39 +235,39 @@ public function lowerSkilledContestantProvider()
new Team(2200, 2400, 100),
new Team(2400, 2400, 100),
RatingSystem::DRAW,
3,
2203,
],
'lower skilled elite lost' => [
new Team(2200, 2400, 100),
new Team(2400, 2400, 100),
RatingSystem::LOST,
-2,
2198,
],
'lower skilled elite won' => [
new Team(2200, 2400, 100),
new Team(2400, 2400, 100),
RatingSystem::WON,
8,
2208,
],

];
}

/**
* Test the rating change calculation for a given contestant versus a given
* Test the new rating calculation for a given contestant versus a given
* opponent with a given outcome.
*
* @param Contestant $contestant
* @param Contestant $opponent
* @param int $outcome
* @param int $expectedRatingChange
* @param int $expectedNewRating
* @dataProvider contestantProvider
*/
public function testVariousContestantOutcomes(Contestant $contestant, Contestant $opponent, $outcome, $expectedRatingChange)
public function testVariousContestantOutcomes(Contestant $contestant, Contestant $opponent, $outcome, $expectedNewRating)
{
$this->assertEquals(
$expectedRatingChange,
RatingSystem::calculateRatingChange($contestant, $opponent, $outcome)
$expectedNewRating,
RatingSystem::calculateNewRating($contestant, $opponent, $outcome)
);
}
}

0 comments on commit 448392d

Please sign in to comment.