10. Oefenruns, delen en voortgang
Deze pagina is de ERD-inzoomlaag voor het databasehoofdstuk oefenruns, delen en voortgang. De tabeldefinities in dat brondocument blijven leidend; deze pagina biedt een leesbare visuele ingang, zoompaden en compacte diagrammen.
10.1 Doel van deze inzoomlaag
Dit domein beschrijft de uitvoering van oefeningen. Het is kleiner dan sommige andere databasehoofdstukken, maar functioneel zeer centraal omdat dezelfde brondata wordt gebruikt voor:
- lopende oefenvoortgang;
- hervatten na onderbreking;
- live meekijken;
- resultaatweergave na afronding;
- geschiedenis;
- PDF-export;
- gedeelde oefeningen;
- duplicaten of opnieuw maken van een run.
De kernregel is dat ExerciseRuns de run op hoofdniveau vastlegt en dat ExerciseRunProgress de server-side vraagvoortgang per vraag vastlegt. SharedExercises is bewust geen run, maar een administratief ontvangen gedeelde oefening waar pas later eventueel een echte run uit ontstaat.
10.2 Leesroute
| Vraag | Start bij | Daarna kijken naar |
|---|---|---|
| Waar staat het resultaat van een afgeronde oefening? | ExerciseRuns | ExerciseRunProgress voor vraagdetails en modulepayload. |
| Hoe werkt hervatten of abrupt onderbreken? | ExerciseRuns.IsCompleted, LastActivityAtUtc | ExerciseRunProgress.IsCompleted per vraag. |
| Hoe werkt live meekijken? | ExerciseRuns en ExerciseRunProgress | LiveViewAudit in het docent-/auditdomein. |
| Hoe blijft historie leesbaar na wijziging van categorie, oefening of module? | Soft links op ExerciseRuns | Snapshotwaarden in SharedExercises, exportmodellen en modulepayload. |
| Hoe werkt delen van een oefening? | SharedExercises | SourceExerciseRunId, SharedByUserId, SharedToUserId en later StartedExerciseRunId. |
| Hoe werkt “maak opnieuw”? | ExerciseRuns.DuplicateOfExerciseRunId | Nieuwe zelfstandige run met eigen voortgang en statistieken. |
10.3 Kern-ERD binnen het domein
Dit diagram toont alleen de tabellen uit het run-/deel-/voortgangsdomein zelf. De self-reference voor opnieuw maken staat als apart contextblokje getekend, zodat Mermaid geen ontbrekend of afgesneden knooppunt maakt.
Interpretatie
- Eén
ExerciseRunkan meerdereExerciseRunProgress-regels hebben, normaal één per gegenereerde vraag. - Een run kan via
DuplicateOfExerciseRunIdherleidbaar zijn naar een bronrun, zonder resultaten te delen of te overschrijven. SharedExercises.SourceExerciseRunIdverwijst naar de afgeronde bronrun die gedeeld is.SharedExercises.StartedExerciseRunIdblijft leeg totdat de ontvanger de gedeelde oefening daadwerkelijk start.ExerciseRuns.SharedExerciseIdmaakt zichtbaar dat een run is ontstaan vanuit een eerder ontvangen gedeelde oefening.
10.4 Contextdiagram met belangrijkste externe verwijzingen
Dit diagram laat zien waarom ExerciseRuns een historische bron is over meerdere domeinen heen. De verbindingen naar identity, catalogus, relationships, live monitoring en communication zijn bewust als soft links of logische voorwaarden weergegeven. Alleen relaties binnen het practice-domein zelf worden als harde ERD-relatie getekend in de kern-ERD.
Bewuste notaties in dit diagram
| Notatie | Betekenis |
|---|---|
| Volle lijn | Harde FK-relatie binnen het practice-domein. |
| Gestippelde lijn | Soft link, logische verwijzing of functionele voorwaarde over domeingrenzen heen. |
Users .. ExerciseRuns | De uitvoerende gebruiker blijft functioneel herleidbaar, maar ExerciseRuns.UserId krijgt geen harde database-FK naar identity. |
TeacherLevels/Categories/Exercises/ExerciseModules .. ExerciseRuns | De run bewaart historische cataloguscontext als soft link + snapshotcontext; latere cataloguswijzigingen herschrijven bestaande runs niet. |
UserRelationships .. SharedExercises | Een actieve vriendschapsrelatie is nodig om nieuw te delen, maar bestaande gedeelde oefeningen blijven bestaan na ontkoppeling. |
SystemMessages .. SharedExercises | Systeemcommunicatie kan de ontvanger informeren, maar het systeembericht is niet de bron van de gedeelde oefening. |
10.5 Run-lifecycle
De lifecycle is belangrijker dan het aantal tabellen doet vermoeden. Niet iedere run is direct geschiedenis: alleen afgeronde, niet-test runs horen in reguliere resultaat- en geschiedenisweergaven.
10.6 Gedeelde oefening-lifecycle
Een gedeelde oefening wordt niet meteen een run voor de ontvanger. Eerst ontstaat een administratief shared-record; pas na start door de ontvanger ontstaat een zelfstandige run.
10.7 Tabellen in dit domein
| Tabel | Rol in het model | Brondata of afgeleid? | Belangrijkste verantwoordelijkheid |
|---|---|---|---|
ExerciseRuns | Hoofdrecord van één oefenuitvoering | Brondata | Historische runcontext, moduleversie, uniforme totalen, statistieken, status, duplicate/shared-herkomst en modulepayload. |
ExerciseRunProgress | Vraagvoortgang binnen een run | Brondata | Server-side voortgang per vraag, timing, resultaatstatus en modulespecifieke vraagtoestand. |
SharedExercises | Ontvangen gedeelde oefening vóór start | Brondata / administratief record | Herkomst, deler, ontvanger, snapshots, soft delete en koppeling naar de eventueel later gestarte run. |
10.8 Belangrijkste relatiepatronen
1. Run als historische context
ExerciseRuns bevat soft links naar TeacherLevels, Categories, Exercises en ExerciseModules. Deze combinatie legt vast binnen welke onderwijscontext en moduleversie de run is gegenereerd. Latere wijzigingen of migraties aan categorieën, oefeningen of modules herschrijven deze runcontext niet.
2. Uniforme kolommen naast modulepayload
QuestionDataJsonBase64 en QuestionStateJsonBase64 blijven module-specifiek. Tegelijkertijd worden uniforme velden zoals CorrectCount, IncorrectCount, DunnoCount, CompletedQuestionCount, AverageTimeSeconds en MedianTimeSeconds relationeel opgeslagen. Daardoor kunnen geschiedenis, resultaten, PDF en live meekijken snel uitlezen zonder telkens de volledige payload te reconstrueren.
3. Runniveau versus vraagniveau
ExerciseRuns.IsCompleted betekent dat de volledige oefenrun is afgerond. ExerciseRunProgress.IsCompleted betekent alleen dat één vraag binnen de run verwerkt is. Deze twee velden hebben dus een verschillende betekenis en mogen niet als uitwisselbaar worden behandeld.
4. Delen is geen kopie van resultaatdata
SharedExercises bevat een verwijzing naar de bronrun en snapshots voor stabiele weergave. Het deelt niet het resultaat van de afzender. Wanneer de ontvanger start, ontstaat een nieuwe zelfstandige ExerciseRuns-regel met eigen voortgang en eigen statistieken.
5. Duplicaten blijven zelfstandige runs
DuplicateOfExerciseRunId legt herkomst vast voor “maak opnieuw”, maar de nieuwe run krijgt eigen antwoorden, timing, totalen en statistieken. Resultaten worden niet gedeeld en niet overschreven.
6. Live meekijken leest voortgang, maar schrijft geen antwoorddata
Live meekijken gebruikt ExerciseRunProgress en uniforme runvelden als bron na server-side verwerking van leerlingacties. LiveViewAudit registreert wie meekijkt en wanneer, maar de meekijker wijzigt geen antwoord, score of voortgang.
10.9 Relatie-inventaris binnen dit domein
| Brontabel | Veld | Verwijst naar | Relatietype | Nullable | Betekenis |
|---|---|---|---|---|---|
ExerciseRuns | UserId | Users.Id | Soft link | N | Gebruiker die de run uitvoert of heeft uitgevoerd. |
ExerciseRuns | LevelId | TeacherLevels.Id | Soft link + snapshotcontext | N | Historisch niveau op moment van genereren. |
ExerciseRuns | CategoryId | Categories.Id | Soft link + snapshotcontext | N | Historische centrale categoriecontext. |
ExerciseRuns | ExerciseId | Exercises.Id | Soft link + snapshotcontext | N | Concrete oefening waarop de run is gebaseerd. |
ExerciseRuns | ExerciseModuleId | ExerciseModules.Id | Soft link + snapshotcontext | N | Moduleversie die vraag- en antwoordstructuur bepaalt. |
ExerciseRuns | DuplicateOfExerciseRunId | ExerciseRuns.Id | Harde FK | J | Bronrun voor opnieuw gemaakte oefening binnen hetzelfde practice-domein. |
ExerciseRuns | SharedExerciseId | SharedExercises.Id | Harde FK | J | Ontvangen shared-record waaruit deze run is gestart. |
SharedExercises | SourceExerciseRunId | ExerciseRuns.Id | Harde FK | N | Afgeronde bronrun die gedeeld is. |
SharedExercises | SharedByUserId | Users.Id | Soft link | N | Deler van de oefening. |
SharedExercises | SharedToUserId | Users.Id | Soft link | N | Ontvanger van de gedeelde oefening. |
SharedExercises | StartedExerciseRunId | ExerciseRuns.Id | Harde FK | J | Door ontvanger gestarte run, pas gevuld na start. |
SharedExercises | DeletedByUserId | Users.Id | Soft link | J | Gebruiker die de ontvangen gedeelde oefening uit eigen overzicht heeft verwijderd. |
ExerciseRunProgress | ExerciseRunId | ExerciseRuns.Id | Harde FK | N | Run waar deze vraagvoortgang bij hoort. |
10.10 Grenzen van dit ERD
| Onderwerp | Waar staat het wel? | Waarom niet volledig hier tekenen? |
|---|---|---|
| Relatievoorwaarde voor delen | Relatiebeheer | De relatie is autoriserend bij nieuw delen, maar geen eigenschap van het shared-record zelf. |
| Docentniveau, categorie en oefeningconfiguratie | Docentstructuur en leerlingtoegang | ExerciseRuns bewaart historische context, maar beheert de onderwijsstructuur niet. |
| Live meekijk-audit | Docentstructuur en leerlingtoegang en Audit/historie | De auditregel hoort bij meekijken; de run blijft bron voor voortgang. |
| Systeemcommunicatie over gedeelde oefeningen | Communicatie en notificaties | Berichten informeren of routeren, maar zijn niet de bron van de gedeelde oefening. |
| PDF-exportbestand | Geen permanente tabel in dit domein | PDF-export gebruikt de historische runcontext en levert een tijdelijke downloadresponse. |
10.11 Afgedichte keuzes en onderhoud
| Onderwerp | V1.0-keuze | Vervolgcontrole |
|---|---|---|
| Dubbele relatie rond gedeelde oefeningen | SharedExercises.StartedExerciseRunId en ExerciseRuns.SharedExerciseId blijven beide bestaan in de V1.0-baseline. De eerste ondersteunt het shared-record, de tweede ondersteunt snelle herkomst op de gestarte run. | Alleen versimpelen wanneer implementatie en migratie aantonen dat één richting structureel redundant is. |
| Historische FK versus actuele beheer-FK | Het ERD gebruikt geen extra visuele stijl naast harde lijn, stippellijn en relatietype-label. Het verschil wordt tekstueel aangeduid als harde FK, soft link of soft link + snapshotcontext. | Nieuwe relatiepatronen worden eerst aan de relatie-index toegevoegd. |
| Soft link + snapshotcontext | De relatie-index markeert harde FK, soft link en soft link + snapshot afzonderlijk. Extra veldniveau-diagrammen zijn niet nodig zolang de relatie-inventaris helder blijft. | Alleen toevoegen bij aantoonbare leesbaarheidsproblemen. |
| Live meekijken | LiveViewAudit is al in de audit-/docentcontext opgenomen. Geen apart subdiagram nodig zolang de live-flow geen extra persistente tabellen krijgt. | Herzien wanneer live meekijken nieuwe brondata krijgt. |
| Modulepayloads | JSON/base64-payloads blijven buiten het relationele ERD. Modules verwijzen naar hun moduledossier; payloadschema's horen bij de oefenmodule- of TO-documentatie. | Nieuwe duurzame payloadtabellen vereisen database-informatie en ERD-impactcontrole. |