@fboes/aerofly-custom-missions 1.3.0 → 1.4.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/.editorconfig +4 -0
- package/AGENTS.md +43 -0
- package/CHANGELOG.md +23 -12
- package/LICENSE.txt +1 -1
- package/README.md +6 -1
- package/dist/check/TestHelpers.js +13 -0
- package/dist/check/TestHelpers.test.js +8 -0
- package/dist/dto/AeroflyLocalizedText.test.js +16 -0
- package/dist/dto/AeroflyMission.js +15 -5
- package/dist/dto/AeroflyMission.test.js +166 -0
- package/dist/dto/AeroflyMissionCheckpoint.js +1 -1
- package/dist/dto/AeroflyMissionCheckpoint.test.js +41 -0
- package/dist/dto/AeroflyMissionConditions.js +4 -6
- package/dist/dto/AeroflyMissionConditions.test.js +33 -0
- package/dist/dto/AeroflyMissionConditionsCloud.js +12 -7
- package/dist/dto/AeroflyMissionConditionsCloud.test.js +25 -0
- package/dist/dto/AeroflyMissionTargetPlane.js +1 -1
- package/dist/dto/AeroflyMissionTargetPlane.test.js +14 -0
- package/dist/dto/AeroflyMissionsList.js +2 -6
- package/dist/dto/AeroflyMissionsList.test.js +16 -0
- package/dist/dto-flight/AeroflyFlight.js +94 -0
- package/dist/dto-flight/AeroflyFlight.test.js +69 -0
- package/dist/dto-flight/AeroflyNavRouteAirports.js +53 -0
- package/dist/dto-flight/AeroflyNavRouteBase.js +54 -0
- package/dist/dto-flight/AeroflyNavRouteRunway.js +70 -0
- package/dist/dto-flight/AeroflyNavRouteTransition.js +75 -0
- package/dist/dto-flight/AeroflyNavRouteWaypoint.js +58 -0
- package/dist/dto-flight/AeroflyNavigationConfig.js +50 -0
- package/dist/dto-flight/AeroflySettingsAircraft.js +28 -0
- package/dist/dto-flight/AeroflySettingsCloud.js +103 -0
- package/dist/dto-flight/AeroflySettingsCloud.test.js +53 -0
- package/dist/dto-flight/AeroflySettingsFlight.js +95 -0
- package/dist/dto-flight/AeroflySettingsFlight.test.js +52 -0
- package/dist/dto-flight/AeroflySettingsFuelLoad.js +30 -0
- package/dist/dto-flight/AeroflySettingsWind.js +74 -0
- package/dist/dto-flight/AeroflyTimeUtc.js +84 -0
- package/dist/dto-flight/AeroflyWaypoint.js +85 -0
- package/dist/index.js +13 -0
- package/dist/node/AeroflyBasicTypes.js +61 -0
- package/dist/node/AeroflyConfigurationNode.js +64 -29
- package/dist/node/AeroflyConfigurationNode.test.js +28 -0
- package/dist/node/Convert copy.js +67 -0
- package/dist/node/Convert.js +72 -0
- package/dist/node/Convert.test.js +50 -0
- package/docs/custom_missions_user.tmc +7 -2
- package/docs/custom_missions_user.xml +6 -4
- package/docs/flight-mcf.md +7 -0
- package/docs/flight.mcf +116 -0
- package/docs/flight.xml +116 -0
- package/package.json +4 -2
- package/src/check/TestHelpers.test.ts +10 -0
- package/src/check/TestHelpers.ts +16 -0
- package/src/dto/AeroflyLocalizedText.test.ts +20 -0
- package/src/dto/AeroflyMission.test.ts +185 -0
- package/src/dto/AeroflyMission.ts +29 -5
- package/src/dto/AeroflyMissionCheckpoint.test.ts +50 -0
- package/src/dto/AeroflyMissionCheckpoint.ts +2 -2
- package/src/dto/AeroflyMissionConditions.test.ts +38 -0
- package/src/dto/AeroflyMissionConditions.ts +5 -7
- package/src/dto/AeroflyMissionConditionsCloud.test.ts +29 -0
- package/src/dto/AeroflyMissionConditionsCloud.ts +23 -8
- package/src/dto/AeroflyMissionTargetPlane.test.ts +15 -0
- package/src/dto/AeroflyMissionTargetPlane.ts +2 -2
- package/src/dto/AeroflyMissionsList.test.ts +19 -0
- package/src/dto/AeroflyMissionsList.ts +3 -7
- package/src/dto-flight/AeroflyFlight.test.ts +87 -0
- package/src/dto-flight/AeroflyFlight.ts +180 -0
- package/src/dto-flight/AeroflyNavRouteAirports.ts +86 -0
- package/src/dto-flight/AeroflyNavRouteBase.ts +109 -0
- package/src/dto-flight/AeroflyNavRouteRunway.ts +123 -0
- package/src/dto-flight/AeroflyNavRouteTransition.ts +127 -0
- package/src/dto-flight/AeroflyNavRouteWaypoint.ts +98 -0
- package/src/dto-flight/AeroflyNavigationConfig.ts +79 -0
- package/src/dto-flight/AeroflySettingsAircraft.ts +51 -0
- package/src/dto-flight/AeroflySettingsCloud.test.ts +68 -0
- package/src/dto-flight/AeroflySettingsCloud.ts +137 -0
- package/src/dto-flight/AeroflySettingsFlight.test.ts +70 -0
- package/src/dto-flight/AeroflySettingsFlight.ts +157 -0
- package/src/dto-flight/AeroflySettingsFuelLoad.ts +62 -0
- package/src/dto-flight/AeroflySettingsWind.ts +114 -0
- package/src/dto-flight/AeroflyTimeUtc.ts +103 -0
- package/src/index.ts +23 -0
- package/src/node/AeroflyConfigurationNode.test.ts +46 -0
- package/src/node/AeroflyConfigurationNode.ts +59 -16
- package/src/node/Convert.test.ts +90 -0
- package/src/node/Convert.ts +90 -0
- package/types/check/TestHelpers.d.ts +3 -0
- package/types/check/TestHelpers.d.ts.map +1 -0
- package/types/check/TestHelpers.test.d.ts +2 -0
- package/types/check/TestHelpers.test.d.ts.map +1 -0
- package/types/dto/AeroflyConfigFileSet.d.ts +1 -1
- package/types/dto/AeroflyConfiguration.interface.d.ts +1 -1
- package/types/dto/AeroflyLocalizedText.d.ts +1 -1
- package/types/dto/AeroflyLocalizedText.test.d.ts +2 -0
- package/types/dto/AeroflyLocalizedText.test.d.ts.map +1 -0
- package/types/dto/AeroflyMission.d.ts +47 -4
- package/types/dto/AeroflyMission.d.ts.map +1 -1
- package/types/dto/AeroflyMission.test.d.ts +2 -0
- package/types/dto/AeroflyMission.test.d.ts.map +1 -0
- package/types/dto/AeroflyMissionCheckpoint.d.ts +32 -8
- package/types/dto/AeroflyMissionCheckpoint.test.d.ts +2 -0
- package/types/dto/AeroflyMissionCheckpoint.test.d.ts.map +1 -0
- package/types/dto/AeroflyMissionConditions.d.ts +15 -6
- package/types/dto/AeroflyMissionConditions.d.ts.map +1 -1
- package/types/dto/AeroflyMissionConditions.test.d.ts +2 -0
- package/types/dto/AeroflyMissionConditions.test.d.ts.map +1 -0
- package/types/dto/AeroflyMissionConditionsCloud.d.ts +4 -4
- package/types/dto/AeroflyMissionConditionsCloud.d.ts.map +1 -1
- package/types/dto/AeroflyMissionConditionsCloud.test.d.ts +2 -0
- package/types/dto/AeroflyMissionConditionsCloud.test.d.ts.map +1 -0
- package/types/dto/AeroflyMissionTargetPlane.d.ts +3 -3
- package/types/dto/AeroflyMissionTargetPlane.test.d.ts +2 -0
- package/types/dto/AeroflyMissionTargetPlane.test.d.ts.map +1 -0
- package/types/dto/AeroflyMissionsList.d.ts +1 -1
- package/types/dto/AeroflyMissionsList.d.ts.map +1 -1
- package/types/dto/AeroflyMissionsList.test.d.ts +2 -0
- package/types/dto/AeroflyMissionsList.test.d.ts.map +1 -0
- package/types/dto/index.test.d.ts +2 -0
- package/types/dto/index.test.d.ts.map +1 -0
- package/types/dto-flight/AeroflyFlight.d.ts +103 -0
- package/types/dto-flight/AeroflyFlight.d.ts.map +1 -0
- package/types/dto-flight/AeroflyFlight.test.d.ts +2 -0
- package/types/dto-flight/AeroflyFlight.test.d.ts.map +1 -0
- package/types/dto-flight/AeroflyNavRouteAirports.d.ts +55 -0
- package/types/dto-flight/AeroflyNavRouteAirports.d.ts.map +1 -0
- package/types/dto-flight/AeroflyNavRouteBase.d.ts +65 -0
- package/types/dto-flight/AeroflyNavRouteBase.d.ts.map +1 -0
- package/types/dto-flight/AeroflyNavRouteRunway.d.ts +54 -0
- package/types/dto-flight/AeroflyNavRouteRunway.d.ts.map +1 -0
- package/types/dto-flight/AeroflyNavRouteTransition.d.ts +62 -0
- package/types/dto-flight/AeroflyNavRouteTransition.d.ts.map +1 -0
- package/types/dto-flight/AeroflyNavRouteWaypoint.d.ts +49 -0
- package/types/dto-flight/AeroflyNavRouteWaypoint.d.ts.map +1 -0
- package/types/dto-flight/AeroflyNavigationConfig.d.ts +38 -0
- package/types/dto-flight/AeroflyNavigationConfig.d.ts.map +1 -0
- package/types/dto-flight/AeroflySettingsAircraft.d.ts +32 -0
- package/types/dto-flight/AeroflySettingsAircraft.d.ts.map +1 -0
- package/types/dto-flight/AeroflySettingsCloud.d.ts +45 -0
- package/types/dto-flight/AeroflySettingsCloud.d.ts.map +1 -0
- package/types/dto-flight/AeroflySettingsCloud.test.d.ts +2 -0
- package/types/dto-flight/AeroflySettingsCloud.test.d.ts.map +1 -0
- package/types/dto-flight/AeroflySettingsFlight.d.ts +66 -0
- package/types/dto-flight/AeroflySettingsFlight.d.ts.map +1 -0
- package/types/dto-flight/AeroflySettingsFlight.test.d.ts +2 -0
- package/types/dto-flight/AeroflySettingsFlight.test.d.ts.map +1 -0
- package/types/dto-flight/AeroflySettingsFuelLoad.d.ts +42 -0
- package/types/dto-flight/AeroflySettingsFuelLoad.d.ts.map +1 -0
- package/types/dto-flight/AeroflySettingsWind.d.ts +63 -0
- package/types/dto-flight/AeroflySettingsWind.d.ts.map +1 -0
- package/types/dto-flight/AeroflyTimeUtc.d.ts +47 -0
- package/types/dto-flight/AeroflyTimeUtc.d.ts.map +1 -0
- package/types/dto-flight/AeroflyWaypoint.d.ts +68 -0
- package/types/dto-flight/AeroflyWaypoint.d.ts.map +1 -0
- package/types/index.d.ts +20 -1
- package/types/index.d.ts.map +1 -1
- package/types/index.test.d.ts +1 -1
- package/types/node/AeroflyBasicTypes.d.ts +13 -0
- package/types/node/AeroflyBasicTypes.d.ts.map +1 -0
- package/types/node/AeroflyConfigurationNode.d.ts +25 -5
- package/types/node/AeroflyConfigurationNode.d.ts.map +1 -1
- package/types/node/AeroflyConfigurationNode.test.d.ts +2 -0
- package/types/node/AeroflyConfigurationNode.test.d.ts.map +1 -0
- package/types/node/Convert copy.d.ts +15 -0
- package/types/node/Convert copy.d.ts.map +1 -0
- package/types/node/Convert.d.ts +15 -0
- package/types/node/Convert.d.ts.map +1 -0
- package/types/node/Convert.test.d.ts +2 -0
- package/types/node/Convert.test.d.ts.map +1 -0
- package/dist/index.test.js +0 -258
- package/src/index.test.ts +0 -297
package/.editorconfig
CHANGED
package/AGENTS.md
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# AGENTS.md
|
|
2
|
+
|
|
3
|
+
## Project Overview
|
|
4
|
+
|
|
5
|
+
This project provides custom mission support for Aerofly flight simulators. It includes TypeScript source code, DTOs, configuration files, and supporting documentation for mission creation and management.
|
|
6
|
+
|
|
7
|
+
## Coding Guidelines
|
|
8
|
+
|
|
9
|
+
- **Explicit Class Properties:**
|
|
10
|
+
- All class properties must be explicitly defined in every class. Avoid using implicit or dynamic property assignment.
|
|
11
|
+
- **JSDoc Comments:**
|
|
12
|
+
- Add descriptive JSDoc comments to every class property and method. This improves code readability and enables rich IntelliSense in VS Code.
|
|
13
|
+
- Example:
|
|
14
|
+
```typescript
|
|
15
|
+
/**
|
|
16
|
+
* @property {string} name The name of the mission
|
|
17
|
+
*/
|
|
18
|
+
name: string;
|
|
19
|
+
```
|
|
20
|
+
- **TypeScript Usage:**
|
|
21
|
+
- Use TypeScript types and interfaces for all data structures.
|
|
22
|
+
- Keep types up to date in the `types/` directory.
|
|
23
|
+
|
|
24
|
+
## Contribution
|
|
25
|
+
|
|
26
|
+
- Follow the coding guidelines above for all new code and pull requests.
|
|
27
|
+
- See the `README.md` for setup and usage instructions.
|
|
28
|
+
|
|
29
|
+
## Testing
|
|
30
|
+
|
|
31
|
+
- TypeScript files have corresponding test files with the same filename and an added `.test` before the extension (e.g., `AeroflyMission.ts` and `AeroflyMission.test.ts`).
|
|
32
|
+
- Run all tests using:
|
|
33
|
+
```sh
|
|
34
|
+
npm test
|
|
35
|
+
```
|
|
36
|
+
- To run a single test file, specify its name:
|
|
37
|
+
```sh
|
|
38
|
+
node --test src/dto/AeroflyMission.test.ts
|
|
39
|
+
```
|
|
40
|
+
- Create new tests by using the `node:test`
|
|
41
|
+
```typescript
|
|
42
|
+
import { describe, it } from "node:test";
|
|
43
|
+
```
|
package/CHANGELOG.md
CHANGED
|
@@ -2,22 +2,33 @@
|
|
|
2
2
|
|
|
3
3
|
This changelog documents all notable changes to the Aerofly Custom Missions project. Each version entry includes a list of changes, with the most recent version at the top.
|
|
4
4
|
|
|
5
|
-
## 1.
|
|
5
|
+
## [1.4.0]
|
|
6
|
+
|
|
7
|
+
- Changed testing to standard Node.js testing suite
|
|
8
|
+
- Added `fuel_mass` and `payload_mass` properties
|
|
9
|
+
- Added `flight.mcf` / `main.mcf` DTO
|
|
10
|
+
|
|
11
|
+
## [1.3.1]
|
|
12
|
+
|
|
13
|
+
- Re-introduced spacers between exported missions
|
|
14
|
+
- Re-introduced commented out nodes for exported missions
|
|
15
|
+
|
|
16
|
+
## [1.3.0]
|
|
6
17
|
|
|
7
18
|
- Changed TMC code generation with nodes
|
|
8
19
|
|
|
9
|
-
## 1.2.3
|
|
20
|
+
## [1.2.3]
|
|
10
21
|
|
|
11
22
|
- Internal restructuring of mission generation logic
|
|
12
23
|
- Optimized waypoint handling and validation
|
|
13
24
|
- Improved error handling for mission parsing
|
|
14
25
|
|
|
15
|
-
## 1.2.2
|
|
26
|
+
## [1.2.2]
|
|
16
27
|
|
|
17
28
|
- Added altitude constraint property for waypoints
|
|
18
29
|
- Improved handling of cloud layers with better validation
|
|
19
30
|
|
|
20
|
-
## 1.2.1
|
|
31
|
+
## [1.2.1]
|
|
21
32
|
|
|
22
33
|
- Changed handling of checkpoints to support missions without checkpoints
|
|
23
34
|
- Improved file generation for programmatic mission creation
|
|
@@ -31,7 +42,7 @@ This changelog documents all notable changes to the Aerofly Custom Missions proj
|
|
|
31
42
|
- `before_start`
|
|
32
43
|
- `pushback`
|
|
33
44
|
|
|
34
|
-
## 1.2.0
|
|
45
|
+
## [1.2.0]
|
|
35
46
|
|
|
36
47
|
- Added new cloud level properties:
|
|
37
48
|
- `cirrus_cover` for high-altitude cloud coverage
|
|
@@ -39,13 +50,13 @@ This changelog documents all notable changes to the Aerofly Custom Missions proj
|
|
|
39
50
|
- Added new waypoint property `fly_over` for precise waypoint navigation
|
|
40
51
|
- Added `finish` property to mark mission completion points
|
|
41
52
|
|
|
42
|
-
## 1.1.1
|
|
53
|
+
## [1.1.1]
|
|
43
54
|
|
|
44
55
|
- Fixed styling issues in mission display
|
|
45
56
|
- Improved UI consistency across different mission types
|
|
46
57
|
- Enhanced error message formatting
|
|
47
58
|
|
|
48
|
-
## 1.1.0
|
|
59
|
+
## [1.1.0]
|
|
49
60
|
|
|
50
61
|
- Added new mission metadata properties:
|
|
51
62
|
- `tags` for mission categorization
|
|
@@ -59,31 +70,31 @@ This changelog documents all notable changes to the Aerofly Custom Missions proj
|
|
|
59
70
|
- `aerotow` for towed aircraft operations
|
|
60
71
|
- Improved temperature property with better unit handling
|
|
61
72
|
|
|
62
|
-
## 1.0.4
|
|
73
|
+
## [1.0.4]
|
|
63
74
|
|
|
64
75
|
- Added comprehensive documentation for known issues and workarounds
|
|
65
76
|
- Added `AeroflyMissionConditions.temperature` property with Celsius support
|
|
66
77
|
- Improved error handling for weather conditions
|
|
67
78
|
|
|
68
|
-
## 1.0.3
|
|
79
|
+
## [1.0.3]
|
|
69
80
|
|
|
70
81
|
- Enhanced API documentation with examples
|
|
71
82
|
- Added detailed parameter descriptions
|
|
72
83
|
- Improved code documentation
|
|
73
84
|
|
|
74
|
-
## 1.0.2
|
|
85
|
+
## [1.0.2]
|
|
75
86
|
|
|
76
87
|
- Added shorthand properties for common mission parameters
|
|
77
88
|
- Improved property access methods
|
|
78
89
|
- Enhanced mission validation
|
|
79
90
|
|
|
80
|
-
## 1.0.1
|
|
91
|
+
## [1.0.1]
|
|
81
92
|
|
|
82
93
|
- Added initial API documentation
|
|
83
94
|
- Improved code comments
|
|
84
95
|
- Added basic usage examples
|
|
85
96
|
|
|
86
|
-
## 1.0.0
|
|
97
|
+
## [1.0.0]
|
|
87
98
|
|
|
88
99
|
- Initial release of Aerofly Custom Missions
|
|
89
100
|
- Basic mission creation and editing functionality
|
package/LICENSE.txt
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
The MIT License (MIT)
|
|
2
2
|
|
|
3
|
-
Copyright © 2024 Frank Boës
|
|
3
|
+
Copyright © 2024-2026 Frank Boës
|
|
4
4
|
|
|
5
5
|
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
6
6
|
|
package/README.md
CHANGED
|
@@ -4,6 +4,8 @@
|
|
|
4
4
|
|
|
5
5
|
[Aerofly Flight Simulator 4](https://www.aerofly.com/) has a custom missions file `custom_missions_user.tmc` with a very unique format. To help you build this custom missions file, this JavaScript / TypeScript library offers Data Objects to create this file programmatically.
|
|
6
6
|
|
|
7
|
+
This simulator also defines flight plans and settings in the `main.mcf`, which is automatically loaded on simulator startup. This library contains a proposal for a `flight.mcf`, which is a stripped-down version of the `main.mcf` which only contains all information necessary for flight set-up. See [the documentation for `flight.mcf`](./docs/flight-mcf.md).
|
|
8
|
+
|
|
7
9
|
This library is intended to work in modern browsers as well as [Node.js](https://nodejs.org/en).
|
|
8
10
|
|
|
9
11
|
## Installation
|
|
@@ -52,6 +54,9 @@ import {
|
|
|
52
54
|
|
|
53
55
|
You might want to enable TypeScript type checking by adding `// @ts-check` as your first line in your scripts.
|
|
54
56
|
|
|
57
|
+
> [!NOTE]
|
|
58
|
+
> This library also contains classes for building the yet unsupported `flight.mcf`. Please refer to the code on how to use this. See [the documentation for `flight.mcf`](./docs/flight-mcf.md).
|
|
59
|
+
|
|
55
60
|
### Basic idea
|
|
56
61
|
|
|
57
62
|
All objects are basic structures needed for the missions list. The constructors tell you which properties are required, and will start with sensible defaults for all other properties.
|
|
@@ -60,7 +65,7 @@ All objects can be exported as JSON or as string via the `toString()` methods. E
|
|
|
60
65
|
|
|
61
66
|
### Building a missions file
|
|
62
67
|
|
|
63
|
-
A mission file contains one or multiple missions. Building this file starts with the outer container, wich contains the missions:
|
|
68
|
+
A `custom_missions_user.tmc` mission file contains one or multiple missions. Building this file starts with the outer container, wich contains the missions:
|
|
64
69
|
|
|
65
70
|
```javascript
|
|
66
71
|
// Build a missions list
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { strict as assert } from "node:assert";
|
|
2
|
+
export const assertValidAeroflyStructure = (aeroflyString) => {
|
|
3
|
+
const openingBrackets = aeroflyString.match(/</g);
|
|
4
|
+
const closingBrackets = aeroflyString.match(/>/g);
|
|
5
|
+
const openingBrackets2 = aeroflyString.match(/\[/g);
|
|
6
|
+
const closingBrackets2 = aeroflyString.match(/\]/g);
|
|
7
|
+
assert.ok(openingBrackets?.length ?? 0 > 0, "Has opening <");
|
|
8
|
+
assert.strictEqual(openingBrackets?.length, closingBrackets?.length, "Number of <> matches");
|
|
9
|
+
assert.strictEqual(openingBrackets2?.length, closingBrackets2?.length, "Number of [] matches");
|
|
10
|
+
};
|
|
11
|
+
export const assertIncludes = (string, includes) => {
|
|
12
|
+
assert.ok(string.includes(includes), `Includes "${includes}"`);
|
|
13
|
+
};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { assertValidAeroflyStructure } from "../check/TestHelpers.js";
|
|
2
|
+
import { describe, it } from "node:test";
|
|
3
|
+
describe("TestHelpers", () => {
|
|
4
|
+
it("should validate Aerofly structure correctly", () => {
|
|
5
|
+
const validString = "<>";
|
|
6
|
+
assertValidAeroflyStructure(validString);
|
|
7
|
+
});
|
|
8
|
+
});
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { AeroflyLocalizedText } from "./AeroflyLocalizedText.js";
|
|
2
|
+
import { strict as assert } from "node:assert";
|
|
3
|
+
import { assertValidAeroflyStructure } from "../check/TestHelpers.js";
|
|
4
|
+
import { describe, it } from "node:test";
|
|
5
|
+
describe("AeroflyLocalizedText", () => {
|
|
6
|
+
const localizedText = new AeroflyLocalizedText("de", "Test", "Test2");
|
|
7
|
+
it("should correctly map constructor values", () => {
|
|
8
|
+
assert.deepStrictEqual(localizedText.language, "de");
|
|
9
|
+
assert.deepStrictEqual(localizedText.title, "Test");
|
|
10
|
+
assert.deepStrictEqual(localizedText.description, "Test2");
|
|
11
|
+
assertValidAeroflyStructure(localizedText.toString());
|
|
12
|
+
});
|
|
13
|
+
it("should create a valid Aerofly mission", () => {
|
|
14
|
+
assertValidAeroflyStructure(localizedText.toString());
|
|
15
|
+
});
|
|
16
|
+
});
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AeroflyConfigurationNode } from "../node/AeroflyConfigurationNode.js";
|
|
1
|
+
import { AeroflyConfigurationNode, AeroflyConfigurationNodeComment } from "../node/AeroflyConfigurationNode.js";
|
|
2
2
|
import { AeroflyMissionConditions } from "./AeroflyMissionConditions.js";
|
|
3
3
|
export const feetPerMeter = 3.28084;
|
|
4
4
|
export const meterPerStatuteMile = 1609.344;
|
|
@@ -23,6 +23,8 @@ export class AeroflyMission {
|
|
|
23
23
|
* @param {"cold_and_dark"|"before_start"|"taxi"|"takeoff"|"cruise"|"approach"|"landing"|"winch_launch"|"aerotow"|"pushback"} [additionalAttributes.flightSetting] of aircraft, like "taxi", "cruise"
|
|
24
24
|
* @param {{name:string,livery:string,icao:string}} [additionalAttributes.aircraft] for this mission
|
|
25
25
|
* @param {string} [additionalAttributes.callsign] of aircraft, uppercased
|
|
26
|
+
* @param {?number} [additionalAttributes.fuelMass] in kg
|
|
27
|
+
* @param {?number} [additionalAttributes.payloadMass] in kg
|
|
26
28
|
* @param {object} [additionalAttributes.origin] position of aircraft, as well as name of starting airport. Position does not have match airport.
|
|
27
29
|
* @param {object} [additionalAttributes.destination] position of aircraft, as well as name of destination airport. Position does not have match airport.
|
|
28
30
|
* @param {?number} [additionalAttributes.distance] in meters
|
|
@@ -36,7 +38,7 @@ export class AeroflyMission {
|
|
|
36
38
|
name: "c172",
|
|
37
39
|
icao: "",
|
|
38
40
|
livery: "",
|
|
39
|
-
}, callsign = "", origin = {
|
|
41
|
+
}, callsign = "", fuelMass = null, payloadMass = null, origin = {
|
|
40
42
|
icao: "",
|
|
41
43
|
longitude: 0,
|
|
42
44
|
latitude: 0,
|
|
@@ -60,6 +62,8 @@ export class AeroflyMission {
|
|
|
60
62
|
this.flightSetting = flightSetting;
|
|
61
63
|
this.aircraft = aircraft;
|
|
62
64
|
this.callsign = callsign;
|
|
65
|
+
this.fuelMass = fuelMass;
|
|
66
|
+
this.payloadMass = payloadMass;
|
|
63
67
|
this.origin = origin;
|
|
64
68
|
this.destination = destination;
|
|
65
69
|
this.distance = distance;
|
|
@@ -130,11 +134,17 @@ export class AeroflyMission {
|
|
|
130
134
|
}
|
|
131
135
|
element.appendChild("string8", "flight_setting", this.flightSetting);
|
|
132
136
|
element.appendChild("string8u", "aircraft_name", this.aircraft.name);
|
|
133
|
-
/*if (this.aircraft.livery) {
|
|
134
|
-
mission.createChild("string8", "aircraft_livery", this.aircraft.livery);
|
|
135
|
-
}*/
|
|
136
137
|
element.appendChild("stringt8c", "aircraft_icao", this.aircraft.icao);
|
|
138
|
+
if (this.aircraft.livery) {
|
|
139
|
+
element.append(new AeroflyConfigurationNodeComment("string8", "aircraft_livery", this.aircraft.livery));
|
|
140
|
+
}
|
|
137
141
|
element.appendChild("stringt8c", "callsign", this.callsign);
|
|
142
|
+
if (this.fuelMass !== null) {
|
|
143
|
+
element.append(new AeroflyConfigurationNodeComment("float64", "fuel_mass", this.fuelMass, `kg`));
|
|
144
|
+
}
|
|
145
|
+
if (this.payloadMass !== null) {
|
|
146
|
+
element.append(new AeroflyConfigurationNodeComment("float64", "payload_mass", this.payloadMass, `kg`));
|
|
147
|
+
}
|
|
138
148
|
element.appendChild("stringt8c", "origin_icao", this.origin.icao);
|
|
139
149
|
element.appendChild("tmvector2d", "origin_lon_lat", [this.origin.longitude, this.origin.latitude]);
|
|
140
150
|
element.appendChild("float64", "origin_alt", this.origin.alt, `${Math.ceil(this.origin.alt * feetPerMeter)} ft MSL`);
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
import { AeroflyMission } from "./AeroflyMission.js";
|
|
2
|
+
import { strict as assert } from "node:assert";
|
|
3
|
+
import fs from "node:fs";
|
|
4
|
+
import { assertIncludes, assertValidAeroflyStructure } from "../check/TestHelpers.js";
|
|
5
|
+
import { describe, it } from "node:test";
|
|
6
|
+
import { AeroflyLocalizedText } from "./AeroflyLocalizedText.js";
|
|
7
|
+
import { AeroflyMissionCheckpoint } from "./AeroflyMissionCheckpoint.js";
|
|
8
|
+
import { AeroflyMissionConditions } from "./AeroflyMissionConditions.js";
|
|
9
|
+
import { AeroflyMissionConditionsCloud } from "./AeroflyMissionConditionsCloud.js";
|
|
10
|
+
import { AeroflyMissionsList } from "./AeroflyMissionsList.js";
|
|
11
|
+
import { AeroflyMissionTargetPlane } from "./AeroflyMissionTargetPlane.js";
|
|
12
|
+
describe("AeroflyMission", () => {
|
|
13
|
+
const mission = new AeroflyMission("Title", {
|
|
14
|
+
origin: {
|
|
15
|
+
icao: "XXXX",
|
|
16
|
+
longitude: 0,
|
|
17
|
+
latitude: 0,
|
|
18
|
+
dir: 0,
|
|
19
|
+
alt: 0,
|
|
20
|
+
},
|
|
21
|
+
destination: {
|
|
22
|
+
icao: "XXXX",
|
|
23
|
+
longitude: 0,
|
|
24
|
+
latitude: 0,
|
|
25
|
+
dir: 0,
|
|
26
|
+
alt: 0,
|
|
27
|
+
},
|
|
28
|
+
});
|
|
29
|
+
it("should correctly map constructor values", () => {
|
|
30
|
+
assert.strictEqual(mission.title, "Title");
|
|
31
|
+
});
|
|
32
|
+
it("should create a valid Aerofly mission", () => {
|
|
33
|
+
assertValidAeroflyStructure(mission.toString());
|
|
34
|
+
});
|
|
35
|
+
it("should create a valid XML mission", () => {
|
|
36
|
+
assertValidAeroflyStructure(mission.getElement().toXmlString());
|
|
37
|
+
});
|
|
38
|
+
it("should create AeroflyMissionConditions correctly", () => {
|
|
39
|
+
const conditions = new AeroflyMissionConditions({
|
|
40
|
+
time: new Date(Date.UTC(2024, 5, 14, 13, 15, 38)),
|
|
41
|
+
wind: {
|
|
42
|
+
direction: 190,
|
|
43
|
+
speed: 11,
|
|
44
|
+
gusts: 22,
|
|
45
|
+
},
|
|
46
|
+
turbulenceStrength: 1,
|
|
47
|
+
temperature: 21,
|
|
48
|
+
visibility: 14484.096000000001,
|
|
49
|
+
clouds: [
|
|
50
|
+
AeroflyMissionConditionsCloud.createInFeet(0.1, 5000),
|
|
51
|
+
AeroflyMissionConditionsCloud.createInFeet(0.2, 7500),
|
|
52
|
+
AeroflyMissionConditionsCloud.createInFeet(0.1, 9500),
|
|
53
|
+
],
|
|
54
|
+
});
|
|
55
|
+
assert.strictEqual(conditions.wind.direction, 190);
|
|
56
|
+
assert.strictEqual(conditions.wind.speed, 11);
|
|
57
|
+
assert.strictEqual(conditions.wind.gusts, 22);
|
|
58
|
+
assert.strictEqual(conditions.turbulenceStrength, 1);
|
|
59
|
+
assert.strictEqual(conditions.temperature, 21);
|
|
60
|
+
assert.strictEqual(conditions.visibility, 14484.096000000001);
|
|
61
|
+
const checkpoints = [
|
|
62
|
+
new AeroflyMissionCheckpoint("KCCR", "origin", -122.057, 37.9897, {
|
|
63
|
+
altitude: 8,
|
|
64
|
+
}),
|
|
65
|
+
new AeroflyMissionCheckpoint("19L", "departure_runway", -122.05504061196366, 37.993168229891225, {
|
|
66
|
+
length: 844.2959729825288,
|
|
67
|
+
}),
|
|
68
|
+
new AeroflyMissionCheckpoint("24", "destination_runway", -70.60730234370952, 41.399093035543366, {
|
|
69
|
+
altitude: 20,
|
|
70
|
+
length: 1677.6191463161874,
|
|
71
|
+
frequency: 108700000,
|
|
72
|
+
}),
|
|
73
|
+
new AeroflyMissionCheckpoint("KMVY", "destination", -70.6139, 41.3934, {
|
|
74
|
+
altitude: 20,
|
|
75
|
+
flyOver: false,
|
|
76
|
+
}),
|
|
77
|
+
];
|
|
78
|
+
const mission = new AeroflyMission("KCCR #1: Concord / Buchanan Field", {
|
|
79
|
+
checkpoints,
|
|
80
|
+
conditions,
|
|
81
|
+
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.
|
|
82
|
+
|
|
83
|
+
- Local tower / CTAF frequency: 123.90
|
|
84
|
+
- Local navigational aids: VOR/DME CCR (117.00) 3.4 NM to the north`,
|
|
85
|
+
flightSetting: "cruise",
|
|
86
|
+
aircraft: {
|
|
87
|
+
name: "c172",
|
|
88
|
+
livery: "default",
|
|
89
|
+
icao: "C172",
|
|
90
|
+
},
|
|
91
|
+
callsign: "N51911",
|
|
92
|
+
origin: {
|
|
93
|
+
icao: "KCCR",
|
|
94
|
+
longitude: -122.0736009331662,
|
|
95
|
+
latitude: 38.122300745843944,
|
|
96
|
+
dir: 174.37511511143452,
|
|
97
|
+
alt: 1066.799965862401,
|
|
98
|
+
},
|
|
99
|
+
destination: {
|
|
100
|
+
icao: "KMVY",
|
|
101
|
+
longitude: -70.6139,
|
|
102
|
+
latitude: 41.3934,
|
|
103
|
+
dir: 221,
|
|
104
|
+
alt: 20,
|
|
105
|
+
},
|
|
106
|
+
});
|
|
107
|
+
const missionList = new AeroflyMissionsList([mission]);
|
|
108
|
+
assert.strictEqual(missionList.missions.length, 1);
|
|
109
|
+
assert.strictEqual(missionList.missions[0].aircraft.name, "c172");
|
|
110
|
+
assert.strictEqual(missionList.missions[0].aircraft.icao, "C172");
|
|
111
|
+
let missionListString = missionList.toString();
|
|
112
|
+
assert.strictEqual(missionListString, missionList.toString());
|
|
113
|
+
assertIncludes(missionListString, "[origin]");
|
|
114
|
+
assertIncludes(missionListString, "[tmmission_definition]");
|
|
115
|
+
assertIncludes(missionListString, "[list_tmmission_checkpoint]");
|
|
116
|
+
assertIncludes(missionListString, "[tmmission_checkpoint]");
|
|
117
|
+
assertIncludes(missionListString, "[departure_runway]");
|
|
118
|
+
assertIncludes(missionListString, "[cloud_cover]");
|
|
119
|
+
assertIncludes(missionListString, "[cirrus_cover]");
|
|
120
|
+
assertIncludes(missionListString, "[tmmission_checkpoint][element][0]");
|
|
121
|
+
assertIncludes(missionListString, "[tmmission_checkpoint][element][1]");
|
|
122
|
+
assertIncludes(missionListString, "[tmmission_checkpoint][element][2]");
|
|
123
|
+
assertIncludes(missionListString, "[tmmission_checkpoint][element][3]");
|
|
124
|
+
assertIncludes(missionListString, "<[float64][length][844.2959729825288]>");
|
|
125
|
+
assert.ok(!missionListString.includes("[tags]"));
|
|
126
|
+
assert.ok(!missionListString.includes("[difficulty]"));
|
|
127
|
+
assert.ok(!missionListString.includes("[is_featured]"));
|
|
128
|
+
assert.ok(!missionListString.includes("[tmmission_definition_localized]"));
|
|
129
|
+
assert.ok(!missionListString.includes("[distance]"));
|
|
130
|
+
assert.ok(!missionListString.includes("[duration]"));
|
|
131
|
+
assert.ok(!missionListString.includes("[alt_cst]"));
|
|
132
|
+
assertValidAeroflyStructure(missionListString);
|
|
133
|
+
//console.log(missionListString);
|
|
134
|
+
mission.difficulty = 1.0;
|
|
135
|
+
mission.isFeatured = true;
|
|
136
|
+
mission.localizedTexts.push(new AeroflyLocalizedText("de", "Landeübung #1", "Probier die Landung"));
|
|
137
|
+
mission.distance = 1400;
|
|
138
|
+
mission.duration = 2 * 60 * 60;
|
|
139
|
+
mission.tags.push("approach");
|
|
140
|
+
mission.tags.push("pattern");
|
|
141
|
+
mission.finish = new AeroflyMissionTargetPlane(0, 1, 2);
|
|
142
|
+
mission.tutorialName = "c172";
|
|
143
|
+
mission.isScheduled = true;
|
|
144
|
+
missionListString = missionList.toString();
|
|
145
|
+
assertIncludes(missionListString, "[tags]");
|
|
146
|
+
assertIncludes(missionListString, "[difficulty]");
|
|
147
|
+
assertIncludes(missionListString, "[is_featured]");
|
|
148
|
+
assertIncludes(missionListString, "true");
|
|
149
|
+
assertIncludes(missionListString, "[tmmission_definition_localized]");
|
|
150
|
+
assertIncludes(missionListString, "Landeübung");
|
|
151
|
+
assertIncludes(missionListString, "[distance]");
|
|
152
|
+
assertIncludes(missionListString, "[duration]");
|
|
153
|
+
assertIncludes(missionListString, "[finish]");
|
|
154
|
+
assertIncludes(missionListString, "[tutorial_name]");
|
|
155
|
+
assertIncludes(missionListString, "[is_scheduled]");
|
|
156
|
+
assertValidAeroflyStructure(missionListString);
|
|
157
|
+
//console.dir(missionList.missions[0], { depth: null });
|
|
158
|
+
//console.log(missionListString);
|
|
159
|
+
//console.log(missionList.getElement().toXmlString());
|
|
160
|
+
const file = new AeroflyMissionsList([mission]);
|
|
161
|
+
const fileContent = file.toString();
|
|
162
|
+
fs.writeFileSync("docs/custom_missions_user.tmc", fileContent);
|
|
163
|
+
const xmlContent = file.toXmlString();
|
|
164
|
+
fs.writeFileSync("docs/custom_missions_user.xml", xmlContent);
|
|
165
|
+
});
|
|
166
|
+
});
|
|
@@ -15,7 +15,7 @@ export class AeroflyMissionCheckpoint {
|
|
|
15
15
|
* @param {"origin"|"departure_runway"|"departure"|"waypoint"|"arrival"|"approach"|"destination_runway"|"destination"} type Type of checkpoint, like "departure_runway"
|
|
16
16
|
* @param {number} longitude easting, using the World Geodetic
|
|
17
17
|
* System 1984 (WGS 84) [WGS84] datum, with longitude and latitude units
|
|
18
|
-
* of decimal degrees; -180
|
|
18
|
+
* of decimal degrees; [-180,180]
|
|
19
19
|
* @param {number} latitude northing, using the World Geodetic
|
|
20
20
|
* System 1984 (WGS 84) [WGS84] datum, with longitude and latitude units
|
|
21
21
|
* of decimal degrees; -90..90
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { AeroflyMissionCheckpoint } from "./AeroflyMissionCheckpoint.js";
|
|
2
|
+
import { strict as assert } from "node:assert";
|
|
3
|
+
import { assertValidAeroflyStructure, assertIncludes } from "../check/TestHelpers.js";
|
|
4
|
+
import { describe, it } from "node:test";
|
|
5
|
+
describe("AeroflyMissionCheckpoint", () => {
|
|
6
|
+
it("should correctly map constructor values", () => {
|
|
7
|
+
const checkpoint = new AeroflyMissionCheckpoint("TEST", "waypoint", 15, 20, {
|
|
8
|
+
altitude_feet: 1000,
|
|
9
|
+
flyOver: true,
|
|
10
|
+
length_feet: 500,
|
|
11
|
+
});
|
|
12
|
+
assert.strictEqual(checkpoint.name, "TEST");
|
|
13
|
+
assert.strictEqual(checkpoint.type, "waypoint");
|
|
14
|
+
assert.strictEqual(checkpoint.longitude, 15);
|
|
15
|
+
assert.strictEqual(checkpoint.latitude, 20);
|
|
16
|
+
assert.strictEqual(checkpoint.flyOver, true);
|
|
17
|
+
assert.strictEqual(Math.round(checkpoint.altitude_feet), 1000);
|
|
18
|
+
assert.strictEqual(Math.round(checkpoint.altitude), Math.round(1000 * 0.3048));
|
|
19
|
+
assert.strictEqual(Math.round(checkpoint.length_feet), 500);
|
|
20
|
+
assert.strictEqual(Math.round(checkpoint.length ?? 0), Math.round(500 * 0.3048));
|
|
21
|
+
});
|
|
22
|
+
it("should correctly map values from properties", () => {
|
|
23
|
+
const checkpoint = new AeroflyMissionCheckpoint("TEST", "waypoint", 15, 20);
|
|
24
|
+
let checkpointString = checkpoint.toString();
|
|
25
|
+
assertIncludes(checkpointString, "[type]");
|
|
26
|
+
assertIncludes(checkpointString, "[name]");
|
|
27
|
+
assertIncludes(checkpointString, "[lon_lat]");
|
|
28
|
+
assertIncludes(checkpointString, "15 20");
|
|
29
|
+
assertIncludes(checkpointString, "[altitude]");
|
|
30
|
+
assert.ok(!checkpointString.includes("[fly_over]"));
|
|
31
|
+
assert.ok(!checkpointString.includes("[alt_cst]"));
|
|
32
|
+
checkpoint.altitudeConstraint = false;
|
|
33
|
+
checkpoint.flyOver = false;
|
|
34
|
+
checkpoint.altitude_feet = 1000;
|
|
35
|
+
checkpoint.length_feet = 500;
|
|
36
|
+
checkpointString = checkpoint.toString();
|
|
37
|
+
assertIncludes(checkpointString, "[fly_over]");
|
|
38
|
+
assertIncludes(checkpointString, "[alt_cst]");
|
|
39
|
+
assertValidAeroflyStructure(checkpointString);
|
|
40
|
+
});
|
|
41
|
+
});
|
|
@@ -15,8 +15,8 @@ export class AeroflyMissionConditions {
|
|
|
15
15
|
* @param {Date} [additionalAttributes.time] of flight plan. Relevant is the UTC part, so
|
|
16
16
|
* consider setting this date in UTC.
|
|
17
17
|
* @param {{direction: number, speed: number, gusts: number}} [additionalAttributes.wind] state
|
|
18
|
-
* @param {number} [additionalAttributes.turbulenceStrength] 0
|
|
19
|
-
* @param {number} [additionalAttributes.thermalStrength] 0
|
|
18
|
+
* @param {number} [additionalAttributes.turbulenceStrength] normalized value [0,1]
|
|
19
|
+
* @param {number} [additionalAttributes.thermalStrength] normalized value [0,1]
|
|
20
20
|
* @param {number} [additionalAttributes.visibility] in meters
|
|
21
21
|
* @param {?number} [additionalAttributes.visibility_sm] in statute miles, will overwrite visibility
|
|
22
22
|
* @param {?number} [additionalAttributes.temperature] in °C, will overwrite thermalStrength
|
|
@@ -26,7 +26,7 @@ export class AeroflyMissionConditions {
|
|
|
26
26
|
direction: 0,
|
|
27
27
|
speed: 0,
|
|
28
28
|
gusts: 0,
|
|
29
|
-
}, turbulenceStrength = 0, thermalStrength = 0, visibility =
|
|
29
|
+
}, turbulenceStrength = 0, thermalStrength = 0, visibility = 25_000, visibility_sm = 0, temperature = 0, clouds = [], } = {}) {
|
|
30
30
|
/**
|
|
31
31
|
* @property {AeroflyMissionConditionsCloud[]} clouds for the whole flight
|
|
32
32
|
*/
|
|
@@ -90,9 +90,7 @@ export class AeroflyMissionConditions {
|
|
|
90
90
|
* @returns {AeroflyConfigurationNode[]} cloud elements
|
|
91
91
|
*/
|
|
92
92
|
getCloudElements() {
|
|
93
|
-
return this.clouds
|
|
94
|
-
.slice(0, 2) // Aerofly FS4 supports max 2 cloud layers
|
|
95
|
-
.flatMap((c, index) => c.getElements(index));
|
|
93
|
+
return this.clouds.flatMap((c, index) => c.getElements(index));
|
|
96
94
|
}
|
|
97
95
|
/**
|
|
98
96
|
* @returns {string} to use in Aerofly FS4's `custom_missions_user.tmc`
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { AeroflyMissionConditions } from "./AeroflyMissionConditions.js";
|
|
2
|
+
import { strict as assert } from "node:assert";
|
|
3
|
+
import { assertValidAeroflyStructure } from "../check/TestHelpers.js";
|
|
4
|
+
import { describe, it } from "node:test";
|
|
5
|
+
describe("AeroflyMissionConditions", () => {
|
|
6
|
+
it("should handle visibility in meters correctly when set via property", () => {
|
|
7
|
+
const conditions = new AeroflyMissionConditions();
|
|
8
|
+
conditions.visibility = 15_000;
|
|
9
|
+
assert.deepStrictEqual(conditions.visibility, 15_000);
|
|
10
|
+
});
|
|
11
|
+
it("should handle visibility in statute miles correctly when set via property", () => {
|
|
12
|
+
const conditions = new AeroflyMissionConditions();
|
|
13
|
+
conditions.visibility_sm = 10;
|
|
14
|
+
assert.notDeepStrictEqual(conditions.visibility, 10);
|
|
15
|
+
assert.deepStrictEqual(Math.round(conditions.visibility_sm), 10);
|
|
16
|
+
assertValidAeroflyStructure(conditions.toString());
|
|
17
|
+
});
|
|
18
|
+
it("should handle visibility in meters correctly when set via constructor", () => {
|
|
19
|
+
const conditions = new AeroflyMissionConditions({
|
|
20
|
+
visibility: 15_000,
|
|
21
|
+
});
|
|
22
|
+
assert.deepStrictEqual(conditions.visibility, 15_000);
|
|
23
|
+
assertValidAeroflyStructure(conditions.toString());
|
|
24
|
+
});
|
|
25
|
+
it("should handle visibility in statute miles correctly when set via constructor", () => {
|
|
26
|
+
const conditions = new AeroflyMissionConditions({
|
|
27
|
+
visibility_sm: 10,
|
|
28
|
+
});
|
|
29
|
+
assert.notDeepStrictEqual(conditions.visibility, 10);
|
|
30
|
+
assert.deepStrictEqual(Math.round(conditions.visibility_sm), 10);
|
|
31
|
+
assertValidAeroflyStructure(conditions.toString());
|
|
32
|
+
});
|
|
33
|
+
});
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AeroflyConfigurationNode } from "../node/AeroflyConfigurationNode.js";
|
|
1
|
+
import { AeroflyConfigurationNode, AeroflyConfigurationNodeComment } from "../node/AeroflyConfigurationNode.js";
|
|
2
2
|
import { feetPerMeter } from "./AeroflyMission.js";
|
|
3
3
|
/**
|
|
4
4
|
* @class
|
|
@@ -10,7 +10,7 @@ import { feetPerMeter } from "./AeroflyMission.js";
|
|
|
10
10
|
*/
|
|
11
11
|
export class AeroflyMissionConditionsCloud {
|
|
12
12
|
/**
|
|
13
|
-
* @param {number} cover 0
|
|
13
|
+
* @param {number} cover normalized value [0,1]
|
|
14
14
|
* @param {number} base altitude in meters AGL
|
|
15
15
|
*/
|
|
16
16
|
constructor(cover, base) {
|
|
@@ -18,7 +18,7 @@ export class AeroflyMissionConditionsCloud {
|
|
|
18
18
|
this.base = base;
|
|
19
19
|
}
|
|
20
20
|
/**
|
|
21
|
-
* @param {number} cover 0
|
|
21
|
+
* @param {number} cover normalized value [0,1]
|
|
22
22
|
* @param {number} base_feet altitude, but in feet AGL instead of meters AGL
|
|
23
23
|
* @returns {AeroflyMissionConditionsCloud} self
|
|
24
24
|
*/
|
|
@@ -73,10 +73,15 @@ export class AeroflyMissionConditionsCloud {
|
|
|
73
73
|
}
|
|
74
74
|
};
|
|
75
75
|
const indexString = getIndexString(index);
|
|
76
|
-
return
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
76
|
+
return index <= 1
|
|
77
|
+
? [
|
|
78
|
+
new AeroflyConfigurationNode("float64", `${indexString}_cover`, this.cover ?? 0, this.cover_code),
|
|
79
|
+
new AeroflyConfigurationNode("float64", `${indexString}_base`, this.base, `${this.base_feet} ft AGL`),
|
|
80
|
+
]
|
|
81
|
+
: [
|
|
82
|
+
new AeroflyConfigurationNodeComment("float64", `${indexString}_cover`, this.cover ?? 0, this.cover_code),
|
|
83
|
+
new AeroflyConfigurationNodeComment("float64", `${indexString}_base`, this.base, `${this.base_feet} ft AGL`),
|
|
84
|
+
];
|
|
80
85
|
}
|
|
81
86
|
/**
|
|
82
87
|
* @param {number} index if used in an array will set the array index
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { AeroflyMissionConditionsCloud } from "./AeroflyMissionConditionsCloud.js";
|
|
2
|
+
import { strict as assert } from "node:assert";
|
|
3
|
+
import { assertValidAeroflyStructure } from "../check/TestHelpers.js";
|
|
4
|
+
import { describe, it } from "node:test";
|
|
5
|
+
describe("AeroflyMissionConditionsCloud", () => {
|
|
6
|
+
it("should create clouds with indentation", () => {
|
|
7
|
+
const cloud = new AeroflyMissionConditionsCloud(0, 0);
|
|
8
|
+
assert.deepStrictEqual(cloud.cover, 0);
|
|
9
|
+
assert.deepStrictEqual(cloud.base, 0);
|
|
10
|
+
assertValidAeroflyStructure(cloud.toString());
|
|
11
|
+
assertValidAeroflyStructure(cloud.toString(0));
|
|
12
|
+
assertValidAeroflyStructure(cloud.toString(1));
|
|
13
|
+
assertValidAeroflyStructure(cloud.toString(2));
|
|
14
|
+
assertValidAeroflyStructure(cloud.toString(3));
|
|
15
|
+
});
|
|
16
|
+
it("should assign values correctly from constructor and properties", () => {
|
|
17
|
+
const cloud = new AeroflyMissionConditionsCloud(1, 1000);
|
|
18
|
+
assert.deepStrictEqual(cloud.cover, 1);
|
|
19
|
+
assert.deepStrictEqual(cloud.base, 1000);
|
|
20
|
+
cloud.base_feet = 1000;
|
|
21
|
+
assert.notDeepStrictEqual(cloud.base, 1000);
|
|
22
|
+
assert.deepStrictEqual(Math.round(cloud.base_feet), 1000);
|
|
23
|
+
assertValidAeroflyStructure(cloud.toString());
|
|
24
|
+
});
|
|
25
|
+
});
|
|
@@ -8,7 +8,7 @@ export class AeroflyMissionTargetPlane {
|
|
|
8
8
|
*
|
|
9
9
|
* @param {number} longitude easting, using the World Geodetic
|
|
10
10
|
* System 1984 (WGS 84) [WGS84] datum, with longitude and latitude units
|
|
11
|
-
* of decimal degrees; -180
|
|
11
|
+
* of decimal degrees; [-180,180]
|
|
12
12
|
* @param {number}latitude northing, using the World Geodetic
|
|
13
13
|
* System 1984 (WGS 84) [WGS84] datum, with longitude and latitude units
|
|
14
14
|
* of decimal degrees; -90..90
|