rosu-pp icon indicating copy to clipboard operation
rosu-pp copied to clipboard

PP calculation from cached attributes not working in v0.10.0

Open Minoxs opened this issue 1 year ago • 4 comments

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

Minoxs avatar Dec 29 '23 03:12 Minoxs

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.

MaxOhn avatar Dec 29 '23 07:12 MaxOhn

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 the n_circles, n_sliders, and n_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 👍

MaxOhn avatar Dec 29 '23 07:12 MaxOhn

Awesome! This will be super useful 😄

Minoxs avatar Dec 29 '23 22:12 Minoxs

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()
}

MaxOhn avatar Apr 02 '24 10:04 MaxOhn