Files
blitzkit/src/commands/stats.tsx
T

178 lines
6.2 KiB
TypeScript
Raw Normal View History

2023-05-27 18:15:02 +00:00
import {
ActionRowBuilder,
ButtonBuilder,
SlashCommandBuilder,
} from 'discord.js';
2023-06-01 18:36:39 +00:00
import GenericAllStats from '../components/GenericAllStats.js';
2023-06-06 01:31:16 +00:00
import NoData, { NoDataType } from '../components/NoData.js';
2023-05-25 18:20:51 +00:00
import PoweredByBlitzStars from '../components/PoweredByBlitzStars.js';
2023-05-24 02:01:22 +00:00
import TitleBar from '../components/TitleBar.js';
import Wrapper from '../components/Wrapper.js';
import { BLITZ_SERVERS } from '../constants/servers.js';
2023-05-14 17:13:42 +00:00
import usernameAutocomplete from '../core/autocomplete/username.js';
2023-05-16 02:02:50 +00:00
import getBlitzAccount from '../core/blitz/getBlitzAccount.js';
import getTankStats from '../core/blitz/getTankStats.js';
2023-06-01 18:36:39 +00:00
import getWN8 from '../core/blitz/getWN8.js';
2023-05-13 22:01:58 +00:00
import getWargamingResponse from '../core/blitz/getWargamingResponse.js';
2023-05-29 18:15:03 +00:00
import sumStats from '../core/blitz/sumStats.js';
2023-06-01 18:36:39 +00:00
import { tankopedia } from '../core/blitz/tankopedia.js';
2023-05-30 17:24:24 +00:00
import getPeriodNow from '../core/blitzstars/getPeriodNow.js';
import getPeriodicStart from '../core/blitzstars/getPeriodStart.js';
2023-05-29 18:15:03 +00:00
import getTankStatsOverTime from '../core/blitzstars/getTankStatsOverTime.js';
2023-06-02 01:31:14 +00:00
import { tankAverages } from '../core/blitzstars/tankAverages.js';
2023-05-13 22:01:58 +00:00
import cmdName from '../core/interaction/cmdName.js';
2023-05-30 18:42:34 +00:00
import fullBlitzStarsStats from '../core/interaction/fullBlitzStarsStats.js';
import { supportBlitzStars } from '../core/interaction/supportBlitzStars.js';
2023-05-30 17:24:24 +00:00
import addStatPeriodChoices, {
StatPeriod,
statPeriodNames,
} from '../core/options/addStatPeriodChoices.js';
2023-05-14 17:13:42 +00:00
import addUsernameOption from '../core/options/addUsernameOption.js';
2023-06-12 01:17:26 +00:00
import { WARGAMING_APPLICATION_ID } from '../core/process/args.js';
2023-05-28 02:25:59 +00:00
import render from '../core/ui/render.js';
2023-05-19 23:50:24 +00:00
import { CommandRegistry } from '../events/interactionCreate.js';
2023-06-01 18:36:39 +00:00
import {
AccountInfo,
AllStats,
SupplementaryStats,
} from '../types/accountInfo.js';
2023-05-24 02:01:22 +00:00
import { PlayerClanData } from '../types/playerClanData.js';
2023-04-21 23:45:13 +00:00
2023-04-26 00:02:10 +00:00
export default {
inProduction: true,
2023-06-06 16:53:13 +00:00
inDevelopment: false,
2023-04-26 00:02:10 +00:00
inPublic: true,
2023-04-22 01:18:07 +00:00
2023-04-26 00:02:10 +00:00
command: new SlashCommandBuilder()
2023-05-13 01:27:12 +00:00
.setName(cmdName('stats'))
2023-04-26 00:02:10 +00:00
.setDescription("Gets the user's in-game statistics")
2023-05-30 17:24:24 +00:00
.addStringOption(addStatPeriodChoices)
2023-05-14 17:13:42 +00:00
.addStringOption(addUsernameOption),
2023-04-22 01:18:07 +00:00
2023-05-08 01:03:05 +00:00
async execute(interaction) {
2023-05-29 17:44:32 +00:00
const period = interaction.options.getString('period') as StatPeriod;
2023-06-04 00:01:10 +00:00
const { id, server } = await getBlitzAccount(interaction);
2023-05-13 01:27:12 +00:00
const accountInfo = await getWargamingResponse<AccountInfo>(
2023-06-12 01:17:26 +00:00
`https://api.wotblitz.${server}/wotb/account/info/?application_id=${WARGAMING_APPLICATION_ID}&account_id=${id}`,
2023-05-13 01:27:12 +00:00
);
2023-05-24 02:01:22 +00:00
const clanData = await getWargamingResponse<PlayerClanData>(
2023-06-12 01:17:26 +00:00
`https://api.wotblitz.${server}/wotb/clans/accountinfo/?application_id=${WARGAMING_APPLICATION_ID}&account_id=${id}&extra=clan`,
2023-05-24 02:01:22 +00:00
);
const tankStats = await getTankStats(interaction, server, id);
2023-05-29 18:15:03 +00:00
let stats: AllStats;
2023-06-01 18:36:39 +00:00
let supplementaryStats: SupplementaryStats | undefined;
let hasWN8AccumulatedAtAll = false;
2023-04-26 00:02:10 +00:00
2023-05-29 18:15:03 +00:00
if (period === 'career') {
stats = accountInfo[id].statistics.all;
const totalBattles = tankStats.reduce(
(accumulator, { all }) => accumulator + all.battles,
0,
);
supplementaryStats = {
tier:
tankStats.reduce(
(accumulator, { tank_id, all }) =>
accumulator + tankopedia[tank_id].tier * all.battles,
0,
) / totalBattles,
WN8:
tankStats.reduce((accumulator, { tank_id, all }) => {
if (tankAverages[tank_id]) {
const tankWN8 = getWN8(tankAverages[tank_id].all, all);
if (isNaN(tankWN8)) return accumulator;
hasWN8AccumulatedAtAll = true;
return accumulator + tankWN8 * all.battles;
} else return accumulator;
}, 0) / totalBattles,
};
2023-05-08 01:45:57 +00:00
} else {
2023-06-01 18:36:39 +00:00
const tankStatsOverTime = await getTankStatsOverTime(
interaction,
2023-06-01 18:36:39 +00:00
server,
id,
getPeriodicStart(period),
getPeriodNow(),
2023-05-29 18:15:03 +00:00
);
2023-06-01 18:36:39 +00:00
const entries = Object.entries(tankStatsOverTime);
const totalBattles = entries.reduce(
(accumulator, [, stats]) => accumulator + stats.battles,
0,
);
supplementaryStats = {
tier:
entries.reduce((accumulator, [tankIdString, stats]) => {
const tankId = parseInt(tankIdString);
2023-06-01 18:36:39 +00:00
const tankTier = tankopedia[tankId].tier;
return accumulator + tankTier * stats.battles;
}, 0) / totalBattles,
2023-06-01 19:16:29 +00:00
WN8:
2023-06-01 18:36:39 +00:00
entries.reduce((accumulator, [tankIdString, stats]) => {
const tankId = parseInt(tankIdString);
2023-06-01 18:36:39 +00:00
// edge case where new tanks don't have averages
if (tankAverages[tankId]) {
const tankWN8 = getWN8(tankAverages[tankId].all, stats);
if (isNaN(tankWN8)) return accumulator;
hasWN8AccumulatedAtAll = true;
return accumulator + tankWN8 * stats.battles;
} else return accumulator;
2023-06-01 18:36:39 +00:00
}, 0) / totalBattles,
};
stats = sumStats(entries.map(([, stats]) => stats));
2023-05-08 01:45:57 +00:00
}
if (!hasWN8AccumulatedAtAll) supplementaryStats.WN8 = undefined;
2023-05-28 02:25:59 +00:00
const image = await render(
<Wrapper>
<TitleBar
2023-05-29 18:15:03 +00:00
name={accountInfo[id].nickname}
2023-05-28 02:25:59 +00:00
nameDiscriminator={
clanData[id]?.clan ? `[${clanData[id]?.clan?.tag}]` : undefined
}
image={
clanData[id]?.clan
? `https://wotblitz-gc.gcdn.co/icons/clanEmblems1x/clan-icon-v2-${clanData[id]?.clan?.emblem_set_id}.png`
: undefined
}
description={`${
2023-05-29 17:44:32 +00:00
statPeriodNames[period]
2023-05-28 02:25:59 +00:00
} • ${new Date().toDateString()} • ${BLITZ_SERVERS[server]}`}
/>
2023-05-25 18:20:51 +00:00
2023-06-06 16:53:13 +00:00
{stats.battles === 0 && <NoData type={NoDataType.BattlesInPeriod} />}
2023-05-29 18:15:03 +00:00
{stats.battles > 0 && (
2023-06-01 18:36:39 +00:00
<GenericAllStats
stats={stats}
supplementaryStats={supplementaryStats}
2023-05-28 02:25:59 +00:00
/>
)}
2023-05-25 18:20:51 +00:00
2023-05-28 02:25:59 +00:00
<PoweredByBlitzStars />
</Wrapper>,
2023-05-24 02:01:22 +00:00
);
2023-05-25 18:20:51 +00:00
2023-05-27 18:15:02 +00:00
const actionRow = new ActionRowBuilder<ButtonBuilder>().addComponents(
fullBlitzStarsStats(server, accountInfo[id].nickname),
supportBlitzStars,
);
await interaction.editReply({
2023-05-28 02:25:59 +00:00
files: [image],
2023-05-27 18:15:02 +00:00
components: [actionRow],
});
2023-04-26 00:02:10 +00:00
},
2023-05-14 17:13:42 +00:00
autocomplete: usernameAutocomplete,
2023-04-26 00:02:10 +00:00
} satisfies CommandRegistry;