feat: filter strings

This commit is contained in:
TrèsAbhi committed 2024-03-07 13:49:38 -06:00
1 parent 935c578ef6
commit b60f8bfd57
12 files changed
+187 -128

No files matched your search

+1 -15
View File
@@ -34,7 +34,6 @@ import {
import { DATA, POI } from './constants'; import { DATA, POI } from './constants';
import { TankParameters } from './tankIcons'; import { TankParameters } from './tankIcons';
type BlitzTankType = 'AT-SPG' | 'lightTank' | 'mediumTank' | 'heavyTank';
interface Strings { interface Strings {
[key: string]: string; [key: string]: string;
} }
@@ -306,19 +305,6 @@ type ConsumablesVehicleFilter =
| { name: string } | { name: string }
| { extendedTags: string }; | { extendedTags: string };
const consumableProvisionEffectSuffixes = [
'Increase',
'Factor',
'Bias',
'Coef',
'Percent',
];
const blitzTankTypeToBlitzkrieg: Record<BlitzTankType, TankType> = {
'AT-SPG': 'tankDestroyer',
lightTank: 'light',
mediumTank: 'medium',
heavyTank: 'heavy',
};
const blitzShellKindToBLitzkrieg: Record<ShellKind, ShellType> = { const blitzShellKindToBLitzkrieg: Record<ShellKind, ShellType> = {
ARMOR_PIERCING: 'ap', ARMOR_PIERCING: 'ap',
ARMOR_PIERCING_CR: 'ap_cr', ARMOR_PIERCING_CR: 'ap_cr',
@@ -502,7 +488,7 @@ export async function definitions(production: boolean) {
? 'premium' ? 'premium'
: 'researchable', : 'researchable',
tier: tank.level as Tier, tier: tank.level as Tier,
type: blitzTankTypeToBlitzkrieg[tankTags[0] as BlitzTankType], type: tankTags[0] as TankType,
testing: tankTags.includes('testTank') ? true : undefined, testing: tankTags.includes('testTank') ? true : undefined,
price: tankPrice, price: tankPrice,
camouflage: { camouflage: {
@@ -136,12 +136,12 @@ export function Characteristics() {
]); ]);
const enginePowerCoefficient = coefficient( const enginePowerCoefficient = coefficient(
[ [
hasEngineAccelerator && (tank.type === 'light' || tank.type === 'medium'), hasEngineAccelerator && (tank.type === 'lightTank' || tank.type === 'mediumTank'),
0.05, 0.05,
], ],
[ [
hasEngineAccelerator && hasEngineAccelerator &&
(tank.type === 'heavy' || tank.type === 'tankDestroyer'), (tank.type === 'heavyTank' || tank.type === 'AT-SPG'),
0.07, 0.07,
], ],
[hasEnginePowerBoost, 0.2], [hasEnginePowerBoost, 0.2],
@@ -163,7 +163,7 @@ export function Characteristics() {
const viewRangeCoefficient = const viewRangeCoefficient =
coefficient([ coefficient([
hasImprovedOptics, hasImprovedOptics,
tank.type === 'tankDestroyer' ? 0.05 : tank.type === 'heavy' ? 0.07 : 0.1, tank.type === 'AT-SPG' ? 0.05 : tank.type === 'heavyTank' ? 0.07 : 0.1,
]) * coefficient([true, progressiveStat(commanderMastery)]); ]) * coefficient([true, progressiveStat(commanderMastery)]);
const fireChanceCoefficient = coefficient([hasProtectiveKit, -0.2]); const fireChanceCoefficient = coefficient([hasProtectiveKit, -0.2]);
@@ -180,17 +180,17 @@ export function Characteristics() {
const camouflageSumMoving = sum( const camouflageSumMoving = sum(
[ [
hasCamouflageNet, hasCamouflageNet,
tank.type === 'heavy' tank.type === 'heavyTank'
? 0.03 ? 0.03
: tank.type === 'tankDestroyer' : tank.type === 'AT-SPG'
? 0.07 ? 0.07
: 0.05, : 0.05,
], ],
[ [
camouflage, camouflage,
tank.type === 'tankDestroyer' tank.type === 'AT-SPG'
? 0.04 ? 0.04
: tank.type === 'heavy' : tank.type === 'heavyTank'
? 0.03 ? 0.03
: 0.02, : 0.02,
], ],
@@ -199,17 +199,17 @@ export function Characteristics() {
[ [
hasCamouflageNet, hasCamouflageNet,
2 * 2 *
(tank.type === 'heavy' (tank.type === 'heavyTank'
? 0.03 ? 0.03
: tank.type === 'tankDestroyer' : tank.type === 'AT-SPG'
? 0.07 ? 0.07
: 0.05), : 0.05),
], ],
[ [
camouflage, camouflage,
tank.type === 'tankDestroyer' tank.type === 'AT-SPG'
? 0.04 ? 0.04
: tank.type === 'heavy' : tank.type === 'heavyTank'
? 0.03 ? 0.03
: 0.02, : 0.02,
], ],
@@ -15,7 +15,7 @@ import {
} from '@radix-ui/themes'; } from '@radix-ui/themes';
import { go } from 'fuzzysort'; import { go } from 'fuzzysort';
import { use, useEffect, useMemo, useRef, useState } from 'react'; import { use, useEffect, useMemo, useRef, useState } from 'react';
import { TankType, TreeType } from '../../../../../components/Tanks'; import { TANK_TYPES, TreeType } from '../../../../../components/Tanks';
import { resolveNearPenetration } from '../../../../../core/blitz/resolveNearPenetration'; import { resolveNearPenetration } from '../../../../../core/blitz/resolveNearPenetration';
import { asset } from '../../../../../core/blitzkrieg/asset'; import { asset } from '../../../../../core/blitzkrieg/asset';
import { modelDefinitions } from '../../../../../core/blitzkrieg/modelDefinitions'; import { modelDefinitions } from '../../../../../core/blitzkrieg/modelDefinitions';
@@ -49,7 +49,6 @@ interface TankSearchProps {
onSelect?: (tank: TankDefinition) => void; onSelect?: (tank: TankDefinition) => void;
} }
const tankTypeOrder: TankType[] = ['light', 'medium', 'heavy', 'tankDestroyer'];
const treeTypeOrder: TreeType[] = ['researchable', 'premium', 'collector']; const treeTypeOrder: TreeType[] = ['researchable', 'premium', 'collector'];
export function TankSearch({ compact, onSelect = () => {} }: TankSearchProps) { export function TankSearch({ compact, onSelect = () => {} }: TankSearchProps) {
@@ -70,7 +69,7 @@ export function TankSearch({ compact, onSelect = () => {} }: TankSearchProps) {
) )
.sort( .sort(
(a, b) => (a, b) =>
(tankTypeOrder.indexOf(a.type) - tankTypeOrder.indexOf(b.type)) * (TANK_TYPES.indexOf(a.type) - TANK_TYPES.indexOf(b.type)) *
(sort.direction === 'descending' ? -1 : 1), (sort.direction === 'descending' ? -1 : 1),
) )
.sort( .sort(
+6 -9
View File
@@ -1,4 +1,4 @@
import { Locale, SlashCommandBuilder } from 'discord.js'; import { Locale } from 'discord.js';
import CommandWrapper from '../components/CommandWrapper'; import CommandWrapper from '../components/CommandWrapper';
import GenericAllStats from '../components/GenericAllStats'; import GenericAllStats from '../components/GenericAllStats';
import NoData from '../components/NoData'; import NoData from '../components/NoData';
@@ -16,6 +16,7 @@ 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 { getCustomPeriodParams } from '../core/discord/getCustomPeriodParams'; import { getCustomPeriodParams } from '../core/discord/getCustomPeriodParams';
import { getFiltersFromButton } from '../core/discord/getFiltersFromButton'; import { getFiltersFromButton } from '../core/discord/getFiltersFromButton';
import { getFiltersFromCommand } from '../core/discord/getFiltersFromCommand'; import { getFiltersFromCommand } from '../core/discord/getFiltersFromCommand';
@@ -73,18 +74,14 @@ async function render(
export const fullStatsCommand = new Promise<CommandRegistry>( export const fullStatsCommand = new Promise<CommandRegistry>(
async (resolve) => { async (resolve) => {
const command = await addPeriodicFilterOptions(
new SlashCommandBuilder()
.setName('full-stats')
.setDescription('Full in-game statistics'),
(option) => option.addStringOption(addUsernameChoices),
);
resolve({ resolve({
inProduction: true, inProduction: true,
inPublic: true, inPublic: true,
command, command: await addPeriodicFilterOptions(
createLocalizedCommand('full-stats'),
(option) => option.addStringOption(addUsernameChoices),
),
async handler(interaction) { async handler(interaction) {
const player = await resolvePlayerFromCommand(interaction); const player = await resolvePlayerFromCommand(interaction);
+3 -3
View File
@@ -1,5 +1,5 @@
import { SlashCommandBuilder } from 'discord.js'; import { SlashCommandBuilder } from 'discord.js';
import { encyclopediaInfo } from '../core/blitz/encyclopediaInfo'; import { NATIONS } from '../core/blitzkrieg/tankDefinitions';
import { getBlitzStarsLinkButton } from '../core/blitzstars/getBlitzStarsLinkButton'; import { getBlitzStarsLinkButton } from '../core/blitzstars/getBlitzStarsLinkButton';
import { addFilterOptions } from '../core/discord/addFilterOptions'; import { addFilterOptions } from '../core/discord/addFilterOptions';
import addUsernameChoices from '../core/discord/addUsernameChoices'; import addUsernameChoices from '../core/discord/addUsernameChoices';
@@ -18,12 +18,12 @@ import { CommandRegistry } from '../events/interactionCreate';
import { renderBreakdown } from './breakdown'; import { renderBreakdown } from './breakdown';
export const todayCommand = new Promise<CommandRegistry>(async (resolve) => { export const todayCommand = new Promise<CommandRegistry>(async (resolve) => {
const awaitedEncyclopediaInfo = await encyclopediaInfo; const nations = await NATIONS;
const command = addFilterOptions( const command = addFilterOptions(
new SlashCommandBuilder() new SlashCommandBuilder()
.setName('today') .setName('today')
.setDescription("Today's played tanks and statistics"), .setDescription("Today's played tanks and statistics"),
awaitedEncyclopediaInfo, nations,
).addStringOption(addUsernameChoices); ).addStringOption(addUsernameChoices);
resolve({ resolve({
+4 -4
View File
@@ -6,10 +6,10 @@ import {
import { theme } from '../../../stitches.config'; import { theme } from '../../../stitches.config';
export const TANK_TYPES = [ export const TANK_TYPES = [
'light', 'lightTank',
'medium', 'mediumTank',
'heavy', 'heavyTank',
'tankDestroyer', 'AT-SPG',
] as const; ] as const;
export const TREE_TYPES = ['researchable', 'premium', 'collector'] as const; export const TREE_TYPES = ['researchable', 'premium', 'collector'] as const;
+12 -12
View File
@@ -181,24 +181,24 @@ export const tankNames = tanksDefinitionsArray.then((tanks) =>
); );
export const TANK_ICONS: Record<TankType, string> = { export const TANK_ICONS: Record<TankType, string> = {
tankDestroyer: 'https://i.imgur.com/BIHSEH0.png', 'AT-SPG': 'https://i.imgur.com/BIHSEH0.png',
light: 'https://i.imgur.com/CSNha5V.png', lightTank: 'https://i.imgur.com/CSNha5V.png',
medium: 'https://i.imgur.com/wvf3ltm.png', mediumTank: 'https://i.imgur.com/wvf3ltm.png',
heavy: 'https://i.imgur.com/ECeqlZa.png', heavyTank: 'https://i.imgur.com/ECeqlZa.png',
}; };
export const TANK_ICONS_PREMIUM: Record<TankType, string> = { export const TANK_ICONS_PREMIUM: Record<TankType, string> = {
tankDestroyer: 'https://i.imgur.com/TCu3EdR.png', 'AT-SPG': 'https://i.imgur.com/TCu3EdR.png',
light: 'https://i.imgur.com/zdkpTRb.png', lightTank: 'https://i.imgur.com/zdkpTRb.png',
medium: 'https://i.imgur.com/3z7eHX6.png', mediumTank: 'https://i.imgur.com/3z7eHX6.png',
heavy: 'https://i.imgur.com/P3vbmyA.png', heavyTank: 'https://i.imgur.com/P3vbmyA.png',
}; };
export const TANK_ICONS_COLLECTOR: Record<TankType, string> = { export const TANK_ICONS_COLLECTOR: Record<TankType, string> = {
tankDestroyer: 'https://i.imgur.com/WTjeirB.png', 'AT-SPG': 'https://i.imgur.com/WTjeirB.png',
light: 'https://i.imgur.com/EwhtKkU.png', lightTank: 'https://i.imgur.com/EwhtKkU.png',
medium: 'https://i.imgur.com/u8YDMBh.png', mediumTank: 'https://i.imgur.com/u8YDMBh.png',
heavy: 'https://i.imgur.com/8xRf3nc.png', heavyTank: 'https://i.imgur.com/8xRf3nc.png',
}; };
export const TIERS = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] as const; export const TIERS = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] as const;
+102 -54
View File
@@ -1,60 +1,108 @@
import { SlashCommandBuilder, SlashCommandSubcommandBuilder } from 'discord.js'; import {
import { TREE_TYPE_NAMES, TreeType } from '../../components/Tanks'; APIApplicationCommandOptionChoice,
import { EncyclopediaInfo } from '../blitz/encyclopediaInfo'; Locale,
SlashCommandBuilder,
SlashCommandSubcommandBuilder,
} from 'discord.js';
import { TANK_TYPES, TREE_TYPES } from '../../components/Tanks';
import { translator } from '../localization/translator';
import addTankChoices from './addTankChoices'; import addTankChoices from './addTankChoices';
import addTierChoices from './addTierChoices'; import addTierChoices from './addTierChoices';
import { localizationObject } from './localizationObject';
export function addFilterOptions< export function addFilterOptions<
Option extends SlashCommandBuilder | SlashCommandSubcommandBuilder, Option extends SlashCommandBuilder | SlashCommandSubcommandBuilder,
>(option: Option, encyclopediaInfo: EncyclopediaInfo) { >(option: Option, nations: string[]) {
return option const { translate } = translator(Locale.EnglishUS);
.addStringOption((option) =>
option return (
.setName('nation') option
.setDescription('Nation') .addStringOption((option) =>
.addChoices( option
...Object.entries(encyclopediaInfo.vehicle_nations).map( .setName(translate('bot.common.options.filters.nation'))
([type, name]) => ({ name, value: type }), .setNameLocalizations(
), localizationObject('bot.common.options.filters.nation'),
) )
.setRequired(false), .setDescription(
) translate('bot.common.options.filters.nation.description'),
.addStringOption((option) => addTierChoices(option).setRequired(false)) )
.addStringOption((option) => .setDescriptionLocalizations(
option localizationObject('bot.common.options.filters.nation.description'),
.setName('tank-type') )
.setDescription('Tank type') .addChoices(
.addChoices( ...nations.map(
...Object.entries(encyclopediaInfo.vehicle_types).map( (nation) =>
([type, name]) => ({ ({
name: name.replace(' Tank', ''), value: nation,
value: type, name: translate(`common.nations.${nation}`),
}), name_localizations: localizationObject(
), `common.nations.${nation}`,
) ),
.setRequired(false), }) satisfies APIApplicationCommandOptionChoice,
) ),
.addStringOption((option) => )
option .setRequired(false),
.setName('tree-type') )
.setDescription('Tech tree type') .addStringOption((option) => addTierChoices(option).setRequired(false))
.addChoices( .addStringOption((option) =>
{ option
name: TREE_TYPE_NAMES['researchable'], .setName(translate('bot.common.options.filters.tank_type'))
value: 'researchable' satisfies TreeType, .setNameLocalizations(
}, localizationObject('bot.common.options.filters.tank_type'),
{ )
name: TREE_TYPE_NAMES.premium, .setDescription(
value: 'premium' satisfies TreeType, translate('bot.common.options.filters.tank_type.description'),
}, )
{ .setDescriptionLocalizations(
name: TREE_TYPE_NAMES.collector, localizationObject(
value: 'collector' satisfies TreeType, 'bot.common.options.filters.tank_type.description',
}, ),
) )
.setRequired(false), .addChoices(
) ...TANK_TYPES.map(
.addStringOption((option) => (tankType) =>
addTankChoices(option).setRequired(false), ({
) as Option; value: tankType,
name: translate(`common.tank_type_short.${tankType}`),
name_localizations: localizationObject(
`common.tank_type_short.${tankType}`,
),
}) satisfies APIApplicationCommandOptionChoice,
),
)
.setRequired(false),
)
.addStringOption((option) =>
option
.setName(translate('bot.common.options.filters.tree_type'))
.setNameLocalizations(
localizationObject('bot.common.options.filters.tree_type'),
)
.setDescription(
translate('bot.common.options.filters.tree_type.description'),
)
.setDescriptionLocalizations(
localizationObject(
'bot.common.options.filters.tree_type.description',
),
)
.addChoices(
...TREE_TYPES.map(
(treeType) =>
({
value: treeType,
name: translate(`common.tree_type.${treeType}`),
name_localizations: localizationObject(
`common.tree_type.${treeType}`,
),
}) satisfies APIApplicationCommandOptionChoice,
),
)
.setRequired(false),
)
// TODO: somehow localize this?
.addStringOption((option) =>
addTankChoices(option).setRequired(false),
) as Option
);
} }
+5 -5
View File
@@ -3,7 +3,7 @@ import {
SlashCommandSubcommandBuilder, SlashCommandSubcommandBuilder,
SlashCommandSubcommandGroupBuilder, SlashCommandSubcommandGroupBuilder,
} from 'discord.js'; } from 'discord.js';
import { encyclopediaInfo } from '../blitz/encyclopediaInfo'; import { NATIONS } from '../blitzkrieg/tankDefinitions';
import { addFilterOptions } from './addFilterOptions'; import { addFilterOptions } from './addFilterOptions';
import { addPeriodSubCommands } from './addPeriodSubCommands'; import { addPeriodSubCommands } from './addPeriodSubCommands';
@@ -15,10 +15,10 @@ export default async function addPeriodicFilterOptions<
option: SlashCommandSubcommandBuilder, option: SlashCommandSubcommandBuilder,
) => SlashCommandSubcommandBuilder = (option) => option, ) => SlashCommandSubcommandBuilder = (option) => option,
): Promise<OptionType> { ): Promise<OptionType> {
const awaitedEncyclopediaInfo = await encyclopediaInfo; const nations = await NATIONS;
addPeriodSubCommands(option, (option) => { addPeriodSubCommands(option, (option) =>
return addFilterOptions(extra(option), awaitedEncyclopediaInfo); addFilterOptions(extra(option), nations),
}); );
return option; return option;
} }
+11 -3
View File
@@ -1,9 +1,17 @@
import { SlashCommandStringOption } from 'discord.js'; import { Locale, SlashCommandStringOption } from 'discord.js';
import { translator } from '../localization/translator';
import { localizationObject } from './localizationObject';
export default function addTankChoices(option: SlashCommandStringOption) { export default function addTankChoices(option: SlashCommandStringOption) {
const { translate } = translator(Locale.EnglishUS);
return option return option
.setName('tank') .setName(translate('bot.common.options.tank'))
.setDescription('The tank to get stats for') .setNameLocalizations(localizationObject('bot.common.options.tank'))
.setDescription(translate('bot.common.options.tank.description'))
.setDescriptionLocalizations(
localizationObject('bot.common.options.tank.description'),
)
.setAutocomplete(true) .setAutocomplete(true)
.setRequired(true); .setRequired(true);
} }
+10 -9
View File
@@ -23,23 +23,24 @@ export function createLocalizedCommand(
| CreateLocalizedCommandSubcommand[] | CreateLocalizedCommandSubcommand[]
| CreateLocalizedCommandSubcommandGroup[], | CreateLocalizedCommandSubcommandGroup[],
) { ) {
const commandPathItem = command.replaceAll('-', '_');
const { translate } = translator(Locale.EnglishUS); const { translate } = translator(Locale.EnglishUS);
const slashCommand = new SlashCommandBuilder() const slashCommand = new SlashCommandBuilder()
.setName(command) .setName(command)
.setNameLocalizations(localizationObject(`bot.commands.${command}`)) .setNameLocalizations(localizationObject(`bot.commands.${commandPathItem}`))
.setDescription(translate(`bot.commands.${command}.description`)) .setDescription(translate(`bot.commands.${commandPathItem}.description`))
.setDescriptionLocalizations( .setDescriptionLocalizations(
localizationObject(`bot.commands.${command}.description`), localizationObject(`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(
`bot.commands.${command}.subcommands.${subItem.subcommand}`, `bot.commands.${commandPathItem}.subcommands.${subItem.subcommand}`,
); );
const subcommandDescriptionLocalizations = localizationObject( const subcommandDescriptionLocalizations = localizationObject(
`bot.commands.${command}.subcommands.${subItem.subcommand}.description`, `bot.commands.${commandPathItem}.subcommands.${subItem.subcommand}.description`,
); );
slashCommand.addSubcommand((option) => { slashCommand.addSubcommand((option) => {
@@ -50,17 +51,17 @@ export function createLocalizedCommand(
.setNameLocalizations(subcommandNameLocalizations) .setNameLocalizations(subcommandNameLocalizations)
.setDescription( .setDescription(
translate( translate(
`bot.commands.${command}.subcommands.${subItem.subcommand}.description`, `bot.commands.${commandPathItem}.subcommands.${subItem.subcommand}.description`,
), ),
) )
.setDescriptionLocalizations(subcommandDescriptionLocalizations); .setDescriptionLocalizations(subcommandDescriptionLocalizations);
}); });
} else { } else {
const subcommandNameLocalizations = localizationObject( const subcommandNameLocalizations = localizationObject(
`bot.commands.${command}.groups.${subItem.group}`, `bot.commands.${commandPathItem}.groups.${subItem.group}`,
); );
const subcommandDescriptionLocalizations = localizationObject( const subcommandDescriptionLocalizations = localizationObject(
`bot.commands.${command}.groups.${subItem.group}.description`, `bot.commands.${commandPathItem}.groups.${subItem.group}.description`,
); );
slashCommand.addSubcommandGroup((option) => { slashCommand.addSubcommandGroup((option) => {
@@ -71,7 +72,7 @@ export function createLocalizedCommand(
.setNameLocalizations(subcommandNameLocalizations) .setNameLocalizations(subcommandNameLocalizations)
.setDescription( .setDescription(
translate( translate(
`bot.commands.${command}.groups.${subItem.group}.description`, `bot.commands.${commandPathItem}.groups.${subItem.group}.description`,
), ),
) )
.setDescriptionLocalizations(subcommandDescriptionLocalizations); .setDescriptionLocalizations(subcommandDescriptionLocalizations);
+20
View File
@@ -84,6 +84,26 @@
"clan": { "clan": {
"$": "clan", "$": "clan",
"description": "The clan name or tag" "description": "The clan name or tag"
},
"tank": {
"$": "tank",
"description": "The tank to get stats for"
},
"filters": {
"nation": {
"$": "nation",
"description": "Nation"
},
"tank_type": {
"$": "tank-type",
"description": "Tank type"
},
"tree_type": {
"$": "tree-type",
"description": "Tree type"
}
} }
}, },