Bit foies for static code analysis.

This commit is contained in:
2026-03-09 11:44:13 +00:00
parent 58aee11808
commit 0b75519947
8 changed files with 305 additions and 29 deletions

View File

@@ -1,12 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<phive xmlns="https://phar.io/phive"> <phive xmlns="https://phar.io/phive">
<phar name="phpmd" version="^2.15.0" installed="2.15.0" location="./tools/phpmd" copy="false"/> <phar name="phpmd" version="^2.15.0" installed="2.15.0" location="./tools/phpmd" copy="false"/>
<phar name="phpstan" version="^2.1.12" installed="2.1.39" location="./tools/phpstan" copy="false"/> <phar name="phpstan" version="^2.1.12" installed="2.1.40" location="./tools/phpstan" copy="false"/>
<phar name="psalm" version="^7.0.0-beta6" installed="7.0.0-beta16" location="./tools/psalm" copy="false"/> <phar name="psalm" version="^7.0.0-beta6" installed="7.0.0-beta16" location="./tools/psalm" copy="false"/>
<phar name="phpcs" version="^3.12.2" installed="3.13.5" location="./tools/phpcs" copy="false"/> <phar name="phpcs" version="^3.12.2" installed="3.13.5" location="./tools/phpcs" copy="false"/>
<phar name="phpcbf" version="^3.12.2" installed="3.13.5" location="./tools/phpcbf" copy="false"/> <phar name="phpcbf" version="^3.12.2" installed="3.13.5" location="./tools/phpcbf" copy="false"/>
<phar name="phpdocumentor" version="^3.7.1" installed="3.9.1" location="./tools/phpdocumentor" copy="false"/> <phar name="phpdocumentor" version="^3.7.1" installed="3.9.1" location="./tools/phpdocumentor" copy="false"/>
<phar name="phpbench" version="^1.4.1" installed="1.4.3" location="./tools/phpbench" copy="false"/> <phar name="phpbench" version="^1.4.1" installed="1.5.1" location="./tools/phpbench" copy="false"/>
<phar name="infection" version="^0.29.14" installed="0.29.14" location="./tools/infection" copy="false"/> <phar name="infection" version="^0.29.14" installed="0.29.14" location="./tools/infection" copy="false"/>
<phar name="phpunit" version="^12.1.3" installed="12.5.14" location="./tools/phpunit" copy="false"/> <phar name="phpunit" version="^12.1.3" installed="12.5.14" location="./tools/phpunit" copy="false"/>
</phive> </phive>

8
composer.lock generated
View File

@@ -456,11 +456,11 @@
}, },
{ {
"name": "phpstan/phpstan", "name": "phpstan/phpstan",
"version": "1.12.32", "version": "1.12.33",
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/2770dcdf5078d0b0d53f94317e06affe88419aa8", "url": "https://api.github.com/repos/phpstan/phpstan/zipball/37982d6fc7cbb746dda7773530cda557cdf119e1",
"reference": "2770dcdf5078d0b0d53f94317e06affe88419aa8", "reference": "37982d6fc7cbb746dda7773530cda557cdf119e1",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -505,7 +505,7 @@
"type": "github" "type": "github"
} }
], ],
"time": "2025-09-30T10:16:31+00:00" "time": "2026-02-28T20:30:03+00:00"
}, },
{ {
"name": "phpunit/php-code-coverage", "name": "phpunit/php-code-coverage",

288
psalm-baseline.xml Normal file
View File

@@ -0,0 +1,288 @@
<?xml version="1.0" encoding="UTF-8"?>
<files psalm-version="7.0.0-beta16@491dd740b8862db7d4fe8c1f6c161055c32ad651">
<file src="src/FactorGraphs/Factor.php">
<MissingAbstractPureAnnotation>
<code><![CDATA[createVariableToMessageBinding]]></code>
<code><![CDATA[sendMessageVariable]]></code>
</MissingAbstractPureAnnotation>
<MissingPureAnnotation>
<code><![CDATA[__construct]]></code>
<code><![CDATA[getLogNormalization]]></code>
<code><![CDATA[getNumberOfMessages]]></code>
<code><![CDATA[updateMessageVariable]]></code>
</MissingPureAnnotation>
<MixedArgument>
<code><![CDATA[$variable]]></code>
<code><![CDATA[$variable]]></code>
</MixedArgument>
<MixedAssignment>
<code><![CDATA[$currentVariable]]></code>
<code><![CDATA[$variable]]></code>
<code><![CDATA[$variable]]></code>
</MixedAssignment>
<MixedMethodCall>
<code><![CDATA[resetToPrior]]></code>
</MixedMethodCall>
</file>
<file src="src/FactorGraphs/FactorGraph.php">
<MissingPureAnnotation>
<code><![CDATA[setVariableFactory]]></code>
</MissingPureAnnotation>
</file>
<file src="src/FactorGraphs/FactorGraphLayer.php">
<MissingAbstractPureAnnotation>
<code><![CDATA[buildLayer]]></code>
</MissingAbstractPureAnnotation>
<MissingPureAnnotation>
<code><![CDATA[__construct]]></code>
<code><![CDATA[addLayerFactor]]></code>
<code><![CDATA[createPosteriorSchedule]]></code>
<code><![CDATA[createPriorSchedule]]></code>
<code><![CDATA[getLocalFactors]]></code>
<code><![CDATA[setInputVariablesGroups]]></code>
</MissingPureAnnotation>
</file>
<file src="src/FactorGraphs/FactorList.php">
<MissingPureAnnotation>
<code><![CDATA[addFactor]]></code>
<code><![CDATA[count]]></code>
</MissingPureAnnotation>
</file>
<file src="src/FactorGraphs/KeyedVariable.php">
<MixedArgument>
<code><![CDATA[$prior]]></code>
</MixedArgument>
</file>
<file src="src/FactorGraphs/Message.php">
<MissingImmutableAnnotation>
<code><![CDATA[Message]]></code>
</MissingImmutableAnnotation>
<MissingPureAnnotation>
<code><![CDATA[__construct]]></code>
<code><![CDATA[setValue]]></code>
</MissingPureAnnotation>
</file>
<file src="src/FactorGraphs/Schedule.php">
<MissingAbstractPureAnnotation>
<code><![CDATA[visit]]></code>
</MissingAbstractPureAnnotation>
<MissingImmutableAnnotation>
<code><![CDATA[Schedule]]></code>
</MissingImmutableAnnotation>
</file>
<file src="src/FactorGraphs/ScheduleLoop.php">
<MissingPureAnnotation>
<code><![CDATA[__construct]]></code>
</MissingPureAnnotation>
</file>
<file src="src/FactorGraphs/ScheduleSequence.php">
<MissingPureAnnotation>
<code><![CDATA[__construct]]></code>
</MissingPureAnnotation>
</file>
<file src="src/FactorGraphs/ScheduleStep.php">
<MissingPureAnnotation>
<code><![CDATA[__construct]]></code>
</MissingPureAnnotation>
</file>
<file src="src/FactorGraphs/Variable.php">
<MissingImmutableAnnotation>
<code><![CDATA[Variable]]></code>
</MissingImmutableAnnotation>
<MissingPureAnnotation>
<code><![CDATA[__construct]]></code>
<code><![CDATA[resetToPrior]]></code>
<code><![CDATA[setValue]]></code>
</MissingPureAnnotation>
</file>
<file src="src/FactorGraphs/VariableFactory.php">
<MissingPureAnnotation>
<code><![CDATA[__construct]]></code>
</MissingPureAnnotation>
<MixedArgument>
<code><![CDATA[$initializer()]]></code>
</MixedArgument>
</file>
<file src="src/GameInfo.php">
<MissingPureAnnotation>
<code><![CDATA[__construct]]></code>
</MissingPureAnnotation>
</file>
<file src="src/Guard.php">
<MissingImmutableAnnotation>
<code><![CDATA[Guard]]></code>
</MissingImmutableAnnotation>
<MissingPureAnnotation>
<code><![CDATA[argumentInRangeInclusive]]></code>
<code><![CDATA[argumentIsValidIndex]]></code>
</MissingPureAnnotation>
</file>
<file src="src/HashMap.php">
<MissingImmutableAnnotation>
<code><![CDATA[HashMap]]></code>
</MissingImmutableAnnotation>
<MissingPureAnnotation>
<code><![CDATA[count]]></code>
<code><![CDATA[getAllKeys]]></code>
<code><![CDATA[getAllValues]]></code>
<code><![CDATA[getValue]]></code>
<code><![CDATA[setValue]]></code>
</MissingPureAnnotation>
</file>
<file src="src/ISupportPartialPlay.php">
<MissingAbstractPureAnnotation>
<code><![CDATA[getPartialPlayPercentage]]></code>
</MissingAbstractPureAnnotation>
<MissingInterfaceImmutableAnnotation>
<code><![CDATA[ISupportPartialPlay]]></code>
</MissingInterfaceImmutableAnnotation>
</file>
<file src="src/ISupportPartialUpdate.php">
<MissingAbstractPureAnnotation>
<code><![CDATA[getPartialUpdatePercentage]]></code>
</MissingAbstractPureAnnotation>
<MissingInterfaceImmutableAnnotation>
<code><![CDATA[ISupportPartialUpdate]]></code>
</MissingInterfaceImmutableAnnotation>
</file>
<file src="src/Numerics/BasicMath.php">
<MissingPureAnnotation>
<code><![CDATA[square]]></code>
</MissingPureAnnotation>
</file>
<file src="src/Numerics/GaussianDistribution.php">
<MissingPureAnnotation>
<code><![CDATA[absoluteDifference]]></code>
<code><![CDATA[errorFunctionCumulativeTo]]></code>
<code><![CDATA[getNormalizationConstant]]></code>
</MissingPureAnnotation>
</file>
<file src="src/Numerics/Matrix.php">
<MissingPureAnnotation>
<code><![CDATA[__construct]]></code>
<code><![CDATA[checkRowCol]]></code>
<code><![CDATA[isSquare]]></code>
</MissingPureAnnotation>
</file>
<file src="src/Numerics/Range.php">
<MissingPureAnnotation>
<code><![CDATA[__construct]]></code>
<code><![CDATA[isInRange]]></code>
</MissingPureAnnotation>
</file>
<file src="src/PartialPlay.php">
<MissingImmutableAnnotation>
<code><![CDATA[PartialPlay]]></code>
</MissingImmutableAnnotation>
<MissingPureAnnotation>
<code><![CDATA[getPartialPlayPercentage]]></code>
</MissingPureAnnotation>
</file>
<file src="src/RankSorter.php">
<MissingImmutableAnnotation>
<code><![CDATA[RankSorter]]></code>
</MissingImmutableAnnotation>
<MissingPureAnnotation>
<code><![CDATA[sort]]></code>
</MissingPureAnnotation>
<MixedReturnTypeCoercion>
<code><![CDATA[$teams]]></code>
<code><![CDATA[array<int>]]></code>
</MixedReturnTypeCoercion>
</file>
<file src="src/Rating.php">
<MissingPureAnnotation>
<code><![CDATA[__construct]]></code>
<code><![CDATA[getConservativeRating]]></code>
</MissingPureAnnotation>
</file>
<file src="src/RatingContainer.php">
<MissingPureAnnotation>
<code><![CDATA[__construct]]></code>
</MissingPureAnnotation>
<MixedReturnStatement>
<code><![CDATA[$this->playerToRating->getValue($player)]]></code>
</MixedReturnStatement>
<MixedReturnTypeCoercion>
<code><![CDATA[$this->playerToRating->getAllKeys()]]></code>
<code><![CDATA[$this->playerToRating->getAllValues()]]></code>
<code><![CDATA[Player[]]]></code>
<code><![CDATA[Rating[]]]></code>
</MixedReturnTypeCoercion>
</file>
<file src="src/SkillCalculator.php">
<MissingAbstractPureAnnotation>
<code><![CDATA[calculateMatchQuality]]></code>
<code><![CDATA[calculateNewRatings]]></code>
</MissingAbstractPureAnnotation>
<MissingPureAnnotation>
<code><![CDATA[__construct]]></code>
<code><![CDATA[isSupported]]></code>
</MissingPureAnnotation>
</file>
<file src="src/TrueSkill/FactorGraphTrueSkillCalculator.php">
<MixedArgumentTypeCoercion>
<code><![CDATA[$teams]]></code>
</MixedArgumentTypeCoercion>
<MixedAssignment>
<code><![CDATA[$playerRatingValues[]]]></code>
</MixedAssignment>
<MixedReturnTypeCoercion>
<code><![CDATA[$playerRatingValues]]></code>
<code><![CDATA[int[]]]></code>
</MixedReturnTypeCoercion>
</file>
<file src="src/TrueSkill/Factors/GaussianWeightedSumFactor.php">
<InvalidPropertyAssignmentValue>
<code><![CDATA[$this->varIndexOrdersForWeights]]></code>
</InvalidPropertyAssignmentValue>
</file>
<file src="src/TrueSkill/Layers/PlayerPerformancesToTeamPerformancesLayer.php">
<MixedArgument>
<code><![CDATA[$player]]></code>
</MixedArgument>
<MixedAssignment>
<code><![CDATA[$player]]></code>
</MixedAssignment>
<UnsupportedReferenceUsage>
<code><![CDATA[$outputVarGroups = &$this->getOutputVariablesGroups()]]></code>
</UnsupportedReferenceUsage>
</file>
<file src="src/TrueSkill/Layers/PlayerPriorValuesToSkillsLayer.php">
<UnsupportedReferenceUsage>
<code><![CDATA[$outputVariablesGroups = &$this->getOutputVariablesGroups()]]></code>
</UnsupportedReferenceUsage>
</file>
<file src="src/TrueSkill/Layers/PlayerSkillsToPerformancesLayer.php">
<MixedAssignment>
<code><![CDATA[$currentPlayer]]></code>
</MixedAssignment>
<UnsupportedReferenceUsage>
<code><![CDATA[$outputVarGroups = &$this->getOutputVariablesGroups()]]></code>
</UnsupportedReferenceUsage>
</file>
<file src="src/TrueSkill/Layers/TeamPerformancesToTeamPerformanceDifferencesLayer.php">
<UnsupportedReferenceUsage>
<code><![CDATA[$outputVariablesGroup = &$this->getOutputVariablesGroups()]]></code>
</UnsupportedReferenceUsage>
</file>
<file src="src/TrueSkill/TrueSkillFactorGraph.php">
<MixedArgument>
<code><![CDATA[$localCurrentPlayer]]></code>
</MixedArgument>
<MixedAssignment>
<code><![CDATA[$localCurrentPlayer]]></code>
</MixedAssignment>
</file>
<file src="tests/SkillCalculatorTest.php">
<DeprecatedMethod>
<code><![CDATA[getMockForAbstractClass]]></code>
</DeprecatedMethod>
</file>
<file src="tests/TrueSkill/FactorGraphTrueSkillCalculatorTest.php">
<MixedArrayOffset>
<code><![CDATA[$expected[$player->getId()]]]></code>
<code><![CDATA[$expected[$player->getId()]]]></code>
</MixedArrayOffset>
</file>
</files>

View File

@@ -1,12 +1,13 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<psalm <psalm
errorLevel="7" errorLevel="1"
resolveFromConfigFile="true" resolveFromConfigFile="true"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="https://getpsalm.org/schema/config" xmlns="https://getpsalm.org/schema/config"
xsi:schemaLocation="https://getpsalm.org/schema/config vendor/vimeo/psalm/config.xsd" xsi:schemaLocation="https://getpsalm.org/schema/config vendor/vimeo/psalm/config.xsd"
findUnusedBaselineEntry="true" findUnusedBaselineEntry="true"
findUnusedCode="false" findUnusedCode="false"
errorBaseline="psalm-baseline.xml"
> >
<projectFiles> <projectFiles>
<directory name="src"/> <directory name="src"/>

View File

@@ -8,11 +8,11 @@ use DNW\Skills\Numerics\GaussianDistribution;
class Variable class Variable
{ {
private mixed $value; private GaussianDistribution $value;
public function __construct(private readonly GaussianDistribution $prior) public function __construct(private readonly GaussianDistribution $prior)
{ {
$this->resetToPrior(); $this->value = $prior;
} }
public function getValue(): GaussianDistribution public function getValue(): GaussianDistribution

View File

@@ -29,9 +29,6 @@ final class FactorGraphTrueSkillCalculator extends SkillCalculator
parent::__construct(SkillCalculator::PARTIAL_PLAY | SkillCalculator::PARTIAL_UPDATE, TeamsRange::atLeast(2), PlayersRange::atLeast(1)); parent::__construct(SkillCalculator::PARTIAL_PLAY | SkillCalculator::PARTIAL_UPDATE, TeamsRange::atLeast(2), PlayersRange::atLeast(1));
} }
/**
* {@inheritdoc}
*/
#[\Override] #[\Override]
public function calculateNewRatings( public function calculateNewRatings(
GameInfo $gameInfo, GameInfo $gameInfo,
@@ -52,9 +49,6 @@ final class FactorGraphTrueSkillCalculator extends SkillCalculator
return $factorGraph->getUpdatedRatings(); return $factorGraph->getUpdatedRatings();
} }
/**
* {@inheritdoc}
*/
#[\Override] #[\Override]
public function calculateMatchQuality(GameInfo $gameInfo, array $teams): float public function calculateMatchQuality(GameInfo $gameInfo, array $teams): float
{ {

View File

@@ -5,7 +5,7 @@ declare(strict_types=1);
namespace DNW\Skills\TrueSkill; namespace DNW\Skills\TrueSkill;
use DNW\Skills\GameInfo; use DNW\Skills\GameInfo;
use DNW\Skills\Guard; use DNW\Skills\Team;
use DNW\Skills\Numerics\BasicMath; use DNW\Skills\Numerics\BasicMath;
use DNW\Skills\PairwiseComparison; use DNW\Skills\PairwiseComparison;
use DNW\Skills\PlayersRange; use DNW\Skills\PlayersRange;
@@ -28,9 +28,6 @@ final class TwoPlayerTrueSkillCalculator extends SkillCalculator
parent::__construct(SkillCalculator::NONE, TeamsRange::exactly(2), PlayersRange::exactly(1)); parent::__construct(SkillCalculator::NONE, TeamsRange::exactly(2), PlayersRange::exactly(1));
} }
/**
* {@inheritdoc}
*/
#[\Override] #[\Override]
public function calculateNewRatings(GameInfo $gameInfo, array $teams, array $teamRanks): RatingContainer public function calculateNewRatings(GameInfo $gameInfo, array $teams, array $teamRanks): RatingContainer
{ {
@@ -39,7 +36,9 @@ final class TwoPlayerTrueSkillCalculator extends SkillCalculator
// Make sure things are in order // Make sure things are in order
RankSorter::sort($teams, $teamRanks); RankSorter::sort($teams, $teamRanks);
/**
* @var Team[] $teams
*/
// Since we verified that each team has one player, we know the player is the first one // Since we verified that each team has one player, we know the player is the first one
$winningTeamPlayers = $teams[0]->getAllPlayers(); $winningTeamPlayers = $teams[0]->getAllPlayers();
$winner = $winningTeamPlayers[0]; $winner = $winningTeamPlayers[0];
@@ -132,9 +131,6 @@ final class TwoPlayerTrueSkillCalculator extends SkillCalculator
return new Rating($newMean, $newStdDev); return new Rating($newMean, $newStdDev);
} }
/**
* {@inheritdoc}
*/
#[\Override] #[\Override]
public function calculateMatchQuality(GameInfo $gameInfo, array $teams): float public function calculateMatchQuality(GameInfo $gameInfo, array $teams): float
{ {

View File

@@ -28,9 +28,6 @@ final class TwoTeamTrueSkillCalculator extends SkillCalculator
parent::__construct(SkillCalculator::NONE, TeamsRange::exactly(2), PlayersRange::atLeast(1)); parent::__construct(SkillCalculator::NONE, TeamsRange::exactly(2), PlayersRange::atLeast(1));
} }
/**
* {@inheritdoc}
*/
#[\Override] #[\Override]
public function calculateNewRatings(GameInfo $gameInfo, array $teams, array $teamRanks): RatingContainer public function calculateNewRatings(GameInfo $gameInfo, array $teams, array $teamRanks): RatingContainer
{ {
@@ -38,6 +35,9 @@ final class TwoTeamTrueSkillCalculator extends SkillCalculator
RankSorter::sort($teams, $teamRanks); RankSorter::sort($teams, $teamRanks);
/**
* @var Team[] $teams
*/
$team1 = $teams[0]; $team1 = $teams[0];
$team2 = $teams[1]; $team2 = $teams[1];
@@ -138,9 +138,6 @@ final class TwoTeamTrueSkillCalculator extends SkillCalculator
} }
} }
/**
* {@inheritdoc}
*/
#[\Override] #[\Override]
public function calculateMatchQuality(GameInfo $gameInfo, array $teams): float public function calculateMatchQuality(GameInfo $gameInfo, array $teams): float
{ {