Browse Source

change flag assets to circle and better quality
refactor color var names
code refactor with prettier
add prettier config

lairaalmas 1 year ago
parent
commit
f5ed4a3280

+ 23 - 0
.prettierrc

@@ -0,0 +1,23 @@
+{
+  "arrowParens": "always",
+  "bracketSpacing": true,
+  "endOfLine": "lf",
+  "htmlWhitespaceSensitivity": "css",
+  "insertPragma": false,
+  "singleAttributePerLine": false,
+  "bracketSameLine": false,
+  "jsxBracketSameLine": false,
+  "jsxSingleQuote": false,
+  "printWidth": 80,
+  "proseWrap": "preserve",
+  "quoteProps": "as-needed",
+  "requirePragma": false,
+  "semi": true,
+  "singleQuote": true,
+  "tabWidth": 2,
+  "trailingComma": "es5",
+  "useTabs": false,
+  "vueIndentScriptAndStyle": false,
+  "filepath": "/var/www/html/Ifractions-web/js/",
+  "parser": "babel"
+}

BIN
assets/img/flag/BRAZ.jpg


BIN
assets/img/flag/FRAN.jpg


BIN
assets/img/flag/ITAL.png


BIN
assets/img/flag/PERU.jpg


BIN
assets/img/flag/UNST.jpg


BIN
assets/img/flag/br.png


BIN
assets/img/flag/fr.png


BIN
assets/img/flag/it.png


BIN
assets/img/flag/pe.png


BIN
assets/img/flag/us.png


+ 2 - 1
index.html

@@ -117,7 +117,8 @@
           <input type="text" id="textbox-content" value="" size="13" maxlength="36"> <!-- Textbox to get player name -->
         </div>
 
-        <div id="my-modal" class="modal"> <!-- Modal black background-->
+        <div id="my-modal" class="modal">
+          <!-- Modal black background-->
           <div class="modal-content">
             <span class="close">&times;</span> <!-- Modal close button -->
             <div id='infobox-content'></div> <!-- Modal box -->

+ 478 - 248
js/customMenu.js

@@ -3,49 +3,62 @@
  ******************************/
 
 /** [CUSTOM MENU STATE] Screen where the user can customise the selected game - game mode, math operation, level of difficulty.
- * 
+ *
  * @namespace
  */
 const customMenuState = {
-
   /**
    * Preloads media for current state
    */
   preload: function () {
-
     // LOADING MEDIA
     game.load.sprite(url[gameType].sprite);
     game.load.image(url[gameType].image);
-
   },
 
   /**
    * Main code
    */
   create: function () {
-
     // FOR MOODLE
-    if (moodle && iLMparameters.iLM_PARAM_SendAnswer == 'false') { // Student role
+    if (moodle && iLMparameters.iLM_PARAM_SendAnswer == 'false') {
+      // Student role
 
       game.state.start('map');
-
     } else {
-
       // Background color
-      game.add.geom.rect(0, 0, context.canvas.width, context.canvas.height, undefined, 0, colors.blueBckg, 1);
+      game.add.geom.rect(
+        0,
+        0,
+        context.canvas.width,
+        context.canvas.height,
+        undefined,
+        0,
+        colors.blueBg,
+        1
+      );
       // Floor
-      for (let i = 0; i < context.canvas.width / 100; i++) { game.add.image(i * 100, context.canvas.height - 100, 'floor'); }
+      for (let i = 0; i < context.canvas.width / 100; i++) {
+        game.add.image(i * 100, context.canvas.height - 100, 'floor');
+      }
 
       // Overtitle : Selected game
-      game.add.text(context.canvas.width / 2, 40, game.lang.game.toUpperCase() + ": " + menuState.menuIcons, textStyles.h4_brown);
+      game.add.text(
+        context.canvas.width / 2,
+        40,
+        game.lang.game.toUpperCase() + ': ' + menuState.menuIcons,
+        textStyles.h4_brown
+      );
       // Title : Customize the selected game
-      game.add.text(context.canvas.width / 2, 80, game.lang.custom_game, textStyles.h1_green);
+      game.add.text(
+        context.canvas.width / 2,
+        80,
+        game.lang.custom_game,
+        textStyles.h1_green
+      );
 
       // Loads navigation icons
-      navigationIcons.add(
-        true, false, false,
-        true, true,
-        'menu', false);
+      navigationIcons.add(true, false, false, true, true, 'menu', false);
 
       let infoIcon;
       const iconScale = 0.7;
@@ -56,12 +69,15 @@ const customMenuState = {
       let y = gameFrame().y;
 
       let offsetW = game.math.getOffset(gameFrame().width, 5);
-      let offsetH = game.math.getOffset(gameFrame().height, curGame.gameMode.length);
+      let offsetH = game.math.getOffset(
+        gameFrame().height,
+        curGame.gameMode.length
+      );
 
       const line_thickness = 5;
 
       // Label 'Game Modes'
-      game.add.text(x + offsetW, y, game.lang.game_modes, textStyles.h2_blue_2);
+      game.add.text(x + offsetW, y, game.lang.game_modes, textStyles.h2_blue);
 
       infoIcon = game.add.image(x + 2 * offsetW - 30, y - 20, 'info', 0.5, 0.4);
       infoIcon.anchor(0.5, 0.5);
@@ -70,7 +86,12 @@ const customMenuState = {
       this.menuIcons.push(infoIcon);
 
       // Label 'Operations'
-      game.add.text(x + 3 * offsetW, y, game.lang.operations, textStyles.h2_blue_2);
+      game.add.text(
+        x + 3 * offsetW,
+        y,
+        game.lang.operations,
+        textStyles.h2_blue
+      );
 
       infoIcon = game.add.image(x + 4 * offsetW - 30, y - 20, 'info', 0.5, 0.4);
       infoIcon.anchor(0.5, 0.5);
@@ -79,7 +100,12 @@ const customMenuState = {
       this.menuIcons.push(infoIcon);
 
       // Label 'Difficulties'
-      game.add.text(x + 5 * offsetW, y, game.lang.difficulties, textStyles.h2_blue_2);
+      game.add.text(
+        x + 5 * offsetW,
+        y,
+        game.lang.difficulties,
+        textStyles.h2_blue
+      );
 
       infoIcon = game.add.image(x + 6 * offsetW - 30, y - 20, 'info', 0.5, 0.4);
       infoIcon.anchor(0.5, 0.5);
@@ -88,39 +114,106 @@ const customMenuState = {
       this.menuIcons.push(infoIcon);
 
       // Horizontal line
-      game.add.geom.rect(x - 25, y + 10, gameFrame().width, line_thickness, undefined, 0, colors.blueMenuLine).anchor(0, 0.5);
+      game.add.geom
+        .rect(
+          x - 25,
+          y + 10,
+          gameFrame().width,
+          line_thickness,
+          undefined,
+          0,
+          colors.blueMenuLine
+        )
+        .anchor(0, 0.5);
       // Vertical lines
-      game.add.geom.rect(x + 2 * offsetW, y - 25, line_thickness, gameFrame().height, undefined, 0, colors.blueMenuLine).anchor(0.5, 0);
-      game.add.geom.rect(x + 4 * offsetW, y - 25, line_thickness, gameFrame().height, undefined, 0, colors.blueMenuLine).anchor(0.5, 0);
+      game.add.geom
+        .rect(
+          x + 2 * offsetW,
+          y - 25,
+          line_thickness,
+          gameFrame().height,
+          undefined,
+          0,
+          colors.blueMenuLine
+        )
+        .anchor(0.5, 0);
+      game.add.geom
+        .rect(
+          x + 4 * offsetW,
+          y - 25,
+          line_thickness,
+          gameFrame().height,
+          undefined,
+          0,
+          colors.blueMenuLine
+        )
+        .anchor(0.5, 0);
 
       // --------------------------- TURN ON/OFF FRACTION LABELS / RECTANGLE GUIDE
 
       // Horizontal line
-      game.add.geom.rect(x + 4 * offsetW, y + offsetH, gameFrame().width / 3 - 4 * line_thickness, line_thickness, undefined, 0, colors.blueMenuLine).anchor(0, 0.5);
-
-      infoIcon = game.add.image(x + 6 * offsetW - 30, y + offsetH - 20, 'info', 0.5, 0.4);
+      game.add.geom
+        .rect(
+          x + 4 * offsetW,
+          y + offsetH,
+          gameFrame().width / 3 - 4 * line_thickness,
+          line_thickness,
+          undefined,
+          0,
+          colors.blueMenuLine
+        )
+        .anchor(0, 0.5);
+
+      infoIcon = game.add.image(
+        x + 6 * offsetW - 30,
+        y + offsetH - 20,
+        'info',
+        0.5,
+        0.4
+      );
       infoIcon.anchor(0.5, 0.5);
       infoIcon.iconType = 'infoIcon';
       infoIcon.id = 'gameMisc';
       this.menuIcons.push(infoIcon);
 
       // Label 'Show Fractions / Auxiliar rectangles'
-      game.add.text(x + 5 * offsetW, y + offsetH - 48, game.lang.show, textStyles.h4_blue_2);
+      game.add.text(
+        x + 5 * offsetW,
+        y + offsetH - 48,
+        game.lang.show,
+        textStyles.h4_blue
+      );
 
       let auxText;
       if (gameType == 'squareTwo') {
         auxText = game.lang.aux_rectangle;
-        game.add.text(x + 5 * offsetW + 10, y + offsetH - 24, auxText, textStyles.h4_blue_2);
+        game.add.text(
+          x + 5 * offsetW + 10,
+          y + offsetH - 24,
+          auxText,
+          textStyles.h4_blue
+        );
       } else {
         auxText = game.lang.title;
-        game.add.text(x + 5 * offsetW, y + offsetH - 24, auxText, textStyles.h2_blue_2);
+        game.add.text(
+          x + 5 * offsetW,
+          y + offsetH - 24,
+          auxText,
+          textStyles.h2_blue
+        );
       }
 
       // Selection box
       y += 40;
-      const frame = (fractionLabel) ? 1 : 0;
-
-      const selectionBox = game.add.sprite(x + 5 * offsetW, y + offsetH, 'select', frame, 0.11);
+      const frame = fractionLabel ? 1 : 0;
+
+      const selectionBox = game.add.sprite(
+        x + 5 * offsetW,
+        y + offsetH,
+        'select',
+        frame,
+        0.11
+      );
       selectionBox.anchor(0.5, 0.5);
       selectionBox.iconType = 'selectionBox';
       this.menuIcons.push(selectionBox);
@@ -131,7 +224,14 @@ const customMenuState = {
       y = gameFrame().y + offsetH / 2;
 
       for (let i = 0; i < curGame.gameModeUrl.length; i++, y += offsetH) {
-        const icon = game.add.sprite(x, y, curGame.gameModeUrl[i], 0, iconScale, 1);
+        const icon = game.add.sprite(
+          x,
+          y,
+          curGame.gameModeUrl[i],
+          0,
+          iconScale,
+          1
+        );
         icon.anchor(0.5, 0.5);
 
         icon.gameMode = curGame.gameMode[i];
@@ -148,13 +248,23 @@ const customMenuState = {
 
       x += 2 * offsetW;
       y = gameFrame().y + offsetH / 2;
-      offsetH = game.math.getOffset(gameFrame().height, curGame.gameOperation.length);
+      offsetH = game.math.getOffset(
+        gameFrame().height,
+        curGame.gameOperation.length
+      );
 
       let icon;
 
       // Placing math operation icons
       for (let i = 0; i < curGame.gameOperation.length; i++, y += offsetH) {
-        icon = game.add.sprite(x, y, curGame.gameOperationUrl[i], 0, iconScale, 1);
+        icon = game.add.sprite(
+          x,
+          y,
+          curGame.gameOperationUrl[i],
+          0,
+          iconScale,
+          1
+        );
         icon.anchor(0.5, 0.5);
 
         icon.gameOperation = curGame.gameOperation[i];
@@ -169,9 +279,12 @@ const customMenuState = {
       }
 
       // --------------------------- DIFFICULTY ICONS
-      x = gameFrame().x - 50 + 5 * offsetW
+      x = gameFrame().x - 50 + 5 * offsetW;
 
-      offsetH = game.math.getOffset(gameFrame().height, curGame.gameMode.length);
+      offsetH = game.math.getOffset(
+        gameFrame().height,
+        curGame.gameMode.length
+      );
       y = gameFrame().y + offsetH / 3;
 
       if (gameType != 'squareOne') x -= 40;
@@ -181,7 +294,16 @@ const customMenuState = {
         const curX = x + (30 + 10) * i;
 
         // Difficulty menuIcons
-        const icon = game.add.geom.rect(curX, y, 30, 30, undefined, 0, colors.gray, 1);
+        const icon = game.add.geom.rect(
+          curX,
+          y,
+          30,
+          30,
+          undefined,
+          0,
+          colors.gray,
+          1
+        );
         icon.anchor(0.5, 0.5);
         icon.difficulty = i + 1;
         icon.iconType = 'difficulty';
@@ -200,7 +322,6 @@ const customMenuState = {
 
       // FOR MOODLE
       if (!moodle) {
-
         x = context.canvas.width - 100;
         y = context.canvas.height - 110;
 
@@ -210,8 +331,12 @@ const customMenuState = {
 
         this.menuIcons.push(enterIcon);
 
-        this.enterText = game.add.text(x, y, game.lang.continue, textStyles.h4_white);
-
+        this.enterText = game.add.text(
+          x,
+          y,
+          game.lang.continue,
+          textStyles.h4_white
+        );
       }
 
       // --------------------------- INFO BOX
@@ -221,42 +346,63 @@ const customMenuState = {
       // When the user clicks on the 'x', close the modal
       document.getElementsByClassName('close')[0].onclick = function () {
         self.infoBox.style.display = 'none';
-      }
+      };
 
       // When the user clicks anywhere outside of the modal, close it
       window.onclick = function (event) {
         if (event.target == self.infoBox) {
           self.infoBox.style.display = 'none';
         }
-      }
+      };
 
       this.infoBoxContent = {
-
         gameMode: {
           squareOne: {
             title: '<b>' + game.lang.game_modes + '</b>',
             body: game.lang.infoBox_mode,
-            img: '<table> <tr> <td> <b>A)</b> ' + game.lang.infoBox_mode_s1_A +
-              ' </td> <td> <b>B)</b> ' + game.lang.infoBox_mode_s1_B +
-              ' </td> </tr> <tr> <td> <img width=100% src="' + game.image['s1-A-h'].src + '"> ' +
-              ' </td> <td> <img width=100% src="' + game.image['s1-B-h'].src + '"> </td> </tr> <table>'
+            img:
+              '<table> <tr> <td> <b>A)</b> ' +
+              game.lang.infoBox_mode_s1_A +
+              ' </td> <td> <b>B)</b> ' +
+              game.lang.infoBox_mode_s1_B +
+              ' </td> </tr> <tr> <td> <img width=100% src="' +
+              game.image['s1-A-h'].src +
+              '"> ' +
+              ' </td> <td> <img width=100% src="' +
+              game.image['s1-B-h'].src +
+              '"> </td> </tr> <table>',
           },
           circleOne: {
             title: '<b>' + game.lang.game_modes + '</b>',
             body: game.lang.infoBox_mode,
-            img: '<table> <tr style="border-bottom: 5px solid white"> <td width=70%> <img width=100% src="' + game.image['c1-A-h'].src + '">' +
-              ' </td> <td> &nbsp; <b>A)</b> ' + game.lang.infoBox_mode_c1_A +
-              ' </td> </tr> </tr> <td> <img width=100% src="' + game.image['c1-B-h'].src + '"> ' +
-              ' </td> <td> &nbsp; <b>B)</b> ' + game.lang.infoBox_mode_c1_B + '</td> </tr> <table>'
+            img:
+              '<table> <tr style="border-bottom: 5px solid white"> <td width=70%> <img width=100% src="' +
+              game.image['c1-A-h'].src +
+              '">' +
+              ' </td> <td> &nbsp; <b>A)</b> ' +
+              game.lang.infoBox_mode_c1_A +
+              ' </td> </tr> </tr> <td> <img width=100% src="' +
+              game.image['c1-B-h'].src +
+              '"> ' +
+              ' </td> <td> &nbsp; <b>B)</b> ' +
+              game.lang.infoBox_mode_c1_B +
+              '</td> </tr> <table>',
           },
           squareTwo: {
             title: '<b>' + game.lang.game_modes + '</b>',
             body: game.lang.infoBox_mode,
-            img: '<table> <tr> <td> <b>A)</b> ' + game.lang.infoBox_mode_s2_A +
-              ' </td> <td> <b>B)</b> ' + game.lang.infoBox_mode_s2_B +
-              ' </td> </tr> <tr> <td> <img width=98% src="' + game.image['s2-A-h'].src + '"> ' +
-              ' </td> <td> <img width=98% src="' + game.image['s2-B-h'].src + '"> </td> </tr> <table>'
-          }
+            img:
+              '<table> <tr> <td> <b>A)</b> ' +
+              game.lang.infoBox_mode_s2_A +
+              ' </td> <td> <b>B)</b> ' +
+              game.lang.infoBox_mode_s2_B +
+              ' </td> </tr> <tr> <td> <img width=98% src="' +
+              game.image['s2-A-h'].src +
+              '"> ' +
+              ' </td> <td> <img width=98% src="' +
+              game.image['s2-B-h'].src +
+              '"> </td> </tr> <table>',
+          },
         },
 
         gameOperation: {
@@ -265,220 +411,304 @@ const customMenuState = {
           img:
             '<table class="table">' +
             '<tr>' +
-            '<td> <img width=50 src="' + game.image['operation_plus'].src + '"> </td>' +
-            '<td> <img width=50 src="' + game.image['operation_mixed'].src + '"> </td>' +
-            '<td> <img width=50 src="' + game.image['operation_minus'].src + '"> </td>' +
-            '<td> <img width=50 src="' + game.image['operation_equals'].src + '"> </td>' +
+            '<td> <img width=50 src="' +
+            game.image['operation_plus'].src +
+            '"> </td>' +
+            '<td> <img width=50 src="' +
+            game.image['operation_mixed'].src +
+            '"> </td>' +
+            '<td> <img width=50 src="' +
+            game.image['operation_minus'].src +
+            '"> </td>' +
+            '<td> <img width=50 src="' +
+            game.image['operation_equals'].src +
+            '"> </td>' +
             '</tr> <tr>' +
-            '<td class="text-center">' + game.lang.plus + '</td>' +
-            '<td class="text-center">' + game.lang.mixed + '</td>' +
-            '<td class="text-center">' + game.lang.minus + '</td>' +
-            '<td class="text-center">' + game.lang.equals + '</td>' +
+            '<td class="text-center">' +
+            game.lang.plus +
+            '</td>' +
+            '<td class="text-center">' +
+            game.lang.mixed +
+            '</td>' +
+            '<td class="text-center">' +
+            game.lang.minus +
+            '</td>' +
+            '<td class="text-center">' +
+            game.lang.equals +
+            '</td>' +
             '</tr>' +
-            '</table>'
+            '</table>',
         },
 
-gameDifficulty: {
-  squareOne: {
-    title: '<b>' + game.lang.difficulties + '</b>',
-      body: game.lang.infoBox_diff + ' ' + game.lang.infoBox_diff_obs,
-        img: '<table> <tr> <td> <b>' + game.lang.difficulty + ':</b> 1' +
-          ' </td> <td> <b>' + game.lang.difficulty + ':</b> 3' +
-          ' </td> </tr> <tr> <td> <img width=100% src="' + game.image['s1-diff-1'].src + '"> ' +
-          ' </td> <td style="border-left: 4px solid white"> <img width=100% src="' + game.image['s1-diff-3'].src + '"> </td> </tr> </table> <br>' +
-          game.lang.infoBox_diff_aux + '<center> <img width=50% src="' + game.image['map-s1'].src + '"> </center>'
-  },
-  circleOne: {
-    title: '<b>' + game.lang.difficulties + '</b>',
-      body: game.lang.infoBox_diff + ' ' + game.lang.infoBox_diff_obs,
-        img: '<table> <tr> <td style="border-right: 4px solid white"> <b>' + game.lang.difficulty + ':</b> 1' +
-          ' </td> <td> <b>' + game.lang.difficulty + ':</b> 5' +
-          ' </td> </tr> <tr> <td> <img width=100% src="' + game.image['c1-diff-1'].src + '"> ' +
-          ' </td> <td style="border-left: 4px solid white"> <img width=100% src="' + game.image['c1-diff-5'].src + '"> </td> </tr> </table> <center> <br>' +
-          game.lang.infoBox_diff_aux + '<center> <img width=50% src="' + game.image['map-c1s2'].src + '"> </center>'
-  },
-  squareTwo: {
-    title: '<b>' + game.lang.difficulties + '</b>',
-      body: game.lang.infoBox_diff,
-        img: '<table> <tr> <td> <b>' + game.lang.difficulty + ':</b> 1' +
-          ' </td> <td> <b>' + game.lang.difficulty + ':</b> 5' +
-          ' </td> </tr> <tr> <td> <img width=100% src="' + game.image['s2-diff-1'].src + '"> ' +
-          ' </td> <td style="border-left: 4px solid white"> <img width=100% src="' + game.image['s2-diff-5'].src + '"> </td> </tr> </table> <br>' +
-          game.lang.infoBox_diff_aux + '<center> <img width=50% src="' + game.image['map-c1s2'].src + '"> </center>'
-  },
-},
-
-gameMisc: {
-  squareOne: {
-    title: '<b>' + game.lang.show + ' ' + auxText + '</b>',
-      body: game.lang.infoBox_misc_label,
-        img: '<img class="mx-auto" width=80% src="' + game.image['s1-label'].src + '">',
+        gameDifficulty: {
+          squareOne: {
+            title: '<b>' + game.lang.difficulties + '</b>',
+            body: game.lang.infoBox_diff + ' ' + game.lang.infoBox_diff_obs,
+            img:
+              '<table> <tr> <td> <b>' +
+              game.lang.difficulty +
+              ':</b> 1' +
+              ' </td> <td> <b>' +
+              game.lang.difficulty +
+              ':</b> 3' +
+              ' </td> </tr> <tr> <td> <img width=100% src="' +
+              game.image['s1-diff-1'].src +
+              '"> ' +
+              ' </td> <td style="border-left: 4px solid white"> <img width=100% src="' +
+              game.image['s1-diff-3'].src +
+              '"> </td> </tr> </table> <br>' +
+              game.lang.infoBox_diff_aux +
+              '<center> <img width=50% src="' +
+              game.image['map-s1'].src +
+              '"> </center>',
+          },
+          circleOne: {
+            title: '<b>' + game.lang.difficulties + '</b>',
+            body: game.lang.infoBox_diff + ' ' + game.lang.infoBox_diff_obs,
+            img:
+              '<table> <tr> <td style="border-right: 4px solid white"> <b>' +
+              game.lang.difficulty +
+              ':</b> 1' +
+              ' </td> <td> <b>' +
+              game.lang.difficulty +
+              ':</b> 5' +
+              ' </td> </tr> <tr> <td> <img width=100% src="' +
+              game.image['c1-diff-1'].src +
+              '"> ' +
+              ' </td> <td style="border-left: 4px solid white"> <img width=100% src="' +
+              game.image['c1-diff-5'].src +
+              '"> </td> </tr> </table> <center> <br>' +
+              game.lang.infoBox_diff_aux +
+              '<center> <img width=50% src="' +
+              game.image['map-c1s2'].src +
+              '"> </center>',
           },
-  circleOne: {
-    title: '<b>' + game.lang.show + ' ' + auxText + '</b>',
-      body: game.lang.infoBox_misc_label,
-        img: '<img class="mx-auto" width=60% src="' + game.image['c1-label'].src + '">',
+          squareTwo: {
+            title: '<b>' + game.lang.difficulties + '</b>',
+            body: game.lang.infoBox_diff,
+            img:
+              '<table> <tr> <td> <b>' +
+              game.lang.difficulty +
+              ':</b> 1' +
+              ' </td> <td> <b>' +
+              game.lang.difficulty +
+              ':</b> 5' +
+              ' </td> </tr> <tr> <td> <img width=100% src="' +
+              game.image['s2-diff-1'].src +
+              '"> ' +
+              ' </td> <td style="border-left: 4px solid white"> <img width=100% src="' +
+              game.image['s2-diff-5'].src +
+              '"> </td> </tr> </table> <br>' +
+              game.lang.infoBox_diff_aux +
+              '<center> <img width=50% src="' +
+              game.image['map-c1s2'].src +
+              '"> </center>',
           },
-  squareTwo: {
-    title: '<b>' + game.lang.show + ' ' + auxText + '</b>',
-      body: game.lang.infoBox_misc_rect,
-        img: '<img class="mx-auto" width=100% src="' + game.image['s2-label'].src + '">',
-          }
-}
+        },
 
+        gameMisc: {
+          squareOne: {
+            title: '<b>' + game.lang.show + ' ' + auxText + '</b>',
+            body: game.lang.infoBox_misc_label,
+            img:
+              '<img class="mx-auto" width=80% src="' +
+              game.image['s1-label'].src +
+              '">',
+          },
+          circleOne: {
+            title: '<b>' + game.lang.show + ' ' + auxText + '</b>',
+            body: game.lang.infoBox_misc_label,
+            img:
+              '<img class="mx-auto" width=60% src="' +
+              game.image['c1-label'].src +
+              '">',
+          },
+          squareTwo: {
+            title: '<b>' + game.lang.show + ' ' + auxText + '</b>',
+            body: game.lang.infoBox_misc_rect,
+            img:
+              '<img class="mx-auto" width=100% src="' +
+              game.image['s2-label'].src +
+              '">',
+          },
+        },
       };
 
-// ------------- EVENTS
-
-game.event.add('click', this.onInputDown);
-game.event.add('mousemove', this.onInputOver);
+      // ------------- EVENTS
 
+      game.event.add('click', this.onInputDown);
+      game.event.add('mousemove', this.onInputOver);
     }
-
   },
 
-/**
- * Displays game menu information boxes.
- */
-showInfoBox: function (icon) {
-  self.infoBox.style.display = 'block';
-
-  const element = (icon.id == 'gameOperation') ? self.infoBoxContent[icon.id] : self.infoBoxContent[icon.id][gameType];
-
-  let msg = '<h3>' + element.title + '</h3>'
-    + '<p align=justify>' + element.body + '</p>'
-    + element.img;
-
-  document.getElementById('infobox-content').innerHTML = msg;
-},
-
-/**
- * Saves information selected by the player 
- * 
- * @param {object} icon selected icon
- */
-load: function (icon) {
-
-  const type = icon.iconType;
-
-  if (audioStatus) game.audio.popSound.play();
-
-  switch (type) {
-    case 'gameMode': gameMode = icon.gameMode; break;
-    case 'gameOperation': gameOperation = icon.gameOperation; break;
-    case 'difficulty': gameDifficulty = icon.difficulty; break;
-    case 'infoIcon': self.showInfoBox(icon); break;
-    case 'selectionBox':
-      if (icon.curFrame == 0) {
-        icon.curFrame = 1;
-        fractionLabel = true;
-      } else {
-        icon.curFrame = 0;
-        fractionLabel = false;
-      }
-      game.render.all();
-      break;
-    case 'enter':
-      if (debugMode) {
-        console.log('------------------------------' +
-          '\nGame State: ' + gameType +
-          '\nGame Mode: ' + gameMode +
-          '\n------------------------------');
-      }
-      mapPosition = 0;  // Map position
-      mapMove = true; // Move no next point
-      completedLevels = 0;  // Reset the game progress when entering a new level
-      game.state.start('map');
-      break;
-  }
-
-},
+  /**
+   * Displays game menu information boxes.
+   */
+  showInfoBox: function (icon) {
+    self.infoBox.style.display = 'block';
+
+    const element =
+      icon.id == 'gameOperation'
+        ? self.infoBoxContent[icon.id]
+        : self.infoBoxContent[icon.id][gameType];
+
+    let msg =
+      '<h3>' +
+      element.title +
+      '</h3>' +
+      '<p align=justify>' +
+      element.body +
+      '</p>' +
+      element.img;
+
+    document.getElementById('infobox-content').innerHTML = msg;
+  },
 
-/**
- * Called by mouse click event
- * 
- * @param {object} mouseEvent contains the mouse click coordinates
- */
-onInputDown: function (mouseEvent) {
-  const x = game.math.getMouse(mouseEvent).x;
-  const y = game.math.getMouse(mouseEvent).y;
-  let overIcon;
-
-  // Check if clicked on an icon
-  for (let i in self.menuIcons) {
-    if (game.math.isOverIcon(x, y, self.menuIcons[i])) {
-      overIcon = i;
-      break;
-    }
-  }
-
-  // Update gui
-  if (overIcon) { // If has clicked on an icon
-    document.body.style.cursor = 'pointer';
-    self.menuIcons.forEach(cur => {
-      if (cur.iconType == self.menuIcons[overIcon].iconType) { // If its in the same icon category
-        if (cur == self.menuIcons[overIcon]) { // If its the clicked icon
-          if (cur.iconType == 'gameMode' || cur.iconType == 'gameOperation') cur.curFrame = 1;
-          else if (cur.iconType == 'difficulty') cur.fillColor = colors.blue;
+  /**
+   * Saves information selected by the player
+   *
+   * @param {object} icon selected icon
+   */
+  load: function (icon) {
+    const type = icon.iconType;
+
+    if (audioStatus) game.audio.popSound.play();
+
+    switch (type) {
+      case 'gameMode':
+        gameMode = icon.gameMode;
+        break;
+      case 'gameOperation':
+        gameOperation = icon.gameOperation;
+        break;
+      case 'difficulty':
+        gameDifficulty = icon.difficulty;
+        break;
+      case 'infoIcon':
+        self.showInfoBox(icon);
+        break;
+      case 'selectionBox':
+        if (icon.curFrame == 0) {
+          icon.curFrame = 1;
+          fractionLabel = true;
         } else {
-          if (cur.iconType == 'gameMode' || cur.iconType == 'gameOperation') cur.curFrame = 0;
-          else if (cur.iconType == 'difficulty') cur.fillColor = colors.gray;
+          icon.curFrame = 0;
+          fractionLabel = false;
         }
-      }
-    });
+        game.render.all();
+        break;
+      case 'enter':
+        if (debugMode) {
+          console.log(
+            '------------------------------' +
+              '\nGame State: ' +
+              gameType +
+              '\nGame Mode: ' +
+              gameMode +
+              '\n------------------------------'
+          );
+        }
+        mapPosition = 0; // Map position
+        mapMove = true; // Move no next point
+        completedLevels = 0; // Reset the game progress when entering a new level
+        game.state.start('map');
+        break;
+    }
+  },
 
-    self.load(self.menuIcons[overIcon]);
+  /**
+   * Called by mouse click event
+   *
+   * @param {object} mouseEvent contains the mouse click coordinates
+   */
+  onInputDown: function (mouseEvent) {
+    const x = game.math.getMouse(mouseEvent).x;
+    const y = game.math.getMouse(mouseEvent).y;
+    let overIcon;
+
+    // Check if clicked on an icon
+    for (let i in self.menuIcons) {
+      if (game.math.isOverIcon(x, y, self.menuIcons[i])) {
+        overIcon = i;
+        break;
+      }
+    }
 
-  } else document.body.style.cursor = 'auto';
+    // Update gui
+    if (overIcon) {
+      // If has clicked on an icon
+      document.body.style.cursor = 'pointer';
+      self.menuIcons.forEach((cur) => {
+        if (cur.iconType == self.menuIcons[overIcon].iconType) {
+          // If its in the same icon category
+          if (cur == self.menuIcons[overIcon]) {
+            // If its the clicked icon
+            if (cur.iconType == 'gameMode' || cur.iconType == 'gameOperation')
+              cur.curFrame = 1;
+            else if (cur.iconType == 'difficulty') cur.fillColor = colors.blue;
+          } else {
+            if (cur.iconType == 'gameMode' || cur.iconType == 'gameOperation')
+              cur.curFrame = 0;
+            else if (cur.iconType == 'difficulty') cur.fillColor = colors.gray;
+          }
+        }
+      });
 
-  navigationIcons.onInputDown(x, y);
+      self.load(self.menuIcons[overIcon]);
+    } else document.body.style.cursor = 'auto';
 
-  game.render.all();
+    navigationIcons.onInputDown(x, y);
 
-},
+    game.render.all();
+  },
 
-/**
- * Called by mouse move event
- * 
- * @param {object} mouseEvent contains the mouse move coordinates
- */
-onInputOver: function (mouseEvent) {
-  const x = game.math.getMouse(mouseEvent).x;
-  const y = game.math.getMouse(mouseEvent).y;
-  let overIcon;
-
-  // Check if pointer is over an icon
-  for (let i in self.menuIcons) {
-    if (game.math.isOverIcon(x, y, self.menuIcons[i])) {
-      overIcon = i;
-      break;
-    }
-  }
-
-  // Update gui
-  if (overIcon) { // If pointer is over icon
-    document.body.style.cursor = 'pointer';
-    self.menuIcons.forEach(cur => {
-      if (cur.iconType == self.menuIcons[overIcon].iconType) { // If its in the same icon category
-        if (cur == self.menuIcons[overIcon]) { // If its the icon the pointer is over 
-          if (cur.iconType == 'enter') self.enterText.style = textStyles.h3__white;
-          cur.scale = cur.originalScale * 1.1;
-        } else {
-          cur.scale = cur.originalScale;
-        }
+  /**
+   * Called by mouse move event
+   *
+   * @param {object} mouseEvent contains the mouse move coordinates
+   */
+  onInputOver: function (mouseEvent) {
+    const x = game.math.getMouse(mouseEvent).x;
+    const y = game.math.getMouse(mouseEvent).y;
+    let overIcon;
+
+    // Check if pointer is over an icon
+    for (let i in self.menuIcons) {
+      if (game.math.isOverIcon(x, y, self.menuIcons[i])) {
+        overIcon = i;
+        break;
       }
-    });
-  } else { // If pointer is not over icon
-    if (self.enterText) self.enterText.style = textStyles.h4_white;
-    self.menuIcons.forEach(cur => { cur.scale = cur.originalScale; });
-    document.body.style.cursor = 'auto';
-  }
-
-  // Check navigation icons
-  navigationIcons.onInputOver(x, y);
+    }
 
-  game.render.all();
+    // Update gui
+    if (overIcon) {
+      // If pointer is over icon
+      document.body.style.cursor = 'pointer';
+      self.menuIcons.forEach((cur) => {
+        if (cur.iconType == self.menuIcons[overIcon].iconType) {
+          // If its in the same icon category
+          if (cur == self.menuIcons[overIcon]) {
+            // If its the icon the pointer is over
+            if (cur.iconType == 'enter')
+              self.enterText.style = textStyles.h3__white;
+            cur.scale = cur.originalScale * 1.1;
+          } else {
+            cur.scale = cur.originalScale;
+          }
+        }
+      });
+    } else {
+      // If pointer is not over icon
+      if (self.enterText) self.enterText.style = textStyles.h4_white;
+      self.menuIcons.forEach((cur) => {
+        cur.scale = cur.originalScale;
+      });
+      document.body.style.cursor = 'auto';
+    }
 
-}
+    // Check navigation icons
+    navigationIcons.onInputOver(x, y);
 
-}
+    game.render.all();
+  },
+};

File diff suppressed because it is too large
+ 334 - 185
js/gameMechanics.js


+ 221 - 97
js/games/circleOne.js

@@ -14,7 +14,7 @@
  * ......\.|./.......
  * ........|.........
  * ....1,2,3,4,5..... = gameDifficulty
- * 
+ *
  * Character : kid/balloon
  * Theme : flying in a balloon
  * Concept : 'How much the kid has to walk to get to the balloon?'
@@ -39,7 +39,6 @@
  * @namespace
  */
 const circleOne = {
-
   /**
    * Main code
    */
@@ -58,8 +57,8 @@ const circleOne = {
 
     let hasBaseDifficulty = false; // Will validate that level isnt too easy (has at least one '1/difficulty' fraction)
 
-    const startY =  context.canvas.height - 75;
-    const startX = (gameOperation == 'Minus') ? 66 + 5 * 156 : 66;  // Initial 'x' coordinate for the kid and the baloon
+    const startY = context.canvas.height - 75;
+    const startX = gameOperation == 'Minus' ? 66 + 5 * 156 : 66; // Initial 'x' coordinate for the kid and the baloon
     this.correctX = startX; // Ending position, accumulative
 
     // BACKGROUND
@@ -72,7 +71,9 @@ const circleOne = {
     game.add.image(300, 85, 'cloud', 0.8);
 
     // Add floor of grass
-    for (let i = 0; i < context.canvas.width / 100; i++) { game.add.image(i * 100, context.canvas.height - 100, 'floor'); }
+    for (let i = 0; i < context.canvas.width / 100; i++) {
+      game.add.image(i * 100, context.canvas.height - 100, 'floor');
+    }
 
     // Road
     this.road = game.add.image(47, startY - 11, 'road', 1.01, 0.94);
@@ -81,8 +82,15 @@ const circleOne = {
     const distanceBetweenPoints = 156; // Distance between road points
 
     for (let i = 0; i <= 5; i++) {
-      game.add.image(66 + i * distanceBetweenPoints, startY, 'place_off', 0.3).anchor(0.5, 0.5);
-      game.add.text(66 + i * distanceBetweenPoints, startY + 34, i, textStyles.h2_blue);
+      game.add
+        .image(66 + i * distanceBetweenPoints, startY, 'place_off', 0.3)
+        .anchor(0.5, 0.5);
+      game.add.text(
+        66 + i * distanceBetweenPoints,
+        startY + 34,
+        i,
+        textStyles.h2_blueDark
+      );
     }
 
     this.trace = game.add.geom.rect(startX - 1, startY, 1, 1, undefined, 1);
@@ -93,38 +101,47 @@ const circleOne = {
     // FOR MOODLE
     if (moodle) {
       navigationIcons.add(
-        false, false, false, // Left buttons
-        true, false,         // Right buttons
-        false, false
+        false,
+        false,
+        false, // Left buttons
+        true,
+        false, // Right buttons
+        false,
+        false
       );
     } else {
       navigationIcons.add(
-        true, true, true, // Left buttons
-        true, false,      // Right buttons
-        'customMenu', this.viewHelp
+        true,
+        true,
+        true, // Left buttons
+        true,
+        false, // Right buttons
+        'customMenu',
+        this.viewHelp
       );
     }
 
     // CIRCLES AND FRACTIONS
     this.circles = {
-      all: [],       // Circles objects of current level
-      label: [],     // Fractions labels
+      all: [], // Circles objects of current level
+      label: [], // Fractions labels
 
-      diameter: 60,  // (Fixed) diameter for circles
-      cur: 0,        // Current circle index
+      diameter: 60, // (Fixed) diameter for circles
+      cur: 0, // Current circle index
       direction: [], // Circle direction : 'Right' (plus), 'Left' (minus)
-      distance: [],  // Fraction of distance between circles (used in walking animation)
-      angle: [],     // Angle in degrees : 90 / 180 / 270 / 360
+      distance: [], // Fraction of distance between circles (used in walking animation)
+      angle: [], // Angle in degrees : 90 / 180 / 270 / 360
       lineColor: [], // Circle line colors (also used for tracing on floor)
 
-      direc: [],     // Can be : 1 or -1 : will be multiplied to values to easily change object direction when needed
+      direc: [], // Can be : 1 or -1 : will be multiplied to values to easily change object direction when needed
     };
 
     this.balloonPlace = context.canvas.width / 2; // Balloon place
 
     // Number of circles
-    const max = (gameOperation == 'Mixed' || gameMode == 'B') ? 6 : mapPosition + 1;
-    const min = (gameOperation == 'Mixed' && mapPosition < 2) ? 2 : mapPosition; // Mixed level has at least 2 fractions
+    const max =
+      gameOperation == 'Mixed' || gameMode == 'B' ? 6 : mapPosition + 1;
+    const min = gameOperation == 'Mixed' && mapPosition < 2 ? 2 : mapPosition; // Mixed level has at least 2 fractions
     const total = game.math.randomInRange(min, max); // Total number of circles
 
     // gameMode 'B' exclusive variables
@@ -132,11 +149,10 @@ const circleOne = {
     this.numberOfPlusFractions = game.math.randomInRange(1, total - 1);
 
     // CIRCLES
-    const levelDirection = (gameOperation == 'Minus') ? -1 : 1;
+    const levelDirection = gameOperation == 'Minus' ? -1 : 1;
     const x = startX + 65 * levelDirection;
 
     for (let i = 0; i < total; i++) {
-
       const divisor = game.math.randomInRange(1, gameDifficulty); // Set fraction 'divisor' (depends on difficulty)
 
       if (divisor == gameDifficulty) hasBaseDifficulty = true; // True if after for ends has at least 1 '1/difficulty' fraction
@@ -147,8 +163,12 @@ const circleOne = {
       let direction;
 
       switch (gameOperation) {
-        case 'Plus': direction = 'Right'; break;
-        case 'Minus': direction = 'Left'; break;
+        case 'Plus':
+          direction = 'Right';
+          break;
+        case 'Minus':
+          direction = 'Left';
+          break;
         case 'Mixed':
           if (i < this.numberOfPlusFractions) direction = 'Right';
           else direction = 'Left';
@@ -160,7 +180,7 @@ const circleOne = {
       let lineColor, anticlockwise;
 
       if (direction == 'Right') {
-        lineColor = colors.darkBlue;
+        lineColor = colors.blueDark;
         this.circles.direc[i] = 1;
         anticlockwise = true;
       } else {
@@ -170,19 +190,32 @@ const circleOne = {
       }
       this.circles.lineColor[i] = lineColor;
 
-      // Draw circles 
-      let circle, label = [];
+      // Draw circles
+      let circle,
+        label = [];
 
       if (divisor == 1) {
-        circle = game.add.geom.circle(startX, startY - 36 - i * this.circles.diameter, this.circles.diameter,
-          lineColor, 2, colors.white, 1);
+        circle = game.add.geom.circle(
+          startX,
+          startY - 36 - i * this.circles.diameter,
+          this.circles.diameter,
+          lineColor,
+          2,
+          colors.white,
+          1
+        );
 
         circle.anticlockwise = anticlockwise;
 
         this.circles.angle.push(360);
 
         if (fractionLabel) {
-          label[0] = game.add.text(x, startY - 36 - i * this.circles.diameter, divisor, textStyles.h2_blue);
+          label[0] = game.add.text(
+            x,
+            startY - 36 - i * this.circles.diameter,
+            divisor,
+            textStyles.h2_blueDark
+          );
           this.circles.label.push(label);
         }
       } else {
@@ -190,16 +223,40 @@ const circleOne = {
 
         if (direction == 'Right') degree = 360 - degree; // Anticlockwise equivalent
 
-        circle = game.add.geom.arc(startX, startY - 36 - i * this.circles.diameter, this.circles.diameter,
-          0, game.math.degreeToRad(degree), anticlockwise,
-          lineColor, 2, colors.white, 1);
+        circle = game.add.geom.arc(
+          startX,
+          startY - 36 - i * this.circles.diameter,
+          this.circles.diameter,
+          0,
+          game.math.degreeToRad(degree),
+          anticlockwise,
+          lineColor,
+          2,
+          colors.white,
+          1
+        );
 
         this.circles.angle.push(degree);
 
         if (fractionLabel) {
-          label[0] = game.add.text(x, startY - 46 - i * this.circles.diameter + 32, divisor, textStyles.h4_blue);
-          label[1] = game.add.text(x, startY - 38 - i * this.circles.diameter, '1', textStyles.h4_blue);
-          label[2] = game.add.text(x, startY - 38 - i * this.circles.diameter, '___', textStyles.h4_blue);
+          label[0] = game.add.text(
+            x,
+            startY - 46 - i * this.circles.diameter + 32,
+            divisor,
+            textStyles.h4_blueDark
+          );
+          label[1] = game.add.text(
+            x,
+            startY - 38 - i * this.circles.diameter,
+            '1',
+            textStyles.h4_blueDark
+          );
+          label[2] = game.add.text(
+            x,
+            startY - 38 - i * this.circles.diameter,
+            '___',
+            textStyles.h4_blueDark
+          );
           this.circles.label.push(label);
         }
       }
@@ -214,7 +271,8 @@ const circleOne = {
       this.circles.distance.push(Math.floor(distanceBetweenPoints / divisor));
       this.circles.all.push(circle);
 
-      this.correctX += Math.floor(distanceBetweenPoints / divisor) * this.circles.direc[i];
+      this.correctX +=
+        Math.floor(distanceBetweenPoints / divisor) * this.circles.direc[i];
     }
 
     // Calculate next circle
@@ -224,30 +282,54 @@ const circleOne = {
     this.restart = false;
 
     // If top circle position is out of bounds (when on the ground) or game doesnt have base difficulty, restart
-    if (this.correctX < 66 || this.correctX > 66 + 3 * 260 || !hasBaseDifficulty) {
+    if (
+      this.correctX < 66 ||
+      this.correctX > 66 + 3 * 260 ||
+      !hasBaseDifficulty
+    ) {
       this.restart = true;
     }
 
     // If game is type B, selectiong a random balloon place
     if (gameMode == 'B') {
       this.balloonPlace = startX;
-      this.endIndex = game.math.randomInRange(this.numberOfPlusFractions, this.circles.all.length);
+      this.endIndex = game.math.randomInRange(
+        this.numberOfPlusFractions,
+        this.circles.all.length
+      );
 
       for (let i = 0; i < this.endIndex; i++) {
         this.balloonPlace += this.circles.distance[i] * this.circles.direc[i];
       }
 
       // If balloon position is out of bounds, restart
-      if (this.balloonPlace < 66 || this.balloonPlace > 66 + 5 * distanceBetweenPoints) {
+      if (
+        this.balloonPlace < 66 ||
+        this.balloonPlace > 66 + 5 * distanceBetweenPoints
+      ) {
         this.restart = true;
       }
     }
 
     // KID
-    this.availableAnimations['Right'] = ['Right', [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11], 4];
-    this.availableAnimations['Left'] = ['Left', [23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12], 4];
-
-    this.kid = game.add.sprite(startX, startY - 31 - this.circles.all.length * this.circles.diameter, 'kid_walk', 0, 0.8);
+    this.availableAnimations['Right'] = [
+      'Right',
+      [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11],
+      4,
+    ];
+    this.availableAnimations['Left'] = [
+      'Left',
+      [23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12],
+      4,
+    ];
+
+    this.kid = game.add.sprite(
+      startX,
+      startY - 31 - this.circles.all.length * this.circles.diameter,
+      'kid_walk',
+      0,
+      0.8
+    );
     this.kid.anchor(0.5, 0.8);
     if (gameOperation == 'Minus') {
       this.kid.animation = this.availableAnimations['Left'];
@@ -257,11 +339,21 @@ const circleOne = {
     }
 
     // BALLOON
-    this.balloon = game.add.image(this.balloonPlace, startY - 176, 'balloon', 1, 0.5);
+    this.balloon = game.add.image(
+      this.balloonPlace,
+      startY - 176,
+      'balloon',
+      1,
+      0.5
+    );
     this.balloon.alpha = 0.5;
     this.balloon.anchor(0.5, 0.5);
 
-    this.basket = game.add.image(this.balloonPlace, startY - 54, 'balloon_basket');
+    this.basket = game.add.image(
+      this.balloonPlace,
+      startY - 54,
+      'balloon_basket'
+    );
     this.basket.anchor(0.5, 0.5);
 
     // Help pointer
@@ -287,7 +379,8 @@ const circleOne = {
       let cur = self.circles.cur;
       let direc = self.circles.direc[cur];
 
-      if (self.count % 2 == 0) { // Lowers animation
+      if (self.count % 2 == 0) {
+        // Lowers animation
         // Move kid
         self.kid.x += 2 * direc;
 
@@ -302,19 +395,23 @@ const circleOne = {
 
         // Change angle of current arc
         self.circles.angle[cur] += 4.6 * direc;
-        self.circles.all[cur].angleEnd = game.math.degreeToRad(self.circles.angle[cur]);
+        self.circles.all[cur].angleEnd = game.math.degreeToRad(
+          self.circles.angle[cur]
+        );
 
         // When finish current circle
         let lowerCircles;
         if (self.circles.direction[cur] == 'Right') {
           lowerCircles = self.circles.all[cur].x >= self.nextX;
-        }
-        else if (self.circles.direction[cur] == 'Left') {
-
+        } else if (self.circles.direction[cur] == 'Left') {
           lowerCircles = self.circles.all[cur].x <= self.nextX;
 
           // If just changed from 'right' to 'left' inform to change direction of kid animation
-          if (self.changeAnimationFrames == undefined && cur > 0 && self.circles.direction[cur - 1] == 'Right') {
+          if (
+            self.changeAnimationFrames == undefined &&
+            cur > 0 &&
+            self.circles.direction[cur - 1] == 'Right'
+          ) {
             self.changeAnimationFrames = true;
           }
         }
@@ -333,7 +430,7 @@ const circleOne = {
 
         if (lowerCircles) {
           self.circles.all[cur].alpha = 0; // Cicle disappear
-          self.circles.all.forEach(cur => {
+          self.circles.all.forEach((cur) => {
             cur.y += self.circles.diameter; // Lower circles
           });
           self.kid.y += self.circles.diameter; // Lower kid
@@ -347,7 +444,10 @@ const circleOne = {
         }
 
         // When finish all circles (final position)
-        if (cur == self.circles.all.length || self.circles.all[cur].alpha == 0) {
+        if (
+          cur == self.circles.all.length ||
+          self.circles.all[cur].alpha == 0
+        ) {
           self.animate = false;
           self.checkAnswer = true;
         }
@@ -362,15 +462,19 @@ const circleOne = {
 
       if (self.checkOverlap(self.basket, self.kid)) {
         self.result = true; // Answer is correct
-        self.kid.curFrame = (self.kid.curFrame < 12) ? 24 : 25;
+        self.kid.curFrame = self.kid.curFrame < 12 ? 24 : 25;
         if (audioStatus) game.audio.okSound.play();
-        game.add.image(context.canvas.width / 2, context.canvas.height / 2, 'ok').anchor(0.5, 0.5);
+        game.add
+          .image(context.canvas.width / 2, context.canvas.height / 2, 'ok')
+          .anchor(0.5, 0.5);
         completedLevels++;
         if (debugMode) console.log('Completed Levels: ' + completedLevels);
       } else {
         self.result = false; // Answer is incorrect
         if (audioStatus) game.audio.errorSound.play();
-        game.add.image(context.canvas.width / 2, context.canvas.height / 2, 'error').anchor(0.5, 0.5);
+        game.add
+          .image(context.canvas.width / 2, context.canvas.height / 2, 'error')
+          .anchor(0.5, 0.5);
       }
 
       self.postScore();
@@ -401,14 +505,14 @@ const circleOne = {
 
   /**
    * (in gameMode 'B') Function called when cursor is over a valid circle
-   * 
+   *
    * @param {object} cur circle the cursor is over
    */
   overCircle: function (cur) {
     if (!self.hasClicked) {
       document.body.style.cursor = 'pointer';
       for (let i in self.circles.all) {
-        self.circles.all[i].alpha = (i <= cur.index) ? 1 : 0.5;
+        self.circles.all[i].alpha = i <= cur.index ? 1 : 0.5;
       }
     }
   },
@@ -419,7 +523,7 @@ const circleOne = {
   outCircle: function () {
     if (!self.hasClicked) {
       document.body.style.cursor = 'auto';
-      self.circles.all.forEach(cur => {
+      self.circles.all.forEach((cur) => {
         cur.alpha = 0.5;
       });
     }
@@ -427,20 +531,17 @@ const circleOne = {
 
   /**
    * (in gameMode 'B') Function called when player clicked over a valid circle
-   * 
+   *
    * @param {number|object} cur clicked circle
    */
   clicked: function (cur) {
     if (!self.hasClicked) {
-
       // On gameMode A
       if (gameMode == 'A') {
         self.balloon.x = cur;
         self.basket.x = cur;
         // On gameMode B
-      }
-      else if (gameMode == 'B') {
-
+      } else if (gameMode == 'B') {
         document.body.style.cursor = 'auto';
 
         for (let i in self.circles.all) {
@@ -448,8 +549,8 @@ const circleOne = {
             self.circles.all[i].alpha = 1; // Keep selected circle
             self.fractionIndex = cur.index;
           } else {
-            self.circles.all[i].alpha = 0;  // Hide unselected circle
-            self.kid.y += self.circles.diameter;  // Lower kid to selected circle
+            self.circles.all[i].alpha = 0; // Hide unselected circle
+            self.kid.y += self.circles.diameter; // Lower kid to selected circle
           }
         }
       }
@@ -458,8 +559,10 @@ const circleOne = {
 
       // Hide fractions
       if (fractionLabel) {
-        self.circles.label.forEach(cur => {
-          cur.forEach(cur => { cur.alpha = 0; });
+        self.circles.label.forEach((cur) => {
+          cur.forEach((cur) => {
+            cur.alpha = 0;
+          });
         });
       }
 
@@ -478,10 +581,10 @@ const circleOne = {
 
   /**
    * Checks if 2 images overlap
-   * 
+   *
    * @param {object} spriteA image 1
    * @param {object} spriteB image 2
-   * 
+   *
    * @returns {boolean} true if there is overlap
    */
   checkOverlap: function (spriteA, spriteB) {
@@ -505,7 +608,8 @@ const circleOne = {
         // On gameMode B
       } else {
         self.help.x = self.circles.all[self.endIndex - 1].x;
-        self.help.y = self.circles.all[self.endIndex - 1].y - self.circles.diameter / 2;
+        self.help.y =
+          self.circles.all[self.endIndex - 1].y - self.circles.diameter / 2;
       }
       self.help.alpha = 0.7;
     }
@@ -524,14 +628,19 @@ const circleOne = {
     if (gameMode == 'A') {
       const cur = self.road;
 
-      const valid = y > 60 && (x >= cur.xWithAnchor && x <= (cur.xWithAnchor + cur.width * cur.scale));
+      const valid =
+        y > 60 &&
+        x >= cur.xWithAnchor &&
+        x <= cur.xWithAnchor + cur.width * cur.scale;
       if (valid) self.clicked(x);
     }
 
     // GAME MODE B : click circle
     if (gameMode == 'B') {
-      self.circles.all.forEach(cur => {
-        const valid = game.math.distanceToPointer(x, cur.xWithAnchor, y, cur.yWithAnchor) <= (cur.diameter / 2) * cur.scale;
+      self.circles.all.forEach((cur) => {
+        const valid =
+          game.math.distanceToPointer(x, cur.xWithAnchor, y, cur.yWithAnchor) <=
+          (cur.diameter / 2) * cur.scale;
         if (valid) self.clicked(cur);
       });
     }
@@ -553,7 +662,9 @@ const circleOne = {
 
     // GAME MODE A : balloon follow mouse
     if (gameMode == 'A' && !self.hasClicked) {
-      if (game.math.distanceToPointer(x, self.balloon.x, y, self.balloon.y) > 8) {
+      if (
+        game.math.distanceToPointer(x, self.balloon.x, y, self.balloon.y) > 8
+      ) {
         self.balloon.x = x;
         self.basket.x = x;
       }
@@ -563,8 +674,10 @@ const circleOne = {
 
     // GAME MODE B : hover circle
     if (gameMode == 'B' && !self.hasClicked) {
-      self.circles.all.forEach(cur => {
-        const valid = game.math.distanceToPointer(x, cur.xWithAnchor, y, cur.yWithAnchor) <= (cur.diameter / 2) * cur.scale;
+      self.circles.all.forEach((cur) => {
+        const valid =
+          game.math.distanceToPointer(x, cur.xWithAnchor, y, cur.yWithAnchor) <=
+          (cur.diameter / 2) * cur.scale;
         if (valid) {
           self.overCircle(cur);
           flag = true;
@@ -580,28 +693,39 @@ const circleOne = {
 
   /**
    * Saves players data after level ends - to be sent to database <br>
-   * 
+   *
    * Attention: the 'line_' prefix data table must be compatible to data table fields (MySQL server)
-   * 
+   *
    * @see /php/squareOne.js
    */
   postScore: function () {
     // Creates string that is going to be sent to db
-    const data = '&line_game=' + gameShape
-      + '&line_mode=' + gameMode
-      + '&line_oper=' + gameOperation
-      + '&line_leve=' + gameDifficulty
-      + '&line_posi=' + mapPosition
-      + '&line_resu=' + self.result
-      + '&line_time=' + game.timer.elapsed
-      + '&line_deta='
-      + 'numCircles:' + self.circles.all.length
-      + ', valCircles: ' + self.divisorsList
-      + ' balloonX: ' + self.basket.x
-      + ', selIndex: ' + self.fractionIndex;
+    const data =
+      '&line_game=' +
+      gameShape +
+      '&line_mode=' +
+      gameMode +
+      '&line_oper=' +
+      gameOperation +
+      '&line_leve=' +
+      gameDifficulty +
+      '&line_posi=' +
+      mapPosition +
+      '&line_resu=' +
+      self.result +
+      '&line_time=' +
+      game.timer.elapsed +
+      '&line_deta=' +
+      'numCircles:' +
+      self.circles.all.length +
+      ', valCircles: ' +
+      self.divisorsList +
+      ' balloonX: ' +
+      self.basket.x +
+      ', selIndex: ' +
+      self.fractionIndex;
 
     // FOR MOODLE
     sendToDB(data);
-  }
-
-};
+  },
+};

+ 210 - 104
js/games/squareOne.js

@@ -3,9 +3,9 @@
  ******************************/
 
 /** [GAME STATE]
- * 
+ *
  * ..squareOne...	= gameType
- * ..../...\..... 
+ * ..../...\.....
  * ...A.....B.... = gameMode
  * .....\./......
  * ......|.......
@@ -37,29 +37,28 @@
  * @namespace
  */
 const squareOne = {
-
   /**
    * Main code
    */
   create: function () {
     // CONTROL VARIABLES
-    this.checkAnswer = false;   // When true allows game to run 'check answer' code in update
-    this.animate = false;       // When true allows game to run 'tractor animation' code in update (turns animation of the moving tractor ON/OFF)
+    this.checkAnswer = false; // When true allows game to run 'check answer' code in update
+    this.animate = false; // When true allows game to run 'tractor animation' code in update (turns animation of the moving tractor ON/OFF)
     this.animateEnding = false; // When true allows game to run 'tractor ending animation' code in update (turns 'ending' animation of the moving tractor ON/OFF)
-    this.hasClicked = false;    // Checks if player 'clicked' on a block
-    this.result = false;        // Checks player 'answer' 
-    this.count = 0;             // An 'x' position counter used in the tractor animation        
+    this.hasClicked = false; // Checks if player 'clicked' on a block
+    this.result = false; // Checks player 'answer'
+    this.count = 0; // An 'x' position counter used in the tractor animation
 
-    this.divisorsList = '';     // Hold the divisors for each fraction on stacked blocks (created for postScore())
+    this.divisorsList = ''; // Hold the divisors for each fraction on stacked blocks (created for postScore())
 
-    this.direc_level = (gameOperation == 'Minus') ? -1 : 1;    // Will be multiplied to values to easily change tractor direction when needed
-    this.animationSpeed = 2 * this.direc_level;   // X distance in which the tractor moves in each iteration of the animation
+    this.direc_level = gameOperation == 'Minus' ? -1 : 1; // Will be multiplied to values to easily change tractor direction when needed
+    this.animationSpeed = 2 * this.direc_level; // X distance in which the tractor moves in each iteration of the animation
 
     // GAME VARIABLES
-    this.defaultBlockWidth = 80;   // Base block width
-    this.defaultBlockHeight = 40;  // Base block height
+    this.defaultBlockWidth = 80; // Base block width
+    this.defaultBlockHeight = 40; // Base block height
 
-    this.startX = (gameOperation == 'Minus') ? 730 : 170; // Initial 'x' coordinate for the tractor and stacked blocks
+    this.startX = gameOperation == 'Minus' ? 730 : 170; // Initial 'x' coordinate for the tractor and stacked blocks
     this.startY = context.canvas.height - 157;
 
     // BACKGROUND
@@ -73,26 +72,36 @@ const squareOne = {
     game.add.image(300, 85, 'cloud', 0.8);
 
     // Add floor of grass
-    for (let i = 0; i < context.canvas.width / 100; i++) { game.add.image(i * 100, context.canvas.height - 100, 'floor'); }
+    for (let i = 0; i < context.canvas.width / 100; i++) {
+      game.add.image(i * 100, context.canvas.height - 100, 'floor');
+    }
 
     // Calls function that loads navigation icons
 
     // FOR MOODLE
     if (moodle) {
       navigationIcons.add(
-        false, false, false, // Left icons
-        true, false,         // Right icons
-        false, false
+        false,
+        false,
+        false, // Left icons
+        true,
+        false, // Right icons
+        false,
+        false
       );
     } else {
       navigationIcons.add(
-        true, true, true,   // Left icons
-        true, false,        // Right icons
-        'customMenu', this.viewHelp
+        true,
+        true,
+        true, // Left icons
+        true,
+        false, // Right icons
+        'customMenu',
+        this.viewHelp
       );
     }
 
-    // TRACTOR 
+    // TRACTOR
     this.tractor = game.add.sprite(this.startX, this.startY, 'tractor', 0, 0.8);
 
     if (gameOperation == 'Plus') {
@@ -129,8 +138,8 @@ const squareOne = {
 
       // Correct values
       correctIndex: undefined, // (gameMode 'A') index of the CORRECT 'floor' block
-      correctX: undefined,  // 'x' coordinate of CORRECT 'floor' block
-      correctXA: undefined, // Temporary variable 
+      correctX: undefined, // 'x' coordinate of CORRECT 'floor' block
+      correctXA: undefined, // Temporary variable
       correctXB: undefined, // Temporary variable
     };
 
@@ -143,7 +152,11 @@ const squareOne = {
     // SELECTION ARROW
 
     if (gameMode == 'A') {
-      this.arrow = game.add.image(this.startX + this.defaultBlockWidth * this.direc_level, this.startY + 35, 'arrow_down');
+      this.arrow = game.add.image(
+        this.startX + this.defaultBlockWidth * this.direc_level,
+        this.startY + 35,
+        'arrow_down'
+      );
       this.arrow.anchor(0.5, 0.5);
       this.arrow.alpha = 0.5;
     }
@@ -183,31 +196,44 @@ const squareOne = {
 
       // MANAGE BLOCKS AND FLOOR GAPS
       // If block is 1/n (not 1/1) there's an extra block space to go through before the start of next block
-      const restOfCurBlock = (self.defaultBlockWidth - stck.blocks[stck.curIndex].width) * self.direc_level;
+      const restOfCurBlock =
+        (self.defaultBlockWidth - stck.blocks[stck.curIndex].width) *
+        self.direc_level;
 
       // Check if block falls
-      if ((gameOperation == 'Plus' && stck.blocks[0].x >= (stck.curBlockEnd + restOfCurBlock)) ||
-        (gameOperation == 'Minus' && stck.blocks[0].x <= (stck.curBlockEnd + restOfCurBlock))) {
-
+      if (
+        (gameOperation == 'Plus' &&
+          stck.blocks[0].x >= stck.curBlockEnd + restOfCurBlock) ||
+        (gameOperation == 'Minus' &&
+          stck.blocks[0].x <= stck.curBlockEnd + restOfCurBlock)
+      ) {
         let lowerBlock = true;
 
-        const curEnd = stck.blocks[0].x + stck.blocks[stck.curIndex].width * self.direc_level;
+        const curEnd =
+          stck.blocks[0].x +
+          stck.blocks[stck.curIndex].width * self.direc_level;
 
         // If current index is (A) last stacked index (correct index - fixed)
         // If current index is (B) selected stacked index
         if (stck.curIndex == stck.index) {
           // floor.index : (A) selected floor index
           // floor.index : (B) last floor index (correct index - fixed)
-          const selectedEnd = floor.blocks[floor.index].x + floor.blocks[0].width * self.direc_level;
+          const selectedEnd =
+            floor.blocks[floor.index].x +
+            floor.blocks[0].width * self.direc_level;
 
           // (A) last stacked block (fixed) doesnt fit selected gap AKA NOT ENOUGH FLOOR BLOCKS (DOESNT CHECK TOO MANY)
           // (B) selected stacked index doesnt fit last floor gap (fixed) AKA TOO MANY STACKED BLOCKS (DOESNT CHECK NOT ENOUGH)
-          if ((gameOperation == 'Plus' && curEnd > selectedEnd) || (gameOperation == 'Minus' && curEnd < selectedEnd)) {
+          if (
+            (gameOperation == 'Plus' && curEnd > selectedEnd) ||
+            (gameOperation == 'Minus' && curEnd < selectedEnd)
+          ) {
             lowerBlock = false;
           }
         } else {
           // Update to next block end
-          stck.curBlockEnd += stck.blocks[stck.curIndex + 1].width * self.direc_level;
+          stck.curBlockEnd +=
+            stck.blocks[stck.curIndex + 1].width * self.direc_level;
         }
 
         // Fill floor gap
@@ -216,7 +242,10 @@ const squareOne = {
           // Until (B) last floor index (correct index - fixed)
           // Updates floor index to be equivalent to stacked index (and change alpha so floor appears to be filled)
           for (let i = 0; i <= floor.index; i++) {
-            if ((gameOperation == 'Plus' && floor.blocks[i].x < curEnd) || (gameOperation == 'Minus' && floor.blocks[i].x > curEnd)) {
+            if (
+              (gameOperation == 'Plus' && floor.blocks[i].x < curEnd) ||
+              (gameOperation == 'Minus' && floor.blocks[i].x > curEnd)
+            ) {
               floor.blocks[i].alpha = 0.2;
               floor.curIndex = i;
             }
@@ -224,7 +253,9 @@ const squareOne = {
 
           // Lower
           stck.blocks[stck.curIndex].alpha = 0;
-          stck.blocks.forEach(cur => { cur.y += self.defaultBlockHeight - 2; }); // Lower stacked blocks
+          stck.blocks.forEach((cur) => {
+            cur.y += self.defaultBlockHeight - 2;
+          }); // Lower stacked blocks
         }
 
         stck.curIndex++;
@@ -250,18 +281,24 @@ const squareOne = {
       }
 
       // Give feedback to player and turns on sprite animation
-      if (self.result) { // Correct answer
+      if (self.result) {
+        // Correct answer
         game.animation.play(self.tractor.animation[0]);
 
-        // Displays feedback image and sound 
-        game.add.image(context.canvas.width / 2, context.canvas.height / 2, 'ok').anchor(0.5, 0.5);
+        // Displays feedback image and sound
+        game.add
+          .image(context.canvas.width / 2, context.canvas.height / 2, 'ok')
+          .anchor(0.5, 0.5);
         if (audioStatus) game.audio.okSound.play();
 
         completedLevels++; // Increases number os finished levels
         if (debugMode) console.log('Completed Levels: ' + completedLevels);
-      } else { // Incorrect answer
+      } else {
+        // Incorrect answer
         // Displays feedback image and sound
-        game.add.image(context.canvas.width / 2, context.canvas.height / 2, 'error').anchor(0.5, 0.5);
+        game.add
+          .image(context.canvas.width / 2, context.canvas.height / 2, 'error')
+          .anchor(0.5, 0.5);
         if (audioStatus) game.audio.errorSound.play();
       }
 
@@ -295,7 +332,7 @@ const squareOne = {
 
   /**
    * Function called by self.onInputOver() when cursor is over a valid rectangle
-   * 
+   *
    * @param {object} cur rectangle the cursor is over
    */
   overSquare: function (cur) {
@@ -305,7 +342,7 @@ const squareOne = {
       // On gameMode A
       if (gameMode == 'A') {
         for (let i in self.floor.blocks) {
-          self.floor.blocks[i].alpha = (i <= cur.index) ? 1 : 0.5;
+          self.floor.blocks[i].alpha = i <= cur.index ? 1 : 0.5;
         }
 
         // Saves the index of the selected 'floor' block
@@ -314,7 +351,7 @@ const squareOne = {
         // On gameMode B
       } else {
         for (let i in self.stck.blocks) {
-          self.stck.blocks[i].alpha = (i <= cur.index) ? 0.5 : 0.2;
+          self.stck.blocks[i].alpha = i <= cur.index ? 0.5 : 0.2;
         }
 
         // Saves the index of the selected 'stack' block
@@ -387,8 +424,10 @@ const squareOne = {
 
       // Hide labels
       if (fractionLabel) {
-        self.stck.labels.forEach(cur => {
-          cur.forEach(cur => { cur.alpha = 0; });
+        self.stck.labels.forEach((cur) => {
+          cur.forEach((cur) => {
+            cur.alpha = 0;
+          });
         });
       }
       // Hide solution pointer
@@ -404,18 +443,20 @@ const squareOne = {
 
   /**
    * Create stacked blocks for the level in create()
-   * 
+   *
    * @returns {boolean}
    */
   createStckBlocks: function () {
     let hasBaseDifficulty = false; // Will be true after next for loop if level has at least one '1/difficulty' fraction (if false, restart)
-    const max = (gameMode == 'B') ? 10 : mapPosition + 4; // Maximum number of stacked blocks for the level
+    const max = gameMode == 'B' ? 10 : mapPosition + 4; // Maximum number of stacked blocks for the level
 
     const total = game.math.randomInRange(mapPosition + 2, max); // Current number of stacked blocks for the level
 
-    self.floor.correctXA = self.startX + self.defaultBlockWidth * self.direc_level;
+    self.floor.correctXA =
+      self.startX + self.defaultBlockWidth * self.direc_level;
 
-    for (let i = 0; i < total; i++) { // For each stacked block
+    for (let i = 0; i < total; i++) {
+      // For each stacked block
       let divisor = game.math.randomInRange(1, gameDifficulty); // Set divisor for fraction
       if (divisor == gameDifficulty) hasBaseDifficulty = true;
       if (divisor == 3) divisor = 4; // Make sure valid divisors are 1, 2 and 4 (not 3)
@@ -426,7 +467,7 @@ const squareOne = {
       self.floor.correctXA += curBlockWidth * self.direc_level;
 
       // Create stacked block (close to tractor)
-      const lineColor = (gameOperation == 'Minus') ? colors.red : colors.darkBlue;
+      const lineColor = gameOperation == 'Minus' ? colors.red : colors.blueDark;
       const lineSize = 2;
       const block = game.add.geom.rect(
         self.startX,
@@ -436,8 +477,9 @@ const squareOne = {
         lineColor,
         lineSize,
         colors.white,
-        1);
-      const anchor = (gameOperation == 'Minus') ? 1 : 0;
+        1
+      );
+      const anchor = gameOperation == 'Minus' ? 1 : 0;
       block.anchor(anchor, 0);
 
       // If game is type B, adding events to stacked blocks
@@ -456,11 +498,31 @@ const squareOne = {
         const label = [];
 
         if (divisor == 1) {
-          label[0] = game.add.text(x, self.startY + 43 - i * y, divisor, textStyles.h2_blue);
+          label[0] = game.add.text(
+            x,
+            self.startY + 43 - i * y,
+            divisor,
+            textStyles.h2_blueDark
+          );
         } else {
-          label[0] = game.add.text(x, self.startY + 34 - i * y + 16, divisor, textStyles.p_blue);
-          label[1] = game.add.text(x, self.startY + 34 - i * y, '1', textStyles.p_blue);
-          label[2] = game.add.text(x, self.startY + 39 - i * y, '_', textStyles.p_blue);
+          label[0] = game.add.text(
+            x,
+            self.startY + 34 - i * y + 16,
+            divisor,
+            textStyles.p_blueDark
+          );
+          label[1] = game.add.text(
+            x,
+            self.startY + 34 - i * y,
+            '1',
+            textStyles.p_blueDark
+          );
+          label[2] = game.add.text(
+            x,
+            self.startY + 39 - i * y,
+            '_',
+            textStyles.p_blueDark
+          );
         }
         // Add current label to group of labels
         self.stck.labels.push(label);
@@ -468,21 +530,34 @@ const squareOne = {
     }
 
     // Will be used as a counter in update, adding in the width of each stacked block to check if the end matches the floor selected position
-    self.stck.curBlockEnd = self.startX + self.stck.blocks[0].width * self.direc_level;
+    self.stck.curBlockEnd =
+      self.startX + self.stck.blocks[0].width * self.direc_level;
 
     let restart = false;
 
     // Check for errors (level too easy for its difficulty or end position out of bounds)
-    if (!hasBaseDifficulty ||
-      (gameOperation == 'Plus' && (self.floor.correctXA < (self.startX + self.defaultBlockWidth) ||
-        self.floor.correctXA > (self.startX + 8 * self.defaultBlockWidth))) ||
-      (gameOperation == 'Minus' && (self.floor.correctXA < (self.startX - (8 * self.defaultBlockWidth)) ||
-        self.floor.correctXA > (self.startX - self.defaultBlockWidth)))
+    if (
+      !hasBaseDifficulty ||
+      (gameOperation == 'Plus' &&
+        (self.floor.correctXA < self.startX + self.defaultBlockWidth ||
+          self.floor.correctXA > self.startX + 8 * self.defaultBlockWidth)) ||
+      (gameOperation == 'Minus' &&
+        (self.floor.correctXA < self.startX - 8 * self.defaultBlockWidth ||
+          self.floor.correctXA > self.startX - self.defaultBlockWidth))
     ) {
       restart = true; // If any error is found restart the level
     }
 
-    if (debugMode) console.log('Stacked blocks: ' + total + ' (min: ' + (mapPosition + 2) + ', max: ' + max + ')');
+    if (debugMode)
+      console.log(
+        'Stacked blocks: ' +
+          total +
+          ' (min: ' +
+          (mapPosition + 2) +
+          ', max: ' +
+          max +
+          ')'
+      );
 
     return restart;
   },
@@ -490,8 +565,9 @@ const squareOne = {
   /**
    * Create floor blocks for the level in create()
    */
-  createFloorBlocks: function () { // For each floor block
-    const divisor = (gameDifficulty == 3) ? 4 : gameDifficulty; // Make sure valid divisors are 1, 2 and 4 (not 3)
+  createFloorBlocks: function () {
+    // For each floor block
+    const divisor = gameDifficulty == 3 ? 4 : gameDifficulty; // Make sure valid divisors are 1, 2 and 4 (not 3)
 
     let total = 8 * divisor; // Number of floor blocks
 
@@ -499,9 +575,13 @@ const squareOne = {
 
     // If game is type B, selectiong a random floor x position
     if (gameMode == 'B') {
-      self.stck.correctIndex = game.math.randomInRange(0, (self.stck.blocks.length - 1)); // Correct stacked index
+      self.stck.correctIndex = game.math.randomInRange(
+        0,
+        self.stck.blocks.length - 1
+      ); // Correct stacked index
 
-      self.floor.correctXB = self.startX + self.defaultBlockWidth * self.direc_level;
+      self.floor.correctXB =
+        self.startX + self.defaultBlockWidth * self.direc_level;
 
       for (let i = 0; i <= self.stck.correctIndex; i++) {
         self.floor.correctXB += self.stck.blocks[i].width * self.direc_level; // Equivalent x position on the floor
@@ -510,19 +590,28 @@ const squareOne = {
 
     let flag = true;
 
-    for (let i = 0; i < total; i++) { // For each floor block
+    for (let i = 0; i < total; i++) {
+      // For each floor block
       // 'x' coordinate for floor block
-      const x = self.startX + (self.defaultBlockWidth + i * blockWidth) * self.direc_level;
+      const x =
+        self.startX +
+        (self.defaultBlockWidth + i * blockWidth) * self.direc_level;
 
       if (flag && gameMode == 'A') {
-        if ((gameOperation == 'Plus' && x >= self.floor.correctXA) || (gameOperation == 'Minus' && x <= self.floor.correctXA)) {
+        if (
+          (gameOperation == 'Plus' && x >= self.floor.correctXA) ||
+          (gameOperation == 'Minus' && x <= self.floor.correctXA)
+        ) {
           self.floor.correctIndex = i - 1; // Set index of correct floor block
           flag = false;
         }
       }
 
       if (gameMode == 'B') {
-        if ((gameOperation == 'Plus' && x >= self.floor.correctXB) || (gameOperation == 'Minus' && x <= self.floor.correctXB)) {
+        if (
+          (gameOperation == 'Plus' && x >= self.floor.correctXB) ||
+          (gameOperation == 'Minus' && x <= self.floor.correctXB)
+        ) {
           total = i;
           break;
         }
@@ -535,11 +624,12 @@ const squareOne = {
         self.startY + 17 + self.defaultBlockHeight - lineSize,
         blockWidth - lineSize,
         self.defaultBlockHeight - lineSize,
-        colors.blueBckg,
+        colors.blueBg,
         lineSize,
-        colors.blueBckgInsideLevel,
-        1);
-      const anchor = (gameOperation == 'Minus') ? 1 : 0;
+        colors.blueBgInsideLevel,
+        1
+      );
+      const anchor = gameOperation == 'Minus' ? 1 : 0;
       block.anchor(anchor, 0);
 
       // If game is type A, adding events to floor blocks
@@ -557,8 +647,13 @@ const squareOne = {
 
     // Creates labels on the floor to display the numbers
     for (let i = 1; i < 10; i++) {
-      const x = self.startX + (i * self.defaultBlockWidth * self.direc_level);
-      game.add.text(x, self.startY + self.defaultBlockHeight + 78, i - 1, textStyles.h2_blue);
+      const x = self.startX + i * self.defaultBlockWidth * self.direc_level;
+      game.add.text(
+        x,
+        self.startY + self.defaultBlockHeight + 78,
+        i - 1,
+        textStyles.h2_blueDark
+      );
     }
   },
 
@@ -570,12 +665,12 @@ const squareOne = {
       // On gameMode A
       if (gameMode == 'A') {
         const aux = self.floor.blocks[0];
-        self.help.x = self.floor.correctX - aux.width / 2 * self.direc_level;
+        self.help.x = self.floor.correctX - (aux.width / 2) * self.direc_level;
         self.help.y = 501;
         // On gameMode B
       } else {
         const aux = self.stck.blocks[self.stck.correctIndex];
-        self.help.x = aux.x + aux.width / 2 * self.direc_level;
+        self.help.x = aux.x + (aux.width / 2) * self.direc_level;
         self.help.y = aux.y;
       }
 
@@ -585,7 +680,7 @@ const squareOne = {
 
   /**
    * Called by mouse click event
-   * 
+   *
    * @param {object} mouseEvent contains the mouse click coordinates
    */
   onInputDown: function (mouseEvent) {
@@ -593,11 +688,11 @@ const squareOne = {
     const y = game.math.getMouse(mouseEvent).y;
 
     if (gameMode == 'A') {
-      self.floor.blocks.forEach(cur => {
+      self.floor.blocks.forEach((cur) => {
         if (game.math.isOverIcon(x, y, cur)) self.clickSquare(cur);
       });
     } else {
-      self.stck.blocks.forEach(cur => {
+      self.stck.blocks.forEach((cur) => {
         if (game.math.isOverIcon(x, y, cur)) self.clickSquare(cur);
       });
     }
@@ -609,7 +704,7 @@ const squareOne = {
 
   /**
    * Called by mouse move event
-   * 
+   *
    * @param {object} mouseEvent contains the mouse move coordinates
    */
   onInputOver: function (mouseEvent) {
@@ -622,11 +717,11 @@ const squareOne = {
       // Make arrow follow mouse
       if (!self.hasClicked && !self.animateEnding) {
         if (game.math.distanceToPointer(self.arrow.x, x, self.arrow.y, y) > 8) {
-          self.arrow.x = (x < 250) ? 250 : x; // Limits the arrow left position to 250
+          self.arrow.x = x < 250 ? 250 : x; // Limits the arrow left position to 250
         }
       }
 
-      self.floor.blocks.forEach(cur => {
+      self.floor.blocks.forEach((cur) => {
         if (game.math.isOverIcon(x, y, cur)) {
           flagA = true;
           self.overSquare(cur);
@@ -637,7 +732,7 @@ const squareOne = {
     }
 
     if (gameMode == 'B') {
-      self.stck.blocks.forEach(cur => {
+      self.stck.blocks.forEach((cur) => {
         if (game.math.isOverIcon(x, y, cur)) {
           flagB = true;
           self.overSquare(cur);
@@ -656,26 +751,37 @@ const squareOne = {
    * Saves players data after level ends - to be sent to database <br>
    *
    * Attention: the 'line_' prefix data table must be compatible to data table fields (MySQL server)
-   * 
+   *
    * @see /php/save.php
    */
   postScore: function () {
     // Creates string that is going to be sent to db
-    const data = '&line_game=' + gameShape
-      + '&line_mode=' + gameMode
-      + '&line_oper=' + gameOperation
-      + '&line_leve=' + gameDifficulty
-      + '&line_posi=' + mapPosition
-      + '&line_resu=' + self.result
-      + '&line_time=' + game.timer.elapsed
-      + '&line_deta='
-      + 'numBlocks:' + self.stck.blocks.length
-      + ', valBlocks: ' + self.divisorsList // Ends in ','
-      + ' blockIndex: ' + self.stck.index
-      + ', floorIndex: ' + self.floor.index;
-
-    // FOR MOODLE  
-    sendToDB(data);
-  }
+    const data =
+      '&line_game=' +
+      gameShape +
+      '&line_mode=' +
+      gameMode +
+      '&line_oper=' +
+      gameOperation +
+      '&line_leve=' +
+      gameDifficulty +
+      '&line_posi=' +
+      mapPosition +
+      '&line_resu=' +
+      self.result +
+      '&line_time=' +
+      game.timer.elapsed +
+      '&line_deta=' +
+      'numBlocks:' +
+      self.stck.blocks.length +
+      ', valBlocks: ' +
+      self.divisorsList + // Ends in ','
+      ' blockIndex: ' +
+      self.stck.index +
+      ', floorIndex: ' +
+      self.floor.index;
 
-};
+    // FOR MOODLE
+    sendToDB(data);
+  },
+};

+ 237 - 89
js/games/squareTwo.js

@@ -3,7 +3,7 @@
  ******************************/
 
 /** [GAME STATE]
- *  
+ *
  * .squareTwo. = gameType
  * .../...\...
  * ..A.....B.. = gameMode
@@ -12,44 +12,43 @@
  * ...Equals.. = gameOperation
  * .....|.....
  * .1,2,3,4,5. = gameDifficulty
- * 
+ *
  * Character : kid
  * Theme : (not themed)
  * Concept : player select equivalent dividends for fractions with different divisors
  * Represent fractions as : subdivided rectangles
  *
  * Game modes can be :
- * 
- *   A : equivalence of fractions 
+ *
+ *   A : equivalence of fractions
  *       top has more subdivisions
  *   B : equivalence of fractions
  *       bottom has more subdivisions
- * 
+ *
  * Operations :
  *
- *   Equals : Player selects equivalent fractions of both blocks 
- * 
+ *   Equals : Player selects equivalent fractions of both blocks
+ *
  * @namespace
  */
 const squareTwo = {
-
   /**
    * Main code
    */
   create: function () {
     // CONTROL VARIABLES
 
-    this.result = false;    // Check if selected blocks are correct
-    this.delay = 0;         // Counter for game dalays
+    this.result = false; // Check if selected blocks are correct
+    this.delay = 0; // Counter for game dalays
     this.endLevel = false;
 
     this.A = {
-      blocks: [],     // List of selection blocks
-      auxBlocks: [],  // List of shadow under selection blocks
-      fractions: [],  // Fraction numbers
-      selected: 0,    // Number of selected blocks for A
-      hasClicked: false,  // Check if player clicked blocks from A
-      animate: false,     // Animate blocks from A
+      blocks: [], // List of selection blocks
+      auxBlocks: [], // List of shadow under selection blocks
+      fractions: [], // Fraction numbers
+      selected: 0, // Number of selected blocks for A
+      hasClicked: false, // Check if player clicked blocks from A
+      animate: false, // Animate blocks from A
       warningText: undefined,
       label: undefined,
     };
@@ -74,25 +73,43 @@ const squareTwo = {
     game.add.image(300, 85, 'cloud', 0.8);
 
     // Add floor of grass
-    for (let i = 0; i < context.canvas.width / 100; i++) { game.add.image(i * 100, context.canvas.height - 100, 'floor'); }
+    for (let i = 0; i < context.canvas.width / 100; i++) {
+      game.add.image(i * 100, context.canvas.height - 100, 'floor');
+    }
 
     // Calls function that loads navigation icons
 
     // FOR MOODLE
     if (moodle) {
       navigationIcons.add(
-        false, false, false, // Left buttons
-        true, false,         // Right buttons
-        false, false);
+        false,
+        false,
+        false, // Left buttons
+        true,
+        false, // Right buttons
+        false,
+        false
+      );
     } else {
       navigationIcons.add(
-        true, true, false, // Left buttons
-        true, false,       // Right buttons
-        'customMenu', false);
+        true,
+        true,
+        false, // Left buttons
+        true,
+        false, // Right buttons
+        'customMenu',
+        false
+      );
     }
 
     // Add kid
-    this.kidAnimation = game.add.sprite(100, context.canvas.height - 128, 'kid_standing', 5, 0.8);
+    this.kidAnimation = game.add.sprite(
+      100,
+      context.canvas.height - 128,
+      'kid_standing',
+      5,
+      0.8
+    );
     this.kidAnimation.anchor(0.5, 0.7);
 
     // Width and Height of A and B
@@ -101,55 +118,90 @@ const squareTwo = {
 
     // Coordinates for A and B
     let xA, xB, yA, yB;
-    if (gameMode != 'B') { // More subdivisions on B
-      xA = context.canvas.width / 2 - this.figureWidth/2;
+    if (gameMode != 'B') {
+      // More subdivisions on B
+      xA = context.canvas.width / 2 - this.figureWidth / 2;
       yA = gameFrame().y;
       xB = xA;
       yB = yA + 3 * figureHeight + 30;
-    } else { // More subdivisions on A
-      xB = context.canvas.width / 2 - this.figureWidth/2;
+    } else {
+      // More subdivisions on A
+      xB = context.canvas.width / 2 - this.figureWidth / 2;
       yB = gameFrame().y;
       xA = xB;
       yA = yB + 3 * figureHeight + 30;
     }
-    
+
     // Possible points for A
     const points = [2, 4, 6, 8, 9, 10, 12, 14, 15, 16, 18, 20];
 
     // Random index for 'points'
-    const randomIndex = game.math.randomInRange((gameDifficulty - 1) * 2 + 1, (gameDifficulty - 1) * 2 + 3);
+    const randomIndex = game.math.randomInRange(
+      (gameDifficulty - 1) * 2 + 1,
+      (gameDifficulty - 1) * 2 + 3
+    );
 
     // Number of subdivisions of A and B (blocks)
     const totalBlocksA = points[randomIndex];
     const totalBlocksB = game.math.randomDivisor(totalBlocksA);
 
     if (debugMode) {
-      console.log('Difficulty: ' + gameDifficulty +
-        '\ncur index: ' + randomIndex + ', (min index: ' + ((gameDifficulty - 1) * 2 + 1) + ', max index: ' + ((gameDifficulty - 1) * 2 + 3) + ')' +
-        '\ntotal blocks A: ' + totalBlocksA + ', total blocks B: ' + totalBlocksB);
+      console.log(
+        'Difficulty: ' +
+          gameDifficulty +
+          '\ncur index: ' +
+          randomIndex +
+          ', (min index: ' +
+          ((gameDifficulty - 1) * 2 + 1) +
+          ', max index: ' +
+          ((gameDifficulty - 1) * 2 + 3) +
+          ')' +
+          '\ntotal blocks A: ' +
+          totalBlocksA +
+          ', total blocks B: ' +
+          totalBlocksB
+      );
     }
 
     // CREATING TOP FIGURE (A)
     let blockWidth = this.figureWidth / totalBlocksA; // Width of each block in A
-    let lineColor = colors.darkRed;
-    let fillColor = colors.lightRed;
+    let lineColor = colors.redDark;
+    let fillColor = colors.redLight;
 
     // Create blocks
     for (let i = 0; i < totalBlocksA; i++) {
       const x = xA + i * blockWidth;
 
       // Blocks
-      const block = game.add.geom.rect(x, yA, blockWidth, figureHeight, lineColor, 2, fillColor, 0.5);
+      const block = game.add.geom.rect(
+        x,
+        yA,
+        blockWidth,
+        figureHeight,
+        lineColor,
+        2,
+        fillColor,
+        0.5
+      );
       block.figure = 'A';
       block.index = i;
       block.finalX = xA;
       this.A.blocks.push(block);
 
       // Auxiliar blocks
-      const alpha = (fractionLabel) ? 0.1 : 0;
+      const alpha = fractionLabel ? 0.1 : 0;
 
       const yAux = yA + figureHeight + 10; // On the bottom of A
-      const auxBlock = game.add.geom.rect(x, yAux, blockWidth, figureHeight, lineColor, 1, fillColor, alpha);
+      const auxBlock = game.add.geom.rect(
+        x,
+        yAux,
+        blockWidth,
+        figureHeight,
+        lineColor,
+        1,
+        fillColor,
+        alpha
+      );
       this.A.auxBlocks.push(auxBlock);
     }
 
@@ -157,38 +209,76 @@ const squareTwo = {
     let xLabel = xA + this.figureWidth + 30;
     let yLabel = yA + figureHeight / 2;
 
-    this.A.label = game.add.text(xLabel, yLabel, this.A.blocks.length, textStyles.h4_blue);
+    this.A.label = game.add.text(
+      xLabel,
+      yLabel,
+      this.A.blocks.length,
+      textStyles.h4_blueDark
+    );
 
     // 'selected blocks/fraction' label for A : at the bottom of A
     yLabel = yA + figureHeight + 34;
 
-    this.A.fractions[0] = game.add.text(xLabel, yLabel, '', textStyles.h4_blue);
-    this.A.fractions[1] = game.add.text(xLabel, yLabel + 21, '', textStyles.h4_blue);
-    this.A.fractions[2] = game.add.text(xLabel, yLabel, '___', textStyles.h4_blue);
+    this.A.fractions[0] = game.add.text(
+      xLabel,
+      yLabel,
+      '',
+      textStyles.h4_blueDark
+    );
+    this.A.fractions[1] = game.add.text(
+      xLabel,
+      yLabel + 21,
+      '',
+      textStyles.h4_blueDark
+    );
+    this.A.fractions[2] = game.add.text(
+      xLabel,
+      yLabel,
+      '___',
+      textStyles.h4_blueDark
+    );
     this.A.fractions[0].alpha = 0;
     this.A.fractions[1].alpha = 0;
     this.A.fractions[2].alpha = 0;
 
     // CREATING BOTTOM FIGURE (B)
     blockWidth = this.figureWidth / totalBlocksB; // Width of each block in B
-    lineColor = colors.darkGreen;
-    fillColor = colors.lightGreen;
+    lineColor = colors.greenDark;
+    fillColor = colors.greenLight;
 
     // Blocks and auxiliar blocks
     for (let i = 0; i < totalBlocksB; i++) {
       const x = xB + i * blockWidth;
 
       // Blocks
-      const block = game.add.geom.rect(x, yB, blockWidth, figureHeight, lineColor, 2, fillColor, 0.5);
+      const block = game.add.geom.rect(
+        x,
+        yB,
+        blockWidth,
+        figureHeight,
+        lineColor,
+        2,
+        fillColor,
+        0.5
+      );
       block.figure = 'B';
       block.index = i;
       block.finalX = xB;
       this.B.blocks.push(block);
 
       // Auxiliar blocks
-      const alpha = (fractionLabel) ? 0.1 : 0;
+      const alpha = fractionLabel ? 0.1 : 0;
       const yAux = yB + figureHeight + 10; // On the bottom of B
-      const auxBlock = game.add.geom.rect(x, yAux, blockWidth, figureHeight, lineColor, 1, fillColor, alpha);
+      const auxBlock = game.add.geom.rect(
+        x,
+        yAux,
+        blockWidth,
+        figureHeight,
+        lineColor,
+        1,
+        fillColor,
+        alpha
+      );
       this.B.auxBlocks.push(auxBlock);
     }
 
@@ -196,21 +286,51 @@ const squareTwo = {
     xLabel = xB + this.figureWidth + 30;
     yLabel = yB + figureHeight / 2;
 
-    this.B.label = game.add.text(xLabel, yLabel, this.B.blocks.length, textStyles.h4_blue);
+    this.B.label = game.add.text(
+      xLabel,
+      yLabel,
+      this.B.blocks.length,
+      textStyles.h4_blueDark
+    );
 
     // Label fraction
     yLabel = yB + figureHeight + 34;
 
-    this.B.fractions[0] = game.add.text(xLabel, yLabel, '', textStyles.h4_blue);
-    this.B.fractions[1] = game.add.text(xLabel, yLabel + 21, '', textStyles.h4_blue);
-    this.B.fractions[2] = game.add.text(xLabel, yLabel, '___', textStyles.h4_blue);
+    this.B.fractions[0] = game.add.text(
+      xLabel,
+      yLabel,
+      '',
+      textStyles.h4_blueDark
+    );
+    this.B.fractions[1] = game.add.text(
+      xLabel,
+      yLabel + 21,
+      '',
+      textStyles.h4_blueDark
+    );
+    this.B.fractions[2] = game.add.text(
+      xLabel,
+      yLabel,
+      '___',
+      textStyles.h4_blueDark
+    );
     this.B.fractions[0].alpha = 0;
     this.B.fractions[1].alpha = 0;
     this.B.fractions[2].alpha = 0;
 
     // Invalid selection text
-    this.A.warningText = game.add.text(context.canvas.width / 2, context.canvas.height / 2 - 225, '', textStyles.h4_brown);
-    this.B.warningText = game.add.text(context.canvas.width / 2, context.canvas.height / 2 - 45, '', textStyles.h4_brown);
+    this.A.warningText = game.add.text(
+      context.canvas.width / 2,
+      context.canvas.height / 2 - 225,
+      '',
+      textStyles.h4_brown
+    );
+    this.B.warningText = game.add.text(
+      context.canvas.width / 2,
+      context.canvas.height / 2 - 45,
+      '',
+      textStyles.h4_brown
+    );
 
     game.timer.start(); // Set a timer for the current level (used in postScore)
 
@@ -224,7 +344,7 @@ const squareTwo = {
   update: function () {
     // Animate blocks
     if (self.A.animate || self.B.animate) {
-      ['A', 'B'].forEach(cur => {
+      ['A', 'B'].forEach((cur) => {
         if (self[cur].animate) {
           // Lower selected blocks
           for (let i = 0; i < self[cur].selected; i++) {
@@ -247,13 +367,17 @@ const squareTwo = {
 
       // After delay is over, check result
       if (self.delay > 50) {
-        self.result = (self.A.selected / self.A.blocks.length) == (self.B.selected / self.B.blocks.length);
+        self.result =
+          self.A.selected / self.A.blocks.length ==
+          self.B.selected / self.B.blocks.length;
 
         // Fractions are equivalent : CORRECT
         if (self.result) {
           if (audioStatus) game.audio.okSound.play();
 
-          game.add.image(context.canvas.width / 2, context.canvas.height / 2, 'ok').anchor(0.5, 0.5);
+          game.add
+            .image(context.canvas.width / 2, context.canvas.height / 2, 'ok')
+            .anchor(0.5, 0.5);
           mapMove = true; // Allow character to move to next level in map state
           completedLevels++;
 
@@ -262,7 +386,9 @@ const squareTwo = {
           // Fractions are not equivalent : INCORRECT
         } else {
           if (audioStatus) game.audio.errorSound.play();
-          game.add.image(context.canvas.width / 2, context.canvas.height / 2, 'error').anchor(0.5, 0.5);
+          game.add
+            .image(context.canvas.width / 2, context.canvas.height / 2, 'error')
+            .anchor(0.5, 0.5);
           mapMove = false; // Doesnt allow character to move to next level in map state
         }
 
@@ -288,16 +414,17 @@ const squareTwo = {
 
   /**
    * Function called by self.onInputOver() when cursor is over a valid rectangle.
-   * 
+   *
    * @param {object} curBlock rectangle the cursor is over : can be self.A.blocks[i] or self.B.blocks[i]
    */
   overSquare: function (curBlock) {
     const curSet = curBlock.figure; // 'A' || 'B'
 
-    if (!self[curSet].hasClicked) { // self.A.hasClicked || self.B.hasClicked 
+    if (!self[curSet].hasClicked) {
+      // self.A.hasClicked || self.B.hasClicked
       // If over fraction 'n/n' shows warning message not allowing it
       if (curBlock.index == self[curSet].blocks.length - 1) {
-        const otherSet = (curSet == 'A') ? 'B' : 'A';
+        const otherSet = curSet == 'A' ? 'B' : 'A';
 
         self[curSet].warningText.name = game.lang.s2_error_msg;
         self[otherSet].warningText.name = '';
@@ -311,13 +438,17 @@ const squareTwo = {
 
         // Selected blocks become fully visible
         for (let i in self[curSet].blocks) {
-          self[curSet].blocks[i].alpha = (i <= curBlock.index) ? 1 : 0.5;
+          self[curSet].blocks[i].alpha = i <= curBlock.index ? 1 : 0.5;
         }
 
         self[curSet].fractions[0].name = curBlock.index + 1; // Nominator : selected blocks
         self[curSet].fractions[1].name = self[curSet].blocks.length; // Denominator : total blocks
 
-        const newX = curBlock.finalX + ((curBlock.index + 1) * (self.figureWidth / self[curSet].blocks.length)) + 25;
+        const newX =
+          curBlock.finalX +
+          (curBlock.index + 1) *
+            (self.figureWidth / self[curSet].blocks.length) +
+          25;
         self[curSet].fractions[0].x = newX;
         self[curSet].fractions[1].x = newX;
         self[curSet].fractions[2].x = newX;
@@ -329,7 +460,7 @@ const squareTwo = {
 
   /**
    * Function called (by self.onInputOver() and self.overSquare()) when cursor is out of a valid rectangle.
-   * 
+   *
    * @param {object} curSet set of rectangles : can be top (self.A) or bottom (self.B)
    */
   outSquare: function (curSet) {
@@ -338,7 +469,7 @@ const squareTwo = {
       self[curSet].fractions[1].alpha = 0;
       self[curSet].fractions[2].alpha = 0;
 
-      self[curSet].blocks.forEach(cur => {
+      self[curSet].blocks.forEach((cur) => {
         cur.alpha = 0.5;
       });
     }
@@ -346,13 +477,16 @@ const squareTwo = {
 
   /**
    * Function called by self.onInputDown() when player clicked a valid rectangle.
-   * 
+   *
    * @param {object} curBlock clicked rectangle : can be self.A.blocks[i] or self.B.blocks[i]
    */
   clickSquare: function (curBlock) {
     const curSet = curBlock.figure; // 'A' || 'B'
 
-    if (!self[curSet].hasClicked && curBlock.index != self[curSet].blocks.length - 1) {
+    if (
+      !self[curSet].hasClicked &&
+      curBlock.index != self[curSet].blocks.length - 1
+    ) {
       document.body.style.cursor = 'auto';
 
       // Turn auxiliar blocks invisible
@@ -369,7 +503,11 @@ const squareTwo = {
       self[curSet].selected = curBlock.index + 1;
 
       // Set fraction x position
-      const newX = curBlock.finalX + (self[curSet].selected * (self.figureWidth / self[curSet].blocks.length)) + 25;
+      const newX =
+        curBlock.finalX +
+        self[curSet].selected *
+          (self.figureWidth / self[curSet].blocks.length) +
+        25;
       self[curSet].fractions[0].x = newX;
       self[curSet].fractions[1].x = newX;
       self[curSet].fractions[2].x = newX;
@@ -386,7 +524,7 @@ const squareTwo = {
 
   /**
    * Called by mouse click event
-   * 
+   *
    * @param {object} mouseEvent contains the mouse click coordinates
    */
   onInputDown: function (mouseEvent) {
@@ -394,12 +532,12 @@ const squareTwo = {
     const y = game.math.getMouse(mouseEvent).y;
 
     // Click block in A
-    self.A.blocks.forEach(cur => {
+    self.A.blocks.forEach((cur) => {
       if (game.math.isOverIcon(x, y, cur)) self.clickSquare(cur);
     });
 
     // Click block in B
-    self.B.blocks.forEach(cur => {
+    self.B.blocks.forEach((cur) => {
       if (game.math.isOverIcon(x, y, cur)) self.clickSquare(cur);
     });
 
@@ -411,7 +549,7 @@ const squareTwo = {
 
   /**
    * Called by mouse move event
-   * 
+   *
    * @param {object} mouseEvent contains the mouse move coordinates
    */
   onInputOver: function (mouseEvent) {
@@ -421,7 +559,7 @@ const squareTwo = {
     let flagB = false;
 
     // Mouse over A : show fraction
-    self.A.blocks.forEach(cur => {
+    self.A.blocks.forEach((cur) => {
       if (game.math.isOverIcon(x, y, cur)) {
         flagA = true;
         self.overSquare(cur);
@@ -430,7 +568,7 @@ const squareTwo = {
     if (!flagA) self.outSquare('A');
 
     // Mouse over B : show fraction
-    self.B.blocks.forEach(cur => {
+    self.B.blocks.forEach((cur) => {
       if (game.math.isOverIcon(x, y, cur)) {
         flagB = true;
         self.overSquare(cur);
@@ -450,26 +588,36 @@ const squareTwo = {
    * Saves players data after level ends - to be sent to database. <br>
    *
    * Attention: the 'line_' prefix data table must be compatible to data table fields (MySQL server)
-   * 
+   *
    * @see /php/save.php
    */
   postScore: function () {
     // Creates string that is going to be sent to db
-    const data = '&line_game=' + gameShape
-      + '&line_mode=' + gameMode
-      + '&line_oper=Equal'
-      + '&line_leve=' + gameDifficulty
-      + '&line_posi=' + mapPosition
-      + '&line_resu=' + self.result
-      + '&line_time=' + game.timer.elapsed
-      + '&line_deta='
-      + 'numBlocksA: ' + self.A.blocks.length
-      + ', valueA: ' + self.A.selected
-      + ', numBlocksB: ' + self.B.blocks.length
-      + ', valueB: ' + self.B.selected;
+    const data =
+      '&line_game=' +
+      gameShape +
+      '&line_mode=' +
+      gameMode +
+      '&line_oper=Equal' +
+      '&line_leve=' +
+      gameDifficulty +
+      '&line_posi=' +
+      mapPosition +
+      '&line_resu=' +
+      self.result +
+      '&line_time=' +
+      game.timer.elapsed +
+      '&line_deta=' +
+      'numBlocksA: ' +
+      self.A.blocks.length +
+      ', valueA: ' +
+      self.A.selected +
+      ', numBlocksB: ' +
+      self.B.blocks.length +
+      ', valueB: ' +
+      self.B.selected;
 
     // FOR MOODLE
     sendToDB(data);
-  }
-
-};
+  },
+};

+ 267 - 145
js/globals.js

@@ -1,27 +1,27 @@
 /**************************************************************
  * LInE - Free Education, Private Data - http://www.usp.br/line
- * 
+ *
  * This file holds all global elements to the game.
- * 
+ *
  * Generating game levels in menu:
- * ..................................................... 
+ * .....................................................
  * ...............square....................circle...... }                   = gameShape
  * .........../...........\....................|........ } = gameType (game)
  * ........One.............Two................One....... }
- * ......./...\.........../...\............./....\...... 
+ * ......./...\.........../...\............./....\......
  * ......A.....B.........A.....B...........A......B..... = gameMode (game mode)
  * .(floor)..(stack)..(top)..(bottom)..(floor)..(stack).
- * .......\./.............\./................\./........ 
- * ........|...............|..................|......... 
- * ......./.\..............|................/.|.\....... 
+ * .......\./.............\./................\./........
+ * ........|...............|..................|.........
+ * ......./.\..............|................/.|.\.......
  * ...Plus...Minus.......Equals........Plus.Minus.Mixed. = gameOperation (game math operation)
- * .......\./..............|................\.|./....... 
- * ........|...............|..................|......... 
+ * .......\./..............|................\.|./.......
+ * ........|...............|..................|.........
  * ......1,2,3.........1,2,3,4,5..........1,2,3,4,5..... = gameDifficulty (difficulty level)
- * ..................................................... 
- * 
+ * .....................................................
+ *
  * About levels in map:
- * 
+ *
  * ..................(game.levels)......................
  * ......................__|__..........................
  * .....................|.|.|.|.........................
@@ -37,7 +37,7 @@
 const debugMode = false;
 
 /** FOR MOODLE <br>
- * 
+ *
  * iFractions can run on a server or inside moodle through iAssign. <br>
  * This variable should be set according to where it is suposed to run: <br>
  * - if true, on moodle <br>
@@ -48,7 +48,7 @@ const moodle = false;
 /**
  * Name of the selected game.<br>
  * Can be: 'squareOne', 'squareTwo' or 'circleOne'.
- * 
+ *
  * @type {string}
  */
 let gameType;
@@ -57,7 +57,7 @@ let gameType;
  * Used for text and game information.<br>
  * Shape that makes the name of the game - e.g in 'squareOne' it is 'square'.<br>
  * Can be: 'circle' or 'square'.
- * 
+ *
  * @type {string}
  */
 let gameShape;
@@ -66,7 +66,7 @@ let gameShape;
  * Holds selected game mode.<br>
  * In squareOne/circleOne   can be: 'A' (click on the floor) or 'B' (click on the amount to go/stacked figures).<br>
  * In squareTwo             can be: 'A' (more subdivisions on top) or 'B' (more subdivisions on bottom).
- * 
+ *
  * @type {string}
  */
 let gameMode;
@@ -76,16 +76,16 @@ let gameMode;
  * In squareOne   can be: 'Plus' (green tractor goes right) or 'Minus' (red tractor goes left).<br>
  * In circleOne   can be: 'Plus' (green tractor goes right), 'Minus' (red tractor goes left) or 'Mixed' (green tractor goes both sides).<br>
  * In squareTwo   can be: 'Equals' (compares two rectangle subdivisions).
- * 
+ *
  * @type {string}
  */
 let gameOperation;
 
 /**
- * Holds game overall difficulty. 1 (easier) -> n (harder).<br> 
+ * Holds game overall difficulty. 1 (easier) -> n (harder).<br>
  * In squareOne             can be: 1..3.<br>
  * In circleOne/squareTwo   can be: 1..5.
- * 
+ *
  * @type {number}
  */
 let gameDifficulty;
@@ -147,9 +147,7 @@ const medSrc = 'assets/img/'; // Base directory for media
  * @type {object}
  */
 const info = {
-
   all: {
-
     squareOne: {
       gameShape: 'square',
       gameType: 'squareOne',
@@ -158,7 +156,7 @@ const info = {
       gameModeUrl: ['mode0', 'mode1'],
       gameOperation: ['Plus', 'Minus'],
       gameOperationUrl: ['operation_plus', 'operation_minus'],
-      gameDifficulty: 3
+      gameDifficulty: 3,
     },
 
     circleOne: {
@@ -168,8 +166,12 @@ const info = {
       gameMode: ['A', 'B'],
       gameModeUrl: ['mode2', 'mode3'],
       gameOperation: ['Plus', 'Minus', 'Mixed'],
-      gameOperationUrl: ['operation_plus', 'operation_minus', 'operation_mixed'],
-      gameDifficulty: 5
+      gameOperationUrl: [
+        'operation_plus',
+        'operation_minus',
+        'operation_mixed',
+      ],
+      gameDifficulty: 5,
     },
 
     squareTwo: {
@@ -180,9 +182,8 @@ const info = {
       gameModeUrl: ['mode4', 'mode5'],
       gameOperation: ['Equals'],
       gameOperationUrl: ['operation_equals'],
-      gameDifficulty: 5
+      gameDifficulty: 5,
     },
-
   },
   gameShape: [],
   gameType: [],
@@ -192,7 +193,6 @@ const info = {
   gameOperation: [],
   gameOperationUrl: [],
   gameDifficulty: [],
-
 };
 
 // Called once when the game starts
@@ -207,7 +207,7 @@ const info = {
     info.gameOperationUrl.push(info.all[key].gameOperationUrl);
     info.gameDifficulty.push(info.all[key].gameDifficulty);
   }
-})()
+})();
 
 /**
  * Preset colors for graphic elements.
@@ -215,74 +215,137 @@ const info = {
  */
 const colors = {
   // Blues
-  blueBckg: '#cce5ff', // Background color 
-  blueBckgOff: '#adc8e6',
-  blueBckgInsideLevel: '#a8c0e6', // Background color in squareOne (used for floor gap)
   blue: '#003cb3', // Subtitle
+  blueDark: '#183780', // Line color that indicates right and fraction numbers
+
+  blueBg: '#cce5ff', // Background color
+  blueBgOff: '#adc8e6',
+  blueBgInsideLevel: '#a8c0e6', // Background color in squareOne (used for floor gap)
+
   blueMenuLine: '#b7cdf4',
-  darkBlue: '#183780', // Line color that indicates right and fraction numbers
 
   // Reds
   red: '#b30000', // Linecolor that indicates left
-  lightRed: '#d27979', // squareTwo figures
-  darkRed: '#330000', // squareTwo figures and some titles
+  redLight: '#d27979', // squareTwo figures
+  redDark: '#330000', // squareTwo figures and some titles
 
   // Greens
   green: '#00804d', // Title
-  lightGreen: '#83afaf', // squareTwo figures
-  darkGreen: '#1e2f2f', // squareTwo figures
-  intenseGreen: '#00d600',
+  greenLight: '#83afaf', // squareTwo figures
+  greenDark: '#1e2f2f', // squareTwo figures
+  greenNeon: '#00d600',
 
   // Basics
   white: '#efeff5',
   gray: '#708090',
   black: '#000',
-  yellow: '#ffef1f'
+  yellow: '#ffef1f',
 };
 
 /**
  * Preset text styles for game text.<br>
  * Contains: font, size, text color and text align.
- * @type {object} 
+ * @type {object}
  */
 const textStyles = {
-  h1_green: { font: '32px Arial,sans-serif', fill: colors.green, align: 'center' }, // Menu title
-  h2_green: { font: '26px Arial,sans-serif', fill: colors.green, align: 'center' }, // Flag labels (langState)
-
-  h1_white: { font: '32px Arial,sans-serif', fill: colors.white, align: 'center' }, // Ok button (nameState)
-  h2_white: { font: '26px Arial,sans-serif', fill: colors.white, align: 'center' }, // Difficulty buttons (menuState)
-  h3__white: { font: '23px Arial,sans-serif', fill: colors.white, align: 'center' }, // Difficulty numbers (menuState)
-  h4_white: { font: '20px Arial,sans-serif', fill: colors.white, align: 'center' }, // Difficulty numbers (menuState)
-  p_white: { font: '14px Arial,sans-serif', fill: colors.white, align: 'center' }, // Enter button (menuState)
-
-  h2_brown: { font: '26px Arial,sans-serif', fill: colors.darkRed, align: 'center' }, // Map difficulty label
-  h4_brown: { font: '20px Arial,sans-serif', fill: colors.darkRed, align: 'center' }, // Menu overtitle
-  p_brown: { font: '14px Arial,sans-serif', fill: colors.darkRed, align: 'center' }, // Map difficulty label
-
-  h2_blue_2: { font: '26px Arial,sans-serif', fill: colors.blue, align: 'center' }, // Menu subtitle
-  h4_blue_2: { font: '20px Arial,sans-serif', fill: colors.blue, align: 'center' }, // Menu subtitle
-  h2_blue: { font: '26px Arial,sans-serif', fill: colors.darkBlue, align: 'center' }, // Fractions
-  h4_blue: { font: '20px Arial,sans-serif', fill: colors.darkBlue, align: 'center' }, // Fractions
-  p_blue: { font: '14px Arial,sans-serif', fill: colors.darkBlue, align: 'center' } // Fractions
+  h1_green: {
+    font: '32px Arial,sans-serif',
+    fill: colors.green,
+    align: 'center',
+  }, // Menu title
+  h2_green: {
+    font: '26px Arial,sans-serif',
+    fill: colors.green,
+    align: 'center',
+  }, // Flag labels (langState)
+
+  h1_white: {
+    font: '32px Arial,sans-serif',
+    fill: colors.white,
+    align: 'center',
+  }, // Ok button (nameState)
+  h2_white: {
+    font: '26px Arial,sans-serif',
+    fill: colors.white,
+    align: 'center',
+  }, // Difficulty buttons (menuState)
+  h3__white: {
+    font: '23px Arial,sans-serif',
+    fill: colors.white,
+    align: 'center',
+  }, // Difficulty numbers (menuState)
+  h4_white: {
+    font: '20px Arial,sans-serif',
+    fill: colors.white,
+    align: 'center',
+  }, // Difficulty numbers (menuState)
+  p_white: {
+    font: '14px Arial,sans-serif',
+    fill: colors.white,
+    align: 'center',
+  }, // Enter button (menuState)
+
+  h2_brown: {
+    font: '26px Arial,sans-serif',
+    fill: colors.redDark,
+    align: 'center',
+  }, // Map difficulty label
+  h4_brown: {
+    font: '20px Arial,sans-serif',
+    fill: colors.redDark,
+    align: 'center',
+  }, // Menu overtitle
+  p_brown: {
+    font: '14px Arial,sans-serif',
+    fill: colors.redDark,
+    align: 'center',
+  }, // Map difficulty label
+
+  h2_blue: {
+    font: '26px Arial,sans-serif',
+    fill: colors.blue,
+    align: 'center',
+  }, // Menu subtitle
+  h4_blue: {
+    font: '20px Arial,sans-serif',
+    fill: colors.blue,
+    align: 'center',
+  }, // Menu subtitle
+
+  h2_blueDark: {
+    font: '26px Arial,sans-serif',
+    fill: colors.blueDark,
+    align: 'center',
+  }, // Fractions
+  h4_blueDark: {
+    font: '20px Arial,sans-serif',
+    fill: colors.blueDark,
+    align: 'center',
+  }, // Fractions
+  p_blueDark: {
+    font: '14px Arial,sans-serif',
+    fill: colors.blueDark,
+    align: 'center',
+  }, // Fractions
 };
 
 /**
  * List of URL for all media in the game
- * divided 1st by the 'state' that loads the media 
+ * divided 1st by the 'state' that loads the media
  * and 2nd by the 'media type' for that state.
- * 
+ *
  * @type {object}
  */
 const url = {
-  /** 
-   * url.<state> 
-   * where <state> can be: boot, menu, squareOne, squareTwo, circleOne. 
-  */
+  /**
+   * url.<state>
+   * where <state> can be: boot, menu, squareOne, squareTwo, circleOne.
+   */
   boot: {
     /**
-     * url.<state>.<media type> 
+     * url.<state>.<media type>
      * where <media type> can be: image, sprite, audio <br><br>
-     * 
+     *
      * image: [ [name, source], ... ] <br>
      * sprite: [ [name, source, number of frames], ... ] <br>
      * audio: [ [name, [source, alternative source] ], ... ]
@@ -305,11 +368,11 @@ const url = {
       ['tree3', medSrc + 'scene/tree3.png'],
       ['tree4', medSrc + 'scene/tree4.png'],
       // Flags
-      ['flag_BR', medSrc + 'flag/BRAZ.jpg'],
-      ['flag_FR', medSrc + 'flag/FRAN.jpg'],
-      ['flag_IT', medSrc + 'flag/ITAL.png'],
-      ['flag_PE', medSrc + 'flag/PERU.jpg'],
-      ['flag_US', medSrc + 'flag/UNST.jpg'],
+      ['flag_BR', medSrc + 'flag/br.png'],
+      ['flag_FR', medSrc + 'flag/fr.png'],
+      ['flag_IT', medSrc + 'flag/it.png'],
+      ['flag_PE', medSrc + 'flag/pe.png'],
+      ['flag_US', medSrc + 'flag/us.png'],
       // Navigation icons on the top of the page
       ['back', medSrc + 'navig_icon/back.png'],
       ['help', medSrc + 'navig_icon/help.png'],
@@ -370,7 +433,7 @@ const url = {
       // Menu icons - Math operations
       ['operation_plus', medSrc + 'levels/operation_plus.png', 2], // Square/circle I : right
       ['operation_minus', medSrc + 'levels/operation_minus.png', 2], // Square/circle I : left
-      ['operation_mixed', medSrc + 'levels/operation_mixed.png', 2], // Circle I : mixed 
+      ['operation_mixed', medSrc + 'levels/operation_mixed.png', 2], // Circle I : mixed
       ['operation_equals', medSrc + 'levels/operation_equals.png', 2], // Square II : equals
     ],
     audio: [
@@ -378,33 +441,33 @@ const url = {
       ['beepSound', ['assets/audio/beep.ogg', 'assets/audio/beep.mp3']],
       ['okSound', ['assets/audio/ok.ogg', 'assets/audio/ok.mp3']],
       ['errorSound', ['assets/audio/error.ogg', 'assets/audio/error.mp3']],
-      ['popSound', ['','assets/audio/pop.wav']]
-    ]
+      ['popSound', ['', 'assets/audio/pop.wav']],
+    ],
   },
   squareOne: {
     image: [
       // Map buildings
       ['farm', medSrc + 'scene/farm.png'],
-      ['garage', medSrc + 'scene/garage.png']
+      ['garage', medSrc + 'scene/garage.png'],
     ],
     sprite: [
       // Game sprites
-      ['tractor', medSrc + 'character/tractor/tractor.png', 15]
+      ['tractor', medSrc + 'character/tractor/tractor.png', 15],
     ],
-    audio: []
+    audio: [],
   },
   squareTwo: {
     image: [
       // Map buildings
       ['house', medSrc + 'scene/house.png'],
-      ['school', medSrc + 'scene/school.png']
+      ['school', medSrc + 'scene/school.png'],
     ],
     sprite: [
       // Game sprites
       ['kid_standing', medSrc + 'character/kid/lost.png', 6],
-      ['kid_run', medSrc + 'character/kid/run.png', 12]
+      ['kid_run', medSrc + 'character/kid/run.png', 12],
     ],
-    audio: []
+    audio: [],
   },
   circleOne: {
     image: [
@@ -413,13 +476,13 @@ const url = {
       ['school', medSrc + 'scene/school.png'],
       // Game images
       ['balloon', medSrc + 'character/balloon/airballoon_upper.png'],
-      ['balloon_basket', medSrc + 'character/balloon/airballoon_base.png']
+      ['balloon_basket', medSrc + 'character/balloon/airballoon_base.png'],
     ],
     sprite: [
       // Game sprites
-      ['kid_run', medSrc + 'character/kid/run.png', 12]
+      ['kid_run', medSrc + 'character/kid/run.png', 12],
     ],
-    audio: []
+    audio: [],
   },
 };
 
@@ -428,12 +491,11 @@ const url = {
  * @namespace
  */
 const navigationIcons = {
-
   /**
    * Add navigation icons.<br>
    *  * The icons on the left are ordered from left to right. <br>
    *  * The icons on the right are ordered from right to left.
-   * 
+   *
    * @param {boolean} leftIcon0 1st left icon (back)
    * @param {boolean} leftIcon1 2nd left icon (main menu)
    * @param {boolean} leftIcon2 3rd left icon (solve game)
@@ -442,8 +504,15 @@ const navigationIcons = {
    * @param {undefined|string} state state to be called by the 'back' button (must exist if param 'leftIcon0' is true)
    * @param {undefined|function} help function in the current game state that display correct answer
    */
-  add: function (leftIcon0, leftIcon1, leftIcon2, rightIcon0, rightIcon1, state, help) {
-
+  add: function (
+    leftIcon0,
+    leftIcon1,
+    leftIcon2,
+    rightIcon0,
+    rightIcon1,
+    state,
+    help
+  ) {
     let left_x = 10;
     let right_x = context.canvas.width - 50 - 10;
     this.iconsList = [];
@@ -457,9 +526,12 @@ const navigationIcons = {
 
     // Left icons
 
-    if (leftIcon0) { // Return to previous screen
+    if (leftIcon0) {
+      // Return to previous screen
       if (!state) {
-        console.error('Game error: You tried to add a \'back\' icon without the \'state\' parameter.');
+        console.error(
+          "Game error: You tried to add a 'back' icon without the 'state' parameter."
+        );
       } else {
         this.state = state;
         this.iconsList.push(game.add.image(left_x, 10, 'back'));
@@ -467,14 +539,18 @@ const navigationIcons = {
       }
     }
 
-    if (leftIcon1) { // Return to main menu screen
+    if (leftIcon1) {
+      // Return to main menu screen
       this.iconsList.push(game.add.image(left_x, 10, 'menu'));
       left_x += 50;
     }
 
-    if (leftIcon2) { // Shows solution to the game
+    if (leftIcon2) {
+      // Shows solution to the game
       if (!help) {
-        console.error('Game error: You tried to add a \'game solution\' icon without the \'help\' parameter.');
+        console.error(
+          "Game error: You tried to add a 'game solution' icon without the 'help' parameter."
+        );
       } else {
         this.help = help;
         this.iconsList.push(game.add.image(left_x, 10, 'help'));
@@ -484,23 +560,24 @@ const navigationIcons = {
 
     // Right icons
 
-    if (rightIcon0) { // Turns game audio on/off
+    if (rightIcon0) {
+      // Turns game audio on/off
       this.audioIcon = game.add.sprite(right_x, 10, 'audio', 1);
       this.audioIcon.curFrame = audioStatus ? 0 : 1;
       this.iconsList.push(this.audioIcon);
       right_x -= 50;
     }
 
-    if (rightIcon1) { // Return to select language screen
+    if (rightIcon1) {
+      // Return to select language screen
       this.iconsList.push(game.add.image(right_x, 10, 'language'));
       right_x -= 50;
     }
-
   },
 
   /**
    * When 'back' icon is clicked go to this state
-   * 
+   *
    * @param {string} state name of the next state
    */
   callState: function (state) {
@@ -511,21 +588,28 @@ const navigationIcons = {
   },
 
   /**
-   * Called by mouse click event 
-   * 
+   * Called by mouse click event
+   *
    * @param {number} x contains the mouse x coordinate
    * @param {number} y contains the mouse y coordinate
    */
   onInputDown: function (x, y) {
-
-    navigationIcons.iconsList.forEach(cur => {
+    navigationIcons.iconsList.forEach((cur) => {
       if (game.math.isOverIcon(x, y, cur)) {
         const name = cur.name;
         switch (name) {
-          case 'back': navigationIcons.callState(navigationIcons.state); break;
-          case 'menu': navigationIcons.callState('menu'); break;
-          case 'help': navigationIcons.help(); break;
-          case 'language': navigationIcons.callState('lang'); break;
+          case 'back':
+            navigationIcons.callState(navigationIcons.state);
+            break;
+          case 'menu':
+            navigationIcons.callState('menu');
+            break;
+          case 'help':
+            navigationIcons.help();
+            break;
+          case 'language':
+            navigationIcons.callState('lang');
+            break;
           case 'audio':
             if (audioStatus) {
               audioStatus = false;
@@ -537,7 +621,8 @@ const navigationIcons = {
             }
             game.render.all();
             break;
-          default: console.error('Game error: error in navigation icon');
+          default:
+            console.error('Game error: error in navigation icon');
         }
       }
     });
@@ -545,24 +630,33 @@ const navigationIcons = {
 
   /**
    * Called by mouse move event
-   * 
+   *
    * @param {number} x contains the mouse x coordinate
    * @param {number} y contains the mouse y coordinate
    */
   onInputOver: function (x, y) {
-
     let flag = false;
 
-    navigationIcons.iconsList.forEach(cur => {
+    navigationIcons.iconsList.forEach((cur) => {
       if (game.math.isOverIcon(x, y, cur)) {
         flag = true;
         let name = cur.name;
         switch (name) {
-          case 'back': navigationIcons.left_text.name = game.lang.nav_back; break;
-          case 'menu': navigationIcons.left_text.name = game.lang.nav_menu; break;
-          case 'help': navigationIcons.left_text.name = game.lang.nav_help; break;
-          case 'language': navigationIcons.right_text.name = game.lang.nav_lang; break;
-          case 'audio': navigationIcons.right_text.name = game.lang.audio; break;
+          case 'back':
+            navigationIcons.left_text.name = game.lang.nav_back;
+            break;
+          case 'menu':
+            navigationIcons.left_text.name = game.lang.nav_menu;
+            break;
+          case 'help':
+            navigationIcons.left_text.name = game.lang.nav_help;
+            break;
+          case 'language':
+            navigationIcons.right_text.name = game.lang.nav_lang;
+            break;
+          case 'audio':
+            navigationIcons.right_text.name = game.lang.audio;
+            break;
         }
       }
     });
@@ -573,20 +667,17 @@ const navigationIcons = {
     } else {
       document.body.style.cursor = 'pointer';
     }
-  }
-
+  },
 };
 
 /**
  * Sends game information to database
- *  
+ *
  * @param {string} extraData player information for the current game
  */
 const sendToDB = function (extraData) {
-
   // FOR MOODLE
   if (moodle) {
-
     if (self.result) moodleVar.hits[mapPosition - 1]++;
     else moodleVar.errors[mapPosition - 1]++;
 
@@ -595,58 +686,81 @@ const sendToDB = function (extraData) {
     const url = iLMparameters.iLM_PARAM_ServerToGetAnswerURL;
     const grade = '' + getEvaluation();
     const report = getAnswer();
-    const data = 'return_get_answer=1' +
-      '&iLM_PARAM_ActivityEvaluation=' + encodeURIComponent(grade) +
-      '&iLM_PARAM_ArchiveContent=' + encodeURIComponent(report);
-
-    const init = { method: 'POST', body: data, headers: { 'Content-type': 'application/x-www-form-urlencoded; charset=UTF-8' } };
+    const data =
+      'return_get_answer=1' +
+      '&iLM_PARAM_ActivityEvaluation=' +
+      encodeURIComponent(grade) +
+      '&iLM_PARAM_ArchiveContent=' +
+      encodeURIComponent(report);
+
+    const init = {
+      method: 'POST',
+      body: data,
+      headers: {
+        'Content-type': 'application/x-www-form-urlencoded; charset=UTF-8',
+      },
+    };
 
     fetch(url, init)
-      .then(response => {
+      .then((response) => {
         if (response.ok) {
-          if (debugMode) console.log("Processing...");
+          if (debugMode) console.log('Processing...');
         } else {
-          console.error("Game error: Network response was not ok.");
+          console.error('Game error: Network response was not ok.');
         }
       })
-      .catch(error => {
-        console.error('Game error: problem with fetch operation - ' + error.message + '.');
+      .catch((error) => {
+        console.error(
+          'Game error: problem with fetch operation - ' + error.message + '.'
+        );
       });
-
   } else {
-
     // Create some variables we need to send to our PHP file
     // Attention: this names must be compactible to data table (MySQL server)
     // @see php/save.php
-    const data = 'line_ip=143.107.45.11' // INSERT database server IP
-      + '&line_name=' + playerName
-      + '&line_lang=' + langString
-      + extraData;
+    const data =
+      'line_ip=143.107.45.11' + // INSERT database server IP
+      '&line_name=' +
+      playerName +
+      '&line_lang=' +
+      langString +
+      extraData;
 
     const url = 'php/save.php';
 
-    const init = { method: 'POST', body: data, headers: { 'Content-type': 'application/x-www-form-urlencoded' } };
+    const init = {
+      method: 'POST',
+      body: data,
+      headers: { 'Content-type': 'application/x-www-form-urlencoded' },
+    };
     fetch(url, init)
-      .then(response => {
+      .then((response) => {
         if (response.ok) {
-          if (debugMode) console.log("Processing...");
-          response.text().then(text => { if (debugMode) { console.log(text); } })
+          if (debugMode) console.log('Processing...');
+          response.text().then((text) => {
+            if (debugMode) {
+              console.log(text);
+            }
+          });
         } else {
-          console.error("Game error: Network response was not ok.");
+          console.error('Game error: Network response was not ok.');
         }
       })
-      .catch(error => {
-        console.error('Game error: problem with fetch operation - ' + error.message + '.');
+      .catch((error) => {
+        console.error(
+          'Game error: problem with fetch operation - ' + error.message + '.'
+        );
       });
   }
-
 };
 
 let gameFrame = function () {
-  let x = y = 200;
+  let x = (y = 200);
   let width = context.canvas.width - 2 * x;
   let height = context.canvas.height - 2 * y;
-  let rect = function () { game.add.geom.rect(x, y, width, height, colors.red, 2) }
+  let rect = function () {
+    game.add.geom.rect(x, y, width, height, colors.red, 2);
+  };
   let point = function (offsetW, offsetH) {
     for (let i = 0, y1 = y; i < 4; i++) {
       x1 = x;
@@ -656,6 +770,14 @@ let gameFrame = function () {
       }
       y1 += offsetH;
     }
+  };
+  return { x, y, width, height, rect, point };
+};
+
+// for debug
+const debugGrid = function () {
+  for (let i = 0; i < 12; i++) {
+    game.add.geom.rect(i * 160, 0, 80, 1080, colors.white, 0, colors.blue, 0.3);
+    game.add.geom.rect(0, i * 180, 1920, 90, colors.white, 0, colors.blue, 0.3);
   }
-  return { x, y, width, height, rect, point}
-}
+};

+ 101 - 67
js/integrationFunctions.js

@@ -1,19 +1,19 @@
 /*************************************************************************************
  * LInE - Free Education, Private Data - http://www.usp.br/line
- * 
- * This code is used EXCLUSIVELY when iFractions is runnign inside Moodle via iAssign 
+ *
+ * This code is used EXCLUSIVELY when iFractions is runnign inside Moodle via iAssign
  * as an iLM (interactive learning module) and the global variable moodle=true.
- * 
- * More about iAssign: 
+ *
+ * More about iAssign:
  * http://200.144.254.107/git/LInE/iassign
- * 
- * More about creating iLM for iAssign (and the functions in this file): 
+ *
+ * More about creating iLM for iAssign (and the functions in this file):
  * https://www.ime.usp.br/~igormf/ima-tutorial/ (in pt-BR)
- * 
+ *
  *************************************************************************************/
 
 /** [Functions used by iAssign]
- * 
+ *
  * The iLM will be included in the HTML page as an iFrame,
  * therefore some parameters are going to be passed by the iAssign to the iLM via URL. <br>
  * This method will read these parameters.
@@ -21,38 +21,52 @@
 function getParameterByName(name) {
   var match = RegExp('[?&]' + name + '=([^&]*)').exec(window.location.search);
   return match ? decodeURIComponent(match[1].replace(/\+/g, ' ')) : null;
-};
+}
 
 /** [Functions used by iAssign]
- * 
+ *
  * This function is automaticaly called by iAssign in two different times: <br>
- * 
+ *
  * - When a PROFESSOR finishes creating an new iLM and clicks "save". <br>
  *   Returns: the iLM created (aka the values set by the professor in text form). <br>
- * 
+ *
  * - When a STUDENT finishes solving an assignment and clicks "send". <br>
  *   Returns: data about the student's progress (aka the student's progress in text form). <br>
- * 
+ *
  *  @returns {string} the data that will be received by iAssign and stored on the database (a game file with extension .frc)
  */
 function getAnswer() {
   let str = '';
-  if (iLMparameters.iLM_PARAM_SendAnswer == 'false') { // Student - sending results
-    str += 'gameType:' + gameType
-      + '\ngameShape:' + gameShape
-      + '\ngameMode:' + gameMode
-      + '\ngameOperation:' + gameOperation
-      + '\ngameDifficulty:' + gameDifficulty
-      + '\nfractionLabel:' + fractionLabel
-      + '\nresults:';
+  if (iLMparameters.iLM_PARAM_SendAnswer == 'false') {
+    // Student - sending results
+    str +=
+      'gameType:' +
+      gameType +
+      '\ngameShape:' +
+      gameShape +
+      '\ngameMode:' +
+      gameMode +
+      '\ngameOperation:' +
+      gameOperation +
+      '\ngameDifficulty:' +
+      gameDifficulty +
+      '\nfractionLabel:' +
+      fractionLabel +
+      '\nresults:';
     for (let i = 0; i < moodleVar.hits.length; i++) {
-      str += '{level=' + (i + 1)
-        + ',hits=' + moodleVar.hits[i]
-        + ',errors=' + moodleVar.errors[i]
-        + ',timeElapsed=' + moodleVar.time[i]
-        + '}';
+      str +=
+        '{level=' +
+        (i + 1) +
+        ',hits=' +
+        moodleVar.hits[i] +
+        ',errors=' +
+        moodleVar.errors[i] +
+        ',timeElapsed=' +
+        moodleVar.time[i] +
+        '}';
     }
-  } else { // Professor - creating new assignment
+  } else {
+    // Professor - creating new assignment
     if (!gameType) {
       alert(game.lang.error_must_select_game);
       return x;
@@ -60,37 +74,45 @@ function getAnswer() {
     moodleVar.hits = [0, 0, 0, 0];
     moodleVar.errors = [0, 0, 0, 0];
     moodleVar.time = [0, 0, 0, 0];
-    str += 'gameType:' + gameType
-      + '\ngameShape:' + gameShape
-      + '\ngameMode:' + gameMode
-      + '\ngameOperation:' + gameOperation
-      + '\ngameDifficulty:' + gameDifficulty
-      + '\nfractionLabel:' + fractionLabel;
+    str +=
+      'gameType:' +
+      gameType +
+      '\ngameShape:' +
+      gameShape +
+      '\ngameMode:' +
+      gameMode +
+      '\ngameOperation:' +
+      gameOperation +
+      '\ngameDifficulty:' +
+      gameDifficulty +
+      '\nfractionLabel:' +
+      fractionLabel;
   }
-  
+
   return str;
-};
+}
 
 /** [Functions used by iAssign]
- * 
+ *
  * This function must be present if the iMA uses automatic evaluation. <br>
  * It is is called by iAssign after the student submits a solution
  * and the data is sent to the moodle database.
  *
  * @returns {number} student's grade for the current assignment : real number between 0.0 and 1.0
  */
- function getEvaluation() {
-  if (iLMparameters.iLM_PARAM_SendAnswer == 'false') { // Student
+function getEvaluation() {
+  if (iLMparameters.iLM_PARAM_SendAnswer == 'false') {
+    // Student
     let i;
     for (i = 0; i < moodleVar.hits.length && moodleVar.hits[i] == 1; i++);
     const grade = i / 4;
     parent.getEvaluationCallback(grade); // Sends grade to moodle db
     return grade;
   }
-};
+}
 
 /** [Functions used by iAssign]
- * 
+ *
  * Holds the parameters passed by the iAssign to the iLM via URL.
  */
 const iLMparameters = {
@@ -99,44 +121,52 @@ const iLMparameters = {
    * - if true, the user is creating a new iLM (as professor) <br>
    * - if false, the user is solving the iLM (as student), value=false
    */
-  iLM_PARAM_SendAnswer: getParameterByName("iLM_PARAM_SendAnswer"), // Checks if you're student (false) or professor (true)
-  /** 
+  iLM_PARAM_SendAnswer: getParameterByName('iLM_PARAM_SendAnswer'), // Checks if you're student (false) or professor (true)
+  /**
    * This parameter is used when the user is opening an iLM to solve it. <br>
    * It holds a URL with the path to the game file (assignment/iLM) created by the professor. <br>
    * Example: http://myschool.edu/moodle/mod/iassign/ilm_security.php?id=3&token=b3660dd4de0b0e9bb01fea6cc8f02ccd&view=1
-   * 
+   *
    * The first parameter, 'token', can be used only once.
    * Once the iLM gets the game file, the token is destroied (for security).
    */
-  iLM_PARAM_Assignment: getParameterByName("iLM_PARAM_Assignment"),
+  iLM_PARAM_Assignment: getParameterByName('iLM_PARAM_Assignment'),
   /**
    * Gets current moodle language.
    */
-  lang: getParameterByName("lang"),
-  iLM_PARAM_ServerToGetAnswerURL: getParameterByName("iLM_PARAM_ServerToGetAnswerURL")
+  lang: getParameterByName('lang'),
+  iLM_PARAM_ServerToGetAnswerURL: getParameterByName(
+    'iLM_PARAM_ServerToGetAnswerURL'
+  ),
 };
 
 /**
- * Makes a GET request for the assignment file 
+ * Makes a GET request for the assignment file
  * and sends it to breakString() to treat its content.
  */
 const getiLMContent = function () {
   const url = iLMparameters.iLM_PARAM_Assignment;
   if (url == null) {
-    console.error("Game error: iLMparameters.iLM_PARAM_Assignment empty (File with extension .frc not found).");
+    console.error(
+      'Game error: iLMparameters.iLM_PARAM_Assignment empty (File with extension .frc not found).'
+    );
   } else {
     const init = { method: 'GET' };
     fetch(url, init)
-      .then(response => {
+      .then((response) => {
         if (response.ok) {
           if (debugMode) console.log('Processing...');
-          response.text().then(text => { breakString(text); }); // Sends text to be treated
+          response.text().then((text) => {
+            breakString(text);
+          }); // Sends text to be treated
         } else {
-          console.error("Game error: Network response was not ok.")
+          console.error('Game error: Network response was not ok.');
         }
       })
-      .catch(error => {
-        console.error('Game error: problem with fetch operation - ' + error.message + '.');
+      .catch((error) => {
+        console.error(
+          'Game error: problem with fetch operation - ' + error.message + '.'
+        );
       });
   }
 };
@@ -144,16 +174,17 @@ const getiLMContent = function () {
 /**
  * Receives the text from the assignment file,
  * breaks the string into a key/value
- * and sends it to updateGlobalVariables() 
+ * and sends it to updateGlobalVariables()
  * to update game variables before showing the screen.
- * 
+ *
  * @param {string} text content of the .frc file
  */
 const breakString = function (text) {
-  let gameInfo = {}, results;
+  let gameInfo = {},
+    results;
   const lines = text.split('\n'); // Break by line
 
-  lines.forEach(cur => {
+  lines.forEach((cur) => {
     try {
       let line = cur.split(':'); // Break by key:value
       if (line[0] != 'results') {
@@ -163,7 +194,9 @@ const breakString = function (text) {
       } else {
         results = line[1].replace(/^\s+|\s+$/g, '');
       }
-    } catch (Error) { console.error('Game error: sintax error.'); }
+    } catch (Error) {
+      console.error('Game error: sintax error.');
+    }
   });
 
   if (results) {
@@ -171,10 +204,10 @@ const breakString = function (text) {
     const curLevel = results.split('}'); // Remove }
     results = { l1: {}, l2: {}, l3: {}, l4: {} };
 
-    curLevel.forEach(cur => {
+    curLevel.forEach((cur) => {
       cur = cur.slice(1); // Remove {
       cur = cur.split(','); // Break by line
-      cur.forEach(cur => {
+      cur.forEach((cur) => {
         try {
           if (cur.length != 0) {
             let line = cur.split('='); // Break by key=value
@@ -182,22 +215,22 @@ const breakString = function (text) {
             const value = line[1].replace(/^\s+|\s+$/g, ''); // Removes end char
             results['l' + i][key] = parseInt(value);
           }
-        } catch (Error) { console.error('Game error: sintax error.'); }
+        } catch (Error) {
+          console.error('Game error: sintax error.');
+        }
       });
       i++;
     });
-
   }
 
   updateGlobalVariables(gameInfo, results);
-
 };
 
 /**
  * Updates game variables before starting the activity, then: <br>
  * - calls state 'customMenu' if the assignment WAS NOT previously completed. <br>
  * - calls state 'studentReport' otherwise.
- * 
+ *
  * @param {object} info game information
  * @param {undefined|object} infoResults student answer (if there is any)
  */
@@ -222,7 +255,8 @@ const updateGlobalVariables = function (infoGame, infoResults) {
       moodleVar.time[i] = infoResults['l' + (i + 1)].timeElapsed;
     }
     game.state.start('studentReport');
-  } else { // If assignment WAS NOT previously completed, calls 'customMenu' after all is loaded.
+  } else {
+    // If assignment WAS NOT previously completed, calls 'customMenu' after all is loaded.
     game.state.start('customMenu');
   }
 };
@@ -230,5 +264,5 @@ const updateGlobalVariables = function (infoGame, infoResults) {
 const moodleVar = {
   hits: [0, 0, 0, 0],
   errors: [0, 0, 0, 0],
-  time: [0, 0, 0, 0]
-};
+  time: [0, 0, 0, 0],
+};

+ 194 - 90
js/map.js

@@ -3,78 +3,151 @@
  ******************************/
 
 /** [MAP STATE] Screen that shows the 4 generated levels in a map (and the level where the player is currently in).
- * 
+ *
  * @namespace
  */
 const mapState = {
-
   /**
    * Main code
    */
   create: function () {
-
     // Background color
-    game.add.geom.rect(0, 0, context.canvas.width, context.canvas.height, undefined, 0, colors.blueBckg, 1);
+    game.add.geom.rect(
+      0,
+      0,
+      context.canvas.width,
+      context.canvas.height,
+      undefined,
+      0,
+      colors.blueBg,
+      1
+    );
 
     // Calls function that loads navigation icons
 
     // FOR MOODLE
     if (moodle) {
       navigationIcons.add(
-        false, false, false, // Left icons
-        false, false,        // Right icons
-        false, false);
+        false,
+        false,
+        false, // Left icons
+        false,
+        false, // Right icons
+        false,
+        false
+      );
     } else {
       navigationIcons.add(
-        true, true, false, // Left icons
-        false, false,      // Right icons
-        'customMenu', false);
+        true,
+        true,
+        false, // Left icons
+        false,
+        false, // Right icons
+        'customMenu',
+        false
+      );
     }
 
     this.points = {
       x: [90, 204, 318, 432, 546, 660],
-      y: [486, 422, 358, 294, 230, 166]
+      y: [486, 422, 358, 294, 230, 166],
     };
     const rocks = {
       x: [156, 275, 276, 441, 452, 590, 712],
       y: [309, 543, 259, 156, 419, 136, 316],
-      type: [1, 1, 2, 1, 2, 2, 2]
+      type: [1, 1, 2, 1, 2, 2, 2],
     };
     const trees = {
       x: [105, 214, 354, 364, 570, 600, 740, 779],
       y: [341, 219, 180, 520, 550, 392, 488, 286],
-      type: [2, 4, 3, 4, 1, 2, 4, 4]
+      type: [2, 4, 3, 4, 1, 2, 4, 4],
     };
     const offsetH = gameFrame().y;
     const offsetW = gameFrame().x * 2.5;
-    for (let i = 0, cur = this.points; i < cur.x.length; i++) { cur.x[i] += offsetW; cur.y[i] += offsetH; }
-    for (let i = 0, cur = rocks; i < cur.x.length; i++) { cur.x[i] += offsetW; cur.y[i] += offsetH; }
-    for (let i = 0, cur = trees; i < cur.x.length; i++) { cur.x[i] += offsetW; cur.y[i] += offsetH; }
-    
+    for (let i = 0, cur = this.points; i < cur.x.length; i++) {
+      cur.x[i] += offsetW;
+      cur.y[i] += offsetH;
+    }
+    for (let i = 0, cur = rocks; i < cur.x.length; i++) {
+      cur.x[i] += offsetW;
+      cur.y[i] += offsetH;
+    }
+    for (let i = 0, cur = trees; i < cur.x.length; i++) {
+      cur.x[i] += offsetW;
+      cur.y[i] += offsetH;
+    }
+
     // Map
     game.add.image(offsetW, offsetH + 40, 'bgmap');
 
     // Progress bar
     const percentText = completedLevels * 25;
 
-    if (completedLevels >= 4) game.add.geom.rect(context.canvas.width - 240, 10, 4 * 37.5, 35, undefined, 0, colors.intenseGreen, 0.5);
-    else game.add.geom.rect(context.canvas.width - 240, 10, completedLevels * 37.5, 35, undefined, 0, colors.yellow, 0.9);
-
-    game.add.geom.rect(context.canvas.width - 240 + 1, 11, 149, 34, colors.blue, 3, undefined, 1); // Box
-    game.add.text(context.canvas.width - 240 + 160, 38, percentText + '%', textStyles.h2_blue).align = 'left';
-    game.add.text(context.canvas.width - 240 - 10, 38, game.lang.difficulty + ' ' + gameDifficulty, textStyles.h2_blue).align = 'right';
+    if (completedLevels >= 4)
+      game.add.geom.rect(
+        context.canvas.width - 240,
+        10,
+        4 * 37.5,
+        35,
+        undefined,
+        0,
+        colors.greenNeon,
+        0.5
+      );
+    else
+      game.add.geom.rect(
+        context.canvas.width - 240,
+        10,
+        completedLevels * 37.5,
+        35,
+        undefined,
+        0,
+        colors.yellow,
+        0.9
+      );
+
+    game.add.geom.rect(
+      context.canvas.width - 240 + 1,
+      11,
+      149,
+      34,
+      colors.blue,
+      3,
+      undefined,
+      1
+    ); // Box
+    game.add.text(
+      context.canvas.width - 240 + 160,
+      38,
+      percentText + '%',
+      textStyles.h2_blueDark
+    ).align = 'left';
+    game.add.text(
+      context.canvas.width - 240 - 10,
+      38,
+      game.lang.difficulty + ' ' + gameDifficulty,
+      textStyles.h2_blueDark
+    ).align = 'right';
 
     // Map positions
     if (gameType == 'squareOne') {
       // Garage
-      game.add.image(this.points.x[0], this.points.y[0], 'garage', 0.4).anchor(0.5, 1);
+      game.add
+        .image(this.points.x[0], this.points.y[0], 'garage', 0.4)
+        .anchor(0.5, 1);
       // Farm
-      game.add.image(this.points.x[5], this.points.y[5], 'farm', 0.6).anchor(0.1, 0.7);
+      game.add
+        .image(this.points.x[5], this.points.y[5], 'farm', 0.6)
+        .anchor(0.1, 0.7);
     } else {
       // House
-      game.add.image(this.points.x[0], this.points.y[0], 'house', 0.7).anchor(0.7, 0.8);
+      game.add
+        .image(this.points.x[0], this.points.y[0], 'house', 0.7)
+        .anchor(0.7, 0.8);
       // School
-      game.add.image(this.points.x[5], this.points.y[5], 'school', 0.35).anchor(0.2, 0.7);
+      game.add
+        .image(this.points.x[5], this.points.y[5], 'school', 0.35)
+        .anchor(0.2, 0.7);
     }
 
     // Rocks and bushes
@@ -88,41 +161,67 @@ const mapState = {
 
     // Trees
     for (let i in trees.type) {
-      game.add.image(trees.x[i], trees.y[i], 'tree' + trees.type[i], 0.6).anchor(0.5, 0.95);
+      game.add
+        .image(trees.x[i], trees.y[i], 'tree' + trees.type[i], 0.6)
+        .anchor(0.5, 0.95);
     }
 
     // Map positions
     for (let i = 1; i < this.points.x.length - 1; i++) {
-
-      const aux = (i < mapPosition || (mapMove && i == mapPosition)) ? 'place_on' : 'place_off';
+      const aux =
+        i < mapPosition || (mapMove && i == mapPosition)
+          ? 'place_on'
+          : 'place_off';
 
       // Map road positions - game levels
-      game.add.image(this.points.x[i], this.points.y[i], aux, 0.3).anchor(0.5, 0.5);
+      game.add
+        .image(this.points.x[i], this.points.y[i], aux, 0.3)
+        .anchor(0.5, 0.5);
 
       // Map road signs - game level number
-      game.add.image(this.points.x[i] - 20, this.points.y[i] - 60, 'sign', 0.4).anchor(0.5, 1);
-      game.add.text(this.points.x[i] - 20, this.points.y[i] - 79, i, textStyles.h2_white);
-
+      game.add
+        .image(this.points.x[i] - 20, this.points.y[i] - 60, 'sign', 0.4)
+        .anchor(0.5, 1);
+      game.add.text(
+        this.points.x[i] - 20,
+        this.points.y[i] - 79,
+        i,
+        textStyles.h2_white
+      );
     }
 
-    // Game Character 
+    // Game Character
     if (gameType == 'squareOne') {
-
       if (gameOperation == 'Plus') {
-        this.character = game.add.sprite(this.points.x[mapPosition], this.points.y[mapPosition], 'tractor', 0, 0.5);
+        this.character = game.add.sprite(
+          this.points.x[mapPosition],
+          this.points.y[mapPosition],
+          'tractor',
+          0,
+          0.5
+        );
         this.character.animation = ['green_tractor', [0, 1, 2, 3, 4], 3];
       } else {
-        this.character = game.add.sprite(this.points.x[mapPosition], this.points.y[mapPosition], 'tractor', 10, 0.5);
+        this.character = game.add.sprite(
+          this.points.x[mapPosition],
+          this.points.y[mapPosition],
+          'tractor',
+          10,
+          0.5
+        );
         this.character.animation = ['red_tractor', [10, 11, 12, 13, 14], 3];
       }
 
       this.character.rotate = -30; // 25 anticlock
-
     } else {
-
-      this.character = game.add.sprite(this.points.x[mapPosition], this.points.y[mapPosition], 'kid_run', 0, 0.4);
+      this.character = game.add.sprite(
+        this.points.x[mapPosition],
+        this.points.y[mapPosition],
+        'kid_run',
+        0,
+        0.4
+      );
       this.character.animation = ['kid', [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 3];
-
     }
 
     this.character.anchor(0.5, 1);
@@ -137,27 +236,28 @@ const mapState = {
     const yB = this.points.y[mapPosition + 1];
     self.speedX = (xB - xA) / speed;
     self.speedY = (yA - yB) / speed;
-    
+
     game.event.add('click', this.onInputDown);
     game.event.add('mousemove', this.onInputOver);
-
   },
 
   /**
    * Game loop
    */
   update: function () {
-
     let endUpdate = false;
 
     self.count++;
 
-    if (self.count > 60) { // Wait 1 second before moving or staring a game
+    if (self.count > 60) {
+      // Wait 1 second before moving or staring a game
 
-      if (mapMove) { // Move character on screen for 1 second
+      if (mapMove) {
+        // Move character on screen for 1 second
         self.character.x += self.speedX;
         self.character.y -= self.speedY;
-        if (Math.ceil(self.character.x) >= self.points.x[mapPosition + 1]) { // Reached next map position
+        if (Math.ceil(self.character.x) >= self.points.x[mapPosition + 1]) {
+          // Reached next map position
           mapMove = false;
           mapPosition++; // Set new next position
         }
@@ -166,8 +266,6 @@ const mapState = {
       if (!mapMove) {
         endUpdate = true;
       }
-
-
     }
 
     game.render.all();
@@ -176,22 +274,19 @@ const mapState = {
       game.animation.stop(self.character.animation[0]);
       self.loadGame();
     }
-
   },
 
   /**
    * Calls game state
    */
   loadGame: function () {
-
     if (mapPosition <= 4) game.state.start('' + gameType);
     else game.state.start('end');
-
   },
 
   /**
    * Called by mouse click event
-   * 
+   *
    * @param {object} mouseEvent contains the mouse click coordinates
    */
   onInputDown: function (mouseEvent) {
@@ -202,33 +297,39 @@ const mapState = {
 
   /**
    * Called by mouse move event
-   * 
+   *
    * @param {object} mouseEvent contains the mouse move coordinates
    */
   onInputOver: function (mouseEvent) {
     const x = game.math.getMouse(mouseEvent).x;
     const y = game.math.getMouse(mouseEvent).y;
     navigationIcons.onInputOver(x, y);
-  }
-
+  },
 };
 
 /** [ENDING STATE] Ending screen shown when the player has completed all 4 levels and therefore completed the game.
- * 
+ *
  * @namespace
  */
 const endState = {
-
   /**
    * Main code
    */
   create: function () {
-
     self.preAnimate = false;
     self.animate = true;
 
     // Background color
-    game.add.geom.rect(0, 0, context.canvas.width, context.canvas.height, undefined, 0, colors.blueBckg, 1);
+    game.add.geom.rect(
+      0,
+      0,
+      context.canvas.width,
+      context.canvas.height,
+      undefined,
+      0,
+      colors.blueBg,
+      1
+    );
 
     // Background
     game.add.image(0, 0, 'bgimage', 2.2);
@@ -239,21 +340,35 @@ const endState = {
     game.add.image(300, 85, 'cloud', 0.8);
 
     // Floor
-    for (let i = 0; i < context.canvas.width / 100; i++) { game.add.image(i * 100, context.canvas.height - 100, 'floor'); }
+    for (let i = 0; i < context.canvas.width / 100; i++) {
+      game.add.image(i * 100, context.canvas.height - 100, 'floor');
+    }
 
     // Progress bar
-    game.add.geom.rect(660, 10, 4 * 37.5, 35, undefined, 0, colors.intenseGreen, 0.5); // Progress
+    game.add.geom.rect(
+      660,
+      10,
+      4 * 37.5,
+      35,
+      undefined,
+      0,
+      colors.greenNeon,
+      0.5
+    ); // Progress
     game.add.geom.rect(661, 11, 149, 34, colors.blue, 3, undefined, 1); // Box
-    game.add.text(820, 38, '100%', textStyles.h2_blue).align = 'left';
-    game.add.text(650, 38, game.lang.difficulty + ' ' + gameDifficulty, textStyles.h2_blue).align = 'right';
+    game.add.text(820, 38, '100%', textStyles.h2_blueDark).align = 'left';
+    game.add.text(
+      650,
+      38,
+      game.lang.difficulty + ' ' + gameDifficulty,
+      textStyles.h2_blueDark
+    ).align = 'right';
 
     game.add.image(360, 545, 'tree4', 0.7).anchor(0, 1);
 
     // Level character
     switch (gameType) {
-
       case 'circleOne':
-
         this.preAnimate = true;
         this.animate = false;
 
@@ -263,7 +378,11 @@ const endState = {
         // Kid
         this.character = game.add.sprite(0, -152, 'kid_run', 0, 0.7);
         this.character.anchor(0.5, 0.5);
-        this.character.animation = ['move', [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11], 3];
+        this.character.animation = [
+          'move',
+          [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11],
+          3,
+        ];
 
         // Balloon
         this.balloon = game.add.image(0, -260, 'balloon');
@@ -275,19 +394,21 @@ const endState = {
         break;
 
       case 'squareTwo':
-
         // School
         game.add.image(600, 222, 'school', 0.7);
 
         // Kid
         this.character = game.add.sprite(0, 460, 'kid_run', 6, 0.7);
         this.character.anchor(0.5, 0.5);
-        this.character.animation = ['move', [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11], 3];
+        this.character.animation = [
+          'move',
+          [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11],
+          3,
+        ];
 
         break;
 
       case 'squareOne':
-
         // Farm
         game.add.image(650, 260, 'farm', 1.1);
 
@@ -302,25 +423,20 @@ const endState = {
         }
 
         break;
-
     }
 
     if (this.animate) game.animation.play(this.character.animation[0]);
 
     game.add.image(30, 585, 'tree4', 0.85).anchor(0, 1);
-
   },
 
   /**
    * Game loop
    */
   update: function () {
-
     // Balloon falling
     if (self.preAnimate) {
-
       if (self.character.y < 460) {
-
         self.balloon.y += 2;
         self.basket.y += 2;
         self.character.y += 2;
@@ -328,26 +444,18 @@ const endState = {
         self.balloon.x++;
         self.basket.x++;
         self.character.x++;
-
       } else {
-
         self.preAnimate = false;
         self.animate = true;
         game.animation.play(self.character.animation[0]);
-
       }
-
     }
 
     // Character running
     if (self.animate) {
-
       if (self.character.x <= 700) {
-
         self.character.x += 2;
-
       } else {
-
         self.animate = false;
         game.animation.stop(self.character.animation[0]);
 
@@ -359,13 +467,9 @@ const endState = {
           // FOR MOODLE
           parent.location.reload(true);
         }
-
       }
-
     }
 
     game.render.all();
-
-  }
-
-};
+  },
+};

+ 124 - 59
js/menu.js

@@ -3,58 +3,86 @@
  ******************************/
 
 /** [MAIN MENU STATE] Screen where the user can select a game.
- * 
+ *
  * @namespace
  */
 const menuState = {
-  
   /**
    * Main code
    */
   create: function () {
-
     // FOR MOODLE
-    if (moodle && iLMparameters.iLM_PARAM_SendAnswer == 'false') { // Student role
+    if (moodle && iLMparameters.iLM_PARAM_SendAnswer == 'false') {
+      // Student role
 
       playerName = game.lang.student; // TODO pegar o nome do aluno no bd do moodle
       getiLMContent();
-
     } else {
-
       // FOR MOODLE
-      if (moodle && iLMparameters.iLM_PARAM_SendAnswer == 'true') playerName = game.lang.professor;
+      if (moodle && iLMparameters.iLM_PARAM_SendAnswer == 'true')
+        playerName = game.lang.professor;
 
       // Background color
-      game.add.geom.rect(0, 0, context.canvas.width, context.canvas.height, undefined, 0, colors.blueBckg, 1);
+      game.add.geom.rect(
+        0,
+        0,
+        context.canvas.width,
+        context.canvas.height,
+        undefined,
+        0,
+        colors.blueBg,
+        1
+      );
       // Floor
-      for (let i = 0; i < context.canvas.width / 100; i++) { game.add.image(i * 100, context.canvas.height - 100, 'floor'); }
+      for (let i = 0; i < context.canvas.width / 100; i++) {
+        game.add.image(i * 100, context.canvas.height - 100, 'floor');
+      }
 
       // Overtitle: Welcome, <player name>!
-      game.add.text(context.canvas.width / 2, 40, game.lang.welcome + ', ' + playerName + '!', textStyles.h4_brown);
+      game.add.text(
+        context.canvas.width / 2,
+        40,
+        game.lang.welcome + ', ' + playerName + '!',
+        textStyles.h4_brown
+      );
       // Title : Select a game
-      game.add.text(context.canvas.width / 2, 80, game.lang.menu_title, textStyles.h1_green);
-      // Subtitle : <game mode> 
-      this.lbl_game = game.add.text(context.canvas.width / 2, 110, '', textStyles.h2_blue_2);
+      game.add.text(
+        context.canvas.width / 2,
+        80,
+        game.lang.menu_title,
+        textStyles.h1_green
+      );
+      // Subtitle : <game mode>
+      this.lbl_game = game.add.text(
+        context.canvas.width / 2,
+        110,
+        '',
+        textStyles.h2_blue
+      );
 
       // Loads navigation icons
-      navigationIcons.add(
-        false, false, false,
-        true, true,
-        false, false);
+      navigationIcons.add(false, false, false, true, true, false, false);
 
       // INFO ICONS
 
       this.menuIcons = [];
       let infoIcon;
 
-      // --------------------------- GAME ICONS 
+      // --------------------------- GAME ICONS
 
-      const offset = game.math.getOffset(context.canvas.width, info.gameType.length);
+      const offset = game.math.getOffset(
+        context.canvas.width,
+        info.gameType.length
+      );
 
       for (let i = 0, x = offset; i < info.gameType.length; i++, x += offset) {
-
-        const icon = game.add.image(x, context.canvas.height / 2 - 70, info.gameTypeUrl[i], 1);
-        icon.anchor(0.5, 0.5); 
+        const icon = game.add.image(
+          x,
+          context.canvas.height / 2 - 70,
+          info.gameTypeUrl[i],
+          1
+        );
+        icon.anchor(0.5, 0.5);
 
         icon.gameShape = info.gameShape[i];
         icon.gameType = info.gameType[i];
@@ -63,12 +91,17 @@ const menuState = {
         this.menuIcons.push(icon);
 
         // "more information" button
-        infoIcon = game.add.image(x + 70, context.canvas.height / 2 - 70 - 80, 'info', 0.6, 0.4);
+        infoIcon = game.add.image(
+          x + 70,
+          context.canvas.height / 2 - 70 - 80,
+          'info',
+          0.6,
+          0.4
+        );
         infoIcon.anchor(0.5, 0.5);
         infoIcon.iconType = 'infoIcon';
         infoIcon.id = icon.gameType;
         this.menuIcons.push(infoIcon);
-
       }
 
       // --------------------------- INFO BOX
@@ -78,40 +111,62 @@ const menuState = {
       // When the user clicks on the 'x', close the modal
       document.getElementsByClassName('close')[0].onclick = function () {
         self.infoBox.style.display = 'none';
-      }
+      };
 
       // When the user clicks anywhere outside of the modal, close it
       window.onclick = function (event) {
         if (event.target == self.infoBox) {
           self.infoBox.style.display = 'none';
         }
-      }
+      };
 
       this.infoBoxContent = {
         squareOne: {
-          title: '<strong>' + game.lang.game + ':</strong> ' + game.lang.square + ' I',
+          title:
+            '<strong>' +
+            game.lang.game +
+            ':</strong> ' +
+            game.lang.square +
+            ' I',
           body: '<ul>' + game.lang.infoBox_squareOne + '</ul>',
-          img: '<img class="mx-auto" width=60% src="' + game.image['s1-A'].src + '">'
+          img:
+            '<img class="mx-auto" width=60% src="' +
+            game.image['s1-A'].src +
+            '">',
         },
         circleOne: {
-          title: '<strong>' + game.lang.game + ':</strong> ' + game.lang.circle + ' I',
+          title:
+            '<strong>' +
+            game.lang.game +
+            ':</strong> ' +
+            game.lang.circle +
+            ' I',
           body: '<ul>' + game.lang.infoBox_circleOne + '</ul>',
-          img: '<img class="mx-auto" width=80% src="' + game.image['c1-A'].src + '">',
+          img:
+            '<img class="mx-auto" width=80% src="' +
+            game.image['c1-A'].src +
+            '">',
         },
         squareTwo: {
-          title: '<strong>' + game.lang.game + ':</strong> ' + game.lang.square + ' II',
+          title:
+            '<strong>' +
+            game.lang.game +
+            ':</strong> ' +
+            game.lang.square +
+            ' II',
           body: '<ul>' + game.lang.infoBox_squareTwo + '</ul>',
-          img: '<img class="mx-auto" width=80% src="' + game.image['s2'].src + '">',
-        }
+          img:
+            '<img class="mx-auto" width=80% src="' +
+            game.image['s2'].src +
+            '">',
+        },
       };
 
       // ------------- EVENTS
 
       game.event.add('click', this.onInputDown);
       game.event.add('mousemove', this.onInputOver);
-
     }
-
   },
 
   /**
@@ -120,46 +175,50 @@ const menuState = {
   showInfoBox: function (icon) {
     self.infoBox.style.display = 'block';
 
-    let msg = '<h3>' + self.infoBoxContent[icon.id].title + '</h3>'
-      + '<p>' + self.infoBoxContent[icon.id].body + '</p>'
-      + self.infoBoxContent[icon.id].img;
+    let msg =
+      '<h3>' +
+      self.infoBoxContent[icon.id].title +
+      '</h3>' +
+      '<p>' +
+      self.infoBoxContent[icon.id].body +
+      '</p>' +
+      self.infoBoxContent[icon.id].img;
 
     document.getElementById('infobox-content').innerHTML = msg;
   },
 
   /**
    * Saves info from selected game and goes to next state
-   * 
+   *
    * @param {object} icon clicked icon
    */
   load: function (icon) {
-
     if (audioStatus) game.audio.popSound.play();
 
     switch (icon.iconType) {
-      case 'infoIcon': self.showInfoBox(icon); break;
+      case 'infoIcon':
+        self.showInfoBox(icon);
+        break;
       case 'game':
         gameShape = icon.gameShape;
         gameType = icon.gameType;
-        if (!info.gameType.includes(gameType)) console.error('Game error: the name of the game is not valid.');
+        if (!info.gameType.includes(gameType))
+          console.error('Game error: the name of the game is not valid.');
         self.menuIcons = self.lbl_game.name;
         game.state.start('customMenu');
         break;
     }
-
   },
 
   /**
    * Display the name of the game on screen
-   * 
+   *
    * @param {object} icon icon for the game
    */
   showTitle: function (icon) {
-
-    const number = (icon.gameType.slice(-3) == 'One') ? 'I' : 'II';
+    const number = icon.gameType.slice(-3) == 'One' ? 'I' : 'II';
 
     self.lbl_game.name = game.lang[icon.gameShape] + ' ' + number;
-
   },
 
   /**
@@ -171,7 +230,7 @@ const menuState = {
 
   /**
    * Called by mouse click event
-   * 
+   *
    * @param {object} mouseEvent contains the mouse click coordinates
    */
   onInputDown: function (mouseEvent) {
@@ -196,7 +255,7 @@ const menuState = {
 
   /**
    * Called by mouse move event
-   * 
+   *
    * @param {object} mouseEvent contains the mouse move coordinates
    */
   onInputOver: function (mouseEvent) {
@@ -213,21 +272,28 @@ const menuState = {
     }
 
     // Update gui
-    if (overIcon) { // If pointer is over icon
+    if (overIcon) {
+      // If pointer is over icon
       document.body.style.cursor = 'pointer';
-      if (self.menuIcons[overIcon].iconType == 'game') self.showTitle(self.menuIcons[overIcon]);
-      self.menuIcons.forEach(cur => {
-        if (cur.iconType == self.menuIcons[overIcon].iconType) { // If its in the same icon category
-          if (cur == self.menuIcons[overIcon]) { // If its the icon the pointer is over 
+      if (self.menuIcons[overIcon].iconType == 'game')
+        self.showTitle(self.menuIcons[overIcon]);
+      self.menuIcons.forEach((cur) => {
+        if (cur.iconType == self.menuIcons[overIcon].iconType) {
+          // If its in the same icon category
+          if (cur == self.menuIcons[overIcon]) {
+            // If its the icon the pointer is over
             cur.scale = cur.originalScale * 1.1;
           } else {
             cur.scale = cur.originalScale;
           }
         }
       });
-    } else { // If pointer is not over icon
+    } else {
+      // If pointer is not over icon
       self.clearTitle();
-      self.menuIcons.forEach(cur => { cur.scale = cur.originalScale; });
+      self.menuIcons.forEach((cur) => {
+        cur.scale = cur.originalScale;
+      });
       document.body.style.cursor = 'auto';
     }
 
@@ -235,6 +301,5 @@ const menuState = {
     navigationIcons.onInputOver(x, y);
 
     game.render.all();
-  }
-
-};
+  },
+};

+ 120 - 60
js/preMenu.js

@@ -3,11 +3,10 @@
  ******************************/
 
 /** [BOOT STATE] First state called. Loads media. <br>
- * 
+ *
  * @namespace
  */
 const bootState = {
-
   /**
    * Preloads media for current state
    */
@@ -17,12 +16,23 @@ const bootState = {
       loadLangState.firstTime = false;
       const moodleLang = iLMparameters.lang;
       switch (moodleLang) {
-        case 'en': langString = 'en_US'; break;
-        case 'pt': langString = 'pt_BR'; break;
-        case 'fr': langString = 'fr_FR'; break;
-        case 'es': langString = 'es_PE'; break;
-        case 'it': langString = 'it_IT'; break;
-        default: langString = 'en_US';
+        case 'en':
+          langString = 'en_US';
+          break;
+        case 'pt':
+          langString = 'pt_BR';
+          break;
+        case 'fr':
+          langString = 'fr_FR';
+          break;
+        case 'es':
+          langString = 'es_PE';
+          break;
+        case 'it':
+          langString = 'it_IT';
+          break;
+        default:
+          langString = 'en_US';
       }
       game.load.lang('assets/lang/' + langString);
     }
@@ -36,7 +46,6 @@ const bootState = {
    * Main code
    */
   create: function () {
-
     // Calls first screen seen by the player
 
     // FOR MOODLE
@@ -45,43 +54,66 @@ const bootState = {
     } else {
       game.state.start('lang');
     }
-  }
-
+  },
 };
 
 /** [LANGUAGE STATE] Screen that asks the user to select the language for the game text.
- * 
+ *
  * @namespace
  */
 const langState = {
-
   /**
    * Main code
    */
   create: function () {
     // Background color
-    game.add.geom.rect(0, 0, context.canvas.width, context.canvas.height, colors.white, 0, colors.blueBckg, 1);
+    game.add.geom.rect(
+      0,
+      0,
+      context.canvas.width,
+      context.canvas.height,
+      colors.white,
+      0,
+      colors.blueBg,
+      1
+    );
+
+    if (debugMode) debugGrid();
 
     // Parameters for the elements on the screen
     this.listOfFlags = [];
 
     this.langs = {
-      text: ['FRAÇÕES  ', 'FRAZIONI  ', 'FRACTIONS  ', 'FRACCIONES  ', 'FRACTIONS  '], // Language names
+      text: [
+        'FRAÇÕES  ',
+        'FRAZIONI  ',
+        'FRACTIONS  ',
+        'FRACCIONES  ',
+        'FRACTIONS  ',
+      ], // Language names
       flag: ['flag_BR', 'flag_IT', 'flag_US', 'flag_PE', 'flag_FR'], // Icon names
       lang: ['pt_BR', 'it_IT', 'en_US', 'es_PE', 'fr_FR'], // Parameters sent for language object
-      x: [-220, -220, -220, 200, 200],
-      y: [-180, 0, 180, -100, 100]
+      x: [-280, -280, -280, 140, 140],
+      y: [-220, 0, 220, -120, 120],
     };
 
-    // Create elements on screen  
+    // Create elements on screen
     for (let i in this.langs.flag) {
       // Add text for language names
-      game.add.text(context.canvas.width / 2 + this.langs.x[i], context.canvas.height / 2 + this.langs.y[i], this.langs.text[i], textStyles.h2_green).align = 'right';
+      game.add.text(
+        context.canvas.width / 2 + this.langs.x[i],
+        context.canvas.height / 2 + this.langs.y[i],
+        this.langs.text[i],
+        textStyles.h2_green
+      ).align = 'right';
 
       // Add icons for flags
-      const flag = game.add.image(context.canvas.width / 2 + this.langs.x[i] + 100, context.canvas.height / 2 + this.langs.y[i], this.langs.flag[i]);
+      const flag = game.add.image(
+        context.canvas.width / 2 + this.langs.x[i] + 100,
+        context.canvas.height / 2 + this.langs.y[i],
+        this.langs.flag[i]
+      );
       flag.anchor(0.5, 0.5);
-
       this.listOfFlags.push(flag);
     }
 
@@ -91,7 +123,7 @@ const langState = {
 
   /**
    * Calls state that loads selected language
-   * 
+   *
    * @param {string} selectedLang language selected by player
    */
   setLang: function (selectedLang) {
@@ -103,15 +135,15 @@ const langState = {
   },
 
   /**
- * Called by mouse click event
- * 
- * @param {object} mouseEvent contains the mouse click coordinates
- */
+   * Called by mouse click event
+   *
+   * @param {object} mouseEvent contains the mouse click coordinates
+   */
   onInputDown: function (mouseEvent) {
     const x = game.math.getMouse(mouseEvent).x;
     const y = game.math.getMouse(mouseEvent).y;
-   
-    self.listOfFlags.forEach(cur => {
+
+    self.listOfFlags.forEach((cur) => {
       if (game.math.isOverIcon(x, y, cur)) {
         for (let i in self.langs.flag) {
           if (self.langs.flag[i] == cur.name) {
@@ -125,15 +157,15 @@ const langState = {
 
   /**
    * Called by mouse move event
-   * 
+   *
    * @param {object} mouseEvent contains the mouse move coordinates
    */
   onInputOver: function (mouseEvent) {
     const x = game.math.getMouse(mouseEvent).x;
     const y = game.math.getMouse(mouseEvent).y;
     let flag = false;
-    
-    self.listOfFlags.forEach(cur => {
+
+    self.listOfFlags.forEach((cur) => {
       if (game.math.isOverIcon(x, y, cur)) {
         flag = true;
         cur.scale = cur.scale = 1.05;
@@ -146,16 +178,14 @@ const langState = {
     else document.body.style.cursor = 'auto';
 
     game.render.all();
-  }
-
+  },
 };
 
 /** [LOADING LANGUAGE STATE] Loads the selected language.
- * 
+ *
  *  @namespace
  */
 const loadLangState = {
-
   /**
    * Preloads media for current state
    */
@@ -175,58 +205,89 @@ const loadLangState = {
       this.firstTime = false;
       game.state.start('name'); // First time opening ifractions ('language' >> 'name' >> 'menu')
     } else {
-      game.state.start('menu'); // If changing language during the game ('language' >> >> 'menu')         
+      game.state.start('menu'); // If changing language during the game ('language' >> >> 'menu')
     }
-  }
-
+  },
 };
 
 /** [NAME STATE] Screen that asks for the user's name.
- * 
+ *
  * @namespace
  */
 const nameState = {
-
   /**
    * Main code
    */
   create: function () {
-
     // Background color
-    game.add.geom.rect(0, 0, context.canvas.width, context.canvas.height, colors.white, 0, colors.blueBckg, 1);
+    game.add.geom.rect(
+      0,
+      0,
+      context.canvas.width,
+      context.canvas.height,
+      colors.white,
+      0,
+      colors.blueBg,
+      1
+    );
 
     // Set title and warning text
 
-    game.add.text(context.canvas.width / 2, context.canvas.height / 2 - 100, game.lang.insert_name, textStyles.h1_green);
+    game.add.text(
+      context.canvas.width / 2,
+      context.canvas.height / 2 - 100,
+      game.lang.insert_name,
+      textStyles.h1_green
+    );
 
-    this.warningEmptyName = game.add.text(context.canvas.width / 2, context.canvas.height / 2 - 70, '', textStyles.h4_brown);
+    this.warningEmptyName = game.add.text(
+      context.canvas.width / 2,
+      context.canvas.height / 2 - 70,
+      '',
+      textStyles.h4_brown
+    );
 
     // Set 'ok' button that gets player's information
-    this.okBtn = game.add.geom.rect(context.canvas.width / 2 - 84, context.canvas.height / 2 + 70, 168, 60, undefined, 0, colors.gray, 0.6);
+    this.okBtn = game.add.geom.rect(
+      context.canvas.width / 2 - 84,
+      context.canvas.height / 2 + 70,
+      168,
+      60,
+      undefined,
+      0,
+      colors.gray,
+      0.6
+    );
 
     // Set button Text
-    game.add.text(context.canvas.width / 2 + 1, context.canvas.height / 2 + 112, game.lang.ready, textStyles.h1_white);
+    game.add.text(
+      context.canvas.width / 2 + 1,
+      context.canvas.height / 2 + 112,
+      game.lang.ready,
+      textStyles.h1_white
+    );
 
     // Makes text field visible
     document.getElementById('textbox').style.visibility = 'visible';
 
     // Does the same as the button click when the player presses 'enter'
-    document.getElementById('textbox-content').addEventListener('keypress', function (e) {
-      const keycode = e.key || e.code;
-      if (keycode == 'Enter') {
-        if (self.checkEmptyName()) self.saveName();
-        game.render.all(); // Can show empty name
-      }
-    });
+    document
+      .getElementById('textbox-content')
+      .addEventListener('keypress', function (e) {
+        const keycode = e.key || e.code;
+        if (keycode == 'Enter') {
+          if (self.checkEmptyName()) self.saveName();
+          game.render.all(); // Can show empty name
+        }
+      });
 
     game.event.add('click', this.onInputDown);
     game.event.add('mousemove', this.onInputOver);
-
   },
 
   /**
    * Checks if player entered name in text box
-   * 
+   *
    * @returns {boolean} false is textBox is emptys
    */
   checkEmptyName: function () {
@@ -259,7 +320,7 @@ const nameState = {
 
   /**
    * Called by mouse click event
-   * 
+   *
    * @param {object} mouseEvent contains the mouse click coordinates
    */
   onInputDown: function (mouseEvent) {
@@ -277,7 +338,7 @@ const nameState = {
 
   /**
    * Called by mouse move event
-   * 
+   *
    * @param {object} mouseEvent contains the mouse move coordinates
    */
   onInputOver: function (mouseEvent) {
@@ -294,6 +355,5 @@ const nameState = {
     }
 
     game.render.all();
-  }
-
-};
+  },
+};

+ 98 - 27
js/studentReport.js

@@ -1,67 +1,138 @@
 /************************************************************************************
- * This code is used EXCLUSIVELY when iFractions is runnign inside Moodle via iAssign 
+ * This code is used EXCLUSIVELY when iFractions is runnign inside Moodle via iAssign
  * as an iLM (interactive learning module) and the global variable moodle=true.
- * 
- * This file holds game states. 
+ *
+ * This file holds game states.
  ************************************************************************************/
 
-/** 
+/**
  * [STUDENT REPORT STATE] Screen that shows the stats of a previously played game (exclusive to moodle).
- * 
+ *
  * FOR MOODLE
- * 
+ *
  * @namespace
  */
 const studentReport = {
-
   /** FOR MOODLE
    * Main code
    */
   create: function () {
-
     const offsetW = context.canvas.width / 4;
     let x = offsetW / 2;
     let y = context.canvas.height / 2 - 50;
 
     // Background
-    game.add.geom.rect(0, 0, context.canvas.width, context.canvas.height, undefined, 0, colors.blueBckg, 1);
+    game.add.geom.rect(
+      0,
+      0,
+      context.canvas.width,
+      context.canvas.height,
+      undefined,
+      0,
+      colors.blueBg,
+      1
+    );
     game.add.image(640, 100, 'cloud');
     game.add.image(1280, 80, 'cloud');
     game.add.image(300, 85, 'cloud', 0.8);
-    for (let i = 0; i < context.canvas.width / 100; i++) { game.add.image(i * 100, context.canvas.height - 100, 'floor'); }
+    for (let i = 0; i < context.canvas.width / 100; i++) {
+      game.add.image(i * 100, context.canvas.height - 100, 'floor');
+    }
 
     // Title
-    game.add.text(context.canvas.width / 2, 80, game.lang.results, textStyles.h1_green);
+    game.add.text(
+      context.canvas.width / 2,
+      80,
+      game.lang.results,
+      textStyles.h1_green
+    );
     game.add.image(x - 40, y - 70, info.all[gameType].gameTypeUrl, 0.8);
 
     // Game info
-    text = game.lang[gameShape].charAt(0).toUpperCase() + game.lang[gameShape].slice(1);
-    text = game.lang.game + ': ' + text + ((gameType.slice(-3) == 'One') ? ' I' : ' II');
+    text =
+      game.lang[gameShape].charAt(0).toUpperCase() +
+      game.lang[gameShape].slice(1);
+    text =
+      game.lang.game +
+      ': ' +
+      text +
+      (gameType.slice(-3) == 'One' ? ' I' : ' II');
     game.add.text(190, y - 50, text, textStyles.h4_brown).align = 'left';
-    game.add.text(190, y - 25, game.lang.game_mode + ': ' + gameMode, textStyles.h4_brown).align = 'left';
-    game.add.text(190, y, game.lang.operation + ': ' + gameOperation, textStyles.h4_brown).align = 'left';
-    game.add.text(190, y + 25, game.lang.difficulty + ': ' + gameDifficulty, textStyles.h4_brown).align = 'left';
+    game.add.text(
+      190,
+      y - 25,
+      game.lang.game_mode + ': ' + gameMode,
+      textStyles.h4_brown
+    ).align = 'left';
+    game.add.text(
+      190,
+      y,
+      game.lang.operation + ': ' + gameOperation,
+      textStyles.h4_brown
+    ).align = 'left';
+    game.add.text(
+      190,
+      y + 25,
+      game.lang.difficulty + ': ' + gameDifficulty,
+      textStyles.h4_brown
+    ).align = 'left';
 
     // Student info
     y = context.canvas.height - 200;
     for (let i = 0; i < 4; i++, x += offsetW) {
       // If level wasnt completed, show broken sign
       if (moodleVar.hits[i] == 0 && moodleVar.errors[i] == 0) {
-        const sign = game.add.image(x, context.canvas.height - 100, 'broken_sign', 0.7);
+        const sign = game.add.image(
+          x,
+          context.canvas.height - 100,
+          'broken_sign',
+          0.7
+        );
         sign.anchor(0.5, 0.5);
       } else {
         // If level was completed shows sign with level number and student report
-        const sign = game.add.image(x, context.canvas.height - 100, 'sign', 0.7);
+        const sign = game.add.image(
+          x,
+          context.canvas.height - 100,
+          'sign',
+          0.7
+        );
         sign.anchor(0.5, 0.5);
-        game.add.text(x, context.canvas.height - 100, '' + (i + 1), textStyles.h2_white);
+        game.add.text(
+          x,
+          context.canvas.height - 100,
+          '' + (i + 1),
+          textStyles.h2_white
+        );
 
-        game.add.geom.rect(x - 55, y - 40, 5, 135, undefined, 0, colors.blueMenuLine);
-        game.add.text(x - 40, y - 25, game.lang.time + ': ' + game.math.convertTime(moodleVar.time[i]), textStyles.h4_brown).align = 'left';
-        game.add.text(x - 40, y, game.lang.hits + ': ' + moodleVar.hits[i], textStyles.h4_brown).align = 'left';
-        game.add.text(x - 40, y + 25, game.lang.errors + ': ' + moodleVar.errors[i], textStyles.h4_brown).align = 'left';
+        game.add.geom.rect(
+          x - 55,
+          y - 40,
+          5,
+          135,
+          undefined,
+          0,
+          colors.blueMenuLine
+        );
+        game.add.text(
+          x - 40,
+          y - 25,
+          game.lang.time + ': ' + game.math.convertTime(moodleVar.time[i]),
+          textStyles.h4_brown
+        ).align = 'left';
+        game.add.text(
+          x - 40,
+          y,
+          game.lang.hits + ': ' + moodleVar.hits[i],
+          textStyles.h4_brown
+        ).align = 'left';
+        game.add.text(
+          x - 40,
+          y + 25,
+          game.lang.errors + ': ' + moodleVar.errors[i],
+          textStyles.h4_brown
+        ).align = 'left';
       }
     }
-
-  }
-
-};
+  },
+};