[split-required] Split final 43 files (500-668 LOC) to complete refactoring
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>
This commit is contained in:
161
backend-lehrer/classroom/models_analytics.py
Normal file
161
backend-lehrer/classroom/models_analytics.py
Normal file
@@ -0,0 +1,161 @@
|
||||
"""
|
||||
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
|
||||
Reference in New Issue
Block a user