""" State Engine API - Pydantic Models und Helper Functions. """ import uuid from datetime import datetime, timedelta from typing import Dict, Any, List, Optional from pydantic import BaseModel, Field from state_engine import ( SchoolYearPhase, ClassSummary, Event, TeacherContext, TeacherStats, get_phase_info, ) # ============================================================================ # In-Memory Storage (später durch DB ersetzen) # ============================================================================ _teacher_contexts: Dict[str, TeacherContext] = {} _milestones: Dict[str, List[str]] = {} # teacher_id -> milestones # ============================================================================ # Pydantic Models # ============================================================================ class MilestoneRequest(BaseModel): """Request zum Abschließen eines Meilensteins.""" milestone: str = Field(..., description="Name des Meilensteins") class TransitionRequest(BaseModel): """Request für Phasen-Übergang.""" target_phase: str = Field(..., description="Zielphase") class ContextResponse(BaseModel): """Response mit TeacherContext.""" context: Dict[str, Any] phase_info: Dict[str, Any] class SuggestionsResponse(BaseModel): """Response mit Vorschlägen.""" suggestions: List[Dict[str, Any]] current_phase: str phase_display_name: str priority_counts: Dict[str, int] class DashboardResponse(BaseModel): """Response mit Dashboard-Daten.""" context: Dict[str, Any] suggestions: List[Dict[str, Any]] stats: Dict[str, Any] upcoming_events: List[Dict[str, Any]] progress: Dict[str, Any] phases: List[Dict[str, Any]] # ============================================================================ # Helper Functions # ============================================================================ def get_or_create_context(teacher_id: str) -> TeacherContext: """ Holt oder erstellt TeacherContext. In Produktion würde dies aus der Datenbank geladen. """ if teacher_id not in _teacher_contexts: now = datetime.now() school_year_start = datetime(now.year if now.month >= 8 else now.year - 1, 8, 1) weeks_since_start = (now - school_year_start).days // 7 month = now.month if month in [8, 9]: phase = SchoolYearPhase.SCHOOL_YEAR_START elif month in [10, 11]: phase = SchoolYearPhase.TEACHING_SETUP elif month == 12: phase = SchoolYearPhase.PERFORMANCE_1 elif month in [1, 2]: phase = SchoolYearPhase.SEMESTER_END elif month in [3, 4]: phase = SchoolYearPhase.TEACHING_2 elif month in [5, 6]: phase = SchoolYearPhase.PERFORMANCE_2 else: phase = SchoolYearPhase.YEAR_END _teacher_contexts[teacher_id] = TeacherContext( teacher_id=teacher_id, school_id=str(uuid.uuid4()), school_year_id=str(uuid.uuid4()), federal_state="niedersachsen", school_type="gymnasium", school_year_start=school_year_start, current_phase=phase, phase_entered_at=now - timedelta(days=7), weeks_since_start=weeks_since_start, days_in_phase=7, classes=[], total_students=0, upcoming_events=[], completed_milestones=_milestones.get(teacher_id, []), pending_milestones=[], stats=TeacherStats(), ) return _teacher_contexts[teacher_id] def update_context_from_services(ctx: TeacherContext) -> TeacherContext: """ Aktualisiert Kontext mit Daten aus anderen Services. In Produktion würde dies von school-service, gradebook etc. laden. """ ctx.days_in_phase = (datetime.now() - ctx.phase_entered_at).days ctx.completed_milestones = _milestones.get(ctx.teacher_id, []) phase_info = get_phase_info(ctx.current_phase) ctx.pending_milestones = [ m for m in phase_info.required_actions if m not in ctx.completed_milestones ] return ctx def get_phase_display_name(phase: str) -> str: """Gibt Display-Name für Phase zurück.""" try: return get_phase_info(SchoolYearPhase(phase)).display_name except (ValueError, KeyError): return phase