feat: added owned types for gradual calc of any mode
This commit is contained in:
@@ -94,7 +94,7 @@ let map = match Beatmap::from_path("/path/to/file.osu") {
|
|||||||
|
|
||||||
let mods = 8 + 64; // HDDT
|
let mods = 8 + 64; // HDDT
|
||||||
|
|
||||||
// If you're only interested in the star rating or other difficulty value,
|
// If you're only interested in the star rating or other difficulty values,
|
||||||
// use `GradualDifficulty`.
|
// use `GradualDifficulty`.
|
||||||
let gradual_difficulty = GradualDifficulty::new(&map, mods);
|
let gradual_difficulty = GradualDifficulty::new(&map, mods);
|
||||||
|
|
||||||
|
|||||||
+147
-16
@@ -1,5 +1,9 @@
|
|||||||
#![cfg(feature = "gradual")]
|
#![cfg(feature = "gradual")]
|
||||||
|
|
||||||
|
use crate::catch::{CatchOwnedGradualDifficulty, CatchOwnedGradualPerformance};
|
||||||
|
use crate::mania::{ManiaOwnedGradualDifficulty, ManiaOwnedGradualPerformance};
|
||||||
|
use crate::osu::OsuOwnedGradualPerformance;
|
||||||
|
use crate::taiko::TaikoOwnedGradualPerformance;
|
||||||
use crate::{
|
use crate::{
|
||||||
catch::{CatchGradualDifficulty, CatchGradualPerformance},
|
catch::{CatchGradualDifficulty, CatchGradualPerformance},
|
||||||
mania::{ManiaGradualDifficulty, ManiaGradualPerformance},
|
mania::{ManiaGradualDifficulty, ManiaGradualPerformance},
|
||||||
@@ -70,20 +74,86 @@ impl Iterator for GradualDifficulty<'_> {
|
|||||||
#[inline]
|
#[inline]
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
match self {
|
match self {
|
||||||
GradualDifficulty::Osu(o) => o.next().map(DifficultyAttributes::Osu),
|
Self::Osu(o) => o.next().map(DifficultyAttributes::Osu),
|
||||||
GradualDifficulty::Taiko(t) => t.next().map(DifficultyAttributes::Taiko),
|
Self::Taiko(t) => t.next().map(DifficultyAttributes::Taiko),
|
||||||
GradualDifficulty::Catch(f) => f.next().map(DifficultyAttributes::Catch),
|
Self::Catch(f) => f.next().map(DifficultyAttributes::Catch),
|
||||||
GradualDifficulty::Mania(m) => m.next().map(DifficultyAttributes::Mania),
|
Self::Mania(m) => m.next().map(DifficultyAttributes::Mania),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||||
match self {
|
match self {
|
||||||
GradualDifficulty::Osu(o) => o.size_hint(),
|
Self::Osu(o) => o.size_hint(),
|
||||||
GradualDifficulty::Taiko(t) => t.size_hint(),
|
Self::Taiko(t) => t.size_hint(),
|
||||||
GradualDifficulty::Catch(f) => f.size_hint(),
|
Self::Catch(f) => f.size_hint(),
|
||||||
GradualDifficulty::Mania(m) => m.size_hint(),
|
Self::Mania(m) => m.size_hint(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn nth(&mut self, n: usize) -> Option<Self::Item> {
|
||||||
|
match self {
|
||||||
|
Self::Osu(o) => o.nth(n).map(DifficultyAttributes::Osu),
|
||||||
|
Self::Taiko(t) => t.nth(n).map(DifficultyAttributes::Taiko),
|
||||||
|
Self::Catch(c) => c.nth(n).map(DifficultyAttributes::Catch),
|
||||||
|
Self::Mania(m) => m.nth(n).map(DifficultyAttributes::Mania),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Gradually calculate the difficulty attributes on maps of any mode.
|
||||||
|
///
|
||||||
|
/// Check [`GradualDifficulty`] for more information. This type does the same
|
||||||
|
/// but depending on the mode it might clone [`Beatmap`] to avoid being bound to a lifetime.
|
||||||
|
#[cfg_attr(docsrs, doc(cfg(feature = "gradual")))]
|
||||||
|
#[derive(Debug)]
|
||||||
|
#[allow(clippy::large_enum_variant)]
|
||||||
|
pub enum OwnedGradualDifficulty {
|
||||||
|
/// Gradual osu!standard difficulty attributes.
|
||||||
|
Osu(OsuGradualDifficulty),
|
||||||
|
/// Gradual osu!taiko difficulty attributes.
|
||||||
|
Taiko(TaikoGradualDifficulty),
|
||||||
|
/// Gradual osu!catch difficulty attributes.
|
||||||
|
Catch(CatchOwnedGradualDifficulty),
|
||||||
|
/// Gradual osu!mania difficulty attributes.
|
||||||
|
Mania(ManiaOwnedGradualDifficulty),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl OwnedGradualDifficulty {
|
||||||
|
// FIXME: converted catch maps will always count as osu!std since their mode is not modified
|
||||||
|
/// Create a new gradual difficulty calculator for maps of any mode.
|
||||||
|
#[inline]
|
||||||
|
pub fn new(map: &Beatmap, mods: u32) -> Self {
|
||||||
|
match map.mode {
|
||||||
|
GameMode::Osu => Self::Osu(OsuGradualDifficulty::new(map, mods)),
|
||||||
|
GameMode::Taiko => Self::Taiko(TaikoGradualDifficulty::new(map, mods)),
|
||||||
|
GameMode::Catch => Self::Catch(CatchOwnedGradualDifficulty::new(map.to_owned(), mods)),
|
||||||
|
GameMode::Mania => Self::Mania(ManiaOwnedGradualDifficulty::new(map.to_owned(), mods)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Iterator for OwnedGradualDifficulty {
|
||||||
|
type Item = DifficultyAttributes;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
|
match self {
|
||||||
|
Self::Osu(o) => o.next().map(DifficultyAttributes::Osu),
|
||||||
|
Self::Taiko(t) => t.next().map(DifficultyAttributes::Taiko),
|
||||||
|
Self::Catch(f) => f.next().map(DifficultyAttributes::Catch),
|
||||||
|
Self::Mania(m) => m.next().map(DifficultyAttributes::Mania),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||||
|
match self {
|
||||||
|
Self::Osu(o) => o.size_hint(),
|
||||||
|
Self::Taiko(t) => t.size_hint(),
|
||||||
|
Self::Catch(f) => f.size_hint(),
|
||||||
|
Self::Mania(m) => m.size_hint(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -180,13 +250,13 @@ impl Iterator for GradualDifficulty<'_> {
|
|||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
#[allow(clippy::large_enum_variant)]
|
#[allow(clippy::large_enum_variant)]
|
||||||
pub enum GradualPerformance<'map> {
|
pub enum GradualPerformance<'map> {
|
||||||
/// Gradual osu!standard performance attributes.
|
/// Gradual osu!standard performance calculator.
|
||||||
Osu(OsuGradualPerformance<'map>),
|
Osu(OsuGradualPerformance<'map>),
|
||||||
/// Gradual osu!taiko performance attributes.
|
/// Gradual osu!taiko performance calculator.
|
||||||
Taiko(TaikoGradualPerformance<'map>),
|
Taiko(TaikoGradualPerformance<'map>),
|
||||||
/// Gradual osu!catch performance attributes.
|
/// Gradual osu!catch performance calculator.
|
||||||
Catch(CatchGradualPerformance<'map>),
|
Catch(CatchGradualPerformance<'map>),
|
||||||
/// Gradual osu!mania performance attributes.
|
/// Gradual osu!mania performance calculator.
|
||||||
Mania(ManiaGradualPerformance<'map>),
|
Mania(ManiaGradualPerformance<'map>),
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -211,6 +281,7 @@ impl<'map> GradualPerformance<'map> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Process all remaining hit objects and calculate the final performance attributes.
|
/// Process all remaining hit objects and calculate the final performance attributes.
|
||||||
|
#[inline]
|
||||||
pub fn last(&mut self, state: ScoreState) -> Option<PerformanceAttributes> {
|
pub fn last(&mut self, state: ScoreState) -> Option<PerformanceAttributes> {
|
||||||
self.nth(state, usize::MAX)
|
self.nth(state, usize::MAX)
|
||||||
}
|
}
|
||||||
@@ -223,10 +294,70 @@ impl<'map> GradualPerformance<'map> {
|
|||||||
#[inline]
|
#[inline]
|
||||||
pub fn nth(&mut self, state: ScoreState, n: usize) -> Option<PerformanceAttributes> {
|
pub fn nth(&mut self, state: ScoreState, n: usize) -> Option<PerformanceAttributes> {
|
||||||
match self {
|
match self {
|
||||||
GradualPerformance::Osu(o) => o.nth(state.into(), n).map(From::from),
|
Self::Osu(o) => o.nth(state.into(), n).map(PerformanceAttributes::Osu),
|
||||||
GradualPerformance::Taiko(t) => t.nth(state.into(), n).map(From::from),
|
Self::Taiko(t) => t.nth(state.into(), n).map(PerformanceAttributes::Taiko),
|
||||||
GradualPerformance::Catch(f) => f.nth(state.into(), n).map(From::from),
|
Self::Catch(f) => f.nth(state.into(), n).map(PerformanceAttributes::Catch),
|
||||||
GradualPerformance::Mania(m) => m.nth(state.into(), n).map(From::from),
|
Self::Mania(m) => m.nth(state.into(), n).map(PerformanceAttributes::Mania),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Gradually calculate the performance attributes on maps of any mode.
|
||||||
|
///
|
||||||
|
/// Check [`GradualPerformance`] for more information. This type does the same
|
||||||
|
/// but takes ownership of [`Beatmap`] to avoid being bound to a lifetime.
|
||||||
|
#[cfg_attr(docsrs, doc(cfg(feature = "gradual")))]
|
||||||
|
#[derive(Debug)]
|
||||||
|
#[allow(clippy::large_enum_variant)]
|
||||||
|
pub enum OwnedGradualPerformance {
|
||||||
|
/// Gradual osu!standard performance calculator.
|
||||||
|
Osu(OsuOwnedGradualPerformance),
|
||||||
|
/// Gradual osu!taiko performance calculator.
|
||||||
|
Taiko(TaikoOwnedGradualPerformance),
|
||||||
|
/// Gradual osu!catch performance calculator.
|
||||||
|
Catch(CatchOwnedGradualPerformance),
|
||||||
|
/// Gradual osu!mania performance calculator.
|
||||||
|
Mania(ManiaOwnedGradualPerformance),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl OwnedGradualPerformance {
|
||||||
|
// FIXME: converted catch maps will always count as osu!std since their mode is not modified
|
||||||
|
/// Create a new gradual performance calculator for maps of any mode.
|
||||||
|
#[inline]
|
||||||
|
pub fn new(map: Beatmap, mods: u32) -> Self {
|
||||||
|
match map.mode {
|
||||||
|
GameMode::Osu => Self::Osu(OsuOwnedGradualPerformance::new(map, mods)),
|
||||||
|
GameMode::Taiko => Self::Taiko(TaikoOwnedGradualPerformance::new(map, mods)),
|
||||||
|
GameMode::Catch => Self::Catch(CatchOwnedGradualPerformance::new(map, mods)),
|
||||||
|
GameMode::Mania => Self::Mania(ManiaOwnedGradualPerformance::new(map, mods)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Process the next hit object and calculate the
|
||||||
|
/// performance attributes for the resulting score.
|
||||||
|
#[inline]
|
||||||
|
pub fn next(&mut self, state: ScoreState) -> Option<PerformanceAttributes> {
|
||||||
|
self.nth(state, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Process all remaining hit objects and calculate the final performance attributes.
|
||||||
|
#[inline]
|
||||||
|
pub fn last(&mut self, state: ScoreState) -> Option<PerformanceAttributes> {
|
||||||
|
self.nth(state, usize::MAX)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Process everything up the the next `n`th hit object and calculate the performance
|
||||||
|
/// attributes for the resulting score state.
|
||||||
|
///
|
||||||
|
/// Note that the count is zero-indexed, so `n=0` will process 1 object, `n=1` will process 2,
|
||||||
|
/// and so on.
|
||||||
|
#[inline]
|
||||||
|
pub fn nth(&mut self, state: ScoreState, n: usize) -> Option<PerformanceAttributes> {
|
||||||
|
match self {
|
||||||
|
Self::Osu(o) => o.nth(state.into(), n).map(PerformanceAttributes::Osu),
|
||||||
|
Self::Taiko(t) => t.nth(state.into(), n).map(PerformanceAttributes::Taiko),
|
||||||
|
Self::Catch(f) => f.nth(state.into(), n).map(PerformanceAttributes::Catch),
|
||||||
|
Self::Mania(m) => m.nth(state.into(), n).map(PerformanceAttributes::Mania),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+9
-4
@@ -86,7 +86,9 @@
|
|||||||
//! println!("PP: {}", result.pp());
|
//! println!("PP: {}", result.pp());
|
||||||
//! ```
|
//! ```
|
||||||
//!
|
//!
|
||||||
#![cfg_attr(feature = "gradual", doc = r#"
|
#![cfg_attr(
|
||||||
|
feature = "gradual",
|
||||||
|
doc = r#"
|
||||||
## Gradual calculation
|
## Gradual calculation
|
||||||
Sometimes you might want to calculate the difficulty of a map or performance of a score after each hit object.
|
Sometimes you might want to calculate the difficulty of a map or performance of a score after each hit object.
|
||||||
This could be done by using `passed_objects` as the amount of objects that were passed so far.
|
This could be done by using `passed_objects` as the amount of objects that were passed so far.
|
||||||
@@ -110,7 +112,7 @@
|
|||||||
|
|
||||||
let mods = 8 + 64; // HDDT
|
let mods = 8 + 64; // HDDT
|
||||||
|
|
||||||
// If you're only interested in the star rating or other difficulty value,
|
// If you're only interested in the star rating or other difficulty values,
|
||||||
// use `GradualDifficulty`.
|
// use `GradualDifficulty`.
|
||||||
let gradual_difficulty = GradualDifficulty::new(&map, mods);
|
let gradual_difficulty = GradualDifficulty::new(&map, mods);
|
||||||
|
|
||||||
@@ -171,7 +173,8 @@
|
|||||||
println!("PP after the first 11 objects: {}", curr_performance.pp());
|
println!("PP after the first 11 objects: {}", curr_performance.pp());
|
||||||
```
|
```
|
||||||
|
|
||||||
"#)]
|
"#
|
||||||
|
)]
|
||||||
//! ## Features
|
//! ## Features
|
||||||
//!
|
//!
|
||||||
//! | Flag | Description |
|
//! | Flag | Description |
|
||||||
@@ -204,7 +207,9 @@ pub use beatmap::{Beatmap, BeatmapExt, GameMode};
|
|||||||
#[cfg(feature = "gradual")]
|
#[cfg(feature = "gradual")]
|
||||||
mod gradual;
|
mod gradual;
|
||||||
#[cfg(feature = "gradual")]
|
#[cfg(feature = "gradual")]
|
||||||
pub use gradual::{GradualDifficulty, GradualPerformance};
|
pub use gradual::{
|
||||||
|
GradualDifficulty, GradualPerformance, OwnedGradualDifficulty, OwnedGradualPerformance,
|
||||||
|
};
|
||||||
|
|
||||||
mod pp;
|
mod pp;
|
||||||
pub use pp::{AnyPP, AttributeProvider, HitResultPriority};
|
pub use pp::{AnyPP, AttributeProvider, HitResultPriority};
|
||||||
|
|||||||
Reference in New Issue
Block a user