bryceco / GoMap

OpenStreetMap editor for iPhone/iPad
ISC License
318 stars 41 forks source link

Question about the QuestDefinitionFilter implementation #766

Open bickelmeister opened 4 months ago

bickelmeister commented 4 months ago

Because I am willing to dig deeper into Go Map!! as tool for mapping to go, I kinda want to know how the Quest implementation is working:

First Case

{
    "label": "🚲",
    "title": "How many rental bicycle spaces are here?",
    "geometry": {
        "area": true,
        "point": true,
        "vertex": false,
        "line": true
    },
    "filters": [
        {
            "tagValue": "bicycle_rental",
            "relation": "=",
            "tagKey": "amenity",
            "included": "include"
        },
        {
            "tagValue": "docking_station",
            "relation": "=",
            "tagKey": "bicycle_rental",
            "included": "include"
        },
        {
            "included": "include",
            "tagKey": "capacity",
            "relation": "=",
            "tagValue": ""
        }
    ],
    "tagKeys": [
        "capacity"
    ]
}

Is this a valid json for a quest definition and furthermore are the filters combined with OR, XOR or AND? My expectation how this definition is that it will show me all amenity=bicycle_rental and bicycle_rental=docking_station which are not containing a value for the capacity Is that true?

Second Case

    {
      "label": "🚲",
      "title": "Lastenrad?",
      "geometry": {
        "vertex": true,
        "line": true,
        "area": true,
        "point": true
      },
      "filters": [
        {
          "tagKey": "amenity",
          "relation": "=",
          "tagValue": "bicycle_parking",
          "included": "include"
        },
        {
          "tagKey": "cargo_bike",
          "relation": "=",
          "tagValue": "",
          "included": "include"
        },
        {
          "tagKey": "capacity:cargo_bike",
          "relation": "=",
          "tagValue": "",
          "included": "include"
        }
      ],
      "tagKeys": [
        "cargo_bike",
        "capacity:cargo_bike"
      ]
    }

Will this pop up if one of the values is set? Or have to be both empty?

Thanks in advance. May some day I will master swift and unterstand the implementation ^^

bryceco commented 4 months ago

Great question! In general everything is combined with AND, but with an important exception (which I'll get to).

In the first case you have:

amenity=bicycle_rental
bicycle_rental=docking_station
capacity=

and these will all be combined with AND, so all three need to match.

In the second case you have:

amenity=bicycle_parking
capacity:cargo_bike=
cargo_bike=

and again these are all combined with AND, which is probably not what you want. To get the OR result you want you'll have to write two different quests. (However, looking at this I realize that the code could probably be made smart enough to notice that the tagKeys array lists both the items you're filtering on, which means that you want to set both of those keys and they should probably use an OR. Let me work on that!)

Moving on, what is the exception? There are situations where using AND doesn't make any sense and we can conclude that OR is necessary. If you have a key duplicated using an = relation with different values then using AND will never be true, so we infer that it is an OR:

amenity=cafe
amenity=restaurant
website=

In this situation the amenity values would be ORs, and the result of that would be AND everything else.

Except there's exception to this exception! We only convert multiple values to OR when the relation is =. If the relation is ≠ then it's non-sensical to use OR (because it would always be true):

amenity≠cafe
amenity≠restaurant
website=

In this case the amenity values would use AND.

Hope that helps!

bickelmeister commented 3 months ago

It helps a lot. I see two approaches. You can make the code a bit smarter, or let the user decide :)

At least for the expanded quest build. But I am sure you will find a good solution :) Thanks for clarification.