eatc-airlines
Version:
A command-line tool and API for retrieving scheduled and historical flight data and generating Endless ATC airline configurations.
423 lines • 55.9 kB
JavaScript
#!/usr/bin/env node
/*
* Copyright © 2025 Zefir Kirilov.
*
* This file is part of eatc-airlines.
*
* eatc-airlines is free software: you can redistribute it and/or modify it under the terms of the GNU
* General Public License as published by the Free Software Foundation, either version 3 of the License,
* or (at your option) any later version.
*
* eatc-airlines is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License along with eatc-airlines.
* If not, see <https://www.gnu.org/licenses/>.
*/
import path from "node:path";
import url from "node:url";
import fs from "node:fs/promises";
import { Command } from "commander";
import { Flight, Location, PHONETIC, NUMBERS } from "./api.js";
const PATH = path.dirname(url.fileURLToPath(import.meta.url));
const project = JSON.parse(await fs.readFile(path.join(PATH, "..", "package.json"), "utf-8"));
const program = new Command();
async function loadFlightsFromFs(file, _currentDepth = 0) {
const flights = [];
let stats;
try {
stats = await fs.stat(file);
}
catch (e) {
return program.error(`${file}: ${e instanceof Error ? e.message : "failed to stat"}`);
}
if (stats.isDirectory()) {
if (_currentDepth > 5)
return program.error(`${file}: maximum sub-directory depth reached`);
for (const dirent of await fs.readdir(file))
for (const flight of await loadFlightsFromFs(path.join(file, dirent), ++_currentDepth))
flights.push(flight);
return flights;
}
const contents = await fs.readFile(file, "utf-8");
let rawFlights;
try {
rawFlights = JSON.parse(contents);
}
catch (e) {
return program.error(`${file}: ${e instanceof Error ? e.message : "JSON.parse: failed to parse"}`);
}
for (const flight of rawFlights)
flights.push(new Flight(flight.id, new Date(flight.time), flight.tail, flight.type, flight.airline, flight.callsign, new Location(flight.to.name, flight.to.lat, flight.to.lon), new Location(flight.from.name, flight.from.lat, flight.from.lon)));
return flights;
}
const alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
const digits = "1234567890";
function tailToCallsign(prefix, sample) {
const countryPart = prefix.toUpperCase();
const localPart = sample.toUpperCase();
const indices = { letter: 0, number: 0 };
const localPartFormat = localPart.split("").map(char => {
if (/^\d$/.test(char))
return digits[(indices.number++) % digits.length];
else if (/^[A-Z]$/.test(char))
return alphabet[(indices.letter++) % alphabet.length];
return char;
}).join("");
return `${countryPart}-${localPartFormat}`;
}
program
.name(project.name)
.description(project.description.replace(/(.{1,80})(?=\s|$)/g, "$1\n").replace(/\n\s+/g, "\n"))
.version(project.version, "-v, --version", "Output the version number.")
.helpOption("-h, --help", "Display help for command.")
.helpCommand("help [command]", "Display help for command.");
async function get(icao, t) {
const url = new URL(icao, "https://www.airnavradar.com/data/airports/search/");
url.searchParams.set("key", "mrgapdstic");
url.searchParams.set("max", (t.getTime() / 1000).toFixed(0));
const res = await fetch(url);
if (!res.ok)
throw new Error(`API returned ${res.status} (${res.statusText}) for ${url}`);
const body = await res.text();
try {
const json = JSON.parse(body);
const more = json.hasEarlier;
let oldest = t;
const flights = [];
for (const flight of json.list) {
if (typeof flight.fid !== "number")
continue;
const id = flight.fid;
// actual, estimated, scheduled
if (typeof (flight.arrau ?? flight.arreu ?? flight.arrsu ?? flight.arrsts) !== "number")
continue;
const time = new Date((flight.arrau ?? flight.arreu ?? flight.arrsu ?? flight.arrsts) * 1000);
if (flight.acr !== null && typeof flight.acr !== "string")
continue;
const tail = flight.acr;
if (typeof flight.act !== "string" || flight.act === "GRND" || flight.act.toLowerCase() === "zzzz")
continue;
const type = flight.act;
if (((flight.csalic === undefined ? flight.alic : flight.csalic) ?? null) !== null
&& typeof (flight.csalic === undefined ? flight.alic : flight.csalic) !== "string")
continue;
const airline = ((flight.csalic === undefined ? flight.alic : flight.csalic) ?? null);
if ((flight.cs ?? flight.fnic ?? flight.ectlcs) !== null && typeof (flight.cs ?? flight.fnic ?? flight.ectlcs) !== "string")
continue;
const callsign = (flight.cs ?? flight.fnic ?? flight.ectlcs);
if (typeof flight.apdstic !== "string" || typeof flight.apdstla !== "number" || typeof flight.apdstlo !== "number")
continue;
const to = new Location(flight.apdstic, flight.apdstla, flight.apdstlo);
if (typeof flight.aporgic !== "string" || typeof flight.aporgla !== "number" || typeof flight.aporglo !== "number")
continue;
const from = new Location(flight.aporgic, flight.aporgla, flight.aporglo);
if (to.name === from.name)
continue;
flights.push(new Flight(id, time, tail, type, airline, callsign, to, from));
if (time < oldest)
oldest = time;
}
return { list: flights, more, oldest };
}
catch (e) {
return program.error(`${icao}: ${e instanceof Error ? e.message : "failed to parse"}`);
}
}
function timeAgo(date) {
const diff = Math.floor((Date.now() - date.getTime()) / 1000);
return `${Math.floor(diff / 3600) > 0 ? Math.floor(diff / 3600) + ":" : ""}${Math.floor(diff / 60)}:${(diff % 60).toString().padStart(2, "0")}`;
}
async function loadFlights(paths) {
const flights = new Map();
for (const path of paths) {
if (path === "-") {
const chunks = [];
process.stdin.on("data", chunk => chunks.push(chunk));
await Promise.race([
new Promise(resolve => process.stdin.once("end", () => resolve())),
new Promise(resolve => process.stdin.once("close", () => resolve())),
]);
const contents = Buffer.concat(chunks).toString("utf-8");
let rawFlights;
try {
rawFlights = JSON.parse(contents);
}
catch (e) {
return program.error("stdin: " + (e instanceof Error ? e.message : "JSON.parse: failed to parse"));
}
for (const flight of rawFlights)
flights.set(flight.id, new Flight(flight.id, new Date(flight.time), flight.tail, flight.type, flight.airline, flight.callsign, new Location(flight.to.name, flight.to.lat, flight.to.lon), new Location(flight.from.name, flight.from.lat, flight.from.lon)));
continue;
}
for (const flight of await loadFlightsFromFs(path))
flights.set(flight.id, flight);
}
return flights;
}
const accent = `\x1b[38;2;${[0, 188, 125].join(";")}m`;
const bold = "\x1b[1m";
const dim = "\x1b[38;5;250m";
const reset = "\x1b[0m";
function bar(label, value, percent, colour = accent) {
const char = "▇";
const bars = 50;
let bar = "";
if (percent === 0)
bar = "";
else if (percent < 0.02)
bar = "▏";
else
bar = char.repeat(Math.round(bars * percent));
process.stdout.write(`${label}${dim}:${reset} ${colour}${bar}${reset} ${value}\n`);
}
program.command("fetch")
.description("Fetch arriving flights from airnavradar.com API.")
.argument("<icao>", "ICAO code of the airport.")
.argument("[path]", "Path where the retrieved data will be saved in JSON format. Use a dash ('-') to write to standard output.")
.option("-c, --concurrency <count>", "Number of requests to send in parallel.", "5")
.option("-s, --silent", "Silent mode (no progress indicator).")
.action(async (a, b, options) => {
const icao = a;
let location = b ?? icao + "-" + (Date.now() / 1000).toFixed(0) + ".json";
const concurrency = Number.parseInt(options.concurrency);
if (Number.isNaN(concurrency) || !Number.isFinite(concurrency))
program.error("concurrency must be valid integer");
if (options.silent !== true)
process.stderr.write(`Fetching flights for ${icao}…\n`);
const started = new Date();
function progress(flights, started) {
if (options.silent)
return;
const week = new Date(Date.now() - 7 * 24 * 60 * 60 * 1000);
const thisWeek = Array.from(flights.values()).filter(f => f.time.getTime() > week.getTime());
const averagePerDay = thisWeek.length / new Set(thisWeek.map(f => f.time.toDateString())).size;
const oldest = thisWeek.length > 0 ? thisWeek.reduce((f, g) => f.time.getTime() < g.time.getTime() ? f : g).time : null;
const remainingDays = ((oldest?.getTime() ?? week.getTime()) - week.getTime()) / (24 * 60 * 60 * 1000);
const estimated = Math.round(averagePerDay * remainingDays);
const message = `\r[${timeAgo(started)}] Fetched: ${flights.size} of ${Number.isNaN(estimated) ? "N/A" : (flights.size + estimated)} (estimated).${oldest !== null ? ` Oldest flight: ${oldest.toLocaleDateString(void 0, { day: "numeric", weekday: "short", month: "short", year: "numeric" })}` : ""}`;
process.stderr.write(message + " ".repeat(Math.max(0, process.stdout.columns - message.length)));
}
const flights = new Map();
progress(flights, started);
const progressInterval = setInterval(() => progress(flights, started), 1000);
const initial = await get(icao, new Date(Date.now() + 24 * 60 * 60 * 1000));
for (const flight of initial.list)
flights.set(flight.id, flight);
progress(flights, started);
let more = initial.more;
let t = new Date(initial.oldest.getTime() + 27e5);
while (more) {
const promises = [];
for (let i = 0; i < concurrency; ++i) {
promises.push(get(icao, new Date(t)));
t = new Date(t.getTime() - 27e5);
}
const results = await Promise.all(promises);
for (const result of results)
for (const flight of result.list)
flights.set(flight.id, flight);
more = results.every(r => r.more);
progress(flights, started);
}
clearInterval(progressInterval);
if (options.silent !== true)
process.stderr.write("\n");
const json = JSON.stringify(Array.from(flights.values()));
if (location === "-")
process.stdout.write(json);
else {
process.stdout.write(`Fetched ${flights.size} flights.\nWriting to ${location}…`);
await fs.writeFile(location, json);
process.stdout.write(`\rWritten to ${location} \n`);
}
});
program.command("gen")
.description("Generate airlines configuration.")
.argument("<paths...>", "Paths to JSON files or directories containing JSON files. Use a dash ('-') to read from standard input.")
.action(async (p) => {
const paths = new Set(p);
const flights = await loadFlights(paths);
// remove invalid flights or try to fill data
const helicopters = new Set(JSON.parse(await fs.readFile(path.join(PATH, "..", "data", "helicopters.json"), "utf-8")));
for (const [id, flight] of flights) {
if (helicopters.has(flight.type.toUpperCase())
|| (flight.airline === null && flight.callsign === null)
|| (flight.airline === null && flight.tail === null)) {
flights.delete(id);
continue;
}
if (flight.callsign !== null && (flight.airline === "{PVT}" || flight.airline === null)) {
// Regional registrations
if (flight.tail !== null) {
/**
* Regular expressions for areas with odd registration formats
* [expression, number of characters that are part of area code]
*/
const regexes = [
[/^N\d{1,5}[A-Z]{0,2}$/, 1], // US (N)
[/^HI\d{3}([A-Z]{2}|\d)?$/, 2], // DO (HI)
[/^JA(\d{4}|\d{3}[A-Z]|\d{2}[A-Z]{2})$/, 2], // JP (JA)
[/^HL\d{4}$/, 2], // KR (HL)
[/^UR\d{5}$/, 2], // UA (UR)
[/^UK\d{5}$/, 2], // UZ (UK)
[/^YV\d{3}(\d|T|E)$/, 2], // VE (YV)
[/^C-[FGI][A-Z]{3}$/, 3], // CA (C-F, C-G, C-I)
[/^7T-([VW])[A-Z]{2}$/, 4], // Algeria Civilian (7T-V 7T-W)
[/^V[PQ]-B[A-Z]{2}$/, 4], // Bermuda (VP-B VQ-B)
[/^VP-L[A-Z]{2}$/, 4], // British Virgin Islands (VP-L)
[/^V[PQ]-C[A-Z]{2}$/, 4], // Cayman Islands (VP-C VQ-C)
[/^CU-[ACHNTU]1\d{4}$/, 5], // Cuba (CU-A1 CU-C1 CU-H1 CU-N1 CU-T1 CU-U1)
];
const match = regexes.find(([regex]) => regex.test(flight.callsign)) ?? null;
if (match !== null) {
flights.set(id, new Flight(flight.id, flight.time, flight.tail, flight.type, tailToCallsign(flight.tail.slice(0, match[1]).replaceAll("-", ""), flight.tail.slice(match[1])), flight.callsign, new Location(flight.to.name, flight.to.lat, flight.to.lon), new Location(flight.from.name, flight.from.lat, flight.from.lon)));
continue;
}
// Registrations with a dash (e.g. AB-123CD)
if (flight.tail.replace("-", "").toUpperCase() === flight.callsign.replace("-", "").toUpperCase()) {
flights.set(id, new Flight(flight.id, flight.time, flight.tail, flight.type, tailToCallsign(flight.tail.slice(0, flight.tail.indexOf("-")), flight.tail.slice(flight.tail.indexOf("-") + 1)), flight.callsign, new Location(flight.to.name, flight.to.lat, flight.to.lon), new Location(flight.from.name, flight.from.lat, flight.from.lon)));
continue;
}
}
// Assuming airline callsign
// (if it doesn’t start with 3 letters… ¯\_(ツ)_/¯)
if (/^[A-Z]{3}\d[A-Z\d]{0,3}$/.test(flight.callsign)) {
flights.delete(id);
continue;
}
flights.set(id, new Flight(flight.id, flight.time, flight.tail, flight.type, flight.callsign.slice(0, 3), flight.callsign, new Location(flight.to.name, flight.to.lat, flight.to.lon), new Location(flight.from.name, flight.from.lat, flight.from.lon)));
}
// if there is an airline and the callsign start with more than 3 letters
else if (flight.callsign !== null && /^[A-Z]{4,}/.test(flight.callsign.toUpperCase())) {
flights.set(id, new Flight(flight.id, flight.time, flight.tail, flight.type, flight.callsign.toUpperCase().replace(/[^A-Z\d]/g, "") + "-", flight.callsign, flight.to, flight.from));
}
}
const merged = [];
// group together flights that are from same airline, type and direction
const callsigns = new Map(Object.entries(JSON.parse(await fs.readFile(path.join(PATH, "..", "data", "callsigns.json"), "utf-8"))));
for (const flight of flights.values()) {
if (flight.airline === undefined)
continue;
const direction = flight.to.direction(flight.from);
const existing = merged.find(m => m.airline === flight.airline && m.type.has(flight.type) && m.direction.has(direction));
if (existing !== undefined) {
existing.flights.push(flight);
existing.type.add(flight.type);
existing.direction.add(direction);
}
else {
let pronunciation;
if (flight.airline !== null && flight.airline.endsWith("-")) {
pronunciation = flight.airline.slice(0, -1);
for (const [number, value] of Object.entries(NUMBERS))
pronunciation = pronunciation.replaceAll(number, ` ${value} `);
pronunciation = pronunciation.trim().replace(/\s+/g, " ").toLowerCase();
}
else if (flight.airline === null || flight.airline.includes("-"))
pronunciation = null;
else
pronunciation = callsigns.get(flight.airline.toUpperCase())
?? flight.airline.toUpperCase().split("")
.map(c => PHONETIC[c] ?? c).join(" ");
if (pronunciation !== null && !flight.airline?.endsWith("-") && !Array.from(callsigns.values()).includes(pronunciation))
process.stderr.write(`WARNING! ${flight.airline}: no pronunciation available\n`);
merged.push({
airline: flight.airline,
type: new Set([flight.type]),
direction: new Set([direction]),
flights: [flight],
score: NaN,
pronunciation
});
}
}
// calculate score
const maxFlights = Math.max(...merged.map(m => m.flights.length));
for (const m of merged)
m.score = (m.flights.length / maxFlights) * 10;
process.stdout.write(merged
// sort by score descending
.sort((a, b) => b.score - a.score)
.map(entry => {
return "\t" +
entry.airline + ", " +
entry.score.toFixed(2) + ", " +
Array.from(entry.type).sort((a, b) => a.localeCompare(b)).join("/").toLowerCase() + ", " +
(entry.pronunciation === null ? "0" : entry.pronunciation) + ", " +
Array.from(entry.direction).sort((a, b) => a.name.localeCompare(b.name)).join("").toLowerCase();
}).join("\n")
+ "\n");
});
program.command("flow")
.description("Calculate the flow of arrivals of an airport.")
.argument("<paths...>", "Paths to JSON files or directories containing JSON files. Use a dash ('-') to read from standard input.")
.action(async (p) => {
const paths = new Set(p);
const flights = await loadFlights(paths);
const stats = {};
const helicopters = new Set(JSON.parse(await fs.readFile(path.join(PATH, "..", "data", "helicopters.json"), "utf-8")));
for (const flight of flights.values()) {
if (typeof flight.type !== "string"
|| !(flight.time instanceof Date)
|| Number.isNaN(flight.time.getTime())
|| helicopters.has(flight.type.toUpperCase())) {
flights.delete(flight.id);
continue;
}
const day = flight.time.toISOString().split("T")[0];
const hour = flight.time.getUTCHours();
if (stats[day] === undefined)
stats[day] = {};
if (stats[day][hour] === undefined)
stats[day][hour] = 0;
++stats[day][hour];
}
if (flights.size === 0)
program.error("No flights were loaded.");
const sorted = Array.from(flights.values()).sort((a, b) => b.time.getTime() - a.time.getTime());
const oldest = sorted.slice(-1)[0].time;
oldest.setUTCHours(0, 0, 0, 0);
const earliest = sorted[0].time;
earliest.setUTCHours(0, 0, 0, 0);
process.stdout.write(`${dim}#${reset} ${bold}Hourly Flow${reset} ${dim}(${oldest.toLocaleDateString()}${oldest.getTime() === earliest.getTime()
? ""
: (" to " + earliest.toLocaleDateString())})${reset}\n\n`);
const avgHourlyFlowOverall = Object
.values(stats)
.flatMap(day => Object.values(day))
.reduce((sum, count) => sum + count, 0)
/ Object
.values(stats)
.flatMap(day => Object.values(day))
.length;
const peakHourlyFlow = Math.max(...Object.values(stats).flatMap(day => Object.values(day)));
const lowestHourlyFlow = Math.min(...Object.values(stats).flatMap(day => Object.values(day)));
process.stdout.write(`\taverage\t${dim}=${reset} ${avgHourlyFlowOverall.toFixed(2)}\n`);
process.stdout.write(`\thighest\t${dim}=${reset} ${peakHourlyFlow}\n`);
process.stdout.write(`\tlowest\t${dim}=${reset} ${lowestHourlyFlow}\n`);
process.stdout.write(`\n\n${dim}#${reset} ${bold}Hourly Average per Weekday${reset}\n\n`);
const weekDays = new Map();
let weekDayMax = 0;
for (const [day, hours] of Object.entries(stats)) {
const key = new Date(day).toLocaleDateString(void 0, { weekday: "short" });
if (!weekDays.has(key))
weekDays.set(key, [0, 0, new Date(day).getUTCDay()]);
weekDays.get(key)[0] += Object.values(hours).reduce((sum, count) => sum + count, 0);
weekDays.get(key)[1] += Object.values(hours).length;
weekDayMax = Math.max(weekDayMax, weekDays.get(key)[0]);
}
for (const [day, [flights, count]] of Array.from(weekDays.entries()).sort((a, b) => (a[1][2] && !b[1][2]) ? -1 : (!a[1][2] && b[1][2]) ? 1 : a[1][2] - b[1][2]))
bar(day, (flights / count).toFixed(2), flights / weekDayMax);
process.stdout.write(`\n\n${dim}#${reset} ${bold}Average per Hour${reset}\n\n`);
const hourlyAverage = Array.from({ length: 24 }, (_, hour) => Object.values(stats)
.map(dayStats => dayStats[hour] ?? 0)
.reduce((sum, count) => sum + count, 0)
/ Object.values(stats).length);
const hourlyAverageMax = Math.max(...hourlyAverage);
for (const [hour, flights] of hourlyAverage.entries())
bar(hour.toString().padStart(2, "0") + ":00Z", flights.toFixed(2), flights / hourlyAverageMax);
});
program.parse();
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xpLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL2NsaS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQ0E7Ozs7Ozs7Ozs7Ozs7OztHQWVHO0FBQ0gsT0FBTyxJQUFJLE1BQU0sV0FBVyxDQUFDO0FBQzdCLE9BQU8sR0FBRyxNQUFNLFVBQVUsQ0FBQztBQUMzQixPQUFPLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQUNsQyxPQUFPLEVBQUMsT0FBTyxFQUFDLE1BQU0sV0FBVyxDQUFDO0FBQ2xDLE9BQU8sRUFBQyxNQUFNLEVBQUUsUUFBUSxFQUFhLFFBQVEsRUFBRSxPQUFPLEVBQUMsTUFBTSxVQUFVLENBQUM7QUFFeEUsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsYUFBYSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztBQUU5RCxNQUFNLE9BQU8sR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLE1BQU0sRUFBRSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRSxJQUFJLEVBQUUsY0FBYyxDQUFDLEVBQUUsT0FBTyxDQUFDLENBQUMsQ0FBQztBQUM5RixNQUFNLE9BQU8sR0FBRyxJQUFJLE9BQU8sRUFBRSxDQUFDO0FBRTlCLEtBQUssVUFBVSxpQkFBaUIsQ0FBQyxJQUFZLEVBQUUsZ0JBQXdCLENBQUM7SUFDcEUsTUFBTSxPQUFPLEdBQWEsRUFBRSxDQUFDO0lBQzdCLElBQUksS0FBOEIsQ0FBQztJQUNuQyxJQUFJLENBQUM7UUFDRCxLQUFLLEdBQUcsTUFBTSxFQUFFLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQ2hDLENBQUM7SUFDRCxPQUFPLENBQUMsRUFBRSxDQUFDO1FBQ1AsT0FBTyxPQUFPLENBQUMsS0FBSyxDQUFDLEdBQUcsSUFBSSxLQUFLLENBQUMsWUFBWSxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMs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