From db976c4ae98cace4f5cfb14315fbafde7b2188a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tr=C3=A8sAbhi?= <43380238+tresabhi@users.noreply.github.com> Date: Wed, 11 Oct 2023 20:18:51 -0500 Subject: [PATCH] =?UTF-8?q?feat:=20added=20future=20features=20?= =?UTF-8?q?=F0=9F=91=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/commands/evolution.tsx | 139 +++++++++++++++++- src/core/blitzkrieg/addStatPropertyOptions.ts | 61 ++++++++ src/core/discord/autocompleteClan.ts | 2 - src/core/discord/autocompleteStatProperty.ts | 20 +++ src/core/discord/autocompleteTanks.ts | 2 - src/core/discord/autocompleteUsername.ts | 8 +- src/renderers/evolution.tsx | 120 --------------- 7 files changed, 214 insertions(+), 138 deletions(-) create mode 100644 src/core/blitzkrieg/addStatPropertyOptions.ts create mode 100644 src/core/discord/autocompleteStatProperty.ts delete mode 100644 src/renderers/evolution.tsx diff --git a/src/commands/evolution.tsx b/src/commands/evolution.tsx index 11eab4063..3cebffd36 100644 --- a/src/commands/evolution.tsx +++ b/src/commands/evolution.tsx @@ -2,20 +2,130 @@ import { SlashCommandBuilder } from 'discord.js'; import { WARGAMING_APPLICATION_ID } from '../constants/wargamingApplicationID'; import getWargamingResponse from '../core/blitz/getWargamingResponse'; import resolveTankId from '../core/blitz/resolveTankId'; +import getPlayerHistories from '../core/blitzstars/getPlayerHistories'; +import getTankHistories from '../core/blitzstars/getTankHistories'; import addStatTypeSubCommandGroups from '../core/discord/addStatTypeSubCommandGroups'; -import addUsernameChoices from '../core/discord/addUsernameChoices'; import autocompleteTanks from '../core/discord/autocompleteTanks'; import autocompleteUsername from '../core/discord/autocompleteUsername'; import interactionToURL from '../core/discord/interactionToURL'; import linkButton from '../core/discord/linkButton'; import primaryButton from '../core/discord/primaryButton'; import resolvePeriodFromButton from '../core/discord/resolvePeriodFromButton'; -import resolvePeriodFromCommand from '../core/discord/resolvePeriodFromCommand'; +import resolvePeriodFromCommand, { + ResolvedPeriod, +} from '../core/discord/resolvePeriodFromCommand'; import resolvePlayerFromButton from '../core/discord/resolvePlayerFromButton'; -import resolvePlayerFromCommand from '../core/discord/resolvePlayerFromCommand'; +import resolvePlayerFromCommand, { + ResolvedPlayer, +} from '../core/discord/resolvePlayerFromCommand'; import { CommandRegistryRaw } from '../events/interactionCreate'; -import evolution from '../renderers/evolution'; import { AccountInfo } from '../types/accountInfo'; +import { PlayerClanInfo } from '../types/playerClanData'; + +async function render( + { region, id }: ResolvedPlayer, + { start, end, name }: ResolvedPeriod, + type: 'player' | 'tank', + tankId?: number, +) { + let nameDiscriminator: string | undefined; + let image: string | undefined; + + if (type === 'player') { + const clan = ( + await getWargamingResponse( + `https://api.wotblitz.${region}/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 = `(${await resolveTankName(tankId!)})`; + image = (await tankopedia)[tankId!]?.images.normal; + } + + let histories: Histories; + + if (type === 'player') { + histories = await getPlayerHistories(region, id, { + start, + end, + includeLatestHistories: true, + includePreviousHistories: true, + }); + } else { + histories = await getTankHistories(region, id, { + tankId: tankId!, + start, + end, + includeLatestHistories: true, + includePreviousHistories: true, + }); + } + + const plot = histories.map( + (history) => + [ + history.all.battles, + (history.all.wins / history.all.battles) * 100, + ] as Graph.PlotItem, + ); + const times = histories.map((history) => history.last_battle_time); + const minTime = Math.min(...times); + const maxTime = Math.max(...times); + const ys = plot.map(([, y]) => y); + const xs = plot.map(([x]) => x); + const maxY = Math.max(...ys); + const minY = Math.min(...ys); + const maxX = Math.max(...xs); + const minX = Math.min(...xs); + + const accountInfo = await getWargamingResponse( + `https://api.wotblitz.${region}/wotb/account/info/?application_id=${WARGAMING_APPLICATION_ID}&account_id=${id}`, + ); + + return ( + + + + {/* goofy ahh bug forces me to call them as functions */} + {plot.length > 0 && ( + + {Graph.Line({ + // career winrate + color: Graph.LineColor.Red, + plot: plot, + minY, + maxY, + })} + + )} + + {plot.length === 0 && } + + ); +} export const evolutionCommand = new Promise( async (resolve) => { @@ -23,7 +133,21 @@ export const evolutionCommand = new Promise( new SlashCommandBuilder() .setName('evolution') .setDescription('Evolution of statistics'), - (option) => option.addStringOption(addUsernameChoices), + // (option) => + // option + // .addStringOption((option) => + // addStatPropertyOptions(option) + // .setName('x') + // .setDescription('X axis') + // .setRequired(false), + // ) + // .addStringOption((option) => + // addStatPropertyOptions(option) + // .setName('y') + // .setDescription('Y axis') + // .setRequired(false), + // ) + // .addStringOption(addUsernameChoices), ); resolve({ @@ -56,7 +180,7 @@ export const evolutionCommand = new Promise( }); return [ - await evolution(commandGroup, period, player, tankId), + await render(commandGroup, period, player, tankId), primaryButton(path, 'Refresh'), linkButton( `https://www.blitzstars.com/player/${player.region}/${nickname}${ @@ -70,6 +194,7 @@ export const evolutionCommand = new Promise( autocomplete: (interaction) => { autocompleteUsername(interaction); autocompleteTanks(interaction); + // autocompleteStatProperty(interaction, 'x'); }, async button(interaction) { @@ -79,7 +204,7 @@ export const evolutionCommand = new Promise( const player = await resolvePlayerFromButton(interaction); const period = resolvePeriodFromButton(player.region, interaction); - return await evolution( + return await render( commandGroup, period, player, diff --git a/src/core/blitzkrieg/addStatPropertyOptions.ts b/src/core/blitzkrieg/addStatPropertyOptions.ts new file mode 100644 index 000000000..b8d6dcedb --- /dev/null +++ b/src/core/blitzkrieg/addStatPropertyOptions.ts @@ -0,0 +1,61 @@ +import { SlashCommandStringOption } from 'discord.js'; + +export const STAT_PROPERTIES = [ + { name: 'Time', value: 'time' }, + + { name: 'Battles', value: 'battles' }, + { name: 'Maximum XP', value: 'max_xp' }, + { name: 'Maximum kills', value: 'max_frags' }, + + { name: 'Accumulated spots', value: 'spotted' }, + { name: 'Accumulated hits', value: 'hits' }, + { name: 'Accumulated kills', value: 'frags' }, + { name: 'Accumulated wins', value: 'wins' }, + { name: 'Accumulated losses', value: 'losses' }, + { name: 'Accumulated capture points', value: 'capture_points' }, + { name: 'Accumulated damage dealt', value: 'damage_dealt' }, + { name: 'Accumulated damage received', value: 'damage_received' }, + { name: 'Accumulated shots', value: 'shots' }, + { name: 'Accumulated kills above tier 8', value: 'frags8p' }, + { name: 'Accumulated XP', value: 'xp' }, + { + name: 'Accumulated won and survived battles', + value: 'win_and_survived', + }, + { name: 'Accumulated survived battles', value: 'survived_battles' }, + { + name: 'Accumulated dropped capture points', + value: 'dropped_capture_points', + }, + + { name: 'Average spots', value: 'average_spotted' }, + { name: 'Average hits', value: 'average_hits' }, + { name: 'Average kills', value: 'average_frags' }, + { name: 'Average winrate', value: 'average_wins' }, + { name: 'Average loss rate', value: 'average_losses' }, + { name: 'Average capture points', value: 'average_capture_points' }, + { name: 'Average damage dealt', value: 'average_damage_dealt' }, + { name: 'Average damage received', value: 'average_damage_received' }, + { name: 'Average shots', value: 'average_shots' }, + { name: 'Average kills above tier 8', value: 'average_frags8p' }, + { name: 'Average XP', value: 'average_xp' }, + { + name: 'Average win and survival rate', + value: 'average_win_and_survived', + }, + { name: 'Average survival rate', value: 'average_survived_battles' }, + + { name: 'Average WN8', value: 'average_wn8' }, + { name: 'Average damage ratio', value: 'average_damage_ratio' }, + { + name: 'Average kills to death ratio', + value: 'average_kills_to_death_ratio', + }, +]; + +export function addStatPropertyOptions(option: SlashCommandStringOption) { + return option + .setName('stat-property') + .setDescription('A specific statistical property') + .setAutocomplete(true); +} diff --git a/src/core/discord/autocompleteClan.ts b/src/core/discord/autocompleteClan.ts index c80d0c2c5..1b9cef647 100644 --- a/src/core/discord/autocompleteClan.ts +++ b/src/core/discord/autocompleteClan.ts @@ -25,6 +25,4 @@ export default async function autocompleteClan( ) : [], ); - - console.log(`Clan autocomplete for ${focusedOption.value}`); } diff --git a/src/core/discord/autocompleteStatProperty.ts b/src/core/discord/autocompleteStatProperty.ts new file mode 100644 index 000000000..ff2cec6b1 --- /dev/null +++ b/src/core/discord/autocompleteStatProperty.ts @@ -0,0 +1,20 @@ +import { AutocompleteInteraction, CacheType } from 'discord.js'; +import { go } from 'fuzzysort'; +import { STAT_PROPERTIES } from '../blitzkrieg/addStatPropertyOptions'; + +export default async function autocompleteStatProperty( + interaction: AutocompleteInteraction, + name = 'stat-property', +) { + const focusedOption = interaction.options.getFocused(true); + if (focusedOption.name !== name) return; + + await interaction.respond( + focusedOption.value + ? go(focusedOption.value, STAT_PROPERTIES, { + keys: ['name'], + limit: 10, + }).map(({ obj }) => obj) + : STAT_PROPERTIES.slice(0, 25), + ); +} diff --git a/src/core/discord/autocompleteTanks.ts b/src/core/discord/autocompleteTanks.ts index dabd7d25a..64d953101 100644 --- a/src/core/discord/autocompleteTanks.ts +++ b/src/core/discord/autocompleteTanks.ts @@ -28,6 +28,4 @@ export default async function autocompleteTanks( ) : [], ); - - console.log(`Tanks autocomplete for ${focusedOption.value}`); } diff --git a/src/core/discord/autocompleteUsername.ts b/src/core/discord/autocompleteUsername.ts index f83722c01..753cfe516 100644 --- a/src/core/discord/autocompleteUsername.ts +++ b/src/core/discord/autocompleteUsername.ts @@ -25,11 +25,5 @@ export default async function autocompleteUsername( ) : [], ); - - console.log(`Username autocomplete for ${focusedOption.value}`); - } catch (error) { - console.warn( - `Failed to autocomplete username for ${focusedOption.value} in time`, - ); - } + } catch (error) {} } diff --git a/src/renderers/evolution.tsx b/src/renderers/evolution.tsx deleted file mode 100644 index 2b792e388..000000000 --- a/src/renderers/evolution.tsx +++ /dev/null @@ -1,120 +0,0 @@ -import * as Graph from '../components/Graph'; -import NoData, { NoDataType } from '../components/NoData'; -import TitleBar from '../components/TitleBar'; -import Wrapper from '../components/Wrapper'; -import { WARGAMING_APPLICATION_ID } from '../constants/wargamingApplicationID'; -import getWargamingResponse from '../core/blitz/getWargamingResponse'; -import resolveTankName from '../core/blitz/resolveTankName'; -import { tankopedia } from '../core/blitz/tankopedia'; -import getPlayerHistories from '../core/blitzstars/getPlayerHistories'; -import getTankHistories from '../core/blitzstars/getTankHistories'; -import { ResolvedPeriod } from '../core/discord/resolvePeriodFromCommand'; -import { ResolvedPlayer } from '../core/discord/resolvePlayerFromCommand'; -import { AccountInfo } from '../types/accountInfo'; -import { Histories } from '../types/histories'; -import { PlayerClanInfo } from '../types/playerClanData'; - -export default async function evolution( - type: Type, - { start, end, name }: ResolvedPeriod, - { region: server, id }: ResolvedPlayer, - tankId: Type extends 'tank' ? number : null, -) { - 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 = `(${await resolveTankName(tankId!)})`; - image = (await 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: tankId!, - start, - end, - includeLatestHistories: true, - includePreviousHistories: true, - }); - } - - const plot = histories.map( - (history) => - [ - history.all.battles, - (history.all.wins / history.all.battles) * 100, - ] as Graph.PlotItem, - ); - const times = histories.map((history) => history.last_battle_time); - const minTime = Math.min(...times); - const maxTime = Math.max(...times); - const ys = plot.map(([, y]) => y); - const xs = plot.map(([x]) => x); - const maxY = Math.max(...ys); - const minY = Math.min(...ys); - const maxX = Math.max(...xs); - const minX = Math.min(...xs); - - 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 */} - {plot.length > 0 && ( - - {Graph.Line({ - // career winrate - color: Graph.LineColor.Red, - plot: plot, - minY, - maxY, - })} - - )} - - {plot.length === 0 && } - - ); -}