added Beatmap::bpm and DifficultyAttributes::max_combo methods

This commit is contained in:
MaxOhn
2021-11-21 03:28:19 +01:00
parent f2e8a2e4c3
commit 79bc7441e8
3 changed files with 99 additions and 6 deletions
+2
View File
@@ -6,6 +6,8 @@
- [BREAKING] Removed the `last_control_point` field of `HitObjectKind::Slider` when neither the `osu` nor the `fruits` feature is enabled.
- Fixed out of bounds panic on maps with single-control-point linear sliders
- [BREAKING] Added the field `TaikoDifficultyAttributes::max_combo`
- Added method `Beatmap::bpm`
- Added method `DifficultyAttributes::max_combo`
# v0.3.0
+32 -1
View File
@@ -318,6 +318,37 @@ impl DifficultyAttributes {
Self::Taiko(attributes) => attributes.stars,
}
}
/// The max combo of the map.
///
/// This will only be `None` for attributes of osu!mania maps.
#[inline]
#[cfg(feature = "mania")]
pub fn max_combo(&self) -> Option<usize> {
match self {
#[cfg(feature = "fruits")]
Self::Fruits(attributes) => Some(attributes.max_combo),
Self::Mania(_) => None,
#[cfg(feature = "osu")]
Self::Osu(attributes) => Some(attributes.max_combo),
#[cfg(feature = "taiko")]
Self::Taiko(attributes) => Some(attributes.max_combo),
}
}
/// The max combo of the map.
#[inline]
#[cfg(not(feature = "mania"))]
pub fn max_combo(&self) -> usize {
match self {
#[cfg(feature = "fruits")]
Self::Fruits(attributes) => attributes.max_combo,
#[cfg(feature = "osu")]
Self::Osu(attributes) => attributes.max_combo,
#[cfg(feature = "taiko")]
Self::Taiko(attributes) => attributes.max_combo,
}
}
}
#[cfg(feature = "fruits")]
@@ -407,7 +438,7 @@ impl PerformanceAttributes {
#[cfg(feature = "osu")]
Self::Osu(attributes) => DifficultyAttributes::Osu(attributes.attributes.clone()),
#[cfg(feature = "taiko")]
Self::Taiko(attributes) => DifficultyAttributes::Taiko(attributes.attributes.clone()),
Self::Taiko(attributes) => DifficultyAttributes::Taiko(attributes.attributes),
}
}
}
+65 -5
View File
@@ -71,11 +71,7 @@ macro_rules! line_prepare {
($buf:ident) => {{
let mut line = $buf.trim_end();
if line.is_empty()
|| line.starts_with("//")
|| line.starts_with(' ')
|| line.starts_with('_')
{
if skip_line(line) {
$buf.clear();
continue;
}
@@ -284,6 +280,42 @@ macro_rules! parse_timingpoints_body {
(short => $self:ident, $reader:ident, $buf:ident, $section:ident) => {{
let mut empty = true;
// Only parse the first timing point to calculate the bpm
if read_line!($reader, $buf)? != 0 {
let line = {
let mut line = $buf.trim_end();
if skip_line(line) {
$buf.clear();
return Ok(empty);
}
if let Some(idx) = line.find("//") {
line = &line[..idx];
}
line
};
if line.starts_with('[') && line.ends_with(']') {
*$section = Section::from_str(&line[1..line.len() - 1]);
empty = false;
$buf.clear();
return Ok(empty);
}
let beat_len = line
.split(',')
.nth(1)
.next_field("beat_len")?
.trim()
.parse()?;
$self.bpm = bpm(beat_len);
$buf.clear();
}
while read_line!($reader, $buf)? != 0 {
let line = line_prepare!($buf);
@@ -782,6 +814,9 @@ pub struct Beatmap {
/// All hitobjects of the beatmap.
pub hit_objects: Vec<HitObject>,
#[cfg(not(any(feature = "osu", feature = "fruits")))]
bpm: f64,
#[cfg(any(feature = "osu", feature = "fruits"))]
/// Timing points that indicate a new timing section.
pub timing_points: Vec<TimingPoint>,
@@ -811,6 +846,23 @@ impl Beatmap {
pub fn attributes(&self) -> BeatmapAttributes {
BeatmapAttributes::new(self.ar, self.od, self.cs, self.hp)
}
/// The beats per minute of the map.
#[cfg(any(feature = "osu", feature = "fruits"))]
#[inline]
pub fn bpm(&self) -> f64 {
match self.timing_points.first() {
Some(point) => bpm(point.beat_len),
None => 0.0,
}
}
/// The beats per minute of the map.
#[cfg(not(any(feature = "osu", feature = "fruits")))]
#[inline]
pub fn bpm(&self) -> f64 {
self.bpm
}
}
#[cfg(feature = "sliders")]
@@ -996,6 +1048,14 @@ impl Beatmap {
from_path!(async Path);
}
fn bpm(beat_len: f64) -> f64 {
beat_len.recip() * 1000.0 * 60.0
}
fn skip_line(line: &str) -> bool {
line.is_empty() || line.starts_with("//") || line.starts_with(' ') || line.starts_with('_')
}
#[inline]
fn split_colon(line: &str) -> Option<(&str, &str)> {
let mut split = line.split(':');