/* teach - woorddata: algemene kaart, thema's, gedeelde woordbronnen */ /* ========================================================= Letter game data ==========================================================*/ const DOTCODE = { a:[1], b:[1,2], c:[1,4], d:[1,4,5], e:[1,5], f:[1,2,4], g:[1,2,4,5], h:[1,2,5], i:[2,4], j:[2,4,5], k:[1,3], l:[1,2,3], m:[1,3,4], n:[1,3,4,5], o:[1,3,5], p:[1,2,3,4], q:[1,2,3,4,5], r:[1,2,3,5], s:[2,3,4], t:[2,3,4,5], u:[1,3,6], v:[1,2,3,6], w:[2,4,5,6], x:[1,3,4,6], y:[1,3,4,5,6], z:[1,3,5,6] }; /* cijferblokken gebruikten hiervoor de braille a-j-patronen, maar die gebruiken nooit posities 3/6 (de onderste rij) - op een kind-oog leken alle tien blokken daardoor op elkaar. Een eigen codetabel die alle zes stippen inzet, geeft elk cijfer een echt eigen vorm. */ const DIGIT_DOTCODE = { "0":[], "1":[2], "2":[2,5], "3":[1,2,3], "4":[1,3,4,6], "5":[1,2,3,4,5], "6":[1,2,3,4,5,6], "7":[1,2,4,5], "8":[1,2,3,4,6], "9":[1,4,6] }; /* Klassenmanagement (v0.4.34-beta e.v.): rekenen is het eerste vakgebied waarvan de leerlijn direct in getalgrenzen te vertalen is (SLO/TULE: groep 3 automatiseert optellen/aftrekken t/m 20, groep 4 t/m 100, groep 5 t/m 1000, groep 6 t/m 10.000 met de tafels verder uitgebouwd, groep 7-8 bouwen daarop voort). math.js gebruikt dit als de daadwerkelijke inhoud zodra een leerling een groep heeft (zie mathRangeFor hieronder) - zonder groep blijft het oude, vaste 10/20/100-gedrag exact bestaan. */ const SLO_MATH_RANGES = { 1:{addSub:10, timesTable:5}, 2:{addSub:10, timesTable:5}, 3:{addSub:20, timesTable:5}, 4:{addSub:100, timesTable:10}, 5:{addSub:1000, timesTable:10}, 6:{addSub:10000,timesTable:12}, 7:{addSub:10000,timesTable:12}, 8:{addSub:10000,timesTable:12}, }; /* niveau (1-3) is de verfijning BINNEN een groep - een breukdeel van de groep-grens, nooit onder de kleinste bestaande standaardwaarde (10) of onder tafel 3. Levert bij ontbrekend yearGroup expres geen waarde (math.js valt dan terug op zijn eigen oude vaste 10/20/100-logica). */ function mathRangeFor(yearGroup, level){ if(yearGroup == null) return null; const g = SLO_MATH_RANGES[Math.max(1, Math.min(8, +yearGroup || 1))]; if(!g) return null; const frac = level===1 ? .25 : level===2 ? .6 : 1; return { addSub: Math.max(10, Math.round(g.addSub*frac/5)*5), timesTable: Math.max(3, Math.round(g.timesTable*frac)), }; } const VOWELS = "aeiou"; function dotGrid(letter){ const code = (Object.prototype.hasOwnProperty.call(DIGIT_DOTCODE, letter) ? DIGIT_DOTCODE[letter] : DOTCODE[letter]) || []; const grid = document.createElement("div"); grid.className = "dots"; [1,4,2,5,3,6].forEach(p=>{ const d = document.createElement("i"); d.className = code.includes(p) ? "on" : "off"; grid.appendChild(d); }); return grid; } /* De taalplaatjes hebben รฉรฉn centrale bron. Daardoor gebruiken de spelletjes, de themakiezer en de afbeeldingenbibliotheek altijd dezelfde woorden en verdwijnen oude plaatjes niet wanneer de woordenschat wordt uitgebreid. */ const LANGUAGE_THEME_DEFS = [ {id:"animals", icon:"๐Ÿพ", nl:"Dieren", en:"Animals", colors:["#eaf7df","#cdeeb5"]}, {id:"food", icon:"๐ŸŽ", nl:"Eten & drinken", en:"Food & drink", colors:["#fff0dc","#ffd9aa"]}, {id:"nature", icon:"๐ŸŒฟ", nl:"Natuur & weer", en:"Nature & weather", colors:["#e4f7ee","#bfead4"]}, {id:"travel", icon:"๐Ÿšฒ", nl:"Onderweg", en:"Getting around", colors:["#e6f3ff","#beddf8"]}, {id:"home", icon:"๐ŸŽ’", nl:"Thuis & school", en:"Home & school", colors:["#f1ecff","#d9ccff"]}, {id:"body", icon:"๐Ÿ‘•", nl:"Lichaam & kleding", en:"Body & clothes", colors:["#ffeaf1","#ffcbdc"]}, {id:"actions", icon:"๐Ÿƒ", nl:"Doen", en:"Actions", colors:["#fff8d9","#f6e8a4"]}, {id:"feelings", icon:"๐Ÿ™‚", nl:"Gevoelens", en:"Feelings", colors:["#e9f5ff","#c8e4fa"]}, {id:"people", icon:"๐Ÿ‘จโ€๐Ÿ‘ฉโ€๐Ÿ‘ง", nl:"Mensen & familie", en:"People & family", colors:["#fff0f4","#ffd3df"]}, {id:"play", icon:"๐Ÿ€", nl:"Spelen & sport", en:"Play & sports", colors:["#fff4dc","#ffdca8"]}, {id:"places", icon:"๐Ÿ˜๏ธ", nl:"Plekken & beroepen", en:"Places & jobs", colors:["#e8f3ff","#c9e2fb"]}, {id:"time", icon:"๐Ÿ“…", nl:"Tijd & feest", en:"Time & celebrations", colors:["#f2edff","#ddd1ff"]}, {id:"arts", icon:"๐ŸŽจ", nl:"Kunst & muziek", en:"Arts & music", colors:["#fff0fa","#f4ccec"]}, {id:"science", icon:"๐Ÿ”ฌ", nl:"Onderzoeken & techniek", en:"Science & technology", colors:["#e7f7f5","#bfe9e3"]}, {id:"learning", icon:"๐Ÿ“š", nl:"Taal & rekenen", en:"Language & maths", colors:["#fff7df","#f3dfa6"]}, {id:"society", icon:"๐ŸŒ", nl:"Samenleven & wereld", en:"Society & world", colors:["#e8f1ff","#c8daf7"]} ]; const LANGUAGE_CONCEPTS = [ ["monkey","animals","aap","monkey","๐Ÿต"], ["cat","animals","kat","cat","๐Ÿˆ"], ["dog","animals","hond","dog","๐Ÿ•"], ["fish","animals","vis","fish","๐ŸŸ"], ["hen","animals","kip","hen","๐Ÿ”"], ["mouse","animals","muis","mouse","๐Ÿญ"], ["bear","animals","beer","bear","๐Ÿป"], ["duck","animals","eend","duck","๐Ÿฆ†"], ["frog","animals","kikker","frog","๐Ÿธ"], ["bee","animals","bij","bee","๐Ÿ"], ["cow","animals","koe","cow","๐Ÿ„"], ["pig","animals","varken","pig","๐Ÿท"], ["owl","animals","uil","owl","๐Ÿฆ‰"], ["goat","animals","geit","goat","๐Ÿ"], ["hare","animals","haas","hare","๐Ÿ‡"], ["horse","animals","paard","horse","๐Ÿด"], ["lion","animals","leeuw","lion","๐Ÿฆ"], ["ant","animals","mier","ant","๐Ÿœ"], ["egg","food","ei","egg","๐Ÿฅš"], ["apple","food","appel","apple","๐ŸŽ"], ["pear","food","peer","pear","๐Ÿ"], ["cheese","food","kaas","cheese","๐Ÿง€"], ["milk","food","melk","milk","๐Ÿฅ›"], ["cake","food","taart","cake","๐ŸŽ‚"], ["bread","food","brood","bread","๐Ÿž"], ["soup","food","soep","soup","๐Ÿฅฃ"], ["rice","food","rijst","rice","๐Ÿš"], ["corn","food","mais","corn","๐ŸŒฝ"], ["grape","food","druif","grape","๐Ÿ‡"], ["strawberry","food","aardbei","strawberry","๐Ÿ“"], ["candy","food","snoep","candy","๐Ÿฌ"], ["lemon","food","citroen","lemon","๐Ÿ‹"], ["pizza","food","pizza","pizza","๐Ÿ•"], ["juice","food","sap","juice","๐Ÿงƒ"], ["cookie","food","koek","cookie","๐Ÿช"], ["carrot","food","wortel","carrot","๐Ÿฅ•"], ["sun","nature","zon","sun","โ˜€๏ธ"], ["moon","nature","maan","moon","๐ŸŒ™"], ["star","nature","ster","star","โญ"], ["tree","nature","boom","tree","๐ŸŒณ"], ["rose","nature","roos","rose","๐ŸŒน"], ["fire","nature","vuur","fire","๐Ÿ”ฅ"], ["flower","nature","bloem","flower","๐ŸŒท"], ["leaf","nature","blad","leaf","๐Ÿƒ"], ["cloud","nature","wolk","cloud","โ˜๏ธ"], ["rain","nature","regen","rain","๐ŸŒง๏ธ"], ["snow","nature","sneeuw","snow","โ„๏ธ"], ["water","nature","water","water","๐Ÿ’ง"], ["stone","nature","steen","stone","๐Ÿชจ"], ["sand","nature","zand","sand","๐Ÿ–๏ธ"], ["sea","nature","zee","sea","๐ŸŒŠ"], ["forest","nature","bos","forest","๐ŸŒฒ"], ["grass","nature","gras","grass","๐ŸŒฑ"], ["wind","nature","wind","wind","๐Ÿ’จ"], ["rainbow","nature","regenboog","rainbow","๐ŸŒˆ"], ["car","travel","auto","car","๐Ÿš—"], ["bike","travel","fiets","bike","๐Ÿšฒ"], ["boat","travel","boot","boat","โ›ต"], ["train","travel","trein","train","๐Ÿš‚"], ["bus","travel","bus","bus","๐ŸšŒ"], ["taxi","travel","taxi","taxi","๐Ÿš•"], ["truck","travel","vrachtauto","truck","๐Ÿšš"], ["jet","travel","vliegtuig","plane","โœˆ๏ธ"], ["tram","travel","tram","tram","๐Ÿš‹"], ["ship","travel","schip","ship","๐Ÿšข"], ["rocket","travel","raket","rocket","๐Ÿš€"], ["road","travel","weg","road","๐Ÿ›ฃ๏ธ"], ["wheel","travel","wiel","wheel","๐Ÿ›ž"], ["sail","travel","zeil","sail","โ›ต"], ["scooter","travel","step","scooter","๐Ÿ›ด"], ["tractor","travel","tractor","tractor","๐Ÿšœ"], ["helicopter","travel","helikopter","helicopter","๐Ÿš"], ["house","home","huis","house","๐Ÿ "], ["book","home","boek","book","๐Ÿ“•"], ["pen","home","pen","pen","๐Ÿ–Š๏ธ"], ["pencil","home","potlood","pencil","โœ๏ธ"], ["bag","home","tas","bag","๐ŸŽ’"], ["coat","home","jas","coat","๐Ÿงฅ"], ["chair","home","stoel","chair","๐Ÿช‘"], ["bed","home","bed","bed","๐Ÿ›๏ธ"], ["door","home","deur","door","๐Ÿšช"], ["clock","home","klok","clock","โฐ"], ["glasses","home","bril","glasses","๐Ÿ‘“"], ["ball","home","bal","ball","โšฝ"], ["doll","home","pop","doll","๐Ÿช†"], ["block","home","blok","block","๐Ÿงฑ"], ["key","home","sleutel","key","๐Ÿ”‘"], ["lamp","home","lamp","lamp","๐Ÿ’ก"], ["cup","home","beker","cup","๐Ÿฅค"], ["brush","home","borstel","brush","๐Ÿชฅ"], ["drum","home","trommel","drum","๐Ÿฅ"], ["gift","home","cadeau","gift","๐ŸŽ"], ["paint","home","verf","paint","๐ŸŽจ"], ["scissors","home","schaar","scissors","โœ‚๏ธ"], ["desk","home","bureau","desk","๐Ÿ—„๏ธ"], ["school","home","school","school","๐Ÿซ"], ["hand","body","hand","hand","โœ‹"], ["foot","body","voet","foot","๐Ÿฆถ"], ["nose","body","neus","nose","๐Ÿ‘ƒ"], ["eye","body","oog","eye","๐Ÿ‘๏ธ"], ["ear","body","oor","ear","๐Ÿ‘‚"], ["mouth","body","mond","mouth","๐Ÿ‘„"], ["hair","body","haar","hair","๐Ÿง‘โ€๐Ÿฆฑ"], ["head","body","hoofd","head","๐Ÿ™‚"], ["arm","body","arm","arm","๐Ÿ’ช"], ["leg","body","been","leg","๐Ÿฆต"], ["cap","body","pet","cap","๐Ÿงข"], ["sock","body","sok","sock","๐Ÿงฆ"], ["shoe","body","schoen","shoe","๐Ÿ‘Ÿ"], ["dress","body","jurk","dress","๐Ÿ‘—"], ["shirt","body","shirt","shirt","๐Ÿ‘•"], ["glove","body","want","glove","๐Ÿงค"], ["pants","body","broek","trousers","๐Ÿ‘–"], ["skirt","body","rok","skirt","๐Ÿ‘—"], ["tooth","body","tand","tooth","๐Ÿฆท"], ["read","actions","lezen","read","๐Ÿ“–"], ["eat","actions","eten","eat","๐Ÿฝ๏ธ"], ["drink","actions","drinken","drink","๐Ÿฅค"], ["sleep","actions","slapen","sleep","๐Ÿ˜ด"], ["walk","actions","lopen","walk","๐Ÿšถ"], ["swim","actions","zwemmen","swim","๐ŸŠ"], ["jump","actions","springen","jump","๐Ÿคธ"], ["laugh","actions","lachen","laugh","๐Ÿ˜„"], ["cry","actions","huilen","cry","๐Ÿ˜ข"], ["sing","actions","zingen","sing","๐ŸŽค"], ["dance","actions","dansen","dance","๐Ÿ’ƒ"], ["draw","actions","tekenen","draw","๐Ÿ–๏ธ"], ["write","actions","schrijven","write","โœ๏ธ"], ["play","actions","spelen","play","๐Ÿงธ"], ["sit","actions","zitten","sit","๐ŸงŽ"], ["run","actions","rennen","run","๐Ÿƒ"], ["climb","actions","klimmen","climb","๐Ÿง—"], ["wave","actions","zwaaien","wave","๐Ÿ‘‹"], ["look","actions","kijken","look","๐Ÿ‘€"], ["think","actions","denken","think","๐Ÿค”"], ["happy","feelings","blij","happy","๐Ÿ˜€"], ["sad","feelings","verdrietig","sad","๐Ÿ˜ข"], ["angry","feelings","boos","angry","๐Ÿ˜ "], ["scared","feelings","bang","scared","๐Ÿ˜จ"], ["tired","feelings","moe","tired","๐Ÿฅฑ"], ["sick","feelings","ziek","sick","๐Ÿค’"], ["proud","feelings","trots","proud","๐Ÿ˜Œ"], ["calm","feelings","rustig","calm","๐Ÿ™‚"], ["surprised","feelings","verrast","surprised","๐Ÿ˜ฎ"], ["excited","feelings","enthousiast","excited","๐Ÿคฉ"], ["bird","animals","vogel","bird","๐Ÿฆ"], ["rabbit","animals","konijn","rabbit","๐Ÿฐ"], ["fox","animals","vos","fox","๐ŸฆŠ"], ["butterfly","animals","vlinder","butterfly","๐Ÿฆ‹"], ["snail","animals","slak","snail","๐ŸŒ"], ["ladybird","animals","lieveheersbeestje","ladybird","๐Ÿž"], ["spider","animals","spin","spider","๐Ÿ•ท๏ธ"], ["turtle","animals","schildpad","turtle","๐Ÿข"], ["dolphin","animals","dolfijn","dolphin","๐Ÿฌ"], ["elephant","animals","olifant","elephant","๐Ÿ˜"], ["giraffe","animals","giraf","giraffe","๐Ÿฆ’"], ["sheep","animals","schaap","sheep","๐Ÿ‘"], ["banana","food","banaan","banana","๐ŸŒ"], ["orange","food","sinaasappel","orange","๐ŸŠ"], ["watermelon","food","watermeloen","watermelon","๐Ÿ‰"], ["cherry","food","kers","cherry","๐Ÿ’"], ["tomato","food","tomaat","tomato","๐Ÿ…"], ["potato","food","aardappel","potato","๐Ÿฅ”"], ["pancake","food","pannenkoek","pancake","๐Ÿฅž"], ["honey","food","honing","honey","๐Ÿฏ"], ["chocolate","food","chocolade","chocolate","๐Ÿซ"], ["ice","food","ijs","ice","๐Ÿฆ"], ["sandwich","food","boterham","sandwich","๐Ÿฅช"], ["yoghurt","food","yoghurt","yoghurt","๐Ÿฅฃ"], ["mountain","nature","berg","mountain","โ›ฐ๏ธ"], ["island","nature","eiland","island","๐Ÿ๏ธ"], ["beach","nature","strand","beach","๐Ÿ–๏ธ"], ["river","nature","rivier","river","๐Ÿž๏ธ"], ["lightning","nature","bliksem","lightning","โšก"], ["fog","nature","mist","fog","๐ŸŒซ๏ธ"], ["autumn","nature","herfst","autumn","๐Ÿ‚"], ["spring","nature","lente","spring","๐ŸŒผ"], ["summer","nature","zomer","summer","๐ŸŒž"], ["winter","nature","winter","winter","โ›„"], ["seed","nature","zaad","seed","๐ŸŒฐ"], ["motorcycle","travel","motor","motorcycle","๐Ÿ๏ธ"], ["ambulance","travel","ambulance","ambulance","๐Ÿš‘"], ["firetruck","travel","brandweerauto","firetruck","๐Ÿš’"], ["policecar","travel","politieauto","policecar","๐Ÿš“"], ["subway","travel","metro","subway","๐Ÿš‡"], ["canoe","travel","kano","canoe","๐Ÿ›ถ"], ["bridge","travel","brug","bridge","๐ŸŒ‰"], ["tunnel","travel","tunnel","tunnel","๐Ÿš‡"], ["trafficlight","travel","stoplicht","trafficlight","๐Ÿšฆ"], ["station","travel","station","station","๐Ÿš‰"], ["airport","travel","vliegveld","airport","๐Ÿ›ซ"], ["mirror","home","spiegel","mirror","๐Ÿชž"], ["sofa","home","bank","sofa","๐Ÿ›‹๏ธ"], ["toilet","home","wc","toilet","๐Ÿšฝ"], ["shower","home","douche","shower","๐Ÿšฟ"], ["broom","home","bezem","broom","๐Ÿงน"], ["spoon","home","lepel","spoon","๐Ÿฅ„"], ["fork","home","vork","fork","๐Ÿด"], ["plate","home","bord","plate","๐Ÿฝ๏ธ"], ["computer","home","computer","computer","๐Ÿ’ป"], ["phone","home","telefoon","phone","๐Ÿ“ฑ"], ["window","home","raam","window","๐ŸชŸ"], ["finger","body","vinger","finger","โ˜๏ธ"], ["thumb","body","duim","thumb","๐Ÿ‘"], ["knee","body","knie","knee","๐Ÿฆต"], ["heart","body","hart","heart","โค๏ธ"], ["brain","body","hersenen","brain","๐Ÿง "], ["bone","body","bot","bone","๐Ÿฆด"], ["tongue","body","tong","tongue","๐Ÿ‘…"], ["blood","body","bloed","blood","๐Ÿฉธ"], ["hat","body","hoed","hat","๐Ÿ‘’"], ["boot","body","laars","boot","๐Ÿฅพ"], ["scarf","body","sjaal","scarf","๐Ÿงฃ"], ["cook","actions","koken","cook","๐Ÿง‘โ€๐Ÿณ"], ["bake","actions","bakken","bake","๐Ÿง"], ["cycle","actions","fietsen","cycle","๐Ÿšด"], ["drive","actions","rijden","drive","๐Ÿš™"], ["open","actions","openen","open","๐Ÿ“‚"], ["close","actions","sluiten","close","๐Ÿ“•"], ["wash","actions","wassen","wash","๐Ÿงผ"], ["help","actions","helpen","help","๐Ÿค"], ["listen","actions","luisteren","listen","๐Ÿ‘‚"], ["smell","actions","ruiken","smell","๐Ÿ‘ƒ"], ["shy","feelings","verlegen","shy","๐Ÿ˜Š"], ["curious","feelings","nieuwsgierig","curious","๐Ÿง"], ["confused","feelings","verward","confused","๐Ÿ˜•"], ["lonely","feelings","eenzaam","lonely","๐Ÿ˜”"], ["friendly","feelings","vriendelijk","friendly","๐Ÿ™‚"], ["brave","feelings","dapper","brave","๐Ÿฆธ"], ["jealous","feelings","jaloers","jealous","๐Ÿ˜’"], ["bored","feelings","verveeld","bored","๐Ÿฅฑ"], ["relieved","feelings","opgelucht","relieved","๐Ÿ˜Œ"], ["silly","feelings","grappig","silly","๐Ÿคช"], ["baby","people","baby","baby","๐Ÿ‘ถ"], ["child","people","kind","child","๐Ÿง’"], ["boy","people","jongen","boy","๐Ÿ‘ฆ"], ["girl","people","meisje","girl","๐Ÿ‘ง"], ["mother","people","moeder","mother","๐Ÿ‘ฉ"], ["father","people","vader","father","๐Ÿ‘จ"], ["sister","people","zus","sister","๐Ÿ‘ง"], ["brother","people","broer","brother","๐Ÿ‘ฆ"], ["grandmother","people","oma","grandmother","๐Ÿ‘ต"], ["grandfather","people","opa","grandfather","๐Ÿ‘ด"], ["family","people","familie","family","๐Ÿ‘จโ€๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘ฆ"], ["friend","people","vriend","friend","๐Ÿง‘โ€๐Ÿคโ€๐Ÿง‘"], ["teacher","people","leerkracht","teacher","๐Ÿง‘โ€๐Ÿซ"], ["pupil","people","leerling","pupil","๐Ÿง‘โ€๐ŸŽ“"], ["neighbor","people","buur","neighbor","๐Ÿ˜๏ธ"], ["woman","people","vrouw","woman","๐Ÿ‘ฉ"], ["man","people","man","man","๐Ÿ‘จ"], ["person","people","mens","person","๐Ÿง‘"], ["twins","people","tweeling","twins","๐Ÿ‘ฏ"], ["group","people","groep","group","๐Ÿ‘ฅ"], ["football","play","voetbal","football","โšฝ"], ["basketball","play","basketbal","basketball","๐Ÿ€"], ["tennis","play","tennis","tennis","๐ŸŽพ"], ["hockey","play","hockey","hockey","๐Ÿ‘"], ["volleyball","play","volleybal","volleyball","๐Ÿ"], ["skating","play","schaatsen","skating","โ›ธ๏ธ"], ["ski","play","ski","ski","๐ŸŽฟ"], ["cycling","play","wielrennen","cycling","๐Ÿšด"], ["running","play","hardlopen","running","๐Ÿƒ"], ["playground","play","speeltuin","playground","๐Ÿ›"], ["bowling","play","bowlen","bowling","๐ŸŽณ"], ["slide","play","glijbaan","slide","๐Ÿ›"], ["kite","play","vlieger","kite","๐Ÿช"], ["puzzle","play","puzzel","puzzle","๐Ÿงฉ"], ["game","play","spel","game","๐ŸŽฎ"], ["dice","play","dobbelsteen","dice","๐ŸŽฒ"], ["marble","play","knikker","marble","๐Ÿ”ต"], ["teddy","play","knuffel","teddy","๐Ÿงธ"], ["cards","play","kaarten","cards","๐Ÿƒ"], ["chess","play","schaken","chess","โ™Ÿ๏ธ"], ["medal","play","medaille","medal","๐Ÿ…"], ["shop","places","winkel","shop","๐Ÿช"], ["bakery","places","bakkerij","bakery","๐Ÿฅ"], ["hospital","places","ziekenhuis","hospital","๐Ÿฅ"], ["doctor","places","dokter","doctor","๐Ÿง‘โ€โš•๏ธ"], ["police","places","politie","police","๐Ÿ‘ฎ"], ["firefighter","places","brandweer","firefighter","๐Ÿง‘โ€๐Ÿš’"], ["farm","places","boerderij","farm","๐Ÿก"], ["farmer","places","boer","farmer","๐Ÿง‘โ€๐ŸŒพ"], ["library","places","bibliotheek","library","๐Ÿ“š"], ["librarian","places","bibliothecaris","librarian","๐Ÿ“š"], ["park","places","park","park","๐Ÿž๏ธ"], ["zoo","places","dierentuin","zoo","๐Ÿฆ’"], ["museum","places","museum","museum","๐Ÿ›๏ธ"], ["restaurant","places","restaurant","restaurant","๐Ÿฝ๏ธ"], ["kitchen","places","keuken","kitchen","๐Ÿณ"], ["classroom","places","klas","classroom","๐Ÿซ"], ["office","places","kantoor","office","๐Ÿข"], ["garage","places","garage","garage","๐Ÿš—"], ["postman","places","postbode","postman","๐Ÿ“ฌ"], ["nurse","places","verpleegkundige","nurse","๐Ÿง‘โ€โš•๏ธ"], ["dentist","places","tandarts","dentist","๐Ÿฆท"], ["builder","places","bouwer","builder","๐Ÿ‘ท"], ["chef","places","kok","chef","๐Ÿง‘โ€๐Ÿณ"], ["hairdresser","places","kapper","hairdresser","๐Ÿ’‡"], ["market","places","markt","market","๐Ÿ›๏ธ"], ["city","places","stad","city","๐Ÿ™๏ธ"], ["village","places","dorp","village","๐Ÿ˜๏ธ"], ["church","places","kerk","church","โ›ช"], ["pool","places","zwembad","pool","๐ŸŠ"], ["morning","time","ochtend","morning","๐ŸŒ…"], ["afternoon","time","middag","afternoon","๐ŸŒค๏ธ"], ["evening","time","avond","evening","๐ŸŒ‡"], ["night","time","nacht","night","๐ŸŒ™"], ["today","time","vandaag","today","๐Ÿ“…"], ["tomorrow","time","morgen","tomorrow","โžก๏ธ"], ["yesterday","time","gisteren","yesterday","โฌ…๏ธ"], ["day","time","dag","day","โ˜€๏ธ"], ["week","time","week","week","๐Ÿ—“๏ธ"], ["month","time","maand","month","๐Ÿ“†"], ["year","time","jaar","year","๐ŸŽ†"], ["birthday","time","verjaardag","birthday","๐ŸŽ‚"], ["party","time","feest","party","๐Ÿฅณ"], ["candle","time","kaars","candle","๐Ÿ•ฏ๏ธ"], ["balloon","time","ballon","balloon","๐ŸŽˆ"], ["flag","time","vlag","flag","๐Ÿšฉ"], ["crown","time","kroon","crown","๐Ÿ‘‘"], ["christmas","time","kerst","christmas","๐ŸŽ„"], ["easter","time","pasen","easter","๐Ÿฃ"], ["garland","time","slinger","garland","๐ŸŽŠ"], ["calendar","time","kalender","calendar","๐Ÿ“…"], ["hour","time","uur","hour","๐Ÿ•"], ["minute","time","minuut","minute","โฑ๏ธ"], ["season","time","seizoen","season","๐Ÿ"] ].map(([id,theme,nl,en,pic])=>({id,theme,nl,en,pic})); /* Gecontroleerde Nederlandse beeldcorrecties. Bestaande handgekozen emoji blijven de terugval; deze lijst corrigeert polyseme woorden en geeft veel voorkomende concrete woorden een specifieker beeld. */ const LANGUAGE_PICTURE_EXACT=Object.freeze({ groentekraam:"๐Ÿฅ•๐Ÿช",veehouderij:"๐Ÿ„",wastafel:"๐Ÿšฐ",woonkamermeubel:"๐Ÿ›‹๏ธ",badkamertegel:"๐Ÿšฟ",prullenbak:"๐Ÿ—‘๏ธ", tekstproductie:"โœ๏ธ๐Ÿ“„",verdrietverwerking:"๐Ÿ˜ข๐Ÿง ",bezorgd:"๐Ÿ˜Ÿ",ouderverzorging:"๐Ÿ‘ฉโค๏ธ",spierkracht:"๐Ÿ’ช", schoolslag:"๐ŸŠ",wedstrijdreglement:"๐Ÿ€๐Ÿ“‹",toneelspeler:"๐ŸŽญ",spellingspatroon:"๐Ÿ”ค",meetinstrument:"๐Ÿ“", lentebloem:"๐ŸŒผ",zomerdag:"๐ŸŒž",herfstblad:"๐Ÿ‚",winterjas:"โ›„",jaargetijde:"๐Ÿ",gitaarspel:"๐ŸŽธ", ruimtestation:"๐Ÿ›ฐ๏ธ",boekje:"๐Ÿ“–",muziek:"๐ŸŽถ",onderzoeksverslag:"๐Ÿงช๐Ÿ“‹",grondrecht:"โš–๏ธ", bol:"๐Ÿฅฏ",toast:"๐Ÿž",korst:"๐Ÿž",kruimel:"๐Ÿž",karnemelk:"๐Ÿฅ›",room:"๐Ÿฅ›",boter:"๐Ÿงˆ",vla:"๐Ÿฎ", brie:"๐Ÿง€",plak:"๐Ÿง€",friet:"๐ŸŸ",puree:"๐Ÿฅ”",schil:"๐Ÿฅ”",knol:"๐Ÿฅ”",prei:"๐Ÿฅฌ",kool:"๐Ÿฅฌ",boon:"๐Ÿซ˜",erwtje:"๐Ÿซ›", koek:"๐Ÿช",snoep:"๐Ÿฌ",wafel:"๐Ÿง‡",gebakje:"๐Ÿง",slagroom:"๐Ÿฐ", stam:"๐ŸŒณ",tak:"๐ŸŒฟ",wortel:"๐ŸŒฑ",stengel:"๐ŸŒฑ",knop:"๐ŸŒท",boeket:"๐Ÿ’",druppel:"๐Ÿ’ง",plas:"๐Ÿ’ฆ",sloot:"๐Ÿž๏ธ",beek:"๐Ÿž๏ธ", licht:"โ˜€๏ธ",schaduw:"โ—",bui:"๐ŸŒฆ๏ธ",vorst:"๐Ÿฅถ",hagel:"๐ŸŒจ๏ธ",vlok:"โ„๏ธ",aarde:"๐ŸŒ",grond:"๐ŸŸซ",kiem:"๐ŸŒฑ", bus:"๐ŸšŒ",taxi:"๐Ÿš•",rit:"๐Ÿ›ฃ๏ธ",band:"๐Ÿ›ž",step:"๐Ÿ›ด",pedaal:"๐Ÿšฒ",bel:"๐Ÿ””",stuur:"๐Ÿšฒ",rail:"๐Ÿ›ค๏ธ",spoor:"๐Ÿ›ค๏ธ", roeispaan:"๐Ÿšฃ",vleugel:"โœˆ๏ธ",piloot:"๐Ÿง‘โ€โœˆ๏ธ",vlucht:"โœˆ๏ธ",pad:"๐Ÿฅพ",bocht:"โ†ช๏ธ",streep:"โž–",file:"๐Ÿš—๐Ÿš—",route:"๐Ÿ—บ๏ธ", kast:"๐Ÿ—„๏ธ",nachtkast:"๐Ÿ—„๏ธ",slaapkamer:"๐Ÿ›๏ธ",slaapkamerraam:"๐ŸชŸ",flat:"๐Ÿข",hut:"๐Ÿ›–",dak:"๐Ÿ ",muur:"๐Ÿงฑ",deken:"๐Ÿ›๏ธ",kussen:"๐Ÿ›๏ธ",kruk:"๐Ÿช‘",slot:"๐Ÿ”’",sleutel:"๐Ÿ”‘", pan:"๐Ÿณ",pot:"๐Ÿฒ",kom:"๐Ÿฅฃ",lepel:"๐Ÿฅ„",bad:"๐Ÿ›",douche:"๐Ÿšฟ",wc:"๐Ÿšฝ",kraan:"๐Ÿšฐ",zeep:"๐Ÿงผ", stof:"๐Ÿซง",vuil:"๐Ÿ—‘๏ธ",bezem:"๐Ÿงน",dweil:"๐Ÿงฝ",spons:"๐Ÿงฝ", duim:"๐Ÿ‘",vinger:"โ˜๏ธ",nagel:"๐Ÿ’…",pols:"โŒš",teen:"๐Ÿฆถ",hiel:"๐Ÿฆถ",enkel:"๐Ÿฆต",knie:"๐Ÿฆต", wang:"๐Ÿ™‚",kin:"๐Ÿ™‚",nek:"๐Ÿงฃ",keel:"๐Ÿ—ฃ๏ธ",lip:"๐Ÿ‘„",kies:"๐Ÿฆท",tong:"๐Ÿ‘…",speeksel:"๐Ÿ’ง",gebit:"๐Ÿ˜", trui:"๐Ÿ‘•",broek:"๐Ÿ‘–",rok:"๐Ÿ‘—",long:"๐Ÿซ",bloed:"๐Ÿฉธ",bot:"๐Ÿฆด",spier:"๐Ÿ’ช",skelet:"๐Ÿฆด", bewegingsapparaat:"๐Ÿฆด",bewegingsrichting:"๐Ÿงญ",lichaamsbeweging:"๐Ÿคธ",bewegingsreeks:"๐Ÿ”„",bewegingsoefening:"๐Ÿคธ",bewegingspatroon:"๐Ÿ’ƒ",gaan:"๐Ÿšถ",stap:"๐Ÿ‘ฃ",staan:"๐Ÿง",zitten:"๐Ÿช‘",racen:"๐Ÿ",sprinten:"๐Ÿƒ",haasten:"โฉ",vluchten:"๐Ÿƒ", hupsen:"๐Ÿ‡",bukken:"๐Ÿ™‡",rollen:"๐Ÿคธ",draaien:"๐Ÿ”„",blad:"๐Ÿ“„",zin:"๐Ÿ“",tekst:"๐Ÿ“„",schrift:"๐Ÿ““", praten:"๐Ÿ—ฃ๏ธ",zeggen:"๐Ÿ’ฌ",vragen:"โ“",roepen:"๐Ÿ“ฃ",fluisteren:"๐Ÿคซ",delen:"๐Ÿคฒ",geven:"๐ŸŽ",halen:"๐Ÿ“ฅ",brengen:"๐Ÿ“ค", leuk:"๐Ÿ˜€",fijn:"๐Ÿ˜Š",glimlach:"๐Ÿ™‚",sip:"๐Ÿ˜”",verdriet:"๐Ÿ˜ข",pijn:"๐Ÿค•",kwaad:"๐Ÿ˜ ",ruzie:"๐Ÿ’ข",zorgen:"๐Ÿ˜Ÿ", rust:"๐Ÿง˜",kalm:"๐Ÿ™‚",stil:"๐Ÿคซ",zacht:"๐Ÿชถ",ademen:"๐ŸŒฌ๏ธ",dapper:"๐Ÿฆธ",durven:"๐Ÿ’ช",winnen:"๐Ÿ†",raar:"๐Ÿค”",wauw:"๐Ÿคฉ", gezin:"๐Ÿ‘จโ€๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘ฆ",ouders:"๐Ÿ‘ช",mama:"๐Ÿ‘ฉ",tante:"๐Ÿ‘ฉ",dochter:"๐Ÿ‘ง",papa:"๐Ÿ‘จ",oom:"๐Ÿ‘จ",zoon:"๐Ÿ‘ฆ", jongen:"๐Ÿ‘ฆ",meisje:"๐Ÿ‘ง",kleuter:"๐Ÿง’",puber:"๐Ÿง‘",maat:"๐Ÿง‘โ€๐Ÿคโ€๐Ÿง‘",buur:"๐Ÿ˜๏ธ",gast:"๐Ÿง‘",juf:"๐Ÿ‘ฉโ€๐Ÿซ",meester:"๐Ÿ‘จโ€๐Ÿซ", leraar:"๐Ÿง‘โ€๐Ÿซ",mentor:"๐Ÿง‘โ€๐Ÿซ",coach:"๐Ÿง‘โ€๐Ÿซ",team:"๐Ÿ‘ฅ",klas:"๐Ÿซ",paar:"๐Ÿ‘ซ",kring:"โญ•", kaart:"๐Ÿƒ",doel:"๐Ÿฅ…",trap:"โšฝ",veld:"๐ŸŸ๏ธ",basket:"๐Ÿ€",korf:"๐Ÿงบ",worp:"๐Ÿคพ",score:"๐Ÿ’ฏ",punt:"๐Ÿ”ต",stuk:"๐Ÿงฉ",rand:"๐Ÿงฉ", plaat:"๐Ÿ–ผ๏ธ",beer:"๐Ÿงธ",blok:"๐Ÿงฑ",pion:"โ™Ÿ๏ธ",plons:"๐Ÿ’ฆ",slag:"๐ŸŠ",prijs:"๐Ÿ†",beker:"๐Ÿ†",medaille:"๐Ÿ…", straat:"๐Ÿ›ฃ๏ธ",landingsbaan:"๐Ÿ›ฌ",plattegrond:"๐Ÿ—บ๏ธ",landbouwer:"๐Ÿง‘โ€๐ŸŒพ",plein:"๐Ÿ˜๏ธ",les:"๐Ÿ“š",gym:"๐Ÿคธ",kassa:"๐Ÿงพ",kar:"๐Ÿ›’",mand:"๐Ÿงบ",klant:"๐Ÿง‘",arts:"๐Ÿง‘โ€โš•๏ธ",zaal:"๐Ÿšช",zorg:"โค๏ธ", boer:"๐Ÿง‘โ€๐ŸŒพ",stal:"๐Ÿš๏ธ",schuur:"๐Ÿš๏ธ",land:"๐ŸŒพ",erf:"๐Ÿก",balie:"๐Ÿ›Ž๏ธ",lezer:"๐Ÿ“–",buurt:"๐Ÿ˜๏ธ",vijver:"๐Ÿž๏ธ", dag:"โ˜€๏ธ",uur:"๐Ÿ•",tijd:"โฐ",middag:"๐ŸŒค๏ธ",vroeg:"๐ŸŒ…",wakker:"โฐ",ontbijt:"๐Ÿฅฃ",avond:"๐ŸŒ‡",laat:"๐ŸŒ™", donker:"๐ŸŒ‘",week:"๐Ÿ—“๏ธ",maand:"๐Ÿ“†",jaar:"๐ŸŽ†",datum:"๐Ÿ“…",agenda:"๐Ÿ“’",feest:"๐Ÿฅณ",kaars:"๐Ÿ•ฏ๏ธ",ballon:"๐ŸŽˆ", lente:"๐ŸŒผ",zomer:"๐ŸŒž",herfst:"๐Ÿ‚",winter:"โ›„",seconde:"โฑ๏ธ",kwart:"ยผ",half:"ยฝ",duur:"โณ", kleur:"๐ŸŒˆ",verf:"๐ŸŽจ",kwast:"๐Ÿ–Œ๏ธ",doek:"๐Ÿ–ผ๏ธ",palet:"๐ŸŽจ",tekening:"๐Ÿ–๏ธ",lijn:"โž–",vorm:"๐Ÿ”ท",vak:"โ—ป๏ธ", toon:"๐ŸŽต",lied:"๐ŸŽถ",stem:"๐Ÿ—ฃ๏ธ",klank:"๐Ÿ”Š",trom:"๐Ÿฅ",fluit:"๐Ÿชˆ",snaar:"๐ŸŽธ",toets:"๐ŸŽน", dans:"๐Ÿ’ƒ",sprong:"๐Ÿคธ",draai:"๐Ÿ”„",toneel:"๐ŸŽญ",rol:"๐ŸŽญ",pak:"๐Ÿ‘”",podium:"๐ŸŽญ",foto:"๐Ÿ“ท",film:"๐ŸŽฌ",lens:"๐Ÿ“ท", zoeken:"๐Ÿ”Ž",vraag:"โ“",vondst:"๐Ÿ’ก",proef:"๐Ÿงช",test:"โœ…",buis:"๐Ÿงช",mengen:"๐Ÿฅฃ", magneet:"๐Ÿงฒ",ijzer:"๐Ÿ”ฉ",pool:"๐Ÿงฒ",kracht:"๐Ÿ’ช",wiel:"๐Ÿ›ž",as:"โš™๏ธ",tand:"๐Ÿฆท",veer:"๐Ÿชถ",hefboom:"โš–๏ธ", stroom:"โšก",draad:"๐Ÿงต",stekker:"๐Ÿ”Œ",digitaal:"๐Ÿ’ป",internet:"๐ŸŒ",programmeren:"๐Ÿง‘โ€๐Ÿ’ป",computer:"๐Ÿ’ป",muis:"๐Ÿ–ฑ๏ธ",scherm:"๐Ÿ–ฅ๏ธ",bestand:"๐Ÿ“„",ruimte:"๐ŸŒŒ", planeet:"๐Ÿช",raket:"๐Ÿš€",satelliet:"๐Ÿ›ฐ๏ธ",heelal:"๐ŸŒŒ",astronaut:"๐Ÿง‘โ€๐Ÿš€", letter:"๐Ÿ”ค",woord:"๐Ÿ” ",naam:"๐Ÿท๏ธ",teken:"โœ๏ธ",komma:",",titel:"๐Ÿท๏ธ",prent:"๐Ÿ–ผ๏ธ",taal:"๐Ÿ—ฃ๏ธ", spraak:"๐Ÿ’ฌ",verhaal:"๐Ÿ“–",nul:"0๏ธโƒฃ",een:"1๏ธโƒฃ",twee:"2๏ธโƒฃ",drie:"3๏ธโƒฃ",getal:"๐Ÿ”ข",cijfer:"๐Ÿ”ฃ",reeks:"๐Ÿ”ข", som:"โž•",plus:"โž•",min:"โž–",keer:"โœ–๏ธ",hoek:"๐Ÿ“",vlak:"โ—ป๏ธ",lengte:"๐Ÿ“", samen:"๐Ÿค",hulp:"๐Ÿ†˜",beurt:"๐Ÿ”„",afspraak:"๐Ÿค",regel:"๐Ÿ“‹",wijk:"๐Ÿ˜๏ธ",wereld:"๐ŸŒ",grens:"๐Ÿšง", noord:"โฌ†๏ธ",zuid:"โฌ‡๏ธ",oost:"โžก๏ธ",west:"โฌ…๏ธ",plek:"๐Ÿ“",richting:"๐Ÿงญ",nieuws:"๐Ÿ“ฐ",krant:"๐Ÿ—ž๏ธ",bericht:"๐Ÿ’ฌ", radio:"๐Ÿ“ป",media:"๐Ÿ“บ",afval:"๐Ÿ—‘๏ธ",bak:"๐Ÿ—‘๏ธ",glas:"โ™ป๏ธ",papier:"๐Ÿ“„",recht:"โš–๏ธ",plicht:"๐Ÿ“‹",keus:"๐Ÿ”€", wet:"โš–๏ธ",eerlijk:"โš–๏ธ",mening:"๐Ÿ’ญ",besluit:"โœ…" }); /* Betekenisdragende delen voor samenstellingen. Het familiebeeld blijft voorop staan; maximaal รฉรฉn tweede symbool verduidelijkt het onderscheid. */ const LANGUAGE_PICTURE_HINTS=Object.freeze([ ["bescherming","๐Ÿ›ก๏ธ"],["veiligheid","๐Ÿ›ก๏ธ"],["verzorging","๐Ÿงผ"],["vaardigheid","๐ŸŽฏ"],["onderzoek","๐Ÿ”ฌ"], ["bereiding","๐Ÿณ"],["productie","๐Ÿญ"],["verwerking","๐Ÿญ"],["organisatie","๐Ÿ“‹"],["ontwikkeling","๐Ÿ“ˆ"], ["geschiedenis","๐Ÿ“œ"],["industrie","๐Ÿญ"],["maatschappij","๐ŸŒ"],["informatie","โ„น๏ธ"],["technologie","๐Ÿ’ป"], ["wedstrijd","๐Ÿ†"],["training","๐Ÿ‹๏ธ"],["strategie","โ™Ÿ๏ธ"],["berekening","๐Ÿงฎ"],["verdeling","๐Ÿ“Š"], ["winkel","๐Ÿช"],["fabriek","๐Ÿญ"],["bedrijf","๐Ÿญ"],["centrum","๐Ÿ™๏ธ"],["gebouw","๐Ÿข"],["kamer","๐Ÿšช"], ["boek","๐Ÿ“•"],["schrift","๐Ÿ““"],["kaart","๐Ÿ—บ๏ธ"],["verslag","๐Ÿ“‹"],["bericht","๐Ÿ’ฌ"],["programma","๐Ÿ’ป"], ["verlichting","๐Ÿ’ก"],["licht","๐Ÿ’ก"],["water","๐Ÿ’ง"],["lucht","๐ŸŒฌ๏ธ"],["grond","๐ŸŸซ"],["bloem","๐ŸŒท"], ["boom","๐ŸŒณ"],["tuin","๐ŸŒฑ"],["weide","๐ŸŒฟ"],["storm","๐ŸŒช๏ธ"],["regen","๐ŸŒง๏ธ"],["sneeuw","โ„๏ธ"], ["bak","๐Ÿ“ฆ"],["voer","๐Ÿฝ๏ธ"],["hok","๐Ÿ "],["stal","๐Ÿš๏ธ"],["riem","๐Ÿฆฎ"],["kooi","๐Ÿชน"], ["boot","โ›ต"],["reis","๐Ÿงณ"],["straat","๐Ÿ˜๏ธ"],["station","๐Ÿš‰"],["haven","โš“"], ["deur","๐Ÿšช"],["raam","๐ŸชŸ"],["kast","๐Ÿ—„๏ธ"],["tafel","๐Ÿช‘"],["stoel","๐Ÿช‘"],["bed","๐Ÿ›๏ธ"], ["zorg","โค๏ธ"],["hulp","๐Ÿค"],["school","๐Ÿซ"],["leer","๐Ÿ“š"],["taal","๐Ÿ”ค"],["reken","๐Ÿงฎ"], ["spel","๐ŸŽฒ"],["sport","๐Ÿ…"],["feest","๐Ÿฅณ"],["dag","๐Ÿ“…"],["tijd","โฐ"],["jaar","๐Ÿ—“๏ธ"], ["kracht","๐Ÿ’ช"],["energie","โšก"],["stroom","โšก"],["machine","โš™๏ธ"],["instrument","๐ŸŽต"],["muziek","๐ŸŽถ"], ["groep","๐Ÿ‘ฅ"],["team","๐Ÿ‘ฅ"],["familie","๐Ÿ‘จโ€๐Ÿ‘ฉโ€๐Ÿ‘ง"],["ouder","๐Ÿ‘ช"],["kind","๐Ÿง’"],["mens","๐Ÿง‘"], ["wereld","๐ŸŒ"],["milieu","โ™ป๏ธ"],["afval","๐Ÿ—‘๏ธ"],["bestuur","๐Ÿ›๏ธ"] ]); function languageProgressionPicture(word,fallback){ if(LANGUAGE_PICTURE_EXACT[word])return LANGUAGE_PICTURE_EXACT[word]; const match=LANGUAGE_PICTURE_HINTS.filter(([part])=>word.includes(part)).sort((a,b)=>b[0].length-a[0].length) .find(([,emoji])=>emoji!==fallback); return match?fallback+match[1]:fallback } /* Ruim duizend aanvullende Nederlandse woorden, geordend in woordfamilies. Iedere regel loopt bewust van een kort, concreet basiswoord naar langere afleidingen, samenstellingen en schooltaal. De positie op de regel bepaalt het eerste leerjaar waarin het woord wordt aangeboden; hogere leerjaren behouden de eerder aangeboden woorden. Woorden die al in LANGUAGE_CONCEPTS staan worden hieronder automatisch overgeslagen. */ const LANGUAGE_NL_PROGRESSION_FAMILIES={ animals:"๐Ÿˆ|kat,poes,kitten,kater,katten,poesje,kattenbak,kattenvoer,huiskat,kattenluik,zwerfkat,kattenkwaad\n๐Ÿ•|hond,pup,reu,teef,honden,pupje,hondenhok,hondenriem,waakhond,hondensport,geleidehond,hondenbezitter\n๐Ÿด|paard,pony,veulen,merrie,hengst,paardenstal,paardrijden,renpaard,paardensprong,paardentrailer,paardenverzorging,paardrijwedstrijd\n๐Ÿฆ|vogel,mus,merel,kraai,duif,nestje,vogelvoer,zangvogel,trekvogel,vogelkooi,vogelkenner,vogelbescherming\n๐ŸŸ|vis,karper,baars,haai,rog,visje,vijvervis,zeedier,visnet,vissersboot,onderwaterdier,waterdierenverblijf\n๐Ÿž|mier,bij,wesp,kever,vlinder,rups,insectenhotel,bijenkorf,sprinkhaan,lieveheersbeestje,insectenkenner,insectenonderzoek\n๐Ÿ„|koe,kalf,geit,schaap,varken,lammetje,kippenhok,melkkoe,boerderijdier,dierenweide,dierenverzorger,veehouderij", food:"๐Ÿž|brood,bol,toast,korst,kruimel,broodje,volkorenbrood,broodmes,bakkerij,broodbeleg,broodtrommel,broodbereiding\n๐ŸŽ|fruit,appel,peer,pruim,kers,appeltje,fruitsap,fruitmand,boomgaard,vruchtvlees,fruitsoorten,fruitteeltbedrijf\n๐Ÿฅ›|melk,karnemelk,room,boter,vla,melkpak,melkglas,zuivel,melkboer,melkproduct,zuivelfabriek,voedingsmiddel\n๐Ÿง€|kaas,brie,gaten,plak,korst,kaasje,kaasplank,kaasschaaf,kaaswinkel,smeerkaas,kaasbereiding,zuivelproduct\n๐Ÿฅ”|aardappel,friet,puree,schil,knol,pieper,aardappelmes,stamppot,aardappelveld,aardappelplant,aardappelgerecht,aardappelverwerking\n๐Ÿฅ•|groente,wortel,prei,kool,boon,erwtje,groentesoep,snijplank,moestuin,groentekraam,groentesoorten,groentegerecht\n๐Ÿฐ|taart,koek,snoep,cake,wafel,gebakje,slagroom,taartpunt,bakvorm,koekjesdeeg,feestmaaltijd,suikergehalte", nature:"๐ŸŒณ|boom,stam,tak,blad,wortel,boompje,boomschors,boomkroon,loofboom,naaldboom,boomsoorten,bomenonderzoek\n๐ŸŒท|bloem,roos,tulp,stengel,knop,bloempje,bloempot,bloembol,boeket,zonnebloem,bloemenweide,bloembestuiving\n๐Ÿ’ง|water,druppel,plas,sloot,beek,waterkant,drinkwater,waterput,grondwater,waterleiding,waterzuivering,waterkringloop\nโ˜€๏ธ|zon,maan,ster,licht,schaduw,zonnetje,zonlicht,maansikkel,sterrenhemel,zonsopgang,zonnestraling,sterrenstelsel\n๐ŸŒง๏ธ|regen,wolk,wind,mist,bui,regendruppel,regenjas,wolkbreuk,weersbericht,regenboog,neerslaggebied,weersverwachting\nโ„๏ธ|sneeuw,ijs,vorst,hagel,vlok,sneeuwpop,ijskoud,sneeuwbal,winterweer,sneeuwstorm,temperatuurdaling,winterlandschap\n๐ŸŒฑ|aarde,grond,zaad,kiem,plant,zaadje,potgrond,plantengroei,bodemlaag,bodemvruchtbaarheid,voedingsstoffen,kiemingsproces", travel:"๐Ÿš—|auto,bus,taxi,rit,band,autootje,autodeur,autoruit,parkeerplek,autoweg,automobilist,verkeersveiligheid\n๐Ÿšฒ|fiets,step,pedaal,bel,stuur,fietsje,fietspad,fietspomp,bakfiets,fietstocht,fietsenmaker,fietsverlichting\n๐Ÿš‚|trein,tram,rail,spoor,rit,treintje,perron,station,spoorlijn,treinreis,treinmachinist,spoorwegovergang\nโ›ต|boot,schip,kano,zeil,roeispaan,bootje,zeilboot,reddingsboei,haven,scheepsdek,binnenvaartschip,scheepvaartverkeer\nโœˆ๏ธ|vliegtuig,jet,vleugel,piloot,vlucht,vliegveld,landingsbaan,luchtvaart,vliegreis,verkeerstoren,passagiersvliegtuig,luchtvaartmaatschappij\n๐Ÿ›ฃ๏ธ|weg,pad,brug,tunnel,bocht,wegdek,kruispunt,rotonde,rijbaan,wegwijzer,infrastructuur,verkeersknooppunt\n๐Ÿšฆ|licht,bord,streep,file,route,stoplicht,verkeersbord,zebrapad,voorrang,weggebruiker,verkeersregelaar,verkeerssituatie", home:"๐Ÿ |huis,flat,hut,dak,muur,huisje,voordeur,woonkamer,rijtjeshuis,woonwijk,huizenblok,woninginrichting\n๐Ÿ›๏ธ|bed,kast,lamp,deken,kussen,bedje,nachtkast,bedlamp,slaapkamer,dekbedovertrek,slaapvertrek,slaapkamerraam\n๐Ÿช‘|stoel,tafel,bank,kruk,kast,stoeltje,tafelblad,eettafel,boekenkast,stoelzitting,meubelwinkel,woonkamermeubel\n๐Ÿšช|deur,raam,slot,sleutel,bel,deurtje,deurklink,vensterbank,raamkozijn,voordeurbel,inbraakbeveiliging,toegangssysteem\n๐Ÿณ|pan,pot,kom,bord,lepel,pannetje,koekenpan,keukenkast,aanrecht,afwasborstel,keukengerei,voedselbereiding\n๐Ÿšฟ|bad,douche,wc,kraan,zeep,badje,handdoek,wastafel,badkamer,tandenborstel,waterbesparing,badkamertegel\n๐Ÿงน|stof,vuil,bezem,dweil,spons,stofdoek,afwasmiddel,prullenbak,schoonmaak,schoonmaker,schoonmaakmiddel,huishoudelijkehulp", body:"โœ‹|hand,duim,vinger,nagel,pols,handje,vingertop,handpalm,wijsvinger,vingerafdruk,handbeweging,handvaardigheid\n๐Ÿฆถ|voet,teen,hiel,enkel,knie,voetje,voetzool,knieschijf,onderbeen,voetstap,lichaamshouding,bewegingsapparaat\n๐Ÿ™‚|hoofd,wang,kin,nek,keel,hoofdje,voorhoofd,achterhoofd,gezicht,gezichtsvorm,gelaatsuitdrukking,hoofdbescherming\n๐Ÿ‘๏ธ|oog,oor,neus,mond,lip,oogje,ooglid,neusgat,wenkbrauw,zintuig,gehoororgaan,waarnemingsvermogen\n๐Ÿฆท|tand,kies,tong,speeksel,gebit,tandje,tandvlees,tandenborstel,tandarts,mondzorg,tandheelkunde,gebitsverzorging\n๐Ÿ‘•|jas,shirt,trui,broek,rok,jasje,regenbroek,winterjas,kledingkast,kledingmaat,kledingstuk,kledingindustrie\nโค๏ธ|hart,long,bloed,bot,spier,hartslag,bloedvat,longinhoud,skelet,spierkracht,bloedsomloop,ademhalingsstelsel", actions:"๐Ÿšถ|gaan,lopen,stap,staan,zitten,wandelen,voetstap,doorlopen,oversteken,vooruitgaan,verplaatsing,bewegingsrichting\n๐Ÿƒ|rennen,racen,sprinten,haasten,vluchten,hardlopen,renbaan,wedloop,marathon,snelheidsmeter,hardloopwedstrijd,uithoudingsvermogen\n๐Ÿคธ|springen,hupsen,bukken,rollen,draaien,sprongetje,springtouw,koprol,evenwicht,lichaamsbeweging,bewegingsreeks,bewegingsoefening\n๐Ÿ“–|lezen,boek,blad,zin,tekst,leesboek,voorlezen,leesbril,leeshoek,leesstrategie,leesvaardigheid,tekstinterpretatie\nโœ๏ธ|schrijven,pen,schrift,letter,woord,opschrijven,handschrift,schrijfboek,schrijfregel,schrijfopdracht,schrijfvaardigheid,tekstproductie\n๐Ÿ—ฃ๏ธ|praten,zeggen,vragen,roepen,fluisteren,vertellen,spreekbeurt,gesprek,uitspraak,woordkeuze,taalgebruik,gespreksvaardigheid\n๐Ÿค|helpen,delen,geven,halen,brengen,hulpje,samenwerken,meehelpen,ondersteunen,hulpverlening,samenwerkingsvorm,verantwoordelijkheid", feelings:"๐Ÿ˜€|blij,leuk,fijn,lachen,vrolijk,glimlach,plezier,opgewekt,tevreden,blijheid,enthousiasme,geluksgevoel\n๐Ÿ˜ข|sip,moe,verdriet,pijn,huilen,traantje,teleurgesteld,verdrietig,somber,eenzaamheid,teleurstelling,verdrietverwerking\n๐Ÿ˜ |boos,kwaad,ruzie,mopperen,grommen,boosheid,driftig,prikkelbaar,woedend,meningsverschil,frustratie,conflictbeheersing\n๐Ÿ˜จ|bang,eng,schrik,zorgen,trillen,angstig,schrikken,onzeker,bezorgd,angstgevoel,onveiligheid,zelfbescherming\n๐Ÿ™‚|rust,kalm,stil,zacht,ademen,rustig,ontspannen,geduldig,vertrouwd,ontspanning,zelfbeheersing,ademhalingsoefening\n๐Ÿ˜Œ|trots,dapper,sterk,durven,winnen,trotsheid,moedig,zelfstandig,zelfvertrouwen,doorzetter,doorzettingsvermogen,zelfwaardering\n๐Ÿคฉ|nieuw,raar,wauw,vragen,kijken,verrast,benieuwd,nieuwsgierig,verwondering,belangstelling,onderzoekshouding,ontdekkingsvreugde", people:"๐Ÿ‘จโ€๐Ÿ‘ฉโ€๐Ÿ‘ง|familie,gezin,kind,baby,ouders,gezinnetje,familielid,stiefouder,grootouder,familieband,gezinssituatie,familiegeschiedenis\n๐Ÿ‘ฉ|mama,moeder,vrouw,tante,dochter,moedertje,schoonmoeder,moederdag,moederfiguur,moederschap,ouderverzorging,gezinsverantwoordelijkheid\n๐Ÿ‘จ|papa,vader,man,oom,zoon,vadertje,schoonvader,vaderdag,vaderfiguur,vaderschap,oudercontact,opvoedingsverantwoordelijkheid\n๐Ÿง’|kind,jongen,meisje,kleuter,puber,kindje,schoolkind,leeftijdgenoot,jeugd,ontwikkeling,kinderrechten,identiteitsontwikkeling\n๐Ÿง‘โ€๐Ÿคโ€๐Ÿง‘|vriend,maat,buur,gast,club,vriendje,vriendschap,buurkind,kennismaking,groepsgenoot,vertrouwenspersoon,vriendschapsrelatie\n๐Ÿง‘โ€๐Ÿซ|juf,meester,leraar,mentor,coach,leerkracht,lesgever,schoolteam,begeleider,onderwijsassistent,onderwijsprofessional,leerlingbegeleiding\n๐Ÿ‘ฅ|groep,team,klas,paar,kring,groepje,klasgenoot,teamlid,samenkomst,groepswerk,groepsvorming,groepsdynamiek", play:"โšฝ|bal,doel,trap,team,veld,balletje,voetbal,doelman,wedstrijd,voetballer,voetbaltraining,competitiewedstrijd\n๐Ÿ€|basket,korf,worp,score,punt,gooien,basketbal,dribbelen,balbezit,teamsport,sportvereniging,wedstrijdreglement\n๐Ÿงฉ|puzzel,stuk,vorm,rand,plaat,puzzelstuk,legpuzzel,denkspel,oplossing,puzzelboek,probleemoplossing,denkstrategie\n๐Ÿงธ|pop,beer,blok,trein,auto,popje,knuffel,bouwblok,speelgoed,speelkamer,speelgoedwinkel,fantasiespel\n๐ŸŽฒ|spel,beurt,dobbelsteen,kaart,pion,spelletje,spelregel,bordspel,tegenstander,winnaar,spelstrategie,gezelschapsspel\n๐ŸŠ|zwemmen,duiken,bad,plons,slag,zwemband,zwembad,schoolslag,duikplank,zwemles,zwemvaardigheid,waterveiligheid\n๐Ÿ…|sport,spel,prijs,beker,medaille,sporter,sportdag,training,kampioen,sportprestatie,sportiviteit,wedstrijdorganisatie", places:"๐Ÿซ|school,klas,plein,les,gym,schooltje,schoolbank,schoolplein,schoolgebouw,schooljaar,schoolorganisatie,onderwijsomgeving\n๐Ÿช|winkel,kassa,kar,mand,klant,winkeltje,winkelier,winkelstraat,boodschap,winkelcentrum,klantenservice,detailhandel\n๐Ÿฅ|arts,dokter,bed,zaal,zorg,ziekenhuis,verpleegkundige,wachtkamer,behandeling,zorgverlening,gezondheidszorg,ziekenhuisafdeling\n๐Ÿก|boer,stal,schuur,land,erf,boerderij,landbouwer,akkerbouw,boerenbedrijf,landbouwgrond,landbouwmachine,voedselproductie\n๐Ÿ“š|boek,kast,balie,pas,lezer,bibliotheek,boekenkast,bibliothecaris,uitleentermijn,boekenafdeling,informatiedienst,mediatheekbeheer\n๐Ÿ™๏ธ|stad,dorp,straat,plein,buurt,stadje,dorpsplein,woonplaats,stadscentrum,gemeentehuis,stedelijkgebied,bevolkingsdichtheid\n๐Ÿž๏ธ|park,bos,veld,pad,vijver,parkje,speelweide,natuurpark,wandelroute,recreatiegebied,landschapsbeheer,natuurvoorziening", time:"โ˜€๏ธ|dag,uur,tijd,klok,middag,dagje,daglicht,dagdeel,dagritme,tijdstip,dagindeling,tijdswaarneming\n๐ŸŒ…|ochtend,vroeg,wakker,ontbijt,zonsopgang,ochtendlicht,ochtendritueel,schoolochtend,dagbegin,ochtendspits,ochtendprogramma,ochtendactiviteit\n๐ŸŒ‡|avond,laat,eten,donker,zonsondergang,avondlicht,avondeten,bedtijd,dagafsluiting,avondprogramma,avondschemering,avondvoorstelling\n๐Ÿ—“๏ธ|week,maand,jaar,datum,agenda,weekje,weekdag,maandblad,jaartal,kalenderjaar,tijdrekening,kalenderindeling\n๐ŸŽ‚|feest,taart,kaars,cadeau,ballon,feestje,verjaardag,feestmuts,feestdag,uitnodiging,feestversiering,verjaardagsviering\n๐Ÿ‚|lente,zomer,herfst,winter,seizoen,lentebloem,zomerdag,herfstblad,winterjas,seizoenswissel,jaargetijde,seizoensverschijnsel\nโฑ๏ธ|minuut,seconde,kwart,half,duur,minuutje,tijdsduur,stopwatch,kwartier,wachttijd,tijdseenheid,tijdsberekening", arts:"๐ŸŽจ|kleur,verf,kwast,doek,palet,kleurtje,verfpot,schilderen,schilderij,kunstschilder,kleurgebruik,schildertechniek\n๐Ÿ–๏ธ|tekening,lijn,vorm,punt,vak,tekenen,kleurplaat,schetsboek,omtrek,tekenmateriaal,beeldverhaal,illustratietechniek\n๐ŸŽต|toon,lied,stem,klank,maat,liedje,muziek,nootbalk,melodie,muzikant,muziekstuk,muziekuitvoering\n๐Ÿฅ|trom,fluit,snaar,toets,bel,trommel,instrument,gitaarspel,slagwerk,muziekles,muziekinstrument,instrumentenfamilie\n๐Ÿ’ƒ|dans,stap,sprong,draai,pas,dansje,dansvloer,dansgroep,choreografie,dansvoorstelling,bewegingspatroon,podiumkunst\n๐ŸŽญ|toneel,rol,pak,tekst,podium,toneelstuk,acteur,optreden,voorstelling,toneelspeler,podiumverlichting,theatervoorstelling\n๐Ÿ“ท|foto,film,beeld,lens,flits,fotootje,camera,fotoboek,filmopname,fotograaf,beeldbewerking,mediaproductie", science:"๐Ÿ”|kijken,zoeken,vraag,vondst,spoor,onderzoek,waarnemen,vergrootglas,ontdekking,onderzoeker,waarneming,onderzoeksresultaat\n๐Ÿงช|proef,test,buis,stof,mengen,proefje,reactie,meetglas,experiment,laboratorium,proefopstelling,onderzoeksverslag\n๐Ÿงฒ|magneet,ijzer,pool,kracht,veld,aantrekken,afstoten,magnetisch,kompasnaald,magneetkracht,magnetisme,natuurverschijnsel\nโš™๏ธ|wiel,as,tand,veer,hefboom,tandwiel,overbrenging,mechaniek,machine,werktuig,bewegingsenergie,machinewerking\n๐Ÿ’ก|licht,stroom,draad,lamp,stekker,schakelaar,batterij,stroomkring,elektrisch,elektriciteit,energieverbruik,energievoorziening\n๐Ÿ’ป|computer,muis,toets,scherm,bestand,computerprogramma,toetsenbord,beeldscherm,digitaal,internet,programmeren,informatietechnologie\n๐Ÿš€|ruimte,maan,planeet,ster,raket,ruimtevaart,satelliet,heelal,astronaut,zonnestelsel,ruimtestation,ruimteonderzoek", learning:"๐Ÿ”ค|letter,klank,woord,naam,teken,alfabet,lettergreep,klinker,medeklinker,lettervolgorde,klankstructuur,spellingspatroon\n๐Ÿ“|zin,punt,komma,vraag,tekst,zinnetje,hoofdletter,leesteken,zinsdeel,zinsbouw,tekstverband,taalbeschouwing\n๐Ÿ“–|boek,blad,kaft,titel,prent,boekje,hoofdstuk,inhoudsopgave,schrijver,boekbespreking,literatuur,leeservaring\n๐Ÿ—ฃ๏ธ|taal,stem,spraak,gesprek,verhaal,vertellen,luisteraar,spreker,spreekbeurt,gespreksregel,taalgebruik,communicatievaardigheid\n๐Ÿ”ข|nul,een,twee,drie,getal,cijfer,reeks,getallenlijn,getalbeeld,plaatswaarde,getalstructuur,getalnotatie\nโž•|som,plus,min,keer,delen,optellen,aftrekken,uitkomst,bewerking,rekenregel,rekenstrategie,bewerkingsvolgorde\n๐Ÿ“|vorm,lijn,hoek,vlak,lengte,driehoek,rechthoek,meetlat,oppervlakte,omtrekberekening,meetinstrument,meetkundigevorm", society:"๐Ÿค|samen,hulp,beurt,afspraak,regel,samenwerken,overleggen,taakverdeling,deelname,samenleving,samenwerkingsverband,maatschappijleer\n๐Ÿ˜๏ธ|buurt,wijk,dorp,stad,straat,buurthuis,woonwijk,gemeente,provincie,stadsbestuur,gemeenteraad,gebiedsindeling\n๐ŸŒ|wereld,land,zee,kaart,grens,wereldbol,landkaart,continent,werelddeel,bevolking,wereldbevolking,wereldburgerschap\n๐Ÿ—บ๏ธ|noord,zuid,oost,west,plek,richting,kompas,kaartteken,plattegrond,schaalverdeling,herkenningspunt,kaartvaardigheid\n๐Ÿ“ฐ|nieuws,krant,bericht,radio,media,nieuwsblad,journalist,nieuwsbron,actualiteit,nieuwsbericht,betrouwbaarheid,mediageletterdheid\nโ™ป๏ธ|afval,bak,glas,papier,natuur,recyclen,hergebruik,afvalbak,milieuzorg,afvalscheiding,duurzaamheid,grondstoffengebruik\nโš–๏ธ|recht,plicht,keus,stem,wet,eerlijk,verkiezing,mening,besluit,democratie,grondrecht,besluitvorming" }; const LANGUAGE_PROGRESSION_YEARS=[1,2,3,3,4,5,5,6,7,8,7,8]; const LANGUAGE_NL_PROGRESSION_WORDS=(()=>{ const seen=new Set(LANGUAGE_CONCEPTS.map(item=>item.nl)),out=[]; Object.entries(LANGUAGE_NL_PROGRESSION_FAMILIES).forEach(([theme,rows])=>rows.split("\n").forEach(row=>{ const [pic,list]=row.split("|");let familyPosition=0; list.split(",").forEach(raw=>{ const word=raw.trim();if(!word||seen.has(word))return;seen.add(word); const slug=word.normalize("NFD").replace(/[\u0300-\u036f]/g,"").replace(/[^a-z]/g,""); const yearGroup=LANGUAGE_PROGRESSION_YEARS[Math.min(familyPosition++,LANGUAGE_PROGRESSION_YEARS.length-1)]; out.push({id:"nl-"+theme+"-"+slug,theme,nl:word,pic:languageProgressionPicture(word,pic),yearGroup,pictureChecked:true}); }); })); return out })(); /* Instapwoorden voor beginnende geletterdheid. In groep 1 zijn woorden alleen beeldankers om een letter en beginklank te herkennen; kinderen hoeven deze woorden nog niet te lezen. Groep 2 voegt korte, vertrouwde woorden toe voor letter-klankkoppeling en het aanvullen van een ontbrekende klank. */ const LANGUAGE_EARLY_WORDS=Object.freeze({ 1:new Set("aap arm bal bed been boek boom boot bos bus deur ei hand huis jas kaas kat kip koe maan mier mond muis neus oog oor pen peer pet pop rok roos sok tas uil vis voet vuur wiel zon".split(" ")), 2:new Set("appel beer bij eend geit haas hond kikker paard vos slak spin varken melk taart brood soep rijst mais druif snoep sap koek wortel ster bloem blad wolk regen water steen zand zee gras wind auto fiets trein taxi tram weg zeil step stoel klok bril blok sleutel lamp beker verf schaar school haar hoofd schoen jurk shirt want broek tand lezen eten slapen lopen lachen huilen zingen dansen spelen zitten rennen kijken blij boos bang moe ziek trots rustig baby kind jongen meisje vader moeder zus broer oma opa buur man voetbal puzzel spel knikker winkel boer park klas kok stad dorp dag week jaar feest kaars vlag uur".split(" ")) }); const LANGUAGE_LOANWORDS_FROM_YEAR5=new Set("wc ski toast jet rail brie pizza citroen cadeau team club cake score hockey bowlen shirt flat".split(" ")); function languageDataComplexity(word){ const w=String(word||"").toLocaleLowerCase("nl-NL").replace(/[^a-z]/g,""); const clusters=(w.match(/[bcdfghjklmnpqrstvwxz]{2,}/g)||[]).reduce((n,x)=>n+x.length-1,0); const patterns=(w.match(/aai|ooi|oei|eeuw|ieuw|sch|ng|nk|ch|aa|ee|oo|uu|oe|ie|ei|ij|ou|au|ui|eu/g)||[]).length; const syllables=(w.match(/[aeiouy]+/g)||[]).length; return w.length+clusters*2+patterns+Math.max(0,syllables-1)*2; } /* Een woord stroomt pas in als zowel de geplande woordfamilie, de spelling als de inhoud bij het leerjaar passen. Dit voorkomt bijvoorbeeld dat korte maar abstracte woorden als 'som', 'wet' en 'team' in de kleuterpool komen. */ function languageRecommendedYear(item){ const word=String(item.nl||"").toLocaleLowerCase("nl-NL"); if(LANGUAGE_EARLY_WORDS[1].has(word))return 1; if(LANGUAGE_EARLY_WORDS[2].has(word))return 2; const complexity=languageDataComplexity(word); const syllables=(word.match(/[aeiouy]+/g)||[]).length; const patternYear=/eeuw|ieuw|aai|ooi|oei/.test(word)?5:/sch|ng|nk|ch|oe|ie|ei|ij|ou|au|ui|eu/.test(word)?4:3; const loanwordYear=LANGUAGE_LOANWORDS_FROM_YEAR5.has(word)?5:3; const spellingYear=Math.max(complexity<=9?3:complexity<=14?4:complexity<=19?5:complexity<=24?6:complexity<=30?7:8,syllables>=3?5:syllables>=2?4:3,patternYear,loanwordYear); const themeYear={learning:4,science:4,society:5,arts:3,feelings:3}[item.theme]||3; return Math.max(3,Number(item.yearGroup)||3,spellingYear,themeYear); } const LANGUAGE_NL_BUILTIN_WORDS=LANGUAGE_CONCEPTS.concat(LANGUAGE_NL_PROGRESSION_WORDS) .map(item=>Object.assign({},item,{yearGroup:languageRecommendedYear(item)})); /* De vertrouwde startkaart blijft exact dezelfde 30 woorden houden. */ const START_WORD_KEYS = { nl:["monkey","fish","sun","cat","ball","egg","tree","house","moon","boat","hen","mouse","book","star","rose","fire","bike","cake","coat","glasses","clock","pear","cheese","duck","hand","foot","nose","eye","ear","mouth"], en:["cat","dog","sun","egg","ball","fish","tree","moon","boat","star","book","cake","house","mouse","apple","train","fire","rose","bear","duck","frog","bee","cow","pig","hand","foot","nose","eye","ear","milk"] }; const WORDS = Object.fromEntries(["nl","en"].map(lang=>[ lang, START_WORD_KEYS[lang].map(id=>{ const concept=LANGUAGE_CONCEPTS.find(item=>item.id===id); return [concept[lang],concept.pic,lang==="nl"?languageRecommendedYear(concept):null]; }) ])); function languageBuiltinWords(lang=LANG){ return lang==="nl"?LANGUAGE_NL_BUILTIN_WORDS:LANGUAGE_CONCEPTS } function languageThemeList(lang=LANG){ return LANGUAGE_THEME_DEFS.map(theme=>({ ...theme, name:theme[lang], words:languageBuiltinWords(lang).filter(item=>item.theme===theme.id) .map(item=>[item[lang]||item.nl,item.pic,item.yearGroup||null]) })).filter(theme=>theme.words.length); } function languageEmojiDataUrl(emoji,colors=["#f4f8ff","#dce9fa"]){ const fontSize=emoji.length>4?104:emoji.length>2?122:148; const svg=`${emoji}`; return "data:image/svg+xml;charset=utf-8,"+encodeURIComponent(svg); } function languagePictureCatalog(lang=LANG){ const builtinThemes=languageThemeList(lang).map((theme,index)=>({ id:-200-index,nameNl:theme.nl,nameEn:theme.en,scope:"global",filterOnly:true, languageBuiltin:true,wordPicture:true,icon:theme.icon })); const themeIds=new Map(LANGUAGE_THEME_DEFS.map((theme,index)=>[theme.id,-200-index])); const images=languageBuiltinWords(lang).map((item,index)=>{ const theme=LANGUAGE_THEME_DEFS.find(def=>def.id===item.theme); const name=item[lang]||item.nl; return { id:-1000-index,name,folder:`Taal/Woordenschat/${theme[lang]}`, scope:"global",themes:[themeIds.get(item.theme)],tags:[item.nl,item.en,theme.nl,theme.en].filter(Boolean), src:languageEmojiDataUrl(item.pic,theme.colors),value:item.pic,canManage:false,canDelete:false, wordPicture:true,builtin:true,yearGroup:item.yearGroup||null }; }); const ownThemes=[]; const customImages=[]; let customId=-5000; const addOwn=(words,name,folder,themeId)=>{ (words||[]).forEach(([word,pic])=>{ if(!word||!pic)return; customImages.push({ id:customId--,name:word,folder,scope:"personal",themes:[themeId],tags:[word,name], src:isImg(pic)?pic:languageEmojiDataUrl(pic),value:pic,canManage:false,canDelete:false, wordPicture:true,builtin:false }); }); }; const generalThemeId=-400; ownThemes.push({id:generalThemeId,nameNl:"Mijn woordkaarten",nameEn:"My word cards",scope:"personal",filterOnly:true,wordPicture:true,icon:"โญ"}); addOwn(GENERAL_EXTRA[lang],lang==="nl"?"Mijn woordkaarten":"My word cards","Taal/Mijn woordkaarten",generalThemeId); THEMES[lang].forEach((theme,index)=>{ const id=-401-index; ownThemes.push({id,nameNl:theme.name,nameEn:theme.name,scope:"personal",filterOnly:true,wordPicture:true,icon:"๐Ÿ“"}); addOwn(theme.words,theme.name,["Taal/Mijn themaโ€™s",theme.folder,theme.name].filter(Boolean).join("/"),id); }); return {themes:builtinThemes.concat(ownThemes),images:images.concat(customImages)}; } /* teacher's own additions to the general card (persisted per user) */ let GENERAL_EXTRA = {nl:[], en:[]}; function generalList(){ return WORDS[LANG].concat(GENERAL_EXTRA[LANG]); } const shuffle = a => { a=a.slice(); for(let i=a.length-1;i>0;i--){const j=Math.floor(Math.random()*(i+1)); [a[i],a[j]]=[a[j],a[i]];} return a; }; /* custom themes: folders of own words. {nl:[{name:"Herfst", words:[[word,pic],...]}], en:[...]} */ let THEMES = {nl:[], en:[]}; /* ankerbibliotheek: los van borden bewaarde ankerdiagrammen, herbruikbaar op elk bord. [{id, name, folder?, cells, pics}] - cells/pics in dezelfde vorm als de widget-staat van anchor.js; folder is een pad ("A/B") zoals bij de thema's en borden in de mappenverkenner. */ let ANCHOR_LIB = []; function themesFromData(data){ if(!data) return {nl:[],en:[]}; if(data.themes) return data.themes; /* migrate old flat word lists into one theme */ const t = {nl:[],en:[]}; if(data.words) ["nl","en"].forEach(l=>{ if(Array.isArray(data.words[l]) && data.words[l].length) t[l] = [{name: l==="nl" ? "Mijn woorden" : "My words", words: data.words[l]}]; }); return t; } const isImg = p => typeof p==="string" && /^(?:data:|https?:|blob:|\/)/.test(p); function setPic(el, pic){ if(isImg(pic)){ el.innerHTML = ""; const im = document.createElement("img"); im.src = pic; im.alt=""; el.appendChild(im); } else el.textContent = pic; } /* ---- ARASAAC pictogram lookup (shared by the word editor + anchor grid) ---- */ async function arasaacSearch(term, lang){ const resp = await fetch(`https://api.arasaac.org/api/pictograms/${lang}/search/${encodeURIComponent(term)}`); if(!resp.ok) throw new Error("http "+resp.status); return resp.json(); } const arasaacUrl = id => `https://static.arasaac.org/pictograms/${id}/${id}_300.png`; /* ---- shared word source (general card + themes + anchor grids) ---- */ /* anchor-word widgets register their words here so every language widget can use them as a theme automatically */ let ANCHORS = []; /* [{el, name, words:[[w,pic],...]}] */ function anchorSources(){ ANCHORS = ANCHORS.filter(a=>a.el && document.contains(a.el)); return ANCHORS.filter(a=>a.words.length); } function normWordSource(card){ if(typeof card==="string"){ if(card.startsWith("b:")){ if(languageThemeList().some(theme=>theme.id===card.slice(2))) return card; }else if(card.startsWith("t")){ const th = THEMES[LANG][+card.slice(1)]; if(th && th.words.length) return card; }else if(card.startsWith("a")){ if(anchorSources()[+card.slice(1)]) return card; } } return "g"; } function wordSourceList(card){ card = normWordSource(card); if(card.startsWith("b:")) return languageThemeList().find(theme=>theme.id===card.slice(2)).words; if(card.startsWith("t")) return THEMES[LANG][+card.slice(1)].words; if(card.startsWith("a")) return anchorSources()[+card.slice(1)].words; return generalList(); } function fillWordSourceSel(sel, card, yearGroup=null, level=2){ sel.innerHTML = ""; const og = document.createElement("option"); og.value = "g"; og.textContent = "โญ "+T("cardStart"); sel.appendChild(og); const builtinGroup = document.createElement("optgroup"); builtinGroup.label = "๐Ÿ“š "+T("wordThemes"); languageThemeList().forEach(theme=>{ const available=yearGroup&&typeof languageWordsForYear==="function"?languageWordsForYear(theme.words,yearGroup,level):theme.words; if(!available.length)return; const option=document.createElement("option"); option.value="b:"+theme.id; option.textContent=`${theme.icon} ${theme.name} (${available.length})`; builtinGroup.appendChild(option); }); sel.appendChild(builtinGroup); /* thema's zonder map bovenaan, daarna per map gegroepeerd (optgroup) - zelfde indeling als de theme-dropdown in de woorden-editor */ const groups = new Map(); THEMES[LANG].forEach((th,i)=>{ if(!th.words.length) return; const f = th.folder || ""; if(!groups.has(f)) groups.set(f, []); groups.get(f).push([th, i]); }); const addOpt = (parent, th, i)=>{ const o = document.createElement("option"); o.value = "t"+i; o.textContent = "โ˜… "+th.name; parent.appendChild(o); }; (groups.get("") || []).forEach(([th,i])=>addOpt(sel, th, i)); [...groups.keys()].filter(f=>f).sort().forEach(f=>{ const grp = document.createElement("optgroup"); grp.label = "๐Ÿ“ " + f; groups.get(f).forEach(([th,i])=>addOpt(grp, th, i)); sel.appendChild(grp); }); anchorSources().forEach((a,i)=>{ const o = document.createElement("option"); o.value = "a"+i; o.textContent = "โš“ "+a.name; sel.appendChild(o); }); sel.value = normWordSource(card); if(sel.selectedIndex < 0) sel.selectedIndex = 0; } /* emoji palette (grouped) */ const splitEmoji = s => { const out = []; for(const ch of s){ if(out.length && (ch==="๏ธ" || ch==="โ€")) out[out.length-1]+=ch; else if(out.length && out[out.length-1].endsWith("โ€")) out[out.length-1]+=ch; else out.push(ch); } return out; }; const EMOJI_CATS = [ splitEmoji("๐Ÿต๐Ÿถ๐Ÿฑ๐Ÿญ๐Ÿน๐Ÿฐ๐ŸฆŠ๐Ÿป๐Ÿผ๐Ÿจ๐Ÿฏ๐Ÿฆ๐Ÿฎ๐Ÿท๐Ÿธ๐Ÿ”๐Ÿง๐Ÿฆ๐Ÿฆ†๐Ÿฆ‰๐Ÿด๐Ÿฆ„๐Ÿ๐Ÿ›๐Ÿฆ‹๐ŸŒ๐Ÿž๐Ÿ ๐ŸŸ๐Ÿฌ๐Ÿณ๐Ÿข๐Ÿ๐ŸฆŽ๐Ÿ˜๐Ÿฆ’"), splitEmoji("๐ŸŽ๐Ÿ๐ŸŠ๐Ÿ‹๐ŸŒ๐Ÿ‰๐Ÿ‡๐Ÿ“๐Ÿ’๐Ÿ‘๐Ÿฅ๐Ÿ…๐Ÿฅ•๐ŸŒฝ๐Ÿฅ”๐Ÿง€๐Ÿฅš๐Ÿž๐Ÿฅ๐Ÿฅž๐Ÿ•๐ŸŸ๐Ÿฆ๐Ÿช๐ŸŽ‚๐Ÿซ๐Ÿฌ๐Ÿฅ›๐Ÿงƒ๐Ÿฏ"), splitEmoji("๐ŸŒณ๐ŸŒฒ๐ŸŒด๐ŸŒต๐ŸŒท๐ŸŒน๐ŸŒป๐ŸŒธ๐Ÿ’๐Ÿ„โญ๐ŸŒ™โ˜€๏ธโ›…๐ŸŒˆโ„๏ธ๐Ÿ”ฅ๐Ÿ’ง๐ŸŒŠ๐Ÿชจ"), splitEmoji("๐Ÿš—๐Ÿš•๐ŸšŒ๐Ÿš‘๐Ÿš’๐Ÿšœ๐Ÿšฒ๐Ÿ›ด๐Ÿ๏ธ๐Ÿš‚โœˆ๏ธ๐Ÿšโ›ต๐Ÿš€๐Ÿ›ถ๐Ÿšข"), splitEmoji("โšฝ๐Ÿ€๐ŸŽˆ๐ŸŽ๐Ÿงธ๐Ÿ“•โœ๏ธ๐Ÿ–๏ธโœ‚๏ธ๐ŸŽจ๐Ÿฅ๐ŸŽธ๐Ÿ‘“โŒšโฐ๐Ÿ’ก๐Ÿ”‘๐Ÿงค๐Ÿงข๐Ÿ‘Ÿ๐Ÿ‘—๐Ÿงฅ๐Ÿ›๏ธ๐Ÿช‘๐Ÿšช๐Ÿ "), splitEmoji("โœ‹๐Ÿ‘‚๐Ÿ‘ƒ๐Ÿ‘๏ธ๐Ÿ‘„๐Ÿฆถ๐Ÿ˜€๐Ÿ˜ข๐Ÿ˜ด๐Ÿคง๐Ÿ‘ถ๐Ÿ‘ฆ๐Ÿ‘ง๐Ÿ‘ต๐Ÿ‘ด") ];