瀏覽代碼

Implementar visualização de todos os alunos

Implementar bloco de seleção de area no mapa de calor

Implementar informações do ponto no mapa de calor
Lucas de Souza 5 年之前
父節點
當前提交
54b57b2741

+ 2 - 1
.gitignore

@@ -35,4 +35,5 @@ Thumbs.db
 !.vscode/launch.json
 !.vscode/extensions.json
 
-./cursos/
+cursos/
+temp/

文件差異過大導致無法顯示
+ 1 - 1
dist/line_heatmap.js


文件差異過大導致無法顯示
+ 1 - 1
dist/line_heatmap.js.map


+ 3 - 1
index.html

@@ -7,6 +7,8 @@
   <link rel="stylesheet" href="dist/style.css">
   <style>
     #line-heatmap-canvas { width:60%; height:60%; position:absolute; }
+    #line-heatmap-view { width:60%; height:60%; position:absolute; }
+    #line-heatmap-tooltip { position:absolute; left:0; top:0; background:rgba(0,0,0,.8); color:white; font-size:14px; padding:5px; line-height:18px; display:none;}
   </style>
   <title>Test</title>
 </head>
@@ -17,7 +19,7 @@
   </div>
   <script src="dist/line_heatmap.js"></script>
   <script>
-    line_heatmap.Container.init('hea',"100,200,1,0\n100,200,1,0\n100,200,1,0\n100,200,1,0\n250,350,1,0\n250,350,1,0\n250,350,1,0\n250,350,1,0\n250,350,1,0");
+    line_heatmap.Container.init('hea',"100,200,1,0\n100,200,1,0\n100,200,1,0\n100,200,1,0\n250,350,1,0\n250,350,1,0\n250,350,1,0\n250,350,1,0\n250,350,1,0", true, {radius:100});
   </script>
 </body>
 </html>

+ 2 - 2
ivprog_contexto/css/ivprog-visual-1.0.css

@@ -16,8 +16,8 @@ body {
 
 .ivprog_visual_panel {
 	height: 96%;
-	overflow: auto;
-	overflow-x: auto;
+	/*overflow: auto;
+	overflow-x: auto;*/
 }
 
 .ivprog_textual_code {

+ 2 - 2
ivprog_menu/css/ivprog-visual-1.0 (cópia).css

@@ -16,8 +16,8 @@ body {
 
 .ivprog_visual_panel {
 	height: 96%;
-	overflow: auto;
-	overflow-x: auto;
+	/*overflow: auto;
+	overflow-x: auto;*/
 }
 
 .ivprog_textual_code {

+ 2 - 2
ivprog_menu/css/ivprog-visual-1.0.css

@@ -16,8 +16,8 @@ body {
 
 .ivprog_visual_panel, .ivprog_tab {
 	height: 96%;
-	overflow: auto;
-	overflow-x: auto;
+	/*overflow: auto;
+	overflow-x: auto;*/
 }
 
 .ivprog_functions_tab_panel {

+ 30 - 11
package-lock.json

@@ -2220,7 +2220,8 @@
         "ansi-regex": {
           "version": "2.1.1",
           "bundled": true,
-          "dev": true
+          "dev": true,
+          "optional": true
         },
         "aproba": {
           "version": "1.2.0",
@@ -2241,12 +2242,14 @@
         "balanced-match": {
           "version": "1.0.0",
           "bundled": true,
-          "dev": true
+          "dev": true,
+          "optional": true
         },
         "brace-expansion": {
           "version": "1.1.11",
           "bundled": true,
           "dev": true,
+          "optional": true,
           "requires": {
             "balanced-match": "^1.0.0",
             "concat-map": "0.0.1"
@@ -2261,17 +2264,20 @@
         "code-point-at": {
           "version": "1.1.0",
           "bundled": true,
-          "dev": true
+          "dev": true,
+          "optional": true
         },
         "concat-map": {
           "version": "0.0.1",
           "bundled": true,
-          "dev": true
+          "dev": true,
+          "optional": true
         },
         "console-control-strings": {
           "version": "1.1.0",
           "bundled": true,
-          "dev": true
+          "dev": true,
+          "optional": true
         },
         "core-util-is": {
           "version": "1.0.2",
@@ -2388,7 +2394,8 @@
         "inherits": {
           "version": "2.0.3",
           "bundled": true,
-          "dev": true
+          "dev": true,
+          "optional": true
         },
         "ini": {
           "version": "1.3.5",
@@ -2400,6 +2407,7 @@
           "version": "1.0.0",
           "bundled": true,
           "dev": true,
+          "optional": true,
           "requires": {
             "number-is-nan": "^1.0.0"
           }
@@ -2414,6 +2422,7 @@
           "version": "3.0.4",
           "bundled": true,
           "dev": true,
+          "optional": true,
           "requires": {
             "brace-expansion": "^1.1.7"
           }
@@ -2421,12 +2430,14 @@
         "minimist": {
           "version": "0.0.8",
           "bundled": true,
-          "dev": true
+          "dev": true,
+          "optional": true
         },
         "minipass": {
           "version": "2.3.5",
           "bundled": true,
           "dev": true,
+          "optional": true,
           "requires": {
             "safe-buffer": "^5.1.2",
             "yallist": "^3.0.0"
@@ -2445,6 +2456,7 @@
           "version": "0.5.1",
           "bundled": true,
           "dev": true,
+          "optional": true,
           "requires": {
             "minimist": "0.0.8"
           }
@@ -2525,7 +2537,8 @@
         "number-is-nan": {
           "version": "1.0.1",
           "bundled": true,
-          "dev": true
+          "dev": true,
+          "optional": true
         },
         "object-assign": {
           "version": "4.1.1",
@@ -2537,6 +2550,7 @@
           "version": "1.4.0",
           "bundled": true,
           "dev": true,
+          "optional": true,
           "requires": {
             "wrappy": "1"
           }
@@ -2622,7 +2636,8 @@
         "safe-buffer": {
           "version": "5.1.2",
           "bundled": true,
-          "dev": true
+          "dev": true,
+          "optional": true
         },
         "safer-buffer": {
           "version": "2.1.2",
@@ -2658,6 +2673,7 @@
           "version": "1.0.2",
           "bundled": true,
           "dev": true,
+          "optional": true,
           "requires": {
             "code-point-at": "^1.0.0",
             "is-fullwidth-code-point": "^1.0.0",
@@ -2677,6 +2693,7 @@
           "version": "3.0.1",
           "bundled": true,
           "dev": true,
+          "optional": true,
           "requires": {
             "ansi-regex": "^2.0.0"
           }
@@ -2720,12 +2737,14 @@
         "wrappy": {
           "version": "1.0.2",
           "bundled": true,
-          "dev": true
+          "dev": true,
+          "optional": true
         },
         "yallist": {
           "version": "3.0.3",
           "bundled": true,
-          "dev": true
+          "dev": true,
+          "optional": true
         }
       }
     },

+ 0 - 0
relatorio.php


+ 5 - 4
relatorio_aluno_exercicio.php

@@ -29,7 +29,9 @@ $qualVersao = qualVersaoDoIVProg($arquivoLogsAluno);
   <link href="css/bootstrap.min.css" rel="stylesheet" />
     <link href="css/style.css" rel="stylesheet" />
   <style>
-    #line-heatmap-canvas { width:91%; height:100%; position:absolute;}
+    #line-heatmap-canvas { width:1500px; height:1500px; position:absolute;}
+    #line-heatmap-view { width:1500px; height:1500px; position:absolute;}
+    #line-heatmap-tooltip { position:absolute; left:0; top:0; background:rgba(0,0,0,.8); color:white; font-size:14px; padding:5px; line-height:18px; display:none; z-index:10}
   </style>
   <title>Test</title>
   <script src="dist/line_heatmap.js"></script>
@@ -94,7 +96,6 @@ $qualVersao = qualVersaoDoIVProg($arquivoLogsAluno);
             <label for="inputexercicio" class="col-sm-2 col-form-label">Exercício:</label>
             <div class="col-sm-10">
               <select class="form-control" id="inputexercicio" name="exercicio">
-                <option value="Todos">Todos</option>
                 <?php
                   for ($i = 0; $i < count($exercicios); $i++) {
                     echo "<option value='$exercicios[$i]'" . ($exercicios[$i] == $_GET['exercicio']?" selected":"") . ">" . str_replace('_', ' ', $exercicios[$i]) . "</option>";
@@ -139,10 +140,10 @@ $qualVersao = qualVersaoDoIVProg($arquivoLogsAluno);
 	  ?>
   
 	  <script>
-	    line_heatmap.Container.init('hea',"<?= $logsAlunoString ?>");
+	    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: 800px;'":"style='width: 800px; height: 600px;'") ?> >
+	  <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>
 
   <?php

+ 162 - 0
relatorio_exercicio.php

@@ -0,0 +1,162 @@
+<?php
+
+require 'functions.php';
+
+$cursos = listarCursos();
+$alunos = listarAlunos($_GET['curso']);
+$exercicios = listarExercicios($_GET['curso']);
+
+$curso_selecionado = $_GET['curso'];
+// $aluno_selecionado = $_GET['aluno'];
+$exercicio_selecionado = $_GET['exercicio'];
+
+?>
+
+<!DOCTYPE html>
+<html lang="en">
+<head>
+  <meta charset="UTF-8">
+  <title>ivprog_log_analysis</title>
+  <meta name="viewport" content="width=device-width, initial-scale=1.0">
+  <meta http-equiv="X-UA-Compatible" content="ie=edge">
+  <link rel="stylesheet" href="dist/style.css">
+  <link href="css/bootstrap.min.css" rel="stylesheet" />
+    <link href="css/style.css" rel="stylesheet" />
+  <style>
+    #line-heatmap-canvas { width:1200px; height:1200px; position:absolute;}
+    #line-heatmap-view { width:1200px; height:1200px; position:absolute;}
+    #line-heatmap-tooltip { position:absolute; left:0; top:0; background:rgba(0,0,0,.8); color:white; font-size:14px; padding:5px; line-height:18px; display:none; z-index:10}
+  </style>
+  <title>Test</title>
+  <script src="dist/line_heatmap.js"></script>
+  <style type="text/css">
+  </style>
+</head>
+<body>
+
+	<nav class="navbar navbar-expand-md navbar-dark fixed-top" style="background-color: #03396c;">
+      <b><a class="navbar-brand" href="./">ivprog_log_analysis - Ambiente de análise dos logs do iVProgH</a></b>
+      <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarsExampleDefault" aria-controls="navbarsExampleDefault" aria-expanded="false" aria-label="Toggle navigation">
+        <span class="navbar-toggler-icon"></span>
+      </button>
+      <div class="collapse navbar-collapse" id="navbarsExampleDefault">
+        <ul class="navbar-nav mr-auto">
+          <li class="nav-item active">
+            <a class="nav-link" href="./" title=""></a>
+          </li>
+          </ul>
+      </div>
+    </nav>
+
+    <main role="main">
+      <div class="jumbotron ivprogh-desc">
+        <div class="container">
+          <?= instrucoes() ?>
+        </div>
+      </div>
+
+
+      <div class="container ivprog-container" style="padding: 3em; margin-top: 3em;">
+        <form action="process.php" method="get" novalidate>
+
+          <div class="form-group row">
+            <label for="inputname" class="col-sm-2 col-form-label">Curso:</label>
+            <div class="col-sm-10">
+              <select class="form-control" id="inputname" name="curso">
+                <?php
+                  for ($i = 0; $i < count($cursos); $i++) {
+                    echo "<option" . ($cursos[$i] == $_GET['curso']?" selected":"") . ">" . $cursos[$i] . "</option>";
+                  }
+                ?>
+              </select>
+            </div>
+          </div>
+
+          <div class="form-group row">
+            <label for="inputaluno" class="col-sm-2 col-form-label">Aluno:</label>
+            <div class="col-sm-10">
+              <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>";
+                  }
+                ?>
+              </select>
+            </div>
+        </div>
+
+      <div class="form-group row">
+            <label for="inputexercicio" class="col-sm-2 col-form-label">Exercício:</label>
+            <div class="col-sm-10">
+              <select class="form-control" id="inputexercicio" name="exercicio">
+                <?php
+                  for ($i = 0; $i < count($exercicios); $i++) {
+                    echo "<option value='$exercicios[$i]'" . ($exercicios[$i] == $_GET['exercicio']?" selected":"") . ">" . str_replace('_', ' ', $exercicios[$i]) . "</option>";
+                  }
+                ?>
+              </select>
+            </div>
+        </div>
+
+      <div class="form-group row">
+          <div class="offset-sm-2 col-sm-10">
+            <button type="button" class="btn btn-secondary" onclick="window.history.back();">Voltar</button>
+            <button type="submit" class="btn btn-primary">Continuar</button>
+            <span class="reported" style="color: green; font-size: 120%;"></span>
+            <span class="error" style="color: red; font-size: 120%;"></span>
+          </div>
+        </div>
+
+        </form>
+      </div>
+
+      <div>
+        
+      </div>
+    </main>
+    <script src="./js/jquery.min.js"></script>
+    <script src="./js/bootstrap.bundle.min.js"></script>
+
+    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/octicons/3.5.0/octicons.min.css">
+
+
+  <div>
+    <div id="hea">
+    </div>
+ 
+
+	  <?php
+      $arquivoLogsAluno = null;
+      
+      $logsTodosAlunos = "";
+      for ($i=0; $i < count($alunos); ++$i) { 
+        $tempAluno = $alunos[$i];
+        $tempArquivoLogsAluno = pegarLogsDoAluno($curso_selecionado, $tempAluno, $exercicio_selecionado);
+        $logAluno = pegarLogsDoAlunoComoString($tempArquivoLogsAluno);
+        if(!empty($logAluno) && is_null($arquivoLogsAluno)) {
+          $arquivoLogsAluno = $tempArquivoLogsAluno;
+        }
+        $logsTodosAlunos .= $logAluno;
+      }
+      $qualVersao = qualVersaoDoIVProg($arquivoLogsAluno);
+
+      if (is_null($arquivoLogsAluno)) {
+        echo "<center><h4>N&atilde;o houve submiss&otilde;es para o exerc&iacute;cio selecionado!</h4></center>";
+      } else {
+	  ?>
+  
+	  <script>
+	    line_heatmap.Container.init('hea',"<?= $logsTodosAlunos ?>", 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>
+  <?php
+      }
+  ?>
+ </div>
+
+
+</body>
+</html>

+ 170 - 7
src/heatContainer.js

@@ -6,25 +6,39 @@ const template = `<div>
     <div id="line-heatmap-slider"></div>
   </div>
   <div id="line-heatmap-canvas">
+    <div id="line-heatmap-view"></div>
+    <div id="line-heatmap-tooltip"></div>
   </div>
 </div>
 `;
 
+const cursorDist = 10;
+
 const stateObject = {};
 
-function init (elementId, logString) {
+let x1, y1, x2, y2;
+let firstClick = true;
+let div = null;
+
+let posLeft;
+let posTop;
+let yBottom;
+let xBottom;
+
+function init (elementId, logString, useTooltip = false, config = {}) {
   const el = document.getElementById(elementId);
   el.innerHTML = template;
   const logData = logTransform(logString);
   // create container
-  const heatmap = new LineHeatmap('line-heatmap-canvas');
-  heatmap.create();
+  const heatmap = new LineHeatmap('line-heatmap-view');
+  heatmap.create(config);
   heatmap.setTrackData(logData);
 
   const html5Slider = document.getElementById('line-heatmap-slider');
   noUiSlider.create(html5Slider, {
       start: [1, logData.length],
       connect: true,
+      step: 1,
       margin: 1,
       range: {
           'min': 1,
@@ -37,12 +51,40 @@ function init (elementId, logString) {
   stateObject['data'] = logData;
   stateObject['slider'] = html5Slider;
 
+  if (useTooltip) {
+    registerClickEvent();
+    const canvasWrapper = document.getElementById('line-heatmap-canvas');
+    const tooltip = document.getElementById('line-heatmap-tooltip');
+    function updateTooltip (x, y, value) {
+      const transl = `translate(${x + cursorDist}px, ${y + cursorDist}px)`;
+      tooltip.style.webkitTransform = transl;
+      tooltip.innerHTML = `(${x},${y},${value})`;
+    };
+
+    canvasWrapper.onmousemove = function (ev) {
+      var x = ev.layerX;
+      var y = ev.layerY;
+      // getValueAt gives us the value for a point p(x/y)
+      var value = stateObject['heatmap'].instance.getValueAt({
+        x: x, 
+        y: y
+      });
+      tooltip.style.display = 'block';
+      updateTooltip(x, y, value);
+    };
+    // hide tooltip on mouseout
+    canvasWrapper.onmouseout = function() {
+      tooltip.style.display = 'none';
+    };
+    /* tooltip code end */
+  }
+
   html5Slider.noUiSlider.on('update', function (values, handle) {
     const logValues = this.get();
-    console.log(logValues);
     const newData = stateObject['data'].slice(+logValues[0]-1, +logValues[1] + 1);
-    console.log(newData);
     stateObject['heatmap'].setTrackData(newData);
+    if(div !== null)
+      updateDivText(div, posLeft, posTop, xBottom, yBottom);
   });
 }
 
@@ -58,6 +100,25 @@ function updateLogString (logString) {
   stateObject['heatmap'].setTrackData(logData); 
 }
 
+function countClicks (x1, y1, x2, y2) {
+  const instance = stateObject['heatmap'].instance;
+  const points = instance.getData().data;
+  let counter = 0;
+  for(let i = 0; i < points.length; ++i) {
+    const point = points[i];
+    if (point.x >= x1 && point.y >= y1) {
+      if (point.x <= x2 && point.y <= y2) {
+        counter += point.value;
+      }
+    }
+  }
+  return counter;
+}
+
+function totalClicks () {
+  return stateObject['data'].length;
+}
+
 function logTransform (logString) {
   const data = logString.split("\n")
   .filter(v => v.split(',').length > 3)
@@ -72,7 +133,109 @@ function logTransform (logString) {
   return data;
 }
 
+function registerClickEvent () {
+  const elemen = document.querySelector(".heatmap-canvas");
+  window.onclick = function (evt) {
+    if(evt.target !== elemen) {
+      return;
+    }
+    if (firstClick) {
+      if (evt.pageX || evt.pageY) {
+        x1 = evt.pageX;
+        y1 = evt.pageY;
+      } else {
+        x1 = evt.clientX + document.body.scrollLeft + elemen.scrollLeft;
+        y1 = evt.clientY + document.body.scrollTop + elemen.scrollTop;
+      }
+      x1 -= elemen.offsetLeft;
+      y1 -= elemen.offsetTop;
+      firstClick = false;
+    } else {
+      if (evt.pageX || evt.pageY) {
+        x2 = evt.pageX;
+        y2 = evt.pageY;
+      } else {
+        x2 = evt.clientX + document.body.scrollLeft + elemen.scrollLeft;
+        y2 = evt.clientY + document.body.scrollTop + elemen.scrollTop;
+      }
+      x2 -= elemen.offsetLeft;
+      y2 -= elemen.offsetTop;
+
+      firstClick = true;
+      if (div !== null) {
+        document.getElementById("line-heatmap-canvas").removeChild(div);
+        div = null;
+      }
+      div = document.createElement("div");
+      posLeft = Math.min(x1,x2);
+      posTop = Math.min(y1,y2) - 585;
+      yBottom = Math.max(y1,y2) - 585;
+      xBottom = Math.max(x1,x2);
+      const width = Math.abs(xBottom - posLeft);
+      const height = Math.abs(yBottom - posTop);
+      updateDivText(div, posLeft, posTop, xBottom, yBottom);
+      div.style.width = width + "px";
+      div.style.height = height + "px";
+      div.style.position = "absolute";
+      div.style.top = posTop + "px";
+      div.style.left = posLeft + "px";
+      div.style.border = "1px solid green";
+      document.getElementById("line-heatmap-canvas").append(div);
+      
+    }
+  }
+}
+
+function updateDivText (div, posLeft, posTop, xBottom, yBottom) {
+  const count = countClicks(posLeft, posTop, xBottom, yBottom);
+  const ratio = count/totalClicks();
+  div.innerHTML = `<span style="font-size:14px">Quantidade de clicks: ${count}</span>
+  <span style="font-size:14px">Proporção em relação ao total: ${ratio}</span>`;
+}
+
+
 export default {
   init,
-  updateLogString
-}
+  updateLogString,
+  countClicks,
+  totalClicks
+}
+
+/**
+ var x1, y1, x2, y2;
+var sequencia = 1;
+
+window.onclick = function(evt) {
+    var elemen = document.querySelector(".heatmap-canvas");
+    if (sequencia == 1) {
+     if (evt.pageX || evt.pageY) {
+        x1 = evt.pageX;
+        y1 = evt.pageY;
+     } else {
+        x1 = evt.clientX + document.body.scrollLeft + elemen.scrollLeft;
+        y1 = evt.clientY + document.body.scrollTop + elemen.scrollTop;
+       }
+     x1 -= elemen.offsetLeft;
+       y1 -= elemen.offsetTop;
+       sequencia ++;
+    } else {
+      if (evt.pageX || evt.pageY) {
+        x2 = evt.pageX;
+        y2 = evt.pageY;
+     } else {
+        x2 = evt.clientX + document.body.scrollLeft + elemen.scrollLeft;
+        y2 = evt.clientY + document.body.scrollTop + elemen.scrollTop;
+       }
+    x2 -= elemen.offsetLeft;
+       y2 -= elemen.offsetTop;
+       
+      var width = Math.abs(x2 - x1);
+      var height = Math.abs(y2 - y1);
+      sequencia = 1;
+
+
+        $('#line-heatmap-canvas').append($('<div style="position: absolute; border: 1px solid green; top: '+(y1 - 580)+'px; left: '+x1+'px; width: '+width+'px; height: '+height+'px; "></div>'));
+            
+    }
+}
+ */

+ 4 - 0
src/lineHeatmap.js

@@ -7,6 +7,10 @@ export default class LineHeatmap {
     this.heatmap = null;
   }
 
+  get instance () {
+    return this.heatmap;
+  }
+
   create (config = {}) {
     let myConfig = {
       container: document.getElementById(this.ID)

文件差異過大導致無法顯示
+ 0 - 1869
temp/1.4_Pratica_-_Idade-2019_01_21_10_32.ivph