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;
 }
 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()));
 }