diff --git a/src/components/leaderboard/leaderboard-score-stats.tsx b/src/components/leaderboard/leaderboard-score-stats.tsx index 565dd81..38ec25e 100644 --- a/src/components/leaderboard/leaderboard-score-stats.tsx +++ b/src/components/leaderboard/leaderboard-score-stats.tsx @@ -4,16 +4,11 @@ import { formatNumberWithCommas } from "@/common/number-utils"; import StatValue from "@/components/stat-value"; import { XMarkIcon } from "@heroicons/react/24/solid"; import clsx from "clsx"; +import { getScoreBadgeFromAccuracy } from "@/common/song-utils"; +import Tooltip from "@/components/tooltip"; +import { ScoreBadge } from "@/components/score/score-badge"; -type Badge = { - name: string; - create: ( - score: ScoreSaberScoreToken, - leaderboard: ScoreSaberLeaderboardToken - ) => string | React.ReactNode | undefined; -}; - -const badges: Badge[] = [ +const badges: ScoreBadge[] = [ { name: "PP", create: (score: ScoreSaberScoreToken) => { @@ -26,9 +21,35 @@ const badges: Badge[] = [ }, { name: "Accuracy", + color: (score: ScoreSaberScoreToken, leaderboard: ScoreSaberLeaderboardToken) => { + const acc = (score.baseScore / leaderboard.maxScore) * 100; + return getScoreBadgeFromAccuracy(acc).color; + }, create: (score: ScoreSaberScoreToken, leaderboard: ScoreSaberLeaderboardToken) => { const acc = (score.baseScore / leaderboard.maxScore) * 100; - return `${acc.toFixed(2)}%`; + const scoreBadge = getScoreBadgeFromAccuracy(acc); + let accDetails = `Accuracy ${scoreBadge.name != "-" ? scoreBadge.name : ""}`; + if (scoreBadge.max == null) { + accDetails += ` (> ${scoreBadge.min}%)`; + } else if (scoreBadge.min == null) { + accDetails += ` (< ${scoreBadge.max}%)`; + } else { + accDetails += ` (${scoreBadge.min}% - ${scoreBadge.max}%)`; + } + + return ( + <> + +

{accDetails}

+ + } + > +

{acc.toFixed(2)}%

+
+ + ); }, }, { @@ -56,11 +77,11 @@ export default function LeaderboardScoreStats({ score, leaderboard }: Props) {
{badges.map((badge, index) => { const toRender = badge.create(score, leaderboard); + const color = badge.color?.(score, leaderboard); if (toRender === undefined) { return
; } - - return ; + return ; })}
); diff --git a/src/components/score/score-badge.tsx b/src/components/score/score-badge.tsx new file mode 100644 index 0000000..603c916 --- /dev/null +++ b/src/components/score/score-badge.tsx @@ -0,0 +1,14 @@ +import ScoreSaberScoreToken from "@/common/model/token/scoresaber/score-saber-score-token"; +import ScoreSaberLeaderboardToken from "@/common/model/token/scoresaber/score-saber-leaderboard-token"; + +/** + * A badge to display in the score stats. + */ +export type ScoreBadge = { + name: string; + color?: (score: ScoreSaberScoreToken, leaderboard: ScoreSaberLeaderboardToken) => string | undefined; + create: ( + score: ScoreSaberScoreToken, + leaderboard: ScoreSaberLeaderboardToken + ) => string | React.ReactNode | undefined; +}; diff --git a/src/components/score/score-stats.tsx b/src/components/score/score-stats.tsx index 5b77583..863d705 100644 --- a/src/components/score/score-stats.tsx +++ b/src/components/score/score-stats.tsx @@ -6,17 +6,9 @@ import StatValue from "@/components/stat-value"; import { XMarkIcon } from "@heroicons/react/24/solid"; import clsx from "clsx"; import Tooltip from "@/components/tooltip"; +import { ScoreBadge } from "@/components/score/score-badge"; -type Badge = { - name: string; - color?: (score: ScoreSaberScoreToken, leaderboard: ScoreSaberLeaderboardToken) => string | undefined; - create: ( - score: ScoreSaberScoreToken, - leaderboard: ScoreSaberLeaderboardToken - ) => string | React.ReactNode | undefined; -}; - -const badges: Badge[] = [ +const badges: ScoreBadge[] = [ { name: "PP", color: () => {