diff --git a/assets/layers/questions/questions.json b/assets/layers/questions/questions.json index 1bdd43127c..58e8131c04 100644 --- a/assets/layers/questions/questions.json +++ b/assets/layers/questions/questions.json @@ -1105,26 +1105,7 @@ }, { "or": [ - "_country=at", - "_country=be", - "_country=cy", - "_country=de", - "_country=ee", - "_country=es", - "_country=fi", - "_country=fr", - "_country=gr", - "_country=hr", - "_country=ie", - "_country=it", - "_country=lt", - "_country=lu", - "_country=lv", - "_country=mt", - "_country=nl", - "_country=pt", - "_country=si", - "_country=sk" + "_currency=EUR" ] } ] @@ -1156,7 +1137,8 @@ "es": "Se aceptan monedas de 1 céntimo", "cs": "Jsou přijímány mince v hodnotě 1 centu", "id": "1 koin sen diterima" - } + }, + "hideInAnswer": "_currency!~.*EUR.*" }, { "if": "payment:coins:denominations=0.02 EUR", @@ -1172,7 +1154,8 @@ "es": "Se aceptan monedas de 2 céntimos", "cs": "Jsou přijímány mince v hodnotě 2 centů", "id": "Koin 2 sen diterima" - } + }, + "hideInAnswer": "_currency!~.*EUR.*" }, { "if": "payment:coins:denominations=0.05 EUR", @@ -1188,7 +1171,8 @@ "es": "Se aceptan monedas de 5 céntimos", "cs": "Jsou přijímány mince v hodnotě 5 centů", "id": "Koin 5 sen diterima" - } + }, + "hideInAnswer": "_currency!~.*EUR.*" }, { "if": "payment:coins:denominations=0.10 EUR", @@ -1204,7 +1188,8 @@ "es": "Se aceptan monedas de 10 céntimos", "cs": "Jsou přijímány mince v hodnotě 10 centů", "id": "Koin 10 sen diterima" - } + }, + "hideInAnswer": "_currency!~.*EUR.*" }, { "if": "payment:coins:denominations=0.20 EUR", @@ -1220,7 +1205,8 @@ "es": "Se aceptan monedas de 20 céntimos", "cs": "Jsou přijímány mince v hodnotě 20 centů", "id": "Koin 20 sen diterima" - } + }, + "hideInAnswer": "_currency!~.*EUR.*" }, { "if": "payment:coins:denominations=0.50 EUR", @@ -1236,7 +1222,8 @@ "es": "Se aceptan monedas de 50 céntimos", "cs": "Jsou přijímány mince v hodnotě 50 centů", "id": "Koin 50 sen diterima" - } + }, + "hideInAnswer": "_currency!~.*EUR.*" }, { "if": "payment:coins:denominations=1 EUR", @@ -1251,7 +1238,8 @@ "ca": "S'accepten monedes de 1 euro", "es": "Se aceptan monedas de 1 euro", "cs": "Jsou přijímány mince v hodnotě 1 eura" - } + }, + "hideInAnswer": "_currency!~.*EUR.*" }, { "if": "payment:coins:denominations=2 EUR", @@ -1266,7 +1254,8 @@ "ca": "S'accepten monedes de 2 euros", "es": "Se aceptan monedas de 2 euros", "cs": "Jsou přijímány mince v hodnotě 2 euro" - } + }, + "hideInAnswer": "_currency!~.*EUR.*" } ] }, @@ -1282,26 +1271,7 @@ }, { "or": [ - "_country=at", - "_country=be", - "_country=cy", - "_country=de", - "_country=ee", - "_country=es", - "_country=fi", - "_country=fr", - "_country=gr", - "_country=hr", - "_country=ie", - "_country=it", - "_country=lt", - "_country=lu", - "_country=lv", - "_country=mt", - "_country=nl", - "_country=pt", - "_country=si", - "_country=sk" + "_currency=EUR" ] } ] @@ -1330,7 +1300,8 @@ "cs": "Jsou přijímány bankovky v hodnotě 5 euro", "ca": "S'accepten billets de 5 euros", "fr": "Les billets de 5 euros ne sont pas acceptés" - } + }, + "hideInAnswer": "_currency!~.*EUR.*" }, { "if": "payment:notes:denominations=10 EUR", @@ -1344,7 +1315,8 @@ "cs": "Jsou přijímány bankovky v hodnotě 10 euro", "ca": "S'accepten bitllets de 10 euros", "fr": "Les billets de 10 euros sont acceptés" - } + }, + "hideInAnswer": "_currency!~.*EUR.*" }, { "if": "payment:notes:denominations=20 EUR", @@ -1358,7 +1330,8 @@ "cs": "Jsou přijímány bankovky v hodnotě 20 euro", "ca": "S'accepten bitllets de 20 euros", "fr": "Les billets de 20 euros sont acceptés" - } + }, + "hideInAnswer": "_currency!~.*EUR.*" }, { "if": "payment:notes:denominations=50 EUR", @@ -1372,7 +1345,8 @@ "cs": "Jsou přijímány bankovky v hodnotě 50 euro", "ca": "S'accepten bitllets de 50 euros", "fr": "Les billets de 50 euros sont acceptés" - } + }, + "hideInAnswer": "_currency!~.*EUR.*" }, { "if": "payment:notes:denominations=100 EUR", @@ -1386,7 +1360,8 @@ "cs": "Jsou přijímány bankovky v hodnotě 100 euro", "ca": "S'accepten bitllets de 100 euros", "fr": "Les billets de 100 euros sont acceptés" - } + }, + "hideInAnswer": "_currency!~.*EUR.*" }, { "if": "payment:notes:denominations=200 EUR", @@ -1400,7 +1375,8 @@ "cs": "Jsou přijímány bankovky v hodnotě 200 euro", "ca": "S'accepten bitllets de 200 euros", "fr": "Les billets de 200 euros sont acceptés" - } + }, + "hideInAnswer": "_currency!~.*EUR.*" }, { "if": "payment:notes:denominations=500 EUR", @@ -1414,7 +1390,8 @@ "cs": "Jsou přijímány bankovky v hodnotě 500 euro", "ca": "S'accepten bitllets de 500 euros", "fr": "Les billets de 500 euros sont acceptés" - } + }, + "hideInAnswer": "_currency!~.*EUR.*" } ] }, @@ -2175,4 +2152,4 @@ ] } ] -} +} \ No newline at end of file diff --git a/assets/themes/elongated_coin/elongated_coin.json b/assets/themes/elongated_coin/elongated_coin.json index 086a40daae..0c3d5fcf55 100644 --- a/assets/themes/elongated_coin/elongated_coin.json +++ b/assets/themes/elongated_coin/elongated_coin.json @@ -6,7 +6,6 @@ "description": { "en": "Find penny presses to create your own elongated coins." }, - "hideFromOverview": true, "icon": "./assets/themes/elongated_coin/penny.svg", "layers": [ { @@ -80,6 +79,13 @@ "question": { "en": "What coin is used for pressing?" }, + "freeform": { + "key": "coin:type", + "type": "string", + "placeholder": { + "en": "Coin type (e.g. 10cent)" + } + }, "mappings": [ { "if": "coin:type=2cent", @@ -98,14 +104,31 @@ "then": { "en": "This penny press uses a 10 cent coin for pressing." } + }, + { + "if": "coin:type=25cent", + "then": { + "en": "This penny press uses a 25 cent coin for pressing." + }, + "hideInAnswer": "_currency!~.*USD.*" + }, + { + "if": "coin:type=50cent", + "then": { + "en": "This penny press uses a 50 cent coin for pressing." + }, + "hideInAnswer": "_currency!~.*USD.*" } - ] + ], + "render": { + "en": "This penny press uses a {coin:type} coin for pressing." + } }, "website", { "id": "charge", "question": { - "en": "How much does it cost to press a penny?" + "en": "How much does it cost to press a coin?" }, "freeform": { "key": "charge", @@ -117,18 +140,20 @@ { "if": "charge=1 EUR", "then": { - "en": "It costs 1 euro to press a penny." - } + "en": "It costs 1 euro to press a coin." + }, + "hideInAnswer": "_currency!~.*EUR.*" }, { "if": "charge=2 EUR", "then": { - "en": "It costs 2 euros to press a penny." - } + "en": "It costs 2 euros to press a coin." + }, + "hideInAnswer": "_currency!~.*EUR.*" } ], "render": { - "en": "It costs {charge} to press a penny." + "en": "It costs {charge} to press a coin." } }, "denominations-coins", diff --git a/package-lock.json b/package-lock.json index 6d695a8bad..69493ba474 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "mapcomplete", - "version": "0.30.9", + "version": "0.31.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "mapcomplete", - "version": "0.30.9", + "version": "0.31.0", "license": "GPL-3.0-or-later", "dependencies": { "@rgossiaux/svelte-headlessui": "^1.0.2", @@ -21,6 +21,7 @@ "@types/showdown": "^2.0.0", "chart.js": "^3.8.0", "country-language": "^0.1.7", + "country-to-currency": "^1.0.10", "csv-parse": "^5.1.0", "doctest-ts-improved": "^0.8.8", "email-validator": "^2.0.4", @@ -4907,6 +4908,11 @@ "node": "*" } }, + "node_modules/country-to-currency": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/country-to-currency/-/country-to-currency-1.0.10.tgz", + "integrity": "sha512-M/RiNYiJ2Xp1okxqlINc/aTPXbxeYItgd0xTD4dtxREce8vjRqV3Vehrulcy8IimV/Of0wG5f//YSJp4KyGZFA==" + }, "node_modules/create-require": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", @@ -16028,6 +16034,11 @@ "underscore.deep": "~0.5.1" } }, + "country-to-currency": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/country-to-currency/-/country-to-currency-1.0.10.tgz", + "integrity": "sha512-M/RiNYiJ2Xp1okxqlINc/aTPXbxeYItgd0xTD4dtxREce8vjRqV3Vehrulcy8IimV/Of0wG5f//YSJp4KyGZFA==" + }, "create-require": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", diff --git a/package.json b/package.json index 6c36d1f20e..634428003d 100644 --- a/package.json +++ b/package.json @@ -73,6 +73,7 @@ "@types/showdown": "^2.0.0", "chart.js": "^3.8.0", "country-language": "^0.1.7", + "country-to-currency": "^1.0.10", "csv-parse": "^5.1.0", "doctest-ts-improved": "^0.8.8", "email-validator": "^2.0.4", diff --git a/scripts/generateDocs.ts b/scripts/generateDocs.ts index 9d0e90c48a..2813d3a8a9 100644 --- a/scripts/generateDocs.ts +++ b/scripts/generateDocs.ts @@ -1,30 +1,30 @@ -import Combine from "../UI/Base/Combine" -import BaseUIElement from "../UI/BaseUIElement" +import Combine from "../src/UI/Base/Combine" +import BaseUIElement from "../src/UI/BaseUIElement" import { existsSync, mkdirSync, writeFile, writeFileSync } from "fs" -import { AllKnownLayouts } from "../Customizations/AllKnownLayouts" -import TableOfContents from "../UI/Base/TableOfContents" -import SimpleMetaTaggers from "../Logic/SimpleMetaTagger" -import SpecialVisualizations from "../UI/SpecialVisualizations" -import { ExtraFunctions } from "../Logic/ExtraFunctions" -import Title from "../UI/Base/Title" -import QueryParameterDocumentation from "../UI/QueryParameterDocumentation" +import { AllKnownLayouts } from "../src/Customizations/AllKnownLayouts" +import TableOfContents from "../src/UI/Base/TableOfContents" +import SimpleMetaTaggers from "../src/Logic/SimpleMetaTagger" +import SpecialVisualizations from "../src/UI/SpecialVisualizations" +import { ExtraFunctions } from "../src/Logic/ExtraFunctions" +import Title from "../src/UI/Base/Title" +import QueryParameterDocumentation from "../src/UI/QueryParameterDocumentation" import ScriptUtils from "./ScriptUtils" -import List from "../UI/Base/List" -import SharedTagRenderings from "../Customizations/SharedTagRenderings" -import Translations from "../UI/i18n/Translations" +import List from "../src/UI/Base/List" +import SharedTagRenderings from "../src/Customizations/SharedTagRenderings" +import Translations from "../src/UI/i18n/Translations" import themeOverview from "../assets/generated/theme_overview.json" -import LayoutConfig from "../Models/ThemeConfig/LayoutConfig" +import LayoutConfig from "../src/Models/ThemeConfig/LayoutConfig" import bookcases from "../assets/generated/themes/bookcases.json" import fakedom from "fake-dom" -import Hotkeys from "../UI/Base/Hotkeys" -import { QueryParameters } from "../Logic/Web/QueryParameters" -import Link from "../UI/Base/Link" -import Constants from "../Models/Constants" -import LayerConfig from "../Models/ThemeConfig/LayerConfig" -import DependencyCalculator from "../Models/ThemeConfig/DependencyCalculator" -import { AllSharedLayers } from "../Customizations/AllSharedLayers" -import ThemeViewState from "../Models/ThemeViewState" -import Validators from "../UI/InputElement/Validators" +import Hotkeys from "../src/UI/Base/Hotkeys" +import { QueryParameters } from "../src/Logic/Web/QueryParameters" +import Link from "../src/UI/Base/Link" +import Constants from "../src/Models/Constants" +import LayerConfig from "../src/Models/ThemeConfig/LayerConfig" +import DependencyCalculator from "../src/Models/ThemeConfig/DependencyCalculator" +import { AllSharedLayers } from "../src/Customizations/AllSharedLayers" +import ThemeViewState from "../src/Models/ThemeViewState" +import Validators from "../src/UI/InputElement/Validators" function WriteFile( filename, @@ -335,7 +335,7 @@ Array.from(AllKnownLayouts.allKnownLayouts.values()).map((theme) => { ) }) WriteFile("./Docs/SpecialRenderings.md", SpecialVisualizations.HelpMessage(), [ - "UI/SpecialVisualizations.ts", + "src/UI/SpecialVisualizations.ts", ]) WriteFile( "./Docs/CalculatedTags.md", @@ -344,15 +344,17 @@ WriteFile( SimpleMetaTaggers.HelpText(), ExtraFunctions.HelpText(), ]).SetClass("flex-col"), - ["Logic/SimpleMetaTagger.ts", "Logic/ExtraFunctions.ts"] + ["src/Logic/SimpleMetaTagger.ts", "src/Logic/ExtraFunctions.ts"] ) WriteFile("./Docs/SpecialInputElements.md", Validators.HelpText(), [ - "UI/InputElement/Validators.ts", + "src/UI/InputElement/Validators.ts", +]) +WriteFile("./Docs/BuiltinLayers.md", GenLayerOverviewText(), [ + "src/Customizations/AllKnownLayouts.ts", ]) -WriteFile("./Docs/BuiltinLayers.md", GenLayerOverviewText(), ["Customizations/AllKnownLayouts.ts"]) WriteFile("./Docs/BuiltinQuestions.md", SharedTagRenderings.HelpText(), [ - "Customizations/SharedTagRenderings.ts", - "assets/tagRenderings/questions.json", + "src/Customizations/SharedTagRenderings.ts", + "assets/layers/questions/questions.json", ]) { @@ -402,8 +404,8 @@ WriteFile("./Docs/BuiltinQuestions.md", SharedTagRenderings.HelpText(), [ } WriteFile("./Docs/URL_Parameters.md", QueryParameterDocumentation.GenerateQueryParameterDocs(), [ - "Logic/Web/QueryParameters.ts", - "UI/QueryParameterDocumentation.ts", + "src/Logic/Web/QueryParameters.ts", + "src/UI/QueryParameterDocumentation.ts", ]) if (fakedom === undefined || window === undefined) { throw "FakeDom not initialized" diff --git a/scripts/generateTaginfoProjectFiles.ts b/scripts/generateTaginfoProjectFiles.ts index 19aa027359..63743ac5cb 100644 --- a/scripts/generateTaginfoProjectFiles.ts +++ b/scripts/generateTaginfoProjectFiles.ts @@ -1,11 +1,11 @@ -import { AllKnownLayouts } from "../Customizations/AllKnownLayouts" -import Locale from "../UI/i18n/Locale" -import { Translation } from "../UI/i18n/Translation" +import { AllKnownLayouts } from "../src/Customizations/AllKnownLayouts" +import Locale from "../src/UI/i18n/Locale" +import { Translation } from "../src/UI/i18n/Translation" import { readFileSync, writeFileSync } from "fs" -import LayoutConfig from "../Models/ThemeConfig/LayoutConfig" -import LayerConfig from "../Models/ThemeConfig/LayerConfig" -import { Utils } from "../Utils" -import TagRenderingConfig from "../Models/ThemeConfig/TagRenderingConfig" +import LayoutConfig from "../src/Models/ThemeConfig/LayoutConfig" +import LayerConfig from "../src/Models/ThemeConfig/LayerConfig" +import { Utils } from "../src/Utils" +import TagRenderingConfig from "../src/Models/ThemeConfig/TagRenderingConfig" /** * Generates all the files in "Docs/TagInfo". These are picked up by the taginfo project, showing a link to the mapcomplete theme if the key is used diff --git a/src/Logic/SimpleMetaTagger.ts b/src/Logic/SimpleMetaTagger.ts index fa6f38dca3..d0aea0ebef 100644 --- a/src/Logic/SimpleMetaTagger.ts +++ b/src/Logic/SimpleMetaTagger.ts @@ -14,6 +14,7 @@ import { OsmTags } from "../Models/OsmFeature" import { UIEventSource } from "./UIEventSource" import LayoutConfig from "../Models/ThemeConfig/LayoutConfig" import OsmObjectDownloader from "./Osm/OsmObjectDownloader" +import countryToCurrency from "country-to-currency" /** * All elements that are needed to perform metatagging @@ -583,6 +584,47 @@ export default class SimpleMetaTaggers { } ) + private static currency = new InlineMetaTagger( + { + keys: ["_currency"], + doc: "Adds the currency valid for the object, based on country or explicit tagging. Can be a single currency or a semicolon-separated list of currencies. Empty if no currency is found.", + isLazy: true, + }, + (feature) => { + Utils.AddLazyProperty(feature.properties, "_currency", () => { + // Initialize a list of currencies + const currencies = {} + + // Check if there are any currency:XXX tags, add them to the map + for (const key in feature.properties) { + if (key.startsWith("currency:")) { + if (feature.properties[key] === "yes") { + currencies[key.slice(9)] = true + } else { + currencies[key.slice(9)] = false + } + } + } + + // Determine the default currency for the country + const defaultCurrency = countryToCurrency[feature.properties._country.toUpperCase()] + + // If the default currency is not in the list, add it + if (defaultCurrency && !currencies[defaultCurrency]) { + currencies[defaultCurrency] = true + } + + if (currencies) { + return Object.keys(currencies) + .filter((key) => currencies[key]) + .join(";") + } + return "" + }) + return true + } + ) + public static metatags: SimpleMetaTagger[] = [ SimpleMetaTaggers.latlon, SimpleMetaTaggers.layerInfo, @@ -601,6 +643,7 @@ export default class SimpleMetaTaggers { SimpleMetaTaggers.levels, SimpleMetaTaggers.referencingWays, SimpleMetaTaggers.timeSinceLastEdit, + SimpleMetaTaggers.currency, ] /**