import { type BarkBattleSession,createBarkBattleSession } from '../domain/BarkBattleSession'; import type { MicrophoneFailureReason } from '../domain/BarkBattleTypes'; import { BarkDetector } from '../domain/BarkDetector'; import type { BarkBattleConfig } from './BarkBattleConfig'; export class BarkBattleController { private session: BarkBattleSession; private detector: BarkDetector; private sampleClockMs = 0; constructor(private config: BarkBattleConfig) { this.session = createBarkBattleSession(config); this.detector = this.createDetector(); } getSnapshot() { return this.session.snapshot; } updateConfig(config: BarkBattleConfig) { this.config = config; this.restart(); } finishNow() { if (this.session.snapshot.phase !== 'playing') { this.session = this.session.startMockRound(); } if (this.session.snapshot.phase === 'countdown') { this.session = this.session.tick(this.session.snapshot.countdownMs); } this.session = this.session.tick(this.session.snapshot.remainingMs + 1); } startWithMockInput() { this.session = createBarkBattleSession(this.config).startMockRound(); this.detector = this.createDetector(); this.sampleClockMs = 0; } submitMockSample(volume: number) { const events = this.detector.acceptSample({ atMs: this.sampleClockMs, volume }); for (const event of events) { this.session = this.session.applyPlayerBark(event); } } tick(deltaMs: number) { this.sampleClockMs += deltaMs; this.session = this.session.tick(deltaMs); } restart() { this.session = createBarkBattleSession(this.config); this.detector = this.createDetector(); this.sampleClockMs = 0; } failMicrophone(reason: MicrophoneFailureReason) { this.session = this.session.failMicrophone(reason); } private createDetector() { return new BarkDetector({ threshold: this.config.barkThreshold, minBarkGapMs: this.config.minBarkGapMs, minBarkDurationMs: this.config.minBarkDurationMs, maxBarkDurationMs: this.config.maxBarkDurationMs, }); } }