Преглед на файлове

feat: solver replays on results screen

- All 4 solvers record guess sequences (not just attempt counts)
- Word bank stores replays alongside difficulty scores
- API returns replays on final guess response (win or loss)
- Screen 3 renders 2x2 mini grid showing each solver's path
- Mini tiles use same green/yellow/gray colors at 20px size

Co-Authored-By: Claude <noreply@anthropic.com>
Oleg Panashchenko преди 2 седмици
родител
ревизия
6431c2c592

+ 4 - 1
.claude/settings.local.json

@@ -27,7 +27,10 @@
       "Bash(git rm *)",
       "Bash(git add *)",
       "Bash(git commit *)",
-      "Bash(echo \"solver: $?\")"
+      "Bash(echo \"solver: $?\")",
+      "Bash(fuser -k 3001/tcp)",
+      "Bash(curl -s -X POST http://localhost:3001/api/guess -H 'Content-Type: application/json' -d '{\"wordId\":4,\"guess\":\"style\",\"tryNo\":1}')",
+      "Bash(curl -s -X POST http://localhost:3001/api/guess -H 'Content-Type: application/json' -d '{\"wordId\":4,\"guess\":\"crane\",\"tryNo\":6}')"
     ]
   }
 }

+ 2 - 1
client/src/App.tsx

@@ -13,7 +13,7 @@ export default function App() {
   const [screen, setScreen] = useState<Screen>('game');
   const [wordId, setWordId] = useState<number | null>(null);
   const {
-    guesses, gameStatus, message, lastDifficulty, revealedWord,
+    guesses, gameStatus, message, lastDifficulty, revealedWord, replays,
     submitGuess, dismissMessage, resetForNewGame,
   } = useGame(state.currentGame?.guesses ?? []);
   const initialised = useRef(false);
@@ -134,6 +134,7 @@ export default function App() {
         attemptCount={guesses.length}
         revealedWord={revealedWord}
         stats={state.stats}
+        replays={replays ?? undefined}
         onPlayAgain={handlePlayAgain}
       />
     );

+ 8 - 2
client/src/hooks/useGame.ts

@@ -1,5 +1,5 @@
 import { useState, useCallback } from 'react';
-import type { GuessEntry, GuessResponse } from '@wordle/shared';
+import type { GuessEntry, GuessResponse, SolverReplay } from '@wordle/shared';
 
 const BASE = '/api';
 
@@ -9,6 +9,7 @@ interface UseGameReturn {
   message: string | null;
   lastDifficulty: number | null;
   revealedWord: string | null;
+  replays: SolverReplay[] | null;
   submitGuess: (wordId: number, guess: string) => Promise<void>;
   dismissMessage: () => void;
   resetForNewGame: () => void;
@@ -19,6 +20,7 @@ export function useGame(initialGuesses: GuessEntry[]): UseGameReturn {
   const [message, setMessage] = useState<string | null>(null);
   const [lastDifficulty, setLastDifficulty] = useState<number | null>(null);
   const [revealedWord, setRevealedWord] = useState<string | null>(null);
+  const [replays, setReplays] = useState<SolverReplay[] | null>(null);
 
   const gameStatus = deriveStatus(guesses);
   const dismissMessage = useCallback(() => setMessage(null), []);
@@ -28,6 +30,7 @@ export function useGame(initialGuesses: GuessEntry[]): UseGameReturn {
     setMessage(null);
     setLastDifficulty(null);
     setRevealedWord(null);
+    setReplays(null);
   }, []);
 
   const submitGuess = useCallback(async (wordId: number, guess: string) => {
@@ -62,9 +65,12 @@ export function useGame(initialGuesses: GuessEntry[]): UseGameReturn {
     if (data.word) {
       setRevealedWord(data.word);
     }
+    if (data.replays) {
+      setReplays(data.replays);
+    }
   }, [guesses.length]);
 
-  return { guesses, gameStatus, message, lastDifficulty, revealedWord, submitGuess, dismissMessage, resetForNewGame };
+  return { guesses, gameStatus, message, lastDifficulty, revealedWord, replays, submitGuess, dismissMessage, resetForNewGame };
 }
 
 function deriveStatus(guesses: GuessEntry[]): 'playing' | 'won' | 'lost' {

+ 50 - 3
client/src/screens/Screen3Results.tsx

@@ -1,11 +1,12 @@
-import type { GameStats } from '@wordle/shared';
+import type { GameStats, SolverReplay } from '@wordle/shared';
 
 interface Screen3ResultsProps {
   won: boolean;
   attemptCount: number;
   revealedWord: string | null;
   stats: GameStats;
-  onPlayAgain?: () => void; // Story 1.3
+  replays?: SolverReplay[];
+  onPlayAgain?: () => void;
 }
 
 function Histogram({ stats }: { stats: GameStats }) {
@@ -30,7 +31,40 @@ function Histogram({ stats }: { stats: GameStats }) {
   );
 }
 
-export function Screen3Results({ won, attemptCount, revealedWord, stats, onPlayAgain }: Screen3ResultsProps) {
+const MINI_COLORS: Record<string, string> = { g: '#6aaa64', y: '#c9b458', x: '#787c7e' };
+
+function MiniBoard({ replay }: { replay: SolverReplay }) {
+  return (
+    <div style={{ marginBottom: '12px' }}>
+      <div style={{ fontSize: '0.7rem', fontWeight: 'bold', color: '#555', marginBottom: '4px', textAlign: 'center' }}>
+        {replay.solver}
+      </div>
+      {replay.steps.map((step, rowIdx) => (
+        <div key={rowIdx} style={{ display: 'flex', gap: '2px', justifyContent: 'center', marginBottom: '2px' }}>
+          {step.guess.split('').map((letter, colIdx) => {
+            const c = step.colors[colIdx];
+            const bg = MINI_COLORS[c] ?? '#d3d6da';
+            return (
+              <div key={colIdx} style={{
+                width: '20px', height: '20px',
+                backgroundColor: bg,
+                color: c === 'x' || !c ? '#fff' : '#fff',
+                display: 'flex', alignItems: 'center', justifyContent: 'center',
+                fontSize: '0.55rem', fontWeight: 'bold',
+                textTransform: 'uppercase', fontFamily: 'monospace',
+                borderRadius: '2px',
+              }}>
+                {letter}
+              </div>
+            );
+          })}
+        </div>
+      ))}
+    </div>
+  );
+}
+
+export function Screen3Results({ won, attemptCount, revealedWord, stats, replays, onPlayAgain }: Screen3ResultsProps) {
   return (
     <div style={{ maxWidth: '400px', margin: '24px auto', padding: '16px', fontFamily: 'sans-serif', textAlign: 'center' }}>
       <h1 style={{ fontSize: '1.6rem', marginBottom: '12px' }}>{won ? '🎉 Congratulations!' : 'Better luck next time'}</h1>
@@ -52,6 +86,19 @@ export function Screen3Results({ won, attemptCount, revealedWord, stats, onPlayA
         <Histogram stats={stats} />
       </div>
 
+      {replays && replays.length > 0 && (
+        <div style={{ margin: '24px 0' }}>
+          <p style={{ fontSize: '0.85rem', color: '#787c7e', marginBottom: '12px' }}>
+            How the solvers cracked this word:
+          </p>
+          <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '16px', maxWidth: '320px', margin: '0 auto' }}>
+            {replays.map((r) => (
+              <MiniBoard key={r.solver} replay={r} />
+            ))}
+          </div>
+        </div>
+      )}
+
       {onPlayAgain && (
         <button
           onClick={onPlayAgain}

+ 5730 - 40
data/word-bank.json

@@ -772,202 +772,5892 @@
     {
       "id": 1,
       "word": "crane",
-      "difficulty": 2.5
+      "difficulty": 2.5,
+      "replays": [
+        {
+          "solver": "Entropy",
+          "steps": [
+            {
+              "guess": "arise",
+              "colors": [
+                "y",
+                "g",
+                "x",
+                "x",
+                "g"
+              ]
+            },
+            {
+              "guess": "grace",
+              "colors": [
+                "x",
+                "g",
+                "g",
+                "y",
+                "g"
+              ]
+            },
+            {
+              "guess": "crane",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        },
+        {
+          "solver": "Frequency",
+          "steps": [
+            {
+              "guess": "alert",
+              "colors": [
+                "y",
+                "x",
+                "y",
+                "y",
+                "x"
+              ]
+            },
+            {
+              "guess": "grace",
+              "colors": [
+                "x",
+                "g",
+                "g",
+                "y",
+                "g"
+              ]
+            },
+            {
+              "guess": "crane",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        },
+        {
+          "solver": "Vowel First",
+          "steps": [
+            {
+              "guess": "audio",
+              "colors": [
+                "y",
+                "x",
+                "x",
+                "x",
+                "x"
+              ]
+            },
+            {
+              "guess": "eager",
+              "colors": [
+                "y",
+                "y",
+                "x",
+                "x",
+                "y"
+              ]
+            },
+            {
+              "guess": "crane",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        },
+        {
+          "solver": "Greedy",
+          "steps": [
+            {
+              "guess": "crane",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        }
+      ]
     },
     {
       "id": 2,
       "word": "apple",
-      "difficulty": 3.25
+      "difficulty": 3.25,
+      "replays": [
+        {
+          "solver": "Entropy",
+          "steps": [
+            {
+              "guess": "arise",
+              "colors": [
+                "g",
+                "x",
+                "x",
+                "x",
+                "g"
+              ]
+            },
+            {
+              "guess": "ankle",
+              "colors": [
+                "g",
+                "x",
+                "x",
+                "g",
+                "g"
+              ]
+            },
+            {
+              "guess": "apple",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        },
+        {
+          "solver": "Frequency",
+          "steps": [
+            {
+              "guess": "alert",
+              "colors": [
+                "g",
+                "y",
+                "y",
+                "x",
+                "x"
+              ]
+            },
+            {
+              "guess": "angel",
+              "colors": [
+                "g",
+                "x",
+                "x",
+                "y",
+                "y"
+              ]
+            },
+            {
+              "guess": "ample",
+              "colors": [
+                "g",
+                "x",
+                "g",
+                "g",
+                "g"
+              ]
+            },
+            {
+              "guess": "apple",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        },
+        {
+          "solver": "Vowel First",
+          "steps": [
+            {
+              "guess": "audio",
+              "colors": [
+                "g",
+                "x",
+                "x",
+                "x",
+                "x"
+              ]
+            },
+            {
+              "guess": "agree",
+              "colors": [
+                "g",
+                "x",
+                "x",
+                "x",
+                "g"
+              ]
+            },
+            {
+              "guess": "ample",
+              "colors": [
+                "g",
+                "x",
+                "g",
+                "g",
+                "g"
+              ]
+            },
+            {
+              "guess": "apple",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        },
+        {
+          "solver": "Greedy",
+          "steps": [
+            {
+              "guess": "crane",
+              "colors": [
+                "x",
+                "x",
+                "y",
+                "x",
+                "g"
+              ]
+            },
+            {
+              "guess": "apple",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        }
+      ]
     },
     {
       "id": 3,
       "word": "grape",
-      "difficulty": 2.75
+      "difficulty": 2.75,
+      "replays": [
+        {
+          "solver": "Entropy",
+          "steps": [
+            {
+              "guess": "arise",
+              "colors": [
+                "y",
+                "g",
+                "x",
+                "x",
+                "g"
+              ]
+            },
+            {
+              "guess": "grace",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "x",
+                "g"
+              ]
+            },
+            {
+              "guess": "grape",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        },
+        {
+          "solver": "Frequency",
+          "steps": [
+            {
+              "guess": "alert",
+              "colors": [
+                "y",
+                "x",
+                "y",
+                "y",
+                "x"
+              ]
+            },
+            {
+              "guess": "grace",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "x",
+                "g"
+              ]
+            },
+            {
+              "guess": "grape",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        },
+        {
+          "solver": "Vowel First",
+          "steps": [
+            {
+              "guess": "audio",
+              "colors": [
+                "y",
+                "x",
+                "x",
+                "x",
+                "x"
+              ]
+            },
+            {
+              "guess": "eager",
+              "colors": [
+                "y",
+                "y",
+                "y",
+                "x",
+                "y"
+              ]
+            },
+            {
+              "guess": "grape",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        },
+        {
+          "solver": "Greedy",
+          "steps": [
+            {
+              "guess": "crane",
+              "colors": [
+                "x",
+                "g",
+                "g",
+                "x",
+                "g"
+              ]
+            },
+            {
+              "guess": "grape",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        }
+      ]
     },
     {
       "id": 4,
       "word": "style",
-      "difficulty": 2.5
+      "difficulty": 2.5,
+      "replays": [
+        {
+          "solver": "Entropy",
+          "steps": [
+            {
+              "guess": "arise",
+              "colors": [
+                "x",
+                "x",
+                "x",
+                "y",
+                "g"
+              ]
+            },
+            {
+              "guess": "scope",
+              "colors": [
+                "g",
+                "x",
+                "x",
+                "x",
+                "g"
+              ]
+            },
+            {
+              "guess": "style",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        },
+        {
+          "solver": "Frequency",
+          "steps": [
+            {
+              "guess": "alert",
+              "colors": [
+                "x",
+                "y",
+                "y",
+                "x",
+                "y"
+              ]
+            },
+            {
+              "guess": "style",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        },
+        {
+          "solver": "Vowel First",
+          "steps": [
+            {
+              "guess": "audio",
+              "colors": [
+                "x",
+                "x",
+                "x",
+                "x",
+                "x"
+              ]
+            },
+            {
+              "guess": "temple",
+              "colors": [
+                "y",
+                "y",
+                "x",
+                "x",
+                "y"
+              ]
+            },
+            {
+              "guess": "style",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        },
+        {
+          "solver": "Greedy",
+          "steps": [
+            {
+              "guess": "crane",
+              "colors": [
+                "x",
+                "x",
+                "x",
+                "x",
+                "g"
+              ]
+            },
+            {
+              "guess": "style",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        }
+      ]
     },
     {
       "id": 5,
       "word": "hello",
-      "difficulty": 2.5
+      "difficulty": 2.5,
+      "replays": [
+        {
+          "solver": "Entropy",
+          "steps": [
+            {
+              "guess": "arise",
+              "colors": [
+                "x",
+                "x",
+                "x",
+                "x",
+                "y"
+              ]
+            },
+            {
+              "guess": "lemon",
+              "colors": [
+                "y",
+                "g",
+                "x",
+                "y",
+                "x"
+              ]
+            },
+            {
+              "guess": "hello",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        },
+        {
+          "solver": "Frequency",
+          "steps": [
+            {
+              "guess": "alert",
+              "colors": [
+                "x",
+                "y",
+                "y",
+                "x",
+                "x"
+              ]
+            },
+            {
+              "guess": "lemon",
+              "colors": [
+                "y",
+                "g",
+                "x",
+                "y",
+                "x"
+              ]
+            },
+            {
+              "guess": "hello",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        },
+        {
+          "solver": "Vowel First",
+          "steps": [
+            {
+              "guess": "audio",
+              "colors": [
+                "x",
+                "x",
+                "x",
+                "x",
+                "g"
+              ]
+            },
+            {
+              "guess": "hello",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        },
+        {
+          "solver": "Greedy",
+          "steps": [
+            {
+              "guess": "crane",
+              "colors": [
+                "x",
+                "x",
+                "x",
+                "x",
+                "y"
+              ]
+            },
+            {
+              "guess": "hello",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        }
+      ]
     },
     {
       "id": 6,
       "word": "world",
-      "difficulty": 2.5
+      "difficulty": 2.5,
+      "replays": [
+        {
+          "solver": "Entropy",
+          "steps": [
+            {
+              "guess": "arise",
+              "colors": [
+                "x",
+                "y",
+                "x",
+                "x",
+                "x"
+              ]
+            },
+            {
+              "guess": "court",
+              "colors": [
+                "x",
+                "g",
+                "x",
+                "y",
+                "x"
+              ]
+            },
+            {
+              "guess": "world",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        },
+        {
+          "solver": "Frequency",
+          "steps": [
+            {
+              "guess": "alert",
+              "colors": [
+                "x",
+                "y",
+                "x",
+                "y",
+                "x"
+              ]
+            },
+            {
+              "guess": "world",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        },
+        {
+          "solver": "Vowel First",
+          "steps": [
+            {
+              "guess": "audio",
+              "colors": [
+                "x",
+                "x",
+                "y",
+                "x",
+                "y"
+              ]
+            },
+            {
+              "guess": "dozen",
+              "colors": [
+                "y",
+                "g",
+                "x",
+                "x",
+                "x"
+              ]
+            },
+            {
+              "guess": "world",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        },
+        {
+          "solver": "Greedy",
+          "steps": [
+            {
+              "guess": "crane",
+              "colors": [
+                "x",
+                "y",
+                "x",
+                "x",
+                "x"
+              ]
+            },
+            {
+              "guess": "world",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        }
+      ]
     },
     {
       "id": 7,
       "word": "large",
-      "difficulty": 2.25
+      "difficulty": 2.25,
+      "replays": [
+        {
+          "solver": "Entropy",
+          "steps": [
+            {
+              "guess": "arise",
+              "colors": [
+                "y",
+                "y",
+                "x",
+                "x",
+                "g"
+              ]
+            },
+            {
+              "guess": "large",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        },
+        {
+          "solver": "Frequency",
+          "steps": [
+            {
+              "guess": "alert",
+              "colors": [
+                "y",
+                "y",
+                "y",
+                "y",
+                "x"
+              ]
+            },
+            {
+              "guess": "large",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        },
+        {
+          "solver": "Vowel First",
+          "steps": [
+            {
+              "guess": "audio",
+              "colors": [
+                "y",
+                "x",
+                "x",
+                "x",
+                "x"
+              ]
+            },
+            {
+              "guess": "eager",
+              "colors": [
+                "y",
+                "g",
+                "y",
+                "x",
+                "y"
+              ]
+            },
+            {
+              "guess": "large",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        },
+        {
+          "solver": "Greedy",
+          "steps": [
+            {
+              "guess": "crane",
+              "colors": [
+                "x",
+                "y",
+                "y",
+                "x",
+                "g"
+              ]
+            },
+            {
+              "guess": "large",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        }
+      ]
     },
     {
       "id": 8,
       "word": "house",
-      "difficulty": 2.5
+      "difficulty": 2.5,
+      "replays": [
+        {
+          "solver": "Entropy",
+          "steps": [
+            {
+              "guess": "arise",
+              "colors": [
+                "x",
+                "x",
+                "x",
+                "g",
+                "g"
+              ]
+            },
+            {
+              "guess": "house",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        },
+        {
+          "solver": "Frequency",
+          "steps": [
+            {
+              "guess": "alert",
+              "colors": [
+                "x",
+                "x",
+                "y",
+                "x",
+                "x"
+              ]
+            },
+            {
+              "guess": "noise",
+              "colors": [
+                "x",
+                "g",
+                "x",
+                "g",
+                "g"
+              ]
+            },
+            {
+              "guess": "house",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        },
+        {
+          "solver": "Vowel First",
+          "steps": [
+            {
+              "guess": "audio",
+              "colors": [
+                "x",
+                "y",
+                "x",
+                "x",
+                "y"
+              ]
+            },
+            {
+              "guess": "house",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        },
+        {
+          "solver": "Greedy",
+          "steps": [
+            {
+              "guess": "crane",
+              "colors": [
+                "x",
+                "x",
+                "x",
+                "x",
+                "g"
+              ]
+            },
+            {
+              "guess": "style",
+              "colors": [
+                "y",
+                "x",
+                "x",
+                "x",
+                "g"
+              ]
+            },
+            {
+              "guess": "house",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        }
+      ]
     },
     {
       "id": 9,
       "word": "brain",
-      "difficulty": 2.75
+      "difficulty": 2.75,
+      "replays": [
+        {
+          "solver": "Entropy",
+          "steps": [
+            {
+              "guess": "arise",
+              "colors": [
+                "y",
+                "g",
+                "y",
+                "x",
+                "x"
+              ]
+            },
+            {
+              "guess": "train",
+              "colors": [
+                "x",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            },
+            {
+              "guess": "brain",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        },
+        {
+          "solver": "Frequency",
+          "steps": [
+            {
+              "guess": "alert",
+              "colors": [
+                "y",
+                "x",
+                "x",
+                "y",
+                "x"
+              ]
+            },
+            {
+              "guess": "grand",
+              "colors": [
+                "x",
+                "g",
+                "g",
+                "y",
+                "x"
+              ]
+            },
+            {
+              "guess": "brain",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        },
+        {
+          "solver": "Vowel First",
+          "steps": [
+            {
+              "guess": "audio",
+              "colors": [
+                "y",
+                "x",
+                "x",
+                "g",
+                "x"
+              ]
+            },
+            {
+              "guess": "email",
+              "colors": [
+                "x",
+                "x",
+                "g",
+                "g",
+                "x"
+              ]
+            },
+            {
+              "guess": "brain",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        },
+        {
+          "solver": "Greedy",
+          "steps": [
+            {
+              "guess": "crane",
+              "colors": [
+                "x",
+                "g",
+                "g",
+                "y",
+                "x"
+              ]
+            },
+            {
+              "guess": "brain",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        }
+      ]
     },
     {
       "id": 10,
       "word": "cloud",
-      "difficulty": 2.5
+      "difficulty": 2.5,
+      "replays": [
+        {
+          "solver": "Entropy",
+          "steps": [
+            {
+              "guess": "arise",
+              "colors": [
+                "x",
+                "x",
+                "x",
+                "x",
+                "x"
+              ]
+            },
+            {
+              "guess": "count",
+              "colors": [
+                "g",
+                "y",
+                "y",
+                "x",
+                "x"
+              ]
+            },
+            {
+              "guess": "cloud",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        },
+        {
+          "solver": "Frequency",
+          "steps": [
+            {
+              "guess": "alert",
+              "colors": [
+                "x",
+                "g",
+                "x",
+                "x",
+                "x"
+              ]
+            },
+            {
+              "guess": "flock",
+              "colors": [
+                "x",
+                "g",
+                "g",
+                "y",
+                "x"
+              ]
+            },
+            {
+              "guess": "cloud",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        },
+        {
+          "solver": "Vowel First",
+          "steps": [
+            {
+              "guess": "audio",
+              "colors": [
+                "x",
+                "y",
+                "y",
+                "x",
+                "y"
+              ]
+            },
+            {
+              "guess": "cloud",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        },
+        {
+          "solver": "Greedy",
+          "steps": [
+            {
+              "guess": "crane",
+              "colors": [
+                "g",
+                "x",
+                "x",
+                "x",
+                "x"
+              ]
+            },
+            {
+              "guess": "cloud",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        }
+      ]
     },
     {
       "id": 11,
       "word": "dance",
-      "difficulty": 2.5
+      "difficulty": 2.5,
+      "replays": [
+        {
+          "solver": "Entropy",
+          "steps": [
+            {
+              "guess": "arise",
+              "colors": [
+                "y",
+                "x",
+                "x",
+                "x",
+                "g"
+              ]
+            },
+            {
+              "guess": "blame",
+              "colors": [
+                "x",
+                "x",
+                "y",
+                "x",
+                "g"
+              ]
+            },
+            {
+              "guess": "dance",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        },
+        {
+          "solver": "Frequency",
+          "steps": [
+            {
+              "guess": "alert",
+              "colors": [
+                "y",
+                "x",
+                "y",
+                "x",
+                "x"
+              ]
+            },
+            {
+              "guess": "chase",
+              "colors": [
+                "y",
+                "x",
+                "y",
+                "x",
+                "g"
+              ]
+            },
+            {
+              "guess": "dance",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        },
+        {
+          "solver": "Vowel First",
+          "steps": [
+            {
+              "guess": "audio",
+              "colors": [
+                "y",
+                "x",
+                "y",
+                "x",
+                "x"
+              ]
+            },
+            {
+              "guess": "dance",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        },
+        {
+          "solver": "Greedy",
+          "steps": [
+            {
+              "guess": "crane",
+              "colors": [
+                "y",
+                "x",
+                "y",
+                "y",
+                "g"
+              ]
+            },
+            {
+              "guess": "dance",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        }
+      ]
     },
     {
       "id": 12,
       "word": "flame",
-      "difficulty": 2.75
+      "difficulty": 2.75,
+      "replays": [
+        {
+          "solver": "Entropy",
+          "steps": [
+            {
+              "guess": "arise",
+              "colors": [
+                "y",
+                "x",
+                "x",
+                "x",
+                "g"
+              ]
+            },
+            {
+              "guess": "blame",
+              "colors": [
+                "x",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            },
+            {
+              "guess": "flame",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        },
+        {
+          "solver": "Frequency",
+          "steps": [
+            {
+              "guess": "alert",
+              "colors": [
+                "y",
+                "g",
+                "y",
+                "x",
+                "x"
+              ]
+            },
+            {
+              "guess": "blame",
+              "colors": [
+                "x",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            },
+            {
+              "guess": "flame",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        },
+        {
+          "solver": "Vowel First",
+          "steps": [
+            {
+              "guess": "audio",
+              "colors": [
+                "y",
+                "x",
+                "x",
+                "x",
+                "x"
+              ]
+            },
+            {
+              "guess": "eager",
+              "colors": [
+                "y",
+                "y",
+                "x",
+                "x",
+                "x"
+              ]
+            },
+            {
+              "guess": "flame",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        },
+        {
+          "solver": "Greedy",
+          "steps": [
+            {
+              "guess": "crane",
+              "colors": [
+                "x",
+                "x",
+                "g",
+                "x",
+                "g"
+              ]
+            },
+            {
+              "guess": "flame",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        }
+      ]
     },
     {
       "id": 13,
       "word": "giant",
-      "difficulty": 2.75
+      "difficulty": 2.75,
+      "replays": [
+        {
+          "solver": "Entropy",
+          "steps": [
+            {
+              "guess": "arise",
+              "colors": [
+                "y",
+                "x",
+                "y",
+                "x",
+                "x"
+              ]
+            },
+            {
+              "guess": "panic",
+              "colors": [
+                "x",
+                "y",
+                "y",
+                "y",
+                "x"
+              ]
+            },
+            {
+              "guess": "giant",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        },
+        {
+          "solver": "Frequency",
+          "steps": [
+            {
+              "guess": "alert",
+              "colors": [
+                "y",
+                "x",
+                "x",
+                "x",
+                "g"
+              ]
+            },
+            {
+              "guess": "saint",
+              "colors": [
+                "x",
+                "y",
+                "y",
+                "g",
+                "g"
+              ]
+            },
+            {
+              "guess": "giant",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        },
+        {
+          "solver": "Vowel First",
+          "steps": [
+            {
+              "guess": "audio",
+              "colors": [
+                "y",
+                "x",
+                "x",
+                "y",
+                "x"
+              ]
+            },
+            {
+              "guess": "image",
+              "colors": [
+                "y",
+                "x",
+                "g",
+                "y",
+                "x"
+              ]
+            },
+            {
+              "guess": "giant",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        },
+        {
+          "solver": "Greedy",
+          "steps": [
+            {
+              "guess": "crane",
+              "colors": [
+                "x",
+                "x",
+                "g",
+                "g",
+                "x"
+              ]
+            },
+            {
+              "guess": "giant",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        }
+      ]
     },
     {
       "id": 14,
       "word": "happy",
-      "difficulty": 3
+      "difficulty": 3,
+      "replays": [
+        {
+          "solver": "Entropy",
+          "steps": [
+            {
+              "guess": "arise",
+              "colors": [
+                "y",
+                "x",
+                "x",
+                "x",
+                "x"
+              ]
+            },
+            {
+              "guess": "batch",
+              "colors": [
+                "x",
+                "g",
+                "x",
+                "x",
+                "y"
+              ]
+            },
+            {
+              "guess": "happy",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        },
+        {
+          "solver": "Frequency",
+          "steps": [
+            {
+              "guess": "alert",
+              "colors": [
+                "y",
+                "x",
+                "x",
+                "x",
+                "x"
+              ]
+            },
+            {
+              "guess": "chain",
+              "colors": [
+                "x",
+                "y",
+                "y",
+                "x",
+                "x"
+              ]
+            },
+            {
+              "guess": "happy",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        },
+        {
+          "solver": "Vowel First",
+          "steps": [
+            {
+              "guess": "audio",
+              "colors": [
+                "y",
+                "x",
+                "x",
+                "x",
+                "x"
+              ]
+            },
+            {
+              "guess": "eager",
+              "colors": [
+                "x",
+                "g",
+                "x",
+                "x",
+                "x"
+              ]
+            },
+            {
+              "guess": "batch",
+              "colors": [
+                "x",
+                "g",
+                "x",
+                "x",
+                "y"
+              ]
+            },
+            {
+              "guess": "happy",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        },
+        {
+          "solver": "Greedy",
+          "steps": [
+            {
+              "guess": "crane",
+              "colors": [
+                "x",
+                "x",
+                "y",
+                "x",
+                "x"
+              ]
+            },
+            {
+              "guess": "happy",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        }
+      ]
     },
     {
       "id": 15,
       "word": "lemon",
-      "difficulty": 2
+      "difficulty": 2,
+      "replays": [
+        {
+          "solver": "Entropy",
+          "steps": [
+            {
+              "guess": "arise",
+              "colors": [
+                "x",
+                "x",
+                "x",
+                "x",
+                "y"
+              ]
+            },
+            {
+              "guess": "lemon",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        },
+        {
+          "solver": "Frequency",
+          "steps": [
+            {
+              "guess": "alert",
+              "colors": [
+                "x",
+                "y",
+                "y",
+                "x",
+                "x"
+              ]
+            },
+            {
+              "guess": "lemon",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        },
+        {
+          "solver": "Vowel First",
+          "steps": [
+            {
+              "guess": "audio",
+              "colors": [
+                "x",
+                "x",
+                "x",
+                "x",
+                "y"
+              ]
+            },
+            {
+              "guess": "lemon",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        },
+        {
+          "solver": "Greedy",
+          "steps": [
+            {
+              "guess": "crane",
+              "colors": [
+                "x",
+                "x",
+                "x",
+                "y",
+                "y"
+              ]
+            },
+            {
+              "guess": "lemon",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        }
+      ]
     },
     {
       "id": 16,
       "word": "mango",
-      "difficulty": 2.5
+      "difficulty": 2.5,
+      "replays": [
+        {
+          "solver": "Entropy",
+          "steps": [
+            {
+              "guess": "arise",
+              "colors": [
+                "y",
+                "x",
+                "x",
+                "x",
+                "x"
+              ]
+            },
+            {
+              "guess": "batch",
+              "colors": [
+                "x",
+                "g",
+                "x",
+                "x",
+                "x"
+              ]
+            },
+            {
+              "guess": "mango",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        },
+        {
+          "solver": "Frequency",
+          "steps": [
+            {
+              "guess": "alert",
+              "colors": [
+                "y",
+                "x",
+                "x",
+                "x",
+                "x"
+              ]
+            },
+            {
+              "guess": "chain",
+              "colors": [
+                "x",
+                "x",
+                "y",
+                "x",
+                "y"
+              ]
+            },
+            {
+              "guess": "mango",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        },
+        {
+          "solver": "Vowel First",
+          "steps": [
+            {
+              "guess": "audio",
+              "colors": [
+                "y",
+                "x",
+                "x",
+                "x",
+                "g"
+              ]
+            },
+            {
+              "guess": "mango",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        },
+        {
+          "solver": "Greedy",
+          "steps": [
+            {
+              "guess": "crane",
+              "colors": [
+                "x",
+                "x",
+                "y",
+                "y",
+                "x"
+              ]
+            },
+            {
+              "guess": "mango",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        }
+      ]
     },
     {
       "id": 17,
       "word": "noble",
-      "difficulty": 2.75
+      "difficulty": 2.75,
+      "replays": [
+        {
+          "solver": "Entropy",
+          "steps": [
+            {
+              "guess": "arise",
+              "colors": [
+                "x",
+                "x",
+                "x",
+                "x",
+                "g"
+              ]
+            },
+            {
+              "guess": "uncle",
+              "colors": [
+                "x",
+                "y",
+                "x",
+                "g",
+                "g"
+              ]
+            },
+            {
+              "guess": "noble",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        },
+        {
+          "solver": "Frequency",
+          "steps": [
+            {
+              "guess": "alert",
+              "colors": [
+                "x",
+                "y",
+                "y",
+                "x",
+                "x"
+              ]
+            },
+            {
+              "guess": "lemon",
+              "colors": [
+                "y",
+                "y",
+                "x",
+                "y",
+                "y"
+              ]
+            },
+            {
+              "guess": "noble",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        },
+        {
+          "solver": "Vowel First",
+          "steps": [
+            {
+              "guess": "audio",
+              "colors": [
+                "x",
+                "x",
+                "x",
+                "x",
+                "y"
+              ]
+            },
+            {
+              "guess": "lemon",
+              "colors": [
+                "y",
+                "y",
+                "x",
+                "y",
+                "y"
+              ]
+            },
+            {
+              "guess": "noble",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        },
+        {
+          "solver": "Greedy",
+          "steps": [
+            {
+              "guess": "crane",
+              "colors": [
+                "x",
+                "x",
+                "x",
+                "y",
+                "g"
+              ]
+            },
+            {
+              "guess": "noble",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        }
+      ]
     },
     {
       "id": 18,
       "word": "ocean",
-      "difficulty": 2.25
+      "difficulty": 2.25,
+      "replays": [
+        {
+          "solver": "Entropy",
+          "steps": [
+            {
+              "guess": "arise",
+              "colors": [
+                "y",
+                "x",
+                "x",
+                "x",
+                "y"
+              ]
+            },
+            {
+              "guess": "metal",
+              "colors": [
+                "x",
+                "y",
+                "x",
+                "g",
+                "x"
+              ]
+            },
+            {
+              "guess": "ocean",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        },
+        {
+          "solver": "Frequency",
+          "steps": [
+            {
+              "guess": "alert",
+              "colors": [
+                "y",
+                "x",
+                "g",
+                "x",
+                "x"
+              ]
+            },
+            {
+              "guess": "ocean",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        },
+        {
+          "solver": "Vowel First",
+          "steps": [
+            {
+              "guess": "audio",
+              "colors": [
+                "y",
+                "x",
+                "x",
+                "x",
+                "y"
+              ]
+            },
+            {
+              "guess": "ocean",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        },
+        {
+          "solver": "Greedy",
+          "steps": [
+            {
+              "guess": "crane",
+              "colors": [
+                "y",
+                "x",
+                "y",
+                "y",
+                "y"
+              ]
+            },
+            {
+              "guess": "ocean",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        }
+      ]
     },
     {
       "id": 19,
       "word": "piano",
-      "difficulty": 2.75
+      "difficulty": 2.75,
+      "replays": [
+        {
+          "solver": "Entropy",
+          "steps": [
+            {
+              "guess": "arise",
+              "colors": [
+                "y",
+                "x",
+                "y",
+                "x",
+                "x"
+              ]
+            },
+            {
+              "guess": "panic",
+              "colors": [
+                "g",
+                "y",
+                "y",
+                "y",
+                "x"
+              ]
+            },
+            {
+              "guess": "piano",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        },
+        {
+          "solver": "Frequency",
+          "steps": [
+            {
+              "guess": "alert",
+              "colors": [
+                "y",
+                "x",
+                "x",
+                "x",
+                "x"
+              ]
+            },
+            {
+              "guess": "chain",
+              "colors": [
+                "x",
+                "x",
+                "g",
+                "y",
+                "y"
+              ]
+            },
+            {
+              "guess": "piano",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        },
+        {
+          "solver": "Vowel First",
+          "steps": [
+            {
+              "guess": "audio",
+              "colors": [
+                "y",
+                "x",
+                "x",
+                "y",
+                "g"
+              ]
+            },
+            {
+              "guess": "piano",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        },
+        {
+          "solver": "Greedy",
+          "steps": [
+            {
+              "guess": "crane",
+              "colors": [
+                "x",
+                "x",
+                "g",
+                "g",
+                "x"
+              ]
+            },
+            {
+              "guess": "giant",
+              "colors": [
+                "x",
+                "g",
+                "g",
+                "g",
+                "x"
+              ]
+            },
+            {
+              "guess": "piano",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        }
+      ]
     },
     {
       "id": 20,
       "word": "queen",
-      "difficulty": 2.75
+      "difficulty": 2.75,
+      "replays": [
+        {
+          "solver": "Entropy",
+          "steps": [
+            {
+              "guess": "arise",
+              "colors": [
+                "x",
+                "x",
+                "x",
+                "x",
+                "y"
+              ]
+            },
+            {
+              "guess": "lemon",
+              "colors": [
+                "x",
+                "y",
+                "x",
+                "x",
+                "g"
+              ]
+            },
+            {
+              "guess": "queen",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        },
+        {
+          "solver": "Frequency",
+          "steps": [
+            {
+              "guess": "alert",
+              "colors": [
+                "x",
+                "x",
+                "g",
+                "x",
+                "x"
+              ]
+            },
+            {
+              "guess": "spend",
+              "colors": [
+                "x",
+                "x",
+                "g",
+                "y",
+                "x"
+              ]
+            },
+            {
+              "guess": "queen",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        },
+        {
+          "solver": "Vowel First",
+          "steps": [
+            {
+              "guess": "audio",
+              "colors": [
+                "x",
+                "g",
+                "x",
+                "x",
+                "x"
+              ]
+            },
+            {
+              "guess": "queen",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        },
+        {
+          "solver": "Greedy",
+          "steps": [
+            {
+              "guess": "crane",
+              "colors": [
+                "x",
+                "x",
+                "x",
+                "y",
+                "y"
+              ]
+            },
+            {
+              "guess": "lemon",
+              "colors": [
+                "x",
+                "y",
+                "x",
+                "x",
+                "g"
+              ]
+            },
+            {
+              "guess": "queen",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        }
+      ]
     },
     {
       "id": 21,
       "word": "sugar",
-      "difficulty": 2.75
+      "difficulty": 2.75,
+      "replays": [
+        {
+          "solver": "Entropy",
+          "steps": [
+            {
+              "guess": "arise",
+              "colors": [
+                "y",
+                "y",
+                "x",
+                "y",
+                "x"
+              ]
+            },
+            {
+              "guess": "sharp",
+              "colors": [
+                "g",
+                "x",
+                "y",
+                "y",
+                "x"
+              ]
+            },
+            {
+              "guess": "sugar",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        },
+        {
+          "solver": "Frequency",
+          "steps": [
+            {
+              "guess": "alert",
+              "colors": [
+                "y",
+                "x",
+                "x",
+                "y",
+                "x"
+              ]
+            },
+            {
+              "guess": "grand",
+              "colors": [
+                "y",
+                "y",
+                "y",
+                "x",
+                "x"
+              ]
+            },
+            {
+              "guess": "sugar",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        },
+        {
+          "solver": "Vowel First",
+          "steps": [
+            {
+              "guess": "audio",
+              "colors": [
+                "y",
+                "g",
+                "x",
+                "x",
+                "x"
+              ]
+            },
+            {
+              "guess": "sugar",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        },
+        {
+          "solver": "Greedy",
+          "steps": [
+            {
+              "guess": "crane",
+              "colors": [
+                "x",
+                "y",
+                "y",
+                "x",
+                "x"
+              ]
+            },
+            {
+              "guess": "radio",
+              "colors": [
+                "y",
+                "y",
+                "x",
+                "x",
+                "x"
+              ]
+            },
+            {
+              "guess": "sugar",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        }
+      ]
     },
     {
       "id": 22,
       "word": "tiger",
-      "difficulty": 3
+      "difficulty": 3,
+      "replays": [
+        {
+          "solver": "Entropy",
+          "steps": [
+            {
+              "guess": "arise",
+              "colors": [
+                "x",
+                "y",
+                "y",
+                "x",
+                "y"
+              ]
+            },
+            {
+              "guess": "tired",
+              "colors": [
+                "g",
+                "g",
+                "y",
+                "g",
+                "x"
+              ]
+            },
+            {
+              "guess": "tiger",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        },
+        {
+          "solver": "Frequency",
+          "steps": [
+            {
+              "guess": "alert",
+              "colors": [
+                "x",
+                "x",
+                "y",
+                "y",
+                "y"
+              ]
+            },
+            {
+              "guess": "virtue",
+              "colors": [
+                "x",
+                "g",
+                "y",
+                "y",
+                "x"
+              ]
+            },
+            {
+              "guess": "tiger",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        },
+        {
+          "solver": "Vowel First",
+          "steps": [
+            {
+              "guess": "audio",
+              "colors": [
+                "x",
+                "x",
+                "x",
+                "y",
+                "x"
+              ]
+            },
+            {
+              "guess": "elite",
+              "colors": [
+                "y",
+                "x",
+                "y",
+                "y",
+                "x"
+              ]
+            },
+            {
+              "guess": "kitey",
+              "colors": [
+                "x",
+                "g",
+                "y",
+                "g",
+                "x"
+              ]
+            },
+            {
+              "guess": "tiger",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        },
+        {
+          "solver": "Greedy",
+          "steps": [
+            {
+              "guess": "crane",
+              "colors": [
+                "x",
+                "y",
+                "x",
+                "x",
+                "y"
+              ]
+            },
+            {
+              "guess": "tiger",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        }
+      ]
     },
     {
       "id": 23,
       "word": "vivid",
-      "difficulty": 3
+      "difficulty": 3,
+      "replays": [
+        {
+          "solver": "Entropy",
+          "steps": [
+            {
+              "guess": "arise",
+              "colors": [
+                "x",
+                "x",
+                "y",
+                "x",
+                "x"
+              ]
+            },
+            {
+              "guess": "limit",
+              "colors": [
+                "x",
+                "g",
+                "x",
+                "g",
+                "x"
+              ]
+            },
+            {
+              "guess": "vivid",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        },
+        {
+          "solver": "Frequency",
+          "steps": [
+            {
+              "guess": "alert",
+              "colors": [
+                "x",
+                "x",
+                "x",
+                "x",
+                "x"
+              ]
+            },
+            {
+              "guess": "sound",
+              "colors": [
+                "x",
+                "x",
+                "x",
+                "x",
+                "g"
+              ]
+            },
+            {
+              "guess": "vivid",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        },
+        {
+          "solver": "Vowel First",
+          "steps": [
+            {
+              "guess": "audio",
+              "colors": [
+                "x",
+                "x",
+                "y",
+                "g",
+                "x"
+              ]
+            },
+            {
+              "guess": "devil",
+              "colors": [
+                "y",
+                "x",
+                "g",
+                "g",
+                "x"
+              ]
+            },
+            {
+              "guess": "vivid",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        },
+        {
+          "solver": "Greedy",
+          "steps": [
+            {
+              "guess": "crane",
+              "colors": [
+                "x",
+                "x",
+                "x",
+                "x",
+                "x"
+              ]
+            },
+            {
+              "guess": "igloo",
+              "colors": [
+                "y",
+                "x",
+                "x",
+                "x",
+                "x"
+              ]
+            },
+            {
+              "guess": "vivid",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        }
+      ]
     },
     {
       "id": 24,
       "word": "waste",
-      "difficulty": 3
+      "difficulty": 3,
+      "replays": [
+        {
+          "solver": "Entropy",
+          "steps": [
+            {
+              "guess": "arise",
+              "colors": [
+                "y",
+                "x",
+                "x",
+                "y",
+                "g"
+              ]
+            },
+            {
+              "guess": "shake",
+              "colors": [
+                "y",
+                "x",
+                "y",
+                "x",
+                "g"
+              ]
+            },
+            {
+              "guess": "waste",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        },
+        {
+          "solver": "Frequency",
+          "steps": [
+            {
+              "guess": "alert",
+              "colors": [
+                "y",
+                "x",
+                "y",
+                "x",
+                "y"
+              ]
+            },
+            {
+              "guess": "stake",
+              "colors": [
+                "y",
+                "y",
+                "y",
+                "x",
+                "g"
+              ]
+            },
+            {
+              "guess": "waste",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        },
+        {
+          "solver": "Vowel First",
+          "steps": [
+            {
+              "guess": "audio",
+              "colors": [
+                "y",
+                "x",
+                "x",
+                "x",
+                "x"
+              ]
+            },
+            {
+              "guess": "eager",
+              "colors": [
+                "y",
+                "g",
+                "x",
+                "x",
+                "x"
+              ]
+            },
+            {
+              "guess": "waste",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        },
+        {
+          "solver": "Greedy",
+          "steps": [
+            {
+              "guess": "crane",
+              "colors": [
+                "x",
+                "x",
+                "y",
+                "x",
+                "g"
+              ]
+            },
+            {
+              "guess": "apple",
+              "colors": [
+                "y",
+                "x",
+                "x",
+                "x",
+                "g"
+              ]
+            },
+            {
+              "guess": "waste",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        }
+      ]
     },
     {
       "id": 25,
       "word": "yield",
-      "difficulty": 2.75
+      "difficulty": 2.75,
+      "replays": [
+        {
+          "solver": "Entropy",
+          "steps": [
+            {
+              "guess": "arise",
+              "colors": [
+                "x",
+                "x",
+                "y",
+                "x",
+                "y"
+              ]
+            },
+            {
+              "guess": "fixed",
+              "colors": [
+                "x",
+                "g",
+                "x",
+                "y",
+                "g"
+              ]
+            },
+            {
+              "guess": "yield",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        },
+        {
+          "solver": "Frequency",
+          "steps": [
+            {
+              "guess": "alert",
+              "colors": [
+                "x",
+                "y",
+                "g",
+                "x",
+                "x"
+              ]
+            },
+            {
+              "guess": "shelf",
+              "colors": [
+                "x",
+                "x",
+                "g",
+                "g",
+                "x"
+              ]
+            },
+            {
+              "guess": "yield",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        },
+        {
+          "solver": "Vowel First",
+          "steps": [
+            {
+              "guess": "audio",
+              "colors": [
+                "x",
+                "x",
+                "y",
+                "y",
+                "x"
+              ]
+            },
+            {
+              "guess": "yield",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        },
+        {
+          "solver": "Greedy",
+          "steps": [
+            {
+              "guess": "crane",
+              "colors": [
+                "x",
+                "x",
+                "x",
+                "x",
+                "y"
+              ]
+            },
+            {
+              "guess": "hello",
+              "colors": [
+                "x",
+                "y",
+                "x",
+                "g",
+                "x"
+              ]
+            },
+            {
+              "guess": "yield",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        }
+      ]
     },
     {
       "id": 26,
       "word": "zebra",
-      "difficulty": 3.25
+      "difficulty": 3.25,
+      "replays": [
+        {
+          "solver": "Entropy",
+          "steps": [
+            {
+              "guess": "arise",
+              "colors": [
+                "y",
+                "y",
+                "x",
+                "x",
+                "y"
+              ]
+            },
+            {
+              "guess": "later",
+              "colors": [
+                "x",
+                "y",
+                "x",
+                "y",
+                "y"
+              ]
+            },
+            {
+              "guess": "zebra",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        },
+        {
+          "solver": "Frequency",
+          "steps": [
+            {
+              "guess": "alert",
+              "colors": [
+                "y",
+                "x",
+                "y",
+                "g",
+                "x"
+              ]
+            },
+            {
+              "guess": "scare",
+              "colors": [
+                "x",
+                "x",
+                "y",
+                "g",
+                "y"
+              ]
+            },
+            {
+              "guess": "zebra",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        },
+        {
+          "solver": "Vowel First",
+          "steps": [
+            {
+              "guess": "audio",
+              "colors": [
+                "y",
+                "x",
+                "x",
+                "x",
+                "x"
+              ]
+            },
+            {
+              "guess": "eager",
+              "colors": [
+                "y",
+                "y",
+                "x",
+                "x",
+                "y"
+              ]
+            },
+            {
+              "guess": "crane",
+              "colors": [
+                "x",
+                "y",
+                "y",
+                "x",
+                "y"
+              ]
+            },
+            {
+              "guess": "zebra",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        },
+        {
+          "solver": "Greedy",
+          "steps": [
+            {
+              "guess": "crane",
+              "colors": [
+                "x",
+                "y",
+                "y",
+                "x",
+                "y"
+              ]
+            },
+            {
+              "guess": "eager",
+              "colors": [
+                "y",
+                "y",
+                "x",
+                "x",
+                "y"
+              ]
+            },
+            {
+              "guess": "zebra",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        }
+      ]
     },
     {
       "id": 27,
       "word": "ghost",
-      "difficulty": 3.5
+      "difficulty": 3.5,
+      "replays": [
+        {
+          "solver": "Entropy",
+          "steps": [
+            {
+              "guess": "arise",
+              "colors": [
+                "x",
+                "x",
+                "x",
+                "g",
+                "x"
+              ]
+            },
+            {
+              "guess": "flush",
+              "colors": [
+                "x",
+                "x",
+                "x",
+                "g",
+                "y"
+              ]
+            },
+            {
+              "guess": "ghost",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        },
+        {
+          "solver": "Frequency",
+          "steps": [
+            {
+              "guess": "alert",
+              "colors": [
+                "x",
+                "x",
+                "x",
+                "x",
+                "g"
+              ]
+            },
+            {
+              "guess": "sight",
+              "colors": [
+                "y",
+                "x",
+                "y",
+                "y",
+                "g"
+              ]
+            },
+            {
+              "guess": "ghost",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        },
+        {
+          "solver": "Vowel First",
+          "steps": [
+            {
+              "guess": "audio",
+              "colors": [
+                "x",
+                "x",
+                "x",
+                "x",
+                "y"
+              ]
+            },
+            {
+              "guess": "lemon",
+              "colors": [
+                "x",
+                "x",
+                "x",
+                "y",
+                "x"
+              ]
+            },
+            {
+              "guess": "forth",
+              "colors": [
+                "x",
+                "y",
+                "x",
+                "y",
+                "y"
+              ]
+            },
+            {
+              "guess": "ghost",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        },
+        {
+          "solver": "Greedy",
+          "steps": [
+            {
+              "guess": "crane",
+              "colors": [
+                "x",
+                "x",
+                "x",
+                "x",
+                "x"
+              ]
+            },
+            {
+              "guess": "igloo",
+              "colors": [
+                "x",
+                "y",
+                "x",
+                "y",
+                "x"
+              ]
+            },
+            {
+              "guess": "dough",
+              "colors": [
+                "x",
+                "y",
+                "x",
+                "y",
+                "y"
+              ]
+            },
+            {
+              "guess": "ghost",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        }
+      ]
     },
     {
       "id": 28,
       "word": "judge",
-      "difficulty": 3.25
+      "difficulty": 3.25,
+      "replays": [
+        {
+          "solver": "Entropy",
+          "steps": [
+            {
+              "guess": "arise",
+              "colors": [
+                "x",
+                "x",
+                "x",
+                "x",
+                "g"
+              ]
+            },
+            {
+              "guess": "uncle",
+              "colors": [
+                "y",
+                "x",
+                "x",
+                "x",
+                "g"
+              ]
+            },
+            {
+              "guess": "queue",
+              "colors": [
+                "x",
+                "g",
+                "x",
+                "x",
+                "g"
+              ]
+            },
+            {
+              "guess": "judge",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        },
+        {
+          "solver": "Frequency",
+          "steps": [
+            {
+              "guess": "alert",
+              "colors": [
+                "x",
+                "x",
+                "y",
+                "x",
+                "x"
+              ]
+            },
+            {
+              "guess": "noise",
+              "colors": [
+                "x",
+                "x",
+                "x",
+                "x",
+                "g"
+              ]
+            },
+            {
+              "guess": "judge",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        },
+        {
+          "solver": "Vowel First",
+          "steps": [
+            {
+              "guess": "audio",
+              "colors": [
+                "x",
+                "g",
+                "g",
+                "x",
+                "x"
+              ]
+            },
+            {
+              "guess": "judge",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        },
+        {
+          "solver": "Greedy",
+          "steps": [
+            {
+              "guess": "crane",
+              "colors": [
+                "x",
+                "x",
+                "x",
+                "x",
+                "g"
+              ]
+            },
+            {
+              "guess": "style",
+              "colors": [
+                "x",
+                "x",
+                "x",
+                "x",
+                "g"
+              ]
+            },
+            {
+              "guess": "guide",
+              "colors": [
+                "y",
+                "g",
+                "x",
+                "y",
+                "g"
+              ]
+            },
+            {
+              "guess": "judge",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        }
+      ]
     },
     {
       "id": 29,
       "word": "knife",
-      "difficulty": 4
+      "difficulty": 4,
+      "replays": [
+        {
+          "solver": "Entropy",
+          "steps": [
+            {
+              "guess": "arise",
+              "colors": [
+                "x",
+                "x",
+                "g",
+                "x",
+                "g"
+              ]
+            },
+            {
+              "guess": "elite",
+              "colors": [
+                "x",
+                "x",
+                "g",
+                "x",
+                "g"
+              ]
+            },
+            {
+              "guess": "oxide",
+              "colors": [
+                "x",
+                "x",
+                "g",
+                "x",
+                "g"
+              ]
+            },
+            {
+              "guess": "juice",
+              "colors": [
+                "x",
+                "x",
+                "g",
+                "x",
+                "g"
+              ]
+            },
+            {
+              "guess": "knife",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        },
+        {
+          "solver": "Frequency",
+          "steps": [
+            {
+              "guess": "alert",
+              "colors": [
+                "x",
+                "x",
+                "y",
+                "x",
+                "x"
+              ]
+            },
+            {
+              "guess": "noise",
+              "colors": [
+                "y",
+                "x",
+                "g",
+                "x",
+                "g"
+              ]
+            },
+            {
+              "guess": "knife",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        },
+        {
+          "solver": "Vowel First",
+          "steps": [
+            {
+              "guess": "audio",
+              "colors": [
+                "x",
+                "x",
+                "x",
+                "y",
+                "x"
+              ]
+            },
+            {
+              "guess": "elite",
+              "colors": [
+                "x",
+                "x",
+                "g",
+                "x",
+                "g"
+              ]
+            },
+            {
+              "guess": "crime",
+              "colors": [
+                "x",
+                "x",
+                "g",
+                "x",
+                "g"
+              ]
+            },
+            {
+              "guess": "knife",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        },
+        {
+          "solver": "Greedy",
+          "steps": [
+            {
+              "guess": "crane",
+              "colors": [
+                "x",
+                "x",
+                "x",
+                "y",
+                "g"
+              ]
+            },
+            {
+              "guess": "noble",
+              "colors": [
+                "y",
+                "x",
+                "x",
+                "x",
+                "g"
+              ]
+            },
+            {
+              "guess": "dense",
+              "colors": [
+                "x",
+                "x",
+                "y",
+                "x",
+                "g"
+              ]
+            },
+            {
+              "guess": "knife",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        }
+      ]
     },
     {
       "id": 30,
       "word": "lucky",
-      "difficulty": 3.5
+      "difficulty": 3.5,
+      "replays": [
+        {
+          "solver": "Entropy",
+          "steps": [
+            {
+              "guess": "arise",
+              "colors": [
+                "x",
+                "x",
+                "x",
+                "x",
+                "x"
+              ]
+            },
+            {
+              "guess": "count",
+              "colors": [
+                "y",
+                "x",
+                "y",
+                "x",
+                "x"
+              ]
+            },
+            {
+              "guess": "lucky",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        },
+        {
+          "solver": "Frequency",
+          "steps": [
+            {
+              "guess": "alert",
+              "colors": [
+                "x",
+                "y",
+                "x",
+                "x",
+                "x"
+              ]
+            },
+            {
+              "guess": "guild",
+              "colors": [
+                "x",
+                "g",
+                "x",
+                "y",
+                "x"
+              ]
+            },
+            {
+              "guess": "lucky",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        },
+        {
+          "solver": "Vowel First",
+          "steps": [
+            {
+              "guess": "audio",
+              "colors": [
+                "x",
+                "g",
+                "x",
+                "x",
+                "x"
+              ]
+            },
+            {
+              "guess": "queen",
+              "colors": [
+                "x",
+                "g",
+                "x",
+                "x",
+                "x"
+              ]
+            },
+            {
+              "guess": "burst",
+              "colors": [
+                "x",
+                "g",
+                "x",
+                "x",
+                "x"
+              ]
+            },
+            {
+              "guess": "fully",
+              "colors": [
+                "x",
+                "g",
+                "y",
+                "x",
+                "g"
+              ]
+            },
+            {
+              "guess": "lucky",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        },
+        {
+          "solver": "Greedy",
+          "steps": [
+            {
+              "guess": "crane",
+              "colors": [
+                "y",
+                "x",
+                "x",
+                "x",
+                "x"
+              ]
+            },
+            {
+              "guess": "block",
+              "colors": [
+                "x",
+                "y",
+                "x",
+                "y",
+                "y"
+              ]
+            },
+            {
+              "guess": "lucky",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        }
+      ]
     },
     {
       "id": 31,
       "word": "movie",
-      "difficulty": 3
+      "difficulty": 3,
+      "replays": [
+        {
+          "solver": "Entropy",
+          "steps": [
+            {
+              "guess": "arise",
+              "colors": [
+                "x",
+                "x",
+                "y",
+                "x",
+                "g"
+              ]
+            },
+            {
+              "guess": "indie",
+              "colors": [
+                "x",
+                "x",
+                "x",
+                "g",
+                "g"
+              ]
+            },
+            {
+              "guess": "movie",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        },
+        {
+          "solver": "Frequency",
+          "steps": [
+            {
+              "guess": "alert",
+              "colors": [
+                "x",
+                "x",
+                "y",
+                "x",
+                "x"
+              ]
+            },
+            {
+              "guess": "noise",
+              "colors": [
+                "x",
+                "g",
+                "y",
+                "x",
+                "g"
+              ]
+            },
+            {
+              "guess": "movie",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        },
+        {
+          "solver": "Vowel First",
+          "steps": [
+            {
+              "guess": "audio",
+              "colors": [
+                "x",
+                "x",
+                "x",
+                "g",
+                "y"
+              ]
+            },
+            {
+              "guess": "movie",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        },
+        {
+          "solver": "Greedy",
+          "steps": [
+            {
+              "guess": "crane",
+              "colors": [
+                "x",
+                "x",
+                "x",
+                "x",
+                "g"
+              ]
+            },
+            {
+              "guess": "style",
+              "colors": [
+                "x",
+                "x",
+                "x",
+                "x",
+                "g"
+              ]
+            },
+            {
+              "guess": "guide",
+              "colors": [
+                "x",
+                "x",
+                "y",
+                "x",
+                "g"
+              ]
+            },
+            {
+              "guess": "movie",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        }
+      ]
     },
     {
       "id": 32,
       "word": "prize",
-      "difficulty": 4.5
+      "difficulty": 4.5,
+      "replays": [
+        {
+          "solver": "Entropy",
+          "steps": [
+            {
+              "guess": "arise",
+              "colors": [
+                "x",
+                "g",
+                "g",
+                "x",
+                "g"
+              ]
+            },
+            {
+              "guess": "price",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "x",
+                "g"
+              ]
+            },
+            {
+              "guess": "pride",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "x",
+                "g"
+              ]
+            },
+            {
+              "guess": "prime",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "x",
+                "g"
+              ]
+            },
+            {
+              "guess": "prize",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        },
+        {
+          "solver": "Frequency",
+          "steps": [
+            {
+              "guess": "alert",
+              "colors": [
+                "x",
+                "x",
+                "y",
+                "y",
+                "x"
+              ]
+            },
+            {
+              "guess": "drove",
+              "colors": [
+                "x",
+                "g",
+                "x",
+                "x",
+                "g"
+              ]
+            },
+            {
+              "guess": "price",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "x",
+                "g"
+              ]
+            },
+            {
+              "guess": "prime",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "x",
+                "g"
+              ]
+            },
+            {
+              "guess": "prize",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        },
+        {
+          "solver": "Vowel First",
+          "steps": [
+            {
+              "guess": "audio",
+              "colors": [
+                "x",
+                "x",
+                "x",
+                "y",
+                "x"
+              ]
+            },
+            {
+              "guess": "elite",
+              "colors": [
+                "x",
+                "x",
+                "g",
+                "x",
+                "g"
+              ]
+            },
+            {
+              "guess": "crime",
+              "colors": [
+                "x",
+                "g",
+                "g",
+                "x",
+                "g"
+              ]
+            },
+            {
+              "guess": "prize",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        },
+        {
+          "solver": "Greedy",
+          "steps": [
+            {
+              "guess": "crane",
+              "colors": [
+                "x",
+                "g",
+                "x",
+                "x",
+                "g"
+              ]
+            },
+            {
+              "guess": "drive",
+              "colors": [
+                "x",
+                "g",
+                "g",
+                "x",
+                "g"
+              ]
+            },
+            {
+              "guess": "prime",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "x",
+                "g"
+              ]
+            },
+            {
+              "guess": "prize",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        }
+      ]
     },
     {
       "id": 33,
       "word": "quiet",
-      "difficulty": 3.25
+      "difficulty": 3.25,
+      "replays": [
+        {
+          "solver": "Entropy",
+          "steps": [
+            {
+              "guess": "arise",
+              "colors": [
+                "x",
+                "x",
+                "g",
+                "x",
+                "y"
+              ]
+            },
+            {
+              "guess": "chief",
+              "colors": [
+                "x",
+                "x",
+                "g",
+                "g",
+                "x"
+              ]
+            },
+            {
+              "guess": "quiet",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        },
+        {
+          "solver": "Frequency",
+          "steps": [
+            {
+              "guess": "alert",
+              "colors": [
+                "x",
+                "x",
+                "y",
+                "x",
+                "g"
+              ]
+            },
+            {
+              "guess": "exist",
+              "colors": [
+                "y",
+                "x",
+                "g",
+                "x",
+                "g"
+              ]
+            },
+            {
+              "guess": "quiet",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        },
+        {
+          "solver": "Vowel First",
+          "steps": [
+            {
+              "guess": "audio",
+              "colors": [
+                "x",
+                "g",
+                "x",
+                "y",
+                "x"
+              ]
+            },
+            {
+              "guess": "juice",
+              "colors": [
+                "x",
+                "g",
+                "g",
+                "x",
+                "y"
+              ]
+            },
+            {
+              "guess": "quiet",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        },
+        {
+          "solver": "Greedy",
+          "steps": [
+            {
+              "guess": "crane",
+              "colors": [
+                "x",
+                "x",
+                "x",
+                "x",
+                "y"
+              ]
+            },
+            {
+              "guess": "hello",
+              "colors": [
+                "x",
+                "y",
+                "x",
+                "x",
+                "x"
+              ]
+            },
+            {
+              "guess": "kitey",
+              "colors": [
+                "x",
+                "y",
+                "y",
+                "g",
+                "x"
+              ]
+            },
+            {
+              "guess": "quiet",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        }
+      ]
     },
     {
       "id": 34,
       "word": "solar",
-      "difficulty": 4.75
+      "difficulty": 4.75,
+      "replays": [
+        {
+          "solver": "Entropy",
+          "steps": [
+            {
+              "guess": "arise",
+              "colors": [
+                "y",
+                "y",
+                "x",
+                "y",
+                "x"
+              ]
+            },
+            {
+              "guess": "sharp",
+              "colors": [
+                "g",
+                "x",
+                "y",
+                "y",
+                "x"
+              ]
+            },
+            {
+              "guess": "sugar",
+              "colors": [
+                "g",
+                "x",
+                "x",
+                "g",
+                "g"
+              ]
+            },
+            {
+              "guess": "solar",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        },
+        {
+          "solver": "Frequency",
+          "steps": [
+            {
+              "guess": "alert",
+              "colors": [
+                "y",
+                "y",
+                "x",
+                "y",
+                "x"
+              ]
+            },
+            {
+              "guess": "royal",
+              "colors": [
+                "y",
+                "g",
+                "x",
+                "g",
+                "y"
+              ]
+            },
+            {
+              "guess": "polar",
+              "colors": [
+                "x",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            },
+            {
+              "guess": "solar",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        },
+        {
+          "solver": "Vowel First",
+          "steps": [
+            {
+              "guess": "audio",
+              "colors": [
+                "y",
+                "x",
+                "x",
+                "x",
+                "y"
+              ]
+            },
+            {
+              "guess": "ocean",
+              "colors": [
+                "y",
+                "x",
+                "x",
+                "g",
+                "x"
+              ]
+            },
+            {
+              "guess": "float",
+              "colors": [
+                "x",
+                "y",
+                "y",
+                "g",
+                "x"
+              ]
+            },
+            {
+              "guess": "loyal",
+              "colors": [
+                "y",
+                "g",
+                "x",
+                "g",
+                "x"
+              ]
+            },
+            {
+              "guess": "polar",
+              "colors": [
+                "x",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            },
+            {
+              "guess": "solar",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        },
+        {
+          "solver": "Greedy",
+          "steps": [
+            {
+              "guess": "crane",
+              "colors": [
+                "x",
+                "y",
+                "y",
+                "x",
+                "x"
+              ]
+            },
+            {
+              "guess": "radio",
+              "colors": [
+                "y",
+                "y",
+                "x",
+                "x",
+                "y"
+              ]
+            },
+            {
+              "guess": "moral",
+              "colors": [
+                "x",
+                "g",
+                "y",
+                "g",
+                "y"
+              ]
+            },
+            {
+              "guess": "polar",
+              "colors": [
+                "x",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            },
+            {
+              "guess": "solar",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        }
+      ]
     },
     {
       "id": 35,
       "word": "truly",
-      "difficulty": 3.5
+      "difficulty": 3.5,
+      "replays": [
+        {
+          "solver": "Entropy",
+          "steps": [
+            {
+              "guess": "arise",
+              "colors": [
+                "x",
+                "g",
+                "x",
+                "x",
+                "x"
+              ]
+            },
+            {
+              "guess": "trunk",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "x",
+                "x"
+              ]
+            },
+            {
+              "guess": "truly",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        },
+        {
+          "solver": "Frequency",
+          "steps": [
+            {
+              "guess": "alert",
+              "colors": [
+                "x",
+                "y",
+                "x",
+                "y",
+                "y"
+              ]
+            },
+            {
+              "guess": "truly",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        },
+        {
+          "solver": "Vowel First",
+          "steps": [
+            {
+              "guess": "audio",
+              "colors": [
+                "x",
+                "y",
+                "x",
+                "x",
+                "x"
+              ]
+            },
+            {
+              "guess": "venue",
+              "colors": [
+                "x",
+                "x",
+                "x",
+                "y",
+                "x"
+              ]
+            },
+            {
+              "guess": "brush",
+              "colors": [
+                "x",
+                "g",
+                "g",
+                "x",
+                "x"
+              ]
+            },
+            {
+              "guess": "truck",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "x",
+                "x"
+              ]
+            },
+            {
+              "guess": "truly",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        },
+        {
+          "solver": "Greedy",
+          "steps": [
+            {
+              "guess": "crane",
+              "colors": [
+                "x",
+                "g",
+                "x",
+                "x",
+                "x"
+              ]
+            },
+            {
+              "guess": "brook",
+              "colors": [
+                "x",
+                "g",
+                "x",
+                "x",
+                "x"
+              ]
+            },
+            {
+              "guess": "drift",
+              "colors": [
+                "x",
+                "g",
+                "x",
+                "x",
+                "y"
+              ]
+            },
+            {
+              "guess": "truly",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        }
+      ]
     },
     {
       "id": 36,
       "word": "vital",
-      "difficulty": 4.25
+      "difficulty": 4.25,
+      "replays": [
+        {
+          "solver": "Entropy",
+          "steps": [
+            {
+              "guess": "arise",
+              "colors": [
+                "y",
+                "x",
+                "y",
+                "x",
+                "x"
+              ]
+            },
+            {
+              "guess": "panic",
+              "colors": [
+                "x",
+                "y",
+                "x",
+                "y",
+                "x"
+              ]
+            },
+            {
+              "guess": "tidal",
+              "colors": [
+                "y",
+                "g",
+                "x",
+                "g",
+                "g"
+              ]
+            },
+            {
+              "guess": "vital",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        },
+        {
+          "solver": "Frequency",
+          "steps": [
+            {
+              "guess": "alert",
+              "colors": [
+                "y",
+                "y",
+                "x",
+                "x",
+                "y"
+              ]
+            },
+            {
+              "guess": "tidal",
+              "colors": [
+                "y",
+                "g",
+                "x",
+                "g",
+                "g"
+              ]
+            },
+            {
+              "guess": "vital",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        },
+        {
+          "solver": "Vowel First",
+          "steps": [
+            {
+              "guess": "audio",
+              "colors": [
+                "y",
+                "x",
+                "x",
+                "y",
+                "x"
+              ]
+            },
+            {
+              "guess": "image",
+              "colors": [
+                "y",
+                "x",
+                "y",
+                "x",
+                "x"
+              ]
+            },
+            {
+              "guess": "china",
+              "colors": [
+                "x",
+                "x",
+                "y",
+                "x",
+                "y"
+              ]
+            },
+            {
+              "guess": "rival",
+              "colors": [
+                "x",
+                "g",
+                "y",
+                "g",
+                "g"
+              ]
+            },
+            {
+              "guess": "vital",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        },
+        {
+          "solver": "Greedy",
+          "steps": [
+            {
+              "guess": "crane",
+              "colors": [
+                "x",
+                "x",
+                "y",
+                "x",
+                "x"
+              ]
+            },
+            {
+              "guess": "happy",
+              "colors": [
+                "x",
+                "y",
+                "x",
+                "x",
+                "x"
+              ]
+            },
+            {
+              "guess": "about",
+              "colors": [
+                "y",
+                "x",
+                "x",
+                "x",
+                "y"
+              ]
+            },
+            {
+              "guess": "tidal",
+              "colors": [
+                "y",
+                "g",
+                "x",
+                "g",
+                "g"
+              ]
+            },
+            {
+              "guess": "vital",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        }
+      ]
     },
     {
       "id": 37,
       "word": "wheat",
-      "difficulty": 3.25
+      "difficulty": 3.25,
+      "replays": [
+        {
+          "solver": "Entropy",
+          "steps": [
+            {
+              "guess": "arise",
+              "colors": [
+                "y",
+                "x",
+                "x",
+                "x",
+                "y"
+              ]
+            },
+            {
+              "guess": "metal",
+              "colors": [
+                "x",
+                "y",
+                "y",
+                "g",
+                "x"
+              ]
+            },
+            {
+              "guess": "wheat",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        },
+        {
+          "solver": "Frequency",
+          "steps": [
+            {
+              "guess": "alert",
+              "colors": [
+                "y",
+                "x",
+                "g",
+                "x",
+                "g"
+              ]
+            },
+            {
+              "guess": "wheat",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        },
+        {
+          "solver": "Vowel First",
+          "steps": [
+            {
+              "guess": "audio",
+              "colors": [
+                "y",
+                "x",
+                "x",
+                "x",
+                "x"
+              ]
+            },
+            {
+              "guess": "eager",
+              "colors": [
+                "y",
+                "y",
+                "x",
+                "x",
+                "x"
+              ]
+            },
+            {
+              "guess": "flame",
+              "colors": [
+                "x",
+                "x",
+                "y",
+                "x",
+                "y"
+              ]
+            },
+            {
+              "guess": "cheap",
+              "colors": [
+                "x",
+                "g",
+                "g",
+                "g",
+                "x"
+              ]
+            },
+            {
+              "guess": "wheat",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        },
+        {
+          "solver": "Greedy",
+          "steps": [
+            {
+              "guess": "crane",
+              "colors": [
+                "x",
+                "x",
+                "y",
+                "x",
+                "y"
+              ]
+            },
+            {
+              "guess": "ahead",
+              "colors": [
+                "x",
+                "g",
+                "g",
+                "g",
+                "x"
+              ]
+            },
+            {
+              "guess": "wheat",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        }
+      ]
     },
     {
       "id": 38,
       "word": "xenon",
-      "difficulty": 3.25
+      "difficulty": 3.25,
+      "replays": [
+        {
+          "solver": "Entropy",
+          "steps": [
+            {
+              "guess": "arise",
+              "colors": [
+                "x",
+                "x",
+                "x",
+                "x",
+                "y"
+              ]
+            },
+            {
+              "guess": "lemon",
+              "colors": [
+                "x",
+                "g",
+                "x",
+                "g",
+                "g"
+              ]
+            },
+            {
+              "guess": "xenon",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        },
+        {
+          "solver": "Frequency",
+          "steps": [
+            {
+              "guess": "alert",
+              "colors": [
+                "x",
+                "x",
+                "y",
+                "x",
+                "x"
+              ]
+            },
+            {
+              "guess": "noise",
+              "colors": [
+                "y",
+                "y",
+                "x",
+                "x",
+                "y"
+              ]
+            },
+            {
+              "guess": "enjoy",
+              "colors": [
+                "y",
+                "y",
+                "x",
+                "g",
+                "x"
+              ]
+            },
+            {
+              "guess": "xenon",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        },
+        {
+          "solver": "Vowel First",
+          "steps": [
+            {
+              "guess": "audio",
+              "colors": [
+                "x",
+                "x",
+                "x",
+                "x",
+                "y"
+              ]
+            },
+            {
+              "guess": "lemon",
+              "colors": [
+                "x",
+                "g",
+                "x",
+                "g",
+                "g"
+              ]
+            },
+            {
+              "guess": "xenon",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        },
+        {
+          "solver": "Greedy",
+          "steps": [
+            {
+              "guess": "crane",
+              "colors": [
+                "x",
+                "x",
+                "x",
+                "y",
+                "y"
+              ]
+            },
+            {
+              "guess": "lemon",
+              "colors": [
+                "x",
+                "g",
+                "x",
+                "g",
+                "g"
+              ]
+            },
+            {
+              "guess": "xenon",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        }
+      ]
     },
     {
       "id": 39,
       "word": "yacht",
-      "difficulty": 3.25
+      "difficulty": 3.25,
+      "replays": [
+        {
+          "solver": "Entropy",
+          "steps": [
+            {
+              "guess": "arise",
+              "colors": [
+                "y",
+                "x",
+                "x",
+                "x",
+                "x"
+              ]
+            },
+            {
+              "guess": "batch",
+              "colors": [
+                "x",
+                "g",
+                "y",
+                "y",
+                "y"
+              ]
+            },
+            {
+              "guess": "yacht",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        },
+        {
+          "solver": "Frequency",
+          "steps": [
+            {
+              "guess": "alert",
+              "colors": [
+                "y",
+                "x",
+                "x",
+                "x",
+                "g"
+              ]
+            },
+            {
+              "guess": "saint",
+              "colors": [
+                "x",
+                "g",
+                "x",
+                "x",
+                "g"
+              ]
+            },
+            {
+              "guess": "yacht",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        },
+        {
+          "solver": "Vowel First",
+          "steps": [
+            {
+              "guess": "audio",
+              "colors": [
+                "y",
+                "x",
+                "x",
+                "x",
+                "x"
+              ]
+            },
+            {
+              "guess": "eager",
+              "colors": [
+                "x",
+                "g",
+                "x",
+                "x",
+                "x"
+              ]
+            },
+            {
+              "guess": "batch",
+              "colors": [
+                "x",
+                "g",
+                "y",
+                "y",
+                "y"
+              ]
+            },
+            {
+              "guess": "yacht",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        },
+        {
+          "solver": "Greedy",
+          "steps": [
+            {
+              "guess": "crane",
+              "colors": [
+                "y",
+                "x",
+                "y",
+                "x",
+                "x"
+              ]
+            },
+            {
+              "guess": "attic",
+              "colors": [
+                "y",
+                "y",
+                "x",
+                "x",
+                "y"
+              ]
+            },
+            {
+              "guess": "yacht",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        }
+      ]
     },
     {
       "id": 40,
       "word": "zebra",
-      "difficulty": 3.25
+      "difficulty": 3.25,
+      "replays": [
+        {
+          "solver": "Entropy",
+          "steps": [
+            {
+              "guess": "arise",
+              "colors": [
+                "y",
+                "y",
+                "x",
+                "x",
+                "y"
+              ]
+            },
+            {
+              "guess": "later",
+              "colors": [
+                "x",
+                "y",
+                "x",
+                "y",
+                "y"
+              ]
+            },
+            {
+              "guess": "zebra",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        },
+        {
+          "solver": "Frequency",
+          "steps": [
+            {
+              "guess": "alert",
+              "colors": [
+                "y",
+                "x",
+                "y",
+                "g",
+                "x"
+              ]
+            },
+            {
+              "guess": "scare",
+              "colors": [
+                "x",
+                "x",
+                "y",
+                "g",
+                "y"
+              ]
+            },
+            {
+              "guess": "zebra",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        },
+        {
+          "solver": "Vowel First",
+          "steps": [
+            {
+              "guess": "audio",
+              "colors": [
+                "y",
+                "x",
+                "x",
+                "x",
+                "x"
+              ]
+            },
+            {
+              "guess": "eager",
+              "colors": [
+                "y",
+                "y",
+                "x",
+                "x",
+                "y"
+              ]
+            },
+            {
+              "guess": "crane",
+              "colors": [
+                "x",
+                "y",
+                "y",
+                "x",
+                "y"
+              ]
+            },
+            {
+              "guess": "zebra",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        },
+        {
+          "solver": "Greedy",
+          "steps": [
+            {
+              "guess": "crane",
+              "colors": [
+                "x",
+                "y",
+                "y",
+                "x",
+                "y"
+              ]
+            },
+            {
+              "guess": "eager",
+              "colors": [
+                "y",
+                "y",
+                "x",
+                "x",
+                "y"
+              ]
+            },
+            {
+              "guess": "zebra",
+              "colors": [
+                "g",
+                "g",
+                "g",
+                "g",
+                "g"
+              ]
+            }
+          ]
+        }
+      ]
     }
   ]
 }

+ 4 - 1
server/src/routes/guess.ts

@@ -50,9 +50,12 @@ export function createGuessRouter(wordBank: WordBank): Router {
       response.word = target.word;
     }
 
-    // Include difficulty on final guess (win or loss)
+    // Include difficulty and replays on final guess (win or loss)
     if (correct || isLastAttempt) {
       response.difficulty = target.difficulty;
+      if (target.replays) {
+        response.replays = target.replays;
+      }
     }
 
     res.json(response);

+ 3 - 5
server/src/validate.ts

@@ -1,4 +1,4 @@
-import type { WordBank } from '@wordle/shared';
+import type { WordBank, TargetWord } from '@wordle/shared';
 
 /**
  * Check whether a guess is in the word bank's guessable list.
@@ -14,8 +14,6 @@ export function isValidGuess(wordBank: WordBank, guess: string): boolean {
 export function getTargetWord(
   wordBank: WordBank,
   wordId: number
-): { word: string; difficulty: number } | undefined {
-  const target = wordBank.targets.find((t) => t.id === wordId);
-  if (!target) return undefined;
-  return { word: target.word, difficulty: target.difficulty };
+): TargetWord | undefined {
+  return wordBank.targets.find((t) => t.id === wordId);
 }

+ 2 - 0
shared/src/api.ts

@@ -22,6 +22,8 @@ export interface GuessResponse {
   word?: string;
   /** Word difficulty score, included on final guess response (win or loss). */
   difficulty?: number;
+  /** Solver replays, included on final guess response. */
+  replays?: import('./word-bank.js').SolverReplay[];
 }
 
 /** POST /api/play-again request */

+ 13 - 0
shared/src/word-bank.ts

@@ -1,8 +1,21 @@
+/** A single solver replay step */
+export interface SolverStep {
+  guess: string;
+  colors: string[];
+}
+
+/** Replay from one solver algorithm */
+export interface SolverReplay {
+  solver: string;
+  steps: SolverStep[];
+}
+
 /** A target word with its pre-computed difficulty score */
 export interface TargetWord {
   id: number;
   word: string;
   difficulty: number;
+  replays?: SolverReplay[];
 }
 
 /** The complete word bank structure */

Файловите разлики са ограничени, защото са твърде много
+ 0 - 0
shared/tsconfig.tsbuildinfo


+ 24 - 57
solver/src/entropy.ts

@@ -1,90 +1,57 @@
-/**
- * Entropy-based Wordle solver.
- * At each step, picks the guess that maximizes expected information gain
- * (minimizes expected remaining candidates).
- */
+import type { SolverStep } from '@wordle/shared';
 
 const ALL_FEEDBACK: string[] = [];
 
 function buildFeedbackPatterns(): string[] {
   if (ALL_FEEDBACK.length > 0) return ALL_FEEDBACK;
   const colors = ['g', 'y', 'x'];
-  // Generate all 3^5 = 243 possible feedback patterns
   for (let i = 0; i < 243; i++) {
-    let n = i;
-    const pattern: string[] = [];
-    for (let j = 0; j < 5; j++) {
-      pattern.push(colors[n % 3]);
-      n = Math.floor(n / 3);
-    }
-    ALL_FEEDBACK.push(pattern.join(''));
+    let n = i; const p: string[] = [];
+    for (let j = 0; j < 5; j++) { p.push(colors[n % 3]); n = Math.floor(n / 3); }
+    ALL_FEEDBACK.push(p.join(''));
   }
   return ALL_FEEDBACK;
 }
 
 function getFeedback(target: string, guess: string): string {
-  const targetUpper = target.toLowerCase();
-  const guessUpper = guess.toLowerCase();
+  const tu = target.toLowerCase(), gu = guess.toLowerCase();
   const counts: Record<string, number> = {};
-  for (const ch of targetUpper) counts[ch] = (counts[ch] ?? 0) + 1;
-
-  const result: string[] = Array(5).fill('x');
-  for (let i = 0; i < 5; i++) {
-    if (guessUpper[i] === targetUpper[i]) {
-      result[i] = 'g';
-      counts[guessUpper[i]]--;
-    }
-  }
-  for (let i = 0; i < 5; i++) {
-    if (result[i] === 'g') continue;
-    if ((counts[guessUpper[i]] ?? 0) > 0) {
-      result[i] = 'y';
-      counts[guessUpper[i]]--;
-    }
-  }
-  return result.join('');
+  for (const ch of tu) counts[ch] = (counts[ch] ?? 0) + 1;
+  const r: string[] = Array(5).fill('x');
+  for (let i = 0; i < 5; i++) { if (gu[i] === tu[i]) { r[i] = 'g'; counts[gu[i]]--; } }
+  for (let i = 0; i < 5; i++) { if (r[i] === 'g') continue; if ((counts[gu[i]] ?? 0) > 0) { r[i] = 'y'; counts[gu[i]]--; } }
+  return r.join('');
 }
 
-/**
- * Solve a single word using entropy-based strategy.
- * Returns the number of attempts (1-6) or 7+ if failed.
- */
-export function solveEntropy(target: string, allWords: string[], maxAttempts = 6): number {
+export function solveEntropy(target: string, allWords: string[], maxAttempts = 6): { attempts: number; steps: SolverStep[] } {
   buildFeedbackPatterns();
   let candidates = [...allWords];
+  const steps: SolverStep[] = [];
 
   for (let attempt = 1; attempt <= maxAttempts; attempt++) {
-    // Pick best guess
     let bestGuess = candidates[0];
     let bestEntropy = Infinity;
+    const pool = attempt === 1 ? allWords : candidates;
 
-    const guessPool = attempt === 1 ? allWords : candidates;
-
-    for (const guess of guessPool) {
-      // Group candidates by feedback pattern for this guess
+    for (const guess of pool) {
       const buckets: Map<string, number> = new Map();
-      for (const candidate of candidates) {
-        const fb = getFeedback(candidate, guess);
+      for (const c of candidates) {
+        const fb = getFeedback(c, guess);
         buckets.set(fb, (buckets.get(fb) ?? 0) + 1);
       }
-      // Expected remaining candidates = weighted average of bucket sizes
-      let expectedSize = 0;
-      for (const count of buckets.values()) {
-        expectedSize += (count / candidates.length) * count;
-      }
-      if (expectedSize < bestEntropy) {
-        bestEntropy = expectedSize;
-        bestGuess = guess;
-      }
+      let expected = 0;
+      for (const count of buckets.values()) expected += (count / candidates.length) * count;
+      if (expected < bestEntropy) { bestEntropy = expected; bestGuess = guess; }
     }
 
     const fb = getFeedback(target, bestGuess);
-    if (fb === 'ggggg') return attempt;
+    steps.push({ guess: bestGuess, colors: fb.split('') });
+
+    if (fb === 'ggggg') return { attempts: attempt, steps };
 
-    // Filter candidates
     candidates = candidates.filter((c) => getFeedback(c, bestGuess) === fb);
-    if (candidates.length === 0) return maxAttempts + 1; // should not happen
+    if (candidates.length === 0) return { attempts: maxAttempts + 1, steps };
   }
 
-  return maxAttempts + 1; // failed
+  return { attempts: maxAttempts + 1, steps };
 }

+ 18 - 47
solver/src/frequency.ts

@@ -1,76 +1,47 @@
-/**
- * Frequency/heuristic-based Wordle solver.
- * Picks guesses based on letter frequency in remaining candidates.
- * Simpler and faster than entropy, providing an alternative perspective on difficulty.
- */
+import type { SolverStep } from '@wordle/shared';
 
 function getFeedback(target: string, guess: string): string {
-  const tu = target.toLowerCase();
-  const gu = guess.toLowerCase();
+  const tu = target.toLowerCase(), gu = guess.toLowerCase();
   const counts: Record<string, number> = {};
   for (const ch of tu) counts[ch] = (counts[ch] ?? 0) + 1;
-
-  const result: string[] = Array(5).fill('x');
-  for (let i = 0; i < 5; i++) {
-    if (gu[i] === tu[i]) { result[i] = 'g'; counts[gu[i]]--; }
-  }
-  for (let i = 0; i < 5; i++) {
-    if (result[i] === 'g') continue;
-    if ((counts[gu[i]] ?? 0) > 0) { result[i] = 'y'; counts[gu[i]]--; }
-  }
-  return result.join('');
+  const r: string[] = Array(5).fill('x');
+  for (let i = 0; i < 5; i++) { if (gu[i] === tu[i]) { r[i] = 'g'; counts[gu[i]]--; } }
+  for (let i = 0; i < 5; i++) { if (r[i] === 'g') continue; if ((counts[gu[i]] ?? 0) > 0) { r[i] = 'y'; counts[gu[i]]--; } }
+  return r.join('');
 }
 
 function letterFrequency(words: string[]): Record<string, number> {
   const freq: Record<string, number> = {};
   for (const w of words) {
     const seen = new Set<string>();
-    for (const ch of w) {
-      if (!seen.has(ch)) {
-        freq[ch] = (freq[ch] ?? 0) + 1;
-        seen.add(ch);
-      }
-    }
+    for (const ch of w) { if (!seen.has(ch)) { freq[ch] = (freq[ch] ?? 0) + 1; seen.add(ch); } }
   }
   return freq;
 }
 
 function scoreWord(word: string, freq: Record<string, number>): number {
-  const seen = new Set<string>();
-  let score = 0;
-  for (const ch of word) {
-    if (!seen.has(ch)) {
-      score += freq[ch] ?? 0;
-      seen.add(ch);
-    }
-  }
-  return score;
+  const seen = new Set<string>(); let s = 0;
+  for (const ch of word) { if (!seen.has(ch)) { s += freq[ch] ?? 0; seen.add(ch); } }
+  return s;
 }
 
-/**
- * Solve a single word using frequency-based strategy.
- * Returns number of attempts.
- */
-export function solveFrequency(target: string, allWords: string[], maxAttempts = 6): number {
+export function solveFrequency(target: string, allWords: string[], maxAttempts = 6): { attempts: number; steps: SolverStep[] } {
   let candidates = [...allWords];
+  const steps: SolverStep[] = [];
 
   for (let attempt = 1; attempt <= maxAttempts; attempt++) {
     const freq = letterFrequency(candidates);
     const pool = attempt === 1 ? allWords : candidates;
-
-    let bestGuess = pool[0];
-    let bestScore = -1;
-    for (const g of pool) {
-      const s = scoreWord(g, freq);
-      if (s > bestScore) { bestScore = s; bestGuess = g; }
-    }
+    let bestGuess = pool[0]; let bestScore = -1;
+    for (const g of pool) { const s = scoreWord(g, freq); if (s > bestScore) { bestScore = s; bestGuess = g; } }
 
     const fb = getFeedback(target, bestGuess);
-    if (fb === 'ggggg') return attempt;
+    steps.push({ guess: bestGuess, colors: fb.split('') });
+    if (fb === 'ggggg') return { attempts: attempt, steps };
 
     candidates = candidates.filter((c) => getFeedback(c, bestGuess) === fb);
-    if (candidates.length === 0) return maxAttempts + 1;
+    if (candidates.length === 0) return { attempts: maxAttempts + 1, steps };
   }
 
-  return maxAttempts + 1;
+  return { attempts: maxAttempts + 1, steps };
 }

+ 21 - 49
solver/src/greedy.ts

@@ -1,71 +1,43 @@
-/**
- * Greedy position-masking Wordle solver.
- * Strategy: strictly respect known greens (lock positions).
- * For yellows, test words that have the letter in different positions.
- * For grays, eliminate words containing that letter.
- *
- * Simpler than entropy — models how many humans actually play.
- */
+import type { SolverStep } from '@wordle/shared';
 
 function getFeedback(target: string, guess: string): string {
-  const tu = target.toLowerCase();
-  const gu = guess.toLowerCase();
+  const tu = target.toLowerCase(), gu = guess.toLowerCase();
   const counts: Record<string, number> = {};
   for (const ch of tu) counts[ch] = (counts[ch] ?? 0) + 1;
-  const result: string[] = Array(5).fill('x');
-  for (let i = 0; i < 5; i++) {
-    if (gu[i] === tu[i]) { result[i] = 'g'; counts[gu[i]]--; }
-  }
-  for (let i = 0; i < 5; i++) {
-    if (result[i] === 'g') continue;
-    if ((counts[gu[i]] ?? 0) > 0) { result[i] = 'y'; counts[gu[i]]--; }
-  }
-  return result.join('');
+  const r: string[] = Array(5).fill('x');
+  for (let i = 0; i < 5; i++) { if (gu[i] === tu[i]) { r[i] = 'g'; counts[gu[i]]--; } }
+  for (let i = 0; i < 5; i++) { if (r[i] === 'g') continue; if ((counts[gu[i]] ?? 0) > 0) { r[i] = 'y'; counts[gu[i]]--; } }
+  return r.join('');
 }
 
-function matchesFeedback(candidate: string, guess: string, feedback: string): boolean {
-  return getFeedback(candidate, guess) === feedback;
-}
+function matchesFeedback(c: string, g: string, fb: string): boolean { return getFeedback(c, g) === fb; }
 
-/**
- * Solve using greedy position-masking.
- * Pick any candidate — the filtering does the work.
- */
-export function solveGreedy(target: string, allWords: string[], maxAttempts = 6): number {
+export function solveGreedy(target: string, allWords: string[], maxAttempts = 6): { attempts: number; steps: SolverStep[] } {
   let candidates = [...allWords];
-
-  // Good human-style starting word
-  const starters = ['crane', 'slate', 'arise', 'stare'];
-  const starter = starters.find((w) => allWords.includes(w)) ?? allWords[0];
+  const STARTERS = ['crane','slate','arise','stare'];
+  const steps: SolverStep[] = [];
 
   for (let attempt = 1; attempt <= maxAttempts; attempt++) {
-    const guess = attempt === 1 ? starter : candidates[0];
+    const guess = attempt === 1 ? (STARTERS.find((w) => allWords.includes(w)) ?? allWords[0]) : candidates[0];
     const fb = getFeedback(target, guess);
-
-    if (fb === 'ggggg') return attempt;
+    steps.push({ guess, colors: fb.split('') });
+    if (fb === 'ggggg') return { attempts: attempt, steps };
 
     candidates = candidates.filter((c) => matchesFeedback(c, guess, fb));
-    if (candidates.length === 0) return maxAttempts + 1;
+    if (candidates.length === 0) return { attempts: maxAttempts + 1, steps };
 
-    // Greedy: prefer candidates with letters in positions matching known greens
     if (attempt < maxAttempts) {
-      const greenPositions: number[] = [];
-      for (let i = 0; i < 5; i++) {
-        if (fb[i] === 'g') greenPositions.push(i);
-      }
-      // Sort candidates by how many greens they match from previous feedback
-      if (greenPositions.length > 0) {
+      const greens: number[] = [];
+      for (let i = 0; i < 5; i++) if (fb[i] === 'g') greens.push(i);
+      if (greens.length > 0) {
         candidates.sort((a, b) => {
-          let aMatch = 0, bMatch = 0;
-          for (const pos of greenPositions) {
-            if (a[pos] === guess[pos]) aMatch++;
-            if (b[pos] === guess[pos]) bMatch++;
-          }
-          return bMatch - aMatch; // more matches first
+          let am = 0, bm = 0;
+          for (const p of greens) { if (a[p] === guess[p]) am++; if (b[p] === guess[p]) bm++; }
+          return bm - am;
         });
       }
     }
   }
 
-  return maxAttempts + 1;
+  return { attempts: maxAttempts + 1, steps };
 }

+ 20 - 26
solver/src/index.ts

@@ -1,7 +1,7 @@
 import { readFileSync, writeFileSync } from 'fs';
 import { resolve, dirname } from 'path';
 import { fileURLToPath } from 'url';
-import type { WordBank } from '@wordle/shared';
+import type { WordBank, SolverReplay } from '@wordle/shared';
 import { solveEntropy } from './entropy.js';
 import { solveFrequency } from './frequency.js';
 import { solveVowelFirst } from './vowel-first.js';
@@ -19,44 +19,38 @@ console.log(`Solving ${bank.targets.length} target words with ${allWords.length}
 
 let solved = 0;
 let failed = 0;
-const newTargets = [];
+const newTargets: WordBank['targets'] = [];
 
 for (const target of bank.targets) {
-  const entropyAttempts = solveEntropy(target.word, allWords, MAX_ATTEMPTS);
-  const freqAttempts = solveFrequency(target.word, allWords, MAX_ATTEMPTS);
-  const vowelAttempts = solveVowelFirst(target.word, allWords, MAX_ATTEMPTS);
-  const greedyAttempts = solveGreedy(target.word, allWords, MAX_ATTEMPTS);
+  const results = [
+    { name: 'Entropy', ...solveEntropy(target.word, allWords, MAX_ATTEMPTS) },
+    { name: 'Frequency', ...solveFrequency(target.word, allWords, MAX_ATTEMPTS) },
+    { name: 'Vowel First', ...solveVowelFirst(target.word, allWords, MAX_ATTEMPTS) },
+    { name: 'Greedy', ...solveGreedy(target.word, allWords, MAX_ATTEMPTS) },
+  ];
 
-  const allAttempts = [entropyAttempts, freqAttempts, vowelAttempts, greedyAttempts];
-  const passCount = allAttempts.filter((a) => a <= MAX_ATTEMPTS).length;
+  const passResults = results.filter((r) => r.attempts <= MAX_ATTEMPTS);
 
-  if (passCount === 0) {
-    console.log(`  REMOVED: ${target.word} (unsolvable in ${MAX_ATTEMPTS} by any strategy)`);
+  if (passResults.length === 0) {
+    console.log(`  REMOVED: ${target.word} (unsolvable by any strategy)`);
     failed++;
     continue;
   }
 
-  const avgAttempts = allAttempts.filter((a) => a <= MAX_ATTEMPTS).reduce((s, a) => s + a, 0) / passCount;
+  const avgAttempts = passResults.reduce((s, r) => s + r.attempts, 0) / passResults.length;
   const difficulty = Math.round(avgAttempts * 100) / 100;
 
-  newTargets.push({
-    ...target,
-    difficulty,
-  });
+  const replays: SolverReplay[] = results
+    .filter((r) => r.attempts <= MAX_ATTEMPTS)
+    .map((r) => ({ solver: r.name, steps: r.steps }));
+
+  newTargets.push({ ...target, difficulty, replays });
 
   solved++;
-  if (solved % 10 === 0) {
-    console.log(`  ${solved}/${bank.targets.length}...`);
-  }
+  if (solved % 10 === 0) console.log(`  ${solved}/${bank.targets.length}...`);
 }
 
-// Write updated bank
-const newBank: WordBank = {
-  guessable: bank.guessable,
-  targets: newTargets,
-};
-
+const newBank: WordBank = { guessable: bank.guessable, targets: newTargets };
 writeFileSync(BANK_PATH, JSON.stringify(newBank, null, 2) + '\n', 'utf-8');
 
-console.log(`\nDone! ${solved} solved, ${failed} removed.`);
-console.log(`Updated ${BANK_PATH}`);
+console.log(`\nDone! ${solved} solved, ${failed} removed. Replays stored.`);

+ 21 - 61
solver/src/vowel-first.ts

@@ -1,89 +1,49 @@
-/**
- * Vowel-first Wordle solver.
- * Strategy: maximize vowel coverage in early guesses,
- * then switch to consonant hunting with positional constraints.
- */
+import type { SolverStep } from '@wordle/shared';
 
-const VOWELS = new Set(['a', 'e', 'i', 'o', 'u']);
-const VOWEL_HEAVY_STARTS = ['adieu', 'audio', 'raise', 'arose', 'irate', 'alone', 'ouija'];
+const VOWELS = new Set(['a','e','i','o','u']);
+const VOWEL_STARTS = ['adieu','audio','raise','arose','irate'];
 
 function getFeedback(target: string, guess: string): string {
-  const tu = target.toLowerCase();
-  const gu = guess.toLowerCase();
+  const tu = target.toLowerCase(), gu = guess.toLowerCase();
   const counts: Record<string, number> = {};
   for (const ch of tu) counts[ch] = (counts[ch] ?? 0) + 1;
-  const result: string[] = Array(5).fill('x');
-  for (let i = 0; i < 5; i++) {
-    if (gu[i] === tu[i]) { result[i] = 'g'; counts[gu[i]]--; }
-  }
-  for (let i = 0; i < 5; i++) {
-    if (result[i] === 'g') continue;
-    if ((counts[gu[i]] ?? 0) > 0) { result[i] = 'y'; counts[gu[i]]--; }
-  }
-  return result.join('');
+  const r: string[] = Array(5).fill('x');
+  for (let i = 0; i < 5; i++) { if (gu[i] === tu[i]) { r[i] = 'g'; counts[gu[i]]--; } }
+  for (let i = 0; i < 5; i++) { if (r[i] === 'g') continue; if ((counts[gu[i]] ?? 0) > 0) { r[i] = 'y'; counts[gu[i]]--; } }
+  return r.join('');
 }
 
-function matchesFeedback(candidate: string, guess: string, feedback: string): boolean {
-  return getFeedback(candidate, guess) === feedback;
-}
+function matchesFeedback(c: string, g: string, fb: string): boolean { return getFeedback(c, g) === fb; }
 
-function countNewVowels(word: string, knownVowels: Set<string>): number {
-  let count = 0;
-  for (const ch of word) {
-    if (VOWELS.has(ch) && !knownVowels.has(ch)) count++;
-  }
-  return count;
-}
-
-function scoreVowel(word: string, knownVowels: Set<string>): number {
-  const newVowels = countNewVowels(word, knownVowels);
-  const uniqueLetters = new Set(word.split('')).size;
-  return newVowels * 3 + uniqueLetters;
-}
-
-/**
- * Solve using vowel-first strategy.
- */
-export function solveVowelFirst(target: string, allWords: string[], maxAttempts = 6): number {
+export function solveVowelFirst(target: string, allWords: string[], maxAttempts = 6): { attempts: number; steps: SolverStep[] } {
   let candidates = [...allWords];
   const knownVowels = new Set<string>();
-  let guesses: { word: string; fb: string }[] = [];
+  const steps: SolverStep[] = [];
 
   for (let attempt = 1; attempt <= maxAttempts; attempt++) {
     let bestGuess: string;
-
     if (attempt === 1) {
-      // Pick best vowel-heavy start word from shortlist
-      bestGuess = VOWEL_HEAVY_STARTS.find((w) => allWords.includes(w)) ?? 'arise';
+      bestGuess = VOWEL_STARTS.find((w) => allWords.includes(w)) ?? 'arise';
     } else if (attempt <= 3 && knownVowels.size < 5) {
-      // Still hunting vowels — pick word with most new vowels
       const pool = candidates.length > 0 ? candidates : allWords;
-      bestGuess = pool[0];
-      let bestScore = -1;
+      bestGuess = pool[0]; let best = -1;
       for (const w of pool) {
-        const s = scoreVowel(w, knownVowels);
-        if (s > bestScore) { bestScore = s; bestGuess = w; }
+        const newV = [...w].filter((c) => VOWELS.has(c) && !knownVowels.has(c)).length;
+        const s = newV * 3 + new Set(w.split('')).size;
+        if (s > best) { best = s; bestGuess = w; }
       }
     } else {
-      // Consonant phase — pick from remaining candidates
       bestGuess = candidates[0];
     }
 
     const fb = getFeedback(target, bestGuess);
-    guesses.push({ word: bestGuess, fb });
-
-    if (fb === 'ggggg') return attempt;
-
-    // Track known vowels from greens and yellows
-    for (let i = 0; i < 5; i++) {
-      if ((fb[i] === 'g' || fb[i] === 'y') && VOWELS.has(bestGuess[i])) {
-        knownVowels.add(bestGuess[i]);
-      }
-    }
+    steps.push({ guess: bestGuess, colors: fb.split('') });
+    if (fb === 'ggggg') return { attempts: attempt, steps };
 
+    for (let i = 0; i < 5; i++) { if ((fb[i] === 'g' || fb[i] === 'y') && VOWELS.has(bestGuess[i])) knownVowels.add(bestGuess[i]); }
     candidates = candidates.filter((c) => matchesFeedback(c, bestGuess, fb));
-    if (candidates.length === 0) return maxAttempts + 1;
+    if (candidates.length === 0) return { attempts: maxAttempts + 1, steps };
   }
 
-  return maxAttempts + 1;
+  return { attempts: maxAttempts + 1, steps };
 }

Някои файлове не бяха показани, защото твърде много файлове са промени