This commit is contained in:
parent
4c32f504a4
commit
024f553586
@ -1,53 +1,121 @@
|
|||||||
import Utils from "../utils/utils";
|
import Utils from "../utils/utils";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* I'm not even sure what this shit does, ask BL
|
* The pp curve of this leaderboard
|
||||||
* @see https://github.com/BeatLeader/beatleader-server/blob/16123a792b1a837faf6287e5bcd58e2e06e6a6f0/Utils/ReplayUtils.cs for more info
|
*/
|
||||||
|
const ppCurve = [
|
||||||
|
[1.0, 7.424],
|
||||||
|
[0.999, 6.241],
|
||||||
|
[0.9975, 5.158],
|
||||||
|
[0.995, 4.01],
|
||||||
|
[0.9925, 3.241],
|
||||||
|
[0.99, 2.7],
|
||||||
|
[0.9875, 2.303],
|
||||||
|
[0.985, 2.007],
|
||||||
|
[0.9825, 1.786],
|
||||||
|
[0.98, 1.618],
|
||||||
|
[0.9775, 1.49],
|
||||||
|
[0.975, 1.392],
|
||||||
|
[0.9725, 1.315],
|
||||||
|
[0.97, 1.256],
|
||||||
|
[0.965, 1.167],
|
||||||
|
[0.96, 1.101],
|
||||||
|
[0.955, 1.047],
|
||||||
|
[0.95, 1.0],
|
||||||
|
[0.94, 0.919],
|
||||||
|
[0.93, 0.847],
|
||||||
|
[0.92, 0.786],
|
||||||
|
[0.91, 0.734],
|
||||||
|
[0.9, 0.692],
|
||||||
|
[0.875, 0.606],
|
||||||
|
[0.85, 0.537],
|
||||||
|
[0.825, 0.48],
|
||||||
|
[0.8, 0.429],
|
||||||
|
[0.75, 0.345],
|
||||||
|
[0.7, 0.286],
|
||||||
|
[0.65, 0.246],
|
||||||
|
[0.6, 0.217],
|
||||||
|
[0.0, 0.0],
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* https://github.com/BeatLeader/beatleader-server/blob/master/Utils/ReplayUtils.cs#L45
|
||||||
|
* funky shit from ^
|
||||||
*
|
*
|
||||||
* @param {Number} acc the accuracy of the score
|
* @param {Number} accuracy the accuracy of the score
|
||||||
* @param {Number} stars the ranked star count
|
* @param {Number} accRating the acc rating of the difficulty
|
||||||
|
* @param {Number} passRating the pass rating of the difficulty
|
||||||
|
* @param {Number} techRating the tech rating of the difficulty
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
function curve(acc, stars) {
|
export function getBeatLeaderPP(accuracy, accRating, passRating, techRating) {
|
||||||
var l = 1 - (0.03 * (stars - 3.0)) / 11.0;
|
const modifierBonus = Utils.calculateModifierBonus();
|
||||||
var a = 0.96 * l;
|
const ppValues = getPP(
|
||||||
var f = 1.2 - (0.6 * stars) / 14.0;
|
accuracy,
|
||||||
return Math.pow(Math.log10(l / (l - acc)) / Math.log10(l / (l - a)), f);
|
accRating,
|
||||||
|
passRating * modifierBonus,
|
||||||
|
techRating * modifierBonus
|
||||||
|
);
|
||||||
|
const pp = inflate(ppValues.passPP + ppValues.accPP + ppValues.techPP);
|
||||||
|
return isNaN(pp) ? 1024 : pp;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the raw pp from the given score
|
* https://github.com/BeatLeader/beatleader-server/blob/master/Utils/ReplayUtils.cs#L45
|
||||||
|
* funky shit from ^
|
||||||
*
|
*
|
||||||
* @param {Number} acc the accuracy of the score
|
* @param {Number} accuracy the accuracy of the score
|
||||||
* @param {Number} stars the ranked star count
|
* @param {Number} accRating the acc rating of the difficulty
|
||||||
|
* @param {Number} passRating the pass rating of the difficulty
|
||||||
|
* @param {Number} techRating the tech rating of the difficulty
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
export function getBeatLeaderPP(acc, stars) {
|
function getPP(accuracy, accRating, passRating, techRating) {
|
||||||
if (stars === undefined || acc === undefined) {
|
let passPP = 15.2 * Math.exp(Math.pow(passRating, 1 / 2.62)) - 30;
|
||||||
return undefined;
|
if (isNaN(passPP) || passPP == Infinity) {
|
||||||
|
passPP = 0;
|
||||||
}
|
}
|
||||||
const modifierBonus = Utils.calculateModifierBonus();
|
let accPP = curve(accuracy) * accRating * 34;
|
||||||
let rawPP = curve(acc, stars - 0.5) * (stars + 0.5) * 42;
|
let techPP = Math.exp(1.9 * accuracy) * techRating;
|
||||||
let fullPP =
|
|
||||||
curve(acc, stars * modifierBonus - 0.5) *
|
|
||||||
(stars * modifierBonus + 0.5) *
|
|
||||||
42;
|
|
||||||
|
|
||||||
const isNegativeAcc = acc < 0;
|
return {
|
||||||
if (isNegativeAcc) {
|
passPP: passPP,
|
||||||
acc *= -1;
|
accPP: accPP,
|
||||||
|
techPP: techPP,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isNaN(rawPP) || rawPP == Infinity) {
|
/**
|
||||||
return 1024;
|
* https://github.com/BeatLeader/beatleader-server/blob/master/Utils/ReplayUtils.cs#L45
|
||||||
|
* funky shit from ^
|
||||||
|
*
|
||||||
|
* @param {Number} acc the accuracy of the score
|
||||||
|
* @returns something
|
||||||
|
*/
|
||||||
|
function curve(acc) {
|
||||||
|
let i = 0;
|
||||||
|
for (; i < ppCurve.length; i++) {
|
||||||
|
if (ppCurve[i][0] <= acc) {
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
if (isNaN(fullPP) || fullPP == Infinity) {
|
|
||||||
return 1024;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isNegativeAcc) {
|
if (i == 0) {
|
||||||
fullPP *= -1;
|
i = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return fullPP;
|
const middle_dis =
|
||||||
|
(acc - ppCurve[i - 1][0]) / (ppCurve[i][0] - ppCurve[i - 1][0]);
|
||||||
|
return ppCurve[i - 1][1] + middle_dis * (ppCurve[i][1] - ppCurve[i - 1][1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* https://github.com/BeatLeader/beatleader-server/blob/master/Utils/ReplayUtils.cs#L77
|
||||||
|
* funky shit from ^
|
||||||
|
*
|
||||||
|
* @param {Number} peepee
|
||||||
|
* @returns funny number, idk
|
||||||
|
*/
|
||||||
|
function inflate(peepee) {
|
||||||
|
return (650 * Math.pow(peepee, 1.3)) / Math.pow(650, 1.3);
|
||||||
}
|
}
|
||||||
|
@ -33,6 +33,9 @@ export default async function handler(req, res) {
|
|||||||
difficulty: difficulty,
|
difficulty: difficulty,
|
||||||
stars: json.stars,
|
stars: json.stars,
|
||||||
modifiers: json.modifiers,
|
modifiers: json.modifiers,
|
||||||
|
passRating: json.passRating,
|
||||||
|
accRating: json.accRating,
|
||||||
|
techRating: json.techRating,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -54,6 +57,10 @@ export default async function handler(req, res) {
|
|||||||
const json = reesponse.data;
|
const json = reesponse.data;
|
||||||
let starCount = undefined;
|
let starCount = undefined;
|
||||||
let modifiers = undefined;
|
let modifiers = undefined;
|
||||||
|
let passRating = undefined;
|
||||||
|
let accRating = undefined;
|
||||||
|
let techRating = undefined;
|
||||||
|
|
||||||
for (const diff of json.difficulties) {
|
for (const diff of json.difficulties) {
|
||||||
if (
|
if (
|
||||||
diff.difficultyName === difficulty &&
|
diff.difficultyName === difficulty &&
|
||||||
@ -61,6 +68,9 @@ export default async function handler(req, res) {
|
|||||||
) {
|
) {
|
||||||
starCount = diff.stars;
|
starCount = diff.stars;
|
||||||
modifiers = diff.modifierValues;
|
modifiers = diff.modifierValues;
|
||||||
|
passRating = diff.passRating;
|
||||||
|
accRating = diff.accRating;
|
||||||
|
techRating = diff.techRating;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (starCount === undefined) {
|
if (starCount === undefined) {
|
||||||
@ -74,6 +84,9 @@ export default async function handler(req, res) {
|
|||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
stars: starCount,
|
stars: starCount,
|
||||||
modifiers: modifiers,
|
modifiers: modifiers,
|
||||||
|
passRating: passRating,
|
||||||
|
accRating: accRating,
|
||||||
|
techRating: techRating,
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
console.log(
|
console.log(
|
||||||
@ -87,5 +100,8 @@ export default async function handler(req, res) {
|
|||||||
difficulty: difficulty,
|
difficulty: difficulty,
|
||||||
stars: starCount,
|
stars: starCount,
|
||||||
modifiers: modifiers,
|
modifiers: modifiers,
|
||||||
|
passRating: passRating,
|
||||||
|
accRating: accRating,
|
||||||
|
techRating: techRating,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,9 @@ interface SongDataState {
|
|||||||
beatleader: {
|
beatleader: {
|
||||||
stars: Number | undefined;
|
stars: Number | undefined;
|
||||||
modifiers: Object;
|
modifiers: Object;
|
||||||
|
passRating: number | undefined;
|
||||||
|
accRating: number | undefined;
|
||||||
|
techRating: number | undefined;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
mapArt: string;
|
mapArt: string;
|
||||||
@ -82,6 +85,9 @@ export const useSongDataStore = create<SongDataState>()((set) => ({
|
|||||||
beatleader: {
|
beatleader: {
|
||||||
stars: 0,
|
stars: 0,
|
||||||
modifiers: {},
|
modifiers: {},
|
||||||
|
passRating: undefined,
|
||||||
|
accRating: undefined,
|
||||||
|
techRating: undefined,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
mapArt: "",
|
mapArt: "",
|
||||||
@ -134,6 +140,16 @@ export const useSongDataStore = create<SongDataState>()((set) => ({
|
|||||||
}
|
}
|
||||||
const { bsr, mapArt } = mapDataresponse.data.data;
|
const { bsr, mapArt } = mapDataresponse.data.data;
|
||||||
|
|
||||||
|
console.log({
|
||||||
|
beatleader: {
|
||||||
|
stars: beatLeaderLeaderboardData.stars,
|
||||||
|
modifiers: beatLeaderLeaderboardData.modifiers,
|
||||||
|
passRating: beatLeaderLeaderboardData.passRating,
|
||||||
|
accRating: beatLeaderLeaderboardData.accRating,
|
||||||
|
techRating: beatLeaderLeaderboardData.techRating,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
set({
|
set({
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
hasError: hasError,
|
hasError: hasError,
|
||||||
@ -141,6 +157,9 @@ export const useSongDataStore = create<SongDataState>()((set) => ({
|
|||||||
beatleader: {
|
beatleader: {
|
||||||
stars: beatLeaderLeaderboardData.stars,
|
stars: beatLeaderLeaderboardData.stars,
|
||||||
modifiers: beatLeaderLeaderboardData.modifiers,
|
modifiers: beatLeaderLeaderboardData.modifiers,
|
||||||
|
passRating: beatLeaderLeaderboardData.passRating,
|
||||||
|
accRating: beatLeaderLeaderboardData.accRating,
|
||||||
|
techRating: beatLeaderLeaderboardData.techRating,
|
||||||
},
|
},
|
||||||
scoresaber: {
|
scoresaber: {
|
||||||
stars: scoreSaberLeaderboardData.stars,
|
stars: scoreSaberLeaderboardData.stars,
|
||||||
@ -244,6 +263,9 @@ export const useSongDataStore = create<SongDataState>()((set) => ({
|
|||||||
beatleader: {
|
beatleader: {
|
||||||
stars: undefined,
|
stars: undefined,
|
||||||
modifiers: {},
|
modifiers: {},
|
||||||
|
passRating: undefined,
|
||||||
|
accRating: undefined,
|
||||||
|
techRating: undefined,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
mapArt: "",
|
mapArt: "",
|
||||||
|
@ -37,7 +37,15 @@ export default class Utils {
|
|||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
if (type === "BeatLeader") {
|
if (type === "BeatLeader") {
|
||||||
return getBeatLeaderPP(acc, stars);
|
const leaderboardData =
|
||||||
|
useSongDataStore.getState().mapLeaderboardData.beatleader;
|
||||||
|
|
||||||
|
return getBeatLeaderPP(
|
||||||
|
acc,
|
||||||
|
leaderboardData.accRating,
|
||||||
|
leaderboardData.passRating,
|
||||||
|
leaderboardData.techRating
|
||||||
|
);
|
||||||
}
|
}
|
||||||
if (type === "ScoreSaber") {
|
if (type === "ScoreSaber") {
|
||||||
return getScoreSaberPP(acc, stars);
|
return getScoreSaberPP(acc, stars);
|
||||||
@ -48,7 +56,7 @@ export default class Utils {
|
|||||||
static calculateModifierBonus() {
|
static calculateModifierBonus() {
|
||||||
const songMods = useSongDataStore.getState().songModifiers;
|
const songMods = useSongDataStore.getState().songModifiers;
|
||||||
const modifierMulipliers =
|
const modifierMulipliers =
|
||||||
useSongDataStore.getState().mapLeaderboardData.modifiers;
|
useSongDataStore.getState().mapLeaderboardData.beatleader.modifiers;
|
||||||
let bonus = 1;
|
let bonus = 1;
|
||||||
|
|
||||||
// No Fail
|
// No Fail
|
||||||
|
Reference in New Issue
Block a user