Skip to main content

rosu_pp/model/beatmap/attributes/
hit_windows.rs

1use crate::model::beatmap::attributes::ext::BeatmapAttributesExt;
2
3/// AR and OD hit windows
4#[derive(Copy, Clone, Debug, Default, PartialEq)]
5pub struct HitWindows {
6    /// Hit window for approach rate i.e. `TimePreempt` in milliseconds.
7    ///
8    /// Only available for osu!standard and osu!catch.
9    pub ar: Option<f64>,
10    /// Perfect hit window for overall difficulty i.e. time to hit a "Perfect"
11    /// in milliseconds.
12    ///
13    /// Only available for osu!mania.
14    pub od_perfect: Option<f64>,
15    /// Great hit window for overall difficulty i.e. time to hit a 300 ("Great")
16    /// in milliseconds.
17    ///
18    /// Only available for osu!standard, osu!taiko, and osu!mania.
19    pub od_great: Option<f64>,
20    /// Good hit window for overall difficulty i.e. time to hit a "Good" in
21    /// milliseconds.
22    ///
23    /// Only available for osu!mania.
24    pub od_good: Option<f64>,
25    /// Ok hit window for overall difficulty i.e. time to hit a 100 ("Ok") in
26    /// milliseconds.
27    ///
28    /// Only available for osu!standard, osu!taiko, and osu!mania.
29    pub od_ok: Option<f64>,
30    /// Meh hit window for overall difficulty i.e. time to hit a 50 ("Meh") in
31    /// milliseconds.
32    ///
33    /// Only available for osu!standard and osu!mania.
34    pub od_meh: Option<f64>,
35}
36
37pub(super) struct GameModeHitWindows {
38    pub min: f64,
39    pub mid: f64,
40    pub max: f64,
41}
42
43impl GameModeHitWindows {
44    pub fn difficulty_range(&self, difficulty: f64) -> f64 {
45        let Self { min, mid, max } = *self;
46
47        BeatmapAttributesExt::difficulty_range(difficulty, min, mid, max)
48    }
49
50    pub fn inverse_difficulty_range(&self, difficulty_value: f64) -> f64 {
51        let Self { min, mid, max } = *self;
52
53        BeatmapAttributesExt::inverse_difficulty_range(difficulty_value, min, mid, max)
54    }
55}
56
57pub mod osu {
58    use super::GameModeHitWindows;
59
60    pub const GREAT: GameModeHitWindows = GameModeHitWindows {
61        min: 80.0,
62        mid: 50.0,
63        max: 20.0,
64    };
65
66    pub const OK: GameModeHitWindows = GameModeHitWindows {
67        min: 140.0,
68        mid: 100.0,
69        max: 60.0,
70    };
71
72    pub const MEH: GameModeHitWindows = GameModeHitWindows {
73        min: 200.0,
74        mid: 150.0,
75        max: 100.0,
76    };
77}
78
79pub mod taiko {
80    use super::GameModeHitWindows;
81
82    pub const GREAT: GameModeHitWindows = GameModeHitWindows {
83        min: 50.0,
84        mid: 35.0,
85        max: 20.0,
86    };
87
88    pub const OK: GameModeHitWindows = GameModeHitWindows {
89        min: 120.0,
90        mid: 80.0,
91        max: 50.0,
92    };
93}
94
95pub mod mania {
96    use super::GameModeHitWindows;
97
98    pub const PERFECT: GameModeHitWindows = GameModeHitWindows {
99        min: 22.4,
100        mid: 19.4,
101        max: 13.9,
102    };
103
104    pub const GREAT: GameModeHitWindows = GameModeHitWindows {
105        min: 64.0,
106        mid: 49.0,
107        max: 34.0,
108    };
109
110    pub const GOOD: GameModeHitWindows = GameModeHitWindows {
111        min: 97.0,
112        mid: 82.0,
113        max: 67.0,
114    };
115
116    pub const OK: GameModeHitWindows = GameModeHitWindows {
117        min: 127.0,
118        mid: 112.0,
119        max: 97.0,
120    };
121
122    pub const MEH: GameModeHitWindows = GameModeHitWindows {
123        min: 151.0,
124        mid: 136.0,
125        max: 121.0,
126    };
127}
128
129// Same in both Osu and Catch
130pub const AR: GameModeHitWindows = GameModeHitWindows {
131    min: 1800.0,
132    mid: 1200.0,
133    max: 450.0,
134};