From bef899d21ecef939042bd2f12d1022bd8ce40757 Mon Sep 17 00:00:00 2001 From: Liam Date: Sun, 29 Oct 2023 13:25:41 +0000 Subject: [PATCH] cleanup and add weighted pp hover on score --- src/app/analytics/page.tsx | 2 +- src/app/leaderboard/[id]/[page]/page.tsx | 2 +- src/app/player/[id]/[sort]/[page]/page.tsx | 2 +- .../leaderboard/LeaderboardScore.tsx | 6 +-- src/components/player/PlayerChart.tsx | 2 +- src/components/player/PlayerInfo.tsx | 2 +- src/components/player/Score.tsx | 7 ++- src/utils/number.ts | 12 ------ src/utils/numberUtils.ts | 22 ++++++++++ src/utils/scoresaber/scores.ts | 43 +++++++++++++++---- 10 files changed, 69 insertions(+), 31 deletions(-) delete mode 100644 src/utils/number.ts diff --git a/src/app/analytics/page.tsx b/src/app/analytics/page.tsx index b381081..a1358a6 100644 --- a/src/app/analytics/page.tsx +++ b/src/app/analytics/page.tsx @@ -3,7 +3,7 @@ import Card from "@/components/Card"; import Container from "@/components/Container"; import { ScoresaberMetricsHistory } from "@/schemas/fascinated/scoresaberMetricsHistory"; import { ssrSettings } from "@/ssrSettings"; -import { formatNumber } from "@/utils/number"; +import { formatNumber } from "@/utils/numberUtils"; import { isProduction } from "@/utils/utils"; import { Metadata } from "next"; import Link from "next/link"; diff --git a/src/app/leaderboard/[id]/[page]/page.tsx b/src/app/leaderboard/[id]/[page]/page.tsx index 6bd5d06..3cdd278 100644 --- a/src/app/leaderboard/[id]/[page]/page.tsx +++ b/src/app/leaderboard/[id]/[page]/page.tsx @@ -1,5 +1,5 @@ import Leaderboard from "@/components/leaderboard/Leaderboard"; -import { formatNumber } from "@/utils/number"; +import { formatNumber } from "@/utils/numberUtils"; import { ScoreSaberAPI } from "@/utils/scoresaber/api"; import { scoresaberDifficultyNumberToName } from "@/utils/songUtils"; import { formatTime } from "@/utils/timeUtils"; diff --git a/src/app/player/[id]/[sort]/[page]/page.tsx b/src/app/player/[id]/[sort]/[page]/page.tsx index 5018002..f1af0c0 100644 --- a/src/app/player/[id]/[sort]/[page]/page.tsx +++ b/src/app/player/[id]/[sort]/[page]/page.tsx @@ -1,6 +1,6 @@ import PlayerPage from "@/components/player/PlayerPage"; import { ssrSettings } from "@/ssrSettings"; -import { formatNumber } from "@/utils/number"; +import { formatNumber } from "@/utils/numberUtils"; import { ScoreSaberAPI } from "@/utils/scoresaber/api"; import { normalizedRegionName } from "@/utils/utils"; import { Metadata } from "next"; diff --git a/src/components/leaderboard/LeaderboardScore.tsx b/src/components/leaderboard/LeaderboardScore.tsx index bc9c16b..b0b2b2b 100644 --- a/src/components/leaderboard/LeaderboardScore.tsx +++ b/src/components/leaderboard/LeaderboardScore.tsx @@ -1,7 +1,6 @@ import { ScoresaberLeaderboardInfo } from "@/schemas/scoresaber/leaderboard"; import { ScoresaberScore } from "@/schemas/scoresaber/score"; -import { formatNumber } from "@/utils/number"; -import { scoresaberDifficultyNumberToName } from "@/utils/songUtils"; +import { formatNumber } from "@/utils/numberUtils"; import { formatDate, formatTimeAgo } from "@/utils/timeUtils"; import Image from "next/image"; import Link from "next/link"; @@ -18,9 +17,6 @@ export default function LeaderboardScore({ player, leaderboard, }: ScoreProps) { - const diffName = scoresaberDifficultyNumberToName( - leaderboard.difficulty.difficulty, - ); const accuracy = ((score.baseScore / leaderboard.maxScore) * 100).toFixed(2); return ( diff --git a/src/components/player/PlayerChart.tsx b/src/components/player/PlayerChart.tsx index 6c32e4d..e237d69 100644 --- a/src/components/player/PlayerChart.tsx +++ b/src/components/player/PlayerChart.tsx @@ -1,5 +1,5 @@ import { ScoresaberPlayer } from "@/schemas/scoresaber/player"; -import { formatNumber } from "@/utils/number"; +import { formatNumber } from "@/utils/numberUtils"; import { CategoryScale, Chart as ChartJS, diff --git a/src/components/player/PlayerInfo.tsx b/src/components/player/PlayerInfo.tsx index 1b41c9f..2cc74e1 100644 --- a/src/components/player/PlayerInfo.tsx +++ b/src/components/player/PlayerInfo.tsx @@ -1,7 +1,7 @@ import { ScoresaberPlayer } from "@/schemas/scoresaber/player"; import { useScoresaberScoresStore } from "@/store/scoresaberScoresStore"; import { useSettingsStore } from "@/store/settingsStore"; -import { formatNumber } from "@/utils/number"; +import { formatNumber } from "@/utils/numberUtils"; import { calcPpBoundary, getAveragePp, diff --git a/src/components/player/Score.tsx b/src/components/player/Score.tsx index b6f4b0b..f131572 100644 --- a/src/components/player/Score.tsx +++ b/src/components/player/Score.tsx @@ -1,7 +1,8 @@ import { ScoresaberLeaderboardInfo } from "@/schemas/scoresaber/leaderboard"; import { ScoresaberPlayer } from "@/schemas/scoresaber/player"; import { ScoresaberScore } from "@/schemas/scoresaber/score"; -import { formatNumber } from "@/utils/number"; +import { formatNumber } from "@/utils/numberUtils"; +import { getPpGainedFromScore } from "@/utils/scoresaber/scores"; import { scoresaberDifficultyNumberToName, songDifficultyToColor, @@ -120,6 +121,10 @@ export default function Score({ score, player, leaderboard }: ScoreProps) { )} diff --git a/src/utils/number.ts b/src/utils/number.ts deleted file mode 100644 index ad09f11..0000000 --- a/src/utils/number.ts +++ /dev/null @@ -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, ","); -} diff --git a/src/utils/numberUtils.ts b/src/utils/numberUtils.ts index 9c24a58..76659bb 100644 --- a/src/utils/numberUtils.ts +++ b/src/utils/numberUtils.ts @@ -7,3 +7,25 @@ export function isNumber(value: any): boolean { 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, + }); +} diff --git a/src/utils/scoresaber/scores.ts b/src/utils/scoresaber/scores.ts index 8cdd226..5b578b3 100644 --- a/src/utils/scoresaber/scores.ts +++ b/src/utils/scoresaber/scores.ts @@ -1,6 +1,7 @@ // 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! +import { ScoresaberScore } from "@/schemas/scoresaber/score"; import { useScoresaberScoresStore } from "@/store/scoresaberScoresStore"; 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 * @@ -195,16 +228,10 @@ export function getHighestPpPlay(playerId: string) { * @param limit the amount of top scores to average (default: 50) */ export function getAveragePp(playerId: string, limit: number = 50) { - const rankedScores = useScoresaberScoresStore - .getState() - .players.find((p) => p.id === playerId) - ?.scores?.filter((s) => s.score.pp !== undefined); + const rankedScores = getRankedScores(playerId, true); if (!rankedScores) return null; - const rankedScorePps = rankedScores - .map((s) => s.score.pp) - .sort((a, b) => b - a) - .slice(0, limit); + const rankedScorePps = rankedScores.map((s) => s.score.pp).slice(0, limit); return ( rankedScorePps.reduce((cum, pp) => cum + pp, 0) / rankedScorePps.length