v0.68.0: re-curate special remote airports — one per ~1000 km region (ISS-144)
CI / build + unit + e2e (pull_request) Successful in 13m18s
CI / build + unit + e2e (pull_request) Successful in 13m18s
Greedy sparse selection replaces the blanket 1000km-from-large filter that over-filled central Australia / Canada edges with dozens of tiny strips: candidates sorted by scheduled service, type rank (medium < small < seaplane), numeric id; accepted only if >= REMOTE_RADIUS_KM from every already-accepted special. CSV: 1483 -> 1161 rows (1119 large unchanged, specials 364 -> 42). New unit test pins the pairwise-sparsity invariant on the committed dataset.
This commit is contained in:
@@ -2,6 +2,7 @@ import { promises as fs } from 'node:fs';
|
||||
import path from 'node:path';
|
||||
import { describe, expect, it } from 'vitest';
|
||||
import { assertUniqueIcaos, filterWorldAirports, isRemote, parseCsv, toGeoJson, airportsHandler, REMOTE_RADIUS_KM } from './airports';
|
||||
import { haversineKm } from './geo';
|
||||
|
||||
const HEADER =
|
||||
'"id","ident","type","name","latitude_deg","longitude_deg","elevation_ft","continent","iso_country","iso_region","municipality","scheduled_service","icao_code","iata_code","gps_code","local_code","home_link","wikipedia_link","keywords"';
|
||||
@@ -191,4 +192,20 @@ describe('isRemote (v0.61.0 — ISS-097 special remote airports)', () => {
|
||||
expect(isRemote([...large, self], self.icao), `${self.icao} (${r.name}) must be remote`).toBe(true);
|
||||
}
|
||||
});
|
||||
|
||||
it('committed dataset sparsity rule: every pair of non-large rows is at least REMOTE_RADIUS_KM apart', async () => {
|
||||
const text = await fs.readFile(path.join(process.cwd(), 'data', 'airports_world.csv'), 'utf8');
|
||||
const rows = filterWorldAirports(parseCsv(text));
|
||||
// v0.68.0 (ISS-144): specials are greedily thinned to one per ~REMOTE_RADIUS_KM region, so no
|
||||
// two non-large rows may sit closer than the radius. n≈dozens makes O(n²) trivial.
|
||||
const nonLarge = rows.filter((r) => r.type !== 'large_airport').map((r) => ({ icao: r.icao_code || r.ident, lat: +r.latitude_deg, lon: +r.longitude_deg }));
|
||||
expect(nonLarge.length).toBeGreaterThan(0);
|
||||
|
||||
for (let i = 0; i < nonLarge.length; i++) {
|
||||
for (let j = i + 1; j < nonLarge.length; j++) {
|
||||
const d = haversineKm(nonLarge[i].lat, nonLarge[i].lon, nonLarge[j].lat, nonLarge[j].lon);
|
||||
expect(d, `${nonLarge[i].icao} ↔ ${nonLarge[j].icao}: ${d.toFixed(1)} km < ${REMOTE_RADIUS_KM}`).toBeGreaterThanOrEqual(REMOTE_RADIUS_KM);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user