Merge branch 'rewrite' of https://github.com/MaxOhn/rosu-pp into rewrite
This commit is contained in:
@@ -2,210 +2,96 @@
|
|||||||
|
|
||||||
# rosu-pp
|
# rosu-pp
|
||||||
|
|
||||||
TODO: Rewrite readme
|
<!-- cargo-rdme start -->
|
||||||
|
|
||||||
A standalone crate to calculate star ratings and performance points for all [osu!](https://osu.ppy.sh/home) gamemodes.
|
Library to calculate difficulty and performance attributes for all [osu!] gamemodes.
|
||||||
|
|
||||||
Async is supported through features, see below.
|
### Description
|
||||||
|
|
||||||
|
A large part of `rosu-pp` is a port of [osu!lazer]'s difficulty and performance calculation
|
||||||
|
with emphasis on a precise translation to Rust for the most accurate results.
|
||||||
|
|
||||||
|
Another important factor is the calculation speed. Optimizations and an accurate translation
|
||||||
|
unfortunately don't always go hand-in-hand. Nonetheless, performance improvements are still
|
||||||
|
snuck in wherever possible, providing a significantly faster runtime than the native C# code.
|
||||||
|
|
||||||
|
TODO: values to compare
|
||||||
|
|
||||||
|
Additionally, `rosu-pp` allows previous values to be re-used so that they don't need to be
|
||||||
|
calculated again. For example, a beatmap needs to be decoded only once and can then be used
|
||||||
|
for any amount of attribute calculations. Similarly, previous attributes can be re-used for
|
||||||
|
later calculations (with some limitations, see the [example](#usage)).
|
||||||
|
|
||||||
|
Last commits of the ported code:
|
||||||
|
- [osu!lazer] : `7342fb7f51b34533a42bffda89c3d6c569cc69ce` (2022-10-11)
|
||||||
|
- [osu!tools] : `146d5916937161ef65906aa97f85d367035f3712` (2022-10-08)
|
||||||
|
|
||||||
|
News posts of the latest gamemode updates:
|
||||||
|
- osu: <https://osu.ppy.sh/home/news/2022-09-30-changes-to-osu-sr-and-pp>
|
||||||
|
- taiko: <https://osu.ppy.sh/home/news/2022-09-28-changes-to-osu-taiko-sr-and-pp>
|
||||||
|
- catch: <https://osu.ppy.sh/home/news/2020-05-14-osucatch-scoring-updates>
|
||||||
|
- mania: <https://osu.ppy.sh/home/news/2022-10-09-changes-to-osu-mania-sr-and-pp>
|
||||||
|
|
||||||
### Usage
|
### Usage
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
use rosu_pp::{Beatmap, BeatmapExt};
|
// Decode the map
|
||||||
|
let map = rosu_pp::Beatmap::from_path("./resources/2785319.osu").unwrap();
|
||||||
|
|
||||||
// Parse the map yourself
|
// Calculate difficulty attributes
|
||||||
let map = match Beatmap::from_path("/path/to/file.osu") {
|
let diff_attrs = map.difficulty()
|
||||||
Ok(map) => map,
|
.mods(8 + 16) // HDHR
|
||||||
Err(why) => panic!("Error while parsing map: {}", why),
|
.calculate();
|
||||||
};
|
|
||||||
|
|
||||||
// If `BeatmapExt` is included, you can make use of
|
let stars = diff_attrs.stars();
|
||||||
// some methods on `Beatmap` to make your life simpler.
|
|
||||||
let result = map.pp()
|
// Calculate performance attributes
|
||||||
.mods(24) // HDHR
|
let perf_attrs = map.performance()
|
||||||
.combo(1234)
|
// To speed up the calculation, we can use the previous attributes.
|
||||||
|
// **Note** that this should only be done if the map, mode, mods,
|
||||||
|
// clock rate, and amount of passed objects stay the same.
|
||||||
|
// Otherwise, the final attributes will be incorrect.
|
||||||
|
.attributes(diff_attrs)
|
||||||
|
.mods(24) // HDHR, must be the same as before
|
||||||
|
.combo(789)
|
||||||
.accuracy(99.2)
|
.accuracy(99.2)
|
||||||
.misses(2)
|
.misses(2)
|
||||||
.calculate();
|
.calculate();
|
||||||
|
|
||||||
println!("PP: {}", result.pp());
|
let pp = perf_attrs.pp();
|
||||||
|
|
||||||
// If you want to reuse the current map-mod combination, make use of the previous result!
|
// Again, we re-use the previous attributes for maximum efficiency.
|
||||||
// If attributes are given, then stars & co don't have to be recalculated.
|
// This time we do it directly instead of through the map.
|
||||||
let next_result = map.pp()
|
let max_pp = perf_attrs.performance()
|
||||||
.mods(24) // HDHR
|
.mods(24) // Still the same
|
||||||
.attributes(result) // recycle
|
|
||||||
.combo(543)
|
|
||||||
.misses(5)
|
|
||||||
.n50(3)
|
|
||||||
.accuracy(96.5)
|
|
||||||
.calculate();
|
|
||||||
|
|
||||||
println!("Next PP: {}", next_result.pp());
|
|
||||||
|
|
||||||
let stars = map.stars()
|
|
||||||
.mods(16) // HR
|
|
||||||
.calculate()
|
.calculate()
|
||||||
.stars();
|
.pp();
|
||||||
|
|
||||||
let max_pp = map.max_pp(16).pp();
|
println!("Stars: {stars} | PP: {pp}/{max_pp}");
|
||||||
|
|
||||||
println!("Stars: {} | Max PP: {}", stars, max_pp);
|
|
||||||
```
|
|
||||||
|
|
||||||
### With async
|
|
||||||
If either the `async_tokio` or `async_std` feature is enabled, beatmap parsing will be async.
|
|
||||||
|
|
||||||
```rust
|
|
||||||
use rosu_pp::{Beatmap, BeatmapExt};
|
|
||||||
|
|
||||||
// Parse the map asynchronously
|
|
||||||
let map = match Beatmap::from_path("/path/to/file.osu").await {
|
|
||||||
Ok(map) => map,
|
|
||||||
Err(why) => panic!("Error while parsing map: {}", why),
|
|
||||||
};
|
|
||||||
|
|
||||||
// The rest stays the same
|
|
||||||
let result = map.pp()
|
|
||||||
.mods(24) // HDHR
|
|
||||||
.combo(1234)
|
|
||||||
.n_misses(2)
|
|
||||||
.accuracy(99.2)
|
|
||||||
.calculate();
|
|
||||||
|
|
||||||
println!("PP: {}", result.pp());
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### Gradual calculation
|
### Gradual calculation
|
||||||
Sometimes you might want to calculate the difficulty of a map or performance of a score after each hit object.
|
|
||||||
This could be done by using `passed_objects` as the amount of objects that were passed so far.
|
|
||||||
However, this requires to recalculate the beginning again and again, we can be more efficient than that.
|
|
||||||
|
|
||||||
Instead, you should enable the `gradual` feature and use `GradualDifficulty` and `GradualPerformance`:
|
TODO
|
||||||
|
|
||||||
```rust
|
|
||||||
use rosu_pp::{
|
|
||||||
Beatmap, BeatmapExt, GradualDifficulty, GradualPerformance, ScoreState,
|
|
||||||
taiko::TaikoScoreState,
|
|
||||||
};
|
|
||||||
|
|
||||||
let map = match Beatmap::from_path("/path/to/file.osu") {
|
|
||||||
Ok(map) => map,
|
|
||||||
Err(why) => panic!("Error while parsing map: {}", why),
|
|
||||||
};
|
|
||||||
|
|
||||||
let mods = 8 + 64; // HDDT
|
|
||||||
|
|
||||||
// If you're only interested in the star rating or other difficulty values,
|
|
||||||
// use `GradualDifficulty`.
|
|
||||||
let gradual_difficulty = GradualDifficulty::new(&map, mods);
|
|
||||||
|
|
||||||
// Since `GradualDifficulty` implements `Iterator`, you can use
|
|
||||||
// any iterate function on it, use it in loops, collect them into a `Vec`, ...
|
|
||||||
for (i, difficulty) in gradual_difficulty.enumerate() {
|
|
||||||
println!("Stars after object {}: {}", i, difficulty.stars());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Gradually calculating performance values does the same as calculating
|
|
||||||
// difficulty attributes but it goes the extra step and also evaluates
|
|
||||||
// the state of a score for these difficulty attributes.
|
|
||||||
let mut gradual_performance = GradualPerformance::new(&map, mods);
|
|
||||||
|
|
||||||
// The default score state is kinda chunky because it considers all modes.
|
|
||||||
let state = ScoreState {
|
|
||||||
max_combo: 1,
|
|
||||||
n_geki: 0, // only relevant for mania
|
|
||||||
n_katu: 0, // only relevant for mania and ctb
|
|
||||||
n300: 1,
|
|
||||||
n100: 0,
|
|
||||||
n50: 0,
|
|
||||||
n_misses: 0,
|
|
||||||
};
|
|
||||||
|
|
||||||
// Process the score state after the first object
|
|
||||||
let curr_performance = match gradual_performance.next(state) {
|
|
||||||
Some(perf) => perf,
|
|
||||||
None => panic!("the map has no hit objects"),
|
|
||||||
};
|
|
||||||
|
|
||||||
println!("PP after the first object: {}", curr_performance.pp());
|
|
||||||
|
|
||||||
// If you're only interested in maps of a specific mode, consider
|
|
||||||
// using the mode's gradual calculator instead of the general one.
|
|
||||||
// Let's assume it's a taiko map.
|
|
||||||
// Instead of starting off with `GradualPerformance` one could have
|
|
||||||
// used `TaikoGradualPerformance`.
|
|
||||||
let mut gradual_performance = match gradual_performance {
|
|
||||||
GradualPerformanceAttributes::Taiko(gradual) => gradual,
|
|
||||||
_ => panic!("the map was not taiko but {:?}", map.mode),
|
|
||||||
};
|
|
||||||
|
|
||||||
// A little simpler than the general score state.
|
|
||||||
let state = TaikoScoreState {
|
|
||||||
max_combo: 11,
|
|
||||||
n300: 9,
|
|
||||||
n100: 1,
|
|
||||||
n_misses: 1,
|
|
||||||
};
|
|
||||||
|
|
||||||
// Process the next 10 objects in one go (`nth` takes a zero-based value).
|
|
||||||
let curr_performance = match gradual_performance.nth(state, 9) {
|
|
||||||
Some(perf) => perf,
|
|
||||||
None => panic!("the previous `next` already processed the last object"),
|
|
||||||
};
|
|
||||||
|
|
||||||
println!("PP after the first 11 objects: {}", curr_performance.pp());
|
|
||||||
```
|
|
||||||
|
|
||||||
### Features
|
### Features
|
||||||
|
|
||||||
| Flag | Description |
|
| Flag | Description | Dependencies
|
||||||
| ------------- |------------------------------------------------------------------------------------------|
|
| --------- | ----------- | ------------
|
||||||
| `default` | Beatmap parsing will be non-async |
|
| `default` | No features |
|
||||||
| `async_tokio` | Beatmap parsing will be async through [tokio](https://github.com/tokio-rs/tokio) |
|
| `tracing` | Any error encountered during beatmap decoding will be logged through `tracing::error`. If this feature is not enabled, errors will be ignored. | [`tracing`]
|
||||||
| `async_std` | Beatmap parsing will be async through [async-std](https://github.com/async-rs/async-std) |
|
|
||||||
| `gradual` | Enable gradual difficulty and performance calculation |
|
|
||||||
|
|
||||||
### Version
|
|
||||||
|
|
||||||
A large portion of this repository is a port of [osu!lazer](https://github.com/ppy/osu)'s difficulty and performance calculation.
|
|
||||||
|
|
||||||
- osu!:
|
|
||||||
- osu!lazer: Commit `85adfc2df7d931164181e145377a6ced8db2bfb3` (Wed Sep 28 18:26:36 2022 +0300)
|
|
||||||
- osu!tools: Commit `146d5916937161ef65906aa97f85d367035f3712` (Sat Oct 8 14:28:49 2022 +0900)
|
|
||||||
- [Article](https://osu.ppy.sh/home/news/2022-09-30-changes-to-osu-sr-and-pp)
|
|
||||||
|
|
||||||
- taiko:
|
|
||||||
- osu!lazer: Commit `234c6ac7998fbc6742503e1a589536255554e56a` (Wed Oct 5 20:21:15 2022 +0900)
|
|
||||||
- osu!tools: Commit `146d5916937161ef65906aa97f85d367035f3712` (Sat Oct 8 14:28:49 2022 +0900)
|
|
||||||
- [Article](https://osu.ppy.sh/home/news/2022-09-28-changes-to-osu-taiko-sr-and-pp)
|
|
||||||
|
|
||||||
- catch: (will be updated on the next rework)
|
|
||||||
- osu!lazer: -
|
|
||||||
- osu!tools: -
|
|
||||||
|
|
||||||
- mania:
|
|
||||||
- osu!lazer: Commit `7342fb7f51b34533a42bffda89c3d6c569cc69ce` (Tue Oct 11 14:34:50 2022 +0900)
|
|
||||||
- osu!tools: Commit `146d5916937161ef65906aa97f85d367035f3712` (Sat Oct 8 14:28:49 2022 +0900)
|
|
||||||
- [Article](https://osu.ppy.sh/home/news/2022-10-09-changes-to-osu-mania-sr-and-pp)
|
|
||||||
|
|
||||||
### Accuracy
|
|
||||||
|
|
||||||
The difficulty and performance attributes generated by [osu-tools](https://github.com/ppy/osu-tools) itself were compared with rosu-pp's results when running on `130,000` different maps. Additionally, multiple mod combinations were tested depending on the mode:
|
|
||||||
|
|
||||||
- osu!: NM, EZ, HD, HR, DT
|
|
||||||
- taiko: NM, HD, HR, DT (+ all osu! converts)
|
|
||||||
- catch: -
|
|
||||||
- mania: NM, DT (+ all osu! converts)
|
|
||||||
|
|
||||||
For every (!) comparison of the star and pp values, the error margin was below `0.000000001`, ensuing a great accuracy.
|
|
||||||
|
|
||||||
### Benchmark
|
|
||||||
|
|
||||||
To be done
|
|
||||||
|
|
||||||
### Bindings
|
### Bindings
|
||||||
|
|
||||||
Using rosu-pp from other languages than Rust:
|
Using `rosu-pp` from other languages than Rust:
|
||||||
- JavaScript: [rosu-pp-js](https://github.com/MaxOhn/rosu-pp-js)
|
- JavaScript: [rosu-pp-js]
|
||||||
- Python: [rosu-pp-py](https://github.com/MaxOhn/rosu-pp-py)
|
- Python: [rosu-pp-py]
|
||||||
|
|
||||||
|
[osu!]: https://osu.ppy.sh/home
|
||||||
|
[osu!lazer]: https://github.com/ppy/osu
|
||||||
|
[osu!tools]: https://github.com/ppy/osu-tools
|
||||||
|
[`tracing`]: https://docs.rs/tracing
|
||||||
|
[rosu-pp-js]: https://github.com/MaxOhn/rosu-pp-js
|
||||||
|
[rosu-pp-py]: https://github.com/MaxOhn/rosu-pp-py
|
||||||
|
|
||||||
|
<!-- cargo-rdme end -->
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ impl DifficultyAttributes {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a builder for performance calculation.
|
/// Returns a builder for performance calculation.
|
||||||
pub fn pp<'a>(self) -> Performance<'a> {
|
pub fn performance<'a>(self) -> Performance<'a> {
|
||||||
self.into()
|
self.into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -275,10 +275,10 @@ impl<A: AttributeProvider> From<A> for Performance<'_> {
|
|||||||
fn from(attrs: A) -> Self {
|
fn from(attrs: A) -> Self {
|
||||||
fn inner(attrs: DifficultyAttributes) -> Performance<'static> {
|
fn inner(attrs: DifficultyAttributes) -> Performance<'static> {
|
||||||
match attrs {
|
match attrs {
|
||||||
DifficultyAttributes::Osu(attrs) => Performance::Osu(attrs.pp()),
|
DifficultyAttributes::Osu(attrs) => Performance::Osu(attrs.performance()),
|
||||||
DifficultyAttributes::Taiko(attrs) => Performance::Taiko(attrs.pp()),
|
DifficultyAttributes::Taiko(attrs) => Performance::Taiko(attrs.performance()),
|
||||||
DifficultyAttributes::Catch(attrs) => Performance::Catch(attrs.pp()),
|
DifficultyAttributes::Catch(attrs) => Performance::Catch(attrs.performance()),
|
||||||
DifficultyAttributes::Mania(attrs) => Performance::Mania(attrs.pp()),
|
DifficultyAttributes::Mania(attrs) => Performance::Mania(attrs.performance()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ impl CatchDifficultyAttributes {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a builder for performance calculation.
|
/// Returns a builder for performance calculation.
|
||||||
pub fn pp<'a>(self) -> CatchPerformance<'a> {
|
pub fn performance<'a>(self) -> CatchPerformance<'a> {
|
||||||
self.into()
|
self.into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+91
-1
@@ -1,4 +1,94 @@
|
|||||||
#![deny(rustdoc::broken_intra_doc_links)]
|
//! Library to calculate difficulty and performance attributes for all [osu!] gamemodes.
|
||||||
|
//!
|
||||||
|
//! ## Description
|
||||||
|
//!
|
||||||
|
//! A large part of `rosu-pp` is a port of [osu!lazer]'s difficulty and performance calculation
|
||||||
|
//! with emphasis on a precise translation to Rust for the most accurate results.
|
||||||
|
//!
|
||||||
|
//! Another important factor is the calculation speed. Optimizations and an accurate translation
|
||||||
|
//! unfortunately don't always go hand-in-hand. Nonetheless, performance improvements are still
|
||||||
|
//! snuck in wherever possible, providing a significantly faster runtime than the native C# code.
|
||||||
|
//!
|
||||||
|
//! TODO: values to compare
|
||||||
|
//!
|
||||||
|
//! Additionally, `rosu-pp` allows previous values to be re-used so that they don't need to be
|
||||||
|
//! calculated again. For example, a beatmap needs to be decoded only once and can then be used
|
||||||
|
//! for any amount of attribute calculations. Similarly, previous attributes can be re-used for
|
||||||
|
//! later calculations (with some limitations, see the [example](#usage)).
|
||||||
|
//!
|
||||||
|
//! Last commits of the ported code:
|
||||||
|
//! - [osu!lazer] : `7342fb7f51b34533a42bffda89c3d6c569cc69ce` (2022-10-11)
|
||||||
|
//! - [osu!tools] : `146d5916937161ef65906aa97f85d367035f3712` (2022-10-08)
|
||||||
|
//!
|
||||||
|
//! News posts of the latest gamemode updates:
|
||||||
|
//! - osu: <https://osu.ppy.sh/home/news/2022-09-30-changes-to-osu-sr-and-pp>
|
||||||
|
//! - taiko: <https://osu.ppy.sh/home/news/2022-09-28-changes-to-osu-taiko-sr-and-pp>
|
||||||
|
//! - catch: <https://osu.ppy.sh/home/news/2020-05-14-osucatch-scoring-updates>
|
||||||
|
//! - mania: <https://osu.ppy.sh/home/news/2022-10-09-changes-to-osu-mania-sr-and-pp>
|
||||||
|
//!
|
||||||
|
//! ## Usage
|
||||||
|
//!
|
||||||
|
//! ```
|
||||||
|
//! // Decode the map
|
||||||
|
//! let map = rosu_pp::Beatmap::from_path("./resources/2785319.osu").unwrap();
|
||||||
|
//!
|
||||||
|
//! // Calculate difficulty attributes
|
||||||
|
//! let diff_attrs = map.difficulty()
|
||||||
|
//! .mods(8 + 16) // HDHR
|
||||||
|
//! .calculate();
|
||||||
|
//!
|
||||||
|
//! let stars = diff_attrs.stars();
|
||||||
|
//!
|
||||||
|
//! // Calculate performance attributes
|
||||||
|
//! let perf_attrs = map.performance()
|
||||||
|
//! // To speed up the calculation, we can use the previous attributes.
|
||||||
|
//! // **Note** that this should only be done if the map, mode, mods,
|
||||||
|
//! // clock rate, and amount of passed objects stay the same.
|
||||||
|
//! // Otherwise, the final attributes will be incorrect.
|
||||||
|
//! .attributes(diff_attrs)
|
||||||
|
//! .mods(24) // HDHR, must be the same as before
|
||||||
|
//! .combo(789)
|
||||||
|
//! .accuracy(99.2)
|
||||||
|
//! .misses(2)
|
||||||
|
//! .calculate();
|
||||||
|
//!
|
||||||
|
//! let pp = perf_attrs.pp();
|
||||||
|
//!
|
||||||
|
//! // Again, we re-use the previous attributes for maximum efficiency.
|
||||||
|
//! // This time we do it directly instead of through the map.
|
||||||
|
//! let max_pp = perf_attrs.performance()
|
||||||
|
//! .mods(24) // Still the same
|
||||||
|
//! .calculate()
|
||||||
|
//! .pp();
|
||||||
|
//!
|
||||||
|
//! println!("Stars: {stars} | PP: {pp}/{max_pp}");
|
||||||
|
//! ```
|
||||||
|
//!
|
||||||
|
//! ## Gradual calculation
|
||||||
|
//!
|
||||||
|
//! TODO
|
||||||
|
//!
|
||||||
|
//! ## Features
|
||||||
|
//!
|
||||||
|
//! | Flag | Description | Dependencies
|
||||||
|
//! | --------- | ----------- | ------------
|
||||||
|
//! | `default` | No features |
|
||||||
|
//! | `tracing` | Any error encountered during beatmap decoding will be logged through `tracing::error`. If this feature is not enabled, errors will be ignored. | [`tracing`]
|
||||||
|
//!
|
||||||
|
//! ## Bindings
|
||||||
|
//!
|
||||||
|
//! Using `rosu-pp` from other languages than Rust:
|
||||||
|
//! - JavaScript: [rosu-pp-js]
|
||||||
|
//! - Python: [rosu-pp-py]
|
||||||
|
//!
|
||||||
|
//! [osu!]: https://osu.ppy.sh/home
|
||||||
|
//! [osu!lazer]: https://github.com/ppy/osu
|
||||||
|
//! [osu!tools]: https://github.com/ppy/osu-tools
|
||||||
|
//! [`tracing`]: https://docs.rs/tracing
|
||||||
|
//! [rosu-pp-js]: https://github.com/MaxOhn/rosu-pp-js
|
||||||
|
//! [rosu-pp-py]: https://github.com/MaxOhn/rosu-pp-py
|
||||||
|
|
||||||
|
#![deny(rustdoc::broken_intra_doc_links, rustdoc::missing_crate_level_docs)]
|
||||||
#![warn(clippy::missing_const_for_fn, clippy::pedantic)]
|
#![warn(clippy::missing_const_for_fn, clippy::pedantic)]
|
||||||
#![allow(
|
#![allow(
|
||||||
clippy::missing_errors_doc,
|
clippy::missing_errors_doc,
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ impl ManiaDifficultyAttributes {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a builder for performance calculation.
|
/// Returns a builder for performance calculation.
|
||||||
pub fn pp<'a>(self) -> ManiaPerformance<'a> {
|
pub fn performance<'a>(self) -> ManiaPerformance<'a> {
|
||||||
self.into()
|
self.into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,7 @@
|
|||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
|
|
||||||
use rosu_map::{
|
use rosu_map::{
|
||||||
section::{
|
section::{general::GameMode, hit_objects::CurveBuffers},
|
||||||
general::GameMode,
|
|
||||||
hit_objects::{BorrowedCurve, CurveBuffers},
|
|
||||||
},
|
|
||||||
util::Pos,
|
util::Pos,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -107,11 +104,7 @@ fn convert(map: &mut Beatmap) {
|
|||||||
last_values.pattern = new_pattern;
|
last_values.pattern = new_pattern;
|
||||||
}
|
}
|
||||||
HitObjectKind::Slider(ref slider) => {
|
HitObjectKind::Slider(ref slider) => {
|
||||||
let curve = BorrowedCurve::new(
|
let curve = slider.curve(&mut curve_bufs);
|
||||||
&slider.control_points,
|
|
||||||
slider.expected_dist,
|
|
||||||
&mut curve_bufs,
|
|
||||||
);
|
|
||||||
|
|
||||||
let mut gen = DistanceObjectPatternGenerator::new(
|
let mut gen = DistanceObjectPatternGenerator::new(
|
||||||
&mut random,
|
&mut random,
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ use rosu_map::{
|
|||||||
LATEST_FORMAT_VERSION,
|
LATEST_FORMAT_VERSION,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use crate::{Performance, Difficulty};
|
||||||
|
|
||||||
pub use self::{
|
pub use self::{
|
||||||
attributes::{BeatmapAttributes, BeatmapAttributesBuilder, HitWindows},
|
attributes::{BeatmapAttributes, BeatmapAttributesBuilder, HitWindows},
|
||||||
converted::Converted,
|
converted::Converted,
|
||||||
@@ -68,6 +70,16 @@ impl Beatmap {
|
|||||||
rosu_map::from_bytes(bytes)
|
rosu_map::from_bytes(bytes)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Create a new difficulty calculator for this [`Beatmap`].
|
||||||
|
pub fn difficulty(&self) -> Difficulty<'_> {
|
||||||
|
Difficulty::new(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create a new performance calculator for this [`Beatmap`].
|
||||||
|
pub fn performance(&self) -> Performance<'_> {
|
||||||
|
Performance::new(self)
|
||||||
|
}
|
||||||
|
|
||||||
/// Finds the [`TimingPoint`] that is active at the given time.
|
/// Finds the [`TimingPoint`] that is active at the given time.
|
||||||
pub(crate) fn timing_point_at(&self, time: f64) -> Option<&TimingPoint> {
|
pub(crate) fn timing_point_at(&self, time: f64) -> Option<&TimingPoint> {
|
||||||
timing_point_at(&self.timing_points, time)
|
timing_point_at(&self.timing_points, time)
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ use std::cmp::Ordering;
|
|||||||
use rosu_map::section::hit_objects::{BorrowedCurve, CurveBuffers};
|
use rosu_map::section::hit_objects::{BorrowedCurve, CurveBuffers};
|
||||||
|
|
||||||
pub use rosu_map::{
|
pub use rosu_map::{
|
||||||
section::hit_objects::{hit_samples::HitSoundType, PathControlPoint},
|
section::hit_objects::{hit_samples::HitSoundType, PathControlPoint, PathType, SplineType},
|
||||||
util::Pos,
|
util::Pos,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ impl OsuDifficultyAttributes {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a builder for performance calculation.
|
/// Returns a builder for performance calculation.
|
||||||
pub fn pp<'a>(self) -> OsuPerformance<'a> {
|
pub fn performance<'a>(self) -> OsuPerformance<'a> {
|
||||||
self.into()
|
self.into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-4
@@ -1,7 +1,5 @@
|
|||||||
use rosu_map::{
|
use rosu_map::{
|
||||||
section::hit_objects::{
|
section::hit_objects::{CurveBuffers, SliderEvent, SliderEventType, SliderEventsIter},
|
||||||
BorrowedCurve, CurveBuffers, SliderEvent, SliderEventType, SliderEventsIter,
|
|
||||||
},
|
|
||||||
util::Pos,
|
util::Pos,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -183,7 +181,7 @@ impl OsuSlider {
|
|||||||
|point| (point.slider_velocity, point.generate_ticks),
|
|point| (point.slider_velocity, point.generate_ticks),
|
||||||
);
|
);
|
||||||
|
|
||||||
let path = BorrowedCurve::new(&slider.control_points, slider.expected_dist, curve_bufs);
|
let path = slider.curve(curve_bufs);
|
||||||
|
|
||||||
let span_count = slider.span_count() as f64;
|
let span_count = slider.span_count() as f64;
|
||||||
|
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ impl TaikoDifficultyAttributes {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a builder for performance calculation.
|
/// Returns a builder for performance calculation.
|
||||||
pub fn pp<'a>(self) -> TaikoPerformance<'a> {
|
pub fn performance<'a>(self) -> TaikoPerformance<'a> {
|
||||||
self.into()
|
self.into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user