travopti/backend/app.js

184 lines
5.6 KiB
JavaScript

var express = require('express')
var sampledata = require('./sampledata')
var db = require('./mysql')
var score = require('./score')
const app = express()
const port = 3000
const multiplier_temp = 5
const sampleRegions = [
{
id: 29837,
name: "Timbuktu",
country: "Mali"
}
]
const samplePresets = [
{
id: 29837,
parameter: "temperature",
label: "warm",
values: [22, 25]
}
]
// db.connect((err) => {
// if (err) throw err;
// console.log('Database connected!')
// });
app.get('/', (req, res) => res.send('Hello Timo!'))
app.get('/v1/regions', (req, res) => res.json(sampleRegions))
app.get('/v1/presets', (req, res) => res.json(samplePresets))
app.get('/v1/search', (req, res) => {
// check query params
let response = {}
response.meta = {
params: req.params,
query: req.query,
headers: req.headers
}
console.log('log params')
console.log(req.query.from)
console.log(req.query.to)
console.log(req.query.temperature)
search(req.query.from, req.query.to, { temperature: req.query.temperature }).then(searchResults => {
response.data = searchResults
res.json(response)
})
})
app.listen(port, () => console.log(`Travopti backend listening at http://localhost:${port}`))
async function search(from, to, queries) {
console.log('search')
// validate regex: YYYY-MM-DD
let re = /([12]\d{3}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01]))/i;
if (!from.match(re) || !to.match(re)) throw new Error("invalid parameter: " + from + " " + to)
// -- Prepare search --
// calculate average if traveldates are in more than one month
let monthFrom = Number(from.split("-")[1])
let monthTo = Number(to.split("-")[1])
let values = []
let virtDays = 0
if (monthFrom === monthTo) {
let element = {
month: monthFrom,
days: Number(to.split("-")[2]) - Number(from.split("-")[2])
}
virtDays = element.days
values.push(element)
} else {
for (let index = monthFrom; index <= monthTo; index++) {
let element = {}
if (index === monthFrom) {
element = {
month: index,
days: 31 - Number(from.split("-")[2])
}
} else if (index === monthTo) {
element = {
month: index,
days: Number(to.split("-")[2])
}
} else {
element = {
month: index,
days: 30
}
}
virtDays += element.days
values.push(element)
}
}
// retrieve data from database
const minMax = await getClimateMinMax()
const data = await Promise.all(values.map(async (val) => {
return await getAllClimatePerMonth(val.month)
}))
console.log("data from getAllClimatePerMonth")
//console.log(data)
// calculate score
// TODO: calculate score for all months
let scores_temp
if (queries.temperature) {
scores_temp = calculateTempScores(data[0], queries.temperature.split(',')[0], queries.temperature.split(',')[1], minMax)
}
// TODO: calculate ratio
return { TODO___temperature_scores: scores_temp }
}
function calculateTempScores(regionDataRows, searchLowParam, searchMaxParam, minMax) {
console.log('calculateTempScores')
console.log(searchLowParam)
console.log(searchMaxParam)
console.log(minMax)
//console.log(regionDataRows)
let result = regionDataRows.map(x => {
console.log(x.temperature_mean)
return {
region_id: x.region_id,
value: x.temperature_mean,
score: Math.round(score.calculateScoreRange(minMax.min.temperature_mean, minMax.max.temperature_mean, multiplier_temp, x.temperature_mean, searchLowParam, searchMaxParam)*100)/100
}
})
return result
}
async function getClimateMinMax() {
console.log('getClimateMinMax')
const sqlMin = `SELECT
MIN(temperature_mean) AS temperature_mean,
MIN(temperature_mean_min) AS temperature_mean_min,
MIN(temperature_mean_max) AS temperature_mean_max,
MIN(percipitation) AS percipitation,
MIN(sunshine) AS sunshine
FROM region_climate`
const sqlMax = `SELECT
MAX(temperature_mean) AS temperature_mean,
MAX(temperature_mean_min) AS temperature_mean_min,
MAX(temperature_mean_max) AS temperature_mean_max,
MAX(percipitation) AS percipitation,
MAX(sunshine) AS sunshine
FROM region_climate`
const [qResMin, qResMax] = await Promise.all([getQueryRows(sqlMin), getQueryRows(sqlMax)])
console.log(qResMin)
return { min: qResMin[0], max: qResMax[0] }
}
async function getQueryRows(sql) {
console.log('getQueryRows')
const [rows, fields] = await db.execute(sql)
return rows
}
async function getRegionIdsWithMeteostatData() {
console.log('getRegionIdsWithMeteostatData')
//return await getQueryRows(`SELECT * FROM regions WHERE meteostat_id IS NOT NULL`)
return await getQueryRows(`SELECT region_id FROM region_climate GROUP BY region_id`)
}
async function getClimatePerRegionAndMonth(regionId, month) {
console.log('getClimatePerRegionAndMonth')
const sql = `SELECT region_id, AVG(temperature_mean), AVG(temperature_mean_min), AVG(temperature_mean_max), AVG(percipitation), AVG(sunshine) FROM region_climate WHERE month = ${month} AND region_id = ${regionId}`
return await getQueryRows(sql)
}
async function getAllClimatePerMonth(month) {
console.log('getAllClimatePerMonth')
const sql = `SELECT
region_id,
ROUND(AVG(temperature_mean), 1) AS temperature_mean,
ROUND(AVG(temperature_mean_min), 1) AS temperature_mean_min,
ROUND(AVG(temperature_mean_max), 1) AS temperature_mean_max,
ROUND(AVG(percipitation), 1) AS percipitation,
ROUND(AVG(sunshine), 1) AS sunshine
FROM region_climate WHERE month = ${month} GROUP BY region_id`
return await getQueryRows(sql)
}