restructure Difficulty and ModeDifficulty
This commit is contained in:
@@ -27,9 +27,9 @@ News posts of the latest gamemode updates:
|
||||
let map = rosu_pp::Beatmap::from_path("./resources/2785319.osu").unwrap();
|
||||
|
||||
// Calculate difficulty attributes
|
||||
let diff_attrs = map.difficulty()
|
||||
let diff_attrs = rosu_pp::Difficulty::new()
|
||||
.mods(8 + 16) // HDHR
|
||||
.calculate();
|
||||
.calculate(&map);
|
||||
|
||||
let stars = diff_attrs.stars();
|
||||
|
||||
@@ -63,17 +63,20 @@ println!("Stars: {stars} | PP: {pp}/{max_pp}");
|
||||
Gradually calculating attributes provides an efficient way to process each hitobject
|
||||
separately and calculate the attributes only up to that point.
|
||||
|
||||
For difficulty attributes, there is [`GradualDifficulty`] which implements [`Iterator`]
|
||||
and for performance attributes there is [`GradualPerformance`] which requires the current
|
||||
For difficulty attributes, there is `GradualDifficulty` which implements `Iterator`
|
||||
and for performance attributes there is `GradualPerformance` which requires the current
|
||||
score state.
|
||||
|
||||
```rust
|
||||
use rosu_pp::{Beatmap, GradualPerformance, ModeDifficulty, any::ScoreState};
|
||||
use rosu_pp::{Beatmap, GradualPerformance, Difficulty, any::ScoreState};
|
||||
|
||||
let map = Beatmap::from_path("./resources/1028484.osu").unwrap();
|
||||
let difficulty = ModeDifficulty::new().mods(16 + 64).clock_rate(1.2); // HRDT on 1.2x
|
||||
|
||||
let mut gradual = GradualPerformance::new(&difficulty, &map);
|
||||
let mut gradual = Difficulty::new()
|
||||
.mods(16 + 64) // HRDT
|
||||
.clock_rate(1.2)
|
||||
.gradual_performance(&map);
|
||||
|
||||
let mut state = ScoreState::new(); // empty state, everything is on 0.
|
||||
|
||||
// The first 10 hitresults are 300s
|
||||
|
||||
@@ -0,0 +1,133 @@
|
||||
use std::{
|
||||
fmt::{Debug, Formatter, Result as FmtResult},
|
||||
marker::PhantomData,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
model::{beatmap::Converted, mode::IGameMode},
|
||||
util::generic_fmt::GenericFormatter,
|
||||
Difficulty,
|
||||
};
|
||||
|
||||
/// Difficulty calculator on maps of a given mode.
|
||||
#[must_use]
|
||||
pub struct ConvertedDifficulty<M> {
|
||||
inner: Difficulty,
|
||||
_mode: PhantomData<M>,
|
||||
}
|
||||
|
||||
impl<M> ConvertedDifficulty<M> {
|
||||
/// Create a new difficulty calculator for a generic mode.
|
||||
pub const fn new() -> Self {
|
||||
Self::from_difficulty(Difficulty::new())
|
||||
}
|
||||
|
||||
pub(crate) const fn from_difficulty(difficulty: Difficulty) -> Self {
|
||||
Self {
|
||||
inner: difficulty,
|
||||
_mode: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
/// Return the internal [`Difficulty`].
|
||||
pub const fn into_inner(self) -> Difficulty {
|
||||
self.inner
|
||||
}
|
||||
|
||||
/// Cast from generic mode `M` to `N`.
|
||||
pub fn cast<N: IGameMode>(self) -> ConvertedDifficulty<N> {
|
||||
ConvertedDifficulty {
|
||||
inner: self.inner,
|
||||
_mode: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
/// Specify mods through their bit values.
|
||||
///
|
||||
/// See [https://github.com/ppy/osu-api/wiki#mods](https://github.com/ppy/osu-api/wiki#mods)
|
||||
pub const fn mods(self, mods: u32) -> Self {
|
||||
Self {
|
||||
inner: self.inner.mods(mods),
|
||||
..self
|
||||
}
|
||||
}
|
||||
|
||||
/// Amount of passed objects for partial plays, e.g. a fail.
|
||||
pub const fn passed_objects(self, passed_objects: u32) -> Self {
|
||||
Self {
|
||||
inner: self.inner.passed_objects(passed_objects),
|
||||
..self
|
||||
}
|
||||
}
|
||||
|
||||
/// Adjust the clock rate used in the calculation between 0.01 and 100.0.
|
||||
///
|
||||
/// If none is specified, it will take the clock rate based on the mods
|
||||
/// i.e. 1.5 for DT, 0.75 for HT and 1.0 otherwise.
|
||||
pub fn clock_rate(self, clock_rate: f64) -> Self {
|
||||
Self {
|
||||
inner: self.inner.clock_rate(clock_rate),
|
||||
..self
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<M: IGameMode> ConvertedDifficulty<M> {
|
||||
/// Perform the difficulty calculation for a [`Converted`] beatmap and
|
||||
/// process the final skill values.
|
||||
pub fn calculate(&self, map: &Converted<'_, M>) -> M::DifficultyAttributes {
|
||||
M::difficulty(&self.inner, map)
|
||||
}
|
||||
|
||||
/// Perform a difficulty calculation for a [`Converted`] beatmap without
|
||||
/// processing the final skill values.
|
||||
pub fn strains(&self, map: &Converted<'_, M>) -> M::Strains {
|
||||
M::strains(&self.inner, map)
|
||||
}
|
||||
|
||||
/// Create a gradual difficulty calculator for a [`Converted`] beatmap.
|
||||
pub fn gradual_difficulty(&self, map: &Converted<'_, M>) -> M::GradualDifficulty {
|
||||
M::gradual_difficulty(&self.inner, map)
|
||||
}
|
||||
|
||||
/// Create a gradual performance calculator for a [`Converted`] beatmap.
|
||||
pub fn gradual_performance(&self, map: &Converted<'_, M>) -> M::GradualPerformance {
|
||||
M::gradual_performance(&self.inner, map)
|
||||
}
|
||||
}
|
||||
|
||||
impl<M: IGameMode> From<Difficulty> for ConvertedDifficulty<M> {
|
||||
fn from(difficulty: Difficulty) -> Self {
|
||||
Self::from_difficulty(difficulty)
|
||||
}
|
||||
}
|
||||
|
||||
impl<M> AsRef<Difficulty> for ConvertedDifficulty<M> {
|
||||
fn as_ref(&self) -> &Difficulty {
|
||||
&self.inner
|
||||
}
|
||||
}
|
||||
|
||||
impl<M> Clone for ConvertedDifficulty<M> {
|
||||
fn clone(&self) -> Self {
|
||||
Self {
|
||||
inner: self.inner.clone(),
|
||||
_mode: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<M> Debug for ConvertedDifficulty<M> {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
|
||||
f.debug_struct("ConvertedDifficulty")
|
||||
.field("inner", &self.inner)
|
||||
.field("mode", &GenericFormatter::<M>::new())
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl<M> PartialEq for ConvertedDifficulty<M> {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.inner == other.inner
|
||||
}
|
||||
}
|
||||
@@ -4,11 +4,12 @@ use rosu_map::section::general::GameMode;
|
||||
|
||||
use crate::{
|
||||
any::DifficultyAttributes,
|
||||
catch::{CatchBeatmap, CatchGradualDifficulty},
|
||||
mania::{ManiaBeatmap, ManiaGradualDifficulty},
|
||||
osu::{OsuBeatmap, OsuGradualDifficulty},
|
||||
taiko::{TaikoBeatmap, TaikoGradualDifficulty},
|
||||
Beatmap, ModeDifficulty,
|
||||
catch::{Catch, CatchBeatmap, CatchGradualDifficulty},
|
||||
mania::{Mania, ManiaBeatmap, ManiaGradualDifficulty},
|
||||
model::mode::IGameMode,
|
||||
osu::{Osu, OsuBeatmap, OsuGradualDifficulty},
|
||||
taiko::{Taiko, TaikoBeatmap, TaikoGradualDifficulty},
|
||||
Beatmap, Converted, Difficulty,
|
||||
};
|
||||
|
||||
/// Gradually calculate the difficulty attributes on maps of any mode.
|
||||
@@ -22,10 +23,10 @@ use crate::{
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// use rosu_pp::{Beatmap, GradualDifficulty, ModeDifficulty};
|
||||
/// use rosu_pp::{Beatmap, GradualDifficulty, Difficulty};
|
||||
///
|
||||
/// let map = Beatmap::from_path("./resources/2785319.osu").unwrap();
|
||||
/// let difficulty = ModeDifficulty::new().mods(64); // DT
|
||||
/// let difficulty = Difficulty::new().mods(64); // DT
|
||||
/// let mut iter = GradualDifficulty::new(&difficulty, &map);
|
||||
///
|
||||
/// // the difficulty of the map after the first object
|
||||
@@ -53,22 +54,28 @@ pub enum GradualDifficulty {
|
||||
macro_rules! from_converted {
|
||||
( $fn:ident, $mode:ident, $converted:ident ) => {
|
||||
#[doc = concat!("Create a [`GradualDifficulty`] for a [`", stringify!($converted), "`]")]
|
||||
pub fn $fn(difficulty: &ModeDifficulty, converted: &$converted<'_>) -> Self {
|
||||
Self::$mode(difficulty.gradual_difficulty(converted))
|
||||
pub fn $fn(difficulty: &Difficulty, converted: &$converted<'_>) -> Self {
|
||||
Self::$mode($mode::gradual_difficulty(difficulty, converted))
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
impl GradualDifficulty {
|
||||
/// Create a [`GradualDifficulty`] for a map of any mode.
|
||||
pub fn new(difficulty: &ModeDifficulty, map: &Beatmap) -> Self {
|
||||
pub fn new(difficulty: &Difficulty, map: &Beatmap) -> Self {
|
||||
let map = Cow::Borrowed(map);
|
||||
|
||||
match map.mode {
|
||||
GameMode::Osu => Self::Osu(difficulty.gradual_difficulty(&OsuBeatmap::new(map))),
|
||||
GameMode::Taiko => Self::Taiko(difficulty.gradual_difficulty(&TaikoBeatmap::new(map))),
|
||||
GameMode::Catch => Self::Catch(difficulty.gradual_difficulty(&CatchBeatmap::new(map))),
|
||||
GameMode::Mania => Self::Mania(difficulty.gradual_difficulty(&ManiaBeatmap::new(map))),
|
||||
GameMode::Osu => Self::Osu(Osu::gradual_difficulty(difficulty, &Converted::new(map))),
|
||||
GameMode::Taiko => {
|
||||
Self::Taiko(Taiko::gradual_difficulty(difficulty, &Converted::new(map)))
|
||||
}
|
||||
GameMode::Catch => {
|
||||
Self::Catch(Catch::gradual_difficulty(difficulty, &Converted::new(map)))
|
||||
}
|
||||
GameMode::Mania => {
|
||||
Self::Mania(Mania::gradual_difficulty(difficulty, &Converted::new(map)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+70
-113
@@ -3,144 +3,79 @@ use std::borrow::Cow;
|
||||
use rosu_map::section::general::GameMode;
|
||||
|
||||
use crate::{
|
||||
catch::{Catch, CatchBeatmap},
|
||||
mania::{Mania, ManiaBeatmap},
|
||||
catch::Catch,
|
||||
mania::Mania,
|
||||
model::beatmap::{Beatmap, Converted},
|
||||
osu::{Osu, OsuBeatmap},
|
||||
taiko::{Taiko, TaikoBeatmap},
|
||||
osu::Osu,
|
||||
taiko::Taiko,
|
||||
GradualDifficulty, GradualPerformance,
|
||||
};
|
||||
|
||||
use self::mode::ModeDifficulty;
|
||||
use self::converted::ConvertedDifficulty;
|
||||
|
||||
use super::{attributes::DifficultyAttributes, Strains};
|
||||
|
||||
pub mod converted;
|
||||
pub mod gradual;
|
||||
pub mod mode;
|
||||
pub mod object;
|
||||
pub mod skills;
|
||||
|
||||
use crate::{model::mode::IGameMode, util::mods::Mods};
|
||||
|
||||
/// Difficulty calculator on maps of any mode.
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
#[derive(Clone, Debug, Default, PartialEq)]
|
||||
#[must_use]
|
||||
pub struct Difficulty<'map> {
|
||||
map: Cow<'map, Beatmap>,
|
||||
inner: ModeDifficulty,
|
||||
pub struct Difficulty {
|
||||
mods: u32,
|
||||
passed_objects: Option<u32>,
|
||||
clock_rate: Option<f64>,
|
||||
}
|
||||
|
||||
impl<'map> Difficulty<'map> {
|
||||
/// Create a new difficulty calculator for the given beatmap.
|
||||
pub const fn new(map: &'map Beatmap) -> Self {
|
||||
Self::new_with_cow(Cow::Borrowed(map))
|
||||
}
|
||||
|
||||
const fn new_with_cow(map: Cow<'map, Beatmap>) -> Self {
|
||||
impl Difficulty {
|
||||
/// Create a new difficulty calculator.
|
||||
pub const fn new() -> Self {
|
||||
Self {
|
||||
map,
|
||||
inner: ModeDifficulty::new(),
|
||||
mods: 0,
|
||||
passed_objects: None,
|
||||
clock_rate: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! impl_from_mode {
|
||||
( $mode:ident ) => {
|
||||
impl<'a> From<Converted<'a, $mode>> for Difficulty<'a> {
|
||||
fn from(converted: Converted<'a, $mode>) -> Self {
|
||||
Self::new_with_cow(converted.into_inner())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'b: 'a> From<&'b Converted<'a, $mode>> for Difficulty<'a> {
|
||||
fn from(converted: &'b Converted<'a, $mode>) -> Self {
|
||||
Self::new(&converted)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
impl_from_mode!(Osu);
|
||||
impl_from_mode!(Taiko);
|
||||
impl_from_mode!(Catch);
|
||||
impl_from_mode!(Mania);
|
||||
|
||||
impl Difficulty<'_> {
|
||||
/// Attempt to convert the map to the specified mode.
|
||||
/// Use this [`&Difficulty`] as a calculator for a specific [`IGameMode`].
|
||||
///
|
||||
/// If the conversion is incompatible, `None` is returned.
|
||||
///
|
||||
/// If the given mode should be ignored in case it is incompatible, use
|
||||
/// [`mode_or_ignore`] instead.
|
||||
///
|
||||
/// [`mode_or_ignore`]: Self::mode_or_ignore
|
||||
pub fn try_mode(&mut self, mode: GameMode) -> Option<&mut Self> {
|
||||
let map = match mode {
|
||||
GameMode::Osu => OsuBeatmap::try_from_ref(self.map.as_ref())?.into_inner(),
|
||||
GameMode::Taiko => TaikoBeatmap::try_from_ref(self.map.as_ref())?.into_inner(),
|
||||
GameMode::Catch => CatchBeatmap::try_from_ref(self.map.as_ref())?.into_inner(),
|
||||
GameMode::Mania => ManiaBeatmap::try_from_ref(self.map.as_ref())?.into_inner(),
|
||||
/// [`&Difficulty`]: Difficulty
|
||||
pub const fn with_mode<M: IGameMode>(&self) -> ConvertedDifficulty<M> {
|
||||
let this = Self {
|
||||
mods: self.mods,
|
||||
passed_objects: self.passed_objects,
|
||||
clock_rate: self.clock_rate,
|
||||
};
|
||||
|
||||
if matches!(map, Cow::Owned(_)) {
|
||||
let map = map.into_owned();
|
||||
self.map = Cow::Owned(map);
|
||||
}
|
||||
|
||||
Some(self)
|
||||
}
|
||||
|
||||
/// Attempt to convert the map to the specified mode.
|
||||
///
|
||||
/// If the conversion is incompatible, the map won't be modified.
|
||||
///
|
||||
/// To see whether the given mode is incompatible, use [`try_mode`]
|
||||
/// instead.
|
||||
///
|
||||
/// [`try_mode`]: Self::try_mode
|
||||
pub fn mode_or_ignore(&mut self, mode: GameMode) -> &mut Self {
|
||||
let map = self.map.as_ref();
|
||||
|
||||
let map_opt = match mode {
|
||||
GameMode::Osu => OsuBeatmap::try_from_ref(map).map(Converted::into_inner),
|
||||
GameMode::Taiko => TaikoBeatmap::try_from_ref(map).map(Converted::into_inner),
|
||||
GameMode::Catch => CatchBeatmap::try_from_ref(map).map(Converted::into_inner),
|
||||
GameMode::Mania => ManiaBeatmap::try_from_ref(map).map(Converted::into_inner),
|
||||
};
|
||||
|
||||
match map_opt {
|
||||
Some(cow @ Cow::Owned(_)) => {
|
||||
let map = cow.into_owned();
|
||||
self.map = Cow::Owned(map);
|
||||
}
|
||||
Some(Cow::Borrowed(_)) | None => {}
|
||||
}
|
||||
|
||||
self
|
||||
ConvertedDifficulty::from_difficulty(this)
|
||||
}
|
||||
|
||||
/// Specify mods through their bit values.
|
||||
///
|
||||
/// See [https://github.com/ppy/osu-api/wiki#mods](https://github.com/ppy/osu-api/wiki#mods)
|
||||
pub fn mods(self, mods: u32) -> Self {
|
||||
Self {
|
||||
inner: self.inner.mods(mods),
|
||||
..self
|
||||
}
|
||||
pub const fn mods(self, mods: u32) -> Self {
|
||||
Self { mods, ..self }
|
||||
}
|
||||
|
||||
/// Amount of passed objects for partial plays, e.g. a fail.
|
||||
pub fn passed_objects(self, passed_objects: u32) -> Self {
|
||||
pub const fn passed_objects(self, passed_objects: u32) -> Self {
|
||||
Self {
|
||||
inner: self.inner.passed_objects(passed_objects),
|
||||
passed_objects: Some(passed_objects),
|
||||
..self
|
||||
}
|
||||
}
|
||||
|
||||
/// Adjust the clock rate used in the calculation.
|
||||
/// Adjust the clock rate used in the calculation between 0.01 and 100.0.
|
||||
///
|
||||
/// If none is specified, it will take the clock rate based on the mods
|
||||
/// i.e. 1.5 for DT, 0.75 for HT and 1.0 otherwise.
|
||||
pub fn clock_rate(self, clock_rate: f64) -> Self {
|
||||
Self {
|
||||
inner: self.inner.clock_rate(clock_rate),
|
||||
clock_rate: Some(clock_rate.clamp(0.01, 100.0)),
|
||||
..self
|
||||
}
|
||||
}
|
||||
@@ -148,19 +83,19 @@ impl Difficulty<'_> {
|
||||
/// Perform the difficulty calculation.
|
||||
///
|
||||
/// The returned attributes depend on the map's mode.
|
||||
pub fn calculate(&self) -> DifficultyAttributes {
|
||||
let map = Cow::Borrowed(self.map.as_ref());
|
||||
pub fn calculate(&self, map: &Beatmap) -> DifficultyAttributes {
|
||||
let map = Cow::Borrowed(map);
|
||||
|
||||
match self.map.mode {
|
||||
GameMode::Osu => DifficultyAttributes::Osu(self.inner.calculate(&OsuBeatmap::new(map))),
|
||||
match map.mode {
|
||||
GameMode::Osu => DifficultyAttributes::Osu(Osu::difficulty(self, &Converted::new(map))),
|
||||
GameMode::Taiko => {
|
||||
DifficultyAttributes::Taiko(self.inner.calculate(&TaikoBeatmap::new(map)))
|
||||
DifficultyAttributes::Taiko(Taiko::difficulty(self, &Converted::new(map)))
|
||||
}
|
||||
GameMode::Catch => {
|
||||
DifficultyAttributes::Catch(self.inner.calculate(&CatchBeatmap::new(map)))
|
||||
DifficultyAttributes::Catch(Catch::difficulty(self, &Converted::new(map)))
|
||||
}
|
||||
GameMode::Mania => {
|
||||
DifficultyAttributes::Mania(self.inner.calculate(&ManiaBeatmap::new(map)))
|
||||
DifficultyAttributes::Mania(Mania::difficulty(self, &Converted::new(map)))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -169,14 +104,36 @@ impl Difficulty<'_> {
|
||||
/// strains, return them as is.
|
||||
///
|
||||
/// Suitable to plot the difficulty of a map over time.
|
||||
pub fn strains(&self) -> Strains {
|
||||
let map = Cow::Borrowed(self.map.as_ref());
|
||||
pub fn strains(&self, map: &Beatmap) -> Strains {
|
||||
let map = Cow::Borrowed(map);
|
||||
|
||||
match self.map.mode {
|
||||
GameMode::Osu => Strains::Osu(self.inner.strains(&OsuBeatmap::new(map))),
|
||||
GameMode::Taiko => Strains::Taiko(self.inner.strains(&TaikoBeatmap::new(map))),
|
||||
GameMode::Catch => Strains::Catch(self.inner.strains(&CatchBeatmap::new(map))),
|
||||
GameMode::Mania => Strains::Mania(self.inner.strains(&ManiaBeatmap::new(map))),
|
||||
match map.mode {
|
||||
GameMode::Osu => Strains::Osu(Osu::strains(self, &Converted::new(map))),
|
||||
GameMode::Taiko => Strains::Taiko(Taiko::strains(self, &Converted::new(map))),
|
||||
GameMode::Catch => Strains::Catch(Catch::strains(self, &Converted::new(map))),
|
||||
GameMode::Mania => Strains::Mania(Mania::strains(self, &Converted::new(map))),
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a gradual difficulty calculator for a [`Beatmap`].
|
||||
pub fn gradual_difficulty(&self, map: &Beatmap) -> GradualDifficulty {
|
||||
GradualDifficulty::new(self, map)
|
||||
}
|
||||
|
||||
/// Create a gradual performance calculator for a [`Beatmap`].
|
||||
pub fn gradual_performance(&self, map: &Beatmap) -> GradualPerformance {
|
||||
GradualPerformance::new(self, map)
|
||||
}
|
||||
|
||||
pub(crate) const fn get_mods(&self) -> u32 {
|
||||
self.mods
|
||||
}
|
||||
|
||||
pub(crate) fn get_clock_rate(&self) -> f64 {
|
||||
self.clock_rate.unwrap_or_else(|| self.mods.clock_rate())
|
||||
}
|
||||
|
||||
pub(crate) fn get_passed_objects(&self) -> usize {
|
||||
self.passed_objects.map_or(usize::MAX, |n| n as usize)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,87 +0,0 @@
|
||||
use crate::{
|
||||
model::{beatmap::Converted, mode::IGameMode},
|
||||
util::mods::Mods,
|
||||
};
|
||||
|
||||
/// Difficulty calculator on maps of a given mode.
|
||||
#[derive(Clone, Debug, Default, PartialEq)]
|
||||
#[must_use]
|
||||
pub struct ModeDifficulty {
|
||||
mods: u32,
|
||||
passed_objects: Option<u32>,
|
||||
clock_rate: Option<f64>,
|
||||
}
|
||||
|
||||
impl ModeDifficulty {
|
||||
/// Create a new difficulty calculator.
|
||||
pub const fn new() -> Self {
|
||||
Self {
|
||||
mods: 0,
|
||||
passed_objects: None,
|
||||
clock_rate: None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Specify mods through their bit values.
|
||||
///
|
||||
/// See [https://github.com/ppy/osu-api/wiki#mods](https://github.com/ppy/osu-api/wiki#mods)
|
||||
pub const fn mods(self, mods: u32) -> Self {
|
||||
Self { mods, ..self }
|
||||
}
|
||||
|
||||
/// Amount of passed objects for partial plays, e.g. a fail.
|
||||
pub const fn passed_objects(self, passed_objects: u32) -> Self {
|
||||
Self {
|
||||
passed_objects: Some(passed_objects),
|
||||
..self
|
||||
}
|
||||
}
|
||||
|
||||
/// Adjust the clock rate used in the calculation between 0.01 and 100.0.
|
||||
///
|
||||
/// If none is specified, it will take the clock rate based on the mods
|
||||
/// i.e. 1.5 for DT, 0.75 for HT and 1.0 otherwise.
|
||||
pub fn clock_rate(self, clock_rate: f64) -> Self {
|
||||
Self {
|
||||
clock_rate: Some(clock_rate.clamp(0.01, 100.0)),
|
||||
..self
|
||||
}
|
||||
}
|
||||
|
||||
/// Perform the difficulty calculation for a [`Converted`] beatmap and
|
||||
/// process the final skill values.
|
||||
pub fn calculate<M: IGameMode>(&self, map: &Converted<'_, M>) -> M::DifficultyAttributes {
|
||||
M::difficulty(self, map)
|
||||
}
|
||||
|
||||
/// Perform a difficulty calculation for a [`Converted`] beatmap without
|
||||
/// processing the final skill values.
|
||||
pub fn strains<M: IGameMode>(&self, map: &Converted<'_, M>) -> M::Strains {
|
||||
M::strains(self, map)
|
||||
}
|
||||
|
||||
/// Create a gradual difficulty calculator for a [`Converted`] beatmap.
|
||||
pub fn gradual_difficulty<M: IGameMode>(&self, map: &Converted<'_, M>) -> M::GradualDifficulty {
|
||||
M::gradual_difficulty(self, map)
|
||||
}
|
||||
|
||||
/// Create a gradual performance calculator for a [`Converted`] beatmap.
|
||||
pub fn gradual_performance<M: IGameMode>(
|
||||
&self,
|
||||
map: &Converted<'_, M>,
|
||||
) -> M::GradualPerformance {
|
||||
M::gradual_performance(self, map)
|
||||
}
|
||||
|
||||
pub(crate) const fn get_mods(&self) -> u32 {
|
||||
self.mods
|
||||
}
|
||||
|
||||
pub(crate) fn get_clock_rate(&self) -> f64 {
|
||||
self.clock_rate.unwrap_or_else(|| self.mods.clock_rate())
|
||||
}
|
||||
|
||||
pub(crate) fn get_passed_objects(&self) -> usize {
|
||||
self.passed_objects.map_or(usize::MAX, |n| n as usize)
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -2,7 +2,7 @@ pub use self::{
|
||||
attributes::{
|
||||
AttributeProvider, DifficultyAttributes, ModeAttributeProvider, PerformanceAttributes,
|
||||
},
|
||||
difficulty::{gradual::GradualDifficulty, mode::ModeDifficulty, Difficulty},
|
||||
difficulty::{converted::ConvertedDifficulty, gradual::GradualDifficulty, Difficulty},
|
||||
performance::{gradual::GradualPerformance, HitResultPriority, Performance},
|
||||
score_state::ScoreState,
|
||||
strains::Strains,
|
||||
|
||||
@@ -4,11 +4,12 @@ use rosu_map::section::general::GameMode;
|
||||
|
||||
use crate::{
|
||||
any::{PerformanceAttributes, ScoreState},
|
||||
catch::{CatchBeatmap, CatchGradualPerformance},
|
||||
mania::{ManiaBeatmap, ManiaGradualPerformance},
|
||||
osu::{OsuBeatmap, OsuGradualPerformance},
|
||||
taiko::{TaikoBeatmap, TaikoGradualPerformance},
|
||||
Beatmap, ModeDifficulty,
|
||||
catch::{Catch, CatchBeatmap, CatchGradualPerformance},
|
||||
mania::{Mania, ManiaBeatmap, ManiaGradualPerformance},
|
||||
model::mode::IGameMode,
|
||||
osu::{Osu, OsuBeatmap, OsuGradualPerformance},
|
||||
taiko::{Taiko, TaikoBeatmap, TaikoGradualPerformance},
|
||||
Beatmap, Converted, Difficulty,
|
||||
};
|
||||
|
||||
/// Gradually calculate the performance attributes on maps of any mode.
|
||||
@@ -31,10 +32,10 @@ use crate::{
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// use rosu_pp::{Beatmap, GradualPerformance, ModeDifficulty, any::ScoreState};
|
||||
/// use rosu_pp::{Beatmap, GradualPerformance, Difficulty, any::ScoreState};
|
||||
///
|
||||
/// let map = Beatmap::from_path("./resources/2785319.osu").unwrap();
|
||||
/// let difficulty = ModeDifficulty::new().mods(64); // DT
|
||||
/// let difficulty = Difficulty::new().mods(64); // DT
|
||||
/// let mut gradual = GradualPerformance::new(&difficulty, &map);
|
||||
/// let mut state = ScoreState::new(); // empty state, everything is on 0.
|
||||
///
|
||||
@@ -102,22 +103,28 @@ pub enum GradualPerformance {
|
||||
macro_rules! from_converted {
|
||||
( $fn:ident, $mode:ident, $converted:ident ) => {
|
||||
#[doc = concat!("Create a [`GradualPerformance`] for a [`", stringify!($converted), "`]")]
|
||||
pub fn $fn(difficulty: &ModeDifficulty, converted: &$converted<'_>) -> Self {
|
||||
Self::$mode(difficulty.gradual_performance(converted))
|
||||
pub fn $fn(difficulty: &Difficulty, converted: &$converted<'_>) -> Self {
|
||||
Self::$mode($mode::gradual_performance(difficulty, converted))
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
impl GradualPerformance {
|
||||
/// Create a [`GradualPerformance`] for a map of any mode.
|
||||
pub fn new(difficulty: &ModeDifficulty, map: &Beatmap) -> Self {
|
||||
pub fn new(difficulty: &Difficulty, map: &Beatmap) -> Self {
|
||||
let map = Cow::Borrowed(map);
|
||||
|
||||
match map.mode {
|
||||
GameMode::Osu => Self::Osu(difficulty.gradual_performance(&OsuBeatmap::new(map))),
|
||||
GameMode::Taiko => Self::Taiko(difficulty.gradual_performance(&TaikoBeatmap::new(map))),
|
||||
GameMode::Catch => Self::Catch(difficulty.gradual_performance(&CatchBeatmap::new(map))),
|
||||
GameMode::Mania => Self::Mania(difficulty.gradual_performance(&ManiaBeatmap::new(map))),
|
||||
GameMode::Osu => Self::Osu(Osu::gradual_performance(difficulty, &Converted::new(map))),
|
||||
GameMode::Taiko => {
|
||||
Self::Taiko(Taiko::gradual_performance(difficulty, &Converted::new(map)))
|
||||
}
|
||||
GameMode::Catch => {
|
||||
Self::Catch(Catch::gradual_performance(difficulty, &Converted::new(map)))
|
||||
}
|
||||
GameMode::Mania => {
|
||||
Self::Mania(Mania::gradual_performance(difficulty, &Converted::new(map)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ use crate::{
|
||||
CatchBeatmap, CatchDifficultyAttributes,
|
||||
},
|
||||
util::mods::Mods,
|
||||
ModeDifficulty,
|
||||
Difficulty,
|
||||
};
|
||||
|
||||
use super::{
|
||||
@@ -32,14 +32,14 @@ use super::{
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// use rosu_pp::{Beatmap, ModeDifficulty};
|
||||
/// use rosu_pp::{Beatmap, Difficulty};
|
||||
/// use rosu_pp::catch::{Catch, CatchGradualDifficulty};
|
||||
///
|
||||
/// let converted = Beatmap::from_path("./resources/2118524.osu")
|
||||
/// .unwrap()
|
||||
/// .unchecked_into_converted::<Catch>();
|
||||
///
|
||||
/// let difficulty = ModeDifficulty::new().mods(64); // DT
|
||||
/// let difficulty = Difficulty::new().mods(64); // DT
|
||||
/// let mut iter = CatchGradualDifficulty::new(&difficulty, &converted);
|
||||
///
|
||||
/// // the difficulty of the map after the first hit object
|
||||
@@ -66,7 +66,7 @@ pub struct CatchGradualDifficulty {
|
||||
}
|
||||
|
||||
impl CatchGradualDifficulty {
|
||||
pub fn new(difficulty: &ModeDifficulty, converted: &CatchBeatmap<'_>) -> Self {
|
||||
pub fn new(difficulty: &Difficulty, converted: &CatchBeatmap<'_>) -> Self {
|
||||
let mods = difficulty.get_mods();
|
||||
let clock_rate = difficulty.get_clock_rate();
|
||||
|
||||
@@ -163,7 +163,7 @@ impl ExactSizeIterator for CatchGradualDifficulty {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::Beatmap;
|
||||
use crate::{any::difficulty::converted::ConvertedDifficulty, Beatmap};
|
||||
|
||||
use super::*;
|
||||
|
||||
@@ -171,7 +171,7 @@ mod tests {
|
||||
fn empty() {
|
||||
let converted = Beatmap::from_bytes(&[]).unwrap().unchecked_into_converted();
|
||||
|
||||
let difficulty = ModeDifficulty::new();
|
||||
let difficulty = Difficulty::new();
|
||||
let mut gradual = CatchGradualDifficulty::new(&difficulty, &converted);
|
||||
|
||||
assert!(gradual.next().is_none());
|
||||
@@ -183,7 +183,7 @@ mod tests {
|
||||
.unwrap()
|
||||
.unchecked_into_converted();
|
||||
|
||||
let difficulty = ModeDifficulty::new();
|
||||
let difficulty = Difficulty::new();
|
||||
|
||||
let mut gradual = CatchGradualDifficulty::new(&difficulty, &converted);
|
||||
let mut gradual_2nd = CatchGradualDifficulty::new(&difficulty, &converted);
|
||||
@@ -207,7 +207,7 @@ mod tests {
|
||||
assert_eq!(next_gradual, next_gradual_3rd);
|
||||
}
|
||||
|
||||
let expected = ModeDifficulty::new()
|
||||
let expected = ConvertedDifficulty::new()
|
||||
.passed_objects(i as u32)
|
||||
.calculate(&converted);
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use crate::{
|
||||
any::difficulty::{mode::ModeDifficulty, skills::Skill},
|
||||
any::difficulty::{skills::Skill, Difficulty},
|
||||
catch::{
|
||||
catcher::Catcher, convert::convert_objects, difficulty::object::CatchDifficultyObject,
|
||||
},
|
||||
@@ -22,7 +22,7 @@ mod skills;
|
||||
const STAR_SCALING_FACTOR: f64 = 0.153;
|
||||
|
||||
pub fn difficulty(
|
||||
difficulty: &ModeDifficulty,
|
||||
difficulty: &Difficulty,
|
||||
converted: &CatchBeatmap<'_>,
|
||||
) -> CatchDifficultyAttributes {
|
||||
let DifficultyValues {
|
||||
@@ -41,7 +41,7 @@ pub struct CatchDifficultySetup {
|
||||
}
|
||||
|
||||
impl CatchDifficultySetup {
|
||||
pub fn new(difficulty: &ModeDifficulty, converted: &CatchBeatmap<'_>) -> Self {
|
||||
pub fn new(difficulty: &Difficulty, converted: &CatchBeatmap<'_>) -> Self {
|
||||
let mods = difficulty.get_mods();
|
||||
let clock_rate = difficulty.get_clock_rate();
|
||||
|
||||
@@ -67,7 +67,7 @@ pub struct DifficultyValues {
|
||||
}
|
||||
|
||||
impl DifficultyValues {
|
||||
pub fn calculate(difficulty: &ModeDifficulty, converted: &CatchBeatmap<'_>) -> Self {
|
||||
pub fn calculate(difficulty: &Difficulty, converted: &CatchBeatmap<'_>) -> Self {
|
||||
let take = difficulty.get_passed_objects();
|
||||
let mods = difficulty.get_mods();
|
||||
let clock_rate = difficulty.get_clock_rate();
|
||||
|
||||
+5
-5
@@ -1,9 +1,9 @@
|
||||
use crate::{
|
||||
any::ModeDifficulty,
|
||||
model::{
|
||||
beatmap::Beatmap,
|
||||
mode::{ConvertStatus, IGameMode},
|
||||
},
|
||||
Difficulty,
|
||||
};
|
||||
|
||||
pub use self::{
|
||||
@@ -47,13 +47,13 @@ impl IGameMode for Catch {
|
||||
}
|
||||
|
||||
fn difficulty(
|
||||
difficulty: &ModeDifficulty,
|
||||
difficulty: &Difficulty,
|
||||
converted: &CatchBeatmap<'_>,
|
||||
) -> Self::DifficultyAttributes {
|
||||
difficulty::difficulty(difficulty, converted)
|
||||
}
|
||||
|
||||
fn strains(difficulty: &ModeDifficulty, converted: &CatchBeatmap<'_>) -> Self::Strains {
|
||||
fn strains(difficulty: &Difficulty, converted: &CatchBeatmap<'_>) -> Self::Strains {
|
||||
strains::strains(difficulty, converted)
|
||||
}
|
||||
|
||||
@@ -62,14 +62,14 @@ impl IGameMode for Catch {
|
||||
}
|
||||
|
||||
fn gradual_difficulty(
|
||||
difficulty: &ModeDifficulty,
|
||||
difficulty: &Difficulty,
|
||||
map: &CatchBeatmap<'_>,
|
||||
) -> Self::GradualDifficulty {
|
||||
CatchGradualDifficulty::new(difficulty, map)
|
||||
}
|
||||
|
||||
fn gradual_performance(
|
||||
difficulty: &ModeDifficulty,
|
||||
difficulty: &Difficulty,
|
||||
map: &CatchBeatmap<'_>,
|
||||
) -> Self::GradualPerformance {
|
||||
CatchGradualPerformance::new(difficulty, map)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use crate::{
|
||||
catch::{CatchBeatmap, CatchGradualDifficulty, CatchPerformanceAttributes, CatchScoreState},
|
||||
ModeDifficulty,
|
||||
Difficulty,
|
||||
};
|
||||
|
||||
/// Gradually calculate the performance attributes of an osu!catch map.
|
||||
@@ -21,14 +21,14 @@ use crate::{
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// use rosu_pp::{Beatmap, ModeDifficulty};
|
||||
/// use rosu_pp::{Beatmap, Difficulty};
|
||||
/// use rosu_pp::catch::{Catch, CatchGradualPerformance, CatchScoreState};
|
||||
///
|
||||
/// let converted = Beatmap::from_path("./resources/2118524.osu")
|
||||
/// .unwrap()
|
||||
/// .unchecked_into_converted::<Catch>();
|
||||
///
|
||||
/// let difficulty = ModeDifficulty::new().mods(64); // DT
|
||||
/// let difficulty = Difficulty::new().mods(64); // DT
|
||||
/// let mut gradual = CatchGradualPerformance::new(&difficulty, &converted);
|
||||
/// let mut state = CatchScoreState::new(); // empty state, everything is on 0.
|
||||
///
|
||||
@@ -90,7 +90,7 @@ pub struct CatchGradualPerformance {
|
||||
|
||||
impl CatchGradualPerformance {
|
||||
/// Create a new gradual performance calculator for osu!catch maps.
|
||||
pub fn new(difficulty: &ModeDifficulty, converted: &CatchBeatmap<'_>) -> Self {
|
||||
pub fn new(difficulty: &Difficulty, converted: &CatchBeatmap<'_>) -> Self {
|
||||
let difficulty = CatchGradualDifficulty::new(difficulty, converted);
|
||||
|
||||
Self { difficulty }
|
||||
@@ -144,7 +144,7 @@ mod tests {
|
||||
.unchecked_into_converted();
|
||||
|
||||
let mods = 88; // HDHRDT
|
||||
let difficulty = ModeDifficulty::new().mods(88);
|
||||
let difficulty = Difficulty::new().mods(88);
|
||||
|
||||
let mut gradual = CatchGradualPerformance::new(&difficulty, &converted);
|
||||
let mut gradual_2nd = CatchGradualPerformance::new(&difficulty, &converted);
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
use std::cmp::{self, Ordering};
|
||||
|
||||
use crate::{
|
||||
any::ModeAttributeProvider,
|
||||
any::ModeDifficulty,
|
||||
any::{Difficulty, ModeAttributeProvider},
|
||||
osu::OsuPerformance,
|
||||
util::{map_or_attrs::MapOrAttrs, mods::Mods},
|
||||
};
|
||||
@@ -21,7 +20,7 @@ pub mod gradual;
|
||||
#[must_use]
|
||||
pub struct CatchPerformance<'map> {
|
||||
map_or_attrs: MapOrAttrs<'map, Catch>,
|
||||
difficulty: ModeDifficulty,
|
||||
difficulty: Difficulty,
|
||||
acc: Option<f64>,
|
||||
combo: Option<u32>,
|
||||
fruits: Option<u32>,
|
||||
@@ -36,7 +35,7 @@ impl<'map> CatchPerformance<'map> {
|
||||
pub const fn new(map: CatchBeatmap<'map>) -> Self {
|
||||
Self {
|
||||
map_or_attrs: MapOrAttrs::Map(map),
|
||||
difficulty: ModeDifficulty::new(),
|
||||
difficulty: Difficulty::new(),
|
||||
acc: None,
|
||||
combo: None,
|
||||
fruits: None,
|
||||
@@ -50,7 +49,7 @@ impl<'map> CatchPerformance<'map> {
|
||||
pub(crate) const fn from_catch_attributes(attrs: CatchDifficultyAttributes) -> Self {
|
||||
Self {
|
||||
map_or_attrs: MapOrAttrs::Attrs(attrs),
|
||||
difficulty: ModeDifficulty::new(),
|
||||
difficulty: Difficulty::new(),
|
||||
acc: None,
|
||||
combo: None,
|
||||
fruits: None,
|
||||
@@ -180,7 +179,7 @@ impl<'map> CatchPerformance<'map> {
|
||||
pub fn generate_state(&mut self) -> CatchScoreState {
|
||||
let attrs = match self.map_or_attrs {
|
||||
MapOrAttrs::Map(ref map) => {
|
||||
let attrs = self.generate_attributes(map);
|
||||
let attrs = self.difficulty.with_mode().calculate(map);
|
||||
|
||||
self.map_or_attrs.insert_attrs(attrs)
|
||||
}
|
||||
@@ -327,7 +326,7 @@ impl<'map> CatchPerformance<'map> {
|
||||
let state = self.generate_state();
|
||||
|
||||
let attrs = match self.map_or_attrs {
|
||||
MapOrAttrs::Map(ref map) => self.generate_attributes(map),
|
||||
MapOrAttrs::Map(ref map) => self.difficulty.with_mode().calculate(map),
|
||||
MapOrAttrs::Attrs(attrs) => attrs,
|
||||
};
|
||||
|
||||
@@ -340,10 +339,6 @@ impl<'map> CatchPerformance<'map> {
|
||||
inner.calculate()
|
||||
}
|
||||
|
||||
fn generate_attributes(&self, map: &CatchBeatmap<'_>) -> CatchDifficultyAttributes {
|
||||
self.difficulty.calculate(map)
|
||||
}
|
||||
|
||||
/// Try to create [`CatchPerformance`] through a [`ModeAttributeProvider`].
|
||||
///
|
||||
/// If you already calculated the attributes for the current map-mod
|
||||
@@ -547,7 +542,7 @@ mod test {
|
||||
|
||||
use proptest::prelude::*;
|
||||
|
||||
use crate::Beatmap;
|
||||
use crate::{any::difficulty::converted::ConvertedDifficulty, Beatmap};
|
||||
|
||||
use super::*;
|
||||
|
||||
@@ -564,7 +559,7 @@ mod test {
|
||||
.unwrap()
|
||||
.unchecked_into_converted::<Catch>();
|
||||
|
||||
let attrs = ModeDifficulty::new().calculate(&converted);
|
||||
let attrs = ConvertedDifficulty::new().calculate(&converted);
|
||||
|
||||
assert_eq!(N_FRUITS, attrs.n_fruits);
|
||||
assert_eq!(N_DROPLETS, attrs.n_droplets);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use crate::{any::ModeDifficulty, catch::difficulty::DifficultyValues};
|
||||
use crate::{any::Difficulty, catch::difficulty::DifficultyValues};
|
||||
|
||||
use super::convert::CatchBeatmap;
|
||||
|
||||
@@ -16,7 +16,7 @@ impl CatchStrains {
|
||||
pub const SECTION_LEN: f64 = 750.0;
|
||||
}
|
||||
|
||||
pub fn strains(difficulty: &ModeDifficulty, converted: &CatchBeatmap<'_>) -> CatchStrains {
|
||||
pub fn strains(difficulty: &Difficulty, converted: &CatchBeatmap<'_>) -> CatchStrains {
|
||||
let DifficultyValues { movement, .. } = DifficultyValues::calculate(difficulty, converted);
|
||||
|
||||
CatchStrains {
|
||||
|
||||
+9
-6
@@ -21,9 +21,9 @@
|
||||
//! let map = rosu_pp::Beatmap::from_path("./resources/2785319.osu").unwrap();
|
||||
//!
|
||||
//! // Calculate difficulty attributes
|
||||
//! let diff_attrs = map.difficulty()
|
||||
//! let diff_attrs = rosu_pp::Difficulty::new()
|
||||
//! .mods(8 + 16) // HDHR
|
||||
//! .calculate();
|
||||
//! .calculate(&map);
|
||||
//!
|
||||
//! let stars = diff_attrs.stars();
|
||||
//!
|
||||
@@ -62,12 +62,15 @@
|
||||
//! score state.
|
||||
//!
|
||||
//! ```
|
||||
//! use rosu_pp::{Beatmap, GradualPerformance, ModeDifficulty, any::ScoreState};
|
||||
//! use rosu_pp::{Beatmap, GradualPerformance, Difficulty, any::ScoreState};
|
||||
//!
|
||||
//! let map = Beatmap::from_path("./resources/1028484.osu").unwrap();
|
||||
//! let difficulty = ModeDifficulty::new().mods(16 + 64).clock_rate(1.2); // HRDT on 1.2x
|
||||
//!
|
||||
//! let mut gradual = GradualPerformance::new(&difficulty, &map);
|
||||
//! let mut gradual = Difficulty::new()
|
||||
//! .mods(16 + 64) // HRDT
|
||||
//! .clock_rate(1.2)
|
||||
//! .gradual_performance(&map);
|
||||
//!
|
||||
//! let mut state = ScoreState::new(); // empty state, everything is on 0.
|
||||
//!
|
||||
//! // The first 10 hitresults are 300s
|
||||
@@ -162,7 +165,7 @@
|
||||
|
||||
#[doc(inline)]
|
||||
pub use self::{
|
||||
any::{Difficulty, GradualDifficulty, GradualPerformance, ModeDifficulty, Performance},
|
||||
any::{ConvertedDifficulty, Difficulty, GradualDifficulty, GradualPerformance, Performance},
|
||||
model::beatmap::{Beatmap, Converted},
|
||||
};
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ use crate::{
|
||||
mania::{object::ObjectParams, ManiaBeatmap},
|
||||
model::{beatmap::HitWindows, hit_object::HitObject},
|
||||
util::float_ext::FloatExt,
|
||||
ModeDifficulty,
|
||||
Difficulty,
|
||||
};
|
||||
|
||||
use super::{
|
||||
@@ -25,14 +25,14 @@ use super::{
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// use rosu_pp::{Beatmap, ModeDifficulty};
|
||||
/// use rosu_pp::{Beatmap, Difficulty};
|
||||
/// use rosu_pp::mania::ManiaGradualDifficulty;
|
||||
///
|
||||
/// let converted = Beatmap::from_path("./resources/1638954.osu")
|
||||
/// .unwrap()
|
||||
/// .unchecked_into_converted();
|
||||
///
|
||||
/// let difficulty = ModeDifficulty::new().mods(64); // DT
|
||||
/// let difficulty = Difficulty::new().mods(64); // DT
|
||||
/// let mut iter = ManiaGradualDifficulty::new(&difficulty, &converted);
|
||||
///
|
||||
/// // the difficulty of the map after the first hit object
|
||||
@@ -61,7 +61,7 @@ pub struct ManiaGradualDifficulty {
|
||||
|
||||
impl ManiaGradualDifficulty {
|
||||
/// Create a new difficulty attributes iterator for osu!mania maps.
|
||||
pub fn new(difficulty: &ModeDifficulty, converted: &ManiaBeatmap<'_>) -> Self {
|
||||
pub fn new(difficulty: &Difficulty, converted: &ManiaBeatmap<'_>) -> Self {
|
||||
let take = difficulty.get_passed_objects();
|
||||
let mods = difficulty.get_mods();
|
||||
let total_columns = converted.cs.round_even().max(1.0);
|
||||
@@ -209,7 +209,7 @@ fn increment_combo_raw(is_circle: bool, start_time: f64, end_time: f64, curr_com
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::{mania::Mania, Beatmap};
|
||||
use crate::{any::difficulty::converted::ConvertedDifficulty, mania::Mania, Beatmap};
|
||||
|
||||
use super::*;
|
||||
|
||||
@@ -219,7 +219,7 @@ mod tests {
|
||||
.unwrap()
|
||||
.unchecked_into_converted::<Mania>();
|
||||
|
||||
let difficulty = ModeDifficulty::new();
|
||||
let difficulty = Difficulty::new();
|
||||
let mut gradual = ManiaGradualDifficulty::new(&difficulty, &converted);
|
||||
|
||||
assert!(gradual.next().is_none());
|
||||
@@ -231,7 +231,7 @@ mod tests {
|
||||
.unwrap()
|
||||
.unchecked_into_converted::<Mania>();
|
||||
|
||||
let difficulty = ModeDifficulty::new();
|
||||
let difficulty = Difficulty::new();
|
||||
|
||||
let mut gradual = ManiaGradualDifficulty::new(&difficulty, &converted);
|
||||
let mut gradual_2nd = ManiaGradualDifficulty::new(&difficulty, &converted);
|
||||
@@ -257,7 +257,7 @@ mod tests {
|
||||
assert_eq!(next_gradual, next_gradual_3rd);
|
||||
}
|
||||
|
||||
let expected = ModeDifficulty::new()
|
||||
let expected = ConvertedDifficulty::new()
|
||||
.passed_objects(i as u32)
|
||||
.calculate(&converted);
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use std::cmp;
|
||||
|
||||
use crate::{
|
||||
any::difficulty::{mode::ModeDifficulty, skills::Skill},
|
||||
any::difficulty::{skills::Skill, Difficulty},
|
||||
mania::{
|
||||
difficulty::{object::ManiaDifficultyObject, skills::strain::Strain},
|
||||
object::{ManiaObject, ObjectParams},
|
||||
@@ -18,7 +18,7 @@ mod skills;
|
||||
const STAR_SCALING_FACTOR: f64 = 0.018;
|
||||
|
||||
pub fn difficulty(
|
||||
difficulty: &ModeDifficulty,
|
||||
difficulty: &Difficulty,
|
||||
converted: &ManiaBeatmap<'_>,
|
||||
) -> ManiaDifficultyAttributes {
|
||||
let n_objects = cmp::min(difficulty.get_passed_objects(), converted.hit_objects.len()) as u32;
|
||||
@@ -47,7 +47,7 @@ pub struct DifficultyValues {
|
||||
}
|
||||
|
||||
impl DifficultyValues {
|
||||
pub fn calculate(difficulty: &ModeDifficulty, converted: &ManiaBeatmap<'_>) -> Self {
|
||||
pub fn calculate(difficulty: &Difficulty, converted: &ManiaBeatmap<'_>) -> Self {
|
||||
let take = difficulty.get_passed_objects();
|
||||
let total_columns = converted.cs.round_even().max(1.0);
|
||||
let clock_rate = difficulty.get_clock_rate();
|
||||
|
||||
+5
-5
@@ -1,9 +1,9 @@
|
||||
use crate::{
|
||||
any::ModeDifficulty,
|
||||
model::{
|
||||
beatmap::Beatmap,
|
||||
mode::{ConvertStatus, IGameMode},
|
||||
},
|
||||
Difficulty,
|
||||
};
|
||||
|
||||
pub use self::{
|
||||
@@ -44,13 +44,13 @@ impl IGameMode for Mania {
|
||||
}
|
||||
|
||||
fn difficulty(
|
||||
difficulty: &ModeDifficulty,
|
||||
difficulty: &Difficulty,
|
||||
converted: &ManiaBeatmap<'_>,
|
||||
) -> Self::DifficultyAttributes {
|
||||
difficulty::difficulty(difficulty, converted)
|
||||
}
|
||||
|
||||
fn strains(difficulty: &ModeDifficulty, converted: &ManiaBeatmap<'_>) -> Self::Strains {
|
||||
fn strains(difficulty: &Difficulty, converted: &ManiaBeatmap<'_>) -> Self::Strains {
|
||||
strains::strains(difficulty, converted)
|
||||
}
|
||||
|
||||
@@ -59,14 +59,14 @@ impl IGameMode for Mania {
|
||||
}
|
||||
|
||||
fn gradual_difficulty(
|
||||
difficulty: &ModeDifficulty,
|
||||
difficulty: &Difficulty,
|
||||
map: &ManiaBeatmap<'_>,
|
||||
) -> Self::GradualDifficulty {
|
||||
ManiaGradualDifficulty::new(difficulty, map)
|
||||
}
|
||||
|
||||
fn gradual_performance(
|
||||
difficulty: &ModeDifficulty,
|
||||
difficulty: &Difficulty,
|
||||
map: &ManiaBeatmap<'_>,
|
||||
) -> Self::GradualPerformance {
|
||||
ManiaGradualPerformance::new(difficulty, map)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use crate::{
|
||||
mania::{ManiaBeatmap, ManiaGradualDifficulty},
|
||||
ModeDifficulty,
|
||||
Difficulty,
|
||||
};
|
||||
|
||||
use super::{ManiaPerformanceAttributes, ManiaScoreState};
|
||||
@@ -20,14 +20,14 @@ use super::{ManiaPerformanceAttributes, ManiaScoreState};
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// use rosu_pp::{Beatmap, ModeDifficulty};
|
||||
/// use rosu_pp::{Beatmap, Difficulty};
|
||||
/// use rosu_pp::mania::{Mania, ManiaGradualPerformance, ManiaScoreState};
|
||||
///
|
||||
/// let converted = Beatmap::from_path("./resources/1638954.osu")
|
||||
/// .unwrap()
|
||||
/// .unchecked_into_converted::<Mania>();
|
||||
///
|
||||
/// let difficulty = ModeDifficulty::new().mods(64); // DT
|
||||
/// let difficulty = Difficulty::new().mods(64); // DT
|
||||
/// let mut gradual = ManiaGradualPerformance::new(&difficulty, &converted);
|
||||
/// let mut state = ManiaScoreState::new(); // empty state, everything is on 0.
|
||||
///
|
||||
@@ -75,7 +75,7 @@ pub struct ManiaGradualPerformance {
|
||||
|
||||
impl ManiaGradualPerformance {
|
||||
/// Create a new gradual performance calculator for osu!mania maps.
|
||||
pub fn new(difficulty: &ModeDifficulty, converted: &ManiaBeatmap<'_>) -> Self {
|
||||
pub fn new(difficulty: &Difficulty, converted: &ManiaBeatmap<'_>) -> Self {
|
||||
let difficulty = ManiaGradualDifficulty::new(difficulty, converted);
|
||||
|
||||
Self { difficulty }
|
||||
@@ -129,7 +129,7 @@ mod tests {
|
||||
.unchecked_into_converted::<Mania>();
|
||||
|
||||
let mods = 88; // HDHRDT
|
||||
let difficulty = ModeDifficulty::new().mods(88);
|
||||
let difficulty = Difficulty::new().mods(88);
|
||||
|
||||
let mut gradual = ManiaGradualPerformance::new(&difficulty, &converted);
|
||||
let mut gradual_2nd = ManiaGradualPerformance::new(&difficulty, &converted);
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
use std::cmp;
|
||||
|
||||
use crate::{
|
||||
any::ModeDifficulty,
|
||||
any::{HitResultPriority, ModeAttributeProvider},
|
||||
any::{Difficulty, HitResultPriority, ModeAttributeProvider},
|
||||
osu::OsuPerformance,
|
||||
util::{map_or_attrs::MapOrAttrs, mods::Mods},
|
||||
};
|
||||
@@ -21,7 +20,7 @@ pub mod gradual;
|
||||
#[must_use]
|
||||
pub struct ManiaPerformance<'map> {
|
||||
map_or_attrs: MapOrAttrs<'map, Mania>,
|
||||
difficulty: ModeDifficulty,
|
||||
difficulty: Difficulty,
|
||||
n320: Option<u32>,
|
||||
n300: Option<u32>,
|
||||
n200: Option<u32>,
|
||||
@@ -37,7 +36,7 @@ impl<'map> ManiaPerformance<'map> {
|
||||
pub const fn new(map: ManiaBeatmap<'map>) -> Self {
|
||||
Self {
|
||||
map_or_attrs: MapOrAttrs::Map(map),
|
||||
difficulty: ModeDifficulty::new(),
|
||||
difficulty: Difficulty::new(),
|
||||
n320: None,
|
||||
n300: None,
|
||||
n200: None,
|
||||
@@ -52,7 +51,7 @@ impl<'map> ManiaPerformance<'map> {
|
||||
pub(crate) const fn from_mania_attributes(attrs: ManiaDifficultyAttributes) -> Self {
|
||||
Self {
|
||||
map_or_attrs: MapOrAttrs::Attrs(attrs),
|
||||
difficulty: ModeDifficulty::new(),
|
||||
difficulty: Difficulty::new(),
|
||||
n320: None,
|
||||
n300: None,
|
||||
n200: None,
|
||||
@@ -192,7 +191,7 @@ impl<'map> ManiaPerformance<'map> {
|
||||
pub fn generate_state(&mut self) -> ManiaScoreState {
|
||||
let attrs = match self.map_or_attrs {
|
||||
MapOrAttrs::Map(ref map) => {
|
||||
let attrs = self.generate_attributes(map);
|
||||
let attrs = self.difficulty.with_mode().calculate(map);
|
||||
|
||||
self.map_or_attrs.insert_attrs(attrs)
|
||||
}
|
||||
@@ -718,7 +717,7 @@ impl<'map> ManiaPerformance<'map> {
|
||||
let state = self.generate_state();
|
||||
|
||||
let attrs = match self.map_or_attrs {
|
||||
MapOrAttrs::Map(ref map) => self.generate_attributes(map),
|
||||
MapOrAttrs::Map(ref map) => self.difficulty.with_mode().calculate(map),
|
||||
MapOrAttrs::Attrs(attrs) => attrs,
|
||||
};
|
||||
|
||||
@@ -731,10 +730,6 @@ impl<'map> ManiaPerformance<'map> {
|
||||
inner.calculate()
|
||||
}
|
||||
|
||||
fn generate_attributes(&self, map: &ManiaBeatmap<'_>) -> ManiaDifficultyAttributes {
|
||||
self.difficulty.calculate(map)
|
||||
}
|
||||
|
||||
/// Try to create [`ManiaPerformance`] through a [`ModeAttributeProvider`].
|
||||
///
|
||||
/// If you already calculated the attributes for the current map-mod
|
||||
@@ -921,7 +916,7 @@ mod tests {
|
||||
|
||||
use proptest::prelude::*;
|
||||
|
||||
use crate::Beatmap;
|
||||
use crate::{any::difficulty::converted::ConvertedDifficulty, Beatmap};
|
||||
|
||||
use super::*;
|
||||
|
||||
@@ -936,7 +931,7 @@ mod tests {
|
||||
.unwrap()
|
||||
.unchecked_into_converted::<Mania>();
|
||||
|
||||
let attrs = ModeDifficulty::new().calculate(&converted);
|
||||
let attrs = ConvertedDifficulty::new().calculate(&converted);
|
||||
|
||||
assert_eq!(N_OBJECTS, converted.hit_objects.len() as u32);
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use crate::{any::ModeDifficulty, mania::difficulty::DifficultyValues};
|
||||
use crate::{any::Difficulty, mania::difficulty::DifficultyValues};
|
||||
|
||||
use super::convert::ManiaBeatmap;
|
||||
|
||||
@@ -16,7 +16,7 @@ impl ManiaStrains {
|
||||
pub const SECTION_LEN: f64 = 400.0;
|
||||
}
|
||||
|
||||
pub fn strains(difficulty: &ModeDifficulty, converted: &ManiaBeatmap<'_>) -> ManiaStrains {
|
||||
pub fn strains(difficulty: &Difficulty, converted: &ManiaBeatmap<'_>) -> ManiaStrains {
|
||||
let values = DifficultyValues::calculate(difficulty, converted);
|
||||
|
||||
ManiaStrains {
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
use std::{
|
||||
any,
|
||||
borrow::Cow,
|
||||
fmt::{Debug, Formatter, Result as FmtResult},
|
||||
marker::PhantomData,
|
||||
@@ -8,7 +7,8 @@ use std::{
|
||||
|
||||
use crate::{
|
||||
model::mode::{ConvertStatus, IGameMode},
|
||||
ModeDifficulty,
|
||||
util::generic_fmt::GenericFormatter,
|
||||
Difficulty,
|
||||
};
|
||||
|
||||
use super::Beatmap;
|
||||
@@ -74,13 +74,13 @@ impl<M: IGameMode> Converted<'_, M> {
|
||||
}
|
||||
|
||||
/// Create a gradual difficulty calculator for the map.
|
||||
pub fn gradual_difficulty(&self, difficulty: &ModeDifficulty) -> M::GradualDifficulty {
|
||||
difficulty.gradual_difficulty(self)
|
||||
pub fn gradual_difficulty(&self, difficulty: &Difficulty) -> M::GradualDifficulty {
|
||||
M::gradual_difficulty(difficulty, self)
|
||||
}
|
||||
|
||||
/// Create a gradual performance calculator for the map.
|
||||
pub fn gradual_performance(&self, difficulty: &ModeDifficulty) -> M::GradualPerformance {
|
||||
difficulty.gradual_performance(self)
|
||||
pub fn gradual_performance(&self, difficulty: &Difficulty) -> M::GradualPerformance {
|
||||
M::gradual_performance(difficulty, self)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -189,34 +189,9 @@ impl<M> Clone for Converted<'_, M> {
|
||||
|
||||
impl<M> Debug for Converted<'_, M> {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
|
||||
struct GenericFormatter<T>(PhantomData<T>);
|
||||
|
||||
impl<T> Default for GenericFormatter<T> {
|
||||
fn default() -> Self {
|
||||
Self(PhantomData)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Debug for GenericFormatter<T> {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
|
||||
fn fmt_stripped(full_type_name: &str, f: &mut Formatter<'_>) -> FmtResult {
|
||||
// Strip fully qualified syntax
|
||||
if let Some(position) = full_type_name.rfind("::") {
|
||||
if let Some(type_name) = full_type_name.get(position + 2..) {
|
||||
f.write_str(type_name)?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fmt_stripped(any::type_name::<T>(), f)
|
||||
}
|
||||
}
|
||||
|
||||
f.debug_struct("Converted")
|
||||
.field("map", &self.map)
|
||||
.field("mode", &GenericFormatter::<M>::default())
|
||||
.field("mode", &GenericFormatter::<M>::new())
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ use rosu_map::{
|
||||
|
||||
use crate::{
|
||||
catch::Catch, mania::Mania, osu::Osu, taiko::Taiko, Difficulty, GradualDifficulty,
|
||||
GradualPerformance, ModeDifficulty, Performance,
|
||||
GradualPerformance, Performance,
|
||||
};
|
||||
|
||||
pub use self::{
|
||||
@@ -85,23 +85,18 @@ impl Beatmap {
|
||||
bpm::bpm(self.hit_objects.last(), &self.timing_points)
|
||||
}
|
||||
|
||||
/// Create a difficulty calculator for this [`Beatmap`].
|
||||
pub const fn difficulty(&self) -> Difficulty<'_> {
|
||||
Difficulty::new(self)
|
||||
}
|
||||
|
||||
/// Create a performance calculator for this [`Beatmap`].
|
||||
pub const fn performance(&self) -> Performance<'_> {
|
||||
Performance::new(self)
|
||||
}
|
||||
|
||||
/// Create a gradual difficulty calculator for this [`Beatmap`].
|
||||
pub fn gradual_difficulty(&self, difficulty: &ModeDifficulty) -> GradualDifficulty {
|
||||
pub fn gradual_difficulty(&self, difficulty: &Difficulty) -> GradualDifficulty {
|
||||
GradualDifficulty::new(difficulty, self)
|
||||
}
|
||||
|
||||
/// Create a gradual performance calculator for this [`Beatmap`].
|
||||
pub fn gradual_performance(&self, difficulty: &ModeDifficulty) -> GradualPerformance {
|
||||
pub fn gradual_performance(&self, difficulty: &Difficulty) -> GradualPerformance {
|
||||
GradualPerformance::new(difficulty, self)
|
||||
}
|
||||
|
||||
@@ -126,7 +121,7 @@ impl Beatmap {
|
||||
}
|
||||
|
||||
/// Convert a [`&mut Beatmap`] to the specified mode with an argument
|
||||
/// instead of a generic parameter and return the [`ConvertStatus`].
|
||||
/// instead of a generic parameter.
|
||||
///
|
||||
/// [`&mut Beatmap`]: Beatmap
|
||||
pub fn convert_inplace(&mut self, mode: GameMode) -> ConvertStatus {
|
||||
|
||||
+6
-8
@@ -1,6 +1,6 @@
|
||||
pub use rosu_map::section::general::GameMode;
|
||||
|
||||
use crate::any::ModeDifficulty;
|
||||
use crate::Difficulty;
|
||||
|
||||
use super::beatmap::{Beatmap, Converted};
|
||||
|
||||
@@ -40,27 +40,25 @@ pub trait IGameMode: Sized {
|
||||
|
||||
/// Perform a difficulty calculation for a [`Converted`] beatmap and
|
||||
/// process the final skill values.
|
||||
fn difficulty(
|
||||
difficulty: &ModeDifficulty,
|
||||
map: &Converted<'_, Self>,
|
||||
) -> Self::DifficultyAttributes;
|
||||
fn difficulty(difficulty: &Difficulty, map: &Converted<'_, Self>)
|
||||
-> Self::DifficultyAttributes;
|
||||
|
||||
/// Perform a difficulty calculation for a [`Converted`] beatmap without
|
||||
/// processing the final skill values.
|
||||
fn strains(difficulty: &ModeDifficulty, map: &Converted<'_, Self>) -> Self::Strains;
|
||||
fn strains(difficulty: &Difficulty, map: &Converted<'_, Self>) -> Self::Strains;
|
||||
|
||||
/// Create a performance calculator for a [`Converted`] beatmap.
|
||||
fn performance(map: Converted<'_, Self>) -> Self::Performance<'_>;
|
||||
|
||||
/// Create a gradual difficulty calculator for a [`Converted`] beatmap.
|
||||
fn gradual_difficulty(
|
||||
difficulty: &ModeDifficulty,
|
||||
difficulty: &Difficulty,
|
||||
map: &Converted<'_, Self>,
|
||||
) -> Self::GradualDifficulty;
|
||||
|
||||
/// Create a gradual performance calculator for a [`Converted`] beatmap.
|
||||
fn gradual_performance(
|
||||
difficulty: &ModeDifficulty,
|
||||
difficulty: &Difficulty,
|
||||
map: &Converted<'_, Self>,
|
||||
) -> Self::GradualPerformance;
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ use crate::{
|
||||
OsuBeatmap,
|
||||
},
|
||||
util::mods::Mods,
|
||||
ModeDifficulty,
|
||||
Difficulty,
|
||||
};
|
||||
|
||||
use self::osu_objects::OsuObjects;
|
||||
@@ -31,14 +31,14 @@ use super::{
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// use rosu_pp::{Beatmap, ModeDifficulty};
|
||||
/// use rosu_pp::{Beatmap, Difficulty};
|
||||
/// use rosu_pp::osu::{Osu, OsuGradualDifficulty};
|
||||
///
|
||||
/// let converted = Beatmap::from_path("./resources/2785319.osu")
|
||||
/// .unwrap()
|
||||
/// .unchecked_into_converted::<Osu>();
|
||||
///
|
||||
/// let difficulty = ModeDifficulty::new().mods(64); // DT
|
||||
/// let difficulty = Difficulty::new().mods(64); // DT
|
||||
/// let mut iter = OsuGradualDifficulty::new(&difficulty, &converted);
|
||||
///
|
||||
/// // the difficulty of the map after the first hit object
|
||||
@@ -73,7 +73,7 @@ struct NotClonable;
|
||||
|
||||
impl OsuGradualDifficulty {
|
||||
/// Create a new difficulty attributes iterator for osu!standard maps.
|
||||
pub fn new(difficulty: &ModeDifficulty, converted: &OsuBeatmap<'_>) -> Self {
|
||||
pub fn new(difficulty: &Difficulty, converted: &OsuBeatmap<'_>) -> Self {
|
||||
let mods = difficulty.get_mods();
|
||||
let clock_rate = difficulty.get_clock_rate();
|
||||
|
||||
@@ -262,7 +262,7 @@ mod osu_objects {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
|
||||
use crate::{osu::Osu, Beatmap};
|
||||
use crate::{any::difficulty::converted::ConvertedDifficulty, osu::Osu, Beatmap};
|
||||
|
||||
use super::*;
|
||||
|
||||
@@ -272,7 +272,7 @@ mod tests {
|
||||
.unwrap()
|
||||
.unchecked_into_converted::<Osu>();
|
||||
|
||||
let difficulty = ModeDifficulty::new();
|
||||
let difficulty = Difficulty::new();
|
||||
let mut gradual = OsuGradualDifficulty::new(&difficulty, &converted);
|
||||
|
||||
assert!(gradual.next().is_none());
|
||||
@@ -284,7 +284,7 @@ mod tests {
|
||||
.unwrap()
|
||||
.unchecked_into_converted::<Osu>();
|
||||
|
||||
let difficulty = ModeDifficulty::new();
|
||||
let difficulty = Difficulty::new();
|
||||
|
||||
let mut gradual = OsuGradualDifficulty::new(&difficulty, &converted);
|
||||
let mut gradual_2nd = OsuGradualDifficulty::new(&difficulty, &converted);
|
||||
@@ -310,7 +310,7 @@ mod tests {
|
||||
assert_eq!(next_gradual, next_gradual_3rd);
|
||||
}
|
||||
|
||||
let expected = ModeDifficulty::new()
|
||||
let expected = ConvertedDifficulty::new()
|
||||
.passed_objects(i as u32)
|
||||
.calculate(&converted);
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use std::{cmp, pin::Pin};
|
||||
|
||||
use crate::{
|
||||
any::difficulty::{mode::ModeDifficulty, skills::Skill},
|
||||
any::difficulty::{skills::Skill, Difficulty},
|
||||
model::beatmap::BeatmapAttributes,
|
||||
osu::{
|
||||
convert::convert_objects,
|
||||
@@ -26,10 +26,7 @@ const DIFFICULTY_MULTIPLIER: f64 = 0.0675;
|
||||
const HD_FADE_IN_DURATION_MULTIPLIER: f64 = 0.4;
|
||||
const HD_FADE_OUT_DURATION_MULTIPLIER: f64 = 0.3;
|
||||
|
||||
pub fn difficulty(
|
||||
difficulty: &ModeDifficulty,
|
||||
converted: &OsuBeatmap<'_>,
|
||||
) -> OsuDifficultyAttributes {
|
||||
pub fn difficulty(difficulty: &Difficulty, converted: &OsuBeatmap<'_>) -> OsuDifficultyAttributes {
|
||||
let DifficultyValues {
|
||||
skills:
|
||||
OsuSkills {
|
||||
@@ -70,7 +67,7 @@ pub struct OsuDifficultySetup {
|
||||
}
|
||||
|
||||
impl OsuDifficultySetup {
|
||||
pub fn new(difficulty: &ModeDifficulty, converted: &OsuBeatmap) -> Self {
|
||||
pub fn new(difficulty: &Difficulty, converted: &OsuBeatmap) -> Self {
|
||||
let mods = difficulty.get_mods();
|
||||
let clock_rate = difficulty.get_clock_rate();
|
||||
|
||||
@@ -106,7 +103,7 @@ pub struct DifficultyValues {
|
||||
}
|
||||
|
||||
impl DifficultyValues {
|
||||
pub fn calculate(difficulty: &ModeDifficulty, converted: &OsuBeatmap<'_>) -> Self {
|
||||
pub fn calculate(difficulty: &Difficulty, converted: &OsuBeatmap<'_>) -> Self {
|
||||
let mods = difficulty.get_mods();
|
||||
let take = difficulty.get_passed_objects();
|
||||
|
||||
@@ -218,7 +215,7 @@ impl DifficultyValues {
|
||||
}
|
||||
|
||||
pub fn create_difficulty_objects<'a>(
|
||||
difficulty: &ModeDifficulty,
|
||||
difficulty: &Difficulty,
|
||||
scaling_factor: &ScalingFactor,
|
||||
osu_objects: impl ExactSizeIterator<Item = Pin<&'a mut OsuObject>>,
|
||||
) -> Vec<OsuDifficultyObject<'a>> {
|
||||
|
||||
+5
-5
@@ -1,11 +1,11 @@
|
||||
use rosu_map::util::Pos;
|
||||
|
||||
use crate::{
|
||||
any::ModeDifficulty,
|
||||
model::{
|
||||
beatmap::Beatmap,
|
||||
mode::{ConvertStatus, IGameMode},
|
||||
},
|
||||
Difficulty,
|
||||
};
|
||||
|
||||
pub use self::{
|
||||
@@ -48,13 +48,13 @@ impl IGameMode for Osu {
|
||||
}
|
||||
|
||||
fn difficulty(
|
||||
difficulty: &ModeDifficulty,
|
||||
difficulty: &Difficulty,
|
||||
converted: &OsuBeatmap<'_>,
|
||||
) -> Self::DifficultyAttributes {
|
||||
difficulty::difficulty(difficulty, converted)
|
||||
}
|
||||
|
||||
fn strains(difficulty: &ModeDifficulty, converted: &OsuBeatmap<'_>) -> Self::Strains {
|
||||
fn strains(difficulty: &Difficulty, converted: &OsuBeatmap<'_>) -> Self::Strains {
|
||||
strains::strains(difficulty, converted)
|
||||
}
|
||||
|
||||
@@ -63,14 +63,14 @@ impl IGameMode for Osu {
|
||||
}
|
||||
|
||||
fn gradual_difficulty(
|
||||
difficulty: &ModeDifficulty,
|
||||
difficulty: &Difficulty,
|
||||
map: &OsuBeatmap<'_>,
|
||||
) -> Self::GradualDifficulty {
|
||||
OsuGradualDifficulty::new(difficulty, map)
|
||||
}
|
||||
|
||||
fn gradual_performance(
|
||||
difficulty: &ModeDifficulty,
|
||||
difficulty: &Difficulty,
|
||||
map: &OsuBeatmap<'_>,
|
||||
) -> Self::GradualPerformance {
|
||||
OsuGradualPerformance::new(difficulty, map)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use crate::{
|
||||
osu::{OsuBeatmap, OsuGradualDifficulty},
|
||||
ModeDifficulty,
|
||||
Difficulty,
|
||||
};
|
||||
|
||||
use super::{OsuPerformanceAttributes, OsuScoreState};
|
||||
@@ -20,14 +20,14 @@ use super::{OsuPerformanceAttributes, OsuScoreState};
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// use rosu_pp::{Beatmap, ModeDifficulty};
|
||||
/// use rosu_pp::{Beatmap, Difficulty};
|
||||
/// use rosu_pp::osu::{Osu, OsuGradualPerformance, OsuScoreState};
|
||||
///
|
||||
/// let converted = Beatmap::from_path("./resources/2785319.osu")
|
||||
/// .unwrap()
|
||||
/// .unchecked_into_converted::<Osu>();
|
||||
///
|
||||
/// let difficulty = ModeDifficulty::new().mods(64); // DT
|
||||
/// let difficulty = Difficulty::new().mods(64); // DT
|
||||
/// let mut gradual = OsuGradualPerformance::new(&difficulty, &converted);
|
||||
/// let mut state = OsuScoreState::new(); // empty state, everything is on 0.
|
||||
///
|
||||
@@ -85,7 +85,7 @@ pub struct OsuGradualPerformance {
|
||||
|
||||
impl OsuGradualPerformance {
|
||||
/// Create a new gradual performance calculator for osu!standard maps.
|
||||
pub fn new(difficulty: &ModeDifficulty, converted: &OsuBeatmap<'_>) -> Self {
|
||||
pub fn new(difficulty: &Difficulty, converted: &OsuBeatmap<'_>) -> Self {
|
||||
let difficulty = OsuGradualDifficulty::new(difficulty, converted);
|
||||
|
||||
Self { difficulty }
|
||||
@@ -139,7 +139,7 @@ mod tests {
|
||||
.unchecked_into_converted::<Osu>();
|
||||
|
||||
let mods = 88; // HDHRDT
|
||||
let difficulty = ModeDifficulty::new().mods(88);
|
||||
let difficulty = Difficulty::new().mods(88);
|
||||
|
||||
let mut gradual = OsuGradualPerformance::new(&difficulty, &converted);
|
||||
let mut gradual_2nd = OsuGradualPerformance::new(&difficulty, &converted);
|
||||
|
||||
@@ -3,8 +3,7 @@ use std::cmp;
|
||||
use rosu_map::section::general::GameMode;
|
||||
|
||||
use crate::{
|
||||
any::ModeDifficulty,
|
||||
any::{HitResultPriority, ModeAttributeProvider, Performance},
|
||||
any::{Difficulty, HitResultPriority, ModeAttributeProvider, Performance},
|
||||
catch::CatchPerformance,
|
||||
mania::ManiaPerformance,
|
||||
taiko::TaikoPerformance,
|
||||
@@ -25,7 +24,7 @@ pub mod gradual;
|
||||
#[must_use]
|
||||
pub struct OsuPerformance<'map> {
|
||||
pub(crate) map_or_attrs: MapOrAttrs<'map, Osu>,
|
||||
pub(crate) difficulty: ModeDifficulty,
|
||||
pub(crate) difficulty: Difficulty,
|
||||
pub(crate) acc: Option<f64>,
|
||||
pub(crate) combo: Option<u32>,
|
||||
pub(crate) n300: Option<u32>,
|
||||
@@ -40,7 +39,7 @@ impl<'map> OsuPerformance<'map> {
|
||||
pub const fn new(map: OsuBeatmap<'map>) -> Self {
|
||||
Self {
|
||||
map_or_attrs: MapOrAttrs::Map(map),
|
||||
difficulty: ModeDifficulty::new(),
|
||||
difficulty: Difficulty::new(),
|
||||
acc: None,
|
||||
combo: None,
|
||||
n300: None,
|
||||
@@ -54,7 +53,7 @@ impl<'map> OsuPerformance<'map> {
|
||||
pub(crate) const fn from_osu_attributes(attrs: OsuDifficultyAttributes) -> Self {
|
||||
Self {
|
||||
map_or_attrs: MapOrAttrs::Attrs(attrs),
|
||||
difficulty: ModeDifficulty::new(),
|
||||
difficulty: Difficulty::new(),
|
||||
acc: None,
|
||||
combo: None,
|
||||
n300: None,
|
||||
@@ -233,7 +232,7 @@ impl<'map> OsuPerformance<'map> {
|
||||
pub fn generate_state(&mut self) -> OsuScoreState {
|
||||
let attrs = match self.map_or_attrs {
|
||||
MapOrAttrs::Map(ref map) => {
|
||||
let attrs = self.generate_attributes(map);
|
||||
let attrs = self.difficulty.with_mode().calculate(map);
|
||||
|
||||
self.map_or_attrs.insert_attrs(attrs)
|
||||
}
|
||||
@@ -417,7 +416,7 @@ impl<'map> OsuPerformance<'map> {
|
||||
let state = self.generate_state();
|
||||
|
||||
let attrs = match self.map_or_attrs {
|
||||
MapOrAttrs::Map(ref map) => self.generate_attributes(map),
|
||||
MapOrAttrs::Map(ref map) => self.difficulty.with_mode().calculate(map),
|
||||
MapOrAttrs::Attrs(attrs) => attrs,
|
||||
};
|
||||
|
||||
@@ -434,10 +433,6 @@ impl<'map> OsuPerformance<'map> {
|
||||
inner.calculate()
|
||||
}
|
||||
|
||||
fn generate_attributes(&self, map: &OsuBeatmap<'_>) -> OsuDifficultyAttributes {
|
||||
self.difficulty.calculate(map)
|
||||
}
|
||||
|
||||
/// Try to create [`OsuPerformance`] through a [`ModeAttributeProvider`].
|
||||
///
|
||||
/// If you already calculated the attributes for the current map-mod
|
||||
@@ -828,7 +823,7 @@ mod test {
|
||||
|
||||
use proptest::prelude::*;
|
||||
|
||||
use crate::Beatmap;
|
||||
use crate::{any::difficulty::converted::ConvertedDifficulty, Beatmap};
|
||||
|
||||
use super::*;
|
||||
|
||||
@@ -843,7 +838,7 @@ mod test {
|
||||
.unwrap()
|
||||
.unchecked_into_converted::<Osu>();
|
||||
|
||||
let attrs = ModeDifficulty::new().calculate(&converted);
|
||||
let attrs = ConvertedDifficulty::new().calculate(&converted);
|
||||
|
||||
assert_eq!(
|
||||
(attrs.n_circles, attrs.n_sliders, attrs.n_spinners),
|
||||
|
||||
+2
-2
@@ -1,4 +1,4 @@
|
||||
use crate::any::ModeDifficulty;
|
||||
use crate::Difficulty;
|
||||
|
||||
use super::{
|
||||
convert::OsuBeatmap,
|
||||
@@ -25,7 +25,7 @@ impl OsuStrains {
|
||||
pub const SECTION_LEN: f64 = 400.0;
|
||||
}
|
||||
|
||||
pub fn strains(difficulty: &ModeDifficulty, converted: &OsuBeatmap<'_>) -> OsuStrains {
|
||||
pub fn strains(difficulty: &Difficulty, converted: &OsuBeatmap<'_>) -> OsuStrains {
|
||||
let DifficultyValues {
|
||||
skills:
|
||||
OsuSkills {
|
||||
|
||||
@@ -4,7 +4,7 @@ use crate::{
|
||||
model::{beatmap::HitWindows, hit_object::HitObject},
|
||||
taiko::TaikoBeatmap,
|
||||
util::sync::RefCount,
|
||||
ModeDifficulty,
|
||||
Difficulty,
|
||||
};
|
||||
|
||||
use super::{
|
||||
@@ -25,14 +25,14 @@ use super::{
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// use rosu_pp::{Beatmap, ModeDifficulty};
|
||||
/// use rosu_pp::{Beatmap, Difficulty};
|
||||
/// use rosu_pp::taiko::{Taiko, TaikoGradualDifficulty};
|
||||
///
|
||||
/// let converted = Beatmap::from_path("./resources/1028484.osu")
|
||||
/// .unwrap()
|
||||
/// .unchecked_into_converted::<Taiko>();
|
||||
///
|
||||
/// let difficulty = ModeDifficulty::new().mods(64); // DT
|
||||
/// let difficulty = Difficulty::new().mods(64); // DT
|
||||
/// let mut iter = TaikoGradualDifficulty::new(&difficulty, &converted);
|
||||
///
|
||||
/// // the difficulty of the map after the first hit object
|
||||
@@ -69,7 +69,7 @@ enum FirstTwoCombos {
|
||||
|
||||
impl TaikoGradualDifficulty {
|
||||
/// Create a new difficulty attributes iterator for osu!taiko maps.
|
||||
pub fn new(difficulty: &ModeDifficulty, converted: &TaikoBeatmap<'_>) -> Self {
|
||||
pub fn new(difficulty: &Difficulty, converted: &TaikoBeatmap<'_>) -> Self {
|
||||
let take = difficulty.get_passed_objects();
|
||||
let mods = difficulty.get_mods();
|
||||
let clock_rate = difficulty.get_clock_rate();
|
||||
@@ -260,8 +260,7 @@ impl ExactSizeIterator for TaikoGradualDifficulty {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
|
||||
use crate::Beatmap;
|
||||
use crate::{any::difficulty::converted::ConvertedDifficulty, Beatmap};
|
||||
|
||||
use super::*;
|
||||
|
||||
@@ -269,7 +268,7 @@ mod tests {
|
||||
fn empty() {
|
||||
let converted = Beatmap::from_bytes(&[]).unwrap().unchecked_into_converted();
|
||||
|
||||
let difficulty = ModeDifficulty::new();
|
||||
let difficulty = Difficulty::new();
|
||||
let mut gradual = TaikoGradualDifficulty::new(&difficulty, &converted);
|
||||
|
||||
assert!(gradual.next().is_none());
|
||||
@@ -281,7 +280,7 @@ mod tests {
|
||||
.unwrap()
|
||||
.unchecked_into_converted();
|
||||
|
||||
let difficulty = ModeDifficulty::new();
|
||||
let difficulty = Difficulty::new();
|
||||
|
||||
let mut gradual = TaikoGradualDifficulty::new(&difficulty, &converted);
|
||||
let mut gradual_2nd = TaikoGradualDifficulty::new(&difficulty, &converted);
|
||||
@@ -313,7 +312,7 @@ mod tests {
|
||||
assert_eq!(next_gradual, next_gradual_3rd);
|
||||
}
|
||||
|
||||
let expected = ModeDifficulty::new()
|
||||
let expected = ConvertedDifficulty::new()
|
||||
.passed_objects(i as u32)
|
||||
.calculate(&converted);
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
use crate::{
|
||||
any::difficulty::mode::ModeDifficulty,
|
||||
taiko::{
|
||||
difficulty::{
|
||||
color::preprocessor::ColorDifficultyPreprocessor,
|
||||
@@ -8,6 +7,7 @@ use crate::{
|
||||
},
|
||||
object::TaikoObject,
|
||||
},
|
||||
Difficulty,
|
||||
};
|
||||
|
||||
use self::skills::peaks::Peaks;
|
||||
@@ -23,7 +23,7 @@ mod skills;
|
||||
const DIFFICULTY_MULTIPLIER: f64 = 1.35;
|
||||
|
||||
pub fn difficulty(
|
||||
difficulty: &ModeDifficulty,
|
||||
difficulty: &Difficulty,
|
||||
converted: &TaikoBeatmap<'_>,
|
||||
) -> TaikoDifficultyAttributes {
|
||||
let clock_rate = difficulty.get_clock_rate();
|
||||
@@ -74,7 +74,7 @@ pub struct DifficultyValues {
|
||||
}
|
||||
|
||||
impl DifficultyValues {
|
||||
pub fn calculate(difficulty: &ModeDifficulty, converted: &TaikoBeatmap<'_>) -> Self {
|
||||
pub fn calculate(difficulty: &Difficulty, converted: &TaikoBeatmap<'_>) -> Self {
|
||||
let take = difficulty.get_passed_objects();
|
||||
let clock_rate = difficulty.get_clock_rate();
|
||||
|
||||
|
||||
+5
-5
@@ -1,9 +1,9 @@
|
||||
use crate::{
|
||||
any::ModeDifficulty,
|
||||
model::{
|
||||
beatmap::Beatmap,
|
||||
mode::{ConvertStatus, IGameMode},
|
||||
},
|
||||
Difficulty,
|
||||
};
|
||||
|
||||
pub use self::{
|
||||
@@ -44,13 +44,13 @@ impl IGameMode for Taiko {
|
||||
}
|
||||
|
||||
fn difficulty(
|
||||
difficulty: &ModeDifficulty,
|
||||
difficulty: &Difficulty,
|
||||
converted: &TaikoBeatmap<'_>,
|
||||
) -> Self::DifficultyAttributes {
|
||||
difficulty::difficulty(difficulty, converted)
|
||||
}
|
||||
|
||||
fn strains(difficulty: &ModeDifficulty, converted: &TaikoBeatmap<'_>) -> Self::Strains {
|
||||
fn strains(difficulty: &Difficulty, converted: &TaikoBeatmap<'_>) -> Self::Strains {
|
||||
strains::strains(difficulty, converted)
|
||||
}
|
||||
|
||||
@@ -59,14 +59,14 @@ impl IGameMode for Taiko {
|
||||
}
|
||||
|
||||
fn gradual_difficulty(
|
||||
difficulty: &ModeDifficulty,
|
||||
difficulty: &Difficulty,
|
||||
map: &TaikoBeatmap<'_>,
|
||||
) -> Self::GradualDifficulty {
|
||||
TaikoGradualDifficulty::new(difficulty, map)
|
||||
}
|
||||
|
||||
fn gradual_performance(
|
||||
difficulty: &ModeDifficulty,
|
||||
difficulty: &Difficulty,
|
||||
map: &TaikoBeatmap<'_>,
|
||||
) -> Self::GradualPerformance {
|
||||
TaikoGradualPerformance::new(difficulty, map)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use crate::{
|
||||
taiko::{difficulty::gradual::TaikoGradualDifficulty, TaikoBeatmap, TaikoScoreState},
|
||||
ModeDifficulty,
|
||||
Difficulty,
|
||||
};
|
||||
|
||||
use super::TaikoPerformanceAttributes;
|
||||
@@ -20,14 +20,14 @@ use super::TaikoPerformanceAttributes;
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// use rosu_pp::{Beatmap, ModeDifficulty};
|
||||
/// use rosu_pp::{Beatmap, Difficulty};
|
||||
/// use rosu_pp::taiko::{Taiko, TaikoGradualPerformance, TaikoScoreState};
|
||||
///
|
||||
/// let converted = Beatmap::from_path("./resources/1028484.osu")
|
||||
/// .unwrap()
|
||||
/// .unchecked_into_converted::<Taiko>();
|
||||
///
|
||||
/// let difficulty = ModeDifficulty::new().mods(64); // DT
|
||||
/// let difficulty = Difficulty::new().mods(64); // DT
|
||||
/// let mut gradual = TaikoGradualPerformance::new(&difficulty, &converted);
|
||||
/// let mut state = TaikoScoreState::new(); // empty state, everything is on 0.
|
||||
///
|
||||
@@ -84,7 +84,7 @@ pub struct TaikoGradualPerformance {
|
||||
|
||||
impl TaikoGradualPerformance {
|
||||
/// Create a new gradual performance calculator for osu!taiko maps.
|
||||
pub fn new(difficulty: &ModeDifficulty, converted: &TaikoBeatmap<'_>) -> Self {
|
||||
pub fn new(difficulty: &Difficulty, converted: &TaikoBeatmap<'_>) -> Self {
|
||||
let difficulty = TaikoGradualDifficulty::new(difficulty, converted);
|
||||
|
||||
Self { difficulty }
|
||||
@@ -135,7 +135,7 @@ mod tests {
|
||||
.unchecked_into_converted();
|
||||
|
||||
let mods = 88; // HDHRDT
|
||||
let difficulty = ModeDifficulty::new().mods(88);
|
||||
let difficulty = Difficulty::new().mods(88);
|
||||
|
||||
let mut gradual = TaikoGradualPerformance::new(&difficulty, &converted);
|
||||
let mut gradual_2nd = TaikoGradualPerformance::new(&difficulty, &converted);
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
use std::cmp;
|
||||
|
||||
use crate::{
|
||||
any::ModeDifficulty,
|
||||
any::{HitResultPriority, ModeAttributeProvider},
|
||||
any::{Difficulty, HitResultPriority, ModeAttributeProvider},
|
||||
osu::OsuPerformance,
|
||||
util::{map_or_attrs::MapOrAttrs, mods::Mods},
|
||||
};
|
||||
@@ -21,7 +20,7 @@ pub mod gradual;
|
||||
#[must_use]
|
||||
pub struct TaikoPerformance<'map> {
|
||||
pub(crate) map_or_attrs: MapOrAttrs<'map, Taiko>,
|
||||
difficulty: ModeDifficulty,
|
||||
difficulty: Difficulty,
|
||||
combo: Option<u32>,
|
||||
acc: Option<f64>,
|
||||
hitresult_priority: HitResultPriority,
|
||||
@@ -35,7 +34,7 @@ impl<'map> TaikoPerformance<'map> {
|
||||
pub const fn new(map: TaikoBeatmap<'map>) -> Self {
|
||||
Self {
|
||||
map_or_attrs: MapOrAttrs::Map(map),
|
||||
difficulty: ModeDifficulty::new(),
|
||||
difficulty: Difficulty::new(),
|
||||
combo: None,
|
||||
acc: None,
|
||||
misses: None,
|
||||
@@ -48,7 +47,7 @@ impl<'map> TaikoPerformance<'map> {
|
||||
pub(crate) const fn from_taiko_attributes(attrs: TaikoDifficultyAttributes) -> Self {
|
||||
Self {
|
||||
map_or_attrs: MapOrAttrs::Attrs(attrs),
|
||||
difficulty: ModeDifficulty::new(),
|
||||
difficulty: Difficulty::new(),
|
||||
combo: None,
|
||||
acc: None,
|
||||
misses: None,
|
||||
@@ -167,7 +166,7 @@ impl<'map> TaikoPerformance<'map> {
|
||||
pub fn generate_state(&mut self) -> TaikoScoreState {
|
||||
let attrs = match self.map_or_attrs {
|
||||
MapOrAttrs::Map(ref map) => {
|
||||
let attrs = self.generate_attributes(map);
|
||||
let attrs = self.difficulty.with_mode().calculate(map);
|
||||
|
||||
self.map_or_attrs.insert_attrs(attrs)
|
||||
}
|
||||
@@ -255,7 +254,7 @@ impl<'map> TaikoPerformance<'map> {
|
||||
let state = self.generate_state();
|
||||
|
||||
let attrs = match self.map_or_attrs {
|
||||
MapOrAttrs::Map(ref map) => self.generate_attributes(map),
|
||||
MapOrAttrs::Map(ref map) => self.difficulty.with_mode().calculate(map),
|
||||
MapOrAttrs::Attrs(attrs) => attrs,
|
||||
};
|
||||
|
||||
@@ -268,10 +267,6 @@ impl<'map> TaikoPerformance<'map> {
|
||||
inner.calculate()
|
||||
}
|
||||
|
||||
fn generate_attributes(&self, map: &TaikoBeatmap<'_>) -> TaikoDifficultyAttributes {
|
||||
self.difficulty.calculate(map)
|
||||
}
|
||||
|
||||
/// Try to create [`TaikoPerformance`] through a [`ModeAttributeProvider`].
|
||||
///
|
||||
/// If you already calculated the attributes for the current map-mod
|
||||
@@ -506,7 +501,7 @@ mod test {
|
||||
|
||||
use proptest::prelude::*;
|
||||
|
||||
use crate::Beatmap;
|
||||
use crate::{any::difficulty::converted::ConvertedDifficulty, Beatmap};
|
||||
|
||||
use super::*;
|
||||
|
||||
@@ -521,7 +516,7 @@ mod test {
|
||||
.unwrap()
|
||||
.unchecked_into_converted::<Taiko>();
|
||||
|
||||
let attrs = ModeDifficulty::new().calculate(&converted);
|
||||
let attrs = ConvertedDifficulty::new().calculate(&converted);
|
||||
|
||||
assert_eq!(MAX_COMBO, attrs.max_combo);
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use crate::{any::ModeDifficulty, taiko::difficulty::DifficultyValues};
|
||||
use crate::{taiko::difficulty::DifficultyValues, Difficulty};
|
||||
|
||||
use super::convert::TaikoBeatmap;
|
||||
|
||||
@@ -20,7 +20,7 @@ impl TaikoStrains {
|
||||
pub const SECTION_LEN: f64 = 400.0;
|
||||
}
|
||||
|
||||
pub fn strains(difficulty: &ModeDifficulty, converted: &TaikoBeatmap<'_>) -> TaikoStrains {
|
||||
pub fn strains(difficulty: &Difficulty, converted: &TaikoBeatmap<'_>) -> TaikoStrains {
|
||||
let values = DifficultyValues::calculate(difficulty, converted);
|
||||
|
||||
TaikoStrains {
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
use std::{
|
||||
any,
|
||||
fmt::{Debug, Formatter, Result as FmtResult},
|
||||
marker::PhantomData,
|
||||
};
|
||||
|
||||
pub struct GenericFormatter<T>(PhantomData<T>);
|
||||
|
||||
impl<T> GenericFormatter<T> {
|
||||
pub const fn new() -> Self {
|
||||
Self(PhantomData)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Debug for GenericFormatter<T> {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
|
||||
fn fmt_stripped(full_type_name: &str, f: &mut Formatter<'_>) -> FmtResult {
|
||||
// Strip fully qualified syntax
|
||||
if let Some(position) = full_type_name.rfind("::") {
|
||||
if let Some(type_name) = full_type_name.get(position + 2..) {
|
||||
f.write_str(type_name)?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fmt_stripped(any::type_name::<T>(), f)
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
pub mod float_ext;
|
||||
pub mod generic_fmt;
|
||||
pub mod limited_queue;
|
||||
pub mod map_or_attrs;
|
||||
pub mod mods;
|
||||
|
||||
+4
-4
@@ -133,10 +133,10 @@ impl<T: fmt::Debug> fmt::Debug for Weak<T> {
|
||||
}
|
||||
|
||||
/// ```compile_fail
|
||||
/// use rosu_pp::{taiko::TaikoGradualDifficulty, Beatmap, ModeDifficulty};
|
||||
/// use rosu_pp::{taiko::TaikoGradualDifficulty, Beatmap, Difficulty};
|
||||
///
|
||||
/// let converted = Beatmap::from_bytes(&[]).unwrap().unchecked_into_converted();
|
||||
/// let difficulty = ModeDifficulty::new();
|
||||
/// let difficulty = Difficulty::new();
|
||||
/// let mut gradual = TaikoGradualDifficulty::new(&difficulty, &converted);
|
||||
///
|
||||
/// // Rc<RefCell<_>> cannot be shared across threads so compilation should fail
|
||||
@@ -149,10 +149,10 @@ const fn _share_gradual_taiko() {}
|
||||
mod tests {
|
||||
#[test]
|
||||
fn share_gradual_taiko() {
|
||||
use crate::{taiko::TaikoGradualDifficulty, Beatmap, ModeDifficulty};
|
||||
use crate::{taiko::TaikoGradualDifficulty, Beatmap, Difficulty};
|
||||
|
||||
let converted = Beatmap::from_bytes(&[]).unwrap().unchecked_into_converted();
|
||||
let difficulty = ModeDifficulty::new();
|
||||
let difficulty = Difficulty::new();
|
||||
let mut gradual = TaikoGradualDifficulty::new(&difficulty, &converted);
|
||||
|
||||
// Arc<RwLock<_>> *can* be shared across threads so this should compile
|
||||
|
||||
+2
-2
@@ -5,7 +5,7 @@ use rosu_pp::{
|
||||
mania::{Mania, ManiaDifficultyAttributes},
|
||||
osu::{Osu, OsuDifficultyAttributes},
|
||||
taiko::{Taiko, TaikoDifficultyAttributes},
|
||||
Beatmap, ModeDifficulty,
|
||||
Beatmap, ConvertedDifficulty,
|
||||
};
|
||||
|
||||
use self::common::*;
|
||||
@@ -25,7 +25,7 @@ macro_rules! test_cases {
|
||||
$(
|
||||
let mods = 0 $( + $mods )*;
|
||||
let expected = test_cases!(@$mode { $( $key: $value, )* });
|
||||
let actual = ModeDifficulty::new().mods(mods).calculate(&map);
|
||||
let actual = ConvertedDifficulty::new().mods(mods).calculate(&map);
|
||||
run(&actual, &expected, mods);
|
||||
)*
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user