Some checks failed
CI / go-lint (push) Has been skipped
CI / python-lint (push) Has been skipped
CI / nodejs-lint (push) Has been skipped
CI / test-go-school (push) Successful in 27s
CI / test-go-edu-search (push) Successful in 40s
CI / test-python-klausur (push) Failing after 2m30s
CI / test-python-agent-core (push) Successful in 28s
CI / test-nodejs-website (push) Successful in 20s
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
|