- 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:
- 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:
- 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
- De math.js-pilot (v0.4.23-beta: eigen personage kort naast "Goed!" bij
een juist antwoord) hergebruikt in vier andere widgets, zoals destijds
al voorzien in de roadmap: klok (mountClock), geld (mountMoney),
plaatswaarde (mountPlacevalue) en de wereldoriëntatie-spelopdracht
(mountWorldQuiz - dekt bomen/vogels/planten in één keer - en
mountTopography).
- Zelfde patroon overal: bij S.feedback==='good' (of S.spellSolved) en
een ingesteld personage verschijnt renderAvatarFace(...,"md") met de
av-cheer-animatie naast het bestaande feedbackbericht - puur visueel,
geen nieuw feedbacktype. Zonder personage blijft het gedrag exact
ongewijzigd.
- Geverifieerd met echte oplos-interacties (niet alleen mounten): klok
(typemodus + toetsenbord), geld (typemodus + toetsenbord), plaatswaarde
(blokken plaatsen via toetsenbord-Enter) en de spelopdracht (letters
plaatsen via toetsenbord-Enter) - in alle vier verschijnt het
personage daadwerkelijk in de feedback-HTML na een echt juist
antwoord. Volledige testsuite: 112/112.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014EPxzBVRXZZnBPvSAaPAbJ
- Nieuwe migratie db/018_user_avatar.sql: kolom avatar_data (jsonb) op users.
- publicUser() geeft avatar overal automatisch mee (login, /auth/me,
/admin/users) - bestaande school/klas-rechten regelen vanzelf wie welke
personages ziet, geen nieuwe permissie-sleutel nodig.
- Nieuwe route PUT /me/avatar (open voor elke ingelogde rol, zelfde patroon
als /me/data): valideert soort/kleuren/haar/accessoires, slaat de eigen rij op.
- Nieuwe gedeelde module public/js/avatar.js: personage samenstellen uit
soort (dino/monster/dier - elk met een vast eigen lichaamsdeel, ook de
gevraagde dinostekels), lichaams- en haarkleur, haarstijl en hoofd-/
lichaamsaccessoires; gedeelde editor-UI voor zowel de instellingen-sectie
"Mijn personage" als de nieuwe widget.
- Instellingen-sectie "Mijn personage" (cms.js-patroon) - de leerling-toegang,
want widgets van categorie "class" zijn niet toewijsbaar in het
afgeschermde leerling-speelscherm.
- Widget 🦖 toegevoegd aan het bord (categorie "class") voor staf en
volledige-whiteboard-gebruikers.
- School-navigator (admin.js): leerkracht/beheerder ziet nu het personage
van elk klaslid in de personenlijst i.p.v. altijd de initialen-cirkel.
- Voorbereiding gerelateerd roadmappunt: math.js toont het eigen personage
kort naast "Goed!" als aanmoediging (pilot in één widget, geen nieuw
feedbacktype); zonder ingesteld personage blijft het gedrag ongewijzigd.
- Vertalingen (nl+en) voor de nieuwe widget, instellingen-sectie en editor.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014EPxzBVRXZZnBPvSAaPAbJ
- Geluidsmeter: meet het klasgeluid live via de microfoon in een verticale
meter (rustig/pratend/te luid). Twee aanpasbare streefniveaus ("Rustig
tot" / "Te luid vanaf") laten de leerkracht de meter afstemmen op het
eigen lokaal en apparaat. Microfoon staat standaard uit en start alleen
na een expliciete klik; er wordt niets opgenomen of verstuurd, alles
blijft lokaal in de browser. Stopt de microfoonstream vanzelf zodra de
widget van het bord verdwijnt, ook als "Stop" niet eerst is ingedrukt.
- Gevoelszones: individuele check-in met vier zones (blauw/groen/geel/
rood, Zones of Regulation-stijl) - elke zone geeft een korte uitleg én
een concrete tip om jezelf te helpen. Anders dan de bestaande
Gevoelsmeter (mood.js), die een anonieme klaspoll is.
- Ademhalingsoefening: een groeiende/krimpende cirkel begeleidt rustig
ademhalen in drie instelbare tempo's (4-4, 4-7-8, box breathing),
met rondjesteller.
- Complimentenmachine: trekt een willekeurig compliment uit twintig
kindvriendelijke complimenten, met dezelfde spin-en-onthul-animatie als
de namenkiezer.
- Alle vier volledig tweetalig (nl/en), toegevoegd aan de mobiele-dekking-
test, en geverifieerd in de browser inclusief een echte (fake) micro-
foonstream voor de geluidsmeter.
- De nieuwe "Letterblokken"-werkvorm (v0.4.18) verklapte op elk niveau
altijd elke letter - alleen de soorten-/plaatsenpool werd moeilijker,
de spelopdracht zelf bleef identiek. Bij de originele letterblokken-
widget (letters.js) maakt niveau juist de opdracht zelf moeilijker:
niveau 1 verklapt alles, niveau 3 niets.
- Zelfde schaal nu ook hier: niveau 1 toont elke letter, niveau 2 ongeveer
de helft (willekeurig gekozen, vast per opdracht), niveau 3 toont geen
enkele letter. Het puntenpatroon per vak blijft op elk niveau zichtbaar
als tastbare hint, ook wanneer de letter zelf verborgen is.
- Geverifieerd: niveau 1 toont 11/11 letters, niveau 2 ~helft, niveau 3
0/13 (met de puntenpatronen nog intact).
- Bomen/vogels/planten/topografie verstopten "Niveau" als een los
keuzeveld onderin het inklapbare Instellingen-paneel; de oefenklok,
het geldwidget, plaatswaarde en rekenwidgets tonen niveau altijd als
een knoppenrij bovenaan, direct zichtbaar tijdens het spelen.
- Niveau is nu overal dezelfde knoppenrij (Niveau 1/2/3, met uitleg per
knop via title, net als bij de oefenklok) direct in de bovenbalk naast
de score - geen Instellingen meer nodig om niveau te wisselen.
- Niveau wisselen zet score en reeks terug naar 0, zoals bij de andere
oefenwidgets (voorheen bleef de score gewoon doorlopen).
- Topografie: de knoppenrij verdwijnt bij "Landsdelen", waar niveau toch
al niet van toepassing was - zelfde gedrag als voorheen, nu alleen
consistent met de rest.
- Bomen, vogels en wilde planten krijgen twee nieuwe werkvormen naast
Leren/Quiz: Flitskaarten (naam kort tonen, dan zelftoets - zelfde opzet
als het losse Flitswoorden-widget) en Letterblokken (de naam met
sleepblokken spellen, zelfde mechaniek als de letterblokken-widget,
inclusief puntenpatroon per letter).
- Topografie krijgt dezelfde twee werkvormen: flitskaarten tonen de kaart
met de plek pas gelabeld na onthullen, letterblokken laat de naam van de
gemarkeerde provincie/plaats/rivier/werelddeel spellen.
- Letterblokken werkt ook bij namen met spaties (bv. "Witte
paardenkastanje") - spaties worden een visuele tussenruimte, geen vak.
- Geverifieerd door alle vier widgets (bomen/vogels/planten/topografie)
volledig te spelen: flitskaart onthullen + zelftoets, en een woord
volledig spellen puur op basis van de getoonde puntenpatronen.
- De vorige puntenpatroon-fix (v0.4.16) loste alleen op dat de tien
cijferblokken onderling verschillen. De écht ontbrekende stap: bij de
letterblokken en de rekenwidgets (madd/msub/mmul/mdiv/mpct) toont een
leeg vakje altijd het puntenpatroon van het cijfer/de letter die er
hoort te staan - een tastbare hint, ongeacht wat er al ligt. Bij de
oefenklok en het geldwidget toonde het vakje in plaats daarvan niets
(leeg) of het patroon van wat er toevallig al in lag - geen hint.
- Oefenklok (blockAnswer), geldwidget (digitAnswer) en de nieuwe
plaatswaarde-oefening (buildAnswer) tonen nu overal het patroon van het
juiste doelcijfer per vak, consistent met letterblokken/rekenwidgets.
- Geverifieerd door drie oefeningen (geldrekenen niveau 2/3, oefenklok
niveau 3, plaatswaarde niveau 3) volledig op te lossen met uitsluitend
de puntenpatronen als leidraad (geen tekst gelezen) - in alle gevallen
"Goed gedaan!".
- De cijferblokken (oefenklok, geldwidget) hergebruikten de braille a-j-
patronen, die nooit de onderste rij (posities 3/6) gebruiken - daardoor
leken alle tien blokken op elkaar. Eigen DIGIT_DOTCODE-tabel die alle
zes stippen inzet, geeft elk cijfer nu een echt eigen vorm.
- Plaatswaardetabel-widget had geen enkele oefenvorm (alleen een vrij
invoerveld); nieuwe "Bouwen"-stand met drie niveaus (T/E, H/T/E, of
HD/TD/D/H/T/E) laat kinderen een getal opbouwen door cijferblokken in
de juiste kolom te slepen, met score/reeks en directe feedback - zelfde
bouwsteen als de oefenklok/het geldwidget. De vrije verkenstand blijft
ongewijzigd bestaan.
- Bijvangst: instellingenvelden met .hidden (bv. "24-uursklok" bij de
oefenklok) werden nooit echt verborgen door een CSS-specificiteitsbotsing
(.edu-controls label versloeg [hidden]); toegevoegde regel herstelt dit
voor alle leerwidgets.
- Oorzaak van het "vanzelf" openende uploadvenster gevonden: elk leeg plaatjesvak in een ankerdiagram had eigen pointer/click-handlers die het pannen blokkeerden en de plaatjeskiezer (met uploadtab) openden bij elke veeg die erop begon - op een telefoon was dat vrijwel elke aanraking, dus ook direct na het verversen
- Lege plaatjesvakken lopen nu via dezelfde tik/sleep-logica als de cellen (6px-drempel): vegen pant het diagram, alleen een stilstaande tik opent de kiezer; woord bewerken blijft ongewijzigd
- Tekenbalk op telefoons weer gecentreerd op inhoudsbreedte i.p.v. vastgepind aan beide randen: geminimaliseerd is hij weer smal (121px i.p.v. volle breedte), nog steeds in de eigen laag boven +/borden
- Hardening: een onbekende achtergrond-waarde in opgeslagen borddata crashte de hydrate en logde de gebruiker stilletjes uit bij verversen - valt nu terug op de standaardachtergrond
- Geverifieerd in iPhone-emulatie (8 checks): geen venster na verversen, veeg pant, tik kiest, tekenbalk smal en vrij van +
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0149FgUQvuwxKKEdvQGmNngF