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::db::{OsuSavedUsers, OsuUser};
use super::OsuClient; use super::{calculate_weighted_map_length, OsuClient};
use super::{embeds::score_embed, BeatmapWithMode}; use super::{embeds::score_embed, BeatmapWithMode};
use crate::{ use crate::{
discord::beatmap_cache::BeatmapMetaCache, discord::beatmap_cache::BeatmapMetaCache,
@ -200,22 +200,7 @@ impl Announcer {
let scores = client let scores = client
.user_best(UserID::ID(u.id), |f| f.mode(Mode::Std).limit(100)) .user_best(UserID::ID(u.id), |f| f.mode(Mode::Std).limit(100))
.await?; .await?;
scores calculate_weighted_map_length(&scores, cache, Mode::Std).await
.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
} }
} }

View file

@ -423,6 +423,7 @@ impl<'a> ScoreEmbedBuilder<'a> {
pub(crate) fn user_embed( pub(crate) fn user_embed(
u: User, u: User,
map_length: f64,
best: Option<(Score, BeatmapWithMode, BeatmapInfo)>, best: Option<(Score, BeatmapWithMode, BeatmapInfo)>,
) -> CreateEmbed { ) -> CreateEmbed {
CreateEmbed::new() CreateEmbed::new()
@ -470,6 +471,19 @@ pub(crate) fn user_embed(
), ),
false, 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( .field(
format!("Level {:.0}", u.level), format!("Level {:.0}", u.level),
format!( format!(

View file

@ -2,7 +2,7 @@ use crate::{
discord::beatmap_cache::BeatmapMetaCache, discord::beatmap_cache::BeatmapMetaCache,
discord::display::ScoreListStyle, discord::display::ScoreListStyle,
discord::oppai_cache::{BeatmapCache, BeatmapInfo}, discord::oppai_cache::{BeatmapCache, BeatmapInfo},
models::{self, Beatmap, Mode, Mods, User}, models::{self, Beatmap, Mode, Mods, Score, User},
request::{BeatmapRequestKind, UserID}, request::{BeatmapRequestKind, UserID},
Client as OsuHttpClient, Client as OsuHttpClient,
}; };
@ -18,7 +18,7 @@ use serenity::{
utils::MessageBuilder, utils::MessageBuilder,
}; };
use std::{str::FromStr, sync::Arc}; use std::{str::FromStr, sync::Arc};
use youmubot_prelude::*; use youmubot_prelude::{stream::FuturesUnordered, *};
mod announcer; mod announcer;
pub(crate) mod beatmap_cache; 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(); let oppai = data.get::<BeatmapCache>().unwrap();
match user { match user {
Some(u) => { Some(u) => {
let best = match osu let bests = osu
.user_best(UserID::ID(u.id), |f| f.limit(1).mode(mode)) .user_best(UserID::ID(u.id), |f| f.limit(100).mode(mode))
.await? .await?;
.into_iter() let map_length = calculate_weighted_map_length(&bests, cache, mode).await?;
.next() let best = match bests.into_iter().next() {
{
Some(m) => { Some(m) => {
let beatmap = cache.get_beatmap(m.beatmap_id, mode).await?; let beatmap = cache.get_beatmap(m.beatmap_id, mode).await?;
let info = oppai 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", "{}: here is the user that you requested",
msg.author msg.author
)) ))
.embed(user_embed(u, best)), .embed(user_embed(u, map_length, best)),
) )
.await?; .await?;
} }
@ -762,3 +761,26 @@ async fn get_user(ctx: &Context, msg: &Message, mut args: Args, mode: Mode) -> C
}; };
Ok(()) 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
}