// Import Firebase functions import { initializeApp } from "https://www.gstatic.com/firebasejs/9.6.1/firebase-app.js"; import { getStorage, ref, getDownloadURL, listAll } from "https://www.gstatic.com/firebasejs/9.6.1/firebase-storage.js"; // Declare startTimer globally let startTimer = null; // Timer-related variables let totalMinutes = 61; // 181 minutes let timeLeft = totalMinutes * 60; // Convert to seconds let timerId; let timerKey = 'JEE 11'; // Unique key for the 120-min timer let timeDetailMessage = ""; // Global variable to store time details // Check if time exists in localStorage if (localStorage.getItem(timerKey)) { timeLeft = parseInt(localStorage.getItem(timerKey), 10); } // Function to start the timer startTimer = function () { if (!document.getElementById('time_left')) return; // ✅ Prevents error on `index.html` timerId = setInterval(function () { let minutes = Math.floor(timeLeft / 60); let seconds = timeLeft % 60; // Display the timer document.getElementById('time_left').innerHTML = `Time Left: ${minutes}m ${seconds < 10 ? '0' : ''}${seconds}s`; // Save the time left in localStorage localStorage.setItem(timerKey, timeLeft); if (timeLeft <= 0) { clearInterval(timerId); autoSubmit(); localStorage.removeItem(timerKey); } timeLeft--; }, 1000); }; // Function to stop the timer function stopTimer() { clearInterval(timerId); localStorage.removeItem(timerKey); const totalSeconds = totalMinutes * 60; const timeTakenSeconds = totalSeconds - timeLeft; const minutesTaken = Math.floor(timeTakenSeconds / 60); const secondsTaken = timeTakenSeconds % 60; timeDetailMessage = `Test duration: ${totalMinutes} minutes. Time taken: ${minutesTaken} minutes and ${secondsTaken} seconds.`; console.log(timeDetailMessage); } // Function to handle auto submission function autoSubmit() { alert("Time is over! Submitting the test automatically."); document.getElementById('submit').click(); } // ✅ Ensure this runs only if `time_left` exists window.onload = function () { if (document.getElementById('time_left')) { startTimer(); } }; // ✅ Ensure `submit` button exists before attaching event listener document.addEventListener("DOMContentLoaded", function () { let submitButton = document.getElementById('submit'); if (submitButton) { submitButton.onclick = stopTimer; } }); // Login handler (assuming there's a login form) export function handleLogin(event) { event.preventDefault(); // Prevent form submission console.log("Login function triggered"); const userId = document.getElementById('userId').value; const password = document.getElementById('password').value; // Basic validation to check if the fields are filled if (userId === "" || password === "") { alert("Please fill in both the ID and Password."); return false; } // Object with valid usernames and their respective passwords const validCredentials = { "ROHIT01": "ROHIT01", "ARYAN01": "ARYAN01", "SAMPAUL01": "SAMPAUL01", "KARTIK01": "KARTIK01", "RAVI01": "RAVI01", "VINEET01": "VINEET01", "SHANTANU01": "SHANTANU01", "SAGAR01": "SAGAR01", "KESHAV01": "KESHAV01", "jee2025": "jee2025", "jee02": "124", "jee03": "125", "jee04": "126" }; // Check if the entered username exists in the object and if the password matches if (validCredentials[userId] && validCredentials[userId] === password) { // If login is successful window.location.href = "exam.html"; // Redirect to another page } else { // If login fails alert("Invalid Username or Password. Hands' up, you are going to be arrested!"); } } document.addEventListener('DOMContentLoaded', function () { let currentSection = "phySec1"; // Default section let quizSubmitted = false; // Track whether the quiz has been submitted const sectionData = { phySec1: [], phySec2: [] // bioSec1: [] }; // Function to generate URLs based on question number function generateUrl(section, questionNumber) { return `https://firebasestorage.googleapis.com/v0/b/mentorsmantratestportal1.appspot.com/o/${section}%2F${questionNumber}.png?alt=media`; } // Populate phySec1 for (let i = 1; i <= 20; i++) { sectionData.phySec1.push({ questionNumber: i, url // : i === 2 // ? "https://firebasestorage.googleapis.com/v0/b/mentorsmantratestportal1.appspot.com/o/WPE%20%2B%20CIRCULAR%20MAINS%20TEST%2FCOM%20ADV%20QUES%2F1.jpeg?alt=media&token=e7d8978a-7339-4eb2-b791-bf7c5f205686" : generateUrl('NLM', i), // Default URL for other questions options // : i === 3 ? ["1/5", "1/10", "1/20", "1/15"] : ["A", "B", "C", "D"], // Custom options for question 2 correctAnswer: [ /*1*/ "C", /*2*/ "C", /*3*/ "A", /*4*/ "A", /*5*/ "B", /*6*/ "D", /*7*/ "D", /*8*/ "D", /*9*/ "B", /*10*/ "D", /*11*/ "C", /*12*/ "B", /*13*/ "D", /*14*/ "B", /*15*/ "D", /*16*/ "C", /*17*/ "A", /*18*/ "A", /*19*/ "B", /*20*/ "B" ][i - 1] // Adjust correct answers as needed }); } // Populate phySec2 const phySec2CorrectAnswers = [ /*1*/ 4, /*2*/ 5, /*3*/ 4, /*4*/ 3, /*5*/ 5]; for (let i = 21; i <= 25; i++) { sectionData.phySec2.push({ questionNumber: i, url: generateUrl('NLM', i), correctAnswer: phySec2CorrectAnswers[i - 21] // Adjusting the index to start from 0 }); } const sectionQuestionIndex = { phySec1: 0, phySec2: 0 }; const selectedAnswers = {}; const markedForReview = {}; // New object to track marked for review const isVisited = {}; const smarkedForReview = {}; let nselectedAnswers=0; let nmarkedForReview=0; let nisVisited=0; let nsmarkedForReview=0; // Add the getAnswersData function here function getAnswersData() { const userAnswers = []; const correctAnswers = []; // Iterate through each section Object.keys(sectionData).forEach(section => { sectionData[section].forEach((question, index) => { // Get the user's answer (if any) const userAnswer = selectedAnswers[section] ? selectedAnswers[section][index] : null; userAnswers.push(userAnswer); // Get the correct answer const correctAnswer = question.correctAnswer; correctAnswers.push(correctAnswer); }); }); return { selectedAnswers: userAnswers, correctAnswers: correctAnswers }; } const saveButton = document.getElementById('favourite'); const saveAndNextButton = document.getElementById('next'); const smarkforreviewAndNextButton = document.getElementById('smfran'); const markforreviewAndNextButton = document.getElementById('mfran'); const clearResponseButton = document.getElementById('cr'); const previousButton = document.getElementById('previous'); const unsNextButton = document.getElementById('next_u'); const submitButton = document.getElementById('submit'); // Assuming there's a submit button saveButton.addEventListener('click', saveCurrentQuestion); saveAndNextButton.addEventListener('click', saveAndNextQuestion); markforreviewAndNextButton.addEventListener('click', markforreviewAndNextQuestion); smarkforreviewAndNextButton.addEventListener('click', smarkforreviewAndNextQuestion); clearResponseButton.addEventListener('click', clearResponse); previousButton.addEventListener('click', goToPreviousQuestion); unsNextButton.addEventListener('click', goToNextQuestion); submitButton.addEventListener('click', submitQuiz); function saveCurrentQuestion() { if (currentSection.includes("Sec2")) { // For Section 2, save numerical answer const numericalAnswer = document.getElementById('numerical-answer').value; if (numericalAnswer) { if (!selectedAnswers[currentSection]) { selectedAnswers[currentSection] = {}; } if(!selectedAnswers[currentSection][sectionQuestionIndex[currentSection]]){ nselectedAnswers++; } selectedAnswers[currentSection][sectionQuestionIndex[currentSection]] = numericalAnswer; } } else { // For Section 1, save MCQ answers as before const selectedOption = document.querySelector(`input[name="option${sectionQuestionIndex[currentSection]}"]:checked`); if (selectedOption) { if (!selectedAnswers[currentSection]) { selectedAnswers[currentSection] = {}; } if(!selectedAnswers[currentSection][sectionQuestionIndex[currentSection]]){ nselectedAnswers++; } selectedAnswers[currentSection][sectionQuestionIndex[currentSection]] = selectedOption.value; } } updatePaletteItems(); } function markforreviewAndNextQuestion() { // Initialize the review tracking for the current section if not already done if (!markedForReview[currentSection]) { markedForReview[currentSection] = {}; } // Set the current question as marked for review if(!markedForReview[currentSection][sectionQuestionIndex[currentSection]]){ nmarkedForReview++; } markedForReview[currentSection][sectionQuestionIndex[currentSection]] = true; updatePaletteItems(); // Update the palette to reflect the change goToNextQuestion(); } function smarkforreviewAndNextQuestion(){ saveCurrentQuestion(); if (!smarkedForReview[currentSection]) { smarkedForReview[currentSection] = {}; } // Set the current question as marked for review if(!smarkedForReview[currentSection][sectionQuestionIndex[currentSection]]){ nsmarkedForReview++; } smarkedForReview[currentSection][sectionQuestionIndex[currentSection]] = true; updatePaletteItems(); // Update the palette to reflect the change goToNextQuestion(); } function saveAndNextQuestion() { saveCurrentQuestion(); if (!markedForReview[currentSection]) { markedForReview[currentSection] = {}; } if (!smarkedForReview[currentSection]) { smarkedForReview[currentSection] = {}; } if(markedForReview[currentSection][sectionQuestionIndex[currentSection]]){ nmarkedForReview--; } markedForReview[currentSection][sectionQuestionIndex[currentSection]] = false; if(smarkedForReview[currentSection][sectionQuestionIndex[currentSection]]){ smarkedForReview[currentSection][sectionQuestionIndex[currentSection]] = true; } goToNextQuestion(); } function goToNextQuestion() { const currentIndex = sectionQuestionIndex[currentSection]; if (currentIndex < sectionData[currentSection].length - 1) { sectionQuestionIndex[currentSection]++; updateQuestionDisplay(); updatePaletteItems(); // Update palette colors } else { const nextSection = getNextSection(); if (nextSection) { switchSection(nextSection); } } } function goToPreviousQuestion() { const currentIndex = sectionQuestionIndex[currentSection]; if (currentIndex > 0) { sectionQuestionIndex[currentSection]--; updateQuestionDisplay(); updatePaletteItems(); // Update palette colors } } function clearResponse() { // Clear selected option for the current question document.querySelectorAll(`input[name="option${sectionQuestionIndex[currentSection]}"]`).forEach(input => { input.checked = false; // Uncheck the radio buttons }); if (selectedAnswers[currentSection]) { if(selectedAnswers[currentSection][sectionQuestionIndex[currentSection]]){ nselectedAnswers--; } selectedAnswers[currentSection][sectionQuestionIndex[currentSection]] = null; // Clear the selected answer } // Update the palette items to reflect the cleared state updatePaletteItems(); status(); } function updateQuestionDisplay() { const currentQuestionData = sectionData[currentSection][sectionQuestionIndex[currentSection]]; const questionImage = document.getElementById('q1'); // Update the image source questionImage.src = currentQuestionData.url; // Reset any previously applied inline styles questionImage.style.height = ""; questionImage.style.width = ""; // Apply specific dimensions for Phy Sec 1, Q15 if (currentSection === "phySec1" && sectionQuestionIndex[currentSection] === 30) { // Index starts from 0 questionImage.style.height = "450px"; // Custom height questionImage.style.width = "460px"; // Custom width }else if (currentSection === "phySec2" && sectionQuestionIndex[currentSection] === 1) { // Index starts from 0 questionImage.style.height = "450px"; // Custom height questionImage.style.width = "460px"; // Custom width }else if (currentSection === "chemSec2" && sectionQuestionIndex[currentSection] === 32) { // Index starts from 0 questionImage.style.height = "450px"; // Custom height questionImage.style.width = "460px"; // Custom width }else if (currentSection === "mathsSec2" && sectionQuestionIndex[currentSection] === 1) { // Index starts from 0 questionImage.style.height = "450px"; // Custom height questionImage.style.width = "460px"; // Custom width } else if (currentSection.includes("Sec2")) { // Numerical question questionImage.classList.add('numerical-image'); questionImage.classList.remove('mcq-image'); } else { // MCQ question questionImage.classList.add('mcq-image'); questionImage.classList.remove('numerical-image'); } document.getElementById('question-title').textContent = `Question no. ${sectionQuestionIndex[currentSection] + 1}`; const optionsContainer = document.querySelector('.answers'); optionsContainer.innerHTML = ""; // Clear previous content if (currentSection.includes("Sec2")) { // For Section 2, show a numerical input field const inputField = document.createElement('input'); inputField.type = 'number'; inputField.id = 'numerical-answer'; inputField.style.width = "200px"; inputField.style.height = "40px"; inputField.placeholder = 'Enter your answer'; if (selectedAnswers[currentSection] && selectedAnswers[currentSection][sectionQuestionIndex[currentSection]] !== undefined) { inputField.value = selectedAnswers[currentSection][sectionQuestionIndex[currentSection]]; } optionsContainer.appendChild(inputField); } else { // For Section 1, display MCQs as usual currentQuestionData.options.forEach((option, index) => { const label = document.createElement('label'); label.innerHTML = ` ${option}`; optionsContainer.appendChild(label); }); if (selectedAnswers[currentSection] && selectedAnswers[currentSection][sectionQuestionIndex[currentSection]] !== undefined) { const selectedValue = selectedAnswers[currentSection][sectionQuestionIndex[currentSection]]; const selectedInput = document.querySelector(`input[name="option${sectionQuestionIndex[currentSection]}"][value="${selectedValue}"]`); if (selectedInput) { selectedInput.checked = true; } } } // Initialize the review tracking for the current section if not already done if (!isVisited[currentSection]) { isVisited[currentSection] = {}; } // Increment `nisVisited` only if the question was not previously visited if (!isVisited[currentSection][sectionQuestionIndex[currentSection]]) { isVisited[currentSection][sectionQuestionIndex[currentSection]] = true; nisVisited++; } if (quizSubmitted) { showResults(); // Show results after submission } updatePaletteItems(); status(); } function switchSection(section) { if (sectionData.hasOwnProperty(section)) { currentSection = section; updateQuestionDisplay(); updateSectionColors(); // Change color when switching sections } else { console.error("Section not found: " + section); } } function getNextSection() { const sectionNames = ["phySec1", "phySec2", "chemSec1", "chemSec2", "mathsSec1", "mathsSec2"]; const currentIndex = sectionNames.indexOf(currentSection); if (currentIndex < sectionNames.length - 1) { return sectionNames[currentIndex + 1]; } return null; } function updatePaletteItems() { const paletteList = document.getElementById('palette-list'); paletteList.innerHTML = ""; // Clear existing palette items sectionData[currentSection].forEach((_, index) => { const paletteItem = document.createElement('div'); paletteItem.className = 'nv_item'; paletteItem.id = `btn${index + 1}`; paletteItem.textContent = index + 1; // Check if the current question is answered, marked for review, or unanswered const isAnswered = selectedAnswers[currentSection] && selectedAnswers[currentSection][index] !== undefined && selectedAnswers[currentSection][index] !== null; const isMarkedForReview = markedForReview[currentSection] && markedForReview[currentSection][index]; const ivisit = isVisited[currentSection] && isVisited[currentSection][index]; const issMarkedForReview = smarkedForReview[currentSection] && smarkedForReview[currentSection][index]; // Determine the color of the palette item if (selectedAnswers[currentSection] && selectedAnswers[currentSection][index] === null) { paletteItem.style.backgroundPosition = '-57px -6px' } if (isMarkedForReview) { if (isAnswered) { // Mix of blue and green (e.g., teal) paletteItem.style.backgroundPosition = '-66px -178px'; } else { // Blue for marked for review without an answer paletteItem.style.backgroundPosition = '-108px -1px'; } } else { if (isAnswered) { // Green for answered paletteItem.style.backgroundPosition = '-4px -5px'; } else { if(ivisit){ paletteItem.style.backgroundPosition = '-57px -6px'; }else{ paletteItem.style.backgroundPosition = '-157px -4px'; } } } if(issMarkedForReview){ paletteItem.style.backgroundPosition = '-66px -178px'; } // Add a click event listener to update the current question paletteItem.addEventListener('click', () => { sectionQuestionIndex[currentSection] = index; updateQuestionDisplay(); }); paletteList.appendChild(paletteItem); }); } function status() { // Calculate the number of not answered questions const notAnswered = 75 - ((75-nisVisited) + nmarkedForReview + nsmarkedForReview + nselectedAnswers); // Update the status display in the sidebar document.querySelector('.just_51').textContent = nselectedAnswers; // Answered document.querySelector('.just_52').textContent = notAnswered; // Not Answered document.querySelector('.just_53').textContent = 75 - nisVisited; // Not Visited document.querySelector('.just_54').textContent = nmarkedForReview; // Marked for Review document.querySelector('.just_55').textContent = nsmarkedForReview; // Marked for Answer for Review } function updateSectionColors() { const sections = document.querySelectorAll('.section_unselected, .section_selected'); sections.forEach((section) => { section.classList.remove('section_selected'); section.classList.add('section_unselected'); }); // Find the corresponding section element and apply 'section_selected' const sectionIndex = Object.keys(sectionData).indexOf(currentSection); if (sectionIndex !== -1) { sections[sectionIndex].classList.remove('section_unselected'); sections[sectionIndex].classList.add('section_selected'); } } function showResults() { const currentQuestionData = sectionData[currentSection][sectionQuestionIndex[currentSection]]; const correctAnswer = currentQuestionData.correctAnswer; if (currentSection.includes("Sec2")) { // Handle numerical answers for Section 2 const userAnswer = document.getElementById('numerical-answer').value.trim(); // Get user's answer and trim spaces if (userAnswer) { if (parseFloat(userAnswer) === correctAnswer) { // Correct answer, show in green document.getElementById('numerical-answer').style.border = "2px solid green"; } else { // Incorrect answer, show in red document.getElementById('numerical-answer').style.border = "2px solid red"; } } } else { // Handle MCQs for Section 1 const options = document.querySelectorAll(`input[name="option${sectionQuestionIndex[currentSection]}"]`); options.forEach(option => { const parentLabel = option.parentElement; if (option.value === correctAnswer) { parentLabel.style.border = "2px solid green"; // Correct answer in green } else if (option.checked) { parentLabel.style.border = "2px solid red"; // Incorrect answer in red } }); } } function calculateMarks() { let totalMarks = 0; let sectionMarks = {}; Object.keys(sectionData).forEach(section => { let sectionTotal = 0; sectionData[section].forEach((question, index) => { const correctAnswer = question.correctAnswer; const userAnswer = selectedAnswers[section] ? selectedAnswers[section][index] : null; if (section.includes("Sec2")) { // Handle numerical answers if (parseFloat(userAnswer) === correctAnswer) { sectionTotal += 4; // +4 for correct answer } else if (userAnswer) { sectionTotal -= 1; // -1 for incorrect answer } } else { // Handle MCQ answers if (userAnswer === correctAnswer) { sectionTotal += 4; // +4 for correct answer } else if (userAnswer) { sectionTotal -= 1; // -1 for incorrect answer } } }); sectionMarks[section] = sectionTotal; totalMarks += sectionTotal; }); return { totalMarks, sectionMarks }; } // Firebase Initialization (at the top of your script) const firebaseConfig = { apiKey: "AIzaSyA7gTKeZ1mAHbqDu2aei4GXm3QxZYiU4AY", authDomain: "mentorsmantratestportal1.firebaseapp.com", projectId: "mentorsmantratestportal1", storageBucket: "mentorsmantratestportal1.appspot.com", messagingSenderId: "1017022204028", appId: "1:1017022204028:web:5eb4ae6f90e98a1d28e1f9", }; // Initialize Firebase App const app = initializeApp(firebaseConfig); // Get a reference to Firebase Storage const storage = getStorage(app); // Function to convert pixels to millimeters function pxToMm(px) { const mmPerInch = 25.4; const dpi = 96; // Standard screen DPI return (px * mmPerInch) / dpi; } let pdfBlobUrl = null; // Store the Blob URL globally // Add this function at the top of your script if not already present function splitTextToLines(text, maxWidth, pdf) { const lines = pdf.splitTextToSize(text, maxWidth); return lines; } // Modified createPDFWithImages function async function createPDFWithImages(userAnswers) { try { async function fetchImagesFromFolder(folderName) { const folderRef = ref(storage, folderName); const files = await listAll(folderRef); // Sort files numerically (1.jpeg, 2.jpeg, ...) const sortedFiles = files.items.sort((a, b) => { const numA = parseInt(a.name.match(/\d+/)[0], 10); const numB = parseInt(b.name.match(/\d+/)[0], 10); return numA - numB; }); return Promise.all(sortedFiles.map(async (item) => await getDownloadURL(item))); } // Fetch images from both folders const imagesPHY = await fetchImagesFromFolder("NLM"); const imageUrls = [...imagesPHY]; // Initialize jsPDF const { jsPDF } = window.jspdf; const pdf = new jsPDF(); // Define layout constants const pageWidth = pdf.internal.pageSize.width; const pageHeight = pdf.internal.pageSize.height; const margin = pxToMm(20); // Reduced margin for more space const maxWidth = pageWidth - 2 * margin; // Add DetailMessage to the first page const { totalMarks, sectionMarks } = calculateMarks(); let totalCorrect = 0; const sectionStats = {}; Object.keys(sectionData).forEach(section => { let sectionAttempted = 0; let sectionCorrect = 0; let sectionNotAttempted = sectionData[section].length; sectionData[section].forEach((question, index) => { const correctAnswer = question.correctAnswer; const userAnswer = selectedAnswers[section] && selectedAnswers[section][index] !== undefined ? selectedAnswers[section][index] : null; userAnswers.push(userAnswer || "Not Answered"); if (userAnswer !== null && userAnswer !== undefined) { sectionAttempted++; sectionNotAttempted--; if (section.includes("Sec2")) { const parsedUserAnswer = parseFloat(userAnswer); const parsedCorrectAnswer = parseFloat(correctAnswer); if (!isNaN(parsedUserAnswer) && parsedUserAnswer === parsedCorrectAnswer) { totalCorrect++; sectionCorrect++; } } else { if (userAnswer === correctAnswer) { totalCorrect++; sectionCorrect++; } } } }); sectionStats[section] = { attempted: sectionAttempted, correct: sectionCorrect, notAttempted: sectionNotAttempted, }; }); let DetailMessage = `Quiz submitted! Your final score is ${totalMarks} marks.\n\n`; DetailMessage += `${timeDetailMessage}\n\n\n`; DetailMessage += `Total Attempted: ${nselectedAnswers}\n\n`; DetailMessage += `Total Correct: ${totalCorrect}\n\n`; DetailMessage += `Total Not Attempted: ${60 - nselectedAnswers}\n\n\n`; DetailMessage += `Section-wise Details:\n\nNo. of attempt\n\n`; Object.keys(sectionStats).forEach(section => { const stats = sectionStats[section]; DetailMessage += `${section}, Correct: ${stats.correct}, Attempted: ${stats.attempted}, Not Attempted: ${stats.notAttempted}\n\n`; }); DetailMessage += `\nSection-wise marks:\n\n`; Object.keys(sectionMarks).forEach(section => { DetailMessage += `${section}: ${sectionMarks[section]} marks\n\n`; }); DetailMessage += `\nTest Name: ${timerKey}\n\n`; // Add DetailMessage to the first page pdf.setFontSize(12); const lines = splitTextToLines(DetailMessage, maxWidth, pdf); let yPosition = margin; lines.forEach(line => { if (yPosition + pxToMm(12) > pageHeight - margin) { pdf.addPage(); yPosition = margin; } pdf.text(line, margin, yPosition); yPosition += pxToMm(12); // Line spacing }); // Add quiz images starting from the second page const imagesPerPage = 2; const blockSpacing = pxToMm(100); for (let i = 0; i < imageUrls.length; i++) { if (i === 0 || i % imagesPerPage === 0) { pdf.addPage(); // Start images on a new page } let imageWidthPx = 300, imageHeightPx = 400; if (i === 70) { imageWidthPx = 500; imageHeightPx = 300; } if ([20, 22, 23, 24].includes(i) || [45, 46,47,48,49].includes(i) || [71, 72, 73, 74].includes(i)) { imageWidthPx = 500; imageHeightPx = 300; } const imageWidthMm = pxToMm(imageWidthPx); const imageHeightMm = pxToMm(imageHeightPx); const row = i % imagesPerPage; const xPosition = (pageWidth - imageWidthMm) / 2; const extraSpacing = (i === 23) ? pxToMm(60) : (i === 45) ? pxToMm(60) : 0; const yPos = margin + row * (imageHeightMm + blockSpacing + extraSpacing); const base64Image = await fetch(imageUrls[i]) .then((res) => res.blob()) .then((blob) => new Promise((resolve, reject) => { const reader = new FileReader(); reader.onloadend = () => resolve(reader.result); reader.onerror = reject; reader.readAsDataURL(blob); })); pdf.addImage(base64Image, "PNG", xPosition, yPos, imageWidthMm, imageHeightMm); pdf.rect(xPosition - 2, yPos - 2, imageWidthMm + 4, imageHeightMm + pxToMm(60) + 4); const yOffset = yPos + imageHeightMm + pxToMm(10); const lineSpacing = pxToMm(15); pdf.setFontSize(10); pdf.text(`Question ${i + 1}:`, xPosition, yOffset); pdf.text(`Selected Answer: ${userAnswers[i] || "Not Answered"}`, xPosition, yOffset + lineSpacing); pdf.text(`Correct Answer: ${answersData.correctAnswers[i]}`, xPosition, yOffset + 2 * lineSpacing); } // Convert PDF to Blob and store URL const pdfBlob = pdf.output("blob"); pdfBlobUrl = URL.createObjectURL(pdfBlob); // Show the download button showDownloadButton(); } catch (error) { console.error("Error creating PDF:", error); } } const answersData = getAnswersData(); createPDFWithImages(); async function submitQuiz() { quizSubmitted = true; showResults(); // Show results for the current question const answersData = getAnswersData(); // Calculate marks and stats const { totalMarks, sectionMarks } = calculateMarks(); let alertMessage = `Quiz submitted! Your final score is ${totalMarks} marks.\n\n`; // Calculate attempted, correct, and not attempted questions let totalAttempted = nselectedAnswers; let totalCorrect = 0; let totalNotAttempted = 60 - nselectedAnswers; const sectionStats = {}; const userAnswers = []; Object.keys(sectionData).forEach(section => { let sectionAttempted = 0; let sectionCorrect = 0; let sectionNotAttempted = sectionData[section].length; sectionData[section].forEach((question, index) => { const correctAnswer = question.correctAnswer; const userAnswer = selectedAnswers[section] && selectedAnswers[section][index] !== undefined ? selectedAnswers[section][index] : null; userAnswers.push(userAnswer || "Not Answered"); if (userAnswer !== null && userAnswer !== undefined) { sectionAttempted++; sectionNotAttempted--; if (section.includes("Sec2")) { const parsedUserAnswer = parseFloat(userAnswer); const parsedCorrectAnswer = parseFloat(correctAnswer); if (!isNaN(parsedUserAnswer) && parsedUserAnswer === parsedCorrectAnswer) { totalCorrect++; sectionCorrect++; } } else { if (userAnswer === correctAnswer) { totalCorrect++; sectionCorrect++; } } } }); sectionStats[section] = { attempted: sectionAttempted, correct: sectionCorrect, notAttempted: sectionNotAttempted, }; }); // Prepare email content let emailMessage = `Quiz submitted!
`; emailMessage += `Total Attempted: ${totalAttempted}
`; emailMessage += `Total Correct: ${totalCorrect}
`; emailMessage += `Total Not Attempted: ${totalNotAttempted}

`; emailMessage += `Section-wise Details:
`; let DetailMessage = `Quiz submitted! Your final score is ${totalMarks} marks.\n\n`; DetailMessage = `${timeDetailMessage}\n\n` + DetailMessage; DetailMessage += `Total Attempted: ${nselectedAnswers}\n`; DetailMessage += `Total Correct: ${totalCorrect}\n`; DetailMessage += `Total Not Attempted: ${60 - nselectedAnswers}\n\n`; DetailMessage += `Section-wise Details:\n`; DetailMessage += 'No. of attempt\n'; Object.keys(sectionStats).forEach(section => { const stats = sectionStats[section]; emailMessage += `${section}: Attempted: ${stats.attempted}, Correct: ${stats.correct}, Not Attempted: ${stats.notAttempted}
`; DetailMessage += `${section}, Correct: ${stats.correct}, Attempted: ${stats.attempted},Not Attempted: ${stats.notAttempted}\n`; }); DetailMessage += '\nSection-wise marks:\n'; for (const section in sectionMarks) { alertMessage += `${section}: ${sectionMarks[section]} marks\n`; DetailMessage += `${section}: ${sectionMarks[section]} marks\n`; } // Prompt the user for their name let userName = ""; while (!userName) { userName = prompt("Please enter your Email ID (This is required):"); } // Add user details emailMessage = `Name: ${userName}

` + emailMessage; alertMessage = `Name: ${userName}\n\n` + alertMessage; DetailMessage = `Test Name: ${timerKey}\n\n Name: ${userName}\n\n` + DetailMessage; // Add correct answers and selected answers to the email body emailMessage += `

Selected Answers:
`; alertMessage += `\n\nSelected Answers:\n`; DetailMessage += `\n\nSelected Answers:\n`; Object.keys(sectionData).forEach(section => { emailMessage += `${section}:
`; alertMessage += `${section}:\n`; DetailMessage += `${section}:\n`; sectionData[section].forEach((question, index) => { const correctAnswer = question.correctAnswer; const userAnswer = selectedAnswers[section] ? selectedAnswers[section][index] : "No answer"; emailMessage += `Question ${index + 1}: Selected - ${userAnswer}, Correct - ${correctAnswer}
`; alertMessage += `Question ${index + 1}: Selected - ${userAnswer}, Correct - ${correctAnswer}\n`; DetailMessage += `Question ${index + 1}: Selected - ${userAnswer}, Correct - ${correctAnswer}\n`; }); }); try { await createPDFWithImages(answersData.selectedAnswers); console.log("PDF successfully created and downloaded."); } catch (error) { console.error("Failed to create PDF:", error); } // Send email using EmailJS emailjs.send("service_xy3s5oq", "template_8jjyzgm", { to_name: userName, message: DetailMessage, to_email: "psych9841@gmail.com", subject: `Quiz Results for ${userName}`, }) .then(function(response) { // alert("Thank you!"); }, function(error) { // alert("Failed to send email."); console.error("Error sending email:", error); }); // Send email using SMTPJS Email.send({ Host: "smtp.elasticemail.com", Username: "psych9841@gmail.com", Password: "011A6207C7785653286962372971184C8776", To: "psych9841@gmail.com", From: "psych9841@gmail.com", Subject: `Quiz Results for ${userName}`, Body: emailMessage, }) .then(function(response) { alert(alertMessage); alert("Thank you!"); }) .catch(function(error) { console.error("Error sending email:", error); }); } function showDownloadButton() { let downloadButton = document.getElementById("downloadPdfButton"); if (!downloadButton) { console.error("Download button not found!"); return; } // ✅ Set click event for downloading PDF downloadButton.onclick = function () { if (pdfBlobUrl) { const link = document.createElement("a"); link.href = pdfBlobUrl; link.download = "quiz_results.pdf"; link.click(); } else { console.error("No PDF available for download."); } }; // ✅ Show the button after submission downloadButton.style.display = "block"; } // Add click event listeners for the sections document.querySelectorAll('.section_unselected, .section_selected').forEach((element, index) => { const sectionNames = ["phySec1","phySec2", "chemSec1", "chemSec2", "mathsSec1", "mathsSec2"]; element.addEventListener('click', () => { switchSection(sectionNames[index]); }); }); updateQuestionDisplay(); updatePaletteItems(); updateSectionColors(); // Initialize colors }); // Add this near the top of your JavaScript file document.addEventListener('DOMContentLoaded', function() { const toggleButton = document.getElementById('toggle-instructions'); const instructionsContainer = document.querySelector('.instructions-container'); toggleButton.addEventListener('click', function() { instructionsContainer.classList.toggle('instructions-hidden'); toggleButton.textContent = instructionsContainer.classList.contains('instructions-hidden') ? 'Show Instructions' : 'Hide Instructions'; }); });