62 lines
2.2 KiB
TypeScript
62 lines
2.2 KiB
TypeScript
import { defaultSettings } from "./constants";
|
|
import type { AppSettings } from "./types";
|
|
|
|
export function shuffleArray<T>(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>): 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);
|
|
}
|