Files
breakpilot-lehrer/backend-lehrer/unit_models.py
Benjamin Admin 6811264756 [split-required] Split final batch of monoliths >1000 LOC
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>
2026-04-24 23:17:30 +02:00

150 lines
4.8 KiB
Python

# ==============================================
# Breakpilot Drive - Unit API Models
# ==============================================
# Pydantic models for the Unit API.
# Extracted from unit_api.py for file-size compliance.
from pydantic import BaseModel, Field
from typing import List, Optional, Dict, Any
from datetime import datetime
class UnitDefinitionResponse(BaseModel):
"""Unit definition response"""
unit_id: str
template: str
version: str
locale: List[str]
grade_band: List[str]
duration_minutes: int
difficulty: str
definition: Dict[str, Any]
class CreateSessionRequest(BaseModel):
"""Request to create a unit session"""
unit_id: str
student_id: str
locale: str = "de-DE"
difficulty: str = "base"
class SessionResponse(BaseModel):
"""Response after creating a session"""
session_id: str
unit_definition_url: str
session_token: str
telemetry_endpoint: str
expires_at: datetime
class TelemetryEvent(BaseModel):
"""Single telemetry event"""
ts: Optional[str] = None
type: str = Field(..., alias="type")
stop_id: Optional[str] = None
metrics: Optional[Dict[str, Any]] = None
class Config:
populate_by_name = True
class TelemetryPayload(BaseModel):
"""Batch telemetry payload"""
session_id: str
events: List[TelemetryEvent]
class TelemetryResponse(BaseModel):
"""Response after receiving telemetry"""
accepted: int
class PostcheckAnswer(BaseModel):
"""Single postcheck answer"""
question_id: str
answer: str
class CompleteSessionRequest(BaseModel):
"""Request to complete a session"""
postcheck_answers: Optional[List[PostcheckAnswer]] = None
class SessionSummaryResponse(BaseModel):
"""Response with session summary"""
summary: Dict[str, Any]
next_recommendations: Dict[str, Any]
class UnitListItem(BaseModel):
"""Unit list item"""
unit_id: str
template: str
difficulty: str
duration_minutes: int
locale: List[str]
grade_band: List[str]
class RecommendedUnit(BaseModel):
"""Recommended unit with reason"""
unit_id: str
template: str
difficulty: str
reason: str
class CreateUnitRequest(BaseModel):
"""Request to create a new unit definition"""
unit_id: str = Field(..., description="Unique unit identifier")
template: str = Field(..., description="Template type: flight_path or station_loop")
version: str = Field(default="1.0.0", description="Version string")
locale: List[str] = Field(default=["de-DE"], description="Supported locales")
grade_band: List[str] = Field(default=["5", "6", "7"], description="Target grade levels")
duration_minutes: int = Field(default=8, ge=3, le=20, description="Expected duration")
difficulty: str = Field(default="base", description="Difficulty level: base or advanced")
subject: Optional[str] = Field(default=None, description="Subject area")
topic: Optional[str] = Field(default=None, description="Topic within subject")
learning_objectives: List[str] = Field(default=[], description="Learning objectives")
stops: List[Dict[str, Any]] = Field(default=[], description="Unit stops/stations")
precheck: Optional[Dict[str, Any]] = Field(default=None, description="Pre-check configuration")
postcheck: Optional[Dict[str, Any]] = Field(default=None, description="Post-check configuration")
teacher_controls: Optional[Dict[str, Any]] = Field(default=None, description="Teacher control settings")
assets: Optional[Dict[str, Any]] = Field(default=None, description="Asset configuration")
metadata: Optional[Dict[str, Any]] = Field(default=None, description="Additional metadata")
status: str = Field(default="draft", description="Publication status: draft or published")
class UpdateUnitRequest(BaseModel):
"""Request to update an existing unit definition"""
version: Optional[str] = None
locale: Optional[List[str]] = None
grade_band: Optional[List[str]] = None
duration_minutes: Optional[int] = Field(default=None, ge=3, le=20)
difficulty: Optional[str] = None
subject: Optional[str] = None
topic: Optional[str] = None
learning_objectives: Optional[List[str]] = None
stops: Optional[List[Dict[str, Any]]] = None
precheck: Optional[Dict[str, Any]] = None
postcheck: Optional[Dict[str, Any]] = None
teacher_controls: Optional[Dict[str, Any]] = None
assets: Optional[Dict[str, Any]] = None
metadata: Optional[Dict[str, Any]] = None
status: Optional[str] = None
class ValidationError(BaseModel):
"""Single validation error"""
field: str
message: str
severity: str = "error" # error or warning
class ValidationResult(BaseModel):
"""Result of unit validation"""
valid: bool
errors: List[ValidationError] = []
warnings: List[ValidationError] = []