private OsuJsonUserBest[] ProcessJson(OsuJsonUserBest[] array) { var oldarray = array; if (Recent) { array = array.OrderByDescending(x => x.date).Take(5).ToArray(); } foreach (var item in array) { item.play_number = (Array.IndexOf(oldarray, item) + 1); OsuUtil.GetCalculatedAccuracy(item, Mode); //Get Beatmap last update item.Beatmap = GetBeatmap(item.beatmap_id); if (item.enabled_mods > 0) { //Star rating var data = OsuDlBeatmap.FindMap(item.beatmap_id, item.Beatmap.last_update.DateTime); var diff = new DiffCalc().Calc(Beatmap.Read(new StreamReader(new MemoryStream(data, false))), (Mods)item.enabled_mods); item.starrating = diff.Total; } } return(array); }
public void TestSinglePlay() { const int id = 774965; if (!File.Exists($"{id}.osu")) { new WebClient().DownloadFile($"https://osu.ppy.sh/osu/{id}", $"{id}.osu"); } var reader = new StreamReader($"{id}.osu"); //read a beatmap var beatmap = Beatmap.Read(reader); //calculate star ratings for HDDT Mods mods = Mods.Hidden | Mods.DoubleTime; var stars = new DiffCalc().Calc(beatmap, mods); output.WriteLine($"Star rating: {stars.Total:F2} (aim stars: {stars.Aim:F2}, speed stars: {stars.Speed:F2})"); //calculate the PP for this map //the play has no misses or 50's, so we don't specify it var pp = new PPv2(new PPv2Parameters(beatmap, stars, c100: 8, mods: mods, combo: 1773)); output.WriteLine($"Play is worth {pp.Total:F2}pp ({pp.Aim:F2} aim pp, {pp.Acc:F2} acc pp, {pp.Speed:F2} " + $"speed pp) and has an accuracy of {pp.ComputedAccuracy.Value() * 100:F2}%"); Assert.InRange(775.99, pp.Total - 1, pp.Total + 1); }
private OsuJsonUserRecent[] ProcessJson(OsuJsonUserRecent[] array, bool retrycount) { foreach (var item in array) { if (retrycount) { continue; } //Get Beatmap last update var beatmapBuilder = new OsuBeatmapBuilder { Mode = Mode, ConvertedIncluded = "1", BeatmapId = item.beatmap_id }; item.Beatmap = beatmapBuilder.Execute().First(); OsuUtil.GetCalculatedAccuracy(item, Mode); var data = OsuDlBeatmap.FindMap(item.beatmap_id, item.Beatmap.last_update.DateTime); var beatmapData = Beatmap.Read(new StreamReader(new MemoryStream(data, false))); var diff = new DiffCalc().Calc(beatmapData, (Mods)item.enabled_mods); var rawPp = new PPv2(new PPv2Parameters(beatmapData, diff, new Accuracy(item.count300, item.count100, item.count50, item.countmiss).Value(), item.countmiss, item.maxcombo, (Mods)item.enabled_mods)); item.nochokeaccuracy = new Accuracy(item.count300 + item.countmiss, item.count100, item.count50, 0).Value() * 100; var nochokePp = new PPv2(new PPv2Parameters(beatmapData, diff, item.nochokeaccuracy / 100, 0, diff.Beatmap.GetMaxCombo(), (Mods)item.enabled_mods)); item.pp = rawPp.Total; item.nochokepp = nochokePp.Total; item.rounded_score = item.score.ToString("C0", _nfi); if (item.maxcombo <= (beatmapData.GetMaxCombo() - (item.count100 + item.count50)) || item.rank == "XH" || item.rank == "SH") { item.choked = true; } else if (item.countmiss > 0) { item.choked = true; } item.starrating = diff.Total; item.counttotal = beatmapData.CountCircles + beatmapData.CountSliders + beatmapData.CountSpinners; item.rounded_score = item.score.ToString("C0", _nfi); item.standardhit = item.count300 + item.count100 + item.count50 + item.countmiss; item.hitted = item.countkatu + item.countgeki + item.count300 + item.count100 + item.count50 + item.countmiss; item.completion = item.standardhit / (double)item.counttotal * 100; } return(array); }
public PPCalc(int maxCombo, int amount300, int amount100, int amountKatu, int amount50, int amountMiss, Modifiers mods, Beatmap map) { this.maxCombo = maxCombo; this.amount300 = amount300; this.amount100 = amount100; this.amountKatu = amountKatu; this.amount50 = amount50; this.amountMiss = amountMiss; this.mods = mods; this.map = map; this.difficulty = new DiffCalc(map); ComputeTotalValue(); }
internal static void PrintPP(Beatmap map, Mods[] allMods) { Console.WriteLine($"Map: {map.Artist} - {map.Title} [{map.Version}]"); Console.WriteLine($"Mapper: {map.Creator}"); Console.WriteLine(); Console.WriteLine($"CS{map.CS} AR{map.AR} OD{map.OD} HP{map.HP}"); Console.WriteLine(); for (int i = 0; i <= (1 << allMods.Length) - 1; i++) { var mods = Mods.NoMod; for (int j = 0; j <= allMods.Length; j++) { if ((i & 1 << j) != 0) { mods |= allMods[j]; } } var diff = new DiffCalc().Calc(map, mods); var modStr = OppaiSharp.Helpers.ModsToString(mods); if (string.IsNullOrWhiteSpace(modStr)) { modStr = "NoMod"; } void ShowWithPercent(double percent) { var acc = new Accuracy(percent, map.Objects.Count, 0); var pp = new PPv2(new PPv2Parameters { Beatmap = map, Mods = mods, AimStars = diff.Aim, SpeedStars = diff.Speed, Count300 = acc.Count300, Count100 = acc.Count100, Count50 = acc.Count50, CountMiss = acc.CountMiss }); Console.Write($" | {$"{pp.Total:F2}pp".PadRight(9)} ({percent.ToString(CultureInfo.InvariantCulture)}%)"); } Console.Write($"{modStr.PadRight(6)}| {diff.Total:F2}* (Aim: {diff.Aim:F2}*, Speed: {diff.Speed:F2}*)"); ShowWithPercent(92.5); ShowWithPercent(95); ShowWithPercent(97.5); ShowWithPercent(100); Console.WriteLine(); } }
private List <OsuJsonUserBest> ProcessSingle(OsuJsonUserBest[] array) { List <OsuJsonUserBest> list = new List <OsuJsonUserBest> { array[(int)PlayNumber - 1] }; if (list[0].enabled_mods > 0) { var data = OsuDlBeatmap.FindMap(list[0].beatmap_id, list[0].Beatmap.last_update.DateTime); var diff = new DiffCalc().Calc(Beatmap.Read(new StreamReader(new MemoryStream(data, false))), (Mods)list[0].enabled_mods); list[0].starrating = diff.Total; } list[0].Beatmap = GetBeatmap(list[0].beatmap_id); return(list); }
public void TestManyHundreds() { const int id = 706711; if (!File.Exists($"{id}.osu")) { new WebClient().DownloadFile($"https://osu.ppy.sh/osu/{id}", $"{id}.osu"); } var reader = new StreamReader($"{id}.osu"); //read a beatmap var beatmap = Beatmap.Read(reader); var stars = new DiffCalc().Calc(beatmap); var pp = new PPv2(new PPv2Parameters(beatmap, stars, beatmap.CountCircles + 1)); //not checking the actual value, just making sure that it doesn't throw }
private static PPv2 CalcPP(BeatmapBase beatmap, LegacyMods mods = LegacyMods.NM, double acc = -1, int combo = -1, int misses = 0, bool cache = false) { try { var mapCachePath = Path.Combine(cache_path, $"{beatmap.Id}_{(int)(mods & LegacyMods.DifficultyChanging)}.json"); var ppParams = GetCachedPPv2Parameters(mapCachePath); if (ppParams != null) { ppParams.Accuracy = acc / 100; ppParams.Combo = combo; ppParams.CountMiss = misses; ppParams.Mods = (Mods)mods; return(new PPv2(ppParams)); } using (var stream = new MemoryStream(beatmap.FileBytes, false)) using (var reader = new StreamReader(stream, true)) { Beatmap map = Beatmap.Read(reader); DiffCalc diff = new DiffCalc().Calc(map, (Mods)mods); ppParams = new PPv2Parameters(map, diff, acc / 100, misses, combo, (Mods)mods); if (cache) { CachePPv2Parameters(mapCachePath, ppParams); } return(new PPv2(ppParams)); } } catch (Exception e) { Log.Error($"CalcPP failed, ${e.InnerMessageIfAny()}"); } return(null); }
public async Task LinkParserMethod(SocketMessage s, EmbedBuilder embed, SocketCommandContext context) { stopWatch.Start(); string link = $"{s}"; string mapID = link.Split('/').Last(); //Gets the map's ID from the link. if (mapID.Contains('?')) { mapID = mapID.Replace("?m=0", ""); } string jsonMapParse; string jsonOsuMapData; using (WebClient client = new WebClient()) { jsonMapParse = client.DownloadString($"https://api.tillerino.org/beatmapinfo?beatmapid={mapID}&k={tillerinoapikey}"); } using (WebClient client = new WebClient()) { jsonOsuMapData = client.DownloadString($"https://osu.ppy.sh/api/get_beatmaps?k={osuapikey}&b={mapID}"); } var mapObject = JsonConvert.DeserializeObject <dynamic>(jsonMapParse); var mapData = JsonConvert.DeserializeObject <dynamic>(jsonOsuMapData)[0]; //osu! API Data string mapTitle = mapData.title; string beatmapSetID = mapData.beatmapset_id; string artist = mapData.artist; string creator = mapData.creator; string creatorID = mapData.creator_id; string difficulty = mapData.version; double starRating = mapData.difficultyrating; double cs = mapData.diff_size; double od = mapData.diff_overall; double ar = mapData.diff_approach; double hp = mapData.diff_drain; TimeSpan length = TimeSpan.FromSeconds((int)mapData.total_length); double bpm = mapData.bpm; int maxCombo = mapData.max_combo; int favoriteCount = mapData.favourite_count; int playCount = mapData.playcount; int passCount = mapData.passcount; string status = mapData.approved; if (status == "-2" || status == "-1" || status == "0") { switch (status) { case "-2": status = "Graveyard"; break; case "-1": status = "Work in Progress"; break; case "0": status = "Pending"; break; } } else { DateTime approvedDate = mapData.approved_date; switch (status) { case "-2": status = "Graveyard"; break; case "-1": status = "Work in Progress"; break; case "0": status = "Pending"; break; case "1": status = $"Ranked on {approvedDate.ToShortDateString()}"; break; case "2": status = $"Approved on {approvedDate.ToShortDateString()}"; break; case "3": status = $"Qualified on {approvedDate.ToShortDateString()}"; break; case "4": status = $"Loved 💙 on {approvedDate.ToShortDateString()}"; break; } } string lengthValue = length.ToString(@"mm\:ss"); if (status.ToLower() == "graveyard" || status.ToLower() == "work in progress" || status.ToLower() == "pending") { byte[] data = new WebClient().DownloadData($"https://osu.ppy.sh/osu/{mapID}"); var stream = new MemoryStream(data, false); var reader = new StreamReader(stream); var mods = Mods.NoMod; var beatmap = Beatmap.Read(reader); var diff = new DiffCalc().Calc(beatmap, mods: mods); var unranked95 = new PPv2(new PPv2Parameters(beatmap, diff, accuracy: .95, mods: mods)); var unranked98 = new PPv2(new PPv2Parameters(beatmap, diff, accuracy: .98, mods: mods)); var unranked99 = new PPv2(new PPv2Parameters(beatmap, diff, accuracy: .99, mods: mods)); var unranked100 = new PPv2(new PPv2Parameters(beatmap, diff, accuracy: 1, mods: mods)); embed.WithAuthor(author => { author.Name = $"{mapTitle} by {creator}"; author.Url = $"https://osu.ppy.sh/b/{mapID}"; author.IconUrl = $"https://a.ppy.sh/{creatorID}"; }); embed.WithDescription( $"**{mapTitle} [{difficulty}]** by **{artist}**" + $"\n" + $"\n<:total_length:567812515346513932> **Total Length:** {lengthValue} <:bpm:567813349820071937> **BPM:** {bpm.ToString("N0")}" + $"\n**Star Rating:** `{starRating.ToString("N2")} ☆` **Maximum Combo:** `{maxCombo.ToString("N0")}x`" + $"\n**Download:** [[Beatmap]](https://osu.ppy.sh/beatmapsets/{beatmapSetID}/download)" + $"[(without video)](https://osu.ppy.sh/d/{beatmapSetID}n)" + $"\n" + $"\n**CS:** `{(float)cs} ` **AR:** `{(float)ar}` **OD:** `{(float)od}` **HP:** `{(float)hp}`" + $"\n" + $"\n**95% FC:** `{unranked95.Total.ToString("N0")}pp` **98% FC:** `{unranked98.Total.ToString("N0")}pp`" + $"\n**99% FC:** `{unranked99.Total.ToString("N0")}pp` **100% FC (SS):** `{unranked100.Total.ToString("N0")}pp`"); embed.WithFooter($"Status: {status} | 💙 Amount: {favoriteCount}"); embed.WithColor(Pink); await context.Channel.SendMessageAsync("", false, embed.Build()); stopWatch.Stop(); logger.ConsoleCommandLog(context, stopWatch.ElapsedMilliseconds); return; } double passRate = (playCount / passCount); //Tillerino API Data: Performance Point values for full combos on the map with the given accuracy. double value75 = mapObject.ppForAcc.entry[0].value; double value90 = mapObject.ppForAcc.entry[3].value; double value95 = mapObject.ppForAcc.entry[5].value; double value98 = mapObject.ppForAcc.entry[9].value; double value99 = mapObject.ppForAcc.entry[11].value; double value100 = mapObject.ppForAcc.entry[13].value; embed.WithAuthor(author => { author.Name = $"{mapTitle} by {creator}"; author.Url = $"https://osu.ppy.sh/b/{mapID}"; author.IconUrl = $"https://a.ppy.sh/{creatorID}"; }); embed.WithDescription($"**{mapTitle} [{difficulty}]** by **{artist}**" + $"\n" + $"\n<:total_length:567812515346513932> **Total Length:** {lengthValue} <:bpm:567813349820071937> **BPM:** {bpm.ToString("N0")}" + $"\n**Star Rating:** `{starRating.ToString("N2")} ☆` **Maximum Combo:** `{maxCombo}x`" + $"\n**Download:** [[Beatmap]](https://osu.ppy.sh/beatmapsets/{beatmapSetID}/download)" + $"[(without video)](https://osu.ppy.sh/d/{beatmapSetID}n) [[Bloodcat Mirror]](https://bloodcat.com/osu/s/{beatmapSetID})" + $"\n" + $"\n**CS:** `{(float)cs} ` **AR:** `{(float)ar}` **OD:** `{(float)od}` **HP:** `{(float)hp}`" + $"\n" + $"\n**75% FC:** `{(int)value75}pp` **90% FC:** `{(int)value90}pp`" + $"\n**95% FC:** `{(int)value95}pp` **98% FC:** `{(int)value98}pp`" + $"\n**99% FC:** `{(int)value99}pp` **100% FC (SS):** `{(int)value100}pp`"); embed.WithFooter($"Status: {status} | 💙 Amount: {favoriteCount} | Pass Rate: {passRate.ToString("N2")}%"); embed.WithColor(Pink); await context.Channel.SendMessageAsync("", false, embed.Build()); stopWatch.Stop(); logger.ConsoleCommandLog(context, stopWatch.ElapsedMilliseconds); return; }
public async Task osuRecent(string player = null) { stopWatch.Start(); string cmdPrefix = Servers.GetServer(Context.Guild).commandPrefix; string osuapikey = Config.bot.OsuApiKey; if (player == null || player == "") { player = UserAccounts.GetAccount(Context.User).OsuUsername; if (player == null || player == "") { embed.WithTitle("osu! Recent"); embed.WithDescription($"**{Context.User.Mention} Failed to acquire username! Please specify a player or set your osu! username with `{cmdPrefix}osuset`!**"); embed.WithColor(Red); await BE(); return; } } string jsonRecent; using (WebClient client = new WebClient()) { jsonRecent = client.DownloadString($"https://osu.ppy.sh/api/get_user_recent?k={osuapikey}&u=" + player); } if (jsonRecent == "[]") { string jsonUserData; using (WebClient client = new WebClient()) { jsonUserData = client.DownloadString($"https://osu.ppy.sh/api/get_user?k={osuapikey}&u=" + player); } var mapUserNameObject = JsonConvert.DeserializeObject <dynamic>(jsonUserData)[0]; embed.WithAuthor(author => { author .WithName("" + mapUserNameObject.username + " hasn't got any recent plays") .WithIconUrl("https://a.ppy.sh/" + mapUserNameObject.user_id); }); embed.WithColor(Pink); await BE(); } else { var playerRecentObject = JsonConvert.DeserializeObject <dynamic>(jsonRecent)[0]; string mapID = playerRecentObject.beatmap_id; string mapRecent = ""; using (WebClient client = new WebClient()) { mapRecent = client.DownloadString($"https://osu.ppy.sh/api/get_beatmaps?k={osuapikey}&b={mapID}"); } var mapRecentObject = JsonConvert.DeserializeObject <dynamic>(mapRecent)[0]; string mapTitle = mapRecentObject.title; string difficulty = mapRecentObject.version; string score = playerRecentObject.score; double maxCombo = playerRecentObject.maxcombo; string artist = mapRecentObject.artist; double count50 = playerRecentObject.count50; double count100 = playerRecentObject.count100; double count300 = playerRecentObject.count300; double countMiss = playerRecentObject.countmiss; string fullCombo = playerRecentObject.perfect; if (fullCombo == "1") { fullCombo = " **Full Combo!**"; } else { fullCombo = null; } string mods = playerRecentObject.enabled_mods; double maxPossibleCombo = mapRecentObject.max_combo; var modnum = playerRecentObject.enabled_mods; mods = ((AllMods)modnum).ToString().Replace(",", ""); mods = mods.Replace(" ", ""); mods = mods.Replace("NM", ""); string date = playerRecentObject.date; double starRating = mapRecentObject.difficultyrating; double accuracy = 100 * ((50 * count50) + (100 * count100) + (300 * count300)) / ((300 * (countMiss + count50 + count100 + count300))); string grade = playerRecentObject.rank; switch (grade) { case "XH": grade = "<:XH:553119188089176074>"; break; case "X": grade = "<:X_:553119217109565470>"; break; case "SH": grade = "<:SH:553119233463025691>"; break; case "S": grade = "<:S_:553119252329267240>"; break; case "A": grade = "<:A_:553119274256826406>"; break; case "B": grade = "<:B_:553119304925577228>"; break; case "C": grade = "<:C_:553119325565878272>"; break; case "D": grade = "<:D_:553119338035675138>"; break; case "F": grade = "<:F_:557297028263051288>"; break; } string NormalUserName = ""; using (WebClient client = new WebClient()) { NormalUserName = client.DownloadString($"https://osu.ppy.sh/api/get_user?k={osuapikey}&u=" + player); } if (NormalUserName == "[]") { embed.WithDescription($"{Context.User.Mention} **ERROR: Could not download data for {player}!**"); embed.WithColor(Red); await BE(); stopWatch.Stop(); logger.ConsoleCommandLog(Context, stopWatch.ElapsedMilliseconds, CommandError.Unsuccessful, "osu! API did not return any data for the given username."); return; } var mapUserNameObject = JsonConvert.DeserializeObject <dynamic>(NormalUserName)[0]; //PPv2 byte[] data = new WebClient().DownloadData($"https://osu.ppy.sh/osu/{mapID}"); var stream = new MemoryStream(data, false); var reader = new StreamReader(stream); var enabledMods = Mods.NoMod; switch (mods) { case "": enabledMods = Mods.NoMod; break; case "HD": enabledMods = Mods.Hidden; break; case "HR": enabledMods = Mods.Hardrock; break; case "DT": case "NC": enabledMods = Mods.DoubleTime; break; case "FL": enabledMods = Mods.Flashlight; break; case "HDDT": case "HDNC": enabledMods = (int)Mods.DoubleTime + Mods.Hidden; break; case "HDHR": enabledMods = (int)Mods.Hidden + Mods.Hardrock; break; case "HDFL": enabledMods = (int)Mods.Hidden + Mods.Flashlight; break; case "EZ": enabledMods = Mods.Easy; break; case "HDHRDT": case "HDHRNC": enabledMods = (int)Mods.Hidden + (int)Mods.Hardrock + Mods.DoubleTime; break; default: enabledMods = Mods.NoMod; break; } var beatmap = Beatmap.Read(reader); var diff = new DiffCalc().Calc(beatmap, mods: enabledMods); var fullComboPP = new PPv2(new PPv2Parameters(beatmap, diff, accuracy: (accuracy / 100), mods: enabledMods)); //PPv2 End string plus = "+"; var objectsEncountered = (count300 + count100 + count50 + countMiss); var mapCompletion = ((objectsEncountered / beatmap.Objects.Count()) * 100).ToString("N2"); if (plus == "+" && mods == "") { plus = ""; } mods = mods.Replace("576", "NC"); string playerRecentString = $"▸ **{grade}{plus}{mods}** ▸ **[{mapTitle} [{difficulty}]](https://osu.ppy.sh/b/{mapID})** by **{artist}**\n" + $"▸ **☆{starRating.ToString("F")}** ▸ **{accuracy.ToString("F")}%**\n" + $"▸ **Combo:** `{maxCombo.ToString("N0")}x / {maxPossibleCombo.ToString("N0")}x`\n" + $"▸ [300 / 100 / 50 / X]: `[{count300} / {count100} / {count50} / {countMiss}]`\n" + $"▸ **Map Completion:** `{mapCompletion}`%\n" + $"▸ **Full Combo Percentage:** `{((maxCombo / maxPossibleCombo) * 100).ToString("N2")}%`\n" + $"▸ **PP for FC**: `{fullComboPP.Total.ToString("N0")}pp`"; var difference = DateTime.UtcNow - (DateTime)playerRecentObject.date; string footer = $"{mapUserNameObject.username} performed this play {(int)difference.TotalHours} hours {difference.Minutes} minutes and {difference.Seconds} seconds ago."; embed.WithAuthor(author => { author .WithName($"Most Recent osu! Standard Play for " + mapUserNameObject.username) .WithIconUrl("https://a.ppy.sh/" + playerRecentObject.user_id); }); embed.WithDescription($"{playerRecentString}"); embed.WithFooter(footer); embed.WithColor(Pink); await BE(); stopWatch.Stop(); logger.ConsoleCommandLog(Context, stopWatch.ElapsedMilliseconds); } }
public static void Main(string[] args) { Directory.SetCurrentDirectory(Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location)); DebugController debugger = new DebugController(); //Load in custom beatmaps if specified args = debugger.LoadCustom(args); //Display a message if no files are specified if (args.Length == 0) { Console.WriteLine("CTB Difficulty Analyzer"); Console.WriteLine("Just drag your beatmap (.osu file) onto this program to measure difficulty"); Console.WriteLine("Press any key to exit..."); } //Otherwise try to run the program, and catch and display any exceptions that arise else { Console.WriteLine("Calculating..."); SortedList <double, string> beatmaps = new SortedList <double, string>(); List <DiffCalc> calculators = new List <DiffCalc>(); Stopwatch timer = new Stopwatch(); try { int count = 0; foreach (string name in args) { timer.Start(); Beatmap map = new Beatmap(name); DiffCalc calc; try { calc = new DiffCalc(map); } catch (InvalidBeatmapException) { //Skip this beatmap if it's not a standard or ctb map, but only if //it was loaded through debug if (debugger.IsLoadCustom()) { continue; } else { throw; } } string title = calc.GetBeatmapTitle() + ": \t"; double difficulty = calc.GetDifficulty(); timer.Stop(); title += timer.ElapsedMilliseconds; beatmaps[difficulty] = title; calculators.Add(calc); timer.Reset(); count++; Console.Write(Math.Round((double)count * 100 / args.Length) + "%\r"); } Console.WriteLine("\n"); for (int i = beatmaps.Count - 1; i >= 0; i--) { string[] titleandtime = beatmaps.Values[i].Split('\t'); Console.WriteLine(titleandtime[0] + beatmaps.Keys[i]); Console.WriteLine("Calculation Time (ms): " + titleandtime[1] + "\n"); } debugger.WriteDebug(calculators.ToArray()); Console.WriteLine("\nDone."); } catch (Exception e) { Console.WriteLine(e); } finally { //Just in case the timer is still running timer.Stop(); } } Console.ReadKey(); }