forked from technolyceum/ai6-m2
349 lines
11 KiB
Plaintext
349 lines
11 KiB
Plaintext
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! |