store is_convert in Beatmap itself

This commit is contained in:
MaxOhn
2024-03-02 06:27:52 +01:00
parent 0f23f81234
commit 59dfc109e0
16 changed files with 66 additions and 115 deletions
+4 -10
View File
@@ -65,16 +65,10 @@ impl GradualDifficulty {
let map = Cow::Borrowed(map);
match map.mode {
GameMode::Osu => Self::Osu(difficulty.gradual_difficulty(&OsuBeatmap::new(map, false))),
GameMode::Taiko => {
Self::Taiko(difficulty.gradual_difficulty(&TaikoBeatmap::new(map, false)))
}
GameMode::Catch => {
Self::Catch(difficulty.gradual_difficulty(&CatchBeatmap::new(map, false)))
}
GameMode::Mania => {
Self::Mania(difficulty.gradual_difficulty(&ManiaBeatmap::new(map, false)))
}
GameMode::Osu => Self::Osu(difficulty.gradual_difficulty(&OsuBeatmap::new(map))),
GameMode::Taiko => Self::Taiko(difficulty.gradual_difficulty(&TaikoBeatmap::new(map))),
GameMode::Catch => Self::Catch(difficulty.gradual_difficulty(&CatchBeatmap::new(map))),
GameMode::Mania => Self::Mania(difficulty.gradual_difficulty(&ManiaBeatmap::new(map))),
}
}
+27 -61
View File
@@ -24,20 +24,18 @@ pub mod skills;
#[must_use]
pub struct Difficulty<'map> {
map: Cow<'map, Beatmap>,
is_convert: bool,
inner: ModeDifficulty,
}
impl<'map> Difficulty<'map> {
/// Create a new difficulty calculator for the given beatmap.
pub const fn new(map: &'map Beatmap) -> Self {
Self::new_with_is_convert(Cow::Borrowed(map), false)
Self::new_with_cow(Cow::Borrowed(map))
}
const fn new_with_is_convert(map: Cow<'map, Beatmap>, is_convert: bool) -> Self {
const fn new_with_cow(map: Cow<'map, Beatmap>) -> Self {
Self {
map,
is_convert,
inner: ModeDifficulty::new(),
}
}
@@ -47,16 +45,13 @@ macro_rules! impl_from_mode {
( $mode:ident ) => {
impl<'a> From<Converted<'a, $mode>> for Difficulty<'a> {
fn from(converted: Converted<'a, $mode>) -> Self {
Self::new_with_is_convert(converted.map, converted.is_convert)
Self::new_with_cow(converted.map)
}
}
impl<'a, 'b: 'a> From<&'b Converted<'a, $mode>> for Difficulty<'a> {
fn from(converted: &'b Converted<'a, $mode>) -> Self {
Self::new_with_is_convert(
Cow::Borrowed(converted.map.as_ref()),
converted.is_convert,
)
Self::new(converted.map.as_ref())
}
}
};
@@ -77,31 +72,14 @@ impl Difficulty<'_> {
///
/// [`mode_or_ignore`]: Self::mode_or_ignore
pub fn try_mode(&mut self, mode: GameMode) -> Option<&mut Self> {
let (map, is_convert) = match mode {
GameMode::Osu => {
let converted = OsuBeatmap::try_from_ref(self.map.as_ref())?;
(converted.map, converted.is_convert)
}
GameMode::Taiko => {
let converted = TaikoBeatmap::try_from_ref(self.map.as_ref())?;
(converted.map, converted.is_convert)
}
GameMode::Catch => {
let converted = CatchBeatmap::try_from_ref(self.map.as_ref())?;
(converted.map, converted.is_convert)
}
GameMode::Mania => {
let converted = ManiaBeatmap::try_from_ref(self.map.as_ref())?;
(converted.map, converted.is_convert)
}
let map = match mode {
GameMode::Osu => OsuBeatmap::try_from_ref(self.map.as_ref())?.map,
GameMode::Taiko => TaikoBeatmap::try_from_ref(self.map.as_ref())?.map,
GameMode::Catch => CatchBeatmap::try_from_ref(self.map.as_ref())?.map,
GameMode::Mania => ManiaBeatmap::try_from_ref(self.map.as_ref())?.map,
};
if matches!(map, Cow::Owned(_)) {
self.is_convert |= is_convert;
let map = map.into_owned();
self.map = Cow::Owned(map);
}
@@ -118,39 +96,38 @@ impl Difficulty<'_> {
///
/// [`try_mode`]: Self::try_mode
pub fn mode_or_ignore(&mut self, mode: GameMode) -> &mut Self {
let (map, is_convert) = match mode {
let map = match mode {
GameMode::Osu => {
let Some(converted) = OsuBeatmap::try_from_ref(self.map.as_ref()) else {
return self;
};
(converted.map, converted.is_convert)
converted.map
}
GameMode::Taiko => {
let Some(converted) = TaikoBeatmap::try_from_ref(self.map.as_ref()) else {
return self;
};
(converted.map, converted.is_convert)
converted.map
}
GameMode::Catch => {
let Some(converted) = CatchBeatmap::try_from_ref(self.map.as_ref()) else {
return self;
};
(converted.map, converted.is_convert)
converted.map
}
GameMode::Mania => {
let Some(converted) = ManiaBeatmap::try_from_ref(self.map.as_ref()) else {
return self;
};
(converted.map, converted.is_convert)
converted.map
}
};
if matches!(map, Cow::Owned(_)) {
self.is_convert |= is_convert;
let map = map.into_owned();
self.map = Cow::Owned(map);
}
@@ -191,22 +168,19 @@ impl Difficulty<'_> {
///
/// The returned attributes depend on the map's mode.
pub fn calculate(&self) -> DifficultyAttributes {
let is_convert = self.is_convert;
let map = Cow::Borrowed(self.map.as_ref());
match self.map.mode {
GameMode::Osu => {
DifficultyAttributes::Osu(self.inner.calculate(&OsuBeatmap::new(map, is_convert)))
GameMode::Osu => DifficultyAttributes::Osu(self.inner.calculate(&OsuBeatmap::new(map))),
GameMode::Taiko => {
DifficultyAttributes::Taiko(self.inner.calculate(&TaikoBeatmap::new(map)))
}
GameMode::Catch => {
DifficultyAttributes::Catch(self.inner.calculate(&CatchBeatmap::new(map)))
}
GameMode::Mania => {
DifficultyAttributes::Mania(self.inner.calculate(&ManiaBeatmap::new(map)))
}
GameMode::Taiko => DifficultyAttributes::Taiko(
self.inner.calculate(&TaikoBeatmap::new(map, is_convert)),
),
GameMode::Catch => DifficultyAttributes::Catch(
self.inner.calculate(&CatchBeatmap::new(map, is_convert)),
),
GameMode::Mania => DifficultyAttributes::Mania(
self.inner.calculate(&ManiaBeatmap::new(map, is_convert)),
),
}
}
@@ -218,18 +192,10 @@ impl Difficulty<'_> {
let map = Cow::Borrowed(self.map.as_ref());
match self.map.mode {
GameMode::Osu => {
Strains::Osu(self.inner.strains(&OsuBeatmap::new(map, self.is_convert)))
}
GameMode::Taiko => {
Strains::Taiko(self.inner.strains(&TaikoBeatmap::new(map, self.is_convert)))
}
GameMode::Catch => {
Strains::Catch(self.inner.strains(&CatchBeatmap::new(map, self.is_convert)))
}
GameMode::Mania => {
Strains::Mania(self.inner.strains(&ManiaBeatmap::new(map, self.is_convert)))
}
GameMode::Osu => Strains::Osu(self.inner.strains(&OsuBeatmap::new(map))),
GameMode::Taiko => Strains::Taiko(self.inner.strains(&TaikoBeatmap::new(map))),
GameMode::Catch => Strains::Catch(self.inner.strains(&CatchBeatmap::new(map))),
GameMode::Mania => Strains::Mania(self.inner.strains(&ManiaBeatmap::new(map))),
}
}
}
+4 -12
View File
@@ -114,18 +114,10 @@ impl GradualPerformance {
let map = Cow::Borrowed(map);
match map.mode {
GameMode::Osu => {
Self::Osu(difficulty.gradual_performance(&OsuBeatmap::new(map, false)))
}
GameMode::Taiko => {
Self::Taiko(difficulty.gradual_performance(&TaikoBeatmap::new(map, false)))
}
GameMode::Catch => {
Self::Catch(difficulty.gradual_performance(&CatchBeatmap::new(map, false)))
}
GameMode::Mania => {
Self::Mania(difficulty.gradual_performance(&ManiaBeatmap::new(map, false)))
}
GameMode::Osu => Self::Osu(difficulty.gradual_performance(&OsuBeatmap::new(map))),
GameMode::Taiko => Self::Taiko(difficulty.gradual_performance(&TaikoBeatmap::new(map))),
GameMode::Catch => Self::Catch(difficulty.gradual_performance(&CatchBeatmap::new(map))),
GameMode::Mania => Self::Mania(difficulty.gradual_performance(&ManiaBeatmap::new(map))),
}
}
+4 -4
View File
@@ -35,10 +35,10 @@ impl<'map> Performance<'map> {
let map = Cow::Borrowed(map);
match mode {
GameMode::Osu => Self::Osu(OsuPerformance::new(Converted::new(map, false))),
GameMode::Taiko => Self::Taiko(TaikoPerformance::new(Converted::new(map, false))),
GameMode::Catch => Self::Catch(CatchPerformance::new(Converted::new(map, false))),
GameMode::Mania => Self::Mania(ManiaPerformance::new(Converted::new(map, false))),
GameMode::Osu => Self::Osu(OsuPerformance::new(Converted::new(map))),
GameMode::Taiko => Self::Taiko(TaikoPerformance::new(Converted::new(map))),
GameMode::Catch => Self::Catch(CatchPerformance::new(Converted::new(map))),
GameMode::Mania => Self::Mania(ManiaPerformance::new(Converted::new(map))),
}
}
+1
View File
@@ -38,6 +38,7 @@ pub fn try_convert(map: &mut Beatmap) -> ConvertStatus {
match map.mode {
GameMode::Osu => {
map.mode = GameMode::Catch;
map.is_convert = true;
ConvertStatus::Conversion
}
+1 -1
View File
@@ -53,7 +53,7 @@ impl CatchDifficultySetup {
let attrs = CatchDifficultyAttributes {
ar: map_attrs.ar,
is_convert: converted.is_convert,
is_convert: converted.map.is_convert,
..Default::default()
};
+2 -2
View File
@@ -170,6 +170,7 @@ fn convert(map: &mut Beatmap) {
sort::osu_legacy(&mut map.hit_objects);
map.mode = GameMode::Mania;
map.is_convert = true;
}
pub struct PrevValues {
@@ -224,9 +225,8 @@ mod tests {
.unwrap()
.unchecked_into_converted::<Mania>();
assert!(converted.is_convert);
let map = converted.map;
assert!(map.is_convert);
assert_eq!(map.mode, GameMode::Mania);
assert_eq!(map.version, 14);
+1 -1
View File
@@ -110,7 +110,7 @@ impl ManiaGradualDifficulty {
mods,
clock_rate,
objects_is_circle,
is_convert: converted.is_convert,
is_convert: converted.map.is_convert,
strain,
diff_objects,
hit_window,
+1 -1
View File
@@ -40,7 +40,7 @@ pub fn difficulty(
hit_window,
max_combo: values.max_combo,
n_objects,
is_convert: converted.is_convert,
is_convert: converted.map.is_convert,
}
}
+3 -7
View File
@@ -34,13 +34,13 @@ pub struct HitWindows {
#[derive(Clone, Debug, Default, PartialEq)]
pub struct BeatmapAttributesBuilder {
mode: GameMode,
is_convert: bool,
ar: f32,
od: f32,
cs: f32,
hp: f32,
mods: u32,
clock_rate: Option<f64>,
is_convert: bool,
}
impl BeatmapAttributesBuilder {
@@ -54,10 +54,6 @@ impl BeatmapAttributesBuilder {
/// Create a new [`BeatmapAttributesBuilder`].
pub const fn new(map: &Beatmap) -> Self {
Self::new_internal(map, false)
}
const fn new_internal(map: &Beatmap, is_convert: bool) -> Self {
Self {
mode: map.mode,
ar: map.ar,
@@ -66,7 +62,7 @@ impl BeatmapAttributesBuilder {
hp: map.hp,
mods: 0,
clock_rate: None,
is_convert,
is_convert: map.is_convert,
}
}
@@ -243,7 +239,7 @@ impl From<&Beatmap> for BeatmapAttributesBuilder {
impl<M> From<&Converted<'_, M>> for BeatmapAttributesBuilder {
fn from(converted: &Converted<'_, M>) -> Self {
Self::new_internal(converted.map.as_ref(), converted.is_convert)
Self::new(converted.map.as_ref())
}
}
+12 -14
View File
@@ -30,17 +30,15 @@ const INCOMPATIBLE_MODES: &str = "the gamemodes were incompatible";
/// All other conversions are incompatible.
pub struct Converted<'a, M> {
pub(crate) map: Cow<'a, Beatmap>,
pub(crate) is_convert: bool,
mode: PhantomData<M>,
}
impl<'a, M> Converted<'a, M> {
/// Initialize a [`Converted`] beatmap by promising the given map's mode
/// matches the generic type `M`.
pub(crate) const fn new(map: Cow<'a, Beatmap>, is_convert: bool) -> Self {
pub(crate) const fn new(map: Cow<'a, Beatmap>) -> Self {
Self {
map,
is_convert,
mode: PhantomData,
}
}
@@ -72,8 +70,8 @@ impl<M: IGameMode> Converted<'_, M> {
#[allow(clippy::result_large_err)]
pub fn try_from_owned(mut map: Beatmap) -> Result<Self, Beatmap> {
match M::try_convert(&mut map) {
ConvertStatus::Noop => Ok(Self::new(Cow::Owned(map), false)),
ConvertStatus::Conversion => Ok(Self::new(Cow::Owned(map), true)),
ConvertStatus::Noop => Ok(Self::new(Cow::Owned(map))),
ConvertStatus::Conversion => Ok(Self::new(Cow::Owned(map))),
ConvertStatus::Incompatible => Err(map),
}
}
@@ -106,7 +104,7 @@ impl<'a, M: IGameMode> Converted<'a, M> {
/// shorter.
#[must_use]
pub fn as_owned(&'a self) -> Self {
Self::new(Cow::Borrowed(self.map.as_ref()), self.is_convert)
Self::new(Cow::Borrowed(self.map.as_ref()))
}
/// Create a performance calculator for the map.
@@ -121,14 +119,14 @@ impl<'a, M: IGameMode> Converted<'a, M> {
/// [`&Beatmap`]: Beatmap
pub fn try_from_ref(map: &'a Beatmap) -> Option<Self> {
let mut map = match M::check_convert(map) {
ConvertStatus::Noop => return Some(Self::new(Cow::Borrowed(map), false)),
ConvertStatus::Noop => return Some(Self::new(Cow::Borrowed(map))),
ConvertStatus::Conversion => map.to_owned(),
ConvertStatus::Incompatible => return None,
};
match M::try_convert(&mut map) {
ConvertStatus::Conversion => Some(Self::new(Cow::Owned(map), true)),
ConvertStatus::Noop => Some(Self::new(Cow::Owned(map), false)),
ConvertStatus::Conversion => Some(Self::new(Cow::Owned(map))),
ConvertStatus::Noop => Some(Self::new(Cow::Owned(map))),
ConvertStatus::Incompatible => None,
}
}
@@ -152,8 +150,9 @@ impl<'a, M: IGameMode> Converted<'a, M> {
pub fn try_convert<N: IGameMode>(self) -> Result<Converted<'a, N>, Self> {
match self.map {
Cow::Borrowed(map) => Converted::<N>::try_from_ref(map).ok_or(self),
Cow::Owned(map) => Converted::<N>::try_from_owned(map)
.map_err(|map| Self::new(Cow::Owned(map), self.is_convert)),
Cow::Owned(map) => {
Converted::<N>::try_from_owned(map).map_err(|map| Self::new(Cow::Owned(map)))
}
}
}
@@ -172,7 +171,7 @@ impl<'a, M: IGameMode> Converted<'a, M> {
impl<M> Clone for Converted<'_, M> {
fn clone(&self) -> Self {
Self::new(self.map.clone(), self.is_convert)
Self::new(self.map.clone())
}
}
@@ -203,7 +202,6 @@ impl<M> Debug for Converted<'_, M> {
f.debug_struct("Converted")
.field("map", &self.map)
.field("is_convert", &self.is_convert)
.field("mode", &GenericFormatter::<M>::default())
.finish()
}
@@ -211,6 +209,6 @@ impl<M> Debug for Converted<'_, M> {
impl<M> PartialEq for Converted<'_, M> {
fn eq(&self, other: &Self) -> bool {
self.map == other.map && self.is_convert == other.is_convert
self.map == other.map
}
}
+1
View File
@@ -297,6 +297,7 @@ impl From<BeatmapState> for Beatmap {
Beatmap {
version: state.version,
is_convert: false,
stack_leniency: state.stack_leniency,
mode: state.mode,
ar: approach_rate,
+2
View File
@@ -32,6 +32,7 @@ mod decode;
#[derive(Clone, Debug, PartialEq)]
pub struct Beatmap {
pub version: i32,
pub is_convert: bool,
// General
pub stack_leniency: f32,
@@ -176,6 +177,7 @@ impl Default for Beatmap {
fn default() -> Self {
Self {
version: LATEST_FORMAT_VERSION,
is_convert: false,
stack_leniency: DEFAULT_SLIDER_LENIENCY,
mode: GameMode::default(),
ar: 5.0,
+1
View File
@@ -119,6 +119,7 @@ fn convert(map: &mut Beatmap) {
sorter.sort(&mut map.hit_sounds);
map.mode = GameMode::Taiko;
map.is_convert = true;
}
fn should_convert_slider_to_taiko_hits(map: &Beatmap, params: &mut SliderParams<'_>) -> bool {
+1 -1
View File
@@ -105,7 +105,7 @@ impl TaikoGradualDifficulty {
let attrs = TaikoDifficultyAttributes {
hit_window,
is_convert: converted.is_convert,
is_convert: converted.map.is_convert,
..Default::default()
};
+1 -1
View File
@@ -40,7 +40,7 @@ pub fn difficulty(
let mut attrs = TaikoDifficultyAttributes {
hit_window,
max_combo,
is_convert: converted.is_convert,
is_convert: converted.map.is_convert,
..Default::default()
};