Compare commits

...

5 Commits

Author SHA1 Message Date
4b3a328726 Additional tests
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-05-15 12:41:34 +00:00
82a5505438 Codestandards 2024-05-15 07:13:01 +00:00
cbf03c5736 Additional tests. 2024-05-15 07:01:15 +00:00
65db7f64ea Teams::concat was unnessecary 2024-05-14 11:12:26 +00:00
5cf6acdfb1 More tests 2024-05-14 09:41:17 +00:00
13 changed files with 253 additions and 62 deletions

@ -31,7 +31,7 @@ class BasicBench
$team2 = new Team($p2, $gameInfo->getDefaultRating());
for ($i = 0; $i < 10; ++$i) {
$teams = Teams::concat($team1, $team2);
$teams = [$team1, $team2];
$calculator = new TwoPlayerTrueSkillCalculator();
@ -62,7 +62,7 @@ class BasicBench
$team2 = new Team($p2, $gameInfo->getDefaultRating());
for ($i = 0; $i < 10; ++$i) {
$teams = Teams::concat($team1, $team2);
$teams = [$team1, $team2];
$calculator = new TwoTeamTrueSkillCalculator();
@ -93,7 +93,7 @@ class BasicBench
$team2 = new Team($p2, $gameInfo->getDefaultRating());
for ($i = 0; $i < 10; ++$i) {
$teams = Teams::concat($team1, $team2);
$teams = [$team1, $team2];
$calculator = new FactorGraphTrueSkillCalculator();
@ -126,7 +126,7 @@ class BasicBench
$team3 = new Team($p3, $gameInfo->getDefaultRating());
for ($i = 0; $i < 10; ++$i) {
$teams = Teams::concat($team1, $team2, $team3);
$teams = [$team1, $team2, $team3];
$calculator = new FactorGraphTrueSkillCalculator();

@ -22,7 +22,7 @@ $team3 = new Team($p3, $gameInfo->getDefaultRating());
for($i = 0; $i < 5; ++$i) {
echo "Iteration: " . $i . PHP_EOL;
$teams = Teams::concat($team1, $team2, $team3);
$teams = [$team1, $team2, $team3];
$calculator = new FactorGraphTrueSkillCalculator();

@ -21,7 +21,7 @@ $team2 = new Team($p2, $gameInfo->getDefaultRating());
for($i = 0; $i < 5; ++$i) {
echo "Iteration: " . $i . PHP_EOL;
$teams = Teams::concat($team1, $team2);
$teams = [$team1, $team2];
$calculator = new TwoPlayerTrueSkillCalculator();

@ -252,7 +252,6 @@ class GaussianDistribution
private static function inverseErrorFunctionCumulativeTo(float $p): float
{
// From page 265 of numerical recipes
if ($p >= 2.0) {
return -100;
}

@ -1,23 +0,0 @@
<?php
declare(strict_types=1);
namespace DNW\Skills;
class Teams
{
/**
* @return Team[]
*/
public static function concat(Team ...$args/*variable arguments*/): array
{
$result = [];
foreach ($args as $currentTeam) {
$localCurrentTeam = $currentTeam;
$result[] = $localCurrentTeam;
}
return $result;
}
}

@ -5,7 +5,7 @@ declare(strict_types=1);
namespace DNW\Skills\Tests;
use DNW\Skills\GameInfo;
use \DNW\Skills\Rating;
use DNW\Skills\Rating;
use PHPUnit\Framework\TestCase;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\UsesClass;

@ -12,24 +12,43 @@ use PHPUnit\Framework\Attributes\CoversClass;
#[CoversClass(Guard::class)]
class GuardTest extends TestCase
{
public function testargumentIsValidIndex(): void
public function testargumentIsValidIndexArgumentAbove(): void
{
$this->expectException(Exception::class);
$this->expectExceptionMessage('dummy is an invalid index');
Guard::argumentIsValidIndex(10, 10, "dummy");
}
public function testargumentIsValidIndex2(): void
public function testargumentIsValidIndexArgumentBelow(): void
{
$this->expectException(Exception::class);
$this->expectExceptionMessage('dummy is an invalid index');
Guard::argumentIsValidIndex(-1, 10, "dummy");
}
public function testargumentInRangeInclusive(): void
public function testargumentIsValidIndexArgumentValid(): void
{
Guard::argumentIsValidIndex(5, 10, "dummy");
$this->expectNotToPerformAssertions();
}
public function testargumentInRangeInclusiveAbove(): void
{
$this->expectException(Exception::class);
$this->expectExceptionMessage('dummy is not in the valid range [0, 100]');
Guard::argumentInRangeInclusive(101, 0, 100, "dummy");
}
public function testargumentInRangeInclusiveBelow(): void
{
$this->expectException(Exception::class);
$this->expectExceptionMessage('dummy is not in the valid range [0, 100]');
Guard::argumentInRangeInclusive(-1, 0, 100, "dummy");
}
public function testargumentInRangeInclusiveValid(): void
{
Guard::argumentInRangeInclusive(50, 0, 100, "dummy");
$this->expectNotToPerformAssertions();
}
}

27
tests/PartialPlayTest.php Normal file

@ -0,0 +1,27 @@
<?php
declare(strict_types=1);
namespace DNW\Skills\Tests;
use DNW\Skills\PartialPlay;
use DNW\Skills\Player;
use DNW\Skills\Guard;
use PHPUnit\Framework\TestCase;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\UsesClass;
#[CoversClass(PartialPlay::class)]
#[UsesClass(Player::class)]
#[UsesClass(Guard::class)]
class PartialPlayTest extends TestCase
{
public function testgetPartialPlayPercentage(): void
{
$p = new Player(1, 0.5);
$this->assertEquals($p->getPartialPlayPercentage(), PartialPlay::getPartialPlayPercentage($p));
$p = new Player(1, 0.000000);
$this->assertNotEquals(0.0, PartialPlay::getPartialPlayPercentage($p));
}
}

@ -10,7 +10,6 @@ use PHPUnit\Framework\TestCase;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\UsesClass;
#[CoversClass(Player::class)]
#[UsesClass(Guard::class)]
class PlayerTest extends TestCase

@ -0,0 +1,47 @@
<?php
declare(strict_types=1);
namespace DNW\Skills\Tests;
use DNW\Skills\RatingContainer;
use DNW\Skills\HashMap;
use DNW\Skills\Player;
use DNW\Skills\Rating;
use DNW\Skills\Guard;
use PHPUnit\Framework\TestCase;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\UsesClass;
#[CoversClass(RatingContainer::class)]
#[UsesClass(Hashmap::class)]
#[UsesClass(Player::class)]
#[UsesClass(Rating::class)]
#[UsesClass(Guard::class)]
class RatingContainerTest extends TestCase
{
public function testRatingContainer(): void
{
$rc = new RatingContainer();
$this->assertEquals([], $rc->getAllPlayers());
$this->assertEquals([], $rc->getAllRatings());
$this->assertEquals(0, $rc->count());
$p1 = new Player(1);
$p2 = new Player(2);
$r1 = new Rating(100, 10);
$r2 = new Rating(200, 20);
$rc->setRating($p1, $r1);
$rc->setRating($p2, $r2);
$this->assertEquals($r1, $rc->getRating($p1));
$this->assertEquals($r2, $rc->getRating($p2));
$this->assertEquals([$p1, $p2], $rc->getAllPlayers());
$this->assertEquals([$r1, $r2], $rc->getAllRatings());
$this->assertEquals(2, $rc->count());
}
}

69
tests/TeamTest.php Normal file

@ -0,0 +1,69 @@
<?php
declare(strict_types=1);
namespace DNW\Skills\Tests;
use DNW\Skills\Team;
use DNW\Skills\RatingContainer;
use DNW\Skills\HashMap;
use DNW\Skills\Player;
use DNW\Skills\Rating;
use DNW\Skills\Guard;
use PHPUnit\Framework\TestCase;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\UsesClass;
#[CoversClass(Team::class)]
#[CoversClass(RatingContainer::class)]
#[UsesClass(Hashmap::class)]
#[UsesClass(Player::class)]
#[UsesClass(Rating::class)]
#[UsesClass(Guard::class)]
class TeamTest extends TestCase
{
public function testTeam(): void
{
$p1 = new Player(1);
$p2 = new Player(2);
$r1 = new Rating(100, 10);
$r2 = new Rating(200, 20);
$rc = new Team($p1, $r1);
$this->assertEquals($r1, $rc->getRating($p1));
$this->assertEquals([$p1], $rc->getAllPlayers());
$this->assertEquals([$r1], $rc->getAllRatings());
$this->assertEquals(1, $rc->count());
$rc->addPlayer($p2, $r2);
$this->assertEquals($r2, $rc->getRating($p2));
$this->assertEquals([$p1, $p2], $rc->getAllPlayers());
$this->assertEquals([$r1, $r2], $rc->getAllRatings());
$this->assertEquals(2, $rc->count());
}
public function testTeamConstructor(): void
{
$p = new Player(0);
$r = new Rating(100, 10);
$rc = new Team(NULL, NULL);
$this->assertEquals(0, $rc->count());
$rc = new Team($p, NULL);
$this->assertEquals(0, $rc->count());
$rc = new Team(NULL, $r);
$this->assertEquals(0, $rc->count());
$rc = new Team($p, $r);
$this->assertEquals($r, $rc->getRating($p));
$this->assertEquals([$p], $rc->getAllPlayers());
$this->assertEquals([$r], $rc->getAllRatings());
$this->assertEquals(1, $rc->count());
}
}

@ -86,7 +86,7 @@ class TrueSkillCalculatorTests
$team1 = new Team($player1, $gameInfo->getDefaultRating());
$team2 = new Team($player2, $gameInfo->getDefaultRating());
$teams = Teams::concat($team1, $team2);
$teams = [$team1, $team2];
$newRatings = $calculator->calculateNewRatings($gameInfo, $teams, [1, 2]);
@ -109,7 +109,7 @@ class TrueSkillCalculatorTests
$team1 = new Team($player1, $gameInfo->getDefaultRating());
$team2 = new Team($player2, $gameInfo->getDefaultRating());
$teams = Teams::concat($team1, $team2);
$teams = [$team1, $team2];
$newRatings = $calculator->calculateNewRatings($gameInfo, $teams, [1, 1]);
@ -132,7 +132,7 @@ class TrueSkillCalculatorTests
$team1 = new Team($player1, new Rating(1301.0007, 42.9232));
$team2 = new Team($player2, new Rating(1188.7560, 42.5570));
$newRatings = $calculator->calculateNewRatings($gameInfo, Teams::concat($team1, $team2), [1, 2]);
$newRatings = $calculator->calculateNewRatings($gameInfo, [$team1, $team2], [1, 2]);
$player1NewRating = $newRatings->getRating($player1);
self::assertRating($testClass, 1304.7820836053318, 42.843513887848658, $player1NewRating);
@ -153,7 +153,7 @@ class TrueSkillCalculatorTests
$team2 = new Team($player2, new Rating(50, 12.5));
$teams = Teams::concat($team1, $team2);
$teams = [$team1, $team2];
$newRatingsWinLose = $calculator->calculateNewRatings($gameInfo, $teams, [1, 1]);
@ -184,7 +184,7 @@ class TrueSkillCalculatorTests
$team2->addPlayer($player2, $gameInfo->getDefaultRating());
$team2->addPlayer($player3, $gameInfo->getDefaultRating());
$teams = Teams::concat($team1, $team2);
$teams = [$team1, $team2];
$newRatingsWinLose = $calculator->calculateNewRatings($gameInfo, $teams, [1, 2]);
// Winners
@ -219,7 +219,7 @@ class TrueSkillCalculatorTests
$team2->addPlayer($player3, $gameInfo->getDefaultRating());
$team2->addPlayer($player4, $gameInfo->getDefaultRating());
$teams = Teams::concat($team1, $team2);
$teams = [$team1, $team2];
$newRatingsWinLose = $calculator->calculateNewRatings($gameInfo, $teams, [1, 2]);
// Winners
@ -249,7 +249,7 @@ class TrueSkillCalculatorTests
$team2->addPlayer($player2, new Rating(20, 7));
$team2->addPlayer($player3, new Rating(25, 8));
$teams = Teams::concat($team1, $team2);
$teams = [$team1, $team2];
$newRatingsWinLose = $calculator->calculateNewRatings($gameInfo, $teams, [1, 2]);
// Winners
@ -280,7 +280,7 @@ class TrueSkillCalculatorTests
$team2->addPlayer($player3, $gameInfo->getDefaultRating());
$team2->addPlayer($player4, $gameInfo->getDefaultRating());
$teams = Teams::concat($team1, $team2);
$teams = [$team1, $team2];
$newRatingsWinLose = $calculator->calculateNewRatings($gameInfo, $teams, [1, 2]);
// Winners
@ -310,7 +310,7 @@ class TrueSkillCalculatorTests
$team2->addPlayer($player2, $gameInfo->getDefaultRating());
$team2->addPlayer($player3, $gameInfo->getDefaultRating());
$teams = Teams::concat($team1, $team2);
$teams = [$team1, $team2];
$newRatingsWinLose = $calculator->calculateNewRatings($gameInfo, $teams, [1, 1]);
// Winners
@ -341,7 +341,7 @@ class TrueSkillCalculatorTests
$team2->addPlayer($player3, $gameInfo->getDefaultRating());
$team2->addPlayer($player4, $gameInfo->getDefaultRating());
$teams = Teams::concat($team1, $team2);
$teams = [$team1, $team2];
$newRatingsWinLose = $calculator->calculateNewRatings($gameInfo, $teams, [1, 1]);
// Winners
@ -381,7 +381,7 @@ class TrueSkillCalculatorTests
$team2->addPlayer($player7, $gameInfo->getDefaultRating());
$team2->addPlayer($player8, $gameInfo->getDefaultRating());
$teams = Teams::concat($team1, $team2);
$teams = [$team1, $team2];
$newRatingsWinLose = $calculator->calculateNewRatings($gameInfo, $teams, [1, 2]);
// Winners
@ -419,7 +419,7 @@ class TrueSkillCalculatorTests
$gameInfo = new GameInfo();
$teams = Teams::concat($team1, $team2);
$teams = [$team1, $team2];
$newRatingsWinLoseExpected = $calculator->calculateNewRatings($gameInfo, $teams, [1, 2]);
// Winners
@ -431,7 +431,7 @@ class TrueSkillCalculatorTests
self::assertRating($testClass, 29.785, 3.958, $newRatingsWinLoseExpected->getRating($player4));
self::assertRating($testClass, 30.879, 2.983, $newRatingsWinLoseExpected->getRating($player5));
$newRatingsWinLoseUpset = $calculator->calculateNewRatings($gameInfo, Teams::concat($team1, $team2), [2, 1]);
$newRatingsWinLoseUpset = $calculator->calculateNewRatings($gameInfo, [$team1, $team2], [2, 1]);
// Winners
self::assertRating($testClass, 32.012, 3.877, $newRatingsWinLoseUpset->getRating($player4));
@ -463,7 +463,7 @@ class TrueSkillCalculatorTests
$team2->addPlayer($player3, new Rating(25, 4));
$team2->addPlayer($player4, new Rating(30, 3));
$teams = Teams::concat($team1, $team2);
$teams = [$team1, $team2];
$newRatingsWinLose = $calculator->calculateNewRatings($gameInfo, $teams, [1, 1]);
// Winners
@ -495,7 +495,7 @@ class TrueSkillCalculatorTests
$team2->addPlayer($player3, new Rating(35, 7));
$team2->addPlayer($player4, new Rating(40, 5));
$teams = Teams::concat($team1, $team2);
$teams = [$team1, $team2];
$newRatingsWinLose = $calculator->calculateNewRatings($gameInfo, $teams, [1, 2]);
// Winners
@ -535,7 +535,7 @@ class TrueSkillCalculatorTests
$team2->addPlayer($player7, $gameInfo->getDefaultRating());
$team2->addPlayer($player8, $gameInfo->getDefaultRating());
$teams = Teams::concat($team1, $team2);
$teams = [$team1, $team2];
$newRatingsWinLose = $calculator->calculateNewRatings($gameInfo, $teams, [1, 2]);
@ -572,7 +572,7 @@ class TrueSkillCalculatorTests
$team2->addPlayer($player3, $gameInfo->getDefaultRating());
$team2->addPlayer($player4, $gameInfo->getDefaultRating());
$teams = Teams::concat($team1, $team2);
$teams = [$team1, $team2];
$newRatingsWinLose = $calculator->calculateNewRatings($gameInfo, $teams, [1, 1]);
// Winners
@ -598,7 +598,7 @@ class TrueSkillCalculatorTests
$team2 = new Team($player2, $gameInfo->getDefaultRating());
$team3 = new Team($player3, $gameInfo->getDefaultRating());
$teams = Teams::concat($team1, $team2, $team3);
$teams = [$team1, $team2, $team3];
$newRatings = $calculator->calculateNewRatings($gameInfo, $teams, [1, 2, 3]);
$player1NewRating = $newRatings->getRating($player1);
@ -625,7 +625,7 @@ class TrueSkillCalculatorTests
$team2 = new Team($player2, $gameInfo->getDefaultRating());
$team3 = new Team($player3, $gameInfo->getDefaultRating());
$teams = Teams::concat($team1, $team2, $team3);
$teams = [$team1, $team2, $team3];
$newRatings = $calculator->calculateNewRatings($gameInfo, $teams, [1, 1, 1]);
$player1NewRating = $newRatings->getRating($player1);
@ -653,7 +653,7 @@ class TrueSkillCalculatorTests
$team3 = new Team($player3, $gameInfo->getDefaultRating());
$team4 = new Team($player4, $gameInfo->getDefaultRating());
$teams = Teams::concat($team1, $team2, $team3, $team4);
$teams = [$team1, $team2, $team3, $team4];
$newRatings = $calculator->calculateNewRatings($gameInfo, $teams, [1, 2, 3, 4]);
@ -687,7 +687,7 @@ class TrueSkillCalculatorTests
$team4 = new Team($player4, $gameInfo->getDefaultRating());
$team5 = new Team($player5, $gameInfo->getDefaultRating());
$teams = Teams::concat($team1, $team2, $team3, $team4, $team5);
$teams = [$team1, $team2, $team3, $team4, $team5];
$newRatings = $calculator->calculateNewRatings($gameInfo, $teams, [1, 2, 3, 4, 5]);
$player1NewRating = $newRatings->getRating($player1);
@ -729,7 +729,7 @@ class TrueSkillCalculatorTests
$team7 = new Team($player7, $gameInfo->getDefaultRating());
$team8 = new Team($player8, $gameInfo->getDefaultRating());
$teams = Teams::concat($team1, $team2, $team3, $team4, $team5, $team6, $team7, $team8);
$teams = [$team1, $team2, $team3, $team4, $team5, $team6, $team7, $team8];
$newRatings = $calculator->calculateNewRatings($gameInfo, $teams, [1, 1, 1, 1, 1, 1, 1, 1]);
$player1NewRating = $newRatings->getRating($player1);
@ -781,7 +781,7 @@ class TrueSkillCalculatorTests
$team7 = new Team($player7, new Rating(40, 2));
$team8 = new Team($player8, new Rating(45, 1));
$teams = Teams::concat($team1, $team2, $team3, $team4, $team5, $team6, $team7, $team8);
$teams = [$team1, $team2, $team3, $team4, $team5, $team6, $team7, $team8];
$newRatings = $calculator->calculateNewRatings($gameInfo, $teams, [1, 2, 3, 4, 5, 6, 7, 8]);
$player1NewRating = $newRatings->getRating($player1);
@ -849,7 +849,7 @@ class TrueSkillCalculatorTests
$team15 = new Team($player15, $gameInfo->getDefaultRating());
$team16 = new Team($player16, $gameInfo->getDefaultRating());
$teams = Teams::concat(
$teams = [
$team1,
$team2,
$team3,
@ -866,7 +866,7 @@ class TrueSkillCalculatorTests
$team14,
$team15,
$team16
);
];
$newRatings = $calculator->calculateNewRatings(
$gameInfo,
@ -952,7 +952,7 @@ class TrueSkillCalculatorTests
$team3->addPlayer($player7, new Rating(50, 5));
$team3->addPlayer($player8, new Rating(30, 2));
$teams = Teams::concat($team1, $team2, $team3);
$teams = [$team1, $team2, $team3];
$newRatingsWinLose = $calculator->calculateNewRatings($gameInfo, $teams, [1, 2, 2]);
// Winners
@ -986,7 +986,7 @@ class TrueSkillCalculatorTests
$team2->addPlayer($p2, $gameInfo->getDefaultRating());
$team2->addPlayer($p3, $gameInfo->getDefaultRating());
$teams = Teams::concat($team1, $team2);
$teams = [$team1, $team2];
$newRatings = $calculator->calculateNewRatings($gameInfo, $teams, [1, 2]);
$p1NewRating = $newRatings->getRating($p1);

@ -0,0 +1,54 @@
<?php
declare(strict_types=1);
namespace DNW\Skills\Tests\TrueSkill;
use DNW\Skills\TrueSkill\TruncatedGaussianCorrectionFunctions;
use DNW\Skills\Numerics\BasicMath;
use DNW\Skills\Numerics\GaussianDistribution;
use PHPUnit\Framework\TestCase;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\UsesClass;
#[CoversClass(TruncatedGaussianCorrectionFunctions::class)]
#[UsesClass(BasicMath::class)]
#[UsesClass(GaussianDistribution::class)]
class TruncatedGaussianCorrectionFunctionsTest extends TestCase
{
public function testvGreaterThan(): void
{
// Test values taken from Ralf Herbrich's F# TrueSkill implementation
$want = 0.4181660649773850;
$tVar = 0.7495591915280050;
$eps = 0.0631282276750071;
$this->assertEqualsWithDelta($want, TruncatedGaussianCorrectionFunctions::vExceedsMargin($tVar, $eps), 1e-6);
}
public function testwGreaterThan(): void
{
// Test values taken from Ralf Herbrich's F# TrueSkill implementation
$want = 0.4619049929317120;
$tVar = 0.7495591915280050;
$eps = 0.0631282276750071;
$this->assertEqualsWithDelta($want, TruncatedGaussianCorrectionFunctions::wExceedsMargin($tVar, $eps), 1e-6);
}
public function testvWithin(): void
{
// Test values taken from Ralf Herbrich's F# TrueSkill implementation
$want = -0.7485644072749330;
$tVar = 0.7495591915280050;
$eps = 0.0631282276750071;
$this->assertEqualsWithDelta($want, TruncatedGaussianCorrectionFunctions::vWithinMargin($tVar, $eps), 1e-6);
}
public function testwWithin(): void
{
// Test values taken from Ralf Herbrich's F# TrueSkill implementation
$want = 0.9986734210033660;
$tVar = 0.7495591915280050;
$eps = 0.0631282276750071;
$this->assertEqualsWithDelta($want, TruncatedGaussianCorrectionFunctions::wWithinMargin($tVar, $eps), 1e-6);
}
}