use rosu_map::section::general::GameMode;
use crate::{
Beatmap, Difficulty,
any::{PerformanceAttributes, ScoreState},
catch::{Catch, CatchGradualPerformance},
mania::{Mania, ManiaGradualPerformance},
model::{
beatmap::TooSuspicious,
mode::{ConvertError, IGameMode},
},
osu::{Osu, OsuGradualPerformance},
taiko::{Taiko, TaikoGradualPerformance},
};
pub enum GradualPerformance {
Osu(OsuGradualPerformance),
Taiko(TaikoGradualPerformance),
Catch(CatchGradualPerformance),
Mania(ManiaGradualPerformance),
}
impl GradualPerformance {
#[expect(clippy::missing_panics_doc, reason = "unreachable")]
pub fn new(difficulty: Difficulty, map: &Beatmap) -> Self {
Self::new_with_mode(difficulty, map, map.mode).expect("no conversion required")
}
pub fn checked_new(difficulty: Difficulty, map: &Beatmap) -> Result<Self, TooSuspicious> {
map.check_suspicion()?;
Ok(Self::new(difficulty, map))
}
pub fn new_with_mode(
difficulty: Difficulty,
map: &Beatmap,
mode: GameMode,
) -> Result<Self, ConvertError> {
match mode {
GameMode::Osu => Osu::gradual_performance(difficulty, map).map(Self::Osu),
GameMode::Taiko => Taiko::gradual_performance(difficulty, map).map(Self::Taiko),
GameMode::Catch => Catch::gradual_performance(difficulty, map).map(Self::Catch),
GameMode::Mania => Mania::gradual_performance(difficulty, map).map(Self::Mania),
}
}
pub fn next(&mut self, state: ScoreState) -> Option<PerformanceAttributes> {
self.nth(state, 0)
}
pub fn last(&mut self, state: ScoreState) -> Option<PerformanceAttributes> {
self.nth(state, usize::MAX)
}
pub fn nth(&mut self, state: ScoreState, n: usize) -> Option<PerformanceAttributes> {
match self {
GradualPerformance::Osu(gradual) => {
gradual.nth(state.into(), n).map(PerformanceAttributes::Osu)
}
GradualPerformance::Taiko(gradual) => gradual
.nth(state.into(), n)
.map(PerformanceAttributes::Taiko),
GradualPerformance::Catch(gradual) => gradual
.nth(state.into(), n)
.map(PerformanceAttributes::Catch),
GradualPerformance::Mania(gradual) => gradual
.nth(state.into(), n)
.map(PerformanceAttributes::Mania),
}
}
#[expect(clippy::len_without_is_empty, reason = "TODO")]
pub fn len(&self) -> usize {
match self {
GradualPerformance::Osu(gradual) => gradual.len(),
GradualPerformance::Taiko(gradual) => gradual.len(),
GradualPerformance::Catch(gradual) => gradual.len(),
GradualPerformance::Mania(gradual) => gradual.len(),
}
}
}