1use rosu_map::section::general::GameMode;
2
3use crate::{
4 catch::CatchScoreState, mania::ManiaScoreState, osu::OsuScoreState, taiko::TaikoScoreState,
5};
6
7#[derive(Clone, Debug, Eq, PartialEq)]
9pub struct ScoreState {
10 pub max_combo: u32,
18 pub osu_large_tick_hits: u32,
29 pub osu_small_tick_hits: u32,
36 pub slider_end_hits: u32,
40 pub n_geki: u32,
42 pub n_katu: u32,
45 pub n300: u32,
47 pub n100: u32,
49 pub n50: u32,
51 pub misses: u32,
53}
54
55impl ScoreState {
56 pub const fn new() -> Self {
58 Self {
59 max_combo: 0,
60 osu_large_tick_hits: 0,
61 osu_small_tick_hits: 0,
62 slider_end_hits: 0,
63 n_geki: 0,
64 n_katu: 0,
65 n300: 0,
66 n100: 0,
67 n50: 0,
68 misses: 0,
69 }
70 }
71
72 pub fn total_hits(&self, mode: GameMode) -> u32 {
75 let mut amount = self.n300 + self.n100 + self.misses;
76
77 if mode != GameMode::Taiko {
78 amount += self.n50;
79
80 if mode != GameMode::Osu {
81 amount += self.n_katu;
82 amount += u32::from(mode != GameMode::Catch) * self.n_geki;
83 }
84 }
85
86 amount
87 }
88}
89
90impl From<ScoreState> for OsuScoreState {
91 fn from(state: ScoreState) -> Self {
92 Self {
93 max_combo: state.max_combo,
94 large_tick_hits: state.osu_large_tick_hits,
95 small_tick_hits: state.osu_small_tick_hits,
96 slider_end_hits: state.slider_end_hits,
97 n300: state.n300,
98 n100: state.n100,
99 n50: state.n50,
100 misses: state.misses,
101 }
102 }
103}
104
105impl From<ScoreState> for TaikoScoreState {
106 fn from(state: ScoreState) -> Self {
107 Self {
108 max_combo: state.max_combo,
109 n300: state.n300,
110 n100: state.n100,
111 misses: state.misses,
112 }
113 }
114}
115
116impl From<ScoreState> for CatchScoreState {
117 fn from(state: ScoreState) -> Self {
118 Self {
119 max_combo: state.max_combo,
120 fruits: state.n300,
121 droplets: state.n100,
122 tiny_droplets: state.n50,
123 tiny_droplet_misses: state.n_katu,
124 misses: state.misses,
125 }
126 }
127}
128
129impl From<ScoreState> for ManiaScoreState {
130 fn from(state: ScoreState) -> Self {
131 Self {
132 n320: state.n_geki,
133 n300: state.n300,
134 n200: state.n_katu,
135 n100: state.n100,
136 n50: state.n50,
137 misses: state.misses,
138 }
139 }
140}
141
142impl From<OsuScoreState> for ScoreState {
143 fn from(state: OsuScoreState) -> Self {
144 Self {
145 max_combo: state.max_combo,
146 osu_large_tick_hits: state.large_tick_hits,
147 osu_small_tick_hits: state.small_tick_hits,
148 slider_end_hits: state.slider_end_hits,
149 n_geki: 0,
150 n_katu: 0,
151 n300: state.n300,
152 n100: state.n100,
153 n50: state.n50,
154 misses: state.misses,
155 }
156 }
157}
158
159impl From<TaikoScoreState> for ScoreState {
160 fn from(state: TaikoScoreState) -> Self {
161 Self {
162 max_combo: state.max_combo,
163 osu_large_tick_hits: 0,
164 osu_small_tick_hits: 0,
165 slider_end_hits: 0,
166 n_geki: 0,
167 n_katu: 0,
168 n300: state.n300,
169 n100: state.n100,
170 n50: 0,
171 misses: state.misses,
172 }
173 }
174}
175
176impl From<CatchScoreState> for ScoreState {
177 fn from(state: CatchScoreState) -> Self {
178 Self {
179 max_combo: state.max_combo,
180 osu_large_tick_hits: 0,
181 osu_small_tick_hits: 0,
182 slider_end_hits: 0,
183 n_geki: 0,
184 n_katu: state.tiny_droplet_misses,
185 n300: state.fruits,
186 n100: state.droplets,
187 n50: state.tiny_droplets,
188 misses: state.misses,
189 }
190 }
191}
192
193impl From<ManiaScoreState> for ScoreState {
194 fn from(state: ManiaScoreState) -> Self {
195 Self {
196 max_combo: 0,
197 osu_large_tick_hits: 0,
198 osu_small_tick_hits: 0,
199 slider_end_hits: 0,
200 n_geki: state.n320,
201 n_katu: state.n200,
202 n300: state.n300,
203 n100: state.n100,
204 n50: state.n50,
205 misses: state.misses,
206 }
207 }
208}
209
210impl Default for ScoreState {
211 fn default() -> Self {
212 Self::new()
213 }
214}