310 lines
8.2 KiB
JavaScript
310 lines
8.2 KiB
JavaScript
var crypto = require('crypto');
|
|
var fs = require('fs');
|
|
var XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest;
|
|
var moment = require('moment');
|
|
var locale = require('os-locale').sync();
|
|
|
|
var cal = {};
|
|
|
|
function fromIcal(string) {
|
|
return new Date(
|
|
parseInt(string.substr(0 , 4), 10),
|
|
parseInt(string.substr(4 , 2), 10) - 1,
|
|
parseInt(string.substr(6 , 2), 10),
|
|
parseInt(string.substr(9, 2), 10),
|
|
parseInt(string.substr(11, 2), 10),
|
|
parseInt(string.substr(13, 2), 10)
|
|
);
|
|
}
|
|
|
|
cal.Type = {
|
|
CM: 1,
|
|
CTD: 2,
|
|
TD: 3,
|
|
TP: 4,
|
|
Other: {
|
|
BE: 5,
|
|
Examen: 6,
|
|
Projet: 7,
|
|
APP: 8,
|
|
},
|
|
Unknown: 9,
|
|
}
|
|
|
|
cal.getTypeName = function(type) {
|
|
switch (type) {
|
|
case cal.Type.TD: return "TD";
|
|
case cal.Type.TP: return "TP";
|
|
case cal.Type.CTD: return "CTD";
|
|
case cal.Type.CM: return "CM";
|
|
case cal.Type.Other.BE:
|
|
case cal.Type.Other.Projet:
|
|
case cal.Type.Other.Examen:
|
|
case cal.Type.Other.APP:
|
|
return "Other";
|
|
default: return "Unknown";
|
|
}
|
|
}
|
|
|
|
cal.getFactor = function(type) {
|
|
switch (type) {
|
|
case cal.Type.TD:
|
|
case cal.Type.TP:
|
|
case cal.Type.Other.BE: return 1;
|
|
case cal.Type.Other.Projet: return 1;
|
|
case cal.Type.Other.Examen: return 0;
|
|
case cal.Type.Other.APP: return 1.5;
|
|
case cal.Type.CTD: return 1.25;
|
|
case cal.Type.CM: return 1.5;
|
|
default: return 0;
|
|
}
|
|
}
|
|
|
|
cal.getTypeFromName = function(name) {
|
|
|
|
if (name.indexOf("CTD") !== -1) {
|
|
return cal.Type.CTD;
|
|
} else if (name.indexOf("TP") !== -1) {
|
|
return cal.Type.TP;
|
|
} else if (name.indexOf("TD") !== -1) {
|
|
return cal.Type.TD;
|
|
} else if (name.indexOf("CM") !== -1) {
|
|
return cal.Type.CM;
|
|
} else if (name.indexOf("BE") !== -1) {
|
|
return cal.Type.Other.BE;
|
|
} else if (name.toLowerCase().indexOf("exam") !== -1) {
|
|
return cal.Type.Other.Examen;
|
|
} else if (name.toLowerCase().indexOf("projet") !== -1) {
|
|
return cal.Type.Other.Projet;
|
|
} else if (name.indexOf("APP ") !== -1) {
|
|
return cal.Type.Other.APP;
|
|
} else {
|
|
return cal.Type.Unkown;
|
|
}
|
|
|
|
}
|
|
|
|
cal.Event = class {
|
|
|
|
constructor(content, firstLineIndex = 0) {
|
|
this.startTime = undefined;
|
|
this.finishTime = undefined;
|
|
this.name = undefined;
|
|
this.location = undefined;
|
|
this.type = cal.Type.Unkown;
|
|
|
|
if (content !== undefined)
|
|
this.setFromContent(content, firstLineIndex);
|
|
}
|
|
|
|
guessTypeFromName() {
|
|
this.type = cal.getTypeFromName(this.name);
|
|
}
|
|
|
|
getDurationInHours() {
|
|
return (this.finishTime - this.startTime) / (1000 * 60 * 60);
|
|
}
|
|
|
|
getTdEquivalent() {
|
|
return this.getDurationInHours() * cal.getFactor(this.type);
|
|
}
|
|
|
|
setFromContent(content, firstLineIndex = 0) {
|
|
let index = firstLineIndex;
|
|
let lines = content.split('\n').map((a) => a.trim());
|
|
|
|
for (let line of lines.slice(firstLineIndex)) {
|
|
let split = line.split(':');
|
|
|
|
switch (split[0]) {
|
|
|
|
case 'END' : if (split[1] === 'VEVENT') return index;
|
|
case 'DTSTART' : this.startTime = fromIcal(split[1]); break;
|
|
case 'DTEND' : this.finishTime = fromIcal(split[1]); break;
|
|
case 'LOCATION':
|
|
this.location = split[1].replace('\\','');
|
|
break;
|
|
case 'SUMMARY' :
|
|
this.name = split[1];
|
|
this.guessTypeFromName();
|
|
break;
|
|
|
|
}
|
|
|
|
index++
|
|
}
|
|
|
|
return index;
|
|
}
|
|
|
|
};
|
|
|
|
cal.Calendar = class {
|
|
|
|
constructor(content) {
|
|
this.events = [];
|
|
|
|
if (content !== undefined)
|
|
this.setFromContent(content);
|
|
}
|
|
|
|
setFromContent(content) {
|
|
let index = 0;
|
|
let lines = content.split('\n').map((a) => a.trim());
|
|
|
|
while (index < lines.length) {
|
|
|
|
let split = lines[index].split(':');
|
|
|
|
if (split[0] === 'BEGIN' && split[1] === 'VEVENT') {
|
|
let event = new cal.Event();
|
|
index = event.setFromContent(content, index);
|
|
this.events.push(event);
|
|
} else {
|
|
index++;
|
|
}
|
|
|
|
}
|
|
|
|
this.events.sort((a,b) => {
|
|
if (a.startTime < b.startTime)
|
|
return -1
|
|
else if (a.startTime > b.startTime)
|
|
return 1
|
|
else
|
|
return 0;
|
|
});
|
|
}
|
|
|
|
setFromUrl(url, callback) {
|
|
|
|
let xhr = new XMLHttpRequest();
|
|
xhr.open("get", url, true);
|
|
xhr.onreadystatechange = (e) => {
|
|
if (xhr.readyState === 4) {
|
|
if (xhr.responseText.indexOf('<html>') === -1) {
|
|
this.setFromContent(xhr.responseText);
|
|
callback(this);
|
|
}
|
|
}
|
|
};
|
|
xhr.send();
|
|
|
|
if (xhr.responseText.indexOf('<html>') === -1) {
|
|
this.setFromContent(xhr.responseText);
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
function dateToString(dt) {
|
|
return dt.getFullYear() + "-" + (dt.getMonth() + 1) + "-" + dt.getDate();
|
|
}
|
|
|
|
cal.getUrlFromUser = function(user, firstDate = new Date(), lastDate = new Date(), calType = "ical") {
|
|
|
|
if (firstDate instanceof Date) {
|
|
firstDate = dateToString(firstDate);
|
|
}
|
|
|
|
if (lastDate instanceof Date) {
|
|
lastDate = dateToString(lastDate);
|
|
}
|
|
|
|
let baseUrl = "https://edt.inp-toulouse.fr/jsp/custom/modules/plannings/anonymous_cal.jsp?";
|
|
let resourcesParam = `resources=${user._resources.value}`;
|
|
let projectIdParam = `projectId=${user._projectId.value}`;
|
|
let firstDateParam = `firstDate=${firstDate}`;
|
|
let lastDateParam = `lastDate=${lastDate}`;
|
|
let calTypeParam = `calType=${calType}`;
|
|
let parameters = [resourcesParam, projectIdParam, firstDateParam, lastDateParam, calTypeParam].join("&");
|
|
|
|
return baseUrl + parameters;
|
|
|
|
};
|
|
|
|
cal.getCalendar = function(user, firstDate = new Date(), lastDate = new Date(), calType, callback) {
|
|
|
|
if (typeof calType === 'function') {
|
|
callback = calType;
|
|
calType = "iCal";
|
|
}
|
|
|
|
let calendar = new cal.Calendar();
|
|
let url = cal.getUrlFromUser(user, firstDate, lastDate, calType);
|
|
calendar.setFromUrl(url, cal => {
|
|
callback(cal);
|
|
});
|
|
|
|
};
|
|
|
|
cal.getTotal = function(user, callback) {
|
|
let firstDate = new Date(2000, 8, 1);
|
|
let lastDate = new Date(3000, 8, 1);
|
|
|
|
cal.getCalendar(user, firstDate, lastDate, (calendar) => {
|
|
let res = {};
|
|
|
|
for (let event of calendar.events) {
|
|
|
|
let hours = event.getDurationInHours();
|
|
let td = event.getTdEquivalent();
|
|
|
|
if (res[event.name] === undefined) {
|
|
res[event.name] = {
|
|
time: 0,
|
|
tdEquivalent: 0,
|
|
type: cal.getTypeName(event.type) +
|
|
' (x' + cal.getFactor(event.type) + ')',
|
|
};
|
|
}
|
|
|
|
res[event.name].time += hours;
|
|
res[event.name].tdEquivalent += td;
|
|
|
|
}
|
|
|
|
callback(res);
|
|
});
|
|
|
|
}
|
|
|
|
cal.getTotalByCourse = function(user, callback) {
|
|
|
|
let firstDate = new Date(2000, 8, 1);
|
|
let lastDate = new Date(3000, 8, 1);
|
|
|
|
cal.getCalendar(user, firstDate, lastDate, (calendar) => {
|
|
let res = {};
|
|
|
|
for (let event of calendar.events) {
|
|
// Guess name of event, last element of split('-');
|
|
let split = event.name.split(' -').map(x => x.trim());
|
|
let name = split[split.length - 1];
|
|
|
|
if (res[name] === undefined) {
|
|
res[name] = {}
|
|
for (let type in cal.Type) {
|
|
res[name][type] = 0;
|
|
}
|
|
res[name].totalTdEquivalent = 0;
|
|
}
|
|
|
|
let type = event.type;
|
|
let typeName;
|
|
if (type in cal.Type.Other) {
|
|
typeName = "Other";
|
|
} else {
|
|
typeName = cal.getTypeName(type);
|
|
}
|
|
res[name][typeName]++;
|
|
res[name].totalTdEquivalent += event.getTdEquivalent();
|
|
}
|
|
|
|
callback(res);
|
|
});
|
|
}
|
|
|
|
module.exports = cal;
|