From 63490719d6ed8ffaca21993ecbda59b327f0c051 Mon Sep 17 00:00:00 2001 From: Ramon Date: Sun, 19 Jul 2026 00:23:39 +0200 Subject: [PATCH] =?UTF-8?q?fix:=20letterblokken=20bij=20wereldori=C3=ABnta?= =?UTF-8?q?tie=20verschillen=20nu=20ook=20per=20niveau=20(v0.4.20-beta)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 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). --- VERSION | 2 +- public/js/core.js | 2 +- public/js/widgets/world.js | 29 +++++++++++++++++++---------- 3 files changed, 21 insertions(+), 12 deletions(-) diff --git a/VERSION b/VERSION index d5be2c3..f900021 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.4.19-beta +0.4.20-beta diff --git a/public/js/core.js b/public/js/core.js index 2c35348..f8446f5 100644 --- a/public/js/core.js +++ b/public/js/core.js @@ -2,7 +2,7 @@ "use strict"; /* version — shown until /api/version resolves (or if the fetch fails, e.g. offline). Kept in sync by hand with the VERSION file at the repo root on every release. */ -const VERSION = "0.4.19-beta"; +const VERSION = "0.4.20-beta"; (function(){ const tag = document.getElementById("verTag"); tag.textContent = "v"+VERSION; diff --git a/public/js/widgets/world.js b/public/js/widgets/world.js index 14ea601..872b8da 100644 --- a/public/js/widgets/world.js +++ b/public/js/widgets/world.js @@ -361,22 +361,30 @@ function worldFlashCard(card,name,visual,S,redraw,onNext,onAssess){ } /* ---- letterblokken: spel de naam met dezelfde sleep-blokken-mechaniek als - letters.js, hier gevoed door de naam van de soort/plaats. Elk vak toont - meteen het puntenpatroon (en de letter) van het juiste antwoord - bewust - de makkelijkste ondersteuning, want deze namen zijn voor de meeste - kinderen onbekende spelling; het quiz/foto/latijn-werk hierboven test - het herkennen al veel strenger. */ + letters.js, hier gevoed door de naam van de soort/plaats. Het puntenpatroon + van het juiste antwoord staat altijd in het vak (zelfde tastbare hint als + overal elders); of de LETTER er ook gewoon bij staat hangt af van het + niveau, net als bij letters.js: niveau 1 verklapt alles, niveau 2 de + helft, niveau 3 niets - alleen de stippen blijven dan over als hint. */ const worldIsLetter=ch=>/\p{L}/u.test(ch); const worldSpellPool=name=>[...name.toLowerCase()].filter(worldIsLetter); +function worldSpellRevealMask(count,level){ + if(level===1)return new Array(count).fill(true); + if(level===3)return new Array(count).fill(false); + const hideCount=Math.max(1,Math.min(count-1,Math.round(count/2))); + const hidden=new Set(worldShuffle([...Array(count).keys()]).slice(0,hideCount)); + return Array.from({length:count},(_,i)=>!hidden.has(i)); +} function worldSpellNeedsNewTray(S,name){ const letters=worldSpellPool(name); - return !Array.isArray(S.answerLetters)||S.answerLetters.length!==letters.length||!Array.isArray(S.trayLetters); + return !Array.isArray(S.answerLetters)||S.answerLetters.length!==letters.length||!Array.isArray(S.trayLetters)||!Array.isArray(S.revealMask)||S.revealMask.length!==letters.length; } function worldSpellNewTray(S,name){ const letters=worldSpellPool(name); const distractPool="abcdefghijklmnopqrstuvwxyz".split("").filter(c=>!letters.includes(c)); S.trayLetters=worldShuffle([...letters,...worldShuffle(distractPool).slice(0,4)]); S.answerLetters=letters.map(()=>null); + S.revealMask=worldSpellRevealMask(letters.length,S.level); S.spellSolved=false; } function worldLetterBlock(ch,trayIndex,letters,S,redraw){ @@ -472,7 +480,7 @@ function worldSpellAnswer(name,S,redraw){ slot.dataset.index=idx; const ghost=document.createElement("div"); ghost.className="ghost"; - ghost.textContent=letters[idx]; + ghost.textContent=S.revealMask[idx]?letters[idx]:"?"; const dots=dotGrid(letters[idx]); dots.classList.add("slot-dots"); slot.append(ghost,dots); @@ -506,7 +514,7 @@ function mountWorldQuiz(root,init,config){ const S=Object.assign({ activity:"quiz",exercise:"recognize",level:1,view:config.type==="trees"?"mixed":config.type==="birds"?"bird":"plant", score:0,streak:0,target:"",taskView:"",options:[],picked:"",solved:false,feedback:"", - flashRevealed:false,answerLetters:null,trayLetters:null,spellSolved:false, + flashRevealed:false,answerLetters:null,trayLetters:null,revealMask:null,spellSolved:false, },init||{}); S.level=Math.max(1,Math.min(3,+S.level||1)); if(!exerciseOptions.some(([id])=>id===S.exercise))S.exercise="recognize"; @@ -538,6 +546,7 @@ function mountWorldQuiz(root,init,config){ S.flashRevealed=false; S.answerLetters=null; S.trayLetters=null; + S.revealMask=null; S.spellSolved=false; draw(); }; @@ -933,7 +942,7 @@ function mountTopography(root,init){ const S=Object.assign({ activity:"quiz",mode:"provinces",level:1,score:0,streak:0, target:"",picked:"",solved:false,feedback:"", - flashRevealed:false,answerLetters:null,trayLetters:null,spellSolved:false, + flashRevealed:false,answerLetters:null,trayLetters:null,revealMask:null,spellSolved:false, },init||{}); S.level=Math.max(1,Math.min(3,+S.level||1)); if(!modeOptions.some(([id])=>id===S.mode))S.mode="provinces"; @@ -955,7 +964,7 @@ function mountTopography(root,init){ let target=items[Math.floor(Math.random()*items.length)]; if(items.length>1)while(target.id===previous)target=items[Math.floor(Math.random()*items.length)]; S.target=target.id;S.picked="";S.solved=false;S.feedback=""; - S.flashRevealed=false;S.answerLetters=null;S.trayLetters=null;S.spellSolved=false; + S.flashRevealed=false;S.answerLetters=null;S.trayLetters=null;S.revealMask=null;S.spellSolved=false; draw(); }; const answer=id=>{