mirror of
https://github.com/Sendouc/sendou.ink.git
synced 2026-08-02 18:01:29 -05:00
105 lines
3.1 KiB
TypeScript
105 lines
3.1 KiB
TypeScript
import {
|
|
IN_GAME_NAME,
|
|
sanitizeInGameName,
|
|
} from "~/features/user-page/in-game-name";
|
|
import { abilities } from "~/modules/in-game-lists/abilities";
|
|
import {
|
|
clothesGearIds,
|
|
headGearIds,
|
|
shoesGearIds,
|
|
} from "~/modules/in-game-lists/gear-ids";
|
|
import { rankedModesShort } from "~/modules/in-game-lists/modes";
|
|
import { stageIds } from "~/modules/in-game-lists/stage-ids";
|
|
import type {
|
|
Ability,
|
|
BuildAbilitiesTuple,
|
|
MainWeaponId,
|
|
ModeWithStage,
|
|
} from "~/modules/in-game-lists/types";
|
|
import {
|
|
canonicalWeaponSplId,
|
|
mainWeaponIds,
|
|
} from "~/modules/in-game-lists/weapon-ids";
|
|
import invariant from "~/utils/invariant";
|
|
import { faker } from "./faker";
|
|
|
|
const STACKABLE_ABILITIES = abilities
|
|
.filter((ability) => ability.type === "STACKABLE")
|
|
.map((ability) => ability.name);
|
|
|
|
export function mainWeapon(): MainWeaponId {
|
|
return faker.helpers.arrayElement(mainWeaponIds);
|
|
}
|
|
|
|
const CANONICAL_MAIN_WEAPON_IDS = mainWeaponIds.filter(
|
|
(id) => canonicalWeaponSplId(id) === id,
|
|
);
|
|
|
|
/** `count` main weapons distinct down to their canonical id, e.g. a weapon pool or
|
|
* a multi-weapon build's. */
|
|
export function mainWeapons(count: number): MainWeaponId[] {
|
|
return faker.helpers.arrayElements(CANONICAL_MAIN_WEAPON_IDS, count);
|
|
}
|
|
|
|
/** The gear of a build: a head, clothes and shoes item. */
|
|
export function gear() {
|
|
return {
|
|
headGearSplId: faker.helpers.arrayElement(headGearIds),
|
|
clothesGearSplId: faker.helpers.arrayElement(clothesGearIds),
|
|
shoesGearSplId: faker.helpers.arrayElement(shoesGearIds),
|
|
};
|
|
}
|
|
|
|
/**
|
|
* An in-game name with its discriminator, e.g. `Agent 4#1859`. `name` is sanitized and
|
|
* truncated the way the real thing is, so the result always passes `inGameNameIsValid`.
|
|
*/
|
|
export function inGameName(name = faker.person.firstName()): string {
|
|
const discriminator = faker.string.alphanumeric({
|
|
length: {
|
|
min: IN_GAME_NAME.DISCRIMINATOR_MIN_LENGTH,
|
|
max: IN_GAME_NAME.DISCRIMINATOR_MAX_LENGTH,
|
|
},
|
|
casing: "lower",
|
|
});
|
|
|
|
return `${sanitizedName(name)}#${discriminator}`;
|
|
}
|
|
|
|
/**
|
|
* A map list of `count` maps, rotating through the ranked modes and never repeating
|
|
* a stage, the way a real one looks. Callers add whatever `source` their domain uses.
|
|
*/
|
|
export function mapList(count: number): ModeWithStage[] {
|
|
const stages = faker.helpers.arrayElements(stageIds, count);
|
|
|
|
return stages.map((stageId, i) => ({
|
|
mode: rankedModesShort[i % rankedModesShort.length],
|
|
stageId,
|
|
}));
|
|
}
|
|
|
|
/**
|
|
* The abilities of a build: a main and three subs per gear slot. All of them are
|
|
* stackable ones, which every slot allows.
|
|
*/
|
|
export function buildAbilities(): BuildAbilitiesTuple {
|
|
return [gearAbilities(), gearAbilities(), gearAbilities()];
|
|
}
|
|
|
|
function sanitizedName(name: string): string {
|
|
const characters = [...sanitizeInGameName(name)].slice(
|
|
0,
|
|
IN_GAME_NAME.NAME_MAX_LENGTH,
|
|
);
|
|
invariant(characters.length > 0, `No valid in-game name characters: ${name}`);
|
|
|
|
return characters.join("");
|
|
}
|
|
|
|
function gearAbilities(): [Ability, Ability, Ability, Ability] {
|
|
const draw = () => faker.helpers.arrayElement(STACKABLE_ABILITIES);
|
|
|
|
return [draw(), draw(), draw(), draw()];
|
|
}
|