Problem-Based Learning (PBL) Scenario Realism Indexer
Step 1: Paste Your PBL Scenario
Step 2: Evaluate Realism Criteria
Check all criteria that your scenario successfully meets. (Customize these in the 'Data Configuration' tab).
Your results will appear here. Fill out the form in Tab 1 and click "Calculate".
Manage Realism Criteria
Add, edit, or remove the criteria used to score scenarios. "Weight" (1-5) determines how much each criterion affects the total score. (Spec #4, #6)
Saved!
${scenarioText}
`; pblResultsContent.innerHTML = resultsHTML; // --- Update PDF Content --- pdfOutputContent.innerHTML = `PBL Scenario Realism Report
Realism Index: ${percentage}%
This score is based on a weighted calculation of ${pblData.length} criteria, totaling ${maxScore} possible points. The scenario scored ${score} points.
Strengths (Met Criteria)
- ${metCriteria.length === 0 ? '
- None ' : metCriteria.map(item => `
- ${item.name} `).join("")}
Weaknesses (Missing Criteria)
- ${missingCriteria.length === 0 ? '
- None ' : missingCriteria.map(item => `
- ${item.name} `).join("")}
Submitted Scenario
${scenarioText}
`; showPBLTab('pbl-tab-results'); } /** * Switches the active tab * (Spec II.B.4) */ window.showPBLTab = function (tabId) { tabContents.forEach((content) => { content.classList.remove("active"); }); tabButtons.forEach((button) => { button.classList.remove("active"); }); const contentToShow = document.getElementById(tabId); const buttonToActivate = document.querySelector( `[onclick="showPBLTab('${tabId}')"]` ); if (contentToShow) contentToShow.classList.add("active"); if (buttonToActivate) buttonToActivate.classList.add("active"); if (tabId === "pbl-tab-config") { buildConfig(); } }; window.showPBLTab = showPBLTab; // Make global /** * Navigates between tabs using Next/Previous buttons * (Spec II.B.4.o) */ window.navigatePBLTabs = function (direction) { let currentIndex = -1; tabButtons.forEach((button, index) => { if (button.classList.contains("active")) { currentIndex = index; } }); if (currentIndex === -1) return; let nextIndex; if (direction === "next") { nextIndex = (currentIndex + 1) % tabButtons.length; } else { nextIndex = (currentIndex - 1 + tabButtons.length) % tabButtons.length; } const nextButton = tabButtons[nextIndex]; const onclickAttr = nextButton.getAttribute("onclick"); const tabId = onclickAttr.match(/'([^']*)'/)[1]; if (tabId) showPBLTab(tabId); }; window.navigatePBLTabs = navigatePBLTabs; // Make global /** * Downloads the output as a PDF * (Spec II.C) */ function downloadPBLPDF() { if ( typeof jspdf === "undefined" || typeof html2canvas === "undefined" ) { console.error("PDF libraries not loaded."); return; } if (!pdfOutputContent.innerHTML.trim() || pdfOutputContent.children.length === 0) { console.error("No report content to download."); return; } const { jsPDF } = jspdf; const pdfOutputElement = document.getElementById("pdf-output-content"); pdfOutputElement.style.display = "block"; pdfOutputElement.style.position = "absolute"; pdfOutputElement.style.left = "-9999px"; html2canvas(pdfOutputElement, { scale: 2, backgroundColor: "#ffffff", }).then((canvas) => { pdfOutputElement.style.display = "none"; pdfOutputElement.style.position = "static"; const imgData = canvas.toDataURL("image/png"); const pdf = new jsPDF({ orientation: "p", unit: "px", format: "a4", }); const pdfWidth = pdf.internal.pageSize.getWidth(); const pdfHeight = pdf.internal.pageSize.getHeight(); const canvasWidth = canvas.width; const canvasHeight = canvas.height; const ratio = canvasWidth / canvasHeight; const imgWidth = pdfWidth - 40; // 20px margin const imgHeight = imgWidth / ratio; const pageMargin = 20; if (imgHeight <= pdfHeight - 2 * pageMargin) { pdf.addImage(imgData, "PNG", pageMargin, pageMargin, imgWidth, imgHeight); } else { // Handle multiple pages let heightLeft = canvasHeight; let canvasPosition = 0; const pageHeightInPixels = (pdfHeight - 2 * pageMargin) * (canvasWidth / imgWidth); while (heightLeft > 0.1) { const pageHeight = Math.min(heightLeft, pageHeightInPixels); const pageImgHeight = (pageHeight * imgWidth) / canvasWidth; const tempCanvas = document.createElement("canvas"); tempCanvas.width = canvasWidth; tempCanvas.height = pageHeight; const ctx = tempCanvas.getContext("2d"); ctx.drawImage( canvas, 0, canvasPosition, canvasWidth, pageHeight, 0, 0, canvasWidth, pageHeight ); const pageImgData = tempCanvas.toDataURL("image/png"); pdf.addImage( pageImgData, "PNG", pageMargin, pageMargin, imgWidth, pageImgHeight ); heightLeft -= pageHeight; canvasPosition += pageHeight; if (heightLeft > 0.1) pdf.addPage(); } } pdf.save("pbl-realism-report.pdf"); }); } // --- 5. Event Listeners (Spec IV.C) --- calculateScoreBtn.addEventListener("click", calculateScore); pdfDownloadBtn.addEventListener("click", downloadPBLPDF); addCriterionBtn.addEventListener("click", window.addPBLCriterion); saveConfigBtn.addEventListener("click", window.savePBLConfig); // --- 6. Initialization --- loadData(); buildDashboard(); buildConfig(); // Build config once to have data ready showPBLTab("pbl-tab-dashboard"); });