- Libelle in de vijverplaat kreeg weer vier symmetrische vleugels
- Zeepaardje in het koraalrif herbouwd van een onherkenbare buis naar een
duidelijk zeepaardje, verplaatst zodat het niet meer over de clownvis valt
- Nieuwe coloringLegPath()-vorm: giraffe en zebra hebben nu getapte,
licht geknikte poten in plaats van rechte kokerpoten
- Instellingenindeling omgedraaid: de kleurplaat (thema/plaat) is weer
direct zichtbaar, kleurhulp/reset gaan achter het tandwiel
- Letterblokken en rekenwidgets: niveauknoppen naar het tandwiel, het
woord/thema blijft direct zichtbaar
- Klok, geldrekenen, plaatswaardetabel, boom&blad/vogels/planten en
topografie: spel/activiteit (en bij geld/plaatswaarde het bijpassende
veld) staan weer in de vaste bovenbalk, niveau staat achter het tandwiel
- Plaatswaardetabel toont nu ook in verkennen-stand een vaste bovenbalk
(spel, getal, dobbelsteen) in plaats van alleen in bouwen-stand
- Bugfix onderweg: niveauwissel in verkennen-stand van de plaatswaardetabel
sprong per ongeluk naar bouwen-stand - nu blijft de stand behouden
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011YErxhic5w9K57zmt8Q1uS
Bij veel widgets nam de instellingenstrook te veel hoogte in, vooral bij een
smal widgetvenster waar de rij naar meerdere regels uitwaaierde. Nieuw
gedeeld patroon: besturing die voortdurend nodig is (kleur, niveau,
woordbron) blijft in één compacte rij zichtbaar; besturing die maar zelden
wordt aangepast (thema, geluid aan/uit, invoerwijze, bereik) gaat achter een
inklapbaar ⚙-paneel. Dit patroon bestond al voor klok/geld/rekengetallen/
wereld (learningShell() in learning.js) - nu als widgetGear()/gearField() in
core.js beschikbaar voor de rest van de app, met dezelfde .edu-settings-
opmaak zodat het overal hetzelfde oogt en werkt.
- kleurplaten: twee volle rijen (thema/plaat + kwast/emmer/gum/kleur/dikte/
hulp/reset/klaar) teruggebracht naar één vaste rij (gereedschap, kleur,
dikte, klaar) plus het ingeklapte paneel (thema, plaat, kleurhulp, reset).
Losstaand: coloring.css gebruikte @media(max-width:620px) in plaats van de
@container widget-conventie die de rest van de app gebruikt, waardoor die
regels nooit afgingen bij het verkleinen van het widgetvenster zelf - nu
gecorrigeerd.
- letterblokken: geluid, invoerwijze en aantal kaarten in het paneel; niveau
en woordbron blijven vast.
- rekenwidgets (optellen/aftrekken/keer/delen/procenten): geluid en
invoerwijze in het paneel; niveau blijft vast.
- ballonnenwoord: geluid in het paneel.
- flitswoorden: flitstijd in het paneel.
- getallenlijn: het hele bereik-instelblok (van/tot/stap/nieuw) in het
paneel - dat stond toch al uit voor leerlingen met een beheerd niveau.
- zinsbouwer: het rijtje voor eigen woorden toevoegen in het paneel; de
speelknoppen (verrassing/ongedaan/wissen/voorlezen) blijven vast.
- timer: geluid en weergavevorm in het paneel; starttijden en start/reset
blijven vast.
- geluidsmeter: de twee drempelschuifjes plus de privacynotitie in het
paneel.
Widgets die dit patroon al hadden (klok, geld, breuken, plaatswaarde,
woordsoorten, bomen/vogels/planten, topografie, stemming, stemming-poll,
dagplanning) of waar de rij al compact genoeg was (schrijfblad, hakken en
plakken, dobbelstenen, notities, naamtrekker) zijn ongewijzigd gelaten.
Geverifieerd door elke aangepaste widget live via de echte makeWidget()/
REGISTRY in een headless browser te openen, het paneel open en dicht te
klappen en te controleren op consolefouten - ook op de minimale
widgetbreedte (coloring, minW 390). 202 tests groen.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011YErxhic5w9K57zmt8Q1uS
Drie platen die na eerdere reparaties nog niet klopten, nu fundamenteel
anders aangepakt in plaats van bijgeschaafd.
Boom van vier seizoenen: het idee van één cirkel in vier kwarten werkte niet,
ook niet met ronde plukken op de rand - het bleef een bal met een kruis erin.
Vervangen door vier losse boompjes naast elkaar, één per seizoen, elk met een
eigen kroonvorm: lente (bloesem met groene blaadjes), zomer (vol groen blad
met wat vruchten), herfst (oranje/geel blad, twee vallende blaadjes op de
grond) en winter (kale boom - drie echte, gevulde takken vanuit verschillende
hoogtes op de stam, met dunne twijgjes en sneeuwklompjes op de uiteinden).
Eerste versie van de kale winterboom liet takken vanuit één punt uitwaaieren
en oogde als vuurwerk; met gevulde taksegmenten en een aftakpunt per tak is
het nu een boom.
Dinosaurus: nog niet herkenbaar genoeg. Volledig hertekend naar de klassieke,
direct herkenbare langnekdino-verhoudingen: een veel langere gracieuze hals,
een groot rond lijf, een lange dunne staart en een klein koppie met een grote
vriendelijke oog - in plaats van de kortere, gedrongen versie van de vorige
ronde.
Windmolen in de duurzame stad: de drie wieken stonden niet gelijk verdeeld
(twee dicht bij elkaar, één ver weg) en één wiek liep dwars door de zon heen.
Nu netjes 120 graden uit elkaar en gedraaid zodat geen enkele wiek de zon
raakt.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011YErxhic5w9K57zmt8Q1uS
Gecontroleerd door elke plaat op ware grootte te renderen en niet op de
gemiddelde vinkjes te vertrouwen; drie echte problemen bleken over het hoofd
gezien te zijn.
Losse bladeren die kaal aan de boom hingen:
- boom van vier seizoenen: de kroon was een gladde cirkel met losse spitse
blaadjes op de rand, die als ogen of aangeplakte snippers lazen. Vervangen
door ronde plukken ruim binnen elk kwart, in drie maten zodat ze niet als
een paar ogen naast elkaar staan.
- regenwoud: de bladeren zweefden los in de lucht tussen de twee stammen,
met alleen een puntig uiteinde dat de stam raakte. Beide stammen kregen nu
een echte kroon erbovenop, met bladplukken erin.
De dinosaurus was echt vreemd: de hals was een rechte dikke staaf met een los
rondje erboven als kop, en de poten waren twee brede lappen die als "twee
poten" oogden. Volledig hertekend: een S-vormige hals, kop en snuit als één
doorlopende ovale vorm met oog, neusgat en mond, en vier duidelijk
gescheiden poten met elk een eigen voet.
Giraf en zebra op de savanne hadden wel vier potervakken, maar alleen de
achterpoten hadden een hoef - de voorpoten liepen dood zonder afsluiting en
vielen daardoor optisch weg, waardoor het dier op twee poten leek te staan.
Alle vier de poten hebben nu een eigen hoef.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011YErxhic5w9K57zmt8Q1uS
De twee platen die ik zelf had aangemerkt plus de overige zwakke plekken uit de
visuele controle. Audit blijft schoon op alle drie de niveaus: geen
onbereikbare vakken, geen onzichtbare of afdwalende lijnen.
Dieren met vier poten in plaats van twee latjes:
- savanne: giraf en zebra hebben nu vier poten met een knik en een hoef, een
langere en slankere giraffennek die breed uitloopt in de schouder, een kop
met snuit, ossenhoorns en oor, en een manestreep bij de zebra.
- dinosaurusvallei: vier poten met voeten en een staart die echt versmalt.
Vormen die verkeerd lazen:
- boom van vier seizoenen: de kroon was een gladde cirkel met een kruis erin en
las als een bal. De vier seizoenskwarten hebben nu een geschulpte buitenrand,
dus het leest als bladerdek. De losse plukken op de rand zijn vervangen door
bladclusters binnen elk kwart, waardoor ook de inkepingen verdwenen die
ontstonden waar plukken en bladvormen elkaar overlapten.
- koraalrif: het zeepaardje was een smal buisje dat als worm las. Nu een
stevige romp met een aparte gekrulde staart, de rugvin op de rug in plaats
van dwars door het lichaam, en meer buikringen.
- vrienden in zee: de schildpad stond klem tegen de rechterrand; hij is groter
en verder naar binnen geschoven, met grotere schildplaten.
Lege vlakken gevuld, want er was niets te kleuren:
- kleine tuindieren: zon, wolk en een vlinder in de bovenhelft.
- koraalrif: een schooltje visjes in de lege bovenhoek; de bellen zijn
meegeschoven.
- feesttaart: een tafelkleed met schulprand in de onderste strook.
- grote graafmachine: zonnestralen, zoals bij de andere zonnen.
Losse elementen vastgezet:
- regenwoud: de bladeren aan de rechterkant zweefden los naast de stam en
sluiten nu aan, met bladnerven op niveau 3.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011YErxhic5w9K57zmt8Q1uS
Systematisch nagelopen met een meetkundige audit in de browser plus een
visuele controle van alle 20 platen op ware grootte (800x600). De audit meet
per niveau welke kleurvakken volledig achter latere vakken verdwijnen, welke
detaillijnen onzichtbaar zijn en welke lijnen buiten het blad vallen.
Onbereikbare kleurvakken verholpen (waren onzichtbaar én niet te kleuren):
- kleine tuindieren: de kop van het lieveheersbeestje zat volledig achter het
schild; de kop komt nu boven het lichaam uit.
- molen in de polder: de onderste wiek verdween achter de romp. De wieken
staan nu als schuin kruis, zodat alle vier vrij liggen, met latwerk erin.
- regenwoud: een mosplukje zat achter de ara.
- kasteel: de verre heuvels waren voor 89% bedekt en zijn opgeschoven.
- leven rond de vijver: twee bloemblaadjes van de waterlelie zaten achter de
vis; de bloem staat nu naast de vis.
Overtollige strepen weggehaald:
- graspollen in vlinder, tuindieren, molen en vogelnest stonden los in het
gras; ze beginnen nu op de grondlijn zelf.
- feesttaart: losse kruisjes in de lucht lazen als vergissingen, nu confetti-
stippen; de ballontouwtjes lopen door tot op de tafel.
- bergkamp: de graatlijnen liepen door tot in het meer en stoppen nu bij de
bergvoet.
- boom van vier seizoenen: een losse kromme stond midden in de kroon.
- kasteel: het bootje overlapte de brug, waardoor zeil en brugdek door elkaar
heen liepen; het ligt nu links in de rivier.
- koraalrif: de rugvin van het zeepaardje stak dwars door het lichaam.
Ontbrekende strepen toegevoegd:
- schorslijnen op de stammen van picknick en regenwoud.
- glazuur op de middelste laag van de taart (alleen boven- en onderlaag hadden
het).
- sneeuwkappen op beide bergtoppen zijn groter en echt zichtbaar.
- fanlijnen in het fankoraal, bloemblaadjeslijnen in de bloesems.
Vormen die verkeerd lazen hertekend:
- tulpen bij de molen hadden een ronde koepel en lazen als paddenstoelen; nu
een puntige kelk van drie blaadjes.
- lensvormen die als ogen of blaadjes lazen zijn ronde plukken geworden in de
herfstboom, de acacia (met een derde pluk om het "ogenpaar" te breken) en de
kroon van de vierseizoenenboom.
- de kikker had lensvormige poten naast zich; nu poten met knik en voet.
- graspollen op de savanne zijn tuiltjes van twee blaadjes.
- dinosaurus: dikkere poten, lava op de kraterrand in plaats van in de kegel.
- vlinder: acht symmetrische zonnestralen in plaats van vijf scheve.
- rechte kadelijnen in molen, bergkamp, kasteel, dinosaurusvallei, tuindieren
en vierseizoenen zijn golvend gemaakt; ze lazen als een liniaal.
- leven rond de vijver had een lege bovenhelft: zon, wolk en zwaluwen erbij.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011YErxhic5w9K57zmt8Q1uS
Kwast en verfemmer werkten al, maar het resultaat was onzichtbaar: de
contourlaag zette fill="#fff" op elk vak en vertrouwde op
mix-blend-mode:multiply om dat onschadelijk te maken. Doordat .coloring-ink
zelf een stacking context is (position+z-index), vormt die een geisoleerde
blendgroep zonder achtergrond, en werd het wit gewoon dekkend over de hele
tekening gelegd. Live nagemeten met headless Chromium.
- Tekenmodel omgezet naar een echte schildersvolgorde in een enkele SVG: elk
vak wordt uitgeklapt naar vak -> verflaag -> contour, zodat verf zichtbaar
blijft en latere vakken de verf en contour van eerdere vakken afdekken.
Daarmee kijk je ook niet meer door figuren heen.
- Canvas vervangen door SVG-streken: geen opschalingsonscherpte meer en geen
donkere naden (dekking staat per streek op de groep, niet per segment).
- Kwast blijft binnen de lijnen als hulp, gestuurd door niveau: groep 1-4 op
niveau 1 en 2, groep 5-8 op niveau 1, daarboven vrij schilderen.
- Verfemmer dekt een vak volledig; de gum pelt de bovenste laag af (eerst de
vulling, daarna de streken eronder).
- Kleurwijzer toegevoegd: op niveau 1 laat een stip per vak de voorgestelde
kleur zien, op niveau 2 op te vragen met een knop, op niveau 3 uit.
- Niveau sloopt de tekening niet meer: data-tier staat alleen op groepen en
detaillijnen, dus een rekwisiet verdwijnt als geheel en de plaat is op elk
niveau een complete tekening. Niveau 3 voegt alleen fijn lijnwerk toe.
- Atlas hertekend naar 20 platen, 5 per groepenband en 1 per thema. Twee
lijndiktes, vakken op maat van de band, geen evenodd-gaten, en composities
met voor-, midden- en achtergrond.
- partBelow/elementFromPoint en het omzetten van pointer-events vervallen:
aanwijzen gebeurt meetkundig met isPointInFill/isPointInStroke.
- langchange-listener ruimt zichzelf op na demontage.
- Staat bewaart nu streken in plaats van een PNG; oud werk met een ink-PNG
blijft zichtbaar.
- Tests: asserties die de bug vastzetten verwijderd en vervangen door een
regressietest die verbiedt dat CSS een fill op een kleurvak zet, plus
controles op gesloten vakken, geen transform, tier-regels, vakaantallen per
niveau en de clip-matrix.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011YErxhic5w9K57zmt8Q1uS
- Teken alle 28 scènes vanaf een leeg canvas opnieuw met samenhangende silhouetten en detailniveaus per leerjaar.
- Geef dieren soortspecifieke anatomie, natuurlijke verhoudingen en vloeiende realistische contouren.
- Borg gesloten vulvakken, correcte laagvolgorde en blijvend zichtbare contour- en binnenlijnen.
- Verwijder de oude reparatielaag en voeg anatomische en functionele regressietests toe.
- vervang alle 28 kleurplaten door samenhangende scènes met organische contouren en leeftijdsgerichte detaillering
- houd buiten- en binnenlijnen zichtbaar boven kwastwerk en sluit verfemmerkleuren zonder witte rand aan
- borg gesloten kleurvakken, anatomische laagvolgorde en scene-opbouw met uitgebreide regressietests
- laat de gum ook verfpotvullingen bij tikken en slepen verwijderen
- vervang dubbele filterlagen door één gemaskeerde contourlaag zonder witte halo
- verberg overlappende herkenningshulplijnen en dek achterliggende contouren correct af
- voeg regressietests toe voor gum, vulranden en lijnlagen
Gewijzigde functionaliteiten:
- Vervang losse geometrische dierdelen door vloeiende Bézier-silhouetten met geloofwaardiger anatomie.
- Schilder poten, staarten, vinnen, vleugels, wielen en andere appendages achter het hoofdsilhouet voor aansluitende contouren.
- Voeg een SVG-occlusiefilter toe dat alleen werkelijk zichtbare lijnen boven kwast en verfpot toont.
- Verfijn lijngewichten, witte contrastrand, wielkasten, manen en objectcontouren.
- Geef kwast, verfpot en gum zichtbare labels en verbeter ARIA-groepering van gereedschappen en palet.
- Voeg regressietests toe voor organische contouren, schildervolgorde, gesloten kleurvakken en UX-bediening.
Tests:
- npm test (201 geslaagd)
Gewijzigde functionaliteiten:
- Vervang foutgevoelige zwarte en witte SVG-vullingen door transparante contourlagen.
- Laat de verfpot rechtstreeks de aanklikbare kleurvakken bedienen.
- Vervang het kleurpotlood door een vloeiende, pendrukgevoelige kwast met eigen icoon en cursor.
- Migreer opgeslagen potloodstate automatisch naar het nieuwe kwastgereedschap.
- Voeg regressietests toe voor achtergrond, laagweergave en gereedschapsinvoer.
Tests:
- npm test (201 geslaagd)
Gewijzigde functionaliteiten:
- Splits kleurplaten in kleur-, potlood- en bovenste inktlaag zodat contouren zichtbaar blijven.
- Versterk lijnen met een lichte contrastrand en donkere inkt, met behoud van de juiste overlappingen.
- Vernieuw werkvlak, gereedschappen en kleurenpalet voor een krachtiger grafische uitstraling.
- Voeg regressietests toe voor laagvolgorde en inktweergave.
Tests:
- npm test (201 geslaagd)
Gewijzigde functionaliteiten:
- Brengt een rustige lijnhiërarchie aan met subtiele buitenkaders, stevige kleurvlakken en lichtere binnenlijnen.
- Voegt herkenbare textuurdetails toe aan onder meer vlinder, herfstboom, taart, zeedieren, molen, raket en kasteel.
- Verbetert het fietsframe in de duurzame-stadplaat en markeert kleurvlakken bij aanwijzen met de verfemmer.
- Borgt het consistente SVG-profiel voor alle 28 kleurplaten met aanvullende tests.
Tests: 201 geslaagd (npm test); 5 gerichte kleurplaattests geslaagd.
Gewijzigde functionaliteiten:
- De open stippen in de doelvakken stonden links-boven in hun rastercel in
plaats van gecentreerd, waardoor het patroon scheef oogde; ze staan nu op
dezelfde as als de gevulde stippen.
- De stippen van de geldblokken en van alle cijferblokken in een smalgemaakte
widget staken onder het blok uit. De stipmaat komt nu uit een variabele die
elk bloktype naast zijn eigen hoogte zet, in plaats van uit losse
hardgecodeerde regels per widget.
- De smalle-widget-weergave verkleint alleen nog de breedte; blokhoogtes
blijven gelijk, want juist het verkleinen van de hoogte duwde het raster naar
buiten. Letterblokken krijgen daar een passend kleiner cijfer/letterformaat.
- Nieuw vangnet: het raster houdt altijd zijn maat en het label geeft mee als
een blokformaat krap is, zodat een nieuw blokformaat dit niet opnieuw kan
veroorzaken.
Tests: 196 geslaagd (4 nieuw in test/dot-grid.test.js; die vier vallen ook
daadwerkelijk om op de oude CSS). Daarnaast in de browser opgemeten voor alle
zeven blokcontexten, bij normale en smalle widgetbreedte, plus screenshots en
een controle in de echte leerlingweergave.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0126hjBPD2ggZ2LEoDYZSW7S
Gewijzigde functionaliteiten:
- Letterblokken logt per afgerond woord hoeveel pogingen het kostte en welke
letter op welke plek fout ging (beide invoerwijzen: blokken slepen en typen).
- Ballonnenwoord logt nu ook een verloren woord; dat leverde tot nu toe geen
enkele voortgang op. Een gewonnen woord telt de fout geraden letters mee.
- Flitswoorden stuurt de bestaande zelfcheck ("Gelukt" / "Nog oefenen") door
naar de voortgang; die uitkomst werd eerder weggegooid.
- Hakken & plakken krijgt dezelfde zelfcheck en daarmee als laatste taalwidget
een goed/fout-moment; de oefening zelf verandert niet.
- Voortgang-tab toont de fouten van taal: naast fout afgesloten opdrachten ook
"na N pogingen goed" (letterblokken kent geen faalmoment) en zelfchecks.
- Reeksstappen met flitswoorden of hakken & plakken wachten nu op een echt
afgerond moment in plaats van meteen te completeren.
Tests: 192 geslaagd (7 nieuw), plus live nagelopen in de leerlingweergave met
echte interactie per widget en een screenshot van de Voortgang-tab.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0126hjBPD2ggZ2LEoDYZSW7S
Gewijzigde functionaliteiten:
- Centreert doelvakken in letter-, reken-, klok-, geld-, plaatswaarde- en wereldwidgets.
- Houdt lange woordrijen scrollbaar zonder de eerste vakken af te snijden.
- Centreert kleinere geplaatste cijferblokken binnen hun doelvak.
- Verwijdert de links uitgelijnde compacte woordrij.
Tests: 160 geslaagd.
Gewijzigde functionaliteiten:
- Voegt vijf afwisselende avatardansen toe.
- Houdt lichaam, haar en accessoires als een verbonden SVG-figuur.
- Danst na afgeronde woordgroepen, flitsrondes, galgjerondes en rekenrondes.
- Respecteert verminderde beweging met een stil feestbeeld.
Tests: 159 geslaagd; npm audit: 0 kwetsbaarheden.
- Bug gevonden en bevestigd (niet blind aangenomen): math.js riep
onProgress maar op ÉÉN plek aan, in endRound(), NA een heel blok van
10 sommen, met alleen het geaggregeerde totaal. Eén sessie van 10
sommen - "een groep opdrachten" - leverde dus precies 1 rij op in
progress_events, niet 10, en maakte "welke som ging fout" onmogelijk
te zien (alleen een totaaltelling per blok).
- Fix: onProgress verplaatst naar check(), bij elke afgeronde som (goed
op de eerste keer, of opgeven na 3 pogingen) - een sessie van 10
sommen levert nu 10 progress_events-rijen op, elk met een nieuw
optioneel detail-veld (welke som, gegeven antwoord, juist antwoord).
letters.js/ball.js blijven deze ronde ongemoeid (hun granulariteit
veroorzaakte niet deze bug).
- Nieuwe kolom progress_events.detail (JSONB, nullable, puur additief -
db/020_progress_detail.sql). POST /my/progress accepteert het
optioneel; te groot/geen plain object wordt stilzwijgend genegeerd
zonder de rest van de log-poging te laten falen (detail is decoratief,
geen kernfunctionaliteit).
- Voortgang-tab (admin.js) herontworpen, zelfde ontwerptaal als de
eerdere School-navigator-herbouw: vakgebied-tabs, een
klassenmanagement-infobadge (Groep {n} · Niveau {n}, opgehaald via de
bestaande /levels/pupil/:id-route) zodat resultaten meteen tegen het
toegewezen niveau afgezet kunnen worden, een met de hand getekende
SVG-nauwkeurigheidsring + staafdiagram (goed/fout per dag, laatste 14
dagen - geen library, zelfde aanpak als avatar.js) en een "recente
fouten"-lijst die precies toont welke som fout ging. De bestaande
ruwe tijdlijn blijft eronder staan, niets is verwijderd.
- Terzijde gevonden en gefixt: .am-btn.active bestond nergens in de
CSS, waardoor de vakgebied-tabs (hier én in Klassenmanagement,
v0.4.34-beta) geen enkele visuele aanduiding hadden welke actief was.
- Tests: test/progress-logging.test.js uitgebreid met 4 tests voor het
detail-veld (opgeslagen, te groot genegeerd, geen plain object
genegeerd, afwezig blijft null). Volledige testsuite: 132/132.
- Live geverifieerd: een math.js-sessie met een mix van goede/foute
sommen doorlopen en bevestigd dat er 3 aparte POST /my/progress-
aanroepen gebeuren voor 3 sommen (niet 1 aggregaat), elk met het
juiste detail; de herbouwde Voortgang-tab geopend met gemockte data
en met screenshots bevestigd dat de nauwkeurigheidsring (38% = 3/8,
rekenkundig geverifieerd), het klassenmanagement-infobadge, de
staafdiagram en de "recente fouten"-lijst (met de daadwerkelijke som)
correct tonen, én dat de active-tab-fix ook op de Klassenmanagement-
tab zichtbaar is.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014EPxzBVRXZZnBPvSAaPAbJ
- Grootste openstaande roadmap-punt. Nieuwe tabel pupil_levels
(db/019_pupil_levels.sql, zelfde class_id/pupil_id-vorm als
assignments) legt per vakgebied (taal/rekenen/world) een niveaugroep
vast (groep 1-8, gebaseerd op de leerjaren van de basisschool waaraan
de leerdoelen gekoppeld zijn) + niveau (1-3, fijnmazige verfijning
BINNEN die groep). Klas-standaard met individuele leerling-overrides,
net zo laagdrempelig instelbaar als de standaard - het speciaal-
onderwijs-geval waar dat vanaf het begin de norm is.
- Server: GET/PUT/DELETE /levels/class/:id en /levels/pupil/:id
(src/api.js) hergebruiken exact het assignments-patroon (upsert via
partial-unique-index, pupil-eerst-dan-klas-resolutie), plus
GET /my/level voor de leerling-kant. Zelfde permissie
(assignments.manage) en sameSchool/teacherOnly/pupilAccessible-
guards als de bestaande toewijzingsroutes.
- Nieuwe admin-tab "Klassenmanagement": klas + vakgebied kiezen, een
klas-standaard instellen, en per leerling de effectieve groep/niveau
zien (overerft van de klas tenzij een eigen afwijking is ingesteld)
met bewerk- en terug-naar-standaard-knoppen.
- ECHTE inhoudskoppeling, niet alleen een standaardwaarde: rekenen is
het eerste vakgebied waarvan de SLO/TULE-leerlijn direct in
getalgrenzen te vertalen is (groep 3 t/m 20, groep 4 t/m 100, groep 5
t/m 1000, groep 6 t/m 10.000). Nieuwe SLO_MATH_RANGES/mathRangeFor()
in data.js; math.js's gen() gebruikt dit voor de daadwerkelijke
getallen zodra een leerling een groep heeft (S.yearGroup), met het
bestaande niveau 1-3 als verfijning daarbinnen. Zonder groep blijft
het oude vaste 10/20/100-gedrag exact bestaan.
- pupil.js geeft groep/niveau door aan taal/rekenen-widgets bij het
mounten: niveau is een standaardwaarde (een al opgeslagen bord-niveau
blijft leidend), groep wordt voor rekenen-widgets altijd meegegeven
(er is geen "oud" groep-concept om te respecteren). Terzijde ook de
stille .catch() op de nieuwe async renderPupilWidgets() opgelost.
- Taal/wereldoriëntatie krijgen deze ronde nog geen eigen
inhoudskoppeling (vraagt een eigen contentbron per groep, nog niet
uitgezocht) - eerlijk benoemd als vervolgstap, geen loze belofte.
- Tests: test/pupil-levels.test.js (10 tests) dekt de server-routes
(mocked-pool-patroon) én - via dezelfde vm-techniek als elders in
test/widgets.test.js voor MONEY_LEVELS - een ECHTE (niet regex-)test
van mathRangeFor die bevestigt dat elke groep de juiste getalgrens
oplevert en niveau nooit boven de groep-grens uitkomt. Twee bugs
gevonden en gefixt tijdens het schrijven van deze tests: null-yearGroup
werd per ongeluk als groep 1 behandeld i.p.v. "geen groep", en de
testrol had geen klas-eigenaarschap waardoor 403 in plaats van 200
terugkwam. Volledige testsuite: 128/128.
- Live geverifieerd in de sandbox: klas-standaard + leerling-override
instellen in de nieuwe admin-tab, en drie scenario's in de
leerling-omgeving die bevestigen dat de daadwerkelijk gegenereerde
sommen binnen de juiste groep-grens blijven (geen klassenmanagement →
ongewijzigd oud gedrag; groep zonder eigen bord-niveau → volledige
groep-grens; groep mét een al opgeslagen bord-niveau → dat niveau
blijft leidend, geschaald naar de juiste groep-grens).
- public/js/data.js bevatte al niet-gerelateerde, nog niet gecommitte
wijzigingen van vóór deze sessie (extra taalthema's/woorden) - alleen
de SLO_MATH_RANGES/mathRangeFor-hunk is hier meegenomen (git add -p),
de rest blijft bewust ongemoeid staan, net als test/language-library.test.js.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014EPxzBVRXZZnBPvSAaPAbJ