From 042ac0f9d30f998a84de98d305450f6f5aa5df6f Mon Sep 17 00:00:00 2001 From: Thomas Forgione Date: Sat, 23 Sep 2017 22:38:12 +0000 Subject: [PATCH] Nice formatting --- controllers/total/calendar.js | 240 +++++++++++++++++++++++++ controllers/total/templates/total.html | 23 +++ controllers/total/templates/total.pug | 26 +++ controllers/total/urls.js | 5 + controllers/total/views.js | 31 ++++ index.js | 2 + package.json | 2 + templates/base.pug | 2 +- 8 files changed, 330 insertions(+), 1 deletion(-) create mode 100644 controllers/total/calendar.js create mode 100644 controllers/total/templates/total.html create mode 100644 controllers/total/templates/total.pug create mode 100644 controllers/total/urls.js create mode 100644 controllers/total/views.js diff --git a/controllers/total/calendar.js b/controllers/total/calendar.js new file mode 100644 index 0000000..8112aea --- /dev/null +++ b/controllers/total/calendar.js @@ -0,0 +1,240 @@ +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 = { + TP: 1, + CTD: 2, + CM: 3, + Other: 4, +} + +cal.getTypeName = function(type) { + switch (type) { + case cal.Type.TP: return "TP"; + case cal.Type.CTD: return "CTD"; + case cal.Type.CM: return "CM"; + default: return "Other"; + } +} + +cal.getFactor = function(type) { + switch (type) { + case cal.Type.TP: return 1; + case cal.Type.CTD: return 1.25; + case cal.Type.CM: return 1.5; + default: return 0; + } +} + +cal.Event = class { + + constructor(content, firstLineIndex = 0) { + this.startTime = undefined; + this.finishTime = undefined; + this.name = undefined; + this.location = undefined; + this.type = cal.Type.Other; + + if (content !== undefined) + this.setFromContent(content, firstLineIndex); + } + + guessTypeFromName() { + if (this.name.indexOf("CTD") !== -1) { + this.type = cal.Type.CTD; + } else if (this.name.indexOf("TP") !== -1) { + this.type = cal.Type.TP; + } else if (this.name.indexOf("CM") !== -1) { + this.type = cal.Type.CM; + } + } + + getDurationInHours() { + return (this.finishTime - this.startTime) / (1000 * 60 * 60); + } + + getTdEquivalent() { + console.log(this.type); + 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('') === -1) { + this.setFromContent(xhr.responseText); + callback(this); + } + } + }; + xhr.send(); + + if (xhr.responseText.indexOf('') === -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(2017, 8, 1); + let lastDate = new Date(2018, 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); + }); + +} + +module.exports = cal; diff --git a/controllers/total/templates/total.html b/controllers/total/templates/total.html new file mode 100644 index 0000000..6611685 --- /dev/null +++ b/controllers/total/templates/total.html @@ -0,0 +1,23 @@ +{% extends "pyade/base.html" %} +{% block content %} + + + + + + + + + {% for key, value in total_by_course.items %} + + + + + {% endfor %} + + + + + +
Course nameCount in hours
{{ key }}{{ value }}
Total{{ total }}
+{% endblock %} diff --git a/controllers/total/templates/total.pug b/controllers/total/templates/total.pug new file mode 100644 index 0000000..7e5d7a9 --- /dev/null +++ b/controllers/total/templates/total.pug @@ -0,0 +1,26 @@ +extends ../../../templates/base.pug + +block content + table.table.table-bordered.table-striped.table-hover + thead + tr + th Course name + th Detected type + th Count in hours + th Count in TD equivalent + tbody + each course in courses + tr + td #{course.name} + td #{course.type} + td #{course.time} + td #{course.tdEquivalent} + tr + td + strong #{total.name} + td + strong #{total.type} + td + strong #{total.time} + td + strong #{total.tdEquivalent} diff --git a/controllers/total/urls.js b/controllers/total/urls.js new file mode 100644 index 0000000..d28f97f --- /dev/null +++ b/controllers/total/urls.js @@ -0,0 +1,5 @@ +const url = require('create-url').url; + +module.exports = [ + url('/total', 'total', 'total'), +] diff --git a/controllers/total/views.js b/controllers/total/views.js new file mode 100644 index 0000000..0a6841a --- /dev/null +++ b/controllers/total/views.js @@ -0,0 +1,31 @@ +const cal = require('./calendar'); + +module.exports.total = function(req, res, render) { + cal.getTotal(req.session.user, (table) => { + let courses = []; + let total = { + name: "Total", + type: "Total", + time: 0, + tdEquivalent: 0, + } + + for (let key in table) { + courses.push({ + name: key, + type: table[key].type, + time: table[key].time, + tdEquivalent: table[key].tdEquivalent, + }); + + total.time += table[key].time; + total.tdEquivalent += table[key].tdEquivalent; + } + + res.locals.courses = courses; + res.locals.total = total; + + + render('total.pug'); + }); +} diff --git a/index.js b/index.js index efcc46f..1935e4f 100644 --- a/index.js +++ b/index.js @@ -9,6 +9,7 @@ const http = require('http'); const path = require('path'); const log = require('log'); const model = require('model'); +const repl = require('repl'); // Load models model.load(config.CONTROLLERS_DIR); @@ -79,6 +80,7 @@ function startServer() { const commands = { runserver: startServer, reinitdb: model.reinitialize, + shell: repl.start, } function showHelp() { diff --git a/package.json b/package.json index acdd8ce..800e836 100644 --- a/package.json +++ b/package.json @@ -21,6 +21,8 @@ "cookie-session": "^1.3.1", "emailjs": "^1.0.12", "express": "^4.15.4", + "moment": "^2.18.1", + "os-locale": "^2.1.0", "pg": "^7.3.0", "pug": "^2.0.0-rc.4", "xmlhttprequest": "^1.8.0" diff --git a/templates/base.pug b/templates/base.pug index 0e4650e..1b5d664 100644 --- a/templates/base.pug +++ b/templates/base.pug @@ -23,7 +23,7 @@ html ul.navbar-nav if session.user !== undefined li.nav-item - a.nav-link(href='#') Total + a.nav-link(href=getUrl("total")) Total ul.navbar-nav.ml-auto if session.user === undefined li.nav-item