forked from MapComplete/MapComplete
Correctly handle non-working optional match groups in generate build_db script
This commit is contained in:
parent
760276922d
commit
b37ea885a5
1 changed files with 61 additions and 35 deletions
|
@ -10,7 +10,6 @@ import { AllKnownLayouts } from "../../src/Customizations/AllKnownLayouts"
|
||||||
import { OsmObject } from "../../src/Logic/Osm/OsmObject"
|
import { OsmObject } from "../../src/Logic/Osm/OsmObject"
|
||||||
|
|
||||||
class LuaSnippets {
|
class LuaSnippets {
|
||||||
|
|
||||||
public static helpers = [
|
public static helpers = [
|
||||||
"function countTbl(tbl)\n" +
|
"function countTbl(tbl)\n" +
|
||||||
" local c = 0\n" +
|
" local c = 0\n" +
|
||||||
|
@ -21,7 +20,7 @@ class LuaSnippets {
|
||||||
"end",
|
"end",
|
||||||
].join("\n")
|
].join("\n")
|
||||||
|
|
||||||
public static isPolygonFeature(): { blacklist: TagsFilter, whitelisted: TagsFilter } {
|
public static isPolygonFeature(): { blacklist: TagsFilter; whitelisted: TagsFilter } {
|
||||||
const dict = OsmObject.polygonFeatures
|
const dict = OsmObject.polygonFeatures
|
||||||
const or: TagsFilter[] = []
|
const or: TagsFilter[] = []
|
||||||
const blacklisted: TagsFilter[] = []
|
const blacklisted: TagsFilter[] = []
|
||||||
|
@ -31,7 +30,7 @@ class LuaSnippets {
|
||||||
blacklisted.push(new RegexTag(k, /.+/is))
|
blacklisted.push(new RegexTag(k, /.+/is))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
values.forEach(v => {
|
values.forEach((v) => {
|
||||||
blacklisted.push(new RegexTag(k, v))
|
blacklisted.push(new RegexTag(k, v))
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
|
@ -40,11 +39,14 @@ class LuaSnippets {
|
||||||
or.push(new RegexTag(k, /.+/is))
|
or.push(new RegexTag(k, /.+/is))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
values.forEach(v => {
|
values.forEach((v) => {
|
||||||
or.push(new RegexTag(k, v))
|
or.push(new RegexTag(k, v))
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
console.log("Polygon features are:", or.map(t => t.asHumanString(false, false, {})))
|
console.log(
|
||||||
|
"Polygon features are:",
|
||||||
|
or.map((t) => t.asHumanString(false, false, {}))
|
||||||
|
)
|
||||||
return { blacklist: new Or(blacklisted), whitelisted: new Or(or) }
|
return { blacklist: new Or(blacklisted), whitelisted: new Or(or) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,14 +55,14 @@ class LuaSnippets {
|
||||||
return `object.tags["${tag.key}"] == "${tag.value}"`
|
return `object.tags["${tag.key}"] == "${tag.value}"`
|
||||||
}
|
}
|
||||||
if (tag instanceof And) {
|
if (tag instanceof And) {
|
||||||
const expr = tag.and.map(t => this.toLuaFilter(t, true)).join(" and ")
|
const expr = tag.and.map((t) => this.toLuaFilter(t, true)).join(" and ")
|
||||||
if (useParens) {
|
if (useParens) {
|
||||||
return "(" + expr + ")"
|
return "(" + expr + ")"
|
||||||
}
|
}
|
||||||
return expr
|
return expr
|
||||||
}
|
}
|
||||||
if (tag instanceof Or) {
|
if (tag instanceof Or) {
|
||||||
const expr = tag.or.map(t => this.toLuaFilter(t, true)).join(" or ")
|
const expr = tag.or.map((t) => this.toLuaFilter(t, true)).join(" or ")
|
||||||
if (useParens) {
|
if (useParens) {
|
||||||
return "(" + expr + ")"
|
return "(" + expr + ")"
|
||||||
}
|
}
|
||||||
|
@ -87,7 +89,7 @@ class LuaSnippets {
|
||||||
return `object.tags["${tag.key}"] == "${tag.value}"`
|
return `object.tags["${tag.key}"] == "${tag.value}"`
|
||||||
}
|
}
|
||||||
|
|
||||||
const v = (<RegExp>tag.value).source.replace(/\\\//g, "/")
|
let v: string = (<RegExp>tag.value).source.replace(/\\\//g, "/")
|
||||||
|
|
||||||
if ("" + tag.value === "/.+/is" && !tag.invert) {
|
if ("" + tag.value === "/.+/is" && !tag.invert) {
|
||||||
return `object.tags["${tag.key}"] ~= nil`
|
return `object.tags["${tag.key}"] ~= nil`
|
||||||
|
@ -101,18 +103,35 @@ class LuaSnippets {
|
||||||
return `object.tags["${tag.key}"] == nil or object.tags["${tag.key}"] == ""`
|
return `object.tags["${tag.key}"] == nil or object.tags["${tag.key}"] == ""`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (tag.matchesEmpty && tag.invert) {
|
if (tag.matchesEmpty && tag.invert) {
|
||||||
return `object.tags["${tag.key}"] ~= nil or object.tags["${tag.key}"] ~= ""`
|
return `object.tags["${tag.key}"] ~= nil or object.tags["${tag.key}"] ~= ""`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let head = "^((.*;)?"
|
||||||
|
let tail = "(;.*)?)$"
|
||||||
|
if (v.startsWith(head)) {
|
||||||
|
v = "(" + v.substring(head.length)
|
||||||
|
}
|
||||||
|
if (v.endsWith(tail)) {
|
||||||
|
v = v.substring(0, v.length - tail.length) + ")"
|
||||||
|
// We basically remove the optional parts at the start and the end, as object.find has this freedom anyway.
|
||||||
|
// This might result in _some_ incorrect values that end up in the database (e.g. when matching 'friture', it might als match "abc;foo_friture_bar;xyz", but the frontend will filter this out
|
||||||
|
}
|
||||||
|
|
||||||
|
if (v.indexOf(")?") > 0) {
|
||||||
|
throw (
|
||||||
|
"LUA regexes have a bad support for (optional) capture groups, as such, " +
|
||||||
|
v +
|
||||||
|
" is not supported"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
if (tag.invert) {
|
if (tag.invert) {
|
||||||
return `object.tags["${tag.key}"] == nil or not string.find(object.tags["${tag.key}"], "${v}")`
|
return `object.tags["${tag.key}"] == nil or not string.find(object.tags["${tag.key}"], "${v}")`
|
||||||
}
|
}
|
||||||
|
|
||||||
return `(object.tags["${tag.key}"] ~= nil and string.find(object.tags["${tag.key}"], "${v}"))`
|
return `(object.tags["${tag.key}"] ~= nil and string.find(object.tags["${tag.key}"], "${v}"))`
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class GenerateLayerLua {
|
class GenerateLayerLua {
|
||||||
|
@ -163,8 +182,6 @@ class GenerateLayerLua {
|
||||||
"",
|
"",
|
||||||
].join("\n")
|
].join("\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class GenerateBuildDbScript extends Script {
|
class GenerateBuildDbScript extends Script {
|
||||||
|
@ -174,7 +191,7 @@ class GenerateBuildDbScript extends Script {
|
||||||
|
|
||||||
async main(args: string[]) {
|
async main(args: string[]) {
|
||||||
const allNeededLayers = new ValidateThemeEnsemble().convertStrict(
|
const allNeededLayers = new ValidateThemeEnsemble().convertStrict(
|
||||||
AllKnownLayouts.allKnownLayouts.values(),
|
AllKnownLayouts.allKnownLayouts.values()
|
||||||
)
|
)
|
||||||
|
|
||||||
const generators: GenerateLayerLua[] = []
|
const generators: GenerateLayerLua[] = []
|
||||||
|
@ -186,29 +203,30 @@ class GenerateBuildDbScript extends Script {
|
||||||
const script = [
|
const script = [
|
||||||
"local db_tables = {}",
|
"local db_tables = {}",
|
||||||
LuaSnippets.helpers,
|
LuaSnippets.helpers,
|
||||||
...generators.map(g => g.generateTables()),
|
...generators.map((g) => g.generateTables()),
|
||||||
this.generateProcessPoi(allNeededLayers),
|
this.generateProcessPoi(allNeededLayers),
|
||||||
this.generateProcessWay(allNeededLayers),
|
this.generateProcessWay(allNeededLayers),
|
||||||
].join("\n\n\n")
|
].join("\n\n\n")
|
||||||
const path = "build_db.lua"
|
const path = "build_db.lua"
|
||||||
fs.writeFileSync(path, script, "utf-8")
|
fs.writeFileSync(path, script, "utf-8")
|
||||||
console.log("Written", path)
|
console.log("Written", path)
|
||||||
console.log(allNeededLayers.size + " layers will be created with 3 tables each. Make sure to set 'max_connections' to at least " + (10 + 3 * allNeededLayers.size))
|
console.log(
|
||||||
|
allNeededLayers.size +
|
||||||
|
" layers will be created with 3 tables each. Make sure to set 'max_connections' to at least " +
|
||||||
|
(10 + 3 * allNeededLayers.size)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private earlyAbort() {
|
private earlyAbort() {
|
||||||
return [" if countTbl(object.tags) == 0 then",
|
return [" if countTbl(object.tags) == 0 then", " return", " end", ""].join("\n")
|
||||||
" return",
|
|
||||||
" end",
|
|
||||||
""].join("\n")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private generateProcessPoi(allNeededLayers: Map<string, { tags: TagsFilter; foundInTheme: string[] }>) {
|
private generateProcessPoi(
|
||||||
|
allNeededLayers: Map<string, { tags: TagsFilter; foundInTheme: string[] }>
|
||||||
|
) {
|
||||||
const body: string[] = []
|
const body: string[] = []
|
||||||
allNeededLayers.forEach(({ tags }, layerId) => {
|
allNeededLayers.forEach(({ tags }, layerId) => {
|
||||||
body.push(
|
body.push(this.insertInto(tags, layerId, "pois_").join("\n"))
|
||||||
this.insertInto(tags, layerId, "pois_").join("\n"),
|
|
||||||
)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
return [
|
return [
|
||||||
|
@ -228,7 +246,11 @@ class GenerateBuildDbScript extends Script {
|
||||||
* @param tableprefix
|
* @param tableprefix
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
private insertInto(tags: TagsFilter, layerId: string, tableprefix: "pois_" | "lines_" | "polygons_") {
|
private insertInto(
|
||||||
|
tags: TagsFilter,
|
||||||
|
layerId: string,
|
||||||
|
tableprefix: "pois_" | "lines_" | "polygons_"
|
||||||
|
) {
|
||||||
const filter = LuaSnippets.toLuaFilter(tags)
|
const filter = LuaSnippets.toLuaFilter(tags)
|
||||||
return [
|
return [
|
||||||
" matches_filter = " + filter,
|
" matches_filter = " + filter,
|
||||||
|
@ -265,8 +287,12 @@ class GenerateBuildDbScript extends Script {
|
||||||
"",
|
"",
|
||||||
"function osm2pgsql.process_way(object)",
|
"function osm2pgsql.process_way(object)",
|
||||||
this.earlyAbort(),
|
this.earlyAbort(),
|
||||||
" local object_is_line = not object.is_closed or "+LuaSnippets.toLuaFilter(isPolygon.blacklist),
|
" local object_is_line = not object.is_closed or " +
|
||||||
` local object_is_area = object.is_closed and (object.tags["area"] == "yes" or (not object_is_line and ${LuaSnippets.toLuaFilter(isPolygon.whitelisted, true)}))`,
|
LuaSnippets.toLuaFilter(isPolygon.blacklist),
|
||||||
|
` local object_is_area = object.is_closed and (object.tags["area"] == "yes" or (not object_is_line and ${LuaSnippets.toLuaFilter(
|
||||||
|
isPolygon.whitelisted,
|
||||||
|
true
|
||||||
|
)}))`,
|
||||||
" if object_is_area then",
|
" if object_is_area then",
|
||||||
" process_polygon(object, object:as_polygon())",
|
" process_polygon(object, object:as_polygon())",
|
||||||
" else",
|
" else",
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue