expose Converted::map
This commit is contained in:
+18
-37
@@ -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
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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()
|
||||
};
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
})
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
@@ -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);
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user