cleanup and add weighted pp hover on score
Some checks failed
deploy / deploy (push) Failing after 1m34s
Some checks failed
deploy / deploy (push) Failing after 1m34s
This commit is contained in:
parent
7b293b3eff
commit
bef899d21e
@ -3,7 +3,7 @@ import Card from "@/components/Card";
|
|||||||
import Container from "@/components/Container";
|
import Container from "@/components/Container";
|
||||||
import { ScoresaberMetricsHistory } from "@/schemas/fascinated/scoresaberMetricsHistory";
|
import { ScoresaberMetricsHistory } from "@/schemas/fascinated/scoresaberMetricsHistory";
|
||||||
import { ssrSettings } from "@/ssrSettings";
|
import { ssrSettings } from "@/ssrSettings";
|
||||||
import { formatNumber } from "@/utils/number";
|
import { formatNumber } from "@/utils/numberUtils";
|
||||||
import { isProduction } from "@/utils/utils";
|
import { isProduction } from "@/utils/utils";
|
||||||
import { Metadata } from "next";
|
import { Metadata } from "next";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import Leaderboard from "@/components/leaderboard/Leaderboard";
|
import Leaderboard from "@/components/leaderboard/Leaderboard";
|
||||||
import { formatNumber } from "@/utils/number";
|
import { formatNumber } from "@/utils/numberUtils";
|
||||||
import { ScoreSaberAPI } from "@/utils/scoresaber/api";
|
import { ScoreSaberAPI } from "@/utils/scoresaber/api";
|
||||||
import { scoresaberDifficultyNumberToName } from "@/utils/songUtils";
|
import { scoresaberDifficultyNumberToName } from "@/utils/songUtils";
|
||||||
import { formatTime } from "@/utils/timeUtils";
|
import { formatTime } from "@/utils/timeUtils";
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import PlayerPage from "@/components/player/PlayerPage";
|
import PlayerPage from "@/components/player/PlayerPage";
|
||||||
import { ssrSettings } from "@/ssrSettings";
|
import { ssrSettings } from "@/ssrSettings";
|
||||||
import { formatNumber } from "@/utils/number";
|
import { formatNumber } from "@/utils/numberUtils";
|
||||||
import { ScoreSaberAPI } from "@/utils/scoresaber/api";
|
import { ScoreSaberAPI } from "@/utils/scoresaber/api";
|
||||||
import { normalizedRegionName } from "@/utils/utils";
|
import { normalizedRegionName } from "@/utils/utils";
|
||||||
import { Metadata } from "next";
|
import { Metadata } from "next";
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import { ScoresaberLeaderboardInfo } from "@/schemas/scoresaber/leaderboard";
|
import { ScoresaberLeaderboardInfo } from "@/schemas/scoresaber/leaderboard";
|
||||||
import { ScoresaberScore } from "@/schemas/scoresaber/score";
|
import { ScoresaberScore } from "@/schemas/scoresaber/score";
|
||||||
import { formatNumber } from "@/utils/number";
|
import { formatNumber } from "@/utils/numberUtils";
|
||||||
import { scoresaberDifficultyNumberToName } from "@/utils/songUtils";
|
|
||||||
import { formatDate, formatTimeAgo } from "@/utils/timeUtils";
|
import { formatDate, formatTimeAgo } from "@/utils/timeUtils";
|
||||||
import Image from "next/image";
|
import Image from "next/image";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
@ -18,9 +17,6 @@ export default function LeaderboardScore({
|
|||||||
player,
|
player,
|
||||||
leaderboard,
|
leaderboard,
|
||||||
}: ScoreProps) {
|
}: ScoreProps) {
|
||||||
const diffName = scoresaberDifficultyNumberToName(
|
|
||||||
leaderboard.difficulty.difficulty,
|
|
||||||
);
|
|
||||||
const accuracy = ((score.baseScore / leaderboard.maxScore) * 100).toFixed(2);
|
const accuracy = ((score.baseScore / leaderboard.maxScore) * 100).toFixed(2);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { ScoresaberPlayer } from "@/schemas/scoresaber/player";
|
import { ScoresaberPlayer } from "@/schemas/scoresaber/player";
|
||||||
import { formatNumber } from "@/utils/number";
|
import { formatNumber } from "@/utils/numberUtils";
|
||||||
import {
|
import {
|
||||||
CategoryScale,
|
CategoryScale,
|
||||||
Chart as ChartJS,
|
Chart as ChartJS,
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { ScoresaberPlayer } from "@/schemas/scoresaber/player";
|
import { ScoresaberPlayer } from "@/schemas/scoresaber/player";
|
||||||
import { useScoresaberScoresStore } from "@/store/scoresaberScoresStore";
|
import { useScoresaberScoresStore } from "@/store/scoresaberScoresStore";
|
||||||
import { useSettingsStore } from "@/store/settingsStore";
|
import { useSettingsStore } from "@/store/settingsStore";
|
||||||
import { formatNumber } from "@/utils/number";
|
import { formatNumber } from "@/utils/numberUtils";
|
||||||
import {
|
import {
|
||||||
calcPpBoundary,
|
calcPpBoundary,
|
||||||
getAveragePp,
|
getAveragePp,
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
import { ScoresaberLeaderboardInfo } from "@/schemas/scoresaber/leaderboard";
|
import { ScoresaberLeaderboardInfo } from "@/schemas/scoresaber/leaderboard";
|
||||||
import { ScoresaberPlayer } from "@/schemas/scoresaber/player";
|
import { ScoresaberPlayer } from "@/schemas/scoresaber/player";
|
||||||
import { ScoresaberScore } from "@/schemas/scoresaber/score";
|
import { ScoresaberScore } from "@/schemas/scoresaber/score";
|
||||||
import { formatNumber } from "@/utils/number";
|
import { formatNumber } from "@/utils/numberUtils";
|
||||||
|
import { getPpGainedFromScore } from "@/utils/scoresaber/scores";
|
||||||
import {
|
import {
|
||||||
scoresaberDifficultyNumberToName,
|
scoresaberDifficultyNumberToName,
|
||||||
songDifficultyToColor,
|
songDifficultyToColor,
|
||||||
@ -120,6 +121,10 @@ export default function Score({ score, player, leaderboard }: ScoreProps) {
|
|||||||
<ScoreStatLabel
|
<ScoreStatLabel
|
||||||
className="bg-blue-500 text-center"
|
className="bg-blue-500 text-center"
|
||||||
value={formatNumber(score.pp.toFixed(2)) + "pp"}
|
value={formatNumber(score.pp.toFixed(2)) + "pp"}
|
||||||
|
title={`Weighted pp ${formatNumber(
|
||||||
|
getPpGainedFromScore(player.id, score),
|
||||||
|
2,
|
||||||
|
)}pp`}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
@ -1,12 +0,0 @@
|
|||||||
/**
|
|
||||||
* Formats a number to a string with commas
|
|
||||||
*
|
|
||||||
* @param number the number to format
|
|
||||||
* @returns the formatted number
|
|
||||||
*/
|
|
||||||
export function formatNumber(number: any) {
|
|
||||||
if (number === undefined) {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
return number.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
|
|
||||||
}
|
|
@ -7,3 +7,25 @@
|
|||||||
export function isNumber(value: any): boolean {
|
export function isNumber(value: any): boolean {
|
||||||
return !isNaN(value);
|
return !isNaN(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Formats a number to a string with commas
|
||||||
|
*
|
||||||
|
* @param number the number to format
|
||||||
|
* @returns the formatted number
|
||||||
|
*/
|
||||||
|
export function formatNumber(number: any, decimals?: number) {
|
||||||
|
if (decimals === undefined) {
|
||||||
|
decimals = 0;
|
||||||
|
}
|
||||||
|
if (number === undefined) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
if (typeof number !== "number") {
|
||||||
|
return number;
|
||||||
|
}
|
||||||
|
return number.toLocaleString(undefined, {
|
||||||
|
minimumFractionDigits: decimals,
|
||||||
|
maximumFractionDigits: decimals,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
// Yoinked from https://github.com/Shurdoof/pp-calculator
|
// Yoinked from https://github.com/Shurdoof/pp-calculator
|
||||||
// Thank for for this I have no fucking idea what the maths is doing but it works!
|
// Thank for for this I have no fucking idea what the maths is doing but it works!
|
||||||
|
|
||||||
|
import { ScoresaberScore } from "@/schemas/scoresaber/score";
|
||||||
import { useScoresaberScoresStore } from "@/store/scoresaberScoresStore";
|
import { useScoresaberScoresStore } from "@/store/scoresaberScoresStore";
|
||||||
|
|
||||||
export const WEIGHT_COEFFICIENT = 0.965;
|
export const WEIGHT_COEFFICIENT = 0.965;
|
||||||
@ -168,6 +169,38 @@ export function calcPpBoundary(playerId: string, expectedPp = 1) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the ranked scores of the player
|
||||||
|
*
|
||||||
|
* @param playerId the player id
|
||||||
|
* @returns all ranked scores of the player
|
||||||
|
*/
|
||||||
|
export function getRankedScores(playerId: string, sorted: boolean = false) {
|
||||||
|
const scores = useScoresaberScoresStore
|
||||||
|
.getState()
|
||||||
|
.players.find((p) => p.id === playerId)
|
||||||
|
?.scores?.filter((s) => s.score.pp !== undefined);
|
||||||
|
if (sorted && scores) {
|
||||||
|
return scores.sort((a, b) => b.score.pp - a.score.pp);
|
||||||
|
}
|
||||||
|
return scores;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the global pp gained from the score
|
||||||
|
*
|
||||||
|
* @param playerId the player id
|
||||||
|
* @param score the score to get the pp gained from
|
||||||
|
* @returns the pp gained from the score
|
||||||
|
*/
|
||||||
|
export function getPpGainedFromScore(playerId: string, score: ScoresaberScore) {
|
||||||
|
const scores = getRankedScores(playerId, true);
|
||||||
|
if (!scores) return null;
|
||||||
|
const scoreIndex = scores.map((s) => s.score.id).indexOf(score.id);
|
||||||
|
|
||||||
|
return score.pp * Math.pow(WEIGHT_COEFFICIENT, scoreIndex);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the highest pp play of a player
|
* Get the highest pp play of a player
|
||||||
*
|
*
|
||||||
@ -195,16 +228,10 @@ export function getHighestPpPlay(playerId: string) {
|
|||||||
* @param limit the amount of top scores to average (default: 50)
|
* @param limit the amount of top scores to average (default: 50)
|
||||||
*/
|
*/
|
||||||
export function getAveragePp(playerId: string, limit: number = 50) {
|
export function getAveragePp(playerId: string, limit: number = 50) {
|
||||||
const rankedScores = useScoresaberScoresStore
|
const rankedScores = getRankedScores(playerId, true);
|
||||||
.getState()
|
|
||||||
.players.find((p) => p.id === playerId)
|
|
||||||
?.scores?.filter((s) => s.score.pp !== undefined);
|
|
||||||
if (!rankedScores) return null;
|
if (!rankedScores) return null;
|
||||||
|
|
||||||
const rankedScorePps = rankedScores
|
const rankedScorePps = rankedScores.map((s) => s.score.pp).slice(0, limit);
|
||||||
.map((s) => s.score.pp)
|
|
||||||
.sort((a, b) => b - a)
|
|
||||||
.slice(0, limit);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
rankedScorePps.reduce((cum, pp) => cum + pp, 0) / rankedScorePps.length
|
rankedScorePps.reduce((cum, pp) => cum + pp, 0) / rankedScorePps.length
|
||||||
|
Loading…
Reference in New Issue
Block a user