index.js 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. const express = require('express');
  2. const helpers = require('./helpers.js');
  3. const nutsData = require('./nuts-data.js');
  4. const cors = require('cors');
  5. const R = require('r-script');
  6. const app = express();
  7. const _datasetsFilePath = 'data/datasets.csv';
  8. const _dataFilePath = 'data/data.csv';
  9. var _datasets = undefined;
  10. var _ruralData = undefined;
  11. // parse incoming POST requests body to JSON
  12. app.use(express.json());
  13. // handle CORS
  14. app.use(cors())
  15. /* Dummy web service call without the method specified */
  16. app.get('/', (req, res) => {
  17. res.send('Rural attractivness web service');
  18. });
  19. /* Makes refresh of the data loaded to the server objects.
  20. Must be called after the CSV data has changed */
  21. app.get('/refresh', (req, res, next) => {
  22. nutsData.loadDatasets(_datasetsFilePath, function (ds) {
  23. //console.log('Datasets loaded succesfully');
  24. _datasets = ds;
  25. nutsData.loadRuralData(_dataFilePath, _datasets, function (rd) {
  26. //console.log('Rural data loaded succesfully');
  27. _ruralData = rd;
  28. });
  29. });
  30. });
  31. /* Returns JSON array with the list of all the datasets */
  32. app.get('/datasets', (req, res, next) => {
  33. if (_datasets) {
  34. helpers.formatResponse(_datasets, req, res);
  35. }
  36. else {
  37. nutsData.loadDatasets(_datasetsFilePath, function (ds) {
  38. //console.log('Datasets loaded callback');
  39. _datasets = ds;
  40. helpers.formatResponse(_datasets, req, res);
  41. });
  42. }
  43. });
  44. /* Returns attractivity data for the region with ID equal to the 'nuts' parameter */
  45. app.get('/scores/:nuts', (req, res, next) => {
  46. if (_ruralData) {
  47. returnRegionScores(req.params.nuts, req, res);
  48. }
  49. else {
  50. if (_datasets) { // datasets must be loaded prior to data loading
  51. nutsData.loadRuralData(_dataFilePath, _datasets, function (rd) {
  52. _ruralData = rd;
  53. returnRegionScores(req.params.nuts, req, res);
  54. });
  55. }
  56. else {
  57. nutsData.loadDatasets(_datasetsFilePath, function (ds) {
  58. _datasets = ds;
  59. nutsData.loadRuralData(_dataFilePath, _datasets, function (rd) {
  60. _ruralData = rd;
  61. returnRegionScores(req.params.nuts, req, res);
  62. });
  63. });
  64. }
  65. }
  66. });
  67. /* Returns attractivity data for all the regions in source CSV data. */
  68. app.get('/scores', (req, res, next) => {
  69. if (_ruralData)
  70. helpers.formatResponse(_ruralData, req, res);
  71. else {
  72. if (_datasets) { // datasets must be loaded prior to data loading
  73. nutsData.loadRuralData(_dataFilePath, _datasets, function (rd) {
  74. _ruralData = rd;
  75. helpers.formatResponse(_ruralData, req, res);
  76. });
  77. }
  78. else {
  79. nutsData.loadDatasets(_datasetsFilePath, function (ds) {
  80. _datasets = ds;
  81. nutsData.loadRuralData(_dataFilePath, _datasets, function (rd) {
  82. _ruralData = rd;
  83. helpers.formatResponse(_ruralData, req, res);
  84. });
  85. });
  86. }
  87. }
  88. });
  89. /* Computes and returns attractivity data for all the NUTS regions based on the
  90. incomming datasets and factor weights. */
  91. app.post('/scores', (req, res, next) => {
  92. //console.log("query: " + JSON.stringify(req.body.factors, null, 4));
  93. if (_ruralData) {
  94. returnAllScores(req, res);
  95. }
  96. else {
  97. if (_datasets) { // datasets must be loaded prior to data loading
  98. nutsData.loadRuralData(_dataFilePath, _datasets, function (rd) {
  99. _ruralData = rd;
  100. returnAllScores(req, res);
  101. });
  102. }
  103. else {
  104. nutsData.loadDatasets(_datasetsFilePath, function (ds) {
  105. _datasets = ds;
  106. nutsData.loadRuralData(_dataFilePath, _datasets, function (rd) {
  107. _ruralData = rd;
  108. returnAllScores(req, res);
  109. });
  110. });
  111. }
  112. }
  113. });
  114. app.get('/runR', (req, res, next) => {
  115. //console.log(console);
  116. console.log('calling R...')
  117. R('./r/selected_data.r').call(
  118. function(err, data) {
  119. console.log('R done');
  120. if (err) console.log(err.toString('utf8'))
  121. else {
  122. console.log(data);
  123. data = {result: 'R call succesful'};
  124. }
  125. helpers.formatResponse({ response: data }, req, res);
  126. }
  127. );
  128. });
  129. // start the service on the port xxxx
  130. app.listen(3000, () => console.log('Rural attractivity WS listening on port 3000...'));
  131. function returnAllScores(req, res) {
  132. var resData = [];
  133. _ruralData.forEach(region => {
  134. //var region = _ruralData[0];
  135. var sumWeight = 0;
  136. var sumValue = 0;
  137. let regionIndexes = { code: region.nuts };
  138. req.body.factors.forEach(f => {
  139. let fi = nutsData.getFactorIndex(region, f);
  140. //console.log("f: " + JSON.stringify(f));
  141. //console.log("fi: " + JSON.stringify(fi));
  142. regionIndexes[f.factor] = fi.index;
  143. sumValue += fi.sumValue * f.weight;
  144. sumWeight += fi.sumWeight;
  145. });
  146. regionIndexes.aggregate = sumValue / sumWeight;
  147. resData.push(regionIndexes);
  148. });
  149. helpers.formatResponse(resData, req, res);
  150. }
  151. function returnRegionScores(nuts, req, res) {
  152. var found = false;
  153. res.header("Content-Type", 'application/json');
  154. _ruralData.forEach(region => {
  155. if (region.nuts == nuts) {
  156. helpers.formatResponse(region, req, res);
  157. found = true;
  158. }
  159. });
  160. if (!found)
  161. // NUTS region not found
  162. res.status(404).send('NUTS region not found.');
  163. }