integration-functions.js 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  1. /*
  2. iHano'i
  3. http://www.usp.br/line
  4. Uso: localhost/ihanoi/index.html?n=3&lang=pt
  5. @TODO ainda nao implementado multi-lingua
  6. Leo^nidas de Oliveira Branda~o
  7. v0.5: 2020/11/22 (getiLMContent(): se 'iLMparameters.iLM_PARAM_Assignment' vazio, nem tenta carregar arquivo do iHanoi (IHN))
  8. v0.4: 2020/08/03
  9. v0.1: 2020/07/31
  10. v0: 2020/07/28
  11. */
  12. console.log("integration-functions.js: inicio");
  13. // Variaveis externas
  14. // nDiscos = numero de disco definido na funcao principal iHanoi
  15. // contador = contador de numero de movimentos realizados
  16. // topoHasteA, topoHasteB, topoHasteC = indice na haste do maior disco nela
  17. const NOTA_MINIMO_B = 0.8; // alvo nao era haste B, descontar
  18. const ESPERA = 0; // retardo para permitir ver movimentos qdo carga automatica
  19. // Funcao para ler parametros informados pelo iTarefa via URL
  20. // Apesar de nao ser obrigatorio, sera muito útil para capturar os parametros
  21. function getParameterByName (name) {
  22. var match = RegExp('[?&]' + name + '=([^&]*)').exec(window.location.search);
  23. return match ? decodeURIComponent(match[1].replace(/\+/g, ' ')) : null;
  24. }
  25. // Criando um vetor com os parametros informados pelo iTarefa
  26. // Observe que para cada parametro, e realizada a chamada do metodo getParameterByName, implementado acima
  27. var iLMparameters = {
  28. // 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
  29. iLM_PARAM_Authoring: getParameterByName("iLM_PARAM_Authoring"), // if defined, then is teacher, allow edit
  30. iLM_PARAM_ServerToGetAnswerURL: getParameterByName("iLM_PARAM_ServerToGetAnswerURL"),
  31. iLM_PARAM_SendAnswer: getParameterByName("iLM_PARAM_SendAnswer"),
  32. iLM_PARAM_AssignmentURL: getParameterByName("iLM_PARAM_AssignmentURL"),
  33. iLM_PARAM_Assignment: getParameterByName("iLM_PARAM_Assignment"),
  34. iLM_PARAM_TeacherAutoEval: getParameterByName("iLM_PARAM_TeacherAutoEval"),
  35. lang: getParameterByName("lang")
  36. };
  37. // Funcao chamada pelo iTarefa quando o professor finaliza a criacao da atividade
  38. // ou quando o aluno finaliza a resolucao do exercicio
  39. // O retorno e um JSON com os dados do exercicio ou da resolucao
  40. // Esse retorno sera armazenado no banco de dados do Moodle, pelo iTarefa
  41. function getAnswer () {
  42. // Se o parametro "iLM_PARAM_SendAnswer" for false,
  43. // entao trata-se de resolucao de atividade
  44. if (iLMparameters.iLM_PARAM_SendAnswer == 'false') {
  45. // Montar o retorno da resposta do aluno
  46. var studentAnswer = "Numero de discos: " + nDiscos + " \nQuantidade de Movimentos: " + contador + " \nMovimentos:";
  47. for (var i = 0; i < vetorMovimentos.length; i++) {
  48. studentAnswer += "\n" + vetorMovimentos[i]; // vetorMovimentos[]: global definida em 'ihanoi.js'
  49. }
  50. // alert(studentAnswer);
  51. return studentAnswer; // teacherReturn;
  52. } else { //se for o professor acessando, mostra a pagina de elaboracao
  53. return "Número de Discos: " + nDiscos;
  54. }
  55. }
  56. function potencia2 (n) {
  57. var pot = 1, i;
  58. for (i=0; i<n; i++) pot *= 2;
  59. return pot;
  60. }
  61. // Funcao chamada pelo iTarefa para receber a nota do aluno na atividade
  62. // O retorno e um valor entre 0.0 e 1.0
  63. function getEvaluation () {
  64. if (iLMparameters.iLM_PARAM_SendAnswer == 'false') {
  65. // Calculo da nota: resposta correta = 1 (C em minimo), 0.7 (B em minimo), errada = 0
  66. var aux;
  67. var nota;
  68. var minimo = potencia2(nDiscos)-1; // 2^nDiscos-1
  69. if (topoHasteC+1 == nDiscos) { // moveu todos para C
  70. if (contador == minimo) { // com o minimo
  71. nota = 1;
  72. aux = 1;
  73. }
  74. else {
  75. nota = minimo / contador; // quanto mais movimentos, menor nota
  76. aux = 2;
  77. }
  78. }
  79. else
  80. if (topoHasteB+1 == nDiscos) { // moveu todos para B
  81. if (contador == minimo) { // com o minimo
  82. nota = NOTA_MINIMO_B; // alvo nao era haste B, descontar
  83. aux = 3;
  84. }
  85. else {
  86. nota = minimo / contador; // quanto mais movimentos, menor nota
  87. aux = 4;
  88. }
  89. }
  90. else {
  91. nota = 0;
  92. aux = 5;
  93. }
  94. // getEvaluation(): topoHasteB=2, topoHasteC=-1, nota=0 :: 4
  95. // getEvaluation(): topoHasteB=-1, topoHasteC=2, nota=0 :: 2 minimo=0 contador=7 0
  96. console.log("getEvaluation(): topoHasteB=" + topoHasteB + ", topoHasteC=" + topoHasteC + ", nota="+nota + " :: " + aux + " minimo="+minimo+" contador="+contador+" "+(minimo/contador));
  97. // A chamada do metodo abaixo e obrigatoria!
  98. // Observe que a chamada parte do iLM para o iTarefa
  99. //D alert("nota="+nota+"\n"+msg);
  100. parent.getEvaluationCallback(nota); //TODO NAO usado!!!!????
  101. return nota;
  102. }
  103. }
  104. // Formato do arquivo iHanoi: exercicio, apenas com numero de discos
  105. // Numero de Discos: 2
  106. // Formato do arquivo iHanoi: resposta do aluno, com discos e movimentos
  107. // Numero de Discos: 2
  108. // Quantidade de Movimentos: 3
  109. // Movimentos:
  110. // 0 1
  111. // 0 2
  112. // 1 2
  113. function decodificaArquivo (strContent) {
  114. var linhas = strContent.split("\n");
  115. var msg = "";
  116. var nlinhas = linhas.length, nmov;
  117. var itens, i1, i2;
  118. if (nlinhas>0) {
  119. itens = linhas[0].split(":");
  120. nDiscos = eval(itens[1]);
  121. nDiscos0 = nDiscos;
  122. if (iLMparameters.iLM_PARAM_Authoring == 'true')
  123. setExercise(true); // global definidas em 'ihanoi.js': indica tratar-se de exercicio
  124. else
  125. setExercise(false); // global definidas em 'ihanoi.js': indica tratar-se de exercicio
  126. //D alert("decodificaArquivo: iLM_PARAM_Authoring=" + iLMparameters.iLM_PARAM_Authoring);
  127. // nDiscos = 0;
  128. reiniciar(); // Funcao externa: reinicia iHanoi
  129. if (nlinhas>1) {
  130. itens = linhas[1].split(":");
  131. nmov = itens[1]; // numero de movimentos do aluno
  132. contador = nmov;
  133. }
  134. if (nlinhas>2) {
  135. contador = 0; // global definidas em 'ihanoi.js': conta numero de movimentos
  136. for (i=3; i<nlinhas; i++) { // pula linha com "Movimentos:"
  137. itens = linhas[i].split(" ");
  138. if (itens=="" || itens.length<2) {
  139. console.log("Erro: arquivo nao está no formato iHanoi. Linha " + i + ": " + linhas[i]);
  140. return;
  141. }//decodificaArquivo: "0,,1
  142. i0 = 0; i1 = 1;
  143. if (itens.length==3) // se decomposicao tratar "0 1" como {0,,1}
  144. i1 = 2;
  145. clickDe = itens[i0]; // global definidas em 'ihanoi.js': haste de partida
  146. clickPara = -1; // global definidas em 'ihanoi.js': haste de chegada
  147. //D alert("decodificaArquivo: \"" + itens + "\":" + clickDe + " - " + itens[i1]);
  148. movaHaste(eval(itens[i1])); // funcao definidas em 'ihanoi.js': mover de hastes - 'eval(.)' elimina eventual \n ou ' '
  149. desenhaTudo(); // funcao definidas em 'ihanoi.js': desenhar novo configuracao
  150. // sleep(ESPERA);
  151. msg += "\n" + linhas[i];
  152. }
  153. }
  154. }
  155. } // function decodificaArquivo(strContent)
  156. // Funcao para que o iMA leia os dados da atividade fornecidos pelo iTarefa
  157. function getiLMContent () {
  158. var msg = "";
  159. // O parametro "iLM_PARAM_Assignment" fornece o URL do endereco que deve ser
  160. // requisitado via XMLHttpRequest() para a captura dos dados da atividade
  161. var pagina = iLMparameters.iLM_PARAM_Assignment;
  162. var txtFile;
  163. var data = -1;
  164. //D console.log("integration-functions.js: getiLMContent(): iLMparameters.iLM_PARAM_TeacherAutoEval=" + iLMparameters.iLM_PARAM_TeacherAutoEval); //D
  165. //D console.log("integration-functions.js: getiLMContent(): iLMparameters.iLM_PARAM_Assignment=" + iLMparameters.iLM_PARAM_Assignment);
  166. if (iLMparameters.iLM_PARAM_Assignment == null) {
  167. console.log("integration-functions.js: getiLMContent(): NAO existe arquivo IHN para ser carregado (iLMparameters.iLM_PARAM_Assignment vazio), finalize");
  168. return;
  169. }
  170. if (iLMparameters.iLM_PARAM_TeacherAutoEval != null) {
  171. try {
  172. parent.getAutoEvalOriginalData(); // funcao definida pelo iTarefa que devolve o conteudo original do exercicio atual
  173. } catch (Error) {
  174. console.log("integration-functions.js: getiLMContent(): erro ao tentar executar funcao 'getAutoEvalOriginalData()'");
  175. } // se nao esta' em re-avaliacao => NAO esta' definida 'parent.getAutoEvalOriginalData()'
  176. // alert("integration-functions.js: actual exercise=" + data);
  177. teacherAutoEval(data);
  178. console.log("integration-functions.js: getiLMContent(): final (apos ler arquivo IHN)");
  179. return;
  180. }
  181. txtFile = new XMLHttpRequest(); // preparar coneccao HTTP para requisitar um arquivo IHN
  182. console.log("integration-functions.js: getiLMContent(): tenta pegar arquivo de " + pagina);
  183. // window.location : href = a URL inteira; pathname = ; hostname = apenas o nome do servidor
  184. txtFile.open("GET", pagina, true); // true=>asincrono - mas ambos estao resultando (arq. IHN nao passar teste XML...): XML Parsing Error: syntax error
  185. txtFile.send(); // so' pode fechar apos 3o passo
  186. txtFile.responseType="text"; // Evita advertencia: XML Parsing Error: syntax error
  187. txtFile.onreadystatechange = function () {
  188. if (txtFile.readyState === 4) { // Makes sure the document is ready to parse.
  189. if (txtFile.status === 200) { // Makes sure the file exists.
  190. // 3o passo: por ultimo chega aqui!
  191. var nDiscos0;
  192. nDiscos0 = nDiscos;
  193. allText = txtFile.responseText;
  194. texto = allText; // define global 'texto'
  195. // processar conteudo de INH
  196. decodificaArquivo(allText);
  197. }
  198. //else alert("Erro 2"); // 2o passo: passa depois aqui
  199. }
  200. //else alert("Erro 1"); // 1o passo: passa primeiro aqui
  201. }
  202. console.log("integration-functions.js: getiLMContent(): final");
  203. } // function getiLMContent()
  204. // Adicionamos a diretiva .ready(), para que quando a pagina HTML estiver carregada,
  205. // seja verificado qual a visualizacao deve ser apresentada: se a area de construcao
  206. // de atividade ou de resolucao. E no caso de ser resolucao, os dados da atividade
  207. // precisam ser consultados, pelo metodo implementado acima, o getiLMContent()
  208. // Pegar conteudo da ativida iMA
  209. getiLMContent();
  210. function sleep (milliseconds) {
  211. var startSleep = new Date().getTime();
  212. for (var i = 0; i < 1e7; i++) {
  213. if ((new Date().getTime() - startSleep) > milliseconds) {
  214. break;
  215. }
  216. }
  217. }
  218. // To be used with re-evaluation
  219. function teacherAutoEval (data) {
  220. var nDiscos0;
  221. nDiscos0 = nDiscos;
  222. alert("integration-functions.js: teacherAutoEval(.): " + data);
  223. // processar conteudo de INH
  224. decodificaArquivo(data);
  225. }
  226. console.log("integration-functions.js: final");