2023-04-26 00:02:10 +00:00
|
|
|
import { EmbedBuilder, SlashCommandBuilder } from 'discord.js';
|
2023-05-06 17:45:43 +00:00
|
|
|
import markdownEscape from 'markdown-escape';
|
2023-04-26 00:02:10 +00:00
|
|
|
import { CommandRegistry } from '../behaviors/interactionCreate.js';
|
2023-04-22 19:32:49 +00:00
|
|
|
import { SKILLED_COLOR } from '../constants/colors.js';
|
2023-05-10 20:00:30 +00:00
|
|
|
import { BlitzServer } from '../constants/servers.js';
|
2023-05-14 17:13:42 +00:00
|
|
|
import usernameAutocomplete from '../core/autocomplete/username.js';
|
2023-05-13 22:01:58 +00:00
|
|
|
import getWargamingResponse from '../core/blitz/getWargamingResponse.js';
|
2023-05-14 17:13:42 +00:00
|
|
|
import validateUsername from '../core/blitz/validateUsername.js';
|
2023-05-13 22:01:58 +00:00
|
|
|
import blitzStarsLinks from '../core/blitzstars/blitzStarsLinks.js';
|
|
|
|
|
import getBlitzStarsAccount from '../core/blitzstars/getBlitzStarsAccount.js';
|
|
|
|
|
import poweredByBlitzStars from '../core/blitzstars/poweredByBlitzStars.js';
|
|
|
|
|
import cleanTable from '../core/interaction/cleanTable.js';
|
|
|
|
|
import cmdName from '../core/interaction/cmdName.js';
|
|
|
|
|
import addServerChoices from '../core/options/addServerChoices.js';
|
2023-05-14 17:13:42 +00:00
|
|
|
import addUsernameOption from '../core/options/addUsernameOption.js';
|
2023-05-13 22:01:58 +00:00
|
|
|
import { args } from '../core/process/args.js';
|
2023-05-08 00:08:13 +00:00
|
|
|
import { AccountInfo, AllStats } from '../types/accountInfo.js';
|
2023-05-13 01:27:12 +00:00
|
|
|
import { BlitzStartsComputedPeriodicStatistics } from '../types/statistics.js';
|
2023-04-21 23:45:13 +00:00
|
|
|
|
2023-05-08 00:08:13 +00:00
|
|
|
type Period = 'today' | '30' | '90' | 'career';
|
|
|
|
|
|
2023-04-26 00:02:10 +00:00
|
|
|
export default {
|
|
|
|
|
inProduction: true,
|
2023-05-13 22:01:58 +00:00
|
|
|
inDevelopment: true,
|
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")
|
|
|
|
|
.addStringOption((option) =>
|
|
|
|
|
option
|
|
|
|
|
.setName('period')
|
|
|
|
|
.setDescription('The last number of days of stats')
|
|
|
|
|
.setChoices(
|
2023-05-08 00:08:13 +00:00
|
|
|
{ name: 'Today', value: 'today' satisfies Period },
|
|
|
|
|
{ name: '30 Days', value: '30' satisfies Period },
|
|
|
|
|
{ name: '90 Days', value: '90' satisfies Period },
|
|
|
|
|
{ name: 'Career', value: 'career' satisfies Period },
|
2023-04-26 00:02:10 +00:00
|
|
|
)
|
|
|
|
|
.setRequired(true),
|
|
|
|
|
)
|
2023-05-02 23:01:54 +00:00
|
|
|
.addStringOption(addServerChoices)
|
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-08 00:08:13 +00:00
|
|
|
const period = interaction.options.getString('period') as Period;
|
2023-05-14 17:13:42 +00:00
|
|
|
const username = interaction.options.getString('username')!;
|
2023-05-10 20:00:30 +00:00
|
|
|
const server = interaction.options.getString('server') as BlitzServer;
|
2023-05-14 17:13:42 +00:00
|
|
|
const blitzAccount = await validateUsername(interaction, username, server);
|
2023-05-08 01:45:57 +00:00
|
|
|
if (!blitzAccount) return;
|
2023-05-13 01:27:12 +00:00
|
|
|
let stats: BlitzStartsComputedPeriodicStatistics;
|
|
|
|
|
const accountInfo = await getWargamingResponse<AccountInfo>(
|
|
|
|
|
`https://api.wotblitz.${server}/wotb/account/info/?application_id=${args['wargaming-application-id']}&account_id=${blitzAccount.account_id}`,
|
|
|
|
|
);
|
|
|
|
|
if (!accountInfo) return;
|
|
|
|
|
const blitzStarsAccount = await getBlitzStarsAccount(
|
2023-05-08 00:08:13 +00:00
|
|
|
interaction,
|
2023-05-08 01:45:57 +00:00
|
|
|
blitzAccount.account_id,
|
2023-05-13 01:27:12 +00:00
|
|
|
);
|
2023-05-08 01:45:57 +00:00
|
|
|
if (!blitzStarsAccount) return;
|
2023-04-26 00:02:10 +00:00
|
|
|
|
2023-05-13 01:27:12 +00:00
|
|
|
if (period === 'today') {
|
2023-05-08 01:45:57 +00:00
|
|
|
const a1 = blitzStarsAccount.statistics;
|
|
|
|
|
const a2 = accountInfo[blitzAccount.account_id].statistics;
|
|
|
|
|
const battles = a2.all.battles - a1.all.battles;
|
2023-05-08 00:08:13 +00:00
|
|
|
|
2023-05-08 01:45:57 +00:00
|
|
|
function pb(value: (allStats: AllStats) => number) {
|
|
|
|
|
return (value(a2.all) - value(a1.all)) / battles;
|
|
|
|
|
}
|
|
|
|
|
function diff(value: (allStats: AllStats) => number) {
|
|
|
|
|
return value(a2.all) - value(a1.all);
|
|
|
|
|
}
|
|
|
|
|
function span(
|
|
|
|
|
value1: (allStats: AllStats) => number,
|
|
|
|
|
value2: (allStats: AllStats) => number,
|
|
|
|
|
) {
|
|
|
|
|
return (
|
|
|
|
|
(value1(a2.all) - value1(a1.all)) / (value2(a2.all) - value2(a1.all))
|
2023-05-08 00:08:13 +00:00
|
|
|
);
|
2023-05-08 01:45:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
stats = {
|
|
|
|
|
all: {
|
|
|
|
|
battles,
|
|
|
|
|
capture_points: pb((a) => a.capture_points),
|
|
|
|
|
damage_dealt: pb((a) => a.damage_dealt),
|
|
|
|
|
damage_received: pb((a) => a.damage_received),
|
|
|
|
|
dropped_capture_points: diff((a) => a.dropped_capture_points),
|
|
|
|
|
frags: pb((a) => a.frags),
|
|
|
|
|
frags8p: pb((a) => a.frags8p),
|
|
|
|
|
hits: diff((a) => a.hits),
|
|
|
|
|
losses: diff((a) => a.losses),
|
|
|
|
|
max_frags: pb((a) => a.max_frags),
|
|
|
|
|
max_frags_tank_id: pb((a) => a.max_frags_tank_id),
|
|
|
|
|
max_xp: pb((a) => a.max_xp),
|
|
|
|
|
max_xp_tank_id: pb((a) => a.max_xp_tank_id),
|
|
|
|
|
shots: diff((a) => a.shots),
|
2023-05-13 01:27:12 +00:00
|
|
|
spotted: diff((a) => a.spotted),
|
|
|
|
|
survived_battles: diff((a) => a.survived_battles),
|
|
|
|
|
win_and_survived: diff((a) => a.win_and_survived),
|
2023-05-08 01:45:57 +00:00
|
|
|
wins: diff((a) => a.wins),
|
|
|
|
|
xp: diff((a) => a.xp),
|
|
|
|
|
},
|
|
|
|
|
avg_tier: -Infinity,
|
|
|
|
|
wn7: -Infinity,
|
|
|
|
|
wn8: -Infinity,
|
|
|
|
|
};
|
|
|
|
|
} else {
|
2023-05-13 01:27:12 +00:00
|
|
|
stats =
|
|
|
|
|
period === 'career'
|
|
|
|
|
? blitzStarsAccount.statistics
|
|
|
|
|
: blitzStarsAccount[`period${period}d`];
|
2023-05-08 01:45:57 +00:00
|
|
|
}
|
2023-05-13 01:27:12 +00:00
|
|
|
if (!stats!) return;
|
2023-05-08 01:45:57 +00:00
|
|
|
|
2023-05-13 01:27:12 +00:00
|
|
|
await interaction.editReply({
|
|
|
|
|
embeds: [
|
|
|
|
|
poweredByBlitzStars(
|
|
|
|
|
new EmbedBuilder()
|
|
|
|
|
.setColor(SKILLED_COLOR)
|
|
|
|
|
.setTitle(
|
|
|
|
|
`${markdownEscape(blitzAccount.nickname)}'s ${
|
|
|
|
|
period === 'career' ? period : `${period} day`
|
|
|
|
|
} stats`,
|
|
|
|
|
)
|
|
|
|
|
.setDescription(
|
2023-05-13 17:50:03 +00:00
|
|
|
stats.all.battles > 0
|
|
|
|
|
? `${
|
|
|
|
|
period === 'today'
|
|
|
|
|
? '**⚠ "Today" stats are in development. Some stats are not available/wrong.**\n\n'
|
|
|
|
|
: ''
|
2023-05-13 21:42:40 +00:00
|
|
|
}${cleanTable([
|
2023-05-13 17:50:03 +00:00
|
|
|
[
|
|
|
|
|
'Winrate',
|
|
|
|
|
`${(100 * (stats.all.wins / stats.all.battles)).toFixed(
|
|
|
|
|
2,
|
|
|
|
|
)}%`,
|
|
|
|
|
],
|
|
|
|
|
[
|
|
|
|
|
'Survival',
|
|
|
|
|
`${(
|
|
|
|
|
100 *
|
|
|
|
|
(stats.all.survived_battles / stats.all.battles)
|
|
|
|
|
).toFixed(2)}%`,
|
|
|
|
|
],
|
|
|
|
|
[
|
|
|
|
|
'Accuracy',
|
|
|
|
|
`${((stats.all.hits / stats.all.shots) * 100).toFixed(
|
|
|
|
|
2,
|
|
|
|
|
)}%`,
|
|
|
|
|
],
|
|
|
|
|
['WN8', stats.wn8.toFixed(0)],
|
|
|
|
|
['WN7', stats.wn7.toFixed(0)],
|
|
|
|
|
[],
|
|
|
|
|
['Battles', stats.all.battles],
|
|
|
|
|
['Wins', stats.all.wins],
|
|
|
|
|
['Losses', stats.all.losses],
|
|
|
|
|
['Average tier', stats.avg_tier.toFixed(2)],
|
|
|
|
|
[],
|
|
|
|
|
[
|
|
|
|
|
'Shots per battle',
|
|
|
|
|
(stats.all.shots / stats.all.battles).toFixed(2),
|
|
|
|
|
],
|
|
|
|
|
[
|
|
|
|
|
'Hits per battle',
|
|
|
|
|
(stats.all.hits / stats.all.battles).toFixed(2),
|
|
|
|
|
],
|
|
|
|
|
[
|
|
|
|
|
'Damage per battle',
|
|
|
|
|
(stats.all.damage_dealt / stats.all.battles).toFixed(0),
|
|
|
|
|
],
|
|
|
|
|
[
|
|
|
|
|
'Kills per battle',
|
|
|
|
|
(stats.all.frags / stats.all.battles).toFixed(2),
|
|
|
|
|
],
|
|
|
|
|
[
|
|
|
|
|
'Spots per battle',
|
|
|
|
|
(stats.all.spotted / stats.all.battles).toFixed(2),
|
|
|
|
|
],
|
|
|
|
|
[
|
|
|
|
|
'XP per battle',
|
|
|
|
|
(stats.all.xp / stats.all.battles).toFixed(0),
|
|
|
|
|
],
|
|
|
|
|
[],
|
|
|
|
|
[
|
|
|
|
|
'Damage ratio',
|
|
|
|
|
(
|
|
|
|
|
stats.all.damage_dealt / stats.all.damage_received
|
|
|
|
|
).toFixed(2),
|
|
|
|
|
],
|
|
|
|
|
[
|
|
|
|
|
'Kills to death ratio',
|
|
|
|
|
(
|
|
|
|
|
stats.all.frags /
|
|
|
|
|
(stats.all.battles - stats.all.survived_battles)
|
|
|
|
|
).toFixed(2),
|
|
|
|
|
],
|
2023-05-13 22:01:58 +00:00
|
|
|
])}\n\n${blitzStarsLinks(server, blitzAccount.nickname)}`
|
2023-05-13 17:50:03 +00:00
|
|
|
: 'No battles played in this period.',
|
2023-05-13 01:27:12 +00:00
|
|
|
),
|
|
|
|
|
),
|
|
|
|
|
],
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
console.log(`Showing stats for ${blitzAccount.nickname}`);
|
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;
|