Skip to content

Commit b84c363

Browse files
committed
don't ask for power line attachment on poles that have more than one power line going through (fixes #6547)
1 parent b5de1d8 commit b84c363

File tree

2 files changed

+68
-4
lines changed

2 files changed

+68
-4
lines changed

app/src/androidMain/kotlin/de/westnordost/streetcomplete/quests/power_attachment/AddPowerAttachment.kt

Lines changed: 37 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,63 @@
11
package de.westnordost.streetcomplete.quests.power_attachment
22

33
import de.westnordost.streetcomplete.R
4+
import de.westnordost.streetcomplete.data.elementfilter.toElementFilterExpression
45
import de.westnordost.streetcomplete.data.osm.geometry.ElementGeometry
56
import de.westnordost.streetcomplete.data.osm.mapdata.Element
67
import de.westnordost.streetcomplete.data.osm.mapdata.MapDataWithGeometry
78
import de.westnordost.streetcomplete.data.osm.mapdata.filter
9+
import de.westnordost.streetcomplete.data.osm.osmquests.OsmElementQuestType
810
import de.westnordost.streetcomplete.data.osm.osmquests.OsmFilterQuestType
911
import de.westnordost.streetcomplete.data.quest.AndroidQuest
1012
import de.westnordost.streetcomplete.data.user.achievements.EditTypeAchievement.BUILDING
1113
import de.westnordost.streetcomplete.osm.Tags
1214
import de.westnordost.streetcomplete.resources.*
1315

14-
class AddPowerAttachment : OsmFilterQuestType<PowerAttachment>(), AndroidQuest {
16+
class AddPowerAttachment : OsmElementQuestType<PowerAttachment>, AndroidQuest {
1517

16-
override val elementFilter = """
18+
private val polesFilter by lazy { """
1719
nodes with
1820
power ~ tower|pole|insulator
1921
and !line_attachment
20-
and disused != yes and ruined != yes and abandoned != yes
21-
"""
22+
and disused != yes
23+
and ruined != yes
24+
and abandoned != yes
25+
""".toElementFilterExpression() }
26+
27+
private val powerLinesFilter by lazy { """
28+
ways with power ~ line|minor_line
29+
""".toElementFilterExpression() }
30+
2231
override val changesetComment = "Specify line_attachment power support"
2332
override val wikiLink = "Key:line_attachment"
2433
override val icon = R.drawable.quest_power
2534
override val title = Res.string.quest_powerAttachment_title
2635
override val achievements = listOf(BUILDING)
2736

37+
override fun getApplicableElements(mapData: MapDataWithGeometry): Iterable<Element> {
38+
// when several power lines are attached to any one power pole, it is very likely that that
39+
// power pole has *multiple* power line attachments, which requires a more complex tagging
40+
// that the UI for this quest does not support. Hence, we filter out all power poles that
41+
// are nodes of more than one power lines. See #6547
42+
val poleNodeIdsWithSeveralPowerLines = mapData.ways
43+
.filter { powerLinesFilter.matches(it) }
44+
.flatMap { it.nodeIds }
45+
.groupingBy { it }.eachCount()
46+
.filter { (id, count) -> count != 1 }
47+
.mapTo(HashSet<Long>()) { (id, count) -> id }
48+
49+
return mapData.nodes.filter {
50+
polesFilter.matches(it) && it.id !in poleNodeIdsWithSeveralPowerLines
51+
}
52+
}
53+
54+
override fun isApplicableTo(element: Element): Boolean? {
55+
if (!polesFilter.matches(element)) return false
56+
// otherwise, we can't say, because the power pole may be part of several power lines
57+
// (see comment in getApplicableElements)
58+
return null
59+
}
60+
2861
override fun getHighlightedElements(element: Element, mapData: MapDataWithGeometry) =
2962
// and also show the (power) lines themselves
3063
mapData.filter("nodes with power ~ tower|pole|insulator") +
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package de.westnordost.streetcomplete.quests.power_attachment
2+
3+
import de.westnordost.streetcomplete.quests.TestMapDataWithGeometry
4+
import de.westnordost.streetcomplete.testutils.node
5+
import de.westnordost.streetcomplete.testutils.way
6+
import de.westnordost.streetcomplete.util.ktx.containsExactlyInAnyOrder
7+
import kotlin.test.Test
8+
import kotlin.test.assertEquals
9+
import kotlin.test.assertTrue
10+
11+
class AddPowerAttachmentTest {
12+
13+
private val questType = AddPowerAttachment()
14+
15+
@Test fun `applicable only to power poles part of exactly one power line`() {
16+
val poleWithMultiplePowerLines = node(id = 2, tags = mapOf("power" to "pole"))
17+
val poleWithOnePowerLine = node(id = 1, tags = mapOf("power" to "pole"))
18+
val poleWithNoPowerLine = node(id = 6, tags = mapOf("power" to "pole"))
19+
val mapData = TestMapDataWithGeometry(listOf(
20+
poleWithOnePowerLine,
21+
poleWithMultiplePowerLines,
22+
way(1, listOf(1, 2, 3), mapOf("power" to "line")),
23+
way(2, listOf(4, 2, 5), mapOf("power" to "line")),
24+
))
25+
26+
assertEquals(
27+
poleWithOnePowerLine,
28+
questType.getApplicableElements(mapData).single()
29+
)
30+
}
31+
}

0 commit comments

Comments
 (0)