diff --git a/config.js.example b/config.js.example index ae636fc21b9f2dceb439e8afbb769e9a5e6fe02a..1846bae3e073ab0b34827a5bcc14a28e7e9aaff5 100644 --- a/config.js.example +++ b/config.js.example @@ -8,4 +8,8 @@ config.db_config = { port: 5432 }; +config.webservice_config = { + ip: "127.0.0.1" +} + config.agentVersion = 0.0; diff --git a/config_test.js.example b/config_test.js.example index bc4bb7e06e00bcb5df20e247a885a6e7daecad42..3a80276e7414581f10a2b34d52403530016b77d5 100644 --- a/config_test.js.example +++ b/config_test.js.example @@ -7,4 +7,9 @@ config.db_config = { host: 'localhost', port: 5432 }; + +config.webservice_config = { + ip: "127.0.0.1" +} + config.agentVersion = 0.0; diff --git a/config_test_error.js b/config_test_error.js index 5a00d0e29e9bd0abb4778a19e33dc6d6aa3642cb..7e9c26ef68f9762b47c9a77b652e9fecdb6b2ebd 100644 --- a/config_test_error.js +++ b/config_test_error.js @@ -8,5 +8,9 @@ config.db_config = { port: 5432 }; +config.webservice_config = { + ip: "127.0.0.1" +} + config.agentVersion = 0.0; diff --git a/database/create/schema/bd.sql b/database/create/schema/bd.sql index 4dcdcd151219a0a3200452310b04b852e7eb288b..f3cfd94af79fb59ecc390892c4a738b22c26dc6d 100755 --- a/database/create/schema/bd.sql +++ b/database/create/schema/bd.sql @@ -63,30 +63,34 @@ CREATE TABLE Course( ); CREATE TABLE MachineUse( - -- ~ Triagem DATE, - -- ~ Consulta DATE, - -- ~ Simulador DATE, - -- ~ Tratamento DATE, - -- ~ Tri_Cons int, -- DIAS - -- ~ Cons_Simulador int, -- DIAS - -- ~ Simulador_Trat int, -- DIAS - -- ~ CID VARCHAR(4), Pacient_id VARCHAR(254), Pacient_name VARCHAR(254), Energy VARCHAR(254), Use_date TIMESTAMP, Field_name VARCHAR(254), Machine_id VARCHAR(254), - Fk_Agent int + Fk_agent int ); CREATE TABLE Agent ( Id BIGSERIAL primary key, - Hospital VARCHAR(16), + Hospital_name VARCHAR(16), Geo_long FLOAT, Geo_lat FLOAT ); + +CREATE MATERIALIZED VIEW ResumeUsesMonth AS + SELECT date_trunc('month', use_date) AS date, count(*) as uses, fk_agent + FROM machineuse + GROUP BY date, fk_agent; + +CREATE MATERIALIZED VIEW ResumeUsesDay AS + SELECT date_trunc('day', use_date) AS date, count(*) as uses, fk_agent + FROM machineuse + GROUP BY date, fk_agent; + + ALTER TABLE session ADD CONSTRAINT fk_session_1 FOREIGN KEY(CourseSer) REFERENCES Course(CourseSer); ALTER TABLE SessionProcedurePart ADD CONSTRAINT fk_SessionProcedurePart_2 FOREIGN KEY(SessionProcedurePartSer) REFERENCES session(sessionSer); ALTER TABLE SessionProcedurePart ADD CONSTRAINT unique_SessionProcedurePart UNIQUE(SessionProcedurePartSer); diff --git a/src/db/query_builder.js b/src/db/query_builder.js index c99720267e7a9cbf9be75a285efaed04de347c5d..57a5697c11e2b6c7edc4922e5d989a21986f9817 100644 --- a/src/db/query_builder.js +++ b/src/db/query_builder.js @@ -16,7 +16,10 @@ module.exports = { }, select: function(table, conditions){ - var q = squel.select().from(table); - return q; + var q = squel.select().from(table); + for(c in conditions){ + q = q.where(c+" = "+"'"+conditions[c]+"'"); + } + return q; } }; diff --git a/src/middleware/db.js b/src/middleware/db.js index 308c4dbf13a0bdd722c7f41b95d8a6653762cd74..c506f7baf06a9f49e71dc35c97e99e695ac27e58 100644 --- a/src/middleware/db.js +++ b/src/middleware/db.js @@ -66,16 +66,16 @@ function namedPatch(client) { exports.pool = function (config) { return function (req, res, next) { + var pool = new pg.Pool(config); req.db = { connect: function (callback) { - pg.on('error', function(err) { - pg.end(); - throw(err); + pool.on('error', function(err) { + pool.end(); return; }); - pg.connect(config, function (err, client, done) { + pool.connect(function (err, client, done) { if (err) { - setTimeout(req.db.connect, 5000, callback); + callback(err, null, done); return; } @@ -83,7 +83,7 @@ exports.pool = function (config) { callback(null, new Connection(client), done); }); - pg.end(); + pool.end(); } }; diff --git a/src/middleware/populate.js b/src/middleware/populate.js index e8d7403f22924dc4f8dc86eec1b4fce09c8805b0..44f23f62e4e52400a5abca59b52fbbf0cbd856bf 100644 --- a/src/middleware/populate.js +++ b/src/middleware/populate.js @@ -8,9 +8,7 @@ var async = require('async'); var XLSX = require('xlsx'); -function namedPatch(client) { - - +function namedPatch(client) { var originalQuery = client.query; if (originalQuery.patched) return client; @@ -127,18 +125,17 @@ var sheet2arr = function(sheet){ }; function waterfall_queries(queries, config, cb_w){ + var pool = new pg.Pool(config); var temp_db = { connect: function (callback) { - pg.on('error', function(err) { + pool.on('error', function(err) { throw(err); cb_w(); - return; }); - pg.connect(config, function (err, client, done) { + pool.connect(function (err, client, done) { if (err) { setTimeout(temp_db.connect, 5000, callback); - cb_w(); - throw(err); + done(); return; } @@ -146,15 +143,13 @@ function waterfall_queries(queries, config, cb_w){ callback(null, new Connection(client), done); }); - pg.end(); + pool.end(); } }; temp_db.connect(function(err, conn, done) { if (err) { throw(err); - cb_w(); - return; } async.waterfall([ @@ -191,8 +186,9 @@ exports.populateAgent = function(file, config, callback = function(){}){ var queries = []; + //TODO: Create a config file that will be used to populate this table var q = qb.insert("agent",{ - Hospital: "Erasto Gaertner", + Hospital_name: "Erasto Gaertner", Geo_lat: -25.4696528, Geo_long: -49.261403 }); @@ -217,6 +213,20 @@ exports.populeMachineuse = function (file,config, callback = function(){}){ queries.push(q); } + var refresh_views_query = { + toParam: function refresh_views(){ + return { + values: [], + text: + "REFRESH materialized view ResumeUsesMonth;"+ + "REFRESH materialized view ResumeUsesDay;" + } + } + } + + queries.push(refresh_views_query); waterfall_queries(queries, config, callback); + + } diff --git a/src/routes/data.js b/src/routes/data.js index 0ced3c0e6710a3955e2cf82ecdb3bb4c1df12409..f4053339f693137d4cb873ccea54fcb121497d3c 100644 --- a/src/routes/data.js +++ b/src/routes/data.js @@ -27,22 +27,32 @@ module.exports = function(agentVersion) { return { listTable : function (req, res, table) { - req.db.connect(function(err, conn, done) { + if (err) { req.log.error(err); res.status(500).json({error: 'db_connection_failed'}); + done(); return; } + + var parameters = {}; + + switch(table){ + case 'ResumeUsesMonth': + case 'ResumeUsesDay': + if(req.query['hospital_id']) parameters["fk_agent"] = parseInt(req.query['hospital_id']); + break; + } - var q = qb.select(table,{}); + var q = qb.select(table,parameters); + conn.query(q.toParam().text,q.toParam().values, function(err,data,fields){ - if (err) throw err; - res.setHeader('Access-Control-Allow-Origin', 'file:///home/bhm15/c3sl/webservice/src/static/exemplo.html'); + if (err) req.log.error(err); res.header("Access-Control-Allow-Origin", "*"); res.header("Access-Control-Allow-Headers", "X-Requested-With"); - + done(); return res.status(200).json(data.rows); }); diff --git a/src/server.js b/src/server.js index 36648576e57fec4b52cbf103aab7acb386330757..c236018abcccaef6f2cdacc2a24db180a7f65eb7 100644 --- a/src/server.js +++ b/src/server.js @@ -27,7 +27,6 @@ /*jshint esversion: 6*/ var os = require('os'); -var ip = require("ip"); var fs = require('fs'); var cluster = require('cluster'); var bodyParser = require('body-parser'); @@ -176,16 +175,21 @@ app.get('/api/data/listAgents', function(req, res) { data.listTable(req,res,"agent"); }); -app.get('/api/data/listMachineUses', function(req, res) { - data.listTable(req,res,"machineuse"); +app.get('/api/data/ResumeUsesDay', function(req, res) { + data.listTable(req,res,"ResumeUsesDay"); }); +app.get('/api/data/ResumeUsesMonth', function(req, res) { + data.listTable(req,res,"ResumeUsesMonth"); +}); + + app.get('/pinsis.js', function(req, res) { - res.render(path.join(__dirname + '/static/pinsis.ejs'),{ip:ip.address()}); + res.render(path.join(__dirname + '/static/pinsis.ejs'),{ip:config.webservice_config.ip}); }); app.get('/exemplo.html', function(req, res) { - res.render(path.join(__dirname + '/static/exemplo.html'),{ip:ip.address()}); + res.render(path.join(__dirname + '/static/exemplo.html'),{ip:config.webservice_config.ip}); }); @@ -200,6 +204,8 @@ var exit = function exit() { // Fork process // if (cluster.isMaster) { + //Here is where should be populated the tables + // daemonize the process (useful for init.d scripts and similar) if (argv.daemon) { diff --git a/src/static/exemplo.html b/src/static/exemplo.html index 279e2969f6f0303adcb0d59a8b073ed77c262854..7c78735d1e32aeab82f419fabbd1a192e4442b2a 100644 --- a/src/static/exemplo.html +++ b/src/static/exemplo.html @@ -18,73 +18,57 @@ <script src="http://<%= ip %>:3000/pinsis.js"></script> <script src="https://cdn.plot.ly/plotly-latest.min.js"></script> - <script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore.js"></script> - <script src="https://momentjs.com/downloads/moment.js"></script> <script> + + function get_attribute_list(object_list, key){ + return object_list.map(function(x){return x[key];}); + } function plot_uses_by(uses,groupby, divname){ - var dates = uses.map(function(x){ - return x["use_date"]; - }); - - var occurrenceDay = function(occurrence){ - return moment(occurrence).startOf(groupby).format(); - }; - - var groupToDay = function(group, day){ - return { - day: day, - times: group - } - }; - - var result = _.chain(dates) - .groupBy(occurrenceDay) - .map(groupToDay) - .sortBy('day') - .value(); - + var plot1_data_x = get_attribute_list(uses,"date"); + var plot2_data_x = plot1_data_x; - var plot1_data_x = []; - var plot1_data_y = []; - var plot2_data_x = []; + var plot1_data_y = get_attribute_list(uses,"uses"); var plot2_data_y = []; - for(x in result){ - if(Math.round(Math.random()) == 1){ - plot1_data_x.push(result[x].day); - plot1_data_y.push(result[x].times.length); - } - else{ - plot2_data_x.push(result[x].day); - plot2_data_y.push(result[x].times.length); - } + for(i in plot1_data_x){ + plot2_data_y[i] = plot1_data_y[i] - parseInt(plot1_data_y[i]*Math.random()); + plot1_data_y[i] -= plot2_data_y[i]; } + + var susColor = 'green'; + var othersColor = 'blue'; + var plot_data = [ { x: plot1_data_x, y: plot1_data_y, - type: 'scatter', - name: 'Outros' + type: 'bar', + name: 'Outros', + marker: {color: othersColor}, }, { x: plot2_data_x, y: plot2_data_y, - type: 'scatter', - name: 'SUS' + type: 'bar', + name: 'SUS', + marker: {color: susColor}, } ]; - Plotly.newPlot(divname, plot_data); + Plotly.newPlot(divname, plot_data, {barmode: 'group'}); + var sum = function(x,y){return x+y;} + var data = [{ - values: [plot1_data_x.length,plot2_data_x.length], - labels: ['Outros', 'SUS'], - type: 'pie' + values: [plot2_data_y.reduce(sum),plot1_data_y.reduce(sum)], + labels: ['SUS', 'Outros'], + type: 'pie', + marker:{colors:[susColor, othersColor]}, }]; var layout = { @@ -96,43 +80,46 @@ } - function plot(groupby){ - Pinsis.lastUses(function(err, data){ - console.log(err); - //~ console.log(data); - plot_uses_by(data,groupby,"myDiv"); - - data_m = data.filter(function(x){ - return x["machine_id"].indexOf("CX") !== -1 - }); - - data_h = data.filter(function(x){ - return x["machine_id"].indexOf("CX") === -1 - }); - - - plot_uses_by(data_m, groupby,"myDiv2"); - plot_uses_by(data_h, groupby,"myDiv3"); - }); + var hospitals; + + function plot(groupby, hospital){ + switch(groupby){ + case "days": + Pinsis.lastUsesByDay(function(err, data){ + if(err) console.log(err); + plot_uses_by(data,groupby,"myDiv"); + }, hospital.id); + break; + case "months": + Pinsis.lastUsesByMonth(function(err, data){ + if(err) console.log(err); + plot_uses_by(data,groupby,"myDiv"); + },hospital.id); + break; + } + + document.getElementById("hospital_name").innerHTML = hospital.hospital_name; } - Pinsis.agents(function(err, data){ - console.log(err); + + Pinsis.hospitals(function(err, data){ + if(err) console.log(err); + hospitals = data; + console.log(data); + plot("days",hospitals[0]); }); - plot("day"); + </script> </header> <body> <center> - <button onClick="plot('years')" > ANOS </button> - <button onClick="plot('months')" > MESES </button> - <button onClick="plot('days')" > DIAS </button> - <button onClick="plot('hours')" > HORAS </button> - <button onClick="plot('minutes')" > MINUTOS </button> + <button onClick="plot('months', hospitals[0])" > MESES </button> + <button onClick="plot('days', hospitals[0])" > DIAS </button> </center> - <center><h1>Todas as máquinas</h1> + <center><h1>Monitoramento: <span id="hospital_name"></span></h1> + <div class="SEPARADOR"></div> <div id="myDiv"></div> <div id="myDiv_pizza"></div> <div class="SEPARADOR"></div> @@ -140,19 +127,6 @@ <br><br> - <center><h1>Máquinas do Ministério</h1> - <div id="myDiv2"></div> - <div id="myDiv2_pizza"></div> - <div class="SEPARADOR"></div> - </center> - - <br><br> - - <center><h1>Máquinas do Hospital</h1> - <div id="myDiv3"></div> - <div id="myDiv3_pizza"></div> - <div class="SEPARADOR"></div> - </center> </body> diff --git a/src/static/pinsis.ejs b/src/static/pinsis.ejs index 23974fb9969854a64102b5277870425b7d9b9fee..724d23f782cf27bdf5d13517c4808181b2310433 100644 --- a/src/static/pinsis.ejs +++ b/src/static/pinsis.ejs @@ -17,14 +17,26 @@ var Pinsis = { xmlhttp.send(); }, - lastUses: function(callback){ + lastUsesByDay: function(callback, hospital_id){ + var url = "http://<%= ip %>:3000/api/data/ResumeUsesDay"; + if(hospital_id) url+="?hospital_id="+hospital_id; this.getJson( callback, - "http://<%= ip %>:3000/api/data/listMachineUses" + url ); }, - agents: function(callback){ + lastUsesByMonth: function(callback, hospital_id){ + var url = "http://<%= ip %>:3000/api/data/ResumeUsesMonth"; + if(hospital_id) url+="?hospital_id="+hospital_id; + this.getJson( + callback, + url + ); + + }, + + hospitals: function(callback){ this.getJson( callback, "http://<%= ip %>:3000/api/data/listAgents"