summaryrefslogblamecommitdiff
path: root/blog/data/poll.js
blob: 55b4e22bcaa5697cfc4ed688494b8e152075e77a (plain) (tree)










































































































































































                                                                                                 
//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();