use the same StarResult type for all modes

This commit is contained in:
MaxOhn
2021-01-18 12:55:46 +01:00
parent aae601a91e
commit 44538a7022
11 changed files with 170 additions and 120 deletions
+17 -8
View File
@@ -1,5 +1,5 @@
use super::DifficultyAttributes;
use crate::{Beatmap, Mods, PpResult};
use crate::{Beatmap, Mods, PpResult, StarResult};
pub trait OsuAttributeProvider {
fn attributes(self) -> Option<DifficultyAttributes>;
@@ -11,9 +11,9 @@ impl OsuAttributeProvider for DifficultyAttributes {
}
}
impl OsuAttributeProvider for PpResult {
impl OsuAttributeProvider for StarResult {
fn attributes(self) -> Option<DifficultyAttributes> {
if let PpResult::Osu { attributes, .. } = self {
if let Self::Osu { attributes } = self {
Some(attributes)
} else {
None
@@ -21,6 +21,12 @@ impl OsuAttributeProvider for PpResult {
}
}
impl OsuAttributeProvider for PpResult {
fn attributes(self) -> Option<DifficultyAttributes> {
self.attributes.attributes()
}
}
/// Calculator for pp on osu!standard maps.
pub struct OsuPP<'m> {
map: &'m Beatmap,
@@ -170,10 +176,12 @@ impl<'m> OsuPP<'m> {
/// The default is suggested to be [`stars`](crate::osu::no_leniency::stars).
pub fn calculate(
mut self,
stars_func: impl FnOnce(&Beatmap, u32, Option<usize>) -> DifficultyAttributes,
stars_func: impl FnOnce(&Beatmap, u32, Option<usize>) -> StarResult,
) -> PpResult {
if self.attributes.is_none() {
let attributes = stars_func(self.map, self.mods, self.passed_objects);
let attributes = stars_func(self.map, self.mods, self.passed_objects)
.attributes()
.unwrap();
self.attributes.replace(attributes);
}
@@ -227,10 +235,11 @@ impl<'m> OsuPP<'m> {
.powf(1.0 / 1.1)
* multiplier;
PpResult::Osu {
pp,
let attributes = StarResult::Osu {
attributes: self.attributes.unwrap(),
}
};
PpResult { pp, attributes }
}
fn compute_aim_value(&self, total_hits: f32) -> f32 {
+12 -12
View File
@@ -11,7 +11,7 @@ use skill::Skill;
use skill_kind::SkillKind;
use super::super::DifficultyAttributes;
use crate::{Beatmap, Mods};
use crate::{Beatmap, Mods, StarResult};
const SECTION_LEN: f32 = 400.0;
const DIFFICULTY_MULTIPLIER: f32 = 0.0675;
@@ -19,11 +19,7 @@ const DIFFICULTY_MULTIPLIER: f32 = 0.0675;
/// Star calculation for osu!standard maps
///
/// In case of a partial play, e.g. a fail, one can specify the amount of passed objects.
pub fn stars(
map: &Beatmap,
mods: impl Mods,
passed_objects: Option<usize>,
) -> DifficultyAttributes {
pub fn stars(map: &Beatmap, mods: impl Mods, passed_objects: Option<usize>) -> StarResult {
let take = passed_objects.unwrap_or_else(|| map.hit_objects.len());
let attributes = map.attributes().mods(mods);
@@ -31,10 +27,12 @@ pub fn stars(
let od = (80.0 - hitwindow) / 6.0;
if take < 2 {
return DifficultyAttributes {
ar: attributes.ar,
od,
..Default::default()
return StarResult::Osu {
attributes: DifficultyAttributes {
ar: attributes.ar,
od,
..Default::default()
},
};
}
@@ -118,7 +116,7 @@ pub fn stars(
let stars = aim_rating + speed_rating + (aim_rating - speed_rating).abs() / 2.0;
DifficultyAttributes {
let attributes = DifficultyAttributes {
stars,
ar: attributes.ar,
od,
@@ -127,7 +125,9 @@ pub fn stars(
max_combo: 0, // TODO
n_circles: 0, // TODO
n_spinners: 0, // TODO
}
};
StarResult::Osu { attributes }
}
#[cfg(test)]
+8 -8
View File
@@ -17,7 +17,7 @@ use skill::Skill;
use skill_kind::SkillKind;
use slider_state::SliderState;
use crate::{Beatmap, Mods};
use crate::{Beatmap, Mods, StarResult};
const OBJECT_RADIUS: f32 = 64.0;
const SECTION_LEN: f32 = 400.0;
@@ -33,11 +33,7 @@ const NORMALIZED_RADIUS: f32 = 52.0;
/// processing stack leniency is relatively expensive.
///
/// In case of a partial play, e.g. a fail, one can specify the amount of passed objects.
pub fn stars(
map: &Beatmap,
mods: impl Mods,
passed_objects: Option<usize>,
) -> DifficultyAttributes {
pub fn stars(map: &Beatmap, mods: impl Mods, passed_objects: Option<usize>) -> StarResult {
let take = passed_objects.unwrap_or_else(|| map.hit_objects.len());
let map_attributes = map.attributes().mods(mods);
@@ -51,7 +47,9 @@ pub fn stars(
};
if take < 2 {
return diff_attributes;
return StarResult::Osu {
attributes: diff_attributes,
};
}
let section_len = SECTION_LEN * map_attributes.clock_rate;
@@ -150,7 +148,9 @@ pub fn stars(
diff_attributes.speed_strain = speed_strain;
diff_attributes.aim_strain = aim_strain;
diff_attributes
StarResult::Osu {
attributes: diff_attributes,
}
}
#[cfg(test)]
+19 -19
View File
@@ -15,7 +15,7 @@ use skill::Skill;
use skill_kind::SkillKind;
use slider_state::SliderState;
use crate::{Beatmap, HitObject, HitObjectKind, Mods};
use crate::{Beatmap, HitObject, HitObjectKind, Mods, StarResult};
use std::borrow::Cow;
@@ -31,11 +31,7 @@ const NORMALIZED_RADIUS: f32 = 52.0;
/// However, this is the most efficient one.
///
/// In case of a partial play, e.g. a fail, one can specify the amount of passed objects.
pub fn stars(
map: &Beatmap,
mods: impl Mods,
passed_objects: Option<usize>,
) -> DifficultyAttributes {
pub fn stars(map: &Beatmap, mods: impl Mods, passed_objects: Option<usize>) -> StarResult {
let take = passed_objects.unwrap_or_else(|| map.hit_objects.len());
let attributes = map.attributes().mods(mods);
@@ -43,10 +39,12 @@ pub fn stars(
let od = (80.0 - hitwindow) / 6.0;
if take < 2 {
return DifficultyAttributes {
ar: attributes.ar,
od,
..Default::default()
return StarResult::Osu {
attributes: DifficultyAttributes {
ar: attributes.ar,
od,
..Default::default()
},
};
}
@@ -165,15 +163,17 @@ pub fn stars(
let stars = aim_strain + speed_strain + (aim_strain - speed_strain).abs() / 2.0;
DifficultyAttributes {
stars,
ar: attributes.ar,
od,
speed_strain,
aim_strain,
max_combo,
n_circles,
n_spinners,
StarResult::Osu {
attributes: DifficultyAttributes {
stars,
ar: attributes.ar,
od,
speed_strain,
aim_strain,
max_combo,
n_circles,
n_spinners,
},
}
}