public override void Execute() { var workingBeatmap = ProcessorWorkingBeatmap.FromFileOrId(Beatmap); var scoreParser = new ProcessorScoreDecoder(workingBeatmap); foreach (var f in Replays) { Score score; using (var stream = File.OpenRead(f)) score = scoreParser.Parse(stream); var ruleset = score.ScoreInfo.Ruleset.CreateInstance(); var difficultyCalculator = ruleset.CreateDifficultyCalculator(workingBeatmap); Mod[] mods = score.ScoreInfo.Mods; if (score.ScoreInfo.IsLegacyScore) { mods = LegacyHelper.ConvertToLegacyDifficultyAdjustmentMods(ruleset, mods); } var difficultyAttributes = difficultyCalculator.Calculate(mods); var performanceCalculator = score.ScoreInfo.Ruleset.CreateInstance().CreatePerformanceCalculator(); var ppAttributes = performanceCalculator?.Calculate(score.ScoreInfo, difficultyAttributes); Console.WriteLine(f); writeAttribute("Player", score.ScoreInfo.User.Username); writeAttribute("Mods", score.ScoreInfo.Mods.Length > 0 ? score.ScoreInfo.Mods.Select(m => m.Acronym).Aggregate((c, n) => $"{c}, {n}") : "None"); var ppAttributeValues = JsonConvert.DeserializeObject <Dictionary <string, object> >(JsonConvert.SerializeObject(ppAttributes)) ?? new Dictionary <string, object>(); foreach (var attrib in ppAttributeValues) { writeAttribute(attrib.Key.Humanize(), FormattableString.Invariant($"{attrib.Value:N2}")); } Console.WriteLine(); } }
public override void Execute() { var displayPlays = new List <UserPlayInfo>(); var ruleset = LegacyHelper.GetRulesetFromLegacyID(Ruleset ?? 0); var rulesetApiName = LegacyHelper.GetRulesetShortNameFromId(Ruleset ?? 0); Console.WriteLine("Getting user data..."); dynamic userData = GetJsonFromApi($"users/{ProfileName}/{rulesetApiName}"); Console.WriteLine("Getting user top scores..."); foreach (var play in GetJsonFromApi($"users/{userData.id}/scores/best?mode={rulesetApiName}&limit=100")) { var working = ProcessorWorkingBeatmap.FromFileOrId((string)play.beatmap.id); var modsAcronyms = ((JArray)play.mods).Select(x => x.ToString()).ToArray(); Mod[] mods = ruleset.CreateAllMods().Where(m => modsAcronyms.Contains(m.Acronym)).ToArray(); var scoreInfo = new ScoreInfo(working.BeatmapInfo, ruleset.RulesetInfo) { TotalScore = play.score, MaxCombo = play.max_combo, Mods = mods, Statistics = new Dictionary <HitResult, int>() }; scoreInfo.SetCount300((int)play.statistics.count_300); scoreInfo.SetCountGeki((int)play.statistics.count_geki); scoreInfo.SetCount100((int)play.statistics.count_100); scoreInfo.SetCountKatu((int)play.statistics.count_katu); scoreInfo.SetCount50((int)play.statistics.count_50); scoreInfo.SetCountMiss((int)play.statistics.count_miss); var score = new ProcessorScoreDecoder(working).Parse(scoreInfo); var difficultyCalculator = ruleset.CreateDifficultyCalculator(working); var difficultyAttributes = difficultyCalculator.Calculate(LegacyHelper.ConvertToLegacyDifficultyAdjustmentMods(ruleset, scoreInfo.Mods).ToArray()); var performanceCalculator = ruleset.CreatePerformanceCalculator(); var ppAttributes = performanceCalculator?.Calculate(score.ScoreInfo, difficultyAttributes); var thisPlay = new UserPlayInfo { Beatmap = working.BeatmapInfo, LocalPP = ppAttributes?.Total ?? 0, LivePP = play.pp, Mods = scoreInfo.Mods.Select(m => m.Acronym).ToArray(), MissCount = play.statistics.count_miss, Accuracy = scoreInfo.Accuracy * 100, Combo = play.max_combo, MaxCombo = difficultyAttributes.MaxCombo }; displayPlays.Add(thisPlay); } var localOrdered = displayPlays.OrderByDescending(p => p.LocalPP).ToList(); var liveOrdered = displayPlays.OrderByDescending(p => p.LivePP).ToList(); int index = 0; double totalLocalPP = localOrdered.Sum(play => Math.Pow(0.95, index++) * play.LocalPP); double totalLivePP = userData.statistics.pp; index = 0; double nonBonusLivePP = liveOrdered.Sum(play => Math.Pow(0.95, index++) * play.LivePP); //todo: implement properly. this is pretty damn wrong. var playcountBonusPP = (totalLivePP - nonBonusLivePP); totalLocalPP += playcountBonusPP; double totalDiffPP = totalLocalPP - totalLivePP; if (OutputJson) { var json = JsonConvert.SerializeObject(new { Username = userData.username, LivePp = totalLivePP, LocalPp = totalLocalPP, PlaycountPp = playcountBonusPP, Scores = localOrdered.Select(item => new { BeatmapId = item.Beatmap.OnlineID, BeatmapName = item.Beatmap.ToString(), item.Combo, item.Accuracy, item.MissCount, item.Mods, LivePp = item.LivePP, LocalPp = item.LocalPP, PositionChange = liveOrdered.IndexOf(item) - localOrdered.IndexOf(item) }) }); Console.Write(json); if (OutputFile != null) { File.WriteAllText(OutputFile, json); } } else { OutputDocument(new Document( new Span($"User: {userData.username}"), "\n", new Span($"Live PP: {totalLivePP:F1} (including {playcountBonusPP:F1}pp from playcount)"), "\n", new Span($"Local PP: {totalLocalPP:F1} ({totalDiffPP:+0.0;-0.0;-})"), "\n", new Grid { Columns = { GridLength.Auto, GridLength.Auto, GridLength.Auto, GridLength.Auto, GridLength.Auto, GridLength.Auto, GridLength.Auto, GridLength.Auto, GridLength.Auto, GridLength.Auto }, Children = { new Cell("#"), new Cell("beatmap"), new Cell("max combo"), new Cell("accuracy"), new Cell("misses"), new Cell("mods"), new Cell("live pp"), new Cell("local pp"), new Cell("pp change"), new Cell("position change"), localOrdered.Select(item => new[] { new Cell($"{localOrdered.IndexOf(item) + 1}"), new Cell($"{item.Beatmap.OnlineID} - {item.Beatmap}"), new Cell($"{item.Combo}/{item.MaxCombo}x") { Align = Align.Right }, new Cell($"{Math.Round(item.Accuracy, 2)}%") { Align = Align.Right }, new Cell($"{item.MissCount}") { Align = Align.Right }, new Cell($"{(item.Mods.Length > 0 ? string.Join(", ", item.Mods) : "None")}") { Align = Align.Right }, new Cell($"{item.LivePP:F1}") { Align = Align.Right }, new Cell($"{item.LocalPP:F1}") { Align = Align.Right }, new Cell($"{item.LocalPP - item.LivePP:F1}") { Align = Align.Right }, new Cell($"{liveOrdered.IndexOf(item) - localOrdered.IndexOf(item):+0;-0;-}") { Align = Align.Center }, }) } }) ); } }
public override void Execute() { var rulesetApiName = LegacyHelper.GetRulesetShortNameFromId(Ruleset ?? 0); var leaderboard = GetJsonFromApi($"rankings/{rulesetApiName}/performance?cursor[page]={LeaderboardPage - 1}"); var calculatedPlayers = new List <LeaderboardPlayerInfo>(); foreach (var player in leaderboard.ranking) { if (calculatedPlayers.Count >= Limit) { break; } var plays = new List <(double, double)>(); // (local, live) var ruleset = LegacyHelper.GetRulesetFromLegacyID(Ruleset ?? 0); Console.WriteLine($"Calculating {player.user.username} top scores..."); foreach (var play in GetJsonFromApi($"users/{player.user.id}/scores/best?mode={rulesetApiName}&limit=100")) { var working = ProcessorWorkingBeatmap.FromFileOrId((string)play.beatmap.id); var modsAcronyms = ((JArray)play.mods).Select(x => x.ToString()).ToArray(); Mod[] mods = ruleset.CreateAllMods().Where(m => modsAcronyms.Contains(m.Acronym)).ToArray(); var scoreInfo = new ScoreInfo(working.BeatmapInfo, ruleset.RulesetInfo) { TotalScore = play.score, MaxCombo = play.max_combo, Mods = mods, Statistics = new Dictionary <HitResult, int>() }; scoreInfo.SetCount300((int)play.statistics.count_300); scoreInfo.SetCountGeki((int)play.statistics.count_geki); scoreInfo.SetCount100((int)play.statistics.count_100); scoreInfo.SetCountKatu((int)play.statistics.count_katu); scoreInfo.SetCount50((int)play.statistics.count_50); scoreInfo.SetCountMiss((int)play.statistics.count_miss); var score = new ProcessorScoreDecoder(working).Parse(scoreInfo); var difficultyCalculator = ruleset.CreateDifficultyCalculator(working); var difficultyAttributes = difficultyCalculator.Calculate(LegacyHelper.ConvertToLegacyDifficultyAdjustmentMods(ruleset, scoreInfo.Mods).ToArray()); var performanceCalculator = ruleset.CreatePerformanceCalculator(); plays.Add((performanceCalculator?.Calculate(score.ScoreInfo, difficultyAttributes).Total ?? 0, play.pp)); } var localOrdered = plays.Select(x => x.Item1).OrderByDescending(x => x).ToList(); var liveOrdered = plays.Select(x => x.Item2).OrderByDescending(x => x).ToList(); int index = 0; double totalLocalPP = localOrdered.Sum(play => Math.Pow(0.95, index++) * play); double totalLivePP = player.pp; index = 0; double nonBonusLivePP = liveOrdered.Sum(play => Math.Pow(0.95, index++) * play); //todo: implement properly. this is pretty damn wrong. var playcountBonusPP = (totalLivePP - nonBonusLivePP); totalLocalPP += playcountBonusPP; calculatedPlayers.Add(new LeaderboardPlayerInfo { LivePP = totalLivePP, LocalPP = totalLocalPP, Username = player.user.username }); } calculatedPlayers = calculatedPlayers.OrderByDescending(x => x.LocalPP).ToList(); var liveOrderedPlayers = calculatedPlayers.OrderByDescending(x => x.LivePP).ToList(); if (OutputJson) { var json = JsonConvert.SerializeObject(calculatedPlayers); Console.Write(json); if (OutputFile != null) { File.WriteAllText(OutputFile, json); } } else { OutputDocument(new Document( new Grid { Columns = { GridLength.Auto, GridLength.Auto, GridLength.Auto, GridLength.Auto, GridLength.Auto }, Children = { new Cell("#"), new Cell("username"), new Cell("live pp"), new Cell("local pp"), new Cell("pp change"), calculatedPlayers.Select(item => new[] { new Cell($"{liveOrderedPlayers.IndexOf(item) - calculatedPlayers.IndexOf(item):+0;-0;-}"), new Cell($"{item.Username}"), new Cell($"{item.LivePP:F1}") { Align = Align.Right }, new Cell($"{item.LocalPP:F1}") { Align = Align.Right }, new Cell($"{item.LocalPP - item.LivePP:F1}") { Align = Align.Right } }) } }) ); } }
public override void Execute() { var resultSet = new ResultSet(); if (Directory.Exists(Path)) { foreach (string file in Directory.GetFiles(Path, "*.osu", SearchOption.AllDirectories)) { try { var beatmap = new ProcessorWorkingBeatmap(file); resultSet.Results.Add(processBeatmap(beatmap)); } catch (Exception e) { resultSet.Errors.Add($"Processing beatmap \"{file}\" failed:\n{e.Message}"); } } } else { resultSet.Results.Add(processBeatmap(ProcessorWorkingBeatmap.FromFileOrId(Path))); } if (OutputJson) { string json = JsonConvert.SerializeObject(resultSet); Console.WriteLine(json); if (OutputFile != null) { File.WriteAllText(OutputFile, json); } } else { var document = new Document(); foreach (var error in resultSet.Errors) { document.Children.Add(new Span(error), "\n"); } if (resultSet.Errors.Count > 0) { document.Children.Add("\n"); } foreach (var group in resultSet.Results.GroupBy(r => r.RulesetId)) { var ruleset = LegacyHelper.GetRulesetFromLegacyID(group.First().RulesetId); document.Children.Add(new Span($"ruleset: {ruleset.ShortName}"), "\n"); Grid grid = new Grid(); bool firstResult = true; foreach (var result in group) { var attributeValues = JsonConvert.DeserializeObject <Dictionary <string, object> >(JsonConvert.SerializeObject(result.Attributes)) ?? new Dictionary <string, object>(); // Headers if (firstResult) { grid.Columns.Add(GridLength.Auto); grid.Children.Add(new Cell("beatmap")); foreach (var column in attributeValues) { grid.Columns.Add(GridLength.Auto); grid.Children.Add(new Cell(column.Key.Humanize())); } } // Values grid.Children.Add(new Cell($"{result.BeatmapId} - {result.Beatmap}")); foreach (var column in attributeValues) { grid.Children.Add(new Cell($"{column.Value:N2}") { Align = Align.Right }); } firstResult = false; } document.Children.Add(grid, "\n"); } OutputDocument(document); } }
public override void Execute() { var ruleset = Ruleset; var mods = NoClassicMod ? GetMods(ruleset) : LegacyHelper.ConvertToLegacyDifficultyAdjustmentMods(ruleset, GetMods(ruleset)); var workingBeatmap = ProcessorWorkingBeatmap.FromFileOrId(Beatmap); var beatmap = workingBeatmap.GetPlayableBeatmap(ruleset.RulesetInfo, mods); var beatmapMaxCombo = GetMaxCombo(beatmap); var maxCombo = Combo ?? (int)Math.Round(PercentCombo / 100 * beatmapMaxCombo); var statistics = GenerateHitResults(Accuracy / 100, beatmap, Misses, Mehs, Goods); var score = Score; var accuracy = GetAccuracy(statistics); var difficultyCalculator = ruleset.CreateDifficultyCalculator(workingBeatmap); var difficultyAttributes = difficultyCalculator.Calculate(mods); var performanceCalculator = ruleset.CreatePerformanceCalculator(); var ppAttributes = performanceCalculator?.Calculate(new ScoreInfo(beatmap.BeatmapInfo, ruleset.RulesetInfo) { Accuracy = accuracy, MaxCombo = maxCombo, Statistics = statistics, Mods = mods, TotalScore = score, }, difficultyAttributes); var result = new Result { Score = new ScoreStatistics { RulesetId = ruleset.RulesetInfo.OnlineID, BeatmapId = workingBeatmap.BeatmapInfo.OnlineID, Beatmap = workingBeatmap.BeatmapInfo.ToString(), Mods = mods.Select(m => new APIMod(m)).ToList(), Score = score, Accuracy = accuracy * 100, Combo = maxCombo, Statistics = statistics }, PerformanceAttributes = ppAttributes, DifficultyAttributes = difficultyAttributes }; if (OutputJson) { string json = JsonConvert.SerializeObject(result); Console.Write(json); if (OutputFile != null) { File.WriteAllText(OutputFile, json); } } else { var document = new Document(); AddSectionHeader(document, "Basic score info"); document.Children.Add( FormatDocumentLine("beatmap", $"{result.Score.BeatmapId} - {result.Score.Beatmap}"), FormatDocumentLine("score", result.Score.Score.ToString(CultureInfo.InvariantCulture)), FormatDocumentLine("accuracy", result.Score.Accuracy.ToString("N2", CultureInfo.InvariantCulture)), FormatDocumentLine("combo", result.Score.Combo.ToString(CultureInfo.InvariantCulture)), FormatDocumentLine("mods", result.Score.Mods.Count > 0 ? result.Score.Mods.Select(m => m.ToString()).Aggregate((c, n) => $"{c}, {n}") : "None") ); AddSectionHeader(document, "Hit statistics"); foreach (var stat in result.Score.Statistics) { document.Children.Add(FormatDocumentLine(stat.Key.ToString().ToLowerInvariant(), stat.Value.ToString(CultureInfo.InvariantCulture))); } AddSectionHeader(document, "Performance attributes"); var ppAttributeValues = JsonConvert.DeserializeObject <Dictionary <string, object> >(JsonConvert.SerializeObject(result.PerformanceAttributes)) ?? new Dictionary <string, object>(); foreach (var attrib in ppAttributeValues) { document.Children.Add(FormatDocumentLine(attrib.Key.Humanize().ToLower(), FormattableString.Invariant($"{attrib.Value:N2}"))); } AddSectionHeader(document, "Difficulty attributes"); var diffAttributeValues = JsonConvert.DeserializeObject <Dictionary <string, object> >(JsonConvert.SerializeObject(result.DifficultyAttributes)) ?? new Dictionary <string, object>(); foreach (var attrib in diffAttributeValues) { document.Children.Add(FormatDocumentLine(attrib.Key.Humanize(), FormattableString.Invariant($"{attrib.Value:N2}"))); } OutputDocument(document); } }