瀏覽代碼

Update 'js/iassign-integration-functions.js'

Now version 2025/06/10 can load IVPH file with Portugol syntax (under iLM_PARAM_Assignment parameter). See function prepareActivityToStudent(.).
leo 3 月之前
父節點
當前提交
6521e250e3
共有 1 個文件被更改,包括 138 次插入96 次删除
  1. 138 96
      js/iassign-integration-functions.js

+ 138 - 96
js/iassign-integration-functions.js

@@ -1,16 +1,16 @@
 // iVProg - www.usp.br/line/ivprog
 // LInE - Free Education, Private Data
+// Version: 2025/06/10 (now can load IVPH file with Portugol sintax throgh iLM_PARAM_Assignment parameter)
 
-
-// Funcao para ler parametros informados pelo iTarefa via URL
-// Apesar de nao ser obrigatorio, sera muito util para capturar os parametros
+// Function to read parameters informed by iAssign (URL)
+// It is not mandatory to any iLM, but could be usefull to read special parameters
 function getParameterByName (name, defaultReturn = null) {
   var match = RegExp('[?&]' + name + '=([^&]*)').exec(window.location.search);
   return match ? decodeURIComponent(match[1].replace(/\+/g, ' ')) : defaultReturn;
   }
 
-// Criando um object com os parametros informados pelo iTarefa
-// Observe que para cada parametro, e realizada a chamada do metodo getParameterByName, implementado acima
+// To create object with parameters informed by iAssign
+// To each parameter is performed a calling to the getParameterByName method (above)
 var iLMparameters = {
   iLM_PARAM_ServerToGetAnswerURL: getParameterByName("iLM_PARAM_ServerToGetAnswerURL"),
   iLM_PARAM_SendAnswer: getParameterByName("iLM_PARAM_SendAnswer"),
@@ -60,22 +60,22 @@ function configAuxiliarProgrammingType (form_element) {
     map[obj.name] = obj.value;
     return map;
     }, {});
-
   return temp;
   }
 
-// Funcao chamada pelo iTarefa quando o professor finaliza a criacao da atividade
-// ou quando o aluno finaliza a resolucao do exercício
-// O retorno e um JSON com os dados do exercício ou da resolucao
-// Esse retorno sera armazenado no banco de dados do Moodle, pelo iTarefa
+// This is one of 2 essencial funcions to any iLM
+// This function allow iAssign to call iLM (here iVProg) to return the student answer
+// It is also used when teacher is finishing the iAssign activity
+// The returned answer will be registered by Moodle through iAssign
 function getAnswer () {
+
   var objAnswer = new Object();
   objAnswer.version = '1.0';
 
-  // Se o parametro "iLM_PARAM_SendAnswer" for false,
-  // entao trata-se de resolucao de atividade
+  // If parameter "iLM_PARAM_SendAnswer" is false,
+  // then it the case of one answer to the activity
   if (iLMparameters.iLM_PARAM_SendAnswer == 'false') {
-    // Montar o retorno com a resposta do aluno
+    // Build the text with the student answer
 
     objAnswer.code = generator();
     objAnswer.test_cases = ivprogCore.getTestCases();
@@ -98,9 +98,12 @@ function getAnswer () {
         "filter": []
         };
       }
+
     return JSON.stringify(objAnswer, null, 4);
+
   } else {
     objAnswer.test_cases = prepareTestCases();
+
     objAnswer.settings = {
       "programming": configAuxiliarProgrammingType($('form[name="settings_programming_type"]')),
       "functions": configAuxiliar($('form[name="settings_functions"]')),
@@ -117,12 +120,13 @@ function getAnswer () {
     }
   }
 
+
 function prepareTestCases () {
   var test_cases_array = $('form[name="test_cases"]').serializeArray();
   var cases = [];
-
   for (var i = 0; i < test_cases_array.length; i = i + 2) {
     var temp = new Object();
+
     temp.input = [];
     temp.output = [];
 
@@ -132,7 +136,7 @@ function prepareTestCases () {
         temp.input.push(inps[j]);
         }
       }
-    
+
     var outs = test_cases_array[i+1].value.match(/[^\r\n]+/g);
     if (outs) {
       for (var j = 0; j < outs.length; j++) {
@@ -146,14 +150,14 @@ function prepareTestCases () {
   return cases;
   }
 
-// Funcao chamada pelo iTarefa para receber a nota do aluno na atividade
-// O retorno e um valor entre 0.0 e 1.0
+// This is one of 2 essencial funcions to any iLM
+// This function is called by iAssign to get access to the student grade in the activity
+// The returned value must be between 0 and 1 (real)
 function getEvaluation () {
   if (iLMparameters.iLM_PARAM_SendAnswer == 'false') {
-    // A chamada do metodo abaixo e obrigatoria!
-    // Observe que a chamada parte do iLM para o iTarefa
-    //parent.getEvaluationCallback(window.studentGrade);
-
+    // The code bellow is mandatory to the iLM
+    // Observe that the calls is originated here (in the iLM) to the iAssign
+    //x parent.getEvaluationCallback(window.studentGrade);
     var canRunAssessment = runCodeAssessment();
     if (canRunAssessment === -1) {
       parent.getEvaluationCallback(-1);
@@ -170,38 +174,38 @@ var settingsFilter = null;
 var algorithm_in_ilm = null;
 var previousContent = null;
 
-// Funcao para que o iMA leia os dados da atividade fornecidos pelo iTarefa
+// Function to iLM read content provided by iAssign
 function getiLMContent () {
-  // O parametro "iLM_PARAM_Assignment" fornece o URL do endereco que deve ser
-  // requisitado via AJAX para a captura dos dados da atividade
+  // The parameter "iLM_PARAM_Assignment" provides the URL where AJAX must get the file content (*.ivph)
   $.get(iLMparameters.iLM_PARAM_Assignment, function (data) {
-    //professor invocou a avaliacao automatica dos exercícios do bloco
+    // Teacher calls the automatic evaluation to exercices block
     if (iLMparameters.iLM_PARAM_TeacherAutoEval != null) {
       teacherAutoEval(data);
-      //nao deve exibir nenhuma interface...
+      // do not presents any interface (background process)
       return;
-    } else if (iLMparameters.iLM_PARAM_SendAnswer == 'false') {
-      // Aluno esta trabalhando em alguma atividade:
+    } else if (iLMparameters.iLM_PARAM_SendAnswer == 'false' || iLMparameters.iLM_PARAM_SendAnswer == undefined) {
+      // Student is working in one activity
       previousContent = data;
       prepareActivityToStudent(data);
-    } else { // Professor esta editando uma atividade:
+    } else { // Teacher is editing one activity
+      // console.log("getiLMContent(): iLMparameters.iLM_PARAM_SendAnswer=" + iLMparameters.iLM_PARAM_SendAnswer);
       previousContent = data;
       prepareActivityToEdit(data);
       }
 
     window.block_render = false;
     renderAlgorithm();
-    });
-  }
+  });
+}
 
 function prepareActivityToEdit (ilm_cont) {
   //var content = JSON.parse(ilm_cont.split('\n::algorithm::')[0]);
-  // Ver arquivo js/util/iassignHelpers.js
+  // See file 'js/util/iassignHelpers.js'
   var content = ivprogCore.prepareActivityToStudentHelper(ilm_cont).getOrElse(null);
   if (!content) {
     showInvalidData();
     return;
-    }
+  }
   var testCases = ivprogCore.getTestCases();
 
   settingsProgrammingTypes = content.settingsProgrammingType;
@@ -210,8 +214,10 @@ function prepareActivityToEdit (ilm_cont) {
   settingsFunctions = content.settingsFunctions;
   settingsFilter = content.settingsFilter;
 
-  for (var i = 0; i < testCases.length; i++) {
-    addTestCase(testCases[i]);
+  if (testCases==undefined || testCases=="")
+    console.error("iassign-integration-functions.js: prepareActivityToEdit(.): testCases undefined...");
+  else {
+    for (var i = 0; i < testCases.length; i++) { addTestCase(testCases[i]); }
     }
 
   if (content.algorithmInIlm != null) {
@@ -288,18 +294,31 @@ function prepareActivityToStudent (ilm_cont, ignore_logs = false) {
     var jsonObj = JSON.parse(ilm_cont);
     ivprogCore.prepareActivityToStudentHelperJSON(jsonObj);
 
-    if (ivprogCore.getTestCases())
-      $('.assessment_button').removeClass('disabled');
+    if (ivprogCore.getTestCases()) {
+      //D console.log("iassign-integration-functions.js!prepareActivityToStudent(.): ivprogCore.getTestCases");
+      $('.assessment_button').removeClass('disabled'); // remove 'disable' from evaluation button
+      }
 
     renderAlgorithm();
 
     $('.ivprog_visual_panel').removeClass("loading");
     return;
-    }
-  catch (e) {
-    console.log('Previous file format!');
+  } catch (e) {
+    console.log('iassign-integration-functions.js: try Portugol syntax');
     console.log(e);
-    console.log(ilm_cont);
+    console.log(ilm_cont); //D
+
+    // Try the plain Portugol algorithm
+    try {
+      console.log("prepareActivityToStudent(.): try plain language");
+      // var content = ivprogCore.prepareActivityToStudentHelper(ilm_cont, ignore_logs).getOrElse(null);
+      ivprogCore.setPreviousAlgorithm(ilm_cont); // load "code_obj = ivprogCore.parseCode(code)" and "parserCodeVisual(code_obj)"
+      renderAlgorithm();
+      $('.ivprog_visual_panel').removeClass("loading");
+      return;
+    } catch (e) {
+      console.log('iassign-integration-functions.js: not worked Portugal, try previou file format JSON!');
+      }
     }
 
   // Previous file format:
@@ -308,22 +327,30 @@ function prepareActivityToStudent (ilm_cont, ignore_logs = false) {
   if (!content) {
     $('.ivprog_visual_panel').removeClass("loading");
     showInvalidData();
+    console.log('iassign-integration-functions.js: empty content!');
     return;
     }
-  
-  // Casos de testes agora sao delegados ao tratamento apropriado pela funcao acima
-  // var testCases = content.testcases;
-  settingsProgrammingTypes = content.settingsProgrammingType;
-  settingsDataTypes = content.settingsDataTypes;
-  settingsCommands = content.settingsCommands;
-  settingsFunctions = content.settingsFunctions;
-  settingsFilter = content.settingsFilter;
+
+  // Now the "test-cases" are submitted to analysis of iLM/iVProg (using the abouve "includePreviousAlgorithm(.)" function
+  //var testCases = content.testcases; // not defined in 'js/util/iassignHelpers.js'
+  try { // js/util/iassignHelpers.js : settingsProgrammingType ; settingsDataTypes ; settingsCommands ; settingsFunctions ; algorithmInIlm ; settingsFilter
+    settingsProgrammingTypes = content.settingsProgrammingType; // js/visualUI/functions.js : settingsProgrammingTypes == "textual" (or "visual")
+    settingsDataTypes = content.settingsDataTypes; // "settings_data_types"
+    settingsCommands = content.settingsCommands;   // "settings_commands"
+    settingsFunctions = content.settingsFunctions; // "settings_functions"
+    settingsFilter = content.settingsFilter;       // ""
+    //testCases = content.testcases;
+  } catch (ex) {
+    console.log("iassign-integration-functions.js: Error! Not defined field of 'content' " + ex);
+    console.trace(); //D print execution stack
+    }
 
   if (content.algorithmInIlm != null) {
     algorithm_in_ilm = content.algorithmInIlm;
     includePreviousAlgorithm();
     }
-  $('.assessment_button').removeClass('disabled');
+  console.log("iassign-integration-functions.js!prepareActivityToStudent(.): assessment_button?");
+  $('.assessment_button').removeClass('disabled'); // with this command, all old format ivph file will enter with evaluation button enabled!!!
   $('.ivprog_visual_panel').removeClass("loading");
   renderAlgorithm();
 
@@ -333,38 +360,39 @@ function prepareActivityToStudent (ilm_cont, ignore_logs = false) {
     }
   }
 
-
-// Funcao para organizar se para criacao, visualizacao ou resolucao de atividade
+// Used to organize the creation, visualization or resolution of each activity
 function prepareEnvironment () {
   $('.div_to_body').click(function(e) {
     // trackingMatrix.push(adCoords(e, 1));
     ivprogCore.registerClick(e.pageX, e.pageY, e.target.classList['value']);
-    });
+  });
 
-  // Se iLM_PARAM_SendAnswer for false, entao trata-se de resolucao de atividade,
-  // portanto, a "DIV" de resolucao e liberada
+  // If 'iLM_PARAM_SendAnswer' is false, then it is the resolution of an activity,
+  // in this case, the "div" to resolution is presented
   if (iLMparameters.iLM_PARAM_SendAnswer == 'false') {
     //$('.resolucao').css("display","block");
     $('.ivprog_visual_panel').addClass("loading");
 
     getiLMContent();
 
-    // $('.div_to_body').mousemove(function(e) { trackingMatrix.push(adCoords(e, 0)); });
+    // $('.div_to_body').mousemove(function(e) {
+    //     trackingMatrix.push(adCoords(e, 0));
+    // });
+
     // $('.div_to_body').click(function(e) {
     //   // trackingMatrix.push(adCoords(e, 1));
     //   ivprogCore.registerClick(e.pageX, e.pageY, e.target.classList['value']);
     // });
   } else if (iLMparameters.iLM_PARAM_Assignment) {
-    // Caso nao esteja em modo de resolucao de atividade, a visualizacao no momento
-    // e para a elaboracao de atividade:
+    // If it is not an activity resolution, then the visualization mode must be "template construction"
     //$('.elaboracao').css("display","block");
 
-    // Se possuir o parametro iLMparameters.iLM_PARAM_Assignment, o professor
-    // esta editando uma atividade:
+    // If 'iLMparameters.iLM_PARAM_Assignment' parameter is present,
+    // then the teacher is editing the activity
     getiLMContent();
   } else {
     renderAlgorithm();
-    }
+  }
 
   if ((iLMparameters.iLM_PARAM_AssignmentURL == "true") && (iLMparameters.iLM_PARAM_SendAnswer == "true")) {
     prepareActivityCreation();
@@ -426,10 +454,10 @@ function blockAllEditingOptions () {
   $('.ui.dropdown.function_return.disabled').css('opacity', '1');
   $('.ui.dropdown.parameter_type.disabled').css('opacity', '1');
 
-
   ivprogCore.CodeEditor.disable(true);
   }
 
+
 function ivprogTextualOrVisual () {
   if (settingsProgrammingTypes) {
     if (settingsProgrammingTypes == "textual") {
@@ -447,7 +475,7 @@ function ivprogTextualOrVisual () {
         textual_code = textual_code.replace(/\\n/g,"\n");
         textual_code = textual_code.replace(/\\t/g,"\t");
         }
-      
+
       ivprogCore.CodeEditor.setCode(textual_code);
       ivprogCore.CodeEditor.disable(false);
       }
@@ -467,22 +495,25 @@ function iassingIntegration () {
     }
   }
 
-// Funcao para preparar a interface para o professor criar atividade:
+// To prepare the teacher's interface to create a new activity:
 function prepareActivityCreation () {
   var menuTab = $('<div class="ui top attached tabular menu">'
-    + '<a class="item active" data-tab="testcases">' + LocalizedStrings.getUI('text_teacher_test_case') + '</a>'
-    + '<a class="item" data-tab="algorithm">' + LocalizedStrings.getUI('text_teacher_algorithm') + '</a>'
-    + '<a class="item" data-tab="settings">' + LocalizedStrings.getUI('text_teacher_config') + '</a>'
-    + '</div>'
-    + '<div class="ui bottom attached tab segment active tab_test_cases" data-tab="testcases"></div>'
-    + '<div class="ui bottom attached tab segment tab_algorithm" data-tab="algorithm"></div>'
-    + '<div class="ui bottom attached tab segment tab_settings" data-tab="settings"></div>');
+        + '<a class="item active" data-tab="testcases">' + LocalizedStrings.getUI('text_teacher_test_case') + '</a>'
+        + '<a class="item" data-tab="algorithm">' + LocalizedStrings.getUI('text_teacher_algorithm') + '</a>'
+        + '<a class="item" data-tab="settings">' + LocalizedStrings.getUI('text_teacher_config') + '</a>'
+        + '</div>'
+        + '<div class="ui bottom attached tab segment active tab_test_cases" data-tab="testcases"></div>'
+        + '<div class="ui bottom attached tab segment tab_algorithm" data-tab="algorithm"></div>'
+        + '<div class="ui bottom attached tab segment tab_settings" data-tab="settings"></div>');
 
   menuTab.insertBefore('.add_accordion');
   $('.tabular.menu .item').tab();
+
   $('.main_title').remove();
   $('.ui.accordion').addClass('styled');
+
   $('<div class="content_margin"></div>').insertBefore($('.add_accordion').find('.content').find('.div_to_body'));
+
   $('<div class="ui checkbox"><input type="checkbox" name="include_algo" class="include_algo" tabindex="0" class="hidden"><label>'+LocalizedStrings.getUI('text_teacher_algorithm_include')+'</label></div>').insertAfter('.content_margin');
 
   var cases_test_div = $('<div></div>');
@@ -492,10 +523,13 @@ function prepareActivityCreation () {
   var config_div = $('<div></div>');
 
   $('.tab_settings').append(config_div);
+
   $('.ui.checkbox').checkbox();
+
   $('.tab_algorithm').append($('.add_accordion'));
 
   prepareTableSettings(config_div);
+
   prepareTableTestCases(cases_test_div);
 
   if (inIframe()) {
@@ -504,6 +538,7 @@ function prepareActivityCreation () {
   }
 
 function prepareTableTestCases (div_el) {
+
   var table_el = '<form name="test_cases"><table class="ui blue table"><thead><tr><th width="30px">#</th><th>'+LocalizedStrings.getUI('text_teacher_test_case_input')+'</th><th>'+LocalizedStrings.getUI('text_teacher_test_case_output')+'</th><th width="80px">'+LocalizedStrings.getUI('text_teacher_test_case_actions')+'</th></tr></thead>'
     + '<tbody class="content_cases"></tbody></table></form>';
 
@@ -516,11 +551,12 @@ function prepareTableTestCases (div_el) {
     + '</td></tr></table>';
 
   div_el.append(table_buttons);
-  div_el.append($('<div class="ui basic modal"><div class="content"><p>Ola</p></div><div class="actions"><div class="ui green ok inverted button">Fechar</div></div></div>'));
+
+  div_el.append($('<div class="ui basic modal"><div class="content"><p>Olá</p></div><div class="actions"><div class="ui green ok inverted button">Fechar</div></div></div>'));
 
   $('.button_add_case').on('click', function(e) {
     addTestCase();
-    });
+  });
   $('.button_generate_outputs').on('click', function(e) {
     generateOutputs();
     });
@@ -539,27 +575,27 @@ function generateOutputs () {
     showAlert(LocalizedStrings.getUI('text_teacher_generate_outputs_algorithm'));
     return;
     }
-  // codigo:
+  // To generate template code:
   var code_teacher = window.generator();
-  // array com as entradas ja inseridas:
+  // array with the test-cases:
   var test_cases = prepareTestCases();
   ivprogCore.autoGenerateTestCaseOutput(code_teacher, test_cases).catch(function (error) {
-    showAlert("Houve um erro durante a execucao do seu programa: "+error.message);
+    showAlert("There was an error in your iVProg code: " + error.message);
     });
   }
 
 function outputGenerated (test_cases) {
   var fields = $('.text_area_output');
-  /*for (var i = 0; i < test_cases.length; i++) {
-    $(fields[i]).val('');
-    for (var j = 0; j < test_cases[i].output.length; j++) {
-      $(fields[i]).val($(fields[i]).val() + test_cases[i].output[j]);
-      if (j < test_cases[i].output.length - 1) {
-        $(fields[i]).val($(fields[i]).val() + '\n');
-      }
-    }
-    $(fields[i]).attr('rows', test_cases[i].output.length);
-  }*/
+  //_ for (var i = 0; i < test_cases.length; i++) {
+  //_   $(fields[i]).val('');
+  //_   for (var j = 0; j < test_cases[i].output.length; j++) {
+  //_     $(fields[i]).val($(fields[i]).val() + test_cases[i].output[j]);
+  //_     if (j < test_cases[i].output.length - 1) {
+  //_       $(fields[i]).val($(fields[i]).val() + '\n');
+  //_     }
+  //_   }
+  //_   $(fields[i]).attr('rows', test_cases[i].output.length);
+  //_ }
   animateOutput(fields, test_cases, 0);
   }
 
@@ -694,17 +730,17 @@ function prepareTableSettings (div_el) {
   $('.circular.inverted.teal.question.icon').popup({
     content : LocalizedStrings.getUI("text_teacher_filter_help"),
     delay: { show: 750, hide: 0 }
-  });
+    });
 
   $('.ui.checkbox').checkbox();
   }
 
-function orderWidth() {
+function orderWidth () {
   $('.ui.raised.container.segment.div_to_body').css('width', '100%');
   $('.ui.one.column.container.segment.ivprog_visual_panel').css('width', '100%');
   }
 
-function orderIcons() {
+function orderIcons () {
   $('.ui.one.column.doubling.stackable.grid.container').css('display', 'none');
   $('.only_in_frame').css('display', 'block');
   }
@@ -728,7 +764,7 @@ function full_screen () {
       //requestFullscreen is used to display an element in full screen mode.
       if ("requestFullscreen" in element) {
         element.requestFullscreen();
-        }
+      }
       else if ("webkitRequestFullscreen" in element) {
         element.webkitRequestFullscreen();
         }
@@ -756,7 +792,7 @@ function teacherAutoEval (data) {
     showInvalidData();
     return;
     }
-  // Casos de testes agora sao delegados ao tratamento apropriado pela funcao acima
+  // Now the "test-cases" are submitted to analysis of iLM/iVProg (using the abouve "getAutoEvalOriginalData(.)" function
   // var testCases = content.testcases;
   settingsProgrammingTypes = content.settingsProgrammingType;
   settingsDataTypes = content.settingsDataTypes;
@@ -782,7 +818,9 @@ function displayGrade(grade) {
   }
 
 function showInvalidData () {
-  $('.ui.height_100.add_accordion').dimmer({ closable: false });
+  $('.ui.height_100.add_accordion').dimmer({
+    closable: false
+    });
   $('.dimmer_content_message h3').html(LocalizedStrings.getUI('text_message_error_activity_file'));
   $('.dimmer_content_message button').text(LocalizedStrings.getUI('text_message_error_activity_reload'));
   $('.dimmer_content_message').css('display', 'block');
@@ -794,7 +832,9 @@ function showInvalidData () {
   }
 
 function showMessageDialog (msg = "") {
-  $('.ui.height_100.add_accordion').dimmer({ closable: false });
+  $('.ui.height_100.add_accordion').dimmer({
+    closable: false
+    });
   $('.dimmer_content_message h3').html(msg);
   $('.dimmer_content_message button').text("OK");
   $('.dimmer_content_message').css('display', 'block');
@@ -802,11 +842,13 @@ function showMessageDialog (msg = "") {
   $('.ui.height_100.add_accordion').dimmer('show');
   $('.dimmer_content_message button').on('click', function(e) {
     $('.ui.height_100.add_accordion').dimmer('hide');
-  })
+    })
   }
 
 function showInvalidFile () {
-  $('.ui.height_100.add_accordion').dimmer({ closable: true });
+  $('.ui.height_100.add_accordion').dimmer({
+    closable: true
+    });
   $('.dimmer_content_message h3').html(LocalizedStrings.getUI('text_message_error_upload_file'));
   $('.dimmer_content_message button').text(LocalizedStrings.getUI('text_message_error_upload_close'));
   $('.dimmer_content_message').css('display', 'block');
@@ -814,5 +856,5 @@ function showInvalidFile () {
   $('.ui.height_100.add_accordion').dimmer('show');
   $('.dimmer_content_message button').on('click', function(e) {
     $('.ui.height_100.add_accordion').dimmer('hide');
-  })
+    })
   }