/** * The kinds of place read from OpenStreetMap for the Backpacker Map * (scripts/build-backpacker-places.mjs), and what each is called. * * Kept free of app imports so the build script and the node test runner can * load it. Each kind lands in one of the map's five buckets; a kind with no * bucket here is not drawn. */ export type OsmBucket = 'Stay' | 'Food' | 'Water' | 'Transport' | 'Wi-Fi'; /** One place as stored: latitude, longitude, name ('' when it has none), kind code. */ export type OsmRow = readonly [number, number, string, string]; export type OsmKind = Readonly<{ code: string; bucket: OsmBucket; /** Overpass selectors that find it. */ selectors: readonly string[]; /** How many a country keeps, best first. */ keep: number; /** * What a place must show to be worth a pin (osm-score.ts): a web page, a * phone, opening hours, a Wikipedia or Wikidata entry. A place nobody has * described is a dot on a map, not somewhere to go. */ minScore: number; /** How many are read before the best are chosen. */ read: number; /** A place with no name is no use on a map: only kinds that are found by what they are keep nameless ones. */ needsName: boolean; label: Readonly<{ en: string; tr: string; es: string }>; }>; export const OSM_KINDS: readonly OsmKind[] = [ { code: 'hostel', bucket: 'Stay', selectors: ['["tourism"="hostel"]'], keep: 40, minScore: 2, read: 1500, needsName: true, label: { en: 'Hostel', tr: 'Hostel', es: 'Hostal' } }, { code: 'guesthouse', bucket: 'Stay', selectors: ['["tourism"="guest_house"]'], keep: 25, minScore: 3, read: 1500, needsName: true, label: { en: 'Guesthouse', tr: 'Pansiyon', es: 'Casa de huéspedes' } }, { code: 'camp', bucket: 'Stay', selectors: ['["tourism"="camp_site"]'], keep: 25, minScore: 2, read: 1500, needsName: true, label: { en: 'Campsite', tr: 'Kamp alanı', es: 'Camping' } }, { code: 'water', bucket: 'Water', selectors: ['["amenity"="drinking_water"]'], keep: 15, minScore: 2, read: 2500, needsName: false, label: { en: 'Drinking water', tr: 'İçme suyu', es: 'Agua potable' } }, { code: 'bus', bucket: 'Transport', selectors: ['["amenity"="bus_station"]'], keep: 20, minScore: 2, read: 1500, needsName: true, label: { en: 'Bus station', tr: 'Otogar', es: 'Estación de autobuses' } }, { code: 'train', bucket: 'Transport', selectors: ['["railway"="station"]["train"!="no"]'], keep: 20, minScore: 2, read: 2000, needsName: true, label: { en: 'Train station', tr: 'Tren istasyonu', es: 'Estación de tren' } }, { code: 'ferry', bucket: 'Transport', selectors: ['["amenity"="ferry_terminal"]'], keep: 15, minScore: 1, read: 800, needsName: true, label: { en: 'Ferry terminal', tr: 'Feribot iskelesi', es: 'Terminal de ferris' } }, { code: 'border', bucket: 'Transport', selectors: ['["barrier"="border_control"]'], keep: 20, minScore: 1, read: 600, needsName: false, label: { en: 'Border crossing', tr: 'Sınır kapısı', es: 'Paso fronterizo' } }, { code: 'market', bucket: 'Food', selectors: ['["amenity"="marketplace"]'], keep: 20, minScore: 2, read: 1500, needsName: true, label: { en: 'Market', tr: 'Pazar', es: 'Mercado' } }, { code: 'wifi', bucket: 'Wi-Fi', selectors: ['["internet_access"="wlan"]["internet_access:fee"="no"]["amenity"]'], keep: 15, minScore: 3, read: 1500, needsName: true, label: { en: 'Free Wi-Fi', tr: 'Ücretsiz Wi-Fi', es: 'Wi-Fi gratis' } }, ]; /** * The kinds worth showing: what a general map is poor at for someone on the * road - somewhere to fill a bottle, where a border can be crossed, where to * pitch a tent, where a ferry leaves from. A hostel or a market is better told * by travelers' own pins, with their photographs and their word that it is * still there; OpenStreetMap's say nothing a map app does not. */ export const OSM_PRACTICAL_KINDS: ReadonlySet = new Set(['water', 'border', 'camp', 'ferry']); export const OSM_KIND_BY_CODE: ReadonlyMap = new Map(OSM_KINDS.map((kind) => [kind.code, kind]));