fixed & extended test cases
This commit is contained in:
@@ -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()
|
||||
}
|
||||
@@ -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,
|
||||
};
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
Reference in New Issue
Block a user