Skip to content

Commit

Permalink
Merge branch 'master' into osmapi
Browse files Browse the repository at this point in the history
  • Loading branch information
westnordost committed Aug 8, 2024
2 parents 8725d94 + a09ae22 commit 8e4e051
Show file tree
Hide file tree
Showing 30 changed files with 385 additions and 169 deletions.
4 changes: 4 additions & 0 deletions CONTRIBUTING_A_NEW_QUEST.md
Original file line number Diff line number Diff line change
Expand Up @@ -543,6 +543,10 @@ For nodes within ways, the node will remain and tags will be removed.
When there are doubts on the question itself (terms used, etc.), how to answer or how to find the answer, more information can be provided via info button text & images.
Examples for such info button would be explanation of what is halal, what is [tactile paving](app/src/main/java/de/westnordost/streetcomplete/quests/tactile_paving/AddTactilePavingBusStop.kt#L33-L38), what is a sanitary dump station, when a level counts as a roof level and when as a normal level, explanation of the street side puzzle UI, etc.

Instructions for answering the quest should instead be directly visible either in the quest title or a label on the form always shown with the answers. For example, when asked for the name of a road, a label instructs the user to expand abbreviated road names. When asked about whether a restaurant offers vegetarian options, it is clarified that one should only answer "yes" if these are proper options (not just a salad or whatever).

For doubts on how to answer specific situations, like e.g. when asked for the opening hours of a shop that doesn't seem to exist anymore or asked about the house number of a building that instead has a house name, it is better to provide such answer through the "Uh..." menu, see [Designing the form](#designing-the-form).

## Per-country quest behaviour modification

While quests should generally be tailored to function in whole world similarly, if really needed one can use `countryInfo` to modify behaviour of the quest in specific country, see e.g. [AddTrafficSignalsVibrationForm.kt](app/src/main/java/de/westnordost/streetcomplete/quests/traffic_signals_vibrate/AddTrafficSignalsVibrationForm.kt) for example usage.
22 changes: 1 addition & 21 deletions app/src/main/assets/map_theme/jawg/streetcomplete.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -262,29 +262,9 @@ layers:
# styled map data shown in overlays
streetcomplete_map_data:
data: { source: streetcomplete_map_data }
# if the icons do not collide, it will get too busy
point-collide:
filter: { icon: true, $zoom: { min: 18, max: 19.999 } }
draw:
map_data-icons:
interactive: true
priority: 1
collide: true
size: 34px
sprite: function() { return feature.icon }
text:
anchor: [right]
optional: true
text_source: text
max_lines: 2
font:
family: global.text_font_family
fill: global.text_fill_color
size: global.text_size
stroke: { color: global.text_stroke_color, width: 4px }
# same as above but with collide=false, at ~max zoom
point-no-collide:
filter: { icon: true, $zoom: { min: 20 } }
filter: { icon: true, $zoom: { min: 18 } }
draw:
map_data-icons:
interactive: true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import com.russhwolf.settings.long
import com.russhwolf.settings.nullableString
import com.russhwolf.settings.string
import de.westnordost.streetcomplete.data.osm.mapdata.LatLon
import de.westnordost.streetcomplete.util.ktx.putStringOrNull

class Preferences(private val prefs: ObservableSettings) {
// application settings
Expand Down Expand Up @@ -36,26 +37,6 @@ class Preferences(private val prefs: ObservableSettings) {

var showAllNotes: Boolean by prefs.boolean(SHOW_ALL_NOTES, false)

fun getLastPicked(key: String): List<String> =
prefs.getStringOrNull(LAST_PICKED_PREFIX + key)?.split(',') ?: listOf()

fun addLastPicked(key: String, value: String, maxValueCount: Int = 100) {
addLastPicked(key, listOf(value), maxValueCount)
}

fun addLastPicked(key: String, values: List<String>, maxValueCount: Int = 100) {
val lastValues = values + getLastPicked(key)
setLastPicked(key, lastValues.take(maxValueCount))
}

fun setLastPicked(key: String, values: List<String>) {
prefs.putString(LAST_PICKED_PREFIX + key, values.joinToString(","))
}

fun setLastPicked(key: String, value: String) {
prefs.putString(LAST_PICKED_PREFIX + key, value)
}

fun onLanguageChanged(callback: (String?) -> Unit): SettingsListener =
prefs.addStringOrNullListener(LANGUAGE_SELECT, callback)

Expand Down Expand Up @@ -157,6 +138,46 @@ class Preferences(private val prefs: ObservableSettings) {

var lastEditTime: Long by prefs.long(LAST_EDIT_TIME, 0L)

fun getLastPicked(key: String): List<String> =
prefs.getStringOrNull(LAST_PICKED_PREFIX + key)?.split(',') ?: listOf()

fun addLastPicked(key: String, value: String, maxValueCount: Int = 100) {
addLastPicked(key, listOf(value), maxValueCount)
}

fun addLastPicked(key: String, values: List<String>, maxValueCount: Int = 100) {
val lastValues = values + getLastPicked(key)
setLastPicked(key, lastValues.take(maxValueCount))
}

fun setLastPicked(key: String, values: List<String>) {
prefs.putString(LAST_PICKED_PREFIX + key, values.joinToString(","))
}

fun getLastPickedLeft(key: String): String? =
prefs.getStringOrNull(getLastPickedSideKey(key, "left"))

fun setLastPickedLeft(key: String, value: String?) {
prefs.putStringOrNull(getLastPickedSideKey(key, "left"), value)
}

fun getLastPickedRight(key: String): String? =
prefs.getStringOrNull(getLastPickedSideKey(key, "right"))

fun setLastPickedRight(key: String, value: String?) {
prefs.putStringOrNull(getLastPickedSideKey(key, "right"), value)
}

fun getLastPickedOneSide(key: String): String? =
prefs.getStringOrNull(getLastPickedSideKey(key, "oneSide"))

fun setLastPickedOneSide(key: String, value: String?) {
prefs.putStringOrNull(getLastPickedSideKey(key, "oneSide"), value)
}

private fun getLastPickedSideKey(key: String, side: String): String =
"$LAST_PICKED_PREFIX$key.$side"

// profile & statistics screen UI
var userGlobalRank: Int by prefs.int(USER_GLOBAL_RANK, -1)
var userGlobalRankCurrentWeek: Int by prefs.int(USER_GLOBAL_RANK_CURRENT_WEEK, -1)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,10 @@ abstract class AImageListQuestForm<I, T> : AbstractOsmQuestForm<T>() {
binding.list.layoutManager = GridLayoutManager(activity, itemsPerRow)
binding.list.isNestedScrollingEnabled = false

binding.selectHintLabel.setText(if (maxSelectableItems == 1) R.string.quest_roofShape_select_one else R.string.quest_select_hint)
binding.selectHintLabel.setText(
if (maxSelectableItems == 1) R.string.quest_roofShape_select_one
else R.string.quest_multiselect_hint
)

imageSelector.listeners.add(object : ImageSelectAdapter.OnItemSelectionListener {
override fun onIndexSelected(index: Int) {
Expand Down Expand Up @@ -98,14 +101,16 @@ abstract class AImageListQuestForm<I, T> : AbstractOsmQuestForm<T>() {

override fun isFormComplete() = imageSelector.selectedIndices.isNotEmpty()

private fun moveFavouritesToFront(originalList: List<DisplayItem<I>>): List<DisplayItem<I>> =
private fun moveFavouritesToFront(originalList: List<DisplayItem<I>>): List<DisplayItem<I>> {
if (originalList.size > itemsPerRow && moveFavoritesToFront) {
prefs.getLastPicked(this::class.simpleName!!)
val favourites = prefs.getLastPicked(this::class.simpleName!!)
.map { itemsByString[it] }
.takeFavourites(n = itemsPerRow, history = 50, pad = originalList)
.takeFavourites(n = itemsPerRow, history = 50)
return (favourites + originalList).distinct()
} else {
originalList
return originalList
}
}

companion object {
private const val SELECTED_INDICES = "selected_indices"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import de.westnordost.streetcomplete.quests.atm_operator.AddAtmOperator
import de.westnordost.streetcomplete.quests.baby_changing_table.AddBabyChangingTable
import de.westnordost.streetcomplete.quests.barrier_bicycle_barrier_installation.AddBicycleBarrierInstallation
import de.westnordost.streetcomplete.quests.barrier_bicycle_barrier_type.AddBicycleBarrierType
import de.westnordost.streetcomplete.quests.barrier_opening.AddBarrierOpening
import de.westnordost.streetcomplete.quests.barrier_type.AddBarrierOnPath
import de.westnordost.streetcomplete.quests.barrier_type.AddBarrierOnRoad
import de.westnordost.streetcomplete.quests.barrier_type.AddBarrierType
Expand Down Expand Up @@ -501,6 +502,7 @@ fun questTypeRegistry(
140 to AddRoadWidth(arSupportChecker),
141 to AddRoadSmoothness(),
142 to AddPathSmoothness(),
170 to AddBarrierOpening(arSupportChecker),

// footways
143 to AddPathSurface(), // used by OSM Carto, BRouter, OsmAnd, OSRM, graphhopper...
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ class AddAcceptsCards : OsmFilterQuestType<CardAcceptance>() {
and !payment:credit_cards and !payment:debit_cards and payment:others != no
and !brand and !wikipedia:brand and !wikidata:brand
and (!seasonal or seasonal = no)
and (!fee or fee != no)
and (name or noname = yes or name:signed = no)
and access !~ private|no
"""
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package de.westnordost.streetcomplete.quests.barrier_opening

import de.westnordost.streetcomplete.R
import de.westnordost.streetcomplete.data.elementfilter.toElementFilterExpression
import de.westnordost.streetcomplete.data.osm.geometry.ElementGeometry
import de.westnordost.streetcomplete.data.osm.mapdata.Element
import de.westnordost.streetcomplete.data.osm.mapdata.MapDataWithGeometry
import de.westnordost.streetcomplete.data.osm.osmquests.OsmElementQuestType
import de.westnordost.streetcomplete.data.user.achievements.EditTypeAchievement.BICYCLIST
import de.westnordost.streetcomplete.data.user.achievements.EditTypeAchievement.WHEELCHAIR
import de.westnordost.streetcomplete.osm.Tags
import de.westnordost.streetcomplete.quests.width.AddWidthForm
import de.westnordost.streetcomplete.quests.width.WidthAnswer
import de.westnordost.streetcomplete.screens.measure.ArSupportChecker

class AddBarrierOpening(
private val checkArSupport: ArSupportChecker
) : OsmElementQuestType<WidthAnswer> {

private val nodeFilter by lazy { """
nodes with
barrier ~ gate|entrance|sliding_gate|swing_gate|wicket_gate
and (!maxwidth:physical or source:maxwidth_physical ~ ".*estimat.*")
and (!width or source:width ~ ".*estimat.*")
and (!maxwidth or source:maxwidth ~ ".*estimat.*")
and access !~ private|no|customers|agricultural
""".toElementFilterExpression() }

private val excludedWaysFilter by lazy { """
ways with
highway and access ~ private|no|customers|agricultural
""".toElementFilterExpression() }

override val changesetComment = "Specify width of opening"
override val wikiLink = "Key:barrier"
override val icon = R.drawable.ic_quest_wheelchair_width
override val achievements = listOf(BICYCLIST, WHEELCHAIR)
override val defaultDisabledMessage: Int
get() = if (!checkArSupport()) R.string.default_disabled_msg_no_ar else 0

override fun getTitle(tags: Map<String, String>) = R.string.quest_barrier_opening_width_gate

override fun getApplicableElements(mapData: MapDataWithGeometry): Iterable<Element> {
val excludedWayNodeIds = mapData.ways
.filter { excludedWaysFilter.matches(it) }
.flatMapTo(HashSet()) { it.nodeIds }

return mapData.nodes
.filter { nodeFilter.matches(it) && it.id !in excludedWayNodeIds }
}

override fun isApplicableTo(element: Element) =
if (nodeFilter.matches(element)) null else false

override fun createForm() = AddWidthForm()

override fun applyAnswerTo(answer: WidthAnswer, tags: Tags, geometry: ElementGeometry, timestampEdited: Long) {
val key = "maxwidth:physical"

tags[key] = answer.width.toOsmValue()

if (answer.isARMeasurement) {
tags["source:$key"] = "ARCore"
} else {
tags.remove("source:$key")
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ class AddDrinkingWaterType : OsmFilterQuestType<DrinkingWaterType>() {
or
(disused:amenity = drinking_water and !amenity and older today -1 years)
)
and (!intermittent or intermittent = no)
and (!seasonal or seasonal = no)
and !man_made and !natural and !fountain and !pump
"""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ class AddRecyclingType : OsmFilterQuestType<RecyclingType>() {
override fun getTitle(tags: Map<String, String>) = R.string.quest_recycling_type_title

override fun getHighlightedElements(element: Element, getMapData: () -> MapDataWithGeometry) =
getMapData().filter("nodes with amenity = recycling")
getMapData().filter("nodes, ways with amenity ~ recycling|waste_disposal|waste_basket")

override fun createForm() = AddRecyclingTypeForm()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ class AddRecyclingContainerMaterials : OsmElementQuestType<RecyclingContainerMat
override fun createForm() = AddRecyclingContainerMaterialsForm()

override fun getHighlightedElements(element: Element, getMapData: () -> MapDataWithGeometry) =
getMapData().filter("nodes with amenity = recycling")
getMapData().filter("nodes, ways with amenity ~ recycling|waste_disposal|waste_basket")

override fun applyAnswerTo(answer: RecyclingContainerMaterialsAnswer, tags: Tags, geometry: ElementGeometry, timestampEdited: Long) {
if (answer is RecyclingMaterials) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import android.os.Bundle
import android.text.Html
import android.text.method.LinkMovementMethod
import android.text.util.Linkify
import android.view.KeyEvent
import android.view.View
import android.view.WindowManager
import android.widget.TextView
Expand Down Expand Up @@ -175,17 +174,6 @@ class MainActivity :
updateLocationAvailability(hasLocationPermission && isLocationEnabled)
}

override fun dispatchKeyEvent(event: KeyEvent): Boolean {
val mainFragment = mainFragment
if (event.keyCode == KeyEvent.KEYCODE_MENU && mainFragment != null) {
if (event.action == KeyEvent.ACTION_UP) {
mainFragment.onClickMainMenu()
}
return true
}
return super.dispatchKeyEvent(event)
}

public override fun onPause() {
super.onPause()
val pos = mainFragment?.getCameraPosition()?.position ?: return
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ fun PrivacyStatementScreen(
tryParseHtml(stringResource(R.string.privacy_html)) +
tryParseHtml(stringResource(R.string.privacy_html_tileserver2, vectorTileProvider.title, vectorTileProvider.privacyStatementLink)) +
tryParseHtml(stringResource(R.string.privacy_html_statistics)) +
tryParseHtml(stringResource(R.string.privacy_html_third_party_quest_sources)) +
tryParseHtml(stringResource(R.string.privacy_html_image_upload2)),
modifier = Modifier
.fillMaxWidth()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,6 @@ import de.westnordost.streetcomplete.screens.main.bottom_sheet.IsMapPositionAwar
import de.westnordost.streetcomplete.screens.main.bottom_sheet.MoveNodeFragment
import de.westnordost.streetcomplete.screens.main.bottom_sheet.SplitWayFragment
import de.westnordost.streetcomplete.screens.main.controls.LocationState
import de.westnordost.streetcomplete.screens.main.controls.LocationStateButton
import de.westnordost.streetcomplete.screens.main.controls.MainMenuDialog
import de.westnordost.streetcomplete.screens.main.edithistory.EditHistoryFragment
import de.westnordost.streetcomplete.screens.main.edithistory.EditHistoryViewModel
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,6 @@ enum class LocationState {
SEARCHING,
/** receiving location updates */
UPDATING;

val isEnabled: Boolean get() = ordinal >= ENABLED.ordinal
}
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ class SettingsActivity : BaseActivity(), AbstractOsmQuestForm.Listener {
}

listeners += prefs.onLanguageChanged { ActivityCompat.recreate(this) }
listeners += prefs.onThemeChanged { ActivityCompat.recreate(this) }
}

override fun onDestroy() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@ fun SettingsScreen(
items = Autosync.entries,
onItemSelected = {
viewModel.setAutosync(it)
if (autosync != Autosync.ON) {
if (it != Autosync.ON) {
showUploadTutorialInfo = true
}
},
Expand Down
Loading

0 comments on commit 8e4e051

Please sign in to comment.