From 2c9109bcd4b8718a341c918140edbb65cf78d8ea Mon Sep 17 00:00:00 2001
From: Michael Corcoran <tracer@outlook.co.nz>
Date: Fri, 17 Jan 2025 19:07:02 +1300
Subject: [PATCH 1/4] fix(mathutils): remove machToKCas temperature dependency
 (#9771)

---
 .../systems/shared/src/OperatingSpeeds.tsx    | 19 ++-----------------
 .../src/systems/shared/src/MathUtils.spec.ts  | 10 ++++++++++
 .../src/systems/shared/src/MathUtils.ts       | 11 +++++++----
 3 files changed, 19 insertions(+), 21 deletions(-)

diff --git a/fbw-a380x/src/systems/shared/src/OperatingSpeeds.tsx b/fbw-a380x/src/systems/shared/src/OperatingSpeeds.tsx
index f5fcd90d7c3..c8fd7d26b9a 100644
--- a/fbw-a380x/src/systems/shared/src/OperatingSpeeds.tsx
+++ b/fbw-a380x/src/systems/shared/src/OperatingSpeeds.tsx
@@ -402,29 +402,14 @@ function getVfeNIdx(fi: number): number {
   }
 }
 
-/**
- * Convert degrees Celsius into Kelvin
- * @param T degrees Celsius
- * @returns degrees Kelvin
- */
-function convertCtoK(T: number): number {
-  return T + 273.15;
-}
-
 /**
  * Get correct Vmax for Vmo and Mmo in knots
  * @returns Min(Vmo, Mmo)
  * @private
  */
 function getVmo() {
-  return Math.min(
-    Vmo,
-    MathUtils.convertMachToKCas(
-      Mmo,
-      convertCtoK(Simplane.getAmbientTemperature()),
-      SimVar.GetSimVarValue('AMBIENT PRESSURE', 'millibar'),
-    ),
-  );
+  // FIXME use ADR corrected average static pressure
+  return Math.min(Vmo, MathUtils.convertMachToKCas(Mmo, SimVar.GetSimVarValue('AMBIENT PRESSURE', 'millibar')));
 }
 
 export class A380OperatingSpeeds {
diff --git a/fbw-common/src/systems/shared/src/MathUtils.spec.ts b/fbw-common/src/systems/shared/src/MathUtils.spec.ts
index 5ff140552f5..51600fc9239 100644
--- a/fbw-common/src/systems/shared/src/MathUtils.spec.ts
+++ b/fbw-common/src/systems/shared/src/MathUtils.spec.ts
@@ -143,4 +143,14 @@ describe('MathUtils.correctMsfsLocaliserError', () => {
     expect(MathUtils.correctMsfsLocaliserError(177.5)).toBeCloseTo(2.5);
     expect(MathUtils.correctMsfsLocaliserError(90.1)).toBeCloseTo(89.9);
   });
+
+  describe('MathUtils.convertMachToKCas', () => {
+    it('correctly converts mach to CAS', () => {
+      expect(MathUtils.convertMachToKCas(0, 1013.25)).toBeCloseTo(0);
+      expect(MathUtils.convertMachToKCas(0.84, 1013.25)).toBeCloseTo(555.634);
+      // FL350 = 238.423 hPa
+      expect(MathUtils.convertMachToKCas(0, 238.423)).toBeCloseTo(0);
+      expect(MathUtils.convertMachToKCas(0.84, 238.423)).toBeCloseTo(287.097);
+    });
+  });
 });
diff --git a/fbw-common/src/systems/shared/src/MathUtils.ts b/fbw-common/src/systems/shared/src/MathUtils.ts
index a835dee0608..1ecf06db53a 100644
--- a/fbw-common/src/systems/shared/src/MathUtils.ts
+++ b/fbw-common/src/systems/shared/src/MathUtils.ts
@@ -289,7 +289,7 @@ export class MathUtils {
     return (
       1479.1 *
       Math.sqrt(
-        ((pressure / 1013) * ((1 + (1 / (oat / 288.15)) * (tas / 1479.1) ** 2) ** 3.5 - 1) + 1) ** (1 / 3.5) - 1,
+        ((pressure / 1013.25) * ((1 + (1 / (oat / 288.15)) * (tas / 1479.1) ** 2) ** 3.5 - 1) + 1) ** (1 / 3.5) - 1,
       )
     );
   }
@@ -306,7 +306,7 @@ export class MathUtils {
       1479.1 *
       Math.sqrt(
         (oat / 288.15) *
-          (((1 / (pressure / 1013)) * ((1 + 0.2 * (kcas / 661.4786) ** 2) ** 3.5 - 1) + 1) ** (1 / 3.5) - 1),
+          (((1 / (pressure / 1013.25)) * ((1 + 0.2 * (kcas / 661.4786) ** 2) ** 3.5 - 1) + 1) ** (1 / 3.5) - 1),
       )
     );
   }
@@ -318,8 +318,11 @@ export class MathUtils {
    * @param pressure current pressure hpa
    * @returns Calibrated Air Speed
    */
-  public static convertMachToKCas(mach: number, oat: number, pressure: number): number {
-    return MathUtils.convertTasToKCas(MathUtils.convertMachToKTas(mach, oat), oat, pressure);
+  public static convertMachToKCas(mach: number, pressure: number): number {
+    // Formula from Jet Transport Performance Methods 2009.
+    return (
+      1479.1 * Math.sqrt(Math.pow((pressure / 1013.25) * (Math.pow(0.2 * mach * mach + 1, 3.5) - 1) + 1, 1 / 3.5) - 1)
+    );
   }
 
   /**

From c5991b8a0d8c036c28ee5bc8792940b274d69e84 Mon Sep 17 00:00:00 2001
From: floridude <63071941+flogross89@users.noreply.github.com>
Date: Fri, 17 Jan 2025 08:46:08 +0200
Subject: [PATCH 2/4] fix(a380x/pfd): Fix precision of pitch trim indicator
 (#9770)

* clean-up oops: remove failures

* increase precision of cgPercent subscription (value is percent, but from 0 to 1)

* changelog
---
 .github/CHANGELOG.md                                      | 1 +
 fbw-a380x/src/systems/instruments/src/PFD/PFD.tsx         | 8 --------
 .../src/systems/instruments/src/PFD/PitchTrimDisplay.tsx  | 2 +-
 3 files changed, 2 insertions(+), 9 deletions(-)

diff --git a/.github/CHANGELOG.md b/.github/CHANGELOG.md
index b396639427e..a92b729492d 100644
--- a/.github/CHANGELOG.md
+++ b/.github/CHANGELOG.md
@@ -124,6 +124,7 @@
 1. [A380X/FCU] Add TRUE indication on FCU when TRUE North reference is selected on AFS CP - @heclak (Heclak)
 1. [A380X/MFD] Add airport data page into the MFD (DATA > AIRPORT) - @bulenteroglu (senolitam)
 1. [A380X/EFB] Adds PRIM/SEC/FCDC failures to EFB - @flogross89 (floridude)
+1. [A380X/PFD] Fix precision of pitch trim indicator - @flogross89 (floridude)
 
 
 ## 0.12.0
diff --git a/fbw-a380x/src/systems/instruments/src/PFD/PFD.tsx b/fbw-a380x/src/systems/instruments/src/PFD/PFD.tsx
index 385b8be4864..46e53d877a5 100644
--- a/fbw-a380x/src/systems/instruments/src/PFD/PFD.tsx
+++ b/fbw-a380x/src/systems/instruments/src/PFD/PFD.tsx
@@ -1,4 +1,3 @@
-import { A380Failure } from '@flybywiresim/failures';
 import {
   ClockEvents,
   ComponentProps,
@@ -103,8 +102,6 @@ export class PFDComponent extends DisplayComponent<PFDProps> {
   public onAfterRender(node: VNode): void {
     super.onAfterRender(node);
 
-    this.failuresConsumer.register(getDisplayIndex() === 1 ? A380Failure.LeftPfdDisplay : A380Failure.RightPfdDisplay);
-
     this.sub.on('headingAr').handle((h) => {
       if (this.headingFailed.get() !== h.isNormalOperation()) {
         this.headingFailed.set(!h.isNormalOperation());
@@ -124,11 +121,6 @@ export class PFDComponent extends DisplayComponent<PFDProps> {
       .atFrequency(1)
       .handle((_t) => {
         this.failuresConsumer.update();
-        this.displayFailed.set(
-          this.failuresConsumer.isActive(
-            getDisplayIndex() === 1 ? A380Failure.LeftPfdDisplay : A380Failure.RightPfdDisplay,
-          ),
-        );
         if (
           !this.isAttExcessive.get() &&
           ((this.pitch.isNormalOperation() && (this.pitch.value > 25 || this.pitch.value < -13)) ||
diff --git a/fbw-a380x/src/systems/instruments/src/PFD/PitchTrimDisplay.tsx b/fbw-a380x/src/systems/instruments/src/PFD/PitchTrimDisplay.tsx
index f10a16d143d..5966a11206a 100644
--- a/fbw-a380x/src/systems/instruments/src/PFD/PitchTrimDisplay.tsx
+++ b/fbw-a380x/src/systems/instruments/src/PFD/PitchTrimDisplay.tsx
@@ -41,7 +41,7 @@ export class PitchTrimDisplay extends DisplayComponent<{ bus: EventBus; visible:
 
   private readonly fwcFlightPhase = ConsumerSubject.create(this.sub.on('fwcFlightPhase'), 0);
 
-  private readonly cgPercent = ConsumerSubject.create(this.sub.on('cgPercent').withPrecision(2), 0).map(
+  private readonly cgPercent = ConsumerSubject.create(this.sub.on('cgPercent').withPrecision(4), 0).map(
     (it) => it * 100,
   );
 

From bf00fa872d72c0b1b03b13da79fefb0648a1a3b3 Mon Sep 17 00:00:00 2001
From: donstim <70166617+donstim@users.noreply.github.com>
Date: Fri, 17 Jan 2025 04:07:10 -0400
Subject: [PATCH 3/4] fix(a32nx/takeoff calculator): Accuracy update for
 takeoff calculator V2 speeds (#9733)

* Update a32nx_takeoff.ts

* Update a32nx_takeoff.ts

* Update a32nx_takeoff.ts

* Update a32nx_takeoff.ts

* Update a32nx_takeoff.ts

* Update a32nx_takeoff.ts

* Update a32nx_takeoff.ts

* Update a32nx_takeoff.ts

* Update a32nx_takeoff.ts

* Update a32nx_takeoff.ts
---
 .../shared/src/performance/a32nx_takeoff.ts      | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/fbw-a32nx/src/systems/shared/src/performance/a32nx_takeoff.ts b/fbw-a32nx/src/systems/shared/src/performance/a32nx_takeoff.ts
index 6a56f4802c4..2bf31ac5377 100644
--- a/fbw-a32nx/src/systems/shared/src/performance/a32nx_takeoff.ts
+++ b/fbw-a32nx/src/systems/shared/src/performance/a32nx_takeoff.ts
@@ -82,7 +82,7 @@ export class A320251NTakeoffPerformanceCalculator implements TakeoffPerformanceC
 
   /** CONF 1+F runway limited weights at sea level/ISA/0 slope/no bleed/fwd cg/no wind/dry, MTOW [kg], runway length [metres] => lookup key = (runway length) */
   private static readonly runwayPerfLimitConf1 = new LerpLookupTable([
-    [54_000, 1000],
+    [53_950, 1000],
     [59_300, 1219],
     [68_700, 1604],
     [75_700, 1959],
@@ -914,31 +914,31 @@ export class A320251NTakeoffPerformanceCalculator implements TakeoffPerformanceC
   };
 
   private static readonly v2SecondSegBrakeThresholds: Record<number, [number, number]> = {
-    1: [-0.009368, 186.79],
+    1: [-0.011031, 189.0],
     2: [0.02346, 68.33],
-    3: [0.022112, 83.141],
+    3: [0.014175, 106.14],
   };
 
   private static readonly v2SecondSegBrakeBaseTable1: Record<number, [number, number]> = {
     1: [0.72637, 101.077],
-    2: [0.74005, 97.073],
+    2: [0.74005, 97.048],
     3: [0.3746, 130.078],
   };
 
   private static readonly v2SecondSegBrakeBaseTable2: Record<number, [number, number]> = {
-    1: [0.63964, 102.127],
-    2: [0.692636, 92.9863],
+    1: [0.868263, 85.8],
+    2: [0.46666, 111.0],
     3: [0.859926, 82.4377],
   };
 
   private static readonly v2SecondSegBrakeRunwayTable1: Record<number, [number, number]> = {
     1: [3180, -0.015997],
-    2: [3180, -0.014862],
+    2: [3180, -0.012],
     3: [3180, -0.019296],
   };
 
   private static readonly v2SecondSegBrakeRunwayTable2: Record<number, [number, number]> = {
-    1: [3180, -0.003612],
+    1: [3180, -0.007],
     2: [3180, -0.007],
     3: [3180, -0.013],
   };

From 43f8291fcd6f5c6c103491353b60326f03de7bd6 Mon Sep 17 00:00:00 2001
From: bilo <44871554+bulenteroglu@users.noreply.github.com>
Date: Sat, 18 Jan 2025 00:37:49 +0000
Subject: [PATCH 4/4] fix(mfd): add leading zeros to track display and altitude
 on F-PLN page (#9724)

Co-authored-by: BravoMike99 <119708186+BravoMike99@users.noreply.github.com>
---
 .github/CHANGELOG.md                                      | 2 +-
 .../instruments/src/MFD/pages/FMS/F-PLN/MfdFmsFpln.tsx    | 8 ++++++--
 2 files changed, 7 insertions(+), 3 deletions(-)

diff --git a/.github/CHANGELOG.md b/.github/CHANGELOG.md
index a92b729492d..49a4b41a2cd 100644
--- a/.github/CHANGELOG.md
+++ b/.github/CHANGELOG.md
@@ -125,7 +125,7 @@
 1. [A380X/MFD] Add airport data page into the MFD (DATA > AIRPORT) - @bulenteroglu (senolitam)
 1. [A380X/EFB] Adds PRIM/SEC/FCDC failures to EFB - @flogross89 (floridude)
 1. [A380X/PFD] Fix precision of pitch trim indicator - @flogross89 (floridude)
-
+1. [A380X/MFD] Add leading zero to altitude prediction and track from last waypoint on FPLN page - @bulenteroglu (senolitam)
 
 ## 0.12.0
 
diff --git a/fbw-a380x/src/systems/instruments/src/MFD/pages/FMS/F-PLN/MfdFmsFpln.tsx b/fbw-a380x/src/systems/instruments/src/MFD/pages/FMS/F-PLN/MfdFmsFpln.tsx
index a08180e3e91..fb97bdbdb41 100644
--- a/fbw-a380x/src/systems/instruments/src/MFD/pages/FMS/F-PLN/MfdFmsFpln.tsx
+++ b/fbw-a380x/src/systems/instruments/src/MFD/pages/FMS/F-PLN/MfdFmsFpln.tsx
@@ -1304,7 +1304,7 @@ class FplnLegLine extends DisplayComponent<FplnLegLineProps> {
           this.fpaRef.instance.innerText = '';
         } else {
           this.trackRef.instance.innerText = data.trackFromLastWpt
-            ? `${data.trackFromLastWpt.toFixed(0)}°${this.props.trueTrack.get() ? 'T' : ''}`
+            ? `${data.trackFromLastWpt.toFixed(0).padStart(3, '0')}°${this.props.trueTrack.get() ? 'T' : ''}`
             : '';
           this.distRef.instance.innerText = data.distFromLastWpt?.toFixed(0) ?? '';
           this.fpaRef.instance.innerText = data.fpa ? data.fpa.toFixed(1) : '';
@@ -1445,7 +1445,11 @@ class FplnLegLine extends DisplayComponent<FplnLegLineProps> {
       ) {
         altStr = <span style="font-family: HoneywellMCDU, monospace;">"</span>;
       } else if (!isBelowTransAlt) {
-        altStr = <span>{`FL${Math.round(data.altitudePrediction / 100).toString()}`}</span>;
+        altStr = (
+          <span>{`FL${Math.round(data.altitudePrediction / 100)
+            .toString()
+            .padStart(3, '0')}`}</span>
+        );
       } else {
         const roundedAltitude = MathUtils.round(data.altitudePrediction, 10).toFixed(0);
         altStr = <span>{roundedAltitude}</span>;