Display lazer mod instead of classic mod

This commit is contained in:
Natsu Kagami 2024-02-14 00:42:40 +01:00 committed by Natsu Kagami
parent fef6516ae1
commit c5d00f12d8
5 changed files with 50 additions and 30 deletions

1
Cargo.lock generated
View file

@ -3087,6 +3087,7 @@ dependencies = [
"osuparse",
"rand",
"regex",
"reqwest",
"rosu-pp",
"rosu-v2",
"serde",

View file

@ -273,12 +273,7 @@ mod scores {
let pw = pp.iter().map(|v| v.len()).max().unwrap_or(2);
/*mods width*/
let mw = plays
.iter()
.map(|v| v.mods.to_string().len())
.max()
.unwrap()
.max(4);
let mw = plays.iter().map(|v| v.mods.str_len()).max().unwrap().max(4);
/*beatmap names*/
let bw = beatmaps.iter().map(|v| v.len()).max().unwrap().max(7);
/* ranks width */
@ -311,16 +306,15 @@ mod scores {
// Each row
for (id, (play, beatmap)) in plays.iter().zip(beatmaps.iter()).enumerate() {
m.push_line(format!(
"{:>3} | {:>pw$} | {:>8} | {:>rw$} | {:mw$} | {:bw$}",
"{:>3} | {:>pw$} | {:>8} | {:>rw$} | {} | {:bw$}",
id + start + 1,
pp[id],
format!("{:.2}%", play.accuracy(self.mode)),
ranks[id],
play.mods.to_string(),
play.mods.to_string_padded(mw),
beatmap,
rw = rw,
pw = pw,
mw = mw,
bw = bw
));
}

View file

@ -461,7 +461,7 @@ async fn show_leaderboard(
/*mods width*/
let mdw = scores
.iter()
.map(|(_, _, v)| v.mods.to_string().len())
.map(|(_, _, v)| v.mods.str_len())
.max()
.unwrap()
.max(4);
@ -514,17 +514,16 @@ async fn show_leaderboard(
));
for (id, (_, member, p)) in scores.iter().enumerate() {
content.push_line_safe(format!(
"{:>4} | {:>pw$} | {:>mdw$} | {:>rw$} | {:>aw$} | {:>cw$} | {:>mw$} | {:uw$}",
"{:>4} | {:>pw$} | {} | {:>rw$} | {:>aw$} | {:>cw$} | {:>mw$} | {:uw$}",
format!("#{}", 1 + id + start),
pp[id],
p.mods.to_string(),
p.mods.to_string_padded(mdw),
ranks[id],
accuracies[id],
combos[id],
misses[id],
member,
pw = pw,
mdw = mdw,
rw = rw,
aw = aw,
cw = cw,

View file

@ -1,6 +1,8 @@
use serde::{Deserialize, Serialize};
use std::fmt;
const LAZER_TEXT: &'static str = "";
bitflags::bitflags! {
/// The mods available to osu!
#[derive(std::default::Default, Serialize, Deserialize)]
@ -42,7 +44,7 @@ bitflags::bitflags! {
const MAP_CHANGING = Self::HR.bits | Self::EZ.bits | Self::SPEED_CHANGING.bits;
// Made up flags
const CLASSIC = 1 << 59;
const LAZER = 1 << 59;
const UNKNOWN = 1 << 60;
}
}
@ -72,10 +74,24 @@ const MODS_WITH_NAMES: &[(Mods, &str)] = &[
(Mods::KEY7, "7K"),
(Mods::KEY8, "8K"),
(Mods::KEY9, "9K"),
(Mods::CLASSIC, "CL"),
(Mods::UNKNOWN, "??"),
];
impl Mods {
// Return the string length of the string representation of the mods.
pub fn str_len(&self) -> usize {
let s = format!("{}", self);
s.len() + if s.contains(LAZER_TEXT) { 1 } else { 0 }
}
// Format the mods into a string with padded size.
pub fn to_string_padded(&self, size: usize) -> String {
let s = format!("{}", self);
let real_padded = size - if s.contains(LAZER_TEXT) { 1 } else { 0 };
format!("{:>mw$}", s, mw = real_padded)
}
}
impl std::str::FromStr for Mods {
type Err = String;
fn from_str(mut s: &str) -> Result<Self, Self::Err> {
@ -112,7 +128,6 @@ impl std::str::FromStr for Mods {
"7K" => res |= Mods::KEY7,
"8K" => res |= Mods::KEY8,
"9K" => res |= Mods::KEY9,
"CL" => res |= Mods::CLASSIC,
"??" => res |= Mods::UNKNOWN,
v => return Err(format!("{} is not a valid mod", v)),
}
@ -127,19 +142,22 @@ impl std::str::FromStr for Mods {
impl fmt::Display for Mods {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
if self.is_empty() {
// Return an empty string
return Ok(());
if !(*self & (Mods::all() ^ Mods::LAZER)).is_empty() {
write!(f, "+")?;
for p in MODS_WITH_NAMES.iter() {
if !self.contains(p.0) {
continue;
}
match p.0 {
Mods::DT if self.contains(Mods::NC) => continue,
Mods::SD if self.contains(Mods::PF) => continue,
_ => (),
};
write!(f, "{}", p.1)?;
}
}
write!(f, "+")?;
for p in MODS_WITH_NAMES.iter() {
if !self.contains(p.0) {
continue;
}
if p.0 == Mods::DT && self.contains(Mods::NC) {
continue;
}
write!(f, "{}", p.1)?;
if self.contains(Mods::LAZER) {
write!(f, "{}", LAZER_TEXT)?;
}
Ok(())
}

View file

@ -302,12 +302,20 @@ impl From<Mods> for rosu::mods::GameModsIntermode {
res.insert(*m2);
}
}
if !value.contains(Mods::LAZER) {
res.insert(GameModIntermode::Classic);
}
res
}
}
impl From<rosu::mods::GameModsIntermode> for Mods {
fn from(value: rosu_v2::prelude::GameModsIntermode) -> Self {
let init = if value.contains(GameModIntermode::Classic) {
Mods::NOMOD
} else {
Mods::LAZER
};
value
.into_iter()
.map(|m| match m {
@ -335,10 +343,10 @@ impl From<rosu::mods::GameModsIntermode> for Mods {
GameModIntermode::SevenKeys => Mods::KEY7,
GameModIntermode::EightKeys => Mods::KEY8,
GameModIntermode::NineKeys => Mods::KEY9,
GameModIntermode::Classic => Mods::CLASSIC,
GameModIntermode::Classic => Mods::NOMOD,
_ => Mods::UNKNOWN,
})
.fold(Mods::NOMOD, |a, b| a | b)
.fold(init, |a, b| a | b)
// Mods::from_bits_truncate(value.bits() as u64)
}