""" Phasenspezifische Content-Vorschlaege (Feature f18 erweitert). Generiert Aktivitaets-Vorschlaege basierend auf der aktuellen Unterrichtsphase und optional dem Fach. """ from typing import List, Dict, Any, Optional from .models import LessonPhase, LessonSession, PhaseSuggestion from .suggestion_data import ( SUPPORTED_SUBJECTS, SUBJECT_SUGGESTIONS, PHASE_SUGGESTIONS, ) class SuggestionEngine: """ Engine zur Generierung von phasenspezifischen Vorschlaegen (Feature f18 erweitert). Liefert Aktivitaets-Vorschlaege basierend auf: - Aktueller Phase - Fach (priorisiert fachspezifische Vorschlaege) - Optional: Klassenstufe, bisherige Nutzung """ def _normalize_subject(self, subject: str) -> Optional[str]: """Normalisiert Fachnamen fuer die Suche.""" if not subject: return None normalized = subject.lower().strip() # Mapping zu Hauptkategorien mappings = { "mathe": "mathematik", "math": "mathematik", "bio": "biologie", "english": "englisch", "erdkunde": "geografie", } return mappings.get(normalized, normalized) def _get_subject_suggestions( self, subject: str, phase: LessonPhase ) -> List[Dict[str, Any]]: """Holt fachspezifische Vorschlaege (Feature f18).""" normalized = self._normalize_subject(subject) if not normalized: return [] subject_data = SUBJECT_SUGGESTIONS.get(normalized, {}) return subject_data.get(phase, []) def get_suggestions( self, session: LessonSession, limit: int = 3 ) -> List[PhaseSuggestion]: """ Gibt Vorschlaege fuer die aktuelle Phase zurueck. Priorisiert fachspezifische Vorschlaege (Feature f18), ergaenzt mit allgemeinen Vorschlaegen. Args: session: Die aktuelle Session limit: Maximale Anzahl Vorschlaege Returns: Liste von PhaseSuggestion Objekten """ # Keine Vorschlaege fuer inaktive Phasen if session.current_phase in [LessonPhase.NOT_STARTED, LessonPhase.ENDED]: return [] suggestions = [] seen_ids = set() # 1. Fachspezifische Vorschlaege zuerst (Feature f18) if session.subject: subject_suggestions = self._get_subject_suggestions( session.subject, session.current_phase ) for s in subject_suggestions: if s["id"] not in seen_ids: suggestions.append(PhaseSuggestion(**s)) seen_ids.add(s["id"]) if len(suggestions) >= limit: return suggestions # 2. Allgemeine Vorschlaege ergaenzen phase_suggestions = PHASE_SUGGESTIONS.get(session.current_phase, []) for s in phase_suggestions: if s["id"] not in seen_ids: suggestions.append(PhaseSuggestion(**s)) seen_ids.add(s["id"]) if len(suggestions) >= limit: break return suggestions def get_all_suggestions(self, session: LessonSession) -> List[PhaseSuggestion]: """ Gibt alle Vorschlaege fuer die aktuelle Phase zurueck. Inkludiert fachspezifische und allgemeine Vorschlaege (Feature f18). Args: session: Die aktuelle Session Returns: Alle Vorschlaege fuer die Phase """ return self.get_suggestions(session, limit=100) def get_suggestion_by_id( self, session: LessonSession, suggestion_id: str ) -> Optional[PhaseSuggestion]: """ Gibt einen spezifischen Vorschlag zurueck. Args: session: Die aktuelle Session suggestion_id: ID des Vorschlags Returns: Der Vorschlag oder None """ all_suggestions = self.get_all_suggestions(session) for s in all_suggestions: if s.id == suggestion_id: return s return None def get_suggestions_by_type( self, session: LessonSession, activity_type: str ) -> List[PhaseSuggestion]: """ Gibt Vorschlaege eines bestimmten Typs zurueck. Args: session: Die aktuelle Session activity_type: Der Aktivitaetstyp (z.B. "warmup", "group_work") Returns: Gefilterte Vorschlaege """ all_suggestions = self.get_all_suggestions(session) return [s for s in all_suggestions if s.activity_type == activity_type] def get_suggestions_response( self, session: LessonSession, limit: int = 3 ) -> Dict[str, Any]: """ Gibt die Vorschlaege als API-Response-Format zurueck (Feature f18 erweitert). Args: session: Die aktuelle Session limit: Maximale Anzahl Vorschlaege Returns: Dictionary fuer API-Response """ suggestions = self.get_suggestions(session, limit) # Zaehle fachspezifische und allgemeine Vorschlaege general_count = len(PHASE_SUGGESTIONS.get(session.current_phase, [])) subject_count = len(self._get_subject_suggestions( session.subject, session.current_phase )) if session.subject else 0 return { "suggestions": [s.to_dict() for s in suggestions], "current_phase": session.current_phase.value, "phase_display_name": session.get_phase_display_name(), "total_available": general_count + subject_count, "subject_specific_available": subject_count, "subject": session.subject, }