diff --git a/src/commands/evolution.tsx b/src/commands/evolution.tsx index 8abf4b152..a6843aecd 100644 --- a/src/commands/evolution.tsx +++ b/src/commands/evolution.tsx @@ -1,35 +1,17 @@ -import { ButtonBuilder, ButtonStyle, SlashCommandBuilder } from 'discord.js'; -import * as Graph from '../components/Graph/index.js'; -import NoData, { NoDataType } from '../components/NoData.js'; -import PoweredByBlitzStars from '../components/PoweredByBlitzStars.js'; -import TitleBar from '../components/TitleBar.js'; -import Wrapper from '../components/Wrapper.js'; -import { BLITZ_SERVERS } from '../constants/servers.js'; +import { SlashCommandBuilder } from 'discord.js'; import tanksAutocomplete from '../core/autocomplete/tanks.js'; import usernameAutocomplete from '../core/autocomplete/username.js'; -import getWargamingResponse from '../core/blitz/getWargamingResponse.js'; import resolveTankId from '../core/blitz/resolveTankId.js'; -import resolveTankName from '../core/blitz/resolveTankName.js'; -import { tankopedia } from '../core/blitz/tankopedia.js'; -import getPlayerHistories from '../core/blitzstars/getPlayerHistories.js'; -import getTankHistories from '../core/blitzstars/getTankHistories.js'; -import { supportBlitzStars } from '../core/interaction/supportBlitzStars.js'; -import { - Period, - RELATIVE_PERIOD_NAMES, -} from '../core/options/addPeriodSubCommands.js'; import addStatsSubCommandGroups from '../core/options/addStatsSubCommandGroups.js'; import resolvePeriod from '../core/options/resolvePeriod.js'; import resolvePlayer from '../core/options/resolvePlayer.js'; -import { WARGAMING_APPLICATION_ID } from '../core/process/args.js'; import { CommandRegistry } from '../events/interactionCreate.js'; -import { AccountInfo } from '../types/accountInfo.js'; -import { Histories } from '../types/histories.js'; -import { PlayerClanData } from '../types/playerClanData.js'; +import evolution from '../renderers/evolution.js'; +import { StatType } from '../renderers/stats.js'; export default { inProduction: true, - inDevelopment: false, + inDevelopment: true, inPublic: true, command: addStatsSubCommandGroups( @@ -39,136 +21,26 @@ export default { ), async execute(interaction) { - const commandGroup = interaction.options.getSubcommandGroup()!; - const { id, server } = await resolvePlayer(interaction); - let nameDiscriminator: string | undefined; - let image: string | undefined; + const commandGroup = interaction.options.getSubcommandGroup( + true, + ) as StatType; + const player = await resolvePlayer(interaction); + const period = resolvePeriod(interaction); const tankIdRaw = interaction.options.getString('tank')!; - let tankId: number; + const tankId = commandGroup === 'tank' ? resolveTankId(tankIdRaw) : 0; - if (commandGroup === 'player') { - const clan = ( - await getWargamingResponse( - `https://api.wotblitz.${server}/wotb/clans/accountinfo/?application_id=${WARGAMING_APPLICATION_ID}&account_id=${id}&extra=clan`, - ) - )[id]?.clan; + return await evolution(commandGroup, period, player, tankId); - if (clan) nameDiscriminator = `[${clan.tag}]`; - image = clan - ? `https://wotblitz-gc.gcdn.co/icons/clanEmblems1x/clan-icon-v2-${clan.emblem_set_id}.png` - : undefined; - } else if (commandGroup === 'tank') { - tankId = resolveTankId(tankIdRaw); - nameDiscriminator = `(${resolveTankName(tankId)})`; - image = tankopedia[tankId].images.normal; - } - - let histories: Histories; - - const { evolutionName, start, end } = resolvePeriod(interaction); - - if (commandGroup === 'player') { - histories = await getPlayerHistories(server, id, { - start, - end, - includeLatestHistories: true, - includePreviousHistories: true, - }); - } else { - const tankId = resolveTankId(tankIdRaw); - histories = await getTankHistories(server, id, { - tankId, - start, - end, - includeLatestHistories: true, - includePreviousHistories: true, - }); - } - - const careerWinrate = histories.map( - (history) => - [ - history.last_battle_time, - (history.all.wins / history.all.battles) * 100, - ] as Graph.PlotItem, - ); - const careerBattles = histories.map( - (history) => - [history.last_battle_time, history.all.battles] as Graph.PlotItem, - ); - const winrateYs = careerWinrate.map(([, y]) => y); - const maxWinrate = Math.max(...winrateYs); - const minWinrate = Math.min(...winrateYs); - const battleYs = careerBattles.map(([, y]) => y); - const maxBattle = Math.max(...battleYs); - const minBattle = Math.min(...battleYs); - - const accountInfo = await getWargamingResponse( - `https://api.wotblitz.${server}/wotb/account/info/?application_id=${WARGAMING_APPLICATION_ID}&account_id=${id}`, - ); - - return [ - - - - {/* goofy ahh bug forces me to call them as functions */} - {careerWinrate.length > 0 && ( - - {Graph.Line({ - // total battles - plot: careerBattles!, - color: Graph.LineColor.Blue, - })} - {Graph.Line({ - // career winrate - plot: careerWinrate!, - minY: minWinrate, - maxY: maxWinrate, - })} - - )} - - {careerWinrate.length === 0 && ( - - )} - - - , - new ButtonBuilder() - .setStyle(ButtonStyle.Link) - .setLabel('View on BlitzStars') - .setURL( - commandGroup === 'tank' - ? `https://www.blitzstars.com/player/com/${ - accountInfo[id].nickname - }/tank/${tankId!}` - : `https://www.blitzstars.com/player/com/${accountInfo[id].nickname}`, - ), - supportBlitzStars, - ]; + // new ButtonBuilder() + // .setStyle(ButtonStyle.Link) + // .setLabel('View on BlitzStars') + // .setURL( + // commandGroup === 'tank' + // ? `https://www.blitzstars.com/player/com/${ + // accountInfo[id].nickname + // }/tank/${tankId!}` + // : `https://www.blitzstars.com/player/com/${accountInfo[id].nickname}`, + // ); }, autocomplete: (interaction) => { diff --git a/src/core/blitzstars/getPlayerHistories.ts b/src/core/blitzstars/getPlayerHistories.ts index 3d2e0ed2e..d52cfd151 100644 --- a/src/core/blitzstars/getPlayerHistories.ts +++ b/src/core/blitzstars/getPlayerHistories.ts @@ -88,5 +88,5 @@ export default async function getPlayerHistories( } } - return [...previousNodes, ...filtered, ...latestNodes] satisfies Histories; + return [...latestNodes, ...filtered, ...previousNodes] satisfies Histories; } diff --git a/src/core/options/resolvePeriod.ts b/src/core/options/resolvePeriod.ts index 793d5e86f..c1fab0745 100644 --- a/src/core/options/resolvePeriod.ts +++ b/src/core/options/resolvePeriod.ts @@ -2,7 +2,7 @@ import { CacheType, ChatInputCommandInteraction } from 'discord.js'; import getPeriodNow from '../blitzstars/getPeriodNow.js'; import getPeriodStart from '../blitzstars/getPeriodStart.js'; import getTimeDaysAgo from '../blitzstars/getTimeDaysAgo.js'; -import { Period } from './addPeriodSubCommands.js'; +import { Period, RELATIVE_PERIOD_NAMES } from './addPeriodSubCommands.js'; export const PERIOD_NAMES: Record = { today: "Today's statistics", @@ -23,6 +23,7 @@ export const EVOLUTION_PERIOD_NAMES: Record = { }; export interface ResolvedPeriod { + relativePeriodName: string; statsName: string; evolutionName: string; start: number; @@ -37,6 +38,8 @@ export default function resolvePeriod( let evolutionName: string; let start: number; let end: number; + const relativePeriodName = + RELATIVE_PERIOD_NAMES[interaction.options.getSubcommand() as Period]; if (period === 'custom') { const startRaw = interaction.options.getInteger('start')!; @@ -55,5 +58,11 @@ export default function resolvePeriod( end = getPeriodNow(); } - return { statsName, evolutionName, start, end } satisfies ResolvedPeriod; + return { + statsName, + evolutionName, + start, + end, + relativePeriodName, + } satisfies ResolvedPeriod; } diff --git a/src/renderers/evolution.tsx b/src/renderers/evolution.tsx new file mode 100644 index 000000000..f6e8a9ac7 --- /dev/null +++ b/src/renderers/evolution.tsx @@ -0,0 +1,133 @@ +import * as Graph from '../components/Graph/index.js'; +import NoData, { NoDataType } from '../components/NoData.js'; +import PoweredByBlitzStars from '../components/PoweredByBlitzStars.js'; +import TitleBar from '../components/TitleBar.js'; +import Wrapper from '../components/Wrapper.js'; +import { BLITZ_SERVERS } from '../constants/servers.js'; +import getWargamingResponse from '../core/blitz/getWargamingResponse.js'; +import resolveTankName from '../core/blitz/resolveTankName.js'; +import { tankopedia } from '../core/blitz/tankopedia.js'; +import getPlayerHistories from '../core/blitzstars/getPlayerHistories.js'; +import getTankHistories from '../core/blitzstars/getTankHistories.js'; +import { ResolvedPeriod } from '../core/options/resolvePeriod.js'; +import { ResolvedPlayer } from '../core/options/resolvePlayer.js'; +import { WARGAMING_APPLICATION_ID } from '../core/process/args.js'; +import { AccountInfo } from '../types/accountInfo.js'; +import { Histories } from '../types/histories.js'; +import { PlayerClanData } from '../types/playerClanData.js'; +import { StatType } from './stats.js'; + +export default async function evolution( + type: Type, + { start, end, evolutionName, relativePeriodName }: ResolvedPeriod, + { server, id }: ResolvedPlayer, + tankId: Type extends 'tank' ? number : never, +) { + let nameDiscriminator: string | undefined; + let image: string | undefined; + + if (type === 'player') { + const clan = ( + await getWargamingResponse( + `https://api.wotblitz.${server}/wotb/clans/accountinfo/?application_id=${WARGAMING_APPLICATION_ID}&account_id=${id}&extra=clan`, + ) + )[id]?.clan; + + if (clan) nameDiscriminator = `[${clan.tag}]`; + image = clan + ? `https://wotblitz-gc.gcdn.co/icons/clanEmblems1x/clan-icon-v2-${clan.emblem_set_id}.png` + : undefined; + } else { + nameDiscriminator = `(${resolveTankName(tankId)})`; + image = tankopedia[tankId].images.normal; + } + + let histories: Histories; + + if (type === 'player') { + histories = await getPlayerHistories(server, id, { + start, + end, + includeLatestHistories: true, + includePreviousHistories: true, + }); + } else { + histories = await getTankHistories(server, id, { + tankId, + start, + end, + includeLatestHistories: true, + includePreviousHistories: true, + }); + } + + const careerWinrate = histories.map( + (history) => + [ + history.last_battle_time, + (history.all.wins / history.all.battles) * 100, + ] as Graph.PlotItem, + ); + const careerBattles = histories.map( + (history) => + [history.last_battle_time, history.all.battles] as Graph.PlotItem, + ); + const winrateYs = careerWinrate.map(([, y]) => y); + const maxWinrate = Math.max(...winrateYs); + const minWinrate = Math.min(...winrateYs); + const battleYs = careerBattles.map(([, y]) => y); + const maxBattle = Math.max(...battleYs); + const minBattle = Math.min(...battleYs); + + const accountInfo = await getWargamingResponse( + `https://api.wotblitz.${server}/wotb/account/info/?application_id=${WARGAMING_APPLICATION_ID}&account_id=${id}`, + ); + + return ( + + + + {/* goofy ahh bug forces me to call them as functions */} + {careerWinrate.length > 0 && ( + + {Graph.Line({ + // total battles + plot: careerBattles!, + color: Graph.LineColor.Blue, + })} + {Graph.Line({ + // career winrate + plot: careerWinrate!, + minY: minWinrate, + maxY: maxWinrate, + })} + + )} + + {careerWinrate.length === 0 && ( + + )} + + + + ); +}