const _ = require('lodash') const moment = require("moment") const getClimateMinMax = require("./getClimateMinMax.js") const oldToNewQuerySyntax = require("./oldToNewQuerySyntax.js") const getAllRegionsWithClimatePerMonth = require('./getAllRegionsWithClimatePerMonth') const score = require('./score') const transformer = require('./transformer') const getRegions = require('../models/getRegions.js').getRegionsInternal // const getRegions = require('../models/getRegions2.js') const MULTIPLIER = { temperature_mean_max: 5, percipitation: 3.5, raindays: 3, sunhours: 2.5, } module.exports = function (dbConn) { return async function (from, to, queries) { console.log('search') // get Min and Max values for each Parameter const minMax = await getClimateMinMax.getClimateMinMax(dbConn) // to still support old query syntax queries = oldToNewQuerySyntax.oldToNewQuerySyntax(queries) console.log(queries) // TODO simplify and remove support for old query syntaax let monthFrom = 0 let monthTo = 0 let dayFrom = 0 let dayTo = 0 if (_.isNumber(from) && _.isNumber(to)) { let dateFrom = moment(from).toDate() let dateTo = moment(to).toDate() monthFrom = dateFrom.getMonth() monthTo = dateTo.getMonth() dayFrom = dateFrom.getDay() dayTo = dateTo.getDay() if (moment(dateFrom).add(23, 'hours').isAfter(moment(dateTo))) throw new Error("ERR: 'to' must be at least one day after 'from'.") } else { // this block to still support old query syntax let re = /([12]\d{3}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01]))/i; monthFrom = Number(from.split("-")[1]) monthTo = Number(to.split("-")[1]) dayFrom = Number(from.split("-")[2]) dayTo = Number(to.split("-")[2]) if (!from.match(re) || !to.match(re)) throw new Error("ERR: invalid parameter:", from, to) if (moment(from, 'YYYY-MM-DD').add(23, 'hours').isAfter(moment(to, 'YYYY-MM-DD'))) throw new Error("ERR: 'to' must be at least one day after 'from'.") } // -- Prepare search -- // to calculate average if traveldates are in more than one month let travelPeriods = [] if (monthFrom === monthTo) { let element = { month: monthFrom, days: dayTo - dayFrom } travelPeriods.push(element) } else { for (let index = monthFrom; index <= monthTo; index++) { let element = {} if (index === monthFrom) { element = { month: index, days: 32 - dayFrom } } else if (index === monthTo) { element = { month: index, days: dayTo } } else { element = { month: index, days: 30 } } travelPeriods.push(element) } } // calculate detail scores let detailScores = await Promise.all(travelPeriods.map(async period => { period.climate = await getAllRegionsWithClimatePerMonth(dbConn)(period.month) // @TimoJ hier müssten die Preise mit rein, z.B. // period.prices = await getAveragePricesPerMonth(dbConn)(period.month) period.scores = {} Object.entries(queries).forEach(([key, value]) => { // console.log('key',key) // console.log('val', value) period.scores[key] = calculateScores(key, period.climate, value[0], value[1], minMax) }); return period })); //console.log(allRegs) // calculate ratio and transform into target object let allRegs = await getRegions(dbConn) return { results: transformer.transform(detailScores, allRegs), debug: { detailScores: detailScores, minMax: minMax } } } function calculateScores(type, regionDataRows, searchLowParam, searchMaxParam, minMax) { console.log('calculateScores for', type) let result = regionDataRows.map(x => { const sc = Math.round(score.calculateScoreRange(minMax.min[type], minMax.max[type], MULTIPLIER[type], x[type], searchLowParam, searchMaxParam) * 100) / 100 return { region_id: x.region_id, type: type, value: x[type], score: x[type] === null ? null : sc } }) return result } }