Example #1
0
// Calculates the match quality as the likelihood of all teams drawing (0% = bad, 100% = well matched).
func (calc *TwoTeamCalc) CalcMatchQual(gi *skills.GameInfo, teams []skills.Team) float64 {
	// Basic argument checking
	validateTeamCount(teams, twoTeamTeamRange)
	validatePlayersPerTeam(teams, twoTeamPlayerRange)

	// We've verified that there's just two teams
	team1 := teams[0]
	team1Count := team1.PlayerCount()

	team2 := teams[1]
	team2Count := team2.PlayerCount()

	totalPlayers := team1Count + team2Count

	betaSqr := numerics.Sqr(gi.Beta)

	team1MeanSum := team1.Accum(skills.MeanSum)
	team1VarSum := team1.Accum(skills.VarianceSum)

	team2MeanSum := team2.Accum(skills.MeanSum)
	team2VarSum := team2.Accum(skills.VarianceSum)

	// This comes from equation 4.1 in the TrueSkill paper on page 8
	// The equation was broken up into the part under the square root sign and
	// the exponential part to make the code easier to read.

	betaSqrPlayers := betaSqr * float64(totalPlayers)

	sqrtPart := math.Sqrt(betaSqrPlayers / (betaSqrPlayers + team1VarSum + team2VarSum))
	expPart := math.Exp(-.5 * numerics.Sqr(team1MeanSum-team2MeanSum) / (betaSqrPlayers + team1VarSum + team2VarSum))

	return expPart * sqrtPart
}
Example #2
0
// Calculates the match quality as the likelihood of all teams drawing (0% = bad, 100% = well matched).
func (calc *TwoPlayerCalc) CalcMatchQual(gi *skills.GameInfo, teams []skills.Team) float64 {
	validateTeamCount(teams, twoPlayerTeamRange)
	validatePlayersPerTeam(teams, twoPlayerPlayerRange)

	team1 := teams[0]
	p1 := team1.Players()[0]
	p1Rating := team1.PlayerRating(p1)

	team2 := teams[1]
	p2 := team2.Players()[0]
	p2Rating := team2.PlayerRating(p2)

	// We just use equation 4.1 found on page 8 of the TrueSkill 2006 paper:
	betaSqr := numerics.Sqr(gi.Beta)
	p1var := p1Rating.Variance()
	p2var := p2Rating.Variance()

	// This is the square root part of the equation:
	sqrtPart := math.Sqrt(2 * betaSqr / (2*betaSqr + p1var + p2var))

	// This is the exponent part of the equation:
	numerator := -numerics.Sqr(p1Rating.Mean() - p2Rating.Mean())
	denominator := 2 * (2*betaSqr + p1var + p2var)
	expPart := math.Exp(numerator / denominator)

	return sqrtPart * expPart
}
Example #3
0
func twoTeamUpdateRatings(gi *skills.GameInfo, newSkills skills.PlayerRatings, selfTeam, otherTeam skills.Team, comparison int) {
	drawMargin := drawMarginFromDrawProbability(gi.DrawProbability, gi.Beta)
	betaSqr := numerics.Sqr(gi.Beta)
	tauSqr := numerics.Sqr(gi.DynamicsFactor)

	totalPlayers := selfTeam.PlayerCount() + otherTeam.PlayerCount()

	selfMeanSum := selfTeam.Accum(skills.MeanSum)
	otherMeanSum := otherTeam.Accum(skills.MeanSum)

	c := math.Sqrt(selfTeam.Accum(skills.VarianceSum) + otherTeam.Accum(skills.VarianceSum) + float64(totalPlayers)*betaSqr)

	winningMean := selfMeanSum
	losingMean := otherMeanSum

	if comparison == skills.Lose {
		winningMean, losingMean = losingMean, winningMean
	}

	meanDelta := winningMean - losingMean

	var v, w, rankMultiplier float64

	if comparison != skills.Draw {
		v = vExceedsMarginC(meanDelta, drawMargin, c)
		w = wExceedsMarginC(meanDelta, drawMargin, c)
		rankMultiplier = float64(comparison)
	} else {
		v = vWithinMarginC(meanDelta, drawMargin, c)
		w = wWithinMarginC(meanDelta, drawMargin, c)
		rankMultiplier = 1
	}

	for p, r := range selfTeam.PlayerRatings {
		prevPlayerRating := r

		meanMultiplier := (prevPlayerRating.Variance() + tauSqr) / c
		stdDevMultiplier := (prevPlayerRating.Variance() + tauSqr) / numerics.Sqr(c)

		playerMeanDelta := rankMultiplier * meanMultiplier * v
		newMean := prevPlayerRating.Mean() + playerMeanDelta

		newStdDev := math.Sqrt((prevPlayerRating.Variance() + tauSqr) * (1 - w*stdDevMultiplier))

		newSkills[p] = skills.NewRating(newMean, newStdDev)
	}
}
Example #4
0
func twoPlayerCalcNewRating(gi *skills.GameInfo, selfRating, oppRating skills.Rating, comparison int) skills.Rating {
	drawMargin := drawMarginFromDrawProbability(gi.DrawProbability, gi.Beta)

	c := math.Sqrt(numerics.Sqr(selfRating.Stddev()) + numerics.Sqr(oppRating.Stddev()) + 2*numerics.Sqr(gi.Beta))

	winningMean := selfRating.Mean()
	losingMean := oppRating.Mean()

	if comparison == skills.Lose {
		winningMean = oppRating.Mean()
		losingMean = selfRating.Mean()
	}

	meanDelta := winningMean - losingMean

	var v, w, rankMultiplier float64

	if comparison != skills.Draw {
		v = vExceedsMarginC(meanDelta, drawMargin, c)
		w = wExceedsMarginC(meanDelta, drawMargin, c)
		rankMultiplier = float64(comparison)
	} else {
		v = vWithinMarginC(meanDelta, drawMargin, c)
		w = wWithinMarginC(meanDelta, drawMargin, c)
		rankMultiplier = 1
	}

	meanMultiplier := (numerics.Sqr(selfRating.Stddev()) + numerics.Sqr(gi.DynamicsFactor)) / c

	varianceWithDynamics := numerics.Sqr(selfRating.Stddev()) + numerics.Sqr(gi.DynamicsFactor)
	stdDevMultiplier := varianceWithDynamics / numerics.Sqr(c)

	newMean := selfRating.Mean() + (rankMultiplier * meanMultiplier * v)
	newStdDev := math.Sqrt(varianceWithDynamics * (1 - w*stdDevMultiplier))

	return skills.NewRating(newMean, newStdDev)
}
Example #5
0
func (r Rating) Variance() float64 {
	return numerics.Sqr(r.stddev)
}