feat: adjusted lint restrictions (#31)
This commit is contained in:
@@ -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 {
|
||||
|
||||
@@ -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
@@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user