osu: finished all_included version

This commit is contained in:
MaxOhn
2021-01-26 18:01:47 +01:00
parent 7d8653d57d
commit 07bf677982
6 changed files with 85 additions and 32 deletions
@@ -24,9 +24,9 @@ impl<'h> DifficultyObject<'h> {
let delta = (base.time - prev.time) / clock_rate;
let strain_time = delta.max(50.0);
let pos = base.pos;
let pos = base.pos; // stacked position
let travel_dist = prev.travel_dist();
let prev_cursor_pos = prev.end_pos();
let prev_cursor_pos = prev.lazy_end_pos();
let jump_dist = if base.is_spinner() {
0.0
@@ -35,9 +35,9 @@ impl<'h> DifficultyObject<'h> {
};
let angle = prev_prev.map(|prev_prev| {
let prev_prev_cursor_pos = prev_prev.end_pos();
let prev_prev_cursor_pos = prev_prev.lazy_end_pos();
let v1 = prev_prev_cursor_pos - prev_cursor_pos;
let v1 = prev_prev_cursor_pos - prev.pos;
let v2 = pos - prev_cursor_pos;
let dot = v1.dot(v2);
+45 -14
View File
@@ -25,7 +25,6 @@ const OBJECT_RADIUS: f32 = 64.0;
const SECTION_LEN: f32 = 400.0;
const DIFFICULTY_MULTIPLIER: f32 = 0.0675;
const NORMALIZED_RADIUS: f32 = 52.0;
const TIME_PREEMPT: f32 = 600.0; // TODO: Check mod influences
const STACK_DISTANCE: f32 = 3.0;
/// Star calculation for osu!standard maps.
@@ -53,6 +52,16 @@ pub fn stars(map: &Beatmap, mods: impl Mods, passed_objects: Option<usize>) -> S
return StarResult::Osu(diff_attributes);
}
let mut raw_ar = map.ar;
if mods.hr() {
raw_ar *= 1.4;
} else if mods.ez() {
raw_ar *= 0.5;
}
let time_preempt = difficulty_range_ar(raw_ar);
let section_len = SECTION_LEN * map_attributes.clock_rate;
let scale = (1.0 - 0.7 * (map_attributes.cs - 5.0) / 5.0) / 2.0;
let radius = OBJECT_RADIUS * scale;
@@ -75,6 +84,7 @@ pub fn stars(map: &Beatmap, mods: impl Mods, passed_objects: Option<usize>) -> S
h,
map,
radius,
scaling_factor,
&mut ticks_buf,
&mut diff_attributes,
&mut slider_state,
@@ -82,10 +92,12 @@ pub fn stars(map: &Beatmap, mods: impl Mods, passed_objects: Option<usize>) -> S
})
.collect();
let stack_threshold = time_preempt * map.stack_leniency;
if map.version >= 6 {
stacking(&mut hit_objects, map.stack_leniency, TIME_PREEMPT);
stacking(&mut hit_objects, stack_threshold);
} else {
old_stacking(&mut hit_objects, map.stack_leniency, TIME_PREEMPT);
old_stacking(&mut hit_objects, stack_threshold);
}
let mut hit_objects = hit_objects.into_iter().map(|mut h| {
@@ -194,6 +206,16 @@ pub fn strains(map: &Beatmap, mods: impl Mods) -> Strains {
return Strains::default();
}
let mut raw_ar = map.ar;
if mods.hr() {
raw_ar *= 1.4;
} else if mods.ez() {
raw_ar *= 0.5;
}
let time_preempt = difficulty_range_ar(raw_ar);
let section_len = SECTION_LEN * map_attributes.clock_rate;
let scale = (1.0 - 0.7 * (map_attributes.cs - 5.0) / 5.0) / 2.0;
let radius = OBJECT_RADIUS * scale;
@@ -215,6 +237,7 @@ pub fn strains(map: &Beatmap, mods: impl Mods) -> Strains {
h,
map,
radius,
scaling_factor,
&mut ticks_buf,
&mut diff_attributes,
&mut slider_state,
@@ -222,10 +245,12 @@ pub fn strains(map: &Beatmap, mods: impl Mods) -> Strains {
})
.collect();
let stack_threshold = time_preempt * map.stack_leniency;
if map.version >= 6 {
stacking(&mut hit_objects, map.stack_leniency, TIME_PREEMPT);
stacking(&mut hit_objects, stack_threshold);
} else {
old_stacking(&mut hit_objects, map.stack_leniency, TIME_PREEMPT);
old_stacking(&mut hit_objects, stack_threshold);
}
let mut hit_objects = hit_objects.into_iter().map(|mut h| {
@@ -316,12 +341,10 @@ pub fn strains(map: &Beatmap, mods: impl Mods) -> Strains {
}
}
fn stacking(hit_objects: &mut [OsuObject], stack_leniency: f32, time_preempt: f32) {
fn stacking(hit_objects: &mut [OsuObject], stack_threshold: f32) {
let mut extended_start_idx = 0;
let extended_end_idx = hit_objects.len() - 1;
let stack_threshold = time_preempt * stack_leniency; // TODO: Calculate outside?
for mut i in (1..=extended_end_idx).rev() {
let mut n = i;
@@ -380,16 +403,15 @@ fn stacking(hit_objects: &mut [OsuObject], stack_leniency: f32, time_preempt: f3
}
}
fn old_stacking(hit_objects: &mut [OsuObject], stack_leniency: f32, time_preempt: f32) {
let stack_threshold = time_preempt * stack_leniency; // TODO: Calculate outside?
fn old_stacking(hit_objects: &mut [OsuObject], stack_threshold: f32) {
for i in 0..hit_objects.len() {
if hit_objects[i].stack_height != 0.0 && !hit_objects[i].is_slider() {
continue;
}
let mut start_time = hit_objects[i].end_time();
let end_pos = hit_objects[i].end_pos(); // FIXME: Wrong for sliders? Position at 100% progress.
let end_pos = hit_objects[i].end_pos();
let mut slider_stack = 0.0;
for j in i + 1..hit_objects.len() {
@@ -409,6 +431,15 @@ fn old_stacking(hit_objects: &mut [OsuObject], stack_leniency: f32, time_preempt
}
}
const OSU_AR_MAX: f32 = 450.0;
const OSU_AR_AVG: f32 = 1200.0;
const OSU_AR_MIN: f32 = 1800.0;
#[inline]
fn difficulty_range_ar(ar: f32) -> f32 {
crate::difficulty_range(ar, OSU_AR_MAX, OSU_AR_AVG, OSU_AR_MIN)
}
#[cfg(test)]
mod tests {
use super::super::super::OsuPP;
@@ -416,9 +447,9 @@ mod tests {
use std::fs::File;
#[test]
#[ignore]
// #[ignore]
fn all_included_single() {
let file = match File::open("./maps/295.osu") {
let file = match File::open("./maps/2514909.osu") {
Ok(file) => file,
Err(why) => panic!("Could not open file: {}", why),
};
+18 -3
View File
@@ -17,6 +17,7 @@ enum OsuObjectKind {
Slider {
end_time: f32,
end_pos: Pos2,
lazy_end_pos: Pos2,
travel_dist: f32,
},
Spinner {
@@ -29,6 +30,7 @@ impl OsuObject {
h: &HitObject,
map: &Beatmap,
radius: f32,
scaling_factor: f32,
ticks: &mut Vec<f32>,
attributes: &mut DifficultyAttributes,
slider_state: &mut SliderState,
@@ -54,7 +56,7 @@ impl OsuObject {
path_type,
} => {
// Key values which are computed here
let mut end_pos = h.pos;
let mut lazy_end_pos = h.pos;
let mut travel_dist = 0.0;
// Responsible for timing point values
@@ -107,12 +109,12 @@ impl OsuObject {
let curr_dist = pixel_len * progress;
let curr_pos = curve.point_at_distance(curr_dist);
let diff = curr_pos - end_pos;
let diff = curr_pos - lazy_end_pos;
let mut dist = diff.length();
if dist > approx_follow_circle_radius {
dist -= approx_follow_circle_radius;
end_pos += diff.normalize() * dist;
lazy_end_pos += diff.normalize() * dist;
travel_dist += dist;
}
};
@@ -163,6 +165,10 @@ impl OsuObject {
ticks.clear();
travel_dist *= scaling_factor;
let end_pos = curve.point_at_distance(*pixel_len);
Self {
time: h.start_time,
pos: h.pos,
@@ -170,6 +176,7 @@ impl OsuObject {
kind: OsuObjectKind::Slider {
end_time: final_span_end_time,
end_pos,
lazy_end_pos,
travel_dist,
},
}
@@ -217,6 +224,14 @@ impl OsuObject {
}
}
#[inline]
pub(crate) fn lazy_end_pos(&self) -> Pos2 {
match &self.kind {
OsuObjectKind::Circle | OsuObjectKind::Spinner { .. } => self.pos,
OsuObjectKind::Slider { lazy_end_pos, .. } => *lazy_end_pos,
}
}
#[inline]
pub(crate) fn is_circle(&self) -> bool {
matches!(self.kind, OsuObjectKind::Circle)
+3 -1
View File
@@ -68,6 +68,7 @@ pub fn stars(map: &Beatmap, mods: impl Mods, passed_objects: Option<usize>) -> S
h,
map,
radius,
scaling_factor,
&mut ticks_buf,
&mut diff_attributes,
&mut slider_state,
@@ -186,6 +187,7 @@ pub fn strains(map: &Beatmap, mods: impl Mods) -> Strains {
h,
map,
radius,
scaling_factor,
&mut ticks_buf,
&mut diff_attributes,
&mut slider_state,
@@ -278,7 +280,7 @@ mod tests {
#[test]
#[ignore]
fn no_leniency_single() {
let file = match File::open("./maps/295.osu") {
let file = match File::open("./maps/2514909.osu") {
Ok(file) => file,
Err(why) => panic!("Could not open file: {}", why),
};
@@ -18,6 +18,7 @@ impl OsuObject {
h: &HitObject,
map: &Beatmap,
radius: f32,
scaling_factor: f32,
ticks: &mut Vec<f32>,
attributes: &mut DifficultyAttributes,
slider_state: &mut SliderState,
@@ -151,6 +152,8 @@ impl OsuObject {
ticks.clear();
travel_dist *= scaling_factor;
Self {
time: h.start_time,
pos: h.pos,
+12 -10
View File
@@ -14,12 +14,14 @@ struct MapResult {
#[test]
fn osu() {
let margin = if cfg!(feature = "no_leniency") {
0.0025
} else if cfg!(feature = "no_sliders_no_leniency") {
let margin = if cfg!(feature = "no_sliders_no_leniency") {
0.0075
} else {
} else if cfg!(feature = "no_leniency") {
0.0025
} else if cfg!(feature = "all_included") {
0.001
} else {
unreachable!()
};
let star_margin = margin;
@@ -48,9 +50,9 @@ fn osu() {
assert!(
(result.stars() - stars).abs() < star_margin * stars,
"\nStars:\n\
Calculated: {calculated} | Expected: {expected}\n \
=> {margin} margin ({allowed} allowed)\n\
[map {map} | mods {mods}]\n",
Calculated: {calculated} | Expected: {expected}\n \
=> {margin} margin ({allowed} allowed)\n\
[map {map} | mods {mods}]\n",
calculated = result.stars(),
expected = stars,
margin = (result.stars() - stars).abs(),
@@ -62,9 +64,9 @@ fn osu() {
assert!(
(result.pp() - pp).abs() < pp_margin * pp,
"\nPP:\n\
Calculated: {calculated} | Expected: {expected}\n \
=> {margin} margin ({allowed} allowed)\n\
[map {map} | mods {mods}]\n",
Calculated: {calculated} | Expected: {expected}\n \
=> {margin} margin ({allowed} allowed)\n\
[map {map} | mods {mods}]\n",
calculated = result.pp(),
expected = pp,
margin = (result.pp() - pp).abs(),