add daily, weekly and monthly change to rank, countryRank and pp as a hover
All checks were successful
Deploy Backend / deploy (push) Successful in 2m26s
Deploy Website / deploy (push) Successful in 3m34s

This commit is contained in:
Lee 2024-10-11 19:35:39 +01:00
parent a0681d7b1c
commit ccedfa2645
3 changed files with 74 additions and 27 deletions

@ -158,31 +158,27 @@ export async function getScoreSaberPlayerFromToken(
.sort((a, b) => Date.parse(b[0]) - Date.parse(a[0]))
.reduce((obj, [key, value]) => ({ ...obj, [key]: value }), {});
const yesterdayDate = formatDateMinimal(getMidnightAlignedDate(getDaysAgoDate(1)));
const todayStats = statisticHistory[todayDate];
const yesterdayStats = statisticHistory[yesterdayDate];
const hasChange = !!(todayStats && yesterdayStats);
/**
* Gets the change in the given stat
*
* @param statType the stat to check
* @param daysAgo the amount of days ago to get the stat for
* @return the change
*/
const getChange = (statType: "rank" | "countryRank" | "pp"): number => {
const getChange = (statType: "rank" | "countryRank" | "pp", daysAgo: number = 1): number => {
const todayStats = statisticHistory[todayDate];
const otherDate = formatDateMinimal(getMidnightAlignedDate(getDaysAgoDate(daysAgo)));
const otherStats = statisticHistory[otherDate];
const hasChange = !!(todayStats && otherStats);
if (!hasChange) {
return 0;
}
const statToday = todayStats[`${statType}`];
const statYesterday = yesterdayStats[`${statType}`];
return !!(statToday && statYesterday) ? statToday - statYesterday : 0;
const statOther = otherStats[`${statType}`];
return (!!(statToday && statOther) ? statToday - statOther : 0) * -1;
};
// Calculate the changes
const rankChange = getChange("rank");
const countryRankChange = getChange("countryRank");
const ppChange = getChange("pp");
const getRankPosition = (rank: number): number => {
return Math.floor(rank / 50) + 1;
};
@ -198,9 +194,21 @@ export async function getScoreSaberPlayerFromToken(
bio: bio,
pp: token.pp,
statisticChange: {
rank: rankChange * -1, // Reverse the rank change
countryRank: countryRankChange * -1, // Reverse the country rank change
pp: ppChange,
today: {
rank: getChange("rank", 1),
countryRank: getChange("countryRank", 1),
pp: getChange("pp", 1),
},
weekly: {
rank: getChange("rank", 7),
countryRank: getChange("countryRank", 7),
pp: getChange("pp", 7),
},
monthly: {
rank: getChange("rank", 30),
countryRank: getChange("countryRank", 30),
pp: getChange("pp", 30),
},
},
role: role,
badges: badges,

@ -55,4 +55,8 @@ export default class Player {
}
}
export type StatisticChange = PlayerHistory;
export type StatisticChange = {
today: PlayerHistory;
weekly: PlayerHistory;
monthly: PlayerHistory;
};

@ -18,7 +18,7 @@ import Link from "next/link";
* @param tooltip the tooltip to display
* @param format the function to format the value
*/
const renderChange = (change: number, tooltip: ReactElement, format?: (value: number) => string) => {
const renderDailyChange = (change: number, tooltip: ReactElement, format?: (value: number) => string) => {
format = format ?? formatNumberWithCommas;
return (
@ -31,6 +31,34 @@ const renderChange = (change: number, tooltip: ReactElement, format?: (value: nu
);
};
/**
* Renders the change over time a stat eg: rank, country rank
*
* @param player the player to get the stats for
* @param children the children to render
* @param type the type of stat to get the change for
*/
const renderChange = (player: ScoreSaberPlayer, type: "rank" | "countryRank" | "pp", children: ReactElement) => {
const todayStats = player.statisticChange?.today;
const weeklyStats = player.statisticChange?.weekly;
const monthlyStats = player.statisticChange?.monthly;
return (
<Tooltip
side="bottom"
display={
<div>
<p>Daily Change: {todayStats?.[type] || "Missing Data"}</p>
<p>Weekly Change: {weeklyStats?.[type] || "Missing Data"}</p>
<p>Monthly Change: {monthlyStats?.[type] || "Missing Data"}</p>
</div>
}
>
{children}
</Tooltip>
);
};
const playerData = [
{
showWhenInactiveOrBanned: false,
@ -39,13 +67,15 @@ const playerData = [
},
render: (player: ScoreSaberPlayer) => {
const statisticChange = player.statisticChange;
const rankChange = statisticChange?.rank ?? 0;
const rankChange = statisticChange?.today?.rank ?? 0;
return (
return renderChange(
player,
"rank",
<Link href={`/ranking/${player.rankPages.global}`}>
<div className="text-gray-300 flex gap-1 items-center">
<p className="hover:brightness-75 transition-all transform-gpu">#{formatNumberWithCommas(player.rank)}</p>
{rankChange != 0 && renderChange(rankChange, <p>The change in your rank compared to yesterday</p>)}
{rankChange != 0 && renderDailyChange(rankChange, <p>The change in your rank compared to yesterday</p>)}
</div>
</Link>
);
@ -58,15 +88,18 @@ const playerData = [
},
render: (player: ScoreSaberPlayer) => {
const statisticChange = player.statisticChange;
const rankChange = statisticChange?.countryRank ?? 0;
const rankChange = statisticChange?.today?.countryRank ?? 0;
return (
return renderChange(
player,
"countryRank",
<Link href={`/ranking/${player.country}/${player.rankPages.country}`}>
<div className="text-gray-300 flex gap-1 items-center">
<p className="hover:brightness-75 transition-all transform-gpu">
#{formatNumberWithCommas(player.countryRank)}
</p>
{rankChange != 0 && renderChange(rankChange, <p>The change in your country rank compared to yesterday</p>)}
{rankChange != 0 &&
renderDailyChange(rankChange, <p>The change in your country rank compared to yesterday</p>)}
</div>
</Link>
);
@ -76,13 +109,15 @@ const playerData = [
showWhenInactiveOrBanned: true,
render: (player: ScoreSaberPlayer) => {
const statisticChange = player.statisticChange;
const ppChange = statisticChange?.pp ?? 0;
const ppChange = statisticChange?.today?.pp ?? 0;
return (
return renderChange(
player,
"pp",
<div className="text-pp flex gap-1 items-center">
<p>{formatPp(player.pp)}pp</p>
{ppChange != 0 &&
renderChange(ppChange, <p>The change in your pp compared to yesterday</p>, number => {
renderDailyChange(ppChange, <p>The change in your pp compared to yesterday</p>, number => {
return `${formatPp(number)}pp`;
})}
</div>