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;"
/>