[split-required] Split 500-850 LOC files (batch 2)
backend-lehrer (10 files): - game/database.py (785 → 5), correction_api.py (683 → 4) - classroom_engine/antizipation.py (676 → 5) - llm_gateway schools/edu_search already done in prior batch klausur-service (12 files): - orientation_crop_api.py (694 → 5), pdf_export.py (677 → 4) - zeugnis_crawler.py (676 → 5), grid_editor_api.py (671 → 5) - eh_templates.py (658 → 5), mail/api.py (651 → 5) - qdrant_service.py (638 → 5), training_api.py (625 → 4) website (6 pages): - middleware (696 → 8), mail (733 → 6), consent (628 → 8) - compliance/risks (622 → 5), export (502 → 5), brandbook (629 → 7) studio-v2 (3 components): - B2BMigrationWizard (848 → 3), CleanupPanel (765 → 2) - dashboard-experimental (739 → 2) admin-lehrer (4 files): - uebersetzungen (769 → 4), manager (670 → 2) - ChunkBrowserQA (675 → 6), dsfa/page (674 → 5) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
131
backend-lehrer/classroom_engine/antizipation_collector.py
Normal file
131
backend-lehrer/classroom_engine/antizipation_collector.py
Normal file
@@ -0,0 +1,131 @@
|
||||
"""
|
||||
Antizipation Engine - Signal collector.
|
||||
|
||||
Sammelt Signale aus verschiedenen Quellen:
|
||||
- TeacherContext (Makro-Phase, Schuljahr)
|
||||
- SchoolyearEvents (Klausuren, Elternabende, etc.)
|
||||
- RecurringRoutines (Konferenzen heute)
|
||||
- Zeit/Kalender (Wochenende, Ferien)
|
||||
"""
|
||||
|
||||
import logging
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
from .antizipation_models import Signals
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class SignalCollector:
|
||||
"""
|
||||
Sammelt Signale aus verschiedenen Quellen.
|
||||
"""
|
||||
|
||||
def __init__(self, db_session=None):
|
||||
self.db = db_session
|
||||
|
||||
def collect(self, teacher_id: str) -> Signals:
|
||||
"""Sammelt alle Signale fuer einen Lehrer."""
|
||||
signals = Signals()
|
||||
|
||||
# Zeit-Signale
|
||||
self._collect_time_signals(signals)
|
||||
|
||||
if self.db:
|
||||
# Kontext-Signale
|
||||
self._collect_context_signals(signals, teacher_id)
|
||||
# Event-Signale
|
||||
self._collect_event_signals(signals, teacher_id)
|
||||
# Routine-Signale
|
||||
self._collect_routine_signals(signals, teacher_id)
|
||||
|
||||
return signals
|
||||
|
||||
def _collect_time_signals(self, signals: Signals):
|
||||
"""Sammelt zeitbasierte Signale."""
|
||||
now = datetime.utcnow()
|
||||
signals.is_weekend = now.weekday() >= 5
|
||||
|
||||
# TODO: Ferien-Kalender pro Bundesland integrieren
|
||||
# Fuer jetzt: Dummy-Werte
|
||||
signals.is_before_holidays = False
|
||||
signals.days_until_holidays = 999
|
||||
|
||||
def _collect_context_signals(self, signals: Signals, teacher_id: str):
|
||||
"""Sammelt Signale aus dem Teacher-Kontext."""
|
||||
from .repository import TeacherContextRepository
|
||||
|
||||
try:
|
||||
repo = TeacherContextRepository(self.db)
|
||||
context = repo.get_or_create(teacher_id)
|
||||
|
||||
signals.macro_phase = context.macro_phase.value
|
||||
signals.current_week = context.current_week or 1
|
||||
signals.onboarding_completed = context.onboarding_completed
|
||||
signals.has_classes = context.has_classes
|
||||
signals.has_schedule = context.has_schedule
|
||||
signals.classes_count = 1 if context.has_classes else 0
|
||||
|
||||
# Wochen seit Schuljahresstart berechnen
|
||||
if context.schoolyear_start:
|
||||
delta = datetime.utcnow() - context.schoolyear_start
|
||||
signals.weeks_since_start = max(0, delta.days // 7)
|
||||
|
||||
signals.is_before_holidays = context.is_before_holidays
|
||||
|
||||
except Exception as e:
|
||||
logger.warning(f"Failed to collect context signals: {e}")
|
||||
|
||||
def _collect_event_signals(self, signals: Signals, teacher_id: str):
|
||||
"""Sammelt Signale aus Events."""
|
||||
from .repository import SchoolyearEventRepository
|
||||
|
||||
try:
|
||||
repo = SchoolyearEventRepository(self.db)
|
||||
now = datetime.utcnow()
|
||||
|
||||
# Alle anstehenden Events (30 Tage)
|
||||
upcoming = repo.get_upcoming(teacher_id, days=30, limit=20)
|
||||
signals.upcoming_events = [repo.to_dict(e) for e in upcoming]
|
||||
|
||||
# Klausuren in den naechsten 7 Tagen
|
||||
seven_days = now + timedelta(days=7)
|
||||
signals.exams_in_7_days = [
|
||||
repo.to_dict(e) for e in upcoming
|
||||
if e.event_type.value == "exam" and e.start_date <= seven_days
|
||||
]
|
||||
signals.exams_scheduled_count = len([
|
||||
e for e in upcoming if e.event_type.value == "exam"
|
||||
])
|
||||
|
||||
# Klassenfahrten in 30 Tagen
|
||||
signals.trips_in_30_days = [
|
||||
repo.to_dict(e) for e in upcoming
|
||||
if e.event_type.value == "trip"
|
||||
]
|
||||
|
||||
# Elternabende bald
|
||||
signals.parent_evenings_soon = [
|
||||
repo.to_dict(e) for e in upcoming
|
||||
if e.event_type.value in ("parent_evening", "parent_consultation")
|
||||
]
|
||||
|
||||
except Exception as e:
|
||||
logger.warning(f"Failed to collect event signals: {e}")
|
||||
|
||||
def _collect_routine_signals(self, signals: Signals, teacher_id: str):
|
||||
"""Sammelt Signale aus Routinen."""
|
||||
from .repository import RecurringRoutineRepository
|
||||
|
||||
try:
|
||||
repo = RecurringRoutineRepository(self.db)
|
||||
today_routines = repo.get_today(teacher_id)
|
||||
|
||||
signals.routines_today = [repo.to_dict(r) for r in today_routines]
|
||||
signals.has_conference_today = any(
|
||||
r.routine_type.value in ("teacher_conference", "subject_conference")
|
||||
for r in today_routines
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
logger.warning(f"Failed to collect routine signals: {e}")
|
||||
Reference in New Issue
Block a user