public override void Execute() { var workingBeatmap = new ProcessorWorkingBeatmap(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); var difficultyAttributes = difficultyCalculator.Calculate(LegacyHelper.TrimNonDifficultyAdjustmentMods(ruleset, score.ScoreInfo.Mods).ToArray()); var performanceCalculator = score.ScoreInfo.Ruleset.CreateInstance().CreatePerformanceCalculator(difficultyAttributes, score.ScoreInfo); var categoryAttribs = new Dictionary <string, double>(); double pp = performanceCalculator.Calculate(categoryAttribs); 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"); foreach (var kvp in categoryAttribs) { writeAttribute(kvp.Key, kvp.Value.ToString(CultureInfo.InvariantCulture)); } writeAttribute("pp", pp.ToString(CultureInfo.InvariantCulture)); Console.WriteLine(); } }
public void SetNewMap(MapSearchResult map) { lock (_lockingObject) { if ((map.Action & OsuStatus.ResultsScreen) != 0) { return; } if (map.FoundBeatmaps && map.BeatmapsFound[0].IsValidBeatmap(_settings, out var mapLocation)) { _sliderBreaks = 0; _lastMisses = 0; _lastCombo = 0; if (map.SearchArgs.EventType == OsuEventType.MapChange) { var workingBeatmap = new ProcessorWorkingBeatmap(mapLocation); var mods = map.Mods?.WorkingMods ?? ""; _rawData.SetCurrentMap(map.BeatmapsFound[0], mods, mapLocation, (PlayMode)PpCalculatorHelpers.GetRulesetId(workingBeatmap.RulesetID, map.PlayMode.HasValue ? (int?)map.PlayMode : null)); } _newPlayStarted.Set(); } } }
public void Execute() { var workingBeatmap = new ProcessorWorkingBeatmap(command.Beatmap); var scoreParser = new ProcessorScoreParser(workingBeatmap); foreach (var f in command.Replays) { Score score; using (var stream = File.OpenRead(f)) score = scoreParser.Parse(stream); workingBeatmap.Mods.Value = score.ScoreInfo.Mods; // Convert + process beatmap var categoryAttribs = new Dictionary <string, double>(); double pp = score.ScoreInfo.Ruleset.CreateInstance().CreatePerformanceCalculator(workingBeatmap, score.ScoreInfo).Calculate(categoryAttribs); command.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"); foreach (var kvp in categoryAttribs) { writeAttribute(kvp.Key, kvp.Value.ToString(CultureInfo.InvariantCulture)); } writeAttribute("pp", pp.ToString(CultureInfo.InvariantCulture)); command.Console.WriteLine(); } }
public void SetNewMap(MapSearchResult map) { lock (_lockingObject) { if ((map.Action & OsuStatus.ResultsScreen) != 0) { return; } OutputPatterns.Clear(); if (map.FoundBeatmaps && map.BeatmapsFound[0].IsValidBeatmap(_settings, out var mapLocation)) { var workingBeatmap = new ProcessorWorkingBeatmap(mapLocation); var mods = map.Mods?.WorkingMods ?? ""; _rawData.SetCurrentMap(map.BeatmapsFound[0], mods, mapLocation, (PlayMode)PpCalculatorHelpers.GetRulesetId(workingBeatmap.RulesetID, map.PlayMode.HasValue ? (int?)map.PlayMode : null)); CopyPatterns(map.FormatedStrings); } else { _rawData.SetCurrentMap(null, "", null, PlayMode.Osu); } } }
public override void Execute() { var ruleset = Ruleset; var mods = getMods(ruleset).ToArray(); var workingBeatmap = new ProcessorWorkingBeatmap(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 scoreInfo = new ScoreInfo { Accuracy = accuracy, MaxCombo = maxCombo, Statistics = statistics, Mods = mods, TotalScore = score, RulesetID = Ruleset.RulesetInfo.ID ?? 0 }; var categoryAttribs = new Dictionary <string, double>(); double pp = ruleset.CreatePerformanceCalculator(workingBeatmap, scoreInfo).Calculate(categoryAttribs); System.Console.WriteLine(pp); }
public override void Execute() { var ruleset = Ruleset; var mods = getMods(ruleset).ToArray(); var workingBeatmap = new ProcessorWorkingBeatmap(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 scoreInfo = new ScoreInfo { Accuracy = accuracy, MaxCombo = maxCombo, Statistics = statistics, Mods = mods, TotalScore = score }; var categoryAttribs = new Dictionary <string, double>(); double pp = ruleset.CreatePerformanceCalculator(workingBeatmap, scoreInfo).Calculate(categoryAttribs); if (OutputAsJSON ?? false) { var playInfo = new Dictionary <string, dynamic>(); WritePlayInfoToDict(playInfo, scoreInfo, beatmap); OutputJSON(new SimulationResults { BeatmapInfo = workingBeatmap.BeatmapInfo.ToString(), Mods = mods.Select(m => m.Acronym).ToList(), CategoryAttribs = categoryAttribs, PlayInfo = playInfo, PP = pp }); } else { Console.WriteLine(workingBeatmap.BeatmapInfo.ToString()); WritePlayInfo(scoreInfo, beatmap); WriteAttribute("Mods", mods.Length > 0 ? mods.Select(m => m.Acronym).Aggregate((c, n) => $"{c}, {n}") : "None"); foreach (var kvp in categoryAttribs) { WriteAttribute(kvp.Key, kvp.Value.ToString(CultureInfo.InvariantCulture)); } WriteAttribute("pp", pp.ToString(CultureInfo.InvariantCulture)); } }
public override void Execute() { var results = new List <Result>(); if (Directory.Exists(Path)) { foreach (string file in Directory.GetFiles(Path, "*.osu", SearchOption.AllDirectories)) { var beatmap = new ProcessorWorkingBeatmap(file); results.Add(processBeatmap(beatmap)); } } else { results.Add(processBeatmap(new ProcessorWorkingBeatmap(Path))); } var document = new Document(); foreach (var group in results.GroupBy(r => r.RulesetId)) { var ruleset = LegacyHelper.GetRulesetFromLegacyID(group.First().RulesetId); document.Children.Add(new Span($"Ruleset: {ruleset.ShortName}"), "\n"); var grid = new Grid(); grid.Columns.Add(GridLength.Auto, GridLength.Auto); grid.Children.Add(new Cell("beatmap"), new Cell("star rating")); foreach (var attribute in group.First().AttributeData) { grid.Columns.Add(GridLength.Auto); grid.Children.Add(new Cell(attribute.name)); } foreach (var result in group) { grid.Children.Add(new Cell(result.Beatmap), new Cell(result.Stars) { Align = Align.Right }); foreach (var attribute in result.AttributeData) { grid.Children.Add(new Cell(attribute.value) { Align = Align.Right }); } } document.Children.Add(grid); document.Children.Add("\n"); } OutputDocument(document); }
public void ProcessBeatmap(string beatmap_path, string[] mods) { ProcessorWorkingBeatmap beatmap = new ProcessorWorkingBeatmap(beatmap_path); // Get the ruleset var ruleset = LegacyHelper.GetRulesetFromLegacyID(beatmap.BeatmapInfo.RulesetID); var attributes = ruleset.CreateDifficultyCalculator(beatmap).Calculate(getMods(ruleset, mods).ToArray()); var beatmapName = $"{beatmap.BeatmapInfo.OnlineBeatmapID} - {beatmap.BeatmapInfo}"; if (beatmapName.Length > 100) { beatmapName = beatmapName.Substring(0, 100) + "..."; } var result = new Result { RulesetId = ruleset.RulesetInfo.ID ?? 0, Beatmap = beatmapName, Stars = attributes.StarRating.ToString("N3") }; result.AttributeData = new List <(string, object)> { }; CalcResults = new Document(); CalcResults.Children.Add(new Span($"Ruleset: {ruleset.ShortName}"), "\n"); var grid = new Grid(); grid.Columns.Add(GridLength.Auto, GridLength.Auto); grid.Children.Add(new Cell("beatmap"), new Cell("star rating")); foreach (var attribute in result.AttributeData) { grid.Columns.Add(GridLength.Auto); grid.Children.Add(new Cell(attribute.name)); } grid.Children.Add(new Cell(result.Beatmap), new Cell(result.Stars) { Align = Align.Right }); foreach (var attribute in result.AttributeData) { grid.Children.Add(new Cell(attribute.value) { Align = Align.Right }); } CalcResults.Children.Add(grid); CalcResults.Children.Add("\n"); }
private static StrainsResult GetStrains(string mapLocation, PlayMode?desiredPlayMode) { var workingBeatmap = new ProcessorWorkingBeatmap(mapLocation); var playMode = (PlayMode)PpCalculatorHelpers.GetRulesetId(workingBeatmap.RulesetID, desiredPlayMode.HasValue ? (int?)desiredPlayMode : null); var ppCalculator = PpCalculatorHelpers.GetPpCalculator((int)playMode, mapLocation, null); //Length refers to beatmap time, not song total time var mapLength = workingBeatmap.Length; var strainLength = 5000; var interval = 1500; var time = 0; var strains = new Dictionary <int, double>(300); if (ppCalculator == null) { while (time + strainLength / 2 < mapLength) { strains.Add(time, 50); time += interval; } } else if (playMode == PlayMode.Osu || playMode == PlayMode.Taiko || playMode == PlayMode.OsuMania) { var a = new Dictionary <string, double>(); while (time + strainLength / 2 < mapLength) { var strain = ppCalculator.Calculate(time, time + strainLength, a); if (double.IsNaN(strain) || strain < 0) { strain = 0; } else if (strain > 2000) { strain = 2000; //lets not freeze everything with aspire/fancy 100* maps } strains.Add(time, strain); time += interval; a.Clear(); } } return(new StrainsResult { Strains = strains, PpCalculator = ppCalculator, WorkingBeatmap = workingBeatmap, PlayMode = playMode, MapLocation = mapLocation }); }
public static async Task <double> CalculatePerformancePoints(Score score) { var beatmapMd5 = await GetBeatmap(score.FileChecksum, score.Beatmap.Id); var beatmap = new ProcessorWorkingBeatmap($"./data/beatmaps/{beatmapMd5}.osu"); var psp = new ProcessorScoreDecoder(beatmap); var parsedScore = psp.Parse(score, $"./data/osr/{score.ReplayChecksum}.osr"); var categoryAttribs = new Dictionary <string, double>(); var pp = parsedScore.ScoreInfo.Ruleset .CreateInstance() .CreatePerformanceCalculator(beatmap, parsedScore.ScoreInfo) .Calculate(categoryAttribs); return(pp); }
public override void Execute() { if (Directory.Exists(Path)) { foreach (string file in Directory.GetFiles(Path, "*.osu", SearchOption.AllDirectories)) { var beatmap = new ProcessorWorkingBeatmap(file); Console.WriteLine(beatmap.BeatmapInfo.ToString()); processBeatmap(beatmap); } } else { processBeatmap(new ProcessorWorkingBeatmap(Path)); } }
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 static async Task <double> CalculatePerformancePoints(DbScore score) { var beatmapMd5 = await GetBeatmapByMd5(score.FileChecksum); if (beatmapMd5 == string.Empty) { return(0.0); } var workingBeatmap = new ProcessorWorkingBeatmap($"./data/beatmaps/{beatmapMd5}.osu"); var psp = new ProcessorScoreDecoder(workingBeatmap); var parsedScore = psp.Parse(score); var categoryAttribs = new Dictionary <string, double>(); var pp = parsedScore.ScoreInfo.Ruleset .CreateInstance() .CreatePerformanceCalculator(workingBeatmap, parsedScore.ScoreInfo) .Calculate(categoryAttribs); return(pp); }
public override void Execute() { var document = new Document(); if (Directory.Exists(Path)) { foreach (string file in Directory.GetFiles(Path, "*.osu", SearchOption.AllDirectories)) { var beatmap = new ProcessorWorkingBeatmap(file); document.Children.Add(new Span(beatmap.BeatmapInfo.ToString()), "\n"); processBeatmap(beatmap, document); } } else { var beatmap = new ProcessorWorkingBeatmap(Path); document.Children.Add(new Span(beatmap.BeatmapInfo.ToString()), "\n"); processBeatmap(beatmap, document); } OutputDocument(document); }
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 displayPlays = new List <UserPlayInfo>(); var ruleset = LegacyHelper.GetRulesetFromLegacyID(Ruleset ?? 0); Console.WriteLine("Getting user data..."); dynamic userData = getJsonFromApi($"get_user?k={Key}&u={ProfileName}&m={Ruleset}")[0]; Console.WriteLine("Getting user top scores..."); foreach (var play in getJsonFromApi($"get_user_best?k={Key}&u={ProfileName}&m={Ruleset}&limit=100")) { string beatmapID = play.beatmap_id; string cachePath = Path.Combine("cache", $"{beatmapID}.osu"); if (!File.Exists(cachePath)) { Console.WriteLine($"Downloading {beatmapID}.osu..."); new FileWebRequest(cachePath, $"{base_url}/osu/{beatmapID}").Perform(); } Mod[] mods = ruleset.ConvertFromLegacyMods((LegacyMods)play.enabled_mods).ToArray(); var working = new ProcessorWorkingBeatmap(cachePath, (int)play.beatmap_id); var score = new ProcessorScoreDecoder(working).Parse(new ScoreInfo { Ruleset = ruleset.RulesetInfo, MaxCombo = play.maxcombo, Mods = mods, Statistics = new Dictionary <HitResult, int> { { HitResult.Perfect, (int)play.countgeki }, { HitResult.Great, (int)play.count300 }, { HitResult.Good, (int)play.count100 }, { HitResult.Ok, (int)play.countkatu }, { HitResult.Meh, (int)play.count50 }, { HitResult.Miss, (int)play.countmiss } } }); var thisPlay = new UserPlayInfo { Beatmap = working.BeatmapInfo, LocalPP = ruleset.CreatePerformanceCalculator(working, score.ScoreInfo).Calculate(), LivePP = play.pp, Mods = mods.Length > 0 ? mods.Select(m => m.Acronym).Aggregate((c, n) => $"{c}, {n}") : "None" }; 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.pp_raw; 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; 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 }, Children = { new Cell("beatmap"), new Cell("live pp"), new Cell("local pp"), new Cell("pp change"), new Cell("position change"), localOrdered.Select(item => new[] { new Cell($"{item.Beatmap.OnlineBeatmapID} - {item.Beatmap}"), 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 displayPlays = new List <UserPlayInfo>(); var ruleset = LegacyHelper.GetRulesetFromLegacyID(Ruleset ?? 0); Console.WriteLine("Getting user data..."); dynamic userData = getJsonFromApi($"get_user?k={Key}&u={ProfileName}&m={Ruleset}")[0]; Console.WriteLine("Getting user top scores..."); foreach (var play in getJsonFromApi($"get_user_best?k={Key}&u={ProfileName}&m={Ruleset}&limit=100")) { string beatmapID = play.beatmap_id; string cachePath = Path.Combine("cache", $"{beatmapID}.osu"); if (!File.Exists(cachePath)) { Console.WriteLine($"Downloading {beatmapID}.osu..."); new FileWebRequest(cachePath, $"{base_url}/osu/{beatmapID}").Perform(); } var working = new ProcessorWorkingBeatmap(cachePath, (int)play.beatmap_id); var scoreInfo = new ScoreInfo { Ruleset = ruleset.RulesetInfo, TotalScore = play.score, MaxCombo = play.maxcombo, Mods = ruleset.ConvertFromLegacyMods((LegacyMods)play.enabled_mods).ToArray(), Statistics = new Dictionary <HitResult, int>() }; scoreInfo.SetCount300((int)play.count300); scoreInfo.SetCountGeki((int)play.countgeki); scoreInfo.SetCount100((int)play.count100); scoreInfo.SetCountKatu((int)play.countkatu); scoreInfo.SetCount50((int)play.count50); scoreInfo.SetCountMiss((int)play.countmiss); var score = new ProcessorScoreDecoder(working).Parse(scoreInfo); var difficultyCalculator = ruleset.CreateDifficultyCalculator(working); var difficultyAttributes = difficultyCalculator.Calculate(LegacyHelper.TrimNonDifficultyAdjustmentMods(ruleset, scoreInfo.Mods).ToArray()); var performanceCalculator = ruleset.CreatePerformanceCalculator(difficultyAttributes, score.ScoreInfo); var categories = new Dictionary <string, double>(); var localPP = performanceCalculator.Calculate(categories); var thisPlay = new UserPlayInfo { Beatmap = working.BeatmapInfo, LocalPP = localPP, LivePP = play.pp, Mods = scoreInfo.Mods.Select(m => m.Acronym).ToArray(), MissCount = play.countmiss, Accuracy = scoreInfo.Accuracy * 100, Combo = play.maxcombo, MaxCombo = (int)categories.GetValueOrDefault("Max Combo") }; 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.pp_raw; 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.OnlineBeatmapID, 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.OnlineBeatmapID} - {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 ruleset = Ruleset; var mods = getMods(ruleset).ToArray(); var workingBeatmap = new ProcessorWorkingBeatmap(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 scoreInfo = new ScoreInfo { Accuracy = accuracy, MaxCombo = maxCombo, Statistics = statistics, Mods = mods, TotalScore = score, RulesetID = Ruleset.RulesetInfo.ID ?? 0 }; var categoryAttribs = new Dictionary <string, double>(); double pp = ruleset.CreatePerformanceCalculator(workingBeatmap, scoreInfo).Calculate(categoryAttribs); if (OutputJson) { var o = new JObject { { "Beatmap", workingBeatmap.BeatmapInfo.ToString() } }; foreach (var info in getPlayValues(scoreInfo, beatmap)) { o[info.Key] = info.Value; } o["Mods"] = mods.Length > 0 ? mods.Select(m => m.Acronym).Aggregate((c, n) => $"{c}, {n}") : "None"; foreach (var kvp in categoryAttribs) { o[kvp.Key] = kvp.Value; } o["pp"] = pp; string json = o.ToString(); Console.Write(json); if (OutputFile != null) { File.WriteAllText(OutputFile, json); } } else { var document = new Document(); document.Children.Add(new Span(workingBeatmap.BeatmapInfo.ToString()), "\n"); document.Children.Add(new Span(GetPlayInfo(scoreInfo, beatmap)), "\n"); document.Children.Add(new Span(GetAttribute("Mods", mods.Length > 0 ? mods.Select(m => m.Acronym).Aggregate((c, n) => $"{c}, {n}") : "None")), "\n"); foreach (var kvp in categoryAttribs) { document.Children.Add(new Span(GetAttribute(kvp.Key, kvp.Value.ToString(CultureInfo.InvariantCulture))), "\n"); } document.Children.Add(new Span(GetAttribute("pp", pp.ToString(CultureInfo.InvariantCulture)))); OutputDocument(document); } }
public override void Execute() { if (Database == "false") { var displayPlays = new List <UserPlayInfo>(); var ruleset = LegacyHelper.GetRulesetFromLegacyID(Ruleset ?? 0); Console.WriteLine("Getting user data..."); dynamic userData = getJsonFromApi($"get_user?k={Key}&u={ProfileName}&m={Ruleset}")[0]; Console.WriteLine("Getting user top scores..."); foreach (var play in getJsonFromApi($"get_user_best?k={Key}&u={ProfileName}&m={Ruleset}&limit=100")) { string beatmapID = play.beatmap_id; string cachePath = Path.Combine("cache", $"{beatmapID}.osu"); if (!File.Exists(cachePath)) { Console.WriteLine($"Downloading {beatmapID}.osu..."); new FileWebRequest(cachePath, $"{base_url}/osu/{beatmapID}").Perform(); } Mod[] mods = ruleset.ConvertLegacyMods((LegacyMods)play.enabled_mods).ToArray(); var working = new ProcessorWorkingBeatmap(cachePath, (int)play.beatmap_id); var score = new ProcessorScoreParser(working).Parse(new ScoreInfo { Ruleset = ruleset.RulesetInfo, MaxCombo = play.maxcombo, Mods = mods, Statistics = new Dictionary <HitResult, int> { { HitResult.Perfect, (int)play.countgeki }, { HitResult.Great, (int)play.count300 }, { HitResult.Good, (int)play.count100 }, { HitResult.Ok, (int)play.countkatu }, { HitResult.Meh, (int)play.count50 }, { HitResult.Miss, (int)play.countmiss } } }); var thisPlay = new UserPlayInfo { Beatmap = working.BeatmapInfo, LocalPP = ruleset.CreatePerformanceCalculator(working, score.ScoreInfo).Calculate(), LivePP = play.pp, Mods = mods.Length > 0 ? mods.Select(m => m.Acronym).Aggregate((c, n) => $"{c}, {n}") : "None" }; 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.pp_raw; 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; 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 }, Children = { new Cell("beatmap"), new Cell("live pp"), new Cell("local pp"), new Cell("pp change"), new Cell("position change"), localOrdered.Select(item => new[] { new Cell($"{item.Beatmap.OnlineBeatmapID} - {item.Beatmap}"), 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 }, }) } } )); } else { var displayPlays = new List <UserPlayInfo>(); var ruleset = LegacyHelper.GetRulesetFromLegacyID(Ruleset ?? 0); Console.WriteLine("Getting user data..."); dynamic userData = getJsonFromApi($"get_user?k={Key}&u={ProfileName}&m={Ruleset}")[0]; string[] config = { }; if (File.Exists("db.cfg")) { config = File.ReadAllLines("db.cfg"); } else { File.AppendAllLines("db.cfg", new string[] { "server=", "database=", "mysqlUsername="******"mySqlPassword="******"config file generated, fill it in, and rerun this program"); Environment.Exit(-1); } MySqlConnection connection = new MySqlConnection($"server={config[0].Split("=")[1]};database={config[1].Split("=")[1]};uid={config[2].Split("=")[1]};password={config[3].Split("=")[1]}"); MySqlCommand cmd = new MySqlCommand($"SELECT * FROM `osu_scores_high` WHERE `user_id` = {userData.user_id}", connection); connection.Open(); MySqlDataReader rdr = cmd.ExecuteReader(); List <string> buffer = new List <string>(); while (rdr.Read()) { int pp = 0; try { pp = rdr.GetInt32("pp"); string beatmap_id = rdr.GetString("beatmap_id"); string[] blacklist = { "1257904" }; if (beatmap_id != blacklist[0]) { buffer.Add($"{beatmap_id}|{rdr.GetString("enabled_mods")}|{rdr.GetInt32("maxcombo")}|{rdr.GetInt32("countgeki")}|{rdr.GetInt32("count300")}|{rdr.GetInt32("count100")}|{rdr.GetInt32("countkatu")}|{rdr.GetInt32("count50")}|{rdr.GetInt32("countmiss")}|{pp}\n"); } } catch (Exception e) { if (e.Message.Contains("null")) { pp = 0; } continue; } } foreach (string s in buffer) { string[] split = s.Split('|'); string beatmapID = split[0]; string cachePath = Path.Combine("cache", $"{beatmapID}.osu"); if (!File.Exists(cachePath)) { Console.WriteLine($"Downloading {beatmapID}.osu..."); new FileWebRequest(cachePath, $"{base_url}/osu/{beatmapID}").Perform(); } Mod[] mods = ruleset.ConvertLegacyMods((LegacyMods)int.Parse(split[1])).ToArray(); var working = new ProcessorWorkingBeatmap(cachePath, int.Parse(split[0])); var score = new ProcessorScoreParser(working).Parse(new ScoreInfo { Ruleset = ruleset.RulesetInfo, MaxCombo = int.Parse(split[2]), Mods = mods, Statistics = new Dictionary <HitResult, int> { { HitResult.Perfect, int.Parse(split[3]) }, { HitResult.Great, int.Parse(split[4]) }, { HitResult.Good, int.Parse(split[5]) }, { HitResult.Ok, int.Parse(split[6]) }, { HitResult.Meh, int.Parse(split[7]) }, { HitResult.Miss, int.Parse(split[8]) } } }); var thisPlay = new UserPlayInfo { Beatmap = working.BeatmapInfo, LocalPP = ruleset.CreatePerformanceCalculator(working, score.ScoreInfo).Calculate(), LivePP = int.Parse(split[9]), Mods = mods.Length > 0 ? mods.Select(m => m.Acronym).Aggregate((c, n) => $"{c}, {n}") : "None" }; 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.pp_raw; 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; 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 }, Children = { new Cell("beatmap"), new Cell("live pp"), new Cell("local pp"), new Cell("pp change"), new Cell("position change"), localOrdered.Select(item => new[] { new Cell($"{item.Beatmap.OnlineBeatmapID} - {item.Beatmap}"), 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 ruleset = new OsuRuleset(); var allLines = File.ReadAllLines(ScoreSetsPath).Select(a => a.Split(',')); var lines = allLines.Where(l => l[0] == SetName); var sw = new StringWriter(); sw.WriteLine("ID, Beatmap, Mods, Combo, Max Combo, Accuracy, Aim pp, Tap pp, Acc pp, pp"); foreach (var l in lines) { var s = new Score(l); var mods = s.Mods.ToArray(); string beatmapID = s.ID; string cachePath = Path.Combine("cache", $"{beatmapID}.osu"); if (!File.Exists(cachePath)) { Console.WriteLine($"Downloading {beatmapID}.osu..."); new FileWebRequest(cachePath, $"{base_url}/osu/{beatmapID}").Perform(); } var workingBeatmap = new ProcessorWorkingBeatmap(cachePath); var beatmap = workingBeatmap.GetPlayableBeatmap(ruleset.RulesetInfo, mods); var beatmapMaxCombo = getMaxCombo(beatmap); var maxCombo = (int)Math.Round(s.PercentCombo / 100 * beatmapMaxCombo); var accuracy = s.Accuracy; var statistics = generateHitResults(accuracy, beatmap, s.MissCount); var scoreInfo = new ScoreInfo { Accuracy = accuracy, MaxCombo = maxCombo, Statistics = statistics, Mods = mods, }; var categoryAttribs = new Dictionary <string, double>(); double pp = ruleset.CreatePerformanceCalculator(workingBeatmap, scoreInfo).Calculate(categoryAttribs); var resultLine = new List <string>() { beatmap.BeatmapInfo.OnlineBeatmapID.ToString(), beatmap.BeatmapInfo.ToString().Replace(",", ";"), string.Join("", s.ModStrings), maxCombo.ToString(), beatmapMaxCombo.ToString(), (accuracy * 100).ToString("F2"), categoryAttribs["Aim"].ToString("F2"), categoryAttribs["Tap"].ToString("F2"), categoryAttribs["Accuracy"].ToString("F2"), pp.ToString("F2") }; sw.WriteLine(string.Join(", ", resultLine)); } if (OutputFile == null) { Console.Write(sw.ToString()); } else { File.WriteAllText(OutputFile, sw.ToString()); } sw.Dispose(); }
public Tokens GetMapReplacements(MapSearchResult map) { var ret = new Tokens { { "GameMode", new Token(null) }, { "MaxCombo", new Token(null) }, { "SSPP", new Token(null) }, { "99.9PP", new Token(null) }, { "99PP", new Token(null) }, { "98PP", new Token(null) }, { "95PP", new Token(null) }, { "90PP", new Token(null) }, { "1 000 000PP", new Token(null) }, { "990 000PP", new Token(null) }, { "950 000PP", new Token(null) }, { "900 000PP", new Token(null) }, { "800 000PP", new Token(null) }, { "700 000PP", new Token(null) }, { "600 000PP", new Token(null) }, { "mMod", new Token(null) }, { "mSSPP", new Token(null) }, { "m99.9PP", new Token(null) }, { "m99PP", new Token(null) }, { "m98PP", new Token(null) }, { "m95PP", new Token(null) }, { "m90PP", new Token(null) }, { "m1 000 000PP", new Token(null) }, { "m990 000PP", new Token(null) }, { "m950 000PP", new Token(null) }, { "m900 000PP", new Token(null) }, { "m800 000PP", new Token(null) }, { "m700 000PP", new Token(null) }, { "m600 000PP", new Token(null) }, }; if (!map.FoundBeatmaps || !map.BeatmapsFound[0].IsValidBeatmap(_settings, out var mapLocation) ) { return(ret); } var workingBeatmap = new ProcessorWorkingBeatmap(mapLocation); var playMode = (PlayMode)PpCalculatorHelpers.GetRulesetId(workingBeatmap.RulesetID, map.PlayMode.HasValue ? (int?)map.PlayMode : null); _ppCalculator = PpCalculatorHelpers.GetPpCalculator((int)playMode, mapLocation, _ppCalculator); if (_ppCalculator == null) { return(ret);//Ctb not supported :( } if (playMode == PlayMode.OsuMania) { _ppCalculator.Score = 1_000_000; } else { _ppCalculator.Score = 0; } _ppCalculator.Mods = null; ret["GameMode"] = new TokenWithFormat(playMode.ToString()); string mods = ""; if (playMode == PlayMode.OsuMania) { ret["1 000 000PP"] = new TokenWithFormat(GetPp(_ppCalculator, 0, mods, 1_000_000), format: PpFormat); ret["990 000PP"] = new TokenWithFormat(GetPp(_ppCalculator, 0, mods, 990_000), format: PpFormat); ret["950 000PP"] = new TokenWithFormat(GetPp(_ppCalculator, 0, mods, 950_000), format: PpFormat); ret["900 000PP"] = new TokenWithFormat(GetPp(_ppCalculator, 0, mods, 900_000), format: PpFormat); ret["800 000PP"] = new TokenWithFormat(GetPp(_ppCalculator, 0, mods, 800_000), format: PpFormat); ret["700 000PP"] = new TokenWithFormat(GetPp(_ppCalculator, 0, mods, 700_000), format: PpFormat); ret["600 000PP"] = new TokenWithFormat(GetPp(_ppCalculator, 0, mods, 600_000), format: PpFormat); } else { ret["SSPP"] = new TokenWithFormat(GetPp(_ppCalculator, 100d), format: PpFormat); ret["99.9PP"] = new TokenWithFormat(GetPp(_ppCalculator, 99.9d), format: PpFormat); ret["99PP"] = new TokenWithFormat(GetPp(_ppCalculator, 99d), format: PpFormat); ret["98PP"] = new TokenWithFormat(GetPp(_ppCalculator, 98d), format: PpFormat); ret["95PP"] = new TokenWithFormat(GetPp(_ppCalculator, 95d), format: PpFormat); ret["90PP"] = new TokenWithFormat(GetPp(_ppCalculator, 90d), format: PpFormat); } ret["MaxCombo"] = new TokenWithFormat(_ppCalculator.GetMaxCombo()); string modsStr; if (map.Action == OsuStatus.Playing || map.Action == OsuStatus.Watching) { mods = map.Mods?.WorkingMods ?? ""; modsStr = map.Mods?.ShownMods ?? ""; _lastShortMods = mods; _lastModsStr = modsStr; } else { mods = _lastShortMods; modsStr = _lastModsStr; } ret["mMod"] = new Token(modsStr); if (playMode == PlayMode.OsuMania) { ret["m1 000 000PP"] = new TokenWithFormat(GetPp(_ppCalculator, 0, mods, 1_000_000), format: PpFormat); ret["m990 000PP"] = new TokenWithFormat(GetPp(_ppCalculator, 0, mods, 990_000), format: PpFormat); ret["m950 000PP"] = new TokenWithFormat(GetPp(_ppCalculator, 0, mods, 950_000), format: PpFormat); ret["m900 000PP"] = new TokenWithFormat(GetPp(_ppCalculator, 0, mods, 900_000), format: PpFormat); ret["m800 000PP"] = new TokenWithFormat(GetPp(_ppCalculator, 0, mods, 800_000), format: PpFormat); ret["m700 000PP"] = new TokenWithFormat(GetPp(_ppCalculator, 0, mods, 700_000), format: PpFormat); ret["m600 000PP"] = new TokenWithFormat(GetPp(_ppCalculator, 0, mods, 600_000), format: PpFormat); } else { ret["mSSPP"] = new TokenWithFormat(GetPp(_ppCalculator, 100d, mods), format: PpFormat); ret["m99.9PP"] = new TokenWithFormat(GetPp(_ppCalculator, 99.9d, mods), format: PpFormat); ret["m99PP"] = new TokenWithFormat(GetPp(_ppCalculator, 99d, mods), format: PpFormat); ret["m98PP"] = new TokenWithFormat(GetPp(_ppCalculator, 98d, mods), format: PpFormat); ret["m95PP"] = new TokenWithFormat(GetPp(_ppCalculator, 95d, mods), format: PpFormat); ret["m90PP"] = new TokenWithFormat(GetPp(_ppCalculator, 90d, mods), format: PpFormat); } return(ret); }
public void CreateTokens(MapSearchResult map) { foreach (var tokenkv in Tokens.AllTokens.Where(t => t.Value.PluginName == Name)) { tokenkv.Value.Reset(); } if (!map.FoundBeatmaps || !map.BeatmapsFound[0].IsValidBeatmap(_settings, out var mapLocation)) { return; } var workingBeatmap = new ProcessorWorkingBeatmap(mapLocation); var playMode = (PlayMode)PpCalculatorHelpers.GetRulesetId(workingBeatmap.RulesetID, map.PlayMode.HasValue ? (int?)map.PlayMode : null); _ppCalculator = PpCalculatorHelpers.GetPpCalculator((int)playMode, mapLocation, _ppCalculator); if (_ppCalculator == null) { return;//Ctb not supported :( } if (playMode == PlayMode.OsuMania) { _ppCalculator.Score = 1_000_000; } else { _ppCalculator.Score = 0; } _ppCalculator.Mods = null; _tokenSetter("GameMode", playMode.ToString()); string mods = ""; if (playMode == PlayMode.OsuMania) { _tokenSetter("1 000 000PP", GetPp(_ppCalculator, 0, mods, 1_000_000), format: PpFormat); _tokenSetter("990 000PP", GetPp(_ppCalculator, 0, mods, 990_000), format: PpFormat); _tokenSetter("950 000PP", GetPp(_ppCalculator, 0, mods, 950_000), format: PpFormat); _tokenSetter("900 000PP", GetPp(_ppCalculator, 0, mods, 900_000), format: PpFormat); _tokenSetter("800 000PP", GetPp(_ppCalculator, 0, mods, 800_000), format: PpFormat); _tokenSetter("700 000PP", GetPp(_ppCalculator, 0, mods, 700_000), format: PpFormat); _tokenSetter("600 000PP", GetPp(_ppCalculator, 0, mods, 600_000), format: PpFormat); } else { _tokenSetter("SSPP", GetPp(_ppCalculator, 100d), format: PpFormat); _tokenSetter("99.9PP", GetPp(_ppCalculator, 99.9d), format: PpFormat); _tokenSetter("99PP", GetPp(_ppCalculator, 99d), format: PpFormat); _tokenSetter("98PP", GetPp(_ppCalculator, 98d), format: PpFormat); _tokenSetter("95PP", GetPp(_ppCalculator, 95d), format: PpFormat); _tokenSetter("90PP", GetPp(_ppCalculator, 90d), format: PpFormat); } _tokenSetter("MaxCombo", _ppCalculator.GetMaxCombo()); mods = map.Mods?.WorkingMods ?? ""; if (playMode == PlayMode.OsuMania) { _tokenSetter("m1 000 000PP", GetPp(_ppCalculator, 0, mods, 1_000_000), format: PpFormat); _tokenSetter("m990 000PP", GetPp(_ppCalculator, 0, mods, 990_000), format: PpFormat); _tokenSetter("m950 000PP", GetPp(_ppCalculator, 0, mods, 950_000), format: PpFormat); _tokenSetter("m900 000PP", GetPp(_ppCalculator, 0, mods, 900_000), format: PpFormat); _tokenSetter("m800 000PP", GetPp(_ppCalculator, 0, mods, 800_000), format: PpFormat); _tokenSetter("m700 000PP", GetPp(_ppCalculator, 0, mods, 700_000), format: PpFormat); _tokenSetter("m600 000PP", GetPp(_ppCalculator, 0, mods, 600_000), format: PpFormat); } else { _tokenSetter("mSSPP", GetPp(_ppCalculator, 100d, mods), format: PpFormat); _tokenSetter("m99.9PP", GetPp(_ppCalculator, 99.9d, mods), format: PpFormat); _tokenSetter("m99PP", GetPp(_ppCalculator, 99d, mods), format: PpFormat); _tokenSetter("m98PP", GetPp(_ppCalculator, 98d, mods), format: PpFormat); _tokenSetter("m95PP", GetPp(_ppCalculator, 95d, mods), format: PpFormat); _tokenSetter("m90PP", GetPp(_ppCalculator, 90d, mods), format: PpFormat); } }
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 displayPlays = new List <UserPlayInfo>(); var ruleset = LegacyHelper.GetRulesetFromLegacyID(Ruleset ?? 0); Console.WriteLine("Getting user data..."); dynamic userData = getJsonFromApi($"get_user?k={Key}&u={ProfileName}&m={Ruleset}")[0]; Console.WriteLine("Getting user top scores..."); foreach (var play in getJsonFromApi($"get_user_best?k={Key}&u={ProfileName}&m={Ruleset}&limit=100")) { string beatmapID = play.beatmap_id; string cachePath = Path.Combine("cache", $"{beatmapID}.osu"); if (!File.Exists(cachePath)) { Console.WriteLine($"Downloading {beatmapID}.osu..."); new FileWebRequest(cachePath, $"{base_url}/osu/{beatmapID}").Perform(); } Mod[] mods = ruleset.ConvertFromLegacyMods((LegacyMods)play.enabled_mods).ToArray(); var working = new ProcessorWorkingBeatmap(cachePath, (int)play.beatmap_id); var scoreInfo = new ScoreInfo { Ruleset = ruleset.RulesetInfo, MaxCombo = play.maxcombo, Mods = mods, Statistics = new Dictionary <HitResult, int> { { HitResult.Perfect, (int)play.countgeki }, { HitResult.Great, (int)play.count300 }, { HitResult.Good, (int)play.countkatu }, { HitResult.Ok, (int)play.count100 }, { HitResult.Meh, (int)play.count50 }, { HitResult.Miss, (int)play.countmiss } } }; var score = new ProcessorScoreDecoder(working).Parse(scoreInfo); var categoryAttribs = new Dictionary <string, double>(); OsuPerformanceCalculator calculator = (OsuPerformanceCalculator)ruleset.CreatePerformanceCalculator(working, score.ScoreInfo); double localPP = calculator.Calculate(categoryAttribs); var thisPlay = new UserPlayInfo { Beatmap = working.BeatmapInfo, LocalPP = localPP, MapCategoryAttribs = categoryAttribs, LivePP = play.pp, Mods = mods.Length > 0 ? mods.Select(m => m.Acronym).Aggregate((c, n) => $"{c}|{n}") : "", PlayMaxCombo = scoreInfo.MaxCombo, BeatmapMaxCombo = calculator.Attributes.MaxCombo, PlayAccuracy = scoreInfo.Accuracy, MissCount = scoreInfo.Statistics[HitResult.Miss] }; 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.pp_raw; 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; for (int i = 0; i < localOrdered.Count; i++) { localOrdered[i].Position = i + 1; } if (SortColumnName != null) { localOrdered.Sort((s1, s2) => s2.MapCategoryAttribs[SortColumnName].CompareTo(s1.MapCategoryAttribs[SortColumnName])); } foreach (var playInfo in localOrdered) { if (playInfo.Beatmap.ToString().Length > max_name_length) { playInfo.MapName = "..." + playInfo.Beatmap.ToString().Substring(playInfo.Beatmap.ToString().Length - max_name_length); } else { playInfo.MapName = playInfo.Beatmap.ToString(); } } Grid grid = new Grid(); ExtraColumns = new string[] { "Aim", "Speed", "Accuracy" }; grid.Columns.Add(createColumns(10 + (ExtraColumns?.Length ?? 0))); grid.Children.Add( new Cell("#") { Align = Align.Center }, new Cell("beatmap"), new Cell("mods") { Align = Align.Center }, new Cell("live pp"), new Cell("acc") { Align = Align.Center }, new Cell("miss"), new Cell("combo") { Align = Align.Center } ); if (ExtraColumns != null) { foreach (var extraColumn in ExtraColumns) { grid.Children.Add(new Cell(extraColumn) { Align = Align.Center }); } } grid.Children.Add( new Cell("local pp"), new Cell("pp change"), new Cell("position change") ); grid.Children.Add(localOrdered.Select((item) => { List <Cell> cells = new List <Cell> { new Cell(item.Position) { Align = Align.Left }, new Cell($" {item.Beatmap.OnlineBeatmapID} - {item.MapName}"), new Cell(item.Mods) { Align = Align.Right }, new Cell($"{item.LivePP:F1}") { Align = Align.Right }, new Cell($"{item.PlayAccuracy * 100f:F2}" + " %") { Align = Align.Right }, new Cell($"{item.MissCount}") { Align = Align.Right }, new Cell($"{item.PlayMaxCombo}/{item.BeatmapMaxCombo}") { Align = Align.Right }, }; if (ExtraColumns != null) { cells.AddRange(ExtraColumns.Select(extraColumn => new Cell($"{item.MapCategoryAttribs[extraColumn]:F1}") { Align = Align.Right })); } cells.AddRange(new List <Cell> { 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 }, } ); return(cells); })); 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", grid )); }
public override void Execute() { var ruleset = Ruleset; var mods = GetMods(ruleset).ToArray(); if (!Beatmap.EndsWith(".osu")) { if (!int.TryParse(Beatmap, out _)) { Console.WriteLine("Incorrect beatmap ID."); return; } string cachePath = Path.Combine("cache", $"{Beatmap}.osu"); if (!File.Exists(cachePath)) { Console.WriteLine($"Downloading {Beatmap}.osu..."); new FileWebRequest(cachePath, $"https://osu.ppy.sh/osu/{Beatmap}").Perform(); } Beatmap = cachePath; } var workingBeatmap = new ProcessorWorkingBeatmap(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 scoreInfo = new ScoreInfo { Accuracy = accuracy, MaxCombo = maxCombo, Statistics = statistics, Mods = mods, TotalScore = score, RulesetID = Ruleset.RulesetInfo.ID ?? 0 }; var difficultyCalculator = ruleset.CreateDifficultyCalculator(workingBeatmap); var difficultyAttributes = difficultyCalculator.Calculate(LegacyHelper.TrimNonDifficultyAdjustmentMods(ruleset, scoreInfo.Mods).ToArray()); var performanceCalculator = ruleset.CreatePerformanceCalculator(difficultyAttributes, scoreInfo); var categoryAttribs = new Dictionary <string, double>(); double pp = performanceCalculator.Calculate(categoryAttribs); if (OutputJson) { var o = new JObject { { "Beatmap", workingBeatmap.BeatmapInfo.ToString() } }; foreach (var info in getPlayValues(scoreInfo, beatmap)) { o[info.Key] = info.Value; } o["Mods"] = mods.Length > 0 ? mods.Select(m => m.Acronym).Aggregate((c, n) => $"{c}, {n}") : "None"; foreach (var kvp in categoryAttribs) { o[kvp.Key] = kvp.Value; } o["pp"] = pp; string json = o.ToString(); Console.Write(json); if (OutputFile != null) { File.WriteAllText(OutputFile, json); } } else { var document = new Document(); document.Children.Add(new Span(workingBeatmap.BeatmapInfo.ToString()), "\n"); document.Children.Add(new Span(GetPlayInfo(scoreInfo, beatmap)), "\n"); document.Children.Add(new Span(GetAttribute("Mods", mods.Length > 0 ? mods.Select(m => m.Acronym).Aggregate((c, n) => $"{c}, {n}") : "None")), "\n"); foreach (var kvp in categoryAttribs) { document.Children.Add(new Span(GetAttribute(kvp.Key, kvp.Value.ToString(CultureInfo.InvariantCulture))), "\n"); } document.Children.Add(new Span(GetAttribute("pp", pp.ToString(CultureInfo.InvariantCulture)))); OutputDocument(document); } }
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 async Task ExecuteAsync(Label status_block) { if (Key == "" || ProfileName == "") { return; } var displayPlays = new List <UserPlayInfo>(); var ruleset = LegacyHelper.GetRulesetFromLegacyID(0); status_block.Dispatcher.Invoke(() => { status_block.Content = "Getting user data..."; }); dynamic userData = await getJsonFromApi($"get_user?k={Key}&u={ProfileName}&m={0}"); if (!((JArray)userData).Any()) { ResultsDoc = new Document(new Span("Could not find user " + ProfileName)); return; } userData = userData[0]; status_block.Dispatcher.Invoke(() => { status_block.Content = "Getting user top scores..."; }); foreach (var play in await getJsonFromApi($"get_user_best?k={Key}&u={ProfileName}&m={0}&limit=100")) { string beatmapID = play.beatmap_id; string cachePath = Path.Combine("cache", $"{beatmapID}.osu"); if (!File.Exists(cachePath)) { status_block.Dispatcher.Invoke(() => { status_block.Content = $"Downloading {beatmapID}.osu..."; }); await new FileWebRequest(cachePath, $"{base_url}/osu/{beatmapID}").PerformAsync(); } Mod[] mods = ruleset.ConvertFromLegacyMods((LegacyMods)play.enabled_mods).ToArray(); var working = new ProcessorWorkingBeatmap(cachePath, (int)play.beatmap_id); var scoreInfo = new ScoreInfo { Ruleset = ruleset.RulesetInfo, MaxCombo = play.maxcombo, Mods = mods, Statistics = new Dictionary <HitResult, int> { { HitResult.Perfect, (int)play.countgeki }, { HitResult.Great, (int)play.count300 }, { HitResult.Good, (int)play.countkatu }, { HitResult.Ok, (int)play.count100 }, { HitResult.Meh, (int)play.count50 }, { HitResult.Miss, (int)play.countmiss } } }; var score = new ProcessorScoreDecoder(working).Parse(scoreInfo); var categoryAttribs = new Dictionary <string, double>(); OsuPerformanceCalculator calculator = (OsuPerformanceCalculator)ruleset.CreatePerformanceCalculator(working, score.ScoreInfo); double localPP = calculator.Calculate(categoryAttribs); var thisPlay = new UserPlayInfo { Beatmap = working.BeatmapInfo, LocalPP = localPP, AimPP = categoryAttribs["Aim"], TapPP = categoryAttribs["Speed"], AccPP = categoryAttribs["Accuracy"], LivePP = play.pp, Mods = mods.Length > 0 ? mods.Select(m => m.Acronym).Aggregate((c, n) => $"{c}, {n}") : "", PlayMaxCombo = scoreInfo.MaxCombo, BeatmapMaxCombo = calculator.Attributes.MaxCombo, PlayAccuracy = scoreInfo.Accuracy, MissCount = scoreInfo.Statistics[HitResult.Miss] }; 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.pp_raw; 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; ResultsDoc = 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 Alba.CsConsoleFormat.Grid { Columns = { GridLength.Auto, GridLength.Auto, GridLength.Auto, GridLength.Auto, GridLength.Auto, GridLength.Auto, GridLength.Auto, GridLength.Auto, GridLength.Auto, GridLength.Auto, GridLength.Auto, GridLength.Auto }, Children = { new Cell("beatmap"), new Cell("mods") { Align = Align.Center }, new Cell("live pp"), new Cell("acc") { Align = Align.Center }, new Cell("miss"), new Cell("combo") { Align = Align.Center }, new Cell("aim pp"), new Cell("tap pp"), new Cell("acc pp"), new Cell("local pp"), new Cell("pp change"), new Cell("position change"), localOrdered.Select(item => new[] { new Cell($"{item.Beatmap.OnlineBeatmapID} - {item.Beatmap.ToString().Substring(0, Math.Min(80, item.Beatmap.ToString().Length))}"), new Cell(item.Mods) { Align = Align.Center }, new Cell($"{item.LivePP:F1}") { Align = Align.Right }, new Cell($"{item.PlayAccuracy * 100f:F2}" + " %") { Align = Align.Center }, new Cell($"{item.MissCount}") { Align = Align.Center }, new Cell($"{item.PlayMaxCombo}/{item.BeatmapMaxCombo}") { Align = Align.Center }, new Cell($"{item.AimPP:F1}") { Align = Align.Right }, new Cell($"{item.TapPP:F1}") { Align = Align.Right }, new Cell($"{item.AccPP: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 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); } }