From e7f2d1ffc3f85bd6a904472b9ad6b0198ba48ce0 Mon Sep 17 00:00:00 2001 From: Andras Schmelczer Date: Sat, 7 Feb 2026 19:27:35 +0000 Subject: [PATCH] Update poi mapping --- pipeline/transform/transform_poi.py | 1491 ++++++++++++++++++--------- 1 file changed, 981 insertions(+), 510 deletions(-) diff --git a/pipeline/transform/transform_poi.py b/pipeline/transform/transform_poi.py index 8482142..cdff4c6 100644 --- a/pipeline/transform/transform_poi.py +++ b/pipeline/transform/transform_poi.py @@ -1,49 +1,128 @@ import argparse -import warnings from pathlib import Path import polars as pl DROP_CATEGORIES = { + # Street furniture & infrastructure "amenity/advice", "amenity/atm", "amenity/bbq", "amenity/bench", "amenity/bicycle_parking", + "amenity/binoculars", + "amenity/boot_scraper", + "amenity/check_in", "amenity/clock", + "amenity/compressed_air", + "amenity/donation_box", + "amenity/dressing_room", + "amenity/drinking_water", + "shop/taxi", + "amenity/feeding_place", "amenity/fixme", "amenity/grit_bin", "amenity/hunting_stand", + "amenity/letter_box", + "amenity/loading_dock", + "amenity/lounge", + "tourism/preserved_railway", + "amenity/lounger", "amenity/motorcycle_parking", + "amenity/mounting_block", "amenity/notice_board", + "amenity/parcel_locker", "amenity/parking", "amenity/parking_entrance", "amenity/parking_space", + "amenity/payment_terminal", + "amenity/photo_booth", + "amenity/piano", "amenity/post_box", + "amenity/public_bookcase", + "amenity/reception_desk", + "amenity/sanitary_dump_station", + "amenity/shelter", + "amenity/shower", + "amenity/smoking_area", + "amenity/table", "amenity/telephone", + "amenity/telescope", + "amenity/ticket_validator", "amenity/toilets", + "amenity/trolley_bay", "amenity/vacuum_cleaner", + "amenity/vending_machine", + "amenity/washing_machine", + "amenity/washingline", "amenity/waste_basket", + "amenity/waste_disposal", + "amenity/waste_transfer_station", + "amenity/water_point", + "amenity/watering_place", + "amenity/weighbridge", + # Niche amenities not useful for home buyers + "amenity/animal_boarding", + "amenity/animal_breeding", + "amenity/animal_shelter", + "amenity/boat_storage", + "amenity/bureau_de_change", + "amenity/bus_station", + "amenity/conference_centre", + "amenity/crematorium", + "amenity/driving_school", + "amenity/escooter_rental", + "amenity/ferry_terminal", + "amenity/grave_yard", + "amenity/hall", + "shop/funeral_directors", + "amenity/kick-scooter_rental", + "amenity/money_transfer", + "amenity/post_depot", + "amenity/public_building", + "amenity/recycling", + "amenity/scout_hut", + "amenity/social_facility", + "amenity/studio", + "amenity/taxi", + "amenity/training", + "amenity/vehicle_inspection", + # Buildings (except church & university which are mapped) "building/air_shaft", "building/apartments", + "building/barn", + "building/bunker", + "building/chapel", + "building/commercial", + "building/construction", "building/detached", "building/entrance", "building/entry", + "building/farm", "building/garage", "building/garages", + "building/greenhouse", "building/house", "building/hut", + "building/industrial", + "building/kiosk", "building/no", "building/office", "building/public", "building/residential", + "building/retail", "building/roof", + "building/ruins", + "building/school", + "building/semidetached_house", + "building/service", "building/shed", "building/terrace", + "building/warehouse", "building/yes", + # All emergency "emergency/access_point", - "emergency/ambulance_station", "emergency/assembly_point", "emergency/bleed_control_kit", "emergency/defibrillator", @@ -64,512 +143,904 @@ DROP_CATEGORIES = { "emergency/throw_bag", "emergency/water_rescue", "emergency/yes", - "leisure/firepit", - "leisure/fishing", - "leisure/picnic_table", - "office/company", - "office/yes", "tourism/apartment", "tourism/apartments", "tourism/camp_pitch", + "tourism/caravan_site", "tourism/information", + "tourism/picnic_site", + "tourism/viewpoint", "tourism/village_sign", "tourism/yes", - # public transport comes from naptan + # Public transport (from NaPTAN instead) "public_transport/entrance", "public_transport/platform", "public_transport/station", "public_transport/stop_position", } -# (friendly_name, emoji) for every category we keep -CATEGORY_MAP: dict[str, tuple[str, str]] = { - # amenity - "amenity/animal_boarding": ("Animal Boarding", "๐Ÿพ"), - "amenity/animal_breeding": ("Animal Breeding", "๐Ÿฃ"), - "amenity/animal_shelter": ("Animal Shelter", "๐Ÿ "), - "amenity/arts_centre": ("Arts Centre", "๐ŸŽจ"), - "amenity/bank": ("Bank", "๐Ÿฆ"), - "amenity/bar": ("Bar", "๐Ÿธ"), - "amenity/bicycle_rental": ("Bike Rental", "๐Ÿšฒ"), - "amenity/bicycle_repair_station": ("Bike Repair", "๐Ÿ”ง"), - "amenity/binoculars": ("Public Binoculars", "๐Ÿ”ญ"), - "amenity/boat_rental": ("Boat Rental", "โ›ต"), - "amenity/boat_storage": ("Boat Storage", "๐Ÿšข"), - "amenity/boot_scraper": ("Boot Scraper", "๐Ÿฅพ"), - "amenity/bureau_de_change": ("Currency Exchange", "๐Ÿ’ฑ"), - "amenity/bus_station": ("Bus Station", "๐ŸšŒ"), - "amenity/cafe": ("Cafรฉ", "โ˜•"), - "amenity/car_rental": ("Car Rental", "๐Ÿš—"), - "amenity/car_sharing": ("Car Sharing", "๐Ÿš™"), - "amenity/car_wash": ("Car Wash", "๐Ÿงฝ"), - "amenity/care_home": ("Care Home", "๐Ÿฅ"), - "amenity/casino": ("Casino", "๐ŸŽฐ"), - "amenity/charging_station": ("EV Charging", "๐Ÿ”Œ"), - "amenity/check_in": ("Check-In Point", "โœ…"), - "amenity/childcare": ("Childcare", "๐Ÿ‘ถ"), - "amenity/cinema": ("Cinema", "๐ŸŽฌ"), - "amenity/clinic": ("Clinic", "๐Ÿฉบ"), - "amenity/club": ("Club", "๐Ÿ›๏ธ"), - "amenity/college": ("College", "๐ŸŽ“"), - "amenity/community_centre": ("Community Centre", "๐Ÿค"), - "amenity/compressed_air": ("Compressed Air", "๐Ÿ’จ"), - "amenity/conference_centre": ("Conference Centre", "๐Ÿ“‹"), - "amenity/courthouse": ("Courthouse", "โš–๏ธ"), - "amenity/coworking_space": ("Co-working Space", "๐Ÿ’ป"), - "amenity/crematorium": ("Crematorium", "๐Ÿ•ฏ๏ธ"), - "amenity/dancing_school": ("Dance School", "๐Ÿ’ƒ"), - "amenity/dentist": ("Dentist", "๐Ÿฆท"), - "amenity/doctors": ("Doctor", "๐Ÿ‘จโ€โš•๏ธ"), - "amenity/dojo": ("Dojo", "๐Ÿฅ‹"), - "amenity/donation_box": ("Donation Box", "๐Ÿ“ฆ"), - "amenity/dressing_room": ("Dressing Room", "๐Ÿ‘—"), - "amenity/drinking_water": ("Drinking Water", "๐Ÿšฐ"), - "amenity/driving_school": ("Driving School", "๐Ÿšฆ"), - "amenity/escooter_rental": ("E-Scooter Rental", "๐Ÿ›ด"), - "amenity/events_venue": ("Events Venue", "๐ŸŽช"), - "amenity/fast_food": ("Fast Food", "๐Ÿ”"), - "amenity/feeding_place": ("Feeding Place", "๐Ÿฝ๏ธ"), - "amenity/ferry_terminal": ("Ferry Terminal", "โ›ด๏ธ"), - "amenity/fire_station": ("Fire Station", "๐Ÿš’"), - "amenity/food_court": ("Food Court", "๐Ÿด"), - "amenity/fountain": ("Fountain", "โ›ฒ"), - "amenity/fuel": ("Fuel Station", "โ›ฝ"), - "amenity/gambling": ("Gambling", "๐ŸŽฒ"), - "amenity/grave_yard": ("Graveyard", "๐Ÿชฆ"), - "amenity/hall": ("Hall", "๐Ÿ›๏ธ"), - "amenity/hookah_lounge": ("Hookah Lounge", "๐Ÿ’จ"), - "amenity/hospital": ("Hospital", "๐Ÿฅ"), - "amenity/ice_cream": ("Ice Cream", "๐Ÿฆ"), - "amenity/internet_cafe": ("Internet Cafรฉ", "๐ŸŒ"), - "amenity/kick-scooter_rental": ("Kick Scooter Rental", "๐Ÿ›ด"), - "amenity/kindergarten": ("Kindergarten", "๐Ÿ’’"), - "amenity/language_school": ("Language School", "๐Ÿ—ฃ๏ธ"), - "amenity/letter_box": ("Letter Box", "๐Ÿ“ฎ"), - "amenity/library": ("Library", "๐Ÿ“š"), - "amenity/loading_dock": ("Loading Dock", "๐Ÿ“ฅ"), - "amenity/lounge": ("Lounge", "๐Ÿ›‹๏ธ"), - "amenity/lounger": ("Public Lounger", "๐Ÿช‘"), - "amenity/marketplace": ("Market", "๐Ÿ›’"), - "amenity/money_transfer": ("Money Transfer", "๐Ÿ’ธ"), - "amenity/mounting_block": ("Mounting Block", "๐Ÿด"), - "amenity/music_school": ("Music School", "๐ŸŽต"), - "amenity/music_venue": ("Music Venue", "๐ŸŽถ"), - "amenity/nightclub": ("Nightclub", "๐Ÿชฉ"), - "amenity/nursing_home": ("Nursing Home", "๐Ÿ "), - "amenity/parcel_locker": ("Parcel Locker", "๐Ÿ“ฆ"), - "amenity/payment_terminal": ("Payment Terminal", "๐Ÿ’ณ"), - "amenity/pharmacy": ("Pharmacy", "๐Ÿ’Š"), - "amenity/photo_booth": ("Photo Booth", "๐Ÿ“ธ"), - "amenity/piano": ("Public Piano", "๐ŸŽน"), - "amenity/place_of_worship": ("Place of Worship", "โ›ช"), - "amenity/police": ("Police Station", "๐Ÿš”"), - "amenity/post_depot": ("Post Depot", "๐Ÿ“ฌ"), - "amenity/post_office": ("Post Office", "๐Ÿค"), - "amenity/prep_school": ("Prep School", "๐Ÿ“–"), - "amenity/pub": ("Pub", "๐Ÿบ"), - "amenity/public_bookcase": ("Public Bookcase", "๐Ÿ“•"), - "amenity/public_building": ("Public Building", "๐Ÿข"), - "amenity/reception_desk": ("Reception Desk", "๐Ÿ›Ž๏ธ"), - "amenity/recycling": ("Recycling", "โ™ป๏ธ"), - "amenity/restaurant": ("Restaurant", "๐Ÿฝ๏ธ"), - "amenity/sanitary_dump_station": ("Sanitary Dump Station", "๐Ÿšฟ"), - "amenity/school": ("School", "๐Ÿซ"), - "amenity/scout_hut": ("Scout Hut", "โšœ๏ธ"), - "amenity/shelter": ("Shelter", "๐Ÿ›–"), - "amenity/shower": ("Public Shower", "๐Ÿšฟ"), - "amenity/smoking_area": ("Smoking Area", "๐Ÿšฌ"), - "amenity/social_centre": ("Social Centre", "๐Ÿ˜๏ธ"), - "amenity/social_club": ("Social Club", "๐Ÿค"), - "amenity/social_facility": ("Social Facility", "๐Ÿซ‚"), - "amenity/stripclub": ("Strip Club", "๐Ÿ”ž"), - "amenity/studio": ("Studio", "๐ŸŽ™๏ธ"), - "amenity/table": ("Public Table", "๐Ÿช‘"), - "amenity/taxi": ("Taxi Stand", "๐Ÿš•"), - "amenity/telescope": ("Public Telescope", "๐Ÿ”ญ"), - "amenity/theatre": ("Theatre", "๐ŸŽญ"), - "amenity/ticket_validator": ("Ticket Validator", "๐ŸŽซ"), - "amenity/townhall": ("Town Hall", "๐Ÿ›๏ธ"), - "amenity/training": ("Training Centre", "๐Ÿ“"), - "amenity/trolley_bay": ("Trolley Bay", "๐Ÿ›’"), - "amenity/university": ("University", "๐Ÿซ"), - "amenity/vehicle_inspection": ("Vehicle Inspection", "๐Ÿ”"), - "amenity/vending_machine": ("Vending Machine", "๐Ÿง"), - "amenity/veterinary": ("Vet", "๐Ÿ•"), - "amenity/washing_machine": ("Washing Machine", "๐Ÿงบ"), - "amenity/washingline": ("Washing Line", "๐Ÿ‘•"), - "amenity/waste_disposal": ("Waste Disposal", "๐Ÿ—‘๏ธ"), - "amenity/waste_transfer_station": ("Waste Transfer Station", "๐Ÿš›"), - "amenity/water_point": ("Water Point", "๐Ÿ’ง"), - "amenity/watering_place": ("Watering Place", "๐Ÿšฐ"), - "amenity/weighbridge": ("Weighbridge", "โš–๏ธ"), - # building - "building/barn": ("Barn", "๐Ÿš๏ธ"), - "building/bunker": ("Bunker", "๐Ÿ—๏ธ"), - "building/chapel": ("Chapel", "โ›ช"), - "building/church": ("Church", "โ›ช"), - "building/commercial": ("Commercial Building", "๐Ÿฌ"), - "building/construction": ("Construction Site", "๐Ÿšง"), - "building/farm": ("Farmhouse", "๐ŸŒพ"), - "building/greenhouse": ("Greenhouse", "๐ŸŒฟ"), - "building/industrial": ("Industrial Building", "๐Ÿญ"), - "building/kiosk": ("Kiosk", "๐Ÿช"), - "building/retail": ("Retail Building", "๐Ÿฌ"), - "building/ruins": ("Ruins", "๐Ÿš๏ธ"), - "building/school": ("School Building", "๐Ÿซ"), - "building/semidetached_house": ("Semi-Detached House", "๐Ÿ "), - "building/service": ("Service Building", "๐Ÿ”ง"), - "building/university": ("University Building", "๐ŸŽ“"), - "building/warehouse": ("Warehouse", "๐Ÿญ"), - # craft - "craft/agricultural_engines": ("Agricultural Engines", "๐Ÿšœ"), - "craft/atelier": ("Atelier", "๐ŸŽจ"), - "craft/blacksmith": ("Blacksmith", "๐Ÿ”จ"), - "craft/bookbinder": ("Bookbinder", "๐Ÿ“–"), - "craft/brewery": ("Brewery", "๐Ÿบ"), - "craft/builder": ("Builder", "๐Ÿงฑ"), - "craft/carpenter": ("Carpenter", "๐Ÿชš"), - "craft/caterer": ("Caterer", "๐Ÿฑ"), - "craft/cleaning": ("Cleaning Service", "๐Ÿงน"), - "craft/confectionery": ("Confectioner", "๐Ÿฌ"), - "craft/distillery": ("Distillery", "๐Ÿฅƒ"), - "craft/dressmaker": ("Dressmaker", "๐Ÿ‘—"), - "craft/electrician": ("Electrician", "โšก"), - "craft/electronics_repair": ("Electronics Repair", "๐Ÿ”Œ"), - "craft/floorer": ("Flooring Specialist", "๐Ÿชต"), - "craft/gardener": ("Gardener", "๐ŸŒฑ"), - "craft/glaziery": ("Glazier", "๐ŸชŸ"), - "craft/handicraft": ("Handicraft", "โœ‚๏ธ"), - "craft/hvac": ("HVAC", "โ„๏ธ"), - "craft/jeweller": ("Jeweller", "๐Ÿ’Ž"), - "craft/joiner": ("Joiner", "๐Ÿชš"), - "craft/key_cutter": ("Key Cutter", "๐Ÿ”‘"), - "craft/locksmith": ("Locksmith", "๐Ÿ”"), - "craft/metal_construction": ("Metal Fabrication", "๐Ÿ”ฉ"), - "craft/painter": ("Painter & Decorator", "๐Ÿ–Œ๏ธ"), - "craft/photographer": ("Photographer", "๐Ÿ“ท"), - "craft/photographic_laboratory": ("Photo Lab", "๐Ÿ–ผ๏ธ"), - "craft/plumber": ("Plumber", "๐Ÿ”ง"), - "craft/pottery": ("Pottery", "๐Ÿบ"), - "craft/printer": ("Printer", "๐Ÿ–จ๏ธ"), - "craft/roofer": ("Roofer", "๐Ÿ "), - "craft/sawmill": ("Sawmill", "๐Ÿชต"), - "craft/scaffolder": ("Scaffolder", "๐Ÿ—๏ธ"), - "craft/sculptor": ("Sculptor", "๐Ÿ—ฟ"), - "craft/shoemaker": ("Shoemaker", "๐Ÿ‘ž"), - "craft/signmaker": ("Sign Maker", "๐Ÿชง"), - "craft/stonemason": ("Stonemason", "๐Ÿชจ"), - "craft/tailor": ("Tailor", "๐Ÿงต"), - "craft/upholsterer": ("Upholsterer", "๐Ÿ›‹๏ธ"), - "craft/watchmaker": ("Watchmaker", "โŒš"), - "craft/window_construction": ("Window Fitter", "๐ŸชŸ"), - "craft/winery": ("Winery", "๐Ÿท"), - "craft/yes": ("Craft Workshop", "๐Ÿ› ๏ธ"), - # healthcare - "healthcare/alternative": ("Alternative Medicine", "๐ŸŒฟ"), - "healthcare/audiologist": ("Audiologist", "๐Ÿ‘‚"), - "healthcare/centre": ("Health Centre", "๐Ÿฅ"), - "healthcare/clinic": ("Health Clinic", "๐Ÿฉบ"), - "healthcare/counselling": ("Counselling", "๐Ÿง "), - "healthcare/dentist": ("Dental Practice", "๐Ÿฆท"), - "healthcare/doctor": ("GP Surgery", "๐Ÿ‘จโ€โš•๏ธ"), - "healthcare/hospital": ("Hospital", "๐Ÿฅ"), - "healthcare/laboratory": ("Medical Lab", "๐Ÿ”ฌ"), - "healthcare/optometrist": ("Optometrist", "๐Ÿ‘๏ธ"), - "healthcare/pharmacy": ("Pharmacy", "๐Ÿ’Š"), - "healthcare/physiotherapist": ("Physiotherapist", "๐Ÿƒ"), - "healthcare/podiatrist": ("Podiatrist", "๐Ÿฆถ"), - "healthcare/psychotherapist": ("Psychotherapist", "๐Ÿง "), - "healthcare/rehabilitation": ("Rehabilitation Centre", "โ™ฟ"), - "healthcare/vaccination_centre": ("Vaccination Centre", "๐Ÿ’‰"), - "healthcare/yes": ("Healthcare Facility", "๐Ÿฅ"), - # leisure - "leisure/adult_gaming_centre": ("Adult Gaming Centre", "๐ŸŽฎ"), - "leisure/amusement_arcade": ("Amusement Arcade", "๐Ÿ•น๏ธ"), - "leisure/bandstand": ("Bandstand", "๐ŸŽบ"), - "leisure/bathing_place": ("Bathing Spot", "๐Ÿ–๏ธ"), - "leisure/bird_hide": ("Bird Hide", "๐Ÿฆ"), - "leisure/bowling_alley": ("Bowling Alley", "๐ŸŽณ"), - "leisure/common": ("Common Land", "๐ŸŒณ"), - "leisure/dance": ("Dance Venue", "๐Ÿ’ƒ"), - "leisure/dog_park": ("Dog Park", "๐Ÿ•"), - "leisure/escape_game": ("Escape Room", "๐Ÿ”“"), - "leisure/fitness_centre": ("Gym", "๐Ÿ‹๏ธ"), - "leisure/fitness_station": ("Outdoor Gym", "๐Ÿ’ช"), - "leisure/garden": ("Garden", "๐ŸŒท"), - "leisure/golf_course": ("Golf Course", "โ›ณ"), - "leisure/hackerspace": ("Hackerspace", "๐Ÿ’ป"), - "leisure/horse_riding": ("Horse Riding", "๐ŸŽ"), - "leisure/indoor_play": ("Indoor Play Area", "๐Ÿง’"), - "leisure/marina": ("Marina", "โš“"), - "leisure/miniature_golf": ("Mini Golf", "โ›ณ"), - "leisure/nature_reserve": ("Nature Reserve", "๐Ÿฆ”"), - "leisure/outdoor_seating": ("Outdoor Seating", "๐Ÿช‘"), - "leisure/park": ("Park", "๐ŸŒณ"), - "leisure/pitch": ("Sports Pitch", "โšฝ"), - "leisure/playground": ("Playground", "๐Ÿ›"), - "leisure/sauna": ("Sauna", "๐Ÿง–"), - "leisure/slipway": ("Slipway", "๐Ÿšค"), - "leisure/social_club": ("Social Club", "๐Ÿป"), - "leisure/sports_centre": ("Sports Centre", "๐ŸŸ๏ธ"), - "leisure/sports_hall": ("Sports Hall", "๐Ÿ€"), - "leisure/swimming_pool": ("Swimming Pool", "๐ŸŠ"), - "leisure/tanning_salon": ("Tanning Salon", "โ˜€๏ธ"), - "leisure/track": ("Running Track", "๐Ÿƒ"), - "leisure/trampoline_park": ("Trampoline Park", "๐Ÿคธ"), - "leisure/water_park": ("Water Park", "๐ŸŒŠ"), - "leisure/wildlife_hide": ("Wildlife Hide", "๐ŸฆŒ"), - "leisure/yes": ("Leisure Facility", "๐ŸŽ‰"), - # office - "office/accountant": ("Accountant", "๐Ÿงฎ"), - "office/advertising_agency": ("Advertising Agency", "๐Ÿ“ข"), - "office/architect": ("Architect", "๐Ÿ“"), - "office/association": ("Association", "๐Ÿ›๏ธ"), - "office/charity": ("Charity", "โค๏ธ"), - "office/construction_company": ("Construction Company", "๐Ÿ—๏ธ"), - "office/consulting": ("Consulting Firm", "๐Ÿ“Š"), - "office/courier": ("Courier Service", "๐Ÿ“ฆ"), - "office/coworking": ("Co-working Space", "๐Ÿ’ป"), - "office/design": ("Design Studio", "๐ŸŽจ"), - "office/diplomatic": ("Diplomatic Office", "๐Ÿ›๏ธ"), - "office/educational_institution": ("Education Office", "๐ŸŽ“"), - "office/employment_agency": ("Employment Agency", "๐Ÿ’ผ"), - "office/energy_supplier": ("Energy Supplier", "โšก"), - "office/engineer": ("Engineering Firm", "โš™๏ธ"), - "office/estate_agent": ("Estate Agent", "๐Ÿ "), - "office/financial": ("Financial Services", "๐Ÿ’ฐ"), - "office/financial_advisor": ("Financial Advisor", "๐Ÿ“ˆ"), - "office/foundation": ("Foundation", "๐Ÿ›๏ธ"), - "office/government": ("Government Office", "๐Ÿ›๏ธ"), - "office/graphic_design": ("Graphic Design", "๐Ÿ–Œ๏ธ"), - "office/healthcare": ("Healthcare Office", "๐Ÿฅ"), - "office/home_care": ("Home Care Service", "๐Ÿ "), - "office/insurance": ("Insurance", "๐Ÿ›ก๏ธ"), - "office/interior_design": ("Interior Design", "๐Ÿ›‹๏ธ"), - "office/it": ("IT Company", "๐Ÿ’ป"), - "office/lawyer": ("Lawyer", "โš–๏ธ"), - "office/logistics": ("Logistics", "๐Ÿšš"), - "office/marketing": ("Marketing Agency", "๐Ÿ“ฃ"), - "office/mortgage": ("Mortgage Broker", "๐Ÿฆ"), - "office/moving_company": ("Moving Company", "๐Ÿ“ฆ"), - "office/newspaper": ("Newspaper Office", "๐Ÿ“ฐ"), - "office/ngo": ("NGO", "๐ŸŒ"), - "office/notary": ("Notary", "๐Ÿ“œ"), - "office/political_party": ("Political Party", "๐Ÿ—ณ๏ธ"), - "office/politician": ("Politician Office", "๐Ÿ›๏ธ"), - "office/property_management": ("Property Management", "๐Ÿ˜๏ธ"), - "office/recruitment": ("Recruitment Agency", "๐Ÿ‘ฅ"), - "office/religion": ("Religious Office", "โœ๏ธ"), - "office/research": ("Research Office", "๐Ÿ”ฌ"), - "office/security": ("Security Company", "๐Ÿ”’"), - "office/solicitor": ("Solicitor", "โš–๏ธ"), - "office/surveyor": ("Surveyor", "๐Ÿ“"), - "office/tax_advisor": ("Tax Advisor", "๐Ÿงพ"), - "office/taxi": ("Taxi Office", "๐Ÿš•"), - "office/telecommunication": ("Telecoms Office", "๐Ÿ“ก"), - "office/therapist": ("Therapist", "๐Ÿง "), - "office/travel_agent": ("Travel Agent", "โœˆ๏ธ"), - "office/union": ("Trade Union", "โœŠ"), - "office/university": ("University Office", "๐ŸŽ“"), - "office/vacant": ("Vacant Office", "๐Ÿš๏ธ"), - "office/web_design": ("Web Design", "๐ŸŒ"), - # shop - "shop/accessories": ("Accessories Shop", "๐Ÿ‘œ"), - "shop/agrarian": ("Farm Supply Shop", "๐ŸŒพ"), - "shop/alcohol": ("Off-Licence", "๐Ÿท"), - "shop/antiques": ("Antiques Shop", "๐Ÿบ"), - "shop/appliance": ("Appliance Shop", "๐Ÿ”Œ"), - "shop/art": ("Art Shop", "๐ŸŽจ"), - "shop/baby_goods": ("Baby Shop", "๐Ÿผ"), - "shop/bag": ("Bag Shop", "๐Ÿ‘œ"), - "shop/bakery": ("Bakery", "๐Ÿฅ"), - "shop/bathroom": ("Bathroom Shop", "๐Ÿ›"), - "shop/bathroom_furnishing": ("Bathroom Furnishings", "๐Ÿšฟ"), - "shop/beauty": ("Beauty Shop", "๐Ÿ’„"), - "shop/bed": ("Bed Shop", "๐Ÿ›๏ธ"), - "shop/beverages": ("Drinks Shop", "๐Ÿฅค"), - "shop/bicycle": ("Bike Shop", "๐Ÿšฒ"), - "shop/boat": ("Boat Shop", "โ›ต"), - "shop/bookmaker": ("Bookmaker", "๐Ÿ‡"), - "shop/books": ("Bookshop", "๐Ÿ“š"), - "shop/boutique": ("Boutique", "๐Ÿ‘—"), - "shop/building_materials": ("Building Materials", "๐Ÿงฑ"), - "shop/butcher": ("Butcher", "๐Ÿฅฉ"), - "shop/camera": ("Camera Shop", "๐Ÿ“ท"), - "shop/candles": ("Candle Shop", "๐Ÿ•ฏ๏ธ"), - "shop/car": ("Car Dealership", "๐Ÿš—"), - "shop/car;car_repair": ("Car Sales & Repair", "๐Ÿš—"), - "shop/car_parts": ("Car Parts", "๐Ÿ”ฉ"), - "shop/car_repair": ("Car Repair", "๐Ÿ”ง"), - "shop/caravan": ("Caravan Dealer", "๐Ÿš"), - "shop/carpet": ("Carpet Shop", "๐Ÿงถ"), - "shop/catalogue": ("Catalogue Shop", "๐Ÿ“‹"), - "shop/charity": ("Charity Shop", "โค๏ธ"), - "shop/cheese": ("Cheese Shop", "๐Ÿง€"), - "shop/chemist": ("Chemist", "๐Ÿงช"), - "shop/chocolate": ("Chocolate Shop", "๐Ÿซ"), - "shop/clothes": ("Clothes Shop", "๐Ÿ‘•"), - "shop/coffee": ("Coffee Shop", "โ˜•"), - "shop/collector": ("Collector Shop", "๐Ÿ†"), - "shop/computer": ("Computer Shop", "๐Ÿ–ฅ๏ธ"), - "shop/confectionery": ("Sweet Shop", "๐Ÿฌ"), - "shop/convenience": ("Convenience Store", "๐Ÿช"), - "shop/copyshop": ("Copy Shop", "๐Ÿ–จ๏ธ"), - "shop/cosmetics": ("Cosmetics Shop", "๐Ÿ’…"), - "shop/country_store": ("Country Store", "๐Ÿก"), - "shop/craft": ("Craft Shop", "โœ‚๏ธ"), - "shop/curtain": ("Curtain Shop", "๐ŸชŸ"), - "shop/dairy": ("Dairy Shop", "๐Ÿฅ›"), - "shop/deli": ("Delicatessen", "๐Ÿง†"), - "shop/department_store": ("Department Store", "๐Ÿฌ"), - "shop/discount": ("Discount Store", "๐Ÿ’ฒ"), - "shop/doityourself": ("DIY Store", "๐Ÿ”จ"), - "shop/doors": ("Door Shop", "๐Ÿšช"), - "shop/dry_cleaning": ("Dry Cleaner", "๐Ÿ‘”"), - "shop/e-cigarette": ("Vape Shop", "๐Ÿ’จ"), - "shop/electrical": ("Electrical Shop", "โšก"), - "shop/electronics": ("Electronics Shop", "๐Ÿ“ฑ"), - "shop/erotic": ("Adult Shop", "๐Ÿ”ž"), - "shop/esoteric": ("Esoteric Shop", "๐Ÿ”ฎ"), - "shop/estate_agent": ("Estate Agent", "๐Ÿ "), - "shop/fabric": ("Fabric Shop", "๐Ÿงต"), - "shop/fan": ("Fan Shop", "๐Ÿ…"), - "shop/farm": ("Farm Shop", "๐Ÿฅ•"), - "shop/fashion_accessories": ("Fashion Accessories", "๐Ÿ‘’"), - "shop/fireplace": ("Fireplace Shop", "๐Ÿ”ฅ"), - "shop/fishing": ("Fishing Shop", "๐ŸŽฃ"), - "shop/flooring": ("Flooring Shop", "๐Ÿชต"), - "shop/florist": ("Florist", "๐Ÿ’"), - "shop/food": ("Food Shop", "๐Ÿž"), - "shop/frame": ("Framing Shop", "๐Ÿ–ผ๏ธ"), - "shop/frozen_food": ("Frozen Food Shop", "๐ŸงŠ"), - "shop/fuel": ("Fuel Shop", "โ›ฝ"), - "shop/funeral_directors": ("Funeral Director", "โšฐ๏ธ"), - "shop/furniture": ("Furniture Shop", "๐Ÿช‘"), - "shop/games": ("Games Shop", "๐ŸŽฎ"), - "shop/garden_centre": ("Garden Centre", "๐ŸŒป"), - "shop/gas": ("Gas Shop", "๐Ÿ”ฅ"), - "shop/general": ("General Store", "๐Ÿช"), - "shop/gift": ("Gift Shop", "๐ŸŽ"), - "shop/glaziery": ("Glazier", "๐ŸชŸ"), - "shop/greengrocer": ("Greengrocer", "๐Ÿฅฌ"), - "shop/grocery": ("Grocery Shop", "๐Ÿ›’"), - "shop/haberdashery": ("Haberdashery", "๐Ÿงต"), - "shop/hairdresser": ("Hairdresser", "๐Ÿ’‡"), - "shop/hairdresser_supply": ("Hairdresser Supply", "๐Ÿ’‡"), - "shop/hardware": ("Hardware Shop", "๐Ÿ”ฉ"), - "shop/health": ("Health Shop", "๐ŸŒฟ"), - "shop/health_food": ("Health Food Shop", "๐Ÿฅ—"), - "shop/hearing_aids": ("Hearing Aid Shop", "๐Ÿ‘‚"), - "shop/herbalist": ("Herbalist", "๐ŸŒฟ"), - "shop/hifi": ("Hi-Fi Shop", "๐Ÿ”Š"), - "shop/household": ("Household Shop", "๐Ÿ "), - "shop/household_linen": ("Linen Shop", "๐Ÿ›๏ธ"), - "shop/houseware": ("Houseware Shop", "๐Ÿณ"), - "shop/ice_cream": ("Ice Cream Shop", "๐Ÿฆ"), - "shop/interior_decoration": ("Interior Decoration", "๐Ÿ–ผ๏ธ"), - "shop/jewelry": ("Jewellery Shop", "๐Ÿ’"), - "shop/kiosk": ("Kiosk", "๐Ÿช"), - "shop/kitchen": ("Kitchen Shop", "๐Ÿณ"), - "shop/laundry": ("Laundry", "๐Ÿงบ"), - "shop/leather": ("Leather Shop", "๐Ÿงณ"), - "shop/lighting": ("Lighting Shop", "๐Ÿ’ก"), - "shop/locksmith": ("Locksmith", "๐Ÿ”"), - "shop/mall": ("Shopping Centre", "๐Ÿฌ"), - "shop/massage": ("Massage Parlour", "๐Ÿ’†"), - "shop/medical_supply": ("Medical Supply", "๐Ÿฉบ"), - "shop/military_surplus": ("Military Surplus", "๐ŸŽ–๏ธ"), - "shop/mobile_phone": ("Mobile Phone Shop", "๐Ÿ“ฑ"), - "shop/mobile_phone_accessories": ("Phone Accessories", "๐Ÿ“ฑ"), - "shop/mobility": ("Mobility Shop", "โ™ฟ"), - "shop/mobility_scooter": ("Mobility Scooter Shop", "๐Ÿฆฝ"), - "shop/model": ("Model Shop", "โœˆ๏ธ"), - "shop/money_lender": ("Money Lender", "๐Ÿ’ฐ"), - "shop/motorcycle": ("Motorcycle Shop", "๐Ÿ๏ธ"), - "shop/motorcycle_repair": ("Motorcycle Repair", "๐Ÿ”ง"), - "shop/music": ("Music Shop", "๐ŸŽต"), - "shop/musical_instrument": ("Musical Instrument Shop", "๐ŸŽธ"), - "shop/newsagent": ("Newsagent", "๐Ÿ“ฐ"), - "shop/nutrition_supplements": ("Nutrition Shop", "๐Ÿ’ช"), - "shop/optician": ("Optician", "๐Ÿ‘“"), - "shop/outdoor": ("Outdoor Shop", "๐Ÿ•๏ธ"), - "shop/outpost": ("Outpost", "๐Ÿ“ฆ"), - "shop/paint": ("Paint Shop", "๐ŸŽจ"), - "shop/party": ("Party Shop", "๐ŸŽˆ"), - "shop/pastry": ("Pastry Shop", "๐Ÿฅ"), - "shop/pawnbroker": ("Pawnbroker", "๐Ÿ’ฐ"), - "shop/perfumery": ("Perfumery", "๐ŸŒธ"), - "shop/pet": ("Pet Shop", "๐Ÿพ"), - "shop/pet_grooming": ("Pet Grooming", "๐Ÿฉ"), - "shop/photo": ("Photo Shop", "๐Ÿ“ธ"), - "shop/piercing": ("Piercing Studio", "๐Ÿ’Ž"), - "shop/plant_hire": ("Plant Hire", "๐Ÿšœ"), - "shop/pottery": ("Pottery Shop", "๐Ÿบ"), - "shop/printer_ink": ("Ink & Toner Shop", "๐Ÿ–จ๏ธ"), - "shop/printing": ("Print Shop", "๐Ÿ–จ๏ธ"), - "shop/psychic": ("Psychic", "๐Ÿ”ฎ"), - "shop/pyrotechnics": ("Fireworks Shop", "๐ŸŽ†"), - "shop/religion": ("Religious Shop", "โœ๏ธ"), - "shop/rental": ("Rental Shop", "๐Ÿ”‘"), - "shop/repair": ("Repair Shop", "๐Ÿ”ง"), - "shop/scuba_diving": ("Scuba Diving Shop", "๐Ÿคฟ"), - "shop/seafood": ("Fishmonger", "๐ŸŸ"), - "shop/second_hand": ("Second-Hand Shop", "โ™ป๏ธ"), - "shop/security": ("Security Shop", "๐Ÿ”’"), - "shop/sewing": ("Sewing Shop", "๐Ÿชก"), - "shop/shoe_repair": ("Shoe Repair", "๐Ÿ‘ž"), - "shop/shoes": ("Shoe Shop", "๐Ÿ‘Ÿ"), - "shop/sports": ("Sports Shop", "โšฝ"), - "shop/stationery": ("Stationery Shop", "โœ๏ธ"), - "shop/storage_rental": ("Self Storage", "๐Ÿ“ฆ"), - "shop/supermarket": ("Supermarket", "๐Ÿ›’"), - "shop/swimming_pool": ("Pool Supplies", "๐ŸŠ"), - "shop/tailor": ("Tailor", "๐Ÿงต"), - "shop/tattoo": ("Tattoo Studio", "๐Ÿ–‹๏ธ"), - "shop/taxi": ("Taxi Booking", "๐Ÿš•"), - "shop/tea": ("Tea Shop", "๐Ÿซ–"), - "shop/telecommunication": ("Telecoms Shop", "๐Ÿ“ก"), - "shop/ticket": ("Ticket Office", "๐ŸŽซ"), - "shop/tiles": ("Tile Shop", "๐Ÿ”ฒ"), - "shop/tobacco": ("Tobacconist", "๐Ÿšฌ"), - "shop/tool_hire": ("Tool Hire", "๐Ÿงฐ"), - "shop/toys": ("Toy Shop", "๐Ÿงธ"), - "shop/trade": ("Trade Supplier", "๐Ÿญ"), - "shop/travel_agency": ("Travel Agency", "โœˆ๏ธ"), - "shop/trophy": ("Trophy Shop", "๐Ÿ†"), - "shop/tyres": ("Tyre Shop", "๐Ÿ›ž"), - "shop/vacant": ("Vacant Shop", "๐Ÿš๏ธ"), - "shop/variety_store": ("Variety Store", "๐Ÿช"), - "shop/video": ("Video Shop", "๐Ÿ“€"), - "shop/video_games": ("Video Game Shop", "๐ŸŽฎ"), - "shop/watches": ("Watch Shop", "โŒš"), - "shop/water_sports": ("Water Sports Shop", "๐Ÿ„"), - "shop/weapons": ("Weapons Shop", "๐Ÿ—ก๏ธ"), - "shop/wedding": ("Wedding Shop", "๐Ÿ’’"), - "shop/wholesale": ("Wholesaler", "๐Ÿ“ฆ"), - "shop/wigs": ("Wig Shop", "๐Ÿ’‡"), - "shop/window_blind": ("Blinds Shop", "๐ŸชŸ"), - "shop/windows": ("Window Shop", "๐ŸชŸ"), - "shop/wine": ("Wine Shop", "๐Ÿท"), - "shop/wool": ("Wool Shop", "๐Ÿงถ"), - "shop/yes": ("Shop", "๐Ÿ›๏ธ"), - # tourism - "tourism/artwork": ("Public Artwork", "๐ŸŽจ"), - "tourism/attraction": ("Tourist Attraction", "๐Ÿ“ธ"), - "tourism/camp_site": ("Campsite", "โ›บ"), - "tourism/caravan_site": ("Caravan Site", "๐Ÿš"), - "tourism/chalet": ("Chalet", "๐Ÿ”๏ธ"), - "tourism/gallery": ("Gallery", "๐Ÿ–ผ๏ธ"), - "tourism/guest_house": ("Guest House", "๐Ÿก"), - "tourism/hostel": ("Hostel", "๐Ÿ›๏ธ"), - "tourism/hotel": ("Hotel", "๐Ÿจ"), - "tourism/motel": ("Motel", "๐Ÿจ"), - "tourism/museum": ("Museum", "๐Ÿ›๏ธ"), - "tourism/picnic_site": ("Picnic Site", "๐Ÿงบ"), - "tourism/preserved_railway": ("Heritage Railway", "๐Ÿš‚"), - "tourism/theme_park": ("Theme Park", "๐ŸŽข"), - "tourism/viewpoint": ("Viewpoint", "๐Ÿ”ญ"), - "tourism/zoo": ("Zoo", "๐Ÿฆ"), + +# Each output category defined once: (group, friendly_name, emoji, [osm_keys...]) +# The flat CATEGORY_MAP lookup dict is built from this at the bottom. +_CATEGORIES: list[tuple[str, str, str, list[str]]] = [ + ( + "Leisure", + "Cafรฉ", + "โ˜•", + [ + "amenity/cafe", + "amenity/ice_cream", + "amenity/internet_cafe", + ], + ), + ( + "Leisure", + "Restaurant", + "๐Ÿฝ๏ธ", + [ + "amenity/restaurant", + "amenity/food_court", + ], + ), + ( + "Leisure", + "Pub", + "๐Ÿบ", + [ + "amenity/pub", + "amenity/social_club", + "amenity/club", + "leisure/social_club", + "craft/brewery", + "craft/distillery", + "craft/winery", + ], + ), + ( + "Leisure", + "Bar", + "๐Ÿธ", + [ + "amenity/bar", + "amenity/hookah_lounge", + ], + ), + ( + "Leisure", + "Fast Food", + "๐Ÿ”", + [ + "amenity/fast_food", + ], + ), + ( + "Leisure", + "Nightclub", + "๐Ÿชฉ", + [ + "amenity/nightclub", + "amenity/stripclub", + "amenity/casino", + "amenity/gambling", + ], + ), + ( + "Leisure", + "Cinema", + "๐ŸŽฌ", + [ + "amenity/cinema", + ], + ), + ( + "Leisure", + "Theatre", + "๐ŸŽญ", + [ + "amenity/theatre", + ], + ), + ( + "Leisure", + "Live Music & Events", + "๐ŸŽถ", + [ + "amenity/music_venue", + "amenity/events_venue", + "leisure/dance", + ], + ), + ( + "Leisure", + "Park", + "๐ŸŒณ", + [ + "leisure/park", + "leisure/garden", + "leisure/common", + "leisure/nature_reserve", + "leisure/dog_park", + "leisure/bandstand", + "leisure/bird_hide", + "leisure/firepit", + "leisure/outdoor_seating", + "leisure/picnic_table", + "leisure/wildlife_hide", + ], + ), + ( + "Leisure", + "Playground", + "๐Ÿ›", + [ + "leisure/playground", + "leisure/indoor_play", + ], + ), + ( + "Leisure", + "Sports Centre", + "๐ŸŸ๏ธ", + [ + "leisure/sports_centre", + "leisure/sports_hall", + "leisure/pitch", + "leisure/track", + "leisure/golf_course", + "leisure/miniature_golf", + "leisure/horse_riding", + "leisure/fishing", + "leisure/swimming_pool", + "leisure/water_park", + "leisure/bathing_place", + ], + ), + ( + "Leisure", + "Entertainment", + "๐ŸŽณ", + [ + "leisure/bowling_alley", + "leisure/amusement_arcade", + "leisure/adult_gaming_centre", + "leisure/escape_game", + "leisure/trampoline_park", + "leisure/sauna", + "leisure/tanning_salon", + "tourism/theme_park", + "amenity/bicycle_rental", + "amenity/boat_rental", + "leisure/marina", + "leisure/slipway", + "leisure/hackerspace", + "leisure/yes", + ], + ), + ( + "Groceries", + "Supermarket", + "๐Ÿ›’", + [ + "shop/supermarket", + ], + ), + ( + "Groceries", + "Convenience Store", + "๐Ÿช", + [ + "shop/convenience", + "shop/general", + "shop/kiosk", + "shop/grocery", + ], + ), + ( + "Groceries", + "Bakery", + "๐Ÿฅ", + [ + "shop/bakery", + "shop/pastry", + "craft/confectionery", + ], + ), + ( + "Groceries", + "Butcher & Fishmonger", + "๐Ÿฅฉ", + [ + "shop/butcher", + "shop/seafood", + ], + ), + ( + "Groceries", + "Greengrocer", + "๐Ÿฅฌ", + [ + "shop/greengrocer", + "shop/farm", + "amenity/marketplace", + ], + ), + ( + "Groceries", + "Off-Licence", + "๐Ÿท", + [ + "shop/alcohol", + "shop/wine", + "shop/beverages", + ], + ), + ( + "Groceries", + "Deli & Specialty", + "๐Ÿง†", + [ + "shop/deli", + "shop/cheese", + "shop/chocolate", + "shop/coffee", + "shop/confectionery", + "shop/dairy", + "shop/food", + "shop/frozen_food", + "shop/health_food", + "shop/ice_cream", + "shop/nutrition_supplements", + "shop/tea", + ], + ), + ( + "Shops", + "Fashion & Clothing", + "๐Ÿ‘•", + [ + "shop/clothes", + "shop/boutique", + "shop/shoes", + "shop/accessories", + "shop/bag", + "shop/fashion_accessories", + "shop/jewelry", + "shop/leather", + "shop/watches", + ], + ), + ( + "Shops", + "Electronics", + "๐Ÿ“ฑ", + [ + "shop/electronics", + "shop/mobile_phone", + "shop/mobile_phone_accessories", + "shop/computer", + "shop/appliance", + "shop/electrical", + "shop/hifi", + "shop/video_games", + "shop/games", + ], + ), + ( + "Shops", + "Charity Shop", + "โค๏ธ", + [ + "shop/charity", + "shop/second_hand", + ], + ), + ( + "Shops", + "DIY & Hardware", + "๐Ÿ”จ", + [ + "shop/doityourself", + "shop/hardware", + "shop/paint", + ], + ), + ( + "Shops", + "Home & Garden", + "๐Ÿช‘", + [ + "shop/furniture", + "shop/garden_centre", + "shop/kitchen", + "shop/bathroom", + "shop/bathroom_furnishing", + "shop/bed", + "shop/carpet", + "shop/curtain", + "shop/flooring", + "shop/fireplace", + "shop/household", + "shop/household_linen", + "shop/houseware", + "shop/interior_decoration", + "shop/lighting", + "shop/window_blind", + ], + ), + ( + "Shops", + "Bookshop", + "๐Ÿ“š", + [ + "shop/books", + "shop/stationery", + ], + ), + ( + "Shops", + "Pet Shop", + "๐Ÿพ", + [ + "shop/pet", + ], + ), + ( + "Shops", + "Sports & Outdoor", + "๐Ÿ•๏ธ", + [ + "shop/sports", + "shop/outdoor", + "shop/bicycle", + ], + ), + ( + "Shops", + "Newsagent", + "๐Ÿ“ฐ", + [ + "shop/newsagent", + "shop/tobacco", + ], + ), + ( + "Shops", + "Department Store", + "๐Ÿฌ", + [ + "shop/department_store", + "shop/mall", + "shop/variety_store", + "shop/discount", + ], + ), + ( + "Shops", + "Gift & Hobby", + "๐ŸŽ", + [ + "shop/gift", + "shop/florist", + "shop/toys", + "shop/craft", + "shop/candles", + "shop/party", + "shop/art", + "shop/music", + "shop/musical_instrument", + "shop/antiques", + "shop/baby_goods", + "shop/fabric", + "shop/haberdashery", + "shop/wool", + "shop/pottery", + ], + ), + ( + "Shops", + "Specialist Shop", + "๐Ÿช", + [ + "shop/agrarian", + "shop/boat", + "shop/bookmaker", + "shop/building_materials", + "shop/camera", + "shop/car", + "shop/caravan", + "shop/catalogue", + "shop/collector", + "shop/copyshop", + "shop/country_store", + "shop/doors", + "shop/e-cigarette", + "shop/erotic", + "shop/esoteric", + "shop/fan", + "shop/fishing", + "shop/frame", + "shop/fuel", + "shop/gas", + "shop/hairdresser_supply", + "shop/military_surplus", + "shop/model", + "shop/money_lender", + "shop/motorcycle", + "shop/outpost", + "shop/pawnbroker", + "shop/photo", + "shop/plant_hire", + "shop/printer_ink", + "shop/printing", + "shop/psychic", + "shop/pyrotechnics", + "shop/religion", + "shop/rental", + "shop/scuba_diving", + "shop/security", + "shop/sewing", + "shop/storage_rental", + "shop/swimming_pool", + "shop/telecommunication", + "shop/ticket", + "shop/tiles", + "shop/tool_hire", + "shop/trade", + "shop/trophy", + "shop/vacant", + "shop/video", + "shop/water_sports", + "shop/weapons", + "shop/wedding", + "shop/wholesale", + "shop/wigs", + "shop/yes", + ], + ), + # โ”€โ”€ Services โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ + ( + "Services", + "Hairdresser & Beauty", + "๐Ÿ’‡", + [ + "shop/hairdresser", + "shop/beauty", + "shop/cosmetics", + "shop/massage", + "shop/perfumery", + ], + ), + ( + "Services", + "Gym & Fitness", + "๐Ÿ‹๏ธ", + [ + "leisure/fitness_centre", + "leisure/fitness_station", + "amenity/dojo", + "amenity/dancing_school", + ], + ), + ( + "Services", + "Dry Cleaner & Laundry", + "๐Ÿ‘”", + [ + "shop/dry_cleaning", + "shop/laundry", + "shop/tailor", + "shop/shoe_repair", + "shop/repair", + "craft/cleaning", + "craft/dressmaker", + "craft/shoemaker", + "craft/tailor", + ], + ), + ( + "Services", + "Car Services", + "๐Ÿ”ง", + [ + "shop/car_repair", + "shop/car;car_repair", + "shop/car_parts", + "shop/motorcycle_repair", + "shop/tyres", + "amenity/car_wash", + "amenity/car_rental", + "amenity/car_sharing", + "amenity/bicycle_repair_station", + ], + ), + ( + "Services", + "Post Office", + "๐Ÿค", + [ + "amenity/post_office", + ], + ), + ( + "Services", + "Vet & Pet Care", + "๐Ÿ•", + [ + "amenity/veterinary", + "shop/pet_grooming", + ], + ), + ( + "Services", + "Bank", + "๐Ÿฆ", + [ + "amenity/bank", + ], + ), + ( + "Services", + "Travel Agent", + "โœˆ๏ธ", + [ + "shop/travel_agency", + "office/travel_agent", + ], + ), + ( + "Services", + "Other", + "๐Ÿ›Ž๏ธ", + [ + "shop/tattoo", + "shop/piercing", + "shop/locksmith", + "craft/key_cutter", + ], + ), + ( + "Emergency Services", + "Police", + "๐Ÿ‘ฎ", + ["amenity/police"], + ), + ( + "Emergency Services", + "Fire Station", + "๐Ÿš’", + ["amenity/fire_station"], + ), + ( + "Emergency Services", + "Ambulance Station", + "๐Ÿš‘", + ["emergency/ambulance_station"], + ), + ( + "Health", + "GP Surgery", + "๐Ÿ‘จโ€โš•๏ธ", + [ + "amenity/doctors", + "healthcare/doctor", + ], + ), + ( + "Health", + "Dentist", + "๐Ÿฆท", + [ + "amenity/dentist", + "healthcare/dentist", + ], + ), + ( + "Health", + "Pharmacy", + "๐Ÿ’Š", + [ + "amenity/pharmacy", + "healthcare/pharmacy", + "shop/chemist", + "shop/herbalist", + "shop/health", + "healthcare/alternative", + ], + ), + ( + "Health", + "Hospital & Clinic", + "๐Ÿฅ", + [ + "amenity/hospital", + "amenity/clinic", + "healthcare/hospital", + "healthcare/centre", + "healthcare/clinic", + "office/healthcare", + "healthcare/laboratory", + "healthcare/rehabilitation", + "healthcare/vaccination_centre", + "healthcare/yes", + ], + ), + ( + "Health", + "Optician", + "๐Ÿ‘“", + [ + "shop/optician", + "healthcare/optometrist", + "shop/hearing_aids", + "healthcare/audiologist", + ], + ), + ( + "Health", + "Physiotherapy", + "๐Ÿƒ", + [ + "healthcare/physiotherapist", + "healthcare/podiatrist", + ], + ), + ( + "Health", + "Counselling & Therapy", + "๐Ÿง ", + [ + "healthcare/counselling", + "healthcare/psychotherapist", + "office/therapist", + ], + ), + ( + "Health", + "Care Home", + "๐Ÿ ", + [ + "amenity/care_home", + "amenity/nursing_home", + "office/home_care", + ], + ), + ( + "Health", + "Medical & Mobility", + "โ™ฟ", + [ + "shop/medical_supply", + "shop/mobility", + "shop/mobility_scooter", + ], + ), + ( + "Culture", + "Museum", + "๐Ÿ›๏ธ", + [ + "tourism/museum", + ], + ), + ( + "Culture", + "Gallery", + "๐Ÿ–ผ๏ธ", + [ + "tourism/gallery", + "tourism/artwork", + ], + ), + ( + "Culture", + "Library", + "๐Ÿ“š", + [ + "amenity/library", + ], + ), + ( + "Culture", + "Place of Worship", + "โ›ช", + [ + "amenity/place_of_worship", + "building/church", + ], + ), + ( + "Culture", + "Arts Centre", + "๐ŸŽจ", + [ + "amenity/arts_centre", + ], + ), + ( + "Culture", + "Zoo", + "๐Ÿฆ", + [ + "tourism/zoo", + ], + ), + ( + "Culture", + "Tourist Attraction", + "๐Ÿ“ธ", + [ + "tourism/attraction", + "amenity/fountain", + "amenity/courthouse", + "tourism/chalet", + ], + ), + ( + "Education", + "School", + "๐Ÿซ", + [ + "amenity/school", + "amenity/prep_school", + "amenity/language_school", + "amenity/music_school", + "amenity/university", + "amenity/college", + "building/university", + "amenity/kindergarten", + "amenity/childcare", + ], + ), + ( + "Local Businesses", + "Hotel", + "๐Ÿจ", + [ + "tourism/hotel", + "tourism/hostel", + "tourism/guest_house", + "tourism/motel", + "tourism/camp_site", + ], + ), + ( + "Local Businesses", + "Local Business", + "๐Ÿ› ๏ธ", + [ + # Tradespeople + "craft/builder", + "craft/carpenter", + "craft/electrician", + "craft/electronics_repair", + "craft/floorer", + "craft/gardener", + "craft/glaziery", + "craft/hvac", + "craft/joiner", + "craft/locksmith", + "craft/painter", + "craft/plumber", + "craft/roofer", + "craft/window_construction", + "craft/agricultural_engines", + "craft/atelier", + "craft/blacksmith", + "craft/bookbinder", + "craft/caterer", + "craft/handicraft", + "craft/jeweller", + "craft/metal_construction", + "craft/photographer", + "craft/photographic_laboratory", + "craft/pottery", + "craft/printer", + "craft/sawmill", + "craft/scaffolder", + "craft/sculptor", + "craft/signmaker", + "craft/stonemason", + "craft/upholsterer", + "craft/watchmaker", + "craft/yes", + "shop/glaziery", + "shop/windows", + # Professional offices & estate agents + "shop/estate_agent", + "office/accountant", + "office/architect", + "office/construction_company", + "office/engineer", + "office/estate_agent", + "office/financial", + "office/financial_advisor", + "office/insurance", + "office/lawyer", + "office/mortgage", + "office/property_management", + "office/solicitor", + "office/surveyor", + "office/tax_advisor", + ], + ), + ( + "Local Businesses", + "Offices", + "๐Ÿข", + [ + "amenity/coworking_space", + "office/advertising_agency", + "office/association", + "office/charity", + "office/company", + "office/consulting", + "office/courier", + "office/coworking", + "office/design", + "office/diplomatic", + "office/educational_institution", + "office/employment_agency", + "office/energy_supplier", + "office/foundation", + "office/government", + "office/graphic_design", + "office/interior_design", + "office/it", + "office/logistics", + "office/marketing", + "office/moving_company", + "office/newspaper", + "office/ngo", + "office/notary", + "office/political_party", + "office/politician", + "office/recruitment", + "office/religion", + "office/research", + "office/security", + "office/taxi", + "office/telecommunication", + "office/union", + "office/university", + "office/vacant", + "office/web_design", + "office/yes", + ], + ), + # โ”€โ”€ Other โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ + ( + "Other", + "EV Charging", + "๐Ÿ”Œ", + [ + "amenity/charging_station", + ], + ), + ( + "Other", + "Fuel Station", + "โ›ฝ", + [ + "amenity/fuel", + ], + ), + ( + "Other", + "Community Centre", + "๐Ÿค", + [ + "amenity/community_centre", + "amenity/social_centre", + "amenity/townhall", + ], + ), +] + +# Build flat lookup: OSM category โ†’ (group, friendly_name, emoji) +CATEGORY_MAP: dict[str, tuple[str, str, str]] = { + osm_key: (group, name, emoji) + for group, name, emoji, osm_keys in _CATEGORIES + for osm_key in osm_keys } @@ -588,7 +1059,9 @@ def transform(input_path: Path, naptan_path: Path | None = None) -> pl.LazyFrame lf = pl.scan_parquet(input_path) # Get all unique categories present in the data - all_categories = lf.select("category").unique().collect(engine="streaming").to_series().to_list() + all_categories = ( + lf.select("category").unique().collect(engine="streaming").to_series().to_list() + ) # Verify every non-dropped category has a mapping unmapped = [] @@ -612,23 +1085,19 @@ def transform(input_path: Path, naptan_path: Path | None = None) -> pl.LazyFrame # Drop unwanted categories lf = lf.filter(~pl.col("category").is_in(list(DROP_CATEGORIES))) - # Build name and emoji lookup expressions - name_mapping = {k: v[0] for k, v in CATEGORY_MAP.items()} - emoji_mapping = {k: v[1] for k, v in CATEGORY_MAP.items()} + # Build lookup expressions from the 3-tuple mapping + group_mapping = {k: v[0] for k, v in CATEGORY_MAP.items()} + name_mapping = {k: v[1] for k, v in CATEGORY_MAP.items()} + emoji_mapping = {k: v[2] for k, v in CATEGORY_MAP.items()} - # Check no friendly names are missing (defensive) - missing_names = [k for k, v in CATEGORY_MAP.items() if not v[0]] + # Check no friendly names or emojis are empty (defensive) + missing_names = [k for k, v in CATEGORY_MAP.items() if not v[1]] if missing_names: raise ValueError(f"Empty friendly names for: {missing_names}") - missing_emojis = [k for k, v in CATEGORY_MAP.items() if not v[1]] + missing_emojis = [k for k, v in CATEGORY_MAP.items() if not v[2]] if missing_emojis: raise ValueError(f"Empty emojis for: {missing_emojis}") - # Derive group from the first component of the raw category key, title-cased - group_mapping = { - k: k.split("/")[0].replace("_", " ").title() for k in CATEGORY_MAP - } - lf = lf.with_columns( pl.col("category").replace_strict(group_mapping).alias("group"), pl.col("category").replace_strict(name_mapping).alias("category"), @@ -664,9 +1133,11 @@ def main(): size_mb = args.output.stat().st_size / (1024 * 1024) print(f"Wrote {args.output} ({size_mb:.1f} MB, {len(df):,} POIs)") print(f"\nCategories ({df['category'].n_unique()}):") - counts = df.group_by("category", "emoji").len().sort("len", descending=True) + counts = ( + df.group_by("group", "category", "emoji").len().sort("len", descending=True) + ) for row in counts.iter_rows(named=True): - print(f" {row['emoji']} {row['category']}: {row['len']:,}") + print(f" [{row['group']}] {row['emoji']} {row['category']}: {row['len']:,}") if __name__ == "__main__":