use crate::{
catch::{CatchDifficultyAttributes, CatchPP, CatchPerformanceAttributes},
mania::{ManiaDifficultyAttributes, ManiaPP, ManiaPerformanceAttributes},
osu::{OsuDifficultyAttributes, OsuPP, OsuPerformanceAttributes},
taiko::{TaikoDifficultyAttributes, TaikoPP, TaikoPerformanceAttributes},
Beatmap, DifficultyAttributes, GameMode, PerformanceAttributes, ScoreState,
};
#[allow(clippy::upper_case_acronyms)]
#[derive(Clone, Debug)]
pub enum AnyPP<'map> {
Osu(OsuPP<'map>),
Taiko(TaikoPP<'map>),
Catch(CatchPP<'map>),
Mania(ManiaPP<'map>),
}
impl<'map> AnyPP<'map> {
#[inline]
pub fn new(map: &'map Beatmap) -> Self {
match map.mode {
GameMode::Osu => Self::Osu(OsuPP::new(map)),
GameMode::Taiko => Self::Taiko(TaikoPP::new(map)),
GameMode::Catch => Self::Catch(CatchPP::new(map)),
GameMode::Mania => Self::Mania(ManiaPP::new(map)),
}
}
#[inline]
pub fn calculate(self) -> PerformanceAttributes {
match self {
Self::Osu(o) => PerformanceAttributes::Osu(o.calculate()),
Self::Taiko(t) => PerformanceAttributes::Taiko(t.calculate()),
Self::Catch(f) => PerformanceAttributes::Catch(f.calculate()),
Self::Mania(m) => PerformanceAttributes::Mania(m.calculate()),
}
}
#[inline]
pub fn attributes(self, attributes: impl AttributeProvider) -> Self {
match self {
Self::Osu(o) => Self::Osu(o.attributes(attributes.attributes())),
Self::Taiko(t) => Self::Taiko(t.attributes(attributes.attributes())),
Self::Catch(f) => Self::Catch(f.attributes(attributes.attributes())),
Self::Mania(m) => Self::Mania(m.attributes(attributes.attributes())),
}
}
#[inline]
pub fn mode(self, mode: GameMode) -> Self {
match self {
AnyPP::Osu(o) => match mode {
GameMode::Osu => AnyPP::Osu(o),
GameMode::Taiko => AnyPP::Taiko(o.into()),
GameMode::Catch => AnyPP::Catch(o.into()),
GameMode::Mania => AnyPP::Mania(o.into()),
},
other => other,
}
}
#[inline]
pub fn mods(self, mods: u32) -> Self {
match self {
Self::Osu(o) => Self::Osu(o.mods(mods)),
Self::Taiko(t) => Self::Taiko(t.mods(mods)),
Self::Catch(f) => Self::Catch(f.mods(mods)),
Self::Mania(m) => Self::Mania(m.mods(mods)),
}
}
#[inline]
pub fn passed_objects(self, passed_objects: usize) -> Self {
match self {
Self::Osu(o) => Self::Osu(o.passed_objects(passed_objects)),
Self::Taiko(t) => Self::Taiko(t.passed_objects(passed_objects)),
Self::Catch(f) => Self::Catch(f.passed_objects(passed_objects)),
Self::Mania(m) => Self::Mania(m.passed_objects(passed_objects)),
}
}
#[inline]
pub fn clock_rate(self, clock_rate: f64) -> Self {
match self {
Self::Osu(o) => Self::Osu(o.clock_rate(clock_rate)),
Self::Taiko(t) => Self::Taiko(t.clock_rate(clock_rate)),
Self::Catch(f) => Self::Catch(f.clock_rate(clock_rate)),
Self::Mania(m) => Self::Mania(m.clock_rate(clock_rate)),
}
}
#[inline]
pub fn state(self, state: ScoreState) -> Self {
match self {
Self::Osu(o) => Self::Osu(o.state(state.into())),
Self::Taiko(t) => Self::Taiko(t.state(state.into())),
Self::Catch(f) => Self::Catch(f.state(state.into())),
Self::Mania(m) => Self::Mania(m.state(state.into())),
}
}
#[inline]
pub fn accuracy(self, acc: f64) -> Self {
match self {
Self::Osu(o) => Self::Osu(o.accuracy(acc)),
Self::Taiko(t) => Self::Taiko(t.accuracy(acc)),
Self::Catch(f) => Self::Catch(f.accuracy(acc)),
Self::Mania(m) => Self::Mania(m.accuracy(acc)),
}
}
#[inline]
pub fn n_misses(self, n_misses: usize) -> Self {
match self {
Self::Osu(o) => Self::Osu(o.n_misses(n_misses)),
Self::Taiko(t) => Self::Taiko(t.n_misses(n_misses)),
Self::Catch(f) => Self::Catch(f.misses(n_misses)),
Self::Mania(m) => Self::Mania(m.n_misses(n_misses)),
}
}
#[inline]
pub fn combo(self, combo: usize) -> Self {
match self {
Self::Osu(o) => Self::Osu(o.combo(combo)),
Self::Taiko(t) => Self::Taiko(t.combo(combo)),
Self::Catch(f) => Self::Catch(f.combo(combo)),
Self::Mania(_) => self,
}
}
#[inline]
pub fn n300(self, n300: usize) -> Self {
match self {
Self::Osu(o) => Self::Osu(o.n300(n300)),
Self::Taiko(t) => Self::Taiko(t.n300(n300)),
Self::Catch(f) => Self::Catch(f.fruits(n300)),
Self::Mania(m) => Self::Mania(m.n300(n300)),
}
}
#[inline]
pub fn n100(self, n100: usize) -> Self {
match self {
Self::Osu(o) => Self::Osu(o.n100(n100)),
Self::Taiko(t) => Self::Taiko(t.n100(n100)),
Self::Catch(f) => Self::Catch(f.droplets(n100)),
Self::Mania(m) => Self::Mania(m.n100(n100)),
}
}
#[inline]
pub fn n50(self, n50: usize) -> Self {
match self {
Self::Osu(o) => Self::Osu(o.n50(n50)),
Self::Taiko(_) => self,
Self::Catch(f) => Self::Catch(f.tiny_droplets(n50)),
Self::Mania(m) => Self::Mania(m.n50(n50)),
}
}
#[inline]
pub fn n_katu(self, n_katu: usize) -> Self {
match self {
Self::Osu(_) => self,
Self::Taiko(_) => self,
Self::Catch(f) => Self::Catch(f.tiny_droplet_misses(n_katu)),
Self::Mania(m) => Self::Mania(m.n200(n_katu)),
}
}
#[inline]
pub fn n_geki(self, n_geki: usize) -> Self {
match self {
Self::Osu(_) => self,
Self::Taiko(_) => self,
Self::Catch(_) => self,
Self::Mania(m) => Self::Mania(m.n320(n_geki)),
}
}
}
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum HitResultPriority {
BestCase,
WorstCase,
}
impl Default for HitResultPriority {
#[inline]
fn default() -> Self {
Self::BestCase
}
}
pub trait AttributeProvider {
fn attributes(self) -> DifficultyAttributes;
}
impl AttributeProvider for DifficultyAttributes {
#[inline]
fn attributes(self) -> DifficultyAttributes {
self
}
}
impl AttributeProvider for PerformanceAttributes {
#[inline]
fn attributes(self) -> DifficultyAttributes {
match self {
Self::Osu(attrs) => DifficultyAttributes::Osu(attrs.difficulty),
Self::Taiko(attrs) => DifficultyAttributes::Taiko(attrs.difficulty),
Self::Catch(attrs) => DifficultyAttributes::Catch(attrs.difficulty),
Self::Mania(attrs) => DifficultyAttributes::Mania(attrs.difficulty),
}
}
}
macro_rules! impl_attr_provider {
($mode:ident: $difficulty:ident, $performance:ident) => {
impl AttributeProvider for $difficulty {
#[inline]
fn attributes(self) -> DifficultyAttributes {
DifficultyAttributes::$mode(self)
}
}
impl AttributeProvider for $performance {
#[inline]
fn attributes(self) -> DifficultyAttributes {
DifficultyAttributes::$mode(self.difficulty)
}
}
};
}
impl_attr_provider!(Catch: CatchDifficultyAttributes, CatchPerformanceAttributes);
impl_attr_provider!(Mania: ManiaDifficultyAttributes, ManiaPerformanceAttributes);
impl_attr_provider!(Osu: OsuDifficultyAttributes, OsuPerformanceAttributes);
impl_attr_provider!(Taiko: TaikoDifficultyAttributes, TaikoPerformanceAttributes);