// ========== LETTER DATA ========== // Letters she has in school: A, E, I, O, U, T, M, N // big / small: characters to show // audio: short sound of you saying just the letter // teachAudio: you explaining "This is the letter X..." //Please don't change the const letters teachAudio and audio file names const letters = [ { big: "A", small: "a", audio: "a.m4a", teachAudio: "a.m4a" }, { big: "E", small: "e", audio: "e.m4a", teachAudio: "e.m4a" }, { big: "I", small: "i", audio: "i.m4a", teachAudio: "i.m4a" }, { big: "O", small: "o", audio: "o.m4a", teachAudio: "o.m4a" }, { big: "U", small: "u", audio: "u.m4a", teachAudio: "u.m4a" }, { big: "T", small: "t", audio: "t.m4a", teachAudio: "t.m4a" }, { big: "M", small: "m", audio: "m.m4a", teachAudio: "m.m4a" }, { big: "N", small: "n", audio: "n.m4a", teachAudio: "n.m4a" } ]; // ========== PETS DATA ========== // You can change image filenames & treats to whatever you have. // Make sure images exist in your folder (or adjust paths). const pets = [ { id: "dog", name: "Doggo", emoji: "🐶", unlocked: true, image: "dog.jpg", treat: "🍗" }, { id: "cat", name: "Kitty", emoji: "🐱", unlocked: true, image: "cat.jpg", treat: "🐟" }, { id: "turtle", name: "Turtle", emoji: "🐢", unlocked: true, image: "turtle.jpg", treat: "🥬" }, { id: "bird", name: "Bird", emoji: "🐦", unlocked: true, image: "bird.jpg", treat: "🌽" }, { id: "bunny", name: "Bunny", emoji: "🐰", unlocked: true, image: "bunny.jpg", treat: "🥕" } ]; // ========== AUDIO FILES ========== // Put these in the same folder (or adjust paths): // intro.mp3 -> "Hello cousin, I am a robot from space..." // dog_happy.mp3 -> happy woof // dog_sad.mp3 -> optional sad sound const audioIntro = new Audio("hello.m4a"); const audioDogHappy = new Audio("dog_happy.mp3"); const audioDogSad = new Audio("dog_sad.mp3"); // These change depending on current letter: let audioLetter = null; // short letter sound (A, E, ...) let audioTeach = null; // Robo explains letter (we still set it in showRandomLetter, but we'll also recreate on demand) // ========== DOM ELEMENTS ========== // Screens const screenIntro = document.getElementById("screen-intro"); const screenMain = document.getElementById("screen-main"); // Intro buttons const btnPlayIntro = document.getElementById("btnPlayIntro"); const btnStart = document.getElementById("btnStart"); // Robot side (main screen) const btnRobotHello = document.getElementById("btnRobotHello"); const btnExplainLetter = document.getElementById("btnExplainLetter"); const robotImageEl = document.getElementById("robotImage"); // Letter + quiz const bigEl = document.getElementById("letterBig"); const smallEl = document.getElementById("letterSmall"); const hintTextEl = document.getElementById("hintText"); const btnStartQuiz = document.getElementById("btnStartQuiz"); const scoreTextEl = document.getElementById("scoreText"); const quizButtonsEl = document.getElementById("quizButtons"); const quizStatusEl = document.getElementById("quizStatus"); // Pet image & treats & pets list const dogMessageEl = document.getElementById("dogMessage"); const treatsRowEl = document.getElementById("treatsRow"); const petsListEl = document.getElementById("petsList"); const petImageEl = document.getElementById("petImage"); // ========== STATE ========== let currentLetterIndex = 0; let quizActive = false; let correctScore = 0; const neededCorrect = 10; // how many correct answers finish the letter // NEW: which pet is currently active let currentPetId = "dog"; // helper to get active pet object function getCurrentPet() { return pets.find(p => p.id === currentPetId) || pets[0]; } // ========== SCREEN HELPERS ========== function showScreenIntro() { screenIntro.classList.add("active"); screenMain.classList.remove("active"); } function showScreenMain() { screenIntro.classList.remove("active"); screenMain.classList.add("active"); } // ========== QUIZ RESET HELPER (NEW) ========== function stopAndResetQuiz(message = "Quiz stopped.") { quizActive = false; correctScore = 0; scoreTextEl.textContent = `⭐ 0 / ${neededCorrect}`; quizButtonsEl.innerHTML = ""; quizStatusEl.textContent = message; // show letters again (teaching mode) bigEl.classList.remove("hidden"); smallEl.classList.remove("hidden"); } // ========== PETS RENDERING & UNLOCKING ========== function renderPets() { petsListEl.innerHTML = ""; const activePet = getCurrentPet(); pets.forEach(pet => { const div = document.createElement("div"); div.className = "pet-card " + (pet.unlocked ? "unlocked" : "locked"); if (pet.unlocked) { div.classList.add("selectable"); } if (pet.id === activePet.id) { div.classList.add("active-pet"); } const emojiDiv = document.createElement("div"); emojiDiv.className = "pet-emoji"; emojiDiv.textContent = pet.emoji; const nameDiv = document.createElement("div"); nameDiv.className = "pet-name"; nameDiv.textContent = pet.name; div.appendChild(emojiDiv); div.appendChild(nameDiv); // Click to select this pet (if unlocked) if (pet.unlocked) { div.addEventListener("click", () => { selectPet(pet.id); }); } petsListEl.appendChild(div); }); } // select a pet, update picture & message function selectPet(petId) { currentPetId = petId; const pet = getCurrentPet(); // stop & reset quiz when changing pet stopAndResetQuiz("Quiz stopped. You changed the pet. Press Start quiz again."); // update main image (fallback to dog.jpg if image missing) if (petImageEl) { petImageEl.src = pet.image || "dog.jpg"; petImageEl.alt = pet.name; } // reset treats when changing pet treatsRowEl.innerHTML = ""; dogMessageEl.textContent = `${pet.name} is ready! Feed ${pet.emoji} with correct answers.`; // re-render list to highlight current pet renderPets(); } function unlockNextPet() { const nextLocked = pets.find(p => !p.unlocked); if (nextLocked) { nextLocked.unlocked = true; renderPets(); const pet = getCurrentPet(); dogMessageEl.textContent = `${pet.name} is full and happy! You unlocked ${nextLocked.name}! ${nextLocked.emoji}`; } else { const pet = getCurrentPet(); dogMessageEl.textContent = `${pet.name} is full and all pets are unlocked! 🎉`; } } // ========== LETTER SETUP ========== function showRandomLetter() { currentLetterIndex = Math.floor(Math.random() * letters.length); const letter = letters[currentLetterIndex]; bigEl.textContent = letter.big; smallEl.textContent = letter.small; // Make sure letters are visible again (for teaching phase) bigEl.classList.remove("hidden"); smallEl.classList.remove("hidden"); // Load audio for this letter (short "A", "E", etc.) if (audioLetter) audioLetter.pause(); audioLetter = new Audio(letter.audio); // Load teaching audio for this letter (we still store it, but will also recreate fresh when needed) if (audioTeach) audioTeach.pause(); audioTeach = letter.teachAudio ? new Audio(letter.teachAudio) : null; // Reset quiz state quizActive = false; correctScore = 0; scoreTextEl.textContent = `⭐ 0 / ${neededCorrect}`; quizButtonsEl.innerHTML = ""; quizStatusEl.textContent = "Quiz not started."; treatsRowEl.innerHTML = ""; const pet = getCurrentPet(); dogMessageEl.textContent = `Feed ${pet.name} by choosing the right letter!`; hintTextEl.textContent = "Tap the letter to hear it!"; } // ========== AUDIO HELPERS ========== function playIntroAudio() { audioIntro.currentTime = 0; audioIntro.play().catch(() => { console.log("Intro audio play blocked by browser until user interaction."); }); } function playLetterSound() { if (!audioLetter) { const letter = letters[currentLetterIndex]; audioLetter = new Audio(letter.audio); } audioLetter.currentTime = 0; audioLetter.play(); } // ⭐ Updated: always create a fresh Audio so we can click robot unlimited times function playTeachSound() { const letter = letters[currentLetterIndex]; const src = letter.teachAudio || letter.audio; const voice = new Audio(src); voice.play().catch(() => {}); } // NEW: play sound for a letter by its BIG character (for answer buttons) function playLetterByBigChar(bigChar) { const letterObj = letters.find(l => l.big === bigChar); if (!letterObj) return; const audio = new Audio(letterObj.audio); audio.play().catch(() => {}); } // ========== QUIZ LOGIC ========== btnStartQuiz.addEventListener("click", () => { startQuiz(); }); function startQuiz() { quizActive = true; correctScore = 0; scoreTextEl.textContent = `⭐ 0 / ${neededCorrect}`; quizStatusEl.textContent = "Listen to Robo and choose the correct letter!"; treatsRowEl.innerHTML = ""; const pet = getCurrentPet(); dogMessageEl.textContent = `Robo will say the letter. Help ${pet.name} find food!`; // IMPORTANT: hide the letters so she can't "cheat" visually bigEl.classList.add("hidden"); smallEl.classList.add("hidden"); // Robo says which letter we're looking for playTeachSound(); createQuizButtons(); } // Create 4 buttons: 1 correct letter + 3 random wrong letters function createQuizButtons() { quizButtonsEl.innerHTML = ""; const correctLetter = letters[currentLetterIndex].big; // Get other letters for wrong options const others = letters.map(l => l.big).filter(c => c !== correctLetter); shuffleArray(others); // We want 3 wrong answers, total 4 options const wrong = others.slice(0, 3); const options = [correctLetter, ...wrong]; shuffleArray(options); options.forEach(ch => { const btn = document.createElement("button"); btn.className = "quiz-btn"; btn.textContent = ch; btn.addEventListener("click", () => handleQuizClick(btn, ch)); quizButtonsEl.appendChild(btn); }); } function handleQuizClick(button, chosen) { if (!quizActive) return; const correct = letters[currentLetterIndex].big; // 🔊 Always play pronunciation of the clicked letter (learning from every click) playLetterByBigChar(chosen); // reset styles const allButtons = quizButtonsEl.querySelectorAll(".quiz-btn"); allButtons.forEach(b => b.classList.remove("correct", "wrong")); if (chosen === correct) { // ✅ CORRECT ANSWER button.classList.add("correct"); correctScore++; scoreTextEl.textContent = `⭐ ${correctScore} / ${neededCorrect}`; // add treat for the current pet const pet = getCurrentPet(); const span = document.createElement("span"); span.textContent = pet.treat || "🍗"; treatsRowEl.appendChild(span); // happy sound audioDogHappy.currentTime = 0; audioDogHappy.play().catch(() => {}); dogMessageEl.textContent = `${pet.name} is happy! ${pet.emoji}`; if (correctScore >= neededCorrect) { // finished this letter quizActive = false; quizStatusEl.textContent = "Great! You finished this letter!"; unlockNextPet(); // still works if all are already unlocked // short pause, then new letter (letters will be visible again there) setTimeout(() => { showRandomLetter(); }, 1200); } else { quizStatusEl.textContent = "Correct!"; // wait a bit so she sees green, then shuffle answers setTimeout(() => { if (quizActive) { createQuizButtons(); } }, 800); } } else { // ❌ WRONG ANSWER button.classList.add("wrong"); // NEW: take away one treat if there is any if (treatsRowEl.lastChild) { treatsRowEl.removeChild(treatsRowEl.lastChild); } const pet = getCurrentPet(); quizStatusEl.textContent = "Not this one. Try again!"; dogMessageEl.textContent = `No food this time for ${pet.name}. Try again!`; audioDogSad.currentTime = 0; audioDogSad.play().catch(() => {}); } } // Simple shuffle helper function shuffleArray(arr) { for (let i = arr.length - 1; i > 0; i--) { const j = Math.floor(Math.random() * (i + 1)); [arr[i], arr[j]] = [arr[j], arr[i]]; } return arr; } // ========== EVENT LISTENERS ========== // Intro screen buttons btnPlayIntro.addEventListener("click", playIntroAudio); btnStart.addEventListener("click", () => { // stop intro if playing audioIntro.pause(); audioIntro.currentTime = 0; showScreenMain(); }); // Robot buttons on main screen btnRobotHello.addEventListener("click", playIntroAudio); btnExplainLetter.addEventListener("click", () => { // When explaining letter, stop any active quiz and go to teaching mode stopAndResetQuiz("Quiz stopped. Robo is explaining the letter now."); // Teaching phase: show letters & explain them bigEl.classList.remove("hidden"); smallEl.classList.remove("hidden"); playTeachSound(); hintTextEl.textContent = "Listen to Robo, then tap the letter and repeat."; }); // 👉 Clicking the ROBOT image during quiz repeats the current letter as many times as needed robotImageEl.addEventListener("click", () => { if (quizActive) { // During quiz: repeat which letter to find (no letters visible) playTeachSound(); } else { // Outside quiz: Robo can say hello again playIntroAudio(); } }); // Letter clicks -> play letter sound (teaching mode, when visible) bigEl.addEventListener("click", () => { playLetterSound(); }); smallEl.addEventListener("click", () => { playLetterSound(); }); // ========== INIT ========== window.addEventListener("load", () => { showScreenIntro(); // start on intro showRandomLetter(); // prepare first letter renderPets(); // show pets selectPet("dog"); // set default active pet + update image/message // attempt autoplay intro (may be blocked) playIntroAudio(); });