|
|
@@ -3,7 +3,7 @@ const helpers = require('./helpers.js');
|
|
|
const nutsData = require('./nuts-data.js');
|
|
|
const cors = require('cors');
|
|
|
const R = require('r-script');
|
|
|
-var where = require("lodash.where");
|
|
|
+var where = require('lodash.where');
|
|
|
|
|
|
const app = express();
|
|
|
|
|
|
@@ -26,171 +26,171 @@ app.set('view engine', 'pug')
|
|
|
|
|
|
/* Dummy web service call without the method specified */
|
|
|
app.get('/', (req, res) => {
|
|
|
- res.send('Rural attractivness web service');
|
|
|
+ res.send('Rural attractivness web service');
|
|
|
});
|
|
|
|
|
|
/* Makes refresh of the data loaded to the server objects.
|
|
|
Must be called after the CSV data has changed */
|
|
|
app.get('/refresh', (req, res, next) => {
|
|
|
- nutsData.loadDatasets(_datasetsFilePath, function (ds) {
|
|
|
- //console.log('Datasets loaded succesfully');
|
|
|
- _datasets = ds;
|
|
|
- nutsData.loadRuralData(_dataFilePath, _datasets, function (rd) {
|
|
|
- //console.log('Rural data loaded succesfully');
|
|
|
- _ruralData = rd;
|
|
|
- res.send('Data refreshed');
|
|
|
- });
|
|
|
+ nutsData.loadDatasets(_datasetsFilePath, function (ds) {
|
|
|
+ //console.log('Datasets loaded succesfully');
|
|
|
+ _datasets = ds;
|
|
|
+ nutsData.loadRuralData(_dataFilePath, _datasets, function (rd) {
|
|
|
+ //console.log('Rural data loaded succesfully');
|
|
|
+ _ruralData = rd;
|
|
|
+ res.send('Data refreshed');
|
|
|
});
|
|
|
+ });
|
|
|
});
|
|
|
|
|
|
/* Returns JSON array with the list of all the datasets */
|
|
|
app.get('/datasets', (req, res, next) => {
|
|
|
- if (_datasets) {
|
|
|
- helpers.formatResponse(_datasets, req, res);
|
|
|
- }
|
|
|
- else {
|
|
|
- nutsData.loadDatasets(_datasetsFilePath, function (ds) {
|
|
|
- //console.log('Datasets loaded callback');
|
|
|
- _datasets = ds;
|
|
|
- helpers.formatResponse(_datasets, req, res);
|
|
|
- });
|
|
|
- }
|
|
|
+ if (_datasets) {
|
|
|
+ helpers.formatResponse(_datasets, req, res);
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ nutsData.loadDatasets(_datasetsFilePath, function (ds) {
|
|
|
+ //console.log('Datasets loaded callback');
|
|
|
+ _datasets = ds;
|
|
|
+ helpers.formatResponse(_datasets, req, res);
|
|
|
+ });
|
|
|
+ }
|
|
|
});
|
|
|
|
|
|
/* Returns attractivity data for the region with ID equal to the 'nuts' parameter */
|
|
|
app.get('/scores/:nuts', (req, res, next) => {
|
|
|
- if (_ruralData) {
|
|
|
+ if (_ruralData) {
|
|
|
+ returnRegionScores(req.params.nuts, req, res);
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ if (_datasets) { // datasets must be loaded prior to data loading
|
|
|
+ nutsData.loadRuralData(_dataFilePath, _datasets, function (rd) {
|
|
|
+ _ruralData = rd;
|
|
|
returnRegionScores(req.params.nuts, req, res);
|
|
|
+ });
|
|
|
}
|
|
|
else {
|
|
|
- if (_datasets) { // datasets must be loaded prior to data loading
|
|
|
- nutsData.loadRuralData(_dataFilePath, _datasets, function (rd) {
|
|
|
- _ruralData = rd;
|
|
|
- returnRegionScores(req.params.nuts, req, res);
|
|
|
- });
|
|
|
- }
|
|
|
- else {
|
|
|
- nutsData.loadDatasets(_datasetsFilePath, function (ds) {
|
|
|
- _datasets = ds;
|
|
|
-
|
|
|
- nutsData.loadRuralData(_dataFilePath, _datasets, function (rd) {
|
|
|
- _ruralData = rd;
|
|
|
- returnRegionScores(req.params.nuts, req, res);
|
|
|
- });
|
|
|
- });
|
|
|
- }
|
|
|
+ nutsData.loadDatasets(_datasetsFilePath, function (ds) {
|
|
|
+ _datasets = ds;
|
|
|
+
|
|
|
+ nutsData.loadRuralData(_dataFilePath, _datasets, function (rd) {
|
|
|
+ _ruralData = rd;
|
|
|
+ returnRegionScores(req.params.nuts, req, res);
|
|
|
+ });
|
|
|
+ });
|
|
|
}
|
|
|
+ }
|
|
|
});
|
|
|
|
|
|
/* Returns attractivity data for all the regions in source CSV data. */
|
|
|
app.get('/scores', (req, res, next) => {
|
|
|
- if (_ruralData)
|
|
|
+ if (_ruralData)
|
|
|
+ helpers.formatResponse(_ruralData, req, res);
|
|
|
+ else {
|
|
|
+ if (_datasets) { // datasets must be loaded prior to data loading
|
|
|
+ nutsData.loadRuralData(_dataFilePath, _datasets, function (rd) {
|
|
|
+ _ruralData = rd;
|
|
|
helpers.formatResponse(_ruralData, req, res);
|
|
|
+ });
|
|
|
+ }
|
|
|
else {
|
|
|
- if (_datasets) { // datasets must be loaded prior to data loading
|
|
|
- nutsData.loadRuralData(_dataFilePath, _datasets, function (rd) {
|
|
|
- _ruralData = rd;
|
|
|
- helpers.formatResponse(_ruralData, req, res);
|
|
|
- });
|
|
|
- }
|
|
|
- else {
|
|
|
- nutsData.loadDatasets(_datasetsFilePath, function (ds) {
|
|
|
- _datasets = ds;
|
|
|
-
|
|
|
- nutsData.loadRuralData(_dataFilePath, _datasets, function (rd) {
|
|
|
- _ruralData = rd;
|
|
|
- helpers.formatResponse(_ruralData, req, res);
|
|
|
- });
|
|
|
- });
|
|
|
- }
|
|
|
+ nutsData.loadDatasets(_datasetsFilePath, function (ds) {
|
|
|
+ _datasets = ds;
|
|
|
+
|
|
|
+ nutsData.loadRuralData(_dataFilePath, _datasets, function (rd) {
|
|
|
+ _ruralData = rd;
|
|
|
+ helpers.formatResponse(_ruralData, req, res);
|
|
|
+ });
|
|
|
+ });
|
|
|
}
|
|
|
+ }
|
|
|
});
|
|
|
|
|
|
/* Computes and returns attractivity data for all the NUTS regions based on the
|
|
|
incomming datasets and factor weights. */
|
|
|
app.post('/scores', (req, res, next) => {
|
|
|
- //console.log("query: " + JSON.stringify(req.body.factors, null, 4));
|
|
|
+ //console.log("query: " + JSON.stringify(req.body.factors, null, 4));
|
|
|
|
|
|
- if (_ruralData) {
|
|
|
+ if (_ruralData) {
|
|
|
+ returnAllScores(req, res);
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ if (_datasets) { // datasets must be loaded prior to data loading
|
|
|
+ nutsData.loadRuralData(_dataFilePath, _datasets, function (rd) {
|
|
|
+ _ruralData = rd;
|
|
|
returnAllScores(req, res);
|
|
|
+ });
|
|
|
}
|
|
|
else {
|
|
|
- if (_datasets) { // datasets must be loaded prior to data loading
|
|
|
- nutsData.loadRuralData(_dataFilePath, _datasets, function (rd) {
|
|
|
- _ruralData = rd;
|
|
|
- returnAllScores(req, res);
|
|
|
- });
|
|
|
- }
|
|
|
- else {
|
|
|
- nutsData.loadDatasets(_datasetsFilePath, function (ds) {
|
|
|
- _datasets = ds;
|
|
|
-
|
|
|
- nutsData.loadRuralData(_dataFilePath, _datasets, function (rd) {
|
|
|
- _ruralData = rd;
|
|
|
- returnAllScores(req, res);
|
|
|
- });
|
|
|
- });
|
|
|
- }
|
|
|
+ nutsData.loadDatasets(_datasetsFilePath, function (ds) {
|
|
|
+ _datasets = ds;
|
|
|
+
|
|
|
+ nutsData.loadRuralData(_dataFilePath, _datasets, function (rd) {
|
|
|
+ _ruralData = rd;
|
|
|
+ returnAllScores(req, res);
|
|
|
+ });
|
|
|
+ });
|
|
|
}
|
|
|
+ }
|
|
|
});
|
|
|
|
|
|
/*
|
|
|
Only testing purposes
|
|
|
*/
|
|
|
app.get('/runR', (req, res, next) => {
|
|
|
- //console.log(console);
|
|
|
- console.log('calling R...')
|
|
|
- console.log(req)
|
|
|
- R('./r/selected_data.r').call(
|
|
|
- function(err, data) {
|
|
|
- console.log('R done');
|
|
|
- if (err) {
|
|
|
- console.log(err.toString('utf8'));
|
|
|
- data = { result: err.toString('utf8') };
|
|
|
- }
|
|
|
- else {
|
|
|
- console.log(data);
|
|
|
- data = { result: 'R call succesful' };
|
|
|
- }
|
|
|
- helpers.formatResponse({ response: data }, req, res);
|
|
|
- }
|
|
|
- );
|
|
|
+ //console.log(console);
|
|
|
+ console.log('calling R...')
|
|
|
+ //console.log(req)
|
|
|
+ R('./r/selected_data.r').call(
|
|
|
+ function (err, data) {
|
|
|
+ console.log('R done');
|
|
|
+ if (err) {
|
|
|
+ console.log(err.toString('utf8'));
|
|
|
+ data = { result: err.toString('utf8') };
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ console.log(data);
|
|
|
+ data = { result: 'R call succesful' };
|
|
|
+ }
|
|
|
+ helpers.formatResponse({ response: data }, req, res);
|
|
|
+ }
|
|
|
+ );
|
|
|
});
|
|
|
|
|
|
/*
|
|
|
Just informative response. POST with JSON data is required.
|
|
|
*/
|
|
|
app.get('/clusters', (req, res, next) => {
|
|
|
- const data = { response: '/clusters method is only available under POST' }
|
|
|
- helpers.formatResponse(data, req, res);
|
|
|
+ const data = { response: '/clusters method is only available under POST' }
|
|
|
+ helpers.formatResponse(data, req, res);
|
|
|
});
|
|
|
|
|
|
/*
|
|
|
Modifies input CSV file, calls R script, loads the resulting CSV file and returns it
|
|
|
*/
|
|
|
app.post('/clusters', async (req, res, next) => {
|
|
|
- try {
|
|
|
- if (!_datasets) {
|
|
|
- //TODO: promisify all functions to avoid callback hell and make this work properly
|
|
|
- await nutsData.loadDatasets(_datasetsFilePath, function (ds) {
|
|
|
- //console.log('Datasets loaded succesfully');
|
|
|
- _datasets = ds;
|
|
|
- })
|
|
|
- }
|
|
|
- //console.log(req.body);
|
|
|
- const clusteringData = await nutsData.loadClusteringInput(
|
|
|
- _dataFilePath
|
|
|
- );
|
|
|
- await nutsData.modifyClusteringData({
|
|
|
- datasets: _datasets,
|
|
|
- data: clusteringData,
|
|
|
- params: req.body,
|
|
|
- outputFileName: _clusteringModifiedFilePath
|
|
|
- });
|
|
|
- handleRCall(req, res);
|
|
|
- } catch (error) { // Catch errors in async functions
|
|
|
- next(error.toString());
|
|
|
+ try {
|
|
|
+ if (!_datasets) {
|
|
|
+ //TODO: promisify all functions to avoid callback hell and make this work properly
|
|
|
+ await nutsData.loadDatasets(_datasetsFilePath, function (ds) {
|
|
|
+ //console.log('Datasets loaded succesfully');
|
|
|
+ _datasets = ds;
|
|
|
+ })
|
|
|
}
|
|
|
+ //console.log(req.body);
|
|
|
+ const clusteringData = await nutsData.loadClusteringInput(
|
|
|
+ _dataFilePath
|
|
|
+ );
|
|
|
+ await nutsData.modifyClusteringData({
|
|
|
+ datasets: _datasets,
|
|
|
+ data: clusteringData,
|
|
|
+ params: req.body,
|
|
|
+ outputFileName: _clusteringModifiedFilePath
|
|
|
+ });
|
|
|
+ handleRCall(req, res);
|
|
|
+ } catch (error) { // Catch errors in async functions
|
|
|
+ next(error.toString());
|
|
|
+ }
|
|
|
});
|
|
|
|
|
|
app.get('/georeport/:nuts', (req, res, next) => {
|
|
|
@@ -244,66 +244,67 @@ function renderPugReport(nuts, req, res) {
|
|
|
});
|
|
|
|
|
|
if (!found)
|
|
|
- res.render('err', { });
|
|
|
+ res.render('err', {});
|
|
|
}
|
|
|
|
|
|
function returnAllScores(req, res) {
|
|
|
- var resData = [];
|
|
|
- _ruralData.forEach(region => {
|
|
|
+ var resData = [];
|
|
|
+ _ruralData.forEach(region => {
|
|
|
//var region = _ruralData[0];
|
|
|
- var sumWeight = 0;
|
|
|
- var sumValue = 0;
|
|
|
- let regionIndexes = { code: region.nuts };
|
|
|
-
|
|
|
- req.body.factors.forEach(f => {
|
|
|
- let fi = nutsData.getFactorIndex(region, f);
|
|
|
- //console.log("f: " + JSON.stringify(f));
|
|
|
- //console.log("fi: " + JSON.stringify(fi));
|
|
|
-
|
|
|
- regionIndexes[f.factor] = fi.index;
|
|
|
- sumValue += fi.sumValue * f.weight;
|
|
|
- sumWeight += fi.sumWeight;
|
|
|
- });
|
|
|
-
|
|
|
- regionIndexes.aggregate = sumValue / sumWeight;
|
|
|
- resData.push(regionIndexes);
|
|
|
+ var sumWeight = 0;
|
|
|
+ var sumValue = 0;
|
|
|
+ let regionIndexes = { code: region.nuts };
|
|
|
+
|
|
|
+ req.body.factors.forEach(f => {
|
|
|
+ let fi = nutsData.getFactorIndex(region, f);
|
|
|
+ //console.log("f: " + JSON.stringify(f));
|
|
|
+ //console.log("fi: " + JSON.stringify(fi));
|
|
|
+
|
|
|
+ regionIndexes[f.factor] = fi.index;
|
|
|
+ sumValue += fi.sumValue * f.weight;
|
|
|
+ sumWeight += fi.sumWeight;
|
|
|
});
|
|
|
|
|
|
- helpers.formatResponse(resData, req, res);
|
|
|
+ regionIndexes.aggregate = sumValue / sumWeight;
|
|
|
+ resData.push(regionIndexes);
|
|
|
+ });
|
|
|
+
|
|
|
+ helpers.formatResponse(resData, req, res);
|
|
|
}
|
|
|
|
|
|
function returnRegionScores(nuts, req, res) {
|
|
|
- var found = false;
|
|
|
- res.header("Content-Type", 'application/json');
|
|
|
-
|
|
|
- _ruralData.forEach(region => {
|
|
|
- if (region.nuts == nuts) {
|
|
|
- helpers.formatResponse(region, req, res);
|
|
|
- found = true;
|
|
|
- }
|
|
|
- });
|
|
|
+ var found = false;
|
|
|
+ res.header("Content-Type", 'application/json');
|
|
|
|
|
|
- if (!found)
|
|
|
- // NUTS region not found
|
|
|
- res.status(404).send('NUTS region not found.');
|
|
|
+ _ruralData.forEach(region => {
|
|
|
+ if (region.nuts == nuts) {
|
|
|
+ helpers.formatResponse(region, req, res);
|
|
|
+ found = true;
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ if (!found)
|
|
|
+ // NUTS region not found
|
|
|
+ res.status(404).send('NUTS region not found.');
|
|
|
}
|
|
|
|
|
|
function handleRCall(req, res) {
|
|
|
- //console.log('calling R...')
|
|
|
- R('./r/selected_data.r').call(
|
|
|
- function(err, data) {
|
|
|
- //console.log('R done');
|
|
|
- if (err) {
|
|
|
- console.log(err.toString('utf8'));
|
|
|
- data = { result: err.toString('utf8') };
|
|
|
- }
|
|
|
- else {
|
|
|
- //console.log(data);
|
|
|
- nutsData.loadClusters(_clustersFilePath, function(clusterData) {
|
|
|
- data = clusterData;
|
|
|
- helpers.formatResponse({ response: data }, req, res);
|
|
|
- });
|
|
|
- }
|
|
|
- }
|
|
|
- );
|
|
|
+ console.log('calling R...')
|
|
|
+ R('./r/selected_data.r').call(
|
|
|
+ function (err, data) {
|
|
|
+ console.log('R done');
|
|
|
+ if (err) {
|
|
|
+ console.log(err.toString('utf8'));
|
|
|
+ data = { result: err.toString('utf8') };
|
|
|
+ res.status(204).send({ response: data });
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ //console.log(data);
|
|
|
+ nutsData.loadClusters(_clustersFilePath, function (clusterData) {
|
|
|
+ data = clusterData;
|
|
|
+ helpers.formatResponse({ response: data }, req, res);
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }
|
|
|
+ );
|
|
|
}
|