`;
list.appendChild(item);
});
}
function renderPaperPreview(paper) {
const previewContainer = document.getElementById('paperPreview');
const pdfContainer = document.getElementById('pdf-exam-paper');
if (!paper) {
previewContainer.innerHTML = '
`;
sections.forEach(section => {
if (section.questions.length > 0) {
html += `
`;
}
});
previewContainer.innerHTML = html;
pdfContainer.innerHTML = html; // Also render to the hidden PDF div
// Update total marks in both previews
const marksText = `Total Marks: ${totalMarks}`;
document.getElementById('totalMarksPreview').innerHTML = marksText;
const pdfMarksElem = pdfContainer.querySelector('#totalMarksPreview');
if(pdfMarksElem) pdfMarksElem.innerHTML = marksText;
}
// --- LOGIC & EVENT HANDLERS ---
function updateTabs() {
tabs.forEach(tab => tab.classList.toggle('active', parseInt(tab.dataset.tab) === currentTab));
tabPanes.forEach(pane => pane.classList.toggle('hidden', parseInt(pane.id.split('-')[1]) !== currentTab));
prevBtn.disabled = currentTab === 1;
nextBtn.disabled = currentTab === totalTabs;
}
function goToTab(tabNumber) {
if (tabNumber >= 1 && tabNumber <= totalTabs) {
currentTab = tabNumber;
updateTabs();
}
}
function addQuestion() {
const text = document.getElementById('questionText').value.trim();
const type = document.getElementById('questionType').value;
const topic = document.getElementById('questionTopic').value.trim();
const marks = parseInt(document.getElementById('questionMarks').value);
const mcqOptionsRaw = document.getElementById('mcqOptions').value.trim();
if (!text || !topic || isNaN(marks)) {
alert('Please fill all fields: Question, Topic, and Marks.');
return;
}
if (type === 'mcq' && !mcqOptionsRaw) {
alert('Please provide comma-separated options for MCQ questions.');
return;
}
const newId = appData.questionBank.length > 0 ? Math.max(...appData.questionBank.map(q => q.id)) + 1 : 1;
const newQuestion = { id: newId, text, type, topic, marks };
if (type === 'mcq') {
newQuestion.options = mcqOptionsRaw.split(',').map(opt => opt.trim());
}
appData.questionBank.push(newQuestion);
renderQuestionBankList();
// Clear inputs
document.getElementById('questionText').value = '';
document.getElementById('questionTopic').value = '';
document.getElementById('questionMarks').value = '';
document.getElementById('mcqOptions').value = '';
}
function deleteQuestion(questionId) {
appData.questionBank = appData.questionBank.filter(q => q.id !== questionId);
renderQuestionBankList();
}
function generatePaper() {
// 1. Update details from inputs
appData.examDetails.title = document.getElementById('examTitle').value;
appData.examDetails.courseName = document.getElementById('courseName').value;
appData.examDetails.duration = document.getElementById('examDuration').value;
appData.examDetails.instructions = document.getElementById('examInstructions').value;
// 2. Get requested number of questions
const numMcq = parseInt(document.getElementById('generateNumMcq').value) || 0;
const numShort = parseInt(document.getElementById('generateNumShort').value) || 0;
const numLong = parseInt(document.getElementById('generateNumLong').value) || 0;
// 3. Filter and select questions randomly
const selectRandomQuestions = (type, count) => {
const filtered = appData.questionBank.filter(q => q.type === type);
return filtered.sort(() => 0.5 - Math.random()).slice(0, count);
};
const mcqSection = { title: 'Section A: Multiple Choice Questions', questions: selectRandomQuestions('mcq', numMcq) };
const shortSection = { title: 'Section B: Short Answer Questions', questions: selectRandomQuestions('short', numShort) };
const longSection = { title: 'Section C: Essay Questions', questions: selectRandomQuestions('long', numLong) };
appData.generatedPaper = {
details: appData.examDetails,
sections: [mcqSection, shortSection, longSection]
};
renderPaperPreview(appData.generatedPaper);
document.getElementById('downloadPdfBtn').disabled = false;
}
function downloadPdf() {
if (!appData.generatedPaper) {
alert('Please generate the paper first.');
return;
}
const elementToCapture = document.getElementById('pdf-exam-paper');
html2canvas(elementToCapture, { scale: 2, windowWidth: elementToCapture.scrollWidth, windowHeight: elementToCapture.scrollHeight }).then(canvas => {
const imgData = canvas.toDataURL('image/png');
const { jsPDF } = window.jspdf;
const pdf = new jsPDF({ orientation: 'portrait', unit: 'in', format: 'letter' });
const pdfWidth = pdf.internal.pageSize.getWidth();
const pdfHeight = pdf.internal.pageSize.getHeight();
const imgWidth = canvas.width / 200; // Approximate conversion from pixels to inches
const imgHeight = canvas.height / 200;
const ratio = imgWidth / imgHeight;
let finalImgHeight = pdfHeight;
let finalImgWidth = finalImgHeight * ratio;
if (finalImgWidth > pdfWidth) {
finalImgWidth = pdfWidth;
finalImgHeight = finalImgWidth / ratio;
}
let heightLeft = imgHeight;
let position = 0;
pdf.addImage(imgData, 'PNG', 0, position, pdfWidth, imgHeight);
heightLeft -= pdfHeight;
while (heightLeft > 0) {
position = heightLeft - imgHeight;
pdf.addPage();
pdf.addImage(imgData, 'PNG', 0, position, pdfWidth, imgHeight);
heightLeft -= pdfHeight;
}
pdf.save(`${appData.examDetails.title.replace(/\s+/g, '-')}.pdf`);
});
}
// --- EVENT LISTENERS ---
tabs.forEach(tab => tab.addEventListener('click', (e) => goToTab(parseInt(e.currentTarget.dataset.tab))));
prevBtn.addEventListener('click', () => goToTab(currentTab - 1));
nextBtn.addEventListener('click', () => goToTab(currentTab + 1));
document.getElementById('addQuestionBtn').addEventListener('click', addQuestion);
document.getElementById('generatePaperBtn').addEventListener('click', generatePaper);
document.getElementById('downloadPdfBtn').addEventListener('click', downloadPdf);
document.getElementById('questionBankList').addEventListener('click', (e) => {
if (e.target.classList.contains('delete-question-btn')) {
deleteQuestion(parseInt(e.target.dataset.questionId));
}
});
document.getElementById('questionType').addEventListener('change', (e) => {
document.getElementById('mcqOptionsContainer').style.display = e.target.value === 'mcq' ? 'block' : 'none';
});
// --- INITIALIZATION ---
renderAll();
updateTabs();
document.getElementById('mcqOptionsContainer').style.display = 'block'; // Default view
});
Click "Generate Exam Paper" to create a preview.
'; pdfContainer.innerHTML = ''; return; } const { details, sections } = paper; let totalMarks = 0; let html = `${details.title}
${details.courseName}
Duration: ${details.duration} minutes
Instructions:
${details.instructions}
${section.title}
`; section.questions.forEach((q, index) => { totalMarks += q.marks; html += `
${index + 1}.
`;
if (q.type === 'mcq' && q.options) {
html += ``;
}
});
html += `${q.text}
[${q.marks}]
