1use std::{
2 error::Error,
3 fmt::{Display, Formatter, Result as FmtResult},
4};
5
6pub use rosu_map::section::general::GameMode;
7
8use crate::Difficulty;
9
10use super::beatmap::Beatmap;
11
12pub trait IGameMode: Sized {
22 type DifficultyAttributes;
24
25 type Strains;
27
28 type Performance<'map>;
30
31 type GradualDifficulty;
33
34 type GradualPerformance;
36
37 fn difficulty(
40 difficulty: &Difficulty,
41 map: &Beatmap,
42 ) -> Result<Self::DifficultyAttributes, ConvertError>;
43
44 fn strains(difficulty: &Difficulty, map: &Beatmap) -> Result<Self::Strains, ConvertError>;
47
48 fn performance(map: &Beatmap) -> Self::Performance<'_>;
50
51 fn gradual_difficulty(
53 difficulty: Difficulty,
54 map: &Beatmap,
55 ) -> Result<Self::GradualDifficulty, ConvertError>;
56
57 fn gradual_performance(
59 difficulty: Difficulty,
60 map: &Beatmap,
61 ) -> Result<Self::GradualPerformance, ConvertError>;
62}
63
64#[derive(Copy, Clone, Debug)]
67pub enum ConvertError {
68 AlreadyConverted,
70 Convert { from: GameMode, to: GameMode },
72}
73
74impl Error for ConvertError {
75 fn source(&self) -> Option<&(dyn Error + 'static)> {
76 None
77 }
78}
79
80impl Display for ConvertError {
81 fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
82 match self {
83 ConvertError::AlreadyConverted => {
84 f.write_str("Cannot convert an already converted map")
85 }
86 ConvertError::Convert { from, to } => {
87 write!(f, "Cannot convert from {from:?} to {to:?}")
88 }
89 }
90 }
91}