refactor: store either map or attrs in perf calc
This commit is contained in:
+59
-51
@@ -1,5 +1,8 @@
|
||||
use super::{CatchDifficultyAttributes, CatchPerformanceAttributes, CatchScoreState, CatchStars};
|
||||
use crate::{Beatmap, DifficultyAttributes, Mods, OsuPP, PerformanceAttributes};
|
||||
use crate::{
|
||||
util::{MapOrElse, MapRef},
|
||||
Beatmap, DifficultyAttributes, Mods, OsuPP, PerformanceAttributes,
|
||||
};
|
||||
use std::cmp::Ordering;
|
||||
|
||||
/// Performance calculator on osu!catch maps.
|
||||
@@ -34,8 +37,7 @@ use std::cmp::Ordering;
|
||||
#[derive(Clone, Debug)]
|
||||
#[allow(clippy::upper_case_acronyms)]
|
||||
pub struct CatchPP<'map> {
|
||||
pub(crate) map: &'map Beatmap,
|
||||
pub(crate) attributes: Option<CatchDifficultyAttributes>,
|
||||
pub(crate) map_or_attrs: MapOrElse<MapRef<'map>, CatchDifficultyAttributes>,
|
||||
pub(crate) mods: u32,
|
||||
pub(crate) acc: Option<f64>,
|
||||
pub(crate) combo: Option<usize>,
|
||||
@@ -54,8 +56,7 @@ impl<'map> CatchPP<'map> {
|
||||
#[inline]
|
||||
pub fn new(map: &'map Beatmap) -> Self {
|
||||
Self {
|
||||
map,
|
||||
attributes: None,
|
||||
map_or_attrs: MapOrElse::from(map),
|
||||
mods: 0,
|
||||
acc: None,
|
||||
combo: None,
|
||||
@@ -70,13 +71,15 @@ impl<'map> CatchPP<'map> {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: new_with_attributes function
|
||||
|
||||
/// Provide the result of a previous difficulty or performance calculation.
|
||||
/// If you already calculated the attributes for the current map-mod combination,
|
||||
/// be sure to put them in here so that they don't have to be recalculated.
|
||||
#[inline]
|
||||
pub fn attributes(mut self, attributes: impl CatchAttributeProvider) -> Self {
|
||||
if let Some(attributes) = attributes.attributes() {
|
||||
self.attributes = Some(attributes);
|
||||
if let Some(attrs) = attributes.attributes() {
|
||||
self.map_or_attrs = MapOrElse::Else(attrs);
|
||||
}
|
||||
|
||||
self
|
||||
@@ -195,9 +198,13 @@ impl<'map> CatchPP<'map> {
|
||||
|
||||
/// Create the [`CatchScoreState`] that will be used for performance calculation.
|
||||
pub fn generate_state(&mut self) -> CatchScoreState {
|
||||
let attrs = match self.attributes {
|
||||
Some(ref attrs) => attrs,
|
||||
None => self.attributes.insert(self.generate_attributes()),
|
||||
let attrs = match self.map_or_attrs {
|
||||
MapOrElse::Map(ref map) => {
|
||||
let attrs = self.generate_attributes(map.as_ref());
|
||||
|
||||
self.map_or_attrs.else_or_insert(attrs)
|
||||
}
|
||||
MapOrElse::Else(ref attrs) => attrs,
|
||||
};
|
||||
|
||||
let n_misses = self
|
||||
@@ -332,10 +339,10 @@ impl<'map> CatchPP<'map> {
|
||||
pub fn calculate(mut self) -> CatchPerformanceAttributes {
|
||||
let state = self.generate_state();
|
||||
|
||||
let attrs = self
|
||||
.attributes
|
||||
.take()
|
||||
.unwrap_or_else(|| self.generate_attributes());
|
||||
let attrs = match self.map_or_attrs {
|
||||
MapOrElse::Map(ref map) => self.generate_attributes(map.as_ref()),
|
||||
MapOrElse::Else(attrs) => attrs,
|
||||
};
|
||||
|
||||
let inner = CatchPPInner {
|
||||
attrs,
|
||||
@@ -346,8 +353,8 @@ impl<'map> CatchPP<'map> {
|
||||
inner.calculate()
|
||||
}
|
||||
|
||||
fn generate_attributes(&self) -> CatchDifficultyAttributes {
|
||||
let mut calculator = CatchStars::new(self.map).mods(self.mods);
|
||||
fn generate_attributes(&self, map: &Beatmap) -> CatchDifficultyAttributes {
|
||||
let mut calculator = CatchStars::new(map).mods(self.mods);
|
||||
|
||||
if let Some(passed_objects) = self.passed_objects {
|
||||
calculator = calculator.passed_objects(passed_objects);
|
||||
@@ -359,6 +366,42 @@ impl<'map> CatchPP<'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;
|
||||
};
|
||||
|
||||
Some(Self {
|
||||
map_or_attrs: MapOrElse::Map(map),
|
||||
mods,
|
||||
acc,
|
||||
combo,
|
||||
n_fruits: n300,
|
||||
n_droplets: n100,
|
||||
n_tiny_droplets: n50,
|
||||
n_tiny_droplet_misses: None,
|
||||
n_misses,
|
||||
passed_objects,
|
||||
clock_rate,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
struct CatchPPInner {
|
||||
@@ -442,41 +485,6 @@ impl CatchPPInner {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'map> From<OsuPP<'map>> for CatchPP<'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;
|
||||
|
||||
Self {
|
||||
map,
|
||||
attributes: None,
|
||||
mods,
|
||||
acc,
|
||||
combo,
|
||||
n_fruits: n300,
|
||||
n_droplets: n100,
|
||||
n_tiny_droplets: n50,
|
||||
n_tiny_droplet_misses: None,
|
||||
n_misses,
|
||||
passed_objects,
|
||||
clock_rate,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn accuracy(
|
||||
n_fruits: usize,
|
||||
n_droplets: usize,
|
||||
|
||||
Reference in New Issue
Block a user