Spaces:
Running
Running
| // Core game elements | |
| const statusEl = document.getElementById('status'); | |
| const timerEl = document.getElementById('timer'); | |
| const gameInfoEl = document.getElementById('game-info'); | |
| const guessInput = document.getElementById('guess-input'); | |
| const submitGuessBtn = document.getElementById('submit-guess'); | |
| const feedbackSection = document.getElementById('feedback-section'); | |
| const guessedWordEl = document.getElementById('guessed-word'); | |
| const guessScoreEl = document.getElementById('guess-score'); | |
| const feedbackTextEl = document.getElementById('feedback-text'); | |
| const chatContent = document.getElementById('chat-content'); | |
| const gridContainer = document.getElementById('grid-container'); | |
| // Game state variables | |
| let countdownInterval; | |
| const playerName = 'Player1'; | |
| let squareCount = 0; | |
| let chatCount = 1; | |
| // Grid management functions | |
| const updateGrid = () => { | |
| const cols = Math.ceil(Math.sqrt(squareCount)); | |
| const rows = Math.ceil(squareCount / cols); | |
| gridContainer.style.gridTemplateColumns = `repeat(${cols}, minmax(0, 1fr))`; | |
| }; | |
| const addSquare = () => { | |
| squareCount++; | |
| updateGrid(); | |
| const colors = ["cerulean", "light-sea-green", "sunset", "floral-white", "light-red"]; | |
| const square = document.createElement("div"); | |
| square.className = `${colors[(squareCount - 1) % colors.length]} w-16 h-16 rounded-md shadow-md flex flex-col items-center justify-center text-black font-bold pop-in`; | |
| square.innerHTML = ` | |
| <span class="iconify" data-icon="mdi:account" data-width="24" data-height="24"></span> | |
| Student ${squareCount} | |
| `; | |
| gridContainer.appendChild(square); | |
| }; | |
| const removeSquare = () => { | |
| if (squareCount > 0) { | |
| const squareToRemove = gridContainer.lastElementChild; | |
| squareToRemove.classList.add("pop-out"); | |
| setTimeout(() => { | |
| squareToRemove.remove(); | |
| squareCount--; | |
| updateGrid(); | |
| }, 300); | |
| } | |
| }; | |
| // Chat functionality | |
| const addStreamMessage = (message, type = 'user') => { | |
| if (!message.trim()) return; | |
| const chatLine = document.createElement("div"); | |
| chatLine.className = "text-gray-700 flex items-center gap-2"; | |
| if (type === 'system') { | |
| chatLine.innerHTML = `<span class="font-bold text-blue-600">${message}</span>`; | |
| } else if (type === 'student') { | |
| chatLine.innerHTML = `<span class="font-bold text-green-600">${message}</span>`; | |
| } else if (type === 'system2') { | |
| chatLine.innerHTML = `<span class="font-bold text-red-600">${message}</span>`; | |
| } | |
| else { | |
| chatLine.innerHTML = `<span class="font-bold">${chatCount}.</span> <span>${message}</span>`; | |
| chatCount++; | |
| } | |
| chatContent.appendChild(chatLine); | |
| chatContent.scrollTop = chatContent.scrollHeight; | |
| }; | |
| // Timer functionality | |
| function startCountdown(endTimestamp) { | |
| if (countdownInterval) { | |
| clearInterval(countdownInterval); | |
| } | |
| function updateTimer() { | |
| const now = new Date().getTime(); | |
| const timeLeft = endTimestamp - now; | |
| if (timeLeft <= 0) { | |
| clearInterval(countdownInterval); | |
| timerEl.textContent = 'Time\'s up!'; | |
| timerEl.classList.add('text-red-600'); | |
| fetchGameState(); | |
| return; | |
| } | |
| const seconds = Math.floor(timeLeft / 1000); | |
| timerEl.textContent = `${seconds}s`; | |
| } | |
| updateTimer(); | |
| countdownInterval = setInterval(updateTimer, 1000); | |
| } | |
| // Game state management | |
| function updateGameState(data) { | |
| gameInfoEl.innerHTML = ''; | |
| statusEl.textContent = data.message || ''; | |
| if (data.session_id) { | |
| const infoHtml = ` | |
| <div> | |
| Session: ${data.session_id || ''}<br> | |
| Turn: ${data.turn_number || ''}<br> | |
| Word: ${data.word || ''} | |
| </div> | |
| `; | |
| gameInfoEl.innerHTML = infoHtml; | |
| const turnNumber = parseInt(data.turn_number) || 0; | |
| if (turnNumber === 1 && data.hint0) { | |
| addStreamMessage(data.hint0, 'system'); | |
| } | |
| else if (turnNumber === 3 && data.hint1) { | |
| addStreamMessage(data.hint1, 'system'); | |
| } | |
| else if (turnNumber === 5 && data.hint2) { | |
| addStreamMessage(data.hint2, 'system'); | |
| } | |
| else if (turnNumber === 7 && data.hint3) { | |
| addStreamMessage(data.hint3, 'system'); | |
| } | |
| if (data.end_timestamp) { | |
| startCountdown(data.end_timestamp); | |
| } | |
| } | |
| } | |
| // API interactions | |
| async function submitAdvice(adviceText) { | |
| guessText = adviceText; | |
| if (!guessText) return; | |
| submitGuessBtn.disabled = true; | |
| submitGuessBtn.classList.add('opacity-75'); | |
| try { | |
| const formData = new FormData(); | |
| formData.append('guess_text', guessText); | |
| formData.append('player_name', playerName); | |
| formData.append('personality', document.getElementById('personality-select').value); | |
| const response = await fetch('https://lemot.online/player/submit_guess/', { | |
| method: 'POST', | |
| body: formData | |
| }); | |
| const data = await response.json(); | |
| if (data.error) { | |
| statusEl.textContent = data.message || "Error submitting guess."; | |
| statusEl.classList.add('text-red-600'); | |
| addStreamMessage('Error submitting guess', 'system'); | |
| } else { | |
| feedbackSection.classList.remove('hidden'); | |
| guessedWordEl.textContent = data.guessed_word; | |
| guessScoreEl.textContent = `${data.score} / 10`; | |
| // feedbackTextEl.textContent = data.feedback; | |
| addStreamMessage(data.feedback, type='student'); | |
| addStreamMessage(`${data.guessed_word} - Score: ${data.score} / 10`); | |
| if (data.score === 10) { | |
| addStreamMessage("Congratulations! You've guessed the word correctly!", 'system2'); | |
| } | |
| guessInput.value = ''; | |
| fetchGameState(); | |
| } | |
| } catch (err) { | |
| console.error(err); | |
| statusEl.textContent = "Error submitting guess."; | |
| statusEl.classList.add('text-red-600'); | |
| } finally { | |
| submitGuessBtn.disabled = false; | |
| submitGuessBtn.classList.remove('opacity-75'); | |
| } | |
| } | |
| function fetchGameState() { | |
| const formData = new FormData(); | |
| formData.append('player_name', playerName); | |
| fetch('https://lemot.online/player/play/', { | |
| method: 'POST', | |
| body: formData | |
| }) | |
| .then(res => res.json()) | |
| .then(data => { | |
| if (data.error) { | |
| statusEl.textContent = data.message; | |
| statusEl.classList.add('text-red-600'); | |
| addStreamMessage(data.message, 'system'); | |
| } else { | |
| statusEl.classList.remove('text-red-600'); | |
| updateGameState(data); | |
| } | |
| }) | |
| .catch(err => { | |
| console.error(err); | |
| statusEl.textContent = "Error fetching game state."; | |
| addStreamMessage("Error fetching game state", 'system'); | |
| }); | |
| } | |
| // Event listeners | |
| let isProcessing = false; | |
| submitGuessBtn.addEventListener('click', () => { | |
| if (isProcessing) return; | |
| isProcessing = true; | |
| const guessAdvice = guessInput.value.trim(); | |
| guessInput.value = ''; | |
| submitAdvice(guessAdvice); | |
| setTimeout(() => { | |
| isProcessing = false; | |
| }, 1000); | |
| }); | |
| guessInput.addEventListener('keypress', (e) => { | |
| if (e.key === 'Enter') { | |
| const guessText = guessInput.value.trim(); | |
| submitAdvice(guessText); | |
| } | |
| }); | |
| // Initialize game | |
| window.addEventListener('load', fetchGameState); |