From afa0cfaeef80c4e8b58d596c70e9a4d894744485 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tr=C3=A8sAbhi?= <43380238+tresabhi@users.noreply.github.com> Date: Sun, 24 Mar 2024 22:06:48 -0500 Subject: [PATCH] feat: start on final design --- docs/guide/bkrl.md | 4 +- package.json | 2 +- src/commands/evolution.tsx | 4 +- src/commands/fullStats.tsx | 4 +- src/commands/ratingSession.tsx | 117 +++++++++++++++--- src/commands/research.tsx | 4 +- src/commands/stats.tsx | 4 +- .../components/HeroStat/index.tsx | 34 ++--- src/components/AllStatsOverview/index.tsx | 22 +--- src/components/CommandWrapper.tsx | 3 +- src/components/DeltaCaret.tsx | 17 +++ src/components/GenericAllStats/index.tsx | 6 - src/components/TitleBar.tsx | 1 + src/core/blitz/getAccountInfo.ts | 13 +- src/core/blitz/normalizeLeagueIcon.ts | 3 + .../{emblemIdToURL.ts => emblemURL.ts} | 2 +- src/core/statistics/deltaBkrlBlitzStats.ts | 27 ++-- src/core/statistics/filterStats.ts | 5 +- src/core/streams/bkrl.ts | 16 +-- src/stitches.config.ts | 4 + yarn.lock | 2 +- 21 files changed, 178 insertions(+), 116 deletions(-) create mode 100644 src/components/DeltaCaret.tsx create mode 100644 src/core/blitz/normalizeLeagueIcon.ts rename src/core/blitzkrieg/{emblemIdToURL.ts => emblemURL.ts} (64%) diff --git a/docs/guide/bkrl.md b/docs/guide/bkrl.md index e66db7018..03c8db8c2 100644 --- a/docs/guide/bkrl.md +++ b/docs/guide/bkrl.md @@ -17,7 +17,7 @@ Header { Format enum { Minimal, - Comprehensive1, + Superset1, } Body
match { @@ -28,7 +28,7 @@ Body
match { }[header.count] entries; }; - Comprehensive1 { + Superset1 { primary { uint32 id; uint16 score; diff --git a/package.json b/package.json index b565eb12f..07bc47704 100644 --- a/package.json +++ b/package.json @@ -65,7 +65,7 @@ "react-fuzzysort": "^1.0.1", "react-promise-suspense": "^0.3.4", "react-spinners": "^0.13.8", - "satori": "^0.10.8", + "satori": "^0.10.13", "sharp": "0.33.1", "three": "0.159.0", "three-stdlib": "^2.29.4", diff --git a/src/commands/evolution.tsx b/src/commands/evolution.tsx index 75233426f..1243551fc 100644 --- a/src/commands/evolution.tsx +++ b/src/commands/evolution.tsx @@ -7,7 +7,7 @@ import TitleBar from '../components/TitleBar'; import { getAccountInfo } from '../core/blitz/getAccountInfo'; import { getClanAccountInfo } from '../core/blitz/getClanAccountInfo'; import resolveTankId from '../core/blitz/resolveTankId'; -import { emblemIdToURL } from '../core/blitzkrieg/emblemIdToURL'; +import { emblemURL } from '../core/blitzkrieg/emblemURL'; import getTankHistories from '../core/blitzkrieg/getTankHistories'; import { getBlitzStarsLinkButton } from '../core/blitzstars/getBlitzStarsLinkButton'; import getPlayerHistories from '../core/blitzstars/getPlayerHistories'; @@ -41,7 +41,7 @@ async function render( ) { const accountInfo = await getAccountInfo(region, id); const clan = (await getClanAccountInfo(region, id, ['clan']))?.clan; - const logo = clan ? emblemIdToURL(clan.emblem_set_id) : undefined; + const logo = clan ? emblemURL(clan.emblem_set_id) : undefined; const histories = await (type === 'player' ? getPlayerHistories(region, id, { start, diff --git a/src/commands/fullStats.tsx b/src/commands/fullStats.tsx index 2463fb113..79e518150 100644 --- a/src/commands/fullStats.tsx +++ b/src/commands/fullStats.tsx @@ -6,7 +6,7 @@ import TierWeights from '../components/TierWeights'; import TitleBar from '../components/TitleBar'; import { getAccountInfo } from '../core/blitz/getAccountInfo'; import { getClanAccountInfo } from '../core/blitz/getClanAccountInfo'; -import { emblemIdToURL } from '../core/blitzkrieg/emblemIdToURL'; +import { emblemURL } from '../core/blitzkrieg/emblemURL'; import { filtersToDescription } from '../core/blitzkrieg/filtersToDescription'; import { getBlitzStarsLinkButton } from '../core/blitzstars/getBlitzStarsLinkButton'; import getStatsInPeriod from '../core/blitzstars/getStatsInPeriod'; @@ -40,7 +40,7 @@ async function render( ) { const { nickname } = await getAccountInfo(region, id); const clan = (await getClanAccountInfo(region, id, ['clan']))?.clan; - const clanImage = clan ? emblemIdToURL(clan.emblem_set_id) : undefined; + const clanImage = clan ? emblemURL(clan.emblem_set_id) : undefined; const diffedTankStats = await getStatsInPeriod( region, id, diff --git a/src/commands/ratingSession.tsx b/src/commands/ratingSession.tsx index c328c17b9..8833da256 100644 --- a/src/commands/ratingSession.tsx +++ b/src/commands/ratingSession.tsx @@ -1,10 +1,15 @@ import markdownEscape from 'markdown-escape'; -import AllStatsOverview from '../components/AllStatsOverview'; import CommandWrapper from '../components/CommandWrapper'; +import { DeltaCaret } from '../components/DeltaCaret'; import NoData from '../components/NoData'; import TitleBar from '../components/TitleBar'; import { getAccountInfo } from '../core/blitz/getAccountInfo'; +import { getClanAccountInfo } from '../core/blitz/getClanAccountInfo'; +import { getLeagueFromScore } from '../core/blitz/getLeagueFromScore'; +import getRatingInfo from '../core/blitz/getRatingInfo'; 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 addUsernameChoices from '../core/discord/addUsernameChoices'; import { createLocalizedCommand } from '../core/discord/createLocalizedCommand'; @@ -13,6 +18,7 @@ import { translator } from '../core/localization/translator'; import { deltaBkrlBlitzStats } from '../core/statistics/deltaBkrlBlitzStats'; import { BkrlFormat } from '../core/streams/bkrl'; import { CommandRegistry } from '../events/interactionCreate'; +import { theme } from '../stitches.config'; export const ratingStatsCommand = new Promise((resolve) => { resolve({ @@ -27,6 +33,8 @@ export const ratingStatsCommand = new Promise((resolve) => { async handler(interaction) { const { t, translate } = translator(interaction.locale); const { id, region } = await resolvePlayerFromCommand(interaction); + const clan = (await getClanAccountInfo(region, id, ['clan']))?.clan; + const clanImage = clan ? emblemURL(clan.emblem_set_id) : undefined; const leaderboard = await getArchivedRatingLeaderboard(region, 53); if (leaderboard.format === BkrlFormat.Minimal) { @@ -35,13 +43,18 @@ export const ratingStatsCommand = new Promise((resolve) => { ); } + const ratingInfo = await getRatingInfo(region); const accountInfo = await getAccountInfo(region, id, [ 'statistics.rating', ]); const statsA = leaderboard.entries.find((entry) => entry.id === id); const statsB1 = accountInfo.statistics.rating!; const [statsB2] = (await getRatingNeighbors(region, id, 0)).neighbors; + const league = getLeagueFromScore(statsB2.score); + if (ratingInfo.detail) { + throw new Error(`Rating info not available for ${region}`); + } if (!statsA) { return t`bot.commands.rating_session.errors.unrecorded_stats`; } @@ -52,13 +65,17 @@ export const ratingStatsCommand = new Promise((resolve) => { ); } - const delta = deltaBkrlBlitzStats(statsA, accountInfo.statistics.rating!); + const delta = deltaBkrlBlitzStats( + statsA, + accountInfo.statistics.rating!, + statsB2, + ); return ( @@ -66,24 +83,84 @@ export const ratingStatsCommand = new Promise((resolve) => { )} {delta.battles > 0 && ( - + > +
+ + +
+
+ + {statsB2.score.toLocaleString(interaction.locale)} + + {delta.score !== 0 && ( + <> + + 0 + ? theme.colors.textLowContrast_green + : theme.colors.textLowContrast_red, + fontSize: 16, + }} + > + {delta.score.toLocaleString(interaction.locale)} + + + )} +
+ + #{statsB2.number.toLocaleString(interaction.locale)} + +
+
+ )}
); diff --git a/src/commands/research.tsx b/src/commands/research.tsx index dfa96519f..bc6f215bf 100644 --- a/src/commands/research.tsx +++ b/src/commands/research.tsx @@ -8,7 +8,7 @@ import getTankStats from '../core/blitz/getTankStats'; import resolveTankId from '../core/blitz/resolveTankId'; import { asset } from '../core/blitzkrieg/asset'; import { buildTechTreeLine } from '../core/blitzkrieg/buildTechTreeLine'; -import { emblemIdToURL } from '../core/blitzkrieg/emblemIdToURL'; +import { emblemURL } from '../core/blitzkrieg/emblemURL'; import { iconPng } from '../core/blitzkrieg/iconPng'; import { resolveAncestry } from '../core/blitzkrieg/resolveAncestry'; import { tankDefinitions } from '../core/blitzkrieg/tankDefinitions'; @@ -155,7 +155,7 @@ export const researchCommand = new Promise((resolve) => { const line = [...techTreeLine, startingTankId].reverse(); const { nickname } = await getAccountInfo(region, id); const clan = (await getClanAccountInfo(region, id, ['clan']))?.clan; - const clanImage = clan ? emblemIdToURL(clan.emblem_set_id) : undefined; + const clanImage = clan ? emblemURL(clan.emblem_set_id) : undefined; const costs = await Promise.all( line.map(async (id) => { const tank = awaitedTankDefinitions[id]; diff --git a/src/commands/stats.tsx b/src/commands/stats.tsx index eb909643e..fcc773e9d 100644 --- a/src/commands/stats.tsx +++ b/src/commands/stats.tsx @@ -5,7 +5,7 @@ import NoData from '../components/NoData'; import TitleBar from '../components/TitleBar'; import { getAccountInfo } from '../core/blitz/getAccountInfo'; import { getClanAccountInfo } from '../core/blitz/getClanAccountInfo'; -import { emblemIdToURL } from '../core/blitzkrieg/emblemIdToURL'; +import { emblemURL } from '../core/blitzkrieg/emblemURL'; import { filtersToDescription } from '../core/blitzkrieg/filtersToDescription'; import { getBlitzStarsLinkButton } from '../core/blitzstars/getBlitzStarsLinkButton'; import getStatsInPeriod from '../core/blitzstars/getStatsInPeriod'; @@ -38,7 +38,7 @@ async function render( ) { const { nickname } = await getAccountInfo(region, id); const clan = (await getClanAccountInfo(region, id, ['clan']))?.clan; - const clanImage = clan ? emblemIdToURL(clan.emblem_set_id) : undefined; + const clanImage = clan ? emblemURL(clan.emblem_set_id) : undefined; const diffedTankStats = await getStatsInPeriod( region, id, diff --git a/src/components/AllStatsOverview/components/HeroStat/index.tsx b/src/components/AllStatsOverview/components/HeroStat/index.tsx index b71b882b5..e16818ad9 100644 --- a/src/components/AllStatsOverview/components/HeroStat/index.tsx +++ b/src/components/AllStatsOverview/components/HeroStat/index.tsx @@ -1,13 +1,11 @@ import { Locale } from 'discord.js'; import { Percentile } from '../../../../constants/percentiles'; import { SupplementaryStats } from '../../../../core/blitz/getAccountInfo'; -import { getLeagueFromScore } from '../../../../core/blitz/getLeagueFromScore'; import { translator } from '../../../../core/localization/translator'; import getWN8Percentile from '../../../../core/statistics/getWN8Percentile'; import { theme } from '../../../../stitches.config'; import { PERCENTILE_COLORS } from '../../../PercentileIndicator/constants'; import { Glow } from './components/Glow'; -import { LEAGUE_COLORS } from './constants'; export interface WN8DisplayProps { stats: SupplementaryStats; @@ -16,24 +14,12 @@ export interface WN8DisplayProps { export function HeroStat({ stats, locale }: WN8DisplayProps) { const { translate } = translator(locale); - let color: string; - let heroStat: string | number; - let subtitle: string | number | undefined; - if (stats.type === 'random') { - const percentile = - stats.WN8 === undefined - ? Percentile.VeryBad - : getWN8Percentile(stats.WN8); - color = PERCENTILE_COLORS[percentile]; - heroStat = stats.WN8 === undefined ? '--' : stats.WN8.toFixed(0); - subtitle = translate(`common.wn8_percentile.${percentile}`); - } else { - heroStat = stats.score; - const league = getLeagueFromScore(stats.score); - color = LEAGUE_COLORS[league.index]; - subtitle = translate(`common.leagues.${league.name}`); - } + const percentile = + stats.WN8 === undefined ? Percentile.VeryBad : getWN8Percentile(stats.WN8); + const color = PERCENTILE_COLORS[percentile]; + const heroStat = stats.WN8 === undefined ? '--' : stats.WN8.toFixed(0); + const subtitle = translate(`common.wn8_percentile.${percentile}`); return (
- {supplementaryStats.type === 'random' && ( - - )} - {supplementaryStats.type === 'rating' && ( - - )} + {children} diff --git a/src/components/DeltaCaret.tsx b/src/components/DeltaCaret.tsx new file mode 100644 index 000000000..784d7e491 --- /dev/null +++ b/src/components/DeltaCaret.tsx @@ -0,0 +1,17 @@ +interface DeltaCaretProps { + delta: number; +} + +export function DeltaCaret({ delta }: DeltaCaretProps) { + return ( + 0 + ? 'https://i.imgur.com/gjI4a5f.png' + : 'https://i.imgur.com/lLGZygN.png' + } + /> + ); +} diff --git a/src/components/GenericAllStats/index.tsx b/src/components/GenericAllStats/index.tsx index f3ff45bb5..2e2ff3bb5 100644 --- a/src/components/GenericAllStats/index.tsx +++ b/src/components/GenericAllStats/index.tsx @@ -23,12 +23,6 @@ export default function GenericAllStats({ const killsToDeathRatio = stats.frags / (stats.battles - stats.survived_battles); - if (supplementaryStats && supplementaryStats.type !== 'random') { - throw new Error( - 'Generic all stats does not support random supplementary stats', - ); - } - return ( diff --git a/src/components/TitleBar.tsx b/src/components/TitleBar.tsx index 861e2116f..abd76060f 100644 --- a/src/components/TitleBar.tsx +++ b/src/components/TitleBar.tsx @@ -15,6 +15,7 @@ export default function TitleBar({ title, image, description }: TitleBarProps) { flexDirection: 'column', justifyContent: 'center', alignItems: 'center', + padding: '8px 0px', }} >
; + battles: b1.battles - a.battles, + damageDealt: b1.damage_dealt - a.damageDealt, + damageReceived: b1.damage_received - a.damageReceived, + hits: b1.hits - a.hits, + kills: b1.frags - a.kills, + shots: b1.shots - a.shots, + survived: b1.survived_battles - a.survived, + wins: b1.wins - a.wins, + score: b2.score - a.score, + } satisfies Omit; } diff --git a/src/core/statistics/filterStats.ts b/src/core/statistics/filterStats.ts index 4da925a2c..3ca1e47a6 100644 --- a/src/core/statistics/filterStats.ts +++ b/src/core/statistics/filterStats.ts @@ -1,5 +1,5 @@ import { TreeType } from '../../components/Tanks'; -import { SupplementaryStatsRandom } from '../blitz/getAccountInfo'; +import { SupplementaryStats } from '../blitz/getAccountInfo'; import { tankDefinitions } from '../blitzkrieg/tankDefinitions'; import { DiffedTankStats } from '../blitzstars/getStatsInPeriod'; import { tankAverages } from '../blitzstars/tankAverages'; @@ -51,7 +51,6 @@ export async function filterStats( 0, ); const supplementary = { - type: 'random', WN8: filteredOrder.reduce( (accumulator, id) => @@ -70,7 +69,7 @@ export async function filterStats( : accumulator, 0, ) / battlesOfTanksWithTankDefinition, - } satisfies SupplementaryStatsRandom; + } satisfies SupplementaryStats; return { stats, supplementary, filteredOrder }; } diff --git a/src/core/streams/bkrl.ts b/src/core/streams/bkrl.ts index 79b9e2706..6af5a7027 100644 --- a/src/core/streams/bkrl.ts +++ b/src/core/streams/bkrl.ts @@ -3,7 +3,7 @@ import { ReadStream, WriteStream } from './buffer'; export enum BkrlFormat { Minimal, - Comprehensive1, + Superset1, } export interface BkrlMinimalEntry { @@ -11,7 +11,7 @@ export interface BkrlMinimalEntry { score: number; } -export interface BkrlComprehensive1Entry { +export interface BkrlSuperset1Entry { id: number; score: number; @@ -34,8 +34,8 @@ export type BkrlDiscriminatedEntries = entries: BkrlMinimalEntry[]; } | { - format: BkrlFormat.Comprehensive1; - entries: BkrlComprehensive1Entry[]; + format: BkrlFormat.Superset1; + entries: BkrlSuperset1Entry[]; }; export class BkrlReadStream extends ReadStream { @@ -61,9 +61,9 @@ export class BkrlReadStream extends ReadStream { }; } - case BkrlFormat.Comprehensive1: { + case BkrlFormat.Superset1: { return { - format: BkrlFormat.Comprehensive1, + format: BkrlFormat.Superset1, entries: times( header.count, () => @@ -82,7 +82,7 @@ export class BkrlReadStream extends ReadStream { hits: this.uint32(), kills: this.uint32(), - }) satisfies BkrlComprehensive1Entry, + }) satisfies BkrlSuperset1Entry, ), }; } @@ -123,7 +123,7 @@ export class BkrlWriteStream extends WriteStream { break; } - case BkrlFormat.Comprehensive1: { + case BkrlFormat.Superset1: { discriminatedEntries.entries.forEach((entry) => { this.uint32(entry.id); this.uint16(entry.score); diff --git a/src/stitches.config.ts b/src/stitches.config.ts index 5e769f749..7cc88ee13 100644 --- a/src/stitches.config.ts +++ b/src/stitches.config.ts @@ -2,8 +2,10 @@ import { amberDark, amberDarkA, blueDark, + greenDark, orangeDark, purpleDark, + redDark, slate, slateDark, slateDarkA, @@ -26,6 +28,8 @@ export const theme = { ...createColors(purpleDark, 'purple'), ...createColors(blueDark, 'blue'), ...createColors(tealDark, 'teal'), + ...createColors(greenDark, 'green'), + ...createColors(redDark, 'red'), }, borderStyles: { diff --git a/yarn.lock b/yarn.lock index 4b7608193..7702a9bf4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4984,7 +4984,7 @@ safe-buffer@~5.1.0, safe-buffer@~5.1.1: resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== -satori@^0.10.8: +satori@^0.10.13: version "0.10.13" resolved "https://registry.yarnpkg.com/satori/-/satori-0.10.13.tgz#658a9920f55268d2002819387a80a0b6d4bdc262" integrity sha512-klCwkVYMQ/ZN5inJLHzrUmGwoRfsdP7idB5hfpJ1jfiJk1ErDitK8Hkc6Kll1+Ox2WtqEuGecSZLnmup3CGzvQ==