diff --git a/fbw-a380x/src/.eslintrc.js b/fbw-a380x/src/.eslintrc.js new file mode 100644 index 000000000000..1911b8917878 --- /dev/null +++ b/fbw-a380x/src/.eslintrc.js @@ -0,0 +1,141 @@ +'use strict'; + +module.exports = { + root: true, + env: { browser: true }, + extends: [ + '@flybywiresim/eslint-config', + 'plugin:jest/recommended', + 'plugin:jest/style', + 'plugin:tailwindcss/recommended', + ], + plugins: [ + '@typescript-eslint', + 'tailwindcss', + ], + parser: '@typescript-eslint/parser', + ignorePatterns: [ + 'mcdu-server/client/build/**', + // disabled all for now as the A380 code is not up to standard + '**/*', + ], + parserOptions: { + ecmaVersion: 2021, + sourceType: 'script', + requireConfigFile: false, + }, + settings: { + 'tailwindcss': { groupByResponsive: true }, + 'import/resolver': { node: { extensions: ['.js', '.mjs', '.jsx', '.ts', '.tsx'] } }, + }, + overrides: [ + { + files: ['*.jsx', '*.tsx'], + parserOptions: { + sourceType: 'module', + ecmaFeatures: { jsx: true }, + }, + }, + { + files: ['*.mjs', '*.ts', '*.d.ts'], + parserOptions: { sourceType: 'module' }, + }, + ], + // overrides airbnb, use sparingly + rules: { + 'tailwindcss/no-custom-classname': 'off', + 'no-bitwise': 'off', + 'no-mixed-operators': 'off', + 'arrow-parens': ['error', 'always'], + 'brace-style': ['error', '1tbs', { allowSingleLine: false }], + 'class-methods-use-this': 'off', + 'curly': ['error', 'multi-line'], + 'import/prefer-default-export': 'off', + 'import/no-extraneous-dependencies': ['error', { devDependencies: true }], + 'indent': ['error', 4], + 'react/jsx-filename-extension': [2, { extensions: ['.jsx', '.tsx'] }], + 'react/jsx-indent': ['error', 4], + 'no-restricted-syntax': 'off', + 'quote-props': ['error', 'consistent-as-needed'], + 'strict': ['error', 'global'], + + 'no-case-declarations': 'off', + + 'no-plusplus': 'off', + 'no-shadow': 'off', + 'no-continue': 'off', + 'no-return-assign': 'off', + 'radix': 'off', + 'max-classes-per-file': 'off', + 'no-useless-constructor': 'off', + '@typescript-eslint/no-useless-constructor': ['error'], + 'no-empty-function': ['error', { allow: ['constructors', 'arrowFunctions'] }], + '@typescript-eslint/no-empty-function': 'off', + + // buggy + 'prefer-destructuring': 'off', + + // Avoid typescript-eslint conflicts + 'no-unused-vars': 'off', + 'import/no-unresolved': 'off', + '@typescript-eslint/no-unused-vars': ['error', { + vars: 'all', + varsIgnorePattern: '^_|^FSComponent$', + args: 'after-used', + argsIgnorePattern: '^_|^node$|^deltaTime$', + }], + + 'no-use-before-define': 'off', + + 'react/jsx-indent-props': 'off', + + // not relevant now + 'react/no-unused-state': 'off', + + // useless + 'react/prop-types': 'off', + 'react/require-default-props': 'off', + 'react/no-unused-prop-types': 'off', + 'react/destructuring-assignment': 'off', + 'react/jsx-props-no-spreading': 'off', + 'react/no-unescaped-entities': 'off', + + // Not needed with react 17+ + 'react/jsx-uses-react': 'off', + 'react/react-in-jsx-scope': 'off', + + 'import/extensions': 'off', + 'no-param-reassign': 'off', + 'no-undef-init': 'off', + 'no-undef': 'off', + 'max-len': ['error', { code: 192 }], + + // Irrelevant for our use + 'jsx-a11y/alt-text': 'off', + 'jsx-a11y/no-static-element-interactions': 'off', + 'jsx-a11y/click-events-have-key-events': 'off', + 'jsx-a11y/anchor-is-valid': 'off', + 'object-curly-newline': ['error', { multiline: true }], + 'linebreak-style': 'off', + + // allow typescript overloads + 'no-redeclare': 'off', + '@typescript-eslint/no-redeclare': ['error'], + 'lines-between-class-members': 'off', + '@typescript-eslint/lines-between-class-members': ['error'], + 'no-dupe-class-members': 'off', + '@typescript-eslint/no-dupe-class-members': ['error'], + + // allow console logging + 'no-console': 'off', + }, + globals: { + Simplane: 'readonly', + SimVar: 'readonly', + Utils: 'readonly', + JSX: 'readonly', + Coherent: 'readonly', + ViewListener: 'readonly', + RegisterViewListener: 'readonly', + }, +}; diff --git a/fbw-a380x/src/systems/atsu/src/components/FlightStateObserver.ts b/fbw-a380x/src/systems/atsu/src/components/FlightStateObserver.ts index 088fb055d27e..bfd127de5281 100644 --- a/fbw-a380x/src/systems/atsu/src/components/FlightStateObserver.ts +++ b/fbw-a380x/src/systems/atsu/src/components/FlightStateObserver.ts @@ -18,7 +18,7 @@ export class FlightStateObserver { public PresentPosition = { lat: null, lon: null, altitude: null, heading: null, track: null, indicatedAirspeed: null, groundSpeed: null, verticalSpeed: null }; - public FcuSettings = { apActive: false, speed: null, machMode: false, altitude: null }; + public FcuSettings = { apActive: false, speed: null, machMode: false, altitude: null } public ActiveWaypoint: Waypoint | undefined = undefined; diff --git a/fbw-a380x/src/systems/atsu/src/components/UplinkMessageMonitoring.ts b/fbw-a380x/src/systems/atsu/src/components/UplinkMessageMonitoring.ts index b66aff67786e..45a2659e8864 100644 --- a/fbw-a380x/src/systems/atsu/src/components/UplinkMessageMonitoring.ts +++ b/fbw-a380x/src/systems/atsu/src/components/UplinkMessageMonitoring.ts @@ -165,7 +165,7 @@ export class UplinkMessageMonitoring { this.atsu = atsu; } - public; + public public monitorMessage(message: CpdlcMessage): boolean { if (UplinkMonitor.relevantMessage(message)) { diff --git a/fbw-a380x/src/systems/extras-host/modules/pushbutton_check/PushbuttonCheck.ts b/fbw-a380x/src/systems/extras-host/modules/pushbutton_check/PushbuttonCheck.ts index 61018b824aa7..f0934441161d 100644 --- a/fbw-a380x/src/systems/extras-host/modules/pushbutton_check/PushbuttonCheck.ts +++ b/fbw-a380x/src/systems/extras-host/modules/pushbutton_check/PushbuttonCheck.ts @@ -21,7 +21,7 @@ export class PushbuttonCheck { private readonly toConfTimer = new DebounceTimer(); - private readonly toConfButtonInCruise = MappedSubject.create(([toConf, phase]) => toConf && phase === 6, this.toConfButton, this.fwcFlightPhase); + private readonly toConfButtonInCruise = MappedSubject.create(([toConf, phase]) => toConf && phase === 6, this.toConfButton, this.fwcFlightPhase) private toConfMessageShown = false; diff --git a/fbw-a380x/src/systems/fmgc/src/NavigationDatabase.ts b/fbw-a380x/src/systems/fmgc/src/NavigationDatabase.ts index 1380761cde15..04cee1c930fd 100644 --- a/fbw-a380x/src/systems/fmgc/src/NavigationDatabase.ts +++ b/fbw-a380x/src/systems/fmgc/src/NavigationDatabase.ts @@ -11,7 +11,7 @@ import { Database, ExternalBackend, MsfsBackend, - Waypoint, + Waypoint } from 'msfs-navdata'; /** @@ -28,7 +28,7 @@ export enum NavigationDatabaseBackend { * Only to be used by user-facing functions to search for data. Raw flight plan editing should use the `backendDatabase` property directly */ export class NavigationDatabase { - readonly backendDatabase: Database; + readonly backendDatabase: Database constructor( readonly backend: NavigationDatabaseBackend, @@ -67,7 +67,7 @@ export class NavigationDatabase { } static formatLongApproachIdent(approach: Approach): string { - const suffix = this.approachSuffix(approach); + let suffix = this.approachSuffix(approach); switch (approach.type) { case ApproachType.LocBackcourse: // TODO confirm diff --git a/fbw-a380x/src/systems/fmgc/src/flightphase/FlightPhaseManager.ts b/fbw-a380x/src/systems/fmgc/src/flightphase/FlightPhaseManager.ts index cfcac01f8b26..ddc5e86f07a3 100644 --- a/fbw-a380x/src/systems/fmgc/src/flightphase/FlightPhaseManager.ts +++ b/fbw-a380x/src/systems/fmgc/src/flightphase/FlightPhaseManager.ts @@ -27,7 +27,7 @@ export class FlightPhaseManager { [FmgcFlightPhase.Approach]: new ApproachPhase(), [FmgcFlightPhase.GoAround]: new GoAroundPhase(), [FmgcFlightPhase.Done]: new DonePhase(), - }; + } private phaseChangeListeners: Array<(prev: FmgcFlightPhase, next: FmgcFlightPhase) => void> = []; diff --git a/fbw-a380x/src/systems/fmgc/src/flightplanning/DirectTo.ts b/fbw-a380x/src/systems/fmgc/src/flightplanning/DirectTo.ts index 1f3d13068283..725a626cb961 100644 --- a/fbw-a380x/src/systems/fmgc/src/flightplanning/DirectTo.ts +++ b/fbw-a380x/src/systems/fmgc/src/flightplanning/DirectTo.ts @@ -28,24 +28,24 @@ import { FlightPlanSegment } from './FlightPlanSegment'; * Information about the current direct-to procedures in the flight plan. */ export class DirectTo { - /** Whether or not the current direct-to is in the flight plan. */ - public waypointIsInFlightPlan = false; + /** Whether or not the current direct-to is in the flight plan. */ + public waypointIsInFlightPlan = false; - /** Whether or not direct-to is active. */ - public isActive = false; + /** Whether or not direct-to is active. */ + public isActive = false; - /** The current direct-to waypoint, if not part of the flight plan. */ - public waypoint?: WayPoint; + /** The current direct-to waypoint, if not part of the flight plan. */ + public waypoint?: WayPoint; - /** The current direct-to waypoint index, if part of the flight plan. */ - public planWaypointIndex = 0; + /** The current direct-to waypoint index, if part of the flight plan. */ + public planWaypointIndex = 0; - /** The intercept points towards the direct. */ - public interceptPoints?: WayPoint[]; + /** The intercept points towards the direct. */ + public interceptPoints?: WayPoint[]; - /** The current active index in the direct to waypoints. */ - public currentWaypointIndex = 0; + /** The current active index in the direct to waypoints. */ + public currentWaypointIndex = 0; - /** The segments of the direct plan. */ - public segments?: FlightPlanSegment[]; + /** The segments of the direct plan. */ + public segments?: FlightPlanSegment[]; } diff --git a/fbw-a380x/src/systems/fmgc/src/flightplanning/FixNamingScheme.ts b/fbw-a380x/src/systems/fmgc/src/flightplanning/FixNamingScheme.ts index 4ced20fd64a3..14988a39928a 100644 --- a/fbw-a380x/src/systems/fmgc/src/flightplanning/FixNamingScheme.ts +++ b/fbw-a380x/src/systems/fmgc/src/flightplanning/FixNamingScheme.ts @@ -24,30 +24,30 @@ /** Generates fix names based on the ARINC default naming scheme. */ export class FixNamingScheme { - private static alphabet: string[] = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', - 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z']; + private static alphabet: string[] = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', + 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z']; - /** + /** * Generates a fix name for a vector type fix. * * @returns The generated fix name. */ - public static vector(): string { - return 'MANUAL'; - } + public static vector(): string { + return 'MANUAL'; + } - /** + /** * Generates a fix name for a heading to altitude type fix. * * @param altitudeFeet The altitude that will be flown to. * * @returns The generated fix name. */ - public static headingUntilAltitude(altitudeFeet: number): string { - return Math.round(altitudeFeet).toString(); - } + public static headingUntilAltitude(altitudeFeet: number): string { + return Math.round(altitudeFeet).toString(); + } - /** + /** * Generates a fix name for a course to distance type fix. * * @param course The course that will be flown. @@ -55,21 +55,21 @@ export class FixNamingScheme { * * @returns The generated fix name. */ - public static courseToDistance(course: number, distance: number): string { - const roundedDistance = Math.round(distance); - const distanceAlpha = distance > 26 ? 'Z' : this.alphabet[roundedDistance]; + public static courseToDistance(course: number, distance: number): string { + const roundedDistance = Math.round(distance); + const distanceAlpha = distance > 26 ? 'Z' : this.alphabet[roundedDistance]; - return `D${course.toFixed(0).padStart(3, '0')}${distanceAlpha}`; - } + return `D${course.toFixed(0).padStart(3, '0')}${distanceAlpha}`; + } - /** + /** * Generates a fix name for a course turn to intercept type fix. * * @param course The course that will be turned to. * * @returns The generated fix name. */ - public static courseToIntercept(course: number): string { - return 'INTCPT'; - } + public static courseToIntercept(course: number): string { + return 'INTCPT'; + } } diff --git a/fbw-a380x/src/systems/fmgc/src/flightplanning/FlightPlanAsoboSync.ts b/fbw-a380x/src/systems/fmgc/src/flightplanning/FlightPlanAsoboSync.ts index ceed8892a349..5c7367c6268b 100644 --- a/fbw-a380x/src/systems/fmgc/src/flightplanning/FlightPlanAsoboSync.ts +++ b/fbw-a380x/src/systems/fmgc/src/flightplanning/FlightPlanAsoboSync.ts @@ -111,12 +111,12 @@ export class FlightPlanAsoboSync { console.error(e); }); } else if (data.departureRunwayIndex !== -1 && data.departureProcIndex !== -1) { - await fpln.setOriginRunwayIndexFromDeparture() - // .then(() => console.log(`[FP LOAD] Setting Origin using ${data.departureProcIndex}/${data.departureRunwayIndex}... SUCCESS`)) - .catch((e) => { - console.error(`[FP LOAD] Setting Origin using ${data.departureProcIndex}/${data.departureRunwayIndex} ... FAILED`); - console.error(e); - }); + await fpln.setOriginRunwayIndexFromDeparture() + // .then(() => console.log(`[FP LOAD] Setting Origin using ${data.departureProcIndex}/${data.departureRunwayIndex}... SUCCESS`)) + .catch((e) => { + console.error(`[FP LOAD] Setting Origin using ${data.departureProcIndex}/${data.departureRunwayIndex} ... FAILED`); + console.error(e); + }); } // enroutetrans index await fpln.setDepartureEnRouteTransitionIndex(data.departureEnRouteTransitionIndex) @@ -125,14 +125,14 @@ export class FlightPlanAsoboSync { console.error(`[FP LOAD] Setting Departure En Route Transition ${data.departureEnRouteTransitionIndex} ... FAILED`); console.error(e); }); - // set approach + // set approach // rwy index await fpln.setArrivalRunwayIndex(data.arrivalRunwayIndex) // .then(() => console.log(`[FP LOAD] Setting Arrival Runway ${data.arrivalRunwayIndex} ... SUCCESS`)) - .catch((e) => { - console.error(`[FP LOAD] Setting Arrival Runway ${data.arrivalRunwayIndex} ... FAILED`); - console.error(e); - }); + .catch((e) => { + console.error(`[FP LOAD] Setting Arrival Runway ${data.arrivalRunwayIndex} ... FAILED`); + console.error(e); + }); // approach index await fpln.setApproachIndex(data.approachIndex) // .then(() => console.log(`[FP LOAD] Setting Approach ${data.approachIndex} ... SUCCESS`)) @@ -166,10 +166,10 @@ export class FlightPlanAsoboSync { await fpln.setDestinationRunwayIndexFromApproach() // .then(() => console.log(`[FP LOAD] Setting Destination Runway using ${data.approachIndex} ... SUCCESS`)) - .catch((e) => { - console.error(`[FP LOAD] Setting Destination Runway using ${data.approachIndex} ... FAILED`); - console.error(e); - }); + .catch((e) => { + console.error(`[FP LOAD] Setting Destination Runway using ${data.approachIndex} ... FAILED`); + console.error(e); + }); fpln.resumeSync(); diff --git a/fbw-a380x/src/systems/fmgc/src/flightplanning/FlightPlanSegment.ts b/fbw-a380x/src/systems/fmgc/src/flightplanning/FlightPlanSegment.ts index 3e2dfdcd9d0a..8d0f7706cf18 100644 --- a/fbw-a380x/src/systems/fmgc/src/flightplanning/FlightPlanSegment.ts +++ b/fbw-a380x/src/systems/fmgc/src/flightplanning/FlightPlanSegment.ts @@ -38,8 +38,8 @@ export class FlightPlanSegment { this.waypoints = waypoints; } - /** An empty flight plan segment. */ - public static Empty: FlightPlanSegment = new FlightPlanSegment(-1, -1, []); + /** An empty flight plan segment. */ + public static Empty: FlightPlanSegment = new FlightPlanSegment(-1, -1, []); } /** Types of flight plan segments. */ diff --git a/fbw-a380x/src/systems/fmgc/src/flightplanning/GeoMath.ts b/fbw-a380x/src/systems/fmgc/src/flightplanning/GeoMath.ts index a1d730b5be4b..8fefa740ac50 100644 --- a/fbw-a380x/src/systems/fmgc/src/flightplanning/GeoMath.ts +++ b/fbw-a380x/src/systems/fmgc/src/flightplanning/GeoMath.ts @@ -27,87 +27,87 @@ import { WorldMagneticModel } from './WorldMagneticModel'; /** A class for geographical mathematics. */ export class GeoMath { - private static magneticModel = new WorldMagneticModel(); + private static magneticModel = new WorldMagneticModel(); - /** + /** * Gets coordinates at a relative bearing and distance from a set of coordinates. * @param course The course, in degrees, from the reference coordinates. * @param distanceInNM The distance, in nautical miles, from the reference coordinates. * @param referenceCoordinates The reference coordinates to calculate from. * @returns The calculated coordinates. */ - public static relativeBearingDistanceToCoords(course: number, distanceInNM: number, referenceCoordinates: LatLongAlt): LatLongAlt { - const courseRadians = course * Avionics.Utils.DEG2RAD; - const distanceRadians = (Math.PI / (180 * 60)) * distanceInNM; + public static relativeBearingDistanceToCoords(course: number, distanceInNM: number, referenceCoordinates: LatLongAlt): LatLongAlt { + const courseRadians = course * Avionics.Utils.DEG2RAD; + const distanceRadians = (Math.PI / (180 * 60)) * distanceInNM; - const refLat = referenceCoordinates.lat * Avionics.Utils.DEG2RAD; - const refLon = -(referenceCoordinates.long * Avionics.Utils.DEG2RAD); + const refLat = referenceCoordinates.lat * Avionics.Utils.DEG2RAD; + const refLon = -(referenceCoordinates.long * Avionics.Utils.DEG2RAD); - const lat = Math.asin(Math.sin(refLat) * Math.cos(distanceRadians) + Math.cos(refLat) * Math.sin(distanceRadians) * Math.cos(courseRadians)); - const dlon = Math.atan2(Math.sin(courseRadians) * Math.sin(distanceRadians) * Math.cos(refLat), Math.cos(distanceRadians) - Math.sin(refLat) * Math.sin(lat)); - const lon = Avionics.Utils.fmod(refLon - dlon + Math.PI, 2 * Math.PI) - Math.PI; + const lat = Math.asin(Math.sin(refLat) * Math.cos(distanceRadians) + Math.cos(refLat) * Math.sin(distanceRadians) * Math.cos(courseRadians)); + const dlon = Math.atan2(Math.sin(courseRadians) * Math.sin(distanceRadians) * Math.cos(refLat), Math.cos(distanceRadians) - Math.sin(refLat) * Math.sin(lat)); + const lon = Avionics.Utils.fmod(refLon - dlon + Math.PI, 2 * Math.PI) - Math.PI; - return new LatLongAlt(lat * Avionics.Utils.RAD2DEG, -(lon * Avionics.Utils.RAD2DEG)); - } + return new LatLongAlt(lat * Avionics.Utils.RAD2DEG, -(lon * Avionics.Utils.RAD2DEG)); + } - /** + /** * Gets a magnetic heading given a true course and a magnetic variation. * @param trueCourse The true course to correct. * @param magneticVariation The measured magnetic variation. * @returns The magnetic heading, corrected for magnetic variation. */ - public static correctMagvar(trueCourse: number, magneticVariation: number): number { - return trueCourse - GeoMath.normalizeMagVar(magneticVariation); - } + public static correctMagvar(trueCourse: number, magneticVariation: number): number { + return trueCourse - GeoMath.normalizeMagVar(magneticVariation); + } - /** + /** * Gets a true course given a magnetic heading and a magnetic variation. * @param headingMagnetic The magnetic heading to correct. * @param magneticVariation The measured magnetic variation. * @returns The true course, corrected for magnetic variation. */ - public static removeMagvar(headingMagnetic: number, magneticVariation: number): number { - return headingMagnetic + GeoMath.normalizeMagVar(magneticVariation); - } + public static removeMagvar(headingMagnetic: number, magneticVariation: number): number { + return headingMagnetic + GeoMath.normalizeMagVar(magneticVariation); + } - /** + /** * Gets a magnetic variation difference in 0-360 degrees. * @param magneticVariation The magnetic variation to normalize. * @returns A normalized magnetic variation. */ - private static normalizeMagVar(magneticVariation: number): number { - let normalizedMagVar: number; - if (magneticVariation <= 180) { - normalizedMagVar = magneticVariation; - } else { - normalizedMagVar = magneticVariation - 360; - } + private static normalizeMagVar(magneticVariation: number): number { + let normalizedMagVar: number; + if (magneticVariation <= 180) { + normalizedMagVar = magneticVariation; + } else { + normalizedMagVar = magneticVariation - 360; + } - return normalizedMagVar; - } + return normalizedMagVar; + } - /** + /** * Gets the magnetic variation for a given latitude and longitude. * @param lat The latitude to get a magvar for. * @param lon The longitude to get a magvar for. * @returns The magnetic variation at the specific latitude and longitude. */ - public static getMagvar(lat: number, lon: number): number { - return GeoMath.magneticModel.declination(0, lat, lon, 2020); - } + public static getMagvar(lat: number, lon: number): number { + return GeoMath.magneticModel.declination(0, lat, lon, 2020); + } - public static directedDistanceToGo(from: Coordinates, to: Coordinates, acDirectedLineBearing: number): NauticalMiles { - const absDtg = Avionics.Utils.computeGreatCircleDistance(from, to); + public static directedDistanceToGo(from: Coordinates, to: Coordinates, acDirectedLineBearing: number): NauticalMiles { + const absDtg = Avionics.Utils.computeGreatCircleDistance(from, to); - // @todo should be abeam distance - if (acDirectedLineBearing >= 90 && acDirectedLineBearing <= 270) { - // Since a line perpendicular to the leg is formed by two 90 degree angles, an aircraftLegBearing outside - // (North - 90) and (North + 90) is in the lower quadrants of a plane centered at the TO fix. This means - // the aircraft is NOT past the TO fix, and DTG must be positive. + // @todo should be abeam distance + if (acDirectedLineBearing >= 90 && acDirectedLineBearing <= 270) { + // Since a line perpendicular to the leg is formed by two 90 degree angles, an aircraftLegBearing outside + // (North - 90) and (North + 90) is in the lower quadrants of a plane centered at the TO fix. This means + // the aircraft is NOT past the TO fix, and DTG must be positive. - return absDtg; - } + return absDtg; + } - return -absDtg; - } + return -absDtg; + } } diff --git a/fbw-a380x/src/systems/fmgc/src/flightplanning/LegsProcedure.ts b/fbw-a380x/src/systems/fmgc/src/flightplanning/LegsProcedure.ts index ca52feac9b2f..2ff0d911eb95 100644 --- a/fbw-a380x/src/systems/fmgc/src/flightplanning/LegsProcedure.ts +++ b/fbw-a380x/src/systems/fmgc/src/flightplanning/LegsProcedure.ts @@ -33,44 +33,44 @@ import { RawDataMapper } from './RawDataMapper'; * Creates a collection of waypoints from a legs procedure. */ export class LegsProcedure { - /** The current index in the procedure. */ - private _currentIndex = 0; + /** The current index in the procedure. */ + private _currentIndex = 0; - /** Whether or not there is a discontinuity pending to be mapped. */ - private _isDiscontinuityPending = false; + /** Whether or not there is a discontinuity pending to be mapped. */ + private _isDiscontinuityPending = false; - /** A collection of the loaded facilities needed for this procedure. */ - private _facilities = new Map(); + /** A collection of the loaded facilities needed for this procedure. */ + private _facilities = new Map(); - /** Whether or not the facilities have completed loading. */ - private _facilitiesLoaded = false; + /** Whether or not the facilities have completed loading. */ + private _facilitiesLoaded = false; - /** The collection of facility promises to await on first load. */ - private _facilitiesToLoad = new Map(); + /** The collection of facility promises to await on first load. */ + private _facilitiesToLoad = new Map(); - /** Whether or not a non initial-fix procedure start has been added to the procedure. */ - private _addedProcedureStart = false; + /** Whether or not a non initial-fix procedure start has been added to the procedure. */ + private _addedProcedureStart = false; - /** A normalization factor for calculating distances from triangular ratios. */ - public static distanceNormalFactorNM = (21639 / 2) * Math.PI; + /** A normalization factor for calculating distances from triangular ratios. */ + public static distanceNormalFactorNM = (21639 / 2) * Math.PI; - /** A collection of filtering rules for filtering ICAO data to pre-load for the procedure. */ - private legFilteringRules: ((icao: string) => boolean)[] = [ - (icao) => icao.trim() !== '', // Icao is not empty - (icao) => icao[0] !== 'R', // Icao is not runway icao, which is not searchable - (icao) => icao[0] !== 'A', // Icao is not airport icao, which can be skipped - (icao) => icao.substr(1, 2) !== ' ', // Icao is not missing a region code - (icao) => !this._facilitiesToLoad.has(icao), // Icao is not already being loaded - ]; + /** A collection of filtering rules for filtering ICAO data to pre-load for the procedure. */ + private legFilteringRules: ((icao: string) => boolean)[] = [ + (icao) => icao.trim() !== '', // Icao is not empty + (icao) => icao[0] !== 'R', // Icao is not runway icao, which is not searchable + (icao) => icao[0] !== 'A', // Icao is not airport icao, which can be skipped + (icao) => icao.substr(1, 2) !== ' ', // Icao is not missing a region code + (icao) => !this._facilitiesToLoad.has(icao), // Icao is not already being loaded + ]; - /** + /** * Creates an instance of a LegsProcedure. * @param legs The legs that are part of the procedure. * @param startingPoint The starting point for the procedure. * @param instrument The instrument that is attached to the flight plan. * @param approachType The approach type if this is an approach procedure */ - constructor( + constructor( private _legs: RawProcedureLeg[], private _previousFix: WayPoint, private _instrument: BaseInstrument, @@ -78,287 +78,287 @@ export class LegsProcedure { private approachType?: ApproachType, private legAnnotations?: string[], ) { - for (const leg of this._legs) { - if (this.isIcaoValid(leg.fixIcao)) { - this._facilitiesToLoad.set(leg.fixIcao, this._instrument.facilityLoader.getFacilityRaw(leg.fixIcao, 2000)); - } - - if (this.isIcaoValid(leg.originIcao)) { - this._facilitiesToLoad.set(leg.originIcao, this._instrument.facilityLoader.getFacilityRaw(leg.originIcao, 2000)); - } - - if (this.isIcaoValid(leg.arcCenterFixIcao)) { - this._facilitiesToLoad.set(leg.arcCenterFixIcao, this._instrument.facilityLoader.getFacilityRaw(leg.arcCenterFixIcao, 2000)); - } - } - } - - /** + for (const leg of this._legs) { + if (this.isIcaoValid(leg.fixIcao)) { + this._facilitiesToLoad.set(leg.fixIcao, this._instrument.facilityLoader.getFacilityRaw(leg.fixIcao, 2000)); + } + + if (this.isIcaoValid(leg.originIcao)) { + this._facilitiesToLoad.set(leg.originIcao, this._instrument.facilityLoader.getFacilityRaw(leg.originIcao, 2000)); + } + + if (this.isIcaoValid(leg.arcCenterFixIcao)) { + this._facilitiesToLoad.set(leg.arcCenterFixIcao, this._instrument.facilityLoader.getFacilityRaw(leg.arcCenterFixIcao, 2000)); + } + } + } + + /** * Checks whether or not there are any legs remaining in the procedure. * @returns True if there is a next leg, false otherwise. */ - public hasNext(): boolean { - return this._currentIndex < this._legs.length || this._isDiscontinuityPending; - } - - private async ensureFacilitiesLoaded(): Promise { - if (!this._facilitiesLoaded) { - const facilityResults = await Promise.all(this._facilitiesToLoad.values()); - for (const facility of facilityResults.filter((f) => f !== undefined)) { - this._facilities.set(facility.icao, facility); - } - - this._facilitiesLoaded = true; - } - } - - /** + public hasNext(): boolean { + return this._currentIndex < this._legs.length || this._isDiscontinuityPending; + } + + private async ensureFacilitiesLoaded(): Promise { + if (!this._facilitiesLoaded) { + const facilityResults = await Promise.all(this._facilitiesToLoad.values()); + for (const facility of facilityResults.filter((f) => f !== undefined)) { + this._facilities.set(facility.icao, facility); + } + + this._facilitiesLoaded = true; + } + } + + /** * Gets the next mapped leg from the procedure. * @returns The mapped waypoint from the leg of the procedure. */ - public async getNext(): Promise { - let isLegMappable = false; - let mappedLeg: WayPoint; - - await this.ensureFacilitiesLoaded(); - - while (!isLegMappable && this._currentIndex < this._legs.length) { - const currentLeg = this._legs[this._currentIndex]; - const currentAnnotation = this.legAnnotations[this._currentIndex]; - isLegMappable = true; - - // Some procedures don't start with 15 (initial fix) but instead start with a heading and distance from - // a fix: the procedure then starts with the fix exactly - if (this._currentIndex === 0 && currentLeg.type === 10 && !this._addedProcedureStart) { - mappedLeg = this.mapExactFix(currentLeg); - this._addedProcedureStart = true; - } else { - try { - switch (currentLeg.type) { - case LegType.AF: - mappedLeg = this.mapExactFix(currentLeg); - break; - case LegType.CD: - case LegType.VD: - mappedLeg = this.mapHeadingUntilDistanceFromOrigin(currentLeg, this._previousFix); - break; - case LegType.CF: - // Only map if the fix is itself not a runway fix to avoid double - // adding runway fixes - if (currentLeg.fixIcao === '' || currentLeg.fixIcao[0] !== 'R') { - mappedLeg = this.mapOriginRadialForDistance(currentLeg, this._previousFix); - } else { - isLegMappable = false; - } - break; - case LegType.CI: - case LegType.VI: - mappedLeg = this.mapHeadingToInterceptNextLeg(currentLeg, this._previousFix, this._legs[this._currentIndex + 1]); - break; - case LegType.CR: - case LegType.VR: - mappedLeg = this.mapHeadingUntilRadialCrossing(currentLeg, this._previousFix); - break; - case LegType.FC: - case LegType.FD: - mappedLeg = this.mapBearingAndDistanceFromOrigin(currentLeg); - break; - case LegType.FM: - case LegType.VM: - mappedLeg = this.mapVectors(currentLeg, this._previousFix); - break; - case LegType.IF: - if (currentLeg.fixIcao[0] !== 'A') { - const leg = this.mapExactFix(currentLeg); - const prevLeg = this._previousFix; - - // If a type 15 (initial fix) comes up in the middle of a plan - if (leg.icao === prevLeg.icao && leg.infos.coordinates.lat === prevLeg.infos.coordinates.lat + public async getNext(): Promise { + let isLegMappable = false; + let mappedLeg: WayPoint; + + await this.ensureFacilitiesLoaded(); + + while (!isLegMappable && this._currentIndex < this._legs.length) { + const currentLeg = this._legs[this._currentIndex]; + const currentAnnotation = this.legAnnotations[this._currentIndex]; + isLegMappable = true; + + // Some procedures don't start with 15 (initial fix) but instead start with a heading and distance from + // a fix: the procedure then starts with the fix exactly + if (this._currentIndex === 0 && currentLeg.type === 10 && !this._addedProcedureStart) { + mappedLeg = this.mapExactFix(currentLeg); + this._addedProcedureStart = true; + } else { + try { + switch (currentLeg.type) { + case LegType.AF: + mappedLeg = this.mapExactFix(currentLeg); + break; + case LegType.CD: + case LegType.VD: + mappedLeg = this.mapHeadingUntilDistanceFromOrigin(currentLeg, this._previousFix); + break; + case LegType.CF: + // Only map if the fix is itself not a runway fix to avoid double + // adding runway fixes + if (currentLeg.fixIcao === '' || currentLeg.fixIcao[0] !== 'R') { + mappedLeg = this.mapOriginRadialForDistance(currentLeg, this._previousFix); + } else { + isLegMappable = false; + } + break; + case LegType.CI: + case LegType.VI: + mappedLeg = this.mapHeadingToInterceptNextLeg(currentLeg, this._previousFix, this._legs[this._currentIndex + 1]); + break; + case LegType.CR: + case LegType.VR: + mappedLeg = this.mapHeadingUntilRadialCrossing(currentLeg, this._previousFix); + break; + case LegType.FC: + case LegType.FD: + mappedLeg = this.mapBearingAndDistanceFromOrigin(currentLeg); + break; + case LegType.FM: + case LegType.VM: + mappedLeg = this.mapVectors(currentLeg, this._previousFix); + break; + case LegType.IF: + if (currentLeg.fixIcao[0] !== 'A') { + const leg = this.mapExactFix(currentLeg); + const prevLeg = this._previousFix; + + // If a type 15 (initial fix) comes up in the middle of a plan + if (leg.icao === prevLeg.icao && leg.infos.coordinates.lat === prevLeg.infos.coordinates.lat && leg.infos.coordinates.long === prevLeg.infos.coordinates.long) { - isLegMappable = false; - } else { - mappedLeg = leg; - } - } else { - // If type 15 is an airport itself, we don't need to map it (and the data is generally wrong) - isLegMappable = false; - } - break; - case LegType.DF: - case LegType.TF: - // Only map if the fix is itself not a runway fix to avoid double - // adding runway fixes - if (currentLeg.fixIcao === '' || currentLeg.fixIcao[0] !== 'R') { - mappedLeg = this.mapExactFix(currentLeg); - } else { - isLegMappable = false; - } - break; - case LegType.RF: - mappedLeg = this.mapRadiusToFix(currentLeg); - break; - case LegType.CA: - case LegType.VA: - mappedLeg = this.mapHeadingUntilAltitude(currentLeg, this._previousFix); - break; - case LegType.HA: - case LegType.HF: - case LegType.HM: - mappedLeg = this.mapHold(currentLeg); - break; - default: - isLegMappable = false; - break; - } - } catch (err) { - console.log(`LegsProcedure: Unexpected unmappable leg: ${err}`); - } - - if (mappedLeg !== undefined) { - const magCorrection = this.getMagCorrection(currentLeg); - - if (this.approachType === ApproachType.APPROACH_TYPE_ILS && (currentLeg.fixTypeFlags & FixTypeFlags.FAF) > 0) { - if (currentLeg.altDesc === AltitudeDescriptor.At) { - mappedLeg.legAltitudeDescription = AltitudeDescriptor.G; - } else { - mappedLeg.legAltitudeDescription = AltitudeDescriptor.H; - } - } else { - mappedLeg.legAltitudeDescription = currentLeg.altDesc; - } - mappedLeg.legAltitude1 = currentLeg.altitude1 * 3.28084; - mappedLeg.legAltitude2 = currentLeg.altitude2 * 3.28084; - mappedLeg.speedConstraint = currentLeg.speedRestriction; - mappedLeg.turnDirection = currentLeg.turnDirection; - - const recNavaid: RawVor | RawNdb | undefined = this._facilities.get(currentLeg.originIcao); - - mappedLeg.additionalData.legType = currentLeg.type; - mappedLeg.additionalData.overfly = currentLeg.flyOver; - mappedLeg.additionalData.fixTypeFlags = currentLeg.fixTypeFlags; - mappedLeg.additionalData.distance = currentLeg.distanceMinutes ? undefined : currentLeg.distance / 1852; - mappedLeg.additionalData.distanceInMinutes = currentLeg.distanceMinutes ? currentLeg.distance : undefined; - mappedLeg.additionalData.course = currentLeg.trueDegrees ? currentLeg.course : A32NX_Util.magneticToTrue(currentLeg.course, magCorrection); - mappedLeg.additionalData.recommendedIcao = currentLeg.originIcao.trim().length > 0 ? currentLeg.originIcao : undefined; - mappedLeg.additionalData.recommendedFrequency = recNavaid ? recNavaid.freqMHz : undefined; - mappedLeg.additionalData.recommendedLocation = recNavaid ? { lat: recNavaid.lat, long: recNavaid.lon } : undefined; - mappedLeg.additionalData.rho = currentLeg.rho / 1852; - mappedLeg.additionalData.theta = currentLeg.theta; - mappedLeg.additionalData.thetaTrue = A32NX_Util.magneticToTrue(currentLeg.theta, magCorrection); - mappedLeg.additionalData.annotation = currentAnnotation; - } - - this._currentIndex++; - } - } - - if (mappedLeg !== undefined) { - this._previousFix = mappedLeg; - return mappedLeg; - } - - return undefined; - } - - private getMagCorrection(currentLeg: RawProcedureLeg): number { + isLegMappable = false; + } else { + mappedLeg = leg; + } + } else { + // If type 15 is an airport itself, we don't need to map it (and the data is generally wrong) + isLegMappable = false; + } + break; + case LegType.DF: + case LegType.TF: + // Only map if the fix is itself not a runway fix to avoid double + // adding runway fixes + if (currentLeg.fixIcao === '' || currentLeg.fixIcao[0] !== 'R') { + mappedLeg = this.mapExactFix(currentLeg); + } else { + isLegMappable = false; + } + break; + case LegType.RF: + mappedLeg = this.mapRadiusToFix(currentLeg); + break; + case LegType.CA: + case LegType.VA: + mappedLeg = this.mapHeadingUntilAltitude(currentLeg, this._previousFix); + break; + case LegType.HA: + case LegType.HF: + case LegType.HM: + mappedLeg = this.mapHold(currentLeg); + break; + default: + isLegMappable = false; + break; + } + } catch (err) { + console.log(`LegsProcedure: Unexpected unmappable leg: ${err}`); + } + + if (mappedLeg !== undefined) { + const magCorrection = this.getMagCorrection(currentLeg); + + if (this.approachType === ApproachType.APPROACH_TYPE_ILS && (currentLeg.fixTypeFlags & FixTypeFlags.FAF) > 0) { + if (currentLeg.altDesc === AltitudeDescriptor.At) { + mappedLeg.legAltitudeDescription = AltitudeDescriptor.G; + } else { + mappedLeg.legAltitudeDescription = AltitudeDescriptor.H; + } + } else { + mappedLeg.legAltitudeDescription = currentLeg.altDesc; + } + mappedLeg.legAltitude1 = currentLeg.altitude1 * 3.28084; + mappedLeg.legAltitude2 = currentLeg.altitude2 * 3.28084; + mappedLeg.speedConstraint = currentLeg.speedRestriction; + mappedLeg.turnDirection = currentLeg.turnDirection; + + const recNavaid: RawVor | RawNdb | undefined = this._facilities.get(currentLeg.originIcao); + + mappedLeg.additionalData.legType = currentLeg.type; + mappedLeg.additionalData.overfly = currentLeg.flyOver; + mappedLeg.additionalData.fixTypeFlags = currentLeg.fixTypeFlags; + mappedLeg.additionalData.distance = currentLeg.distanceMinutes ? undefined : currentLeg.distance / 1852; + mappedLeg.additionalData.distanceInMinutes = currentLeg.distanceMinutes ? currentLeg.distance : undefined; + mappedLeg.additionalData.course = currentLeg.trueDegrees ? currentLeg.course : A32NX_Util.magneticToTrue(currentLeg.course, magCorrection); + mappedLeg.additionalData.recommendedIcao = currentLeg.originIcao.trim().length > 0 ? currentLeg.originIcao : undefined; + mappedLeg.additionalData.recommendedFrequency = recNavaid ? recNavaid.freqMHz : undefined; + mappedLeg.additionalData.recommendedLocation = recNavaid ? { lat: recNavaid.lat, long: recNavaid.lon } : undefined; + mappedLeg.additionalData.rho = currentLeg.rho / 1852; + mappedLeg.additionalData.theta = currentLeg.theta; + mappedLeg.additionalData.thetaTrue = A32NX_Util.magneticToTrue(currentLeg.theta, magCorrection); + mappedLeg.additionalData.annotation = currentAnnotation; + } + + this._currentIndex++; + } + } + + if (mappedLeg !== undefined) { + this._previousFix = mappedLeg; + return mappedLeg; + } + + return undefined; + } + + private getMagCorrection(currentLeg: RawProcedureLeg): number { // we try to interpret PANS OPs as accurately as possible within the limits of available data - // magnetic tracks to/from a VOR always use VOR station declination - if (currentLeg.fixIcao.charAt(0) === 'V') { - const vor: RawVor = this._facilities.get(currentLeg.fixIcao); - if (!vor || vor.magneticVariation === undefined) { - console.warn('Leg coded incorrectly (missing vor fix or station declination)', currentLeg, vor); - return this.airportMagVar; - } - return 360 - vor.magneticVariation; - } + // magnetic tracks to/from a VOR always use VOR station declination + if (currentLeg.fixIcao.charAt(0) === 'V') { + const vor: RawVor = this._facilities.get(currentLeg.fixIcao); + if (!vor || vor.magneticVariation === undefined) { + console.warn('Leg coded incorrectly (missing vor fix or station declination)', currentLeg, vor); + return this.airportMagVar; + } + return 360 - vor.magneticVariation; + } - // we use station declination for VOR/DME approaches - if (this.approachType === ApproachType.APPROACH_TYPE_VORDME) { - // find a leg with the reference navaid for the procedure - for (let i = this._legs.length - 1; i >= 0; i--) { - if (this._legs[i].originIcao.trim().length > 0) { - const recNavaid: RawVor = this._facilities.get(currentLeg.originIcao); - if (recNavaid && recNavaid.magneticVariation !== undefined) { - return 360 - recNavaid.magneticVariation; - } - } - } - console.warn('VOR/DME approach coded incorrectly (missing recommended navaid or station declination)', currentLeg); - return this.airportMagVar; + // we use station declination for VOR/DME approaches + if (this.approachType === ApproachType.APPROACH_TYPE_VORDME) { + // find a leg with the reference navaid for the procedure + for (let i = this._legs.length - 1; i >= 0; i--) { + if (this._legs[i].originIcao.trim().length > 0) { + const recNavaid: RawVor = this._facilities.get(currentLeg.originIcao); + if (recNavaid && recNavaid.magneticVariation !== undefined) { + return 360 - recNavaid.magneticVariation; + } } + } + console.warn('VOR/DME approach coded incorrectly (missing recommended navaid or station declination)', currentLeg); + return this.airportMagVar; + } - // for RNAV procedures use recommended navaid station declination for these leg types - let useStationDeclination = (currentLeg.type === LegType.CF || currentLeg.type === LegType.FA || currentLeg.type === LegType.FM); + // for RNAV procedures use recommended navaid station declination for these leg types + let useStationDeclination = (currentLeg.type === LegType.CF || currentLeg.type === LegType.FA || currentLeg.type === LegType.FM); - // for localiser bearings (i.e. at or beyond FACF), always use airport value - if (this.approachType === ApproachType.APPROACH_TYPE_ILS || this.approachType === ApproachType.APPROACH_TYPE_LOCALIZER) { - useStationDeclination = useStationDeclination && this._legs.indexOf(currentLeg) < this.getFacfIndex(); - } - - if (useStationDeclination) { - const recNavaid: RawVor = this._facilities.get(currentLeg.originIcao); - if (!recNavaid || recNavaid.magneticVariation === undefined) { - console.warn('Leg coded incorrectly (missing recommended navaid or station declination)', currentLeg, recNavaid); - return this.airportMagVar; - } - return 360 - recNavaid.magneticVariation; - } + // for localiser bearings (i.e. at or beyond FACF), always use airport value + if (this.approachType === ApproachType.APPROACH_TYPE_ILS || this.approachType === ApproachType.APPROACH_TYPE_LOCALIZER) { + useStationDeclination = useStationDeclination && this._legs.indexOf(currentLeg) < this.getFacfIndex(); + } - // for all other terminal procedure legs we use airport magnetic variation + if (useStationDeclination) { + const recNavaid: RawVor = this._facilities.get(currentLeg.originIcao); + if (!recNavaid || recNavaid.magneticVariation === undefined) { + console.warn('Leg coded incorrectly (missing recommended navaid or station declination)', currentLeg, recNavaid); return this.airportMagVar; + } + return 360 - recNavaid.magneticVariation; } - private getFacfIndex(): number { - if (this.approachType !== undefined) { - for (let i = this._legs.length - 1; i >= 0; i--) { - if (this._legs[i].fixTypeFlags & FixTypeFlags.IF) { - return i; - } - } - } + // for all other terminal procedure legs we use airport magnetic variation + return this.airportMagVar; + } - return undefined; + private getFacfIndex(): number { + if (this.approachType !== undefined) { + for (let i = this._legs.length - 1; i >= 0; i--) { + if (this._legs[i].fixTypeFlags & FixTypeFlags.IF) { + return i; + } + } } - /** + return undefined; + } + + /** * Maps a heading until distance from origin leg. * @param leg The procedure leg to map. * @param prevLeg The previously mapped waypoint in the procedure. * @returns The mapped leg. */ - public mapHeadingUntilDistanceFromOrigin(leg: RawProcedureLeg, prevLeg: WayPoint): WayPoint { - const origin = this._facilities.get(leg.originIcao); - const originIdent = origin.icao.substring(7, 12).trim(); + public mapHeadingUntilDistanceFromOrigin(leg: RawProcedureLeg, prevLeg: WayPoint): WayPoint { + const origin = this._facilities.get(leg.originIcao); + const originIdent = origin.icao.substring(7, 12).trim(); - const bearingToOrigin = Avionics.Utils.computeGreatCircleHeading(prevLeg.infos.coordinates, new LatLongAlt(origin.lat, origin.lon)); - const distanceToOrigin = Avionics.Utils.computeGreatCircleDistance(prevLeg.infos.coordinates, new LatLongAlt(origin.lat, origin.lon)) / LegsProcedure.distanceNormalFactorNM; + const bearingToOrigin = Avionics.Utils.computeGreatCircleHeading(prevLeg.infos.coordinates, new LatLongAlt(origin.lat, origin.lon)); + const distanceToOrigin = Avionics.Utils.computeGreatCircleDistance(prevLeg.infos.coordinates, new LatLongAlt(origin.lat, origin.lon)) / LegsProcedure.distanceNormalFactorNM; - const deltaAngle = this.deltaAngleRadians(bearingToOrigin, leg.course); - const targetDistance = (leg.distance / 1852) / LegsProcedure.distanceNormalFactorNM; + const deltaAngle = this.deltaAngleRadians(bearingToOrigin, leg.course); + const targetDistance = (leg.distance / 1852) / LegsProcedure.distanceNormalFactorNM; - const distanceAngle = Math.asin((Math.sin(distanceToOrigin) * Math.sin(deltaAngle)) / Math.sin(targetDistance)); - const inverseDistanceAngle = Math.PI - distanceAngle; + const distanceAngle = Math.asin((Math.sin(distanceToOrigin) * Math.sin(deltaAngle)) / Math.sin(targetDistance)); + const inverseDistanceAngle = Math.PI - distanceAngle; - const legDistance1 = 2 * Math.atan(Math.tan(0.5 * (targetDistance - distanceToOrigin)) * (Math.sin(0.5 * (deltaAngle + distanceAngle)) + const legDistance1 = 2 * Math.atan(Math.tan(0.5 * (targetDistance - distanceToOrigin)) * (Math.sin(0.5 * (deltaAngle + distanceAngle)) / Math.sin(0.5 * (deltaAngle - distanceAngle)))); - const legDistance2 = 2 * Math.atan(Math.tan(0.5 * (targetDistance - distanceToOrigin)) * (Math.sin(0.5 * (deltaAngle + inverseDistanceAngle)) + const legDistance2 = 2 * Math.atan(Math.tan(0.5 * (targetDistance - distanceToOrigin)) * (Math.sin(0.5 * (deltaAngle + inverseDistanceAngle)) / Math.sin(0.5 * (deltaAngle - inverseDistanceAngle)))); - const legDistance = targetDistance > distanceToOrigin ? legDistance1 : Math.min(legDistance1, legDistance2); - const course = leg.course + GeoMath.getMagvar(prevLeg.infos.coordinates.lat, prevLeg.infos.coordinates.long); - const coordinates = Avionics.Utils.bearingDistanceToCoordinates( - course, - legDistance * LegsProcedure.distanceNormalFactorNM, prevLeg.infos.coordinates.lat, prevLeg.infos.coordinates.long, - ); + const legDistance = targetDistance > distanceToOrigin ? legDistance1 : Math.min(legDistance1, legDistance2); + const course = leg.course + GeoMath.getMagvar(prevLeg.infos.coordinates.lat, prevLeg.infos.coordinates.long); + const coordinates = Avionics.Utils.bearingDistanceToCoordinates( + course, + legDistance * LegsProcedure.distanceNormalFactorNM, prevLeg.infos.coordinates.lat, prevLeg.infos.coordinates.long, + ); - const waypoint = this.buildWaypoint(`${originIdent}${Math.trunc(legDistance * LegsProcedure.distanceNormalFactorNM)}`, coordinates); + const waypoint = this.buildWaypoint(`${originIdent}${Math.trunc(legDistance * LegsProcedure.distanceNormalFactorNM)}`, coordinates); - return waypoint; - } + return waypoint; + } - /** + /** * Maps an FC or FD leg in the procedure. * @note FC and FD legs are mapped to CF legs in the real FMS * @todo move the code into the CF leg (maybe static functions fromFc and fromFd to construct the leg) @@ -366,332 +366,332 @@ export class LegsProcedure { * @param leg The procedure leg to map. * @returns The mapped leg. */ - public mapBearingAndDistanceFromOrigin(leg: RawProcedureLeg): WayPoint { - const origin = this._facilities.get(leg.fixIcao); - const originIdent = origin.icao.substring(7, 12).trim(); - const course = leg.trueDegrees ? leg.course : A32NX_Util.magneticToTrue(leg.course, Facilities.getMagVar(origin.lat, origin.lon)); - // this is the leg length for FC, and the DME distance for FD - const refDistance = leg.distance / 1852; - - let termPoint; - let legLength; - if (leg.type === LegType.FD) { - const recNavaid = this._facilities.get(leg.originIcao); - termPoint = firstSmallCircleIntersection( - { lat: recNavaid.lat, long: recNavaid.lon }, - refDistance, - { lat: origin.lat, long: origin.lon }, - course, - ); - legLength = Avionics.Utils.computeGreatCircleDistance( - { lat: origin.lat, long: origin.lon }, - termPoint, - ); - } else { // FC - termPoint = Avionics.Utils.bearingDistanceToCoordinates( - course, - refDistance, - origin.lat, - origin.lon, - ); - legLength = refDistance; - } - - return this.buildWaypoint(`${originIdent.substring(0, 3)}/${Math.round(legLength).toString().padStart(2, '0')}`, termPoint); + public mapBearingAndDistanceFromOrigin(leg: RawProcedureLeg): WayPoint { + const origin = this._facilities.get(leg.fixIcao); + const originIdent = origin.icao.substring(7, 12).trim(); + const course = leg.trueDegrees ? leg.course : A32NX_Util.magneticToTrue(leg.course, Facilities.getMagVar(origin.lat, origin.lon)); + // this is the leg length for FC, and the DME distance for FD + const refDistance = leg.distance / 1852; + + let termPoint; + let legLength; + if (leg.type === LegType.FD) { + const recNavaid = this._facilities.get(leg.originIcao); + termPoint = firstSmallCircleIntersection( + { lat: recNavaid.lat, long: recNavaid.lon }, + refDistance, + { lat: origin.lat, long: origin.lon }, + course, + ); + legLength = Avionics.Utils.computeGreatCircleDistance( + { lat: origin.lat, long: origin.lon }, + termPoint, + ); + } else { // FC + termPoint = Avionics.Utils.bearingDistanceToCoordinates( + course, + refDistance, + origin.lat, + origin.lon, + ); + legLength = refDistance; } - /** + return this.buildWaypoint(`${originIdent.substring(0, 3)}/${Math.round(legLength).toString().padStart(2, '0')}`, termPoint); + } + + /** * Maps a radial on the origin for a specified distance leg in the procedure. * @param leg The procedure leg to map. * @param prevLeg The previously mapped leg. * @returns The mapped leg. */ - public mapOriginRadialForDistance(leg: RawProcedureLeg, prevLeg: WayPoint): WayPoint { - if (leg.fixIcao.trim() !== '') { - return this.mapExactFix(leg); - } + public mapOriginRadialForDistance(leg: RawProcedureLeg, prevLeg: WayPoint): WayPoint { + if (leg.fixIcao.trim() !== '') { + return this.mapExactFix(leg); + } - const origin = this._facilities.get(leg.originIcao); - const originIdent = origin.icao.substring(7, 12).trim(); + const origin = this._facilities.get(leg.originIcao); + const originIdent = origin.icao.substring(7, 12).trim(); - const course = leg.course + GeoMath.getMagvar(prevLeg.infos.coordinates.lat, prevLeg.infos.coordinates.long); - const coordinates = Avionics.Utils.bearingDistanceToCoordinates(course, leg.distance / 1852, prevLeg.infos.coordinates.lat, prevLeg.infos.coordinates.long); + const course = leg.course + GeoMath.getMagvar(prevLeg.infos.coordinates.lat, prevLeg.infos.coordinates.long); + const coordinates = Avionics.Utils.bearingDistanceToCoordinates(course, leg.distance / 1852, prevLeg.infos.coordinates.lat, prevLeg.infos.coordinates.long); - const distanceFromOrigin = Avionics.Utils.computeGreatCircleDistance(new LatLongAlt(origin.lat, origin.lon), coordinates); - return this.buildWaypoint(`${originIdent}${Math.trunc(distanceFromOrigin / 1852)}`, coordinates); - } + const distanceFromOrigin = Avionics.Utils.computeGreatCircleDistance(new LatLongAlt(origin.lat, origin.lon), coordinates); + return this.buildWaypoint(`${originIdent}${Math.trunc(distanceFromOrigin / 1852)}`, coordinates); + } - /** + /** * Maps a heading turn to intercept the next leg in the procedure. * @param leg The procedure leg to map. * @param prevLeg The previously mapped leg. * @param nextLeg The next leg in the procedure to intercept. * @returns The mapped leg. */ - public mapHeadingToInterceptNextLeg(leg: RawProcedureLeg, prevLeg: WayPoint, nextLeg: RawProcedureLeg): WayPoint | null { - const magVar = Facilities.getMagVar(prevLeg.infos.coordinates.lat, prevLeg.infos.coordinates.long); - const course = leg.trueDegrees ? leg.course : A32NX_Util.magneticToTrue(leg.course, magVar); + public mapHeadingToInterceptNextLeg(leg: RawProcedureLeg, prevLeg: WayPoint, nextLeg: RawProcedureLeg): WayPoint | null { + const magVar = Facilities.getMagVar(prevLeg.infos.coordinates.lat, prevLeg.infos.coordinates.long); + const course = leg.trueDegrees ? leg.course : A32NX_Util.magneticToTrue(leg.course, magVar); - const coordinates = GeoMath.relativeBearingDistanceToCoords(course, 1, prevLeg.infos.coordinates); - const waypoint = this.buildWaypoint(FixNamingScheme.courseToIntercept(course), coordinates, prevLeg.infos.magneticVariation); + const coordinates = GeoMath.relativeBearingDistanceToCoords(course, 1, prevLeg.infos.coordinates); + const waypoint = this.buildWaypoint(FixNamingScheme.courseToIntercept(course), coordinates, prevLeg.infos.magneticVariation); - return waypoint; - } + return waypoint; + } - /** + /** * Maps flying a heading until crossing a radial of a reference fix. * @param leg The procedure leg to map. * @param prevLeg The previously mapped leg. * @returns The mapped leg. */ - public mapHeadingUntilRadialCrossing(leg: RawProcedureLeg, prevLeg: WayPoint) { - const origin = this._facilities.get(leg.originIcao); - const originCoordinates = new LatLongAlt(origin.lat, origin.lon); + public mapHeadingUntilRadialCrossing(leg: RawProcedureLeg, prevLeg: WayPoint) { + const origin = this._facilities.get(leg.originIcao); + const originCoordinates = new LatLongAlt(origin.lat, origin.lon); - const originToCoordinates = Avionics.Utils.computeGreatCircleHeading(originCoordinates, prevLeg.infos.coordinates); - const coordinatesToOrigin = Avionics.Utils.computeGreatCircleHeading(prevLeg.infos.coordinates, new LatLongAlt(origin.lat, origin.lon)); - const distanceToOrigin = Avionics.Utils.computeGreatCircleDistance(prevLeg.infos.coordinates, originCoordinates) / LegsProcedure.distanceNormalFactorNM; + const originToCoordinates = Avionics.Utils.computeGreatCircleHeading(originCoordinates, prevLeg.infos.coordinates); + const coordinatesToOrigin = Avionics.Utils.computeGreatCircleHeading(prevLeg.infos.coordinates, new LatLongAlt(origin.lat, origin.lon)); + const distanceToOrigin = Avionics.Utils.computeGreatCircleDistance(prevLeg.infos.coordinates, originCoordinates) / LegsProcedure.distanceNormalFactorNM; - const alpha = this.deltaAngleRadians(coordinatesToOrigin, leg.course); - const beta = this.deltaAngleRadians(originToCoordinates, leg.theta); + const alpha = this.deltaAngleRadians(coordinatesToOrigin, leg.course); + const beta = this.deltaAngleRadians(originToCoordinates, leg.theta); - const gamma = Math.acos(Math.sin(alpha) * Math.sin(beta) * Math.cos(distanceToOrigin) - Math.cos(alpha) * Math.cos(beta)); - const legDistance = Math.acos((Math.cos(beta) + Math.cos(alpha) * Math.cos(gamma)) / (Math.sin(alpha) * Math.sin(gamma))); + const gamma = Math.acos(Math.sin(alpha) * Math.sin(beta) * Math.cos(distanceToOrigin) - Math.cos(alpha) * Math.cos(beta)); + const legDistance = Math.acos((Math.cos(beta) + Math.cos(alpha) * Math.cos(gamma)) / (Math.sin(alpha) * Math.sin(gamma))); - const magVar = Facilities.getMagVar(prevLeg.infos.coordinates.lat, prevLeg.infos.coordinates.long); - const course = leg.trueDegrees ? leg.course : A32NX_Util.magneticToTrue(leg.course, magVar); + const magVar = Facilities.getMagVar(prevLeg.infos.coordinates.lat, prevLeg.infos.coordinates.long); + const course = leg.trueDegrees ? leg.course : A32NX_Util.magneticToTrue(leg.course, magVar); - const coordinates = Avionics.Utils.bearingDistanceToCoordinates( - course, - legDistance * LegsProcedure.distanceNormalFactorNM, prevLeg.infos.coordinates.lat, prevLeg.infos.coordinates.long, - ); + const coordinates = Avionics.Utils.bearingDistanceToCoordinates( + course, + legDistance * LegsProcedure.distanceNormalFactorNM, prevLeg.infos.coordinates.lat, prevLeg.infos.coordinates.long, + ); - const waypoint = this.buildWaypoint(`${this.getIdent(origin.icao)}${leg.theta}`, coordinates); + const waypoint = this.buildWaypoint(`${this.getIdent(origin.icao)}${leg.theta}`, coordinates); - return waypoint; - } + return waypoint; + } - /** + /** * Maps flying a heading until a proscribed altitude. * @param leg The procedure leg to map. * @param prevLeg The previous leg in the procedure. * @returns The mapped leg. */ - public mapHeadingUntilAltitude(leg: RawProcedureLeg, prevLeg: WayPoint) { - const magVar = Facilities.getMagVar(prevLeg.infos.coordinates.lat, prevLeg.infos.coordinates.long); - const course = leg.trueDegrees ? leg.course : A32NX_Util.magneticToTrue(leg.course, magVar); - const heading = leg.trueDegrees ? A32NX_Util.trueToMagnetic(leg.course, magVar) : leg.course; - const altitudeFeet = (leg.altitude1 * 3.2808399); - const distanceInNM = altitudeFeet / 500.0; + public mapHeadingUntilAltitude(leg: RawProcedureLeg, prevLeg: WayPoint) { + const magVar = Facilities.getMagVar(prevLeg.infos.coordinates.lat, prevLeg.infos.coordinates.long); + const course = leg.trueDegrees ? leg.course : A32NX_Util.magneticToTrue(leg.course, magVar); + const heading = leg.trueDegrees ? A32NX_Util.trueToMagnetic(leg.course, magVar) : leg.course; + const altitudeFeet = (leg.altitude1 * 3.2808399); + const distanceInNM = altitudeFeet / 500.0; - const coordinates = GeoMath.relativeBearingDistanceToCoords(course, distanceInNM, prevLeg.infos.coordinates); - const waypoint = this.buildWaypoint(FixNamingScheme.headingUntilAltitude(altitudeFeet), coordinates, prevLeg.infos.magneticVariation); + const coordinates = GeoMath.relativeBearingDistanceToCoords(course, distanceInNM, prevLeg.infos.coordinates); + const waypoint = this.buildWaypoint(FixNamingScheme.headingUntilAltitude(altitudeFeet), coordinates, prevLeg.infos.magneticVariation); - waypoint.additionalData.vectorsAltitude = altitudeFeet; + waypoint.additionalData.vectorsAltitude = altitudeFeet; - return waypoint; - } + return waypoint; + } - /** + /** * Maps a vectors instruction. * @param leg The procedure leg to map. * @param prevLeg The previous leg in the procedure. * @returns The mapped leg. */ - public mapVectors(leg: RawProcedureLeg, prevLeg: WayPoint) { - const magVar = Facilities.getMagVar(prevLeg.infos.coordinates.lat, prevLeg.infos.coordinates.long); - const course = leg.trueDegrees ? leg.course : A32NX_Util.magneticToTrue(leg.course, magVar); - const heading = leg.trueDegrees ? A32NX_Util.trueToMagnetic(leg.course, magVar) : leg.course; - const coordinates = GeoMath.relativeBearingDistanceToCoords(course, 1, prevLeg.infos.coordinates); - - const waypoint = this.buildWaypoint(FixNamingScheme.vector(), coordinates); - waypoint.isVectors = true; - waypoint.endsInDiscontinuity = true; - waypoint.discontinuityCanBeCleared = false; - - return waypoint; - } + public mapVectors(leg: RawProcedureLeg, prevLeg: WayPoint) { + const magVar = Facilities.getMagVar(prevLeg.infos.coordinates.lat, prevLeg.infos.coordinates.long); + const course = leg.trueDegrees ? leg.course : A32NX_Util.magneticToTrue(leg.course, magVar); + const heading = leg.trueDegrees ? A32NX_Util.trueToMagnetic(leg.course, magVar) : leg.course; + const coordinates = GeoMath.relativeBearingDistanceToCoords(course, 1, prevLeg.infos.coordinates); + + const waypoint = this.buildWaypoint(FixNamingScheme.vector(), coordinates); + waypoint.isVectors = true; + waypoint.endsInDiscontinuity = true; + waypoint.discontinuityCanBeCleared = false; - /** + return waypoint; + } + + /** * Maps an exact fix leg in the procedure. * @param leg The procedure leg to map. * @returns The mapped leg. */ - public mapExactFix(leg: RawProcedureLeg): WayPoint { - const facility = this._facilities.get(leg.fixIcao); - return RawDataMapper.toWaypoint(facility, this._instrument); - } + public mapExactFix(leg: RawProcedureLeg): WayPoint { + const facility = this._facilities.get(leg.fixIcao); + return RawDataMapper.toWaypoint(facility, this._instrument); + } - public mapArcToFix(leg: RawProcedureLeg, prevLeg: WayPoint): WayPoint { - const toFix = this._facilities.get(leg.fixIcao); + public mapArcToFix(leg: RawProcedureLeg, prevLeg: WayPoint): WayPoint { + const toFix = this._facilities.get(leg.fixIcao); - const waypoint = RawDataMapper.toWaypoint(toFix, this._instrument); + const waypoint = RawDataMapper.toWaypoint(toFix, this._instrument); - return waypoint; - } + return waypoint; + } - public mapRadiusToFix(leg: RawProcedureLeg): WayPoint { - const arcCentreFix = this._facilities.get(leg.arcCenterFixIcao); - const arcCenterCoordinates = new LatLongAlt(arcCentreFix.lat, arcCentreFix.lon, 0); + public mapRadiusToFix(leg: RawProcedureLeg): WayPoint { + const arcCentreFix = this._facilities.get(leg.arcCenterFixIcao); + const arcCenterCoordinates = new LatLongAlt(arcCentreFix.lat, arcCentreFix.lon, 0); - const toFix = this._facilities.get(leg.fixIcao); - const toCoordinates = new LatLongAlt(toFix.lat, toFix.lon, 0); + const toFix = this._facilities.get(leg.fixIcao); + const toCoordinates = new LatLongAlt(toFix.lat, toFix.lon, 0); - const radius = Avionics.Utils.computeGreatCircleDistance(arcCenterCoordinates, toCoordinates); - const waypoint = RawDataMapper.toWaypoint(toFix, this._instrument); + const radius = Avionics.Utils.computeGreatCircleDistance(arcCenterCoordinates, toCoordinates); + const waypoint = RawDataMapper.toWaypoint(toFix, this._instrument); - waypoint.additionalData.radius = radius; - waypoint.additionalData.center = arcCenterCoordinates; + waypoint.additionalData.radius = radius; + waypoint.additionalData.center = arcCenterCoordinates; - return waypoint; - } + return waypoint; + } - public mapHold(leg: RawProcedureLeg): WayPoint { - const facility = this._facilities.get(leg.fixIcao); - const waypoint = RawDataMapper.toWaypoint(facility, this._instrument); + public mapHold(leg: RawProcedureLeg): WayPoint { + const facility = this._facilities.get(leg.fixIcao); + const waypoint = RawDataMapper.toWaypoint(facility, this._instrument); - const magVar = Facilities.getMagVar(facility.lat, facility.lon); + const magVar = Facilities.getMagVar(facility.lat, facility.lon); - (waypoint.additionalData.defaultHold as HoldData) = { - inboundMagneticCourse: leg.trueDegrees ? A32NX_Util.trueToMagnetic(leg.course, magVar) : leg.course, - turnDirection: leg.turnDirection, - distance: leg.distanceMinutes ? undefined : leg.distance / 1852, - time: leg.distanceMinutes ? leg.distance : undefined, - type: HoldType.Database, - }; - waypoint.additionalData.modifiedHold = {}; + (waypoint.additionalData.defaultHold as HoldData) = { + inboundMagneticCourse: leg.trueDegrees ? A32NX_Util.trueToMagnetic(leg.course, magVar) : leg.course, + turnDirection: leg.turnDirection, + distance: leg.distanceMinutes ? undefined : leg.distance / 1852, + time: leg.distanceMinutes ? leg.distance : undefined, + type: HoldType.Database, + }; + waypoint.additionalData.modifiedHold = {}; - return waypoint; - } + return waypoint; + } - /** + /** * Gets the difference between two headings in zero north normalized radians. * @param a The degrees of heading a. * @param b The degrees of heading b. * @returns The difference between the two headings in zero north normalized radians. */ - private deltaAngleRadians(a: number, b: number): number { - return Math.abs((Avionics.Utils.fmod((a - b) + 180, 360) - 180) * Avionics.Utils.DEG2RAD); - } + private deltaAngleRadians(a: number, b: number): number { + return Math.abs((Avionics.Utils.fmod((a - b) + 180, 360) - 180) * Avionics.Utils.DEG2RAD); + } - /** + /** * Gets an ident from an ICAO. * @param icao The icao to pull the ident from. * @returns The parsed ident. */ - private getIdent(icao: string): string { - return icao.substring(7, 12).trim(); - } + private getIdent(icao: string): string { + return icao.substring(7, 12).trim(); + } - /** + /** * Checks if an ICAO is valid to load. * @param icao The icao to check. * @returns Whether or not the ICAO is valid. */ - private isIcaoValid(icao: string): boolean { - for (const rule of this.legFilteringRules) { - if (!rule(icao)) { - return false; - } - } + private isIcaoValid(icao: string): boolean { + for (const rule of this.legFilteringRules) { + if (!rule(icao)) { + return false; + } + } - return true; - } + return true; + } - /** + /** * Builds a WayPoint from basic data. * @param ident The ident of the waypoint. * @param coordinates The coordinates of the waypoint. * @param magneticVariation The magnetic variation of the waypoint, if any. * @returns The built waypoint. */ - public buildWaypoint(ident: string, coordinates: LatLongAlt, magneticVariation?: number): WayPoint { - const waypoint = new WayPoint(this._instrument); - waypoint.type = 'W'; - - waypoint.infos = new IntersectionInfo(this._instrument); - waypoint.infos.coordinates = coordinates; - waypoint.infos.magneticVariation = magneticVariation; - - waypoint.ident = ident; - waypoint.infos.ident = ident; - - waypoint.additionalData = {}; - - return waypoint; - } - - public async calculateApproachData(runway: OneWayRunway): Promise { - await this.ensureFacilitiesLoaded(); - - // our fallback for threshold crossing altitude is threshold + 50 feet - let threshCrossAlt = runway.thresholdElevation + 15.24; - - // see if we have a runway fix, to give us coded TCH - // it can either be the MAP, or be before the MAP (MAP must be last leg of final approach) - // TCH altitude must be coded in altitude1 according to ARINC - for (let i = this._legs.length - 1; i > 0; i--) { - const leg = this._legs[i]; - // TODO check it's the same runway for robustness? - if (leg.fixIcao.charAt(0) === 'R') { - threshCrossAlt = leg.altitude1; - break; - } - } - - // MSFS does not give the coded descent angle - // we do our best to calculate one... - let fafAlt; - let fafIndex; - let fafToTcaDist = 0; - let lastLegPoint; - - for (let i = 0; i < this._legs.length; i++) { - const leg = this._legs[i]; - let termPoint; - if (leg.fixIcao.charAt(0) === 'R') { - termPoint = runway.thresholdCoordinates; - } else { - const fix = this._facilities.get(leg.fixIcao); - termPoint = new LatLongAlt(fix.lat, fix.lon); - } - - if (leg.fixTypeFlags & FixTypeFlags.FAF) { - if (leg.altDesc === AltitudeDescriptor.Empty) { - // this is illegal by ARINC - break; - } - - fafIndex = i; - // MSFS codes the wrong altDesc... but the right data... - fafAlt = leg.altitude2 > 0 ? leg.altitude2 : leg.altitude1; - } else if (fafIndex !== undefined) { - if (leg.distance > 0) { - fafToTcaDist += leg.distance; - } else { - // assume a straight leg - fafToTcaDist += 1852 * Avionics.Utils.computeGreatCircleDistance(lastLegPoint, termPoint); - } - } - - if (leg.fixIcao.charAt(0) === 'R') { - break; - } - - lastLegPoint = termPoint; - } - - if (fafIndex !== undefined && fafAlt > 0 && fafToTcaDist > 0) { - let glideAngle = Math.atan((fafAlt - threshCrossAlt) / fafToTcaDist) * 180 / Math.PI; - // arinc specifics < 3 degrees is rounded up to 3 degrees when calculating glide angle from alt sources - // we do the same if we have invalid data.. - if (!Number.isFinite(glideAngle) || glideAngle < 3 || glideAngle > 10) { - glideAngle = 3; - } - - for (let i = fafIndex + 1; i < this._legs.length; i++) { - this._legs[i].verticalAngle = glideAngle; - } - } - } + public buildWaypoint(ident: string, coordinates: LatLongAlt, magneticVariation?: number): WayPoint { + const waypoint = new WayPoint(this._instrument); + waypoint.type = 'W'; + + waypoint.infos = new IntersectionInfo(this._instrument); + waypoint.infos.coordinates = coordinates; + waypoint.infos.magneticVariation = magneticVariation; + + waypoint.ident = ident; + waypoint.infos.ident = ident; + + waypoint.additionalData = {}; + + return waypoint; + } + + public async calculateApproachData(runway: OneWayRunway): Promise { + await this.ensureFacilitiesLoaded(); + + // our fallback for threshold crossing altitude is threshold + 50 feet + let threshCrossAlt = runway.thresholdElevation + 15.24; + + // see if we have a runway fix, to give us coded TCH + // it can either be the MAP, or be before the MAP (MAP must be last leg of final approach) + // TCH altitude must be coded in altitude1 according to ARINC + for (let i = this._legs.length - 1; i > 0; i--) { + const leg = this._legs[i]; + // TODO check it's the same runway for robustness? + if (leg.fixIcao.charAt(0) === 'R') { + threshCrossAlt = leg.altitude1; + break; + } + } + + // MSFS does not give the coded descent angle + // we do our best to calculate one... + let fafAlt; + let fafIndex; + let fafToTcaDist = 0; + let lastLegPoint; + + for (let i = 0; i < this._legs.length; i++) { + const leg = this._legs[i]; + let termPoint; + if (leg.fixIcao.charAt(0) === 'R') { + termPoint = runway.thresholdCoordinates; + } else { + const fix = this._facilities.get(leg.fixIcao); + termPoint = new LatLongAlt(fix.lat, fix.lon); + } + + if (leg.fixTypeFlags & FixTypeFlags.FAF) { + if (leg.altDesc === AltitudeDescriptor.Empty) { + // this is illegal by ARINC + break; + } + + fafIndex = i; + // MSFS codes the wrong altDesc... but the right data... + fafAlt = leg.altitude2 > 0 ? leg.altitude2 : leg.altitude1; + } else if (fafIndex !== undefined) { + if (leg.distance > 0) { + fafToTcaDist += leg.distance; + } else { + // assume a straight leg + fafToTcaDist += 1852 * Avionics.Utils.computeGreatCircleDistance(lastLegPoint, termPoint); + } + } + + if (leg.fixIcao.charAt(0) === 'R') { + break; + } + + lastLegPoint = termPoint; + } + + if (fafIndex !== undefined && fafAlt > 0 && fafToTcaDist > 0) { + let glideAngle = Math.atan((fafAlt - threshCrossAlt) / fafToTcaDist) * 180 / Math.PI; + // arinc specifics < 3 degrees is rounded up to 3 degrees when calculating glide angle from alt sources + // we do the same if we have invalid data.. + if (!Number.isFinite(glideAngle) || glideAngle < 3 || glideAngle > 10) { + glideAngle = 3; + } + + for (let i = fafIndex + 1; i < this._legs.length; i++) { + this._legs[i].verticalAngle = glideAngle; + } + } + } } diff --git a/fbw-a380x/src/systems/fmgc/src/flightplanning/ManagedFlightPlan.ts b/fbw-a380x/src/systems/fmgc/src/flightplanning/ManagedFlightPlan.ts index 93ed8e886c21..a73e0fbfa594 100644 --- a/fbw-a380x/src/systems/fmgc/src/flightplanning/ManagedFlightPlan.ts +++ b/fbw-a380x/src/systems/fmgc/src/flightplanning/ManagedFlightPlan.ts @@ -23,7 +23,6 @@ */ import { HoldData, WaypointStats } from '@fmgc/flightplanning/data/flightplan'; -import { WaypointConstraintType } from '@fmgc/flightplanning/FlightPlanManager'; import { AltitudeDescriptor, FixTypeFlags, LegType } from '../types/fstypes/FSEnums'; import { FlightPlanSegment, SegmentType } from './FlightPlanSegment'; import { LegsProcedure } from './LegsProcedure'; @@ -33,6 +32,7 @@ import { ProcedureDetails } from './ProcedureDetails'; import { DirectTo } from './DirectTo'; import { GeoMath } from './GeoMath'; import { WaypointBuilder } from './WaypointBuilder'; +import { WaypointConstraintType } from '@fmgc/flightplanning/FlightPlanManager'; /** * A flight plan managed by the FlightPlanManager. @@ -582,13 +582,14 @@ export class ManagedFlightPlan { atWaypoint.additionalData.defaultHold = defaultHold; } return index; - } - const manualHoldWaypoint = WaypointBuilder.fromWaypointManualHold(atWaypoint, desiredHold.turnDirection, trueCourse, desiredHold.distance, desiredHold.time, this._parentInstrument); - manualHoldWaypoint.additionalData.modifiedHold = modifiedHold; - manualHoldWaypoint.additionalData.defaultHold = defaultHold; + } else { + const manualHoldWaypoint = WaypointBuilder.fromWaypointManualHold(atWaypoint, desiredHold.turnDirection, trueCourse, desiredHold.distance, desiredHold.time, this._parentInstrument); + manualHoldWaypoint.additionalData.modifiedHold = modifiedHold; + manualHoldWaypoint.additionalData.defaultHold = defaultHold; - this.addWaypoint(manualHoldWaypoint, index + 1); - return index + 1; + this.addWaypoint(manualHoldWaypoint, index + 1); + return index + 1; + } } /** @@ -792,7 +793,7 @@ export class ManagedFlightPlan { newFlightPlan._segments[i].waypoints = [...seg.waypoints.map((wp) => { const clone = new (wp as any).constructor(); Object.assign(clone, wp); - clone.additionalData = { ...wp.additionalData }; + clone.additionalData = Object.assign({}, wp.additionalData); return clone; })]; } @@ -828,7 +829,7 @@ export class ManagedFlightPlan { const turningPoint = WaypointBuilder.fromCoordinates('T-P', new LatLongAlt(lat, long), this._parentInstrument, { legType: LegType.CF, course: trueTrack, dynamicPpos: true }, this.getTurningPointIcao()); turningPoint.isTurningPoint = true; - const waypointIndex = this.waypoints.findIndex((w, idx) => idx >= this.activeWaypointIndex && w.icao === waypoint.icao); + let waypointIndex = this.waypoints.findIndex((w, idx) => idx >= this.activeWaypointIndex && w.icao === waypoint.icao); if (waypointIndex === -1) { // in this case the waypoint is not already in the flight plan // we string it to the start of the flight plan, add a discontinuity after, and then the existing flight plan @@ -873,7 +874,7 @@ export class ManagedFlightPlan { private getTurningPointIcao(): string { this.turningPointIndex = (this.turningPointIndex + 1) % 1000; - return `WXX TP${this.turningPointIndex.toFixed(0).padStart(3, '0')}`; + return `WXX TP${this.turningPointIndex.toFixed(0).padStart(3, '0')}` } /** @@ -918,7 +919,7 @@ export class ManagedFlightPlan { const departure: RawDeparture = airportInfo.departures[departureIndex]; if (runwayTransition) { legs.push(...runwayTransition.legs); - legAnnotations.push(...runwayTransition.legs.map((_) => departure.name)); + legAnnotations.push(...runwayTransition.legs.map(_ => departure.name)); origin.endsInDiscontinuity = false; origin.discontinuityCanBeCleared = undefined; } @@ -927,14 +928,14 @@ export class ManagedFlightPlan { if (departureIndex !== -1) { const departure: RawDeparture = airportInfo.departures[departureIndex]; legs.push(...departure.commonLegs); - legAnnotations.push(...departure.commonLegs.map((_) => departure.name)); + legAnnotations.push(...departure.commonLegs.map(_ => departure.name)); } if (transitionIndex !== -1 && departureIndex !== -1) { if (airportInfo.departures[departureIndex].enRouteTransitions.length > 0) { const transition: RawEnRouteTransition = airportInfo.departures[departureIndex].enRouteTransitions[transitionIndex]; legs.push(...transition.legs); - legAnnotations.push(...transition.legs.map((_) => transition.name)); + legAnnotations.push(...transition.legs.map(_ => transition.name)); } } @@ -949,7 +950,7 @@ export class ManagedFlightPlan { if (legs.length > 0 || selectedOriginRunwayIndex !== -1 || (departureIndex !== -1 && runwayIndex !== -1)) { segment = this.addSegment(SegmentType.Departure); - const procedure = new LegsProcedure(legs, origin, this._parentInstrument, airportMagVar, undefined, legAnnotations); + let procedure = new LegsProcedure(legs, origin, this._parentInstrument, airportMagVar, undefined, legAnnotations); const runway: OneWayRunway | null = this.getOriginRunway(); @@ -1022,7 +1023,7 @@ export class ManagedFlightPlan { const transition: RawEnRouteTransition = destinationInfo.arrivals[arrivalIndex].enRouteTransitions[arrivalTransitionIndex]; if (transition !== undefined) { legs.push(...transition.legs); - legAnnotations.push(...transition.legs.map((_) => transition.name)); + legAnnotations.push(...transition.legs.map(_ => transition.name)); // console.log('MFP: buildArrival - pushing transition legs ->', legs); } } @@ -1030,7 +1031,7 @@ export class ManagedFlightPlan { if (arrivalIndex !== -1) { const arrival: RawArrival = destinationInfo.arrivals[arrivalIndex]; legs.push(...arrival.commonLegs); - legAnnotations.push(...arrival.commonLegs.map((_) => arrival.name)); + legAnnotations.push(...arrival.commonLegs.map(_ => arrival.name)); // console.log('MFP: buildArrival - pushing STAR legs ->', legs); } @@ -1039,7 +1040,7 @@ export class ManagedFlightPlan { const runwayTransition: RawRunwayTransition = destinationInfo.arrivals[arrivalIndex].runwayTransitions[arrivalRunwayIndex]; if (runwayTransition) { legs.push(...runwayTransition.legs); - legAnnotations.push(...runwayTransition.legs.map((_) => arrival.name)); + legAnnotations.push(...runwayTransition.legs.map(_ => arrival.name)); } // console.log('MFP: buildArrival - pushing VIA legs ->', legs); } @@ -1095,14 +1096,14 @@ export class ManagedFlightPlan { if (approachIndex !== -1 && approachTransitionIndex !== -1) { const transition: RawApproachTransition = destinationInfo.approaches[approachIndex].transitions[approachTransitionIndex]; legs.push(...transition.legs); - legAnnotations.push(...transition.legs.map((_) => transition.name)); + legAnnotations.push(...transition.legs.map(_ => transition.name)); // console.log('MFP: buildApproach - pushing approachTransition legs ->', legs); } if (approachIndex !== -1) { this.procedureDetails.approachType = approach.approachType; legs.push(...approach.finalLegs); - legAnnotations.push(...approach.finalLegs.map((_) => approachName)); + legAnnotations.push(...approach.finalLegs.map(_ => approachName)); missedLegs.push(...approach.missedLegs); } @@ -1217,26 +1218,26 @@ export class ManagedFlightPlan { private static isXfLeg(leg: WayPoint): boolean { switch (leg?.additionalData?.legType) { - case LegType.CF: - case LegType.DF: - case LegType.IF: - case LegType.RF: - case LegType.TF: - return true; - default: - return false; + case LegType.CF: + case LegType.DF: + case LegType.IF: + case LegType.RF: + case LegType.TF: + return true; + default: + return false; } } private static isFxLeg(leg: WayPoint): boolean { switch (leg?.additionalData?.legType) { - case LegType.FA: - case LegType.FC: - case LegType.FD: - case LegType.FM: - return true; - default: - return false; + case LegType.FA: + case LegType.FC: + case LegType.FD: + case LegType.FM: + return true; + default: + return false; } } @@ -1246,21 +1247,21 @@ export class ManagedFlightPlan { private static climbConstraint(leg: WayPoint): number { switch (leg.legAltitudeDescription) { - case AltitudeDescriptor.At: - case AltitudeDescriptor.AtOrBelow: - return leg.legAltitude1; - case AltitudeDescriptor.Between: - return leg.legAltitude2; + case AltitudeDescriptor.At: + case AltitudeDescriptor.AtOrBelow: + return leg.legAltitude1; + case AltitudeDescriptor.Between: + return leg.legAltitude2; } return Infinity; } private static descentConstraint(leg: WayPoint): number { switch (leg.legAltitudeDescription) { - case AltitudeDescriptor.At: - case AltitudeDescriptor.AtOrAbove: - case AltitudeDescriptor.Between: - return leg.legAltitude1; + case AltitudeDescriptor.At: + case AltitudeDescriptor.AtOrAbove: + case AltitudeDescriptor.Between: + return leg.legAltitude1; } return -Infinity; } @@ -1310,7 +1311,7 @@ export class ManagedFlightPlan { legAltitude1, legAltitude2, speedConstraint: Number.isFinite(speed) ? speed : 0, - }; + } } /** @@ -1520,7 +1521,8 @@ export class ManagedFlightPlan { default: } } else if (ManagedFlightPlan.isXfLeg(a) && ManagedFlightPlan.isXfLeg(b) - || ManagedFlightPlan.isFxLeg(a) && ManagedFlightPlan.isFxLeg(b)) { + || ManagedFlightPlan.isFxLeg(a) && ManagedFlightPlan.isFxLeg(b)) + { return a.icao === b.icao; } diff --git a/fbw-a380x/src/systems/fmgc/src/flightplanning/new/FlightPlanManager.ts b/fbw-a380x/src/systems/fmgc/src/flightplanning/new/FlightPlanManager.ts index 420489af0085..ee55dde3176c 100644 --- a/fbw-a380x/src/systems/fmgc/src/flightplanning/new/FlightPlanManager.ts +++ b/fbw-a380x/src/systems/fmgc/src/flightplanning/new/FlightPlanManager.ts @@ -13,7 +13,7 @@ export enum FlightPlanIndex { } export class FlightPlanManager { - private plans: FlightPlan[] = []; + private plans: FlightPlan[] = [] has(index: number) { return this.plans[index] !== undefined; diff --git a/fbw-a380x/src/systems/fmgc/src/flightplanning/new/FlightPlanService.spec.ts b/fbw-a380x/src/systems/fmgc/src/flightplanning/new/FlightPlanService.spec.ts index 5a24e005fbc1..219df350fe43 100644 --- a/fbw-a380x/src/systems/fmgc/src/flightplanning/new/FlightPlanService.spec.ts +++ b/fbw-a380x/src/systems/fmgc/src/flightplanning/new/FlightPlanService.spec.ts @@ -68,11 +68,11 @@ describe('the flight plan service', () => { const leg4 = assertNotDiscontinuity(FlightPlanService.active.allLegs[4]); - expect(leg4.ident).toBe('ERBUS'); + expect(leg4.ident).toEqual('ERBUS'); const leg5 = assertNotDiscontinuity(FlightPlanService.active.allLegs[5]); - expect(leg5.ident).toBe('SELAP'); + expect(leg5.ident).toEqual('SELAP'); }); it('without duplicate', async () => { @@ -84,13 +84,13 @@ describe('the flight plan service', () => { const leg4 = assertNotDiscontinuity(FlightPlanService.active.allLegs[4]); - expect(leg4.ident).toBe('ERBUS'); + expect(leg4.ident).toEqual('ERBUS'); assertDiscontinuity(FlightPlanService.active.allLegs[5]); const leg6 = assertNotDiscontinuity(FlightPlanService.active.allLegs[6]); - expect(leg6.ident).toBe('DULPA'); + expect(leg6.ident).toEqual('DULPA'); }); }); diff --git a/fbw-a380x/src/systems/fmgc/src/flightplanning/new/FlightPlanService.ts b/fbw-a380x/src/systems/fmgc/src/flightplanning/new/FlightPlanService.ts index 3da3d671b714..8362db4799f6 100644 --- a/fbw-a380x/src/systems/fmgc/src/flightplanning/new/FlightPlanService.ts +++ b/fbw-a380x/src/systems/fmgc/src/flightplanning/new/FlightPlanService.ts @@ -16,9 +16,9 @@ export class FlightPlanService { private static flightPlanManager = new FlightPlanManager(); - private static config: FpmConfig = A380FpmConfig; + private static config: FpmConfig = A380FpmConfig - static navigationDatabase: NavigationDatabase; + static navigationDatabase: NavigationDatabase static version = 0; @@ -256,7 +256,7 @@ export class FlightPlanService { static startAirwayEntry(at: number, planIndex = FlightPlanIndex.Active) { const finalIndex = this.prepareDestructiveModification(planIndex); - const plan = this.flightPlanManager.get(finalIndex); + const plan = this.flightPlanManager.get(finalIndex) plan.startAirwayEntry(at); } diff --git a/fbw-a380x/src/systems/fmgc/src/flightplanning/new/NavigationDatabaseService.ts b/fbw-a380x/src/systems/fmgc/src/flightplanning/new/NavigationDatabaseService.ts index 2c2764716440..20c272e3cde7 100644 --- a/fbw-a380x/src/systems/fmgc/src/flightplanning/new/NavigationDatabaseService.ts +++ b/fbw-a380x/src/systems/fmgc/src/flightplanning/new/NavigationDatabaseService.ts @@ -11,7 +11,7 @@ export class NavigationDatabaseService { static _activeDatabase: NavigationDatabase; static get activeDatabase(): NavigationDatabase { - return this._activeDatabase; + return this._activeDatabase } static set activeDatabase(db: NavigationDatabase) { diff --git a/fbw-a380x/src/systems/fmgc/src/flightplanning/new/legs/FlightPlanLeg.ts b/fbw-a380x/src/systems/fmgc/src/flightplanning/new/legs/FlightPlanLeg.ts index 0e5e0f0dfed0..492ee4cdccab 100644 --- a/fbw-a380x/src/systems/fmgc/src/flightplanning/new/legs/FlightPlanLeg.ts +++ b/fbw-a380x/src/systems/fmgc/src/flightplanning/new/legs/FlightPlanLeg.ts @@ -38,7 +38,7 @@ export class FlightPlanLeg { this.type = definition.type; } - isDiscontinuity: false = false; + isDiscontinuity: false = false get waypointDescriptor() { return this.definition.waypointDescriptor; diff --git a/fbw-a380x/src/systems/fmgc/src/flightplanning/new/plans/BaseFlightPlan.ts b/fbw-a380x/src/systems/fmgc/src/flightplanning/new/plans/BaseFlightPlan.ts index 23d21d95849e..fabde771d600 100644 --- a/fbw-a380x/src/systems/fmgc/src/flightplanning/new/plans/BaseFlightPlan.ts +++ b/fbw-a380x/src/systems/fmgc/src/flightplanning/new/plans/BaseFlightPlan.ts @@ -99,7 +99,7 @@ export abstract class BaseFlightPlan { departureSegment = new DepartureSegment(this); - departureEnrouteTransitionSegment = new DepartureEnrouteTransitionSegment(this); + departureEnrouteTransitionSegment = new DepartureEnrouteTransitionSegment(this) enrouteSegment = new EnrouteSegment(this); diff --git a/fbw-a380x/src/systems/fmgc/src/flightplanning/new/plans/FlightPlan.spec.ts b/fbw-a380x/src/systems/fmgc/src/flightplanning/new/plans/FlightPlan.spec.ts index 673746e61d01..389b47c97f93 100644 --- a/fbw-a380x/src/systems/fmgc/src/flightplanning/new/plans/FlightPlan.spec.ts +++ b/fbw-a380x/src/systems/fmgc/src/flightplanning/new/plans/FlightPlan.spec.ts @@ -42,7 +42,7 @@ describe('a base flight plan', () => { const fpLeg = assertNotDiscontinuity(fp.allLegs[4]); - expect(fpLeg.ident).toBe('NOSUS'); + expect(fpLeg.ident).toEqual('NOSUS'); expect(fp.allLegs[5].isDiscontinuity).toBeTruthy(); expect(fp.allLegs).toHaveLength(23); @@ -100,7 +100,7 @@ describe('a base flight plan', () => { expect(flightPlan.departureRunwayTransitionSegment.allLegs).toHaveLength(4); const lastLegOfTruncatedDeparture = assertNotDiscontinuity(flightPlan.departureRunwayTransitionSegment.allLegs[3]); - expect(lastLegOfTruncatedDeparture.ident).toBe('DUVKO'); + expect(lastLegOfTruncatedDeparture.ident).toEqual('DUVKO'); expect(flightPlan.departureSegment.allLegs).toHaveLength(0); @@ -109,7 +109,7 @@ describe('a base flight plan', () => { expect(flightPlan.enrouteSegment.allLegs).toHaveLength(2); const firstLegOfEnroute = assertNotDiscontinuity(flightPlan.enrouteSegment.allLegs[0]); - expect(firstLegOfEnroute.ident).toBe('AVSEP'); + expect(firstLegOfEnroute.ident).toEqual('AVSEP'); }); it('should insert a discontinuity when deleting a leg', async () => { @@ -147,15 +147,15 @@ describe('a base flight plan', () => { const l3 = assertNotDiscontinuity(flightPlan.allLegs[2]); const l4 = assertNotDiscontinuity(flightPlan.allLegs[3]); - expect(l1.ident).toBe('NOSUS'); - expect(l2.ident).toBe('NAPEE'); - expect(l3.ident).toBe('PBERG'); - expect(l4.ident).toBe('HOVOB'); + expect(l1.ident).toEqual('NOSUS'); + expect(l2.ident).toEqual('NAPEE'); + expect(l3.ident).toEqual('PBERG'); + expect(l4.ident).toEqual('HOVOB'); flightPlan.insertElementAfter(0, FlightPlanLeg.fromEnrouteWaypoint(segment, w4)); expect(flightPlan.allLegs).toHaveLength(2); - expect(assertNotDiscontinuity(flightPlan.allLegs[1]).ident).toBe('HOVOB'); + expect(assertNotDiscontinuity(flightPlan.allLegs[1]).ident).toEqual('HOVOB'); }); it('should collapse waypoints across segments', async () => { @@ -181,8 +181,8 @@ describe('a base flight plan', () => { flightPlan.insertElementAfter(4, FlightPlanLeg.fromEnrouteWaypoint(enroute, w1)); expect(flightPlan.allLegs).toHaveLength(6); - expect(assertNotDiscontinuity(flightPlan.allLegs[4]).ident).toBe('QN852'); - expect(assertNotDiscontinuity(flightPlan.allLegs[5]).ident).toBe('PEDPO'); + expect(assertNotDiscontinuity(flightPlan.allLegs[4]).ident).toEqual('QN852'); + expect(assertNotDiscontinuity(flightPlan.allLegs[5]).ident).toEqual('PEDPO'); }); }); diff --git a/fbw-a380x/src/systems/fmgc/src/flightplanning/new/plans/FlightPlan.ts b/fbw-a380x/src/systems/fmgc/src/flightplanning/new/plans/FlightPlan.ts index d221060b692a..02d1252f345f 100644 --- a/fbw-a380x/src/systems/fmgc/src/flightplanning/new/plans/FlightPlan.ts +++ b/fbw-a380x/src/systems/fmgc/src/flightplanning/new/plans/FlightPlan.ts @@ -9,7 +9,7 @@ import { FlightPlanSegment } from '@fmgc/flightplanning/new/segments/FlightPlanS import { AlternateFlightPlan } from '@fmgc/flightplanning/new/plans/AlternateFlightPlan'; import { BaseFlightPlan } from '@fmgc/flightplanning/new/plans/BaseFlightPlan'; import { FlightPlanElement } from '@fmgc/flightplanning/new/legs/FlightPlanLeg'; -import { PendingAirways } from '@fmgc/flightplanning/new/plans/PendingAirways'; +import { PendingAirways } from "@fmgc/flightplanning/new/plans/PendingAirways"; // import { FlightPlanPerformanceData } from '@fmgc/flightplanning/new/plans/performance/FlightPlanPerformanceData'; export class FlightPlan extends BaseFlightPlan { diff --git a/fbw-a380x/src/systems/fmgc/src/flightplanning/new/plans/PendingAirways.spec.ts b/fbw-a380x/src/systems/fmgc/src/flightplanning/new/plans/PendingAirways.spec.ts index e90940398f12..f60c48186d2d 100644 --- a/fbw-a380x/src/systems/fmgc/src/flightplanning/new/plans/PendingAirways.spec.ts +++ b/fbw-a380x/src/systems/fmgc/src/flightplanning/new/plans/PendingAirways.spec.ts @@ -1,10 +1,10 @@ -import fetch from 'node-fetch'; -import { FlightPlanService } from '@fmgc/flightplanning/new/FlightPlanService'; -import { setupNavigraphDatabase } from '@fmgc/flightplanning/new/test/Database'; -import { NavigationDatabaseService } from '@fmgc/flightplanning/new/NavigationDatabaseService'; -import { loadSingleFix, loadSingleWaypoint } from '@fmgc/flightplanning/new/segments/enroute/WaypointLoading'; -import { FlightPlanPerformanceData } from '@fmgc/flightplanning/new/plans/performance/FlightPlanPerformanceData'; -import { dumpFlightPlan } from '@fmgc/flightplanning/new/test/FlightPlan'; +import fetch from "node-fetch"; +import { FlightPlanService } from "@fmgc/flightplanning/new/FlightPlanService"; +import { setupNavigraphDatabase } from "@fmgc/flightplanning/new/test/Database"; +import { NavigationDatabaseService } from "@fmgc/flightplanning/new/NavigationDatabaseService"; +import { loadSingleFix, loadSingleWaypoint } from "@fmgc/flightplanning/new/segments/enroute/WaypointLoading"; +import { FlightPlanPerformanceData } from "@fmgc/flightplanning/new/plans/performance/FlightPlanPerformanceData"; +import { dumpFlightPlan } from "@fmgc/flightplanning/new/test/FlightPlan"; if (!globalThis.fetch) { globalThis.fetch = fetch; @@ -117,5 +117,5 @@ describe('pending airways entry', () => { FlightPlanService.active.pendingAirways.thenTo(to13); debugger; - }); + }) }); diff --git a/fbw-a380x/src/systems/fmgc/src/flightplanning/new/segments/ApproachSegment.ts b/fbw-a380x/src/systems/fmgc/src/flightplanning/new/segments/ApproachSegment.ts index 1537295b0351..6d9f72651276 100644 --- a/fbw-a380x/src/systems/fmgc/src/flightplanning/new/segments/ApproachSegment.ts +++ b/fbw-a380x/src/systems/fmgc/src/flightplanning/new/segments/ApproachSegment.ts @@ -11,11 +11,11 @@ import { SegmentClass } from '@fmgc/flightplanning/new/segments/SegmentClass'; import { NavigationDatabaseService } from '../NavigationDatabaseService'; export class ApproachSegment extends FlightPlanSegment { - class = SegmentClass.Arrival; + class = SegmentClass.Arrival - allLegs: FlightPlanElement[] = []; + allLegs: FlightPlanElement[] = [] - private approach: Approach | undefined; + private approach: Approach | undefined get approachProcedure() { return this.approach; diff --git a/fbw-a380x/src/systems/fmgc/src/flightplanning/new/segments/ApproachViaSegment.ts b/fbw-a380x/src/systems/fmgc/src/flightplanning/new/segments/ApproachViaSegment.ts index b016571c27f8..a34513b18739 100644 --- a/fbw-a380x/src/systems/fmgc/src/flightplanning/new/segments/ApproachViaSegment.ts +++ b/fbw-a380x/src/systems/fmgc/src/flightplanning/new/segments/ApproachViaSegment.ts @@ -10,11 +10,11 @@ import { BaseFlightPlan, FlightPlanQueuedOperation } from '@fmgc/flightplanning/ import { SegmentClass } from '@fmgc/flightplanning/new/segments/SegmentClass'; export class ApproachViaSegment extends FlightPlanSegment { - class = SegmentClass.Arrival; + class = SegmentClass.Arrival - allLegs: FlightPlanElement[] = []; + allLegs: FlightPlanElement[] = [] - private approachVia: ProcedureTransition | undefined = undefined; + private approachVia: ProcedureTransition | undefined = undefined get approachViaProcedure() { return this.approachVia; diff --git a/fbw-a380x/src/systems/fmgc/src/flightplanning/new/segments/ArrivalEnrouteTransitionSegment.ts b/fbw-a380x/src/systems/fmgc/src/flightplanning/new/segments/ArrivalEnrouteTransitionSegment.ts index f0382af02997..7daa718367d2 100644 --- a/fbw-a380x/src/systems/fmgc/src/flightplanning/new/segments/ArrivalEnrouteTransitionSegment.ts +++ b/fbw-a380x/src/systems/fmgc/src/flightplanning/new/segments/ArrivalEnrouteTransitionSegment.ts @@ -10,11 +10,11 @@ import { BaseFlightPlan, FlightPlanQueuedOperation } from '@fmgc/flightplanning/ import { SegmentClass } from '@fmgc/flightplanning/new/segments/SegmentClass'; export class ArrivalEnrouteTransitionSegment extends FlightPlanSegment { - class = SegmentClass.Arrival; + class = SegmentClass.Arrival - allLegs: FlightPlanElement[] = []; + allLegs: FlightPlanElement[] = [] - private arrivalEnrouteTransition: ProcedureTransition | undefined = undefined; + private arrivalEnrouteTransition: ProcedureTransition | undefined = undefined get arrivalEnrouteTransitionProcedure() { return this.arrivalEnrouteTransition; diff --git a/fbw-a380x/src/systems/fmgc/src/flightplanning/new/segments/ArrivalRunwayTransitionSegment.ts b/fbw-a380x/src/systems/fmgc/src/flightplanning/new/segments/ArrivalRunwayTransitionSegment.ts index a2a9c14210a9..1da332c3978d 100644 --- a/fbw-a380x/src/systems/fmgc/src/flightplanning/new/segments/ArrivalRunwayTransitionSegment.ts +++ b/fbw-a380x/src/systems/fmgc/src/flightplanning/new/segments/ArrivalRunwayTransitionSegment.ts @@ -10,11 +10,11 @@ import { BaseFlightPlan, FlightPlanQueuedOperation } from '@fmgc/flightplanning/ import { SegmentClass } from '@fmgc/flightplanning/new/segments/SegmentClass'; export class ArrivalRunwayTransitionSegment extends FlightPlanSegment { - class = SegmentClass.Arrival; + class = SegmentClass.Arrival - allLegs: FlightPlanElement[] = []; + allLegs: FlightPlanElement[] = [] - private arrivalRunwayTransition: ProcedureTransition | undefined = undefined; + private arrivalRunwayTransition: ProcedureTransition | undefined = undefined get arrivalRunwayTransitionProcedure() { return this.arrivalRunwayTransition; diff --git a/fbw-a380x/src/systems/fmgc/src/flightplanning/new/segments/ArrivalSegment.ts b/fbw-a380x/src/systems/fmgc/src/flightplanning/new/segments/ArrivalSegment.ts index 7f97f44fc07e..d172825d0ec6 100644 --- a/fbw-a380x/src/systems/fmgc/src/flightplanning/new/segments/ArrivalSegment.ts +++ b/fbw-a380x/src/systems/fmgc/src/flightplanning/new/segments/ArrivalSegment.ts @@ -11,11 +11,11 @@ import { SegmentClass } from '@fmgc/flightplanning/new/segments/SegmentClass'; import { NavigationDatabaseService } from '../NavigationDatabaseService'; export class ArrivalSegment extends FlightPlanSegment { - class = SegmentClass.Arrival; + class = SegmentClass.Arrival - allLegs: FlightPlanElement[] = []; + allLegs: FlightPlanElement[] = [] - private arrival: Arrival | undefined; + private arrival: Arrival | undefined get arrivalProcedure() { return this.arrival; diff --git a/fbw-a380x/src/systems/fmgc/src/flightplanning/new/segments/DepartureEnrouteTransitionSegment.ts b/fbw-a380x/src/systems/fmgc/src/flightplanning/new/segments/DepartureEnrouteTransitionSegment.ts index e004f081003e..f8bdf3aa4db3 100644 --- a/fbw-a380x/src/systems/fmgc/src/flightplanning/new/segments/DepartureEnrouteTransitionSegment.ts +++ b/fbw-a380x/src/systems/fmgc/src/flightplanning/new/segments/DepartureEnrouteTransitionSegment.ts @@ -10,11 +10,11 @@ import { SegmentClass } from '@fmgc/flightplanning/new/segments/SegmentClass'; import { BaseFlightPlan, FlightPlanQueuedOperation } from '@fmgc/flightplanning/new/plans/BaseFlightPlan'; export class DepartureEnrouteTransitionSegment extends FlightPlanSegment { - class = SegmentClass.Departure; + class = SegmentClass.Departure - allLegs: FlightPlanElement[] = []; + allLegs: FlightPlanElement[] = [] - private departureEnrouteTransition: ProcedureTransition | undefined = undefined; + private departureEnrouteTransition: ProcedureTransition | undefined = undefined get departureEnrouteTransitionProcedure() { return this.departureEnrouteTransition; diff --git a/fbw-a380x/src/systems/fmgc/src/flightplanning/new/segments/DepartureRunwayTransitionSegment.ts b/fbw-a380x/src/systems/fmgc/src/flightplanning/new/segments/DepartureRunwayTransitionSegment.ts index 06ddf9ff51ec..d5989892f78d 100644 --- a/fbw-a380x/src/systems/fmgc/src/flightplanning/new/segments/DepartureRunwayTransitionSegment.ts +++ b/fbw-a380x/src/systems/fmgc/src/flightplanning/new/segments/DepartureRunwayTransitionSegment.ts @@ -10,11 +10,11 @@ import { BaseFlightPlan, FlightPlanQueuedOperation } from '@fmgc/flightplanning/ import { SegmentClass } from '@fmgc/flightplanning/new/segments/SegmentClass'; export class DepartureRunwayTransitionSegment extends FlightPlanSegment { - class = SegmentClass.Departure; + class = SegmentClass.Departure - allLegs: FlightPlanElement[] = []; + allLegs: FlightPlanElement[] = [] - private departureRunwayTransition: ProcedureTransition | undefined = undefined; + private departureRunwayTransition: ProcedureTransition | undefined = undefined get departureRunwayTransitionProcedure() { return this.departureRunwayTransition; diff --git a/fbw-a380x/src/systems/fmgc/src/flightplanning/new/segments/DepartureSegment.ts b/fbw-a380x/src/systems/fmgc/src/flightplanning/new/segments/DepartureSegment.ts index 507d62a8fc51..d4367ddee8ae 100644 --- a/fbw-a380x/src/systems/fmgc/src/flightplanning/new/segments/DepartureSegment.ts +++ b/fbw-a380x/src/systems/fmgc/src/flightplanning/new/segments/DepartureSegment.ts @@ -11,11 +11,11 @@ import { BaseFlightPlan, FlightPlanQueuedOperation } from '@fmgc/flightplanning/ import { NavigationDatabaseService } from '../NavigationDatabaseService'; export class DepartureSegment extends FlightPlanSegment { - class = SegmentClass.Departure; + class = SegmentClass.Departure - originDeparture: Departure; + originDeparture: Departure - allLegs: FlightPlanLeg[] = []; + allLegs: FlightPlanLeg[] = [] async setDepartureProcedure(procedureIdent: string | undefined) { if (procedureIdent === undefined) { diff --git a/fbw-a380x/src/systems/fmgc/src/flightplanning/new/segments/DestinationSegment.ts b/fbw-a380x/src/systems/fmgc/src/flightplanning/new/segments/DestinationSegment.ts index d5faa41ca161..eb2b2d555ad7 100644 --- a/fbw-a380x/src/systems/fmgc/src/flightplanning/new/segments/DestinationSegment.ts +++ b/fbw-a380x/src/systems/fmgc/src/flightplanning/new/segments/DestinationSegment.ts @@ -12,9 +12,9 @@ import { FlightPlanSegment } from './FlightPlanSegment'; import { NavigationDatabaseService } from '../NavigationDatabaseService'; export class DestinationSegment extends FlightPlanSegment { - class = SegmentClass.Arrival; + class = SegmentClass.Arrival - allLegs: FlightPlanElement[] = []; + allLegs: FlightPlanElement[] = [] private airport: Airport; diff --git a/fbw-a380x/src/systems/fmgc/src/flightplanning/new/segments/EnrouteSegment.spec.ts b/fbw-a380x/src/systems/fmgc/src/flightplanning/new/segments/EnrouteSegment.spec.ts index b1da71647a14..283a0f875153 100644 --- a/fbw-a380x/src/systems/fmgc/src/flightplanning/new/segments/EnrouteSegment.spec.ts +++ b/fbw-a380x/src/systems/fmgc/src/flightplanning/new/segments/EnrouteSegment.spec.ts @@ -39,9 +39,9 @@ describe('an enroute segment', () => { const e2 = segment.allLegs[2]; expect(e2.isDiscontinuity).toBeFalsy(); - expect((e0 as FlightPlanLeg).ident).toBe('NOSUS'); - expect((e1 as FlightPlanLeg).ident).toBe('NAPEE'); - expect((e2 as FlightPlanLeg).ident).toBe('PBERG'); + expect((e0 as FlightPlanLeg).ident).toEqual('NOSUS'); + expect((e1 as FlightPlanLeg).ident).toEqual('NAPEE'); + expect((e2 as FlightPlanLeg).ident).toEqual('PBERG'); }); it('should insert airway', async () => { @@ -59,7 +59,7 @@ describe('an enroute segment', () => { const endLeg = airwayLegs[airwayLegs.length - 1]; - expect(endLeg.ident).toBe('PONCT'); + expect(endLeg.ident).toEqual('PONCT'); segment.insertLegs(...airwayLegs); diff --git a/fbw-a380x/src/systems/fmgc/src/flightplanning/new/segments/EnrouteSegment.ts b/fbw-a380x/src/systems/fmgc/src/flightplanning/new/segments/EnrouteSegment.ts index ad9f83ce3f23..e7ff965ccbd8 100644 --- a/fbw-a380x/src/systems/fmgc/src/flightplanning/new/segments/EnrouteSegment.ts +++ b/fbw-a380x/src/systems/fmgc/src/flightplanning/new/segments/EnrouteSegment.ts @@ -10,9 +10,9 @@ import { SegmentClass } from '@fmgc/flightplanning/new/segments/SegmentClass'; import { FlightPlanSegment } from './FlightPlanSegment'; export class EnrouteSegment extends FlightPlanSegment { - class = SegmentClass.Enroute; + class = SegmentClass.Enroute - allLegs: FlightPlanElement[] = []; + allLegs: FlightPlanElement[] = [] insertLeg(leg: FlightPlanLeg) { this.allLegs.push(leg); diff --git a/fbw-a380x/src/systems/fmgc/src/flightplanning/new/segments/FlightPlanSegment.ts b/fbw-a380x/src/systems/fmgc/src/flightplanning/new/segments/FlightPlanSegment.ts index d3a9f62abee0..e652d3cb3bff 100644 --- a/fbw-a380x/src/systems/fmgc/src/flightplanning/new/segments/FlightPlanSegment.ts +++ b/fbw-a380x/src/systems/fmgc/src/flightplanning/new/segments/FlightPlanSegment.ts @@ -23,7 +23,7 @@ export abstract class FlightPlanSegment { /** * Whether the segment has already been strung */ - strung = false; + strung = false constructor( protected readonly flightPlan: BaseFlightPlan, diff --git a/fbw-a380x/src/systems/fmgc/src/flightplanning/new/segments/MissedApproachSegment.ts b/fbw-a380x/src/systems/fmgc/src/flightplanning/new/segments/MissedApproachSegment.ts index 63fda7de0fd5..2fe795960b45 100644 --- a/fbw-a380x/src/systems/fmgc/src/flightplanning/new/segments/MissedApproachSegment.ts +++ b/fbw-a380x/src/systems/fmgc/src/flightplanning/new/segments/MissedApproachSegment.ts @@ -9,9 +9,9 @@ import { SegmentClass } from '@fmgc/flightplanning/new/segments/SegmentClass'; import { BaseFlightPlan } from '@fmgc/flightplanning/new/plans/BaseFlightPlan'; export class MissedApproachSegment extends FlightPlanSegment { - class = SegmentClass.Arrival; + class = SegmentClass.Arrival - allLegs: FlightPlanElement[] = []; + allLegs: FlightPlanElement[] = [] setMissedApproachLegs(legs: FlightPlanElement[]) { this.allLegs.length = 0; diff --git a/fbw-a380x/src/systems/fmgc/src/flightplanning/new/segments/OriginSegment.ts b/fbw-a380x/src/systems/fmgc/src/flightplanning/new/segments/OriginSegment.ts index 7c7fea5c1a73..72923e8708b4 100644 --- a/fbw-a380x/src/systems/fmgc/src/flightplanning/new/segments/OriginSegment.ts +++ b/fbw-a380x/src/systems/fmgc/src/flightplanning/new/segments/OriginSegment.ts @@ -12,9 +12,9 @@ import { FlightPlanElement, FlightPlanLeg } from '../legs/FlightPlanLeg'; import { NavigationDatabaseService } from '../NavigationDatabaseService'; export class OriginSegment extends FlightPlanSegment { - class = SegmentClass.Departure; + class = SegmentClass.Departure - allLegs: FlightPlanElement[] = []; + allLegs: FlightPlanElement[] = [] private airport: Airport; diff --git a/fbw-a380x/src/systems/fmgc/src/flightplanning/new/segments/enroute/WaypointLoading.spec.ts b/fbw-a380x/src/systems/fmgc/src/flightplanning/new/segments/enroute/WaypointLoading.spec.ts index eb14d95ca1be..084db1d26977 100644 --- a/fbw-a380x/src/systems/fmgc/src/flightplanning/new/segments/enroute/WaypointLoading.spec.ts +++ b/fbw-a380x/src/systems/fmgc/src/flightplanning/new/segments/enroute/WaypointLoading.spec.ts @@ -22,8 +22,8 @@ describe('waypoint loading', () => { const element = await loadSingleWaypoint('NOSUS', 'WCYCYULNOSUS'); expect(element).not.toBeNull(); - expect(element.ident).toBe('NOSUS'); - expect(element.icaoCode).toBe('CY'); + expect(element.ident).toEqual('NOSUS'); + expect(element.icaoCode).toEqual('CY'); }); it('can load ALB (ALBANY) VOR', async () => { @@ -34,6 +34,6 @@ describe('waypoint loading', () => { const albanyVor = elements.find((it) => it.icaoCode === 'K6'); expect(albanyVor).not.toBeNull(); - expect((albanyVor as VhfNavaid).name).toBe('ALBANY'); + expect((albanyVor as VhfNavaid).name).toEqual('ALBANY'); }); }); diff --git a/fbw-a380x/src/systems/fmgc/src/guidance/Guidable.ts b/fbw-a380x/src/systems/fmgc/src/guidance/Guidable.ts index 34d1d105f31c..4e0ef3d8f2a5 100644 --- a/fbw-a380x/src/systems/fmgc/src/guidance/Guidable.ts +++ b/fbw-a380x/src/systems/fmgc/src/guidance/Guidable.ts @@ -17,7 +17,7 @@ export abstract class Guidable { * For a transition, this indicates that the transition between the legs is selected but has no geometry. * For a leg, this indicates that geometry conditions cause the leg to be skipped. */ - isNull = false; + isNull = false /** * The first valid guidable that precedes this one. This takes into account the `isNull` property, meaning other diff --git a/fbw-a380x/src/systems/fmgc/src/guidance/GuidanceController.ts b/fbw-a380x/src/systems/fmgc/src/guidance/GuidanceController.ts index 1099b4c73dea..fdcdbd965efd 100644 --- a/fbw-a380x/src/systems/fmgc/src/guidance/GuidanceController.ts +++ b/fbw-a380x/src/systems/fmgc/src/guidance/GuidanceController.ts @@ -60,13 +60,13 @@ export class GuidanceController { automaticSequencing: boolean = true; - leftEfisState: EfisState; + leftEfisState: EfisState - rightEfisState: EfisState; + rightEfisState: EfisState - efisStateForSide: { L: EfisState, R: EfisState }; + efisStateForSide: { L: EfisState, R: EfisState } - private approachMessage: string = ''; + private approachMessage: string = '' taskQueue = new TaskQueue(); diff --git a/fbw-a380x/src/systems/fmgc/src/guidance/GuidanceManager.ts b/fbw-a380x/src/systems/fmgc/src/guidance/GuidanceManager.ts index 165cfd89ef42..f9946fa9b164 100644 --- a/fbw-a380x/src/systems/fmgc/src/guidance/GuidanceManager.ts +++ b/fbw-a380x/src/systems/fmgc/src/guidance/GuidanceManager.ts @@ -10,6 +10,7 @@ import { FlightPlanManager } from '../flightplanning/FlightPlanManager'; * calculating the autopilot inputs to follow the predicted flight path. */ export class GuidanceManager { + constructor() { } diff --git a/fbw-a380x/src/systems/fmgc/src/guidance/lnav/legs/AF.ts b/fbw-a380x/src/systems/fmgc/src/guidance/lnav/legs/AF.ts index 42127e621a81..08fefe2aff6a 100644 --- a/fbw-a380x/src/systems/fmgc/src/guidance/lnav/legs/AF.ts +++ b/fbw-a380x/src/systems/fmgc/src/guidance/lnav/legs/AF.ts @@ -45,25 +45,25 @@ export class AFLeg extends XFLeg { this.outboundCourse = this.terminationRadial + 90 * this.turnDirectionSign; } - readonly centre: Coordinates | undefined; + readonly centre: Coordinates | undefined private readonly terminationRadial: DegreesTrue | undefined; - private readonly bearing: DegreesTrue | undefined; + private readonly bearing: DegreesTrue | undefined - readonly arcStartPoint: Coordinates | undefined; + readonly arcStartPoint: Coordinates | undefined - readonly arcEndPoint: Coordinates | undefined; + readonly arcEndPoint: Coordinates | undefined - readonly radius: NauticalMiles | undefined; + readonly radius: NauticalMiles | undefined - private sweepAngle: Degrees | undefined; + private sweepAngle: Degrees | undefined - private clockwise: boolean | undefined; + private clockwise: boolean | undefined - inboundCourse: DegreesTrue | undefined; + inboundCourse: DegreesTrue | undefined - outboundCourse: DegreesTrue | undefined; + outboundCourse: DegreesTrue | undefined getPathStartPoint(): Coordinates | undefined { return this.inboundGuidable instanceof DmeArcTransition ? this.inboundGuidable.getPathEndPoint() : this.arcStartPoint; diff --git a/fbw-a380x/src/systems/fmgc/src/guidance/lnav/legs/Leg.ts b/fbw-a380x/src/systems/fmgc/src/guidance/lnav/legs/Leg.ts index e0dd86657d4e..ecb2fc144b48 100644 --- a/fbw-a380x/src/systems/fmgc/src/guidance/lnav/legs/Leg.ts +++ b/fbw-a380x/src/systems/fmgc/src/guidance/lnav/legs/Leg.ts @@ -28,13 +28,13 @@ export abstract class Leg extends Guidable { abstract get ident(): string - isNull = false; + isNull = false - displayedOnMap = true; + displayedOnMap = true - predictedTas: Knots; + predictedTas: Knots - predictedGs: Knots; + predictedGs: Knots get disableAutomaticSequencing(): boolean { return false; diff --git a/fbw-a380x/src/systems/fmgc/src/guidance/lnav/legs/TF.ts b/fbw-a380x/src/systems/fmgc/src/guidance/lnav/legs/TF.ts index f0d93dd6e484..8ef9284a335e 100644 --- a/fbw-a380x/src/systems/fmgc/src/guidance/lnav/legs/TF.ts +++ b/fbw-a380x/src/systems/fmgc/src/guidance/lnav/legs/TF.ts @@ -24,9 +24,9 @@ export class TFLeg extends XFLeg { private computedPath: PathVector[] = []; - altitudeConstraint: AltitudeConstraint | undefined; + altitudeConstraint: AltitudeConstraint | undefined - speedConstraint: SpeedConstraint | undefined; + speedConstraint: SpeedConstraint | undefined constructor( public from: Waypoint, diff --git a/fbw-a380x/src/systems/fmgc/src/guidance/lnav/transitions/DmeArcTransition.ts b/fbw-a380x/src/systems/fmgc/src/guidance/lnav/transitions/DmeArcTransition.ts index 51ea1774f11d..23922eca2a47 100644 --- a/fbw-a380x/src/systems/fmgc/src/guidance/lnav/transitions/DmeArcTransition.ts +++ b/fbw-a380x/src/systems/fmgc/src/guidance/lnav/transitions/DmeArcTransition.ts @@ -44,17 +44,17 @@ export class DmeArcTransition extends Transition { return this.ftp; } - private radius: NauticalMiles | undefined; + private radius: NauticalMiles | undefined - private itp: Coordinates | undefined; + private itp: Coordinates | undefined - private centre: Coordinates | undefined; + private centre: Coordinates | undefined - private ftp: Coordinates | undefined; + private ftp: Coordinates | undefined - private sweepAngle: Degrees | undefined; + private sweepAngle: Degrees | undefined - private clockwise: boolean | undefined; + private clockwise: boolean | undefined recomputeWithParameters(_isActive: boolean, tas: Knots, gs: MetresPerSecond, _ppos: Coordinates, _trueTrack: DegreesTrue) { if (this.isFrozen) { diff --git a/fbw-a380x/src/systems/fmgc/src/guidance/lnav/transitions/PathCaptureTransition.ts b/fbw-a380x/src/systems/fmgc/src/guidance/lnav/transitions/PathCaptureTransition.ts index fd17523e2b73..e3ba1d97b6da 100644 --- a/fbw-a380x/src/systems/fmgc/src/guidance/lnav/transitions/PathCaptureTransition.ts +++ b/fbw-a380x/src/systems/fmgc/src/guidance/lnav/transitions/PathCaptureTransition.ts @@ -69,7 +69,7 @@ export class PathCaptureTransition extends Transition { super(previousLeg, nextLeg); } - startWithTad = false; + startWithTad = false getPathStartPoint(): Coordinates | undefined { return this.itp; diff --git a/fbw-a380x/src/systems/fmgc/src/guidance/vnav/FlightModel.ts b/fbw-a380x/src/systems/fmgc/src/guidance/vnav/FlightModel.ts index c555a1f30f07..3ba3f1b13d7a 100644 --- a/fbw-a380x/src/systems/fmgc/src/guidance/vnav/FlightModel.ts +++ b/fbw-a380x/src/systems/fmgc/src/guidance/vnav/FlightModel.ts @@ -14,14 +14,14 @@ export class FlightModel { static requiredAccelRateMS2 = 0.684; // in m/s^2 - static gravityConstKNS = 19.0626; // in knots/second + static gravityConstKNS = 19.0626 // in knots/second static gravityConstMS2 = 9.806665; // in m/s^2 // From https://github.com/flybywiresim/a32nx/pull/6903#issuecomment-1073168320 - static machValues: Mach[] = [0.55, 0.6, 0.65, 0.7, 0.75, 0.8, 0.85]; + static machValues: Mach[] = [0.55, 0.6, 0.65, 0.7, 0.75, 0.8, 0.85] - static dragCoefficientCorrections: number[] = [0, 0.0002, 0.0003, 0.0004, 0.0008, 0.0015, 0.01]; + static dragCoefficientCorrections: number[] = [0, 0.0002, 0.0003, 0.0004, 0.0008, 0.0015, 0.01] /** * Get lift coefficient at given conditions diff --git a/fbw-a380x/src/systems/fmgc/src/guidance/vnav/VnavDriver.ts b/fbw-a380x/src/systems/fmgc/src/guidance/vnav/VnavDriver.ts index 9e77bdefc498..d51b651e6e3b 100644 --- a/fbw-a380x/src/systems/fmgc/src/guidance/vnav/VnavDriver.ts +++ b/fbw-a380x/src/systems/fmgc/src/guidance/vnav/VnavDriver.ts @@ -21,7 +21,7 @@ export class VnavDriver implements GuidanceComponent { currentClimbProfile: ClimbProfileBuilderResult; - currentDescentProfile: TheoreticalDescentPathCharacteristics; + currentDescentProfile: TheoreticalDescentPathCharacteristics currentApproachProfile: DecelPathCharacteristics; diff --git a/fbw-a380x/src/systems/fmgc/src/navigation/FlightArea.ts b/fbw-a380x/src/systems/fmgc/src/navigation/FlightArea.ts index 3af08c8430d2..b49da137a5fb 100644 --- a/fbw-a380x/src/systems/fmgc/src/navigation/FlightArea.ts +++ b/fbw-a380x/src/systems/fmgc/src/navigation/FlightArea.ts @@ -4,7 +4,7 @@ /** * Navigation flight areas */ -export enum FlightArea { + export enum FlightArea { Terminal, Takeoff, Enroute, diff --git a/fbw-a380x/src/systems/fmgc/src/types/fstypes/FSTypes.d.ts b/fbw-a380x/src/systems/fmgc/src/types/fstypes/FSTypes.d.ts index 2b2fa41b8b6c..73ae165aea65 100644 --- a/fbw-a380x/src/systems/fmgc/src/types/fstypes/FSTypes.d.ts +++ b/fbw-a380x/src/systems/fmgc/src/types/fstypes/FSTypes.d.ts @@ -74,7 +74,7 @@ declare global { constraintType: WaypointConstraintType; - additionalData: { [key: string]: any }; + additionalData: { [key: string]: any } turnDirection: TurnDirection; diff --git a/fbw-a380x/src/systems/instruments/src/Common/LegacyCdsDisplayUnit.tsx b/fbw-a380x/src/systems/instruments/src/Common/LegacyCdsDisplayUnit.tsx index c9810adabf4e..49c972906716 100644 --- a/fbw-a380x/src/systems/instruments/src/Common/LegacyCdsDisplayUnit.tsx +++ b/fbw-a380x/src/systems/instruments/src/Common/LegacyCdsDisplayUnit.tsx @@ -59,7 +59,7 @@ function BacklightBleed(props) { if (props.homeCockpit) { return null; } - return
; + return
; } export const LegacyCdsDisplayUnit = forwardRef>(({ displayUnitId, failed, children }, ref) => { @@ -127,7 +127,7 @@ export const LegacyCdsDisplayUnit = forwardRef - {children} + {children} ); } @@ -136,11 +136,11 @@ export const LegacyCdsDisplayUnit = forwardRef - - + + - - + + ); @@ -150,20 +150,20 @@ export const LegacyCdsDisplayUnit = forwardRef - - + + SAFETY TEST IN PROGRESS (MAX 30 SECONDS) diff --git a/fbw-a380x/src/systems/instruments/src/Common/NXLogic.ts b/fbw-a380x/src/systems/instruments/src/Common/NXLogic.ts index f01d05053f52..92af1b9b580b 100644 --- a/fbw-a380x/src/systems/instruments/src/Common/NXLogic.ts +++ b/fbw-a380x/src/systems/instruments/src/Common/NXLogic.ts @@ -10,49 +10,49 @@ * after the detection. It is not retriggerable, so a rising/falling edge within t will not reset the timer. */ export class NXLogicTriggeredMonostableNode { - t: number; + t: number; - risingEdge: boolean; + risingEdge: boolean; - timer: number; + timer: number; - previousValue: any; - - constructor(t, risingEdge = true) { - this.t = t; - this.risingEdge = risingEdge; - this.timer = 0; - this.previousValue = null; - } + previousValue: any; - write(value, _deltaTime) { - if (this.previousValue === null && SimVar.GetSimVarValue('L:A32NX_FWC_SKIP_STARTUP', 'Bool')) { - this.previousValue = value; + constructor(t, risingEdge = true) { + this.t = t; + this.risingEdge = risingEdge; + this.timer = 0; + this.previousValue = null; } - if (this.risingEdge) { - if (this.timer > 0) { - this.timer = Math.max(this.timer - _deltaTime / 1000, 0); - this.previousValue = value; - return true; - } if (!this.previousValue && value) { - this.timer = this.t; + + write(value, _deltaTime) { + if (this.previousValue === null && SimVar.GetSimVarValue('L:A32NX_FWC_SKIP_STARTUP', 'Bool')) { this.previousValue = value; - return true; } - } else { - if (this.timer > 0) { - this.timer = Math.max(this.timer - _deltaTime / 1000, 0); - this.previousValue = value; - return true; - } if (this.previousValue && !value) { - this.timer = this.t; - this.previousValue = value; - return true; + if (this.risingEdge) { + if (this.timer > 0) { + this.timer = Math.max(this.timer - _deltaTime / 1000, 0); + this.previousValue = value; + return true; + } if (!this.previousValue && value) { + this.timer = this.t; + this.previousValue = value; + return true; + } + } else { + if (this.timer > 0) { + this.timer = Math.max(this.timer - _deltaTime / 1000, 0); + this.previousValue = value; + return true; + } if (this.previousValue && !value) { + this.timer = this.t; + this.previousValue = value; + return true; + } } + this.previousValue = value; + return false; } - this.previousValue = value; - return false; - } } /** diff --git a/fbw-a380x/src/systems/instruments/src/Common/gauges.tsx b/fbw-a380x/src/systems/instruments/src/Common/gauges.tsx index 75c25cb7a82d..36b218f26414 100644 --- a/fbw-a380x/src/systems/instruments/src/Common/gauges.tsx +++ b/fbw-a380x/src/systems/instruments/src/Common/gauges.tsx @@ -136,7 +136,7 @@ export const GaugeMarkerComponent: React.FC = ({ return ( <> - {textValue} + {textValue} ); }; @@ -158,7 +158,7 @@ export const GaugeComponent: FC = memo(({ x, y, radius, sta return ( <> - + <>{children} @@ -277,7 +277,7 @@ export const GaugeThrustComponent: FC = memo(({ x, y, return ( <> - + diff --git a/fbw-a380x/src/systems/instruments/src/EWD/EngineWarningDisplay.tsx b/fbw-a380x/src/systems/instruments/src/EWD/EngineWarningDisplay.tsx index 2e2f7c427e42..c3934adbe1c7 100644 --- a/fbw-a380x/src/systems/instruments/src/EWD/EngineWarningDisplay.tsx +++ b/fbw-a380x/src/systems/instruments/src/EWD/EngineWarningDisplay.tsx @@ -32,13 +32,13 @@ export const EngineWarningDisplay: React.FC = () => { - THR - % + THR + % {/* N1 */} - N1 - % + N1 + % @@ -47,10 +47,10 @@ export const EngineWarningDisplay: React.FC = () => { {/* EGT */} - EGT - °C + EGT + °C - + {/* BEFORE START */} diff --git a/fbw-a380x/src/systems/instruments/src/EWD/elements/EGT.tsx b/fbw-a380x/src/systems/instruments/src/EWD/elements/EGT.tsx index 8820a3251c30..9314705cf312 100644 --- a/fbw-a380x/src/systems/instruments/src/EWD/elements/EGT.tsx +++ b/fbw-a380x/src/systems/instruments/src/EWD/elements/EGT.tsx @@ -49,15 +49,15 @@ const EGT: React.FC = ({ x, y, engine, active }) => { {!active && ( <> - - XX + + XX )} {active && ( <> {Math.round(EGTemperature)} - - + + = ({ x, y, engine, active }) => { radius={radius} startAngle={startAngle} endAngle={endAngle} - className="GaugeText Gauge Medium" + className='GaugeText Gauge Medium' /> - - + + = ({ x, y, engine, active }) => { radius={radius} startAngle={startAngle} endAngle={endAngle} - className="GaugeThrustLimitIndicatorFill Gauge" + className='GaugeThrustLimitIndicatorFill Gauge' /> - + = ({ x, y, {active && showBorder && ( <> - - + + )} diff --git a/fbw-a380x/src/systems/instruments/src/EWD/elements/N1.tsx b/fbw-a380x/src/systems/instruments/src/EWD/elements/N1.tsx index 677408afb5c1..0972d7726bb5 100644 --- a/fbw-a380x/src/systems/instruments/src/EWD/elements/N1.tsx +++ b/fbw-a380x/src/systems/instruments/src/EWD/elements/N1.tsx @@ -23,26 +23,26 @@ const N1: React.FC = ({ x, y {!active && ( <> - - XX + + XX )} {active && !n1Degraded && ( <> - {N1PercentSplit[0]} - . - {N1PercentSplit[1]} + {N1PercentSplit[0]} + . + {N1PercentSplit[1]} )} {active && n1Degraded && ( <> - {N1PercentSplit[0]} - . - {N1PercentSplit[1]} - - + {N1PercentSplit[0]} + . + {N1PercentSplit[1]} + + = ({ x, y radius={radius} startAngle={startAngle} endAngle={endAngle} - className="GaugeText Gauge" + className='GaugeText Gauge' showValue textNudgeY={-5} textNudgeX={13} @@ -67,7 +67,7 @@ const N1: React.FC = ({ x, y radius={radius} startAngle={startAngle} endAngle={endAngle} - className="GaugeText Gauge" + className='GaugeText Gauge' textNudgeY={6} textNudgeX={13} multiplierInner={0.9} @@ -81,7 +81,7 @@ const N1: React.FC = ({ x, y radius={radius} startAngle={startAngle} endAngle={endAngle} - className="GaugeText Gauge" + className='GaugeText Gauge' showValue textNudgeX={7} textNudgeY={11} @@ -96,7 +96,7 @@ const N1: React.FC = ({ x, y radius={radius} startAngle={startAngle} endAngle={endAngle} - className="GaugeText Gauge" + className='GaugeText Gauge' multiplierInner={0.9} /> = ({ x, y radius={radius} startAngle={startAngle} endAngle={endAngle} - className="GaugeText Gauge" + className='GaugeText Gauge' showValue textNudgeY={0} textNudgeX={-13} multiplierInner={0.9} /> - + = ({ x, y radius={radius} startAngle={startAngle} endAngle={endAngle} - className="GaugeIndicator Gauge" + className='GaugeIndicator Gauge' multiplierOuter={1.10} indicator /> @@ -149,7 +149,7 @@ const N1: React.FC = ({ x, y radius={radius} startAngle={startAngle} endAngle={endAngle} - className="DonutThrottleIndicator" + className='DonutThrottleIndicator' /> @@ -211,7 +211,7 @@ const N1CommandAndTrend: React.FC = ({ x, y, radius, sta startAngle={N1Actual > (N1Commanded / 10) ? n1CommandXY.angle : n1ActualXY.angle} endAngle={N1Actual > (N1Commanded / 10) ? n1ActualXY.angle : n1CommandXY.angle} visible={autothrustStatus === 2 && Math.abs(N1Actual - (N1Commanded / 10)) > 0.3} - className="GreenLine" + className='GreenLine' />)); return ( diff --git a/fbw-a380x/src/systems/instruments/src/EWD/elements/ThrustGauge.tsx b/fbw-a380x/src/systems/instruments/src/EWD/elements/ThrustGauge.tsx index 8357d52522fa..f15a11144c47 100644 --- a/fbw-a380x/src/systems/instruments/src/EWD/elements/ThrustGauge.tsx +++ b/fbw-a380x/src/systems/instruments/src/EWD/elements/ThrustGauge.tsx @@ -42,8 +42,8 @@ const ThrustGauge: React.FC {(!active || n1Degraded) && ( <> - - THR XX + + THR XX )} {active && !n1Degraded @@ -52,9 +52,9 @@ const ThrustGauge: React.FC {(!revVisible || [1, 4].includes(engine)) && ( <> - {ThrustPercentSplit[0]} - . - {ThrustPercentSplit[1]} + {ThrustPercentSplit[0]} + . + {ThrustPercentSplit[1]} min={min} max={max} visible={availVisible || engineState === 1} - className="GaugeComponent GaugeThrustFill" + className='GaugeComponent GaugeThrustFill' /> radius={radius} startAngle={startAngle} endAngle={endAngle} - className="DonutThrottleIndicator" + className='DonutThrottleIndicator' /> )} - + radius={radius} startAngle={startAngle} endAngle={endAngle} - className="GaugeText Gauge" + className='GaugeText Gauge' showValue textNudgeY={-5} textNudgeX={13} @@ -109,7 +109,7 @@ const ThrustGauge: React.FC radius={radius} startAngle={startAngle} endAngle={endAngle} - className="GaugeText Gauge" + className='GaugeText Gauge' textNudgeY={6} textNudgeX={13} multiplierInner={0.9} @@ -123,7 +123,7 @@ const ThrustGauge: React.FC radius={radius} startAngle={startAngle} endAngle={endAngle} - className="GaugeText Gauge" + className='GaugeText Gauge' showValue textNudgeX={7} textNudgeY={11} @@ -138,7 +138,7 @@ const ThrustGauge: React.FC radius={radius} startAngle={startAngle} endAngle={endAngle} - className="GaugeText Gauge" + className='GaugeText Gauge' multiplierInner={0.9} /> radius={radius} startAngle={startAngle} endAngle={endAngle} - className="GaugeText Gauge" + className='GaugeText Gauge' showValue textNudgeY={0} textNudgeX={-13} @@ -159,7 +159,7 @@ const ThrustGauge: React.FC {(!revVisible || [1, 4].includes(engine)) && ( <> - + radius={radius} startAngle={startAngle} endAngle={endAngle} - className="GaugeIndicator Gauge" + className='GaugeIndicator Gauge' multiplierOuter={1.10} indicator /> @@ -193,11 +193,11 @@ const ThrustGauge: React.FC min={revMin} max={revMax} visible={revVisible || engineState === 1} - className="GaugeComponent GaugeThrustFill" + className='GaugeComponent GaugeThrustFill' reverse /> {/* reverse */} - + radius={revRadius} startAngle={revStartAngle} endAngle={revEndAngle} - className="GaugeText Gauge" + className='GaugeText Gauge' textNudgeY={0} textNudgeX={-13} multiplierInner={1.1} @@ -222,7 +222,7 @@ const ThrustGauge: React.FC radius={revRadius} startAngle={revStartAngle} endAngle={revEndAngle} - className="GaugeIndicator Gauge" + className='GaugeIndicator Gauge' multiplierOuter={1.10} indicator reverse @@ -237,7 +237,7 @@ const ThrustGauge: React.FC radius={revRadius} startAngle={revStartAngle} endAngle={revEndAngle} - className="DonutThrottleIndicator" + className='DonutThrottleIndicator' /> @@ -260,11 +260,11 @@ type AvailRevProps = { const AvailRev: React.FC = ({ x, y, mesg, visible, revDoorOpen }) => ( <> - + {mesg === 'REV' && 5 ? 'Green' : 'Amber'}`} x={x - 8} y={y + 9}>REV} {mesg === 'AVAIL' - && AVAIL} + && AVAIL} ); diff --git a/fbw-a380x/src/systems/instruments/src/EWD/elements/ThrustRatingMode.tsx b/fbw-a380x/src/systems/instruments/src/EWD/elements/ThrustRatingMode.tsx index f36c65079304..e0ae5d6fb941 100644 --- a/fbw-a380x/src/systems/instruments/src/EWD/elements/ThrustRatingMode.tsx +++ b/fbw-a380x/src/systems/instruments/src/EWD/elements/ThrustRatingMode.tsx @@ -21,27 +21,27 @@ const N1Limit: React.FC = ({ x, y, active }) => { return ( <> - + {!active && ( <> - XX + XX )} {active && ( <> - {thrustLimitTypeArray[N1LimitType]} - {N1ThrustLimitSplit[0]} - . - {N1ThrustLimitSplit[1]} - % + {thrustLimitTypeArray[N1LimitType]} + {N1ThrustLimitSplit[0]} + . + {N1ThrustLimitSplit[1]} + % )} {active && displayFlexTemp && ( <> - + {Math.round(flexTemp)} °C diff --git a/fbw-a380x/src/systems/instruments/src/MFD/ATCCOM/Messages/Clearance/RequestDepartureClearance.tsx b/fbw-a380x/src/systems/instruments/src/MFD/ATCCOM/Messages/Clearance/RequestDepartureClearance.tsx index c0db257e53e9..966896310efb 100644 --- a/fbw-a380x/src/systems/instruments/src/MFD/ATCCOM/Messages/Clearance/RequestDepartureClearance.tsx +++ b/fbw-a380x/src/systems/instruments/src/MFD/ATCCOM/Messages/Clearance/RequestDepartureClearance.tsx @@ -4,7 +4,9 @@ import { MessageElement } from '../../Elements/MessageElement'; import { MessageVisualizationProps } from '../Registry'; export const RequestDepartureClearance: FC = ({ x = 0, y = 0, index, messageElements, onDelete }) => { - const updateValue = (value: string, boxIndex: number): boolean => false; + const updateValue = (value: string, boxIndex: number): boolean => { + return false; + }; return ( <> diff --git a/fbw-a380x/src/systems/instruments/src/MFD/ATCCOM/Messages/Clearance/RequestOceanicClearance.tsx b/fbw-a380x/src/systems/instruments/src/MFD/ATCCOM/Messages/Clearance/RequestOceanicClearance.tsx index 9c0295c68db6..ef0f566bcc9b 100644 --- a/fbw-a380x/src/systems/instruments/src/MFD/ATCCOM/Messages/Clearance/RequestOceanicClearance.tsx +++ b/fbw-a380x/src/systems/instruments/src/MFD/ATCCOM/Messages/Clearance/RequestOceanicClearance.tsx @@ -4,7 +4,9 @@ import { MessageElement } from '../../Elements/MessageElement'; import { MessageVisualizationProps } from '../Registry'; export const RequestOceanicClearance: FC = ({ x = 0, y = 0, index, messageElements, onDelete }) => { - const updateValue = (value: string, boxIndex: number): boolean => false; + const updateValue = (value: string, boxIndex: number): boolean => { + return false; + }; return ( <> diff --git a/fbw-a380x/src/systems/instruments/src/MFD/Components/Dropdown.tsx b/fbw-a380x/src/systems/instruments/src/MFD/Components/Dropdown.tsx index 6aae28b61912..4c2be0de58f5 100644 --- a/fbw-a380x/src/systems/instruments/src/MFD/Components/Dropdown.tsx +++ b/fbw-a380x/src/systems/instruments/src/MFD/Components/Dropdown.tsx @@ -105,8 +105,8 @@ export const Dropdown: FC = ({ if (open && disabled) setOpen(false); return ( - -