Add BeatLeader score modifier support
This commit is contained in:
parent
9150fc4dd6
commit
2e06ac16ac
@ -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
|
||||
|
||||
|
@ -12,9 +12,9 @@ const nextConfig = {
|
||||
"avatars.akamai.steamstatic.com",
|
||||
],
|
||||
},
|
||||
experimental: {
|
||||
optimizeCss: true,
|
||||
},
|
||||
// experimental: {
|
||||
// optimizeCss: true,
|
||||
// },
|
||||
};
|
||||
|
||||
module.exports = nextConfig;
|
||||
|
@ -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;
|
||||
},
|
||||
},
|
||||
};
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
});
|
||||
}
|
@ -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,
|
||||
});
|
||||
}
|
@ -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: "",
|
||||
|
||||
|
@ -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));
|
||||
}
|
||||
|
Reference in New Issue
Block a user