import type { GameStats, SolverReplay } from '@wordle/shared'; import { getMessages } from '../messages/index.js'; import { LangSwitch } from '../components/LangSwitch.js'; interface Screen3ResultsProps { won: boolean; attemptCount: number; revealedWord: string | null; stats: GameStats; replays?: SolverReplay[]; onPlayAgain?: () => void; } const MINI_COLORS: Record = { g: '#6aaa64', y: '#c9b458', x: '#787c7e' }; /** Compute Wordle feedback colors for a guess against the target word (same algorithm as server). */ function computeFeedback(target: string, guess: string): string[] { const targetUpper = target.toLowerCase(); const guessUpper = guess.toLowerCase(); const targetCounts: Record = {}; for (const ch of targetUpper) { targetCounts[ch] = (targetCounts[ch] ?? 0) + 1; } const result: string[] = Array(5).fill('x'); // Pass 1: greens for (let i = 0; i < 5; i++) { if (guessUpper[i] === targetUpper[i]) { result[i] = 'g'; targetCounts[guessUpper[i]]--; } } // Pass 2: yellows for (let i = 0; i < 5; i++) { if (result[i] === 'g') continue; const ch = guessUpper[i]; if ((targetCounts[ch] ?? 0) > 0) { result[i] = 'y'; targetCounts[ch]--; } } return result; } function MiniBoard({ replay, targetWord }: { replay: SolverReplay; targetWord: string }) { return (
{replay.solver}
{replay.steps.map((guess, rowIdx) => { const colors = computeFeedback(targetWord, guess); return (
{guess.split('').map((letter, colIdx) => { const c = colors[colIdx]; return (
{letter}
); })}
); })}
); } function Histogram({ stats }: { stats: GameStats }) { if (stats.gamesPlayed === 0) return

{getMessages().results.noGames}

; const maxCount = Math.max(...stats.histogram, 1); return (
{stats.histogram.map((count, idx) => { const label = idx < 6 ? `${idx + 1}` : 'X'; const pct = (count / maxCount) * 100; return (
{label}
0 ? '#6aaa64' : '#d3d6da', width: `${Math.max(pct, count > 0 ? 5 : 0)}%`, minWidth: count > 0 ? '12px' : '4px', borderRadius: '2px' }} /> {count}
); })}
); } export function Screen3Results({ won, attemptCount, revealedWord, stats, replays, onPlayAgain }: Screen3ResultsProps) { const r = getMessages().results; return (

{won ? r.congratulations : r.betterLuck}

{won ? (

{r.solvedIn(attemptCount)}

) : ( revealedWord &&

{r.theWordWas(revealedWord)}

)}

{r.statistics}

{stats.gamesPlayed}
{r.played}
{stats.gamesPlayed > 0 ? Math.round((stats.wins / stats.gamesPlayed) * 100) : 0}%
{r.winRate}
{stats.currentStreak}
{r.streak}
{stats.maxStreak}
{r.maxStreak}
{replays && replays.length > 0 && revealedWord && (

{r.solverCaption}

{replays.map((rp) => (
))}
)} {onPlayAgain && ( )}
); }