rosu-pp
A standalone crate to calculate star ratings and performance points for all osu! gamemodes.
Async is supported through features, see below.
Usage
use ;
// Parse the map yourself
let map = match from_path ;
// If `BeatmapExt` is included, you can make use of
// some methods on `Beatmap` to make your life simpler.
let result = map.pp
.mods // HDHR
.combo
.misses
.accuracy // should be called last
.calculate;
println!;
// If you intend to reuse the current map-mod combination,
// make use of the previous result!
// If attributes are given, then stars & co don't have to be recalculated.
let next_result = map.pp
.mods // HDHR
.attributes // recycle
.combo
.misses
.n50
.accuracy
.calculate;
println!;
let stars = map.stars
.mods // HR
.calculate
.stars;
let max_pp = map.max_pp.pp;
println!;
With async
If either the async_tokio or async_std feature is enabled, beatmap parsing will be async.
use ;
// Parse the map asynchronously
let map = match from_path.await ;
// The rest stays the same
let result = map.pp
.mods // HDHR
.combo
.misses
.accuracy
.calculate;
println!;
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:
use ;
let map = match from_path ;
let mods = 8 + 64; // HDDT
// If you're only interested in the star rating or other difficulty value,
// use `GradualDifficultyAttributes`, either through its function `new`
// or through the method `BeatmapExt::gradual_difficulty`.
let gradual_difficulty = map.gradual_difficulty;
// Since `GradualDifficultyAttributes` implements `Iterator`, you can use
// any iterate function on it, use it in loops, collect them into a `Vec`, ...
for in gradual_difficulty.enumerate
// 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;
// The default score state is kinda chunky because it considers all modes.
let state = ScoreState ;
// Process the score state after the first object
let curr_performance = match gradual_performance.process_next_object ;
println!;
// 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 ;
// A little simpler than the general score state.
let state = TaikoScoreState ;
// Process the next 10 objects in one go
let curr_performance = match gradual_performance.process_next_n_objects ;
println!;
Features
| Flag | Description |
|---|---|
default |
Beatmap parsing will be non-async |
async_tokio |
Beatmap parsing will be async through tokio |
async_std |
Beatmap parsing will be async through async-std |
Accuracy
Here are some plots showing the differences of rosu-pp's values and osu!'s official osu-tools.
Note that osu-tools was used on this commit which is currently (2021-11-14) accurate for osu!standard but for other modes it might include changes that were not applied into stable and thus not implemented in rosu-pp.
osu!standard: (very accurate, flashlight has the highest average but is still very small)
osu!mania: (close to perfect values)
osu!catch: (pretty accurate)
osu!taiko: (decently accurate, potentially more imprecise due to non-live changes in osu-tools)
Bindings
Using rosu-pp from other languages than Rust:
- JavaScript: rosu-pp-js
- Python: rosu-pp-py