Ga direct naar de hoofdinhoud
Klasklaar.nl
Home
Blog
Gr. 1/2
Inloopactiviteiten
Thema's
Thema Herfst
Thema Ruimte
Thema Sinterklaas
Thema Boerderij
Thema Vlinder
Thema Vervoer
Thema Bouwen
Thema Koningsspelen
Thema Gezondheid
Motoriek 1/2
Rekenen 1/2
Lezen 1/2
Verklanken
Voorleesteksten
SEO 1/2
Energizers
dagritmekaarten
Gr. 3
Thema's
Rekenen 3
Bussommen
Dobbelsteen sommen
Contextsommen
Lezen 3
Teksten op thema
Sinterklaas
Kerst
Carnaval
Feest
Koningsspelen
Beroepen
De bakker
De bouw
De hulpdiensten
De post
De bibliotheek
De boerderij
De speeltuin
De tuin
Dierentuin
Het bos
het restaurant
Strand
Het zwembad
Thuis
School
Supermarkt
Verkeer
Het vliegtuig
De trein
Winter
Lente
Zomer
Herfst
Piraten
Sprookjes
Familie
Huisdieren
Kleding
Gezondheid
Gezond eten
Sport
Insecten
Teksten B3
Teksten M3
Teksten E3
Lees en kleur
Luister, lees en kies
Lees en zoek
Waar of niet waar
SEO 3
Creatief
dagritmekaarten
Gr. 4
Rekenen 4
Getallen en bewerkingen
Verhaaltjessommen
Werkbladen
Rekenspelletjes
Meten
Verhaaltjessommen
Werkbladen
Tijd
Verhaaltjessommen
Werkbladen
Geld
Verhaaltjessommen
Werkbladen
Som bij het plaatje
Steunkaarten
Taal 4
Woordbenoemen
Zinsontleding
Taal Algemeen
Steunkaarten
Spelling 4
Steunkaarten
Spellingwerkbladen
Spellen
Lezen 4
Teksten B4
Teksten M4
Teksten E4
Leeslessen 4
Begrijpend Lezen 4
SEO 4
Overig
Geschiedenis 4
dagritmekaarten
Gr. 5
Rekenen 5
Getallen en bewerkingen
Verhaalsommen
Werkbladen
Rekenspelletjes
Meten
Werkbladen
Verhaalsommen
Tijd
Verhaalsommen
Werkbladen
Geld
Verhaalsommen
Werkbladen
Breuken
Verhaalsommen
Werkbladen
Steunkaarten
Taal 5
Woordbenoemen
Zinsontleding
Taal Algemeen
Spelling 5
Spellingwerkbladen
Spellen
Lezen 5
Teksten B5
Teksten M5
Teksten E5
Leeslessen 5
Begrijpend Lezen 5
SEO 5
Geschiedenis 5
Gr. 6
Rekenen 6
Getallen en Bewerkingen
Verhaalsommen
Werkbladen
Meten
Verhaalsommen
Werkbladen
Tijd
Verhaalsommen
Werkbladen
Geld
Verhaalsommen
Werkbladen
Breuken
Verhaalsommen
Werkbladen
Procenten
Verhaalsommen
Werkbladen
Steunkaarten
Taal 6
Woordbenoemen
Zinsontleding
Taal Algemeen
Spelling 6
Spellingwerkbladen
Spellen
Werkwoordspelling
Lezen 6
Teksten B6
Teksten M6
Teksten E6
Leeslessen 6
Begrijpend Lezen 6
SEO 6
Gr. 7
Rekenen 7
Getallen en Bewerkingen
Werkbladen
Verhaalsommen
Meten
Werkbladen
Verhaalsommen
Tijd
Werkbladen
Verhaalsommen
Geld
Werkbladen
Verhaalsommen
Breuken
Verhaalsommen
Werkbladen
Procenten
Werkbladen
Verhaalsommen
Verhoudingen
Steunkaarten
Taal 7
Woordbenoemen
Zinsontleding
Taal Algemeen
Spelling 7
Spellingwerkbladen
Spellen
Lezen 7
Teksten B7
Teksten M7
Teksten E7
Leeslessen 7
Begrijpend Lezen 7
SEO 7
Gr. 8
Rekenen 8
Getallen en bewerkingen
Verhaalsommen
Werkbladen
Meten
Verhaalsommen
Werkbladen
Tijd
Verhaalsommen
Werkbladen
Geld
Verhaalsommen
Werkbladen
Breuken
Verhaalsommen
Werkbladen
Procenten
Verhaalsommen
Werkbladen
Verhoudingen
Steunkaarten
Taal 8
Woordbenoemen
Zinsontleding
Taal Algemeen
Spelling 8
Spellingwerkbladen
Spellen
Lezen 8
Leeslessen
Lezen B8
Begrijpend Lezen
SEO 8
Afscheid
Didactiek
Sommenmaker
Taalmaker
Woordbenoemen generator
Woorden generator
Zinnen generator
NT2
Lezen
Pictokaarten
Taal
Portfolio
Dit ben ik
Mijn werk in beeld
Doeboekjes
Prentenboeken
Vlam en het feest
Blaadje en de storm
Kooltje en steenkolen
Wolkje in de lucht
Tok en Tik - De taart
Tok en Tik - We gaan je missen
Tok en Tik - De storm
Tok en Tik - Het ruim
Groepsvorming
Gouden Weken
Kinderliedjes
Digitale Geletterdheid
B-bot
Techniek
Kleurplaten
Sinterklaas
Kerst
Pasen
Carnaval
Koningsdag
Koningsspelen
Oud en Nieuw
Verjaardag
Moederdag
Vaderdag
Halloween
Valentijn
Lente
Zomer
Herfst
Winter
Regen
Sneeuw
Strand
Bloemen
Paddenstoelen
Weer
Bakker
Bouw
Kunstenaar
Politie
Brandweer
Dokter
Tandarts
Boer
Kapper
Post
Winkel
Auto
Tractor
Bus
Vliegtuig
Boot
Fiets
Trein
Vrachtwagen
Graafmachine
Brandweerauto
Politieauto
Voetbal
Hockey
Korfbal
Zwemmen
Dansen
Turnen
Sportdag
Speeltuin
Speelgoed
Spelletjes
Sprookjes
Draken
Ridders
Piraten
Prinsessen
Zeemeerminnen
Heksen
Tovenaars
Eenhoorns
Monsters
Natuur
Bos
Boerderij
Ruimte
Verkeer
Gezondheid
Lichaam
Eten en drinken
Techniek
Recycling
Boerderijdieren
Dierentuin
Huisdieren
Bosdieren
Zeedieren
Insecten
Vogels
Dino's
Paarden
Honden
Katten
Ballet
Timer
Sommenflitser
Woordenflitser
Keuzerad
Dagstarter
Praatplaten
Naamplaatjes
Splitsmachine
Bussommen
Rekenrek
AR Aquarium
Woordzoeker maker
Sudoku Maker
Doolhof maker
Klokken maker
Online spellen
Blikgooien (tafels)
Eendjes vangen (tafels)
Ringwerpen (tafels)
Roodkapje (splitsen)
Hans en Grietje (plus en min)
Zeven kleine geitjes (plus via de 10)
Verliefde harten
Ruimtemissie (automatiseren)
Locomotief (automatiseren)
contact
Zoeken
Klokkijken werkblad maken
Maak een werkblad met analoge en digitale tijden, precies zoals jij wilt oefenen.
Werkblad
Antwoordblad
Analoge klok omzetten · hele en halve uren · 12-uurs · 8 opdrachten
Werkblad wordt gemaakt
De preview verschijnt automatisch.
window.__KKCL_LOGO_DATA="data:image/png;base64,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"; (function(global){ 'use strict'; const TIMEKINDS={ whole:{id:'whole',label:'Hele uren',minutes:[0]}, half:{id:'half',label:'Halve uren',minutes:[30]}, quarter:{id:'quarter',label:'Kwartieren',minutes:[15,45]}, five:{id:'five',label:'5 minuten',minutes:[5,10,20,25,35,40,50,55]}, minute:{id:'minute',label:'1 minuut',minutes:Array.from({length:60},(_,i)=>i).filter(m=>m%5!==0)} }; const MODES={analog_convert:'Analoge klok omzetten',analog_read:'Analoge klok aflezen',digital_convert:'Digitale klok omzetten',draw_hands:'Wijzers tekenen',compare:'Vergelijken'}; const COUNTS=[6,8,10,12]; const HOUR_WORDS=['twaalf','één','twee','drie','vier','vijf','zes','zeven','acht','negen','tien','elf']; const NUMBER_WORDS={1:'één',2:'twee',3:'drie',4:'vier',5:'vijf',6:'zes',7:'zeven',8:'acht',9:'negen',10:'tien',11:'elf',12:'twaalf',13:'dertien',14:'veertien',15:'vijftien',16:'zestien',17:'zeventien',18:'achttien',19:'negentien',20:'twintig',21:'eenentwintig',22:'tweeëntwintig',23:'drieëntwintig',24:'vierentwintig',25:'vijfentwintig',26:'zesentwintig',27:'zevenentwintig',28:'achtentwintig',29:'negenentwintig'}; function hashSeed(seed){const s=String(seed==null?'':seed);let h=2166136261>>>0;for(let i=0;i<s.length;i++){h^=s.charCodeAt(i);h=Math.imul(h,16777619)>>>0;}return h||0x9e3779b9} function createRng(seed){let a=hashSeed(seed);return function(){a|=0;a=(a+0x6D2B79F5)|0;let t=Math.imul(a^(a>>>15),1|a);t=(t+Math.imul(t^(t>>>7),61|t))^t;return ((t^(t>>>14))>>>0)/4294967296}} function randInt(rng,max){return Math.floor(rng()*max)} function shuffle(arr,rng){const a=arr.slice();for(let i=a.length-1;i>0;i--){const j=randInt(rng,i+1);[a[i],a[j]]=[a[j],a[i]];}return a} function pad2(n){return String(n).padStart(2,'0')} function partsFromTotal(total){let n=Math.round(Number(total));n%=1440;if(n<0)n+=1440;return {hour24:Math.floor(n/60),minute:n%60}} function hour12From24(h){const v=h%12;return v===0?12:v} function formatTime(total,notation){const p=partsFromTotal(total);return notation==='24'?pad2(p.hour24)+':'+pad2(p.minute):String(hour12From24(p.hour24))+':'+pad2(p.minute)} function hourWord(h){return HOUR_WORDS[(h%12+12)%12]} function numberWord(n){return NUMBER_WORDS[n]||String(n)} function formatTimeWords(total){const p=partsFromTotal(total),h=p.hour24%12,m=p.minute,next=(h+1)%12;if(m===0)return hourWord(h)+' uur';if(m<15)return numberWord(m)+' over '+hourWord(h);if(m===15)return 'kwart over '+hourWord(h);if(m<30)return numberWord(30-m)+' voor half '+hourWord(next);if(m===30)return 'half '+hourWord(next);if(m<45)return numberWord(m-30)+' over half '+hourWord(next);if(m===45)return 'kwart voor '+hourWord(next);return numberWord(60-m)+' voor '+hourWord(next)} function daypartForHour(h){if(h<6)return "'s nachts";if(h<12)return "'s ochtends";if(h<18)return "'s middags";return "'s avonds"} function analogGeometry(total){const p=partsFromTotal(total),h=p.hour24%12;return {minuteAngle:p.minute*6,hourAngle:h*30+p.minute*.5}} function normalizeAngle(a){let n=Number(a)%360;if(n<0)n+=360;return n} function angleClose(a,b,tol=.000001){let d=Math.abs(normalizeAngle(a)-normalizeAngle(b));d=Math.min(d,360-d);return d<=tol} function normalizeKinds(kinds){const arr=Array.isArray(kinds)?kinds.filter(k=>TIMEKINDS[k]):[];return arr.length?Array.from(new Set(arr)):['whole','half']} function normalizeConfig(config){const c=config||{};return {mode:MODES[c.mode]?c.mode:'analog_convert',timeKinds:normalizeKinds(c.timeKinds),notation:c.notation==='24'?'24':'12',count:COUNTS.includes(Number(c.count))?Number(c.count):8}} function usesDigitalNotation(mode){return mode==='analog_convert'||mode==='digital_convert'||mode==='compare'} function generationNotation(config){return usesDigitalNotation(config.mode)?config.notation:'12'} function minuteAllowed(minute,kinds){return kinds.some(k=>TIMEKINDS[k].minutes.includes(minute))} function categoryForMinute(minute){for(const k of Object.keys(TIMEKINDS))if(TIMEKINDS[k].minutes.includes(minute))return k;return null} function poolForKind(kind,notation){const hours=notation==='24'?24:12,out=[];for(let h=0;h<hours;h++)for(const m of TIMEKINDS[kind].minutes)out.push(h*60+m);return out} function allPool(config){const notation=generationNotation(config);let out=[];for(const k of config.timeKinds)out=out.concat(poolForKind(k,notation));return out} function balancedKindSchedule(kinds,count,rng){const shuffled=shuffle(kinds,rng),out=[];for(let i=0;i<count;i++)out.push(shuffled[i%shuffled.length]);return shuffle(out,rng)} function timeObj(total,notation,needDaypart){const p=partsFromTotal(total),g=analogGeometry(total);return {totalMinutes:total,hour24:p.hour24,minute:p.minute,label:formatTime(total,notation),words:formatTimeWords(total),daypart:needDaypart?daypartForHour(p.hour24):'',geometry:g}} function keyFor(total,notation){return notation==='24'?total:total%720} function generateBalancedTimes(config,count,rng){let best=null;const notation=generationNotation(config);for(let attempt=0;attempt<30;attempt++){ const schedule=balancedKindSchedule(config.timeKinds,count,rng),used=new Set(),vals=[];let ok=true; for(const kind of schedule){const pool=shuffle(poolForKind(kind,notation),rng);let chosen=null;for(const v of pool){const key=keyFor(v,notation);if(!used.has(key)){chosen=v;break}}if(chosen===null){ok=false;break}used.add(keyFor(chosen,notation));vals.push(chosen)} if(!ok)continue;const hours=new Set(vals.map(v=>partsFromTotal(v).hour24%(notation==='24'?24:12)));let score=hours.size*8;for(let i=1;i<vals.length;i++){if(partsFromTotal(vals[i]).minute===partsFromTotal(vals[i-1]).minute)score-=3;if(partsFromTotal(vals[i]).hour24===partsFromTotal(vals[i-1]).hour24)score-=2}if(!best||score>best.score)best={vals,score}; } if(!best)throw new Error('TIME_POOL_EXHAUSTED');return best.vals; } function makeAnalogConvert(total,config,id){const t=timeObj(total,config.notation,config.notation==='24');return {id,type:'analog_convert',...t,answer:t.label}} function makeAnalogRead(total,config,id){const t=timeObj(total,'12',false);return {id,type:'analog_read',...t,answer:t.words}} function makeDigitalConvert(total,config,id){const t=timeObj(total,config.notation,false);return {id,type:'digital_convert',...t,prompt:t.label,answer:t.label}} function makeDrawHands(total,config,id){const t=timeObj(total,'12',false);return {id,type:'draw_hands',...t,prompt:t.words,answer:t.words}} function generateSimple(config,rng,type){const vals=generateBalancedTimes(config,config.count,rng);return vals.map((v,i)=>type==='analog_convert'?makeAnalogConvert(v,config,i+1):type==='analog_read'?makeAnalogRead(v,config,i+1):type==='digital_convert'?makeDigitalConvert(v,config,i+1):makeDrawHands(v,config,i+1))} function compareValue(total,notation){return notation==='24'?total:total%720} function operatorFor(a,b,notation){const av=compareValue(a,notation),bv=compareValue(b,notation);return av===bv?'=':(av<bv?'<':'>')} function compareOpSchedule(count,rng){let eq=Math.max(1,Math.round(count*.2));let rest=count-eq,lt=Math.floor(rest/2),gt=rest-lt;const ops=[];while(eq--)ops.push('=');while(lt--)ops.push('<');while(gt--)ops.push('>');return shuffle(ops,rng)} function pickDifferent(pool,left,op,notation,rng){const lv=compareValue(left,notation);const eligible=pool.filter(v=>{const vv=compareValue(v,notation);return op==='<'?lv<vv:lv>vv});if(!eligible.length)return null;return eligible[randInt(rng,eligible.length)]} function generateCompare(config,rng){const allowed=allPool(config),ops=compareOpSchedule(config.count,rng),tasks=[],seenPairs=new Set();for(let i=0;i<config.count;i++){ let made=null;for(let a=0;a<100&&!made;a++){const left=allowed[randInt(rng,allowed.length)],op=ops[i],right=op==='='?left:pickDifferent(allowed,left,op,config.notation,rng);if(right===null)continue;const k=keyFor(left,config.notation)+'|'+keyFor(right,config.notation)+'|'+op;if(seenPairs.has(k))continue;seenPairs.add(k);made={id:i+1,type:'compare',left:{display:'digital',...timeObj(left,config.notation,false)},right:{display:'analog',...timeObj(right,config.notation,config.notation==='24')},operator:operatorFor(left,right,config.notation)}} if(!made)throw new Error('COMPARE_BUILD_FAILED');tasks.push(made) }return tasks} function generateWorksheet(config,seed){const c=normalizeConfig(config),base=String(seed==null?'clock':seed);for(let attempt=0;attempt<40;attempt++){ const rng=createRng(base+':'+attempt);let tasks=[];if(c.mode==='compare')tasks=generateCompare(c,rng);else tasks=generateSimple(c,rng,c.mode);const result={version:4,seed:base,config:c,tasks};const verdict=validateWorksheet(result);if(verdict.ok)return result }throw new Error('CLOCK_VALIDATION_FAILED')} function validateCoreTime(t,config,notation,needsDaypart,pre,errors){if(!t||!Number.isInteger(t.totalMinutes)||t.totalMinutes<0||t.totalMinutes>=1440){errors.push(pre+'_TIME');return}const p=partsFromTotal(t.totalMinutes);if(t.hour24!==p.hour24||t.minute!==p.minute)errors.push(pre+'_PARTS');if(!minuteAllowed(t.minute,config.timeKinds))errors.push(pre+'_TIMEKIND');if(t.label!==formatTime(t.totalMinutes,notation))errors.push(pre+'_LABEL');if(t.words!==formatTimeWords(t.totalMinutes))errors.push(pre+'_WORDS');const g=analogGeometry(t.totalMinutes);if(!t.geometry||!angleClose(t.geometry.minuteAngle,g.minuteAngle)||!angleClose(t.geometry.hourAngle,g.hourAngle))errors.push(pre+'_GEOMETRY');if(needsDaypart&¬ation==='24'&&t.daypart!==daypartForHour(t.hour24))errors.push(pre+'_DAYPART');if((!needsDaypart||notation==='12')&&t.daypart)errors.push(pre+'_EXTRA_DAYPART')} function validateWorksheet(result){const errors=[];if(!result||typeof result!=='object')return {ok:false,errors:['RESULT_MISSING']};const c=normalizeConfig(result.config||{}),tasks=Array.isArray(result.tasks)?result.tasks:[];if(tasks.length!==c.count)errors.push('COUNT');if(!c.timeKinds.length)errors.push('NO_TIMEKINDS');const seen=new Set(),uniqueNotation=generationNotation(c); tasks.forEach((t,i)=>{const pre='TASK_'+i;if(!t||t.id!==i+1){errors.push(pre+'_ID');return} if(c.mode==='compare'){ if(t.type!=='compare'){errors.push(pre+'_TYPE');return}if(!t.left||t.left.display!=='digital'||!t.right||t.right.display!=='analog')errors.push(pre+'_DISPLAY_ORDER');validateCoreTime(t.left,c,c.notation,false,pre+'_L',errors);validateCoreTime(t.right,c,c.notation,true,pre+'_R',errors);const op=operatorFor(t.left.totalMinutes,t.right.totalMinutes,c.notation);if(t.operator!==op)errors.push(pre+'_OP');return; } if(t.type!==c.mode){errors.push(pre+'_TYPE');return}const notation=(c.mode==='analog_read'||c.mode==='draw_hands')?'12':c.notation;const needsDaypart=c.mode==='analog_convert';validateCoreTime(t,c,notation,needsDaypart,pre,errors);const key=keyFor(t.totalMinutes,uniqueNotation);if(seen.has(key))errors.push(pre+'_DUP');seen.add(key); if(c.mode==='analog_convert'&&t.answer!==formatTime(t.totalMinutes,c.notation))errors.push(pre+'_ANSWER'); if(c.mode==='analog_read'&&t.answer!==formatTimeWords(t.totalMinutes))errors.push(pre+'_ANSWER'); if(c.mode==='digital_convert'&&(t.prompt!==formatTime(t.totalMinutes,c.notation)||t.answer!==t.prompt))errors.push(pre+'_PROMPT'); if(c.mode==='draw_hands'&&(t.prompt!==formatTimeWords(t.totalMinutes)||t.answer!==t.prompt))errors.push(pre+'_PROMPT'); }); if(c.mode==='compare'&&c.count>=6){const ops=tasks.map(t=>t.operator);if(!ops.includes('<')||!ops.includes('>')||!ops.includes('='))errors.push('COMPARE_BALANCE')} return {ok:errors.length===0,errors}} function makeSeed(){return Date.now().toString(36)+'-'+Math.random().toString(36).slice(2,10)} function instructionFor(c){if(c.mode==='analog_convert')return 'Zet de analoge klok om naar digitale tijd.';if(c.mode==='analog_read')return 'Lees de analoge klok af en schrijf de tijd in woorden.';if(c.mode==='digital_convert')return 'Zet de digitale tijd om naar een analoge klok.';if(c.mode==='draw_hands')return 'Lees de tijd in woorden en teken de uurwijzer en minuutwijzer.';return 'Vergelijk de digitale tijd links met de analoge klok rechts en schrijf <, > of = in het vak.'} function kindsLabel(kinds){const labels=kinds.map(k=>TIMEKINDS[k].label.toLowerCase());if(labels.length===1)return labels[0];if(labels.length===2)return labels[0]+' en '+labels[1];return labels.slice(0,-1).join(', ')+' en '+labels[labels.length-1]} global.KKCLClockEngineV4={TIMEKINDS,MODES,normalizeConfig,formatTime,formatTimeWords,daypartForHour,analogGeometry,generateWorksheet,validateWorksheet,makeSeed,instructionFor,kindsLabel,categoryForMinute,minuteAllowed,operatorFor,usesDigitalNotation}; })(typeof window!=='undefined'?window:globalThis); (function(){ 'use strict'; const root=document.getElementById('kkcl-clock-root');if(!root||root.dataset.kkclInitialized==='1')return;root.dataset.kkclInitialized='1'; const E=window.KKCLClockEngineV4,LOGO_DATA=window.__KKCL_LOGO_DATA||''; const q=s=>root.querySelector(s),qa=s=>Array.from(root.querySelectorAll(s)); const els={title:q('#kkcl-titleInput'),notationSection:q('#kkcl-notationSection'),showName:q('#kkcl-showName'),showGroup:q('#kkcl-showGroup'),showDate:q('#kkcl-showDate'),includeSolution:q('#kkcl-includeSolution'),status:q('#kkcl-statusBox'),newBtn:q('#kkcl-newVersionBtn'),print:q('#kkcl-printBtn'),stage:q('#kkcl-sheetStage'),meta:q('#kkcl-previewMeta')}; const state={mode:'analog_convert',timeKinds:new Set(['whole','half']),notation:'12',count:8,seed:E.makeSeed(),result:null,generating:false,activeTab:'student'}; function esc(s){return String(s==null?'':s).replace(/[&<>"']/g,m=>({'&':'&','<':'<','>':'>','"':'"',"'":'''}[m]))} function config(){return {mode:state.mode,timeKinds:Array.from(state.timeKinds),notation:state.notation,count:state.count}} function selectSingle(selector,key,value){qa(selector).forEach(b=>b.classList.toggle('active',String(b.dataset[key])===String(value)))} function setStatus(type,title,text){els.status.className='status '+type;els.status.innerHTML='<strong>'+esc(title)+'</strong><span>'+esc(text)+'</span>'} function syncConditional(){if(els.notationSection)els.notationSection.hidden=!E.usesDigitalNotation(state.mode)} function updateMeta(){const c=config(),parts=[E.MODES[c.mode],E.kindsLabel(c.timeKinds)];if(E.usesDigitalNotation(c.mode))parts.push(c.notation+'-uurs');parts.push(c.count+' opdrachten');els.meta.textContent=parts.join(' · ')} function regenerate(){state.seed=E.makeSeed();syncConditional();updateMeta();generate()} function generate(){if(state.generating)return;state.generating=true;els.newBtn.disabled=true;els.print.disabled=true;setStatus('info','Werkblad wordt gemaakt','De tijden, wijzerstanden en antwoorden worden gecontroleerd.');setTimeout(()=>{try{const result=E.generateWorksheet(config(),state.seed),v=E.validateWorksheet(result);if(!v.ok)throw new Error(v.errors.join(','));state.result=result;setStatus('success','Werkblad gecontroleerd','Alle '+result.tasks.length+' opdrachten en antwoorden zijn gecontroleerd.');els.newBtn.disabled=false;els.print.disabled=false;renderPreview()}catch(err){state.result=null;setStatus('error','Werkblad kon niet worden gemaakt','Probeer een nieuwe versie.');els.stage.innerHTML='<div class="empty-preview"><div><strong>Geen werkblad</strong>Er ging iets mis tijdens de controle.</div></div>';if(console&&console.error)console.error('Klasklaar klokkijken:',err)}finally{state.generating=false}},0)} function studentFields(){const out=[];if(els.showName.checked)out.push(field('Naam',55));if(els.showGroup.checked)out.push(field('Groep',35));if(els.showDate.checked)out.push(field('Datum',38));return out.join('')} function field(label,w){return '<div class="kkcl-print-student-field"><span class="kkcl-print-student-label">'+esc(label)+'</span><span class="kkcl-print-student-line" style="width:'+w+'mm"></span></div>'} function point(cx,cy,r,deg){const a=(deg-90)*Math.PI/180;return [cx+Math.cos(a)*r,cy+Math.sin(a)*r]} function clockSvg(task,showHands,compare){let ticks='';for(let i=0;i<60;i++){const major=i%5===0,deg=i*6,r1=major?39:41.5,r2=44;const a=point(50,50,r1,deg),b=point(50,50,r2,deg);ticks+='<line x1="'+a[0].toFixed(2)+'" y1="'+a[1].toFixed(2)+'" x2="'+b[0].toFixed(2)+'" y2="'+b[1].toFixed(2)+'" stroke="#222" stroke-width="'+(major?'1.15':'.55')+'" />'}let nums='';for(let n=1;n<=12;n++){const p=point(50,50,33,n*30);nums+='<text x="'+p[0].toFixed(2)+'" y="'+(p[1]+2.7).toFixed(2)+'" text-anchor="middle" font-family="Arial,Helvetica,sans-serif" font-size="7.2" font-weight="700" fill="#111">'+n+'</text>'}let hands='';if(showHands){const mh=point(50,50,30,task.geometry.minuteAngle),hh=point(50,50,21,task.geometry.hourAngle);hands='<line x1="50" y1="50" x2="'+hh[0].toFixed(2)+'" y2="'+hh[1].toFixed(2)+'" stroke="#111" stroke-width="3.1" stroke-linecap="round"/><line x1="50" y1="50" x2="'+mh[0].toFixed(2)+'" y2="'+mh[1].toFixed(2)+'" stroke="#111" stroke-width="1.8" stroke-linecap="round"/><circle cx="50" cy="50" r="2.2" fill="#111"/>'}else hands='<circle cx="50" cy="50" r="1.9" fill="#111"/>'; return '<svg class="kkcl-clock-svg'+(compare?' kkcl-compare-clock':'')+'" viewBox="0 0 100 100" role="img" aria-label="Analoge klok"><circle cx="50" cy="50" r="47" fill="#fff" stroke="#111" stroke-width="1.7"/>'+ticks+nums+hands+'</svg>'} function analogSide(task,showHands,compare){return '<div class="kkcl-task-side">'+(task.daypart?'<div class="kkcl-daypart">'+esc(task.daypart)+'</div>':'')+clockSvg(task,showHands,compare)+'</div>'} function digitalSide(task){return '<div class="kkcl-task-side"><div class="kkcl-digital-box">'+esc(task.label||task.prompt)+'</div></div>'} function wordSide(task){return '<div class="kkcl-task-side"><div class="kkcl-word-box">'+esc(task.prompt||task.words)+'</div></div>'} function analogConvertTaskHtml(t,solution){return '<div class="kkcl-horizontal-task"><span class="kkcl-task-number">'+t.id+'.</span>'+analogSide(t,true,false)+'<div class="kkcl-task-side"><div class="kkcl-answer-box'+(solution?'':' blank')+'">'+(solution?esc(t.answer):'__ : __')+'</div></div></div>'} function analogReadTaskHtml(t,solution){const studentSentence=t.minute===0?'Het is op de klok: <span class="kkcl-writing-line"></span> uur.':'Het is op de klok: <span class="kkcl-writing-line"></span>.';const answerSentence='Het is op de klok: <strong>'+esc(t.answer)+'</strong>.';return '<div class="kkcl-analog-read-task"><span class="kkcl-task-number">'+t.id+'.</span>'+analogSide(t,true,false)+'<div class="kkcl-time-sentence">'+(solution?answerSentence:studentSentence)+'</div></div>'} function digitalConvertTaskHtml(t,solution){return '<div class="kkcl-horizontal-task"><span class="kkcl-task-number">'+t.id+'.</span>'+digitalSide(t)+analogSide(t,solution,false)+'</div>'} function drawHandsTaskHtml(t,solution){return '<div class="kkcl-horizontal-task"><span class="kkcl-task-number">'+t.id+'.</span>'+wordSide(t)+analogSide(t,solution,false)+'</div>'} function compareTaskHtml(t,solution){return '<div class="kkcl-compare-task"><span class="kkcl-task-number">'+t.id+'.</span><div class="kkcl-compare-side"><div class="kkcl-digital-box">'+esc(t.left.label)+'</div></div><div class="kkcl-compare-center">'+(solution?'<div class="kkcl-compare-solution">'+esc(t.operator)+'</div>':'<div class="kkcl-compare-blank"></div>')+'</div><div class="kkcl-compare-side">'+(t.right.daypart?'<div class="kkcl-daypart">'+esc(t.right.daypart)+'</div>':'')+clockSvg(t.right,true,true)+'</div></div>'} function taskHtml(t,solution){if(t.type==='analog_convert')return analogConvertTaskHtml(t,solution);if(t.type==='analog_read')return analogReadTaskHtml(t,solution);if(t.type==='digital_convert')return digitalConvertTaskHtml(t,solution);return drawHandsTaskHtml(t,solution)} function bodyHtml(solution){const c=state.result.config;if(c.mode==='compare')return '<div class="kkcl-compare-grid" style="--kkcl-compare-rows:'+c.count+'">'+state.result.tasks.map(t=>compareTaskHtml(t,solution)).join('')+'</div>';return '<div class="kkcl-task-grid" style="--kkcl-rows:'+Math.ceil(c.count/2)+'">'+state.result.tasks.map(t=>taskHtml(t,solution)).join('')+'</div>'} function sheetHtml(solution){if(!state.result)return '';const title=(els.title.value||'Klokkijken').trim()||'Klokkijken',c=state.result.config,solutionTitle=solution?title+' - antwoorden':title;return '<section class="kkcl-print-page kkcl-count-'+c.count+' kkcl-mode-'+c.mode+'" data-sheet="'+(solution?'solution':'student')+'"><div class="kkcl-print-content"><header class="kkcl-print-header"><div class="kkcl-print-heading"><div class="kkcl-print-kicker">KLOKKIJKEN</div><h1 class="kkcl-print-title">'+esc(solutionTitle)+'</h1></div><div class="kkcl-print-logo-box"><img class="kkcl-print-logo" src="'+LOGO_DATA+'" alt="Klasklaar"></div></header><div class="kkcl-print-student-row">'+(solution?'':studentFields())+'</div><p class="kkcl-print-instruction">'+esc(solution?'Antwoorden bij dit werkblad.':E.instructionFor(c))+'</p>'+bodyHtml(solution)+'<footer class="kkcl-print-footer">Klasklaar.nl</footer></div></section>'} function renderPreview(){if(!state.result)return;if(state.activeTab==='solution'&&!els.includeSolution.checked)state.activeTab='student';qa('.tab').forEach(t=>t.classList.toggle('active',t.dataset.tab===state.activeTab));const st=q('.tab[data-tab="solution"]');if(st)st.style.display=els.includeSolution.checked?'':'none';els.stage.innerHTML='<div class="kkcl-preview-page-wrap kkcl-doc" id="kkcl-previewPageWrap">'+sheetHtml(state.activeTab==='solution')+'</div>';requestAnimationFrame(fitSheet)} function fitSheet(){const wrap=q('#kkcl-previewPageWrap');if(!wrap)return;const page=wrap.querySelector('.kkcl-print-page');if(!page)return;wrap.style.transform='none';const stageW=els.stage.clientWidth,baseW=page.getBoundingClientRect().width;if(!stageW||!baseW)return;const scale=Math.min(1.42,Math.max(.25,(stageW-8)/baseW));wrap.style.transform='scale('+scale+')';wrap.style.left=Math.max(0,(stageW-baseW*scale)/2)+'px';wrap.style.top='0px';els.stage.style.height=Math.ceil(page.getBoundingClientRect().height*scale+8)+'px'} function scheduleRender(){if(state.result)renderPreview()} qa('.choice[data-mode]').forEach(b=>b.addEventListener('click',()=>{const v=b.dataset.mode;if(v===state.mode)return;state.mode=v;selectSingle('.choice[data-mode]','mode',v);regenerate()})); qa('.choice[data-timekind]').forEach(b=>b.addEventListener('click',()=>{const k=b.dataset.timekind;if(state.timeKinds.has(k)){if(state.timeKinds.size===1){setStatus('info','Kies minimaal één soort tijd','Er moet altijd minimaal één tijdsoort actief blijven.');return}state.timeKinds.delete(k);b.classList.remove('active')}else{state.timeKinds.add(k);b.classList.add('active')}regenerate()})); qa('.choice[data-notation]').forEach(b=>b.addEventListener('click',()=>{const v=b.dataset.notation;if(v===state.notation)return;state.notation=v;selectSingle('.choice[data-notation]','notation',v);regenerate()})); qa('.choice[data-count]').forEach(b=>b.addEventListener('click',()=>{const v=Number(b.dataset.count);if(v===state.count)return;state.count=v;selectSingle('.choice[data-count]','count',v);regenerate()})); els.title.addEventListener('input',scheduleRender);[els.showName,els.showGroup,els.showDate].forEach(x=>x.addEventListener('change',scheduleRender));els.includeSolution.addEventListener('change',()=>{if(!els.includeSolution.checked&&state.activeTab==='solution')state.activeTab='student';scheduleRender()});els.newBtn.addEventListener('click',regenerate);qa('.tab').forEach(t=>t.addEventListener('click',()=>{if(t.dataset.tab==='solution'&&!els.includeSolution.checked)return;state.activeTab=t.dataset.tab;renderPreview()}));window.addEventListener('resize',()=>requestAnimationFrame(fitSheet)); function printWorksheet(){if(!state.result||state.generating)return;const pages=[sheetHtml(false)];if(els.includeSolution.checked)pages.push(sheetHtml(true));const printLayer=document.createElement('div');printLayer.id='kkcl-print-sandbox';printLayer.className='kkcl-doc';printLayer.innerHTML=pages.join('');const sourceStyle=document.getElementById('kkcl-clock-style'),tempStyle=document.createElement('style');tempStyle.id='kkcl-print-temp-style';tempStyle.textContent=(sourceStyle?sourceStyle.textContent:'')+'\n@page{size:A4 portrait;margin:0}html,body{margin:0!important;padding:0!important;background:#fff!important;width:210mm!important;min-width:210mm!important;max-width:210mm!important}#kkcl-print-sandbox{display:block!important;margin:0!important;padding:0!important;width:210mm!important;min-width:210mm!important;max-width:210mm!important;background:#fff!important}#kkcl-print-sandbox .kkcl-print-page{display:block!important;width:210mm!important;min-width:210mm!important;max-width:210mm!important;height:297mm!important;min-height:297mm!important;max-height:297mm!important;margin:0!important;box-shadow:none!important;overflow:hidden!important;break-after:page;page-break-after:always}#kkcl-print-sandbox .kkcl-print-page:last-child{break-after:auto;page-break-after:auto}';document.head.appendChild(tempStyle);const body=document.body,oldClass=body.className,oldStyle=body.getAttribute('style'),oldTitle=document.title,stash=document.createDocumentFragment();Array.from(body.childNodes).forEach(node=>stash.appendChild(node));body.className='kkcl-print-isolated';body.removeAttribute('style');document.title='';body.appendChild(printLayer);let cleaned=false;const cleanup=()=>{if(cleaned)return;cleaned=true;try{printLayer.remove()}catch(_e){}while(body.firstChild)body.removeChild(body.firstChild);body.appendChild(stash);body.className=oldClass;document.title=oldTitle;if(oldStyle===null)body.removeAttribute('style');else body.setAttribute('style',oldStyle);tempStyle.remove();requestAnimationFrame(fitSheet)};window.addEventListener('afterprint',cleanup,{once:true});setTimeout(()=>{try{window.print()}catch(err){if(console&&console.error)console.error('Klasklaar klokkijken print:',err)}finally{setTimeout(cleanup,0)}},80)} els.print.addEventListener('click',printWorksheet);selectSingle('.choice[data-mode]','mode',state.mode);selectSingle('.choice[data-notation]','notation',state.notation);selectSingle('.choice[data-count]','count',state.count);syncConditional();updateMeta();generate(); })();
${body}
${SITE_TEXT}
${rows}