Shape Sorter

Shape Sorter

Correct: 0
Incorrect Attempts: 0
Remaining: 0

Go to 'Game Settings' to start a new game!

Configure Your Game

All shapes sorted! Well done!

`; } }, flashFeedback: function(element, type) { const className = `feedback-${type}`; element.classList.add(className); setTimeout(() => { element.classList.remove(className); }, 500); }, // --- PDF Download Functionality --- generatePdfReportHtml: function() { if (Object.keys(this.gameStats).length === 0) { alert("Please start and play a game first to generate a report."); return null; } const accuracy = (this.gameStats.totalShapes + this.gameStats.incorrectAttempts) === 0 ? 0 : (this.gameStats.correct / (this.gameStats.correct + this.gameStats.incorrectAttempts)) * 100; let summaryHtml = `

Game Summary

Metric Value
Total Shapes ${this.gameStats.totalShapes}
Correctly Sorted ${this.gameStats.correct}
Incorrect Attempts ${this.gameStats.incorrectAttempts}
Overall Accuracy ${accuracy.toFixed(1)}%
`; let detailsHtml = `

Detailed Breakdown

`; for (const [type, data] of Object.entries(this.gameStats.details)) { const typeCapitalized = type.charAt(0).toUpperCase() + type.slice(1); detailsHtml += ` `; } detailsHtml += `
Shape Type Total Count Correctly Sorted
${typeCapitalized}s ${data.total} ${data.sorted}
`; return `

Shape Sorter Results

${summaryHtml} ${detailsHtml}
`; }, downloadPDF: function() { const { jsPDF } = window.jspdf; const html2canvas = window.html2canvas; if (!jsPDF || !html2canvas) { alert("PDF generation libraries are not loaded. Please try again."); return; } const reportHtml = this.generatePdfReportHtml(); if (!reportHtml) return; const pdfContainer = document.createElement('div'); pdfContainer.style.position = 'absolute'; pdfContainer.style.left = '-9999px'; pdfContainer.style.top = '0'; pdfContainer.innerHTML = reportHtml; document.body.appendChild(pdfContainer); const contentToCapture = pdfContainer.querySelector('.ss-pdf-output'); if (!contentToCapture) { document.body.removeChild(pdfContainer); return; } html2canvas(contentToCapture, { scale: 2 }) .then(canvas => { const doc = new jsPDF({ orientation: 'p', unit: 'px', format: 'a4' }); const imgData = canvas.toDataURL('image/png'); const imgProps = doc.getImageProperties(imgData); const pdfWidth = doc.internal.pageSize.getWidth(); const pdfHeight = (imgProps.height * pdfWidth) / imgProps.width; let heightLeft = pdfHeight; let position = 0; doc.addImage(imgData, 'PNG', 0, position, pdfWidth, pdfHeight); heightLeft -= doc.internal.pageSize.getHeight(); while (heightLeft >= 0) { position = heightLeft - pdfHeight; doc.addPage(); doc.addImage(imgData, 'PNG', 0, position, pdfWidth, pdfHeight); heightLeft -= doc.internal.pageSize.getHeight(); } doc.save('Shape_Sorter_Results.pdf'); document.body.removeChild(pdfContainer); }) .catch(err => { console.error("Error generating PDF:", err); alert("An error occurred while generating the PDF."); if (document.body.contains(pdfContainer)) { document.body.removeChild(pdfContainer); } }); }, // --- Initialization --- init: function() { this.elements = { container: document.getElementById('shape-sorter-tool'), tabContents: document.querySelectorAll('.ss-tab-content'), tabButtons: document.querySelectorAll('.ss-tab-button'), prevButton: document.getElementById('ss-prev-btn'), nextButton: document.getElementById('ss-next-btn'), // Dashboard scoreCorrect: document.getElementById('ss-score-correct'), scoreIncorrect: document.getElementById('ss-score-incorrect'), scoreRemaining: document.getElementById('ss-score-remaining'), unsortedPen: document.getElementById('ss-unsorted-pen'), binsArea: document.getElementById('ss-bins-area'), // Settings shapeCount: document.getElementById('ss-shape-count'), shapeToggles: document.querySelectorAll('.ss-shape-toggle'), // Colors for JS correctColor: getComputedStyle(document.documentElement).getPropertyValue('--ss-correct-color') }; // Set initial state this.openTab('game-dashboard', 0); } }; // Run the init function after the DOM is fully loaded document.addEventListener('DOMContentLoaded', function() { if (!document.getElementById('shape-sorter-tool').classList.contains('ss-initialized')) { ssApp.init(); document.getElementById('shape-sorter-tool').classList.add('ss-initialized'); } });