refactor!: store lazer in Difficulty
This commit is contained in:
@@ -27,6 +27,11 @@ pub struct InspectDifficulty {
|
|||||||
///
|
///
|
||||||
/// Only relevant for osu!catch.
|
/// Only relevant for osu!catch.
|
||||||
pub hardrock_offsets: Option<bool>,
|
pub hardrock_offsets: Option<bool>,
|
||||||
|
/// Whether the calculated attributes belong to an osu!lazer or osu!stable
|
||||||
|
/// score.
|
||||||
|
///
|
||||||
|
/// Defaults to `true`.
|
||||||
|
pub lazer: Option<bool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl InspectDifficulty {
|
impl InspectDifficulty {
|
||||||
@@ -41,6 +46,7 @@ impl InspectDifficulty {
|
|||||||
hp,
|
hp,
|
||||||
od,
|
od,
|
||||||
hardrock_offsets,
|
hardrock_offsets,
|
||||||
|
lazer,
|
||||||
} = self;
|
} = self;
|
||||||
|
|
||||||
let mut difficulty = Difficulty::new().mods(mods);
|
let mut difficulty = Difficulty::new().mods(mods);
|
||||||
@@ -73,6 +79,10 @@ impl InspectDifficulty {
|
|||||||
difficulty = difficulty.hardrock_offsets(hardrock_offsets);
|
difficulty = difficulty.hardrock_offsets(hardrock_offsets);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(lazer) = lazer {
|
||||||
|
difficulty = difficulty.lazer(lazer);
|
||||||
|
}
|
||||||
|
|
||||||
difficulty
|
difficulty
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -62,6 +62,7 @@ pub struct Difficulty {
|
|||||||
hp: Option<ModsDependent>,
|
hp: Option<ModsDependent>,
|
||||||
od: Option<ModsDependent>,
|
od: Option<ModsDependent>,
|
||||||
hardrock_offsets: Option<bool>,
|
hardrock_offsets: Option<bool>,
|
||||||
|
lazer: Option<bool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Wrapper for beatmap attributes in [`Difficulty`].
|
/// Wrapper for beatmap attributes in [`Difficulty`].
|
||||||
@@ -97,6 +98,7 @@ impl Difficulty {
|
|||||||
hp: None,
|
hp: None,
|
||||||
od: None,
|
od: None,
|
||||||
hardrock_offsets: None,
|
hardrock_offsets: None,
|
||||||
|
lazer: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -120,6 +122,7 @@ impl Difficulty {
|
|||||||
hp,
|
hp,
|
||||||
od,
|
od,
|
||||||
hardrock_offsets,
|
hardrock_offsets,
|
||||||
|
lazer,
|
||||||
} = self;
|
} = self;
|
||||||
|
|
||||||
InspectDifficulty {
|
InspectDifficulty {
|
||||||
@@ -131,6 +134,7 @@ impl Difficulty {
|
|||||||
hp,
|
hp,
|
||||||
od,
|
od,
|
||||||
hardrock_offsets,
|
hardrock_offsets,
|
||||||
|
lazer,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -268,6 +272,18 @@ impl Difficulty {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Whether the calculated attributes belong to an osu!lazer or osu!stable
|
||||||
|
/// score.
|
||||||
|
///
|
||||||
|
/// Defaults to `true`.
|
||||||
|
///
|
||||||
|
/// Only relevant for osu!standard performance calculation.
|
||||||
|
pub const fn lazer(mut self, lazer: bool) -> Self {
|
||||||
|
self.lazer = Some(lazer);
|
||||||
|
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
/// Perform the difficulty calculation.
|
/// Perform the difficulty calculation.
|
||||||
pub fn calculate(&self, map: &Beatmap) -> DifficultyAttributes {
|
pub fn calculate(&self, map: &Beatmap) -> DifficultyAttributes {
|
||||||
let map = Cow::Borrowed(map);
|
let map = Cow::Borrowed(map);
|
||||||
@@ -347,6 +363,10 @@ impl Difficulty {
|
|||||||
self.hardrock_offsets
|
self.hardrock_offsets
|
||||||
.unwrap_or_else(|| self.mods.hardrock_offsets())
|
.unwrap_or_else(|| self.mods.hardrock_offsets())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn get_lazer(&self) -> bool {
|
||||||
|
self.lazer.unwrap_or(true)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn non_zero_u32_to_f32(n: NonZeroU32) -> f32 {
|
fn non_zero_u32_to_f32(n: NonZeroU32) -> f32 {
|
||||||
@@ -364,6 +384,7 @@ impl Debug for Difficulty {
|
|||||||
hp,
|
hp,
|
||||||
od,
|
od,
|
||||||
hardrock_offsets,
|
hardrock_offsets,
|
||||||
|
lazer,
|
||||||
} = self;
|
} = self;
|
||||||
|
|
||||||
f.debug_struct("Difficulty")
|
f.debug_struct("Difficulty")
|
||||||
@@ -375,6 +396,7 @@ impl Debug for Difficulty {
|
|||||||
.field("hp", hp)
|
.field("hp", hp)
|
||||||
.field("od", od)
|
.field("od", od)
|
||||||
.field("hardrock_offsets", hardrock_offsets)
|
.field("hardrock_offsets", hardrock_offsets)
|
||||||
|
.field("lazer", lazer)
|
||||||
.finish()
|
.finish()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -302,7 +302,7 @@ impl<'map> Performance<'map> {
|
|||||||
/// Whether the calculated attributes belong to an osu!lazer or osu!stable
|
/// Whether the calculated attributes belong to an osu!lazer or osu!stable
|
||||||
/// score.
|
/// score.
|
||||||
///
|
///
|
||||||
/// Defaults to lazer.
|
/// Defaults to `true`.
|
||||||
///
|
///
|
||||||
/// This affects internal accuracy calculation because lazer considers
|
/// This affects internal accuracy calculation because lazer considers
|
||||||
/// slider heads for accuracy whereas stable does not.
|
/// slider heads for accuracy whereas stable does not.
|
||||||
|
|||||||
@@ -481,7 +481,6 @@ impl<'map> TryFrom<OsuPerformance<'map>> for CatchPerformance<'map> {
|
|||||||
n50,
|
n50,
|
||||||
misses,
|
misses,
|
||||||
hitresult_priority: _,
|
hitresult_priority: _,
|
||||||
lazer: _,
|
|
||||||
} = osu;
|
} = osu;
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
|
|||||||
@@ -834,7 +834,6 @@ impl<'map> TryFrom<OsuPerformance<'map>> for ManiaPerformance<'map> {
|
|||||||
n50,
|
n50,
|
||||||
misses,
|
misses,
|
||||||
hitresult_priority,
|
hitresult_priority,
|
||||||
lazer: _,
|
|
||||||
} = osu;
|
} = osu;
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
|
|||||||
+1
-11
@@ -55,18 +55,8 @@ pub fn convert_objects(
|
|||||||
OsuObjectKind::Circle => attrs.n_circles += 1,
|
OsuObjectKind::Circle => attrs.n_circles += 1,
|
||||||
OsuObjectKind::Slider(ref slider) => {
|
OsuObjectKind::Slider(ref slider) => {
|
||||||
attrs.n_sliders += 1;
|
attrs.n_sliders += 1;
|
||||||
|
attrs.n_slider_ticks += slider.tick_count() as u32;
|
||||||
attrs.max_combo += slider.nested_objects.len() as u32;
|
attrs.max_combo += slider.nested_objects.len() as u32;
|
||||||
|
|
||||||
attrs.n_slider_ticks += slider
|
|
||||||
.nested_objects
|
|
||||||
.iter()
|
|
||||||
.filter(|nested| {
|
|
||||||
matches!(
|
|
||||||
nested.kind,
|
|
||||||
NestedSliderObjectKind::Tick | NestedSliderObjectKind::Repeat
|
|
||||||
)
|
|
||||||
})
|
|
||||||
.count() as u32;
|
|
||||||
}
|
}
|
||||||
OsuObjectKind::Spinner(_) => attrs.n_spinners += 1,
|
OsuObjectKind::Spinner(_) => attrs.n_spinners += 1,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -92,6 +92,7 @@ impl OsuGradualDifficulty {
|
|||||||
|
|
||||||
attrs.n_circles = 0;
|
attrs.n_circles = 0;
|
||||||
attrs.n_sliders = 0;
|
attrs.n_sliders = 0;
|
||||||
|
attrs.n_slider_ticks = 0;
|
||||||
attrs.n_spinners = 0;
|
attrs.n_spinners = 0;
|
||||||
attrs.max_combo = 0;
|
attrs.max_combo = 0;
|
||||||
|
|
||||||
@@ -128,6 +129,7 @@ impl OsuGradualDifficulty {
|
|||||||
OsuObjectKind::Circle => attrs.n_circles += 1,
|
OsuObjectKind::Circle => attrs.n_circles += 1,
|
||||||
OsuObjectKind::Slider(slider) => {
|
OsuObjectKind::Slider(slider) => {
|
||||||
attrs.n_sliders += 1;
|
attrs.n_sliders += 1;
|
||||||
|
attrs.n_slider_ticks += slider.tick_count() as u32;
|
||||||
attrs.max_combo += slider.nested_objects.len() as u32;
|
attrs.max_combo += slider.nested_objects.len() as u32;
|
||||||
}
|
}
|
||||||
OsuObjectKind::Spinner { .. } => attrs.n_spinners += 1,
|
OsuObjectKind::Spinner { .. } => attrs.n_spinners += 1,
|
||||||
|
|||||||
@@ -308,6 +308,19 @@ impl OsuSlider {
|
|||||||
.count()
|
.count()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Counts both ticks and repeats
|
||||||
|
pub fn tick_count(&self) -> usize {
|
||||||
|
self.nested_objects
|
||||||
|
.iter()
|
||||||
|
.filter(|nested| {
|
||||||
|
matches!(
|
||||||
|
nested.kind,
|
||||||
|
NestedSliderObjectKind::Tick | NestedSliderObjectKind::Repeat
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.count()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn tail(&self) -> Option<&NestedSliderObject> {
|
pub fn tail(&self) -> Option<&NestedSliderObject> {
|
||||||
self.nested_objects
|
self.nested_objects
|
||||||
.iter()
|
.iter()
|
||||||
|
|||||||
@@ -80,15 +80,17 @@ use super::{OsuPerformanceAttributes, OsuScoreState};
|
|||||||
/// [`next`]: OsuGradualPerformance::next
|
/// [`next`]: OsuGradualPerformance::next
|
||||||
/// [`nth`]: OsuGradualPerformance::nth
|
/// [`nth`]: OsuGradualPerformance::nth
|
||||||
pub struct OsuGradualPerformance {
|
pub struct OsuGradualPerformance {
|
||||||
|
lazer: bool,
|
||||||
difficulty: OsuGradualDifficulty,
|
difficulty: OsuGradualDifficulty,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl OsuGradualPerformance {
|
impl OsuGradualPerformance {
|
||||||
/// Create a new gradual performance calculator for osu!standard maps.
|
/// Create a new gradual performance calculator for osu!standard maps.
|
||||||
pub fn new(difficulty: Difficulty, converted: &OsuBeatmap<'_>) -> Self {
|
pub fn new(difficulty: Difficulty, converted: &OsuBeatmap<'_>) -> Self {
|
||||||
|
let lazer = difficulty.get_lazer();
|
||||||
let difficulty = OsuGradualDifficulty::new(difficulty, converted);
|
let difficulty = OsuGradualDifficulty::new(difficulty, converted);
|
||||||
|
|
||||||
Self { difficulty }
|
Self { lazer, difficulty }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Process the next hit object and calculate the performance attributes
|
/// Process the next hit object and calculate the performance attributes
|
||||||
@@ -113,6 +115,7 @@ impl OsuGradualPerformance {
|
|||||||
.difficulty
|
.difficulty
|
||||||
.nth(n)?
|
.nth(n)?
|
||||||
.performance()
|
.performance()
|
||||||
|
.lazer(self.lazer)
|
||||||
.state(state)
|
.state(state)
|
||||||
.difficulty(self.difficulty.difficulty.clone())
|
.difficulty(self.difficulty.difficulty.clone())
|
||||||
.passed_objects(self.difficulty.idx as u32)
|
.passed_objects(self.difficulty.idx as u32)
|
||||||
|
|||||||
@@ -35,7 +35,6 @@ pub struct OsuPerformance<'map> {
|
|||||||
pub(crate) n50: Option<u32>,
|
pub(crate) n50: Option<u32>,
|
||||||
pub(crate) misses: Option<u32>,
|
pub(crate) misses: Option<u32>,
|
||||||
pub(crate) hitresult_priority: HitResultPriority,
|
pub(crate) hitresult_priority: HitResultPriority,
|
||||||
pub(crate) lazer: Option<bool>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'map> OsuPerformance<'map> {
|
impl<'map> OsuPerformance<'map> {
|
||||||
@@ -158,12 +157,12 @@ impl<'map> OsuPerformance<'map> {
|
|||||||
/// Whether the calculated attributes belong to an osu!lazer or osu!stable
|
/// Whether the calculated attributes belong to an osu!lazer or osu!stable
|
||||||
/// score.
|
/// score.
|
||||||
///
|
///
|
||||||
/// Defaults to lazer.
|
/// Defaults to `true`.
|
||||||
///
|
///
|
||||||
/// This affects internal accuracy calculation because lazer considers
|
/// This affects internal accuracy calculation because lazer considers
|
||||||
/// slider heads for accuracy whereas stable does not.
|
/// slider heads for accuracy whereas stable does not.
|
||||||
pub const fn lazer(mut self, lazer: bool) -> Self {
|
pub fn lazer(mut self, lazer: bool) -> Self {
|
||||||
self.lazer = Some(lazer);
|
self.difficulty = self.difficulty.lazer(lazer);
|
||||||
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
@@ -366,7 +365,7 @@ impl<'map> OsuPerformance<'map> {
|
|||||||
let mut n100 = self.n100.map_or(0, |n| cmp::min(n, n_remaining));
|
let mut n100 = self.n100.map_or(0, |n| cmp::min(n, n_remaining));
|
||||||
let mut n50 = self.n50.map_or(0, |n| cmp::min(n, n_remaining));
|
let mut n50 = self.n50.map_or(0, |n| cmp::min(n, n_remaining));
|
||||||
|
|
||||||
let lazer = self.lazer.unwrap_or(true);
|
let lazer = self.difficulty.get_lazer();
|
||||||
|
|
||||||
let (n_slider_ends, n_slider_ticks, max_slider_ends, max_slider_ticks) = if lazer {
|
let (n_slider_ends, n_slider_ticks, max_slider_ends, max_slider_ticks) = if lazer {
|
||||||
let n_slider_ends = self
|
let n_slider_ends = self
|
||||||
@@ -627,7 +626,7 @@ impl<'map> OsuPerformance<'map> {
|
|||||||
|
|
||||||
let effective_miss_count = calculate_effective_misses(&attrs, &state);
|
let effective_miss_count = calculate_effective_misses(&attrs, &state);
|
||||||
|
|
||||||
let lazer = self.lazer.unwrap_or(true);
|
let lazer = self.difficulty.get_lazer();
|
||||||
|
|
||||||
let (n_slider_ends, n_slider_ticks) = if lazer {
|
let (n_slider_ends, n_slider_ticks) = if lazer {
|
||||||
(attrs.n_sliders, attrs.n_slider_ticks)
|
(attrs.n_sliders, attrs.n_slider_ticks)
|
||||||
@@ -660,7 +659,6 @@ impl<'map> OsuPerformance<'map> {
|
|||||||
n50: None,
|
n50: None,
|
||||||
misses: None,
|
misses: None,
|
||||||
hitresult_priority: HitResultPriority::DEFAULT,
|
hitresult_priority: HitResultPriority::DEFAULT,
|
||||||
lazer: None,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -371,7 +371,6 @@ impl<'map> TryFrom<OsuPerformance<'map>> for TaikoPerformance<'map> {
|
|||||||
n50: _,
|
n50: _,
|
||||||
misses,
|
misses,
|
||||||
hitresult_priority,
|
hitresult_priority,
|
||||||
lazer: _,
|
|
||||||
} = osu;
|
} = osu;
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
|
|||||||
Reference in New Issue
Block a user