feat: some more type prefixes

This commit is contained in:
TrèsAbhi committed 2025-10-13 23:20:26 -05:00
1 parent 0d8cb5c1ae
commit 26304fc281
71 files changed
+411 -409

No files matched your search

+2
View File
@@ -40,6 +40,7 @@
"Carro", "Carro",
"CCPAOPTOUT", "CCPAOPTOUT",
"CDON", "CDON",
"clanid",
"classname", "classname",
"cleandist", "cleandist",
"closedkrieg", "closedkrieg",
@@ -128,6 +129,7 @@
"NEGATIVEX", "NEGATIVEX",
"NEGATIVEY", "NEGATIVEY",
"NEGATIVEZ", "NEGATIVEZ",
"networkidle",
"NITROPAY", "NITROPAY",
"nivo", "nivo",
"nmatname", "nmatname",
+47 -47
View File
@@ -1,48 +1,48 @@
import { emblemURL, getAccountInfo, getClanAccountInfo } from '@blitzkit/core'; import { emblemURL, getAccountInfo, getClanAccountInfo } from "@blitzkit/core";
import { Locale, SlashCommandSubcommandGroupBuilder } from 'discord.js'; import { Locale, SlashCommandSubcommandGroupBuilder } from "discord.js";
import { CommandWrapper } from '../components/CommandWrapper'; import { CommandWrapper } from "../components/CommandWrapper";
import * as Graph from '../components/Graph'; import * as Graph from "../components/Graph";
import { LineColor } from '../components/Graph/components/Line/constants'; import { LineColor } from "../components/Graph/components/Line/constants";
import { NoData } from '../components/NoData'; import { NoData } from "../components/NoData";
import { TitleBar } from '../components/TitleBar'; import { TitleBar } from "../components/TitleBar";
import { resolveTankId } from '../core/blitz/resolveTankId'; import { resolveTankId } from "../core/blitz/resolveTankId";
import { getBlitzStarsLinkButton } from '../core/blitzstars/getBlitzStarsLinkButton'; import { getBlitzStarsLinkButton } from "../core/blitzstars/getBlitzStarsLinkButton";
import { getPlayerHistories } from '../core/blitzstars/getPlayerHistories'; import { getPlayerHistories } from "../core/blitzstars/getPlayerHistories";
import { getTankHistories } from '../core/blitzstars/getTankHistories'; import { getTankHistories } from "../core/blitzstars/getTankHistories";
import { addPeriodSubCommands } from '../core/discord/addPeriodSubCommands'; import { addPeriodSubCommands } from "../core/discord/addPeriodSubCommands";
import { addTankChoices } from '../core/discord/addTankChoices'; import { addTankChoices } from "../core/discord/addTankChoices";
import { addUsernameChoices } from '../core/discord/addUsernameChoices'; import { addUsernameChoices } from "../core/discord/addUsernameChoices";
import { autocompleteTanks } from '../core/discord/autocompleteTanks'; import { autocompleteTanks } from "../core/discord/autocompleteTanks";
import { autocompleteUsername } from '../core/discord/autocompleteUsername'; import { autocompleteUsername } from "../core/discord/autocompleteUsername";
import { buttonRefresh } from '../core/discord/buttonRefresh'; import { buttonRefresh } from "../core/discord/buttonRefresh";
import { commandToURL } from '../core/discord/commandToURL'; import { commandToURL } from "../core/discord/commandToURL";
import { createLocalizedCommand } from '../core/discord/createLocalizedCommand'; import { createLocalizedCommand } from "../core/discord/createLocalizedCommand";
import { getCustomPeriodParams } from '../core/discord/getCustomPeriodParams'; import { getCustomPeriodParams } from "../core/discord/getCustomPeriodParams";
import { resolvePeriodFromButton } from '../core/discord/resolvePeriodFromButton'; import { resolvePeriodFromButton } from "../core/discord/resolvePeriodFromButton";
import { import {
ResolvedPeriod, type ResolvedPeriod,
resolvePeriodFromCommand, resolvePeriodFromCommand,
} from '../core/discord/resolvePeriodFromCommand'; } from "../core/discord/resolvePeriodFromCommand";
import { resolvePlayerFromButton } from '../core/discord/resolvePlayerFromButton'; import { resolvePlayerFromButton } from "../core/discord/resolvePlayerFromButton";
import { import {
ResolvedPlayer, type ResolvedPlayer,
resolvePlayerFromCommand, resolvePlayerFromCommand,
} from '../core/discord/resolvePlayerFromCommand'; } from "../core/discord/resolvePlayerFromCommand";
import { CommandRegistry } from '../events/interactionCreate'; import type { CommandRegistry } from "../events/interactionCreate";
type EvolutionStatType = 'player' | 'tank'; type EvolutionStatType = "player" | "tank";
async function render( async function render(
{ region, id }: ResolvedPlayer, { region, id }: ResolvedPlayer,
{ start, end, name }: ResolvedPeriod, { start, end, name }: ResolvedPeriod,
type: 'player' | 'tank', type: "player" | "tank",
tankId: number | null, tankId: number | null,
locale: Locale, locale: Locale
) { ) {
const accountInfo = await getAccountInfo(region, id); const accountInfo = await getAccountInfo(region, id);
const clan = (await getClanAccountInfo(region, id, ['clan']))?.clan; const clan = (await getClanAccountInfo(region, id, ["clan"]))?.clan;
const logo = clan ? emblemURL(clan.emblem_set_id) : undefined; const logo = clan ? emblemURL(clan.emblem_set_id) : undefined;
const histories = await (type === 'player' const histories = await (type === "player"
? getPlayerHistories(region, id, { ? getPlayerHistories(region, id, {
start, start,
end, end,
@@ -61,7 +61,7 @@ async function render(
[ [
history.all.battles, history.all.battles,
(history.all.wins / history.all.battles) * 100, (history.all.wins / history.all.battles) * 100,
] as Graph.PlotItem, ] as Graph.PlotItem
); );
const times = histories.map((history) => history.last_battle_time); const times = histories.map((history) => history.last_battle_time);
const minTime = Math.min(...times); const minTime = Math.min(...times);
@@ -82,7 +82,7 @@ async function render(
verticalMargin={{ verticalMargin={{
min: minY, min: minY,
max: maxY, max: maxY,
suffix: '%', suffix: "%",
precision: 2, precision: 2,
}} }}
horizontalMargin={{ horizontalMargin={{
@@ -110,22 +110,22 @@ async function render(
export const evolutionCommand = new Promise<CommandRegistry>( export const evolutionCommand = new Promise<CommandRegistry>(
async (resolve) => { async (resolve) => {
resolve({ resolve({
command: createLocalizedCommand('evolution', [ command: createLocalizedCommand("evolution", [
{ {
group: 'player', group: "player",
modify(option: SlashCommandSubcommandGroupBuilder) { modify(option: SlashCommandSubcommandGroupBuilder) {
addPeriodSubCommands(option, (option) => addPeriodSubCommands(option, (option) =>
option.addStringOption(addUsernameChoices), option.addStringOption(addUsernameChoices)
); );
}, },
}, },
{ {
group: 'tank', group: "tank",
modify(option: SlashCommandSubcommandGroupBuilder) { modify(option: SlashCommandSubcommandGroupBuilder) {
addPeriodSubCommands(option, (option) => addPeriodSubCommands(option, (option) =>
option option
.addStringOption(addTankChoices) .addStringOption(addTankChoices)
.addStringOption(addUsernameChoices), .addStringOption(addUsernameChoices)
); );
}, },
}, },
@@ -136,9 +136,9 @@ export const evolutionCommand = new Promise<CommandRegistry>(
interaction.options.getSubcommandGroup() as EvolutionStatType; interaction.options.getSubcommandGroup() as EvolutionStatType;
const player = await resolvePlayerFromCommand(interaction); const player = await resolvePlayerFromCommand(interaction);
const period = resolvePeriodFromCommand(player.region, interaction); const period = resolvePeriodFromCommand(player.region, interaction);
const tankIdRaw = interaction.options.getString('tank')!; const tankIdRaw = interaction.options.getString("tank")!;
const tankId = const tankId =
commandGroup === 'tank' commandGroup === "tank"
? await resolveTankId(tankIdRaw, interaction.locale) ? await resolveTankId(tankIdRaw, interaction.locale)
: null; : null;
const path = commandToURL(interaction, { const path = commandToURL(interaction, {
@@ -153,13 +153,13 @@ export const evolutionCommand = new Promise<CommandRegistry>(
period, period,
commandGroup, commandGroup,
tankId, tankId,
interaction.locale, interaction.locale
), ),
buttonRefresh(interaction, path), buttonRefresh(interaction, path),
await getBlitzStarsLinkButton( await getBlitzStarsLinkButton(
player.region, player.region,
player.id, player.id,
tankId ?? undefined, tankId ?? undefined
), ),
]; ];
}, },
@@ -171,7 +171,7 @@ export const evolutionCommand = new Promise<CommandRegistry>(
async button(interaction) { async button(interaction) {
const url = new URL(`https://example.com/${interaction.customId}`); const url = new URL(`https://example.com/${interaction.customId}`);
const path = url.pathname.split('/'); const path = url.pathname.split("/");
const commandGroup = path[2] as EvolutionStatType; const commandGroup = path[2] as EvolutionStatType;
const player = await resolvePlayerFromButton(interaction); const player = await resolvePlayerFromButton(interaction);
const period = resolvePeriodFromButton(player.region, interaction); const period = resolvePeriodFromButton(player.region, interaction);
@@ -180,10 +180,10 @@ export const evolutionCommand = new Promise<CommandRegistry>(
player, player,
period, period,
commandGroup, commandGroup,
parseInt(url.searchParams.get('tankId') ?? '0') || null, parseInt(url.searchParams.get("tankId") ?? "0") || null,
interaction.locale, interaction.locale
); );
}, },
}); });
}, }
); );
+4 -4
View File
@@ -11,7 +11,7 @@ import { NoData } from '../components/NoData';
import { TierWeights } from '../components/TierWeights'; import { TierWeights } from '../components/TierWeights';
import { TitleBar } from '../components/TitleBar'; import { TitleBar } from '../components/TitleBar';
import { filtersToDescription } from '../core/blitzkit/filtersToDescription'; import { filtersToDescription } from '../core/blitzkit/filtersToDescription';
import { filterStats, StatFilters } from '../core/blitzstars/filterStats'; import { filterStats, type StatFilters } from '../core/blitzstars/filterStats';
import { getBlitzStarsLinkButton } from '../core/blitzstars/getBlitzStarsLinkButton'; import { getBlitzStarsLinkButton } from '../core/blitzstars/getBlitzStarsLinkButton';
import { getStatsInPeriod } from '../core/blitzstars/getStatsInPeriod'; import { getStatsInPeriod } from '../core/blitzstars/getStatsInPeriod';
import { addPeriodicFilterOptions } from '../core/discord/addPeriodicFilterOptions'; import { addPeriodicFilterOptions } from '../core/discord/addPeriodicFilterOptions';
@@ -26,15 +26,15 @@ import { getFiltersFromButton } from '../core/discord/getFiltersFromButton';
import { getFiltersFromCommand } from '../core/discord/getFiltersFromCommand'; import { getFiltersFromCommand } from '../core/discord/getFiltersFromCommand';
import { resolvePeriodFromButton } from '../core/discord/resolvePeriodFromButton'; import { resolvePeriodFromButton } from '../core/discord/resolvePeriodFromButton';
import { import {
ResolvedPeriod, type ResolvedPeriod,
resolvePeriodFromCommand, resolvePeriodFromCommand,
} from '../core/discord/resolvePeriodFromCommand'; } from '../core/discord/resolvePeriodFromCommand';
import { resolvePlayerFromButton } from '../core/discord/resolvePlayerFromButton'; import { resolvePlayerFromButton } from '../core/discord/resolvePlayerFromButton';
import { import {
ResolvedPlayer, type ResolvedPlayer,
resolvePlayerFromCommand, resolvePlayerFromCommand,
} from '../core/discord/resolvePlayerFromCommand'; } from '../core/discord/resolvePlayerFromCommand';
import { CommandRegistry } from '../events/interactionCreate'; import type { CommandRegistry } from '../events/interactionCreate';
async function render( async function render(
{ region, id }: ResolvedPlayer, { region, id }: ResolvedPlayer,
+1 -1
View File
@@ -19,7 +19,7 @@ import { chunkLines } from "../core/discord/chunkLines";
import { createLocalizedCommand } from "../core/discord/createLocalizedCommand"; import { createLocalizedCommand } from "../core/discord/createLocalizedCommand";
import { resolvePlayerFromCommand } from "../core/discord/resolvePlayerFromCommand"; import { resolvePlayerFromCommand } from "../core/discord/resolvePlayerFromCommand";
import { translator } from "../core/localization/translator"; import { translator } from "../core/localization/translator";
import { CommandRegistry } from "../events/interactionCreate"; import { type CommandRegistry } from "../events/interactionCreate";
export const ownedTanksCommand = new Promise<CommandRegistry>((resolve) => { export const ownedTanksCommand = new Promise<CommandRegistry>((resolve) => {
resolve({ resolve({
+1 -1
View File
@@ -20,7 +20,7 @@ import { blitzStarsTankAverages } from '../core/blitzstars/tankAverages';
import { buttonLink } from '../core/discord/buttonLink'; import { buttonLink } from '../core/discord/buttonLink';
import { createLocalizedCommand } from '../core/discord/createLocalizedCommand'; import { createLocalizedCommand } from '../core/discord/createLocalizedCommand';
import { translator } from '../core/localization/translator'; import { translator } from '../core/localization/translator';
import { CommandRegistry } from '../events/interactionCreate'; import { type CommandRegistry } from '../events/interactionCreate';
import { theme } from '../stitches.config'; import { theme } from '../stitches.config';
type WotInspectorReplaySubmission = type WotInspectorReplaySubmission =
+1 -1
View File
@@ -25,7 +25,7 @@ import { createLocalizedCommand } from "../core/discord/createLocalizedCommand";
import { localizationObject } from "../core/discord/localizationObject"; import { localizationObject } from "../core/discord/localizationObject";
import { resolvePlayerFromCommand } from "../core/discord/resolvePlayerFromCommand"; import { resolvePlayerFromCommand } from "../core/discord/resolvePlayerFromCommand";
import { translator } from "../core/localization/translator"; import { translator } from "../core/localization/translator";
import { CommandRegistry } from "../events/interactionCreate"; import { type CommandRegistry } from "../events/interactionCreate";
import { theme } from "../stitches.config"; import { theme } from "../stitches.config";
export const researchCommand = new Promise<CommandRegistry>((resolve) => { export const researchCommand = new Promise<CommandRegistry>((resolve) => {
@@ -1,4 +1,4 @@
import { ReactNode } from 'react'; import { type ReactNode } from "react";
interface RootProps { interface RootProps {
children: ReactNode; children: ReactNode;
@@ -8,7 +8,7 @@ export function Root({ children }: RootProps) {
return ( return (
<div <div
className="session-tracker-root" className="session-tracker-root"
style={{ display: 'flex', flexDirection: 'column', gap: 8 }} style={{ display: "flex", flexDirection: "column", gap: 8 }}
> >
{children} {children}
</div> </div>
@@ -6,8 +6,8 @@ import {
} from '@blitzkit/core'; } from '@blitzkit/core';
import { createColors } from 'bepaint'; import { createColors } from 'bepaint';
import { import {
AccentColor, type AccentColor,
GrayColor, type GrayColor,
PALETTES, PALETTES,
} from '../../../core/radix/radixColors'; } from '../../../core/radix/radixColors';
import { RowStat } from './RowStat'; import { RowStat } from './RowStat';
@@ -1,11 +1,11 @@
import { Percentile } from '@blitzkit/core'; import { Percentile } from "@blitzkit/core";
import { createColors } from 'bepaint'; import { createColors } from "bepaint";
import { import {
AccentColor, type AccentColor,
GrayColor, type GrayColor,
PALETTES, PALETTES,
} from '../../../core/radix/radixColors'; } from "../../../core/radix/radixColors";
import { PercentileIndicator } from '../../PercentileIndicator'; import { PercentileIndicator } from "../../PercentileIndicator";
interface RowStatProps { interface RowStatProps {
name: string; name: string;
@@ -22,7 +22,7 @@ export function RowStat({
delta, delta,
percentile, percentile,
minimized = false, minimized = false,
color = 'slate', color = "slate",
}: RowStatProps) { }: RowStatProps) {
const theme = createColors(PALETTES[`${color}Dark`]); const theme = createColors(PALETTES[`${color}Dark`]);
@@ -30,29 +30,29 @@ export function RowStat({
<div <div
className="session-tracker-row-stat" className="session-tracker-row-stat"
style={{ style={{
display: 'flex', display: "flex",
flexDirection: 'column', flexDirection: "column",
gap: 4, gap: 4,
alignItems: 'center', alignItems: "center",
justifyContent: 'center', justifyContent: "center",
flex: 1, flex: 1,
}} }}
> >
<div <div
style={{ style={{
display: 'flex', display: "flex",
gap: 4, gap: 4,
alignItems: 'center', alignItems: "center",
justifyContent: 'center', justifyContent: "center",
}} }}
> >
{percentile === undefined && delta !== undefined && delta !== 0 && ( {percentile === undefined && delta !== undefined && delta !== 0 && (
<img <img
alt={delta > 0 ? 'Increase' : 'Decrease'} alt={delta > 0 ? "Increase" : "Decrease"}
src={ src={
(delta ?? 0) > 0 (delta ?? 0) > 0
? 'https://i.imgur.com/qbjiXa1.png' ? "https://i.imgur.com/qbjiXa1.png"
: 'https://i.imgur.com/3uyNhun.png' : "https://i.imgur.com/3uyNhun.png"
} }
style={{ width: 12, height: 12 }} style={{ width: 12, height: 12 }}
/> />
@@ -66,7 +66,7 @@ export function RowStat({
color: theme.textHighContrast, color: theme.textHighContrast,
fontWeight: 700, fontWeight: 700,
fontSize: 16, fontSize: 16,
textAlign: 'center', textAlign: "center",
}} }}
> >
{value} {value}
@@ -77,7 +77,7 @@ export function RowStat({
<span <span
style={{ style={{
color: theme.textLowContrast, color: theme.textLowContrast,
textAlign: 'center', textAlign: "center",
fontSize: 12, fontSize: 12,
}} }}
> >
@@ -1,5 +1,5 @@
import { GenericStat } from '..'; import { type GenericStat } from "..";
import { GenericStatsRow } from './GenericStatsRow'; import { GenericStatsRow } from "./GenericStatsRow";
interface GenericStatsColumnProps { interface GenericStatsColumnProps {
stats: GenericStat[]; stats: GenericStat[];
@@ -7,7 +7,7 @@ interface GenericStatsColumnProps {
export function GenericStatsColumn({ stats }: GenericStatsColumnProps) { export function GenericStatsColumn({ stats }: GenericStatsColumnProps) {
return ( return (
<div style={{ flex: 1, display: 'flex', flexDirection: 'column', gap: 8 }}> <div style={{ flex: 1, display: "flex", flexDirection: "column", gap: 8 }}>
{stats.map((stat) => ( {stats.map((stat) => (
<GenericStatsRow key={stat[0]} stat={stat} /> <GenericStatsRow key={stat[0]} stat={stat} />
))} ))}
@@ -1,6 +1,6 @@
import { GenericStat } from '..'; import { type GenericStat } from "..";
import { theme } from '../../../stitches.config'; import { theme } from "../../../stitches.config";
import { PercentileIndicator } from '../../PercentileIndicator'; import { PercentileIndicator } from "../../PercentileIndicator";
interface GenericStatsRowProps { interface GenericStatsRowProps {
stat: GenericStat; stat: GenericStat;
@@ -10,18 +10,18 @@ export function GenericStatsRow({ stat }: GenericStatsRowProps) {
return ( return (
<div <div
style={{ style={{
display: 'flex', display: "flex",
justifyContent: 'space-between', justifyContent: "space-between",
alignItems: 'center', alignItems: "center",
}} }}
> >
<span <span
style={{ style={{
color: theme.colors.textLowContrast, color: theme.colors.textLowContrast,
fontSize: 16, fontSize: 16,
whiteSpace: 'nowrap', whiteSpace: "nowrap",
maxWidth: 128, maxWidth: 128,
overflow: 'hidden', overflow: "hidden",
}} }}
> >
{stat[0]} {stat[0]}
@@ -32,9 +32,9 @@ export function GenericStatsRow({ stat }: GenericStatsRowProps) {
color: theme.colors.textHighContrast, color: theme.colors.textHighContrast,
fontWeight: 700, fontWeight: 700,
fontSize: 16, fontSize: 16,
display: 'flex', display: "flex",
alignItems: 'center', alignItems: "center",
justifyContent: 'center', justifyContent: "center",
gap: 4, gap: 4,
}} }}
> >
@@ -1,9 +1,9 @@
import { times } from 'lodash-es'; import { times } from "lodash-es";
import { ReactNode } from 'react'; import { type ReactNode } from "react";
import { theme } from '../../../../stitches.config'; import { theme } from "../../../../stitches.config";
import { Margin } from '../Margin'; import { Margin } from "../Margin";
import { MarginOrientation } from '../Margin/constants'; import { MarginOrientation } from "../Margin/constants";
import { GRAPH_HEIGHT, GRAPH_WIDTH } from './constants'; import { GRAPH_HEIGHT, GRAPH_WIDTH } from "./constants";
export interface MarginInputProps { export interface MarginInputProps {
min: number; min: number;
@@ -32,12 +32,12 @@ export function Root({
xTitle, xTitle,
}: RootProps) { }: RootProps) {
return ( return (
<div style={{ display: 'flex', flexDirection: 'column', gap: 16 }}> <div style={{ display: "flex", flexDirection: "column", gap: 16 }}>
<div <div
style={{ style={{
paddingLeft: 64, paddingLeft: 64,
display: 'flex', display: "flex",
justifyContent: 'space-between', justifyContent: "space-between",
}} }}
> >
<span style={{ fontSize: 16, color: theme.colors.textHighContrast }}> <span style={{ fontSize: 16, color: theme.colors.textHighContrast }}>
@@ -48,7 +48,7 @@ export function Root({
</span> </span>
</div> </div>
<div style={{ display: 'flex', gap: 16 }}> <div style={{ display: "flex", gap: 16 }}>
{verticalMargin && ( {verticalMargin && (
<Margin {...verticalMargin} verticalSeparations={separations} /> <Margin {...verticalMargin} verticalSeparations={separations} />
)} )}
@@ -94,9 +94,9 @@ export function Root({
<div <div
style={{ style={{
paddingLeft: 64, paddingLeft: 64,
display: 'flex', display: "flex",
alignItems: 'center', alignItems: "center",
justifyContent: 'center', justifyContent: "center",
}} }}
> >
<span style={{ fontSize: 16, color: theme.colors.textLowContrast }}> <span style={{ fontSize: 16, color: theme.colors.textLowContrast }}>
@@ -1,4 +1,4 @@
import { ReactNode } from 'react'; import { type ReactNode } from 'react';
interface RootProps { interface RootProps {
children: ReactNode; children: ReactNode;
@@ -1,7 +1,7 @@
import { fetchTankDefinitions, TIER_ROMAN_NUMERALS } from "@blitzkit/core"; import { fetchTankDefinitions, TIER_ROMAN_NUMERALS } from "@blitzkit/core";
import { literals } from "@blitzkit/i18n"; import { literals } from "@blitzkit/i18n";
import { Locale } from "discord.js"; import { Locale } from "discord.js";
import { StatFilters } from "../blitzstars/filterStats"; import { type StatFilters } from "../blitzstars/filterStats";
import { translator } from "../localization/translator"; import { translator } from "../localization/translator";
export async function filtersToDescription( export async function filtersToDescription(
@@ -1,5 +1,5 @@
import { getTimeDaysAgo, Region } from '@blitzkit/core'; import { getTimeDaysAgo, type Region } from '@blitzkit/core';
import { PeriodSize } from '../discord/addPeriodSubCommands'; import type { PeriodSize } from '../discord/addPeriodSubCommands';
export function getPeriodStart(region: Region, period: PeriodSize) { export function getPeriodStart(region: Region, period: PeriodSize) {
if (period === 'career') return 0; if (period === 'career') return 0;
+12 -12
View File
@@ -1,10 +1,10 @@
import { TankClass, TankType } from '@blitzkit/core'; import { TankClass, TankType } from "@blitzkit/core";
import { SupplementaryStats } from '@blitzkit/core/src/blitz/getAccountInfo'; import type { SupplementaryStats } from "@blitzkit/core/src/blitz/getAccountInfo";
import { calculateWN8 } from '@blitzkit/core/src/statistics/calculateWN8'; import { calculateWN8 } from "@blitzkit/core/src/statistics/calculateWN8";
import { BlitzStats } from '@blitzkit/core/src/statistics/compositeStats'; import type { BlitzStats } from "@blitzkit/core/src/statistics/compositeStats";
import { sumAllStats } from '@blitzkit/core/src/statistics/sumAllStats'; import { sumAllStats } from "@blitzkit/core/src/statistics/sumAllStats";
import { tankDefinitions } from '../blitzkit/nonBlockingPromises'; import { tankDefinitions } from "../blitzkit/nonBlockingPromises";
import { blitzStarsTankAverages } from './tankAverages'; import { blitzStarsTankAverages } from "./tankAverages";
export interface StatFilters { export interface StatFilters {
nation?: string; nation?: string;
@@ -16,7 +16,7 @@ export interface StatFilters {
export async function filterStats( export async function filterStats(
{ diff, order }: DiffedTankStats, { diff, order }: DiffedTankStats,
filters: StatFilters, filters: StatFilters
) { ) {
// tank, if provided, takes priority over all other filters // tank, if provided, takes priority over all other filters
if (filters.tank) filters = { tank: filters.tank }; if (filters.tank) filters = { tank: filters.tank };
@@ -45,14 +45,14 @@ export async function filterStats(
const battlesOfTanksWithAverages = filteredOrder.reduce<number>( const battlesOfTanksWithAverages = filteredOrder.reduce<number>(
(accumulator, id) => (accumulator, id) =>
awaitedTankAverages[id] ? accumulator + diff[id].battles : accumulator, awaitedTankAverages[id] ? accumulator + diff[id].battles : accumulator,
0, 0
); );
const battlesOfTanksWithTankDefinition = filteredOrder.reduce<number>( const battlesOfTanksWithTankDefinition = filteredOrder.reduce<number>(
(accumulator, id) => (accumulator, id) =>
awaitedTankDefinitions.tanks[id] awaitedTankDefinitions.tanks[id]
? accumulator + diff[id].battles ? accumulator + diff[id].battles
: accumulator, : accumulator,
0, 0
); );
const supplementary = { const supplementary = {
WN8: WN8:
@@ -63,7 +63,7 @@ export async function filterStats(
calculateWN8(awaitedTankAverages[id].all, diff[id]) * calculateWN8(awaitedTankAverages[id].all, diff[id]) *
diff[id].battles diff[id].battles
: accumulator, : accumulator,
0, 0
) / battlesOfTanksWithAverages, ) / battlesOfTanksWithAverages,
tier: tier:
filteredOrder.reduce<number>( filteredOrder.reduce<number>(
@@ -72,7 +72,7 @@ export async function filterStats(
? accumulator + ? accumulator +
awaitedTankDefinitions.tanks[id]!.tier * diff[id].battles awaitedTankDefinitions.tanks[id]!.tier * diff[id].battles
: accumulator, : accumulator,
0, 0
) / battlesOfTanksWithTankDefinition, ) / battlesOfTanksWithTankDefinition,
} satisfies SupplementaryStats; } satisfies SupplementaryStats;
@@ -1,17 +1,17 @@
import { getAccountInfo, Region } from '@blitzkit/core'; import { getAccountInfo, type Region } from "@blitzkit/core";
import { buttonLink } from '../discord/buttonLink'; import { buttonLink } from "../discord/buttonLink";
export async function getBlitzStarsLinkButton( export async function getBlitzStarsLinkButton(
region: Region, region: Region,
id: number, id: number,
tankId?: number, tankId?: number
) { ) {
const { nickname } = await getAccountInfo(region, id); const { nickname } = await getAccountInfo(region, id);
return buttonLink( return buttonLink(
`https://www.blitzstars.com/player/${region}/${nickname}${ `https://www.blitzstars.com/player/${region}/${nickname}${
tankId ? `/tank/${tankId!}` : '' tankId ? `/tank/${tankId!}` : ""
}`, }`,
'BlitzStars', "BlitzStars"
); );
} }
@@ -1,11 +1,11 @@
import { Region, emptyAllStats, getAccountInfo } from '@blitzkit/core'; import { type Region, emptyAllStats, getAccountInfo } from '@blitzkit/core';
import { import {
GetHistoriesOptions, type GetHistoriesOptions,
Histories, type Histories,
History, type History,
getHistoriesDefaultOptions, getHistoriesDefaultOptions,
} from '../../types/histories'; } from '../../types/histories';
import { PlayerStats } from './getPlayerStats'; import type { PlayerStats } from './getPlayerStats';
export async function getPlayerHistories( export async function getPlayerHistories(
server: Region, server: Region,
@@ -1,4 +1,4 @@
import { BlitzStats, Region } from '@blitzkit/core'; import type { BlitzStats, Region } from "@blitzkit/core";
interface IndividualPlayerStats { interface IndividualPlayerStats {
clan: { clan_id: number; name: string; tag: string }; clan: { clan_id: number; name: string; tag: string };
@@ -25,13 +25,13 @@ export async function getPlayerStats<
ReturnType = Ids extends number ? PlayerStats : PlayerStats[], ReturnType = Ids extends number ? PlayerStats : PlayerStats[],
>(region: Region, ids: Ids) { >(region: Region, ids: Ids) {
const stats = await Promise.all( const stats = await Promise.all(
((typeof ids === 'number' ? [ids] : ids) as number[]).map((id) => ((typeof ids === "number" ? [ids] : ids) as number[]).map((id) =>
fetch(`https://www.blitzstars.com/api/playerstats/${id}`).then( fetch(`https://www.blitzstars.com/api/playerstats/${id}`).then(
(response) => response.json() as Promise<PlayerStats>, (response) => response.json() as Promise<PlayerStats>
), )
), )
); );
if (typeof ids === 'number') return stats[0] as ReturnType; if (typeof ids === "number") return stats[0] as ReturnType;
return stats as ReturnType; return stats as ReturnType;
} }
@@ -1,11 +1,11 @@
import { BlitzStats, emptyAllStats, Region } from '@blitzkit/core'; import { type BlitzStats, emptyAllStats, type Region } from "@blitzkit/core";
import { Locale } from 'discord.js'; import { Locale } from "discord.js";
import { DiffedTankStats } from './filterStats'; import type { DiffedTankStats } from "./filterStats";
import { import {
getTankHistories, getTankHistories,
TankHistories, type TankHistories,
TankHistoryRaw, type TankHistoryRaw,
} from './getTankHistories'; } from "./getTankHistories";
const emptyTankHistoryNode: TankHistoryRaw = { const emptyTankHistoryNode: TankHistoryRaw = {
account_id: 0, account_id: 0,
@@ -22,7 +22,7 @@ export async function getStatsInPeriod(
id: number, id: number,
start: number, start: number,
end: number, end: number,
locale: Locale, locale: Locale
) { ) {
const history = await getTankHistories(server, id, locale, { const history = await getTankHistories(server, id, locale, {
includeLatestHistories: true, includeLatestHistories: true,
@@ -43,8 +43,8 @@ export async function getStatsInPeriod(
// find the ones played within the range // find the ones played within the range
const inRangeTanks = tanks.filter((tankId) => const inRangeTanks = tanks.filter((tankId) =>
tankSortedHistory[tankId].some( tankSortedHistory[tankId].some(
(node) => node.last_battle_time > start && node.last_battle_time < end, (node) => node.last_battle_time > start && node.last_battle_time < end
), )
); );
const playedTanks: number[] = []; const playedTanks: number[] = [];
@@ -1,13 +1,13 @@
import { Region, emptyAllStats, getTankStats } from '@blitzkit/core'; import { type Region, emptyAllStats, getTankStats } from "@blitzkit/core";
import { Locale } from 'discord.js'; import { Locale } from "discord.js";
import { import {
GetHistoriesOptions, type GetHistoriesOptions,
Histories, type Histories,
History, type History,
getHistoriesDefaultOptions, getHistoriesDefaultOptions,
} from '../../types/histories'; } from "../../types/histories";
import { UserError } from '../blitzkit/userError'; import { UserError } from "../blitzkit/userError";
import { translator } from '../localization/translator'; import { translator } from "../localization/translator";
export interface TankHistory extends History { export interface TankHistory extends History {
tank_id: number; tank_id: number;
@@ -36,12 +36,12 @@ export async function getTankHistories(
server: Region, server: Region,
id: number, id: number,
locale: Locale, locale: Locale,
options?: Partial<GetTankHistoriesOptions>, options?: Partial<GetTankHistoriesOptions>
) { ) {
const { strings } = translator(locale); const { strings } = translator(locale);
const mergedOptions = { ...getTankHistoriesDefaultOptions, ...options }; const mergedOptions = { ...getTankHistoriesDefaultOptions, ...options };
const tankHistoriesResponse = await fetch( const tankHistoriesResponse = await fetch(
`https://www.blitzstars.com/api/tankhistories/for/${id}/`, `https://www.blitzstars.com/api/tankhistories/for/${id}/`
); );
const tankHistories = ( const tankHistories = (
(await tankHistoriesResponse.json()) as TankHistoriesRaw (await tankHistoriesResponse.json()) as TankHistoriesRaw
@@ -51,7 +51,7 @@ export async function getTankHistories(
all: history.all, all: history.all,
last_battle_time: history.last_battle_time, last_battle_time: history.last_battle_time,
tank_id: history.tank_id, tank_id: history.tank_id,
}) satisfies TankHistory, }) satisfies TankHistory
); );
const compliantTanks: number[] = []; const compliantTanks: number[] = [];
const lastBattles: Record<number, number> = {}; const lastBattles: Record<number, number> = {};
@@ -73,7 +73,7 @@ export async function getTankHistories(
lastBattles[tank_id] = battles; lastBattles[tank_id] = battles;
return complies; return complies;
}, }
); );
const latestNodes: TankHistories = []; const latestNodes: TankHistories = [];
@@ -112,7 +112,7 @@ export async function getTankHistories(
all: emptyAllStats, all: emptyAllStats,
last_battle_time: -Infinity, last_battle_time: -Infinity,
tank_id: tankId, tank_id: tankId,
} satisfies TankHistory), } satisfies TankHistory)
); );
} }
}); });
@@ -4,7 +4,7 @@ import {
TANK_TYPES, TANK_TYPES,
} from '@blitzkit/core'; } from '@blitzkit/core';
import { import {
APIApplicationCommandOptionChoice, type APIApplicationCommandOptionChoice,
Locale, Locale,
SlashCommandBuilder, SlashCommandBuilder,
SlashCommandSubcommandBuilder, SlashCommandSubcommandBuilder,
@@ -1,11 +1,11 @@
import { REGIONS } from '@blitzkit/core'; import { REGIONS } from "@blitzkit/core";
import { import {
APIApplicationCommandOptionChoice, type APIApplicationCommandOptionChoice,
Locale, Locale,
SlashCommandStringOption, SlashCommandStringOption,
} from 'discord.js'; } from "discord.js";
import { translator } from '../localization/translator'; import { translator } from "../localization/translator";
import { localizationObject } from './localizationObject'; import { localizationObject } from "./localizationObject";
export function addRegionChoices(option: SlashCommandStringOption) { export function addRegionChoices(option: SlashCommandStringOption) {
const { strings } = translator(Locale.EnglishUS); const { strings } = translator(Locale.EnglishUS);
@@ -16,14 +16,14 @@ export function addRegionChoices(option: SlashCommandStringOption) {
localizationObject( localizationObject(
(strings) => strings.bot.common.options.region.name, (strings) => strings.bot.common.options.region.name,
undefined, undefined,
true, true
), )
) )
.setDescription(strings.bot.common.options.region.description) .setDescription(strings.bot.common.options.region.description)
.setDescriptionLocalizations( .setDescriptionLocalizations(
localizationObject( localizationObject(
(strings) => strings.bot.common.options.region.description, (strings) => strings.bot.common.options.region.description
), )
) )
.addChoices( .addChoices(
...REGIONS.map( ...REGIONS.map(
@@ -32,10 +32,10 @@ export function addRegionChoices(option: SlashCommandStringOption) {
value: region, value: region,
name: strings.common.regions.normal[region], name: strings.common.regions.normal[region],
name_localizations: localizationObject( name_localizations: localizationObject(
(strings) => strings.common.regions.normal[region], (strings) => strings.common.regions.normal[region]
), ),
}) satisfies APIApplicationCommandOptionChoice, }) satisfies APIApplicationCommandOptionChoice
), )
) )
.setRequired(true); .setRequired(true);
} }
@@ -1,25 +1,25 @@
import { fetchTankNames, SEARCH_KEYS, TankType } from '@blitzkit/core'; import { fetchTankNames, SEARCH_KEYS, TankType } from "@blitzkit/core";
import { import {
ApplicationCommandOptionChoiceData, type ApplicationCommandOptionChoiceData,
AutocompleteInteraction, AutocompleteInteraction,
CacheType, type CacheType,
} from 'discord.js'; } from "discord.js";
import { go } from 'fuzzysort'; import { go } from "fuzzysort";
import { tankNames } from '../blitzkit/nonBlockingPromises'; import { tankNames } from "../blitzkit/nonBlockingPromises";
import { translator } from '../localization/translator'; import { translator } from "../localization/translator";
import { import {
DISCORD_CHOICES_MAX_NAME_SIZE, DISCORD_CHOICES_MAX_NAME_SIZE,
OVERFLOW_SUFFIX, OVERFLOW_SUFFIX,
} from './autocompleteClan/constants'; } from "./autocompleteClan/constants";
export const tankNamesTechTreeOnly = fetchTankNames().then((names) => export const tankNamesTechTreeOnly = fetchTankNames().then((names) =>
names.filter((tank) => tank.treeType === TankType.RESEARCHABLE), names.filter((tank) => tank.treeType === TankType.RESEARCHABLE)
); );
export async function autocompleteTanks( export async function autocompleteTanks(
interaction: AutocompleteInteraction<CacheType>, interaction: AutocompleteInteraction<CacheType>,
techTreeOnly = false, techTreeOnly = false,
fields = ['tank'], fields = ["tank"]
) { ) {
const { unwrap } = translator(interaction.locale); const { unwrap } = translator(interaction.locale);
const focusedOption = interaction.options.getFocused(true); const focusedOption = interaction.options.getFocused(true);
@@ -31,7 +31,7 @@ export async function autocompleteTanks(
go( go(
focusedOption.value, focusedOption.value,
await (techTreeOnly ? tankNamesTechTreeOnly : tankNames), await (techTreeOnly ? tankNamesTechTreeOnly : tankNames),
{ keys: SEARCH_KEYS, limit: 10 }, { keys: SEARCH_KEYS, limit: 10 }
).map(async (item) => { ).map(async (item) => {
let name = unwrap(item.obj.searchableName); let name = unwrap(item.obj.searchableName);
@@ -42,7 +42,7 @@ export async function autocompleteTanks(
0, 0,
unwrap(item.obj.searchableName).length - unwrap(item.obj.searchableName).length -
overSize - overSize -
OVERFLOW_SUFFIX.length, OVERFLOW_SUFFIX.length
)}${OVERFLOW_SUFFIX}`; )}${OVERFLOW_SUFFIX}`;
} }
@@ -50,8 +50,8 @@ export async function autocompleteTanks(
name, name,
value: `${item.obj.id}`, value: `${item.obj.id}`,
} satisfies ApplicationCommandOptionChoiceData<string>; } satisfies ApplicationCommandOptionChoiceData<string>;
}), })
) )
: [], : []
); );
} }
+3 -3
View File
@@ -1,13 +1,13 @@
import { import {
ButtonBuilder, ButtonBuilder,
ButtonStyle, ButtonStyle,
ComponentEmojiResolvable, type ComponentEmojiResolvable,
} from 'discord.js'; } from "discord.js";
export function buttonLink( export function buttonLink(
url: string, url: string,
label: string, label: string,
emoji?: ComponentEmojiResolvable, emoji?: ComponentEmojiResolvable
) { ) {
const button = new ButtonBuilder() const button = new ButtonBuilder()
.setStyle(ButtonStyle.Link) .setStyle(ButtonStyle.Link)
@@ -1,13 +1,13 @@
import { import {
ButtonBuilder, ButtonBuilder,
ButtonStyle, ButtonStyle,
ComponentEmojiResolvable, type ComponentEmojiResolvable,
} from 'discord.js'; } from "discord.js";
export function buttonPrimary( export function buttonPrimary(
id: string, id: string,
label: string, label: string,
emoji?: ComponentEmojiResolvable, emoji?: ComponentEmojiResolvable
) { ) {
const button = new ButtonBuilder() const button = new ButtonBuilder()
.setCustomId(id) .setCustomId(id)
@@ -1,4 +1,4 @@
import { CacheType, ChatInputCommandInteraction } from 'discord.js'; import { type CacheType, ChatInputCommandInteraction } from "discord.js";
export interface Parameters { export interface Parameters {
[key: string]: string | number | boolean | undefined | null; [key: string]: string | number | boolean | undefined | null;
@@ -9,7 +9,7 @@ export interface Parameters {
export function commandToURL( export function commandToURL(
interaction: ChatInputCommandInteraction<CacheType>, interaction: ChatInputCommandInteraction<CacheType>,
parameters?: Parameters, parameters?: Parameters
) { ) {
const pathname = [ const pathname = [
interaction.commandName, interaction.commandName,
@@ -17,11 +17,11 @@ export function commandToURL(
interaction.options.getSubcommand(false), interaction.options.getSubcommand(false),
] ]
.filter(Boolean) .filter(Boolean)
.join('/'); .join("/");
const params = (parameters ? Object.entries(parameters) : []) const params = (parameters ? Object.entries(parameters) : [])
.filter(([, value]) => value !== undefined && value !== null) .filter(([, value]) => value !== undefined && value !== null)
.map(([key, value]) => `${key}=${value}`) .map(([key, value]) => `${key}=${value}`)
.join('&'); .join("&");
return `${pathname}${params.length > 0 ? `?${params}` : ''}`; return `${pathname}${params.length > 0 ? `?${params}` : ""}`;
} }
@@ -1,12 +1,12 @@
import { BlitzKitStrings } from '@blitzkit/i18n'; import { type BlitzKitStrings } from "@blitzkit/i18n";
import { import {
Locale, Locale,
SlashCommandBuilder, SlashCommandBuilder,
SlashCommandSubcommandBuilder, SlashCommandSubcommandBuilder,
SlashCommandSubcommandGroupBuilder, SlashCommandSubcommandGroupBuilder,
} from 'discord.js'; } from "discord.js";
import { translator } from '../localization/translator'; import { translator } from "../localization/translator";
import { localizationObject } from './localizationObject'; import { localizationObject } from "./localizationObject";
interface CreateLocalizedCommandSubcommand { interface CreateLocalizedCommandSubcommand {
subcommand: string; subcommand: string;
@@ -22,12 +22,12 @@ export function createLocalizedCommand(
command: string, command: string,
sub?: sub?:
| CreateLocalizedCommandSubcommand[] | CreateLocalizedCommandSubcommand[]
| CreateLocalizedCommandSubcommandGroup[], | CreateLocalizedCommandSubcommandGroup[]
) { ) {
const commandPathItem = command.replaceAll( const commandPathItem = command.replaceAll(
'-', "-",
'_', "_"
) as keyof BlitzKitStrings['bot']['commands']; ) as keyof BlitzKitStrings["bot"]["commands"];
const { strings } = translator(Locale.EnglishUS); const { strings } = translator(Locale.EnglishUS);
const slashCommand = new SlashCommandBuilder() const slashCommand = new SlashCommandBuilder()
.setName(command) .setName(command)
@@ -35,19 +35,19 @@ export function createLocalizedCommand(
localizationObject( localizationObject(
(strings) => strings.bot.commands[commandPathItem].name, (strings) => strings.bot.commands[commandPathItem].name,
undefined, undefined,
true, true
), )
) )
.setDescription(strings.bot.commands[commandPathItem].description) .setDescription(strings.bot.commands[commandPathItem].description)
.setDescriptionLocalizations( .setDescriptionLocalizations(
localizationObject( localizationObject(
(strings) => strings.bot.commands[commandPathItem].description, (strings) => strings.bot.commands[commandPathItem].description
), )
); );
if (sub) { if (sub) {
sub.map((subItem) => { sub.map((subItem) => {
if ('subcommand' in subItem) { if ("subcommand" in subItem) {
const subcommandNameLocalizations = localizationObject( const subcommandNameLocalizations = localizationObject(
(strings) => (strings) =>
( (
@@ -56,7 +56,7 @@ export function createLocalizedCommand(
} }
).subcommands[subItem.subcommand].name, ).subcommands[subItem.subcommand].name,
undefined, undefined,
true, true
); );
const subcommandDescriptionLocalizations = localizationObject( const subcommandDescriptionLocalizations = localizationObject(
(strings) => (strings) =>
@@ -64,7 +64,7 @@ export function createLocalizedCommand(
strings.bot.commands[commandPathItem] as unknown as { strings.bot.commands[commandPathItem] as unknown as {
subcommands: Record<string, { description: string }>; subcommands: Record<string, { description: string }>;
} }
).subcommands[subItem.subcommand].description, ).subcommands[subItem.subcommand].description
); );
slashCommand.addSubcommand((option) => { slashCommand.addSubcommand((option) => {
@@ -78,7 +78,7 @@ export function createLocalizedCommand(
strings.bot.commands[commandPathItem] as unknown as { strings.bot.commands[commandPathItem] as unknown as {
subcommands: Record<string, { description: string }>; subcommands: Record<string, { description: string }>;
} }
).subcommands[subItem.subcommand].description, ).subcommands[subItem.subcommand].description
) )
.setDescriptionLocalizations(subcommandDescriptionLocalizations); .setDescriptionLocalizations(subcommandDescriptionLocalizations);
}); });
@@ -91,7 +91,7 @@ export function createLocalizedCommand(
} }
).groups[subItem.group].name, ).groups[subItem.group].name,
undefined, undefined,
true, true
); );
const subcommandDescriptionLocalizations = localizationObject( const subcommandDescriptionLocalizations = localizationObject(
(strings) => (strings) =>
@@ -99,7 +99,7 @@ export function createLocalizedCommand(
strings.bot.commands[commandPathItem] as unknown as { strings.bot.commands[commandPathItem] as unknown as {
groups: Record<string, { description: string }>; groups: Record<string, { description: string }>;
} }
).groups[subItem.group].description, ).groups[subItem.group].description
); );
slashCommand.addSubcommandGroup((option) => { slashCommand.addSubcommandGroup((option) => {
@@ -113,7 +113,7 @@ export function createLocalizedCommand(
strings.bot.commands[commandPathItem] as unknown as { strings.bot.commands[commandPathItem] as unknown as {
groups: Record<string, { description: string }>; groups: Record<string, { description: string }>;
} }
).groups[subItem.group].description, ).groups[subItem.group].description
) )
.setDescriptionLocalizations(subcommandDescriptionLocalizations); .setDescriptionLocalizations(subcommandDescriptionLocalizations);
}); });
@@ -1,17 +1,17 @@
import { ChatInputCommandInteraction } from 'discord.js'; import { ChatInputCommandInteraction } from "discord.js";
import { PeriodType } from './addPeriodSubCommands'; import type { PeriodType } from "./addPeriodSubCommands";
export function getCustomPeriodParams( export function getCustomPeriodParams(
interaction: ChatInputCommandInteraction, interaction: ChatInputCommandInteraction,
forcedNonCustomPeriod = false, forcedNonCustomPeriod = false
) { ) {
if ( if (
!forcedNonCustomPeriod && !forcedNonCustomPeriod &&
(interaction.options.getSubcommand() as PeriodType) === 'custom' (interaction.options.getSubcommand() as PeriodType) === "custom"
) { ) {
return { return {
start: interaction.options.getInteger('start', true), start: interaction.options.getInteger("start", true),
end: interaction.options.getInteger('end', true), end: interaction.options.getInteger("end", true),
}; };
} }
@@ -1,19 +1,19 @@
import { TankClass, TankType } from '@blitzkit/core'; import { TankClass, TankType } from "@blitzkit/core";
import { ButtonInteraction } from 'discord.js'; import { ButtonInteraction } from "discord.js";
import { StatFilters } from '../blitzstars/filterStats'; import type { StatFilters } from "../blitzstars/filterStats";
export function getFiltersFromButton(interaction: ButtonInteraction) { export function getFiltersFromButton(interaction: ButtonInteraction) {
const url = new URL(`https://example.com/${interaction.customId}`); const url = new URL(`https://example.com/${interaction.customId}`);
return { return {
nation: url.searchParams.get('nation') ?? undefined, nation: url.searchParams.get("nation") ?? undefined,
tank: parseInt(url.searchParams.get('tank') ?? '0') || undefined, tank: parseInt(url.searchParams.get("tank") ?? "0") || undefined,
class: class:
(Number(url.searchParams.get('class')) as TankClass | undefined) ?? (Number(url.searchParams.get("class")) as TankClass | undefined) ??
undefined, undefined,
type: type:
(Number(url.searchParams.get('type')) as TankType | undefined) ?? (Number(url.searchParams.get("type")) as TankType | undefined) ??
undefined, undefined,
tier: parseInt(url.searchParams.get('tier') ?? '0') || undefined, tier: parseInt(url.searchParams.get("tier") ?? "0") || undefined,
} satisfies StatFilters; } satisfies StatFilters;
} }
@@ -1,6 +1,6 @@
import { ChatInputCommandInteraction } from 'discord.js'; import { ChatInputCommandInteraction } from 'discord.js';
import { resolveTankId } from '../blitz/resolveTankId'; import { resolveTankId } from '../blitz/resolveTankId';
import { StatFilters } from '../blitzstars/filterStats'; import type { StatFilters } from '../blitzstars/filterStats';
export async function getFiltersFromCommand( export async function getFiltersFromCommand(
interaction: ChatInputCommandInteraction, interaction: ChatInputCommandInteraction,
@@ -1,7 +1,7 @@
import { literals } from "@blitzkit/i18n"; import { literals } from "@blitzkit/i18n";
import { Locale } from "discord.js"; import { Locale } from "discord.js";
import { translator } from "../localization/translator"; import { translator } from "../localization/translator";
import { PeriodSize } from "./addPeriodSubCommands"; import type { PeriodSize } from "./addPeriodSubCommands";
export function getPeriodOptionName(period: PeriodSize, locale: Locale) { export function getPeriodOptionName(period: PeriodSize, locale: Locale) {
const { strings } = translator(locale); const { strings } = translator(locale);
@@ -1,4 +1,4 @@
import { BlitzKitStrings, literals as literalsFunc } from "@blitzkit/i18n"; import { type BlitzKitStrings, literals as literalsFunc } from "@blitzkit/i18n";
import { Locale } from "discord.js"; import { Locale } from "discord.js";
import { SUPPORTED_LOCALES_DISCORD } from "../localization/strings/constants"; import { SUPPORTED_LOCALES_DISCORD } from "../localization/strings/constants";
import { translator } from "../localization/translator"; import { translator } from "../localization/translator";
@@ -3,12 +3,12 @@ import {
AttachmentBuilder, AttachmentBuilder,
ButtonBuilder, ButtonBuilder,
EmbedBuilder, EmbedBuilder,
InteractionEditReplyOptions, type InteractionEditReplyOptions,
InteractionReplyOptions, type InteractionReplyOptions,
MessageEditOptions, type MessageEditOptions,
} from "discord.js"; } from "discord.js";
import { InteractionReturnable } from "../../events/interactionCreate"; import type { InteractionReturnable } from "../../events/interactionCreate";
import { Writeable } from "../../types/writable"; import type { Writeable } from "../../types/writable";
import { jsxToPngThreaded } from "../blitzkit/jsxToPngThreaded"; import { jsxToPngThreaded } from "../blitzkit/jsxToPngThreaded";
import { RenderConfiguration } from "../blitzkit/renderConfiguration"; import { RenderConfiguration } from "../blitzkit/renderConfiguration";
@@ -1,4 +1,4 @@
import { Region } from "@blitzkit/core"; import type { Region } from "@blitzkit/core";
import { literals } from "@blitzkit/i18n"; import { literals } from "@blitzkit/i18n";
import { ChatInputCommandInteraction } from "discord.js"; import { ChatInputCommandInteraction } from "discord.js";
import markdownEscape from "markdown-escape"; import markdownEscape from "markdown-escape";
@@ -1,25 +1,25 @@
import { getTimeDaysAgo, Region } from '@blitzkit/core'; import { getTimeDaysAgo, type Region } from "@blitzkit/core";
import { ButtonInteraction } from 'discord.js'; import { ButtonInteraction } from "discord.js";
import { getPeriodNow } from '../blitzkit/getPeriodNow'; import { getPeriodNow } from "../blitzkit/getPeriodNow";
import { getPeriodStart } from '../blitzkit/getPeriodStart'; import { getPeriodStart } from "../blitzkit/getPeriodStart";
import { PeriodType } from './addPeriodSubCommands'; import type { PeriodType } from "./addPeriodSubCommands";
import { getPeriodOptionName } from './getPeriodOptionName'; import { getPeriodOptionName } from "./getPeriodOptionName";
import { ResolvedPeriod } from './resolvePeriodFromCommand'; import type { ResolvedPeriod } from "./resolvePeriodFromCommand";
export function resolvePeriodFromButton( export function resolvePeriodFromButton(
region: Region, region: Region,
interaction: ButtonInteraction, interaction: ButtonInteraction
) { ) {
let name: string; let name: string;
let start: number; let start: number;
let end: number; let end: number;
const url = new URL(`https://example.com/${interaction.customId}`); const url = new URL(`https://example.com/${interaction.customId}`);
const path = url.pathname.split('/'); const path = url.pathname.split("/");
const periodSubcommand = path.at(-1) as PeriodType; const periodSubcommand = path.at(-1) as PeriodType;
if (periodSubcommand === 'custom') { if (periodSubcommand === "custom") {
const startRaw = parseInt(url!.searchParams.get('start')!); const startRaw = parseInt(url!.searchParams.get("start")!);
const endRaw = parseInt(url!.searchParams.get('end')!); const endRaw = parseInt(url!.searchParams.get("end")!);
const startDaysAgoMin = Math.min(startRaw, endRaw); const startDaysAgoMin = Math.min(startRaw, endRaw);
const endDaysAgoMax = Math.max(startRaw, endRaw); const endDaysAgoMax = Math.max(startRaw, endRaw);
@@ -1,10 +1,10 @@
import { getTimeDaysAgo, Region } from "@blitzkit/core"; import { getTimeDaysAgo, type Region } from "@blitzkit/core";
import { literals } from "@blitzkit/i18n"; import { literals } from "@blitzkit/i18n";
import { CacheType, ChatInputCommandInteraction } from "discord.js"; import { type CacheType, ChatInputCommandInteraction } from "discord.js";
import { getPeriodNow } from "../blitzkit/getPeriodNow"; import { getPeriodNow } from "../blitzkit/getPeriodNow";
import { getPeriodStart } from "../blitzkit/getPeriodStart"; import { getPeriodStart } from "../blitzkit/getPeriodStart";
import { translator } from "../localization/translator"; import { translator } from "../localization/translator";
import { PeriodType } from "./addPeriodSubCommands"; import type { PeriodType } from "./addPeriodSubCommands";
import { getPeriodOptionName } from "./getPeriodOptionName"; import { getPeriodOptionName } from "./getPeriodOptionName";
export interface ResolvedPeriod { export interface ResolvedPeriod {
@@ -1,12 +1,12 @@
import { Region } from '@blitzkit/core'; import type { Region } from "@blitzkit/core";
import { ButtonInteraction } from 'discord.js'; import { ButtonInteraction } from "discord.js";
import { ResolvedPlayer } from './resolvePlayerFromCommand'; import type { ResolvedPlayer } from "./resolvePlayerFromCommand";
export async function resolvePlayerFromButton(interaction: ButtonInteraction) { export async function resolvePlayerFromButton(interaction: ButtonInteraction) {
const url = new URL(`https://exmaple.com/${interaction.customId}`); const url = new URL(`https://exmaple.com/${interaction.customId}`);
return { return {
id: parseInt(url.searchParams.get('id')!), id: parseInt(url.searchParams.get("id")!),
region: url.searchParams.get('region') as Region, region: url.searchParams.get("region") as Region,
} satisfies ResolvedPlayer; } satisfies ResolvedPlayer;
} }
@@ -1,6 +1,6 @@
import { idToRegion, Region } from "@blitzkit/core"; import { idToRegion, type Region } from "@blitzkit/core";
import { literals } from "@blitzkit/i18n"; import { literals } from "@blitzkit/i18n";
import { CacheType, ChatInputCommandInteraction } from "discord.js"; import { type CacheType, ChatInputCommandInteraction } from "discord.js";
import markdownEscape from "markdown-escape"; import markdownEscape from "markdown-escape";
import { searchPlayersAcrossRegionsBotWrapper } from "../../blitz/searchPlayersAcrossRegionsBotWrapper"; import { searchPlayersAcrossRegionsBotWrapper } from "../../blitz/searchPlayersAcrossRegionsBotWrapper";
import { getBlitzFromDiscord } from "../../blitzkit/getBlitzFromDiscord"; import { getBlitzFromDiscord } from "../../blitzkit/getBlitzFromDiscord";
+38 -38
View File
@@ -1,52 +1,52 @@
import * as colors from '@radix-ui/colors'; import * as colors from "@radix-ui/colors";
import { Theme } from '@radix-ui/themes'; import { Theme } from "@radix-ui/themes";
import { ComponentProps } from 'react'; import type { ComponentProps } from "react";
export type AccentColor = Exclude< export type AccentColor = Exclude<
ComponentProps<typeof Theme>['accentColor'], ComponentProps<typeof Theme>["accentColor"],
'gray' | undefined "gray" | undefined
>; >;
export type AccentColorDark = `${AccentColor}Dark`; export type AccentColorDark = `${AccentColor}Dark`;
export type GrayColor = Exclude< export type GrayColor = Exclude<
ComponentProps<typeof Theme>['grayColor'], ComponentProps<typeof Theme>["grayColor"],
'auto' | undefined "auto" | undefined
>; >;
export type GrayColorDark = `${GrayColor}Dark`; export type GrayColorDark = `${GrayColor}Dark`;
export const ACCENT_COLORS: AccentColor[] = [ export const ACCENT_COLORS: AccentColor[] = [
'tomato', "tomato",
'red', "red",
'ruby', "ruby",
'crimson', "crimson",
'pink', "pink",
'plum', "plum",
'purple', "purple",
'violet', "violet",
'iris', "iris",
'indigo', "indigo",
'blue', "blue",
'cyan', "cyan",
'teal', "teal",
'jade', "jade",
'green', "green",
'grass', "grass",
'brown', "brown",
'orange', "orange",
'sky', "sky",
'mint', "mint",
'lime', "lime",
'yellow', "yellow",
'amber', "amber",
'gold', "gold",
'bronze', "bronze",
]; ];
export const GRAY_COLORS: GrayColor[] = [ export const GRAY_COLORS: GrayColor[] = [
'gray', "gray",
'mauve', "mauve",
'slate', "slate",
'sage', "sage",
'olive', "olive",
'sand', "sand",
]; ];
export const PALETTES: Record< export const PALETTES: Record<
@@ -3,21 +3,21 @@ import {
AttachmentBuilder, AttachmentBuilder,
ButtonBuilder, ButtonBuilder,
ButtonStyle, ButtonStyle,
CacheType, type CacheType,
ChatInputCommandInteraction, ChatInputCommandInteraction,
InteractionReplyOptions, type InteractionReplyOptions,
} from 'discord.js'; } from "discord.js";
import { InteractionRawReturnable, commands } from '..'; import { type InteractionRawReturnable, commands } from "..";
import { UserError } from '../../../core/blitzkit/userError'; import { UserError } from "../../../core/blitzkit/userError";
import { buttonLink } from '../../../core/discord/buttonLink'; import { buttonLink } from "../../../core/discord/buttonLink";
import { embedWarning } from '../../../core/discord/embedWarning'; import { embedWarning } from "../../../core/discord/embedWarning";
import { normalizeInteractionReturnable } from '../../../core/discord/normalizeInteractionReturnable'; import { normalizeInteractionReturnable } from "../../../core/discord/normalizeInteractionReturnable";
import { psa } from '../../../core/discord/psa'; import { psa } from "../../../core/discord/psa";
import { translator } from '../../../core/localization/translator'; import { translator } from "../../../core/localization/translator";
import { Writeable } from '../../../types/writable'; import type { Writeable } from "../../../types/writable";
export async function handleChatInputCommand( export async function handleChatInputCommand(
interaction: ChatInputCommandInteraction<CacheType>, interaction: ChatInputCommandInteraction<CacheType>
) { ) {
await interaction.deferReply(); await interaction.deferReply();
@@ -33,10 +33,10 @@ export async function handleChatInputCommand(
(Array.isArray(returnable) ? returnable : [returnable]).forEach( (Array.isArray(returnable) ? returnable : [returnable]).forEach(
(object) => { (object) => {
if (typeof object === 'string') { if (typeof object === "string") {
chunks.push([object]); chunks.push([object]);
} else chunks.at(-1)?.push(object!); } else chunks.at(-1)?.push(object!);
}, }
); );
let index = 0; let index = 0;
@@ -49,17 +49,17 @@ export async function handleChatInputCommand(
(psa.data.commands === undefined || (psa.data.commands === undefined ||
psa.data.commands.includes(interaction.commandName)) psa.data.commands.includes(interaction.commandName))
) { ) {
if (psa.data.type === undefined || psa.data.type === 'embed') { if (psa.data.type === undefined || psa.data.type === "embed") {
if (!reply.embeds) reply.embeds = []; if (!reply.embeds) reply.embeds = [];
const embed = embedWarning(psa.data.title, psa.data.description); const embed = embedWarning(psa.data.title, psa.data.description);
if (psa.data.image) embed.setImage(psa.data.image); if (psa.data.image) embed.setImage(psa.data.image);
(reply.embeds as Writeable<typeof reply.embeds>).push(embed); (reply.embeds as Writeable<typeof reply.embeds>).push(embed);
} else if (psa.data.type === 'image') { } else if (psa.data.type === "image") {
if (!reply.files) reply.files = []; if (!reply.files) reply.files = [];
(reply.files as Writeable<typeof reply.files>).push( (reply.files as Writeable<typeof reply.files>).push(
new AttachmentBuilder(psa.data.image), new AttachmentBuilder(psa.data.image)
); );
reply.content = reply.content ?? psa.data.title; reply.content = reply.content ?? psa.data.title;
} }
@@ -72,7 +72,7 @@ export async function handleChatInputCommand(
( (
reply.components[0] as ActionRowBuilder<ButtonBuilder> reply.components[0] as ActionRowBuilder<ButtonBuilder>
).addComponents( ).addComponents(
psa.data.links.map(({ title, url }) => buttonLink(url, title)), psa.data.links.map(({ title, url }) => buttonLink(url, title))
); );
} }
} }
@@ -93,17 +93,17 @@ export async function handleChatInputCommand(
ephemeral: true, ephemeral: true,
}; };
if (psa.data.type === undefined || psa.data.type === 'embed') { if (psa.data.type === undefined || psa.data.type === "embed") {
if (!followUp.embeds) followUp.embeds = []; if (!followUp.embeds) followUp.embeds = [];
const embed = embedWarning(psa.data.title, psa.data.description); const embed = embedWarning(psa.data.title, psa.data.description);
if (psa.data.image) embed.setImage(psa.data.image); if (psa.data.image) embed.setImage(psa.data.image);
(followUp.embeds as Writeable<typeof followUp.embeds>).push(embed); (followUp.embeds as Writeable<typeof followUp.embeds>).push(embed);
} else if (psa.data.type === 'image') { } else if (psa.data.type === "image") {
if (!followUp.files) followUp.files = []; if (!followUp.files) followUp.files = [];
(followUp.files as Writeable<typeof followUp.files>).push( (followUp.files as Writeable<typeof followUp.files>).push(
new AttachmentBuilder(psa.data.image), new AttachmentBuilder(psa.data.image)
); );
followUp.content = followUp.content ?? psa.data.title; followUp.content = followUp.content ?? psa.data.title;
} }
@@ -116,7 +116,7 @@ export async function handleChatInputCommand(
( (
followUp.components[0] as ActionRowBuilder<ButtonBuilder> followUp.components[0] as ActionRowBuilder<ButtonBuilder>
).addComponents( ).addComponents(
psa.data.links.map(({ title, url }) => buttonLink(url, title)), psa.data.links.map(({ title, url }) => buttonLink(url, title))
); );
} }
@@ -132,8 +132,8 @@ export async function handleChatInputCommand(
new ActionRowBuilder<ButtonBuilder>().addComponents( new ActionRowBuilder<ButtonBuilder>().addComponents(
new ButtonBuilder() new ButtonBuilder()
.setLabel(strings.bot.common.errors.get_help) .setLabel(strings.bot.common.errors.get_help)
.setURL('https://discord.gg/nDt7AjGJQH') .setURL("https://discord.gg/nDt7AjGJQH")
.setStyle(ButtonStyle.Link), .setStyle(ButtonStyle.Link)
), ),
]; ];
if (error instanceof UserError) { if (error instanceof UserError) {
@@ -4,15 +4,15 @@ import {
AutocompleteInteraction, AutocompleteInteraction,
ButtonBuilder, ButtonBuilder,
ButtonInteraction, ButtonInteraction,
CacheType, type CacheType,
ChatInputCommandInteraction, ChatInputCommandInteraction,
EmbedBuilder, EmbedBuilder,
Interaction, type Interaction,
REST, REST,
Routes, Routes,
SlashCommandBuilder, SlashCommandBuilder,
SlashCommandOptionsOnlyBuilder, type SlashCommandOptionsOnlyBuilder,
SlashCommandSubcommandsOnlyBuilder, type SlashCommandSubcommandsOnlyBuilder,
} from "discord.js"; } from "discord.js";
import { aboutCommand } from "../../commands/about"; import { aboutCommand } from "../../commands/about";
import { breakdownCommand } from "../../commands/breakdown"; import { breakdownCommand } from "../../commands/breakdown";
+1 -1
View File
@@ -1,6 +1,6 @@
// a cleaner simplification of Blitz Stars' histories because it's a mess there // a cleaner simplification of Blitz Stars' histories because it's a mess there
import { BlitzStats } from '@blitzkit/core'; import { type BlitzStats } from '@blitzkit/core';
export interface History { export interface History {
all: BlitzStats; all: BlitzStats;
+5 -5
View File
@@ -1,5 +1,5 @@
import { TankClass, TankType } from '../protos'; import { TankClass, TankType } from "../protos";
import { BlitzStats } from '../statistics'; import type { BlitzStats } from "../statistics";
export const TANK_TYPES = [ export const TANK_TYPES = [
TankType.RESEARCHABLE, TankType.RESEARCHABLE,
@@ -8,9 +8,9 @@ export const TANK_TYPES = [
]; ];
export const TANK_TYPE_COMMAND_NAMES = { export const TANK_TYPE_COMMAND_NAMES = {
[TankType.RESEARCHABLE]: 'researchable', [TankType.RESEARCHABLE]: "researchable",
[TankType.PREMIUM]: 'premium', [TankType.PREMIUM]: "premium",
[TankType.COLLECTOR]: 'collector', [TankType.COLLECTOR]: "collector",
}; };
export const TANK_CLASSES = [ export const TANK_CLASSES = [
+11 -11
View File
@@ -1,19 +1,19 @@
import { assertSecret, EventManager } from '../blitzkit'; import { assertSecret, EventManager } from "../blitzkit";
import { patientFetch } from '../blitzkit/patientFetch'; import { patientFetch } from "../blitzkit/patientFetch";
import { Region } from './regions'; import type { Region } from "./regions";
const RETRY_ERRORS = ['REQUEST_LIMIT_EXCEEDED', 'SOURCE_NOT_AVAILABLE']; const RETRY_ERRORS = ["REQUEST_LIMIT_EXCEEDED", "SOURCE_NOT_AVAILABLE"];
export const retryAbleBlitzFetchEvent = new EventManager(); export const retryAbleBlitzFetchEvent = new EventManager();
export const blitzFetchQueueAvailableEvent = new EventManager(); export const blitzFetchQueueAvailableEvent = new EventManager();
type BlitzResponse<Data extends object> = type BlitzResponse<Data extends object> =
| { | {
status: 'error'; status: "error";
error: { field: string; message: string; code: 402; value: null }; error: { field: string; message: string; code: 402; value: null };
} }
| { | {
status: 'ok'; status: "ok";
data: Data; data: Data;
}; };
@@ -36,11 +36,11 @@ async function manageQueue() {
const request = queue.shift()!; const request = queue.shift()!;
const data = (await patientFetch(request.url) const data = (await patientFetch(request.url)
.then((response) => response.json()) .then((response) => response.json())
.catch((error) => ({ status: 'error', error }))) as BlitzResponse< .catch((error) => ({ status: "error", error }))) as BlitzResponse<
typeof request.resolve typeof request.resolve
>; >;
if (data.status === 'ok') { if (data.status === "ok") {
request.resolve(data.data); request.resolve(data.data);
} else { } else {
if (RETRY_ERRORS.includes(data.error.message)) { if (RETRY_ERRORS.includes(data.error.message)) {
@@ -67,19 +67,19 @@ export type FetchBlitzParams = Record<string, string | number | undefined>;
export function fetchBlitz<Data extends object>( export function fetchBlitz<Data extends object>(
region: Region, region: Region,
path: string, path: string,
params: FetchBlitzParams = {}, params: FetchBlitzParams = {}
) { ) {
return new Promise<Data>((resolve) => { return new Promise<Data>((resolve) => {
queue.push({ queue.push({
url: `https://api.wotblitz.${region}/wotb/${path}/?${Object.entries({ url: `https://api.wotblitz.${region}/wotb/${path}/?${Object.entries({
application_id: assertSecret( application_id: assertSecret(
import.meta.env.PUBLIC_WARGAMING_APPLICATION_ID, import.meta.env.PUBLIC_WARGAMING_APPLICATION_ID
), ),
...params, ...params,
}) })
.filter(([_, value]) => value !== undefined) .filter(([_, value]) => value !== undefined)
.map(([key, value]) => `${key}=${encodeURIComponent(value!)}`) .map(([key, value]) => `${key}=${encodeURIComponent(value!)}`)
.join('&')}`, .join("&")}`,
resolve(data) { resolve(data) {
resolve(data as Data); resolve(data as Data);
}, },
+4 -4
View File
@@ -1,11 +1,11 @@
import { assertSecret } from '../blitzkit'; import { assertSecret } from "../blitzkit";
import { BlitzGlossary } from '../types'; import type { BlitzGlossary } from "../types";
export async function fetchGlossary(locale: string) { export async function fetchGlossary(locale: string) {
const response = await fetch( const response = await fetch(
`${assertSecret( `${assertSecret(
import.meta.env.WOTB_GLOSSARY_DOMAIN, import.meta.env.WOTB_GLOSSARY_DOMAIN
)}/${locale}${assertSecret(import.meta.env.WOTB_GLOSSARY_PATH)}`, )}/${locale}${assertSecret(import.meta.env.WOTB_GLOSSARY_PATH)}`
); );
return (await response.json()) as BlitzGlossary; return (await response.json()) as BlitzGlossary;
} }
+8 -8
View File
@@ -1,14 +1,14 @@
import { BlitzStats, calculateWN8 } from "../statistics"; import { type BlitzStats, calculateWN8 } from "../statistics";
export type Stat = keyof ReturnType<typeof generateStats>; export type Stat = keyof ReturnType<typeof generateStats>;
export const STAT_NAMES: Record<Stat, string> = { export const STAT_NAMES: Record<Stat, string> = {
battles: 'Battles', battles: "Battles",
winrate: 'Winrate', winrate: "Winrate",
wn8: 'WN8', wn8: "WN8",
averageDamage: 'Damage', averageDamage: "Damage",
damage: 'Accumulated damage', damage: "Accumulated damage",
wins: 'Wins', wins: "Wins",
}; };
export const STAT_KEYS = Object.keys(STAT_NAMES) as Stat[]; export const STAT_KEYS = Object.keys(STAT_NAMES) as Stat[];
@@ -29,7 +29,7 @@ export function prettifyStats(s: ReturnType<typeof generateStats>) {
battles: `${s.battles}`, battles: `${s.battles}`,
wins: `${s.wins}`, wins: `${s.wins}`,
winrate: `${(s.winrate * 100).toFixed(0)}%`, winrate: `${(s.winrate * 100).toFixed(0)}%`,
wn8: s.wn8 ? s.wn8.toFixed(0) : '--', wn8: s.wn8 ? s.wn8.toFixed(0) : "--",
damage: `${s.damage}`, damage: `${s.damage}`,
averageDamage: s.averageDamage.toFixed(0), averageDamage: s.averageDamage.toFixed(0),
} satisfies Record<Stat, string>; } satisfies Record<Stat, string>;
@@ -1,6 +1,6 @@
import { fetchBlitz } from "./fetchBlitz"; import { fetchBlitz } from "./fetchBlitz";
import { normalizeIds } from "./normalizeIds"; import { normalizeIds } from "./normalizeIds";
import { Region } from "./regions"; import type { Region } from "./regions";
interface IndividualAccountAchievements { interface IndividualAccountAchievements {
achievements: { achievements: {
@@ -1,6 +1,6 @@
import { fetchBlitz } from "./fetchBlitz"; import { fetchBlitz } from "./fetchBlitz";
import { normalizeIds } from "./normalizeIds"; import { normalizeIds } from "./normalizeIds";
import { Region } from "./regions"; import type { Region } from "./regions";
type IndividualClanAccountInfo = { type IndividualClanAccountInfo = {
account_id: number; account_id: number;
+1 -1
View File
@@ -1,6 +1,6 @@
import { fetchBlitz } from "./fetchBlitz"; import { fetchBlitz } from "./fetchBlitz";
import { normalizeIds } from "./normalizeIds"; import { normalizeIds } from "./normalizeIds";
import { Region } from "./regions"; import type { Region } from "./regions";
interface IndividualClanInfo { interface IndividualClanInfo {
recruiting_options: { recruiting_options: {
+2 -2
View File
@@ -1,7 +1,7 @@
import { context } from "../blitzkit/context"; import { context } from "../blitzkit/context";
import { patientFetch } from "../blitzkit/patientFetch"; import { patientFetch } from "../blitzkit/patientFetch";
import { RatingLeague, RatingReward } from "./rating"; import type { RatingLeague, RatingReward } from "./rating";
import { Region } from "./regions"; import type { Region } from "./regions";
import { regionToRegionSubdomain } from "./regionToRegionSubdomain"; import { regionToRegionSubdomain } from "./regionToRegionSubdomain";
export type RatingInfo = export type RatingInfo =
+3 -3
View File
@@ -1,8 +1,8 @@
import { context } from "../blitzkit/context"; import { context } from "../blitzkit/context";
import { patientFetch } from "../blitzkit/patientFetch"; import { patientFetch } from "../blitzkit/patientFetch";
import { RatingPlayer } from "../statistics"; import type { RatingPlayer } from "../statistics";
import { LeagueTop } from "./rating"; import type { LeagueTop } from "./rating";
import { Region } from "./regions"; import type { Region } from "./regions";
import { regionToRegionSubdomain } from "./regionToRegionSubdomain"; import { regionToRegionSubdomain } from "./regionToRegionSubdomain";
export async function getRatingLeague( export async function getRatingLeague(
@@ -1,7 +1,7 @@
import { patientFetch } from "../blitzkit/patientFetch"; import { patientFetch } from "../blitzkit/patientFetch";
import { withCORSProxy } from "../blitzkit/withCORSProxy"; import { withCORSProxy } from "../blitzkit/withCORSProxy";
import { RatingNeighbors } from "./rating"; import type { RatingNeighbors } from "./rating";
import { Region } from "./regions"; import type { Region } from "./regions";
import { regionToRegionSubdomain } from "./regionToRegionSubdomain"; import { regionToRegionSubdomain } from "./regionToRegionSubdomain";
export async function getRatingNeighbors( export async function getRatingNeighbors(
+3 -3
View File
@@ -1,6 +1,6 @@
import { TanksStats } from "../types"; import type { TanksStats } from "../types";
import { FetchBlitzParams, fetchBlitz } from "./fetchBlitz"; import { type FetchBlitzParams, fetchBlitz } from "./fetchBlitz";
import { Region } from "./regions"; import type { Region } from "./regions";
export async function getTankStats( export async function getTankStats(
region: Region, region: Region,
+1 -1
View File
@@ -1,4 +1,4 @@
import { Region } from './regions'; import { type Region } from './regions';
export const MIN_REGION_IDS: Record<Region, number> = { export const MIN_REGION_IDS: Record<Region, number> = {
asia: 20e8, asia: 20e8,
+1 -1
View File
@@ -1,4 +1,4 @@
import { RatingPlayer } from '../statistics'; import { type RatingPlayer } from '../statistics';
export const LEAGUES = [ export const LEAGUES = [
{ name: 'diamond', minScore: 5000, index: 0, icon: 'YOw6mZ4' }, { name: 'diamond', minScore: 5000, index: 0, icon: 'YOw6mZ4' },
@@ -1,4 +1,4 @@
import { Region, RegionSubdomain } from "./regions"; import type { Region, RegionSubdomain } from "./regions";
export function regionSubdomainToRegion(regionDomain: RegionSubdomain): Region { export function regionSubdomainToRegion(regionDomain: RegionSubdomain): Region {
return regionDomain === "na" ? "com" : regionDomain; return regionDomain === "na" ? "com" : regionDomain;
@@ -1,4 +1,4 @@
import { Region, RegionSubdomain } from "./regions"; import { type Region, type RegionSubdomain } from "./regions";
export function regionToRegionSubdomain(regionDomain: Region): RegionSubdomain { export function regionToRegionSubdomain(regionDomain: Region): RegionSubdomain {
return regionDomain === "com" ? "na" : regionDomain; return regionDomain === "com" ? "na" : regionDomain;
@@ -1,6 +1,6 @@
import { ClanList } from "./clans"; import type { ClanList } from "./clans";
import { fetchBlitz } from "./fetchBlitz"; import { fetchBlitz } from "./fetchBlitz";
import { Region } from "./regions"; import type { Region } from "./regions";
export async function searchClansAcrossRegions(search: string, limit = 25) { export async function searchClansAcrossRegions(search: string, limit = 25) {
const trimmed = search.trim(); const trimmed = search.trim();
@@ -1,5 +1,5 @@
import { context } from "../blitzkit/context"; import { context } from "../blitzkit/context";
import { Region } from "./regions"; import { type Region } from "./regions";
import { regionToRegionSubdomain } from "./regionToRegionSubdomain"; import { regionToRegionSubdomain } from "./regionToRegionSubdomain";
type CurrentRatingPlayerSearch = Record< type CurrentRatingPlayerSearch = Record<
@@ -1,6 +1,6 @@
import { fetchBlitz } from '../fetchBlitz'; import { fetchBlitz } from "../fetchBlitz";
import { Region } from '../regions'; import type { Region } from "../regions";
import { usernamePattern } from './constants'; import { usernamePattern } from "./constants";
export interface AccountListItem { export interface AccountListItem {
nickname: string; nickname: string;
@@ -19,7 +19,7 @@ export async function searchPlayersAcrossRegions(search: string, limit = 25) {
if (usernamePattern.test(trimmed)) { if (usernamePattern.test(trimmed)) {
return ( return (
await Promise.all([ await Promise.all([
fetchBlitz<AccountList>('com', 'account/list', { fetchBlitz<AccountList>("com", "account/list", {
search, search,
limit: normalizedLimit, limit: normalizedLimit,
}).then( }).then(
@@ -27,10 +27,10 @@ export async function searchPlayersAcrossRegions(search: string, limit = 25) {
value && value &&
value.map((account) => ({ value.map((account) => ({
...account, ...account,
region: 'com' as Region, region: "com" as Region,
})), }))
), ),
fetchBlitz<AccountList>('eu', 'account/list', { fetchBlitz<AccountList>("eu", "account/list", {
search, search,
limit: normalizedLimit, limit: normalizedLimit,
}).then( }).then(
@@ -38,10 +38,10 @@ export async function searchPlayersAcrossRegions(search: string, limit = 25) {
value && value &&
value.map((account) => ({ value.map((account) => ({
...account, ...account,
region: 'eu' as Region, region: "eu" as Region,
})), }))
), ),
fetchBlitz<AccountList>('asia', 'account/list', { fetchBlitz<AccountList>("asia", "account/list", {
search, search,
limit: normalizedLimit, limit: normalizedLimit,
}).then( }).then(
@@ -49,8 +49,8 @@ export async function searchPlayersAcrossRegions(search: string, limit = 25) {
value && value &&
value.map((account) => ({ value.map((account) => ({
...account, ...account,
region: 'asia' as Region, region: "asia" as Region,
})), }))
), ),
]) ])
) )
@@ -61,4 +61,4 @@ export async function searchPlayersAcrossRegions(search: string, limit = 25) {
} }
} }
export * from './constants'; export * from "./constants";
@@ -1,6 +1,6 @@
import { emptyAllStats } from '../../blitz/constants'; import { emptyAllStats } from '../../blitz/constants';
import { Samples } from '../../protos'; import { Samples } from '../../protos';
import { BlitzkitStats } from '../../statistics'; import type { BlitzkitStats } from '../../statistics';
export const emptyAverageDefinitionsAllStats: BlitzkitStats = { export const emptyAverageDefinitionsAllStats: BlitzkitStats = {
...emptyAllStats, ...emptyAllStats,
@@ -1,4 +1,4 @@
import { Region } from "../blitz/regions"; import type { Region } from "../blitz/regions";
import { RatingLeaderboard } from "../protos"; import { RatingLeaderboard } from "../protos";
import { asset } from "./asset"; import { asset } from "./asset";
+1 -1
View File
@@ -1,4 +1,4 @@
import { MessageFns } from '../protos'; import type { MessageFns } from '../protos';
export async function fetchPB<Type>(url: string, message: MessageFns<Type>) { export async function fetchPB<Type>(url: string, message: MessageFns<Type>) {
const response = await fetch(url); const response = await fetch(url);
@@ -1,10 +1,10 @@
import { calculateWN8 } from '../calculateWN8'; import { calculateWN8 } from "../calculateWN8";
import { import {
BlitzkitStats, type BlitzkitStats,
CompositeStats, type CompositeStats,
compositeStatsFormatting, compositeStatsFormatting,
CompositeStatsKey, type CompositeStatsKey,
} from './constants'; } from "./constants";
export function compositeStats(stats: BlitzkitStats, average: BlitzkitStats) { export function compositeStats(stats: BlitzkitStats, average: BlitzkitStats) {
return { return {
@@ -52,9 +52,9 @@ export function compositeStats(stats: BlitzkitStats, average: BlitzkitStats) {
export function formatCompositeStat( export function formatCompositeStat(
value: number, value: number,
key: CompositeStatsKey, key: CompositeStatsKey,
composite: CompositeStats, composite: CompositeStats
) { ) {
if (composite.cumulative_battles === 0) return '--'; if (composite.cumulative_battles === 0) return "--";
const formatting = compositeStatsFormatting[key]; const formatting = compositeStatsFormatting[key];
const resolvedValue = (formatting.coefficient ?? 1) * value; const resolvedValue = (formatting.coefficient ?? 1) * value;
@@ -62,7 +62,7 @@ export function formatCompositeStat(
formatting.localeFormat formatting.localeFormat
? Math.round(resolvedValue).toLocaleString() ? Math.round(resolvedValue).toLocaleString()
: resolvedValue.toFixed(formatting.fixed) : resolvedValue.toFixed(formatting.fixed)
}${formatting.unit ?? ''}`; }${formatting.unit ?? ""}`;
} }
export * from './constants'; export * from "./constants";
@@ -1,8 +1,8 @@
import { IndividualTankStats, emptyIndividualTankStats } from '../types'; import { type IndividualTankStats, emptyIndividualTankStats } from "../types";
export function deltaTankStats( export function deltaTankStats(
tanksA: IndividualTankStats[], tanksA: IndividualTankStats[],
tanksB: IndividualTankStats[], tanksB: IndividualTankStats[]
) { ) {
return tanksB return tanksB
.map((b) => { .map((b) => {
@@ -1,5 +1,5 @@
import { fetchTankDefinitions } from '../blitzkit'; import { fetchTankDefinitions } from '../blitzkit';
import { BlitzStats } from './compositeStats/constants'; import type { BlitzStats } from './compositeStats/constants';
export async function getTierWeights( export async function getTierWeights(
stats: Record<number, BlitzStats>, stats: Record<number, BlitzStats>,
+1 -1
View File
@@ -1,5 +1,5 @@
import { emptyAllStats } from '../blitz'; import { emptyAllStats } from '../blitz';
import { BlitzStats } from '../statistics'; import type { BlitzStats } from '../statistics';
export interface IndividualTankStats { export interface IndividualTankStats {
all: BlitzStats; all: BlitzStats;
+1 -1
View File
@@ -1,5 +1,5 @@
import locales from "../locales.json"; import locales from "../locales.json";
import { BlitzKitStrings, STRINGS } from "./strings"; import { type BlitzKitStrings, STRINGS } from "./strings";
export function wrapper(slicer: (strings: BlitzKitStrings) => string) { export function wrapper(slicer: (strings: BlitzKitStrings) => string) {
const defaultString = slicer(STRINGS[locales.default] as BlitzKitStrings); const defaultString = slicer(STRINGS[locales.default] as BlitzKitStrings);
+3 -3
View File
@@ -1,10 +1,10 @@
import { import {
AverageDefinitions, AverageDefinitions,
AverageDefinitionsEntry, AverageDefinitionsEntry,
AverageDefinitionsManifest, type AverageDefinitionsManifest,
IndividualTankStats, type IndividualTankStats,
REGIONS, REGIONS,
Region, type Region,
Samples, Samples,
averageDefinitionsAllStatsKeys, averageDefinitionsAllStatsKeys,
emptySamples, emptySamples,
@@ -2,7 +2,7 @@ import { BLITZKIT_TANK_ICON_SIZE, fetchTankDefinitions } from "@blitzkit/core";
import { launch } from "puppeteer"; import { launch } from "puppeteer";
import sharp from "sharp"; import sharp from "sharp";
import { commitAssets } from "../core/github/commitAssets"; import { commitAssets } from "../core/github/commitAssets";
import { FileChange } from "../core/github/commitMultipleFiles"; import { type FileChange } from "../core/github/commitMultipleFiles";
export async function blitzkitTankIcons() { export async function blitzkitTankIcons() {
console.log("Building blitzkit tank icons..."); console.log("Building blitzkit tank icons...");