import { defaultSettings } from "./constants"; import type { AppSettings } from "./types"; export function shuffleArray(array: T[]) { const next = [...array]; for (let i = next.length - 1; i > 0; i -= 1) { const j = Math.floor(Math.random() * (i + 1)); [next[i], next[j]] = [next[j], next[i]]; } return next; } export function mergeSettings(settings: Partial): AppSettings { return { ttsVoice: settings.ttsVoice || defaultSettings.ttsVoice, ttsRate: settings.ttsRate || defaultSettings.ttsRate, scorePerCorrect: Number(settings.scorePerCorrect ?? defaultSettings.scorePerCorrect), scorePerWrong: Number(settings.scorePerWrong ?? defaultSettings.scorePerWrong), autoSpeak: settings.autoSpeak ?? defaultSettings.autoSpeak, wordDisplayMode: settings.wordDisplayMode === "capitalize" || settings.wordDisplayMode === "input" || settings.wordDisplayMode === "uppercase" ? settings.wordDisplayMode : defaultSettings.wordDisplayMode, pkWordCount: Math.max(0, Math.floor(Number(settings.pkWordCount ?? defaultSettings.pkWordCount))), pkOptionCount: normalizeOptionCount(Number(settings.pkOptionCount ?? defaultSettings.pkOptionCount)), }; } export function getFairRoundCount(availableCount: number, limit: number) { const requestedCount = limit > 0 ? Math.min(limit, availableCount) : availableCount; if (requestedCount < 2) return requestedCount; return requestedCount % 2 === 0 ? requestedCount : requestedCount - 1; } export function formatWordDisplay(text: string, mode: AppSettings["wordDisplayMode"]) { if (mode === "input") return text; if (mode === "capitalize") { return text .split(/(\s+)/) .map((part) => { if (/^\s+$/.test(part) || !part) return part; return part.charAt(0).toUpperCase() + part.slice(1).toLowerCase(); }) .join(""); } return text.toUpperCase(); } export function normalizeOptionCount(value: number) { const count = Math.floor(value); if (!Number.isFinite(count)) return defaultSettings.pkOptionCount; if (count < 2) return 2; if (count > 8) return 8; return count % 2 === 0 ? count : count + 1; } export function isImageSource(value: string) { return /^(https?:\/\/|\/|data:image\/)/i.test(value); }