added example for gradual calculation to readme
This commit is contained in:
@@ -73,6 +73,87 @@ let result = map.pp()
|
||||
println!("PP: {}", result.pp());
|
||||
```
|
||||
|
||||
### Gradual calculation
|
||||
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.
|
||||
However, this requires to recalculate the beginning again and again, we can be more efficient than that.
|
||||
|
||||
Instead, you should use `GradualDifficultyAttributes` and `GradualPerformanceAttributes`:
|
||||
|
||||
```rust
|
||||
use rosu_pp::{
|
||||
Beatmap, BeatmapExt, GradualPerformanceAttributes, ScoreState, taiko::TaikoScoreState,
|
||||
};
|
||||
|
||||
let map = match Beatmap::from_path("/path/to/file.osu") {
|
||||
Ok(map) => map,
|
||||
Err(why) => panic!("Error while parsing map: {}", why),
|
||||
};
|
||||
|
||||
let mods = 8 + 64; // HDDT
|
||||
|
||||
// If you're only interested in the star rating or other difficulty value,
|
||||
// use `GradualDifficultyAttribtes`, either through its function `new`
|
||||
// or through the method `BeatmapExt::gradual_difficulty`.
|
||||
let gradual_difficulty = map.gradual_difficulty(mods);
|
||||
|
||||
// Since `GradualDifficultyAttributes` implements `Iterator`, you can use
|
||||
// any iterate function on it, use it in loops, collect them into a `Vec`, ...
|
||||
for (i, difficulty) in gradual_difficulty.enumerate() {
|
||||
println!("Stars after object {}: {}", i, difficulty.stars());
|
||||
}
|
||||
|
||||
// Gradually calculating performance values does the same as calculating
|
||||
// difficulty attributes but it goes the extra step and also evaluates
|
||||
// the state of a score for these difficulty attributes.
|
||||
let mut gradual_performance = map.gradual_performance(mods);
|
||||
|
||||
// The default score state is kinda chunky because it considers all modes.
|
||||
let state = ScoreState {
|
||||
max_combo: 1,
|
||||
n_katu: 0, // only relevant for ctb
|
||||
n300: 1,
|
||||
n100: 0,
|
||||
n50: 0,
|
||||
misses: 0,
|
||||
score: 300, // only relevant for mania
|
||||
};
|
||||
|
||||
// Process the score state after the first object
|
||||
let curr_performance = match gradual_performance.process_next_object(state) {
|
||||
Some(perf) => perf,
|
||||
None => panic!("the map has no hit objects"),
|
||||
};
|
||||
|
||||
println!("PP after the first object: {}", curr_performance.pp());
|
||||
|
||||
// If you're only interested in maps of a specific mode, consider
|
||||
// using the mode's gradual calculator instead of the general one.
|
||||
// Let's assume it's a taiko map.
|
||||
// Instead of starting off with `BeatmapExt::gradual_performance` one could have
|
||||
// created the struct via `TaikoGradualPerformanceAttributes::new`.
|
||||
let mut gradual_performance = match gradual_performance {
|
||||
GradualPerformanceAttributes::Taiko(gradual) => gradual,
|
||||
_ => panic!("the map was not taiko but {:?}", map.mode),
|
||||
};
|
||||
|
||||
// A little simpler than the general score state.
|
||||
let state = TaikoScoreState {
|
||||
max_combo: 11,
|
||||
n300: 9,
|
||||
n100: 1,
|
||||
misses: 1,
|
||||
};
|
||||
|
||||
// Process the next 10 objects in one go
|
||||
let curr_performance = match gradual_performance.process_next_n_objects(state, 10) {
|
||||
Some(perf) => perf,
|
||||
None => panic!("the last `process_next_object` already processed the last object"),
|
||||
};
|
||||
|
||||
println!("PP after the first 11 objects: {}", curr_performance.pp());
|
||||
```
|
||||
|
||||
### Features
|
||||
|
||||
| Flag | Description |
|
||||
|
||||
+1
-1
@@ -139,7 +139,7 @@ impl<'map> FruitsPP<'map> {
|
||||
///
|
||||
/// If you want to calculate the performance after every few objects, instead of
|
||||
/// using [`FruitsPP`] multiple times with different `passed_objects`, you should use
|
||||
/// [`FruitsGradualPerformanceAttributes`](crate::fuits::FruitsGradualPerformanceAttributes).
|
||||
/// [`FruitsGradualPerformanceAttributes`](crate::fruits::FruitsGradualPerformanceAttributes).
|
||||
#[inline]
|
||||
pub fn passed_objects(mut self, passed_objects: usize) -> Self {
|
||||
self.passed_objects.replace(passed_objects);
|
||||
|
||||
+1
-1
@@ -112,7 +112,7 @@ impl Iterator for GradualDifficultyAttributes<'_> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Aggregation for a score's current state i.e. what wa
|
||||
/// Aggregation for a score's current state i.e. what is
|
||||
/// the maximum combo so far, what are the current
|
||||
/// hitresults and what is the current score.
|
||||
///
|
||||
|
||||
+82
@@ -73,6 +73,88 @@
|
||||
//! println!("PP: {}", result.pp());
|
||||
//! ```
|
||||
//!
|
||||
//! ## Gradual calculation
|
||||
//! 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.
|
||||
//! However, this requires to recalculate the beginning again and again, we can be more efficient than that.
|
||||
//!
|
||||
//! Instead, you should use `GradualDifficultyAttributes` and `GradualPerformanceAttributes`:
|
||||
//!
|
||||
//! ```no_run
|
||||
//! use rosu_pp::{
|
||||
//! Beatmap, BeatmapExt, GradualPerformanceAttributes, ScoreState,
|
||||
//! taiko::TaikoScoreState,
|
||||
//! };
|
||||
//!
|
||||
//! let map = match Beatmap::from_path("/path/to/file.osu") {
|
||||
//! Ok(map) => map,
|
||||
//! Err(why) => panic!("Error while parsing map: {}", why),
|
||||
//! };
|
||||
//!
|
||||
//! let mods = 8 + 64; // HDDT
|
||||
//!
|
||||
//! // If you're only interested in the star rating or other difficulty value,
|
||||
//! // use `GradualDifficultyAttribtes`, either through its function `new`
|
||||
//! // or through the method `BeatmapExt::gradual_difficulty`.
|
||||
//! let gradual_difficulty = map.gradual_difficulty(mods);
|
||||
//!
|
||||
//! // Since `GradualDifficultyAttributes` implements `Iterator`, you can use
|
||||
//! // any iterate function on it, use it in loops, collect them into a `Vec`, ...
|
||||
//! for (i, difficulty) in gradual_difficulty.enumerate() {
|
||||
//! println!("Stars after object {}: {}", i, difficulty.stars());
|
||||
//! }
|
||||
//!
|
||||
//! // Gradually calculating performance values does the same as calculating
|
||||
//! // difficulty attributes but it goes the extra step and also evaluates
|
||||
//! // the state of a score for these difficulty attributes.
|
||||
//! let mut gradual_performance = map.gradual_performance(mods);
|
||||
//!
|
||||
//! // The default score state is kinda chunky because it considers all modes.
|
||||
//! let state = ScoreState {
|
||||
//! max_combo: 1,
|
||||
//! n_katu: 0, // only relevant for ctb
|
||||
//! n300: 1,
|
||||
//! n100: 0,
|
||||
//! n50: 0,
|
||||
//! misses: 0,
|
||||
//! score: 300, // only relevant for mania
|
||||
//! };
|
||||
//!
|
||||
//! // Process the score state after the first object
|
||||
//! let curr_performance = match gradual_performance.process_next_object(state) {
|
||||
//! Some(perf) => perf,
|
||||
//! None => panic!("the map has no hit objects"),
|
||||
//! };
|
||||
//!
|
||||
//! println!("PP after the first object: {}", curr_performance.pp());
|
||||
//!
|
||||
//! // If you're only interested in maps of a specific mode, consider
|
||||
//! // using the mode's gradual calculator instead of the general one.
|
||||
//! // Let's assume it's a taiko map.
|
||||
//! // Instead of starting off with `BeatmapExt::gradual_performance` one could have
|
||||
//! // created the struct via `TaikoGradualPerformanceAttributes::new`.
|
||||
//! let mut gradual_performance = match gradual_performance {
|
||||
//! GradualPerformanceAttributes::Taiko(gradual) => gradual,
|
||||
//! _ => panic!("the map was not taiko but {:?}", map.mode),
|
||||
//! };
|
||||
//!
|
||||
//! // A little simpler than the general score state.
|
||||
//! let state = TaikoScoreState {
|
||||
//! max_combo: 11,
|
||||
//! n300: 9,
|
||||
//! n100: 1,
|
||||
//! misses: 1,
|
||||
//! };
|
||||
//!
|
||||
//! // Process the next 10 objects in one go
|
||||
//! let curr_performance = match gradual_performance.process_next_n_objects(state, 10) {
|
||||
//! Some(perf) => perf,
|
||||
//! None => panic!("the last `process_next_object` already processed the last object"),
|
||||
//! };
|
||||
//!
|
||||
//! println!("PP after the first 11 objects: {}", curr_performance.pp());
|
||||
//! ```
|
||||
//!
|
||||
//! ## Features
|
||||
//!
|
||||
//! | Flag | Description |
|
||||
|
||||
Reference in New Issue
Block a user