diff --git a/assets/advanced_question_catalog/definition.json b/assets/advanced_question_catalog/definition.json index 32102fb0..eff300c6 100644 --- a/assets/advanced_question_catalog/definition.json +++ b/assets/advanced_question_catalog/definition.json @@ -59,7 +59,14 @@ "public_transport": "platform", "ref:IFOPT": false, "noref:IFOPT": false - } + }, + "!parent": [ + { + "osm_tags": { + "public_transport": "platform" + } + } + ] } ] }, diff --git a/assets/question_catalog/definition.json b/assets/question_catalog/definition.json index 8d205785..84401631 100644 --- a/assets/question_catalog/definition.json +++ b/assets/question_catalog/definition.json @@ -1,4 +1,90 @@ [ + { + "question": { + "name": "@transportationModesName", + "text": "@transportationModesText" + }, + "answer": { + "type": "MultiList", + "input": [ + { + "name": "@transportationModesBusOption", + "image": "assets/question_catalog/images/bus.jpg", + "osm_tags": { + "bus": "yes" + } + }, + { + "name": "@transportationModesTramOption", + "image": "assets/question_catalog/images/tram.jpg", + "osm_tags": { + "tram": "yes" + } + }, + { + "name": "@transportationModesTrainOptionName", + "image": "assets/question_catalog/images/train.jpg", + "description": "@transportationModesTrainOptionDescription", + "osm_tags": { + "train": "yes" + } + }, + { + "name": "@transportationModesLightRailOptionName", + "image": "assets/question_catalog/images/lightrail.jpg", + "description": "@transportationModesLightRailOptionDescription", + "osm_tags": { + "light_rail": "yes" + } + }, + { + "name":"@transportationModesSubwayOption", + "image": "assets/question_catalog/images/subway.jpg", + "osm_tags": { + "subway": "yes" + } + }, + { + "name": "@transportationModesMonorailOptionName", + "image": "assets/question_catalog/images/monorail.jpg", + "description": "@transportationModesMonorailOptionDescription", + "osm_tags": { + "monorail": "yes" + } + } + ], + "constructor": { + "bus": ["COALESCE", "$input"], + "tram": ["COALESCE", "$input"], + "train": ["COALESCE", "$input"], + "light_rail": ["COALESCE", "$input"], + "subway": ["COALESCE", "$input"], + "monorail": ["COALESCE", "$input"] + } + }, + "conditions": [ + { + "osm_tags": { + "public_transport": "platform", + "bus": false, + "ferry": false, + "light_rail": false, + "monorail": false, + "subway": false, + "train": false, + "tram": false, + "trolleybus": false + }, + "!parent": [ + { + "osm_tags": { + "public_transport": "platform" + } + } + ] + } + ] + }, { "question": { "name": "@operatorName", @@ -417,8 +503,7 @@ "text": "@stopCoveredAreaText", "image": [ "assets/question_catalog/images/platform_shelter_1.jpg", - "assets/question_catalog/images/platform_shelter_2.jpg", - "assets/question_catalog/images/platform_shelter_3.jpg" + "assets/question_catalog/images/platform_shelter_2.jpg" ] }, "answer": { @@ -1030,7 +1115,7 @@ "conditions": [ { "osm_tags": { - "platform_lift": "yes", + "platform_lift": ["yes", "vertical"], "platform_lift:portable": "yes", "platform_lift:maxlength:physical": false } @@ -1063,7 +1148,7 @@ "conditions": [ { "osm_tags": { - "platform_lift": "yes", + "platform_lift": ["yes", "vertical"], "platform_lift:portable": "yes", "platform_lift:maxweight": false } @@ -2067,7 +2152,7 @@ { "question": { "name": "@cycleBarrierSpacingName", - "text": "@cycleBarrierSpacingTex", + "text": "@cycleBarrierSpacingText", "image": [ "assets/question_catalog/images/cycle_barrier_double_spacing.png", "assets/question_catalog/images/cycle_barrier_triple_spacing.png" @@ -2174,9 +2259,11 @@ "conditions": [ { "osm_tags": { - "platform_lift": "yes", + "highway": "steps", + "platform_lift": ["yes", "vertical", "inclined"], "platform_lift:maxlength:physical": false - } + }, + "osm_element": "OpenWay" } ] }, @@ -2249,9 +2336,11 @@ "conditions": [ { "osm_tags": { - "platform_lift": "yes", + "highway": "steps", + "platform_lift": ["yes", "vertical", "inclined"], "platform_lift:maxwidth:physical ": false - } + }, + "osm_element": "OpenWay" } ] }, @@ -2435,7 +2524,7 @@ "type": "List", "input": [ { - "name": "J@stairsTactilePavingBothOption", + "name": "@stairsTactilePavingBothOption", "image": "assets/question_catalog/images/steps_tactile_paving_yes.jpg", "osm_tags": { "tactile_paving": "yes" @@ -2468,6 +2557,7 @@ { "osm_tags": { "highway": "steps", + "conveying": ["no", false], "tactile_paving": false }, "osm_element": "OpenWay" @@ -3230,91 +3320,5 @@ "osm_element": "Node" } ] - }, - { - "question": { - "name": "@tranportationModesName", - "text": "@tranportationModesText" - }, - "answer": { - "type": "MultiList", - "input": [ - { - "name": "@tranportationModesBusOption", - "image": "assets/question_catalog/images/bus.jpg", - "osm_tags": { - "bus": "yes" - } - }, - { - "name": "@tranportationModesTramOption", - "image": "assets/question_catalog/images/tram.jpg", - "osm_tags": { - "tram": "yes" - } - }, - { - "name": "@tranportationModesTrainOptionName", - "image": "assets/question_catalog/images/train.jpg", - "description": "@tranportationModesTrainOptionDescription", - "osm_tags": { - "train": "yes" - } - }, - { - "name": "@tranportationModesLightRailOptionName", - "image": "assets/question_catalog/images/lightrail.jpg", - "description": "@tranportationModesLightRailOptionDescription", - "osm_tags": { - "light_rail": "yes" - } - }, - { - "name":"@tranportationModesSubwayOption", - "image": "assets/question_catalog/images/subway.jpg", - "osm_tags": { - "subway": "yes" - } - }, - { - "name": "@tranportationModesMonorailOptionName", - "image": "assets/question_catalog/images/monorail.jpg", - "description": "@tranportationModesMonorailOptionDescription", - "osm_tags": { - "monorail": "yes" - } - } - ], - "constructor": { - "bus": ["COALESCE", "$input"], - "tram": ["COALESCE", "$input"], - "train": ["COALESCE", "$input"], - "light_rail": ["COALESCE", "$input"], - "subway": ["COALESCE", "$input"], - "monorail": ["COALESCE", "$input"] - } - }, - "conditions": [ - { - "osm_tags": { - "public_transport": "platform", - "bus": false, - "ferry": false, - "light_rail": false, - "monorail": false, - "subway": false, - "train": false, - "tram": false, - "trolleybus": false - }, - "!parent": [ - { - "osm_tags": { - "public_transport": "platform" - } - } - ] - } - ] } ] \ No newline at end of file diff --git a/assets/question_catalog/locales/de.arb b/assets/question_catalog/locales/de.arb index fe7ac734..72333f26 100644 --- a/assets/question_catalog/locales/de.arb +++ b/assets/question_catalog/locales/de.arb @@ -68,7 +68,7 @@ "@toiletAccessibilityEveryoneOptionDescription" : {}, "toiletAccessibilityNoWheelchairOptionName" : "Nicht für Rollstuhlfahrende", "@toiletAccessibilityNoWheelchairOptionName" : {}, - "toiletAccessibilityNoWheelchairOptionDescription" : "Die Toiletten sind nicht rollstuhlgerecht. Rollstuhlfahrernde haben keine Zugangsmöglichkeiten.", + "toiletAccessibilityNoWheelchairOptionDescription" : "Die Toiletten sind nicht rollstuhlgerecht. Rollstuhlfahrende haben keine Zugangsmöglichkeiten.", "@toiletAccessibilityNoWheelchairOptionDescription" : {}, "toiletFeesName" : "Toiletten-Gebühren", "@toiletFeesName" : {}, @@ -152,13 +152,13 @@ "@portableRampName" : {}, "portableRampText" : "Gibt es eine bewegbare Rollstuhl-Rampe?", "@portableRampText" : {}, - "portableRampDescription" : "Bahnsteiggebundene Rampen sind bewegbar und helfen beim Ein- und Ausstieg von Rollstuhlfahrenden zur Überwindung eines Spalts bzw. von Stufen.", + "portableRampDescription" : "Bewegbare Rampen helfen Rollstuhlfahrenden bei der Überwindung eines Spalts bzw. von Stufen (beim Ein- und Ausstieg).", "@portableRampDescription" : {}, "portableRampLengthName" : "Rampen-Länge", "@portableRampLengthName" : {}, "portableRampLengthText" : "Wie lang ist die bewegbare Rollstuhl-Rampe?", "@portableRampLengthText" : {}, - "portableRampLengthDescription" : "Bahnsteiggebundene Rampen sind bewegbar und helfen beim Ein- und Ausstieg von Rollstuhlfahrenden zur Überwindung eines Spalts bzw. von Stufen.", + "portableRampLengthDescription" : "Bewegbare Rampen helfen Rollstuhlfahrenden bei der Überwindung eines Spalts bzw. von Stufen (beim Ein- und Ausstieg).", "@portableRampLengthDescription" : {}, "portableRampLengthPlaceholder" : "Rampenlänge", "@portableRampLengthPlaceholder" : {}, @@ -166,7 +166,7 @@ "@portableRampLoadCapacityName" : {}, "portableRampLoadCapacityText" : "Was ist die maximale Tragfähigkeit der bewegbaren Rampe?", "@portableRampLoadCapacityText" : {}, - "portableRampLoadCapacityDescription" : "Bahnsteiggebundene Rampen sind bewegbar und helfen beim Ein- und Ausstieg von Rollstuhlfahrenden zur Überwindung eines Spalts bzw. von Stufen.", + "portableRampLoadCapacityDescription" : "Bewegbare Rampen helfen Rollstuhlfahrenden bei der Überwindung eines Spalts bzw. von Stufen (beim Ein- und Ausstieg).", "@portableRampLoadCapacityDescription" : {}, "portableRampLoadCapacityPlaceholder" : "Tragfähigkeit", "@portableRampLoadCapacityPlaceholder" : {}, @@ -174,13 +174,13 @@ "@portableLiftName" : {}, "portableLiftText" : "Gibt es einen bewegbaren Hublift für Rollstuhlfahrende?", "@portableLiftText" : {}, - "portableLiftDescription" : "Bahnsteiggebundene Hublifte sind bewegbar und helfen beim Ein- und Ausstieg von Rollstuhlfahrenden zur Überwindung eines Spalts bzw. von Stufen.", + "portableLiftDescription" : "Bewegbare Hublifte helfen Rollstuhlfahrenden bei der Überwindung eines Spalts bzw. von Stufen (beim Ein- und Ausstieg).", "@portableLiftDescription" : {}, "portableLiftLengthName" : "Hublift-Stellflächenlänge", "@portableLiftLengthName" : {}, "portableLiftLengthText" : "Wie lang ist die Stellfläche des bewegbaren Hublifts?", "@portableLiftLengthText" : {}, - "portableLiftLengthDescription" : "Bahnsteiggebundene Hublifte sind bewegbar und helfen beim Ein- und Ausstieg von Rollstuhlfahrenden zur Überwindung eines Spalts bzw. von Stufen.", + "portableLiftLengthDescription" : "Bewegbare Hublifte helfen Rollstuhlfahrenden bei der Überwindung eines Spalts bzw. von Stufen (beim Ein- und Ausstieg).", "@portableLiftLengthDescription" : {}, "portableLiftLengthPlaceholder" : "Stellflächenlänge", "@portableLiftLengthPlaceholder" : {}, @@ -188,7 +188,7 @@ "@portableLiftLoadCapacityName" : {}, "portableLiftLoadCapacityText" : "Was ist die maximale Tragfähigkeit des bewegbaren Hublifts?", "@portableLiftLoadCapacityText" : {}, - "portableLiftLoadCapacityDescription" : "Bahnsteiggebundene Hublifte sind bewegbar und helfen beim Ein- und Ausstieg von Rollstuhlfahrenden zur Überwindung eines Spalts bzw. von Stufen.", + "portableLiftLoadCapacityDescription" : "Bewegbare Hublifte helfen Rollstuhlfahrenden bei der Überwindung eines Spalts bzw. von Stufen (beim Ein- und Ausstieg).", "@portableLiftLoadCapacityDescription" : {}, "portableLiftLoadCapacityPlaceholder" : "Tragfähigkeit", "@portableLiftLoadCapacityPlaceholder" : {}, @@ -526,28 +526,28 @@ "@crossingGroundIndicatorText" : {}, "crossingGroundIndicatorDescription" : "Bodenindikatoren dienen vor allem Sehbehinderten als Warnung vor abgesenkten Bordsteinen oder Straßenüberquerungen und verhindern so ein unbewusstes Betreten der Fahrbahn.", "@crossingGroundIndicatorDescription" : {}, - "tranportationModesName" : "Verkehrsmittel", - "@tranportationModesName" : {}, - "tranportationModesText" : "Welche Verkehrsmittel halten an dieser Haltestelle?", - "@tranportationModesText" : {}, - "tranportationModesBusOption" : "Bus", - "@tranportationModesBusOption" : {}, - "tranportationModesTramOption" : "Straßenbahn", - "@tranportationModesTramOption" : {}, - "tranportationModesTrainOptionName" : "Zug", - "@tranportationModesTrainOptionName" : {}, - "tranportationModesTrainOptionDescription" : "Hierunter sind sowohl Züge für den Nahverkehr (inkl. S-Bahnen) als auch Fernverkehr zu verstehen.", - "@tranportationModesTrainOptionDescription" : {}, - "tranportationModesLightRailOptionName" : "Leichtbahn", - "@tranportationModesLightRailOptionName" : {}, - "tranportationModesLightRailOptionDescription" : "Eine Leichtbahn, auch Stadtbahn genannt, ist eine Zwischenstufe zwischen Straßenbahn und Zug. Sie verbindet oft ländliche Gebiete mit der Stadt und sind hochfluriger als Straßenbahnen.", - "@tranportationModesLightRailOptionDescription" : {}, - "tranportationModesSubwayOption" : "U-Bahn", - "@tranportationModesSubwayOption" : {}, - "tranportationModesMonorailOptionName" : "Einschienenbahn", - "@tranportationModesMonorailOptionName" : {}, - "tranportationModesMonorailOptionDescription" : "Eine Einschienenbahn fährt meistens über der Straßenebene und hat keine sichtbaren Räder.", - "@tranportationModesMonorailOptionDescription" : {}, + "transportationModesName" : "Verkehrsmittel", + "@transportationModesName" : {}, + "transportationModesText" : "Welche Verkehrsmittel halten an dieser Haltestelle?", + "@transportationModesText" : {}, + "transportationModesBusOption" : "Bus", + "@transportationModesBusOption" : {}, + "transportationModesTramOption" : "Straßenbahn", + "@transportationModesTramOption" : {}, + "transportationModesTrainOptionName" : "Zug", + "@transportationModesTrainOptionName" : {}, + "transportationModesTrainOptionDescription" : "Hierunter sind sowohl Züge für den Nahverkehr (inkl. S-Bahnen) als auch Fernverkehr zu verstehen.", + "@transportationModesTrainOptionDescription" : {}, + "transportationModesLightRailOptionName" : "Leichtbahn", + "@transportationModesLightRailOptionName" : {}, + "transportationModesLightRailOptionDescription" : "Eine Leichtbahn, auch Stadtbahn genannt, ist eine Zwischenstufe zwischen Straßenbahn und Zug. Sie verbindet oft ländliche Gebiete mit der Stadt und sind hochfluriger als Straßenbahnen.", + "@transportationModesLightRailOptionDescription" : {}, + "transportationModesSubwayOption" : "U-Bahn", + "@transportationModesSubwayOption" : {}, + "transportationModesMonorailOptionName" : "Einschienenbahn", + "@transportationModesMonorailOptionName" : {}, + "transportationModesMonorailOptionDescription" : "Eine Einschienenbahn fährt meistens über der Straßenebene und hat keine sichtbaren Räder.", + "@transportationModesMonorailOptionDescription" : {}, "unitCentimeter" : "Zentimeter", "@unitCentimeter": {}, "unitMeter" : "Meter", diff --git a/assets/question_catalog/locales/en.arb b/assets/question_catalog/locales/en.arb index 97c88e01..28999ae8 100644 --- a/assets/question_catalog/locales/en.arb +++ b/assets/question_catalog/locales/en.arb @@ -152,13 +152,13 @@ "@portableRampName" : {}, "portableRampText" : "Is there a portable wheelchair ramp?", "@portableRampText" : {}, - "portableRampDescription" : "Platform-bound ramps are portable and help wheelchair users with on- and offboarding to overcome gaps or steps.", + "portableRampDescription" : "Portable ramps help wheelchair users to overcome gaps or steps (when getting on or off a vehicle).", "@portableRampDescription" : {}, "portableRampLengthName" : "Ramp length", "@portableRampLengthName" : {}, "portableRampLengthText" : "How long is the portable wheelchair ramp?", "@portableRampLengthText" : {}, - "portableRampLengthDescription" : "Ramps attached to platforms are portable and help wheelchair users to get on and off via a gap or steps.", + "portableRampLengthDescription" : "Portable ramps help wheelchair users to overcome gaps or steps (when getting on or off a vehicle).", "@portableRampLengthDescription" : {}, "portableRampLengthPlaceholder" : "Ramp length", "@portableRampLengthPlaceholder" : {}, @@ -166,7 +166,7 @@ "@portableRampLoadCapacityName" : {}, "portableRampLoadCapacityText" : "What is the maximum load capacity of the portable ramp?", "@portableRampLoadCapacityText" : {}, - "portableRampLoadCapacityDescription" : "Platform-bound ramps are portable and help wheelchair users with on- and offboarding to overcome gaps or steps.", + "portableRampLoadCapacityDescription" : "Portable ramps help wheelchair users to overcome gaps or steps (when getting on or off a vehicle).", "@portableRampLoadCapacityDescription" : {}, "portableRampLoadCapacityPlaceholder" : "Load capacity", "@portableRampLoadCapacityPlaceholder" : {}, @@ -174,13 +174,13 @@ "@portableLiftName" : {}, "portableLiftText" : "Is there a portable lift for wheelchair users?", "@portableLiftText" : {}, - "portableLiftDescription" : "Platform-bound lifts are portable and help wheelchair users with on- and offboarding to overcome gaps or steps.", + "portableLiftDescription" : "Portable lifts help wheelchair users to overcome gaps or steps (when getting on or off a vehicle).", "@portableLiftDescription" : {}, "portableLiftLengthName" : "Usable length of the lift", "@portableLiftLengthName" : {}, "portableLiftLengthText" : "What is the length of the portable lift's usable area?", "@portableLiftLengthText" : {}, - "portableLiftLengthDescription" : "Platform-bound lifts are portable and help wheelchair users with on- and offboarding to overcome gaps or steps.", + "portableLiftLengthDescription" : "Portable lifts help wheelchair users to overcome gaps or steps (when getting on or off a vehicle).", "@portableLiftLengthDescription" : {}, "portableLiftLengthPlaceholder" : "Length", "@portableLiftLengthPlaceholder" : {}, @@ -188,7 +188,7 @@ "@portableLiftLoadCapacityName" : {}, "portableLiftLoadCapacityText" : "What is the maximum load capacity of the portable lift?", "@portableLiftLoadCapacityText" : {}, - "portableLiftLoadCapacityDescription" : "Platform-bound lifts are portable and help wheelchair users with on- and offboarding to overcome gaps or steps.", + "portableLiftLoadCapacityDescription" : "Portable lifts help wheelchair users to overcome gaps or steps (when getting on or off a vehicle).", "@portableLiftLoadCapacityDescription" : {}, "portableLiftLoadCapacityPlaceholder" : "Load capacity", "@portableLiftLoadCapacityPlaceholder" : {}, @@ -288,7 +288,7 @@ "@stopLightName" : {}, "stopLightText" : "Is this stop lighted at night?", "@stopLightText" : {}, - "stopLightDescription" : "The stop doesn’t need to have its own lighting. It is sufficient if it is sufficiently illuminated by surrounding lamps.", + "stopLightDescription" : "The stop doesn't need to have its own lighting. It is sufficient if it is sufficiently illuminated by surrounding lamps.", "@stopLightDescription" : {}, "tactilePavingsStopName" : "Tactile paving", "@tactilePavingsStopName" : {}, @@ -526,28 +526,28 @@ "@crossingGroundIndicatorText" : {}, "crossingGroundIndicatorDescription" : "Tactile paving primarily serves as a warning to visually impaired people about lowered curbs or street crossings, thereby preventing unintentional step onto the roadway.", "@crossingGroundIndicatorDescription" : {}, - "tranportationModesName" : "Modes of transportation", - "@tranportationModesName" : {}, - "tranportationModesText" : "Which modes of transportation approach this stop?", - "@tranportationModesText" : {}, - "tranportationModesBusOption" : "Bus", - "@tranportationModesBusOption" : {}, - "tranportationModesTramOption" : "Tram", - "@tranportationModesTramOption" : {}, - "tranportationModesTrainOptionName" : "Train", - "@tranportationModesTrainOptionName" : {}, - "tranportationModesTrainOptionDescription" : "This includes both local trains (including S-Bahn trains) and long-distance trains.", - "@tranportationModesTrainOptionDescription" : {}, - "tranportationModesLightRailOptionName" : "Light rail", - "@tranportationModesLightRailOptionName" : {}, - "tranportationModesLightRailOptionDescription" : "A light railway, also known as a Stadtbahn, is an intermediate stage between a tram and a train. They often connect rural areas with the city and have a higher floor than trams.", - "@tranportationModesLightRailOptionDescription" : {}, - "tranportationModesSubwayOption" : "Subway", - "@tranportationModesSubwayOption" : {}, - "tranportationModesMonorailOptionName" : "Monorail", - "@tranportationModesMonorailOptionName" : {}, - "tranportationModesMonorailOptionDescription" : "A monorail mostly runs above street level and has no visible wheels.", - "@tranportationModesMonorailOptionDescription" : {}, + "transportationModesName" : "Modes of transportation", + "@transportationModesName" : {}, + "transportationModesText" : "Which modes of transportation approach this stop?", + "@transportationModesText" : {}, + "transportationModesBusOption" : "Bus", + "@transportationModesBusOption" : {}, + "transportationModesTramOption" : "Tram", + "@transportationModesTramOption" : {}, + "transportationModesTrainOptionName" : "Train", + "@transportationModesTrainOptionName" : {}, + "transportationModesTrainOptionDescription" : "This includes both local trains and long-distance trains.", + "@transportationModesTrainOptionDescription" : {}, + "transportationModesLightRailOptionName" : "Light rail", + "@transportationModesLightRailOptionName" : {}, + "transportationModesLightRailOptionDescription" : "A light railway is an intermediate stage between a tram and a train. They often connect rural areas with the city and have a higher floor than trams.", + "@transportationModesLightRailOptionDescription" : {}, + "transportationModesSubwayOption" : "Subway", + "@transportationModesSubwayOption" : {}, + "transportationModesMonorailOptionName" : "Monorail", + "@transportationModesMonorailOptionName" : {}, + "transportationModesMonorailOptionDescription" : "A monorail mostly runs above street level and has no visible wheels.", + "@transportationModesMonorailOptionDescription" : {}, "unitCentimeter" : "Centimeter", "@unitCentimeter": {}, "unitMeter" : "Meter", diff --git a/lib/l10n/app_de.arb b/lib/l10n/app_de.arb index 6228e93e..91d917b9 100644 --- a/lib/l10n/app_de.arb +++ b/lib/l10n/app_de.arb @@ -22,7 +22,7 @@ "@aboutLicensePackageLabel": {}, "aboutSourceCodeLabel": "Quellcode", "@aboutSourceCodeLabel": {}, - + "helpTitle": "Hilfe", "@helpTitle": {}, "helpOnboardingLabel": "Einführung erneut anschauen", @@ -77,7 +77,7 @@ "@settingsThemeOptionLight": {}, "settingsThemeOptionDark": "Dunkel", "@settingsThemeOptionDark": {}, - + "logoutDialogTitle": "Von OSM abmelden?", "@logoutDialogTitle": {}, "logoutDialogDescription": "Wenn du dich abmeldest, kannst du keine Änderungen mehr zu OpenStreetMap hochladen.", @@ -112,6 +112,10 @@ "uploadMessageUnknownConnectionError": "Unbekannter Fehler bei der Übertragung.", "@uploadMessageUnknownConnectionError": {}, + "queryMessageServerUnavailableError": "Der Server ist nicht verfügbar oder überlastet. Versuche es später noch einmal.", + "@queryMessageServerUnavailableError": {}, + "queryMessageTooManyRequestsError": "Zu viele Serveranfragen.", + "@queryMessageTooManyRequestsError": {}, "queryMessageConnectionTimeoutError": "Fehler: Zeitüberschreitung bei der Server-Abfrage.", "@queryMessageConnectionTimeoutError": {}, "queryMessageReceiveTimeoutError": "Fehler: Zeitüberschreitung beim Datenempfang.", diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 4cb95a7b..1c8be1d8 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -153,6 +153,10 @@ "uploadMessageUnknownConnectionError": "Unknown error during transmission.", "@uploadMessageUnknownConnectionError": {}, + "queryMessageServerUnavailableError": "Server unavailable or overloaded. Try again later.", + "@queryMessageServerUnavailableError": {}, + "queryMessageTooManyRequestsError": "Too many requests to the server.", + "@queryMessageTooManyRequestsError": {}, "queryMessageConnectionTimeoutError": "Error: Server query timed out.", "@queryMessageConnectionTimeoutError": {}, "queryMessageReceiveTimeoutError": "Error: Receiving data timed out.", diff --git a/lib/models/element_processing/element_processor.dart b/lib/models/element_processing/element_processor.dart index d8441116..9198190d 100644 --- a/lib/models/element_processing/element_processor.dart +++ b/lib/models/element_processing/element_processor.dart @@ -1,3 +1,4 @@ +import 'package:collection/collection.dart'; import 'package:flutter/foundation.dart'; import 'package:osm_api/osm_api.dart'; @@ -36,44 +37,33 @@ class OSMElementProcessor { /// /// Returns all added elements and marks whether they are new or pre-existed. - Iterable<({ProcessedElement element, bool isNew})> add(OSMElementBundle elements) { - // convert to list so lazy iterable is evaluated - final nodeRecords = _addNodes(elements.nodes) - .toList(growable: false); - final wayRecords = _addWays(elements.ways) - .toList(growable: false); - final relationRecords = _addRelations(elements.relations) - .toList(growable: false); - - final newNodes = nodeRecords - .where((record) => record.isNew) - .map((record) => record.element); - final newWays = wayRecords - .where((record) => record.isNew) - .map((record) => record.element); - final newRelations = relationRecords - .where((record) => record.isNew) - .map((record) => record.element); + UnionSet<({ProcessedElement element, bool isNew})> add(OSMElementBundle elements) { + // convert to Set so lazy iterables are evaluated + // this is important since this adds the elements to the lookup tables + final nodeRecords = _addNodes(elements.nodes).toSet(); + final wayRecords = _addWays(elements.ways).toSet(); + final relationRecords = _addRelations(elements.relations).toSet(); // resolve references AFTER all elements have been added - _resolveWays(newWays); - _resolveRelations(newRelations); + _resolveWays(wayRecords.map((item) => item.element)); + _resolveRelations(relationRecords.map((item) => item.element)); // geometry calculation depends on parent/children assignment // due to inner dependencies first process nodes, then ways and then relations // also remove any elements where geometry calculation failed - _calcGeometries(newNodes) - .forEach((e) => _nodesLookUp.remove(e.id)); - _calcGeometries(newWays) - .forEach((e) => _waysLookUp.remove(e.id)); - _calcGeometries(newRelations) - .forEach((e) => _relationsLookUp.remove(e.id)); - - // don't use sync* and yield here so the above statements get evaluated even if the returned iterable isn't read - return nodeRecords - .cast<({ProcessedElement element, bool isNew})>() - .followedBy(wayRecords) - .followedBy(relationRecords); + nodeRecords.removeWhere( + (item) => _removeOnInvalidGeometry(item.element, _nodesLookUp), + ); + wayRecords.removeWhere( + (item) => _removeOnInvalidGeometry(item.element, _waysLookUp), + ); + relationRecords.removeWhere( + (item) => _removeOnInvalidGeometry(item.element, _relationsLookUp), + ); + + return UnionSet({ + nodeRecords, wayRecords, relationRecords, + }, disjoint: true); } /// Fast way to get an element by it's type and id. @@ -157,20 +147,20 @@ class OSMElementProcessor { } } - /// Lazily calculates the geometry for every element. + /// Calculates the geometry for the given element and removes the element from the given lookup table on failure. /// - /// Return all elements whose geometry calculation failed. + /// Returns `true` if geometry calculation failed. - Iterable _calcGeometries(Iterable elements) sync* { - for (final element in elements) { - try { - element.calcGeometry(); - } - // catch geometry calculation errors - catch(e) { - debugPrint(e.toString()); - yield element; - } + bool _removeOnInvalidGeometry(ProcessedElement element, Map lookupTable) { + try { + element.calcGeometry(); + return false; + } + // catch geometry calculation errors + catch(e) { + debugPrint('Remove failed geometry: $element due to ${e.toString()}'); + lookupTable.remove(element.id); + return true; } } } diff --git a/lib/screens/home.dart b/lib/screens/home.dart index a6378724..b4d8ead9 100644 --- a/lib/screens/home.dart +++ b/lib/screens/home.dart @@ -58,6 +58,7 @@ class HomeScreen extends View with PromptHandler { initialRotation: untracked(() => viewModel.storedMapRotation), minZoom: viewModel.tileLayer.minZoom.toDouble(), maxZoom: viewModel.tileLayer.maxZoom.toDouble(), + backgroundColor: Theme.of(context).colorScheme.background, ), nonRotatedChildren: [ RepaintBoundary( diff --git a/lib/utils/service_worker.dart b/lib/utils/service_worker.dart index 39941435..54487415 100644 --- a/lib/utils/service_worker.dart +++ b/lib/utils/service_worker.dart @@ -58,7 +58,7 @@ class ServiceWorkerController { final _Response response = await responsePort.first; if (response.type == _ResponseType.error) { - completer.completeError(response.data); + completer.completeError(response.data.$1, response.data.$2); } else { completer.complete(response.data); @@ -158,10 +158,10 @@ abstract class ServiceWorker { await messageHandler(message.data), )); } - catch(error) { + catch(error, stackTrace) { message.responsePort.send(_Response( _ResponseType.error, - error, + (error, stackTrace), )); } } diff --git a/lib/view_models/home_view_model.dart b/lib/view_models/home_view_model.dart index 64868826..ca9fd1ea 100644 --- a/lib/view_models/home_view_model.dart +++ b/lib/view_models/home_view_model.dart @@ -567,6 +567,19 @@ class HomeViewModel extends ViewModel with MakeTickerProvider, PromptMediator, N // query elements from loaded stop areas await loadElements(); } + on OSMUnknownException catch (e) { + if (e.errorCode == 503) { + debugPrint(e.toString()); + notifyUser(appLocale.queryMessageServerUnavailableError); + } + else if (e.errorCode == 429) { + debugPrint(e.toString()); + notifyUser(appLocale.queryMessageTooManyRequestsError); + } + else { + rethrow; + } + } on DioError catch (e) { if (e.type == DioErrorType.connectionTimeout) { notifyUser(appLocale.queryMessageConnectionTimeoutError); diff --git a/pubspec.lock b/pubspec.lock index b8af2476..de330c22 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1185,4 +1185,4 @@ packages: version: "3.1.1" sdks: dart: ">=3.0.0 <4.0.0" - flutter: ">=3.10.2" + flutter: ">=3.10.5" diff --git a/pubspec.yaml b/pubspec.yaml index 17a4422c..c48f1b44 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -12,7 +12,7 @@ environment: # The Flutter version is read in different build scripts and is used to setup the appropriate flutter toolkit. # The build processes cannot handle range notations like >=2.17.1 <3.0.0 or ^3.7.0. # Therefore it is important to always specify a fixed flutter version in that format: [0-9]+.[0-9]+.[0-9]+ - flutter: 3.10.2 + flutter: 3.10.5 dependencies: flutter: