Added pp for beat leader

This commit is contained in:
Liam 2022-10-20 15:04:49 +01:00
parent f2e36347ad
commit 538714a61e
4 changed files with 86 additions and 18 deletions

@ -3,6 +3,7 @@ import { Component } from "react";
import PlayerStats from "../src/components/PlayerStats";
import ScoreStats from "../src/components/ScoreStats";
import SongInfo from "../src/components/SongInfo";
import LeaderboardType from "../src/consts/LeaderboardType";
import Utils from "../src/utils/utils";
import styles from "../styles/overlay.module.css";
@ -26,7 +27,7 @@ export default class Overlay extends Component {
showPlayerStats: true,
showScore: false,
showSongInfo: false,
loadedDuringSong: false,
loadedDuringSong: false,
socket: undefined,
isVisible: false,
@ -37,6 +38,7 @@ export default class Overlay extends Component {
currentScore: 0,
percentage: "100.00%",
failed: false,
mapStarCount: undefined,
leftHand: {
averageCut: [15.0],
averagePreSwing: [70.0],
@ -175,7 +177,7 @@ export default class Overlay extends Component {
const data = await fetch(
Utils.getWebsiteApi(
id == "test" ? "Test" : this.state.websiteType
).ApiUrl.replace("%s", id),
).ApiUrl.PlayerData.replace("%s", id),
{
headers: {
"X-Requested-With": "BeatSaber Overlay",
@ -234,6 +236,7 @@ export default class Overlay extends Component {
console.log(
"Attempting to re-connect to the HTTP Status socket in 60 seconds."
);
this.resetData(false);
this.setState({ isConnectedToSocket: false });
setTimeout(() => this.connectSocket(), 60_000);
});
@ -261,6 +264,17 @@ export default class Overlay extends Component {
);
const json = await data.json();
this.setState({ beatSaverData: json });
if (this.state.websiteType == "BeatLeader") {
const { characteristic, levelId, difficulty } = songData;
let mapHash = levelId.replace("custom_level_", "");
const mapStars = await LeaderboardType.BeatLeader.getMapStarCount(
mapHash,
difficulty,
characteristic
);
this.setState({ mapStarCount: mapStars });
}
}
/**
@ -291,7 +305,8 @@ export default class Overlay extends Component {
currentScore: 0,
percentage: "100.00%",
isVisible: visible,
loadedDuringSong: loadedDuringSong
loadedDuringSong: loadedDuringSong,
mapStarCount: undefined,
});
}
@ -299,15 +314,15 @@ export default class Overlay extends Component {
handlers = {
hello: (data) => {
console.log("Hello from HTTP Status!");
if (data.status) {
if (this.state.songData === undefined) {
console.log("Going into level during song, resetting data.");
this.resetData(true, true);
this.setState({ songData: data, paused: false });
if (data.status.beatmap) {
this.setBeatSaver(data.status.beatmap);
}
}
if (
data.status &&
data.status.beatmap &&
this.state.songData === undefined
) {
console.log("Going into level during song, resetting data.");
this.resetData(true, true);
this.setState({ songData: data, paused: false });
this.setBeatSaver(data.status.beatmap);
}
},
scoreChanged: (data) => {
@ -438,7 +453,7 @@ export default class Overlay extends Component {
countryRank={data.countryRank.toLocaleString()}
websiteType={websiteType}
avatar={`/api/steamavatar?steamid=${id}`}
loadedDuringSong={this.state.loadedDuringSong}
loadedDuringSong={this.state.loadedDuringSong}
/>
) : (
<></>

@ -1,6 +1,7 @@
import { Component } from "react";
import styles from "../../styles/scoreStats.module.css";
import Utils from "../utils/utils";
export default class ScoreStats extends Component {
constructor(params) {
@ -19,12 +20,18 @@ export default class ScoreStats extends Component {
render() {
const data = this.props.data;
const currentPP = Utils.calculatePP(
data.mapStarCount,
data.percentage.replace("%", ""),
data.websiteType
);
return (
<div className={styles.scoreStats}>
<div className={styles.scoreStatsInfo}>
<p>{data.percentage}</p>
<p>{data.currentScore.toLocaleString()}</p>
{currentPP !== undefined ? <p>{currentPP.toFixed(0)}pp</p> : null}
</div>
<div>
<p className={styles.scoreStatsAverageCut}>Average Cut</p>

@ -2,10 +2,46 @@ import Config from "../../config.json";
const WebsiteTypes = {
ScoreSaber: {
ApiUrl: Config.proxy_url + "/https://scoresaber.com/api/player/%s/basic",
ApiUrl: {
PlayerData:
Config.proxy_url + "/https://scoresaber.com/api/player/%s/basic",
},
},
BeatLeader: {
ApiUrl: Config.proxy_url + "/https://api.beatleader.xyz/player/%s",
ApiUrl: {
PlayerData: Config.proxy_url + "/https://api.beatleader.xyz/player/%s",
MapData:
Config.proxy_url +
"/https://api.beatleader.xyz/leaderboard/hash/%h/%d/%m",
},
async getMapStarCount(mapHash, mapDiff, characteristic) {
const data = await fetch(
this.ApiUrl.MapData.replace("%h", mapHash)
.replace("%d", mapDiff.replace("+", "Plus"))
.replace("%m", characteristic),
{
headers: {
"X-Requested-With": "BeatSaber Overlay",
},
}
);
const json = await data.json();
return json.difficulty.stars || undefined;
},
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);
},
ppFromAcc(acc, stars) {
if (stars === undefined) {
return undefined;
}
const pp = this.curve(acc / 100, stars - 0.5) * (stars + 0.5) * 42;
return pp == NaN ? undefined : pp;
},
},
Test: {
ApiUrl: "/api/mockdata",

@ -1,9 +1,12 @@
import SteamIdCache from "../../src/caches/SteamIdCache";
import LeaderboardType from "../consts/LeaderboardType";
import {
default as LeaderboardType,
default as WebsiteTypes,
} from "../consts/LeaderboardType";
const TO_CHECK = [
LeaderboardType.ScoreSaber.ApiUrl,
LeaderboardType.BeatLeader.ApiUrl,
LeaderboardType.ScoreSaber.ApiUrl.PlayerData,
LeaderboardType.BeatLeader.ApiUrl.PlayerData,
];
export default class Utils {
@ -64,4 +67,11 @@ export default class Utils {
const json = await data.json();
return !!json.pp;
}
static calculatePP(stars, acc, type) {
if (type === "BeatLeader") {
return WebsiteTypes.BeatLeader.ppFromAcc(acc, stars);
}
return undefined;
}
}