123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185 |
- export function processData () {
- const folderInput = document.querySelector("#folder");
- const header = [
- "submissionid",
- "file",
- "filesize",
- "timestamp",
- "humandate",
- "grade",
- "userid",
- "exerciseid",
- ];
- function generateSubCode (algorithmInIlm) {
- window.program_obj.functions = JSON.parse(algorithmInIlm).functions;
- window.program_obj.globals = JSON.parse(algorithmInIlm).globals;
- return window.ivprogCore.generateCode();
- }
- function prepareData (map, submission) {
- if (!submission) {
- return map;
- }
- const exercID = submission["exerciseid"];
- const studentID = submission["userid"];
- let exercMap = null;
- if (map.has(exercID)) {
- exercMap = map.get(exercID);
- } else {
- exercMap = new Map();
- map.set(exercID, exercMap);
- }
- if (exercMap.has(studentID)) {
- exercMap.get(studentID).push(submission);
- } else {
- exercMap.set(studentID, [submission]);
- }
- return map;
- }
- folderInput.addEventListener("change", async () => {
- const files = Array.from(folderInput.files);
- const idx = files.find((f) => f.name == "index.csv");
- const folderName = idx.webkitRelativePath.replace(idx.name, "");
- //console.debug(idx);
- //console.debug(folderName);
- const data = await idx.text();
- //console.debug(data);
- const csvEntries = data
- .split("\n")
- .slice(1)
- .filter((line) => line.length > 0)
- .map((line) => line.split(","))
- .map((vec) => {
- const obj = {};
- vec.forEach((val, i) => (obj[header[i]] = val));
- return obj;
- });
- //console.debug(csvEntries);
- const blockExercMap = csvEntries.reduce(prepareData, new Map());
- //console.log(Array.from(blockExercMatrix.entries()));
- const getFilePath = async function (submission) {
- const path = `${folderName}${submission["file"]}`;
- const file = files.find((f) => f.webkitRelativePath == path);
- const text = await file.text();
- return text;
- };
- const matrix = {};
- let counter = 0;
- blockExercMap.forEach((studentsMap, exercID) => {
- const column = [];
- studentsMap.forEach(async (submissions, studentID) => {
- submissions = submissions.sort((a, b) => {
- return parseInt(a["timestamp"]) - parseInt(b["timestamp"]);
- });
- counter++;
- submissions.forEach(async (submission, index, array) => {
- counter++;
- const student = {};
- student["grade"] = Math.max(0, parseFloat(submission["grade"]));
- student["timestamp"] = parseInt(submission["timestamp"]);
- student["student_id"] = studentID;
- student["TES"] = 0;
- student["DES"] = 0;
- student["D/T"] = 0;
- let previousCode = "";
- if (index > 0) {
- student["TES"] =
- parseInt(submission["timestamp"]) -
- parseInt(array[index - 1]["timestamp"]);
- const previousFile = await getFilePath(array[index - 1]);
- const previous = window.ivprogCore
- .prepareActivityToStudentHelper(previousFile)
- .getOrElse(1);
- if (previous == 1) {
- console.error(
- `A submission from ${studentID} to ${exercID} is invalid`
- );
- return;
- }
- previousCode = generateSubCode(previous.algorithmInIlm);
- }
- const currentFile = await getFilePath(submission);
- const current = window.ivprogCore
- .prepareActivityToStudentHelper(currentFile)
- .getOrElse(2);
- if (current == 2) {
- console.error(
- `A submission from ${studentID} to ${exercID} is invalid`
- );
- return;
- }
- const currentCode = generateSubCode(current.algorithmInIlm);
- if (previousCode === "") {
- const logs = JSON.parse(currentFile.split("::logs::")[1]);
- const event = logs[0];
- if (event == null) {
- // empty submission
- student["TES"] = 0;
- } else if (event.length === 4) {
- student["TES"] =
- parseInt(submission["timestamp"]) -
- Math.floor(parseInt(event[2]) / 1000);
- } else {
- student["TES"] =
- parseInt(submission["timestamp"]) -
- Math.floor(parseInt(event[1]) / 1000);
- }
- }
- student["DES"] = window.ivprogCore.levenshteinDistance(
- previousCode,
- currentCode
- );
- const ratio =
- student["TES"] === 0 ? 0 : student["DES"] / student["TES"];
- student["D/T"] = isNaN(ratio) ? 0 : ratio;
- column.push(student);
- counter--;
- });
- counter--;
- });
- matrix[exercID] = column;
- });
- function download (file, text) {
- //creating an invisible element
- const element = document.createElement("a");
- element.setAttribute(
- "href",
- "data:text/plain," + encodeURIComponent(text)
- );
- element.setAttribute("download", file);
- element.innerHTML = file;
- element.classList.add("ui", "primary", "button");
- // Above code is equivalent to
- // <a href="path of file" download="file name">
- document.querySelector("#downloads").appendChild(element);
- }
- function getExercHeader (id) {
- const props = ["TES", "DES", "grade", "D/T", "timestamp"];
- return props.reduce((acc, prop) => acc + `${id}_${prop},`, "");
- }
- const id = setInterval(() => {
- if (counter == 0) {
- clearInterval(id);
- for (const exercID in matrix) {
- let csv = "";
- let firstLine = "student_id,";
- firstLine += getExercHeader(exercID);
- for (const submission of matrix[exercID]) {
- csv += `${submission["student_id"]},`;
- csv += `${submission["TES"]},`;
- csv += `${submission["DES"]},`;
- csv += `${submission["grade"]},`;
- csv += `${submission["D/T"]},`;
- csv += `${submission["timestamp"]}`;
- csv += "\n";
- }
- download(`${exercID}.csv`, `${firstLine}\n${csv}`);
- }
- }
- }, 1000);
- });
- }
|