""" Worksheets API - Pydantic Models und Helpers. Request-/Response-Models und Hilfsfunktionen fuer die Arbeitsblatt-Generierungs-API. """ import uuid from datetime import datetime from typing import List, Dict, Any, Optional from enum import Enum from pydantic import BaseModel, Field from generators.mc_generator import Difficulty from generators.cloze_generator import ClozeType from generators.quiz_generator import QuizType # ============================================================================ # Pydantic Models # ============================================================================ class ContentType(str, Enum): """Verfügbare Content-Typen.""" MULTIPLE_CHOICE = "multiple_choice" CLOZE = "cloze" MINDMAP = "mindmap" QUIZ = "quiz" class GenerateRequest(BaseModel): """Basis-Request für Generierung.""" source_text: str = Field(..., min_length=50, description="Quelltext für Generierung") topic: Optional[str] = Field(None, description="Thema/Titel") subject: Optional[str] = Field(None, description="Fach") grade_level: Optional[str] = Field(None, description="Klassenstufe") class MCGenerateRequest(GenerateRequest): """Request für Multiple-Choice-Generierung.""" num_questions: int = Field(5, ge=1, le=20, description="Anzahl Fragen") difficulty: str = Field("medium", description="easy, medium, hard") class ClozeGenerateRequest(GenerateRequest): """Request für Lückentext-Generierung.""" num_gaps: int = Field(5, ge=1, le=15, description="Anzahl Lücken") difficulty: str = Field("medium", description="easy, medium, hard") cloze_type: str = Field("fill_in", description="fill_in, drag_drop, dropdown") class MindmapGenerateRequest(GenerateRequest): """Request für Mindmap-Generierung.""" max_depth: int = Field(3, ge=2, le=5, description="Maximale Tiefe") class QuizGenerateRequest(GenerateRequest): """Request für Quiz-Generierung.""" quiz_types: List[str] = Field( ["true_false", "matching"], description="Typen: true_false, matching, sorting, open_ended" ) num_items: int = Field(5, ge=1, le=10, description="Items pro Typ") difficulty: str = Field("medium", description="easy, medium, hard") class BatchGenerateRequest(BaseModel): """Request für Batch-Generierung mehrerer Content-Typen.""" source_text: str = Field(..., min_length=50) content_types: List[str] = Field(..., description="Liste von Content-Typen") topic: Optional[str] = None subject: Optional[str] = None grade_level: Optional[str] = None difficulty: str = "medium" class WorksheetContent(BaseModel): """Generierter Content.""" id: str content_type: str data: Dict[str, Any] h5p_format: Optional[Dict[str, Any]] = None created_at: datetime topic: Optional[str] = None difficulty: Optional[str] = None class GenerateResponse(BaseModel): """Response mit generiertem Content.""" success: bool content: Optional[WorksheetContent] = None error: Optional[str] = None class BatchGenerateResponse(BaseModel): """Response für Batch-Generierung.""" success: bool contents: List[WorksheetContent] = [] errors: List[str] = [] # ============================================================================ # Helper Functions # ============================================================================ def parse_difficulty(difficulty_str: str) -> Difficulty: """Konvertiert String zu Difficulty Enum.""" mapping = { "easy": Difficulty.EASY, "medium": Difficulty.MEDIUM, "hard": Difficulty.HARD } return mapping.get(difficulty_str.lower(), Difficulty.MEDIUM) def parse_cloze_type(type_str: str) -> ClozeType: """Konvertiert String zu ClozeType Enum.""" mapping = { "fill_in": ClozeType.FILL_IN, "drag_drop": ClozeType.DRAG_DROP, "dropdown": ClozeType.DROPDOWN } return mapping.get(type_str.lower(), ClozeType.FILL_IN) def parse_quiz_types(type_strs: List[str]) -> List[QuizType]: """Konvertiert String-Liste zu QuizType Enums.""" mapping = { "true_false": QuizType.TRUE_FALSE, "matching": QuizType.MATCHING, "sorting": QuizType.SORTING, "open_ended": QuizType.OPEN_ENDED } return [mapping.get(t.lower(), QuizType.TRUE_FALSE) for t in type_strs]