adjust osu skill structure to taiko & mania
This commit is contained in:
+6
-114
@@ -1,120 +1,12 @@
|
|||||||
use std::{cmp::Ordering, mem};
|
|
||||||
|
|
||||||
use super::{difficulty_object::ManiaDifficultyObject, SECTION_LEN};
|
|
||||||
|
|
||||||
pub(crate) use self::strain::Strain;
|
|
||||||
|
|
||||||
mod strain;
|
mod strain;
|
||||||
|
mod traits;
|
||||||
|
|
||||||
pub(crate) trait Skill {
|
pub(crate) use self::{
|
||||||
fn process(&mut self, curr: &ManiaDifficultyObject, diff_objects: &[ManiaDifficultyObject]);
|
strain::Strain,
|
||||||
fn difficulty_value(self) -> f64;
|
traits::{Skill, StrainDecaySkill, StrainSkill},
|
||||||
}
|
};
|
||||||
|
|
||||||
pub(crate) trait StrainSkill: Sized + Skill {
|
use super::difficulty_object::ManiaDifficultyObject;
|
||||||
const DECAY_WEIGHT: f64 = 0.9;
|
|
||||||
|
|
||||||
fn curr_section_end(&self) -> f64;
|
|
||||||
fn curr_section_end_mut(&mut self) -> &mut f64;
|
|
||||||
|
|
||||||
fn curr_section_peak(&self) -> f64;
|
|
||||||
fn curr_section_peak_mut(&mut self) -> &mut f64;
|
|
||||||
|
|
||||||
fn strain_peaks_mut(&mut self) -> &mut Vec<f64>;
|
|
||||||
|
|
||||||
fn strain_value_at(&mut self, curr: &ManiaDifficultyObject) -> f64;
|
|
||||||
|
|
||||||
fn process(&mut self, curr: &ManiaDifficultyObject, diff_objects: &[ManiaDifficultyObject]) {
|
|
||||||
// * The first object doesn't generate a strain, so we begin with an incremented section end
|
|
||||||
if curr.idx == 0 {
|
|
||||||
*self.curr_section_end_mut() = (curr.start_time / SECTION_LEN).ceil() * SECTION_LEN;
|
|
||||||
}
|
|
||||||
|
|
||||||
while curr.start_time > self.curr_section_end() {
|
|
||||||
self.save_curr_peak();
|
|
||||||
self.start_new_section_from(self.curr_section_end(), curr, diff_objects);
|
|
||||||
*self.curr_section_end_mut() += SECTION_LEN;
|
|
||||||
}
|
|
||||||
|
|
||||||
*self.curr_section_peak_mut() = self.strain_value_at(curr).max(self.curr_section_peak());
|
|
||||||
}
|
|
||||||
|
|
||||||
fn save_curr_peak(&mut self) {
|
|
||||||
let curr_section_peak = self.curr_section_peak();
|
|
||||||
self.strain_peaks_mut().push(curr_section_peak);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn start_new_section_from(
|
|
||||||
&mut self,
|
|
||||||
time: f64,
|
|
||||||
curr: &ManiaDifficultyObject,
|
|
||||||
diff_objects: &[ManiaDifficultyObject],
|
|
||||||
) {
|
|
||||||
*self.curr_section_peak_mut() = self.calculate_initial_strain(time, curr, diff_objects);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn calculate_initial_strain(
|
|
||||||
&self,
|
|
||||||
time: f64,
|
|
||||||
curr: &ManiaDifficultyObject,
|
|
||||||
diff_objects: &[ManiaDifficultyObject],
|
|
||||||
) -> f64;
|
|
||||||
|
|
||||||
fn get_curr_strain_peaks(mut self) -> Vec<f64> {
|
|
||||||
let mut peaks = mem::take(self.strain_peaks_mut());
|
|
||||||
peaks.push(self.curr_section_peak());
|
|
||||||
|
|
||||||
peaks
|
|
||||||
}
|
|
||||||
|
|
||||||
fn difficulty_value(self) -> f64 {
|
|
||||||
let mut difficulty = 0.0;
|
|
||||||
let mut weight = 1.0;
|
|
||||||
|
|
||||||
// * Sections with 0 strain are excluded to avoid worst-case time complexity of the following sort (e.g. /b/2351871).
|
|
||||||
// * These sections will not contribute to the difficulty.
|
|
||||||
let mut peaks = self.get_curr_strain_peaks();
|
|
||||||
peaks.retain(|&peak| peak > 0.0);
|
|
||||||
peaks.sort_unstable_by(|a, b| b.partial_cmp(a).unwrap_or(Ordering::Equal));
|
|
||||||
|
|
||||||
// * Difficulty is the weighted sum of the highest strains from every section.
|
|
||||||
// * We're sorting from highest to lowest strain.
|
|
||||||
for strain in peaks {
|
|
||||||
difficulty += strain * weight;
|
|
||||||
weight *= Self::DECAY_WEIGHT;
|
|
||||||
}
|
|
||||||
|
|
||||||
difficulty
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) trait StrainDecaySkill: StrainSkill {
|
|
||||||
const SKILL_MULTIPLIER: f64;
|
|
||||||
const STRAIN_DECAY_BASE: f64;
|
|
||||||
|
|
||||||
fn curr_strain(&self) -> f64;
|
|
||||||
fn curr_strain_mut(&mut self) -> &mut f64;
|
|
||||||
|
|
||||||
fn strain_value_of(&mut self, curr: &ManiaDifficultyObject) -> f64;
|
|
||||||
|
|
||||||
fn calculate_initial_strain(
|
|
||||||
&self,
|
|
||||||
time: f64,
|
|
||||||
curr: &ManiaDifficultyObject,
|
|
||||||
diff_objects: &[ManiaDifficultyObject],
|
|
||||||
) -> f64;
|
|
||||||
|
|
||||||
fn strain_value_at(&mut self, curr: &ManiaDifficultyObject) -> f64 {
|
|
||||||
*self.curr_strain_mut() *= self.strain_decay(curr.delta_time);
|
|
||||||
*self.curr_strain_mut() += self.strain_value_of(curr) * Self::SKILL_MULTIPLIER;
|
|
||||||
|
|
||||||
self.curr_strain()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn strain_decay(&self, ms: f64) -> f64 {
|
|
||||||
Self::STRAIN_DECAY_BASE.powf(ms / 1000.0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn previous(
|
fn previous(
|
||||||
diff_objects: &[ManiaDifficultyObject],
|
diff_objects: &[ManiaDifficultyObject],
|
||||||
|
|||||||
@@ -0,0 +1,113 @@
|
|||||||
|
use std::{cmp::Ordering, mem};
|
||||||
|
|
||||||
|
use crate::mania::{difficulty_object::ManiaDifficultyObject, SECTION_LEN};
|
||||||
|
|
||||||
|
pub(crate) trait Skill {
|
||||||
|
fn process(&mut self, curr: &ManiaDifficultyObject, diff_objects: &[ManiaDifficultyObject]);
|
||||||
|
fn difficulty_value(self) -> f64;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) trait StrainSkill: Sized + Skill {
|
||||||
|
const DECAY_WEIGHT: f64 = 0.9;
|
||||||
|
|
||||||
|
fn curr_section_end(&self) -> f64;
|
||||||
|
fn curr_section_end_mut(&mut self) -> &mut f64;
|
||||||
|
|
||||||
|
fn curr_section_peak(&self) -> f64;
|
||||||
|
fn curr_section_peak_mut(&mut self) -> &mut f64;
|
||||||
|
|
||||||
|
fn strain_peaks_mut(&mut self) -> &mut Vec<f64>;
|
||||||
|
|
||||||
|
fn strain_value_at(&mut self, curr: &ManiaDifficultyObject) -> f64;
|
||||||
|
|
||||||
|
fn process(&mut self, curr: &ManiaDifficultyObject, diff_objects: &[ManiaDifficultyObject]) {
|
||||||
|
// * The first object doesn't generate a strain, so we begin with an incremented section end
|
||||||
|
if curr.idx == 0 {
|
||||||
|
*self.curr_section_end_mut() = (curr.start_time / SECTION_LEN).ceil() * SECTION_LEN;
|
||||||
|
}
|
||||||
|
|
||||||
|
while curr.start_time > self.curr_section_end() {
|
||||||
|
self.save_curr_peak();
|
||||||
|
self.start_new_section_from(self.curr_section_end(), curr, diff_objects);
|
||||||
|
*self.curr_section_end_mut() += SECTION_LEN;
|
||||||
|
}
|
||||||
|
|
||||||
|
*self.curr_section_peak_mut() = self.strain_value_at(curr).max(self.curr_section_peak());
|
||||||
|
}
|
||||||
|
|
||||||
|
fn save_curr_peak(&mut self) {
|
||||||
|
let curr_section_peak = self.curr_section_peak();
|
||||||
|
self.strain_peaks_mut().push(curr_section_peak);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn start_new_section_from(
|
||||||
|
&mut self,
|
||||||
|
time: f64,
|
||||||
|
curr: &ManiaDifficultyObject,
|
||||||
|
diff_objects: &[ManiaDifficultyObject],
|
||||||
|
) {
|
||||||
|
*self.curr_section_peak_mut() = self.calculate_initial_strain(time, curr, diff_objects);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn calculate_initial_strain(
|
||||||
|
&self,
|
||||||
|
time: f64,
|
||||||
|
curr: &ManiaDifficultyObject,
|
||||||
|
diff_objects: &[ManiaDifficultyObject],
|
||||||
|
) -> f64;
|
||||||
|
|
||||||
|
fn get_curr_strain_peaks(mut self) -> Vec<f64> {
|
||||||
|
let mut peaks = mem::take(self.strain_peaks_mut());
|
||||||
|
peaks.push(self.curr_section_peak());
|
||||||
|
|
||||||
|
peaks
|
||||||
|
}
|
||||||
|
|
||||||
|
fn difficulty_value(self) -> f64 {
|
||||||
|
let mut difficulty = 0.0;
|
||||||
|
let mut weight = 1.0;
|
||||||
|
|
||||||
|
// * Sections with 0 strain are excluded to avoid worst-case time complexity of the following sort (e.g. /b/2351871).
|
||||||
|
// * These sections will not contribute to the difficulty.
|
||||||
|
let mut peaks = self.get_curr_strain_peaks();
|
||||||
|
peaks.retain(|&peak| peak > 0.0);
|
||||||
|
peaks.sort_unstable_by(|a, b| b.partial_cmp(a).unwrap_or(Ordering::Equal));
|
||||||
|
|
||||||
|
// * Difficulty is the weighted sum of the highest strains from every section.
|
||||||
|
// * We're sorting from highest to lowest strain.
|
||||||
|
for strain in peaks {
|
||||||
|
difficulty += strain * weight;
|
||||||
|
weight *= Self::DECAY_WEIGHT;
|
||||||
|
}
|
||||||
|
|
||||||
|
difficulty
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) trait StrainDecaySkill: StrainSkill {
|
||||||
|
const SKILL_MULTIPLIER: f64;
|
||||||
|
const STRAIN_DECAY_BASE: f64;
|
||||||
|
|
||||||
|
fn curr_strain(&self) -> f64;
|
||||||
|
fn curr_strain_mut(&mut self) -> &mut f64;
|
||||||
|
|
||||||
|
fn strain_value_of(&mut self, curr: &ManiaDifficultyObject) -> f64;
|
||||||
|
|
||||||
|
fn calculate_initial_strain(
|
||||||
|
&self,
|
||||||
|
time: f64,
|
||||||
|
curr: &ManiaDifficultyObject,
|
||||||
|
diff_objects: &[ManiaDifficultyObject],
|
||||||
|
) -> f64;
|
||||||
|
|
||||||
|
fn strain_value_at(&mut self, curr: &ManiaDifficultyObject) -> f64 {
|
||||||
|
*self.curr_strain_mut() *= self.strain_decay(curr.delta_time);
|
||||||
|
*self.curr_strain_mut() += self.strain_value_of(curr) * Self::SKILL_MULTIPLIER;
|
||||||
|
|
||||||
|
self.curr_strain()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn strain_decay(&self, ms: f64) -> f64 {
|
||||||
|
Self::STRAIN_DECAY_BASE.powf(ms / 1000.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
+4
-119
@@ -2,124 +2,9 @@ mod colour;
|
|||||||
mod peaks;
|
mod peaks;
|
||||||
mod rhythm;
|
mod rhythm;
|
||||||
mod stamina;
|
mod stamina;
|
||||||
|
mod traits;
|
||||||
|
|
||||||
use std::{cmp::Ordering, mem};
|
pub(crate) use self::{
|
||||||
|
peaks::{Peaks, PeaksDifficultyValues, PeaksRaw},
|
||||||
pub(crate) use self::peaks::{Peaks, PeaksDifficultyValues, PeaksRaw};
|
traits::{Skill, StrainDecaySkill, StrainSkill},
|
||||||
|
|
||||||
use super::{
|
|
||||||
difficulty_object::{ObjectLists, TaikoDifficultyObject},
|
|
||||||
SECTION_LEN,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
pub(crate) trait Skill: Sized {
|
|
||||||
fn process(&mut self, curr: &TaikoDifficultyObject, hit_objects: &ObjectLists);
|
|
||||||
fn difficulty_value(self) -> f64;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) trait StrainSkill: Skill {
|
|
||||||
const DECAY_WEIGHT: f64 = 0.9;
|
|
||||||
|
|
||||||
fn strain_peaks_mut(&mut self) -> &mut Vec<f64>;
|
|
||||||
fn curr_section_peak(&mut self) -> &mut f64;
|
|
||||||
fn curr_section_end(&mut self) -> &mut f64;
|
|
||||||
|
|
||||||
fn strain_value_at(&mut self, curr: &TaikoDifficultyObject, hit_objects: &ObjectLists) -> f64;
|
|
||||||
|
|
||||||
fn calculate_initial_strain(&self, time: f64, curr: &TaikoDifficultyObject) -> f64;
|
|
||||||
|
|
||||||
fn process(&mut self, curr: &TaikoDifficultyObject, hit_objects: &ObjectLists) {
|
|
||||||
// * The first object doesn't generate a strain, so we begin with an incremented section end
|
|
||||||
if curr.idx == 0 {
|
|
||||||
let section_len = SECTION_LEN as f64;
|
|
||||||
*self.curr_section_end() = (curr.start_time / section_len).ceil() * section_len;
|
|
||||||
}
|
|
||||||
|
|
||||||
while curr.start_time > *self.curr_section_end() {
|
|
||||||
self.save_curr_peak();
|
|
||||||
|
|
||||||
{
|
|
||||||
let section_end = *self.curr_section_end();
|
|
||||||
self.start_new_section_from(section_end, curr);
|
|
||||||
}
|
|
||||||
|
|
||||||
*self.curr_section_end() += SECTION_LEN as f64;
|
|
||||||
}
|
|
||||||
|
|
||||||
*self.curr_section_peak() = self
|
|
||||||
.strain_value_at(curr, hit_objects)
|
|
||||||
.max(*self.curr_section_peak());
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn save_curr_peak(&mut self) {
|
|
||||||
let peak = *self.curr_section_peak();
|
|
||||||
self.strain_peaks_mut().push(peak);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn start_new_section_from(&mut self, time: f64, curr: &TaikoDifficultyObject) {
|
|
||||||
// * The maximum strain of the new section is not zero by default
|
|
||||||
// * This means we need to capture the strain level at the beginning of the new section,
|
|
||||||
// * and use that as the initial peak level.
|
|
||||||
*self.curr_section_peak() = self.calculate_initial_strain(time, curr);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn difficulty_value(self) -> f64 {
|
|
||||||
let mut difficulty = 0.0;
|
|
||||||
let mut weight = 1.0;
|
|
||||||
|
|
||||||
// * Sections with 0 strain are excluded to avoid worst-case time complexity of the following sort (e.g. /b/2351871).
|
|
||||||
// * These sections will not contribute to the difficulty.
|
|
||||||
let mut peaks = self.get_curr_strain_peaks();
|
|
||||||
|
|
||||||
peaks.retain(|&peak| peak > 0.0);
|
|
||||||
peaks.sort_unstable_by(|a, b| b.partial_cmp(a).unwrap_or(Ordering::Equal));
|
|
||||||
|
|
||||||
// * Difficulty is the weighted sum of the highest strains from every section.
|
|
||||||
// * We're sorting from highest to lowest strain.
|
|
||||||
for strain in peaks {
|
|
||||||
difficulty += strain * weight;
|
|
||||||
weight *= Self::DECAY_WEIGHT;
|
|
||||||
}
|
|
||||||
|
|
||||||
difficulty
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn get_curr_strain_peaks(mut self) -> Vec<f64> {
|
|
||||||
let curr_peak = *self.curr_section_peak();
|
|
||||||
let mut strain_peaks = mem::take(self.strain_peaks_mut());
|
|
||||||
strain_peaks.push(curr_peak);
|
|
||||||
|
|
||||||
strain_peaks
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) trait StrainDecaySkill: StrainSkill {
|
|
||||||
const SKILL_MULTIPLIER: f64;
|
|
||||||
const STRAIN_DECAY_BASE: f64;
|
|
||||||
|
|
||||||
fn curr_strain(&self) -> f64;
|
|
||||||
fn curr_strain_mut(&mut self) -> &mut f64;
|
|
||||||
|
|
||||||
fn strain_value_of(&mut self, curr: &TaikoDifficultyObject, hit_objects: &ObjectLists) -> f64;
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn calculate_initial_strain(&self, time: f64, curr: &TaikoDifficultyObject) -> f64 {
|
|
||||||
self.curr_strain() * self.strain_decay(time - curr.prev_time)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn strain_value_at(&mut self, curr: &TaikoDifficultyObject, hit_objects: &ObjectLists) -> f64 {
|
|
||||||
*self.curr_strain_mut() *= self.strain_decay(curr.delta);
|
|
||||||
*self.curr_strain_mut() += self.strain_value_of(curr, hit_objects) * Self::SKILL_MULTIPLIER;
|
|
||||||
|
|
||||||
self.curr_strain()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn strain_decay(&self, ms: f64) -> f64 {
|
|
||||||
Self::STRAIN_DECAY_BASE.powf(ms / 1000.0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -0,0 +1,118 @@
|
|||||||
|
use std::{cmp::Ordering, mem};
|
||||||
|
|
||||||
|
use crate::taiko::{
|
||||||
|
difficulty_object::{ObjectLists, TaikoDifficultyObject},
|
||||||
|
SECTION_LEN,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub(crate) trait Skill: Sized {
|
||||||
|
fn process(&mut self, curr: &TaikoDifficultyObject, hit_objects: &ObjectLists);
|
||||||
|
fn difficulty_value(self) -> f64;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) trait StrainSkill: Skill {
|
||||||
|
const DECAY_WEIGHT: f64 = 0.9;
|
||||||
|
|
||||||
|
fn strain_peaks_mut(&mut self) -> &mut Vec<f64>;
|
||||||
|
fn curr_section_peak(&mut self) -> &mut f64;
|
||||||
|
fn curr_section_end(&mut self) -> &mut f64;
|
||||||
|
|
||||||
|
fn strain_value_at(&mut self, curr: &TaikoDifficultyObject, hit_objects: &ObjectLists) -> f64;
|
||||||
|
|
||||||
|
fn calculate_initial_strain(&self, time: f64, curr: &TaikoDifficultyObject) -> f64;
|
||||||
|
|
||||||
|
fn process(&mut self, curr: &TaikoDifficultyObject, hit_objects: &ObjectLists) {
|
||||||
|
// * The first object doesn't generate a strain, so we begin with an incremented section end
|
||||||
|
if curr.idx == 0 {
|
||||||
|
let section_len = SECTION_LEN as f64;
|
||||||
|
*self.curr_section_end() = (curr.start_time / section_len).ceil() * section_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
while curr.start_time > *self.curr_section_end() {
|
||||||
|
self.save_curr_peak();
|
||||||
|
|
||||||
|
{
|
||||||
|
let section_end = *self.curr_section_end();
|
||||||
|
self.start_new_section_from(section_end, curr);
|
||||||
|
}
|
||||||
|
|
||||||
|
*self.curr_section_end() += SECTION_LEN as f64;
|
||||||
|
}
|
||||||
|
|
||||||
|
*self.curr_section_peak() = self
|
||||||
|
.strain_value_at(curr, hit_objects)
|
||||||
|
.max(*self.curr_section_peak());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn save_curr_peak(&mut self) {
|
||||||
|
let peak = *self.curr_section_peak();
|
||||||
|
self.strain_peaks_mut().push(peak);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn start_new_section_from(&mut self, time: f64, curr: &TaikoDifficultyObject) {
|
||||||
|
// * The maximum strain of the new section is not zero by default
|
||||||
|
// * This means we need to capture the strain level at the beginning of the new section,
|
||||||
|
// * and use that as the initial peak level.
|
||||||
|
*self.curr_section_peak() = self.calculate_initial_strain(time, curr);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn difficulty_value(self) -> f64 {
|
||||||
|
let mut difficulty = 0.0;
|
||||||
|
let mut weight = 1.0;
|
||||||
|
|
||||||
|
// * Sections with 0 strain are excluded to avoid worst-case time complexity of the following sort (e.g. /b/2351871).
|
||||||
|
// * These sections will not contribute to the difficulty.
|
||||||
|
let mut peaks = self.get_curr_strain_peaks();
|
||||||
|
|
||||||
|
peaks.retain(|&peak| peak > 0.0);
|
||||||
|
peaks.sort_unstable_by(|a, b| b.partial_cmp(a).unwrap_or(Ordering::Equal));
|
||||||
|
|
||||||
|
// * Difficulty is the weighted sum of the highest strains from every section.
|
||||||
|
// * We're sorting from highest to lowest strain.
|
||||||
|
for strain in peaks {
|
||||||
|
difficulty += strain * weight;
|
||||||
|
weight *= Self::DECAY_WEIGHT;
|
||||||
|
}
|
||||||
|
|
||||||
|
difficulty
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn get_curr_strain_peaks(mut self) -> Vec<f64> {
|
||||||
|
let curr_peak = *self.curr_section_peak();
|
||||||
|
let mut strain_peaks = mem::take(self.strain_peaks_mut());
|
||||||
|
strain_peaks.push(curr_peak);
|
||||||
|
|
||||||
|
strain_peaks
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) trait StrainDecaySkill: StrainSkill {
|
||||||
|
const SKILL_MULTIPLIER: f64;
|
||||||
|
const STRAIN_DECAY_BASE: f64;
|
||||||
|
|
||||||
|
fn curr_strain(&self) -> f64;
|
||||||
|
fn curr_strain_mut(&mut self) -> &mut f64;
|
||||||
|
|
||||||
|
fn strain_value_of(&mut self, curr: &TaikoDifficultyObject, hit_objects: &ObjectLists) -> f64;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn calculate_initial_strain(&self, time: f64, curr: &TaikoDifficultyObject) -> f64 {
|
||||||
|
self.curr_strain() * self.strain_decay(time - curr.prev_time)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn strain_value_at(&mut self, curr: &TaikoDifficultyObject, hit_objects: &ObjectLists) -> f64 {
|
||||||
|
*self.curr_strain_mut() *= self.strain_decay(curr.delta);
|
||||||
|
*self.curr_strain_mut() += self.strain_value_of(curr, hit_objects) * Self::SKILL_MULTIPLIER;
|
||||||
|
|
||||||
|
self.curr_strain()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn strain_decay(&self, ms: f64) -> f64 {
|
||||||
|
Self::STRAIN_DECAY_BASE.powf(ms / 1000.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user