eatc-airlines
Version:
A command-line tool and API for retrieving scheduled and historical flight data and generating Endless ATC airline configurations.
240 lines • 11.8 kB
JavaScript
/*
* 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/>.
*/
export class LatLon {
/**
* Latitude in decimal degrees
*/
lat;
/**
* Longitude in decimal degrees
*/
lon;
/**
* @param lat Latitude in decimal degrees
* @param lon Longitude in decimal degrees
*/
constructor(lat, lon) {
this.lat = lat;
this.lon = lon;
}
/**
* Calculate initial bearing to another {@link LatLon}
* @param to
* @returns Bearing in decimal degrees
*/
bearing(to) {
const φ1 = this.lat * Math.PI / 180;
const φ2 = to.lat * Math.PI / 180;
const λ1 = this.lon * Math.PI / 180;
const λ2 = to.lon * Math.PI / 180;
const Δλ = λ2 - λ1;
const y = Math.sin(Δλ) * Math.cos(φ2);
const x = Math.cos(φ1) * Math.sin(φ2) - Math.sin(φ1) * Math.cos(φ2) * Math.cos(Δλ);
const θ = Math.atan2(y, x);
return (θ * 180 / Math.PI + 360) % 360;
}
/**
* Calculate initial direction to another {@link LatLon}
* @param to
*/
direction(to) {
return Direction.fromBearing(this.bearing(to));
}
toString() {
return `${this.lat >= 0 ? Direction.N : Direction.S}, ${this.lon >= 0 ? Direction.E : Direction.W}`;
}
toJSON() {
return {
lat: this.lat,
lon: this.lon,
};
}
}
export class Location extends LatLon {
/**
* The name of this location
*/
name;
/**
* @param name The name of this location
* @param lat Latitude in decimal degrees
* @param lon Longitude in decimal degrees
*/
constructor(name, lat, lon) {
super(lat, lon);
this.name = name;
}
toString() {
return this.name + ", " + super.toString();
}
toJSON() {
return {
name: this.name,
lat: this.lat,
lon: this.lon,
};
}
}
export class Direction {
name;
/**
* North
*/
static N = new Direction("N");
/**
* East
*/
static E = new Direction("E");
/**
* South
*/
static S = new Direction("S");
/**
* West
*/
static W = new Direction("W");
constructor(name) {
this.name = name;
}
/**
* Get direction from bearing
* @param bearing Bearing in decimal degrees
*/
static fromBearing(bearing) {
const normalisedBearing = (bearing + 360) % 360;
if (normalisedBearing >= 225 && normalisedBearing < 315)
return Direction.W;
if (normalisedBearing >= 135 && normalisedBearing < 225)
return Direction.S;
if (normalisedBearing >= 45 && normalisedBearing < 135)
return Direction.E;
return Direction.N;
}
toString() {
return this.name;
}
toJSON() {
return this.name;
}
}
export class Flight {
/**
* Unique ID
*/
id;
/**
* Flight arrival time (or estimate)
*/
time;
/**
* Tail number (aircraft registration)
*/
tail;
/**
* Aircraft ICAO type designator
*/
type;
/**
* Airline ICAO code (unique 3-letter identifier)
*/
airline;
/**
* Flight callsign
*/
callsign;
/**
* Flight destination
*/
to;
/**
* Flight origin
*/
from;
/**
* @param id Unique ID
* @param time Flight arrival time (or estimate)
* @param tail Tail number (aircraft registration)
* @param type Aircraft ICAO type designator
* @param airline Airline ICAO code (unique 3-letter identifier)
* @param callsign Flight callsign
* @param to Flight destination
* @param from Flight origin
*/
constructor(id, time, tail, type, airline, callsign, to, from) {
this.id = id;
this.time = time;
this.tail = tail;
this.type = type;
this.airline = airline;
this.callsign = callsign;
this.to = to;
this.from = from;
}
toJSON() {
return {
id: this.id,
time: this.time?.getTime() ?? null,
tail: this.tail,
type: this.type,
airline: this.airline,
callsign: this.callsign,
to: this.to,
from: this.from,
};
}
}
export const PHONETIC = {
A: "Alpha",
B: "Bravo",
C: "Charlie",
D: "Delta",
E: "Echo",
F: "Foxtrot",
G: "Golf",
H: "Hotel",
I: "India",
J: "Juliet",
K: "Kilo",
L: "Lima",
M: "Mike",
N: "November",
O: "Oscar",
P: "Papa",
Q: "Quebec",
R: "Romeo",
S: "Sierra",
T: "Tango",
U: "Uniform",
V: "Victor",
W: "Whisky",
X: "X-Ray",
Y: "Yankee",
Z: "Zulu",
};
export const NUMBERS = {
0: "Zero",
1: "One",
2: "Two",
3: "Three",
4: "Four",
5: "Five",
6: "Six",
7: "Seven",
8: "Eight",
9: "Niner",
};
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXBpLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL2FwaS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7Ozs7Ozs7O0dBZUc7QUFDSCxNQUFNLE9BQU8sTUFBTTtJQUNmOztPQUVHO0lBQ2EsR0FBRyxDQUFTO0lBRTVCOztPQUVHO0lBQ2EsR0FBRyxDQUFTO0lBRTVCOzs7T0FHRztJQUNILFlBQ0ksR0FBVyxFQUNYLEdBQVc7UUFFWCxJQUFJLENBQUMsR0FBRyxHQUFHLEdBQUcsQ0FBQztRQUNmLElBQUksQ0FBQyxHQUFHLEdBQUcsR0FBRyxDQUFDO0lBQ25CLENBQUM7SUFFRDs7OztPQUlHO0lBQ0ksT0FBTyxDQUFDLEVBQVU7UUFDckIsTUFBTSxFQUFFLEdBQUcsSUFBSSxDQUFDLEdBQUcsR0FBRyxJQUFJLENBQUMsRUFBRSxHQUFHLEdBQUcsQ0FBQztRQUNwQyxNQUFNLEVBQUUsR0FBRyxFQUFFLENBQUMsR0FBRyxHQUFHLElBQUksQ0FBQyxFQUFFLEdBQUcsR0FBRyxDQUFDO1FBQ2xDLE1BQU0sRUFBRSxHQUFHLElBQUksQ0FBQyxHQUFHLEdBQUcsSUFBSSxDQUFDLEVBQUUsR0FBRyxHQUFHLENBQUM7UUFDcEMsTUFBTSxFQUFFLEdBQUcsRUFBRSxDQUFDLEdBQUcsR0FBRyxJQUFJLENBQUMsRUFBRSxHQUFHLEdBQUcsQ0FBQztRQUVsQyxNQUFNLEVBQUUsR0FBRyxFQUFFLEdBQUcsRUFBRSxDQUFDO1FBRW5CLE1BQU0sQ0FBQyxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsQ0FBQztRQUN0QyxNQUFNLENBQUMsR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxJQUFJLENBQUMsR0FB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