import type { CharacterProfile } from "../app/types"; import { ArenaSimulation } from "../../server/arena-simulation.mjs"; import type { ArenaAuthoritativeSnapshot, ArenaCombatIntent, ArenaResult, ArenaRole, ArenaStageManifest } from "./arenaTypes"; interface PracticeOptions { character: CharacterProfile; role: ArenaRole; bracket: "2v2" | "3v3"; ruleset: "wow" | "coa" | "rom"; stage: ArenaStageManifest; difficulty: number; onSnapshot: (snapshot: ArenaAuthoritativeSnapshot) => void; onResult: (result: ArenaResult) => void; } function teamRoles(teamSize: number, playerRole?: ArenaRole): ArenaRole[] { const roles: ArenaRole[] = playerRole ? [playerRole] : []; if (!roles.includes("healer")) roles.push("healer"); while (roles.length < teamSize) roles.push("damage"); return roles; } export function createArenaPractice(options: PracticeOptions) { const id = `practice-${Date.now().toString(36)}`; const teamSize = options.bracket === "2v2" ? 2 : 3; const participants = [ ...teamRoles(teamSize, options.role).map((role, index) => ({ actorId: index === 0 ? "practice-player" : `practice-ally-${index}`, accountId: null, characterId: index === 0 ? options.character.id : null, name: index === 0 ? options.character.name : role === "healer" ? "Training Medic" : `Training Ally ${index}`, team: 0 as const, role, isBot: index !== 0, rating: options.difficulty, })), ...teamRoles(teamSize).map((role, index) => ({ actorId: `practice-enemy-${index}`, accountId: null, characterId: null, name: role === "healer" ? "Opponent Medic" : `Opponent ${index + 1}`, team: 1 as const, role, isBot: true, rating: options.difficulty, })), ]; const simulation = new ArenaSimulation({ id, stage: options.stage, bracket: options.bracket, mode: "practice", ruleset: options.ruleset, participants, onSnapshot: (snapshot) => options.onSnapshot({ ...snapshot, controlledActorId: "practice-player" }), onResult: (result) => options.onResult({ ...result, ratingUpdates: [] }), }); options.onSnapshot({ ...simulation.snapshot(), controlledActorId: "practice-player" }); let started = false; return { start() { if (started) return; started = true; simulation.resetPreparationClock(); simulation.start(); }, intent(intent: ArenaCombatIntent) { return simulation.receiveIntent("practice-player", intent); }, stop() { simulation.stop(); }, }; }