INNA - FRONTEND DEVELOPER MISSION Your Role: Game Interface Designer | Your Files: templates/ and static/script.js 💡 What You're Building: You're creating what players see and click on! 📋 LESSON 1-2: SETUP & BASIC GAME FLOW Step 1: Fork and Clone (10 minutes) 1. Go to: https://gitea.techshare.cc/technolyceum/ai6-m2 2. Click the "Fork" button (creates your copy) 3. Copy your forked repository URL 4. Open Terminal and type: git clone [YOUR-FORKED-URL-HERE] cd ai6-m2 git checkout -b inna-frontend-work Step 2: Make the Game Load Questions (30 minutes) Open static/script.js and find the loadQuestion function. DELETE these lines: function loadQuestion() { fetch('/get_question') .then(response => response.json()) .then(data => { if (data.error) { console.error(data.error); return; } if (data.game_over) { endGame(data.final_score); return; } gameState.currentQuestion = data; displayQuestion(data); }) .catch(error => console.error('Error:', error)); } TYPE THIS instead: function loadQuestion() { fetch('/get_question') .then(response => response.json()) .then(data => { if (data.error) { alert("Game error: " + data.error); return; } if (data.game_over) { endGame(data.final_score); return; } gameState.currentQuestion = data; displayQuestion(data); }) .catch(error => { alert("Network error - check if server is running!"); console.error('Error:', error); }); } Step 3: Make Questions Display Properly (20 minutes) Find the displayQuestion function. DELETE these lines: function displayQuestion(questionData) { document.getElementById('question-num').textContent = questionData.question_number; document.getElementById('question-text').textContent = questionData.question; const optionsContainer = document.getElementById('options-container'); optionsContainer.innerHTML = ''; const optionLetters = ['A', 'B', 'C', 'D']; questionData.options.forEach((option, index) => { const optionElement = document.createElement('div'); optionElement.className = 'option'; optionElement.textContent = `${optionLetters[index]}. ${option}`; optionElement.onclick = () => selectAnswer(option); optionsContainer.appendChild(optionElement); }); document.getElementById('feedback').style.display = 'none'; gameState.optionsDisabled = false; } TYPE THIS instead: function displayQuestion(questionData) { // Update question number and text document.getElementById('question-num').textContent = questionData.question_number; document.getElementById('question-text').textContent = questionData.question; document.getElementById('current-prize').textContent = questionData.current_prize; // Clear previous options const optionsContainer = document.getElementById('options-container'); optionsContainer.innerHTML = ''; // Create new option buttons const optionLetters = ['A', 'B', 'C', 'D']; questionData.options.forEach((option, index) => { const optionElement = document.createElement('div'); optionElement.className = 'option'; optionElement.textContent = `${optionLetters[index]}. ${option}`; optionElement.onclick = () => selectAnswer(option); optionsContainer.appendChild(optionElement); }); // Reset feedback and enable clicking document.getElementById('feedback').style.display = 'none'; document.getElementById('feedback').className = 'feedback'; gameState.optionsDisabled = false; // Clear lifeline result document.getElementById('lifeline-result').textContent = ''; } Save and push: git add static/script.js git commit -m "feat: basic question loading working" git push origin inna-frontend-work 📋 LESSON 3-4: ANSWER HANDLING Step 4: Make Answer Selection Work (30 minutes) Find the selectAnswer function. DELETE these lines: function selectAnswer(selectedAnswer) { if (gameState.optionsDisabled) return; gameState.optionsDisabled = true; fetch('/answer', { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify({ answer: selectedAnswer }) }) .then(response => response.json()) .then(data => { const feedback = document.getElementById('feedback'); feedback.style.display = 'block'; if (data.correct) { feedback.textContent = 'Correct! 🎉'; feedback.className = 'feedback correct'; setTimeout(() => { if (data.next_question) loadQuestion(); else endGame(data.final_score, true); }, 1500); } else { feedback.textContent = `Incorrect! Correct answer: ${data.correct_answer}`; feedback.className = 'feedback incorrect'; setTimeout(() => endGame(data.final_score), 2000); } }) .catch(error => console.error('Error:', error)); } TYPE THIS instead: function selectAnswer(selectedAnswer) { // Prevent double-clicking if (gameState.optionsDisabled) return; gameState.optionsDisabled = true; // Disable all options while checking document.querySelectorAll('.option').forEach(btn => { btn.style.pointerEvents = 'none'; }); // Send answer to server fetch('/answer', { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify({ answer: selectedAnswer }) }) .then(response => response.json()) .then(data => { const feedback = document.getElementById('feedback'); feedback.style.display = 'block'; if (data.correct) { feedback.textContent = 'Correct! 🎉 +' + data.prize_won + ' ₽'; feedback.className = 'feedback correct'; // Wait then load next question or end game setTimeout(() => { if (data.game_won) { endGame(data.final_score, true); } else if (data.next_question) { loadQuestion(); } else { endGame(data.final_score); } }, 2000); } else { feedback.textContent = `Incorrect! Correct answer was: ${data.correct_answer}`; feedback.className = 'feedback incorrect'; // Highlight correct answer in green document.querySelectorAll('.option').forEach(btn => { if (btn.textContent.includes(data.correct_answer)) { btn.style.background = '#4CAF50'; btn.style.color = 'white'; } }); setTimeout(() => endGame(data.final_score), 3000); } }) .catch(error => { alert("Error sending answer!"); console.error('Error:', error); }); } Step 5: Make Lifelines Work (20 minutes) Find the useLifeline function. DELETE these lines: function useLifeline(lifelineName) { fetch(`/lifeline/${lifelineName}`) .then(response => response.json()) .then(data => { if (data.error) { alert(data.error); return; } document.getElementById('lifeline-result').textContent = data.hint || data.friend_says || 'Lifeline used!'; }) .catch(error => console.error('Error:', error)); } TYPE THIS instead: function useLifeline(lifelineName) { // Disable the lifeline button document.querySelector(`button[onclick="useLifeline('${lifelineName}')"]`).disabled = true; fetch(`/lifeline/${lifelineName}`) .then(response => response.json()) .then(data => { if (data.error) { alert(data.error); document.querySelector(`button[onclick="useLifeline('${lifelineName}')"]`).disabled = false; return; } const resultElement = document.getElementById('lifeline-result'); if (lifelineName === 'fifty_fifty') { // Hide the wrong options document.querySelectorAll('.option').forEach(option => { const optionText = option.textContent.substring(3); // Remove "A. ", "B. ", etc. if (!data.remaining_options.includes(optionText)) { option.style.display = 'none'; } }); resultElement.textContent = 'Two wrong answers removed!'; } else if (lifelineName === 'phone_friend') { resultElement.textContent = data.friend_says; } }) .catch(error => { alert("Lifeline error!"); console.error('Error:', error); }); } Save and push: git add static/script.js git commit -m "feat: answer handling and lifelines working" git push origin inna-frontend-work 📋 LESSON 5-6: GAME FLOW COMPLETION Step 6: Complete the Game Flow (40 minutes) Find the endGame function. DELETE these lines: function endGame(finalScore, isWin = false) { document.getElementById('final-prize').textContent = finalScore; document.getElementById('game-over-screen').style.display = 'block'; document.querySelector('.game-area').style.display = 'none'; } TYPE THIS instead: function endGame(finalScore, isWin = false) { const finalPrizeElement = document.getElementById('final-prize'); const gameOverScreen = document.getElementById('game-over-screen'); const gameOverTitle = document.getElementById('game-over-title'); const gameOverMessage = document.getElementById('game-over-message'); finalPrizeElement.textContent = finalScore.toLocaleString(); if (isWin) { gameOverTitle.innerHTML = '🎉 YOU WIN! 🎉'; gameOverTitle.style.color = '#fdbb2d'; gameOverMessage.textContent = 'Congratulations! You won the top prize!'; } else if (finalScore > 0) { gameOverTitle.textContent = 'Game Over!'; gameOverTitle.style.color = '#1a2a6c'; gameOverMessage.textContent = 'You reached a guaranteed prize level!'; } else { gameOverTitle.textContent = 'Game Over!'; gameOverTitle.style.color = '#b21f1f'; gameOverMessage.textContent = 'Better luck next time!'; } gameOverScreen.style.display = 'block'; document.querySelector('.game-area').style.display = 'none'; } Also update the restartGame function: DELETE this line: function restartGame() { window.location.href = '/start'; } TYPE THIS instead: function restartGame() { // Reload the page to start fresh window.location.reload(); } Final push: git add static/script.js git commit -m "feat: completed frontend game flow" git push origin inna-frontend-work ✅ INNA'S COMPLETION CHECKLIST ☐ Questions load and display correctly ☐ Answer buttons work and show feedback ☐ Prize money updates when answering ☐ 50:50 lifeline hides wrong answers ☐ Phone a Friend shows hints ☐ Game over screen shows correct messages ☐ Restart button works ☐ All code pushed to your branch ☐ Created Pull Request for teacher to review 🎉 Congratulations Inna! You built the entire game interface!