private static function calculateNewRating(GameInfo $gameInfo, Rating $selfRating, Rating $opponentRating, $comparison)
 {
     $drawMargin = DrawMargin::getDrawMarginFromDrawProbability($gameInfo->getDrawProbability(), $gameInfo->getBeta());
     $c = sqrt(square($selfRating->getStandardDeviation()) + square($opponentRating->getStandardDeviation()) + 2 * square($gameInfo->getBeta()));
     $winningMean = $selfRating->getMean();
     $losingMean = $opponentRating->getMean();
     switch ($comparison) {
         case PairwiseComparison::WIN:
         case PairwiseComparison::DRAW:
             // NOP
             break;
         case PairwiseComparison::LOSE:
             $winningMean = $opponentRating->getMean();
             $losingMean = $selfRating->getMean();
             break;
     }
     $meanDelta = $winningMean - $losingMean;
     if ($comparison != PairwiseComparison::DRAW) {
         // non-draw case
         $v = TruncatedGaussianCorrectionFunctions::vExceedsMarginScaled($meanDelta, $drawMargin, $c);
         $w = TruncatedGaussianCorrectionFunctions::wExceedsMarginScaled($meanDelta, $drawMargin, $c);
         $rankMultiplier = (int) $comparison;
     } else {
         $v = TruncatedGaussianCorrectionFunctions::vWithinMarginScaled($meanDelta, $drawMargin, $c);
         $w = TruncatedGaussianCorrectionFunctions::wWithinMarginScaled($meanDelta, $drawMargin, $c);
         $rankMultiplier = 1;
     }
     $meanMultiplier = (square($selfRating->getStandardDeviation()) + square($gameInfo->getDynamicsFactor())) / $c;
     $varianceWithDynamics = square($selfRating->getStandardDeviation()) + square($gameInfo->getDynamicsFactor());
     $stdDevMultiplier = $varianceWithDynamics / square($c);
     $newMean = $selfRating->getMean() + $rankMultiplier * $meanMultiplier * $v;
     $newStdDev = sqrt($varianceWithDynamics * (1 - $w * $stdDevMultiplier));
     return new Rating($newMean, $newStdDev);
 }
 private static function updatePlayerRatings(GameInfo $gameInfo, RatingContainer &$newPlayerRatings, Team $selfTeam, Team $otherTeam, $selfToOtherTeamComparison)
 {
     $drawMargin = DrawMargin::getDrawMarginFromDrawProbability($gameInfo->getDrawProbability(), $gameInfo->getBeta());
     $betaSquared = square($gameInfo->getBeta());
     $tauSquared = square($gameInfo->getDynamicsFactor());
     $totalPlayers = $selfTeam->count() + $otherTeam->count();
     $meanGetter = function ($currentRating) {
         return $currentRating->getMean();
     };
     $selfMeanSum = sum($selfTeam->getAllRatings(), $meanGetter);
     $otherTeamMeanSum = sum($otherTeam->getAllRatings(), $meanGetter);
     $varianceGetter = function ($currentRating) {
         return square($currentRating->getStandardDeviation());
     };
     $c = sqrt(sum($selfTeam->getAllRatings(), $varianceGetter) + sum($otherTeam->getAllRatings(), $varianceGetter) + $totalPlayers * $betaSquared);
     $winningMean = $selfMeanSum;
     $losingMean = $otherTeamMeanSum;
     switch ($selfToOtherTeamComparison) {
         case PairwiseComparison::WIN:
         case PairwiseComparison::DRAW:
             // NOP
             break;
         case PairwiseComparison::LOSE:
             $winningMean = $otherTeamMeanSum;
             $losingMean = $selfMeanSum;
             break;
     }
     $meanDelta = $winningMean - $losingMean;
     if ($selfToOtherTeamComparison != PairwiseComparison::DRAW) {
         // non-draw case
         $v = TruncatedGaussianCorrectionFunctions::vExceedsMarginScaled($meanDelta, $drawMargin, $c);
         $w = TruncatedGaussianCorrectionFunctions::wExceedsMarginScaled($meanDelta, $drawMargin, $c);
         $rankMultiplier = (int) $selfToOtherTeamComparison;
     } else {
         // assume draw
         $v = TruncatedGaussianCorrectionFunctions::vWithinMarginScaled($meanDelta, $drawMargin, $c);
         $w = TruncatedGaussianCorrectionFunctions::wWithinMarginScaled($meanDelta, $drawMargin, $c);
         $rankMultiplier = 1;
     }
     $selfTeamAllPlayers =& $selfTeam->getAllPlayers();
     foreach ($selfTeamAllPlayers as &$selfTeamCurrentPlayer) {
         $localSelfTeamCurrentPlayer =& $selfTeamCurrentPlayer;
         $previousPlayerRating = $selfTeam->getRating($localSelfTeamCurrentPlayer);
         $meanMultiplier = (square($previousPlayerRating->getStandardDeviation()) + $tauSquared) / $c;
         $stdDevMultiplier = (square($previousPlayerRating->getStandardDeviation()) + $tauSquared) / square($c);
         $playerMeanDelta = $rankMultiplier * $meanMultiplier * $v;
         $newMean = $previousPlayerRating->getMean() + $playerMeanDelta;
         $newStdDev = sqrt((square($previousPlayerRating->getStandardDeviation()) + $tauSquared) * (1 - $w * $stdDevMultiplier));
         $newPlayerRatings->setRating($localSelfTeamCurrentPlayer, new Rating($newMean, $newStdDev));
     }
 }
 public function calculateMatchQuality(GameInfo $gameInfo, array $teams)
 {
     // We need to create the A matrix which is the player team assigments.
     $teamAssignmentsList = $teams;
     $skillsMatrix = $this->getPlayerCovarianceMatrix($teamAssignmentsList);
     $meanVector = $this->getPlayerMeansVector($teamAssignmentsList);
     $meanVectorTranspose = $meanVector->getTranspose();
     $playerTeamAssignmentsMatrix = $this->createPlayerTeamAssignmentMatrix($teamAssignmentsList, $meanVector->getRowCount());
     $playerTeamAssignmentsMatrixTranspose = $playerTeamAssignmentsMatrix->getTranspose();
     $betaSquared = square($gameInfo->getBeta());
     $start = Matrix::multiply($meanVectorTranspose, $playerTeamAssignmentsMatrix);
     $aTa = Matrix::multiply(Matrix::scalarMultiply($betaSquared, $playerTeamAssignmentsMatrixTranspose), $playerTeamAssignmentsMatrix);
     $aTSA = Matrix::multiply(Matrix::multiply($playerTeamAssignmentsMatrixTranspose, $skillsMatrix), $playerTeamAssignmentsMatrix);
     $middle = Matrix::add($aTa, $aTSA);
     $middleInverse = $middle->getInverse();
     $end = Matrix::multiply($playerTeamAssignmentsMatrixTranspose, $meanVector);
     $expPartMatrix = Matrix::scalarMultiply(-0.5, Matrix::multiply(Matrix::multiply($start, $middleInverse), $end));
     $expPart = $expPartMatrix->getDeterminant();
     $sqrtPartNumerator = $aTa->getDeterminant();
     $sqrtPartDenominator = $middle->getDeterminant();
     $sqrtPart = $sqrtPartNumerator / $sqrtPartDenominator;
     $result = exp($expPart) * sqrt($sqrtPart);
     return $result;
 }
Example #4
0
function loadRatings()
{
    $stats = file_get_contents('games.stats');
    $stats = explode("\n", $stats);
    $ratings = array();
    foreach ($stats as $stat) {
        if (empty($stat)) {
            continue;
        }
        $stat = explode("\t", $stat);
        $playerId = (int) $stat[0];
        $mean = (double) $stat[1];
        $stddev = (double) $stat[2];
        $ratings[$playerId] = new Rating($mean, $stddev);
    }
    $gameInfo = new GameInfo();
    $players = loadPlayers();
    foreach ($players as $playerId => $playerName) {
        if (!isset($ratings[$playerId])) {
            $ratings[$playerId] = $gameInfo->getDefaultRating();
        }
    }
    return $ratings;
}
 public function getPlayerWinProbability(GameInfo $gameInfo, $playerRating, $opponentRating)
 {
     $ratingDifference = $playerRating - $opponentRating;
     // See equation 1.1 in the TrueSkill paper
     return GaussianDistribution::cumulativeTo($ratingDifference / (sqrt(2) * $gameInfo->getBeta()));
 }
 private static function oneOnTwoBalancedPartialPlay($testClass, SkillCalculator $calculator)
 {
     $gameInfo = new GameInfo();
     $p1 = new Player(1);
     $team1 = new Team($p1, $gameInfo->getDefaultRating());
     $p2 = new Player(2, 0.0);
     $p3 = new Player(3, 1.0);
     $team2 = new Team();
     $team2->addPlayer($p2, $gameInfo->getDefaultRating());
     $team2->addPlayer($p3, $gameInfo->getDefaultRating());
     $teams = Teams::concat($team1, $team2);
     $newRatings = $calculator->calculateNewRatings($gameInfo, $teams, array(1, 2));
     $p1NewRating = $newRatings->getRating($p1);
     $p2NewRating = $newRatings->getRating($p2);
     $p3NewRating = $newRatings->getRating($p3);
     // This should be roughly the same as a 1 v 1
     self::assertRating($testClass, 29.39648040436841, 7.1713980703143205, $p1NewRating);
     self::assertRating($testClass, 24.999560351959563, 8.333749978770932, $p2NewRating);
     self::assertRating($testClass, 20.603519595631585, 7.1713980703143205, $p3NewRating);
     $matchQuality = $calculator->calculateMatchQuality($gameInfo, $teams);
     self::assertMatchQuality($testClass, 0.44721358745011336, $matchQuality);
 }