Skip to main content

rosu_pp/model/beatmap/attributes/
attribute.rs

1/// A beatmap attribute.
2///
3/// It contains either:
4/// - the default value (5.0)
5/// - a value taken from a [`Beatmap`] or mutated default value
6/// - a user-given value that may be adjusted
7/// - a user-given *fixed* value that will stay as-is
8///
9/// [`Beatmap`]: crate::Beatmap
10#[derive(Copy, Clone, Debug, Default, PartialEq)]
11pub enum BeatmapAttribute {
12    /// No value has been set.
13    ///
14    /// Will be treated as the default value (5.0).
15    #[default]
16    None,
17    /// Variable value taken from a [`Beatmap`] or mutated default value that
18    /// may be overriden and adjusted based on mods and clock rate.
19    ///
20    /// [`Beatmap`]: crate::Beatmap
21    Value(f32),
22    /// Given by the user and may not be overriden by custom mod values.
23    ///
24    /// Mods and clock rate may *adjust* the value, though.
25    ///
26    /// # Example
27    /// Mods include `DifficultyAdjust` which sets AR to 9.5 but the user
28    /// specified AR to be 9.7. In this case, the user's value is should take
29    /// precedence.
30    Given(f32),
31    /// Represents a final value that should not be adjusted based on mods or
32    /// clock rate.
33    Fixed(f32),
34}
35
36impl BeatmapAttribute {
37    /// The default value for a `BeatmapAttribute`.
38    pub const DEFAULT: f32 = 5.0;
39
40    /// Overwrites `self` with `other` if `other` is not `None`.
41    #[must_use]
42    pub const fn overwrite(self, other: Self) -> Self {
43        if let Self::None = other { self } else { other }
44    }
45
46    /// Mutates the `Value` and `Given` variants.
47    pub fn try_mutate(&mut self, f: impl Fn(&mut f32)) {
48        if let Self::None = self {
49            *self = Self::Value(Self::DEFAULT);
50        }
51
52        if let Self::Value(value) | Self::Given(value) = self {
53            f(value);
54        }
55    }
56
57    /// Sets the `Value` variant only.
58    pub const fn try_set(&mut self, value: f32) {
59        match self {
60            Self::None => *self = Self::Value(value),
61            Self::Value(old) => *old = value,
62            _ => {}
63        }
64    }
65
66    /// Applies `f` onto the `Value` and `Given` variants and `default` onto the
67    /// `Fixed` variant.
68    pub fn map_or_else<U, D, F>(self, default: D, f: F) -> U
69    where
70        D: FnOnce(f32) -> U,
71        F: FnOnce(f32) -> U,
72    {
73        match self {
74            Self::None => f(Self::DEFAULT),
75            Self::Value(value) | Self::Given(value) => f(value),
76            Self::Fixed(fixed) => default(fixed),
77        }
78    }
79
80    pub const fn get_raw(self) -> f32 {
81        match self {
82            Self::None => Self::DEFAULT,
83            Self::Value(value) | Self::Given(value) | Self::Fixed(value) => value,
84        }
85    }
86}