fixed & extended test cases

This commit is contained in:
MaxOhn
2022-10-21 11:07:29 +02:00
parent 17ce0ef2c9
commit 335f0a7dde
27 changed files with 1677 additions and 898 deletions
+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_str")))]
{ common::test_map::<$mode>() }
#[cfg(any(feature = "async_tokio", feature = "async_str"))]
{ common::test_map::<$mode>().await }
}};
}
#[cfg(not(any(feature = "async_tokio", feature = "async_str")))]
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_str"))]
pub async fn test_map() -> 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,
};
}
+40
View File
@@ -0,0 +1,40 @@
#![cfg(not(any(feature = "async_tokio", feature = "async_std")))]
use common::{test_map, Osu};
use rosu_pp::{CatchStars, ManiaStars, OsuStars, TaikoStars};
use crate::common::{Catch, Mania, Mode, Taiko};
mod common;
#[test]
fn difficulty_osu() {
let map = test_map::<Osu>();
let attrs = OsuStars::new(&map).calculate();
assert_eq!(Osu::TEST_DIFF_ATTRS, attrs);
}
#[test]
fn difficulty_taiko() {
let map = test_map::<Taiko>();
let attrs = TaikoStars::new(&map).calculate();
assert_eq!(Taiko::TEST_DIFF_ATTRS, attrs);
}
#[test]
fn difficulty_catch() {
let map = test_map::<Catch>();
let attrs = CatchStars::new(&map).calculate();
assert_eq!(Catch::TEST_DIFF_ATTRS, attrs);
}
#[test]
fn difficulty_mania() {
let map = test_map::<Mania>();
let attrs = ManiaStars::new(&map).calculate();
assert_eq!(Mania::TEST_DIFF_ATTRS, attrs);
}
+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);
}
+113
View File
@@ -0,0 +1,113 @@
#![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: 246,
n300: 246,
n100: 0,
n_misses: 0,
};
let gradual = gradual.process_next_n_objects(state, n).unwrap();
// Cyclic types in difficulty calculation prohibit values to coincide completely
assert_eq!(regular.difficulty.max_combo, gradual.difficulty.max_combo);
}