feat: adjusted lint restrictions (#31)

This commit is contained in:
Badewanne3
2023-12-31 09:19:41 +01:00
committed by GitHub
parent aeb65ab3a4
commit ecf1b2c7f4
59 changed files with 427 additions and 374 deletions
+21 -20
View File
@@ -30,7 +30,7 @@ impl<'h> OsuDifficultyObject<'h> {
let delta_time = (base.start_time - last.start_time) / clock_rate;
// * Capped to 25ms to prevent difficulty calculation breaking from simultaneous objects.
let strain_time = delta_time.max(Self::MIN_DELTA_TIME as f64);
let strain_time = delta_time.max(f64::from(Self::MIN_DELTA_TIME));
Self {
start_time,
@@ -94,6 +94,7 @@ impl Distances {
///
/// By taking in [`Pin<&mut OsuObject>`](Pin), we imply that the argument will be
/// modified but it won't be moved.
#[allow(clippy::similar_names)]
pub(crate) fn new(
base: &mut Pin<&mut OsuObject>,
last: &OsuObject,
@@ -113,11 +114,11 @@ impl Distances {
Self {
// * Bonus for repeat sliders until a better per nested object strain system can be achieved.
travel_dist: (lazy_travel_dist
* (1.0 + repeat_count as f64 / 2.5).powf(1.0 / 2.5) as f32)
as f64,
travel_dist: f64::from(
lazy_travel_dist * (1.0 + repeat_count as f64 / 2.5).powf(1.0 / 2.5) as f32,
),
travel_time: (base.lazy_travel_time() / clock_rate)
.max(OsuDifficultyObject::MIN_DELTA_TIME as f64),
.max(f64::from(OsuDifficultyObject::MIN_DELTA_TIME)),
lazy_travel_dist,
..Default::default()
}
@@ -136,17 +137,17 @@ impl Distances {
let last_cursor_pos = Self::get_end_cursor_pos(last);
this.lazy_jump_dist = (base.stacked_pos() * scaling_factor
- last_cursor_pos * scaling_factor)
.length() as f64;
this.lazy_jump_dist = f64::from(
(base.stacked_pos() * scaling_factor - last_cursor_pos * scaling_factor).length(),
);
this.min_jump_time = strain_time;
this.min_jump_dist = this.lazy_jump_dist;
if let OsuObjectKind::Slider(slider) = &last.kind {
let last_travel_time = (last.lazy_travel_time() / clock_rate)
.max(OsuDifficultyObject::MIN_DELTA_TIME as f64);
this.min_jump_time =
(strain_time - last_travel_time).max(OsuDifficultyObject::MIN_DELTA_TIME as f64);
.max(f64::from(OsuDifficultyObject::MIN_DELTA_TIME));
this.min_jump_time = (strain_time - last_travel_time)
.max(f64::from(OsuDifficultyObject::MIN_DELTA_TIME));
// * There are two types of slider-to-object patterns to consider in order
// * to better approximate the real movement a player will take to jump between the hitobjects.
@@ -176,8 +177,8 @@ impl Distances {
let tail_jump_dist = (stacked_tail_pos - base.stacked_pos()).length() * scaling_factor;
let diff = (Self::MAXIMUM_SLIDER_RADIUS - Self::ASSUMED_SLIDER_RADIUS) as f64;
let min = (tail_jump_dist - Self::MAXIMUM_SLIDER_RADIUS) as f64;
let diff = f64::from(Self::MAXIMUM_SLIDER_RADIUS - Self::ASSUMED_SLIDER_RADIUS);
let min = f64::from(tail_jump_dist - Self::MAXIMUM_SLIDER_RADIUS);
// "attributes on expressions are experimental see issue #15701 https://github.com/rust-lang/rust/issues/15701"
// rust pls...
@@ -192,8 +193,8 @@ impl Distances {
let v1 = last_last_cursor_pos - last.stacked_pos();
let v2 = base.stacked_pos() - last_cursor_pos;
let dot = v1.dot(v2) as f64;
let det = (v1.x * v2.y - v1.y * v2.x) as f64;
let dot = f64::from(v1.dot(v2));
let det = f64::from(v1.x * v2.y - v1.y * v2.x);
this.angle = Some(det.atan2(dot).abs());
}
@@ -208,16 +209,16 @@ impl Distances {
scaling_factor_: &ScalingFactor,
) -> f32 {
let mut curr_cursor_pos = pos + stack_offset;
let scaling_factor = Self::NORMALISED_RADIUS as f64 / scaling_factor_.radius as f64;
let scaling_factor = f64::from(Self::NORMALISED_RADIUS) / f64::from(scaling_factor_.radius);
let mut lazy_travel_dist: f32 = 0.0;
for (curr_movement_obj, i) in slider.nested_objects.iter().zip(1..) {
let mut curr_movement = (curr_movement_obj.pos + stack_offset) - curr_cursor_pos;
let mut curr_movement_len = scaling_factor * curr_movement.length() as f64;
let mut curr_movement_len = scaling_factor * f64::from(curr_movement.length());
// * Amount of movement required so that the cursor position needs to be updated.
let mut required_movement = Self::ASSUMED_SLIDER_RADIUS as f64;
let mut required_movement = f64::from(Self::ASSUMED_SLIDER_RADIUS);
if i == slider.nested_objects.len() {
// * The end of a slider has special aim rules due
@@ -234,10 +235,10 @@ impl Distances {
curr_movement = lazy_movement;
}
curr_movement_len = scaling_factor * curr_movement.length() as f64;
curr_movement_len = scaling_factor * f64::from(curr_movement.length());
} else if let NestedObjectKind::Repeat = curr_movement_obj.kind {
// * For a slider repeat, assume a tighter movement threshold to better assess repeat sliders.
required_movement = Self::NORMALISED_RADIUS as f64;
required_movement = f64::from(Self::NORMALISED_RADIUS);
}
if curr_movement_len > required_movement {
+6 -3
View File
@@ -70,10 +70,13 @@ struct NotClonable;
impl Debug for OsuGradualDifficulty {
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
f.debug_struct("OsuGradualDifficulty")
.field("mods", &self.mods)
.field("idx", &self.idx)
.field("attrs", &self.attrs)
.field("diff_objects", &self.diff_objects)
.field("osu_objects", &"...")
.field("skills", &self.skills)
.field("_not_clonable", &"...")
.finish()
}
}
@@ -86,7 +89,7 @@ impl OsuGradualDifficulty {
let scaling_factor = ScalingFactor::new(map_attrs.cs);
let hr = mods.hr();
let hit_window = 2.0 * map_attrs.hit_windows.od;
let time_preempt = (map_attrs.hit_windows.ar * clock_rate) as f32 as f64;
let time_preempt = f64::from((map_attrs.hit_windows.ar * clock_rate) as f32);
// * Preempt time can go below 450ms. Normally, this is achieved via the DT mod
// * which uniformly speeds up all animations game wide regardless of AR.
@@ -171,7 +174,7 @@ impl OsuGradualDifficulty {
let delta_time = (curr.start_time - last.start_time) / clock_rate;
// * Capped to 25ms to prevent difficulty calculation breaking from simultaneous objects.
let strain_time = delta_time.max(OsuDifficultyObject::MIN_DELTA_TIME as f64);
let strain_time = delta_time.max(f64::from(OsuDifficultyObject::MIN_DELTA_TIME));
let dists = Distances::new(
&mut curr,
@@ -361,7 +364,7 @@ mod osu_objects {
}
}
pub(super) fn is_empty(&self) -> bool {
pub(super) const fn is_empty(&self) -> bool {
self.objects.is_empty()
}
+18 -16
View File
@@ -58,6 +58,7 @@ const PLAYFIELD_BASE_SIZE: Pos2 = Pos2 { x: 512.0, y: 384.0 };
/// println!("Stars: {}", difficulty_attrs.stars);
/// ```
#[derive(Clone, Debug)]
#[must_use]
pub struct OsuStars<'map> {
pub(crate) map: &'map Beatmap,
pub(crate) mods: u32,
@@ -68,7 +69,7 @@ pub struct OsuStars<'map> {
impl<'map> OsuStars<'map> {
/// Create a new difficulty calculator for osu!standard maps.
#[inline]
pub fn new(map: &'map Beatmap) -> Self {
pub const fn new(map: &'map Beatmap) -> Self {
Self {
map,
mods: 0,
@@ -92,7 +93,7 @@ impl<'map> OsuStars<'map> {
///
/// See [https://github.com/ppy/osu-api/wiki#mods](https://github.com/ppy/osu-api/wiki#mods)
#[inline]
pub fn mods(mut self, mods: u32) -> Self {
pub const fn mods(mut self, mods: u32) -> Self {
self.mods = mods;
self
@@ -107,7 +108,7 @@ impl<'map> OsuStars<'map> {
[`OsuGradualDifficulty`]."
)]
#[inline]
pub fn passed_objects(mut self, passed_objects: usize) -> Self {
pub const fn passed_objects(mut self, passed_objects: usize) -> Self {
self.passed_objects = Some(passed_objects);
self
@@ -117,7 +118,7 @@ impl<'map> OsuStars<'map> {
/// 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.
#[inline]
pub fn clock_rate(mut self, clock_rate: f64) -> Self {
pub const fn clock_rate(mut self, clock_rate: f64) -> Self {
self.clock_rate = Some(clock_rate);
self
@@ -245,6 +246,7 @@ impl OsuStrains {
}
}
#[allow(clippy::needless_pass_by_value)]
fn calculate_skills(params: OsuStars<'_>) -> (Skills, OsuDifficultyAttributes) {
let OsuStars {
map,
@@ -260,7 +262,7 @@ fn calculate_skills(params: OsuStars<'_>) -> (Skills, OsuDifficultyAttributes) {
let scaling_factor = ScalingFactor::new(map_attrs.cs);
let hr = mods.hr();
let hit_window = 2.0 * map_attrs.hit_windows.od;
let time_preempt = (map_attrs.hit_windows.ar * clock_rate) as f32 as f64;
let time_preempt = f64::from((map_attrs.hit_windows.ar * clock_rate) as f32);
// * Preempt time can go below 450ms. Normally, this is achieved via the DT mod
// * which uniformly speeds up all animations game wide regardless of AR.
@@ -316,7 +318,7 @@ fn calculate_skills(params: OsuStars<'_>) -> (Skills, OsuDifficultyAttributes) {
let delta_time = (curr.start_time - last.start_time) / clock_rate;
// * Capped to 25ms to prevent difficulty calculation breaking from simultaneous objects.
let strain_time = delta_time.max(OsuDifficultyObject::MIN_DELTA_TIME as f64);
let strain_time = delta_time.max(f64::from(OsuDifficultyObject::MIN_DELTA_TIME));
let dists = Distances::new(
&mut curr,
@@ -389,7 +391,7 @@ pub(crate) fn create_osu_objects(
hit_objects.extend(iter.map(|h| OsuObject::new(h, &mut params)));
}
let stack_threshold = time_preempt * map.stack_leniency as f64;
let stack_threshold = time_preempt * f64::from(map.stack_leniency);
if map.version >= 6 {
stacking(&mut hit_objects, stack_threshold);
@@ -443,9 +445,9 @@ fn stacking(hit_objects: &mut [OsuObject], stack_threshold: f64) {
if hit_objects[n].is_spinner() {
continue;
} else if hit_objects[obj_i_idx].start_time - hit_objects[n].end_time()
> stack_threshold
{
}
if hit_objects[obj_i_idx].start_time - hit_objects[n].end_time() > stack_threshold {
break; // * We are no longer within stacking range of the previous object.
}
@@ -589,13 +591,13 @@ pub struct OsuDifficultyAttributes {
impl OsuDifficultyAttributes {
/// Return the maximum combo.
#[inline]
pub fn max_combo(&self) -> usize {
pub const fn max_combo(&self) -> usize {
self.max_combo
}
/// Return the amount of hitobjects.
#[inline]
pub fn n_objects(&self) -> usize {
pub const fn n_objects(&self) -> usize {
self.n_circles + self.n_sliders + self.n_spinners
}
@@ -628,24 +630,24 @@ pub struct OsuPerformanceAttributes {
impl OsuPerformanceAttributes {
/// Return the star value.
#[inline]
pub fn stars(&self) -> f64 {
pub const fn stars(&self) -> f64 {
self.difficulty.stars
}
/// Return the performance point value.
#[inline]
pub fn pp(&self) -> f64 {
pub const fn pp(&self) -> f64 {
self.pp
}
/// Return the maximum combo of the map.
#[inline]
pub fn max_combo(&self) -> usize {
pub const fn max_combo(&self) -> usize {
self.difficulty.max_combo
}
/// Return the amount of hitobjects.
#[inline]
pub fn n_objects(&self) -> usize {
pub const fn n_objects(&self) -> usize {
self.difficulty.n_objects()
}
}
+8 -6
View File
@@ -55,7 +55,7 @@ impl OsuSlider {
/// The amount of repeat points.
pub fn repeat_count(&self) -> usize {
self.nested_objects.iter().fold(0, |count, nested| {
count + matches!(nested.kind, NestedObjectKind::Repeat) as usize
count + usize::from(matches!(nested.kind, NestedObjectKind::Repeat))
})
}
@@ -120,6 +120,7 @@ pub(crate) struct ObjectParameters<'a> {
}
impl OsuObject {
#[allow(clippy::too_many_lines)]
pub(crate) fn new(h: &HitObject, params: &mut ObjectParameters<'_>) -> Self {
let ObjectParameters {
map,
@@ -195,6 +196,7 @@ impl OsuObject {
ticks.clear();
#[allow(clippy::if_not_else)]
let mut nested_objects = if tick_dist != 0.0 {
ticks.reserve((len / tick_dist) as usize);
let mut nested_objects =
@@ -221,7 +223,7 @@ impl OsuObject {
// Other spans
for span_idx in 1..=*repeats {
let progress = (span_idx % 2 == 1) as u8 as f64;
let progress = f64::from(u8::from(span_idx % 2 == 1));
let span_idx_f64 = span_idx as f64;
// Repeat point
@@ -269,7 +271,7 @@ impl OsuObject {
let final_span_end_time = (h.start_time + total_duration / 2.0)
.max(final_span_start_time + span_duration - LEGACY_LAST_TICK_OFFSET);
let progress = (*repeats % 2 == 0) as u8 as f64;
let progress = f64::from(u8::from(*repeats % 2 == 0));
let end_pos = curve.position_at(progress);
// * we need to use the LegacyLastTick here for compatibility reasons (difficulty).
@@ -347,7 +349,7 @@ impl OsuObject {
}
/// Endtime of the object.
pub fn end_time(&self) -> f64 {
pub const fn end_time(&self) -> f64 {
match &self.kind {
OsuObjectKind::Circle => self.start_time,
OsuObjectKind::Slider(slider) => slider.end_time,
@@ -445,7 +447,7 @@ impl OsuObject {
}
/// Applies stack offset, flips playfield for HR,
/// and adjusts slider tails and lazy_end_positions.
/// and adjusts slider tails and lazy end positions.
pub(crate) fn post_process(&mut self, hr: bool, scaling_factor: &ScalingFactor) {
self.stack_offset = scaling_factor.stack_offset(self.stack_height);
let pos = self.pos();
@@ -501,7 +503,7 @@ impl OsuObject {
}
if hr {
self.pos.y = PLAYFIELD_BASE_SIZE.y - pos.y
self.pos.y = PLAYFIELD_BASE_SIZE.y - pos.y;
}
}
}
+20 -15
View File
@@ -38,6 +38,7 @@ use crate::{
/// ```
#[derive(Clone, Debug)]
#[allow(clippy::upper_case_acronyms)]
#[must_use]
pub struct OsuPP<'map> {
pub(crate) map_or_attrs: MapOrElse<MapRef<'map>, OsuDifficultyAttributes>,
pub(crate) mods: u32,
@@ -104,7 +105,7 @@ impl<'map> OsuPP<'map> {
///
/// See [https://github.com/ppy/osu-api/wiki#mods](https://github.com/ppy/osu-api/wiki#mods)
#[inline]
pub fn mods(mut self, mods: u32) -> Self {
pub const fn mods(mut self, mods: u32) -> Self {
self.mods = mods;
self
@@ -112,7 +113,7 @@ impl<'map> OsuPP<'map> {
/// Specify the max combo of the play.
#[inline]
pub fn combo(mut self, combo: usize) -> Self {
pub const fn combo(mut self, combo: usize) -> Self {
self.combo = Some(combo);
self
@@ -122,7 +123,7 @@ impl<'map> OsuPP<'map> {
///
/// Defauls to [`HitResultPriority::BestCase`].
#[inline]
pub fn hitresult_priority(mut self, priority: HitResultPriority) -> Self {
pub const fn hitresult_priority(mut self, priority: HitResultPriority) -> Self {
self.hitresult_priority = Some(priority);
self
@@ -130,7 +131,7 @@ impl<'map> OsuPP<'map> {
/// Specify the amount of 300s of a play.
#[inline]
pub fn n300(mut self, n300: usize) -> Self {
pub const fn n300(mut self, n300: usize) -> Self {
self.n300 = Some(n300);
self
@@ -138,7 +139,7 @@ impl<'map> OsuPP<'map> {
/// Specify the amount of 100s of a play.
#[inline]
pub fn n100(mut self, n100: usize) -> Self {
pub const fn n100(mut self, n100: usize) -> Self {
self.n100 = Some(n100);
self
@@ -146,7 +147,7 @@ impl<'map> OsuPP<'map> {
/// Specify the amount of 50s of a play.
#[inline]
pub fn n50(mut self, n50: usize) -> Self {
pub const fn n50(mut self, n50: usize) -> Self {
self.n50 = Some(n50);
self
@@ -154,7 +155,7 @@ impl<'map> OsuPP<'map> {
/// Specify the amount of misses of a play.
#[inline]
pub fn n_misses(mut self, n_misses: usize) -> Self {
pub const fn n_misses(mut self, n_misses: usize) -> Self {
self.n_misses = Some(n_misses);
self
@@ -169,7 +170,7 @@ impl<'map> OsuPP<'map> {
[`OsuGradualPerformanceAttributes`](crate::osu::OsuGradualPerformance)."
)]
#[inline]
pub fn passed_objects(mut self, passed_objects: usize) -> Self {
pub const fn passed_objects(mut self, passed_objects: usize) -> Self {
self.passed_objects = Some(passed_objects);
self
@@ -179,7 +180,7 @@ impl<'map> OsuPP<'map> {
/// 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.
#[inline]
pub fn clock_rate(mut self, clock_rate: f64) -> Self {
pub const fn clock_rate(mut self, clock_rate: f64) -> Self {
self.clock_rate = Some(clock_rate);
self
@@ -187,7 +188,8 @@ impl<'map> OsuPP<'map> {
/// Provide parameters through an [`OsuScoreState`].
#[inline]
pub fn state(mut self, state: OsuScoreState) -> Self {
#[allow(clippy::needless_pass_by_value)]
pub const fn state(mut self, state: OsuScoreState) -> Self {
let OsuScoreState {
max_combo,
n300,
@@ -215,6 +217,7 @@ impl<'map> OsuPP<'map> {
}
/// Create the [`OsuScoreState`] that will be used for performance calculation.
#[allow(clippy::too_many_lines)]
pub fn generate_state(&mut self) -> OsuScoreState {
let attrs = match self.map_or_attrs {
MapOrElse::Map(ref map) => {
@@ -527,7 +530,7 @@ impl OsuPpInner {
let len_bonus = 0.95
+ 0.4 * (total_hits / 2000.0).min(1.0)
+ (total_hits > 2000.0) as u8 as f64 * (total_hits / 2000.0).log10() * 0.5;
+ f64::from(u8::from(total_hits > 2000.0)) * (total_hits / 2000.0).log10() * 0.5;
aim_value *= len_bonus;
@@ -594,7 +597,7 @@ impl OsuPpInner {
let len_bonus = 0.95
+ 0.4 * (total_hits / 2000.0).min(1.0)
+ (total_hits > 2000.0) as u8 as f64 * (total_hits / 2000.0).log10() * 0.5;
+ f64::from(u8::from(total_hits > 2000.0)) * (total_hits / 2000.0).log10() * 0.5;
speed_value *= len_bonus;
@@ -646,7 +649,7 @@ impl OsuPpInner {
// * Scale the speed value with # of 50s to punish doubletapping.
speed_value *= 0.99_f64.powf(
(self.state.n50 as f64 >= total_hits / 500.0) as u8 as f64
f64::from(u8::from(self.state.n50 as f64 >= total_hits / 500.0))
* (self.state.n50 as f64 - total_hits / 500.0),
);
@@ -718,7 +721,9 @@ impl OsuPpInner {
// * Account for shorter maps having a higher ratio of 0 combo/100 combo flashlight radius.
flashlight_value *= 0.7
+ 0.1 * (total_hits / 200.0).min(1.0)
+ (total_hits > 200.0) as u8 as f64 * 0.2 * ((total_hits - 200.0) / 200.0).min(1.0);
+ f64::from(u8::from(total_hits > 200.0))
* 0.2
* ((total_hits - 200.0) / 200.0).min(1.0);
// * Scale the flashlight value with accuracy _slightly_.
flashlight_value *= 0.5 + self.acc / 2.0;
@@ -737,7 +742,7 @@ impl OsuPpInner {
}
}
fn total_hits(&self) -> f64 {
const fn total_hits(&self) -> f64 {
self.state.total_hits() as f64
}
}
+1 -1
View File
@@ -24,7 +24,7 @@ impl OsuScoreState {
/// Return the total amount of hits by adding everything up.
#[inline]
pub fn total_hits(&self) -> usize {
pub const fn total_hits(&self) -> usize {
self.n300 + self.n100 + self.n50 + self.n_misses
}
+6 -9
View File
@@ -39,7 +39,7 @@ impl Skill for Aim {
curr: &OsuDifficultyObject<'_>,
diff_objects: &[OsuDifficultyObject<'_>],
) {
<Self as StrainSkill>::process(self, curr, diff_objects)
<Self as StrainSkill>::process(self, curr, diff_objects);
}
#[inline]
@@ -110,13 +110,10 @@ impl AimEvaluator {
) -> f64 {
let osu_curr_obj = curr;
let (osu_last_last_obj, osu_last_obj) = if let Some(tuple) =
previous(diff_objects, curr.idx, 1)
.zip(previous(diff_objects, curr.idx, 0))
.filter(|(_, last)| !(curr.base.is_spinner() || last.base.is_spinner()))
{
tuple
} else {
let Some((osu_last_last_obj, osu_last_obj)) = previous(diff_objects, curr.idx, 1)
.zip(previous(diff_objects, curr.idx, 0))
.filter(|(_, last)| !(curr.base.is_spinner() || last.base.is_spinner()))
else {
return 0.0;
};
@@ -234,7 +231,7 @@ impl AimEvaluator {
if osu_last_obj.base.is_slider() {
// * Reward sliders based on velocity.
slider_bonus = osu_last_obj.dists.travel_dist / osu_last_obj.dists.travel_time
slider_bonus = osu_last_obj.dists.travel_dist / osu_last_obj.dists.travel_time;
}
// * Add in acute angle bonus or wide angle bonus + velocity change bonus, whichever is larger.
+6 -5
View File
@@ -29,7 +29,7 @@ impl Flashlight {
curr_section_end: 0.0,
strain_peaks: CompactVec::new(),
has_hidden_mod: mods.hd(),
scaling_factor: 52.0 / radius as f64,
scaling_factor: 52.0 / f64::from(radius),
time_preempt,
time_fade_in,
}
@@ -47,7 +47,7 @@ impl Skill for Flashlight {
curr: &OsuDifficultyObject<'_>,
diff_objects: &[OsuDifficultyObject<'_>],
) {
<Self as StrainSkill>::process(self, curr, diff_objects)
<Self as StrainSkill>::process(self, curr, diff_objects);
}
#[inline]
@@ -155,8 +155,9 @@ impl FlashlightEvaluator {
let curr_hit_obj = curr_obj.base;
if !curr_obj.base.is_spinner() {
let jump_dist =
(osu_hit_obj.stacked_pos() - curr_hit_obj.stacked_end_pos()).length() as f64;
let jump_dist = f64::from(
(osu_hit_obj.stacked_pos() - curr_hit_obj.stacked_end_pos()).length(),
);
cumulative_strain_time += last_obj.strain_time;
// * We want to nerf objects that can be easily seen within the Flashlight circle radius.
@@ -210,7 +211,7 @@ impl FlashlightEvaluator {
if let OsuObjectKind::Slider(slider) = &osu_curr.base.kind {
// * Invert the scaling factor to determine the true travel distance independent of circle size.
let pixel_travel_dist = osu_curr.dists.lazy_travel_dist as f64 / scaling_factor;
let pixel_travel_dist = f64::from(osu_curr.dists.lazy_travel_dist) / scaling_factor;
// * Reward sliders based on velocity.
slider_bonus = ((pixel_travel_dist / osu_curr.dists.travel_time - Self::MIN_VELOCITY)
+13 -14
View File
@@ -56,7 +56,7 @@ impl Skill for Speed {
curr: &OsuDifficultyObject<'_>,
diff_objects: &[OsuDifficultyObject<'_>],
) {
<Self as StrainSkill>::process(self, curr, diff_objects)
<Self as StrainSkill>::process(self, curr, diff_objects);
}
#[inline]
@@ -210,7 +210,7 @@ impl RhythmEvaluator {
while previous(diff_objects, curr.idx, rhythm_start)
.filter(|prev| {
rhythm_start + 2 < historical_note_count
&& curr.start_time - prev.start_time < Self::HISTORY_TIME_MAX as f64
&& curr.start_time - prev.start_time < f64::from(Self::HISTORY_TIME_MAX)
})
.is_some()
{
@@ -218,20 +218,17 @@ impl RhythmEvaluator {
}
for i in (1..=rhythm_start).rev() {
let (curr_obj, prev_obj, last_obj) = if let Some(((curr, prev), last)) =
previous(diff_objects, curr.idx, i - 1)
.zip(previous(diff_objects, curr.idx, i))
.zip(previous(diff_objects, curr.idx, i + 1))
{
(curr, prev, last)
} else {
let Some(((curr_obj, prev_obj), last_obj)) = previous(diff_objects, curr.idx, i - 1)
.zip(previous(diff_objects, curr.idx, i))
.zip(previous(diff_objects, curr.idx, i + 1))
else {
break;
};
// * scales note 0 to 1 from history to now
let mut curr_historical_decay = (Self::HISTORY_TIME_MAX as f64
let mut curr_historical_decay = (f64::from(Self::HISTORY_TIME_MAX)
- (curr.start_time - curr_obj.start_time))
/ Self::HISTORY_TIME_MAX as f64;
/ f64::from(Self::HISTORY_TIME_MAX);
// * either we're limited by time or limited by object count.
curr_historical_decay = curr_historical_decay
@@ -245,7 +242,7 @@ impl RhythmEvaluator {
let base = (PI / (prev_delta.min(curr_delta) / prev_delta.max(curr_delta))).sin();
let curr_ratio = 1.0 + 6.0 * (base * base).min(0.5);
let hit_window = !curr_obj.base.is_spinner() as u64 as f64 * hit_window;
let hit_window = u64::from(!curr_obj.base.is_spinner()) as f64 * hit_window;
let mut window_penalty = ((((prev_delta - curr_delta).abs() - hit_window * 0.3)
.max(0.0))
@@ -257,6 +254,8 @@ impl RhythmEvaluator {
let mut effective_ratio = window_penalty * curr_ratio;
if first_delta_switch {
// Keep in-sync with lazer
#[allow(clippy::if_not_else)]
if !(prev_delta > 1.25 * curr_delta || prev_delta * 1.25 < curr_delta) {
if island_size < 7 {
// * island is still progressing, count size.
@@ -290,9 +289,9 @@ impl RhythmEvaluator {
rhythm_complexity_sum += (effective_ratio * start_ratio).sqrt()
* curr_historical_decay
* ((4 + island_size) as f64).sqrt()
* f64::from(4 + island_size).sqrt()
/ 2.0
* ((4 + prev_island_size) as f64).sqrt()
* f64::from(4 + prev_island_size).sqrt()
/ 2.0;
start_ratio = effective_ratio;
+2 -1
View File
@@ -125,7 +125,8 @@ pub(crate) trait OsuStrainSkill: StrainSkill + Sized {
// * We are reducing the highest strains first to account for extreme difficulty spikes
for (i, strain) in peak_iter.enumerate() {
let clamped = (i as f32 / Self::REDUCED_SECTION_COUNT as f32).clamp(0.0, 1.0) as f64;
let clamped =
f64::from((i as f32 / Self::REDUCED_SECTION_COUNT as f32).clamp(0.0, 1.0));
let scale = (lerp(1.0, 10.0, clamped)).log10();
*strain *= lerp(Self::REDUCED_STRAIN_BASELINE, 1.0, scale);
}