first score search draft working
This commit is contained in:
parent
84b9a8abc9
commit
e566344098
151
backend/app.js
151
backend/app.js
@ -1,8 +1,11 @@
|
|||||||
var express = require('express')
|
var express = require('express')
|
||||||
var sampledata = require('./sampledata')
|
var sampledata = require('./sampledata')
|
||||||
|
var db = require('./mysql')
|
||||||
|
var score = require('./score')
|
||||||
|
|
||||||
const app = express()
|
const app = express()
|
||||||
const port = 3000
|
const port = 3000
|
||||||
|
const multiplier_temp = 5
|
||||||
|
|
||||||
const sampleRegions = [
|
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('/', (req, res) => res.send('Hello Timo!'))
|
||||||
app.get('/v1/regions', (req, res) => res.json(sampleRegions))
|
app.get('/v1/regions', (req, res) => res.json(sampleRegions))
|
||||||
app.get('/v1/presets', (req, res) => res.json(samplePresets))
|
app.get('/v1/presets', (req, res) => res.json(samplePresets))
|
||||||
@ -32,10 +40,145 @@ app.get('/v1/search', (req, res) => {
|
|||||||
query: req.query,
|
query: req.query,
|
||||||
headers: req.headers
|
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
|
search(req.query.from, req.query.to, { temperature: req.query.temperature }).then(searchResults => {
|
||||||
|
response.data = searchResults
|
||||||
res.json(response)
|
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)
|
||||||
|
}
|
||||||
@ -15,17 +15,10 @@ async function main() {
|
|||||||
});
|
});
|
||||||
const [result, fields] = await connection.execute(`SELECT * FROM regions WHERE meteostat_id IS NOT NULL`)
|
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 temp = await Promise.all(result.map(x => createClimateObject(x)))
|
||||||
let final = temp.reduce((total, element) => total.concat(element), [])
|
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 temp2 = await Promise.all(result.map(x => createClimateObjectFrom(x)))
|
||||||
let final2 = temp2.reduce((total, element) => total.concat(element), [])
|
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",
|
"version": "1.0.0",
|
||||||
"description": "",
|
"description": "",
|
||||||
"main": "app.js",
|
"main": "app.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "echo \"Error: no test specified\" && exit 1"
|
"start": "nodemon ./app.js"
|
||||||
},
|
},
|
||||||
"author": "",
|
"author": "",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|||||||
@ -8,24 +8,23 @@ const multiplier_temperature = 5;
|
|||||||
*
|
*
|
||||||
* @param {...any} scores expects objects which contains score and their weight
|
* @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;
|
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
|
// 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
|
// 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;
|
return score <= 0 ? 0 : score * 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('Calc')
|
console.log('test score calculation. result: ' + this.calculateScoreRange(-15, 45, 5, 24, 15, 22))
|
||||||
console.log(calculateScoreRange(-15, 45, 5, 24, 15, 22))
|
|
||||||
Loading…
Reference in New Issue
Block a user