public function __construct(TrueSkillFactorGraph $parentGraph, array $teamRanks)
 {
     parent::__construct($parentGraph);
     $this->_teamRanks = $teamRanks;
     $gameInfo = $this->getParentFactorGraph()->getGameInfo();
     $this->_epsilon = DrawMargin::getDrawMarginFromDrawProbability($gameInfo->getDrawProbability(), $gameInfo->getBeta());
 }
 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));
     }
 }
 private function assertDrawMargin($drawProbability, $beta, $expected)
 {
     $actual = DrawMargin::getDrawMarginFromDrawProbability($drawProbability, $beta);
     $this->assertEquals($expected, $actual, '', DrawMarginTest::ERROR_TOLERANCE);
 }