Initial version of Moserware.Skills TrueSkill calculator to go along with my Computing Your Skill blog post

This commit is contained in:
Jeff Moser
2010-03-18 07:39:48 -04:00
commit cb46631ff8
77 changed files with 6172 additions and 0 deletions

View File

@ -0,0 +1,51 @@
using Moserware.Skills;
using Moserware.Skills.Elo;
using NUnit.Framework;
namespace UnitTests.Elo
{
[TestFixture]
public class DuellingEloTest
{
private const double ErrorTolerance = 0.1;
[Test]
public void TwoOnTwoDuellingTest()
{
var calculator = new DuellingEloCalculator(new GaussianEloCalculator());
var player1 = new Player(1);
var player2 = new Player(2);
var gameInfo = GameInfo.DefaultGameInfo;
var team1 = new Team()
.AddPlayer(player1, gameInfo.DefaultRating)
.AddPlayer(player2, gameInfo.DefaultRating);
var player3 = new Player(3);
var player4 = new Player(4);
var team2 = new Team()
.AddPlayer(player3, gameInfo.DefaultRating)
.AddPlayer(player4, gameInfo.DefaultRating);
var teams = Teams.Concat(team1, team2);
var newRatingsWinLose = calculator.CalculateNewRatings(gameInfo, teams, 1, 2);
// TODO: Verify?
AssertRating(37, newRatingsWinLose[player1]);
AssertRating(37, newRatingsWinLose[player2]);
AssertRating(13, newRatingsWinLose[player3]);
AssertRating(13, newRatingsWinLose[player4]);
var quality = calculator.CalculateMatchQuality(gameInfo, teams);
Assert.AreEqual(1.0, quality, 0.001);
}
private static void AssertRating(double expected, Rating actual)
{
Assert.AreEqual(expected, actual.Mean, ErrorTolerance);
}
}
}

View File

@ -0,0 +1,37 @@
using Moserware.Skills;
using Moserware.Skills.Elo;
using NUnit.Framework;
namespace UnitTests.Elo
{
internal static class EloAssert
{
private const double ErrorTolerance = 0.1;
public static void AssertChessRating(TwoPlayerEloCalculator calculator,
double player1BeforeRating,
double player2BeforeRating,
PairwiseComparison player1Result,
double player1AfterRating,
double player2AfterRating)
{
var player1 = new Player(1);
var player2 = new Player(2);
var teams = Teams.Concat(
new Team(player1, new EloRating(player1BeforeRating)),
new Team(player2, new EloRating(player2BeforeRating)));
var chessGameInfo = new GameInfo(1200, 0, 200, 0, 0);
var result = calculator.CalculateNewRatings(chessGameInfo, teams,
(player1Result == PairwiseComparison.Win) ? new[] { 1, 2 } :
(player1Result == PairwiseComparison.Lose) ? new[] { 2, 1 } :
new[] { 1, 1 });
Assert.AreEqual(player1AfterRating, result[player1].Mean, ErrorTolerance);
Assert.AreEqual(player2AfterRating, result[player2].Mean, ErrorTolerance);
}
}
}

View File

@ -0,0 +1,36 @@
using Moserware.Skills;
using Moserware.Skills.Elo;
using NUnit.Framework;
namespace UnitTests.Elo
{
[TestFixture]
public class FideEloCalculatorTest
{
[Test]
public void FideProvisionalEloCalculatorTests()
{
// verified against http://ratings.fide.com/calculator_rtd.phtml
var calc = new FideEloCalculator(new FideKFactor.Provisional());
EloAssert.AssertChessRating(calc, 1200, 1500, PairwiseComparison.Win, 1221.25, 1478.75);
EloAssert.AssertChessRating(calc, 1200, 1500, PairwiseComparison.Draw, 1208.75, 1491.25);
EloAssert.AssertChessRating(calc, 1200, 1500, PairwiseComparison.Lose, 1196.25, 1503.75);
}
[Test]
public void FideNonProvisionalEloCalculatorTests()
{
// verified against http://ratings.fide.com/calculator_rtd.phtml
var calc = new FideEloCalculator();
EloAssert.AssertChessRating(calc, 1200, 1200, PairwiseComparison.Win, 1207.5, 1192.5);
EloAssert.AssertChessRating(calc, 1200, 1200, PairwiseComparison.Draw, 1200, 1200);
EloAssert.AssertChessRating(calc, 1200, 1200, PairwiseComparison.Lose, 1192.5, 1207.5);
EloAssert.AssertChessRating(calc, 2600, 2500, PairwiseComparison.Win, 2603.6, 2496.4);
EloAssert.AssertChessRating(calc, 2600, 2500, PairwiseComparison.Draw, 2598.6, 2501.4);
EloAssert.AssertChessRating(calc, 2600, 2500, PairwiseComparison.Lose, 2593.6, 2506.4);
}
}
}

View File

@ -0,0 +1,26 @@
using Moserware.Skills;
using Moserware.Skills.Elo;
using NUnit.Framework;
namespace UnitTests.Elo
{
[TestFixture]
public class GaussianEloCalculatorTest
{
[Test]
public void GaussianEloCalculatorTests()
{
const double defaultKFactor = 24.0;
var calc = new GaussianEloCalculator();
EloAssert.AssertChessRating(calc, 1200, 1200, PairwiseComparison.Win, 1212, 1188);
EloAssert.AssertChessRating(calc, 1200, 1200, PairwiseComparison.Draw, 1200, 1200);
EloAssert.AssertChessRating(calc, 1200, 1200, PairwiseComparison.Lose, 1188, 1212);
// verified using TrueSkill paper equation
EloAssert.AssertChessRating(calc, 1200, 1000, PairwiseComparison.Win, 1200 + ((1 - 0.76024993890652326884) * defaultKFactor), 1000 - (1 - 0.76024993890652326884) * defaultKFactor);
EloAssert.AssertChessRating(calc, 1200, 1000, PairwiseComparison.Draw, 1200 - (0.76024993890652326884 - 0.5) * defaultKFactor, 1000 + (0.76024993890652326884 - 0.5) * defaultKFactor);
EloAssert.AssertChessRating(calc, 1200, 1000, PairwiseComparison.Lose, 1200 - 0.76024993890652326884 * defaultKFactor, 1000 + 0.76024993890652326884 * defaultKFactor);
}
}
}