ideditor / schema-builder

🏗🏷 Create tagging schemas for iD
ISC License
12 stars 16 forks source link

Allow to match a preset based on the absence of further tags #25

Open tyrasd opened 2 years ago

tyrasd commented 2 years ago

This would allow us to add specialized presets for map features which use the <key>:<subkey>=yes/no syntax to refine their scope and purpose.

For example, recycling amenities are defined by adding recycling:<recycling_good>=yes/no. In order to add a preset for a recycling container for only glass-bottles, we must be able to match the following object:

amenity = recycling
recycling_type = container
recycling:glass_bottles = yes

…and at the same time not match this object:

amenity = recycling
recycling_type = container
recycling:cans = yes
recycling:glass_bottles = yes

This would unblock https://github.com/openstreetmap/id-tagging-schema/pull/308, https://github.com/openstreetmap/id-tagging-schema/issues/294 and https://github.com/openstreetmap/id-tagging-schema/issues/295.

This would make it possible to fix "false-positive" matches (example) of map features which only partially match the E-Waste Container or `green_waste presets:

See also https://github.com/openstreetmap/id-tagging-schema/pull/308#pullrequestreview-842648480.

tordans commented 2 years ago

Thinking more about this: Are there cases, where the exclude-list requires tags to be evaluated with an and operator?

For the given case of recycling, an or-list would be sufficient, like for example:

{
  "icon": "maki-recycling",
  "fields": [],
  "moreFields": [],
  "geometry": [
    "point"
  ],
  "terms": [],
  "tags": {
    "amenity": "recycling",
    "recycling_type": "container",
    "recycling:glass_bottles": "yes"
  },
  "reference": {
    "key": "recycling:glass_bottles",
    "value": "yes"
  },
  "referenceExcludeSet": [
    { "key": "recycling:animal_waste", "value": "yes" },
    { "key": "recycling:aluminium", "value": "yes" },
    { "key": "recycling:batteries", "value": "yes" },
    { "key": "recycling:beverage_cartons", "value": "yes" },
    { "key": "recycling:bicycles", "value": "yes" },
    { "key": "recycling:books", "value": "yes" },
    { "key": "recycling:cans", "value": "yes" },
    { "key": "recycling:car_batteries", "value": "yes" },
    { "key": "recycling:cardboard", "value": "yes" },
    { "key": "recycling:cds", "value": "yes" },
    { "key": "recycling:christmas_trees", "value": "yes" },
    { "key": "recycling:clothes", "value": "yes" },
    { "key": "recycling:computers", "value": "yes" },
    { "key": "recycling:cooking_oil", "value": "yes" },
    { "key": "recycling:cork", "value": "yes" },
    { "key": "recycling:drugs", "value": "yes" },
    { "key": "recycling:electrical_appliances", "value": "yes" },
    { "key": "recycling:engine_oil", "value": "yes" },
    { "key": "recycling:fluorescent_tubes", "value": "yes" },
    { "key": "recycling:foil", "value": "yes" },
    { "key": "recycling:gas_bottles", "value": "yes" },
    { "key": "recycling:garden_waste", "value": "yes" },
    // { "key": "recycling:glass", "value": "yes" },
    // { "key": "recycling:glass_bottles", "value": "yes" },
    { "key": "recycling:green_waste", "value": "yes" },
    { "key": "recycling:hardcore", "value": "yes" },
    { "key": "recycling:low_energy_bulbs", "value": "yes" },
    { "key": "recycling:magazines", "value": "yes" },
    { "key": "recycling:mobile_phones", "value": "yes" },
    { "key": "recycling:music", "value": "yes" },
    { "key": "recycling:newspaper", "value": "yes" },
    { "key": "recycling:paint", "value": "yes" },
    { "key": "recycling:paper", "value": "yes" },
    { "key": "recycling:paper_packaging", "value": "ye" },
    { "key": "recycling:plasterboard", "value": "yes" },
    { "key": "recycling:plastic", "value": "yes" },
    { "key": "recycling:plastic_bags", "value": "yes" },
    { "key": "recycling:plastic_bottles", "value": "yes" },
    { "key": "recycling:polyester", "value": "ye" },
    { "key": "recycling:printer_cartridges", "value": "yes" },
    { "key": "recycling:rubble", "value": "yes" },
    { "key": "recycling:scrap_metal", "value": "yes" },
    { "key": "recycling:sheet_metal", "value": "yes" },
    { "key": "recycling:shoes", "value": "yes" },
    { "key": "recycling:small_appliances", "value": "yes" },
    { "key": "recycling:small_electrical_appliances", "value": "yes" },
    { "key": "recycling:styrofoam", "value": "yes" },
    { "key": "recycling:tyres", "value": "yes" },
    { "key": "recycling:waste", "value": "yes" },
    { "key": "recycling:waste_oil", "value": "yes" },
    { "key": "recycling:white_goods", "value": "yes" },
    { "key": "recycling:wood", "value": "yes" }
  ],
  "name": "Recycling Container for Glass Bottles"
}

The list is taken from https://wiki.openstreetmap.org/wiki/DE:Tag:amenity%3Drecycling. It kind of show that we might need another way to solve this, since adding all manner of tags here makes the definition huge and still not "save" (in terms of completeness).


In case we need an and, we could try something like this, where (tag1 and tag2) or tag3 or tag4 need to match. Its ab bit implicit, though. Is there a common way to write such definitions in JSON that is more explicit by stating and/or more clearly?

  "referenceExcludeSet": [
    [
      { "key": "tag1", "value": "yes" },
      { "key": "tag2", "value": "yes" }
    ],
    { "key": "tag3", "value": "yes" },
    { "key": "tag4", "value": "yes"}
  ],