Compare commits

..

No commits in common. "99eb3271c22882cb0b1416a09190cdb93edcfa1c" and "c18ccd38e2a674f9f60ce3ae700a8acae43bd8e6" have entirely different histories.

13 changed files with 80 additions and 164 deletions

8
README

@ -6,10 +6,4 @@ For more details on how the algorithm works, see
http://www.moserware.com/2010/03/computing-your-skill.html http://www.moserware.com/2010/03/computing-your-skill.html
For details on how to use this project, see the accompanying example snippets with this project. For details on how to use this project, see the accompanying unit tests with this project
For development Composer and the following packages are used (Recommended as Phars installed via Phive)
sudo phive install -g composer phpdocumentor infection phpcs phpcbf phploc phpbench overtrue/phplint
composer install
composer all

72
composer.lock generated

@ -1590,16 +1590,16 @@
}, },
{ {
"name": "phpunit/phpunit", "name": "phpunit/phpunit",
"version": "10.5.10", "version": "10.5.9",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/sebastianbergmann/phpunit.git", "url": "https://github.com/sebastianbergmann/phpunit.git",
"reference": "50b8e314b6d0dd06521dc31d1abffa73f25f850c" "reference": "0bd663704f0165c9e76fe4f06ffa6a1ca727fdbe"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/50b8e314b6d0dd06521dc31d1abffa73f25f850c", "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/0bd663704f0165c9e76fe4f06ffa6a1ca727fdbe",
"reference": "50b8e314b6d0dd06521dc31d1abffa73f25f850c", "reference": "0bd663704f0165c9e76fe4f06ffa6a1ca727fdbe",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -1671,7 +1671,7 @@
"support": { "support": {
"issues": "https://github.com/sebastianbergmann/phpunit/issues", "issues": "https://github.com/sebastianbergmann/phpunit/issues",
"security": "https://github.com/sebastianbergmann/phpunit/security/policy", "security": "https://github.com/sebastianbergmann/phpunit/security/policy",
"source": "https://github.com/sebastianbergmann/phpunit/tree/10.5.10" "source": "https://github.com/sebastianbergmann/phpunit/tree/10.5.9"
}, },
"funding": [ "funding": [
{ {
@ -1687,7 +1687,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2024-02-04T09:07:51+00:00" "time": "2024-01-22T14:35:40+00:00"
}, },
{ {
"name": "psr/container", "name": "psr/container",
@ -2928,16 +2928,16 @@
}, },
{ {
"name": "symfony/polyfill-ctype", "name": "symfony/polyfill-ctype",
"version": "v1.29.0", "version": "v1.28.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/polyfill-ctype.git", "url": "https://github.com/symfony/polyfill-ctype.git",
"reference": "ef4d7e442ca910c4764bce785146269b30cb5fc4" "reference": "ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/ef4d7e442ca910c4764bce785146269b30cb5fc4", "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb",
"reference": "ef4d7e442ca910c4764bce785146269b30cb5fc4", "reference": "ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -2951,6 +2951,9 @@
}, },
"type": "library", "type": "library",
"extra": { "extra": {
"branch-alias": {
"dev-main": "1.28-dev"
},
"thanks": { "thanks": {
"name": "symfony/polyfill", "name": "symfony/polyfill",
"url": "https://github.com/symfony/polyfill" "url": "https://github.com/symfony/polyfill"
@ -2987,7 +2990,7 @@
"portable" "portable"
], ],
"support": { "support": {
"source": "https://github.com/symfony/polyfill-ctype/tree/v1.29.0" "source": "https://github.com/symfony/polyfill-ctype/tree/v1.28.0"
}, },
"funding": [ "funding": [
{ {
@ -3003,20 +3006,20 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2024-01-29T20:11:03+00:00" "time": "2023-01-26T09:26:14+00:00"
}, },
{ {
"name": "symfony/polyfill-intl-grapheme", "name": "symfony/polyfill-intl-grapheme",
"version": "v1.29.0", "version": "v1.28.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/polyfill-intl-grapheme.git", "url": "https://github.com/symfony/polyfill-intl-grapheme.git",
"reference": "32a9da87d7b3245e09ac426c83d334ae9f06f80f" "reference": "875e90aeea2777b6f135677f618529449334a612"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/32a9da87d7b3245e09ac426c83d334ae9f06f80f", "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/875e90aeea2777b6f135677f618529449334a612",
"reference": "32a9da87d7b3245e09ac426c83d334ae9f06f80f", "reference": "875e90aeea2777b6f135677f618529449334a612",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -3027,6 +3030,9 @@
}, },
"type": "library", "type": "library",
"extra": { "extra": {
"branch-alias": {
"dev-main": "1.28-dev"
},
"thanks": { "thanks": {
"name": "symfony/polyfill", "name": "symfony/polyfill",
"url": "https://github.com/symfony/polyfill" "url": "https://github.com/symfony/polyfill"
@ -3065,7 +3071,7 @@
"shim" "shim"
], ],
"support": { "support": {
"source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.29.0" "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.28.0"
}, },
"funding": [ "funding": [
{ {
@ -3081,20 +3087,20 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2024-01-29T20:11:03+00:00" "time": "2023-01-26T09:26:14+00:00"
}, },
{ {
"name": "symfony/polyfill-intl-normalizer", "name": "symfony/polyfill-intl-normalizer",
"version": "v1.29.0", "version": "v1.28.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/polyfill-intl-normalizer.git", "url": "https://github.com/symfony/polyfill-intl-normalizer.git",
"reference": "bc45c394692b948b4d383a08d7753968bed9a83d" "reference": "8c4ad05dd0120b6a53c1ca374dca2ad0a1c4ed92"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/bc45c394692b948b4d383a08d7753968bed9a83d", "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/8c4ad05dd0120b6a53c1ca374dca2ad0a1c4ed92",
"reference": "bc45c394692b948b4d383a08d7753968bed9a83d", "reference": "8c4ad05dd0120b6a53c1ca374dca2ad0a1c4ed92",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -3105,6 +3111,9 @@
}, },
"type": "library", "type": "library",
"extra": { "extra": {
"branch-alias": {
"dev-main": "1.28-dev"
},
"thanks": { "thanks": {
"name": "symfony/polyfill", "name": "symfony/polyfill",
"url": "https://github.com/symfony/polyfill" "url": "https://github.com/symfony/polyfill"
@ -3146,7 +3155,7 @@
"shim" "shim"
], ],
"support": { "support": {
"source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.29.0" "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.28.0"
}, },
"funding": [ "funding": [
{ {
@ -3162,20 +3171,20 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2024-01-29T20:11:03+00:00" "time": "2023-01-26T09:26:14+00:00"
}, },
{ {
"name": "symfony/polyfill-mbstring", "name": "symfony/polyfill-mbstring",
"version": "v1.29.0", "version": "v1.28.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/polyfill-mbstring.git", "url": "https://github.com/symfony/polyfill-mbstring.git",
"reference": "9773676c8a1bb1f8d4340a62efe641cf76eda7ec" "reference": "42292d99c55abe617799667f454222c54c60e229"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/9773676c8a1bb1f8d4340a62efe641cf76eda7ec", "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/42292d99c55abe617799667f454222c54c60e229",
"reference": "9773676c8a1bb1f8d4340a62efe641cf76eda7ec", "reference": "42292d99c55abe617799667f454222c54c60e229",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -3189,6 +3198,9 @@
}, },
"type": "library", "type": "library",
"extra": { "extra": {
"branch-alias": {
"dev-main": "1.28-dev"
},
"thanks": { "thanks": {
"name": "symfony/polyfill", "name": "symfony/polyfill",
"url": "https://github.com/symfony/polyfill" "url": "https://github.com/symfony/polyfill"
@ -3226,7 +3238,7 @@
"shim" "shim"
], ],
"support": { "support": {
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.29.0" "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.28.0"
}, },
"funding": [ "funding": [
{ {
@ -3242,7 +3254,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2024-01-29T20:11:03+00:00" "time": "2023-07-28T09:04:16+00:00"
}, },
{ {
"name": "symfony/service-contracts", "name": "symfony/service-contracts",

@ -7,8 +7,7 @@
"tests" "tests"
], ],
"report": { "report": {
"html": "output/metrics/", "html": "output/metrics/"
"json": "output/metrics/report.json"
}, },
"plugins": { "plugins": {
"git": { "git": {

@ -18,7 +18,6 @@
<coverage> <coverage>
<report> <report>
<html outputDirectory="output/coverage" /> <html outputDirectory="output/coverage" />
<clover outputFile ="output/coverage/clover.xml" />
</report> </report>
</coverage> </coverage>
</phpunit> </phpunit>

@ -8,6 +8,11 @@ class FactorGraph
{ {
private VariableFactory $variableFactory; private VariableFactory $variableFactory;
public function __construct(VariableFactory $factory)
{
$this->variableFactory = $factory;
}
public function getVariableFactory(): VariableFactory public function getVariableFactory(): VariableFactory
{ {
return $this->variableFactory; return $this->variableFactory;

@ -1,22 +0,0 @@
<?php
declare(strict_types=1);
namespace DNW\Skills\Tests;
use DNW\Skills\GameInfo;
use PHPUnit\Framework\TestCase;
class GameInfoTest extends TestCase
{
public function testMembers(): void
{
$gi = new GameInfo(1, 2, 3, 4, 5);
$this->assertEquals(1, $gi->getInitialMean());
$this->assertEquals(2, $gi->getInitialStandardDeviation());
$this->assertEquals(3, $gi->getBeta());
$this->assertEquals(4, $gi->getDynamicsFactor());
$this->assertEquals(5, $gi->getDrawProbability());
$this->assertInstanceOf(\DNW\Skills\Rating::class, $gi->getDefaultRating());
}
}

@ -15,18 +15,4 @@ class BasicMathTest extends TestCase
$this->assertEquals(1.44, BasicMath::square(1.2)); $this->assertEquals(1.44, BasicMath::square(1.2));
$this->assertEquals(4, BasicMath::square(2)); $this->assertEquals(4, BasicMath::square(2));
} }
public function testSum(): void
{
$arr = [1, 1, 1, 1];
$func_return = function ($f) {
return $f;
};
$func_double = function ($f) {
return $f * 2;
};
$this->assertEquals(4, BasicMath::sum($arr, $func_return));
$this->assertEquals(8, BasicMath::sum($arr, $func_double));
}
} }

@ -7,27 +7,12 @@ namespace DNW\Skills\Tests\Numerics;
use DNW\Skills\Numerics\IdentityMatrix; use DNW\Skills\Numerics\IdentityMatrix;
use DNW\Skills\Numerics\Matrix; use DNW\Skills\Numerics\Matrix;
use DNW\Skills\Numerics\SquareMatrix; use DNW\Skills\Numerics\SquareMatrix;
use DNW\Skills\Numerics\DiagonalMatrix;
use PHPUnit\Framework\TestCase; use PHPUnit\Framework\TestCase;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\UsesClass;
use Exception; use Exception;
#[CoversClass(Matrix::class)]
#[UsesClass(SquareMatrix::class)]
#[UsesClass(IdentityMatrix::class)]
#[UsesClass(DiagonalMatrix::class)]
// phpcs:disable PSR2.Methods.FunctionCallSignature,Generic.Functions.FunctionCallArgumentSpacing.TooMuchSpaceAfterComma // phpcs:disable PSR2.Methods.FunctionCallSignature,Generic.Functions.FunctionCallArgumentSpacing.TooMuchSpaceAfterComma
class MatrixTest extends TestCase class MatrixTest extends TestCase
{ {
public function testOneByOneDeterminant(): void
{
$a = new SquareMatrix(1);
$this->assertEquals(1, $a->getDeterminant());
}
public function testTwoByTwoDeterminant(): void public function testTwoByTwoDeterminant(): void
{ {
$a = new SquareMatrix(1, 2, $a = new SquareMatrix(1, 2,
@ -125,7 +110,9 @@ class MatrixTest extends TestCase
1, 2, 3, 1, 2, 3,
4, 5, 6); 4, 5, 6);
$d = Matrix::fromColumnValues(2, 3, [[1, 4], [2, 5], [3,6]]); $d = Matrix::fromRowsColumns(2, 3,
1, 2, 3,
4, 5, 6);
$this->assertTrue($c->equals($d)); $this->assertTrue($c->equals($d));
@ -157,21 +144,6 @@ class MatrixTest extends TestCase
$this->assertFalse($k->equals($l)); $this->assertFalse($k->equals($l));
} }
public function testAdd(): void
{
// From Wikipedia: http://en.wikipedia.org/wiki/Adjugate_matrix
$a = new SquareMatrix(1, 2,
3, 4);
$b = new SquareMatrix(4, 3,
2, 1);
$sum = Matrix::add($a, $b);
$result = new SquareMatrix(5, 5, 5, 5);
$this->assertEquals(TRUE, $result->equals($sum));
}
public function testAdjugate(): void public function testAdjugate(): void
{ {
// From Wikipedia: http://en.wikipedia.org/wiki/Adjugate_matrix // From Wikipedia: http://en.wikipedia.org/wiki/Adjugate_matrix
@ -225,14 +197,6 @@ class MatrixTest extends TestCase
$ccInverse = Matrix::multiply($c, $cInverse); $ccInverse = Matrix::multiply($c, $cInverse);
$this->assertTrue($identity3x3->equals($ccInverse)); $this->assertTrue($identity3x3->equals($ccInverse));
$e = new SquareMatrix(10);
$f = new SquareMatrix(0.1);
$eInverse = $e->getInverse();
$this->assertTrue($f->equals($eInverse));
} }
public function testErrorDeterminant(): void public function testErrorDeterminant(): void

@ -27,19 +27,5 @@ class RangeTest extends TestCase
$range = Range::inclusive(1, 10); $range = Range::inclusive(1, 10);
$this->assertEquals(1, $range->getMin()); $this->assertEquals(1, $range->getMin());
$this->assertEquals(10, $range->getMax()); $this->assertEquals(10, $range->getMax());
$this->assertEquals(FALSE, $range->isInRange(0));
$this->assertEquals(TRUE, $range->isInRange(1));
$this->assertEquals(TRUE, $range->isInRange(2));
$this->assertEquals(TRUE, $range->isInRange(9));
$this->assertEquals(TRUE, $range->isInRange(10));
$this->assertEquals(FALSE, $range->isInRange(11));
$range = Range::atLeast(20);
$this->assertEquals(20, $range->getMin());
$this->assertEquals(PHP_INT_MAX, $range->getMax());
$range = Range::exactly(5);
$this->assertEquals(5, $range->getMin());
$this->assertEquals(5, $range->getMax());
} }
} }

@ -0,0 +1,28 @@
<?php
declare(strict_types=1);
namespace DNW\Skills\Tests\TrueSkill;
use DNW\Skills\TrueSkill\FactorGraphTrueSkillCalculator;
use DNW\Skills\SkillCalculatorSupportedOptions;
use PHPUnit\Framework\TestCase;
class FactorGraphTeamTrueSkillCalculatorTest extends TestCase
{
public function testFactorGraphTrueSkillCalculator(): void
{
$calculator = new FactorGraphTrueSkillCalculator();
TrueSkillCalculatorTests::testAllTwoPlayerScenarios($this, $calculator);
TrueSkillCalculatorTests::testAllTwoTeamScenarios($this, $calculator);
TrueSkillCalculatorTests::testAllMultipleTeamScenarios($this, $calculator);
TrueSkillCalculatorTests::testPartialPlayScenarios($this, $calculator);
}
public function testMethodisSupported(): void
{
$calculator = new FactorGraphTrueSkillCalculator();
$this->assertEquals(TRUE, $calculator->isSupported(SkillCalculatorSupportedOptions::PARTIAL_PLAY));
}
}

@ -8,20 +8,10 @@ use DNW\Skills\GameInfo;
use DNW\Skills\Player; use DNW\Skills\Player;
use DNW\Skills\Team; use DNW\Skills\Team;
use DNW\Skills\TrueSkill\FactorGraphTrueSkillCalculator; use DNW\Skills\TrueSkill\FactorGraphTrueSkillCalculator;
use DNW\Skills\SkillCalculatorSupportedOptions;
use PHPUnit\Framework\TestCase; use PHPUnit\Framework\TestCase;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\CoversNothing;
use PHPUnit\Framework\Attributes\UsesClass;
#[CoversClass(FactorGraphTrueSkillCalculator::class)]
#[UsesClass(\DNW\Skills\Numerics\Range::class)]
#[UsesClass(\DNW\Skills\PlayersRange::class)]
#[UsesClass(\DNW\Skills\SkillCalculator::class)]
#[UsesClass(\DNW\Skills\TeamsRange::class)]
class FactorGraphTrueSkillCalculatorTest extends TestCase class FactorGraphTrueSkillCalculatorTest extends TestCase
{ {
#[CoversNothing]
public function testMicrosoftResearchExample(): void public function testMicrosoftResearchExample(): void
{ {
$gameInfo = new GameInfo(); $gameInfo = new GameInfo();
@ -63,21 +53,4 @@ class FactorGraphTrueSkillCalculatorTest extends TestCase
$this->assertEqualsWithDelta($expected[$player->getId()][1], $rating->getStandardDeviation(), 0.001); $this->assertEqualsWithDelta($expected[$player->getId()][1], $rating->getStandardDeviation(), 0.001);
} }
} }
#[CoversNothing]
public function testFactorGraphTrueSkillCalculator(): void
{
$calculator = new FactorGraphTrueSkillCalculator();
TrueSkillCalculatorTests::testAllTwoPlayerScenarios($this, $calculator);
TrueSkillCalculatorTests::testAllTwoTeamScenarios($this, $calculator);
TrueSkillCalculatorTests::testAllMultipleTeamScenarios($this, $calculator);
TrueSkillCalculatorTests::testPartialPlayScenarios($this, $calculator);
}
public function testMethodisSupported(): void
{
$calculator = new FactorGraphTrueSkillCalculator();
$this->assertEquals(TRUE, $calculator->isSupported(SkillCalculatorSupportedOptions::PARTIAL_PLAY));
}
} }

@ -6,13 +6,9 @@ namespace DNW\Skills\Tests\TrueSkill;
use DNW\Skills\TrueSkill\TwoPlayerTrueSkillCalculator; use DNW\Skills\TrueSkill\TwoPlayerTrueSkillCalculator;
use PHPUnit\Framework\TestCase; use PHPUnit\Framework\TestCase;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\CoversNothing;
#[CoversClass(TwoPlayerTrueSkillCalculator::class)]
class TwoPlayerTrueSkillCalculatorTest extends TestCase class TwoPlayerTrueSkillCalculatorTest extends TestCase
{ {
#[CoversNothing]
public function testTwoPlayerTrueSkillCalculator(): void public function testTwoPlayerTrueSkillCalculator(): void
{ {
$calculator = new TwoPlayerTrueSkillCalculator(); $calculator = new TwoPlayerTrueSkillCalculator();

@ -6,13 +6,9 @@ namespace DNW\Skills\Tests\TrueSkill;
use DNW\Skills\TrueSkill\TwoTeamTrueSkillCalculator; use DNW\Skills\TrueSkill\TwoTeamTrueSkillCalculator;
use PHPUnit\Framework\TestCase; use PHPUnit\Framework\TestCase;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\CoversNothing;
//#[CoversClass(TwoTeamTrueSkillCalculator::class)]
class TwoTeamTrueSkillCalculatorTest extends TestCase class TwoTeamTrueSkillCalculatorTest extends TestCase
{ {
#[CoversNothing]
public function testTwoTeamTrueSkillCalculator(): void public function testTwoTeamTrueSkillCalculator(): void
{ {
$calculator = new TwoTeamTrueSkillCalculator(); $calculator = new TwoTeamTrueSkillCalculator();