95 lines
2.7 KiB
TypeScript
95 lines
2.7 KiB
TypeScript
export type ClockConnectTimeMode =
|
|
| 'random'
|
|
| 'whole-hour'
|
|
| 'half-hour'
|
|
| 'quarter-hour';
|
|
|
|
export interface ClockConnectProblem {
|
|
hour: number;
|
|
minute: number;
|
|
/** 格式化后的时间文本,如 "6:00" */
|
|
timeText: string;
|
|
}
|
|
|
|
export interface ClockConnectData {
|
|
/** 左侧钟表列表(按原始顺序) */
|
|
clocks: ClockConnectProblem[];
|
|
/** 右侧时间文本列表(打乱顺序) */
|
|
shuffledTimes: ClockConnectProblem[];
|
|
timeMode: ClockConnectTimeMode;
|
|
}
|
|
|
|
export const CLOCK_CONNECT_PROBLEM_COUNT = 6;
|
|
|
|
const MINUTES_BY_MODE: Record<
|
|
Exclude<ClockConnectTimeMode, 'random'>,
|
|
readonly number[]
|
|
> = {
|
|
'whole-hour': [0],
|
|
'half-hour': [30],
|
|
'quarter-hour': [15, 45],
|
|
};
|
|
|
|
function pickMinute(timeMode: ClockConnectTimeMode): 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;
|
|
}
|
|
|
|
function formatTime(hour: number, minute: number): string {
|
|
return `${hour}:${minute.toString().padStart(2, '0')}`;
|
|
}
|
|
|
|
/** Fisher-Yates shuffle */
|
|
function shuffle<T>(arr: T[]): T[] {
|
|
const result = [...arr];
|
|
for (let i = result.length - 1; i > 0; i--) {
|
|
const j = Math.floor(Math.random() * (i + 1));
|
|
[result[i], result[j]] = [result[j], result[i]];
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/** 生成一页 6 道时钟连线题,同一页内时刻不重复 */
|
|
export function generateClockConnectProblems(
|
|
timeMode: ClockConnectTimeMode,
|
|
): ClockConnectProblem[] {
|
|
const used = new Set<string>();
|
|
const problems: ClockConnectProblem[] = [];
|
|
let guard = 0;
|
|
|
|
while (problems.length < CLOCK_CONNECT_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, timeText: formatTime(hour, minute) });
|
|
}
|
|
|
|
return problems;
|
|
}
|
|
|
|
export function buildClockConnectData(
|
|
timeMode: ClockConnectTimeMode,
|
|
): ClockConnectData {
|
|
const clocks = generateClockConnectProblems(timeMode);
|
|
const shuffledTimes = shuffle(clocks);
|
|
|
|
return {
|
|
timeMode,
|
|
clocks,
|
|
shuffledTimes,
|
|
};
|
|
}
|
|
|
|
export const CLOCK_CONNECT_TIME_MODE_OPTIONS = [
|
|
{ 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' },
|
|
{ id: 'random' as const, label: '随机', subtitle: '整点/半点/刻钟' },
|
|
];
|