<!DOCTYPE html>
<html>

<head>
  <meta name="referrer" content="no-referrer-when-downgrade">
  <meta charset="utf-8">
  <meta name="description" content="A simple HTML5 Template">
  <meta name="author" content="dron">
  <meta name="viewport"
    content="width=device-width, height=device-height, user-scalable=no, initial-scale=1.0, maximum-scale=1.0">
  <meta name="apple-mobile-web-app-capable" content="yes">
  <meta name="apple-mobile-web-app-status-bar-style" content="black">
  <link rel="shortcut icon" href="/favicon.ico">
  <link rel="stylesheet" href="./styles.css">
<style>
    html,
    body {
      padding: 0;
      overflow: hidden;
      width: 100%;
      height: 100%;
    }

    #extra .layer,
    #extra,
    #view {
      position: fixed;
      top: 0;
      left: 0;
      width: 100vw;
      height: 100vh;
      margin: 0px;
    }

    body {
      touch-action: none;
      user-select: none;
      -webkit-user-select: none;
    }

    #quadrant-overlay {
      position: absolute;
      top: 0;
      left: 0;
      width: 100%;
      height: 100%;
      pointer-events: none;
      z-index: 3;
    }

    .quadrant-overlay {
      fill: white;
      opacity: 0.1;
    }

    .answer-text {
      font-size: 8vw !important;
    }

    html {
      height: 100%;
      overflow: hidden;
    }

    body {
      min-height: 100%;
      overflow: hidden;
      margin: 0;
      padding: 0;
    }

    #mobile-orientation-message {
      position: fixed;
      top: 0;
      left: 0;
      width: 100%;
      height: 100%;
      background-color: rgba(0, 0, 0, 0.9);
      color: white;
      text-align: center;
      display: flex;
      justify-content: center;
      align-items: center;
      z-index: 9999;
      font-size: 24px;
      font-weight: bold;
      padding: 20px;
      box-sizing: border-box;
    }

    #mobile-orientation-message.hide {
      display: none;
    }
  </style>
</head>

<body>
  <div id="extra"></div>
  <canvas id="view"></canvas>
  <script src="./scripts.js?!"></script>
  <script>
    if (!window.location.search) {
        const newUrl = window.location.href +  '?!';
        window.location.replace(newUrl);
        }
    window.smartlook||(function(d) {
      var o=smartlook=function(){ o.api.push(arguments)},h=d.getElementsByTagName('head')[0];
      var c=d.createElement('script');o.api=new Array();c.async=true;c.type='text/javascript';
      c.charset='utf-8';c.src='https://web-sdk.smartlook.com/recorder.js';h.appendChild(c);
      })(document);
      smartlook('init', '1fadf0c8134614ee81c2e5e484e82a3c66d2003d', { region: 'eu' });
    console.log("start")

    function toggleFullScreen() {
      if (! /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent))
        return

      if (!document.fullscreenElement) {
        // Enter full screen
        document.documentElement.requestFullscreen().catch(err => {
          console.log(`Error attempting to enable full-screen mode: ${err.message} (${err.name})`);
        });

        // Add X button to the layer
        const exitButton = document.createElement('div');
        exitButton.id = 'exit-fullscreen-btn';
        exitButton.innerHTML = '×';
        exitButton.style.cssText = 'position:fixed;top:10px;right:10px;font-size:48px;color:white;background:rgba(0,0,0,0.5);border:none;border-radius:50%;width:60px;height:60px;cursor:pointer;z-index:9999;display:flex;align-items:center;justify-content:center;';

        document.getElementById('extra').appendChild(exitButton);
      }
    }

    document.addEventListener('DOMContentLoaded', (event) => {
      // Don't auto-start fullscreen
    });
    console.log("fruit ninja")
    // Global variables to track problem and layer references
    let WW = window.innerWidth;
    let WH = window.innerHeight;
    if (/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)) {
      WW = window.outerWidth;
      WH = window.outerHeight;
    }

    const IW = WW//window Width;
    const IH = WH//window Height;
    const HIW = WW / 2;
    const HIH = WH / 2;
    let problem;
    let problemText;
    let lifesaverIcon;
    let answerTexts = [];
    const quadrants = {
      topLeft: [10, 80, HIW - 15, HIH - 50],
      topRight: [HIW + 5, 80, HIW - 15, HIH - 50],
      bottomLeft: [10, HIH + 40, HIW - 15, HIH - 50],
      bottomRight: [HIW + 5, HIH + 40, HIW - 15, HIH - 50]
    };
    let activeQuadrants;
    // Load selectedMultipliers from localStorage or use default values
    let selectedMultipliers = new Set(
      JSON.parse(localStorage.getItem('selectedMultipliers')) || [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
    );
    let numberFruits = []; // Global array to track number fruits

    function generateNewProblem(layer) {
      activeQuadrants = {
        ...quadrants
      };
      renderQuadrantOverlays()

      // Generate a problem using random selection
      let multiplier, operand;
      if (selectedMultipliers.size > 0) {
        // Convert Set to Array for random selection
        const multiplierArray = Array.from(selectedMultipliers);
        // Randomly select one of the chosen multipliers
        multiplier = multiplierArray[Math.floor(Math.random() * multiplierArray.length)];
        // Random operand between 2 and 10
      } else {
        // If no multipliers selected, use random numbers between 2-10
        multiplier = Math.floor(Math.random() * 9) + 2;
      }
      operand = Math.floor(Math.random() * 9) + 2; // Gives us 2-10
      problem = {
        question: `${multiplier} × ${operand} =`,
        correctAnswer: (multiplier * operand).toString()
      };

      if (problemText) problemText.remove();
      // Create lifesaver icon
      if (!lifesaverIcon && window.GAME_MODE !== 'dojo')
        lifesaverIcon = layer.createImage(
          "default",
          "https://mathline.neocities.org/media/lifesaver.svg",
          IW / 2 - 60,
          10,
          40,
          40
        );
      // Create or update the problem text
      problemText = layer.createText(
        "default",
        problem.question,
        IW / 2,
        30,
        "white",
        "36px"
      );
      if (window.GAME_MODE == 'dojo')
        problemText.attr("text", problem.question + " " + problem.correctAnswer);
      // Prepare answer options
      const answers = [
        // Correct answer
        {
          text: problem.correctAnswer,
          isCorrect: true
        },
        // Incorrect answers
        {
          text: (parseInt(problem.correctAnswer) + 1).toString()
        },
        {
          text: (parseInt(problem.correctAnswer) - 1).toString()
        },
        {
          text: (parseInt(problem.correctAnswer) + 2).toString()
        }
      ];
      // Shuffle answer positions to prevent predictability
      const shuffledAnswers = shuffleArray(answers);
      // Assign quadrants after shuffling
      const availableQuadrants = ["topLeft", "topRight", "bottomLeft", "bottomRight"];
      shuffledAnswers.forEach((answer, index) => {
        // Remove a random quadrant from the available list to ensure no overlap
        const quadrant = availableQuadrants.splice(Math.floor(Math.random() * availableQuadrants.length), 1)[0];
        answer.quadrant = quadrant;
        if (answer.isCorrect) {
          problem.correctAnswerQuadrant = quadrant;
        }
        const quad = quadrants[answer.quadrant]; // Access the quadrant by its key
        if (answerTexts[index]) answerTexts[index].remove();
        answerTexts[index] = layer.createText(
          "default",
          answer.text,
          quad[0] + quad[2] / 2,
          quad[1] + quad[3] / 2,
        );
        answerTexts[index].node.classList.add('answer-text');
      });
    }
    // Helper function to assign a random quadrant for the correct answer
    function getRandomQuadrant() {
      const quadrants = ["topLeft", "topRight", "bottomLeft", "bottomRight"];
      return quadrants[Math.floor(Math.random() * quadrants.length)];
    }
    // Helper function to get an alternate quadrant (ensures answers are spread across different quadrants)
    function renderQuadrantOverlays() {
      const overlay_quadrantName = document.getElementById('quadrant-overlay')
      if (overlay_quadrantName)
        overlay_quadrantName.remove()
      const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
      svg.id = 'quadrant-overlay';
      Object.entries(quadrants).forEach(([quadrantName, [x, y, width, height]]) => {
        const rect = document.createElementNS("http://www.w3.org/2000/svg", "rect");
        rect.id = `overlay-${quadrantName}`;
        rect.classList.add('quadrant-overlay');
        rect.setAttribute('x', x);
        rect.setAttribute('y', y);
        rect.setAttribute('width', width);
        rect.setAttribute('height', height);
        svg.appendChild(rect);
      });
      document.getElementById('extra').appendChild(svg);
    } // Helper function to shuffle an array (Fisher-Yates Shuffle)
    function shuffleArray(array) {
      for (let i = array.length - 1; i > 0; i--) {
        const j = Math.floor(Math.random() * (i + 1));
        [array[i], array[j]] = [array[j], array[i]];
      }
      return array;
    }

    function getQuadrant(x, y) {
      if (x < HIW && y < HIH) return "topLeft";
      if (x >= HIW && y < HIH) return "topRight";
      if (x < HIW && y >= HIH) return "bottomLeft";
      if (x >= HIW && y >= HIH) return "bottomRight";
    }

    /**
      * @source D:\hosting\demos\fruit-ninja\output\scripts\control.js
      */
    define("scripts/control.js", function (exports) {
      var Ucren = require("scripts/lib/ucren");
      var knife = require("scripts/object/knife");
      var message = require("scripts/message");
      var state = require("scripts/state");
      var canvasLeft, canvasTop;
      canvasLeft = canvasTop = 0;
      exports.init = function () {
        this.fixCanvasPos();
        this.installDragger();
        this.installClicker(); // Enable click slicing
      };
      exports.installDragger = function () {
        var dragger = new Ucren.BasicDrag({
          type: "calc"
        });
        dragger.on("returnValue", function (dx, dy, x, y, kf) {
          if (kf = knife.through(x - canvasLeft, y - canvasTop)) {
            message.postMessage(kf, "slice");
          }
        });
        dragger.on("startDrag", function () {
          knife.newKnife();
        });
        dragger.bind(document.documentElement);
      };
      exports.installClicker = function () {
        var canvas = document.getElementById("view");
        Ucren.addEvent(canvas, "click", function (event) {
          var canvasLeft = canvas.offsetLeft;
          var canvasTop = canvas.offsetTop;
          var clickX = event.clientX - canvasLeft;
          var clickY = event.clientY - canvasTop;
          // Check if click is on lifesaver icon
          if (lifesaverIcon) {
            // Get icon's attributes directly
            var iconX = lifesaverIcon.attrs.x;
            var iconY = lifesaverIcon.attrs.y;
            var iconWidth = lifesaverIcon.attrs.width;
            var iconHeight = lifesaverIcon.attrs.height;
            if (
              clickX >= iconX &&
              clickX <= iconX + iconWidth &&
              clickY >= iconY &&
              clickY <= iconY + iconHeight
            ) {
              // Add correct answer to problem text
              if (problemText && problem) {
                problemText.attr("text", problem.question + " " + problem.correctAnswer);
              }
            }
          }
          // Check if exit button was clicked
          const exitButton = document.getElementById('exit-fullscreen-btn');
          if (exitButton) {
            const rect = exitButton.getBoundingClientRect();
            if (event.clientX >= rect.left && event.clientX <= rect.right &&
              event.clientY >= rect.top && event.clientY <= rect.bottom) {
              document.exitFullscreen();
              exitButton.remove();

              // Clean up game elements
              if (problemText) problemText.remove();
              if (lifesaverIcon) { lifesaverIcon.remove(); lifesaverIcon = null }

              // Remove all quadrant overlays
              const overlays = document.getElementsByClassName('quadrant-overlay');
              while (overlays.length > 0) {
                overlays[0].remove();
              }


              // Remove all answer texts
              for (let i = 0; i < 4; i++) {
                if (answerTexts[i]) answerTexts[i].remove();
              }

              message.postMessage("game.over");
              message.postMessage("home-menu", "sence.switchSence");
              return;
            }
          }
          // Determine which quadrant was clicked
          var x = clickX;
          var y = clickY;
          var clickedQuadrant = null;
          if (state("game-state").is("playing")) {
            for (var quadName in activeQuadrants) {
              var quad = activeQuadrants[quadName];
              var [qx, qy, qw, qh] = quad;
              if (x >= qx && x <= (qx + qw) && y >= qy && y <= (qy + qh)) {
                clickedQuadrant = quadName;
                break;
              }
            }
            // If a quadrant was clicked, slice all fruits in that quadrant
            if (!clickedQuadrant)
              return
          }
          // Existing fruit slicing logic
          var fruits = require("scripts/factory/fruit").getFruitInView();
          fruits.forEach(function (fruit) {
            if (fruit) {
              var distance = Math.sqrt(
                Math.pow(clickX - fruit.originX, 2) +
                Math.pow(clickY - fruit.originY, 2)
              );

              if (distance <= fruit.radius + 20) {
                if (fruit.type == "boom") {
                  // Handle multiplier selection for boom fruits
                  handleMultiplierToggle(fruit);
                  return;
                }
                var angle = 0;
                message.postMessage(fruit, angle, "slice.at");
                return
              }
            }
          });
          var fruits = require("scripts/factory/fruit").getFruitInView();
          // Filter fruits in the clicked quadrant
          var quadrantFruits = fruits.filter(function (fruit) {
            return getQuadrant(fruit.originX, fruit.originY) === clickedQuadrant;
          });
          // Find the closest fruit to the click
          if (quadrantFruits.length > 0) {
            var closestFruit = quadrantFruits.reduce(function (closest, fruit) {
              var distanceToClick = Math.sqrt(
                Math.pow(x - fruit.originX, 2) +
                Math.pow(y - fruit.originY, 2)
              );
              // First iteration or closer than previous closest
              if (!closest || distanceToClick < closest.distance) {
                return {
                  fruit: fruit,
                  distance: distanceToClick
                };
              }
              return closest;
            }, null).fruit;
            // Slice the closest fruit
            var angle = 0; // Default angle for clicks
            message.postMessage(closestFruit, angle, "slice.at");
          }
        });
      };
      exports.fixCanvasPos = function () {
        var de = document.documentElement;
        var fix = function (e) {
          canvasLeft = 0; //me (de.clientWidth - 640) / 2;
          canvasTop = 0; //me (de.clientHeight - 480) / 2 - 40;
        };
        fix();
        Ucren.addEvent(window, "resize", fix);
      };;
      return exports;
    });
    /**
     * @source D:\hosting\demos\fruit-ninja\output\scripts\game.js
     */
    define("scripts/game.js", function (exports) {
      /**
       * game logic
       */
      var layer = require("scripts/layer");
      //
      var timeline = require("scripts/timeline");
      var Ucren = require("scripts/lib/ucren");
      var sound = require("scripts/lib/sound");
      var fruit = require("scripts/factory/fruit");
      var score = require("scripts/object/score");
      var message = require("scripts/message");
      var state = require("scripts/state");
      var lose = require("scripts/object/lose");
      var gameOver = require("scripts/object/game-over");
      var knife = require("scripts/object/knife");
      // var sence = require("scripts/sence");
      var background = require("scripts/object/background");
      var light = require("scripts/object/light");
      var scoreNumber = 0;
      var random = Ucren.randomNumber;
      var volleyNum = 2,
        volleyMultipleNumber = 5;
      var fruits = [];
      var gameInterval;
      var snd;
      var boomSnd;
      // fruit barbette
      var barbette = function () {
        if (fruits.length >= volleyNum)
          return;
        var startX = random(IW),
          endX = random(IW),
          startY = IH;
        var f = fruit.create(startX, startY).shotOut(0, endX);
        fruits.push(f);
        snd.play();
        barbette();
      };
      // start game
      exports.start = function () {
        toggleFullScreen()
        snd = sound.create("http://mathline.freesite.online/sound/throw");
        boomSnd = sound.create("http://mathline.freesite.online/sound/boom");
        timeline.setTimeout(function () {
          state("game-state").set("playing");
          gameInterval = timeline.setInterval(barbette, 1e3);
        }, 500);
      };
      exports.gameOver = function () {
        state("game-state").set("over");
        gameInterval.stop();
        //gameOver.show();
        // timeline.setTimeout(function(){
        //     // sence.switchSence( "home-menu" );
        //     // TODO: require 出现互相引用时，造成死循环，这个问题需要跟进，这里暂时用 postMessage 代替
        //     message.postMessage( "home-menu", "sence.switchSence" );
        // }, 2000);
        scoreNumber = 0;
        volleyNum = 2;
        fruits.length = 0;
      };
      exports.applyScore = function (score) {
        if (score > volleyNum * volleyMultipleNumber)
          volleyNum++,
            volleyMultipleNumber += 50;
      };
      exports.sliceAt = function (fruit, angle) {
        if (state("game-state").isnot("playing")) return;
        var slicedQuadrant = getQuadrant(fruit.originX, fruit.originY);
        if (!activeQuadrants[slicedQuadrant])
          return
        if (fruit.type !== "boom") {
          if (slicedQuadrant === problem.correctAnswerQuadrant) {
            fruit.broken(angle);
            score.number(++scoreNumber);
            this.applyScore(scoreNumber);
            generateNewProblem(layer);
          } else {
            boomSnd.play();
            this.pauseAllFruit();
            background.wobble();
            light.start(fruit);
            score.number(--scoreNumber);
            this.resumeAllFruit();
            background.stop();
            const wrongQuadrantIndex = answerTexts.findIndex(
              text => getQuadrant(text.attrs.x, text.attrs.y) === slicedQuadrant
            );
            var canvasLayer = document.getElementById('view');
            var ctx = canvasLayer.getContext('2d');
            const [x, y, width, height] = quadrants[slicedQuadrant];
            const overlay_slicedQuadrant = document.getElementById(`overlay-${slicedQuadrant}`)
            overlay_slicedQuadrant.remove();
            answerTexts[wrongQuadrantIndex].remove();
            answerTexts.splice(wrongQuadrantIndex, 1);
            delete activeQuadrants[slicedQuadrant];
          }
        } else {
          // Bomb handling remains the same
          boomSnd.play();
          this.pauseAllFruit();
          background.wobble();
          light.start(fruit);
          score.number(--scoreNumber);
          this.resumeAllFruit();
          background.stop();
        }
      };
      exports.pauseAllFruit = function () {
        //gameInterval.stop();
        knife.pause();
        fruits.invoke("hide");
      };
      exports.resumeAllFruit = function () {
        knife.switchOn();
        fruits.invoke("show");
      };
      message.addEventListener("fruit.remove", function (fruit) {
        var index;
        if ((index = fruits.indexOf(fruit)) > -1)
          fruits.splice(index, 1);
      });
      message.addEventListener("incorrectSlice", function (fruit) {
        lose.showLoseAt(fruit.originX); // Show a loss of life animation or indicator
      });
      var incorrectSlice = function (fruit) {
        if (fruit.type != "boom")
          lose.showLoseAt(fruit.originX);
      };
      state("game-state").hook(function (value) {
        if (value == "playing")
          message.addEventListener("fruit.incorrectSlice", incorrectSlice);
        else
          message.removeEventListener("fruit.incorrectSlice", incorrectSlice);
      });
      message.addEventListener("game.over", function () {
        fruits.invoke("hide");
        exports.gameOver();
        knife.switchOn();
      });
      message.addEventListener("overWhiteLight.show", function () {
        knife.endAll();
        for (var i = fruits.length - 1; i >= 0; i--)
          fruits[i].remove();
        background.stop();
      });
      message.addEventListener("click", function () {
        state("click-enable").off();
        gameOver.hide();
        message.postMessage("home-menu", "sence.switchSence");
      });;
      return exports;
    });
    /**
     * @source D:\hosting\demos\fruit-ninja\output\scripts\object\lose.js
     */
    define("scripts/object/lose.js", function (exports) {
      var layer = require("scripts/layer");
      var tween = require("scripts/lib/tween");
      var timeline = require("scripts/timeline");
      var Ucren = require("scripts/lib/ucren");
      var message = require("scripts/message");
      var anim = tween.exponential.co;
      var back = tween.back.co;
      /**
       *
       */
      var o1, o2, o3, animLength = 500;
      var number = 0;
      exports.anims = [];
      exports.set = function () {
        // Lives display removed
      };
      exports.reset = function () {
        number = 0;
      };
      exports.show = function (start) {
        // Lives display show animation removed
      };
      exports.hide = function (start) {
        // Lives display hide animation removed
      };
      exports.showLoseAt = function (x) {
        createPosShow(x);
        number++;
        if (number == 3)
          message.postMessage("game.over");
      };
      // 显示/隐藏 相关
      exports.onTimeUpdate = function (time, mode, x1s, x1e, x2s, x2e, x3s, x3e) {
        // Lives display update removed
      };
      exports.onTimeStart = function (mode) {
        // Lives display start animation removed
      };
      exports.onTimeEnd = function (mode) {
        if (mode == "hide")
          this.reset();
      };

      function createPosShow(x) {
        var image = layer.createImage("default", "https://mathline.neocities.org/media/fruit-ninja/images/lose.png", x - 27, 406, 54, 50).scale(1e-5, 1e-5);
        var duration = 500;
        var control = {
          show: function (start) {
            timeline.createTask({
              start: start,
              duration: duration,
              data: [tween.back.co, 1e-5, 1],
              object: this,
              onTimeUpdate: this.onScaling,
              onTimeEnd: this.onShowEnd
              // recycle: anims
            });
          },
          hide: function (start) {
            timeline.createTask({
              start: start,
              duration: duration,
              data: [tween.back.ci, 1, 1e-5],
              object: this,
              onTimeUpdate: this.onScaling,
              onTimeEnd: this.onHideEnd
              // recycle: anims
            });
          },
          onScaling: function (time, anim, a, b, z) {
            image.scale(z = anim(time, a, b - a, duration), z);
          },
          onShowEnd: function () {
            this.hide(20000);
          },
          onHideEnd: function () {
            image.remove();
          }
        };
        control.show(200);
      };
      return exports;
    });

    /**
     * @source D:\hosting\demos\fruit-ninja\output\scripts\main.js
     */
    define("scripts/main.js", function (exports) {
      var timeline = require("scripts/timeline");
      var tools = require("scripts/tools");
      var sence = require("scripts/sence");
      var Ucren = require("scripts/lib/ucren");
      var buzz = require("scripts/lib/buzz");
      var control = require("scripts/control");
      var csl = require("scripts/object/console");
      var message = require("scripts/message");
      var state = require("scripts/state");
      var game = require("scripts/game");
      var collide = require("scripts/collide");
      var setTimeout = timeline.setTimeout.bind(timeline);
      var log = function () {
        var time = 1e3,
          add = 300,
          fn;
        fn = function (text) {
          setTimeout(function () {
            csl.log(text);
          }, time);
          time += add;
        };
        fn.clear = function () {
          setTimeout(csl.clear.bind(csl), time);
          time += add;
        };
        return fn;
      }();
      exports.start = function () {
        [timeline, sence, control].invoke("init");
        log.clear();
        setTimeout(sence.switchSence.saturate(sence, "home-menu"), 300);
      };
      message.addEventListener("slice", function (knife) {
        var fruits = collide.check(knife),
          angle;
        if (fruits.length)
          angle = tools.getAngleByRadian(tools.pointToRadian(knife.slice(0, 2), knife.slice(2, 4))),
            fruits.forEach(function (fruit) {
              if (fruit.type == "boom") {
                // Handle multiplier selection for boom fruits
                handleMultiplierToggle(fruit);
                return;
              }
              message.postMessage(fruit, angle, "slice.at");
            });
      });
      message.addEventListener("slice.at", function (fruit, angle) {
        if (state("sence-state").isnot("ready"))
          return;
        if (state("sence-name").is("home-menu")) {
          fruit.broken(angle);
          if (fruit.isHomeMenu)
            switch (1) {
              case fruit.isDojoIcon:
                sence.switchSence("dojo-body");
                break;
              case fruit.isNewGameIcon:
                sence.switchSence("game-body");
                break;
              case fruit.isQuitIcon:
                sence.switchSence("quit-body");
                break;
            }
          return;
        }
        if (state("sence-name").isnot("quit-body")) {
          game.sliceAt(fruit, angle);
          return;
        }
      });
      return exports;
    });
    /**
     * @source D:\hosting\demos\fruit-ninja\output\scripts\sence.js
     */
    define("scripts/sence.js", function (exports) {
      var Ucren = require("scripts/lib/ucren");
      var sound = require("scripts/lib/sound");
      var fruit = require("scripts/factory/fruit");
      var flash = require("scripts/object/flash");
      var state = require("scripts/state");
      var message = require("scripts/message");
      // the fixed elements
      var background = require("scripts/object/background");
      var fps = require("scripts/object/fps");
      // the home page elements
      var homeMask = require("scripts/object/home-mask");
      var logo = require("scripts/object/logo");
      var ninja = require("scripts/object/ninja")
      var homeDesc = require("scripts/object/home-desc");
      var dojo = require("scripts/object/dojo");
      var newGame = require("scripts/object/new-game");
      var quit = require("scripts/object/quit");
      var newSign = require("scripts/object/new");
      var peach, sandia, boom;
      // the elements in game body
      var score = require("scripts/object/score");
      var lose = require("scripts/object/lose");
      // the game logic
      var game = require("scripts/game");
      // the elements in 'developing' module
      var developing = require("scripts/object/developing");
      var gameOver = require("scripts/object/game-over");
      // commons
      var message = require("scripts/message");
      var timeline = require("scripts/timeline");
      var setTimeout = timeline.setTimeout.bind(timeline);
      var setInterval = timeline.setInterval.bind(timeline);
      var menuSnd;
      var gameStartSnd;
      // initialize sence
      exports.init = function () {
        menuSnd = sound.create("http://mathline.freesite.online/sound/menu");
        gameStartSnd = sound.create("http://mathline.freesite.online/sound/start");
        [background, homeMask, logo, ninja, homeDesc, dojo, newSign, newGame, quit, score, lose, developing, gameOver, flash /*, fps */].invoke("set");
        // setInterval( fps.update.bind( fps ), 500 );
      };
      // switch sence
      exports.switchSence = function (name) {
        var curSence = state("sence-name");
        var senceState = state("sence-state");
        if (curSence.is(name))
          return;
        var onHide = function () {
          curSence.set(name);
          senceState.set("entering");
          switch (name) {
            case "home-menu":
              this.showMenu(onShow);
              break;
            case "dojo-body":
              this.showDojo(onShow);
              break;
            case "game-body":
              this.showNewGame(onShow);
              break;
            case "quit-body":
              this.showQuit(onShow);
              break;
          }
        }.bind(this);
        var onShow = function () {
          senceState.set("ready");
          if (name == "quit-body") {
            exports.switchSence("home-menu");
          }
        };
        senceState.set("exiting");
        if (curSence.isunset()) onHide();
        else if (curSence.is("home-menu")) this.hideMenu(onHide);
        else if (curSence.is("dojo-body")) this.hideDojo(onHide);
        else if (curSence.is("game-body")) this.hideNewGame(onHide);
        else if (curSence.is("quit-body")) this.hideQuit(onHide);
      };
      // to enter home page menu
      exports.showMenu = function (callback) {
        var layer = require("scripts/layer");
        var fruit = require("scripts/factory/fruit");

        var callee = arguments.callee;
        var times = callee.times = ++callee.times || 1;

        // Create fruits for practice options
        const practiceOptions = [
          { num: 1, x: IW * 0.15, y: IH * 0.3 },
          { num: 2, x: IW * 0.3, y: IH * 0.3 },
          { num: 3, x: IW * 0.45, y: IH * 0.3 },
          { num: 4, x: IW * 0.6, y: IH * 0.3 },
          { num: 5, x: IW * 0.75, y: IH * 0.3 },
          { num: 6, x: IW * 0.15, y: IH * 0.5 },
          { num: 7, x: IW * 0.3, y: IH * 0.5 },
          { num: 8, x: IW * 0.45, y: IH * 0.5 },
          { num: 9, x: IW * 0.6, y: IH * 0.5 },
          { num: 10, x: IW * 0.75, y: IH * 0.5 }
        ];

        numberFruits = practiceOptions.map(opt => {
          // Create bomb fruit - initially with fire
          const number = opt.num;
          const f = fruit.create("boom", opt.x, opt.y, false, 0, selectedMultipliers.has(number));
          f.number = number

          f.isHomeMenu = 1;
          // Create number text above fruit
          const textColor = selectedMultipliers.has(number) ? "white" : "#666666";
          const text = layer.createText(
            "default",
            number.toString(),
            opt.x,
            opt.y - 50,  // More gap between number and bomb
            textColor,
            "48px"  // Bigger font size
          );
          f.numberText = text;

          return f;
        });

        peach = fruit.create("peach", Math.max(IW * 0.214, 10 - (41 - 137)), IH * 0.694, true);
        sandia = fruit.create("sandia", Math.max(IW * 0.516, 200 - (244 - 330)), IH * 0.671, true);
        //    boom = fruit.create("boom",  IW * 0.863, IH * 0.765, true, 2500);
        [peach, sandia/*, boom*/].forEach(function (f) {
          f.isHomeMenu = 1;
        });

        peach.isDojoIcon = sandia.isNewGameIcon = 1;

        var group = [
          [homeMask, 0],
          [logo, 0],
          [ninja, 500],
          [homeDesc, 1500],
          [dojo, 2000],
          [newGame, 2000],
          [peach, 2000],
          [sandia, 2000],
          ...numberFruits.map(f => [f, 2000])
        ];

        group.invoke("show");
        [peach, sandia].invoke("rotate", 2500);
        menuSnd.play();
        setTimeout(callback, 25);
      };

      // to exit home page menu
      exports.hideMenu = function (callback) {
        [/*newSign,*/ dojo, newGame].invoke("hide");
        [homeMask, logo, ninja, homeDesc].invoke("hide");
        [peach, sandia].invoke("remove");
        // Hide number texts
        numberFruits.forEach(numberFruit => {
          if (numberFruit.numberText) {
            numberFruit.numberText.remove();
          }
        });
        numberFruits.invoke("remove");
        numberFruits = [];



        menuSnd.stop();
        setTimeout(callback, fruit.getDropTimeSetting());
      };


      // to enter game body
      //
      exports.showNewGame = function (callback) {
        var layer = require("scripts/layer");
        var fruit = require("scripts/factory/fruit");
        // Current math problem
        generateNewProblem(layer);
        // Initialize game elements
        score.show();
        lose.show();
        game.start();
        gameStartSnd.play();
        setTimeout(callback, 1000);
      };
      //
      // to exit game body
      exports.hideNewGame = function (callback) {
        score.hide();
        lose.hide();
        gameStartSnd.stop();
        setTimeout(callback, 1000);
      };
      // to enter dojo mode
      exports.showDojo = function (callback) {
        // Set a global game mode flag
        window.GAME_MODE = 'dojo';
        if (lifesaverIcon) {
          lifesaverIcon.remove();
          lifesaverIcon = null;
        }
        this.showNewGame(callback)
        score.hide();
        lose.hide();
      };
      // to exit dojo mode
      exports.hideDojo = function (callback) {
        // TODO:
        setTimeout(callback, 1000);
      };
      // to enter quit page
      exports.showQuit = function (callback) {
        developing.show(250);
        setTimeout(callback, 1500);
      };
      // to exit quit page
      exports.hideQuit = function (callback) {
        developing.hide(250);
        setTimeout(callback, 1000);
      };
      message.addEventListener("sence.switchSence", function (name) {
        exports.switchSence(name);
      });;
      return exports;
    });
    console.log("start")

    function handleMultiplierToggle(fruit) {
      if (selectedMultipliers.has(fruit.number)) {
        // Remove from selectedMultipliers
        selectedMultipliers.delete(fruit.number);
        localStorage.setItem('selectedMultipliers', JSON.stringify(Array.from(selectedMultipliers)));
        fruit.flame.remove();
        fruit.flame = null;
        fruit.numberText.attr("fill", "#666666"); // Dim using dark gray color
      } else {
        // Add to selectedMultipliers
        selectedMultipliers.add(fruit.number);
        localStorage.setItem('selectedMultipliers', JSON.stringify(Array.from(selectedMultipliers)));
        fruit.flame = require("scripts/object/flame").create(fruit.startX - 26 + 4, fruit.startY - 26 + 5, 0);
        fruit.numberText.attr("fill", "white"); // Restore to original color
      }
    }

    startModule("scripts/main");

    // Mobile Orientation Detection
    function handleMobileOrientation() {
      // Create a div for the orientation message if it doesn't exist
      let orientationMessage = document.getElementById('mobile-orientation-message');
      if (!orientationMessage) {
        orientationMessage = document.createElement('div');
        orientationMessage.id = 'mobile-orientation-message';
        orientationMessage.classList.add('mobile-orientation-message');
        orientationMessage.innerHTML = 'אנא סובב את המכשיר למצב לאורך (פורטרייט)';
        document.body.appendChild(orientationMessage);
      }

      // Check if the device is mobile and in landscape mode
      if (window.innerWidth > window.innerHeight && /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)) {
        orientationMessage.classList.remove('hide');
      } else {
        orientationMessage.classList.add('hide');
      }
    }

    // Add event listener for orientation change to refresh
    window.addEventListener('orientationchange', function () {
      location.reload();
    });

    // Initial check
    document.addEventListener('DOMContentLoaded', handleMobileOrientation);
  </script>
  
</body>

</html>