// User statistics tracking and persistence import { join } from "@std/path"; import { ensureDir } from "@std/fs"; export interface GameStats { totalGames: number; totalRounds: number; correctAnswers: number; incorrectAnswers: number; averageTimePerRound: number; bestStreak: number; modeStats: { letters: ModeStats; alphanumeric: ModeStats; full: ModeStats; words: ModeStats; phrases: ModeStats; }; lastPlayed?: string; } export interface ModeStats { gamesPlayed: number; correctAnswers: number; incorrectAnswers: number; averageAccuracy: number; } export interface GameResult { mode: "letters" | "alphanumeric" | "full" | "words" | "phrases"; rounds: number; correct: number; incorrect: number; averageTime: number; streak: number; } const DEFAULT_STATS: GameStats = { totalGames: 0, totalRounds: 0, correctAnswers: 0, incorrectAnswers: 0, averageTimePerRound: 0, bestStreak: 0, modeStats: { letters: { gamesPlayed: 0, correctAnswers: 0, incorrectAnswers: 0, averageAccuracy: 0, }, alphanumeric: { gamesPlayed: 0, correctAnswers: 0, incorrectAnswers: 0, averageAccuracy: 0, }, full: { gamesPlayed: 0, correctAnswers: 0, incorrectAnswers: 0, averageAccuracy: 0, }, words: { gamesPlayed: 0, correctAnswers: 0, incorrectAnswers: 0, averageAccuracy: 0, }, phrases: { gamesPlayed: 0, correctAnswers: 0, incorrectAnswers: 0, averageAccuracy: 0, }, }, }; function getStatsPath(): string { return join(Deno.cwd(), "data", "stats.json"); } /** * Load stats from JSON file */ export async function loadStats(): Promise { try { const statsPath = getStatsPath(); const content = await Deno.readTextFile(statsPath); return JSON.parse(content); } catch { return { ...DEFAULT_STATS }; } } /** * Save stats to JSON file */ export async function saveStats(stats: GameStats): Promise { try { const statsPath = getStatsPath(); const dataDir = join(Deno.cwd(), "data"); await ensureDir(dataDir); await Deno.writeTextFile(statsPath, JSON.stringify(stats, null, 2)); } catch (error) { throw new Error( `Failed to save statistics: ${error instanceof Error ? error.message : "Unknown error"}` ); } } /** * Update stats with a new game result */ export async function updateStats(result: GameResult): Promise { const stats = await loadStats(); // Update overall stats stats.totalGames++; stats.totalRounds += result.rounds; stats.correctAnswers += result.correct; stats.incorrectAnswers += result.incorrect; stats.averageTimePerRound = (stats.averageTimePerRound * (stats.totalRounds - result.rounds) + result.averageTime * result.rounds) / stats.totalRounds; stats.bestStreak = Math.max(stats.bestStreak, result.streak); stats.lastPlayed = new Date().toISOString(); // Update mode-specific stats const modeStats = stats.modeStats[result.mode]; modeStats.gamesPlayed++; modeStats.correctAnswers += result.correct; modeStats.incorrectAnswers += result.incorrect; const totalAnswers = modeStats.correctAnswers + modeStats.incorrectAnswers; modeStats.averageAccuracy = totalAnswers > 0 ? (modeStats.correctAnswers / totalAnswers) * 100 : 0; await saveStats(stats); return stats; } /** * Reset all stats */ export async function resetStats(): Promise { await saveStats({ ...DEFAULT_STATS }); } /** * Get formatted accuracy percentage */ export function getAccuracy(stats: GameStats): number { const total = stats.correctAnswers + stats.incorrectAnswers; return total > 0 ? (stats.correctAnswers / total) * 100 : 0; }