@fboes/aerofly-custom-missions 1.2.2 → 1.3.0

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.
Files changed (52) hide show
  1. package/.editorconfig +1 -5
  2. package/.eslintrc.json +24 -0
  3. package/CHANGELOG.md +59 -21
  4. package/dist/dto/AeroflyLocalizedText.js +44 -0
  5. package/dist/dto/AeroflyMission.js +173 -0
  6. package/dist/dto/AeroflyMissionCheckpoint.js +127 -0
  7. package/dist/dto/AeroflyMissionConditions.js +124 -0
  8. package/dist/dto/AeroflyMissionConditionsCloud.js +90 -0
  9. package/dist/dto/AeroflyMissionTargetPlane.js +35 -0
  10. package/dist/dto/AeroflyMissionsList.js +36 -0
  11. package/dist/index.js +7 -634
  12. package/dist/index.test.js +17 -11
  13. package/dist/node/AeroflyConfigurationNode.js +82 -0
  14. package/docs/custom_missions_user.tmc +3 -6
  15. package/docs/custom_missions_user.xml +100 -0
  16. package/package.json +9 -10
  17. package/src/dto/AeroflyLocalizedText.ts +74 -0
  18. package/src/dto/AeroflyMission.ts +372 -0
  19. package/src/dto/AeroflyMissionCheckpoint.ts +234 -0
  20. package/src/dto/AeroflyMissionConditions.ts +189 -0
  21. package/src/dto/AeroflyMissionConditionsCloud.ts +111 -0
  22. package/src/dto/AeroflyMissionTargetPlane.ts +62 -0
  23. package/src/dto/AeroflyMissionsList.ts +52 -0
  24. package/src/index.test.ts +22 -25
  25. package/src/index.ts +7 -1099
  26. package/src/node/AeroflyConfigurationNode.ts +89 -0
  27. package/types/AeroflyMissionCheckpoint.d.ts +140 -0
  28. package/types/AeroflyMissionTargetPlane.d.ts +40 -0
  29. package/types/dto/AeroflyConfigFileSet.d.ts +10 -0
  30. package/types/dto/AeroflyConfigFileSet.d.ts.map +1 -0
  31. package/types/dto/AeroflyConfiguration.interface.d.ts +4 -0
  32. package/types/dto/AeroflyConfiguration.interface.d.ts.map +1 -0
  33. package/types/dto/AeroflyLocalizedText.d.ts +58 -0
  34. package/types/dto/AeroflyLocalizedText.d.ts.map +1 -0
  35. package/types/dto/AeroflyMission.d.ts +163 -0
  36. package/types/dto/AeroflyMission.d.ts.map +1 -0
  37. package/types/dto/AeroflyMissionCheckpoint.d.ts +126 -0
  38. package/types/dto/AeroflyMissionCheckpoint.d.ts.map +1 -0
  39. package/types/dto/AeroflyMissionConditions.d.ts +102 -0
  40. package/types/dto/AeroflyMissionConditions.d.ts.map +1 -0
  41. package/types/dto/AeroflyMissionConditionsCloud.d.ts +57 -0
  42. package/types/dto/AeroflyMissionConditionsCloud.d.ts.map +1 -0
  43. package/types/dto/AeroflyMissionTargetPlane.d.ts +45 -0
  44. package/types/dto/AeroflyMissionTargetPlane.d.ts.map +1 -0
  45. package/types/dto/AeroflyMissionsList.d.ts +30 -0
  46. package/types/dto/AeroflyMissionsList.d.ts.map +1 -0
  47. package/types/dto/basicTypes.d.ts +1 -0
  48. package/types/index.d.ts +7 -585
  49. package/types/index.d.ts.map +1 -1
  50. package/types/node/AeroflyConfigurationNode.d.ts +14 -0
  51. package/types/node/AeroflyConfigurationNode.d.ts.map +1 -0
  52. package/eslint.config.js +0 -29
package/dist/index.js CHANGED
@@ -1,634 +1,7 @@
1
- var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
2
- if (kind === "m") throw new TypeError("Private method is not writable");
3
- if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
4
- if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
5
- return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
6
- };
7
- var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
8
- if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
9
- if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
10
- return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
11
- };
12
- var _AeroflyConfigFileSet_indent;
13
- const feetPerMeter = 3.28084;
14
- const meterPerStatuteMile = 1609.344;
15
- export class AeroflyConfigFileSet {
16
- constructor(indent, type, name, value = "") {
17
- _AeroflyConfigFileSet_indent.set(this, void 0);
18
- __classPrivateFieldSet(this, _AeroflyConfigFileSet_indent, indent, "f");
19
- this.elements = [`${this.indent}<[${type}][${name}][${value}]`];
20
- }
21
- get indent() {
22
- return " ".repeat(__classPrivateFieldGet(this, _AeroflyConfigFileSet_indent, "f"));
23
- }
24
- push(type, name, value, comment = "") {
25
- if (value instanceof Array) {
26
- value = value.join(" ");
27
- }
28
- else if (typeof value === "boolean") {
29
- value = value ? "true" : "false";
30
- }
31
- let tag = `${this.indent} <[${type}][${name}][${value}]>`;
32
- if (comment) {
33
- tag += ` // ${comment}`;
34
- }
35
- return this.pushRaw(tag);
36
- }
37
- pushRaw(s) {
38
- this.elements.push(s);
39
- return this;
40
- }
41
- toString() {
42
- return this.elements.join("\n") + "\n" + `${this.indent}>`;
43
- }
44
- }
45
- _AeroflyConfigFileSet_indent = new WeakMap();
46
- /**
47
- * @class
48
- * A list of flight plans.
49
- *
50
- * The purpose of this class is to collect data needed for Aerofly FS4's
51
- * `custom_missions_user.tmc` flight plan file format, and export the structure
52
- * for this file via the `toString()` method.
53
- */
54
- export class AeroflyMissionsList {
55
- /**
56
- * @param {AeroflyMission[]} missions in this mission list
57
- */
58
- constructor(missions = []) {
59
- this.missions = missions;
60
- }
61
- /**
62
- * @returns {string} to use in Aerofly FS4's `custom_missions_user.tmc`
63
- */
64
- toString() {
65
- const separator = "\n// -----------------------------------------------------------------------------\n";
66
- return `\
67
- <[file][][]
68
- <[tmmissions_list][][]
69
- <[list_tmmission_definition][missions][]${separator + this.missions.join(separator) + separator} >
70
- >
71
- >`;
72
- }
73
- }
74
- /**
75
- * @class
76
- * A single flighplan, containing aircraft and weather data as well.
77
- *
78
- * The purpose of this class is to collect data needed for Aerofly FS4's
79
- * `custom_missions_user.tmc` flight plan file format, and export the structure
80
- * for this file via the `toString()` method.
81
- */
82
- export class AeroflyMission {
83
- /**
84
- * @param {string} title of this flight plan
85
- * @param {object} [additionalAttributes] allows to set additional attributes on creation
86
- * @param {string} [additionalAttributes.description] text, mission briefing, etc
87
- * @param {AeroflyLocalizedText[]} [additionalAttributes.localizedTexts] translations for title and description
88
- * @param {?string} [additionalAttributes.tutorialName] will create a link to a tutorial page at https://www.aerofly.com/aircraft-tutorials/
89
- * @param {string[]} [additionalAttributes.tags]
90
- * @param {?boolean} [additionalAttributes.isFeatured] makes this mission pop up in "Challenges"
91
- * @param {?number} [additionalAttributes.difficulty] values between 0.00 and 2.00 have been encountered, but they seem to be without limit
92
- * @param {"cold_and_dark"|"before_start"|"taxi"|"takeoff"|"cruise"|"approach"|"landing"|"winch_launch"|"aerotow"|"pushback"} [additionalAttributes.flightSetting] of aircraft, like "taxi", "cruise"
93
- * @param {{name:string,livery:string,icao:string}} [additionalAttributes.aircraft] for this mission
94
- * @param {string} [additionalAttributes.callsign] of aircraft, uppercased
95
- * @param {object} [additionalAttributes.origin] position of aircraft, as well as name of starting airport. Position does not have match airport.
96
- * @param {object} [additionalAttributes.destination] position of aircraft, as well as name of destination airport. Position does not have match airport.
97
- * @param {?number} [additionalAttributes.distance] in meters
98
- * @param {?number} [additionalAttributes.duration] in seconds
99
- * @param {?boolean} [additionalAttributes.isScheduled] marks this flight as "Scheduled flight".
100
- * @param {?AeroflyMissionTargetPlane} [additionalAttributes.finish] as finish condition
101
- * @param {AeroflyMissionConditions} [additionalAttributes.conditions] like time and weather for mission
102
- * @param {AeroflyMissionCheckpoint[]} [additionalAttributes.checkpoints] form the actual flight plan
103
- */
104
- constructor(title, { tutorialName = null, description = "", localizedTexts = [], tags = [], isFeatured = null, difficulty = null, flightSetting = "taxi", aircraft = {
105
- name: "c172",
106
- icao: "",
107
- livery: "",
108
- }, callsign = "", origin = {
109
- icao: "",
110
- longitude: 0,
111
- latitude: 0,
112
- dir: 0,
113
- alt: 0,
114
- }, destination = {
115
- icao: "",
116
- longitude: 0,
117
- latitude: 0,
118
- dir: 0,
119
- alt: 0,
120
- }, distance = null, duration = null, isScheduled = null, finish = null, conditions = new AeroflyMissionConditions(), checkpoints = [], } = {}) {
121
- this.tutorialName = tutorialName;
122
- this.title = title;
123
- this.checkpoints = checkpoints;
124
- this.description = description;
125
- this.localizedTexts = localizedTexts;
126
- this.tags = tags;
127
- this.isFeatured = isFeatured;
128
- this.difficulty = difficulty;
129
- this.flightSetting = flightSetting;
130
- this.aircraft = aircraft;
131
- this.callsign = callsign;
132
- this.origin = origin;
133
- this.destination = destination;
134
- this.distance = distance;
135
- this.duration = duration;
136
- this.isScheduled = isScheduled;
137
- this.finish = finish;
138
- this.conditions = conditions;
139
- }
140
- /**
141
- * @returns {string} indexed checkpoints
142
- */
143
- getCheckpointsString() {
144
- return this.checkpoints
145
- .map((c, index) => {
146
- return c.toString(index);
147
- })
148
- .join("\n");
149
- }
150
- /**
151
- * @returns {string} indexed checkpoints
152
- */
153
- getLocalizedTextsString() {
154
- return this.localizedTexts
155
- .map((c, index) => {
156
- return c.toString(index);
157
- })
158
- .join("\n");
159
- }
160
- /**
161
- * @throws {Error} on missing waypoints
162
- * @returns {string} to use in Aerofly FS4's `custom_missions_user.tmc`
163
- */
164
- toString() {
165
- if (!this.origin.icao) {
166
- const firstCheckpoint = this.checkpoints[0];
167
- this.origin = {
168
- icao: firstCheckpoint.name,
169
- longitude: firstCheckpoint.longitude,
170
- latitude: firstCheckpoint.latitude,
171
- dir: this.origin.dir,
172
- alt: firstCheckpoint.altitude,
173
- };
174
- }
175
- if (!this.destination.icao) {
176
- const lastCheckpoint = this.checkpoints[this.checkpoints.length - 1];
177
- this.destination = {
178
- icao: lastCheckpoint.name,
179
- longitude: lastCheckpoint.longitude,
180
- latitude: lastCheckpoint.latitude,
181
- dir: lastCheckpoint.direction ?? 0,
182
- alt: lastCheckpoint.altitude,
183
- };
184
- }
185
- const fileSet = new AeroflyConfigFileSet(3, "tmmission_definition", "mission");
186
- fileSet.push("string8", "title", this.title);
187
- fileSet.push("string8", "description", this.description);
188
- if (this.tutorialName !== null) {
189
- fileSet.push("string8", "tutorial_name", this.tutorialName, `Opens https://www.aerofly.com/aircraft-tutorials/${this.tutorialName}`);
190
- }
191
- if (this.localizedTexts.length > 0) {
192
- fileSet.pushRaw(new AeroflyConfigFileSet(4, "list_tmmission_definition_localized", "localized_text")
193
- .pushRaw(this.getLocalizedTextsString())
194
- .toString());
195
- }
196
- if (this.tags.length > 0) {
197
- fileSet.push("string8u", "tags", this.tags.join(" "));
198
- }
199
- if (this.difficulty !== null) {
200
- fileSet.push("float64", "difficulty", this.difficulty);
201
- }
202
- if (this.isFeatured !== null) {
203
- fileSet.push("bool", "is_featured", this.isFeatured);
204
- }
205
- fileSet.push("string8", "flight_setting", this.flightSetting);
206
- fileSet.push("string8u", "aircraft_name", this.aircraft.name);
207
- /*if (this.aircraft.livery) {
208
- fileSet.push("string8", "aircraft_livery", this.aircraft.livery);
209
- }*/
210
- fileSet.push("stringt8c", "aircraft_icao", this.aircraft.icao);
211
- fileSet.push("stringt8c", "callsign", this.callsign);
212
- fileSet.push("stringt8c", "origin_icao", this.origin.icao);
213
- fileSet.push("tmvector2d", "origin_lon_lat", [this.origin.longitude, this.origin.latitude]);
214
- fileSet.push("float64", "origin_alt", this.origin.alt, `${Math.ceil(this.origin.alt * feetPerMeter)} ft MSL`);
215
- fileSet.push("float64", "origin_dir", this.origin.dir);
216
- fileSet.push("stringt8c", "destination_icao", this.destination.icao);
217
- fileSet.push("tmvector2d", "destination_lon_lat", [this.destination.longitude, this.destination.latitude]);
218
- fileSet.push("float64", "destination_alt", this.destination.alt, `${Math.ceil(this.destination.alt * feetPerMeter)} ft MSL`);
219
- fileSet.push("float64", "destination_dir", this.destination.dir);
220
- if (this.distance !== null) {
221
- fileSet.push("float64", "distance", this.distance, `${Math.round(this.distance / 1000)} km`);
222
- }
223
- if (this.duration !== null) {
224
- fileSet.push("float64", "duration", this.duration, `${Math.round(this.duration / 60)} min`);
225
- }
226
- if (this.isScheduled !== null) {
227
- fileSet.push("bool", "is_scheduled", this.isScheduled ? "true" : "false");
228
- }
229
- if (this.finish !== null) {
230
- fileSet.pushRaw(this.finish.toString());
231
- }
232
- fileSet.pushRaw(this.conditions.toString());
233
- if (this.checkpoints.length > 0) {
234
- fileSet.pushRaw(new AeroflyConfigFileSet(4, "list_tmmission_checkpoint", "checkpoints")
235
- .pushRaw(this.getCheckpointsString())
236
- .toString());
237
- }
238
- return fileSet.toString();
239
- }
240
- }
241
- /**
242
- * @class
243
- * Time and weather data for the given flight plan
244
- *
245
- * The purpose of this class is to collect data needed for Aerofly FS4's
246
- * `custom_missions_user.tmc` flight plan file format, and export the structure
247
- * for this file via the `toString()` method.
248
- */
249
- export class AeroflyMissionConditions {
250
- /**
251
- * @param {object} additionalAttributes allows to set additional attributes on creation
252
- * @param {Date} [additionalAttributes.time] of flight plan. Relevant is the UTC part, so
253
- * consider setting this date in UTC.
254
- * @param {{direction: number, speed: number, gusts: number}} [additionalAttributes.wind] state
255
- * @param {number} [additionalAttributes.turbulenceStrength] 0..1, percentage
256
- * @param {number} [additionalAttributes.thermalStrength] 0..1, percentage
257
- * @param {number} [additionalAttributes.visibility] in meters
258
- * @param {?number} [additionalAttributes.visibility_sm] in statute miles, will overwrite visibility
259
- * @param {?number} [additionalAttributes.temperature] in °C, will overwrite thermalStrength
260
- * @param {AeroflyMissionConditionsCloud[]} [additionalAttributes.clouds] for the whole flight
261
- */
262
- constructor({ time = new Date(), wind = {
263
- direction: 0,
264
- speed: 0,
265
- gusts: 0,
266
- }, turbulenceStrength = 0, thermalStrength = 0, visibility = 25000, visibility_sm = null, temperature = null, clouds = [], } = {}) {
267
- /**
268
- * @property {AeroflyMissionConditionsCloud[]} clouds for the whole flight
269
- */
270
- this.clouds = [];
271
- this.time = time;
272
- this.wind = wind;
273
- this.turbulenceStrength = turbulenceStrength;
274
- this.thermalStrength = thermalStrength;
275
- this.visibility = visibility;
276
- this.clouds = clouds;
277
- if (visibility_sm) {
278
- this.visibility_sm = visibility_sm;
279
- }
280
- if (temperature) {
281
- this.temperature = temperature;
282
- }
283
- }
284
- /**
285
- * @returns {number} the Aerofly value for UTC hours + minutes/60 + seconds/3600. Ignores milliseconds ;)
286
- */
287
- get time_hours() {
288
- return this.time.getUTCHours() + this.time.getUTCMinutes() / 60 + this.time.getUTCSeconds() / 3600;
289
- }
290
- /**
291
- * @returns {string} Time representation like "20:15:00"
292
- */
293
- get time_presentational() {
294
- return [this.time.getUTCHours(), this.time.getUTCMinutes(), this.time.getUTCSeconds()]
295
- .map((t) => {
296
- return String(t).padStart(2, "0");
297
- })
298
- .join(":");
299
- }
300
- /**
301
- * @param {number} visibility_sm `this.visibility` in statute miles instead of meters
302
- */
303
- set visibility_sm(visibility_sm) {
304
- this.visibility = visibility_sm * meterPerStatuteMile;
305
- }
306
- /**
307
- * @returns {number} `this.visibility` in statute miles instead of meters
308
- */
309
- get visibility_sm() {
310
- return this.visibility / meterPerStatuteMile;
311
- }
312
- /**
313
- * Will set `this.thermalStrength`
314
- * @param {number} temperature in °C
315
- */
316
- set temperature(temperature) {
317
- // Range from -15°C to 35°C
318
- this.thermalStrength = Math.max(0, (temperature + 15) / 50) ** 2;
319
- }
320
- /**
321
- * @returns {number} in °C
322
- */
323
- get temperature() {
324
- return Math.sqrt(this.thermalStrength) * 50 - 15;
325
- }
326
- /**
327
- * @returns {string}
328
- */
329
- getCloudsString() {
330
- return this.clouds
331
- .map((c, index) => {
332
- return c.toString(index);
333
- })
334
- .join("\n");
335
- }
336
- /**
337
- * @returns {string} to use in Aerofly FS4's `custom_missions_user.tmc`
338
- */
339
- toString() {
340
- if (this.clouds.length < 1) {
341
- this.clouds = [new AeroflyMissionConditionsCloud(0, 0)];
342
- }
343
- return new AeroflyConfigFileSet(4, "tmmission_conditions", "conditions")
344
- .pushRaw(new AeroflyConfigFileSet(5, "tm_time_utc", "time")
345
- .push("int32", "time_year", this.time.getUTCFullYear())
346
- .push("int32", "time_month", this.time.getUTCMonth() + 1)
347
- .push("int32", "time_day", this.time.getUTCDate())
348
- .push("float64", "time_hours", this.time_hours, `${this.time_presentational} UTC`)
349
- .toString())
350
- .push("float64", "wind_direction", this.wind.direction)
351
- .push("float64", "wind_speed", this.wind.speed, "kts")
352
- .push("float64", "wind_gusts", this.wind.gusts, "kts")
353
- .push("float64", "turbulence_strength", this.turbulenceStrength)
354
- .push("float64", "thermal_strength", this.thermalStrength, `${this.temperature} °C`)
355
- .push("float64", "visibility", this.visibility, `${this.visibility_sm} SM`)
356
- .pushRaw(this.getCloudsString())
357
- .toString();
358
- }
359
- }
360
- /**
361
- * @class
362
- * A cloud layer for the current flight plan's weather data
363
- *
364
- * The purpose of this class is to collect data needed for Aerofly FS4's
365
- * `custom_missions_user.tmc` flight plan file format, and export the structure
366
- * for this file via the `toString()` method.
367
- */
368
- export class AeroflyMissionConditionsCloud {
369
- /**
370
- * @param {number} cover 0..1, percentage
371
- * @param {number} base altitude in meters AGL
372
- */
373
- constructor(cover, base) {
374
- this.cover = cover;
375
- this.base = base;
376
- }
377
- /**
378
- * @param {number} cover 0..1, percentage
379
- * @param {number} base_feet altitude, but in feet AGL instead of meters AGL
380
- * @returns {AeroflyMissionConditionsCloud}
381
- */
382
- static createInFeet(cover, base_feet) {
383
- return new AeroflyMissionConditionsCloud(cover, base_feet / feetPerMeter);
384
- }
385
- /**
386
- * @param {number} base_feet `this.base` in feet instead of meters
387
- */
388
- set base_feet(base_feet) {
389
- this.base = base_feet / feetPerMeter;
390
- }
391
- /**
392
- * @returns {number} `this.base` in feet instead of meters
393
- */
394
- get base_feet() {
395
- return this.base * feetPerMeter;
396
- }
397
- /**
398
- * @returns {string} Cloud coverage as text representation like "OVC" for `this.cover`
399
- */
400
- get cover_code() {
401
- if (this.cover < 1 / 8) {
402
- return "CLR";
403
- }
404
- else if (this.cover <= 2 / 8) {
405
- return "FEW";
406
- }
407
- else if (this.cover <= 4 / 8) {
408
- return "SCT";
409
- }
410
- else if (this.cover <= 7 / 8) {
411
- return "BKN";
412
- }
413
- return "OVC";
414
- }
415
- /**
416
- * @param {number} index if used in an array will se the array index
417
- * @returns {string} to use in Aerofly FS4's `custom_missions_user.tmc`
418
- */
419
- toString(index = 0) {
420
- const getIndexString = (index) => {
421
- switch (index) {
422
- case 0:
423
- return "cloud";
424
- case 1:
425
- return "cirrus";
426
- case 2:
427
- return "cumulus_mediocris";
428
- default:
429
- return "more_clouds";
430
- }
431
- };
432
- const indexString = getIndexString(index);
433
- const comment = index > 1 ? '//' : '';
434
- return `\
435
- ${comment}<[float64][${indexString}_cover][${this.cover ?? 0}]> // ${this.cover_code}
436
- ${comment}<[float64][${indexString}_base][${this.base}]> // ${this.base_feet} ft AGL`;
437
- }
438
- }
439
- /**
440
- * @class
441
- * A single way point for the given flight plan
442
- *
443
- * The purpose of this class is to collect data needed for Aerofly FS4's
444
- * `custom_missions_user.tmc` flight plan file format, and export the structure
445
- * for this file via the `toString()` method.
446
- */
447
- export class AeroflyMissionCheckpoint {
448
- /**
449
- * @param {string} name ICAO code for airport, runway designator, navaid
450
- * designator, fix name, or custom name
451
- * @param {"origin"|"departure_runway"|"departure"|"waypoint"|"arrival"|"approach"|"destination_runway"|"destination"} type Type of checkpoint, like "departure_runway"
452
- * @param {number} longitude easting, using the World Geodetic
453
- * System 1984 (WGS 84) [WGS84] datum, with longitude and latitude units
454
- * of decimal degrees; -180..180
455
- * @param {number} latitude northing, using the World Geodetic
456
- * System 1984 (WGS 84) [WGS84] datum, with longitude and latitude units
457
- * of decimal degrees; -90..90
458
- * @param {object} additionalAttributes allows to set additional attributes on creation
459
- * @param {number} [additionalAttributes.altitude] The height in meters above or below the WGS
460
- * 84 reference ellipsoid
461
- * @param {?number} [additionalAttributes.altitude_feet] The height in feet above or below the WGS
462
- * 84 reference ellipsoid. Will overwrite altitude
463
- * @param {number} [additionalAttributes.altitudeConstraint] The altitude given in `altitude`
464
- * will be interpreted as mandatory flight plan altitude instead of
465
- * suggestion.
466
- * @param {boolean} [additionalAttributes.direction] of runway, in degree
467
- * @param {?number} [additionalAttributes.slope] of runway
468
- * @param {?number} [additionalAttributes.length] of runway, in meters
469
- * @param {?number} [additionalAttributes.length_feet] of runway, in feet. Will overwrite length
470
- * @param {?number} [additionalAttributes.frequency] of runways or navigational aids, in Hz; multiply by 1000 for kHz, 1_000_000 for MHz
471
- * @param {?boolean} [additionalAttributes.flyOver] if waypoint is meant to be flown over
472
- */
473
- constructor(name, type, longitude, latitude, { altitude = 0, altitude_feet = null, altitudeConstraint = null, direction = null, slope = null, length = null, length_feet = null, frequency = null, flyOver = null, } = {}) {
474
- this.type = type;
475
- this.name = name;
476
- this.longitude = longitude;
477
- this.latitude = latitude;
478
- this.altitude = altitude;
479
- this.altitudeConstraint = altitudeConstraint;
480
- this.direction = direction;
481
- this.slope = slope;
482
- this.length = length;
483
- this.frequency = frequency;
484
- this.flyOver = flyOver;
485
- if (altitude_feet) {
486
- this.altitude_feet = altitude_feet;
487
- }
488
- if (length_feet) {
489
- this.length_feet = length_feet;
490
- }
491
- }
492
- /**
493
- * @param {number} altitude_feet
494
- */
495
- set altitude_feet(altitude_feet) {
496
- this.altitude = altitude_feet / feetPerMeter;
497
- }
498
- /**
499
- * @returns {number} altitude_feet
500
- */
501
- get altitude_feet() {
502
- return this.altitude * feetPerMeter;
503
- }
504
- /**
505
- * @param {number} length_feet
506
- */
507
- set length_feet(length_feet) {
508
- this.length = length_feet / feetPerMeter;
509
- }
510
- /**
511
- * @returns {number} length_feet
512
- */
513
- get length_feet() {
514
- return (this.length ?? 0) * feetPerMeter;
515
- }
516
- /**
517
- * @returns {string}
518
- */
519
- get frequency_string() {
520
- if (!this.frequency) {
521
- return "None";
522
- }
523
- if (this.frequency > 1000000) {
524
- return String(this.frequency / 1000000) + " MHz";
525
- }
526
- if (this.frequency > 1000) {
527
- return String(this.frequency / 1000) + " kHz";
528
- }
529
- return String(this.frequency) + " Hz";
530
- }
531
- /**
532
- * @param {number} index if used in an array will se the array index
533
- * @returns {string} to use in Aerofly FS4's `custom_missions_user.tmc`
534
- */
535
- toString(index = 0) {
536
- const fileSet = new AeroflyConfigFileSet(5, "tmmission_checkpoint", "element", String(index))
537
- .push("string8u", "type", this.type)
538
- .push("string8u", "name", this.name)
539
- .push("vector2_float64", "lon_lat", [this.longitude, this.latitude])
540
- .push("float64", "altitude", this.altitude, `${Math.ceil(this.altitude_feet)} ft`)
541
- .push("float64", "direction", this.direction ?? (index === 0 ? -1 : 0))
542
- .push("float64", "slope", this.slope ?? 0);
543
- if (this.altitudeConstraint !== null) {
544
- fileSet.push("bool", "alt_cst", this.altitudeConstraint);
545
- }
546
- if (this.length) {
547
- fileSet.push("float64", "length", this.length ?? 0, `${Math.floor(this.length_feet)} ft`);
548
- }
549
- if (this.frequency) {
550
- fileSet.push("float64", "frequency", this.frequency ?? 0, `${this.frequency_string}`);
551
- }
552
- if (this.flyOver !== null) {
553
- fileSet.push("bool", "fly_over", this.flyOver);
554
- }
555
- return fileSet.toString();
556
- }
557
- }
558
- /**
559
- * @class
560
- * A translation for the mission title and description.
561
- */
562
- export class AeroflyLocalizedText {
563
- /**
564
- * @param {string} language ISO 639-1 like
565
- * - br
566
- * - cn
567
- * - de
568
- * - es
569
- * - fr
570
- * - id
571
- * - it
572
- * - jp
573
- * - kr
574
- * - pl
575
- * - sv
576
- * - tr
577
- * @param {string} title of this flight plan
578
- * @param {string} description text, mission briefing, etc
579
- */
580
- constructor(language, title, description) {
581
- this.language = language;
582
- this.title = title;
583
- this.description = description;
584
- }
585
- /**
586
- * @param {number} index if used in an array will se the array index
587
- * @returns {string} to use in Aerofly FS4's `custom_missions_user.tmc`
588
- */
589
- toString(index = 0) {
590
- return new AeroflyConfigFileSet(4, "tmmission_definition_localized", "element", String(index))
591
- .push("string8u", "language", this.language)
592
- .push("string8", "title", this.title)
593
- .push("string8", "description", this.description)
594
- .toString();
595
- }
596
- }
597
- /**
598
- * @class
599
- * A target plane which the aircraft needs to cross.
600
- */
601
- export class AeroflyMissionTargetPlane {
602
- /**
603
- *
604
- * @param {number} longitude easting, using the World Geodetic
605
- * System 1984 (WGS 84) [WGS84] datum, with longitude and latitude units
606
- * of decimal degrees; -180..180
607
- * @param {number}latitude northing, using the World Geodetic
608
- * System 1984 (WGS 84) [WGS84] datum, with longitude and latitude units
609
- * of decimal degrees; -90..90
610
- * @param {number} dir in degree
611
- * @param {string} name of property
612
- */
613
- constructor(longitude, latitude, dir, name = "finish") {
614
- this.longitude = longitude;
615
- this.latitude = latitude;
616
- this.dir = dir;
617
- this.name = name;
618
- }
619
- toString() {
620
- return new AeroflyConfigFileSet(4, "tmmission_target_plane", this.name)
621
- .push("vector2_float64", "lon_lat", [this.longitude, this.latitude])
622
- .push("float64", "direction", this.dir)
623
- .toString();
624
- }
625
- }
626
- export default {
627
- AeroflyMissionsList,
628
- AeroflyMission,
629
- AeroflyMissionConditions,
630
- AeroflyMissionConditionsCloud,
631
- AeroflyMissionCheckpoint,
632
- AeroflyLocalizedText,
633
- AeroflyMissionTargetPlane,
634
- };
1
+ export { AeroflyLocalizedText } from "./dto/AeroflyLocalizedText.js";
2
+ export { AeroflyMission } from "./dto/AeroflyMission.js";
3
+ export { AeroflyMissionCheckpoint } from "./dto/AeroflyMissionCheckpoint.js";
4
+ export { AeroflyMissionConditions } from "./dto/AeroflyMissionConditions.js";
5
+ export { AeroflyMissionConditionsCloud } from "./dto/AeroflyMissionConditionsCloud.js";
6
+ export { AeroflyMissionsList } from "./dto/AeroflyMissionsList.js";
7
+ export { AeroflyMissionTargetPlane } from "./dto/AeroflyMissionTargetPlane.js";