diff --git a/src/arcaea/play.rs b/src/arcaea/play.rs index 993f523..40ef07b 100644 --- a/src/arcaea/play.rs +++ b/src/arcaea/play.rs @@ -255,7 +255,7 @@ impl Play { author: Option<&poise::serenity_prelude::User>, ) -> Result<(CreateEmbed, Option), Error> { // {{{ Get previously best score - let previously_best = query_as!( + let prev_play = query_as!( DbPlay, " SELECT * FROM plays @@ -277,6 +277,8 @@ impl Play { ) })? .map(|p| p.to_play()); + let prev_score = prev_play.as_ref().map(|p| p.score); + let prev_zeta_score = prev_play.as_ref().map(|p| p.zeta_score); // }}} let attachement_name = format!("{:?}-{:?}-{:?}.png", song.id, self.score.0, index); @@ -290,43 +292,23 @@ impl Play { "{} [{:?} {}]", &song.title, chart.difficulty, chart.level )) - .field("Score", format!("{} (+?)", self.score), true) + .field("Score", self.score.display_with_diff(prev_score)?, true) .field( "Rating", - format!( - "{:.2} (+?)", - self.score.play_rating_f32(chart.chart_constant) - ), + self.score.display_play_rating(prev_score, chart)?, true, ) .field("Grade", format!("{}", self.score.grade()), true) - .field("ξ-Score", format!("{} (+?)", self.zeta_score), true) + .field( + "ξ-Score", + self.zeta_score.display_with_diff(prev_zeta_score)?, + true, + ) // {{{ ξ-Rating .field( "ξ-Rating", - { - let play_rating = self.zeta_score.play_rating_f32(chart.chart_constant); - if let Some(previous) = previously_best { - let previous_play_rating = - previous.zeta_score.play_rating_f32(chart.chart_constant); - - if play_rating >= previous_play_rating { - format!( - "{:.2} (+{})", - play_rating, - play_rating - previous_play_rating - ) - } else { - format!( - "{:.2} (-{})", - play_rating, - play_rating - previous_play_rating - ) - } - } else { - format!("{:.2}", play_rating) - } - }, + self.zeta_score + .display_play_rating(prev_zeta_score, chart)?, true, ) // }}} diff --git a/src/arcaea/score.rs b/src/arcaea/score.rs index 30c52cb..3bed2ba 100644 --- a/src/arcaea/score.rs +++ b/src/arcaea/score.rs @@ -1,9 +1,11 @@ -use std::fmt::Display; +use std::fmt::{Display, Write}; use num::Rational64; use crate::context::Error; +use super::chart::Chart; + // {{{ Grade #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] pub enum Grade { @@ -125,6 +127,25 @@ impl Score { pub fn play_rating_f32(self, chart_constant: u32) -> f32 { (self.play_rating(chart_constant)) as f32 / 100.0 } + + pub fn display_play_rating(self, prev: Option, chart: &Chart) -> Result { + let mut buffer = String::with_capacity(14); + + let play_rating = self.play_rating_f32(chart.chart_constant); + write!(buffer, "{:.2}", play_rating)?; + + if let Some(prev) = prev { + let prev_play_rating = prev.play_rating_f32(chart.chart_constant); + + if play_rating >= prev_play_rating { + write!(buffer, " (+{:.2})", play_rating - prev_play_rating)?; + } else { + write!(buffer, " (-{:.2})", play_rating - prev_play_rating)?; + } + } + + Ok(buffer) + } // }}} // {{{ Score => grade #[inline] @@ -307,6 +328,41 @@ impl Score { } } // }}} + // {{{ Display self with diff + /// Similar to the display implementation, but without the padding + /// to at least 7 digits. + fn display_mini_into(self, buffer: &mut String) -> Result<(), Error> { + let score = self.0; + if self.0 < 1_000 { + write!(buffer, "{}", score)?; + } else if self.0 < 1_000_000 { + write!(buffer, "{}'{:0>3}", (score / 1000), score % 1000)?; + } else { + write!(buffer, "{}", self)?; + } + + Ok(()) + } + + pub fn display_with_diff(self, prev: Option) -> Result { + let mut buffer = String::with_capacity(24); + write!(buffer, "{}", self)?; + + if let Some(prev) = prev { + write!(buffer, " (")?; + if self >= prev { + write!(buffer, "+")?; + Score(self.0 - prev.0).display_mini_into(&mut buffer)?; + } else { + write!(buffer, "-")?; + Score(prev.0 - self.0).display_mini_into(&mut buffer)?; + } + write!(buffer, ")")?; + } + + Ok(buffer) + } + // }}} } impl Display for Score { diff --git a/src/assets.rs b/src/assets.rs index 621243b..2f8fa49 100644 --- a/src/assets.rs +++ b/src/assets.rs @@ -1,4 +1,3 @@ -#![allow(dead_code)] use std::{cell::RefCell, env::var, path::PathBuf, str::FromStr, sync::OnceLock}; use freetype::{Face, Library};