diff --git a/youmubot-osu/src/discord/announcer.rs b/youmubot-osu/src/discord/announcer.rs index 91836c7..c06910d 100644 --- a/youmubot-osu/src/discord/announcer.rs +++ b/youmubot-osu/src/discord/announcer.rs @@ -1,5 +1,5 @@ use super::db::{OsuSavedUsers, OsuUser}; -use super::OsuClient; +use super::{calculate_weighted_map_length, OsuClient}; use super::{embeds::score_embed, BeatmapWithMode}; use crate::{ discord::beatmap_cache::BeatmapMetaCache, @@ -200,22 +200,7 @@ impl Announcer { let scores = client .user_best(UserID::ID(u.id), |f| f.mode(Mode::Std).limit(100)) .await?; - scores - .into_iter() - .enumerate() - .map(|(i, s)| async move { - let beatmap = cache.get_beatmap_default(s.beatmap_id).await?; - const SCALING_FACTOR: f64 = 0.975; - Ok(beatmap - .difficulty - .apply_mods(s.mods, 0.0 /* dont care */) - .drain_length - .as_secs_f64() - * (SCALING_FACTOR.powi(i as i32))) - }) - .collect::>() - .try_fold(0.0, |a, b| future::ready(Ok(a + b))) - .await + calculate_weighted_map_length(&scores, cache, Mode::Std).await } } diff --git a/youmubot-osu/src/discord/embeds.rs b/youmubot-osu/src/discord/embeds.rs index 69b010b..f5ef3d8 100644 --- a/youmubot-osu/src/discord/embeds.rs +++ b/youmubot-osu/src/discord/embeds.rs @@ -423,6 +423,7 @@ impl<'a> ScoreEmbedBuilder<'a> { pub(crate) fn user_embed( u: User, + map_length: f64, best: Option<(Score, BeatmapWithMode, BeatmapInfo)>, ) -> CreateEmbed { CreateEmbed::new() @@ -470,6 +471,19 @@ pub(crate) fn user_embed( ), false, ) + .field( + "Weighted Map Length", + { + let secs = map_length.floor() as u64; + let minutes = secs / 60; + let seconds = map_length - (60 * minutes) as f64; + format!( + "**{}** minutes **{:05.2}** seconds (**{:.2}**s)", + minutes, seconds, map_length + ) + }, + false, + ) .field( format!("Level {:.0}", u.level), format!( diff --git a/youmubot-osu/src/discord/mod.rs b/youmubot-osu/src/discord/mod.rs index 90f04ef..2cc6695 100644 --- a/youmubot-osu/src/discord/mod.rs +++ b/youmubot-osu/src/discord/mod.rs @@ -2,7 +2,7 @@ use crate::{ discord::beatmap_cache::BeatmapMetaCache, discord::display::ScoreListStyle, discord::oppai_cache::{BeatmapCache, BeatmapInfo}, - models::{self, Beatmap, Mode, Mods, User}, + models::{self, Beatmap, Mode, Mods, Score, User}, request::{BeatmapRequestKind, UserID}, Client as OsuHttpClient, }; @@ -18,7 +18,7 @@ use serenity::{ utils::MessageBuilder, }; use std::{str::FromStr, sync::Arc}; -use youmubot_prelude::*; +use youmubot_prelude::{stream::FuturesUnordered, *}; mod announcer; pub(crate) mod beatmap_cache; @@ -728,12 +728,11 @@ async fn get_user(ctx: &Context, msg: &Message, mut args: Args, mode: Mode) -> C let oppai = data.get::().unwrap(); match user { Some(u) => { - let best = match osu - .user_best(UserID::ID(u.id), |f| f.limit(1).mode(mode)) - .await? - .into_iter() - .next() - { + let bests = osu + .user_best(UserID::ID(u.id), |f| f.limit(100).mode(mode)) + .await?; + let map_length = calculate_weighted_map_length(&bests, cache, mode).await?; + let best = match bests.into_iter().next() { Some(m) => { let beatmap = cache.get_beatmap(m.beatmap_id, mode).await?; let info = oppai @@ -752,7 +751,7 @@ async fn get_user(ctx: &Context, msg: &Message, mut args: Args, mode: Mode) -> C "{}: here is the user that you requested", msg.author )) - .embed(user_embed(u, best)), + .embed(user_embed(u, map_length, best)), ) .await?; } @@ -762,3 +761,26 @@ async fn get_user(ctx: &Context, msg: &Message, mut args: Args, mode: Mode) -> C }; Ok(()) } + +pub(in crate::discord) async fn calculate_weighted_map_length( + from_scores: impl IntoIterator, + cache: &BeatmapMetaCache, + mode: Mode, +) -> Result { + from_scores + .into_iter() + .enumerate() + .map(|(i, s)| async move { + let beatmap = cache.get_beatmap(s.beatmap_id, mode).await?; + const SCALING_FACTOR: f64 = 0.975; + Ok(beatmap + .difficulty + .apply_mods(s.mods, 0.0 /* dont care */) + .drain_length + .as_secs_f64() + * (SCALING_FACTOR.powi(i as i32))) + }) + .collect::>() + .try_fold(0.0, |a, b| future::ready(Ok(a + b))) + .await +}