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>
112 lines
3.1 KiB
Python
112 lines
3.1 KiB
Python
"""
|
|
Correction API - Pydantic models and enums.
|
|
"""
|
|
|
|
from datetime import datetime
|
|
from typing import List, Dict, Any, Optional
|
|
from enum import Enum
|
|
from pathlib import Path
|
|
|
|
from pydantic import BaseModel, Field
|
|
|
|
|
|
# Upload directory
|
|
UPLOAD_DIR = Path("/tmp/corrections")
|
|
UPLOAD_DIR.mkdir(parents=True, exist_ok=True)
|
|
|
|
|
|
# ============================================================================
|
|
# Enums and Models
|
|
# ============================================================================
|
|
|
|
class CorrectionStatus(str, Enum):
|
|
"""Status einer Korrektur."""
|
|
UPLOADED = "uploaded" # Datei hochgeladen
|
|
PROCESSING = "processing" # OCR laeuft
|
|
OCR_COMPLETE = "ocr_complete" # OCR abgeschlossen
|
|
ANALYZING = "analyzing" # Analyse laeuft
|
|
ANALYZED = "analyzed" # Analyse abgeschlossen
|
|
REVIEWING = "reviewing" # Lehrkraft prueft
|
|
COMPLETED = "completed" # Korrektur abgeschlossen
|
|
ERROR = "error" # Fehler aufgetreten
|
|
|
|
|
|
class AnswerEvaluation(BaseModel):
|
|
"""Bewertung einer einzelnen Antwort."""
|
|
question_number: int
|
|
extracted_text: str
|
|
points_possible: float
|
|
points_awarded: float
|
|
feedback: str
|
|
is_correct: bool
|
|
confidence: float # 0-1, wie sicher die OCR/Analyse ist
|
|
|
|
|
|
class CorrectionCreate(BaseModel):
|
|
"""Request zum Erstellen einer neuen Korrektur."""
|
|
student_id: str
|
|
student_name: str
|
|
class_name: str
|
|
exam_title: str
|
|
subject: str
|
|
max_points: float = Field(default=100.0, ge=0)
|
|
expected_answers: Optional[Dict[str, str]] = None # Musterloesung
|
|
|
|
|
|
class CorrectionUpdate(BaseModel):
|
|
"""Request zum Aktualisieren einer Korrektur."""
|
|
evaluations: Optional[List[AnswerEvaluation]] = None
|
|
total_points: Optional[float] = None
|
|
grade: Optional[str] = None
|
|
teacher_notes: Optional[str] = None
|
|
status: Optional[CorrectionStatus] = None
|
|
|
|
|
|
class Correction(BaseModel):
|
|
"""Eine Korrektur."""
|
|
id: str
|
|
student_id: str
|
|
student_name: str
|
|
class_name: str
|
|
exam_title: str
|
|
subject: str
|
|
max_points: float
|
|
total_points: float = 0.0
|
|
percentage: float = 0.0
|
|
grade: Optional[str] = None
|
|
status: CorrectionStatus
|
|
file_path: Optional[str] = None
|
|
extracted_text: Optional[str] = None
|
|
evaluations: List[AnswerEvaluation] = []
|
|
teacher_notes: Optional[str] = None
|
|
ai_feedback: Optional[str] = None
|
|
created_at: datetime
|
|
updated_at: datetime
|
|
|
|
|
|
class CorrectionResponse(BaseModel):
|
|
"""Response fuer eine Korrektur."""
|
|
success: bool
|
|
correction: Optional[Correction] = None
|
|
error: Optional[str] = None
|
|
|
|
|
|
class OCRResponse(BaseModel):
|
|
"""Response fuer OCR-Ergebnis."""
|
|
success: bool
|
|
extracted_text: Optional[str] = None
|
|
regions: List[Dict[str, Any]] = []
|
|
confidence: float = 0.0
|
|
error: Optional[str] = None
|
|
|
|
|
|
class AnalysisResponse(BaseModel):
|
|
"""Response fuer Analyse-Ergebnis."""
|
|
success: bool
|
|
evaluations: List[AnswerEvaluation] = []
|
|
total_points: float = 0.0
|
|
percentage: float = 0.0
|
|
suggested_grade: Optional[str] = None
|
|
ai_feedback: Optional[str] = None
|
|
error: Optional[str] = None
|