Skip to content

Commit

Permalink
rework the blind traffic light quest to include vibration and tactile…
Browse files Browse the repository at this point in the history
… arrow (fixes #1330)
  • Loading branch information
westnordost committed Sep 28, 2020
1 parent 044bee0 commit eb94b24
Show file tree
Hide file tree
Showing 17 changed files with 433 additions and 42 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ object AchievementsModule {
"AddAccessibleForPedestrians" to "AddProhibitedForPedestrians",
"AddWheelChairAccessPublicTransport" to "AddWheelchairAccessPublicTransport",
"AddWheelChairAccessToilets" to "AddWheelchairAccessToilets",
"AddSidewalks" to "AddSidewalk"
"AddSidewalks" to "AddSidewalk",
"AddTrafficSignalsSound" to "AddTrafficSignalsBlindFeatures"
)

private val links = listOf(
Expand Down Expand Up @@ -523,7 +524,7 @@ object AchievementsModule {
SolvedQuestsOfTypes(
listOf(
"AddTactilePavingCrosswalk",
"AddTrafficSignalsSound",
"AddTrafficSignalsBlindFeatures",
"AddTactilePavingBusStop"
)
),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package de.westnordost.streetcomplete.ktx

fun Boolean.toYesNo(): String = if(this) "yes" else "no"
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ import de.westnordost.streetcomplete.quests.toilets_fee.AddToiletsFee
import de.westnordost.streetcomplete.quests.tourism_information.AddInformationToTourism
import de.westnordost.streetcomplete.quests.tracktype.AddTracktype
import de.westnordost.streetcomplete.quests.traffic_signals_button.AddTrafficSignalsButton
import de.westnordost.streetcomplete.quests.traffic_signals_sound.AddTrafficSignalsSound
import de.westnordost.streetcomplete.quests.traffic_signals_blind.AddTrafficSignalsBlindFeatures
import de.westnordost.streetcomplete.quests.way_lit.AddWayLit
import de.westnordost.streetcomplete.quests.wheelchair_access.*
import de.westnordost.streetcomplete.settings.ResurveyIntervalsStore
Expand Down Expand Up @@ -164,7 +164,7 @@ object QuestModule
AddBabyChangingTable(o), // used by OsmAnd in the object description
AddBikeParkingCover(o), // used by OsmAnd in the object description
AddTactilePavingCrosswalk(o, r), // Paving can be completed while waiting to cross
AddTrafficSignalsSound(o, r), // Sound needs to be done as or after you're crossing
AddTrafficSignalsBlindFeatures(o, r), // Sound needs to be done as or after you're crossing
AddRoofShape(o),
AddWheelchairAccessPublicTransport(o, r),
AddWheelchairAccessOutside(o, r),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package de.westnordost.streetcomplete.quests.traffic_signals_blind

import de.westnordost.osmapi.map.data.BoundingBox
import de.westnordost.osmapi.map.data.Element
import de.westnordost.osmapi.map.data.Node
import de.westnordost.streetcomplete.R
import de.westnordost.streetcomplete.data.elementfilter.filters.RelativeDate
import de.westnordost.streetcomplete.data.elementfilter.filters.TagOlderThan
import de.westnordost.streetcomplete.data.elementfilter.getQuestPrintStatement
import de.westnordost.streetcomplete.data.elementfilter.toGlobalOverpassBBox
import de.westnordost.streetcomplete.data.meta.deleteCheckDatesForKey
import de.westnordost.streetcomplete.data.meta.updateCheckDateForKey
import de.westnordost.streetcomplete.data.osm.changes.StringMapChangesBuilder
import de.westnordost.streetcomplete.data.osm.changes.StringMapEntryModify
import de.westnordost.streetcomplete.data.osm.elementgeometry.ElementGeometry
import de.westnordost.streetcomplete.data.osm.mapdata.OverpassMapDataAndGeometryApi
import de.westnordost.streetcomplete.data.osm.osmquest.OsmElementQuestType
import de.westnordost.streetcomplete.ktx.toYesNo
import de.westnordost.streetcomplete.settings.ResurveyIntervalsStore

class AddTrafficSignalsBlindFeatures(
private val overpassApi: OverpassMapDataAndGeometryApi,
private val r: ResurveyIntervalsStore
) : OsmElementQuestType<TrafficSignalsBlindFeaturesAnswer> {

override fun download(bbox: BoundingBox, handler: (element: Element, geometry: ElementGeometry?) -> Unit): Boolean {
return overpassApi.query(getOverpassQuery(bbox), handler)
}

private fun getOverpassQuery(bbox: BoundingBox) = """
${bbox.toGlobalOverpassBBox()}
node[highway = crossing][crossing = traffic_signals] -> .all;
node.all["traffic_signals:sound"]["traffic_signals:vibration"]["traffic_signals:arrow"] -> .with_tags;
(.all; - .with_tags;) -> .without_tags;
node.with_tags${olderThan(4).toOverpassQLString()} -> .old;
(.without_tags; .old;);
${getQuestPrintStatement()}
""".trimIndent()


override fun isApplicableTo(element: Element): Boolean {
if (element !is Node) return false
val t = element.tags ?: return false
return t["highway"] == "crossing" &&
t["crossing"] == "traffic_signals" && (
!t.containsKey("traffic_signals:sound") ||
!t.containsKey("traffic_signals:vibration") ||
!t.containsKey("traffic_signals:arrow") ||
olderThan(4).matches(element)
)
}

private fun olderThan(years: Int) =
TagOlderThan("traffic_signals", RelativeDate(-(r * 365 * years).toFloat()))

override val commitMessage = "Add features for blind people to traffic lights"
override val wikiLink = "Tag:highway=traffic_signals"
override val icon = R.drawable.ic_quest_blind_traffic_lights

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

override fun createForm() = AddTrafficSignalsBlindFeaturesForm()

override fun applyAnswerTo(answer: TrafficSignalsBlindFeaturesAnswer, changes: StringMapChangesBuilder) {
changes.addOrModify("traffic_signals:sound", answer.sound.toYesNo())
changes.addOrModify("traffic_signals:vibration", answer.vibration.toYesNo())
changes.addOrModify("traffic_signals:arrow", answer.arrow.toYesNo())

// only set the check date if nothing was changed
val isNotActuallyChangingAnything = changes.getChanges().all { change ->
change is StringMapEntryModify && change.value == change.valueBefore
}
if (isNotActuallyChangingAnything) {
changes.updateCheckDateForKey("traffic_signals")
} else {
changes.deleteCheckDatesForKey("traffic_signals")
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package de.westnordost.streetcomplete.quests.traffic_signals_blind

import android.os.Bundle
import android.view.View

import de.westnordost.streetcomplete.R
import de.westnordost.streetcomplete.quests.AbstractQuestFormAnswerFragment
import kotlinx.android.synthetic.main.quest_traffic_signals_blind_features.*

class AddTrafficSignalsBlindFeaturesForm : AbstractQuestFormAnswerFragment<TrafficSignalsBlindFeaturesAnswer>() {

override val contentLayoutResId = R.layout.quest_traffic_signals_blind_features

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
soundSignalsCheckBox.setOnCheckedChangeListener(this::onChecked)
vibrateCheckBox.setOnCheckedChangeListener(this::onChecked)
arrowCheckBox.setOnCheckedChangeListener(this::onChecked)
noneCheckBox.setOnCheckedChangeListener(this::onChecked)
}

override fun onClickOk() {
applyAnswer(TrafficSignalsBlindFeaturesAnswer(
soundSignalsCheckBox.isChecked,
vibrateCheckBox.isChecked,
arrowCheckBox.isChecked
))
}

override fun isFormComplete() =
noneCheckBox.isChecked ||
soundSignalsCheckBox.isChecked ||
vibrateCheckBox.isChecked ||
arrowCheckBox.isChecked

private fun onChecked(buttonView: View, isChecked: Boolean) {
// none-checkbox is exclusive with everything else
if (isChecked) {
if (buttonView.id == R.id.noneCheckBox) {
soundSignalsCheckBox.isChecked = false
vibrateCheckBox.isChecked = false
arrowCheckBox.isChecked = false
} else {
noneCheckBox.isChecked = false
}
}
checkIsFormComplete()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package de.westnordost.streetcomplete.quests.traffic_signals_blind

data class TrafficSignalsBlindFeaturesAnswer(
val sound: Boolean,
val vibration: Boolean,
val arrow: Boolean
)

This file was deleted.

6 changes: 6 additions & 0 deletions app/src/main/res/drawable/ic_blind_arrow.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<vector android:height="32dp" android:viewportHeight="128"
android:viewportWidth="128" android:width="32dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#00000000"
android:pathData="m26.216,9.445 l28.287,112.99 19.713,-29.856 35.713,-2.144z"
android:strokeColor="#333" android:strokeLineJoin="round" android:strokeWidth="5"/>
</vector>
9 changes: 9 additions & 0 deletions app/src/main/res/drawable/ic_blind_sound.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<vector android:height="32dp" android:viewportHeight="128"
android:viewportWidth="128" android:width="32dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path
android:pathData="m116,40v48h-24l-20,24h-8c-0.18,-29.859 0.167,-61.281 0,-96h8l20,24z"
android:strokeColor="#333" android:strokeLineJoin="round" android:strokeWidth="5"/>
<path
android:pathData="m20,120c-11.243,-33.086 -10.077,-80.974 0,-112m16,96c-10.986,-21.718 -10.343,-59.029 0,-80m12,16c-5.995,12.184 -4.628,38.444 0,48"
android:strokeColor="#333" android:strokeLineCap="round" android:strokeWidth="5"/>
</vector>
10 changes: 10 additions & 0 deletions app/src/main/res/drawable/ic_blind_vibration.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<vector android:height="32dp" android:viewportHeight="128"
android:viewportWidth="128" android:width="32dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path
android:pathData="m47.717,61.383s0.076,-22.59 0,-22.659c-0.895,-0.813 -6.18,-4.664 -8.677,1.381l-0.096,41.465c-0.108,6.107 3.411,24.993 24.296,25.287 22.1,0.311 23.389,-23.301 23.427,-23.587 0.09,-0.677 -2.039,-24.889 2.484,-34.657 0,0 -11.811,-7.719 -14.149,12.665l-0.001,-29.778s-3.085,-7.119 -9.062,-1.063m-9.738,-1.7s-4.82,-5.525 -8.484,0.319v10.944m18.028,17.771 l-0.192,-35.409s-4.435,-6.375 -9.062,0v36.046"
android:strokeColor="#333" android:strokeLineCap="round"
android:strokeLineJoin="round" android:strokeWidth="5"/>
<path
android:pathData="m103.96,104c21.719,-21.444 20.947,-58.758 0,-80m-3.96,16c11.317,10.743 10.021,36.989 0,48m-75.96,16c-21.719,-21.444 -20.947,-58.758 0,-80m3.96,16c-11.317,10.743 -10.021,36.989 0,48"
android:strokeColor="#333" android:strokeLineCap="round" android:strokeWidth="5"/>
</vector>
46 changes: 46 additions & 0 deletions app/src/main/res/layout/quest_traffic_signals_blind_features.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical">

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
android:text="@string/quest_traffic_signals_blind_description" />

<CheckBox
android:id="@+id/soundSignalsCheckBox"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:drawableStart="@drawable/ic_blind_sound"
android:drawablePadding="4dp"
app:drawableTint="@color/text"
android:text="@string/quest_traffic_signals_blind_sound_signal" />

<CheckBox
android:id="@+id/vibrateCheckBox"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:drawableStart="@drawable/ic_blind_vibration"
android:drawablePadding="4dp"
app:drawableTint="@color/text"
android:text="@string/quest_traffic_signals_blind_vibrate" />

<CheckBox
android:id="@+id/arrowCheckBox"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:drawableStart="@drawable/ic_blind_arrow"
android:drawablePadding="4dp"
app:drawableTint="@color/text"
android:text="@string/quest_traffic_signals_blind_arrow" />

<CheckBox
android:id="@+id/noneCheckBox"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/quest_traffic_signals_blind_none" />
</LinearLayout>
7 changes: 6 additions & 1 deletion app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -680,7 +680,12 @@ Otherwise, you can download another keyboard in the app store. Popular keyboards
<string name="quest_wheelchairAccess_outside_title">Is this place wheelchair accessible?</string>
<string name="quest_building_underground_name_title">Is %s completely underground?</string>
<string name="quest_building_underground_title">Is this building completely underground?</string>
<string name="quest_traffic_signals_sound_title">Are there sound signals for the blind here?</string>
<string name="quest_traffic_signals_blind_title">What features for the blind do these traffic lights have, if any?</string>
<string name="quest_traffic_signals_blind_description">Select all that apply. Note that the arrow and button are often on the underside of the traffic light button case.</string>
<string name="quest_traffic_signals_blind_sound_signal">sound signals that indicate when crossing is permitted</string>
<string name="quest_traffic_signals_blind_vibrate">a button that vibrates or something when crossing is permitted</string>
<string name="quest_traffic_signals_blind_arrow">tactile arrow that indicates which direction to cross</string>
<string name="quest_traffic_signals_blind_none">no such features here</string>
<string name="quest_traffic_signals_button_title">Do these traffic lights have a button to request a walk signal?</string>
<string name="quest_motorcycleParkingCapacity_title">How many motorcycles can be parked here?</string>
<string name="quest_motorcycleParkingCoveredStatus_title">Is this motorcycle parking covered (protected from rain)?</string>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
package de.westnordost.streetcomplete.quests

import de.westnordost.osmapi.map.data.OsmNode
import de.westnordost.streetcomplete.data.meta.toCheckDate
import de.westnordost.streetcomplete.data.meta.toCheckDateString
import de.westnordost.streetcomplete.data.osm.changes.StringMapEntryAdd
import de.westnordost.streetcomplete.data.osm.changes.StringMapEntryDelete
Expand All @@ -13,7 +11,6 @@ import de.westnordost.streetcomplete.quests.recycling_material.RecyclingMaterial
import de.westnordost.streetcomplete.quests.recycling_material.IsWasteContainer
import de.westnordost.streetcomplete.quests.recycling_material.RecyclingMaterial.*
import de.westnordost.streetcomplete.settings.ResurveyIntervalsStore
import org.junit.Assert.*
import org.junit.Before
import org.junit.Test
import org.mockito.ArgumentMatchers.anyDouble
Expand Down
Loading

0 comments on commit eb94b24

Please sign in to comment.