private StatisticsSummary ProcessStatistic(StatisticsSummary input, GameType gameId, Player player)
        {
            var currentStatisticSummary = input.Clone();

            if (player != null)
            {
                // Statistic for the day we are playing on
                var currentStatistic = currentStatisticSummary.CreateLatestStatisticForGameType(gameId);

                var previousStatistic = currentStatisticSummary.GetPreviousStatisticForGame(gameId, SystemTime.Now())
                                        ?? currentStatistic;

                currentStatistic.Do(stat =>
                {
                    stat.MatchesWon = player.IsWinner
                        ? previousStatistic.MatchesWon + 1
                        : stat.MatchesWon;

                    stat.MatchesPlayed = previousStatistic.MatchesPlayed + 1;

                    stat.LegsWon    = previousStatistic.LegsWon + player.CummulativeLegsWon;
                    stat.LegsPlayed = previousStatistic.LegsPlayed + player.LegsPlayed;

                    var lastDartAverage = previousStatistic.OneDartAverage;
                    var lastDartsThrown = previousStatistic.DartsThrown;

                    stat.OneDartAverage = stat.DartsThrown > 0
                        ? ((lastDartAverage * lastDartsThrown) +
                           player.Scores.Sum(m => m.Value))
                                          / (stat.DartsThrown + player.Scores.Count)
                        : (decimal)player.Scores.Average(m => m.Value);

                    var maxTurnScoreInGames = player.TurnScores.Max(m => m.DartScore);
                    stat.HighestScore       = maxTurnScoreInGames > stat.HighestScore
                        ? maxTurnScoreInGames
                        : 0;

                    stat.HundredsScored = previousStatistic.HundredsScored +
                                          player.TurnScores.Count(
                        m => m.DartScore >= 100 && m.DartScore < 140);
                    stat.HundredFortiesScored = previousStatistic.HundredFortiesScored +
                                                player.TurnScores.Count(
                        m => m.DartScore >= 140 && m.DartScore < 180);
                    stat.HundredEightiesScored = previousStatistic.HundredEightiesScored +
                                                 player.TurnScores.Count(
                        m => m.DartScore == 180);

                    var winningLegs = player.Scores.Select(score => score.ScoredInLeg).Where(leg => leg.IsWinner);

                    stat.DartsThrownInWinningLegs = previousStatistic.DartsThrownInWinningLegs +
                                                    player.Scores.Count(score => winningLegs.Count(leg => leg.Id == score.ScoredInLeg.Id) > 0);
                });
            }

            return(currentStatisticSummary);
        }
        private StatisticsSummary ProcessStatistic(StatisticsSummary input, GameType gameId,
                                                   Player player)
        {
            var currentStatisticSummary = input.Clone();

            if (player != null)
            {
                // Statistic for the day we are playing on
                var previousStatistic = currentStatisticSummary.GetPreviousStatisticForGame(gameId, SystemTime.Now());

                var currentStatistic = currentStatisticSummary.CreateLatestStatisticForGameType(gameId);

                if (previousStatistic == null)
                {
                    previousStatistic = currentStatistic;
                }

                currentStatistic.Do(statistic =>
                {
                    statistic.MatchesWon = previousStatistic.MatchesWon;

                    if (player.IsWinner)
                    {
                        statistic.MatchesWon++;
                    }

                    var newBestGame = player.GetDartBestCheckOut();

                    statistic.BestGame = previousStatistic.BestGame;

                    if ((newBestGame != 0 && newBestGame < previousStatistic.BestGame) || previousStatistic.BestGame == 0)
                    {
                        statistic.BestGame = newBestGame;
                    }

                    statistic.TwelveDartCheckouts = previousStatistic.TwelveDartCheckouts +
                                                    player.GetDartCheckOuts(10, 12);
                    statistic.NineDartCheckouts = previousStatistic.NineDartCheckouts +
                                                  player.GetDartCheckOuts(1, 9);

                    statistic.MatchesPlayed = previousStatistic.MatchesPlayed + 1;

                    statistic.LegsWon    = previousStatistic.LegsWon + player.CummulativeLegsWon;
                    statistic.LegsPlayed = previousStatistic.LegsPlayed + player.LegsPlayed;

                    var lastDartAverage = previousStatistic.OneDartAverage;
                    var lastDartsThrown = previousStatistic.DartsThrown;

                    if (statistic.DartsThrown > 0)
                    {
                        statistic.OneDartAverage = ((lastDartAverage * lastDartsThrown) +
                                                    player.Scores.Sum(m => m.Value))
                                                   / (statistic.DartsThrown + player.Scores.Count);
                    }
                    else
                    {
                        statistic.OneDartAverage = (decimal)player.Scores.Average(m => m.Value);
                    }

                    statistic.HighestScore = previousStatistic.HighestScore;

                    if (player.TurnScores.Max(m => m.DartScore) > statistic.HighestScore)
                    {
                        statistic.HighestScore = player.TurnScores.Max(m => m.DartScore);
                    }

                    var isWinner = player.TurnScores.FirstOrDefault(m => m.ScoredInLeg.IsWinner) != null;

                    statistic.HighestCheckout = previousStatistic.HighestCheckout;

                    if (isWinner &&
                        player.TurnScores.Where(m => m.ScoredInLeg.IsWinner).Max(m => m.DartScore) >
                        statistic.HighestCheckout)
                    {
                        statistic.HighestCheckout =
                            player.TurnScores.Where(m => m.ScoredInLeg.IsWinner).Max(m => m.DartScore);
                    }

                    statistic.HundredsScored = previousStatistic.HundredsScored +
                                               player.TurnScores.Count(
                        m => m.DartScore >= 100 && m.DartScore < 140);
                    statistic.HundredFortiesScored = previousStatistic.HundredFortiesScored +
                                                     player.TurnScores.Count(
                        m => m.DartScore >= 140 && m.DartScore < 180);
                    statistic.HundredEightiesScored = previousStatistic.HundredEightiesScored +
                                                      player.TurnScores.Count(m => m.DartScore == 180);

                    statistic.CheckoutPossibleCount = previousStatistic.CheckoutPossibleCount + player.TurnScores.Count(m => m.GetCanCheckout());

                    statistic.CheckoutAchievedCount = previousStatistic.CheckoutAchievedCount + player.GetDartCheckOuts(1, int.MaxValue);

                    statistic.DartsThrown = previousStatistic.DartsThrown + player.Scores.Count;

                    var winningLegs = player.Scores.Select(score => score.ScoredInLeg).Where(leg => leg.IsWinner);

                    statistic.DartsThrownInWinningLegs = previousStatistic.DartsThrownInWinningLegs +
                                                         player.Scores.Count(score => winningLegs.Count(leg => leg.Id == score.ScoredInLeg.Id) > 0);
                });
            }

            return(currentStatisticSummary);
        }