Refactoring
This commit is contained in:
parent
2cc170395c
commit
c4cd9d1806
2 changed files with 104 additions and 79 deletions
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* RuleSet Class
|
* RuleSet Class
|
||||||
* Constructor
|
* Constructor
|
||||||
|
@ -12,14 +11,14 @@ class RuleSet {
|
||||||
this.defaultValue = defaultValue;
|
this.defaultValue = defaultValue;
|
||||||
this.values = values;
|
this.values = values;
|
||||||
this.score = this.defaultValue;
|
this.score = this.defaultValue;
|
||||||
this.scoreValues = null;
|
|
||||||
this.order = null;
|
this.order = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* toString
|
* toString
|
||||||
* Returns constructor values in string for display in the console
|
* Returns constructor values in string for display in the console
|
||||||
*/
|
*/
|
||||||
toString () {
|
toString() {
|
||||||
return `${this.name} | ${this.defaultValue} | ${this.values}`;
|
return `${this.name} | ${this.defaultValue} | ${this.values}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,65 +26,109 @@ class RuleSet {
|
||||||
* getScore calculates a score for the RuleSet
|
* getScore calculates a score for the RuleSet
|
||||||
* @param tags {object} Active tags to compare against
|
* @param tags {object} Active tags to compare against
|
||||||
*/
|
*/
|
||||||
runProgram (tags, initValues = this.values) {
|
runProgram(tags, program = this.values) {
|
||||||
const [
|
console.log("Running program", program)
|
||||||
[program, keys], values
|
if(typeof program !== "object"){
|
||||||
] = Object.entries(initValues);
|
return program;
|
||||||
console.log(program)
|
}
|
||||||
|
|
||||||
|
let functionName /*: string*/ = undefined;
|
||||||
|
let functionArguments /*: any */= undefined
|
||||||
|
let otherValues = {}
|
||||||
|
Object.entries(program).forEach(
|
||||||
|
entry => {
|
||||||
|
const [key, value] = entry
|
||||||
|
if (key.startsWith("$")) {
|
||||||
|
functionName = key
|
||||||
|
functionArguments = value
|
||||||
|
}else{
|
||||||
|
otherValues[key] = value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
if (program === '$multiply') {
|
if(functionName === undefined){
|
||||||
this.scoreValues = keys;
|
return this.interpretAsDictionary(program, tags)
|
||||||
this.score = this.multiplyScore(tags);
|
}
|
||||||
|
|
||||||
|
|
||||||
|
console.log(program)
|
||||||
|
if (functionName === '$multiply') {
|
||||||
|
this.score = this.multiplyScore(tags, functionArguments);
|
||||||
return `"${this.name.slice(8)}":"${this.score}"`;
|
return `"${this.name.slice(8)}":"${this.score}"`;
|
||||||
|
|
||||||
} else if (program === '$firstMatchOf') {
|
} else if (functionName === '$firstMatchOf') {
|
||||||
this.scoreValues = values;
|
|
||||||
this.order = keys;
|
this.order = keys;
|
||||||
const match = this.getFirstMatchScore(tags);
|
const match = this.getFirstMatchScore(tags);
|
||||||
return `"${this.name.slice(8)}":"${match}"`;
|
return `"${this.name.slice(8)}":"${match}"`;
|
||||||
|
|
||||||
} else if (program === '$min') {
|
} else if (functionName === '$min') {
|
||||||
this.scoreValues = keys;
|
const minVal = this.getMinValue(tags, functionArguments);
|
||||||
const minVal = this.getMinValue(tags);
|
|
||||||
return `"${this.name.slice(8)}":"${minVal}"`;
|
return `"${this.name.slice(8)}":"${minVal}"`;
|
||||||
|
|
||||||
} else if (program === '$max') {
|
} else if (functionName === '$max') {
|
||||||
this.scoreValues = keys;
|
const maxVal = this.getMaxValue(tags, functionArguments);
|
||||||
const maxVal = this.getMaxValue(tags);
|
|
||||||
return `"${this.name.slice(8)}":"${maxVal}"`;
|
return `"${this.name.slice(8)}":"${maxVal}"`;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
console.error(`Error: Program ${program} is not implemented yet. ${JSON.stringify(keys)}`);
|
console.error(`Error: Program ${functionName} is not implemented yet. ${JSON.stringify(program)}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given a 'program' without function invocation, interprets it as a dictionary
|
||||||
|
*
|
||||||
|
* E.g., given the program
|
||||||
|
*
|
||||||
|
* {
|
||||||
|
* highway: {
|
||||||
|
* residential: 30,
|
||||||
|
* living_street: 20
|
||||||
|
* },
|
||||||
|
* surface: {
|
||||||
|
* sett : 0.9
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* in combination with the tags {highway: residential},
|
||||||
|
*
|
||||||
|
* the result should be [30, undefined];
|
||||||
|
*
|
||||||
|
* For the tags {highway: residential, surface: sett} we should get [30, 0.9]
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @param program
|
||||||
|
* @param tags
|
||||||
|
* @return {(undefined|*)[]}
|
||||||
|
*/
|
||||||
|
interpretAsDictionary(program, tags) {
|
||||||
|
return Object.entries(tags).map(tag => {
|
||||||
|
const [key, value] = tag;
|
||||||
|
const propertyValue = program[key]
|
||||||
|
if (propertyValue === undefined) {
|
||||||
|
return undefined
|
||||||
|
}
|
||||||
|
if(typeof propertyValue !== "object"){
|
||||||
|
return propertyValue
|
||||||
|
}
|
||||||
|
return propertyValue[value]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Multiplies the default score with the proper values
|
* Multiplies the default score with the proper values
|
||||||
* @param tags {object} the active tags to check against
|
* @param tags {object} the active tags to check against
|
||||||
|
* @param subprogram which should generate a list of values
|
||||||
* @returns score after multiplication
|
* @returns score after multiplication
|
||||||
*/
|
*/
|
||||||
multiplyScore (tags) {
|
multiplyScore(tags, subprogram) {
|
||||||
let number = this.defaultValue;
|
let number = 1
|
||||||
|
this.runProgram(tags, subprogram).filter(r => r !== undefined).forEach(r => number *= parseFloat(r))
|
||||||
Object.entries(JSON.parse(tags)).forEach(tag => {
|
|
||||||
const [key, value] = tag;
|
|
||||||
console.log(key, value)
|
|
||||||
|
|
||||||
Object.entries(this.scoreValues).forEach(property => {
|
|
||||||
const [propKey, propValues] = property;
|
|
||||||
|
|
||||||
if (key === propKey) {
|
|
||||||
for (let propEntry of Object.entries(propValues)) {
|
|
||||||
const [propValueKey, propValue] = propEntry;
|
|
||||||
|
|
||||||
if (value === propValueKey) number *= propValue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
});
|
|
||||||
console.log(number)
|
|
||||||
return number.toFixed(2);
|
return number.toFixed(2);
|
||||||
}
|
}
|
||||||
getFirstMatchScore (tags) {
|
|
||||||
|
getFirstMatchScore(tags) {
|
||||||
let matchFound = false;
|
let matchFound = false;
|
||||||
let match = "";
|
let match = "";
|
||||||
let i = 0;
|
let i = 0;
|
||||||
|
@ -113,11 +156,11 @@ class RuleSet {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
checkValues (tag) {
|
checkValues(tag) {
|
||||||
const [tagKey, tagValue] = tag;
|
const [tagKey, tagValue] = tag;
|
||||||
const options = Object.entries(this.scoreValues[1])
|
const options = Object.entries(this.scoreValues[1])
|
||||||
|
|
||||||
for (let option of options) {
|
for (let option of options) {
|
||||||
const [optKey, optValues] = option;
|
const [optKey, optValues] = option;
|
||||||
|
|
||||||
if (optKey === tagKey) {
|
if (optKey === tagKey) {
|
||||||
|
@ -127,48 +170,29 @@ class RuleSet {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
getMinValue (tags) {
|
getMinValue(tags, subprogram) {
|
||||||
const minArr = this.scoreValues.map(part => {
|
console.log("Running min with", tags, subprogram)
|
||||||
if (typeof(part) === 'object') {
|
const minArr = subprogram.map(part => {
|
||||||
return this.getMin(part, JSON.parse(tags))
|
if (typeof (part) === 'object') {
|
||||||
|
const calculatedValue = this.runProgram(tags, part)
|
||||||
|
return parseFloat(calculatedValue)
|
||||||
} else {
|
} else {
|
||||||
return parseInt(part);
|
return parseFloat(part);
|
||||||
}
|
}
|
||||||
});
|
}).filter(v => !isNaN(v));
|
||||||
let absMin = Math.min(...minArr);
|
return Math.min(...minArr);
|
||||||
return absMin;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getMin (part, tags) {
|
getMaxValue(tags, subprogram) {
|
||||||
let min;
|
const maxArr = subprogram.map(part => {
|
||||||
const [ group ] = Object.entries(part);
|
if (typeof (part) === 'object') {
|
||||||
const [,compareVals] = group;
|
return parseFloat(this.runProgram(tags, part))
|
||||||
const minArr = Object.values(compareVals).map(v => parseInt(v));
|
|
||||||
min = Math.min(...minArr);
|
|
||||||
return min;
|
|
||||||
}
|
|
||||||
|
|
||||||
getMaxValue (tags) {
|
|
||||||
const maxArr = this.scoreValues.map(part => {
|
|
||||||
if (typeof(part) === 'object') {
|
|
||||||
return this.getMax(part, JSON.parse(tags))
|
|
||||||
} else {
|
} else {
|
||||||
return parseInt(part);
|
return parseFloat(part);
|
||||||
}
|
}
|
||||||
});
|
}).filter(v => !isNaN(v));
|
||||||
let absMax = Math.max(...maxArr);
|
return Math.max(...maxArr);
|
||||||
return absMax;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getMax (part, tags) {
|
|
||||||
let max;
|
|
||||||
const [ group ] = Object.entries(part);
|
|
||||||
const [,compareVals] = group;
|
|
||||||
const maxArr = Object.values(compareVals).map(v => parseInt(v));
|
|
||||||
max = Math.max(...maxArr);
|
|
||||||
return max;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,7 @@ const app = {
|
||||||
* @param tags {any} OSM tags as key/value pairs
|
* @param tags {any} OSM tags as key/value pairs
|
||||||
*/
|
*/
|
||||||
interpret (definitionFile, tags) {
|
interpret (definitionFile, tags) {
|
||||||
|
tags = JSON.parse(tags)
|
||||||
const rawData = fs.readFileSync(definitionFile);
|
const rawData = fs.readFileSync(definitionFile);
|
||||||
const ruleSet = JSON.parse(rawData);
|
const ruleSet = JSON.parse(rawData);
|
||||||
const { name, $default, $multiply, $min, value} = ruleSet;
|
const { name, $default, $multiply, $min, value} = ruleSet;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue