@@ -378,6 +378,31 @@ class CDUPerformancePage {
378
378
const isSelected = Simplane . getAutoPilotAirspeedSelected ( ) ;
379
379
const actModeCell = isSelected ? "SELECTED" : "MANAGED" ;
380
380
const costIndexCell = isFinite ( mcdu . costIndex ) ? mcdu . costIndex . toFixed ( 0 ) + "[color]cyan" : "[][color]cyan" ;
381
+
382
+ // Predictions to altitude
383
+ const vnavDriver = mcdu . guidanceController . vnavDriver ;
384
+
385
+ const cruiseAltitude = mcdu . cruiseFlightLevel * 100 ;
386
+ const fcuAltitude = SimVar . GetSimVarValue ( "AUTOPILOT ALTITUDE LOCK VAR:3" , "feet" ) ;
387
+ const altitudeToPredict = Math . min ( cruiseAltitude , fcuAltitude ) ;
388
+
389
+ const predToCell = CDUPerformancePage . formatAltitudeOrLevel ( altitudeToPredict , mcdu . flightPlanManager . getOriginTransitionAltitude ( ) ) + "[color]cyan" ;
390
+
391
+ let predToDistanceCell = "---" ;
392
+ let predToTimeCell = "----" ;
393
+
394
+ let expeditePredToDistanceCell = "---" ;
395
+ let expeditePredToTimeCell = "----" ;
396
+
397
+ if ( vnavDriver ) {
398
+ [ predToDistanceCell , predToTimeCell ] = CDUPerformancePage . getTimeAndDistancePredictionsFromGeometryProfile ( vnavDriver . mcduProfile , altitudeToPredict , mcdu . flightPhaseManager . phase >= FmgcFlightPhases . TAKEOFF ) ;
399
+
400
+ if ( isPhaseActive ) {
401
+ const expediteProfile = vnavDriver . expediteProfile ;
402
+ [ expeditePredToDistanceCell , expeditePredToTimeCell ] = CDUPerformancePage . getTimeAndDistancePredictionsFromGeometryProfile ( expediteProfile , altitudeToPredict , mcdu . flightPhaseManager . phase >= FmgcFlightPhases . TAKEOFF , true ) ;
403
+ }
404
+ }
405
+
381
406
let managedSpeedCell = "" ;
382
407
if ( isPhaseActive ) {
383
408
if ( mcdu . managedSpeedTarget === mcdu . managedSpeedClimb ) {
@@ -388,7 +413,7 @@ class CDUPerformancePage {
388
413
managedSpeedCell = "{small}" + mcdu . managedSpeedTarget . toFixed ( 0 ) + "{end}" ;
389
414
}
390
415
} else {
391
- managedSpeedCell = ( isSelected ? "*" : "" ) + mcdu . managedSpeedClimb > mcdu . managedSpeedLimit ? mcdu . managedSpeedLimit . toFixed ( 0 ) : mcdu . managedSpeedClimb . toFixed ( 0 ) ;
416
+ managedSpeedCell = ( isSelected ? "*" : "" ) + mcdu . managedSpeedClimb > mcdu . climbSpeedLimit ? mcdu . climbSpeedLimit . toFixed ( 0 ) : mcdu . managedSpeedClimb . toFixed ( 0 ) ;
392
417
393
418
mcdu . onLeftInput [ 3 ] = ( value , scratchpadCallback ) => {
394
419
if ( mcdu . trySetPreSelectedClimbSpeed ( value ) ) {
@@ -441,16 +466,16 @@ class CDUPerformancePage {
441
466
} ;
442
467
mcdu . setTemplate ( [
443
468
[ "CLB[color]" + titleColor ] ,
444
- [ "ACT MODE" , "EFOB" , timeLabel ] ,
445
- [ actModeCell + "[color]green" , "6.0[color]green" , "----[color]green" ] ,
469
+ [ "ACT MODE" ] ,
470
+ [ actModeCell + "[color]green" ] ,
446
471
[ "\xa0CI" ] ,
447
- [ costIndexCell + "[color]cyan" ] ,
448
- [ "\xa0MANAGED" ] ,
449
- [ "\xa0" + managedSpeedCell + "[color]green" ] ,
472
+ [ costIndexCell + "[color]cyan" , predToCell , "\xa0\xa0\xa0{small}PRED TO{end}" ] ,
473
+ [ "\xa0MANAGED" , "DIST" , timeLabel ] ,
474
+ [ "\xa0" + managedSpeedCell + "[color]green" , ! isSelected ? predToDistanceCell : "" , ! isSelected ? predToTimeCell : "" ] ,
450
475
[ "\xa0" + selectedSpeedTitle ] ,
451
- [ "\xa0" + selectedSpeedCell + "[color]cyan" ] ,
452
- [ "" ] ,
476
+ [ "\xa0" + selectedSpeedCell , isSelected ? predToDistanceCell : "" , isSelected ? predToTimeCell : "" ] ,
453
477
[ "" ] ,
478
+ isPhaseActive ? [ "\xa0{small}EXPEDITE{end}[color]green" , expeditePredToDistanceCell , expeditePredToTimeCell ] : [ "" ] ,
454
479
bottomRowLabels ,
455
480
bottomRowCells
456
481
] ) ;
@@ -473,15 +498,19 @@ class CDUPerformancePage {
473
498
const isPhaseActive = mcdu . flightPhaseManager . phase === FmgcFlightPhases . CRUISE ;
474
499
const titleColor = isPhaseActive ? "green" : "white" ;
475
500
const isSelected = Simplane . getAutoPilotAirspeedSelected ( ) ;
476
- const isFlying = false ;
501
+ const isFlying = mcdu . flightPhaseManager . phase >= FmgcFlightPhases . TAKEOFF ;
477
502
const actModeCell = isSelected ? "SELECTED" : "MANAGED" ;
478
503
const costIndexCell = isFinite ( mcdu . costIndex ) ? mcdu . costIndex . toFixed ( 0 ) + "[color]cyan" : "[][color]cyan" ;
479
- let managedSpeedCell = "" ;
504
+ let managedSpeedCell = "---/--- " ;
480
505
const managedSpeed = isPhaseActive ? mcdu . managedSpeedTarget : mcdu . managedSpeedCruise ;
481
506
if ( isFinite ( managedSpeed ) ) {
482
- managedSpeedCell = ( isSelected ? "*" : "" ) + managedSpeed . toFixed ( 0 ) ;
507
+ managedSpeedCell = managedSpeed . toFixed ( 0 ) + "[color]green" ;
508
+ }
509
+ const preselTitle = isPhaseActive ? "" : "\xa0PRESEL" ;
510
+ let preselCell = "" ;
511
+ if ( ! isPhaseActive ) {
512
+ preselCell = ( isFinite ( mcdu . preSelectedCrzSpeed ) ? Math . round ( mcdu . preSelectedCrzSpeed ) . toFixed ( 0 ) : "\xa0*[ ]" ) + "[color]cyan" ;
483
513
}
484
- const [ selectedSpeedTitle , selectedSpeedCell ] = CDUPerformancePage . getSelectedTitleAndValue ( isPhaseActive , isSelected , mcdu . preSelectedCrzSpeed ) ;
485
514
mcdu . onLeftInput [ 1 ] = ( value , scratchpadCallback ) => {
486
515
if ( mcdu . tryUpdateCostIndex ( value ) ) {
487
516
CDUPerformancePage . ShowCRZPage ( mcdu ) ;
@@ -493,6 +522,13 @@ class CDUPerformancePage {
493
522
if ( isFlying ) {
494
523
timeLabel = "UTC" ;
495
524
}
525
+ const [ destEfobCell , destTimeCell ] = CDUPerformancePage . formatDestEfobAndTime ( mcdu , isFlying ) ;
526
+ const [ toUtcLabel , toDistLabel ] = isFlying ? [ "UTC" , "DIST" ] : [ "" , "" ] ;
527
+ const [ toReasonCell , toDistCell , toTimeCell ] = isFlying ? CDUPerformancePage . formatToReasonDistanceAndTime ( mcdu ) : [ "" , "" , "" ] ;
528
+ const desCabinRateCell = "{small}-350{end}" ;
529
+ const shouldShowStepAltsOption = mcdu . _cruiseEntered && mcdu . _cruiseFlightLevel
530
+ && ( mcdu . flightPhaseManager . phase < FmgcFlightPhases . DESCENT || mcdu . flightPhaseManager . phase > FmgcFlightPhases . GOAROUND ) ;
531
+
496
532
const bottomRowLabels = [ "\xa0PREV" , "NEXT\xa0" ] ;
497
533
const bottomRowCells = [ "<PHASE" , "PHASE>" ] ;
498
534
mcdu . leftInputDelay [ 5 ] = ( ) => {
@@ -526,6 +562,18 @@ class CDUPerformancePage {
526
562
CDUPerformancePage . ShowCLBPage ( mcdu ) ;
527
563
} ;
528
564
}
565
+ mcdu . onRightInput [ 3 ] = ( ) => {
566
+ // DES CABIN RATE
567
+ mcdu . setScratchpadMessage ( NXFictionalMessages . notYetImplemented ) ;
568
+ } ;
569
+ if ( shouldShowStepAltsOption ) {
570
+ CDUStepAltsPage . Return = ( ) => {
571
+ CDUPerformancePage . ShowCRZPage ( mcdu , false ) ;
572
+ } ;
573
+ mcdu . onRightInput [ 4 ] = ( ) => {
574
+ CDUStepAltsPage . ShowPage ( mcdu ) ;
575
+ } ;
576
+ }
529
577
mcdu . rightInputDelay [ 5 ] = ( ) => {
530
578
return mcdu . getDelaySwitchPage ( ) ;
531
579
} ;
@@ -534,16 +582,16 @@ class CDUPerformancePage {
534
582
} ;
535
583
mcdu . setTemplate ( [
536
584
[ "CRZ[color]" + titleColor ] ,
537
- [ "ACT MODE" , "EFOB" , timeLabel ] ,
538
- [ actModeCell + "[color]green" , "6.0[color]green" , "----[color]green" ] ,
585
+ [ "ACT MODE" , "DEST EFOB" , timeLabel ] ,
586
+ [ actModeCell + "[color]green" , destEfobCell , destTimeCell ] ,
539
587
[ "\xa0CI" ] ,
540
- [ costIndexCell + "[color]cyan" ] ,
541
- [ "\xa0MANAGED" ] ,
542
- [ "\xa0" + managedSpeedCell + "[color]green" ] ,
543
- [ "\xa0" + selectedSpeedTitle ] ,
544
- [ " \xa0" + selectedSpeedCell + "[color] cyan" ] ,
545
- [ "" , "DES CABIN RATE>" ] ,
546
- [ "" , "-350FT/MIN[color]green "] ,
588
+ [ costIndexCell + "[color]cyan" , toReasonCell ] ,
589
+ [ "\xa0MANAGED" , toDistLabel , toUtcLabel ] ,
590
+ [ "\xa0" + managedSpeedCell , toDistCell , toTimeCell ] ,
591
+ [ preselTitle , "DES CABIN RATE" ] ,
592
+ [ preselCell , ` \xa0{ cyan} ${ desCabinRateCell } {end}{white}{small}FT/MN{end}{end}` ] ,
593
+ [ "" ] ,
594
+ [ "" , shouldShowStepAltsOption ? "STEP ALTS>" : " "] ,
547
595
bottomRowLabels ,
548
596
bottomRowCells
549
597
] ) ;
@@ -565,7 +613,7 @@ class CDUPerformancePage {
565
613
} ;
566
614
const isPhaseActive = mcdu . flightPhaseManager . phase === FmgcFlightPhases . DESCENT ;
567
615
const titleColor = isPhaseActive ? "green" : "white" ;
568
- const isFlying = false ;
616
+ const isFlying = mcdu . flightPhaseManager . phase >= FmgcFlightPhases . TAKEOFF ;
569
617
const isSelected = Simplane . getAutoPilotAirspeedSelected ( ) ;
570
618
const actModeCell = isSelected ? "SELECTED" : "MANAGED" ;
571
619
const costIndexCell = isFinite ( mcdu . costIndex ) ? mcdu . costIndex . toFixed ( 0 ) + "[color]cyan" : "[][color]cyan" ;
@@ -579,6 +627,8 @@ class CDUPerformancePage {
579
627
if ( isFlying ) {
580
628
timeLabel = "UTC" ;
581
629
}
630
+ const [ destEfobCell , destTimeCell ] = CDUPerformancePage . formatDestEfobAndTime ( mcdu , isFlying ) ;
631
+
582
632
const bottomRowLabels = [ "\xa0PREV" , "NEXT\xa0" ] ;
583
633
const bottomRowCells = [ "<PHASE" , "PHASE>" ] ;
584
634
mcdu . leftInputDelay [ 5 ] = ( ) => {
@@ -627,14 +677,14 @@ class CDUPerformancePage {
627
677
} ;
628
678
mcdu . setTemplate ( [
629
679
[ "DES[color]" + titleColor ] ,
630
- [ "ACT MODE" , "EFOB" , timeLabel ] ,
631
- [ actModeCell + "[color]green" , "6.0[color]green" , "----[color]green" ] ,
680
+ [ "ACT MODE" , "DEST EFOB" , timeLabel ] ,
681
+ [ actModeCell + "[color]green" , destEfobCell , destTimeCell ] ,
632
682
[ "\xa0CI" ] ,
633
683
[ costIndexCell + "[color]cyan" ] ,
634
684
[ "\xa0MANAGED" ] ,
635
685
[ "\xa0" + managedSpeedCell + "[color]green" ] ,
636
686
[ "\xa0" + selectedSpeedTitle ] ,
637
- [ "\xa0" + selectedSpeedCell + "[color]cyan" ] ,
687
+ [ "\xa0" + selectedSpeedCell ] ,
638
688
[ "" ] ,
639
689
[ "" ] ,
640
690
bottomRowLabels ,
@@ -977,10 +1027,108 @@ class CDUPerformancePage {
977
1027
978
1028
static getSelectedTitleAndValue ( _isPhaseActive , _isSelected , _preSel ) {
979
1029
if ( _isPhaseActive ) {
980
- return _isSelected ? [ "SELECTED" , "" + Math . round ( Simplane . getAutoPilotMachModeActive ( ) ? SimVar . GetGameVarValue ( 'FROM MACH TO KIAS' , 'number' , Simplane . getAutoPilotMachHoldValue ( ) ) : Simplane . getAutoPilotAirspeedHoldValue ( ) ) ] : [ "" , "" ] ;
1030
+ return _isSelected
1031
+ ? [ "SELECTED" , "" + Math . round ( Simplane . getAutoPilotMachModeActive ( )
1032
+ ? SimVar . GetGameVarValue ( 'FROM MACH TO KIAS' , 'number' , Simplane . getAutoPilotMachHoldValue ( ) )
1033
+ : Simplane . getAutoPilotAirspeedHoldValue ( ) ) + "[color]green" ]
1034
+ : [ "" , "" ] ;
981
1035
} else {
982
- return [ "PRESEL" , isFinite ( _preSel ) ? "" + _preSel : "*[ ]" ] ;
1036
+ return [ "PRESEL" , ( isFinite ( _preSel ) ? "" + _preSel : "*[ ]" ) + "[color]cyan" ] ;
1037
+ }
1038
+ }
1039
+ static formatAltitudeOrLevel ( altitudeToFormat , transitionAltitude ) {
1040
+ if ( transitionAltitude >= 100 && altitudeToFormat > transitionAltitude ) {
1041
+ return `FL${ ( altitudeToFormat / 100 ) . toFixed ( 0 ) . toString ( ) . padStart ( 3 , "0" ) } ` ;
1042
+ }
1043
+
1044
+ return ( 10 * Math . round ( altitudeToFormat / 10 ) ) . toFixed ( 0 ) . toString ( ) . padStart ( 5 , "\xa0" ) ;
1045
+ }
1046
+ static getTimeAndDistancePredictionsFromGeometryProfile ( geometryProfile , altitudeToPredict , isFlying , printSmall = false ) {
1047
+ let predToDistanceCell = "---" ;
1048
+ let predToTimeCell = "----" ;
1049
+
1050
+ if ( ! geometryProfile || ! geometryProfile . isReadyToDisplay ) {
1051
+ return [ predToTimeCell , predToDistanceCell ] ;
983
1052
}
1053
+
1054
+ const predictions = geometryProfile . computePredictionToFcuAltitude ( altitudeToPredict ) ;
1055
+
1056
+ if ( predictions ) {
1057
+ if ( Number . isFinite ( predictions . distanceFromStart ) ) {
1058
+ if ( printSmall ) {
1059
+ predToDistanceCell = "{small}" + predictions . distanceFromStart . toFixed ( 0 ) + "{end}[color]green" ;
1060
+ } else {
1061
+ predToDistanceCell = predictions . distanceFromStart . toFixed ( 0 ) + "[color]green" ;
1062
+ }
1063
+ }
1064
+
1065
+ if ( Number . isFinite ( predictions . secondsFromPresent ) ) {
1066
+ const utcTime = SimVar . GetGlobalVarValue ( "ZULU TIME" , "seconds" ) ;
1067
+
1068
+ const predToTimeCellText = isFlying
1069
+ ? FMCMainDisplay . secondsToUTC ( utcTime + predictions . secondsFromPresent )
1070
+ : FMCMainDisplay . minutesTohhmm ( predictions . secondsFromPresent ) ;
1071
+
1072
+ if ( printSmall ) {
1073
+ predToTimeCell = "{small}" + predToTimeCellText + "{end}[color]green" ;
1074
+ } else {
1075
+ predToTimeCell = predToTimeCellText + "[color]green" ;
1076
+ }
1077
+ }
1078
+ }
1079
+
1080
+ return [ predToDistanceCell , predToTimeCell ] ;
1081
+ }
1082
+ static formatDestEfobAndTime ( mcdu , isFlying ) {
1083
+ const destinationPrediction = mcdu . guidanceController . vnavDriver . getDestinationPrediction ( ) ;
1084
+
1085
+ let destEfobCell = "---.-" ;
1086
+ let destTimeCell = "----" ;
1087
+
1088
+ if ( destinationPrediction ) {
1089
+ if ( Number . isFinite ( destinationPrediction . estimatedFuelOnBoard ) ) {
1090
+ destEfobCell = ( NXUnits . poundsToUser ( destinationPrediction . estimatedFuelOnBoard ) / 1000 ) . toFixed ( 1 ) + "[color]green" ;
1091
+ }
1092
+
1093
+ if ( Number . isFinite ( destinationPrediction . secondsFromPresent ) ) {
1094
+ const utcTime = SimVar . GetGlobalVarValue ( "ZULU TIME" , "seconds" ) ;
1095
+
1096
+ const predToTimeCellText = isFlying
1097
+ ? FMCMainDisplay . secondsToUTC ( utcTime + destinationPrediction . secondsFromPresent )
1098
+ : FMCMainDisplay . secondsTohhmm ( destinationPrediction . secondsFromPresent ) ;
1099
+
1100
+ destTimeCell = predToTimeCellText + "[color]green" ;
1101
+ }
1102
+ }
1103
+
1104
+ return [ destEfobCell , destTimeCell ] ;
1105
+ }
1106
+ static formatToReasonDistanceAndTime ( mcdu ) {
1107
+ const toPrediction = mcdu . guidanceController . vnavDriver . getPerfCrzToPrediction ( ) ;
1108
+
1109
+ let reasonCell = "(T/D)" ;
1110
+ let distCell = "---" ;
1111
+ let timeCell = "----" ;
1112
+
1113
+ if ( toPrediction ) {
1114
+ if ( Number . isFinite ( toPrediction . distanceFromPresentPosition ) ) {
1115
+ distCell = Math . round ( toPrediction . distanceFromPresentPosition ) + "[color]green" ;
1116
+ }
1117
+
1118
+ if ( Number . isFinite ( toPrediction . secondsFromPresent ) ) {
1119
+ const utcTime = SimVar . GetGlobalVarValue ( "ZULU TIME" , "seconds" ) ;
1120
+
1121
+ timeCell = FMCMainDisplay . secondsToUTC ( utcTime + toPrediction . secondsFromPresent ) + "\xa0[color]green" ;
1122
+ }
1123
+
1124
+ if ( toPrediction . reason === "StepClimb" ) {
1125
+ reasonCell = "(S/C)" ;
1126
+ } else if ( toPrediction . reason === "StepDescent" ) {
1127
+ reasonCell = "(S/D)" ;
1128
+ }
1129
+ }
1130
+
1131
+ return [ "{small}TO{end}\xa0{green}" + reasonCell + "{end}" , distCell , timeCell ] ;
984
1132
}
985
1133
}
986
1134
CDUPerformancePage . _timer = 0 ;
0 commit comments