From 77127eb20be06ef9c3ee7021fbbb498188e31278 Mon Sep 17 00:00:00 2001 From: Andreas Schwenk Date: Fri, 15 Mar 2024 17:08:27 +0100 Subject: [PATCH] version 1.2.2 - bug fix: filled matrix elements vanished after resizing the matrix - minor bug fixes --- CHANGELOG | 5 + docs/ex1.html | 4 +- sell.py | 939 ++++++++++++++++++++++++----------------------- web/src/eval.js | 2 +- web/src/input.js | 40 +- web/src/math.js | 4 +- 6 files changed, 510 insertions(+), 484 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 09d4ff2..58b25c7 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,8 @@ +# v1.2.2 + +- bug fix: filled matrix elements vanished after resizing the matrix +- minor bug fixes + # v1.2.1 - feedback for unfilled input fields diff --git a/docs/ex1.html b/docs/ex1.html index 122676a..938c30f 100644 --- a/docs/ex1.html +++ b/docs/ex1.html @@ -1,4 +1,4 @@ - pySELL Quiz

DEBUG VERSION

This quiz was created using pySELL, the Python-based Simple E-Learning Language, written by Andreas Schwenk, GPLv3
last update on

DEBUG VERSION

This quiz was created using pySELL, the Python-based Simple E-Learning Language, written by Andreas Schwenk, GPLv3
last update on

\ No newline at end of file + `.includes(s)==!1&&(this.token+=s),this.pos++}}isNum(e){return e.charCodeAt(0)>=48&&e.charCodeAt(0)<=57}isAlpha(e){return e.charCodeAt(0)>=65&&e.charCodeAt(0)<=90||e.charCodeAt(0)>=97&&e.charCodeAt(0)<=122||e==="_"}toString(){return this.root==null?"":this.root.toString()}toTexString(){return this.root==null?"":this.root.toTexString()}},m=class r{constructor(e,t,i=0,s=0){this.op=e,this.c=t,this.re=i,this.im=s,this.explicitParentheses=!1}clone(){let e=new r(this.op,this.c.map(t=>t.clone()),this.re,this.im);return e.explicitParentheses=this.explicitParentheses,e}static const(e=0,t=0){return new r("const",[],e,t)}compare(e,t=0,i=1e-9){let s=this.re-e,a=this.im-t;return Math.sqrt(s*s+a*a)1e-14,i=Math.abs(this.im)>1e-14;t&&i&&this.im>=0?e="("+this.re+"+"+this.im+"i)":t&&i&&this.im<0?e="("+this.re+"-"+-this.im+"i)":t&&this.re>0?e=""+this.re:t&&this.re<0?e="("+this.re+")":i?e="("+this.im+"i)":e="0"}else this.op.startsWith("var")?e=this.op.split(":")[1]:this.c.length==1?e=(this.op===".-"?"-":this.op)+"("+this.c.toString()+")":e="("+this.c.map(t=>t.toString()).join(this.op)+")";return e}toTexString(e=!1){let i="";switch(this.op){case"const":{let s=Math.abs(this.re)>1e-9,a=Math.abs(this.im)>1e-9,l=s?""+this.re:"",h=a?""+this.im+"i":"";h==="1i"?h="i":h==="-1i"&&(h="-i"),!s&&!a?i="0":(a&&this.im>=0&&s&&(h="+"+h),i=l+h);break}case".-":i="-"+this.c[0].toTexString();break;case"+":case"-":case"*":case"^":{let s=this.c[0].toTexString(),a=this.c[1].toTexString(),l=this.op==="*"?"\\cdot ":this.op;i="{"+s+"}"+l+"{"+a+"}";break}case"/":{let s=this.c[0].toTexString(!0),a=this.c[1].toTexString(!0);i="\\frac{"+s+"}{"+a+"}";break}case"sin":case"sinc":case"cos":case"tan":case"cot":case"exp":case"ln":{let s=this.c[0].toTexString(!0);i+="\\"+this.op+"\\left("+s+"\\right)";break}case"sqrt":{let s=this.c[0].toTexString(!0);i+="\\"+this.op+"{"+s+"}";break}case"abs":{let s=this.c[0].toTexString(!0);i+="\\left|"+s+"\\right|";break}default:if(this.op.startsWith("var:")){let s=this.op.substring(4);switch(s){case"pi":s="\\pi";break}i=" "+s+" "}else{let s="warning: Node.toString(..):";s+=" unimplemented operator '"+this.op+"'",console.log(s),i=this.op,this.c.length>0&&(i+="\\left({"+this.c.map(a=>a.toTexString(!0)).join(",")+"}\\right)")}}return!e&&this.explicitParentheses&&(i="\\left({"+i+"}\\right)"),i}};function ie(r,e){let t=1e-9;if(k.compare(r,e))return!0;r=r.clone(),e=e.clone(),N(r.root),N(e.root);let i=new Set;r.getVars(i),e.getVars(i);let s=[],a=[];for(let n of i.keys())n.startsWith("C")?s.push(n):a.push(n);let l=s.length;for(let n=0;n{r.feedbackPopupDiv.style.display="none"},500),r.state===x.passed?r.src.instances.length>0?r.checkAndRepeatBtn.innerHTML=te:r.checkAndRepeatBtn.style.display="none":r.checkAndRepeatBtn.innerHTML=I}var A=class{constructor(e,t,i,s){this.question=t,this.inputId=i,i.length==0&&(this.inputId=i="gap-"+t.gapIdx,t.types[this.inputId]="string",t.expected[this.inputId]=s,t.gapIdx++),i in t.student||(t.student[i]="");let a=s.split("|"),l=0;for(let c=0;cl&&(l=u.length)}let h=v("");e.appendChild(h);let n=Math.max(l*15,24),o=R(n);if(t.gapInputs[this.inputId]=o,o.addEventListener("keyup",()=>{this.question.editedQuestion(),o.value=o.value.toUpperCase(),this.question.student[this.inputId]=o.value.trim()}),h.appendChild(o),this.question.showSolution&&(this.question.student[this.inputId]=o.value=a[0],a.length>1)){let c=v("["+a.join("|")+"]");c.style.fontSize="small",c.style.textDecoration="underline",h.appendChild(c)}}},D=class{constructor(e,t,i,s,a,l,h=!1){i in t.student||(t.student[i]=""),this.question=t,this.inputId=i,this.outerSpan=v(""),this.outerSpan.style.position="relative",e.appendChild(this.outerSpan),this.inputElement=R(Math.max(s*12,48)),this.outerSpan.appendChild(this.inputElement),this.equationPreviewDiv=b(),this.equationPreviewDiv.classList.add("equationPreview"),this.equationPreviewDiv.style.display="none",this.outerSpan.appendChild(this.equationPreviewDiv),this.inputElement.addEventListener("click",()=>{this.question.editedQuestion(),this.edited()}),this.inputElement.addEventListener("keyup",()=>{this.question.editedQuestion(),this.edited()}),this.inputElement.addEventListener("focusout",()=>{this.equationPreviewDiv.innerHTML="",this.equationPreviewDiv.style.display="none"}),this.inputElement.addEventListener("keydown",n=>{let o="abcdefghijklmnopqrstuvwxyz";o+="ABCDEFGHIJKLMNOPQRSTUVWXYZ",o+="0123456789",o+="+-*/^(). <>=|",l&&(o="-0123456789"),n.key.length<3&&o.includes(n.key)==!1&&n.preventDefault();let c=this.inputElement.value.length*12;this.inputElement.offsetWidth0&&!i?"block":"none",this.question.student[this.inputId]=e}},V=class{constructor(e,t,i,s){this.parent=e,this.question=t,this.inputId=i,this.matExpected=new E(0,0),this.matExpected.fromString(s),this.matStudent=new E(this.matExpected.m==1?1:3,this.matExpected.n==1?1:3),t.showSolution&&this.matStudent.fromMatrix(this.matExpected),this.genMatrixDom(!0)}genMatrixDom(e){let t=b();this.parent.innerHTML="",this.parent.appendChild(t),t.style.position="relative",t.style.display="inline-block";let i=document.createElement("table");t.appendChild(i);let s=this.matExpected.getMaxCellStrlen();for(let d=0;d=10,this.matStudent.n<=1,this.matStudent.m>=10,this.matStudent.m<=1];for(let d=0;d<4;d++){if(u[d]==!1)continue;let f=v(a[d]);n[d]!=888&&(f.style.top=""+n[d]+"px"),o[d]!=888&&(f.style.bottom=""+o[d]+"px"),c[d]!=888&&(f.style.right=""+c[d]+"px"),f.classList.add("matrixResizeButton"),t.appendChild(f),p[d]?f.style.opacity="0.5":f.addEventListener("click",()=>{for(let g=0;g=5&&(this.feedbackSpan.innerHTML=""+this.numCorrect+" / "+this.numChecked);break}this.questionDiv.style.color=this.feedbackSpan.style.color=this.titleDiv.style.color=this.checkAndRepeatBtn.style.backgroundColor=this.questionDiv.style.borderColor=e,this.questionDiv.style.backgroundColor=t}populateDom(){if(this.parentDiv.innerHTML="",this.questionDiv=b(),this.parentDiv.appendChild(this.questionDiv),this.questionDiv.classList.add("question"),this.feedbackPopupDiv=b(),this.feedbackPopupDiv.classList.add("questionFeedback"),this.questionDiv.appendChild(this.feedbackPopupDiv),this.feedbackPopupDiv.innerHTML="awesome",this.debug&&"src_line"in this.src){let a=b();a.classList.add("debugInfo"),a.innerHTML="Source code: lines "+this.src.src_line+"..",this.questionDiv.appendChild(a)}if(this.titleDiv=b(),this.questionDiv.appendChild(this.titleDiv),this.titleDiv.classList.add("questionTitle"),this.titleDiv.innerHTML=this.src.title,this.src.error.length>0){let a=v(this.src.error);this.questionDiv.appendChild(a),a.style.color="red";return}let e=this.getCurrentInstance();if(e!=null&&"__svg_image"in e){let a=e.__svg_image.v,l=b();this.questionDiv.appendChild(l);let h=document.createElement("img");l.appendChild(h),h.classList.add("img"),h.src="data:image/svg+xml;base64,"+a}for(let a of this.src.text.c)this.questionDiv.appendChild(this.generateText(a));let t=b();this.questionDiv.appendChild(t),t.classList.add("buttonRow");let i=Object.keys(this.expected).length>0;i&&(this.checkAndRepeatBtn=j(),t.appendChild(this.checkAndRepeatBtn),this.checkAndRepeatBtn.innerHTML=I,this.checkAndRepeatBtn.style.backgroundColor="black");let s=v("   ");if(t.appendChild(s),this.feedbackSpan=v(""),t.appendChild(this.feedbackSpan),this.debug){if(this.src.variables.length>0){let h=b();h.classList.add("debugInfo"),h.innerHTML="Variables generated by Python Code",this.questionDiv.appendChild(h);let n=b();n.classList.add("debugCode"),this.questionDiv.appendChild(n);let o=this.getCurrentInstance(),c="",u=[...this.src.variables];u.sort();for(let p of u){let d=o[p].t,f=o[p].v;switch(d){case"vector":f="["+f+"]";break;case"set":f="{"+f+"}";break}c+=d+" "+p+" = "+f+"
"}n.innerHTML=c}let a=["python_src_html","text_src_html"],l=["Python Source Code","Text Source Code"];for(let h=0;h0){let o=b();o.classList.add("debugInfo"),o.innerHTML=l[h],this.questionDiv.appendChild(o);let c=b();c.classList.add("debugCode"),this.questionDiv.append(c),c.innerHTML=this.src[n]}}}i&&this.checkAndRepeatBtn.addEventListener("click",()=>{this.state==x.passed?(this.state=x.init,this.reset(),this.populateDom()):se(this)})}generateMathString(e){let t="";switch(e.t){case"math":case"display-math":for(let i of e.c){let s=this.generateMathString(i);i.t==="var"&&t.includes("!PM")&&(s.startsWith("{-")?(s="{"+s.substring(2),t=t.replaceAll("!PM","-")):t=t.replaceAll("!PM","+")),t+=s}break;case"text":return e.d;case"plus_minus":{t+=" !PM ";break}case"var":{let i=this.getCurrentInstance(),s=i[e.d].t,a=i[e.d].v;switch(s){case"vector":return"\\left["+a+"\\right]";case"set":return"\\left\\{"+a+"\\right\\}";case"complex":{let l=a.split(","),h=parseFloat(l[0]),n=parseFloat(l[1]);return m.const(h,n).toTexString()}case"matrix":{let l=new E(0,0);return l.fromString(a),t=l.toTeXString(e.d.includes("augmented"),this.language!="de"),t}case"term":{try{t=k.parse(a).toTexString()}catch{}break}default:t=a}}}return e.t==="plus_minus"?t:"{"+t+"}"}generateText(e,t=!1){switch(e.t){case"paragraph":case"span":{let i=document.createElement(e.t=="span"||t?"span":"p");for(let s of e.c)i.appendChild(this.generateText(s));return i}case"text":return v(e.d);case"code":{let i=v(e.d);return i.classList.add("code"),i}case"italic":case"bold":{let i=v("");return i.append(...e.c.map(s=>this.generateText(s))),e.t==="bold"?i.style.fontWeight="bold":i.style.fontStyle="italic",i}case"math":case"display-math":{let i=this.generateMathString(e);return T(i,e.t==="display-math")}case"string_var":{let i=v(""),s=this.getCurrentInstance(),a=s[e.d].t,l=s[e.d].v;return a==="string"?i.innerHTML=l:(i.innerHTML="EXPECTED VARIABLE OF TYPE STRING",i.style.color="red"),i}case"gap":{let i=v("");return new A(i,this,"",e.d),i}case"input":case"input2":{let i=e.t==="input2",s=v("");s.style.verticalAlign="text-bottom";let a=e.d,l=this.getCurrentInstance()[a];if(this.expected[a]=l.v,this.types[a]=l.t,!i)switch(l.t){case"set":s.append(T("\\{"),v(" "));break;case"vector":s.append(T("["),v(" "));break}if(l.t==="string")new A(s,this,a,this.expected[a]);else if(l.t==="vector"||l.t==="set"){let h=l.v.split(","),n=h.length;for(let o=0;o0&&s.appendChild(v(" , "));let c=a+"-"+o;new D(s,this,c,h[o].length,h[o],!1)}}else if(l.t==="matrix"){let h=b();s.appendChild(h),new V(h,this,a,l.v)}else if(l.t==="complex"){let h=l.v.split(",");new D(s,this,a+"-0",h[0].length,h[0],!1),s.append(v(" "),T("+"),v(" ")),new D(s,this,a+"-1",h[1].length,h[1],!1),s.append(v(" "),T("i"))}else{let h=l.t==="int";new D(s,this,a,l.v.length,l.v,h)}if(!i)switch(l.t){case"set":s.append(v(" "),T("\\}"));break;case"vector":s.append(v(" "),T("]"));break}return s}case"itemize":return z(e.c.map(i=>U(this.generateText(i))));case"single-choice":case"multi-choice":{let i=e.t=="multi-choice",s=document.createElement("table"),a=e.c.length,l=this.debug==!1,h=P(a,l),n=i?J:ee,o=i?G:$,c=[],u=[];for(let p=0;p{this.editedQuestion(),this.student[g]=this.student[g]==="true"?"false":"true",this.student[g]==="true"?S.innerHTML=n:S.innerHTML=o}):C.addEventListener("click",()=>{this.editedQuestion();for(let L of u)this.student[L]="false";this.student[g]="true";for(let L=0;L";document.getElementById("courseInfo2").innerHTML=F[r.lang].replace("*",t);let i=[],s=document.getElementById("questions"),a=1;for(let l of r.questions){l.title=""+a+". "+l.title;let h=b();s.appendChild(h);let n=new H(h,l,r.lang,e);n.showSolution=e,i.push(n),n.populateDom(),e&&l.error.length==0&&n.checkAndRepeatBtn.click(),a++}}return he(de);})();sell.init(quizSrc,debug); \ No newline at end of file diff --git a/sell.py b/sell.py index 3e3fa17..d54aec8 100755 --- a/sell.py +++ b/sell.py @@ -972,26 +972,26 @@ def compile_input_file(input_dirname: str, src: str) -> dict: HTML += b'et debug = false; let quizSrc = {};var sell=(()=>{var B=Obje' HTML += b'ct.defineProperty;var re=Object.getOwnPropertyDescriptor;var' HTML += b' ne=Object.getOwnPropertyNames;var ae=Object.prototype.hasOw' -HTML += b'nProperty;var le=(n,e)=>{for(var t in e)B(n,t,{get:e[t],enum' -HTML += b'erable:!0})},oe=(n,e,t,i)=>{if(e&&typeof e=="object"||typeof' -HTML += b' e=="function")for(let s of ne(e))!ae.call(n,s)&&s!==t&&B(n,' +HTML += b'nProperty;var le=(r,e)=>{for(var t in e)B(r,t,{get:e[t],enum' +HTML += b'erable:!0})},oe=(r,e,t,i)=>{if(e&&typeof e=="object"||typeof' +HTML += b' e=="function")for(let s of ne(e))!ae.call(r,s)&&s!==t&&B(r,' HTML += b's,{get:()=>e[s],enumerable:!(i=re(e,s))||i.enumerable});retu' -HTML += b'rn n};var he=n=>oe(B({},"__esModule",{value:!0}),n);var de={' -HTML += b'};le(de,{init:()=>pe});function v(n=[]){let e=document.creat' -HTML += b'eElement("div");return e.append(...n),e}function z(n=[]){let' -HTML += b' e=document.createElement("ul");return e.append(...n),e}func' -HTML += b'tion U(n){let e=document.createElement("li");return e.append' -HTML += b'Child(n),e}function R(n){let e=document.createElement("input' +HTML += b'rn r};var he=r=>oe(B({},"__esModule",{value:!0}),r);var de={' +HTML += b'};le(de,{init:()=>pe});function b(r=[]){let e=document.creat' +HTML += b'eElement("div");return e.append(...r),e}function z(r=[]){let' +HTML += b' e=document.createElement("ul");return e.append(...r),e}func' +HTML += b'tion U(r){let e=document.createElement("li");return e.append' +HTML += b'Child(r),e}function R(r){let e=document.createElement("input' HTML += b'");return e.spellcheck=!1,e.type="text",e.classList.add("inp' -HTML += b'utField"),e.style.width=n+"px",e}function j(){let n=document' -HTML += b'.createElement("button");return n.type="button",n.classList.' -HTML += b'add("button"),n}function k(n,e=[]){let t=document.createElem' -HTML += b'ent("span");return e.length>0?t.append(...e):t.innerHTML=n,t' -HTML += b'}function W(n,e,t=!1){katex.render(e,n,{throwOnError:!1,disp' +HTML += b'utField"),e.style.width=r+"px",e}function j(){let r=document' +HTML += b'.createElement("button");return r.type="button",r.classList.' +HTML += b'add("button"),r}function v(r,e=[]){let t=document.createElem' +HTML += b'ent("span");return e.length>0?t.append(...e):t.innerHTML=r,t' +HTML += b'}function W(r,e,t=!1){katex.render(e,r,{throwOnError:!1,disp' HTML += b'layMode:t,macros:{"\\\\RR":"\\\\mathbb{R}","\\\\NN":"\\\\mathbb{N}",' HTML += b'"\\\\QQ":"\\\\mathbb{Q}","\\\\ZZ":"\\\\mathbb{Z}","\\\\CC":"\\\\mathbb{C' -HTML += b'}"}})}function y(n,e=!1){let t=document.createElement("span"' -HTML += b');return W(t,n,e),t}var O={en:"This page runs in your browse' +HTML += b'}"}})}function T(r,e=!1){let t=document.createElement("span"' +HTML += b');return W(t,r,e),t}var O={en:"This page runs in your browse' HTML += b'r and does not store any data on servers.",de:"Diese Seite w' HTML += b'ird in Ihrem Browser ausgef\\xFChrt und speichert keine Daten' HTML += b' auf Servern.",es:"Esta p\\xE1gina se ejecuta en su navegador' @@ -1018,13 +1018,13 @@ def compile_input_file(input_dirname: str, src: str) -> dict: HTML += b'h\'s nochmal"],es:["int\\xE9ntalo de nuevo","todav\\xEDa alguno' HTML += b's errores","respuesta incorrecta"],it:["riprova","ancora qua' HTML += b'lche errore","risposta sbagliata"],fr:["r\\xE9essayer","encor' -HTML += b'e des erreurs","mauvaise r\\xE9ponse"]};function Y(n,e){let t' -HTML += b'=Array(e.length+1).fill(null).map(()=>Array(n.length+1).fill' -HTML += b'(null));for(let i=0;i<=n.length;i+=1)t[0][i]=i;for(let i=0;i' +HTML += b'e des erreurs","mauvaise r\\xE9ponse"]};function Y(r,e){let t' +HTML += b'=Array(e.length+1).fill(null).map(()=>Array(r.length+1).fill' +HTML += b'(null));for(let i=0;i<=r.length;i+=1)t[0][i]=i;for(let i=0;i' HTML += b'<=e.length;i+=1)t[i][0]=i;for(let i=1;i<=e.length;i+=1)for(l' -HTML += b'et s=1;s<=n.length;s+=1){let a=n[s-1]===e[i-1]?0:1;t[i][s]=M' +HTML += b'et s=1;s<=r.length;s+=1){let a=r[s-1]===e[i-1]?0:1;t[i][s]=M' HTML += b'ath.min(t[i][s-1]+1,t[i-1][s]+1,t[i-1][s-1]+a)}return t[e.le' -HTML += b'ngth][n.length]}var G=\'\';function P(n,e=!1){let t=new Array(n);for(let ' -HTML += b'i=0;i\';function P(r,e=!1){let t=new Array(r);for(let ' +HTML += b'i=0;i=this.m||t<0||t>=th' -HTML += b'is.n?"0":this.v[e*this.n+t]}resize(e,t,i){if(e<1||e>50||t<1|' -HTML += b'|t>50)return!1;let s=new n(e,t);s.v.fill(i);for(let a=0;at.trim()),this.n=this.v.length/this.m}getMaxCellSt' -HTML += b'rlen(){let e=0;for(let t of this.v)t.length>e&&(e=t.length);' -HTML += b'return e}toTeXString(e=!1,t=!0){let i="";t?i+=e?"\\\\left[\\\\be' -HTML += b'gin{array}":"\\\\begin{bmatrix}":i+=e?"\\\\left(\\\\begin{array}":' -HTML += b'"\\\\begin{pmatrix}",e&&(i+="{"+"c".repeat(this.n-1)+"|c}");fo' -HTML += b'r(let s=0;s0&&(i+="' -HTML += b'&");let l=this.getElement(s,a);try{l=f.parse(l).toTexString(' -HTML += b')}catch{}i+=l}i+="\\\\\\\\"}return t?i+=e?"\\\\end{array}\\\\right]"' -HTML += b':"\\\\end{bmatrix}":i+=e?"\\\\end{array}\\\\right)":"\\\\end{pmatrix' -HTML += b'}",i}},f=class n{constructor(){this.root=null,this.src="",th' -HTML += b'is.token="",this.skippedWhiteSpace=!1,this.pos=0}clone(){let' -HTML += b' e=new n;return e.root=this.root.clone(),e}getVars(e,t="",i=' -HTML += b'null){if(i==null&&(i=this.root),i.op.startsWith("var:")){let' -HTML += b' s=i.op.substring(4);(t.length==0||t.length>0&&s.startsWith(' -HTML += b't))&&e.add(s)}for(let s of i.c)this.getVars(e,t,s)}setVars(e' -HTML += b',t=null){t==null&&(t=this.root);for(let i of t.c)this.setVar' -HTML += b's(e,i);if(t.op.startsWith("var:")){let i=t.op.substring(4);i' -HTML += b'f(i in e){let s=e[i].clone();t.op=s.op,t.c=s.c,t.re=s.re,t.i' -HTML += b'm=s.im}}}renameVar(e,t,i=null){i==null&&(i=this.root);for(le' -HTML += b't s of i.c)this.renameVar(e,t,s);i.op.startsWith("var:")&&i.' -HTML += b'op.substring(4)===e&&(i.op="var:"+t)}eval(e,t=null){let s=u.' -HTML += b'const(),a=0,l=0,o=null;switch(t==null&&(t=this.root),t.op){c' -HTML += b'ase"const":s=t;break;case"+":case"-":case"*":case"/":case"^"' -HTML += b':{let r=this.eval(e,t.c[0]),h=this.eval(e,t.c[1]);switch(t.o' -HTML += b'p){case"+":s.re=r.re+h.re,s.im=r.im+h.im;break;case"-":s.re=' -HTML += b'r.re-h.re,s.im=r.im-h.im;break;case"*":s.re=r.re*h.re-r.im*h' -HTML += b'.im,s.im=r.re*h.im+r.im*h.re;break;case"/":a=h.re*h.re+h.im*' -HTML += b'h.im,s.re=(r.re*h.re+r.im*h.im)/a,s.im=(r.im*h.re-r.re*h.im)' -HTML += b'/a;break;case"^":o=new u("exp",[new u("*",[h,new u("ln",[r])' -HTML += b'])]),s=this.eval(e,o);break}break}case".-":case"abs":case"si' -HTML += b'n":case"sinc":case"cos":case"tan":case"cot":case"exp":case"l' -HTML += b'n":case"log":case"sqrt":{let r=this.eval(e,t.c[0]);switch(t.' -HTML += b'op){case".-":s.re=-r.re,s.im=-r.im;break;case"abs":s.re=Math' -HTML += b'.sqrt(r.re*r.re+r.im*r.im),s.im=0;break;case"sin":s.re=Math.' -HTML += b'sin(r.re)*Math.cosh(r.im),s.im=Math.cos(r.re)*Math.sinh(r.im' -HTML += b');break;case"sinc":o=new u("/",[new u("sin",[r]),r]),s=this.' -HTML += b'eval(e,o);break;case"cos":s.re=Math.cos(r.re)*Math.cosh(r.im' -HTML += b'),s.im=-Math.sin(r.re)*Math.sinh(r.im);break;case"tan":a=Mat' -HTML += b'h.cos(r.re)*Math.cos(r.re)+Math.sinh(r.im)*Math.sinh(r.im),s' -HTML += b'.re=Math.sin(r.re)*Math.cos(r.re)/a,s.im=Math.sinh(r.im)*Mat' -HTML += b'h.cosh(r.im)/a;break;case"cot":a=Math.sin(r.re)*Math.sin(r.r' -HTML += b'e)+Math.sinh(r.im)*Math.sinh(r.im),s.re=Math.sin(r.re)*Math.' -HTML += b'cos(r.re)/a,s.im=-(Math.sinh(r.im)*Math.cosh(r.im))/a;break;' -HTML += b'case"exp":s.re=Math.exp(r.re)*Math.cos(r.im),s.im=Math.exp(r' -HTML += b'.re)*Math.sin(r.im);break;case"ln":case"log":s.re=Math.log(M' -HTML += b'ath.sqrt(r.re*r.re+r.im*r.im)),a=Math.abs(r.im)<1e-9?0:r.im,' -HTML += b's.im=Math.atan2(a,r.re);break;case"sqrt":o=new u("^",[r,u.co' -HTML += b'nst(.5)]),s=this.eval(e,o);break}break}default:if(t.op.start' -HTML += b'sWith("var:")){let r=t.op.substring(4);if(r==="pi")return u.' -HTML += b'const(Math.PI);if(r==="e")return u.const(Math.E);if(r==="i")' -HTML += b'return u.const(0,1);if(r in e)return e[r];throw new Error("e' -HTML += b'val-error: unknown variable \'"+r+"\'")}else throw new Error("' -HTML += b'UNIMPLEMENTED eval \'"+t.op+"\'")}return s}static parse(e){let' -HTML += b' t=new n;if(t.src=e,t.token="",t.skippedWhiteSpace=!1,t.pos=' -HTML += b'0,t.next(),t.root=t.parseExpr(!1),t.token!=="")throw new Err' -HTML += b'or("remaining tokens: "+t.token+"...");return t}parseExpr(e)' -HTML += b'{return this.parseAdd(e)}parseAdd(e){let t=this.parseMul(e);' -HTML += b'for(;["+","-"].includes(this.token)&&!(e&&this.skippedWhiteS' -HTML += b'pace);){let i=this.token;this.next(),t=new u(i,[t,this.parse' -HTML += b'Mul(e)])}return t}parseMul(e){let t=this.parsePow(e);for(;!(' -HTML += b'e&&this.skippedWhiteSpace);){let i="*";if(["*","/"].includes' -HTML += b'(this.token))i=this.token,this.next();else if(!e&&this.token' -HTML += b'==="(")i="*";else if(this.token.length>0&&(this.isAlpha(this' -HTML += b'.token[0])||this.isNum(this.token[0])))i="*";else break;t=ne' -HTML += b'w u(i,[t,this.parsePow(e)])}return t}parsePow(e){let t=this.' -HTML += b'parseUnary(e);for(;["^"].includes(this.token)&&!(e&&this.ski' -HTML += b'ppedWhiteSpace);){let i=this.token;this.next(),t=new u(i,[t,' -HTML += b'this.parseUnary(e)])}return t}parseUnary(e){return this.toke' -HTML += b'n==="-"?(this.next(),new u(".-",[this.parseMul(e)])):this.pa' -HTML += b'rseInfix(e)}parseInfix(e){if(this.token.length==0)throw new ' -HTML += b'Error("expected unary");if(this.isNum(this.token[0])){let t=' -HTML += b'this.token;return this.next(),this.token==="."&&(t+=".",this' -HTML += b'.next(),this.token.length>0&&(t+=this.token,this.next())),ne' -HTML += b'w u("const",[],parseFloat(t))}else if(this.fun1().length>0){' -HTML += b'let t=this.fun1();this.next(t.length);let i=null;if(this.tok' -HTML += b'en==="(")if(this.next(),i=this.parseExpr(e),this.token+="",t' -HTML += b'his.token===")")this.next();else throw Error("expected \')\'")' -HTML += b';else i=this.parseMul(!0);return new u(t,[i])}else if(this.t' -HTML += b'oken==="("){this.next();let t=this.parseExpr(e);if(this.toke' -HTML += b'n+="",this.token===")")this.next();else throw Error("expecte' -HTML += b'd \')\'");return t.explicitParentheses=!0,t}else if(this.token' -HTML += b'==="|"){this.next();let t=this.parseExpr(e);if(this.token+="' -HTML += b'",this.token==="|")this.next();else throw Error("expected \'|' -HTML += b'\'");return new u("abs",[t])}else if(this.isAlpha(this.token[' -HTML += b'0])){let t="";return this.token.startsWith("pi")?t="pi":this' -HTML += b'.token.startsWith("C1")?t="C1":this.token.startsWith("C2")?t' -HTML += b'="C2":t=this.token[0],t==="I"&&(t="i"),this.next(t.length),n' -HTML += b'ew u("var:"+t,[])}else throw new Error("expected unary")}sta' -HTML += b'tic compare(e,t,i={}){let l=new Set;e.getVars(l),t.getVars(l' -HTML += b');for(let o=0;o<10;o++){let r={};for(let g of l)g in i?r[g]=' -HTML += b'i[g]:r[g]=u.const(Math.random(),Math.random());let h=e.eval(' -HTML += b'r),c=t.eval(r),d=h.re-c.re,p=h.im-c.im;if(Math.sqrt(d*d+p*p)' -HTML += b'>1e-9)return!1}return!0}fun1(){let e=["abs","sinc","sin","co' -HTML += b's","tan","cot","exp","ln","sqrt"];for(let t of e)if(this.tok' -HTML += b'en.toLowerCase().startsWith(t))return t;return""}next(e=-1){' -HTML += b'if(e>0&&this.token.length>e){this.token=this.token.substring' -HTML += b'(e),this.skippedWhiteSpace=!1;return}this.token="";let t=!1,' -HTML += b'i=this.src.length;for(this.skippedWhiteSpace=!1;this.pos0&&(this.isNum(this.token[0])&&this.isA' -HTML += b'lpha(s)||this.isAlpha(this.token[0])&&this.isNum(s))&&this.t' -HTML += b'oken!="C")return;if(`^%#*$()[]{},.:;+-*/_!<>=?|\t\n `.includes' -HTML += b'(s)){if(this.token.length>0)return;t=!0}`\t\n `.includes(s)==!' -HTML += b'1&&(this.token+=s),this.pos++}}isNum(e){return e.charCodeAt(' -HTML += b'0)>=48&&e.charCodeAt(0)<=57}isAlpha(e){return e.charCodeAt(0' -HTML += b')>=65&&e.charCodeAt(0)<=90||e.charCodeAt(0)>=97&&e.charCodeA' -HTML += b't(0)<=122||e==="_"}toString(){return this.root==null?"":this' -HTML += b'.root.toString()}toTexString(){return this.root==null?"":thi' -HTML += b's.root.toTexString()}},u=class n{constructor(e,t,i=0,s=0){th' -HTML += b'is.op=e,this.c=t,this.re=i,this.im=s,this.explicitParenthese' -HTML += b's=!1}clone(){let e=new n(this.op,this.c.map(t=>t.clone()),th' -HTML += b'is.re,this.im);return e.explicitParentheses=this.explicitPar' -HTML += b'entheses,e}static const(e=0,t=0){return new n("const",[],e,t' -HTML += b')}compare(e,t=0,i=1e-9){let s=this.re-e,a=this.im-t;return M' -HTML += b'ath.sqrt(s*s+a*a)1e-14,i=Math.abs(this.im)>1e-14;t&' -HTML += b'&i&&this.im>=0?e="("+this.re+"+"+this.im+"i)":t&&i&&this.im<' -HTML += b'0?e="("+this.re+"-"+-this.im+"i)":t&&this.re>0?e=""+this.re:' -HTML += b't&&this.re<0?e="("+this.re+")":i?e="("+this.im+"i)":e="0"}el' -HTML += b'se this.op.startsWith("var")?e=this.op.split(":")[1]:this.c.' -HTML += b'length==1?e=(this.op===".-"?"-":this.op)+"("+this.c.toString' -HTML += b'()+")":e="("+this.c.map(t=>t.toString()).join(this.op)+")";r' -HTML += b'eturn e}toTexString(e=!1){let i="";switch(this.op){case"cons' -HTML += b't":{let s=Math.abs(this.re)>1e-9,a=Math.abs(this.im)>1e-9,l=' -HTML += b's?""+this.re:"",o=a?""+this.im+"i":"";o==="1i"?o="i":o==="-1' -HTML += b'i"&&(o="-i"),!s&&!a?i="0":(a&&this.im>=0&&s&&(o="+"+o),i=l+o' -HTML += b');break}case".-":i="-"+this.c[0].toTexString();break;case"+"' -HTML += b':case"-":case"*":case"^":{let s=this.c[0].toTexString(),a=th' -HTML += b'is.c[1].toTexString(),l=this.op==="*"?"\\\\cdot ":this.op;i="{' -HTML += b'"+s+"}"+l+"{"+a+"}";break}case"/":{let s=this.c[0].toTexStri' -HTML += b'ng(!0),a=this.c[1].toTexString(!0);i="\\\\frac{"+s+"}{"+a+"}";' -HTML += b'break}case"sin":case"sinc":case"cos":case"tan":case"cot":cas' -HTML += b'e"exp":case"ln":{let s=this.c[0].toTexString(!0);i+="\\\\"+thi' -HTML += b's.op+"\\\\left("+s+"\\\\right)";break}case"sqrt":{let s=this.c[0' -HTML += b'].toTexString(!0);i+="\\\\"+this.op+"{"+s+"}";break}case"abs":' -HTML += b'{let s=this.c[0].toTexString(!0);i+="\\\\left|"+s+"\\\\right|";b' -HTML += b'reak}default:if(this.op.startsWith("var:")){let s=this.op.su' -HTML += b'bstring(4);switch(s){case"pi":s="\\\\pi";break}i=" "+s+" "}els' -HTML += b'e{let s="warning: Node.toString(..):";s+=" unimplemented ope' -HTML += b'rator \'"+this.op+"\'",console.log(s),i=this.op,this.c.length>' -HTML += b'0&&(i+="\\\\left({"+this.c.map(a=>a.toTexString(!0)).join(",")' -HTML += b'+"}\\\\right)")}}return!e&&this.explicitParentheses&&(i="\\\\lef' -HTML += b't({"+i+"}\\\\right)"),i}};function ie(n,e){let t=1e-9;if(f.com' -HTML += b'pare(n,e))return!0;n=n.clone(),e=e.clone(),N(n.root),N(e.roo' -HTML += b't);let i=new Set;n.getVars(i),e.getVars(i);let s=[],a=[];for' -HTML += b'(let r of i.keys())r.startsWith("C")?s.push(r):a.push(r);let' -HTML += b' l=s.length;for(let r=0;r{n.feedbackPopupDiv.style.display="none"},500),n.state==' -HTML += b'=x.passed?n.src.instances.length>0?n.checkAndRepeatBtn.inner' -HTML += b'HTML=te:n.checkAndRepeatBtn.style.display="none":n.checkAndR' -HTML += b'epeatBtn.innerHTML=I}var A=class{constructor(e,t,i,s){t.stud' -HTML += b'ent[i]="",this.question=t,this.inputId=i,i.length==0&&(this.' -HTML += b'inputId="gap-"+t.gapIdx,t.types[this.inputId]="string",t.exp' -HTML += b'ected[this.inputId]=s,t.gapIdx++);let a=s.split("|"),l=0;for' -HTML += b'(let c=0;cl&&(l=d.length)' -HTML += b'}let o=k("");e.appendChild(o);let r=Math.max(l*15,24),h=R(r)' -HTML += b';if(t.gapInputs[this.inputId]=h,h.addEventListener("keyup",(' -HTML += b')=>{this.question.editedQuestion(),h.value=h.value.toUpperCa' -HTML += b'se(),this.question.student[this.inputId]=h.value.trim()}),o.' -HTML += b'appendChild(h),this.question.showSolution&&(this.question.st' -HTML += b'udent[this.inputId]=h.value=a[0],a.length>1)){let c=k("["+a.' -HTML += b'join("|")+"]");c.style.fontSize="small",c.style.textDecorati' -HTML += b'on="underline",o.appendChild(c)}}},E=class{constructor(e,t,i' -HTML += b',s,a,l){t.student[i]="",this.question=t,this.inputId=i,this.' -HTML += b'outerSpan=k(""),this.outerSpan.style.position="relative",e.a' -HTML += b'ppendChild(this.outerSpan),this.inputElement=R(Math.max(s*12' -HTML += b',48)),this.outerSpan.appendChild(this.inputElement),this.equ' -HTML += b'ationPreviewDiv=v(),this.equationPreviewDiv.classList.add("e' -HTML += b'quationPreview"),this.equationPreviewDiv.style.display="none' -HTML += b'",this.outerSpan.appendChild(this.equationPreviewDiv),this.i' -HTML += b'nputElement.addEventListener("click",()=>{this.question.edit' -HTML += b'edQuestion(),this.edited()}),this.inputElement.addEventListe' -HTML += b'ner("keyup",()=>{this.question.editedQuestion(),this.edited(' -HTML += b')}),this.inputElement.addEventListener("focusout",()=>{this.' -HTML += b'equationPreviewDiv.innerHTML="",this.equationPreviewDiv.styl' -HTML += b'e.display="none"}),this.inputElement.addEventListener("keydo' -HTML += b'wn",o=>{let r="abcdefghijklmnopqrstuvwxyz";r+="ABCDEFGHIJKLM' -HTML += b'NOPQRSTUVWXYZ",r+="0123456789",r+="+-*/^(). <>=|",l&&(r="-01' -HTML += b'23456789"),o.key.length<3&&r.includes(o.key)==!1&&o.preventD' -HTML += b'efault();let h=this.inputElement.value.length*12;this.inputE' -HTML += b'lement.offsetWidth0&&!i?"block":"none",thi' -HTML += b's.question.student[this.inputId]=e}},V=class{constructor(e,t' -HTML += b',i,s){this.parent=e,this.question=t,this.inputId=i,this.matE' -HTML += b'xpected=new C(0,0),this.matExpected.fromString(s),this.matSt' -HTML += b'udent=new C(this.matExpected.m==1?1:3,this.matExpected.n==1?' -HTML += b'1:3),t.showSolution&&this.matStudent.fromMatrix(this.matExpe' -HTML += b'cted),this.genMatrixDom()}genMatrixDom(){let e=v();this.pare' -HTML += b'nt.innerHTML="",this.parent.appendChild(e),e.style.position=' -HTML += b'"relative",e.style.display="inline-block";let t=document.cre' -HTML += b'ateElement("table");e.appendChild(t);let i=this.matExpected.' -HTML += b'getMaxCellStrlen();for(let p=0;p=10,this.matStudent.n<=1,this.matStudent.m>=10,this.matStu' -HTML += b'dent.m<=1];for(let p=0;p<4;p++){if(c[p]==!1)continue;let m=k' -HTML += b'(s[p]);o[p]!=888&&(m.style.top=""+o[p]+"px"),r[p]!=888&&(m.s' -HTML += b'tyle.bottom=""+r[p]+"px"),h[p]!=888&&(m.style.right=""+h[p]+' -HTML += b'"px"),m.classList.add("matrixResizeButton"),e.appendChild(m)' -HTML += b',d[p]?m.style.opacity="0.5":m.addEventListener("click",()=>{' -HTML += b'this.matStudent.resize(this.matStudent.m+a[p],this.matStuden' -HTML += b't.n+l[p],"0"),this.genMatrixDom()})}}generateMatrixParenthes' -HTML += b'is(e,t){let i=document.createElement("td");i.style.width="3p' -HTML += b'x";for(let s of["Top",e?"Left":"Right","Bottom"])i.style["bo' -HTML += b'rder"+s+"Width"]="2px",i.style["border"+s+"Style"]="solid";r' -HTML += b'eturn this.question.language=="de"&&(e?i.style.borderTopLeft' -HTML += b'Radius="5px":i.style.borderTopRightRadius="5px",e?i.style.bo' -HTML += b'rderBottomLeftRadius="5px":i.style.borderBottomRightRadius="' -HTML += b'5px"),i.rowSpan=t,i}};var x={init:0,errors:1,passed:2,incomp' -HTML += b'lete:3},H=class{constructor(e,t,i,s){this.state=x.init,this.' -HTML += b'language=i,this.src=t,this.debug=s,this.instanceOrder=P(t.in' -HTML += b'stances.length,!0),this.instanceIdx=0,this.choiceIdx=0,this.' -HTML += b'gapIdx=0,this.expected={},this.types={},this.student={},this' -HTML += b'.gapInputs={},this.parentDiv=e,this.questionDiv=null,this.fe' -HTML += b'edbackPopupDiv=null,this.titleDiv=null,this.checkAndRepeatBt' -HTML += b'n=null,this.showSolution=!1,this.feedbackSpan=null,this.numC' -HTML += b'orrect=0,this.numChecked=0}reset(){this.instanceIdx=(this.in' -HTML += b'stanceIdx+1)%this.src.instances.length}getCurrentInstance(){' -HTML += b'let e=this.instanceOrder[this.instanceIdx];return this.src.i' -HTML += b'nstances[e]}editedQuestion(){this.state=x.init,this.updateVi' -HTML += b'sualQuestionState(),this.questionDiv.style.color="black",thi' -HTML += b's.checkAndRepeatBtn.innerHTML=I,this.checkAndRepeatBtn.style' -HTML += b'.display="block",this.checkAndRepeatBtn.style.color="black"}' -HTML += b'updateVisualQuestionState(){let e="black",t="transparent";sw' -HTML += b'itch(this.state){case x.init:case x.incomplete:e="rgb(0,0,0)' -HTML += b'",t="transparent";break;case x.passed:e="rgb(0,150,0)",t="rg' -HTML += b'ba(0,150,0, 0.025)";break;case x.errors:e="rgb(150,0,0)",t="' -HTML += b'rgba(150,0,0, 0.025)",this.numChecked>=5&&(this.feedbackSpan' -HTML += b'.innerHTML=""+this.numCorrect+" / "+this.numChecked);break}t' -HTML += b'his.questionDiv.style.color=this.feedbackSpan.style.color=th' -HTML += b'is.titleDiv.style.color=this.checkAndRepeatBtn.style.backgro' -HTML += b'undColor=this.questionDiv.style.borderColor=e,this.questionD' -HTML += b'iv.style.backgroundColor=t}populateDom(){if(this.parentDiv.i' -HTML += b'nnerHTML="",this.questionDiv=v(),this.parentDiv.appendChild(' -HTML += b'this.questionDiv),this.questionDiv.classList.add("question")' -HTML += b',this.feedbackPopupDiv=v(),this.feedbackPopupDiv.classList.a' -HTML += b'dd("questionFeedback"),this.questionDiv.appendChild(this.fee' -HTML += b'dbackPopupDiv),this.feedbackPopupDiv.innerHTML="awesome",thi' -HTML += b's.debug&&"src_line"in this.src){let a=v();a.classList.add("d' -HTML += b'ebugInfo"),a.innerHTML="Source code: lines "+this.src.src_li' -HTML += b'ne+"..",this.questionDiv.appendChild(a)}if(this.titleDiv=v()' -HTML += b',this.questionDiv.appendChild(this.titleDiv),this.titleDiv.c' -HTML += b'lassList.add("questionTitle"),this.titleDiv.innerHTML=this.s' -HTML += b'rc.title,this.src.error.length>0){let a=k(this.src.error);th' -HTML += b'is.questionDiv.appendChild(a),a.style.color="red";return}let' -HTML += b' e=this.getCurrentInstance();if(e!=null&&"__svg_image"in e){' -HTML += b'let a=e.__svg_image.v,l=v();this.questionDiv.appendChild(l);' -HTML += b'let o=document.createElement("img");l.appendChild(o),o.class' -HTML += b'List.add("img"),o.src="data:image/svg+xml;base64,"+a}for(let' -HTML += b' a of this.src.text.c)this.questionDiv.appendChild(this.gene' -HTML += b'rateText(a));let t=v();this.questionDiv.appendChild(t),t.cla' -HTML += b'ssList.add("buttonRow");let i=Object.keys(this.expected).len' -HTML += b'gth>0;i&&(this.checkAndRepeatBtn=j(),t.appendChild(this.chec' -HTML += b'kAndRepeatBtn),this.checkAndRepeatBtn.innerHTML=I,this.check' -HTML += b'AndRepeatBtn.style.backgroundColor="black");let s=k(" &' -HTML += b'nbsp; ");if(t.appendChild(s),this.feedbackSpan=k(""),t.' -HTML += b'appendChild(this.feedbackSpan),this.debug){if(this.src.varia' -HTML += b'bles.length>0){let o=v();o.classList.add("debugInfo"),o.inne' -HTML += b'rHTML="Variables generated by Python Code",this.questionDiv.' -HTML += b'appendChild(o);let r=v();r.classList.add("debugCode"),this.q' -HTML += b'uestionDiv.appendChild(r);let h=this.getCurrentInstance(),c=' -HTML += b'"",d=[...this.src.variables];d.sort();for(let p of d){let m=' -HTML += b'h[p].t,g=h[p].v;switch(m){case"vector":g="["+g+"]";break;cas' -HTML += b'e"set":g="{"+g+"}";break}c+=m+" "+p+" = "+g+"
"}r.innerH' -HTML += b'TML=c}let a=["python_src_html","text_src_html"],l=["Python S' -HTML += b'ource Code","Text Source Code"];for(let o=0;o0){let h=v()' -HTML += b';h.classList.add("debugInfo"),h.innerHTML=l[o],this.question' -HTML += b'Div.appendChild(h);let c=v();c.classList.add("debugCode"),th' -HTML += b'is.questionDiv.append(c),c.innerHTML=this.src[r]}}}i&&this.c' -HTML += b'heckAndRepeatBtn.addEventListener("click",()=>{this.state==x' -HTML += b'.passed?(this.state=x.init,this.reset(),this.populateDom()):' -HTML += b'se(this)})}generateMathString(e){let t="";switch(e.t){case"m' -HTML += b'ath":case"display-math":for(let i of e.c){let s=this.generat' -HTML += b'eMathString(i);i.t==="var"&&t.includes("!PM")&&(s.startsWith' -HTML += b'("{-")?(s="{"+s.substring(2),t=t.replaceAll("!PM","-")):t=t.' -HTML += b'replaceAll("!PM","+")),t+=s}break;case"text":return e.d;case' -HTML += b'"plus_minus":{t+=" !PM ";break}case"var":{let i=this.getCurr' -HTML += b'entInstance(),s=i[e.d].t,a=i[e.d].v;switch(s){case"vector":r' -HTML += b'eturn"\\\\left["+a+"\\\\right]";case"set":return"\\\\left\\\\{"+a+"\\' -HTML += b'\\right\\\\}";case"complex":{let l=a.split(","),o=parseFloat(l[' -HTML += b'0]),r=parseFloat(l[1]);return u.const(o,r).toTexString()}cas' -HTML += b'e"matrix":{let l=new C(0,0);return l.fromString(a),t=l.toTeX' -HTML += b'String(e.d.includes("augmented"),this.language!="de"),t}case' -HTML += b'"term":{try{t=f.parse(a).toTexString()}catch{}break}default:' -HTML += b't=a}}}return e.t==="plus_minus"?t:"{"+t+"}"}generateText(e,t' -HTML += b'=!1){switch(e.t){case"paragraph":case"span":{let i=document.' -HTML += b'createElement(e.t=="span"||t?"span":"p");for(let s of e.c)i.' -HTML += b'appendChild(this.generateText(s));return i}case"text":return' -HTML += b' k(e.d);case"code":{let i=k(e.d);return i.classList.add("cod' -HTML += b'e"),i}case"italic":case"bold":{let i=k("");return i.append(.' -HTML += b'..e.c.map(s=>this.generateText(s))),e.t==="bold"?i.style.fon' -HTML += b'tWeight="bold":i.style.fontStyle="italic",i}case"math":case"' -HTML += b'display-math":{let i=this.generateMathString(e);return y(i,e' -HTML += b'.t==="display-math")}case"string_var":{let i=k(""),s=this.ge' -HTML += b'tCurrentInstance(),a=s[e.d].t,l=s[e.d].v;return a==="string"' -HTML += b'?i.innerHTML=l:(i.innerHTML="EXPECTED VARIABLE OF TYPE STRIN' -HTML += b'G",i.style.color="red"),i}case"gap":{let i=k("");return new ' -HTML += b'A(i,this,"",e.d),i}case"input":case"input2":{let i=e.t==="in' -HTML += b'put2",s=k("");s.style.verticalAlign="text-bottom";let a=e.d,' -HTML += b'l=this.getCurrentInstance()[a];if(this.expected[a]=l.v,this.' -HTML += b'types[a]=l.t,!i)switch(l.t){case"set":s.append(y("\\\\{"),k(" ' -HTML += b'"));break;case"vector":s.append(y("["),k(" "));break}if(l.t=' -HTML += b'=="string")new A(s,this,a,this.expected[a]);else if(l.t==="v' -HTML += b'ector"||l.t==="set"){let o=l.v.split(","),r=o.length;for(let' -HTML += b' h=0;h0&&s.appendChild(k(" , "));let c=a+"-"+h;new' -HTML += b' E(s,this,c,o[h].length,o[h],!1)}}else if(l.t==="matrix"){le' -HTML += b't o=v();s.appendChild(o),new V(o,this,a,l.v)}else if(l.t==="' -HTML += b'complex"){let o=l.v.split(",");new E(s,this,a+"-0",o[0].leng' -HTML += b'th,o[0],!1),s.append(k(" "),y("+"),k(" ")),new E(s,this,a+"-' -HTML += b'1",o[1].length,o[1],!1),s.append(k(" "),y("i"))}else{let o=l' -HTML += b'.t==="int";new E(s,this,a,l.v.length,l.v,o)}if(!i)switch(l.t' -HTML += b'){case"set":s.append(k(" "),y("\\\\}"));break;case"vector":s.a' -HTML += b'ppend(k(" "),y("]"));break}return s}case"itemize":return z(e' -HTML += b'.c.map(i=>U(this.generateText(i))));case"single-choice":case' -HTML += b'"multi-choice":{let i=e.t=="multi-choice",s=document.createE' -HTML += b'lement("table"),a=e.c.length,l=this.debug==!1,o=P(a,l),r=i?J' -HTML += b':ee,h=i?G:$,c=[],d=[];for(let p=0;p{this.editedQuestion(),this.stud' -HTML += b'ent[b]=this.student[b]==="true"?"false":"true",this.student[' -HTML += b'b]==="true"?D.innerHTML=r:D.innerHTML=h}):M.addEventListener' -HTML += b'("click",()=>{this.editedQuestion();for(let L of d)this.stud' -HTML += b'ent[L]="false";this.student[b]="true";for(let L=0;L\'+K[n.la' -HTML += b'ng]+"";document.getElementById("courseInfo2").innerHT' -HTML += b'ML=F[n.lang].replace("*",t);let i=[],s=document.getElementBy' -HTML += b'Id("questions"),a=1;for(let l of n.questions){l.title=""+a+"' -HTML += b'. "+l.title;let o=v();s.appendChild(o);let r=new H(o,l,n.lan' -HTML += b'g,e);r.showSolution=e,i.push(r),r.populateDom(),e&&l.error.l' -HTML += b'ength==0&&r.checkAndRepeatBtn.click(),a++}}return he(de);})(' -HTML += b');sell.init(quizSrc,debug); ' +HTML += b'is.n?"":this.v[e*this.n+t]}resize(e,t,i){if(e<1||e>50||t<1||' +HTML += b't>50)return!1;let s=new r(e,t);s.v.fill(i);for(let a=0;at.trim()),this.n=this.v.length/this.m}getMaxCellStr' +HTML += b'len(){let e=0;for(let t of this.v)t.length>e&&(e=t.length);r' +HTML += b'eturn e}toTeXString(e=!1,t=!0){let i="";t?i+=e?"\\\\left[\\\\beg' +HTML += b'in{array}":"\\\\begin{bmatrix}":i+=e?"\\\\left(\\\\begin{array}":"' +HTML += b'\\\\begin{pmatrix}",e&&(i+="{"+"c".repeat(this.n-1)+"|c}");for' +HTML += b'(let s=0;s0&&(i+="&' +HTML += b'");let l=this.getElement(s,a);try{l=k.parse(l).toTexString()' +HTML += b'}catch{}i+=l}i+="\\\\\\\\"}return t?i+=e?"\\\\end{array}\\\\right]":' +HTML += b'"\\\\end{bmatrix}":i+=e?"\\\\end{array}\\\\right)":"\\\\end{pmatrix}' +HTML += b'",i}},k=class r{constructor(){this.root=null,this.src="",thi' +HTML += b's.token="",this.skippedWhiteSpace=!1,this.pos=0}clone(){let ' +HTML += b'e=new r;return e.root=this.root.clone(),e}getVars(e,t="",i=n' +HTML += b'ull){if(i==null&&(i=this.root),i.op.startsWith("var:")){let ' +HTML += b's=i.op.substring(4);(t.length==0||t.length>0&&s.startsWith(t' +HTML += b'))&&e.add(s)}for(let s of i.c)this.getVars(e,t,s)}setVars(e,' +HTML += b't=null){t==null&&(t=this.root);for(let i of t.c)this.setVars' +HTML += b'(e,i);if(t.op.startsWith("var:")){let i=t.op.substring(4);if' +HTML += b'(i in e){let s=e[i].clone();t.op=s.op,t.c=s.c,t.re=s.re,t.im' +HTML += b'=s.im}}}renameVar(e,t,i=null){i==null&&(i=this.root);for(let' +HTML += b' s of i.c)this.renameVar(e,t,s);i.op.startsWith("var:")&&i.o' +HTML += b'p.substring(4)===e&&(i.op="var:"+t)}eval(e,t=null){let s=m.c' +HTML += b'onst(),a=0,l=0,h=null;switch(t==null&&(t=this.root),t.op){ca' +HTML += b'se"const":s=t;break;case"+":case"-":case"*":case"/":case"^":' +HTML += b'{let n=this.eval(e,t.c[0]),o=this.eval(e,t.c[1]);switch(t.op' +HTML += b'){case"+":s.re=n.re+o.re,s.im=n.im+o.im;break;case"-":s.re=n' +HTML += b'.re-o.re,s.im=n.im-o.im;break;case"*":s.re=n.re*o.re-n.im*o.' +HTML += b'im,s.im=n.re*o.im+n.im*o.re;break;case"/":a=o.re*o.re+o.im*o' +HTML += b'.im,s.re=(n.re*o.re+n.im*o.im)/a,s.im=(n.im*o.re-n.re*o.im)/' +HTML += b'a;break;case"^":h=new m("exp",[new m("*",[o,new m("ln",[n])]' +HTML += b')]),s=this.eval(e,h);break}break}case".-":case"abs":case"sin' +HTML += b'":case"sinc":case"cos":case"tan":case"cot":case"exp":case"ln' +HTML += b'":case"log":case"sqrt":{let n=this.eval(e,t.c[0]);switch(t.o' +HTML += b'p){case".-":s.re=-n.re,s.im=-n.im;break;case"abs":s.re=Math.' +HTML += b'sqrt(n.re*n.re+n.im*n.im),s.im=0;break;case"sin":s.re=Math.s' +HTML += b'in(n.re)*Math.cosh(n.im),s.im=Math.cos(n.re)*Math.sinh(n.im)' +HTML += b';break;case"sinc":h=new m("/",[new m("sin",[n]),n]),s=this.e' +HTML += b'val(e,h);break;case"cos":s.re=Math.cos(n.re)*Math.cosh(n.im)' +HTML += b',s.im=-Math.sin(n.re)*Math.sinh(n.im);break;case"tan":a=Math' +HTML += b'.cos(n.re)*Math.cos(n.re)+Math.sinh(n.im)*Math.sinh(n.im),s.' +HTML += b're=Math.sin(n.re)*Math.cos(n.re)/a,s.im=Math.sinh(n.im)*Math' +HTML += b'.cosh(n.im)/a;break;case"cot":a=Math.sin(n.re)*Math.sin(n.re' +HTML += b')+Math.sinh(n.im)*Math.sinh(n.im),s.re=Math.sin(n.re)*Math.c' +HTML += b'os(n.re)/a,s.im=-(Math.sinh(n.im)*Math.cosh(n.im))/a;break;c' +HTML += b'ase"exp":s.re=Math.exp(n.re)*Math.cos(n.im),s.im=Math.exp(n.' +HTML += b're)*Math.sin(n.im);break;case"ln":case"log":s.re=Math.log(Ma' +HTML += b'th.sqrt(n.re*n.re+n.im*n.im)),a=Math.abs(n.im)<1e-9?0:n.im,s' +HTML += b'.im=Math.atan2(a,n.re);break;case"sqrt":h=new m("^",[n,m.con' +HTML += b'st(.5)]),s=this.eval(e,h);break}break}default:if(t.op.starts' +HTML += b'With("var:")){let n=t.op.substring(4);if(n==="pi")return m.c' +HTML += b'onst(Math.PI);if(n==="e")return m.const(Math.E);if(n==="i")r' +HTML += b'eturn m.const(0,1);if(n in e)return e[n];throw new Error("ev' +HTML += b'al-error: unknown variable \'"+n+"\'")}else throw new Error("U' +HTML += b'NIMPLEMENTED eval \'"+t.op+"\'")}return s}static parse(e){let ' +HTML += b't=new r;if(t.src=e,t.token="",t.skippedWhiteSpace=!1,t.pos=0' +HTML += b',t.next(),t.root=t.parseExpr(!1),t.token!=="")throw new Erro' +HTML += b'r("remaining tokens: "+t.token+"...");return t}parseExpr(e){' +HTML += b'return this.parseAdd(e)}parseAdd(e){let t=this.parseMul(e);f' +HTML += b'or(;["+","-"].includes(this.token)&&!(e&&this.skippedWhiteSp' +HTML += b'ace);){let i=this.token;this.next(),t=new m(i,[t,this.parseM' +HTML += b'ul(e)])}return t}parseMul(e){let t=this.parsePow(e);for(;!(e' +HTML += b'&&this.skippedWhiteSpace);){let i="*";if(["*","/"].includes(' +HTML += b'this.token))i=this.token,this.next();else if(!e&&this.token=' +HTML += b'=="(")i="*";else if(this.token.length>0&&(this.isAlpha(this.' +HTML += b'token[0])||this.isNum(this.token[0])))i="*";else break;t=new' +HTML += b' m(i,[t,this.parsePow(e)])}return t}parsePow(e){let t=this.p' +HTML += b'arseUnary(e);for(;["^"].includes(this.token)&&!(e&&this.skip' +HTML += b'pedWhiteSpace);){let i=this.token;this.next(),t=new m(i,[t,t' +HTML += b'his.parseUnary(e)])}return t}parseUnary(e){return this.token' +HTML += b'==="-"?(this.next(),new m(".-",[this.parseMul(e)])):this.par' +HTML += b'seInfix(e)}parseInfix(e){if(this.token.length==0)throw new E' +HTML += b'rror("expected unary");if(this.isNum(this.token[0])){let t=t' +HTML += b'his.token;return this.next(),this.token==="."&&(t+=".",this.' +HTML += b'next(),this.token.length>0&&(t+=this.token,this.next())),new' +HTML += b' m("const",[],parseFloat(t))}else if(this.fun1().length>0){l' +HTML += b'et t=this.fun1();this.next(t.length);let i=null;if(this.toke' +HTML += b'n==="(")if(this.next(),i=this.parseExpr(e),this.token+="",th' +HTML += b'is.token===")")this.next();else throw Error("expected \')\'");' +HTML += b'else i=this.parseMul(!0);return new m(t,[i])}else if(this.to' +HTML += b'ken==="("){this.next();let t=this.parseExpr(e);if(this.token' +HTML += b'+="",this.token===")")this.next();else throw Error("expected' +HTML += b' \')\'");return t.explicitParentheses=!0,t}else if(this.token=' +HTML += b'=="|"){this.next();let t=this.parseExpr(e);if(this.token+=""' +HTML += b',this.token==="|")this.next();else throw Error("expected \'|\'' +HTML += b'");return new m("abs",[t])}else if(this.isAlpha(this.token[0' +HTML += b'])){let t="";return this.token.startsWith("pi")?t="pi":this.' +HTML += b'token.startsWith("C1")?t="C1":this.token.startsWith("C2")?t=' +HTML += b'"C2":t=this.token[0],t==="I"&&(t="i"),this.next(t.length),ne' +HTML += b'w m("var:"+t,[])}else throw new Error("expected unary")}stat' +HTML += b'ic compare(e,t,i={}){let l=new Set;e.getVars(l),t.getVars(l)' +HTML += b';for(let h=0;h<10;h++){let n={};for(let f of l)f in i?n[f]=i' +HTML += b'[f]:n[f]=m.const(Math.random(),Math.random());let o=e.eval(n' +HTML += b'),c=t.eval(n),u=o.re-c.re,p=o.im-c.im;if(Math.sqrt(u*u+p*p)>' +HTML += b'1e-9)return!1}return!0}fun1(){let e=["abs","sinc","sin","cos' +HTML += b'","tan","cot","exp","ln","sqrt"];for(let t of e)if(this.toke' +HTML += b'n.toLowerCase().startsWith(t))return t;return""}next(e=-1){i' +HTML += b'f(e>0&&this.token.length>e){this.token=this.token.substring(' +HTML += b'e),this.skippedWhiteSpace=!1;return}this.token="";let t=!1,i' +HTML += b'=this.src.length;for(this.skippedWhiteSpace=!1;this.pos0&&(this.isNum(this.token[0])&&this.isAl' +HTML += b'pha(s)||this.isAlpha(this.token[0])&&this.isNum(s))&&this.to' +HTML += b'ken!="C")return;if(`^%#*$()[]{},.:;+-*/_!<>=?|\t\n `.includes(' +HTML += b's)){if(this.token.length>0)return;t=!0}`\t\n `.includes(s)==!1' +HTML += b'&&(this.token+=s),this.pos++}}isNum(e){return e.charCodeAt(0' +HTML += b')>=48&&e.charCodeAt(0)<=57}isAlpha(e){return e.charCodeAt(0)' +HTML += b'>=65&&e.charCodeAt(0)<=90||e.charCodeAt(0)>=97&&e.charCodeAt' +HTML += b'(0)<=122||e==="_"}toString(){return this.root==null?"":this.' +HTML += b'root.toString()}toTexString(){return this.root==null?"":this' +HTML += b'.root.toTexString()}},m=class r{constructor(e,t,i=0,s=0){thi' +HTML += b's.op=e,this.c=t,this.re=i,this.im=s,this.explicitParentheses' +HTML += b'=!1}clone(){let e=new r(this.op,this.c.map(t=>t.clone()),thi' +HTML += b's.re,this.im);return e.explicitParentheses=this.explicitPare' +HTML += b'ntheses,e}static const(e=0,t=0){return new r("const",[],e,t)' +HTML += b'}compare(e,t=0,i=1e-9){let s=this.re-e,a=this.im-t;return Ma' +HTML += b'th.sqrt(s*s+a*a)1e-14,i=Math.abs(this.im)>1e-14;t&&' +HTML += b'i&&this.im>=0?e="("+this.re+"+"+this.im+"i)":t&&i&&this.im<0' +HTML += b'?e="("+this.re+"-"+-this.im+"i)":t&&this.re>0?e=""+this.re:t' +HTML += b'&&this.re<0?e="("+this.re+")":i?e="("+this.im+"i)":e="0"}els' +HTML += b'e this.op.startsWith("var")?e=this.op.split(":")[1]:this.c.l' +HTML += b'ength==1?e=(this.op===".-"?"-":this.op)+"("+this.c.toString(' +HTML += b')+")":e="("+this.c.map(t=>t.toString()).join(this.op)+")";re' +HTML += b'turn e}toTexString(e=!1){let i="";switch(this.op){case"const' +HTML += b'":{let s=Math.abs(this.re)>1e-9,a=Math.abs(this.im)>1e-9,l=s' +HTML += b'?""+this.re:"",h=a?""+this.im+"i":"";h==="1i"?h="i":h==="-1i' +HTML += b'"&&(h="-i"),!s&&!a?i="0":(a&&this.im>=0&&s&&(h="+"+h),i=l+h)' +HTML += b';break}case".-":i="-"+this.c[0].toTexString();break;case"+":' +HTML += b'case"-":case"*":case"^":{let s=this.c[0].toTexString(),a=thi' +HTML += b's.c[1].toTexString(),l=this.op==="*"?"\\\\cdot ":this.op;i="{"' +HTML += b'+s+"}"+l+"{"+a+"}";break}case"/":{let s=this.c[0].toTexStrin' +HTML += b'g(!0),a=this.c[1].toTexString(!0);i="\\\\frac{"+s+"}{"+a+"}";b' +HTML += b'reak}case"sin":case"sinc":case"cos":case"tan":case"cot":case' +HTML += b'"exp":case"ln":{let s=this.c[0].toTexString(!0);i+="\\\\"+this' +HTML += b'.op+"\\\\left("+s+"\\\\right)";break}case"sqrt":{let s=this.c[0]' +HTML += b'.toTexString(!0);i+="\\\\"+this.op+"{"+s+"}";break}case"abs":{' +HTML += b'let s=this.c[0].toTexString(!0);i+="\\\\left|"+s+"\\\\right|";br' +HTML += b'eak}default:if(this.op.startsWith("var:")){let s=this.op.sub' +HTML += b'string(4);switch(s){case"pi":s="\\\\pi";break}i=" "+s+" "}else' +HTML += b'{let s="warning: Node.toString(..):";s+=" unimplemented oper' +HTML += b'ator \'"+this.op+"\'",console.log(s),i=this.op,this.c.length>0' +HTML += b'&&(i+="\\\\left({"+this.c.map(a=>a.toTexString(!0)).join(",")+' +HTML += b'"}\\\\right)")}}return!e&&this.explicitParentheses&&(i="\\\\left' +HTML += b'({"+i+"}\\\\right)"),i}};function ie(r,e){let t=1e-9;if(k.comp' +HTML += b'are(r,e))return!0;r=r.clone(),e=e.clone(),N(r.root),N(e.root' +HTML += b');let i=new Set;r.getVars(i),e.getVars(i);let s=[],a=[];for(' +HTML += b'let n of i.keys())n.startsWith("C")?s.push(n):a.push(n);let ' +HTML += b'l=s.length;for(let n=0;n{r.feedbackPopupDiv.style.display="none"},500),r' +HTML += b'.state===x.passed?r.src.instances.length>0?r.checkAndRepeatB' +HTML += b'tn.innerHTML=te:r.checkAndRepeatBtn.style.display="none":r.c' +HTML += b'heckAndRepeatBtn.innerHTML=I}var A=class{constructor(e,t,i,s' +HTML += b'){this.question=t,this.inputId=i,i.length==0&&(this.inputId=' +HTML += b'i="gap-"+t.gapIdx,t.types[this.inputId]="string",t.expected[' +HTML += b'this.inputId]=s,t.gapIdx++),i in t.student||(t.student[i]=""' +HTML += b');let a=s.split("|"),l=0;for(let c=0;cl&&(l=u.length)}let h=v("");e.appendChild(h);le' +HTML += b't n=Math.max(l*15,24),o=R(n);if(t.gapInputs[this.inputId]=o,' +HTML += b'o.addEventListener("keyup",()=>{this.question.editedQuestion' +HTML += b'(),o.value=o.value.toUpperCase(),this.question.student[this.' +HTML += b'inputId]=o.value.trim()}),h.appendChild(o),this.question.sho' +HTML += b'wSolution&&(this.question.student[this.inputId]=o.value=a[0]' +HTML += b',a.length>1)){let c=v("["+a.join("|")+"]");c.style.fontSize=' +HTML += b'"small",c.style.textDecoration="underline",h.appendChild(c)}' +HTML += b'}},D=class{constructor(e,t,i,s,a,l,h=!1){i in t.student||(t.' +HTML += b'student[i]=""),this.question=t,this.inputId=i,this.outerSpan' +HTML += b'=v(""),this.outerSpan.style.position="relative",e.appendChil' +HTML += b'd(this.outerSpan),this.inputElement=R(Math.max(s*12,48)),thi' +HTML += b's.outerSpan.appendChild(this.inputElement),this.equationPrev' +HTML += b'iewDiv=b(),this.equationPreviewDiv.classList.add("equationPr' +HTML += b'eview"),this.equationPreviewDiv.style.display="none",this.ou' +HTML += b'terSpan.appendChild(this.equationPreviewDiv),this.inputEleme' +HTML += b'nt.addEventListener("click",()=>{this.question.editedQuestio' +HTML += b'n(),this.edited()}),this.inputElement.addEventListener("keyu' +HTML += b'p",()=>{this.question.editedQuestion(),this.edited()}),this.' +HTML += b'inputElement.addEventListener("focusout",()=>{this.equationP' +HTML += b'reviewDiv.innerHTML="",this.equationPreviewDiv.style.display' +HTML += b'="none"}),this.inputElement.addEventListener("keydown",n=>{l' +HTML += b'et o="abcdefghijklmnopqrstuvwxyz";o+="ABCDEFGHIJKLMNOPQRSTUV' +HTML += b'WXYZ",o+="0123456789",o+="+-*/^(). <>=|",l&&(o="-0123456789"' +HTML += b'),n.key.length<3&&o.includes(n.key)==!1&&n.preventDefault();' +HTML += b'let c=this.inputElement.value.length*12;this.inputElement.of' +HTML += b'fsetWidth0&&!i?"block":"none",this.qu' +HTML += b'estion.student[this.inputId]=e}},V=class{constructor(e,t,i,s' +HTML += b'){this.parent=e,this.question=t,this.inputId=i,this.matExpec' +HTML += b'ted=new E(0,0),this.matExpected.fromString(s),this.matStuden' +HTML += b't=new E(this.matExpected.m==1?1:3,this.matExpected.n==1?1:3)' +HTML += b',t.showSolution&&this.matStudent.fromMatrix(this.matExpected' +HTML += b'),this.genMatrixDom(!0)}genMatrixDom(e){let t=b();this.paren' +HTML += b't.innerHTML="",this.parent.appendChild(t),t.style.position="' +HTML += b'relative",t.style.display="inline-block";let i=document.crea' +HTML += b'teElement("table");t.appendChild(i);let s=this.matExpected.g' +HTML += b'etMaxCellStrlen();for(let d=0;d=10,this.matStudent.n<=1,this.matStudent.m>=10,this.matS' +HTML += b'tudent.m<=1];for(let d=0;d<4;d++){if(u[d]==!1)continue;let f' +HTML += b'=v(a[d]);n[d]!=888&&(f.style.top=""+n[d]+"px"),o[d]!=888&&(f' +HTML += b'.style.bottom=""+o[d]+"px"),c[d]!=888&&(f.style.right=""+c[d' +HTML += b']+"px"),f.classList.add("matrixResizeButton"),t.appendChild(' +HTML += b'f),p[d]?f.style.opacity="0.5":f.addEventListener("click",()=' +HTML += b'>{for(let g=0;g=5&&(this.feedbackSpan.innerHTML=""+this.numCorrect+" /' +HTML += b' "+this.numChecked);break}this.questionDiv.style.color=this.' +HTML += b'feedbackSpan.style.color=this.titleDiv.style.color=this.chec' +HTML += b'kAndRepeatBtn.style.backgroundColor=this.questionDiv.style.b' +HTML += b'orderColor=e,this.questionDiv.style.backgroundColor=t}popula' +HTML += b'teDom(){if(this.parentDiv.innerHTML="",this.questionDiv=b(),' +HTML += b'this.parentDiv.appendChild(this.questionDiv),this.questionDi' +HTML += b'v.classList.add("question"),this.feedbackPopupDiv=b(),this.f' +HTML += b'eedbackPopupDiv.classList.add("questionFeedback"),this.quest' +HTML += b'ionDiv.appendChild(this.feedbackPopupDiv),this.feedbackPopup' +HTML += b'Div.innerHTML="awesome",this.debug&&"src_line"in this.src){l' +HTML += b'et a=b();a.classList.add("debugInfo"),a.innerHTML="Source co' +HTML += b'de: lines "+this.src.src_line+"..",this.questionDiv.appendCh' +HTML += b'ild(a)}if(this.titleDiv=b(),this.questionDiv.appendChild(thi' +HTML += b's.titleDiv),this.titleDiv.classList.add("questionTitle"),thi' +HTML += b's.titleDiv.innerHTML=this.src.title,this.src.error.length>0)' +HTML += b'{let a=v(this.src.error);this.questionDiv.appendChild(a),a.s' +HTML += b'tyle.color="red";return}let e=this.getCurrentInstance();if(e' +HTML += b'!=null&&"__svg_image"in e){let a=e.__svg_image.v,l=b();this.' +HTML += b'questionDiv.appendChild(l);let h=document.createElement("img' +HTML += b'");l.appendChild(h),h.classList.add("img"),h.src="data:image' +HTML += b'/svg+xml;base64,"+a}for(let a of this.src.text.c)this.questi' +HTML += b'onDiv.appendChild(this.generateText(a));let t=b();this.quest' +HTML += b'ionDiv.appendChild(t),t.classList.add("buttonRow");let i=Obj' +HTML += b'ect.keys(this.expected).length>0;i&&(this.checkAndRepeatBtn=' +HTML += b'j(),t.appendChild(this.checkAndRepeatBtn),this.checkAndRepea' +HTML += b'tBtn.innerHTML=I,this.checkAndRepeatBtn.style.backgroundColo' +HTML += b'r="black");let s=v("   ");if(t.appendChild(s)' +HTML += b',this.feedbackSpan=v(""),t.appendChild(this.feedbackSpan),th' +HTML += b'is.debug){if(this.src.variables.length>0){let h=b();h.classL' +HTML += b'ist.add("debugInfo"),h.innerHTML="Variables generated by Pyt' +HTML += b'hon Code",this.questionDiv.appendChild(h);let n=b();n.classL' +HTML += b'ist.add("debugCode"),this.questionDiv.appendChild(n);let o=t' +HTML += b'his.getCurrentInstance(),c="",u=[...this.src.variables];u.so' +HTML += b'rt();for(let p of u){let d=o[p].t,f=o[p].v;switch(d){case"ve' +HTML += b'ctor":f="["+f+"]";break;case"set":f="{"+f+"}";break}c+=d+" "' +HTML += b'+p+" = "+f+"
"}n.innerHTML=c}let a=["python_src_html","t' +HTML += b'ext_src_html"],l=["Python Source Code","Text Source Code"];f' +HTML += b'or(let h=0;h0){let o=b();o.classList.add("debugInfo"),o.i' +HTML += b'nnerHTML=l[h],this.questionDiv.appendChild(o);let c=b();c.cl' +HTML += b'assList.add("debugCode"),this.questionDiv.append(c),c.innerH' +HTML += b'TML=this.src[n]}}}i&&this.checkAndRepeatBtn.addEventListener' +HTML += b'("click",()=>{this.state==x.passed?(this.state=x.init,this.r' +HTML += b'eset(),this.populateDom()):se(this)})}generateMathString(e){' +HTML += b'let t="";switch(e.t){case"math":case"display-math":for(let i' +HTML += b' of e.c){let s=this.generateMathString(i);i.t==="var"&&t.inc' +HTML += b'ludes("!PM")&&(s.startsWith("{-")?(s="{"+s.substring(2),t=t.' +HTML += b'replaceAll("!PM","-")):t=t.replaceAll("!PM","+")),t+=s}break' +HTML += b';case"text":return e.d;case"plus_minus":{t+=" !PM ";break}ca' +HTML += b'se"var":{let i=this.getCurrentInstance(),s=i[e.d].t,a=i[e.d]' +HTML += b'.v;switch(s){case"vector":return"\\\\left["+a+"\\\\right]";case"' +HTML += b'set":return"\\\\left\\\\{"+a+"\\\\right\\\\}";case"complex":{let l=a' +HTML += b'.split(","),h=parseFloat(l[0]),n=parseFloat(l[1]);return m.c' +HTML += b'onst(h,n).toTexString()}case"matrix":{let l=new E(0,0);retur' +HTML += b'n l.fromString(a),t=l.toTeXString(e.d.includes("augmented"),' +HTML += b'this.language!="de"),t}case"term":{try{t=k.parse(a).toTexStr' +HTML += b'ing()}catch{}break}default:t=a}}}return e.t==="plus_minus"?t' +HTML += b':"{"+t+"}"}generateText(e,t=!1){switch(e.t){case"paragraph":' +HTML += b'case"span":{let i=document.createElement(e.t=="span"||t?"spa' +HTML += b'n":"p");for(let s of e.c)i.appendChild(this.generateText(s))' +HTML += b';return i}case"text":return v(e.d);case"code":{let i=v(e.d);' +HTML += b'return i.classList.add("code"),i}case"italic":case"bold":{le' +HTML += b't i=v("");return i.append(...e.c.map(s=>this.generateText(s)' +HTML += b')),e.t==="bold"?i.style.fontWeight="bold":i.style.fontStyle=' +HTML += b'"italic",i}case"math":case"display-math":{let i=this.generat' +HTML += b'eMathString(e);return T(i,e.t==="display-math")}case"string_' +HTML += b'var":{let i=v(""),s=this.getCurrentInstance(),a=s[e.d].t,l=s' +HTML += b'[e.d].v;return a==="string"?i.innerHTML=l:(i.innerHTML="EXPE' +HTML += b'CTED VARIABLE OF TYPE STRING",i.style.color="red"),i}case"ga' +HTML += b'p":{let i=v("");return new A(i,this,"",e.d),i}case"input":ca' +HTML += b'se"input2":{let i=e.t==="input2",s=v("");s.style.verticalAli' +HTML += b'gn="text-bottom";let a=e.d,l=this.getCurrentInstance()[a];if' +HTML += b'(this.expected[a]=l.v,this.types[a]=l.t,!i)switch(l.t){case"' +HTML += b'set":s.append(T("\\\\{"),v(" "));break;case"vector":s.append(T' +HTML += b'("["),v(" "));break}if(l.t==="string")new A(s,this,a,this.ex' +HTML += b'pected[a]);else if(l.t==="vector"||l.t==="set"){let h=l.v.sp' +HTML += b'lit(","),n=h.length;for(let o=0;o0&&s.appendChild(' +HTML += b'v(" , "));let c=a+"-"+o;new D(s,this,c,h[o].length,h[o],!1)}' +HTML += b'}else if(l.t==="matrix"){let h=b();s.appendChild(h),new V(h,' +HTML += b'this,a,l.v)}else if(l.t==="complex"){let h=l.v.split(",");ne' +HTML += b'w D(s,this,a+"-0",h[0].length,h[0],!1),s.append(v(" "),T("+"' +HTML += b'),v(" ")),new D(s,this,a+"-1",h[1].length,h[1],!1),s.append(' +HTML += b'v(" "),T("i"))}else{let h=l.t==="int";new D(s,this,a,l.v.len' +HTML += b'gth,l.v,h)}if(!i)switch(l.t){case"set":s.append(v(" "),T("\\\\' +HTML += b'}"));break;case"vector":s.append(v(" "),T("]"));break}return' +HTML += b' s}case"itemize":return z(e.c.map(i=>U(this.generateText(i))' +HTML += b'));case"single-choice":case"multi-choice":{let i=e.t=="multi' +HTML += b'-choice",s=document.createElement("table"),a=e.c.length,l=th' +HTML += b'is.debug==!1,h=P(a,l),n=i?J:ee,o=i?G:$,c=[],u=[];for(let p=0' +HTML += b';p{this' +HTML += b'.editedQuestion(),this.student[g]=this.student[g]==="true"?"' +HTML += b'false":"true",this.student[g]==="true"?S.innerHTML=n:S.inner' +HTML += b'HTML=o}):C.addEventListener("click",()=>{this.editedQuestion' +HTML += b'();for(let L of u)this.student[L]="false";this.student[g]="t' +HTML += b'rue";for(let L=0;L\'+K[r.lang]+"";document.getElement' +HTML += b'ById("courseInfo2").innerHTML=F[r.lang].replace("*",t);let i' +HTML += b'=[],s=document.getElementById("questions"),a=1;for(let l of ' +HTML += b'r.questions){l.title=""+a+". "+l.title;let h=b();s.appendChi' +HTML += b'ld(h);let n=new H(h,l,r.lang,e);n.showSolution=e,i.push(n),n' +HTML += b'.populateDom(),e&&l.error.length==0&&n.checkAndRepeatBtn.cli' +HTML += b'ck(),a++}}return he(de);})();sell.init(quizSrc,debug); ' HTML = HTML.decode('utf-8') # @end(html) diff --git a/web/src/eval.js b/web/src/eval.js index c7ef445..1c6e683 100644 --- a/web/src/eval.js +++ b/web/src/eval.js @@ -162,7 +162,7 @@ export function evalQuestion(question) { for (let j = 0; j < mat.n; j++) { let idx = i * mat.n + j; student = question.student[id + "-" + idx]; - if (student.length == 0) isComplete = false; + if (student != undefined && student.length == 0) isComplete = false; let e = mat.v[idx]; try { let u = Term.parse(e); diff --git a/web/src/input.js b/web/src/input.js index 6155403..e9f8e73 100644 --- a/web/src/input.js +++ b/web/src/input.js @@ -30,8 +30,6 @@ export class GapInput { * @param {string} solutionString -- the sample solution */ constructor(parent, question, inputId, solutionString) { - // initialize the students answer to "unset" - question.student[inputId] = ""; /** @type {Question} */ this.question = question; /** @type {string} */ @@ -39,11 +37,13 @@ export class GapInput { if (inputId.length == 0) { // generate a new id, if the input does not correspond to a variable, // but the solution was given directly as string in the text. - this.inputId = "gap-" + question.gapIdx; + this.inputId = inputId = "gap-" + question.gapIdx; question.types[this.inputId] = "string"; question.expected[this.inputId] = solutionString; question.gapIdx++; } + // initialize the students answer to "unset" in case it does not yet exist + if (inputId in question.student == false) question.student[inputId] = ""; // split the solution string into single answers let expectedList = solutionString.split("|"); // get the maximum number of characters (to estimate the width of the input) @@ -86,6 +86,7 @@ export class TermInput { * @param {number} numChars -- number of characters for the width-estimation * @param {string} solutionString -- the sample solution * @param {boolean} integersOnly -- if true, then only numbers can be entered + * @param {boolean} forceSolution -- if true, the solution string will be set, regardless of question.showSolution */ constructor( parent, @@ -93,10 +94,11 @@ export class TermInput { inputId, numChars, solutionString, - integersOnly + integersOnly, + forceSolution = false ) { - // initialize the students answer to "unset" - question.student[inputId] = ""; + // initialize the students answer to "unset" in case it does not yet exist + if (inputId in question.student == false) question.student[inputId] = ""; /** @type {Question} */ this.question = question; /** @type {string} */ @@ -149,7 +151,7 @@ export class TermInput { this.inputElement.style.width = "" + requiredWidth + "px"; }); // for debugging purposes - if (this.question.showSolution) + if (forceSolution || this.question.showSolution) question.student[inputId] = this.inputElement.value = solutionString; } @@ -207,13 +209,14 @@ export class MatrixInput { ); if (question.showSolution) this.matStudent.fromMatrix(this.matExpected); // generate the DOM - this.genMatrixDom(); + this.genMatrixDom(true); } /** * Generate the DOM (HTMLTable and children) + * @param {boolean} initial -- true, iff generated the first time */ - genMatrixDom() { + genMatrixDom(initial) { // we need an additional HTMLDivElement that contains both the table for the // matrix, as well as the resizing buttons ("+" and "-") let div = genDiv(); @@ -247,7 +250,8 @@ export class MatrixInput { elementId, maxCellStrlen, this.matStudent.v[idx], - false + false, + !initial ); } // insert a column for the right (rendered by a bordered HTMLDivElement) @@ -290,12 +294,24 @@ export class MatrixInput { btn.style.opacity = "0.5"; } else { btn.addEventListener("click", () => { + // set values from input to matrix elements + for (let u = 0; u < this.matStudent.m; u++) { + for (let v = 0; v < this.matStudent.n; v++) { + let idx = u * this.matStudent.n + v; + let id = this.inputId + "-" + idx; + let value = this.question.student[id]; + this.matStudent.v[idx] = value; + delete this.question.student[id]; + } + } + // resize matrix (and reuse old values if feasible) this.matStudent.resize( this.matStudent.m + deltaM[i], this.matStudent.n + deltaN[i], - "0" + "" ); - this.genMatrixDom(); + // generate DOM + this.genMatrixDom(false); }); } } diff --git a/web/src/math.js b/web/src/math.js index 32305ea..d0c1d8f 100644 --- a/web/src/math.js +++ b/web/src/math.js @@ -76,13 +76,13 @@ export class Matrix { } /** - * Returns the term of element (i,j), or "0" if the index is invalid. + * Returns the term of element (i,j), or "" if the index is invalid. * @param {number} i * @param {number} j * @returns {string} */ getElement(i, j) { - if (i < 0 || i >= this.m || j < 0 || j >= this.n) return "0"; + if (i < 0 || i >= this.m || j < 0 || j >= this.n) return ""; return this.v[i * this.n + j]; }