use round_ties_even from std lib
This commit is contained in:
@@ -9,7 +9,7 @@ use crate::{
|
|||||||
hit_object::{HitObjectKind, HoldNote, Spinner},
|
hit_object::{HitObjectKind, HoldNote, Spinner},
|
||||||
mode::ConvertStatus,
|
mode::ConvertStatus,
|
||||||
},
|
},
|
||||||
util::{float_ext::FloatExt, limited_queue::LimitedQueue, random::Random, sort},
|
util::{limited_queue::LimitedQueue, random::Random, sort},
|
||||||
};
|
};
|
||||||
|
|
||||||
use self::{
|
use self::{
|
||||||
@@ -53,9 +53,9 @@ pub fn try_convert(map: &mut Beatmap) -> ConvertStatus {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn convert(map: &mut Beatmap) {
|
fn convert(map: &mut Beatmap) {
|
||||||
let seed = (map.hp + map.cs).round_even() as i32 * 20
|
let seed = (map.hp + map.cs).round_ties_even() as i32 * 20
|
||||||
+ (map.od * 41.2) as i32
|
+ (map.od * 41.2) as i32
|
||||||
+ map.ar.round_even() as i32;
|
+ map.ar.round_ties_even() as i32;
|
||||||
|
|
||||||
let mut random = Random::new(seed);
|
let mut random = Random::new(seed);
|
||||||
|
|
||||||
@@ -192,8 +192,8 @@ impl Default for PrevValues {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn target_columns(map: &Beatmap) -> f32 {
|
fn target_columns(map: &Beatmap) -> f32 {
|
||||||
let rounded_cs = map.cs.round_even();
|
let rounded_cs = map.cs.round_ties_even();
|
||||||
let rounded_od = map.od.round_even();
|
let rounded_od = map.od.round_ties_even();
|
||||||
|
|
||||||
let slider_or_spinner_count = map
|
let slider_or_spinner_count = map
|
||||||
.hit_objects
|
.hit_objects
|
||||||
@@ -217,6 +217,8 @@ fn target_columns(map: &Beatmap) -> f32 {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
use crate::util::float_ext::FloatExt;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ use crate::{
|
|||||||
control_point::{DifficultyPoint, EffectPoint, TimingPoint},
|
control_point::{DifficultyPoint, EffectPoint, TimingPoint},
|
||||||
hit_object::HitObject,
|
hit_object::HitObject,
|
||||||
},
|
},
|
||||||
util::{float_ext::FloatExt, random::Random},
|
util::random::Random,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::PatternGenerator;
|
use super::PatternGenerator;
|
||||||
@@ -65,7 +65,7 @@ impl<'h> DistanceObjectPatternGenerator<'h> {
|
|||||||
let beat_len = timing_beat_len * bpm_multiplier;
|
let beat_len = timing_beat_len * bpm_multiplier;
|
||||||
|
|
||||||
let span_count = (repeats + 1) as i32;
|
let span_count = (repeats + 1) as i32;
|
||||||
let start_time = hit_object.start_time.round_even() as i32;
|
let start_time = hit_object.start_time.round_ties_even() as i32;
|
||||||
|
|
||||||
// * This matches stable's calculation.
|
// * This matches stable's calculation.
|
||||||
let end_time = (f64::from(start_time)
|
let end_time = (f64::from(start_time)
|
||||||
@@ -107,7 +107,7 @@ impl<'h> DistanceObjectPatternGenerator<'h> {
|
|||||||
|
|
||||||
// Keeping it in-sync with lazer
|
// Keeping it in-sync with lazer
|
||||||
#[allow(clippy::if_not_else)]
|
#[allow(clippy::if_not_else)]
|
||||||
if self.end_time != obj.end_time().round_even() as i32 {
|
if self.end_time != obj.end_time().round_ties_even() as i32 {
|
||||||
intermediate_pattern.add_object(obj, col);
|
intermediate_pattern.add_object(obj, col);
|
||||||
} else {
|
} else {
|
||||||
end_time_pattern.add_object(obj, col);
|
end_time_pattern.add_object(obj, col);
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ use crate::{
|
|||||||
any::difficulty::skills::Skill,
|
any::difficulty::skills::Skill,
|
||||||
mania::{object::ObjectParams, ManiaBeatmap},
|
mania::{object::ObjectParams, ManiaBeatmap},
|
||||||
model::{beatmap::HitWindows, hit_object::HitObject},
|
model::{beatmap::HitWindows, hit_object::HitObject},
|
||||||
util::float_ext::FloatExt,
|
|
||||||
Difficulty,
|
Difficulty,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -62,7 +61,7 @@ impl ManiaGradualDifficulty {
|
|||||||
/// Create a new difficulty attributes iterator for osu!mania maps.
|
/// Create a new difficulty attributes iterator for osu!mania maps.
|
||||||
pub fn new(difficulty: Difficulty, converted: &ManiaBeatmap<'_>) -> Self {
|
pub fn new(difficulty: Difficulty, converted: &ManiaBeatmap<'_>) -> Self {
|
||||||
let take = difficulty.get_passed_objects();
|
let take = difficulty.get_passed_objects();
|
||||||
let total_columns = converted.cs.round_even().max(1.0);
|
let total_columns = converted.cs.round_ties_even().max(1.0);
|
||||||
let clock_rate = difficulty.get_clock_rate();
|
let clock_rate = difficulty.get_clock_rate();
|
||||||
let mut params = ObjectParams::new(converted);
|
let mut params = ObjectParams::new(converted);
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ use crate::{
|
|||||||
difficulty::{object::ManiaDifficultyObject, skills::strain::Strain},
|
difficulty::{object::ManiaDifficultyObject, skills::strain::Strain},
|
||||||
object::{ManiaObject, ObjectParams},
|
object::{ManiaObject, ObjectParams},
|
||||||
},
|
},
|
||||||
util::float_ext::FloatExt,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{attributes::ManiaDifficultyAttributes, convert::ManiaBeatmap};
|
use super::{attributes::ManiaDifficultyAttributes, convert::ManiaBeatmap};
|
||||||
@@ -48,7 +47,7 @@ pub struct DifficultyValues {
|
|||||||
impl DifficultyValues {
|
impl DifficultyValues {
|
||||||
pub fn calculate(difficulty: &Difficulty, converted: &ManiaBeatmap<'_>) -> Self {
|
pub fn calculate(difficulty: &Difficulty, converted: &ManiaBeatmap<'_>) -> Self {
|
||||||
let take = difficulty.get_passed_objects();
|
let take = difficulty.get_passed_objects();
|
||||||
let total_columns = converted.cs.round_even().max(1.0);
|
let total_columns = converted.cs.round_ties_even().max(1.0);
|
||||||
let clock_rate = difficulty.get_clock_rate();
|
let clock_rate = difficulty.get_clock_rate();
|
||||||
let mut params = ObjectParams::new(converted);
|
let mut params = ObjectParams::new(converted);
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,6 @@
|
|||||||
use rosu_map::section::general::GameMode;
|
use rosu_map::section::general::GameMode;
|
||||||
|
|
||||||
use crate::{
|
use crate::{any::difficulty::ModsDependent, util::mods::Mods, Difficulty};
|
||||||
any::difficulty::ModsDependent,
|
|
||||||
util::{float_ext::FloatExt, mods::Mods},
|
|
||||||
Difficulty,
|
|
||||||
};
|
|
||||||
|
|
||||||
use super::{converted::Converted, Beatmap};
|
use super::{converted::Converted, Beatmap};
|
||||||
|
|
||||||
@@ -244,7 +240,7 @@ impl BeatmapAttributesBuilder {
|
|||||||
GameMode::Mania => {
|
GameMode::Mania => {
|
||||||
let mut value = if !self.is_convert {
|
let mut value = if !self.is_convert {
|
||||||
34.0 + 3.0 * (10.0 - self.od.value).clamp(0.0, 10.0)
|
34.0 + 3.0 * (10.0 - self.od.value).clamp(0.0, 10.0)
|
||||||
} else if self.od.value.round_even() > 4.0 {
|
} else if self.od.value.round_ties_even() > 4.0 {
|
||||||
34.0
|
34.0
|
||||||
} else {
|
} else {
|
||||||
47.0
|
47.0
|
||||||
@@ -351,6 +347,8 @@ impl Default for BeatmapAttributesBuilder {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
use crate::util::float_ext::FloatExt;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|||||||
@@ -1,11 +1,4 @@
|
|||||||
pub trait FloatExt: Sized {
|
pub trait FloatExt: Sized {
|
||||||
/// Workaround since rust rounds ties away from 0.0
|
|
||||||
/// while C# rounds them to the nearest even integer.
|
|
||||||
/// See github
|
|
||||||
/// - <https://github.com/rust-lang/rust/issues/96710>
|
|
||||||
/// - <https://github.com/rust-lang/rust/pull/82273>
|
|
||||||
fn round_even(self) -> Self;
|
|
||||||
|
|
||||||
/// `self == other`
|
/// `self == other`
|
||||||
fn eq(self, other: Self) -> bool;
|
fn eq(self, other: Self) -> bool;
|
||||||
|
|
||||||
@@ -16,14 +9,6 @@ pub trait FloatExt: Sized {
|
|||||||
macro_rules! impl_float_ext {
|
macro_rules! impl_float_ext {
|
||||||
( $ty:ty ) => {
|
( $ty:ty ) => {
|
||||||
impl FloatExt for $ty {
|
impl FloatExt for $ty {
|
||||||
fn round_even(self) -> Self {
|
|
||||||
if self.fract().abs().eq(0.5) {
|
|
||||||
2.0 * (self / 2.0).round()
|
|
||||||
} else {
|
|
||||||
self.round()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn eq(self, other: Self) -> bool {
|
fn eq(self, other: Self) -> bool {
|
||||||
(self - other).abs() < <$ty>::EPSILON
|
(self - other).abs() < <$ty>::EPSILON
|
||||||
}
|
}
|
||||||
@@ -37,35 +22,3 @@ macro_rules! impl_float_ext {
|
|||||||
|
|
||||||
impl_float_ext!(f32);
|
impl_float_ext!(f32);
|
||||||
impl_float_ext!(f64);
|
impl_float_ext!(f64);
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
#[test]
|
|
||||||
fn round_even() {
|
|
||||||
let values = vec![
|
|
||||||
(3.0, 3.0),
|
|
||||||
(3.5, 4.0),
|
|
||||||
(4.5, 4.0),
|
|
||||||
(4.500_001, 5.0),
|
|
||||||
(3.499_999, 3.0),
|
|
||||||
(3.500_001, 4.0),
|
|
||||||
(100_000_000_002.5, 100_000_000_002.0),
|
|
||||||
(-3.0, -3.0),
|
|
||||||
(-3.5, -4.0),
|
|
||||||
(-4.5, -4.0),
|
|
||||||
(-4.500_001, -5.0),
|
|
||||||
(-3.499_999, -3.0),
|
|
||||||
(-3.500_001, -4.0),
|
|
||||||
(-100_000_000_002.5, -100_000_000_002.0),
|
|
||||||
];
|
|
||||||
|
|
||||||
for (value, expected) in values {
|
|
||||||
let rounded = <f32 as super::FloatExt>::round_even(value);
|
|
||||||
|
|
||||||
assert!(
|
|
||||||
(rounded - expected).abs() <= f32::EPSILON,
|
|
||||||
"expected {expected} for {value}; got {rounded}"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
Reference in New Issue
Block a user