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

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

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

@ -7,6 +7,33 @@ import ClaimProfile from "./claim-profile";
import PlayerStats from "./player-stats"; import PlayerStats from "./player-stats";
import ScoreSaberPlayer from "@/common/model/player/impl/scoresaber-player"; import ScoreSaberPlayer from "@/common/model/player/impl/scoresaber-player";
import Tooltip from "@/components/tooltip"; 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 = [ const playerData = [
{ {
@ -15,7 +42,19 @@ const playerData = [
return <GlobeAmericasIcon className="h-5 w-5" />; return <GlobeAmericasIcon className="h-5 w-5" />;
}, },
render: (player: ScoreSaberPlayer) => { 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} />; return <CountryFlag code={player.country} size={15} />;
}, },
render: (player: ScoreSaberPlayer) => { 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, showWhenInactiveOrBanned: true,
render: (player: ScoreSaberPlayer) => { render: (player: ScoreSaberPlayer) => {
const statisticChange = player.statisticChange;
const ppChange = statisticChange?.pp ?? 0;
return ( return (
<div className="text-pp flex gap-1 items-center"> <div className="text-pp flex gap-1 items-center">
<p>{formatPp(player.pp)}pp</p> <p>{formatPp(player.pp)}pp</p>
{player.ppChange != 0 && ( {ppChange != 0 &&
<Tooltip renderChange(
display={<p>The change in your pp compared to yesterday</p>} ppChange,
> <p>The change in your pp compared to yesterday</p>,
<p (number) => {
className={`text-sm ${player.ppChange > 0 ? "text-green-400" : "text-red-400"}`} return `${formatPp(number)}pp`;
> },
{player.ppChange > 0 ? "+" : ""} )}
{formatPp(player.ppChange)}pp
</p>
</Tooltip>
)}
</div> </div>
); );
}, },