Skip to content

Commit

Permalink
Refactor osu API requests, switch to Pettanko for pp calculation
Browse files Browse the repository at this point in the history
  • Loading branch information
stanriders committed Dec 9, 2023
1 parent 3258e84 commit bce78c9
Show file tree
Hide file tree
Showing 33 changed files with 588 additions and 698 deletions.
13 changes: 7 additions & 6 deletions den0bot.Modules.Osu/ModBeatmap.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// den0bot (c) StanR 2022 - MIT License
// den0bot (c) StanR 2023 - MIT License
//#define PARSE_PHOTOS
using den0bot.Modules.Osu.Types.V2;
using den0bot.Modules.Osu.WebAPI;
Expand All @@ -15,6 +15,7 @@
using den0bot.Modules.Osu.Types;
using den0bot.Modules.Osu.Types.Enums;
using IronOcr;
using Pettanko;
using Serilog;
using Telegram.Bot.Types;
using Telegram.Bot.Types.InputFiles;
Expand Down Expand Up @@ -44,7 +45,7 @@ public async Task ReceiveMessage(Message message)
if (mappedBy is not null)
query += $" creator={mappedBy}";

var sets = await WebApiHandler.MakeApiRequest(new BeatmapSetSearch(query));
var sets = await new BeatmapSetSearch(query).Execute();
if (sets.Length > 0)
{
var map = sets[0].Beatmaps.FirstOrDefault(x => name.Contains(x.Version));
Expand Down Expand Up @@ -72,13 +73,13 @@ public async Task ReceiveMessage(Message message)
Beatmap map = null;
if (beatmapLinkData.IsBeatmapset)
{
var set = await WebApiHandler.MakeApiRequest(new GetBeatmapSet(beatmapLinkData.ID));
var set = await new GetBeatmapSet(beatmapLinkData.ID).Execute();
if (set?.Beatmaps.Count > 0)
map = set.Beatmaps.Last();
}
else
{
map = await WebApiHandler.MakeApiRequest(new GetBeatmap(beatmapLinkData.ID));
map = await new GetBeatmap(beatmapLinkData.ID).Execute();
}

await SendMapInfo(message.Chat.Id, map, beatmapLinkData.Mods);
Expand Down Expand Up @@ -147,13 +148,13 @@ await API.EditMediaCaption(callback.Message.Chat.Id, callback.Message.MessageId,
return (lines[0], mappedBy);
}

private async Task SendMapInfo(long chatId, Beatmap map, LegacyMods mods, bool includeName = false)
private async Task SendMapInfo(long chatId, Beatmap map, Mod[] mods, bool includeName = false)
{
if (map != null)
{
var sentMessage = await API.SendPhoto(map.BeatmapSet.Covers.Cover2X,
chatId,
map.GetFormattedMapInfo(mods, includeName),
await map.GetFormattedMapInfo(mods, includeName),
Telegram.Bot.Types.Enums.ParseMode.Html,
replyMarkup: buttons);

Expand Down
6 changes: 3 additions & 3 deletions den0bot.Modules.Osu/ModMaplist.cs
Original file line number Diff line number Diff line change
Expand Up @@ -85,17 +85,17 @@ private async Task<ICommandAnswer> GetMap(Telegram.Bot.Types.Message message)
Beatmap map;
if (linkData.IsBeatmapset)
{
var set = await WebApiHandler.MakeApiRequest(new GetBeatmapSet(linkData.ID));
var set = await new GetBeatmapSet(linkData.ID).Execute();
map = set?.Beatmaps.Last();
}
else
{
map = await WebApiHandler.MakeApiRequest(new GetBeatmap(linkData.ID));
map = await new GetBeatmap(linkData.ID).Execute();
}

if (map != null)
{
string format = map.GetFormattedMapInfo(LegacyMods.NM);
string format = await map.GetFormattedMapInfo();
string caption = $"{maplist[num][0]} {format}";
if (caption.Length > 265) // 200 regular character limit + HTML
{
Expand Down
6 changes: 3 additions & 3 deletions den0bot.Modules.Osu/ModMatchFollow.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// den0bot (c) StanR 2021 - MIT License
// den0bot (c) StanR 2023 - MIT License
using System;
using System.Collections.Generic;
using System.Linq;
Expand Down Expand Up @@ -88,7 +88,7 @@ private async Task Update()

var updatingMatch = followList[currentMatchId];

var match = await WebApiHandler.MakeApiRequest(new GetMatch(updatingMatch.MatchId));
var match = await new GetMatch(updatingMatch.MatchId).Execute();
if (match.Events.Length > 0)
{
if (match.Info.EndTime == null)
Expand Down Expand Up @@ -141,7 +141,7 @@ public async Task ReceiveMessage(Message message)
var matchId = MatchLinkParser.Parse(message.Text)?.Id;
if (matchId != null)
{
var match = await WebApiHandler.MakeApiRequest(new GetMatch(matchId.Value));
var match = await new GetMatch(matchId.Value).Execute();
if (match?.Events.Length > 0)
{
var matchInfo =
Expand Down
6 changes: 3 additions & 3 deletions den0bot.Modules.Osu/ModProfile.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// den0bot (c) StanR 2021 - MIT License
// den0bot (c) StanR 2023 - MIT License
using System.Linq;
using System.Threading.Tasks;
using den0bot.DB;
Expand Down Expand Up @@ -47,12 +47,12 @@ await API.SendMessage(await FormatPlayerInfo(playerId), message.Chat.Id, ParseMo

private async Task<string> FormatPlayerInfo(string playerID)
{
Types.V2.User info = await WebApiHandler.MakeApiRequest(new GetUser(playerID));
Types.V2.User info = await new GetUser(playerID).Execute();

if (info == null)
return string.Empty;

var topscores = await WebApiHandler.MakeApiRequest(new GetUserScores(info.Id, ScoreType.Best, limit: topscores_to_show));
var topscores = await new GetUserScores(info.Id, ScoreType.Best, limit: topscores_to_show).Execute();
if (topscores == null || topscores.Count <= 0)
return string.Empty;

Expand Down
86 changes: 46 additions & 40 deletions den0bot.Modules.Osu/ModRecentScores.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// den0bot (c) StanR 2022 - MIT License
// den0bot (c) StanR 2023 - MIT License
using System;
using System.Collections.Generic;
using System.Linq;
Expand All @@ -15,7 +15,9 @@
using Telegram.Bot.Types.Enums;
using den0bot.Types;
using den0bot.Types.Answers;
using Pettanko;
using Serilog;
using Score = den0bot.Modules.Osu.Types.V2.Score;

namespace den0bot.Modules.Osu
{
Expand Down Expand Up @@ -83,16 +85,12 @@ private async Task<ICommandAnswer> GetLastScores(Telegram.Bot.Types.Message mess
{
msgSplit.Remove(msgSplit.Last());
}

if (amount > recent_amount)
amount = recent_amount;
else if (amount <= 0)
amount = 1;
amount = Math.Clamp(amount, 1, recent_amount);

if (msgSplit.Count > 0)
{
var playerName = string.Join(" ", msgSplit);
var player = await WebApiHandler.MakeApiRequest(new GetUser(playerName));
var player = await new GetUser(playerName).Execute();
if (player != null)
playerId = player.Id;
}
Expand All @@ -109,7 +107,7 @@ private async Task<ICommandAnswer> GetLastScores(Telegram.Bot.Types.Message mess
if (playerId == 0)
return Localization.GetAnswer("generic_fail", message.Chat.Id);

List<Score> lastScores = await WebApiHandler.MakeApiRequest(new GetUserScores(playerId, ScoreType.Recent, true));
List<Score> lastScores = await new GetUserScores(playerId, ScoreType.Recent, true).Execute();
if (lastScores != null)
{
if (lastScores.Count == 0)
Expand All @@ -121,8 +119,8 @@ private async Task<ICommandAnswer> GetLastScores(Telegram.Bot.Types.Message mess
if (amount == 1)
ChatBeatmapCache.StoreLastMap(message.Chat.Id, new ChatBeatmapCache.CachedBeatmap { BeatmapId = score.BeatmapShort.Id, BeatmapSetId = score.BeatmapShort.BeatmapSetId });

score.Beatmap = await WebApiHandler.MakeApiRequest(new GetBeatmap(score.BeatmapShort.Id));
result += FormatScore(score, true);
var beatmap = await new GetBeatmap(score.BeatmapShort.Id).Execute();
result += await FormatScore(score, beatmap, true);
}

return new TextCommandAnswer(result);
Expand All @@ -141,7 +139,7 @@ private async Task<ICommandAnswer> GetPass(Telegram.Bot.Types.Message message)
if (msgSplit.Count > 0)
{
var playerName = string.Join(" ", msgSplit);
var player = await WebApiHandler.MakeApiRequest(new GetUser(playerName));
var player = await new GetUser(playerName).Execute();
if (player != null)
playerId = player.Id;
}
Expand All @@ -158,14 +156,14 @@ private async Task<ICommandAnswer> GetPass(Telegram.Bot.Types.Message message)
if (playerId == 0)
return Localization.GetAnswer("generic_fail", message.Chat.Id);

var lastScores = await WebApiHandler.MakeApiRequest(new GetUserScores(playerId, ScoreType.Recent, false));
var lastScores = await new GetUserScores(playerId, ScoreType.Recent, false).Execute();
if (lastScores.Count > 0)
{
var score = lastScores[0];
ChatBeatmapCache.StoreLastMap(message.Chat.Id, new ChatBeatmapCache.CachedBeatmap { BeatmapId = score.BeatmapShort.Id, BeatmapSetId = score.BeatmapShort.BeatmapSetId});

score.Beatmap = await WebApiHandler.MakeApiRequest(new GetBeatmap(score.BeatmapShort.Id));
return new TextCommandAnswer(FormatScore(score, true));
var beatmap = await new GetBeatmap(score.BeatmapShort.Id).Execute();
return new TextCommandAnswer(await FormatScore(score, beatmap, true));
}

return Localization.GetAnswer("generic_fail", message.Chat.Id);
Expand All @@ -187,7 +185,7 @@ private async Task<ICommandAnswer> GetMapScores(Telegram.Bot.Types.Message messa
}

var msgSplit = msgText.Split(' ').ToList();
var mods = LegacyMods.NM;
var mods = Array.Empty<Mod>();
if (msgSplit.Count > 1)
{
var data = BeatmapLinkParser.Parse(msgText);
Expand All @@ -197,7 +195,7 @@ private async Task<ICommandAnswer> GetMapScores(Telegram.Bot.Types.Message messa
mods = data.Mods;
if (data.IsBeatmapset)
{
BeatmapSet set = await WebApiHandler.MakeApiRequest(new GetBeatmapSet(data.ID));
BeatmapSet set = await new GetBeatmapSet(data.ID).Execute();
if (set?.Beatmaps?.Count > 0)
mapId = set.Beatmaps.OrderBy(x => x.StarRating).Last().Id;
}
Expand All @@ -219,28 +217,27 @@ private async Task<ICommandAnswer> GetMapScores(Telegram.Bot.Types.Message messa

var result = string.Empty;

if (mods == 0)
if (mods.Length == 0)
{
var scores = await WebApiHandler.MakeApiRequest(new GetUserBeatmapScores(mapId, playerId.Value));
var scores = await new GetUserBeatmapScores(mapId, playerId.Value).Execute();
if (scores == null || scores.Count <= 0)
return Localization.GetAnswer("recentscores_no_scores", message.Chat.Id);

var map = await WebApiHandler.MakeApiRequest(new GetBeatmap(mapId));
var map = await new GetBeatmap(mapId).Execute();

foreach (var score in scores.Take(score_amount))
{
score.Beatmap = map;
result += FormatScore(score, false);
result += await FormatScore(score, map, false);
}
}
else
{
var score = await WebApiHandler.MakeApiRequest(new GetUserBeatmapScore(mapId, playerId.Value, mods));
var score = await new GetUserBeatmapScore(mapId, playerId.Value, mods.Select(x=> x.Acronym).ToArray()).Execute();
if (score == null)
return Localization.GetAnswer("recentscores_no_scores", message.Chat.Id);

score.Beatmap = await WebApiHandler.MakeApiRequest(new GetBeatmap(mapId));
result += FormatScore(score, false);
var beatmap = await new GetBeatmap(mapId).Execute();
result += await FormatScore(score, beatmap, false);
}

if (!string.IsNullOrEmpty(result))
Expand Down Expand Up @@ -270,7 +267,7 @@ private async Task<ICommandAnswer> AddMe(Telegram.Bot.Types.Message message)
if (!uint.TryParse(player, out var osuID))
{
// if they used /u/cookiezi instead of /u/124493 we ask osu API for an ID
var info = await WebApiHandler.MakeApiRequest(new GetUser(player));
var info = await new GetUser(player).Execute();

if (info == null)
return Localization.GetAnswer("recentscores_player_add_failed", message.Chat.Id);
Expand Down Expand Up @@ -333,11 +330,11 @@ private async Task<ICommandAnswer> RemovePlayer(Telegram.Bot.Types.Message messa
}
}

private static string FormatScore(ScoreBase score, bool useAgo)
private static async Task<string> FormatScore(Score score, Beatmap beatmap, bool useAgo)
{
string mods = string.Empty;
if (score.LegacyMods != LegacyMods.NM)
mods = $" +{score.LegacyMods?.ReadableMods()}";
if (score.Mods.Length > 0)
mods = $" +{string.Join(null, score.Mods)}";

string date = score.Date?.ToShortDateString();
if (useAgo && score.Date != null)
Expand All @@ -346,7 +343,6 @@ private static string FormatScore(ScoreBase score, bool useAgo)
date = $"{ago:hh\\:mm\\:ss} ago";
}

Beatmap beatmap = (Beatmap)score.Beatmap;
// html-filtered map title
string mapInfo = $"{beatmap.BeatmapSet.Artist} - {beatmap.BeatmapSet.Title} [{score.Beatmap.Version}]".FilterToHTML();

Expand All @@ -356,25 +352,35 @@ private static string FormatScore(ScoreBase score, bool useAgo)
try
{
// Add pp values
double scorePp = score.Pp ?? Oppai.GetBeatmapPP(score.Beatmap, score);
var shouldCalculatePp = score.Pp is null ||
score.ComboBasedMissCount(beatmap.MaxCombo, beatmap.Sliders) > 0;

Pettanko.Difficulty.OsuDifficultyAttributes attributes = null;

if (shouldCalculatePp)
{
attributes = await new GetBeatmapAttributes(beatmap.Id, score.Mods.Select(x=> Mod.AllMods.FirstOrDefault(y=> y.Acronym == x)).ToArray()).Execute();
}

double scorePp = score.Pp ?? PpCalculation.CalculatePerformance(score, attributes, beatmap);
string possiblePp = string.Empty;

if (score.ComboBasedMissCount(beatmap.MaxCombo.Value, beatmap.Sliders.Value) > 0)
if (score.ComboBasedMissCount(beatmap.MaxCombo, beatmap.Sliders) > 0)
{
// Add possible pp value if they missed
var fcScore = new Score
{
Statistics = new Score.ScoreStatistics
{
Count300 = (score.Beatmap.ObjectsTotal - score.Count100 - score.Count50) ?? 0,
Count100 = score.Count100,
Count50 = score.Count50,
Count300 = (score.Beatmap.ObjectsTotal - score.Statistics.Count100 - score.Statistics.Count50) ?? 0,
Count100 = score.Statistics.Count100,
Count50 = score.Statistics.Count50,
},
Combo = beatmap.MaxCombo ?? 0,
LegacyMods = score.LegacyMods
Combo = beatmap.MaxCombo,
Mods = score.Mods
};

double possiblePPval = Oppai.GetBeatmapPP(score.Beatmap, fcScore);
double possiblePPval = PpCalculation.CalculatePerformance(fcScore, attributes, beatmap);
possiblePp = $"(~{possiblePPval:N2}pp if FC)";
}

Expand All @@ -388,15 +394,15 @@ private static string FormatScore(ScoreBase score, bool useAgo)

var position = string.Empty;
if (score.LeaderboardPosition != null)
position = $"#{score.LeaderboardPosition}{(!string.IsNullOrEmpty(mods) ? $" ({score.LegacyMods?.ReadableMods()})" : "") } | ";
position = $"#{score.LeaderboardPosition}{(score.Mods.Length > 0 ? $" ({string.Join(null, score.Mods)})" : "") } | ";

var completion = string.Empty;
if (useAgo)
completion = $" | {(double)(score.Count300 + score.Count100 + score.Count50 + score.Misses) / score.Beatmap.ObjectsTotal * 100.0:N1}% completion";
completion = $" | {(double)(score.Statistics.Count300 + score.Statistics.Count100 + score.Statistics.Count50 + score.Statistics.CountMiss) / score.Beatmap.ObjectsTotal * 100.0:N1}% completion";

return
$"<b>({score.Grade.GetDescription()})</b> <a href=\"{score.Beatmap.Link}\">{mapInfo}</a><b>{mods} ({score.Accuracy:N2}%)</b>{Environment.NewLine}" +
$"{score.Combo}/{beatmap.MaxCombo}x ({score.Count300} / {score.Count100} / {score.Count50} / {score.Misses}) {pp}{Environment.NewLine}" +
$"{score.Combo}/{beatmap.MaxCombo}x ({score.Statistics.Count300} / {score.Statistics.Count100} / {score.Statistics.Count50} / {score.Statistics.CountMiss}) {pp}{Environment.NewLine}" +
$"{position}{date}{completion}{Environment.NewLine}{Environment.NewLine}";
}
}
Expand Down
Loading

0 comments on commit bce78c9

Please sign in to comment.