private static Rating CalculateNewRating(GameInfo gameInfo, Rating selfRating, Rating opponentRating, PairwiseComparison comparison) { double drawMargin = DrawMargin.GetDrawMarginFromDrawProbability(gameInfo.DrawProbability, gameInfo.Beta); double c = Math.Sqrt( Square(selfRating.StandardDeviation) + Square(opponentRating.StandardDeviation) + 2 * Square(gameInfo.Beta)); double winningMean = selfRating.Mean; double losingMean = opponentRating.Mean; switch (comparison) { case PairwiseComparison.Win: case PairwiseComparison.Draw: // NOP break; case PairwiseComparison.Lose: winningMean = opponentRating.Mean; losingMean = selfRating.Mean; break; } double meanDelta = winningMean - losingMean; double v; double w; double rankMultiplier; if (comparison != PairwiseComparison.Draw) { // non-draw case v = TruncatedGaussianCorrectionFunctions.VExceedsMargin(meanDelta, drawMargin, c); w = TruncatedGaussianCorrectionFunctions.WExceedsMargin(meanDelta, drawMargin, c); rankMultiplier = (int)comparison; } else { v = TruncatedGaussianCorrectionFunctions.VWithinMargin(meanDelta, drawMargin, c); w = TruncatedGaussianCorrectionFunctions.WWithinMargin(meanDelta, drawMargin, c); rankMultiplier = 1; } double meanMultiplier = (Square(selfRating.StandardDeviation) + Square(gameInfo.DynamicsFactor)) / c; double varianceWithDynamics = Square(selfRating.StandardDeviation) + Square(gameInfo.DynamicsFactor); double stdDevMultiplier = varianceWithDynamics / Square(c); double newMean = selfRating.Mean + (rankMultiplier * meanMultiplier * v); double newStdDev = Math.Sqrt(varianceWithDynamics * (1 - w * stdDevMultiplier)); return(new Rating(newMean, newStdDev)); }
private static void UpdatePlayerRatings <TPlayer>(GameInfo gameInfo, IDictionary <TPlayer, Rating> newPlayerRatings, IDictionary <TPlayer, Rating> selfTeam, IDictionary <TPlayer, Rating> otherTeam, PairwiseComparison selfToOtherTeamComparison) { double drawMargin = DrawMargin.GetDrawMarginFromDrawProbability(gameInfo.DrawProbability, gameInfo.Beta); double betaSquared = Square(gameInfo.Beta); double tauSquared = Square(gameInfo.DynamicsFactor); int totalPlayers = selfTeam.Count() + otherTeam.Count(); double selfMeanSum = selfTeam.Values.Sum(r => r.Mean); double otherTeamMeanSum = otherTeam.Values.Sum(r => r.Mean); double c = Math.Sqrt(selfTeam.Values.Sum(r => Square(r.StandardDeviation)) + otherTeam.Values.Sum(r => Square(r.StandardDeviation)) + totalPlayers * betaSquared); double winningMean = selfMeanSum; double losingMean = otherTeamMeanSum; switch (selfToOtherTeamComparison) { case PairwiseComparison.Win: case PairwiseComparison.Draw: // NOP break; case PairwiseComparison.Lose: winningMean = otherTeamMeanSum; losingMean = selfMeanSum; break; } double meanDelta = winningMean - losingMean; double v; double w; double rankMultiplier; if (selfToOtherTeamComparison != PairwiseComparison.Draw) { // non-draw case v = TruncatedGaussianCorrectionFunctions.VExceedsMargin(meanDelta, drawMargin, c); w = TruncatedGaussianCorrectionFunctions.WExceedsMargin(meanDelta, drawMargin, c); rankMultiplier = (int)selfToOtherTeamComparison; } else { // assume draw v = TruncatedGaussianCorrectionFunctions.VWithinMargin(meanDelta, drawMargin, c); w = TruncatedGaussianCorrectionFunctions.WWithinMargin(meanDelta, drawMargin, c); rankMultiplier = 1; } foreach (var teamPlayerRatingPair in selfTeam) { Rating previousPlayerRating = teamPlayerRatingPair.Value; double meanMultiplier = (Square(previousPlayerRating.StandardDeviation) + tauSquared) / c; double stdDevMultiplier = (Square(previousPlayerRating.StandardDeviation) + tauSquared) / Square(c); double playerMeanDelta = (rankMultiplier * meanMultiplier * v); double newMean = previousPlayerRating.Mean + playerMeanDelta; double newStdDev = Math.Sqrt((Square(previousPlayerRating.StandardDeviation) + tauSquared) * (1 - w * stdDevMultiplier)); newPlayerRatings[teamPlayerRatingPair.Key] = new Rating(newMean, newStdDev); } }