Add BeatLeader score modifier support

This commit is contained in:
Lee 2022-12-11 09:42:24 +00:00
parent 9150fc4dd6
commit 2e06ac16ac
No known key found for this signature in database
GPG Key ID: 6EA25896ECCB3121
9 changed files with 103 additions and 47 deletions

View File

@ -22,7 +22,6 @@ Need help? Feel free to message me at: Fascinated#4719
## Todo
- Make BeatLeader pp count check for modifiers
- Add toggle for showing pp
- Change the song time to a circular style in the song art

View File

@ -12,9 +12,9 @@ const nextConfig = {
"avatars.akamai.steamstatic.com",
],
},
experimental: {
optimizeCss: true,
},
// experimental: {
// optimizeCss: true,
// },
};
module.exports = nextConfig;

View File

@ -9,12 +9,12 @@ const LeaderboardType = {
MapData:
"https://scoresaber.com/api/leaderboard/by-hash/%h/info?difficulty=%d",
},
async getMapStarCount(mapHash, mapDiff, characteristic) {
async getMapLeaderboardData(mapHash, mapDiff, characteristic) {
const data = await fetch(
`/api/scoresaber/stars?hash=${mapHash}&difficulty=${mapDiff}&characteristic=${characteristic}`
`/api/scoresaber/data?hash=${mapHash}&difficulty=${mapDiff}&characteristic=${characteristic}`
);
const json = await data.json();
return json.stars || undefined;
return json || undefined;
},
},
BeatLeader: {
@ -23,12 +23,12 @@ const LeaderboardType = {
env(VARS.HTTP_PROXY) + "/https://api.beatleader.xyz/player/%s",
MapData: "https://api.beatleader.xyz/map/hash/%h",
},
async getMapStarCount(mapHash, mapDiff, characteristic) {
async getMapLeaderboardData(mapHash, mapDiff, characteristic) {
const data = await fetch(
`/api/beatleader/stars?hash=${mapHash}&difficulty=${mapDiff}&characteristic=${characteristic}`
`/api/beatleader/data?hash=${mapHash}&difficulty=${mapDiff}&characteristic=${characteristic}`
);
const json = await data.json();
return json.stars || undefined;
return json || undefined;
},
},
};

View File

@ -2,7 +2,6 @@ function curve(acc, stars) {
var l = 1 - (0.03 * (stars - 3.0)) / 11.0;
var a = 0.96 * l;
var f = 1.2 - (0.6 * stars) / 14.0;
return Math.pow(Math.log10(l / (l - acc)) / Math.log10(l / (l - a)), f);
}

View File

@ -77,6 +77,7 @@ const handlers: any = {
resetCutState();
state.setInSong(true);
state.setCombo(data.status.performance.combo);
state.setModifiers(data.status.mod);
useDataStore.setState({ loadedDuringSong: true });
const { score, relativeScore } = data.status.performance;
@ -114,15 +115,9 @@ const handlers: any = {
} = data.status.beatmap;
state.reset();
cutData.saberA = {
count: [0, 0, 0],
totalScore: [0, 0, 0],
};
cutData.saberB = {
count: [0, 0, 0],
totalScore: [0, 0, 0],
};
resetCutState();
state.setInSong(true);
state.setModifiers(data.status.mod);
state.updateMapData(
getMapHashFromLevelId(levelId),
difficultyEnum,

View File

@ -1,12 +1,8 @@
import fetch from "node-fetch";
import WebsiteTypes from "../../../../src/consts/LeaderboardType";
import {
getValue,
setValue,
valueExists,
} from "../../../../src/utils/redisUtils";
import WebsiteTypes from "../../../consts/LeaderboardType";
import { getValue, setValue, valueExists } from "../../../utils/redisUtils";
const KEY = "BL_MAP_STAR_";
const KEY = "BL_MAP_DATA_";
/**
*
@ -29,12 +25,14 @@ export default async function handler(req, res) {
const exists = await valueExists(key);
if (exists) {
const data = await getValue(key);
const json = JSON.parse(data);
res.setHeader("Cache-Status", "hit");
return res.status(200).json({
status: "OK",
stars: Number.parseFloat(data),
difficulty: difficulty,
stars: json.stars,
modifiers: json.modifiers,
});
}
@ -55,12 +53,14 @@ export default async function handler(req, res) {
}
const json = await data.json();
let starCount = undefined;
let modifiers = undefined;
for (const diff of json.difficulties) {
if (
diff.difficultyName === difficulty &&
diff.modeName === characteristic
) {
starCount = diff.stars;
modifiers = diff.modifierValues;
}
}
if (starCount === undefined) {
@ -69,7 +69,13 @@ export default async function handler(req, res) {
message: "Unknown Map Hash",
});
}
await setValue(key, starCount);
await setValue(
key,
JSON.stringify({
stars: starCount,
modifiers: modifiers,
})
);
console.log(
`[Cache]: Cached BL Star Count for hash ${mapHash} in ${
Date.now() - before
@ -78,6 +84,8 @@ export default async function handler(req, res) {
res.setHeader("Cache-Status", "miss");
return res.status(200).json({
status: "OK",
difficulty: difficulty,
stars: starCount,
modifiers: modifiers,
});
}

View File

@ -1,11 +1,7 @@
import fetch from "node-fetch";
import WebsiteTypes from "../../../../src/consts/LeaderboardType";
import {
getValue,
setValue,
valueExists,
} from "../../../../src/utils/redisUtils";
import { diffToScoreSaberDiff } from "../../../../src/utils/scoreSaberUtils";
import WebsiteTypes from "../../../consts/LeaderboardType";
import { getValue, setValue, valueExists } from "../../../utils/redisUtils";
import { diffToScoreSaberDiff } from "../../../utils/scoreSaberUtils";
const KEY = "SS_MAP_STAR_";
@ -34,8 +30,8 @@ export default async function handler(req, res) {
return res.status(200).json({
status: "OK",
stars: Number.parseFloat(data),
difficulty: difficulty,
stars: Number.parseFloat(data),
});
}
@ -74,6 +70,7 @@ export default async function handler(req, res) {
res.setHeader("Cache-Status", "miss");
return res.status(200).json({
status: "OK",
difficulty: difficulty,
stars: starCount,
});
}

View File

@ -12,7 +12,11 @@ interface SongDataState {
songSubTitle: string;
songLength: number;
songDifficulty: string;
mapStarCount: number;
songModifiers: Object;
mapLeaderboardData: {
stars: Number;
modifiers: Object;
};
mapArt: string;
bsr: string;
@ -50,6 +54,7 @@ interface SongDataState {
setPp: (percent: number) => void;
setInSong: (isInSong: boolean) => void;
setSaberData: (saberType: string, cutData: any) => void;
setModifiers: (modifiers: Map<string, object>) => void;
}
export const useSongDataStore = create<SongDataState>()((set) => ({
@ -60,7 +65,11 @@ export const useSongDataStore = create<SongDataState>()((set) => ({
songSubTitle: "",
songLength: 0,
songDifficulty: "",
mapStarCount: 0,
songModifiers: {},
mapLeaderboardData: {
stars: 0,
modifiers: {},
},
mapArt: "",
bsr: "",
@ -93,11 +102,10 @@ export const useSongDataStore = create<SongDataState>()((set) => ({
let hasError = false;
const leaderboardType = useSettingsStore.getState().leaderboardType;
const mapStars = await Utils.getWebsiteApi(leaderboardType).getMapStarCount(
mapHash,
mapDiff,
characteristic
);
const mapLeaderboardData = await Utils.getWebsiteApi(
leaderboardType
).getMapLeaderboardData(mapHash, mapDiff, characteristic);
console.log(mapLeaderboardData);
const mapData = await axios.get(
`${env("SITE_URL")}/api/beatsaver/map?hash=${mapHash}`
@ -110,7 +118,7 @@ export const useSongDataStore = create<SongDataState>()((set) => ({
set({
isLoading: false,
hasError: hasError,
mapStarCount: mapStars,
mapLeaderboardData: mapLeaderboardData,
bsr: bsr,
mapArt: mapArt,
songDifficulty: mapDiff,
@ -150,7 +158,7 @@ export const useSongDataStore = create<SongDataState>()((set) => ({
setPp: (percent: number) => {
const leaderboardType = useSettingsStore.getState().leaderboardType;
const mapStarCount = useSongDataStore.getState().mapStarCount;
const mapStarCount = useSongDataStore.getState().mapLeaderboardData.stars;
let pp = Utils.calculatePP(mapStarCount, percent, leaderboardType);
if (pp === undefined) {
@ -163,6 +171,10 @@ export const useSongDataStore = create<SongDataState>()((set) => ({
set({ inSong: isInSong });
},
setModifiers(modifiers: Map<string, object>) {
set({ songModifiers: modifiers });
},
reset: () =>
set({
isLoading: true,
@ -170,7 +182,11 @@ export const useSongDataStore = create<SongDataState>()((set) => ({
songTitle: "",
songSubTitle: "",
songDifficulty: "",
mapStarCount: 0,
songModifiers: {},
mapLeaderboardData: {
stars: 0,
modifiers: {},
},
mapArt: "",
bsr: "",

View File

@ -1,6 +1,7 @@
import { default as LeaderboardType } from "../consts/LeaderboardType";
import { getBeatLeaderPP } from "../curve/BeatLeaderCurve";
import { getScoreSaberPP } from "../curve/ScoreSaberCurve";
import { useSongDataStore } from "../store/songDataStore";
export default class Utils {
/**
@ -35,7 +36,7 @@ export default class Utils {
return undefined;
}
if (type === "BeatLeader") {
return getBeatLeaderPP(acc, stars);
return getBeatLeaderPP(acc, stars) * (1 + this.calculateModifierBonus());
}
if (type === "ScoreSaber") {
return getScoreSaberPP(acc, stars);
@ -43,6 +44,47 @@ export default class Utils {
return undefined;
}
static calculateModifierBonus() {
const songMods = useSongDataStore.getState().songModifiers;
const modifierMulipliers =
useSongDataStore.getState().mapLeaderboardData.modifiers;
let bonus = 0;
if (
songMods.noFail == true &&
modifierMulipliers.nf < 0 &&
useSongDataStore.getState().failed
) {
bonus -= modifierMulipliers.nf;
}
if (songMods.songSpeed != "Normal") {
if (songMods.songSpeed == "FasterSong" && modifierMulipliers.fs > 0) {
bonus += modifierMulipliers.fs;
}
if (songMods.songSpeed == "SuperFast" && modifierMulipliers.sf > 0) {
bonus += modifierMulipliers.sf;
}
}
if (songMods.disappearingArrows == true && modifierMulipliers.da > 0) {
bonus += modifierMulipliers.da;
}
if (songMods.ghostNotes == true && modifierMulipliers.gn > 0) {
toAdd += modifierMulipliers.gn;
}
if (songMods.noArrows == true && modifierMulipliers.na < 0) {
bonus -= modifierMulipliers.na;
}
if (songMods.noBombs == true && modifierMulipliers.nb < 0) {
bonus -= modifierMulipliers.nb;
}
return bonus;
}
static base64ToArrayBuffer(base64) {
return Uint8Array.from(atob(base64), (c) => c.charCodeAt(0));
}