Python (6 files in klausur-service): - rbac.py (1,132 → 4), admin_api.py (1,012 → 4) - routes/eh.py (1,111 → 4), ocr_pipeline_geometry.py (1,105 → 5) Python (2 files in backend-lehrer): - unit_api.py (1,226 → 6), game_api.py (1,129 → 5) Website (6 page files): - 4x klausur-korrektur pages (1,249-1,328 LOC each) → shared components in website/components/klausur-korrektur/ (17 shared files) - companion (1,057 → 10), magic-help (1,017 → 8) All re-export barrels preserve backward compatibility. Zero import errors verified. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
323 lines
11 KiB
Python
323 lines
11 KiB
Python
# ==============================================
|
|
# Breakpilot Drive - Game API Models & Data
|
|
# ==============================================
|
|
# Pydantic models, difficulty mappings, and sample questions.
|
|
# Extracted from game_api.py for file-size compliance.
|
|
|
|
from pydantic import BaseModel
|
|
from typing import List, Optional, Literal, Dict, Any
|
|
from datetime import datetime
|
|
|
|
|
|
# ==============================================
|
|
# Pydantic Models
|
|
# ==============================================
|
|
|
|
class LearningLevel(BaseModel):
|
|
"""Lernniveau eines Benutzers aus dem Breakpilot-System"""
|
|
user_id: str
|
|
overall_level: int # 1-5 (1=Anfaenger/Klasse 2, 5=Fortgeschritten/Klasse 6)
|
|
math_level: float
|
|
german_level: float
|
|
english_level: float
|
|
last_updated: datetime
|
|
|
|
|
|
class GameDifficulty(BaseModel):
|
|
"""Spielschwierigkeit basierend auf Lernniveau"""
|
|
lane_speed: float # Geschwindigkeit in m/s
|
|
obstacle_frequency: float # Hindernisse pro Sekunde
|
|
power_up_chance: float # Wahrscheinlichkeit fuer Power-Ups (0-1)
|
|
question_complexity: int # 1-5
|
|
answer_time: int # Sekunden zum Antworten
|
|
hints_enabled: bool
|
|
speech_speed: float # Sprechgeschwindigkeit fuer Audio-Version
|
|
|
|
|
|
class QuizQuestion(BaseModel):
|
|
"""Quiz-Frage fuer das Spiel"""
|
|
id: str
|
|
question_text: str
|
|
audio_url: Optional[str] = None
|
|
options: List[str] # 2-4 Antwortmoeglichkeiten
|
|
correct_index: int # 0-3
|
|
difficulty: int # 1-5
|
|
subject: Literal["math", "german", "english", "general"]
|
|
grade_level: Optional[int] = None # 2-6
|
|
# NEU: Quiz-Modus
|
|
quiz_mode: Literal["quick", "pause"] = "quick" # quick=waehrend Fahrt, pause=Spiel haelt an
|
|
visual_trigger: Optional[str] = None # z.B. "bridge", "house", "tree" - loest Frage aus
|
|
time_limit_seconds: Optional[float] = None # Zeit bis Antwort noetig (bei quick)
|
|
|
|
|
|
class QuizAnswer(BaseModel):
|
|
"""Antwort auf eine Quiz-Frage"""
|
|
question_id: str
|
|
selected_index: int
|
|
answer_time_ms: int # Zeit bis zur Antwort in ms
|
|
was_correct: bool
|
|
|
|
|
|
class GameSession(BaseModel):
|
|
"""Spielsession-Daten fuer Analytics"""
|
|
user_id: str
|
|
game_mode: Literal["video", "audio"]
|
|
duration_seconds: int
|
|
distance_traveled: float
|
|
score: int
|
|
questions_answered: int
|
|
questions_correct: int
|
|
difficulty_level: int
|
|
quiz_answers: Optional[List[QuizAnswer]] = None
|
|
|
|
|
|
class SessionResponse(BaseModel):
|
|
"""Antwort nach Session-Speicherung"""
|
|
session_id: str
|
|
status: str
|
|
new_level: Optional[int] = None # Falls Lernniveau angepasst wurde
|
|
|
|
|
|
# ==============================================
|
|
# Schwierigkeits-Mapping
|
|
# ==============================================
|
|
|
|
DIFFICULTY_MAPPING = {
|
|
1: GameDifficulty(
|
|
lane_speed=3.0,
|
|
obstacle_frequency=0.3,
|
|
power_up_chance=0.4,
|
|
question_complexity=1,
|
|
answer_time=15,
|
|
hints_enabled=True,
|
|
speech_speed=0.8
|
|
),
|
|
2: GameDifficulty(
|
|
lane_speed=4.0,
|
|
obstacle_frequency=0.4,
|
|
power_up_chance=0.35,
|
|
question_complexity=2,
|
|
answer_time=12,
|
|
hints_enabled=True,
|
|
speech_speed=0.9
|
|
),
|
|
3: GameDifficulty(
|
|
lane_speed=5.0,
|
|
obstacle_frequency=0.5,
|
|
power_up_chance=0.3,
|
|
question_complexity=3,
|
|
answer_time=10,
|
|
hints_enabled=True,
|
|
speech_speed=1.0
|
|
),
|
|
4: GameDifficulty(
|
|
lane_speed=6.0,
|
|
obstacle_frequency=0.6,
|
|
power_up_chance=0.25,
|
|
question_complexity=4,
|
|
answer_time=8,
|
|
hints_enabled=False,
|
|
speech_speed=1.1
|
|
),
|
|
5: GameDifficulty(
|
|
lane_speed=7.0,
|
|
obstacle_frequency=0.7,
|
|
power_up_chance=0.2,
|
|
question_complexity=5,
|
|
answer_time=6,
|
|
hints_enabled=False,
|
|
speech_speed=1.2
|
|
),
|
|
}
|
|
|
|
|
|
# ==============================================
|
|
# Beispiel Quiz-Fragen (spaeter aus DB laden)
|
|
# ==============================================
|
|
|
|
SAMPLE_QUESTIONS = [
|
|
# ==============================================
|
|
# QUICK QUESTIONS (waehrend der Fahrt, visuell getriggert)
|
|
# ==============================================
|
|
|
|
# Englisch Vokabeln - Objekte im Spiel (QUICK MODE)
|
|
QuizQuestion(
|
|
id="vq-bridge", question_text="What is this?",
|
|
options=["Bridge", "House"], correct_index=0,
|
|
difficulty=1, subject="english", grade_level=3,
|
|
quiz_mode="quick", visual_trigger="bridge", time_limit_seconds=3.0
|
|
),
|
|
QuizQuestion(
|
|
id="vq-tree", question_text="What is this?",
|
|
options=["Tree", "Flower"], correct_index=0,
|
|
difficulty=1, subject="english", grade_level=3,
|
|
quiz_mode="quick", visual_trigger="tree", time_limit_seconds=3.0
|
|
),
|
|
QuizQuestion(
|
|
id="vq-house", question_text="What is this?",
|
|
options=["House", "Car"], correct_index=0,
|
|
difficulty=1, subject="english", grade_level=3,
|
|
quiz_mode="quick", visual_trigger="house", time_limit_seconds=3.0
|
|
),
|
|
QuizQuestion(
|
|
id="vq-car", question_text="What is this?",
|
|
options=["Car", "Bus"], correct_index=0,
|
|
difficulty=1, subject="english", grade_level=3,
|
|
quiz_mode="quick", visual_trigger="car", time_limit_seconds=2.5
|
|
),
|
|
QuizQuestion(
|
|
id="vq-mountain", question_text="What is this?",
|
|
options=["Hill", "Mountain", "Valley"], correct_index=1,
|
|
difficulty=2, subject="english", grade_level=4,
|
|
quiz_mode="quick", visual_trigger="mountain", time_limit_seconds=3.5
|
|
),
|
|
QuizQuestion(
|
|
id="vq-river", question_text="What is this?",
|
|
options=["Lake", "River", "Sea"], correct_index=1,
|
|
difficulty=2, subject="english", grade_level=4,
|
|
quiz_mode="quick", visual_trigger="river", time_limit_seconds=3.5
|
|
),
|
|
|
|
# Schnelle Rechenaufgaben (QUICK MODE)
|
|
QuizQuestion(
|
|
id="mq-1", question_text="3 + 4 = ?",
|
|
options=["6", "7"], correct_index=1,
|
|
difficulty=1, subject="math", grade_level=2,
|
|
quiz_mode="quick", time_limit_seconds=4.0
|
|
),
|
|
QuizQuestion(
|
|
id="mq-2", question_text="5 x 2 = ?",
|
|
options=["10", "12"], correct_index=0,
|
|
difficulty=1, subject="math", grade_level=2,
|
|
quiz_mode="quick", time_limit_seconds=4.0
|
|
),
|
|
QuizQuestion(
|
|
id="mq-3", question_text="8 - 3 = ?",
|
|
options=["4", "5"], correct_index=1,
|
|
difficulty=1, subject="math", grade_level=2,
|
|
quiz_mode="quick", time_limit_seconds=3.5
|
|
),
|
|
QuizQuestion(
|
|
id="mq-4", question_text="6 x 7 = ?",
|
|
options=["42", "48"], correct_index=0,
|
|
difficulty=2, subject="math", grade_level=3,
|
|
quiz_mode="quick", time_limit_seconds=5.0
|
|
),
|
|
QuizQuestion(
|
|
id="mq-5", question_text="9 x 8 = ?",
|
|
options=["72", "64"], correct_index=0,
|
|
difficulty=3, subject="math", grade_level=4,
|
|
quiz_mode="quick", time_limit_seconds=5.0
|
|
),
|
|
|
|
# ==============================================
|
|
# PAUSE QUESTIONS (Spiel haelt an, mehr Zeit)
|
|
# ==============================================
|
|
|
|
# Mathe Level 1-2 (Klasse 2-3) - PAUSE MODE
|
|
QuizQuestion(
|
|
id="mp1-1", question_text="Anna hat 5 Aepfel. Sie bekommt 3 dazu. Wie viele hat sie jetzt?",
|
|
options=["6", "7", "8", "9"], correct_index=2,
|
|
difficulty=1, subject="math", grade_level=2,
|
|
quiz_mode="pause"
|
|
),
|
|
QuizQuestion(
|
|
id="mp2-1", question_text="Ein Bus hat 24 Sitze. 18 sind besetzt. Wie viele sind frei?",
|
|
options=["4", "5", "6", "7"], correct_index=2,
|
|
difficulty=2, subject="math", grade_level=3,
|
|
quiz_mode="pause"
|
|
),
|
|
QuizQuestion(
|
|
id="mp2-2", question_text="Was ist 45 + 27?",
|
|
options=["72", "62", "82", "70"], correct_index=0,
|
|
difficulty=2, subject="math", grade_level=3,
|
|
quiz_mode="pause"
|
|
),
|
|
|
|
# Mathe Level 3-4 (Klasse 4-5) - PAUSE MODE
|
|
QuizQuestion(
|
|
id="mp3-1", question_text="Was ist 7 x 8?",
|
|
options=["54", "56", "58", "48"], correct_index=1,
|
|
difficulty=3, subject="math", grade_level=4,
|
|
quiz_mode="pause"
|
|
),
|
|
QuizQuestion(
|
|
id="mp3-2", question_text="Ein Rechteck ist 8m lang und 5m breit. Wie gross ist die Flaeche?",
|
|
options=["35 m2", "40 m2", "45 m2", "26 m2"], correct_index=1,
|
|
difficulty=3, subject="math", grade_level=4,
|
|
quiz_mode="pause"
|
|
),
|
|
QuizQuestion(
|
|
id="mp4-1", question_text="Was ist 15% von 80?",
|
|
options=["10", "12", "8", "15"], correct_index=1,
|
|
difficulty=4, subject="math", grade_level=5,
|
|
quiz_mode="pause"
|
|
),
|
|
QuizQuestion(
|
|
id="mp4-2", question_text="Was ist 3/4 + 1/2?",
|
|
options=["5/4", "4/6", "1", "5/6"], correct_index=0,
|
|
difficulty=4, subject="math", grade_level=5,
|
|
quiz_mode="pause"
|
|
),
|
|
|
|
# Mathe Level 5 (Klasse 6) - PAUSE MODE
|
|
QuizQuestion(
|
|
id="mp5-1", question_text="Was ist (-5) x (-3)?",
|
|
options=["-15", "15", "-8", "8"], correct_index=1,
|
|
difficulty=5, subject="math", grade_level=6,
|
|
quiz_mode="pause"
|
|
),
|
|
QuizQuestion(
|
|
id="mp5-2", question_text="Loesung von 2x + 5 = 11?",
|
|
options=["2", "3", "4", "6"], correct_index=1,
|
|
difficulty=5, subject="math", grade_level=6,
|
|
quiz_mode="pause"
|
|
),
|
|
|
|
# Deutsch - PAUSE MODE (brauchen Lesezeit)
|
|
QuizQuestion(
|
|
id="dp1-1", question_text="Welches Wort ist ein Nomen?",
|
|
options=["laufen", "schnell", "Hund", "und"], correct_index=2,
|
|
difficulty=1, subject="german", grade_level=2,
|
|
quiz_mode="pause"
|
|
),
|
|
QuizQuestion(
|
|
id="dp2-1", question_text="Was ist die Mehrzahl von 'Haus'?",
|
|
options=["Haeuse", "Haeuser", "Hausern", "Haus"], correct_index=1,
|
|
difficulty=2, subject="german", grade_level=3,
|
|
quiz_mode="pause"
|
|
),
|
|
QuizQuestion(
|
|
id="dp3-1", question_text="Welches Verb steht im Praeteritum?",
|
|
options=["geht", "ging", "gegangen", "gehen"], correct_index=1,
|
|
difficulty=3, subject="german", grade_level=4,
|
|
quiz_mode="pause"
|
|
),
|
|
QuizQuestion(
|
|
id="dp3-2", question_text="Finde den Rechtschreibfehler: 'Der Hund leuft schnell.'",
|
|
options=["Hund", "leuft", "schnell", "Der"], correct_index=1,
|
|
difficulty=3, subject="german", grade_level=4,
|
|
quiz_mode="pause"
|
|
),
|
|
|
|
# Englisch Saetze - PAUSE MODE
|
|
QuizQuestion(
|
|
id="ep3-1", question_text="How do you say 'Schmetterling'?",
|
|
options=["bird", "bee", "butterfly", "beetle"], correct_index=2,
|
|
difficulty=3, subject="english", grade_level=4,
|
|
quiz_mode="pause"
|
|
),
|
|
QuizQuestion(
|
|
id="ep4-1", question_text="Choose the correct form: She ___ to school.",
|
|
options=["go", "goes", "going", "gone"], correct_index=1,
|
|
difficulty=4, subject="english", grade_level=5,
|
|
quiz_mode="pause"
|
|
),
|
|
QuizQuestion(
|
|
id="ep4-2", question_text="What is the past tense of 'run'?",
|
|
options=["runned", "ran", "runed", "running"], correct_index=1,
|
|
difficulty=4, subject="english", grade_level=5,
|
|
quiz_mode="pause"
|
|
),
|
|
]
|