use std::borrow::Cow;
use rosu_map::section::general::GameMode;
use crate::{
any::DifficultyAttributes,
catch::{Catch, CatchBeatmap, CatchGradualDifficulty},
mania::{Mania, ManiaBeatmap, ManiaGradualDifficulty},
model::mode::IGameMode,
osu::{Osu, OsuBeatmap, OsuGradualDifficulty},
taiko::{Taiko, TaikoBeatmap, TaikoGradualDifficulty},
Beatmap, Converted, Difficulty,
};
#[allow(clippy::large_enum_variant)]
pub enum GradualDifficulty {
Osu(OsuGradualDifficulty),
Taiko(TaikoGradualDifficulty),
Catch(CatchGradualDifficulty),
Mania(ManiaGradualDifficulty),
}
macro_rules! from_converted {
( $fn:ident, $mode:ident, $converted:ident ) => {
#[doc = concat!("Create a [`GradualDifficulty`] for a [`", stringify!($converted), "`]")]
pub fn $fn(difficulty: Difficulty, converted: &$converted<'_>) -> Self {
Self::$mode($mode::gradual_difficulty(difficulty, converted))
}
};
}
impl GradualDifficulty {
pub fn new(difficulty: Difficulty, map: &Beatmap) -> Self {
let map = Cow::Borrowed(map);
match map.mode {
GameMode::Osu => Self::Osu(Osu::gradual_difficulty(difficulty, &Converted::new(map))),
GameMode::Taiko => {
Self::Taiko(Taiko::gradual_difficulty(difficulty, &Converted::new(map)))
}
GameMode::Catch => {
Self::Catch(Catch::gradual_difficulty(difficulty, &Converted::new(map)))
}
GameMode::Mania => {
Self::Mania(Mania::gradual_difficulty(difficulty, &Converted::new(map)))
}
}
}
from_converted!(from_osu_map, Osu, OsuBeatmap);
from_converted!(from_taiko_map, Taiko, TaikoBeatmap);
from_converted!(from_catch_map, Catch, CatchBeatmap);
from_converted!(from_mania_map, Mania, ManiaBeatmap);
}
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(),
}
}
}