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
| Shape Type |
Total Count |
Correctly Sorted |
`;
for (const [type, data] of Object.entries(this.gameStats.details)) {
const typeCapitalized = type.charAt(0).toUpperCase() + type.slice(1);
detailsHtml += `
| ${typeCapitalized}s |
${data.total} |
${data.sorted} |
`;
}
detailsHtml += `
`;
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');
}
});