recoded and added rhythm complexity calculator (untested)

This commit is contained in:
MaxOhn
2021-10-28 19:15:20 +02:00
parent 9ca4ec7de4
commit 6d1676762b
2 changed files with 90 additions and 5 deletions
@@ -193,6 +193,11 @@ impl OsuObject {
}
}
#[inline]
pub(crate) fn is_slider(&self) -> bool {
matches!(self.kind, OsuObjectKind::Slider { .. })
}
#[inline]
pub(crate) fn is_spinner(&self) -> bool {
matches!(self.kind, OsuObjectKind::Spinner)
+85 -5
View File
@@ -27,12 +27,21 @@ const AIM_DIFFICULTY_MULTIPLIER: f32 = 1.06;
const FLASHLIGHT_DIFFICULTY_MULTIPLIER: f32 = 1.06;
const SPEED_DIFFICULTY_MULTIPLIER: f32 = 1.04;
const SPEED_HISTORY_TIME_MAX: f32 = 4.0;
const SPEED_RHYTHM_MULTIPLIER: f32 = 1.0;
pub(crate) struct FlashlightHistoryEntry {
is_spinner: bool,
end_pos: Pos2,
strain_time: f32,
}
pub(crate) struct SpeedHistoryEntry {
is_slider: bool,
start_time: f32,
strain_time: f32,
}
pub(crate) enum SkillKind {
Aim,
Flashlight {
@@ -40,7 +49,7 @@ pub(crate) enum SkillKind {
scaling_factor: f32,
},
Speed {
history: VecDeque<()>,
history: VecDeque<SpeedHistoryEntry>,
},
}
@@ -78,7 +87,15 @@ impl SkillKind {
history.push_front(entry);
}
Self::Speed { history } => {}
Self::Speed { history } => {
let entry = SpeedHistoryEntry {
is_slider: current.base.is_slider(),
start_time: current.base.time,
strain_time: current.strain_time,
};
history.push_front(entry);
}
}
}
@@ -156,7 +173,7 @@ impl SkillKind {
result * result
}
Self::Speed { history } => {
Self::Speed { .. } => {
if current.base.is_spinner() {
return 0.0;
}
@@ -201,11 +218,13 @@ impl SkillKind {
pub(crate) fn total_current_strain(
&self,
current_strain: f32,
_current: &DifficultyObject,
current: &DifficultyObject,
) -> f32 {
match self {
SkillKind::Aim | SkillKind::Flashlight { .. } => current_strain,
SkillKind::Speed { history } => current_strain * 1.0,
SkillKind::Speed { history } => {
current_strain * calculate_speed_rhythm_bonus(history, current.base.time)
}
}
}
@@ -222,7 +241,68 @@ impl SkillKind {
}
}
fn calculate_speed_rhythm_bonus(history: &VecDeque<SpeedHistoryEntry>, start_time: f32) -> f32 {
let mut previous_island_size = usize::MAX;
let mut island_times = [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0];
let mut island_size = 0;
let mut first_delta_switch = false;
for (prev, curr) in history.iter().skip(1).zip(history) {
let prev_delta = prev.strain_time;
let curr_delta = curr.strain_time;
let mut effective_ratio = prev_delta.min(curr_delta) / prev_delta.max(curr_delta);
let curr_historical_decay = (SPEED_HISTORY_TIME_MAX - (start_time - curr.start_time))
.max(0.0)
/ SPEED_HISTORY_TIME_MAX;
if first_delta_switch {
if is_ratio_equal(1.0, prev_delta, curr_delta) {
island_size += 1;
} else {
if island_size > 6 {
island_size = 6;
}
if curr.is_slider {
effective_ratio /= 2.0;
}
if prev.is_slider {
effective_ratio *= 0.75;
}
if previous_island_size == island_size {
effective_ratio /= 0.5;
}
island_times[island_size] += effective_ratio * curr_historical_decay;
previous_island_size = island_size;
if prev_delta * 1.25 < curr_delta {
first_delta_switch = false;
}
island_size = 6;
}
} else if prev_delta > 1.25 * curr_delta {
first_delta_switch = true;
island_size = 0;
}
}
let rhythm_complexity_sum: f32 = island_times.iter().sum();
((4.0 + rhythm_complexity_sum * SPEED_RHYTHM_MULTIPLIER).sqrt() / 2.0).min(1.5)
}
#[inline]
fn apply_diminishing_exp(val: f32) -> f32 {
val.powf(0.99)
}
#[inline]
fn is_ratio_equal(ratio: f32, a: f32, b: f32) -> bool {
a + 15.0 > ratio * b && a - 15.0 < ratio * b
}