index.js 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  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('/run', (req, res, next) => {
  115. //console.log(console);
  116. console.log('calling R...')
  117. let out = 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 console.log(data);
  122. helpers.formatResponse({ response: data }, req, res);
  123. }
  124. );
  125. });
  126. // start the service on the port xxxx
  127. app.listen(3000, () => console.log('Rural attractivity WS listening on port 3000...'));
  128. function returnAllScores(req, res) {
  129. var resData = [];
  130. _ruralData.forEach(region => {
  131. //var region = _ruralData[0];
  132. var sumWeight = 0;
  133. var sumValue = 0;
  134. let regionIndexes = { code: region.nuts };
  135. req.body.factors.forEach(f => {
  136. let fi = nutsData.getFactorIndex(region, f);
  137. //console.log("f: " + JSON.stringify(f));
  138. //console.log("fi: " + JSON.stringify(fi));
  139. regionIndexes[f.factor] = fi.index;
  140. sumValue += fi.sumValue * f.weight;
  141. sumWeight += fi.sumWeight;
  142. });
  143. regionIndexes.aggregate = sumValue / sumWeight;
  144. resData.push(regionIndexes);
  145. });
  146. helpers.formatResponse(resData, req, res);
  147. }
  148. function returnRegionScores(nuts, req, res) {
  149. var found = false;
  150. res.header("Content-Type", 'application/json');
  151. _ruralData.forEach(region => {
  152. if (region.nuts == nuts) {
  153. helpers.formatResponse(region, req, res);
  154. found = true;
  155. }
  156. });
  157. if (!found)
  158. // NUTS region not found
  159. res.status(404).send('NUTS region not found.');
  160. }