Skip to content

Commit

Permalink
Merge pull request #2872 from TurnrDev/feature/sunsetlit
Browse files Browse the repository at this point in the history
Only show lit quests during night-time
  • Loading branch information
westnordost authored Aug 22, 2021
2 parents 238ca9d + a9f9cdf commit 03645ed
Show file tree
Hide file tree
Showing 9 changed files with 91 additions and 13 deletions.
3 changes: 3 additions & 0 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,9 @@ dependencies {

// opening hours parser
implementation("ch.poole:OpeningHoursParser:0.25.0")

// sunset-sunrise parser for lit quests
implementation("com.luckycatlabs:SunriseSunsetCalculator:1.2")
}

/** Localizations that should be pulled from POEditor etc. */
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package de.westnordost.streetcomplete.data.quest

enum class DayNightCycle { DAY_AND_NIGHT, ONLY_DAY, ONLY_NIGHT }
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,7 @@ interface QuestType<T> {

/** The quest type can clean it's metadata that is older than the given timestamp here, if any */
fun deleteMetadataOlderThan(timestamp: Long) {}

/** if the quest should only be shown during day-light os night-time hours */
val dayNightCycle: DayNightCycle get() = DayNightCycle.DAY_AND_NIGHT
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import de.westnordost.streetcomplete.data.osm.osmquests.OsmQuest
import de.westnordost.streetcomplete.data.osm.osmquests.OsmQuestSource
import de.westnordost.streetcomplete.data.osmnotes.notequests.OsmNoteQuest
import de.westnordost.streetcomplete.data.osmnotes.notequests.OsmNoteQuestSource
import de.westnordost.streetcomplete.data.visiblequests.DayNightQuestFilter
import de.westnordost.streetcomplete.data.visiblequests.TeamModeQuestFilter
import de.westnordost.streetcomplete.data.visiblequests.VisibleQuestTypeSource
import java.util.concurrent.CopyOnWriteArrayList
Expand All @@ -17,7 +18,8 @@ import javax.inject.Singleton
private val osmQuestSource: OsmQuestSource,
private val osmNoteQuestSource: OsmNoteQuestSource,
private val visibleQuestTypeSource: VisibleQuestTypeSource,
private val teamModeQuestFilter: TeamModeQuestFilter
private val teamModeQuestFilter: TeamModeQuestFilter,
private val dayNightQuestFilter: DayNightQuestFilter,
) {
interface Listener {
/** Called when given quests in the given group have been added/removed */
Expand Down Expand Up @@ -82,7 +84,7 @@ import javax.inject.Singleton
}

private fun isVisible(quest: Quest): Boolean =
visibleQuestTypeSource.isVisible(quest.type) && teamModeQuestFilter.isVisible(quest)
visibleQuestTypeSource.isVisible(quest.type) && teamModeQuestFilter.isVisible(quest) && dayNightQuestFilter.isVisible(quest)

fun addListener(listener: Listener) {
listeners.add(listener)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package de.westnordost.streetcomplete.data.visiblequests

import de.westnordost.streetcomplete.data.quest.DayNightCycle.*
import de.westnordost.streetcomplete.data.quest.Quest
import de.westnordost.streetcomplete.util.isDay
import javax.inject.Inject

class DayNightQuestFilter @Inject internal constructor() {
/*
Might be an idea to add a listener so this is reevaluated occasionally, or something like that.
However, I think it's reevaluated everytime the displayed quests are updated?
*/
fun isVisible(quest: Quest): Boolean {
return when (quest.type.dayNightCycle) {
DAY_AND_NIGHT -> true
ONLY_DAY -> isDay(quest.position)
ONLY_NIGHT -> !isDay(quest.position)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,11 @@ import javax.inject.Singleton
// ↓ 1. notes
OsmNoteQuestType,

// ↓ 2. important data that is used by many data consumers
// ↓ 2. time-specific quests, such as lit quests which are moved to only show ar night
AddWayLit(), // used by OsmAnd if "Street lighting" is enabled. (Configure map, Map rendering, Details)
AddBusStopLit(),

// ↓ 3. important data that is used by many data consumers
AddRoadName(),
AddPlaceName(featureDictionaryFuture),
AddOneway(),
Expand All @@ -152,7 +156,7 @@ import javax.inject.Singleton
AddReligionToPlaceOfWorship(), // icons on maps are different - OSM Carto, mapy.cz, OsmAnd, Sputnik etc
AddParkingAccess(), //OSM Carto, mapy.cz, OSMand, Sputnik etc

//3. useful data that is used by some data consumers
//4. useful data that is used by some data consumers
AddRecyclingType(),
AddRecyclingContainerMaterials(),
AddSport(),
Expand Down Expand Up @@ -191,15 +195,14 @@ import javax.inject.Singleton
AddFerryAccessMotorVehicle(),
AddAcceptsCash(featureDictionaryFuture),

//4. definitely shown as errors in QA tools
//5. definitely shown as errors in QA tools

//5. may be shown as missing in QA tools
//6. may be shown as missing in QA tools
DetermineRecyclingGlass(), // because most recycling:glass=yes is a tagging mistake

//6. may be shown as possibly missing in QA tools
//7. may be shown as possibly missing in QA tools

// ↓ 7. data useful for only a specific use case
AddWayLit(), // used by OsmAnd if "Street lighting" is enabled. (Configure map, Map rendering, Details)
// ↓ 8. data useful for only a specific use case
AddToiletsFee(), // used by OsmAnd in the object description
AddBabyChangingTable(), // used by OsmAnd in the object description
AddBikeParkingCover(), // used by OsmAnd in the object description
Expand Down Expand Up @@ -237,10 +240,10 @@ import javax.inject.Singleton
AddBollardType(), // useful for first responders
AddCameraType(),

//8. defined in the wiki, but not really used by anyone yet. Just collected for
//9. defined in the wiki, but not really used by anyone yet. Just collected for
// the sake of mapping it in case it makes sense later
AddPitchSurface(),
AddPitchLit(),
AddPitchLit(), // Not affected by new DayNight cycle because the lights are usually only on during games
AddIsDefibrillatorIndoor(),
AddSummitRegister(),
AddCyclewayPartSurface(),
Expand All @@ -256,7 +259,6 @@ import javax.inject.Singleton
AddCarWashType(),
AddBenchStatusOnBusStop(),
AddBinStatusOnBusStop(),
AddBusStopLit(),
AddBenchBackrest(),
AddTrafficSignalsButton(),
AddPostboxRoyalCypher()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import de.westnordost.streetcomplete.R
import de.westnordost.streetcomplete.data.meta.updateWithCheckDate
import de.westnordost.streetcomplete.data.osm.edits.update_tags.StringMapChangesBuilder
import de.westnordost.streetcomplete.data.osm.osmquests.OsmFilterQuestType
import de.westnordost.streetcomplete.data.quest.DayNightCycle.ONLY_NIGHT
import de.westnordost.streetcomplete.ktx.arrayOfNotNull
import de.westnordost.streetcomplete.ktx.containsAnyKey
import de.westnordost.streetcomplete.ktx.toYesNo
Expand All @@ -29,6 +30,7 @@ class AddBusStopLit : OsmFilterQuestType<Boolean>() {
override val commitMessage = "Add whether a bus stop is lit"
override val wikiLink = "Key:lit"
override val icon = R.drawable.ic_quest_bus_stop_lit
override val dayNightCycle = ONLY_NIGHT

override fun getTitle(tags: Map<String, String>): Int {
val hasName = tags.containsAnyKey("name", "ref")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@ package de.westnordost.streetcomplete.quests.way_lit
import de.westnordost.streetcomplete.R
import de.westnordost.streetcomplete.data.meta.MAXSPEED_TYPE_KEYS
import de.westnordost.streetcomplete.data.meta.updateWithCheckDate
import de.westnordost.streetcomplete.data.osm.osmquests.OsmFilterQuestType
import de.westnordost.streetcomplete.data.osm.edits.update_tags.StringMapChangesBuilder
import de.westnordost.streetcomplete.data.osm.osmquests.OsmFilterQuestType
import de.westnordost.streetcomplete.data.quest.DayNightCycle.ONLY_NIGHT

class AddWayLit : OsmFilterQuestType<WayLit>() {

Expand Down Expand Up @@ -44,6 +45,7 @@ class AddWayLit : OsmFilterQuestType<WayLit>() {
override val wikiLink = "Key:lit"
override val icon = R.drawable.ic_quest_lantern
override val isSplitWayEnabled = true
override val dayNightCycle = ONLY_NIGHT

override fun getTitle(tags: Map<String, String>): Int {
val type = tags["highway"]
Expand Down
41 changes: 41 additions & 0 deletions app/src/main/java/de/westnordost/streetcomplete/util/CheckIfDay.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package de.westnordost.streetcomplete.util

import com.luckycatlabs.sunrisesunset.Zenith
import com.luckycatlabs.sunrisesunset.calculator.SolarEventCalculator
import com.luckycatlabs.sunrisesunset.dto.Location
import de.westnordost.streetcomplete.data.osm.mapdata.LatLon
import java.time.LocalDate
import java.time.LocalTime
import java.time.ZoneId
import java.time.ZonedDateTime
import java.util.*

fun localDateToCalendar(localDate: LocalDate): Calendar {
val calendar = Calendar.getInstance()
calendar.set(localDate.year, localDate.month.value, localDate.dayOfMonth)
return calendar
}

fun isDay(pos: LatLon): Boolean {
/* This functions job is to check if it's currently light out.
It will use the location of the node and check the civil sunrise/sunset time.
Sometimes sunset is after midnight. This would actually cause sunset to be before sunrise (as it's checking 00:00 to 23:59, it'll catch the day before!), so to gnt around this, we check the next day if that's the case.
*/

val timezone = TimeZone.getDefault().id
val location = Location(pos.latitude, pos.longitude)
val calculator = SolarEventCalculator(location, timezone)
val now = ZonedDateTime.now(ZoneId.of(timezone))
val today = now.toLocalDate()

val sunrise = ZonedDateTime.of(today, LocalTime.parse(calculator.computeSunriseTime(Zenith.CIVIL, localDateToCalendar(today))), ZoneId.of(timezone))
val sunset = ZonedDateTime.of(today, LocalTime.parse(calculator.computeSunsetTime(Zenith.CIVIL, localDateToCalendar(today))), ZoneId.of(timezone))
return if (sunset < sunrise) {

val sunset = ZonedDateTime.of(today.plusDays(1), LocalTime.parse(calculator.computeSunsetTime(Zenith.CIVIL, localDateToCalendar(today.plusDays(1)))), ZoneId.of(timezone))
now in sunrise..sunset
} else {
now in sunrise..sunset
}
}

0 comments on commit 03645ed

Please sign in to comment.