From ebb7618f2de67f7179092fe64d5273e0be1d1bae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tr=C3=A8sAbhi?= <43380238+tresabhi@users.noreply.github.com> Date: Mon, 25 Mar 2024 18:00:07 -0500 Subject: [PATCH] feat: hero stat --- src/commands/ratingLeaderboard.tsx | 2 +- src/commands/ratingSession.tsx | 207 ++++++++++++++++-- src/commands/research.tsx | 18 +- .../components/HeroStat/components/Glow.tsx | 20 +- .../components/HeroStat/constants.ts | 9 - src/components/DeltaCaret.tsx | 7 +- src/core/blitzkrieg/iconPng.ts | 4 +- src/core/blitzkrieg/tankIconPng.ts | 4 +- src/lang/en-US.json | 4 +- src/stitches.config.ts | 6 + 10 files changed, 238 insertions(+), 43 deletions(-) delete mode 100644 src/components/AllStatsOverview/components/HeroStat/constants.ts diff --git a/src/commands/ratingLeaderboard.tsx b/src/commands/ratingLeaderboard.tsx index b6ba14d40..ad255b73d 100644 --- a/src/commands/ratingLeaderboard.tsx +++ b/src/commands/ratingLeaderboard.tsx @@ -69,7 +69,7 @@ export type RatingReward = { roman_level: string; user_string: string; image_url: string; - preview_url: string; + preview_image_url: string; is_premium: boolean; is_collectible: boolean; }; diff --git a/src/commands/ratingSession.tsx b/src/commands/ratingSession.tsx index 8833da256..aec783a9c 100644 --- a/src/commands/ratingSession.tsx +++ b/src/commands/ratingSession.tsx @@ -1,4 +1,5 @@ import markdownEscape from 'markdown-escape'; +import { Glow } from '../components/AllStatsOverview/components/HeroStat/components/Glow'; import CommandWrapper from '../components/CommandWrapper'; import { DeltaCaret } from '../components/DeltaCaret'; import NoData from '../components/NoData'; @@ -11,6 +12,7 @@ import { getRatingNeighbors } from '../core/blitz/getRatingNeighbors'; import { normalizeLeagueIcon } from '../core/blitz/normalizeLeagueIcon'; import { emblemURL } from '../core/blitzkrieg/emblemURL'; import { getArchivedRatingLeaderboard } from '../core/blitzkrieg/getArchivedRatingLeaderboard'; +import { webpToPng } from '../core/blitzkrieg/iconPng'; import addUsernameChoices from '../core/discord/addUsernameChoices'; import { createLocalizedCommand } from '../core/discord/createLocalizedCommand'; import resolvePlayerFromCommand from '../core/discord/resolvePlayerFromCommand'; @@ -20,6 +22,14 @@ import { BkrlFormat } from '../core/streams/bkrl'; import { CommandRegistry } from '../events/interactionCreate'; import { theme } from '../stitches.config'; +const LEAGUE_ACCENT = [ + '_purple', + '_sand', + '_amber', + '_mauve', + '_brown', +] as const; + export const ratingStatsCommand = new Promise((resolve) => { resolve({ command: @@ -47,7 +57,11 @@ export const ratingStatsCommand = new Promise((resolve) => { const accountInfo = await getAccountInfo(region, id, [ 'statistics.rating', ]); - const statsA = leaderboard.entries.find((entry) => entry.id === id); + const statsIndex = leaderboard.entries.findIndex( + (entry) => entry.id === id, + ); + const statsA = leaderboard.entries[statsIndex]; + const numberA = statsIndex + 1; const statsB1 = accountInfo.statistics.rating!; const [statsB2] = (await getRatingNeighbors(region, id, 0)).neighbors; const league = getLeagueFromScore(statsB2.score); @@ -65,33 +79,59 @@ export const ratingStatsCommand = new Promise((resolve) => { ); } + const reward = ratingInfo.rewards.find( + (reward) => + statsB2.number >= reward.from_position && + statsB2.number <= reward.to_position, + ); + const positionDelta = statsB2.number - numberA; const delta = deltaBkrlBlitzStats( statsA, accountInfo.statistics.rating!, statsB2, ); + const leagueTheme = LEAGUE_ACCENT[league.index]; return ( - {delta.battles === 0 && ( - - )} - {delta.battles > 0 && ( +
+ {reward === undefined && ( + + )} +
((resolve) => { style={{ display: 'flex', alignItems: 'center', - justifyContent: 'center', + justifyContent: 'flex-start', }} > ((resolve) => { )}
- - #{statsB2.number.toLocaleString(interaction.locale)} - + + #{statsB2.number.toLocaleString(interaction.locale)} + + {positionDelta !== 0 && ( + <> + + 0 + ? theme.colors.textLowContrast_green + : theme.colors.textLowContrast_red, + fontSize: 16, + }} + > + {positionDelta.toLocaleString(interaction.locale)} + + + )} +
+ + {reward && ( +
+
+
+ + {reward.type === 'vehicle' + ? reward.vehicle.user_string + : reward.stuff.title} + +
+ +
+ + Reward + {reward.type === 'stuff' ? ` x${reward.count}` : ''} + +
+
+ + +
+ )} + + {reward === undefined && ( + + )} + + {/* separated because fragment middle man invalidates relative parent: https://github.com/vercel/satori/issues/605 */} + {reward && ( + + )} + {reward && ( + + )} + + + {delta.battles === 0 && ( + )}
); diff --git a/src/commands/research.tsx b/src/commands/research.tsx index bc6f215bf..8996d4e16 100644 --- a/src/commands/research.tsx +++ b/src/commands/research.tsx @@ -9,7 +9,7 @@ import resolveTankId from '../core/blitz/resolveTankId'; import { asset } from '../core/blitzkrieg/asset'; import { buildTechTreeLine } from '../core/blitzkrieg/buildTechTreeLine'; import { emblemURL } from '../core/blitzkrieg/emblemURL'; -import { iconPng } from '../core/blitzkrieg/iconPng'; +import { webpToPng } from '../core/blitzkrieg/iconPng'; import { resolveAncestry } from '../core/blitzkrieg/resolveAncestry'; import { tankDefinitions } from '../core/blitzkrieg/tankDefinitions'; import { @@ -276,7 +276,7 @@ export const researchCommand = new Promise((resolve) => { }} > @@ -301,7 +301,7 @@ export const researchCommand = new Promise((resolve) => { }} > @@ -326,7 +326,7 @@ export const researchCommand = new Promise((resolve) => { }} > @@ -452,7 +452,9 @@ export const researchCommand = new Promise((resolve) => { }} > @@ -479,7 +481,7 @@ export const researchCommand = new Promise((resolve) => { }} > ((resolve) => { }} > ((resolve) => { }} > { color: string; direction?: 'default' | 'reverse'; rotation?: number; + startOpacity?: number; + endOpacity?: number; } const width = 16; @@ -10,9 +14,17 @@ export function Glow({ color, direction = 'default', rotation = 0, + style, + startOpacity = 0, + endOpacity = 1, + ...props }: GlowProps) { - const color1 = color; - const color2 = `${color}00`; + const color1 = `${color}${Math.round(endOpacity * 255) + .toString(16) + .padStart(2, '0')}`; + const color2 = `${color}${Math.round(startOpacity * 255) + .toString(16) + .padStart(2, '0')}`; const background = `linear-gradient(${ direction === 'default' ? 0 : 180 }deg, ${color1} 0%, ${color2} 100%)`; @@ -24,7 +36,9 @@ export function Glow({ alignItems: direction === 'default' ? 'flex-end' : 'flex-start', justifyContent: 'center', transform: `rotate(${rotation}deg)`, + ...style, }} + {...props} >
diff --git a/src/components/AllStatsOverview/components/HeroStat/constants.ts b/src/components/AllStatsOverview/components/HeroStat/constants.ts deleted file mode 100644 index 8e1de6207..000000000 --- a/src/components/AllStatsOverview/components/HeroStat/constants.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { amber, brown, purple, sandDark, slate } from '@radix-ui/colors'; - -export const LEAGUE_COLORS = [ - purple.purple9, - sandDark.sand11, - amber.amber10, - slate.slate9, - brown.brown9, -]; diff --git a/src/components/DeltaCaret.tsx b/src/components/DeltaCaret.tsx index 784d7e491..9e2126c25 100644 --- a/src/components/DeltaCaret.tsx +++ b/src/components/DeltaCaret.tsx @@ -5,8 +5,11 @@ interface DeltaCaretProps { export function DeltaCaret({ delta }: DeltaCaretProps) { return ( 0 ? 'https://i.imgur.com/gjI4a5f.png' diff --git a/src/core/blitzkrieg/iconPng.ts b/src/core/blitzkrieg/iconPng.ts index d3e61bb14..d50e522c2 100644 --- a/src/core/blitzkrieg/iconPng.ts +++ b/src/core/blitzkrieg/iconPng.ts @@ -2,7 +2,9 @@ import sharp from 'sharp'; const cache: Record = {}; -export async function iconPng(url: string) { +export async function webpToPng(url: string) { + if (!url.endsWith('.webp')) return url; + if (!cache[url]) { const imageResponse = await fetch(url); const imageBufferWEBP = await imageResponse.arrayBuffer(); diff --git a/src/core/blitzkrieg/tankIconPng.ts b/src/core/blitzkrieg/tankIconPng.ts index 97b076bf9..21b5d3c21 100644 --- a/src/core/blitzkrieg/tankIconPng.ts +++ b/src/core/blitzkrieg/tankIconPng.ts @@ -1,6 +1,6 @@ -import { iconPng } from './iconPng'; +import { webpToPng } from './iconPng'; import { tankIcon } from './tankIcon'; export function tankIconPng(id: number) { - return iconPng(tankIcon(id)); + return webpToPng(tankIcon(id)); } diff --git a/src/lang/en-US.json b/src/lang/en-US.json index 95e6a61fa..0dae68feb 100644 --- a/src/lang/en-US.json +++ b/src/lang/en-US.json @@ -546,12 +546,12 @@ "description": "Rating player's statistics", "body": { - "subtitle": "Today's rating statistics" + "subtitle": "Rating session" }, "errors": { "no_participation": "# %s hasn't played rating\n\nThis player hasn't participated in the rating gamemode this season.", - "unrecorded_stats": "# Statistics unavailable\n\nRatings statistics are currently unavailable. If there is an on-going season, statistics should be available withing 24 hours." + "unrecorded_stats": "# Statistics currently unavailable\n\nWargaming may be currently be facing server downtime. If there is an on-going season, statistics should be available withing 24 hours." } } } diff --git a/src/stitches.config.ts b/src/stitches.config.ts index 7cc88ee13..c94b4892d 100644 --- a/src/stitches.config.ts +++ b/src/stitches.config.ts @@ -2,10 +2,13 @@ import { amberDark, amberDarkA, blueDark, + brownDark, greenDark, + mauveDark, orangeDark, purpleDark, redDark, + sandDark, slate, slateDark, slateDarkA, @@ -30,6 +33,9 @@ export const theme = { ...createColors(tealDark, 'teal'), ...createColors(greenDark, 'green'), ...createColors(redDark, 'red'), + ...createColors(brownDark, 'brown'), + ...createColors(mauveDark, 'mauve'), + ...createColors(sandDark, 'sand'), }, borderStyles: {