forked from MapComplete/MapComplete
Fix: improve optimization; add tests
This commit is contained in:
parent
78238dccc7
commit
595503cfc3
3 changed files with 47 additions and 8 deletions
|
@ -233,6 +233,15 @@ export class And extends TagsFilter {
|
|||
return And.construct(newAnds)
|
||||
}
|
||||
|
||||
/**
|
||||
* const raw = {"and": [{"or":["leisure=playground","playground!=forest"]},{"or":["leisure=playground","playground!=forest"]}]}
|
||||
* const parsed = TagUtils.Tag(raw)
|
||||
* parsed.optimize().asJson() // => {"or":["leisure=playground","playground!=forest"]}
|
||||
*
|
||||
* const raw = {"and": [{"and":["advertising=screen"]}, {"and":["advertising~*"]}]}]
|
||||
* const parsed = TagUtils.Tag(raw)
|
||||
* parsed.optimize().asJson() // => "advertising=screen"
|
||||
*/
|
||||
optimize(): TagsFilter | boolean {
|
||||
if (this.and.length === 0) {
|
||||
return true
|
||||
|
@ -294,9 +303,17 @@ export class And extends TagsFilter {
|
|||
optimized.splice(i, 1)
|
||||
i--
|
||||
}
|
||||
} else if (v !== opt.value) {
|
||||
// detected an internal conflict
|
||||
return false
|
||||
} else {
|
||||
if (!v.match(opt.value)) {
|
||||
// We _know_ that for the key of the RegexTag `opt`, the value will be `v`.
|
||||
// As such, if `opt.value` cannot match `v`, we detected an internal conflict and can fail
|
||||
|
||||
return false
|
||||
} else {
|
||||
// Another tag already provided a _stricter_ value then this regex, so we can remove this one!
|
||||
optimized.splice(i, 1)
|
||||
i--
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -374,10 +391,13 @@ export class And extends TagsFilter {
|
|||
const elements = containedOr.or.filter(
|
||||
(candidate) => !commonValues.some((cv) => cv.shadows(candidate))
|
||||
)
|
||||
newOrs.push(Or.construct(elements))
|
||||
if (elements.length > 0) {
|
||||
newOrs.push(Or.construct(elements))
|
||||
}
|
||||
}
|
||||
if (newOrs.length > 0) {
|
||||
commonValues.push(And.construct(newOrs))
|
||||
}
|
||||
|
||||
commonValues.push(And.construct(newOrs))
|
||||
const result = new Or(commonValues).optimize()
|
||||
if (result === false) {
|
||||
return false
|
||||
|
|
|
@ -162,6 +162,12 @@ export class Or extends TagsFilter {
|
|||
return Or.construct(newOrs)
|
||||
}
|
||||
|
||||
/**
|
||||
* const raw = {"or": [{"and":["leisure=playground","playground!=forest"]},{"and":["leisure=playground","playground!=forest"]}]}
|
||||
* const parsed = TagUtils.Tag(raw)
|
||||
* parsed.optimize().asJson() // => {"and":["leisure=playground","playground!=forest"]}
|
||||
*
|
||||
*/
|
||||
optimize(): TagsFilter | boolean {
|
||||
if (this.or.length === 0) {
|
||||
return false
|
||||
|
@ -241,16 +247,21 @@ export class Or extends TagsFilter {
|
|||
const elements = containedAnd.and.filter(
|
||||
(candidate) => !commonValues.some((cv) => cv.shadows(candidate))
|
||||
)
|
||||
if (elements.length == 0) {
|
||||
continue
|
||||
}
|
||||
newAnds.push(And.construct(elements))
|
||||
}
|
||||
if (newAnds.length > 0) {
|
||||
commonValues.push(Or.construct(newAnds))
|
||||
}
|
||||
|
||||
commonValues.push(Or.construct(newAnds))
|
||||
const result = new And(commonValues).optimize()
|
||||
if (result === true) {
|
||||
return true
|
||||
} else if (result === false) {
|
||||
// neutral element: skip
|
||||
} else {
|
||||
} else if (commonValues.length > 0) {
|
||||
newOrs.push(And.construct(commonValues))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -325,6 +325,14 @@ export class TagUtils {
|
|||
return tags
|
||||
}
|
||||
|
||||
static optimzeJson(json: TagConfigJson): TagConfigJson | boolean {
|
||||
const optimized = TagUtils.Tag(json).optimize()
|
||||
if (optimized === true || optimized === false) {
|
||||
return optimized
|
||||
}
|
||||
return optimized.asJson()
|
||||
}
|
||||
|
||||
/**
|
||||
* Given multiple tagsfilters which can be used as answer, will take the tags with the same keys together as set.
|
||||
*
|
||||
|
|
Loading…
Reference in a new issue