1use crate::{Beatmap, GameMode, PpResult, StarResult};
2
3#[cfg(feature = "fruits")]
4use crate::FruitsPP;
5
6#[cfg(feature = "mania")]
7use crate::ManiaPP;
8
9#[cfg(feature = "osu")]
10use crate::OsuPP;
11
12#[cfg(feature = "taiko")]
13use crate::TaikoPP;
14
15#[derive(Clone)]
17#[allow(clippy::upper_case_acronyms)]
18pub enum AnyPP<'m> {
19 #[cfg(feature = "fruits")]
20 Fruits(FruitsPP<'m>),
21 #[cfg(feature = "mania")]
22 Mania(ManiaPP<'m>),
23 #[cfg(feature = "osu")]
24 Osu(OsuPP<'m>),
25 #[cfg(feature = "taiko")]
26 Taiko(TaikoPP<'m>),
27}
28
29impl<'m> AnyPP<'m> {
30 #[inline]
31 pub fn new(map: &'m Beatmap) -> Self {
32 match map.mode {
33 #[cfg(feature = "fruits")]
34 GameMode::CTB => Self::Fruits(FruitsPP::new(map)),
35 #[cfg(feature = "mania")]
36 GameMode::MNA => Self::Mania(ManiaPP::new(map)),
37 #[cfg(feature = "osu")]
38 GameMode::STD => Self::Osu(OsuPP::new(map)),
39 #[cfg(feature = "taiko")]
40 GameMode::TKO => Self::Taiko(TaikoPP::new(map)),
41 #[allow(unreachable_patterns)]
42 _ => panic!("feature for mode {:?} is not enabled", map.mode),
43 }
44 }
45
46 #[cfg(any(feature = "async_std", feature = "async_tokio"))]
47 #[inline]
48 pub async fn calculate(&mut self) -> PpResult {
49 match self {
50 #[cfg(feature = "fruits")]
51 Self::Fruits(f) => f.calculate_async().await,
52 #[cfg(feature = "mania")]
53 Self::Mania(m) => m.calculate_async().await,
54 #[cfg(feature = "osu")]
55 Self::Osu(o) => o.calculate_async().await,
56 #[cfg(feature = "taiko")]
57 Self::Taiko(t) => t.calculate_async().await,
58 }
59 }
60
61 #[cfg(not(any(feature = "async_std", feature = "async_tokio")))]
62 #[inline]
63 pub fn calculate(&mut self) -> PpResult {
64 match self {
65 #[cfg(feature = "fruits")]
66 Self::Fruits(f) => f.calculate(),
67 #[cfg(feature = "mania")]
68 Self::Mania(m) => m.calculate(),
69 #[cfg(feature = "osu")]
70 Self::Osu(o) => o.calculate(),
71 #[cfg(feature = "taiko")]
72 Self::Taiko(t) => t.calculate(),
73 }
74 }
75
76 #[inline]
82 pub fn attributes(self, attributes: impl AttributeProvider) -> Self {
83 match self {
84 #[cfg(feature = "fruits")]
85 Self::Fruits(f) => Self::Fruits(f.attributes(attributes.attributes())),
86 #[cfg(feature = "mania")]
87 Self::Mania(m) => Self::Mania(m.attributes(attributes.attributes())),
88 #[cfg(feature = "osu")]
89 Self::Osu(o) => Self::Osu(o.attributes(attributes.attributes())),
90 #[cfg(feature = "taiko")]
91 Self::Taiko(t) => Self::Taiko(t.attributes(attributes.attributes())),
92 }
93 }
94
95 #[inline]
99 pub fn mods(self, mods: u32) -> Self {
100 match self {
101 #[cfg(feature = "fruits")]
102 Self::Fruits(f) => Self::Fruits(f.mods(mods)),
103 #[cfg(feature = "mania")]
104 Self::Mania(m) => Self::Mania(m.mods(mods)),
105 #[cfg(feature = "osu")]
106 Self::Osu(o) => Self::Osu(o.mods(mods)),
107 #[cfg(feature = "taiko")]
108 Self::Taiko(t) => Self::Taiko(t.mods(mods)),
109 }
110 }
111
112 #[inline]
114 pub fn passed_objects(self, passed_objects: usize) -> Self {
115 match self {
116 #[cfg(feature = "fruits")]
117 Self::Fruits(f) => Self::Fruits(f.passed_objects(passed_objects)),
118 #[cfg(feature = "mania")]
119 Self::Mania(m) => Self::Mania(m.passed_objects(passed_objects)),
120 #[cfg(feature = "osu")]
121 Self::Osu(o) => Self::Osu(o.passed_objects(passed_objects)),
122 #[cfg(feature = "taiko")]
123 Self::Taiko(t) => Self::Taiko(t.passed_objects(passed_objects)),
124 }
125 }
126
127 #[allow(unused_variables)]
134 #[inline]
135 pub fn accuracy(self, acc: f32) -> Self {
136 match self {
137 #[cfg(feature = "fruits")]
138 Self::Fruits(f) => Self::Fruits(f.accuracy(acc)),
139 #[cfg(feature = "mania")]
140 Self::Mania(_) => self,
141 #[cfg(feature = "osu")]
142 Self::Osu(o) => Self::Osu(o.accuracy(acc)),
143 #[cfg(feature = "taiko")]
144 Self::Taiko(t) => Self::Taiko(t.accuracy(acc)),
145 }
146 }
147
148
149 #[allow(unused_variables)]
150 #[inline(always)]
151 pub fn set_accuracy(&mut self, acc: f32) {
201 match self {
202 #[cfg(feature = "fruits")]
203 Self::Fruits(f) => f.set_accuracy(acc),
204 #[cfg(feature = "mania")]
205 Self::Mania(_) => {}
206 #[cfg(feature = "osu")]
207 Self::Osu(o) => o.set_accuracy(acc),
208 #[cfg(feature = "taiko")]
209 Self::Taiko(t) => t.set_accuracy(acc),
210 }
211 }
212
213 #[allow(unused_variables)]
217 #[inline]
218 pub fn misses(self, misses: usize) -> Self {
219 match self {
220 #[cfg(feature = "fruits")]
221 Self::Fruits(f) => Self::Fruits(f.misses(misses)),
222 #[cfg(feature = "mania")]
223 Self::Mania(_) => self,
224 #[cfg(feature = "osu")]
225 Self::Osu(o) => Self::Osu(o.misses(misses)),
226 #[cfg(feature = "taiko")]
227 Self::Taiko(t) => Self::Taiko(t.misses(misses)),
228 }
229 }
230
231 #[allow(unused_variables)]
235 #[inline]
236 pub fn combo(self, combo: usize) -> Self {
237 match self {
238 #[cfg(feature = "fruits")]
239 Self::Fruits(f) => Self::Fruits(f.combo(combo)),
240 #[cfg(feature = "mania")]
241 Self::Mania(_) => self,
242 #[cfg(feature = "osu")]
243 Self::Osu(o) => Self::Osu(o.combo(combo)),
244 #[cfg(feature = "taiko")]
245 Self::Taiko(t) => Self::Taiko(t.combo(combo)),
246 }
247 }
248
249 #[allow(unused_variables)]
253 #[inline]
254 pub fn n300(self, n300: usize) -> Self {
255 match self {
256 #[cfg(feature = "fruits")]
257 Self::Fruits(f) => Self::Fruits(f.fruits(n300)),
258 #[cfg(feature = "mania")]
259 Self::Mania(_) => self,
260 #[cfg(feature = "osu")]
261 Self::Osu(o) => Self::Osu(o.n300(n300)),
262 #[cfg(feature = "taiko")]
263 Self::Taiko(t) => Self::Taiko(t.n300(n300)),
264 }
265 }
266
267 #[allow(unused_variables)]
271 #[inline]
272 pub fn n100(self, n100: usize) -> Self {
273 match self {
274 #[cfg(feature = "fruits")]
275 Self::Fruits(f) => Self::Fruits(f.droplets(n100)),
276 #[cfg(feature = "mania")]
277 Self::Mania(_) => self,
278 #[cfg(feature = "osu")]
279 Self::Osu(o) => Self::Osu(o.n100(n100)),
280 #[cfg(feature = "taiko")]
281 Self::Taiko(t) => Self::Taiko(t.n100(n100)),
282 }
283 }
284
285 #[allow(unused_variables)]
289 #[inline]
290 pub fn n50(self, n50: usize) -> Self {
291 match self {
292 #[cfg(feature = "fruits")]
293 Self::Fruits(f) => Self::Fruits(f.tiny_droplets(n50)),
294 #[cfg(feature = "mania")]
295 Self::Mania(_) => self,
296 #[cfg(feature = "osu")]
297 Self::Osu(o) => Self::Osu(o.n50(n50)),
298 #[cfg(feature = "taiko")]
299 Self::Taiko(_) => self,
300 }
301 }
302
303 #[allow(unused_variables)]
308 #[inline]
309 pub fn n_katu(self, n_katu: usize) -> Self {
310 match self {
311 #[cfg(feature = "fruits")]
312 Self::Fruits(f) => Self::Fruits(f.tiny_droplet_misses(n_katu)),
313 #[cfg(feature = "mania")]
314 Self::Mania(_) => self,
315 #[cfg(feature = "osu")]
316 Self::Osu(_) => self,
317 #[cfg(feature = "taiko")]
318 Self::Taiko(_) => self,
319 }
320 }
321
322 #[allow(unused_variables)]
328 #[inline]
329 pub fn score(self, score: u32) -> Self {
330 match self {
331 #[cfg(feature = "fruits")]
332 Self::Fruits(_) => self,
333 #[cfg(feature = "mania")]
334 Self::Mania(m) => Self::Mania(m.score(score)),
335 #[cfg(feature = "osu")]
336 Self::Osu(_) => self,
337 #[cfg(feature = "taiko")]
338 Self::Taiko(_) => self,
339 }
340 }
341}
342
343pub trait AttributeProvider {
344 fn attributes(self) -> StarResult;
345}
346
347impl AttributeProvider for StarResult {
348 #[inline]
349 fn attributes(self) -> StarResult {
350 self
351 }
352}
353
354impl AttributeProvider for PpResult {
355 #[inline]
356 fn attributes(self) -> StarResult {
357 self.attributes
358 }
359}