"use strict";(self.webpackChunkWebComponents=self.webpackChunkWebComponents||[]).push([[566],{14566:(e,t,n)=>{n.r(t),n.d(t,{MatchingProblem:()=>s});var o=n(78673);class s extends o.A{constructor(e){super(e);let t=e.orig;this.containerDiv=e.orig;const n=t.querySelector("script");if(n){let e;try{e="text/xml"==n.type?function(e){const t=(new DOMParser).parseFromString(e,"text/html"),n=t.querySelector("parsererror");if(n)throw new Error("XML parse error: "+n.textContent);function o(e){return Array.from(t.querySelectorAll(e)).map((e=>{const t=e.querySelector("id"),n=e.querySelector("label");return{id:t?t.textContent.trim():"",label:n?n.innerHTML.trim():""}}))}return{statement:function(){const e=t.querySelector("statement");return e?e.innerHTML.trim():""}(),feedback:function(){const e=t.querySelector("feedback");return e?e.innerHTML.trim():""}(),left:o("premise"),right:o("response"),correctAnswers:Array.from(t.querySelectorAll("edge")).map((e=>Array.from(e.querySelectorAll("label")).slice(0,2).map((e=>e.textContent.trim()))))}}(n.textContent):JSON.parse(n.textContent),this.boxData=e}catch(e){console.error("Failed to parse boxData JSON:",e)}}this.divid=t.id,this.boxesRenderedPromise=new Promise((e=>{this.boxesRenderedResolve=e})),this.workspace=this.createWorkspace(t);try{this.statement=this.createStatement(t)}catch(e){console.error("Error setting statement:",e)}this.connList=this.createConnList(t),this.ariaLive=this.createAriaLive(t),this.controlDiv=this.createControlDiv(t),this.createHelpModal(),this.connections=[],this.allBoxes=[],this.selectedBox=null,this.startBox=null,this.tempLine=null,this.useRunestoneServices=eBookConfig.useRunestoneServices,this.graderactive=e.graderactive||!1,this.init(),this.boxesRenderedPromise.then((()=>{this.checkServer("matching",!0)}))}init(){this.shuffle(this.boxData.left),this.shuffle(this.boxData.right),this.renderBoxes(),this.attachEvents(),this.queueMathJax(this.containerDiv)}checkCurrentAnswer(){const e=this.boxData.correctAnswers,t=this.connections.map((e=>[e.fromBox.dataset.id,e.toBox.dataset.id])),n=e.filter((e=>t.some((t=>t[0]===e[0]&&t[1]===e[1])))),o=t.filter((t=>!e.some((e=>e[0]===t[0]&&e[1]===t[1]))));this.correctCount=n.length,this.incorrectCount=o.length,this.missingCount=e.length-this.correctCount,this.denominator=this.correctCount+this.incorrectCount+this.missingCount,this.scorePercent=0===this.denominator?0:Math.max(0,Math.min(100,Math.round(this.correctCount/this.denominator*100)))}async logCurrentAnswer(){let e={score:this.scorePercent,percent:this.scorePercent/100,correctCount:this.correctCount,incorrectCount:this.incorrectCount,missingCount:this.missingCount,connections:this.connections.map((e=>({from:e.fromBox.dataset.id,to:e.toBox.dataset.id}))),event:"matching"};e.div_id=this.divid,e.act=`score:${e.score} connections:${JSON.stringify(e.connections)}`,e.correct=100===e.score,e.answer=JSON.stringify({connections:e.connections}),await this.logBookEvent(e)}renderFeedback(){this.connections.forEach((e=>{const t=[e.fromBox.dataset.id,e.toBox.dataset.id],n=this.boxData.correctAnswers.some((e=>e[0]===t[0]&&e[1]===t[1]));e.line.classList.remove("correct","incorrect"),e.line.classList.add(n?"correct":"incorrect")})),this.connList.innerHTML=`Score: ${this.scorePercent}%
`,this.connList.innerHTML+=`
Correct: ${this.correctCount}`,this.connList.innerHTML+=`
Incorrect: ${this.incorrectCount}`,this.connList.innerHTML+=`
Missing: ${this.missingCount}`,100!==this.scorePercent&&(this.connList.innerHTML+=`
Feedback: ${this.boxData.feedback}
`),this.queueMathJax(this.connList)}createStatement(e){const t=document.createElement("div");return t.className="statement",t.classList.add("match_question"),t.classList.add("exercise-statement"),t.innerHTML=this.boxData.statement,e.insertBefore(t,e.firstChild),t}restoreAnswers(e){e&&(this.connections=e.answer.connections.map((e=>({fromBox:this.allBoxes.find((t=>t.dataset.id===e.from)),toBox:this.allBoxes.find((t=>t.dataset.id===e.to))}))),this.updateConnectionModel(),this.correct=e.correct),this.connections.forEach((e=>{const t=this.getRightBoxCenter(e.fromBox),n=this.getLeftBoxCenter(e.toBox),o=this.createLineElement(t.x,t.y,n.x,n.y);o.fromBox=e.fromBox,o.toBox=e.toBox,this.svg.appendChild(o),e.line=o}))}checkLocalStorage(){if(this.graderactive)return;const e=localStorage.getItem(this.divid);if(e){const t=JSON.parse(e);this.connections=t.connections.map((e=>({fromBox:this.allBoxes.find((t=>t.dataset.id===e.from)),toBox:this.allBoxes.find((t=>t.dataset.id===e.to))}))),this.updateConnectionModel(),this.correctCount=t.correctCount,this.incorrectCount=t.incorrectCount,this.missingCount=t.missingCount,this.scorePercent=t.score,this.restoreAnswers(),this.renderFeedback()}}setLocalStorage(){const e={connections:this.connections.map((e=>({from:e.fromBox.dataset.id,to:e.toBox.dataset.id}))),score:this.scorePercent,correctCount:this.correctCount,incorrectCount:this.incorrectCount,missingCount:this.missingCount};localStorage.setItem(this.divid,JSON.stringify(e))}disableInteraction(){}createWorkspace(e){const t=document.createElement("div");t.className="matching-workspace";const n=document.createElement("div");n.className="left-column",this.leftColumn=n;const o=document.createElementNS("http://www.w3.org/2000/svg","svg");o.classList.add("connector-svg"),this.svg=o;const s=document.createElement("div");return s.className="right-column",this.rightColumn=s,t.appendChild(n),t.appendChild(o),t.appendChild(s),e.insertBefore(t,e.firstChild),t}createConnList(e){const t=document.createElement("div");return t.className="conn-list",t.innerHTML="Connections:
",e.appendChild(t),t}createAriaLive(e){const t=document.createElement("div");return t.className="aria-live",t.setAttribute("aria-live","polite"),t.setAttribute("aria-atomic","true"),e.appendChild(t),t}createControlDiv(e){const t=document.createElement("div");t.className="control-div";const n=document.createElement("button");n.className="grade-button",n.textContent="Check Me",n.classList.add("btn","btn-success");const o=document.createElement("button");o.className="reset-button",o.textContent="Reset",o.classList.add("btn","btn-default");const s=document.createElement("button");return s.className="help-button",s.textContent="?",s.setAttribute("aria-label","Help"),t.appendChild(n),t.appendChild(o),t.appendChild(s),e.appendChild(t),n.addEventListener("click",(()=>this.gradeConnections())),o.addEventListener("click",(()=>this.resetConnections())),s.addEventListener("click",(()=>this.showHelp())),this.gradeBtn=n,this.resetBtn=o,this.helpBtn=s,t}createHelpModal(){this.helpModal=document.createElement("div"),this.helpModal.className="help-modal",this.helpModal.innerHTML='\n
\n \n

Click and drag between boxes to create connections.

\n

Use the tab key to navigate to a box and press Enter to select the box. Then tab to the connecting box and press Enter to create a connection between the two selected boxes.

\n

Click on a connection line to remove it. You can also use the tab key to select lines. Press the delete key to remove a selected line.

\n

Click the "Check Me" button to check your connections, and save your work.

\n

Click the "Reset" button to clear all connections.

\n
',this.containerDiv.appendChild(this.helpModal),this.helpModal.querySelector(".help-close").addEventListener("click",(()=>this.hideHelp()))}showHelp(){this.helpModal.style.display="flex"}hideHelp(){this.helpModal.style.display="none"}shuffle(e){for(let t=e.length-1;t>0;t--){const n=Math.floor(Math.random()*(t+1));[e[t],e[n]]=[e[n],e[t]]}return e}renderBoxes(){this.boxData.left.forEach((({id:e,label:t})=>{const n=this.createBox(e,t,"drag");this.leftColumn.appendChild(n),this.allBoxes.push(n)})),this.boxData.right.forEach((({id:e,label:t})=>{const n=this.createBox(e,t,"drop");this.rightColumn.appendChild(n),this.allBoxes.push(n)}));const e=Array.from(this.workspace.querySelectorAll("img"));0===e.length&&this.boxesRenderedResolve();const t=e.map((e=>"function"==typeof e.decode?e.decode():e.complete&&0!==e.naturalWidth?Promise.resolve():new Promise((t=>{e.addEventListener("load",(()=>t())),e.addEventListener("error",(()=>t()))}))));Promise.all(t).then((()=>{this.boxesRenderedResolve()}))}createBox(e,t,n){const o=document.createElement("div");return o.className="box",o.dataset.id=e,o.dataset.role=n,o.innerHTML=t,o.tabIndex=0,o.setAttribute("role","button"),o.setAttribute("aria-label",`${"drag"===n?"Draggable":"Droppable"}: ${t}`),o}getCenter(e){const t=e.getBoundingClientRect(),n=this.workspace.getBoundingClientRect();return{x:t.left-n.left+t.width/2,y:t.top-n.top+t.height/2}}getRightBoxCenter(e){const t=e.getBoundingClientRect(),n=this.workspace.getBoundingClientRect();return{x:t.left-n.left+t.width,y:t.top-n.top+t.height/2}}getLeftBoxCenter(e){const t=e.getBoundingClientRect(),n=this.workspace.getBoundingClientRect();return{x:t.left-n.left,y:t.top-n.top+t.height/2}}createLineElement(e,t,n,o){const s=document.createElementNS("http://www.w3.org/2000/svg","line");return s.setAttribute("x1",e),s.setAttribute("y1",t),s.setAttribute("x2",n),s.setAttribute("y2",o),s.setAttribute("class","line"),s.setAttribute("tabindex","0"),s.setAttribute("focusable","true"),s.setAttribute("role","button"),s.setAttribute("aria-label","Connection line. Press Delete to remove."),s.addEventListener("click",(()=>{this.removeLine(s)})),s.addEventListener("keydown",(e=>{"Delete"!==e.key&&"Backspace"!==e.key||(e.preventDefault(),this.removeLine(s))})),s}removeLine(e){this.svg.removeChild(e);const t=this.connections.findIndex((t=>t.fromBox===e.fromBox&&t.toBox===e.toBox||t.fromBox===e.toBox&&t.toBox===e.fromBox));-1!==t&&this.connections.splice(t,1),this.updateConnectionModel()}isConnected(e,t){return this.connections.some((n=>n.fromBox===e&&n.toBox===t||n.fromBox===t&&n.toBox===e))}createPermanentLine(e,t){if(e.dataset.role===t.dataset.role)return void alert("You can only connect a draggable to a droppable.");if("drop"===e.dataset.role&&([e,t]=[t,e]),this.isConnected(e,t))return;const n=this.getRightBoxCenter(e),o=this.getLeftBoxCenter(t),s=this.createLineElement(n.x,n.y,o.x,o.y);s.fromBox=e,s.toBox=t,this.svg.appendChild(s),this.connections.push({fromBox:e,toBox:t,line:s}),this.updateConnectionModel(),this.isAnswered=!0,this.ariaLive&&(this.ariaLive.textContent=`Connected ${e.textContent} to ${t.textContent}`)}updateConnectionModel(){this.connList.innerHTML="Connections:
",this.connections.forEach((e=>{const t=e.fromBox.textContent;let n=e.toBox.textContent;n||(n=e.toBox.querySelector("img").alt);const o=document.createElement("div");o.className="conn-entry",o.textContent=`${t} → ${n}`,this.connList.appendChild(o)}))}gradeConnections(){this.checkCurrentAnswer(),this.renderFeedback(),this.logCurrentAnswer(),this.setLocalStorage()}resetConnections(){this.connections.forEach((e=>{e.line&&e.line.parentNode===this.svg&&this.svg.removeChild(e.line)})),this.connections.length=0,this.updateConnectionModel(),this.ariaLive&&(this.ariaLive.textContent="All connections have been cleared.")}attachEvents(){this.allBoxes.forEach((e=>{e.addEventListener("pointerdown",(t=>{t.ctrlKey||t.metaKey;{t.preventDefault(),this.startBox=e;const n=this.getRightBoxCenter(this.startBox);this.tempLine=this.createLineElement(n.x,n.y,n.x,n.y),this.tempLine.setAttribute("stroke","gray"),this.tempLine.setAttribute("stroke-dasharray","4"),this.svg.appendChild(this.tempLine),document.addEventListener("pointermove",this.updateTempLine),document.addEventListener("pointerup",this.finishConnection)}})),e.addEventListener("keydown",(t=>{if("Enter"===t.key)if(t.preventDefault(),this.selectedBox){e!==this.selectedBox&&this.createPermanentLine(this.selectedBox,e),this.selectedBox.classList.remove("selected"),this.selectedBox=null;const t=this.allBoxes.indexOf(e),n=this.allBoxes[t+1];n?n.focus():this.allBoxes[0].focus()}else this.selectedBox=e,e.classList.add("selected")})),e.addEventListener("mouseenter",(()=>{this.connections.forEach((t=>{t.fromBox===e||t.toBox===e?(t.line.classList.add("highlighted"),t.line.classList.remove("faded")):(t.line.classList.add("faded"),t.line.classList.remove("highlighted"))}))})),e.addEventListener("mouseleave",(()=>{this.connections.forEach((e=>{e.line.classList.remove("highlighted","faded")}))}))}));const e=this.containerDiv.querySelector(".grade-button"),t=this.containerDiv.querySelector(".reset-button");e&&e.addEventListener("click",(()=>this.gradeConnections())),t&&t.addEventListener("click",(()=>this.resetConnections())),window.addEventListener("resize",(()=>{this.connections.forEach((e=>{const t=this.getRightBoxCenter(e.fromBox),n=this.getLeftBoxCenter(e.toBox);e.line.setAttribute("x1",t.x),e.line.setAttribute("y1",t.y),e.line.setAttribute("x2",n.x),e.line.setAttribute("y2",n.y)}))}))}updateTempLine=e=>{if(e.preventDefault(),!this.startBox||!this.tempLine)return;const t=this.getRightBoxCenter(this.startBox);this.tempLine.setAttribute("x1",t.x),this.tempLine.setAttribute("y1",t.y);const n=this.workspace.getBoundingClientRect(),o=e.clientX-n.left,s=e.clientY-n.top;this.tempLine.setAttribute("x2",o),this.tempLine.setAttribute("y2",s)};finishConnection=e=>{e.preventDefault(),this.tempLine&&(this.svg.removeChild(this.tempLine),this.tempLine=null);const t=e.clientX||e.changedTouches&&e.changedTouches[0].clientX,n=e.clientY||e.changedTouches&&e.changedTouches[0].clientY,o=document.elementFromPoint(t,n),s=this.allBoxes.find((e=>e.contains(o)&&e!==this.startBox));this.startBox&&s&&this.createPermanentLine(this.startBox,s),this.startBox=null,document.removeEventListener("pointermove",this.updateTempLine),document.removeEventListener("pointerup",this.finishConnection)}}document.addEventListener("runestone:login-complete",(()=>{document.querySelectorAll('[data-component="matching"]').forEach((e=>{if(!e.closest("[data-component=timedAssessment]")){let t={orig:e};window.componentMap[e.id]=new s(t)}}))})),void 0===window.component_factory&&(window.component_factory={}),window.component_factory.matching=function(e){return new s(e)}}}]); //# sourceMappingURL=566.750e5a3f55fac7c5.js.map