Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Creating more filter options #101

Merged
merged 19 commits into from
Sep 10, 2024
Merged

Conversation

jonha1
Copy link
Contributor

@jonha1 jonha1 commented Jul 22, 2024

This makes it easier to filter places that are nearby.

Issue#82:
https://github.com/soundscape-community/soundscape/issues/82

@jonha1
Copy link
Contributor Author

jonha1 commented Jul 22, 2024

I feel like I am close but having trouble understanding why it isn't working. If I can get help with one of them, I can create other filters.

Copy link
Member

@steinbro steinbro left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you provide a little more detail about what isn't working, what errors you're running into, etc.? I left a few comments/questions based on what jumps out to me in your diffs.

Comment on lines 3261 to 3265
/* Open Street Map term. An ice cream shop is a place where ice cream is sold. */
"osm.tag.ice_cream" = "amenity=ice_cream";

/* Open Street Map term. A pub is a place selling beer and other alcoholic drinks; may also provide food or accommodation (UK). */
"osm.tag.pub" = "amenity=pub";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't include amenity= here. These should be the tag values, not keys.

Comment on lines 66 to 67
let isFoodLocation = category == .places &&
localizedName.lowercased().contains(GDLocalizedString("osm.tag.restaurant").lowercased())
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was suggesting matching the amenity attribute of the place, rather than its name. I haven't tested this, but I'm thinking all you'd have to do is something like:

let isFoodLocation = amenity == GDLocalizedString("osm.tag.restaurant")

where amenity should be recognized as a field of GDASpatialDataResultEntity per

Comment on lines 211 to 214
if value == "fast_food"{
superCategory = SuperCategory.foods
return
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did this not work to assign the supercategory? This feels like the right place to be doing the classification of GeoJSON features, so the later filtering logic can be based entirely on the superCategory field.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I still think you can do the category assignment here. When the OSM feature is tagged with e.g. leisure=playground, the local variable type will be leisure here, and value will be playground.

@jonha1
Copy link
Contributor Author

jonha1 commented Jul 24, 2024

Your code helped me gain a better understanding of it. Food saw more results however not all of them appeared. Landmarks seems to be working mostly well, some results dont match since I dont consdier them to be a landmark. For exmaple, the focus lab in Troy, NY isn't a landmark and I dont know why it is being classified as one. What should I do about it?

@steinbro
Copy link
Member

For exmaple, the focus lab in Troy, NY isn't a landmark and I dont know why it is being classified as one. What should I do about it?

Here are the OSM tags for the FOCUS Lab: https://www.openstreetmap.org/node/10565967149

Of note is the tourism=gallery tag.

I searched for "gallery" in the Soundscape codebase, and found it here, being mapped to "landmark":

"landmark": ["waterfall", "boatyard", "theme_park", "roundhouse", "generator", "beach", "naval_base", "works", "water_works", "telescope", "pier", "observatory", "reservoir", "monument", "battlefield", "post_office", "planetarium", "social_centre", "prison", "courthouse", "bridge", "hangar", "tower", "attraction", "zoo", "gallery", "artwork", "alpine_hut", "plant", "insurance", "airfield", "water_tower", "pumping_station", "hot_water_tank", "campanile", "sports_centre", "beach_resort", "village_green", "ship", "memorial", "synagogue", "mosque", "chapel", "cathedral", "train_terminal", "college", "arts_centre", "ranger_station", "hospital", "fountain", "track", "conference_centre", "viewpoint", "supermarket", "peak", "storage_tank", "lighthouse", "beacon", "park", "port", "archaeological_site", "train_station", "shrine", "church", "historic_monument", "generic_landmark", "tourism_museum", "register_office", "grave_yard", "school", "marketplace", "fire_station", "ruins", "weir", "museum", "mall", "volcano", "hot_spring", "glacier", "wastewater_plant", "offshore_platform", "gasometer", "water_park", "bandstand", "wreck", "pillory", "monastery", "locomotive", "fort", "services", "lifeguard_tower", "temple", "national_park", "heliport", "public_park", "department_store", "studio", "public_building", "place_of_worship", "clock", "casino", "ferry_terminal", "stadium", "dam", "dock", "geyser", "bay", "barracks", "windmill", "watermill", "communications_tower", "swimming_area", "slipway", "nature_reserve", "marina", "ice_rink", "manor", "city_gate", "castle", "aircraft", "digester", "sally_port", "aerodrome", "shopping_mall", "cinema", "rescue_station", "airport", "theatre", "library", "university", "townhall", "police", "embassy", "bus_station", "station"],

That code is part of the OSM data ingestion, specifically to add custom fields that Soundscape uses. I believe the mapping there is used to determine what sound effect should be played for each map feature (for example, a "safety" item plays a different sound than a "landmark" does). The list includes many different types of locations, most of which wouldn't be considered landmarks in the colloquial sense, so we can't really depend on the category field for our purposes here.

- need to fix OSM tags and isPark
@jonha1
Copy link
Contributor Author

jonha1 commented Jul 26, 2024

Thanks, the feedback greatly helped!

Copy link
Member

@steinbro steinbro left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Glad I could help. I assume you're still working on the other categories, cleaning up print statements, and adding some categorization test cases? I've also added a few more comments.

Comment on lines 137 to 139
let lowercasedAmenity = amenity.lowercased()

let isParkLocation = parkTags.contains(lowercasedAmenity)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You'd want to do exact comparison rather than substrings, no? Otherwise you wind up matching e.g. parking lots as parks.

Comment on lines 124 to 135
let parkTags = [
GDLocalizedString("osm.tag.park"),
GDLocalizedString("osm.tag.garden"),
GDLocalizedString("osm.tag.green_space"),
GDLocalizedString("osm.tag.recreation_area"),
GDLocalizedString("osm.tag.playground"),
GDLocalizedString("osm.tag.nature_reserve"),
GDLocalizedString("osm.tag.botanical_garden"),
GDLocalizedString("osm.tag.public_garden"),
GDLocalizedString("osm.tag.field"),
GDLocalizedString("osm.tag.reserve")
]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe OSM tags are always in English, so no need to localize each of these. (I know I said to use localized strings, but that was when you were comparing against place names, which are in the local language.)

@jonha1
Copy link
Contributor Author

jonha1 commented Jul 29, 2024

For test location (Latitude: 42.732782, Longitude: -73.68809) when I filter by park, I get a result named "leisure=garden". Do you know why? Is isPark how you want the other functions to be like?

@steinbro
Copy link
Member

For test location (Latitude: 42.732782, Longitude: -73.68809) when I filter by park, I get a result named "leisure=garden". Do you know why? Is isPark how you want the other functions to be like?

Maybe there's a nearby green area that's tagged in OSM as leisure=park but has no name? I thought that the code already handled unnamed features gracefully, like crosswalks. In cases like these, the filtered features should have human-friendly names like "Park", and this is where you'll want to use localized strings for the name. I believe the code that constructs the localized name for an OSM feature is here: https://github.com/soundscape-community/soundscape/blob/main/apps/ios/GuideDogs/Code/Data/Models/Extensions/OSM%20Entity/GDASpatialDataResult%2BExtensions.swift#L54

@jonha1
Copy link
Contributor Author

jonha1 commented Aug 1, 2024

It turns out that the place name defined by localizedName is "leasure=garden". I tested the same logic for landmakrs and it works. I'll impelment it for the other functions soon.

@jonha1
Copy link
Contributor Author

jonha1 commented Aug 2, 2024

The functions should now have similiar logic and all works. The reason why the localizedName is "leisure=garden" is due to the fact that the garden doesnt have a name on open street maps. There is no name associated with it. How would you like me to handle it?
image

Copy link
Member

@steinbro steinbro left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The quick answer to your question is that if you simply tweak your localized strings to human-readable form, you'll wind up with nice human-readable names even for unnamed OSM entities. More feedback in comments below.

Comment on lines 3313 to 3324
"osm.tag.park" = "leisure=park";

//TODO JON
"osm.tag.garden" = "leisure=garden";
"osm.tag.playground" = "leisure=playground";
"osm.tag.nature_reserve" = "leisure=nature_reserve";
"osm.tag.botanical_garden" = "leisure=botanical_garden";
"osm.tag.public_garden" = "leisure=public_garden";
"osm.tag.field" = "leisure=field";
"osm.tag.reserve" = "leisure=reserve";
"osm.tag.green_space" = "leisure=green_space";
"osm.tag.recreation_area" = "leisure=recreation_area";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These should be the human-friendly version of the text, e.g. "osm.tag.public_garden" = "Public Garden";. This is what gets displayed in the UI when them entity doesn't have a name.

self.image = UIImage(named: "Transit")
case .food:
self.localizedString = GDLocalizedString("filter.food_drink")
self.image = UIImage(named: "Food and Drinks")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do these icons exist? I see an image next to Transit, but not the others.

self.localizedString = GDLocalizedString("filter.park")
self.image = UIImage(named: "Parks")
case .hotel:
self.localizedString = GDLocalizedString("filter.hotel")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This key is missing from the English localizations.

Comment on lines 211 to 214
if value == "fast_food"{
superCategory = SuperCategory.foods
return
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I still think you can do the category assignment here. When the OSM feature is tagged with e.g. leisure=playground, the local variable type will be leisure here, and value will be playground.

Comment on lines 22 to 26
NearbyTableFilter(type: .transit),
NearbyTableFilter(type: .food),
NearbyTableFilter(type: .landmarks),
NearbyTableFilter(type: .park),
NearbyTableFilter(type: .hotel)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should be consistent with pluralization, both in variable names and displayed strings. Transit and Food are both collective nouns, but Landmarks, Parks, and Hotels need a trailing "s".

Comment on lines 62 to 68
GDLocalizedString("osm.tag.restaurant"),
GDLocalizedString("osm.tag.fast_food"),
GDLocalizedString("osm.tag.cafe"),
GDLocalizedString("osm.tag.bar"),
GDLocalizedString("osm.tag.ice_cream"),
GDLocalizedString("osm.tag.pub"),
GDLocalizedString("osm.tag.coffee_shop")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You don't need to use localized strings here, because the OSM tag will always be e.g. "restaurant" regardless of what language the name of the restaurant is in. I think you're handling this properly in landmarks and parks below.

@steinbro
Copy link
Member

steinbro commented Sep 7, 2024

@jonha1 I went ahead and cleaned this up since I wanted to see this deployed. I figured you wouldn't mind. :)

@RDMurray This is ready for inclusion in the next TestFlight build. I haven't merged since I wasn't sure whether you prefer we merge branches before or after they've been tested.

@RDMurray
Copy link
Contributor

It looks good here, categories are working in my local area.

I don't have any objection to you merging PRs in the future when you think they are ready.

@RDMurray RDMurray merged commit 5f5ade4 into soundscape-community:main Sep 10, 2024
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants