Gustavo Grancieiro 3 vuotta sitten
vanhempi
commit
d0d2d84699

+ 58 - 0
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; }

+ 1 - 0
ihanoi/exer2.ihn

@@ -0,0 +1 @@
+Numero de Discos: 2

+ 6 - 0
ihanoi/exer2_solucao.ihn

@@ -0,0 +1,6 @@
+Numero de discos:  2 
+Quantidade de Movimentos: 3 
+Movimentos:
+0  1
+0  2
+1  2

+ 75 - 0
ihanoi/ihanoi.html

@@ -0,0 +1,75 @@
+<!--
+
+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
+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();">
+
+<!--canvas id="canvas"></canvas-->
+<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="disco5" style="display:none;" src="img/disk6.png" />
+<img id="disco4" style="display:none;" src="img/disk5.png" />
+<img id="disco3" style="display:none;" src="img/disk4.png" />
+<img id="disco2" style="display:none;" src="img/disk3.png" />
+<img id="disco1" style="display:none;" src="img/disk2.png" />
+<img id="disco0" style="display:none;" src="img/disk1.png" />
+
+
+<script src="js/ihanoi.js"></script>
+<script src="js/integration-functions.js"></script>
+
+<script type='text/javascript'>
+  //<![CDATA[
+  // ./mod/iassign/ilm/
+  function getConstruction () {
+     strAnswer = window.getAnswer();
+     alert("Movimentos realizados até agora (no formato iHanói):\n" + strAnswer);
+     return true;
+     }
+  //]]>
+</script>
+
+<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>
+ <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>
+
+
+<hr/>
+
+<div class="foot">
+<a href="http://www.usp.br/~leo" title="página Leônidas O. Brandão">Prof. Leônidas de Oliveira Brandão (coord. do LInE)</a><br/>
+<a href="http://www.usp.br/line" title="página do LInE">Laboratório de Informática na Educação (LInE)</a><br/>
+<a href="http://www.matematica.br/ihanoi" title="página do iHanói no iMática">iHanói/iMática</a><br/>
+</div>
+
+</body>
+</html>

BIN
ihanoi/ihanoi.zip


BIN
ihanoi/img/disk1.png


BIN
ihanoi/img/disk2.png


BIN
ihanoi/img/disk3.png


BIN
ihanoi/img/disk4.png


BIN
ihanoi/img/disk5.png


BIN
ihanoi/img/disk6.png


BIN
ihanoi/img/fundo1.png


BIN
ihanoi/img/fundo2.png


BIN
ihanoi/img/hasteA.png


BIN
ihanoi/img/hasteB.png


BIN
ihanoi/img/hasteC.png


BIN
ihanoi/img/img_fundo_hanoi.png


+ 247 - 0
ihanoi/index.html

@@ -0,0 +1,247 @@
+<!-- Diretorio: programas/hanoi -->
+
+<!--
+
+ http://www.matematica.br
+
+ O material desta pagina pode ser livremente impresso e utilizado, nao podendo
+ ser copiado sem citar o endereco original do material.
+ Coordenacao: Prof. Dr. Leo^nidas de Oliveira Branda~o - www.ime.usp.br/~leo
+  ____  ______         _ _ ___ ___ 
+ | |  \/  |  _|  ---  | | |  _| _ |
+ | |      |  _| |   | | | |_  |  _|
+ |_|_|\/|_|___|  ---  |___|___|_|  
+ 
+-->
+
+<html>
+<head>
+<title>Torres de Han&oacute;i - iM&aacute;tica </title>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<meta charset="utf-8">
+<META name="Author" content="Leônidas de Oliveira Brand&atilde;o - leo@ime.usp.br">
+<META name="description" content="iMatica: paginas de Matematica na Internet,
+      sua Matematica interativa, hist&otilde;ria da Matematica, material didatico,
+      problemas Matematicos, curiosidades, programas gratuitos, download"> 
+<META name="keywords" content=" hist&otilde;ria da Matematica, material didatico,
+      problemas Matematicos, curiosidades, programas gratuitos, download">
+
+<LINK REL="stylesheet" TYPE="text/css" HREF="ihanoi.css"> 
+
+<script language="JavaScript">
+<!--
+function MM_swapImgRestore() { //v3.0
+  var i,x,a=document.MM_sr; for(i=0;a&&i<a.length&&(x=a[i])&&x.oSrc;i++) x.src=x.oSrc;
+}
+
+function MM_preloadImages() { //v3.0
+ var d=document; if(d.images){ if(!d.MM_p) d.MM_p=new Array();
+ var i,j=d.MM_p.length,a=MM_preloadImages.arguments; for(i=0; i<a.length; i++)
+ if (a[i].indexOf("#")!=0){ d.MM_p[j]=new Image; d.MM_p[j++].src=a[i];}}
+}
+
+function MM_findObj(n, d) { //v4.0
+  var p,i,x;  if(!d) d=document; if((p=n.indexOf("?"))>0&&parent.frames.length) {
+  d=parent.frames[n.substring(p+1)].document; n=n.substring(0,p);}
+  if(!(x=d[n])&&d.all) x=d.all[n]; for (i=0;!x&&i<d.forms.length;i++) x=d.forms[i][n];
+  for(i=0;!x&&d.layers&&i<d.layers.length;i++) x=MM_findObj(n,d.layers[i].document);
+  if(!x && document.getElementById) x=document.getElementById(n); return x;
+}
+
+function MM_swapImage() { //v3.0
+  var i,j=0,x,a=MM_swapImage.arguments; document.MM_sr=new Array; for(i=0;i<(a.length-2);i+=3)
+  if ((x=MM_findObj(a[i]))!=null){document.MM_sr[j++]=x; if(!x.oSrc) x.oSrc=x.src; x.src=a[i+2];}
+}
+//-->
+</script>
+</head>
+
+<body topmargin="5" leftmargin="0" marginheight="5" bgcolor="#FFFFFF" text="#000000"
+      background="../../imagens/bg-fundo9.gif">
+
+<table hspace=0 width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td width="100"><img src="../../imagens/white100.gif"></td>
+ <td  align=center>
+ <table width="550" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+   <td>
+   <div align=center><a href="../../"><img src="../../imagens/logo1_31.gif" border="0"></a><br/>
+     <a href="../../"><img src="../../imagens/logob1_2.gif" width="400" height="33" border="0"></a> 
+   </div>
+  <div align=right><b><font color="#0099FF" size="+1">www.matematica.br</font></b></div> </td>
+ </tr>
+ </table></td></tr>
+</table>
+
+<!-- cabecalho--------------------------------------------------------->
+
+<font face="Arial, Helvetica, sans-serif">
+
+<center>
+  <h2><b> <font color=#0066ff>Torres de Han&oacute;i</font> </b></h2>
+</center>
+
+<center>
+[ <a href="#ihanoi">ihanoi</a> | <a href="#lenda">lenda</a> | <a href="#jogar">jogar</a> |
+  <a href="#descarregar" title="fazer uma c&otilde;pia do iHan&oacute;i para uso local">download</a>]
+</center>
+
+
+<center>
+
+<table width="1100">
+ <tr><td class="titulo" colspan="2"><a name="objetivo"></a><b>Objetivo</b></td></tr>
+ <tr><td>&nbsp;&nbsp;&nbsp;&nbsp;</td>
+  <td><font color=#000f0f face="Arial,Helvetica"> Mover todos os discos 
+    da haste A para a haste C, utilizando o menor n&uacute;mero poss&iacute;vel de movimentos, 
+    respeitando-se as regras abaixo.</font></td>
+ </tr>
+
+  <tr><td class="titulo" colspan="2"><a name="regras"></a><b>Regras</b></td></tr>
+  <tr><td>&nbsp;&nbsp;&nbsp;&nbsp;</td>
+   <td><font face="Arial,Helvetica" color=#000f0f>
+    <ol>
+      <li> um disco maior n&atilde;o pode ser colocado sobre um disco menor;
+      <li> pode-se mover um &uacute;nico disco por vez;
+      <li> um disco deve estar sempre numa das tr&ecirc;s hastes, ou em movimento.
+    </ol>
+    </font></td></tr>
+
+  <tr><td class="titulo" colspan="2"><a name="jogar"></a><b>Como jogar</b></td></tr>
+  <tr><td>&nbsp;&nbsp;&nbsp;&nbsp;</td>
+  <td><font face="Arial,Helvetica" color=#000f0f>
+    <ol>
+      <li>Para mover o menor disco (no topo) de uma haste "clique" sobre essa haste de <b>origem</b>, depois "clique" sobre a haste de <b>destino</b>.<br/>
+          Por exemplo, se desejar mover o disco (no topo) da haste B para (o topo da) haste C, clique primeiro em B e depois em C.
+      <li>Para alterar o n&uacute;mero de disco, "clique" sobre o bot&atilde;o desejado
+          (<tt>1 disco</tt> para um único disco, <tt>2 discos</tt> para dois discos e assim por diante).
+      <li>Para recome&ccedil;ar o <i>jogo</i>, clique no bot&atilde;o <i>Reiniciar</i>.
+      <li>Para rever os movimentos, "clique" sobre o botão <i>Rever</i> (é necessário ter havido algum movimento).
+    </ol>
+    </font></td>
+  </tr>
+  </table>
+
+
+  <!-- Quadro com o HTML que devera' carregar o iHanoi -->
+  <iframe frameborder="0" name="iLM" src="index_ihanoi.html" style="width: 1140px; height: 540px;"  id="iLM"></iframe>
+
+
+  <table width="1100">
+  <tr><td class="titulo" colspan="2"><a name="lenda"></a><b>Lenda</b></td></tr>
+  <tr><td>&nbsp;&nbsp;&nbsp;&nbsp;</td>
+  <td><font color=#000f0f face="Arial,Helvetica"> O problema das Torres 
+    de Han&oacute;i foi inicialmente proposta pelo matem&aacute;tico franc&ecirc;s Edouard Lucas, 
+    em 1883. Lucas elaborou para seu "invento" uma lenda curiosa sobre uma 
+    torre muito grande, a Torre de Brama, que foi criada no in&iacute;cio dos tempos, 
+    com tr&ecirc;s hastes contendo 64 discos conc&ecirc;ntricos. O criador do universo 
+    tamb&eacute;m gerou uma comunidade de monges cuja &uacute;nica atividade seria mover 
+    os discos da haste original ("A") para uma de destino ("C"). e estabeleceu 
+    o mundo acabaria quando os monges terminassem sua tarefa. Por&eacute;m, os 
+    monges deveriam respeitar tr&ecirc;s regras na sua tarefa:
+    <ol>
+      <li> nunca colocar um disco maior sobre um disco menor; 
+      <li> pode-se mover um &uacute;nico disco por vez;
+      <li> nunca colocar um disco noutro lugar que n&atilde;o numa 
+        das tr&ecirc;s hastes.
+    </ol>
+    Assim, sua tarefa &eacute; encontrar a regra de movimenta&ccedil;&atilde;o 
+    &otilde;tima (que atinja o objetivo com um n&uacute;mero m&iacute;nimo de movimentos) e com 
+    isso estimar quanto tempo ainda nos resta!! <br/>
+    Suponha que cada disco leve 1 segundo para ser movido. Tente encontrar 
+    uma f&otilde;rmula que, dado "n" devolva o n&uacute;mero m&iacute;nimo de movimentos para 
+    "n" discos. </font></td>
+  </tr>
+
+  <tr><td class="titulo" colspan="2"><a name="descarregar"></a>
+    <b>Interessado em contribuir com o desenvolvimento (ou personalizar uma vers&atilde;o para voc&ecirc;)?</b></td></tr>
+  <tr><td>&nbsp;&nbsp;&nbsp;&nbsp;</td>  
+   <td><font color=#000f0f face="Arial,Helvetica">
+    <!--
+    Basta pegar o c&oacute;digo fonte em no servidor <a href="http://200.144.254.107/git/bernardo/iHanoi" title="seguir para o repositorio com o iHanoi HTML5">GIT</a><br/>
+    -->
+    Essa versão do <b>iHanói</b> foi desenvolvida em <i>JavaScript</i> puro (sem apoio de arcabouços) para ilustrar os
+    <b>Módulos de Aprendizagem interativa (iMA)</b>.
+    <br/>
+    Um <i>iMA</i> pode ser integrado ao <i>Moodle</i>, se desejar conferir como, 
+    <a href="ima.html" title="clique aqui para examinar o que é um iMA">por favor clique aqui</a>.
+    <br/>&nbsp;<br/>
+    Para pegar uma cópia completa do <b>iHanói</b> (incluindo estas páginas),
+    <a href="ihanoi_modelo_ima.tgz" title="cópia completa do iHanói">"clique" nesse apontador</a>.
+    <br/>&nbsp;<br/>
+    Para examinar outros sistemas educacionais livres desenvolvidos no <a href="http://www.usp.br/line" title="para ir para pagina inicial do LInE (Laboratorio de Inoformatica na Educacao)">LInE</a>.
+    <br/>
+    <b>Software livre, dados privados</b>.
+    <br/>&nbsp;<br/>
+    <a href="http://www.usp.br/~leo" title="página Leônidas O. Brandão">Prof. Leônidas de Oliveira Brandão</a><br/>
+    <a href="http://www.usp.br/line" title="página do LInE">Laboratório de Informática na Educação (LInE)</a><br/>
+  </td>
+  </tr>
+
+</table>
+
+<br/>&nbsp;</br>
+
+<!--
+<table>
+ <tr>
+  <td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</td>
+  <td><font face="Arial,Helvetica" color=#000f0f>
+     Se no topo direito do iHan&oacute;i n&atilde;o entrar uma lista para selecionar n&uacute;mero de
+     discos (em alguns navegadores de Windows n&atilde;o esta funcionando), use aqui:
+     <a href="ihanoi1.html">1 discos</a> - <a href="ihanoi2.html">2 discos</a> - 
+     <a href="ihanoi3.html">3 discos</a> - <a href="ihanoi4.html">4 discos</a> - 
+     <a href="ihanoi5.html">5 discos</a> - <a href="ihanoi6.html">6 discos</a> - 
+     <a href="ihanoi7.html">7 discos</a></font></td>
+ </tr>
+ <tr>
+  <td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</td>
+  <td><br/><table>
+    <tr><td class="menor2" colspan="2">Vers&atilde;o atual:</td><td class="menor2">&nbsp; 0.1&nbsp; (primeira vers&aacute;o HTML5)</td></tr>
+    <tr><td class="menor2">23/03/2011 &nbsp; </td><td class="menor2">&nbsp; 2.4 &nbsp; </td>
+  <td class="menor2"><i>acertos no gerenciador de movimentos automaticos; acerto erro ao abrir janela Sobre</i></td></tr>
+    <tr><td class="menor2">10/03/2011 &nbsp; </td><td class="menor2">&nbsp; 2.3 &nbsp; </td>
+  <td class="menor2"><i>aparecer escolha de n&uacute;mero de discos em HTML, junto com bot&atilde;o para mover automaticamente</i></td></tr>
+    <tr><td class="menor2">08/03/2011 &nbsp;</td><td class="menor2">&nbsp; 2.2&nbsp; </td>
+  <td class="menor2"><i>alterada escolha de n&uacute;mero de discos</i>; internacionaliza&ccedil;&atilde;o e melhoria de algumas mensagens</td></tr>
+    <tr><td class="menor2">19/05/2008 &nbsp;</td><td class="menor2">&nbsp; 2.0&nbsp; </td>
+  <td class="menor2"><i>desfazer &uacute;ltimo movimento</i>; <i>rever todos os movimentos</i>; internacionaliza&ccedil;&atilde;o; melhoria de mensagens</td></tr>
+  </table></td>
+ </tr>
+</table>
+-->
+</p>
+
+</center>
+
+<!-----------------------Rodape---------------------------------------->
+
+<center>
+<table width=750>
+ <tr><td width="100" valign="bottom">
+  <div align="left"><a href="../index.html"><img src="../../imagens/setaE.gif" width="30" height="18" border="0"></a><br/>
+       <font face="Arial,Helvetica"><strong>voltar</strong></font></div></td>
+<td align=center>
+<br/>
+<table width=550 border=0 cellspacing=0 cellpadding=0>
+  <tr>
+    <td align=center><a href="../../cursos.html"><img src="../../imagens/L1.gif" border="0"></a></td>
+    <td align=center><a href="../index.html"><img src="../../imagens/L2.gif" border="0"></a></td>
+    <td align=center ><a href="../../problemas/index.html"><img src="../../imagens/L3.gif" border="0"></a></td>
+    <td align=center><a href="../../programas/index.html"><img src="../../imagens/L5.gif" border="0"></a></td>
+  </tr>
+  <tr> 
+    <td colspan=5 align=center><img src="../../imagens/Blue.jpg" width="550" height=3></td>
+  </tr>
+  </table>
+   <table width=650 border=0 cellspacing=0 cellpadding=0>
+    <tr> 
+    <td colspan=2 align=left><a href="http://www.usp.br"><img src="../../imagens/L6.gif" border="0"></a></td>
+    <td colspan=3 align=right><a href="http://www.ime.usp.br"><img src="../../imagens/L7.gif" border="0"></a></td>
+  </tr>
+  </table>
+</td></tr></table>
+</center>
+</body>
+</html>

+ 58 - 0
ihanoi/index_ihanoi.html

@@ -0,0 +1,58 @@
+<!--
+
+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 as configurações" onclick="reiniciar();">Reiniciar</button> &nbsp;
+ <button id="rever"     class="classeBotao classeBotaoR" title="Rever os movimentos" 	  	onclick="rever();"	  >Resolver </button> &nbsp;
+ <button id="automatic"	class="classeBotao classeBotaoR" title="Resolver automaticamente" 	onclick="autoCheck();">Automático</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;
+ <!--TODO: Resolver torre com 6 discos gera erro de renderiazação-->
+ </div>
+</div>
+
+</body>
+</html>

+ 186 - 0
ihanoi/itarefa1.html

@@ -0,0 +1,186 @@
+<!DOCTYPE html>
+<!--
+
+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
+v0.5: 2020/11/23
+v0.1: 2020/07/28
+
+-->
+
+<html  dir="ltr" lang="pt-br" xml:lang="pt-br">
+<head>
+  <title>Protótipo para uso de iMA - com iHanóiL</title>
+  <link rel="stylesheet" href="css/ihanoi_style.css" />
+  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+  <meta name="keywords" content="moodle, Testes iMA HTML" />
+</head>
+
+<body >
+
+<h4>Testar iHanói como <b title="Módulo de Aprendizagem interativa na Internet">iMA</b></h4>
+<p>
+Esta página simula a visão do aprendiz usando o pacote <a href="" title="página principal do projeto iTarefa">iTarefa</a>.
+O professor poderia posteriormente examinar a
+<a href="itarefa2.html" title="veja simulação do envio">tarefa enviada pelo aprendiz</a>.
+</p>
+
+<p>
+<strong>Enunciado:</strong>&nbsp; Resolver o problema das Torres de Hanói com 2 discos.<br/>
+Necessário mover todos os discos da haste A para a haste C com mínimo número de movimentos.<br/>
+<strong>Atividade independente</strong><br/>
+<strong>Número de tentativas:</strong>&nbsp;ilimitada&nbsp;&nbsp;&nbsp;<strong>Nota da atividade</strong>&nbsp;0</p>
+
+<div class="box generalbox py-3">
+<!-- script estava aqui!!! -->
+
+<center>
+
+<form name='formEnvio' id='formEnvio' onsubmit="return false;">
+<!-- se fosse efetivamente enviar para servidor Moodle/iTarefa
+     method='post' enctype='multipart/form-data'
+     action ='http://localhost/saw/mod/iassign/view.php?action=get_answer&id=18612&iassign_current=5425&userid_iassign=3'
+-->
+
+<script>function full_screen() {
+  if('fullscreenEnabled' in document || 'webkitFullscreenEnabled' in document || 'mozFullScreenEnabled' in document || 'msFullscreenEnabled' in document) {
+    if(document.fullscreenEnabled || document.webkitFullscreenEnabled || document.mozFullScreenEnabled || document.msFullscreenEnabled) {
+      var element = document.getElementsByName('iLM').item(0);
+      //requestFullscreen is used to display an element in full screen mode.
+      if('requestFullscreen' in element) {
+        element.requestFullscreen();
+      } 
+      else if ('webkitRequestFullscreen' in element) {
+        element.webkitRequestFullscreen();
+      } 
+      else if ('mozRequestFullScreen' in element) {
+        element.mozRequestFullScreen();
+      } 
+      else if ('msRequestFullscreen' in element) {
+        element.msRequestFullscreen();
+      }
+    }
+  } else {
+    //$('.expand_button').addClass('disabled');
+  }
+  }
+</script>
+  <div style='width: 1100px;text-align: right;'>
+  <div onClick='full_screen()' style='color: blue; cursor: pointer; display: contents;'>Tela cheia</div>
+  </div>
+  <iframe frameborder="0" name="iLM"
+          src="ihanoi.html?1=1&iLM_PARAM_AssignmentURL=true&iLM_PARAM_Assignment=http%3A%2F%2Flocalhost%2Fihanoi%2Fexer2.ihn&iLM_PARAM_SendAnswer=false&lang=pt"
+          style="width: 1100px; height: 500px;"  id="iLM">
+  <!--
+  src="ihanoi.html?1=1&iLM_PARAM_AssignmentURL=true&iLM_PARAM_Assignment=http%3A%2F%2Fmilanesa.ime.usp.br%2Fihanoi%2Fexer2.ihn&iLM_PARAM_SendAnswer=false&lang=pt"
+  src="index.html?1=1&iLM_PARAM_AssignmentURL=true&iLM_PARAM_Assignment=http%3A%2F%2Flocalhost%2Fihanoi%2Fexer2.ihn&iLM_PARAM_SendAnswer=false&lang=pt"
+  src="index.html?1=1&iLM_PARAM_AssignmentURL=true&iLM_PARAM_Assignment=&iLM_PARAM_SendAnswer=false&lang=pt"
+  exer2_solucao.ihn
+  exer2.ihn
+  -->
+</iframe>
+  <script type='text/javascript'>
+  //<![CDATA[
+  var strAnswer = '';
+  var evaluationResult = '';
+  var comment = '';
+
+  //D x alert('./mod/iassign/ilm_handlers/html5.php: 1 window.frames.iLM.getEvaluation=' + window.frames.iLM.getEvaluation); // sem efeito!
+  //D x alert('./mod/iassign/ilm_handlers/html5.php: 1 window.frames.iLM.getEvaluation=' + window.frames.iLM.getEvaluation()); // sem efeito!  
+  // alert('./mod/iassign/ilm_handlers/html5.php: 1 window.frames[0].getEvaluation=' + window.frames[0].getEvaluation()); // sem efeito!  
+
+
+  // Ao clicar no botao "Enviar solucao" cai aqui
+  function jsAnalyseAnswer () {
+    // iVProgH5 will call function 'getEvaluationCallback(...)': /var/www/html/ivprogh5/js/services.js
+    // 'getEvaluation()' calls 'js/services.js : endTest function(index)' that calls 'getEvaluationCallback(apro/100);'
+    // sumEval = getSummation(); alert('mod/iassign/ilm/ifractions_5/index.html: sumEval = ' + sumEval);
+    //CUIDADO 2017/11/22 - usar 'window.frames.iLM' resultava neste ponto 'TypeError: window.frames.iLM.getEvaluation is not a function'
+    //CUIDADO resp = window.frames.iLM.getEvaluation();
+    resp = window.frames[0].getEvaluation(); // pegar diretamente a primeira janela (nao pode haver outra!)
+    alert("Resultado da avaliação automática: nota=" + resp + " (dentre 0 e 1)");
+
+    if (resp == 'undefined') // in './mod/iassign/ilm/ivprog-html/js/services.js'; './mod/iassign/ilm/ivprog-html/main.html'
+      return false;
+
+    return false;
+    }
+
+  // ./mod/iassign/ilm/ivprog-html/js/services.js : call this to define the variable 'evaluationResult'
+  function getEvaluationCallback (evaluation) {
+    evaluationResult = evaluation;
+    //leo 2017/11/22 strAnswer = window.frames.iLM.getAnswer();
+    strAnswer = window.frames[0].getAnswer();
+    // alert('getEvaluationCallback(...)' + evaluation + ', strAnswer=' + strAnswer);
+    comment = document.formEnvio.submission_comment.value;
+    //leo alert('getEvaluationCallback: enviando evaluationResult=' + evaluation + ', strAnswer=' + strAnswer);
+
+    //leo
+    if ((strAnswer==null || strAnswer=='' || strAnswer==-1) && (comment==null || comment=='')) { // undefined
+      alert('Atividade enviada sem conteúdo.'); // 'Activity sent without content.'
+      return false; // error...
+      }
+    else {
+      document.formEnvio.iLM_PARAM_ArchiveContent.value = strAnswer;
+      document.formEnvio.iLM_PARAM_ActivityEvaluation.value = evaluationResult;
+      document.formEnvio.iLM_PARAM_RealGrade.value = evaluation;
+      //D alert(strAnswer);
+      document.formEnvio.submit();
+      return true; // success
+      }
+     }
+
+  // ./mod/iassign/ilm/
+  function getConstruction () {
+     strAnswer = window.frames[0].getAnswer();
+     alert("Movimentos realizados até agora (no formato iHanói):\n" + strAnswer);
+     return true;
+     }
+  //]]>
+  </script>
+
+ <input type='hidden' name='iLM_PARAM_ArchiveContent' value=''>
+ <input type='hidden' name='iLM_PARAM_ActivityEvaluation' value=''>
+ <input type='hidden' name='iLM_PARAM_RealGrade' value=''>
+ <input type='hidden' name='submission_comment'>
+  <!-- load button -->
+  <!-- input type=button value='Enviar solução'
+       onClick='javascript:window.jsAnalyseAnswer();' title='Clique aqui para enviar sua resposta' -->
+<p>
+  <button value='Avaliar solução' onClick='javascript:window.jsAnalyseAnswer();'
+          title='Clique aqui para avaliar/enviar sua resposta' />Avaliar</button>
+  &nbsp;&nbsp;
+  <button value='Examinr solução' onClick='javascript:window.getConstruction();'
+          title='Clique aqui para avaliar/enviar sua resposta' />Examinar</button>
+</p>
+</center>
+<p>
+  Um <b title="Módulo Interativo de Aprendizagem">iMA</b> pode ser integrado ao
+  <a href="https://moodle.org/" title="página princial do gerenciador de cursos de código livre Moodle">Moodle</a>
+  por meio de nosso pacote livre
+  <a href="https://moodle.org/plugins/index.php?q=iassign" title="página do iTarefa na área do Moodle - versão desatualizada">iTarefa</a>.
+  <br/>
+  Porém, até submetermos a última versão que permite integração de <i>iMA</i> codificados em <i>JavaScript</i>, por favor, 
+  utilize a 
+  <a href="http://www.matematica.br/ia" title="página oficial do iTarefa">versão disponível no iMática</a>.
+</p>
+
+
+</form>
+</center>
+
+<hr/>
+
+<div class="foot">
+<a href="http://www.usp.br/line" title="página do LInE">Laboratório de Informática na Educação (LInE)</a><br/>
+<a href="http://www.matematica.br/ihanoi" title="página do iHanói no iMática">iHanói/iMática</a><br/>
+</div>
+
+
+</body>
+</html>

+ 634 - 0
ihanoi/js/ihanoi.js

@@ -0,0 +1,634 @@
+/* 
+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) {
+  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.lgo("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 || (nDiscos == 1 && contador == 1))
+            { // Moveu para haste C com minimo
+                return 4;
+            }
+            return 3; // Moveu para haste C
+        }
+        if (haste == 1)
+        {
+            if (contador == 2^nDiscos - 1 || (nDiscos == 1 && contador == 1)) 
+            { // Moveu para haste B com minimo
+                return 2;
+            }
+        return 1; // Moveu para a haste B
+        }
+    }
+    return 0; //Falha em mover tudo
+}
+
+/* Atualizacao botao automático e velocidade
+ * Resolve a torre de hanoi usando recursão
+ * TODO: Solucionar renderização
+ */
+function solve(n, origem, destino, aux)
+{
+    //alert("Ciclo: " + counter + "; movimento: " + mov)
+    if (n == 1)
+    {
+        // O menor disco (1) se move livremente em qualquer haste
+        movaHaste(origem);
+        movaHaste(destino);
+        return;
+    }
+    // Retirar discos menores "do caminho"
+    solve(n - 1, origem, aux, destino); 
+    
+    // Mover maior disco para o destino
+    movaHaste(origem);
+    movaHaste(destino);    
+
+    /* Problema: sleep() têm sucesso em atrasar o algoritmo
+     * Porém a renderização por algum motivo não acontece em paralelo
+     * Isso impede o aluno de assistir os movimentos acontecerem
+     */
+
+    //Mover os discos menores para cima do maior novamente
+    solve(n - 1, aux, destino, origem);
+}
+
+// Verifica posicao dos discos e chama a funcao recursiva
+function autoCheck()
+{
+    reiniciar(nDiscos); //formula nao funciona caso os discos estejam desorganizados
+    solve(nDiscos, 0, 2 ,1);
+}
+
+// Mover disco do topo da haste 'clickDe' para a haste 'hi' (sem 'clickDe' definido)
+function movaHaste (hi)
+{
+    var strHaste = pegaHaste(hi); //Retorna haste A, B ou C para 0, 1 e 2 respectivamente
+    var de0 = clickDe, para0 = clickPara;
+    if (clickDe == -1 && clickPara == -1) // Começo do movimento
+    {
+        clickDe = hi;
+        topoDe = pegaTopoHaste(clickDe); // Pega disco no topo da haste
+        if (topoDe == -1)                // Erro: sem discos na haste
+        {
+            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;
+        topoDe = pegaTopoHaste(clickDe);     // devolve indice topo de haste
+        topoPara = pegaTopoHaste(clickPara); // devolve indice topo de haste
+        
+        if (clickDe == clickPara) // Erro: origem e destino são iguais
+        {
+            str_haste = pegaHaste(clickDe);
+            mensagem = msgDeParaIguais + " (haste " + str_haste + ")";
+            console.log("Erro: Tentando mover disco para a mesma haste! (haste " + str_haste + ")");
+            clickDe = clickPara = -1; // Restart no movimento
+            desenhaMensagem();
+            return -1;
+        }
+        
+        if (topoPara > -1 && matHastes[clickDe][topoDe] > matHastes[clickPara][topoPara]) // Erro: disco maior sobre menor
+        { 
+            mensagem = mensagem2_1 + " (" + matHastes[clickDe][topoDe] + mensagem2_2 + matHastes[clickPara][topoPara] + ")";
+            clickDe = clickPara = -1; // Restart no movimento
+            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 para haste C; 4=moveu tudo para 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;
+        }
+        desenhaTudo();
+    }
+    console.log("movaHaste(hi): final");
+    return 1;
+}
+
+
+// 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; //  "stava revendo movimentação, mas ao mover manualmente, a revisão foi finalizada!
+        limparRevisao();
+        desenhaMensagem(); //sem efeito, 'sleep(.)' nao permite aparecer a mensagem
+    }
+}
+
+
+
+// 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
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
+alert("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");