Spaces:
Sleeping
Sleeping
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>Wordle Solver</title> | |
| <link rel="icon" type="image/x-icon" href="{{ url_for('static', filename='favicon.ico') }}"> | |
| <style> | |
| body { | |
| font-family: 'Helvetica Neue', Arial, sans-serif; | |
| margin: 0; | |
| padding: 0; | |
| background-color: #1a1a1a; | |
| color: #ffffff; | |
| min-height: 100vh; | |
| } | |
| .container { | |
| padding: 2rem; | |
| max-width: 1200px; | |
| margin: 0 auto; | |
| } | |
| h1 { | |
| color: #ffffff; | |
| margin: 0 0 1rem 0; | |
| font-size: 2.5rem; | |
| font-weight: 700; | |
| text-align: center; | |
| font-family: 'Helvetica Neue', Arial, sans-serif; | |
| letter-spacing: 0.05em; | |
| } | |
| .disclaimer { | |
| color: #999999; | |
| font-size: 0.9rem; | |
| text-align: center; | |
| margin-bottom: 1rem; | |
| font-style: italic; | |
| } | |
| .feedback-instruction { | |
| color: #ffffff; | |
| font-size: 1.1rem; | |
| text-align: center; | |
| margin-bottom: 0.5rem; | |
| } | |
| #current-word { | |
| color: #ffffff; | |
| font-size: 1.5rem; | |
| text-align: center; | |
| margin: 0 0 1rem 0; | |
| font-weight: bold; | |
| } | |
| .warning-note { | |
| color: #ffa500; | |
| font-size: 0.9rem; | |
| text-align: center; | |
| margin: 0 0 2rem 0; | |
| padding: 8px 16px; | |
| background-color: rgba(255, 165, 0, 0.1); | |
| border: 1px solid rgba(255, 165, 0, 0.3); | |
| border-radius: 6px; | |
| max-width: 500px; | |
| margin-left: auto; | |
| margin-right: auto; | |
| margin-bottom: 2rem; | |
| } | |
| .game-container { | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| gap: 20px; | |
| margin: 0 auto; | |
| max-width: 450px; | |
| } | |
| .row-indicator { | |
| width: 30px; | |
| text-align: center; | |
| display: flex; | |
| flex-direction: column; | |
| justify-content: space-around; | |
| height: 100%; | |
| } | |
| .arrow { | |
| font-size: 1.5rem; | |
| color: #ffffff; | |
| opacity: 0; | |
| transition: opacity 0.3s; | |
| height: 62px; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| margin-bottom: 5px; | |
| } | |
| .arrow.active { | |
| opacity: 1; | |
| } | |
| .game-grid { | |
| display: grid; | |
| grid-template-rows: repeat(6, 1fr); | |
| gap: 5px; | |
| max-width: 350px; | |
| padding: 20px; | |
| } | |
| .grid-row { | |
| display: grid; | |
| grid-template-columns: repeat(5, 1fr); | |
| gap: 5px; | |
| } | |
| .grid-cell { | |
| width: 62px; | |
| height: 62px; | |
| border: 2px solid #3a3a3c; | |
| background-color: transparent; | |
| display: flex; | |
| justify-content: center; | |
| align-items: center; | |
| font-size: 2rem; | |
| font-weight: bold; | |
| color: #ffffff; | |
| text-transform: uppercase; | |
| } | |
| .grid-cell.filled { | |
| border-color: #565758; | |
| } | |
| .grid-cell.selected { | |
| border-color: #ffffff; | |
| border-width: 3px; | |
| } | |
| .grid-cell.correct { | |
| background-color: #6aaa64; | |
| border-color: #3a3a3c; | |
| } | |
| .grid-cell.present { | |
| background-color: #c9b458; | |
| border-color: #3a3a3c; | |
| } | |
| .grid-cell.absent { | |
| background-color: #787c7e; | |
| border-color: #3a3a3c; | |
| } | |
| .feedback-buttons { | |
| display: flex; | |
| justify-content: center; | |
| gap: 15px; | |
| margin: 30px auto 0; | |
| max-width: 600px; | |
| } | |
| .feedback-btn { | |
| padding: 12px 20px; | |
| border: none; | |
| border-radius: 6px; | |
| font-family: 'Helvetica Neue', Arial, sans-serif; | |
| font-weight: bold; | |
| font-size: 14px; | |
| color: #ffffff; | |
| cursor: pointer; | |
| transition: opacity 0.2s; | |
| } | |
| .feedback-btn:hover { | |
| opacity: 0.8; | |
| } | |
| .feedback-btn.green { | |
| background-color: #6aaa64; | |
| } | |
| .feedback-btn.yellow { | |
| background-color: #c9b458; | |
| } | |
| .feedback-btn.gray { | |
| background-color: #787c7e; | |
| } | |
| .control-buttons { | |
| display: flex; | |
| justify-content: center; | |
| gap: 15px; | |
| margin: 20px auto 0; | |
| } | |
| .control-btn { | |
| padding: 10px 18px; | |
| border: none; | |
| border-radius: 6px; | |
| font-family: 'Helvetica Neue', Arial, sans-serif; | |
| font-weight: bold; | |
| font-size: 13px; | |
| color: #ffffff; | |
| background-color: #565758; | |
| cursor: pointer; | |
| transition: opacity 0.2s; | |
| } | |
| .control-btn:hover { | |
| opacity: 0.8; | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <div class="container"> | |
| <h1>Wordle Solver</h1> | |
| <p class="disclaimer">This solver is unofficial and not affiliated with the New York Times or Wordle.</p> | |
| <h2 class="feedback-instruction">Enter feedback for</h2> | |
| <h2 id="current-word">ARISE</h2> | |
| <div class="warning-note" id="warning-note"> | |
| ⚠️ Make sure your feedback is accurate - incorrect feedback may lead to wrong suggestions! | |
| </div> | |
| <div class="game-container"> | |
| <div class="row-indicator"> | |
| <div class="arrow active" id="arrow-0">➤</div> | |
| <div class="arrow" id="arrow-1">➤</div> | |
| <div class="arrow" id="arrow-2">➤</div> | |
| <div class="arrow" id="arrow-3">➤</div> | |
| <div class="arrow" id="arrow-4">➤</div> | |
| <div class="arrow" id="arrow-5">➤</div> | |
| </div> | |
| <div class="game-grid"> | |
| <div class="grid-row"> | |
| <div class="grid-cell"></div> | |
| <div class="grid-cell"></div> | |
| <div class="grid-cell"></div> | |
| <div class="grid-cell"></div> | |
| <div class="grid-cell"></div> | |
| </div> | |
| <div class="grid-row"> | |
| <div class="grid-cell"></div> | |
| <div class="grid-cell"></div> | |
| <div class="grid-cell"></div> | |
| <div class="grid-cell"></div> | |
| <div class="grid-cell"></div> | |
| </div> | |
| <div class="grid-row"> | |
| <div class="grid-cell"></div> | |
| <div class="grid-cell"></div> | |
| <div class="grid-cell"></div> | |
| <div class="grid-cell"></div> | |
| <div class="grid-cell"></div> | |
| </div> | |
| <div class="grid-row"> | |
| <div class="grid-cell"></div> | |
| <div class="grid-cell"></div> | |
| <div class="grid-cell"></div> | |
| <div class="grid-cell"></div> | |
| <div class="grid-cell"></div> | |
| </div> | |
| <div class="grid-row"> | |
| <div class="grid-cell"></div> | |
| <div class="grid-cell"></div> | |
| <div class="grid-cell"></div> | |
| <div class="grid-cell"></div> | |
| <div class="grid-cell"></div> | |
| </div> | |
| <div class="grid-row"> | |
| <div class="grid-cell"></div> | |
| <div class="grid-cell"></div> | |
| <div class="grid-cell"></div> | |
| <div class="grid-cell"></div> | |
| <div class="grid-cell"></div> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="feedback-buttons"> | |
| <button class="feedback-btn green">Green (Correct)</button> | |
| <button class="feedback-btn yellow">Yellow (Wrong Position)</button> | |
| <button class="feedback-btn gray">Gray (Not in Word)</button> | |
| </div> | |
| <div class="control-buttons"> | |
| <button class="control-btn" id="clear-cell-btn">Clear Cell</button> | |
| <button class="control-btn" id="next-row-btn">Next Row</button> | |
| <button class="control-btn" id="reset-game-btn">Reset Game</button> | |
| </div> | |
| </div> | |
| <script> | |
| let currentRow = 0; | |
| let currentCol = 0; | |
| const maxCols = 5; | |
| const maxRows = 6; | |
| // Get all grid cells | |
| const gridCells = document.querySelectorAll('.grid-cell'); | |
| function getCellIndex(row, col) { | |
| return row * maxCols + col; | |
| } | |
| function addLetter(letter) { | |
| if (currentCol < maxCols) { | |
| const cellIndex = getCellIndex(currentRow, currentCol); | |
| gridCells[cellIndex].textContent = letter; | |
| gridCells[cellIndex].classList.add('filled'); | |
| currentCol++; | |
| } | |
| } | |
| function deleteLetter() { | |
| if (currentCol > 0) { | |
| currentCol--; | |
| const cellIndex = getCellIndex(currentRow, currentCol); | |
| const cell = gridCells[cellIndex]; | |
| // Remove color classes instead of text content | |
| cell.classList.remove('correct', 'present', 'absent', 'filled'); | |
| } | |
| } | |
| function updateRowIndicator() { | |
| // Hide all arrows | |
| for (let i = 0; i < maxRows; i++) { | |
| document.getElementById(`arrow-${i}`).classList.remove('active'); | |
| } | |
| // Show current row arrow | |
| if (currentRow < maxRows) { | |
| document.getElementById(`arrow-${currentRow}`).classList.add('active'); | |
| } | |
| } | |
| function getRowFeedback(row) { | |
| // Convert row colors to byg string (black/yellow/green) | |
| let feedback = ""; | |
| for (let col = 0; col < maxCols; col++) { | |
| const cellIndex = getCellIndex(row, col); | |
| const cell = gridCells[cellIndex]; | |
| if (cell.classList.contains('absent')) { | |
| feedback += 'b'; // black/gray | |
| } else if (cell.classList.contains('present')) { | |
| feedback += 'y'; // yellow | |
| } else if (cell.classList.contains('correct')) { | |
| feedback += 'g'; // green | |
| } else { | |
| feedback += '?'; // no color set | |
| } | |
| } | |
| return feedback; | |
| } | |
| function submitWord() { | |
| if (currentCol < maxCols) { | |
| alert("You need to have 5 colored cells!"); | |
| return; | |
| } | |
| if (currentCol === maxCols) { | |
| // Get current row feedback before moving | |
| const feedback = getRowFeedback(currentRow); | |
| const currentWord = document.getElementById('current-word').textContent; | |
| console.log(`Round ${currentRow + 1}: Guessed "${currentWord}" with feedback "${feedback}"`); | |
| // Check if word is solved (all green) | |
| if (feedback === 'ggggg') { | |
| alert("🎉 Congratulations! Word found! 🎉"); | |
| document.getElementById('current-word').textContent = "SOLVED!"; | |
| console.log(`🎉 SOLVED in ${currentRow + 1} rounds! Final word: "${currentWord}"`); | |
| // Disable further interaction | |
| return; | |
| } | |
| // Send feedback to solver and get next word | |
| document.getElementById('current-word').textContent = "Loading... this may take a while"; | |
| fetch('/get_next_word', { | |
| method: 'POST', | |
| headers: { | |
| 'Content-Type': 'application/json', | |
| }, | |
| body: JSON.stringify({ feedback: feedback }) | |
| }) | |
| .then(response => response.json()) | |
| .then(data => { | |
| if (data.word === 'ERROR') { | |
| alert("❌ No valid words remaining! There might be an error in your feedback."); | |
| return; | |
| } | |
| // Update the current word display | |
| document.getElementById('current-word').textContent = data.word; | |
| console.log(`Round ${currentRow + 2}: Next word suggested: "${data.word}" (${data.candidates_remaining} candidates remaining)`); | |
| }) | |
| .catch(error => { | |
| console.error('Error:', error); | |
| alert("Error communicating with solver!"); | |
| }); | |
| // Move to next row | |
| currentRow++; | |
| currentCol = 0; | |
| if (currentRow >= maxRows) { | |
| currentRow = maxRows - 1; // Stay on last row | |
| } | |
| // Update arrow indicator | |
| updateRowIndicator(); | |
| } | |
| } | |
| // Handle physical keyboard input (Enter and Backspace only) | |
| document.addEventListener('keydown', function(event) { | |
| const key = event.key.toUpperCase(); | |
| if (key === 'BACKSPACE') { | |
| deleteLetter(); | |
| } else if (key === 'ENTER') { | |
| submitWord(); | |
| } | |
| }); | |
| // Handle feedback button clicks - color cells in sequence | |
| document.querySelectorAll('.feedback-btn').forEach(btn => { | |
| btn.addEventListener('click', function() { | |
| const cellIndex = getCellIndex(currentRow, currentCol); | |
| if (currentCol < maxCols) { | |
| const cell = gridCells[cellIndex]; | |
| // Remove existing color classes | |
| cell.classList.remove('correct', 'present', 'absent'); | |
| // Add new color class based on button | |
| if (this.classList.contains('green')) { | |
| cell.classList.add('correct'); | |
| } else if (this.classList.contains('yellow')) { | |
| cell.classList.add('present'); | |
| } else if (this.classList.contains('gray')) { | |
| cell.classList.add('absent'); | |
| } | |
| // Move to next cell | |
| currentCol++; | |
| } | |
| }); | |
| }); | |
| // Handle control button clicks | |
| document.getElementById('clear-cell-btn').addEventListener('click', function() { | |
| deleteLetter(); | |
| }); | |
| document.getElementById('next-row-btn').addEventListener('click', function() { | |
| submitWord(); | |
| }); | |
| document.getElementById('reset-game-btn').addEventListener('click', function() { | |
| // Reset frontend state | |
| currentRow = 0; | |
| currentCol = 0; | |
| // Clear all grid cells | |
| gridCells.forEach(cell => { | |
| cell.classList.remove('correct', 'present', 'absent', 'filled', 'selected'); | |
| }); | |
| // Reset arrow indicator | |
| updateRowIndicator(); | |
| // Clear any solved state immediately | |
| document.getElementById('current-word').textContent = "Loading..."; | |
| // Reset backend state | |
| fetch('/reset_game', { | |
| method: 'POST', | |
| headers: { | |
| 'Content-Type': 'application/json', | |
| } | |
| }) | |
| .then(response => response.json()) | |
| .then(data => { | |
| document.getElementById('current-word').textContent = data.word; | |
| console.log('Game reset. Starting word:', data.word); | |
| }) | |
| .catch(error => { | |
| console.error('Error:', error); | |
| // If there's an error, still show the default starting word | |
| document.getElementById('current-word').textContent = "ARISE"; | |
| }); | |
| }); | |
| </script> | |
| </body> | |
| </html> | |