expose Converted::map

This commit is contained in:
MaxOhn
2024-03-02 07:00:01 +01:00
parent 59dfc109e0
commit 6eac895339
20 changed files with 73 additions and 113 deletions
+18 -37
View File
@@ -45,13 +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_cow(converted.map)
Self::new_with_cow(converted.into_inner())
}
}
impl<'a, 'b: 'a> From<&'b Converted<'a, $mode>> for Difficulty<'a> {
fn from(converted: &'b Converted<'a, $mode>) -> Self {
Self::new(converted.map.as_ref())
Self::new(&converted)
}
}
};
@@ -73,10 +73,10 @@ impl Difficulty<'_> {
/// [`mode_or_ignore`]: Self::mode_or_ignore
pub fn try_mode(&mut self, mode: GameMode) -> Option<&mut Self> {
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,
GameMode::Osu => OsuBeatmap::try_from_ref(self.map.as_ref())?.into_inner(),
GameMode::Taiko => TaikoBeatmap::try_from_ref(self.map.as_ref())?.into_inner(),
GameMode::Catch => CatchBeatmap::try_from_ref(self.map.as_ref())?.into_inner(),
GameMode::Mania => ManiaBeatmap::try_from_ref(self.map.as_ref())?.into_inner(),
};
if matches!(map, Cow::Owned(_)) {
@@ -96,40 +96,21 @@ impl Difficulty<'_> {
///
/// [`try_mode`]: Self::try_mode
pub fn mode_or_ignore(&mut self, mode: GameMode) -> &mut Self {
let map = match mode {
GameMode::Osu => {
let Some(converted) = OsuBeatmap::try_from_ref(self.map.as_ref()) else {
return self;
};
let map = self.map.as_ref();
converted.map
}
GameMode::Taiko => {
let Some(converted) = TaikoBeatmap::try_from_ref(self.map.as_ref()) else {
return self;
};
converted.map
}
GameMode::Catch => {
let Some(converted) = CatchBeatmap::try_from_ref(self.map.as_ref()) else {
return self;
};
converted.map
}
GameMode::Mania => {
let Some(converted) = ManiaBeatmap::try_from_ref(self.map.as_ref()) else {
return self;
};
converted.map
}
let map_opt = match mode {
GameMode::Osu => OsuBeatmap::try_from_ref(map).map(Converted::into_inner),
GameMode::Taiko => TaikoBeatmap::try_from_ref(map).map(Converted::into_inner),
GameMode::Catch => CatchBeatmap::try_from_ref(map).map(Converted::into_inner),
GameMode::Mania => ManiaBeatmap::try_from_ref(map).map(Converted::into_inner),
};
if matches!(map, Cow::Owned(_)) {
let map = map.into_owned();
self.map = Cow::Owned(map);
match map_opt {
Some(cow @ Cow::Owned(_)) => {
let map = cow.into_owned();
self.map = Cow::Owned(map);
}
Some(Cow::Borrowed(_)) | None => {}
}
self
+1 -1
View File
@@ -68,7 +68,7 @@ pub fn convert_objects(
let mut last_pos = None;
let mut last_start_time = 0.0;
for h in converted.map.hit_objects.iter() {
for h in converted.hit_objects.iter() {
let mut new_objects = convert_object(h, converted, count, &mut bufs);
apply_pos_offset(
+1 -1
View File
@@ -53,7 +53,7 @@ impl CatchDifficultySetup {
let attrs = CatchDifficultyAttributes {
ar: map_attrs.ar,
is_convert: converted.map.is_convert,
is_convert: converted.is_convert,
..Default::default()
};
+2 -4
View File
@@ -28,16 +28,14 @@ impl<'a> JuiceStream<'a> {
count: &mut ObjectCountBuilder,
bufs: &'a mut JuiceStreamBufs,
) -> Self {
let slider_multiplier = converted.map.slider_multiplier;
let slider_tick_rate = converted.map.slider_tick_rate;
let slider_multiplier = converted.slider_multiplier;
let slider_tick_rate = converted.slider_tick_rate;
let beat_len = converted
.map
.timing_point_at(start_time)
.map_or(TimingPoint::DEFAULT_BEAT_LEN, |point| point.beat_len);
let slider_velocity = converted
.map
.difficulty_point_at(start_time)
.map_or(DifficultyPoint::DEFAULT_SLIDER_VELOCITY, |point| {
point.slider_velocity
+1 -1
View File
@@ -225,7 +225,7 @@ mod tests {
.unwrap()
.unchecked_into_converted::<Mania>();
let map = converted.map;
let map = &converted;
assert!(map.is_convert);
assert_eq!(map.mode, GameMode::Mania);
+5 -7
View File
@@ -64,9 +64,9 @@ impl ManiaGradualDifficulty {
pub fn new(difficulty: &ModeDifficulty, converted: &ManiaBeatmap<'_>) -> Self {
let take = difficulty.get_passed_objects();
let mods = difficulty.get_mods();
let total_columns = converted.map.cs.round_even().max(1.0);
let total_columns = converted.cs.round_even().max(1.0);
let clock_rate = difficulty.get_clock_rate();
let mut params = ObjectParams::new(converted.map.as_ref());
let mut params = ObjectParams::new(&converted);
let HitWindows { od: hit_window, .. } = converted
.attributes()
@@ -75,7 +75,6 @@ impl ManiaGradualDifficulty {
.hit_windows();
let mania_objects = converted
.map
.hit_objects
.iter()
.map(|h| ManiaObject::new(h, total_columns, &mut params))
@@ -88,13 +87,12 @@ impl ManiaGradualDifficulty {
let mut curr_combo = 0;
let objects_is_circle: Box<[_]> = converted
.map
.hit_objects
.iter()
.map(HitObject::is_circle)
.collect();
if let Some(h) = converted.map.hit_objects.first() {
if let Some(h) = converted.hit_objects.first() {
let hit_object = ManiaObject::new(h, total_columns, &mut params);
increment_combo_raw(
@@ -110,7 +108,7 @@ impl ManiaGradualDifficulty {
mods,
clock_rate,
objects_is_circle,
is_convert: converted.map.is_convert,
is_convert: converted.is_convert,
strain,
diff_objects,
hit_window,
@@ -239,7 +237,7 @@ mod tests {
let mut gradual_2nd = ManiaGradualDifficulty::new(&difficulty, &converted);
let mut gradual_3rd = ManiaGradualDifficulty::new(&difficulty, &converted);
let hit_objects_len = converted.map.hit_objects.len();
let hit_objects_len = converted.hit_objects.len();
for i in 1.. {
let Some(next_gradual) = gradual.next() else {
+4 -8
View File
@@ -21,10 +21,7 @@ pub fn difficulty(
difficulty: &ModeDifficulty,
converted: &ManiaBeatmap<'_>,
) -> ManiaDifficultyAttributes {
let n_objects = cmp::min(
difficulty.get_passed_objects(),
converted.map.hit_objects.len(),
) as u32;
let n_objects = cmp::min(difficulty.get_passed_objects(), converted.hit_objects.len()) as u32;
let values = DifficultyValues::calculate(difficulty, converted);
@@ -40,7 +37,7 @@ pub fn difficulty(
hit_window,
max_combo: values.max_combo,
n_objects,
is_convert: converted.map.is_convert,
is_convert: converted.is_convert,
}
}
@@ -52,12 +49,11 @@ pub struct DifficultyValues {
impl DifficultyValues {
pub fn calculate(difficulty: &ModeDifficulty, converted: &ManiaBeatmap<'_>) -> Self {
let take = difficulty.get_passed_objects();
let total_columns = converted.map.cs.round_even().max(1.0);
let total_columns = converted.cs.round_even().max(1.0);
let clock_rate = difficulty.get_clock_rate();
let mut params = ObjectParams::new(converted.map.as_ref());
let mut params = ObjectParams::new(&converted);
let mania_objects = converted
.map
.hit_objects
.iter()
.map(|h| ManiaObject::new(h, total_columns, &mut params))
+1 -1
View File
@@ -137,7 +137,7 @@ mod tests {
let mut state = ManiaScoreState::default();
let hit_objects_len = converted.map.hit_objects.len();
let hit_objects_len = converted.hit_objects.len();
for i in 1.. {
state.misses += 1;
+1 -1
View File
@@ -938,7 +938,7 @@ mod tests {
let attrs = ModeDifficulty::new().calculate(&converted);
assert_eq!(N_OBJECTS, converted.map.hit_objects.len() as u32);
assert_eq!(N_OBJECTS, converted.hit_objects.len() as u32);
attrs
})
+1 -1
View File
@@ -239,7 +239,7 @@ impl From<&Beatmap> for BeatmapAttributesBuilder {
impl<M> From<&Converted<'_, M>> for BeatmapAttributesBuilder {
fn from(converted: &Converted<'_, M>) -> Self {
Self::new(converted.map.as_ref())
Self::new(&converted)
}
}
+14 -18
View File
@@ -3,6 +3,7 @@ use std::{
borrow::Cow,
fmt::{Debug, Formatter, Result as FmtResult},
marker::PhantomData,
ops::Deref,
};
use crate::{
@@ -10,7 +11,7 @@ use crate::{
ModeDifficulty,
};
use super::{attributes::BeatmapAttributesBuilder, Beatmap};
use super::Beatmap;
const INCOMPATIBLE_MODES: &str = "the gamemodes were incompatible";
@@ -29,7 +30,7 @@ const INCOMPATIBLE_MODES: &str = "the gamemodes were incompatible";
///
/// All other conversions are incompatible.
pub struct Converted<'a, M> {
pub(crate) map: Cow<'a, Beatmap>,
map: Cow<'a, Beatmap>,
mode: PhantomData<M>,
}
@@ -42,23 +43,10 @@ impl<'a, M> Converted<'a, M> {
mode: PhantomData,
}
}
}
impl<M> Converted<'_, M> {
/// Sum up the duration of all breaks (in milliseconds).
pub fn total_break_time(&self) -> f64 {
self.map.total_break_time()
}
/// Returns a [`BeatmapAttributesBuilder`] to calculate modified beatmap
/// attributes.
pub fn attributes(&self) -> BeatmapAttributesBuilder {
self.into()
}
/// The beats per minute of the map.
pub fn bpm(&self) -> f64 {
self.map.bpm()
/// Returns the internal [`Beatmap`].
pub fn into_inner(self) -> Cow<'a, Beatmap> {
self.map
}
}
@@ -212,3 +200,11 @@ impl<M> PartialEq for Converted<'_, M> {
self.map == other.map
}
}
impl<M> Deref for Converted<'_, M> {
type Target = Beatmap;
fn deref(&self) -> &Self::Target {
self.map.as_ref()
}
}
+2 -3
View File
@@ -40,7 +40,6 @@ pub fn convert_objects(
let mut ticks_buf = Vec::new();
let mut osu_objects: Box<[_]> = converted
.map
.hit_objects
.iter()
.map(|h| OsuObject::new(h, converted, &mut curve_bufs, &mut ticks_buf))
@@ -71,9 +70,9 @@ pub fn convert_objects(
osu_objects.iter_mut().for_each(OsuObject::finalize_tail);
}
let stack_threshold = time_preempt * f64::from(converted.map.stack_leniency);
let stack_threshold = time_preempt * f64::from(converted.stack_leniency);
if converted.map.version >= 6 {
if converted.version >= 6 {
stacking(&mut osu_objects, stack_threshold);
} else {
old_stacking(&mut osu_objects, stack_threshold);
+2 -2
View File
@@ -89,7 +89,7 @@ impl OsuGradualDifficulty {
&scaling_factor,
mods.hr(),
time_preempt,
converted.map.hit_objects.len(),
converted.hit_objects.len(),
&mut attrs,
);
@@ -290,7 +290,7 @@ mod tests {
let mut gradual_2nd = OsuGradualDifficulty::new(&difficulty, &converted);
let mut gradual_3rd = OsuGradualDifficulty::new(&difficulty, &converted);
let hit_objects_len = converted.map.hit_objects.len();
let hit_objects_len = converted.hit_objects.len();
for i in 1.. {
let Some(next_gradual) = gradual.next() else {
+1 -2
View File
@@ -140,8 +140,7 @@ impl DifficultyValues {
let mut flashlight = Skill::new(&mut skills.flashlight, &diff_objects);
// The first hit object has no difficulty object
let take_diff_objects =
cmp::min(converted.map.hit_objects.len(), take).saturating_sub(1);
let take_diff_objects = cmp::min(converted.hit_objects.len(), take).saturating_sub(1);
for hit_object in diff_objects.iter().take(take_diff_objects) {
aim.process(hit_object);
+10 -12
View File
@@ -167,22 +167,20 @@ impl OsuSlider {
ticks_buf: &mut Vec<SliderEvent>,
) -> Self {
let start_time = h.start_time;
let slider_multiplier = converted.map.slider_multiplier;
let slider_tick_rate = converted.map.slider_tick_rate;
let slider_multiplier = converted.slider_multiplier;
let slider_tick_rate = converted.slider_tick_rate;
let beat_len = converted
.map
.timing_point_at(start_time)
.map_or(TimingPoint::DEFAULT_BEAT_LEN, |point| point.beat_len);
let (slider_velocity, generate_ticks) =
converted.map.difficulty_point_at(start_time).map_or(
(
DifficultyPoint::DEFAULT_SLIDER_VELOCITY,
DifficultyPoint::DEFAULT_GENERATE_TICKS,
),
|point| (point.slider_velocity, point.generate_ticks),
);
let (slider_velocity, generate_ticks) = converted.difficulty_point_at(start_time).map_or(
(
DifficultyPoint::DEFAULT_SLIDER_VELOCITY,
DifficultyPoint::DEFAULT_GENERATE_TICKS,
),
|point| (point.slider_velocity, point.generate_ticks),
);
let path = slider.curve(curve_bufs);
@@ -197,7 +195,7 @@ impl OsuSlider {
let duration = end_time - start_time;
let span_duration = duration / span_count;
let tick_dist_multiplier = if converted.map.version < 8 {
let tick_dist_multiplier = if converted.version < 8 {
slider_velocity.recip()
} else {
1.0
+1 -1
View File
@@ -147,7 +147,7 @@ mod tests {
let mut state = OsuScoreState::default();
let hit_objects_len = converted.map.hit_objects.len();
let hit_objects_len = converted.hit_objects.len();
for i in 1.. {
state.misses += 1;
+4 -6
View File
@@ -75,8 +75,8 @@ impl TaikoGradualDifficulty {
let clock_rate = difficulty.get_clock_rate();
let first_combos = match (
converted.map.hit_objects.first().map(HitObject::is_circle),
converted.map.hit_objects.get(1).map(HitObject::is_circle),
converted.hit_objects.first().map(HitObject::is_circle),
converted.hit_objects.get(1).map(HitObject::is_circle),
) {
(None, _) | (Some(false), Some(false) | None) => FirstTwoCombos::None,
(Some(true), Some(false) | None) => FirstTwoCombos::OnlyFirst,
@@ -105,12 +105,11 @@ impl TaikoGradualDifficulty {
let attrs = TaikoDifficultyAttributes {
hit_window,
is_convert: converted.map.is_convert,
is_convert: converted.is_convert,
..Default::default()
};
let total_hits = converted
.map
.hit_objects
.iter()
.filter(|h| h.is_circle())
@@ -288,10 +287,9 @@ mod tests {
let mut gradual_2nd = TaikoGradualDifficulty::new(&difficulty, &converted);
let mut gradual_3rd = TaikoGradualDifficulty::new(&difficulty, &converted);
let hit_objects_len = converted.map.hit_objects.len();
let hit_objects_len = converted.hit_objects.len();
let n_hits = converted
.map
.hit_objects
.iter()
.filter(|h| h.is_circle())
+3 -4
View File
@@ -40,7 +40,7 @@ pub fn difficulty(
let mut attrs = TaikoDifficultyAttributes {
hit_window,
max_combo,
is_convert: converted.map.is_convert,
is_convert: converted.is_convert,
..Default::default()
};
@@ -146,10 +146,9 @@ impl DifficultyValues {
n_diff_objects: &mut usize,
) -> TaikoDifficultyObjects {
let mut hit_objects_iter = converted
.map
.hit_objects
.iter()
.zip(converted.map.hit_sounds.iter())
.zip(converted.hit_sounds.iter())
.map(|(h, s)| TaikoObject::new(h, *s))
.inspect(|h| {
if *max_combo < take {
@@ -164,7 +163,7 @@ impl DifficultyValues {
};
let mut diff_objects =
TaikoDifficultyObjects::with_capacity(converted.map.hit_objects.len() - 2);
TaikoDifficultyObjects::with_capacity(converted.hit_objects.len() - 2);
for (i, curr) in hit_objects_iter.enumerate() {
let diff_object = TaikoDifficultyObject::new(
+1 -2
View File
@@ -143,10 +143,9 @@ mod tests {
let mut state = TaikoScoreState::default();
let hit_objects_len = converted.map.hit_objects.len();
let hit_objects_len = converted.hit_objects.len();
let n_hits = converted
.map
.hit_objects
.iter()
.filter(|h| h.is_circle())
-1
View File
@@ -316,7 +316,6 @@ impl<'map> TryFrom<OsuPerformance<'map>> for TaikoPerformance<'map> {
/// was called.
///
/// [`OsuDifficultyAttributes`]: crate::osu::OsuDifficultyAttributes
fn try_from(mut osu: OsuPerformance<'map>) -> Result<Self, Self::Error> {
let MapOrAttrs::Map(converted) = osu.map_or_attrs else {
return Err(osu);