📋

Project Overview

Understand the complete project structure and goals

⚙️

Backend Developer

Dima - Game logic, sessions, and prize system

🗃️

Database Manager

Danil - Questions and answers in JSON format

🎨

Frontend Developer

Inna - User interface and game interaction

🎨

Graphics Designer

Artyom - Styling and Russian visual theme

Project Overview & Structure

What We're Building

We're creating a "Who Wants to Be a Millionaire?" style quiz game with a Russian cultural theme. Players answer increasingly difficult questions to win virtual prize money.

Project File Structure:

russian-millionaire/
app.py (Main application file)
questions.json (All quiz questions)
templates/
index.html (Home page)
game.html (Game screen)
static/
style.css (All styling)
script.js (Game interaction)

How Flask Works

Flask is a web framework that lets us create web applications with Python. Think of it as a restaurant:

app.py = The restaurant kitchen (prepares everything)

Routes = The menu (different pages/actions)

Templates = The dining area (what customers see)

Static files = Decorations and utensils (CSS, JavaScript, images)

When a user visits our website, Flask serves the appropriate template and handles any requests, like when a player answers a question.

Development Workflow

We'll follow this process over 6 lessons:

Lessons 1-2: Setup & foundation - Get basic structure working

Lessons 3-4: Core development - Implement main features

Lessons 5-6: Completion & testing - Polish and fix issues

Each student has a specific role, but we'll integrate all our work at the end to create a complete, functional game!

Backend Developer - Dima

Step 1: Prize System Setup

First, let's set up the prize money levels. Players earn more money for each correct answer.

# 1. This file should contain the game logic for the quiz game
# TODO: Import Flask and setup the app
# TODO: Define prize levels and guaranteed levels
# TODO: Setup game session routes
# TODO: Implement question serving functionality
# TODO: Add lifeline functionality

What this does: Creates a list of prize amounts that players can win. Each number represents the prize for answering that question correctly. The amounts increase as questions get harder.

GUARANTEED_LEVELS: These are safety nets - if a player gets a question wrong after one of these levels, they still win the prize from that level.

Step 2: Game Session Setup

We need to track each player's game session - what question they're on, their prize money, etc.

from flask import Flask, session, redirect, url_for

app = Flask(__name__)
app.secret_key = 'your_secret_key_here'  # Needed for sessions

@app.route('/start')
def start_game():
    # Initialize a new game session
    session['current_question'] = 0
    session['score'] = 0
    session['lifelines'] = ['fifty_fifty']  # Only one lifeline implemented
    return redirect(url_for('game_screen'))

What this does: Creates a "/start" route that begins a new game. It resets the player's progress to zero and gives them one lifeline: fifty_fifty.

Session: Like a digital backpack that remembers your game progress as you play.

Routes: Different web addresses that do different things in our app.

Note: Although the original plan included multiple lifelines, the current implementation only includes the fifty_fifty lifeline for simplicity.

Step 3: Question Serving

We need to send questions to the player one by one as they progress.

# 2. This file should contain the database connection and data handling
# TODO: Load questions from JSON file
# TODO: Implement answer checking functionality
# TODO: Handle lifeline requests
# TODO: Manage game state and sessions

What this does: Reads the questions from the JSON file and sends the appropriate question based on how far the player has progressed.

JSON: A file format that stores data in an organized way, like a digital filing cabinet.

Session.get(): Safely checks what question the player is currently on.

Pro Tip: Test your backend by running python app.py and visiting http://localhost:5000/start in your browser!

Database Manager - Danil

Step 1: Understanding JSON Structure

Our "database" is a JSON file that stores all the quiz questions, options, and correct answers.

// 1. This file should contain the basic structure of the game page
// TODO: Create the main game container
// TODO: Add elements for displaying questions and answers
// TODO: Include buttons for lifelines
// TODO: Add a game over screen
// TODO: Link to CSS and JavaScript files

What this does: Creates a list of question objects. Each question has:

  • question: The actual question text
  • options: List of 4 possible answers
  • correct_answer: The index (0-3) of the right answer

Important: The correct_answer uses 0-based indexing, so 0 = first option, 1 = second option, etc.

Step 2: Creating Russian Culture Questions

Create questions about Russian history, culture, geography, and famous people.

{
  "question": "What is the name of the famous Russian ballet company?",
  "options": [
    "Moscow Dance Theater",
    "St. Petersburg Ballet",
    "Bolshoi Ballet", 
    "Russian National Ballet"
  ],
  "correct_answer": 2
},

{
  "question": "Which Russian ruler was known as 'The Great' and modernized Russia?",
  "options": [
    "Ivan the Terrible",
    "Catherine the Great", 
    "Peter the Great",
    "Alexander II"
  ],
  "correct_answer": 2
},

{
  "question": "What is the traditional Russian soup made with beets?",
  "options": [
    "Shchi",
    "Borscht",
    "Solyanka", 
    "Ukha"
  ],
  "correct_answer": 1
}

What this does: Adds culturally relevant questions to our game. Make sure:

  • Questions get progressively harder
  • Wrong answers are plausible (sound like they could be right)
  • Answers are factually accurate

Step 3: Complete Question Set

We need 15 questions total, with increasing difficulty.

// Example of a harder question for later in the game
{
  "question": "In which year did the Soviet Union dissolve?",
  "options": [
    "1989",
    "1991", 
    "1993",
    "1985"
  ],
  "correct_answer": 1
},

{
  "question": "What is the name of the Russian equivalent of NASA?",
  "options": [
    "Russian Space Agency",
    "Soviet Space Program", 
    "Roscosmos",
    "Kosmonavtika"
  ],
  "correct_answer": 2
}

What this does: Adds more challenging questions for the higher prize levels. These should require more specific knowledge.

Tip: Use a mix of history, geography, culture, science, and arts questions to make the game interesting!

Pro Tip: Validate your JSON at jsonlint.com to catch any syntax errors!

Frontend Developer - Inna

Step 1: Basic Game HTML Structure

Create the main game screen where questions will be displayed.

<!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>

What this does: Creates the basic structure of our game page with:

  • A header with the game title and prize display
  • A container for the question and answer options
  • A button for the 50:50 lifeline
  • A game over screen that appears when the game ends

URL_FOR: A Flask function that creates the correct path to our CSS and JavaScript files.

Step 2: Utility Functions for DRY Code

Create utility functions to avoid repeating code and make our application more maintainable.

// 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';
    }
}

What this does: These utility functions follow the DRY (Don't Repeat Yourself) principle:

  • apiRequest(): Handles all API calls with consistent error handling
  • updateElementText(): Simplifies updating text content of elements
  • toggleElementVisibility(): Standardizes showing/hiding elements

DRY Principle: Writing code once and reusing it makes applications easier to maintain and less error-prone.

Step 3: JavaScript - Loading Questions

Use JavaScript to fetch questions from the backend and display them.

let currentQuestion = null;

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';
    }
}

What this does:

  • apiRequest(): Uses our utility function to fetch questions from the backend
  • displayQuestion(): Updates the UI with the received question data
  • Utility functions: Uses our helper functions to simplify DOM manipulation

Event Handling: Makes the answer options clickable by assigning onclick handlers.

Step 4: Answer Selection & Game Flow

Handle what happens when a player selects an answer.

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 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();
}

What this does:

  • selectAnswer(): Sends the chosen answer to the backend for checking
  • Visual feedback: Shows if the answer was correct or incorrect
  • Game flow: Progresses to the next question or ends the game based on the result
  • endGame(): Displays the final score and game over screen

setTimeout(): Adds a delay before progressing to give players time to see the result.

Step 5: Lifeline Implementation

Implement the 50:50 lifeline that removes two wrong answers.

// 2. This file should contain the interactive functionality of the game
// TODO: Implement functions to load and display questions
// TODO: Add event handlers for answer selection
// TODO: Implement lifeline functionality
// TODO: Add game flow control (next question, game over)

What this does:

  • Disables the button: Prevents using the lifeline multiple times
  • API call: Requests the backend to determine which options to remove
  • Hides options: Visually removes two wrong answer options from the screen

Error handling: Gracefully handles errors and re-enables the button if the lifeline fails.

Graphics Designer - Artyom

Step 1: Russian Color Theme

Create a color scheme inspired by the Russian flag and traditional colors.

/* Russian Color Theme */
:root {
    --russian-white: #ffffff;
    --russian-blue: #1a3b8b;
    --russian-red: #d52b1e;
    --russian-gold: #daa520;
    --russian-dark: #0a1a3a;
}

body {
    background: linear-gradient(135deg, var(--russian-blue), var(--russian-dark));
    color: var(--russian-white);
    font-family: 'Arial', sans-serif;
    min-height: 100vh;
    margin: 0;
    padding: 0;
}

.game-container {
    max-width: 800px;
    margin: 0 auto;
    padding: 20px;
    background-color: rgba(255, 255, 255, 0.95);
    border-radius: 15px;
    box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3);
    color: var(--russian-dark);
}

.header {
    background: linear-gradient(to right, var(--russian-blue), var(--russian-red));
    color: white;
    padding: 20px;
    border-radius: 10px;
    text-align: center;
    margin-bottom: 30px;
}

What this does: Establishes a color palette based on the Russian flag colors and applies them to our game:

  • CSS Variables: Define colors once, use everywhere (easy to change later)
  • Gradients: Create smooth color transitions for visual appeal
  • Box Shadow: Adds depth to elements so they don't look flat

Step 2: Question and Option Styling

Style the question display and answer options to be clear and attractive.

.question-container {
    margin-bottom: 30px;
}

.question {
    font-size: 1.5rem;
    font-weight: bold;
    text-align: center;
    margin-bottom: 25px;
    padding: 20px;
    background-color: var(--russian-white);
    border: 3px solid var(--russian-gold);
    border-radius: 10px;
    box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
}

.options {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 15px;
}

.option {
    padding: 15px 20px;
    background: linear-gradient(to bottom, #f8f9fa, #e9ecef);
    border: 2px solid var(--russian-blue);
    border-radius: 8px;
    font-size: 1.1rem;
    cursor: pointer;
    transition: all 0.3s ease;
    color: var(--russian-dark);
}

.option:hover {
    background: linear-gradient(to bottom, #e9ecef, #dee2e6);
    transform: translateY(-2px);
    box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
}

.option:active {
    transform: translateY(0);
}

/* Answer feedback styles */
.option.correct {
    background: linear-gradient(to bottom, #d4edda, #c3e6cb);
    border-color: #28a745;
    color: #155724;
}

.option.wrong {
    background: linear-gradient(to bottom, #f8d7da, #f1b0b7);
    border-color: #dc3545;
    color: #721c24;
}

What this does:

  • Grid Layout: Arranges answer options in two columns
  • Hover Effects: Makes buttons feel interactive
  • Transitions: Creates smooth animations for state changes
  • Feedback Colors: Green for correct answers, red for incorrect

CSS Grid: Modern way to create responsive layouts without complex calculations.

Step 3: Lifeline and Prize Styling

Style the lifeline buttons and prize display to match the Russian theme.

.lifelines {
    display: flex;
    justify-content: center;
    gap: 20px;
    margin: 20px 0;
}

.lifeline {
    padding: 10px 20px;
    background: linear-gradient(to bottom, var(--russian-gold), #b8860b);
    color: var(--russian-dark);
    border: none;
    border-radius: 25px;
    font-weight: bold;
    cursor: pointer;
    transition: all 0.3s ease;
    box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
}

.lifeline:hover:not(:disabled) {
    transform: translateY(-2px);
    box-shadow: 0 6px 12px rgba(0, 0, 0, 0.3);
}

.lifeline:disabled {
    background: linear-gradient(to bottom, #6c757d, #495057);
    color: #adb5bd;
    cursor: not-allowed;
    transform: none;
    box-shadow: none;
}

.prize-display {
    font-size: 1.5rem;
    font-weight: bold;
    color: var(--russian-gold);
    text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.5);
}

/* Responsive design for mobile */
@media (max-width: 768px) {
    .options {
        grid-template-columns: 1fr;
    }
    
    .game-container {
        margin: 10px;
        padding: 15px;
    }
    
    .question {
        font-size: 1.2rem;
    }
}

What this does:

  • Flexbox: Centers the lifeline buttons horizontally
  • Golden Gradient: Makes lifeline buttons stand out
  • Disabled State: Shows when lifelines have been used
  • Responsive Design: Adapts layout for mobile devices

Media Queries: Apply different styles based on screen size - crucial for mobile users!