puzzle-trainer/stats.ts
2026-05-23 01:05:21 +00:00

46 lines
1.5 KiB
TypeScript

export interface GameStats {
streak: number;
lastDate: string; // ISO date YYYY-MM-DD
total: number;
bestTime: number; // seconds, 0 = never recorded
}
const DEFAULT: GameStats = { streak: 0, lastDate: "", total: 0, bestTime: 0 };
function storageKey(game: string) { return `stats-${game}`; }
export function loadStats(game: string): GameStats {
if (typeof window === "undefined") return DEFAULT;
try {
const raw = localStorage.getItem(storageKey(game));
if (!raw) return DEFAULT;
return { ...DEFAULT, ...JSON.parse(raw) };
} catch { return DEFAULT; }
}
export function recordSolve(game: string, date: string, secs: number): GameStats {
const prev = loadStats(game);
// Compute yesterday ISO using local-date arithmetic (avoids UTC offset bug)
const [y, m, d] = date.split("-").map(Number);
const prev2 = new Date(y, m - 1, d - 1); // local date, no UTC issue
const yesterdayISO = `${prev2.getFullYear()}-${String(prev2.getMonth() + 1).padStart(2, "0")}-${String(prev2.getDate()).padStart(2, "0")}`;
let streak = prev.streak;
if (prev.lastDate === date) {
// Already solved today — don't double-count
} else if (prev.lastDate === yesterdayISO) {
streak += 1;
} else {
streak = 1;
}
const stats: GameStats = {
streak,
lastDate: date,
total: prev.lastDate === date ? prev.total : prev.total + 1,
bestTime: prev.bestTime === 0 || secs < prev.bestTime ? secs : prev.bestTime,
};
localStorage.setItem(storageKey(game), JSON.stringify(stats));
return stats;
}