first score search draft working

This commit is contained in:
Timo Volkmann 2020-06-12 18:43:09 +02:00 committed by Timo Volkmann
parent e1a788c56b
commit 7bb07af76a
6 changed files with 243 additions and 97 deletions

View File

@ -1,8 +1,11 @@
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 = [
{
@ -20,6 +23,11 @@ const samplePresets = [
}
]
// 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))
@ -32,10 +40,145 @@ app.get('/v1/search', (req, res) => {
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)
response.data = sampledata.search_response_model
res.json(response)
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}`))
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)
}

View File

@ -15,17 +15,10 @@ async function main() {
});
const [result, fields] = await connection.execute(`SELECT * FROM regions WHERE meteostat_id IS NOT NULL`)
// Promise.all(result.map(res => {
// return createClimateObject(res)
// })).then(results => {
// let flat = results.reduce((total, element) => total.concat(element), [])
// console.log(flat)
// })
let temp = await Promise.all(result.map(x => createClimateObject(x)))
let final = temp.reduce((total, element) => total.concat(element), [])
//await writeToDatabase(connection, final)
await writeToDatabase(connection, final)
let temp2 = await Promise.all(result.map(x => createClimateObjectFrom(x)))
let final2 = temp2.reduce((total, element) => total.concat(element), [])

View File

@ -1,73 +0,0 @@
var mysql = require('mysql');
require('dotenv').config()
var connection = mysql.createConnection({
host: process.env.DB_HOST,
user: process.env.DB_USER,
password: process.env.DB_PASSWORD,
port: process.env.DB_PORT,
database: 'travopti'
});
// var pool = mysql.createPool({
// connectionLimit: 10,
// host: process.env.DB_HOST,
// user: process.env.DB_USER,
// password: process.env.DB_PASSWORD,
// port: process.env.DB_PORT,
// database: 'travopti'
// });
// let travoptidb = {}
// travoptidb.all = () => {
// return new Promise((resolve, reject) => {
// pool.query(`SELECT * FROM regions`, (err, results) => {
// if (err) {
// return reject(err)
// }
// return resolve(results)
// })
// })
// }
connection.connect((err) => {
if (err) throw err;
console.log('Database connected!')
});
exports.getRegions = () => {
let sql = `SELECT * FROM regions`;
console.log(connection.state)
if (connection.state === 'disconnected') {
setTimeout(() => console.log('waiting...'), 1000);
}
console.log('executed')
let res = {}
connection.query(sql, (error, results, fields) => {
if (error) {
return console.error(error.message);
}
console.log('innercallback(1)')
res = results[0]
});
console.log('outsidecallback(2)')
return res;
}
exports.getBYTdata = () => {
connection.query(`SELECT * FROM regions_byt`, (error, results, fields) => {
if (error) {
return console.error(error.message);
}
console.log(results[0])
nres = results.map((obj) => {
return obj.region
})
//console.log(nres);
});
}
exports.end = () => connection.end();
// module.exports = connection;

84
backend/mysql.js Normal file
View File

@ -0,0 +1,84 @@
var mysql = require('mysql2/promise');
require('dotenv').config()
// var connection = mysql.createConnection({
// host: process.env.DB_HOST,
// user: process.env.DB_USER,
// password: process.env.DB_PASSWORD,
// port: process.env.DB_PORT,
// database: 'travopti'
// });
const pool = mysql.createPool({
connectionLimit: 10,
host: process.env.DB_HOST,
user: process.env.DB_USER,
password: process.env.DB_PASSWORD,
port: process.env.DB_PORT,
database: 'travopti'
});
pool.getConnection()
.then(function (connection) {
console.log(`Connected to database: ${process.env.DB_HOST}`);
//pool.releaseConnection(connection)
})
.catch(function (error) {
console.error(error.message);
});
module.exports = pool;
// let travoptidb = {}
// travoptidb.all = () => {
// return new Promise((resolve, reject) => {
// pool.query(`SELECT * FROM regions`, (err, results) => {
// if (err) {
// return reject(err)
// }
// return resolve(results)
// })
// })
// }
// connection.connect((err) => {
// if (err) throw err;
// console.log('Database connected!')
// });
// exports.getRegions = () => {
// let sql = `SELECT * FROM regions`;
// console.log(connection.state)
// if (connection.state === 'disconnected') {
// setTimeout(() => console.log('waiting...'), 1000);
// }
// console.log('executed')
// let res = {}
// connection.query(sql, (error, results, fields) => {
// if (error) {
// return console.error(error.message);
// }
// console.log('innercallback(1)')
// res = results[0]
// });
// console.log('outsidecallback(2)')
// return res;
// }
// exports.getBYTdata = () => {
// connection.query(`SELECT * FROM regions_byt`, (error, results, fields) => {
// if (error) {
// return console.error(error.message);
// }
// console.log(results[0])
// nres = results.map((obj) => {
// return obj.region
// })
// //console.log(nres);
// });
// }
// exports.end = () => connection.end();
// module.exports = connection;

View File

@ -3,9 +3,9 @@
"version": "1.0.0",
"description": "",
"main": "app.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"scripts": {
"start": "nodemon ./app.js"
},
"author": "",
"license": "ISC",
"dependencies": {

View File

@ -8,24 +8,23 @@ const multiplier_temperature = 5;
*
* @param {...any} scores expects objects which contains score and their weight
*/
function calculateAvgScore(...scores) {
exports.calculateAvgScore = (...scores) => {
return avgScore = scores.reduce((total, score) => total += score) / scores.length;
}
function calculateScoreRange(min, max, multiplier, targetVal, sLowVal, sHighVal) {
exports.calculateScoreRange = (min, max, multiplier, regionVal, sLowVal, sHighVal) => {
// return full score when in range
if (targetVal >= sLowVal && targetVal <= sHighVal) return 10;
if (regionVal >= sLowVal && regionVal <= sHighVal) return 10;
// choose value with smallest distance
let sVal = Math.abs(targetVal - sLowVal) < Math.abs(targetVal - sHighVal) ? sLowVal : sHighVal;
let sVal = Math.abs(regionVal - sLowVal) < Math.abs(regionVal - sHighVal) ? sLowVal : sHighVal;
return calculateScore(min, max, multiplier, targetVal, sVal);
return this.calculateScore(min, max, multiplier, regionVal, sVal);
}
function calculateScore(min, max, multiplier, targetVal, searchVal) {
exports.calculateScore = (min, max, multiplier, regionVal, searchVal) => {
let score = 1 - (Math.abs(searchVal - targetVal) / (max - min) * multiplier);
let score = 1 - (Math.abs(searchVal - regionVal) / (max - min) * multiplier);
return score <= 0 ? 0 : score * 10;
}
console.log('Calc')
console.log(calculateScoreRange(-15, 45, 5, 24, 15, 22))
console.log('test score calculation. result: ' + this.calculateScoreRange(-15, 45, 5, 24, 15, 22))