cleaned up and reduced scorer overhead
This commit is contained in:
parent
2060eea09f
commit
6145c40654
@ -1,6 +0,0 @@
|
||||
{
|
||||
"temperature_mean_max": 5,
|
||||
"precipitation": 3.5,
|
||||
"raindays": 3,
|
||||
"sunhours": 2.5
|
||||
}
|
||||
@ -1,6 +0,0 @@
|
||||
{
|
||||
"id": 29837,
|
||||
"parameter": "temperature",
|
||||
"label": "warm",
|
||||
"values": [22, 25]
|
||||
}
|
||||
@ -9,8 +9,7 @@ const _ = require('lodash')
|
||||
const base64 = require("../util/base64.js")
|
||||
const scoreAndSearch = require("../util/scoreAndSearch.js");
|
||||
const oldToNewQuerySyntax = require("../util/oldToNewQuerySyntax.js")
|
||||
const { allTagsWithValues, getUniqueTags } = require("../models/getTags.js");
|
||||
const { getClimateMinMax } = require("../util/getClimateMinMax.js");
|
||||
const { getUniqueTags } = require("../models/getTags.js");
|
||||
|
||||
module.exports = dbConn => {
|
||||
router.get("/api/v1/search", searchHandler(dbConn));
|
||||
@ -61,10 +60,9 @@ function searchHandler(dbConn) {
|
||||
// CHOOSE PARAMS WHICH SHALL BE PASSED TO SCORE AND SEARCH
|
||||
let scoreQueryObj = prepareQueries(q)
|
||||
|
||||
let [regions, boundaryClimate] = await Promise.all([getRegions(dbConn), getClimateMinMax(dbConn)])
|
||||
let [regions] = await Promise.all([getRegions(dbConn)])
|
||||
let data = {
|
||||
regions: regions,
|
||||
boundaryClimate: boundaryClimate
|
||||
}
|
||||
|
||||
// FILTER if query contains filterString
|
||||
@ -82,28 +80,8 @@ function searchHandler(dbConn) {
|
||||
console.log('without null scores');
|
||||
searchResults.forEach(el => console.log('region:', el.name, 'score:', el.score))
|
||||
searchResults = searchResults.filter(el => !_.some(el.scores, score => _.isNaN(score.score) || _.isNil(score.score) || score.score <= 0))
|
||||
// searchResults = searchResults.filter(el => !(_.isNil(el.score) || _.isNaN(el.score)) )
|
||||
// searchResults = searchResults.filter(el => {
|
||||
// let nullcnt = 0
|
||||
// el.scores.forEach(sc => {
|
||||
// if (_.isNaN(sc.score) || sc.score <= 0 || _.isNil(el.score)) {
|
||||
// nullcnt++
|
||||
// }
|
||||
// })
|
||||
// console.log(el.name, nullcnt)
|
||||
// return nullcnt >= 2 ? false : true
|
||||
// })
|
||||
|
||||
/*searchResults = searchResults.filter(el => {
|
||||
console.log('scorrrrrr', el.score);
|
||||
let keepIt = true
|
||||
//if (_.some(el.scores, score => score.score <= 0) && el.score < 1) keepIt = false
|
||||
return cutScores ? keepIt : true
|
||||
})//.filter(el => !_.isNaN(el.score))*/
|
||||
}
|
||||
// SEND RESPONSE
|
||||
// response.data = searchResults
|
||||
// res.json(response)
|
||||
res.json(searchResults)
|
||||
|
||||
}).catch(e => {
|
||||
|
||||
62
backend/settings.js
Normal file
62
backend/settings.js
Normal file
@ -0,0 +1,62 @@
|
||||
module.exports = {
|
||||
scoring: {
|
||||
// parameter: [transition range, transition function, transistion slope exponent]
|
||||
temperature_mean_max: [12, 'easeInOut', 2],
|
||||
precipitation: [60, 'easeInOut', 2], // [170, 'easeInOut', 2],
|
||||
rain_days: [5, 'easeInOut', 2],
|
||||
sun_hours: [80, 'easeInOut', 2],
|
||||
|
||||
accommodation_costs: [30, 'linear', null],
|
||||
food_costs: [25, 'linear', null],
|
||||
alcohol_costs: [15, 'linear', null],
|
||||
water_costs: [15, 'linear', null],
|
||||
local_transportation_costs: [20, 'linear', null],
|
||||
entertainment_costs: [20, 'easeInOut', 0.6],
|
||||
average_per_day_costs: [100, 'linear', null],
|
||||
|
||||
avg_price_relative: [30, 'easeOut', 2],
|
||||
},
|
||||
boundaries: {
|
||||
climate: {
|
||||
min: {
|
||||
temperature_mean: -9.6,
|
||||
temperature_mean_min: -14.5,
|
||||
temperature_mean_max: -4.7,
|
||||
precipitation: 0,
|
||||
rain_days: 0,
|
||||
sun_hours: 3
|
||||
},
|
||||
max: {
|
||||
temperature_mean: 38.3,
|
||||
temperature_mean_min: 33.5,
|
||||
temperature_mean_max: 43.7,
|
||||
precipitation: 1145,
|
||||
rain_days: 28,
|
||||
sun_hours: 416
|
||||
}
|
||||
},
|
||||
static: {
|
||||
max: {
|
||||
accommodation_costs: 500,
|
||||
food_costs: 100,
|
||||
alcohol_costs: 100,
|
||||
water_costs: 100,
|
||||
local_transportation_costs: 100,
|
||||
entertainment_costs: 100,
|
||||
average_per_day_costs: 1000,
|
||||
avg_price_relative: 100
|
||||
|
||||
},
|
||||
min: {
|
||||
accommodation_costs: 0,
|
||||
food_costs: 0,
|
||||
alcohol_costs: 0,
|
||||
water_costs: 0,
|
||||
local_transportation_costs: 0,
|
||||
entertainment_costs: 0,
|
||||
average_per_day_costs: 0,
|
||||
avg_price_relative: 0
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,9 +0,0 @@
|
||||
const moment = require('moment')
|
||||
|
||||
let date = {
|
||||
year: 2012,
|
||||
month: 3,
|
||||
day: 13
|
||||
}
|
||||
|
||||
console.log(moment(date));
|
||||
@ -4,17 +4,17 @@ exports.calculateAvgScore = (...scores) => {
|
||||
return avgScore = scores.reduce((total, score) => total += score) / scores.length;
|
||||
}
|
||||
|
||||
exports.calculateScoreRange = (min, max, multiplier, regionVal, sLowVal, sHighVal) => {
|
||||
exports.calculateScoreRange = (transitionRange, regionVal, sLowVal, sHighVal) => {
|
||||
//console.log('scores.calculateScoreRange:', min, max, multiplier, regionVal, sLowVal, sHighVal)
|
||||
// return full score when in range
|
||||
if (regionVal >= sLowVal && regionVal <= sHighVal) return 10;
|
||||
// choose value with smallest distance
|
||||
let sVal = Math.abs(regionVal - sLowVal) < Math.abs(regionVal - sHighVal) ? sLowVal : sHighVal;
|
||||
return this.calculateScore(min, max, multiplier, regionVal, sVal);
|
||||
return this.calculateScore(transitionRange, regionVal, sVal);
|
||||
}
|
||||
|
||||
exports.calculateScore = (min, max, multiplier, regionVal, searchVal) => {
|
||||
let score = 1 - (Math.abs(searchVal - regionVal) / (max - min) * multiplier);
|
||||
exports.calculateScore = (transitionRange, regionVal, searchVal) => {
|
||||
let score = 1 - (Math.abs(searchVal - regionVal) / transitionRange);
|
||||
return (score) * 10;
|
||||
//return score <= 0 ? 0 : score * 10;
|
||||
}
|
||||
@ -53,4 +53,14 @@ exports.sigmoid = function (x, exponent) {
|
||||
const sigm = 10 / (1 + 8 * Math.pow(Math.E, 3/4 * -x))
|
||||
console.log('sigmoid (IN/OUT):', _.round(x,3), _.round(sigm, 3))
|
||||
return sigm
|
||||
}
|
||||
|
||||
exports.increaseTransitionForHighValues = function (transitionRange, searchVal) {
|
||||
//console.log(transitionRange);
|
||||
// console.log(transitionRange);
|
||||
// console.log(((Math.pow(searchVal / 20, 2) / 100) + 1));
|
||||
// console.log(((Math.pow(searchVal / 20, 2) / 100) + 1) * transitionRange);
|
||||
let transFactor = ((Math.pow(searchVal / 20, 2) / 100) + 1)
|
||||
|
||||
return transFactor >= 4 ? 4 * transitionRange : transFactor * transitionRange
|
||||
}
|
||||
@ -1,26 +1,7 @@
|
||||
const _ = require('lodash')
|
||||
const moment = require("moment")
|
||||
const getClimateMinMax = require("./getClimateMinMax.js")
|
||||
const scorer = require('./score')
|
||||
const getRegions = require('../models/getRegions.js')
|
||||
|
||||
const SHOW_ALL_SCOREOBJECTS = false
|
||||
const SETTINGS = {
|
||||
temperature_mean_max: [4.5, 'easeOut', 2],
|
||||
precipitation: [4, 'easeInOut', 2],
|
||||
rain_days: [2, 'easeInOut', 2],
|
||||
sun_hours: [3.6, 'easeInOut', 2],
|
||||
|
||||
accommodation_costs: [17, 'linear', null],
|
||||
food_costs: [4, 'linear', null],
|
||||
alcohol_costs: [4, 'linear', null],
|
||||
water_costs: [10, 'linear', null],
|
||||
local_transportation_costs: [5, 'linear', null],
|
||||
entertainment_costs: [5, 'easeInOut', 0.6],
|
||||
average_per_day_costs: [5, 'linear', null],
|
||||
|
||||
avg_price_relative: [3, 'easeOut', 2],
|
||||
}
|
||||
const SETTINGS = require('../settings').scoring
|
||||
|
||||
module.exports = async function (data, from, to, q) {
|
||||
console.log('search')
|
||||
@ -28,7 +9,7 @@ module.exports = async function (data, from, to, q) {
|
||||
if ((_.isNil(to) || _.isNil(from)) && !(_.isEmpty(q.climate) || _.isEmpty(q.costs) || _.isEmpty(q.others))) {
|
||||
throw new Error('invalid query')
|
||||
}
|
||||
if (_.isNil(data) || _.isEmpty(data.regions) || _.isEmpty(data.boundaryClimate)) {
|
||||
if (_.isNil(data) || _.isEmpty(data.regions)) {
|
||||
throw new Error('database error')
|
||||
}
|
||||
let regionsArr = data.regions
|
||||
@ -68,20 +49,20 @@ module.exports = async function (data, from, to, q) {
|
||||
// CALCULATE SCORES FOR CLIMATE PROPS
|
||||
reg.scores = []
|
||||
Object.entries(q.climate).forEach(([key, value]) => {
|
||||
let finalScoreObj = calculateScoreForPeriod(key, travelPeriods, reg, value[0], value[1], data.boundaryClimate)
|
||||
let finalScoreObj = calculateScoreForPeriod(key, travelPeriods, reg, value[0], value[1])
|
||||
reg.scores.push(finalScoreObj)
|
||||
});
|
||||
|
||||
// CALCULATE SCORES FOR PRICE PROPS
|
||||
Object.entries(q.costs).forEach(([key, value]) => {
|
||||
let finalScoreObj = scoreFromSimpleRegionProperty(key, reg, value[0], value[1], boundaryStatic)
|
||||
let finalScoreObj = scoreFromSimpleRegionProperty(key, reg, value[0], value[1])
|
||||
|
||||
reg.scores.push(finalScoreObj)
|
||||
});
|
||||
|
||||
// CALCULATE SCORE FOR OFFSEASON
|
||||
if (_.has(q, 'others.avg_price_relative')) {
|
||||
let offSeasonScoreObj = calculateScoreForPeriod('avg_price_relative', travelPeriods, reg, q.others.avg_price_relative[0], q.others.avg_price_relative[1], boundaryStatic, 'easeOut', 2)
|
||||
let offSeasonScoreObj = calculateScoreForPeriod('avg_price_relative', travelPeriods, reg, q.others.avg_price_relative[0], q.others.avg_price_relative[1], 'easeOut', 2)
|
||||
reg.scores.push(offSeasonScoreObj)
|
||||
}
|
||||
|
||||
@ -218,7 +199,7 @@ function createPeriod(from, to, currentMonth, currentYear) {
|
||||
}
|
||||
|
||||
|
||||
function calculateScoreForPeriod(type, travelPeriods, region, searchLowParam, searchMaxParam, minMax) {
|
||||
function calculateScoreForPeriod(type, travelPeriods, region, searchLowParam, searchMaxParam) {
|
||||
// console.log('getScoreAndAverageFromClimate for', region.name, type)
|
||||
|
||||
const singleScores = travelPeriods.map(period => {
|
||||
@ -248,8 +229,14 @@ function calculateScoreForPeriod(type, travelPeriods, region, searchLowParam, se
|
||||
})
|
||||
averagedScore.value = _.round(averagedScore.value / averagedScore.days, 3)
|
||||
delete averagedScore.days
|
||||
|
||||
let transitionRange = SETTINGS[type][0]
|
||||
// special for precipitation
|
||||
if (type === 'precipitation') {
|
||||
transitionRange = scorer.increaseTransitionForHighValues(SETTINGS[type][0], searchLowParam)
|
||||
}
|
||||
|
||||
let sc = scorer.calculateScoreRange(minMax.min[type], minMax.max[type], SETTINGS[type][0], averagedScore.value, searchLowParam, searchMaxParam)
|
||||
let sc = scorer.calculateScoreRange(transitionRange, averagedScore.value, searchLowParam, searchMaxParam)
|
||||
averagedScore.score = _.round(scorer[SETTINGS[type][1]](sc, SETTINGS[type][2]), 3)
|
||||
// console.log('score', averagedScore.score)
|
||||
if (searchLowParam === null) averagedScore.score = null
|
||||
@ -267,7 +254,7 @@ function scoresFromTags(regionTags, tagStringsFromQueries) {
|
||||
}
|
||||
if (_.isNil(tag)) return retVal
|
||||
retVal.value = tag.value
|
||||
retVal.score = /* tag.value <= 0 ? 0 : */ _.round(scorer.calculateScoreRange(40, 100, 1, tag.value, 100, 100), 3)
|
||||
retVal.score = /* tag.value <= 0 ? 0 : */ _.round(scorer.calculateScoreRange(60, tag.value, 100, 100), 3)
|
||||
console.log(retVal);
|
||||
|
||||
return retVal
|
||||
@ -276,7 +263,7 @@ function scoresFromTags(regionTags, tagStringsFromQueries) {
|
||||
|
||||
function scoreFromSimpleRegionProperty(type, region, searchLowParam, searchMaxParam, minMax) {
|
||||
// console.log('getScoreFromCosts for', region.name, type)
|
||||
const sc = _.round(scorer.calculateScoreRange(minMax.min[type], minMax.max[type], SETTINGS[type][0], region[type], searchLowParam, searchMaxParam), 3)
|
||||
const sc = _.round(scorer.calculateScoreRange(SETTINGS[type][0], region[type], searchLowParam, searchMaxParam), 3)
|
||||
|
||||
let finScore = {
|
||||
type: type,
|
||||
|
||||
Loading…
Reference in New Issue
Block a user