Exemple #1
0
        public void TestUpdateRatings(IReadOnlyCollection <IReadOnlyCollection <KeyValuePair <int, int> > > gameResult, Dictionary <int, int> expectedNewRatings)
        {
            var calculator = new EloCalculator(32);
            var gameResultRatingHolders = gameResult
                                          .Select(rs => rs.Select(r => new RatingHolder(r.Key, r.Value)).ToList())
                                          .ToList();
            var newRatingHolders = calculator.UpdateRatings(gameResultRatingHolders).ToList();

            Assert.AreEqual(newRatingHolders.Count, expectedNewRatings.Count);
            Assert.AreEqual(newRatingHolders.Count, newRatingHolders.Select(rh => rh.Identifier).Distinct().Count());
            foreach (var rh in newRatingHolders)
            {
                Assert.AreEqual(rh.Rating, expectedNewRatings[rh.Identifier]);
            }
        }
        public void RegisterCompletedGame(string gameName, DateTime startTime, string location, IReadOnlyCollection <IReadOnlyCollection <string> > playerNamesByPosition)
        {
            using (var gameRepository = repositoryFactory.GetRepository <Game>())
                using (var playerRepository = repositoryFactory.GetRepository <Player>())
                    using (var gameResultRepository = repositoryFactory.GetRepository <GameResult>())
                    {
                        var game = gameRepository.Get(new Game {
                            Name = gameName
                        });
                        if (game == null)
                        {
                            throw new ArgumentException($"Unrecogised game name: {gameName}", nameof(gameName));
                        }
                        var playerCount = playerNamesByPosition.Sum(pns => pns.Count);
                        if (playerCount < game.MinimumPlayerCount || playerCount > game.MaximumPlayerCount)
                        {
                            throw new ArgumentException($"Invalid number of players for {gameName}: {playerCount}", nameof(playerNamesByPosition));
                        }

                        var recognisedPlayerNames   = new HashSet <string>();
                        var duplicatePlayerNames    = new HashSet <string>();
                        var unrecognisedPlayerNames = new HashSet <string>();

                        var playersByPosition = playerNamesByPosition
                                                .Select(pns => pns.Select(pn =>
                        {
                            if (recognisedPlayerNames.Contains(pn))
                            {
                                duplicatePlayerNames.Add(pn);
                                return(null);
                            }
                            var player = playerRepository.Get(new Player {
                                Name = pn
                            });
                            if (player == null)
                            {
                                unrecognisedPlayerNames.Add(pn);
                                return(null);
                            }
                            recognisedPlayerNames.Add(pn);
                            return(player);
                        }).ToList()).ToList();

                        if (duplicatePlayerNames.Count > 0)
                        {
                            throw new ArgumentException($"Duplicate player name(s): {string.Join(", ", duplicatePlayerNames)}",
                                                        nameof(playerNamesByPosition));
                        }

                        if (unrecognisedPlayerNames.Count > 0)
                        {
                            throw new ArgumentException($"Duplicate player name(s): {string.Join(", ", duplicatePlayerNames)}",
                                                        nameof(playerNamesByPosition));
                        }

                        var playersWithRatingsAfter = eloCalculator.UpdateRatings(playersByPosition);

                        var playerResultsByPosition = playersByPosition
                                                      .Select((ps, psi) => ps.Select((p, pi) => new PlayerResult
                        {
                            PlayerName   = p.Name,
                            RatingBefore = p.Rating,
                            RatingAfter  = playersWithRatingsAfter.Single(a => p.IdentifiesWith(a)).Rating
                        }).ToList())
                                                      .ToList();

                        var gameResult = new GameResult
                        {
                            Game      = game.Name,
                            StartTime = startTime,
                            Location  = location,
                            PlayerResultsByPosition = playerResultsByPosition
                        };

                        gameResultRepository.Put(gameResult);

                        foreach (var player in playersWithRatingsAfter)
                        {
                            playerRepository.Put(player);
                        }
                    }
        }