chore: bump to older tag build

This commit is contained in:
2026-06-26 13:48:41 +02:00
commit da105ffb14
115 changed files with 28879 additions and 0 deletions
+43
View File
@@ -0,0 +1,43 @@
use rosu_pp::{Beatmap, CatchPP, GameMode, ManiaPP, OsuPP, TaikoPP};
#[test]
fn osu() {
let map = Beatmap::default();
let _ = OsuPP::new(&map).calculate();
}
#[test]
fn taiko() {
let mut map = Beatmap::default();
// convert
let _ = TaikoPP::new(&map).calculate();
// regular
map.mode = GameMode::Taiko;
let _ = TaikoPP::new(&map).calculate();
}
#[test]
fn catch() {
let mut map = Beatmap::default();
// convert
let _ = CatchPP::new(&map).calculate();
// regular
map.mode = GameMode::Catch;
let _ = CatchPP::new(&map).calculate();
}
#[test]
fn mania() {
let mut map = Beatmap::default();
// convert
let _ = ManiaPP::new(&map).calculate();
// regular
map.mode = GameMode::Mania;
let _ = ManiaPP::new(&map).calculate();
}
+30
View File
@@ -0,0 +1,30 @@
mod mode;
use rosu_pp::Beatmap;
pub use self::mode::{Catch, Mania, Mode, Osu, Taiko};
#[macro_export]
#[rustfmt::skip]
macro_rules! test_map {
($mode:ident) => {{
#[cfg(not(any(feature = "async_tokio", feature = "async_std")))]
{ common::test_map::<$mode>() }
#[cfg(any(feature = "async_tokio", feature = "async_std"))]
{ common::test_map::<$mode>().await }
}};
}
#[cfg(not(any(feature = "async_tokio", feature = "async_std")))]
pub fn test_map<M: Mode>() -> Beatmap {
let path = format!("./maps/{}.osu", M::TEST_MAP_ID);
Beatmap::from_path(path).unwrap()
}
#[cfg(any(feature = "async_tokio", feature = "async_std"))]
pub async fn test_map<M: Mode>() -> Beatmap {
let path = format!("./maps/{}.osu", M::TEST_MAP_ID);
Beatmap::from_path(path).await.unwrap()
}
+68
View File
@@ -0,0 +1,68 @@
use rosu_pp::{
catch::CatchDifficultyAttributes, mania::ManiaDifficultyAttributes,
osu::OsuDifficultyAttributes, taiko::TaikoDifficultyAttributes,
};
pub struct Osu;
pub struct Taiko;
pub struct Catch;
pub struct Mania;
pub trait Mode {
type DifficultyAttributes;
const TEST_MAP_ID: u32;
const TEST_DIFF_ATTRS: Self::DifficultyAttributes;
}
macro_rules! impl_mode {
( $( $mode:ident: $map_id:literal, $diff_attrs:ident $fields:tt; )* ) => {
$(
impl Mode for $mode {
type DifficultyAttributes = $diff_attrs;
const TEST_MAP_ID: u32 = $map_id;
const TEST_DIFF_ATTRS: Self::DifficultyAttributes = $diff_attrs $fields;
}
)*
};
}
impl_mode! {
Osu: 2785319, OsuDifficultyAttributes {
aim: 2.8693628443424104,
speed: 2.533869745015772,
flashlight: 2.288770487900865,
slider_factor: 0.9803052946037858,
speed_note_count: 210.36373973116545,
ar: 9.300000190734863,
od: 8.800000190734863,
hp: 5.0,
n_circles: 307,
n_sliders: 293,
n_spinners: 1,
stars: 5.669858729379628,
max_combo: 909,
};
Taiko: 1028484, TaikoDifficultyAttributes {
stamina: 1.4528845068865617,
rhythm: 0.20130047251681948,
colour: 1.0487315549761433,
peak: 1.8881824429738323,
hit_window: 35.0,
stars: 2.9778030386845606,
max_combo: 289,
};
Catch: 2118524, CatchDifficultyAttributes {
stars: 3.2502669316166624,
ar: 8.0,
n_fruits: 728,
n_droplets: 2,
n_tiny_droplets: 291,
};
Mania: 1974394, ManiaDifficultyAttributes {
stars: 4.824631127426499,
hit_window: 40.0,
max_combo: 5064,
};
}
+119
View File
@@ -0,0 +1,119 @@
#![cfg(not(any(feature = "async_tokio", feature = "async_std")))]
use rosu_pp::{
catch::{CatchGradualDifficultyAttributes, CatchGradualPerformanceAttributes, CatchScoreState},
Beatmap, CatchPP, CatchStars,
};
use crate::common::Catch;
mod common;
#[test]
fn empty_map() {
let map = Beatmap::default();
let mut attributes = CatchGradualDifficultyAttributes::new(&map, 0);
assert!(attributes.next().is_none());
}
#[test]
fn iter_end_eq_regular() {
let map = test_map!(Catch);
let regular = CatchStars::new(&map).calculate();
let iter_end = CatchGradualDifficultyAttributes::new(&map, 0)
.last()
.expect("empty iter");
assert_eq!(regular, iter_end);
}
#[test]
fn correct_empty() {
let map = test_map!(Catch);
let mut gradual = CatchGradualPerformanceAttributes::new(&map, 0);
let state = CatchScoreState::default();
let first_attrs = gradual.process_next_n_objects(state.clone(), usize::MAX);
assert!(first_attrs.is_some());
assert!(gradual.process_next_object(state).is_none());
}
#[test]
fn next_and_next_n() {
let map = test_map!(Catch);
let state = CatchScoreState::default();
let mut gradual1 = CatchGradualPerformanceAttributes::new(&map, 0);
let mut gradual2 = CatchGradualPerformanceAttributes::new(&map, 0);
for _ in 0..20 {
let _ = gradual1.process_next_object(state.clone());
let _ = gradual2.process_next_object(state.clone());
}
let n = 80;
for _ in 1..n {
let _ = gradual1.process_next_object(state.clone());
}
let state = CatchScoreState {
max_combo: 101,
n_fruits: 99,
n_droplets: 2,
n_tiny_droplets: 68,
n_tiny_droplet_misses: 0,
n_misses: 0,
};
let next = gradual1.process_next_object(state.clone());
let next_n = gradual2.process_next_n_objects(state, n);
assert_eq!(next_n, next);
}
#[test]
fn gradual_end_eq_regular() {
let map = test_map!(Catch);
let regular = CatchPP::new(&map).calculate();
let mut gradual = CatchGradualPerformanceAttributes::new(&map, 0);
let state = CatchScoreState {
max_combo: 730,
n_fruits: 728,
n_droplets: 2,
n_tiny_droplets: 291,
n_tiny_droplet_misses: 0,
n_misses: 0,
};
let gradual_end = gradual.process_next_n_objects(state, usize::MAX).unwrap();
assert_eq!(regular, gradual_end);
}
#[test]
fn gradual_eq_regular_passed() {
let map = test_map!(Catch);
let n = 100;
let regular = CatchPP::new(&map).passed_objects(n).calculate();
let mut gradual = CatchGradualPerformanceAttributes::new(&map, 0);
let state = CatchScoreState {
max_combo: 101,
n_fruits: 99,
n_droplets: 2,
n_tiny_droplets: 68,
n_tiny_droplet_misses: 0,
n_misses: 0,
};
let gradual = gradual.process_next_n_objects(state, n).unwrap();
assert_eq!(regular, gradual);
}
+131
View File
@@ -0,0 +1,131 @@
#![cfg(not(any(feature = "async_tokio", feature = "async_std")))]
use rosu_pp::{
mania::{ManiaGradualDifficultyAttributes, ManiaGradualPerformanceAttributes, ManiaScoreState},
Beatmap, ManiaPP, ManiaStars,
};
use crate::common::Mania;
mod common;
#[test]
fn empty_map() {
let map = Beatmap::default();
let mut attributes = ManiaGradualDifficultyAttributes::new(&map, 0);
assert!(attributes.next().is_none());
}
#[test]
fn iter_end_eq_regular() {
let map = test_map!(Mania);
let regular = ManiaStars::new(&map).calculate();
let iter_end = ManiaGradualDifficultyAttributes::new(&map, 0)
.last()
.expect("empty iter");
assert_eq!(regular, iter_end);
}
#[test]
fn correct_empty() {
let map = test_map!(Mania);
let mut gradual = ManiaGradualPerformanceAttributes::new(&map, 0);
let state = ManiaScoreState {
n320: 0,
n300: 0,
n200: 0,
n100: 0,
n50: 0,
n_misses: 0,
};
let first_attrs = gradual.process_next_n_objects(state.clone(), usize::MAX);
assert!(first_attrs.is_some());
assert!(gradual.process_next_object(state).is_none());
}
#[test]
fn next_and_next_n() {
let map = test_map!(Mania);
let mut state = ManiaScoreState {
n320: 0,
n300: 0,
n200: 0,
n100: 0,
n50: 0,
n_misses: 0,
};
let mut gradual1 = ManiaGradualPerformanceAttributes::new(&map, 0);
let mut gradual2 = ManiaGradualPerformanceAttributes::new(&map, 0);
for _ in 0..20 {
let _ = gradual1.process_next_object(state.clone());
let _ = gradual2.process_next_object(state.clone());
state.n320 += 1;
}
let n = 80;
for _ in 1..n {
let _ = gradual1.process_next_object(state.clone());
state.n320 += 1;
}
let next = gradual1.process_next_object(state.clone());
let next_n = gradual2.process_next_n_objects(state, n);
assert_eq!(next_n, next);
}
#[test]
fn gradual_end_eq_regular() {
let map = test_map!(Mania);
let regular = ManiaPP::new(&map).calculate();
let mut gradual = ManiaGradualPerformanceAttributes::new(&map, 0);
let state = ManiaScoreState {
n320: 3238,
n300: 0,
n200: 0,
n100: 0,
n50: 0,
n_misses: 0,
};
let gradual_end = gradual.process_next_n_objects(state, usize::MAX).unwrap();
assert_eq!(regular, gradual_end);
}
#[test]
fn gradual_eq_regular_passed() {
let map = test_map!(Mania);
let n = 100;
let state = ManiaScoreState {
n320: 100,
n300: 0,
n200: 0,
n100: 0,
n50: 0,
n_misses: 0,
};
let regular = ManiaPP::new(&map)
.passed_objects(n)
.state(state.clone())
.calculate();
let mut gradual = ManiaGradualPerformanceAttributes::new(&map, 0);
let gradual = gradual.process_next_n_objects(state, n).unwrap();
assert_eq!(regular, gradual);
}
+115
View File
@@ -0,0 +1,115 @@
#![cfg(not(any(feature = "async_tokio", feature = "async_std")))]
use rosu_pp::{
osu::{OsuGradualDifficultyAttributes, OsuGradualPerformanceAttributes, OsuScoreState},
Beatmap, OsuPP, OsuStars,
};
use crate::common::Osu;
mod common;
#[test]
fn empty_map() {
let map = Beatmap::default();
let mut attributes = OsuGradualDifficultyAttributes::new(&map, 0);
assert!(attributes.next().is_none());
}
#[test]
fn iter_end_eq_regular() {
let map = test_map!(Osu);
let regular = OsuStars::new(&map).calculate();
let iter_end = OsuGradualDifficultyAttributes::new(&map, 0)
.last()
.expect("empty iter");
assert_eq!(regular, iter_end);
}
#[test]
fn correct_empty() {
let map = test_map!(Osu);
let mut gradual = OsuGradualPerformanceAttributes::new(&map, 0);
let state = OsuScoreState::default();
let first_attrs = gradual.process_next_n_objects(state.clone(), usize::MAX);
assert!(first_attrs.is_some());
assert!(gradual.process_next_object(state).is_none());
}
#[test]
fn next_and_next_n() {
let map = test_map!(Osu);
let state = OsuScoreState::default();
let mut gradual1 = OsuGradualPerformanceAttributes::new(&map, 0);
let mut gradual2 = OsuGradualPerformanceAttributes::new(&map, 0);
for _ in 0..20 {
let _ = gradual1.process_next_object(state.clone());
let _ = gradual2.process_next_object(state.clone());
}
let n = 80;
for _ in 1..n {
let _ = gradual1.process_next_object(state.clone());
}
let state = OsuScoreState {
max_combo: 122,
n300: 88,
n100: 8,
n50: 2,
n_misses: 2,
};
let next = gradual1.process_next_object(state.clone());
let next_n = gradual2.process_next_n_objects(state, n);
assert_eq!(next_n, next);
}
#[test]
fn gradual_end_eq_regular() {
let map = test_map!(Osu);
let regular = OsuPP::new(&map).calculate();
let mut gradual = OsuGradualPerformanceAttributes::new(&map, 0);
let state = OsuScoreState {
max_combo: 909,
n300: 601,
n100: 0,
n50: 0,
n_misses: 0,
};
let gradual_end = gradual.process_next_n_objects(state, usize::MAX).unwrap();
assert_eq!(regular, gradual_end);
}
#[test]
fn gradual_eq_regular_passed() {
let map = test_map!(Osu);
let n = 100;
let regular = OsuPP::new(&map).passed_objects(n).calculate();
let mut gradual = OsuGradualPerformanceAttributes::new(&map, 0);
let state = OsuScoreState {
max_combo: 122,
n300: 100,
n100: 0,
n50: 0,
n_misses: 0,
};
let gradual = gradual.process_next_n_objects(state, n).unwrap();
assert_eq!(regular, gradual);
}
+112
View File
@@ -0,0 +1,112 @@
#![cfg(not(any(feature = "async_tokio", feature = "async_std")))]
use rosu_pp::{
taiko::{TaikoGradualDifficultyAttributes, TaikoGradualPerformanceAttributes, TaikoScoreState},
Beatmap, TaikoPP, TaikoStars,
};
use crate::common::Taiko;
mod common;
#[test]
fn empty_map() {
let map = Beatmap::default();
let mut attrs = TaikoGradualDifficultyAttributes::new(&map, 0);
assert!(attrs.next().is_none());
}
#[test]
fn iter_end_eq_regular() {
let map = test_map!(Taiko);
let regular = TaikoStars::new(&map).calculate();
let iter_end = TaikoGradualDifficultyAttributes::new(&map, 0)
.last()
.expect("empty iter");
assert_eq!(regular, iter_end);
}
#[test]
fn correct_empty() {
let map = test_map!(Taiko);
let mut gradual = TaikoGradualPerformanceAttributes::new(&map, 0);
let state = TaikoScoreState::default();
let first_attrs = gradual.process_next_n_objects(state.clone(), usize::MAX);
assert!(first_attrs.is_some());
assert!(gradual.process_next_object(state).is_none());
}
#[test]
fn next_and_next_n() {
let map = test_map!(Taiko);
let state = TaikoScoreState::default();
let mut gradual1 = TaikoGradualPerformanceAttributes::new(&map, 0);
let mut gradual2 = TaikoGradualPerformanceAttributes::new(&map, 0);
for _ in 0..50 {
let _ = gradual1.process_next_object(state.clone());
let _ = gradual2.process_next_object(state.clone());
}
let n = 200;
for _ in 1..n {
let _ = gradual1.process_next_object(state.clone());
}
let state = TaikoScoreState {
max_combo: 246,
n300: 200,
n100: 40,
n_misses: 6,
};
let next = gradual1.process_next_object(state.clone());
let next_n = gradual2.process_next_n_objects(state, n);
assert_eq!(next_n, next);
}
#[test]
fn gradual_end_eq_regular() {
let map = test_map!(Taiko);
let regular = TaikoPP::new(&map).calculate();
let mut gradual = TaikoGradualPerformanceAttributes::new(&map, 0);
let state = TaikoScoreState {
max_combo: 289,
n300: 289,
n100: 0,
n_misses: 0,
};
let gradual_end = gradual.process_next_n_objects(state, usize::MAX).unwrap();
assert_eq!(regular, gradual_end);
}
#[test]
fn gradual_eq_regular_passed() {
let map = test_map!(Taiko);
let n = 250;
let regular = TaikoPP::new(&map).passed_objects(n).calculate();
let mut gradual = TaikoGradualPerformanceAttributes::new(&map, 0);
let state = TaikoScoreState {
max_combo: 250,
n300: 250,
n100: 0,
n_misses: 0,
};
let gradual = gradual.process_next_n_objects(state, n).unwrap();
assert_eq!(regular, gradual);
}
+178
View File
@@ -0,0 +1,178 @@
use rosu_pp::{Beatmap, GameMode};
use crate::common::{Catch, Mania, Osu, Taiko};
mod common;
#[cfg(not(any(feature = "async_tokio", feature = "async_std")))]
mod sync {
use super::*;
#[test]
fn parse_osu() {
assert_osu(test_map!(Osu));
}
#[test]
fn parse_taiko() {
assert_taiko(test_map!(Taiko));
}
#[test]
fn parse_catch() {
assert_catch(test_map!(Catch));
}
#[test]
fn parse_mania() {
assert_mania(test_map!(Mania));
}
}
#[cfg(feature = "async_tokio")]
mod async_tokio {
use tokio::runtime::Builder as RuntimeBuilder;
use super::*;
#[test]
fn parse_osu() {
RuntimeBuilder::new_current_thread()
.build()
.unwrap()
.block_on(async { assert_osu(test_map!(Osu)) });
}
#[test]
fn parse_taiko() {
RuntimeBuilder::new_current_thread()
.build()
.unwrap()
.block_on(async { assert_taiko(test_map!(Taiko)) });
}
#[test]
fn parse_catch() {
RuntimeBuilder::new_current_thread()
.build()
.unwrap()
.block_on(async { assert_catch(test_map!(Catch)) });
}
#[test]
fn parse_mania() {
RuntimeBuilder::new_current_thread()
.build()
.unwrap()
.block_on(async { assert_mania(test_map!(Mania)) });
}
}
#[cfg(feature = "async_std")]
mod async_tokio {
use super::*;
#[test]
fn parse_osu() {
async_std::task::block_on(async { assert_osu(test_map!(Osu)) });
}
#[test]
fn parse_taiko() {
async_std::task::block_on(async { assert_taiko(test_map!(Taiko)) });
}
#[test]
fn parse_catch() {
async_std::task::block_on(async { assert_catch(test_map!(Catch)) });
}
#[test]
fn parse_mania() {
async_std::task::block_on(async { assert_mania(test_map!(Mania)) });
}
}
fn assert_osu(map: Beatmap) {
assert_eq!(map.mode, GameMode::Osu);
assert_eq!(map.version, 14);
assert_eq!(map.n_circles, 307);
assert_eq!(map.n_sliders, 293);
assert_eq!(map.n_spinners, 1);
assert!((map.ar - 9.3).abs() <= f32::EPSILON);
assert!((map.od - 8.8).abs() <= f32::EPSILON);
assert!((map.cs - 4.5).abs() <= f32::EPSILON);
assert!((map.hp - 5.0).abs() <= f32::EPSILON);
assert!((map.slider_mult - 1.7).abs() <= f64::EPSILON);
assert!((map.tick_rate - 1.0).abs() <= f64::EPSILON);
assert_eq!(map.hit_objects.len(), 601);
assert_eq!(map.sounds.len(), 601);
assert_eq!(map.timing_points.len(), 1);
assert_eq!(map.difficulty_points.len(), 50);
assert_eq!(map.effect_points.len(), 131);
assert!((map.stack_leniency - 0.5).abs() <= f32::EPSILON);
assert_eq!(map.breaks.len(), 1)
}
fn assert_taiko(map: Beatmap) {
assert_eq!(map.mode, GameMode::Taiko);
assert_eq!(map.version, 14);
assert_eq!(map.n_circles, 289);
assert_eq!(map.n_sliders, 4);
assert_eq!(map.n_spinners, 2);
assert!((map.ar - 8.0).abs() <= f32::EPSILON);
assert!((map.od - 5.0).abs() <= f32::EPSILON);
assert!((map.cs - 2.0).abs() <= f32::EPSILON);
assert!((map.hp - 6.0).abs() <= f32::EPSILON);
assert!((map.slider_mult - 1.4).abs() <= f64::EPSILON);
assert!((map.tick_rate - 1.0).abs() <= f64::EPSILON);
assert_eq!(map.hit_objects.len(), 295);
assert_eq!(map.sounds.len(), 295);
assert_eq!(map.timing_points.len(), 1);
assert_eq!(map.difficulty_points.len(), 3);
assert_eq!(map.effect_points.len(), 8);
assert!((map.stack_leniency - 0.7).abs() <= f32::EPSILON);
assert_eq!(map.breaks.len(), 0)
}
fn assert_catch(map: Beatmap) {
assert_eq!(map.mode, GameMode::Catch);
assert_eq!(map.version, 14);
assert_eq!(map.n_circles, 249);
assert_eq!(map.n_sliders, 227);
assert_eq!(map.n_spinners, 1);
assert!((map.ar - 8.0).abs() <= f32::EPSILON);
assert!((map.od - 8.0).abs() <= f32::EPSILON);
assert!((map.cs - 3.5).abs() <= f32::EPSILON);
assert!((map.hp - 5.0).abs() <= f32::EPSILON);
assert!((map.slider_mult - 1.45).abs() <= f64::EPSILON);
assert!((map.tick_rate - 1.0).abs() <= f64::EPSILON);
assert_eq!(map.hit_objects.len(), 477);
assert_eq!(map.sounds.len(), 477);
assert_eq!(map.timing_points.len(), 1);
assert_eq!(map.difficulty_points.len(), 0);
assert_eq!(map.effect_points.len(), 57);
assert!((map.stack_leniency - 0.7).abs() <= f32::EPSILON);
assert_eq!(map.breaks.len(), 0)
}
fn assert_mania(map: Beatmap) {
assert_eq!(map.mode, GameMode::Mania);
assert_eq!(map.version, 14);
assert_eq!(map.n_circles, 2815);
assert_eq!(map.n_sliders, 423);
assert_eq!(map.n_spinners, 0);
assert!((map.ar - 5.0).abs() <= f32::EPSILON);
assert!((map.od - 8.0).abs() <= f32::EPSILON);
assert!((map.cs - 4.0).abs() <= f32::EPSILON);
assert!((map.hp - 9.0).abs() <= f32::EPSILON);
assert!((map.slider_mult - 1.4).abs() <= f64::EPSILON);
assert!((map.tick_rate - 1.0).abs() <= f64::EPSILON);
assert_eq!(map.hit_objects.len(), 3238);
assert_eq!(map.sounds.len(), 3238);
assert_eq!(map.timing_points.len(), 1);
assert_eq!(map.difficulty_points.len(), 1740);
assert_eq!(map.effect_points.len(), 1762);
assert!((map.stack_leniency - 0.7).abs() <= f32::EPSILON);
assert_eq!(map.breaks.len(), 0)
}