[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:
143
backend-lehrer/state_engine_models.py
Normal file
143
backend-lehrer/state_engine_models.py
Normal file
@@ -0,0 +1,143 @@
|
||||
"""
|
||||
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
|
||||
Reference in New Issue
Block a user