docs: document learning tasks phase 10a in ADR-0021, roadmap, architecture and dashboard ADR
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
d1ff7dd291
commit
8fb34ba6b9
4 files changed
+94
-7
No files matched your search
@@ -87,6 +87,7 @@ Alle Zeitpunkte werden als UTC (`DateTimeOffset`/`DateTime` UTC) gespeichert und
|
||||
| Kalender ✅ | `FamilyCalendar` (Name, Color, IsDefault, Soft Delete), `CalendarPermission` (Rolle **oder** Benutzer → None/Read/WriteOwn/Write), `CalendarEvent` (Title, Location, Notes, IsAllDay, StartUtc, EndUtc, TimeZoneId, RecurrenceRule, ExceptionDates, Uid, PersonIds, ForWholeFamily, Sequence, RowVersion, Soft Delete; Overrides als eigene Zeile mit `SeriesMasterId` + `RecurrenceId`), `IcsFeed` (Owner, Scope, CalendarId, TaskMode, TokenHash, TokenPrefix, LastAccessAt, RevokedAt) – ADR-0015/0016 |
|
||||
| KI ✅ | `AiProviderConfig` (Name, Type Ollama/Claude/OpenAiCompatible, BaseUrl, Model, ApiKeyProtected, TimeoutSeconds, IsActive, AllowImages, Purposes, DailyLimitPerUser, RowVersion, Soft Delete), `AiUsage` (Person, Anbieter, Zweck, Dauer, Tokens, Erfolg/Fehlerart – ohne Inhalt) – ADR-0020 |
|
||||
| Chat ✅ | `ChatChannel` (Family / Direct), `ChatMember` (LastReadAt), `ChatMessage` (Text, HasImage), `ChatAttachment`, `ChatReaction` |
|
||||
| Lernen ✅ (10a) | `LearningSet` (Titel, Fach Mathe/Deutsch, Klassenstufe 1–6, Zielkind, Fälligkeit, Status, Modus Übung/Prüfung, MaxAttempts, TimeLimitMinutes, ShowSolutionsAfterSubmit, ShuffleItems, TotalPoints, GradeThresholds, Source Manual/Ai + AiPrompt/AiProvider/AiModel für 10b, RowVersion, Soft Delete), `LearningItem` (Frage, Antworttyp Number/Text/SingleChoice, Paper vorgesehen, CorrectAnswer, NumberTolerance, Options, Hint, Explanation, Difficulty, Points, RowVersion, Soft Delete), `LearningAttempt` (Nummer, Status, StartedAt, DeadlineAt, SubmittedAt, AutoSubmitted, ItemOrder, Ergebnis/Note, RowVersion), `LearningAnswer` (Antwort, Verdict Open/Correct/Partial/Wrong, Grader Auto/Ai/Parent, AwardedPoints, Reason); `PointsLedgerEntry.LearningSetId` – ADR-0021 |
|
||||
| Betrieb | `AuditLogEntry` ✅ (ActorName, Action, TargetType/Id/Name, Details, CreatedAt), `PushSubscription` ✅ (UserId, Endpoint + Hash, P256dh, Auth, LastSuccessAt, FailureCount) |
|
||||
|
||||
## 4. Rollen- und Berechtigungsmodell
|
||||
@@ -114,6 +115,8 @@ oder **None (–)**. Die Api registriert je Permission eine Policy `Permission:<
|
||||
| `FamilyChat` | F | F | F | – ² | |
|
||||
| `DirectMessages` | F | F | R | – | nur an Familienmitglieder |
|
||||
| `AiUse` | F | F | – | – | KI-Funktionen nutzen (ADR-0020) |
|
||||
| `LearningManage` | F | F | – | – | Übungsblätter anlegen/zuweisen/prüfen/bestätigen (ADR-0021) |
|
||||
| `LearningSolve` | F | F | R | – | Kind: nur eigene, zugewiesene Blätter lösen; fremde → 404 (ADR-0021) |
|
||||
| `UserManagement`, `CalendarManagement`, `SettingsManagement`, `AuditLogView` | F | – | – | – | |
|
||||
|
||||
¹ `F`, wenn „Gäste dürfen die Einkaufsliste ergänzen/abhaken“ aktiviert ist. ² `F`, wenn „Gäste dürfen den Familienchat nutzen“ aktiviert ist.
|
||||
@@ -153,8 +156,9 @@ Das UI bekommt die wirksamen Berechtigungen über `/api/auth/me` und blendet anh
|
||||
| ICS-Feed | `GET /ics/{token}.ics` (öffentlich, Token-gesichert, ETag/Last-Modified) |
|
||||
| Chat ✅ | `GET /api/chat/channels`, `POST /api/chat/direct`, `GET /api/chat/channels/{id}/messages?before=&take=`, `POST …/messages`, `POST …/images` (Multipart), `POST …/read`, `DELETE /api/chat/messages/{id}`, `PUT /api/chat/messages/{id}/reactions`, `GET /api/chat/attachments/{id}` (ADR-0019) |
|
||||
| KI ✅ | Admin: `GET/POST /api/admin/ai/providers`, `PUT/DELETE …/{id}`, `POST …/{id}/test`, `GET /api/admin/ai/usage`; Eltern: `GET /api/ai/status` (ADR-0020) |
|
||||
| Lernen ✅ (10a) | Eltern (`LearningManage`): `GET/POST /api/learning/sets`, `GET/PUT/DELETE …/sets/{id}`, `POST …/sets/{id}/assign`, `POST …/unassign`, `POST …/sets/{id}/items`, `PUT/DELETE …/items/{itemId}`, `POST …/items/order`, `GET /api/learning/review`, `GET /api/learning/attempts/{id}`, `PUT …/attempts/{id}/answers/{itemId}/review`, `POST …/attempts/{id}/confirm`, `POST …/attempts/{id}/reopen`; Kinder (`LearningSolve`): `GET /api/learning/my`, `POST …/my/{setId}/attempts`, `GET …/my/attempts/{id}`, `PUT …/my/attempts/{id}/answers/{itemId}`, `POST …/my/attempts/{id}/submit` (ADR-0021) |
|
||||
| Dashboard ✅ | `GET /api/dashboard` (alle Kacheln der Rolle in einem Request, ADR-0018) |
|
||||
| Hubs | `/hubs/live` (Live-Updates: Einkauf ✅, Essenplan ✅, Aufgaben ✅, Termine ✅, Chat ✅ inkl. Hub-Methode `Typing`; das Dashboard lädt bei diesen Ereignissen neu) |
|
||||
| Hubs | `/hubs/live` (Live-Updates: Einkauf ✅, Essenplan ✅, Aufgaben ✅, Termine ✅, Chat ✅ inkl. Hub-Methode `Typing`, Lernen ✅ (`LearningChanged` ohne Inhalte); das Dashboard lädt bei diesen Ereignissen neu) |
|
||||
| Betrieb | `/health`, `/alive` |
|
||||
|
||||
## 7. Frontend
|
||||
@@ -173,6 +177,7 @@ SignalR-Hub `/hubs/live` in der Api, vom Web-Host per YARP (WebSockets) durchger
|
||||
`family` (ohne Gäste), `user:{id}`. Der Chat nutzt keine Kanal-Gruppen, sondern sendet an die `user:{id}` der jeweils aktuell Berechtigten (ADR-0019). Slices senden nach dem Speichern über `IHubContext<LiveHub>`
|
||||
Ereignisse mit dem vollständigen DTO (z. B. `ShoppingItemChanged`), die Clients aktualisieren gezielt ihre Ansicht.
|
||||
Aufgaben gehen wegen privater Aufgaben nur an `user:{id}` der Benutzer, die sie sehen dürfen (`TaskChanged`/`TaskRemoved`, ADR-0014).
|
||||
Lern-Ereignisse (`LearningChanged(setId, kind)`) enthalten **keine Inhalte** und gehen nur an die Zielperson und alle Eltern (`user:{id}`, `LearningNotifier`, ADR-0021); die Clients laden über die geschützten Endpunkte nach.
|
||||
Der Client (`LiveConnection`) verbindet sich mit unbegrenzten Wiederholungen neu und lädt danach den aktuellen Stand.
|
||||
|
||||
## 8a. Offline
|
||||
|
||||
+10
-4
@@ -118,10 +118,16 @@ Legende: `[x]` erledigt, `[ ]` offen. Nach jeder Phase: Build ohne Warnungen, Te
|
||||
- [x] Tests: Unit (Adressen/Heimnetz/Schlüsselpflicht/Limits/Zwecke/Validator, Adapter gegen Fake-Handler inkl. Fehlerübersetzung und JSON-Extraktion), bUnit (Verwaltung, Dialog, Test, Nutzung, Löschen), Integration (Rechte, Validierung, Schlüsselschutz, Zweck-Übernahme, Verbindungstest gegen Fake-Anbieter inkl. Timeout, OpenAI-Format, Tageslimit + Protokoll)
|
||||
|
||||
## Phase 10 – Lernaufgaben (ADR-0021)
|
||||
- [ ] 10a: Übungsblätter manuell anlegen/zuweisen, Kind löst digital (Zahl/Auswahl/Text), automatische Bewertung ohne KI, Elternprüfung, Kinderansicht, Dashboard-Kachel, optional Punkte über das Punktebuch
|
||||
- [ ] 10b: KI-Erzeugung per Prompt (z. B. „20 Aufgaben Mathe, 3. Klasse, leicht bis schwer“) als Entwurf, Eltern prüfen/ändern vor dem Zuweisen, Mathe-Lösungen serverseitig nachrechnen
|
||||
- [ ] 10c: Papierlösung per Foto (Upload je Aufgabe/Blatt), Prüfung manuell durch Eltern, danach KI-Prüfung mit Sicherheitsangabe und Eltern-Bestätigung
|
||||
- [ ] Rechte `LearningManage`/`LearningSolve`: Kinder sehen nur eigene Blätter, nie Musterlösungen oder Prompts (serverseitig); Foto-Aufbewahrungsfrist
|
||||
- [x] 10a: Übungsblätter manuell anlegen/zuweisen (Entwurf → Zugewiesen → In Arbeit → Abgegeben → Geprüft), Editor für Blatt und Aufgaben (Zahl/Text/Auswahl, Hinweis, Erklärung, Schwierigkeit, Punkte), Versionsprüfung (409), Bearbeitungssperre nach dem ersten Versuch; Migration `Phase10aLearning`
|
||||
- [x] 10a: Kind löst digital (eigene Blätter, Versuch starten/fortsetzen, Antworten zustandsbasiert speichern, Fortschritt, Abgabe-Bestätigung, Ergebnis mit Lösungen nur nach Regel), automatische Bewertung ohne KI (Zahlenformate mit Komma/Punkt/Tausender, Toleranz, Auswahl, Freitext exakt oder offen), Elternprüfung (Warteschlange, Korrektur, Teilpunkte, Begründung, Bestätigen, erneut öffnen)
|
||||
- [x] 10a: Wiederholen (`MaxAttempts`, 0 = unbegrenzt), Zeitlimit serverseitig (Frist in der Datenbank, 10 s Toleranz, 409 bei späten Speicherungen, automatische Abgabe lazy und per Hintergrunddienst), Prüfungsmodus (keine Sofort-Rückmeldung/Hinweise/Lösungen bis zur Abgabe, optional gemischt und stabil je Versuch, Countdown nach Serveruhr, Auto-Abgabe), Note nach Notenschlüssel
|
||||
- [x] 10a: Punkte über das Punktebuch (anteilig, beste Wertung zählt einmal, Differenz wird gebucht, Rückbuchung beim erneuten Öffnen, Audit, Live `PointsChanged`), Dashboard-Kachel „Lernen“ (Kind: offene Blätter, Eltern: zu prüfen), Live `LearningChanged` nur an Zielperson und Eltern
|
||||
- [x] 10a: Rechte `LearningManage`/`LearningSolve` in der Matrix (Kinder nur eigene Blätter, fremde → 404, nie Musterlösung/Hinweis/Prompt vorab; serverseitig erzwungen), Navigation „Lernen“, Seiten und Komponenten (mobil, Touch-Ziele, ARIA)
|
||||
- [x] 10a: Tests: Unit (Zahlenformate, Auto-Bewertung, Zeitlimit, Wiederholen, Punkte-Differenz, Noten, Prüfungsregeln, Kinder-DTO-Sichtbarkeit, Matrix, Validatoren), bUnit (Kinderansicht, Prüfungs-Runner mit steuerbarer Uhr, Elternansicht, Editor, Prüfung, Rechte, Dashboard-Kachel), Integration (Rechte je Rolle inkl. 404, Lösungen-Leck, Auto-Bewertung, Zeitlimit-409 mit echtem Warten, Wiederholungen, Punkte-Workflow inkl. Rückbuchung, Live nur an Berechtigte)
|
||||
- [ ] 10a offen: „Aufgaben aus früheren Blättern wiederverwenden“, Verknüpfung eines Blatts mit einer Familienaufgabe/einem Ämtchen, Standard-Wiederholungen als Familieneinstellung (aktuell Voreinstellung im Editor)
|
||||
- [ ] 10b: KI-Erzeugung per Prompt (z. B. „20 Aufgaben Mathe, 3. Klasse, leicht bis schwer“) als Entwurf, Eltern prüfen/ändern vor dem Zuweisen, Mathe-Lösungen serverseitig nachrechnen (Spalten für Herkunft/Prompt/Anbieter/Modell am Blatt sind vorhanden)
|
||||
- [ ] 10c: Papierlösung per Foto (Upload je Aufgabe/Blatt), Prüfung manuell durch Eltern, danach KI-Prüfung mit Sicherheitsangabe und Eltern-Bestätigung (`LearningAnswerType.Paper`, `LearningGrader.Ai` sind als Werte vorgesehen)
|
||||
- [ ] Foto-Aufbewahrungsfrist (Standard 30 Tage nach Prüfung, einstellbar) – mit 10c
|
||||
|
||||
## Phase 11 – Härtung
|
||||
- [ ] Content-Security-Policy (Basis-Header X-Content-Type-Options, X-Frame-Options, Referrer-Policy, Permissions-Policy, HSTS sind seit Phase 1 aktiv)
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* Datum: 2026-10-10
|
||||
|
||||
## Kontext
|
||||
Die Startseite zeigt Kacheln aus fünf Fachbereichen (Essenplan, Kalender, Einkauf, Aufgaben, Chat). Rollen sehen unterschiedliche
|
||||
Die Startseite zeigt Kacheln aus sechs Fachbereichen (Essenplan, Kalender, Einkauf, Aufgaben, Chat, Lernen). Rollen sehen unterschiedliche
|
||||
Kacheln („Gast: eingeschränkte Kacheln“, Familien-/Kinderaufgaben nur für Eltern). Auf dem Smartphone zählen wenige Requests.
|
||||
|
||||
## Entscheidung
|
||||
@@ -25,6 +25,9 @@ Kacheln („Gast: eingeschränkte Kacheln“, Familien-/Kinderaufgaben nur für
|
||||
6. **Offline**: Bei Fehlern bleibt der zuletzt geladene Stand mit Hinweis sichtbar; ohne Stand gibt es „Erneut versuchen“.
|
||||
7. **Chat** (Phase 8, ADR-0019): Die Kachel erscheint für Rollen mit Chat-Rechten und zeigt die Summe der ungelesenen Nachrichten über alle sichtbaren Kanäle
|
||||
(`ChatAccessService.TotalUnreadAsync`); die Seite lädt bei Chat-Ereignissen (neue Nachricht, gelöscht, gelesen) neu.
|
||||
8. **Lernen** (Phase 10a, ADR-0021): `DashboardDto.Learning` (letzter Konstruktorparameter, standardmäßig `null`). Eltern (`LearningManage`) sehen die Zahl der abgegebenen, noch nicht bestätigten Versuche und die offenen Blätter der Kinder, die ältesten
|
||||
Abgaben (höchstens fünf) verlinken direkt auf die Prüfung; Kinder sehen ihre offenen Blätter (zugewiesen oder in Arbeit) mit Fälligkeit, ein laufender Versuch verlinkt auf „Weitermachen“. Gäste und Rollen ohne Recht erhalten keine Kachel. Die Seite lädt
|
||||
bei `LearningChanged` neu (ohne Inhalte, nur an Zielperson und Eltern).
|
||||
|
||||
## Folgen
|
||||
* Ein Request je Seitenaufruf; Kosten wachsen mit der Familiengröße, nicht mit der Datenmenge (Aufgaben: nicht erledigte, Termine: zwei Tage).
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# ADR-0021: Lernaufgaben – manuell oder per KI, digital oder auf Papier
|
||||
|
||||
* Status: akzeptiert (Phase 10; Entscheidungen der Rückfragen am 2026-10-10 eingearbeitet)
|
||||
* Status: akzeptiert (Phase 10; Entscheidungen der Rückfragen am 2026-10-10 eingearbeitet) – **Phase 10a umgesetzt** (Abschnitt „Umsetzung Phase 10a“), 10b und 10c offen
|
||||
* Datum: 2026-10-10
|
||||
|
||||
## Kontext
|
||||
@@ -60,6 +60,79 @@ Lernaufgaben sind **kein** Teil der Familienaufgaben (ADR-0014): eigene Entität
|
||||
Papier-Prüfungen: Foto-Abgabe innerhalb des Zeitfensters.
|
||||
Im Übungsmodus (`Practice`) gibt es Sofort-Rückmeldung und Hinweise.
|
||||
|
||||
## Umsetzung Phase 10a (2026-10-10)
|
||||
|
||||
Phase 10a liefert manuell erstellte Übungsblätter, digitales Lösen, automatische Bewertung, Elternprüfung, Punkte und den Prüfungsmodus – **ohne KI (10b) und ohne Foto/Papier (10c)**.
|
||||
Migration `Phase10aLearning`. Reine Regeln liegen in `FamilyPlanner.Domain/Learning` (identisch in Api und Client), der Slice in `Api/Features/Learning`, DTOs und Validatoren in `Shared/Learning`,
|
||||
die Oberfläche in `Web.Client/Components/Learning` und `Pages/Learning*.razor`.
|
||||
|
||||
### Modell
|
||||
* `LearningSet` (Soft Delete, `RowVersion`): Titel, Fach als Text aus `LearningSubjects` (Mathe, Deutsch), Klassenstufe 1–6, `TargetUserId` (Rolle Kind, bloße Id ohne Fremdschlüssel wie bei Aufgaben), `DueDate`,
|
||||
`Status` (Entwurf → Zugewiesen → In Arbeit → Abgegeben → Geprüft), `Mode` (`Practice`/`Exam`), `MaxAttempts` (0 = unbegrenzt), `TimeLimitMinutes` (`null` = keins), `ShowSolutionsAfterSubmit`, `ShuffleItems`,
|
||||
`TotalPoints` (0 = keine Punkte), `GradeThresholds` (Notenschlüssel, `null` = Standard), `Source` (`Manual`|`Ai`) sowie `AiPrompt`/`AiProvider`/`AiModel` (**für 10b schon angelegt**, vom Client nicht setzbar),
|
||||
`AssignedAt`, `ItemsRevision` (Zähler, damit Aufgabenänderungen und ein gleichzeitiger Versuchsstart über die `RowVersion` des Blatts kollidieren).
|
||||
* `LearningItem` (Soft Delete, `RowVersion`): `SortOrder`, `Question`, `AnswerType` (`Number`, `Text`, `SingleChoice`; `Paper` nur als Enum-Wert, der Validator lehnt ihn in 10a ab), `CorrectAnswer`
|
||||
(Zahl, Text – Varianten mit `|` – oder Index der richtigen Option), `NumberTolerance` (absolut), `Options` (2–6, JSON-Liste), `Hint` und `Explanation` (zwei Felder statt „Hinweis/Erklärung“), `Difficulty` 1–3, `Points` 1–20.
|
||||
* `LearningAttempt` (`RowVersion`): `Number`, `Status` (Läuft/Abgegeben/Bestätigt), `StartedAt`, `DeadlineAt`, `LastActivityAt`, `SubmittedAt`, `AutoSubmitted`, `ItemOrder` (Aufgaben-Ids dieses Versuchs, ggf. gemischt),
|
||||
`ReviewedAt/By`, `EarnedPoints`, `TotalItemPoints`, `Grade`, `ReviewNote`. `LearningAnswer`: `Value`, `Verdict` (`Open`/`Correct`/`Partial`/`Wrong`), `Grader` (`Auto`/`Ai`/`Parent`), `AwardedPoints`, `Reason`.
|
||||
Eindeutige Indizes: (Blatt, Kind, Nummer) und **höchstens ein laufender Versuch** je Blatt und Kind (gefiltert auf `InProgress`) – Doppelklick oder zwei Tabs können weder `MaxAttempts` umgehen noch die Prüfungsuhr zurücksetzen.
|
||||
`LearningAnswer.ItemId` ist bewusst keine Beziehung (SQL Server erlaubt keine zweiten Kaskadenpfade; Aufgaben ändern sich nach dem ersten Versuch nicht mehr).
|
||||
* `PointsLedgerEntry.LearningSetId` (neu, nullable): Buchungen zu einem Blatt; der Punktestand bleibt die Summe des Punktebuchs.
|
||||
|
||||
### Regeln (alle unit-getestet)
|
||||
* **Auto-Bewertung** (`LearningGrading`): Zahlen werden kulturunabhängig gelesen (Komma/Punkt als Dezimalzeichen, Punkt/Komma/Leerzeichen als Tausendertrenner, Unicode-Minus); „1.234“ ist mehrdeutig und passt, wenn
|
||||
**eine** Lesart zur Musterlösung passt; Toleranz absolut; Brüche („1/2“) werden **nicht** erkannt (→ falsch, Eltern können korrigieren). Auswahl vergleicht den Index. Freitext ist nur bei **exakter Übereinstimmung nach Normalisierung**
|
||||
(Unicode, Leerraum, Groß/Klein, Randzeichen, Varianten mit `|`) automatisch richtig, sonst `Open` für die Elternprüfung – nie automatisch falsch. Leere Antworten sind immer falsch.
|
||||
* **Zeitlimit serverseitig** (`LearningRules`): `DeadlineAt` = Start + Limit wird beim Start in der Datenbank festgelegt. Speicherungen gelten bis **Frist + 10 s Toleranz**; danach antwortet die Api mit **409**, der Versuch wird automatisch
|
||||
abgegeben (`SubmittedAt` = Frist, `AutoSubmitted`), nur zuvor gespeicherte Antworten zählen. Die Abgabe selbst ist idempotent und nie ein 409. Automatische Abgabe passiert **lazy** bei jedem Zugriff (Kind: Liste/Versuch/Speichern/Starten,
|
||||
Eltern: Liste/Warteschlange/Versuch) und per Hintergrunddienst `LearningExpiryService` (alle 30 s), damit verlassene Prüfungen in der Warteschlange landen. Der Client rechnet den Countdown aus `DeadlineAt` und dem Uhrenabgleich (`ServerNow`),
|
||||
nicht aus der Geräteuhr.
|
||||
* **Sichtbarkeit** (`LearningRules.VisibilityFor`, einzige Quelle für Kinder-DTOs): Übung – Hinweise und Sofort-Rückmeldung (nur richtig/falsch/offen, **nie** die Lösung) während der Bearbeitung; Prüfung – während der Bearbeitung **nichts**
|
||||
(Speicherantwort ohne Bewertung, kein Hinweis); nach der Abgabe immer die Bewertung, die Lösung samt Erklärung nur bei „Lösungen nach Abgabe zeigen“, Hinweise nur in der Übung. Kinder-DTOs sind eigene Typen ohne Felder für Prompt, Anbieter
|
||||
oder Modell; `CorrectAnswer`/`Explanation` stehen nur im optionalen `Feedback`. Kommentare der Eltern erreichen das Kind erst nach der Abgabe, Meldungen der Automatik nie als „Kommentar“.
|
||||
* **Reihenfolge:** gemischt wird deterministisch aus SHA-256 von Versuchs- und Aufgaben-Id (`string.GetHashCode` wäre je Prozess zufällig) und in `ItemOrder` gespeichert – stabil je Versuch, zwischen Versuchen wechselnd.
|
||||
* **Status** wird aus den Versuchen abgeleitet (`DeriveStatus`): läuft einer → In Arbeit, sonst wartet einer → Abgegeben, sonst bestätigt → Geprüft, sonst Zugewiesen.
|
||||
* **Elternprüfung:** Antworten bewerten (`Correct`/`Partial`/`Wrong`, Teilpunkte 1 bis Aufgabenpunkte − 1, Begründung), auch die der Automatik korrigieren; **Bestätigen** erst ohne offene Antworten (409). Auch vollautomatisch bewertete Blätter
|
||||
werden bestätigt – erst dann gibt es Punkte und Note. „Erneut öffnen“ macht den Versuch wieder prüfbar.
|
||||
* **Punkte:** Anteil = erreichte Aufgabenpunkte / mögliche; Gutschrift = **beste bestätigte Wertung** × `TotalPoints`, kaufmännisch auf ganze Punkte gerundet (halbe aufwärts, reine Ganzzahlrechnung). Gebucht wird nur die **Differenz zum bisher für das
|
||||
Blatt gebuchten Stand** (`SyncPointsAsync`): Gutschrift, Verbesserung oder Rückbuchung – dadurch idempotent (zweimal bestätigen bucht nichts), und Erneut-Öffnen fällt auf die nächstbeste Wertung zurück. Audit-Einträge
|
||||
`learning.points_credited`/`learning.points_reversed`, Live-Ereignis `TaskPointsChanged` an die Familie. Ist `ChorePointsEnabled` aus, wird nichts gebucht. Das Löschen eines Blatts lässt bereits gutgeschriebene Punkte bestehen (wie bei Ämtchen,
|
||||
ADR-0014); Korrekturen über die Punkteverwaltung.
|
||||
* **Note** (nur Prüfungen, nach Bestätigung): Schwellen für die Noten 1–5 in Prozent, Standard `92;81;67;50;30`, darunter 6 (ganzzahliger Vergleich ohne Rundungsfehler); einstellbar je Blatt, streng absteigend.
|
||||
* **Bearbeitungssperre:** Aufgaben lassen sich nur ändern, solange es keinen Versuch gibt; danach sind auch Kind, Modus, Mischen, Gesamtpunkte und Notenschlüssel fest (409). Titel, Fälligkeit, Zeitlimit, Versuche und „Lösungen zeigen“ bleiben änderbar.
|
||||
|
||||
### Rechte
|
||||
`LearningManage` (Admin F, Familie F, Kind –, Gast –) und `LearningSolve` (Admin F, Familie F, Kind R, Gast –). Blätter lassen sich nur **Kindern** zuweisen; gelöst wird ausschließlich von der Zielperson (`LearningRules.CanSolve`) – auch Eltern lösen
|
||||
nicht für andere: fremde Blätter und Versuche antworten mit **404**, Entwürfe sind für das Zielkind unsichtbar. Kinder auf Verwaltungsendpunkten und Gäste überall erhalten 403 (Policy). Objektbezogene Prüfungen im Slice, nie nur im UI.
|
||||
|
||||
### Schnittstellen und Oberfläche
|
||||
* Eltern (`/api/learning`): `GET/POST /sets` (POST optional mit `Items`), `GET/PUT/DELETE /sets/{id}`, `POST …/assign`, `POST …/unassign`, `POST …/items`, `PUT/DELETE …/items/{itemId}`, `POST …/items/order`, `GET /review` (Warteschlange),
|
||||
`GET /attempts/{id}`, `PUT /attempts/{id}/answers/{itemId}/review`, `POST …/confirm`, `POST …/reopen`. Versionsprüfung mit 409 und aktuellem Stand bei Blatt und Aufgabe.
|
||||
* Kinder (`/api/learning/my`): `GET /`, `POST /{setId}/attempts` (startet oder setzt fort), `GET /attempts/{id}`, `PUT /attempts/{id}/answers/{itemId}` (zustandsbasiert, idempotent, 409 bei abgegeben/abgelaufen), `POST /attempts/{id}/submit`.
|
||||
* Live: `LearningChanged(setId, kind)` **ohne Inhalte** an `user:{id}` der Zielperson und aller Eltern (`LearningNotifier`); Clients laden über die geschützten Endpunkte nach. Dashboard: Kachel „Lernen“ (`DashboardDto.Learning`).
|
||||
* UI: Navigation „Lernen“ (Admin/Familie/Kind), Routen `/lernen`, `/lernen/neu`, `/lernen/blatt/{id}`, `/lernen/versuch/{id}`, `/lernen/pruefen/{id}`. Kind: Karten, **Prüfungs-Runner** (`AttemptRunner`) mit Countdown, Fortschritt,
|
||||
Aufgaben-Navigation, serialisiertem Speichern, Abgabe-Bestätigung und Auto-Abgabe (Wiederholung bei Netzfehlern); Eltern: Übersicht, Editor (`SetEditor`, `ItemEditDialog`), Prüfung (`AttemptReview`).
|
||||
|
||||
### Abweichungen und bewusste Vereinfachungen
|
||||
* **Standard-Wiederholungen** sind eine Voreinstellung im Editor (Übung: unbegrenzt, Prüfung: 1 Versuch ohne Lösungen), keine Familieneinstellung – das hätte DTO, Validator, Verwaltung und Tests berührt.
|
||||
* Kein eigenes Feld „Schwierigkeitsverlauf“ am Blatt (ergibt sich aus den Schwierigkeiten der Aufgaben; relevant für den Prompt in 10b). Keine Verknüpfung mit einer Familienaufgabe/einem Ämtchen: Punkte laufen direkt über das Punktebuch. „Aufgaben aus früheren Blättern
|
||||
wiederverwenden“ ist nicht umgesetzt.
|
||||
* Die Elternbestätigung ist immer nötig (auch bei vollautomatischer Bewertung); Punkte und Note gibt es erst danach, das Kind sieht bis dahin ein vorläufiges Ergebnis.
|
||||
* Sofort-Rückmeldung in der Übung bedeutet: Das Kind kann eine Antwort ändern, bis es abgibt; gewertet wird der letzte Stand. Die Übung ist ein Lernrahmen, keine Prüfung.
|
||||
* Das Zeitlimit hat mindestens 1 Minute; die Toleranz (10 s) ist fest.
|
||||
|
||||
### Erweiterungspunkte für 10b (KI-Erzeugung)
|
||||
* Die Spalten `Source`, `AiPrompt`, `AiProvider`, `AiModel` am `LearningSet` existieren; `POST /api/learning/sets` setzt immer `Manual`. 10b ergänzt einen eigenen Endpunkt in `Features/Learning` (z. B. `POST /api/learning/sets/ai-draft`, Policy `LearningManage` + `AiUse`),
|
||||
der über `AiService.RunAsync(…, AiPurpose.LearningGeneration, …)` Aufgaben als strukturiertes JSON holt, jede Aufgabe mit `LearningItemInputValidator` und `LearningItemRules.CheckSolution` prüft, Zahlenlösungen mit `LearningNumbers`/`LearningGrading.Grade`
|
||||
nachrechnet und das Ergebnis über denselben Pfad wie `LearningManageEndpoints.CreateSetAsync` als **Entwurf** mit `Source = Ai` speichert. Zuweisen bleibt der bestehende Schritt (`assign`).
|
||||
* UI: ein Assistent-Dialog in `ParentOverview` (Knopf „Mit KI erstellen“, sichtbar anhand `GET /api/ai/status`), Ergebnis öffnet `SetEditor` im Entwurf; `ILearningApi` bekommt eine Methode dafür.
|
||||
|
||||
### Erweiterungspunkte für 10c (Papierlösung per Foto)
|
||||
* `LearningAnswerType.Paper`, `LearningVerdict.Open` und `LearningGrader.Ai` sind vorhanden; `LearningGrading.Grade` liefert für `Paper` bereits `Open`, `LearningItemRules.IsSupported` und `CheckSolution` müssen `Paper` freischalten (Validator und Editor-Auswahl).
|
||||
* Neue Entität `LearningPhoto` (Bytes in der Datenbank, an Versuch/Aufgabe gebunden, Signaturprüfung, Aufbewahrungsfrist) und Endpunkte unter `/api/learning/my/attempts/{id}/…` (Hochladen) bzw. `/api/learning/attempts/{id}/…` (Abruf nur für Eltern/Kind); `AttemptRunner`
|
||||
bekommt für `Paper`-Aufgaben ein Upload-Feld statt Texteingabe, `AttemptReview` zeigt das Foto neben Aufgabe und Musterlösung. Die KI-Prüfung (`AiPurpose.LearningImageGrading`) schreibt `Verdict`, `Grader = Ai`, `Reason` und eine Sicherheitsangabe
|
||||
(neue Spalte) in `LearningAnswer`; bestätigt wird weiterhin über `confirm`. Zeitfenster und Abgabe-Logik (`Submit`, `LearningExpiryService`) bleiben unverändert.
|
||||
|
||||
## Bewusst nicht Teil des ersten Schnitts
|
||||
Offline-Lösen, Sprachausgabe/Diktat, Lernstatistiken über Wochen, Adaptive Schwierigkeit, Formeleditor (Aufgaben bleiben Text), Auswertung mehrerer Kinder im Vergleich,
|
||||
Überwachung gegen Schummeln (die Emulation ist ein Übungsrahmen, keine Fernprüfung).
|
||||
|
||||
Reference in new issue
Block a user