public void Opponent_Match_Win_Percentage_Should_Be_One(SwissStatisticsProvider sut, IEnumerable<Round> rounds, Player A, Player B)
                {
                    var actual = sut
                        .GetOpponentsMatchWinPercentage(rounds, A);

                    Assert.Equal(1.0m, actual);
                }
                public void Game_Win_Percentage_Should_Be_Minimum(SwissStatisticsProvider sut, IEnumerable<Round> rounds, Player A, Player B)
                {
                    var actual = sut
                        .GetGameWinPercentage(rounds, A);

                    Assert.Equal(SwissStatisticsProvider.MinimumMatchWinPercentage, actual);
                }
                public void Should_Be_Awarded_No_Match_Points(SwissStatisticsProvider sut, IEnumerable<Round> rounds, Player A, Player B)
                {
                    var actual = sut
                        .GetMatchPoints(rounds, A);

                    Assert.Equal(0.0m, actual);
                }
                public void Game_Win_Percentage_Should_Be_One_Third(SwissStatisticsProvider sut, IEnumerable<Round> rounds, Player A, Player B)
                {
                    var actual = sut
                        .GetGameWinPercentage(rounds, A);

                    Assert.Equal(1.0m / 3.0m, actual);
                }
                public void Opponent_Game_Win_Percentage_Should_Be_Four_Ninths(SwissStatisticsProvider sut, IEnumerable<Round> rounds, Player A, Player B)
                {
                    var actual = sut
                        .GetOpponentsGameWinPercentage(rounds, A);

                    // One win + one draw = 4GP out of 9 possible
                    Assert.Equal(4.0m / 9.0m, actual);
                }
                public void Opponent_Game_Win_Percentage_Should_Be_Two_Thirds(SwissStatisticsProvider sut, IEnumerable<Round> rounds, Player A, Player B)
                {
                    var actual = sut
                        .GetOpponentsGameWinPercentage(rounds, A);

                    Assert.Equal(2.0m / 3.0m, actual);
                }
        public void It_Just_Freaking_Works()
        {
            // Yay happy path!

            var statisticsProvider = new SwissStatisticsProvider();
            var rankingEngine = new SwissRankingEngine(statisticsProvider);
            var contextBuilder = new SwissTournamanetContextBuilder(statisticsProvider, rankingEngine);
            var commandEventHandler = new CommandEventHandler<SwissTournamentContext>(contextBuilder);

            var context = new SwissTournamentContext(0, TournamentState.None, null, null, null);

            // Create the tournament
            context = commandEventHandler.ProcessCommand(
                context: context,
                commandEvent: new CommandEvent(
                    sequence: 0,
                    aggregateId: "T1",
                    name: TournamentCommand.CreateTournament.ToString(),
                    properties: new Dictionary<string, string>
                    {
                        { "Timestamp", new DateTimeOffset(1982, 7, 22, 01, 14, 22, TimeSpan.FromHours(-7)).ToString() }
                    })
            );

            Assert.Equal(TournamentState.TournamentCreated, context.State);
            Assert.NotEqual(0, context.TournamentSeed);

            // Add players
            context = commandEventHandler.ProcessCommand(
                context: context,
                commandEvent: new CommandEvent(
                    sequence: 0,
                    aggregateId: "T1",
                    name: TournamentCommand.AddPlayer.ToString(),
                    properties: new Dictionary<string, string>
                    {
                        { "Player", "A" }
                    })
            );

            context = commandEventHandler.ProcessCommand(
                context: context,
                commandEvent: new CommandEvent(
                    sequence: 0,
                    aggregateId: "T1",
                    name: TournamentCommand.AddPlayer.ToString(),
                    properties: new Dictionary<string, string>
                    {
                        { "Player", "B" }
                    })
            );

            context = commandEventHandler.ProcessCommand(
                context: context,
                commandEvent: new CommandEvent(
                    sequence: 0,
                    aggregateId: "T1",
                    name: TournamentCommand.AddPlayer.ToString(),
                    properties: new Dictionary<string, string>
                    {
                        { "Player", "C" }
                    })
            );

            context = commandEventHandler.ProcessCommand(
                context: context,
                commandEvent: new CommandEvent(
                    sequence: 0,
                    aggregateId: "T1",
                    name: TournamentCommand.AddPlayer.ToString(),
                    properties: new Dictionary<string, string>
                    {
                        { "Player", "D" }
                    })
            );

            context = commandEventHandler.ProcessCommand(
                context: context,
                commandEvent: new CommandEvent(
                    sequence: 0,
                    aggregateId: "T1",
                    name: TournamentCommand.AddPlayer.ToString(),
                    properties: new Dictionary<string, string>
                    {
                        { "Player", "E" }
                    })
            );

            Assert.Equal(TournamentState.TournamentStarted, context.State);
            Assert.NotEmpty(context.Players);

            var roundOnePairings = rankingEngine.GetPairings(context);

            // Record match results for round 1
            context = commandEventHandler.ProcessCommand(
                context: context,
                commandEvent: new CommandEvent(
                    sequence: 0,
                    aggregateId: "T1",
                    name: TournamentCommand.RecordMatchResults.ToString(),
                    properties: new Dictionary<string, string>
                    {
                        { "Player", "A" },
                        { "Wins", "2" },
                    })
            );

            context = commandEventHandler.ProcessCommand(
                context: context,
                commandEvent: new CommandEvent(
                    sequence: 0,
                    aggregateId: "T1",
                    name: TournamentCommand.RecordMatchResults.ToString(),
                    properties: new Dictionary<string, string>
                    {
                        { "Player", "B" },
                        { "Wins", "1" },
                    })
            );

            context = commandEventHandler.ProcessCommand(
                context: context,
                commandEvent: new CommandEvent(
                    sequence: 0,
                    aggregateId: "T1",
                    name: TournamentCommand.RecordMatchResults.ToString(),
                    properties: new Dictionary<string, string>
                    {
                        { "Player", "D" },
                    })
            );

            context = commandEventHandler.ProcessCommand(
                context: context,
                commandEvent: new CommandEvent(
                    sequence: 0,
                    aggregateId: "T1",
                    name: TournamentCommand.RecordMatchResults.ToString(),
                    properties: new Dictionary<string, string>
                    {
                        { "Player", "E" },
                        { "Draws", "1" },
                    })
            );

            // End round 1
            context = commandEventHandler.ProcessCommand(
                context: context,
                commandEvent: new CommandEvent(
                    sequence: 0,
                    aggregateId: "T1",
                    name: TournamentCommand.EndRound.ToString(),
                    properties: new Dictionary<string, string>
                    {
                    })
            );

            // Get standings as of round 1. If we include round 2, we get the bye points immediately.
            var roundOneStandings = rankingEngine.GetStandings(context, 1);
            var roundTwoPairings = rankingEngine.GetPairings(context);

            // Record match results for round 2
            context = commandEventHandler.ProcessCommand(
                context: context,
                commandEvent: new CommandEvent(
                    sequence: 0,
                    aggregateId: "T1",
                    name: TournamentCommand.RecordMatchResults.ToString(),
                    properties: new Dictionary<string, string>
                    {
                        { "Player", "A" },
                        { "Draws", "1" },
                    })
            );

            context = commandEventHandler.ProcessCommand(
                context: context,
                commandEvent: new CommandEvent(
                    sequence: 0,
                    aggregateId: "T1",
                    name: TournamentCommand.RecordMatchResults.ToString(),
                    properties: new Dictionary<string, string>
                    {
                        { "Player", "C" },
                        { "Wins", "2" },
                    })
            );

            context = commandEventHandler.ProcessCommand(
                context: context,
                commandEvent: new CommandEvent(
                    sequence: 0,
                    aggregateId: "T1",
                    name: TournamentCommand.RecordMatchResults.ToString(),
                    properties: new Dictionary<string, string>
                    {
                        { "Player", "D" },
                        { "Wins", "1" },
                    })
            );

            context = commandEventHandler.ProcessCommand(
                context: context,
                commandEvent: new CommandEvent(
                    sequence: 0,
                    aggregateId: "T1",
                    name: TournamentCommand.RecordMatchResults.ToString(),
                    properties: new Dictionary<string, string>
                    {
                        { "Player", "E" },
                    })
            );

            // End round 2
            context = commandEventHandler.ProcessCommand(
                context: context,
                commandEvent: new CommandEvent(
                    sequence: 0,
                    aggregateId: "T1",
                    name: TournamentCommand.EndRound.ToString(),
                    properties: new Dictionary<string, string>
                    {
                    })
            );

            var roundTwoStandings = rankingEngine.GetStandings(context, 2);

            // Drop a player
            context = commandEventHandler.ProcessCommand(
                context: context,
                commandEvent: new CommandEvent(
                    sequence: 0,
                    aggregateId: "T1",
                    name: TournamentCommand.RemovePlayer.ToString(),
                    properties: new Dictionary<string, string>
                    {
                        { "Player", "E" },
                        { "Wins", "1" },
                    })
            );

            // Record match results for round 3
            var roundThreePairings = rankingEngine.GetPairings(context);

            // Record match results for round 3
            context = commandEventHandler.ProcessCommand(
                context: context,
                commandEvent: new CommandEvent(
                    sequence: 0,
                    aggregateId: "T1",
                    name: TournamentCommand.RecordMatchResults.ToString(),
                    properties: new Dictionary<string, string>
                    {
                        { "Player", "A" },
                        { "Wins", "1" },
                    })
            );

            context = commandEventHandler.ProcessCommand(
                context: context,
                commandEvent: new CommandEvent(
                    sequence: 0,
                    aggregateId: "T1",
                    name: TournamentCommand.RecordMatchResults.ToString(),
                    properties: new Dictionary<string, string>
                    {
                        { "Player", "B" },
                        { "Draws", "1" },
                    })
            );

            context = commandEventHandler.ProcessCommand(
                context: context,
                commandEvent: new CommandEvent(
                    sequence: 0,
                    aggregateId: "T1",
                    name: TournamentCommand.RecordMatchResults.ToString(),
                    properties: new Dictionary<string, string>
                    {
                        { "Player", "C" },
                    })
            );

            context = commandEventHandler.ProcessCommand(
                context: context,
                commandEvent: new CommandEvent(
                    sequence: 0,
                    aggregateId: "T1",
                    name: TournamentCommand.RecordMatchResults.ToString(),
                    properties: new Dictionary<string, string>
                    {
                        { "Player", "D" },
                        { "Wins", "2" },
                    })
            );

            // End round 3 and the tournament
            context = commandEventHandler.ProcessCommand(
                context: context,
                commandEvent: new CommandEvent(
                    sequence: 0,
                    aggregateId: "T1",
                    name: TournamentCommand.EndRound.ToString(),
                    properties: new Dictionary<string, string>
                    {
                    })
            );

            var finalStandings = rankingEngine.GetStandings(context);
        }