first score search draft working
This commit is contained in:
parent
84b9a8abc9
commit
e566344098
145
backend/app.js
145
backend/app.js
@ -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))
|
||||
@ -33,9 +41,144 @@ app.get('/v1/search', (req, res) => {
|
||||
headers: req.headers
|
||||
}
|
||||
|
||||
response.data = sampledata.search_response_model
|
||||
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)
|
||||
}
|
||||
@ -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), [])
|
||||
|
||||
@ -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
84
backend/mysql.js
Normal 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;
|
||||
@ -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": {
|
||||
|
||||
@ -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))
|
||||
Loading…
Reference in New Issue
Block a user