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>
150 lines
4.8 KiB
Python
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] = []
|