use crate::{
catch::{CatchGradualDifficultyAttributes, CatchGradualPerformanceAttributes, CatchScoreState},
mania::{ManiaGradualDifficultyAttributes, ManiaGradualPerformanceAttributes, ManiaScoreState},
osu::{OsuGradualDifficultyAttributes, OsuGradualPerformanceAttributes, OsuScoreState},
taiko::{TaikoGradualDifficultyAttributes, TaikoGradualPerformanceAttributes, TaikoScoreState},
Beatmap, DifficultyAttributes, GameMode, PerformanceAttributes,
};
#[derive(Debug)]
#[allow(clippy::large_enum_variant)]
pub enum GradualDifficultyAttributes<'map> {
Osu(OsuGradualDifficultyAttributes),
Taiko(TaikoGradualDifficultyAttributes),
Catch(CatchGradualDifficultyAttributes<'map>),
Mania(ManiaGradualDifficultyAttributes<'map>),
}
impl<'map> GradualDifficultyAttributes<'map> {
#[inline]
pub fn new(map: &'map Beatmap, mods: u32) -> Self {
match map.mode {
GameMode::Osu => Self::Osu(OsuGradualDifficultyAttributes::new(map, mods)),
GameMode::Taiko => Self::Taiko(TaikoGradualDifficultyAttributes::new(map, mods)),
GameMode::Catch => Self::Catch(CatchGradualDifficultyAttributes::new(map, mods)),
GameMode::Mania => Self::Mania(ManiaGradualDifficultyAttributes::new(map, mods)),
}
}
}
impl Iterator for GradualDifficultyAttributes<'_> {
type Item = DifficultyAttributes;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
match self {
GradualDifficultyAttributes::Osu(o) => o.next().map(DifficultyAttributes::Osu),
GradualDifficultyAttributes::Taiko(t) => t.next().map(DifficultyAttributes::Taiko),
GradualDifficultyAttributes::Catch(f) => f.next().map(DifficultyAttributes::Catch),
GradualDifficultyAttributes::Mania(m) => m.next().map(DifficultyAttributes::Mania),
}
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
match self {
GradualDifficultyAttributes::Osu(o) => o.size_hint(),
GradualDifficultyAttributes::Taiko(t) => t.size_hint(),
GradualDifficultyAttributes::Catch(f) => f.size_hint(),
GradualDifficultyAttributes::Mania(m) => m.size_hint(),
}
}
}
#[derive(Clone, Debug, Default, Eq, PartialEq)]
pub struct ScoreState {
pub max_combo: usize,
pub n_geki: usize,
pub n_katu: usize,
pub n300: usize,
pub n100: usize,
pub n50: usize,
pub n_misses: usize,
}
impl ScoreState {
#[inline]
pub fn new() -> Self {
Self::default()
}
#[inline]
pub fn total_hits(&self, mode: GameMode) -> usize {
let mut amount = self.n300 + self.n100 + self.n_misses;
if mode != GameMode::Taiko {
amount += self.n50;
if mode != GameMode::Osu {
amount += self.n_katu;
amount += (mode != GameMode::Catch) as usize * self.n_geki;
}
}
amount
}
}
impl From<ScoreState> for OsuScoreState {
#[inline]
fn from(state: ScoreState) -> Self {
Self {
max_combo: state.max_combo,
n300: state.n300,
n100: state.n100,
n50: state.n50,
n_misses: state.n_misses,
}
}
}
impl From<ScoreState> for TaikoScoreState {
#[inline]
fn from(state: ScoreState) -> Self {
Self {
max_combo: state.max_combo,
n300: state.n300,
n100: state.n100,
n_misses: state.n_misses,
}
}
}
impl From<ScoreState> for CatchScoreState {
#[inline]
fn from(state: ScoreState) -> Self {
Self {
max_combo: state.max_combo,
n_fruits: state.n300,
n_droplets: state.n100,
n_tiny_droplets: state.n50,
n_tiny_droplet_misses: state.n_katu,
n_misses: state.n_misses,
}
}
}
impl From<ScoreState> for ManiaScoreState {
#[inline]
fn from(state: ScoreState) -> Self {
Self {
n320: state.n_geki,
n300: state.n300,
n200: state.n_katu,
n100: state.n100,
n50: state.n50,
n_misses: state.n_misses,
}
}
}
#[derive(Debug)]
#[allow(clippy::large_enum_variant)]
pub enum GradualPerformanceAttributes<'map> {
Osu(OsuGradualPerformanceAttributes<'map>),
Taiko(TaikoGradualPerformanceAttributes<'map>),
Catch(CatchGradualPerformanceAttributes<'map>),
Mania(ManiaGradualPerformanceAttributes<'map>),
}
impl<'map> GradualPerformanceAttributes<'map> {
#[inline]
pub fn new(map: &'map Beatmap, mods: u32) -> Self {
match map.mode {
GameMode::Osu => Self::Osu(OsuGradualPerformanceAttributes::new(map, mods)),
GameMode::Taiko => Self::Taiko(TaikoGradualPerformanceAttributes::new(map, mods)),
GameMode::Catch => Self::Catch(CatchGradualPerformanceAttributes::new(map, mods)),
GameMode::Mania => Self::Mania(ManiaGradualPerformanceAttributes::new(map, mods)),
}
}
#[inline]
pub fn process_next_object(&mut self, state: ScoreState) -> Option<PerformanceAttributes> {
self.process_next_n_objects(state, 1)
}
#[inline]
pub fn process_next_n_objects(
&mut self,
state: ScoreState,
n: usize,
) -> Option<PerformanceAttributes> {
match self {
GradualPerformanceAttributes::Osu(o) => o
.process_next_n_objects(state.into(), n)
.map(PerformanceAttributes::Osu),
GradualPerformanceAttributes::Taiko(t) => t
.process_next_n_objects(state.into(), n)
.map(PerformanceAttributes::Taiko),
GradualPerformanceAttributes::Catch(f) => f
.process_next_n_objects(state.into(), n)
.map(PerformanceAttributes::Catch),
GradualPerformanceAttributes::Mania(m) => m
.process_next_n_objects(state.into(), n)
.map(PerformanceAttributes::Mania),
}
}
}