add rank and country rank change stats
All checks were successful
Deploy / deploy (push) Successful in 2m36s

This commit is contained in:
Lee 2024-09-28 12:48:14 +01:00
parent 27d2a70198
commit 11a8ee56cc
3 changed files with 96 additions and 23 deletions

View File

@ -1,4 +1,4 @@
import Player from "../player";
import Player, { StatisticChange } from "../player";
import ScoreSaberPlayerToken from "@/common/model/token/scoresaber/score-saber-player-token";
import { PlayerHistory } from "@/common/player/player-history";
import { config } from "../../../../../config";
@ -26,7 +26,7 @@ export default interface ScoreSaberPlayer extends Player {
/**
* The change in pp compared to yesterday.
*/
ppChange: number;
statisticChange: StatisticChange | undefined;
/**
* The role the player has.
@ -129,12 +129,27 @@ export async function getScoreSaberPlayerFromToken(
);
const todayStats = statisticHistory[todayDate];
const yesterdayStats = statisticHistory[yesterdayDate];
const hasChange = !!(todayStats && yesterdayStats);
// Calculate the pp change
const ppChange =
todayStats && yesterdayStats && todayStats.pp && yesterdayStats.pp
? todayStats.pp - yesterdayStats.pp
: 0;
/**
* Gets the change in the given stat
*
* @param statType the stat to check
* @return the change
*/
const getChange = (statType: "rank" | "countryRank" | "pp"): number => {
if (!hasChange) {
return 0;
}
const statToday = todayStats[`${statType}`];
const statYesterday = yesterdayStats[`${statType}`];
return !!(statToday && statYesterday) ? statToday - statYesterday : 0;
};
// Calculate the changes
const rankChange = getChange("rank");
const countryRankChange = getChange("countryRank");
const ppChange = getChange("pp");
return {
id: token.id,
@ -146,7 +161,11 @@ export async function getScoreSaberPlayerFromToken(
joinedDate: new Date(token.firstSeen),
bio: bio,
pp: token.pp,
ppChange: ppChange,
statisticChange: {
rank: rankChange * -1, // Reverse the rank change
countryRank: countryRankChange * -1, // Reverse the country rank change
pp: ppChange,
},
role: role,
badges: badges,
statisticHistory: statisticHistory,

View File

@ -1,3 +1,5 @@
import { PlayerHistory } from "@/common/player/player-history";
export default class Player {
/**
* The ID of this player.
@ -41,7 +43,7 @@ export default class Player {
country: string,
rank: number,
countryRank: number,
joinedDate: Date
joinedDate: Date,
) {
this.id = id;
this.name = name;
@ -52,3 +54,5 @@ export default class Player {
this.joinedDate = joinedDate;
}
}
export type StatisticChange = PlayerHistory;

View File

@ -7,6 +7,33 @@ import ClaimProfile from "./claim-profile";
import PlayerStats from "./player-stats";
import ScoreSaberPlayer from "@/common/model/player/impl/scoresaber-player";
import Tooltip from "@/components/tooltip";
import { ReactElement } from "react";
/**
* Renders the change for a stat.
*
* @param change the amount of change
* @param tooltip the tooltip to display
* @param format the function to format the value
*/
const renderChange = (
change: number,
tooltip: ReactElement,
format?: (value: number) => string,
) => {
format = format ?? formatNumberWithCommas;
return (
<Tooltip display={tooltip}>
<p
className={`text-sm ${change > 0 ? "text-green-400" : "text-red-400"}`}
>
{change > 0 ? "+" : ""}
{format(change)}
</p>
</Tooltip>
);
};
const playerData = [
{
@ -15,7 +42,19 @@ const playerData = [
return <GlobeAmericasIcon className="h-5 w-5" />;
},
render: (player: ScoreSaberPlayer) => {
return <p>#{formatNumberWithCommas(player.rank)}</p>;
const statisticChange = player.statisticChange;
const rankChange = statisticChange?.rank ?? 0;
return (
<div className="text-gray-300 flex gap-1 items-center">
<p>#{formatNumberWithCommas(player.rank)}</p>
{rankChange != 0 &&
renderChange(
rankChange,
<p>The change in your rank compared to yesterday</p>,
)}
</div>
);
},
},
{
@ -24,27 +63,38 @@ const playerData = [
return <CountryFlag code={player.country} size={15} />;
},
render: (player: ScoreSaberPlayer) => {
return <p>#{formatNumberWithCommas(player.countryRank)}</p>;
const statisticChange = player.statisticChange;
const rankChange = statisticChange?.countryRank ?? 0;
return (
<div className="text-gray-300 flex gap-1 items-center">
<p>#{formatNumberWithCommas(player.countryRank)}</p>
{rankChange != 0 &&
renderChange(
rankChange,
<p>The change in your rank compared to yesterday</p>,
)}
</div>
);
},
},
{
showWhenInactiveOrBanned: true,
render: (player: ScoreSaberPlayer) => {
const statisticChange = player.statisticChange;
const ppChange = statisticChange?.pp ?? 0;
return (
<div className="text-pp flex gap-1 items-center">
<p>{formatPp(player.pp)}pp</p>
{player.ppChange != 0 && (
<Tooltip
display={<p>The change in your pp compared to yesterday</p>}
>
<p
className={`text-sm ${player.ppChange > 0 ? "text-green-400" : "text-red-400"}`}
>
{player.ppChange > 0 ? "+" : ""}
{formatPp(player.ppChange)}pp
</p>
</Tooltip>
)}
{ppChange != 0 &&
renderChange(
ppChange,
<p>The change in your pp compared to yesterday</p>,
(number) => {
return `${formatPp(number)}pp`;
},
)}
</div>
);
},