import * as z from "zod"; export interface CatalogConstellation { level: number; name: string; description: string; iconKey: string | null; } export interface CatalogTalent { type: "NA" | "E" | "Q"; name: string; description: string; iconKey: string | null; } const constellationSchema = z.object({ name: z.string(), description: z.string(), icon: z.string(), }); const skillSchema = z.object({ name: z.string(), description: z.string(), icon: z.string(), }); export const characterDetailSchema = z.object({ info: z.object({ element: z.string().optional(), weapon: z.string().optional(), }).nullish(), constellations: z.record(z.string(), constellationSchema).nullish(), skills: z.object({ normalattack: skillSchema.optional(), elementalskill: skillSchema.optional(), elementalburst: skillSchema.optional(), }).nullish(), }); export function cleanLunarisText(value: string): string { return value .replace(/\\n/gu, "\n") .replace(/\{\/?LINK[^}]*\}/gu, "") .replace(/<\/?[a-z]+(?:=[^>]*)?>/giu, "") .replace(/^"|"$/gu, "") .trim(); } export function avatarIconName(value: string): string { return value.replace(/^UI_Gacha_AvatarIcon_/u, "UI_AvatarIcon_"); } export function characterAssetName(value: string): string { return avatarIconName(value).replace(/^UI_AvatarIcon_/u, ""); } export function splashImageName(value: string): string { return `UI_Gacha_AvatarImg_${characterAssetName(value)}.png`; } export function nameCardImageName(value: string): string { return `UI_NameCardPic_${characterAssetName(value)}_P.png`; } export function supportsWeaponType( characterWeaponType: string | null | undefined, weaponType: string | null | undefined, ): boolean { return Boolean(characterWeaponType && characterWeaponType === weaponType); } export function constellationSnapshot( value: z.infer, iconKey: (icon: string) => string, ): CatalogConstellation[] { const result: CatalogConstellation[] = []; for (const index of Array.from({ length: 6 }, (_, itemIndex) => itemIndex)) { const level = index + 1; const item = value.constellations?.[`const${level}`]; if (!item) continue; result.push({ level, name: cleanLunarisText(item.name), description: cleanLunarisText(item.description), iconKey: iconKey(item.icon), }); } return result; } export function talentSnapshot( value: z.infer, iconKey: (icon: string) => string, ): CatalogTalent[] { const talents = [ ["NA", value.skills?.normalattack], ["E", value.skills?.elementalskill], ["Q", value.skills?.elementalburst], ] as const; return talents.flatMap(([type, talent]) => talent ? [{ type, name: cleanLunarisText(talent.name), description: cleanLunarisText(talent.description), iconKey: iconKey(talent.icon), }] : []); }