Gedeelde oefeningen
9.1 Doel
Gedeelde oefeningen maken het mogelijk dat een leerling een afgeronde eigen oefening beschikbaar maakt voor een actieve vriend.
Dit hoofdstuk beschrijft de functionele samenhang tussen:
- een afgeronde bronrun van de deler;
- het administratieve ontvangen gedeelde-oefeningrecord;
- systeemcommunicatie richting de ontvanger;
- het overzicht met ontvangen gedeelde oefeningen;
- de eerste start door de ontvanger;
- hervatten van een niet-afgeronde ontvangerrun;
- opnieuw maken na afronding;
- verwijderen uit het ontvangen overzicht;
- resultaten, geschiedenis en PDF-export van daaruit ontstane runs.
Delen is aanvullend op de normale oefenfunctionaliteit. Het vervangt geen regulier oefenaanbod, geen vriendschapsbeheer, geen berichtenbeheer en geen resultaatdomein.
Een gedeelde oefening is in eerste instantie geen nieuwe oefenrun voor de ontvanger. Eerst ontstaat een administratief record dat vastlegt wie welke afgeronde bronrun met wie heeft gedeeld. Pas wanneer de ontvanger de gedeelde oefening start of opnieuw maakt, ontstaat een zelfstandige ExerciseRun voor de ontvanger.
9.2 Domeinafbakening
| Onderdeel | Binnen dit hoofdstuk | Buiten dit hoofdstuk |
|---|---|---|
| Delen van afgeronde oefening | Voorwaarden, bronruncontrole, ontvangerkeuze en aanmaak van ontvangen gedeeld record. | Resultaatberekening van de bronrun zelf. |
| Ontvangen gedeelde oefening | Administratief record, snapshotcontext, zichtbaarheid en overzichtsstatus. | Algemeen mailboxbeheer of systeemnotificatiebeheer. |
| Eerste start door ontvanger | Aanmaken van een zelfstandige ontvangerrun met dezelfde inhoud en volgorde als de bronrun. | Vraagbeantwoording zelf; die blijft bij het oefenrundomein. |
| Hervatten | Openen van een bestaande niet-afgeronde ontvangerrun. | Algemene hervatlogica buiten gedeelde-oefeningencontext. |
| Opnieuw maken | Nieuwe zelfstandige ontvangerrun op basis van dezelfde gedeelde inhoud. | Regulier opnieuw maken van een eigen niet-gedeelde run. |
| Verwijderen uit ontvangen overzicht | Ontvangergebonden zichtbaarheidmarkering op het shared-record. | Hard delete van bronrun, gedeeld record of afgeronde ontvangerruns. |
| Systeemcommunicatie | Functionele ingang naar ontvangen gedeelde oefening of overzicht. | Mailbox-readstate, threadgedrag en templatebeheer. |
| Resultaat en geschiedenis | Raakvlak: gedeelde ontvangerruns verschijnen als eigen runs van de ontvanger. | Uitwerking van popup, statistieken, PDF-layout en geschiedenisfilters. |
9.3 Bronpositie
Gedeelde oefeningen gebruiken meerdere bronlagen.
| Bronlaag | Betekenis |
|---|---|
| FO | Beschrijft de functionele samenhang, domeingrenzen en lifecycle van gedeelde oefeningen. |
| Usecases | Beschrijven de concrete flows voor delen, ontvangen, starten, opnieuw maken, verwijderen en blokkeren. |
| Schermdocumentatie | Beschrijft zichtbare velden, filters, acties, statussen en lege toestanden van het overzicht. |
| Database-informatie | Beschrijft SharedExercises, ExerciseRuns, voortgang, snapshots, soft delete en historische context. |
| Relatiebeheer | Bepaalt of een actieve vriendschap bestaat en of delen tussen twee leerlingen is toegestaan. |
| Berichten/communicatie | Bepaalt hoe systeemcommunicatie, readstate en badges werken. |
| Popupregister | Bevat popupkeys, teksten, knoppen, themas en invoervelden voor feedback rond delen en verwijderen. |
| Mockups | Ondersteunen visuele interpretatie, maar zijn geen bron voor definitieve datawaarden. |
Dit hoofdstuk herhaalt niet de volledige flow van vraagbeantwoording, resultaatpresentatie, PDF-export, vriendschapsvorming of mailboxbeheer. Die domeinen blijven bronhoudend in hun eigen FO-hoofdstukken en usecases.
9.4 Kernobjecten
| Object | Betekenis |
|---|---|
ExerciseRuns | Hoofdrecord van een uitgevoerde oefening. De bronrun van de deler is afgerond; ontvangerruns ontstaan pas bij starten of opnieuw maken. |
SharedExercises | Administratieve registratie dat een bronrun met een ontvanger is gedeeld, inclusief snapshots en zichtbaarheid. |
ExerciseRunProgress | Operationele voortgang per vraag binnen een ontvangerrun nadat de ontvanger de gedeelde oefening start. |
UserRelationships | Bron voor actieve vriendschapsrelaties tussen leerlingen. |
Users | Deler en ontvanger van de gedeelde oefening. |
SystemMessages | Optionele/gewenste systeemcommunicatie naar de ontvanger; geen bron van waarheid voor het gedeelde record. |
SystemMessageTemplates | Beheerbare tekstbasis voor systeemcommunicatie waar zo'n template bestaat. |
PopupDefinition / popupregister | Bron voor popupfeedback rond delen, blokkeren, starten en verwijderen. |
9.5 Functionele kernregel
Een gedeelde oefening bestaat functioneel uit drie lagen.
| Laag | Moment | Bron van waarheid | Belangrijke grens |
|---|---|---|---|
| Bronrun | Bestaat vóór delen. | ExerciseRuns van de deler. | Wordt door delen niet gewijzigd. |
| Ontvangen gedeeld record | Ontstaat bij delen. | SharedExercises. | Maakt nog geen run voor de ontvanger aan. |
| Ontvangerrun | Ontstaat bij start of opnieuw maken. | Nieuwe ExerciseRuns van de ontvanger. | Heeft eigen voortgang, antwoorden, totalen en resultaat. |
De bronrun, het shared-record en de ontvangerruns overschrijven elkaar nooit.
9.6 Begrippen
| Begrip | Betekenis |
|---|---|
| Deler | Leerling die een afgeronde eigen oefenrun deelt. |
| Ontvanger | Leerling die de gedeelde oefening ontvangt. |
| Bronrun | Afgeronde run van de deler waarop de gedeelde inhoud is gebaseerd. |
| Gedeeld record | SharedExercises-record dat bronrun, deler, ontvanger en snapshotcontext vastlegt. |
| Eerste uitvoering | Eerste ontvangerrun die uit het gedeelde record ontstaat. |
| Herhaling | Nieuwe ontvangerrun nadat de ontvanger de gedeelde oefening al eerder heeft uitgevoerd of wanneer de flow opnieuw maken toestaat. |
| Snapshotcontext | Tekstuele niveau-, categorie- en oefeningweergave zoals zichtbaar op het moment van delen. |
| Ontvangerverwijdering | Soft delete / zichtbaarheidmarkering waardoor het shared-record niet meer in het ontvangen overzicht van deze ontvanger verschijnt. |
9.7 Voorwaarden voor delen
Een leerling kan een oefening alleen delen wanneer alle voorwaarden op het moment van delen server-side geldig zijn.
| Voorwaarde | Regel |
|---|---|
| Actieve leerlingcontext | De actor is ingelogd met een actieve leerlingrolcontext. |
| Eigen bronrun | De bronrun hoort bij de ingelogde leerling. |
| Afgeronde bronrun | Alleen afgeronde runs zijn deelbaar. |
| Geen testrun | Docenttestruns of tijdelijke testruns zijn niet deelbaar als leerlingresultaat. |
| Deelbare oefening | De oefening en modulecontext moeten functioneel deelbaar zijn. |
| Deelfeature beschikbaar | De functie Oefeningen delen is sitebreed/contextueel beschikbaar. |
| Vriendschappen beschikbaar | Vriendschap is functioneel beschikbaar voor de leerling. |
| Actieve vriendrelatie | De ontvanger is een actieve vriend met een actief leerlingaccount. |
| Ontvanger is leerling | Delen met ouder/voogd, docent, beheerder of onbekend e-mailadres valt buiten scope. |
| Server-side hercontrole | Zichtbare deelknop of ontvangerlijst is geen autorisatiebewijs. |
Wanneer één van deze voorwaarden ontbreekt, wordt delen geblokkeerd en ontstaat geen SharedExercises-record, geen ontvangerrun en geen systeemcommunicatie over een gedeelde oefening.
9.8 Delen vanuit resultaat of geschiedenis
Een leerling kan een afgeronde oefening delen vanuit:
- het resultaat direct na afronding;
- een resultaatdetail vanuit oefeninggeschiedenis;
- een resultaatdetail vanuit geschiedenis alles, wanneer delen voor die run is toegestaan.
De deelactie deelt niet het behaalde resultaat van de deler. De ontvanger krijgt geen scores, antwoorden, statistieken of beoordeling van de deler als eigen resultaat.
Wel wordt de oefeninhoud beschikbaar gemaakt:
- vraaginhoud;
- oorspronkelijke vraagvolgorde voor de eerste uitvoering;
- historische context van niveau, categorie en oefening;
- module-/payloadcontext die nodig is om de gedeelde inhoud veilig te renderen en te controleren.
9.9 Wat delen niet doet
Delen mag de volgende zaken niet wijzigen.
| Object / context | Regel |
|---|---|
| Bronrun van deler | Blijft volledig ongewijzigd. |
| Antwoorden van deler | Worden niet als antwoorden van de ontvanger opgeslagen. |
| Statistieken van deler | Worden niet gedeeld als score of resultaat van de ontvanger. |
| Voortgang van deler | Wordt niet aangepast. |
| Vriendschap | Er ontstaat geen nieuwe vriendschap en geen uitnodiging. |
| Niveauautorisatie | Er wordt geen leerlingtoegang tot het oorspronkelijke niveau toegekend. |
| Oefenconfiguratie | De docentconfiguratie wordt niet gewijzigd. |
| Moduleconfiguratie | De module wordt niet aangepast of gemigreerd. |
| Mailboxreadstate | Alleen generieke berichtlogica bepaalt gelezen/ongelezen. |
| Resultaatgeschiedenis | Er ontstaat pas geschiedenis voor de ontvanger na een eigen afgeronde ontvangerrun. |
9.10 Aanmaak van het gedeelde record
Bij succesvol delen maakt OefenHub een administratief SharedExercises-record aan.
Minimaal functioneel relevant zijn:
| Veld / concept | Betekenis |
|---|---|
SourceExerciseRunId | Bronrun waarvan de gedeelde inhoud afkomstig is. |
SharedByUserId | Leerling die de oefening deelt. |
SharedToUserId | Leerling die de oefening ontvangt. |
LevelSnapshotText | Niveauweergave zoals zichtbaar op het moment van delen. |
CategorySnapshotText | Categorieweergave zoals zichtbaar op het moment van delen. |
ExerciseSnapshotText | Oefeningweergave zoals zichtbaar op het moment van delen. |
SharedAtUtc | Moment waarop de share is aangemaakt. |
StartedExerciseRunId | Eerste ontvangerrun wanneer de ontvanger daadwerkelijk start. |
StartedAtUtc | Afgeleid/gespiegeld startmoment van de eerste uitvoering. |
CompletedAtUtc | Afgeleid/gespiegeld afrondmoment voor snelle overzichtsweergave. |
IsDeleted | Zichtbaarheidmarkering voor verwijderen uit het eigen overzicht van de ontvanger. |
DeletedAtUtc / DeletedByUserId | Herleidbaarheid van ontvangerverwijdering. |
StartedAtUtc en CompletedAtUtc op het shared-record zijn overzichtsvelden. De primaire bron voor uitvoering en afronding blijft altijd de echte ontvangerrun.
9.11 Historische snapshotcontext
Voor ontvangen gedeelde oefeningen worden niveau, categorie en oefening als tekstuele momentopname vastgelegd.
Deze snapshot is nodig omdat de gedeelde oefening historisch begrijpelijk moet blijven wanneer later:
- een niveau wordt hernoemd;
- een categorie wordt hernoemd;
- een categorie wordt gemigreerd;
- een oefening wordt hernoemd;
- een oefeningconfiguratie wordt gewijzigd;
- een modulestatus verandert;
- een relatie tussen deler en ontvanger eindigt.
Snapshotwaarden worden niet achteraf herschreven door zulke wijzigingen.
9.12 Relatie tot categorie- en modulemigratie
Categoriemigratie of modulemigratie mag bestaande gedeelde oefeningen niet onleesbaar of historisch onjuist maken.
| Situatie | Regel |
|---|---|
| Broncategorie later gemigreerd | Snapshotwaarden op SharedExercises blijven staan zoals bij delen. |
| Bronrun historisch gekoppeld aan oude categoriecontext | De runcontext blijft historisch bestaan. |
| Ontvanger start later | De uitvoering gebruikt de gedeelde broninhoud en historische context; migratie herschrijft de share niet. |
| Module later inactief of gemigreerd | Historische weergave moet veilig blijven; starten kan worden geblokkeerd als inhoud niet veilig renderbaar/startbaar is. |
| PDF later downloaden | PDF gebruikt historische run- en snapshotcontext, niet actuele naamgeving. |
Wanneer starten of opnieuw maken technisch niet veilig kan door ontbrekende module- of payloadondersteuning, wordt de actie geblokkeerd met een veilige niet-beschikbaarafhandeling. Bestaande afgeronde resultaten blijven waar mogelijk raadpleegbaar.
9.13 Systeemcommunicatie richting ontvanger
Wanneer een leerling een oefening deelt, kan de ontvanger via systeemcommunicatie worden geïnformeerd.
Die communicatie is alleen een ingang naar de gedeelde-oefeningcontext.
Het lezen of openen van het systeembericht:
- start de gedeelde oefening niet;
- maakt geen ontvangerrun aan;
- accepteert geen relatie;
- wijzigt geen resultaatdata;
- verwijdert het gedeelde record niet;
- rondt geen bestaande run af.
De bron van waarheid blijft SharedExercises.
9.14 Systeemberichtverwijzing voor gedeelde oefeningen
Gedeelde oefeningen gebruiken een expliciete systeemberichtverwijzing met:
| Veld | Waarde |
|---|---|
EntityType | SharedExercise |
EntityId | Het betreffende SharedExercises-record. |
Deze verwijzing is uitsluitend een ingang naar de gedeelde-oefeningcontext.
Voor het openen van zo’n systeembericht gelden de volgende regels:
- het lezen van het systeembericht start de gedeelde oefening niet automatisch;
- het lezen van het systeembericht maakt geen ontvangerrun aan;
- de frontend opent hoogstens het ontvangen-gedeelde-oefeningoverzicht of de toegestane detailcontext van het
SharedExercises-record; - de vervolgactie controleert server-side opnieuw of de ingelogde gebruiker de ontvanger is en of het shared-record niet uit de eigen zichtbare lijst is verwijderd;
- ontbrekende, verwijderde of niet-toegankelijke shared-records worden veilig afgehandeld zonder bronruninhoud, antwoorddata of technische payload te tonen.
SharedExercise is daarmee een toegestane domeinverwijzing binnen SystemMessages.EntityType, naast de bestaande verwijstypen voor relatie-uitnodigingen, tickets en privéberichtthreads.
9.15 Ontvangen gedeelde oefeningen overzicht
Het overzicht met ontvangen gedeelde oefeningen is een readmodel over SharedExercises en eventueel daaruit ontstane ontvangerruns.
Het overzicht toont alleen:
- records waarvoor de ingelogde leerling de ontvanger is;
- records die niet uit het eigen overzicht zijn verwijderd;
- waarden waarvoor de leerling volgens actuele sessie en leerlingcontext toegang heeft.
Het overzicht maakt geen nieuwe run aan door alleen bekeken te worden.
9.15.1 Zichtbare onderdelen
| Onderdeel | Betekenis |
|---|---|
| Introblok | Legt uit dat ontvangen gedeelde oefeningen hier verzameld worden. |
| Samenvatting | Dynamische aantallen zoals nieuw ontvangen, al gestart en afgerond. |
| Filters | Filteren op status, niveau, categorie en deler binnen zichtbare dataset. |
| Tabel | Per ontvangen gedeelde oefening een regel met snapshotwaarden, status, voortgang en acties. |
| Statuslabel | Afgeleid label zoals Nieuw ontvangen, Al gestart of Afgerond. |
| Voortgang | Voortgang van de eigen run van de ontvanger, niet van de bronrun. |
| Geschiedenisactie | Alleen beschikbaar wanneer afgeronde ontvangerruns bestaan. |
| Start-/hervat-/opnieuw-maakactie | Afhankelijk van status en runcontext. |
| Verwijderactie | Verwijdert het item uit het ontvangen overzicht via soft delete. |
9.16 Filters en samenvattingswaarden
Filters en samenvattingswaarden zijn afgeleide readmodelwaarden.
| Waarde | Afleiding |
|---|---|
| Nieuw ontvangen | Zichtbaar SharedExercises-record zonder gestarte ontvangerrun. |
| Al gestart | Zichtbaar record met niet-afgeronde ontvangerrun. |
| Afgerond | Zichtbaar record met minimaal één afgeronde ontvangerrun. |
| Niveau-filter | Snapshotwaarden of historische runcontext binnen zichtbare dataset. |
| Categorie-filter | Snapshotwaarden binnen zichtbare dataset. |
| Gedeeld-door-filter | Delers van zichtbare, niet-verwijderde shared-records. |
| Voortgang | Eigen ontvangerrun: CompletedQuestionCount ten opzichte van TotalQuestions. |
| Geschiedenisbeschikbaarheid | Minimaal één afgeronde ontvangerrun binnen deze gedeelde context. |
Filters wijzigen geen data, geen relaties, geen runs en geen systeemcommunicatie.
9.17 Afgeleide status van een gedeelde oefening
De status in het overzicht is afgeleid en geen vrij handmatig statusveld.
| Status | Betekenis |
|---|---|
| Nieuw ontvangen | Er bestaat een zichtbaar shared-record, maar nog geen ontvangerrun. |
| Al gestart | Er bestaat een niet-afgeronde ontvangerrun voor dit shared-record. |
| Afgerond | Er bestaat minimaal één afgeronde ontvangerrun voor dit shared-record. |
| Niet beschikbaar | De gedeelde inhoud bestaat nog administratief, maar kan niet veilig gestart of getoond worden. |
| Verwijderd uit overzicht | Het item is door de ontvanger verborgen en verschijnt niet meer in het reguliere overzicht. |
Een gedeelde oefening kan historisch afgeronde ontvangerruns hebben en toch uit het ontvangen overzicht verwijderd zijn. De afgeronde runs blijven dan via geschiedenis vindbaar volgens de normale geschiedenisregels.
9.18 Eerste start door de ontvanger
De eerste start van een gedeelde oefening maakt een zelfstandige ExerciseRun voor de ontvanger aan.
Voor de eerste uitvoering geldt:
- de ingelogde leerling moet de ontvanger zijn;
- het shared-record moet bestaan;
- het shared-record mag niet door de ontvanger uit het overzicht zijn verwijderd;
- er mag nog geen eerste ontvangerrun bestaan;
- de broninhoud moet beschikbaar en veilig renderbaar zijn;
- de vraaginhoud is gelijk aan de gedeelde broninhoud;
- de vraagvolgorde is gelijk aan de bronrunvolgorde;
- de bronrun van de deler blijft ongewijzigd.
Na aanmaak krijgt de ontvangerrun eigen:
UserId;SharedExerciseId;- voortgangsregels;
- antwoorden;
- totalen;
- timing;
- statistieken;
- afrondstatus;
- geschiedenis- en resultaatweergave.
9.19 Hervatten van een niet-afgeronde ontvangerrun
Wanneer de ontvanger een gedeelde oefening al heeft gestart maar nog niet heeft afgerond, opent de actie vanuit het overzicht de bestaande niet-afgeronde run.
Hervatten:
- maakt geen nieuwe run;
- wijzigt de bronrun niet;
- gebruikt de eigen voortgang van de ontvanger;
- volgt dezelfde server-side voortgangsregels als reguliere leerlingruns;
- blijft binnen de gedeelde-oefeningcontext herleidbaar via
SharedExerciseId.
Wanneer de bestaande run niet veilig hervatbaar is, wordt een veilige fout- of niet-beschikbaarafhandeling getoond. Er mag geen tweede halfbruikbare run ontstaan.
9.20 Opnieuw maken na afronding
Wanneer de ontvanger de gedeelde oefening opnieuw maakt, ontstaat opnieuw een zelfstandige run.
Voor opnieuw maken geldt:
| Aspect | Regel |
|---|---|
| Inhoud | De gedeelde inhoud blijft gelijk aan de broninhoud. |
| Volgorde | Na de eerste uitvoering mag de vraagvolgorde opnieuw worden bepaald wanneer module/configuratie dit toestaat. |
| Eigen run | Iedere herhaling heeft eigen voortgang, antwoorden, totalen en statistieken. |
| Bronrun | Wordt niet aangepast. |
| Eerdere ontvangerruns | Worden niet overschreven. |
| Geschiedenis | Iedere afgeronde herhaalrun verschijnt als eigen geschiedenisregel. |
| PDF exporteert de concrete historische herhaalrun, niet het shared-record als abstract record. |
Wanneer opnieuw maken niet meer veilig kan doordat broninhoud of moduleondersteuning ontbreekt, wordt de herhaalactie geblokkeerd. Bestaande afgeronde resultaten blijven waar mogelijk raadpleegbaar.
9.21 Resultaten en geschiedenis van ontvangerruns
Een ontvangerrun is voor resultaten en geschiedenis een gewone eigen run van de ontvanger, met aanvullende herleidbaarheid naar het gedeelde record.
Daarom geldt:
- afgeronde ontvangerruns verschijnen in geschiedenis;
- niet-afgeronde ontvangerruns verschijnen niet als afgerond resultaat;
- resultaatdetail gebruikt de concrete ontvangerrun;
- statistieken worden gelezen uit de uniforme runvelden van die run;
- PDF-export gebruikt de historische context van die run;
- het shared-record kan overzichtsdata spiegelen, maar is niet de primaire resultaatbron;
- de bronrun van de deler wordt niet getoond als resultaat van de ontvanger.
Bij geschiedenisweergave moet duidelijk blijven dat de run uit een gedeelde oefening kan komen, zonder technische GUID's aan de gebruiker te tonen.
9.22 PDF-export vanuit gedeelde oefeningen
PDF-export van een gedeelde ontvangerrun gebruikt dezelfde historische resultaatbron als gewone resultaat-PDF's.
| Onderdeel | Regel |
|---|---|
| Bron | Concrete afgeronde ontvangerrun. |
| Context | Historische runcontext en gedeelde snapshotcontext waar relevant. |
| Inhoud | Eigen antwoorden, eigen resultaat en eigen statistieken van de ontvanger. |
| Niet gebruiken | Resultaat, antwoorden of statistieken van de deler. |
| Mutatie | PDF-download wijzigt geen run, shared-record, relatie of readstate. |
| Bestandsnaam | Volgt de algemene PDF-regels uit FO-18. |
| Niet-beschikbaar | Bij ontbrekende autorisatie of veilige renderrepresentatie wordt export geblokkeerd zonder gedeeltelijke data. |
9.23 Verwijderen uit het ontvangen overzicht
De ontvanger kan een ontvangen gedeelde oefening uit het eigen overzicht verwijderen.
Dit is een zichtbaarheidshandeling.
Bij verwijderen:
- wordt het shared-record niet hard verwijderd;
- wordt de bronrun niet verwijderd;
- worden ontvangerruns niet verwijderd;
- blijven afgeronde ontvangerruns via geschiedenis beschikbaar;
- blijft audit-/historyinformatie bewaard;
- wordt het item niet meer in het reguliere ontvangen-overzicht getoond;
- wordt geen vriendschap of relatie beëindigd;
- wordt geen systeembericht automatisch verwijderd.
De verwijderactie vereist een bevestiging via de centrale popupafhandeling.
9.24 Niet terugtrekken door afzender
Een eenmaal gedeelde oefening kan niet door de afzender worden teruggetrokken.
Redenen:
- de ontvanger heeft een eigen ontvangen record gekregen;
- de ontvanger kan daaruit al een zelfstandige run hebben gestart;
- afgeronde ontvangerruns zijn eigen historische resultaten van de ontvanger;
- het verwijderen of intrekken door de afzender zou geschiedenis en resultaatcontext van de ontvanger onbetrouwbaar maken.
Wanneer de vriendschap later eindigt, mogen geen nieuwe gedeelde oefeningen meer worden aangemaakt op basis van die gedeactiveerde relatie. Bestaande gedeelde records en afgeronde ontvangerruns blijven historisch bestaan.
9.25 Relatie met vriendschappen
Vriendschap is een voorwaarde voor nieuw delen, maar niet de bron van het gedeelde-oefeningrecord.
| Situatie | Regel |
|---|---|
| Actieve vriendschap op deelmoment | Delen kan doorgaan als alle overige voorwaarden geldig zijn. |
| Geen actieve vrienden | Delen wordt geblokkeerd. |
| Vriendschappen uitgeschakeld | Delen wordt geblokkeerd. |
| Vriendschap eindigt na delen | Bestaande shared-records en ontvangerruns blijven bestaan. |
| Vriendschap eindigt vóór delen | Er kan geen nieuw shared-record ontstaan. |
| Relatie-uitnodiging pending | Is geen actieve vriendschap en telt niet als deelvoorwaarde. |
| Ouder-/voogdrelatie | Geeft geen recht om oefeningen namens een kind te maken of te delen. |
| Docentrelatie | Geeft geen leerling-leerling deelrecht. |
Relatiebeheer blijft bronhoudend voor uitnodigen, accepteren, afwijzen en ontkoppelen. FO-09 gebruikt alleen de uitkomst: een actieve vriendschapsrelatie die delen toestaat.
9.26 Relatie met featuretoggles
Delen is afhankelijk van functionele beschikbaarheid.
Minimaal relevant zijn:
| Feature / instelling | Gevolg |
|---|---|
| Vriendschappen toegestaan | Zonder deze beschikbaarheid kan geen vriendrelatie als deelcontext worden gebruikt. |
| Oefeningen delen toegestaan | Zonder deze beschikbaarheid wordt delen geblokkeerd. |
| Privéberichten toegestaan | Staat los van de share zelf; delen gebruikt systeemcommunicatie of overzicht, geen privéthread als bron. |
| Testoefeningen beschikbaar | Heeft geen reguliere leerlingdeelbaarheid van docenttestruns tot gevolg. |
| Module beschikbaarheid | Kan starten/opnieuw maken beperken wanneer historische inhoud niet veilig renderbaar is. |
Featuretoggles verwijderen geen bestaande shared-records en herschrijven geen historische ontvangerruns.
9.27 Relatie met berichten en communicatie
Gedeelde oefeningen kunnen systeemcommunicatie gebruiken, maar zijn geen berichtendomein.
| Communicatievorm | Relatie tot gedeelde oefeningen |
|---|---|
| Systeembericht | Kan de ontvanger informeren dat een oefening is gedeeld. |
| Mailboxreadstate | Bepaalt gelezen/ongelezenstatus van bericht, niet de status van de gedeelde oefening. |
| Privéberichtthread | Wordt niet automatisch aangemaakt door delen. |
| Systeemnotificatie | Geen kanaal voor individuele gedeelde oefeningen. |
| Popupfeedback | Wordt gebruikt voor actiefeedback zoals succesvol delen, blokkade of verwijderbevestiging. |
| Realtime update | Mag badge/overzicht actueel maken, maar is geen bron van waarheid. |
Tijdens een actieve leerling-oefenrun mogen badges, meldingenterugkoppelingen en popupachtige signalen visueel worden uitgesteld volgens de anti-afleidingsregels. Onderliggende shared-records en systeemberichten blijven server-side correct opgeslagen.
9.28 Relatie met oefenruns en voortgang
Wanneer een ontvangerrun ontstaat vanuit een gedeelde oefening, gelden de normale oefenrunregels.
| Onderwerp | Regel |
|---|---|
| Voortgang | Server-side opgeslagen per vraag in ExerciseRunProgress. |
| Onderbreken | Rondt de run niet af; de run blijft niet-afgerond. |
| Hervatten | Heropent de bestaande niet-afgeronde ontvangerrun. |
| Antwoordcontrole | Gebeurt via de modulelaag en generieke runverwerking. |
Geen idee | Volgt de normale leerlingrunregels. |
| Afronden | Zet IsCompleted, CompletedAtUtc en definitieve statistiekvelden. |
| Live meekijken | Leest voortgang van de ontvangerrun, niet van het shared-record. |
| Geschiedenis | Toont alleen afgeronde ontvangerruns. |
FO-09 beschrijft dus vooral de overgang van shared-record naar ontvangerrun. De verdere vraag- en resultaatverwerking blijft bij FO-08 en FO-18.
9.29 Relatie met live meekijken
Live meekijken is geen deelmechanisme.
Wanneer een leerling een gedeelde oefening start, kan live meekijken functioneel dezelfde voortgangsbron gebruiken als bij reguliere leerlingruns, mits de meekijker daarvoor afzonderlijk geautoriseerd is.
| Rol | Regel |
|---|---|
| Docent | Ziet alleen voortgang binnen geldige docentcontext en niet automatisch omdat een oefening gedeeld is. |
| Ouder/voogd | Ziet alleen voortgang via actieve ouder-/voogdrelatie en read-only grenzen. |
| Deler | Krijgt geen live meekijkrecht op de ontvangerrun door te delen. |
| Beheerder | Heeft geen vrije live-meekijkbypass. |
Delen creëert dus geen extra live-autorisatie.
9.30 Relatie met docent- en ouder-/voogdfunctionaliteit
Gedeelde oefeningen zijn leerling-leerlingfunctionaliteit.
| Context | Regel |
|---|---|
| Docent | Kan gedeelde ontvangerruns alleen zien binnen bestaande resultaat-/geschiedenisautorisatie. |
| Ouder/voogd | Kan gedeelde ontvangerruns van een gekoppeld kind zien als historische run, maar kan niet namens het kind starten. |
| Beheerder | Kan gedeelde oefeningen supportmatig analyseren waar beheercontext dit toestaat, maar niet als eindgebruiker uitvoeren namens de leerling. |
| TestDocent | Testfunctionaliteit geeft geen leerlingdeelrecht. |
| Deler | Is geen eigenaar van de ontvangerrun van de ontvanger. |
9.31 Autorisatie- en veiligheidsregels
Voor gedeelde oefeningen gelden de volgende regels.
- De actieve sessie en leerlingrolcontext worden bij iedere deel-, overzichts-, start-, hervat-, herhaal-, verwijder- en detailactie opnieuw server-side gecontroleerd.
- Routeparameters, browsergeschiedenis, querystrings, frontendfilters en oude selectiecontexten mogen geen toegang verruimen.
- Een visible knop of menu-item is geen autorisatiebewijs.
- Een systeembericht is geen autorisatiebewijs.
- Een actieve vriendschap is alleen vereist voor nieuw delen, niet voor het historisch raadplegen van eerder ontvangen eigen records.
- Een RunId uit een URL is nooit voldoende om resultaat of PDF te tonen.
- Bij autorisatiefouten wordt geen deelinhoud, bronvraag, antwoord, statistiek, kind-/leerlingcontext of technische payload gedeeltelijk getoond.
- De bronrun van de deler mag niet uitlekken aan onbevoegde ontvangers of derden.
- De ontvanger ziet alleen de gedeelde oefeninhoud die als gedeeld record aan hem of haar is toegekend.
9.32 Privacygrenzen
Gedeelde oefeningen bevatten onderwijsinhoud en kunnen indirect persoonsgegevens tonen, zoals naam van de deler.
Daarom geldt:
| Gegeven | Privacyregel |
|---|---|
| Naam deler | Alleen tonen aan de ontvanger binnen zichtbaar gedeeld record. |
| Bronresultaat | Niet tonen als resultaat van de ontvanger. |
| Antwoorden deler | Niet tonen aan de ontvanger als diens eigen antwoorden. |
| Ontvangerresultaat | Niet tonen aan de deler door alleen de share-relatie. |
| Relatie-einde | Geeft geen nieuwe toegang, maar wist bestaande historische resultaten niet automatisch. |
| Technische IDs | Niet zichtbaar maken in gebruikersoverzichten. |
| Verwijderde shared-records | Niet tonen in regulier overzicht van ontvanger. |
| Geanonimiseerd account | Historische reconstructie blijft waar nodig mogelijk zonder actuele persoonsgegevens. |
9.33 Audit, events en historie
Gedeelde oefeningen vereisen herleidbaarheid zonder dat de auditlaag de functionele brondata vervangt.
Minimaal relevante gebeurtenissen zijn:
| Gebeurtenis | Betekenis |
|---|---|
SharedExerciseCreated | Deler heeft een afgeronde oefening met ontvanger gedeeld. |
SharedExerciseSystemMessageCreated | Systeemcommunicatie richting ontvanger is aangemaakt. |
ShareExerciseDenied | Deelactie is geblokkeerd door ontbrekende voorwaarden. |
SharedExerciseStarted | Ontvanger start de gedeelde oefening voor het eerst. |
SharedExerciseRepeated | Ontvanger maakt de gedeelde oefening opnieuw. |
SharedExerciseHiddenByRecipient | Ontvanger verwijdert het record uit eigen overzicht. |
De exacte eventnamen zijn bron-/registerafhankelijk. Het FO beschrijft de functionele behoefte aan herleidbaarheid; command- en eventregisters blijven leidend voor definitieve sleutelsets.
9.34 Lege toestanden
Lege toestanden zijn normaal wanneer de leerling wel toegang heeft tot de context, maar er geen zichtbare items zijn.
Voorbeelden:
- de leerling heeft nog geen gedeelde oefeningen ontvangen;
- alle ontvangen gedeelde oefeningen zijn uit het overzicht verwijderd;
- filters leveren geen resultaten op;
- er zijn geen nieuw ontvangen gedeelde oefeningen;
- er zijn geen al gestarte gedeelde oefeningen;
- er zijn geen afgeronde gedeelde oefeningen;
- er zijn geen actieve vrienden om mee te delen;
- er is geen afgeronde run die deelbaar is;
- er is geen afgeronde ontvangerrun voor de geschiedenisactie.
Een lege toestand mag uitleg of een passende vervolgstap tonen, maar mag geen verborgen data of technische details lekken.
9.35 Fouttoestanden
Fouttoestanden ontstaan wanneer een actie niet veilig kan worden uitgevoerd.
| Fouttoestand | Veilige afhandeling |
|---|---|
| Bronrun bestaat niet | Delen wordt geblokkeerd zonder inhoud te lekken. |
| Bronrun hoort niet bij actor | Delen wordt geweigerd. |
| Bronrun is niet afgerond | Delen wordt geweigerd. |
| Geen actieve vriendrelatie | Delen wordt geblokkeerd. |
| Ontvanger is geen actieve leerling | Delen wordt geblokkeerd. |
| Deelfeature uitgeschakeld | Delen of starten wordt geblokkeerd volgens featuregedrag. |
| Shared-record bestaat niet | Niet-beschikbaarafhandeling. |
| Shared-record hoort niet bij leerling | Toegang geweigerd zonder gedeeltelijke data. |
| Shared-record is verwijderd uit overzicht | Reguliere start/hervatroute wordt geblokkeerd. |
| Broninhoud niet veilig renderbaar | Starten/opnieuw maken wordt geblokkeerd. |
| Module niet meer beschikbaar voor uitvoering | Nieuwe start/herhaling wordt geblokkeerd waar nodig. |
| Runaanmaak faalt | Geen halfbruikbare run achterlaten. |
| Systeembericht kan niet worden gemaakt | Gedeeld record mag alleen blijven bestaan wanneer ontvanger het via overzicht alsnog kan vinden of fouttransactie correct wordt afgehandeld. |
| Verwijderen faalt | Bestaande zichtbaarheid blijft intact. |
| Concurrency bij start | Voorkom dubbele eerste ontvangerrun. |
| Concurrency bij verwijderen/starten | Server-side toestand is leidend; toon veilige melding. |
Bij fouttoestanden worden geen stacktraces, tokens, ruwe JSON/base64-payloads, GUID's of interne identifiers aan gewone gebruikers getoond.
9.36 Tellers en readmodels
Samenvattingswaarden in het overzicht zijn readmodelwaarden.
Per teller moet eenduidig vastliggen:
| Teller | Definitie |
|---|---|
| Nieuw ontvangen | Zichtbare shared-records voor huidige leerling zonder gestarte ontvangerrun. |
| Al gestart | Zichtbare shared-records met niet-afgeronde ontvangerrun. |
| Afgerond | Zichtbare shared-records met minimaal één afgeronde ontvangerrun. |
| Totaal zichtbaar | Alle niet-verwijderde shared-records voor de huidige leerling binnen actieve filters. |
| Geschiedenis beschikbaar | Aantal of boolean op basis van afgeronde ontvangerruns. |
Soft-deleted shared-records tellen niet mee in het reguliere ontvangen-overzicht. Afgeronde ontvangerruns uit verwijderde shared-records blijven wel meetellen in normale geschiedenis wanneer de geschiedeniscontext dit toestaat.
9.37 Popupfeedback
Usecases en schermdocumentatie verwijzen naar popupkeys. FO-09 dupliceert geen popupteksten, knopteksten, inputlabels of themes.
Relevante popupcontexten zijn minimaal:
| Context | Doel |
|---|---|
| Delen selecteren | Ontvanger kiezen uit actieve vrienden. |
| Delen succesvol | Bevestigen dat de oefening is gedeeld. |
| Delen mislukt | Veilige foutmelding zonder technische details. |
| Geen vrienden | Uitleg dat delen niet mogelijk is zonder actieve vrienden. |
| Gedeelde oefening niet beschikbaar | Starten of bekijken kan niet veilig. |
| Gedeelde oefening starten | Bevestiging of uitleg rond eerste start/hervatten/opnieuw maken. |
| Verwijderen bevestigen | Bevestiging vóór zichtbaarheidmarkering. |
| Verwijderen succesvol | Overzicht is bijgewerkt. |
| Verwijderen mislukt | Zichtbaarheid blijft intact. |
Het popupregister en popup-themes blijven leidend.
9.38 Functionele lifecycle
| Fase | Actor | Persistente bron | Resultaat |
|---|---|---|---|
| Bronrun afronden | Deler | ExerciseRuns | Afgeronde eigen run kan kandidaat voor delen zijn. |
| Delen kiezen | Deler | Nog geen mutatie | Server controleert deelbaarheid en vriendschap. |
| Gedeeld record aanmaken | Backend | SharedExercises | Ontvanger heeft ontvangen gedeelde oefening. |
| Ontvanger informeren | Backend | SystemMessages waar ondersteund | Ontvanger krijgt ingang naar overzicht/context. |
| Overzicht bekijken | Ontvanger | Readmodel over SharedExercises | Geen runmutatie. |
| Eerste start | Ontvanger | ExerciseRuns + ExerciseRunProgress | Eerste zelfstandige ontvangerrun. |
| Hervatten | Ontvanger | Bestaande ontvangerrun | Geen nieuwe run. |
| Afronden | Ontvanger | ExerciseRuns | Eigen resultaat en geschiedenisregel. |
| Opnieuw maken | Ontvanger | Nieuwe ExerciseRuns | Nieuwe zelfstandige ontvangerrun. |
| Verwijderen uit overzicht | Ontvanger | SharedExercises.IsDeleted | Record verdwijnt uit ontvangen-overzicht; runs blijven. |
9.39 Relatie tot andere FO-hoofdstukken
| Hoofdstuk | Relatie |
|---|---|
| Relatiebeheer | Bepaalt vriendschap als voorwaarde voor nieuw delen. |
| Oefencatalogus, niveaus, categorieën en oefeningen | Beschrijft oefening, categorie, niveau en modulecontext waar bronruns uit ontstaan. |
| Leerling: oefenen, voortgang en resultaten | Beschrijft algemene run-lifecycle, vraagvoortgang, onderbreken, afronden en geschiedenis. |
| Berichten, communicatie en notificaties | Beschrijft systeemberichten, badges, anti-afleiding en EntityType-routing. |
| Live meekijken | Gebruikt ontvangerrunvoortgang waar live meekijken afzonderlijk geautoriseerd is. |
| PDF-export en resultaatpresentatie | Beschrijft resultaatweergave en PDF-export voor afgeronde ontvangerruns. |
| Popups, templates, features en systeemnotificaties | Beschrijft popupkeys, systeemberichttemplates en featuretoggles. |
| Oefenmodules en modulepayloads | Beschrijft module- en payloadinterpretatie van historische bron- en ontvangerruns. |
| Open punten en buiten scope | Bewaakt buiten-scopegrenzen; voor gedeelde oefeningen is EntityType = SharedExercise vastgelegd. |
9.40 Gerelateerde bronverwijzingen
| Bron | Link |
|---|---|
| Technisch Ontwerp — relatiebeheer | Relatiebeheer, uitnodigingen en gedeelde oefeningen |
| Technisch Ontwerp — oefenruns | Oefenruns, voortgang, resultaten, statistieken en PDF-brondata |
| Technisch Ontwerp — communicatie | Berichten, systeemberichten, notificaties en privéthreads |
| Usecases — leerling gedeelde oefeningen | Gedeelde oefeningen |
| UC-LLN-DEL-001 — Oefening delen met vriend | Oefening delen met vriend |
| UC-LLN-DEL-002 — Ontvangen gedeelde oefeningen bekijken | Ontvangen gedeelde oefeningen bekijken |
| UC-LLN-DEL-003 — Gedeelde oefening starten | Gedeelde oefening starten |
| UC-LLN-DEL-004 — Gedeelde oefening opnieuw maken | Gedeelde oefening opnieuw maken |
| UC-LLN-DEL-005 — Ontvangen gedeelde oefening verwijderen | Ontvangen gedeelde oefening verwijderen |
| UC-LLN-DEL-006 — Delen blokkeren zonder actieve vrienden | Delen blokkeren zonder actieve vrienden |
| Schermdocumentatie — gedeelde oefening overzicht | Gedeelde oefening overzicht |
| Database-informatie — oefenruns, delen en voortgang | Oefenruns, delen en voortgang |
| Database-informatie — relatiebeheer | Relatiebeheer |
| Database-informatie — communicatie en notificaties | Communicatie en notificaties |
| FO — relatiebeheer | Relatiebeheer |
| FO — leerling oefenen, voortgang en resultaten | Leerling: oefenen, voortgang en resultaten |
| FO — berichten, communicatie en notificaties | Berichten, communicatie en notificaties |
| FO — PDF-export en resultaatpresentatie | PDF-export en resultaatpresentatie |
| FO — popups, templates, features en systeemnotificaties | Popups, templates, features en systeemnotificaties |
| FO — oefenmodules en modulepayloads | Oefenmodules en modulepayloads |
| Ontwerpbron — popup-register | Popup-register |
| Ontwerpbron — event-register | Event-register |
| Ontwerpbron — command-register | Command-register |
| Ontwerpbron — business rules | Business rules |