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;
|
use rosu_map::section::general::GameMode;
|
||||||
|
|
||||||
@@ -13,10 +17,11 @@ use crate::{
|
|||||||
|
|
||||||
use self::converted::ConvertedDifficulty;
|
use self::converted::ConvertedDifficulty;
|
||||||
|
|
||||||
use super::{attributes::DifficultyAttributes, Strains};
|
use super::{attributes::DifficultyAttributes, InspectDifficulty, Strains};
|
||||||
|
|
||||||
pub mod converted;
|
pub mod converted;
|
||||||
pub mod gradual;
|
pub mod gradual;
|
||||||
|
pub mod inspect;
|
||||||
pub mod object;
|
pub mod object;
|
||||||
pub mod skills;
|
pub mod skills;
|
||||||
|
|
||||||
@@ -35,7 +40,7 @@ use crate::{model::mode::IGameMode, util::mods::Mods};
|
|||||||
/// .mods(8 + 1024) // HDFL
|
/// .mods(8 + 1024) // HDFL
|
||||||
/// .calculate(&map);
|
/// .calculate(&map);
|
||||||
/// ```
|
/// ```
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, PartialEq)]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub struct Difficulty {
|
pub struct Difficulty {
|
||||||
mods: u32,
|
mods: u32,
|
||||||
@@ -56,9 +61,15 @@ pub struct Difficulty {
|
|||||||
hardrock_offsets: Option<bool>,
|
hardrock_offsets: Option<bool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Wrapper for beatmap attributes in [`Difficulty`].
|
||||||
#[derive(Copy, Clone, Debug, Default, PartialEq)]
|
#[derive(Copy, Clone, Debug, Default, PartialEq)]
|
||||||
pub struct ModsDependent {
|
pub struct ModsDependent {
|
||||||
|
/// Value of the beatmap attribute.
|
||||||
pub value: f32,
|
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,
|
pub with_mods: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -94,9 +105,35 @@ impl Difficulty {
|
|||||||
ConvertedDifficulty::new(self)
|
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.
|
/// 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 {
|
pub const fn mods(self, mods: u32) -> Self {
|
||||||
Self { mods, ..self }
|
Self { mods, ..self }
|
||||||
}
|
}
|
||||||
@@ -269,9 +306,7 @@ impl Difficulty {
|
|||||||
|
|
||||||
pub(crate) fn get_clock_rate(&self) -> f64 {
|
pub(crate) fn get_clock_rate(&self) -> f64 {
|
||||||
self.clock_rate
|
self.clock_rate
|
||||||
.map(NonZeroU32::get)
|
.map_or(self.mods.clock_rate(), non_zero_u32_to_f64)
|
||||||
.map(u64::from)
|
|
||||||
.map_or_else(|| self.mods.clock_rate(), f64::from_bits)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn get_passed_objects(&self) -> usize {
|
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 {
|
impl Default for Difficulty {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self::new()
|
Self::new()
|
||||||
|
|||||||
+4
-1
@@ -2,7 +2,10 @@ pub use self::{
|
|||||||
attributes::{
|
attributes::{
|
||||||
AttributeProvider, DifficultyAttributes, ModeAttributeProvider, PerformanceAttributes,
|
AttributeProvider, DifficultyAttributes, ModeAttributeProvider, PerformanceAttributes,
|
||||||
},
|
},
|
||||||
difficulty::{converted::ConvertedDifficulty, gradual::GradualDifficulty, Difficulty},
|
difficulty::{
|
||||||
|
converted::ConvertedDifficulty, gradual::GradualDifficulty, inspect::InspectDifficulty,
|
||||||
|
Difficulty, ModsDependent,
|
||||||
|
},
|
||||||
performance::{gradual::GradualPerformance, HitResultPriority, Performance},
|
performance::{gradual::GradualPerformance, HitResultPriority, Performance},
|
||||||
score_state::ScoreState,
|
score_state::ScoreState,
|
||||||
strains::Strains,
|
strains::Strains,
|
||||||
|
|||||||
@@ -117,7 +117,7 @@ impl<'map> Performance<'map> {
|
|||||||
|
|
||||||
/// Specify mods through their bit values.
|
/// 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 {
|
pub fn mods(self, mods: u32) -> Self {
|
||||||
match self {
|
match self {
|
||||||
Self::Osu(o) => Self::Osu(o.mods(mods)),
|
Self::Osu(o) => Self::Osu(o.mods(mods)),
|
||||||
|
|||||||
Reference in New Issue
Block a user