diff --git a/fbw-a32nx/src/systems/fmgc/src/flightplanning/FlightPlanInterface.ts b/fbw-a32nx/src/systems/fmgc/src/flightplanning/FlightPlanInterface.ts index 33767f018e5..8878282623f 100644 --- a/fbw-a32nx/src/systems/fmgc/src/flightplanning/FlightPlanInterface.ts +++ b/fbw-a32nx/src/systems/fmgc/src/flightplanning/FlightPlanInterface.ts @@ -11,7 +11,10 @@ import { FlightPlan } from '@fmgc/flightplanning/plans/FlightPlan'; import { FlightPlanIndex } from '@fmgc/flightplanning/FlightPlanManager'; import { AltitudeConstraint } from '@fmgc/flightplanning/data/constraint'; import { ReadonlyFlightPlan } from '@fmgc/flightplanning/plans/ReadonlyFlightPlan'; -import { FlightPlanPerformanceData } from '@fmgc/flightplanning/plans/performance/FlightPlanPerformanceData'; +import { + FlightPlanPerformanceData, + SpeedLimitType, +} from '@fmgc/flightplanning/plans/performance/FlightPlanPerformanceData'; import { FlightPlanLeg } from '@fmgc/flightplanning/legs/FlightPlanLeg'; /** @@ -300,6 +303,22 @@ export interface FlightPlanInterface

; + setPilotEntrySpeedLimitAltitude( + type: SpeedLimitType, + value: number, + planIndex: FlightPlanIndex, + alternate: boolean, + ): void; + + setPilotEntrySpeedLimitSpeed( + type: SpeedLimitType, + value: number, + planIndex: FlightPlanIndex, + alternate: boolean, + ): void; + + deleteSpeedLimit(type: SpeedLimitType, planIndex: FlightPlanIndex, alternate: boolean): void; + // TODO do not pass in waypoint object (rpc) isWaypointInUse(waypoint: Waypoint): Promise; diff --git a/fbw-a32nx/src/systems/fmgc/src/flightplanning/FlightPlanService.ts b/fbw-a32nx/src/systems/fmgc/src/flightplanning/FlightPlanService.ts index d762c674f81..3f28927904c 100644 --- a/fbw-a32nx/src/systems/fmgc/src/flightplanning/FlightPlanService.ts +++ b/fbw-a32nx/src/systems/fmgc/src/flightplanning/FlightPlanService.ts @@ -16,7 +16,11 @@ import { FlightPlanLegDefinition } from '@fmgc/flightplanning/legs/FlightPlanLeg import { FlightPlanInterface } from '@fmgc/flightplanning/FlightPlanInterface'; import { AltitudeConstraint } from '@fmgc/flightplanning/data/constraint'; import { CopyOptions } from '@fmgc/flightplanning/plans/CloningOptions'; -import { FlightPlanPerformanceData } from '@fmgc/flightplanning/plans/performance/FlightPlanPerformanceData'; +import { + DefaultPerformanceData, + FlightPlanPerformanceData, + SpeedLimitType, +} from '@fmgc/flightplanning/plans/performance/FlightPlanPerformanceData'; export class FlightPlanService

implements FlightPlanInterface

@@ -574,6 +578,108 @@ export class FlightPlanService

{ // RTA page // SPD page - private readonly speedMessageArea = Subject.create('TOO STEEP PATH AHEAD'); + private readonly speedMessageArea = Subject.create(''); /** in knots */ private readonly speedConstraintInput = Subject.create(null); private readonly spdConstraintDisabled = Subject.create(true); - private readonly cannotDeleteSpeedConstraint = Subject.create(false); + private readonly cannotDeleteSpeedConstraint = Subject.create(true); - private readonly climbSpeedLimit = Subject.create(true); + private readonly speedLimitType = Subject.create(SpeedLimitType.CLB); private readonly speedLimitPilotEntered = Subject.create(false); - private readonly speedLimit = Subject.create(null); + private readonly speedLimitSpeed = Subject.create(null); private readonly speedLimitAltitude = Subject.create(null); private readonly speedLimitTransition = Subject.create(null); - private readonly showSpeedLimitVisibility = MappedSubject.create( - ([knotSpeedLimit, altitudeSpeedLimit]) => - knotSpeedLimit !== null && altitudeSpeedLimit !== null ? 'visible' : 'hidden', - this.speedLimit, - this.speedLimitAltitude, + private readonly speedLimitText = this.speedLimitType.map( + (v) => `${v === SpeedLimitType.CLB ? 'CLB' : 'DES'} SPD LIMIT`, ); - private readonly speedLimitText = this.climbSpeedLimit.map((v) => `${v ? 'CLB' : 'DES'} SPD LIMIT`); + private readonly deleteSpeedLimitDisabled = MappedSubject.create( + ([speed, altitude]) => speed === null || altitude === null, + this.speedLimitSpeed, + this.speedLimitAltitude, + ); // CMS page // ALT page - private readonly altitudeMessageArea = Subject.create('TOO STEEP PATH AHEAD'); + private readonly altitudeMessageArea = Subject.create(''); /** in feet */ private readonly altitudeConstraintInput = Subject.create(null); private readonly altConstraintDisabled = Subject.create(true); - private readonly cannotDeleteAltConstraint = Subject.create(false); + private readonly cannotDeleteAltConstraint = Subject.create(true); private readonly altitudeClbDesConstraintVisibility = Subject.create('hidden'); @@ -264,28 +265,37 @@ export class MfdFmsFplnVertRev extends FmsPage { // Load speed constraints - this.climbSpeedLimit.set( - leg.constraintType === WaypointConstraintType.CLB || this.activeFlightPhase.get() <= FmgcFlightPhase.Cruise, + this.speedLimitType.set( + leg.constraintType === WaypointConstraintType.DES || + (this.activeFlightPhase.get() > FmgcFlightPhase.Cruise && + this.activeFlightPhase.get() < FmgcFlightPhase.GoAround) + ? SpeedLimitType.DES + : SpeedLimitType.CLB, ); - const climbSpeedLimit = this.climbSpeedLimit.get(); - const speedLimit = climbSpeedLimit - ? this.props.fmcService.master.fmgc.getClimbSpeedLimit() - : this.props.fmcService.master.fmgc.getDescentSpeedLimit(); - if (speedLimit && speedLimit.speed && speedLimit.underAltitude) { - this.speedLimitPilotEntered.set( - climbSpeedLimit - ? this.loadedFlightPlan.performanceData.isClimbSpeedLimitPilotEntered - : this.loadedFlightPlan.performanceData.isDescentSpeedLimitPilotEntered, - ); - this.speedLimit.set(speedLimit.speed); - this.speedLimitAltitude.set(speedLimit.underAltitude); - this.speedLimitTransition.set( - climbSpeedLimit - ? this.loadedFlightPlan.performanceData.transitionAltitude - : this.loadedFlightPlan.performanceData.transitionLevel, - ); - } + // TODO handle alternate? + const climbSpeedLimit = this.speedLimitType.get() === SpeedLimitType.CLB; + + const speedLimitSpeed = climbSpeedLimit + ? this.loadedFlightPlan.performanceData.climbSpeedLimitSpeed + : this.loadedFlightPlan.performanceData.descentSpeedLimitSpeed; + + const speedLimitAltitude = climbSpeedLimit + ? this.loadedFlightPlan.performanceData.climbSpeedLimitAltitude + : this.loadedFlightPlan.performanceData.descentSpeedLimitAltitude; + + this.speedLimitSpeed.set(speedLimitSpeed); + this.speedLimitAltitude.set(speedLimitAltitude); + this.speedLimitPilotEntered.set( + climbSpeedLimit + ? this.loadedFlightPlan.performanceData.isClimbSpeedLimitPilotEntered + : this.loadedFlightPlan.performanceData.isDescentSpeedLimitPilotEntered, + ); + this.speedLimitTransition.set( + climbSpeedLimit + ? this.loadedFlightPlan.performanceData.transitionAltitude + : this.loadedFlightPlan.performanceData.transitionLevel, + ); this.speedConstraintInput.set(leg.speedConstraint?.speed ?? null); this.constraintType.set( @@ -553,40 +563,44 @@ export class MfdFmsFplnVertRev extends FmsPage { } } + private checkPerformanceDataEditCondition() { + return this.checkLegModificationAllowed() && this.loadedFlightPlan?.performanceData; + } + private async tryUpdateSpeedLimitValue(value: number | null) { - if (this.checkLegModificationAllowed() && this.loadedFlightPlan?.performanceData) { - const clbSpdLimit = this.climbSpeedLimit.get(); - this.loadedFlightPlan.setPerformanceData( - clbSpdLimit ? 'climbSpeedLimitSpeed' : 'descentSpeedLimitSpeed', - value ?? - (clbSpdLimit ? DefaultPerformanceData.ClimbSpeedLimitSpeed : DefaultPerformanceData.DescentSpeedLimitSpeed), - ); - this.loadedFlightPlan.setPerformanceData( - clbSpdLimit ? 'isClimbSpeedLimitPilotEntered' : 'isDescentSpeedLimitPilotEntered', - value !== null, + if (value === null) { + this.deleteSpeedLimit(); + } else if (this.checkPerformanceDataEditCondition()) { + this.props.fmcService.master?.flightPlanService.setPilotEntrySpeedLimitSpeed( + this.speedLimitType.get(), + value, + this.loadedFlightPlanIndex.get(), + false, ); } } private async tryUpdateSpeedLimitAltitude(value: number | null) { - if (this.checkLegModificationAllowed() && this.loadedFlightPlan?.performanceData) { - const clbSpdLimit = this.climbSpeedLimit.get(); - this.loadedFlightPlan.setPerformanceData( - clbSpdLimit ? 'climbSpeedLimitAltitude' : 'descentSpeedLimitAltitude', - value ?? - (clbSpdLimit - ? DefaultPerformanceData.ClimbSpeedLimitAltitude - : DefaultPerformanceData.DescentSpeedLimitAltitude), - ); - this.loadedFlightPlan.setPerformanceData( - clbSpdLimit ? 'isClimbSpeedLimitPilotEntered' : 'isDescentSpeedLimitPilotEntered', - value !== null, + if (value === null) { + this.deleteSpeedLimit(); + } else if (this.checkPerformanceDataEditCondition()) { + this.props.fmcService.master?.flightPlanService.setPilotEntrySpeedLimitAltitude( + this.speedLimitType.get(), + value, + this.loadedFlightPlanIndex.get(), + false, ); } } private async deleteSpeedLimit() { - this.tryUpdateSpeedLimitAltitude(null); + if (this.checkPerformanceDataEditCondition()) { + this.props.fmcService.master?.flightPlanService.deleteSpeedLimit( + this.speedLimitType.get(), + this.loadedFlightPlanIndex.get(), + false, + ); + } } /** @@ -790,8 +804,8 @@ export class MfdFmsFplnVertRev extends FmsPage { this.selectedAltitudeConstraintDisabled, this.selectedAltitudeConstraintInvisible, this.stepNotAllowedAtVisibility, - this.showSpeedLimitVisibility, this.speedLimitText, + this.deleteSpeedLimitDisabled, ); this.subs.push( @@ -897,14 +911,14 @@ export class MfdFmsFplnVertRev extends FmsPage { buttonStyle="adding-right: 2px;" /> -

+
{this.speedLimitText}
dataEntryFormat={new SpeedKnotsFormat(Subject.create(90), Subject.create(Vmo))} dataHandlerDuringValidation={(val) => this.tryUpdateSpeedLimitValue(val)} mandatory={Subject.create(false)} - value={this.speedLimit} + value={this.speedLimitSpeed} alignText="flex-end" tmpyActive={this.tmpyActive} enteredByPilot={this.speedLimitPilotEntered} @@ -939,6 +953,7 @@ export class MfdFmsFplnVertRev extends FmsPage { onClick={() => { this.deleteSpeedLimit(); }} + disabled={this.deleteSpeedLimitDisabled} buttonStyle="adding-right: 2px;" />