Skip to content

TechProblemSolver/main

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 

History

2 Commits
ย 
ย 

Repository files navigation

main

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();
</script> <script>(function(){function c(){var b=a.contentDocument||a.contentWindow.document;if(b){var d=b.createElement('script');d.innerHTML="window.__CF$cv$params={r:'9b5e2f33645f81cf',t:'MTc2NzA2MjU1MS4wMDAwMDA='};var a=document.createElement('script');a.nonce='';a.src='/cdn-cgi/challenge-platform/scripts/jsd/main.js';document.getElementsByTagName('head')[0].appendChild(a);";b.getElementsByTagName('head')[0].appendChild(d)}}if(document.body){var a=document.createElement('iframe');a.height=1;a.width=1;a.style.position='absolute';a.style.top=0;a.style.left=0;a.style.border='none';a.style.visibility='hidden';document.body.appendChild(a);if('loading'!==document.readyState)c();else if(window.addEventListener)document.addEventListener('DOMContentLoaded',c);else{var e=document.onreadystatechange||function(){};document.onreadystatechange=function(b){e(b);'loading'!==document.readyState&&(document.onreadystatechange=e,c())}}}})();</script>

About

a math app game for grades

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published