added InspectDifficulty type
This commit is contained in:
@@ -0,0 +1,92 @@
|
||||
use crate::Difficulty;
|
||||
|
||||
use super::ModsDependent;
|
||||
|
||||
/// [`Difficulty`] but all fields are public for inspection.
|
||||
#[derive(Clone, Debug, Default, PartialEq)]
|
||||
pub struct InspectDifficulty {
|
||||
/// Specify mods through their bit values.
|
||||
///
|
||||
/// See <https://github.com/ppy/osu-api/wiki#mods>
|
||||
pub mods: u32,
|
||||
/// Amount of passed objects for partial plays, e.g. a fail.
|
||||
pub passed_objects: Option<u32>,
|
||||
/// Adjust the clock rate used in the calculation.
|
||||
pub clock_rate: Option<f64>,
|
||||
/// Override a beatmap's set AR.
|
||||
///
|
||||
/// Only relevant for osu! and osu!catch.
|
||||
pub ar: Option<ModsDependent>,
|
||||
/// Override a beatmap's set CS.
|
||||
///
|
||||
/// Only relevant for osu! and osu!catch.
|
||||
pub cs: Option<ModsDependent>,
|
||||
/// Override a beatmap's set HP.
|
||||
pub hp: Option<ModsDependent>,
|
||||
/// Override a beatmap's set OD.
|
||||
pub od: Option<ModsDependent>,
|
||||
/// Adjust patterns as if the HR mod is enabled.
|
||||
///
|
||||
/// Only relevant for osu!catch.
|
||||
pub hardrock_offsets: Option<bool>,
|
||||
}
|
||||
|
||||
impl InspectDifficulty {
|
||||
/// Convert `self` into a [`Difficulty`].
|
||||
pub fn into_difficulty(self) -> Difficulty {
|
||||
let Self {
|
||||
mods,
|
||||
passed_objects,
|
||||
clock_rate,
|
||||
ar,
|
||||
cs,
|
||||
hp,
|
||||
od,
|
||||
hardrock_offsets,
|
||||
} = self;
|
||||
|
||||
let mut difficulty = Difficulty::new().mods(mods);
|
||||
|
||||
if let Some(passed_objects) = passed_objects {
|
||||
difficulty = difficulty.passed_objects(passed_objects);
|
||||
}
|
||||
|
||||
if let Some(clock_rate) = clock_rate {
|
||||
difficulty = difficulty.clock_rate(clock_rate);
|
||||
}
|
||||
|
||||
if let Some(ar) = ar {
|
||||
difficulty = difficulty.ar(ar.value, ar.with_mods);
|
||||
}
|
||||
|
||||
if let Some(cs) = cs {
|
||||
difficulty = difficulty.cs(cs.value, cs.with_mods);
|
||||
}
|
||||
|
||||
if let Some(hp) = hp {
|
||||
difficulty = difficulty.hp(hp.value, hp.with_mods);
|
||||
}
|
||||
|
||||
if let Some(od) = od {
|
||||
difficulty = difficulty.od(od.value, od.with_mods);
|
||||
}
|
||||
|
||||
if let Some(hardrock_offsets) = hardrock_offsets {
|
||||
difficulty = difficulty.hardrock_offsets(hardrock_offsets);
|
||||
}
|
||||
|
||||
difficulty
|
||||
}
|
||||
}
|
||||
|
||||
impl From<InspectDifficulty> for Difficulty {
|
||||
fn from(difficulty: InspectDifficulty) -> Self {
|
||||
difficulty.into_difficulty()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Difficulty> for InspectDifficulty {
|
||||
fn from(difficulty: Difficulty) -> Self {
|
||||
difficulty.inspect()
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,8 @@
|
||||
use std::{borrow::Cow, num::NonZeroU32};
|
||||
use std::{
|
||||
borrow::Cow,
|
||||
fmt::{Debug, Formatter, Result as FmtResult},
|
||||
num::NonZeroU32,
|
||||
};
|
||||
|
||||
use rosu_map::section::general::GameMode;
|
||||
|
||||
@@ -13,10 +17,11 @@ use crate::{
|
||||
|
||||
use self::converted::ConvertedDifficulty;
|
||||
|
||||
use super::{attributes::DifficultyAttributes, Strains};
|
||||
use super::{attributes::DifficultyAttributes, InspectDifficulty, Strains};
|
||||
|
||||
pub mod converted;
|
||||
pub mod gradual;
|
||||
pub mod inspect;
|
||||
pub mod object;
|
||||
pub mod skills;
|
||||
|
||||
@@ -35,7 +40,7 @@ use crate::{model::mode::IGameMode, util::mods::Mods};
|
||||
/// .mods(8 + 1024) // HDFL
|
||||
/// .calculate(&map);
|
||||
/// ```
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
#[derive(Clone, PartialEq)]
|
||||
#[must_use]
|
||||
pub struct Difficulty {
|
||||
mods: u32,
|
||||
@@ -56,9 +61,15 @@ pub struct Difficulty {
|
||||
hardrock_offsets: Option<bool>,
|
||||
}
|
||||
|
||||
/// Wrapper for beatmap attributes in [`Difficulty`].
|
||||
#[derive(Copy, Clone, Debug, Default, PartialEq)]
|
||||
pub struct ModsDependent {
|
||||
/// Value of the beatmap attribute.
|
||||
pub value: f32,
|
||||
/// Whether `value` should be used as is or modified based on mods.
|
||||
///
|
||||
/// `true` means "value already considers mods" i.e. use as is;
|
||||
/// `false` means modify with mods.
|
||||
pub with_mods: bool,
|
||||
}
|
||||
|
||||
@@ -94,9 +105,35 @@ impl Difficulty {
|
||||
ConvertedDifficulty::new(self)
|
||||
}
|
||||
|
||||
/// Turn this [`Difficulty`] into a [`InspectDifficulty`] to inspect its
|
||||
/// configured values.
|
||||
pub fn inspect(self) -> InspectDifficulty {
|
||||
let Self {
|
||||
mods,
|
||||
passed_objects,
|
||||
clock_rate,
|
||||
ar,
|
||||
cs,
|
||||
hp,
|
||||
od,
|
||||
hardrock_offsets,
|
||||
} = self;
|
||||
|
||||
InspectDifficulty {
|
||||
mods,
|
||||
passed_objects,
|
||||
clock_rate: clock_rate.map(non_zero_u32_to_f64),
|
||||
ar,
|
||||
cs,
|
||||
hp,
|
||||
od,
|
||||
hardrock_offsets,
|
||||
}
|
||||
}
|
||||
|
||||
/// Specify mods through their bit values.
|
||||
///
|
||||
/// See [https://github.com/ppy/osu-api/wiki#mods](https://github.com/ppy/osu-api/wiki#mods)
|
||||
/// See <https://github.com/ppy/osu-api/wiki#mods>
|
||||
pub const fn mods(self, mods: u32) -> Self {
|
||||
Self { mods, ..self }
|
||||
}
|
||||
@@ -269,9 +306,7 @@ impl Difficulty {
|
||||
|
||||
pub(crate) fn get_clock_rate(&self) -> f64 {
|
||||
self.clock_rate
|
||||
.map(NonZeroU32::get)
|
||||
.map(u64::from)
|
||||
.map_or_else(|| self.mods.clock_rate(), f64::from_bits)
|
||||
.map_or(self.mods.clock_rate(), non_zero_u32_to_f64)
|
||||
}
|
||||
|
||||
pub(crate) fn get_passed_objects(&self) -> usize {
|
||||
@@ -299,6 +334,36 @@ impl Difficulty {
|
||||
}
|
||||
}
|
||||
|
||||
fn non_zero_u32_to_f64(n: NonZeroU32) -> f64 {
|
||||
f64::from_bits(u64::from(n.get()))
|
||||
}
|
||||
|
||||
impl Debug for Difficulty {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
|
||||
let Self {
|
||||
mods,
|
||||
passed_objects,
|
||||
clock_rate,
|
||||
ar,
|
||||
cs,
|
||||
hp,
|
||||
od,
|
||||
hardrock_offsets,
|
||||
} = self;
|
||||
|
||||
f.debug_struct("Difficulty")
|
||||
.field("mods", mods)
|
||||
.field("passed_objects", passed_objects)
|
||||
.field("clock_rate", &clock_rate.map(non_zero_u32_to_f64))
|
||||
.field("ar", ar)
|
||||
.field("cs", cs)
|
||||
.field("hp", hp)
|
||||
.field("od", od)
|
||||
.field("hardrock_offsets", hardrock_offsets)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Difficulty {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
|
||||
+4
-1
@@ -2,7 +2,10 @@ pub use self::{
|
||||
attributes::{
|
||||
AttributeProvider, DifficultyAttributes, ModeAttributeProvider, PerformanceAttributes,
|
||||
},
|
||||
difficulty::{converted::ConvertedDifficulty, gradual::GradualDifficulty, Difficulty},
|
||||
difficulty::{
|
||||
converted::ConvertedDifficulty, gradual::GradualDifficulty, inspect::InspectDifficulty,
|
||||
Difficulty, ModsDependent,
|
||||
},
|
||||
performance::{gradual::GradualPerformance, HitResultPriority, Performance},
|
||||
score_state::ScoreState,
|
||||
strains::Strains,
|
||||
|
||||
@@ -117,7 +117,7 @@ impl<'map> Performance<'map> {
|
||||
|
||||
/// Specify mods through their bit values.
|
||||
///
|
||||
/// See [https://github.com/ppy/osu-api/wiki#mods](https://github.com/ppy/osu-api/wiki#mods)
|
||||
/// See <https://github.com/ppy/osu-api/wiki#mods>
|
||||
pub fn mods(self, mods: u32) -> Self {
|
||||
match self {
|
||||
Self::Osu(o) => Self::Osu(o.mods(mods)),
|
||||
|
||||
Reference in New Issue
Block a user