added example for gradual calculation to readme

This commit is contained in:
MaxOhn
2021-11-25 00:57:39 +01:00
parent 334a1ab891
commit a2efcc5e8b
4 changed files with 165 additions and 2 deletions
+81
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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 |