diff --git a/PHPSkills/TrueSkill/FactorGraphTrueSkillCalculator.php b/PHPSkills/TrueSkill/FactorGraphTrueSkillCalculator.php index ba8c9d9..381b8ec 100644 --- a/PHPSkills/TrueSkill/FactorGraphTrueSkillCalculator.php +++ b/PHPSkills/TrueSkill/FactorGraphTrueSkillCalculator.php @@ -162,29 +162,40 @@ class FactorGraphTrueSkillCalculator extends SkillCalculator $teamAssignmentsListCount = count($teamAssignmentsList); + $currentColumn = 0; + for ($i = 0; $i < $teamAssignmentsListCount - 1; $i++) { $currentTeam = $teamAssignmentsList[$i]; // Need to add in 0's for all the previous players, since they're not // on this team - $currentRowValues = array(); + $playerAssignments[$currentColumn] = ($totalPreviousPlayers > 0) ? \array_fill(0, $totalPreviousPlayers, 0) : array(); foreach ($currentTeam->getAllPlayers() as $currentPlayer) { - $currentRowValues[] = PartialPlay::getPartialPlayPercentage($currentPlayer); + $playerAssignments[$currentColumn][] = PartialPlay::getPartialPlayPercentage($currentPlayer); // indicates the player is on the team $totalPreviousPlayers++; } + $rowsRemaining = $totalPlayers - $totalPreviousPlayers; + $nextTeam = $teamAssignmentsList[$i + 1]; foreach ($nextTeam->getAllPlayers() as $nextTeamPlayer) { // Add a -1 * playing time to represent the difference - $currentRowValues[] = -1 * PartialPlay::getPartialPlayPercentage($nextTeamPlayer); + $playerAssignments[$currentColumn][] = -1 * PartialPlay::getPartialPlayPercentage($nextTeamPlayer); + $rowsRemaining--; } - $playerAssignments[] = &$currentRowValues; + for ($ixAdditionalRow = 0; $ixAdditionalRow < $rowsRemaining; $ixAdditionalRow++) + { + // Pad with zeros + $playerAssignments[$currentColumn][] = 0; + } + + $currentColumn++; } $playerTeamAssignmentsMatrix = Matrix::fromColumnValues($totalPlayers, $teamAssignmentsListCount - 1, $playerAssignments); diff --git a/UnitTests/TrueSkill/FactorGraphTeamTrueSkillCalculatorTest.php b/UnitTests/TrueSkill/FactorGraphTeamTrueSkillCalculatorTest.php index 3cee306..6ae0325 100644 --- a/UnitTests/TrueSkill/FactorGraphTeamTrueSkillCalculatorTest.php +++ b/UnitTests/TrueSkill/FactorGraphTeamTrueSkillCalculatorTest.php @@ -16,6 +16,8 @@ class FactorGraphTrueSkillCalculatorTest extends PHPUnit_Framework_TestCase TrueSkillCalculatorTests::testAllTwoPlayerScenarios($this, $calculator); TrueSkillCalculatorTests::testAllTwoTeamScenarios($this, $calculator); + TrueSkillCalculatorTests::testAllMultipleTeamScenarios($this, $calculator); + } } diff --git a/UnitTests/TrueSkill/TrueSkillCalculatorTests.php b/UnitTests/TrueSkill/TrueSkillCalculatorTests.php index 5280041..467de3d 100644 --- a/UnitTests/TrueSkill/TrueSkillCalculatorTests.php +++ b/UnitTests/TrueSkill/TrueSkillCalculatorTests.php @@ -47,7 +47,17 @@ class TrueSkillCalculatorTests self::fourOnFourSimpleTest($testClass, $calculator); } - + public static function testAllMultipleTeamScenarios($testClass, SkillCalculator $calculator) + { + self::threeTeamsOfOneNotDrawn($testClass, $calculator); + //self::threeTeamsOfOneDrawn(calculator); + //self::fourTeamsOfOneNotDrawn(calculator); + //self::fiveTeamsOfOneNotDrawn(calculator); + //self::eightTeamsOfOneDrawn(calculator); + //self::eightTeamsOfOneUpset(calculator); + //self::sixteenTeamsOfOneNotDrawn(calculator); + //self::twoOnFourOnTwoWinDraw(calculator); + } //------------------- Actual Tests --------------------------- // If you see more than 3 digits of precision in the decimal point, then the expected values calculated from @@ -571,6 +581,33 @@ class TrueSkillCalculatorTests self::assertMatchQuality($testClass, 0.447, $calculator->calculateMatchQuality($gameInfo, $teams)); } + private static function threeTeamsOfOneNotDrawn($testClass, SkillCalculator $calculator) + { + $player1 = new Player(1); + $player2 = new Player(2); + $player3 = new Player(3); + + $gameInfo = new GameInfo(); + + $team1 = new Team($player1, $gameInfo->getDefaultRating()); + $team2 = new Team($player2, $gameInfo->getDefaultRating()); + $team3 = new Team($player3, $gameInfo->getDefaultRating()); + + $teams = Teams::concat($team1, $team2, $team3); + $newRatings = $calculator->calculateNewRatings($gameInfo, $teams, array(1, 2, 3)); + + $player1NewRating = $newRatings->getRating($player1); + self::assertRating($testClass, 31.675352419172107, 6.6559853776206905, $player1NewRating); + + $player2NewRating = $newRatings->getRating($player2); + self::assertRating($testClass, 25.000000000003912, 6.2078966412243233, $player2NewRating); + + $player3NewRating = $newRatings->getRating($player3); + self::assertRating($testClass, 18.324647580823971, 6.6559853776218318, $player3NewRating); + + self::assertMatchQuality($testClass, 0.200, $calculator->calculateMatchQuality($gameInfo, $teams)); + } + private static function assertRating($testClass, $expectedMean, $expectedStandardDeviation, $actual) { $testClass->assertEquals($expectedMean, $actual->getMean(), '', self::ERROR_TOLERANCE_TRUESKILL);