feat/adding-h5p-tasks #10

Merged
DrunkenPinguin merged 6 commits from feat/adding-h5p-tasks into main 2026-09-15 13:00:22 +00:00
204 changed files with 5567 additions and 310 deletions
Showing only changes of commit bc166cae62 - Show all commits

105
README.md
View file

@ -13,8 +13,9 @@ Kinder können durch das Lösen von Lernaufgaben, beispielsweise Mathematikaufga
| Feature | Beschreibung |
| :--------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **JWT-Authentifizierung** | Sichere API-Endpunkte für authentifizierte Benutzer über JSON Web Tokens (JWT). |
| **Lernaufgaben (Tasks)** | Abrufen von interaktiven Lernaufgaben mit vordefinierten Antwortmöglichkeiten und Belohnungen in Minuten. |
| **Lernaufgaben (Tasks)** | Abrufen von interaktiven Lernaufgaben mit vordefinierten Antwortmöglichkeiten, Filterung nach Fach und Alter sowie Belohnungen in Minuten. |
| **Antwort-Verifizierung** | Überprüfung der vom Kind ausgewählten Antworten. Bei korrekter Antwort wird die Belohnung direkt auf die verbleibende Bildschirmzeit aufgerechnet. |
| **OER / H5P Ingestion Pipeline** | Automatisierter Live-Crawler und Batch-Import von freien Bildungsinhalten (ZUM.de / H5P) inklusive HTML-Bereinigung und Lizenzattributierung (CC-BY). |
| **Bildschirmzeit-Synchronisation** | Laufender Datenabgleich der verbrauchten Bildschirmzeit. Sinkt die verbleibende Zeit auf oder unter null, wird der Status automatisch auf `isBlocked = true` gesetzt. |
| **Zwei-Ebenen-Speicher** | PostgreSQL als persistente Datenbank, kombiniert mit Redis-Caching für schnelle Screentime-Abfragen. |
| **Fallback-Mechanismus** | Ist Redis nicht erreichbar, fällt das System automatisch und transparent auf PostgreSQL zurück. |
@ -98,7 +99,8 @@ Prüft, ob der Backend-Server ordnungsgemäß läuft.
```json
{
"token": "eyJhbGciOiJIUzI1NiIsIn...",
"familyName": "Familie Schmidt"
"userId": "6380776f-88d3-4e9f-a2be-0d9cacae447e",
"message": "Registrierung erfolgreich"
}
```
@ -128,7 +130,9 @@ Prüft, ob der Backend-Server ordnungsgemäß läuft.
```json
{
"token": "eyJhbGciOiJIUzI1NiIsIn...",
"familyName": "Familie Schmidt"
"userId": "6380776f-88d3-4e9f-a2be-0d9cacae447e",
"familyName": "Familie Schmidt",
"childAge": 8
}
```
@ -156,9 +160,9 @@ Authorization: Bearer <Token>
**Beschreibung:**
Liefert die aktuell verbleibende Bildschirmzeit sowie den aktuellen Sperrstatus.
Liefert die aktuell verbleibende Bildschirmzeit sowie den aktuellen Sperrstatus des authentifizierten Benutzers.
**Antwort:**
**Antwort – `200 OK`:**
```json
{
@ -181,29 +185,28 @@ Liefert die aktuell verbleibende Bildschirmzeit sowie den aktuellen Sperrstatus.
**Beschreibung:**
Zieht die seit dem letzten Abgleich verbrauchten Sekunden von der verfügbaren Bildschirmzeit ab.
Zieht die seit dem letzten Abgleich vom Endgerät verbrauchten Sekunden von der verfügbaren Bildschirmzeit ab.
**Request-Body:**
```json
{
"userId": "default_user",
"usedSecondsSinceLastSync": 200
"usedSecondsSinceLastSync": 30
}
```
**Antwort:**
**Antwort – `200 OK`:**
```json
{
"remainingSeconds": 1600,
"remainingSeconds": 1770,
"isBlocked": false
}
```
---
#### 6. Alle verfügbaren Aufgaben abrufen
#### 6. Lernaufgaben abrufen (mit Fach- & Altersfilter)
**Methode:** `GET`
@ -213,24 +216,42 @@ Zieht die seit dem letzten Abgleich verbrauchten Sekunden von der verfügbaren B
/api/v1/tasks
```
**Optionale Query-Parameter:**
| Parameter | Typ | Standardwert | Beschreibung |
| :--- | :--- | :--- | :--- |
| `subject` | String | `null` | Schulfach (z. B. `Mathematik`, `Deutsch`, `Sachunterricht`, `Englisch`, `Biologie`, `Geographie`, `Geschichte`). |
| `age` | Integer | `null` | Zielalter des Kindes (filtert nach `minAge <= age AND maxAge >= age`). |
| `limit` | Integer | `10` | Maximale Anzahl an zurückgegebenen Aufgaben. |
**Beispiel-Anfrage:**
```text
GET /api/v1/tasks?subject=Mathematik&age=8&limit=5
```
**Beschreibung:**
Liefert eine Liste aller verfügbaren Lernaufgaben.
Liefert kuratierte oder aus OER/H5P importierte Lernaufgaben. Die korrekte Lösung (`correctAnswer`) wird zum Schutz vor Manipulationen serverseitig geheim gehalten und niemals an den Client übertragen.
**Antwort:**
**Antwort – `200 OK`:**
```json
[
{
"id": "t1",
"question": "Was ist 12 + 15?",
"id": "zum-math-001",
"subject": "Mathematik",
"minAge": 8,
"maxAge": 9,
"question": "Was ist das Ergebnis von 6 × 8?",
"options": [
"25",
"27",
"30",
"22"
"42",
"48",
"54",
"56"
],
"rewardMinutes": 10
"rewardMinutes": 5,
"license": "CC BY-SA 4.0"
}
]
```
@ -251,22 +272,22 @@ Liefert eine Liste aller verfügbaren Lernaufgaben.
```json
{
"taskId": "t1",
"selectedAnswer": "27"
"taskId": "zum-math-001",
"selectedAnswer": "48"
}
```
**Antwort – korrekte Lösung:**
**Antwort – korrekte Lösung (`200 OK`):**
```json
{
"isCorrect": true,
"earnedMinutes": 10,
"message": "Super gemacht! Du hast 10 Minuten gewonnen."
"earnedMinutes": 5,
"message": "Super gemacht! Du hast 5 Minuten gewonnen."
}
```
**Antwort – falsche Lösung:**
**Antwort – falsche Lösung (`200 OK`):**
```json
{
@ -278,6 +299,38 @@ Liefert eine Liste aller verfügbaren Lernaufgaben.
---
## H5P / ZUM.de Aufgaben-Import (Standalone CLI)
Das Backend verfügt über ein integriertes CLI-Tool zum automatisierten Importieren und Crawlen interaktiver Lernaufgaben von **ZUM.de / OER (H5P)**.
### Batch-Import ausführen
```bash
# Alle Fächer importieren (z. B. 100 Aufgaben)
./gradlew runIngestion --args="--limit=100"
# Gezielt ein Schulfach importieren (z. B. Mathematik)
./gradlew runIngestion --args="--subject=Mathematik --limit=50"
# Deutsch für Grundschüler importieren
./gradlew runIngestion --args="--subject=Deutsch --limit=30"
```
### CLI-Optionen
| Argument | Standardwert | Beschreibung |
| :--- | :--- | :--- |
| `--subject=<Name>` | *(alle Fächer)* | Filtert Aufgaben nach Fach (z. B. `Mathematik`, `Deutsch`, `Englisch`, `Sachunterricht`). |
| `--limit=<Zahl>` | `50` | Maximale Anzahl an Aufgaben, die im Durchlauf importiert/aktualisiert werden. |
### Funktionsweise der Ingestion-Pipeline
1. **Live-Crawler & Discovery:** Durchsucht `apps.zum.de` nach interaktiven Inhalten (`H5P.MultiChoice`, `H5P.TrueFalse`, `H5P.QuestionSet`).
2. **Textbereinigung:** Entfernt störende HTML-Tags (`<p>`, `<strong>`, `&nbsp;`) für native mobile Darstellung.
3. **Taxonomie- & Alters-Mapping:** Weist Altersgrenzen (`minAge`, `maxAge`) basierend auf Klassenstufen automatisch zu.
4. **Idempotenter Upsert:** Speichert Fragen, Optionen, geheime Lösungen und CC-Lizenzen direkt relational in PostgreSQL (`TasksTable`). Duplikate werden vermieden.
---
## Projektkonfiguration und Umgebungsvariablen
Die Anwendung wird über folgende Konfigurationsdatei konfiguriert:

View file

@ -11,6 +11,12 @@ version = "1.0.0-SNAPSHOT"
application {
mainClass = "io.ktor.server.netty.EngineMain"
}
ktor {
openApi {
enabled = true // Aktiviert die OpenAPI-Code-Generierung
codeInferenceEnabled = true
}
}
kotlin {
jvmToolchain(21)
@ -20,7 +26,7 @@ dependencies {
implementation(ktorLibs.server.config.yaml)
implementation(ktorLibs.server.core)
implementation(ktorLibs.server.netty)
implementation("io.ktor:ktor-server-openapi")
// JWT Authentication
implementation("io.ktor:ktor-server-auth")
implementation("io.ktor:ktor-server-auth-jwt")
@ -46,3 +52,11 @@ dependencies {
// redis
implementation("redis.clients:jedis:5.1.2")
}
tasks.register<JavaExec>("runIngestion") {
group = "application"
description = "Runs the standalone H5P/ZUM task ingestion CLI tool"
mainClass.set("com.oliver.kidio.backend.ingestion.H5PIngestionCli")
classpath = sourceSets["main"].runtimeClasspath
standardInput = System.`in`
}

Some files were not shown because too many files have changed in this diff Show more