unknown
a-quiz
/* * Generated file — do not edit directly. * Source: tools/modules-builder/src/modules/a-quiz/ * Rebuild: cd tools/modules-builder && npm run build -- a-quiz */ (function(N){"use strict";let S=Object.getPrototypeOf,M,O,b,$,F={isConnected:1},me=1e3,R,U={},he=S(F),G=S(S),T,K=(e,t,r,s)=>(e??(s?setTimeout(r,s):queueMicrotask(r),new Set)).add(t),Y=(e,t,r)=>{let s=b;b=t;try{return e(r)}catch(n){return console.error(n),r}finally{b=s}},j=e=>e.filter(t=>{var r;return(r=t._dom)==null?void 0:r.isConnected}),J=e=>R=K(R,e,()=>{for(let t of R)t._bindings=j(t._bindings),t._listeners=j(t._listeners);R=T},me),Q={get val(){var e;return(e=b==null?void 0:b._getters)==null||e.add(this),this.rawVal},get oldVal(){var e;return(e=b==null?void 0:b._getters)==null||e.add(this),this._oldVal},set val(e){var t;(t=b==null?void 0:b._setters)==null||t.add(this),e!==this.rawVal&&(this.rawVal=e,this._bindings.length+this._listeners.length?(O==null||O.add(this),M=K(M,this,be)):this._oldVal=e)}},W=e=>({__proto__:Q,rawVal:e,_oldVal:e,_bindings:[],_listeners:[]}),V=(e,t)=>{let r={_getters:new Set,_setters:new Set},s={f:e},n=$;$=[];let a=Y(e,r,t);a=(a??document).nodeType?a:new Text(a);for(let o of r._getters)r._setters.has(o)||(J(o),o._bindings.push(s));for(let o of $)o._dom=a;return $=n,s._dom=a},H=(e,t=W(),r)=>{let s={_getters:new Set,_setters:new Set},n={f:e,s:t};n._dom=r??($==null?void 0:$.push(n))??F,t.val=Y(e,s,t.rawVal);for(let a of s._getters)s._setters.has(a)||(J(a),a._listeners.push(n));return t},B=(e,...t)=>{for(let r of t.flat(1/0)){let s=S(r??0),n=s===Q?V(()=>r.val):s===G?V(r):r;n!=T&&e.append(n)}return e},Z=(e,t,...r)=>{var u,h,A;let[{is:s,...n},...a]=S(r[0]??0)===he?r:[{},...r],o=e?document.createElementNS(e,t,{is:s}):document.createElement(t,{is:s});for(let[w,c]of Object.entries(n)){let g=d=>d&&(Object.getOwnPropertyDescriptor(d,w)??g(S(d))),E=!e&&!s&&!t.includes("-")?U[h=t+","+w]??(U[h]=((u=g(S(o)))==null?void 0:u.set)??0):(A=g(S(o)))==null?void 0:A.set,x=w.startsWith("on"),z=x?(d,v)=>{let P=w.slice(2);o.removeEventListener(P,v),o.addEventListener(P,d)}:E?E.bind(o):o.setAttribute.bind(o,w),_=S(c??0);x||_===G&&(c=H(c),_=Q),_===Q?V(()=>(z(c.val,c._oldVal),o)):z(c)}return B(o,a)},X=e=>({get:(t,r)=>Z.bind(T,e,r)}),ee=(e,t)=>t?t!==e&&e.replaceWith(t):e.remove(),be=()=>{let e=100,t=[...M].filter(s=>s.rawVal!==s._oldVal);do{O=new Set;for(let s of new Set(t.flatMap(n=>n._listeners=j(n._listeners))))H(s.f,s.s,s._dom),s._dom=T}while(--e&&(t=[...O]).length);let r=[...M].filter(s=>s.rawVal!==s._oldVal);M=T;for(let s of new Set(r.flatMap(n=>n._bindings=j(n._bindings))))ee(s._dom,V(s.f,s._dom)),s._dom=T;for(let s of r)s._oldVal=s.rawVal};const f={tags:new Proxy(e=>new Proxy(Z,X(e)),X()),hydrate:(e,t)=>ee(e,V(t,e)),add:B,state:W,derive:H},ge=/^(\d+)\.\s+(.+)$/,ve=/^(\*)?([A-Za-z])\)\s+(.+)$/,pe=/^>\s+(.+)$/;function ye(e){const t=[];let r=null;for(const s of e.split(/\r?\n/)){const n=s.trim();if(!n)continue;const a=ge.exec(n);if(a){r={prompt:a[2].trim(),choices:[]},t.push(r);continue}const o=ve.exec(n);if(o){if(!r)throw new Error(`Choice "${n}" appeared before any question.`);r.choices.push({correct:!!o[1],key:o[2].toLowerCase(),text:o[3].trim()});continue}const u=pe.exec(n);if(u){if(!r)throw new Error(`Correct message "${n}" appeared before any question.`);if(r.choices.length===0)throw new Error(`Correct message for "${r.prompt}" appeared before any choices.`);const h=u[1].trim();r.correctMessage=r.correctMessage?`${r.correctMessage} ${h}`:h;continue}throw new Error(`Unrecognized quiz line: "${n}"`)}for(const[s,n]of t.entries()){if(n.choices.length===0)throw new Error(`Question ${s+1} has no choices.`);if(!n.choices.some(a=>a.correct))throw new Error(`Question ${s+1} has no correct choice marked with *.`)}return t}function we(e){const t=e.slice();for(let r=t.length-1;r>0;r-=1){const s=Math.floor(Math.random()*(r+1)),n=t[r];t[r]=t[s],t[s]=n}return t}const{button:L,div:C,input:_e,label:Se,li:ze,p:q,section:ke,strong:qe,ul:Ae}=f.tags,te="data-a-quiz-mounted",Ee="http://localhost:2732",re={Accept:"application/json","Content-Type":"application/json"},$e=` :host { display: block; font: 1rem/1.5 system-ui, sans-serif; color: #1a1a1a; } .quiz { display: grid; gap: 1rem; } .quiz-panel { display: contents; } .progress { margin: 0; font-size: 0.9rem; color: #555; } .question { display: grid; gap: 0.5rem; } .prompt { margin: 0; font-weight: 600; } .choices { display: grid; gap: 0.35rem; margin: 0; padding: 0; list-style: none; } .choice { display: grid; grid-template-columns: auto 1fr; gap: 0.5rem; align-items: start; } .choice input { margin-top: 0.25rem; } .choice.is-correct-choice label { color: #2e7d32; font-weight: 600; } .choice.is-wrong-choice label { color: #c62828; } .feedback { display: grid; gap: 0.35rem; margin: 0; padding: 0.65rem 0.75rem; border-radius: 4px; border: 1px solid transparent; } .feedback[hidden] { display: none; } .feedback.is-correct { background: #e8f5e9; border-color: #a5d6a7; } .feedback.is-incorrect { background: #ffebee; border-color: #ef9a9a; } .feedback-status { margin: 0; font-weight: 600; } .correct-message { margin: 0; } .actions { display: flex; flex-wrap: wrap; gap: 0.5rem; align-items: center; } button { font: inherit; cursor: pointer; padding: 0.4rem 0.75rem; border: 1px solid #888; border-radius: 4px; background: #f5f5f5; } button:hover:not(:disabled) { background: #ebebeb; } button:disabled { cursor: not-allowed; opacity: 0.55; } .result { margin: 0; font-weight: 600; } .submit-status { margin: 0; padding: 0.65rem 0.75rem; border-radius: 4px; border: 1px solid #a5d6a7; background: #e8f5e9; color: #2e7d32; font-weight: 600; } .submit-status.is-error { border-color: #ef9a9a; background: #ffebee; color: #c62828; } .submit-status[hidden] { display: none; } button[data-action="submit"] { background: #1a1a1a; border-color: #1a1a1a; color: #fff; } button[data-action="submit"]:hover:not(:disabled) { background: #333; } button[data-action="submit"]:disabled { background: #1a1a1a; border-color: #1a1a1a; color: #fff; opacity: 0.7; } .error { margin: 0; color: #c62828; } `;function se(e,t){for(const r of t){const s=e.getAttribute(r);if(s!=null&&s.trim()!=="")return s.trim()}return null}function Te(e){return(e.querySelector("code")||e).textContent??""}function Ce(e){return(se(e,["data-origin","origin"])??Ee).replace(/\/$/,"")}function xe(e){return se(e,["data-assessment-id","assessment-id"])}function ne(e,t){return e?new URL(t,`${e}/`).toString():t}function oe(e){return e.hasAttribute("randomize")||e.hasAttribute("data-randomize")}function Me(e){return e.hasAttribute("submit")||e.hasAttribute("data-submit")}function Oe(e,t,r,s){const n=document.createElement("div");return n.className="a-quiz",n.setAttribute(te,""),oe(e)&&n.setAttribute("data-randomize",e.getAttribute("data-randomize")??""),t&&n.setAttribute("data-origin",t),r&&n.setAttribute("data-submit",""),s&&n.setAttribute("data-assessment-id",s),n}function ae(e){if(e.shadowRoot)return e.shadowRoot;const t=e.attachShadow({mode:"open"}),r=document.createElement("style");return r.textContent=$e,t.append(r),t}function ie(e){var t;return(t=e.choices.find(r=>r.correct))==null?void 0:t.key}function Ve(e,t){const r=ye(e);return t?we(r):r}function le(e,t){if(e===401||t==="unauthenticated")return"Sign in to submit your quiz.";switch(t){case"missing_organization":return"Select a course before submitting your quiz.";case"not_enrolled":return"You are not enrolled in this course.";case"course_archived":return"This course is archived; submissions are closed.";case"attempt_limit_reached":return"You have used all attempts for this quiz.";default:return`Could not submit quiz (${t}).`}}function Pe(e){const{sourceText:t,randomize:r,origin:s,submitEnabled:n,assessmentId:a}=e,o=f.state(null),u=f.state([]),h=f.state(0),A=f.state(0),w=f.state([]),c=f.state(!1),g=f.state(null),E=f.state(!1),x=f.state(!1),z=f.state(!1),_=f.state(!1),d=f.state(null),v=f.state(!1),P=()=>({type:"a-quiz",correct:A.val,total:u.val.length,answers:w.val}),je=(i,l)=>{const m=l&&typeof l=="object"&&"error"in l?String(l.error):`HTTP ${i.status}`;v.val=!0,d.val=le(i.status,m)},Qe=async()=>{if(!n||!a)return;const i=P();try{const l=await fetch(ne(s,`/api/submissions/drafts/${encodeURIComponent(a)}`),{method:"PUT",credentials:"include",headers:re,body:JSON.stringify(i)}),m=await l.json().catch(()=>null);if(!l.ok){je(l,m);return}v.val&&!z.val&&(v.val=!1,d.val=null)}catch(l){const m=l instanceof Error?l.message:String(l);v.val=!0,d.val=`Could not save progress (${m}).`}},de=()=>{if(n&&!a){o.val='Graded quizzes require data-assessment-id (or remove the "submit" attribute for practice).',u.val=[];return}try{u.val=Ve(t,r),o.val=null}catch(i){const l=i instanceof Error?i.message:String(i);o.val=l,u.val=[]}h.val=0,A.val=0,w.val=[],c.val=!1,g.val=null,E.val=!1,x.val=!1,z.val=!1,_.val=!1,d.val=null,v.val=!1},Le=()=>{const i=u.val[h.val];if(!i||c.val||g.val==null)return;const l=ie(i),m=!!(l&&g.val===l);m&&(A.val+=1),w.val=[...w.val,{index:h.val,prompt:i.prompt,selectedKey:g.val,correctKey:l,correct:m}],E.val=m,c.val=!0,n&&Qe()},Ie=()=>{if(c.val){if(h.val>=u.val.length-1){x.val=!0;return}h.val+=1,c.val=!1,g.val=null,E.val=!1}},Ne=async()=>{if(!n||!a||z.val||_.val)return;_.val=!0,v.val=!1,d.val=null;const i=u.val.length,l=i>0?A.val/i:0,m=P();try{const p=await fetch(ne(s,"/api/submissions/complete"),{method:"POST",credentials:"include",headers:re,body:JSON.stringify({assessmentId:a,score:l,state:m})}),k=await p.json().catch(()=>null);if(!p.ok){const I=k&&typeof k=="object"&&"error"in k?String(k.error):`HTTP ${p.status}`;v.val=!0,d.val=le(p.status,I);return}z.val=!0,v.val=!1,d.val="Your quiz has been submitted."}catch(p){const k=p instanceof Error?p.message:String(p);v.val=!0,d.val=`Could not reach Pro (${k}).`}finally{_.val=!1}};de();const Ue=(i,l,m)=>{const p=l+1,k=`q${p}`,I=ie(i),De=l>=m-1;return[q({class:"progress"},()=>`Question ${p} of ${m}`),ke({class:"question"},q({class:"prompt"},i.prompt),Ae({class:"choices"},...i.choices.map(y=>{const fe=`${k}-${y.key}`;return ze({class:()=>{const D=["choice"];return c.val&&(y.key===I&&D.push("is-correct-choice"),y.key===g.val&&y.key!==I&&D.push("is-wrong-choice")),D.join(" ")}},_e({type:"radio",id:fe,name:k,value:y.key,disabled:()=>c.val,onchange:()=>{c.val||(g.val=y.key)}}),Se({for:fe},qe(`${y.key})`),` ${y.text}`))})),C({class:()=>{const y=["feedback"];return c.val&&y.push(E.val?"is-correct":"is-incorrect"),y.join(" ")},hidden:()=>!c.val},q({class:"feedback-status"},()=>E.val?"Correct":"Incorrect"),i.correctMessage?q({class:"correct-message",hidden:()=>!c.val},i.correctMessage):null)),C({class:"actions"},L({type:"button","data-action":"check",hidden:()=>c.val,disabled:()=>g.val==null,onclick:Le},"Check answer"),L({type:"button","data-action":"next",hidden:()=>!c.val,onclick:Ie},De?"See results":"Next question"))]},He=()=>{const i=[L({type:"button","data-action":"reset",onclick:de},"Restart")];return n&&i.unshift(L({type:"button","data-action":"submit",disabled:()=>z.val||_.val,onclick:()=>void Ne()},()=>_.val?"Submitting…":z.val?"Submitted":"Submit quiz")),[q({class:"result"},()=>`Score: ${A.val} / ${u.val.length}`),n?q({class:()=>v.val?"submit-status is-error":"submit-status",hidden:()=>d.val==null},()=>d.val??""):null,C({class:"actions"},...i)]};return C({class:"quiz"},()=>{if(o.val)return q({class:"error"},`a-quiz error: ${o.val}`);if(x.val)return C({class:"quiz-panel"},...He());const i=u.val[h.val];return i?C({class:"quiz-panel"},...Ue(i,h.val,u.val.length)):q({class:"error"},"a-quiz error: no questions found")})}function Re(e,t){var s,n;const r=ae(e);(s=r.querySelector(".quiz"))==null||s.remove(),(n=r.querySelector(".error"))==null||n.remove(),f.add(r,Pe(t))}function ce(e){if(!(e instanceof HTMLElement)||e.getAttribute(te)!=null)return null;const t=Te(e),r=oe(e),s=Ce(e),n=Me(e),a=xe(e),o=Oe(e,s,n,a);return e.replaceWith(o),ae(o),Re(o,{sourceText:t,randomize:r,origin:s,submitEnabled:n,assessmentId:a}),o}function ue(e){const t=e||document;if(!t||!("querySelectorAll"in t))return[];const r=t.querySelectorAll("pre.a-quiz"),s=[];for(const n of r){if(!(n instanceof HTMLElement))continue;const a=ce(n);a&&s.push(a)}return s}typeof document<"u"&&ue(),N.mountAQuiz=ce,N.scanAndMountAQuizzes=ue,Object.defineProperty(N,Symbol.toStringTag,{value:"Module"})})(this.a_quiz=this.a_quiz||{});