Added astroid game
This commit is contained in:
535
quiz_game/From_concept_to_release.html
Normal file
535
quiz_game/From_concept_to_release.html
Normal file
@@ -0,0 +1,535 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Build a Russian Millionaire Quiz Game!</title>
|
||||
<style>
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
font-family: 'Comic Sans MS', cursive, sans-serif;
|
||||
}
|
||||
|
||||
body {
|
||||
background: linear-gradient(135deg, #1a2a6c, #b21f1f, #fdbb2d);
|
||||
color: white;
|
||||
min-height: 100vh;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.container {
|
||||
max-width: 1000px;
|
||||
margin: 0 auto;
|
||||
background-color: rgba(0, 0, 0, 0.7);
|
||||
border-radius: 20px;
|
||||
padding: 30px;
|
||||
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
|
||||
header {
|
||||
text-align: center;
|
||||
margin-bottom: 30px;
|
||||
padding: 20px;
|
||||
background: linear-gradient(90deg, #1a2a6c, #b21f1f);
|
||||
border-radius: 15px;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 2.5rem;
|
||||
margin-bottom: 10px;
|
||||
text-shadow: 3px 3px 5px rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
|
||||
h2 {
|
||||
color: #fdbb2d;
|
||||
margin: 20px 0 15px;
|
||||
border-bottom: 2px solid #fdbb2d;
|
||||
padding-bottom: 5px;
|
||||
}
|
||||
|
||||
.slide {
|
||||
display: none;
|
||||
padding: 20px;
|
||||
background-color: rgba(255, 255, 255, 0.1);
|
||||
border-radius: 15px;
|
||||
margin-bottom: 20px;
|
||||
animation: fadeIn 0.5s ease-in;
|
||||
}
|
||||
|
||||
.active {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.content {
|
||||
line-height: 1.6;
|
||||
font-size: 1.2rem;
|
||||
}
|
||||
|
||||
.role-box {
|
||||
background: linear-gradient(135deg, #1a2a6c, #b21f1f);
|
||||
padding: 15px;
|
||||
border-radius: 10px;
|
||||
margin: 15px 0;
|
||||
border-left: 5px solid #fdbb2d;
|
||||
}
|
||||
|
||||
.role-title {
|
||||
font-weight: bold;
|
||||
color: #fdbb2d;
|
||||
font-size: 1.3rem;
|
||||
}
|
||||
|
||||
.role-desc {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.btn-container {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin-top: 30px;
|
||||
}
|
||||
|
||||
button {
|
||||
background: linear-gradient(135deg, #1a2a6c, #b21f1f);
|
||||
color: white;
|
||||
border: none;
|
||||
padding: 12px 25px;
|
||||
border-radius: 50px;
|
||||
font-size: 1.1rem;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s;
|
||||
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
button:hover {
|
||||
transform: translateY(-3px);
|
||||
box-shadow: 0 8px 20px rgba(0, 0, 0, 0.4);
|
||||
}
|
||||
|
||||
button:active {
|
||||
transform: translateY(1px);
|
||||
}
|
||||
|
||||
.progress-bar {
|
||||
height: 10px;
|
||||
background-color: rgba(255, 255, 255, 0.2);
|
||||
border-radius: 5px;
|
||||
margin: 20px 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.progress {
|
||||
height: 100%;
|
||||
background: linear-gradient(90deg, #1a2a6c, #fdbb2d);
|
||||
width: 0%;
|
||||
transition: width 0.5s;
|
||||
}
|
||||
|
||||
.slide-counter {
|
||||
text-align: center;
|
||||
margin-top: 10px;
|
||||
font-size: 1rem;
|
||||
color: #fdbb2d;
|
||||
}
|
||||
|
||||
.game-preview {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
margin: 20px 0;
|
||||
}
|
||||
|
||||
.game-screen {
|
||||
width: 300px;
|
||||
height: 200px;
|
||||
background-color: #1a2a6c;
|
||||
border-radius: 10px;
|
||||
padding: 15px;
|
||||
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5);
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.question-box {
|
||||
background-color: #fdbb2d;
|
||||
color: #1a2a6c;
|
||||
padding: 10px;
|
||||
border-radius: 5px;
|
||||
text-align: center;
|
||||
font-weight: bold;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.option {
|
||||
background-color: white;
|
||||
color: #1a2a6c;
|
||||
padding: 8px;
|
||||
margin: 5px 0;
|
||||
border-radius: 5px;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
|
||||
.option:hover {
|
||||
background-color: #b21f1f;
|
||||
color: white;
|
||||
}
|
||||
|
||||
@keyframes fadeIn {
|
||||
from { opacity: 0; }
|
||||
to { opacity: 1; }
|
||||
}
|
||||
|
||||
.highlight {
|
||||
color: #fdbb2d;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.russian-flag {
|
||||
display: inline-block;
|
||||
width: 20px;
|
||||
height: 15px;
|
||||
background: linear-gradient(to bottom, white 33%, blue 33%, blue 66%, red 66%);
|
||||
margin: 0 5px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<header>
|
||||
<h1>Build a Russian Millionaire Quiz Game!</h1>
|
||||
<p>From Concept to Release in 30 Minutes</p>
|
||||
</header>
|
||||
|
||||
<div class="progress-bar">
|
||||
<div class="progress" id="progress"></div>
|
||||
</div>
|
||||
|
||||
<!-- Slide 1: Introduction -->
|
||||
<div class="slide active" id="slide1">
|
||||
<h2>Welcome, Future Game Developers!</h2>
|
||||
<div class="content">
|
||||
<p>Today we're going to create our very own "Who Wants to Be a Millionaire" style quiz game with a Russian twist!</p>
|
||||
<p>We'll use Python Flask for the website and DeepSeek AI to help with our questions.</p>
|
||||
<p>By the end of this class, you'll understand how games are made from start to finish!</p>
|
||||
|
||||
<div class="game-preview">
|
||||
<div class="game-screen">
|
||||
<div class="question-box">What is the capital of Russia?</div>
|
||||
<div class="option">A. St. Petersburg</div>
|
||||
<div class="option">B. Moscow <span class="russian-flag"></span></div>
|
||||
<div class="option">C. Kazan</div>
|
||||
<div class="option">D. Sochi</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p>Let's get started on our game development journey!</p>
|
||||
</div>
|
||||
|
||||
<div class="btn-container">
|
||||
<button onclick="prevSlide()">Previous</button>
|
||||
<button onclick="nextSlide()">Next</button>
|
||||
</div>
|
||||
<div class="slide-counter">Slide 1 of 8</div>
|
||||
</div>
|
||||
|
||||
<!-- Slide 2: Concept & Research -->
|
||||
<div class="slide" id="slide2">
|
||||
<h2>Stage 1: Concept & Research</h2>
|
||||
<div class="content">
|
||||
<p>Every great game starts with an idea! Our concept is:</p>
|
||||
<p class="highlight">"A 'Who Wants to Be a Millionaire' style quiz about Russian culture, history, and fun facts!"</p>
|
||||
|
||||
<p>Our research tasks:</p>
|
||||
<ul>
|
||||
<li>Learn about the original Millionaire game format</li>
|
||||
<li>Research interesting Russian trivia</li>
|
||||
<li>Study how Flask websites work</li>
|
||||
<li>Explore how AI can help create questions</li>
|
||||
</ul>
|
||||
|
||||
<div class="role-box">
|
||||
<div class="role-title">Research Specialist</div>
|
||||
<div class="role-desc">This person will find fun Russian facts and help create our question database.</div>
|
||||
</div>
|
||||
|
||||
<p>Who wants to be our Research Specialist?</p>
|
||||
</div>
|
||||
|
||||
<div class="btn-container">
|
||||
<button onclick="prevSlide()">Previous</button>
|
||||
<button onclick="nextSlide()">Next</button>
|
||||
</div>
|
||||
<div class="slide-counter">Slide 2 of 8</div>
|
||||
</div>
|
||||
|
||||
<!-- Slide 3: User Stories -->
|
||||
<div class="slide" id="slide3">
|
||||
<h2>Stage 2: User Stories</h2>
|
||||
<div class="content">
|
||||
<p>User stories help us understand what our players will do in the game:</p>
|
||||
|
||||
<ul>
|
||||
<li>"As a player, I want to see multiple choice questions"</li>
|
||||
<li>"As a player, I want lifelines like 50:50 and Ask the Audience"</li>
|
||||
<li>"As a player, I want to see my score increase as I answer correctly"</li>
|
||||
<li>"As a player, I want fun Russian-themed graphics and sounds"</li>
|
||||
</ul>
|
||||
|
||||
<p>These stories help us plan what features to build!</p>
|
||||
|
||||
<div class="game-preview">
|
||||
<div class="game-screen">
|
||||
<div class="question-box">Which Russian composer wrote 'Swan Lake'?</div>
|
||||
<div class="option">A. Tchaikovsky <span class="russian-flag"></span></div>
|
||||
<div class="option">B. Rachmaninoff</div>
|
||||
<div class="option">C. Shostakovich</div>
|
||||
<div class="option">D. Stravinsky</div>
|
||||
<div style="margin-top: 10px; font-size: 0.8rem;">
|
||||
Lifelines: 50:50 | Ask AI | Phone a Friend
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="btn-container">
|
||||
<button onclick="prevSlide()">Previous</button>
|
||||
<button onclick="nextSlide()">Next</button>
|
||||
</div>
|
||||
<div class="slide-counter">Slide 3 of 8</div>
|
||||
</div>
|
||||
|
||||
<!-- Slide 4: Task Allocation -->
|
||||
<div class="slide" id="slide4">
|
||||
<h2>Stage 3: Task Allocation</h2>
|
||||
<div class="content">
|
||||
<p>Now let's divide the work! We have 4 important roles:</p>
|
||||
|
||||
<div class="role-box">
|
||||
<div class="role-title">Backend Developer</div>
|
||||
<div class="role-desc">Creates the game logic using Python Flask and connects to the DeepSeek API.</div>
|
||||
</div>
|
||||
|
||||
<div class="role-box">
|
||||
<div class="role-title">Database Designer</div>
|
||||
<div class="role-desc">Builds the question database using JSON and works with the Research Specialist.</div>
|
||||
</div>
|
||||
|
||||
<div class="role-box">
|
||||
<div class="role-title">Frontend Developer</div>
|
||||
<div class="role-desc">Designs the game screens using HTML, CSS, and JavaScript.</div>
|
||||
</div>
|
||||
|
||||
<div class="role-box">
|
||||
<div class="role-title">Graphics & Sound Artist</div>
|
||||
<div class="role-desc">Creates Russian-themed visuals, icons, and sound effects for the game.</div>
|
||||
</div>
|
||||
|
||||
<p>Which role sounds most interesting to you?</p>
|
||||
</div>
|
||||
|
||||
<div class="btn-container">
|
||||
<button onclick="prevSlide()">Previous</button>
|
||||
<button onclick="nextSlide()">Next</button>
|
||||
</div>
|
||||
<div class="slide-counter">Slide 4 of 8</div>
|
||||
</div>
|
||||
|
||||
<!-- Slide 5: Alpha Development -->
|
||||
<div class="slide" id="slide5">
|
||||
<h2>Stage 4: Alpha Development</h2>
|
||||
<div class="content">
|
||||
<p>In the Alpha stage, we build the basic version of our game:</p>
|
||||
|
||||
<ul>
|
||||
<li>Backend Developer: Sets up Flask server and basic game routes</li>
|
||||
<li>Database Designer: Creates JSON file with first 5 Russian trivia questions</li>
|
||||
<li>Frontend Developer: Builds the question screen with 4 answer options</li>
|
||||
<li>Graphics Artist: Creates simple Russian-themed background and buttons</li>
|
||||
</ul>
|
||||
|
||||
<p>Our Alpha version will have:</p>
|
||||
<ul>
|
||||
<li>Basic question display</li>
|
||||
<li>Answer selection</li>
|
||||
<li>Simple scoring</li>
|
||||
<li>Russian color theme (white, blue, red)</li>
|
||||
</ul>
|
||||
|
||||
<p>Let's build our foundation!</p>
|
||||
</div>
|
||||
|
||||
<div class="btn-container">
|
||||
<button onclick="prevSlide()">Previous</button>
|
||||
<button onclick="nextSlide()">Next</button>
|
||||
</div>
|
||||
<div class="slide-counter">Slide 5 of 8</div>
|
||||
</div>
|
||||
|
||||
<!-- Slide 6: Beta Development -->
|
||||
<div class="slide" id="slide6">
|
||||
<h2>Stage 5: Beta Development</h2>
|
||||
<div class="content">
|
||||
<p>In the Beta stage, we add more features and polish:</p>
|
||||
|
||||
<ul>
|
||||
<li>Backend Developer: Implements lifelines and connects to DeepSeek API</li>
|
||||
<li>Database Designer: Expands to 15 questions with difficulty levels</li>
|
||||
<li>Frontend Developer: Adds lifeline buttons and score display</li>
|
||||
<li>Graphics Artist: Creates matryoshka doll icons and Russian landmark images</li>
|
||||
</ul>
|
||||
|
||||
<p>Our Beta version will have:</p>
|
||||
<ul>
|
||||
<li>All 15 questions with increasing difficulty</li>
|
||||
<li>50:50 and "Ask AI" lifelines</li>
|
||||
<li>Better visuals with Russian themes</li>
|
||||
<li>Sound effects for correct/incorrect answers</li>
|
||||
</ul>
|
||||
|
||||
<div class="game-preview">
|
||||
<div class="game-screen">
|
||||
<div class="question-box">What is the traditional Russian doll called?</div>
|
||||
<div class="option">A. Babushka</div>
|
||||
<div class="option">B. Matryoshka <span class="russian-flag"></span></div>
|
||||
<div class="option">C. Krasnaya</div>
|
||||
<div class="option">D. Kukla</div>
|
||||
<div style="margin-top: 10px; font-size: 0.8rem; text-align: center;">
|
||||
Score: 1,000 RUB | Lifelines: <span style="color: #fdbb2d">50:50</span> | Ask AI |
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="btn-container">
|
||||
<button onclick="prevSlide()">Previous</button>
|
||||
<button onclick="nextSlide()">Next</button>
|
||||
</div>
|
||||
<div class="slide-counter">Slide 6 of 8</div>
|
||||
</div>
|
||||
|
||||
<!-- Slide 7: Production & Testing -->
|
||||
<div class="slide" id="slide7">
|
||||
<h2>Stage 6: Production & Testing</h2>
|
||||
<div class="content">
|
||||
<p>Time to test our game and fix any issues!</p>
|
||||
|
||||
<p>Testing tasks:</p>
|
||||
<ul>
|
||||
<li>Play the game multiple times to find bugs</li>
|
||||
<li>Check if all questions display correctly</li>
|
||||
<li>Test the lifelines - do they work properly?</li>
|
||||
<li>Make sure the scoring system is accurate</li>
|
||||
<li>Verify the AI integration gives helpful hints</li>
|
||||
</ul>
|
||||
|
||||
<p>After testing, we'll:</p>
|
||||
<ul>
|
||||
<li>Fix any problems we find</li>
|
||||
<li>Add final polish to graphics and sounds</li>
|
||||
<li>Prepare for our game launch!</li>
|
||||
</ul>
|
||||
|
||||
<p>Who wants to be our Chief Tester?</p>
|
||||
</div>
|
||||
|
||||
<div class="btn-container">
|
||||
<button onclick="prevSlide()">Previous</button>
|
||||
<button onclick="nextSlide()">Next</button>
|
||||
</div>
|
||||
<div class="slide-counter">Slide 7 of 8</div>
|
||||
</div>
|
||||
|
||||
<!-- Slide 8: Release & Celebration -->
|
||||
<div class="slide" id="slide8">
|
||||
<h2>Stage 7: Release & Celebration!</h2>
|
||||
<div class="content">
|
||||
<p>Congratulations! Our Russian Millionaire Quiz Game is ready!</p>
|
||||
|
||||
<p>What we've accomplished:</p>
|
||||
<ul>
|
||||
<li>Created a working quiz game with 15 Russian trivia questions</li>
|
||||
<li>Built a Flask website with game logic</li>
|
||||
<li>Integrated DeepSeek AI for lifelines</li>
|
||||
<li>Designed Russian-themed graphics and sounds</li>
|
||||
<li>Tested and polished our game</li>
|
||||
</ul>
|
||||
|
||||
<p>Now it's time to:</p>
|
||||
<ul>
|
||||
<li>Share our game with friends and family</li>
|
||||
<li>Celebrate our success!</li>
|
||||
<li>Think about what game we want to make next</li>
|
||||
</ul>
|
||||
|
||||
<div class="game-preview">
|
||||
<div class="game-screen" style="text-align: center; display: flex; flex-direction: column; justify-content: center;">
|
||||
<div style="font-size: 1.5rem; color: #fdbb2d; margin-bottom: 10px;">YOU WIN!</div>
|
||||
<div>1,000,000 RUB</div>
|
||||
<div style="margin-top: 15px; font-size: 0.9rem;">Congratulations, Millionaire!</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p>Great job, game developers! You've successfully created your first AI-powered quiz game!</p>
|
||||
</div>
|
||||
|
||||
<div class="btn-container">
|
||||
<button onclick="prevSlide()">Previous</button>
|
||||
<button onclick="restartPresentation()">Start Over</button>
|
||||
</div>
|
||||
<div class="slide-counter">Slide 8 of 8</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
let currentSlide = 1;
|
||||
const totalSlides = 8;
|
||||
|
||||
function updateProgress() {
|
||||
const progress = (currentSlide / totalSlides) * 100;
|
||||
document.getElementById('progress').style.width = `${progress}%`;
|
||||
}
|
||||
|
||||
function showSlide(n) {
|
||||
// Hide all slides
|
||||
const slides = document.getElementsByClassName('slide');
|
||||
for (let i = 0; i < slides.length; i++) {
|
||||
slides[i].classList.remove('active');
|
||||
}
|
||||
|
||||
// Show the current slide
|
||||
document.getElementById(`slide${n}`).classList.add('active');
|
||||
|
||||
// Update progress bar
|
||||
updateProgress();
|
||||
}
|
||||
|
||||
function nextSlide() {
|
||||
if (currentSlide < totalSlides) {
|
||||
currentSlide++;
|
||||
showSlide(currentSlide);
|
||||
}
|
||||
}
|
||||
|
||||
function prevSlide() {
|
||||
if (currentSlide > 1) {
|
||||
currentSlide--;
|
||||
showSlide(currentSlide);
|
||||
}
|
||||
}
|
||||
|
||||
function restartPresentation() {
|
||||
currentSlide = 1;
|
||||
showSlide(currentSlide);
|
||||
}
|
||||
|
||||
// Initialize the presentation
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
showSlide(1);
|
||||
updateProgress();
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
44
quiz_game/PULL_REQUEST_TEMPLATE.md
Normal file
44
quiz_game/PULL_REQUEST_TEMPLATE.md
Normal file
@@ -0,0 +1,44 @@
|
||||
## Student Submission
|
||||
|
||||
**Name:**
|
||||
**Role:** [Backend/Frontend/Database/Graphics]
|
||||
**Lesson:** [1/2/3]
|
||||
|
||||
## Changes Made
|
||||
|
||||
### Role-Specific Checklist:
|
||||
|
||||
#### Backend Developer (Dima)
|
||||
- [ ] Prize structure implemented (15 levels)
|
||||
- [ ] Game session management
|
||||
- [ ] Answer validation logic
|
||||
- [ ] Lifeline functionality (50:50, Phone Friend)
|
||||
- [ ] All routes working
|
||||
|
||||
#### Frontend Developer (Inna)
|
||||
- [ ] Question display working
|
||||
- [ ] Answer selection handling
|
||||
- [ ] Prize ladder updates
|
||||
- [ ] Lifeline buttons functional
|
||||
- [ ] Game flow complete
|
||||
|
||||
#### Database Designer (Danil)
|
||||
- [ ] 150 Russian culture questions
|
||||
- [ ] Increasing difficulty progression
|
||||
- [ ] Plausible wrong answers
|
||||
- [ ] Categories: history, geography, culture, entertainment
|
||||
|
||||
#### Graphics Artist (Artyom)
|
||||
- [ ] Russian color theme applied
|
||||
- [ ] Enhanced styling from basic template
|
||||
- [ ] Visual improvements
|
||||
- [ ] Visual assets including logo
|
||||
- [ ] Audio assets including sound effects
|
||||
- [ ] Consistent design
|
||||
|
||||
## Testing Performed
|
||||
- [ ] My component works independently
|
||||
- [ ] No errors in console
|
||||
- [ ] Responsive design checked
|
||||
|
||||
## Questions/Blockers
|
||||
1098
quiz_game/Quiz_Game_Project-Student Learning_Portal.html
Normal file
1098
quiz_game/Quiz_Game_Project-Student Learning_Portal.html
Normal file
File diff suppressed because it is too large
Load Diff
13
quiz_game/README.md
Normal file
13
quiz_game/README.md
Normal file
@@ -0,0 +1,13 @@
|
||||
# Quizimoto - Russian Millionaire Quiz Game
|
||||
|
||||
## Team Roles:
|
||||
- **Dima**: Backend Developer (app.py)
|
||||
- **Inna**: Frontend Developer (templates/, static/script.js)
|
||||
- **Danil**: Database Designer (questions.json)
|
||||
- **Artyom**: Graphics/UX Designer (static/style.css, visual design)
|
||||
|
||||
## Development Instructions:
|
||||
1. Each team member focuses on their designated files
|
||||
2. Commit and push changes regularly
|
||||
3. Test your components independently
|
||||
4. Collaborate on integration issues
|
||||
876
quiz_game/Russian_Millionaire_Quiz_Game_Comprehensive_Guide.html
Normal file
876
quiz_game/Russian_Millionaire_Quiz_Game_Comprehensive_Guide.html
Normal file
@@ -0,0 +1,876 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Russian Millionaire Quiz Game - Comprehensive Guide</title>
|
||||
<style>
|
||||
:root {
|
||||
--primary: #1a237e;
|
||||
--secondary: #d32f2f;
|
||||
--accent: #ffc107;
|
||||
--light: #f5f5f5;
|
||||
--dark: #212121;
|
||||
--success: #4caf50;
|
||||
--step-bg: #f8f9fa;
|
||||
--step-border: #dee2e6;
|
||||
}
|
||||
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
||||
}
|
||||
|
||||
body {
|
||||
background-color: var(--light);
|
||||
color: var(--dark);
|
||||
line-height: 1.6;
|
||||
padding: 2rem;
|
||||
}
|
||||
|
||||
.container {
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
header {
|
||||
background: linear-gradient(135deg, var(--primary), #283593);
|
||||
color: white;
|
||||
padding: 2rem;
|
||||
text-align: center;
|
||||
border-radius: 10px 10px 0 0;
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
.logo {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 1rem;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.logo-icon {
|
||||
font-size: 3rem;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 2.5rem;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.subtitle {
|
||||
font-size: 1.4rem;
|
||||
opacity: 0.9;
|
||||
}
|
||||
|
||||
.section {
|
||||
background: white;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 4px 8px rgba(0,0,0,0.1);
|
||||
margin-bottom: 2rem;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.section-header {
|
||||
background: var(--step-bg);
|
||||
padding: 1.5rem;
|
||||
border-bottom: 2px solid var(--step-border);
|
||||
font-size: 1.3rem;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.section-content {
|
||||
padding: 1.5rem;
|
||||
}
|
||||
|
||||
.step {
|
||||
background: #f9f9f9;
|
||||
border-left: 4px solid var(--primary);
|
||||
margin: 1rem 0;
|
||||
padding: 1rem;
|
||||
border-radius: 0 8px 8px 0;
|
||||
}
|
||||
|
||||
.step-number {
|
||||
background: var(--primary);
|
||||
color: white;
|
||||
padding: 0.3rem 0.7rem;
|
||||
border-radius: 4px;
|
||||
font-weight: bold;
|
||||
margin-bottom: 0.5rem;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.file-structure {
|
||||
background: #fff8e1;
|
||||
padding: 1rem;
|
||||
border-radius: 8px;
|
||||
margin: 1rem 0;
|
||||
}
|
||||
|
||||
.file-item {
|
||||
margin: 0.3rem 0;
|
||||
padding-left: 1.5rem;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.file-item:before {
|
||||
content: "📄";
|
||||
position: absolute;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.folder:before {
|
||||
content: "📁";
|
||||
}
|
||||
|
||||
.code-block {
|
||||
position: relative;
|
||||
background: #2d2d2d;
|
||||
color: #f8f8f2;
|
||||
border-radius: 8px;
|
||||
padding: 1rem;
|
||||
margin: 1rem 0;
|
||||
overflow-x: auto;
|
||||
font-family: 'Courier New', Courier, monospace;
|
||||
font-size: 0.9rem;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.code-line {
|
||||
position: relative;
|
||||
padding-left: 4rem;
|
||||
}
|
||||
|
||||
.line-number {
|
||||
position: absolute;
|
||||
left: 1rem;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.tip-box {
|
||||
background: #e8f5e9;
|
||||
padding: 1rem;
|
||||
border-left: 4px solid var(--success);
|
||||
margin: 1rem 0;
|
||||
border-radius: 0 8px 8px 0;
|
||||
}
|
||||
|
||||
.role-header {
|
||||
background: var(--step-bg);
|
||||
padding: 1rem;
|
||||
margin-top: 1.5rem;
|
||||
border-radius: 8px;
|
||||
font-weight: bold;
|
||||
color: var(--primary);
|
||||
}
|
||||
|
||||
footer {
|
||||
text-align: center;
|
||||
padding: 2rem;
|
||||
color: #666;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<header>
|
||||
<div class="logo">
|
||||
<div class="logo-icon">🎮</div>
|
||||
<div>
|
||||
<h1>Russian Millionaire Quiz Game</h1>
|
||||
<div class="subtitle">Comprehensive Step-by-Step Guide</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="section">
|
||||
<div class="section-header">Project Overview</div>
|
||||
<div class="section-content">
|
||||
<div class="file-structure">
|
||||
<h4>Project File Structure:</h4>
|
||||
<div class="file-item folder">russian-millionaire/</div>
|
||||
<div class="file-item">app.py (Main application file)</div>
|
||||
<div class="file-item">questions.json (All quiz questions)</div>
|
||||
<div class="file-item folder">templates/</div>
|
||||
<div class="file-item">index.html (Home page)</div>
|
||||
<div class="file-item">game.html (Game screen)</div>
|
||||
<div class="file-item folder">static/</div>
|
||||
<div class="file-item">style.css (All styling)</div>
|
||||
<div class="file-item">script.js (Game interaction)</div>
|
||||
</div>
|
||||
|
||||
<div class="tip-box">
|
||||
<p><strong>Pro Tip:</strong> All project files are available at <a href="https://gitea.techshare.cc/technolyceum/ai6-m2.git" target="_blank">https://gitea.techshare.cc/technolyceum/ai6-m2.git</a></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="section">
|
||||
<div class="section-header">Installation Instructions</div>
|
||||
<div class="section-content">
|
||||
<div class="step">
|
||||
<div class="step-number">STEP 1</div>
|
||||
<h3>Clone the Repository</h3>
|
||||
<p>Open your terminal and run the following command to get the project files:</p>
|
||||
<div class="code-block">
|
||||
<div class="code-line">
|
||||
<span class="line-number">1</span>
|
||||
git clone https://gitea.techshare.cc/technolyceum/ai6-m2.git
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="step">
|
||||
<div class="step-number">STEP 2</div>
|
||||
<h3>Navigate to Project Directory</h3>
|
||||
<p>Move into the project directory using:</p>
|
||||
<div class="code-block">
|
||||
<div class="code-line">
|
||||
<span class="line-number">1</span>
|
||||
cd ai6-m2
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="step">
|
||||
<div class="step-number">STEP 3</div>
|
||||
<h3>Install Requirements</h3>
|
||||
<p>Install the necessary Python packages:</p>
|
||||
<div class="code-block">
|
||||
<div class="code-line">
|
||||
<span class="line-number">1</span>
|
||||
pip install -r requirements.txt
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="section">
|
||||
<div class="section-header">Database Setup - Danil</div>
|
||||
<div class="section-content">
|
||||
<div class="step">
|
||||
<div class="step-number">STEP 1</div>
|
||||
<h3>Open Database File</h3>
|
||||
<p>Navigate to the database file at:</p>
|
||||
<div class="code-block">
|
||||
<div class="code-line">
|
||||
<span class="line-number">1</span>
|
||||
/Users/home/YandexDisk/TECHNOLYCEUM/ict_repos/ai6-m2/starter_templates/docs/roles/database-designer-danil.md
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="step">
|
||||
<div class="step-number">STEP 2</div>
|
||||
<h3>Set Up MongoDB Connection (Lines 1-5)</h3>
|
||||
<p>Add the MongoDB connection information:</p>
|
||||
<div class="code-block">
|
||||
<div class="code-line">
|
||||
<span class="line-number">1</span>
|
||||
// 1. Import MongoDB driver (line 1)
|
||||
</div>
|
||||
<div class="code-line">
|
||||
<span class="line-number">2</span>
|
||||
from pymongo import MongoClient
|
||||
</div>
|
||||
<div class="code-line">
|
||||
<span class="line-number">3</span>
|
||||
|
||||
</div>
|
||||
<div class="code-line">
|
||||
<span class="line-number">4</span>
|
||||
// 2. Connect to MongoDB using the connection URI (line 3-5)
|
||||
</div>
|
||||
<div class="code-line">
|
||||
<span class="line-number">5</span>
|
||||
client = MongoClient('mongodb://localhost:27017/')
|
||||
</div>
|
||||
<div class="code-line">
|
||||
<span class="line-number">6</span>
|
||||
|
||||
</div>
|
||||
<div class="code-line">
|
||||
<span class="line-number">7</span>
|
||||
// 3. Select the appropriate database (line 7)
|
||||
</div>
|
||||
<div class="code-line">
|
||||
<span class="line-number">8</span>
|
||||
db = client['student_db']
|
||||
</div>
|
||||
<div class="code-line">
|
||||
<span class="line-number">9</span>
|
||||
|
||||
</div>
|
||||
<div class="code-line">
|
||||
<span class="line-number">10</span>
|
||||
// 4. Select the questions collection (line 9)
|
||||
</div>
|
||||
<div class="code-line">
|
||||
<span class="line-number">11</span>
|
||||
questions_collection = db['questions']
|
||||
</div>
|
||||
<div class="code-line">
|
||||
<span class="line-number">12</span>
|
||||
|
||||
</div>
|
||||
<div class="code-line">
|
||||
<span class="line-number">13</span>
|
||||
// 5. Add error handling for database connection (line 11)
|
||||
</div>
|
||||
<div class="code-line">
|
||||
<span class="line-number">14</span>
|
||||
try:
|
||||
</div>
|
||||
<div class="code-line">
|
||||
<span class="line-number">15</span>
|
||||
client.admin.command('ping')
|
||||
</div>
|
||||
<div class="code-line">
|
||||
<span class="line-number">16</span>
|
||||
print("Successfully connected to MongoDB!")
|
||||
</div>
|
||||
<div class="code-line">
|
||||
<span class="line-number">17</span>
|
||||
except Exception as e:
|
||||
</div>
|
||||
<div class="code-line">
|
||||
<span class="line-number">18</span>
|
||||
print(f"MongoDB connection error: {e}")
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="step">
|
||||
<div class="step-number">STEP 3</div>
|
||||
<h3>Insert Questions into Database</h3>
|
||||
<p>Add your quiz questions to the database:</p>
|
||||
<div class="code-block">
|
||||
<div class="code-line">
|
||||
<span class="line-number">1</span>
|
||||
// Sample question format
|
||||
</div>
|
||||
<div class="code-line">
|
||||
<span class="line-number">2</span>
|
||||
question = {
|
||||
</div>
|
||||
<div class="code-line">
|
||||
<span class="line-number">3</span>
|
||||
// 1. Question text (line 1)
|
||||
</div>
|
||||
<div class="code-line">
|
||||
<span class="line-number">4</span>
|
||||
"question": "What is the capital of Russia?",
|
||||
</div>
|
||||
<div class="code-line">
|
||||
<span class="line-number">5</span>
|
||||
// 2. Answer options (line 2-5)
|
||||
</div>
|
||||
<div class="code-line">
|
||||
<span class="line-number">6</span>
|
||||
"options": ["Moscow", "St. Petersburg", "Novosibirsk", "Kazan"],
|
||||
</div>
|
||||
<div class="code-line">
|
||||
<span class="line-number">7</span>
|
||||
// 3. Correct answer index (line 6)
|
||||
</div>
|
||||
<div class="code-line">
|
||||
<span class="line-number">8</span>
|
||||
"correct_answer": 0
|
||||
</div>
|
||||
<div class="code-line">
|
||||
<span class="line-number">9</span>
|
||||
}
|
||||
</div>
|
||||
<div class="code-line">
|
||||
<span class="line-number">10</span>
|
||||
|
||||
</div>
|
||||
<div class="code-line">
|
||||
<span class="line-number">11</span>
|
||||
// Insert question into collection (line 8)
|
||||
</div>
|
||||
<div class="code-line">
|
||||
<span class="line-number">12</span>
|
||||
questions_collection.insert_one(question)
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="section">
|
||||
<div class="section-header">Backend Setup - Dima</div>
|
||||
<div class="section-content">
|
||||
<div class="step">
|
||||
<div class="step-number">STEP 1</div>
|
||||
<h3>Open Backend File</h3>
|
||||
<p>Navigate to the backend developer documentation:</p>
|
||||
<div class="code-block">
|
||||
<div class="code-line">
|
||||
<span class="line-number">1</span>
|
||||
/Users/home/YandexDisk/TECHNOLYCEUM/ict_repos/ai6-m2/starter_templates/docs/roles/backend-developer-dima.md
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="step">
|
||||
<div class="step-number">STEP 2</div>
|
||||
<h3>Set Up Flask Application (Lines 1-6)</h3>
|
||||
<p>Add the Flask setup code:</p>
|
||||
<div class="code-block">
|
||||
<div class="code-line">
|
||||
<span class="line-number">1</span>
|
||||
// 1. Import Flask and PyMongo (line 1-2)
|
||||
</div>
|
||||
<div class="code-line">
|
||||
<span class="line-number">2</span>
|
||||
from flask import Flask, session, redirect, url_for, request, jsonify
|
||||
</div>
|
||||
<div class="code-line">
|
||||
<span class="line-number">3</span>
|
||||
from flask_pymongo import PyMongo
|
||||
</div>
|
||||
<div class="code-line">
|
||||
<span class="line-number">4</span>
|
||||
|
||||
</div>
|
||||
<div class="code-line">
|
||||
<span class="line-number">5</span>
|
||||
// 2. Connect to MongoDB database (line 4-6)
|
||||
</div>
|
||||
<div class="code-line">
|
||||
<span class="line-number">6</span>
|
||||
app = Flask(__name__)
|
||||
</div>
|
||||
<div class="code-line">
|
||||
<span class="line-number">7</span>
|
||||
app.config['MONGO_URI'] = 'mongodb://localhost:27017/student_db'
|
||||
</div>
|
||||
<div class="code-line">
|
||||
<span class="line-number">8</span>
|
||||
mongo = PyMongo(app)
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="step">
|
||||
<div class="step-number">STEP 3</div>
|
||||
<h3>Define API Endpoints (Lines 8-14)</h3>
|
||||
<p>Add the API endpoints for getting questions and submitting answers:</p>
|
||||
<div class="code-block">
|
||||
<div class="code-line">
|
||||
<span class="line-number">1</span>
|
||||
// 3. Define API endpoint for getting questions (line 8-10)
|
||||
</div>
|
||||
<div class="code-line">
|
||||
<span class="line-number">2</span>
|
||||
@app.route('/get_question')
|
||||
</div>
|
||||
<div class="code-line">
|
||||
<span class="line-number">3</span>
|
||||
def get_question():
|
||||
</div>
|
||||
<div class="code-line">
|
||||
<span class="line-number">4</span>
|
||||
// 1. Get current question number from session
|
||||
</div>
|
||||
<div class="code-line">
|
||||
<span class="line-number">5</span>
|
||||
question_num = session.get('current_question', 0)
|
||||
</div>
|
||||
<div class="code-line">
|
||||
<span class="line-number">6</span>
|
||||
|
||||
</div>
|
||||
<div class="code-line">
|
||||
<span class="line-number">7</span>
|
||||
// 2. Get question from database
|
||||
</div>
|
||||
<div class="code-line">
|
||||
<span class="line-number">8</span>
|
||||
question = mongo.db.questions.find_one({"question_number": question_num})
|
||||
</div>
|
||||
<div class="code-line">
|
||||
<span class="line-number">9</span>
|
||||
|
||||
</div>
|
||||
<div class="code-line">
|
||||
<span class="line-number">10</span>
|
||||
// 3. Format response
|
||||
</div>
|
||||
<div class="code-line">
|
||||
<span class="line-number">11</span>
|
||||
if question:
|
||||
</div>
|
||||
<div class="code-line">
|
||||
<span class="line-number">12</span>
|
||||
return jsonify({
|
||||
</div>
|
||||
<div class="code-line">
|
||||
<span class="line-number">13</span>
|
||||
"question": question['question'],
|
||||
</div>
|
||||
<div class="code-line">
|
||||
<span class="line-number">14</span>
|
||||
"options": question['options'],
|
||||
</div>
|
||||
<div class="code-line">
|
||||
<span class="line-number">15</span>
|
||||
"question_number": question_num,
|
||||
</div>
|
||||
<div class="code-line">
|
||||
<span class="line-number">16</span>
|
||||
"current_prize": calculate_prize(question_num)
|
||||
</div>
|
||||
<div class="code-line">
|
||||
<span class="line-number">17</span>
|
||||
})
|
||||
</div>
|
||||
<div class="code-line">
|
||||
<span class="line-number">18</span>
|
||||
else:
|
||||
</div>
|
||||
<div class="code-line">
|
||||
<span class="line-number">19</span>
|
||||
return jsonify({"game_over": True, "final_score": calculate_final_score()})
|
||||
</div>
|
||||
<div class="code-line">
|
||||
<span class="line-number">20</span>
|
||||
|
||||
</div>
|
||||
<div class="code-line">
|
||||
<span class="line-number">21</span>
|
||||
// 4. Define API endpoint for submitting answers (line 12-14)
|
||||
</div>
|
||||
<div class="code-line">
|
||||
<span class="line-number">22</span>
|
||||
@app.route('/answer', methods=['POST'])
|
||||
</div>
|
||||
<div class="code-line">
|
||||
<span class="line-number">23</span>
|
||||
def answer_question():
|
||||
</div>
|
||||
<div class="code-line">
|
||||
<span class="line-number">24</span>
|
||||
// 1. Get user's answer
|
||||
</div>
|
||||
<div class="code-line">
|
||||
<span class="line-number">25</span>
|
||||
user_answer = request.json.get('answer')
|
||||
</div>
|
||||
<div class="code-line">
|
||||
<span class="line-number">26</span>
|
||||
|
||||
</div>
|
||||
<div class="code-line">
|
||||
<span class="line-number">27</span>
|
||||
// 2. Get current question
|
||||
</div>
|
||||
<div class="code-line">
|
||||
<span class="line-number">28</span>
|
||||
question_num = session.get('current_question', 0)
|
||||
</div>
|
||||
<div class="code-line">
|
||||
<span class="line-number">29</span>
|
||||
current_question = mongo.db.questions.find_one({"question_number": question_num})
|
||||
</div>
|
||||
<div class="code-line">
|
||||
<span class="line-number">30</span>
|
||||
|
||||
</div>
|
||||
<div class="code-line">
|
||||
<span class="line-number">31</span>
|
||||
// 3. Check if answer is correct
|
||||
</div>
|
||||
<div class="code-line">
|
||||
<span class="line-number">32</span>
|
||||
is_correct = current_question['options'][current_question['correct_answer']] == user_answer
|
||||
</div>
|
||||
<div class="code-line">
|
||||
<span class="line-number">33</span>
|
||||
|
||||
</div>
|
||||
<div class="code-line">
|
||||
<span class="line-number">34</span>
|
||||
// 4. Update game state
|
||||
</div>
|
||||
<div class="code-line">
|
||||
<span class="line-number">35</span>
|
||||
if is_correct:
|
||||
</div>
|
||||
<div class="code-line">
|
||||
<span class="line-number">36</span>
|
||||
session['current_question'] = question_num + 1
|
||||
</div>
|
||||
<div class="code-line">
|
||||
<span class="line-number">37</span>
|
||||
return jsonify({
|
||||
</div>
|
||||
<div class="code-line">
|
||||
<span class="line-number">38</span>
|
||||
"correct": True,
|
||||
</div>
|
||||
<div class="code-line">
|
||||
<span class="line-number">39</span>
|
||||
"correct_answer": current_question['correct_answer'],
|
||||
</div>
|
||||
<div class="code-line">
|
||||
<span class="line-number">40</span>
|
||||
"game_over": question_num + 1 >= TOTAL_QUESTIONS
|
||||
</div>
|
||||
<div class="code-line">
|
||||
<span class="line-number">41</span>
|
||||
})
|
||||
</div>
|
||||
<div class="code-line">
|
||||
<span class="line-number">42</span>
|
||||
else:
|
||||
</div>
|
||||
<div class="code-line">
|
||||
<span class="line-number">43</span>
|
||||
return jsonify({
|
||||
</div>
|
||||
<div class="code-line">
|
||||
<span class="line-number">44</span>
|
||||
"correct": False,
|
||||
</div>
|
||||
<div class="code-line">
|
||||
<span class="line-number">45</span>
|
||||
"correct_answer": current_question['correct_answer'],
|
||||
</div>
|
||||
<div class="code-line">
|
||||
<span class="line-number">46</span>
|
||||
"game_over": True
|
||||
</div>
|
||||
<div class="code-line">
|
||||
<span class="line-number">47</span>
|
||||
})
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="section">
|
||||
<div class="section-header">Frontend Setup - Inna</div>
|
||||
<div class="section-content">
|
||||
<div class="step">
|
||||
<div class="step-number">STEP 1</div>
|
||||
<h3>Open Frontend File</h3>
|
||||
<p>Navigate to the frontend developer documentation:</p>
|
||||
<div class="code-block">
|
||||
<div class="code-line">
|
||||
<span class="line-number">1</span>
|
||||
/Users/home/YandexDisk/TECHNOLYCEUM/ict_repos/ai6-m2/starter_templates/docs/roles/frontend-developer-inna.md
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="step">
|
||||
<div class="step-number">STEP 2</div>
|
||||
<h3>Create HTML Structure (Lines 1-5)</h3>
|
||||
<p>Add the basic HTML structure with game container:</p>
|
||||
<div class="code-block">
|
||||
<div class="code-line">
|
||||
<span class="line-number">1</span>
|
||||
// 1. Create HTML structure with game container (line 1-5)
|
||||
</div>
|
||||
<div class="code-line">
|
||||
<span class="line-number">2</span>
|
||||
<!DOCTYPE html>
|
||||
</div>
|
||||
<div class="code-line">
|
||||
<span class="line-number">3</span>
|
||||
<html lang="en">
|
||||
</div>
|
||||
<div class="code-line">
|
||||
<span class="line-number">4</span>
|
||||
<head>
|
||||
</div>
|
||||
<div class="code-line">
|
||||
<span class="line-number">5</span>
|
||||
<meta charset="UTF-8">
|
||||
</div>
|
||||
<div class="code-line">
|
||||
<span class="line-number">6</span>
|
||||
<title>Russian Quiz</title>
|
||||
</div>
|
||||
<div class="code-line">
|
||||
<span class="line-number">7</span>
|
||||
<link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}">
|
||||
</div>
|
||||
<div class="code-line">
|
||||
<span class="line-number">8</span>
|
||||
</head>
|
||||
</div>
|
||||
<div class="code-line">
|
||||
<span class="line-number">9</span>
|
||||
<body>
|
||||
</div>
|
||||
<div class="code-line">
|
||||
<span class="line-number">10</span>
|
||||
<div class="container">
|
||||
</div>
|
||||
<div class="code-line">
|
||||
<span class="line-number">11</span>
|
||||
<h1>Russian Quiz</h1>
|
||||
</div>
|
||||
<div class="code-line">
|
||||
<span class="line-number">12</span>
|
||||
<div class="score">Prize: <span id="prize">0</span> ₽</div>
|
||||
</div>
|
||||
<div class="code-line">
|
||||
<span class="line-number">13</span>
|
||||
|
||||
</div>
|
||||
<div class="code-line">
|
||||
<span class="line-number">14</span>
|
||||
<div class="question-box">
|
||||
</div>
|
||||
<div class="code-line">
|
||||
<span class="line-number">15</span>
|
||||
<div class="question-number">Question <span id="q-number">1</span>/5</div>
|
||||
</div>
|
||||
<div class="code-line">
|
||||
<span class="line-number">16</span>
|
||||
<div class="question" id="question-text">Loading...</div>
|
||||
</div>
|
||||
<div class="code-line">
|
||||
<span class="line-number">17</span>
|
||||
|
||||
</div>
|
||||
<div class="code-line">
|
||||
<span class="line-number">18</span>
|
||||
<div class="options" id="options">
|
||||
</div>
|
||||
<div class="code-line">
|
||||
<span class="line-number">19</span>
|
||||
<!-- Options go here -->
|
||||
</div>
|
||||
<div class="code-line">
|
||||
<span class="line-number">20</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="code-line">
|
||||
<span class="line-number">21</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="step">
|
||||
<div class="step-number">STEP 3</div>
|
||||
<h3>Add Game Controls (Lines 17-20)</h3>
|
||||
<p>Add the game control elements:</p>
|
||||
<div class="code-block">
|
||||
<div class="code-line">
|
||||
<span class="line-number">1</span>
|
||||
// 4. Implement game controls and lifelines (line 17-20)
|
||||
</div>
|
||||
<div class="code-line">
|
||||
<span class="line-number">2</span>
|
||||
<button class="lifeline" onclick="useFiftyFifty()">50:50 Lifeline</button>
|
||||
</div>
|
||||
<div class="code-line">
|
||||
<span class="line-number">3</span>
|
||||
|
||||
</div>
|
||||
<div class="code-line">
|
||||
<span class="line-number">4</span>
|
||||
<div class="result" id="result"></div>
|
||||
</div>
|
||||
<div class="code-line">
|
||||
<span class="line-number">5</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="code-line">
|
||||
<span class="line-number">6</span>
|
||||
// 5. Add game over screen UI (line 22-25)
|
||||
</div>
|
||||
<div class="code-line">
|
||||
<span class="line-number">7</span>
|
||||
<div class="game-over" id="game-over" style="display: none;">
|
||||
</div>
|
||||
<div class="code-line">
|
||||
<span class="line-number">8</span>
|
||||
<h2>Game Over!</h2>
|
||||
</div>
|
||||
<div class="code-line">
|
||||
<span class="line-number">9</span>
|
||||
<p>You won: <span id="final-prize">0</span> ₽</p>
|
||||
</div>
|
||||
<div class="code-line">
|
||||
<span class="line-number">10</span>
|
||||
<button onclick="restartGame()">Play Again</button>
|
||||
</div>
|
||||
<div class="code-line">
|
||||
<span class="line-number">11</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="section">
|
||||
<div class="section-header">Final Steps</div>
|
||||
<div class="section-content">
|
||||
<div class="step">
|
||||
<div class="step-number">STEP 1</div>
|
||||
<h3>Start MongoDB</h3>
|
||||
<p>Make sure MongoDB is running:</p>
|
||||
<div class="code-block">
|
||||
<div class="code-line">
|
||||
<span class="line-number">1</span>
|
||||
// Start MongoDB service
|
||||
</div>
|
||||
<div class="code-line">
|
||||
<span class="line-number">2</span>
|
||||
sudo service mongod start
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="step">
|
||||
<div class="step-number">STEP 2</div>
|
||||
<h3>Run the Application</h3>
|
||||
<p>Start the Flask application:</p>
|
||||
<div class="code-block">
|
||||
<div class="code-line">
|
||||
<span class="line-number">1</span>
|
||||
// Run the app
|
||||
</div>
|
||||
<div class="code-line">
|
||||
<span class="line-number">2</span>
|
||||
python app.py
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="step">
|
||||
<div class="step-number">STEP 3</div>
|
||||
<h3>Access the Game</h3>
|
||||
<p>Open your browser and go to:</p>
|
||||
<div class="code-block">
|
||||
<div class="code-line">
|
||||
<span class="line-number">1</span>
|
||||
http://localhost:5000/start
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<footer>
|
||||
<p>© 2025 Technolyceum. All rights reserved.</p>
|
||||
<p>For support, contact: techsupport@technolyceum.cc</p>
|
||||
</footer>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
BIN
quiz_game/__pycache__/app.cpython-313.pyc
Normal file
BIN
quiz_game/__pycache__/app.cpython-313.pyc
Normal file
Binary file not shown.
151
quiz_game/app.py
Normal file
151
quiz_game/app.py
Normal file
@@ -0,0 +1,151 @@
|
||||
from flask import Flask, render_template, request, jsonify, session
|
||||
import json
|
||||
import random
|
||||
from pymongo import MongoClient # Added MongoDB support
|
||||
|
||||
# MongoDB connection
|
||||
MONGO_URI = "mongodb://ai6s3:Student123!@localhost:27017/student_db"
|
||||
client = MongoClient(MONGO_URI)
|
||||
db = client.student_db # Connect to student_db database
|
||||
questions_collection = db.questions # Use questions collection
|
||||
|
||||
app = Flask(__name__)
|
||||
app.secret_key = 'quizimoto_secret_key'
|
||||
|
||||
# Load questions from MongoDB
|
||||
try:
|
||||
questions_data = list(questions_collection.find({}))
|
||||
except Exception as e:
|
||||
print(f"Error loading questions from MongoDB: {e}")
|
||||
questions_data = [] # Fallback to empty list if database connection fails
|
||||
|
||||
# Prize structure (15 levels)
|
||||
PRIZE_LEVELS = [
|
||||
100, 200, 300, 500, 1000,
|
||||
2000, 4000, 8000, 16000, 32000,
|
||||
64000, 125000, 250000, 500000, 1000000
|
||||
]
|
||||
|
||||
GUARANTEED_LEVELS = [5, 10] # First and second guaranteed levels
|
||||
|
||||
def get_current_question():
|
||||
"""Get current question data from session"""
|
||||
current_q_index = session.get('current_question', 0)
|
||||
questions = session.get('questions', [])
|
||||
|
||||
if current_q_index >= len(questions):
|
||||
return None
|
||||
|
||||
return questions[current_q_index], current_q_index
|
||||
|
||||
def calculate_guaranteed_prize(current_index):
|
||||
"""Calculate the guaranteed prize based on current question index"""
|
||||
final_score = 0
|
||||
for level in sorted(GUARANTEED_LEVELS, reverse=True):
|
||||
if current_index + 1 >= level:
|
||||
final_score = PRIZE_LEVELS[level - 1] if level <= len(PRIZE_LEVELS) else 0
|
||||
break
|
||||
return final_score
|
||||
|
||||
@app.route('/')
|
||||
def index():
|
||||
return render_template('index.html')
|
||||
|
||||
@app.route('/start')
|
||||
def start_game():
|
||||
# Initialize game session
|
||||
session['score'] = 0
|
||||
session['current_question'] = 0
|
||||
session['lifelines'] = ['fifty_fifty']
|
||||
session['questions'] = random.sample(questions_data, min(15, len(questions_data))) # Select up to 15 random questions
|
||||
return render_template('game.html')
|
||||
|
||||
@app.route('/get_question')
|
||||
def get_question():
|
||||
current_q_index = session.get('current_question', 0)
|
||||
|
||||
# Check if game is over (15 questions answered or no more questions)
|
||||
if current_q_index >= len(session.get('questions', [])) or current_q_index >= 15:
|
||||
return jsonify({
|
||||
"game_over": True,
|
||||
"final_score": session.get('score', 0)
|
||||
})
|
||||
|
||||
question_data = session['questions'][current_q_index]
|
||||
|
||||
return jsonify({
|
||||
"question_number": current_q_index + 1,
|
||||
"question": question_data['question'],
|
||||
"options": question_data['options'],
|
||||
"current_prize": PRIZE_LEVELS[current_q_index] if current_q_index < len(PRIZE_LEVELS) else 1000000,
|
||||
"game_over": False
|
||||
})
|
||||
|
||||
@app.route('/answer', methods=['POST'])
|
||||
def check_answer():
|
||||
data = request.get_json()
|
||||
answer = data.get('answer', '')
|
||||
|
||||
question_info = get_current_question()
|
||||
if not question_info:
|
||||
return jsonify({"error": "No more questions"})
|
||||
|
||||
question_data, current_q_index = question_info
|
||||
correct = answer == question_data['correct_answer']
|
||||
|
||||
if correct:
|
||||
session['current_q_index'] = current_q_index + 1
|
||||
session['score'] = PRIZE_LEVELS[current_q_index] if current_q_index < len(PRIZE_LEVELS) else session.get('score', 0)
|
||||
|
||||
# Check if game is won (15th question answered correctly)
|
||||
game_won = session['current_question'] >= min(15, len(session.get('questions', [])))
|
||||
|
||||
return jsonify({
|
||||
"correct": True,
|
||||
"correct_answer": question_data['correct_answer'],
|
||||
"final_score": session['score'],
|
||||
"game_over": game_won
|
||||
})
|
||||
else:
|
||||
# Game over with last guaranteed prize
|
||||
final_score = calculate_guaranteed_prize(current_q_index)
|
||||
|
||||
return jsonify({
|
||||
"correct": False,
|
||||
"correct_answer": question_data['correct_answer'],
|
||||
"final_score": final_score,
|
||||
"game_over": True
|
||||
})
|
||||
|
||||
@app.route('/lifeline/<lifeline_name>')
|
||||
def use_lifeline(lifeline_name):
|
||||
if lifeline_name != 'fifty_fifty':
|
||||
return jsonify({"error": "Unknown lifeline"})
|
||||
|
||||
if 'fifty_fifty' not in session.get('lifelines', []):
|
||||
return jsonify({"error": "Lifeline already used"})
|
||||
|
||||
question_info = get_current_question()
|
||||
if not question_info:
|
||||
return jsonify({"error": "No current question"})
|
||||
|
||||
# Remove the lifeline from available lifelines
|
||||
session['lifelines'].remove('fifty_fifty')
|
||||
|
||||
question_data, _ = question_info
|
||||
correct_answer = question_data['correct_answer']
|
||||
options = question_data['options']
|
||||
|
||||
# Find indices of wrong answers to remove (we need to remove 2)
|
||||
wrong_indices = [i for i, option in enumerate(options) if option != correct_answer]
|
||||
|
||||
# Randomly select 2 wrong indices to remove
|
||||
indices_to_remove = random.sample(wrong_indices, min(2, len(wrong_indices)))
|
||||
indices_to_remove.sort(reverse=True) # Sort in descending order for safe removal
|
||||
|
||||
return jsonify({
|
||||
"remove_indices": indices_to_remove
|
||||
})
|
||||
|
||||
if __name__ == '__main__':
|
||||
app.run(debug=True)
|
||||
BIN
quiz_game/docs/.DS_Store
vendored
Normal file
BIN
quiz_game/docs/.DS_Store
vendored
Normal file
Binary file not shown.
19
quiz_game/docs/README.md
Normal file
19
quiz_game/docs/README.md
Normal file
@@ -0,0 +1,19 @@
|
||||
# Project Documentation
|
||||
|
||||
This directory contains all the documentation for the Millionaire Quiz Game project.
|
||||
|
||||
## Structure
|
||||
|
||||
- [/roles](file:///Users/home/YandexDisk/TECHNOLYCEUM/ict_repos/ai6-m2/docs/roles) - Role-specific instructions and guidelines for team members
|
||||
- [/technical-specs](file:///Users/home/YandexDisk/TECHNOLYCEUM/ict_repos/ai6-m2/docs/technical-specs) - Technical specifications and architecture documents
|
||||
|
||||
## Role Documentation
|
||||
|
||||
Each team member has their own instruction file:
|
||||
|
||||
- [Frontend Developer (Inna)](file:///Users/home/YandexDisk/TECHNOLYCEUM/ict_repos/ai6-m2/docs/roles/frontend-developer-inna.md)
|
||||
- [Backend Developer (Dima)](file:///Users/home/YandexDisk/TECHNOLYCEUM/ict_repos/ai6-m2/docs/roles/backend-developer-dima.md)
|
||||
- [Database Designer (Danil)](file:///Users/home/YandexDisk/TECHNOLYCEUM/ict_repos/ai6-m2/docs/roles/database-designer-danil.md)
|
||||
- [Graphics Designer (Artyom)](file:///Users/home/YandexDisk/TECHNOLYCEUM/ict_repos/ai6-m2/docs/roles/graphics-designer-artyom.md)
|
||||
|
||||
These documents contain step-by-step instructions for implementing various parts of the application.
|
||||
185
quiz_game/docs/roles/backend-developer-dima.md
Normal file
185
quiz_game/docs/roles/backend-developer-dima.md
Normal file
@@ -0,0 +1,185 @@
|
||||
DIMA - BACKEND DEVELOPER MISSION
|
||||
Your Role: Game Brain Developer | Your File: app.py
|
||||
|
||||
💡 What You're Building: You're creating the "brain" of the game - all the rules, scoring, and game logic!
|
||||
|
||||
📋 LESSON 1-2: SETUP & PRIZE SYSTEM
|
||||
|
||||
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 dima-backend-work
|
||||
|
||||
Step 2: Create the Prize Money System (20 minutes)
|
||||
Open app.py and find these lines around line 13:
|
||||
|
||||
# Prize structure (15 levels)
|
||||
PRIZE_LEVELS = [
|
||||
100, 200, 300, 500, 1000,
|
||||
2000, 4000, 8000, 16000, 32000,
|
||||
64000, 125000, 250000, 500000, 1000000
|
||||
]
|
||||
|
||||
This is already implemented! Notice how the prizes increase as the player progresses through the questions.
|
||||
|
||||
Step 3: Review Game Session Management (15 minutes)
|
||||
Look at the [start_game](file:///Users/home/YandexDisk/TECHNOLYCEUM/ict_repos/ai6-m2/app.py#L42-L48) function (around line 42):
|
||||
|
||||
```python
|
||||
@app.route('/start')
|
||||
def start_game():
|
||||
# Initialize game session
|
||||
session['score'] = 0
|
||||
session['current_question'] = 0
|
||||
session['lifelines'] = ['fifty_fifty']
|
||||
session['questions'] = random.sample(questions_data, min(15, len(questions_data)))
|
||||
return render_template('game.html')
|
||||
```
|
||||
|
||||
This function initializes the game session with:
|
||||
- Starting score of 0
|
||||
- Current question index of 0
|
||||
- One lifeline available: fifty_fifty
|
||||
- A random selection of up to 15 questions from the database
|
||||
|
||||
📋 LESSON 3-4: QUESTION RETRIEVAL & ANSWER VALIDATION
|
||||
|
||||
Step 4: Review Question Retrieval (15 minutes)
|
||||
Check the [get_question](file:///Users/home/YandexDisk/TECHNOLYCEUM/ict_repos/ai6-m2/app.py#L50-L66) function (around line 50):
|
||||
|
||||
```python
|
||||
@app.route('/get_question')
|
||||
def get_question():
|
||||
current_q_index = session.get('current_question', 0)
|
||||
|
||||
# Check if game is over
|
||||
if current_q_index >= min(15, len(session.get('questions', []))):
|
||||
return jsonify({
|
||||
"game_over": True,
|
||||
"final_score": session.get('score', 0)
|
||||
})
|
||||
|
||||
question_data = session['questions'][current_q_index]
|
||||
|
||||
return jsonify({
|
||||
"question_number": current_q_index + 1,
|
||||
"question": question_data['question'],
|
||||
"options": question_data['options'],
|
||||
"current_prize": PRIZE_LEVELS[current_q_index] if current_q_index < len(PRIZE_LEVELS) else 1000000,
|
||||
"game_over": False
|
||||
})
|
||||
```
|
||||
|
||||
This function retrieves the current question and formats it for the frontend.
|
||||
|
||||
Step 5: Review Answer Validation (20 minutes)
|
||||
Look at the [check_answer](file:///Users/home/YandexDisk/TECHNOLYCEUM/ict_repos/ai6-m2/app.py#L68-L103) function (around line 68):
|
||||
|
||||
```python
|
||||
@app.route('/answer', methods=['POST'])
|
||||
def check_answer():
|
||||
data = request.get_json()
|
||||
answer = data.get('answer', '')
|
||||
|
||||
question_info = get_current_question()
|
||||
if not question_info:
|
||||
return jsonify({"error": "No more questions"})
|
||||
|
||||
question_data, current_q_index = question_info
|
||||
correct = answer == question_data['correct_answer']
|
||||
|
||||
if correct:
|
||||
session['current_question'] = current_q_index + 1
|
||||
session['score'] = PRIZE_LEVELS[current_q_index] if current_q_index < len(PRIZE_LEVELS) else session.get('score', 0)
|
||||
|
||||
# Check if game is won (15th question answered correctly)
|
||||
game_won = session['current_question'] >= min(15, len(session.get('questions', [])))
|
||||
|
||||
return jsonify({
|
||||
"correct": True,
|
||||
"correct_answer": question_data['correct_answer'],
|
||||
"final_score": session['score'],
|
||||
"game_over": game_won
|
||||
})
|
||||
else:
|
||||
# Game over with last guaranteed prize
|
||||
final_score = calculate_guaranteed_prize(current_q_index)
|
||||
|
||||
return jsonify({
|
||||
"correct": False,
|
||||
"correct_answer": question_data['correct_answer'],
|
||||
"final_score": final_score,
|
||||
"game_over": True
|
||||
})
|
||||
```
|
||||
|
||||
Notice the helper functions:
|
||||
- [get_current_question()](file:///Users/home/YandexDisk/TECHNOLYCEUM/ict_repos/ai6-m2/app.py#L20-L28) - Gets the current question data from session
|
||||
- [calculate_guaranteed_prize()](file:///Users/home/YandexDisk/TECHNOLYCEUM/ict_repos/ai6-m2/app.py#L30-L37) - Calculates prize based on guaranteed levels
|
||||
|
||||
📋 LESSON 5-6: LIFELINES & REFACTORING
|
||||
|
||||
Step 6: Review Lifeline Implementation (15 minutes)
|
||||
Check the [use_lifeline](file:///Users/home/YandexDisk/TECHNOLYCEUM/ict_repos/ai6-m2/app.py#L105-L133) function (around line 105):
|
||||
|
||||
```python
|
||||
@app.route('/lifeline/<lifeline_name>')
|
||||
def use_lifeline(lifeline_name):
|
||||
if lifeline_name != 'fifty_fifty':
|
||||
return jsonify({"error": "Unknown lifeline"})
|
||||
|
||||
if 'fifty_fifty' not in session.get('lifelines', []):
|
||||
return jsonify({"error": "Lifeline already used"})
|
||||
|
||||
question_info = get_current_question()
|
||||
if not question_info:
|
||||
return jsonify({"error": "No current question"})
|
||||
|
||||
# Remove the lifeline from available lifelines
|
||||
session['lifelines'].remove('fifty_fifty')
|
||||
|
||||
question_data, _ = question_info
|
||||
correct_answer = question_data['correct_answer']
|
||||
options = question_data['options']
|
||||
|
||||
# Find indices of wrong answers to remove (we need to remove 2)
|
||||
wrong_indices = [i for i, option in enumerate(options) if option != correct_answer]
|
||||
|
||||
# Randomly select 2 wrong indices to remove
|
||||
indices_to_remove = random.sample(wrong_indices, min(2, len(wrong_indices)))
|
||||
indices_to_remove.sort(reverse=True) # Sort in descending order for safe removal
|
||||
|
||||
return jsonify({
|
||||
"remove_indices": indices_to_remove
|
||||
})
|
||||
```
|
||||
|
||||
Notice the improvements:
|
||||
- Uses list comprehension for finding wrong indices
|
||||
- Uses helper functions to reduce code duplication
|
||||
- Has clear error handling
|
||||
|
||||
## Database Configuration
|
||||
|
||||
The application should connect to the MongoDB database using the following connection string:
|
||||
```python
|
||||
MONGO_URI = "mongodb://ai6s3:Student123!@localhost:27017/student_db"
|
||||
```
|
||||
|
||||
This connection string should be set in the application's configuration file or environment variables.
|
||||
|
||||
✅ DIMA'S COMPLETION CHECKLIST
|
||||
☐ Understand the prize system structure
|
||||
☐ Review game session initialization
|
||||
☐ Understand question retrieval logic
|
||||
☐ Review answer validation process
|
||||
☐ Understand lifeline implementation
|
||||
☐ Recognize the use of helper functions for DRY code
|
||||
☐ All code pushed to your branch
|
||||
☐ Created Pull Request for teacher to review
|
||||
|
||||
🎉 Congratulations Dima! You built the entire game backend!
|
||||
100
quiz_game/docs/roles/database-designer-danil.md
Normal file
100
quiz_game/docs/roles/database-designer-danil.md
Normal file
@@ -0,0 +1,100 @@
|
||||
DANIL - DATABASE DESIGNER MISSION
|
||||
Your Role: Question Master | Your File: questions.json
|
||||
|
||||
💡 What You're Building: You're creating all the quiz questions about Russian culture!
|
||||
|
||||
📋 LESSON 1-2: SETUP & BASIC QUESTIONS
|
||||
|
||||
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 danil-database-work
|
||||
|
||||
Step 2: Review the Question Format (10 minutes)
|
||||
Open questions.json and look at the example:
|
||||
|
||||
```json
|
||||
[
|
||||
{
|
||||
"question": "What is the capital of Russia?",
|
||||
"options": ["St. Petersburg", "Moscow", "Kazan", "Sochi"],
|
||||
"correct_answer": "Moscow"
|
||||
},
|
||||
{
|
||||
"question": "Which Russian author wrote 'War and Peace'?",
|
||||
"options": ["Dostoevsky", "Tolstoy", "Pushkin", "Chekhov"],
|
||||
"correct_answer": "Tolstoy"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
Each question needs:
|
||||
- question: The actual question text
|
||||
- options: 4 possible answers (A, B, C, D)
|
||||
- correct_answer: The right answer (must match exactly one of the options)
|
||||
|
||||
Step 3: Understand the Current Implementation (15 minutes)
|
||||
Notice that the current implementation:
|
||||
- Has properly formatted JSON (no comments)
|
||||
- Has 5 sample questions about Russian culture
|
||||
- Follows the correct structure for integration with the backend
|
||||
|
||||
📋 LESSON 3-4: EXPANDING THE DATABASE
|
||||
|
||||
Step 4: Add More Questions (30 minutes)
|
||||
Add at least 10 more questions to reach a total of 15. Here are some examples:
|
||||
|
||||
```json
|
||||
{
|
||||
"question": "What is the traditional Russian soup made with beets?",
|
||||
"options": ["Shchi", "Borscht", "Solyanka", "Ukha"],
|
||||
"correct_answer": "Borscht"
|
||||
},
|
||||
{
|
||||
"question": "Which Russian ruler was known as 'The Terrible'?",
|
||||
"options": ["Peter I", "Catherine II", "Ivan IV", "Nicholas II"],
|
||||
"correct_answer": "Ivan IV"
|
||||
},
|
||||
{
|
||||
"question": "What is the name of the famous Russian ballet company?",
|
||||
"options": ["Moscow Ballet", "St. Petersburg Ballet", "Bolshoi Ballet", "Russian National Ballet"],
|
||||
"correct_answer": "Bolshoi Ballet"
|
||||
}
|
||||
```
|
||||
|
||||
Requirements for new questions:
|
||||
- Make sure questions cover different aspects of Russian culture (history, literature, food, arts, geography)
|
||||
- Ensure plausible wrong answers that are not obviously incorrect
|
||||
- Verify that the correct_answer exactly matches one of the options
|
||||
|
||||
## MongoDB Connection Instructions
|
||||
|
||||
To connect to the MongoDB database:
|
||||
- URL: `mongodb://ai6s3:Student123!@localhost:27017/student_db`
|
||||
- Username: `ai6s3`
|
||||
- Password: `Student123!`
|
||||
- Database: `student_db`
|
||||
|
||||
To import your JSON data:
|
||||
1. Save your JSON data in a file named `data.json`
|
||||
2. Run the following command in terminal:
|
||||
```bash
|
||||
mongoimport --uri="mongodb://ai6s3:Student123!@localhost:27017/student_db" --collection=questions --type=json --file=data.json --jsonArray
|
||||
```
|
||||
|
||||
Make sure your JSON data format matches the expected schema for the application.
|
||||
|
||||
✅ DANIL'S COMPLETION CHECKLIST
|
||||
☐ Understand the question format
|
||||
☐ Review current implementation
|
||||
☐ Add 10+ more questions about Russian culture
|
||||
☐ Verify all questions follow the correct structure
|
||||
☐ Check that correct_answer matches exactly one option
|
||||
☐ All code pushed to your branch
|
||||
☐ Created Pull Request for teacher to review
|
||||
|
||||
🎉 Congratulations Danil! You built the entire question database!
|
||||
225
quiz_game/docs/roles/frontend-developer-inna.md
Normal file
225
quiz_game/docs/roles/frontend-developer-inna.md
Normal file
@@ -0,0 +1,225 @@
|
||||
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: Review Question Loading (15 minutes)
|
||||
Open static/script.js and look at the [loadQuestion](file:///Users/home/YandexDisk/TECHNOLYCEUM/ict_repos/ai6-m2/static/script.js#L9-L19) function:
|
||||
|
||||
```javascript
|
||||
function loadQuestion() {
|
||||
apiRequest('/get_question')
|
||||
.then(data => {
|
||||
if (data.game_over) {
|
||||
endGame(data.final_score);
|
||||
return;
|
||||
}
|
||||
|
||||
currentQuestion = data;
|
||||
displayQuestion(data);
|
||||
})
|
||||
.catch(error => console.error('Error:', error));
|
||||
}
|
||||
```
|
||||
|
||||
Notice how it uses the [apiRequest](file:///Users/home/YandexDisk/TECHNOLYCEUM/ict_repos/ai6-m2/static/script.js#L5-L12) utility function for cleaner code.
|
||||
|
||||
Step 3: Review Question Display (15 minutes)
|
||||
Look at the [displayQuestion](file:///Users/home/YandexDisk/TECHNOLYCEUM/ict_repos/ai6-m2/static/script.js#L21-L41) function:
|
||||
|
||||
```javascript
|
||||
function displayQuestion(data) {
|
||||
updateElementText('q-number', data.question_number);
|
||||
updateElementText('question-text', data.question);
|
||||
updateElementText('prize', data.current_prize);
|
||||
|
||||
const optionsContainer = document.getElementById('options');
|
||||
optionsContainer.innerHTML = '';
|
||||
|
||||
data.options.forEach((option, index) => {
|
||||
const optionElement = document.createElement('div');
|
||||
optionElement.className = 'option';
|
||||
optionElement.textContent = option;
|
||||
optionElement.onclick = () => selectAnswer(option);
|
||||
optionsContainer.appendChild(optionElement);
|
||||
});
|
||||
|
||||
// Reset result display
|
||||
toggleElementVisibility('result', false);
|
||||
const result = document.getElementById('result');
|
||||
if (result) {
|
||||
result.className = 'result';
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Notice the utility functions:
|
||||
- [updateElementText()](file:///Users/home/YandexDisk/TECHNOLYCEUM/ict_repos/ai6-m2/static/script.js#L14-L19) - Simplifies updating element text
|
||||
- [toggleElementVisibility()](file:///Users/home/YandexDisk/TECHNOLYCEUM/ict_repos/ai6-m2/static/script.js#L21-L27) - Standardizes showing/hiding elements
|
||||
|
||||
📋 LESSON 3-4: ANSWER HANDLING & LIFELINES
|
||||
|
||||
Step 4: Review Answer Selection (15 minutes)
|
||||
Check the [selectAnswer](file:///Users/home/YandexDisk/TECHNOLYCEUM/ict_repos/ai6-m2/static/script.js#L43-L72) function:
|
||||
|
||||
```javascript
|
||||
function selectAnswer(answer) {
|
||||
apiRequest('/answer', {
|
||||
method: 'POST',
|
||||
headers: {'Content-Type': 'application/json'},
|
||||
body: JSON.stringify({ answer: answer })
|
||||
})
|
||||
.then(data => {
|
||||
const result = document.getElementById('result');
|
||||
if (result) {
|
||||
result.style.display = 'block';
|
||||
|
||||
if (data.correct) {
|
||||
result.textContent = 'Correct!';
|
||||
result.className = 'result correct';
|
||||
|
||||
setTimeout(() => {
|
||||
if (data.game_over) {
|
||||
endGame(data.final_score);
|
||||
} else {
|
||||
loadQuestion();
|
||||
}
|
||||
}, 1500);
|
||||
} else {
|
||||
result.textContent = `Wrong! Correct answer: ${data.correct_answer}`;
|
||||
result.className = 'result incorrect';
|
||||
|
||||
setTimeout(() => {
|
||||
endGame(data.final_score);
|
||||
}, 2000);
|
||||
}
|
||||
}
|
||||
})
|
||||
.catch(error => console.error('Error:', error));
|
||||
}
|
||||
```
|
||||
|
||||
Step 5: Review Lifeline Implementation (15 minutes)
|
||||
Look at the [useFiftyFifty](file:///Users/home/YandexDisk/TECHNOLYCEUM/ict_repos/ai6-m2/static/script.js#L74-L100) function:
|
||||
|
||||
```javascript
|
||||
function useFiftyFifty() {
|
||||
const lifelineBtn = document.querySelector('.lifeline');
|
||||
if (lifelineBtn) {
|
||||
lifelineBtn.disabled = true;
|
||||
}
|
||||
|
||||
apiRequest('/lifeline/fifty_fifty')
|
||||
.then(data => {
|
||||
if (data.error) {
|
||||
alert(data.error);
|
||||
if (lifelineBtn) {
|
||||
lifelineBtn.disabled = false;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Hide two wrong options
|
||||
const options = document.querySelectorAll('.option');
|
||||
data.remove_indices.forEach(index => {
|
||||
if (options[index]) {
|
||||
options[index].style.display = 'none';
|
||||
}
|
||||
});
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error:', error);
|
||||
if (lifelineBtn) {
|
||||
lifelineBtn.disabled = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
Notice the improvements:
|
||||
- Uses the [apiRequest](file:///Users/home/YandexDisk/TECHNOLYCEUM/ict_repos/ai6-m2/static/script.js#L5-L12) utility function
|
||||
- Has proper error handling with element checks
|
||||
- Cleaner, more maintainable code
|
||||
|
||||
Step 6: Review Utility Functions (10 minutes)
|
||||
At the top of script.js, notice the utility functions that make the code DRY:
|
||||
|
||||
```javascript
|
||||
// Utility function for making API requests
|
||||
function apiRequest(url, options = {}) {
|
||||
return fetch(url, options)
|
||||
.then(response => response.json())
|
||||
.catch(error => {
|
||||
console.error('Error:', error);
|
||||
throw error;
|
||||
});
|
||||
}
|
||||
|
||||
// Utility function for updating element text content
|
||||
function updateElementText(id, text) {
|
||||
const element = document.getElementById(id);
|
||||
if (element) {
|
||||
element.textContent = text;
|
||||
}
|
||||
}
|
||||
|
||||
// Utility function for showing/hiding elements
|
||||
function toggleElementVisibility(id, show = true) {
|
||||
const element = document.getElementById(id);
|
||||
if (element) {
|
||||
element.style.display = show ? 'block' : 'none';
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
📋 LESSON 5-6: GAME FLOW COMPLETION
|
||||
|
||||
Step 7: Review Game End and Restart (10 minutes)
|
||||
Look at the [endGame](file:///Users/home/YandexDisk/TECHNOLYCEUM/ict_repos/ai6-m2/static/script.js#L102-L108) and [restartGame](file:///Users/home/YandexDisk/TECHNOLYCEUM/ict_repos/ai6-m2/static/script.js#L110-L112) functions:
|
||||
|
||||
```javascript
|
||||
function endGame(score) {
|
||||
updateElementText('final-prize', score);
|
||||
toggleElementVisibility('game-over', true);
|
||||
toggleElementVisibility('question-box', false);
|
||||
toggleElementVisibility('lifeline', false);
|
||||
}
|
||||
|
||||
function restartGame() {
|
||||
window.location.href = '/start';
|
||||
}
|
||||
```
|
||||
|
||||
Notice how they use the utility functions to simplify the code.
|
||||
|
||||
✅ INNA'S COMPLETION CHECKLIST
|
||||
☐ Review question loading implementation
|
||||
☐ Understand question display logic
|
||||
☐ Review answer handling process
|
||||
☐ Understand lifeline implementation
|
||||
☐ Recognize utility functions for DRY code
|
||||
☐ Review game flow completion
|
||||
☐ All code pushed to your branch
|
||||
☐ Created Pull Request for teacher to review
|
||||
|
||||
## Connection Requirements
|
||||
|
||||
The frontend communicates with the backend API, which must be properly configured with the MongoDB connection string:
|
||||
```python
|
||||
MONGO_URI = "mongodb://ai6s3:Student123!@localhost:27017/student_db"
|
||||
```
|
||||
|
||||
Ensure the backend developer has correctly configured this connection string in the application's configuration.
|
||||
|
||||
🎉 Congratulations Inna! You built the entire game interface!
|
||||
319
quiz_game/docs/roles/graphics-designer-artyom.md
Normal file
319
quiz_game/docs/roles/graphics-designer-artyom.md
Normal file
@@ -0,0 +1,319 @@
|
||||
ARTYOM - GRAPHICS DESIGNER MISSION
|
||||
Your Role: Visual Designer | Your File: static/style.css
|
||||
|
||||
💡 What You're Building: You're making the game look amazing with Russian themes!
|
||||
|
||||
📋 LESSON 1-2: SETUP & RUSSIAN COLOR THEME
|
||||
|
||||
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 artyom-graphics-work
|
||||
|
||||
Step 2: Enhance the Russian Color Theme (30 minutes)
|
||||
Open static/style.css and find the body section.
|
||||
|
||||
DELETE these lines:
|
||||
|
||||
body {
|
||||
background: #1a2a6c;
|
||||
color: white;
|
||||
min-height: 100vh;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
TYPE THIS instead:
|
||||
|
||||
body {
|
||||
background: linear-gradient(135deg, #1a2a6c, #b21f1f, #fdbb2d);
|
||||
color: white;
|
||||
min-height: 100vh;
|
||||
padding: 20px;
|
||||
font-family: 'Arial', 'Helvetica', sans-serif;
|
||||
}
|
||||
|
||||
Step 3: Make the Header Look Russian (20 minutes)
|
||||
Find the header section.
|
||||
|
||||
DELETE these lines:
|
||||
|
||||
header {
|
||||
text-align: center;
|
||||
margin-bottom: 20px;
|
||||
padding: 15px;
|
||||
background: #b21f1f;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
TYPE THIS instead:
|
||||
|
||||
/* Keep container styling from current implementation */
|
||||
.container {
|
||||
background: rgba(255, 255, 255, 0.9);
|
||||
color: #333;
|
||||
padding: 20px;
|
||||
border-radius: 10px;
|
||||
box-shadow: 0 2px 5px rgba(0,0,0,0.1);
|
||||
margin: 15px 0;
|
||||
}
|
||||
|
||||
h1 {
|
||||
color: #1a237e;
|
||||
text-align: center;
|
||||
font-size: 2.5rem;
|
||||
margin: 20px 0;
|
||||
}
|
||||
|
||||
Save and push:
|
||||
git add static/style.css
|
||||
git commit -m "feat: enhanced Russian color theme"
|
||||
git push origin artyom-graphics-work
|
||||
|
||||
📋 LESSON 3-4: GAME ELEMENTS STYLING
|
||||
|
||||
Step 4: Style the Question Container (25 minutes)
|
||||
Find the question-container section.
|
||||
|
||||
DELETE these lines:
|
||||
|
||||
.question-box {
|
||||
background: rgba(255, 255, 255, 0.9);
|
||||
color: #333;
|
||||
padding: 15px;
|
||||
border-radius: 8px;
|
||||
margin: 15px 0;
|
||||
box-shadow: 0 2px 5px rgba(0,0,0,0.2);
|
||||
}
|
||||
|
||||
.question {
|
||||
font-size: 1.4rem;
|
||||
margin-bottom: 15px;
|
||||
text-align: center;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
TYPE THIS instead:
|
||||
|
||||
.question-container {
|
||||
background: rgba(255, 255, 255, 0.15);
|
||||
padding: 25px;
|
||||
border-radius: 15px;
|
||||
margin-bottom: 25px;
|
||||
border: 1px solid rgba(253, 187, 45, 0.3);
|
||||
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.2);
|
||||
backdrop-filter: blur(10px);
|
||||
}
|
||||
|
||||
.question {
|
||||
font-size: 1.4rem;
|
||||
margin-bottom: 25px;
|
||||
text-align: center;
|
||||
font-weight: bold;
|
||||
color: #fdbb2d;
|
||||
text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
|
||||
.question-number {
|
||||
color: #fdbb2d;
|
||||
font-size: 1.1rem;
|
||||
margin-bottom: 15px;
|
||||
text-align: center;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
Step 5: Make Answer Buttons Beautiful (25 minutes)
|
||||
Find the option styling.
|
||||
|
||||
DELETE these lines:
|
||||
|
||||
.option {
|
||||
background: #2196f3;
|
||||
color: white;
|
||||
padding: 12px;
|
||||
border-radius: 5px;
|
||||
cursor: pointer;
|
||||
text-align: center;
|
||||
margin: 5px 0;
|
||||
transition: background 0.3s;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.option:hover {
|
||||
background: #1976d2;
|
||||
}
|
||||
|
||||
.option.correct {
|
||||
background: #4caf50;
|
||||
}
|
||||
|
||||
.option.wrong {
|
||||
background: #f44336;
|
||||
}
|
||||
|
||||
TYPE THIS instead:
|
||||
|
||||
.option {
|
||||
background: linear-gradient(135deg, #fdbb2d, #e6a923);
|
||||
color: #1a2a6c;
|
||||
padding: 18px;
|
||||
border-radius: 10px;
|
||||
cursor: pointer;
|
||||
text-align: center;
|
||||
font-weight: bold;
|
||||
border: 2px solid #1a2a6c;
|
||||
transition: all 0.3s ease;
|
||||
font-size: 1.1rem;
|
||||
box-shadow: 0 3px 8px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
.option:hover {
|
||||
background: linear-gradient(135deg, #e6a923, #fdbb2d);
|
||||
transform: translateY(-3px);
|
||||
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
.option:active {
|
||||
transform: translateY(1px);
|
||||
}
|
||||
|
||||
Save and push:
|
||||
git add static/style.css
|
||||
git commit -m "feat: enhanced question and option styling"
|
||||
git push origin artyom-graphics-work
|
||||
|
||||
📋 LESSON 5-6: LIFELINES & FINAL TOUCHES
|
||||
|
||||
Step 6: Style Lifelines and Game Over Screen (40 minutes)
|
||||
Find the lifelines section.
|
||||
|
||||
DELETE these lines:
|
||||
|
||||
.lifelines {
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
padding: 15px;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.lifeline-buttons {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.lifeline-btn {
|
||||
background: #1a2a6c;
|
||||
color: white;
|
||||
border: none;
|
||||
padding: 10px 15px;
|
||||
border-radius: 5px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
TYPE THIS instead:
|
||||
|
||||
.result.correct {
|
||||
background: #c8e6c9;
|
||||
color: #2e7d32;
|
||||
padding: 10px;
|
||||
border-radius: 5px;
|
||||
margin: 10px 0;
|
||||
}
|
||||
|
||||
.result.incorrect {
|
||||
background: #ffcdd2;
|
||||
color: #c62828;
|
||||
padding: 10px;
|
||||
border-radius: 5px;
|
||||
margin: 10px 0;
|
||||
}
|
||||
|
||||
.lifeline {
|
||||
background: #ff9800;
|
||||
color: white;
|
||||
border: none;
|
||||
padding: 12px 20px;
|
||||
border-radius: 5px;
|
||||
cursor: pointer;
|
||||
display: block;
|
||||
margin: 15px auto;
|
||||
font-weight: bold;
|
||||
transition: background 0.3s;
|
||||
}
|
||||
|
||||
.lifeline:hover {
|
||||
background: #f57c00;
|
||||
}
|
||||
|
||||
.lifeline:disabled {
|
||||
background: #ccc;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
Step 7: Make Game Over Screen Epic (20 minutes)
|
||||
Find the game-over-screen section.
|
||||
|
||||
DELETE these lines:
|
||||
|
||||
.game-over-screen {
|
||||
text-align: center;
|
||||
padding: 30px;
|
||||
}
|
||||
|
||||
TYPE THIS instead:
|
||||
|
||||
.game-over-screen {
|
||||
text-align: center;
|
||||
padding: 30px;
|
||||
background: white;
|
||||
border-radius: 10px;
|
||||
box-shadow: 0 2px 5px rgba(0,0,0,0.1);
|
||||
margin: 15px 0;
|
||||
}
|
||||
|
||||
.game-over-screen h2 {
|
||||
color: #d32f2f;
|
||||
font-size: 2rem;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.game-over-screen p {
|
||||
font-size: 1.2rem;
|
||||
margin-bottom: 20px;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.game-over-screen button {
|
||||
background: #d32f2f;
|
||||
color: white;
|
||||
border: none;
|
||||
padding: 12px 24px;
|
||||
border-radius: 5px;
|
||||
font-size: 1rem;
|
||||
cursor: pointer;
|
||||
transition: background 0.3s;
|
||||
}
|
||||
|
||||
.game-over-screen button:hover {
|
||||
background: #b71c1c;
|
||||
}
|
||||
|
||||
Final push:
|
||||
git add static/style.css
|
||||
git commit -m "feat: completed Russian-themed visual design"
|
||||
git push origin artyom-graphics-work
|
||||
|
||||
✅ ARTYOM'S COMPLETION CHECKLIST
|
||||
☐ Russian flag colors used throughout (white, blue, red, gold)
|
||||
☐ Gradient backgrounds look professional
|
||||
☐ Buttons have hover effects and animations
|
||||
☐ Game elements have shadows and borders
|
||||
☐ Text is readable with good contrast
|
||||
☐ Game over screen looks exciting
|
||||
☐ All code pushed to your branch
|
||||
☐ Created Pull Request for teacher to review
|
||||
|
||||
🎉 Congratulations Artyom! You made the game look amazing!
|
||||
262
quiz_game/docs/technical-specs/teacher-project-guide.md
Normal file
262
quiz_game/docs/technical-specs/teacher-project-guide.md
Normal file
@@ -0,0 +1,262 @@
|
||||
# Teacher - Complete Project Manager Guide
|
||||
|
||||
## YOUR ROLES:
|
||||
- Team Lead - Guide students through development
|
||||
- Git Master - Manage repositories and merges
|
||||
- User Tester - Verify all components work
|
||||
- Integration Manager - Combine all student work
|
||||
|
||||
## PROJECT TIMELINE (6 Lessons)
|
||||
|
||||
=========================================
|
||||
|
||||
## LESSON 1-2: SETUP & FOUNDATION
|
||||
=========================================
|
||||
|
||||
### STUDENT GOALS:
|
||||
- Dima: Implement prize money system and game logic in app.py
|
||||
- Danil: Create first 5 Russian culture questions
|
||||
- Inna: Make basic question loading and display work
|
||||
- Artyom: Start Russian color theme in CSS
|
||||
|
||||
### TEACHER TASKS:
|
||||
|
||||
✅ Setup Verification:
|
||||
1. Ensure main repo is ready:
|
||||
https://gitea.techshare.cc/technolyceum/ai6-m2
|
||||
|
||||
2. Verify all students have:
|
||||
- Forked the repository
|
||||
- Created their role-specific branch
|
||||
- Made first commit
|
||||
|
||||
3. Quick Progress Check (Terminal):
|
||||
```bash
|
||||
# Check each student's fork manually in Gitea web interface
|
||||
# Look for 4 branches:
|
||||
# - dima-backend-work
|
||||
# - inna-frontend-work
|
||||
# - danil-database-work
|
||||
# - artyom-graphics-work
|
||||
```
|
||||
|
||||
✅ Individual Progress Checks:
|
||||
```bash
|
||||
# Temporary check for each student:
|
||||
git clone [STUDENT-FORK-URL] temp-check
|
||||
cd temp-check
|
||||
git checkout [THEIR-BRANCH]
|
||||
|
||||
# Dima Check:
|
||||
grep -A 15 "PRIZE_LEVELS" app.py
|
||||
|
||||
# Danil Check:
|
||||
python3 -c "import json; print('Questions:', len(json.load(open('questions.json'))))"
|
||||
|
||||
# Inna Check:
|
||||
grep -c "function" static/script.js
|
||||
|
||||
# Artyom Check:
|
||||
grep -c "background" static/style.css
|
||||
|
||||
cd ..
|
||||
rm -rf temp-check
|
||||
```
|
||||
|
||||
=========================================
|
||||
|
||||
## LESSON 3-4: CORE DEVELOPMENT
|
||||
=========================================
|
||||
|
||||
### STUDENT GOALS:
|
||||
- Dima: Complete game session management and answer validation
|
||||
- Danil: 10+ questions completed
|
||||
- Inna: Answer handling system and lifelines
|
||||
- Artyom: Enhanced question/option styling
|
||||
|
||||
### TEACHER TASKS:
|
||||
|
||||
✅ Code Review Workshop:
|
||||
Show examples of DRY (Don't Repeat Yourself) principles:
|
||||
|
||||
**Before (repetitive code):**
|
||||
```javascript
|
||||
document.getElementById('q-number').textContent = data.question_number;
|
||||
document.getElementById('question-text').textContent = data.question;
|
||||
document.getElementById('prize').textContent = data.current_prize;
|
||||
```
|
||||
|
||||
**After (DRY code with utility functions):**
|
||||
```javascript
|
||||
updateElementText('q-number', data.question_number);
|
||||
updateElementText('question-text', data.question);
|
||||
updateElementText('prize', data.current_prize);
|
||||
```
|
||||
|
||||
✅ Git Workshop:
|
||||
```bash
|
||||
# Help students resolve merge conflicts:
|
||||
git fetch origin
|
||||
git checkout main
|
||||
git pull origin main
|
||||
git checkout [THEIR-BRANCH]
|
||||
git merge main
|
||||
|
||||
# If conflicts occur:
|
||||
# 1. Edit conflicted files
|
||||
# 2. Remove conflict markers
|
||||
# 3. git add .
|
||||
# 4. git commit
|
||||
```
|
||||
|
||||
=========================================
|
||||
|
||||
## LESSON 5-6: INTEGRATION & TESTING
|
||||
=========================================
|
||||
|
||||
### STUDENT GOALS:
|
||||
- Dima: Finalize lifelines and error handling
|
||||
- Danil: Complete 15 questions with difficulty progression
|
||||
- Inna: Complete game flow and end game screens
|
||||
- Artyom: Polish all visual elements and animations
|
||||
|
||||
### FINAL INTEGRATION:
|
||||
|
||||
✅ Integration Steps:
|
||||
1. Merge all branches to main:
|
||||
```bash
|
||||
# On main branch:
|
||||
git merge dima-backend-work
|
||||
git merge danil-database-work
|
||||
git merge inna-frontend-work
|
||||
git merge artyom-graphics-work
|
||||
```
|
||||
|
||||
2. Resolve any conflicts
|
||||
|
||||
3. Test complete game flow:
|
||||
- Start game from index.html
|
||||
- Play through all questions
|
||||
- Test lifelines
|
||||
- Verify scoring system
|
||||
- Check end game states
|
||||
|
||||
✅ Final Testing Checklist:
|
||||
- [ ] All 15 questions load correctly
|
||||
- [ ] Answer validation works
|
||||
- [ ] Scoring system functions properly
|
||||
- [ ] Lifelines function correctly
|
||||
- [ ] Game over states work (win/lose)
|
||||
- [ ] Restart functionality works
|
||||
- [ ] Responsive design on different screens
|
||||
- [ ] No console errors in browser
|
||||
|
||||
=========================================
|
||||
|
||||
## PROJECT ARCHITECTURE OVERVIEW
|
||||
=========================================
|
||||
|
||||
### File Structure:
|
||||
```
|
||||
/ai6-m2
|
||||
├── app.py # Flask backend (Dima)
|
||||
├── questions.json # Question database (Danil)
|
||||
├── static/
|
||||
│ ├── script.js # Frontend logic (Inna)
|
||||
│ └── style.css # Styling (Artyom)
|
||||
├── templates/
|
||||
│ ├── index.html # Landing page
|
||||
│ └── game.html # Game interface
|
||||
├── docs/
|
||||
│ ├── roles/ # Role-specific instructions
|
||||
│ └── technical-specs/ # Technical documentation
|
||||
└── README.md # Project overview
|
||||
```
|
||||
|
||||
### Technical Implementation:
|
||||
|
||||
**Backend (app.py):**
|
||||
- Flask routes for game operations
|
||||
- Session management for game state
|
||||
- JSON data handling for questions
|
||||
- Helper functions for DRY code
|
||||
|
||||
**Frontend (script.js):**
|
||||
- API communication with backend
|
||||
- DOM manipulation for game interface
|
||||
- Utility functions for common operations
|
||||
- Event handling for user interactions
|
||||
|
||||
**Database (questions.json):**
|
||||
- JSON format for easy parsing
|
||||
- Structured question data with options
|
||||
- Correct answer validation
|
||||
|
||||
**Styling (style.css):**
|
||||
- Responsive design principles
|
||||
- Russian-themed color scheme
|
||||
- Component-based styling approach
|
||||
|
||||
=========================================
|
||||
|
||||
## TROUBLESHOOTING GUIDE
|
||||
=========================================
|
||||
|
||||
### Common Issues and Solutions:
|
||||
|
||||
1. **"TypeError: Cannot read properties of undefined"**
|
||||
- Usually caused by API returning error instead of data
|
||||
- Solution: Check backend implementation and JSON formatting
|
||||
|
||||
2. **Lifelines not working**
|
||||
- Check session management for lifeline state
|
||||
- Verify frontend-backend communication
|
||||
|
||||
3. **Scoring issues**
|
||||
- Verify prize structure in backend
|
||||
- Check guaranteed level calculations
|
||||
|
||||
4. **Git merge conflicts**
|
||||
- Use systematic approach to resolve conflicts
|
||||
- Communicate with team members about changes
|
||||
|
||||
### Verification Commands:
|
||||
|
||||
```bash
|
||||
# Run the application
|
||||
export FLASK_APP=app.py
|
||||
python -m flask run
|
||||
|
||||
# Check for syntax errors
|
||||
python -m py_compile app.py
|
||||
npx eslint static/script.js
|
||||
|
||||
# Validate JSON
|
||||
python -m json.tool questions.json
|
||||
```
|
||||
|
||||
=========================================
|
||||
|
||||
## ASSESSMENT CRITERIA
|
||||
=========================================
|
||||
|
||||
### Technical Skills:
|
||||
- Code quality and organization (20%)
|
||||
- Implementation of requirements (30%)
|
||||
- Problem-solving and debugging (20%)
|
||||
- Git usage and collaboration (15%)
|
||||
- Documentation and comments (15%)
|
||||
|
||||
### Collaboration:
|
||||
- Team communication
|
||||
- Code review participation
|
||||
- Helpfulness to teammates
|
||||
- Integration contribution
|
||||
|
||||
### Final Product:
|
||||
- Game functions without errors
|
||||
- All features implemented
|
||||
- Visually appealing interface
|
||||
- Good user experience
|
||||
|
||||
🎉 Congratulations on completing the Russian Millionaire Quiz Game project!
|
||||
36
quiz_game/gitea passwords.rtf
Normal file
36
quiz_game/gitea passwords.rtf
Normal file
@@ -0,0 +1,36 @@
|
||||
{\rtf1\ansi\ansicpg1252\cocoartf2818
|
||||
\cocoatextscaling0\cocoaplatform0{\fonttbl\f0\fnil\fcharset0 .SFNS-Regular_wdth_opsz110000_GRAD_wght2580000;}
|
||||
{\colortbl;\red255\green255\blue255;\red19\green21\blue25;\red255\green255\blue255;}
|
||||
{\*\expandedcolortbl;;\cssrgb\c9412\c10980\c12941;\cssrgb\c100000\c100000\c100000;}
|
||||
\paperw11900\paperh16840\margl1440\margr1440\vieww11900\viewh14080\viewkind1
|
||||
\deftab720
|
||||
\pard\pardeftab720\partightenfactor0
|
||||
|
||||
\f0\b\fs32 \cf2 \cb3 \expnd0\expndtw0\kerning0
|
||||
Inna\
|
||||
ai6s4\
|
||||
ai6s4@ict.ru\
|
||||
\pard\pardeftab720\partightenfactor0
|
||||
\cf2 Passwords: Student123!\
|
||||
\
|
||||
\cf2 \
|
||||
\pard\pardeftab720\partightenfactor0
|
||||
\cf2 Daniel\
|
||||
ai6s3\
|
||||
ai6s3@ict.ru\
|
||||
\pard\pardeftab720\partightenfactor0
|
||||
\cf2 Passwords: Student123!\cf2 \
|
||||
\pard\pardeftab720\partightenfactor0
|
||||
\cf2 \
|
||||
\
|
||||
Artyom\
|
||||
ai6s2\
|
||||
ai6s2@ict.ru\
|
||||
\pard\pardeftab720\partightenfactor0
|
||||
\cf2 Passwords: Student123!\cf2 \
|
||||
\pard\pardeftab720\partightenfactor0
|
||||
\cf2 \
|
||||
Dima\
|
||||
ai6s1\
|
||||
ai6s1@ict.ru\
|
||||
Passwords: Student123!}
|
||||
27
quiz_game/questions.json
Normal file
27
quiz_game/questions.json
Normal file
@@ -0,0 +1,27 @@
|
||||
[
|
||||
{
|
||||
"question": "What is the capital of Russia?",
|
||||
"options": ["St. Petersburg", "Moscow", "Kazan", "Sochi"],
|
||||
"correct_answer": "Moscow"
|
||||
},
|
||||
{
|
||||
"question": "Which Russian author wrote 'War and Peace'?",
|
||||
"options": ["Dostoevsky", "Tolstoy", "Pushkin", "Chekhov"],
|
||||
"correct_answer": "Tolstoy"
|
||||
},
|
||||
{
|
||||
"question": "What is the traditional Russian soup made with beets?",
|
||||
"options": ["Shchi", "Borscht", "Solyanka", "Ukha"],
|
||||
"correct_answer": "Borscht"
|
||||
},
|
||||
{
|
||||
"question": "Which Russian ruler was known as 'The Terrible'?",
|
||||
"options": ["Peter I", "Catherine II", "Ivan IV", "Nicholas II"],
|
||||
"correct_answer": "Ivan IV"
|
||||
},
|
||||
{
|
||||
"question": "What is the name of the famous Russian ballet company?",
|
||||
"options": ["Moscow Ballet", "St. Petersburg Ballet", "Bolshoi Ballet", "Russian National Ballet"],
|
||||
"correct_answer": "Bolshoi Ballet"
|
||||
}
|
||||
]
|
||||
2
quiz_game/requirements.txt
Normal file
2
quiz_game/requirements.txt
Normal file
@@ -0,0 +1,2 @@
|
||||
# requirements.txt
|
||||
Flask==2.3.3
|
||||
5
quiz_game/starter_templates/app.py
Normal file
5
quiz_game/starter_templates/app.py
Normal file
@@ -0,0 +1,5 @@
|
||||
// 1. This file should contain the main application logic
|
||||
// TODO: Implement Flask app setup
|
||||
// TODO: Connect to MongoDB database
|
||||
// TODO: Implement game state management
|
||||
// TODO: Create API endpoints for game functionality
|
||||
5
quiz_game/starter_templates/docs/README.md
Normal file
5
quiz_game/starter_templates/docs/README.md
Normal file
@@ -0,0 +1,5 @@
|
||||
// 1. This file should contain project structure documentation
|
||||
// TODO: Describe directory structure
|
||||
// TODO: Document file naming conventions
|
||||
// TODO: Specify documentation standards
|
||||
// TODO: Add contribution guidelines
|
||||
@@ -0,0 +1,55 @@
|
||||
// 1. This file should contain backend API documentation
|
||||
// TODO: Import Flask and PyMongo (line 1-2)
|
||||
from flask import Flask, session, redirect, url_for, request, jsonify
|
||||
from flask_pymongo import PyMongo
|
||||
|
||||
// TODO: Connect to MongoDB database (line 4-6)
|
||||
app = Flask(__name__)
|
||||
app.config['MONGO_URI'] = 'mongodb://localhost:27017/student_db'
|
||||
mongo = PyMongo(app)
|
||||
|
||||
// TODO: Define API endpoint for getting questions (line 8-10)
|
||||
@app.route('/get_question')
|
||||
def get_question():
|
||||
question_num = session.get('current_question', 0)
|
||||
question = mongo.db.questions.find_one({"question_number": question_num})
|
||||
|
||||
if question:
|
||||
return jsonify({
|
||||
"question": question['question'],
|
||||
"options": question['options'],
|
||||
"question_number": question_num,
|
||||
"current_prize": calculate_prize(question_num)
|
||||
})
|
||||
else:
|
||||
return jsonify({"game_over": True, "final_score": calculate_final_score()})
|
||||
|
||||
// TODO: Define API endpoint for submitting answers (line 12-14)
|
||||
@app.route('/answer', methods=['POST'])
|
||||
def answer_question():
|
||||
user_answer = request.json.get('answer')
|
||||
question_num = session.get('current_question', 0)
|
||||
current_question = mongo.db.questions.find_one({"question_number": question_num})
|
||||
|
||||
is_correct = current_question['options'][current_question['correct_answer']] == user_answer
|
||||
|
||||
if is_correct:
|
||||
session['current_question'] = question_num + 1
|
||||
return jsonify({
|
||||
"correct": True,
|
||||
"correct_answer": current_question['correct_answer'],
|
||||
"game_over": question_num + 1 >= TOTAL_QUESTIONS
|
||||
})
|
||||
else:
|
||||
return jsonify({
|
||||
"correct": False,
|
||||
"correct_answer": current_question['correct_answer'],
|
||||
"game_over": True
|
||||
})
|
||||
|
||||
// TODO: Add error handling for database connection (line 16-18)
|
||||
try:
|
||||
mongo.db.command("ping")
|
||||
print("Successfully connected to MongoDB!")
|
||||
except Exception as e:
|
||||
print(f"MongoDB connection error: {e}")
|
||||
@@ -0,0 +1,45 @@
|
||||
// 1. This file should contain database connection information
|
||||
// TODO: Import MongoDB driver (line 1)
|
||||
import pymongo
|
||||
|
||||
// TODO: Connect to MongoDB using the connection URI (line 3-5)
|
||||
client = pymongo.MongoClient("mongodb://localhost:27017/")
|
||||
|
||||
// TODO: Select the appropriate database (line 7)
|
||||
db = client["student_db"]
|
||||
|
||||
// TODO: Select the questions collection (line 9)
|
||||
questions_collection = db["questions"]
|
||||
|
||||
// TODO: Add error handling for database connection (line 11)
|
||||
try:
|
||||
client.admin.command('ping')
|
||||
print("Successfully connected to MongoDB!")
|
||||
except Exception as e:
|
||||
print(f"MongoDB connection error: {e}")
|
||||
|
||||
// 2. Database population instructions (new section)
|
||||
// TODO: Create function to insert questions into database (line 13-25)
|
||||
def insert_questions():
|
||||
questions = [
|
||||
{
|
||||
"question_number": 0,
|
||||
"question": "What is the capital of Russia?",
|
||||
"options": ["Moscow", "Saint Petersburg", "Novosibirsk", "Yekaterinburg"],
|
||||
"correct_answer": 0
|
||||
},
|
||||
{
|
||||
"question_number": 1,
|
||||
"question": "Which river is the longest in Russia?",
|
||||
"options": ["Volga", "Yenisey", "Ob", "Amur"],
|
||||
"correct_answer": 1
|
||||
}
|
||||
]
|
||||
|
||||
# Insert questions into collection
|
||||
db.questions.insert_many(questions)
|
||||
print("Questions inserted successfully!")
|
||||
|
||||
// TODO: Call insert_questions function (line 27)
|
||||
if __name__ == "__main__"::
|
||||
insert_questions()
|
||||
@@ -0,0 +1,46 @@
|
||||
// 1. This file should contain frontend implementation instructions
|
||||
|
||||
// TODO: Create HTML structure with game container (line 1-5)
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Russian Quiz</title>
|
||||
</head>
|
||||
|
||||
// TODO: Add question display elements (line 7-10)
|
||||
<body>
|
||||
<div class="container">
|
||||
<h1>Russian Quiz</h1>
|
||||
<div class="score">Prize: <span id="prize">0</span> ₽</div>
|
||||
|
||||
<div class="question-box">
|
||||
<div class="question-number">Question <span id="q-number">1</span>/5</div>
|
||||
<div class="question" id="question-text">Loading...</div>
|
||||
|
||||
<div class="options" id="options">
|
||||
<!-- Options go here -->
|
||||
</div>
|
||||
|
||||
<div class="result" id="result"></div>
|
||||
</div>
|
||||
|
||||
// TODO: Create answer option buttons (line 12-15)
|
||||
<div class="options" id="options">
|
||||
<!-- Options will be dynamically inserted here -->
|
||||
</div>
|
||||
|
||||
<button class="lifeline" onclick="useFiftyFifty()">50:50 Lifeline</button>
|
||||
|
||||
// TODO: Implement game controls and lifelines (line 17-20)
|
||||
<div class="game-over" id="game-over" style="display: none;">
|
||||
<h2>Game Over!</h2>
|
||||
<p>You won: <span id="final-prize">0</span> ₽</p>
|
||||
<button onclick="restartGame()">Play Again</button>
|
||||
</div>
|
||||
|
||||
<script src="{{ url_for('static', filename='script.js') }}"></script>
|
||||
</body>
|
||||
|
||||
// TODO: Add game over screen UI (line 22-25)
|
||||
// Game over screen is already included above as part of the main structure
|
||||
5
quiz_game/starter_templates/static/script.js
Normal file
5
quiz_game/starter_templates/static/script.js
Normal file
@@ -0,0 +1,5 @@
|
||||
// 1. This file should contain the game logic
|
||||
// TODO: Implement question loading from API
|
||||
// TODO: Implement answer handling
|
||||
// TODO: Implement lifeline functionality
|
||||
// TODO: Add event listeners for game controls
|
||||
6
quiz_game/starter_templates/static/style.css
Normal file
6
quiz_game/starter_templates/static/style.css
Normal file
@@ -0,0 +1,6 @@
|
||||
/* 1. This file should contain basic styling for the game
|
||||
* TODO: Add styles for game container
|
||||
* TODO: Style question display elements
|
||||
* TODO: Style answer options
|
||||
* TODO: Add styles for game controls and lifelines
|
||||
*/
|
||||
5
quiz_game/starter_templates/templates/game.html
Normal file
5
quiz_game/starter_templates/templates/game.html
Normal file
@@ -0,0 +1,5 @@
|
||||
// 1. This file should contain game HTML structure
|
||||
// TODO: Add game container
|
||||
// TODO: Add question display elements
|
||||
// TODO: Add answer options container
|
||||
// TODO: Add game controls and lifelines buttons
|
||||
5
quiz_game/starter_templates/templates/index.html
Normal file
5
quiz_game/starter_templates/templates/index.html
Normal file
@@ -0,0 +1,5 @@
|
||||
// 1. This file should contain the main page structure
|
||||
// TODO: Add welcome message
|
||||
// TODO: Add game start button
|
||||
// TODO: Add instructions section
|
||||
// TODO: Add footer with credits
|
||||
149
quiz_game/static/script.js
Normal file
149
quiz_game/static/script.js
Normal file
@@ -0,0 +1,149 @@
|
||||
// script.js
|
||||
let currentQuestion = null;
|
||||
|
||||
// Utility function for making API requests
|
||||
function apiRequest(url, options = {}) {
|
||||
return fetch(url, options)
|
||||
.then(response => response.json())
|
||||
.catch(error => {
|
||||
console.error('Error:', error);
|
||||
throw error;
|
||||
});
|
||||
}
|
||||
|
||||
// Utility function for updating element text content
|
||||
function updateElementText(id, text) {
|
||||
const element = document.getElementById(id);
|
||||
if (element) {
|
||||
element.textContent = text;
|
||||
}
|
||||
}
|
||||
|
||||
// Utility function for showing/hiding elements
|
||||
function toggleElementVisibility(id, show = true) {
|
||||
const element = document.getElementById(id);
|
||||
if (element) {
|
||||
element.style.display = show ? 'block' : 'none';
|
||||
}
|
||||
}
|
||||
|
||||
function loadQuestion() {
|
||||
apiRequest('/get_question')
|
||||
.then(data => {
|
||||
if (data.game_over) {
|
||||
endGame(data.final_score);
|
||||
return;
|
||||
}
|
||||
|
||||
currentQuestion = data;
|
||||
displayQuestion(data);
|
||||
})
|
||||
.catch(error => console.error('Error:', error));
|
||||
}
|
||||
|
||||
function displayQuestion(data) {
|
||||
updateElementText('q-number', data.question_number);
|
||||
updateElementText('question-text', data.question);
|
||||
updateElementText('prize', data.current_prize);
|
||||
|
||||
const optionsContainer = document.getElementById('options');
|
||||
optionsContainer.innerHTML = '';
|
||||
|
||||
data.options.forEach((option, index) => {
|
||||
const optionElement = document.createElement('div');
|
||||
optionElement.className = 'option';
|
||||
optionElement.textContent = option;
|
||||
optionElement.onclick = () => selectAnswer(option);
|
||||
optionsContainer.appendChild(optionElement);
|
||||
});
|
||||
|
||||
// Reset result display
|
||||
toggleElementVisibility('result', false);
|
||||
const result = document.getElementById('result');
|
||||
if (result) {
|
||||
result.className = 'result';
|
||||
}
|
||||
}
|
||||
|
||||
function selectAnswer(answer) {
|
||||
apiRequest('/answer', {
|
||||
method: 'POST',
|
||||
headers: {'Content-Type': 'application/json'},
|
||||
body: JSON.stringify({ answer: answer })
|
||||
})
|
||||
.then(data => {
|
||||
const result = document.getElementById('result');
|
||||
if (result) {
|
||||
result.style.display = 'block';
|
||||
|
||||
if (data.correct) {
|
||||
result.textContent = 'Correct!';
|
||||
result.className = 'result correct';
|
||||
|
||||
setTimeout(() => {
|
||||
if (data.game_over) {
|
||||
endGame(data.final_score);
|
||||
} else {
|
||||
loadQuestion();
|
||||
}
|
||||
}, 1500);
|
||||
} else {
|
||||
result.textContent = `Wrong! Correct answer: ${data.correct_answer}`;
|
||||
result.className = 'result incorrect';
|
||||
|
||||
setTimeout(() => {
|
||||
endGame(data.final_score);
|
||||
}, 2000);
|
||||
}
|
||||
}
|
||||
})
|
||||
.catch(error => console.error('Error:', error));
|
||||
}
|
||||
|
||||
function useFiftyFifty() {
|
||||
const lifelineBtn = document.querySelector('.lifeline');
|
||||
if (lifelineBtn) {
|
||||
lifelineBtn.disabled = true;
|
||||
}
|
||||
|
||||
apiRequest('/lifeline/fifty_fifty')
|
||||
.then(data => {
|
||||
if (data.error) {
|
||||
alert(data.error);
|
||||
if (lifelineBtn) {
|
||||
lifelineBtn.disabled = false;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Hide two wrong options
|
||||
const options = document.querySelectorAll('.option');
|
||||
data.remove_indices.forEach(index => {
|
||||
if (options[index]) {
|
||||
options[index].style.display = 'none';
|
||||
}
|
||||
});
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error:', error);
|
||||
if (lifelineBtn) {
|
||||
lifelineBtn.disabled = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function endGame(score) {
|
||||
updateElementText('final-prize', score);
|
||||
toggleElementVisibility('game-over', true);
|
||||
toggleElementVisibility('question-box', false);
|
||||
toggleElementVisibility('lifeline', false);
|
||||
}
|
||||
|
||||
function restartGame() {
|
||||
window.location.href = '/start';
|
||||
}
|
||||
|
||||
// Start the game when page loads
|
||||
if (window.location.pathname === '/start') {
|
||||
loadQuestion();
|
||||
}
|
||||
109
quiz_game/static/style.css
Normal file
109
quiz_game/static/style.css
Normal file
@@ -0,0 +1,109 @@
|
||||
/* style.css */
|
||||
body {
|
||||
font-family: Arial, sans-serif;
|
||||
max-width: 600px;
|
||||
margin: 0 auto;
|
||||
padding: 20px;
|
||||
background: #f0f0f0;
|
||||
}
|
||||
|
||||
.container {
|
||||
background: white;
|
||||
padding: 20px;
|
||||
border-radius: 10px;
|
||||
box-shadow: 0 2px 5px rgba(0,0,0,0.1);
|
||||
}
|
||||
|
||||
h1 {
|
||||
color: #1a237e;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.score {
|
||||
text-align: center;
|
||||
font-size: 1.2em;
|
||||
margin: 10px 0;
|
||||
color: #d32f2f;
|
||||
}
|
||||
|
||||
.question-box {
|
||||
background: #e3f2fd;
|
||||
padding: 15px;
|
||||
border-radius: 8px;
|
||||
margin: 15px 0;
|
||||
}
|
||||
|
||||
.question-number {
|
||||
font-weight: bold;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.question {
|
||||
font-size: 1.1em;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.options {
|
||||
display: grid;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.option {
|
||||
background: #2196f3;
|
||||
color: white;
|
||||
padding: 10px;
|
||||
border-radius: 5px;
|
||||
cursor: pointer;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.option:hover {
|
||||
background: #1976d2;
|
||||
}
|
||||
|
||||
.option.correct {
|
||||
background: #4caf50;
|
||||
}
|
||||
|
||||
.option.wrong {
|
||||
background: #f44336;
|
||||
}
|
||||
|
||||
.result {
|
||||
margin-top: 10px;
|
||||
padding: 10px;
|
||||
border-radius: 5px;
|
||||
text-align: center;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.result.correct {
|
||||
background: #c8e6c9;
|
||||
color: #2e7d32;
|
||||
}
|
||||
|
||||
.result.incorrect {
|
||||
background: #ffcdd2;
|
||||
color: #c62828;
|
||||
}
|
||||
|
||||
.start-btn, .lifeline {
|
||||
background: #ff9800;
|
||||
color: white;
|
||||
border: none;
|
||||
padding: 10px 20px;
|
||||
border-radius: 5px;
|
||||
cursor: pointer;
|
||||
display: block;
|
||||
margin: 10px auto;
|
||||
}
|
||||
|
||||
.lifeline:disabled {
|
||||
background: #ccc;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.game-over {
|
||||
text-align: center;
|
||||
padding: 20px;
|
||||
}
|
||||
37
quiz_game/templates/game.html
Normal file
37
quiz_game/templates/game.html
Normal file
@@ -0,0 +1,37 @@
|
||||
<!-- game.html -->
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Russian Quiz - Game</title>
|
||||
<link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}">
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<h1>Russian Quiz</h1>
|
||||
<div class="score">Prize: <span id="prize">0</span> ₽</div>
|
||||
|
||||
<div class="question-box">
|
||||
<div class="question-number">Question <span id="q-number">1</span>/5</div>
|
||||
<div class="question" id="question-text">Loading...</div>
|
||||
|
||||
<div class="options" id="options">
|
||||
<!-- Options go here -->
|
||||
</div>
|
||||
|
||||
<div class="result" id="result"></div>
|
||||
</div>
|
||||
|
||||
<button class="lifeline" onclick="useFiftyFifty()">50:50 Lifeline</button>
|
||||
|
||||
<div class="game-over" id="game-over" style="display: none;">
|
||||
<h2>Game Over!</h2>
|
||||
<p>You won: <span id="final-prize">0</span> ₽</p>
|
||||
<button onclick="restartGame()">Play Again</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="{{ url_for('static', filename='script.js') }}"></script>
|
||||
</body>
|
||||
</html>
|
||||
23
quiz_game/templates/index.html
Normal file
23
quiz_game/templates/index.html
Normal file
@@ -0,0 +1,23 @@
|
||||
<!-- index.html -->
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Russian Quiz Game</title>
|
||||
<link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}">
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<h1>Russian Quiz</h1>
|
||||
<p>Answer questions about Russian culture!</p>
|
||||
<button onclick="startGame()" class="start-btn">Start Game</button>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
function startGame() {
|
||||
window.location.href = '/start';
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user