[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:
136
backend-lehrer/classroom_engine/antizipation_generator.py
Normal file
136
backend-lehrer/classroom_engine/antizipation_generator.py
Normal file
@@ -0,0 +1,136 @@
|
||||
"""
|
||||
Antizipation Engine - SuggestionGenerator.
|
||||
|
||||
Main class that collects signals, evaluates rules, and generates
|
||||
prioritized suggestions for teachers.
|
||||
"""
|
||||
|
||||
from typing import List, Dict, Any
|
||||
|
||||
from .antizipation_models import Signals, ActiveContext, ContextType
|
||||
from .antizipation_collector import SignalCollector
|
||||
from .antizipation_rules import RuleEngine
|
||||
|
||||
|
||||
class SuggestionGenerator:
|
||||
"""
|
||||
Hauptklasse die Signale sammelt, Regeln evaluiert und
|
||||
Vorschlaege generiert.
|
||||
"""
|
||||
|
||||
def __init__(self, db_session=None):
|
||||
self.collector = SignalCollector(db_session)
|
||||
self.rule_engine = RuleEngine()
|
||||
|
||||
def generate(self, teacher_id: str, limit: int = 5) -> Dict[str, Any]:
|
||||
"""
|
||||
Generiert Vorschlaege fuer einen Lehrer.
|
||||
|
||||
Returns:
|
||||
{
|
||||
"active_contexts": [...],
|
||||
"suggestions": [...],
|
||||
"signals_summary": {...}
|
||||
}
|
||||
"""
|
||||
# 1. Signale sammeln
|
||||
signals = self.collector.collect(teacher_id)
|
||||
|
||||
# 2. Regeln evaluieren
|
||||
all_suggestions = self.rule_engine.evaluate(signals)
|
||||
|
||||
# 3. Aktive Kontexte bestimmen
|
||||
active_contexts = self._determine_active_contexts(signals)
|
||||
|
||||
# 4. Top N Vorschlaege
|
||||
top_suggestions = all_suggestions[:limit]
|
||||
|
||||
return {
|
||||
"active_contexts": [
|
||||
{
|
||||
"id": ctx.id,
|
||||
"type": ctx.context_type.value,
|
||||
"label": ctx.label,
|
||||
}
|
||||
for ctx in active_contexts
|
||||
],
|
||||
"suggestions": [
|
||||
{
|
||||
"id": s.id,
|
||||
"title": s.title,
|
||||
"description": s.description,
|
||||
"tone": s.tone.value,
|
||||
"badge": s.badge,
|
||||
"priority": s.priority,
|
||||
"icon": s.icon,
|
||||
"action_url": s.action_url,
|
||||
}
|
||||
for s in top_suggestions
|
||||
],
|
||||
"signals_summary": {
|
||||
"macro_phase": signals.macro_phase,
|
||||
"current_week": signals.current_week,
|
||||
"has_classes": signals.has_classes,
|
||||
"exams_soon": len(signals.exams_in_7_days),
|
||||
"routines_today": len(signals.routines_today),
|
||||
},
|
||||
"total_suggestions": len(all_suggestions),
|
||||
}
|
||||
|
||||
def _determine_active_contexts(self, signals: Signals) -> List[ActiveContext]:
|
||||
"""Bestimmt die aktiven Kontexte basierend auf Signalen."""
|
||||
contexts = []
|
||||
|
||||
# Event-Kontexte
|
||||
if signals.exams_in_7_days:
|
||||
contexts.append(ActiveContext(
|
||||
id="EXAM_IN_7_DAYS",
|
||||
context_type=ContextType.EVENT_WINDOW,
|
||||
label="Klausur in 7 Tagen",
|
||||
))
|
||||
|
||||
if signals.trips_in_30_days:
|
||||
contexts.append(ActiveContext(
|
||||
id="TRIP_UPCOMING",
|
||||
context_type=ContextType.EVENT_WINDOW,
|
||||
label="Klassenfahrt geplant",
|
||||
))
|
||||
|
||||
# Routine-Kontexte
|
||||
if signals.has_conference_today:
|
||||
contexts.append(ActiveContext(
|
||||
id="CONFERENCE_TODAY",
|
||||
context_type=ContextType.ROUTINE,
|
||||
label="Konferenz heute",
|
||||
))
|
||||
|
||||
# Zeit-Kontexte
|
||||
if signals.is_weekend:
|
||||
contexts.append(ActiveContext(
|
||||
id="WEEKEND",
|
||||
context_type=ContextType.TIME,
|
||||
label="Wochenende",
|
||||
))
|
||||
|
||||
if signals.is_before_holidays:
|
||||
contexts.append(ActiveContext(
|
||||
id="BEFORE_HOLIDAYS",
|
||||
context_type=ContextType.TIME,
|
||||
label="Vor den Ferien",
|
||||
))
|
||||
|
||||
# Phase-Kontexte
|
||||
if signals.macro_phase == "onboarding":
|
||||
contexts.append(ActiveContext(
|
||||
id="ONBOARDING",
|
||||
context_type=ContextType.PHASE,
|
||||
label="Einrichtung",
|
||||
))
|
||||
elif signals.macro_phase in ("halbjahresabschluss", "jahresabschluss"):
|
||||
contexts.append(ActiveContext(
|
||||
id="GRADE_PERIOD",
|
||||
context_type=ContextType.PHASE,
|
||||
label="Notenphase",
|
||||
))
|
||||
|
||||
return contexts
|
||||
Reference in New Issue
Block a user