use the same StarResult type for all modes
This commit is contained in:
+17
-8
@@ -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 {
|
||||
|
||||
@@ -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)]
|
||||
|
||||
@@ -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)]
|
||||
|
||||
@@ -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,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user