diff options
Diffstat (limited to 'blog/data/poll.js')
-rw-r--r-- | blog/data/poll.js | 171 |
1 files changed, 171 insertions, 0 deletions
diff --git a/blog/data/poll.js b/blog/data/poll.js new file mode 100644 index 0000000..55b4e22 --- /dev/null +++ b/blog/data/poll.js @@ -0,0 +1,171 @@ +//By Chris Xiong, 2018 +//License: Expat +let p=null; +let Caption; +let Choices; +let Score; +let Next; +let values=[]; +let curq; +function evalexpr(e) +{ + let ret=0; + let op=function(a,o,b){ + switch(o){ + case '+':return a+b; + case '-':return a-b; + case '*':return a*b; + case '/':return a/b; + } + }; + for(let p=e.match(/[+\-*\/]/);p;p=e.match(/[+\-*\/]/)) + { + let vp=e.match(/[A-Za-z]\w*/); + if(vp) + { + const v=vp[0]; + if(values[v]===undefined)throw 'shit'; + ret=op(ret,p[0],values[v]); + e=e.substr(vp.index+vp[0].length); + } + else + { + let np=e.match(/\d+(.\d*)?/); + if(np) + { + const n=Number(np[0]); + ret=op(ret,p[0],n); + e=e.substr(np.index+np[0].length); + }else throw 'shit'; + } + } + return ret; +} +function evalsetexpr(e) +{ + const s=e.split('='); + if(s.length<2)throw 'shit'; + values[s[0].trim()]=evalexpr(s[1]); +} +function evaltestexpr(e) +{ + const m=e.match(/([A-Za-z]\w*)\s*(leq|geq|lt|gt)\s*([A-Za-z0-9.]*)/); + if(!m)throw 'shit'; + const v=m[1],op=m[2],vr=m[3]; + const vv=values[v]; + const vvr=isNaN(Number(vr))?values[vr]:Number(vr); + if(vv===undefined||vvr===undefined)throw 'shit'; + switch(op.trim()) + { + case 'leq':return vv<=vvr; + case 'geq':return vv>=vvr; + case 'lt':return vv<vvr; + case 'gt':return vv>vvr; + } + throw 'shit'; +} +function evalcondexpr(e) +{ + if(!e.trim().length)return true; + let ret=false; + let op=function(a,o,b){ + switch(o){ + case '|':return a||b; + case '&':return a&&b; + } + }; + for(let p=e.search(/[|&]/);p!=-1;p=e.search(/[|&]/)) + { + let np=e.substr(p+1).search(/[|&]/); + let n=e.substr(p+1,np!=-1?np-1:undefined); + ret=op(ret,e[p],evaltestexpr(n.trim())); + e=np?e.substr(np):""; + } + return ret; +} +function initq() +{ + const q=p.question[curq]; + for(let i=0;i<q.initialization.length;++i) + { + if(evalcondexpr(q.initialization[i].c)) + evalsetexpr(q.initialization[i].s); + } + if(!evalcondexpr(q.precond)){++curq;if(curq<p.question.length)initq();else finalize();} +} +function evalq() +{ + if(curq>=p.question.length)return; + const q=p.question[curq]; + let seln=0; + for(let i=0;i<q.choice.length;++i) + { + const e=document.getElementById(`choice${i}`); + if(e.checked)++seln; + if(e.checked) + { + for(let j=0;j<q.choice[i].setp.length;++j) + if(evalcondexpr(q.choice[i].setp[j].c)) + evalsetexpr(q.choice[i].setp[j].s); + } + else + { + for(let j=0;j<q.choice[i].setn.length;++j) + if(evalcondexpr(q.choice[i].setn[j].c)) + evalsetexpr(q.choice[i].setn[j].s); + } + } + if(!seln&&q.type=='single'){alert('Wanna cheat?...');return;} + ++curq; + if(curq==p.question.length)finalize();else{showq();initq();} +} +function showq() +{ + const q=p.question[curq]; + Caption.innerHTML=q.caption; + while(Choices.firstChild)Choices.removeChild(Choices.firstChild); + for(let i=0;i<q.choice.length;++i) + { + const d=document.createElement('div'); + const e=document.createElement('input'); + e.type=q.type=='multi'?'checkbox':'radio'; + e.innerHTML=q.choice[i].caption; + e.qid=i;e.id=`choice${i}`; + e.setAttribute('name','choice'); + e.classList.add('check'); + const l=document.createElement('label'); + l.innerHTML=q.choice[i].caption; + l.setAttribute('for',e.id); + d.appendChild(e); + d.appendChild(l); + Choices.appendChild(d); + } + Score.innerHTML=`${values['score']}, Question ${curq+1}/${p.question.length}`; +} +function _init() +{ + Caption=document.getElementById('qcaption'); + Choices=document.getElementById('qchoices'); + Score=document.getElementById('score'); + Next=document.getElementById('nextbtn'); + curq=0;values['score']=0; + initq();showq(); +} +async function init() +{ + const resp=await fetch(new Request('/blog/data/applefan.json')); + r=await resp.text(); + p=JSON.parse(r); + _init(); +} +function finalize() +{ + Next.style.color='#888'; + Score.innerHTML=`${values['score']}, Question ${p.question.length}/${p.question.length}`; + Caption.innerHTML=''; + Choices.innerHTML=''; + for(let i=0;i<p.verdict.length;++i) + if(evalcondexpr(p.verdict[i].precond)) + Caption.innerHTML+=p.verdict[i].caption; +} +init(); |