Compare commits

...

7 Commits

Author SHA1 Message Date
61af342cfa More rector rules
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
2024-02-21 14:10:01 +00:00
c781540aa6 rector: instanceOf, earlyReturn, strictBooleans 2024-02-21 14:02:35 +00:00
0184d0432b rector: codingStyle 2024-02-21 13:48:37 +00:00
f3e5912ebb Rector: codeQuality 2024-02-21 13:40:20 +00:00
703372fda9 Rector: deadcode. 2024-02-21 13:29:09 +00:00
df5b48b2c4 More static types using rector. 2024-02-21 13:23:39 +00:00
660fbd1486 Rector standards slowly being applied. PHP Version first. 2024-02-20 14:21:44 +00:00
45 changed files with 226 additions and 132 deletions

@ -30,7 +30,7 @@ class BasicBench
$team1 = new Team($p1, $gameInfo->getDefaultRating()); $team1 = new Team($p1, $gameInfo->getDefaultRating());
$team2 = new Team($p2, $gameInfo->getDefaultRating()); $team2 = new Team($p2, $gameInfo->getDefaultRating());
for ($i = 0; $i < 10; $i++) { for ($i = 0; $i < 10; ++$i) {
$teams = Teams::concat($team1, $team2); $teams = Teams::concat($team1, $team2);
$calculator = new TwoPlayerTrueSkillCalculator(); $calculator = new TwoPlayerTrueSkillCalculator();
@ -61,7 +61,7 @@ class BasicBench
$team1 = new Team($p1, $gameInfo->getDefaultRating()); $team1 = new Team($p1, $gameInfo->getDefaultRating());
$team2 = new Team($p2, $gameInfo->getDefaultRating()); $team2 = new Team($p2, $gameInfo->getDefaultRating());
for ($i = 0; $i < 10; $i++) { for ($i = 0; $i < 10; ++$i) {
$teams = Teams::concat($team1, $team2); $teams = Teams::concat($team1, $team2);
$calculator = new TwoTeamTrueSkillCalculator(); $calculator = new TwoTeamTrueSkillCalculator();
@ -92,7 +92,7 @@ class BasicBench
$team1 = new Team($p1, $gameInfo->getDefaultRating()); $team1 = new Team($p1, $gameInfo->getDefaultRating());
$team2 = new Team($p2, $gameInfo->getDefaultRating()); $team2 = new Team($p2, $gameInfo->getDefaultRating());
for ($i = 0; $i < 10; $i++) { for ($i = 0; $i < 10; ++$i) {
$teams = Teams::concat($team1, $team2); $teams = Teams::concat($team1, $team2);
$calculator = new FactorGraphTrueSkillCalculator(); $calculator = new FactorGraphTrueSkillCalculator();
@ -125,7 +125,7 @@ class BasicBench
$team2 = new Team($p2, $gameInfo->getDefaultRating()); $team2 = new Team($p2, $gameInfo->getDefaultRating());
$team3 = new Team($p3, $gameInfo->getDefaultRating()); $team3 = new Team($p3, $gameInfo->getDefaultRating());
for ($i = 0; $i < 10; $i++) { for ($i = 0; $i < 10; ++$i) {
$teams = Teams::concat($team1, $team2, $team3); $teams = Teams::concat($team1, $team2, $team3);
$calculator = new FactorGraphTrueSkillCalculator(); $calculator = new FactorGraphTrueSkillCalculator();

@ -10,7 +10,8 @@
"vimeo/psalm": "^5.21.1", "vimeo/psalm": "^5.21.1",
"phpmetrics/phpmetrics": "^3.0-dev", "phpmetrics/phpmetrics": "^3.0-dev",
"phpunit/phpunit": "^10.5", "phpunit/phpunit": "^10.5",
"psalm/plugin-phpunit": "^0.18.4" "psalm/plugin-phpunit": "^0.18.4",
"rector/rector": "^1.0"
}, },
"autoload": { "autoload": {
"psr-4": { "psr-4": {

68
composer.lock generated

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically" "This file is @generated automatically"
], ],
"content-hash": "ae420a83c061b5eb7f6ec5487f01643a", "content-hash": "ba51339b2bd54ead227bc16656795670",
"packages": [], "packages": [],
"packages-dev": [ "packages-dev": [
{ {
@ -1280,16 +1280,16 @@
}, },
{ {
"name": "phpstan/phpstan", "name": "phpstan/phpstan",
"version": "1.10.58", "version": "1.10.59",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/phpstan/phpstan.git", "url": "https://github.com/phpstan/phpstan.git",
"reference": "a23518379ec4defd9e47cbf81019526861623ec2" "reference": "e607609388d3a6d418a50a49f7940e8086798281"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/a23518379ec4defd9e47cbf81019526861623ec2", "url": "https://api.github.com/repos/phpstan/phpstan/zipball/e607609388d3a6d418a50a49f7940e8086798281",
"reference": "a23518379ec4defd9e47cbf81019526861623ec2", "reference": "e607609388d3a6d418a50a49f7940e8086798281",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -1338,7 +1338,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2024-02-12T20:02:57+00:00" "time": "2024-02-20T13:59:13+00:00"
}, },
{ {
"name": "phpunit/php-code-coverage", "name": "phpunit/php-code-coverage",
@ -1925,6 +1925,62 @@
}, },
"time": "2021-07-14T16:46:02+00:00" "time": "2021-07-14T16:46:02+00:00"
}, },
{
"name": "rector/rector",
"version": "1.0.1",
"source": {
"type": "git",
"url": "https://github.com/rectorphp/rector.git",
"reference": "258b775511e62a7188f8ce114d44acaf244d9a7d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/rectorphp/rector/zipball/258b775511e62a7188f8ce114d44acaf244d9a7d",
"reference": "258b775511e62a7188f8ce114d44acaf244d9a7d",
"shasum": ""
},
"require": {
"php": "^7.2|^8.0",
"phpstan/phpstan": "^1.10.57"
},
"conflict": {
"rector/rector-doctrine": "*",
"rector/rector-downgrade-php": "*",
"rector/rector-phpunit": "*",
"rector/rector-symfony": "*"
},
"bin": [
"bin/rector"
],
"type": "library",
"autoload": {
"files": [
"bootstrap.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"description": "Instant Upgrade and Automated Refactoring of any PHP code",
"keywords": [
"automation",
"dev",
"migration",
"refactoring"
],
"support": {
"issues": "https://github.com/rectorphp/rector/issues",
"source": "https://github.com/rectorphp/rector/tree/1.0.1"
},
"funding": [
{
"url": "https://github.com/tomasvotruba",
"type": "github"
}
],
"time": "2024-02-16T07:53:23+00:00"
},
{ {
"name": "sebastian/cli-parser", "name": "sebastian/cli-parser",
"version": "2.0.0", "version": "2.0.0",

@ -1,6 +1,6 @@
<?php <?php
require_once("vendor/autoload.php"); require_once(__DIR__ . "/vendor/autoload.php");
use DNW\Skills\TrueSkill\FactorGraphTrueSkillCalculator; use DNW\Skills\TrueSkill\FactorGraphTrueSkillCalculator;
use DNW\Skills\GameInfo; use DNW\Skills\GameInfo;
@ -20,8 +20,8 @@ $team2 = new Team($p2, $gameInfo->getDefaultRating());
$team3 = new Team($p3, $gameInfo->getDefaultRating()); $team3 = new Team($p3, $gameInfo->getDefaultRating());
for($i = 0; $i < 5; $i++) { for($i = 0; $i < 5; ++$i) {
echo "Iteration: $i\n"; echo "Iteration: " . $i . PHP_EOL;
$teams = Teams::concat($team1, $team2, $team3); $teams = Teams::concat($team1, $team2, $team3);
$calculator = new FactorGraphTrueSkillCalculator(); $calculator = new FactorGraphTrueSkillCalculator();

@ -1,6 +1,6 @@
<?php <?php
require_once("vendor/autoload.php"); require_once(__DIR__ . "/vendor/autoload.php");
use DNW\Skills\TrueSkill\TwoPlayerTrueSkillCalculator; use DNW\Skills\TrueSkill\TwoPlayerTrueSkillCalculator;
use DNW\Skills\GameInfo; use DNW\Skills\GameInfo;
@ -19,8 +19,8 @@ $team1 = new Team($p1, $gameInfo->getDefaultRating());
$team2 = new Team($p2, $gameInfo->getDefaultRating()); $team2 = new Team($p2, $gameInfo->getDefaultRating());
for($i = 0; $i < 5; $i++) { for($i = 0; $i < 5; ++$i) {
echo "Iteration: $i\n"; echo "Iteration: " . $i . PHP_EOL;
$teams = Teams::concat($team1, $team2); $teams = Teams::concat($team1, $team2);
$calculator = new TwoPlayerTrueSkillCalculator(); $calculator = new TwoPlayerTrueSkillCalculator();

20
rector.php Normal file

@ -0,0 +1,20 @@
<?php
declare(strict_types=1);
use Rector\Config\RectorConfig;
use Rector\CodeQuality\Rector\ClassMethod\LocallyCalledStaticMethodToNonStaticRector;
return RectorConfig::configure()
->withPaths([
__DIR__ . '/benchmark',
__DIR__ . '/examples',
__DIR__ . '/src',
__DIR__ . '/tests',
])
// uncomment to reach your current PHP version
->withPhpSets()
->withPreparedSets(deadCode: true, codeQuality: true, codingStyle: true, typeDeclarations : true, privatization: true, naming: false, instanceOf: true, earlyReturn: true, strictBooleans: true)
->withSkip([
LocallyCalledStaticMethodToNonStaticRector::class
]);;

@ -15,9 +15,9 @@ abstract class Factor implements \Stringable
*/ */
private array $messages = []; private array $messages = [];
private HashMap $messageToVariableBinding; private readonly HashMap $messageToVariableBinding;
private string $name; private readonly string $name;
/** /**
* @var Variable[] $variables * @var Variable[] $variables
@ -31,9 +31,9 @@ abstract class Factor implements \Stringable
} }
/** /**
* @return mixed The log-normalization constant of that factor * @return float The log-normalization constant of that factor
*/ */
public function getLogNormalization() public function getLogNormalization(): float
{ {
return 0; return 0;
} }

@ -18,10 +18,11 @@ abstract class FactorGraphLayer
* @var array<int,array<int,object>> * @var array<int,array<int,object>>
*/ */
private array $outputVariablesGroups = []; private array $outputVariablesGroups = [];
/** /**
* @var array<int,array<int,object>> * @var array<int,array<int,object>>
*/ */
private $inputVariablesGroups = []; private array $inputVariablesGroups = [];
protected function __construct(private readonly TrueSkillFactorGraph $parentFactorGraph) protected function __construct(private readonly TrueSkillFactorGraph $parentFactorGraph)
{ {

@ -25,12 +25,12 @@ class FactorList
$listCount = count($this->list); $listCount = count($this->list);
for ($i = 0; $i < $listCount; $i++) { for ($i = 0; $i < $listCount; ++$i) {
$f = $this->list[$i]; $f = $this->list[$i];
$numberOfMessages = $f->getNumberOfMessages(); $numberOfMessages = $f->getNumberOfMessages();
for ($j = 0; $j < $numberOfMessages; $j++) { for ($j = 0; $j < $numberOfMessages; ++$j) {
$sumLogZ += $f->sendMessageIndex($j); $sumLogZ += $f->sendMessageIndex($j);
} }
} }

@ -6,7 +6,7 @@ namespace DNW\Skills\FactorGraphs;
class KeyedVariable extends Variable class KeyedVariable extends Variable
{ {
public function __construct(private mixed $key, string $name, mixed $prior) public function __construct(private readonly mixed $key, string $name, mixed $prior)
{ {
parent::__construct($name, $prior); parent::__construct($name, $prior);
} }

@ -8,7 +8,7 @@ use DNW\Skills\Numerics\GaussianDistribution;
class Message implements \Stringable class Message implements \Stringable
{ {
public function __construct(private GaussianDistribution $value, private string $name) public function __construct(private GaussianDistribution $value, private readonly string $name)
{ {
} }

@ -6,7 +6,7 @@ namespace DNW\Skills\FactorGraphs;
abstract class Schedule implements \Stringable abstract class Schedule implements \Stringable
{ {
protected function __construct(private string $name) protected function __construct(private readonly string $name)
{ {
} }

@ -6,7 +6,7 @@ namespace DNW\Skills\FactorGraphs;
class ScheduleLoop extends Schedule class ScheduleLoop extends Schedule
{ {
public function __construct(string $name, private readonly Schedule $scheduleToLoop, private float $maxDelta) public function __construct(string $name, private readonly Schedule $scheduleToLoop, private readonly float $maxDelta)
{ {
parent::__construct($name); parent::__construct($name);
} }

@ -6,7 +6,7 @@ namespace DNW\Skills\FactorGraphs;
class ScheduleStep extends Schedule class ScheduleStep extends Schedule
{ {
public function __construct(string $name, private readonly Factor $factor, private int $index) public function __construct(string $name, private readonly Factor $factor, private readonly int $index)
{ {
parent::__construct($name); parent::__construct($name);
} }

@ -8,7 +8,7 @@ use DNW\Skills\Numerics\GaussianDistribution;
class Variable implements \Stringable class Variable implements \Stringable
{ {
private string $name; private readonly string $name;
private mixed $value; private mixed $value;

@ -20,11 +20,11 @@ class GameInfo
private const DEFAULT_INITIAL_STANDARD_DEVIATION = 8.3333333333333333333333333333333; private const DEFAULT_INITIAL_STANDARD_DEVIATION = 8.3333333333333333333333333333333;
public function __construct( public function __construct(
private float $initialMean = self::DEFAULT_INITIAL_MEAN, private readonly float $initialMean = self::DEFAULT_INITIAL_MEAN,
private float $initialStandardDeviation = self::DEFAULT_INITIAL_STANDARD_DEVIATION, private readonly float $initialStandardDeviation = self::DEFAULT_INITIAL_STANDARD_DEVIATION,
private float $beta = self::DEFAULT_BETA, private readonly float $beta = self::DEFAULT_BETA,
private float $dynamicsFactor = self::DEFAULT_DYNAMICS_FACTOR, private readonly float $dynamicsFactor = self::DEFAULT_DYNAMICS_FACTOR,
private float $drawProbability = self::DEFAULT_DRAW_PROBABILITY private readonly float $drawProbability = self::DEFAULT_DRAW_PROBABILITY
) )
{ {
} }

@ -15,8 +15,8 @@ class DiagonalMatrix extends Matrix
parent::__construct($diagonalCount, $diagonalCount); parent::__construct($diagonalCount, $diagonalCount);
for ($currentRow = 0; $currentRow < $diagonalCount; $currentRow++) { for ($currentRow = 0; $currentRow < $diagonalCount; ++$currentRow) {
for ($currentCol = 0; $currentCol < $diagonalCount; $currentCol++) { for ($currentCol = 0; $currentCol < $diagonalCount; ++$currentCol) {
if ($currentRow === $currentCol) { if ($currentRow === $currentCol) {
$this->setValue($currentRow, $currentCol, $diagonalValues[$currentRow]); $this->setValue($currentRow, $currentCol, $diagonalValues[$currentRow]);
} else { } else {

@ -19,6 +19,7 @@ class GaussianDistribution implements \Stringable
//log(sqrt(2*pi)) //log(sqrt(2*pi))
//From https://www.wolframalpha.com/input?i=log%28sqrt%282*pi%29%29 //From https://www.wolframalpha.com/input?i=log%28sqrt%282*pi%29%29
private const M_LOG_SQRT_2_PI = 0.9189385332046727417803297364056176398613974736377834128171515404; private const M_LOG_SQRT_2_PI = 0.9189385332046727417803297364056176398613974736377834128171515404;
// precision and precisionMean are used because they make multiplying and dividing simpler // precision and precisionMean are used because they make multiplying and dividing simpler
// (the the accompanying math paper for more details) // (the the accompanying math paper for more details)
private float $precision; private float $precision;
@ -209,7 +210,7 @@ class GaussianDistribution implements \Stringable
$d = 0.0; $d = 0.0;
$dd = 0.0; $dd = 0.0;
for ($j = $ncof - 1; $j > 0; $j--) { for ($j = $ncof - 1; $j > 0; --$j) {
$tmp = $d; $tmp = $d;
$d = $ty * $d - $dd + $coefficients[$j]; $d = $ty * $d - $dd + $coefficients[$j];
$dd = $tmp; $dd = $tmp;
@ -227,6 +228,7 @@ class GaussianDistribution implements \Stringable
if ($p >= 2.0) { if ($p >= 2.0) {
return -100; return -100;
} }
if ($p <= 0.0) { if ($p <= 0.0) {
return 100; return 100;
} }
@ -235,7 +237,7 @@ class GaussianDistribution implements \Stringable
$t = sqrt(-2 * log($pp / 2.0)); // Initial guess $t = sqrt(-2 * log($pp / 2.0)); // Initial guess
$x = -M_SQRT1_2 * ((2.30753 + $t * 0.27061) / (1.0 + $t * (0.99229 + $t * 0.04481)) - $t); $x = -M_SQRT1_2 * ((2.30753 + $t * 0.27061) / (1.0 + $t * (0.99229 + $t * 0.04481)) - $t);
for ($j = 0; $j < 2; $j++) { for ($j = 0; $j < 2; ++$j) {
$err = GaussianDistribution::errorFunctionCumulativeTo($x) - $pp; $err = GaussianDistribution::errorFunctionCumulativeTo($x) - $pp;
$x += $err / (M_2_SQRTPI * exp(-BasicMath::square($x)) - $x * $err); // Halley $x += $err / (M_2_SQRTPI * exp(-BasicMath::square($x)) - $x * $err); // Halley
} }

@ -13,7 +13,7 @@ class Matrix
/** /**
* @param array<int,array<int,float>> $matrixRowData * @param array<int,array<int,float>> $matrixRowData
*/ */
public function __construct(private int $rowCount = 0, private int $columnCount = 0, private array $matrixRowData = []) public function __construct(private readonly int $rowCount = 0, private readonly int $columnCount = 0, private array $matrixRowData = [])
{ {
} }
@ -25,10 +25,10 @@ class Matrix
$data = []; $data = [];
$result = new Matrix($rows, $columns, $data); $result = new Matrix($rows, $columns, $data);
for ($currentColumn = 0; $currentColumn < $columns; $currentColumn++) { for ($currentColumn = 0; $currentColumn < $columns; ++$currentColumn) {
$currentColumnData = $columnValues[$currentColumn]; $currentColumnData = $columnValues[$currentColumn];
for ($currentRow = 0; $currentRow < $rows; $currentRow++) { for ($currentRow = 0; $currentRow < $rows; ++$currentRow) {
$result->setValue($currentRow, $currentColumn, $currentColumnData[$currentRow]); $result->setValue($currentRow, $currentColumn, $currentColumnData[$currentRow]);
} }
} }
@ -41,8 +41,8 @@ class Matrix
$result = new Matrix($rows, $cols); $result = new Matrix($rows, $cols);
$currentIndex = 0; $currentIndex = 0;
for ($currentRow = 0; $currentRow < $rows; $currentRow++) { for ($currentRow = 0; $currentRow < $rows; ++$currentRow) {
for ($currentCol = 0; $currentCol < $cols; $currentCol++) { for ($currentCol = 0; $currentCol < $cols; ++$currentCol) {
$result->setValue($currentRow, $currentCol, $args[$currentIndex++]); $result->setValue($currentRow, $currentCol, $args[$currentIndex++]);
} }
} }
@ -76,8 +76,8 @@ class Matrix
$transposeMatrix = []; $transposeMatrix = [];
$rowMatrixData = $this->matrixRowData; $rowMatrixData = $this->matrixRowData;
for ($currentRowTransposeMatrix = 0; $currentRowTransposeMatrix < $this->columnCount; $currentRowTransposeMatrix++) { for ($currentRowTransposeMatrix = 0; $currentRowTransposeMatrix < $this->columnCount; ++$currentRowTransposeMatrix) {
for ($currentColumnTransposeMatrix = 0; $currentColumnTransposeMatrix < $this->rowCount; $currentColumnTransposeMatrix++) { for ($currentColumnTransposeMatrix = 0; $currentColumnTransposeMatrix < $this->rowCount; ++$currentColumnTransposeMatrix) {
$transposeMatrix[$currentRowTransposeMatrix][$currentColumnTransposeMatrix] = $transposeMatrix[$currentRowTransposeMatrix][$currentColumnTransposeMatrix] =
$rowMatrixData[$currentColumnTransposeMatrix][$currentRowTransposeMatrix]; $rowMatrixData[$currentColumnTransposeMatrix][$currentRowTransposeMatrix];
} }
@ -88,7 +88,7 @@ class Matrix
private function isSquare(): bool private function isSquare(): bool
{ {
return ($this->rowCount == $this->columnCount) && ($this->rowCount > 0); return ($this->rowCount === $this->columnCount) && ($this->rowCount > 0);
} }
public function getDeterminant(): float public function getDeterminant(): float
@ -126,7 +126,7 @@ class Matrix
$result = 0.0; $result = 0.0;
// I expand along the first row // I expand along the first row
for ($currentColumn = 0; $currentColumn < $this->columnCount; $currentColumn++) { for ($currentColumn = 0; $currentColumn < $this->columnCount; ++$currentColumn) {
$firstRowColValue = $this->matrixRowData[0][$currentColumn]; $firstRowColValue = $this->matrixRowData[0][$currentColumn];
$cofactor = $this->getCofactor(0, $currentColumn); $cofactor = $this->getCofactor(0, $currentColumn);
$itemToAdd = $firstRowColValue * $cofactor; $itemToAdd = $firstRowColValue * $cofactor;
@ -168,8 +168,8 @@ class Matrix
// The idea is that it's the transpose of the cofactors // The idea is that it's the transpose of the cofactors
$result = []; $result = [];
for ($currentColumn = 0; $currentColumn < $this->columnCount; $currentColumn++) { for ($currentColumn = 0; $currentColumn < $this->columnCount; ++$currentColumn) {
for ($currentRow = 0; $currentRow < $this->rowCount; $currentRow++) { for ($currentRow = 0; $currentRow < $this->rowCount; ++$currentRow) {
$result[$currentColumn][$currentRow] = $this->getCofactor($currentRow, $currentColumn); $result[$currentColumn][$currentRow] = $this->getCofactor($currentRow, $currentColumn);
} }
} }
@ -197,8 +197,8 @@ class Matrix
$columns = $matrix->getColumnCount(); $columns = $matrix->getColumnCount();
$newValues = []; $newValues = [];
for ($currentRow = 0; $currentRow < $rows; $currentRow++) { for ($currentRow = 0; $currentRow < $rows; ++$currentRow) {
for ($currentColumn = 0; $currentColumn < $columns; $currentColumn++) { for ($currentColumn = 0; $currentColumn < $columns; ++$currentColumn) {
$newValues[$currentRow][$currentColumn] = $scalarValue * $matrix->getValue($currentRow, $currentColumn); $newValues[$currentRow][$currentColumn] = $scalarValue * $matrix->getValue($currentRow, $currentColumn);
} }
} }
@ -208,7 +208,7 @@ class Matrix
public static function add(Matrix $left, Matrix $right): Matrix public static function add(Matrix $left, Matrix $right): Matrix
{ {
if (($left->getRowCount() != $right->getRowCount()) || ($left->getColumnCount() != $right->getColumnCount())) { if (($left->getRowCount() !== $right->getRowCount()) || ($left->getColumnCount() !== $right->getColumnCount())) {
throw new Exception('Matrices must be of the same size'); throw new Exception('Matrices must be of the same size');
} }
@ -216,8 +216,8 @@ class Matrix
$resultMatrix = []; $resultMatrix = [];
for ($currentRow = 0; $currentRow < $left->getRowCount(); $currentRow++) { for ($currentRow = 0; $currentRow < $left->getRowCount(); ++$currentRow) {
for ($currentColumn = 0; $currentColumn < $right->getColumnCount(); $currentColumn++) { for ($currentColumn = 0; $currentColumn < $right->getColumnCount(); ++$currentColumn) {
$resultMatrix[$currentRow][$currentColumn] = $resultMatrix[$currentRow][$currentColumn] =
$left->getValue($currentRow, $currentColumn) $left->getValue($currentRow, $currentColumn)
+ +
@ -233,7 +233,7 @@ class Matrix
// Just your standard matrix multiplication. // Just your standard matrix multiplication.
// See http://en.wikipedia.org/wiki/Matrix_multiplication for details // See http://en.wikipedia.org/wiki/Matrix_multiplication for details
if ($left->getColumnCount() != $right->getRowCount()) { if ($left->getColumnCount() !== $right->getRowCount()) {
throw new Exception('The width of the left matrix must match the height of the right matrix'); throw new Exception('The width of the left matrix must match the height of the right matrix');
} }
@ -242,11 +242,11 @@ class Matrix
$resultMatrix = []; $resultMatrix = [];
for ($currentRow = 0; $currentRow < $resultRows; $currentRow++) { for ($currentRow = 0; $currentRow < $resultRows; ++$currentRow) {
for ($currentColumn = 0; $currentColumn < $resultColumns; $currentColumn++) { for ($currentColumn = 0; $currentColumn < $resultColumns; ++$currentColumn) {
$productValue = 0; $productValue = 0;
for ($vectorIndex = 0; $vectorIndex < $left->getColumnCount(); $vectorIndex++) { for ($vectorIndex = 0; $vectorIndex < $left->getColumnCount(); ++$vectorIndex) {
$leftValue = $left->getValue($currentRow, $vectorIndex); $leftValue = $left->getValue($currentRow, $vectorIndex);
$rightValue = $right->getValue($vectorIndex, $currentColumn); $rightValue = $right->getValue($vectorIndex, $currentColumn);
$vectorIndexProduct = $leftValue * $rightValue; $vectorIndexProduct = $leftValue * $rightValue;
@ -269,24 +269,24 @@ class Matrix
$actualRow = 0; $actualRow = 0;
for ($currentRow = 0; $currentRow < $this->rowCount; $currentRow++) { for ($currentRow = 0; $currentRow < $this->rowCount; ++$currentRow) {
if ($currentRow == $rowToRemove) { if ($currentRow == $rowToRemove) {
continue; continue;
} }
$actualCol = 0; $actualCol = 0;
for ($currentColumn = 0; $currentColumn < $this->columnCount; $currentColumn++) { for ($currentColumn = 0; $currentColumn < $this->columnCount; ++$currentColumn) {
if ($currentColumn == $columnToRemove) { if ($currentColumn == $columnToRemove) {
continue; continue;
} }
$result[$actualRow][$actualCol] = $this->matrixRowData[$currentRow][$currentColumn]; $result[$actualRow][$actualCol] = $this->matrixRowData[$currentRow][$currentColumn];
$actualCol++; ++$actualCol;
} }
$actualRow++; ++$actualRow;
} }
return new Matrix($this->rowCount - 1, $this->columnCount - 1, $result); return new Matrix($this->rowCount - 1, $this->columnCount - 1, $result);
@ -301,19 +301,19 @@ class Matrix
if ($isEven) { if ($isEven) {
return $this->getMinorMatrix($rowToRemove, $columnToRemove)->getDeterminant(); return $this->getMinorMatrix($rowToRemove, $columnToRemove)->getDeterminant();
} else {
return -1.0 * $this->getMinorMatrix($rowToRemove, $columnToRemove)->getDeterminant();
} }
return -1.0 * $this->getMinorMatrix($rowToRemove, $columnToRemove)->getDeterminant();
} }
public function equals(Matrix $otherMatrix): bool public function equals(Matrix $otherMatrix): bool
{ {
if (($this->rowCount != $otherMatrix->getRowCount()) || ($this->columnCount != $otherMatrix->getColumnCount())) { if (($this->rowCount !== $otherMatrix->getRowCount()) || ($this->columnCount !== $otherMatrix->getColumnCount())) {
return FALSE; return FALSE;
} }
for ($currentRow = 0; $currentRow < $this->rowCount; $currentRow++) { for ($currentRow = 0; $currentRow < $this->rowCount; ++$currentRow) {
for ($currentColumn = 0; $currentColumn < $this->columnCount; $currentColumn++) { for ($currentColumn = 0; $currentColumn < $this->columnCount; ++$currentColumn) {
$delta = $delta =
abs( abs(
$this->matrixRowData[$currentRow][$currentColumn] - $this->matrixRowData[$currentRow][$currentColumn] -

@ -11,7 +11,7 @@ use Exception;
class Range class Range
{ {
final public function __construct(private int $min, private int $max) final public function __construct(private readonly int $min, private readonly int $max)
{ {
if ($min > $max) { if ($min > $max) {
throw new Exception('min > max'); throw new Exception('min > max');

@ -13,8 +13,8 @@ class SquareMatrix extends Matrix
$matrixData = []; $matrixData = [];
$allValuesIndex = 0; $allValuesIndex = 0;
for ($currentRow = 0; $currentRow < $size; $currentRow++) { for ($currentRow = 0; $currentRow < $size; ++$currentRow) {
for ($currentColumn = 0; $currentColumn < $size; $currentColumn++) { for ($currentColumn = 0; $currentColumn < $size; ++$currentColumn) {
$matrixData[$currentRow][$currentColumn] = $allValues[$allValuesIndex++]; $matrixData[$currentRow][$currentColumn] = $allValues[$allValuesIndex++];
} }
} }

@ -15,6 +15,7 @@ class Vector extends Matrix
foreach ($vectorValues as $currentVectorValue) { foreach ($vectorValues as $currentVectorValue) {
$columnValues[] = [$currentVectorValue]; $columnValues[] = [$currentVectorValue];
} }
parent::__construct(count($vectorValues), 1, $columnValues); parent::__construct(count($vectorValues), 1, $columnValues);
} }
} }

@ -13,7 +13,7 @@ class PartialPlay
// HACK to get around bug near 0 // HACK to get around bug near 0
$smallestPercentage = 0.0001; $smallestPercentage = 0.0001;
if ($partialPlayPercentage < $smallestPercentage) { if ($partialPlayPercentage < $smallestPercentage) {
$partialPlayPercentage = $smallestPercentage; return $smallestPercentage;
} }
return $partialPlayPercentage; return $partialPlayPercentage;

@ -13,9 +13,9 @@ class Player implements ISupportPartialPlay, ISupportPartialUpdate, \Stringable
private const DEFAULT_PARTIAL_UPDATE_PERCENTAGE = 1.0; private const DEFAULT_PARTIAL_UPDATE_PERCENTAGE = 1.0;
private float $PartialPlayPercentage; private readonly float $PartialPlayPercentage;
private float $PartialUpdatePercentage; private readonly float $PartialUpdatePercentage;
/** /**
* Constructs a player. * Constructs a player.
@ -25,7 +25,7 @@ class Player implements ISupportPartialPlay, ISupportPartialUpdate, \Stringable
* @param float $partialUpdatePercentage Indicated how much of a skill update a player should receive where 0 represents no update and 1.0 represents 100% of the update. * @param float $partialUpdatePercentage Indicated how much of a skill update a player should receive where 0 represents no update and 1.0 represents 100% of the update.
*/ */
public function __construct( public function __construct(
private mixed $Id, private readonly mixed $Id,
float $partialPlayPercentage = self::DEFAULT_PARTIAL_PLAY_PERCENTAGE, float $partialPlayPercentage = self::DEFAULT_PARTIAL_PLAY_PERCENTAGE,
float $partialUpdatePercentage = self::DEFAULT_PARTIAL_UPDATE_PERCENTAGE float $partialUpdatePercentage = self::DEFAULT_PARTIAL_UPDATE_PERCENTAGE
) )

@ -18,7 +18,7 @@ class Rating implements \Stringable
* @param float $standardDeviation The standard deviation of the rating (also known as s). * @param float $standardDeviation The standard deviation of the rating (also known as s).
* @param float|int $conservativeStandardDeviationMultiplier optional The number of standardDeviations to subtract from the mean to achieve a conservative rating. * @param float|int $conservativeStandardDeviationMultiplier optional The number of standardDeviations to subtract from the mean to achieve a conservative rating.
*/ */
public function __construct(private float $mean, private float $standardDeviation, private float|int $conservativeStandardDeviationMultiplier = self::CONSERVATIVE_STANDARD_DEVIATION_MULTIPLIER) public function __construct(private readonly float $mean, private readonly float $standardDeviation, private readonly float|int $conservativeStandardDeviationMultiplier = self::CONSERVATIVE_STANDARD_DEVIATION_MULTIPLIER)
{ {
} }

@ -6,7 +6,7 @@ namespace DNW\Skills;
class RatingContainer class RatingContainer
{ {
private HashMap $playerToRating; private readonly HashMap $playerToRating;
public function __construct() public function __construct()
{ {

@ -12,7 +12,7 @@ use Exception;
abstract class SkillCalculator abstract class SkillCalculator
{ {
protected function __construct( protected function __construct(
private int $supportedOptions, private readonly int $supportedOptions,
private readonly TeamsRange $totalTeamsAllowed, private readonly TeamsRange $totalTeamsAllowed,
private readonly PlayersRange $playersPerTeamAllowed private readonly PlayersRange $playersPerTeamAllowed
) )
@ -70,7 +70,8 @@ abstract class SkillCalculator
if (! $playersPerTeam->isInRange($currentTeam->count())) { if (! $playersPerTeam->isInRange($currentTeam->count())) {
throw new Exception('Player count is not in range'); throw new Exception('Player count is not in range');
} }
$countOfTeams++;
++$countOfTeams;
} }
if (! $totalTeams->isInRange($countOfTeams)) { if (! $totalTeams->isInRange($countOfTeams)) {

@ -9,10 +9,15 @@ class Team extends RatingContainer
public function __construct(Player $player = NULL, Rating $rating = NULL) public function __construct(Player $player = NULL, Rating $rating = NULL)
{ {
parent::__construct(); parent::__construct();
if (!$player instanceof layer) {
if ($player && $rating) { return;
$this->addPlayer($player, $rating);
} }
if (!$rating instanceof Rating) {
return;
}
$this->addPlayer($player, $rating);
} }
public function addPlayer(Player $player, Rating $rating): self public function addPlayer(Player $player, Rating $rating): self

@ -29,6 +29,7 @@ class FactorGraphTrueSkillCalculator extends SkillCalculator
{ {
parent::__construct(SkillCalculatorSupportedOptions::PARTIAL_PLAY | SkillCalculatorSupportedOptions::PARTIAL_UPDATE, TeamsRange::atLeast(2), PlayersRange::atLeast(1)); parent::__construct(SkillCalculatorSupportedOptions::PARTIAL_PLAY | SkillCalculatorSupportedOptions::PARTIAL_UPDATE, TeamsRange::atLeast(2), PlayersRange::atLeast(1));
} }
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
@ -51,6 +52,7 @@ class FactorGraphTrueSkillCalculator extends SkillCalculator
return $factorGraph->getUpdatedRatings(); return $factorGraph->getUpdatedRatings();
} }
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
@ -104,7 +106,7 @@ class FactorGraphTrueSkillCalculator extends SkillCalculator
return new Vector( return new Vector(
self::getPlayerRatingValues( self::getPlayerRatingValues(
$teamAssignmentsList, $teamAssignmentsList,
fn (Rating $rating): float => $rating->getMean() static fn(Rating $rating): float => $rating->getMean()
) )
); );
} }
@ -119,7 +121,7 @@ class FactorGraphTrueSkillCalculator extends SkillCalculator
return new DiagonalMatrix( return new DiagonalMatrix(
self::getPlayerRatingValues( self::getPlayerRatingValues(
$teamAssignmentsList, $teamAssignmentsList,
fn (Rating $rating): float => BasicMath::square($rating->getStandardDeviation()) static fn(Rating $rating): float => BasicMath::square($rating->getStandardDeviation())
) )
); );
} }
@ -171,7 +173,7 @@ class FactorGraphTrueSkillCalculator extends SkillCalculator
$currentColumn = 0; $currentColumn = 0;
for ($i = 0; $i < count($teamAssignmentsList) - 1; $i++) { for ($i = 0; $i < count($teamAssignmentsList) - 1; ++$i) {
$currentTeam = $teamAssignmentsList[$i]; $currentTeam = $teamAssignmentsList[$i];
// Need to add in 0's for all the previous players, since they're not // Need to add in 0's for all the previous players, since they're not
@ -181,7 +183,7 @@ class FactorGraphTrueSkillCalculator extends SkillCalculator
foreach ($currentTeam->getAllPlayers() as $currentPlayer) { foreach ($currentTeam->getAllPlayers() as $currentPlayer) {
$playerAssignments[$currentColumn][] = PartialPlay::getPartialPlayPercentage($currentPlayer); $playerAssignments[$currentColumn][] = PartialPlay::getPartialPlayPercentage($currentPlayer);
// indicates the player is on the team // indicates the player is on the team
$totalPreviousPlayers++; ++$totalPreviousPlayers;
} }
$rowsRemaining = $totalPlayers - $totalPreviousPlayers; $rowsRemaining = $totalPlayers - $totalPreviousPlayers;
@ -190,15 +192,15 @@ class FactorGraphTrueSkillCalculator extends SkillCalculator
foreach ($nextTeam->getAllPlayers() as $nextTeamPlayer) { foreach ($nextTeam->getAllPlayers() as $nextTeamPlayer) {
// Add a -1 * playing time to represent the difference // Add a -1 * playing time to represent the difference
$playerAssignments[$currentColumn][] = -1 * PartialPlay::getPartialPlayPercentage($nextTeamPlayer); $playerAssignments[$currentColumn][] = -1 * PartialPlay::getPartialPlayPercentage($nextTeamPlayer);
$rowsRemaining--; --$rowsRemaining;
} }
for ($ixAdditionalRow = 0; $ixAdditionalRow < $rowsRemaining; $ixAdditionalRow++) { for ($ixAdditionalRow = 0; $ixAdditionalRow < $rowsRemaining; ++$ixAdditionalRow) {
// Pad with zeros // Pad with zeros
$playerAssignments[$currentColumn][] = 0; $playerAssignments[$currentColumn][] = 0;
} }
$currentColumn++; ++$currentColumn;
} }
return Matrix::fromColumnValues($totalPlayers, count($teamAssignmentsList) - 1, $playerAssignments); return Matrix::fromColumnValues($totalPlayers, count($teamAssignmentsList) - 1, $playerAssignments);

@ -16,7 +16,7 @@ use DNW\Skills\TrueSkill\TruncatedGaussianCorrectionFunctions;
*/ */
class GaussianGreaterThanFactor extends GaussianFactor class GaussianGreaterThanFactor extends GaussianFactor
{ {
private float $epsilon; private readonly float $epsilon;
public function __construct(float $epsilon, Variable $variable) public function __construct(float $epsilon, Variable $variable)
{ {

@ -17,7 +17,7 @@ use Exception;
*/ */
class GaussianLikelihoodFactor extends GaussianFactor class GaussianLikelihoodFactor extends GaussianFactor
{ {
private float $precision; private readonly float $precision;
public function __construct(float $betaSquared, Variable $variable1, Variable $variable2) public function __construct(float $betaSquared, Variable $variable1, Variable $variable2)
{ {

@ -15,7 +15,7 @@ use DNW\Skills\Numerics\GaussianDistribution;
*/ */
class GaussianPriorFactor extends GaussianFactor class GaussianPriorFactor extends GaussianFactor
{ {
private GaussianDistribution $newMessage; private readonly GaussianDistribution $newMessage;
public function __construct(float $mean, float $variance, Variable $variable) public function __construct(float $mean, float $variance, Variable $variable)
{ {

@ -30,6 +30,7 @@ class GaussianWeightedSumFactor extends GaussianFactor
* @var array<float[]> $weights * @var array<float[]> $weights
*/ */
private array $weights = []; private array $weights = [];
/** /**
* @var array<float[]> $weightsSquared * @var array<float[]> $weightsSquared
*/ */
@ -48,7 +49,7 @@ class GaussianWeightedSumFactor extends GaussianFactor
$variableWeightsLength = count($variableWeights); $variableWeightsLength = count($variableWeights);
$this->weights[0] = array_fill(0, count($variableWeights), 0); $this->weights[0] = array_fill(0, count($variableWeights), 0);
for ($i = 0; $i < $variableWeightsLength; $i++) { for ($i = 0; $i < $variableWeightsLength; ++$i) {
$weight = &$variableWeights[$i]; $weight = &$variableWeights[$i];
$this->weights[0][$i] = $weight; $this->weights[0][$i] = $weight;
$this->weightsSquared[0][$i] = BasicMath::square($weight); $this->weightsSquared[0][$i] = BasicMath::square($weight);
@ -58,7 +59,7 @@ class GaussianWeightedSumFactor extends GaussianFactor
// 0..n-1 // 0..n-1
$this->variableIndexOrdersForWeights[0] = []; $this->variableIndexOrdersForWeights[0] = [];
for ($i = 0; $i < ($variablesToSumLength + 1); $i++) { for ($i = 0; $i < ($variablesToSumLength + 1); ++$i) {
$this->variableIndexOrdersForWeights[0][] = $i; $this->variableIndexOrdersForWeights[0][] = $i;
} }
@ -70,7 +71,7 @@ class GaussianWeightedSumFactor extends GaussianFactor
// By convention, we'll put the v_0 term at the end // By convention, we'll put the v_0 term at the end
$weightsLength = $variableWeightsLength + 1; $weightsLength = $variableWeightsLength + 1;
for ($weightsIndex = 1; $weightsIndex < $weightsLength; $weightsIndex++) { for ($weightsIndex = 1; $weightsIndex < $weightsLength; ++$weightsIndex) {
$currentWeights = \array_fill(0, $variableWeightsLength, 0); $currentWeights = \array_fill(0, $variableWeightsLength, 0);
$variableIndices = \array_fill(0, $variableWeightsLength + 1, 0); $variableIndices = \array_fill(0, $variableWeightsLength + 1, 0);
@ -82,7 +83,7 @@ class GaussianWeightedSumFactor extends GaussianFactor
// This is helpful since we skip over one of the spots // This is helpful since we skip over one of the spots
$currentDestinationWeightIndex = 0; $currentDestinationWeightIndex = 0;
for ($currentWeightSourceIndex = 0; $currentWeightSourceIndex < $variableWeightsLength; $currentWeightSourceIndex++) { for ($currentWeightSourceIndex = 0; $currentWeightSourceIndex < $variableWeightsLength; ++$currentWeightSourceIndex) {
if ($currentWeightSourceIndex === $weightsIndex - 1) { if ($currentWeightSourceIndex === $weightsIndex - 1) {
continue; continue;
} }
@ -98,7 +99,7 @@ class GaussianWeightedSumFactor extends GaussianFactor
$currentWeightsSquared[$currentDestinationWeightIndex] = $currentWeight * $currentWeight; $currentWeightsSquared[$currentDestinationWeightIndex] = $currentWeight * $currentWeight;
$variableIndices[$currentDestinationWeightIndex + 1] = $currentWeightSourceIndex + 1; $variableIndices[$currentDestinationWeightIndex + 1] = $currentWeightSourceIndex + 1;
$currentDestinationWeightIndex++; ++$currentDestinationWeightIndex;
} }
// And the final one // And the final one
@ -108,6 +109,7 @@ class GaussianWeightedSumFactor extends GaussianFactor
// HACK: Getting around division by zero // HACK: Getting around division by zero
$finalWeight = 0; $finalWeight = 0;
} }
$currentWeights[$currentDestinationWeightIndex] = $finalWeight; $currentWeights[$currentDestinationWeightIndex] = $finalWeight;
$currentWeightsSquared[$currentDestinationWeightIndex] = BasicMath::square($finalWeight); $currentWeightsSquared[$currentDestinationWeightIndex] = BasicMath::square($finalWeight);
$variableIndices[count($variableWeights)] = 0; $variableIndices[count($variableWeights)] = 0;
@ -125,15 +127,17 @@ class GaussianWeightedSumFactor extends GaussianFactor
} }
} }
public function getLogNormalization() public function getLogNormalization(): float
{ {
$vars = $this->getVariables(); $vars = $this->getVariables();
$messages = $this->getMessages(); $messages = $this->getMessages();
$result = 0.0; $result = 0.0;
// We start at 1 since offset 0 has the sum
$counter = count($vars);
// We start at 1 since offset 0 has the sum // We start at 1 since offset 0 has the sum
for ($i = 1; $i < count($vars); $i++) { for ($i = 1; $i < $counter; ++$i) {
$result += GaussianDistribution::logRatioNormalization($vars[$i]->getValue(), $messages[$i]->getValue()); $result += GaussianDistribution::logRatioNormalization($vars[$i]->getValue(), $messages[$i]->getValue());
} }
@ -162,7 +166,7 @@ class GaussianWeightedSumFactor extends GaussianFactor
$weightsSquaredLength = count($weightsSquared); $weightsSquaredLength = count($weightsSquared);
for ($i = 0; $i < $weightsSquaredLength; $i++) { for ($i = 0; $i < $weightsSquaredLength; ++$i) {
// These flow directly from the paper // These flow directly from the paper
$inverseOfNewPrecisionSum += $weightsSquared[$i] / $inverseOfNewPrecisionSum += $weightsSquared[$i] /
@ -211,11 +215,15 @@ class GaussianWeightedSumFactor extends GaussianFactor
$updatedVariables = []; $updatedVariables = [];
$indicesToUse = $this->variableIndexOrdersForWeights[$messageIndex]; $indicesToUse = $this->variableIndexOrdersForWeights[$messageIndex];
// The tricky part here is that we have to put the messages and variables in the same
// order as the weights. Thankfully, the weights and messages share the same index numbers,
// so we just need to make sure they're consistent
$counter = count($allMessages);
// The tricky part here is that we have to put the messages and variables in the same // The tricky part here is that we have to put the messages and variables in the same
// order as the weights. Thankfully, the weights and messages share the same index numbers, // order as the weights. Thankfully, the weights and messages share the same index numbers,
// so we just need to make sure they're consistent // so we just need to make sure they're consistent
for ($i = 0; $i < count($allMessages); $i++) { for ($i = 0; $i < $counter; ++$i) {
$updatedMessages[] = $allMessages[$indicesToUse[$i]]; $updatedMessages[] = $allMessages[$indicesToUse[$i]];
$updatedVariables[] = $allVariables[$indicesToUse[$i]]; $updatedVariables[] = $allVariables[$indicesToUse[$i]];
} }
@ -239,7 +247,7 @@ class GaussianWeightedSumFactor extends GaussianFactor
$result .= ' = '; $result .= ' = ';
$totalVars = count($variablesToSum); $totalVars = count($variablesToSum);
for ($i = 0; $i < $totalVars; $i++) { for ($i = 0; $i < $totalVars; ++$i) {
$isFirst = ($i == 0); $isFirst = ($i == 0);
if ($isFirst && ($weights[$i] < 0)) { if ($isFirst && ($weights[$i] < 0)) {

@ -16,7 +16,7 @@ use DNW\Skills\TrueSkill\TruncatedGaussianCorrectionFunctions;
*/ */
class GaussianWithinFactor extends GaussianFactor class GaussianWithinFactor extends GaussianFactor
{ {
private float $epsilon; private readonly float $epsilon;
public function __construct(float $epsilon, Variable $variable) public function __construct(float $epsilon, Variable $variable)
{ {

@ -113,7 +113,7 @@ class IteratedTeamDifferencesInnerLayer extends TrueSkillFactorGraphLayer
$forwardScheduleList = []; $forwardScheduleList = [];
for ($i = 0; $i < $totalTeamDifferences - 1; $i++) { for ($i = 0; $i < $totalTeamDifferences - 1; ++$i) {
$teamPerformancesToTeamPerformanceDifferencesLayerLocalFactors = $this->TeamPerformancesToTeamPerformanceDifferencesLayer->getLocalFactors(); $teamPerformancesToTeamPerformanceDifferencesLayerLocalFactors = $this->TeamPerformancesToTeamPerformanceDifferencesLayer->getLocalFactors();
$teamDifferencesComparisonLayerLocalFactors = $this->TeamDifferencesComparisonLayer->getLocalFactors(); $teamDifferencesComparisonLayerLocalFactors = $this->TeamDifferencesComparisonLayer->getLocalFactors();
@ -149,7 +149,7 @@ class IteratedTeamDifferencesInnerLayer extends TrueSkillFactorGraphLayer
$backwardScheduleList = []; $backwardScheduleList = [];
for ($i = 0; $i < $totalTeamDifferences - 1; $i++) { for ($i = 0; $i < $totalTeamDifferences - 1; ++$i) {
$teamPerformancesToTeamPerformanceDifferencesLayerLocalFactors = $this->TeamPerformancesToTeamPerformanceDifferencesLayer->getLocalFactors(); $teamPerformancesToTeamPerformanceDifferencesLayerLocalFactors = $this->TeamPerformancesToTeamPerformanceDifferencesLayer->getLocalFactors();
$teamDifferencesComparisonLayerLocalFactors = $this->TeamDifferencesComparisonLayer->getLocalFactors(); $teamDifferencesComparisonLayerLocalFactors = $this->TeamDifferencesComparisonLayer->getLocalFactors();

@ -37,7 +37,7 @@ class PlayerPerformancesToTeamPerformancesLayer extends TrueSkillFactorGraphLaye
return $this->scheduleSequence( return $this->scheduleSequence(
array_map( array_map(
fn ($weightedSumFactor) => new ScheduleStep('Perf to Team Perf Step', $weightedSumFactor, 0), static fn($weightedSumFactor): ScheduleStep => new ScheduleStep('Perf to Team Perf Step', $weightedSumFactor, 0),
$localFactors $localFactors
), ),
'all player perf to team perf schedule' 'all player perf to team perf schedule'
@ -50,9 +50,8 @@ class PlayerPerformancesToTeamPerformancesLayer extends TrueSkillFactorGraphLaye
protected function createPlayerToTeamSumFactor(array $teamMembers, Variable $sumVariable): GaussianWeightedSumFactor protected function createPlayerToTeamSumFactor(array $teamMembers, Variable $sumVariable): GaussianWeightedSumFactor
{ {
$weights = array_map( $weights = array_map(
function ($v) { static function ($v): float {
$player = $v->getKey(); $player = $v->getKey();
return PartialPlay::getPartialPlayPercentage($player); return PartialPlay::getPartialPlayPercentage($player);
}, },
$teamMembers $teamMembers
@ -72,7 +71,7 @@ class PlayerPerformancesToTeamPerformancesLayer extends TrueSkillFactorGraphLaye
foreach ($localFactors as $currentFactor) { foreach ($localFactors as $currentFactor) {
$localCurrentFactor = $currentFactor; $localCurrentFactor = $currentFactor;
$numberOfMessages = $localCurrentFactor->getNumberOfMessages(); $numberOfMessages = $localCurrentFactor->getNumberOfMessages();
for ($currentIteration = 1; $currentIteration < $numberOfMessages; $currentIteration++) { for ($currentIteration = 1; $currentIteration < $numberOfMessages; ++$currentIteration) {
$allFactors[] = new ScheduleStep( $allFactors[] = new ScheduleStep(
'team sum perf @' . $currentIteration, 'team sum perf @' . $currentIteration,
$localCurrentFactor, $localCurrentFactor,
@ -89,7 +88,7 @@ class PlayerPerformancesToTeamPerformancesLayer extends TrueSkillFactorGraphLaye
*/ */
private function createOutputVariable(array $team): Variable private function createOutputVariable(array $team): Variable
{ {
$memberNames = array_map(fn ($currentPlayer) => (string)($currentPlayer->getKey()), $team); $memberNames = array_map(static fn($currentPlayer): string => (string)($currentPlayer->getKey()), $team);
$teamMemberNames = \implode(', ', $memberNames); $teamMemberNames = \implode(', ', $memberNames);

@ -55,7 +55,7 @@ class PlayerPriorValuesToSkillsLayer extends TrueSkillFactorGraphLayer
return $this->scheduleSequence( return $this->scheduleSequence(
array_map( array_map(
fn ($prior) => new ScheduleStep('Prior to Skill Step', $prior, 0), static fn($prior): ScheduleStep => new ScheduleStep('Prior to Skill Step', $prior, 0),
$localFactors $localFactors
), ),
'All priors' 'All priors'

@ -53,7 +53,7 @@ class PlayerSkillsToPerformancesLayer extends TrueSkillFactorGraphLayer
return $this->scheduleSequence( return $this->scheduleSequence(
array_map( array_map(
fn ($likelihood) => new ScheduleStep('Skill to Perf step', $likelihood, 0), static fn($likelihood): ScheduleStep => new ScheduleStep('Skill to Perf step', $likelihood, 0),
$localFactors $localFactors
), ),
'All skill to performance sending' 'All skill to performance sending'
@ -66,7 +66,7 @@ class PlayerSkillsToPerformancesLayer extends TrueSkillFactorGraphLayer
return $this->scheduleSequence( return $this->scheduleSequence(
array_map( array_map(
fn ($likelihood) => new ScheduleStep('name', $likelihood, 1), static fn($likelihood): ScheduleStep => new ScheduleStep('name', $likelihood, 1),
$localFactors $localFactors
), ),
'All skill to performance sending' 'All skill to performance sending'

@ -11,7 +11,7 @@ use DNW\Skills\TrueSkill\TrueSkillFactorGraph;
class TeamDifferencesComparisonLayer extends TrueSkillFactorGraphLayer class TeamDifferencesComparisonLayer extends TrueSkillFactorGraphLayer
{ {
private float $epsilon; private readonly float $epsilon;
/** /**
* @param int[] $teamRanks * @param int[] $teamRanks
@ -28,7 +28,7 @@ class TeamDifferencesComparisonLayer extends TrueSkillFactorGraphLayer
$inputVarGroups = $this->getInputVariablesGroups(); $inputVarGroups = $this->getInputVariablesGroups();
$inputVarGroupsCount = count($inputVarGroups); $inputVarGroupsCount = count($inputVarGroups);
for ($i = 0; $i < $inputVarGroupsCount; $i++) { for ($i = 0; $i < $inputVarGroupsCount; ++$i) {
$isDraw = ($this->teamRanks[$i] == $this->teamRanks[$i + 1]); $isDraw = ($this->teamRanks[$i] == $this->teamRanks[$i + 1]);
$teamDifference = $inputVarGroups[$i][0]; $teamDifference = $inputVarGroups[$i][0];

@ -15,7 +15,7 @@ class TeamPerformancesToTeamPerformanceDifferencesLayer extends TrueSkillFactorG
$inputVariablesGroupsCount = count($inputVariablesGroups); $inputVariablesGroupsCount = count($inputVariablesGroups);
$outputVariablesGroup = &$this->getOutputVariablesGroups(); $outputVariablesGroup = &$this->getOutputVariablesGroups();
for ($i = 0; $i < $inputVariablesGroupsCount - 1; $i++) { for ($i = 0; $i < $inputVariablesGroupsCount - 1; ++$i) {
$strongerTeam = $inputVariablesGroups[$i][0]; $strongerTeam = $inputVariablesGroups[$i][0];
$weakerTeam = $inputVariablesGroups[$i + 1][0]; $weakerTeam = $inputVariablesGroups[$i + 1][0];

@ -28,7 +28,7 @@ class TrueSkillFactorGraph extends FactorGraph
*/ */
private array $layers; private array $layers;
private PlayerPriorValuesToSkillsLayer $priorLayer; private readonly PlayerPriorValuesToSkillsLayer $priorLayer;
/** /**
* @param GameInfo $gameInfo Parameters for the game. * @param GameInfo $gameInfo Parameters for the game.
@ -39,7 +39,7 @@ class TrueSkillFactorGraph extends FactorGraph
{ {
$this->priorLayer = new PlayerPriorValuesToSkillsLayer($this, $teams); $this->priorLayer = new PlayerPriorValuesToSkillsLayer($this, $teams);
$newFactory = new VariableFactory( $newFactory = new VariableFactory(
fn () => GaussianDistribution::fromPrecisionMean(0, 0) static fn(): GaussianDistribution => GaussianDistribution::fromPrecisionMean(0, 0)
); );
$this->setVariableFactory($newFactory); $this->setVariableFactory($newFactory);

@ -28,6 +28,7 @@ class TwoTeamTrueSkillCalculator extends SkillCalculator
{ {
parent::__construct(SkillCalculatorSupportedOptions::NONE, TeamsRange::exactly(2), PlayersRange::atLeast(1)); parent::__construct(SkillCalculatorSupportedOptions::NONE, TeamsRange::exactly(2), PlayersRange::atLeast(1));
} }
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
@ -82,12 +83,12 @@ class TwoTeamTrueSkillCalculator extends SkillCalculator
$totalPlayers = $selfTeam->count() + $otherTeam->count(); $totalPlayers = $selfTeam->count() + $otherTeam->count();
$meanGetter = fn (Rating $currentRating): float => $currentRating->getMean(); $meanGetter = static fn(Rating $currentRating): float => $currentRating->getMean();
$selfMeanSum = BasicMath::sum($selfTeam->getAllRatings(), $meanGetter); $selfMeanSum = BasicMath::sum($selfTeam->getAllRatings(), $meanGetter);
$otherTeamMeanSum = BasicMath::sum($otherTeam->getAllRatings(), $meanGetter); $otherTeamMeanSum = BasicMath::sum($otherTeam->getAllRatings(), $meanGetter);
$varianceGetter = fn (Rating $currentRating): float => BasicMath::square($currentRating->getStandardDeviation()); $varianceGetter = static fn(Rating $currentRating): float => BasicMath::square($currentRating->getStandardDeviation());
$c = sqrt( $c = sqrt(
BasicMath::sum($selfTeam->getAllRatings(), $varianceGetter) BasicMath::sum($selfTeam->getAllRatings(), $varianceGetter)
@ -163,9 +164,9 @@ class TwoTeamTrueSkillCalculator extends SkillCalculator
$betaSquared = BasicMath::square($gameInfo->getBeta()); $betaSquared = BasicMath::square($gameInfo->getBeta());
$meanGetter = fn (Rating $currentRating): float => $currentRating->getMean(); $meanGetter = static fn(Rating $currentRating): float => $currentRating->getMean();
$varianceGetter = fn (Rating $currentRating): float => BasicMath::square($currentRating->getStandardDeviation()); $varianceGetter = static fn(Rating $currentRating): float => BasicMath::square($currentRating->getStandardDeviation());
$team1MeanSum = BasicMath::sum($team1Ratings, $meanGetter); $team1MeanSum = BasicMath::sum($team1Ratings, $meanGetter);
$team1StdDevSquared = BasicMath::sum($team1Ratings, $varianceGetter); $team1StdDevSquared = BasicMath::sum($team1Ratings, $varianceGetter);

@ -20,12 +20,8 @@ class BasicMathTest extends TestCase
{ {
$arr = [1, 1, 1, 1]; $arr = [1, 1, 1, 1];
$func_return = function (float $f): float { $func_return = static fn(float $f): float => $f;
return $f; $func_double = static fn(float $f): float => $f * 2;
};
$func_double = function (float $f): float {
return $f * 2;
};
$this->assertEquals(4, BasicMath::sum($arr, $func_return)); $this->assertEquals(4, BasicMath::sum($arr, $func_return));
$this->assertEquals(8, BasicMath::sum($arr, $func_double)); $this->assertEquals(8, BasicMath::sum($arr, $func_double));
} }

@ -265,4 +265,5 @@ class MatrixTest extends TestCase
Matrix::multiply($m1, $m2); Matrix::multiply($m1, $m2);
} }
} }
// phpcs:enable // phpcs:enable

@ -13,13 +13,13 @@ class RangeTest extends TestCase
public function testConstructInvalidParam(): void public function testConstructInvalidParam(): void
{ {
$this->expectException(Exception::class); $this->expectException(Exception::class);
$range = new Range(10, 5); new Range(10, 5);
} }
public function testFactoryInclusiveInvalidParam(): void public function testFactoryInclusiveInvalidParam(): void
{ {
$this->expectException(Exception::class); $this->expectException(Exception::class);
$range = Range::inclusive(10, 5); Range::inclusive(10, 5);
} }
public function testNormalUse(): void public function testNormalUse(): void