Example #1
0
        private void CalculateMastery(bool refresh)
        {
            Progress.Reset(Snapshot.AchievementGameCount);
            Progress.IsEnabled = true;

            var unixEpoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);

            var masteryStats            = new List <MasteryStats>();
            var mostAwardedAchievements = new List <GameStatsViewModel.AchievementStats>();

            var achievementIds = new List <int>(Snapshot.GamesWithAchievements);

            achievementIds.Sort();
            foreach (var gameId in achievementIds)
            {
                Progress.Label = "Processing game " + gameId;
                Progress.Current++;

                if (!Progress.IsEnabled)
                {
                    break;
                }

                string gameName  = "";
                int    created   = Int32.MaxValue;
                int    consoleId = 0;
                using (var stream = File.OpenRead(Path.Combine(_settings.DumpDirectory, gameId + ".json")))
                {
                    var json         = new JsonObject(stream);
                    var patchData    = json.GetField("PatchData").ObjectValue;
                    var achievements = patchData.GetField("Achievements");
                    if (achievements.Type != JsonFieldType.ObjectArray)
                    {
                        continue;
                    }

                    if (!achievements.ObjectArrayValue.Any(a => a.GetField("Flags").IntegerValue != 5))
                    {
                        continue;
                    }

                    foreach (var achievement in achievements.ObjectArrayValue)
                    {
                        var createdValue = achievement.GetField("Created").IntegerValue.GetValueOrDefault();
                        if (createdValue > 0 && createdValue < created)
                        {
                            created = createdValue;
                        }
                    }

                    gameName  = patchData.GetField("Title").StringValue;
                    consoleId = patchData.GetField("ConsoleID").IntegerValue.GetValueOrDefault();
                }

                var gameStats = new GameStatsViewModel()
                {
                    GameId = gameId
                };
                Debug.WriteLine(String.Format("{0} processing {1}", DateTime.Now, gameId));
                gameStats.LoadGame(refresh);

                if (!gameStats.Achievements.Any())
                {
                    continue;
                }

                var twentyFifthPlayers  = gameStats.NumberOfPlayers * 1 / 4;
                var fiftiethPlayers     = gameStats.NumberOfPlayers / 2;
                var seventyFifthPlayers = gameStats.NumberOfPlayers * 3 / 4;
                var ninetiethPlayers    = gameStats.NumberOfPlayers * 9 / 10;

                var twentyFifthPercentilePoints     = 0;
                var fiftiethPercentilePoints        = 0;
                var seventyFifthPercentilePoints    = 0;
                var ninetiethPercentilePoints       = 0;
                var ninetiethPercentileAchievements = 0;
                foreach (var achievement in gameStats.Achievements)
                {
                    if (achievement.EarnedBy > twentyFifthPlayers)
                    {
                        twentyFifthPercentilePoints += achievement.Points;
                        if (achievement.EarnedBy >= fiftiethPlayers)
                        {
                            fiftiethPercentilePoints += achievement.Points;
                            if (achievement.EarnedBy >= seventyFifthPlayers)
                            {
                                seventyFifthPercentilePoints += achievement.Points;
                                if (achievement.EarnedBy >= ninetiethPlayers)
                                {
                                    ninetiethPercentilePoints += achievement.Points;
                                    ninetiethPercentileAchievements++;
                                }
                            }
                        }
                    }

                    int i = 0;
                    while (i < mostAwardedAchievements.Count)
                    {
                        if (achievement.EarnedBy > mostAwardedAchievements[i].EarnedBy)
                        {
                            break;
                        }
                        ++i;
                    }
                    if (i < 20)
                    {
                        if (mostAwardedAchievements.Count == 20)
                        {
                            mostAwardedAchievements.RemoveAt(19);
                        }

                        achievement.Description = gameName;
                        mostAwardedAchievements.Insert(i, achievement);
                    }
                }

                var standardDeviation = 0.0;
                var mean = 0.0;
                if (gameStats.HardcoreMasteredUserCount > 0)
                {
                    var times = new List <double>();
                    foreach (var user in gameStats.TopUsers)
                    {
                        if (user.PointsEarned == gameStats.TotalPoints && user.IsEstimateReliable)
                        {
                            times.Add(user.GameTime.TotalMinutes);
                        }
                    }

                    if (times.Count > 0)
                    {
                        mean = times.Average();
                        if (gameStats.HardcoreMasteredUserCountEstimated)
                        {
                            standardDeviation = StandardDeviation.CalculateFromSample(times);
                        }
                        else
                        {
                            standardDeviation = StandardDeviation.Calculate(times);
                        }
                    }
                }

                var minutesPerPoint = new List <float>();
                foreach (var user in gameStats.TopUsers)
                {
                    if (user.PointsEarned > 0)
                    {
                        minutesPerPoint.Add((float)user.GameTime.TotalMinutes / user.PointsEarned);
                    }
                }
                minutesPerPoint.Sort();

                var stats = new MasteryStats
                {
                    GameId     = gameStats.GameId,
                    GameName   = gameStats.DialogTitle.Substring(12).Trim(),
                    ConsoleId  = consoleId,
                    Created    = unixEpoch + TimeSpan.FromSeconds(created),
                    Points     = gameStats.TotalPoints,
                    NumPlayers = gameStats.NumberOfPlayers,
                    HardcoreMasteredUserCount      = gameStats.HardcoreMasteredUserCount,
                    MeanTimeToMaster               = mean,
                    StdDevTimeToMaster             = standardDeviation,
                    MinutesPerPointToMaster        = mean / gameStats.TotalPoints,
                    MinutesPerPoint                = minutesPerPoint.Count > 0 ? minutesPerPoint[minutesPerPoint.Count / 2] : 0,
                    TwentyFifthPercentilePoints    = twentyFifthPercentilePoints,
                    FiftiethPercentilePoints       = fiftiethPercentilePoints,
                    SeventyFifthPercentilePoints   = seventyFifthPercentilePoints,
                    NintiethPercentilePoints       = ninetiethPercentilePoints,
                    NintiethPercentileAchievements = ninetiethPercentileAchievements,
                };

                if (gameStats.NumberOfPlayers == 0)
                {
                    stats.PlayersPerDay = 0.0;
                }
                else
                {
                    var age = (DateTime.Now - stats.Created).TotalDays;
                    stats.PlayersPerDay = gameStats.NumberOfPlayers / age;
                }

                masteryStats.Add(stats);
            }

            masteryStats.Sort((l, r) =>
            {
                if (l.MinutesPerPoint < r.MinutesPerPoint)
                {
                    return(-1);
                }
                else if (l.MinutesPerPoint > r.MinutesPerPoint)
                {
                    return(1);
                }
                return(0);
            });

            _backgroundWorkerService.InvokeOnUiThread(() =>
            {
                Results.Clear();
                foreach (var stats in masteryStats)
                {
                    Results.Add(stats);
                }
            });

            _mostAwardedAchievements = mostAwardedAchievements;

            Progress.Label = String.Empty;
        }