Skip to content

Commit

Permalink
Merge pull request #2078 from matkoniecz/resurface
Browse files Browse the repository at this point in the history
Merge surface quest and detail surface quest, attempt to make interface less confusing [accepted, waiting for merge]
  • Loading branch information
westnordost authored Oct 29, 2020
2 parents 7f2ad5c + 53478a0 commit 9529944
Show file tree
Hide file tree
Showing 41 changed files with 209 additions and 266 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,13 @@ object AchievementsModule {
@Provides @Named("Achievements") fun achievements(): List<Achievement> = achievements
@Provides @Named("QuestAliases") fun questAliases(): List<Pair<String, String>> = questAliases

// list of quest synonyms (this alternate name is mentioned to aid searching for this code)
private val questAliases = listOf(
"AddAccessibleForPedestrians" to "AddProhibitedForPedestrians",
"AddWheelChairAccessPublicTransport" to "AddWheelchairAccessPublicTransport",
"AddWheelChairAccessToilets" to "AddWheelchairAccessToilets",
"AddSidewalks" to "AddSidewalk",
"DetailRoadSurface" to "AddRoadSurface",
"AddTrafficSignalsBlindFeatures" to "AddTrafficSignalsVibration",
"AddSuspectedOneway" to "AddOneway"
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -129,13 +129,12 @@ object QuestModule
AddRecyclingType(o),
AddRecyclingContainerMaterials(o, r),
AddSport(o),
AddRoadSurface(o, r), // used by BRouter, OsmAnd, OSRM, graphhopper, HOT map style
AddRoadSurface(o, r), // used by BRouter, OsmAnd, OSRM, graphhopper, HOT map style...
AddMaxSpeed(o), // should best be after road surface because it excludes unpaved roads
AddMaxHeight(o), // OSRM and other routing engines
AddRailwayCrossingBarrier(o, r), // useful for routing
AddPostboxCollectionTimes(o, r),
AddOpeningHours(o, featureDictionaryFuture, r),
DetailRoadSurface(o), // used by BRouter, OsmAnd, OSRM, graphhopper
AddBikeParkingCapacity(o, r), // used by cycle map layer on osm.org, OsmAnd
AddOrchardProduce(o),
AddBuildingType(o), // because housenumber, building levels etc. depend on it
Expand All @@ -151,7 +150,7 @@ object QuestModule
AddInternetAccess(o, r), // used by OsmAnd
AddParkingFee(o, r), // used by OsmAnd
AddMotorcycleParkingCapacity(o, r),
AddPathSurface(o, r), // used by OSM Carto, OsmAnd
AddPathSurface(o, r), // used by OSM Carto, BRouter, OsmAnd, OSRM, graphhopper...
AddTracktype(o, r), // widely used in map rendering - OSM Carto, OsmAnd...
AddMaxWeight(o), // used by OSRM and other routing engines
AddForestLeafType(o), // used by OSM Carto
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,26 @@ import de.westnordost.streetcomplete.data.osm.mapdata.OverpassMapDataAndGeometry
import de.westnordost.streetcomplete.settings.ResurveyIntervalsStore

class AddCyclewayPartSurface(o: OverpassMapDataAndGeometryApi, r: ResurveyIntervalsStore)
: SimpleOverpassQuestType<String>(o) {
: SimpleOverpassQuestType<SurfaceAnswer>(o) {

override val tagFilters = """
ways with
(
highway = cycleway
highway = cycleway
or (highway ~ path|footway and bicycle != no)
or (highway = bridleway and bicycle ~ designated|yes)
)
and segregated = yes
and (!cycleway:surface or cycleway:surface older today -${r * 8} years)
and (
!cycleway:surface or
cycleway:surface older today -${r * 8} years
or
(
cycleway:surface ~ paved|unpaved
and !cycleway:surface:note
and !note:cycleway:surface
)
)
"""
override val commitMessage = "Add path surfaces"
override val wikiLink = "Key:surface"
Expand All @@ -29,7 +38,17 @@ class AddCyclewayPartSurface(o: OverpassMapDataAndGeometryApi, r: ResurveyInterv

override fun createForm() = AddPathSurfaceForm()

override fun applyAnswerTo(answer: String, changes: StringMapChangesBuilder) {
changes.updateWithCheckDate("cycleway:surface", answer)
override fun applyAnswerTo(answer: SurfaceAnswer, changes: StringMapChangesBuilder) {
when (answer) {
is SpecificSurfaceAnswer -> {
changes.updateWithCheckDate("cycleway:surface", answer.value)
changes.deleteIfExists("cycleway:surface:note")
}
is GenericSurfaceAnswer -> {
changes.updateWithCheckDate("cycleway:surface", answer.value)
changes.addOrModify("cycleway:surface:note", answer.note)
}
}
changes.deleteIfExists("source:cycleway:surface")
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,25 @@ import de.westnordost.streetcomplete.data.osm.mapdata.OverpassMapDataAndGeometry
import de.westnordost.streetcomplete.settings.ResurveyIntervalsStore

class AddFootwayPartSurface(o: OverpassMapDataAndGeometryApi, r: ResurveyIntervalsStore)
: SimpleOverpassQuestType<String>(o) {
: SimpleOverpassQuestType<SurfaceAnswer>(o) {

override val tagFilters = """
ways with
(
highway = footway
highway = footway
or (highway ~ path|cycleway|bridleway and foot != no)
)
and segregated = yes
and (!footway:surface or footway:surface older today -${r * 8} years)
and (
!footway:surface or
footway:surface older today -${r * 8} years
or
(
footway:surface ~ paved|unpaved
and !footway:surface:note
and !note:footway:surface
)
)
"""
override val commitMessage = "Add path surfaces"
override val wikiLink = "Key:surface"
Expand All @@ -28,7 +37,17 @@ class AddFootwayPartSurface(o: OverpassMapDataAndGeometryApi, r: ResurveyInterva

override fun createForm() = AddPathSurfaceForm()

override fun applyAnswerTo(answer: String, changes: StringMapChangesBuilder) {
changes.updateWithCheckDate("footway:surface", answer)
override fun applyAnswerTo(answer: SurfaceAnswer, changes: StringMapChangesBuilder) {
when(answer) {
is SpecificSurfaceAnswer -> {
changes.updateWithCheckDate("footway:surface", answer.value)
changes.deleteIfExists("footway:surface:note")
}
is GenericSurfaceAnswer -> {
changes.updateWithCheckDate("footway:surface", answer.value)
changes.addOrModify("footway:surface:note", answer.note)
}
}
changes.deleteIfExists("source:footway:surface")
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,23 @@ import de.westnordost.streetcomplete.data.osm.mapdata.OverpassMapDataAndGeometry
import de.westnordost.streetcomplete.settings.ResurveyIntervalsStore

class AddPathSurface(o: OverpassMapDataAndGeometryApi, r: ResurveyIntervalsStore)
: SimpleOverpassQuestType<String>(o) {
: SimpleOverpassQuestType<SurfaceAnswer>(o) {

override val tagFilters = """
ways with highway ~ path|footway|cycleway|bridleway|steps
and segregated != yes
and access !~ private|no
and (!conveying or conveying = no) and (!indoor or indoor = no)
and (
!surface
or surface ~ ${ANYTHING_UNPAVED.joinToString("|")} and surface older today -${r * 4} years
or surface older today -${r * 8} years
!surface
or surface ~ ${ANYTHING_UNPAVED.joinToString("|")} and surface older today -${r * 4} years
or surface older today -${r * 8} years
or
(
surface ~ paved|unpaved
and !surface:note
and !note:surface
)
)
"""
/* ~paved ways are less likely to change the surface type */
Expand All @@ -39,7 +45,17 @@ class AddPathSurface(o: OverpassMapDataAndGeometryApi, r: ResurveyIntervalsStore

override fun createForm() = AddPathSurfaceForm()

override fun applyAnswerTo(answer: String, changes: StringMapChangesBuilder) {
changes.updateWithCheckDate("surface", answer)
override fun applyAnswerTo(answer: SurfaceAnswer, changes: StringMapChangesBuilder) {
when(answer) {
is SpecificSurfaceAnswer -> {
changes.updateWithCheckDate("surface", answer.value)
changes.deleteIfExists("surface:note")
}
is GenericSurfaceAnswer -> {
changes.updateWithCheckDate("surface", answer.value)
changes.addOrModify("surface:note", answer.note)
}
}
changes.deleteIfExists("source:surface")
}
}
Original file line number Diff line number Diff line change
@@ -1,56 +1,35 @@
package de.westnordost.streetcomplete.quests.surface

import androidx.appcompat.app.AlertDialog
import de.westnordost.streetcomplete.R
import de.westnordost.streetcomplete.quests.AGroupedImageListQuestAnswerFragment
import de.westnordost.streetcomplete.quests.AImageListQuestAnswerFragment
import de.westnordost.streetcomplete.view.image_select.Item
import de.westnordost.streetcomplete.quests.surface.Surface.*

class AddPathSurfaceForm : AGroupedImageListQuestAnswerFragment<String, String>() {
class AddPathSurfaceForm : AImageListQuestAnswerFragment<String, SurfaceAnswer>() {
override val items: List<Item<String>> get() =
(PAVED_SURFACES + UNPAVED_SURFACES + GROUND_SURFACES).toItems() +
Item("paved", R.drawable.path_surface_paved, R.string.quest_surface_value_paved, null, listOf()) +
Item("unpaved", R.drawable.path_surface_unpaved, R.string.quest_surface_value_unpaved, null, listOf()) +
Item("ground", R.drawable.surface_ground, R.string.quest_surface_value_ground, null, listOf())

override val topItems get() =
when (val pathType = determinePathType(osmElement!!.tags)) {
"bridleway" -> listOf(
DIRT, GRASS, SAND,
PEBBLES, FINE_GRAVEL, COMPACTED
)
"path" -> listOf(
DIRT, PEBBLES, COMPACTED,
ASPHALT, FINE_GRAVEL, PAVING_STONES
)
"footway" -> listOf(
PAVING_STONES, ASPHALT, CONCRETE,
COMPACTED, FINE_GRAVEL, DIRT
)
"cycleway" -> listOf(
PAVING_STONES, ASPHALT, CONCRETE,
COMPACTED, WOOD, METAL
)
"steps" -> listOf(
PAVING_STONES, ASPHALT, CONCRETE,
WOOD, SETT, UNHEWN_COBBLESTONE
)
else -> throw IllegalStateException("Unexpected path type $pathType")
}.toItems()
override val itemsPerRow = 3

override val allItems = listOf(
// except for different panorama images, should be the same as for the road quest, to avoid confusion
Item("paved", R.drawable.panorama_path_surface_paved, R.string.quest_surface_value_paved, null, PAVED_SURFACES.toItems()),
Item("unpaved", R.drawable.panorama_path_surface_unpaved, R.string.quest_surface_value_unpaved, null, UNPAVED_SURFACES.toItems()),
Item("ground", R.drawable.panorama_surface_ground, R.string.quest_surface_value_ground, null, GROUND_SURFACES.toItems())
)

private fun determinePathType(tags: Map<String, String>): String? {
val pathType = tags["highway"]
// interpret paths with foot/bicycle/horse=designated as...
if ("path" == pathType) {
if ("designated" == tags["bicycle"]) return "cycleway"
if ("designated" == tags["horse"]) return "bridleway"
if ("designated" == tags["foot"]) return "footway"
override fun onClickOk(selectedItems: List<String>) {
val value = selectedItems.single()
if(value == "paved" || value == "unpaved") {
AlertDialog.Builder(requireContext())
.setMessage(R.string.quest_surface_detailed_answer_impossible_confirmation)
.setPositiveButton(R.string.quest_generic_confirmation_yes) {
_, _ -> run {
DescribeGenericSurfaceDialog(requireContext()) { description ->
applyAnswer(GenericSurfaceAnswer(value, description))
}.show()
}
}
.setNegativeButton(android.R.string.cancel, null)
.show()
return
}
return pathType
}

override fun onClickOk(value: String) {
applyAnswer(value)
applyAnswer(SpecificSurfaceAnswer(value))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,27 +3,30 @@ package de.westnordost.streetcomplete.quests.surface
import de.westnordost.streetcomplete.R
import de.westnordost.streetcomplete.data.meta.ANYTHING_UNPAVED
import de.westnordost.streetcomplete.data.meta.updateWithCheckDate
import de.westnordost.streetcomplete.data.osm.osmquest.SimpleOverpassQuestType
import de.westnordost.streetcomplete.data.osm.changes.StringMapChangesBuilder
import de.westnordost.streetcomplete.data.osm.mapdata.OverpassMapDataAndGeometryApi
import de.westnordost.streetcomplete.data.osm.osmquest.SimpleOverpassQuestType
import de.westnordost.streetcomplete.settings.ResurveyIntervalsStore


class AddRoadSurface(o: OverpassMapDataAndGeometryApi, r: ResurveyIntervalsStore)
: SimpleOverpassQuestType<String>(o) {

class AddRoadSurface(o: OverpassMapDataAndGeometryApi, r: ResurveyIntervalsStore) : SimpleOverpassQuestType<SurfaceAnswer>(o) {
override val tagFilters = """
ways with highway ~ ${ROADS_WITH_SURFACES.joinToString("|")}
and (
!surface
or surface ~ ${ANYTHING_UNPAVED.joinToString("|")} and surface older today -${r * 4} years
or surface older today -${r * 12} years
)
and (access !~ private|no or (foot and foot !~ private|no))
and
(
!surface
or surface ~ ${ANYTHING_UNPAVED.joinToString("|")} and surface older today -${r * 4} years
or surface older today -${r * 12} years
or
(
surface ~ paved|unpaved
and !surface:note
and !note:surface
)
)
and (access !~ private|no or (foot and foot !~ private|no))
"""
/* ~paved ways are less likely to change the surface type */

override val commitMessage = "Add road surfaces"
override val commitMessage = "Add road surface info"
override val wikiLink = "Key:surface"
override val icon = R.drawable.ic_quest_street_surface
override val isSplitWayEnabled = true
Expand All @@ -46,8 +49,18 @@ class AddRoadSurface(o: OverpassMapDataAndGeometryApi, r: ResurveyIntervalsStore

override fun createForm() = AddRoadSurfaceForm()

override fun applyAnswerTo(answer: String, changes: StringMapChangesBuilder) {
changes.updateWithCheckDate("surface", answer)
override fun applyAnswerTo(answer: SurfaceAnswer, changes: StringMapChangesBuilder) {
when(answer) {
is SpecificSurfaceAnswer -> {
changes.updateWithCheckDate("surface", answer.value)
changes.deleteIfExists("surface:note")
}
is GenericSurfaceAnswer -> {
changes.updateWithCheckDate("surface", answer.value)
changes.addOrModify("surface:note", answer.note)
}
}
changes.deleteIfExists("source:surface")
}

companion object {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,26 +1,35 @@
package de.westnordost.streetcomplete.quests.surface

import androidx.appcompat.app.AlertDialog
import de.westnordost.streetcomplete.R
import de.westnordost.streetcomplete.quests.AGroupedImageListQuestAnswerFragment
import de.westnordost.streetcomplete.quests.AImageListQuestAnswerFragment
import de.westnordost.streetcomplete.view.image_select.Item
import de.westnordost.streetcomplete.quests.surface.Surface.*

class AddRoadSurfaceForm : AGroupedImageListQuestAnswerFragment<String,String>() {
class AddRoadSurfaceForm : AImageListQuestAnswerFragment<String, SurfaceAnswer>() {
override val items: List<Item<String>> get() =
(PAVED_SURFACES + UNPAVED_SURFACES + GROUND_SURFACES).toItems() +
Item("paved", R.drawable.surface_paved, R.string.quest_surface_value_paved, null, listOf()) +
Item("unpaved", R.drawable.surface_unpaved, R.string.quest_surface_value_unpaved, null, listOf()) +
Item("ground", R.drawable.surface_ground, R.string.quest_surface_value_ground, null, listOf())

override val topItems get() =
// tracks often have different surfaces than other roads
if (osmElement!!.tags["highway"] == "track")
listOf(DIRT, GRASS, PEBBLES, FINE_GRAVEL, COMPACTED, ASPHALT).toItems()
else
listOf(ASPHALT, CONCRETE, SETT, PAVING_STONES, COMPACTED, DIRT).toItems()
override val itemsPerRow = 3

override val allItems = listOf(
Item("paved", R.drawable.panorama_surface_paved, R.string.quest_surface_value_paved, null, PAVED_SURFACES.toItems()),
Item("unpaved", R.drawable.panorama_surface_unpaved, R.string.quest_surface_value_unpaved, null, UNPAVED_SURFACES.toItems()),
Item("ground", R.drawable.panorama_surface_ground, R.string.quest_surface_value_ground, null, GROUND_SURFACES.toItems())
)

override fun onClickOk(value: String) {
applyAnswer(value)
override fun onClickOk(selectedItems: List<String>) {
val value = selectedItems.single()
if(value == "paved" || value == "unpaved") {
AlertDialog.Builder(requireContext())
.setMessage(R.string.quest_surface_detailed_answer_impossible_confirmation)
.setPositiveButton(R.string.quest_generic_confirmation_yes) {
_, _ -> run {
DescribeGenericSurfaceDialog(requireContext()) { description ->
applyAnswer(GenericSurfaceAnswer(value, description))
}.show()
}
}
.setNegativeButton(android.R.string.cancel, null)
.show()
return
}
applyAnswer(SpecificSurfaceAnswer(value))
}
}
Loading

0 comments on commit 9529944

Please sign in to comment.