forked from MapComplete/MapComplete
Further improvements to entrances theme, add layer-crossdependency detection, add layers which another layer depends on automatically to the theme, add documentation on which layers depends on which other layers, regenerate documentation
This commit is contained in:
parent
8e40d76281
commit
0ee23ce36d
27 changed files with 9032 additions and 331 deletions
111
Models/ThemeConfig/DependencyCalculator.ts
Normal file
111
Models/ThemeConfig/DependencyCalculator.ts
Normal file
|
@ -0,0 +1,111 @@
|
|||
import {SpecialVisualization} from "../../UI/SpecialVisualizations";
|
||||
import {SubstitutedTranslation} from "../../UI/SubstitutedTranslation";
|
||||
import TagRenderingConfig from "./TagRenderingConfig";
|
||||
import {ExtraFuncParams, ExtraFunctions} from "../../Logic/ExtraFunctions";
|
||||
import LayerConfig from "./LayerConfig";
|
||||
|
||||
export default class DependencyCalculator {
|
||||
|
||||
public static GetTagRenderingDependencies(tr: TagRenderingConfig): string[] {
|
||||
|
||||
if(tr === undefined){
|
||||
throw "Got undefined tag rendering in getTagRenderingDependencies"
|
||||
}
|
||||
const deps: string[] = []
|
||||
|
||||
// All translated snippets
|
||||
const parts: string[] = [].concat(...(tr.EnumerateTranslations().map(tr => tr.AllValues())))
|
||||
|
||||
for (const part of parts) {
|
||||
const specialVizs: { func: SpecialVisualization, args: string[] }[]
|
||||
= SubstitutedTranslation.ExtractSpecialComponents(part).map(o => o.special)
|
||||
.filter(o => o?.func?.getLayerDependencies !== undefined)
|
||||
for (const specialViz of specialVizs) {
|
||||
deps.push(...specialViz.func.getLayerDependencies(specialViz.args))
|
||||
}
|
||||
}
|
||||
return deps;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a set of all other layer-ids that this layer needs to function.
|
||||
* E.g. if this layers does snap to another layer in the preset, this other layer id will be mentioned
|
||||
*/
|
||||
public static getLayerDependencies(layer: LayerConfig): { neededLayer: string, reason: string, context?: string, neededBy: string }[] {
|
||||
const deps: { neededLayer: string, reason: string, context?: string, neededBy: string }[] = []
|
||||
|
||||
for (let i = 0; layer.presets !== undefined && i < layer.presets.length; i++) {
|
||||
const preset = layer.presets[i];
|
||||
preset.preciseInput?.snapToLayers?.forEach(id => {
|
||||
deps.push({
|
||||
neededLayer: id,
|
||||
reason: "a preset snaps to this layer",
|
||||
context: "presets[" + i + "]",
|
||||
neededBy: layer.id
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
for (const tr of layer.AllTagRenderings()) {
|
||||
for (const dep of DependencyCalculator.GetTagRenderingDependencies(tr)) {
|
||||
deps.push({
|
||||
neededLayer: dep,
|
||||
reason: "a tagrendering needs this layer",
|
||||
context: tr.id,
|
||||
neededBy: layer.id
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
if (layer.calculatedTags?.length > 0) {
|
||||
const obj = {
|
||||
type: "Feature",
|
||||
geometry: {
|
||||
type: "Point",
|
||||
coordinates: [0, 0]
|
||||
},
|
||||
properties: {
|
||||
id: "node/1"
|
||||
}
|
||||
}
|
||||
let currentKey = undefined
|
||||
let currentLine = undefined
|
||||
const params: ExtraFuncParams = {
|
||||
getFeaturesWithin: (layerId, _) => {
|
||||
|
||||
if(layerId === '*'){
|
||||
// This is a wildcard
|
||||
return []
|
||||
}
|
||||
|
||||
// The important line: steal the dependencies!
|
||||
deps.push({
|
||||
neededLayer: layerId, reason: "A calculated tag loads features from this layer",
|
||||
context: "calculatedTag[" + currentLine + "] which calculates the value for " + currentKey,
|
||||
neededBy: layer.id
|
||||
})
|
||||
|
||||
return []
|
||||
},
|
||||
memberships: undefined
|
||||
}
|
||||
// Init the extra patched functions...
|
||||
ExtraFunctions.FullPatchFeature(params, obj)
|
||||
// ... Run the calculated tag code, which will trigger the getFeaturesWithin above...
|
||||
for (let i = 0; i < layer.calculatedTags.length; i++) {
|
||||
const [key, code] = layer.calculatedTags[i];
|
||||
currentLine = i; // Leak the state...
|
||||
currentKey = key;
|
||||
try {
|
||||
|
||||
const func = new Function("feat", "return " + code + ";");
|
||||
const result = func(obj)
|
||||
obj.properties[key] = JSON.stringify(result);
|
||||
} catch (e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return deps
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue