rosu-pp
rosu-pp copied to clipboard
PP calculation from cached attributes not working in v0.10.0
Problem
I have been using rosu-pp to calculate scores in a project of mine, where I planned to calculate difficulty attributes once and reuse them constantly. This was working great up until v0.10.0.
pub fn get_pp(attr: DifficultyAttributes, score: CScore) -> f64 {
Beatmap::default()
.pp()
.attributes(attr)
.combo(score.combo)
.n300(score.n300)
.n100(score.n100)
.n50(score.n050)
.n_misses(score.misses)
.calculate()
.pp()
}
It always returns 0 now.
The only way to fix this is loading the beatmap file and calculating PP from there... It'd be great to have the option to calculate PP straight from the difficulty attributes again.
Difficulty
Difficulty was being calculated this way:
pub fn get_difficulty(bytes: &[u8], mods: u32, mode: GameMode) -> Result<DifficultyAttributes, String> {
let parse = Beatmap::from_bytes(bytes);
return match parse {
Ok(map) => Ok(map.stars().mods(mods).mode(mode).calculate()),
Err(why) => Err(why.to_string())
};
}
Workaround
Changing it so that the pp calculation is done on the beatmap itself works just fine, only problem is that can't really cache the attributes and discard the map for future PP calculations.
pub extern "C" fn GetPPFromMap(bytes: &[u8], mods: u32, mode: GameMode, score: CScore) -> f64 {
let parse = Beatmap::from_bytes(bytes);
return match parse {
Ok(map) => {
map.pp()
.mode(mode)
.mods(mods)
.combo(score.combo)
.n300(score.n300)
.n100(score.n100)
.n50(score.n050)
.n_misses(score.misses)
.calculate()
.pp()
}
Err(_) => { 0.0 }
};
}
p.s: Example code has been slightly adapted from the real thing, as seen here https://github.com/Minoxs/crosu-pp
Oh interesting, I've never considered calculating performance attributes only from difficulty attributes without the actual map, am kinda surprised it even worked 😄 It does definitely seem useful, will check on it.
After some quick checkup I noticed that
- in osu!standard performance calc the map is only needed for difficulty calc and the amount of hitobjects. The former is avoided by passing in difficulty attributes and the later is avoided by passing in
passed_objects
which should just be the sum of then_circles
,n_sliders
, andn_spinners
fields of the difficulty attributes. - in taiko and catch performance calc the map is only necessary for difficulty calc
- for mania it's the same as for osu!standard. However, mania difficulty attributes currently don't let you determine the amount of hitobjects so it's not possible without the actual map.
So your initial approach should be good to use again if you also specify the amount of passed objects by calculating it via the difficulty attributes, for osu!standard that is.
The use-case is appealing so even though hitobject count isn't strictly needed in mania difficulty attributes, adding it is probably justified so that the map is no longer necessary for mania performance calc, and thus not needed for any mode as long as attributes and passed objects are specified.
Will work on it 👍
Awesome! This will be super useful 😄
Finally finished the v1.0.0 release which properly supports performance calculation through either beatmap or attributes. 🎉
pub fn get_pp(attr: DifficultyAttributes, score: CScore) -> f64 {
rosu_pp::Performance::new(attr) // `new` method accepts both, attributes or a beatmap
.combo(score.combo)
.n300(score.n300)
.n100(score.n100)
.n50(score.n050)
.misses(score.misses) // `n_misses` -> `misses`
.calculate()
.pp()
}