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,28 +10,27 @@ import { AllKnownLayouts } from "../../src/Customizations/AllKnownLayouts"
|
|||
import { OsmObject } from "../../src/Logic/Osm/OsmObject"
|
||||
|
||||
class LuaSnippets {
|
||||
|
||||
public static helpers = [
|
||||
"function countTbl(tbl)\n" +
|
||||
" local c = 0\n" +
|
||||
" for n in pairs(tbl) do \n" +
|
||||
" c = c + 1 \n" +
|
||||
" end\n" +
|
||||
" return c\n" +
|
||||
"end",
|
||||
" local c = 0\n" +
|
||||
" for n in pairs(tbl) do \n" +
|
||||
" c = c + 1 \n" +
|
||||
" end\n" +
|
||||
" return c\n" +
|
||||
"end",
|
||||
].join("\n")
|
||||
|
||||
public static isPolygonFeature(): { blacklist: TagsFilter, whitelisted: TagsFilter } {
|
||||
public static isPolygonFeature(): { blacklist: TagsFilter; whitelisted: TagsFilter } {
|
||||
const dict = OsmObject.polygonFeatures
|
||||
const or: TagsFilter[] = []
|
||||
const blacklisted : TagsFilter[] = []
|
||||
const blacklisted: TagsFilter[] = []
|
||||
dict.forEach(({ values, blacklist }, k) => {
|
||||
if(blacklist){
|
||||
if(values === undefined){
|
||||
if (blacklist) {
|
||||
if (values === undefined) {
|
||||
blacklisted.push(new RegexTag(k, /.+/is))
|
||||
return
|
||||
}
|
||||
values.forEach(v => {
|
||||
values.forEach((v) => {
|
||||
blacklisted.push(new RegexTag(k, v))
|
||||
})
|
||||
return
|
||||
|
@ -40,11 +39,14 @@ class LuaSnippets {
|
|||
or.push(new RegexTag(k, /.+/is))
|
||||
return
|
||||
}
|
||||
values.forEach(v => {
|
||||
values.forEach((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) }
|
||||
}
|
||||
|
||||
|
@ -53,14 +55,14 @@ class LuaSnippets {
|
|||
return `object.tags["${tag.key}"] == "${tag.value}"`
|
||||
}
|
||||
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) {
|
||||
return "(" + expr + ")"
|
||||
}
|
||||
return expr
|
||||
}
|
||||
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) {
|
||||
return "(" + expr + ")"
|
||||
}
|
||||
|
@ -87,7 +89,7 @@ class LuaSnippets {
|
|||
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) {
|
||||
return `object.tags["${tag.key}"] ~= nil`
|
||||
|
@ -101,18 +103,35 @@ class LuaSnippets {
|
|||
return `object.tags["${tag.key}"] == nil or object.tags["${tag.key}"] == ""`
|
||||
}
|
||||
|
||||
|
||||
if (tag.matchesEmpty && tag.invert) {
|
||||
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) {
|
||||
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}"))`
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class GenerateLayerLua {
|
||||
|
@ -163,8 +182,6 @@ class GenerateLayerLua {
|
|||
"",
|
||||
].join("\n")
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
class GenerateBuildDbScript extends Script {
|
||||
|
@ -174,7 +191,7 @@ class GenerateBuildDbScript extends Script {
|
|||
|
||||
async main(args: string[]) {
|
||||
const allNeededLayers = new ValidateThemeEnsemble().convertStrict(
|
||||
AllKnownLayouts.allKnownLayouts.values(),
|
||||
AllKnownLayouts.allKnownLayouts.values()
|
||||
)
|
||||
|
||||
const generators: GenerateLayerLua[] = []
|
||||
|
@ -186,29 +203,30 @@ class GenerateBuildDbScript extends Script {
|
|||
const script = [
|
||||
"local db_tables = {}",
|
||||
LuaSnippets.helpers,
|
||||
...generators.map(g => g.generateTables()),
|
||||
...generators.map((g) => g.generateTables()),
|
||||
this.generateProcessPoi(allNeededLayers),
|
||||
this.generateProcessWay(allNeededLayers),
|
||||
].join("\n\n\n")
|
||||
const path = "build_db.lua"
|
||||
fs.writeFileSync(path, script, "utf-8")
|
||||
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() {
|
||||
return [" if countTbl(object.tags) == 0 then",
|
||||
" return",
|
||||
" end",
|
||||
""].join("\n")
|
||||
return [" if countTbl(object.tags) == 0 then", " 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[] = []
|
||||
allNeededLayers.forEach(({ tags }, layerId) => {
|
||||
body.push(
|
||||
this.insertInto(tags, layerId, "pois_").join("\n"),
|
||||
)
|
||||
body.push(this.insertInto(tags, layerId, "pois_").join("\n"))
|
||||
})
|
||||
|
||||
return [
|
||||
|
@ -228,7 +246,11 @@ class GenerateBuildDbScript extends Script {
|
|||
* @param tableprefix
|
||||
* @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)
|
||||
return [
|
||||
" matches_filter = " + filter,
|
||||
|
@ -265,8 +287,12 @@ class GenerateBuildDbScript extends Script {
|
|||
"",
|
||||
"function osm2pgsql.process_way(object)",
|
||||
this.earlyAbort(),
|
||||
" local object_is_line = not object.is_closed or "+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)}))`,
|
||||
" local object_is_line = not object.is_closed or " +
|
||||
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",
|
||||
" process_polygon(object, object:as_polygon())",
|
||||
" else",
|
||||
|
|
Loading…
Reference in a new issue