Browse Source

Included iHanoi prepared to iAssign

Igor 3 năm trước cách đây
mục cha
commit
58b092e346
62 tập tin đã thay đổi với 945 bổ sung620 xóa
  1. BIN
      ilm/iHanoi/0.1.20200115/ihanoi/assets/acoes.png
  2. BIN
      ilm/iHanoi/0.1.20200115/ihanoi/assets/disk0.png
  3. BIN
      ilm/iHanoi/0.1.20200115/ihanoi/assets/disk1.png
  4. BIN
      ilm/iHanoi/0.1.20200115/ihanoi/assets/disk2.png
  5. BIN
      ilm/iHanoi/0.1.20200115/ihanoi/assets/disk3.png
  6. BIN
      ilm/iHanoi/0.1.20200115/ihanoi/assets/disk4.png
  7. BIN
      ilm/iHanoi/0.1.20200115/ihanoi/assets/disk5.png
  8. BIN
      ilm/iHanoi/0.1.20200115/ihanoi/assets/diskSelection/fiveDisks.png
  9. BIN
      ilm/iHanoi/0.1.20200115/ihanoi/assets/diskSelection/fourDisks.png
  10. BIN
      ilm/iHanoi/0.1.20200115/ihanoi/assets/diskSelection/sixDisks.png
  11. BIN
      ilm/iHanoi/0.1.20200115/ihanoi/assets/diskSelection/threeDisks.png
  12. BIN
      ilm/iHanoi/0.1.20200115/ihanoi/assets/diskSelection/twoDisks.png
  13. BIN
      ilm/iHanoi/0.1.20200115/ihanoi/assets/diskSelector.png
  14. 0 0
      ilm/iHanoi/0.1.20200115/ihanoi/assets/index.html
  15. BIN
      ilm/iHanoi/0.1.20200115/ihanoi/assets/msgBox.png
  16. BIN
      ilm/iHanoi/0.1.20200115/ihanoi/assets/redo.png
  17. BIN
      ilm/iHanoi/0.1.20200115/ihanoi/assets/redo2.png
  18. BIN
      ilm/iHanoi/0.1.20200115/ihanoi/assets/redoDisabled2.png
  19. BIN
      ilm/iHanoi/0.1.20200115/ihanoi/assets/restart.png
  20. BIN
      ilm/iHanoi/0.1.20200115/ihanoi/assets/selectionArea.png
  21. BIN
      ilm/iHanoi/0.1.20200115/ihanoi/assets/sky.png
  22. 0 0
      ilm/iHanoi/0.1.20200115/ihanoi/assets/sounds/index.html
  23. BIN
      ilm/iHanoi/0.1.20200115/ihanoi/assets/sounds/wrongBuzz.mp3
  24. 0 0
      ilm/iHanoi/0.1.20200115/ihanoi/assets/strokedDisks/index.html
  25. BIN
      ilm/iHanoi/0.1.20200115/ihanoi/assets/strokedDisks/stroked0.png
  26. BIN
      ilm/iHanoi/0.1.20200115/ihanoi/assets/strokedDisks/stroked1.png
  27. BIN
      ilm/iHanoi/0.1.20200115/ihanoi/assets/strokedDisks/stroked2.png
  28. BIN
      ilm/iHanoi/0.1.20200115/ihanoi/assets/strokedDisks/stroked3.png
  29. BIN
      ilm/iHanoi/0.1.20200115/ihanoi/assets/strokedDisks/stroked4.png
  30. BIN
      ilm/iHanoi/0.1.20200115/ihanoi/assets/strokedDisks/stroked5.png
  31. BIN
      ilm/iHanoi/0.1.20200115/ihanoi/assets/torre.png
  32. BIN
      ilm/iHanoi/0.1.20200115/ihanoi/assets/undo.png
  33. BIN
      ilm/iHanoi/0.1.20200115/ihanoi/assets/undo2.png
  34. BIN
      ilm/iHanoi/0.1.20200115/ihanoi/assets/undoDisabled2.png
  35. BIN
      ilm/iHanoi/0.1.20200115/ihanoi/assets/wrongMove.png
  36. 0 0
      ilm/iHanoi/0.1.20200115/ihanoi/css/index.html
  37. 0 16
      ilm/iHanoi/0.1.20200115/ihanoi/css/styles.css
  38. 0 14
      ilm/iHanoi/0.1.20200115/ihanoi/ilm-application.xml
  39. 0 24
      ilm/iHanoi/0.1.20200115/ihanoi/index.html
  40. 0 261
      ilm/iHanoi/0.1.20200115/ihanoi/js/iHanoiFunctions.js
  41. 0 0
      ilm/iHanoi/0.1.20200115/ihanoi/js/index.html
  42. 0 106
      ilm/iHanoi/0.1.20200115/ihanoi/js/integration-functions.js
  43. 0 2
      ilm/iHanoi/0.1.20200115/ihanoi/js/jquery-3.3.1.min.js
  44. 0 197
      ilm/iHanoi/0.1.20200115/ihanoi/js/phaserConfig.js
  45. 0 0
      ilm/iHanoi/0.1.20200115/index.html
  46. 58 0
      ilm/iHanoi/1.0.20200803/ihanoi/css/ihanoi_style.css
  47. BIN
      ilm/iHanoi/1.0.20200803/ihanoi/img/disk1.png
  48. BIN
      ilm/iHanoi/1.0.20200803/ihanoi/img/disk2.png
  49. BIN
      ilm/iHanoi/1.0.20200803/ihanoi/img/disk3.png
  50. BIN
      ilm/iHanoi/1.0.20200803/ihanoi/img/disk4.png
  51. BIN
      ilm/iHanoi/1.0.20200803/ihanoi/img/disk5.png
  52. BIN
      ilm/iHanoi/1.0.20200803/ihanoi/img/disk6.png
  53. BIN
      ilm/iHanoi/1.0.20200803/ihanoi/img/fundo1.png
  54. BIN
      ilm/iHanoi/1.0.20200803/ihanoi/img/fundo2.png
  55. BIN
      ilm/iHanoi/1.0.20200803/ihanoi/img/hasteA.png
  56. BIN
      ilm/iHanoi/1.0.20200803/ihanoi/img/hasteB.png
  57. BIN
      ilm/iHanoi/1.0.20200803/ihanoi/img/hasteC.png
  58. BIN
      ilm/iHanoi/1.0.20200803/ihanoi/img/img_fundo_hanoi.png
  59. 56 0
      ilm/iHanoi/1.0.20200803/ihanoi/index.html
  60. 579 0
      ilm/iHanoi/1.0.20200803/ihanoi/js/ihanoi.js
  61. 252 0
      ilm/iHanoi/1.0.20200803/ihanoi/js/integration-functions.js
  62. 0 0
      ilm/iHanoi/1.0.20200803/index.html

BIN
ilm/iHanoi/0.1.20200115/ihanoi/assets/acoes.png


BIN
ilm/iHanoi/0.1.20200115/ihanoi/assets/disk0.png


BIN
ilm/iHanoi/0.1.20200115/ihanoi/assets/disk1.png


BIN
ilm/iHanoi/0.1.20200115/ihanoi/assets/disk2.png


BIN
ilm/iHanoi/0.1.20200115/ihanoi/assets/disk3.png


BIN
ilm/iHanoi/0.1.20200115/ihanoi/assets/disk4.png


BIN
ilm/iHanoi/0.1.20200115/ihanoi/assets/disk5.png


BIN
ilm/iHanoi/0.1.20200115/ihanoi/assets/diskSelection/fiveDisks.png


BIN
ilm/iHanoi/0.1.20200115/ihanoi/assets/diskSelection/fourDisks.png


BIN
ilm/iHanoi/0.1.20200115/ihanoi/assets/diskSelection/sixDisks.png


BIN
ilm/iHanoi/0.1.20200115/ihanoi/assets/diskSelection/threeDisks.png


BIN
ilm/iHanoi/0.1.20200115/ihanoi/assets/diskSelection/twoDisks.png


BIN
ilm/iHanoi/0.1.20200115/ihanoi/assets/diskSelector.png


+ 0 - 0
ilm/iHanoi/0.1.20200115/ihanoi/assets/index.html


BIN
ilm/iHanoi/0.1.20200115/ihanoi/assets/msgBox.png


BIN
ilm/iHanoi/0.1.20200115/ihanoi/assets/redo.png


BIN
ilm/iHanoi/0.1.20200115/ihanoi/assets/redo2.png


BIN
ilm/iHanoi/0.1.20200115/ihanoi/assets/redoDisabled2.png


BIN
ilm/iHanoi/0.1.20200115/ihanoi/assets/restart.png


BIN
ilm/iHanoi/0.1.20200115/ihanoi/assets/selectionArea.png


BIN
ilm/iHanoi/0.1.20200115/ihanoi/assets/sky.png


+ 0 - 0
ilm/iHanoi/0.1.20200115/ihanoi/assets/sounds/index.html


BIN
ilm/iHanoi/0.1.20200115/ihanoi/assets/sounds/wrongBuzz.mp3


+ 0 - 0
ilm/iHanoi/0.1.20200115/ihanoi/assets/strokedDisks/index.html


BIN
ilm/iHanoi/0.1.20200115/ihanoi/assets/strokedDisks/stroked0.png


BIN
ilm/iHanoi/0.1.20200115/ihanoi/assets/strokedDisks/stroked1.png


BIN
ilm/iHanoi/0.1.20200115/ihanoi/assets/strokedDisks/stroked2.png


BIN
ilm/iHanoi/0.1.20200115/ihanoi/assets/strokedDisks/stroked3.png


BIN
ilm/iHanoi/0.1.20200115/ihanoi/assets/strokedDisks/stroked4.png


BIN
ilm/iHanoi/0.1.20200115/ihanoi/assets/strokedDisks/stroked5.png


BIN
ilm/iHanoi/0.1.20200115/ihanoi/assets/torre.png


BIN
ilm/iHanoi/0.1.20200115/ihanoi/assets/undo.png


BIN
ilm/iHanoi/0.1.20200115/ihanoi/assets/undo2.png


BIN
ilm/iHanoi/0.1.20200115/ihanoi/assets/undoDisabled2.png


BIN
ilm/iHanoi/0.1.20200115/ihanoi/assets/wrongMove.png


+ 0 - 0
ilm/iHanoi/0.1.20200115/ihanoi/css/index.html


+ 0 - 16
ilm/iHanoi/0.1.20200115/ihanoi/css/styles.css

@@ -1,16 +0,0 @@
-.cDiscos{
-  position: absolute;
-  margin-left: 90%;
-  margin-top: 2%;
-  height: 0.5%;
-  width: 2%;
-}
-
-.button{
-  position: absolute;
-  margin-left: 70%;
-  margin-top: 2%;
-  font-size: 80%;
-  width: 9%;
-  text-align: center;
-}

+ 0 - 14
ilm/iHanoi/0.1.20200115/ihanoi/ilm-application.xml

@@ -1,14 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<application xmlns="http://line.ime.usp.br/application/1.5">
-  <name>iHanoi</name>
-  <url>http://www.matematica.br/ihanoi</url>
-  <version>2</version>
-  <type>HTML5</type>
-  <description>{"en":"The Objective to move N discs from stick A to C, following some rule (from the game Towers of Hanoi)","pt_br":"O objetivo é mover N discos da haste A para C, seguindo algumas regras (implementa o jogo Torres de Hanói)"}</description>
-  <extension>ihn</extension>
-  <file_jar>iHanoi</file_jar>
-  <file_class>iHanoi/index.html</file_class>
-  <width>800</width>
-  <height>600</height>
-  <evaluate>1</evaluate>
-</application>

+ 0 - 24
ilm/iHanoi/0.1.20200115/ihanoi/index.html

@@ -1,24 +0,0 @@
-<!doctype html>
-<html lang="en">
-
-<head>
-    <meta charset="UTF-8" />
-    <title>iHanoi</title>
-    <script src="https://cdn.jsdelivr.net/npm/phaser@3.16.2/dist/phaser.js"></script>
-    <script src="https://code.jquery.com/jquery-3.4.1.min.js" integrity="sha256-CSXorXvZcTkaix6Yvo6HppcZGetbYMGWSFlBw8HfCJo=" crossorigin="anonymous"></script>
-    <style type="text/css">
-        body {
-            margin: 0;
-        }
-    </style>
-    <link rel='stylesheet' type='text/css' href='./css/styles.css'>
-</head>
-
-<body>
-
-    <script src="js/iHanoiFunctions.js"></script>
-    <script src="js/phaserConfig.js"></script>
-
-</body>
-
-</html>

+ 0 - 261
ilm/iHanoi/0.1.20200115/ihanoi/js/iHanoiFunctions.js

@@ -1,261 +0,0 @@
-var isMoving = false,
-    diskOrigin, diskDestiny, movements;
-var nWrongMoves = 0;
-var moves = [],
-    totalMoves = []; //vector to save movements
-var acertou = 0;
-var optimalSolution;
-var redo = false,
-    undo = false;
-var textDict = {
-    disk0: "stroked0",
-    disk1: "stroked1",
-    disk2: "stroked2",
-    disk3: "stroked3",
-    disk4: "stroked4",
-    disk5: "stroked5",
-    stroked0: "disk0",
-    stroked1: "disk1",
-    stroked2: "disk2",
-    stroked3: "disk3",
-    stroked4: "disk4",
-    stroked5: "disk5"
-};
-
-var wrongBuzz = new Audio('assets/sounds/wrongBuzz.mp3');
-//freesounds.org
-
-//To know which tower was selected
-function getTower(id) {
-    switch (id) {
-        case 0:
-            return towerA;
-        case 1:
-            return towerB;
-        case 2:
-            return towerC;
-    }
-}
-
-function selectA() {
-    if (!isMoving) {
-        if (towerA.length > 0) {
-            diskOrigin = 0;
-            isMoving = true;
-            towerA[towerA.length - 1].setTexture(textDict[towerA[towerA.length - 1].texture.key]);
-        }
-    } else {
-        if (diskOrigin != 0) {
-            moveFromTo(diskOrigin, 0);
-        } else {
-            towerA[towerA.length - 1].setTexture(textDict[towerA[towerA.length - 1].texture.key]);
-            isMoving = false;
-            nMoves.text++;
-        }
-    }
-}
-
-function selectB() {
-    if (!isMoving) {
-        if (towerB.length > 0) {
-            diskOrigin = 1;
-            isMoving = true;
-            towerB[towerB.length - 1].setTexture(textDict[towerB[towerB.length - 1].texture.key]);
-        }
-    } else {
-        if (diskOrigin != 1) {
-            moveFromTo(diskOrigin, 1);
-        } else {
-            towerB[towerB.length - 1].setTexture(textDict[towerB[towerB.length - 1].texture.key]);
-            isMoving = false;
-            nMoves.text++;
-        }
-    }
-}
-
-function selectC() {
-    if (!isMoving) {
-        if (towerC.length > 0) {
-            diskOrigin = 2;
-            isMoving = true;
-            towerC[towerC.length - 1].setTexture(textDict[towerC[towerC.length - 1].texture.key]); //levantar o disco
-        }
-    } else {
-        if (diskOrigin != 2) {
-            moveFromTo(diskOrigin, 2);
-        } else {
-            towerC[towerC.length - 1].setTexture(textDict[towerC[towerC.length - 1].texture.key]);
-            isMoving = false;
-            nMoves.text++;
-        }
-    }
-}
-
-
-function moveFromTo(origin, destiny) {
-    var originTower = getTower(origin),
-        destinyTower = getTower(destiny);
-    var topDiskOrigin = originTower[originTower.length - 1],
-        topDiskDestiny;
-    if (!undo && !redo) {
-        topDiskOrigin.setTexture(textDict[topDiskOrigin.texture.key]);
-    }
-    if (destinyTower.length > 0) {
-        //movement to a tower with a disk in it
-        topDiskDestiny = destinyTower[destinyTower.length - 1];
-        if (topDiskOrigin.displayWidth <= topDiskDestiny.displayWidth) {
-            topDiskOrigin.x += 435 * (destiny - origin);
-            topDiskOrigin.y += 28 * (originTower.length - destinyTower.length - 1);
-            originTower.pop();
-            destinyTower.push(topDiskOrigin);
-            //control variables
-            nMoves.text++;
-            totalMoves.push(origin + "  " + destiny);
-            if (!undo) {
-                //if it is either a redo or a new move we must add new moves to the current sequence for possible 'undos'
-                if (!redo) {
-                    //if it is a new move, we clean all possible "redos"
-                    moves.splice(nCurrentMoves, moves.length - nCurrentMoves);
-                    moves.push(origin + "  " + destiny);
-                }
-                nCurrentMoves++;
-                undoButton.setInteractive({ useHandCursor: true });
-                undoButton.setTexture('undo');
-                if (nCurrentMoves == moves.length) {
-                    redoButton.disableInteractive();
-                    redoButton.setTexture('redoDisabled');
-                }
-                redo = false;
-            } else {
-                nCurrentMoves--;
-                undo = false;
-                redoButton.setInteractive({ useHandCursor: true });
-                redoButton.setTexture('redo');
-                if (nCurrentMoves == 0) {
-                    undoButton.disableInteractive();
-                    undoButton.setTexture('undoDisabled');
-                }
-            }
-        } else {
-            invalidMovement(destiny);
-        }
-    } else {
-        //move to a tower without a disk in it
-        topDiskOrigin.x += 435 * (destiny - origin);
-        topDiskOrigin.y += 28 * (originTower.length - destinyTower.length - 1);
-        originTower.pop();
-        destinyTower.push(topDiskOrigin);
-        //control variables
-        nMoves.text++;
-        totalMoves.push(origin + "  " + destiny);
-        if (!undo) {
-            //if it is either a redo or a new move we must add new moves to the current sequence for possible 'undos'
-            if (!redo) {
-                //if it is a new move, we clean all possible "redos" and add the new move to the list
-                moves.splice(nCurrentMoves, moves.length - nCurrentMoves);
-                moves.push(origin + "  " + destiny);
-            }
-            nCurrentMoves++;
-            if (nCurrentMoves == moves.length) {
-                redoButton.disableInteractive();
-                redoButton.setTexture('redoDisabled');
-            }
-            undoButton.setInteractive({ useHandCursor: true });
-            undoButton.setTexture('undo');
-            redo = false;
-        } else {
-            nCurrentMoves--;
-            undo = false;
-            redoButton.setInteractive({ useHandCursor: true });
-            redoButton.setTexture('redo');
-            if (nCurrentMoves == 0) {
-                undoButton.disableInteractive();
-                undoButton.setTexture('undoDisabled');
-            }
-        }
-    }
-    movements += origin + " " + destiny + "\n"
-    isMoving = false;
-    if (towerC.length == diskQntity) {
-        if (nMoves.text == minimumMoves) {
-        	outputMsgBox.alpha = 0.8;        
-        	gameWonMsg.text = "Parabéns!\n\nVocê moveu a torre em " + nMoves.text + " movimentos!\nMÍNIMO DE MOVIMENTOS POSSÍVEIS!";
-        } else {
-        	outputMsgBox.alpha = 0.8;
-		    gameWonMsg.text = "Parabéns!\n\nVocê moveu a torre em " + nMoves.text + " movimentos!\n(Mínimo de movimentos possíveis: " + minimumMoves + ")";
-        }
-    } else {
-        outputMsgBox.alpha = 0;
-        gameWonMsg.text = ' ';
-    }
-}
-
-function redoMove() {
-    if (nCurrentMoves < moves.length) {
-        var res = moves[nCurrentMoves].split("  ");
-        redo = true;
-        moveFromTo(parseInt(res[0]), parseInt(res[1]));
-        if (nCurrentMoves == moves.length) redoButton.setInteractive({ useHandCursor: false });
-    }
-}
-
-function undoMove() {
-    if (nCurrentMoves > 0) {
-        var res = moves[nCurrentMoves - 1].split("  ");
-        undo = true;
-        moveFromTo(parseInt(res[1]), parseInt(res[0]));
-        if (nCurrentMoves == 0) undoButton.setInteractive({ useHandCursor: false });
-        redoButton.setInteractive({ useHandCursor: true });
-    }
-}
-
-function destroyDisks(torre) {
-    for (var i = 0; i < torre.length; i++) {
-        torre[i].destroy();
-    }
-    torre.splice(0, torre.length);
-}
-
-function restart(n = 0) {
-    if (n > 0) diskQntity = n;
-    restartVariables();
-    var diskX = 220,
-        diskY = 430;
-    for (var i = diskQntity - 1; i >= 0; i--) {
-        towerA[diskQntity - 1 - i] = scene.add.sprite(diskX, diskY, 'disk' + i).setScale(0.13); //.setDisplaySize(diskWidth, diskHeight);
-        diskY -= 28;
-    }
-
-    outputMsgBox.alpha = 0;
-    gameWonMsg.text = ' ';
-
-}
-
-function restartVariables() {
-    destroyDisks(towerA);
-    destroyDisks(towerB);
-    destroyDisks(towerC);
-    isMoving = false;
-    moves.splice(0, moves.length);
-    nCurrentMoves = 0;
-    minimumMoves = Math.pow(2, diskQntity) - 1;
-}
-
-function selectDisks(qntity, game) {
-    diskQntity = qntity;
-    restartVariables();
-    game.scene.start('sceneGame');
-
-}
-
-
-function invalidMovement(torre) {
-    wrongMoveSprite.setX(220 + torre * 435);
-    wrongBuzz.play();
-    wrongMoveSprite.setAlpha(1);
-    scene.time.delayedCall(1000, hideX, [], scene);
-}
-
-function hideX() {
-    wrongMoveSprite.setAlpha(0);
-}

+ 0 - 0
ilm/iHanoi/0.1.20200115/ihanoi/js/index.html


+ 0 - 106
ilm/iHanoi/0.1.20200115/ihanoi/js/integration-functions.js

@@ -1,106 +0,0 @@
-// Função para ler parâmetros informados pelo iTarefa via URL
-// Apesar de não ser obrigatório, será muito útil para capturar os parâmetros
-function getParameterByName(name) {
-    var match = RegExp('[?&]' + name + '=([^&]*)').exec(window.location.search);
-    return match ? decodeURIComponent(match[1].replace(/\+/g, ' ')) : null;
-}
-
-// Criando um array com os parâmetros informados pelo iTarefa
-// Observe que para cada parâmetro, é realizada a chamada do método getParameterByName, implementado acima
-var iLMparameters = {
-    iLM_PARAM_ServerToGetAnswerURL: getParameterByName("iLM_PARAM_ServerToGetAnswerURL"),
-    iLM_PARAM_SendAnswer: getParameterByName("iLM_PARAM_SendAnswer"),
-    iLM_PARAM_AssignmentURL: getParameterByName("iLM_PARAM_AssignmentURL"),
-    iLM_PARAM_Assignment: getParameterByName("iLM_PARAM_Assignment"),
-    lang: getParameterByName("lang")
-};
-
-// Função chamada pelo iTarefa quando o professor finaliza a criação da atividade
-// ou quando o aluno finaliza a resolução do exercício
-// O retorno é um JSON com os dados do exercício ou da resolução
-// Esse retorno será armazenado no banco de dados do Moodle, pelo iTarefa
-function getAnswer() {
-    // Se o parâmetro "iLM_PARAM_SendAnswer" for false,
-    // então trata-se de resolução de atividade
-    if (iLMparameters.iLM_PARAM_SendAnswer == 'false') {
-        // Montar o retorno da resposta do aluno
-        var studentAnswer = "Numero de discos: " + diskQntity + " \nQuantidade de Movimentos: " + nMoves.text + " \nMovimentos:";
-        for (var i = 0; i < totalMoves.length; i++) {
-            studentAnswer += "\n" + totalMoves[i];
-        }
-        return teacherReturn;
-    } else { //se for o professor acessando, mostra a pagina de elaboração
-        return "Número de Discos: " + diskQntity;
-    }
-}
-
-// Função chamada pelo iTarefa para receber a nota do aluno na atividade
-// O retorno é um valor entre 0.0 e 1.0
-function getEvaluation() {
-    if (iLMparameters.iLM_PARAM_SendAnswer == 'false') {
-
-        // Cálculo da nota: resposta correta = 1, errada = 0
-        var nota;
-        if (towerC.length == diskQntity) nota = 1;
-        else nota = 0;
-        /*  Para fazer nota proporcional descomente as 3 linhas abaixo
-        nota=nMoves.text/(Math.pow(2,diskQntity)-1);
-        if (towerB.length==diskQntity) nota *= 0.8;
-        else if(!towerC.length==diskQntity) nota=0;*/
-
-        // A chamada do método abaixo é obrigatória!
-        // Observe que a chamada parte do iLM para o iTarefa
-        parent.getEvaluationCallback(nota);
-    }
-}
-
-
-// Função para que o iMA leia os dados da atividade fornecidos pelo iTarefa
-function getiLMContent() {
-
-    // O parâmetro "iLM_PARAM_Assignment" fornece o URL do endereço que deve ser
-    // requisitado via AJAX para a captura dos dados da atividade
-    $.get(iLMparameters.iLM_PARAM_Assignment, function(d) {
-        // Uma vez que os dados foram recebidos, o método "organizaAtividade" é chamado.
-        // Observe que esse método faz parte do arquivo js/iarithmetic-functions.js
-        res = d.split(" ");
-        console.log(res[3]);
-
-        setQntityDisks(parseInt(res[3]));
-        //andar até o estado do ultimo envio
-        if (res.length > 4) {
-            res = d.split(/[\r]?\n/);
-            for (i = 3; i < res.length; i++) {
-                var mv = res[i].split(" ");
-                redo = 1; //previne de mudar a textura do disco
-                moveFromTo(parseInt(mv[0]), parseInt(mv[2]));
-            }
-        }
-    });
-}
-
-// Adicionamos a diretiva .ready(), para que quando a página HTML estiver carregada,
-// seja verificado qual a visualização deve ser apresentada: se a área de construção
-// de atividade ou de resolução. E no caso de ser resolução, os dados da atividade
-// precisam ser consultados, pelo método implementado acima, o getiLMContent()
-$(document).ready(function() {
-    // Se iLM_PARAM_SendAnswer for false, então trata-se de resolução de atividade,
-    // portanto, a "DIV" de resolução é liberada
-    if (iLMparameters.iLM_PARAM_SendAnswer == 'false') {
-        //abre a resolução da atividade
-        //pode ser tanto o prof quanto o aluno
-        getiLMContent();
-    } else {
-        // Caso não esteja em modo de resolução de atividade, a visualização no momento
-        // é para a elaboração de atividade:
-    }
-});
-
-function sleep(milliseconds) {
-    var startSleep = new Date().getTime();
-    for (var i = 0; i < 1e7; i++) {
-        if ((new Date().getTime() - startSleep) > milliseconds) {
-            break;
-        }
-    }
-}

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 0 - 2
ilm/iHanoi/0.1.20200115/ihanoi/js/jquery-3.3.1.min.js


+ 0 - 197
ilm/iHanoi/0.1.20200115/ihanoi/js/phaserConfig.js

@@ -1,197 +0,0 @@
-var towerA = [],
-    towerB = [],
-    towerC = [];
-var diskQntity = 3,
-    nMoves, nCurrentMoves = 0,
-    minimumMoves = Math.pow(2, diskQntity) - 1;
-var textsFont = { fontFamily: 'Arial', fontSize: 50, color: '#5cff5c' };
-var gameWonMsg, nMoves;
-var redoButton, undoButton, restartButton, diskSelectorButton;
-var scene, tween;
-var wrongMoveSprite; 
-var outputMsgBox;
-
-class sceneGame extends Phaser.Scene {
-    constructor() {
-        super({ key: 'sceneGame' });
-    }
-
-    preload() {
-        scene = this;
-        this.load.image('sky', 'assets/sky.png');
-        this.load.image('acoesBox', 'assets/acoes.png');
-        //this.load.image('base', 'assets/baseText.png');
-        this.load.image('torre', 'assets/torre.png');
-        this.load.image('selectionArea', 'assets/selectionArea.png');
-        //buttons
-        this.load.image('redo', 'assets/redo2.png');
-        this.load.image('redoDisabled', 'assets/redoDisabled2.png');
-
-        this.load.image('msgBox', 'assets/msgBox.png')
-
-        this.load.image('undo', 'assets/undo2.png');
-        this.load.image('undoDisabled', 'assets/undoDisabled2.png');
-
-        this.load.image('restart', 'assets/restart.png');
-
-        this.load.image('wrongMove', 'assets/wrongMove.png');
-
-        //Only loads disk selection if its the teacher using
-        try {
-            if (iLMparameters.iLM_PARAM_SendAnswer == 'true')
-                this.load.image('diskSelector', 'assets/diskSelector.png');
-            console.log("iAssign version");
-        } catch (e) {
-            this.load.image('diskSelector', 'assets/diskSelector.png');
-            console.log("web-version");
-        }
-        //load all imgs needed for the exercise
-        for (var i = 0; i < 6; i++) {
-
-            this.load.image('disk' + i, 'assets/disk' + i + '.png')
-            this.load.image('stroked' + i, 'assets/strokedDisks/stroked' + i + '.png')
-        }
-    }
-
-    create() {
-        //misc
-        this.add.image(0, 0, 'sky').setOrigin(0).setDisplaySize(1320, 600);
-
-
-        this.add.sprite(120, 90, 'acoesBox').setDisplaySize(80, 70);
-        nMoves = this.add.text(90, 70, 0, textsFont);
-
-        this.add.text(135, 530, 'Torre A', {fontFamily: 'Arial', fontSize: 50, color: '#4c0fbd'} );
-        this.add.text(570, 530, 'Torre B', {fontFamily: 'Arial', fontSize: 50, color: '#4c0fbd'} );
-        this.add.text(1005, 530, 'Torre C', {fontFamily: 'Arial', fontSize: 50, color: '#4c0fbd'} );
-        
-        //buttons
-        redoButton = this.add.sprite(720, 90, 'redoDisabled').setDisplaySize(80, 70); //.setInteractive({useHandCursor: false});
-        redoButton.on('pointerdown', function(pointer) {
-            redoMove();
-        });
-        undoButton = this.add.sprite(600, 90, 'undoDisabled').setDisplaySize(80, 70); //.setInteractive({useHandCursor: false});
-        undoButton.on('pointerdown', function(pointer) {
-            undoMove();
-        });
-
-        restartButton = this.add.sprite(990, 90, 'restart').setDisplaySize(80, 60).setInteractive({ useHandCursor: true });
-        restartButton.on('pointerdown', function(pointer) {
-            restart();
-        });
-
-        diskSelectorButton = this.add.sprite(1200, 90, 'diskSelector').setDisplaySize(80, 70).setInteractive({ useHandCursor: true });
-        diskSelectorButton.on('pointerdown', function(pointer) {
-            this.scene.start('sceneDiskSelection');
-        }, this);
-
-
-        //Towers
-        this.add.image(219, 320, 'torre').setScale(0.13);
-        this.add.image(654, 320, 'torre').setScale(0.13);
-        this.add.image(1089, 320, 'torre').setScale(0.13);
-
-        //Disks
-        var diskX = 220,
-            diskY = 430;
-        for (var i = diskQntity - 1; i >= 0; i--) {
-            towerA[diskQntity - 1 - i] = this.add.sprite(diskX, diskY, 'disk' + i).setScale(0.13); //.setDisplaySize(diskWidth, diskHeight);
-            diskY -= 28;
-        }
-
-        //towerA Selection Area
-        var towerASelectionArea = this.add.sprite(220, 375, 'selectionArea').setDisplaySize(400, 320).setInteractive({ useHandCursor: true });
-        towerASelectionArea.on('pointerdown', function(pointer) {
-            selectA();
-
-        });
-        towerASelectionArea.alpha = 0.1;
-
-        //towerB selectionArea
-        var towerBSelectionArea = this.add.sprite(655, 375, 'selectionArea').setDisplaySize(400, 320).setInteractive({ useHandCursor: true });
-        towerBSelectionArea.on('pointerdown', function(pointer) {
-            selectB();
-        });
-        towerBSelectionArea.alpha = 0.1;
-
-
-        var towerCSelectionArea = this.add.sprite(1090, 375, 'selectionArea').setDisplaySize(400, 320).setInteractive({ useHandCursor: true });
-        towerCSelectionArea.on('pointerdown', function(pointer) {
-            selectC();
-        });
-        towerCSelectionArea.alpha = 0.1;
-
-        wrongMoveSprite = this.add.sprite(220, 300, 'wrongMove').setDisplaySize(100, 100).setAlpha(0);
-
-
-
-        outputMsgBox = this.add.sprite(655, 310, 'msgBox').setDisplaySize(550,180);
-        outputMsgBox.alpha = 0;
-
-        gameWonMsg = this.add.text(450, 255, ' ', { fontFamily: 'Arial', fontSize: 22, color: '#00a600', align: 'center' });
-        
-
-    }
-
-    update() {}
-    event() {
-        console.log('over');
-    }
-}
-
-
-class sceneDiskSelection extends Phaser.Scene {
-    constructor() {
-        super({ key: 'sceneDiskSelection' });
-    }
-
-    preload() {
-        this.load.image('sixDisks', 'assets/diskSelection/sixDisks.png');
-        this.load.image('fiveDisks', 'assets/diskSelection/fiveDisks.png');
-        this.load.image('fourDisks', 'assets/diskSelection/fourDisks.png');
-        this.load.image('threeDisks', 'assets/diskSelection/threeDisks.png');
-        this.load.image('twoDisks', 'assets/diskSelection/twoDisks.png');
-    }
-
-    create() {
-        this.add.image(0, 0, 'sky').setOrigin(0).setDisplaySize(1320, 600);
-
-        var sixDisksButton = this.add.sprite(850, 450, 'sixDisks').setDisplaySize(200, 200).setInteractive({ useHandCursor: true });
-        sixDisksButton.on('pointerdown', function(pointer) {
-            selectDisks(6, this);
-        }, this);
-
-        var fiveDisksButton = this.add.sprite(450, 450, 'fiveDisks').setDisplaySize(200, 200).setInteractive({ useHandCursor: true });
-        fiveDisksButton.on('pointerdown', function(pointer) {
-            selectDisks(5, this);
-        }, this);
-
-        var fourDisksButton = this.add.sprite(1050, 200, 'fourDisks').setDisplaySize(200, 200).setInteractive({ useHandCursor: true });
-        fourDisksButton.on('pointerdown', function(pointer) {
-            selectDisks(4, this);
-        }, this);
-
-        var threeDisksButton = this.add.sprite(650, 200, 'threeDisks').setDisplaySize(200, 200).setInteractive({ useHandCursor: true });
-        threeDisksButton.on('pointerdown', function(pointer) {
-            selectDisks(3, this);
-        }, this);
-
-        var twoDisksButton = this.add.sprite(250, 200, 'twoDisks').setDisplaySize(200, 200).setInteractive({ useHandCursor: true });
-        twoDisksButton.on('pointerdown', function(pointer) {
-            selectDisks(2, this);
-        }, this);
-    }
-}
-
-var config = {
-    type: Phaser.AUTO,
-    scale: {
-        mode: Phaser.Scale.FIT,
-        width: 1320,
-        height: 600
-    },
-    scene: [sceneGame, sceneDiskSelection]
-        //  canvas: doocument.querySelector('mainDiv');
-};
-
-var game = new Phaser.Game(config);

+ 0 - 0
ilm/iHanoi/0.1.20200115/index.html


+ 58 - 0
ilm/iHanoi/1.0.20200803/ihanoi/css/ihanoi_style.css

@@ -0,0 +1,58 @@
+/*
+ LInE (Laboratory of Informatics in Education) - http://www.usp.br/line
+ IME - USP
+ iHanoi - http://www.matematica.br/ihanoi
+ Material didático
+ Pode usar livrevemente este material para fins não comerciais, devendo sempre fazer referência à autoria.
+ Prof. Leônidas de Oliveira Brandão
+ http://www.ime.usp.br/~leo
+ http://line.ime.usp.br
+ http://www.matemtica.br
+ */
+
+body { margin: 10; overflow: hidden; font-family:sans; }
+foot { font-size:.8cm; }
+canvas { padding-left: 0; padding-right: 0; margin-left: auto; margin-right: auto; display: block; }
+.fundoBotao { margin:0 auto; width: 1100px; background:url("../img/fundo1.png"); }
+.classeBotao1 {
+  display: inline-block; background-color: #7b38d8; border-radius: 10px; border: 4px double #cccccc; color: #eeeeee; text-align: center; font-size: 12px; padding: 5px;
+  width: 100px; -webkit-transition: all 0.5s; -moz-transition: all 0.5s; -o-transition: all 0.5s; transition: all 0.5s; cursor: pointer; margin: 2px; }
+
+/*
+ disk1: 3399ff 0066cc
+ disk2: cc66ff 9933ff
+ disk3: e4ee26 cdd711
+ disk4: 29eb46 11b92b
+ disk5: 990099 330033
+ disk6: ff6666 cc0000
+*/
+.tableBotoes { display:table; }
+.tableBotoes-celula { display:table-cell; }
+.tableBotoes-tar { text-align: left; }
+
+.classeBotaoR { background-color: #5566cc; width: 100px; }
+
+.classeBotao { display: inline-block; border-radius: 10px; border: 4px double #cccccc; color: #eeeeee; text-align: center;
+  font-size: 12px; padding: 5px; transition: all 0.5s; cursor: pointer; margin: 2px; }
+.classeBotao span { cursor: pointer; display: inline-block; position: relative; transition: 0.5s; }
+.classeBotao span:after { content: '\00bb'; position: absolute; opacity: 0; top: 0; right: -20px; transition: 0.5s;}
+.classeBotao:hover span { padding-right: 25px;}
+.classeBotao:hover span:after { opacity: 1; right: 0; }
+
+.classeBotao1 { background-color: #0066cc; width: 80px; font-size:.7em; }
+.classeBotao1:hover { background-color: #3399ff; }
+
+.classeBotao2 { background-color: #9933ff; width: 80px; font-size:.7em; }
+.classeBotao2:hover { background-color: #cc66ff; }
+
+.classeBotao3 { color:#444444; border: 4px double #444444; background-color: #cdd711; width: 80px; font-size:.7em; }
+.classeBotao3:hover { background-color: #e4ee26; }
+
+.classeBotao4 { background-color: #11b92b; width: 80px; font-size:.7em; }
+.classeBotao4:hover { background-color: #29eb46; }
+
+.classeBotao5 { background-color: #330033; width: 80px; font-size:.7em; }
+.classeBotao5:hover { background-color: #990099; }
+
+.classeBotao6 { background-color: #cc0000; width: 80px; font-size:.7em; }
+.classeBotao6:hover { background-color: #ff6666; }

BIN
ilm/iHanoi/1.0.20200803/ihanoi/img/disk1.png


BIN
ilm/iHanoi/1.0.20200803/ihanoi/img/disk2.png


BIN
ilm/iHanoi/1.0.20200803/ihanoi/img/disk3.png


BIN
ilm/iHanoi/1.0.20200803/ihanoi/img/disk4.png


BIN
ilm/iHanoi/1.0.20200803/ihanoi/img/disk5.png


BIN
ilm/iHanoi/1.0.20200803/ihanoi/img/disk6.png


BIN
ilm/iHanoi/1.0.20200803/ihanoi/img/fundo1.png


BIN
ilm/iHanoi/1.0.20200803/ihanoi/img/fundo2.png


BIN
ilm/iHanoi/1.0.20200803/ihanoi/img/hasteA.png


BIN
ilm/iHanoi/1.0.20200803/ihanoi/img/hasteB.png


BIN
ilm/iHanoi/1.0.20200803/ihanoi/img/hasteC.png


BIN
ilm/iHanoi/1.0.20200803/ihanoi/img/img_fundo_hanoi.png


+ 56 - 0
ilm/iHanoi/1.0.20200803/ihanoi/index.html

@@ -0,0 +1,56 @@
+<!--
+
+iHanói
+http://www.usp.br/line
+
+Uso: localhost/ihanoi/index.html?n=3&lang=pt
+@TODO ainda nao implementado multi-lingua
+
+Leônidas de Oliveira Brandão
+v0: 2020/07/28
+
+-->
+
+<!DOCTYPE html>
+<html>
+ <head>
+  <meta charset="utf-8">
+  <title>iHanói - Problema das Torres de Hanói</title>
+  <link rel="stylesheet" href="css/ihanoi_style.css" />
+ </head>
+
+<body onload="listaURL(); desenhaTudo();">
+
+<!-- Importante usar estilo para NAO apresentar: style="display:none; -->
+<img id="fundo" style="display:none;" src="img/img_fundo_hanoi.png" />
+<img id="haste0" style="display:none;" src="img/hasteA.png" />
+<img id="haste1" style="display:none;" src="img/hasteB.png" />
+<img id="haste2" style="display:none;" src="img/hasteC.png" />
+<img id="disco0" style="display:none;" src="img/disk1.png" />
+<img id="disco1" style="display:none;" src="img/disk2.png" />
+<img id="disco2" style="display:none;" src="img/disk3.png" />
+<img id="disco3" style="display:none;" src="img/disk4.png" />
+<img id="disco4" style="display:none;" src="img/disk5.png" />
+<img id="disco5" style="display:none;" src="img/disk6.png" />
+
+<!-- Carregar codigos JavaScript -->
+<script src="js/ihanoi.js"></script><!-- Carregar codigo do iMA iHanoi - JavaScript -->
+<script src="js/integration-functions.js"></script><!-- integrador do iMA como o iTarefa/Moodle - JavaScript -->
+
+<!-- Botoes auxiliares para iHanoir: redefinir, rever, 1 disco, ... -->
+<div class="fundoBotao tableBotoes">
+ <div class="tableBotoes-celula tableBotoes-tar">
+ <button id="reiniciar" class="classeBotao classeBotaoR" title="Reiniciar na configuração de partida" onclick="reiniciar();">Reiniciar</button> &nbsp;
+ <button id="rever"     class="classeBotao classeBotaoR" title="Rever os movimento - clique aqui para cada movimento" onclick="rever();">Rever</button>
+ &nbsp;&nbsp;&nbsp;&nbsp;
+ <button id="disco1" class="classeBotao classeBotao1" title="Apenas 1 disco"  onclick="reiniciar(1);">1 disco</button> &nbsp;
+ <button id="disco2" class="classeBotao classeBotao2" title="Apenas 2 discos" onclick="reiniciar(2);">2 discos</button> &nbsp;
+ <button id="disco3" class="classeBotao classeBotao3" title="Apenas 3 discos" onclick="reiniciar(3);">3 discos</button> &nbsp;
+ <button id="disco4" class="classeBotao classeBotao4" title="Apenas 4 discos" onclick="reiniciar(4);">4 discos</button> &nbsp;
+ <button id="disco5" class="classeBotao classeBotao5" title="Apenas 5 discos" onclick="reiniciar(5);">5 discos</button> &nbsp;
+ <button id="disco6" class="classeBotao classeBotao6" title="Apenas 6 discos" onclick="reiniciar(6);">6 discos</button> &nbsp;
+ </div>
+</div>
+
+</body>
+</html>

+ 579 - 0
ilm/iHanoi/1.0.20200803/ihanoi/js/ihanoi.js

@@ -0,0 +1,579 @@
+/* 
+iHanói
+http://www.usp.br/line
+
+Uso: localhost/ihanoi/index.html?n=3&lang=pt
+@TODO ainda nao implementado multi-lingua
+
+@AUTHOR Leônidas de Oliveira Brandão (coord. LInE)
+v0.5: 2020/11/22 (novo fundo; evita erro de disco sumir se de=para: nova msg 'msgDeParaIguais'; em "movaHaste(hi)" acresc. "if (topoDe == topoPara)...")
+v0.4: 2020/08/03
+v0.1: 2020/07/31
+v0: 2020/07/28
+*/
+
+/*
+No arquivo HTML que carrega esse JavaScript deve existir as seguintes imagens:
+  <img id="fundo" style="display:none;" src="img/img_fundo_hanoi.png" />
+  <img id="haste0" style="display:none;" src="img/hasteA.png" />
+  <img id="haste1" style="display:none;" src="img/hasteB.png" />
+  <img id="haste2" style="display:none;" src="img/hasteC.png" />
+  <img id="disco0" style="display:none;" src="img/disk1.png" />
+  <img id="disco1" style="display:none;" src="img/disk2.png" />
+  <img id="disco2" style="display:none;" src="img/disk3.png" />
+  <img id="disco3" style="display:none;" src="img/disk4.png" />
+  <img id="disco4" style="display:none;" src="img/disk5.png" />
+  <img id="disco5" style="display:none;" src="img/disk6.png" />
+
+Dimensoes e posicionamento das imagens
+ Hastes: 325 x 416
+  #   Posicao e tamanho dos discos:
+  6:  34, 250   294 130
+  5:  48, 210   267 130   +14 -40 -27 +0 
+  4:  62, 170   240 130   +14 -40 -27 +0 
+  3:  76, 130   213 130   +14 -40 -27 +0 
+  2:  90,  90   186 130   +14 -40 -27 +0 
+  1: 104,  50   159 130   +14 -40 -27 +0  (mas disk1 esta com 160x130)
+*/
+
+console.log("iHanoi: inicio");
+
+var canvas;
+var context;
+
+var width = 1100;
+var height = 460;
+var posY0  = 290; // posicionamento do disco maior (depende de 'height')
+
+// Posicionamento dos discos nas hastes
+var matHastes = [ [ 5,  4,  3,  2,  1,  0],   // haste A: pilha de discos (id discos em ordem inversa na haste); haste B e C vazias
+                  [-1, -1, -1, -1, -1, -1],   // haste B vazia
+                  [-1, -1, -1, -1, -1, -1] ]; // haste C vazia
+
+var vetorMovimentos = []; // vetor para registrar todos os movimentos do aluno - definido na 'movaHaste(hi)'
+
+// Posicionamentos de coordenadas (x,y) para cada um dos 6 discos (no maximo)
+var posTx = [  34,  48,  62,  76, 90, 104 ]; // posicoes x para discos: 6, 5, 4...  +14
+var posTy = [ 240, 200, 160, 120, 80,  40 ]; // posicoes y para discos: 6, 5, 4...  +40
+
+var nDiscos = 4; // Default entrar com 4 discos
+var contador = 0; // conta numero de movimentos
+var posx = [  52,  66, 80, 94 ]; // posicoes x para discos: 6, 5, 4...  +14
+var posy = [ 160, 120, 80, 40 ]; // posicoes y para discos: 6, 5, 4...  +40
+
+var posx_HA =  20, posy_HA = 40; // posicao haste A
+var posx_HB = 370, posy_HB = 40; // posicao haste A
+var posx_HC = 720, posy_HC = 40; // posicao haste A
+
+redefineDiscos(nDiscos); // redefinir 'matHastes[][]'
+
+var topoHasteA = nDiscos-1, topoHasteB = topoHasteC = -1; // indice do disco no topo de cada haste
+
+var iHanoi = "iHanói";
+var LInE = "LInE-IME-USP";
+
+var isExercise = false;  // se for exercicios, entao NAO permite alterar numero de discos
+var isAuthoring = false; // se for edicao, entao permita alterar numero de discos (sobrepoe opcao 'isExercise=true')
+var revendo = false;     // durante revisao de movimentos, NAO deveria movimentar discos, se o fizer, entao anule revisao!
+
+//TODO Permitir internacionalizar botoes
+var btnReiniciar="Reiniciar", btnRever="Rever", btnCodigo="Código";
+var altBtnReiniciar="Reiniciar tudo, todos os discos para haste A", altBtnRever="Rever todos os movimentos realizados",
+    altBtnCodigo="Examinar o código no formato do iHanói (extensão 'ihn')";
+
+var mensagem0 = "Clique na regiao da haste para selecionar origem, depois destino";
+var mensagem1_1 = "Parabéns! Você conseguiu mover todos os discos com ";
+var mensagem1_2 = " movimentos";
+var mensagem2_1 = "Não é permitido colocar disco maior sobre menor!";
+var mensagem2_2 = " sobre ";
+var mensagem3_1 = "Destino: ";
+var mensagem3_2 = " - Para novo movimento, clique em nova haste inicial";
+
+var msgTeste1 = "Parabéns conseguiu mover todos para B, mas lembre-se objetivo é C. Usou ";                  // 1
+var msgTeste2 = "Parabéns conseguiu mover todos para B e com mínimo de movimentos, mas objetivo é C. Usou "; // 2
+var msgTeste3 = "Parabéns conseguiu mover todos para C, mas não o mínimo de movimentos... Usou ";            // 3
+var msgTeste4 = "Parabéns! Conseguiu mover todos para C e o mínimo de movimentos! Foram ";                   // 4
+var msgEhExercicio = "Não pode alterar número de discos! É um exercício com número de discos pré-fixado.";
+var msgReverProx = "Clique novamente no botão 'Rever' para o próximo movimento.";
+var msgReverFim = "Acabaram os movimentos registrados.";
+var msgReverPare = "Estava revendo movimentação, mas ao mover manualmente, a revisão foi finalizada!";
+var msgDeParaIguais = "Para mover um disco é preciso que a haste de destino seja diferente da haste de origem!";
+
+var mensagemNM = "Número de movimentos: ";
+var mensagem = mensagem0; // mensagem inicial
+
+// Posicionamento para mensagens
+var txtTx = 10, txtTy = 20; // iHanoi
+var txtMX = 10, txtMY = height-10; // barra de mensagens: posicao
+var txtLInEx = width-180, txtLInEy = 20; // LInE-IME-USP
+
+var tamNMX = 300, tamNMY = 20; // mensagem sobre num. movimentos: tamanho
+//1 var txtNMX = 2*325+50, txtNMY = height-10; // mensagem sobre num. movimentos: posicao
+var txtNMX = 120, txtNMY = 20; // mensagem sobre num. movimentos: posicao
+var tamX = 900, tamY = 20;     // para area de mensagem
+
+// Gerenciamento de evento: primeiro ou segundo clique?
+var clickDe = -1, clickPara = -1; // origem e destino: -1,-1 = nada selecionado; x,-1 = selecionada origem; x,y = selecionadas ambas
+
+// Elementos graficos principais: Fundo + Haste + Discos
+var imgFundo  = document.getElementById("fundo");
+var imgHastes = [ document.getElementById("haste0"), document.getElementById("haste1"), document.getElementById("haste2") ];
+var imgDiscos = [ document.getElementById("disco0"), document.getElementById("disco1"), document.getElementById("disco2"),
+                  document.getElementById("disco3"), document.getElementById("disco4"), document.getElementById("disco5") ];
+var corFundo1 = "#26508c"; // para fundo de mensagem
+
+
+canvas = document.createElement("canvas");
+context = canvas.getContext("2d");
+canvas.addEventListener("click", clickCanvas); //OK
+
+// Tamanho da area de trabalho iHanoi
+canvas.width = width; canvas.height = height;
+
+document.body.appendChild(canvas); // iniciar area para desenho "canvas"
+
+//D console.log("iHanoi: apos definir elementos graficos");
+
+
+// Anote tratar-se de exercicio
+function setExercise (valor) { // invocada em 'integration-functions.js: decodificaArquivo(strContent)'
+  var element, i;
+  // se for exercicios, entao NAO permite alterar numero de discos
+  isExercise = true;
+  if (valor) { // if defined, then is teacher, allow edit (iLM_PARAM_Authoring)
+    isExercise = false;
+    return; // nao altere permissoes de trocar numero de discos
+    }
+  //D alert("setExercise: " + valor + ", iLM_PARAM_Authoring=" + iLMparameters.iLM_PARAM_Authoring + ", isExercise=" + isExercise);
+  var msg = "";
+  for (i=1; i<7; i++) {
+    element = document.getElementById("disco"+i);
+    if (element!=null) // se for re-avaliacao NAO existe interface grafica
+      element.disabled = true; // desabilita o botao
+    // Apenas isso NAO impede entrar no tratamento de "clique" no botao, ver 'reiniciar(nD)'
+    }
+  //D
+  console.log("setExercise: " + msg);
+  }
+
+
+// Redefine numero de discos a serem carregados e os posiciona (todos) na haste A
+// Evento: quando "clicar" nos botoes com numero de discos (elemento id="disco"+i (i=0, 1, 2,...5)
+function redefineDiscos (n) {
+  dif = 6-n;
+  for (i=0; i<n; i++) { // >
+    matHastes[0][i] = n-i-1;
+    posx[i] = posTx[i+dif];
+    posy[i] = posTy[i+dif];
+    }
+  for (i=n; i<6; i++) { // >
+    matHastes[0][i] = -1;
+    posx[i] = -1;
+    posy[i] = -1;
+    }
+  //D
+  console.log("redefineDiscos("+n+"): final");
+  }
+
+
+// Inicio --- Para rever movimentos ja' realizados
+var reverMov = -1;
+var totalMov = -1;
+var copiaMovimentos = [];
+
+// @calledby: rever(), clickCanvas(mouseEvent)
+function limparRevisao () { // durante revisao de movimentos, NAO deveria movimentar discos, se o fizer, entao anule revisao!
+  revendo = false; // nao mais revendo
+  reverMov = -1;
+  copiaMovimentos = [];
+  }
+
+function rever () { // vetorMovimentos = { clickDe + "  " + clickPara, ... }
+  if (reverMov == -1) { // inicio
+    limparRevisao();
+    revendo = true; // inicio de revisao
+    totalMov = vetorMovimentos.length;
+    for (i=0; i<totalMov; i++) copiaMovimentos.push(vetorMovimentos[i]);
+    reverMov = 0;
+    reiniciar();
+    mensagem = msgReverProx;
+    desenhaMensagem();
+    revendo = true; // durante revisao de movimentos, NAO deveria movimentar discos, se o fizer, entao anule revisao!
+    return;
+    }
+  if (reverMov == totalMov) { // final
+    mensagem = msgReverFim;
+    desenhaMensagem();
+    totalMov = reverMov = -1; // pode rever novamente
+    clickDe = clickPara = -1;
+    return;
+    }
+  var para, copia = copiaMovimentos[reverMov];
+  itens = copiaMovimentos[reverMov++].split(' ');
+  if (itens.length == 3) { clickDe = eval(itens[0]); para = eval(itens[2]); }
+  else { clickDe = eval(itens[0]); para = eval(itens[1]); }
+  // alert(itens + ": " + itens.length + ": rever: (" + copia + "): " + clickDe + "-" + clickPara);
+  console.log(itens + ", rever: (" + copia + "): " + clickDe + " + " + clickPara + " + " + para); // itens
+  movaHaste(para); // 'clickPara' tem que estar com -1 para completar movimento
+  mensagem = msgReverProx; // clique novamente no 'Rever'
+  desenhaTudo();
+  console.lgo("rever(): final");
+  } // rever()
+// Fim --- Para rever movimentos ja' realizados
+
+
+// Reiniciar o "jogo": zerar movimentos, colocar todos os discos sobre haste A
+function reiniciar (nD) {
+  getEvaluation(); // registrar 
+  vetorMovimentos = []; // zerar movimentos
+  if (nD!="" && nD!=undefined) {
+    var element = document.getElementById("disco1");
+    if (element.disabled) { // verifica se botao esta' desabilitado (neste caso e' exercicio)
+      console.log("Nao pode alterar numero de discos!");
+      mensagem = msgEhExercicio;
+      desenhaMensagem();
+      return;
+      }
+    redefineDiscos(nD);
+    nDiscos = nD;
+    }
+  topoHasteA = nDiscos-1;
+  topoHasteB = topoHasteC = -1;
+  for (i=0; i<nDiscos; i++) { // >
+    matHastes[1][i] = -1;
+    matHastes[2][i] = -1;
+    }
+  contador = 0;
+  redefineDiscos(nDiscos);
+  mensagem = mensagem0;
+  desenhaTudo();
+  console.log("reiniciar(nD): final");
+  }
+
+
+// Decompor parametros recebidos via GET: ?lang=pt&n=4
+// Devolve vetor: { 4, "pt" } nesta ordem
+function analisa_parametros_url (strParametros) {
+  var vars = strParametros.split("&");
+  var vetorParametros = [ 3, "pt" ]; // por padrao devolve { 3, "pt" }
+  var msg = ""; //D
+  var pair, key, value;
+  //?par1=val1&par2=val2&
+  for (var i = 0; i < vars.length; i++) { // >
+    pair = vars[i].split("=");
+    if (pair == "") break;
+    key = decodeURIComponent(pair[0]);
+    value = decodeURIComponent(pair[1]);
+    if (key=="n") {
+      vetorParametros[0] = value; // vetorParametros[i].push(decodeURIComponent(value));
+      nDiscos = value; // redefine 'nDiscos'
+      redefineDiscos(nDiscos);
+      }
+    else
+    if (key=="lang") 
+      vetorParametros[1] = value; // vetorParametros[i].push(decodeURIComponent(value));
+    msg += "("+key+","+value+") "; //D
+    }
+  //D console.log(vetorParametros); console.log("msg="+msg);  
+  return vetorParametros;
+  }
+
+
+// Pegar parametros via GET
+function listaURL () {
+  // window.location. [ href | protocol | host | hostname | port | pathname | search | hash
+  parametros = window.location.search;
+  if (parametros=="undefined")
+    return;
+  if (parametros.length>0) // >
+    parametros = parametros.substring(1); // elimina primeiro caractere '?'
+  analisa_parametros_url(parametros);
+  }
+
+
+// Para depuracao
+function imprimeMovimentos (hi) {
+  var i;
+  var msg, hA = "[", hB = "[", hC = "[";
+  for (i=0; i<nDiscos; i++) { // >
+    hA += matHastes[0][i] + " ";
+    hB += matHastes[1][i] + " ";
+    hC += matHastes[2][i] + " ";
+    }
+  msg = hA + "], " + hB + "], " + hC + "]";
+  return msg;
+  }
+
+
+// Pegar o valor do disco no topo da haste 'ind_haste'
+// Se haste vazia, devolve -1
+function pegaTopoHaste (ind_haste) { // pega indice do topo da haste
+  var topo, i;
+  //D alert("pegaTopoHaste: ind_haste=" + ind_haste + ": " + matHastes[ind_haste] + ", matHastes=" + matHastes);
+  i=0; while (matHastes[ind_haste][i]!=-1 && i<nDiscos) i++; // >
+  return i-1;
+  // Para melhorar a eficiencia, poderiamos usar diretamente as variaveis que tem indice dos topos: topoHasteA, topoHasteB, topoHasteC
+  }
+
+
+// Apos movimentacao de discos entre haste, acertar variaveis de topo e "clique"
+// Copia no topo de destino o disco do topo de origem
+function atualizaTopos (topoDe, topoPara) { // Tira topo "de" e insere em "para"
+  topoPara++;
+  matHastes[clickPara][topoPara] = matHastes[clickDe][topoDe]; // mova disco do topo de origem para topo de destino
+  if (matHastes[clickPara][topoPara] == undefined) { console.log("atualizaTopos("+topoDe+","+topoPara+"): erro! matHastes[clickPara][topoPara] undefined"); }  
+  // Tira disco do topo de origem
+  matHastes[clickDe][topoDe] = -1; // remova disco que estava no topo da haste de origem
+  topoDe--;
+  // Atualiza globais
+  if (clickDe==0) // haste A
+    topoHasteA = topoDe;
+  else
+  if (clickDe==1) // haste B
+    topoHasteB = topoDe;
+  else // haste C
+    topoHasteC = topoDe;
+  if (clickPara==0) // haste A
+    topoHasteA = topoPara;
+  else
+  if (clickPara==1) // haste B
+    topoHasteB = topoPara;
+  else // haste C
+    topoHasteC = topoPara;
+  //D alert("atualizaTopos: " + clickDe + " :: " + clickPara + ": " + imprimeMovimentos(clickPara));
+  clickDe = clickPara = -1; // comeca novamente...
+  }
+
+
+// Devolve rotulo da haste de indice 'hi'
+function pegaHaste (hi) {
+  if (hi==0) return "A";
+  if (hi==1) return "B";
+  return "C";
+  }
+
+
+// Verifica se todos os discos estao na haste C
+// Devolve: 0=nao moveu tudo; 1=moveu tudo para haste B; 2=moveu tudo para haste B com minimo de movimentos;
+//          3=moveu tudo par haste C; 4=moveu tudo par haste C com minimo de movimentos
+function movimentoFinal (haste, num) {
+  var topo = pegaTopoHaste(haste);
+  if (topo == nDiscos-1) { // moveu tudo!
+    if (haste == 2) { // moveu para haste C
+      if (contador == 2^nDiscos-1) { // moveu para haste C com minimo
+        return 4;
+        }
+      return 3; // moveu para haste C mas nao e' minimo
+      }
+    if (haste == 1) { // moveu para haste B
+      if (contador == 2^nDiscos-1) { // moveu para haste B com minimo
+        return 2; // msgTeste2
+        }
+      return 1; // moveu para haste C mas nao e' minimo
+      }
+    }
+  return 0;
+  }
+
+
+// Mover disco do topo da haste 'clickDe' para a haste 'hi' (sem 'clickDe' definido)
+function movaHaste (hi) {
+  var strHaste = pegaHaste(hi);
+  var de0 = clickDe, para0 = clickPara;
+  if (clickDe==-1 && clickPara==-1) { // inicio movimento
+    clickDe = hi;
+    topoDe = pegaTopoHaste(clickDe); // pega disco no topo de haste
+    if (topoDe==-1) { // nao tem discos
+      mensagem = "Haste " + strHaste + " está vazia! Por favor, selecione haste inicial com algum disco";
+      clickDe = clickPara = -1;
+      desenhaMensagem();
+      return;
+      }
+    mensagem = "Origem: " + strHaste + " - Agora clique na haste destino";
+    de0 = hi;
+    desenhaMensagem();
+    }
+  else
+  if (clickDe>-1 && clickPara==-1) { // final do movimento
+    clickPara = hi;
+    para0 = hi;
+    //D alert("De="+clickDe+", Para="+clickPara+", hi="+hi);
+    topoDe = pegaTopoHaste(clickDe);     // devolve indice topo de haste
+    topoPara = pegaTopoHaste(clickPara); // devolve indice topo de haste
+    if (clickDe == clickPara) {
+      str_haste = pegaHaste(clickDe); // nome da haste: "A", "B" ou "C"
+      mensagem = msgDeParaIguais + " (haste " + str_haste + ")";
+      console.log("Erro: Tentando mover disco para a mesma haste! (haste " + str_haste + ")");
+      clickDe = clickPara = -1; // comeca novamente...
+      desenhaMensagem();
+      return -1;
+      }
+    if (topoPara>-1 && matHastes[clickDe][topoDe]>matHastes[clickPara][topoPara]) { // disco maior sobre menor : proibido!
+      mensagem = mensagem2_1 + " (" + matHastes[clickDe][topoDe] + mensagem2_2 + matHastes[clickPara][topoPara] + ")";
+      //D alert("De="+clickDe+", Para="+clickPara+": "+topoDe+","+topoPara+": " + imprimeMovimentos(-1));
+      clickDe = clickPara = -1; // comeca novamente...
+      desenhaMensagem();
+      return -1;
+      }
+    vetorMovimentos.push(clickDe + "  " + clickPara);
+    if (topoDe<0) { console.log("movaHaste("+hi+"): "+clickDe + "  " + clickPara+": erro! undefined"); } //DEBUG
+    atualizaTopos(topoDe, topoPara);
+    contador++;
+
+    // 0=nao moveu tudo; 1=moveu tudo para haste B; 2=moveu tudo para haste B com minimo de movimentos;
+    // 3=moveu tudo par haste C; 4=moveu tudo par haste C com minimo de movimentos
+    respostaMov = movimentoFinal(hi, contador);
+
+    switch (respostaMov) {
+      case 0: mensagem = mensagem3_1 + strHaste + mensagem3_2; break;
+      case 1: mensagem = msgTeste1 + contador + mensagem1_2; break;
+      case 2: mensagem = msgTeste2 + contador + mensagem1_2; break; 
+      case 3: mensagem = msgTeste3 + contador + mensagem1_2; break; 
+      case 4: mensagem = msgTeste4 + contador + mensagem1_2; break; 
+      mensagem = mensagem1_1 + contador + mensagem1_2; // Paranbens! (falta comparar com numero minimo!)
+      }
+      
+    desenhaTudo();
+    }
+  console.lgo("movaHaste(hi): final");
+  return 1;
+  } // movaHaste(hi)
+
+
+// Dispara eventos
+function clickCanvas (mouseEvent) {
+  var posx = mouseEvent.offsetX, posy = mouseEvent.offsetY; // Posicao do "mouse", valores para parametros de '.drawImage(...)'
+  if (posx>25 && posx<350 && posy>30 && posy<440) { // > clicou na haste 1
+    resp = movaHaste(0);
+    }
+  else
+  if (posx>350 && posx<690 && posy>30 && posy<440) { // > clicou na haste 2
+    resp = movaHaste(1);
+    }
+  else
+  if (posx>690 && posx<1030 && posy>30 && posy<440) { // > clicou na haste 3
+    resp = movaHaste(2);
+    }
+  if (revendo) { // estava revendo movimento mas clicou em haste, entao cancele revisao!
+    mensagem = msgReverPare; //  "Estava revendo movimentação, mas ao mover manualmente, a revisão foi finalizada!"
+    limparRevisao();
+    desenhaMensagem(); //D sem efeito, nao 'sleep(.)' nao permite aparecer a mensagem
+    //sleep(1600); // em 'integration-functions.js'
+    }
+  }
+
+
+// Desenha um retangulo - modelo de http://jsfiddle.net/vu7dZ/1/
+function roundRect (ctx, x, y, width, height, radius, fill, stroke) {
+  if (typeof stroke == "undefined" ) { stroke = true; }
+  if (typeof radius === "undefined") { radius = 5; }
+  ctx.beginPath();
+  ctx.moveTo(x + radius, y);
+  ctx.lineTo(x + width - radius, y);
+  ctx.quadraticCurveTo(x + width, y, x + width, y + radius);
+  ctx.lineTo(x + width, y + height - radius);
+  ctx.quadraticCurveTo(x + width, y + height, x + width - radius, y + height);
+  ctx.lineTo(x + radius, y + height);
+  ctx.quadraticCurveTo(x, y + height, x, y + height - radius);
+  ctx.lineTo(x, y + radius);
+  ctx.quadraticCurveTo(x, y, x + radius, y);
+  ctx.closePath();
+  if (stroke) { ctx.stroke(); }
+  if (fill) { ctx.fill(); }        
+  }
+
+
+// Desenha os discos em cada Haste (Haste A = matHastes[0][]; Haste B = matHastes[1][]; Haste C = matHastes[2][])
+// Cada imagem tem 28 pixels a mais que o disco menor (dai o "(nDiscos - ind_disco-1)*14")
+function desenhaDiscos () { // 'context' e' global
+  var posx, posy, i;
+  //D console.log("desenhaDiscos(): inicio");
+
+  // Haste A
+  posy = posY0;
+  ind_disco = matHastes[0][0];
+  i = 0;
+  while (ind_disco!=-1) { // enquanto ainda tem disco, nao e' o ultimo
+    posx = 33 + (6 - ind_disco-1)*14; // para nDiscos=6 : usar 34 + ...
+    //TODO: precisa resolver um erro/advertencia que aparece
+    // TypeError: Argument 1 of CanvasRenderingContext2D.drawImage could not be converted to any of: HTMLImageElement, SVGImageElement, HTMLCanvasElement, HTMLVideoElement, ImageBitmap.
+    context.drawImage(imgDiscos[ind_disco], posx, posy);
+    posy -= 40;
+    i++;
+    ind_disco = matHastes[0][i];
+    }
+  // Haste B
+  posy = posY0;
+  ind_disco = matHastes[1][0];
+  i = 0;
+  while (ind_disco!=-1) { // enquanto ainda tem disco, nao e' o ultimo
+    posx = 382 + (6 - ind_disco-1)*14;
+    if (ind_disco == undefined) { console.log("desenhaDiscos(): disco 1: erro: i=" + i); return; } // alert("desenhaDiscos(): erro: i=" + i);
+    // console.log("desenhaDiscos(): " + imprimeMovimentos(0)); // + ", " + imprimeMovimentos(1) + ", " + imprimeMovimentos(2));
+    context.drawImage(imgDiscos[ind_disco], posx, posy);
+    posy -= 40;
+    i++;
+    ind_disco = matHastes[1][i];
+    }
+  // Haste C
+  posy = posY0;
+  ind_disco = matHastes[2][0];
+  i = 0;
+  while (ind_disco!=-1) { // enquanto ainda tem disco, nao e' o ultimo
+    posx = 732 + (6 - ind_disco-1)*14;
+    context.drawImage(imgDiscos[ind_disco], posx, posy);
+    posy -= 40;
+    i++;
+    ind_disco = matHastes[2][i];
+    }
+  console.log("desenhaDiscos(): final");
+  } // desenhaDiscos()
+
+
+// Apenas muda a mensagem informativa
+function desenhaMensagem () {
+  context.font = 'bold 14px serif';
+  context.fillStyle = "white";
+  //context.clearRect(txtMX, txtMY-15, tamX, tamY);
+  context.fillRect(txtMX, txtMY-15, tamX, tamY);
+  context.fillStyle = "black"; //"white";
+  context.fillText(" " + mensagem, txtMX, txtMY);
+  roundRect(context, txtMX, txtMY-15, tamX, tamY);
+  }
+
+
+// Redesenha tudo
+function desenhaTudo () {
+  console.log("desenhaTudo(): inicio");
+  context.font = 'bold 20px serif';
+  context.drawImage(imgFundo,   0,  0, width, height );
+  context.fillStyle = "white";
+  context.fillText(iHanoi, txtTx, txtTy); // iHanoi
+  context.fillText(LInE, txtLInEx, txtLInEy); // LInE-IME-USP
+  context.drawImage(imgHastes[0], posx_HA, posy_HA); // posicao haste A
+  context.drawImage(imgHastes[1], posx_HB, posy_HB); //
+  context.drawImage(imgHastes[2], posx_HC, posy_HC); //
+  context.font = 'bold 14px serif';
+  context.fillStyle = "white"; // "#26508c"; // para fundo de mensagem
+  //context.clearRect(txtMX, txtMY-15, tamX, tamY);  // Mensagens
+  context.fillRect(txtMX, txtMY-15, tamX, tamY);  // Mensagens
+  roundRect(context, txtMX, txtMY-15, tamX, tamY); // Mensagens
+  //context.clearRect(txtNMX, txtNMY-15, tamNMX, tamNMY);  // Numero de movimentos
+  context.fillRect(txtNMX, txtNMY-15, tamNMX, tamNMY);  // Numero de movimentos
+  roundRect(context, txtNMX, txtNMY-15, tamNMX, tamNMY); // Numero de movimentos
+  context.fillStyle = "black"; //"white";
+  context.fillText(" " + mensagem, txtMX, txtMY); // mensagens
+  context.fillText(" " + mensagemNM + contador, txtNMX, txtNMY); // numero de movimentos
+  desenhaDiscos();
+  console.log("desenhaTudo(): final");
+  } // desenhaTudo()
+
+
+// Versao distinta para inicia - removida em favor do 'onload' no 'body'
+// window.addEventListener("DOMContentLoaded", function () {
+//  //D alert("DOMContentLoaded: " + canvas.width + "," + canvas.height);
+//  desenhaTudo();
+//  });
+
+
+console.log("iHanoi: final do JavaScript principal"); //D

+ 252 - 0
ilm/iHanoi/1.0.20200803/ihanoi/js/integration-functions.js

@@ -0,0 +1,252 @@
+/* 
+iHano'i
+http://www.usp.br/line
+
+Uso: localhost/ihanoi/index.html?n=3&lang=pt
+@TODO ainda nao implementado multi-lingua
+
+Leo^nidas de Oliveira Branda~o
+v0.5: 2020/11/22 (getiLMContent(): se 'iLMparameters.iLM_PARAM_Assignment' vazio, nem tenta carregar arquivo do iHanoi (IHN))
+v0.4: 2020/08/03
+v0.1: 2020/07/31
+v0: 2020/07/28
+*/
+
+console.log("integration-functions.js: inicio");
+
+// Variaveis externas
+// nDiscos = numero de disco definido na funcao principal iHanoi
+// contador = contador de numero de movimentos realizados
+// topoHasteA, topoHasteB, topoHasteC = indice na haste do maior disco nela
+
+const NOTA_MINIMO_B = 0.8; // alvo nao era haste B, descontar
+const ESPERA = 0; // retardo para permitir ver movimentos qdo carga automatica
+
+// Funcao para ler parametros informados pelo iTarefa via URL
+// Apesar de nao ser obrigatorio, sera muito útil para capturar os parametros
+function getParameterByName (name) {
+  var match = RegExp('[?&]' + name + '=([^&]*)').exec(window.location.search);
+  return match ? decodeURIComponent(match[1].replace(/\+/g, ' ')) : null;
+  }
+
+// Criando um vetor com os parametros informados pelo iTarefa
+// Observe que para cada parametro, e realizada a chamada do metodo getParameterByName, implementado acima
+var iLMparameters = {
+  // Exemplo de como seria a URL via iTarefa/Moodle: http://.../moodle/mod/iassign/ilm_manager.php?from=iassign&id=2&action=update&ilmid=53&dirid=41800&fileid=282593
+  iLM_PARAM_Authoring: getParameterByName("iLM_PARAM_Authoring"), // if defined, then is teacher, allow edit
+  iLM_PARAM_ServerToGetAnswerURL: getParameterByName("iLM_PARAM_ServerToGetAnswerURL"),
+  iLM_PARAM_SendAnswer: getParameterByName("iLM_PARAM_SendAnswer"),
+  iLM_PARAM_AssignmentURL: getParameterByName("iLM_PARAM_AssignmentURL"),
+  iLM_PARAM_Assignment: getParameterByName("iLM_PARAM_Assignment"),
+  iLM_PARAM_TeacherAutoEval: getParameterByName("iLM_PARAM_TeacherAutoEval"),
+  lang: getParameterByName("lang")
+  };
+
+// Funcao chamada pelo iTarefa quando o professor finaliza a criacao da atividade
+// ou quando o aluno finaliza a resolucao do exercicio
+// O retorno e um JSON com os dados do exercicio ou da resolucao
+// Esse retorno sera armazenado no banco de dados do Moodle, pelo iTarefa
+function getAnswer () {
+  // Se o parametro "iLM_PARAM_SendAnswer" for false,
+  // entao trata-se de resolucao de atividade
+  if (iLMparameters.iLM_PARAM_SendAnswer == 'false') {
+    // Montar o retorno da resposta do aluno
+    var studentAnswer = "Numero de discos: " + nDiscos + " \nQuantidade de Movimentos: " + contador + " \nMovimentos:";
+    for (var i = 0; i < vetorMovimentos.length; i++) {
+      studentAnswer += "\n" + vetorMovimentos[i]; // vetorMovimentos[]: global definida em 'ihanoi.js'
+      }
+    // alert(studentAnswer);
+    return studentAnswer; // teacherReturn;
+  } else { //se for o professor acessando, mostra a pagina de elaboracao
+    return "Número de Discos: " + nDiscos;
+    }
+  }
+
+function potencia2 (n) {
+  var pot = 1, i;
+  for (i=0; i<n; i++) pot *= 2;
+  return pot;
+  }
+
+// Funcao chamada pelo iTarefa para receber a nota do aluno na atividade
+// O retorno e um valor entre 0.0 e 1.0
+function getEvaluation () {
+  if (iLMparameters.iLM_PARAM_SendAnswer == 'false') {
+    // Calculo da nota: resposta correta = 1 (C em minimo), 0.7 (B em minimo), errada = 0
+    var aux;
+    var nota;
+    var minimo = potencia2(nDiscos)-1; // 2^nDiscos-1
+    if (topoHasteC+1 == nDiscos) { // moveu todos para C
+      if (contador == minimo) { // com o minimo
+        nota = 1;
+        aux = 1;
+        }
+      else {
+        nota = minimo / contador; // quanto mais movimentos, menor nota
+        aux = 2;
+        }
+      }
+    else
+    if (topoHasteB+1 == nDiscos) { // moveu todos para B
+      if (contador == minimo) { // com o minimo
+        nota = NOTA_MINIMO_B; // alvo nao era haste B, descontar
+        aux = 3;
+        }
+      else {
+        nota = minimo / contador; // quanto mais movimentos, menor nota
+        aux = 4;
+        }
+      }
+    else {
+      nota = 0;
+      aux = 5;
+      }
+
+    // getEvaluation(): topoHasteB=2, topoHasteC=-1, nota=0 :: 4
+    // getEvaluation(): topoHasteB=-1, topoHasteC=2, nota=0 :: 2 minimo=0 contador=7 0
+    console.log("getEvaluation(): topoHasteB=" + topoHasteB + ", topoHasteC=" + topoHasteC + ", nota="+nota + " :: " + aux + " minimo="+minimo+" contador="+contador+" "+(minimo/contador));
+    // A chamada do metodo abaixo e obrigatoria!
+    // Observe que a chamada parte do iLM para o iTarefa
+    //D alert("nota="+nota+"\n"+msg);
+    parent.getEvaluationCallback(nota); //TODO NAO usado!!!!????
+    return nota;
+    }
+  }
+
+
+// Formato do arquivo iHanoi: exercicio, apenas com numero de discos
+//    Numero de Discos: 2
+// Formato do arquivo iHanoi: resposta do aluno, com discos e movimentos
+//    Numero de Discos: 2
+//    Quantidade de Movimentos: 3 
+//    Movimentos:
+//    0  1
+//    0  2
+//    1  2
+function decodificaArquivo (strContent) {
+  var linhas = strContent.split("\n");
+  var msg = "";
+  var nlinhas = linhas.length, nmov;
+  var itens, i1, i2;
+  if (nlinhas>0) {
+    itens = linhas[0].split(":");
+    nDiscos = eval(itens[1]);
+    nDiscos0 = nDiscos;
+    if (iLMparameters.iLM_PARAM_Authoring == 'true')
+      setExercise(true); // global definidas em 'ihanoi.js': indica tratar-se de exercicio
+    else
+      setExercise(false); // global definidas em 'ihanoi.js': indica tratar-se de exercicio
+    //D alert("decodificaArquivo: iLM_PARAM_Authoring=" + iLMparameters.iLM_PARAM_Authoring);
+    // nDiscos = 0;
+    reiniciar(); // Funcao externa: reinicia iHanoi
+    if (nlinhas>1) {
+      itens = linhas[1].split(":");
+      nmov = itens[1]; // numero de movimentos do aluno
+      contador = nmov;
+      }
+    if (nlinhas>2) {
+      contador = 0; // global definidas em 'ihanoi.js': conta numero de movimentos
+      for (i=3; i<nlinhas; i++) { // pula linha com "Movimentos:"
+        itens = linhas[i].split(" ");
+	if (itens=="" || itens.length<2) {
+          console.log("Erro: arquivo nao está no formato iHanoi. Linha " + i + ": " + linhas[i]);
+          return;
+          }//decodificaArquivo: "0,,1
+        i0 = 0; i1 = 1;
+        if (itens.length==3) // se decomposicao tratar "0 1" como {0,,1}
+          i1 = 2;
+        clickDe = itens[i0];   // global definidas em 'ihanoi.js': haste de partida
+        clickPara = -1;        // global definidas em 'ihanoi.js': haste de chegada
+        //D alert("decodificaArquivo: \"" + itens + "\":" + clickDe + " - " + itens[i1]);
+        movaHaste(eval(itens[i1]));  // funcao definidas em 'ihanoi.js': mover de hastes - 'eval(.)' elimina eventual \n ou ' '
+	desenhaTudo(); // funcao definidas em 'ihanoi.js': desenhar novo configuracao
+	// sleep(ESPERA);
+        msg += "\n" + linhas[i];
+        }
+      }
+    }
+  } // function decodificaArquivo(strContent)
+
+
+// Funcao para que o iMA leia os dados da atividade fornecidos pelo iTarefa
+function getiLMContent () {
+  var msg = "";
+  // O parametro "iLM_PARAM_Assignment" fornece o URL do endereco que deve ser
+  // requisitado via XMLHttpRequest() para a captura dos dados da atividade
+  var pagina = iLMparameters.iLM_PARAM_Assignment;
+  var txtFile;
+  var data = -1;
+  //D console.log("integration-functions.js: getiLMContent(): iLMparameters.iLM_PARAM_TeacherAutoEval=" + iLMparameters.iLM_PARAM_TeacherAutoEval); //D
+  //D console.log("integration-functions.js: getiLMContent(): iLMparameters.iLM_PARAM_Assignment=" + iLMparameters.iLM_PARAM_Assignment);
+  if (iLMparameters.iLM_PARAM_Assignment == null) {
+    console.log("integration-functions.js: getiLMContent(): NAO existe arquivo IHN para ser carregado (iLMparameters.iLM_PARAM_Assignment vazio), finalize");
+    return;
+    }
+  if (iLMparameters.iLM_PARAM_TeacherAutoEval != null) {
+    try {
+      parent.getAutoEvalOriginalData(); // funcao definida pelo iTarefa que devolve o conteudo original do exercicio atual
+    } catch (Error) {
+      console.log("integration-functions.js: getiLMContent(): erro ao tentar executar funcao 'getAutoEvalOriginalData()'");
+      } // se nao esta' em re-avaliacao => NAO esta' definida 'parent.getAutoEvalOriginalData()'
+    // alert("integration-functions.js: actual exercise=" + data);
+    teacherAutoEval(data);
+    console.log("integration-functions.js: getiLMContent(): final (apos ler arquivo IHN)");
+    return;
+    }
+
+  txtFile = new XMLHttpRequest(); // preparar coneccao HTTP para requisitar um arquivo IHN
+
+  console.log("integration-functions.js: getiLMContent(): tenta pegar arquivo de " + pagina);
+
+  // window.location : href = a URL inteira; pathname = ; hostname = apenas o nome do servidor
+  txtFile.open("GET", pagina, true); // true=>asincrono - mas ambos estao resultando (arq. IHN nao passar teste XML...): XML Parsing Error: syntax error
+  txtFile.send(); // so' pode fechar apos 3o passo
+  txtFile.responseType="text"; // Evita advertencia: XML Parsing Error: syntax error
+
+  txtFile.onreadystatechange = function () {
+    if (txtFile.readyState === 4) { // Makes sure the document is ready to parse.
+      if (txtFile.status === 200) { // Makes sure the file exists.
+        // 3o passo: por ultimo chega aqui!
+        var nDiscos0;
+        nDiscos0 = nDiscos;
+        allText = txtFile.responseText;
+        texto = allText; // define global 'texto'
+        // processar conteudo de INH
+        decodificaArquivo(allText);
+        }
+      //else alert("Erro 2"); // 2o passo: passa depois aqui
+      }
+    //else alert("Erro 1"); // 1o passo: passa primeiro aqui
+    } 
+  console.log("integration-functions.js: getiLMContent(): final");
+  } // function getiLMContent()
+
+
+// Adicionamos a diretiva .ready(), para que quando a pagina HTML estiver carregada,
+// seja verificado qual a visualizacao deve ser apresentada: se a area de construcao
+// de atividade ou de resolucao. E no caso de ser resolucao, os dados da atividade
+// precisam ser consultados, pelo metodo implementado acima, o getiLMContent()
+
+// Pegar conteudo da ativida iMA
+getiLMContent();
+
+function sleep (milliseconds) {
+  var startSleep = new Date().getTime();
+  for (var i = 0; i < 1e7; i++) {
+    if ((new Date().getTime() - startSleep) > milliseconds) {
+      break;
+      }
+    }
+  }
+
+
+// To be used with re-evaluation
+function teacherAutoEval (data) {
+  var nDiscos0;
+  nDiscos0 = nDiscos;
+  alert("integration-functions.js: teacherAutoEval(.): " + data);
+  // processar conteudo de INH
+  decodificaArquivo(data);
+  }
+
+console.log("integration-functions.js: final");

ilm/iHanoi/0.1.20200115/ihanoi/assets/diskSelection/index.html → ilm/iHanoi/1.0.20200803/index.html