a math app game for grades <!doctype html>
<title>Math Money Game</title> <script src="/_sdk/element_sdk.js"></script> <script src="/_sdk/data_sdk.js"></script> <script src="https://cdn.tailwindcss.com"></script> <style> body { box-sizing: border-box; } </style> <style>@view-transition { navigation: auto; }</style> <script> const defaultConfig = { background_color: "#4f46e5", card_color: "#ffffff", text_color: "#1f2937", button_color: "#10b981", secondary_button_color: "#6366f1", font_family: "system-ui", font_size: 16, game_title: "Math Money Challenge", reward_message: "Correct! You earned $10!", wrong_message: "Try again!" };const avatars = [
{ emoji: "๐ฆ", name: "Boy" },
{ emoji: "๐ง", name: "Girl" },
{ emoji: "๐ง", name: "Kid" },
{ emoji: "๐จ", name: "Man" },
{ emoji: "๐ฉ", name: "Woman" },
{ emoji: "๐ง", name: "Person" }
];
const pets = [
{ emoji: "๐ถ", name: "Dog" },
{ emoji: "๐ฑ", name: "Cat" },
{ emoji: "๐ฐ", name: "Bunny" },
{ emoji: "๐น", name: "Hamster" },
{ emoji: "๐ธ", name: "Frog" },
{ emoji: "๐ฆ", name: "Fox" }
];
const grades = ["1st", "2nd", "3rd", "4th", "5th", "6th"];
const difficulties = ["Easy", "Hard"];
let currentData = null;
let currentProblem = {};
let userAnswer = "";
let showFeedback = false;
let feedbackMessage = "";
let isCorrect = false;
let isLoading = false;
let gameStarted = false;
let showMiniGames = false;
let selectedMiniGame = null;
let miniGameActive = false;
let miniGameProblem = null;
let miniGameAnswer = "";
let miniGameFeedback = "";
let miniGameCorrect = false;
let showPetZone = false;
let showPrizeShop = false;
let showPetShop = false;
let walkingPet = false;
let walkProgress = 0;
let showBattleZone = false;
let battleActive = false;
let battleOpponent = null;
let battleRound = 0;
let playerBattleAnswer = "";
let opponentBattleAnswer = "";
let battleProblem = null;
let battleResult = "";
let playerScore = 0;
let opponentScore = 0;
let battleComplete = false;
const battleOpponents = [
{ name: "Alex", avatar: "๐ง", level: 1, speed: 3000 },
{ name: "Sam", avatar: "๐จ", level: 2, speed: 2500 },
{ name: "Jordan", avatar: "๐ฉ", level: 3, speed: 2000 },
{ name: "Taylor", avatar: "๐ง", level: 4, speed: 1500 },
{ name: "Casey", avatar: "๐ง", level: 5, speed: 1000 },
{ name: "Morgan", avatar: "๐ฆ", level: 6, speed: 800 }
];
const miniGames = [
{ name: "Speed Math", cost: 20, emoji: "โก", description: "3 quick problems!", reward: 50 },
{ name: "Brain Teaser", cost: 30, emoji: "๐ง ", description: "Hard challenge!", reward: 80 },
{ name: "Lucky Draw", cost: 15, emoji: "๐ฐ", description: "Double or nothing!", reward: 30 }
];
// Character creation state
let selectedName = "";
let selectedAvatar = avatars[0].emoji;
let selectedPet = pets[0].emoji;
let selectedGrade = "3rd";
let selectedDifficulty = "Easy";
function generateProblem(difficulty, grade) {
const gradeNum = parseInt(grade);
let max = 10;
if (difficulty === "Easy") {
if (gradeNum <= 2) max = 10;
else if (gradeNum <= 4) max = 20;
else max = 50;
} else {
if (gradeNum <= 2) max = 20;
else if (gradeNum <= 4) max = 50;
else max = 100;
}
const operations = ['+', '-', 'ร', 'รท'];
const operation = operations[Math.floor(Math.random() * operations.length)];
let num1, num2, answer;
if (operation === 'รท') {
// For division, ensure we get whole number answers
num2 = Math.floor(Math.random() * (max / 2)) + 1;
answer = Math.floor(Math.random() * (max / 2)) + 1;
num1 = num2 * answer; // This ensures num1 รท num2 = answer (whole number)
} else {
num1 = Math.floor(Math.random() * max) + 1;
num2 = Math.floor(Math.random() * max) + 1;
if (operation === '+') {
answer = num1 + num2;
} else if (operation === '-') {
answer = num1 - num2;
} else if (operation === 'ร') {
answer = num1 * num2;
}
}
return { num1, num2, operation, answer };
}
async function startGame() {
if (!selectedName.trim()) {
feedbackMessage = "Please enter your name!";
showFeedback = true;
render();
return;
}
if (currentData && currentData.length >= 999) {
feedbackMessage = "Maximum limit of 999 players reached!";
showFeedback = true;
render();
return;
}
isLoading = true;
render();
const result = await window.dataSdk.create({
player_name: selectedName,
avatar: selectedAvatar,
pet: selectedPet,
grade: selectedGrade,
difficulty: selectedDifficulty,
total_money: 0,
problems_solved: 0,
last_updated: new Date().toISOString(),
owned_pets: selectedPet,
prizes_owned: "",
pet_happiness: 100,
pet_walks: 0
});
isLoading = false;
if (!result.isOk) {
feedbackMessage = "Error starting game. Please try again.";
showFeedback = true;
render();
} else {
gameStarted = true;
currentProblem = generateProblem(selectedDifficulty, selectedGrade);
render();
}
}
async function walkPet() {
const player = currentData && currentData.length > 0 ? currentData[0] : null;
if (!player || walkingPet) return;
walkingPet = true;
walkProgress = 0;
render();
const walkInterval = setInterval(() => {
walkProgress += 10;
render();
if (walkProgress >= 100) {
clearInterval(walkInterval);
completePetWalk();
}
}, 300);
}
async function completePetWalk() {
const player = currentData && currentData.length > 0 ? currentData[0] : null;
if (!player) return;
const moneyEarned = 5;
const newHappiness = Math.min(100, player.pet_happiness + 10);
isLoading = true;
render();
const result = await window.dataSdk.update({
...player,
total_money: player.total_money + moneyEarned,
pet_happiness: newHappiness,
pet_walks: player.pet_walks + 1,
last_updated: new Date().toISOString()
});
isLoading = false;
walkingPet = false;
walkProgress = 0;
if (result.isOk) {
miniGameFeedback = `Walk complete! Earned $${moneyEarned} and +10 happiness! ๐`;
}
render();
}
async function playWithPet() {
const player = currentData && currentData.length > 0 ? currentData[0] : null;
if (!player) return;
const newHappiness = Math.min(100, player.pet_happiness + 15);
isLoading = true;
render();
const result = await window.dataSdk.update({
...player,
pet_happiness: newHappiness,
last_updated: new Date().toISOString()
});
isLoading = false;
if (result.isOk) {
miniGameFeedback = "Your pet loved playing! +15 happiness! ๐";
}
render();
}
async function buyPrize(prize) {
const player = currentData && currentData.length > 0 ? currentData[0] : null;
if (!player) return;
if (player.total_money < prize.cost) {
miniGameFeedback = `You need $${prize.cost} to buy this prize!`;
render();
return;
}
const ownedPrizes = player.prizes_owned ? player.prizes_owned.split(',') : [];
if (ownedPrizes.includes(prize.emoji)) {
miniGameFeedback = "You already own this prize!";
render();
return;
}
isLoading = true;
render();
ownedPrizes.push(prize.emoji);
const result = await window.dataSdk.update({
...player,
total_money: player.total_money - prize.cost,
prizes_owned: ownedPrizes.join(','),
last_updated: new Date().toISOString()
});
isLoading = false;
if (result.isOk) {
miniGameFeedback = `You bought ${prize.name}! ๐`;
}
render();
}
async function buyPet(pet) {
const player = currentData && currentData.length > 0 ? currentData[0] : null;
if (!player) return;
const petCost = 80;
if (player.total_money < petCost) {
miniGameFeedback = `You need $${petCost} to buy a new pet!`;
render();
return;
}
const ownedPets = player.owned_pets ? player.owned_pets.split(',') : [];
if (ownedPets.includes(pet.emoji)) {
miniGameFeedback = "You already own this pet!";
render();
return;
}
isLoading = true;
render();
ownedPets.push(pet.emoji);
const result = await window.dataSdk.update({
...player,
total_money: player.total_money - petCost,
owned_pets: ownedPets.join(','),
last_updated: new Date().toISOString()
});
isLoading = false;
if (result.isOk) {
miniGameFeedback = `You got a new ${pet.name}! ๐`;
}
render();
}
async function switchPet(petEmoji) {
const player = currentData && currentData.length > 0 ? currentData[0] : null;
if (!player) return;
isLoading = true;
render();
const result = await window.dataSdk.update({
...player,
pet: petEmoji,
last_updated: new Date().toISOString()
});
isLoading = false;
render();
}
function openPetZone() {
showPetZone = true;
miniGameFeedback = "";
render();
}
function closePetZone() {
showPetZone = false;
render();
}
function openPrizeShop() {
showPrizeShop = true;
miniGameFeedback = "";
render();
}
function closePrizeShop() {
showPrizeShop = false;
render();
}
function openPetShop() {
showPetShop = true;
miniGameFeedback = "";
render();
}
function closePetShop() {
showPetShop = false;
render();
}
async function checkAnswer() {
const numAnswer = parseInt(userAnswer);
if (isNaN(numAnswer)) {
feedbackMessage = "Please enter a number!";
showFeedback = true;
isCorrect = false;
render();
return;
}
if (numAnswer === currentProblem.answer) {
isCorrect = true;
feedbackMessage = window.elementSdk.config.reward_message || defaultConfig.reward_message;
if (currentData && currentData.length > 0) {
const gameData = currentData[0];
isLoading = true;
render();
const result = await window.dataSdk.update({
...gameData,
total_money: gameData.total_money + 10,
problems_solved: gameData.problems_solved + 1,
last_updated: new Date().toISOString()
});
isLoading = false;
if (!result.isOk) {
feedbackMessage = "Error saving progress. Please try again.";
}
}
} else {
isCorrect = false;
feedbackMessage = window.elementSdk.config.wrong_message || defaultConfig.wrong_message;
// Lose $5 for wrong answer
if (currentData && currentData.length > 0) {
const gameData = currentData[0];
const newMoney = Math.max(0, gameData.total_money - 5);
isLoading = true;
render();
const result = await window.dataSdk.update({
...gameData,
total_money: newMoney,
last_updated: new Date().toISOString()
});
isLoading = false;
if (!result.isOk) {
feedbackMessage = "Error saving progress. Please try again.";
} else {
feedbackMessage += " You lost $5!";
}
}
}
showFeedback = true;
render();
}
function nextProblem() {
const player = currentData && currentData.length > 0 ? currentData[0] : null;
if (player) {
currentProblem = generateProblem(player.difficulty, player.grade);
}
userAnswer = "";
showFeedback = false;
feedbackMessage = "";
isCorrect = false;
render();
}
function openMiniGames() {
showMiniGames = true;
render();
}
function closeMiniGames() {
showMiniGames = false;
render();
}
async function startMiniGame(game) {
const player = currentData && currentData.length > 0 ? currentData[0] : null;
if (!player) return;
if (player.total_money < game.cost) {
miniGameFeedback = `You need $${game.cost} to play this game!`;
render();
return;
}
// Deduct cost
isLoading = true;
render();
const result = await window.dataSdk.update({
...player,
total_money: player.total_money - game.cost,
last_updated: new Date().toISOString()
});
isLoading = false;
if (!result.isOk) {
miniGameFeedback = "Error starting game. Please try again.";
render();
return;
}
selectedMiniGame = game;
miniGameActive = true;
miniGameProblem = generateProblem("Hard", player.grade);
miniGameAnswer = "";
miniGameFeedback = "";
miniGameCorrect = false;
render();
}
async function checkMiniGameAnswer() {
const numAnswer = parseInt(miniGameAnswer);
const player = currentData && currentData.length > 0 ? currentData[0] : null;
if (!player || !selectedMiniGame) return;
if (isNaN(numAnswer)) {
miniGameFeedback = "Please enter a number!";
render();
return;
}
if (numAnswer === miniGameProblem.answer) {
miniGameCorrect = true;
miniGameFeedback = `Correct! You won $${selectedMiniGame.reward}! ๐`;
isLoading = true;
render();
const result = await window.dataSdk.update({
...player,
total_money: player.total_money + selectedMiniGame.reward,
last_updated: new Date().toISOString()
});
isLoading = false;
if (!result.isOk) {
miniGameFeedback = "Error saving progress.";
}
} else {
miniGameCorrect = false;
miniGameFeedback = `Wrong! You already paid $${selectedMiniGame.cost} to play.`;
}
render();
}
function exitMiniGame() {
miniGameActive = false;
selectedMiniGame = null;
showMiniGames = false;
miniGameFeedback = "";
render();
}
function openBattleZone() {
showBattleZone = true;
miniGameFeedback = "";
render();
}
function closeBattleZone() {
showBattleZone = false;
battleActive = false;
battleOpponent = null;
render();
}
async function startBattle(opponent) {
const player = currentData && currentData.length > 0 ? currentData[0] : null;
if (!player) return;
battleOpponent = opponent;
battleActive = true;
battleRound = 1;
playerScore = 0;
opponentScore = 0;
battleComplete = false;
battleResult = "";
playerBattleAnswer = "";
battleProblem = generateProblem(player.difficulty, player.grade);
// Simulate opponent answer with delay
setTimeout(() => {
const correctChance = Math.random();
const opponentAccuracy = 1 - (opponent.level * 0.1); // Higher level = more accurate
if (correctChance > opponentAccuracy) {
opponentBattleAnswer = battleProblem.answer.toString();
} else {
opponentBattleAnswer = (battleProblem.answer + Math.floor(Math.random() * 5) - 2).toString();
}
render();
}, opponent.speed);
render();
}
async function submitBattleAnswer() {
const numAnswer = parseInt(playerBattleAnswer);
if (isNaN(numAnswer)) {
miniGameFeedback = "Please enter a number!";
render();
return;
}
const player = currentData && currentData.length > 0 ? currentData[0] : null;
if (!player) return;
// Check player answer
if (numAnswer === battleProblem.answer) {
playerScore++;
}
// Check opponent answer (if they've answered)
if (opponentBattleAnswer && parseInt(opponentBattleAnswer) === battleProblem.answer) {
opponentScore++;
}
if (battleRound >= 3) {
// Battle complete
battleComplete = true;
let moneyChange = 0;
let resultMsg = "";
if (playerScore > opponentScore) {
moneyChange = 30;
resultMsg = `๐ You won ${playerScore}-${opponentScore}! Earned $${moneyChange}!`;
} else if (playerScore < opponentScore) {
moneyChange = -10;
resultMsg = `๐ข You lost ${playerScore}-${opponentScore}. Lost $${Math.abs(moneyChange)}.`;
} else {
moneyChange = 5;
resultMsg = `๐ค It's a tie ${playerScore}-${opponentScore}! Earned $${moneyChange}!`;
}
battleResult = resultMsg;
// Update money
isLoading = true;
render();
const newMoney = Math.max(0, player.total_money + moneyChange);
const result = await window.dataSdk.update({
...player,
total_money: newMoney,
last_updated: new Date().toISOString()
});
isLoading = false;
render();
} else {
// Next round
battleRound++;
playerBattleAnswer = "";
opponentBattleAnswer = "";
battleProblem = generateProblem(player.difficulty, player.grade);
// Simulate opponent answer with delay
setTimeout(() => {
const correctChance = Math.random();
const opponentAccuracy = 1 - (battleOpponent.level * 0.1);
if (correctChance > opponentAccuracy) {
opponentBattleAnswer = battleProblem.answer.toString();
} else {
opponentBattleAnswer = (battleProblem.answer + Math.floor(Math.random() * 5) - 2).toString();
}
render();
}, battleOpponent.speed);
render();
}
}
function exitBattle() {
battleActive = false;
battleOpponent = null;
battleComplete = false;
showBattleZone = false;
render();
}
function renderCharacterCreation() {
const config = window.elementSdk.config;
const backgroundColor = config.background_color || defaultConfig.background_color;
const cardColor = config.card_color || defaultConfig.card_color;
const textColor = config.text_color || defaultConfig.text_color;
const buttonColor = config.button_color || defaultConfig.button_color;
const secondaryButtonColor = config.secondary_button_color || defaultConfig.secondary_button_color;
const fontFamily = config.font_family || defaultConfig.font_family;
const fontSize = config.font_size || defaultConfig.font_size;
const gameTitle = config.game_title || defaultConfig.game_title;
document.getElementById('app').innerHTML = `
<div style="background: ${backgroundColor}; font-family: ${fontFamily}, Arial, sans-serif; min-height: 100%;" class="flex items-center justify-center p-6">
<div style="background: ${cardColor}; max-width: 600px;" class="w-full rounded-3xl shadow-2xl p-8">
<h1 style="color: ${textColor}; font-size: ${fontSize * 2}px;" class="font-bold text-center mb-6">${gameTitle}</h1>
<form id="characterForm">
<div class="mb-6">
<label for="nameInput" style="color: ${textColor}; font-size: ${fontSize}px;" class="block mb-2 font-semibold">Your Name:</label>
<input
type="text"
id="nameInput"
value="${selectedName}"
placeholder="Enter your name"
style="border: 3px solid ${secondaryButtonColor}; color: ${textColor}; font-size: ${fontSize}px;"
class="w-full p-3 rounded-xl focus:outline-none focus:ring-4 focus:ring-opacity-50"
required
>
</div>
<div class="mb-6">
<label style="color: ${textColor}; font-size: ${fontSize}px;" class="block mb-3 font-semibold">Choose Your Avatar:</label>
<div class="grid grid-cols-3 gap-3">
${avatars.map(avatar => `
<button
type="button"
class="avatar-btn p-4 rounded-xl border-4 hover:scale-105 transition-transform"
style="border-color: ${selectedAvatar === avatar.emoji ? buttonColor : '#e5e7eb'}; background: ${selectedAvatar === avatar.emoji ? buttonColor + '20' : '#f9fafb'};"
data-avatar="${avatar.emoji}"
>
<div style="font-size: ${fontSize * 3}px;" class="text-center">${avatar.emoji}</div>
<div style="color: ${textColor}; font-size: ${fontSize * 0.75}px;" class="text-center mt-1">${avatar.name}</div>
</button>
`).join('')}
</div>
</div>
<div class="mb-6">
<label style="color: ${textColor}; font-size: ${fontSize}px;" class="block mb-3 font-semibold">Choose Your Pet:</label>
<div class="grid grid-cols-3 gap-3">
${pets.map(pet => `
<button
type="button"
class="pet-btn p-4 rounded-xl border-4 hover:scale-105 transition-transform"
style="border-color: ${selectedPet === pet.emoji ? buttonColor : '#e5e7eb'}; background: ${selectedPet === pet.emoji ? buttonColor + '20' : '#f9fafb'};"
data-pet="${pet.emoji}"
>
<div style="font-size: ${fontSize * 3}px;" class="text-center">${pet.emoji}</div>
<div style="color: ${textColor}; font-size: ${fontSize * 0.75}px;" class="text-center mt-1">${pet.name}</div>
</button>
`).join('')}
</div>
</div>
<div class="mb-6">
<label for="gradeSelect" style="color: ${textColor}; font-size: ${fontSize}px;" class="block mb-2 font-semibold">Your Grade:</label>
<select
id="gradeSelect"
style="border: 3px solid ${secondaryButtonColor}; color: ${textColor}; font-size: ${fontSize}px;"
class="w-full p-3 rounded-xl focus:outline-none focus:ring-4 focus:ring-opacity-50"
>
${grades.map(grade => `
<option value="${grade}" ${selectedGrade === grade ? 'selected' : ''}>${grade} Grade</option>
`).join('')}
</select>
</div>
<div class="mb-6">
<label style="color: ${textColor}; font-size: ${fontSize}px;" class="block mb-3 font-semibold">Difficulty:</label>
<div class="grid grid-cols-2 gap-3">
${difficulties.map(diff => `
<button
type="button"
class="difficulty-btn p-4 rounded-xl border-4 hover:scale-105 transition-transform font-bold"
style="border-color: ${selectedDifficulty === diff ? buttonColor : '#e5e7eb'}; background: ${selectedDifficulty === diff ? buttonColor : '#f9fafb'}; color: ${selectedDifficulty === diff ? '#ffffff' : textColor}; font-size: ${fontSize}px;"
data-difficulty="${diff}"
>
${diff}
</button>
`).join('')}
</div>
</div>
${showFeedback ? `
<div style="background: #ef4444; font-size: ${fontSize * 0.9}px;" class="rounded-xl p-3 text-white text-center mb-4">
${feedbackMessage}
</div>
` : ''}
<button
type="submit"
style="background: ${buttonColor}; font-size: ${fontSize * 1.1}px;"
class="w-full text-white font-bold py-4 px-6 rounded-xl hover:opacity-90 transition-opacity disabled:opacity-50"
${isLoading ? 'disabled' : ''}
>
${isLoading ? 'Starting...' : 'Start Game! ๐'}
</button>
</form>
</div>
</div>
`;
// Add event listeners
const nameInput = document.getElementById('nameInput');
if (nameInput) {
nameInput.addEventListener('input', (e) => {
selectedName = e.target.value;
});
}
const gradeSelect = document.getElementById('gradeSelect');
if (gradeSelect) {
gradeSelect.addEventListener('change', (e) => {
selectedGrade = e.target.value;
});
}
document.querySelectorAll('.avatar-btn').forEach(btn => {
btn.addEventListener('click', (e) => {
selectedAvatar = e.currentTarget.dataset.avatar;
render();
});
});
document.querySelectorAll('.pet-btn').forEach(btn => {
btn.addEventListener('click', (e) => {
selectedPet = e.currentTarget.dataset.pet;
render();
});
});
document.querySelectorAll('.difficulty-btn').forEach(btn => {
btn.addEventListener('click', (e) => {
selectedDifficulty = e.currentTarget.dataset.difficulty;
render();
});
});
const form = document.getElementById('characterForm');
if (form) {
form.addEventListener('submit', (e) => {
e.preventDefault();
startGame();
});
}
}
function renderGame() {
const config = window.elementSdk.config;
const backgroundColor = config.background_color || defaultConfig.background_color;
const cardColor = config.card_color || defaultConfig.card_color;
const textColor = config.text_color || defaultConfig.text_color;
const buttonColor = config.button_color || defaultConfig.button_color;
const secondaryButtonColor = config.secondary_button_color || defaultConfig.secondary_button_color;
const fontFamily = config.font_family || defaultConfig.font_family;
const fontSize = config.font_size || defaultConfig.font_size;
const player = currentData && currentData.length > 0 ? currentData[0] : null;
const money = player ? player.total_money : 0;
const problemsSolved = player ? player.problems_solved : 0;
const playerName = player ? player.player_name : "";
const avatar = player ? player.avatar : "๐ฆ";
const pet = player ? player.pet : "๐ถ";
document.getElementById('app').innerHTML = `
<div style="background: ${backgroundColor}; font-family: ${fontFamily}, Arial, sans-serif; min-height: 100%;" class="flex items-center justify-center p-6">
<div style="background: ${cardColor}; max-width: 500px;" class="w-full rounded-3xl shadow-2xl p-8">
<div class="flex items-center justify-between mb-6">
<div class="flex items-center gap-3">
<div style="font-size: ${fontSize * 3}px;">${avatar}</div>
<div>
<div style="color: ${textColor}; font-size: ${fontSize * 1.1}px;" class="font-bold">${playerName}</div>
<div style="color: ${textColor}; font-size: ${fontSize * 0.8}px;" class="opacity-70">with ${pet}</div>
</div>
</div>
</div>
<div style="background: ${backgroundColor}; font-size: ${fontSize * 1.3}px;" class="rounded-2xl p-5 text-white text-center mb-6">
<div class="font-bold mb-2">๐ฐ Money: $${money}</div>
<div style="font-size: ${fontSize * 0.9}px;">Solved: ${problemsSolved}</div>
</div>
<div class="grid grid-cols-3 gap-2 mb-4">
<button
type="button"
id="miniGamesBtn"
style="background: ${secondaryButtonColor}; font-size: ${fontSize * 0.8}px;"
class="text-white font-bold py-3 px-2 rounded-xl hover:opacity-90 transition-opacity"
>
๐ฎ Games
</button>
<button
type="button"
id="petZoneBtn"
style="background: #ec4899; font-size: ${fontSize * 0.8}px;"
class="text-white font-bold py-3 px-2 rounded-xl hover:opacity-90 transition-opacity"
>
๐พ Pet Zone
</button>
<button
type="button"
id="prizeShopBtn"
style="background: #f59e0b; font-size: ${fontSize * 0.8}px;"
class="text-white font-bold py-3 px-2 rounded-xl hover:opacity-90 transition-opacity"
>
๐ Prizes
</button>
</div>
<button
type="button"
id="battleZoneBtn"
style="background: #ef4444; font-size: ${fontSize * 0.9}px;"
class="w-full text-white font-bold py-3 px-4 rounded-xl hover:opacity-90 transition-opacity mb-4"
>
โ๏ธ Battle Zone - Challenge Players!
</button>
<div style="background: linear-gradient(135deg, ${secondaryButtonColor}, ${backgroundColor}); font-size: ${fontSize * 2.5}px;" class="rounded-2xl p-8 text-white text-center mb-6 font-bold">
${currentProblem.num1} ${currentProblem.operation} ${currentProblem.num2} = ?
</div>
<form id="answerForm" class="mb-4">
<label for="answerInput" style="color: ${textColor}; font-size: ${fontSize}px;" class="block mb-2 font-semibold">Your Answer:</label>
<input
type="number"
id="answerInput"
value="${userAnswer}"
style="border: 3px solid ${secondaryButtonColor}; color: ${textColor}; font-size: ${fontSize * 1.2}px;"
class="w-full p-4 rounded-xl focus:outline-none focus:ring-4 focus:ring-opacity-50 mb-4"
${isLoading ? 'disabled' : ''}
required
>
${showFeedback ? `
<div style="background: ${isCorrect ? buttonColor : '#ef4444'}; font-size: ${fontSize}px;" class="rounded-xl p-4 text-white text-center mb-4 font-semibold">
${isCorrect ? 'โ' : 'โ'} ${feedbackMessage}
</div>
` : ''}
<div class="flex gap-3">
${!showFeedback ? `
<button
type="submit"
style="background: ${buttonColor}; font-size: ${fontSize}px;"
class="flex-1 text-white font-bold py-4 px-6 rounded-xl hover:opacity-90 transition-opacity disabled:opacity-50"
${isLoading ? 'disabled' : ''}
>
${isLoading ? 'Checking...' : 'Check Answer'}
</button>
` : `
<button
type="button"
id="nextButton"
style="background: ${secondaryButtonColor}; font-size: ${fontSize}px;"
class="flex-1 text-white font-bold py-4 px-6 rounded-xl hover:opacity-90 transition-opacity"
>
Next Problem โ
</button>
`}
</div>
</form>
<div style="color: ${textColor}; font-size: ${fontSize * 0.85}px;" class="text-center opacity-70">
Earn $10 for each correct answer! Lose $5 for wrong answers.
</div>
</div>
${showPetZone ? `
<div style="position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.7); display: flex; align-items: center; justify-content: center; padding: 20px; z-index: 1000;">
<div style="background: ${cardColor}; max-width: 550px; width: 100%; border-radius: 24px; padding: 32px; max-height: 90%; overflow-y: auto;">
<div class="flex justify-between items-center mb-6">
<h2 style="color: ${textColor}; font-size: ${fontSize * 1.5}px;" class="font-bold">๐พ Pet Zone</h2>
<button id="closePetZone" style="color: ${textColor}; font-size: ${fontSize * 1.5}px;" class="hover:opacity-70">โ</button>
</div>
${miniGameFeedback ? `
<div style="background: ${buttonColor}; font-size: ${fontSize * 0.9}px; margin-bottom: 16px;" class="rounded-xl p-3 text-white text-center">
${miniGameFeedback}
</div>
` : ''}
<div style="background: linear-gradient(135deg, #ec4899, #f59e0b); padding: 24px; border-radius: 16px; margin-bottom: 24px;">
<div style="font-size: ${fontSize * 5}px;" class="text-center mb-3">${pet}</div>
<div style="color: white; font-size: ${fontSize * 1.2}px;" class="font-bold text-center mb-2">Happiness: ${player ? player.pet_happiness : 100}%</div>
<div style="background: rgba(255,255,255,0.3); height: 12px; border-radius: 6px; overflow: hidden;">
<div style="background: white; height: 100%; width: ${player ? player.pet_happiness : 100}%; transition: width 0.3s;"></div>
</div>
<div style="color: white; font-size: ${fontSize * 0.85}px;" class="text-center mt-2">Walks: ${player ? player.pet_walks : 0}</div>
</div>
<div class="grid grid-cols-2 gap-3 mb-6">
<button
id="walkPetBtn"
style="background: ${buttonColor}; font-size: ${fontSize}px; padding: 16px; border-radius: 12px;"
class="text-white font-bold hover:opacity-90 transition-opacity ${walkingPet ? 'opacity-50' : ''}"
${walkingPet || isLoading ? 'disabled' : ''}
>
${walkingPet ? `๐ถ Walking... ${walkProgress}%` : '๐ถ Walk Pet (+$5)'}
</button>
<button
id="playPetBtn"
style="background: ${secondaryButtonColor}; font-size: ${fontSize}px; padding: 16px; border-radius: 12px;"
class="text-white font-bold hover:opacity-90 transition-opacity disabled:opacity-50"
${isLoading ? 'disabled' : ''}
>
๐พ Play (+15 โค๏ธ)
</button>
</div>
<div class="mb-4">
<h3 style="color: ${textColor}; font-size: ${fontSize * 1.1}px;" class="font-bold mb-3">Your Pets:</h3>
<div class="grid grid-cols-4 gap-2">
${(player && player.owned_pets ? player.owned_pets.split(',') : []).map(petEmoji => `
<button
class="switch-pet-btn p-3 rounded-lg border-4 hover:scale-105 transition-transform"
style="border-color: ${pet === petEmoji ? buttonColor : '#e5e7eb'}; background: ${pet === petEmoji ? buttonColor + '20' : '#f9fafb'}; font-size: ${fontSize * 2.5}px;"
data-pet="${petEmoji}"
>
${petEmoji}
</button>
`).join('')}
</div>
</div>
<button
id="openPetShopBtn"
style="background: #8b5cf6; font-size: ${fontSize}px;"
class="w-full text-white font-bold py-4 px-6 rounded-xl hover:opacity-90 transition-opacity"
>
๐ Pet Shop (Buy More Pets - $80 each)
</button>
</div>
</div>
` : ''}
${showPetShop ? `
<div style="position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.7); display: flex; align-items: center; justify-content: center; padding: 20px; z-index: 1001;">
<div style="background: ${cardColor}; max-width: 550px; width: 100%; border-radius: 24px; padding: 32px; max-height: 90%; overflow-y: auto;">
<div class="flex justify-between items-center mb-6">
<h2 style="color: ${textColor}; font-size: ${fontSize * 1.5}px;" class="font-bold">๐ Pet Shop</h2>
<button id="closePetShop" style="color: ${textColor}; font-size: ${fontSize * 1.5}px;" class="hover:opacity-70">โ</button>
</div>
${miniGameFeedback ? `
<div style="background: ${miniGameFeedback.includes('need') ? '#ef4444' : buttonColor}; font-size: ${fontSize * 0.9}px; margin-bottom: 16px;" class="rounded-xl p-3 text-white text-center">
${miniGameFeedback}
</div>
` : ''}
<div style="color: ${textColor}; font-size: ${fontSize * 0.9}px; margin-bottom: 16px; padding: 12px; background: #dbeafe; border-radius: 12px; text-align: center;">
๐ฐ Your Money: $${money} | Each pet costs $80
</div>
<div class="grid grid-cols-3 gap-3">
${allPets.map((petItem, idx) => {
const ownedPets = player && player.owned_pets ? player.owned_pets.split(',') : [];
const isOwned = ownedPets.includes(petItem.emoji);
return `
<button
class="buy-pet-btn p-4 rounded-xl border-4 hover:scale-105 transition-transform"
style="border-color: ${isOwned ? buttonColor : '#e5e7eb'}; background: ${isOwned ? buttonColor + '20' : '#f9fafb'};"
data-pet-index="${idx}"
${isOwned ? 'disabled' : ''}
>
<div style="font-size: ${fontSize * 3}px;" class="text-center mb-1">${petItem.emoji}</div>
<div style="color: ${textColor}; font-size: ${fontSize * 0.7}px;" class="text-center font-semibold">
${isOwned ? 'โ Owned' : '$80'}
</div>
</button>
`;
}).join('')}
</div>
</div>
</div>
` : ''}
${showPrizeShop ? `
<div style="position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.7); display: flex; align-items: center; justify-content: center; padding: 20px; z-index: 1000;">
<div style="background: ${cardColor}; max-width: 550px; width: 100%; border-radius: 24px; padding: 32px; max-height: 90%; overflow-y: auto;">
<div class="flex justify-between items-center mb-6">
<h2 style="color: ${textColor}; font-size: ${fontSize * 1.5}px;" class="font-bold">๐ Prize Shop</h2>
<button id="closePrizeShop" style="color: ${textColor}; font-size: ${fontSize * 1.5}px;" class="hover:opacity-70">โ</button>
</div>
${miniGameFeedback ? `
<div style="background: ${miniGameFeedback.includes('need') || miniGameFeedback.includes('already') ? '#ef4444' : buttonColor}; font-size: ${fontSize * 0.9}px; margin-bottom: 16px;" class="rounded-xl p-3 text-white text-center">
${miniGameFeedback}
</div>
` : ''}
<div style="color: ${textColor}; font-size: ${fontSize * 0.9}px; margin-bottom: 16px; padding: 12px; background: #fef3c7; border-radius: 12px; text-align: center;">
๐ฐ Your Money: $${money}
</div>
${player && player.prizes_owned ? `
<div style="background: ${backgroundColor}; padding: 16px; border-radius: 12px; margin-bottom: 16px;">
<div style="color: white; font-size: ${fontSize * 0.9}px;" class="font-bold mb-2">Your Prizes:</div>
<div style="font-size: ${fontSize * 2}px; color: white;" class="text-center">
${player.prizes_owned.split(',').filter(p => p).join(' ')}
</div>
</div>
` : ''}
<div class="grid grid-cols-2 gap-3">
${prizes.map((prize, idx) => {
const ownedPrizes = player && player.prizes_owned ? player.prizes_owned.split(',') : [];
const isOwned = ownedPrizes.includes(prize.emoji);
return `
<button
class="buy-prize-btn p-5 rounded-xl border-4 hover:scale-105 transition-transform"
style="border-color: ${isOwned ? buttonColor : secondaryButtonColor}; background: ${isOwned ? buttonColor + '20' : '#f0f9ff'};"
data-prize-index="${idx}"
${isOwned ? 'disabled' : ''}
>
<div style="font-size: ${fontSize * 3}px;" class="text-center mb-2">${prize.emoji}</div>
<div style="color: ${textColor}; font-size: ${fontSize * 0.85}px;" class="text-center font-bold mb-1">${prize.name}</div>
<div style="color: ${textColor}; font-size: ${fontSize * 0.8}px;" class="text-center font-semibold">
${isOwned ? 'โ Owned' : `$${prize.cost}`}
</div>
</button>
`;
}).join('')}
</div>
</div>
</div>
` : ''}
${showBattleZone && !battleActive ? `
<div style="position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.7); display: flex; align-items: center; justify-content: center; padding: 20px; z-index: 1000;">
<div style="background: ${cardColor}; max-width: 550px; width: 100%; border-radius: 24px; padding: 32px; max-height: 90%; overflow-y: auto;">
<div class="flex justify-between items-center mb-6">
<h2 style="color: ${textColor}; font-size: ${fontSize * 1.5}px;" class="font-bold">โ๏ธ Battle Zone</h2>
<button id="closeBattleZone" style="color: ${textColor}; font-size: ${fontSize * 1.5}px;" class="hover:opacity-70">โ</button>
</div>
<div style="background: linear-gradient(135deg, #ef4444, #dc2626); padding: 20px; border-radius: 16px; margin-bottom: 24px; color: white; text-align: center;">
<div style="font-size: ${fontSize * 1.2}px;" class="font-bold mb-2">๐ Math Battle Challenge</div>
<div style="font-size: ${fontSize * 0.9}px;">3 rounds of math problems!</div>
<div style="font-size: ${fontSize * 0.85}px; margin-top: 8px;">Win: +$30 | Lose: -$10 | Tie: +$5</div>
</div>
<h3 style="color: ${textColor}; font-size: ${fontSize * 1.1}px;" class="font-bold mb-3">Choose Your Opponent:</h3>
<div class="space-y-3">
${battleOpponents.map((opp, idx) => `
<button
class="battle-opponent-btn w-full text-left p-4 rounded-xl border-4 hover:scale-102 transition-transform"
style="border-color: ${secondaryButtonColor}; background: linear-gradient(135deg, ${idx % 2 === 0 ? '#fee2e2' : '#fef3c7'}, ${idx % 2 === 0 ? '#fecaca' : '#fde68a'});"
data-opponent-index="${idx}"
>
<div class="flex items-center justify-between">
<div class="flex items-center gap-3">
<div style="font-size: ${fontSize * 2.5}px;">${opp.avatar}</div>
<div>
<div style="color: ${textColor}; font-size: ${fontSize * 1.1}px;" class="font-bold">${opp.name}</div>
<div style="color: ${textColor}; font-size: ${fontSize * 0.85}px;" class="opacity-70">Level ${opp.level}</div>
</div>
</div>
<div style="background: ${buttonColor}; color: white; font-size: ${fontSize * 0.85}px; padding: 8px 16px; border-radius: 8px; font-weight: bold;">
Battle!
</div>
</div>
</button>
`).join('')}
</div>
<div style="background: #dbeafe; padding: 16px; border-radius: 12px; margin-top: 16px;">
<div style="color: ${textColor}; font-size: ${fontSize * 0.85}px; text-align: center;">
๐ก Tip: Higher level opponents are faster and more accurate!
</div>
</div>
</div>
</div>
` : ''}
${battleActive && battleOpponent ? `
<div style="position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.7); display: flex; align-items: center; justify-content: center; padding: 20px; z-index: 1000;">
<div style="background: ${cardColor}; max-width: 550px; width: 100%; border-radius: 24px; padding: 32px;">
<div class="flex justify-between items-center mb-6">
<div class="flex items-center gap-3">
<div style="font-size: ${fontSize * 2}px;">${player ? player.avatar : '๐ฆ'}</div>
<div style="color: ${textColor}; font-size: ${fontSize * 1.1}px;" class="font-bold">${player ? player.player_name : 'You'}</div>
</div>
<div style="color: ${textColor}; font-size: ${fontSize * 1.3}px;" class="font-bold">VS</div>
<div class="flex items-center gap-3">
<div style="color: ${textColor}; font-size: ${fontSize * 1.1}px;" class="font-bold">${battleOpponent.name}</div>
<div style="font-size: ${fontSize * 2}px;">${battleOpponent.avatar}</div>
</div>
</div>
<div style="background: linear-gradient(135deg, #ef4444, #dc2626); padding: 16px; border-radius: 12px; margin-bottom: 16px; color: white; text-align: center;">
<div style="font-size: ${fontSize}px; font-weight: bold;">Round ${battleRound} of 3</div>
<div style="font-size: ${fontSize * 0.9}px; margin-top: 4px;">Score: ${playerScore} - ${opponentScore}</div>
</div>
${!battleComplete ? `
<div style="background: linear-gradient(135deg, ${secondaryButtonColor}, ${backgroundColor}); font-size: ${fontSize * 2.5}px;" class="rounded-2xl p-8 text-white text-center mb-6 font-bold">
${battleProblem.num1} ${battleProblem.operation} ${battleProblem.num2} = ?
</div>
<form id="battleForm">
<label for="battleInput" style="color: ${textColor}; font-size: ${fontSize}px;" class="block mb-2 font-semibold">Your Answer:</label>
<input
type="number"
id="battleInput"
value="${playerBattleAnswer}"
style="border: 3px solid ${secondaryButtonColor}; color: ${textColor}; font-size: ${fontSize * 1.2}px;"
class="w-full p-4 rounded-xl focus:outline-none focus:ring-4 focus:ring-opacity-50 mb-4"
${isLoading ? 'disabled' : ''}
required
>
<div style="background: #fef3c7; padding: 12px; border-radius: 12px; margin-bottom: 16px; text-align: center;">
<div style="color: ${textColor}; font-size: ${fontSize * 0.9}px;">
${opponentBattleAnswer ? `${battleOpponent.name} has answered! โ` : `${battleOpponent.name} is thinking...`}
</div>
</div>
<button
type="submit"
style="background: ${buttonColor}; font-size: ${fontSize}px;"
class="w-full text-white font-bold py-4 px-6 rounded-xl hover:opacity-90 transition-opacity disabled:opacity-50"
${isLoading ? 'disabled' : ''}
>
${isLoading ? 'Checking...' : 'Submit Answer!'}
</button>
</form>
` : `
<div style="background: ${playerScore > opponentScore ? buttonColor : playerScore < opponentScore ? '#ef4444' : '#f59e0b'}; padding: 24px; border-radius: 16px; margin-bottom: 16px; text-align: center;">
<div style="font-size: ${fontSize * 2}px; margin-bottom: 8px;">
${playerScore > opponentScore ? '๐' : playerScore < opponentScore ? '๐ข' : '๐ค'}
</div>
<div style="color: white; font-size: ${fontSize * 1.2}px; font-weight: bold; margin-bottom: 8px;">
${battleResult}
</div>
<div style="color: white; font-size: ${fontSize}px;">
Final Score: ${playerScore} - ${opponentScore}
</div>
</div>
<button
type="button"
id="exitBattleBtn"
style="background: ${secondaryButtonColor}; font-size: ${fontSize}px;"
class="w-full text-white font-bold py-4 px-6 rounded-xl hover:opacity-90 transition-opacity"
>
Back to Battle Zone
</button>
`}
</div>
</div>
` : ''}
${showMiniGames && !miniGameActive ? `
<div style="position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.7); display: flex; align-items: center; justify-content: center; padding: 20px; z-index: 1000;">
<div style="background: ${cardColor}; max-width: 500px; width: 100%; border-radius: 24px; padding: 32px; max-height: 90%; overflow-y: auto;">
<div class="flex justify-between items-center mb-6">
<h2 style="color: ${textColor}; font-size: ${fontSize * 1.5}px;" class="font-bold">๐ฎ Mini-Games</h2>
<button id="closeMiniGames" style="color: ${textColor}; font-size: ${fontSize * 1.5}px;" class="hover:opacity-70">โ</button>
</div>
${miniGameFeedback ? `
<div style="background: #ef4444; font-size: ${fontSize * 0.9}px; margin-bottom: 16px;" class="rounded-xl p-3 text-white text-center">
${miniGameFeedback}
</div>
` : ''}
<div style="color: ${textColor}; font-size: ${fontSize * 0.9}px; margin-bottom: 24px; padding: 12px; background: #fef3c7; border-radius: 12px;">
โ ๏ธ Pay to play! Wrong answers = lose your entry fee!
</div>
<div class="space-y-4">
${miniGames.map((game, idx) => `
<button
class="mini-game-btn w-full text-left p-5 rounded-xl border-4 hover:scale-102 transition-transform"
style="border-color: ${secondaryButtonColor}; background: ${idx === 0 ? '#fef3c7' : idx === 1 ? '#ddd6fe' : '#fce7f3'};"
data-game-index="${idx}"
>
<div class="flex justify-between items-start">
<div>
<div style="font-size: ${fontSize * 2}px;" class="mb-2">${game.emoji}</div>
<div style="color: ${textColor}; font-size: ${fontSize * 1.1}px;" class="font-bold mb-1">${game.name}</div>
<div style="color: ${textColor}; font-size: ${fontSize * 0.85}px;" class="opacity-70 mb-2">${game.description}</div>
<div style="color: ${textColor}; font-size: ${fontSize * 0.9}px;" class="font-semibold">
๐ฐ Cost: $${game.cost} | Win: $${game.reward}
</div>
</div>
<div style="background: ${buttonColor}; color: white; font-size: ${fontSize * 0.85}px; padding: 8px 16px; border-radius: 8px; font-weight: bold;">
Play
</div>
</div>
</button>
`).join('')}
</div>
</div>
</div>
` : ''}
${miniGameActive && selectedMiniGame ? `
<div style="position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.7); display: flex; align-items: center; justify-content: center; padding: 20px; z-index: 1000;">
<div style="background: ${cardColor}; max-width: 500px; width: 100%; border-radius: 24px; padding: 32px;">
<h2 style="color: ${textColor}; font-size: ${fontSize * 1.5}px;" class="font-bold text-center mb-4">
${selectedMiniGame.emoji} ${selectedMiniGame.name}
</h2>
<div style="background: linear-gradient(135deg, ${secondaryButtonColor}, ${backgroundColor}); font-size: ${fontSize * 2.5}px;" class="rounded-2xl p-8 text-white text-center mb-6 font-bold">
${miniGameProblem.num1} ${miniGameProblem.operation} ${miniGameProblem.num2} = ?
</div>
<form id="miniGameForm">
<label for="miniGameInput" style="color: ${textColor}; font-size: ${fontSize}px;" class="block mb-2 font-semibold">Your Answer:</label>
<input
type="number"
id="miniGameInput"
value="${miniGameAnswer}"
style="border: 3px solid ${secondaryButtonColor}; color: ${textColor}; font-size: ${fontSize * 1.2}px;"
class="w-full p-4 rounded-xl focus:outline-none focus:ring-4 focus:ring-opacity-50 mb-4"
${isLoading || miniGameFeedback ? 'disabled' : ''}
required
>
${miniGameFeedback ? `
<div style="background: ${miniGameCorrect ? buttonColor : '#ef4444'}; font-size: ${fontSize}px;" class="rounded-xl p-4 text-white text-center mb-4 font-semibold">
${miniGameCorrect ? 'โ' : 'โ'} ${miniGameFeedback}
</div>
` : ''}
${!miniGameFeedback ? `
<button
type="submit"
style="background: ${buttonColor}; font-size: ${fontSize}px;"
class="w-full text-white font-bold py-4 px-6 rounded-xl hover:opacity-90 transition-opacity disabled:opacity-50 mb-3"
${isLoading ? 'disabled' : ''}
>
${isLoading ? 'Checking...' : 'Submit Answer'}
</button>
` : ''}
<button
type="button"
id="exitMiniGameBtn"
style="background: #6b7280; font-size: ${fontSize * 0.9}px;"
class="w-full text-white font-bold py-3 px-6 rounded-xl hover:opacity-90 transition-opacity"
>
${miniGameFeedback ? 'Close' : 'Exit Game'}
</button>
</form>
</div>
</div>
` : ''}
</div>
`;
const form = document.getElementById('answerForm');
if (form) {
form.addEventListener('submit', (e) => {
e.preventDefault();
checkAnswer();
});
}
const input = document.getElementById('answerInput');
if (input) {
input.addEventListener('input', (e) => {
userAnswer = e.target.value;
});
input.focus();
}
const nextButton = document.getElementById('nextButton');
if (nextButton) {
nextButton.addEventListener('click', nextProblem);
}
const miniGamesBtn = document.getElementById('miniGamesBtn');
if (miniGamesBtn) {
miniGamesBtn.addEventListener('click', openMiniGames);
}
const petZoneBtn = document.getElementById('petZoneBtn');
if (petZoneBtn) {
petZoneBtn.addEventListener('click', openPetZone);
}
const prizeShopBtn = document.getElementById('prizeShopBtn');
if (prizeShopBtn) {
prizeShopBtn.addEventListener('click', openPrizeShop);
}
const battleZoneBtn = document.getElementById('battleZoneBtn');
if (battleZoneBtn) {
battleZoneBtn.addEventListener('click', openBattleZone);
}
const closeBattleZoneBtn = document.getElementById('closeBattleZone');
if (closeBattleZoneBtn) {
closeBattleZoneBtn.addEventListener('click', closeBattleZone);
}
document.querySelectorAll('.battle-opponent-btn').forEach(btn => {
btn.addEventListener('click', (e) => {
const oppIndex = parseInt(e.currentTarget.dataset.opponentIndex);
startBattle(battleOpponents[oppIndex]);
});
});
const battleForm = document.getElementById('battleForm');
if (battleForm) {
battleForm.addEventListener('submit', (e) => {
e.preventDefault();
submitBattleAnswer();
});
}
const battleInput = document.getElementById('battleInput');
if (battleInput) {
battleInput.addEventListener('input', (e) => {
playerBattleAnswer = e.target.value;
});
battleInput.focus();
}
const exitBattleBtn = document.getElementById('exitBattleBtn');
if (exitBattleBtn) {
exitBattleBtn.addEventListener('click', exitBattle);
}
const closePetZoneBtn = document.getElementById('closePetZone');
if (closePetZoneBtn) {
closePetZoneBtn.addEventListener('click', closePetZone);
}
const closePrizeShopBtn = document.getElementById('closePrizeShop');
if (closePrizeShopBtn) {
closePrizeShopBtn.addEventListener('click', closePrizeShop);
}
const closePetShopBtn = document.getElementById('closePetShop');
if (closePetShopBtn) {
closePetShopBtn.addEventListener('click', closePetShop);
}
const walkPetBtn = document.getElementById('walkPetBtn');
if (walkPetBtn) {
walkPetBtn.addEventListener('click', walkPet);
}
const playPetBtn = document.getElementById('playPetBtn');
if (playPetBtn) {
playPetBtn.addEventListener('click', playWithPet);
}
const openPetShopBtn = document.getElementById('openPetShopBtn');
if (openPetShopBtn) {
openPetShopBtn.addEventListener('click', openPetShop);
}
document.querySelectorAll('.switch-pet-btn').forEach(btn => {
btn.addEventListener('click', (e) => {
const petEmoji = e.currentTarget.dataset.pet;
switchPet(petEmoji);
});
});
document.querySelectorAll('.buy-pet-btn').forEach(btn => {
btn.addEventListener('click', (e) => {
const petIndex = parseInt(e.currentTarget.dataset.petIndex);
buyPet(allPets[petIndex]);
});
});
document.querySelectorAll('.buy-prize-btn').forEach(btn => {
btn.addEventListener('click', (e) => {
const prizeIndex = parseInt(e.currentTarget.dataset.prizeIndex);
buyPrize(prizes[prizeIndex]);
});
});
const closeMiniGamesBtn = document.getElementById('closeMiniGames');
if (closeMiniGamesBtn) {
closeMiniGamesBtn.addEventListener('click', closeMiniGames);
}
document.querySelectorAll('.mini-game-btn').forEach(btn => {
btn.addEventListener('click', (e) => {
const gameIndex = parseInt(e.currentTarget.dataset.gameIndex);
startMiniGame(miniGames[gameIndex]);
});
});
const miniGameForm = document.getElementById('miniGameForm');
if (miniGameForm) {
miniGameForm.addEventListener('submit', (e) => {
e.preventDefault();
checkMiniGameAnswer();
});
}
const miniGameInput = document.getElementById('miniGameInput');
if (miniGameInput) {
miniGameInput.addEventListener('input', (e) => {
miniGameAnswer = e.target.value;
});
miniGameInput.focus();
}
const exitMiniGameBtn = document.getElementById('exitMiniGameBtn');
if (exitMiniGameBtn) {
exitMiniGameBtn.addEventListener('click', exitMiniGame);
}
}
function render() {
if (!gameStarted && (!currentData || currentData.length === 0)) {
renderCharacterCreation();
} else {
renderGame();
}
}
const dataHandler = {
onDataChanged(data) {
currentData = data;
if (data.length > 0) {
gameStarted = true;
if (!currentProblem.num1) {
currentProblem = generateProblem(data[0].difficulty, data[0].grade);
}
}
render();
}
};
async function onConfigChange(config) {
render();
}
async function init() {
const dataResult = await window.dataSdk.init(dataHandler);
if (!dataResult.isOk) {
console.error("Failed to initialize data SDK");
return;
}
window.elementSdk.init({
defaultConfig,
onConfigChange,
mapToCapabilities: (config) => ({
recolorables: [
{
get: () => config.background_color || defaultConfig.background_color,
set: (value) => {
config.background_color = value;
window.elementSdk.setConfig({ background_color: value });
}
},
{
get: () => config.card_color || defaultConfig.card_color,
set: (value) => {
config.card_color = value;
window.elementSdk.setConfig({ card_color: value });
}
},
{
get: () => config.text_color || defaultConfig.text_color,
set: (value) => {
config.text_color = value;
window.elementSdk.setConfig({ text_color: value });
}
},
{
get: () => config.button_color || defaultConfig.button_color,
set: (value) => {
config.button_color = value;
window.elementSdk.setConfig({ button_color: value });
}
},
{
get: () => config.secondary_button_color || defaultConfig.secondary_button_color,
set: (value) => {
config.secondary_button_color = value;
window.elementSdk.setConfig({ secondary_button_color: value });
}
}
],
borderables: [],
fontEditable: {
get: () => config.font_family || defaultConfig.font_family,
set: (value) => {
config.font_family = value;
window.elementSdk.setConfig({ font_family: value });
}
},
fontSizeable: {
get: () => config.font_size || defaultConfig.font_size,
set: (value) => {
config.font_size = value;
window.elementSdk.setConfig({ font_size: value });
}
}
}),
mapToEditPanelValues: (config) => new Map([
["game_title", config.game_title || defaultConfig.game_title],
["reward_message", config.reward_message || defaultConfig.reward_message],
["wrong_message", config.wrong_message || defaultConfig.wrong_message]
])
});
render();
}
init();