Refactoring of the climbing theme

This commit is contained in:
pietervdvn 2022-04-23 15:20:54 +02:00
parent c36bce8100
commit bc953abe48
15 changed files with 1099 additions and 1001 deletions

View file

@ -330,12 +330,19 @@ class AddDependencyLayersToTheme extends DesugaringStep<LayoutConfigJson> {
private readonly _state: DesugaringContext;
constructor(state: DesugaringContext,) {
super("If a layer has a dependency on another layer, these layers are added automatically on the theme. (For example: defibrillator depends on 'walls_and_buildings' to snap onto. This layer is added automatically)", ["layers"], "AddDependencyLayersToTheme");
super(
`If a layer has a dependency on another layer, these layers are added automatically on the theme. (For example: defibrillator depends on 'walls_and_buildings' to snap onto. This layer is added automatically)
Note that these layers are added _at the start_ of the layer list, meaning that they will see _every_ feature.
Furthermore, \`passAllFeatures\` will be set, so that they won't steal away features from further layers.
Some layers (e.g. \`all_buildings_and_walls\' or \'streets_with_a_name\') are invisible, so by default, \'force_load\' is set too.
`, ["layers"], "AddDependencyLayersToTheme");
this._state = state;
}
private static CalculateDependencies(alreadyLoaded: LayerConfigJson[], allKnownLayers: Map<string, LayerConfigJson>, themeId: string): LayerConfigJson[] {
const dependenciesToAdd: LayerConfigJson[] = []
private static CalculateDependencies(alreadyLoaded: LayerConfigJson[], allKnownLayers: Map<string, LayerConfigJson>, themeId: string):
{config: LayerConfigJson, reason: string}[] {
const dependenciesToAdd: {config: LayerConfigJson, reason: string}[] = []
const loadedLayerIds: Set<string> = new Set<string>(alreadyLoaded.map(l => l.id));
// Verify cross-dependencies
@ -361,35 +368,39 @@ class AddDependencyLayersToTheme extends DesugaringStep<LayoutConfigJson> {
}
// During the generate script, builtin layers are verified but not loaded - so we have to add them manually here
// Their existance is checked elsewhere, so this is fine
// Their existence is checked elsewhere, so this is fine
unmetDependencies = dependencies.filter(dep => !loadedLayerIds.has(dep.neededLayer))
for (const unmetDependency of unmetDependencies) {
if (loadedLayerIds.has(unmetDependency.neededLayer)) {
continue
}
const dep = allKnownLayers.get(unmetDependency.neededLayer)
const dep = Utils.Clone(allKnownLayers.get(unmetDependency.neededLayer))
const reason = "This layer is needed by " + unmetDependency.neededBy +" because " +
unmetDependency.reason + " (at " + unmetDependency.context + ")";
if (dep === undefined) {
const message =
["Loading a dependency failed: layer " + unmetDependency.neededLayer + " is not found, neither as layer of " + themeId + " nor as builtin layer.",
"This layer is needed by " + unmetDependency.neededBy,
unmetDependency.reason + " (at " + unmetDependency.context + ")",
reason,
"Loaded layers are: " + alreadyLoaded.map(l => l.id).join(",")
]
throw message.join("\n\t");
}
dependenciesToAdd.unshift(dep)
dep.forceLoad = true;
dep.passAllFeatures = true;
dep.description = reason;
dependenciesToAdd.unshift({
config: dep,
reason
})
loadedLayerIds.add(dep.id);
unmetDependencies = unmetDependencies.filter(d => d.neededLayer !== unmetDependency.neededLayer)
}
} while (unmetDependencies.length > 0)
return dependenciesToAdd.map(dep => {
dep = Utils.Clone(dep);
dep.forceLoad = true
return dep
});
return dependenciesToAdd
}
convert(theme: LayoutConfigJson, context: string): { result: LayoutConfigJson; information: string[] } {
@ -404,11 +415,16 @@ class AddDependencyLayersToTheme extends DesugaringStep<LayoutConfigJson> {
})
const dependencies = AddDependencyLayersToTheme.CalculateDependencies(layers, allKnownLayers, theme.id);
if (dependencies.length > 0) {
information.push(context + ": added " + dependencies.map(d => d.id).join(", ") + " to the theme as they are needed")
for (const dependency of dependencies) {
}
layers.unshift(...dependencies);
if (dependencies.length > 0) {
for (const dependency of dependencies) {
information.push(context + ": added " + dependency.config.id + " to the theme. "+dependency.reason)
}
}
layers.unshift(...dependencies.map(l => l.config));
return {
result: {

View file

@ -81,7 +81,7 @@ export default class DependencyCalculator {
// The important line: steal the dependencies!
deps.push({
neededLayer: layerId, reason: "A calculated tag loads features from this layer",
neededLayer: layerId, reason: "a calculated tag loads features from this layer",
context: "calculatedTag[" + currentLine + "] which calculates the value for " + currentKey,
neededBy: layer.id
})

View file

@ -161,7 +161,11 @@ export default class LayerConfig extends WithContextLoader {
this.calculatedTags = [];
for (const kv of json.calculatedTags) {
const index = kv.indexOf("=");
let key = kv.substring(0, index);
let key = kv.substring(0, index).trim();
const r = "[a-z_][a-z0-9:]*"
if(key.match(r) === null){
throw "At "+context+" invalid key for calculated tag: "+key+"; it should match "+r
}
const isStrict = key.endsWith(':')
if (isStrict) {
key = key.substr(0, key.length - 1)

View file

@ -20,6 +20,7 @@ import {QueryParameters} from "../../Logic/Web/QueryParameters";
import {TagUtils} from "../../Logic/Tags/TagUtils";
import {InputElement} from "../Input/InputElement";
import {DropDown} from "../Input/DropDown";
import {UIElement} from "../UIElement";
export default class FilterView extends VariableUiElement {
constructor(filteredLayer: UIEventSource<FilteredLayer[]>,
@ -33,7 +34,7 @@ export default class FilterView extends VariableUiElement {
filteredLayer.map((filteredLayers) => {
// Create the views which toggle layers (and filters them) ...
let elements = filteredLayers
?.map(l => FilterView.createOneFilteredLayerElement(l)?.SetClass("filter-panel"))
?.map(l => FilterView.createOneFilteredLayerElement(l, State.state)?.SetClass("filter-panel"))
?.filter(l => l !== undefined)
elements[0].SetClass("first-filter-panel")
@ -87,10 +88,14 @@ export default class FilterView extends VariableUiElement {
);
}
private static createOneFilteredLayerElement(filteredLayer: FilteredLayer) {
private static createOneFilteredLayerElement(filteredLayer: FilteredLayer, state: {featureSwitchIsDebugging: UIEventSource<boolean>}) {
if (filteredLayer.layerDef.name === undefined) {
// Name is not defined: we hide this one
return undefined;
return new Toggle(
filteredLayer.layerDef.description.Clone().SetClass("subtle") ,
undefined,
state.featureSwitchIsDebugging
);
}
const iconStyle = "width:1.5rem;height:1.5rem;margin-left:1.25rem;flex-shrink: 0;";

View file

@ -85,6 +85,10 @@ export class AllTagsPanel extends VariableUiElement {
if (value === undefined) {
continue
}
let type = "";
if(typeof value !== "string"){
type = " <i>"+(typeof value)+"</i>"
}
parts.push(["<i>" + key + "</i>", value])
}

View file

@ -1,300 +1,375 @@
{
"id": "climbing",
"name": {
"nl": "Klimgelegenheden",
"de": "Klettermöglichkeiten",
"en": "Climbing opportunities",
"ja": "登坂教室",
"fr": "Opportunité descalade",
"it": "Opportunità di arrampicata"
},
"minzoom": 10,
"source": {
"osmTags": {
"and": [
"sport=climbing",
"climbing!~route",
"leisure!~sports_centre",
"climbing!=route_top",
"climbing!=route_bottom"
]
}
},
"title": {
"render": {
"en": "Climbing opportunity",
"nl": "Klimgelegenheid",
"de": "Klettermöglichkeit",
"ja": "登坂教室",
"nb_NO": "Klatremulighet",
"fr": "Opportunité descalade",
"it": "Opportunità di arrampicata"
},
"mappings": [
{
"if": "climbing=crag",
"then": {
"en": "Climbing crag <b>{name}</b>",
"fr": "Mur descalade <b>{name}</b>",
"it": "Muro da arrampicata <b>{name}</b>",
"de": "Klettergarten <b>{name}</b>"
}
},
{
"if": {
"and": [
{
"or": [
"climbing=area",
"climbing=site"
]
},
"name~*"
]
},
"then": {
"en": "Climbing area <b>{name}</b>",
"nl": "Klimsite <b>{name}</b>",
"fr": "Zone descalade <b>{name}</b>",
"de": "Klettergebiet <b>{name}</b>",
"it": "Area di arrampicata <b>{name}</b>"
}
},
{
"if": {
"or": [
"climbing=site",
"climbing=area"
]
},
"then": {
"en": "Climbing site",
"nl": "Klimsite",
"fr": "Site descalade",
"de": "Klettergebiet",
"it": "Sito di arrampicata",
"ca": "Llocs d'escalada"
}
},
{
"if": "name~*",
"then": {
"nl": "Klimgelegenheid <b>{name}</b>",
"en": "Climbing opportunity <b>{name}</b>",
"fr": "Opportunité descalade <b>{name}</b>",
"de": "Klettermöglichkeit <b>{name}</b>",
"it": "Opportunità di arrampicata <b>{name}</b>"
}
}
]
},
"title": null,
"description": {
"nl": "Een klimgelegenheid",
"de": "Eine Klettergelegenheit",
"en": "A climbing opportunity",
"ja": "登坂教室",
"nb_NO": "En klatremulighet",
"fr": "Opportunité descalade",
"it": "Unopportunità di arrampicata"
"en": "A dummy layer which contains tagrenderings, shared among the climbing layers"
},
"minzoom": 25,
"source": {
"osmTags": "sport=climbing"
},
"tagRenderings": [
"images",
{
"id": "minimap",
"render": "{minimap(18, id, _contained_climbing_route_ids): height: 9rem; overflow: hidden; border-radius:3rem; }"
},
{
"render": {
"en": "<h3>Length overview</h3>{histogram(_length_hist)}",
"fr": "<h3>Résumé de longueur</h3>{histogram(_length_hist)}",
"de": "<h3>Längenübersicht</h3>{histogram(_length_hist)}",
"it": "<h3>Riassunto della lunghezza</h3>{histogram(_length_hist)}"
"id": "website",
"question": {
"en": "Is there a (unofficial) website with more informations (e.g. topos)?",
"de": "Gibt es eine (inoffizielle) Website mit mehr Informationen (z.B. Topos)?",
"ja": "もっと情報のある(非公式の)ウェブサイトはありますか(例えば、topos)?",
"nl": "Is er een (onofficiële) website met meer informatie (b.v. met topos)?",
"ru": "Есть ли (неофициальный) веб-сайт с более подробной информацией (напр., topos)?",
"fr": "Existe-til un site avec plus dinformations (ex : topographie) ?",
"it": "Cè un sito web (anche non ufficiale) con qualche informazione in più (ad es. topografie)?"
},
"condition": "_length_hist!~\\[\\]",
"id": "Contained routes length hist"
},
{
"render": {
"en": "<h3>Grades overview</h3>{histogram(_difficulty_hist)}",
"fr": "<h3>Résumé des difficultés</h3>{histogram(_difficulty_hist)}",
"de": "<h3>Schwierigkeitsübersicht</h3>{histogram(_difficulty_hist)}",
"it": "<h3>Riassunto delle difficoltà</h3>{histogram(_difficulty_hist)}"
"condition": {
"and": [
"leisure!~sports_centre",
"sport=climbing",
"office=",
"club="
]
},
"condition": "_difficulty_hist!~\\[\\]",
"id": "Contained routes hist"
"render": "<a href='{url}' target='_blank'>{url}</a>",
"freeform": {
"key": "url",
"type": "url"
}
},
{
"id": "average_length",
"render": {
"en": "<h3>Contains {_contained_climbing_routes_count} routes</h3> <ul>{_contained_climbing_routes}</ul>",
"fr": "<h3>Contient {_contained_climbing_routes_count} voies</h3> <ul>{_contained_climbing_routes}</ul>",
"it": "<h3>Contiene {_contained_climbing_routes_count} vie</h3> <ul>{_contained_climbing_routes}</ul>",
"de": "<h3> Enthält {_contained_climbing_routes_count} Routen</h3> <ul>{_contained_climbing_routes}</ul>"
},
"condition": "_contained_climbing_routes~*",
"id": "Contained_climbing_routes"
},
{
"render": {
"en": "<strong>{name}</strong>",
"nl": "<strong>{name}</strong>",
"de": "<strong>{name}</strong>",
"ca": "<strong>{name}</strong>",
"fr": "<strong>{name}</strong>",
"id": "<strong>{name}</strong>",
"ru": "<strong>{name}</strong>",
"ja": "<strong>{name}</strong>",
"it": "<strong>{name}</strong>"
"de": "Die Routen sind durchschnittlich <b>{canonical(climbing:length)}</b> lang",
"en": "The routes are <b>{canonical(climbing:length)}</b> long on average",
"nl": "De klimroutes zijn gemiddeld <b>{canonical(climbing:length)}</b> lang",
"ja": "ルートの長さは平均で<b>{canonical(climbing:length)}</b>です",
"fr": "Les voies font <b>{canonical(climbing:length)}</b> de long en moyenne",
"it": "Le vie sono lunghe mediamente <b>{canonical(climbing:length)}</b>"
},
"question": {
"en": "What is the name of this climbing opportunity?",
"nl": "Wat is de naam van dit Klimgelegenheid?",
"de": "Wie heißt diese Klettergelegenheit?",
"ja": "この登坂教室の名前は何ですか?",
"fr": "Quel est le nom de ce site ?",
"it": "Qual è il nome di questa opportunità di arrampicata?"
"de": "Wie lang sind die Routen (durchschnittlich) in Metern?",
"en": "What is the (average) length of the routes in meters?",
"nl": "Wat is de (gemiddelde) lengte van de klimroutes, in meter?",
"ja": "ルートの(平均)長さはメートル単位でいくつですか?",
"fr": "Quelle est la longueur moyenne des voies en mètres ?",
"it": "Quale è la lunghezza (media) delle vie in metri?"
},
"freeform": {
"key": "name"
"key": "climbing:length",
"type": "pfloat"
}
},
{
"id": "min_difficulty",
"question": {
"de": "Welche Schwierigkeit hat hier die leichteste Route (französisch/belgisches System)?",
"en": "What is the grade of the easiest route here, according to the french classification system?",
"nl": "Wat is het niveau van de makkelijkste route, volgens het Franse classificatiesysteem?",
"ja": "ここで一番簡単なルートのレベルは、フランスのランク評価システムで何ですか?",
"fr": "Quel est le niveau de la voie la plus simple selon la classification franco-belge ?",
"it": "Qual è il livello della via più facile qua, secondo il sistema di classificazione francese?"
},
"render": {
"de": "Die leichteste Route hat hier die Schwierigkeit {climbing:grade:french:min} (französisch/belgisches System)",
"en": "The lowest grade is {climbing:grade:french:min} according to the french/belgian system",
"nl": "De minimale klimmoeilijkheid is {climbing:grade:french:min} volgens het Franse/Belgische systeem",
"ja": "フランス/ベルギーのランク評価システムでは、最小の難易度は{climbing:grade:french:min}です",
"fr": "La difficulté minimale est {climbing:grade:french:min} selon la classification franco-belge",
"it": "Il minimo livello di difficoltà è {climbing:grade:french:min} secondo il sistema francese/belga"
},
"freeform": {
"key": "climbing:grade:french:min"
}
},
{
"id": "max_difficulty",
"question": {
"de": "Welche Schwierigkeit hat hier die schwerste Route (französisch/belgisches System)?",
"en": "What is the highest grade route here, according to the french classification system?",
"nl": "Wat is het niveau van de moeilijkste route, volgens het Franse classificatiesysteem?",
"ja": "フランスのランク評価によると、ここで一番難しいルートのレベルはどれくらいですか?",
"fr": "Quel est le niveau de la voie la plus difficile selon la classification franco-belge ?",
"it": "Qual è il livello della via più difficile qua, secondo il sistema di classificazione francese?"
},
"render": {
"de": "Die schwierigste Route hat hier die Schwierigkeitsstufe {climbing:grade:french:max} (französisch/belgisches System)",
"en": "The highest grade is {climbing:grade:french:max} according to the french/belgian system",
"nl": "De maximale klimmoeilijkheid is {climbing:grade:french:max} volgens het Franse/Belgische systeem",
"ja": "フランス/ベルギーのランク評価システムでは、最大の難易度は{climbing:grade:french:max}です",
"fr": "La difficulté maximale est {climbing:grade:french:max} selon la classification franco-belge",
"it": "Il massimo livello di difficoltà è {climbing:grade:french:max} secondo il sistema francese/belga"
},
"freeform": {
"key": "climbing:grade:french:max"
},
"condition": {
"and": [
"climbing!~route",
"office=",
"club=",
{
"or": [
"climbing:sport=yes",
"sport=climbing"
]
}
]
}
},
{
"id": "bouldering",
"question": {
"de": "Kann hier gebouldert werden?",
"en": "Is bouldering possible here?",
"nl": "Is het mogelijk om hier te bolderen?",
"ja": "ここでボルダリングはできますか?",
"nb_NO": "Er buldring mulig her?",
"fr": "Lescalade de bloc est-elle possible ici ?",
"it": "È possibile praticare bouldering qua?"
},
"mappings": [
{
"if": "climbing:boulder=yes",
"then": {
"de": "Hier kann gebouldert werden",
"en": "Bouldering is possible here",
"nl": "Bolderen kan hier",
"ja": "ボルダリングはここで可能です",
"nb_NO": "Buldring er mulig her",
"fr": "Lescalade de bloc est possible",
"it": "Larrampicata su massi è possibile qua"
}
},
{
"if": "climbing:boulder=no",
"then": {
"de": "Hier kann nicht gebouldert werden",
"en": "Bouldering is not possible here",
"nl": "Bolderen kan hier niet",
"ja": "ここではボルダリングはできません",
"nb_NO": "Buldring er ikke mulig her",
"fr": "Lescalade de bloc nest pas possible",
"it": "Larrampicata su massi non è possibile qua"
}
},
{
"if": "climbing:boulder=limited",
"then": {
"de": "Bouldern ist hier nur an wenigen Routen möglich",
"en": "Bouldering is possible, allthough there are only a few routes",
"nl": "Bolderen kan hier, maar er zijn niet zoveel routes",
"ja": "ボルダリングは可能ですが、少しのルートしかありません",
"fr": "Lescalade de bloc est possible sur des voies précises",
"it": "Larrampicata su massi è possibile anche se su poche vie"
}
},
{
"if": "climbing:boulder~*",
"then": {
"de": "Hier gibt es {climbing:boulder} Boulder-Routen",
"en": "There are {climbing:boulder} boulder routes",
"nl": "Er zijn hier {climbing:boulder} bolderroutes",
"ja": "{climbing:boulder} ボルダールートがある",
"fr": "Il y a {climbing:boulder} voies descalade de bloc",
"it": "Sono presenti {climbing:boulder} vie di arrampicata su massi"
},
"hideInAnswer": true
}
]
},
{
"id": "toprope",
"question": {
"de": "Ist Toprope-Klettern hier möglich?",
"en": "Is toprope climbing possible here?",
"nl": "Is het mogelijk om hier te toprope-klimmen?",
"ja": "ここでtoprope登坂はできますか?",
"fr": "Est-il possible descalader à la moulinette ?",
"it": "È possibile arrampicarsi con la corda dallalto qua?"
},
"mappings": [
{
"if": "climbing:toprope=yes",
"then": {
"de": "Toprope-Klettern ist hier möglich",
"en": "Toprope climbing is possible here",
"nl": "Toprope-klimmen kan hier",
"ja": "ここでToprope登坂ができます",
"fr": "Lescalade à la moulinette est possible",
"it": "È possibile arrampicarsi con moulinette qua"
}
},
{
"if": "climbing:toprope=no",
"then": {
"de": "Toprope-Climbing ist hier nicht möglich",
"en": "Toprope climbing is not possible here",
"nl": "Toprope-klimmen kan hier niet",
"ja": "ここではToprope登坂はできません",
"fr": "Lescalade à la moulinette nest pas possible",
"it": "Non è possibile arrampicarsi con moulinette qua"
}
},
{
"if": "climbing:toprope~*",
"then": {
"de": "Hier gibt es {climbing:toprope} Toprope-Routen",
"en": "There are {climbing:toprope} toprope routes",
"nl": "Er zijn hier {climbing:toprope} toprope routes",
"ja": "{climbing:toprope} 登坂ルートがある",
"fr": "{climbing:toprope} voies sont équipées de moulinettes",
"it": "Sono presenti {climbing:toprope} vie con moulinette"
},
"hideInAnswer": true
}
]
},
{
"id": "sportclimbing",
"question": {
"de": "Ist hier Sportklettern möglich (feste Ankerpunkte)?",
"en": "Is sport climbing possible here on fixed anchors?",
"nl": "Is het mogelijk om hier te sportklimmen/voorklimmen op reeds aangebrachte haken?",
"ja": "ここでは固定アンカー式のスポーツクライミングはできますか?",
"it": "È possibile arrampicarsi qua con ancoraggi fissi?"
},
"mappings": [
{
"if": "climbing:sport=yes",
"then": {
"de": "Sportklettern ist hier möglich",
"en": "Sport climbing is possible here",
"nl": "Sportklimmen/voorklimmen kan hier",
"ru": "Здесь можно заняться спортивным скалолазанием",
"ja": "ここでスポーツクライミングができます",
"it": "Larrampicata sportiva è possibile qua",
"hu": "Itt lehetőség van sportmászásra",
"fr": "De lescalade est possible ici"
}
},
{
"if": "climbing:sport=no",
"then": {
"de": "Sportklettern ist hier nicht möglich",
"en": "Sport climbing is not possible here",
"nl": "Sportklimmen/voorklimmen kan hier niet",
"ru": "Спортивное скалолазание здесь невозможно",
"ja": "ここではスポーツクライミングはできません",
"it": "Larrampicata sportiva non è possibile qua",
"hu": "Itt nincs lehetőség sportmászásra",
"fr": "Lescalade est impossible ici"
}
},
{
"if": "climbing:sport~*",
"then": {
"de": "Hier gibt es {climbing:sport} Sportkletter-Routen",
"en": "There are {climbing:sport} sport climbing routes",
"nl": "Er zijn hier {climbing:sport} sportklimroutes/voorklimroutes",
"ja": "スポーツクライミングの {climbing:sport} ルートがある",
"it": "Sono presenti {climbing:sport} vie di arrampicata sportiva"
},
"hideInAnswer": true
}
]
},
{
"id": "trad_climbing",
"question": {
"de": "Ist hier traditionelles Klettern möglich (eigene Sicherung z.B. mit Klemmkleilen)?",
"en": "Is traditional climbing possible here (using own gear e.g. chocks)?",
"nl": "Is het mogelijk om hier traditioneel te klimmen? <br/><span class='subtle'>(Dit is klimmen met klemblokjes en friends)</span>",
"ja": "伝統的な登山はここで可能ですか(例えば、チョックのような独自のギアを使用して)",
"it": "È possibile arrampicarsi in maniera tradizionale qua (usando attrezzi propri, ad es. dadi)?"
},
"mappings": [
{
"if": "climbing:traditional=yes",
"then": {
"de": "Traditionelles Klettern ist hier möglich",
"en": "Traditional climbing is possible here",
"nl": "Traditioneel klimmen kan hier",
"ja": "ここでは伝統的な登山が可能です",
"it": "Larrampicata tradizionale è possibile qua"
}
},
{
"if": "climbing:traditional=no",
"then": {
"de": "Traditionelles Klettern ist hier nicht möglich",
"en": "Traditional climbing is not possible here",
"nl": "Traditioneel klimmen kan hier niet",
"ja": "伝統的な登山はここではできない",
"it": "Larrampicata tradizionale non è possibile qua"
}
},
{
"if": "climbing:traditional~*",
"then": {
"de": "Hier gibt es {climbing:traditional} Routen für traditionelles Klettern",
"en": "There are {climbing:traditional} traditional climbing routes",
"nl": "Er zijn hier {climbing:traditional} traditionele klimroutes",
"ja": "{climbing:traditional} の伝統的な登山ルートがある",
"it": "Sono presenti {climbing:traditional} vie di arrampicata tradizionale"
},
"hideInAnswer": true
}
]
},
{
"id": "max_bolts",
"question": {
"en": "How many bolts do routes in {title()} have at most?"
},
"render": {
"en": "The sport climbing routes here have at most {climbing:bolts:max} bolts.<div class='subtle'>This is without relays and indicates how much quickdraws a climber needs</div>"
},
"freeform": {
"key": "climbing:bolts:max",
"type": "pnat",
"addExtraTag": [
"climbing:sport=yes"
],
"inline": true
}
},
{
"id": "fee",
"question": {
"en": "Is a fee required to climb here?"
},
"render": {
"en": "A fee of {charge} should be paid for climbing here"
},
"freeform": {
"key": "charge",
"addExtraTags": [
"fee=yes"
],
"inline": true
},
"mappings": [
{
"if": "fee=no",
"addExtraTags": [
"charge="
],
"then": {
"en": "Climbing here is free of charge"
}
},
{
"if": {
"and": [
"noname=yes",
"name="
"fee=yes",
"charge="
]
},
"then": {
"en": "This climbing opportunity doesn't have a name",
"nl": "Dit Klimgelegenheid heeft geen naam",
"de": "Diese Klettergelegenheit hat keinen Namen",
"ja": "この登坂教室には名前がついていない",
"fr": "Ce site na pas de nom",
"it": "Questa opportunità di arrampicata non ha un nome"
}
"en": "Paying a fee is required to climb here"
},
"hideInAnswer": "charge~*"
}
],
"id": "name"
},
{
"question": "What kind of climbing opportunity is this?",
"mappings": [
{
"if": "climbing=boulder",
"then": {
"en": "A climbing boulder - a single rock or cliff with one or a few climbing routes which can be climbed safely without rope",
"fr": "Rocher descalade, rocher avec une ou peu de voie permettant descalader sans corde",
"de": "Ein Kletterfelsen - ein einzelner Felsen oder eine Klippe mit einer oder wenigen Kletterrouten, die ohne Seil sicher bestiegen werden können",
"it": "Un masso per arrampicata (una singola roccia o falesia con una o poche vie di arrampicata che possono essere scalate in sicurezza senza una corda)"
}
},
{
"if": "climbing=crag",
"then": {
"en": "A climbing crag - a single rock or cliff with at least a few climbing routes",
"fr": "Mur descalade, rocher avec plusieurs voies descalades",
"it": "Un muro da arrampicata (un singolo masso o falesia con almeno qualche via per arrampicata)",
"de": "Ein Kletterfelsen - ein einzelner Fels oder eine Klippe mit mindestens einigen Kletterrouten"
}
},
{
"if": "climbing=area",
"then": "A climbing area with one or more climbing crags and/or boulders"
}
],
"id": "Type"
},
{
"question": {
"en": "What is the rock type here?",
"fr": "Quel est le type de roche ?",
"de": "Welchen Gesteinstyp gibt es hier?",
"it": "Qual è il tipo di roccia qua?"
},
"render": {
"en": "The rock type is {rock}",
"fr": "La roche est du {rock}",
"de": "Der Gesteinstyp ist {rock}",
"it": "Il tipo di roccia è {rock}"
},
"freeform": {
"key": "rock"
},
"mappings": [
{
"if": "rock=limestone",
"then": {
"en": "Limestone",
"nl": "Kalksteen",
"fr": "Calcaire",
"de": "Kalkstein",
"it": "Calcare"
}
}
],
"condition": {
"or": [
"climbing=crag",
"natural=cliff",
"natural=bare_rock"
]
},
"id": "Rock type (crag/rock/cliff only)"
}
],
"presets": [
{
"tags": [
"sport=climbing"
],
"title": {
"en": "a climbing opportunity",
"nl": "een klimgelegenheid",
"de": "eine klettermöglichkeit",
"ja": "登坂教室",
"nb_NO": "en klatremulighet",
"fr": "une opportunité descalade",
"it": "una opportunità di arrampicata"
},
"description": {
"nl": "Een klimgelegenheid",
"de": "Eine Klettergelegenheit",
"en": "A climbing opportunity",
"ja": "登坂教室",
"nb_NO": "En klatremulighet",
"fr": "Opportunité descalade",
"it": "Unopportunità di arrampicata"
}
}
],
"calculatedTags": [
"_contained_climbing_routes_properties=feat.overlapWith('climbing_route').map(f => f.feat.properties).map(p => {return {id: p.id, name: p.name, 'climbing:grade:french': p['climbing:grade:french'], 'climbing:length': p['climbing:length']} })",
"_contained_climbing_routes=JSON.parse(feat.properties._contained_climbing_routes_properties ?? '[]').map(p => `<li><a href='#${p.id}'>${p.name ?? 'climbing route'}</a> (<b>${p['climbing:grade:french'] ?? 'unknown difficulty'}</b>, ${p['climbing:length'] ?? 'unkown length'} meter)</li>`).join('')",
"_contained_climbing_route_ids=JSON.parse(feat.properties._contained_climbing_routes_properties ?? '[]').map(p => p.id)",
"_difficulty_hist=JSON.parse(feat.properties._contained_climbing_routes_properties ?? '[]').map(p => p['climbing:grade:french'])",
"_length_hist=JSON.parse(feat.properties._contained_climbing_routes_properties ?? '[]').map(p => p['climbing:length'])",
"_contained_climbing_routes_count=JSON.parse(feat.properties._contained_climbing_routes_properties ?? '[]').length"
],
"mapRendering": [
{
"icon": {
"render": "./assets/themes/climbing/climbing_no_rope.svg"
},
"iconSize": {
"render": "40,40,center"
},
"location": [
"point",
"centroid"
]
},
{
"color": {
"render": "#d38d5fAA"
},
"width": {
"render": "8"
}
}
]
],
"mapRendering": null
}

View file

@ -0,0 +1,308 @@
{
"id": "climbing_area",
"name": {
"nl": "Klimgelegenheden",
"de": "Klettermöglichkeiten",
"en": "Climbing opportunities",
"ja": "登坂教室",
"fr": "Opportunité descalade",
"it": "Opportunità di arrampicata"
},
"description": {
"en": "An area where climbing is possible, e.g. a crag, site, boulder, ... Contains aggregation of routes"
},
"minzoom": 10,
"source": {
"osmTags": {
"and": [
"sport=climbing",
"climbing!~route",
"leisure!~sports_centre",
"climbing!=route_top",
"climbing!=route_bottom"
]
}
},
"title": {
"render": {
"en": "Climbing opportunity",
"nl": "Klimgelegenheid",
"de": "Klettermöglichkeit",
"ja": "登坂教室",
"nb_NO": "Klatremulighet",
"fr": "Opportunité descalade",
"it": "Opportunità di arrampicata"
},
"mappings": [
{
"if": "climbing=crag",
"then": {
"en": "Climbing crag <b>{name}</b>",
"fr": "Mur descalade <b>{name}</b>",
"it": "Muro da arrampicata <b>{name}</b>",
"de": "Klettergarten <b>{name}</b>"
}
},
{
"if": {
"and": [
{
"or": [
"climbing=area",
"climbing=site"
]
},
"name~*"
]
},
"then": {
"en": "Climbing area <b>{name}</b>",
"nl": "Klimsite <b>{name}</b>",
"fr": "Zone descalade <b>{name}</b>",
"de": "Klettergebiet <b>{name}</b>",
"it": "Area di arrampicata <b>{name}</b>"
}
},
{
"if": {
"or": [
"climbing=site",
"climbing=area"
]
},
"then": {
"en": "Climbing site",
"nl": "Klimsite",
"fr": "Site descalade",
"de": "Klettergebiet",
"it": "Sito di arrampicata",
"ca": "Llocs d'escalada"
}
},
{
"if": "name~*",
"then": {
"nl": "Klimgelegenheid <b>{name}</b>",
"en": "Climbing opportunity <b>{name}</b>",
"fr": "Opportunité descalade <b>{name}</b>",
"de": "Klettermöglichkeit <b>{name}</b>",
"it": "Opportunità di arrampicata <b>{name}</b>"
}
}
]
},
"calculatedTags": [
"_contained_climbing_routes_properties=feat.overlapWith('climbing_route').map(f => f.feat.properties).map(p => {return {id: p.id, name: p.name, 'climbing:grade:french': p['climbing:grade:french'], 'climbing:length': p['climbing:length']} })",
"_contained_climbing_routes=feat.get('_contained_climbing_routes_properties')?.map(p => `<li><a href='#${p.id}'>${p.name ?? 'climbing route'}</a> (<b>${p['climbing:grade:french'] ?? 'unknown difficulty'}</b>, ${p['climbing:length'] ?? 'unkown length'} meter)</li>`).join('')",
"_contained_climbing_route_ids=feat.get('_contained_climbing_routes_properties')?.map(p => p.id)",
"_difficulty_hist=feat.get('_contained_climbing_routes_properties')?.map(p => p['climbing:grade:french'])?.filter(p => (p ?? null) !== null)?.sort()",
"_difficulty_max=feat.get('_difficulty_hist')?.at(-1)",
"_difficulty_min=feat.get('_difficulty_hist')?.at(0)",
"_length_hist=feat.get('_contained_climbing_routes_properties')?.map(p => p['climbing:length'])?.filter(p => (p ?? null) !== null)?.sort()",
"_length_max=feat.get('_length_hist')?.at(-1)",
"_length_min=feat.get('_length_hist')?.at(0)",
"_bolts_hist=feat.get('_contained_climbing_routes_properties')?.map(p => p['climbing:bolts'])?.filter(p => (p ?? null) !== null)?.sort()",
"_bolts_max=feat.get('_bolts_hist')?.at(-1)",
"_bolts_min=feat.get('_bolts_hist')?.at(0)",
"_contained_climbing_routes_count=feat.get('_contained_climbing_routes_properties')?.length"
],
"tagRenderings": [
"images",
{
"id": "minimap",
"render": "{minimap(18, id, _contained_climbing_route_ids): height: 9rem; overflow: hidden; border-radius:3rem; }"
},
{
"render": {
"en": "<h3>Length overview</h3>{histogram(_length_hist)}",
"fr": "<h3>Résumé de longueur</h3>{histogram(_length_hist)}",
"de": "<h3>Längenübersicht</h3>{histogram(_length_hist)}",
"it": "<h3>Riassunto della lunghezza</h3>{histogram(_length_hist)}"
},
"condition": "_length_hist!~\\[\\]",
"id": "Contained routes length hist"
},
{
"render": {
"en": "<h3>Grades overview</h3>{histogram(_difficulty_hist)}",
"fr": "<h3>Résumé des difficultés</h3>{histogram(_difficulty_hist)}",
"de": "<h3>Schwierigkeitsübersicht</h3>{histogram(_difficulty_hist)}",
"it": "<h3>Riassunto delle difficoltà</h3>{histogram(_difficulty_hist)}"
},
"condition": "_difficulty_hist!~\\[\\]",
"id": "Contained routes hist"
},
{
"render": {
"en": "<h3>Contains {_contained_climbing_routes_count} routes</h3> <ul>{_contained_climbing_routes}</ul>",
"fr": "<h3>Contient {_contained_climbing_routes_count} voies</h3> <ul>{_contained_climbing_routes}</ul>",
"it": "<h3>Contiene {_contained_climbing_routes_count} vie</h3> <ul>{_contained_climbing_routes}</ul>",
"de": "<h3> Enthält {_contained_climbing_routes_count} Routen</h3> <ul>{_contained_climbing_routes}</ul>"
},
"condition": "_contained_climbing_routes~*",
"id": "Contained_climbing_routes"
},
{
"render": {
"en": "<strong>{name}</strong>",
"nl": "<strong>{name}</strong>",
"de": "<strong>{name}</strong>",
"ca": "<strong>{name}</strong>",
"fr": "<strong>{name}</strong>",
"id": "<strong>{name}</strong>",
"ru": "<strong>{name}</strong>",
"ja": "<strong>{name}</strong>",
"it": "<strong>{name}</strong>"
},
"question": {
"en": "What is the name of this climbing opportunity?",
"nl": "Wat is de naam van dit Klimgelegenheid?",
"de": "Wie heißt diese Klettergelegenheit?",
"ja": "この登坂教室の名前は何ですか?",
"fr": "Quel est le nom de ce site ?",
"it": "Qual è il nome di questa opportunità di arrampicata?"
},
"freeform": {
"key": "name"
},
"mappings": [
{
"if": {
"and": [
"noname=yes",
"name="
]
},
"then": {
"en": "This climbing opportunity doesn't have a name",
"nl": "Dit Klimgelegenheid heeft geen naam",
"de": "Diese Klettergelegenheit hat keinen Namen",
"ja": "この登坂教室には名前がついていない",
"fr": "Ce site na pas de nom",
"it": "Questa opportunità di arrampicata non ha un nome"
}
}
],
"id": "name"
},
{
"question": "What kind of climbing opportunity is this?",
"mappings": [
{
"if": "climbing=boulder",
"then": {
"en": "A climbing boulder - a single rock or cliff with one or a few climbing routes which can be climbed safely without rope",
"fr": "Rocher descalade, rocher avec une ou peu de voie permettant descalader sans corde",
"de": "Ein Kletterfelsen - ein einzelner Felsen oder eine Klippe mit einer oder wenigen Kletterrouten, die ohne Seil sicher bestiegen werden können",
"it": "Un masso per arrampicata (una singola roccia o falesia con una o poche vie di arrampicata che possono essere scalate in sicurezza senza una corda)"
}
},
{
"if": "climbing=crag",
"then": {
"en": "A climbing crag - a single rock or cliff with at least a few climbing routes",
"fr": "Mur descalade, rocher avec plusieurs voies descalades",
"it": "Un muro da arrampicata (un singolo masso o falesia con almeno qualche via per arrampicata)",
"de": "Ein Kletterfelsen - ein einzelner Fels oder eine Klippe mit mindestens einigen Kletterrouten"
}
},
{
"if": "climbing=area",
"then": "A climbing area with one or more climbing crags and/or boulders"
}
],
"id": "Type"
},
{
"question": {
"en": "What is the rock type here?",
"fr": "Quel est le type de roche ?",
"de": "Welchen Gesteinstyp gibt es hier?",
"it": "Qual è il tipo di roccia qua?"
},
"render": {
"en": "The rock type is {rock}",
"fr": "La roche est du {rock}",
"de": "Der Gesteinstyp ist {rock}",
"it": "Il tipo di roccia è {rock}"
},
"freeform": {
"key": "rock"
},
"mappings": [
{
"if": "rock=limestone",
"then": {
"en": "Limestone",
"nl": "Kalksteen",
"fr": "Calcaire",
"de": "Kalkstein",
"it": "Calcare"
}
}
],
"condition": {
"or": [
"climbing=crag",
"natural=cliff",
"natural=bare_rock"
]
},
"id": "Rock type (crag/rock/cliff only)"
},
{
"builtin": [
"climbing.website",
"climbing.fee",
"climbing.bouldering"
]
}
],
"presets": [
{
"tags": [
"sport=climbing"
],
"title": {
"en": "a climbing opportunity",
"nl": "een klimgelegenheid",
"de": "eine klettermöglichkeit",
"ja": "登坂教室",
"nb_NO": "en klatremulighet",
"fr": "une opportunité descalade",
"it": "una opportunità di arrampicata"
},
"description": {
"nl": "Een klimgelegenheid",
"de": "Eine Klettergelegenheit",
"en": "A climbing opportunity",
"ja": "登坂教室",
"nb_NO": "En klatremulighet",
"fr": "Opportunité descalade",
"it": "Unopportunità di arrampicata"
}
}
],
"mapRendering": [
{
"icon": {
"render": "./assets/themes/climbing/climbing_no_rope.svg"
},
"iconSize": {
"render": "40,40,center"
},
"location": [
"point",
"centroid"
]
},
{
"color": {
"render": "#d38d5fAA"
},
"width": {
"render": "8"
}
}
]
}

View file

@ -55,15 +55,7 @@
"images",
{
"render": {
"en": "<strong>{name}</strong>",
"nl": "<strong>{name}</strong>",
"de": "<strong>{name}</strong>",
"ca": "<strong>{name}</strong>",
"fr": "<strong>{name}</strong>",
"id": "<strong>{name}</strong>",
"ru": "<strong>{name}</strong>",
"ja": "<strong>{name}</strong>",
"it": "<strong>{name}</strong>"
"*": "<strong>{name}</strong>"
},
"question": {
"en": "What is the name of this climbing gym?",
@ -81,7 +73,65 @@
"website",
"phone",
"email",
"opening_hours"
{
"builtin": ["climbing.fee"]
},
"opening_hours",
{
"builtin":
["climbing.average_length","climbing.min_difficulty","climbing.max_difficulty",
"climbing.bouldering",
"climbing.sportclimbing"]
},
{
"builtin": "climbing.max_bolts",
"override": {
"condition": "climbing:sport=yes"
}
},
{
"id": "Speed climbing?",
"question": {
"de": "Gibt es hier eine Speedkletter-Wand?",
"en": "Is there a speed climbing wall?",
"nl": "Is er een snelklimmuur (speed climbing)?",
"ja": "スピードクライミングウォールはありますか?",
"it": "È presente una prete per larrampicata di velocità?"
},
"mappings": [
{
"if": "climbing:speed=yes",
"then": {
"de": "Hier gibt es eine Speedkletter-Wand",
"en": "There is a speed climbing wall",
"nl": "Er is een snelklimmuur voor speed climbing",
"ja": "スピードクライミングウォールがある",
"it": "È presente una parete per larrampicata di velocità"
}
},
{
"if": "climbing:speed=no",
"then": {
"de": "Hier gibt es keine Speedkletter-Wand",
"en": "There is no speed climbing wall",
"nl": "Er is geen snelklimmuur voor speed climbing",
"ja": "スピードクライミングウォールがない",
"it": "Non è presente una parete per larrampicata di velocità"
}
},
{
"if": "climbing:speed~*",
"then": {
"de": "Hier gibt es {climbing:speed} Speedkletter-Routen",
"en": "There are {climbing:speed} speed climbing walls",
"nl": "Er zijn hier {climbing:speed} snelklimmuren",
"ja": "{climbing:speed} のスピードクライミングウォールがある",
"it": "Sono presenti {climbing:speed} pareti per larrampicata di velocità"
},
"hideInAnswer": true
}
]
}
],
"mapRendering": [
{

View file

@ -9,6 +9,9 @@
"fr": "Opportunités descalade ?",
"it": "Opportunità di arrampicata?"
},
"description": {
"en": "Fallback layer with items on which climbing _might_ be possible. It is loaded when zoomed in a lot, to prevent duplicate items to be added"
},
"minzoom": 19,
"source": {
"osmTags": {
@ -38,15 +41,6 @@
"it": "Opportunità di arrampicata?"
}
},
"description": {
"nl": "Een klimgelegenheid?",
"de": "Eine Klettergelegenheit?",
"en": "A climbing opportunity?",
"ja": "登坂教室?",
"nb_NO": "En klatremulighet?",
"fr": "Opportunité descalade ?",
"it": "Unopportunità di arrampicata?"
},
"tagRenderings": [
{
"id": "climbing-opportunity-name",

View file

@ -9,6 +9,9 @@
"fr": "Voies descalade",
"it": "Vie di arrampicata"
},
"description": {
"en": "A single climbing route and its properties. Some properties are derived from the containing features"
},
"minzoom": 18,
"source": {
"osmTags": {
@ -135,6 +138,7 @@
"id": "Difficulty"
},
{
"id": "bolts",
"question": {
"en": "How many bolts does this route have before reaching the anchor?",
"fr": "Combien de prises cette voie possède avant datteindre la moulinette ?",
@ -142,7 +146,7 @@
"it": "Quanti bulloni sono presenti in questo percorso prima di arrivare alla moulinette?"
},
"render": {
"en": "This route has {climbing:bolts} bolts",
"en": "This route has {climbing:bolts} bolts <div class='subtle'>This is without relays and indicates how much quickdraws a climber needs</div>",
"fr": "Cette voie a {climbing:bolts} prises",
"de": "Diese Kletterroute hat {climbing:bolts} Haken",
"it": "Questo percorso ha {climbing:bolts} bulloni"
@ -152,7 +156,8 @@
"type": "pnat",
"addExtraTag": [
"climbing:bolted=yes"
]
],
"inline": true
},
"mappings": [
{
@ -163,29 +168,15 @@
"de": "Auf dieser Kletterroute sind keine Haken vorhanden",
"it": "In questo percorso non sono presenti bulloni"
},
"hideInAnswer": true
},
{
"if": "climbing:bolted=no&climbing:bolts=",
"then": {
"en": "This route is not bolted",
"fr": "Cette voie na pas de prises",
"de": "Auf dieser Kletterroute sind keine Haken vorhanden",
"it": "In questo percorso non sono presenti bulloni"
}
"addExtraTags": [
"climbing:bolts="
]
}
],
"id": "Bolts"
},
{
"question": "Is there other relevant info?",
"render": "<h3>Description</h3><br/>{description}",
"freeform": {
"key": "description"
},
"id": "Description"
]
},
"description",
{
"id": "Rock type via embedded feature",
"render": {
"en": "The rock type is {_embedding_features_with_rock:rock} as stated <a href='#{_embedding_features_with_rock:id}'>on the surrounding crag</a>",
"fr": "Le type de roche est {_embedding_features_with_rock:rock} selon <a href='#{_embedding_features_with_rock:id}'>le mur</a>",
@ -194,8 +185,7 @@
},
"freeform": {
"key": "_embedding_features_with_rock:rock"
},
"id": "Rock type"
}
}
],
"presets": [

View file

@ -43,688 +43,307 @@
"startZoom": 1,
"widenFactor": 1.5,
"layers": [
{
"builtin": [
"climbing_club",
"climbing_gym",
"climbing_route",
"climbing",
"climbing_area",
"climbing_opportunity"
],
"overrideAll": {
"allowMove": {
"enableRelocation": false,
"enableImproveAccuracy": true
},
"+titleIcons": [
{
"render": "<div class='flex' style='word-wrap: normal; padding-right: 0.25rem;'><img src='./assets/themes/climbing/height.svg' style='height: 1.75rem;'/>{climbing:length}m</div>",
"condition": "climbing:length~*"
},
{
"mappings": [
],
"override": {
"allowMove": {
"enableRelocation": false,
"enableImproveAccuracy": true
},
"+titleIcons": [
{
"if": "climbing:bolts~*",
"then": "<div class='flex' style='padding-right: 0.25rem;'><img src='./assets/themes/climbing/carabiner.svg' style='width: 1rem;'/>{climbing:bolts}</div>"
"render": "<div class='flex' style='word-wrap: normal; padding-right: 0.25rem;'><img src='./assets/themes/climbing/height.svg' style='height: 1.75rem;'/>{climbing:length}m</div>",
"condition": "climbing:length~*"
},
{
"if": "climbing:bolted=yes",
"then": "<img src='./assets/themes/climbing/carabiner.svg' style='width:2rem; height:2rem'/>"
"mappings": [
{
"if": "__bolts_max~*",
"then": "<div class='flex' style='padding-right: 0.25rem;'><img src='./assets/themes/climbing/carabiner.svg' style='width: 1rem;'/>{__bolts_max}</div>"
},
{
"if": "climbing:bolted=yes",
"then": "<img src='./assets/themes/climbing/carabiner.svg' style='width:2rem; height:2rem'/>"
}
]
},
{
"id": "Min difficulty",
"condition": "__difficulty_min~*",
"then": "<div class='w-8 flex justify-center rounded-left-full border border-black' style='margin-right: -5px; background-color:#ebf224'> {__difficulty_min}</div>",
"mappings": [
{
"if": "__difficulty_min~(2|3).*",
"then": "<div class='w-8 flex justify-center rounded-left-full' style='margin-right: -5px; background-color:#ebf224'> {__difficulty_min}</div>"
},
{
"if": "__difficulty_min~4.*",
"then": "<div class='w-8 flex justify-center rounded-left-full' style='margin-right: -5px; background-color:#7af224'> {__difficulty_min}</div>"
},
{
"if": "__difficulty_min~5.*",
"then": "<div class='w-8 flex justify-center rounded-left-full' style='margin-right: -5px; background-color:#f24a24'> {__difficulty_min}</div>"
},
{
"if": "__difficulty_min~6.*",
"then": "<div class='w-8 flex justify-center rounded-left-full' style='margin-right: -5px; background-color:#244af2'> {__difficulty_min}</div>"
},
{
"if": "__difficulty_min~(7|8).*",
"then": "<div class='w-8 flex justify-center rounded-left-full' style='margin-right: -5px; background-color:#e904ed'> {__difficulty_min}</div>"
},
{
"if": "__difficulty_min~*",
"then": "<div class='w-8 flex justify-center rounded-left-full' style='margin-right: -5px; background-colour:black'> {__difficulty_min}</div>"
}
]
},
{
"id": "max difficulty",
"condition": "__difficulty_max~*",
"then": "<div class='w-8 flex justify-center rounded-right-full border border-black' style='background-color:#ebf224'> {__difficulty_max}</div>",
"mappings": [
{
"if": "__difficulty_max~(2|3).*",
"then": "<div class='w-8 flex justify-center rounded-right-full' style='background-color:#ebf224'> {__difficulty_max}</div>"
},
{
"if": "__difficulty_max~4.*",
"then": "<div class='w-8 flex justify-center rounded-right-full' style='background-color:#7af224'> {__difficulty_max}</div>"
},
{
"if": "__difficulty_max~5.*",
"then": "<div class='w-8 flex justify-center rounded-right-full' style='background-color:#f24a24'> {__difficulty_max}</div>"
},
{
"if": "__difficulty_max~6.*",
"then": "<div class='w-8 flex justify-center rounded-right-full' style='background-color:#244af2'> {__difficulty_max}</div>"
},
{
"if": "__difficulty_max~(7|8).*",
"then": "<div class='w-8 flex justify-center rounded-right-full' style='background-color:#e904ed'> {__difficulty_max}</div>"
},
{
"if": "__difficulty_max~*",
"then": "<div class='w-8 flex justify-center rounded-right-full' style='background-colour:black'> {__difficulty_max}</div>"
}
]
},
{
"mappings": [
{
"if": "climbing:grade:french~3.*",
"then": "<div class='rounded-full px-1' style='background-color:#ebf224'> {climbing:grade:french}</div>"
},
{
"if": "climbing:grade:french~4.*",
"then": "<div class='rounded-full pl-2 pr-2' style='background-color:#7af224'> {climbing:grade:french}</div>"
},
{
"if": "climbing:grade:french~5.*",
"then": "<div class='rounded-full pl-2 pr-2' style='background-color:#f24a24'> {climbing:grade:french}</div>"
},
{
"if": "climbing:grade:french~6.*",
"then": "<div class='text-white rounded-full pl-2 pr-2' style='background-color:#244af2'> {climbing:grade:french}</div>"
},
{
"if": "climbing:grade:french~7.*",
"then": "<div class='text-white rounded-full pl-2 pr-2' style='background-color:#e904ed'> {climbing:grade:french}</div>"
},
{
"if": "climbing:grade:french~*",
"then": "<div class='text-white rounded-full px-2' style='background-colour:black'> {climbing:grade:french}</div>"
}
]
}
]
},
{
"mappings": [
{
"if": "climbing:grade:french~3.*",
"then": "<div class='rounded-full px-1' style='background-color:#ebf224'> {climbing:grade:french}</div>"
},
{
"if": "climbing:grade:french~4.*",
"then": "<div class='rounded-full pl-2 pr-2' style='background-color:#7af224'> {climbing:grade:french}</div>"
},
{
"if": "climbing:grade:french~5.*",
"then": "<div class='rounded-full pl-2 pr-2' style='background-color:#f24a24'> {climbing:grade:french}</div>"
},
{
"if": "climbing:grade:french~6.*",
"then": "<div class='text-white rounded-full pl-2 pr-2' style='background-color:#244af2'> {climbing:grade:french}</div>"
},
{
"if": "climbing:grade:french~7.*",
"then": "<div class='text-white rounded-full pl-2 pr-2' style='background-color:#e904ed'> {climbing:grade:french}</div>"
},
{
"if": "climbing:grade:french~*",
"then": "<div class='text-white rounded-full px-2' style='background-colour:black'> {climbing:grade:french}</div>"
}
]
}
],
"+calculatedTags": [
"_embedding_feature_properties=feat.overlapWith('climbing').map(f => f.feat.properties).filter(p => p !== undefined).map(p => {return{access: p.access, id: p.id, name: p.name, climbing: p.climbing, 'access:description': p['access:description']}})",
"_embedding_features_with_access=JSON.parse(feat.properties._embedding_feature_properties ?? '[]').filter(p => p.access !== undefined)[0]",
"_embedding_feature_with_rock=JSON.parse(feat.properties._embedding_feature_properties ?? '[]').filter(p => p.rock !== undefined)[0] ?? '{}'",
"_embedding_features_with_rock:rock=JSON.parse(feat.properties._embedding_feature_with_rock ?? '{}')?.rock",
"_embedding_features_with_rock:id=JSON.parse(feat.properties._embedding_feature_with_rock ?? '{}')?.id",
"_embedding_feature:access=JSON.parse(feat.properties._embedding_features_with_access ?? '{}').access",
"_embedding_feature:access:description=JSON.parse(feat.properties._embedding_features_with_access ?? '{}')['access:description']",
"_embedding_feature:id=JSON.parse(feat.properties._embedding_features_with_access ?? '{}').id"
],
"units+": [
{
"appliesToKey": [
"climbing:length",
"climbing:length:min",
"climbing:length:max"
],
"applicableUnits": [
"+calculatedTags": [
"_embedding_feature_properties=feat.overlapWith('climbing_area').map(f => f.feat.properties).filter(p => p !== undefined).map(p => {return{access: p.access, id: p.id, name: p.name, climbing: p.climbing, 'access:description': p['access:description']}})",
"_embedding_features_with_access=feat.get('_embedding_feature_properties')?.filter(p => p.access !== undefined)?.at(0)",
"_embedding_feature_with_rock=feat.get('_embedding_feature_properties')?.filter(p => p.rock !== undefined)?.at(0)",
"_embedding_features_with_rock:rock=feat.get('_embedding_feature_with_rock')?.rock",
"_embedding_features_with_rock:id=feat.get('_embedding_feature_with_rock')?.id",
"_embedding_feature:access=feat.get('_embedding_features_with_access')?.access",
"_embedding_feature:access:description=(feat.get('_embedding_features_with_access')??{})['access:description']",
"_embedding_feature:id=feat.get('_embedding_features_with_access')?.id",
"__difficulty_max= feat.properties['climbing:grade:french:max'] ?? feat.properties['_difficulty_max']",
"__difficulty_min= feat.properties['climbing:grade:french:min'] ?? feat.properties['_difficulty_min']",
"__bolts_max= feat.get('climbing:bolts:max') ?? feat.get('climbing:bolts') ?? feat.get('_bolts_max')"
],
"units+": [
{
"canonicalDenomination": "",
"alternativeDenomination": [
"m",
"meter",
"meters"
"appliesToKey": [
"climbing:length",
"climbing:length:min",
"climbing:length:max"
],
"human": {
"en": " meter",
"nl": " meter",
"fr": " mètres",
"de": " Meter",
"eo": " metro",
"it": " metri",
"ru": " метр",
"ca": " metre"
},
"default": true
},
"applicableUnits": [
{
"canonicalDenomination": "",
"alternativeDenomination": [
"m",
"meter",
"meters"
],
"human": {
"en": " meter",
"nl": " meter",
"fr": " mètres",
"de": " Meter",
"eo": " metro",
"it": " metri",
"ru": " метр",
"ca": " metre"
},
"default": true
},
{
"canonicalDenomination": "ft",
"alternativeDenomination": [
"feet",
"voet"
],
"human": {
"en": " feet",
"nl": " voet",
"fr": " pieds",
"de": " Fuß",
"eo": " futo",
"it": " piedi",
"ca": " peus"
}
}
]
}
],
"tagRenderings+": [
{
"canonicalDenomination": "ft",
"alternativeDenomination": [
"feet",
"voet"
"id": "Access from containing feature",
"mappings": [
{
"if": "_embedding_feature:access=yes",
"then": {
"en": "<span class='subtle'>The <a href='#{_embedding_feature:id}'>containing feature</a> states that this is</span> publicly accessible<br/>{_embedding_feature:access:description}",
"nl": "<span class='subtle'>Een <a href='#{_embedding_feature:id}'>omvattend element</a> geeft aan dat dit <span>publiek toegangkelijk is</span><br/>{_embedding_feature:access:description}",
"fr": "<span class='subtle'>L<a href='#{_embedding_feature:id}'>élément englobant</a> indique un </span> accès libre<br/>{_embedding_feature:access:description}",
"it": "<span class='subtle'>L <a href='#{_embedding_feature:id}'>elemento in cui è contenuto</a> indica che è</span> pubblicamente accessibile<br/>{_embedding_feature:access:description}",
"de": "<span class='subtle'>Das <a href='#{_embedding_feature:id}'>enthaltende Objekt</a> gibt an, dass es </span>öffentlich zugänglich ist<br/>{_embedding_feature:access:description}"
}
},
{
"if": "_embedding_feature:access=permit",
"then": {
"en": "<span class='subtle'>The <a href='#{_embedding_feature:id}'>containing feature</a> states that </span> a permit is needed to access<br/>{_embedding_feature:access:description}",
"nl": "<span class='subtle'>Een <a href='#{_embedding_feature:id}'>omvattend element</a> geeft aan dat</span> een toelating nodig is om hier te klimmen<br/>{_embedding_feature:access:description}",
"fr": "<span class='subtle'>L<a href='#{_embedding_feature:id}'>élément englobant</a> indique qu</span> une autorisation daccès est nécessaire<br/>{_embedding_feature:access:description}",
"it": "<span class='subtle'>L<a href='#{_embedding_feature:id}'>elemento che lo contiene</a> indica che </span> è richiesto unautorizzazione per accedervi<br/>{_embedding_feature:access:description}",
"de": "<span class='subtle'>Das <a href='#{_embedding_feature:id}'>enthaltende Objekt</a> besagt, dass </span> eine Genehmigung erforderlich ist für den Zugang zu<br/>{_embedding_feature:access:description}"
}
},
{
"if": "_embedding_feature:access=customers",
"then": {
"en": "<span class='subtle'>The <a href='#{_embedding_feature:id}'>containing feature</a> states that this is</span> only accessible to customers<br/>{_embedding_feature:access:description}",
"fr": "<span class='subtle'>L<a href='#{_embedding_feature:id}'>élément englobant</a> indique que </span> laccès est réservés aux clients<br/>{_embedding_feature:access:description}",
"it": "<span class='subtle'>L <a href='#{_embedding_feature:id}'>elemento che lo contiene</a> indica che è</span> accessibile solo ai clienti<br/>{_embedding_feature:access:description}",
"de": "<span class='subtle'>Das <a href='#{_embedding_feature:id}'>enthaltende Objekt</a> besagt, dass es nur für Kunden</span> zugänglich ist<br/>{_embedding_feature:access:description}"
}
},
{
"if": "_embedding_feature:access=members",
"then": {
"en": "<span class='subtle'>The <a href='#{_embedding_feature:id}'>containing feature</a> states that this is</span> only accessible to club members<br/>{_embedding_feature:access:description}",
"fr": "<span class='subtle'>L<a href='#{_embedding_feature:id}'>élément englobant</a> indique que </span> laccès est réservé aux membres<br/>{_embedding_feature:access:description}",
"it": "<span class='subtle'>L <a href='#{_embedding_feature:id}'>elemento che lo contiene</a> indica che è </span> accessibile solamente ai membri del club<br/>{_embedding_feature:access:description}",
"de": "<span class='subtle'>Das <a href='#{_embedding_feature:id}'>enthaltende Objekt</a> besagt, dass es </span>nur für Mitglieder zugänglich ist<br/>{_embedding_feature:access:description}"
}
},
{
"if": "_embedding_feature:access=no",
"then": "Not accessible as stated by <a href='#{_embedding_feature:id}'>the containing feature</a>"
}
],
"human": {
"en": " feet",
"nl": " voet",
"fr": " pieds",
"de": " Fuß",
"eo": " futo",
"it": " piedi",
"ca": " peus"
}
}
]
}
],
"tagRenderings+": [
{
"id": "Website",
"question": {
"en": "Is there a (unofficial) website with more informations (e.g. topos)?",
"de": "Gibt es eine (inoffizielle) Website mit mehr Informationen (z.B. Topos)?",
"ja": "もっと情報のある(非公式の)ウェブサイトはありますか(例えば、topos)?",
"nl": "Is er een (onofficiële) website met meer informatie (b.v. met topos)?",
"ru": "Есть ли (неофициальный) веб-сайт с более подробной информацией (напр., topos)?",
"fr": "Existe-til un site avec plus dinformations (ex : topographie) ?",
"it": "Cè un sito web (anche non ufficiale) con qualche informazione in più (ad es. topografie)?"
},
"condition": {
"and": [
"leisure!~sports_centre",
"sport=climbing",
"office=",
"club="
]
},
"render": "<a href='{url}' target='_blank'>{url}</a>",
"freeform": {
"key": "url",
"type": "url"
}
},
{
"id": "Access from containing feature",
"mappings": [
{
"if": "_embedding_feature:access=yes",
"then": {
"en": "<span class='subtle'>The <a href='#{_embedding_feature:id}'>containing feature</a> states that this is</span> publicly accessible<br/>{_embedding_feature:access:description}",
"nl": "<span class='subtle'>Een <a href='#{_embedding_feature:id}'>omvattend element</a> geeft aan dat dit <span>publiek toegangkelijk is</span><br/>{_embedding_feature:access:description}",
"fr": "<span class='subtle'>L<a href='#{_embedding_feature:id}'>élément englobant</a> indique un </span> accès libre<br/>{_embedding_feature:access:description}",
"it": "<span class='subtle'>L <a href='#{_embedding_feature:id}'>elemento in cui è contenuto</a> indica che è</span> pubblicamente accessibile<br/>{_embedding_feature:access:description}",
"de": "<span class='subtle'>Das <a href='#{_embedding_feature:id}'>enthaltende Objekt</a> gibt an, dass es </span>öffentlich zugänglich ist<br/>{_embedding_feature:access:description}"
}
"condition": "_embedding_feature:access~*"
},
{
"if": "_embedding_feature:access=permit",
"then": {
"en": "<span class='subtle'>The <a href='#{_embedding_feature:id}'>containing feature</a> states that </span> a permit is needed to access<br/>{_embedding_feature:access:description}",
"nl": "<span class='subtle'>Een <a href='#{_embedding_feature:id}'>omvattend element</a> geeft aan dat</span> een toelating nodig is om hier te klimmen<br/>{_embedding_feature:access:description}",
"fr": "<span class='subtle'>L<a href='#{_embedding_feature:id}'>élément englobant</a> indique qu</span> une autorisation daccès est nécessaire<br/>{_embedding_feature:access:description}",
"it": "<span class='subtle'>L<a href='#{_embedding_feature:id}'>elemento che lo contiene</a> indica che </span> è richiesto unautorizzazione per accedervi<br/>{_embedding_feature:access:description}",
"de": "<span class='subtle'>Das <a href='#{_embedding_feature:id}'>enthaltende Objekt</a> besagt, dass </span> eine Genehmigung erforderlich ist für den Zugang zu<br/>{_embedding_feature:access:description}"
}
},
{
"if": "_embedding_feature:access=customers",
"then": {
"en": "<span class='subtle'>The <a href='#{_embedding_feature:id}'>containing feature</a> states that this is</span> only accessible to customers<br/>{_embedding_feature:access:description}",
"fr": "<span class='subtle'>L<a href='#{_embedding_feature:id}'>élément englobant</a> indique que </span> laccès est réservés aux clients<br/>{_embedding_feature:access:description}",
"it": "<span class='subtle'>L <a href='#{_embedding_feature:id}'>elemento che lo contiene</a> indica che è</span> accessibile solo ai clienti<br/>{_embedding_feature:access:description}",
"de": "<span class='subtle'>Das <a href='#{_embedding_feature:id}'>enthaltende Objekt</a> besagt, dass es nur für Kunden</span> zugänglich ist<br/>{_embedding_feature:access:description}"
}
},
{
"if": "_embedding_feature:access=members",
"then": {
"en": "<span class='subtle'>The <a href='#{_embedding_feature:id}'>containing feature</a> states that this is</span> only accessible to club members<br/>{_embedding_feature:access:description}",
"fr": "<span class='subtle'>L<a href='#{_embedding_feature:id}'>élément englobant</a> indique que </span> laccès est réservé aux membres<br/>{_embedding_feature:access:description}",
"it": "<span class='subtle'>L <a href='#{_embedding_feature:id}'>elemento che lo contiene</a> indica che è </span> accessibile solamente ai membri del club<br/>{_embedding_feature:access:description}",
"de": "<span class='subtle'>Das <a href='#{_embedding_feature:id}'>enthaltende Objekt</a> besagt, dass es </span>nur für Mitglieder zugänglich ist<br/>{_embedding_feature:access:description}"
}
},
{
"if": "_embedding_feature:access=no",
"then": "Not accessible as stated by <a href='#{_embedding_feature:id}'>the containing feature</a>"
}
],
"condition": "_embedding_feature:access~*"
},
{
"id": "Access",
"question": {
"en": "Who can access here?",
"fr": "Qui peut y accéder ?",
"de": "Wer hat hier Zugang?",
"it": "Chi può accedervi?"
},
"mappings": [
{
"if": "access=yes",
"then": {
"en": "Publicly accessible to anyone",
"fr": "Libre daccès",
"de": "Öffentlich zugänglich für jedermann",
"it": "Pubblicamente accessibile a chiunque"
}
},
{
"if": "access=permit",
"then": {
"en": "You need a permit to access here",
"fr": "Une autorisation est nécessaire",
"de": "Zugang nur mit Genehmigung",
"it": "È necessario avere unautorizzazione per entrare"
}
},
{
"if": "access=customers",
"then": {
"en": "Only customers",
"fr": "Réservé aux clients",
"de": "Nur für Kunden",
"it": "Riservato ai clienti",
"ca": "Només clients"
}
},
{
"if": "access=members",
"then": {
"en": "Only club members",
"ru": "Только членам клуба",
"fr": "Réservé aux membres",
"de": "Nur für Vereinsmitglieder",
"it": "Riservato ai membri del club",
"ca": "Només membres del club"
}
},
{
"if": "access=no",
"then": "Not accessible"
}
],
"condition": {
"and": [
"climbing!=no",
"office=",
"club=",
{
"or": [
"sport=climbing",
"climbing:sport=yes"
]
"id": "access",
"question": {
"en": "Who can access here?",
"fr": "Qui peut y accéder ?",
"de": "Wer hat hier Zugang?",
"it": "Chi può accedervi?"
},
{
"mappings": [
{
"if": "access=yes",
"then": {
"en": "Publicly accessible to anyone",
"fr": "Libre daccès",
"de": "Öffentlich zugänglich für jedermann",
"it": "Pubblicamente accessibile a chiunque"
}
},
{
"if": "access=permit",
"then": {
"en": "You need a permit to access here",
"fr": "Une autorisation est nécessaire",
"de": "Zugang nur mit Genehmigung",
"it": "È necessario avere unautorizzazione per entrare"
}
},
{
"if": "access=customers",
"then": {
"en": "Only customers",
"fr": "Réservé aux clients",
"de": "Nur für Kunden",
"it": "Riservato ai clienti",
"ca": "Només clients"
}
},
{
"if": "access=members",
"then": {
"en": "Only club members",
"ru": "Только членам клуба",
"fr": "Réservé aux membres",
"de": "Nur für Vereinsmitglieder",
"it": "Riservato ai membri del club",
"ca": "Només membres del club"
}
},
{
"if": "access=no",
"then": "Not accessible"
}
],
"condition": {
"or": [
"access~*",
"_embedding_feature:access="
]
}
]
}
},
{
"id": "Access description (without _embedding_feature:access:description)",
"render": "{access:description}",
"freeform": {
"key": "access:description"
}
},
{
"id": "Avg length?",
"render": {
"de": "Die Routen sind durchschnittlich <b>{canonical(climbing:length)}</b> lang",
"en": "The routes are <b>{canonical(climbing:length)}</b> long on average",
"nl": "De klimroutes zijn gemiddeld <b>{canonical(climbing:length)}</b> lang",
"ja": "ルートの長さは平均で<b>{canonical(climbing:length)}</b>です",
"fr": "Les voies font <b>{canonical(climbing:length)}</b> de long en moyenne",
"it": "Le vie sono lunghe mediamente <b>{canonical(climbing:length)}</b>"
},
"condition": {
"and": [
"climbing!~route",
"office=",
"club=",
"climbing:toprope!=no",
{
"or": [
"sport=climbing",
"climbing:sport=yes",
"climbing=traditional",
"climbing=gym"
]
}
]
},
"question": {
"de": "Wie lang sind die Routen (durchschnittlich) in Metern?",
"en": "What is the (average) length of the routes in meters?",
"nl": "Wat is de (gemiddelde) lengte van de klimroutes, in meter?",
"ja": "ルートの(平均)長さはメートル単位でいくつですか?",
"fr": "Quelle est la longueur moyenne des voies en mètres ?",
"it": "Quale è la lunghezza (media) delle vie in metri?"
},
"freeform": {
"key": "climbing:length",
"type": "pnat"
}
},
{
"id": "Difficulty-min",
"question": {
"de": "Welche Schwierigkeit hat hier die leichteste Route (französisch/belgisches System)?",
"en": "What is the grade of the easiest route here, according to the french classification system?",
"nl": "Wat is het niveau van de makkelijkste route, volgens het Franse classificatiesysteem?",
"ja": "ここで一番簡単なルートのレベルは、フランスのランク評価システムで何ですか?",
"fr": "Quel est le niveau de la voie la plus simple selon la classification franco-belge ?",
"it": "Qual è il livello della via più facile qua, secondo il sistema di classificazione francese?"
},
"render": {
"de": "Die leichteste Route hat hier die Schwierigkeit {climbing:grade:french:min} (französisch/belgisches System)",
"en": "The lowest grade is {climbing:grade:french:min} according to the french/belgian system",
"nl": "De minimale klimmoeilijkheid is {climbing:grade:french:min} volgens het Franse/Belgische systeem",
"ja": "フランス/ベルギーのランク評価システムでは、最小の難易度は{climbing:grade:french:min}です",
"fr": "La difficulté minimale est {climbing:grade:french:min} selon la classification franco-belge",
"it": "Il minimo livello di difficoltà è {climbing:grade:french:min} secondo il sistema francese/belga"
},
"freeform": {
"key": "climbing:grade:french:min"
},
"condition": {
"and": [
"climbing!~route",
"office=",
"club=",
{
"or": [
"climbing:sport=yes",
"sport=climbing"
]
}
]
}
},
{
"id": "Difficulty-max",
"question": {
"de": "Welche Schwierigkeit hat hier die schwerste Route (französisch/belgisches System)?",
"en": "What is the highest grade route here, according to the french classification system?",
"nl": "Wat is het niveau van de moeilijkste route, volgens het Franse classificatiesysteem?",
"ja": "フランスのランク評価によると、ここで一番難しいルートのレベルはどれくらいですか?",
"fr": "Quel est le niveau de la voie la plus difficile selon la classification franco-belge ?",
"it": "Qual è il livello della via più difficile qua, secondo il sistema di classificazione francese?"
},
"render": {
"de": "Die schwierigste Route hat hier die Schwierigkeitsstufe {climbing:grade:french:max} (französisch/belgisches System)",
"en": "The highest grade is {climbing:grade:french:max} according to the french/belgian system",
"nl": "De maximale klimmoeilijkheid is {climbing:grade:french:max} volgens het Franse/Belgische systeem",
"ja": "フランス/ベルギーのランク評価システムでは、最大の難易度は{climbing:grade:french:max}です",
"fr": "La difficulté maximale est {climbing:grade:french:max} selon la classification franco-belge",
"it": "Il massimo livello di difficoltà è {climbing:grade:french:max} secondo il sistema francese/belga"
},
"freeform": {
"key": "climbing:grade:french:max"
},
"condition": {
"and": [
"climbing!~route",
"office=",
"club=",
{
"or": [
"climbing:sport=yes",
"sport=climbing"
]
}
]
}
},
{
"id": "Boldering?",
"question": {
"de": "Kann hier gebouldert werden?",
"en": "Is bouldering possible here?",
"nl": "Is het mogelijk om hier te bolderen?",
"ja": "ここでボルダリングはできますか?",
"nb_NO": "Er buldring mulig her?",
"fr": "Lescalade de bloc est-elle possible ici ?",
"it": "È possibile praticare bouldering qua?"
},
"mappings": [
{
"if": "climbing:boulder=yes",
"then": {
"de": "Hier kann gebouldert werden",
"en": "Bouldering is possible here",
"nl": "Bolderen kan hier",
"ja": "ボルダリングはここで可能です",
"nb_NO": "Buldring er mulig her",
"fr": "Lescalade de bloc est possible",
"it": "Larrampicata su massi è possibile qua"
}
},
{
"if": "climbing:boulder=no",
"then": {
"de": "Hier kann nicht gebouldert werden",
"en": "Bouldering is not possible here",
"nl": "Bolderen kan hier niet",
"ja": "ここではボルダリングはできません",
"nb_NO": "Buldring er ikke mulig her",
"fr": "Lescalade de bloc nest pas possible",
"it": "Larrampicata su massi non è possibile qua"
"id": "Access description (without _embedding_feature:access:description)",
"render": "{access:description}",
"freeform": {
"key": "access:description"
}
},
{
"if": "climbing:boulder=limited",
"then": {
"de": "Bouldern ist hier nur an wenigen Routen möglich",
"en": "Bouldering is possible, allthough there are only a few routes",
"nl": "Bolderen kan hier, maar er zijn niet zoveel routes",
"ja": "ボルダリングは可能ですが、少しのルートしかありません",
"fr": "Lescalade de bloc est possible sur des voies précises",
"it": "Larrampicata su massi è possibile anche se su poche vie"
}
},
{
"if": "climbing:boulder~*",
"then": {
"de": "Hier gibt es {climbing:boulder} Boulder-Routen",
"en": "There are {climbing:boulder} boulder routes",
"nl": "Er zijn hier {climbing:boulder} bolderroutes",
"ja": "{climbing:boulder} ボルダールートがある",
"fr": "Il y a {climbing:boulder} voies descalade de bloc",
"it": "Sono presenti {climbing:boulder} vie di arrampicata su massi"
},
"hideInAnswer": true
}
],
"condition": {
"and": [
{
"or": [
"climbing:sport=yes",
"sport=climbing"
]
},
"office=",
"club="
]
}
},
{
"id": "Toproping?",
"question": {
"de": "Ist Toprope-Klettern hier möglich?",
"en": "Is toprope climbing possible here?",
"nl": "Is het mogelijk om hier te toprope-klimmen?",
"ja": "ここでtoprope登坂はできますか?",
"fr": "Est-il possible descalader à la moulinette ?",
"it": "È possibile arrampicarsi con la corda dallalto qua?"
},
"mappings": [
{
"if": "climbing:toprope=yes",
"then": {
"de": "Toprope-Klettern ist hier möglich",
"en": "Toprope climbing is possible here",
"nl": "Toprope-klimmen kan hier",
"ja": "ここでToprope登坂ができます",
"fr": "Lescalade à la moulinette est possible",
"it": "È possibile arrampicarsi con moulinette qua"
}
},
{
"if": "climbing:toprope=no",
"then": {
"de": "Toprope-Climbing ist hier nicht möglich",
"en": "Toprope climbing is not possible here",
"nl": "Toprope-klimmen kan hier niet",
"ja": "ここではToprope登坂はできません",
"fr": "Lescalade à la moulinette nest pas possible",
"it": "Non è possibile arrampicarsi con moulinette qua"
}
},
{
"if": "climbing:toprope~*",
"then": {
"de": "Hier gibt es {climbing:toprope} Toprope-Routen",
"en": "There are {climbing:toprope} toprope routes",
"nl": "Er zijn hier {climbing:toprope} toprope routes",
"ja": "{climbing:toprope} 登坂ルートがある",
"fr": "{climbing:toprope} voies sont équipées de moulinettes",
"it": "Sono presenti {climbing:toprope} vie con moulinette"
},
"hideInAnswer": true
}
],
"condition": {
"and": [
{
"or": [
"climbing:sport=yes",
"sport=climbing"
]
},
"office=",
"club="
]
}
},
{
"id": "Sportclimbing?",
"question": {
"de": "Ist hier Sportklettern möglich (feste Ankerpunkte)?",
"en": "Is sport climbing possible here on fixed anchors?",
"nl": "Is het mogelijk om hier te sportklimmen/voorklimmen op reeds aangebrachte haken?",
"ja": "ここでは固定アンカー式のスポーツクライミングはできますか?",
"it": "È possibile arrampicarsi qua con ancoraggi fissi?"
},
"mappings": [
{
"if": "climbing:sport=yes",
"then": {
"de": "Sportklettern ist hier möglich",
"en": "Sport climbing is possible here",
"nl": "Sportklimmen/voorklimmen kan hier",
"ru": "Здесь можно заняться спортивным скалолазанием",
"ja": "ここでスポーツクライミングができます",
"it": "Larrampicata sportiva è possibile qua",
"hu": "Itt lehetőség van sportmászásra",
"fr": "De lescalade est possible ici"
}
},
{
"if": "climbing:sport=no",
"then": {
"de": "Sportklettern ist hier nicht möglich",
"en": "Sport climbing is not possible here",
"nl": "Sportklimmen/voorklimmen kan hier niet",
"ru": "Спортивное скалолазание здесь невозможно",
"ja": "ここではスポーツクライミングはできません",
"it": "Larrampicata sportiva non è possibile qua",
"hu": "Itt nincs lehetőség sportmászásra",
"fr": "Lescalade est impossible ici"
}
},
{
"if": "climbing:sport~*",
"then": {
"de": "Hier gibt es {climbing:sport} Sportkletter-Routen",
"en": "There are {climbing:sport} sport climbing routes",
"nl": "Er zijn hier {climbing:sport} sportklimroutes/voorklimroutes",
"ja": "スポーツクライミングの {climbing:sport} ルートがある",
"it": "Sono presenti {climbing:sport} vie di arrampicata sportiva"
},
"hideInAnswer": true
}
],
"condition": {
"and": [
{
"or": [
"climbing:sport=yes",
"sport=climbing"
]
},
"office=",
"club="
]
}
},
{
"id": "Traditional climbing?",
"question": {
"de": "Ist hier traditionelles Klettern möglich (eigene Sicherung z.B. mit Klemmkleilen)?",
"en": "Is traditional climbing possible here (using own gear e.g. chocks)?",
"nl": "Is het mogelijk om hier traditioneel te klimmen? <br/><span class='subtle'>(Dit is klimmen met klemblokjes en friends)</span>",
"ja": "伝統的な登山はここで可能ですか(例えば、チョックのような独自のギアを使用して)",
"it": "È possibile arrampicarsi in maniera tradizionale qua (usando attrezzi propri, ad es. dadi)?"
},
"mappings": [
{
"if": "climbing:traditional=yes",
"then": {
"de": "Traditionelles Klettern ist hier möglich",
"en": "Traditional climbing is possible here",
"nl": "Traditioneel klimmen kan hier",
"ja": "ここでは伝統的な登山が可能です",
"it": "Larrampicata tradizionale è possibile qua"
}
},
{
"if": "climbing:traditional=no",
"then": {
"de": "Traditionelles Klettern ist hier nicht möglich",
"en": "Traditional climbing is not possible here",
"nl": "Traditioneel klimmen kan hier niet",
"ja": "伝統的な登山はここではできない",
"it": "Larrampicata tradizionale non è possibile qua"
}
},
{
"if": "climbing:traditional~*",
"then": {
"de": "Hier gibt es {climbing:traditional} Routen für traditionelles Klettern",
"en": "There are {climbing:traditional} traditional climbing routes",
"nl": "Er zijn hier {climbing:traditional} traditionele klimroutes",
"ja": "{climbing:traditional} の伝統的な登山ルートがある",
"it": "Sono presenti {climbing:traditional} vie di arrampicata tradizionale"
},
"hideInAnswer": true
}
],
"condition": {
"and": [
{
"or": [
"climbing:sport=yes",
"sport=climbing"
]
},
"office=",
"club="
]
}
},
{
"id": "Speed climbing?",
"question": {
"de": "Gibt es hier eine Speedkletter-Wand?",
"en": "Is there a speed climbing wall?",
"nl": "Is er een snelklimmuur (speed climbing)?",
"ja": "スピードクライミングウォールはありますか?",
"it": "È presente una prete per larrampicata di velocità?"
},
"condition": {
"and": [
"leisure=sports_centre",
{
"or": [
"climbing:sport=yes",
"sport=climbing"
]
},
"office=",
"club="
]
},
"mappings": [
{
"if": "climbing:speed=yes",
"then": {
"de": "Hier gibt es eine Speedkletter-Wand",
"en": "There is a speed climbing wall",
"nl": "Er is een snelklimmuur voor speed climbing",
"ja": "スピードクライミングウォールがある",
"it": "È presente una parete per larrampicata di velocità"
}
},
{
"if": "climbing:speed=no",
"then": {
"de": "Hier gibt es keine Speedkletter-Wand",
"en": "There is no speed climbing wall",
"nl": "Er is geen snelklimmuur voor speed climbing",
"ja": "スピードクライミングウォールがない",
"it": "Non è presente una parete per larrampicata di velocità"
}
},
{
"if": "climbing:speed~*",
"then": {
"de": "Hier gibt es {climbing:speed} Speedkletter-Routen",
"en": "There are {climbing:speed} speed climbing walls",
"nl": "Er zijn hier {climbing:speed} snelklimmuren",
"ja": "{climbing:speed} のスピードクライミングウォールがある",
"it": "Sono presenti {climbing:speed} pareti per larrampicata di velocità"
},
"hideInAnswer": true
}
"questions",
"reviews"
]
},
"questions",
"reviews"
]
}
}
}
]
}

View file

@ -17,8 +17,8 @@
"es": "Árboles"
},
"shortDescription": {
"nl": "Breng bomen in kaart",
"en": "Map all the trees",
"nl": "Breng bomen in kaart",
"fr": "Carte des arbres",
"it": "Mappa tutti gli alberi",
"ja": "すべての樹木をマッピングする",

View file

@ -1144,16 +1144,16 @@ video {
width: 2.75rem;
}
.w-16 {
width: 4rem;
}
.w-min {
width: -webkit-min-content;
width: -moz-min-content;
width: min-content;
}
.w-16 {
width: 4rem;
}
.w-auto {
width: auto;
}
@ -1987,6 +1987,16 @@ a {
width: min-content;
}
.rounded-left-full {
border-bottom-left-radius: 999rem;
border-top-left-radius: 999rem;
}
.rounded-right-full {
border-bottom-right-radius: 999rem;
border-top-right-radius: 999rem;
}
.w-16-imp {
width: 4rem !important;
}

View file

@ -39,6 +39,16 @@
background-color: var(--catch-detail-color);
color: var(--catch-detail-color-contrast);
}
.rounded-left-full {
border-bottom-left-radius: 999rem;
border-top-left-radius: 999rem;
}
.rounded-right-full {
border-bottom-right-radius: 999rem;
border-top-right-radius: 999rem;
}
}
}
@ -223,6 +233,16 @@ a {
width: min-content;
}
.rounded-left-full {
border-bottom-left-radius: 999rem;
border-top-left-radius: 999rem;
}
.rounded-right-full {
border-bottom-right-radius: 999rem;
border-top-right-radius: 999rem;
}
.w-16-imp {
width: 4rem !important;
}

View file

@ -156,6 +156,9 @@ class LayerOverviewUtils {
}
this.checkAllSvgs()
const green = s => '\x1b[92m' + s + '\x1b[0m'
console.log(green("All done!"))
}
private buildLayerIndex(knownImagePaths: Set<string>): Map<string, LayerConfigJson> {