let currentDay = 1; /* Safely obtain localStorage. Accessing window.localStorage can itself throw a SecurityError when the document runs inside a sandbox without allow-same-origin. */ function getSafeStorage() { try { const storage = window.localStorage; /* Test whether reading and writing are actually permitted. Some browsers expose localStorage but block its methods. */ const testKey = "__superMathStorageTest__"; storage.setItem(testKey, "1"); storage.removeItem(testKey); return storage; } catch (error) { console.warn( "Persistent storage is unavailable. " + "Completed days will reset when the page is reloaded.", error ); return null; } } const safeStorage = getSafeStorage(); function loadCompletedDays() { if (!safeStorage) { return []; } try { const savedValue = safeStorage.getItem("completedMathDays"); if (!savedValue) { return []; } const parsedValue = JSON.parse(savedValue); if (!Array.isArray(parsedValue)) { return []; } /* Remove invalid values, duplicates, and day numbers outside the challenge. */ return Array.from( new Set( parsedValue.filter(function(dayNumber) { return ( Number.isInteger(dayNumber) && dayNumber >= 1 && dayNumber <= challenge.length ); }) ) ).sort(function(a, b) { return a - b; }); } catch (error) { console.warn( "The saved math progress could not be loaded.", error ); return []; } } function saveCompletedDays() { if (!safeStorage) { /* The completedDays array still works in memory. Progress simply will not survive a page reload. */ return; } try { safeStorage.setItem( "completedMathDays", JSON.stringify(completedDays) ); } catch (error) { console.warn( "The math progress could not be saved.", error ); } } let completedDays = loadCompletedDays(); const dayTitle = document.getElementById("dayTitle"); const missionMessage = document.getElementById("missionMessage"); const starCount = document.getElementById("starCount"); const progressBar = document.getElementById("progressBar"); const progressContainer = document.getElementById("progressContainer"); const divisionList = document.getElementById("divisionList"); const multiplicationList = document.getElementById("multiplicationList"); const algebraList = document.getElementById("algebraList"); const wordList = document.getElementById("wordList"); const encouragement = document.getElementById("encouragement"); const completeButton = document.getElementById("completeButton"); const previousButton = document.getElementById("previousButton"); const nextButton = document.getElementById("nextButton"); const daySelector = document.getElementById("daySelector"); const answerLock = document.getElementById("answerLock"); const answerForm = document.getElementById("answerForm"); const passwordInput = document.getElementById("passwordInput"); const passwordMessage = document.getElementById("passwordMessage"); const answerContent = document.getElementById("answerContent"); const divisionAnswers = document.getElementById("divisionAnswers"); const multiplicationAnswers = document.getElementById("multiplicationAnswers"); const algebraAnswers = document.getElementById("algebraAnswers"); const wordAnswers = document.getElementById("wordAnswers"); const hideAnswersButton = document.getElementById("hideAnswersButton"); function createList(items, element) { element.innerHTML = ""; items.forEach(function(item) { const listItem = document.createElement("li"); listItem.textContent = item; element.appendChild(listItem); }); } function createAlgebraList(items) { algebraList.innerHTML = ""; items.forEach(function(item) { const listItem = document.createElement("li"); const typeLabel = document.createElement("span"); typeLabel.className = "algebra-type"; typeLabel.textContent = item.type; const questionText = document.createElement("span"); questionText.textContent = item.question; listItem.appendChild(typeLabel); listItem.appendChild(questionText); algebraList.appendChild(listItem); }); } function calculateDivision(question) { const numbers = question .split("÷") .map(function(part) { return Number(part.trim()); }); const dividend = numbers[0]; const divisor = numbers[1]; const quotient = Math.floor(dividend / divisor); const remainder = dividend % divisor; return ( question + " = " + quotient + " R" + remainder ); } function calculateMultiplication(question) { const numbers = question .split("×") .map(function(part) { return Number(part.trim()); }); const product = numbers[0] * numbers[1]; return ( question + " = " + product.toLocaleString("en-US") ); } function renderAnswers() { const day = challenge[currentDay - 1]; createList( day.division.map(calculateDivision), divisionAnswers ); createList( day.multiplication.map(calculateMultiplication), multiplicationAnswers ); createList( day.algebra.map(function(item) { return ( item.question + "\n\n" + item.answer ); }), algebraAnswers ); createList( day.wordAnswers, wordAnswers ); } function lockAnswers() { answerContent.hidden = true; answerLock.hidden = false; passwordInput.value = ""; passwordMessage.textContent = ""; } function unlockAnswers() { renderAnswers(); answerLock.hidden = true; answerContent.hidden = false; passwordMessage.textContent = ""; } function updateStarDisplay() { starCount.textContent = String(completedDays.length); if (completedDays.includes(currentDay)) { completeButton.textContent = "⭐ Mission completed! Star earned!"; completeButton.classList.add("completed"); } else { completeButton.textContent = "⭐ I finished today's mission!"; completeButton.classList.remove("completed"); } } function createCelebration() { const symbols = [ "⭐", "🌟", "🎉", "🚀", "🌈", "🏆" ]; for (let index = 0; index < 24; index++) { const piece = document.createElement("div"); piece.className = "celebration"; piece.textContent = symbols[ Math.floor( Math.random() * symbols.length ) ]; piece.style.left = Math.random() * 95 + "vw"; piece.style.top = 55 + Math.random() * 35 + "vh"; piece.style.fontSize = 22 + Math.random() * 24 + "px"; piece.style.animationDelay = Math.random() * 0.4 + "s"; document.body.appendChild(piece); setTimeout(function() { piece.remove(); }, 2000); } } function completeCurrentDay() { if (!completedDays.includes(currentDay)) { completedDays.push(currentDay); completedDays.sort(function(a, b) { return a - b; }); /* This safely saves progress if storage is available. It does not throw an error when the page is sandboxed. */ saveCompletedDays(); createCelebration(); } updateStarDisplay(); } function displayDay(dayNumber) { currentDay = Math.min( challenge.length, Math.max(1, dayNumber) ); const day = challenge[currentDay - 1]; dayTitle.textContent = "Day " + currentDay + " Mission"; missionMessage.textContent = missionMessages[currentDay - 1]; progressBar.style.width = ( (currentDay / challenge.length) * 100 ) + "%"; progressContainer.setAttribute( "aria-valuenow", String(currentDay) ); createList( day.division, divisionList ); createList( day.multiplication, multiplicationList ); createAlgebraList(day.algebra); createList( day.words, wordList ); encouragement.textContent = encouragements[currentDay - 1]; previousButton.disabled = currentDay === 1; nextButton.disabled = currentDay === challenge.length; daySelector.value = String(currentDay); document.title = "Day " + currentDay + " – Super Math Adventure"; updateStarDisplay(); lockAnswers(); /* Scrolling can also be restricted in some embedded environments, so use a fallback if smooth scrolling is unavailable. */ try { window.scrollTo({ top: 0, behavior: "smooth" }); } catch (error) { try { window.scrollTo(0, 0); } catch (ignoredError) { // The sandbox does not permit scrolling. } } } /* Add all 15 days to the day selector. */ for ( let dayNumber = 1; dayNumber <= challenge.length; dayNumber++ ) { const option = document.createElement("option"); option.value = String(dayNumber); option.textContent = "Day " + dayNumber + " of " + challenge.length; daySelector.appendChild(option); } previousButton.addEventListener( "click", function() { displayDay(currentDay - 1); } ); nextButton.addEventListener( "click", function() { displayDay(currentDay + 1); } ); daySelector.addEventListener( "change", function() { displayDay( Number(daySelector.value) ); } ); completeButton.addEventListener( "click", completeCurrentDay ); answerForm.addEventListener( "submit", function(event) { event.preventDefault(); if ( passwordInput.value === PARENT_PASSWORD ) { unlockAnswers(); } else { passwordMessage.textContent = "That password is not correct. " + "Please try again."; passwordInput.value = ""; passwordInput.focus(); } } ); hideAnswersButton.addEventListener( "click", function() { lockAnswers(); } ); displayDay(1);