Explorar o código

Merge branch 'new_logs_format' of LInE/ivprog_log_analysis into master

igor %!s(int64=2) %!d(string=hai) anos
pai
achega
6f8c1172ce

index.html → _index.html


+ 9 - 2
curso.php

@@ -64,8 +64,8 @@ $exercicios = listarExercicios($_GET['curso']);
               <select class="form-control" id="inputaluno" name="aluno">
                 <option>Todos</option>
                 <?php
-                  for ($i = 0; $i < count($alunos); $i++) {
-                    echo "<option value='$alunos[$i]'>" . str_replace('_', ' ', $alunos[$i]) . "</option>";
+                  foreach ($alunos as $aluno) {
+                    echo "<option value='$aluno'>$aluno</option>";
                   }
                 ?>
               </select>
@@ -78,9 +78,16 @@ $exercicios = listarExercicios($_GET['curso']);
               <select class="form-control" id="inputexercicio" name="exercicio">
                 <option value="Todos">Todos</option>
                 <?php
+<<<<<<< HEAD
+
+                  foreach ($exercicios as $exercicio) {
+                    echo "<option value='$exercicio'>$exercicio</option>";
+=======
                   for ($i = 0; $i < count($exercicios); $i++) {
                     echo "<option value='".$exercicios[$i][1]."'>" . str_replace('_', ' ', $exercicios[$i][0]) . "</option>";
+>>>>>>> master
                   }
+                  
                 ?>
               </select>
             </div>

+ 162 - 41
functions.php

@@ -1,5 +1,6 @@
 <?php
 
+
 function listarCursos () {
   $dir    = 'cursos';
   $files1 = scandir($dir);
@@ -36,13 +37,28 @@ function qualVersaoDoIVProg ($arquivo) {
 	}
 }
 
+// delete all files and sub-folders from a folder
+function deleteFolderAndFiles($dir) {
+	foreach(glob($dir . '/*') as $file) {
+		if(is_dir($file))
+			deleteFolderAndFiles($file);
+		else
+			unlink($file);
+	}
+	rmdir($dir);
+}
+
 function pegarLogsDoAluno ($curso, $aluno, $exercicio) {
+<<<<<<< HEAD
+
+=======
 	echo $curso . ' ' . $aluno  . ' ' . $exercicio . ' ';
+>>>>>>> master
 	$zip = new ZipArchive;
 	$dir    = 'cursos/' . $curso;
   	$files1 = scandir($dir);
   	$nomes  = array();
-  	
+
   	if (count($files1) < 3) {
   		return null;
 	  }
@@ -71,10 +87,20 @@ function pegarLogsDoAluno ($curso, $aluno, $exercicio) {
   	}
 
   	$arquivo = "";
-
+	
   	for ($i = 0; $i < count($files1); $i++) {
   		if ($files1[$i] == "." || $files1[$i] == "..") continue;
-  		if ( strpos($files1[$i], $exercicio) !== false) {
+
+		$exp = explode("-", $files1[4]);
+		$fi = "";
+		for ($j = 0; $j < count($exp) - 1; $j++) {
+			$fi .= $exp[$j];
+			if ($j < (count($exp) - 3)) {
+				$fi .= "-";
+			}
+		}
+
+  		if (strpos($fi, $exercicio) !== false) {
   			$arquivo = $files1[$i];
   		} else {
   			//unlink($dir . '/' . $files1[$i]);
@@ -84,6 +110,40 @@ function pegarLogsDoAluno ($curso, $aluno, $exercicio) {
   	return $arquivo;
 }
 
+<<<<<<< HEAD
+
+function pegarArquivoMaisRecente ($curso, $aluno, $exercicio) {
+
+	$registros = abrirArquivoCSV($_GET['curso'], false);
+
+	$reg_aluno_exercicio = array();
+
+	foreach ($registros as $registro) {
+
+		$reg_proc = clean(str_replace("_", " ", $registro[1]));
+		
+		if (strpos($reg_proc, $aluno) !== false
+			&& strpos($reg_proc, $exercicio) !== false) {
+			
+			array_push($reg_aluno_exercicio, $registro);
+		}
+
+	}
+
+	$highest = 0;
+	$registro_mais_atual = null;
+	foreach ($reg_aluno_exercicio as $item) {
+
+		if ($item[0] > $highest) {
+			$highest = $item[0];
+			$registro_mais_atual = $item;
+		}
+
+	}
+
+	return $registro_mais_atual[1];
+	
+=======
 function pegarLogsDoAlunoComoString ($arquivo) {
 	$handle = fopen("temp/" . $arquivo, "r");
 	$inicio = false;
@@ -121,40 +181,43 @@ function pegarLogsDoAlunoComoString ($arquivo) {
 	}
 
 	return $string_final;
+>>>>>>> master
 }
 
-function listarAlunos ($curso) {
+function pegarLogsDoAlunoComoString ($curso, $aluno, $exercicio) {
 
-	$dir    = 'cursos/' . $curso;
-  	$files1 = scandir($dir);
-  	$nomes  = array();
-  	
-  	if (count($files1) < 3) {
-  		return null;
-  	}
+	$file = pegarArquivoMaisRecente($curso, $aluno, $exercicio);
 
-  	for ($i = 0; $i < count($files1); $i++) {
-  		if ($files1[$i] == "." || $files1[$i] == "..") continue;
-  		$ex = explode("_iassign_", $files1[$i])[1];
-      $ex = explode("-", $ex)[0];
-  		
-  		$ja_existe = false;
-  		for ($j = 0; $j < count($nomes); $j ++) {
-  			if ($nomes[$j] == $ex) {
-  				$ja_existe = true;
-  				break;
-  			}
-  		}
+	$handle = fopen("temp/" . $curso . "/" . $file, "r");
 
-  		if (!$ja_existe) {
-  			array_push($nomes, $ex);
-  		}
-  	}
+	$string_final = "";
+	if ($handle) {
+	
+		while (($line = fgets($handle)) !== false) {
+			
+			if (strpos($line, "::logs::") !== false) {
+				
+
+				$exploded = explode("],[", $line);
+
+				foreach ($exploded as $log) {
+					$temp = explode(',', $log);
+					if (count($temp) == 4)
+						$string_final .= $temp[0] . "," . $temp[1] . ",1,0\\n";
+				}
+
+				break;
+			}
+		}
+		fclose($handle);
+
+		return  $string_final;
+	}
 
-  	return $nomes;
 }
 
-function listarExercicios ($curso) {
+
+function abrirArquivoCSV ($curso, $delete_temp = true) {
 	$zip = new ZipArchive;
 
 	$dir    = 'cursos/' . $curso;
@@ -165,25 +228,54 @@ function listarExercicios ($curso) {
   		return null;
   	}
 
+	$temp_folder = 'temp/' . $curso;
+
   	for ($i = 0; $i < count($files1); $i++) {
   		if ($files1[$i] == "." || $files1[$i] == "..") continue;
   		$res = $zip->open($dir . '/' . $files1[$i]);
 		if ($res === TRUE) {
-		  $zip->extractTo('temp/');
+		  $zip->extractTo($temp_folder);
 		  $zip->close();
 		}
-  	}
+	}
 
-  	$dir    = 'temp';
-  	$files1 = scandir($dir);
-  	
-  	if (count($files1) < 3) {
-  		return null;
-  	}
 
-  	for ($i = 0; $i < count($files1); $i++) {
-  		if ($files1[$i] == "." || $files1[$i] == "..") continue;
+	if (!file_exists($temp_folder . '/index.csv')) {
+		return null;
+	}
+	
+	$final_array = array();
+	$file = fopen($temp_folder . '/index.csv', 'r');
+	while (($line = fgetcsv($file)) !== FALSE) {
+		array_push($final_array, $line);
+	}
+	fclose($file);
+
+<<<<<<< HEAD
+	if ($delete_temp)
+		deleteFolderAndFiles($temp_folder);
+
+	return $final_array;
+}
+
+function listarAlunos ($curso) {
+	
+	$registros = abrirArquivoCSV($curso);
+
+	$nomes = array();
+	foreach ($registros as $registro) {
+		if ($registro[0] == 'submissionid') continue;
+
+		$nome = clean(str_replace("_", " ", explode("/", $registro[1])[1]));
+
+		array_push($nomes, $nome);
+	}
 
+	$nomes = array_unique($nomes);
+	asort($nomes);
+
+	return $nomes;
+=======
 	  	$exp = explode("-", $files1[$i]);
 	  	$fi = "";
 	  	for ($j = 0; $j < count($exp) - 1; $j++) {
@@ -212,15 +304,44 @@ function listarExercicios ($curso) {
 	  }
 	  
   	return $exercicios;
+>>>>>>> master
 }
 
+function listarExercicios ($curso) {
+	
+	$registros = abrirArquivoCSV($curso);
+
+	$exercicios = array();
+	foreach ($registros as $registro) {
+		if ($registro[0] == 'submissionid') continue;
+
+		$nome = clean(str_replace("_", " ", explode("/", $registro[1])[0]));
+
+		array_push($exercicios, $nome);
+	}
+
+  	return array_unique($exercicios);
+}
+
+function clean($string) {
+	$string = str_replace(' ', '-', $string); // Replaces all spaces with hyphens.
+ 
+	return preg_replace('/[^A-Za-z0-9\-]/', '', $string); // Removes special chars.
+ }
+ 
+
 function instrucoes () {
 
 	return "<p class='text-reduced'>
             <b>Instruções para inserir novos logs para análise:</b> 
-            <p>Em primeiro lugar, crie uma nova pasta no diretório cursos/, com o nome do curso que você pretende analisar.
-                Em seguida, insira nessa pasta recém-criada todos os arquivos .zip que foram gerados pelo iTarefa com os dados dos alunos.</p>
+            <ol>
+				<li>Em primeiro lugar, crie uma nova pasta no diretório cursos/, com o nome do curso que você pretende analisar.</li>
+				<li>Agora, navegue pelo iTarefa até a área do gerenciador de todas as submissões (bloco itarefa -> relatório -> gerenciar todas as submissões).</li>
+				<li>No gerenciador de submissões, utilize o exportador geral, que está disponível no botão de 'download' mais acima na tela.</li>
+                <li>Por fim, insira na pasta criada no primeiro passo o arquivo .zip que fori gerado pelo iTarefa com os dados dos alunos.</li>
+			</ol>
             <p><b>Atenção!</b> Não altere nem o nome do arquivo gerado pelo iTarefa, pois o sistema segue o mesmo padrão.</p>
+			<p style='color: red;'>Essa versão é incompatível com arquivos gerados pelo iTarefa antes de 2020.</p>
           </p>";
 }
 

+ 349 - 0
ivprog/css/codemirror.css

@@ -0,0 +1,349 @@
+/* BASICS */
+
+.CodeMirror {
+  /* Set height, width, borders, and global font properties here */
+  font-family: monospace;
+  height: 300px;
+  color: black;
+  direction: ltr;
+}
+
+/* PADDING */
+
+.CodeMirror-lines {
+  padding: 4px 0; /* Vertical padding around content */
+}
+.CodeMirror pre.CodeMirror-line,
+.CodeMirror pre.CodeMirror-line-like {
+  padding: 0 4px; /* Horizontal padding of content */
+}
+
+.CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler {
+  background-color: white; /* The little square between H and V scrollbars */
+}
+
+/* GUTTER */
+
+.CodeMirror-gutters {
+  border-right: 1px solid #ddd;
+  background-color: #f7f7f7;
+  white-space: nowrap;
+}
+.CodeMirror-linenumbers {}
+.CodeMirror-linenumber {
+  padding: 0 3px 0 5px;
+  min-width: 20px;
+  text-align: right;
+  color: #999;
+  white-space: nowrap;
+}
+
+.CodeMirror-guttermarker { color: black; }
+.CodeMirror-guttermarker-subtle { color: #999; }
+
+/* CURSOR */
+
+.CodeMirror-cursor {
+  border-left: 1px solid black;
+  border-right: none;
+  width: 0;
+}
+/* Shown when moving in bi-directional text */
+.CodeMirror div.CodeMirror-secondarycursor {
+  border-left: 1px solid silver;
+}
+.cm-fat-cursor .CodeMirror-cursor {
+  width: auto;
+  border: 0 !important;
+  background: #7e7;
+}
+.cm-fat-cursor div.CodeMirror-cursors {
+  z-index: 1;
+}
+.cm-fat-cursor-mark {
+  background-color: rgba(20, 255, 20, 0.5);
+  -webkit-animation: blink 1.06s steps(1) infinite;
+  -moz-animation: blink 1.06s steps(1) infinite;
+  animation: blink 1.06s steps(1) infinite;
+}
+.cm-animate-fat-cursor {
+  width: auto;
+  border: 0;
+  -webkit-animation: blink 1.06s steps(1) infinite;
+  -moz-animation: blink 1.06s steps(1) infinite;
+  animation: blink 1.06s steps(1) infinite;
+  background-color: #7e7;
+}
+@-moz-keyframes blink {
+  0% {}
+  50% { background-color: transparent; }
+  100% {}
+}
+@-webkit-keyframes blink {
+  0% {}
+  50% { background-color: transparent; }
+  100% {}
+}
+@keyframes blink {
+  0% {}
+  50% { background-color: transparent; }
+  100% {}
+}
+
+/* Can style cursor different in overwrite (non-insert) mode */
+.CodeMirror-overwrite .CodeMirror-cursor {}
+
+.cm-tab { display: inline-block; text-decoration: inherit; }
+
+.CodeMirror-rulers {
+  position: absolute;
+  left: 0; right: 0; top: -50px; bottom: 0;
+  overflow: hidden;
+}
+.CodeMirror-ruler {
+  border-left: 1px solid #ccc;
+  top: 0; bottom: 0;
+  position: absolute;
+}
+
+/* DEFAULT THEME */
+
+.cm-s-default .cm-header {color: blue;}
+.cm-s-default .cm-quote {color: #090;}
+.cm-negative {color: #d44;}
+.cm-positive {color: #292;}
+.cm-header, .cm-strong {font-weight: bold;}
+.cm-em {font-style: italic;}
+.cm-link {text-decoration: underline;}
+.cm-strikethrough {text-decoration: line-through;}
+
+.cm-s-default .cm-keyword {color: #708;}
+.cm-s-default .cm-atom {color: #219;}
+.cm-s-default .cm-number {color: #164;}
+.cm-s-default .cm-def {color: #00f;}
+.cm-s-default .cm-variable,
+.cm-s-default .cm-punctuation,
+.cm-s-default .cm-property,
+.cm-s-default .cm-operator {}
+.cm-s-default .cm-variable-2 {color: #05a;}
+.cm-s-default .cm-variable-3, .cm-s-default .cm-type {color: #085;}
+.cm-s-default .cm-comment {color: #a50;}
+.cm-s-default .cm-string {color: #a11;}
+.cm-s-default .cm-string-2 {color: #f50;}
+.cm-s-default .cm-meta {color: #555;}
+.cm-s-default .cm-qualifier {color: #555;}
+.cm-s-default .cm-builtin {color: #30a;}
+.cm-s-default .cm-bracket {color: #997;}
+.cm-s-default .cm-tag {color: #170;}
+.cm-s-default .cm-attribute {color: #00c;}
+.cm-s-default .cm-hr {color: #999;}
+.cm-s-default .cm-link {color: #00c;}
+
+.cm-s-default .cm-error {color: #f00;}
+.cm-invalidchar {color: #f00;}
+
+.CodeMirror-composing { border-bottom: 2px solid; }
+
+/* Default styles for common addons */
+
+div.CodeMirror span.CodeMirror-matchingbracket {color: #0b0;}
+div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #a22;}
+.CodeMirror-matchingtag { background: rgba(255, 150, 0, .3); }
+.CodeMirror-activeline-background {background: #e8f2ff;}
+
+/* STOP */
+
+/* The rest of this file contains styles related to the mechanics of
+   the editor. You probably shouldn't touch them. */
+
+.CodeMirror {
+  position: relative;
+  overflow: hidden;
+  background: white;
+}
+
+.CodeMirror-scroll {
+  overflow: scroll !important; /* Things will break if this is overridden */
+  /* 50px is the magic margin used to hide the element's real scrollbars */
+  /* See overflow: hidden in .CodeMirror */
+  margin-bottom: -50px; margin-right: -50px;
+  padding-bottom: 50px;
+  height: 100%;
+  outline: none; /* Prevent dragging from highlighting the element */
+  position: relative;
+}
+.CodeMirror-sizer {
+  position: relative;
+  border-right: 50px solid transparent;
+}
+
+/* The fake, visible scrollbars. Used to force redraw during scrolling
+   before actual scrolling happens, thus preventing shaking and
+   flickering artifacts. */
+.CodeMirror-vscrollbar, .CodeMirror-hscrollbar, .CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler {
+  position: absolute;
+  z-index: 6;
+  display: none;
+}
+.CodeMirror-vscrollbar {
+  right: 0; top: 0;
+  overflow-x: hidden;
+  overflow-y: scroll;
+}
+.CodeMirror-hscrollbar {
+  bottom: 0; left: 0;
+  overflow-y: hidden;
+  overflow-x: scroll;
+}
+.CodeMirror-scrollbar-filler {
+  right: 0; bottom: 0;
+}
+.CodeMirror-gutter-filler {
+  left: 0; bottom: 0;
+}
+
+.CodeMirror-gutters {
+  position: absolute; left: 0; top: 0;
+  min-height: 100%;
+  z-index: 3;
+}
+.CodeMirror-gutter {
+  white-space: normal;
+  height: 100%;
+  display: inline-block;
+  vertical-align: top;
+  margin-bottom: -50px;
+}
+.CodeMirror-gutter-wrapper {
+  position: absolute;
+  z-index: 4;
+  background: none !important;
+  border: none !important;
+}
+.CodeMirror-gutter-background {
+  position: absolute;
+  top: 0; bottom: 0;
+  z-index: 4;
+}
+.CodeMirror-gutter-elt {
+  position: absolute;
+  cursor: default;
+  z-index: 4;
+}
+.CodeMirror-gutter-wrapper ::selection { background-color: transparent }
+.CodeMirror-gutter-wrapper ::-moz-selection { background-color: transparent }
+
+.CodeMirror-lines {
+  cursor: text;
+  min-height: 1px; /* prevents collapsing before first draw */
+}
+.CodeMirror pre.CodeMirror-line,
+.CodeMirror pre.CodeMirror-line-like {
+  /* Reset some styles that the rest of the page might have set */
+  -moz-border-radius: 0; -webkit-border-radius: 0; border-radius: 0;
+  border-width: 0;
+  background: transparent;
+  font-family: inherit;
+  font-size: inherit;
+  margin: 0;
+  white-space: pre;
+  word-wrap: normal;
+  line-height: inherit;
+  color: inherit;
+  z-index: 2;
+  position: relative;
+  overflow: visible;
+  -webkit-tap-highlight-color: transparent;
+  -webkit-font-variant-ligatures: contextual;
+  font-variant-ligatures: contextual;
+}
+.CodeMirror-wrap pre.CodeMirror-line,
+.CodeMirror-wrap pre.CodeMirror-line-like {
+  word-wrap: break-word;
+  white-space: pre-wrap;
+  word-break: normal;
+}
+
+.CodeMirror-linebackground {
+  position: absolute;
+  left: 0; right: 0; top: 0; bottom: 0;
+  z-index: 0;
+}
+
+.CodeMirror-linewidget {
+  position: relative;
+  z-index: 2;
+  padding: 0.1px; /* Force widget margins to stay inside of the container */
+}
+
+.CodeMirror-widget {}
+
+.CodeMirror-rtl pre { direction: rtl; }
+
+.CodeMirror-code {
+  outline: none;
+}
+
+/* Force content-box sizing for the elements where we expect it */
+.CodeMirror-scroll,
+.CodeMirror-sizer,
+.CodeMirror-gutter,
+.CodeMirror-gutters,
+.CodeMirror-linenumber {
+  -moz-box-sizing: content-box;
+  box-sizing: content-box;
+}
+
+.CodeMirror-measure {
+  position: absolute;
+  width: 100%;
+  height: 0;
+  overflow: hidden;
+  visibility: hidden;
+}
+
+.CodeMirror-cursor {
+  position: absolute;
+  pointer-events: none;
+}
+.CodeMirror-measure pre { position: static; }
+
+div.CodeMirror-cursors {
+  visibility: hidden;
+  position: relative;
+  z-index: 3;
+}
+div.CodeMirror-dragcursors {
+  visibility: visible;
+}
+
+.CodeMirror-focused div.CodeMirror-cursors {
+  visibility: visible;
+}
+
+.CodeMirror-selected { background: #d9d9d9; }
+.CodeMirror-focused .CodeMirror-selected { background: #d7d4f0; }
+.CodeMirror-crosshair { cursor: crosshair; }
+.CodeMirror-line::selection, .CodeMirror-line > span::selection, .CodeMirror-line > span > span::selection { background: #d7d4f0; }
+.CodeMirror-line::-moz-selection, .CodeMirror-line > span::-moz-selection, .CodeMirror-line > span > span::-moz-selection { background: #d7d4f0; }
+
+.cm-searching {
+  background-color: #ffa;
+  background-color: rgba(255, 255, 0, .4);
+}
+
+/* Used to force a border model for a node */
+.cm-force-border { padding-right: .1px; }
+
+@media print {
+  /* Hide the cursor when printing */
+  .CodeMirror div.CodeMirror-cursors {
+    visibility: hidden;
+  }
+}
+
+/* See issue #2901 */
+.cm-tab-wrap-hack:after { content: ''; }
+
+/* Help users use markselection to safely style text background */
+span.CodeMirror-selectedtext { background: none; }

+ 3 - 0
ivprog/css/ivprog-editor.css

@@ -0,0 +1,3 @@
+.CodeMirror {
+  height: 100% !important;
+}

+ 208 - 0
ivprog/css/ivprog-term.css

@@ -0,0 +1,208 @@
+.ivprog-term-div {
+  /* background-color: black; */
+  width: 100%;
+  height: 12rem;
+  overflow-y: scroll;
+}
+
+#ivprog-term-div {
+  z-index: 10;
+}
+
+.ivprog-term-userText {
+  white-space: pre;
+  height: 1.6rem;
+}
+
+.ivprog-term-userText, .ivprog-term-userInput {
+  color: #f2d6d6;
+  height: 1.6rem;
+}
+
+.ivprog-term-info {
+  color: #28a628;
+  height: 1.6rem;
+}
+
+.ivprog-term-error {
+  color: #df4242;
+  height: 1.6rem;
+}
+
+.ivprog-term-input {
+  font-family: 'Courier New', Courier, monospace;
+  font-weight: 500;
+  background-color: inherit;
+  border: 0;
+  color: white;
+}
+
+.ivprog-term-div > .ivprog-term-input, .ivprog-term-div > .ivprog-term-userText,
+.ivprog-term-div > .ivprog-term-info, .ivprog-term-div, .ivprog-term-error {
+  padding-left: 20px;
+}
+
+#ivprog-term {
+  /* border: 1px solid gray;
+  background: black;
+  margin-top: -30px;
+  position: relative;
+  padding: 5px;
+  z-index: 999; */
+}
+/* #ivprog-term i {
+  margin-left: 5px;
+  cursor: pointer;
+} */
+.div_toggle_console {
+  cursor: pointer;
+}
+.ivprog-term-active {
+  box-shadow: 0 0 5px rgba(81, 203, 238, 1) !important;
+  border: 3px solid rgba(81, 203, 238, 1) !important;
+}
+
+.ivprog-term-div {
+  overflow:scroll;
+}
+
+.ivprog-term-div::-webkit-scrollbar {
+    width: 12px;
+}
+
+.ivprog-term-div::-webkit-scrollbar-track {
+    -webkit-box-shadow: inset 0 0 6px rgba(0,0,0,0.3);
+    -webkit-border-radius: 10px;
+    border-radius: 10px;
+}
+
+.ivprog-term-div::-webkit-scrollbar-thumb {
+    -webkit-border-radius: 10px;
+    border-radius: 10px;
+    background: green;
+    -webkit-box-shadow: inset 0 0 6px rgba(0,0,0,0.5);
+}
+
+/**novas regras bash*/
+#ivprog-terminal-inputdiv {
+  padding-left: 12px;
+}
+#ivprog-console-clearbtn, #ivprog-console-showbtn, #ivprog-console-hidebtn {
+  cursor: pointer;
+}
+
+.bash {
+  box-shadow: 0 0 30px rgba(0,0,0,0.4);
+  border-radius: 3px;
+  font-family: "Andale Mono", Consolas, "Courier New" !important;
+}
+
+.bash-title {
+  text-align: center;
+  color: #525252;
+  padding: 5px 0;
+  margin: 0;
+  text-shadow: 1px 1px 0 rgba(255,255,255,0.5);
+  font-size: 0.85em;
+  border: 1px solid #CCCCCC;
+  border-bottom: none;
+
+  border-top-left-radius: 3px;
+  border-top-right-radius: 3px;
+
+  background: #f7f7f7; /* Old browsers */
+  background: linear-gradient(to bottom,  #f7f7f7 0%,#B8B8B8 100%); /* W3C */
+}
+
+.bash-body {
+  /* margin: 0;
+  padding: 5px; */
+  background: #111010;
+  /* list-style: none; */
+  color: #F8F8FF;
+
+  font: 14px 'Andale Mono', Consolas, 'Courier New';
+  line-height: 1.6em;
+  border: 1px solid #CCCCCC;
+  border-bottom-right-radius: 3px;
+  border-bottom-left-radius: 3px;
+}
+
+.bash-text {
+  font: 14px 'Andale Mono', Consolas, 'Courier New';
+  line-height: 1.6em;
+}
+
+.bash-highlight {
+  color: #45D40C;
+}
+
+.bash-highlight a {
+  color: #45D40C;
+  text-decoration: underline;
+}
+
+/* .bash-body li:before {
+  content: '$';
+  color: #F8F8FF;
+  position: absolute;
+  left: 0;
+  top: 0;
+} */
+
+.bash-body i {
+  cursor: text;
+}
+
+.bash-body li {
+  word-wrap: break-word;
+  position: relative;
+  padding: 0 0 0 15px;
+}
+
+#cmd {
+  font-family: courier;
+  font-size: 14px;
+  line-height: normal;
+  background:inherit;
+  color: #21f838;
+  padding: 5px;
+  overflow: hidden;
+}
+#cmd span {
+  float: left;
+  padding-left: 3px;
+  white-space: pre;
+}
+#cursor {
+  float: left;
+  width: 5px;
+  height: 14px;
+  background: #21f838;
+}
+#cmd ~ input {
+  width: 0;
+  height: 0;
+  opacity: 0;
+}
+
+.ivprog-term-error > span > ul {
+  margin:0 !important;
+}
+
+.ivprog-term-error > span > ul > li {
+  padding: 0;
+  margin: 0;
+  line-height: 1rem;
+}
+
+.assessment-div-detail:hover {
+  cursor: pointer;
+}
+.assessment-div-detail:hover > span {
+  text-decoration: underline;
+}
+
+.bash span {
+  font-family: 'Courier New', Courier, monospace;
+}

A diferenza do arquivo foi suprimida porque é demasiado grande
+ 1164 - 0
ivprog/css/ivprog-visual-1.0.css


+ 56 - 0
ivprog/css/roboto.css

@@ -0,0 +1,56 @@
+/* cyrillic-ext */
+@font-face {
+  font-family: 'Roboto';
+  font-style: normal;
+  font-weight: 400;
+  src: local('Roboto'), local('Roboto-Regular'), url(fonts/cyrillic-ext-roboto.woff2) format('woff2');
+  unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
+}
+/* cyrillic */
+@font-face {
+  font-family: 'Roboto';
+  font-style: normal;
+  font-weight: 400;
+  src: local('Roboto'), local('Roboto-Regular'), url(fonts/cyrillic-roboto.woff2) format('woff2');
+  unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
+}
+/* greek-ext */
+@font-face {
+  font-family: 'Roboto';
+  font-style: normal;
+  font-weight: 400;
+  src: local('Roboto'), local('Roboto-Regular'), url(fonts/greek-ext-roboto.woff2) format('woff2');
+  unicode-range: U+1F00-1FFF;
+}
+/* greek */
+@font-face {
+  font-family: 'Roboto';
+  font-style: normal;
+  font-weight: 400;
+  src: local('Roboto'), local('Roboto-Regular'), url(fonts/greek-roboto.woff2) format('woff2');
+  unicode-range: U+0370-03FF;
+}
+/* vietnamese */
+@font-face {
+  font-family: 'Roboto';
+  font-style: normal;
+  font-weight: 400;
+  src: local('Roboto'), local('Roboto-Regular'), url(fonts/vietnamese-roboto.woff2) format('woff2');
+  unicode-range: U+0102-0103, U+0110-0111, U+1EA0-1EF9, U+20AB;
+}
+/* latin-ext */
+@font-face {
+  font-family: 'Roboto';
+  font-style: normal;
+  font-weight: 400;
+  src: local('Roboto'), local('Roboto-Regular'), url(fonts/latin-ext-roboto.woff2) format('woff2');
+  unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
+}
+/* latin */
+@font-face {
+  font-family: 'Roboto';
+  font-style: normal;
+  font-weight: 400;
+  src: local('Roboto'), local('Roboto-Regular'), url(fonts/latin-roboto.woff2) format('woff2');
+  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
+}

A diferenza do arquivo foi suprimida porque é demasiado grande
+ 372 - 0
ivprog/css/semantic.min.css


+ 36 - 0
ivprog/css/show-hint.css

@@ -0,0 +1,36 @@
+.CodeMirror-hints {
+  position: absolute;
+  z-index: 10;
+  overflow: hidden;
+  list-style: none;
+
+  margin: 0;
+  padding: 2px;
+
+  -webkit-box-shadow: 2px 3px 5px rgba(0,0,0,.2);
+  -moz-box-shadow: 2px 3px 5px rgba(0,0,0,.2);
+  box-shadow: 2px 3px 5px rgba(0,0,0,.2);
+  border-radius: 3px;
+  border: 1px solid silver;
+
+  background: white;
+  font-size: 90%;
+  font-family: monospace;
+
+  max-height: 20em;
+  overflow-y: auto;
+}
+
+.CodeMirror-hint {
+  margin: 0;
+  padding: 0 4px;
+  border-radius: 2px;
+  white-space: pre;
+  color: black;
+  cursor: pointer;
+}
+
+li.CodeMirror-hint-active {
+  background: #08f;
+  color: white;
+}

BIN=BIN
ivprog/css/themes/default/assets/fonts/icons.woff2


BIN=BIN
ivprog/css/themes/default/assets/fonts/outline-icons.woff2


+ 64 - 0
ivprog/css/ttcn.css

@@ -0,0 +1,64 @@
+.cm-s-ttcn .cm-quote { color: #090; }
+.cm-s-ttcn .cm-negative { color: #d44; }
+.cm-s-ttcn .cm-positive { color: #292; }
+.cm-s-ttcn .cm-header, .cm-strong { font-weight: bold; }
+.cm-s-ttcn .cm-em { font-style: italic; }
+.cm-s-ttcn .cm-link { text-decoration: underline; }
+.cm-s-ttcn .cm-strikethrough { text-decoration: line-through; }
+.cm-s-ttcn .cm-header { color: #00f; font-weight: bold; }
+
+.cm-s-ttcn .cm-atom { color: #219; }
+.cm-s-ttcn .cm-attribute { color: #00c; }
+.cm-s-ttcn .cm-bracket { color: #997; }
+.cm-s-ttcn .cm-comment { color: #333333; }
+.cm-s-ttcn .cm-def { color: #00f; }
+.cm-s-ttcn .cm-em { font-style: italic; }
+.cm-s-ttcn .cm-error { color: #f00; }
+.cm-s-ttcn .cm-hr { color: #999; }
+.cm-s-ttcn .cm-invalidchar { color: #f00; }
+.cm-s-ttcn .cm-keyword { font-weight:bold; }
+.cm-s-ttcn .cm-link { color: #00c; text-decoration: underline; }
+.cm-s-ttcn .cm-meta { color: #555; }
+.cm-s-ttcn .cm-negative { color: #d44; }
+.cm-s-ttcn .cm-positive { color: #292; }
+.cm-s-ttcn .cm-qualifier { color: #555; }
+.cm-s-ttcn .cm-strikethrough { text-decoration: line-through; }
+.cm-s-ttcn .cm-string { color: #006400; }
+.cm-s-ttcn .cm-string-2 { color: #f50; }
+.cm-s-ttcn .cm-strong { font-weight: bold; }
+.cm-s-ttcn .cm-tag { color: #170; }
+.cm-s-ttcn .cm-variable { color: #8B2252; }
+.cm-s-ttcn .cm-variable-2 { color: #05a; }
+.cm-s-ttcn .cm-variable-3, .cm-s-ttcn .cm-type { color: #085; }
+
+.cm-s-ttcn .cm-invalidchar { color: #f00; }
+
+/* ASN */
+.cm-s-ttcn .cm-accessTypes,
+.cm-s-ttcn .cm-compareTypes { color: #27408B; }
+.cm-s-ttcn .cm-cmipVerbs { color: #8B2252; }
+.cm-s-ttcn .cm-modifier { color:#D2691E; }
+.cm-s-ttcn .cm-status { color:#8B4545; }
+.cm-s-ttcn .cm-storage { color:#A020F0; }
+.cm-s-ttcn .cm-tags { color:#006400; }
+
+/* CFG */
+.cm-s-ttcn .cm-externalCommands { color: #8B4545; font-weight:bold; }
+.cm-s-ttcn .cm-fileNCtrlMaskOptions,
+.cm-s-ttcn .cm-sectionTitle { color: #2E8B57; font-weight:bold; }
+
+/* TTCN */
+.cm-s-ttcn .cm-booleanConsts,
+.cm-s-ttcn .cm-otherConsts,
+.cm-s-ttcn .cm-verdictConsts { color: #006400; }
+.cm-s-ttcn .cm-configOps,
+.cm-s-ttcn .cm-functionOps,
+.cm-s-ttcn .cm-portOps,
+.cm-s-ttcn .cm-sutOps,
+.cm-s-ttcn .cm-timerOps,
+.cm-s-ttcn .cm-verdictOps { color: #0000FF; }
+.cm-s-ttcn .cm-preprocessor,
+.cm-s-ttcn .cm-templateMatch,
+.cm-s-ttcn .cm-ttcn3Macros { color: #27408B; }
+.cm-s-ttcn .cm-types { color: #A52A2A; font-weight:bold; }
+.cm-s-ttcn .cm-visibilityModifiers { font-weight:bold; }

A diferenza do arquivo foi suprimida porque é demasiado grande
+ 1 - 0
ivprog/img/empty.svg


A diferenza do arquivo foi suprimida porque é demasiado grande
+ 1 - 0
ivprog/img/new_line.svg


BIN=BIN
ivprog/img/trash-icon.png


+ 162 - 0
ivprog/index.html

@@ -0,0 +1,162 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <meta http-equiv="content-type" content="text/html; charset=UTF-8">
+    <title></title>
+    <link href="css/roboto.css" type="text/css" rel="stylesheet">
+    <link rel="stylesheet" href="css/semantic.min.css"/>
+    <link rel="stylesheet" type="text/css" href="css/codemirror.css">
+    <link rel="stylesheet" type="text/css" href="css/show-hint.css">
+    <link rel="stylesheet" type="text/css" href="css/ttcn.css">
+    <link rel="stylesheet" type="text/css" href="css/ivprog-visual-1.0.css">
+    <link rel="stylesheet" type="text/css" href="css/ivprog-term.css">
+    <link rel="stylesheet" type="text/css" href="css/ivprog-editor.css">
+    <script src="js/jquery.min.js"></script>
+    <script src="js/jquery-ui.min.js"></script>
+    <script src="js/semantic.min.js"></script>
+    <script src="js/Sortable.js"></script>
+    <script src="js/iassign-integration-functions.js"></script>
+  </head>
+  <body>
+
+    <div class="ui height_100 add_accordion" id="ui_main_div">
+
+      <div class="title default_visual_title">
+        <i class="dropdown icon"></i>
+      </div>
+
+    <div class="content height_100">
+
+      <div class="ui raised container segment div_to_body">
+
+        <div class="ui container main_title only_in_frame">
+          <h2>iVProg</h2>
+        </div>
+
+        <div class="ui icon menu center aligned container" style="width: 438px; margin-top: -20px;">
+          <a class="item active visual_coding_button">
+            <i class="window maximize outline icon"></i>
+          </a>
+          <a class="item textual_coding_button">
+            <i class="code icon"></i>
+          </a>
+          <a class="item upload_file_button disabled">
+            <i class="upload icon"></i>
+          </a>
+          <a class="item download_file_button disabled">
+            <i class="download icon"></i>
+          </a>
+          <a class="item undo_button disabled">
+            <i class="undo icon"></i>
+          </a>
+          <a class="item redo_button disabled">
+            <i class="redo icon"></i>
+          </a>
+          <a id="run_button" class="item run_button">
+            <i class="play icon"></i>
+          </a>
+          <a id="stop_button" class="item stop_button" style="display: none">
+            <i class="stop icon"></i>
+          </a>
+          <a class="item assessment assessment_button">
+            <i class="check icon"></i>
+          </a>
+          <!--<a class="item expand_button">
+            <i class="expand arrows alternate icon"></i>
+          </a>-->
+          <a class="item help_button">
+            <i class="help icon"></i>
+          </a>
+        </div>
+
+        <div class="ui one column container segment ivprog_visual_panel loading">
+
+          <div class="global_var">
+
+
+            <div class="ui icon button add-globalVar-button add_global_button purple">
+
+              <i class="icons">
+                <i class="icon superscript" style="margin-top: -2px;margin-bottom: 2px;margin-left: 1px;margin-right: 1px; font-size: 18px;"></i>
+                <i class="corner add icon inverted" style="font-size: 10px;padding-top: 5px;padding-left: 7px;"></i>
+              </i>
+
+            </div>
+
+            <div class="list_globals" id="listGlobalsHandle"></div>
+
+          </div>
+
+          <div class="all_functions list-group" id="listWithHandle">
+
+          </div>
+
+
+          <div class="ui teal small labeled icon button add_function_button">
+            <data class="i18n" value="ui:btn_function">Function</data>
+            <i class="add icon"></i>
+          </div>
+          <div class="program_final"></div>
+
+        </div>
+
+
+        <div class="ui one column container segment ivprog_textual_panel loading" style="display: none;">
+          <textarea id="ivprog-text-editor" class=".ivprog_textual_code"></textarea>
+        </div>
+        <div id='ivprog-term-div' class="six column wide">
+
+        </div>
+      </div>
+    </div>
+    <div class="dimmer_content_message">
+      <h3>Aconteceu um erro ao processar a atividade. <br> Recarregue a página para tentar novamente.</h3>
+      <button class="positive ui button" onclick="window.parent.location.reload()">Recarregar</button>
+    </div>
+    <script src="js/iassign-integration-functions.js"></script>
+  </div>
+  <script src="js/vendors~main.685d1cf2ece1ed4ebb99.js"></script><script src="js/main.7121176c0750a24caa1f.js"></script></body>
+  <script>
+    var mouseX;
+    var mouseY;
+    $(document).ready(() => {
+      var $buttons = $('.ivprog_format .button'),
+        handler = {
+          activate: function () {
+            $(this)
+              .addClass('active')
+              .siblings()
+              .removeClass('active');
+          }
+        };
+
+      $buttons.on('click', handler.activate);
+      $('.ivprog_format_info').popup(
+        {
+          popup: $('.custom.popup'),
+          on: 'click'
+        });
+
+      $(".data_types_dropdown").dropdown();
+
+      $('.ui.dropdown').dropdown();
+
+      $('.ivprog_visual_panel').removeClass("loading");
+
+      $(document).mousemove(function (e) {
+        var parentOffset = $('.ivprog_visual_panel').offset();;
+        mouseX = e.pageX - parentOffset.left + 300;
+        mouseY = e.pageY - parentOffset.top + 100;
+        /*$('.created_element').css('top', mouseY);
+        $('.created_element').css('left', mouseX);*/
+      });
+      ivprogCore.LocalizedStrings.updateTagText();
+      ivprogCore.CodeEditor.initTextEditor("ivprog-text-editor");
+      iassingIntegration();
+      if (iLMparameters.iLM_PARAM_TeacherAutoEval == null) {
+        ivprogCore.initVisualUI();
+      }
+    });
+  </script>
+</html>
+

A diferenza do arquivo foi suprimida porque é demasiado grande
+ 2 - 0
ivprog/js/Sortable.js


+ 821 - 0
ivprog/js/iassign-integration-functions.js

@@ -0,0 +1,821 @@
+// Função para ler parâmetros informados pelo iTarefa via URL
+// Apesar de não ser obrigatório, será muito útil para capturar os parâmetros
+function getParameterByName (name, defaultReturn = null) {
+  var match = RegExp('[?&]' + name + '=([^&]*)').exec(window.location.search);
+  return match ? decodeURIComponent(match[1].replace(/\+/g, ' ')) : defaultReturn;
+}
+
+// Criando um object com os parâmetros informados pelo iTarefa
+// Observe que para cada parâmetro, é realizada a chamada do método getParameterByName, implementado acima
+var iLMparameters = {
+  iLM_PARAM_ServerToGetAnswerURL: getParameterByName("iLM_PARAM_ServerToGetAnswerURL"),
+  iLM_PARAM_SendAnswer: getParameterByName("iLM_PARAM_SendAnswer"),
+  iLM_PARAM_AssignmentURL: getParameterByName("iLM_PARAM_AssignmentURL"),
+  iLM_PARAM_Assignment: getParameterByName("iLM_PARAM_Assignment"),
+  iLM_PARAM_TeacherAutoEval: getParameterByName("iLM_PARAM_TeacherAutoEval"),
+  lang: getParameterByName("lang", "pt")
+};
+
+// Set the lang parameter to the localStorage for easy access
+// and no dependency to the global scope, avoind future 'strict mode' problems
+//localStorage.setItem('ivprog.lang', iLMparameters.lang);
+
+function removeCollapseValue (command) {
+  if (command.collapsed) {
+    delete command.collapsed;
+  }
+  if (command.type == 'iftrue') {
+    if (command.commands_block)
+      for (var i = 0; i < command.commands_block.length; i++) {
+        removeCollapseValue(command.commands_block[i]);
+      }
+    if (command.commands_else)
+      for (var i = 0; i < command.commands_else.length; i++) {
+        removeCollapseValue(command.commands_else[i]);
+      }
+  } else if (command.type == 'repeatNtimes' 
+            || command.type == 'whiletrue' 
+            || command.type == 'dowhiletrue' ) {
+    if (command.commands_block)
+      for (var i = 0; i < command.commands_block.length; i++) {
+        removeCollapseValue(command.commands_block[i]);
+      }
+  }
+}
+
+// Função chamada pelo iTarefa quando o professor finaliza a criação da atividade
+// ou quando o aluno finaliza a resolução do exercício
+// O retorno é um JSON com os dados do exercício ou da resolução
+// Esse retorno será armazenado no banco de dados do Moodle, pelo iTarefa
+function getAnswer () {
+  // Remover o colapsar usado localmente:
+  if (window.program_obj) {
+    for (var i = 0; i < window.program_obj.functions.length; i++) {
+      for (var j = 0; j < window.program_obj.functions[i].commands.length; j++) {
+        removeCollapseValue(window.program_obj.functions[i].commands[j]);
+      }
+    }
+  }
+  // Se o parâmetro "iLM_PARAM_SendAnswer" for false,
+  // então trata-se de resolução de atividade
+  if (iLMparameters.iLM_PARAM_SendAnswer == 'false') {
+    // Montar o retorno com a resposta do aluno
+    var contentToSend = previousContent.split("\n::algorithm::")[0];
+    contentToSend += '\n::algorithm::';
+
+    if (settingsProgrammingTypes == "textual") {
+      contentToSend +=  ivprogCore.CodeEditor.getCode();
+    } else {
+      contentToSend += JSON.stringify(window.program_obj, function(key, value) {
+        if (key == 'dom_object') {
+            return;
+        }
+        return value;
+      });
+    }
+
+    contentToSend += '\n::logs::';
+    contentToSend += getTrackingLogs();
+
+    return contentToSend;
+
+  } else {
+    // Montar o retorno com a criação da atividade do professor
+    var ret = ' { ' + prepareTestCases()
+        + ',\n"settings_programming_type": \n' + JSON.stringify($('form[name="settings_programming_type"]').serializeArray())
+        + ',\n"settings_data_types": \n' + JSON.stringify($('form[name="settings_data_types"]').serializeArray())
+        + ',\n"settings_commands": \n' + JSON.stringify($('form[name="settings_commands"]').serializeArray())
+        + ',\n"settings_functions": \n' + JSON.stringify($('form[name="settings_functions"]').serializeArray())
+        + ',\n"settings_filter": \n' + JSON.stringify($('form[name="settings_filter"]').serializeArray())
+        + ' } ';
+
+    if ($("input[name='include_algo']").is(':checked')) {
+      ret += '\n::algorithm::';
+      ret += JSON.stringify(window.program_obj, function(key, value) {
+
+          if (key == 'dom_object') {
+              return;
+          }
+          return value;
+      });
+    }
+
+    return ret;
+  }
+}
+
+function prepareTestCases () {
+  var ret = ' \n "testcases" : [ '
+  var test_cases_array = $('form[name="test_cases"]').serializeArray();
+  console.log(test_cases_array);
+  for (var i = 0; i < test_cases_array.length; i = i + 2) {
+    ret += '\n{ ';
+    ret += '\n "input": [';
+    var inps = test_cases_array[i].value.match(/[^\r\n]+/g);
+    if (inps) {
+      for (var j = 0; j < inps.length; j++) {
+        ret += '"' + inps[j] + '"';
+        if ((j + 1) < inps.length) {
+          ret += ', ';
+        }
+      }
+    }
+    ret += '], \n "output": [';
+    var outs = test_cases_array[i+1].value.match(/[^\r\n]+/g);
+    console.log(outs);
+    if (outs) {
+      for (var j = 0; j < outs.length; j++) {
+        console.log("output -> ",outs[j]);
+        ret += '"' + outs[j] + '"';
+        if ((j + 1) < outs.length) {
+          ret += ', ';
+        }
+      }
+    }
+    ret += ']';
+    ret += '\n}'
+    if ((i + 2) < test_cases_array.length) {
+      ret += ',';
+    }
+  }
+  ret += '\n] ';
+  return ret;
+}
+
+// Função chamada pelo iTarefa para receber a nota do aluno na atividade
+// O retorno é um valor entre 0.0 e 1.0
+function getEvaluation () {
+  if (iLMparameters.iLM_PARAM_SendAnswer == 'false') {
+    // A chamada do método abaixo é obrigatória!
+    // Observe que a chamada parte do iLM para o iTarefa
+    //parent.getEvaluationCallback(window.studentGrade);
+
+    var canRunAssessment = runCodeAssessment();
+    if(canRunAssessment === -1) {
+      parent.getEvaluationCallback(-1);
+    }
+  }
+}
+
+//var testCases = null
+var settingsDataTypes = null;
+var settingsCommands = null;
+var settingsFunctions = null;
+var settingsProgrammingTypes = null;
+var settingsFilter = null;
+var algorithm_in_ilm = null;
+var previousContent = null;
+
+// Função para que o iMA leia os dados da atividade fornecidos pelo iTarefa
+function getiLMContent () {
+
+  // O parâmetro "iLM_PARAM_Assignment" fornece o URL do endereço que deve ser
+  // requisitado via AJAX para a captura dos dados da atividade
+  $.get(iLMparameters.iLM_PARAM_Assignment, function (data) {
+    //professor invocou a avaliação automática dos exercícios do bloco
+    if (iLMparameters.iLM_PARAM_TeacherAutoEval != null) {
+        teacherAutoEval(data);
+        //não deve exibir nenhuma interface...
+        return;
+    } else if (iLMparameters.iLM_PARAM_SendAnswer == 'false') {
+        // Aluno está trabalhando em alguma atividade:
+        previousContent = data;
+        prepareActivityToStudent(data);
+    } else { // Professor está editando uma atividade:
+        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
+  var content = ivprogCore.prepareActivityToStudentHelper(ilm_cont).getOrElse(null);
+  if(!content) {
+    showInvalidData();
+    return;
+  }
+  var testCases = ivprogCore.getTestCases();
+
+  settingsProgrammingTypes = content.settingsProgrammingType;
+  settingsDataTypes = content.settingsDataTypes;
+  settingsCommands = content.settingsCommands;
+  settingsFunctions = content.settingsFunctions;
+  settingsFilter = content.settingsFilter;
+
+  for (var i = 0; i < testCases.length; i++) {
+    addTestCase(testCases[i]);
+  }
+
+  if (content.algorithmInIlm != null) {
+    algorithm_in_ilm = content.algorithmInIlm;
+    $("input[name='include_algo']").prop('checked', true);
+    includePreviousAlgorithm();
+    renderAlgorithm();
+  }
+
+  ivprogTextualOrVisual();
+  if (settingsFilter && settingsFilter[0]) {
+    blockAllEditingOptions();
+  }
+}
+
+function parsePreviousAlgorithm () {
+  window.program_obj.functions = JSON.parse(algorithm_in_ilm).functions;
+  window.program_obj.globals = JSON.parse(algorithm_in_ilm).globals;
+}
+
+function includePreviousAlgorithm () {
+  if (settingsProgrammingTypes == "textual") {
+    return;
+  }
+
+  parsePreviousAlgorithm();
+
+  window.watchW.watch(window.program_obj.globals, function(){
+    if (window.insertContext) {
+      setTimeout(function(){ renderAlgorithm(); }, 300);
+      window.insertContext = false;
+    } else {
+      renderAlgorithm();
+    }
+  }, 1);
+
+  for (var i = 0; i < window.program_obj.functions.length; i ++) {
+    window.watchW.watch(window.program_obj.functions[i].parameters_list, function(){
+      if (window.insertContext) {
+        setTimeout(function(){ renderAlgorithm(); }, 300);
+        window.insertContext = false;
+      } else {
+        renderAlgorithm();
+      }
+    }, 1);
+
+    window.watchW.watch(window.program_obj.functions[i].variables_list, function(){
+      if (window.insertContext) {
+        setTimeout(function(){ renderAlgorithm(); }, 300);
+        window.insertContext = false;
+      } else {
+        renderAlgorithm();
+      }
+    }, 1);
+
+    if (window.program_obj.functions[i].is_main) {
+        window.program_obj.functions[i].name = LocalizedStrings.getUI("start");
+    }
+  }
+
+  window.watchW.watch(window.program_obj.functions, function(){
+    if (window.insertContext) {
+      setTimeout(function(){ renderAlgorithm(); }, 300);
+      window.insertContext = false;
+    } else {
+      renderAlgorithm();
+    }
+  }, 1);
+}
+
+function prepareActivityToStudent (ilm_cont) {
+    // Ver arquivo js/util/iassignHelpers.js
+    var content = ivprogCore.prepareActivityToStudentHelper(ilm_cont).getOrElse(null);
+    if(!content) {
+      showInvalidData();
+      return;
+    }
+    // Casos de testes agora são delegados ao tratamento apropriado pela função acima
+    // var testCases = content.testcases;
+    settingsProgrammingTypes = content.settingsProgrammingType;
+    settingsDataTypes = content.settingsDataTypes;
+    settingsCommands = content.settingsCommands;
+    settingsFunctions = content.settingsFunctions;
+    settingsFilter = content.settingsFilter;
+
+    if (content.algorithmInIlm != null) {
+        algorithm_in_ilm = content.algorithmInIlm;
+        includePreviousAlgorithm();
+    }
+    $('.assessment_button').removeClass('disabled');
+    renderAlgorithm();
+
+    ivprogTextualOrVisual();
+    if (settingsFilter && settingsFilter[0]) {
+      blockAllEditingOptions();
+    }
+}
+
+// Função para organizar se para criação, visualização ou resolução de atividade
+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, então trata-se de resolução de atividade,
+  // portanto, a "DIV" de resolução é liberada
+  if (iLMparameters.iLM_PARAM_SendAnswer == 'false') {
+    //$('.resolucao').css("display","block");
+    getiLMContent();
+
+    // $('.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 não esteja em modo de resolução de atividade, a visualização no momento
+    // é para a elaboração de atividade:
+    //$('.elaboracao').css("display","block");
+
+    // Se possuir o parâmetro iLMparameters.iLM_PARAM_Assignment, o professor
+    // está editando uma atividade:
+    getiLMContent();
+  } else {
+    renderAlgorithm();
+  }
+
+  if ((iLMparameters.iLM_PARAM_AssignmentURL == "true") && (iLMparameters.iLM_PARAM_SendAnswer == "true")) {
+    prepareActivityCreation();
+  }
+}
+
+function blockAllEditingOptions () {
+
+  if ((iLMparameters.iLM_PARAM_AssignmentURL == "true") && (iLMparameters.iLM_PARAM_SendAnswer == "true")) {
+    return;
+  }
+
+  $('.add_global_button').addClass('disabled');
+  $('.move_function').addClass('disabled');
+  $('.add_function_button').addClass('disabled');
+  $('.add_var_button_function .ui.icon.button.purple').addClass('disabled');
+  $('.add_var_button_function').addClass('disabled');
+  $('.menu_commands').addClass('disabled');
+
+  $('.global_type').addClass('disabled');
+  $('.editing_name_var').addClass('disabled');
+  $('.span_value_variable').addClass('disabled');
+
+  $('.remove_global').addClass('disabled');
+  $('.ui.icon.ellipsis.vertical.inverted').addClass('disabled');
+
+  $('.alternate_constant').addClass('disabled');
+  $('.remove_variable').addClass('disabled');
+
+  $('.add_global_matrix_column').addClass('disabled');
+  $('.remove_global_matrix_column').addClass('disabled');
+
+  $('.add_global_matrix_line').addClass('disabled');
+  $('.remove_global_matrix_line').addClass('disabled');
+
+  $('.add_global_vector_column').addClass('disabled');
+  $('.remove_global_vector_column').addClass('disabled');
+
+  $('.add_expression').addClass('disabled');
+  $('.add_parentheses').addClass('disabled');
+
+  $('.remove_function_button').addClass('disabled');
+  $('.button_remove_command').addClass('disabled');
+
+  $('.command_drag').addClass('disabled');
+  $('.simple_add').addClass('disabled');
+
+  $('.add_parameter_button').addClass('disabled');
+  $('.parameter_div_edit').addClass('disabled');
+  $('.function_name_div_updated').addClass('disabled');
+  $('.value_rendered').addClass('disabled');
+  $('.var_name').addClass('disabled');
+  $('.variable_rendered').addClass('disabled');
+
+  $('.dropdown').addClass('disabled');
+  $('.remove_parameter').addClass('disabled');
+
+  $('.ui.dropdown.global_type.disabled').css('opacity', '1');
+  $('.ui.dropdown.variable_type.disabled').css('opacity', '1');
+  $('.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") {
+      $('.ivprog_visual_panel').css('display', 'none');
+      $('.ivprog_textual_panel').css('display', 'block');
+      $('.ivprog_textual_panel').removeClass('loading');
+
+      $('.visual_coding_button').removeClass('active');
+      $('.textual_coding_button').addClass('active');
+      $('.visual_coding_button').addClass('disabled');
+
+      let textual_code = algorithm_in_ilm;
+      if(!textual_code) {
+        textual_code = ivprogCore.LocalizedStrings.getUI("initial_program_code");
+        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);
+    }
+    if (settingsProgrammingTypes == "visual") {
+
+    }
+  }
+}
+
+function iassingIntegration () {
+
+  // Disable by default...
+  $('.assessment_button').addClass('disabled');
+
+  prepareEnvironment();
+  if (inIframe()) {
+    orderIcons();
+    orderWidth();
+  }
+}
+
+// Função para preparar a interface para o professor criar atividade:
+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>');
+
+  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>');
+
+  $('.tab_test_cases').append(cases_test_div);
+
+  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()) {
+      $('.ui.styled.accordion').css('width', '96%');
+  }
+}
+
+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>';
+
+  div_el.append(table_el);
+
+  var table_buttons = '<table class="table_buttons"><tr><td>'
+    + '<button class="ui teal labeled icon button button_add_case"><i class="plus icon"></i>'+LocalizedStrings.getUI('text_teacher_test_case_add')+'</button>'
+    + '</td><td class="right_align">'
+    + '<button class="ui orange labeled icon button button_generate_outputs"><i class="sign-in icon"></i>'+LocalizedStrings.getUI('text_teacher_generate_outputs')+'</button>'
+    + '</td></tr></table>';
+
+  div_el.append(table_buttons);
+
+  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();
+  });
+}
+
+function showAlert (msg) {
+  $('.ui.basic.modal .content').html('<h3>'+msg+'</h3>');
+  $('.ui.basic.modal').modal('show');
+}
+
+function generateOutputs () {
+  if (window.program_obj.functions.length == 1 && window.program_obj.functions[0].commands.length == 0) {
+    showAlert(LocalizedStrings.getUI('text_teacher_generate_outputs_algorithm'));
+    return;
+  }
+  // código:
+  var code_teacher = window.generator();
+  // array com as entradas já inseridas:
+  var test_cases = JSON.parse(prepareTestCases().replace('"testcases" :', ''));
+  ivprogCore.autoGenerateTestCaseOutput(code_teacher, test_cases).catch(function (error) {
+    showAlert("Houve um erro durante a execução do seu programa: "+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);
+  }*/
+  animateOutput(fields, test_cases, 0);
+
+
+}
+
+function animateOutput (list, test_cases, index) {
+  if (list.length == index) return;
+  $(list[index]).val('');
+  for (var j = 0; j < test_cases[index].output.length; j++) {
+    console.log(test_cases[index].output[j].charCodeAt(0));
+    $(list[index]).val($(list[index]).val() + test_cases[index].output[j]);
+    if (j < test_cases[index].output.length - 1) {
+      $(list[index]).val($(list[index]).val() + '\n');
+    }
+  }
+  $(list[index]).attr('rows', test_cases[index].output.length);
+
+  $(list[index]).effect('highlight', null, 50, function() {
+    animateOutput(list, test_cases, index + 1);
+  });
+}
+
+var hist = false;
+
+function addTestCase (test_case = null) {
+  var new_row = null;
+  if (test_case) {
+    var text_row = '';
+
+    text_row += '<tr><td class="counter"></td><td class="expandingArea"><textarea rows="'+test_case.input.length+'" name="input" class="text_area_input">';
+
+    for (var i = 0; i < test_case.input.length; i ++) {
+      text_row += test_case.input[i];
+      if ((i + 1) < test_case.input.length) {
+        text_row += '\n';
+      }
+    }
+
+    text_row += '</textarea></td><td class="expandingArea"><textarea rows="'+test_case.output.length+'" name="output" class="text_area_output">';
+
+    for (var i = 0; i < test_case.output.length; i ++) {
+      text_row += test_case.output[i];
+      if ((i + 1) < test_case.output.length) {
+        text_row += '\n';
+      }
+    }
+
+    text_row += '</textarea></td><td class="btn_actions"><div class="ui button_remove_case"><i class="red icon times large"></i></div></td></tr>';
+
+    new_row = $(text_row);
+  } else {
+      new_row = $('<tr><td class="counter"></td><td class="expandingArea"><textarea rows="1" name="input" class="text_area_input"></textarea></td><td class="expandingArea"><textarea rows="1" name="output" class="text_area_output"></textarea></td><td class="btn_actions"><div class="ui button_remove_case"><i class="red icon times large"></i></div></td></tr>');
+  }
+  $('.content_cases').append(new_row);
+
+  new_row.find('.button_remove_case').click(function(e) {
+      new_row.remove();
+      updateTestCaseCounter();
+  });
+
+  new_row.find('textarea').on('input', function(e) {
+      var lines = $(this).val().split('\n').length;
+      $(this).attr('rows', lines);
+  });
+
+  updateTestCaseCounter();
+
+  $('.text_area_output').keydown(function(e) {
+    var code = e.keyCode || e.which;
+    if (code == 9 && $(this).closest("tr").is(":last-child")) {
+      hist = true;
+      addTestCase();
+    }
+  });
+  if (test_case == null) {
+    if (!hist) {
+      $( ".content_cases tr:last" ).find('.text_area_input').focus();
+    } else {
+      hist = false;
+    }
+  }
+}
+
+function updateTestCaseCounter () {
+    var i = 1;
+    $( ".content_cases" ).find('tr').each(function() {
+      $( this ).find('.counter').text(i);
+      ++i;
+    });
+}
+
+
+function prepareTableSettings (div_el) {
+
+  div_el.append('<div class="ui segment settings_topic"><h3 class="ui header"><i class="window maximize outline icon"></i><div class="content">'+LocalizedStrings.getUI('text_config_programming')+'</div></h3>'
+    +'<div class="content content_segment_settings"><form name="settings_programming_type"><div class="ui stackable five column grid">'
+    +'<div class="column"><div class="ui radio"><input type="radio" name="programming_type" id="programming_textual" value="textual" tabindex="0" class="hidden small"><label for="programming_textual">'+LocalizedStrings.getUI('text_config_programming_textual')+'</label></div></div>'
+    +'<div class="column"><div class="ui radio"><input type="radio" name="programming_type" id="programming_visual" value="visual" checked tabindex="0" class="hidden small"><label for="programming_visual">'+LocalizedStrings.getUI('text_config_programming_visual')+'</label></div></div>'
+    +'</div></form></div></div>');
+
+  div_el.append('<div class="ui segment settings_topic"><h3 class="ui header"><i class="qrcode icon"></i><div class="content">'+LocalizedStrings.getUI('text_teacher_data_types')+'</div></h3>'
+    +'<div class="content content_segment_settings"><form name="settings_data_types"><div class="ui stackable five column grid">'
+    +'<div class="column"><div class="ui checkbox"><input type="checkbox" name="integer_data_type" checked tabindex="0" class="hidden small"><label>'+LocalizedStrings.getUI('type_integer')+'</label></div></div>'
+    +'<div class="column"><div class="ui checkbox"><input type="checkbox" name="real_data_type" checked tabindex="0" class="hidden small"><label>'+LocalizedStrings.getUI('type_real')+'</label></div></div>'
+    +'<div class="column"><div class="ui checkbox"><input type="checkbox" name="text_data_type" checked tabindex="0" class="hidden small"><label>'+LocalizedStrings.getUI('type_text')+'</label></div></div>'
+    +'<div class="column"><div class="ui checkbox"><input type="checkbox" name="boolean_data_type" checked tabindex="0" class="hidden small"><label>'+LocalizedStrings.getUI('type_boolean')+'</label></div></div>'
+    +'<div class="column"><div class="ui checkbox"><input type="checkbox" name="void_data_type" checked tabindex="0" class="hidden small"><label>'+LocalizedStrings.getUI('type_void')+'</label></div></div>'
+    +'</div></form></div></div>');
+
+  div_el.append('<div class="ui segment settings_topic"><h3 class="ui header"><i class="code icon"></i><div class="content">'+LocalizedStrings.getUI('text_teacher_commands')+'</div></h3>'
+    +'<div class="content content_segment_settings"><form name="settings_commands"><div class="ui stackable three column grid">'
+    +'<div class="column"><div class="ui checkbox"><input type="checkbox" name="commands_read" checked tabindex="0" class="hidden small"><label>'+LocalizedStrings.getUI('text_read_var')+'</label></div></div>'
+    +'<div class="column"><div class="ui checkbox"><input type="checkbox" name="commands_write" checked tabindex="0" class="hidden small"><label>'+LocalizedStrings.getUI('text_write_var')+'</label></div></div>'
+    +'<div class="column"><div class="ui checkbox"><input type="checkbox" name="commands_comment" checked tabindex="0" class="hidden small"><label>'+LocalizedStrings.getUI('text_comment')+'</label></div></div>'
+    +'<div class="column"><div class="ui checkbox"><input type="checkbox" name="commands_attribution" checked tabindex="0" class="hidden small"><label>'+LocalizedStrings.getUI('text_attribution')+'</label></div></div>'
+    +'<div class="column"><div class="ui checkbox"><input type="checkbox" name="commands_functioncall" checked tabindex="0" class="hidden small"><label>'+LocalizedStrings.getUI('text_functioncall')+'</label></div></div>'
+    +'<div class="column"><div class="ui checkbox"><input type="checkbox" name="commands_iftrue" checked tabindex="0" class="hidden small"><label>'+LocalizedStrings.getUI('text_iftrue')+'</label></div></div>'
+    +'<div class="column"><div class="ui checkbox"><input type="checkbox" name="commands_repeatNtimes" checked tabindex="0" class="hidden small"><label>'+LocalizedStrings.getUI('text_repeatNtimes')+'</label></div></div>'
+    +'<div class="column"><div class="ui checkbox"><input type="checkbox" name="commands_while" checked tabindex="0" class="hidden small"><label>'+LocalizedStrings.getUI('text_whiletrue')+'</label></div></div>'
+    +'<div class="column"><div class="ui checkbox"><input type="checkbox" name="commands_dowhile" checked tabindex="0" class="hidden small"><label>'+LocalizedStrings.getUI('text_dowhiletrue')+'</label></div></div>'
+    +'<div class="column"><div class="ui checkbox"><input type="checkbox" name="commands_switch" checked tabindex="0" class="hidden small"><label>'+LocalizedStrings.getUI('text_switch')+'</label></div></div>'
+    +'</div></form></div></div>');
+
+  div_el.append('<div class="ui segment settings_topic"><h3 class="ui header"><i class="terminal icon"></i><div class="content">'+LocalizedStrings.getUI('text_teacher_functions')+'</div></h3>'
+    +'<div class="content content_segment_settings"><form name="settings_functions"><div class="ui stackable one column grid">'
+    +'<div class="column"><div class="ui checkbox"><input type="checkbox" name="functions_creation" checked tabindex="0" class="hidden small"><label>'+LocalizedStrings.getUI('text_teacher_create_functions')+'</label></div></div>'
+    +'<div class="column"><div class="ui checkbox"><input type="checkbox" name="functions_move" checked tabindex="0" class="hidden small"><label>'+LocalizedStrings.getUI('text_teacher_create_movement_functions')+'</label></div></div>'
+    +'</div></form></div></div>');
+
+  div_el.append('<div class="ui segment settings_topic"><h3 class="ui header"><i class="filter icon"></i><div class="content">'+LocalizedStrings.getUI('text_teacher_filter')+'</div><i class="circular inverted teal question icon"></i></h3>'
+    +'<div class="content content_segment_settings"><form name="settings_filter"><div class="ui stackable one column grid">'
+    +'<div class="column"><div class="ui checkbox"><input type="checkbox" name="filter_active" tabindex="0" class="hidden small"><label>'+LocalizedStrings.getUI('text_teacher_filter_active')+'</label></div></div>'
+    +'</div></form></div></div>');
+
+  $('.circular.inverted.teal.question.icon').popup({
+    content : LocalizedStrings.getUI("text_teacher_filter_help"),
+    delay: {
+      show: 750,
+      hide: 0
+    }
+  });
+
+  $('.ui.checkbox').checkbox();
+
+}
+
+function getTrackingLogs () {
+  return ivprogCore.getLogsAsString();
+  // var ret = "";
+  // for (var i = 0; i < trackingMatrix.length; ++i) {
+  //   ret += "\n" + trackingMatrix[i][0] + "," + trackingMatrix[i][1] + "," + trackingMatrix[i][2];
+  //   if (trackingMatrix[i][3] === 1) {
+  //     ret += ',' + trackingMatrix[i][3] + ',"' + trackingMatrix[i][4] + '"';
+  //   }
+  // }
+  // return ret;
+}
+
+// Tracking mouse movements
+// var trackingMatrix = [];
+
+/* function adCoords(e, code){
+  var x = e.pageX;
+  var y = e.pageY;
+  if (code === 1) {
+    return [new Date().getTime(), x, y, code, e.target.classList['value']];
+  } else {
+    return [x, y, code];
+  }
+} */
+
+// $( document ).ready(function() {
+
+//     if (inIframe()) {
+//         orderIcons();
+//         orderWidth();
+//     }
+//     renderAlgorithm();
+// });
+
+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() {
+  $('.ui.one.column.doubling.stackable.grid.container').css('display', 'none');
+  $('.only_in_frame').css('display', 'block');
+}
+
+
+function inIframe () {
+  try {
+    return window.self !== window.top;
+  } catch (e) {
+    return true;
+  }
+}
+
+
+function full_screen() {
+  // check if user allows full screen of elements. This can be enabled or disabled in browser config. By default its enabled.
+  //its also used to check if browser supports full screen api.
+  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.getElementById("ui_main_div");
+      //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');
+  }
+}
+
+function getAutoEvalOriginalData () {
+  return parent.getAutoEvalOriginalData();
+}
+
+function teacherAutoEval (data) {
+  previousContent = data;
+  // Ver arquivo js/util/iassignHelpers.js
+  var content = ivprogCore.prepareActivityToStudentHelper(data).getOrElse(null);
+  if(!content) {
+    showInvalidData();
+    return;
+  }
+  // Casos de testes agora são delegados ao tratamento apropriado pela função acima
+  // var testCases = content.testcases;
+  settingsProgrammingTypes = content.settingsProgrammingType;
+  settingsDataTypes = content.settingsDataTypes;
+  settingsCommands = content.settingsCommands;
+  settingsFunctions = content.settingsFunctions;
+  settingsFilter = content.settingsFilter;
+
+  if (content.algorithmInIlm != null) {
+    algorithm_in_ilm = content.algorithmInIlm;
+    parsePreviousAlgorithm();
+    var originalData = getAutoEvalOriginalData();
+    ivprogCore.autoEval(originalData, parent.postResultAutoEval);
+  }
+
+  ivprogTextualOrVisual();
+  if (settingsFilter && settingsFilter[0]) {
+
+    blockAllEditingOptions(); 
+  }
+}
+
+function displayGrade(grade) {
+  alert(grade);
+}
+
+function showInvalidData () {
+  $('.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');
+  $('.ui.height_100.add_accordion').dimmer('add content', '.dimmer_content_message');
+  $('.ui.height_100.add_accordion').dimmer('show');
+}

+ 821 - 0
ivprog/js/iassign-integration-functions.js.1

@@ -0,0 +1,821 @@
+// Função para ler parâmetros informados pelo iTarefa via URL
+// Apesar de não ser obrigatório, será muito útil para capturar os parâmetros
+function getParameterByName (name, defaultReturn = null) {
+  var match = RegExp('[?&]' + name + '=([^&]*)').exec(window.location.search);
+  return match ? decodeURIComponent(match[1].replace(/\+/g, ' ')) : defaultReturn;
+}
+
+// Criando um object com os parâmetros informados pelo iTarefa
+// Observe que para cada parâmetro, é realizada a chamada do método getParameterByName, implementado acima
+var iLMparameters = {
+  iLM_PARAM_ServerToGetAnswerURL: getParameterByName("iLM_PARAM_ServerToGetAnswerURL"),
+  iLM_PARAM_SendAnswer: getParameterByName("iLM_PARAM_SendAnswer"),
+  iLM_PARAM_AssignmentURL: getParameterByName("iLM_PARAM_AssignmentURL"),
+  iLM_PARAM_Assignment: getParameterByName("iLM_PARAM_Assignment"),
+  iLM_PARAM_TeacherAutoEval: getParameterByName("iLM_PARAM_TeacherAutoEval"),
+  lang: getParameterByName("lang", "pt")
+};
+
+// Set the lang parameter to the localStorage for easy access
+// and no dependency to the global scope, avoind future 'strict mode' problems
+//localStorage.setItem('ivprog.lang', iLMparameters.lang);
+
+function removeCollapseValue (command) {
+  if (command.collapsed) {
+    delete command.collapsed;
+  }
+  if (command.type == 'iftrue') {
+    if (command.commands_block)
+      for (var i = 0; i < command.commands_block.length; i++) {
+        removeCollapseValue(command.commands_block[i]);
+      }
+    if (command.commands_else)
+      for (var i = 0; i < command.commands_else.length; i++) {
+        removeCollapseValue(command.commands_else[i]);
+      }
+  } else if (command.type == 'repeatNtimes' 
+            || command.type == 'whiletrue' 
+            || command.type == 'dowhiletrue' ) {
+    if (command.commands_block)
+      for (var i = 0; i < command.commands_block.length; i++) {
+        removeCollapseValue(command.commands_block[i]);
+      }
+  }
+}
+
+// Função chamada pelo iTarefa quando o professor finaliza a criação da atividade
+// ou quando o aluno finaliza a resolução do exercício
+// O retorno é um JSON com os dados do exercício ou da resolução
+// Esse retorno será armazenado no banco de dados do Moodle, pelo iTarefa
+function getAnswer () {
+  // Remover o colapsar usado localmente:
+  if (window.program_obj) {
+    for (var i = 0; i < window.program_obj.functions.length; i++) {
+      for (var j = 0; j < window.program_obj.functions[i].commands.length; j++) {
+        removeCollapseValue(window.program_obj.functions[i].commands[j]);
+      }
+    }
+  }
+  // Se o parâmetro "iLM_PARAM_SendAnswer" for false,
+  // então trata-se de resolução de atividade
+  if (iLMparameters.iLM_PARAM_SendAnswer == 'false') {
+    // Montar o retorno com a resposta do aluno
+    var contentToSend = previousContent.split("\n::algorithm::")[0];
+    contentToSend += '\n::algorithm::';
+
+    if (settingsProgrammingTypes == "textual") {
+      contentToSend +=  ivprogCore.CodeEditor.getCode();
+    } else {
+      contentToSend += JSON.stringify(window.program_obj, function(key, value) {
+        if (key == 'dom_object') {
+            return;
+        }
+        return value;
+      });
+    }
+
+    contentToSend += '\n::logs::';
+    contentToSend += getTrackingLogs();
+
+    return contentToSend;
+
+  } else {
+    // Montar o retorno com a criação da atividade do professor
+    var ret = ' { ' + prepareTestCases()
+        + ',\n"settings_programming_type": \n' + JSON.stringify($('form[name="settings_programming_type"]').serializeArray())
+        + ',\n"settings_data_types": \n' + JSON.stringify($('form[name="settings_data_types"]').serializeArray())
+        + ',\n"settings_commands": \n' + JSON.stringify($('form[name="settings_commands"]').serializeArray())
+        + ',\n"settings_functions": \n' + JSON.stringify($('form[name="settings_functions"]').serializeArray())
+        + ',\n"settings_filter": \n' + JSON.stringify($('form[name="settings_filter"]').serializeArray())
+        + ' } ';
+
+    if ($("input[name='include_algo']").is(':checked')) {
+      ret += '\n::algorithm::';
+      ret += JSON.stringify(window.program_obj, function(key, value) {
+
+          if (key == 'dom_object') {
+              return;
+          }
+          return value;
+      });
+    }
+
+    return ret;
+  }
+}
+
+function prepareTestCases () {
+  var ret = ' \n "testcases" : [ '
+  var test_cases_array = $('form[name="test_cases"]').serializeArray();
+  console.log(test_cases_array);
+  for (var i = 0; i < test_cases_array.length; i = i + 2) {
+    ret += '\n{ ';
+    ret += '\n "input": [';
+    var inps = test_cases_array[i].value.match(/[^\r\n]+/g);
+    if (inps) {
+      for (var j = 0; j < inps.length; j++) {
+        ret += '"' + inps[j] + '"';
+        if ((j + 1) < inps.length) {
+          ret += ', ';
+        }
+      }
+    }
+    ret += '], \n "output": [';
+    var outs = test_cases_array[i+1].value.match(/[^\r\n]+/g);
+    console.log(outs);
+    if (outs) {
+      for (var j = 0; j < outs.length; j++) {
+        console.log("output -> ",outs[j]);
+        ret += '"' + outs[j] + '"';
+        if ((j + 1) < outs.length) {
+          ret += ', ';
+        }
+      }
+    }
+    ret += ']';
+    ret += '\n}'
+    if ((i + 2) < test_cases_array.length) {
+      ret += ',';
+    }
+  }
+  ret += '\n] ';
+  return ret;
+}
+
+// Função chamada pelo iTarefa para receber a nota do aluno na atividade
+// O retorno é um valor entre 0.0 e 1.0
+function getEvaluation () {
+  if (iLMparameters.iLM_PARAM_SendAnswer == 'false') {
+    // A chamada do método abaixo é obrigatória!
+    // Observe que a chamada parte do iLM para o iTarefa
+    //parent.getEvaluationCallback(window.studentGrade);
+
+    var canRunAssessment = runCodeAssessment();
+    if(canRunAssessment === -1) {
+      parent.getEvaluationCallback(-1);
+    }
+  }
+}
+
+//var testCases = null
+var settingsDataTypes = null;
+var settingsCommands = null;
+var settingsFunctions = null;
+var settingsProgrammingTypes = null;
+var settingsFilter = null;
+var algorithm_in_ilm = null;
+var previousContent = null;
+
+// Função para que o iMA leia os dados da atividade fornecidos pelo iTarefa
+function getiLMContent () {
+
+  // O parâmetro "iLM_PARAM_Assignment" fornece o URL do endereço que deve ser
+  // requisitado via AJAX para a captura dos dados da atividade
+  $.get(iLMparameters.iLM_PARAM_Assignment, function (data) {
+    //professor invocou a avaliação automática dos exercícios do bloco
+    if (iLMparameters.iLM_PARAM_TeacherAutoEval != null) {
+        teacherAutoEval(data);
+        //não deve exibir nenhuma interface...
+        return;
+    } else if (iLMparameters.iLM_PARAM_SendAnswer == 'false') {
+        // Aluno está trabalhando em alguma atividade:
+        previousContent = data;
+        prepareActivityToStudent(data);
+    } else { // Professor está editando uma atividade:
+        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
+  var content = ivprogCore.prepareActivityToStudentHelper(ilm_cont).getOrElse(null);
+  if(!content) {
+    showInvalidData();
+    return;
+  }
+  var testCases = ivprogCore.getTestCases();
+
+  settingsProgrammingTypes = content.settingsProgrammingType;
+  settingsDataTypes = content.settingsDataTypes;
+  settingsCommands = content.settingsCommands;
+  settingsFunctions = content.settingsFunctions;
+  settingsFilter = content.settingsFilter;
+
+  for (var i = 0; i < testCases.length; i++) {
+    addTestCase(testCases[i]);
+  }
+
+  if (content.algorithmInIlm != null) {
+    algorithm_in_ilm = content.algorithmInIlm;
+    $("input[name='include_algo']").prop('checked', true);
+    includePreviousAlgorithm();
+    renderAlgorithm();
+  }
+
+  ivprogTextualOrVisual();
+  if (settingsFilter && settingsFilter[0]) {
+    blockAllEditingOptions();
+  }
+}
+
+function parsePreviousAlgorithm () {
+  window.program_obj.functions = JSON.parse(algorithm_in_ilm).functions;
+  window.program_obj.globals = JSON.parse(algorithm_in_ilm).globals;
+}
+
+function includePreviousAlgorithm () {
+  if (settingsProgrammingTypes == "textual") {
+    return;
+  }
+
+  parsePreviousAlgorithm();
+
+  window.watchW.watch(window.program_obj.globals, function(){
+    if (window.insertContext) {
+      setTimeout(function(){ renderAlgorithm(); }, 300);
+      window.insertContext = false;
+    } else {
+      renderAlgorithm();
+    }
+  }, 1);
+
+  for (var i = 0; i < window.program_obj.functions.length; i ++) {
+    window.watchW.watch(window.program_obj.functions[i].parameters_list, function(){
+      if (window.insertContext) {
+        setTimeout(function(){ renderAlgorithm(); }, 300);
+        window.insertContext = false;
+      } else {
+        renderAlgorithm();
+      }
+    }, 1);
+
+    window.watchW.watch(window.program_obj.functions[i].variables_list, function(){
+      if (window.insertContext) {
+        setTimeout(function(){ renderAlgorithm(); }, 300);
+        window.insertContext = false;
+      } else {
+        renderAlgorithm();
+      }
+    }, 1);
+
+    if (window.program_obj.functions[i].is_main) {
+        window.program_obj.functions[i].name = LocalizedStrings.getUI("start");
+    }
+  }
+
+  window.watchW.watch(window.program_obj.functions, function(){
+    if (window.insertContext) {
+      setTimeout(function(){ renderAlgorithm(); }, 300);
+      window.insertContext = false;
+    } else {
+      renderAlgorithm();
+    }
+  }, 1);
+}
+
+function prepareActivityToStudent (ilm_cont) {
+    // Ver arquivo js/util/iassignHelpers.js
+    var content = ivprogCore.prepareActivityToStudentHelper(ilm_cont).getOrElse(null);
+    if(!content) {
+      showInvalidData();
+      return;
+    }
+    // Casos de testes agora são delegados ao tratamento apropriado pela função acima
+    // var testCases = content.testcases;
+    settingsProgrammingTypes = content.settingsProgrammingType;
+    settingsDataTypes = content.settingsDataTypes;
+    settingsCommands = content.settingsCommands;
+    settingsFunctions = content.settingsFunctions;
+    settingsFilter = content.settingsFilter;
+
+    if (content.algorithmInIlm != null) {
+        algorithm_in_ilm = content.algorithmInIlm;
+        includePreviousAlgorithm();
+    }
+    $('.assessment_button').removeClass('disabled');
+    renderAlgorithm();
+
+    ivprogTextualOrVisual();
+    if (settingsFilter && settingsFilter[0]) {
+      blockAllEditingOptions();
+    }
+}
+
+// Função para organizar se para criação, visualização ou resolução de atividade
+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, então trata-se de resolução de atividade,
+  // portanto, a "DIV" de resolução é liberada
+  if (iLMparameters.iLM_PARAM_SendAnswer == 'false') {
+    //$('.resolucao').css("display","block");
+    getiLMContent();
+
+    // $('.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 não esteja em modo de resolução de atividade, a visualização no momento
+    // é para a elaboração de atividade:
+    //$('.elaboracao').css("display","block");
+
+    // Se possuir o parâmetro iLMparameters.iLM_PARAM_Assignment, o professor
+    // está editando uma atividade:
+    getiLMContent();
+  } else {
+    renderAlgorithm();
+  }
+
+  if ((iLMparameters.iLM_PARAM_AssignmentURL == "true") && (iLMparameters.iLM_PARAM_SendAnswer == "true")) {
+    prepareActivityCreation();
+  }
+}
+
+function blockAllEditingOptions () {
+
+  if ((iLMparameters.iLM_PARAM_AssignmentURL == "true") && (iLMparameters.iLM_PARAM_SendAnswer == "true")) {
+    return;
+  }
+
+  $('.add_global_button').addClass('disabled');
+  $('.move_function').addClass('disabled');
+  $('.add_function_button').addClass('disabled');
+  $('.add_var_button_function .ui.icon.button.purple').addClass('disabled');
+  $('.add_var_button_function').addClass('disabled');
+  $('.menu_commands').addClass('disabled');
+
+  $('.global_type').addClass('disabled');
+  $('.editing_name_var').addClass('disabled');
+  $('.span_value_variable').addClass('disabled');
+
+  $('.remove_global').addClass('disabled');
+  $('.ui.icon.ellipsis.vertical.inverted').addClass('disabled');
+
+  $('.alternate_constant').addClass('disabled');
+  $('.remove_variable').addClass('disabled');
+
+  $('.add_global_matrix_column').addClass('disabled');
+  $('.remove_global_matrix_column').addClass('disabled');
+
+  $('.add_global_matrix_line').addClass('disabled');
+  $('.remove_global_matrix_line').addClass('disabled');
+
+  $('.add_global_vector_column').addClass('disabled');
+  $('.remove_global_vector_column').addClass('disabled');
+
+  $('.add_expression').addClass('disabled');
+  $('.add_parentheses').addClass('disabled');
+
+  $('.remove_function_button').addClass('disabled');
+  $('.button_remove_command').addClass('disabled');
+
+  $('.command_drag').addClass('disabled');
+  $('.simple_add').addClass('disabled');
+
+  $('.add_parameter_button').addClass('disabled');
+  $('.parameter_div_edit').addClass('disabled');
+  $('.function_name_div_updated').addClass('disabled');
+  $('.value_rendered').addClass('disabled');
+  $('.var_name').addClass('disabled');
+  $('.variable_rendered').addClass('disabled');
+
+  $('.dropdown').addClass('disabled');
+  $('.remove_parameter').addClass('disabled');
+
+  $('.ui.dropdown.global_type.disabled').css('opacity', '1');
+  $('.ui.dropdown.variable_type.disabled').css('opacity', '1');
+  $('.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") {
+      $('.ivprog_visual_panel').css('display', 'none');
+      $('.ivprog_textual_panel').css('display', 'block');
+      $('.ivprog_textual_panel').removeClass('loading');
+
+      $('.visual_coding_button').removeClass('active');
+      $('.textual_coding_button').addClass('active');
+      $('.visual_coding_button').addClass('disabled');
+
+      let textual_code = algorithm_in_ilm;
+      if(!textual_code) {
+        textual_code = ivprogCore.LocalizedStrings.getUI("initial_program_code");
+        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);
+    }
+    if (settingsProgrammingTypes == "visual") {
+
+    }
+  }
+}
+
+function iassingIntegration () {
+
+  // Disable by default...
+  $('.assessment_button').addClass('disabled');
+
+  prepareEnvironment();
+  if (inIframe()) {
+    orderIcons();
+    orderWidth();
+  }
+}
+
+// Função para preparar a interface para o professor criar atividade:
+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>');
+
+  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>');
+
+  $('.tab_test_cases').append(cases_test_div);
+
+  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()) {
+      $('.ui.styled.accordion').css('width', '96%');
+  }
+}
+
+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>';
+
+  div_el.append(table_el);
+
+  var table_buttons = '<table class="table_buttons"><tr><td>'
+    + '<button class="ui teal labeled icon button button_add_case"><i class="plus icon"></i>'+LocalizedStrings.getUI('text_teacher_test_case_add')+'</button>'
+    + '</td><td class="right_align">'
+    + '<button class="ui orange labeled icon button button_generate_outputs"><i class="sign-in icon"></i>'+LocalizedStrings.getUI('text_teacher_generate_outputs')+'</button>'
+    + '</td></tr></table>';
+
+  div_el.append(table_buttons);
+
+  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();
+  });
+}
+
+function showAlert (msg) {
+  $('.ui.basic.modal .content').html('<h3>'+msg+'</h3>');
+  $('.ui.basic.modal').modal('show');
+}
+
+function generateOutputs () {
+  if (window.program_obj.functions.length == 1 && window.program_obj.functions[0].commands.length == 0) {
+    showAlert(LocalizedStrings.getUI('text_teacher_generate_outputs_algorithm'));
+    return;
+  }
+  // código:
+  var code_teacher = window.generator();
+  // array com as entradas já inseridas:
+  var test_cases = JSON.parse(prepareTestCases().replace('"testcases" :', ''));
+  ivprogCore.autoGenerateTestCaseOutput(code_teacher, test_cases).catch(function (error) {
+    showAlert("Houve um erro durante a execução do seu programa: "+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);
+  }*/
+  animateOutput(fields, test_cases, 0);
+
+
+}
+
+function animateOutput (list, test_cases, index) {
+  if (list.length == index) return;
+  $(list[index]).val('');
+  for (var j = 0; j < test_cases[index].output.length; j++) {
+    console.log(test_cases[index].output[j].charCodeAt(0));
+    $(list[index]).val($(list[index]).val() + test_cases[index].output[j]);
+    if (j < test_cases[index].output.length - 1) {
+      $(list[index]).val($(list[index]).val() + '\n');
+    }
+  }
+  $(list[index]).attr('rows', test_cases[index].output.length);
+
+  $(list[index]).effect('highlight', null, 50, function() {
+    animateOutput(list, test_cases, index + 1);
+  });
+}
+
+var hist = false;
+
+function addTestCase (test_case = null) {
+  var new_row = null;
+  if (test_case) {
+    var text_row = '';
+
+    text_row += '<tr><td class="counter"></td><td class="expandingArea"><textarea rows="'+test_case.input.length+'" name="input" class="text_area_input">';
+
+    for (var i = 0; i < test_case.input.length; i ++) {
+      text_row += test_case.input[i];
+      if ((i + 1) < test_case.input.length) {
+        text_row += '\n';
+      }
+    }
+
+    text_row += '</textarea></td><td class="expandingArea"><textarea rows="'+test_case.output.length+'" name="output" class="text_area_output">';
+
+    for (var i = 0; i < test_case.output.length; i ++) {
+      text_row += test_case.output[i];
+      if ((i + 1) < test_case.output.length) {
+        text_row += '\n';
+      }
+    }
+
+    text_row += '</textarea></td><td class="btn_actions"><div class="ui button_remove_case"><i class="red icon times large"></i></div></td></tr>';
+
+    new_row = $(text_row);
+  } else {
+      new_row = $('<tr><td class="counter"></td><td class="expandingArea"><textarea rows="1" name="input" class="text_area_input"></textarea></td><td class="expandingArea"><textarea rows="1" name="output" class="text_area_output"></textarea></td><td class="btn_actions"><div class="ui button_remove_case"><i class="red icon times large"></i></div></td></tr>');
+  }
+  $('.content_cases').append(new_row);
+
+  new_row.find('.button_remove_case').click(function(e) {
+      new_row.remove();
+      updateTestCaseCounter();
+  });
+
+  new_row.find('textarea').on('input', function(e) {
+      var lines = $(this).val().split('\n').length;
+      $(this).attr('rows', lines);
+  });
+
+  updateTestCaseCounter();
+
+  $('.text_area_output').keydown(function(e) {
+    var code = e.keyCode || e.which;
+    if (code == 9 && $(this).closest("tr").is(":last-child")) {
+      hist = true;
+      addTestCase();
+    }
+  });
+  if (test_case == null) {
+    if (!hist) {
+      $( ".content_cases tr:last" ).find('.text_area_input').focus();
+    } else {
+      hist = false;
+    }
+  }
+}
+
+function updateTestCaseCounter () {
+    var i = 1;
+    $( ".content_cases" ).find('tr').each(function() {
+      $( this ).find('.counter').text(i);
+      ++i;
+    });
+}
+
+
+function prepareTableSettings (div_el) {
+
+  div_el.append('<div class="ui segment settings_topic"><h3 class="ui header"><i class="window maximize outline icon"></i><div class="content">'+LocalizedStrings.getUI('text_config_programming')+'</div></h3>'
+    +'<div class="content content_segment_settings"><form name="settings_programming_type"><div class="ui stackable five column grid">'
+    +'<div class="column"><div class="ui radio"><input type="radio" name="programming_type" id="programming_textual" value="textual" tabindex="0" class="hidden small"><label for="programming_textual">'+LocalizedStrings.getUI('text_config_programming_textual')+'</label></div></div>'
+    +'<div class="column"><div class="ui radio"><input type="radio" name="programming_type" id="programming_visual" value="visual" checked tabindex="0" class="hidden small"><label for="programming_visual">'+LocalizedStrings.getUI('text_config_programming_visual')+'</label></div></div>'
+    +'</div></form></div></div>');
+
+  div_el.append('<div class="ui segment settings_topic"><h3 class="ui header"><i class="qrcode icon"></i><div class="content">'+LocalizedStrings.getUI('text_teacher_data_types')+'</div></h3>'
+    +'<div class="content content_segment_settings"><form name="settings_data_types"><div class="ui stackable five column grid">'
+    +'<div class="column"><div class="ui checkbox"><input type="checkbox" name="integer_data_type" checked tabindex="0" class="hidden small"><label>'+LocalizedStrings.getUI('type_integer')+'</label></div></div>'
+    +'<div class="column"><div class="ui checkbox"><input type="checkbox" name="real_data_type" checked tabindex="0" class="hidden small"><label>'+LocalizedStrings.getUI('type_real')+'</label></div></div>'
+    +'<div class="column"><div class="ui checkbox"><input type="checkbox" name="text_data_type" checked tabindex="0" class="hidden small"><label>'+LocalizedStrings.getUI('type_text')+'</label></div></div>'
+    +'<div class="column"><div class="ui checkbox"><input type="checkbox" name="boolean_data_type" checked tabindex="0" class="hidden small"><label>'+LocalizedStrings.getUI('type_boolean')+'</label></div></div>'
+    +'<div class="column"><div class="ui checkbox"><input type="checkbox" name="void_data_type" checked tabindex="0" class="hidden small"><label>'+LocalizedStrings.getUI('type_void')+'</label></div></div>'
+    +'</div></form></div></div>');
+
+  div_el.append('<div class="ui segment settings_topic"><h3 class="ui header"><i class="code icon"></i><div class="content">'+LocalizedStrings.getUI('text_teacher_commands')+'</div></h3>'
+    +'<div class="content content_segment_settings"><form name="settings_commands"><div class="ui stackable three column grid">'
+    +'<div class="column"><div class="ui checkbox"><input type="checkbox" name="commands_read" checked tabindex="0" class="hidden small"><label>'+LocalizedStrings.getUI('text_read_var')+'</label></div></div>'
+    +'<div class="column"><div class="ui checkbox"><input type="checkbox" name="commands_write" checked tabindex="0" class="hidden small"><label>'+LocalizedStrings.getUI('text_write_var')+'</label></div></div>'
+    +'<div class="column"><div class="ui checkbox"><input type="checkbox" name="commands_comment" checked tabindex="0" class="hidden small"><label>'+LocalizedStrings.getUI('text_comment')+'</label></div></div>'
+    +'<div class="column"><div class="ui checkbox"><input type="checkbox" name="commands_attribution" checked tabindex="0" class="hidden small"><label>'+LocalizedStrings.getUI('text_attribution')+'</label></div></div>'
+    +'<div class="column"><div class="ui checkbox"><input type="checkbox" name="commands_functioncall" checked tabindex="0" class="hidden small"><label>'+LocalizedStrings.getUI('text_functioncall')+'</label></div></div>'
+    +'<div class="column"><div class="ui checkbox"><input type="checkbox" name="commands_iftrue" checked tabindex="0" class="hidden small"><label>'+LocalizedStrings.getUI('text_iftrue')+'</label></div></div>'
+    +'<div class="column"><div class="ui checkbox"><input type="checkbox" name="commands_repeatNtimes" checked tabindex="0" class="hidden small"><label>'+LocalizedStrings.getUI('text_repeatNtimes')+'</label></div></div>'
+    +'<div class="column"><div class="ui checkbox"><input type="checkbox" name="commands_while" checked tabindex="0" class="hidden small"><label>'+LocalizedStrings.getUI('text_whiletrue')+'</label></div></div>'
+    +'<div class="column"><div class="ui checkbox"><input type="checkbox" name="commands_dowhile" checked tabindex="0" class="hidden small"><label>'+LocalizedStrings.getUI('text_dowhiletrue')+'</label></div></div>'
+    +'<div class="column"><div class="ui checkbox"><input type="checkbox" name="commands_switch" checked tabindex="0" class="hidden small"><label>'+LocalizedStrings.getUI('text_switch')+'</label></div></div>'
+    +'</div></form></div></div>');
+
+  div_el.append('<div class="ui segment settings_topic"><h3 class="ui header"><i class="terminal icon"></i><div class="content">'+LocalizedStrings.getUI('text_teacher_functions')+'</div></h3>'
+    +'<div class="content content_segment_settings"><form name="settings_functions"><div class="ui stackable one column grid">'
+    +'<div class="column"><div class="ui checkbox"><input type="checkbox" name="functions_creation" checked tabindex="0" class="hidden small"><label>'+LocalizedStrings.getUI('text_teacher_create_functions')+'</label></div></div>'
+    +'<div class="column"><div class="ui checkbox"><input type="checkbox" name="functions_move" checked tabindex="0" class="hidden small"><label>'+LocalizedStrings.getUI('text_teacher_create_movement_functions')+'</label></div></div>'
+    +'</div></form></div></div>');
+
+  div_el.append('<div class="ui segment settings_topic"><h3 class="ui header"><i class="filter icon"></i><div class="content">'+LocalizedStrings.getUI('text_teacher_filter')+'</div><i class="circular inverted teal question icon"></i></h3>'
+    +'<div class="content content_segment_settings"><form name="settings_filter"><div class="ui stackable one column grid">'
+    +'<div class="column"><div class="ui checkbox"><input type="checkbox" name="filter_active" tabindex="0" class="hidden small"><label>'+LocalizedStrings.getUI('text_teacher_filter_active')+'</label></div></div>'
+    +'</div></form></div></div>');
+
+  $('.circular.inverted.teal.question.icon').popup({
+    content : LocalizedStrings.getUI("text_teacher_filter_help"),
+    delay: {
+      show: 750,
+      hide: 0
+    }
+  });
+
+  $('.ui.checkbox').checkbox();
+
+}
+
+function getTrackingLogs () {
+  return ivprogCore.getLogsAsString();
+  // var ret = "";
+  // for (var i = 0; i < trackingMatrix.length; ++i) {
+  //   ret += "\n" + trackingMatrix[i][0] + "," + trackingMatrix[i][1] + "," + trackingMatrix[i][2];
+  //   if (trackingMatrix[i][3] === 1) {
+  //     ret += ',' + trackingMatrix[i][3] + ',"' + trackingMatrix[i][4] + '"';
+  //   }
+  // }
+  // return ret;
+}
+
+// Tracking mouse movements
+// var trackingMatrix = [];
+
+/* function adCoords(e, code){
+  var x = e.pageX;
+  var y = e.pageY;
+  if (code === 1) {
+    return [new Date().getTime(), x, y, code, e.target.classList['value']];
+  } else {
+    return [x, y, code];
+  }
+} */
+
+// $( document ).ready(function() {
+
+//     if (inIframe()) {
+//         orderIcons();
+//         orderWidth();
+//     }
+//     renderAlgorithm();
+// });
+
+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() {
+  $('.ui.one.column.doubling.stackable.grid.container').css('display', 'none');
+  $('.only_in_frame').css('display', 'block');
+}
+
+
+function inIframe () {
+  try {
+    return window.self !== window.top;
+  } catch (e) {
+    return true;
+  }
+}
+
+
+function full_screen() {
+  // check if user allows full screen of elements. This can be enabled or disabled in browser config. By default its enabled.
+  //its also used to check if browser supports full screen api.
+  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.getElementById("ui_main_div");
+      //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');
+  }
+}
+
+function getAutoEvalOriginalData () {
+  return parent.getAutoEvalOriginalData();
+}
+
+function teacherAutoEval (data) {
+  previousContent = data;
+  // Ver arquivo js/util/iassignHelpers.js
+  var content = ivprogCore.prepareActivityToStudentHelper(data).getOrElse(null);
+  if(!content) {
+    showInvalidData();
+    return;
+  }
+  // Casos de testes agora são delegados ao tratamento apropriado pela função acima
+  // var testCases = content.testcases;
+  settingsProgrammingTypes = content.settingsProgrammingType;
+  settingsDataTypes = content.settingsDataTypes;
+  settingsCommands = content.settingsCommands;
+  settingsFunctions = content.settingsFunctions;
+  settingsFilter = content.settingsFilter;
+
+  if (content.algorithmInIlm != null) {
+    algorithm_in_ilm = content.algorithmInIlm;
+    parsePreviousAlgorithm();
+    var originalData = getAutoEvalOriginalData();
+    ivprogCore.autoEval(originalData, parent.postResultAutoEval);
+  }
+
+  ivprogTextualOrVisual();
+  if (settingsFilter && settingsFilter[0]) {
+
+    blockAllEditingOptions(); 
+  }
+}
+
+function displayGrade(grade) {
+  alert(grade);
+}
+
+function showInvalidData () {
+  $('.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');
+  $('.ui.height_100.add_accordion').dimmer('add content', '.dimmer_content_message');
+  $('.ui.height_100.add_accordion').dimmer('show');
+}

A diferenza do arquivo foi suprimida porque é demasiado grande
+ 13 - 0
ivprog/js/jquery-ui.min.js


A diferenza do arquivo foi suprimida porque é demasiado grande
+ 2 - 0
ivprog/js/jquery.min.js


A diferenza do arquivo foi suprimida porque é demasiado grande
+ 29324 - 0
ivprog/js/main.7121176c0750a24caa1f.js


A diferenza do arquivo foi suprimida porque é demasiado grande
+ 11 - 0
ivprog/js/semantic.min.js


A diferenza do arquivo foi suprimida porque é demasiado grande
+ 30080 - 0
ivprog/js/vendors~main.685d1cf2ece1ed4ebb99.js


+ 24 - 0
ivprog_contexto/js/visualUI/utils.js

@@ -0,0 +1,24 @@
+
+import $ from 'jquery';
+
+export function renderErrorMessage (dom_obj_target, message_text) {
+
+	dom_obj_target.popup({
+		html : '<i class="ui icon inverted exclamation triangle yellow"></i>' + message_text,
+		transition : "fade up",
+		on    : 'click',
+  		closable : true,
+  		movePopup : true,
+  		boundary : window,
+  		preserve : false,
+  		target : false,
+		className   : {
+		  popup       : 'ui popup invalid-identifier'
+		},
+		onHidden : function($module) {
+			dom_obj_target.popup('destroy');
+		}
+
+	}).popup('toggle');
+
+}

+ 20 - 7
relatorio_aluno_exercicio.php

@@ -1,5 +1,9 @@
 <?php
 
+ini_set('display_errors', 1);
+ini_set('display_startup_errors', 1);
+error_reporting(E_ALL);
+
 require 'functions.php';
 
 $cursos = listarCursos();
@@ -10,11 +14,9 @@ $curso_selecionado = $_GET['curso'];
 $aluno_selecionado = $_GET['aluno'];
 $exercicio_selecionado = $_GET['exercicio'];
 
-$arquivoLogsAluno = pegarLogsDoAluno($curso_selecionado, $aluno_selecionado, $exercicio_selecionado);
-
-$logsAlunoString = pegarLogsDoAlunoComoString($arquivoLogsAluno);
+$logsAlunoString = pegarLogsDoAlunoComoString($curso_selecionado, $aluno_selecionado, $exercicio_selecionado);
 
-$qualVersao = qualVersaoDoIVProg($arquivoLogsAluno);
+$arquivo_ivph_aluno = pegarArquivoMaisRecente($curso_selecionado, $aluno_selecionado, $exercicio_selecionado);
 
 ?>
 
@@ -84,8 +86,10 @@ $qualVersao = qualVersaoDoIVProg($arquivoLogsAluno);
               <select class="form-control" id="inputaluno" name="aluno">
                 <option>Todos</option>
                 <?php
-                  for ($i = 0; $i < count($alunos); $i++) {
-                    echo "<option value='$alunos[$i]'" . ($alunos[$i] == $_GET['aluno']?" selected":"") . ">" . str_replace('_', ' ', $alunos[$i]) . "</option>";
+                  foreach ($alunos as $aluno) {
+                    echo "<option value='$aluno' ". ($aluno == $_GET['aluno']?" selected":"") .">"
+                          . str_replace('-', ' ', $aluno)
+                          . "</option>";
                   }
                 ?>
               </select>
@@ -97,9 +101,18 @@ $qualVersao = qualVersaoDoIVProg($arquivoLogsAluno);
             <div class="col-sm-10">
               <select class="form-control" id="inputexercicio" name="exercicio">
                 <?php
+<<<<<<< HEAD
+
+                  foreach ($exercicios as $exercicio) {
+                    echo "<option value='$exercicio' " . ($exercicio == $_GET['exercicio']?" selected":"") . ">"
+                          . str_replace('-', ' ', $exercicio)
+                          . "</option>";
+=======
                   for ($i = 0; $i < count($exercicios); $i++) {
                     echo "<option value='".$exercicios[$i][1]."'" . ($exercicios[$i][1] == $_GET['exercicio']?" selected":"") . ">" . str_replace('_', ' ', $exercicios[$i][0]) . "</option>";
+>>>>>>> master
                   }
+
                 ?>
               </select>
             </div>
@@ -143,7 +156,7 @@ $qualVersao = qualVersaoDoIVProg($arquivoLogsAluno);
 	    line_heatmap.Container.init('hea','<?= $logsAlunoString ?>', true);
 	  </script>
 
-	  <iframe frameborder="0" name="iLM" src="ivprog_<?= $qualVersao ?>/index.html?1=1&iLM_PARAM_AssignmentURL=true&iLM_PARAM_Assignment=../temp/<?= $arquivoLogsAluno ?>&iLM_PARAM_SendAnswer=false&iLM_PARAM_ServerToGetAnswerURL=&lang=pt" <?= ($qualVersao == "menu"?"style='width: 1400px; height: 1500px;'":"style='width: 800px; height: 1500px;'") ?> >
+	  <iframe frameborder="0" name="iLM" src="ivprog/index.html?1=1&iLM_PARAM_AssignmentURL=true&iLM_PARAM_Assignment=../temp/<?=$curso_selecionado.'/'.$arquivo_ivph_aluno ?>&iLM_PARAM_SendAnswer=false&iLM_PARAM_ServerToGetAnswerURL=&lang=pt" style='width: 800px; height: 1500px;' >
 	</iframe>
 
   <?php

+ 8 - 4
relatorio_exercicio.php

@@ -78,8 +78,8 @@ $exercicio_selecionado = $_GET['exercicio'];
               <select class="form-control" id="inputaluno" name="aluno">
                 <option>Todos</option>
                 <?php
-                  for ($i = 0; $i < count($alunos); $i++) {
-                    echo "<option value='$alunos[$i]'" . ($alunos[$i] == $_GET['aluno']?" selected":"") . ">" . str_replace('_', ' ', $alunos[$i]) . "</option>";
+                  foreach ($alunos as $aluno) {
+                    echo "<option value='$aluno' ". ($aluno == $_GET['aluno']?" selected":"") .">$aluno</option>";
                   }
                 ?>
               </select>
@@ -91,8 +91,13 @@ $exercicio_selecionado = $_GET['exercicio'];
             <div class="col-sm-10">
               <select class="form-control" id="inputexercicio" name="exercicio">
                 <?php
+<<<<<<< HEAD
+                  foreach ($exercicios as $exercicio) {
+                    echo "<option value='$exercicio' " . ($exercicio == $_GET['exercicio']?" selected":"") . ">$exercicio</option>";
+=======
                   for ($i = 0; $i < count($exercicios); $i++) {
                     echo "<option value='".$exercicios[$i][1]."'" . ($exercicios[$i][1] == $_GET['exercicio']?" selected":"") . ">" . str_replace('_', ' ', $exercicios[$i][0]) . "</option>";
+>>>>>>> master
                   }
                 ?>
               </select>
@@ -132,8 +137,7 @@ $exercicio_selecionado = $_GET['exercicio'];
       $logsTodosAlunos = "";
       for ($i=0; $i < count($alunos); ++$i) { 
         $tempAluno = $alunos[$i];
-        $tempArquivoLogsAluno = pegarLogsDoAluno($curso_selecionado, $tempAluno, $exercicio_selecionado);
-        $logAluno = pegarLogsDoAlunoComoString($tempArquivoLogsAluno);
+        $logAluno = pegarLogsDoAlunoComoString($curso_selecionado, $aluno_selecionado, $exercicio_selecionado);
         if(!empty($logAluno) && is_null($arquivoLogsAluno)) {
           $arquivoLogsAluno = $tempArquivoLogsAluno;
         }