import type { Choice } from '../types' export interface ChoiceTimerState { total: number remaining: number } type TimerUpdateCallback = (state: ChoiceTimerState) => void type TimeoutCallback = (choice: Choice) => void export class ChoiceSystem { private timerId: ReturnType | null = null private timeoutId: ReturnType | null = null private timeLimit = 0 private elapsed = 0 private tickMs = 100 private onUpdate: TimerUpdateCallback | null = null private onTimeout: TimeoutCallback | null = null start(choices: Choice[], onUpdate: TimerUpdateCallback, onTimeout: TimeoutCallback) { this.clear() const timed = choices.filter((c) => c.timeLimit && c.timeLimit > 0) if (timed.length === 0) return const maxLimit = Math.max(...timed.map((c) => c.timeLimit!)) this.timeLimit = maxLimit this.elapsed = 0 this.onUpdate = onUpdate this.onTimeout = onTimeout const state: ChoiceTimerState = { total: maxLimit, remaining: maxLimit } this.onUpdate(state) this.timerId = setInterval(() => { this.elapsed += this.tickMs const remaining = Math.max(0, this.timeLimit - this.elapsed) / 1000 const nextState: ChoiceTimerState = { total: this.timeLimit / 1000, remaining: Math.ceil(remaining * 10) / 10, } this.onUpdate?.(nextState) }, this.tickMs) this.timeoutId = setTimeout(() => { this.clear() // Pick the first choice as default on timeout if (choices.length > 0) { this.onTimeout?.(choices[0]) } }, this.timeLimit) } stop() { this.clear() } private clear() { if (this.timerId !== null) { clearInterval(this.timerId) this.timerId = null } if (this.timeoutId !== null) { clearTimeout(this.timeoutId) this.timeoutId = null } } destroy() { this.clear() this.onUpdate = null this.onTimeout = null } }