refactor: store either map or attrs in perf calc

This commit is contained in:
MaxOhn
2023-12-29 10:28:27 +01:00
parent 1213525246
commit 0adec507c1
7 changed files with 285 additions and 190 deletions
+63 -53
View File
@@ -2,7 +2,8 @@ use std::borrow::Cow;
use super::{ManiaDifficultyAttributes, ManiaPerformanceAttributes, ManiaScoreState, ManiaStars};
use crate::{
Beatmap, DifficultyAttributes, GameMode, HitResultPriority, Mods, OsuPP, PerformanceAttributes,
util::MapOrElse, Beatmap, DifficultyAttributes, GameMode, HitResultPriority, Mods, OsuPP,
PerformanceAttributes,
};
/// Performance calculator on osu!mania maps.
@@ -41,9 +42,8 @@ use crate::{
#[derive(Clone, Debug)]
#[allow(clippy::upper_case_acronyms)]
pub struct ManiaPP<'map> {
map: Cow<'map, Beatmap>,
map_or_attrs: MapOrElse<Cow<'map, Beatmap>, ManiaDifficultyAttributes>,
is_convert: bool,
attributes: Option<ManiaDifficultyAttributes>,
mods: u32,
passed_objects: Option<usize>,
clock_rate: Option<f64>,
@@ -67,8 +67,7 @@ impl<'map> ManiaPP<'map> {
Self {
is_convert: matches!(map, Cow::Owned(_)),
map,
attributes: None,
map_or_attrs: MapOrElse::Map(map),
mods: 0,
passed_objects: None,
clock_rate: None,
@@ -89,7 +88,7 @@ impl<'map> ManiaPP<'map> {
#[inline]
pub fn attributes(mut self, attrs: impl ManiaAttributeProvider) -> Self {
if let Some(attrs) = attrs.attributes() {
self.attributes = Some(attrs);
self.map_or_attrs = MapOrElse::Else(attrs);
}
self
@@ -227,8 +226,17 @@ impl<'map> ManiaPP<'map> {
}
/// Create the [`ManiaScoreState`] that will be used for performance calculation.
pub fn generate_state(&self) -> ManiaScoreState {
let n_objects = self.passed_objects.unwrap_or(self.map.hit_objects.len());
pub fn generate_state(&mut self) -> ManiaScoreState {
let attrs = match self.map_or_attrs {
MapOrElse::Map(ref map) => {
let attrs = self.generate_attributes(&map);
self.map_or_attrs.else_or_insert(attrs)
}
MapOrElse::Else(ref attrs) => attrs,
};
let n_objects = attrs.n_objects();
let priority = self.hitresult_priority.unwrap_or_default();
let n_misses = self.n_misses.map_or(0, |n| n.min(n_objects));
@@ -700,12 +708,13 @@ impl<'map> ManiaPP<'map> {
}
/// Calculate all performance related values, including pp and stars.
pub fn calculate(self) -> ManiaPerformanceAttributes {
pub fn calculate(mut self) -> ManiaPerformanceAttributes {
let state = self.generate_state();
let attrs = self
.attributes
.unwrap_or_else(|| self.generate_attributes());
let attrs = match self.map_or_attrs {
MapOrElse::Map(ref map) => self.generate_attributes(map),
MapOrElse::Else(attrs) => attrs,
};
let inner = ManiaPpInner {
mods: self.mods,
@@ -716,8 +725,8 @@ impl<'map> ManiaPP<'map> {
inner.calculate()
}
fn generate_attributes(&self) -> ManiaDifficultyAttributes {
let mut calculator = ManiaStars::new(self.map.as_ref())
fn generate_attributes(&self, map: &Beatmap) -> ManiaDifficultyAttributes {
let mut calculator = ManiaStars::new(map)
.mods(self.mods)
.is_convert(self.is_convert);
@@ -731,6 +740,46 @@ impl<'map> ManiaPP<'map> {
calculator.calculate()
}
/// TODO: docs
#[inline]
pub fn try_from_osu(osu: OsuPP<'map>) -> Option<Self> {
let OsuPP {
map_or_attrs,
mods,
acc,
combo: _,
n300,
n100,
n50,
n_misses,
passed_objects,
clock_rate,
hitresult_priority,
} = osu;
let MapOrElse::Map(map) = map_or_attrs else {
return None;
};
let map = map.into_inner().convert_mode(GameMode::Mania);
Some(Self {
is_convert: matches!(map, Cow::Owned(_)),
map_or_attrs: MapOrElse::Map(map),
mods,
passed_objects,
clock_rate,
n320: None,
n300,
n200: None,
n100,
n50,
n_misses,
acc,
hitresult_priority,
})
}
}
struct ManiaPpInner {
@@ -796,45 +845,6 @@ impl ManiaPpInner {
}
}
impl<'map> From<OsuPP<'map>> for ManiaPP<'map> {
#[inline]
fn from(osu: OsuPP<'map>) -> Self {
let OsuPP {
map,
attributes: _,
mods,
acc,
combo: _,
n300,
n100,
n50,
n_misses,
passed_objects,
clock_rate,
hitresult_priority,
} = osu;
let map = map.convert_mode(GameMode::Mania);
Self {
is_convert: matches!(map, Cow::Owned(_)),
map,
attributes: None,
mods,
passed_objects,
clock_rate,
n320: None,
n300,
n200: None,
n100,
n50,
n_misses,
acc,
hitresult_priority,
}
}
}
fn custom_accuracy(
n320: usize,
n300: usize,