klausur-service (11 files): - cv_gutter_repair, ocr_pipeline_regression, upload_api - ocr_pipeline_sessions, smart_spell, nru_worksheet_generator - ocr_pipeline_overlays, mail/aggregator, zeugnis_api - cv_syllable_detect, self_rag backend-lehrer (17 files): - classroom_engine/suggestions, generators/quiz_generator - worksheets_api, llm_gateway/comparison, state_engine_api - classroom/models (→ 4 submodules), services/file_processor - alerts_agent/api/wizard+digests+routes, content_generators/pdf - classroom/routes/sessions, llm_gateway/inference - classroom_engine/analytics, auth/keycloak_auth - alerts_agent/processing/rule_engine, ai_processor/print_versions agent-core (5 files): - brain/memory_store, brain/knowledge_graph, brain/context_manager - orchestrator/supervisor, sessions/session_manager admin-lehrer (5 components): - GridOverlay, StepGridReview, DevOpsPipelineSidebar - DataFlowDiagram, sbom/wizard/page website (2 files): - DependencyMap, lehrer/abitur-archiv Other: nibis_ingestion, grid_detection_service, export-doclayout-onnx Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
162 lines
4.8 KiB
Python
162 lines
4.8 KiB
Python
"""
|
|
Classroom API - Analytics, Reflection, Feedback, Settings Pydantic Models.
|
|
"""
|
|
|
|
from typing import Dict, List, Optional, Any
|
|
from pydantic import BaseModel, Field
|
|
|
|
|
|
# === Analytics Models ===
|
|
|
|
class SessionSummaryResponse(BaseModel):
|
|
"""Response fuer Session-Summary."""
|
|
session_id: str
|
|
teacher_id: str
|
|
class_id: str
|
|
subject: str
|
|
topic: Optional[str]
|
|
date: Optional[str]
|
|
date_formatted: str
|
|
total_duration_seconds: int
|
|
total_duration_formatted: str
|
|
planned_duration_seconds: int
|
|
planned_duration_formatted: str
|
|
phases_completed: int
|
|
total_phases: int
|
|
completion_percentage: int
|
|
phase_statistics: List[Dict[str, Any]]
|
|
total_overtime_seconds: int
|
|
total_overtime_formatted: str
|
|
phases_with_overtime: int
|
|
total_pause_count: int
|
|
total_pause_seconds: int
|
|
reflection_notes: str = ""
|
|
reflection_rating: Optional[int] = None
|
|
key_learnings: List[str] = []
|
|
|
|
|
|
class TeacherAnalyticsResponse(BaseModel):
|
|
"""Response fuer Lehrer-Analytics."""
|
|
teacher_id: str
|
|
period_start: Optional[str]
|
|
period_end: Optional[str]
|
|
total_sessions: int
|
|
completed_sessions: int
|
|
total_teaching_minutes: int
|
|
total_teaching_hours: float
|
|
avg_phase_durations: Dict[str, int]
|
|
sessions_with_overtime: int
|
|
overtime_percentage: int
|
|
avg_overtime_seconds: int
|
|
avg_overtime_formatted: str
|
|
most_overtime_phase: Optional[str]
|
|
avg_pause_count: float
|
|
avg_pause_duration_seconds: int
|
|
subjects_taught: Dict[str, int]
|
|
classes_taught: Dict[str, int]
|
|
|
|
|
|
class ReflectionCreate(BaseModel):
|
|
"""Request-Body fuer Reflection-Erstellung."""
|
|
session_id: str
|
|
teacher_id: str
|
|
notes: str = ""
|
|
overall_rating: Optional[int] = Field(None, ge=1, le=5)
|
|
what_worked: List[str] = []
|
|
improvements: List[str] = []
|
|
notes_for_next_lesson: str = ""
|
|
|
|
|
|
class ReflectionUpdate(BaseModel):
|
|
"""Request-Body fuer Reflection-Update."""
|
|
notes: Optional[str] = None
|
|
overall_rating: Optional[int] = Field(None, ge=1, le=5)
|
|
what_worked: Optional[List[str]] = None
|
|
improvements: Optional[List[str]] = None
|
|
notes_for_next_lesson: Optional[str] = None
|
|
|
|
|
|
class ReflectionResponse(BaseModel):
|
|
"""Response fuer eine einzelne Reflection."""
|
|
reflection_id: str
|
|
session_id: str
|
|
teacher_id: str
|
|
notes: str
|
|
overall_rating: Optional[int]
|
|
what_worked: List[str]
|
|
improvements: List[str]
|
|
notes_for_next_lesson: str
|
|
created_at: Optional[str]
|
|
updated_at: Optional[str]
|
|
|
|
|
|
# === Feedback Models ===
|
|
|
|
class FeedbackCreate(BaseModel):
|
|
"""Request zum Erstellen von Feedback."""
|
|
title: str = Field(..., min_length=3, max_length=500, description="Kurzer Titel")
|
|
description: str = Field(..., min_length=10, description="Beschreibung")
|
|
feedback_type: str = Field("improvement", description="bug, feature_request, improvement, praise, question")
|
|
priority: str = Field("medium", description="critical, high, medium, low")
|
|
teacher_name: str = Field("", description="Name des Lehrers")
|
|
teacher_email: str = Field("", description="E-Mail fuer Rueckfragen")
|
|
context_url: str = Field("", description="URL wo Feedback gegeben wurde")
|
|
context_phase: str = Field("", description="Aktuelle Phase")
|
|
context_session_id: Optional[str] = Field(None, description="Session-ID falls aktiv")
|
|
related_feature: Optional[str] = Field(None, description="Verwandtes Feature")
|
|
|
|
|
|
class FeedbackResponse(BaseModel):
|
|
"""Response fuer Feedback."""
|
|
id: str
|
|
teacher_id: str
|
|
teacher_name: str
|
|
title: str
|
|
description: str
|
|
feedback_type: str
|
|
priority: str
|
|
status: str
|
|
created_at: str
|
|
response: Optional[str] = None
|
|
|
|
|
|
class FeedbackListResponse(BaseModel):
|
|
"""Liste von Feedbacks."""
|
|
feedbacks: List[Dict[str, Any]]
|
|
total: int
|
|
|
|
|
|
class FeedbackStatsResponse(BaseModel):
|
|
"""Feedback-Statistiken."""
|
|
total: int
|
|
by_status: Dict[str, int]
|
|
by_type: Dict[str, int]
|
|
by_priority: Dict[str, int]
|
|
|
|
|
|
# === Settings Models ===
|
|
|
|
class TeacherSettingsResponse(BaseModel):
|
|
"""Response fuer Lehrer-Einstellungen."""
|
|
teacher_id: str
|
|
default_phase_durations: Dict[str, int]
|
|
audio_enabled: bool = True
|
|
high_contrast: bool = False
|
|
show_statistics: bool = True
|
|
|
|
|
|
class UpdatePhaseDurationsRequest(BaseModel):
|
|
"""Request zum Aktualisieren der Phasen-Dauern."""
|
|
durations: Dict[str, int] = Field(
|
|
...,
|
|
description="Phasen-Dauern in Minuten, z.B. {'einstieg': 10, 'erarbeitung': 25}",
|
|
examples=[{"einstieg": 10, "erarbeitung": 25, "sicherung": 10, "transfer": 8, "reflexion": 5}]
|
|
)
|
|
|
|
|
|
class UpdatePreferencesRequest(BaseModel):
|
|
"""Request zum Aktualisieren der UI-Praeferenzen."""
|
|
audio_enabled: Optional[bool] = None
|
|
high_contrast: Optional[bool] = None
|
|
show_statistics: Optional[bool] = None
|