312 lines
		
	
	
		
			8.2 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			312 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),
 | |
|         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;
 |