mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-21 18:57:03 +02:00
feat: added future features 👀
This commit is contained in:
1 parent
0db96795b3
commit
db976c4ae9
7 files changed
+214
-138
No files matched your search
+132
-7
@@ -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<PlayerClanInfo>(
|
||||
`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<AccountInfo>(
|
||||
`https://api.wotblitz.${region}/wotb/account/info/?application_id=${WARGAMING_APPLICATION_ID}&account_id=${id}`,
|
||||
);
|
||||
|
||||
return (
|
||||
<Wrapper>
|
||||
<TitleBar
|
||||
name={accountInfo[id].nickname}
|
||||
image={image}
|
||||
description={name}
|
||||
/>
|
||||
|
||||
{/* goofy ahh bug forces me to call them as functions */}
|
||||
{plot.length > 0 && (
|
||||
<Graph.Root
|
||||
verticalMargin={{
|
||||
min: minY,
|
||||
max: maxY,
|
||||
suffix: '%',
|
||||
precision: 2,
|
||||
}}
|
||||
horizontalMargin={{
|
||||
min: minX,
|
||||
max: maxX,
|
||||
precision: 0,
|
||||
}}
|
||||
xMinLabel={new Date(minTime * 1000).toDateString()}
|
||||
xMaxLabel={new Date(maxTime * 1000).toDateString()}
|
||||
>
|
||||
{Graph.Line({
|
||||
// career winrate
|
||||
color: Graph.LineColor.Red,
|
||||
plot: plot,
|
||||
minY,
|
||||
maxY,
|
||||
})}
|
||||
</Graph.Root>
|
||||
)}
|
||||
|
||||
{plot.length === 0 && <NoData type={NoDataType.BattlesInPeriod} />}
|
||||
</Wrapper>
|
||||
);
|
||||
}
|
||||
|
||||
export const evolutionCommand = new Promise<CommandRegistryRaw>(
|
||||
async (resolve) => {
|
||||
@@ -23,7 +133,21 @@ export const evolutionCommand = new Promise<CommandRegistryRaw>(
|
||||
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<CommandRegistryRaw>(
|
||||
});
|
||||
|
||||
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<CommandRegistryRaw>(
|
||||
autocomplete: (interaction) => {
|
||||
autocompleteUsername(interaction);
|
||||
autocompleteTanks(interaction);
|
||||
// autocompleteStatProperty(interaction, 'x');
|
||||
},
|
||||
|
||||
async button(interaction) {
|
||||
@@ -79,7 +204,7 @@ export const evolutionCommand = new Promise<CommandRegistryRaw>(
|
||||
const player = await resolvePlayerFromButton(interaction);
|
||||
const period = resolvePeriodFromButton(player.region, interaction);
|
||||
|
||||
return await evolution(
|
||||
return await render(
|
||||
commandGroup,
|
||||
period,
|
||||
player,
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -25,6 +25,4 @@ export default async function autocompleteClan(
|
||||
)
|
||||
: [],
|
||||
);
|
||||
|
||||
console.log(`Clan autocomplete for ${focusedOption.value}`);
|
||||
}
|
||||
@@ -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<CacheType>,
|
||||
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),
|
||||
);
|
||||
}
|
||||
@@ -28,6 +28,4 @@ export default async function autocompleteTanks(
|
||||
)
|
||||
: [],
|
||||
);
|
||||
|
||||
console.log(`Tanks autocomplete for ${focusedOption.value}`);
|
||||
}
|
||||
@@ -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) {}
|
||||
}
|
||||
@@ -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 extends StatType>(
|
||||
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<PlayerClanInfo>(
|
||||
`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<AccountInfo>(
|
||||
`https://api.wotblitz.${server}/wotb/account/info/?application_id=${WARGAMING_APPLICATION_ID}&account_id=${id}`,
|
||||
);
|
||||
|
||||
return (
|
||||
<Wrapper>
|
||||
<TitleBar
|
||||
name={accountInfo[id].nickname}
|
||||
image={image}
|
||||
description={name}
|
||||
/>
|
||||
|
||||
{/* goofy ahh bug forces me to call them as functions */}
|
||||
{plot.length > 0 && (
|
||||
<Graph.Root
|
||||
verticalMargin={{
|
||||
min: minY,
|
||||
max: maxY,
|
||||
suffix: '%',
|
||||
precision: 2,
|
||||
}}
|
||||
horizontalMargin={{
|
||||
min: minX,
|
||||
max: maxX,
|
||||
precision: 0,
|
||||
}}
|
||||
xMinLabel={new Date(minTime * 1000).toDateString()}
|
||||
xMaxLabel={new Date(maxTime * 1000).toDateString()}
|
||||
>
|
||||
{Graph.Line({
|
||||
// career winrate
|
||||
color: Graph.LineColor.Red,
|
||||
plot: plot,
|
||||
minY,
|
||||
maxY,
|
||||
})}
|
||||
</Graph.Root>
|
||||
)}
|
||||
|
||||
{plot.length === 0 && <NoData type={NoDataType.BattlesInPeriod} />}
|
||||
</Wrapper>
|
||||
);
|
||||
}
|
||||
Reference in new issue
Block a user