use rosu_map::section::general::GameMode;
use crate::{
Beatmap, Difficulty,
any::DifficultyAttributes,
catch::{Catch, CatchGradualDifficulty},
mania::{Mania, ManiaGradualDifficulty},
model::{
beatmap::TooSuspicious,
mode::{ConvertError, IGameMode},
},
osu::{Osu, OsuGradualDifficulty},
taiko::{Taiko, TaikoGradualDifficulty},
};
pub enum GradualDifficulty {
Osu(OsuGradualDifficulty),
Taiko(TaikoGradualDifficulty),
Catch(CatchGradualDifficulty),
Mania(ManiaGradualDifficulty),
}
impl GradualDifficulty {
#[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_difficulty(difficulty, map).map(Self::Osu),
GameMode::Taiko => Taiko::gradual_difficulty(difficulty, map).map(Self::Taiko),
GameMode::Catch => Catch::gradual_difficulty(difficulty, map).map(Self::Catch),
GameMode::Mania => Mania::gradual_difficulty(difficulty, map).map(Self::Mania),
}
}
}
impl Iterator for GradualDifficulty {
type Item = DifficultyAttributes;
fn next(&mut self) -> Option<Self::Item> {
match self {
GradualDifficulty::Osu(gradual) => gradual.next().map(DifficultyAttributes::Osu),
GradualDifficulty::Taiko(gradual) => gradual.next().map(DifficultyAttributes::Taiko),
GradualDifficulty::Catch(gradual) => gradual.next().map(DifficultyAttributes::Catch),
GradualDifficulty::Mania(gradual) => gradual.next().map(DifficultyAttributes::Mania),
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
match self {
GradualDifficulty::Osu(gradual) => gradual.size_hint(),
GradualDifficulty::Taiko(gradual) => gradual.size_hint(),
GradualDifficulty::Catch(gradual) => gradual.size_hint(),
GradualDifficulty::Mania(gradual) => gradual.size_hint(),
}
}
fn nth(&mut self, n: usize) -> Option<Self::Item> {
match self {
GradualDifficulty::Osu(gradual) => gradual.nth(n).map(DifficultyAttributes::Osu),
GradualDifficulty::Taiko(gradual) => gradual.nth(n).map(DifficultyAttributes::Taiko),
GradualDifficulty::Catch(gradual) => gradual.nth(n).map(DifficultyAttributes::Catch),
GradualDifficulty::Mania(gradual) => gradual.nth(n).map(DifficultyAttributes::Mania),
}
}
}
impl ExactSizeIterator for GradualDifficulty {
fn len(&self) -> usize {
match self {
GradualDifficulty::Osu(gradual) => gradual.len(),
GradualDifficulty::Taiko(gradual) => gradual.len(),
GradualDifficulty::Catch(gradual) => gradual.len(),
GradualDifficulty::Mania(gradual) => gradual.len(),
}
}
}