Scoring-Logik implementieren
Überblick
Die UebungenAPIEvaluationData Klasse ist eine zentrale Datenstruktur im Hermeneus-Übungssystem, die alle relevanten Daten für die Auswertung einer absolvierten Übung sammelt und verwaltet. Sie implementiert das Composite Pattern und fungiert als Container für drei spezialisierte Datenobjekte.
Zweck und Funktionalität
Diese Klasse konsolidiert alle Ergebnisse einer Übungsauswertung in einem einheitlichen Datencontainer und bietet eine konsistente Schnittstelle für:
- Score-Verwaltung: Berechnung und Speicherung von Punktwerten, Korrektheitsverhältnissen und Gravitas
- Feedback-Generierung: Automatische Erstellung von nutzerfreundlichem Feedback basierend auf der Leistung
- Review-Daten: Detaillierte Aufschlüsselung der Nutzerantworten mit Korrektheitsbewertung
- API-Serialisierung: Einheitliche JSON-Ausgabe für Frontend-Komponenten
Architektur und Design
Komposition
Die Klasse implementiert eine Kompositions-Architektur mit drei Haupt-Datenobjekten:
UebungenAPIEvaluationData
├── UebungenAPIScoreData // Score-Berechnungen und Punktwerte
├── UebungenAPIReviewData // Überprüfte Nutzerantworten (Was war richtig oder falsch?) und Statistiken
└── UebungenAPIFeedbackData // Generiertes NutzerfeedbackAbhängigkeitsmanagement
Die Klasse verwaltet intelligente Abhängigkeiten zwischen ihren Komponenten:
- Feedback ← Score: Feedback-Texte werden automatisch auf Basis der Score-Daten generiert
- Score ← Review: Score-Berechnungen basieren auf Review-Statistiken
- Automatische Synchronisation: Änderungen an Score-Daten lösen Feedback-Neugenerierung aus
Wo können Entwickler einhaken?
Als Entwickler einer neuen Übungsklasse können Sie an zwei zentralen Stellen in die Score-Berechnung eingreifen:
1. Die reviewInput() Methode (PFLICHT)
/**
* Diese Methode MUSS von jeder Übungsklasse implementiert werden
* @param array $input_data Die Nutzerantworten vom Frontend
* @return Collection Collection mit bewerteten Antworten
*/
public function reviewInput(array $input_data): Collection
{
// Ihre Implementierung hier
}2. Die evaluateUebung() Methode (STANDARD-IMPLEMENTIERUNG)
/**
* Diese Methode kann optional überschrieben werden für spezielle Auswertungslogik
* @param Request $request Der Request mit input_data
* @return mixed Meist UebungenAPIEvaluationData
*/
public function evaluateUebung(Request $request = null): mixed
{
// Standard oder eigene Implementierung
}Wie implementiere ich Score-Berechnung in meiner Übungsklasse?
Schritt 1: Evaluable Trait einbinden
<?php
namespace Modules\Uebungen\MeineUebung\app\Models;
use App\Models\UebungBase;
use App\ServiceClasses\Uebungen\UebungenAPI\Traits\PropertyTraits\Evaluable;
class MeineUebung extends UebungBase
{
use Evaluable; // Dieser Trait ist PFLICHT für Score-Berechnung
// Ihre Modellogik...
}Schritt 2: reviewInput() Methode implementieren
/**
* Überprüft Nutzerantworten gegen erwartete Lösungen
* @param array $input_data Nutzerantworten vom Frontend
* @return Collection Bewertete Antworten
*/
public function reviewInput(array $input_data): Collection
{
$InputDataCollection = collect($input_data);
$ContentDataCollection = collect($this->content_data);
return $InputDataCollection->map(function ($inputElement) use ($ContentDataCollection) {
// Finde das entsprechende Content-Element
$contentElement = $ContentDataCollection->firstWhere('value_given', $inputElement['value_given']);
// Bewerte die Antwort
$isCorrect = $this->evaluateAnswer($inputElement, $contentElement);
return [
'value_given' => $contentElement['value_given'],
'value_expected' => $contentElement['value_expected'],
'value_input' => $inputElement['value_input'],
'correct' => $isCorrect, // WICHTIG: 1=korrekt, 0=falsch, null=unbeantwortet
// Weitere Felder nach Bedarf...
];
});
}
/**
* Hilfsmethode für die eigentliche Antwortbewertung
*/
private function evaluateAnswer($inputElement, $contentElement): ?int
{
$userAnswer = $inputElement['value_input'] ?? null;
$expectedAnswer = $contentElement['value_expected'];
// Unbeantwortet?
if ($userAnswer === null || $userAnswer === '') {
return null;
}
// Hier Ihre spezifische Bewertungslogik implementieren:
// Beispiel 1: Einfacher String-Vergleich
return ($userAnswer === $expectedAnswer) ? 1 : 0;
// Beispiel 2: Normalisierter Vergleich
// return (strtolower(trim($userAnswer)) === strtolower(trim($expectedAnswer))) ? 1 : 0;
// Beispiel 3: Array-Vergleich (z.B. für Drag&Drop)
// return (is_array($userAnswer) && $userAnswer === $expectedAnswer) ? 1 : 0;
// Beispiel 4: Teilweise korrekte Antworten
// return $this->calculatePartialCorrectness($userAnswer, $expectedAnswer);
}Schritt 3: Standard evaluateUebung() verwenden ODER überschreiben
Option A: Standard-Implementierung nutzen (empfohlen):
public function evaluateUebung(Request $request = null): mixed
{
// Diese Standard-Implementation führt automatisch durch:
// 1. reviewInput() aufrufen
// 2. Score-Berechnungen
// 3. Feedback-Generierung
// 4. Gravitas vergeben
// 5. AbsolvedRecord speichern
$EvaluationData = $this->getEvaluationData($request->input_data);
$this->rewardUser($EvaluationData);
$this->setAbsolved($EvaluationData);
return $EvaluationData;
}Option B: Eigene Auswertungslogik (für spezielle Fälle):
public function evaluateUebung(Request $request = null): mixed
{
// Eigene Pre-Processing-Logik hier...
// Standard-Evaluation durchführen
$EvaluationData = $this->getEvaluationData($request->input_data, $secondsElapsed);
// Eigene Post-Processing-Logik hier...
// Z.B. Score-Adjustierung basierend auf speziellen Kriterien
if ($this->hasSpecialBonus($request)) {
$adjustedScoreData = $this->applyBonus($EvaluationData->scoreData);
$EvaluationData->setScoreData($adjustedScoreData);
}
// Standard-Aktionen durchführen
$this->rewardUser($EvaluationData);
$this->setAbsolved($EvaluationData);
return $EvaluationData;
}Erweiterte Beispiele: Custom Score-Faktoren
Beispiel: Wiederholungsanzahl in Score-Berechnung einbeziehen
Angenommen, Sie möchten einen Malus-Faktor einbauen, wenn ein Nutzer eine Übung mehrfach wiederholt. Bei jeder Wiederholung soll die erreichbare Score reduziert werden.
public function evaluateUebung(Request $request = null): mixed
{
// Standard-Evaluation durchführen
$EvaluationData = $this->getEvaluationData($request->input_data);
// Anzahl bisheriger Absolvierungen für diesen User und diese Übung zählen
$repetitionCount = $this->getRepetitionCount();
// Malus-Faktor berechnen (z.B. -10% pro Wiederholung, max. -50%)
$repetitionPenalty = min($repetitionCount * 0.1, 0.5);
// Aktuelle Score-Daten holen und anpassen
$scoreData = $EvaluationData->scoreData;
// Option 1: Correct Ratio reduzieren
$adjustedCorrectRatio = $scoreData->score_correct_ratio * (1 - $repetitionPenalty);
$scoreData->setScoreCorrectRatio($adjustedCorrectRatio);
// Option 2: Alternativ - Total Ratio direkt anpassen
// $adjustedTotalRatio = $scoreData->score_total_ratio * (1 - $repetitionPenalty);
// $scoreData->setScoreTotalRatio($adjustedTotalRatio);
// $scoreData->setScoreTotalPoints((int) round($adjustedTotalRatio * 100));
// Gravitas entsprechend neu berechnen
$adjustedGravitas = $scoreData->calculateScoreGravitas($scoreData->score_total_ratio, $this);
$scoreData->setScoreGravitas($adjustedGravitas);
// Aktualisierte Score-Daten setzen (triggert automatische Feedback-Neugenerierung)
$EvaluationData->setScoreData($scoreData);
// Optional: Custom Feedback für Wiederholungen hinzufügen
if ($repetitionCount > 0) {
$customFeedback = "Dies ist dein " . ($repetitionCount + 1) . ". Versuch. " .
"Score wurde um " . ($repetitionPenalty * 100) . "% reduziert.";
$EvaluationData->feedbackData->setGeneralFeedback($customFeedback);
}
// Standard-Aktionen durchführen
$this->rewardUser($EvaluationData);
$this->setAbsolved($EvaluationData);
return $EvaluationData;
}
/**
* Hilfsmethode: Zählt bisherige Absolvierungen dieser Übung für den aktuellen User
*/
private function getRepetitionCount(): int
{
if (!auth()->user()) {
return 0;
}
return DB::table('uebungen_absolved')
->where('user_id', auth()->user()->id)
->where('uebung_id', $this->base_uebung->id)
->count();
}Weitere Custom Score-Faktoren Beispiele
Beispiel: Schwierigkeitsgrad-basierte Boni:
// Bonus für schwierige Übungen
if ($this->difficulty_level >= 4) {
$difficultyBonus = 0.1; // +10% für schwere Übungen
$adjustedTotalRatio = min($scoreData->score_total_ratio * (1 + $difficultyBonus), 1.0);
$scoreData->setScoreTotalRatio($adjustedTotalRatio);
}Beispiel: Zeitbasierte Anpassungen:
// Extra-Bonus für sehr schnelle Bearbeitung
if ($scoreData->score_time_ratio > 1.5) { // 50% schneller als Durchschnitt
$speedBonus = 0.05; // +5% Speed-Bonus
$adjustedCorrectRatio = min($scoreData->score_correct_ratio * (1 + $speedBonus), 1.0);
$scoreData->setScoreCorrectRatio($adjustedCorrectRatio);
}Beispiel: Lernfortschritt-Integration:
// Malus für Nutzer mit hohem Vokabelstand (sollen mehr gefordert werden)
$userVocabLevel = $this->getUserVocabularyLevel();
if ($userVocabLevel > 80) { // Fortgeschrittene Lerner
$expertPenalty = 0.05; // -5% für Fortgeschrittene
$adjustedCorrectRatio = $scoreData->score_correct_ratio * (1 - $expertPenalty);
$scoreData->setScoreCorrectRatio($adjustedCorrectRatio);
}Wichtige Hinweise für Entwickler
Rückgabeformat von reviewInput():
- Muss eine Laravel Collection sein
- Jedes Element MUSS ein
'correct'Feld enthalten - Werte für
'correct':1(korrekt),0(falsch),null(unbeantwortet)
Automatische Score-Berechnung:
- Der
EvaluableTrait berechnet automatisch:score_correct_ratio,score_time_ratio,score_total_ratio,score_gravitas - Basis: Ihre
reviewInput()Ergebnisse und Konfigurationswerte (cfg_max_gravitas,cfg_avg_time_seconds)
- Der
Feedback-Generierung:
- Wird automatisch basierend auf Score-Daten erstellt
- Kann in
UebungenAPIFeedbackDatamanuell angepasst werden
Zeit-Messung:
- Frontend kann
seconds_elapsedmitschicken für Zeit-basierte Bewertung - Wird automatisch in Score-Berechnung einbezogen wenn
cfg_avg_time_secondsgesetzt ist
- Frontend kann
Was passiert automatisch im Hintergrund?
Wenn Sie nur reviewInput() implementieren, übernimmt das System automatisch:
- Review-Statistiken: Zählung korrekter/falscher/unbeantworteter Fragen
- Score-Berechnungen: Korrektheitsverhältnis, Zeitbonus, Gesamtscore, Gravitas
- Feedback-Generierung: Nutzerfreundliche Rückmeldungen basierend auf Leistung
- Datenkonsolidierung: Alles wird in
UebungenAPIEvaluationDataverpackt - JSON-Serialisierung: Frontend-kompatible Ausgabe
Klassen-Referenz
Konstruktor
public function __construct(
UebungenAPIScoreData $scoreData,
UebungenAPIReviewData $reviewData,
UebungenAPIFeedbackData $feedbackData,
?array $config = ['hasGravitas' => true, 'hasTime' => true]
)Parameter:
$scoreData: Objekt mit berechneten Score-Werten (Korrektheit, Zeit, Gesamtscore, Gravitas)$reviewData: Objekt mit überprüften Nutzerantworten und aggregierten Statistiken$feedbackData: Objekt mit generierten Feedback-Texten$config: Konfiguration für Feedback-Features (optional)
Konfigurationsoptionen:
hasGravitas(bool): Aktiviert/deaktiviert Gravitas-bezogenes FeedbackhasTime(bool): Aktiviert/deaktiviert Zeit-bezogenes Feedback
Öffentliche Methoden
setScoreData()
public function setScoreData(UebungenAPIScoreData $scoreData): staticAktualisiert die Score-Daten und triggert automatisch die Neugenerierung aller abhängigen Feedback-Texte.
Verwendung:
$evaluationData->setScoreData($newScoreData);
// Feedback wird automatisch neu generiertjsonSerialize() / toArray()
public function jsonSerialize(): array
public function toArray(): arraySerialisiert alle Evaluationsdaten in ein strukturiertes Array für JSON-Ausgabe.
Ausgabestruktur:
[
'feedbackData' => [
'generalFeedback' => '...',
'correctnessFeedback' => '...',
'timeFeedback' => '...',
'pointsFeedback' => '...',
'gravitasFeedback' => '...'
],
'scoreData' => [
'score_correct_ratio' => 0.85,
'score_time_ratio' => 1.1,
'score_total_ratio' => 0.94,
'score_total_points' => 94,
'score_gravitas' => 8
],
'reviewData' => [
'ReviewedInputData' => Collection,
'ReviewStats' => [...]
],
'config' => [
'hasGravitas' => true,
'hasTime' => true
]
]Abhängige Datenobjekte im Detail
UebungenAPIScoreData
Verwaltet alle score-relevanten Berechnungen:
Eigenschaften:
score_correct_ratio: Verhältnis korrekter Antworten (0.0 - 1.0)score_time_ratio: Zeit-Faktor basierend auf Bearbeitungsgeschwindigkeitscore_total_ratio: Gesamtbewertung als Verhältnisscore_total_points: Gesamtpunkte (total_ratio × 100)score_gravitas: Erreichte Gravitas-Punkte
Wichtige Methoden:
calculateScores(): Berechnet alle Score-WertecalculateCorrectRatio(): Ermittelt KorrektheitsverhältniscalculateScoreGravitas(): Berechnet Gravitas basierend auf Gesamtscore
UebungenAPIReviewData
Enthält detaillierte Analyse der Nutzerantworten:
Eigenschaften:
ReviewedInputData: Collection mit bewerteten EinzelantwortenReviewStats: Aggregierte Statistiken
Review-Statistiken:
'ReviewStats' => [
'total_answers' => 10,
'total_answers_correct' => 7,
'total_answers_semi_correct' => 1,
'total_answers_incorrect' => 2,
'total_answers_unanswered' => 0
]UebungenAPIFeedbackData
Generiert nutzerfreundliche Feedback-Texte:
Feedback-Kategorien:
generalFeedback: Allgemeine Bewertung der LeistungcorrectnessFeedback: Feedback zur inhaltlichen KorrektheittimeFeedback: Bewertung der Bearbeitungszeit (falls aktiviert)pointsFeedback: Feedback zu erreichten PunktengravitasFeedback: Feedback zu Gravitas-Punkten (falls aktiviert)
Automatische Generierung: Das Feedback wird basierend auf Score-Daten automatisch generiert und kann bei Bedarf manuell überschrieben werden.
Verwendungsszenarien
Standard-Auswertung
// Erstellung der Evaluationsdaten nach Übungsabsolvierung
$scoreData = new UebungenAPIScoreData($reviewData);
$scoreData->calculateScores($uebungModel, $secondsElapsed);
$feedbackData = new UebungenAPIFeedbackData($scoreData, true, true);
$evaluationData = new UebungenAPIEvaluationData(
$scoreData,
$reviewData,
$feedbackData
);
// Direkte JSON-Ausgabe für API-Response
return response()->json($evaluationData);Score-Aktualisierung
// Nachträgliche Score-Anpassung
$newScoreData = $scoreData->setScoreCorrectRatio(0.9);
$evaluationData->setScoreData($newScoreData);
// Feedback wird automatisch neu generiertKonfigurierte Feedback-Optionen
// Evaluation ohne Zeit-Feedback für zeitunabhängige Übungen
$config = ['hasGravitas' => true, 'hasTime' => false];
$evaluationData = new UebungenAPIEvaluationData(
$scoreData,
$reviewData,
$feedbackData,
$config
);Integration in die UebungenAPI
Die Klasse ist integraler Bestandteil des Evaluable Trait-Systems:
- Auswertungsprozess: Das spezifische Übungsmodel implementiert
evaluateUebung() - Datensammlung: Score-, Review- und Feedback-Daten werden erstellt
- Konsolidierung:
UebungenAPIEvaluationDatasammelt alle Teilergebnisse - API-Response: Einheitliche JSON-Struktur für Frontend-Komponenten