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
+4 -4
View File
@@ -50,7 +50,7 @@ pub fn try_convert(map: &mut Beatmap) -> ConvertStatus {
pub fn convert_objects(
converted: &CatchBeatmap<'_>,
count: &mut ObjectCountBuilder,
hr: bool,
hr_offsets: bool,
cs: f32,
) -> Vec<PalpableObject> {
// mean=686.54 | median=501
@@ -73,7 +73,7 @@ pub fn convert_objects(
apply_pos_offset(
&mut new_objects,
hr,
hr_offsets,
&mut last_pos,
&mut last_start_time,
&mut rng,
@@ -174,14 +174,14 @@ impl ExactSizeIterator for ObjectIter<'_> {
fn apply_pos_offset(
hit_object: &mut ObjectIter<'_>,
should_apply_hr_offset: bool,
hr_offsets: bool,
last_pos: &mut Option<f32>,
last_start_time: &mut f64,
rng: &mut Random,
) {
match hit_object.state {
ObjectIterState::Fruit(Some(ref mut fruit)) => {
if should_apply_hr_offset {
if hr_offsets {
apply_hr_offset(
hit_object.x,
&mut fruit.x_offset,
+13 -16
View File
@@ -7,7 +7,6 @@ use crate::{
convert::convert_objects,
CatchBeatmap, CatchDifficultyAttributes,
},
util::mods::Mods,
Difficulty,
};
@@ -56,8 +55,7 @@ use super::{
/// [`CatchGradualPerformance`]: crate::catch::CatchGradualPerformance
pub struct CatchGradualDifficulty {
pub(crate) idx: usize,
pub(crate) mods: u32,
pub(crate) clock_rate: f64,
pub(crate) difficulty: Difficulty,
attrs: CatchDifficultyAttributes,
/// The delta of object counts after each palpable object
count: Vec<GradualObjectCount>,
@@ -66,16 +64,16 @@ pub struct CatchGradualDifficulty {
}
impl CatchGradualDifficulty {
pub fn new(difficulty: &Difficulty, converted: &CatchBeatmap<'_>) -> Self {
let mods = difficulty.get_mods();
pub fn new(difficulty: Difficulty, converted: &CatchBeatmap<'_>) -> Self {
let clock_rate = difficulty.get_clock_rate();
let CatchDifficultySetup { map_attrs, attrs } =
CatchDifficultySetup::new(difficulty, converted);
CatchDifficultySetup::new(&difficulty, converted);
let hr = mods.hr();
let hr_offsets = difficulty.get_hardrock_offsets();
let mut count = ObjectCountBuilder::new_gradual();
let palpable_objects = convert_objects(converted, &mut count, hr, map_attrs.cs as f32);
let palpable_objects =
convert_objects(converted, &mut count, hr_offsets, map_attrs.cs as f32);
let diff_objects = DifficultyValues::create_difficulty_objects(
&map_attrs,
@@ -88,8 +86,7 @@ impl CatchGradualDifficulty {
Self {
idx: 0,
mods,
clock_rate,
difficulty,
attrs,
count,
diff_objects,
@@ -171,8 +168,7 @@ mod tests {
fn empty() {
let converted = Beatmap::from_bytes(&[]).unwrap().unchecked_into_converted();
let difficulty = Difficulty::new();
let mut gradual = CatchGradualDifficulty::new(&difficulty, &converted);
let mut gradual = CatchGradualDifficulty::new(Difficulty::new(), &converted);
assert!(gradual.next().is_none());
}
@@ -185,9 +181,9 @@ mod tests {
let difficulty = Difficulty::new();
let mut gradual = CatchGradualDifficulty::new(&difficulty, &converted);
let mut gradual_2nd = CatchGradualDifficulty::new(&difficulty, &converted);
let mut gradual_3rd = CatchGradualDifficulty::new(&difficulty, &converted);
let mut gradual = CatchGradualDifficulty::new(difficulty.clone(), &converted);
let mut gradual_2nd = CatchGradualDifficulty::new(difficulty.clone(), &converted);
let mut gradual_3rd = CatchGradualDifficulty::new(difficulty.clone(), &converted);
for i in 1.. {
let Some(next_gradual) = gradual.next() else {
@@ -207,7 +203,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);
+4 -12
View File
@@ -4,7 +4,6 @@ use crate::{
catcher::Catcher, convert::convert_objects, difficulty::object::CatchDifficultyObject,
},
model::beatmap::BeatmapAttributes,
util::mods::Mods,
};
use self::skills::movement::Movement;
@@ -42,14 +41,7 @@ pub struct CatchDifficultySetup {
impl CatchDifficultySetup {
pub fn new(difficulty: &Difficulty, converted: &CatchBeatmap<'_>) -> 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 attrs = CatchDifficultyAttributes {
ar: map_attrs.ar,
@@ -69,7 +61,6 @@ pub struct DifficultyValues {
impl DifficultyValues {
pub fn calculate(difficulty: &Difficulty, converted: &CatchBeatmap<'_>) -> Self {
let take = difficulty.get_passed_objects();
let mods = difficulty.get_mods();
let clock_rate = difficulty.get_clock_rate();
let CatchDifficultySetup {
@@ -77,10 +68,11 @@ impl DifficultyValues {
mut attrs,
} = CatchDifficultySetup::new(difficulty, converted);
let hr = mods.hr();
let hr_offsets = difficulty.get_hardrock_offsets();
let mut count = ObjectCountBuilder::new_regular(take);
let palpable_objects = convert_objects(converted, &mut count, hr, map_attrs.cs as f32);
let palpable_objects =
convert_objects(converted, &mut count, hr_offsets, map_attrs.cs as f32);
let diff_objects = Self::create_difficulty_objects(
&map_attrs,
+2 -2
View File
@@ -62,14 +62,14 @@ impl IGameMode for Catch {
}
fn gradual_difficulty(
difficulty: &Difficulty,
difficulty: Difficulty,
map: &CatchBeatmap<'_>,
) -> Self::GradualDifficulty {
CatchGradualDifficulty::new(difficulty, map)
}
fn gradual_performance(
difficulty: &Difficulty,
difficulty: Difficulty,
map: &CatchBeatmap<'_>,
) -> Self::GradualPerformance {
CatchGradualPerformance::new(difficulty, map)
+7 -9
View File
@@ -90,7 +90,7 @@ pub struct CatchGradualPerformance {
impl CatchGradualPerformance {
/// Create a new gradual performance calculator for osu!catch maps.
pub fn new(difficulty: &Difficulty, converted: &CatchBeatmap<'_>) -> Self {
pub fn new(difficulty: Difficulty, converted: &CatchBeatmap<'_>) -> Self {
let difficulty = CatchGradualDifficulty::new(difficulty, converted);
Self { difficulty }
@@ -122,8 +122,7 @@ impl CatchGradualPerformance {
.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();
@@ -143,12 +142,11 @@ mod tests {
.unwrap()
.unchecked_into_converted();
let mods = 88; // HDHRDT
let difficulty = Difficulty::new().mods(88);
let difficulty = Difficulty::new().mods(88); // HDHRDT
let mut gradual = CatchGradualPerformance::new(&difficulty, &converted);
let mut gradual_2nd = CatchGradualPerformance::new(&difficulty, &converted);
let mut gradual_3rd = CatchGradualPerformance::new(&difficulty, &converted);
let mut gradual = CatchGradualPerformance::new(difficulty.clone(), &converted);
let mut gradual_2nd = CatchGradualPerformance::new(difficulty.clone(), &converted);
let mut gradual_3rd = CatchGradualPerformance::new(difficulty.clone(), &converted);
let mut state = CatchScoreState::default();
@@ -173,7 +171,7 @@ mod tests {
}
let regular_calc = CatchPerformance::new(converted.as_owned())
.mods(mods)
.difficulty(difficulty.clone())
.passed_objects(i as u32)
.state(state.clone());
+83 -2
View File
@@ -61,8 +61,10 @@ impl<'map> CatchPerformance<'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
/// [`CatchBeatmap`] 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<Catch>) -> Self {
if let Some(attrs) = attributes.attributes() {
self.map_or_attrs = MapOrAttrs::Attrs(attrs);
@@ -122,6 +124,13 @@ impl<'map> CatchPerformance<'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,
@@ -136,14 +145,86 @@ impl<'map> CatchPerformance<'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
}
/// Adjust patterns as if the HR mod is enabled.
pub const fn hardrock_offsets(mut self, hardrock_offsets: bool) -> Self {
self.difficulty = self.difficulty.hardrock_offsets(hardrock_offsets);
self
}
/// Provide parameters through an [`CatchScoreState`].
#[allow(clippy::needless_pass_by_value)]
pub const fn state(mut self, state: CatchScoreState) -> Self {