apply new settings of Difficulty

This commit is contained in:
MaxOhn
2024-03-04 15:56:55 +01:00
parent c5fdf4e610
commit 633955ab1b
30 changed files with 618 additions and 272 deletions
+12 -15
View File
@@ -55,8 +55,7 @@ use super::{
/// [`OsuGradualPerformance`]: crate::osu::OsuGradualPerformance
pub struct OsuGradualDifficulty {
pub(crate) idx: usize,
pub(crate) mods: u32,
pub(crate) clock_rate: f64,
pub(crate) difficulty: Difficulty,
attrs: OsuDifficultyAttributes,
skills: OsuSkills,
// Lifetimes actually depend on `osu_objects` so this type is
@@ -73,16 +72,15 @@ struct NotClonable;
impl OsuGradualDifficulty {
/// Create a new difficulty attributes iterator for osu!standard maps.
pub fn new(difficulty: &Difficulty, converted: &OsuBeatmap<'_>) -> Self {
pub fn new(difficulty: Difficulty, converted: &OsuBeatmap<'_>) -> Self {
let mods = difficulty.get_mods();
let clock_rate = difficulty.get_clock_rate();
let OsuDifficultySetup {
scaling_factor,
map_attrs,
mut attrs,
time_preempt,
} = OsuDifficultySetup::new(difficulty, converted);
} = OsuDifficultySetup::new(&difficulty, converted);
let osu_objects = convert_objects(
converted,
@@ -105,7 +103,7 @@ impl OsuGradualDifficulty {
let mut osu_objects = OsuObjects::new(osu_objects);
let diff_objects = DifficultyValues::create_difficulty_objects(
difficulty,
&difficulty,
&scaling_factor,
osu_objects.iter_mut(),
);
@@ -115,8 +113,7 @@ impl OsuGradualDifficulty {
Self {
idx: 0,
mods,
clock_rate,
difficulty,
attrs,
skills,
diff_objects,
@@ -181,7 +178,7 @@ impl Iterator for OsuGradualDifficulty {
DifficultyValues::eval(
&mut attrs,
self.mods,
self.difficulty.get_mods(),
aim_difficulty_value,
aim_no_sliders_difficulty_value,
speed_difficulty_value,
@@ -271,8 +268,7 @@ mod tests {
.unwrap()
.unchecked_into_converted::<Osu>();
let difficulty = Difficulty::new();
let mut gradual = OsuGradualDifficulty::new(&difficulty, &converted);
let mut gradual = OsuGradualDifficulty::new(Difficulty::new(), &converted);
assert!(gradual.next().is_none());
}
@@ -285,9 +281,9 @@ mod tests {
let difficulty = Difficulty::new();
let mut gradual = OsuGradualDifficulty::new(&difficulty, &converted);
let mut gradual_2nd = OsuGradualDifficulty::new(&difficulty, &converted);
let mut gradual_3rd = OsuGradualDifficulty::new(&difficulty, &converted);
let mut gradual = OsuGradualDifficulty::new(difficulty.clone(), &converted);
let mut gradual_2nd = OsuGradualDifficulty::new(difficulty.clone(), &converted);
let mut gradual_3rd = OsuGradualDifficulty::new(difficulty.clone(), &converted);
let hit_objects_len = converted.hit_objects.len();
@@ -309,7 +305,8 @@ mod tests {
assert_eq!(next_gradual, next_gradual_3rd);
}
let expected = Difficulty::new()
let expected = difficulty
.clone()
.passed_objects(i as u32)
.with_mode()
.calculate(&converted);
+1 -8
View File
@@ -68,15 +68,8 @@ pub struct OsuDifficultySetup {
impl OsuDifficultySetup {
pub fn new(difficulty: &Difficulty, converted: &OsuBeatmap) -> Self {
let mods = difficulty.get_mods();
let clock_rate = difficulty.get_clock_rate();
let map_attrs = converted
.attributes()
.mods(mods)
.clock_rate(clock_rate)
.build();
let map_attrs = converted.attributes().difficulty(difficulty).build();
let scaling_factor = ScalingFactor::new(map_attrs.cs);
let attrs = OsuDifficultyAttributes {
+2 -5
View File
@@ -62,15 +62,12 @@ impl IGameMode for Osu {
OsuPerformance::new(map)
}
fn gradual_difficulty(
difficulty: &Difficulty,
map: &OsuBeatmap<'_>,
) -> Self::GradualDifficulty {
fn gradual_difficulty(difficulty: Difficulty, map: &OsuBeatmap<'_>) -> Self::GradualDifficulty {
OsuGradualDifficulty::new(difficulty, map)
}
fn gradual_performance(
difficulty: &Difficulty,
difficulty: Difficulty,
map: &OsuBeatmap<'_>,
) -> Self::GradualPerformance {
OsuGradualPerformance::new(difficulty, map)
+7 -9
View File
@@ -85,7 +85,7 @@ pub struct OsuGradualPerformance {
impl OsuGradualPerformance {
/// 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 difficulty = OsuGradualDifficulty::new(difficulty, converted);
Self { difficulty }
@@ -114,8 +114,7 @@ impl OsuGradualPerformance {
.nth(n)?
.performance()
.state(state)
.mods(self.difficulty.mods)
.clock_rate(self.difficulty.clock_rate)
.difficulty(self.difficulty.difficulty.clone())
.passed_objects(self.difficulty.idx as u32)
.calculate();
@@ -138,12 +137,11 @@ mod tests {
.unwrap()
.unchecked_into_converted::<Osu>();
let mods = 88; // HDHRDT
let difficulty = Difficulty::new().mods(88);
let difficulty = Difficulty::new().mods(88); // HDHRDT
let mut gradual = OsuGradualPerformance::new(&difficulty, &converted);
let mut gradual_2nd = OsuGradualPerformance::new(&difficulty, &converted);
let mut gradual_3rd = OsuGradualPerformance::new(&difficulty, &converted);
let mut gradual = OsuGradualPerformance::new(difficulty.clone(), &converted);
let mut gradual_2nd = OsuGradualPerformance::new(difficulty.clone(), &converted);
let mut gradual_3rd = OsuGradualPerformance::new(difficulty.clone(), &converted);
let mut state = OsuScoreState::default();
@@ -170,7 +168,7 @@ mod tests {
}
let mut regular_calc = OsuPerformance::new(converted.as_owned())
.mods(mods)
.difficulty(difficulty.clone())
.passed_objects(i as u32)
.state(state);
+76 -2
View File
@@ -114,8 +114,10 @@ impl<'map> OsuPerformance<'map> {
}
/// 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.
///
/// If you already calculated the attributes for the current
/// [`OsuBeatmap`] and [`Difficulty`], be sure to put them in here so that
/// they don't have to be recalculated.
pub fn attributes(mut self, attributes: impl ModeAttributeProvider<Osu>) -> Self {
if let Some(attrs) = attributes.attributes() {
self.map_or_attrs = MapOrAttrs::Attrs(attrs);
@@ -177,6 +179,13 @@ impl<'map> OsuPerformance<'map> {
self
}
/// Use the specified settings of the given [`Difficulty`].
pub const fn difficulty(mut self, difficulty: Difficulty) -> Self {
self.difficulty = difficulty;
self
}
/// Amount of passed objects for partial plays, e.g. a fail.
///
/// If you want to calculate the performance after every few objects,
@@ -191,14 +200,79 @@ impl<'map> OsuPerformance<'map> {
}
/// Adjust the clock rate used in the calculation.
///
/// If none is specified, it will take the clock rate based on the mods
/// i.e. 1.5 for DT, 0.75 for HT and 1.0 otherwise.
///
/// | Minimum | Maximum |
/// | :-----: | :-----: |
/// | 0.01 | 100 |
pub fn clock_rate(mut self, clock_rate: f64) -> Self {
self.difficulty = self.difficulty.clock_rate(clock_rate);
self
}
/// Override a beatmap's set AR.
///
/// `with_mods` determines if the given value should be used before
/// or after accounting for mods, e.g. on `true` the value will be
/// used as is and on `false` it will be modified based on the mods.
///
/// | Minimum | Maximum |
/// | :-----: | :-----: |
/// | -20 | 20 |
pub fn ar(mut self, ar: f32, with_mods: bool) -> Self {
self.difficulty = self.difficulty.ar(ar, with_mods);
self
}
/// Override a beatmap's set CS.
///
/// `with_mods` determines if the given value should be used before
/// or after accounting for mods, e.g. on `true` the value will be
/// used as is and on `false` it will be modified based on the mods.
///
/// | Minimum | Maximum |
/// | :-----: | :-----: |
/// | -20 | 20 |
pub fn cs(mut self, cs: f32, with_mods: bool) -> Self {
self.difficulty = self.difficulty.cs(cs, with_mods);
self
}
/// Override a beatmap's set HP.
///
/// `with_mods` determines if the given value should be used before
/// or after accounting for mods, e.g. on `true` the value will be
/// used as is and on `false` it will be modified based on the mods.
///
/// | Minimum | Maximum |
/// | :-----: | :-----: |
/// | -20 | 20 |
pub fn hp(mut self, hp: f32, with_mods: bool) -> Self {
self.difficulty = self.difficulty.hp(hp, with_mods);
self
}
/// Override a beatmap's set OD.
///
/// `with_mods` determines if the given value should be used before
/// or after accounting for mods, e.g. on `true` the value will be
/// used as is and on `false` it will be modified based on the mods.
///
/// | Minimum | Maximum |
/// | :-----: | :-----: |
/// | -20 | 20 |
pub fn od(mut self, od: f32, with_mods: bool) -> Self {
self.difficulty = self.difficulty.od(od, with_mods);
self
}
/// Provide parameters through an [`OsuScoreState`].
#[allow(clippy::needless_pass_by_value)]
pub const fn state(mut self, state: OsuScoreState) -> Self {