예제 #1
0
        private void AddFolder(FolderViewModel parent, string[] path, int pathIndex)
        {
            FolderViewModel child = parent.Children.FirstOrDefault(f => String.Compare(f.Name, path[pathIndex], StringComparison.OrdinalIgnoreCase) == 0);

            if (child == null)
            {
                child = new FolderViewModel(path[pathIndex], parent);
                _backgroundWorkerService.InvokeOnUiThread(() => parent.Children.Add(child));
            }

            pathIndex++;
            if (pathIndex < path.Length)
            {
                AddFolder(child, path, pathIndex);
            }
        }
예제 #2
0
        private void RefreshFromServer(int gameId, IFileSystemService fileSystemService, IHttpRequestService httpRequestService)
        {
            var file = Path.Combine(_settings.DumpDirectory, String.Format("{0}.json", gameId));

            if (fileSystemService.FileExists(file))
            {
                bool fileValid = (DateTime.Now - fileSystemService.GetFileLastModified(file)) < TimeSpan.FromHours(16);
                if (fileValid)
                {
                    return;
                }
            }

            Debug.WriteLine(String.Format("{0} fetching patch data {1}", DateTime.Now, gameId));
            var url = String.Format("http://retroachievements.org/dorequest.php?u={0}&t={1}&g={2}&h=1&r=patch",
                                    _settings.UserName, _settings.DoRequestToken, gameId);
            var request  = new HttpRequest(url);
            var response = httpRequestService.Request(request);

            if (response.Status == System.Net.HttpStatusCode.OK)
            {
                using (var outputStream = fileSystemService.CreateFile(file))
                {
                    byte[] buffer = new byte[4096];
                    using (var stream = response.GetResponseStream())
                    {
                        int bytesRead;
                        while ((bytesRead = stream.Read(buffer, 0, buffer.Length)) > 0)
                        {
                            if (bytesRead < 100)
                            {
                                var str = Encoding.UTF8.GetString(buffer, 0, bytesRead);
                                if (str.Contains("Error"))
                                {
                                    if (_progress != null)
                                    {
                                        _progress.IsEnabled = false;
                                        _progress.Label     = String.Empty;
                                    }
                                    _backgroundWorkerService.InvokeOnUiThread(() => MessageBoxViewModel.ShowMessage(str));
                                    return;
                                }
                            }
                            outputStream.Write(buffer, 0, bytesRead);
                        }
                    }
                }

                string contents;
                using (var stream = new StreamReader(fileSystemService.OpenFile(file, OpenFileMode.Read)))
                {
                    contents = stream.ReadToEnd();
                }
            }
        }
예제 #3
0
        private void LoadTickets()
        {
            var games        = new Dictionary <int, GameTickets>();
            var tickets      = new Dictionary <int, AchievementTickets>();
            int totalTickets = 0;

            Progress.Reset(25);
            Progress.Label = "Fetching Open Tickets";

            int pageTickets;
            int page = 0;

            do
            {
                var ticketsPage = RAWebCache.Instance.GetOpenTicketsPage(page);
                if (ticketsPage == null)
                {
                    return;
                }

                if (page == 0 && !ticketsPage.Contains("<title>Ticket"))
                {
                    _backgroundWorkerService.InvokeOnUiThread(() =>
                    {
                        MessageBoxViewModel.ShowMessage("Could not retrieve open tickets. Please make sure the Cookie value is up to date in your ini file.");
                        Progress.Label = String.Empty;
                    });
                    var filename = Path.Combine(Path.GetTempPath(), String.Format("raTickets{0}.html", page));
                    File.Delete(filename);
                    return;
                }

                pageTickets = GetPageTickets(games, tickets, ticketsPage);

                ++page;
                totalTickets += pageTickets;
                Progress.Current++;
            } while (pageTickets == 100);

            Progress.Label = "Sorting data";

            var ticketList = new List <AchievementTickets>(tickets.Count);

            foreach (var kvp in tickets)
            {
                ticketList.Add(kvp.Value);
            }
            ticketList.Sort((l, r) =>
            {
                var diff = r.OpenTickets.Count - l.OpenTickets.Count;
                if (diff == 0)
                {
                    diff = String.Compare(l.AchievementName, r.AchievementName, StringComparison.OrdinalIgnoreCase);
                }
                return(diff);
            });

            TopAchievements = ticketList;

            var gameList = new List <GameTickets>(games.Count);

            foreach (var kvp in games)
            {
                gameList.Add(kvp.Value);
            }
            gameList.Sort((l, r) =>
            {
                var diff = r.OpenTickets - l.OpenTickets;
                if (diff == 0)
                {
                    diff = String.Compare(l.GameName, r.GameName, StringComparison.OrdinalIgnoreCase);
                }
                return(diff);
            });

            TopGames = gameList;

            OpenTickets = totalTickets;
            DialogTitle = "Open Tickets: " + totalTickets;

            Progress.Label = String.Empty;
        }
예제 #4
0
        private void DoSearch()
        {
            var criteria = new SearchCriteria();

            ((RangeFilterFieldViewModel)NumConditions).Parse(out criteria.NumConditions, out criteria.NumConditionsComparison);
            ((RangeFilterFieldViewModel)NumAltGroups).Parse(out criteria.NumAltGroups, out criteria.NumAltGroupsComparison);

            criteria.Flag       = (RequirementType)Flag.SelectedId;
            criteria.SourceType = (FieldType)SourceType.SelectedId;
            ((RangeFilterFieldViewModel)SourceValue).Parse(out criteria.SourceValue, out criteria.SourceValueComparison);
            criteria.Comparison = (RequirementOperator)Comparison.SelectedId;
            criteria.TargetType = (FieldType)TargetType.SelectedId;
            ((RangeFilterFieldViewModel)TargetValue).Parse(out criteria.TargetValue, out criteria.TargetValueComparison);
            ((RangeFilterFieldViewModel)HitCount).Parse(out criteria.HitCount, out criteria.HitCountComparison);

            var directory = _settings.DumpDirectory;

            var filesToRead = 0;

            if (IsCoreAchievementsScanned || IsNonCoreAchievementsScanned)
            {
                filesToRead += Snapshot.AchievementGameCount;
            }
            if (IsLeaderboardCancelScanned || IsLeaderboardStartScanned || IsLeaderboardSubmitScanned)
            {
                filesToRead += Snapshot.LeaderboardGameCount;
            }
            if (IsRichPresenceScanned)
            {
                filesToRead += Snapshot.RichPresenceCount;
            }

            Progress.Reset(filesToRead);
            Progress.IsEnabled = true;

            var results = new List <Result>();

            if (IsCoreAchievementsScanned || IsNonCoreAchievementsScanned)
            {
                Progress.Label = "Processing Achievements...";

                foreach (var gameId in Snapshot.GamesWithAchievements)
                {
                    Progress.Current++;
                    if (!Progress.IsEnabled)
                    {
                        break;
                    }

                    var file      = Path.Combine(directory, gameId + ".json");
                    var contents  = File.ReadAllText(file);
                    var json      = new Jamiras.IO.Serialization.JsonObject(contents);
                    var patchData = json.GetField("PatchData");

                    var achievements = patchData.ObjectValue.GetField("Achievements").ObjectArrayValue;
                    if (achievements == null)
                    {
                        continue;
                    }

                    var gameName = patchData.ObjectValue.GetField("Title").StringValue;

                    foreach (var achievement in achievements)
                    {
                        var flags = achievement.GetField("Flags").IntegerValue;
                        if (!IsCoreAchievementsScanned)
                        {
                            if (flags == 3)
                            {
                                continue;
                            }
                        }
                        else if (!IsNonCoreAchievementsScanned)
                        {
                            if (flags != 3)
                            {
                                continue;
                            }
                        }

                        var memAddr = achievement.GetField("MemAddr").StringValue;
                        if (Matches(memAddr, criteria))
                        {
                            results.Add(new Result
                            {
                                GameId        = gameId,
                                GameName      = gameName,
                                AchievementId = achievement.GetField("ID").IntegerValue.GetValueOrDefault(),
                                ItemName      = achievement.GetField("Title").StringValue,
                                Details       = memAddr,
                                IsUnofficial  = flags == 5
                            });
                        }
                    }
                }
            }

            if (IsLeaderboardStartScanned || IsLeaderboardSubmitScanned || IsLeaderboardCancelScanned)
            {
                Progress.Label = "Processing Leaderboards...";

                foreach (var gameId in Snapshot.GamesWithLeaderboards)
                {
                    Progress.Current++;
                    if (!Progress.IsEnabled)
                    {
                        break;
                    }

                    var file      = Path.Combine(directory, gameId + ".json");
                    var contents  = File.ReadAllText(file);
                    var json      = new Jamiras.IO.Serialization.JsonObject(contents);
                    var patchData = json.GetField("PatchData");

                    var leaderboards = patchData.ObjectValue.GetField("Leaderboards").ObjectArrayValue;
                    if (leaderboards == null)
                    {
                        continue;
                    }

                    var gameName = patchData.ObjectValue.GetField("Title").StringValue;

                    foreach (var leaderboard in leaderboards)
                    {
                        var details = String.Empty;

                        var token   = Token.Empty;
                        var memAddr = leaderboard.GetField("Mem").StringValue;
                        foreach (var part in Tokenizer.Split(memAddr, ':'))
                        {
                            if (part == "STA" && IsLeaderboardStartScanned)
                            {
                                token = part;
                                continue;
                            }
                            if (part == "CAN" && IsLeaderboardCancelScanned)
                            {
                                token = part;
                                continue;
                            }
                            if (part == "SUB" && IsLeaderboardSubmitScanned)
                            {
                                token = part;
                                continue;
                            }
                            if (token.IsEmpty)
                            {
                                continue;
                            }

                            if (Matches(part.ToString(), criteria))
                            {
                                if (details.Length > 0)
                                {
                                    details += ", ";
                                }
                                details += token.ToString();
                                details += ':';
                                details += part.ToString();
                            }

                            token = Token.Empty;
                        }

                        if (details.Length > 0)
                        {
                            results.Add(new Result
                            {
                                GameId        = gameId,
                                GameName      = gameName,
                                LeaderboardId = leaderboard.GetField("ID").IntegerValue.GetValueOrDefault(),
                                ItemName      = "Leaderboard: " + leaderboard.GetField("Title").StringValue,
                                Details       = details,
                            });
                        }
                    }
                }
            }

            if (IsRichPresenceScanned)
            {
                Progress.Label = "Processing Rich Presence...";

                foreach (var gameId in Snapshot.GamesWithRichPresence)
                {
                    Progress.Current++;
                    if (!Progress.IsEnabled)
                    {
                        break;
                    }

                    var file      = Path.Combine(directory, gameId + ".json");
                    var contents  = File.ReadAllText(file);
                    var json      = new Jamiras.IO.Serialization.JsonObject(contents);
                    var patchData = json.GetField("PatchData");

                    var richPresence = patchData.ObjectValue.GetField("RichPresencePatch").StringValue;
                    if (richPresence != null)
                    {
                        int index = richPresence.IndexOf("Display:");
                        if (index != -1)
                        {
                            var details = String.Empty;

                            foreach (var line in richPresence.Substring(index).Split('\n'))
                            {
                                if (line.Trim().Length == 0)
                                {
                                    break;
                                }

                                if (line.StartsWith("?"))
                                {
                                    index = line.IndexOf('?', 1);
                                    if (index != -1)
                                    {
                                        var memAddr = line.Substring(1, index - 1);
                                        if (Matches(memAddr, criteria))
                                        {
                                            if (details.Length > 0)
                                            {
                                                details += ", ";
                                            }
                                            details += '?';
                                            details += memAddr;
                                            details += '?';
                                        }
                                    }
                                }
                            }

                            if (details.Length > 0)
                            {
                                results.Add(new Result
                                {
                                    GameId   = gameId,
                                    GameName = patchData.ObjectValue.GetField("Title").StringValue,
                                    ItemName = "Rich Presence",
                                    Details  = details,
                                });
                            }
                        }
                    }
                }
            }

            if (Progress.IsEnabled)
            {
                results.Sort((l, r) =>
                {
                    var diff = String.Compare(l.GameName, r.GameName);
                    if (diff == 0)
                    {
                        diff = String.Compare(l.ItemName, r.ItemName);
                    }

                    return(diff);
                });

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

                Progress.IsEnabled = false;
                Progress.Label     = String.Empty;
            }
        }
예제 #5
0
        internal void LoadGameFromServer(string gamePage, List <AchievementStats> achievementStats, List <UserStats> userStats)
        {
            NumberOfPlayers = 0; // reset so it gets updated from server data

            AchievementStats mostWon, leastWon;

            TotalPoints = LoadAchievementStatsFromServer(gamePage, achievementStats, out mostWon, out leastWon);

            var masteryPoints = (TotalPoints * 2).ToString();
            var masters       = GetMastersFromServer(gamePage, masteryPoints);

            Progress.Label = "Fetching user stats";
            Progress.Reset(achievementStats.Count);

            achievementStats.Sort((l, r) =>
            {
                var diff = r.EarnedHardcoreBy - l.EarnedHardcoreBy;
                if (diff == 0)
                {
                    diff = String.Compare(l.Title, r.Title, StringComparison.OrdinalIgnoreCase);
                }

                return(diff);
            });

            var possibleMasters  = new List <string>();
            var nonHardcoreUsers = new List <string>();

            foreach (var achievement in achievementStats)
            {
                var achievementPage = RAWebCache.Instance.GetAchievementPage(achievement.Id);
                if (achievementPage != null)
                {
                    var tokenizer = Tokenizer.CreateTokenizer(achievementPage);
                    tokenizer.ReadTo("<h3>Winners</h3>");

                    // NOTE: this only lists the ~50 most recent unlocks! For games with more than 50 users who have mastered it, the oldest may be missed!
                    do
                    {
                        var front = tokenizer.ReadTo("<a href='/user/");
                        if (tokenizer.NextChar == '\0')
                        {
                            break;
                        }

                        if (front.Contains("<div id=\"rightcontainer\">"))
                        {
                            break;
                        }

                        tokenizer.ReadTo("'>");
                        tokenizer.Advance(2);

                        // skip user image, we'll get the name from the text
                        var user = tokenizer.ReadTo("</a>");
                        if (user.StartsWith("<img"))
                        {
                            continue;
                        }

                        var mid = tokenizer.ReadTo("<small>");
                        if (mid.Contains("Hardcore!"))
                        {
                            tokenizer.Advance(7);
                            var when = tokenizer.ReadTo("</small>");
                            var date = DateTime.Parse(when.ToString());
                            date = DateTime.SpecifyKind(date, DateTimeKind.Utc);

                            var stats = new UserStats {
                                User = user.ToString()
                            };
                            var index = userStats.BinarySearch(stats, stats);
                            if (index < 0)
                            {
                                userStats.Insert(~index, stats);
                            }
                            else
                            {
                                stats = userStats[index];
                            }

                            stats.Achievements[achievement.Id] = date;

                            if (ReferenceEquals(achievement, leastWon))
                            {
                                if (!masters.Contains(stats.User))
                                {
                                    possibleMasters.Add(stats.User);
                                }
                            }
                        }
                        else
                        {
                            if (!nonHardcoreUsers.Contains(user.ToString()))
                            {
                                nonHardcoreUsers.Add(user.ToString());
                            }
                        }
                    } while (true);
                }

                Progress.Current++;
            }

            // if more than 50 people have earned achievements, people who mastered the game early may no longer display
            // in the individual pages. fetch mastery data by user
            if (mostWon == null || mostWon.EarnedBy <= 50)
            {
                HardcoreMasteredUserCountEstimated = false;
            }
            else
            {
                HardcoreMasteredUserCountEstimated = (leastWon.EarnedBy > 50);

                bool incompleteData = false;
                possibleMasters.AddRange(masters);

                Progress.Reset(possibleMasters.Count);
                foreach (var user in possibleMasters)
                {
                    Progress.Current++;

                    var stats = new UserStats {
                        User = user
                    };
                    var index = userStats.BinarySearch(stats, stats);
                    if (index < 0)
                    {
                        userStats.Insert(~index, stats);
                    }
                    else
                    {
                        stats = userStats[index];
                        if (stats.Achievements.Count >= achievementStats.Count)
                        {
                            continue;
                        }
                    }

                    if (!incompleteData && !MergeUserGameMastery(stats))
                    {
                        incompleteData = true;
                    }

                    stats.Incomplete = incompleteData;
                }

                if (incompleteData)
                {
                    _backgroundWorkerService.InvokeOnUiThread(() =>
                    {
                        var settings = ServiceRepository.Instance.FindService <ISettings>();
                        if (String.IsNullOrEmpty(settings.ApiKey))
                        {
                            MessageBoxViewModel.ShowMessage("Data is limited without an ApiKey in the ini file.");
                        }
                        else
                        {
                            MessageBoxViewModel.ShowMessage("Failed to fetch mastery information. Please make sure the ApiKey value is up to date in your ini file.");
                        }
                    });
                }
            }

            NonHardcoreUserCount = nonHardcoreUsers.Count;

            WriteGameStats(_gameName, achievementStats, userStats);
        }