Add weighted map length to profile

This commit is contained in:
Natsu Kagami 2024-03-06 16:33:22 +01:00
parent 01c743f866
commit 4ba64a466d
Signed by: nki
GPG key ID: 55A032EB38B49ADB
3 changed files with 47 additions and 26 deletions

View file

@ -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::<FuturesUnordered<_>>()
.try_fold(0.0, |a, b| future::ready(Ok(a + b)))
.await
calculate_weighted_map_length(&scores, cache, Mode::Std).await
}
}

View file

@ -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!(

View file

@ -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::<BeatmapCache>().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<Item = &Score>,
cache: &BeatmapMetaCache,
mode: Mode,
) -> Result<f64> {
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::<FuturesUnordered<_>>()
.try_fold(0.0, |a, b| future::ready(Ok(a + b)))
.await
}