@fboes/aerofly-custom-missions 1.9.1 → 1.11.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.
- package/CHANGELOG.md +8 -0
- package/README.md +1 -4
- package/dist/dto/AeroflyLocalizedText.js +24 -0
- package/dist/dto/AeroflyMission.js +83 -0
- package/dist/dto/AeroflyMission.test.js +4 -3
- package/dist/dto/AeroflyMissionCheckpoint.js +52 -0
- package/dist/dto/AeroflyMissionConditions.js +25 -4
- package/dist/dto/AeroflyMissionConditionsCloud.js +8 -0
- package/dist/dto/AeroflyMissionTargetPlane.js +20 -0
- package/dist/dto/AeroflyMissionsList.js +4 -0
- package/dist/dto-flight/AeroflyFlight.js +51 -1
- package/dist/dto-flight/AeroflyFlight.test.js +8 -3
- package/dist/dto-flight/AeroflyNavRouteAirports.js +5 -0
- package/dist/dto-flight/AeroflyNavRouteBase.js +20 -0
- package/dist/dto-flight/AeroflyNavRouteRunway.js +13 -0
- package/dist/dto-flight/AeroflyNavRouteTransition.js +17 -0
- package/dist/dto-flight/AeroflyNavRouteWaypoint.js +16 -0
- package/dist/dto-flight/AeroflyNavigationConfig.js +9 -0
- package/dist/dto-flight/AeroflySettingsAircraft.js +16 -0
- package/dist/dto-flight/AeroflySettingsCloud.js +8 -0
- package/dist/dto-flight/AeroflySettingsFlight.js +27 -14
- package/dist/dto-flight/AeroflySettingsFuelLoad.js +18 -0
- package/dist/dto-flight/AeroflySettingsWind.js +19 -5
- package/dist/dto-flight/AeroflyTimeUtc.js +5 -0
- package/dist/node/AeroflyConfigurationNode.js +7 -6
- package/docs/custom_missions_user.json +65 -65
- package/docs/flight.json +10 -8
- package/docs/flight.mcf +1 -1
- package/docs/flight.xml +1 -1
- package/package.json +5 -5
- package/src/dto/AeroflyMission.test.ts +7 -3
- package/src/dto-flight/AeroflyFlight.test.ts +9 -3
- package/src/dto-flight/AeroflyFlight.ts +16 -0
- package/src/dto-flight/AeroflyNavRouteAirports.ts +1 -1
- package/src/dto-flight/AeroflyNavRouteBase.ts +1 -1
- package/src/dto-flight/AeroflyNavRouteRunway.ts +2 -2
- package/src/dto-flight/AeroflyNavRouteTransition.ts +2 -2
- package/src/dto-flight/AeroflyNavRouteWaypoint.ts +1 -1
- package/src/dto-flight/AeroflySettingsFlight.ts +1 -1
- package/src/dto-flight/AeroflySettingsWind.ts +3 -5
- package/src/node/Convert.test.ts +1 -1
- package/tsconfig.json +4 -3
- package/types/dto-flight/AeroflyFlight.d.ts +18 -1
- package/types/dto-flight/AeroflyFlight.d.ts.map +1 -1
- package/types/dto-flight/AeroflyNavRouteAirports.d.ts +1 -1
- package/types/dto-flight/AeroflyNavRouteAirports.d.ts.map +1 -1
- package/types/dto-flight/AeroflyNavRouteBase.d.ts +1 -1
- package/types/dto-flight/AeroflyNavRouteBase.d.ts.map +1 -1
- package/types/dto-flight/AeroflyNavRouteRunway.d.ts +2 -2
- package/types/dto-flight/AeroflyNavRouteRunway.d.ts.map +1 -1
- package/types/dto-flight/AeroflyNavRouteTransition.d.ts +2 -2
- package/types/dto-flight/AeroflyNavRouteTransition.d.ts.map +1 -1
- package/types/dto-flight/AeroflyNavRouteWaypoint.d.ts +1 -1
- package/types/dto-flight/AeroflyNavRouteWaypoint.d.ts.map +1 -1
- package/types/dto-flight/AeroflySettingsFlight.d.ts +1 -1
- package/types/dto-flight/AeroflySettingsFlight.d.ts.map +1 -1
- package/types/dto-flight/AeroflySettingsWind.d.ts +1 -1
- package/types/dto-flight/AeroflySettingsWind.d.ts.map +1 -1
- package/docs/flight-generator-prompt.md +0 -91
- package/docs/flight-mcf.md +0 -7
|
@@ -1,6 +1,24 @@
|
|
|
1
1
|
import { AeroflyConfigurationNode } from "../node/AeroflyConfigurationNode.js";
|
|
2
2
|
import { Convert } from "../node/Convert.js";
|
|
3
3
|
export class AeroflySettingsFuelLoad {
|
|
4
|
+
/**
|
|
5
|
+
* @property {string} aircraft aerofly aircraft name (e.g. "c172")
|
|
6
|
+
*/
|
|
7
|
+
aircraft;
|
|
8
|
+
/**
|
|
9
|
+
* @property {number} fuelMass in kg
|
|
10
|
+
*/
|
|
11
|
+
fuelMass;
|
|
12
|
+
/**
|
|
13
|
+
* @property {number} payloadMass in kg
|
|
14
|
+
*/
|
|
15
|
+
payloadMass;
|
|
16
|
+
/**
|
|
17
|
+
* @property {AeroflySettingsFuelLoadConfiguration} configuration "Keep"
|
|
18
|
+
* to keep the current fuel load configuration, "Invalid" to set an invalid
|
|
19
|
+
* fuel load configuration (e.g. fuel mass exceeds maximum takeoff weight)
|
|
20
|
+
*/
|
|
21
|
+
configuration;
|
|
4
22
|
/**
|
|
5
23
|
* @param {string} aircraft aerofly aircraft name (e.g. "c172")
|
|
6
24
|
* @param {number} fuelMass in kg
|
|
@@ -3,6 +3,22 @@ import { AeroflyConfigurationNode } from "../node/AeroflyConfigurationNode.js";
|
|
|
3
3
|
* @class Represents the wind settings for a mission in Aerofly FS4.
|
|
4
4
|
*/
|
|
5
5
|
export class AeroflySettingsWind {
|
|
6
|
+
/**
|
|
7
|
+
* @property {number} speed_kts in knots
|
|
8
|
+
*/
|
|
9
|
+
speed_kts;
|
|
10
|
+
/**
|
|
11
|
+
* @property {number} directionInDegree in degree
|
|
12
|
+
*/
|
|
13
|
+
directionInDegree;
|
|
14
|
+
/**
|
|
15
|
+
* @property {number} gust_kts in knots
|
|
16
|
+
*/
|
|
17
|
+
gust_kts;
|
|
18
|
+
/**
|
|
19
|
+
* @property {number} temperature_celsius in degree Celsius, e.g. 14 for 14°C
|
|
20
|
+
*/
|
|
21
|
+
temperature_celsius;
|
|
6
22
|
/**
|
|
7
23
|
* @param {number} speed_kts in knots
|
|
8
24
|
* @param {number} directionInDegree in degree
|
|
@@ -39,15 +55,13 @@ export class AeroflySettingsWind {
|
|
|
39
55
|
this.speed_kts = Math.max(0, (strength + 0.5) ** 2 - 0.25) * 8;
|
|
40
56
|
}
|
|
41
57
|
/**
|
|
42
|
-
* @returns {number} the normalized turbulence value [0,1] for this wind, where 0 means no turbulence and 1 means very strong turbulence
|
|
58
|
+
* @returns {number} the normalized turbulence value [0,1] for this wind, where 0 means no turbulence and 1 means very strong turbulence. Wind difference is [0,15] kts.
|
|
43
59
|
*/
|
|
44
60
|
get turbulence() {
|
|
45
|
-
return Math.min(1, this.
|
|
61
|
+
return Math.max(0, Math.min(1, (this.gust_kts - this.speed_kts) / 15));
|
|
46
62
|
}
|
|
47
63
|
set turbulence(turbulence) {
|
|
48
|
-
|
|
49
|
-
this.speed_kts = Math.min(this.speed_kts, totalWindEffect);
|
|
50
|
-
this.gust_kts = Math.min(this.gust_kts, (totalWindEffect - this.speed_kts) * 20);
|
|
64
|
+
this.gust_kts = turbulence * 15 + this.speed_kts;
|
|
51
65
|
}
|
|
52
66
|
/**
|
|
53
67
|
* @returns {number} the normalized thermal activity value [0,1] for this wind, where 0 means no thermal activity and 1 means very strong thermal activity (30°C or more)
|
|
@@ -3,6 +3,11 @@ import { AeroflyConfigurationNode } from "../node/AeroflyConfigurationNode.js";
|
|
|
3
3
|
* @class Represents the UTC time for a mission in Aerofly FS4.
|
|
4
4
|
*/
|
|
5
5
|
export class AeroflyTimeUtc {
|
|
6
|
+
/**
|
|
7
|
+
* @property {Date} time of flight plan. Relevant is the UTC part, so
|
|
8
|
+
* consider setting this date in UTC.
|
|
9
|
+
*/
|
|
10
|
+
time;
|
|
6
11
|
/**
|
|
7
12
|
* @param {Date} time of flight plan. Relevant is the UTC part, so
|
|
8
13
|
* consider setting this date in UTC.
|
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
export class AeroflyConfigurationNode {
|
|
2
|
+
type;
|
|
3
|
+
name;
|
|
4
|
+
value;
|
|
5
|
+
_comment;
|
|
6
|
+
children = [];
|
|
7
|
+
space = "\n";
|
|
2
8
|
constructor(type, name, value = "", _comment = "") {
|
|
3
9
|
this.type = type;
|
|
4
10
|
this.name = name;
|
|
5
11
|
this.value = value;
|
|
6
12
|
this._comment = _comment;
|
|
7
|
-
this.children = [];
|
|
8
|
-
this.space = "\n";
|
|
9
13
|
}
|
|
10
14
|
append(...nodes) {
|
|
11
15
|
this.children.push(...nodes);
|
|
@@ -76,10 +80,7 @@ export class AeroflyConfigurationNode {
|
|
|
76
80
|
}
|
|
77
81
|
}
|
|
78
82
|
export class AeroflyConfigurationNodeSpacer extends AeroflyConfigurationNode {
|
|
79
|
-
|
|
80
|
-
super(...arguments);
|
|
81
|
-
this.space = `\n// ${"-".repeat(77)}\n`;
|
|
82
|
-
}
|
|
83
|
+
space = `\n// ${"-".repeat(77)}\n`;
|
|
83
84
|
}
|
|
84
85
|
export class AeroflyConfigurationNodeComment extends AeroflyConfigurationNode {
|
|
85
86
|
toString(indent = 0) {
|
|
@@ -2,60 +2,6 @@
|
|
|
2
2
|
{
|
|
3
3
|
"tutorialName": "c172",
|
|
4
4
|
"title": "Landing practice #1: Concord / Buchanan Field",
|
|
5
|
-
"checkpoints": [
|
|
6
|
-
{
|
|
7
|
-
"type": "origin",
|
|
8
|
-
"name": "KCCR",
|
|
9
|
-
"longitude": -122.057,
|
|
10
|
-
"latitude": 37.9897,
|
|
11
|
-
"altitude": 8,
|
|
12
|
-
"altitudeConstraint": null,
|
|
13
|
-
"direction": null,
|
|
14
|
-
"slope": null,
|
|
15
|
-
"length": null,
|
|
16
|
-
"frequency": null,
|
|
17
|
-
"flyOver": null
|
|
18
|
-
},
|
|
19
|
-
{
|
|
20
|
-
"type": "departure_runway",
|
|
21
|
-
"name": "19L",
|
|
22
|
-
"longitude": -122.05504061196366,
|
|
23
|
-
"latitude": 37.993168229891225,
|
|
24
|
-
"altitude": 0,
|
|
25
|
-
"altitudeConstraint": null,
|
|
26
|
-
"direction": null,
|
|
27
|
-
"slope": null,
|
|
28
|
-
"length": 844.2959729825288,
|
|
29
|
-
"frequency": null,
|
|
30
|
-
"flyOver": null
|
|
31
|
-
},
|
|
32
|
-
{
|
|
33
|
-
"type": "destination_runway",
|
|
34
|
-
"name": "24",
|
|
35
|
-
"longitude": -70.60730234370952,
|
|
36
|
-
"latitude": 41.399093035543366,
|
|
37
|
-
"altitude": 20,
|
|
38
|
-
"altitudeConstraint": null,
|
|
39
|
-
"direction": null,
|
|
40
|
-
"slope": null,
|
|
41
|
-
"length": 1677.6191463161874,
|
|
42
|
-
"frequency": 108700000,
|
|
43
|
-
"flyOver": null
|
|
44
|
-
},
|
|
45
|
-
{
|
|
46
|
-
"type": "destination",
|
|
47
|
-
"name": "KMVY",
|
|
48
|
-
"longitude": -70.6139,
|
|
49
|
-
"latitude": 41.3934,
|
|
50
|
-
"altitude": 20,
|
|
51
|
-
"altitudeConstraint": null,
|
|
52
|
-
"direction": null,
|
|
53
|
-
"slope": null,
|
|
54
|
-
"length": null,
|
|
55
|
-
"frequency": null,
|
|
56
|
-
"flyOver": false
|
|
57
|
-
}
|
|
58
|
-
],
|
|
59
5
|
"description": "It is a gusty, clear early morning, and you are 8 NM to the north of the towered airport Concord / Buchanan Field (27ft). As the wind is 11 kts from 190°, the main landing runway is 19L (191° / 844m). Fly the pattern and land safely.\n\n- Local tower / CTAF frequency: 123.90\n- Local navigational aids: VOR/DME CCR (117.00) 3.4 NM to the north",
|
|
60
6
|
"localizedTexts": [
|
|
61
7
|
{
|
|
@@ -76,9 +22,9 @@
|
|
|
76
22
|
"livery": "default",
|
|
77
23
|
"icao": "C172"
|
|
78
24
|
},
|
|
79
|
-
"callsign": "N51911",
|
|
80
25
|
"fuelMass": 80,
|
|
81
26
|
"payloadMass": 90,
|
|
27
|
+
"callsign": "N51911",
|
|
82
28
|
"origin": {
|
|
83
29
|
"icao": "KCCR",
|
|
84
30
|
"longitude": -122.0736009331662,
|
|
@@ -103,6 +49,15 @@
|
|
|
103
49
|
"name": "finish"
|
|
104
50
|
},
|
|
105
51
|
"conditions": {
|
|
52
|
+
"time": "2024-06-14T13:15:38.000Z",
|
|
53
|
+
"wind": {
|
|
54
|
+
"direction": 190,
|
|
55
|
+
"speed": 11,
|
|
56
|
+
"gusts": 22
|
|
57
|
+
},
|
|
58
|
+
"turbulenceStrength": 1,
|
|
59
|
+
"thermalStrength": 0.5184,
|
|
60
|
+
"visibility": 14484.096000000001,
|
|
106
61
|
"clouds": [
|
|
107
62
|
{
|
|
108
63
|
"cover": 0.1,
|
|
@@ -116,16 +71,61 @@
|
|
|
116
71
|
"cover": 0.1,
|
|
117
72
|
"base": 2895.599907340803
|
|
118
73
|
}
|
|
119
|
-
]
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
"
|
|
124
|
-
"
|
|
74
|
+
]
|
|
75
|
+
},
|
|
76
|
+
"checkpoints": [
|
|
77
|
+
{
|
|
78
|
+
"type": "origin",
|
|
79
|
+
"name": "KCCR",
|
|
80
|
+
"longitude": -122.057,
|
|
81
|
+
"latitude": 37.9897,
|
|
82
|
+
"altitude": 8,
|
|
83
|
+
"altitudeConstraint": null,
|
|
84
|
+
"direction": null,
|
|
85
|
+
"slope": null,
|
|
86
|
+
"length": null,
|
|
87
|
+
"frequency": null,
|
|
88
|
+
"flyOver": null
|
|
125
89
|
},
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
90
|
+
{
|
|
91
|
+
"type": "departure_runway",
|
|
92
|
+
"name": "19L",
|
|
93
|
+
"longitude": -122.05504061196366,
|
|
94
|
+
"latitude": 37.993168229891225,
|
|
95
|
+
"altitude": 0,
|
|
96
|
+
"altitudeConstraint": null,
|
|
97
|
+
"direction": null,
|
|
98
|
+
"slope": null,
|
|
99
|
+
"length": 844.2959729825288,
|
|
100
|
+
"frequency": null,
|
|
101
|
+
"flyOver": null
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
"type": "destination_runway",
|
|
105
|
+
"name": "24",
|
|
106
|
+
"longitude": -70.60730234370952,
|
|
107
|
+
"latitude": 41.399093035543366,
|
|
108
|
+
"altitude": 20,
|
|
109
|
+
"altitudeConstraint": null,
|
|
110
|
+
"direction": null,
|
|
111
|
+
"slope": null,
|
|
112
|
+
"length": 1677.6191463161874,
|
|
113
|
+
"frequency": 108700000,
|
|
114
|
+
"flyOver": null
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
"type": "destination",
|
|
118
|
+
"name": "KMVY",
|
|
119
|
+
"longitude": -70.6139,
|
|
120
|
+
"latitude": 41.3934,
|
|
121
|
+
"altitude": 20,
|
|
122
|
+
"altitudeConstraint": null,
|
|
123
|
+
"direction": null,
|
|
124
|
+
"slope": null,
|
|
125
|
+
"length": null,
|
|
126
|
+
"frequency": null,
|
|
127
|
+
"flyOver": false
|
|
128
|
+
}
|
|
129
|
+
]
|
|
130
130
|
}
|
|
131
131
|
]
|
package/docs/flight.json
CHANGED
|
@@ -19,13 +19,19 @@
|
|
|
19
19
|
"runway": "",
|
|
20
20
|
"altitude_ft": 9072.275604893097
|
|
21
21
|
},
|
|
22
|
+
"fuelLoadSetting": {
|
|
23
|
+
"aircraft": "c172",
|
|
24
|
+
"fuelMass": 80,
|
|
25
|
+
"payloadMass": 90,
|
|
26
|
+
"configuration": "Keep"
|
|
27
|
+
},
|
|
22
28
|
"timeUtc": {
|
|
23
29
|
"time": "2026-03-01T21:20:36.000Z"
|
|
24
30
|
},
|
|
25
31
|
"wind": {
|
|
26
32
|
"speed_kts": 9.000001126528,
|
|
27
33
|
"directionInDegree": 70,
|
|
28
|
-
"gust_kts":
|
|
34
|
+
"gust_kts": 11.250001126528,
|
|
29
35
|
"temperature_celsius": 23
|
|
30
36
|
},
|
|
31
37
|
"clouds": [
|
|
@@ -124,11 +130,7 @@
|
|
|
124
130
|
],
|
|
125
131
|
"cruiseAltitude_ft": 32000.001024
|
|
126
132
|
},
|
|
127
|
-
"
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
"payloadMass": 90,
|
|
131
|
-
"configuration": "Keep"
|
|
132
|
-
},
|
|
133
|
-
"visibility_meter": 7999.994999999999
|
|
133
|
+
"visibility_meter": 7999.994999999999,
|
|
134
|
+
"_missionTitle": "Mission title",
|
|
135
|
+
"_missionBriefing": "Additional text, which will only be visible internally"
|
|
134
136
|
}
|
package/docs/flight.mcf
CHANGED
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
<[tmsettings_wind][wind][]
|
|
35
35
|
<[float64][strength][0.672604]> // 10 kts
|
|
36
36
|
<[float64][direction_in_degree][70]>
|
|
37
|
-
<[float64][turbulence][0.
|
|
37
|
+
<[float64][turbulence][0.15]> // 12 kts gusts
|
|
38
38
|
<[float64][thermal_activity][0.72]> // 23°C
|
|
39
39
|
>
|
|
40
40
|
<[tmsettings_clouds][clouds][]
|
package/docs/flight.xml
CHANGED
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
<wind type="tmsettings_wind">
|
|
35
35
|
<strength type="float64">0.672604</strength> <!-- 10 kts -->
|
|
36
36
|
<direction_in_degree type="float64">70</direction_in_degree>
|
|
37
|
-
<turbulence type="float64">0.
|
|
37
|
+
<turbulence type="float64">0.15</turbulence> <!-- 12 kts gusts -->
|
|
38
38
|
<thermal_activity type="float64">0.72</thermal_activity> <!-- 23°C -->
|
|
39
39
|
</wind>
|
|
40
40
|
<clouds type="tmsettings_clouds">
|
package/package.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fboes/aerofly-custom-missions",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.11.0",
|
|
4
4
|
"description": "Builder for Aerofly FS4 Custom Missions Files",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"scripts": {
|
|
7
|
-
"test": "node --test
|
|
8
|
-
"test:coverage": "node --test --experimental-test-coverage
|
|
9
|
-
"test:watch": "node --test --watch
|
|
7
|
+
"test": "cd dist && node --test",
|
|
8
|
+
"test:coverage": "cd dist && node --test --experimental-test-coverage",
|
|
9
|
+
"test:watch": "cd dist && node --test --watch",
|
|
10
10
|
"start": "node ./dist/index.js",
|
|
11
11
|
"prettier": "npx prettier --cache --write .",
|
|
12
12
|
"eslint": "npx eslint src/*.ts --fix",
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
"license": "MIT",
|
|
24
24
|
"type": "module",
|
|
25
25
|
"devDependencies": {
|
|
26
|
-
"@types/node": "^20.19.
|
|
26
|
+
"@types/node": "^20.19.43",
|
|
27
27
|
"@typescript-eslint/eslint-plugin": "^7.0.1",
|
|
28
28
|
"@typescript-eslint/parser": "^7.0.1",
|
|
29
29
|
"eslint": "^8.56.0",
|
|
@@ -2,6 +2,7 @@ import { AeroflyMission } from "./AeroflyMission.js";
|
|
|
2
2
|
|
|
3
3
|
import { strict as assert } from "node:assert";
|
|
4
4
|
import fs from "node:fs";
|
|
5
|
+
import path from "node:path";
|
|
5
6
|
import { assertIncludes, assertValidAeroflyStructure } from "../check/TestHelpers.js";
|
|
6
7
|
import { describe, it } from "node:test";
|
|
7
8
|
import { AeroflyLocalizedText } from "./AeroflyLocalizedText.js";
|
|
@@ -190,11 +191,14 @@ Landeübung #1: Concord / Buchanan Field`,
|
|
|
190
191
|
|
|
191
192
|
const file = new AeroflyMissionsList([mission]);
|
|
192
193
|
const fileContent = file.toString();
|
|
193
|
-
fs.writeFileSync("docs/custom_missions_user.tmc", fileContent);
|
|
194
|
+
fs.writeFileSync(path.join(import.meta.dirname, "../..", "docs/custom_missions_user.tmc"), fileContent);
|
|
194
195
|
|
|
195
196
|
const xmlContent = file.toXmlString();
|
|
196
|
-
fs.writeFileSync("docs/custom_missions_user.xml", xmlContent);
|
|
197
|
+
fs.writeFileSync(path.join(import.meta.dirname, "../..", "docs/custom_missions_user.xml"), xmlContent);
|
|
197
198
|
|
|
198
|
-
fs.writeFileSync(
|
|
199
|
+
fs.writeFileSync(
|
|
200
|
+
path.join(import.meta.dirname, "../..", "docs/custom_missions_user.json"),
|
|
201
|
+
JSON.stringify(file, null, 2),
|
|
202
|
+
);
|
|
199
203
|
});
|
|
200
204
|
});
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { describe, it } from "node:test";
|
|
2
2
|
import fs from "node:fs";
|
|
3
|
+
import path from "node:path";
|
|
3
4
|
import { strict as assert } from "node:assert";
|
|
4
5
|
import { assertValidAeroflyStructure } from "../check/TestHelpers.js";
|
|
5
6
|
|
|
@@ -72,16 +73,21 @@ describe("AeroflyFlight", () => {
|
|
|
72
73
|
{
|
|
73
74
|
fuelLoadSetting: new AeroflySettingsFuelLoad("c172", 80, 90, "Keep"),
|
|
74
75
|
visibility: 0.533333,
|
|
76
|
+
_missionTitle: "Mission title",
|
|
77
|
+
_missionBriefing: "Additional text, which will only be visible internally",
|
|
75
78
|
},
|
|
76
79
|
);
|
|
77
80
|
|
|
81
|
+
assert.ok(flight._missionTitle);
|
|
82
|
+
assert.ok(flight._missionBriefing);
|
|
83
|
+
|
|
78
84
|
const fileContent = flight.toString();
|
|
79
|
-
fs.writeFileSync("docs/flight.mcf", fileContent);
|
|
85
|
+
fs.writeFileSync(path.join(import.meta.dirname, "../..", "docs/flight.mcf"), fileContent);
|
|
80
86
|
|
|
81
87
|
const xmlContent = flight.toXmlString();
|
|
82
|
-
fs.writeFileSync("docs/flight.xml", xmlContent);
|
|
88
|
+
fs.writeFileSync(path.join(import.meta.dirname, "../..", "docs/flight.xml"), xmlContent);
|
|
83
89
|
|
|
84
|
-
fs.writeFileSync("docs/flight.json", JSON.stringify(flight, null, 2));
|
|
90
|
+
fs.writeFileSync(path.join(import.meta.dirname, "../..", "docs/flight.json"), JSON.stringify(flight, null, 2));
|
|
85
91
|
|
|
86
92
|
assertValidAeroflyStructure(fileContent);
|
|
87
93
|
assert.ok(fileContent.includes("c172"));
|
|
@@ -49,6 +49,16 @@ export class AeroflyFlight {
|
|
|
49
49
|
*/
|
|
50
50
|
visibility_meter: number;
|
|
51
51
|
|
|
52
|
+
/**
|
|
53
|
+
* @property {string} _missionTitle unofficial property to store mission title in. For internal use only, will not be exported in MCF / XML.
|
|
54
|
+
*/
|
|
55
|
+
_missionTitle: string;
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* @property {string} _missionBriefing unofficial property to store mission briefing in. For internal use only, will not be exported in MCF / XML.
|
|
59
|
+
*/
|
|
60
|
+
_missionBriefing: string;
|
|
61
|
+
|
|
52
62
|
/**
|
|
53
63
|
*
|
|
54
64
|
* @param {AeroflySettingsAircraft} aircraft settings for the mission
|
|
@@ -62,6 +72,8 @@ export class AeroflyFlight {
|
|
|
62
72
|
* @param {number} [options.visibility_meter] visibility in meter, 9999 for unlimited visibility, default is 9999
|
|
63
73
|
* @param {number} [options.visibility] visibility in normalized value [0,1], where 0 means 0 meter visibility and 1 unlimited visibility, default is 0
|
|
64
74
|
* @param {number} [options.visibility_sm] visibility in statute miles, 10 SM for unlimited visibility, default is 0
|
|
75
|
+
* @param {string} [options._missionTitle] unofficial property to store mission title in. For internal use only, will not be exported in MCF / XML.
|
|
76
|
+
* @param {string} [options._missionBriefing] unofficial property to store mission briefing in. For internal use only, will not be exported in MCF / XML.
|
|
65
77
|
*/
|
|
66
78
|
constructor(
|
|
67
79
|
aircraft: AeroflySettingsAircraft,
|
|
@@ -75,6 +87,8 @@ export class AeroflyFlight {
|
|
|
75
87
|
visibility_meter = 9999,
|
|
76
88
|
visibility = 0,
|
|
77
89
|
visibility_sm = 0,
|
|
90
|
+
_missionTitle = "",
|
|
91
|
+
_missionBriefing = "",
|
|
78
92
|
}: Partial<AeroflyFlight> = {},
|
|
79
93
|
) {
|
|
80
94
|
this.aircraft = aircraft;
|
|
@@ -85,6 +99,8 @@ export class AeroflyFlight {
|
|
|
85
99
|
this.navigation = navigation;
|
|
86
100
|
this.fuelLoadSetting = fuelLoadSetting;
|
|
87
101
|
this.visibility_meter = visibility_meter;
|
|
102
|
+
this._missionTitle = _missionTitle;
|
|
103
|
+
this._missionBriefing = _missionBriefing;
|
|
88
104
|
|
|
89
105
|
if (visibility_sm > 0) {
|
|
90
106
|
this.visibility_sm = visibility_sm;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { AeroflyConfigurationNode } from "../node/AeroflyConfigurationNode.js";
|
|
2
2
|
import { Convert } from "../node/Convert.js";
|
|
3
|
-
import { AeroflyNavRouteBase, AeroflyNavRouteType } from "./AeroflyNavRouteBase.js";
|
|
3
|
+
import { AeroflyNavRouteBase, type AeroflyNavRouteType } from "./AeroflyNavRouteBase.js";
|
|
4
4
|
|
|
5
5
|
class AeroflyNavRouteAirport extends AeroflyNavRouteBase {
|
|
6
6
|
/**
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Convert, AeroflyVector3Float } from "../node/Convert.js";
|
|
1
|
+
import { Convert, type AeroflyVector3Float } from "../node/Convert.js";
|
|
2
2
|
import { AeroflyConfigurationNode, AeroflyConfigurationNodeComment } from "../node/AeroflyConfigurationNode.js";
|
|
3
3
|
|
|
4
4
|
export type AeroflyNavRouteType =
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { AeroflyVector3Float, Convert } from "../node/Convert.js";
|
|
1
|
+
import { type AeroflyVector3Float, Convert } from "../node/Convert.js";
|
|
2
2
|
import { AeroflyConfigurationNode } from "../node/AeroflyConfigurationNode.js";
|
|
3
|
-
import { AeroflyNavRouteBase, AeroflyNavRouteType } from "./AeroflyNavRouteBase.js";
|
|
3
|
+
import { AeroflyNavRouteBase, type AeroflyNavRouteType } from "./AeroflyNavRouteBase.js";
|
|
4
4
|
|
|
5
5
|
class AeroflyNavRouteRunway extends AeroflyNavRouteBase {
|
|
6
6
|
/**
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { AeroflyVector3Float, Convert } from "../node/Convert.js";
|
|
1
|
+
import { type AeroflyVector3Float, Convert } from "../node/Convert.js";
|
|
2
2
|
import { AeroflyConfigurationNode } from "../node/AeroflyConfigurationNode.js";
|
|
3
|
-
import { AeroflyNavRouteBase, AeroflyNavRouteType } from "./AeroflyNavRouteBase.js";
|
|
3
|
+
import { AeroflyNavRouteBase, type AeroflyNavRouteType } from "./AeroflyNavRouteBase.js";
|
|
4
4
|
|
|
5
5
|
class AeroflyNavRouteTransition extends AeroflyNavRouteBase {
|
|
6
6
|
/**
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Convert, AeroflyVector3Float } from "../node/Convert.js";
|
|
1
|
+
import { Convert, type AeroflyVector3Float } from "../node/Convert.js";
|
|
2
2
|
import { AeroflyConfigurationNode } from "../node/AeroflyConfigurationNode.js";
|
|
3
3
|
import { AeroflyNavRouteBase } from "./AeroflyNavRouteBase.js";
|
|
4
4
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AeroflyVector3Float, AeroflyMatrix3Float, Convert } from "../node/Convert.js";
|
|
1
|
+
import { type AeroflyVector3Float, type AeroflyMatrix3Float, Convert } from "../node/Convert.js";
|
|
2
2
|
import { AeroflyConfigurationNode } from "../node/AeroflyConfigurationNode.js";
|
|
3
3
|
|
|
4
4
|
export type AeroflySettingsFlightConfiguration =
|
|
@@ -69,16 +69,14 @@ export class AeroflySettingsWind {
|
|
|
69
69
|
}
|
|
70
70
|
|
|
71
71
|
/**
|
|
72
|
-
* @returns {number} the normalized turbulence value [0,1] for this wind, where 0 means no turbulence and 1 means very strong turbulence
|
|
72
|
+
* @returns {number} the normalized turbulence value [0,1] for this wind, where 0 means no turbulence and 1 means very strong turbulence. Wind difference is [0,15] kts.
|
|
73
73
|
*/
|
|
74
74
|
get turbulence(): number {
|
|
75
|
-
return Math.min(1, this.
|
|
75
|
+
return Math.max(0, Math.min(1, (this.gust_kts - this.speed_kts) / 15));
|
|
76
76
|
}
|
|
77
77
|
|
|
78
78
|
set turbulence(turbulence: number) {
|
|
79
|
-
|
|
80
|
-
this.speed_kts = Math.min(this.speed_kts, totalWindEffect);
|
|
81
|
-
this.gust_kts = Math.min(this.gust_kts, (totalWindEffect - this.speed_kts) * 20);
|
|
79
|
+
this.gust_kts = turbulence * 15 + this.speed_kts;
|
|
82
80
|
}
|
|
83
81
|
|
|
84
82
|
/**
|
package/src/node/Convert.test.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { describe, it } from "node:test";
|
|
2
2
|
import { strict as assert } from "node:assert";
|
|
3
3
|
|
|
4
|
-
import { AeroflyMatrix3Float, Convert } from "./Convert.js";
|
|
4
|
+
import { type AeroflyMatrix3Float, Convert } from "./Convert.js";
|
|
5
5
|
|
|
6
6
|
describe("Convert", () => {
|
|
7
7
|
it("should convert feet to meters correctly", () => {
|
package/tsconfig.json
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"compilerOptions": {
|
|
3
|
-
|
|
4
|
-
"target": "es2021",
|
|
3
|
+
"target": "es2022",
|
|
5
4
|
"module": "nodenext",
|
|
6
5
|
"rootDir": "./src",
|
|
7
6
|
"outDir": "./dist",
|
|
@@ -14,6 +13,8 @@
|
|
|
14
13
|
"skipLibCheck": true,
|
|
15
14
|
"declarationMap": true,
|
|
16
15
|
"declaration": true,
|
|
17
|
-
"declarationDir": "./types"
|
|
16
|
+
"declarationDir": "./types",
|
|
17
|
+
"types": ["node"],
|
|
18
|
+
"verbatimModuleSyntax": true
|
|
18
19
|
}
|
|
19
20
|
}
|
|
@@ -40,6 +40,14 @@ export declare class AeroflyFlight {
|
|
|
40
40
|
* @property {number} visibility_meter visibility in meter, 9999 for unlimited visibility
|
|
41
41
|
*/
|
|
42
42
|
visibility_meter: number;
|
|
43
|
+
/**
|
|
44
|
+
* @property {string} _missionTitle unofficial property to store mission title in. For internal use only, will not be exported in MCF / XML.
|
|
45
|
+
*/
|
|
46
|
+
_missionTitle: string;
|
|
47
|
+
/**
|
|
48
|
+
* @property {string} _missionBriefing unofficial property to store mission briefing in. For internal use only, will not be exported in MCF / XML.
|
|
49
|
+
*/
|
|
50
|
+
_missionBriefing: string;
|
|
43
51
|
/**
|
|
44
52
|
*
|
|
45
53
|
* @param {AeroflySettingsAircraft} aircraft settings for the mission
|
|
@@ -53,6 +61,8 @@ export declare class AeroflyFlight {
|
|
|
53
61
|
* @param {number} [options.visibility_meter] visibility in meter, 9999 for unlimited visibility, default is 9999
|
|
54
62
|
* @param {number} [options.visibility] visibility in normalized value [0,1], where 0 means 0 meter visibility and 1 unlimited visibility, default is 0
|
|
55
63
|
* @param {number} [options.visibility_sm] visibility in statute miles, 10 SM for unlimited visibility, default is 0
|
|
64
|
+
* @param {string} [options._missionTitle] unofficial property to store mission title in. For internal use only, will not be exported in MCF / XML.
|
|
65
|
+
* @param {string} [options._missionBriefing] unofficial property to store mission briefing in. For internal use only, will not be exported in MCF / XML.
|
|
56
66
|
*/
|
|
57
67
|
constructor(
|
|
58
68
|
aircraft: AeroflySettingsAircraft,
|
|
@@ -61,7 +71,14 @@ export declare class AeroflyFlight {
|
|
|
61
71
|
wind: AeroflySettingsWind,
|
|
62
72
|
clouds: AeroflySettingsCloud[],
|
|
63
73
|
navigation: AeroflyNavigationConfig,
|
|
64
|
-
{
|
|
74
|
+
{
|
|
75
|
+
fuelLoadSetting,
|
|
76
|
+
visibility_meter,
|
|
77
|
+
visibility,
|
|
78
|
+
visibility_sm,
|
|
79
|
+
_missionTitle,
|
|
80
|
+
_missionBriefing,
|
|
81
|
+
}?: Partial<AeroflyFlight>,
|
|
65
82
|
);
|
|
66
83
|
/**
|
|
67
84
|
* @returns {number} visibility in statute miles, 10 SM for unlimited visibility
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AeroflyFlight.d.ts","sourceRoot":"","sources":["../../src/dto-flight/AeroflyFlight.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,MAAM,8BAA8B,CAAC;AACvE,OAAO,EAAE,uBAAuB,EAAE,MAAM,8BAA8B,CAAC;AACvE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AACjE,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AACnE,OAAO,EAAE,uBAAuB,EAAE,MAAM,8BAA8B,CAAC;AACvE,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAC/D,OAAO,EAAE,wBAAwB,EAAE,MAAM,qCAAqC,CAAC;AAE/E,qBAAa,aAAa;IACtB;;OAEG;IACH,QAAQ,EAAE,uBAAuB,CAAC;IAElC;;OAEG;IACH,aAAa,EAAE,qBAAqB,CAAC;IAErC;;OAEG;IACH,eAAe,EAAE,uBAAuB,CAAC;IAEzC;;OAEG;IACH,OAAO,EAAE,cAAc,CAAC;IAExB;;OAEG;IACH,IAAI,EAAE,mBAAmB,CAAC;IAE1B;;;OAGG;IACH,MAAM,EAAE,oBAAoB,EAAE,CAAC;IAE/B;;OAEG;IACH,UAAU,EAAE,uBAAuB,CAAC;IAEpC;;OAEG;IACH,gBAAgB,EAAE,MAAM,CAAC;IAEzB
|
|
1
|
+
{"version":3,"file":"AeroflyFlight.d.ts","sourceRoot":"","sources":["../../src/dto-flight/AeroflyFlight.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,MAAM,8BAA8B,CAAC;AACvE,OAAO,EAAE,uBAAuB,EAAE,MAAM,8BAA8B,CAAC;AACvE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AACjE,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AACnE,OAAO,EAAE,uBAAuB,EAAE,MAAM,8BAA8B,CAAC;AACvE,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAC/D,OAAO,EAAE,wBAAwB,EAAE,MAAM,qCAAqC,CAAC;AAE/E,qBAAa,aAAa;IACtB;;OAEG;IACH,QAAQ,EAAE,uBAAuB,CAAC;IAElC;;OAEG;IACH,aAAa,EAAE,qBAAqB,CAAC;IAErC;;OAEG;IACH,eAAe,EAAE,uBAAuB,CAAC;IAEzC;;OAEG;IACH,OAAO,EAAE,cAAc,CAAC;IAExB;;OAEG;IACH,IAAI,EAAE,mBAAmB,CAAC;IAE1B;;;OAGG;IACH,MAAM,EAAE,oBAAoB,EAAE,CAAC;IAE/B;;OAEG;IACH,UAAU,EAAE,uBAAuB,CAAC;IAEpC;;OAEG;IACH,gBAAgB,EAAE,MAAM,CAAC;IAEzB;;OAEG;IACH,aAAa,EAAE,MAAM,CAAC;IAEtB;;OAEG;IACH,gBAAgB,EAAE,MAAM,CAAC;IAEzB;;;;;;;;;;;;;;;OAeG;gBAEC,QAAQ,EAAE,uBAAuB,EACjC,aAAa,EAAE,qBAAqB,EACpC,OAAO,EAAE,cAAc,EACvB,IAAI,EAAE,mBAAmB,EACzB,MAAM,EAAE,oBAAoB,EAAE,EAC9B,UAAU,EAAE,uBAAuB,EACnC,EACI,eAA+C,EAC/C,gBAAuB,EACvB,UAAc,EACd,aAAiB,EACjB,aAAkB,EAClB,gBAAqB,GACxB,GAAE,OAAO,CAAC,aAAa,CAAM;IAqBlC;;OAEG;IACH,IAAI,aAAa,IAAI,MAAM,CAE1B;IAED,IAAI,aAAa,CAAC,aAAa,EAAE,MAAM,EAEtC;IAED;;;;OAIG;IACH,IAAI,UAAU,IAAI,MAAM,CAEvB;IAED,IAAI,UAAU,CAAC,UAAU,EAAE,MAAM,EAEhC;IAED;;;;;;;;;OASG;IACH,eAAe,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI;IAS3C;;OAEG;IACH,gBAAgB,IAAI,wBAAwB,EAAE;IAI9C;;OAEG;IACH,gBAAgB,IAAI,wBAAwB;IAI5C,UAAU,IAAI,wBAAwB;IAoBtC;;OAEG;IACH,QAAQ,IAAI,MAAM;IAIlB;;OAEG;IACH,WAAW,IAAI,MAAM;CAGxB"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { AeroflyConfigurationNode } from "../node/AeroflyConfigurationNode.js";
|
|
2
|
-
import { AeroflyNavRouteBase, AeroflyNavRouteType } from "./AeroflyNavRouteBase.js";
|
|
2
|
+
import { AeroflyNavRouteBase, type AeroflyNavRouteType } from "./AeroflyNavRouteBase.js";
|
|
3
3
|
declare class AeroflyNavRouteAirport extends AeroflyNavRouteBase {
|
|
4
4
|
/**
|
|
5
5
|
* @property {number | null} elevation in meters, null if not set
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AeroflyNavRouteAirports.d.ts","sourceRoot":"","sources":["../../src/dto-flight/AeroflyNavRouteAirports.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,wBAAwB,EAAE,MAAM,qCAAqC,CAAC;AAE/E,OAAO,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"AeroflyNavRouteAirports.d.ts","sourceRoot":"","sources":["../../src/dto-flight/AeroflyNavRouteAirports.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,wBAAwB,EAAE,MAAM,qCAAqC,CAAC;AAE/E,OAAO,EAAE,mBAAmB,EAAE,KAAK,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAEzF,cAAM,sBAAuB,SAAQ,mBAAmB;IACpD;;OAEG;IACH,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IAEzB;;;;;;;;;OASG;gBAEC,IAAI,EAAE,mBAAmB,EACzB,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,EAChB,EAAE,SAAgB,EAAE,YAAmB,EAAE,GAAU,EAAE,GAAE,OAAO,CAAC,sBAAsB,CAAM;IAS/F;;OAEG;IACH,IAAI,YAAY,IAAI,MAAM,GAAG,IAAI,CAEhC;IAED,IAAI,YAAY,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI,EAE3C;IAED,UAAU,CAAC,KAAK,GAAE,MAAU,GAAG,wBAAwB;IAavD,MAAM;CAQT;AAED,qBAAa,qBAAsB,SAAQ,sBAAsB;IAC7D;;OAEG;gBAEC,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,EAChB,EAAE,SAAgB,EAAE,YAAmB,EAAE,GAAU,EAAE,GAAE,OAAO,CAAC,qBAAqB,CAAM;CAIjG;AAED,qBAAa,0BAA2B,SAAQ,sBAAsB;IAClE;;OAEG;gBAEC,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,EAChB,EAAE,SAAgB,EAAE,YAAmB,EAAE,GAAU,EAAE,GAAE,OAAO,CAAC,0BAA0B,CAAM;CAItG"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AeroflyNavRouteBase.d.ts","sourceRoot":"","sources":["../../src/dto-flight/AeroflyNavRouteBase.ts"],"names":[],"mappings":"AAAA,OAAO,EAAW,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"AeroflyNavRouteBase.d.ts","sourceRoot":"","sources":["../../src/dto-flight/AeroflyNavRouteBase.ts"],"names":[],"mappings":"AAAA,OAAO,EAAW,KAAK,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACvE,OAAO,EAAE,wBAAwB,EAAmC,MAAM,qCAAqC,CAAC;AAEhH,MAAM,MAAM,mBAAmB,GACzB,QAAQ,GACR,kBAAkB,GAClB,WAAW,GACX,UAAU,GACV,SAAS,GACT,UAAU,GACV,oBAAoB,GACpB,aAAa,CAAC;AAEpB,qBAAa,mBAAmB;IAC5B;;OAEG;IACH,IAAI,EAAE,mBAAmB,CAAC;IAE1B;;OAEG;IACH,UAAU,EAAE,MAAM,CAAC;IAEnB;;OAEG;IACH,SAAS,EAAE,MAAM,CAAC;IAElB;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAC;IAEjB;;OAEG;IACH,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IAEnB;;;;;;;OAOG;gBAEC,IAAI,EAAE,mBAAmB,EACzB,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,EAChB,EAAE,GAAU,EAAE,GAAE,OAAO,CAAC,mBAAmB,CAAM;IASrD;;OAEG;IACH,IAAI,QAAQ,IAAI,mBAAmB,CAElC;IAED,IAAI,QAAQ,CAAC,QAAQ,EAAE,mBAAmB,EAIzC;IAED;;;;OAIG;IACH,WAAW,CAAC,QAAQ,EAAE,mBAAmB,GAAG,IAAI;IAKhD,UAAU,CAAC,KAAK,GAAE,MAAU,GAAG,wBAAwB;IAkBvD,MAAM;;;IAON;;OAEG;IACH,QAAQ,IAAI,MAAM;CAGrB"}
|