feat: support dx rating of below A rank
This commit is contained in:
@@ -68,89 +68,47 @@ impl Level {
|
||||
/// This will **NOT** ignore utage level, you can calculate a in-theory DX Rating.
|
||||
///
|
||||
/// On invalid input, it returns 0.
|
||||
pub fn dx_rating(&self, achievement: i32) -> u32 {
|
||||
let achievement = Decimal::new(achievement as _, 4);
|
||||
pub fn dx_rating(&self, achievement: i32) -> (&'static str, u32) {
|
||||
let achievement = achievement.min(1005000); // SSS+ case
|
||||
let (rank, _, factor) = RANKS
|
||||
.into_iter()
|
||||
.rev()
|
||||
.find(|&(_, threshold, _)| threshold <= achievement)
|
||||
.unwrap(); // save here, due to zero threshold
|
||||
let difficulty_rank: Decimal = self.difficulty.value;
|
||||
|
||||
let factor = match () {
|
||||
// larger than best achievement
|
||||
_ if achievement > dec!(101.0) => return 0,
|
||||
|
||||
_ if achievement >= SSS_PLUS_THRESHOLD => SSS_PLUS_FACTOR,
|
||||
_ if achievement >= SSS_PRO_THRESHOLD => SSS_PRO_FACTOR,
|
||||
_ if achievement >= SSS_THRESHOLD => SSS_FACTOR,
|
||||
_ if achievement >= SS_PLUS_PRO_THRESHOLD => SS_PLUS_PRO_FACTOR,
|
||||
_ if achievement >= SS_PLUS_THRESHOLD => SS_PLUS_FACTOR,
|
||||
_ if achievement >= SS_THRESHOLD => SS_FACTOR,
|
||||
_ if achievement >= S_PLUS_PRO_THRESHOLD => S_PLUS_PRO_FACTOR,
|
||||
_ if achievement >= S_PLUS_THRESHOLD => S_PLUS_FACTOR,
|
||||
_ if achievement >= S_THRESHOLD => S_FACTOR,
|
||||
_ if achievement >= AAA_PRO_THRESHOLD => AAA_PRO_FACTOR,
|
||||
_ if achievement >= AAA_THRESHOLD => AAA_FACTOR,
|
||||
_ if achievement >= AA_THRESHOLD => AA_FACTOR,
|
||||
_ if achievement >= A_THRESHOLD => A_FACTOR,
|
||||
|
||||
// lower than A rank, does not get rating.
|
||||
_ => return 0,
|
||||
};
|
||||
let achievement = Decimal::new(achievement as _, 4);
|
||||
|
||||
// when ach > 100.5%, calculate as 100.5%
|
||||
(factor * difficulty_rank * achievement.min(Decimal::new(1005, 1)))
|
||||
let rating: u32 = (factor * difficulty_rank * achievement.min(dec!(100.5)))
|
||||
.floor()
|
||||
.try_into()
|
||||
.unwrap_or_default()
|
||||
.unwrap_or_default();
|
||||
(rank, rating)
|
||||
}
|
||||
}
|
||||
|
||||
const SSS_PLUS_THRESHOLD: Decimal = dec!(100.5);
|
||||
const SSS_PLUS_FACTOR: Decimal = dec!(0.224);
|
||||
|
||||
const SSS_PRO_THRESHOLD: Decimal = dec!(100.4999);
|
||||
const SSS_PRO_FACTOR: Decimal = dec!(0.222);
|
||||
|
||||
const SSS_THRESHOLD: Decimal = dec!(100);
|
||||
const SSS_FACTOR: Decimal = dec!(0.216);
|
||||
|
||||
const SS_PLUS_PRO_THRESHOLD: Decimal = dec!(99.9999);
|
||||
const SS_PLUS_PRO_FACTOR: Decimal = dec!(0.214);
|
||||
|
||||
const SS_PLUS_THRESHOLD: Decimal = dec!(99.5);
|
||||
const SS_PLUS_FACTOR: Decimal = dec!(0.211);
|
||||
|
||||
const SS_THRESHOLD: Decimal = dec!(99);
|
||||
const SS_FACTOR: Decimal = dec!(0.208);
|
||||
|
||||
const S_PLUS_PRO_THRESHOLD: Decimal = dec!(98.9999);
|
||||
const S_PLUS_PRO_FACTOR: Decimal = dec!(0.206);
|
||||
|
||||
const S_PLUS_THRESHOLD: Decimal = dec!(98);
|
||||
const S_PLUS_FACTOR: Decimal = dec!(0.203);
|
||||
|
||||
const S_THRESHOLD: Decimal = dec!(97);
|
||||
const S_FACTOR: Decimal = dec!(0.2);
|
||||
|
||||
const AAA_PRO_THRESHOLD: Decimal = dec!(96.9999);
|
||||
const AAA_PRO_FACTOR: Decimal = dec!(0.176);
|
||||
|
||||
const AAA_THRESHOLD: Decimal = dec!(94);
|
||||
const AAA_FACTOR: Decimal = dec!(0.168);
|
||||
|
||||
const AA_THRESHOLD: Decimal = dec!(90);
|
||||
const AA_FACTOR: Decimal = dec!(0.152);
|
||||
|
||||
const A_THRESHOLD: Decimal = dec!(80);
|
||||
const A_FACTOR: Decimal = dec!(0.136);
|
||||
|
||||
/*
|
||||
TODO: calculate (below) BBB dx rating
|
||||
[0, 0, 'd'],
|
||||
[10, 1.6, 'd'],
|
||||
[20, 3.2, 'd'],
|
||||
[30, 4.8, 'd'],
|
||||
[40, 6.4, 'd'],
|
||||
[50, 8, 'c'],
|
||||
[60, 9.6, 'b'],
|
||||
[70, 11.2, 'bb'],
|
||||
[75, 12.0, 'bbb'],
|
||||
[79.9999, 12.8, 'bbb'],
|
||||
*/
|
||||
const RANKS: [(&'static str, i32, Decimal); 23] = [
|
||||
("D", 0, dec!(0.0)),
|
||||
("D", 100000, dec!(0.16)),
|
||||
("D", 200000, dec!(0.32)),
|
||||
("D", 300000, dec!(0.48)),
|
||||
("D", 400000, dec!(0.64)),
|
||||
("C", 500000, dec!(0.80)),
|
||||
("B", 600000, dec!(0.96)),
|
||||
("BB", 700000, dec!(0.112)),
|
||||
("BBB", 750000, dec!(0.120)),
|
||||
("BBB", 799999, dec!(0.128)),
|
||||
("A", 800000, dec!(0.136)),
|
||||
("AA", 900000, dec!(0.152)),
|
||||
("AAA", 940000, dec!(0.168)),
|
||||
("AAA", 969999, dec!(0.176)),
|
||||
("S", 970000, dec!(0.200)),
|
||||
("S+", 980000, dec!(0.203)),
|
||||
("S+", 989999, dec!(0.206)),
|
||||
("SS", 990000, dec!(0.208)),
|
||||
("SS+", 995000, dec!(0.211)),
|
||||
("SS+", 999999, dec!(0.214)),
|
||||
("SSS", 1000000, dec!(0.216)),
|
||||
("SSS", 1004999, dec!(0.222)),
|
||||
("SSS+", 1005000, dec!(0.224)),
|
||||
];
|
||||
|
||||
@@ -141,8 +141,9 @@ impl Display for UserMusicDetail {
|
||||
f.write_fmt(format_args!("DX 分数: \t{}\n", self.deluxscore_max))?;
|
||||
|
||||
if let Some(level) = query_music_level(self.music_id, self.level) {
|
||||
let rating = level.dx_rating(self.achievement as _);
|
||||
f.write_fmt(format_args!("DX RATING: \t{rating}"))?;
|
||||
let (rank, rating) = level.dx_rating(self.achievement as _);
|
||||
f.write_fmt(format_args!("DX RATING: \t{rating}\n"))?;
|
||||
f.write_fmt(format_args!("RANK: \t{rank}"))?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
||||
@@ -182,6 +182,10 @@ impl MusicRating {
|
||||
}
|
||||
|
||||
pub fn dx_rating(&self) -> Option<u32> {
|
||||
Some(query_music_level(self.music_id, self.level)?.dx_rating(self.achievement))
|
||||
Some(
|
||||
query_music_level(self.music_id, self.level)?
|
||||
.dx_rating(self.achievement)
|
||||
.1,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user