@fboes/aerofly-data 1.9.0 → 1.9.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintrc.json +2 -1
- package/CHANGELOG.md +4 -1
- package/data/aircraft-liveries-missing.md +347 -0
- package/data/aircraft-liveries.json +117 -45
- package/data/aircraft-livery-select-optgroup.html +5 -0
- package/data/aircraft.md +5 -5
- package/data/airport-coordinates-object.json +658 -220
- package/data/airport-coordinates.json +141 -68
- package/data/airport-list.json +93 -20
- package/data/airports-unmatched.md +135 -207
- package/data/airports.geojson +2580 -1104
- package/get-aircraft.js +69 -22
- package/get-airports.js +16 -18
- package/package.json +1 -1
- package/src/aircraft-functions.js +62 -25
- package/src/airport-functions.js +8 -8
package/get-aircraft.js
CHANGED
|
@@ -2,40 +2,73 @@
|
|
|
2
2
|
|
|
3
3
|
//@ts-check
|
|
4
4
|
|
|
5
|
-
import * as fs from "node:fs";
|
|
5
|
+
import * as fs from "node:fs/promises";
|
|
6
6
|
import * as path from "node:path";
|
|
7
7
|
import {
|
|
8
8
|
getAeroflyAircraft,
|
|
9
9
|
getSelectLiveryOptgroupOptions,
|
|
10
10
|
getSelectOptgroupOptions,
|
|
11
11
|
getSelectOptions,
|
|
12
|
+
MISSING_LIVERIES,
|
|
12
13
|
} from "./src/aircraft-functions.js";
|
|
13
14
|
|
|
14
15
|
const inputDirectory = process.argv[2] ?? ".";
|
|
15
16
|
const aeroflyAircraft = getAeroflyAircraft(inputDirectory);
|
|
16
17
|
|
|
18
|
+
/**
|
|
19
|
+
* @type {Promise<void>[]}
|
|
20
|
+
*/
|
|
21
|
+
const promises = [];
|
|
22
|
+
|
|
17
23
|
process.stdout
|
|
18
24
|
.write(`Found \x1b[92m${aeroflyAircraft.length}\x1b[0m Aerofly FS Aircraft with \x1b[92m${aeroflyAircraft.reduce((sum, aircraft) => sum + aircraft.liveries.length, 0)}\x1b[0m liveries
|
|
19
25
|
`);
|
|
20
26
|
|
|
21
27
|
// Ensure the output directory exists
|
|
22
28
|
const outputDirectory = path.join("data");
|
|
23
|
-
await fs.
|
|
29
|
+
await fs.mkdir(outputDirectory, { recursive: true });
|
|
24
30
|
|
|
25
31
|
// Write the full output (with liveries) to aircraft-liveries.json
|
|
26
32
|
const outputFilePathWithLiveries = path.join(outputDirectory, "aircraft-liveries.json");
|
|
27
|
-
|
|
28
|
-
|
|
33
|
+
promises.push(
|
|
34
|
+
fs.writeFile(outputFilePathWithLiveries, JSON.stringify(aeroflyAircraft, null, 2), "utf-8").then(() => {
|
|
35
|
+
process.stdout.write(
|
|
36
|
+
`Full aircraft data (with liveries) written to \x1b[92m${outputFilePathWithLiveries}\x1b[0m\n`,
|
|
37
|
+
);
|
|
38
|
+
}),
|
|
39
|
+
);
|
|
40
|
+
|
|
41
|
+
// Write missing livery file
|
|
42
|
+
const outputMissingLiveries = path.join(outputDirectory, "aircraft-liveries-missing.md");
|
|
43
|
+
/**
|
|
44
|
+
* @type {string[]}
|
|
45
|
+
*/
|
|
46
|
+
const missingLiveries = [];
|
|
47
|
+
MISSING_LIVERIES.forEach((m) => {
|
|
48
|
+
missingLiveries.push(`- ${m}`);
|
|
49
|
+
});
|
|
50
|
+
const outputMissingLiveriesContent =
|
|
51
|
+
"# Aerofly FS: Liveries without ICAO code match\n\n" + missingLiveries.sort().join("\n") + "\n";
|
|
52
|
+
promises.push(
|
|
53
|
+
fs.writeFile(outputMissingLiveries, outputMissingLiveriesContent, "utf-8").then(() => {
|
|
54
|
+
process.stdout.write(`Missing livery file written to \x1b[92m${outputMissingLiveries}\x1b[0m\n`);
|
|
55
|
+
}),
|
|
56
|
+
);
|
|
29
57
|
|
|
30
58
|
// Write the abbreviated output (without liveries) to aircraft.json
|
|
31
59
|
const outputFilePathWithoutLiveries = path.join(outputDirectory, "aircraft.json");
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
)
|
|
37
|
-
|
|
38
|
-
|
|
60
|
+
promises.push(
|
|
61
|
+
fs
|
|
62
|
+
.writeFile(
|
|
63
|
+
outputFilePathWithoutLiveries,
|
|
64
|
+
JSON.stringify(aeroflyAircraft, (key, value) => (key === "liveries" ? undefined : value), 2),
|
|
65
|
+
"utf-8",
|
|
66
|
+
)
|
|
67
|
+
.then(() => {
|
|
68
|
+
process.stdout.write(
|
|
69
|
+
`Abbreviated aircraft data (without liveries) written to \x1b[92m${outputFilePathWithoutLiveries}\x1b[0m\n`,
|
|
70
|
+
);
|
|
71
|
+
}),
|
|
39
72
|
);
|
|
40
73
|
|
|
41
74
|
// Sort aeroflyAircraft by nameFull
|
|
@@ -82,29 +115,43 @@ const summaryContent =
|
|
|
82
115
|
- Total Liveries: **${numberFormat(sortedAircraft.reduce((sum, aircraft) => sum + aircraft.liveries.length, 0))}**
|
|
83
116
|
`;
|
|
84
117
|
|
|
85
|
-
|
|
86
|
-
|
|
118
|
+
promises.push(
|
|
119
|
+
fs.writeFile(summaryFilePath, summaryContent, "utf-8").then(() => {
|
|
120
|
+
process.stdout.write(`Summary written to \x1b[92m${summaryFilePath}\x1b[0m\n`);
|
|
121
|
+
}),
|
|
122
|
+
);
|
|
87
123
|
|
|
88
124
|
// Write HTML <select> options to aircraft-select.html
|
|
89
125
|
const selectFilePath = path.join(outputDirectory, "aircraft-select.html");
|
|
90
126
|
let selectContent = getSelectOptions(sortedAircraft);
|
|
91
|
-
|
|
92
|
-
|
|
127
|
+
promises.push(
|
|
128
|
+
fs.writeFile(selectFilePath, selectContent, "utf-8").then(() => {
|
|
129
|
+
process.stdout.write(`HTML <select> options written to \x1b[92m${selectFilePath}\x1b[0m\n`);
|
|
130
|
+
}),
|
|
131
|
+
);
|
|
93
132
|
|
|
94
133
|
// Write HTML <select> with <optgroup> to aircraft-select-optgroup.html
|
|
95
134
|
const selectOptgroupFilePath = path.join(outputDirectory, "aircraft-select-optgroup.html");
|
|
96
135
|
let selectOptgroupContent = getSelectOptgroupOptions(sortedAircraft);
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
136
|
+
promises.push(
|
|
137
|
+
fs.writeFile(selectOptgroupFilePath, selectOptgroupContent, "utf-8").then(() => {
|
|
138
|
+
process.stdout.write(
|
|
139
|
+
`HTML aircraft <select> with category <optgroup> options written to \x1b[92m${selectOptgroupFilePath}\x1b[0m\n`,
|
|
140
|
+
);
|
|
141
|
+
}),
|
|
100
142
|
);
|
|
101
143
|
|
|
102
144
|
// Write HTML <select> with <optgroup> to aircraft-select-optgroup.html
|
|
103
145
|
const selectOptgroupLiveryFilePath = path.join(outputDirectory, "aircraft-livery-select-optgroup.html");
|
|
104
146
|
let selectOptgroupLiveryContent = getSelectLiveryOptgroupOptions(sortedAircraft);
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
147
|
+
promises.push(
|
|
148
|
+
fs.writeFile(selectOptgroupLiveryFilePath, selectOptgroupLiveryContent, "utf-8").then(() => {
|
|
149
|
+
process.stdout.write(
|
|
150
|
+
`HTML livery <select> with aircraft <optgroup> options written to \x1b[92m${selectOptgroupLiveryFilePath}\x1b[0m\n`,
|
|
151
|
+
);
|
|
152
|
+
}),
|
|
108
153
|
);
|
|
109
154
|
|
|
110
|
-
|
|
155
|
+
Promise.all(promises).then(() => {
|
|
156
|
+
process.stdout.write(`\nAll aircraft files written to \x1b[92m${path.resolve(outputDirectory)}\x1b[0m\n`);
|
|
157
|
+
});
|
package/get-airports.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
//@ts-check
|
|
4
4
|
|
|
5
5
|
import GeoJSON from "@fboes/geojson";
|
|
6
|
-
import * as fs from "node:fs";
|
|
6
|
+
import * as fs from "node:fs/promises";
|
|
7
7
|
import * as path from "node:path";
|
|
8
8
|
import { parse } from "csv-parse/sync";
|
|
9
9
|
import {
|
|
@@ -17,9 +17,7 @@ const inputDirectory = process.argv[2] ?? ".";
|
|
|
17
17
|
|
|
18
18
|
// Ensure the output directory exists
|
|
19
19
|
const outputDirectory = path.join("data");
|
|
20
|
-
|
|
21
|
-
fs.mkdirSync(outputDirectory, { recursive: true });
|
|
22
|
-
}
|
|
20
|
+
await fs.mkdir(outputDirectory, { recursive: true });
|
|
23
21
|
|
|
24
22
|
const aeroflyGeoJson = new GeoJSON.FeatureCollection();
|
|
25
23
|
const aeroflyAirports = new Map([
|
|
@@ -30,7 +28,7 @@ const aeroflyAirportsLength = aeroflyAirports.size;
|
|
|
30
28
|
process.stdout.write(`Found \x1b[92m${aeroflyAirports.size}\x1b[0m Aerofly FS Airports
|
|
31
29
|
`);
|
|
32
30
|
|
|
33
|
-
const airportsSource = fs.
|
|
31
|
+
const airportsSource = await fs.readFile(`tmp/airports.csv`);
|
|
34
32
|
|
|
35
33
|
/** @type {string[][]} with a single CSV line from airports.csv */
|
|
36
34
|
let airportsRecords = parse(airportsSource, { bom: true });
|
|
@@ -45,10 +43,10 @@ const icaoCodes = [];
|
|
|
45
43
|
|
|
46
44
|
/**
|
|
47
45
|
* @type {{
|
|
48
|
-
* code:
|
|
49
|
-
* name:
|
|
50
|
-
* lat:
|
|
51
|
-
* lon:
|
|
46
|
+
* code: string,
|
|
47
|
+
* name: string,
|
|
48
|
+
* lat: number,
|
|
49
|
+
* lon: number
|
|
52
50
|
* }[]}
|
|
53
51
|
*/
|
|
54
52
|
const icaoCoordinatesObject = [];
|
|
@@ -58,14 +56,14 @@ const icaoCoordinatesObject = [];
|
|
|
58
56
|
* @param {string[]} searchWords
|
|
59
57
|
* @returns {[number, string]|[undefined, undefined]} Returns the length of the airport and the code if found, otherwise undefined.
|
|
60
58
|
*/
|
|
61
|
-
|
|
59
|
+
function getAeroflyAirport(searchWords) {
|
|
62
60
|
for (const word of searchWords) {
|
|
63
61
|
if (aeroflyAirports.has(word)) {
|
|
64
62
|
return [aeroflyAirports.get(word) || 0, word];
|
|
65
63
|
}
|
|
66
64
|
}
|
|
67
65
|
return [undefined, undefined];
|
|
68
|
-
}
|
|
66
|
+
}
|
|
69
67
|
|
|
70
68
|
/**
|
|
71
69
|
* @param {string} aeroflyCode
|
|
@@ -73,7 +71,7 @@ const getAeroflyAirport = (searchWords) => {
|
|
|
73
71
|
* @param {string[]} airportsRecord
|
|
74
72
|
* @param {number} length
|
|
75
73
|
*/
|
|
76
|
-
|
|
74
|
+
function addRecord(aeroflyCode, bestCode, airportsRecord, length) {
|
|
77
75
|
// Remove airport from list of Aerofly FS4 Airports
|
|
78
76
|
aeroflyAirports.delete(aeroflyCode);
|
|
79
77
|
|
|
@@ -121,7 +119,7 @@ const addRecord = (aeroflyCode, bestCode, airportsRecord, length) => {
|
|
|
121
119
|
}
|
|
122
120
|
|
|
123
121
|
aeroflyGeoJson.addFeature(feature);
|
|
124
|
-
}
|
|
122
|
+
}
|
|
125
123
|
|
|
126
124
|
// -----------------------------------------------------------------------------
|
|
127
125
|
// PARSING
|
|
@@ -187,12 +185,12 @@ icaoCoordinatesObject.sort((a, b) => {
|
|
|
187
185
|
|
|
188
186
|
// Write the GeoJSON data to a file
|
|
189
187
|
const outputFilePath = path.join(outputDirectory, "airports.geojson");
|
|
190
|
-
fs.
|
|
188
|
+
await fs.writeFile(outputFilePath, JSON.stringify(aeroflyGeoJson, null, 2), "utf-8");
|
|
191
189
|
process.stdout.write(`GeoJSON data written to \x1b[92m${outputFilePath}\x1b[0m\n`);
|
|
192
190
|
|
|
193
191
|
// Write the ICAO codes to airport-list.json
|
|
194
192
|
const icaoListFilePath = path.join(outputDirectory, "airport-list.json");
|
|
195
|
-
fs.
|
|
193
|
+
await fs.writeFile(icaoListFilePath, JSON.stringify(icaoCodes.sort(), null, 2) + "\n", "utf-8");
|
|
196
194
|
process.stdout.write(`ICAO code list written to \x1b[92m${icaoListFilePath}\x1b[0m\n`);
|
|
197
195
|
|
|
198
196
|
// Write the ICAO codes with airport names and geocoordinates to airport-coordinates.json
|
|
@@ -200,12 +198,12 @@ const icaoCoordinates = icaoCoordinatesObject.map((feature) => {
|
|
|
200
198
|
return [feature.code, feature.name, feature.lat, feature.lon];
|
|
201
199
|
});
|
|
202
200
|
const icaoCoordinatesFilePath = path.join(outputDirectory, "airport-coordinates.json");
|
|
203
|
-
fs.
|
|
201
|
+
await fs.writeFile(icaoCoordinatesFilePath, JSON.stringify(icaoCoordinates, null, 2) + "\n", "utf-8");
|
|
204
202
|
process.stdout.write(`ICAO coordinates list written to \x1b[92m${icaoCoordinatesFilePath}\x1b[0m\n`);
|
|
205
203
|
|
|
206
204
|
// Write the ICAO codes with airport names and geocoordinates to airport-coordinates-object.json
|
|
207
205
|
const icaoCoordinatesObjectFilePath = path.join(outputDirectory, "airport-coordinates-object.json");
|
|
208
|
-
fs.
|
|
206
|
+
await fs.writeFile(icaoCoordinatesObjectFilePath, JSON.stringify(icaoCoordinatesObject, null, 2) + "\n", "utf-8");
|
|
209
207
|
process.stdout.write(`ICAO coordinates object list written to \x1b[92m${icaoCoordinatesObjectFilePath}\x1b[0m\n`);
|
|
210
208
|
|
|
211
209
|
// Write the missing codes to airports-unmatched.md
|
|
@@ -216,7 +214,7 @@ const unmatchedCodes = [...aeroflyAirports]
|
|
|
216
214
|
})
|
|
217
215
|
.sort()
|
|
218
216
|
.join("\n");
|
|
219
|
-
fs.
|
|
217
|
+
await fs.writeFile(
|
|
220
218
|
unmatchedFilePath,
|
|
221
219
|
`\
|
|
222
220
|
# Aerofly FS4 Unmatched Airports
|
package/package.json
CHANGED
|
@@ -37,25 +37,31 @@ import * as path from "path";
|
|
|
37
37
|
* }}
|
|
38
38
|
*/
|
|
39
39
|
|
|
40
|
+
/**
|
|
41
|
+
* Names of liveries which do not have an ICAO code
|
|
42
|
+
* @type {Set<string>}
|
|
43
|
+
*/
|
|
44
|
+
export const MISSING_LIVERIES = new Set();
|
|
45
|
+
|
|
40
46
|
/**
|
|
41
47
|
* Get all potential aircraft directories in the given directory.
|
|
42
48
|
* @param {string} directory
|
|
43
49
|
* @returns {fs.Dirent<string>[]}
|
|
44
50
|
*/
|
|
45
|
-
|
|
51
|
+
function getAeroflyAircraftDirectories(directory) {
|
|
46
52
|
return fs
|
|
47
53
|
.readdirSync(directory, { withFileTypes: true })
|
|
48
54
|
.filter((dirent) => dirent.isDirectory())
|
|
49
55
|
.sort()
|
|
50
56
|
.filter((dirent) => fs.existsSync(path.join(dirent.parentPath, dirent.name, dirent.name + ".tmc")));
|
|
51
|
-
}
|
|
57
|
+
}
|
|
52
58
|
|
|
53
59
|
/**
|
|
54
60
|
*
|
|
55
61
|
* @param {string} directory
|
|
56
62
|
* @returns {AeroflyAircraft[]}
|
|
57
63
|
*/
|
|
58
|
-
export
|
|
64
|
+
export function getAeroflyAircraft(directory) {
|
|
59
65
|
return getAeroflyAircraftDirectories(directory).map((dirent) => {
|
|
60
66
|
const tmdFileContent = fs.readFileSync(path.join(dirent.parentPath, dirent.name, dirent.name + ".tmc"), "utf8");
|
|
61
67
|
|
|
@@ -97,6 +103,8 @@ export const getAeroflyAircraft = (directory) => {
|
|
|
97
103
|
const liveryIcaoCode = getLiveryIcaoCode(livery.name);
|
|
98
104
|
if (liveryIcaoCode !== "") {
|
|
99
105
|
livery.icaoCode = liveryIcaoCode;
|
|
106
|
+
} else {
|
|
107
|
+
MISSING_LIVERIES.add(livery.name);
|
|
100
108
|
}
|
|
101
109
|
|
|
102
110
|
return livery;
|
|
@@ -108,7 +116,7 @@ export const getAeroflyAircraft = (directory) => {
|
|
|
108
116
|
liveries,
|
|
109
117
|
};
|
|
110
118
|
});
|
|
111
|
-
}
|
|
119
|
+
}
|
|
112
120
|
|
|
113
121
|
/**
|
|
114
122
|
* Convert airline name to airline ICA code
|
|
@@ -118,6 +126,7 @@ export const getAeroflyAircraft = (directory) => {
|
|
|
118
126
|
const getLiveryIcaoCode = (airlineName) => {
|
|
119
127
|
const name = airlineName.toLowerCase();
|
|
120
128
|
switch (name) {
|
|
129
|
+
case "ana":
|
|
121
130
|
case "all nippon airlines":
|
|
122
131
|
return "ANA";
|
|
123
132
|
case "american airlines":
|
|
@@ -128,6 +137,7 @@ const getLiveryIcaoCode = (airlineName) => {
|
|
|
128
137
|
case "china eastern":
|
|
129
138
|
return "CES";
|
|
130
139
|
case "lufthansa":
|
|
140
|
+
case "lufthansa 100":
|
|
131
141
|
return "DLH";
|
|
132
142
|
case "united airlines":
|
|
133
143
|
case "united":
|
|
@@ -152,7 +162,7 @@ const getLiveryIcaoCode = (airlineName) => {
|
|
|
152
162
|
case "air canada":
|
|
153
163
|
return "ACA";
|
|
154
164
|
case "etihad airways":
|
|
155
|
-
case "
|
|
165
|
+
case "etihad":
|
|
156
166
|
return "ETD";
|
|
157
167
|
case "latam airlines":
|
|
158
168
|
case "latam":
|
|
@@ -174,6 +184,7 @@ const getLiveryIcaoCode = (airlineName) => {
|
|
|
174
184
|
return "KLM";
|
|
175
185
|
case "korean air":
|
|
176
186
|
case "korean air lines":
|
|
187
|
+
case "korean airlines":
|
|
177
188
|
return "KAL";
|
|
178
189
|
case "qatar airways":
|
|
179
190
|
return "QTR";
|
|
@@ -202,6 +213,32 @@ const getLiveryIcaoCode = (airlineName) => {
|
|
|
202
213
|
return "CPA";
|
|
203
214
|
case "china southern":
|
|
204
215
|
return "CSN";
|
|
216
|
+
case "norwegian":
|
|
217
|
+
return "NAX";
|
|
218
|
+
case "aer lingus":
|
|
219
|
+
return "EIN";
|
|
220
|
+
case "avianca":
|
|
221
|
+
return "AVA";
|
|
222
|
+
case "finnair":
|
|
223
|
+
return "FIN";
|
|
224
|
+
case "tap portugal":
|
|
225
|
+
return "TAP";
|
|
226
|
+
case "egypt air":
|
|
227
|
+
return "MSR";
|
|
228
|
+
case "japan airlines":
|
|
229
|
+
return "JAL";
|
|
230
|
+
case "kuwait":
|
|
231
|
+
return "KAC";
|
|
232
|
+
case "saudia":
|
|
233
|
+
case "saudia arabian":
|
|
234
|
+
return "SVA";
|
|
235
|
+
case "virgin australia":
|
|
236
|
+
return "VOZ";
|
|
237
|
+
case "virgin":
|
|
238
|
+
case "virgin atlantic":
|
|
239
|
+
return "VIR";
|
|
240
|
+
case "qantas":
|
|
241
|
+
return "QFA";
|
|
205
242
|
default:
|
|
206
243
|
return "";
|
|
207
244
|
}
|
|
@@ -211,7 +248,7 @@ const getLiveryIcaoCode = (airlineName) => {
|
|
|
211
248
|
* @param {string} tmdFileContent
|
|
212
249
|
* @returns {AeroflyAircraftParsed}
|
|
213
250
|
*/
|
|
214
|
-
export
|
|
251
|
+
export function parseAircraft(tmdFileContent) {
|
|
215
252
|
const tags = parseTmdLine(tmdFileContent, "Tags").trim().split(" ");
|
|
216
253
|
|
|
217
254
|
// type: ;
|
|
@@ -258,14 +295,14 @@ export const parseAircraft = (tmdFileContent) => {
|
|
|
258
295
|
operatingEmptyMassKg: Number(parseTmdLine(tmdFileContent, "OperatingEmptyMass")) || undefined,
|
|
259
296
|
maximumPersonsOnBoard: Number(parseTmdLine(tmdFileContent, "MaximumPersonsOnBoard")) || undefined,
|
|
260
297
|
};
|
|
261
|
-
}
|
|
298
|
+
}
|
|
262
299
|
|
|
263
300
|
/**
|
|
264
301
|
*
|
|
265
302
|
* @param {string} tmdFileContent
|
|
266
303
|
* @returns {string[]}
|
|
267
304
|
*/
|
|
268
|
-
|
|
305
|
+
function parseRequirements(tmdFileContent) {
|
|
269
306
|
const requirements = parseTmdLine(tmdFileContent, "Requirements").trim();
|
|
270
307
|
if (requirements === "") {
|
|
271
308
|
return [];
|
|
@@ -274,7 +311,7 @@ const parseRequirements = (tmdFileContent) => {
|
|
|
274
311
|
.split(" ")
|
|
275
312
|
.map((req) => req.trim())
|
|
276
313
|
.filter((req) => req !== "");
|
|
277
|
-
}
|
|
314
|
+
}
|
|
278
315
|
|
|
279
316
|
/**
|
|
280
317
|
*
|
|
@@ -282,45 +319,45 @@ const parseRequirements = (tmdFileContent) => {
|
|
|
282
319
|
* @param {string} key
|
|
283
320
|
* @returns {string}
|
|
284
321
|
*/
|
|
285
|
-
export
|
|
322
|
+
export function parseTmdLine(tmdFileContent, key) {
|
|
286
323
|
const r = new RegExp("\\[" + key + "\\]\\s*\\[(.+?)\\]");
|
|
287
324
|
const match = tmdFileContent.match(r);
|
|
288
325
|
return match && match[1] ? match[1] : "";
|
|
289
|
-
}
|
|
326
|
+
}
|
|
290
327
|
|
|
291
328
|
/**
|
|
292
329
|
*
|
|
293
330
|
* @param {string} speed in m/s
|
|
294
331
|
* @returns {number} in kts
|
|
295
332
|
*/
|
|
296
|
-
export
|
|
333
|
+
export function convertSpeed(speed) {
|
|
297
334
|
return Math.round(Number(speed) * 1.94384449);
|
|
298
|
-
}
|
|
335
|
+
}
|
|
299
336
|
|
|
300
337
|
/**
|
|
301
338
|
*
|
|
302
339
|
* @param {string} altitude in m
|
|
303
340
|
* @returns {number} in ft
|
|
304
341
|
*/
|
|
305
|
-
export
|
|
342
|
+
export function convertAltitude(altitude) {
|
|
306
343
|
return Math.round(Number(altitude) * 3.28084);
|
|
307
|
-
}
|
|
344
|
+
}
|
|
308
345
|
|
|
309
346
|
/**
|
|
310
347
|
*
|
|
311
348
|
* @param {string} range in m
|
|
312
349
|
* @returns {number} in NM
|
|
313
350
|
*/
|
|
314
|
-
export
|
|
351
|
+
export function convertDistance(range) {
|
|
315
352
|
return Math.round(Number(range) / 1852);
|
|
316
|
-
}
|
|
353
|
+
}
|
|
317
354
|
|
|
318
355
|
/**
|
|
319
356
|
*
|
|
320
357
|
* @param {AeroflyAircraft[]} sortedAircraft
|
|
321
358
|
* @returns {string}
|
|
322
359
|
*/
|
|
323
|
-
export
|
|
360
|
+
export function getSelectOptions(sortedAircraft) {
|
|
324
361
|
const selectContent = sortedAircraft
|
|
325
362
|
.map((aircraft) => {
|
|
326
363
|
return ` <option value="${aircraft.aeroflyCode}">${aircraft.nameFull}</option>`;
|
|
@@ -332,14 +369,14 @@ export const getSelectOptions = (sortedAircraft) => {
|
|
|
332
369
|
${selectContent}
|
|
333
370
|
</select>
|
|
334
371
|
`;
|
|
335
|
-
}
|
|
372
|
+
}
|
|
336
373
|
|
|
337
374
|
/**
|
|
338
375
|
*
|
|
339
376
|
* @param {AeroflyAircraft[]} sortedAircraft
|
|
340
377
|
* @returns {string}
|
|
341
378
|
*/
|
|
342
|
-
export
|
|
379
|
+
export function getSelectOptgroupOptions(sortedAircraft) {
|
|
343
380
|
/**
|
|
344
381
|
* @type {{
|
|
345
382
|
* [key: string]: {
|
|
@@ -427,14 +464,14 @@ export const getSelectOptgroupOptions = (sortedAircraft) => {
|
|
|
427
464
|
${html}\
|
|
428
465
|
</select>
|
|
429
466
|
`;
|
|
430
|
-
}
|
|
467
|
+
}
|
|
431
468
|
|
|
432
469
|
/**
|
|
433
470
|
*
|
|
434
471
|
* @param {AeroflyAircraft[]} sortedAircraft
|
|
435
472
|
* @returns {string}
|
|
436
473
|
*/
|
|
437
|
-
export
|
|
474
|
+
export function getSelectLiveryOptgroupOptions(sortedAircraft) {
|
|
438
475
|
let html = "";
|
|
439
476
|
for (const aircraft of sortedAircraft) {
|
|
440
477
|
if (aircraft.liveries.length === 0) {
|
|
@@ -452,12 +489,12 @@ export const getSelectLiveryOptgroupOptions = (sortedAircraft) => {
|
|
|
452
489
|
${html}\
|
|
453
490
|
</select>
|
|
454
491
|
`;
|
|
455
|
-
}
|
|
492
|
+
}
|
|
456
493
|
|
|
457
494
|
/**
|
|
458
495
|
* @param {AeroflyAircraft[]} sortedAircraft
|
|
459
496
|
* @returns {string[]}
|
|
460
497
|
*/
|
|
461
|
-
export
|
|
498
|
+
export function getTags(sortedAircraft) {
|
|
462
499
|
return [...new Set(sortedAircraft.flatMap((aircraft) => aircraft.tags))].sort();
|
|
463
|
-
}
|
|
500
|
+
}
|
package/src/airport-functions.js
CHANGED
|
@@ -10,7 +10,7 @@ import * as path from "path";
|
|
|
10
10
|
* @param {number|undefined} length in Bytes
|
|
11
11
|
* @returns {string}
|
|
12
12
|
*/
|
|
13
|
-
export
|
|
13
|
+
export function geoJsonType(type, isMilitary, length) {
|
|
14
14
|
if (type === "heliport" && length !== undefined && length > 0) {
|
|
15
15
|
return type;
|
|
16
16
|
}
|
|
@@ -35,14 +35,14 @@ export const geoJsonType = (type, isMilitary, length) => {
|
|
|
35
35
|
}
|
|
36
36
|
|
|
37
37
|
return type;
|
|
38
|
-
}
|
|
38
|
+
}
|
|
39
39
|
|
|
40
40
|
/**
|
|
41
41
|
*
|
|
42
42
|
* @param {string} directory
|
|
43
43
|
* @returns {Map<string,number>}
|
|
44
44
|
*/
|
|
45
|
-
export
|
|
45
|
+
export function getAeroflyAirports(directory) {
|
|
46
46
|
const aeroflyAirports = new Map();
|
|
47
47
|
let maxLength = 0;
|
|
48
48
|
let minLength = 10000;
|
|
@@ -61,14 +61,14 @@ export const getAeroflyAirports = (directory) => {
|
|
|
61
61
|
}
|
|
62
62
|
|
|
63
63
|
return aeroflyAirports;
|
|
64
|
-
}
|
|
64
|
+
}
|
|
65
65
|
|
|
66
66
|
/**
|
|
67
67
|
*
|
|
68
68
|
* @param {string} filename
|
|
69
69
|
* @returns {Map<string,number>}
|
|
70
70
|
*/
|
|
71
|
-
export
|
|
71
|
+
export function addCustomAeroflyAirportsToMap(filename) {
|
|
72
72
|
const aeroflyAirports = new Map();
|
|
73
73
|
const fileContent = fs.readFileSync(filename, "utf-8");
|
|
74
74
|
const lines = fileContent.split(/\r?\n/).sort();
|
|
@@ -81,7 +81,7 @@ export const addCustomAeroflyAirportsToMap = (filename) => {
|
|
|
81
81
|
}
|
|
82
82
|
|
|
83
83
|
return aeroflyAirports;
|
|
84
|
-
}
|
|
84
|
+
}
|
|
85
85
|
|
|
86
86
|
/**
|
|
87
87
|
*
|
|
@@ -90,7 +90,7 @@ export const addCustomAeroflyAirportsToMap = (filename) => {
|
|
|
90
90
|
* @param {string[]} airportsRecord
|
|
91
91
|
* @returns {string[]}
|
|
92
92
|
*/
|
|
93
|
-
export
|
|
93
|
+
export function getAirportSearchWords(ident, icaoCode, airportsRecord) {
|
|
94
94
|
/**
|
|
95
95
|
* @type {string[]}
|
|
96
96
|
*/
|
|
@@ -109,4 +109,4 @@ export const getAirportSearchWords = (ident, icaoCode, airportsRecord) => {
|
|
|
109
109
|
...airportsRecord[18].split(/,\s*/),
|
|
110
110
|
...extraWords,
|
|
111
111
|
].filter((word) => word && word.length > 0);
|
|
112
|
-
}
|
|
112
|
+
}
|