feat: support dx rating of below A rank

This commit is contained in:
mokurin000
2025-08-14 22:22:29 +08:00
parent 2b6bb12dce
commit f78c631570
3 changed files with 44 additions and 81 deletions

View File

@@ -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)),
];