From 11685690ed0d4929dbddde8f633fd2da8b66ddd9 Mon Sep 17 00:00:00 2001 From: Wieland <29458682+wielandb@users.noreply.github.com> Date: Wed, 15 Apr 2026 11:35:33 +0200 Subject: [PATCH 1/9] First draft for quest --- .../streetcomplete/quests/QuestsModule.kt | 2 + .../quests/oneway/AddCyclewayDirection.kt | 70 +++++++++++++++++++ .../quests/oneway/AddCyclewayDirectionForm.kt | 39 +++++++++++ .../composeResources/values-de/strings.xml | 5 +- .../composeResources/values-en/strings.xml | 3 + .../composeResources/values/strings.xml | 3 + 6 files changed, 121 insertions(+), 1 deletion(-) create mode 100644 app/src/androidMain/kotlin/de/westnordost/streetcomplete/quests/oneway/AddCyclewayDirection.kt create mode 100644 app/src/androidMain/kotlin/de/westnordost/streetcomplete/quests/oneway/AddCyclewayDirectionForm.kt diff --git a/app/src/androidMain/kotlin/de/westnordost/streetcomplete/quests/QuestsModule.kt b/app/src/androidMain/kotlin/de/westnordost/streetcomplete/quests/QuestsModule.kt index c8499669f9..fc0e173047 100644 --- a/app/src/androidMain/kotlin/de/westnordost/streetcomplete/quests/QuestsModule.kt +++ b/app/src/androidMain/kotlin/de/westnordost/streetcomplete/quests/QuestsModule.kt @@ -124,6 +124,7 @@ import de.westnordost.streetcomplete.quests.moped.AddMopedAccess import de.westnordost.streetcomplete.quests.motorcycle_parking_capacity.AddMotorcycleParkingCapacity import de.westnordost.streetcomplete.quests.motorcycle_parking_cover.AddMotorcycleParkingCover import de.westnordost.streetcomplete.quests.note_discussion.OsmNoteQuestType +import de.westnordost.streetcomplete.quests.oneway.AddCyclewayDirection import de.westnordost.streetcomplete.quests.oneway.AddOneway import de.westnordost.streetcomplete.quests.oneway.AddOnewayAerialway import de.westnordost.streetcomplete.quests.opening_hours.AddOpeningHours @@ -554,6 +555,7 @@ fun questTypeRegistry( // footways 143 to AddPathSurface(), // used by OSM Carto, BRouter, OsmAnd, OSRM, graphhopper... 144 to AddCyclewaySegregation(), // Cyclosm, Valhalla, Bike Citizens Bicycle Navigation... + 198 to AddCyclewayDirection(), 145 to AddFootwayPartSurface(), 146 to AddCyclewayPartSurface(), 147 to AddSidewalkSurface(), diff --git a/app/src/androidMain/kotlin/de/westnordost/streetcomplete/quests/oneway/AddCyclewayDirection.kt b/app/src/androidMain/kotlin/de/westnordost/streetcomplete/quests/oneway/AddCyclewayDirection.kt new file mode 100644 index 0000000000..f07f619413 --- /dev/null +++ b/app/src/androidMain/kotlin/de/westnordost/streetcomplete/quests/oneway/AddCyclewayDirection.kt @@ -0,0 +1,70 @@ +package de.westnordost.streetcomplete.quests.oneway + +import de.westnordost.streetcomplete.R +import de.westnordost.streetcomplete.data.osm.geometry.ElementGeometry +import de.westnordost.streetcomplete.data.osm.osmquests.OsmFilterQuestType +import de.westnordost.streetcomplete.data.quest.AndroidQuest +import de.westnordost.streetcomplete.data.quest.NoCountriesExcept +import de.westnordost.streetcomplete.data.user.achievements.EditTypeAchievement.BICYCLIST +import de.westnordost.streetcomplete.osm.Tags +import de.westnordost.streetcomplete.quests.oneway.OnewayAnswer.BACKWARD +import de.westnordost.streetcomplete.quests.oneway.OnewayAnswer.FORWARD +import de.westnordost.streetcomplete.quests.oneway.OnewayAnswer.NO_ONEWAY +import de.westnordost.streetcomplete.resources.Res +import de.westnordost.streetcomplete.resources.default_disabled_msg_maxspeed +import de.westnordost.streetcomplete.resources.quest_arrow_tutorial +import de.westnordost.streetcomplete.resources.quest_cycleway_direction_title + +class AddCyclewayDirection : OsmFilterQuestType(), AndroidQuest { + + override val elementFilter = """ + ways with + ( + highway = cycleway + or ( + highway ~ path|footway + and (footway = sidewalk or is_sidepath = yes) + and bicycle ~ yes|designated + ) + ) + and !oneway + and !oneway:bicycle + and area != yes + and junction != roundabout + and access !~ private|no + """ + + override val changesetComment = "Specify in which direction cyclists may ride this path" + override val wikiLink = "Key:oneway:bicycle" + override val icon = R.drawable.quest_bicycleway_oneway + override val title = Res.string.quest_cycleway_direction_title + override val hasMarkersAtEnds = true + override val achievements = listOf(BICYCLIST) + override val hint = Res.string.quest_arrow_tutorial + override val defaultDisabledMessage = Res.string.default_disabled_msg_maxspeed + override val enabledInCountries = NoCountriesExcept("DE") + + override fun createForm() = AddCyclewayDirectionForm() + + override fun applyAnswerTo( + answer: OnewayAnswer, + tags: Tags, + geometry: ElementGeometry, + timestampEdited: Long, + ) { + val key = if (tags["highway"] == "cycleway" && + tags["foot"] !in setOf("yes", "designated") && + tags["segregated"] != "yes" + ) { + "oneway" + } else { + "oneway:bicycle" + } + + tags[key] = when (answer) { + FORWARD -> "yes" + BACKWARD -> "-1" + NO_ONEWAY -> "no" + } + } +} diff --git a/app/src/androidMain/kotlin/de/westnordost/streetcomplete/quests/oneway/AddCyclewayDirectionForm.kt b/app/src/androidMain/kotlin/de/westnordost/streetcomplete/quests/oneway/AddCyclewayDirectionForm.kt new file mode 100644 index 0000000000..1a79ddbe7a --- /dev/null +++ b/app/src/androidMain/kotlin/de/westnordost/streetcomplete/quests/oneway/AddCyclewayDirectionForm.kt @@ -0,0 +1,39 @@ +package de.westnordost.streetcomplete.quests.oneway + +import androidx.compose.runtime.Composable +import androidx.compose.runtime.remember +import de.westnordost.streetcomplete.quests.AItemSelectQuestForm +import de.westnordost.streetcomplete.resources.Res +import de.westnordost.streetcomplete.resources.quest_cycleway_direction_dir +import de.westnordost.streetcomplete.resources.quest_cycleway_direction_no_oneway +import de.westnordost.streetcomplete.ui.common.item_select.ImageWithLabel +import de.westnordost.streetcomplete.ui.util.ClipCirclePainter +import kotlinx.serialization.serializer +import org.jetbrains.compose.resources.StringResource +import org.jetbrains.compose.resources.painterResource +import org.jetbrains.compose.resources.stringResource + +class AddCyclewayDirectionForm : AItemSelectQuestForm() { + + override val items = OnewayAnswer.entries + override val itemsPerRow = 3 + override val serializer = serializer() + + @Composable override fun ItemContent(item: OnewayAnswer) { + val painter = painterResource(item.icon) + ImageWithLabel( + painter = remember(painter) { ClipCirclePainter(painter) }, + label = stringResource(item.cyclewayDirectionTitle), + imageRotation = geometryRotation.floatValue - mapRotation.floatValue, + ) + } + + override fun onClickOk(selectedItem: OnewayAnswer) { + applyAnswer(selectedItem) + } +} + +private val OnewayAnswer.cyclewayDirectionTitle: StringResource get() = when (this) { + OnewayAnswer.FORWARD, OnewayAnswer.BACKWARD -> Res.string.quest_cycleway_direction_dir + OnewayAnswer.NO_ONEWAY -> Res.string.quest_cycleway_direction_no_oneway +} diff --git a/app/src/commonMain/composeResources/values-de/strings.xml b/app/src/commonMain/composeResources/values-de/strings.xml index 4263109ea9..5377b91bf4 100644 --- a/app/src/commonMain/composeResources/values-de/strings.xml +++ b/app/src/commonMain/composeResources/values-de/strings.xml @@ -699,6 +699,9 @@ Erfolge Ist dies eine Einbahnstraße? In welche Richtung? Einbahn­straße in diese Richtung Keine Einbahn­straße + In welche Richtung darf man hier mit dem Fahrrad fahren? + Nur in die Richtung + In beide Richtungen Welche Richtung führt hier nach oben? Hier nach oben Wie viele Stufen gibt es hier? @@ -1504,4 +1507,4 @@ Zum Beispiel 1,3 oder 2b,4,6. Kann man hier warm duschen? Neues OSM-Event in deiner Gegend! Neue OSM-Events in deiner Gegend - \ No newline at end of file + diff --git a/app/src/commonMain/composeResources/values-en/strings.xml b/app/src/commonMain/composeResources/values-en/strings.xml index ae6c346405..5689956812 100644 --- a/app/src/commonMain/composeResources/values-en/strings.xml +++ b/app/src/commonMain/composeResources/values-en/strings.xml @@ -1313,6 +1313,9 @@ If there are no signs along the whole street which apply for the highlighted sec Is this a one-way street? In which direction? Oneway in this direction Not a oneway + In what direction are you allowed to ride this path? + Only this way + In both directions What are the opening hours here? Are the opening hours here signed? diff --git a/app/src/commonMain/composeResources/values/strings.xml b/app/src/commonMain/composeResources/values/strings.xml index acdcfe7354..851158a97d 100644 --- a/app/src/commonMain/composeResources/values/strings.xml +++ b/app/src/commonMain/composeResources/values/strings.xml @@ -1315,6 +1315,9 @@ If there are no signs along the whole street which apply for the highlighted sec Is this a one-way street? In which direction? Oneway in this direction Not a oneway + In what direction are you allowed to ride this path? + Only this way + In both directions What are the opening hours here? Are the opening hours here signed? From 5c342e98033fdb8072a9a6321abdc2736d070673 Mon Sep 17 00:00:00 2001 From: Wieland <29458682+wielandb@users.noreply.github.com> Date: Thu, 16 Apr 2026 06:56:35 +0200 Subject: [PATCH 2/9] Update strings --- app/src/commonMain/composeResources/values-de/strings.xml | 1 + app/src/commonMain/composeResources/values-en/strings.xml | 3 +++ app/src/commonMain/composeResources/values/strings.xml | 2 ++ 3 files changed, 6 insertions(+) diff --git a/app/src/commonMain/composeResources/values-de/strings.xml b/app/src/commonMain/composeResources/values-de/strings.xml index 5377b91bf4..2bcf127bb2 100644 --- a/app/src/commonMain/composeResources/values-de/strings.xml +++ b/app/src/commonMain/composeResources/values-de/strings.xml @@ -702,6 +702,7 @@ Erfolge In welche Richtung darf man hier mit dem Fahrrad fahren? Nur in die Richtung In beide Richtungen + Dieser Aufgabentyp ist standardmäßig deaktiviert, da der Zugang für für Fahrräder auf dem Bürgersteig nur durch bestimmte Schilder am Anfang/Ende einer Straße gekennzeichnet ist. Welche Richtung führt hier nach oben? Hier nach oben Wie viele Stufen gibt es hier? diff --git a/app/src/commonMain/composeResources/values-en/strings.xml b/app/src/commonMain/composeResources/values-en/strings.xml index 5689956812..c6e0445d7d 100644 --- a/app/src/commonMain/composeResources/values-en/strings.xml +++ b/app/src/commonMain/composeResources/values-en/strings.xml @@ -1316,6 +1316,9 @@ If there are no signs along the whole street which apply for the highlighted sec In what direction are you allowed to ride this path? Only this way In both directions + + This quest type is disabled by default because bicycle access on sidewalks is only indicated by specific signs at start/end of a sidewalk. + What are the opening hours here? Are the opening hours here signed? diff --git a/app/src/commonMain/composeResources/values/strings.xml b/app/src/commonMain/composeResources/values/strings.xml index 851158a97d..c5e961e7d2 100644 --- a/app/src/commonMain/composeResources/values/strings.xml +++ b/app/src/commonMain/composeResources/values/strings.xml @@ -1319,6 +1319,8 @@ If there are no signs along the whole street which apply for the highlighted sec Only this way In both directions + This quest type is disabled by default because bicycle access on sidewalks is only indicated by specific signs at start/end of a sidewalk. + What are the opening hours here? Are the opening hours here signed? Are these opening hours still correct? From 9531030c7e1fa34c72076897a25613b77969633c Mon Sep 17 00:00:00 2001 From: Wieland <29458682+wielandb@users.noreply.github.com> Date: Thu, 16 Apr 2026 07:00:26 +0200 Subject: [PATCH 3/9] Update element selection Thanks @mcliquid for implementing the original quest in SCEE this PR is based on! --- .../streetcomplete/quests/oneway/AddCyclewayDirection.kt | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/app/src/androidMain/kotlin/de/westnordost/streetcomplete/quests/oneway/AddCyclewayDirection.kt b/app/src/androidMain/kotlin/de/westnordost/streetcomplete/quests/oneway/AddCyclewayDirection.kt index f07f619413..52023c5e67 100644 --- a/app/src/androidMain/kotlin/de/westnordost/streetcomplete/quests/oneway/AddCyclewayDirection.kt +++ b/app/src/androidMain/kotlin/de/westnordost/streetcomplete/quests/oneway/AddCyclewayDirection.kt @@ -20,12 +20,9 @@ class AddCyclewayDirection : OsmFilterQuestType(), AndroidQuest { override val elementFilter = """ ways with ( - highway = cycleway - or ( - highway ~ path|footway + (highway ~ path|footway) or (highway = cycleway) and (footway = sidewalk or is_sidepath = yes) and bicycle ~ yes|designated - ) ) and !oneway and !oneway:bicycle From a08fa7341188c9918f6ce9a30174bac9ae7b64a9 Mon Sep 17 00:00:00 2001 From: Wieland <29458682+wielandb@users.noreply.github.com> Date: Thu, 16 Apr 2026 07:01:26 +0200 Subject: [PATCH 4/9] Use updated strings --- .../streetcomplete/quests/oneway/AddCyclewayDirection.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/androidMain/kotlin/de/westnordost/streetcomplete/quests/oneway/AddCyclewayDirection.kt b/app/src/androidMain/kotlin/de/westnordost/streetcomplete/quests/oneway/AddCyclewayDirection.kt index 52023c5e67..63ff1bf84c 100644 --- a/app/src/androidMain/kotlin/de/westnordost/streetcomplete/quests/oneway/AddCyclewayDirection.kt +++ b/app/src/androidMain/kotlin/de/westnordost/streetcomplete/quests/oneway/AddCyclewayDirection.kt @@ -38,7 +38,7 @@ class AddCyclewayDirection : OsmFilterQuestType(), AndroidQuest { override val hasMarkersAtEnds = true override val achievements = listOf(BICYCLIST) override val hint = Res.string.quest_arrow_tutorial - override val defaultDisabledMessage = Res.string.default_disabled_msg_maxspeed + override val defaultDisabledMessage = Res.string.default_disabled_msg_visible_sign_bicycle_sidewalk_access override val enabledInCountries = NoCountriesExcept("DE") override fun createForm() = AddCyclewayDirectionForm() From fa8844afff3f6365eaa61d53bbcd8ef48f557cf5 Mon Sep 17 00:00:00 2001 From: Wieland <29458682+wielandb@users.noreply.github.com> Date: Thu, 16 Apr 2026 07:13:35 +0200 Subject: [PATCH 5/9] Enable quest in more countries where sidewalk-cycling is oneway by default --- .../streetcomplete/quests/oneway/AddCyclewayDirection.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/androidMain/kotlin/de/westnordost/streetcomplete/quests/oneway/AddCyclewayDirection.kt b/app/src/androidMain/kotlin/de/westnordost/streetcomplete/quests/oneway/AddCyclewayDirection.kt index 63ff1bf84c..c7c129207e 100644 --- a/app/src/androidMain/kotlin/de/westnordost/streetcomplete/quests/oneway/AddCyclewayDirection.kt +++ b/app/src/androidMain/kotlin/de/westnordost/streetcomplete/quests/oneway/AddCyclewayDirection.kt @@ -39,7 +39,7 @@ class AddCyclewayDirection : OsmFilterQuestType(), AndroidQuest { override val achievements = listOf(BICYCLIST) override val hint = Res.string.quest_arrow_tutorial override val defaultDisabledMessage = Res.string.default_disabled_msg_visible_sign_bicycle_sidewalk_access - override val enabledInCountries = NoCountriesExcept("DE") + override val enabledInCountries = NoCountriesExcept("DE", "AT", "DK", "NL", "FI", "NO") override fun createForm() = AddCyclewayDirectionForm() From b6541e3f2b98d554626c08c0541bb5ef9cd7f60d Mon Sep 17 00:00:00 2001 From: Wieland <29458682+wielandb@users.noreply.github.com> Date: Thu, 16 Apr 2026 17:49:55 +0200 Subject: [PATCH 6/9] Update app/src/androidMain/kotlin/de/westnordost/streetcomplete/quests/oneway/AddCyclewayDirection.kt Co-authored-by: Flo Edelmann --- .../streetcomplete/quests/oneway/AddCyclewayDirection.kt | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/app/src/androidMain/kotlin/de/westnordost/streetcomplete/quests/oneway/AddCyclewayDirection.kt b/app/src/androidMain/kotlin/de/westnordost/streetcomplete/quests/oneway/AddCyclewayDirection.kt index c7c129207e..f013862784 100644 --- a/app/src/androidMain/kotlin/de/westnordost/streetcomplete/quests/oneway/AddCyclewayDirection.kt +++ b/app/src/androidMain/kotlin/de/westnordost/streetcomplete/quests/oneway/AddCyclewayDirection.kt @@ -19,11 +19,9 @@ class AddCyclewayDirection : OsmFilterQuestType(), AndroidQuest { override val elementFilter = """ ways with - ( - (highway ~ path|footway) or (highway = cycleway) - and (footway = sidewalk or is_sidepath = yes) - and bicycle ~ yes|designated - ) + highway ~ path|footway|cycleway + and (footway = sidewalk or is_sidepath = yes) + and bicycle ~ yes|designated and !oneway and !oneway:bicycle and area != yes From 00b0e39eecbcfe3881ba5a29beffd0859891b060 Mon Sep 17 00:00:00 2001 From: Wieland <29458682+wielandb@users.noreply.github.com> Date: Thu, 16 Apr 2026 17:54:46 +0200 Subject: [PATCH 7/9] Update quest strings --- app/src/commonMain/composeResources/values-de/strings.xml | 4 ++-- app/src/commonMain/composeResources/values-en/strings.xml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/src/commonMain/composeResources/values-de/strings.xml b/app/src/commonMain/composeResources/values-de/strings.xml index 2bcf127bb2..9545f501df 100644 --- a/app/src/commonMain/composeResources/values-de/strings.xml +++ b/app/src/commonMain/composeResources/values-de/strings.xml @@ -699,8 +699,8 @@ Erfolge Ist dies eine Einbahnstraße? In welche Richtung? Einbahn­straße in diese Richtung Keine Einbahn­straße - In welche Richtung darf man hier mit dem Fahrrad fahren? - Nur in die Richtung + In welche Richtung darf man mit dem Fahrrad auf diesem Bürgersteig fahren? + Nur in diese Richtung In beide Richtungen Dieser Aufgabentyp ist standardmäßig deaktiviert, da der Zugang für für Fahrräder auf dem Bürgersteig nur durch bestimmte Schilder am Anfang/Ende einer Straße gekennzeichnet ist. Welche Richtung führt hier nach oben? diff --git a/app/src/commonMain/composeResources/values-en/strings.xml b/app/src/commonMain/composeResources/values-en/strings.xml index c6e0445d7d..dcaa56f371 100644 --- a/app/src/commonMain/composeResources/values-en/strings.xml +++ b/app/src/commonMain/composeResources/values-en/strings.xml @@ -1313,7 +1313,7 @@ If there are no signs along the whole street which apply for the highlighted sec Is this a one-way street? In which direction? Oneway in this direction Not a oneway - In what direction are you allowed to ride this path? + In what direction are you allowed to cycle on this sidewalk? Only this way In both directions From 913d326240cf53d9778eefc3a44cd1cfdb8535aa Mon Sep 17 00:00:00 2001 From: Wieland <29458682+wielandb@users.noreply.github.com> Date: Thu, 16 Apr 2026 17:57:34 +0200 Subject: [PATCH 8/9] Update strings.xml --- app/src/commonMain/composeResources/values/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/commonMain/composeResources/values/strings.xml b/app/src/commonMain/composeResources/values/strings.xml index c5e961e7d2..189eb9536d 100644 --- a/app/src/commonMain/composeResources/values/strings.xml +++ b/app/src/commonMain/composeResources/values/strings.xml @@ -1315,7 +1315,7 @@ If there are no signs along the whole street which apply for the highlighted sec Is this a one-way street? In which direction? Oneway in this direction Not a oneway - In what direction are you allowed to ride this path? + In what direction are you allowed to cycle on this sidewalk? Only this way In both directions From 268cb79e3eb9f090ea904eefe87fd18b9f5c8cd0 Mon Sep 17 00:00:00 2001 From: Wieland <29458682+wielandb@users.noreply.github.com> Date: Fri, 17 Apr 2026 13:26:17 +0200 Subject: [PATCH 9/9] Update app/src/commonMain/composeResources/values/strings.xml Co-authored-by: Tobias Zwick --- app/src/commonMain/composeResources/values/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/commonMain/composeResources/values/strings.xml b/app/src/commonMain/composeResources/values/strings.xml index 189eb9536d..899afb126b 100644 --- a/app/src/commonMain/composeResources/values/strings.xml +++ b/app/src/commonMain/composeResources/values/strings.xml @@ -1316,7 +1316,7 @@ If there are no signs along the whole street which apply for the highlighted sec Oneway in this direction Not a oneway In what direction are you allowed to cycle on this sidewalk? - Only this way + Only this direction In both directions This quest type is disabled by default because bicycle access on sidewalks is only indicated by specific signs at start/end of a sidewalk.