export type ClockReadingTimeMode = | 'random' | 'whole-hour' | 'half-hour' | 'quarter-hour'; export interface ClockProblem { hour: number; minute: number; } export interface ClockReadingData { problems: ClockProblem[]; timeMode: ClockReadingTimeMode; } export const CLOCK_PROBLEM_COUNT = 12; const MINUTES_BY_MODE: Record< Exclude, readonly number[] > = { 'whole-hour': [0], 'half-hour': [30], 'quarter-hour': [15, 45], }; function pickMinute(timeMode: ClockReadingTimeMode): number { if (timeMode === 'random') { return Math.floor(Math.random() * 60); } const pool = MINUTES_BY_MODE[timeMode]; return pool[Math.floor(Math.random() * pool.length)] ?? 0; } /** 生成一页 12 道钟表题,同一页内时刻不重复 */ export function generateClockProblems( timeMode: ClockReadingTimeMode, ): ClockProblem[] { const used = new Set(); const problems: ClockProblem[] = []; let guard = 0; while (problems.length < CLOCK_PROBLEM_COUNT && guard < 500) { guard += 1; const hour = Math.floor(Math.random() * 12) + 1; const minute = pickMinute(timeMode); const key = `${hour}:${minute}`; if (used.has(key)) continue; used.add(key); problems.push({ hour, minute }); } return problems; } export function buildClockReadingData( timeMode: ClockReadingTimeMode, ): ClockReadingData { return { timeMode, problems: generateClockProblems(timeMode), }; } export const CLOCK_TIME_MODE_OPTIONS = [ { id: 'random' as const, label: '随机', subtitle: '0–59 分均可' }, { id: 'whole-hour' as const, label: '整点', subtitle: '如 3:00' }, { id: 'half-hour' as const, label: '半点', subtitle: '如 6:30' }, { id: 'quarter-hour' as const, label: '刻钟', subtitle: '如 2:15、7:45' }, ];