fix: adjust category assignments, fix retries

This commit is contained in:
Jan-Henrik 2026-03-06 12:55:31 +01:00
parent 43d0dac789
commit fe6e59f427
6 changed files with 23 additions and 17 deletions

View file

@ -195,6 +195,7 @@ interface NominatimResult {
lon: string; lon: string;
type: string; type: string;
class: string; class: string;
place_rank: number;
geojson?: { type: string; coordinates: unknown }; geojson?: { type: string; coordinates: unknown };
} }
@ -232,13 +233,16 @@ function LocationSelector({
setSearching(true); setSearching(true);
try { try {
const res = await fetch( const res = await fetch(
`https://nominatim.openstreetmap.org/search?q=${encodeURIComponent(query)}&polygon_geojson=1&featuretype=settlement&format=json&limit=8`, `https://nominatim.openstreetmap.org/search?q=${encodeURIComponent(query)}&polygon_geojson=1&format=json&limit=8`,
{ headers: { "User-Agent": "Transportationer/1.0 (15-minute city analyzer)" } }, { headers: { "User-Agent": "Transportationer/1.0 (15-minute city analyzer)" } },
); );
const data: NominatimResult[] = await res.json(); const data: NominatimResult[] = await res.json();
// Keep only results that have a real polygon boundary // Keep only results with a real polygon and place_rank >= 13.
// Landkreise/counties are rank 12; cities/towns/municipalities are 13+.
const polygons = data.filter( const polygons = data.filter(
(r) => r.geojson?.type === "Polygon" || r.geojson?.type === "MultiPolygon", (r) =>
r.place_rank >= 12 &&
(r.geojson?.type === "Polygon" || r.geojson?.type === "MultiPolygon"),
); );
setResults(polygons); setResults(polygons);
setShowDropdown(true); setShowDropdown(true);

View file

@ -36,8 +36,10 @@ local tag_map = {
bicycle_rental = { 'transport', 'bike_share' }, bicycle_rental = { 'transport', 'bike_share' },
car_sharing = { 'transport', 'car_share' }, car_sharing = { 'transport', 'car_share' },
ferry_terminal = { 'transport', 'ferry' }, ferry_terminal = { 'transport', 'ferry' },
bus_station = { 'transport', 'bus_stop' },
-- work_school -- work_school
kindergarten = { 'work_school', 'kindergarten' }, kindergarten = { 'work_school', 'kindergarten' },
childcare = { 'work_school', 'kindergarten' },
school = { 'work_school', 'school' }, school = { 'work_school', 'school' },
university = { 'work_school', 'university' }, university = { 'work_school', 'university' },
college = { 'work_school', 'university' }, college = { 'work_school', 'university' },
@ -59,6 +61,7 @@ local tag_map = {
}, },
shop = { shop = {
supermarket = { 'service_trade', 'supermarket' }, supermarket = { 'service_trade', 'supermarket' },
wholesale = { 'service_trade', 'supermarket' },
convenience = { 'service_trade', 'convenience' }, convenience = { 'service_trade', 'convenience' },
bakery = { 'service_trade', 'cafe' }, bakery = { 'service_trade', 'cafe' },
pharmacy = { 'service_trade', 'pharmacy' }, pharmacy = { 'service_trade', 'pharmacy' },
@ -66,6 +69,8 @@ local tag_map = {
dry_cleaning = { 'service_trade', 'laundry' }, dry_cleaning = { 'service_trade', 'laundry' },
greengrocer = { 'service_trade', 'market' }, greengrocer = { 'service_trade', 'market' },
butcher = { 'service_trade', 'market' }, butcher = { 'service_trade', 'market' },
department_store= { 'service_trade', 'market' },
mall = { 'service_trade', 'market' },
}, },
highway = { highway = {
bus_stop = { 'transport', 'bus_stop' }, bus_stop = { 'transport', 'bus_stop' },
@ -75,14 +80,13 @@ local tag_map = {
halt = { 'transport', 'train_station' }, halt = { 'transport', 'train_station' },
tram_stop = { 'transport', 'tram_stop' }, tram_stop = { 'transport', 'tram_stop' },
subway_entrance = { 'transport', 'metro' }, subway_entrance = { 'transport', 'metro' },
subway_station = { 'transport', 'metro' },
}, },
-- public_transport stop_position/platform intentionally excluded: -- public_transport stop_position/platform intentionally excluded:
-- they duplicate highway=bus_stop / railway=tram_stop nodes at the same -- they duplicate highway=bus_stop / railway=tram_stop nodes at the same
-- physical location and would double-count those stops in scoring. -- physical location and would double-count those stops in scoring.
office = { office = {
coworking = { 'work_school', 'coworking' }, coworking = { 'work_school', 'coworking' },
company = { 'work_school', 'office' },
government = { 'work_school', 'office' },
}, },
tourism = { tourism = {
museum = { 'culture_community', 'museum' }, museum = { 'culture_community', 'museum' },
@ -99,8 +103,6 @@ local tag_map = {
arts_centre = { 'culture_community', 'community_center' }, arts_centre = { 'culture_community', 'community_center' },
}, },
landuse = { landuse = {
commercial = { 'work_school', 'office' },
office = { 'work_school', 'office' },
recreation_ground = { 'recreation', 'green_space' }, recreation_ground = { 'recreation', 'green_space' },
grass = { 'recreation', 'green_space' }, grass = { 'recreation', 'green_space' },
meadow = { 'recreation', 'green_space' }, meadow = { 'recreation', 'green_space' },

View file

@ -39,6 +39,7 @@ export const CATEGORIES: CategoryDefinition[] = [
key: "shop", key: "shop",
values: [ values: [
"supermarket", "supermarket",
"wholesale",
"convenience", "convenience",
"bakery", "bakery",
"pharmacy", "pharmacy",
@ -46,6 +47,8 @@ export const CATEGORIES: CategoryDefinition[] = [
"dry_cleaning", "dry_cleaning",
"greengrocer", "greengrocer",
"butcher", "butcher",
"department_store",
"mall",
], ],
}, },
{ {
@ -73,11 +76,11 @@ export const CATEGORIES: CategoryDefinition[] = [
{ key: "highway", values: ["bus_stop"] }, { key: "highway", values: ["bus_stop"] },
{ {
key: "railway", key: "railway",
values: ["station", "halt", "tram_stop", "subway_entrance"], values: ["station", "halt", "tram_stop", "subway_entrance", "subway_station"],
}, },
{ {
key: "amenity", key: "amenity",
values: ["bicycle_rental", "car_sharing", "ferry_terminal"], values: ["bicycle_rental", "car_sharing", "ferry_terminal", "bus_station"],
}, },
{ {
key: "public_transport", key: "public_transport",
@ -92,18 +95,18 @@ export const CATEGORIES: CategoryDefinition[] = [
defaultThresholdMinutes: 20, defaultThresholdMinutes: 20,
color: "#2a9d8f", color: "#2a9d8f",
tags: [ tags: [
{ key: "office", values: ["coworking", "company", "government"] }, { key: "office", values: ["coworking"] },
{ {
key: "amenity", key: "amenity",
values: [ values: [
"kindergarten", "kindergarten",
"childcare",
"school", "school",
"university", "university",
"college", "college",
"driving_school", "driving_school",
], ],
}, },
{ key: "landuse", values: ["commercial", "office"] },
], ],
}, },
{ {

View file

@ -59,7 +59,6 @@ export const UNIVERSAL_SUBCATEGORY_WEIGHTS: Record<string, number> = {
kindergarten: 0.75, // essential for young families kindergarten: 0.75, // essential for young families
university: 0.55, // higher education — relevant to students/young adults university: 0.55, // higher education — relevant to students/young adults
coworking: 0.55, // remote / flexible work coworking: 0.55, // remote / flexible work
office: 0.1, // landuse centroid — not a meaningful walkable destination
// ── culture_community ───────────────────────────────────────────────────── // ── culture_community ─────────────────────────────────────────────────────
hospital: 1.0, // critical healthcare hospital: 1.0, // critical healthcare
@ -132,7 +131,6 @@ export const PROFILES: Record<ProfileId, Profile> = {
gym: 0.5, gym: 0.5,
university: 0.2, university: 0.2,
coworking: 0.25, coworking: 0.25,
office: 0.05,
theatre: 0.3, theatre: 0.3,
museum: 0.35, museum: 0.35,
bar: 0.0, bar: 0.0,
@ -179,7 +177,6 @@ export const PROFILES: Record<ProfileId, Profile> = {
kindergarten: 0.05, kindergarten: 0.05,
university: 0.15, university: 0.15,
coworking: 0.05, coworking: 0.05,
office: 0.0,
playground: 0.3, playground: 0.3,
gym: 0.5, gym: 0.5,
swimming_pool: 0.5, swimming_pool: 0.5,
@ -222,7 +219,6 @@ export const PROFILES: Record<ProfileId, Profile> = {
kindergarten: 0.05, kindergarten: 0.05,
playground: 0.15, playground: 0.15,
university: 0.35, university: 0.35,
office: 0.05,
social_services: 0.4, social_services: 0.4,
}, },
}, },
@ -269,7 +265,6 @@ export const PROFILES: Record<ProfileId, Profile> = {
// not relevant // not relevant
school: 0.05, school: 0.05,
kindergarten: 0.05, kindergarten: 0.05,
office: 0.05,
playground: 0.2, playground: 0.2,
}, },
}, },

View file

@ -147,7 +147,8 @@ export const JOB_OPTIONS: Record<PipelineJobData["type"], object> = {
removeOnFail: { age: 86400 * 30 }, removeOnFail: { age: 86400 * 30 },
}, },
"build-valhalla": { "build-valhalla": {
attempts: 1, attempts: 3,
backoff: { type: "fixed", delay: 60_000 },
removeOnComplete: { age: 86400 * 7 }, removeOnComplete: { age: 86400 * 7 },
removeOnFail: { age: 86400 * 30 }, removeOnFail: { age: 86400 * 30 },
}, },

View file

@ -75,6 +75,7 @@ const worker = new Worker(
concurrency: 1, concurrency: 1,
lockDuration: 1_800_000, // 30 min — large-region tile builds can be very slow lockDuration: 1_800_000, // 30 min — large-region tile builds can be very slow
lockRenewTime: 60_000, lockRenewTime: 60_000,
maxStalledCount: 3,
}, },
); );