""" Content Generator Orchestriert die Generierung aller 8 H5P Content-Typen """ from typing import List, Dict, Any, Optional from datetime import datetime import json class ContentGenerator: """H5P Content Generator - Orchestrator""" def __init__(self, claude_service, youtube_service): self.claude = claude_service self.youtube = youtube_service async def generate_all_content_types( self, topic: str, description: Optional[str], target_grade: str, materials: List[Dict[str, Any]], videos: List[Dict[str, Any]] ) -> Dict[str, Any]: """ Generate all 8 H5P content types Returns: Dictionary with all generated content """ result = { "topic": topic, "description": description, "target_grade": target_grade, "generated_at": datetime.utcnow().isoformat(), "content_types": {} } # 1. Quiz try: quiz_data = await self._generate_quiz(topic, description, target_grade, materials) result["content_types"]["quiz"] = quiz_data except Exception as e: result["content_types"]["quiz"] = {"error": str(e)} # 2. Interactive Video try: video_data = await self._generate_interactive_video(topic, description, target_grade, materials, videos) result["content_types"]["interactive_video"] = video_data except Exception as e: result["content_types"]["interactive_video"] = {"error": str(e)} # 3. Course Presentation try: presentation_data = await self._generate_presentation(topic, description, target_grade, materials) result["content_types"]["course_presentation"] = presentation_data except Exception as e: result["content_types"]["course_presentation"] = {"error": str(e)} # 4. Flashcards try: flashcards_data = await self._generate_flashcards(topic, description, target_grade, materials) result["content_types"]["flashcards"] = flashcards_data except Exception as e: result["content_types"]["flashcards"] = {"error": str(e)} # 5. Timeline try: timeline_data = await self._generate_timeline(topic, description, target_grade, materials) result["content_types"]["timeline"] = timeline_data except Exception as e: result["content_types"]["timeline"] = {"error": str(e)} # 6. Drag and Drop try: dragdrop_data = await self._generate_drag_drop(topic, description, target_grade, materials) result["content_types"]["drag_drop"] = dragdrop_data except Exception as e: result["content_types"]["drag_drop"] = {"error": str(e)} # 7. Fill in the Blanks try: fillblanks_data = await self._generate_fill_blanks(topic, description, target_grade, materials) result["content_types"]["fill_blanks"] = fillblanks_data except Exception as e: result["content_types"]["fill_blanks"] = {"error": str(e)} # 8. Memory Game try: memory_data = await self._generate_memory(topic, description, target_grade, materials) result["content_types"]["memory"] = memory_data except Exception as e: result["content_types"]["memory"] = {"error": str(e)} return result async def _generate_quiz( self, topic: str, description: Optional[str], target_grade: str, materials: List[Dict[str, Any]] ) -> Dict[str, Any]: """Generate Quiz content""" questions = await self.claude.generate_quiz_questions( topic=topic, materials=materials, target_grade=target_grade, num_questions=10 ) return { "type": "quiz", "title": f"Quiz: {topic}", "description": description or f"Teste dein Wissen über {topic}", "questions": questions } async def _generate_interactive_video( self, topic: str, description: Optional[str], target_grade: str, materials: List[Dict[str, Any]], videos: List[Dict[str, Any]] ) -> Dict[str, Any]: """Generate Interactive Video content""" # Wähle bestes Video (falls vorhanden) if not videos or len(videos) == 0: return { "error": "Keine Videos gefunden", "note": "Lehrer muss manuell Video-URL eingeben" } best_video = videos[0] # Nimm erstes Video # Hole Transkript video_id = best_video.get("video_id") if not video_id or video_id == "EXAMPLE_VIDEO_ID": # Fallback: Generiere generische Interaktionen return { "type": "interactive-video", "title": f"Interaktives Video: {topic}", "videoUrl": "https://www.youtube.com/watch?v=EXAMPLE", "description": description or f"Lerne über {topic} mit diesem interaktiven Video", "interactions": [ { "time": "01:00", "type": "question", "title": "Verständnisfrage", "content": f"Was ist das Hauptthema dieses Videos über {topic}?" }, { "time": "03:00", "type": "info", "title": "Wichtiger Hinweis", "content": "Achte auf die wichtigsten Konzepte, die jetzt erklärt werden." } ], "note": "Generische Interaktionen - Lehrer sollte echte Video-URL eingeben" } # Echtes Video mit Transkript transcript_data = await self.youtube.get_video_transcript(video_id) if transcript_data: # Generate interactions using Claude interactions = await self.youtube.generate_video_interactions_with_claude( video_id=video_id, topic=topic, transcript_data=transcript_data["transcript"], claude_service=self.claude, num_interactions=5 ) else: # Fallback ohne Transkript interactions = [] return { "type": "interactive-video", "title": best_video.get("title", f"Video: {topic}"), "videoUrl": best_video.get("url"), "description": description or f"Interaktives Video über {topic}", "interactions": interactions } async def _generate_presentation( self, topic: str, description: Optional[str], target_grade: str, materials: List[Dict[str, Any]] ) -> Dict[str, Any]: """Generate Course Presentation content""" slides = await self.claude.generate_presentation_slides( topic=topic, materials=materials, target_grade=target_grade, num_slides=6 ) # Add IDs to slides for i, slide in enumerate(slides, 1): slide["id"] = i return { "type": "course-presentation", "title": f"Präsentation: {topic}", "description": description or f"Lerne alles über {topic}", "slides": slides } async def _generate_flashcards( self, topic: str, description: Optional[str], target_grade: str, materials: List[Dict[str, Any]] ) -> Dict[str, Any]: """Generate Flashcards content""" cards = await self.claude.generate_flashcards( topic=topic, materials=materials, target_grade=target_grade, num_cards=15 ) # Add IDs to cards for i, card in enumerate(cards, 1): card["id"] = i return { "type": "flashcards", "title": f"Lernkarten: {topic}", "description": description or f"Wiederhole wichtige Begriffe zu {topic}", "cards": cards } async def _generate_timeline( self, topic: str, description: Optional[str], target_grade: str, materials: List[Dict[str, Any]] ) -> Dict[str, Any]: """Generate Timeline content""" events = await self.claude.generate_timeline_events( topic=topic, materials=materials, target_grade=target_grade ) # Add IDs to events for i, event in enumerate(events, 1): event["id"] = i return { "type": "timeline", "title": f"Zeitleiste: {topic}", "description": description or f"Chronologie von {topic}", "events": events } async def _generate_drag_drop( self, topic: str, description: Optional[str], target_grade: str, materials: List[Dict[str, Any]] ) -> Dict[str, Any]: """Generate Drag and Drop content""" exercise = await self.claude.generate_drag_drop_exercise( topic=topic, materials=materials, target_grade=target_grade ) return { "type": "drag-drop", "title": exercise.get("title", f"Zuordnung: {topic}"), "question": exercise.get("question", "Ziehe die Elemente in die richtigen Kategorien."), "zones": exercise.get("zones", []), "draggables": exercise.get("draggables", []) } async def _generate_fill_blanks( self, topic: str, description: Optional[str], target_grade: str, materials: List[Dict[str, Any]] ) -> Dict[str, Any]: """Generate Fill in the Blanks content""" exercise = await self.claude.generate_fill_blanks_text( topic=topic, materials=materials, target_grade=target_grade ) return { "type": "fill-blanks", "title": exercise.get("title", f"Lückentext: {topic}"), "text": exercise.get("text", ""), "hints": exercise.get("hints", "") } async def _generate_memory( self, topic: str, description: Optional[str], target_grade: str, materials: List[Dict[str, Any]] ) -> Dict[str, Any]: """Generate Memory Game content""" pairs = await self.claude.generate_memory_pairs( topic=topic, materials=materials, target_grade=target_grade, num_pairs=8 ) # Add IDs to pairs for i, pair in enumerate(pairs, 1): pair["id"] = i return { "type": "memory", "title": f"Memory: {topic}", "description": description or f"Finde die passenden Paare zu {topic}", "pairs": pairs }