Repository: streetcomplete/StreetComplete (language: kotlin)

Issue:
Add 'previous choice' option to Street lit overlay
**Use case**
Currently if you're doing a bunch of the "is this street lit?" Entries; it is requiring more clicks than I feel like it should be doing

**Proposed Solution**
I think similar to the quest where you have to select every Street has a cycle way; there should be a button when you're trying to answer the streetlights quest in the bottom left corner with the last answer you gave. That would half the amount of taps




Discussion hints:
Huh? But the answer can only be yes or no. How would a "last answer" button help? The "yes" and "no" answers are already displayed!
Sorry, I'm referring to this quest

![Screenshot_20230109_053737_StreetComplete](https://user-images.githubusercontent.com/1010226/211241939-2c0a3373-6dc2-49a7-afa3-600bd0687b86.jpg)

#4640 #4622 I still think that showing the 4 options next to each other immediately after selecting a way is best, with the current value or the previous choice highlighted.
![image](https://user-images.githubusercontent.com/69100427/211291285-36ddf965-24cf-4bb2-85f6-48f569c65d3c.png)

Makes sense and is easy to implement. As always, PR is welcome.

Of course this should be implemented in the `AImageSelectOverlayForm` so that all overlay forms with the same UI will profit from that. (Currently only lit and the separate cycleway form, but also upcoming surface form)
On the other hand, it is only one tap saved. Not sure if this is worth the extra UI clutter. I dimly remember that I once marked a similar feature request as will not fix.
It is only one click. But if you're marking a bunch of streets all after each other... It starts up get really annoying, that extra click X times
But it also takes some time to walk to the next street, doesn't it? So it doesn't really change the speed of recording the lit situation if controlling the UI is like 1 second faster.
Depends on how segmented streets and sidewalks are. In my area I often need to stop and stand to input everything.

And when surface is also missing and `highway=steps` quests are not solved...

https://www.openstreetmap.org/#map=18/50.07567/20.04641

![screen](https://user-images.githubusercontent.com/899988/211304183-fc910e82-b46c-46ed-8761-0aab390055b8.png)

In some places a road can be split into quite a lot of sections due to
surface type, if it's a traffic calming table, separate lanes etc. So one
location can just have a lot of way objects

On Mon, Jan 9, 2023, 13:01 Tobias Zwick ***@***.***> wrote:

> But it also takes some time to walk to the next street, doesn't it? So it
> doesn't really change the speed of recording the lit situation if
> controlling the UI is like 1 second faster.
>
> —
> Reply to this email directly, view it on GitHub
> <https://github.com/streetcomplete/StreetComplete/issues/4741#issuecomment-1375520081>,
> or unsubscribe
> <https://github.com/notifications/unsubscribe-auth/AAHWUMWVESMGHXODEHJP7UDWRP4YHANCNFSM6AAAAAATU3A3WM>
> .
> You are receiving this because you authored the thread.Message ID:
> ***@***.***>
>

Fair enough.
> On the other hand, it is only one tap saved.

It is 50% taps saved :)


>  I dimly remember that I once marked a similar feature request as will not fix.

linked here:
https://github.com/streetcomplete/StreetComplete/issues/4741#issuecomment-1375424771
Maybe it will be better to remove the drop-down menu/dialog? If we make it possible to choose an answer directly without a drop-down menu/dialog, we won't need the 'previous choice' option.

What I mean is:
<img width="200" alt="Screenshot_2" src="https://user-images.githubusercontent.com/114614618/217633771-b97375f0-4c18-4859-b8ab-42974afaca72.png">

This is how it looks now:
<img width="200" alt="Screenshot_1675884557" src="https://user-images.githubusercontent.com/114614618/217633764-5434ed32-8438-41fd-a57c-e67b8320be9b.png">

This was proposed before and rejected.
> This was proposed before and rejected.

That it is proposed again and again shows how annoying the present UI is...

Pull request: Buildings overlay
https://github.com/streetcomplete/StreetComplete/assets/4661658/95a9fd9f-f70f-42c4-970a-e811c1d926f4

### Building type overlay features:

- buildings are roughly categorized according to function and get their highlight color from there. Additionally, when zooming in, the icon of each building type is displayed.

- some not supported building types are treated as "synonyms" to supported building types. E.g. `building=livestock` is treated as synonym to `building=farm_auxiliary`. These buildings will be displayed as that building type in the app and if the in-app building type is not changed to another building, the "synonym" is retained on saving changes.

- other not supported building types are highlighted in grey, together with "other" buildings, clicking on them and changing them is still possible

- deprecated building types are highlighted in red, i.e. as if the building type hasn't been specified yet. However, if the building has a tag that potentially already describes the building type (e.g. `amenity`, `shop`, `emergency`, etc...), it is not highlighted in red

- the last selected buildings are displayed as buttons below the building selector

- added more selectable buildings: tower, container, tent, outbuilding, tomb also for the quest

- changed the categorization of the buildings: There is now a new category named "outbuilding" (which is also selectable) that contains all those smaller secondary buildings, like garages, sheds, garden allotment buildings, service buildings etc.

### Additionally

https://github.com/streetcomplete/StreetComplete/assets/4661658/9ceac671-8d51-4abe-81c2-7ff291f262c6

- added last-picked buttons to surface overlay (only for main surface), lit overlay, cycleway overlay (for separate cycleways) (fixes #4741 and more)

Test command: ./gradlew :app:testDebugUnitTest --tests "de.westnordost.streetcomplete.quests.building_type.AddBuildingTypeTest" --tests "de.westnordost.streetcomplete.osm.building.BuildingTypeParserKtTest" --tests "de.westnordost.streetcomplete.osm.building.BuildingTypeCreatorKtTest"

Fix patch:
diff --git a/app/src/main/java/de/westnordost/streetcomplete/data/user/achievements/AchievementsModule.kt b/app/src/main/java/de/westnordost/streetcomplete/data/user/achievements/AchievementsModule.kt
index d21aad479f9..5cf5cca484d 100644
--- a/app/src/main/java/de/westnordost/streetcomplete/data/user/achievements/AchievementsModule.kt
+++ b/app/src/main/java/de/westnordost/streetcomplete/data/user/achievements/AchievementsModule.kt
@@ -4,6 +4,7 @@ import de.westnordost.streetcomplete.R
 import de.westnordost.streetcomplete.overlays.street_parking.StreetParkingOverlay
 import de.westnordost.streetcomplete.quests.amenity_cover.AddAmenityCover
 import de.westnordost.streetcomplete.quests.amenity_indoor.AddIsAmenityIndoor
+import de.westnordost.streetcomplete.quests.building_type.AddBuildingType
 import de.westnordost.streetcomplete.quests.cycleway.AddCycleway
 import de.westnordost.streetcomplete.quests.foot.AddProhibitedForPedestrians
 import de.westnordost.streetcomplete.quests.oneway.AddOneway
@@ -56,6 +57,7 @@ private val typeAliases = listOf(
     "WayLitOverlay"                      to AddWayLit::class.simpleName!!,
     "SidewalkOverlay"                    to AddSidewalk::class.simpleName!!,
     "CyclewayOverlay"                    to AddCycleway::class.simpleName!!,
+    "BuildingsOverlay"                   to AddBuildingType::class.simpleName!!,
     "AddStreetParking"                   to StreetParkingOverlay::class.simpleName!!,
     "AddIsDefibrillatorIndoor"           to AddIsAmenityIndoor::class.simpleName!!
 )
diff --git a/app/src/main/java/de/westnordost/streetcomplete/osm/Building.kt b/app/src/main/java/de/westnordost/streetcomplete/osm/Building.kt
deleted file mode 100644
index c94cb4485a7..00000000000
--- a/app/src/main/java/de/westnordost/streetcomplete/osm/Building.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-package de.westnordost.streetcomplete.osm
-
-/** building values that are more or less synonymous with supported building values */
-val buildingSynonyms = mapOf(
-    "public" to "civic",
-    "semi" to "semidetached_house",
-    "shop" to "retail"
-)
diff --git a/app/src/main/java/de/westnordost/streetcomplete/osm/building/BuildingType.kt b/app/src/main/java/de/westnordost/streetcomplete/osm/building/BuildingType.kt
new file mode 100644
index 00000000000..c0c1c3a5ae0
--- /dev/null
+++ b/app/src/main/java/de/westnordost/streetcomplete/osm/building/BuildingType.kt
@@ -0,0 +1,222 @@
+package de.westnordost.streetcomplete.osm.building
+
+enum class BuildingType(val osmKey: String?, val osmValue: String?) {
+    UNSUPPORTED     (null, null),
+
+    HISTORIC        ("historic", "yes"),
+    ABANDONED       ("abandoned", "yes"),
+    RUINS           ("ruins", "yes"),
+
+    HOUSE           ("building", "house"),
+    APARTMENTS      ("building", "apartments"),
+    DETACHED        ("building", "detached"),
+    SEMI_DETACHED   ("building", "semidetached_house"),
+    TERRACE         ("building", "terrace"),
+    HOTEL           ("building", "hotel"),
+    DORMITORY       ("building", "dormitory"),
+    HOUSEBOAT       ("building", "houseboat"),
+    BUNGALOW        ("building", "bungalow"),
+    STATIC_CARAVAN  ("building", "static_caravan"),
+    HUT             ("building", "hut"),
+
+    INDUSTRIAL      ("building", "industrial"),
+    RETAIL          ("building", "retail"),
+    OFFICE          ("building", "office"),
+    WAREHOUSE       ("building", "warehouse"),
+    KIOSK           ("building", "kiosk"),
+    STORAGE_TANK    ("man_made", "storage_tank"),
+    GUARDHOUSE      ("building", "guardhouse"),
+
+    KINDERGARTEN    ("building", "kindergarten"),
+    SCHOOL          ("building", "school"),
+    COLLEGE         ("building", "college"),
+    SPORTS_CENTRE   ("building", "sports_centre"),
+    HOSPITAL        ("building", "hospital"),
+    STADIUM         ("building", "stadium"),
+    GRANDSTAND      ("building", "grandstand"),
+    TRAIN_STATION   ("building", "train_station"),
+    TRANSPORTATION  ("building", "transportation"),
+    FIRE_STATION    ("building", "fire_station"),
+    UNIVERSITY      ("building", "university"),
+    GOVERNMENT      ("building", "government"),
+
+    CHURCH          ("building", "church"),
+    CHAPEL          ("building", "chapel"),
+    CATHEDRAL       ("building", "cathedral"),
+    MOSQUE          ("building", "mosque"),
+    TEMPLE          ("building", "temple"),
+    PAGODA          ("building", "pagoda"),
+    SYNAGOGUE       ("building", "synagogue"),
+    SHRINE          ("building", "shrine"),
+
+    CARPORT         ("building", "carport"),
+    GARAGE          ("building", "garage"),
+    GARAGES         ("building", "garages"),
+    PARKING         ("building", "parking"),
+
+    FARM            ("building", "farm"),
+    FARM_AUXILIARY  ("building", "farm_auxiliary"),
+    SILO            ("man_made", "silo"),
+    GREENHOUSE      ("building", "greenhouse"),
+
+    OUTBUILDING     ("building", "outbuilding"),
+    SHED            ("building", "shed"),
+    ALLOTMENT_HOUSE ("building", "allotment_house"),
+    ROOF            ("building", "roof"),
+    BRIDGE          ("building", "bridge"),
+    TOILETS         ("building", "toilets"),
+    SERVICE         ("building", "service"),
+    HANGAR          ("building", "hangar"),
+    BUNKER          ("building", "bunker"),
+    BOATHOUSE       ("building", "boathouse"),
+    CONTAINER       ("building", "container"),
+    TENT            ("building", "tent"),
+    TOMB            ("building", "tomb"),
+    TOWER           ("man_made", "tower"),
+
+    RESIDENTIAL     ("building", "residential"),
+    COMMERCIAL      ("building", "commercial"),
+    CIVIC           ("building", "civic"),
+    RELIGIOUS       ("building", "religious"),
+
+    CONSTRUCTION    ("building", "construction");
+
+    companion object {
+        val topSelectableValues = listOf(DETACHED, APARTMENTS, HOUSE, GARAGE, SHED, HUT)
+
+        /** a map of tag to [BuildingType] of building features that should be treated as aliases
+         *  of known building types, i.e. that are displayed as that building type but whose tag is
+         *  not modified when saving it again. */
+        val aliases: Map<Pair<String, String>, BuildingType> = mapOf(
+            // for better overview, this list is sorted by how the values appear on the wiki page
+            // for Key:building (if they do appear there)
+
+            // Accommodation
+            ("building" to "cabin") to BUNGALOW,
+            ("building" to "chalet") to BUNGALOW, // not documented
+            ("building" to "summer_cottage") to BUNGALOW, // not documented
+            ("building" to "cottage") to BUNGALOW, // not documented
+            ("building" to "ger") to TENT, // a Mongolian tent
+            ("building" to "stilt_house") to HOUSE,
+            ("building" to "terrace_house") to HOUSE,  // not documented, auto-changing to house would be a loss of information
+            ("building" to "trullo") to HUT,
+            ("building" to "pajaru") to HUT, // not documented, but similar to trullo https://it.wikipedia.org/wiki/Pajaru
+
+            // Commercial
+            ("building" to "manufacture") to INDUSTRIAL, // not documented on main page
+            ("building" to "factory") to INDUSTRIAL, // not documented on main page
+            ("building" to "supermarket") to RETAIL,
+            ("building" to "restaurant") to RETAIL, // not documented
+            ("building" to "pub") to RETAIL, // not documented
+            ("building" to "bank") to RETAIL, // not documented
+
+            // Religious
+            ("building" to "kingdom_hall") to RELIGIOUS,
+            ("building" to "monastery") to RELIGIOUS,
+            ("building" to "presbytery") to RELIGIOUS,
+            ("building" to "wayside_shrine") to RELIGIOUS,
+            ("building" to "convent") to RELIGIOUS,
+
+            // Civic
+            ("building" to "museum") to CIVIC,
+            ("building" to "public") to CIVIC, // pretty much a real synonym
+            ("building" to "government_office") to GOVERNMENT, // not documented
+            ("building" to "education") to CIVIC, // not documented (but I like this tag!!)
+            ("building" to "townhall") to CIVIC,
+            ("building" to "administrative") to GOVERNMENT, // not documented; =government is also for provincial administration
+
+            // Agricultural
+            ("building" to "barn") to FARM_AUXILIARY,
+            ("building" to "cowshed") to FARM_AUXILIARY,
+            ("building" to "stable") to FARM_AUXILIARY,
+            ("building" to "sty") to FARM_AUXILIARY,
+            ("building" to "livestock") to FARM_AUXILIARY,
+            ("building" to "poultry_house") to FARM_AUXILIARY, // not documented
+            ("building" to "chicken_coop") to FARM_AUXILIARY, // not documented
+            ("building" to "granary") to SILO, // not documented
+
+            ("building" to "slurry_tank") to STORAGE_TANK,
+            ("building" to "digester") to STORAGE_TANK,
+            ("building" to "gasometer") to STORAGE_TANK,
+            ("building" to "agricultural") to FARM_AUXILIARY, // not documented
+
+            // Technical
+            ("building" to "tech_cab") to SERVICE,
+            ("building" to "transformer_tower") to SERVICE,
+            ("building" to "power_substation") to SERVICE,
+            ("building" to "tower") to TOWER, // not really a synonym though
+            ("building" to "communications_tower") to TOWER,
+            ("building" to "lighthouse") to TOWER,
+            ("building" to "water_tower") to TOWER,
+            ("building" to "cooling_tower") to TOWER,
+
+            // Other
+            ("building" to "castle") to HISTORIC,
+            ("building" to "canopy") to ROOF, // not documented
+            ("man_made" to "canopy") to ROOF, // not documented
+            ("building" to "gazebo") to ROOF, // not documented
+        )
+
+        /** a set of building values that should be treated as deprecated aliases of known building
+         *  types */
+        val deprecatedValues = setOf(
+            "semi",
+            "semidetached",
+            "semi_detached",
+            "duplex", // -> semidetached_house
+
+            "detached_house", // -> detached
+
+            "terraced_house",
+            "terraced",
+            "townhouse", // -> terrace
+
+            "mobile_home", // -> static_caravan
+
+            "flats", // -> apartments
+
+            "shop", // -> retail
+
+            "storage_tank", // -> man_made=storage_tank
+            "tank", // -> man_made=storage_tank
+            "silo", // -> man_made=silo
+
+            "glasshouse", // ambiguous: could be greenhouse or conservatory
+
+            "collapsed",
+            "damaged",
+            "ruins", // (not explicitly deprecated though)
+            "ruin", // -> ruins=yes
+
+            "abandoned",
+            "disused", // -> abandoned=yes
+
+            "unclassified",
+            "undefined",
+            "unknown",
+            "other",
+            "fixme", // -> yes
+        )
+
+        /** other OSM keys that may describe the purpose of a building */
+        val otherKeysPotentiallyDescribingBuildingType = listOf(
+            // See #1854, #1891, #3233
+            "man_made",
+            "historic",
+            "military",
+            "power",
+            "tourism",
+            "attraction",
+            "amenity",
+            "leisure",
+            "aeroway",
+            "railway",
+            "craft",
+            "healthcare",
+            "office",
+            "shop",
+            "description",
+            "emergency",
+        )
+    }
+}
diff --git a/app/src/main/java/de/westnordost/streetcomplete/osm/building/BuildingTypeCategory.kt b/app/src/main/java/de/westnordost/streetcomplete/osm/building/BuildingTypeCategory.kt
new file mode 100644
index 00000000000..f2b7cfda5c6
--- /dev/null
+++ b/app/src/main/java/de/westnordost/streetcomplete/osm/building/BuildingTypeCategory.kt
@@ -0,0 +1,35 @@
+package de.westnordost.streetcomplete.osm.building
+
+import de.westnordost.streetcomplete.osm.building.BuildingType.*
+
+enum class BuildingTypeCategory(val type: BuildingType?, val subTypes: List<BuildingType>) {
+    RESIDENTIAL(
+        BuildingType.RESIDENTIAL, listOf(
+        DETACHED, APARTMENTS, SEMI_DETACHED, TERRACE, HOUSE, FARM, HUT, BUNGALOW, STATIC_CARAVAN,
+        DORMITORY, HOUSEBOAT,
+    )),
+    COMMERCIAL(
+        BuildingType.COMMERCIAL, listOf(
+        OFFICE, RETAIL, KIOSK, INDUSTRIAL, WAREHOUSE, HOTEL, STORAGE_TANK, PARKING, HANGAR,
+    )),
+    CIVIC(
+        BuildingType.CIVIC, listOf(
+        SCHOOL, UNIVERSITY, HOSPITAL, KINDERGARTEN, SPORTS_CENTRE, TRAIN_STATION, TRANSPORTATION,
+        COLLEGE, GOVERNMENT, TOILETS, STADIUM, FIRE_STATION, OFFICE, GRANDSTAND
+    )),
+    OUTBUILDING(
+        BuildingType.OUTBUILDING, listOf(
+        SHED, GARAGE, GARAGES, CARPORT, SERVICE, ALLOTMENT_HOUSE, GREENHOUSE, ROOF,
+        BOATHOUSE, CONTAINER, TENT, GUARDHOUSE,
+    )),
+    RELIGIOUS(
+        BuildingType.RELIGIOUS, listOf(
+        CHURCH, CATHEDRAL, CHAPEL, MOSQUE, TEMPLE, PAGODA, SYNAGOGUE, SHRINE
+    )),
+    FOR_FARMS(null, listOf(
+        FARM, FARM_AUXILIARY, SILO, GREENHOUSE, STORAGE_TANK, SHED,
+    )),
+    OTHER(null, listOf(
+        ROOF, TOWER, BUNKER, BRIDGE, HISTORIC, ABANDONED, RUINS, TOMB
+    )),
+}
diff --git a/app/src/main/java/de/westnordost/streetcomplete/osm/building/BuildingTypeCategoryItem.kt b/app/src/main/java/de/westnordost/streetcomplete/osm/building/BuildingTypeCategoryItem.kt
new file mode 100644
index 00000000000..3434b5cbbdd
--- /dev/null
+++ b/app/src/main/java/de/westnordost/streetcomplete/osm/building/BuildingTypeCategoryItem.kt
@@ -0,0 +1,45 @@
+package de.westnordost.streetcomplete.osm.building
+
+import de.westnordost.streetcomplete.R
+import de.westnordost.streetcomplete.osm.building.BuildingTypeCategory.CIVIC
+import de.westnordost.streetcomplete.osm.building.BuildingTypeCategory.COMMERCIAL
+import de.westnordost.streetcomplete.osm.building.BuildingTypeCategory.OUTBUILDING
+import de.westnordost.streetcomplete.osm.building.BuildingTypeCategory.FOR_FARMS
+import de.westnordost.streetcomplete.osm.building.BuildingTypeCategory.OTHER
+import de.westnordost.streetcomplete.osm.building.BuildingTypeCategory.RELIGIOUS
+import de.westnordost.streetcomplete.osm.building.BuildingTypeCategory.RESIDENTIAL
+import de.westnordost.streetcomplete.view.image_select.GroupableDisplayItem
+import de.westnordost.streetcomplete.view.image_select.Item
+
+fun Iterable<BuildingTypeCategory>.toItems() = map { it.asItem() }
+
+fun BuildingTypeCategory.asItem(): GroupableDisplayItem<BuildingType> =
+    Item(type, iconResId, titleResId, descriptionResId, subTypes.toItems())
+
+private val BuildingTypeCategory.titleResId: Int get() = when (this) {
+    RESIDENTIAL ->  R.string.quest_buildingType_residential
+    COMMERCIAL ->   R.string.quest_buildingType_commercial
+    CIVIC ->        R.string.quest_buildingType_civic
+    RELIGIOUS ->    R.string.quest_buildingType_religious
+    OUTBUILDING ->  R.string.quest_buildingType_outbuilding
+    FOR_FARMS ->    R.string.quest_buildingType_farm
+    OTHER ->        R.string.quest_buildingType_other
+}
+
+private val BuildingTypeCategory.descriptionResId: Int? get() = when (this) {
+    RESIDENTIAL -> R.string.quest_buildingType_residential_description
+    COMMERCIAL ->  R.string.quest_buildingType_commercial_generic_description
+    CIVIC ->       R.string.quest_buildingType_civic_description
+    OUTBUILDING -> R.string.quest_buildingType_outbuilding_description
+    else ->        null
+}
+
+private val BuildingTypeCategory.iconResId: Int get() = when (this) {
+    RESIDENTIAL ->  R.drawable.ic_building_apartments
+    COMMERCIAL ->   R.drawable.ic_building_office
+    CIVIC ->        R.drawable.ic_building_civic
+    RELIGIOUS ->    R.drawable.ic_building_temple
+    OUTBUILDING ->  R.drawable.ic_building_shed
+    FOR_FARMS ->    R.drawable.ic_building_farm
+    OTHER ->        R.drawable.ic_building_other
+}
diff --git a/app/src/main/java/de/westnordost/streetcomplete/osm/building/BuildingTypeCreator.kt b/app/src/main/java/de/westnordost/streetcomplete/osm/building/BuildingTypeCreator.kt
new file mode 100644
index 00000000000..5f1228eb27d
--- /dev/null
+++ b/app/src/main/java/de/westnordost/streetcomplete/osm/building/BuildingTypeCreator.kt
@@ -0,0 +1,37 @@
+package de.westnordost.streetcomplete.osm.building
+
+import de.westnordost.streetcomplete.osm.Tags
+import de.westnordost.streetcomplete.osm.building.BuildingType.*
+import de.westnordost.streetcomplete.osm.hasCheckDateForKey
+import de.westnordost.streetcomplete.osm.updateCheckDate
+import de.westnordost.streetcomplete.osm.updateCheckDateForKey
+import de.westnordost.streetcomplete.osm.updateWithCheckDate
+
+fun BuildingType.applyTo(tags: Tags) {
+    require(osmKey != null && osmValue != null)
+
+    // do not change anything if it is considered an alias! (This could destroy information, e.g.
+    // building=livestock would be changed to building=farm_auxiliary)
+    val alias = BuildingType.aliases.entries.find { tags[it.key.first] == it.key.second }?.value
+    if (alias == this) {
+        tags.updateCheckDate()
+        return
+    }
+
+    // clear the *=yes tags, after that, re-add if this was selected
+    listOf("disused", "abandoned", "ruins", "historic").forEach {
+        tags.remove(it)
+    }
+
+    // switch between man-made and building
+    if (osmKey == "man_made") tags.remove("building")
+    if (osmKey == "building") tags.remove("man_made")
+
+    tags[osmKey] = osmValue
+
+    // we set the check date and not check_date:building because this is about the primary feature,
+    // not a property of a feature.
+    if (!tags.hasChanges) {
+        tags.updateCheckDate()
+    }
+}
diff --git a/app/src/main/java/de/westnordost/streetcomplete/quests/building_type/BuildingTypeItem.kt b/app/src/main/java/de/westnordost/streetcomplete/osm/building/BuildingTypeItem.kt
similarity index 65%
rename from app/src/main/java/de/westnordost/streetcomplete/quests/building_type/BuildingTypeItem.kt
rename to app/src/main/java/de/westnordost/streetcomplete/osm/building/BuildingTypeItem.kt
index 875ff373b01..c9b87beebac 100644
--- a/app/src/main/java/de/westnordost/streetcomplete/quests/building_type/BuildingTypeItem.kt
+++ b/app/src/main/java/de/westnordost/streetcomplete/osm/building/BuildingTypeItem.kt
@@ -1,19 +1,17 @@
-package de.westnordost.streetcomplete.quests.building_type
+package de.westnordost.streetcomplete.osm.building
 
 import de.westnordost.streetcomplete.R
-import de.westnordost.streetcomplete.quests.building_type.BuildingType.*
+import de.westnordost.streetcomplete.osm.building.BuildingType.*
 import de.westnordost.streetcomplete.view.image_select.GroupableDisplayItem
 import de.westnordost.streetcomplete.view.image_select.Item
 
 fun List<BuildingType>.toItems() = mapNotNull { it.asItem() }
 
-fun BuildingType.asItem(): GroupableDisplayItem<BuildingType>? {
-    val iconResId = iconResId ?: return null
-    val titleResId = titleResId ?: return null
-    return Item(this, iconResId, titleResId, descriptionResId)
-}
+fun BuildingType.asItem(): GroupableDisplayItem<BuildingType> =
+    Item(this, iconResId, titleResId, descriptionResId)
 
-private val BuildingType.titleResId: Int? get() = when (this) {
+private val BuildingType.titleResId: Int get() = when (this) {
+    UNSUPPORTED ->     R.string.quest_buildingType_other
     HOUSE ->           R.string.quest_buildingType_house
     APARTMENTS ->      R.string.quest_buildingType_apartments
     DETACHED ->        R.string.quest_buildingType_detached
@@ -66,8 +64,13 @@ private val BuildingType.titleResId: Int? get() = when (this) {
     TOILETS ->         R.string.quest_buildingType_toilets
     SERVICE ->         R.string.quest_buildingType_service
     HANGAR ->          R.string.quest_buildingType_hangar
+    TOWER ->           R.string.quest_buildingType_tower
     BUNKER ->          R.string.quest_buildingType_bunker
     BOATHOUSE ->       R.string.quest_buildingType_boathouse
+    CONTAINER ->       R.string.quest_buildingType_container
+    OUTBUILDING ->     R.string.quest_buildingType_outbuilding
+    TENT ->            R.string.quest_buildingType_tent
+    TOMB ->            R.string.quest_buildingType_tomb
     HISTORIC ->        R.string.quest_buildingType_historic
     ABANDONED ->       R.string.quest_buildingType_abandoned
     RUINS ->           R.string.quest_buildingType_ruins
@@ -76,16 +79,18 @@ private val BuildingType.titleResId: Int? get() = when (this) {
     CIVIC ->           R.string.quest_buildingType_civic
     RELIGIOUS ->       R.string.quest_buildingType_religious
     GUARDHOUSE ->      R.string.quest_buildingType_guardhouse
-    CONSTRUCTION ->    null
+    CONSTRUCTION ->    R.string.quest_buildingType_under_construction
 }
 
 private val BuildingType.descriptionResId: Int? get() = when (this) {
+    UNSUPPORTED ->     R.string.quest_buildingType_other_description
     HOUSE ->           R.string.quest_buildingType_house_description2
     APARTMENTS ->      R.string.quest_buildingType_apartments_description
     DETACHED ->        R.string.quest_buildingType_detached_description
     SEMI_DETACHED ->   R.string.quest_buildingType_semi_detached_description2
     TERRACE ->         R.string.quest_buildingType_terrace_description
     BUNGALOW ->        R.string.quest_buildingType_bungalow_description2
+    OUTBUILDING ->     R.string.quest_buildingType_outbuilding_description
     HUT ->             R.string.quest_buildingType_hut_description
     INDUSTRIAL ->      R.string.quest_buildingType_industrial_description
     RETAIL ->          R.string.quest_buildingType_retail_description
@@ -95,6 +100,7 @@ private val BuildingType.descriptionResId: Int? get() = when (this) {
     FARM_AUXILIARY ->  R.string.quest_buildingType_farm_auxiliary_description
     SERVICE ->         R.string.quest_buildingType_service_description
     HANGAR ->          R.string.quest_buildingType_hangar_description
+    TOWER ->           R.string.quest_buildingType_tower_description
     HISTORIC ->        R.string.quest_buildingType_historic_description
     ABANDONED ->       R.string.quest_buildingType_abandoned_description
     RUINS ->           R.string.quest_buildingType_ruins_description
@@ -104,7 +110,8 @@ private val BuildingType.descriptionResId: Int? get() = when (this) {
     else ->            null
 }
 
-private val BuildingType.iconResId: Int? get() = when (this) {
+val BuildingType.iconResId: Int get() = when (this) {
+    UNSUPPORTED ->     R.drawable.ic_building_other
     HOUSE ->           R.drawable.ic_building_house
     APARTMENTS ->      R.drawable.ic_building_apartments
     DETACHED ->        R.drawable.ic_building_detached
@@ -157,8 +164,13 @@ private val BuildingType.iconResId: Int? get() = when (this) {
     TOILETS ->         R.drawable.ic_building_toilets
     SERVICE ->         R.drawable.ic_building_service
     HANGAR ->          R.drawable.ic_building_hangar
+    TOWER ->           R.drawable.ic_building_tower
     BUNKER ->          R.drawable.ic_building_bunker
     BOATHOUSE ->       R.drawable.ic_building_boathouse
+    OUTBUILDING ->     R.drawable.ic_building_shed
+    CONTAINER ->       R.drawable.ic_building_container
+    TENT ->            R.drawable.ic_building_tent
+    TOMB ->            R.drawable.ic_building_tomb
     HISTORIC ->        R.drawable.ic_building_historic
     ABANDONED ->       R.drawable.ic_building_abandoned
     RUINS ->           R.drawable.ic_building_ruins
@@ -167,5 +179,78 @@ private val BuildingType.iconResId: Int? get() = when (this) {
     CIVIC ->           R.drawable.ic_building_civic
     RELIGIOUS ->       R.drawable.ic_building_temple
     GUARDHOUSE ->      R.drawable.ic_building_guardhouse
-    CONSTRUCTION ->    null
+    CONSTRUCTION ->    R.drawable.ic_building_construction
+}
+
+// unfortunately, we need a string but we do not have access to resources at the point we need it
+val BuildingType.iconResName: String get() = when (this) {
+    UNSUPPORTED ->     "ic_building_other"
+    HOUSE ->           "ic_building_house"
+    APARTMENTS ->      "ic_building_apartments"
+    DETACHED ->        "ic_building_detached"
+    SEMI_DETACHED ->   "ic_building_semi_detached"
+    TERRACE ->         "ic_building_terrace"
+    HOTEL ->           "ic_building_hotel"
+    DORMITORY ->       "ic_building_dormitory"
+    HOUSEBOAT ->       "ic_building_houseboat"
+    BUNGALOW ->        "ic_building_bungalow"
+    STATIC_CARAVAN ->  "ic_building_static_caravan"
+    HUT ->             "ic_building_hut"
+    INDUSTRIAL ->      "ic_building_industrial"
+    RETAIL ->          "ic_building_retail"
+    OFFICE ->          "ic_building_office"
+    WAREHOUSE ->       "ic_building_warehouse"
+    KIOSK ->           "ic_building_kiosk"
+    STORAGE_TANK ->    "ic_building_storage_tank"
+    KINDERGARTEN ->    "ic_building_kindergarten"
+    SCHOOL ->          "ic_building_school"
+    COLLEGE ->         "ic_building_college"
+    SPORTS_CENTRE ->   "ic_sport_volleyball"
+    HOSPITAL ->        "ic_building_hospital"
+    STADIUM ->         "ic_sport_volleyball"
+    GRANDSTAND ->      "ic_sport_volleyball"
+    TRAIN_STATION ->   "ic_building_train_station"
+    TRANSPORTATION ->  "ic_building_transportation"
+    FIRE_STATION ->    "ic_building_fire_truck"
+    UNIVERSITY ->      "ic_building_university"
+    GOVERNMENT ->      "ic_building_historic"
+    CHURCH ->          "ic_religion_christian"
+    CHAPEL ->          "ic_religion_christian"
+    CATHEDRAL ->       "ic_religion_christian"
+    MOSQUE ->          "ic_religion_muslim"
+    TEMPLE ->          "ic_building_temple"
+    PAGODA ->          "ic_building_temple"
+    SYNAGOGUE ->       "ic_religion_jewish"
+    SHRINE ->          "ic_building_temple"
+    CARPORT ->         "ic_building_carport"
+    GARAGE ->          "ic_building_garage"
+    GARAGES ->         "ic_building_garages"
+    PARKING ->         "ic_building_parking"
+    FARM ->            "ic_building_farm_house"
+    FARM_AUXILIARY ->  "ic_building_barn"
+    SILO ->            "ic_building_silo"
+    GREENHOUSE ->      "ic_building_greenhouse"
+    SHED ->            "ic_building_shed"
+    ALLOTMENT_HOUSE -> "ic_building_allotment_house"
+    ROOF ->            "ic_building_roof"
+    BRIDGE ->          "ic_building_bridge"
+    TOILETS ->         "ic_building_toilets"
+    SERVICE ->         "ic_building_service"
+    HANGAR ->          "ic_building_hangar"
+    TOWER ->           "ic_building_tower"
+    BUNKER ->          "ic_building_bunker"
+    BOATHOUSE ->       "ic_building_boathouse"
+    OUTBUILDING ->     "ic_building_shed"
+    CONTAINER ->       "ic_building_container"
+    TENT ->            "ic_building_tent"
+    TOMB ->            "ic_building_tomb"
+    HISTORIC ->        "ic_building_historic"
+    ABANDONED ->       "ic_building_abandoned"
+    RUINS ->           "ic_building_ruins"
+    RESIDENTIAL ->     "ic_building_apartments"
+    COMMERCIAL ->      "ic_building_office"
+    CIVIC ->           "ic_building_civic"
+    RELIGIOUS ->       "ic_building_temple"
+    GUARDHOUSE ->      "ic_building_guardhouse"
+    CONSTRUCTION ->    "ic_building_construction"
 }
diff --git a/app/src/main/java/de/westnordost/streetcomplete/osm/building/BuildingTypeParser.kt b/app/src/main/java/de/westnordost/streetcomplete/osm/building/BuildingTypeParser.kt
new file mode 100644
index 00000000000..a4e2da50325
--- /dev/null
+++ b/app/src/main/java/de/westnordost/streetcomplete/osm/building/BuildingTypeParser.kt
@@ -0,0 +1,37 @@
+package de.westnordost.streetcomplete.osm.building
+
+fun createBuildingType(tags: Map<String, String>): BuildingType? {
+    val building = BuildingType.entries.find { it.osmKey != null && tags[it.osmKey] == it.osmValue }
+        ?: BuildingType.aliases.entries.find { tags[it.key.first] == it.key.second }?.value
+
+    if (building == BuildingType.HOUSE) return createBuildingTypeFromHouseType(tags["house"])
+
+    if (building != null) return building
+
+    val buildingValue = tags["building"]
+
+    // treat unspecified building value as unspecified...
+    if (buildingValue == "yes") return null
+
+    // treat deprecated building value as if it is unspecified
+    if (buildingValue in BuildingType.deprecatedValues) return null
+
+    // ah yes, those two clowns...
+    if (buildingValue == "no" || buildingValue == "entrance") return null
+
+    // no building and no man_made value at all
+    if (buildingValue == null && tags["man_made"] == null) return null
+
+    // otherwise, there is some value but we do not support it
+    return BuildingType.UNSUPPORTED
+}
+
+private fun createBuildingTypeFromHouseType(houseType: String?): BuildingType = when(houseType) {
+    null ->             BuildingType.HOUSE
+    "detached" ->       BuildingType.DETACHED
+    "terrace" ->        BuildingType.TERRACE
+    "semi-detached" ->  BuildingType.SEMI_DETACHED
+    "bungalow" ->       BuildingType.BUNGALOW
+
+    else ->             BuildingType.HOUSE
+}
diff --git a/app/src/main/java/de/westnordost/streetcomplete/overlays/AGroupedImageSelectOverlayForm.kt b/app/src/main/java/de/westnordost/streetcomplete/overlays/AGroupedImageSelectOverlayForm.kt
new file mode 100644
index 00000000000..1b11705557f
--- /dev/null
+++ b/app/src/main/java/de/westnordost/streetcomplete/overlays/AGroupedImageSelectOverlayForm.kt
@@ -0,0 +1,138 @@
+package de.westnordost.streetcomplete.overlays
+
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.core.view.children
+import androidx.core.view.isGone
+import androidx.recyclerview.widget.RecyclerView
+import de.westnordost.streetcomplete.R
+import de.westnordost.streetcomplete.databinding.CellLastPickedButtonBinding
+import de.westnordost.streetcomplete.databinding.FragmentGroupedOverlayImageSelectBinding
+import de.westnordost.streetcomplete.view.image_select.GroupableDisplayItem
+import de.westnordost.streetcomplete.view.image_select.GroupedImageListPickerDialog
+import de.westnordost.streetcomplete.view.image_select.ItemViewHolder
+import de.westnordost.streetcomplete.view.setImage
+
+/** Abstract base class for any overlay form in which the user selects a grouped item */
+abstract class AGroupedImageSelectOverlayForm<I> : AbstractOverlayForm() {
+    // mostly copy-pasta from AImageSelectOverlayForm / AGroupedImageListQuestForm :-(
+
+    final override val contentLayoutResId = R.layout.fragment_grouped_overlay_image_select
+    private val binding by contentViewBinding(FragmentGroupedOverlayImageSelectBinding::bind)
+
+    protected open val itemsPerRow = 1
+
+    /** all items to display. May not be accessed before onCreate */
+    protected abstract val allItems: List<GroupableDisplayItem<I>>
+    /** items to display that are shown as last picked answers. May not be accessed before onCreate */
+    protected open val lastPickedItems: List<GroupableDisplayItem<I>> = emptyList()
+
+    protected open val cellLayoutId: Int = R.layout.cell_labeled_icon_select_with_description
+    protected open val groupCellLayoutId: Int = R.layout.cell_labeled_icon_select_with_description_group
+
+    private lateinit var itemsByString: Map<String, GroupableDisplayItem<I>>
+
+    var selectedItem: GroupableDisplayItem<I>? = null
+        set(value) {
+            field = value
+            updateSelectedCell()
+        }
+
+    override fun onCreate(savedInstanceState: Bundle?) {
+        super.onCreate(savedInstanceState)
+        itemsByString = allItems.mapNotNull { it.items }.flatten().associateBy { it.value.toString() }
+    }
+
+    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+        super.onViewCreated(view, savedInstanceState)
+
+        binding.selectButton.root.setOnClickListener {
+            GroupedImageListPickerDialog(requireContext(), allItems, groupCellLayoutId, cellLayoutId, itemsPerRow) { item ->
+                if (item != selectedItem) {
+                    selectedItem = item
+                    checkIsFormComplete()
+                }
+            }.show()
+        }
+
+        if (savedInstanceState != null) onLoadInstanceState(savedInstanceState)
+
+        LayoutInflater.from(requireContext()).inflate(cellLayoutId, binding.selectButton.selectedCellView, true)
+        binding.selectButton.selectedCellView.children.first().background = null
+
+        binding.lastPickedButtons.isGone = lastPickedItems.isEmpty()
+        binding.lastPickedButtons.adapter = LastPickedAdapter(lastPickedItems, ::onLastPickedButtonClicked)
+
+        updateSelectedCell()
+    }
+
+    private fun updateSelectedCell() {
+        val item = selectedItem
+        binding.selectButton.selectTextView.isGone = item != null
+        binding.selectButton.selectedCellView.isGone = item == null
+        if (item != null) {
+            ItemViewHolder(binding.selectButton.selectedCellView).bind(item)
+        }
+    }
+
+    /* ------------------------------------- instance state ------------------------------------- */
+
+    private fun onLoadInstanceState(inState: Bundle) {
+        selectedItem = inState.getString(SELECTED)?.let { itemsByString[it] }
+    }
+
+    override fun onSaveInstanceState(outState: Bundle) {
+        super.onSaveInstanceState(outState)
+        outState.putString(SELECTED, selectedItem?.value?.toString())
+    }
+
+    /* -------------------------------------- apply answer -------------------------------------- */
+
+    override fun isFormComplete() = selectedItem?.value != null
+
+    /* --------------------------------------- fav items ---------------------------------------- */
+
+    private fun onLastPickedButtonClicked(position: Int) {
+        val item = lastPickedItems[position]
+        selectedItem = item
+        checkIsFormComplete()
+    }
+
+    companion object {
+        private const val SELECTED = "selected"
+    }
+}
+
+private class LastPickedAdapter<I>(
+    private val items: List<GroupableDisplayItem<I>>,
+    private val onItemClicked: (position: Int) -> Unit
+) : RecyclerView.Adapter<LastPickedAdapter<I>.ViewHolder>() {
+
+    inner class ViewHolder(
+        private val binding: CellLastPickedButtonBinding,
+        private val onItemClicked: (position: Int) -> Unit
+    ) : RecyclerView.ViewHolder(binding.root) {
+
+        init {
+            itemView.setOnClickListener { onItemClicked(bindingAdapterPosition) }
+        }
+
+        fun onBind(item: GroupableDisplayItem<I>) {
+            binding.root.setImage(item.image)
+        }
+    }
+
+    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
+        val inflater = LayoutInflater.from(parent.context)
+        val binding = CellLastPickedButtonBinding.inflate(inflater, parent, false)
+        return ViewHolder(binding, onItemClicked)
+    }
+
+    override fun onBindViewHolder(viewHolder: ViewHolder, position: Int) {
+        viewHolder.onBind(items[position])
+    }
+
+    override fun getItemCount() = items.size
+}
diff --git a/app/src/main/java/de/westnordost/streetcomplete/overlays/AImageSelectOverlayForm.kt b/app/src/main/java/de/westnordost/streetcomplete/overlays/AImageSelectOverlayForm.kt
index 8cbd86a57c8..9be8bb8f97c 100644
--- a/app/src/main/java/de/westnordost/streetcomplete/overlays/AImageSelectOverlayForm.kt
+++ b/app/src/main/java/de/westnordost/streetcomplete/overlays/AImageSelectOverlayForm.kt
@@ -8,8 +8,10 @@ import androidx.core.view.isGone
 import de.westnordost.streetcomplete.R
 import de.westnordost.streetcomplete.databinding.FragmentOverlayImageSelectBinding
 import de.westnordost.streetcomplete.view.image_select.DisplayItem
+import de.westnordost.streetcomplete.view.image_select.GroupableDisplayItem
 import de.westnordost.streetcomplete.view.image_select.ImageListPickerDialog
 import de.westnordost.streetcomplete.view.image_select.ItemViewHolder
+import de.westnordost.streetcomplete.view.setImage
 
 /** Abstract base class for any overlay form in which the user selects an image item */
 abstract class AImageSelectOverlayForm<I> : AbstractOverlayForm() {
@@ -20,6 +22,9 @@ abstract class AImageSelectOverlayForm<I> : AbstractOverlayForm() {
     protected open val itemsPerRow = 2
     /** items to display. May not be accessed before onCreate */
     protected abstract val items: List<DisplayItem<I>>
+    /** item to display as last picked answer. May not be accessed before onCreate */
+    protected open val lastPickedItem: DisplayItem<I>? = null
+
     protected open val cellLayoutId: Int = R.layout.cell_icon_select_with_label_below
 
     var selectedItem: DisplayItem<I>? = null
@@ -45,6 +50,14 @@ abstract class AImageSelectOverlayForm<I> : AbstractOverlayForm() {
         LayoutInflater.from(requireContext()).inflate(cellLayoutId, binding.selectButton.selectedCellView, true)
         binding.selectButton.selectedCellView.children.first().background = null
 
+        binding.lastPickedButton.isGone = lastPickedItem == null
+        binding.lastPickedButton.setImage(lastPickedItem?.image)
+        binding.lastPickedButton.setOnClickListener {
+            selectedItem = lastPickedItem
+            binding.lastPickedButton.isGone = true
+            checkIsFormComplete()
+        }
+
         updateSelectedCell()
     }
 
diff --git a/app/src/main/java/de/westnordost/streetcomplete/overlays/Overlay.kt b/app/src/main/java/de/westnordost/streetcomplete/overlays/Overlay.kt
index 6805575cb50..e6225185681 100644
--- a/app/src/main/java/de/westnordost/streetcomplete/overlays/Overlay.kt
+++ b/app/src/main/java/de/westnordost/streetcomplete/overlays/Overlay.kt
@@ -14,6 +14,7 @@ interface Overlay : ElementEditType {
     /** scene updates that should be applied to the map when this overlay is active */
     val sceneUpdates: List<Pair<String, String>>? get() = null
 
+    /** Whether the form can be opened with a null element (=new element) */
     val isCreateNodeEnabled: Boolean get() = false
 
     /** return pairs of element to style for all elements in the map data that should be displayed */
diff --git a/app/src/main/java/de/westnordost/streetcomplete/overlays/OverlaysModule.kt b/app/src/main/java/de/westnordost/streetcomplete/overlays/OverlaysModule.kt
index 893b17348c0..fc2022b27de 100644
--- a/app/src/main/java/de/westnordost/streetcomplete/overlays/OverlaysModule.kt
+++ b/app/src/main/java/de/westnordost/streetcomplete/overlays/OverlaysModule.kt
@@ -9,6 +9,7 @@ import de.westnordost.streetcomplete.data.meta.getByLocation
 import de.westnordost.streetcomplete.data.osm.mapdata.LatLon
 import de.westnordost.streetcomplete.data.overlays.OverlayRegistry
 import de.westnordost.streetcomplete.overlays.address.AddressOverlay
+import de.westnordost.streetcomplete.overlays.buildings.BuildingsOverlay
 import de.westnordost.streetcomplete.overlays.cycleway.CyclewayOverlay
 import de.westnordost.streetcomplete.overlays.shops.ShopsOverlay
 import de.westnordost.streetcomplete.overlays.sidewalk.SidewalkOverlay
@@ -54,4 +55,5 @@ fun overlaysRegistry(
     2 to StreetParkingOverlay(),
     3 to AddressOverlay(getCountryCodeByLocation),
     4 to ShopsOverlay(getFeature),
+    7 to BuildingsOverlay()
 ))
diff --git a/app/src/main/java/de/westnordost/streetcomplete/overlays/buildings/BuildingsOverlay.kt b/app/src/main/java/de/westnordost/streetcomplete/overlays/buildings/BuildingsOverlay.kt
new file mode 100644
index 00000000000..39d1fc86522
--- /dev/null
+++ b/app/src/main/java/de/westnordost/streetcomplete/overlays/buildings/BuildingsOverlay.kt
@@ -0,0 +1,87 @@
+package de.westnordost.streetcomplete.overlays.buildings
+
+import de.westnordost.streetcomplete.R
+import de.westnordost.streetcomplete.data.osm.mapdata.Element
+import de.westnordost.streetcomplete.data.osm.mapdata.MapDataWithGeometry
+import de.westnordost.streetcomplete.data.osm.mapdata.filter
+import de.westnordost.streetcomplete.overlays.Overlay
+import de.westnordost.streetcomplete.data.user.achievements.EditTypeAchievement.BUILDING
+import de.westnordost.streetcomplete.overlays.AbstractOverlayForm
+import de.westnordost.streetcomplete.overlays.Color
+import de.westnordost.streetcomplete.overlays.PolygonStyle
+import de.westnordost.streetcomplete.quests.building_type.AddBuildingType
+import de.westnordost.streetcomplete.osm.building.BuildingType
+import de.westnordost.streetcomplete.osm.building.BuildingType.*
+import de.westnordost.streetcomplete.osm.building.createBuildingType
+import de.westnordost.streetcomplete.osm.building.iconResName
+
+class BuildingsOverlay : Overlay {
+
+    override val title = R.string.overlay_buildings
+    override val icon = R.drawable.ic_quest_building
+    override val changesetComment = "Survey buildings"
+    override val wikiLink = "Key:building"
+    override val achievements = listOf(BUILDING)
+    override val hidesQuestTypes = setOf(AddBuildingType::class.simpleName!!)
+
+    /* building:use not supported, so don't offer to change it -> exclude from the overlay */
+    override fun getStyledElements(mapData: MapDataWithGeometry) = mapData.filter(
+        """
+            ways, relations with
+              (building and building !~ no|entrance
+              or man_made ~ communications_tower|tower|lighthouse|chimney|silo|storage_tank|water_tower|gasometer|cooling_tower
+              ) and !building:use
+        """)
+        .map { element ->
+            val building = createBuildingType(element.tags)
+
+            val color = building?.color
+                ?: if (isBuildingTypeMissing(element.tags)) Color.DATA_REQUESTED else Color.INVISIBLE
+
+            element to PolygonStyle(color = color, icon = building?.iconResName)
+        }
+
+    override fun createForm(element: Element?) = BuildingsOverlayForm()
+
+    private val BuildingType.color get() = when(this) {
+        // ~detached homes
+        DETACHED, SEMI_DETACHED, HOUSEBOAT, BUNGALOW, STATIC_CARAVAN, HUT, FARM, -> // 10%
+            Color.BLUE
+
+        // ~non-detached homes
+        HOUSE, DORMITORY, APARTMENTS, TERRACE, -> // 52%
+            Color.SKY
+
+        // unspecified residential
+        RESIDENTIAL, -> // 12%
+            Color.CYAN
+
+        // parking, sheds, outbuildings in general...
+        OUTBUILDING, CARPORT, GARAGE, GARAGES, SHED, BOATHOUSE, SERVICE, ALLOTMENT_HOUSE,
+        TENT, CONTAINER, GUARDHOUSE, -> // 11%
+            Color.LIME
+
+        // commercial, industrial, farm buildings
+        COMMERCIAL, KIOSK, RETAIL, OFFICE, BRIDGE, HOTEL, PARKING,
+        INDUSTRIAL, WAREHOUSE, HANGAR, STORAGE_TANK,
+        FARM_AUXILIARY, SILO, GREENHOUSE,
+        ROOF -> // 5%
+            Color.GOLD
+
+        // amenity buildings
+        TRAIN_STATION, TRANSPORTATION,
+        CIVIC, GOVERNMENT, FIRE_STATION, HOSPITAL,
+        KINDERGARTEN, SCHOOL, COLLEGE, UNIVERSITY, SPORTS_CENTRE, STADIUM, GRANDSTAND,
+        RELIGIOUS, CHURCH, CHAPEL, CATHEDRAL, MOSQUE, TEMPLE, PAGODA, SYNAGOGUE, SHRINE,
+        TOILETS, -> // 2%
+            Color.ORANGE
+
+        // other/special
+        HISTORIC, ABANDONED, RUINS, CONSTRUCTION, BUNKER, TOMB, TOWER,
+        UNSUPPORTED ->
+            Color.GRAY
+    }
+
+    private fun isBuildingTypeMissing(tags: Map<String, String>): Boolean =
+        !BuildingType.otherKeysPotentiallyDescribingBuildingType.any { it in tags }
+}
diff --git a/app/src/main/java/de/westnordost/streetcomplete/overlays/buildings/BuildingsOverlayForm.kt b/app/src/main/java/de/westnordost/streetcomplete/overlays/buildings/BuildingsOverlayForm.kt
new file mode 100644
index 00000000000..54347e9189f
--- /dev/null
+++ b/app/src/main/java/de/westnordost/streetcomplete/overlays/buildings/BuildingsOverlayForm.kt
@@ -0,0 +1,71 @@
+package de.westnordost.streetcomplete.overlays.buildings
+
+import android.content.Context
+import android.os.Bundle
+import android.view.View
+import de.westnordost.streetcomplete.data.osm.edits.update_tags.StringMapChangesBuilder
+import de.westnordost.streetcomplete.data.osm.edits.update_tags.UpdateElementTagsAction
+import de.westnordost.streetcomplete.osm.building.BuildingType
+import de.westnordost.streetcomplete.osm.building.BuildingTypeCategory
+import de.westnordost.streetcomplete.osm.building.applyTo
+import de.westnordost.streetcomplete.osm.building.asItem
+import de.westnordost.streetcomplete.osm.building.createBuildingType
+import de.westnordost.streetcomplete.osm.building.toItems
+import de.westnordost.streetcomplete.overlays.AGroupedImageSelectOverlayForm
+import de.westnordost.streetcomplete.util.LastPickedValuesStore
+import de.westnordost.streetcomplete.util.getNameAndLocationLabel
+import de.westnordost.streetcomplete.util.mostCommonWithin
+import de.westnordost.streetcomplete.util.padWith
+import de.westnordost.streetcomplete.util.prefs.Preferences
+import de.westnordost.streetcomplete.view.image_select.GroupableDisplayItem
+import org.koin.android.ext.android.inject
+
+class BuildingsOverlayForm : AGroupedImageSelectOverlayForm<BuildingType>() {
+
+    private val prefs: Preferences by inject()
+    private lateinit var favs: LastPickedValuesStore<GroupableDisplayItem<BuildingType>>
+
+    override val allItems = BuildingTypeCategory.entries.toItems()
+
+    override val itemsPerRow = 1
+
+    private val maxLastPickedBuildings = 6
+
+    override val lastPickedItems by lazy {
+        favs.get()
+            .mostCommonWithin(maxLastPickedBuildings, historyCount = 50, first = 1)
+            .padWith(BuildingType.topSelectableValues.take(maxLastPickedBuildings).toItems())
+            .toList()
+    }
+
+    private var originalBuilding: BuildingType? = null
+
+    override fun onAttach(ctx: Context) {
+        super.onAttach(ctx)
+        favs = LastPickedValuesStore(
+            prefs,
+            key = javaClass.simpleName,
+            serialize = { it.value!!.name },
+            deserialize = { BuildingType.valueOf(it).asItem() }
+        )
+    }
+
+    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+        super.onViewCreated(view, savedInstanceState)
+
+        originalBuilding = createBuildingType(element!!.tags)
+        selectedItem = originalBuilding?.asItem()
+
+        setTitleHintLabel(getNameAndLocationLabel(element!!, resources, null, true))
+    }
+
+    override fun hasChanges(): Boolean =
+        selectedItem?.value != originalBuilding
+
+    override fun onClickOk() {
+        favs.add(selectedItem!!)
+        val tagChanges = StringMapChangesBuilder(element!!.tags)
+        selectedItem!!.value!!.applyTo(tagChanges)
+        applyEdit(UpdateElementTagsAction(element!!, tagChanges.create()))
+    }
+}
diff --git a/app/src/main/java/de/westnordost/streetcomplete/overlays/cycleway/SeparateCyclewayForm.kt b/app/src/main/java/de/westnordost/streetcomplete/overlays/cycleway/SeparateCyclewayForm.kt
index 273dbe39380..4c23557776b 100644
--- a/app/src/main/java/de/westnordost/streetcomplete/overlays/cycleway/SeparateCyclewayForm.kt
+++ b/app/src/main/java/de/westnordost/streetcomplete/overlays/cycleway/SeparateCyclewayForm.kt
@@ -1,5 +1,6 @@
 package de.westnordost.streetcomplete.overlays.cycleway
 
+import android.content.Context
 import android.os.Bundle
 import android.view.View
 import de.westnordost.streetcomplete.R
@@ -10,8 +11,13 @@ import de.westnordost.streetcomplete.osm.cycleway_separate.SeparateCycleway.*
 import de.westnordost.streetcomplete.osm.cycleway_separate.applyTo
 import de.westnordost.streetcomplete.osm.cycleway_separate.asItem
 import de.westnordost.streetcomplete.osm.cycleway_separate.parseSeparateCycleway
+import de.westnordost.streetcomplete.osm.lit.LitStatus
+import de.westnordost.streetcomplete.osm.lit.asItem
 import de.westnordost.streetcomplete.overlays.AImageSelectOverlayForm
+import de.westnordost.streetcomplete.util.LastPickedValuesStore
+import de.westnordost.streetcomplete.util.prefs.Preferences
 import de.westnordost.streetcomplete.view.image_select.DisplayItem
+import org.koin.android.ext.android.inject
 
 class SeparateCyclewayForm : AImageSelectOverlayForm<SeparateCycleway>() {
 
@@ -20,11 +26,27 @@ class SeparateCyclewayForm : AImageSelectOverlayForm<SeparateCycleway>() {
             it.asItem(countryInfo.isLeftHandTraffic)
         }
 
+    private val prefs: Preferences by inject()
+    private lateinit var favs: LastPickedValuesStore<DisplayItem<SeparateCycleway>>
+
+    override val lastPickedItem: DisplayItem<SeparateCycleway>?
+        get() = favs.get().firstOrNull()
+
     override val itemsPerRow = 1
     override val cellLayoutId = R.layout.cell_labeled_icon_select_right
 
     private var currentCycleway: SeparateCycleway? = null
 
+    override fun onAttach(ctx: Context) {
+        super.onAttach(ctx)
+        favs = LastPickedValuesStore(
+            prefs,
+            key = javaClass.simpleName,
+            serialize = { it.value!!.name },
+            deserialize = { SeparateCycleway.valueOf(it).asItem(countryInfo.isLeftHandTraffic) }
+        )
+    }
+
     override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
         super.onViewCreated(view, savedInstanceState)
 
@@ -61,6 +83,7 @@ class SeparateCyclewayForm : AImageSelectOverlayForm<SeparateCycleway>() {
         selectedItem?.value != currentCycleway
 
     override fun onClickOk() {
+        favs.add(selectedItem!!)
         val tagChanges = StringMapChangesBuilder(element!!.tags)
         selectedItem!!.value!!.applyTo(tagChanges)
         applyEdit(UpdateElementTagsAction(element!!, tagChanges.create()))
diff --git a/app/src/main/java/de/westnordost/streetcomplete/overlays/surface/SurfaceOverlayForm.kt b/app/src/main/java/de/westnordost/streetcomplete/overlays/surface/SurfaceOverlayForm.kt
index 310248eef14..ce678f5a399 100644
--- a/app/src/main/java/de/westnordost/streetcomplete/overlays/surface/SurfaceOverlayForm.kt
+++ b/app/src/main/java/de/westnordost/streetcomplete/overlays/surface/SurfaceOverlayForm.kt
@@ -1,5 +1,6 @@
 package de.westnordost.streetcomplete.overlays.surface
 
+import android.content.Context
 import android.os.Bundle
 import android.view.View
 import androidx.core.view.isGone
@@ -13,8 +14,10 @@ import de.westnordost.streetcomplete.databinding.FragmentOverlaySurfaceSelectBin
 import de.westnordost.streetcomplete.osm.ALL_PATHS
 import de.westnordost.streetcomplete.osm.changeToSteps
 import de.westnordost.streetcomplete.osm.surface.SELECTABLE_WAY_SURFACES
+import de.westnordost.streetcomplete.osm.surface.Surface
 import de.westnordost.streetcomplete.osm.surface.SurfaceAndNote
 import de.westnordost.streetcomplete.osm.surface.applyTo
+import de.westnordost.streetcomplete.osm.surface.asItem
 import de.westnordost.streetcomplete.osm.surface.isComplete
 import de.westnordost.streetcomplete.osm.surface.parseSurface
 import de.westnordost.streetcomplete.osm.surface.parseSurfaceAndNote
@@ -22,13 +25,23 @@ import de.westnordost.streetcomplete.osm.surface.updateCommonSurfaceFromFootAndC
 import de.westnordost.streetcomplete.overlays.AbstractOverlayForm
 import de.westnordost.streetcomplete.overlays.AnswerItem
 import de.westnordost.streetcomplete.overlays.IAnswerItem
+import de.westnordost.streetcomplete.util.LastPickedValuesStore
 import de.westnordost.streetcomplete.util.getFeatureName
 import de.westnordost.streetcomplete.util.ktx.couldBeSteps
+import de.westnordost.streetcomplete.util.prefs.Preferences
+import de.westnordost.streetcomplete.view.setImage
+import org.koin.android.ext.android.inject
 
 class SurfaceOverlayForm : AbstractOverlayForm() {
     override val contentLayoutResId = R.layout.fragment_overlay_surface_select
     private val binding by contentViewBinding(FragmentOverlaySurfaceSelectBinding::bind)
 
+    private val prefs: Preferences by inject()
+    private lateinit var favs: LastPickedValuesStore<Surface>
+    private val lastPickedSurface: Surface?
+        get() = favs.get().firstOrNull()
+
+
     private lateinit var surfaceCtrl: SurfaceAndNoteViewController
     private lateinit var cyclewaySurfaceCtrl: SurfaceAndNoteViewController
     private lateinit var footwaySurfaceCtrl: SurfaceAndNoteViewController
@@ -59,6 +72,17 @@ class SurfaceOverlayForm : AbstractOverlayForm() {
         binding.main.root.isGone = true
         binding.cyclewaySurfaceContainer.isGone = false
         binding.footwaySurfaceContainer.isGone = false
+        binding.lastPickedButton.isGone = true
+    }
+
+    override fun onAttach(ctx: Context) {
+        super.onAttach(ctx)
+        favs = LastPickedValuesStore(
+            prefs,
+            key = javaClass.simpleName,
+            serialize = { it.name },
+            deserialize = { Surface.valueOf(it) }
+        )
     }
 
     override fun onCreate(savedInstanceState: Bundle?) {
@@ -105,6 +129,14 @@ class SurfaceOverlayForm : AbstractOverlayForm() {
             initStateFromTags()
         }
 
+        binding.lastPickedButton.isGone = lastPickedSurface == null
+        binding.lastPickedButton.setImage(lastPickedSurface?.asItem()?.image)
+        binding.lastPickedButton.setOnClickListener {
+            surfaceCtrl.value = SurfaceAndNote(lastPickedSurface)
+            binding.lastPickedButton.isGone = true
+            checkIsFormComplete()
+        }
+
         val isSegregated = element!!.tags["segregated"] == "yes"
         val isPath = element!!.tags["highway"] in ALL_PATHS
         if (isPath && (isSegregated || originalCyclewaySurface != null || originalFootwaySurface != null)) {
@@ -178,6 +210,9 @@ class SurfaceOverlayForm : AbstractOverlayForm() {
             footwaySurfaceCtrl.value!!.applyTo(changesBuilder, "footway")
             updateCommonSurfaceFromFootAndCyclewaySurface(changesBuilder)
         } else {
+            if (surfaceCtrl.value!!.note == null && surfaceCtrl.value!!.surface != null) {
+                favs.add(surfaceCtrl.value!!.surface!!)
+            }
             surfaceCtrl.value!!.applyTo(changesBuilder)
         }
 
diff --git a/app/src/main/java/de/westnordost/streetcomplete/overlays/way_lit/WayLitOverlayForm.kt b/app/src/main/java/de/westnordost/streetcomplete/overlays/way_lit/WayLitOverlayForm.kt
index 2e53546c34f..ff77d2805f9 100644
--- a/app/src/main/java/de/westnordost/streetcomplete/overlays/way_lit/WayLitOverlayForm.kt
+++ b/app/src/main/java/de/westnordost/streetcomplete/overlays/way_lit/WayLitOverlayForm.kt
@@ -1,5 +1,6 @@
 package de.westnordost.streetcomplete.overlays.way_lit
 
+import android.content.Context
 import android.os.Bundle
 import android.view.View
 import de.westnordost.streetcomplete.R
@@ -17,20 +18,39 @@ import de.westnordost.streetcomplete.osm.lit.asItem
 import de.westnordost.streetcomplete.osm.lit.parseLitStatus
 import de.westnordost.streetcomplete.overlays.AImageSelectOverlayForm
 import de.westnordost.streetcomplete.overlays.AnswerItem
+import de.westnordost.streetcomplete.util.LastPickedValuesStore
 import de.westnordost.streetcomplete.util.ktx.couldBeSteps
+import de.westnordost.streetcomplete.util.prefs.Preferences
 import de.westnordost.streetcomplete.view.image_select.DisplayItem
+import org.koin.android.ext.android.inject
 
 class WayLitOverlayForm : AImageSelectOverlayForm<LitStatus>() {
 
     override val items: List<DisplayItem<LitStatus>> =
         listOf(YES, NO, AUTOMATIC, NIGHT_AND_DAY).map { it.asItem() }
 
+    private val prefs: Preferences by inject()
+    private lateinit var favs: LastPickedValuesStore<DisplayItem<LitStatus>>
+
+    override val lastPickedItem: DisplayItem<LitStatus>?
+        get() = favs.get().firstOrNull()
+
     private var originalLitStatus: LitStatus? = null
 
     override val otherAnswers get() = listOfNotNull(
         createConvertToStepsAnswer()
     )
 
+    override fun onAttach(ctx: Context) {
+        super.onAttach(ctx)
+        favs = LastPickedValuesStore(
+            prefs,
+            key = javaClass.simpleName,
+            serialize = { it.value!!.name },
+            deserialize = { LitStatus.valueOf(it).asItem() }
+        )
+    }
+
     override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
         super.onViewCreated(view, savedInstanceState)
 
@@ -43,6 +63,7 @@ class WayLitOverlayForm : AImageSelectOverlayForm<LitStatus>() {
         selectedItem?.value != originalLitStatus
 
     override fun onClickOk() {
+        favs.add(selectedItem!!)
         val tagChanges = StringMapChangesBuilder(element!!.tags)
         selectedItem!!.value!!.applyTo(tagChanges)
         applyEdit(UpdateElementTagsAction(element!!, tagChanges.create()))
diff --git a/app/src/main/java/de/westnordost/streetcomplete/quests/AGroupedImageListQuestForm.kt b/app/src/main/java/de/westnordost/streetcomplete/quests/AGroupedImageListQuestForm.kt
index 5bed6fa0c07..28a8a167eed 100644
--- a/app/src/main/java/de/westnordost/streetcomplete/quests/AGroupedImageListQuestForm.kt
+++ b/app/src/main/java/de/westnordost/streetcomplete/quests/AGroupedImageListQuestForm.kt
@@ -33,9 +33,9 @@ abstract class AGroupedImageListQuestForm<I, T> : AbstractOsmQuestForm<T>() {
 
     protected lateinit var imageSelector: GroupedImageSelectAdapter<I>
 
-    /** all items to display (after user pressed "see more"). May not be accessed before onCreate */
+    /** all items to display. May not be accessed before onCreate */
     protected abstract val allItems: List<GroupableDisplayItem<I>>
-    /** initial items to display. May not be accessed before onCreate */
+    /** items to display that are shown on the top. May not be accessed before onCreate */
     protected abstract val topItems: List<GroupableDisplayItem<I>>
 
     private lateinit var favs: LastPickedValuesStore<GroupableDisplayItem<I>>
diff --git a/app/src/main/java/de/westnordost/streetcomplete/quests/address/AddHousenumberForm.kt b/app/src/main/java/de/westnordost/streetcomplete/quests/address/AddHousenumberForm.kt
index 545c02b1139..e379b4b2a35 100644
--- a/app/src/main/java/de/westnordost/streetcomplete/quests/address/AddHousenumberForm.kt
+++ b/app/src/main/java/de/westnordost/streetcomplete/quests/address/AddHousenumberForm.kt
@@ -13,12 +13,12 @@ import de.westnordost.streetcomplete.osm.address.HouseAndBlockNumber
 import de.westnordost.streetcomplete.osm.address.HouseNumberAndBlock
 import de.westnordost.streetcomplete.osm.address.looksInvalid
 import de.westnordost.streetcomplete.osm.address.streetHouseNumber
-import de.westnordost.streetcomplete.osm.buildingSynonyms
 import de.westnordost.streetcomplete.quests.AbstractOsmQuestForm
 import de.westnordost.streetcomplete.quests.AnswerItem
 import de.westnordost.streetcomplete.quests.IAnswerItem
-import de.westnordost.streetcomplete.quests.building_type.BuildingType
-import de.westnordost.streetcomplete.quests.building_type.asItem
+import de.westnordost.streetcomplete.osm.building.BuildingType
+import de.westnordost.streetcomplete.osm.building.asItem
+import de.westnordost.streetcomplete.osm.building.createBuildingType
 import de.westnordost.streetcomplete.view.image_select.DisplayItem
 import de.westnordost.streetcomplete.view.image_select.ItemViewHolder
 
@@ -113,11 +113,9 @@ class AddHousenumberForm : AbstractOsmQuestForm<HouseNumberAnswer>() {
     }
 
     private fun onNoHouseNumber() {
-        val buildingValue = element.tags["building"]!!
-        val transformedBuildingValue = buildingSynonyms[buildingValue] ?: buildingValue
-        val buildingType = BuildingType.getByTag("building", transformedBuildingValue)?.asItem()
+        val buildingType = createBuildingType(element.tags)
         if (buildingType != null) {
-            showNoHouseNumberDialog(buildingType)
+            showNoHouseNumberDialog(buildingType.asItem())
         } else {
             // fallback in case the type of building is known by Housenumber quest but not by
             // building type quest
diff --git a/app/src/main/java/de/westnordost/streetcomplete/quests/building_levels/AddBuildingLevelsForm.kt b/app/src/main/java/de/westnordost/streetcomplete/quests/building_levels/AddBuildingLevelsForm.kt
index f061f4258c8..56ae9c58331 100644
--- a/app/src/main/java/de/westnordost/streetcomplete/quests/building_levels/AddBuildingLevelsForm.kt
+++ b/app/src/main/java/de/westnordost/streetcomplete/quests/building_levels/AddBuildingLevelsForm.kt
@@ -33,6 +33,8 @@ class AddBuildingLevelsForm : AbstractOsmQuestForm<BuildingLevelsAnswer>() {
     private val levels get() = binding.levelsInput.intOrNull?.takeIf { it >= 0 }
     private val roofLevels get() = binding.roofLevelsInput.intOrNull?.takeIf { it >= 0 }
 
+    private lateinit var favs: LastPickedValuesStore<BuildingLevelsAnswer>
+
     private val lastPickedAnswers by lazy {
         favs.get()
             .mostCommonWithin(target = 5, historyCount = 15, first = 1)
@@ -40,8 +42,6 @@ class AddBuildingLevelsForm : AbstractOsmQuestForm<BuildingLevelsAnswer>() {
             .toList()
     }
 
-    private lateinit var favs: LastPickedValuesStore<BuildingLevelsAnswer>
-
     override fun onAttach(ctx: Context) {
         super.onAttach(ctx)
         favs = LastPickedValuesStore(
@@ -72,8 +72,9 @@ class AddBuildingLevelsForm : AbstractOsmQuestForm<BuildingLevelsAnswer>() {
     }
 
     private fun onLastPickedButtonClicked(position: Int) {
-        binding.levelsInput.setText(lastPickedAnswers[position].levels.toString())
-        binding.roofLevelsInput.setText(lastPickedAnswers[position].roofLevels?.toString() ?: "")
+        val buildingLevelsAnswer = lastPickedAnswers[position]
+        binding.levelsInput.setText(buildingLevelsAnswer.levels.toString())
+        binding.roofLevelsInput.setText(buildingLevelsAnswer.roofLevels?.toString() ?: "")
     }
 
     override fun onClickOk() {
diff --git a/app/src/main/java/de/westnordost/streetcomplete/quests/building_type/AddBuildingType.kt b/app/src/main/java/de/westnordost/streetcomplete/quests/building_type/AddBuildingType.kt
index 44fe3345726..52d9f0a7a33 100644
--- a/app/src/main/java/de/westnordost/streetcomplete/quests/building_type/AddBuildingType.kt
+++ b/app/src/main/java/de/westnordost/streetcomplete/quests/building_type/AddBuildingType.kt
@@ -5,63 +5,32 @@ import de.westnordost.streetcomplete.data.osm.geometry.ElementGeometry
 import de.westnordost.streetcomplete.data.osm.osmquests.OsmFilterQuestType
 import de.westnordost.streetcomplete.data.user.achievements.EditTypeAchievement.BUILDING
 import de.westnordost.streetcomplete.osm.Tags
+import de.westnordost.streetcomplete.osm.building.BuildingType
+import de.westnordost.streetcomplete.osm.building.applyTo
 
 class AddBuildingType : OsmFilterQuestType<BuildingType>() {
 
-    // in the case of man_made, historic, military, aeroway and power, these tags already contain
-    // information about the purpose of the building, so no need to force asking it
-    // or question would be confusing as there is no matching reply in available answers
-    // same goes (more or less) for tourism, amenity, leisure. See #1854, #1891, #3233
+
     override val elementFilter = """
-        ways, relations with (building = yes or building = unclassified)
-         and !man_made
-         and !historic
-         and !military
-         and !power
-         and !tourism
-         and !attraction
-         and !amenity
-         and !leisure
-         and !aeroway
-         and !railway
-         and !craft
-         and !healthcare
-         and !office
-         and !shop
-         and !description
-         and !emergency
-         and location != underground
-         and abandoned != yes
-         and abandoned != building
-         and abandoned:building != yes
-         and ruins != yes and ruined != yes
+        ways, relations with
+        building ~ yes|${BuildingType.deprecatedValues.joinToString("|")}
+        and ${BuildingType.otherKeysPotentiallyDescribingBuildingType.joinToString(" and ") { "!$it" }}
+        and location != underground
+        and disused != yes
+        and abandoned != yes
+        and ruins != yes
     """
     override val changesetComment = "Specify building types"
     override val wikiLink = "Key:building"
     override val icon = R.drawable.ic_quest_building
     override val achievements = listOf(BUILDING)
+    override val defaultDisabledMessage = R.string.default_disabled_msg_overlay
 
     override fun getTitle(tags: Map<String, String>) = R.string.quest_buildingType_title
 
     override fun createForm() = AddBuildingTypeForm()
 
     override fun applyAnswerTo(answer: BuildingType, tags: Tags, geometry: ElementGeometry, timestampEdited: Long) {
-        if (answer.osmKey == "man_made") {
-            tags.remove("building")
-            tags["man_made"] = answer.osmValue
-        } else if (answer.osmKey != "building") {
-            tags[answer.osmKey] = answer.osmValue
-            if (answer == BuildingType.ABANDONED) {
-                tags.remove("disused")
-            }
-            if (answer == BuildingType.RUINS && tags["disused"] == "no") {
-                tags.remove("disused")
-            }
-            if (answer == BuildingType.RUINS && tags["abandoned"] == "no") {
-                tags.remove("abandoned")
-            }
-        } else {
-            tags["building"] = answer.osmValue
-        }
+        answer.applyTo(tags)
     }
 }
diff --git a/app/src/main/java/de/westnordost/streetcomplete/quests/building_type/AddBuildingTypeForm.kt b/app/src/main/java/de/westnordost/streetcomplete/quests/building_type/AddBuildingTypeForm.kt
index a4f3c4f16a3..064224908dd 100644
--- a/app/src/main/java/de/westnordost/streetcomplete/quests/building_type/AddBuildingTypeForm.kt
+++ b/app/src/main/java/de/westnordost/streetcomplete/quests/building_type/AddBuildingTypeForm.kt
@@ -3,6 +3,9 @@ package de.westnordost.streetcomplete.quests.building_type
 import android.os.Bundle
 import androidx.appcompat.app.AlertDialog
 import de.westnordost.streetcomplete.R
+import de.westnordost.streetcomplete.osm.building.BuildingType
+import de.westnordost.streetcomplete.osm.building.BuildingTypeCategory
+import de.westnordost.streetcomplete.osm.building.toItems
 import de.westnordost.streetcomplete.quests.AGroupedImageListQuestForm
 import de.westnordost.streetcomplete.quests.AnswerItem
 
diff --git a/app/src/main/java/de/westnordost/streetcomplete/quests/building_type/BuildingType.kt b/app/src/main/java/de/westnordost/streetcomplete/quests/building_type/BuildingType.kt
deleted file mode 100644
index ec06ddebbd8..00000000000
--- a/app/src/main/java/de/westnordost/streetcomplete/quests/building_type/BuildingType.kt
+++ /dev/null
@@ -1,84 +0,0 @@
-package de.westnordost.streetcomplete.quests.building_type
-
-enum class BuildingType(val osmKey: String, val osmValue: String) {
-    HOUSE           ("building", "house"),
-    APARTMENTS      ("building", "apartments"),
-    DETACHED        ("building", "detached"),
-    SEMI_DETACHED   ("building", "semidetached_house"),
-    TERRACE         ("building", "terrace"),
-    HOTEL           ("building", "hotel"),
-    DORMITORY       ("building", "dormitory"),
-    HOUSEBOAT       ("building", "houseboat"),
-    BUNGALOW        ("building", "bungalow"),
-    STATIC_CARAVAN  ("building", "static_caravan"),
-    HUT             ("building", "hut"),
-
-    INDUSTRIAL      ("building", "industrial"),
-    RETAIL          ("building", "retail"),
-    OFFICE          ("building", "office"),
-    WAREHOUSE       ("building", "warehouse"),
-    KIOSK           ("building", "kiosk"),
-    STORAGE_TANK    ("man_made", "storage_tank"),
-    GUARDHOUSE      ("building", "guardhouse"),
-
-    KINDERGARTEN    ("building", "kindergarten"),
-    SCHOOL          ("building", "school"),
-    COLLEGE         ("building", "college"),
-    SPORTS_CENTRE   ("building", "sports_centre"),
-    HOSPITAL        ("building", "hospital"),
-    STADIUM         ("building", "stadium"),
-    GRANDSTAND      ("building", "grandstand"),
-    TRAIN_STATION   ("building", "train_station"),
-    TRANSPORTATION  ("building", "transportation"),
-    FIRE_STATION    ("building", "fire_station"),
-    UNIVERSITY      ("building", "university"),
-    GOVERNMENT      ("building", "government"),
-
-    CHURCH          ("building", "church"),
-    CHAPEL          ("building", "chapel"),
-    CATHEDRAL       ("building", "cathedral"),
-    MOSQUE          ("building", "mosque"),
-    TEMPLE          ("building", "temple"),
-    PAGODA          ("building", "pagoda"),
-    SYNAGOGUE       ("building", "synagogue"),
-    SHRINE          ("building", "shrine"),
-
-    CARPORT         ("building", "carport"),
-    GARAGE          ("building", "garage"),
-    GARAGES         ("building", "garages"),
-    PARKING         ("building", "parking"),
-
-    FARM            ("building", "farm"),
-    FARM_AUXILIARY  ("building", "farm_auxiliary"),
-    SILO            ("man_made", "silo"),
-    GREENHOUSE      ("building", "greenhouse"),
-
-    SHED            ("building", "shed"),
-    ALLOTMENT_HOUSE ("building", "allotment_house"),
-    ROOF            ("building", "roof"),
-    BRIDGE          ("building", "bridge"),
-    TOILETS         ("building", "toilets"),
-    SERVICE         ("building", "service"),
-    HANGAR          ("building", "hangar"),
-    BUNKER          ("building", "bunker"),
-    BOATHOUSE       ("building", "boathouse"),
-
-    HISTORIC        ("historic", "yes"),
-    ABANDONED       ("abandoned", "yes"),
-    RUINS           ("ruins", "yes"),
-
-    RESIDENTIAL     ("building", "residential"),
-    COMMERCIAL      ("building", "commercial"),
-    CIVIC           ("building", "civic"),
-    RELIGIOUS       ("building", "religious"),
-
-    CONSTRUCTION    ("building", "construction");
-
-    companion object {
-        fun getByTag(key: String, value: String): BuildingType? {
-            return values().find { it.osmKey == key && it.osmValue == value }
-        }
-
-        val topSelectableValues = listOf(DETACHED, APARTMENTS, HOUSE, GARAGE, SHED, HUT)
-    }
-}
diff --git a/app/src/main/java/de/westnordost/streetcomplete/quests/building_type/BuildingTypeCategory.kt b/app/src/main/java/de/westnordost/streetcomplete/quests/building_type/BuildingTypeCategory.kt
deleted file mode 100644
index 6dcadf23cbc..00000000000
--- a/app/src/main/java/de/westnordost/streetcomplete/quests/building_type/BuildingTypeCategory.kt
+++ /dev/null
@@ -1,30 +0,0 @@
-package de.westnordost.streetcomplete.quests.building_type
-
-import de.westnordost.streetcomplete.quests.building_type.BuildingType.*
-
-enum class BuildingTypeCategory(val type: BuildingType?, val subTypes: List<BuildingType>) {
-    RESIDENTIAL(BuildingType.RESIDENTIAL, listOf(
-        DETACHED, APARTMENTS, SEMI_DETACHED, TERRACE, HOUSE, FARM, HUT, BUNGALOW, HOUSEBOAT,
-        STATIC_CARAVAN, DORMITORY
-    )),
-    COMMERCIAL(BuildingType.COMMERCIAL, listOf(
-        OFFICE, RETAIL, KIOSK, INDUSTRIAL, WAREHOUSE, HOTEL, STORAGE_TANK, BRIDGE,
-    )),
-    CIVIC(BuildingType.CIVIC, listOf(
-        SCHOOL, UNIVERSITY, HOSPITAL, KINDERGARTEN, SPORTS_CENTRE, TRAIN_STATION, TRANSPORTATION,
-        COLLEGE, GOVERNMENT, STADIUM, FIRE_STATION, OFFICE, GRANDSTAND
-    )),
-    RELIGIOUS(BuildingType.RELIGIOUS, listOf(
-        CHURCH, CATHEDRAL, CHAPEL, MOSQUE, TEMPLE, PAGODA, SYNAGOGUE, SHRINE
-    )),
-    FOR_CARS(null, listOf(
-        GARAGE, GARAGES, CARPORT, PARKING
-    )),
-    FOR_FARMS(null, listOf(
-        FARM, FARM_AUXILIARY, SILO, GREENHOUSE, STORAGE_TANK, SHED, ALLOTMENT_HOUSE
-    )),
-    OTHER(null, listOf(
-        SHED, ROOF, GUARDHOUSE, BRIDGE, ALLOTMENT_HOUSE, SERVICE, HUT, TOILETS, HANGAR, BUNKER,
-        HISTORIC, BOATHOUSE, ABANDONED, RUINS
-    )),
-}
diff --git a/app/src/main/java/de/westnordost/streetcomplete/quests/building_type/BuildingTypeCategoryItem.kt b/app/src/main/java/de/westnordost/streetcomplete/quests/building_type/BuildingTypeCategoryItem.kt
deleted file mode 100644
index f8e74c5eb8a..00000000000
--- a/app/src/main/java/de/westnordost/streetcomplete/quests/building_type/BuildingTypeCategoryItem.kt
+++ /dev/null
@@ -1,44 +0,0 @@
-package de.westnordost.streetcomplete.quests.building_type
-
-import de.westnordost.streetcomplete.R
-import de.westnordost.streetcomplete.quests.building_type.BuildingTypeCategory.CIVIC
-import de.westnordost.streetcomplete.quests.building_type.BuildingTypeCategory.COMMERCIAL
-import de.westnordost.streetcomplete.quests.building_type.BuildingTypeCategory.FOR_CARS
-import de.westnordost.streetcomplete.quests.building_type.BuildingTypeCategory.FOR_FARMS
-import de.westnordost.streetcomplete.quests.building_type.BuildingTypeCategory.OTHER
-import de.westnordost.streetcomplete.quests.building_type.BuildingTypeCategory.RELIGIOUS
-import de.westnordost.streetcomplete.quests.building_type.BuildingTypeCategory.RESIDENTIAL
-import de.westnordost.streetcomplete.view.image_select.GroupableDisplayItem
-import de.westnordost.streetcomplete.view.image_select.Item
-
-fun Iterable<BuildingTypeCategory>.toItems() = map { it.asItem() }
-
-fun BuildingTypeCategory.asItem(): GroupableDisplayItem<BuildingType> =
-    Item(type, iconResId, titleResId, descriptionResId, subTypes.toItems())
-
-private val BuildingTypeCategory.titleResId: Int get() = when (this) {
-    RESIDENTIAL -> R.string.quest_buildingType_residential
-    COMMERCIAL ->  R.string.quest_buildingType_commercial
-    CIVIC ->       R.string.quest_buildingType_civic
-    RELIGIOUS ->   R.string.quest_buildingType_religious
-    FOR_CARS ->    R.string.quest_buildingType_cars
-    FOR_FARMS ->   R.string.quest_buildingType_farm
-    OTHER ->       R.string.quest_buildingType_other
-}
-
-private val BuildingTypeCategory.descriptionResId: Int? get() = when (this) {
-    RESIDENTIAL -> R.string.quest_buildingType_residential_description
-    COMMERCIAL ->  R.string.quest_buildingType_commercial_generic_description
-    CIVIC ->       R.string.quest_buildingType_civic_description
-    else ->        null
-}
-
-private val BuildingTypeCategory.iconResId: Int get() = when (this) {
-    RESIDENTIAL -> R.drawable.ic_building_apartments
-    COMMERCIAL ->  R.drawable.ic_building_office
-    CIVIC ->       R.drawable.ic_building_civic
-    RELIGIOUS ->   R.drawable.ic_building_temple
-    FOR_CARS ->    R.drawable.ic_building_car
-    FOR_FARMS ->   R.drawable.ic_building_farm
-    OTHER ->       R.drawable.ic_building_other
-}
diff --git a/app/src/main/java/de/westnordost/streetcomplete/screens/main/map/MapModule.kt b/app/src/main/java/de/westnordost/streetcomplete/screens/main/map/MapModule.kt
index 82ee86a6344..9eac74a8acf 100644
--- a/app/src/main/java/de/westnordost/streetcomplete/screens/main/map/MapModule.kt
+++ b/app/src/main/java/de/westnordost/streetcomplete/screens/main/map/MapModule.kt
@@ -1,5 +1,8 @@
 package de.westnordost.streetcomplete.screens.main.map
 
+import de.westnordost.streetcomplete.osm.building.BuildingType
+import de.westnordost.streetcomplete.osm.building.iconResId
+import de.westnordost.streetcomplete.view.presetIconIndex
 import org.koin.dsl.module
 
 val mapModule = module {
@@ -23,5 +26,11 @@ val mapModule = module {
     }
 
     single { TangramPinsSpriteSheet(get(), get(), get(), get()) }
-    single { TangramIconsSpriteSheet(get(), get()) }
+    single {
+        TangramIconsSpriteSheet(
+            get(),
+            get(),
+            presetIconIndex.values + BuildingType.values().mapNotNull { it.iconResId }
+        )
+    }
 }
diff --git a/app/src/main/java/de/westnordost/streetcomplete/screens/main/map/TangramIconsSpriteSheet.kt b/app/src/main/java/de/westnordost/streetcomplete/screens/main/map/TangramIconsSpriteSheet.kt
index f7ac887d722..a3f5a2b4da4 100644
--- a/app/src/main/java/de/westnordost/streetcomplete/screens/main/map/TangramIconsSpriteSheet.kt
+++ b/app/src/main/java/de/westnordost/streetcomplete/screens/main/map/TangramIconsSpriteSheet.kt
@@ -9,7 +9,6 @@ import de.westnordost.streetcomplete.Prefs
 import de.westnordost.streetcomplete.util.ktx.createBitmapWithWhiteBorder
 import de.westnordost.streetcomplete.util.ktx.dpToPx
 import de.westnordost.streetcomplete.util.prefs.Preferences
-import de.westnordost.streetcomplete.view.presetIconIndex
 import kotlin.math.ceil
 import kotlin.math.max
 import kotlin.math.sqrt
@@ -19,6 +18,7 @@ import kotlin.math.sqrt
 class TangramIconsSpriteSheet(
     private val context: Context,
     private val prefs: Preferences,
+    private val icons: Collection<Int>
 ) {
     val sceneUpdates: List<Pair<String, String>> by lazy {
         val isSpriteSheetCurrent = prefs.getInt(Prefs.ICON_SPRITES_VERSION, 0) == BuildConfig.VERSION_CODE
@@ -31,7 +31,7 @@ class TangramIconsSpriteSheet(
     }
 
     private fun createSpritesheet(): String {
-        val iconResIds = ICONS.toSortedSet()
+        val iconResIds = icons.toSortedSet()
         val iconSize = context.dpToPx(26).toInt()
         val borderWidth = context.dpToPx(3).toInt()
         val safePadding = context.dpToPx(2).toInt()
@@ -81,6 +81,5 @@ class TangramIconsSpriteSheet(
 
     companion object {
         private const val ICONS_FILE = "icons.png"
-        private val ICONS = presetIconIndex.values
     }
 }
diff --git a/app/src/main/java/de/westnordost/streetcomplete/util/NameAndLocationLabel.kt b/app/src/main/java/de/westnordost/streetcomplete/util/NameAndLocationLabel.kt
index 37d24fb4326..bc68925dcc6 100644
--- a/app/src/main/java/de/westnordost/streetcomplete/util/NameAndLocationLabel.kt
+++ b/app/src/main/java/de/westnordost/streetcomplete/util/NameAndLocationLabel.kt
@@ -16,12 +16,12 @@ import java.util.Locale
 fun getNameAndLocationLabel(
     element: Element,
     resources: Resources,
-    featureDictionary: FeatureDictionary,
+    featureDictionary: FeatureDictionary?,
     showHouseNumber: Boolean? = null
 ): CharSequence? {
     // only if geometry is not a node because at this point we cannot tell apart points vs vertices
     val geometryType = if (element.type == ElementType.NODE) null else element.geometryType
-    val feature = featureDictionary.getFeatureName(resources.configuration, element.tags, geometryType)
+    val feature = featureDictionary?.getFeatureName(resources.configuration, element.tags, geometryType)
         ?.withNonBreakingSpaces()
         ?.inItalics()
     val name = getNameLabel(element.tags)
diff --git a/app/src/main/java/de/westnordost/streetcomplete/view/image_select/GroupedImageListPickerDialog.kt b/app/src/main/java/de/westnordost/streetcomplete/view/image_select/GroupedImageListPickerDialog.kt
new file mode 100644
index 00000000000..bb839b2d6d2
--- /dev/null
+++ b/app/src/main/java/de/westnordost/streetcomplete/view/image_select/GroupedImageListPickerDialog.kt
@@ -0,0 +1,68 @@
+package de.westnordost.streetcomplete.view.image_select
+
+import android.content.Context
+import android.os.Bundle
+import android.view.ViewGroup.LayoutParams.MATCH_PARENT
+import androidx.annotation.LayoutRes
+import androidx.annotation.StringRes
+import androidx.appcompat.app.AlertDialog
+import androidx.recyclerview.widget.GridLayoutManager
+import androidx.recyclerview.widget.RecyclerView
+import de.westnordost.streetcomplete.R
+
+/** A dialog in which you can select one grouped item of a range of items */
+class GroupedImageListPickerDialog<T>(
+    context: Context,
+    items: List<GroupableDisplayItem<T>>,
+    @LayoutRes groupCellLayoutId: Int,
+    @LayoutRes cellLayoutId: Int,
+    columns: Int = 3,
+    @StringRes titleResId: Int = R.string.quest_select_hint_most_specific,
+    onSelection: (GroupableDisplayItem<T>) -> Unit
+) : AlertDialog(context) {
+
+    private val adapter: GroupedImageSelectAdapter<T>
+
+    init {
+        val horizontalMargin = context.resources.getDimensionPixelOffset(R.dimen.dialog_horizontal_margin)
+        val verticalMargin = context.resources.getDimensionPixelOffset(R.dimen.dialog_vertical_margin)
+
+        val recyclerView = RecyclerView(context)
+        recyclerView.layoutParams = RecyclerView.LayoutParams(MATCH_PARENT, MATCH_PARENT)
+
+        adapter = GroupedImageSelectAdapter()
+        adapter.groupCellLayoutId = groupCellLayoutId
+        adapter.cellLayoutId = cellLayoutId
+        adapter.items = items
+        adapter.listeners.add { updateOkButtonEnablement() }
+
+        val layoutManager = GridLayoutManager(context, columns)
+        layoutManager.spanSizeLookup = object : GridLayoutManager.SpanSizeLookup() {
+            override fun getSpanSize(position: Int): Int {
+                return if (adapter.items[position].isGroup) layoutManager.spanCount else 1
+            }
+        }
+        recyclerView.layoutManager = GridLayoutManager(context, columns)
+        recyclerView.setPadding(horizontalMargin, verticalMargin, horizontalMargin, verticalMargin)
+
+        setTitle(titleResId)
+        setView(recyclerView)
+
+        recyclerView.adapter = adapter
+
+        setButton(BUTTON_POSITIVE, context.getText(android.R.string.ok)) { _, _ ->
+            dismiss()
+            adapter.selectedItem?.let(onSelection)
+        }
+        setButton(BUTTON_NEGATIVE, context.getText(android.R.string.cancel), null, null)
+    }
+
+    override fun onCreate(savedInstanceState: Bundle?) {
+        super.onCreate(savedInstanceState)
+        updateOkButtonEnablement()
+    }
+
+    private fun updateOkButtonEnablement() {
+        getButton(BUTTON_POSITIVE)?.isEnabled = adapter.selectedItem?.value != null
+    }
+}
diff --git a/app/src/main/java/de/westnordost/streetcomplete/view/image_select/GroupedImageSelectAdapter.kt b/app/src/main/java/de/westnordost/streetcomplete/view/image_select/GroupedImageSelectAdapter.kt
index f77054279d3..6ca1bcbf51e 100644
--- a/app/src/main/java/de/westnordost/streetcomplete/view/image_select/GroupedImageSelectAdapter.kt
+++ b/app/src/main/java/de/westnordost/streetcomplete/view/image_select/GroupedImageSelectAdapter.kt
@@ -5,7 +5,7 @@ import android.view.ViewGroup
 import androidx.recyclerview.widget.RecyclerView
 import de.westnordost.streetcomplete.R
 
-/** Select one items from a groupable list of items  */
+/** Select one item from a groupable list of items  */
 class GroupedImageSelectAdapter<T> :
     RecyclerView.Adapter<ItemViewHolder>() {
 
@@ -69,9 +69,16 @@ class GroupedImageSelectAdapter<T> :
         val previousItem = selectedItem
         val previousGroup = selectedItemGroup
 
-        val foundGroupIndex = getGroupIndex(index)
-        selectedItemGroup = if (foundGroupIndex == -1) null else _items[foundGroupIndex]
-        selectedItem = _items[index]
+        val hasSelectedSameItem = previousItem == _items[index]
+
+        if (hasSelectedSameItem) {
+            selectedItem = null
+            selectedItemGroup = null
+        } else {
+            selectedItem = _items[index]
+            val foundGroupIndex = getGroupIndex(index)
+            selectedItemGroup = if (foundGroupIndex == -1) null else _items[foundGroupIndex]
+        }
 
         if (previousItem != null) {
             val previousItemIndex = indexOfItemGivenGroupMembership(previousItem, previousGroup)
diff --git a/app/src/main/java/de/westnordost/streetcomplete/view/image_select/ImageListPickerDialog.kt b/app/src/main/java/de/westnordost/streetcomplete/view/image_select/ImageListPickerDialog.kt
index 1e250491352..ebef7bb4550 100644
--- a/app/src/main/java/de/westnordost/streetcomplete/view/image_select/ImageListPickerDialog.kt
+++ b/app/src/main/java/de/westnordost/streetcomplete/view/image_select/ImageListPickerDialog.kt
@@ -9,7 +9,7 @@ import androidx.recyclerview.widget.GridLayoutManager
 import androidx.recyclerview.widget.RecyclerView
 import de.westnordost.streetcomplete.R
 
-/** A dialog in which you can one item of a range of items */
+/** A dialog in which you can select one item of a range of items */
 class ImageListPickerDialog<T>(
     context: Context,
     items: List<DisplayItem<T>>,
diff --git a/app/src/main/res/drawable/ic_building_car.xml b/app/src/main/res/drawable/ic_building_car.xml
deleted file mode 100644
index c55613c722d..00000000000
--- a/app/src/main/res/drawable/ic_building_car.xml
+++ /dev/null
@@ -1,54 +0,0 @@
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="48dp"
-        android:height="48dp"
-        android:viewportHeight="128"
-        android:viewportWidth="128">
-    <path
-        android:fillColor="#555"
-        android:pathData="m115.447,107.215c0,3.55 -2.881,6.431 -6.431,6.431h-9.646c-3.55,0 -6.431,-2.881 -6.431,-6.431V81.492c0,-3.55 2.881,-6.431 6.431,-6.431h9.646c3.55,0 6.431,2.881 6.431,6.431z"
-        />
-    <path
-        android:fillColor="#555"
-        android:pathData="m35.061,107.215c0,3.55 -2.881,6.431 -6.431,6.431h-9.646c-3.55,0 -6.431,-2.881 -6.431,-6.431V81.492c0,-3.55 2.881,-6.431 6.431,-6.431h9.646c3.55,0 6.431,2.881 6.431,6.431z"
-        />
-    <path
-        android:fillColor="#3b88c3"
-        android:pathData="m92.939,17.183c12.479,3.119 16.077,35.37 16.077,35.37 0,0 6.431,0 6.431,12.862v25.724c0,0 -0.383,9.743 -12.862,12.862 -12.862,3.215 -22.508,3.215 -38.585,3.215 -16.077,0 -25.724,0 -38.585,-3.215C12.939,100.881 12.553,91.138 12.553,91.138V65.415c0,0 0,-12.862 6.431,-12.862 0,0 3.601,-32.251 16.077,-35.37 12.862,-3.215 45.016,-3.215 57.878,0z"
-        />
-    <path
-        android:fillColor="#bbddf5"
-        android:pathData="m64,49.337c12.556,0 27.727,0.643 38.585,1.807L99.37,33.26C96.154,23.614 76.862,23.614 64,23.614c-12.862,0 -32.154,0 -35.37,9.646L25.415,51.144C36.273,49.98 51.444,49.337 64,49.337"
-        />
-    <path
-        android:fillColor="#3b88c3"
-        android:pathData="m17.376,55.768h-6.431c-2.666,0 -4.823,-2.158 -4.823,-4.823 0,-2.666 2.158,-4.823 4.823,-4.823h6.431c2.666,0 4.823,2.158 4.823,4.823 0,2.666 -2.158,4.823 -4.823,4.823z"
-        />
-    <path
-        android:fillColor="#3b88c3"
-        android:pathData="m110.624,55.768h6.431c2.662,0 4.823,-2.158 4.823,-4.823 0,-2.666 -2.161,-4.823 -4.823,-4.823h-6.431c-2.662,0 -4.823,2.158 -4.823,4.823 0,2.666 2.161,4.823 4.823,4.823z"
-        />
-    <path
-        android:fillColor="#fff"
-        android:pathData="M41.492,75.061c0,5.328 -4.318,9.646 -9.646,9.646h-3.215c-5.328,0 -9.646,-4.318 -9.646,-9.646 0,-5.328 4.318,-9.646 9.646,-9.646h3.215c5.328,0 9.646,4.318 9.646,9.646"
-        />
-    <path
-        android:fillColor="#fff"
-        android:pathData="M109.016,75.061c0,5.328 -4.322,9.646 -9.646,9.646h-3.215c-5.325,0 -9.646,-4.318 -9.646,-9.646 0,-5.328 4.322,-9.646 9.646,-9.646h3.215c5.325,0 9.646,4.318 9.646,9.646"
-        />
-    <path
-        android:fillColor="#226699"
-        android:pathData="m21.923,65.024c9.053,-4.478 23.328,0.232 23.472,0.278 1.682,0.566 3.506,-0.337 4.073,-2.019 0.566,-1.682 -0.327,-3.497 -2.016,-4.071 -0.685,-0.236 -16.923,-5.616 -28.378,0.046 -1.592,0.789 -2.243,2.715 -1.459,4.308 0.295,0.59 0.744,1.053 1.273,1.359 0.899,0.519 2.033,0.595 3.035,0.1z"
-        />
-    <path
-        android:fillColor="#226699"
-        android:pathData="m110.381,63.566c0.787,-1.594 0.136,-3.52 -1.459,-4.308 -11.453,-5.663 -27.693,-0.281 -28.378,-0.046 -1.674,0.573 -2.582,2.389 -2.013,4.069 0.563,1.683 2.388,2.587 4.07,2.02 0.144,-0.046 14.419,-4.756 23.472,-0.278 0.999,0.496 2.136,0.419 3.035,-0.1 0.529,-0.305 0.978,-0.769 1.273,-1.359z"
-        />
-    <path
-        android:fillColor="#55acee"
-        android:pathData="m19.926,90.196c-1.257,-1.257 -1.257,-3.289 0,-4.547 1.106,-1.109 2.82,-1.241 4.074,-0.392 0.746,0.322 7.347,2.666 40,2.666 32.653,0 39.254,-2.344 40,-2.666 1.257,-0.849 2.965,-0.717 4.074,0.392 1.257,1.257 1.257,3.289 0,4.547 -3.434,3.434 -25.865,4.158 -44.074,4.158 -18.209,0 -40.64,-0.723 -44.074,-4.158z"
-        />
-    <path
-        android:fillColor="#226699"
-        android:pathData="m64,104c-12.431,0 -22.508,-3.215 -22.508,-8.039 0,-2.662 10.077,-1.608 22.508,-1.608 12.431,0 22.508,-1.055 22.508,1.608C86.508,100.785 76.431,104 64,104Z"
-        />
-</vector>
diff --git a/app/src/main/res/drawable/ic_building_construction.xml b/app/src/main/res/drawable/ic_building_construction.xml
new file mode 100644
index 00000000000..ca861b61766
--- /dev/null
+++ b/app/src/main/res/drawable/ic_building_construction.xml
@@ -0,0 +1,25 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="128dp"
+    android:height="128dp"
+    android:viewportWidth="128"
+    android:viewportHeight="128">
+  <path
+      android:pathData="m32,24 l0.01,87.92h16l-0.01,-87.92z"
+      android:fillColor="#666"/>
+  <path
+      android:pathData="m80,24 l0.01,87.92h16l-0.01,-87.92z"
+      android:fillColor="#666"/>
+  <path
+      android:pathData="m24.04,32h79.91c4.46,0 8.04,3.59 8.04,8.04v31.91c0,4.46 -3.59,8.04 -8.04,8.04h-79.91c-4.46,0 -8.04,-3.59 -8.04,-8.04v-31.91c0,-4.46 3.59,-8.04 8.04,-8.04z"
+      android:fillColor="#555"/>
+  <path
+      android:pathData="m24,32c-3.82,0 -6.99,2.65 -7.79,6.21l28.75,41.79h14.14l-32.33,-48zM40.62,32 L72.95,80h14.14l-32.33,-48zM68.62,32 L100.95,80h3.05c3.69,0 6.78,-2.48 7.71,-5.87l-28.94,-42.13zM96.62,32 L112,54v-14c0,-4.43 -3.57,-8 -8,-8zM16,58v14c0,4.43 3.57,8 8,8h7.09z"
+      android:fillColor="#ffe94c"/>
+  <path
+      android:pathData="m24.04,32h79.92c4.45,0 8.04,3.58 8.04,8.04v31.92c0,4.45 -3.58,8.04 -8.04,8.04h-79.92c-4.45,0 -8.04,-3.58 -8.04,-8.04v-31.92c0,-4.45 3.58,-8.04 8.04,-8.04z"
+      android:strokeLineJoin="round"
+      android:strokeWidth="4"
+      android:fillColor="#00000000"
+      android:strokeColor="#555"
+      android:strokeLineCap="round"/>
+</vector>
diff --git a/app/src/main/res/drawable/ic_building_container.xml b/app/src/main/res/drawable/ic_building_container.xml
new file mode 100644
index 00000000000..6c1d1219569
--- /dev/null
+++ b/app/src/main/res/drawable/ic_building_container.xml
@@ -0,0 +1,74 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="128dp"
+    android:height="128dp"
+    android:viewportWidth="128"
+    android:viewportHeight="128">
+  <path
+      android:pathData="m120,108v-56h-78v56z"
+      android:strokeWidth="1.0131"
+      android:fillColor="#3279bb"/>
+  <path
+      android:pathData="m42,108v-56h-34v56z"
+      android:strokeWidth=".97182"
+      android:fillColor="#448bcd"/>
+  <path
+      android:pathData="m36,96v-12h-24v12z"
+      android:strokeWidth=".92582"
+      android:fillColor="#3279bb"/>
+  <path
+      android:pathData="m36,76v-12h-24v12z"
+      android:strokeWidth=".92582"
+      android:fillColor="#3279bb"/>
+  <path
+      android:pathData="M108,58h6v44h-6z"
+      android:strokeWidth=".95743"
+      android:fillColor="#2c69a5"/>
+  <path
+      android:pathData="M96,58h6v44h-6z"
+      android:strokeWidth=".95743"
+      android:fillColor="#2c69a5"/>
+  <path
+      android:pathData="M84,58h6v44h-6z"
+      android:strokeWidth=".95743"
+      android:fillColor="#2c69a5"/>
+  <path
+      android:pathData="M72,58h6v44h-6z"
+      android:strokeWidth=".95743"
+      android:fillColor="#2c69a5"/>
+  <path
+      android:pathData="M60,58h6v44h-6z"
+      android:strokeWidth=".95743"
+      android:fillColor="#2c69a5"/>
+  <path
+      android:pathData="M48,58h6v44h-6z"
+      android:strokeWidth=".95743"
+      android:fillColor="#2c69a5"/>
+  <path
+      android:pathData="M112,102h8v8h-8z"
+      android:fillColor="#9c9c9c"/>
+  <path
+      android:pathData="M112,52h8v8h-8z"
+      android:fillColor="#9c9c9c"/>
+  <path
+      android:pathData="M42,52h8v8h-8z"
+      android:fillColor="#9c9c9c"/>
+  <path
+      android:pathData="M42,102h8v8h-8z"
+      android:fillColor="#9c9c9c"/>
+  <path
+      android:pathData="M8,52h6v8h-6z"
+      android:strokeWidth=".86602"
+      android:fillColor="#c6c6c6"/>
+  <path
+      android:pathData="M8,102h6v8h-6z"
+      android:strokeWidth=".86602"
+      android:fillColor="#c6c6c6"/>
+  <path
+      android:pathData="M36,52h6v8h-6z"
+      android:strokeWidth=".86602"
+      android:fillColor="#c6c6c6"/>
+  <path
+      android:pathData="M36,102h6v8h-6z"
+      android:strokeWidth=".86602"
+      android:fillColor="#c6c6c6"/>
+</vector>
diff --git a/app/src/main/res/drawable/ic_building_house.xml b/app/src/main/res/drawable/ic_building_house.xml
index 8cc765a0285..06f6f13ea7a 100644
--- a/app/src/main/res/drawable/ic_building_house.xml
+++ b/app/src/main/res/drawable/ic_building_house.xml
@@ -4,31 +4,34 @@
     android:viewportWidth="128"
     android:viewportHeight="128">
   <path
-      android:pathData="M0,128 L20,128V88L0,68ZM96,52h32v76h-32z"
+      android:pathData="m128,108 l-28,-0v-40l28,-28z"
       android:fillColor="#c4aea0"/>
   <path
-    android:pathData="M0,56V72L23.755,96.241 32.244,87.759ZM96,52 L104,24l24,0v28z"
-    android:fillColor="#ad6262"/>
+      android:pathData="m128,36 l-36.01,31.54 8.03,8.92 27.99,-24.46z"
+      android:fillColor="#ad6262"/>
   <path
-      android:pathData="M28,128H96V88L60,64 28,88Z"
+      android:pathData="m0,116 l24,0v-40l-24,-24z"
+      android:fillColor="#c4aea0"/>
+  <path
+      android:pathData="m32,119.98h68v-40l-36,-24 -32,24z"
       android:fillColor="#deb486"/>
   <path
-      android:pathData="M32,52h16v24h-16z"
+      android:pathData="M40,43.97h16v24h-16z"
       android:fillColor="#deb486"/>
   <path
-      android:pathData="M36,100h20v16h-20z"
+      android:pathData="M68,88h16v32h-16z"
+      android:fillColor="#c08268"/>
+  <path
+      android:pathData="M40,92.01h20v16h-20z"
       android:fillColor="#95685e"/>
   <path
-      android:pathData="M36,96h20v4h-20zM64,96h16v32h-16z"
+      android:pathData="M40,88h20v4h-20z"
       android:fillColor="#c08268"/>
   <path
-      android:pathData="M20,92 L60,56 104,92"
+      android:pathData="m0,48v16l28.2,20.64 7.6,-9.29z"
+      android:fillColor="#ad6262"/>
+  <path
+      android:pathData="m24,84 l40,-36 44,36"
       android:strokeWidth="12"
       android:strokeColor="#c84747"/>
-  <path
-      android:pathData="M104,64h16v16h-16zM104,100h16v16h-16z"
-      android:fillColor="#88706b"/>
-  <path
-      android:pathData="M104,96h16v4h-16zM104,60h16v4h-16z"
-      android:fillColor="#ae897a"/>
 </vector>
diff --git a/app/src/main/res/drawable/ic_building_tent.xml b/app/src/main/res/drawable/ic_building_tent.xml
new file mode 100644
index 00000000000..421d0609cd9
--- /dev/null
+++ b/app/src/main/res/drawable/ic_building_tent.xml
@@ -0,0 +1,15 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="128dp"
+    android:height="128dp"
+    android:viewportWidth="128"
+    android:viewportHeight="128">
+  <path
+      android:pathData="m70,108 l16,-38 16,38z"
+      android:fillColor="#15324e"/>
+  <path
+      android:pathData="m84,48 l-26,60h12s12,-12 16,-38c4,26 16,38 16,38h12c-0.34,0.32 -20.47,-33.05 -26,-60z"
+      android:fillColor="#286097"/>
+  <path
+      android:pathData="m14,108s24,-32 28,-60c16,4 22,4 42,0 -4,28 -26,60 -26,60z"
+      android:fillColor="#3279bb"/>
+</vector>
diff --git a/app/src/main/res/drawable/ic_building_tomb.xml b/app/src/main/res/drawable/ic_building_tomb.xml
new file mode 100644
index 00000000000..198b742fa9b
--- /dev/null
+++ b/app/src/main/res/drawable/ic_building_tomb.xml
@@ -0,0 +1,48 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="128dp"
+    android:height="128dp"
+    android:viewportWidth="128"
+    android:viewportHeight="128">
+  <path
+      android:pathData="M36,60h56v40h-56z"
+      android:strokeWidth=".8165"
+      android:fillColor="#959595"/>
+  <path
+      android:pathData="M32,100h64v8h-64z"
+      android:strokeWidth=".83571"
+      android:fillColor="#aaa"/>
+  <path
+      android:fillColor="#FF000000"
+      android:pathData="m20.61,56.78v35.22h11.74v-35.22z"
+      android:fillAlpha="0"/>
+  <path
+      android:fillColor="#FF000000"
+      android:pathData="m95.74,56.78v35.22h11.74v-35.22z"
+      android:fillAlpha="0"/>
+  <path
+      android:fillColor="#FF000000"
+      android:pathData="m44.09,56.78v35.22h11.74v-35.22z"
+      android:fillAlpha="0"/>
+  <path
+      android:fillColor="#FF000000"
+      android:pathData="m72.26,56.78v35.22h11.74v-35.22z"
+      android:fillAlpha="0"/>
+  <path
+      android:pathData="m36,48v8h56v-8l-28,-8z"
+      android:strokeWidth="8"
+      android:fillColor="#d9d9d9"
+      android:strokeColor="#aeaeae"/>
+  <path
+      android:pathData="M76,60h8v40h-8z"
+      android:fillColor="#d9d9d9"/>
+  <path
+      android:pathData="M44,60h8v40h-8z"
+      android:fillColor="#d9d9d9"/>
+  <path
+      android:pathData="m56,76v24h16v-24c-4,-4 -12,-4 -16,0z"
+      android:fillColor="#58595b"/>
+  <path
+      android:fillColor="#FF000000"
+      android:pathData="M36,60h56v4h-56z"
+      android:fillAlpha="0.2"/>
+</vector>
diff --git a/app/src/main/res/drawable/ic_building_tower.xml b/app/src/main/res/drawable/ic_building_tower.xml
new file mode 100644
index 00000000000..1128017500a
--- /dev/null
+++ b/app/src/main/res/drawable/ic_building_tower.xml
@@ -0,0 +1,55 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="128dp"
+    android:height="128dp"
+    android:viewportWidth="128"
+    android:viewportHeight="128">
+  <path
+      android:pathData="m84,56v68h-40v-68z"
+      android:fillColor="#888"/>
+  <path
+      android:pathData="m32,12v36h64l0,-36z"
+      android:fillColor="#9c9c9c"/>
+  <path
+      android:pathData="m40,12v36h48l-0,-36z"
+      android:fillColor="#aaa"/>
+  <path
+      android:pathData="m76,12v36h-24v-36z"
+      android:fillColor="#c6c6c6"/>
+  <path
+      android:pathData="M32,20h64v20h-64z"
+      android:fillColor="#bacfef"/>
+  <path
+      android:pathData="m78,56v68h-28v-68z"
+      android:fillColor="#a8a8a8"/>
+  <path
+      android:pathData="m70,56v68h-12v-68z"
+      android:fillColor="#c6c6c6"/>
+  <path
+      android:pathData="M28,48h72v8h-72z"
+      android:fillColor="#5878b7"/>
+  <path
+      android:pathData="M28,4h72v8h-72z"
+      android:fillColor="#5878b7"/>
+  <path
+      android:fillColor="#FF000000"
+      android:pathData="M44,56h40v8h-40z"
+      android:fillAlpha="0.2"/>
+  <path
+      android:pathData="M32,20h64v4h-64z"
+      android:fillColor="#859dbf"/>
+  <path
+      android:pathData="M32,20h4v20h-4z"
+      android:fillColor="#6f829f"/>
+  <path
+      android:pathData="M92,20h4v20h-4z"
+      android:fillColor="#6f829f"/>
+  <path
+      android:pathData="M80,20h6v20h-6z"
+      android:fillColor="#6f829f"/>
+  <path
+      android:pathData="M60,20h8v20h-8z"
+      android:fillColor="#6f829f"/>
+  <path
+      android:pathData="M42,20h6v20h-6z"
+      android:fillColor="#6f829f"/>
+</vector>
diff --git a/app/src/main/res/layout/cell_last_picked_button.xml b/app/src/main/res/layout/cell_last_picked_button.xml
new file mode 100644
index 00000000000..552f1a5d9e9
--- /dev/null
+++ b/app/src/main/res/layout/cell_last_picked_button.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<ImageView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:id="@+id/icon"
+    android:layout_width="54dp"
+    android:layout_height="52dp"
+    tools:src="@drawable/ic_building_detached"
+    style="@style/Widget.AppCompat.Button.Small"
+    tools:ignore="RtlHardcoded" />
diff --git a/app/src/main/res/layout/fragment_grouped_overlay_image_select.xml b/app/src/main/res/layout/fragment_grouped_overlay_image_select.xml
new file mode 100644
index 00000000000..e44b5ba8569
--- /dev/null
+++ b/app/src/main/res/layout/fragment_grouped_overlay_image_select.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:layout_marginBottom="48dp"
+    android:minHeight="160dp">
+
+    <include
+        android:id="@+id/selectButton"
+        layout="@layout/view_image_select"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:animateLayoutChanges="true"
+        android:paddingLeft="16dp"
+        android:paddingRight="16dp"
+        app:layout_constraintTop_toTopOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintBottom_toTopOf="@+id/lastPickedButtons" />
+
+    <androidx.recyclerview.widget.RecyclerView
+        android:id="@+id/lastPickedButtons"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:orientation="horizontal"
+        app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
+        tools:itemCount="6"
+        tools:listitem="@layout/cell_last_picked_button"
+        app:layout_constraintBottom_toBottomOf="parent"
+        tools:ignore="RtlHardcoded,RtlSymmetry"
+        android:paddingTop="8dp"
+        android:paddingBottom="8dp"
+        />
+
+</androidx.constraintlayout.widget.ConstraintLayout>
diff --git a/app/src/main/res/layout/fragment_overlay.xml b/app/src/main/res/layout/fragment_overlay.xml
index 710deb01c21..5db89f6ff0d 100644
--- a/app/src/main/res/layout/fragment_overlay.xml
+++ b/app/src/main/res/layout/fragment_overlay.xml
@@ -93,7 +93,6 @@
                         android:paddingEnd="@dimen/quest_form_horizontal_padding"
                         android:paddingTop="@dimen/quest_form_vertical_padding"
                         android:paddingBottom="@dimen/quest_form_vertical_padding"
-                        app:layout_constraintBottom_toBottomOf="parent"
                         app:layout_constraintTop_toTopOf="parent"
                         app:layout_constraintStart_toStartOf="parent"
                         app:layout_constraintEnd_toEndOf="parent"/>
diff --git a/app/src/main/res/layout/fragment_overlay_address.xml b/app/src/main/res/layout/fragment_overlay_address.xml
index 37bceb39722..1179984acac 100644
--- a/app/src/main/res/layout/fragment_overlay_address.xml
+++ b/app/src/main/res/layout/fragment_overlay_address.xml
@@ -5,7 +5,7 @@
     android:layout_height="wrap_content"
     android:orientation="vertical"
     android:showDividers="middle"
-    android:paddingBottom="32dp"
+    android:layout_marginBottom="48dp"
     android:divider="@drawable/space_8dp">
 
     <include
diff --git a/app/src/main/res/layout/fragment_overlay_image_select.xml b/app/src/main/res/layout/fragment_overlay_image_select.xml
index 9e295de93ce..614e7294069 100644
--- a/app/src/main/res/layout/fragment_overlay_image_select.xml
+++ b/app/src/main/res/layout/fragment_overlay_image_select.xml
@@ -1,15 +1,32 @@
 <?xml version="1.0" encoding="utf-8"?>
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    xmlns:tools="http://schemas.android.com/tools"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
-    android:paddingLeft="16dp"
-    android:paddingRight="16dp"
-    android:minHeight="160dp"
-    android:gravity="center">
+    android:layout_marginBottom="48dp"
+    android:minHeight="160dp">
 
     <include
         android:id="@+id/selectButton"
         layout="@layout/view_image_select"
-        />
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        app:layout_constraintWidth_max="220dp"
+        android:animateLayoutChanges="true"
+        app:layout_constraintTop_toTopOf="parent"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintStart_toStartOf="parent" />
 
-</RelativeLayout>
+    <ImageView
+        android:id="@+id/lastPickedButton"
+        android:layout_width="64dp"
+        android:layout_height="64dp"
+        tools:src="@drawable/ic_lit_yes"
+        style="@style/Widget.AppCompat.Button.Small"
+        tools:ignore="RtlHardcoded"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintLeft_toLeftOf="parent"/>
+
+</androidx.constraintlayout.widget.ConstraintLayout>
diff --git a/app/src/main/res/layout/fragment_overlay_shops.xml b/app/src/main/res/layout/fragment_overlay_shops.xml
index 410df993353..3824faee369 100644
--- a/app/src/main/res/layout/fragment_overlay_shops.xml
+++ b/app/src/main/res/layout/fragment_overlay_shops.xml
@@ -6,7 +6,7 @@
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
     android:orientation="vertical"
-    android:paddingBottom="32dp">
+    android:layout_marginBottom="48dp">
 
     <androidx.constraintlayout.widget.ConstraintLayout
         android:id="@+id/featureView"
@@ -66,7 +66,6 @@
         android:id="@+id/nameContainer"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:layout_marginBottom="16dp"
         layout="@layout/quest_localizedname" />
 
 </LinearLayout>
diff --git a/app/src/main/res/layout/fragment_overlay_surface_select.xml b/app/src/main/res/layout/fragment_overlay_surface_select.xml
index 10e85d8616d..8f1d3aee787 100644
--- a/app/src/main/res/layout/fragment_overlay_surface_select.xml
+++ b/app/src/main/res/layout/fragment_overlay_surface_select.xml
@@ -1,33 +1,37 @@
 <?xml version="1.0" encoding="utf-8"?>
-<LinearLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
+<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:app="http://schemas.android.com/apk/res-auto"
     xmlns:tools="http://schemas.android.com/tools"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
     android:minHeight="160dp"
-    android:weightSum="2"
-    android:divider="@drawable/space_16dp"
-    android:showDividers="middle|beginning|end"
+    android:layout_marginBottom="48dp"
     android:orientation="horizontal">
 
     <include
         android:id="@+id/main"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
+        app:layout_constraintWidth_max="220dp"
         layout="@layout/view_image_select_plus_text"
-        tools:visibility="gone"
-        />
+        app:layout_constraintTop_toTopOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintBottom_toBottomOf="parent" />
 
     <LinearLayout
         android:id="@+id/cycleway_surface_container"
         android:layout_width="0dp"
         android:layout_height="wrap_content"
         android:visibility="gone"
-        tools:visibility="visible"
-        android:layout_weight="1"
         android:gravity="center_horizontal"
-        android:orientation="vertical">
+        android:orientation="vertical"
+        android:layout_marginStart="8dp"
+        android:layout_marginEnd="8dp"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toTopOf="parent"
+        app:layout_constraintHorizontal_weight="0.5"
+        app:layout_constraintEnd_toStartOf="@+id/footway_surface_container">
 
         <TextView
             android:id="@+id/cyclewaySurfaceLabel"
@@ -42,8 +46,7 @@
             android:id="@+id/cycleway"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
-            layout="@layout/view_image_select_plus_text"
-            />
+            layout="@layout/view_image_select_plus_text" />
 
     </LinearLayout>
 
@@ -52,10 +55,15 @@
         android:layout_width="0dp"
         android:layout_height="wrap_content"
         android:visibility="gone"
-        tools:visibility="visible"
         android:gravity="center_horizontal"
         android:layout_weight="1"
-        android:orientation="vertical">
+        android:orientation="vertical"
+        android:layout_marginStart="8dp"
+        android:layout_marginEnd="8dp"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintTop_toTopOf="parent"
+        app:layout_constraintHorizontal_weight="0.5"
+        app:layout_constraintStart_toEndOf="@+id/cycleway_surface_container">
 
         <TextView
             android:id="@+id/footwaySurfaceLabel"
@@ -70,8 +78,16 @@
             android:id="@+id/footway"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
-            layout="@layout/view_image_select_plus_text"
-            />
+            layout="@layout/view_image_select_plus_text" />
     </LinearLayout>
 
-</LinearLayout>
+    <ImageView
+        android:id="@+id/lastPickedButton"
+        android:layout_width="64dp"
+        android:layout_height="64dp"
+        tools:src="@drawable/ic_lit_yes"
+        style="@style/Widget.AppCompat.Button.Small"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintLeft_toLeftOf="parent" />
+
+</androidx.constraintlayout.widget.ConstraintLayout>
diff --git a/app/src/main/res/layout/quest_building_levels_last_picked_button.xml b/app/src/main/res/layout/quest_building_levels_last_picked_button.xml
index 8d8ca6bcff3..4a29dc9b5e1 100644
--- a/app/src/main/res/layout/quest_building_levels_last_picked_button.xml
+++ b/app/src/main/res/layout/quest_building_levels_last_picked_button.xml
@@ -3,7 +3,7 @@
     xmlns:tools="http://schemas.android.com/tools"
     style="@style/Widget.AppCompat.Button.Small"
     android:layout_width="wrap_content"
-    android:layout_height="51dp"
+    android:layout_height="52dp"
     android:orientation="horizontal">
 
     <TextView
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index e2f5887d059..a8868695730 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -865,12 +865,13 @@ Before uploading your changes, the app checks with a &lt;a href=\"https://www.we
     <string name="quest_buildingType_transportation">Public transportation building</string>
     <string name="quest_buildingType_university">University building</string>
     <string name="quest_buildingType_government">Government building</string>
-    <string name="quest_buildingType_cars">For cars</string>
+    <string name="quest_buildingType_outbuilding">Outbuilding</string>
+    <string name="quest_buildingType_outbuilding_description">less important building on a property</string>
     <string name="quest_buildingType_carport">Carport</string>
     <string name="quest_buildingType_carport_description">roof for a car</string>
     <string name="quest_buildingType_garage">Single garage</string>
     <string name="quest_buildingType_garages">Multiple garages</string>
-    <string name="quest_buildingType_garages_description">Separate spaces for different owners/tenants</string>
+    <string name="quest_buildingType_garages_description">separate spaces for different owners/tenants</string>
     <string name="quest_buildingType_parking">Parking building</string>
     <string name="quest_buildingType_farm">On a farm</string>
     <string name="quest_buildingType_farmhouse">Farmhouse</string>
@@ -880,8 +881,12 @@ Before uploading your changes, the app checks with a &lt;a href=\"https://www.we
     <string name="quest_buildingType_silo">Silo</string>
     <string name="quest_buildingType_greenhouse">Greenhouse</string>
     <string name="quest_buildingType_other">Other</string>
+    <string name="quest_buildingType_other_description">a specific building that is not selectable in this app</string>
     <string name="quest_buildingType_shed">Shed</string>
     <string name="quest_buildingType_boathouse">Boathouse</string>
+    <string name="quest_buildingType_container">Container</string>
+    <string name="quest_buildingType_tent">Tent</string>
+    <string name="quest_buildingType_tomb">Tomb</string>
     <string name="quest_buildingType_allotment_house">Garden allotment outbuilding</string>
     <string name="quest_buildingType_grandstand">Grandstand</string>
     <string name="quest_buildingType_toilets">Toilets</string>
@@ -893,6 +898,8 @@ Before uploading your changes, the app checks with a &lt;a href=\"https://www.we
     <string name="quest_buildingType_service_description">building with machinery like pumps or transformers</string>
     <string name="quest_buildingType_hangar">Hangar</string>
     <string name="quest_buildingType_hangar_description">storage for airplanes, helicopters or spacecraft</string>
+    <string name="quest_buildingType_tower">Tower</string>
+    <string name="quest_buildingType_tower_description">any kind of tower</string>
     <string name="quest_buildingType_bunker">Bunker</string>
     <string name="quest_buildingType_historic">Historic</string>
     <string name="quest_buildingType_historic_description">building of historic value, constructed for an unknown or unclear purpose</string>
@@ -902,6 +909,7 @@ Before uploading your changes, the app checks with a &lt;a href=\"https://www.we
     <string name="quest_buildingType_ruins_description">derelict, ruined and unidentifiable building</string>
     <string name="quest_buildingType_fire_station">Fire station building</string>
     <string name="quest_buildingType_guardhouse">Guardhouse</string>
+    <string name="quest_buildingType_under_construction">Under construction</string>
 
     <!-- "stop" as in "bus stop". But could be a tram stop, railway stop etc. too -->
     <string name="quest_busStopBench_title2">"Is there a bench at this stop?"</string>
@@ -1676,6 +1684,8 @@ Partially means that a wheelchair can enter and use the restroom, but no handrai
     <string name="overlay_addresses">Addresses</string>
     <string name="overlay_addresses_no_entrance">It’s not an entrance…</string>
 
+    <string name="overlay_buildings">Buildings</string>
+
     <string name="overlay_shops">Shops</string>
     <string name="name_label">Name:</string>
     <!-- Used for places unknown by iD presets. Does not mean it is invalid. The wording that it is "unknown" is avoided so that the user does not think an action is necessary from him -->
diff --git a/res/graphics/building/conservatory.svg b/res/graphics/building/conservatory.svg
new file mode 100644
index 00000000000..5890f65619e
--- /dev/null
+++ b/res/graphics/building/conservatory.svg
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg version="1.1" viewBox="0 0 128 128" xmlns="http://www.w3.org/2000/svg">
+ <g transform="matrix(3.7795 0 0 3.7795 -256 -502.52)">
+  <path d="m84.667 142.49c-1.0583 0-12.7 2.1166-12.7 6.3496v10.583h25.4v-10.583c0-4.2333-11.642-6.3496-12.7-6.3496z" fill="#6493db" fill-opacity=".37647"/>
+  <path d="m91.647 144.16-15.265 15.26h2.9931l14.381-14.388c-0.67539-0.31721-1.3601-0.62554-2.1097-0.8722z" fill="#fff" fill-opacity=".25098"/>
+  <path d="m84.667 142.48-12.7 12.698v4.2333h0.25683l16.202-16.224c-1.1797-0.27257-2.3252-0.56246-3.7589-0.70678z" fill="#fff" fill-opacity=".25098"/>
+  <path d="m71.967 148.83h25.4m-8.4677 10.578 9.48e-4 -15.87m-8.4676 15.87 9.2e-4 -15.87m4.2324-1.0628c-1.0583 0-12.7 2.1166-12.7 6.3496v10.583h25.4v-10.583c0-4.2333-11.642-6.3496-12.7-6.3496z" fill="none" stroke="#c08268" stroke-width="1.3229"/>
+ </g>
+</svg>
diff --git a/res/graphics/building/construction.svg b/res/graphics/building/construction.svg
new file mode 100644
index 00000000000..47540020dc5
--- /dev/null
+++ b/res/graphics/building/construction.svg
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg version="1.1" viewBox="0 0 128 128" xmlns="http://www.w3.org/2000/svg">
+ <path d="m32 24.001 8e-3 87.92h16l-8e-3 -87.921z" fill="#666"/>
+ <path d="m80 24.001 8e-3 87.92h16l-8e-3 -87.92z" fill="#666"/>
+ <path d="m24.044 32.001h79.913c4.456 0 8.0433 3.5873 8.0433 8.0433v31.913c0 4.456-3.5873 8.0433-8.0433 8.0433h-79.913c-4.456 0-8.0433-3.5873-8.0433-8.0433v-31.913c0-4.456 3.5873-8.0433 8.0433-8.0433z" fill="#555"/>
+ <path d="m24 32.001c-3.8167 0-6.9867 2.6476-7.7949 6.2129l28.746 41.787h14.143l-32.332-48zm16.619 0 32.332 48h14.143l-32.332-48zm28 0 32.332 48h3.0488c3.6926 0 6.7759-2.4795 7.7051-5.8691l-28.943-42.131zm28 0 15.381 22v-14c0-4.432-3.568-8-8-8zm-80.619 26v14c0 4.432 3.568 8 8 8h7.0938z" fill="#ffe94c"/>
+ <path d="m24.038 32.001h79.924c4.4531 0 8.038 3.5849 8.038 8.038v31.924c0 4.453-3.5849 8.038-8.038 8.038h-79.924c-4.4531 0-8.038-3.5849-8.038-8.038v-31.924c0-4.453 3.5849-8.038 8.038-8.038z" fill="none" stroke="#555" stroke-linecap="round" stroke-linejoin="round" stroke-width="4"/>
+</svg>
diff --git a/res/graphics/building/container.svg b/res/graphics/building/container.svg
new file mode 100644
index 00000000000..4c9fb1fbae8
--- /dev/null
+++ b/res/graphics/building/container.svg
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg version="1.1" viewBox="0 0 128 128" xmlns="http://www.w3.org/2000/svg">
+ <path d="m120 108v-56h-78v56z" fill="#3279bb" stroke-width="1.0131"/>
+ <path d="m42 108v-56h-34v56z" fill="#448bcd" stroke-width=".97182"/>
+ <path d="m36 96v-12h-24v12z" fill="#3279bb" stroke-width=".92582"/>
+ <path d="m36 76v-12h-24v12z" fill="#3279bb" stroke-width=".92582"/>
+ <rect x="108" y="58" width="6" height="44" fill="#2c69a5" stroke-width=".95743"/>
+ <rect x="96" y="58" width="6" height="44" fill="#2c69a5" stroke-width=".95743"/>
+ <rect x="84" y="58" width="6" height="44" fill="#2c69a5" stroke-width=".95743"/>
+ <rect x="72" y="58" width="6" height="44" fill="#2c69a5" stroke-width=".95743"/>
+ <rect x="60" y="58" width="6" height="44" fill="#2c69a5" stroke-width=".95743"/>
+ <rect x="48" y="58" width="6" height="44" fill="#2c69a5" stroke-width=".95743"/>
+ <rect x="112" y="102" width="8" height="8" fill="#9c9c9c"/>
+ <rect x="112" y="52" width="8" height="8" fill="#9c9c9c"/>
+ <rect x="42" y="52" width="8" height="8" fill="#9c9c9c"/>
+ <rect x="42" y="102" width="8" height="8" fill="#9c9c9c"/>
+ <rect x="8" y="52" width="6" height="8" fill="#c6c6c6" stroke-width=".86602"/>
+ <rect x="8" y="102" width="6" height="8" fill="#c6c6c6" stroke-width=".86602"/>
+ <rect x="36" y="52" width="6" height="8" fill="#c6c6c6" stroke-width=".86602"/>
+ <rect x="36" y="102" width="6" height="8" fill="#c6c6c6" stroke-width=".86602"/>
+</svg>
diff --git a/res/graphics/building/house.svg b/res/graphics/building/house.svg
index ee1025b79bf..a0b80dd879d 100644
--- a/res/graphics/building/house.svg
+++ b/res/graphics/building/house.svg
@@ -1,23 +1,13 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<svg version="1.1" viewBox="0 0 128 128" xmlns="http://www.w3.org/2000/svg">
- <g transform="matrix(3.7795 0 0 3.7795 -5.6895e-6 -990.52)">
-  <path d="m2.4989e-6 293.83 5.2917-1e-5v-10.583l-5.2917-5.2917z" fill="#c4aea0"/>
-  <path d="m0 274.77v4.2333l6.2852 6.4138 2.2461-2.2441z" fill="#ad6262" />
- </g>
- <g transform="matrix(3.7795 0 0 3.7795 -5.6895e-6 -994.52)">
-  <path d="m7.4083 294.88h17.992v-10.583l-9.525-6.35-8.4667 6.35z" fill="#deb486"/>
-  <rect x="8.4667" y="274.77" width="4.2333" height="6.35" fill="#deb486"/>
-  <rect x="16.933" y="286.42" width="4.2333" height="8.4667" fill="#c08268"/>
-  <rect x="9.525" y="287.48" width="5.2917" height="4.2333" fill="#95685e"/>
-  <rect x="9.525" y="286.42" width="5.2917" height="1.0583" fill="#c08268"/>
-  <path d="m5.2917 285.36 10.583-9.525 11.642 9.525" fill="none" stroke="#c84747" stroke-width="3.175"/>
- </g>
- <g>
-  <rect x="96" y="44" width="32" height="76" fill="#c4aea0"/>
-  <rect x="104" y="56" width="16" height="16" fill="#88706b"/>
-  <rect x="104" y="92" width="16" height="16" fill="#88706b"/>
-  <rect x="104" y="88" width="16" height="4" fill="#ae897a"/>
-  <rect x="104" y="52" width="16" height="4" fill="#ae897a"/>
-  <path d="m96 44 8-28 24 3.8e-5v28z" fill="#ad6262"/>
- </g>
+<svg version="1.1" viewBox="0 0 128 128" xml:space="preserve" xmlns="http://www.w3.org/2000/svg">
+<path d="m128 108-28-3e-5v-39.998l28-28.002z" fill="#c4aea0"/>
+<path d="m128 36-36.014 31.539 8.0273 8.918 27.986-24.457z" fill="#ad6262"/>
+<path d="m0 116 24 2e-5v-39.999l-24-24.001z" fill="#c4aea0"/>
+<path d="m32 119.98h68.001v-39.998l-36-24-32 24z" fill="#deb486"/>
+<rect x="40" y="43.973" width="16" height="24" fill="#deb486"/>
+<rect x="67.998" y="88.004" width="16" height="32" fill="#c08268"/>
+<rect x="40" y="92.011" width="20" height="16" fill="#95685e"/>
+<rect x="40" y="88.004" width="20" height="3.9998" fill="#c08268"/>
+<path d="m0 48v16l28.201 20.643 7.5977-9.2871z" color="#000000" fill="#ad6262"/>
+<path d="m24 83.998 40-35.998 43.999 35.998" stroke="#c84747" fill="none" stroke-width="12"/>
 </svg>
diff --git a/res/graphics/building/tent.svg b/res/graphics/building/tent.svg
new file mode 100644
index 00000000000..e83b070a411
--- /dev/null
+++ b/res/graphics/building/tent.svg
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg version="1.1" viewBox="0 0 128 128" xmlns="http://www.w3.org/2000/svg">
+ <g transform="translate(0,20)">
+  <path d="m70 88 16-38 16 38z" fill="#15324e"/>
+  <path d="m84 28-26 60h12s12-12 16-38c4 26 16 38 16 38h12c-0.33504 0.31864-20.468-33.048-26-60z" fill="#286097"/>
+  <path d="m14 88s24-32 28-60c16 4 22 4 42 0-4 28-26 60-26 60z" fill="#3279bb"/>
+ </g>
+</svg>
diff --git a/res/graphics/building/tomb.svg b/res/graphics/building/tomb.svg
new file mode 100644
index 00000000000..22960ce8c5e
--- /dev/null
+++ b/res/graphics/building/tomb.svg
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg version="1.1" viewBox="0 0 128 128" xmlns="http://www.w3.org/2000/svg">
+ <rect x="36" y="60" width="56" height="40" fill="#959595" stroke-width=".8165"/>
+ <rect x="32" y="100" width="64" height="8" fill="#aaa" stroke-width=".83571"/>
+ <path d="m20.609 56.783v35.217h11.739v-35.217z" fill-opacity="0"/>
+ <path d="m95.739 56.783v35.217h11.739v-35.217z" fill-opacity="0"/>
+ <path d="m44.087 56.783v35.217h11.739v-35.217z" fill-opacity="0"/>
+ <path d="m72.261 56.783v35.217h11.739v-35.217z" fill-opacity="0"/>
+ <path d="m36 48v8h56v-8l-28-8z" fill="#d9d9d9" stroke="#aeaeae" stroke-width="8"/>
+ <rect x="76" y="60" width="8" height="40" fill="#d9d9d9"/>
+ <rect x="44" y="60" width="8" height="40" fill="#d9d9d9"/>
+ <path d="m56 76v24h16v-24c-4-4-12-4-16 0z" fill="#58595b"/>
+ <rect x="36" y="60" width="56" height="4" fill-opacity=".2"/>
+</svg>
diff --git a/res/graphics/building/tower.svg b/res/graphics/building/tower.svg
new file mode 100644
index 00000000000..cc24f1339da
--- /dev/null
+++ b/res/graphics/building/tower.svg
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg version="1.1" viewBox="0 0 128 128" xmlns="http://www.w3.org/2000/svg">
+ <path d="m84 56v68h-40v-68z" fill="#888"/>
+ <path d="m32 12v36h63.998l2e-3 -36z" fill="#9c9c9c"/>
+ <path d="m40 12v36h48l-1e-5 -36z" fill="#aaa"/>
+ <path d="m76 12v36h-24v-36z" fill="#c6c6c6"/>
+ <rect x="32" y="20" width="64" height="20" fill="#bacfef"/>
+ <path d="m78 56v68h-28v-68z" fill="#a8a8a8"/>
+ <path d="m70 56v68h-12v-68z" fill="#c6c6c6"/>
+ <rect x="28" y="48" width="72" height="8" fill="#5878b7"/>
+ <rect x="28" y="4" width="72" height="8" fill="#5878b7"/>
+ <rect x="44" y="56" width="40" height="8" fill-opacity=".2"/>
+ <rect x="32" y="20" width="64" height="4" fill="#859dbf"/>
+ <rect x="32" y="20" width="4" height="20" fill="#6f829f"/>
+ <rect x="92" y="20" width="4" height="20" fill="#6f829f"/>
+ <rect x="80" y="20" width="6" height="20" fill="#6f829f"/>
+ <rect x="60" y="20" width="8" height="20" fill="#6f829f"/>
+ <rect x="42" y="20" width="6" height="20" fill="#6f829f"/>
+</svg>


Test patch:
diff --git a/app/src/androidTest/res/drawable/ic_building_tower.xml b/app/src/androidTest/res/drawable/ic_building_tower.xml
new file mode 100644
index 00000000000..1128017500a
--- /dev/null
+++ b/app/src/androidTest/res/drawable/ic_building_tower.xml
@@ -0,0 +1,55 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="128dp"
+    android:height="128dp"
+    android:viewportWidth="128"
+    android:viewportHeight="128">
+  <path
+      android:pathData="m84,56v68h-40v-68z"
+      android:fillColor="#888"/>
+  <path
+      android:pathData="m32,12v36h64l0,-36z"
+      android:fillColor="#9c9c9c"/>
+  <path
+      android:pathData="m40,12v36h48l-0,-36z"
+      android:fillColor="#aaa"/>
+  <path
+      android:pathData="m76,12v36h-24v-36z"
+      android:fillColor="#c6c6c6"/>
+  <path
+      android:pathData="M32,20h64v20h-64z"
+      android:fillColor="#bacfef"/>
+  <path
+      android:pathData="m78,56v68h-28v-68z"
+      android:fillColor="#a8a8a8"/>
+  <path
+      android:pathData="m70,56v68h-12v-68z"
+      android:fillColor="#c6c6c6"/>
+  <path
+      android:pathData="M28,48h72v8h-72z"
+      android:fillColor="#5878b7"/>
+  <path
+      android:pathData="M28,4h72v8h-72z"
+      android:fillColor="#5878b7"/>
+  <path
+      android:fillColor="#FF000000"
+      android:pathData="M44,56h40v8h-40z"
+      android:fillAlpha="0.2"/>
+  <path
+      android:pathData="M32,20h64v4h-64z"
+      android:fillColor="#859dbf"/>
+  <path
+      android:pathData="M32,20h4v20h-4z"
+      android:fillColor="#6f829f"/>
+  <path
+      android:pathData="M92,20h4v20h-4z"
+      android:fillColor="#6f829f"/>
+  <path
+      android:pathData="M80,20h6v20h-6z"
+      android:fillColor="#6f829f"/>
+  <path
+      android:pathData="M60,20h8v20h-8z"
+      android:fillColor="#6f829f"/>
+  <path
+      android:pathData="M42,20h6v20h-6z"
+      android:fillColor="#6f829f"/>
+</vector>
diff --git a/app/src/test/java/de/westnordost/streetcomplete/osm/building/BuildingTypeCreatorKtTest.kt b/app/src/test/java/de/westnordost/streetcomplete/osm/building/BuildingTypeCreatorKtTest.kt
new file mode 100644
index 00000000000..4ef82e545a1
--- /dev/null
+++ b/app/src/test/java/de/westnordost/streetcomplete/osm/building/BuildingTypeCreatorKtTest.kt
@@ -0,0 +1,113 @@
+package de.westnordost.streetcomplete.osm.building
+
+import de.westnordost.streetcomplete.data.osm.edits.update_tags.StringMapChangesBuilder
+import de.westnordost.streetcomplete.osm.building.BuildingType.*
+import de.westnordost.streetcomplete.osm.nowAsCheckDateString
+import kotlin.test.Test
+import kotlin.test.assertFails
+import kotlin.test.assertEquals
+
+class BuildingTypeCreatorKtTest {
+
+    @Test fun `set building as unsupported not possible`() {
+        assertFails { UNSUPPORTED.appliedTo(mapOf()) }
+    }
+
+    @Test fun `set building`() {
+        assertEquals(
+            mapOf("building" to "residential"),
+            RESIDENTIAL.appliedTo(mapOf())
+        )
+
+        assertEquals(
+            mapOf("building" to "residential"),
+            RESIDENTIAL.appliedTo(mapOf("building" to "yes"))
+        )
+
+        assertEquals(
+            mapOf("building" to "residential"),
+            RESIDENTIAL.appliedTo(mapOf("man_made" to "storage_tank"))
+        )
+    }
+
+    @Test fun `set man-made`() {
+        assertEquals(
+            mapOf("man_made" to "storage_tank"),
+            STORAGE_TANK.appliedTo(mapOf())
+        )
+
+        assertEquals(
+            mapOf("man_made" to "storage_tank"),
+            STORAGE_TANK.appliedTo(mapOf("man_made" to "silo"))
+        )
+
+        assertEquals(
+            mapOf("man_made" to "storage_tank"),
+            STORAGE_TANK.appliedTo(mapOf("building" to "roof"))
+        )
+    }
+
+
+    @Test fun `remove ruins etc`() {
+        assertEquals(
+            mapOf("building" to "roof"),
+            ROOF.appliedTo(mapOf(
+                "building" to "residential",
+                "ruins" to "yes",
+                "abandoned" to "yes",
+                "disused" to "yes",
+                "historic" to "yes",
+            ))
+        )
+
+        assertEquals(
+            mapOf("building" to "residential", "historic" to "yes"),
+            HISTORIC.appliedTo(mapOf(
+                "building" to "residential",
+                "ruins" to "yes",
+                "abandoned" to "yes",
+                "disused" to "yes",
+            ))
+        )
+
+        assertEquals(
+            mapOf("building" to "residential"),
+            RESIDENTIAL.appliedTo(mapOf("building" to "residential", "ruins" to "yes"))
+        )
+    }
+
+    @Test fun `update check date`() {
+        assertEquals(
+            mapOf("building" to "residential", "check_date" to nowAsCheckDateString()),
+            RESIDENTIAL.appliedTo(mapOf("building" to "residential"))
+        )
+        assertEquals(
+            mapOf("man_made" to "silo", "check_date" to nowAsCheckDateString()),
+            SILO.appliedTo(mapOf("man_made" to "silo"))
+        )
+        assertEquals(
+            mapOf("building" to "hut", "historic" to "yes", "check_date" to nowAsCheckDateString()),
+            HISTORIC.appliedTo(mapOf("building" to "hut", "historic" to "yes"))
+        )
+    }
+
+    @Test fun `don't overwrite aliases`() {
+        assertEquals(
+            mapOf("building" to "livestock", "check_date" to nowAsCheckDateString()),
+            FARM_AUXILIARY.appliedTo(mapOf("building" to "livestock"))
+        )
+
+        assertEquals(
+            mapOf("building" to "residential"),
+            RESIDENTIAL.appliedTo(mapOf("building" to "livestock"))
+        )
+    }
+}
+
+private fun BuildingType.appliedTo(tags: Map<String, String>): Map<String, String> {
+    val cb = StringMapChangesBuilder(tags)
+    applyTo(cb)
+    val mutableMap = tags.toMutableMap()
+    cb.create().applyTo(mutableMap)
+    return mutableMap
+}
diff --git a/app/src/test/java/de/westnordost/streetcomplete/osm/building/BuildingTypeParserKtTest.kt b/app/src/test/java/de/westnordost/streetcomplete/osm/building/BuildingTypeParserKtTest.kt
new file mode 100644
index 00000000000..0b1797b5492
--- /dev/null
+++ b/app/src/test/java/de/westnordost/streetcomplete/osm/building/BuildingTypeParserKtTest.kt
@@ -0,0 +1,42 @@
+package de.westnordost.streetcomplete.osm.building
+
+import kotlin.test.Test
+import kotlin.test.assertEquals
+import de.westnordost.streetcomplete.osm.building.BuildingType.*
+
+class BuildingTypeParserKtTest {
+
+    @Test fun `parse not buildings`() {
+        assertEquals(null, createBuildingType(mapOf()))
+        assertEquals(null, createBuildingType(mapOf("bla" to "blub")))
+        assertEquals(null, createBuildingType(mapOf("building" to "no")))
+        assertEquals(null, createBuildingType(mapOf("building" to "entrance")))
+    }
+
+    @Test fun `parse buildings`() {
+        assertEquals(HUT, createBuildingType(mapOf("building" to "hut")))
+        assertEquals(STORAGE_TANK, createBuildingType(mapOf("man_made" to "storage_tank")))
+        assertEquals(HISTORIC, createBuildingType(mapOf("historic" to "yes")))
+
+        assertEquals(null, createBuildingType(mapOf("building" to "yes")))
+        assertEquals(UNSUPPORTED, createBuildingType(mapOf("building" to "something else")))
+        assertEquals(UNSUPPORTED, createBuildingType(mapOf("man_made" to "something else")))
+    }
+
+    @Test fun `parse deprecated building aliases`() {
+        assertEquals(null, createBuildingType(mapOf("building" to "semi")))
+        assertEquals(null, createBuildingType(mapOf("building" to "abandoned")))
+    }
+
+    @Test fun `parse non deprecated building aliases`() {
+        assertEquals(FARM_AUXILIARY, createBuildingType(mapOf("building" to "livestock")))
+        assertEquals(RELIGIOUS, createBuildingType(mapOf("building" to "convent")))
+    }
+
+    @Test fun `parse houses with alternative tagging scheme`() {
+        assertEquals(HOUSE, createBuildingType(mapOf("building" to "house")))
+        assertEquals(BUNGALOW, createBuildingType(mapOf("building" to "house", "house" to "bungalow")))
+        assertEquals(DETACHED, createBuildingType(mapOf("building" to "house", "house" to "detached")))
+        assertEquals(HOUSE, createBuildingType(mapOf("building" to "house", "house" to "something else")))
+    }
+}
diff --git a/app/src/test/java/de/westnordost/streetcomplete/quests/building_type/AddBuildingTypeTest.kt b/app/src/test/java/de/westnordost/streetcomplete/quests/building_type/AddBuildingTypeTest.kt
index 5576c87ff99..e69de29bb2d 100644
--- a/app/src/test/java/de/westnordost/streetcomplete/quests/building_type/AddBuildingTypeTest.kt
+++ b/app/src/test/java/de/westnordost/streetcomplete/quests/building_type/AddBuildingTypeTest.kt
@@ -1,53 +0,0 @@
-package de.westnordost.streetcomplete.quests.building_type
-
-import de.westnordost.streetcomplete.data.osm.edits.update_tags.StringMapEntryAdd
-import de.westnordost.streetcomplete.data.osm.edits.update_tags.StringMapEntryDelete
-import de.westnordost.streetcomplete.data.osm.edits.update_tags.StringMapEntryModify
-import de.westnordost.streetcomplete.quests.answerAppliedTo
-import kotlin.test.Test
-import kotlin.test.assertEquals
-
-class AddBuildingTypeTest {
-    private val questType = AddBuildingType()
-
-    @Test fun `set building as residential`() {
-        assertEquals(
-            setOf(StringMapEntryModify("building", "yes", "residential")),
-            questType.answerAppliedTo(BuildingType.RESIDENTIAL, mapOf("building" to "yes"))
-        )
-    }
-
-    @Test fun `set building as abandoned`() {
-        assertEquals(
-            setOf(StringMapEntryAdd("abandoned", "yes")),
-            questType.answerAppliedTo(BuildingType.ABANDONED, mapOf("building" to "yes"))
-        )
-    }
-
-    @Test fun `set building as abandoned and prevent double tagging`() {
-        // https://github.com/streetcomplete/StreetComplete/issues/3386
-        assertEquals(
-            setOf(
-                StringMapEntryAdd("abandoned", "yes"),
-                StringMapEntryDelete("disused", "yes"),
-            ),
-            questType.answerAppliedTo(BuildingType.ABANDONED, mapOf(
-                "building" to "yes",
-                "disused" to "yes",
-            ))
-        )
-    }
-
-    @Test fun `set building as abandoned where it was marked as used`() {
-        assertEquals(
-            setOf(
-                StringMapEntryAdd("abandoned", "yes"),
-                StringMapEntryDelete("disused", "no"),
-            ),
-            questType.answerAppliedTo(BuildingType.ABANDONED, mapOf(
-                "building" to "yes",
-                "disused" to "no",
-            ))
-        )
-    }
-}