using System; using System.Collections.Generic; using System.Linq; using Moserware.Numerics; using Moserware.Skills.FactorGraphs; using Moserware.Skills.TrueSkill.Layers; namespace Moserware.Skills.TrueSkill { public class TrueSkillFactorGraph : FactorGraph, GaussianDistribution, Variable> { private readonly List> _Layers; private readonly PlayerPriorValuesToSkillsLayer _PriorLayer; public TrueSkillFactorGraph(GameInfo gameInfo, IEnumerable> teams, int[] teamRanks) { _PriorLayer = new PlayerPriorValuesToSkillsLayer(this, teams); GameInfo = gameInfo; VariableFactory = new VariableFactory(() => GaussianDistribution.FromPrecisionMean(0, 0)); _Layers = new List> { _PriorLayer, new PlayerSkillsToPerformancesLayer(this), new PlayerPerformancesToTeamPerformancesLayer(this), new IteratedTeamDifferencesInnerLayer( this, new TeamPerformancesToTeamPerformanceDifferencesLayer(this), new TeamDifferencesComparisonLayer(this, teamRanks)) }; } public GameInfo GameInfo { get; private set; } public void BuildGraph() { object lastOutput = null; foreach (var currentLayer in _Layers) { if (lastOutput != null) { currentLayer.SetRawInputVariablesGroups(lastOutput); } currentLayer.BuildLayer(); lastOutput = currentLayer.GetRawOutputVariablesGroups(); } } public void RunSchedule() { Schedule fullSchedule = CreateFullSchedule(); double fullScheduleDelta = fullSchedule.Visit(); } public double GetProbabilityOfRanking() { var factorList = new FactorList(); foreach (var currentLayer in _Layers) { foreach (var currentFactor in currentLayer.UntypedFactors) { factorList.AddFactor(currentFactor); } } double logZ = factorList.LogNormalization; return Math.Exp(logZ); } private Schedule CreateFullSchedule() { var fullSchedule = new List>(); foreach (var currentLayer in _Layers) { Schedule currentPriorSchedule = currentLayer.CreatePriorSchedule(); if (currentPriorSchedule != null) { fullSchedule.Add(currentPriorSchedule); } } // Casting to IEnumerable to get the LINQ Reverse() IEnumerable> allLayers = _Layers; foreach (var currentLayer in allLayers.Reverse()) { Schedule currentPosteriorSchedule = currentLayer.CreatePosteriorSchedule(); if (currentPosteriorSchedule != null) { fullSchedule.Add(currentPosteriorSchedule); } } return new ScheduleSequence("Full schedule", fullSchedule); } public IDictionary GetUpdatedRatings() { var result = new Dictionary(); foreach (var currentTeam in _PriorLayer.OutputVariablesGroups) { foreach (var currentPlayer in currentTeam) { result[currentPlayer.Key] = new Rating(currentPlayer.Value.Mean, currentPlayer.Value.StandardDeviation); } } return result; } } }