From 63d41e8c46eb98f21a4f315479154279cabcbcc4 Mon Sep 17 00:00:00 2001 From: Florian Gross <63071941+flogross89@users.noreply.github.com> Date: Fri, 6 Dec 2024 02:43:32 +0200 Subject: [PATCH 01/40] remove debug output --- .../FlightWarningSystem/FwsAbnormalSensed.ts | 22 ------------------- 1 file changed, 22 deletions(-) diff --git a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsAbnormalSensed.ts b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsAbnormalSensed.ts index 9e3583db849..318f7186a30 100644 --- a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsAbnormalSensed.ts +++ b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsAbnormalSensed.ts @@ -88,28 +88,6 @@ export class FwsAbnormalSensed { }), ); this.pub.pub('fws_abn_sensed_procedures', flattened, true); - SimVar.SetSimVarValue('L:A32NX_EWD_DEBUG_ABNORMAL', 'string', flattened[0] ? flattened[0].id : ''); - - console.log('%c------- ABN SENSED PROCEDURES -------', 'font-family:monospace; font-weight: bold'); - // Debug output for ABN sensed procedures - this.fws.activeAbnormalSensedList.get().forEach((val, key) => { - const proc = EcamAbnormalSensedProcedures[key] as AbnormalProcedure; - console.log('%c' + proc.title, 'font-family:monospace; font-weight: bold'); - proc.items.forEach((it, itemIdx) => { - if (val.itemsToShow[itemIdx]) { - const cpl = isChecklistAction(it) - ? val.itemsChecked[itemIdx] - ? it.labelNotCompleted - : ` .......... ${it.labelNotCompleted}` - : ''; - console.log( - `%c${' '.repeat(it.level ?? 0)} ${val.itemsChecked[itemIdx] ? 'X' : 'O'} ${it.name} ${cpl} ${it.style ? `(${it.style})` : ''}`, - 'font-family:monospace; font-weight: bold', - ); - } - }); - }); - console.log('%c------- END -------', 'font-family:monospace; font-weight: bold'); }, true, ); From d0f4a9941e2ccf096c299589d788fcaed430528e Mon Sep 17 00:00:00 2001 From: Florian Gross <63071941+flogross89@users.noreply.github.com> Date: Fri, 6 Dec 2024 06:52:40 +0200 Subject: [PATCH 02/40] FAILURE PENDING, make sensed lines selectable --- .../src/systems/instruments/src/EWD/EWD.tsx | 84 ++++++++++--------- .../elements/WdAbnormalSensedProcedures.tsx | 74 +++++++++------- .../elements/WdAbstractChecklistComponent.tsx | 5 +- .../src/EWD/shared/EwdSimvarPublisher.tsx | 2 - .../systems/instruments/src/EWD/style.scss | 24 ++++++ .../MsfsAvionicsCommon/EcamMessages/index.tsx | 1 + .../providers/FwsEwdPublisher.ts | 5 ++ .../FlightWarningSystem/FwsAbnormalSensed.ts | 26 +++--- .../systems/FlightWarningSystem/FwsCore.ts | 47 ++++++++++- .../FwsNormalChecklists.ts | 55 ++++++------ 10 files changed, 211 insertions(+), 112 deletions(-) diff --git a/fbw-a380x/src/systems/instruments/src/EWD/EWD.tsx b/fbw-a380x/src/systems/instruments/src/EWD/EWD.tsx index 3af8d94bbef..fbd924265f3 100644 --- a/fbw-a380x/src/systems/instruments/src/EWD/EWD.tsx +++ b/fbw-a380x/src/systems/instruments/src/EWD/EWD.tsx @@ -22,21 +22,23 @@ import { FwsEwdEvents } from 'instruments/src/MsfsAvionicsCommon/providers/FwsEw import { WdAbnormalSensedProcedures } from 'instruments/src/EWD/elements/WdAbnormalSensedProcedures'; export class EngineWarningDisplay extends DisplayComponent<{ bus: ArincEventBus }> { + private readonly sub = this.props.bus.getSubscriber(); + private readonly engineStateSubs: ConsumerSubject[] = [ - ConsumerSubject.create(null, 0), - ConsumerSubject.create(null, 0), - ConsumerSubject.create(null, 0), - ConsumerSubject.create(null, 0), + ConsumerSubject.create(this.sub.on('engine_state_1'), 0), + ConsumerSubject.create(this.sub.on('engine_state_2'), 0), + ConsumerSubject.create(this.sub.on('engine_state_3'), 0), + ConsumerSubject.create(this.sub.on('engine_state_4'), 0), ]; private readonly reverserSubs: ConsumerSubject[] = [ - ConsumerSubject.create(null, false), - ConsumerSubject.create(null, false), + ConsumerSubject.create(this.sub.on('thrust_reverse_2'), false), + ConsumerSubject.create(this.sub.on('thrust_reverse_3'), false), ]; private readonly reverserSelected = MappedSubject.create(SubscribableMapFunctions.or(), ...this.reverserSubs); - private readonly engSelectorPosition = ConsumerSubject.create(null, 0); + private readonly engSelectorPosition = ConsumerSubject.create(this.sub.on('eng_selector_position'), 0); private readonly engineRunningOrIgnitionOn = MappedSubject.create( ([eng1, eng2, eng3, eng4, engSelectorPosition]) => { @@ -55,50 +57,39 @@ export class EngineWarningDisplay extends DisplayComponent<{ bus: ArincEventBus Subject.create(false), ]; - private readonly normalChecklistsVisible = ConsumerSubject.create(null, false); + private readonly normalChecklistsRequested = ConsumerSubject.create(this.sub.on('fws_show_normal_checklists'), false); + + private readonly abnormalSensedRequested = ConsumerSubject.create(this.sub.on('fws_show_abn_sensed'), false); - private readonly abnormalSensedVisible = ConsumerSubject.create(null, false); + private readonly abnormalSensedVisible = MappedSubject.create( + ([ecl, abn]) => abn && !ecl, + this.normalChecklistsRequested, + this.abnormalSensedRequested, + ); // Todo: This logic should be handled by the FADEC private readonly engFirePb: ConsumerSubject[] = [ - ConsumerSubject.create(null, false), - ConsumerSubject.create(null, false), - ConsumerSubject.create(null, false), - ConsumerSubject.create(null, false), + ConsumerSubject.create(this.sub.on('engine_fire_pb_1'), false), + ConsumerSubject.create(this.sub.on('engine_fire_pb_2'), false), + ConsumerSubject.create(this.sub.on('engine_fire_pb_3'), false), + ConsumerSubject.create(this.sub.on('engine_fire_pb_4'), false), ]; private readonly memosLimitationVisible = MappedSubject.create( SubscribableMapFunctions.nor(), - this.normalChecklistsVisible, - this.abnormalSensedVisible, + this.normalChecklistsRequested, + this.abnormalSensedRequested, ); - private readonly abnormalDebugLine = ConsumerSubject.create(null, 0); + private readonly failurePendingIndicationRequested = ConsumerSubject.create( + this.sub.on('fws_show_failure_pending'), + false, + ); + + private readonly stsIndicationRequested = ConsumerSubject.create(this.sub.on('fws_show_sts_indication'), false); public onAfterRender(node: VNode): void { super.onAfterRender(node); - - const sub = this.props.bus.getSubscriber(); - - this.engineStateSubs[0].setConsumer(sub.on('engine_state_1').whenChanged()); - this.engineStateSubs[1].setConsumer(sub.on('engine_state_2').whenChanged()); - this.engineStateSubs[2].setConsumer(sub.on('engine_state_3').whenChanged()); - this.engineStateSubs[3].setConsumer(sub.on('engine_state_4').whenChanged()); - - this.engFirePb[0].setConsumer(sub.on('engine_fire_pb_1')); - this.engFirePb[1].setConsumer(sub.on('engine_fire_pb_2')); - this.engFirePb[2].setConsumer(sub.on('engine_fire_pb_3')); - this.engFirePb[3].setConsumer(sub.on('engine_fire_pb_4')); - - this.reverserSubs[0].setConsumer(sub.on('thrust_reverse_2').whenChanged()); - this.reverserSubs[1].setConsumer(sub.on('thrust_reverse_3').whenChanged()); - - this.engSelectorPosition.setConsumer(sub.on('eng_selector_position').whenChanged()); - - this.normalChecklistsVisible.setConsumer(sub.on('fws_show_normal_checklists').whenChanged()); - this.abnormalSensedVisible.setConsumer(sub.on('fws_show_abn_sensed').whenChanged()); - - this.abnormalDebugLine.setConsumer(sub.on('abnormal_debug_line').whenChanged()); } render(): VNode { @@ -246,9 +237,22 @@ export class EngineWarningDisplay extends DisplayComponent<{ bus: ArincEventBus
- + -
+
+
(s ? 'visible' : 'hidden')) }} + > + FAILURE PENDING +
+
(s ? 'visible' : 'hidden')) }} + > + STS +
+
{/* Reserved for STS */}
diff --git a/fbw-a380x/src/systems/instruments/src/EWD/elements/WdAbnormalSensedProcedures.tsx b/fbw-a380x/src/systems/instruments/src/EWD/elements/WdAbnormalSensedProcedures.tsx index 8c9beff2a45..e5d106c6c1a 100644 --- a/fbw-a380x/src/systems/instruments/src/EWD/elements/WdAbnormalSensedProcedures.tsx +++ b/fbw-a380x/src/systems/instruments/src/EWD/elements/WdAbnormalSensedProcedures.tsx @@ -28,41 +28,43 @@ export class WdAbnormalSensedProcedures extends WdAbstractChecklistComponent { lastLine: procIndex !== 0 ? true : false, }); - cl.items.forEach((item, itemIndex) => { - if (procState.itemsToShow[itemIndex] === false) { - return; - } + if (procIndex === 0) { + // If first and most important procedure: Display in full + cl.items.forEach((item, itemIndex) => { + if (procState.itemsToShow[itemIndex] === false) { + return; + } - let text = item.level ? '\xa0'.repeat(item.level * 2) : ''; - if (isChecklistAction(item)) { - text += item.style !== ChecklistLineStyle.SubHeadline ? '-' : ''; - text += item.name; - if (procState.itemsChecked[itemIndex] && item.labelCompleted) { - text += `${item.colonIfCompleted === false ? ' ' : ' : '}${item.labelCompleted}`; - } else if (procState.itemsChecked[itemIndex] && item.labelNotCompleted) { - text += `${item.colonIfCompleted === false ? ' ' : ' : '}${item.labelNotCompleted}`; - } else if (!procState.itemsChecked[itemIndex] && item.labelNotCompleted) { - // Pad to 39 characters max - const paddingNeeded = 39 - (item.labelNotCompleted.length + item.name.length + (item.level ?? 0) * 2 + 2); - text += ` ${'.'.repeat(paddingNeeded)}${item.labelNotCompleted}`; + let text = item.level ? '\xa0'.repeat(item.level * 2) : ''; + if (isChecklistAction(item)) { + text += item.style !== ChecklistLineStyle.SubHeadline ? '-' : ''; + text += item.name; + if (procState.itemsChecked[itemIndex] && item.labelCompleted) { + text += `${item.colonIfCompleted === false ? ' ' : ' : '}${item.labelCompleted}`; + } else if (procState.itemsChecked[itemIndex] && item.labelNotCompleted) { + text += `${item.colonIfCompleted === false ? ' ' : ' : '}${item.labelNotCompleted}`; + } else if (!procState.itemsChecked[itemIndex] && item.labelNotCompleted) { + // Pad to 39 characters max + const paddingNeeded = + 39 - (item.labelNotCompleted.length + item.name.length + (item.level ?? 0) * 2 + 2); + text += ` ${'.'.repeat(paddingNeeded)}${item.labelNotCompleted}`; + } + } else { + text += `${item.name.substring(0, 2) === 'IF' ? '.' : ''}${item.name}`; } - } else { - text += `${item.name.substring(0, 3) === 'IF' ? '.' : ''}${item.name}`; - } - this.lineData.push({ - abnormalProcedure: true, - activeProcedure: procIndex === 0, - sensed: item.sensed, - checked: procState.itemsChecked[itemIndex], - text: text, - style: item.style ? item.style : ChecklistLineStyle.ChecklistItem, - firstLine: procIndex !== 0 ? true : false, - lastLine: procIndex !== 0 ? true : false, + this.lineData.push({ + abnormalProcedure: true, + activeProcedure: procIndex === 0, + sensed: item.sensed, + checked: procState.itemsChecked[itemIndex], + text: text, + style: item.style ? item.style : ChecklistLineStyle.ChecklistItem, + firstLine: procIndex !== 0 ? true : false, + lastLine: procIndex !== 0 ? true : false, + }); }); - }); - if (procIndex === 0) { this.lineData.push({ abnormalProcedure: true, activeProcedure: true, @@ -73,6 +75,18 @@ export class WdAbnormalSensedProcedures extends WdAbstractChecklistComponent { firstLine: false, lastLine: true, }); + } else { + // Only three dots for following procedures + this.lineData.push({ + abnormalProcedure: true, + activeProcedure: false, + sensed: true, + checked: false, + text: '...', + style: ChecklistLineStyle.OmissionDots, + firstLine: true, + lastLine: true, + }); } // Empty line after procedure diff --git a/fbw-a380x/src/systems/instruments/src/EWD/elements/WdAbstractChecklistComponent.tsx b/fbw-a380x/src/systems/instruments/src/EWD/elements/WdAbstractChecklistComponent.tsx index 0cfb90d0a16..bd110011a8c 100644 --- a/fbw-a380x/src/systems/instruments/src/EWD/elements/WdAbstractChecklistComponent.tsx +++ b/fbw-a380x/src/systems/instruments/src/EWD/elements/WdAbstractChecklistComponent.tsx @@ -151,6 +151,7 @@ export class EclLine extends DisplayComponent { Green: this.props.data.map((d) => d.style === ChecklistLineStyle.Green), Cyan: this.props.data.map((d) => d.style === ChecklistLineStyle.Cyan), Amber: this.props.data.map((d) => d.style === ChecklistLineStyle.Amber), + OmissionDots: this.props.data.map((d) => d.style === ChecklistLineStyle.OmissionDots), }} style={{ display: this.props.data.map((d) => (d.style === ChecklistLineStyle.SeparationLine ? 'none' : 'flex')), @@ -163,7 +164,9 @@ export class EclLine extends DisplayComponent { (d) => d.abnormalProcedure === true && d.style === ChecklistLineStyle.ChecklistItem, ), Checked: this.props.data.map((d) => d.checked), - HiddenElement: this.props.data.map((d) => d.style === ChecklistLineStyle.Headline), + HiddenElement: this.props.data.map( + (d) => d.style === ChecklistLineStyle.Headline || d.style === ChecklistLineStyle.OmissionDots, + ), Invisible: this.props.data.map( (d) => d.sensed || (d.firstLine && d.lastLine) || d.specialLine === WdSpecialLine.Empty, ), diff --git a/fbw-a380x/src/systems/instruments/src/EWD/shared/EwdSimvarPublisher.tsx b/fbw-a380x/src/systems/instruments/src/EWD/shared/EwdSimvarPublisher.tsx index c80db85687c..9c42cbe26d9 100644 --- a/fbw-a380x/src/systems/instruments/src/EWD/shared/EwdSimvarPublisher.tsx +++ b/fbw-a380x/src/systems/instruments/src/EWD/shared/EwdSimvarPublisher.tsx @@ -40,7 +40,6 @@ export interface BaseEwdSimvars { limitations_all: number; memo_left: number; memo_right: number; - abnormal_debug_line: number; nose_gear_compressed: boolean; engine_fire_pb: boolean; cas: number; @@ -119,7 +118,6 @@ export class EwdSimvarPublisher extends SimVarPublisher { ], ['memo_left', { name: 'L:A32NX_EWD_LOWER_LEFT_LINE_#index#', type: SimVarValueType.Number, indexed: true }], ['memo_right', { name: 'L:A32NX_EWD_LOWER_RIGHT_LINE_#index#', type: SimVarValueType.Number, indexed: true }], - ['abnormal_debug_line', { name: 'L:A32NX_EWD_DEBUG_ABNORMAL', type: SimVarValueType.Number }], [ 'nose_gear_compressed', { name: 'L:A32NX_LGCIU_#index#_NOSE_GEAR_COMPRESSED', type: SimVarValueType.Bool, indexed: true }, diff --git a/fbw-a380x/src/systems/instruments/src/EWD/style.scss b/fbw-a380x/src/systems/instruments/src/EWD/style.scss index 42673d54304..648b93d4470 100644 --- a/fbw-a380x/src/systems/instruments/src/EWD/style.scss +++ b/fbw-a380x/src/systems/instruments/src/EWD/style.scss @@ -290,6 +290,26 @@ text, tspan, span { height: 40px; } +.FailurePendingBox { + display: inline; + position: relative; + left: 40px; + top: 0px; + border: 2px outset $display-white; + font-size: 24px; + padding: 2px; +} + +.StsBox { + display: inline; + position: relative; + left: 150px; + top: 0px; + border: 2px outset $display-white; + font-size: 24px; + padding: 2px; +} + .MemosContainer { display: flex; flex-direction: column; @@ -415,6 +435,10 @@ text, tspan, span { text-decoration: underline; } +.EclLine.OmissionDots { + color: $display-cyan !important; +} + .EclLineCheckboxArea { text-align: center; justify-content: center; diff --git a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/index.tsx b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/index.tsx index 434b85ff327..acfa14defd3 100644 --- a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/index.tsx +++ b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/index.tsx @@ -564,6 +564,7 @@ export enum ChecklistLineStyle { SeparationLine = 'SeparationLine', ChecklistItem = 'ChecklistItem', CompletedChecklist = 'CompletedChecklist', + OmissionDots = 'OmissionDots', } interface AbstractChecklistItem { diff --git a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/providers/FwsEwdPublisher.ts b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/providers/FwsEwdPublisher.ts index eb36ae9b268..e795818544a 100644 --- a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/providers/FwsEwdPublisher.ts +++ b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/providers/FwsEwdPublisher.ts @@ -31,4 +31,9 @@ export interface FwsEwdEvents { fws_show_abn_sensed: boolean; /** (FWS -> EWD) List of abnormal sensed procedures to be displayed */ fws_abn_sensed_procedures: FwsEwdAbnormalSensedEntry[]; + + /** (FWS -> EWD) Show FAILURE PENDING indication at bottom of page */ + fws_show_failure_pending: boolean; + /** (FWS -> EWD) Show STS indication at bottom of page */ + fws_show_sts_indication: boolean; } diff --git a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsAbnormalSensed.ts b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsAbnormalSensed.ts index 318f7186a30..b54aa98fdec 100644 --- a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsAbnormalSensed.ts +++ b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsAbnormalSensed.ts @@ -2,11 +2,7 @@ // // SPDX-License-Identifier: GPL-3.0 -import { - AbnormalProcedure, - EcamAbnormalSensedProcedures, - isChecklistAction, -} from '../../../instruments/src/MsfsAvionicsCommon/EcamMessages'; +import { EcamAbnormalSensedProcedures } from '../../../instruments/src/MsfsAvionicsCommon/EcamMessages'; import { MappedSubject, Subject, @@ -61,7 +57,9 @@ export interface EwdAbnormalDict { export class FwsAbnormalSensed { private readonly pub = this.fws.bus.getPublisher(); - public readonly showAbnormalSensed = Subject.create(false); + public readonly abnormalShown = Subject.create(false); + + public readonly showAbnormalSensedRequested = Subject.create(false); /** Marked with cyan box */ public readonly selectedLine = Subject.create(1); @@ -70,7 +68,6 @@ export class FwsAbnormalSensed { public readonly showFromLine = Subject.create(0); constructor(private fws: FwsCore) { - this.showAbnormalSensed.sub((v) => this.pub.pub('fws_show_abn_sensed', v, true), true); this.fws.activeAbnormalSensedList.sub( ( map: ReadonlyMap, @@ -87,12 +84,14 @@ export class FwsAbnormalSensed { itemsToShow: val.itemsToShow, }), ); - this.pub.pub('fws_abn_sensed_procedures', flattened, true); + // Sort by decreasing importance + const sortedAbnormalsFlattened = flattened.sort( + (a, b) => this.ewdAbnormalSensed[b.id].failure - this.ewdAbnormalSensed[a.id].failure, + ); + this.pub.pub('fws_abn_sensed_procedures', sortedAbnormalsFlattened, true); }, true, ); - this.selectedLine.sub((line) => this.pub.pub('fws_active_line', line, true), true); - this.showFromLine.sub((line) => this.pub.pub('fws_show_from_line', line, true), true); } getAbnormalProceduresKeysSorted() { @@ -207,8 +206,7 @@ export class FwsAbnormalSensed { */ update() { if (this.fws.activeAbnormalSensedList.get().size > 0) { - this.showAbnormalSensed.set(true); - this.fws.normalChecklists.showChecklist.set(false); + this.showAbnormalSensedRequested.set(true); // Update selected line: CLEAR of first procedure const firstKey = this.fws.activeAbnormalSensedList.get().keys().next().value; @@ -217,7 +215,7 @@ export class FwsAbnormalSensed { .itemsToShow.filter((v) => v === true).length; this.selectedLine.set(numItems + 1); } else { - this.showAbnormalSensed.set(false); + this.showAbnormalSensedRequested.set(false); } /*if (this.fws.clDownPulseNode.read()) { @@ -235,7 +233,7 @@ export class FwsAbnormalSensed { }*/ if (this.fws.clCheckPulseNode.read()) { - if (!this.showAbnormalSensed.get()) { + if (!this.abnormalShown.get()) { return; } diff --git a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsCore.ts b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsCore.ts index 276c4089590..20a0dc8a783 100644 --- a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsCore.ts +++ b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsCore.ts @@ -42,7 +42,10 @@ import { pfdMemoDisplay, } from '../../../instruments/src/MsfsAvionicsCommon/EcamMessages'; import PitchTrimUtils from '@shared/PitchTrimUtils'; -import { FwsEwdAbnormalSensedEntry } from '../../../instruments/src/MsfsAvionicsCommon/providers/FwsEwdPublisher'; +import { + FwsEwdAbnormalSensedEntry, + FwsEwdEvents, +} from '../../../instruments/src/MsfsAvionicsCommon/providers/FwsEwdPublisher'; import { FwsMemos } from 'systems-host/systems/FlightWarningSystem/FwsMemos'; import { FwsNormalChecklists } from 'systems-host/systems/FlightWarningSystem/FwsNormalChecklists'; import { EwdAbnormalItem, FwsAbnormalSensed } from 'systems-host/systems/FlightWarningSystem/FwsAbnormalSensed'; @@ -283,6 +286,10 @@ export class FwsCore { public readonly ecamStsNormal = Subject.create(true); + public readonly ecamEwdShowStsIndication = Subject.create(false); + + public readonly ecamEwdShowFailurePendingIndication = Subject.create(false); + public readonly fwcOut126 = Arinc429RegisterSubject.createEmpty(); /* MISC STUFF */ @@ -1538,6 +1545,14 @@ export class FwsCore { this.statusNormal.sub((s) => SimVar.SetSimVarValue('L:A32NX_STATUS_NORMAL', 'boolean', s)); + this.ecamEwdShowStsIndication.sub((s) => + this.bus.getPublisher().pub('fws_show_sts_indication', s, true), + ); + + this.ecamEwdShowFailurePendingIndication.sub((s) => + this.bus.getPublisher().pub('fws_show_failure_pending', s, true), + ); + SimVar.SetSimVarValue('L:A32NX_STATUS_LEFT_LINE_8', 'string', '000000001'); const ecamMemoKeys = Object.keys(EcamMemos); @@ -4082,6 +4097,8 @@ export class FwsCore { !ewdLimitationsAllPhasesKeys.length && !ewdLimitationsApprLdgKeys.length, ); + const sdStsShown = SimVar.GetSimVarValue('L:A32NX_ECAM_SD_CURRENT_PAGE_INDEX', SimVarValueType.Number) === 14; + this.ecamEwdShowStsIndication.set(!this.ecamStsNormal.get() && !sdStsShown); // This does not consider interrupting c-chord, priority of synthetic voice etc. const chimeRequested = this.auralSingleChimePending || this.requestSingleChimeFromAThrOff; @@ -4109,6 +4126,34 @@ export class FwsCore { this.abnormalSensed.update(); this.updateRowRopWarnings(); + // Orchestrate display of normal or abnormal proc display + const pub = this.bus.getPublisher(); + if (this.normalChecklists.showChecklistRequested.get()) { + // ECL always shown + this.normalChecklists.checklistShown.set(true); + this.abnormalSensed.abnormalShown.set(false); + + pub.pub('fws_active_line', this.normalChecklists.selectedLine.get() + 1, true); + pub.pub('fws_show_from_line', this.normalChecklists.showFromLine.get(), true); + this.ecamEwdShowFailurePendingIndication.set(this.abnormalSensed.showAbnormalSensedRequested.get()); + } else if ( + this.abnormalSensed.showAbnormalSensedRequested.get() && + !this.normalChecklists.showChecklistRequested.get() + ) { + this.normalChecklists.checklistShown.set(false); + this.abnormalSensed.abnormalShown.set(true); + + pub.pub('fws_active_line', this.abnormalSensed.selectedLine.get(), true); + pub.pub('fws_show_from_line', this.abnormalSensed.showFromLine.get(), true); + this.ecamEwdShowFailurePendingIndication.set(false); + } else { + this.normalChecklists.checklistShown.set(false); + this.abnormalSensed.abnormalShown.set(false); + this.ecamEwdShowFailurePendingIndication.set(false); + } + pub.pub('fws_show_abn_sensed', this.abnormalSensed.abnormalShown.get(), true); + pub.pub('fws_show_normal_checklists', this.normalChecklists.checklistShown.get(), true); + // Reset all buffered inputs this.toConfigInputBuffer.write(false, true); this.clearButtonInputBuffer.write(false, true); diff --git a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsNormalChecklists.ts b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsNormalChecklists.ts index d38c4274c12..40607d6f735 100644 --- a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsNormalChecklists.ts +++ b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsNormalChecklists.ts @@ -24,7 +24,9 @@ export interface FwsNormalChecklistsDict { export class FwsNormalChecklists { private readonly pub = this.fws.bus.getPublisher(); - public readonly showChecklist = Subject.create(false); + public readonly checklistShown = Subject.create(false); + + public readonly showChecklistRequested = Subject.create(false); /** ID of checklist or 0 for overview */ public readonly checklistId = Subject.create(0); @@ -38,7 +40,6 @@ export class FwsNormalChecklists { public readonly checklistState = MapSubject.create(); constructor(private fws: FwsCore) { - this.showChecklist.sub((v) => this.pub.pub('fws_show_normal_checklists', v, true), true); this.checklistState.sub( ( map: ReadonlyMap, @@ -55,8 +56,6 @@ export class FwsNormalChecklists { true, ); this.checklistId.sub((id) => this.pub.pub('fws_normal_checklists_id', id, true), true); - this.selectedLine.sub((line) => this.pub.pub('fws_active_line', line + 1, true), true); // Start at second line, headline not selectable - this.showFromLine.sub((line) => this.pub.pub('fws_show_from_line', line, true), true); // Populate checklistState const keys = this.getNormalProceduresKeysSorted(); @@ -97,13 +96,13 @@ export class FwsNormalChecklists { } else { const clState = this.checklistState.getValue(this.checklistId.get()); const selectableAndNotChecked = EcamNormalProcedures[this.checklistId.get()].items - .map((item, index) => (item.sensed === false && clState.itemsCompleted[index] === false ? index : null)) + .map((_, index) => (clState.itemsCompleted[index] === false ? index : null)) .filter((v) => v !== null); this.selectedLine.set( selectableAndNotChecked[0] !== undefined ? selectableAndNotChecked[0] - 1 : clState.itemsCompleted.length - 1, ); } - this.moveDown(); + this.moveDown(true); } moveUp() { @@ -111,9 +110,7 @@ export class FwsNormalChecklists { this.selectedLine.set(Math.max(this.selectedLine.get() - 1, 0)); } else { const numItems = EcamNormalProcedures[this.checklistId.get()].items.length; - const selectable = EcamNormalProcedures[this.checklistId.get()].items - .map((item, index) => (item.sensed === false ? index : null)) - .filter((v) => v !== null); + const selectable = EcamNormalProcedures[this.checklistId.get()].items.map((_, index) => index); if (this.selectedLine.get() == numItems + 1) { // RESET @@ -140,13 +137,14 @@ export class FwsNormalChecklists { this.showFromLine.set(Math.max(0, this.selectedLine.get() - WD_NUM_LINES + 2)); } - moveDown() { + moveDown(skipCompleted = false) { if (this.checklistId.get() === 0) { this.selectedLine.set(Math.min(this.selectedLine.get() + 1, this.getNormalProceduresKeysSorted().length - 1)); } else { + const clState = this.checklistState.getValue(this.checklistId.get()); const numItems = EcamNormalProcedures[this.checklistId.get()].items.length; const selectable = EcamNormalProcedures[this.checklistId.get()].items - .map((item, index) => (item.sensed === false ? index : null)) + .map((_, index) => (!skipCompleted || clState.itemsCompleted[index] === false ? index : null)) .filter((v) => v !== null); if (this.selectedLine.get() >= selectable[selectable.length - 1] || selectable.length == 0) { // Last element before C/L complete @@ -170,21 +168,25 @@ export class FwsNormalChecklists { checklistCompleted: cl.checklistCompleted, itemsCompleted: [...cl.itemsCompleted], }; - if (this.selectedLine.get() < clState.itemsCompleted.length) { + const proc = EcamNormalProcedures[this.checklistId.get()]; + if ( + this.selectedLine.get() < clState.itemsCompleted.length && + proc.items[this.selectedLine.get()]?.sensed === false + ) { clState.itemsCompleted[this.selectedLine.get()] = !clState.itemsCompleted[this.selectedLine.get()]; this.checklistState.setValue(this.checklistId.get(), clState); - this.moveDown(); + if (clState.itemsCompleted[this.selectedLine.get()]) { + this.moveDown(true); + } } else if (this.selectedLine.get() === clState.itemsCompleted.length) { // C/L complete clState.checklistCompleted = true; - const proc = EcamNormalProcedures[this.checklistId.get()]; clState.itemsCompleted = clState.itemsCompleted.map((val, index) => (proc.items[index].sensed ? val : true)); this.checklistState.setValue(this.checklistId.get(), clState); - this.showChecklist.set(false); + this.showChecklistRequested.set(false); } else if (this.selectedLine.get() === clState.itemsCompleted.length + 1) { // RESET clState.checklistCompleted = false; - const proc = EcamNormalProcedures[this.checklistId.get()]; clState.itemsCompleted = clState.itemsCompleted.map((val, index) => (proc.items[index].sensed ? val : false)); // Reset all following checklists @@ -218,28 +220,26 @@ export class FwsNormalChecklists { update() { if (this.fws.clPulseNode.read()) { - if (!this.fws.abnormalSensed.showAbnormalSensed.get()) { - this.navigateToChecklist(0); - this.showChecklist.set(!this.showChecklist.get()); - } + this.navigateToChecklist(0); + this.showChecklistRequested.set(!this.showChecklistRequested.get()); } if (this.fws.clDownPulseNode.read()) { - if (!this.showChecklist.get()) { + if (!this.checklistShown.get()) { return; } this.moveDown(); } if (this.fws.clUpPulseNode.read()) { - if (!this.showChecklist.get()) { + if (!this.checklistShown.get()) { return; } this.moveUp(); } if (this.fws.clCheckPulseNode.read()) { - if (!this.showChecklist.get()) { + if (!this.checklistShown.get()) { return; } @@ -264,8 +264,15 @@ export class FwsNormalChecklists { continue; } const sensedResult = this.sensedItems[procId].whichItemsChecked(); - if (sensedResult.some((val, index) => val !== null && val !== cl.itemsCompleted[index])) { + const changedEntries = sensedResult.map((val, index) => + val !== null && val !== cl.itemsCompleted[index] ? index : null, + ); + if (changedEntries.some((v) => v !== null)) { changed = true; + + if (changedEntries.includes(this.selectedLine.get()) && sensedResult[this.selectedLine.get()]) { + this.moveDown(); + } } const clState: ChecklistState = { id: procId, From 64c62ebd66a043564bcd1f335e0a5291b6fb2fb7 Mon Sep 17 00:00:00 2001 From: Florian Gross <63071941+flogross89@users.noreply.github.com> Date: Fri, 6 Dec 2024 19:46:19 +0200 Subject: [PATCH 03/40] update ECL rudder trim item --- .../systems-host/systems/FlightWarningSystem/FwsCore.ts | 4 ++++ .../systems/FlightWarningSystem/FwsNormalChecklists.ts | 7 +------ 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsCore.ts b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsCore.ts index 20a0dc8a783..85cf37fb4c6 100644 --- a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsCore.ts +++ b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsCore.ts @@ -809,6 +809,8 @@ export class FwsCore { public readonly rudderTrimNotToWarning = Subject.create(false); + public readonly rudderTrimPosition = Subject.create(0); + public readonly flapsLeverNotZeroWarning = Subject.create(false); public readonly speedBrakeCommand5sConfirm = new NXLogicConfirmNode(5, true); @@ -3351,6 +3353,8 @@ export class FwsCore { (sec1Healthy && Math.abs(sec1RudderTrimActualPos.valueOr(0)) > 3.6) || (sec3Healthy && Math.abs(sec3RudderTrimActualPos.valueOr(0)) > 3.6); + this.rudderTrimPosition.set(sec1Healthy ? sec1RudderTrimActualPos.valueOr(0) : sec3RudderTrimActualPos.valueOr(0)); + this.rudderTrimNotTo.set(this.flightPhase1211.get() && rudderTrimConfig); const rudderTrimConfigTestInPhase129 = this.toConfigTestHeldMin1s5Pulse.get() && this.flightPhase1211.get() && rudderTrimConfig; diff --git a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsNormalChecklists.ts b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsNormalChecklists.ts index 40607d6f735..4202131fac7 100644 --- a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsNormalChecklists.ts +++ b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsNormalChecklists.ts @@ -295,12 +295,7 @@ export class FwsNormalChecklists { whichItemsChecked: () => [null, null, SimVar.GetSimVarValue('A:LIGHT BEACON', SimVarValueType.Bool)], }, 1000003: { - whichItemsChecked: () => [ - null, - !this.fws.pitchTrimNotTo.get(), - Math.abs(SimVar.GetSimVarValue('L:RUDDER_TRIM_1_COMMANDED_POSITION', SimVarValueType.Number)) < 0.35 && - Math.abs(SimVar.GetSimVarValue('L:RUDDER_TRIM_2_COMMANDED_POSITION', SimVarValueType.Number)) < 0.35, - ], + whichItemsChecked: () => [null, !this.fws.pitchTrimNotTo.get(), this.fws.rudderTrimPosition.get() < 0.35], }, 1000004: { whichItemsChecked: () => [ From ee8cdd449f91fd6fbb6eac6fed1ee4a79b40e805 Mon Sep 17 00:00:00 2001 From: Florian Gross <63071941+flogross89@users.noreply.github.com> Date: Sat, 7 Dec 2024 06:25:25 +0200 Subject: [PATCH 04/40] fix abnormal sensed --- .../elements/WdAbnormalSensedProcedures.tsx | 16 +- .../elements/WdAbstractChecklistComponent.tsx | 19 +- .../src/EWD/elements/WdNormalChecklists.tsx | 4 + .../systems/instruments/src/EWD/style.scss | 10 + .../AbnormalSensed/ata21-22-23.tsx | 1 + .../MsfsAvionicsCommon/EcamMessages/index.tsx | 3 + .../providers/FwsEwdPublisher.ts | 10 +- .../FlightWarningSystem/FwsAbnormalSensed.ts | 278 +++++++++++------- .../systems/FlightWarningSystem/FwsCore.ts | 29 +- .../FwsNormalChecklists.ts | 92 +++--- 10 files changed, 291 insertions(+), 171 deletions(-) diff --git a/fbw-a380x/src/systems/instruments/src/EWD/elements/WdAbnormalSensedProcedures.tsx b/fbw-a380x/src/systems/instruments/src/EWD/elements/WdAbnormalSensedProcedures.tsx index e5d106c6c1a..089d4d2fdd3 100644 --- a/fbw-a380x/src/systems/instruments/src/EWD/elements/WdAbnormalSensedProcedures.tsx +++ b/fbw-a380x/src/systems/instruments/src/EWD/elements/WdAbnormalSensedProcedures.tsx @@ -29,9 +29,21 @@ export class WdAbnormalSensedProcedures extends WdAbstractChecklistComponent { }); if (procIndex === 0) { + if (cl.recommendation) { + this.lineData.push({ + abnormalProcedure: true, + activeProcedure: procIndex === 0, + sensed: true, + checked: false, + text: cl.recommendation, + style: cl.recommendation === 'LAND ASAP' ? ChecklistLineStyle.LandAsap : ChecklistLineStyle.LandAnsa, + firstLine: false, + lastLine: false, + }); + } // If first and most important procedure: Display in full cl.items.forEach((item, itemIndex) => { - if (procState.itemsToShow[itemIndex] === false) { + if (!procState.itemsToShow[itemIndex]) { return; } @@ -62,6 +74,7 @@ export class WdAbnormalSensedProcedures extends WdAbstractChecklistComponent { style: item.style ? item.style : ChecklistLineStyle.ChecklistItem, firstLine: procIndex !== 0 ? true : false, lastLine: procIndex !== 0 ? true : false, + originalItemIndex: itemIndex, }); }); @@ -74,6 +87,7 @@ export class WdAbnormalSensedProcedures extends WdAbstractChecklistComponent { style: ChecklistLineStyle.ChecklistItem, firstLine: false, lastLine: true, + originalItemIndex: cl.items.length, }); } else { // Only three dots for following procedures diff --git a/fbw-a380x/src/systems/instruments/src/EWD/elements/WdAbstractChecklistComponent.tsx b/fbw-a380x/src/systems/instruments/src/EWD/elements/WdAbstractChecklistComponent.tsx index bd110011a8c..f92e9ae7dcc 100644 --- a/fbw-a380x/src/systems/instruments/src/EWD/elements/WdAbstractChecklistComponent.tsx +++ b/fbw-a380x/src/systems/instruments/src/EWD/elements/WdAbstractChecklistComponent.tsx @@ -67,7 +67,9 @@ export class WdAbstractChecklistComponent extends DisplayComponent { if (index >= this.showFromLine.get() && lineIdx < WD_NUM_LINES) { this.lineDataSubject[lineIdx].set(ld); - this.lineSelected[lineIdx].set(index === this.activeLine.get()); + this.lineSelected[lineIdx].set( + ld.originalItemIndex !== undefined ? ld.originalItemIndex === this.activeLine.get() : false, + ); lineIdx++; } }); @@ -110,11 +112,7 @@ export class WdAbstractChecklistComponent extends DisplayComponent
{Array.from(Array(WD_NUM_LINES), () => '').map((_, index) => ( - + ))}
@@ -126,7 +124,6 @@ export class WdAbstractChecklistComponent extends DisplayComponent; selected: Subscribable; - abnormal: boolean; } export class EclLine extends DisplayComponent { @@ -152,6 +149,8 @@ export class EclLine extends DisplayComponent { Cyan: this.props.data.map((d) => d.style === ChecklistLineStyle.Cyan), Amber: this.props.data.map((d) => d.style === ChecklistLineStyle.Amber), OmissionDots: this.props.data.map((d) => d.style === ChecklistLineStyle.OmissionDots), + LandAnsa: this.props.data.map((d) => d.style === ChecklistLineStyle.LandAnsa), + LandAsap: this.props.data.map((d) => d.style === ChecklistLineStyle.LandAsap), }} style={{ display: this.props.data.map((d) => (d.style === ChecklistLineStyle.SeparationLine ? 'none' : 'flex')), @@ -165,7 +164,11 @@ export class EclLine extends DisplayComponent { ), Checked: this.props.data.map((d) => d.checked), HiddenElement: this.props.data.map( - (d) => d.style === ChecklistLineStyle.Headline || d.style === ChecklistLineStyle.OmissionDots, + (d) => + d.style === ChecklistLineStyle.Headline || + d.style === ChecklistLineStyle.OmissionDots || + d.style === ChecklistLineStyle.LandAnsa || + d.style === ChecklistLineStyle.LandAsap, ), Invisible: this.props.data.map( (d) => d.sensed || (d.firstLine && d.lastLine) || d.specialLine === WdSpecialLine.Empty, diff --git a/fbw-a380x/src/systems/instruments/src/EWD/elements/WdNormalChecklists.tsx b/fbw-a380x/src/systems/instruments/src/EWD/elements/WdNormalChecklists.tsx index bf101418291..105c6f836df 100644 --- a/fbw-a380x/src/systems/instruments/src/EWD/elements/WdNormalChecklists.tsx +++ b/fbw-a380x/src/systems/instruments/src/EWD/elements/WdNormalChecklists.tsx @@ -39,6 +39,7 @@ export class WdNormalChecklists extends WdAbstractChecklistComponent { style: state.checklistCompleted ? ChecklistLineStyle.CompletedChecklist : ChecklistLineStyle.ChecklistItem, firstLine: false, lastLine: index === sorted.length - 1, + originalItemIndex: index, }); } }); @@ -78,6 +79,7 @@ export class WdNormalChecklists extends WdAbstractChecklistComponent { style: item.style ? item.style : ChecklistLineStyle.ChecklistItem, firstLine: false, lastLine: false, + originalItemIndex: index, }); }); @@ -89,6 +91,7 @@ export class WdNormalChecklists extends WdAbstractChecklistComponent { style: ChecklistLineStyle.ChecklistItem, firstLine: false, lastLine: false, + originalItemIndex: cl.items.length, }); this.lineData.push({ @@ -99,6 +102,7 @@ export class WdNormalChecklists extends WdAbstractChecklistComponent { style: ChecklistLineStyle.ChecklistItem, firstLine: false, lastLine: true, + originalItemIndex: cl.items.length + 1, }); } super.updateChecklists(); diff --git a/fbw-a380x/src/systems/instruments/src/EWD/style.scss b/fbw-a380x/src/systems/instruments/src/EWD/style.scss index 648b93d4470..c269a69ed59 100644 --- a/fbw-a380x/src/systems/instruments/src/EWD/style.scss +++ b/fbw-a380x/src/systems/instruments/src/EWD/style.scss @@ -439,6 +439,16 @@ text, tspan, span { color: $display-cyan !important; } +.EclLine.LandAnsa { + color: $display-amber !important; + justify-content: flex-end; +} + +.EclLine.LandAsap { + color: $display-red !important; + justify-content: flex-end; +} + .EclLineCheckboxArea { text-align: center; justify-content: center; diff --git a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata21-22-23.tsx b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata21-22-23.tsx index d7ca1ef2db4..c7e72540f2d 100644 --- a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata21-22-23.tsx +++ b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata21-22-23.tsx @@ -201,6 +201,7 @@ export const EcamAbnormalSensedAta212223: { [n: number]: AbnormalProcedure } = { }, 211800021: { title: '\x1b<4m\x1b4mAIR\x1bm PACK 1+2 FAULT', + recommendation: 'LAND ANSA', sensed: true, // If at least one door is not closed or is not locked, and at least one engine is running: items: [ diff --git a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/index.tsx b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/index.tsx index acfa14defd3..03b5506529f 100644 --- a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/index.tsx +++ b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/index.tsx @@ -565,6 +565,8 @@ export enum ChecklistLineStyle { ChecklistItem = 'ChecklistItem', CompletedChecklist = 'CompletedChecklist', OmissionDots = 'OmissionDots', + LandAsap = 'LandAsap', + LandAnsa = 'LandAnsa', } interface AbstractChecklistItem { @@ -642,6 +644,7 @@ export interface WdLineData { lastLine: boolean; specialLine?: WdSpecialLine; abnormalProcedure?: boolean; + originalItemIndex?: number; } export enum WdSpecialLine { diff --git a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/providers/FwsEwdPublisher.ts b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/providers/FwsEwdPublisher.ts index e795818544a..bb884e157c3 100644 --- a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/providers/FwsEwdPublisher.ts +++ b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/providers/FwsEwdPublisher.ts @@ -2,8 +2,6 @@ // // SPDX-License-Identifier: GPL-3.0 -import { ChecklistState } from 'systems-host/systems/FlightWarningSystem/FwsNormalChecklists'; - export interface FwsEwdAbnormalSensedEntry { id: string; itemsToShow: boolean[]; @@ -11,6 +9,12 @@ export interface FwsEwdAbnormalSensedEntry { itemsActive: boolean[]; } +export interface NormalChecklistState { + id: number; + checklistCompleted: boolean; + itemsCompleted: boolean[]; +} + /** * Transmitted from FWS to EWD */ @@ -23,7 +27,7 @@ export interface FwsEwdEvents { /** (FWS -> EWD) Show normal procedures / ECL */ fws_show_normal_checklists: boolean; /** (FWS -> EWD) List of all normal checklists, including checked state */ - fws_normal_checklists: ChecklistState[]; + fws_normal_checklists: NormalChecklistState[]; /** (FWS -> EWD) Which checklist to display */ fws_normal_checklists_id: number; diff --git a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsAbnormalSensed.ts b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsAbnormalSensed.ts index b54aa98fdec..bb193e9e584 100644 --- a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsAbnormalSensed.ts +++ b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsAbnormalSensed.ts @@ -2,7 +2,11 @@ // // SPDX-License-Identifier: GPL-3.0 -import { EcamAbnormalSensedProcedures } from '../../../instruments/src/MsfsAvionicsCommon/EcamMessages'; +import { + ChecklistLineStyle, + EcamAbnormalSensedProcedures, + WD_NUM_LINES, +} from '../../../instruments/src/MsfsAvionicsCommon/EcamMessages'; import { MappedSubject, Subject, @@ -61,8 +65,11 @@ export class FwsAbnormalSensed { public readonly showAbnormalSensedRequested = Subject.create(false); + /** ID of active abnormal procedure */ + public readonly activeProcedureId = Subject.create(null); + /** Marked with cyan box */ - public readonly selectedLine = Subject.create(1); + public readonly selectedItem = Subject.create(1); /** For overflowing checklists */ public readonly showFromLine = Subject.create(0); @@ -88,116 +95,164 @@ export class FwsAbnormalSensed { const sortedAbnormalsFlattened = flattened.sort( (a, b) => this.ewdAbnormalSensed[b.id].failure - this.ewdAbnormalSensed[a.id].failure, ); + this.activeProcedureId.set(sortedAbnormalsFlattened.length > 0 ? sortedAbnormalsFlattened[0].id : null); this.pub.pub('fws_abn_sensed_procedures', sortedAbnormalsFlattened, true); }, true, ); + + this.abnormalShown.sub((shown) => { + if (shown) { + this.selectFirst(); + } + }); + + this.activeProcedureId.sub((id) => { + if (id) { + this.selectFirst(); + } + }); + + this.selectedItem.sub(() => this.scrollToSelectedLine()); } getAbnormalProceduresKeysSorted() { - return Object.keys(EcamAbnormalSensedProcedures).map((v) => v); + return Array.from(this.fws.activeAbnormalSensedList.get().keys()); + } + + selectFirst() { + const clState = this.fws.activeAbnormalSensedList.getValue(this.activeProcedureId.get()); + const selectableAndNotChecked = this.selectableItems(false); + this.selectedItem.set( + selectableAndNotChecked[0] !== undefined ? selectableAndNotChecked[0] - 1 : clState.itemsChecked.length - 1, + ); + this.moveDown(false); } moveUp() { - /* const numItems = EcamNormalProcedures[this.checklistId.get()].items.length; - const selectable = EcamNormalProcedures[this.checklistId.get()].items - .map((item, index) => (item.sensed === false ? index : null)) - .filter((v) => v !== null); + const selectable = this.selectableItems(true); - if (this.selectedLine.get() == numItems + 1) { - // RESET - this.selectedLine.set(this.selectedLine.get() - 1); - } else { - if (selectable.length === 0) { - return; - } - const previousElement = () => { - for (let i = selectable.length - 1; i >= 0; i--) { - if (selectable[i] < this.selectedLine.get()) { - return selectable[i]; - } + if (selectable.length === 0) { + return; + } + const previousElement = () => { + for (let i = selectable.length - 1; i >= 0; i--) { + if (selectable[i] < this.selectedItem.get()) { + return selectable[i]; } - return -1; - }; - const pEl = previousElement(); - - if (pEl >= 0) { - this.selectedLine.set(Math.max(pEl, 0)); } + return -1; + }; + const pEl = previousElement(); + + if (pEl >= 0) { + this.selectedItem.set(Math.max(pEl, 0)); } - this.showFromLine.set(Math.max(0, this.selectedLine.get() - WD_NUM_LINES + 2));*/ } - moveDown() { - /* if (this.checklistId.get() === 0) { - this.selectedLine.set( - Math.min(this.selectedLine.get() + 1, this.getAbnormalProceduresKeysSorted().length - 1, WD_NUM_LINES - 1), - ); + static readonly nonSelectableItemStyles = [ + ChecklistLineStyle.Headline, + ChecklistLineStyle.OmissionDots, + ChecklistLineStyle.SeparationLine, + ChecklistLineStyle.SubHeadline, + ChecklistLineStyle.Amber, + ChecklistLineStyle.Cyan, + ChecklistLineStyle.Green, + ]; + + /** + * Used for up/down navigation, to skip not selectable items + * @param skipCompletedSensed Whether sensed item is only selectable if unchecked. Not sensed items can't be skipped. + * @returns Procedure item is selectable with arrow keys + */ + private itemIsSelectable(itemIndex: number, skipCompletedSensed: boolean): boolean { + const procId = this.activeProcedureId.get(); + const clState = this.fws.activeAbnormalSensedList.getValue(this.activeProcedureId.get()); + return ( + (!EcamAbnormalSensedProcedures[procId].items[itemIndex].sensed || + (!skipCompletedSensed && !clState.itemsChecked[itemIndex])) && + clState.itemsActive[itemIndex] && + clState.itemsToShow[itemIndex] && + !FwsAbnormalSensed.nonSelectableItemStyles.includes(EcamAbnormalSensedProcedures[procId].items[itemIndex].style) + ); + } + + private selectableItems(skipCompletedSensed: boolean) { + return EcamAbnormalSensedProcedures[this.activeProcedureId.get()].items + .map((_, index) => (this.itemIsSelectable(index, skipCompletedSensed) ? index : null)) + .filter((v) => v !== null); + } + + /** Returns the index from selectedItem amongst the displayed items */ + private lineInDisplay(selectedItem: number) { + return this.fws.activeAbnormalSensedList.has(this.activeProcedureId.get()) + ? this.fws.activeAbnormalSensedList + .getValue(this.activeProcedureId.get()) + .itemsToShow.map((value, index) => (value ? index : null)) + .filter(Boolean) + .findIndex((v) => v === selectedItem) + : -1; + } + + moveDown(skipCompletedSensed = true) { + const numItems = this.fws.activeAbnormalSensedList.getValue(this.activeProcedureId.get()).itemsToShow.length; + const selectable = this.selectableItems(skipCompletedSensed); + if (selectable.length == 0 || this.selectedItem.get() >= selectable[selectable.length - 1]) { + // Last element before CLEAR + this.selectedItem.set(numItems); } else { - const numItems = EcamNormalProcedures[this.checklistId.get()].items.length; - const selectable = EcamNormalProcedures[this.checklistId.get()].items - .map((item, index) => (item.sensed === false ? index : null)) - .filter((v) => v !== null); - if (this.selectedLine.get() >= selectable[selectable.length - 1] || selectable.length == 0) { - // Last element before C/L complete - this.selectedLine.set(Math.max(numItems, Math.min(this.selectedLine.get() + 1, numItems + 1))); - } else { - this.selectedLine.set( - Math.min( - selectable.find((v) => v > this.selectedLine.get()), - numItems - 1, - ), - ); - } + this.selectedItem.set( + Math.min(selectable.find((v) => v > this.selectedItem.get()) ?? numItems - 1, numItems - 1), + ); } - this.showFromLine.set(Math.max(0, this.selectedLine.get() - WD_NUM_LINES + 2));*/ } checkCurrentItem() { - /* const cl = this.checklistState.getValue(this.checklistId.get()); - const clState: ChecklistState = { + const cl = this.fws.activeAbnormalSensedList.getValue(this.activeProcedureId.get()); + const clState: FwsEwdAbnormalSensedEntry = { id: cl.id, - checklistCompleted: cl.checklistCompleted, - itemsCompleted: [...cl.itemsCompleted], + itemsToShow: [...cl.itemsToShow], + itemsChecked: [...cl.itemsChecked], + itemsActive: [...cl.itemsActive], }; - if (this.selectedLine.get() < clState.itemsCompleted.length) { - clState.itemsCompleted[this.selectedLine.get()] = !clState.itemsCompleted[this.selectedLine.get()]; - this.checklistState.setValue(this.checklistId.get(), clState); - } else if (this.selectedLine.get() === clState.itemsCompleted.length) { - // C/L complete - clState.checklistCompleted = true; - const proc = EcamNormalProcedures[this.checklistId.get()]; - clState.itemsCompleted = clState.itemsCompleted.map((val, index) => (proc.items[index].sensed ? val : true)); - this.checklistState.setValue(this.checklistId.get(), clState); - this.showChecklist.set(false); - } else if (this.selectedLine.get() === clState.itemsCompleted.length + 1) { - // RESET - clState.checklistCompleted = false; - const proc = EcamNormalProcedures[this.checklistId.get()]; - clState.itemsCompleted = clState.itemsCompleted.map((val, index) => (proc.items[index].sensed ? val : false)); + const proc = EcamAbnormalSensedProcedures[this.activeProcedureId.get()]; + if ( + this.selectedItem.get() < clState.itemsChecked.length && + proc.items[this.selectedItem.get()]?.sensed === false + ) { + clState.itemsChecked[this.selectedItem.get()] = !clState.itemsChecked[this.selectedItem.get()]; + this.fws.activeAbnormalSensedList.setValue(this.activeProcedureId.get(), clState); + if (clState.itemsChecked[this.selectedItem.get()]) { + this.moveDown(false); + } + } else if (this.selectedItem.get() === clState.itemsChecked.length) { + this.clearActiveProcedure(); + } + } - // Reset all following checklists - const fromId = this.getAbnormalProceduresKeysSorted().findIndex((v) => v === this.checklistId.get()); - const ids = this.getAbnormalProceduresKeysSorted(); + private clearActiveProcedure() { + this.fws.presentedFailures.splice(0, 1); + this.fws.recallFailures = this.fws.allCurrentFailures.filter((item) => !this.fws.presentedFailures.includes(item)); + } - if (fromId !== -1) { - for (let id = fromId + 1; id < ids.length; id++) { - const idFollowing = ids[id]; - const clFollowing = this.checklistState.getValue(idFollowing); - const procFollowing = EcamNormalProcedures[idFollowing]; - const clStateFollowing: ChecklistState = { - id: idFollowing, - checklistCompleted: false, - itemsCompleted: [...clFollowing.itemsCompleted].map((val, index) => - procFollowing.items[index].sensed ? val : false, - ), - }; - this.checklistState.setValue(idFollowing, clStateFollowing); - } - } - this.checklistState.setValue(this.checklistId.get(), clState); - this.selectFirst(); - }*/ + private scrollToSelectedLine() { + if ( + this.fws.activeAbnormalSensedList.has(this.activeProcedureId.get()) && + this.selectedItem.get() >= + this.fws.activeAbnormalSensedList.getValue(this.activeProcedureId.get()).itemsToShow.length + ) { + // CLEAR + this.showFromLine.set( + Math.max( + 0, + this.fws.activeAbnormalSensedList.getValue(this.activeProcedureId.get()).itemsToShow.length - + WD_NUM_LINES + + 2, + ), + ); + } else { + this.showFromLine.set(Math.max(0, this.lineInDisplay(this.selectedItem.get()) - WD_NUM_LINES + 2)); + } } /** @@ -207,41 +262,44 @@ export class FwsAbnormalSensed { update() { if (this.fws.activeAbnormalSensedList.get().size > 0) { this.showAbnormalSensedRequested.set(true); - - // Update selected line: CLEAR of first procedure - const firstKey = this.fws.activeAbnormalSensedList.get().keys().next().value; - const numItems = this.fws.activeAbnormalSensedList - .getValue(firstKey) - .itemsToShow.filter((v) => v === true).length; - this.selectedLine.set(numItems + 1); } else { this.showAbnormalSensedRequested.set(false); } - /*if (this.fws.clDownPulseNode.read()) { - if (!this.showAbnormalSensed.get()) { - return; - } - this.moveDown(); + if (!this.abnormalShown.get()) { + return; + } + + if (this.fws.clDownPulseNode.read()) { + this.moveDown(true); } if (this.fws.clUpPulseNode.read()) { - if (!this.showAbnormalSensed.get()) { - return; - } this.moveUp(); - }*/ + } if (this.fws.clCheckPulseNode.read()) { - if (!this.abnormalShown.get()) { - return; + this.checkCurrentItem(); + } + + // Auto-move-down if currently marked item was sensed as completed + const ids = this.getAbnormalProceduresKeysSorted(); + + for (let id = 0; id < ids.length; id++) { + const procId = ids[id]; + + if (!this.ewdAbnormalSensed[procId] || !this.fws.abnormalUpdatedItems.has(procId)) { + continue; } - // Only CLEAR implemented atm - this.fws.presentedFailures.splice(0, 1); - this.fws.recallFailures = this.fws.allCurrentFailures.filter( - (item) => !this.fws.presentedFailures.includes(item), - ); + const changedEntries = this.fws.abnormalUpdatedItems.get(procId); + if ( + changedEntries && + changedEntries.includes(this.selectedItem.get()) && + this.fws.activeAbnormalSensedList.getValue(this.activeProcedureId.get()).itemsChecked[this.selectedItem.get()] + ) { + this.moveDown(false); + } } } diff --git a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsCore.ts b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsCore.ts index 85cf37fb4c6..fbd884f4e6e 100644 --- a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsCore.ts +++ b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsCore.ts @@ -223,6 +223,9 @@ export class FwsCore { /** Map to hold all failures which are currently active */ public readonly activeAbnormalSensedList = MapSubject.create(); + /** Indices of items which were updated */ + public readonly abnormalUpdatedItems = new Map(); + public recallFailures: string[] = []; private requestMasterCautionFromFaults = false; @@ -3803,6 +3806,7 @@ export class FwsCore { // Abnormal sensed procedures const ewdAbnormalEntries: [string, EwdAbnormalItem][] = Object.entries(this.abnormalSensed.ewdAbnormalSensed); + this.abnormalUpdatedItems.clear(); for (const [key, value] of ewdAbnormalEntries) { if (value.flightPhaseInhib.some((e) => e === flightPhase)) { continue; @@ -3826,7 +3830,7 @@ export class FwsCore { if (overridden) { continue; } - const itemsChecked = value.whichItemsChecked().map((v, i) => (proc.items[i].sensed === false ? false : v)); + const itemsChecked = value.whichItemsChecked().map((v, i) => (proc.items[i].sensed === false ? false : !!v)); const itemsToShow = value.whichItemsToShow ? value.whichItemsToShow() : Array(itemsChecked.length).fill(true); const itemsActive = value.whichItemsActive ? value.whichItemsActive() : Array(itemsChecked.length).fill(true); @@ -3873,31 +3877,28 @@ export class FwsCore { }); } else if (this.activeAbnormalSensedList.has(key)) { // Update internal map - const prevEl = this.activeAbnormalSensedList.get().get(key); - const itemUpdated = proc.items.some((item, idx) => { + const prevEl = this.activeAbnormalSensedList.getValue(key); + this.abnormalUpdatedItems.set(key, []); + proc.items.forEach((item, idx) => { if (item.sensed === true) { if ( prevEl.itemsToShow[idx] !== itemsToShow[idx] || prevEl.itemsActive[idx] !== itemsActive[idx] || prevEl.itemsChecked[idx] !== itemsChecked[idx] ) { - return true; + this.abnormalUpdatedItems.get(key).push(idx); } } }); - if (itemUpdated) { + if (this.abnormalUpdatedItems.has(key) && this.abnormalUpdatedItems.get(key).length > 0) { this.activeAbnormalSensedList.setValue(key, { id: key, itemsChecked: [...prevEl.itemsChecked].map((val, index) => - proc.items[index].sensed ? itemsChecked[index] : val, - ), - itemsActive: [...prevEl.itemsActive].map((val, index) => - proc.items[index].sensed ? itemsActive[index] : val, - ), - itemsToShow: [...prevEl.itemsToShow].map((val, index) => - proc.items[index].sensed ? itemsToShow[index] : val, + proc.items[index].sensed ? itemsChecked[index] : !!val, ), + itemsActive: [...prevEl.itemsActive].map((_, index) => itemsActive[index]), + itemsToShow: [...prevEl.itemsToShow].map((_, index) => itemsToShow[index]), }); } } @@ -4137,7 +4138,7 @@ export class FwsCore { this.normalChecklists.checklistShown.set(true); this.abnormalSensed.abnormalShown.set(false); - pub.pub('fws_active_line', this.normalChecklists.selectedLine.get() + 1, true); + pub.pub('fws_active_line', this.normalChecklists.selectedLine.get(), true); pub.pub('fws_show_from_line', this.normalChecklists.showFromLine.get(), true); this.ecamEwdShowFailurePendingIndication.set(this.abnormalSensed.showAbnormalSensedRequested.get()); } else if ( @@ -4147,7 +4148,7 @@ export class FwsCore { this.normalChecklists.checklistShown.set(false); this.abnormalSensed.abnormalShown.set(true); - pub.pub('fws_active_line', this.abnormalSensed.selectedLine.get(), true); + pub.pub('fws_active_line', this.abnormalSensed.selectedItem.get(), true); pub.pub('fws_show_from_line', this.abnormalSensed.showFromLine.get(), true); this.ecamEwdShowFailurePendingIndication.set(false); } else { diff --git a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsNormalChecklists.ts b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsNormalChecklists.ts index 4202131fac7..a334036317b 100644 --- a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsNormalChecklists.ts +++ b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsNormalChecklists.ts @@ -2,16 +2,10 @@ // SPDX-License-Identifier: GPL-3.0 import { MapSubject, SimVarValueType, Subject, SubscribableMapEventType } from '@microsoft/msfs-sdk'; -import { FwsEwdEvents } from 'instruments/src/MsfsAvionicsCommon/providers/FwsEwdPublisher'; +import { NormalChecklistState, FwsEwdEvents } from 'instruments/src/MsfsAvionicsCommon/providers/FwsEwdPublisher'; import { FwsCore } from 'systems-host/systems/FlightWarningSystem/FwsCore'; import { EcamNormalProcedures } from 'instruments/src/MsfsAvionicsCommon/EcamMessages/NormalProcedures'; -import { NormalProcedure, WD_NUM_LINES } from 'instruments/src/MsfsAvionicsCommon/EcamMessages'; - -export type ChecklistState = { - id: number; - checklistCompleted: boolean; - itemsCompleted: boolean[]; -}; +import { ChecklistLineStyle, NormalProcedure, WD_NUM_LINES } from 'instruments/src/MsfsAvionicsCommon/EcamMessages'; export interface NormalEclSensedItems { /** Returns a boolean vector (same length as number of items). If true, item is marked as completed. If null, it's a non-sensed item */ @@ -37,17 +31,17 @@ export class FwsNormalChecklists { /** For overflowing checklists */ public readonly showFromLine = Subject.create(0); - public readonly checklistState = MapSubject.create(); + public readonly checklistState = MapSubject.create(); constructor(private fws: FwsCore) { this.checklistState.sub( ( - map: ReadonlyMap, + map: ReadonlyMap, _type: SubscribableMapEventType, _key: number, - _value: ChecklistState, + _value: NormalChecklistState, ) => { - const flattened: ChecklistState[] = []; + const flattened: NormalChecklistState[] = []; map.forEach((val, key) => flattened.push({ id: key, checklistCompleted: val.checklistCompleted, itemsCompleted: val.itemsCompleted }), ); @@ -73,6 +67,8 @@ export class FwsNormalChecklists { checklistCompleted: false, itemsCompleted: Array(Object.keys(EcamNormalProcedures).length).fill(false), }); + + this.selectedLine.sub(() => this.scrollToSelectedLine()); } getNormalProceduresKeysSorted() { @@ -102,7 +98,7 @@ export class FwsNormalChecklists { selectableAndNotChecked[0] !== undefined ? selectableAndNotChecked[0] - 1 : clState.itemsCompleted.length - 1, ); } - this.moveDown(true); + this.moveDown(false); } moveUp() { @@ -110,7 +106,8 @@ export class FwsNormalChecklists { this.selectedLine.set(Math.max(this.selectedLine.get() - 1, 0)); } else { const numItems = EcamNormalProcedures[this.checklistId.get()].items.length; - const selectable = EcamNormalProcedures[this.checklistId.get()].items.map((_, index) => index); + // const selectable = EcamNormalProcedures[this.checklistId.get()].items.map((_, index) => index); + const selectable = this.selectableItems(true); if (this.selectedLine.get() == numItems + 1) { // RESET @@ -134,18 +131,46 @@ export class FwsNormalChecklists { } } } - this.showFromLine.set(Math.max(0, this.selectedLine.get() - WD_NUM_LINES + 2)); } - moveDown(skipCompleted = false) { + static readonly nonSelectableItemStyles = [ + ChecklistLineStyle.Headline, + ChecklistLineStyle.OmissionDots, + ChecklistLineStyle.SeparationLine, + ChecklistLineStyle.SubHeadline, + ChecklistLineStyle.Amber, + ChecklistLineStyle.Cyan, + ChecklistLineStyle.Green, + ]; + + /** + * Used for up/down navigation, to skip not selectable items + * @param skipCompletedSensed Whether sensed item is only selectable if unchecked. Not sensed items can't be skipped. + * @returns Procedure item is selectable with arrow keys + */ + private itemIsSelectable(itemIndex: number, skipCompletedSensed: boolean): boolean { + const clState = this.checklistState.getValue(this.checklistId.get()); + return ( + (!EcamNormalProcedures[this.checklistId.get()].items[itemIndex].sensed || + (!skipCompletedSensed && !clState.itemsCompleted[itemIndex])) && + !FwsNormalChecklists.nonSelectableItemStyles.includes( + EcamNormalProcedures[this.checklistId.get()].items[itemIndex].style, + ) + ); + } + + private selectableItems(skipCompletedSensed: boolean) { + return EcamNormalProcedures[this.checklistId.get()].items + .map((_, index) => (this.itemIsSelectable(index, skipCompletedSensed) ? index : null)) + .filter((v) => v !== null); + } + + moveDown(skipCompletedSensed = true) { if (this.checklistId.get() === 0) { this.selectedLine.set(Math.min(this.selectedLine.get() + 1, this.getNormalProceduresKeysSorted().length - 1)); } else { - const clState = this.checklistState.getValue(this.checklistId.get()); const numItems = EcamNormalProcedures[this.checklistId.get()].items.length; - const selectable = EcamNormalProcedures[this.checklistId.get()].items - .map((_, index) => (!skipCompleted || clState.itemsCompleted[index] === false ? index : null)) - .filter((v) => v !== null); + const selectable = this.selectableItems(skipCompletedSensed); if (this.selectedLine.get() >= selectable[selectable.length - 1] || selectable.length == 0) { // Last element before C/L complete this.selectedLine.set(Math.max(numItems, Math.min(this.selectedLine.get() + 1, numItems + 1))); @@ -158,12 +183,11 @@ export class FwsNormalChecklists { ); } } - this.showFromLine.set(Math.max(0, this.selectedLine.get() - WD_NUM_LINES + 2)); } checkCurrentItem() { const cl = this.checklistState.getValue(this.checklistId.get()); - const clState: ChecklistState = { + const clState: NormalChecklistState = { id: cl.id, checklistCompleted: cl.checklistCompleted, itemsCompleted: [...cl.itemsCompleted], @@ -176,7 +200,7 @@ export class FwsNormalChecklists { clState.itemsCompleted[this.selectedLine.get()] = !clState.itemsCompleted[this.selectedLine.get()]; this.checklistState.setValue(this.checklistId.get(), clState); if (clState.itemsCompleted[this.selectedLine.get()]) { - this.moveDown(true); + this.moveDown(false); } } else if (this.selectedLine.get() === clState.itemsCompleted.length) { // C/L complete @@ -198,7 +222,7 @@ export class FwsNormalChecklists { const idFollowing = ids[id]; const clFollowing = this.checklistState.getValue(idFollowing); const procFollowing = EcamNormalProcedures[idFollowing]; - const clStateFollowing: ChecklistState = { + const clStateFollowing: NormalChecklistState = { id: idFollowing, checklistCompleted: procFollowing.deferred ? true : false, itemsCompleted: [...clFollowing.itemsCompleted].map((val, index) => @@ -218,31 +242,29 @@ export class FwsNormalChecklists { this.selectFirst(); } + private scrollToSelectedLine() { + this.showFromLine.set(Math.max(0, this.selectedLine.get() - WD_NUM_LINES + 2)); + } + update() { if (this.fws.clPulseNode.read()) { this.navigateToChecklist(0); this.showChecklistRequested.set(!this.showChecklistRequested.get()); } + if (!this.checklistShown.get()) { + return; + } + if (this.fws.clDownPulseNode.read()) { - if (!this.checklistShown.get()) { - return; - } this.moveDown(); } if (this.fws.clUpPulseNode.read()) { - if (!this.checklistShown.get()) { - return; - } this.moveUp(); } if (this.fws.clCheckPulseNode.read()) { - if (!this.checklistShown.get()) { - return; - } - if (this.checklistId.get() === 0) { // Navigate to check list this.navigateToChecklist(this.getNormalProceduresKeysSorted()[this.selectedLine.get()]); @@ -274,7 +296,7 @@ export class FwsNormalChecklists { this.moveDown(); } } - const clState: ChecklistState = { + const clState: NormalChecklistState = { id: procId, checklistCompleted: cl.checklistCompleted, itemsCompleted: [...cl.itemsCompleted].map((val, index) => From c3673c8de7ab85924bb8061c0f435227f2ad5b65 Mon Sep 17 00:00:00 2001 From: Florian Gross <63071941+flogross89@users.noreply.github.com> Date: Sun, 8 Dec 2024 04:34:34 +0200 Subject: [PATCH 05/40] introduce conditions --- .../elements/WdAbnormalSensedProcedures.tsx | 45 ++++-- .../elements/WdAbstractChecklistComponent.tsx | 8 +- .../systems/instruments/src/EWD/style.scss | 16 +++ .../AbnormalSensed/ata21-22-23.tsx | 94 +++++------- .../EcamMessages/AbnormalSensed/ata24.tsx | 1 + .../EcamMessages/AbnormalSensed/ata26.tsx | 135 ++++++++---------- .../EcamMessages/AbnormalSensed/ata28.tsx | 89 ++++++------ .../EcamMessages/AbnormalSensed/ata29-30.tsx | 10 +- .../EcamMessages/AbnormalSensed/ata34.tsx | 19 --- .../MsfsAvionicsCommon/EcamMessages/index.tsx | 27 ++-- .../FlightWarningSystem/FwsAbnormalSensed.ts | 36 +++-- .../systems/FlightWarningSystem/FwsCore.ts | 38 +++-- 12 files changed, 277 insertions(+), 241 deletions(-) diff --git a/fbw-a380x/src/systems/instruments/src/EWD/elements/WdAbnormalSensedProcedures.tsx b/fbw-a380x/src/systems/instruments/src/EWD/elements/WdAbnormalSensedProcedures.tsx index 089d4d2fdd3..bc872e7bf63 100644 --- a/fbw-a380x/src/systems/instruments/src/EWD/elements/WdAbnormalSensedProcedures.tsx +++ b/fbw-a380x/src/systems/instruments/src/EWD/elements/WdAbnormalSensedProcedures.tsx @@ -3,6 +3,7 @@ import { ChecklistLineStyle, EcamAbnormalSensedProcedures, isChecklistAction, + isChecklistCondition, WdSpecialLine, } from 'instruments/src/MsfsAvionicsCommon/EcamMessages'; import { WdAbstractChecklistComponent } from 'instruments/src/EWD/elements/WdAbstractChecklistComponent'; @@ -47,35 +48,63 @@ export class WdAbnormalSensedProcedures extends WdAbstractChecklistComponent { return; } - let text = item.level ? '\xa0'.repeat(item.level * 2) : ''; + let clStyle: ChecklistLineStyle = item.style ? item.style : ChecklistLineStyle.ChecklistItem; + let text = item.level ? '\xa0'.repeat(item.level) : ''; if (isChecklistAction(item)) { - text += item.style !== ChecklistLineStyle.SubHeadline ? '-' : ''; + text += clStyle !== ChecklistLineStyle.SubHeadline ? '-' : ''; text += item.name; + if (!procState.itemsActive[itemIndex] && clStyle === ChecklistLineStyle.ChecklistItem) { + clStyle = ChecklistLineStyle.ChecklistItemInactive; + } if (procState.itemsChecked[itemIndex] && item.labelCompleted) { text += `${item.colonIfCompleted === false ? ' ' : ' : '}${item.labelCompleted}`; } else if (procState.itemsChecked[itemIndex] && item.labelNotCompleted) { text += `${item.colonIfCompleted === false ? ' ' : ' : '}${item.labelNotCompleted}`; } else if (!procState.itemsChecked[itemIndex] && item.labelNotCompleted) { // Pad to 39 characters max - const paddingNeeded = - 39 - (item.labelNotCompleted.length + item.name.length + (item.level ?? 0) * 2 + 2); + const paddingNeeded = Math.max( + 0, + 39 - (item.labelNotCompleted.length + item.name.length + (item.level ?? 0) * 1 + 2), + ); + text += ` ${'.'.repeat(paddingNeeded)}${item.labelNotCompleted}`; } + } else if (isChecklistCondition(item)) { + clStyle = ChecklistLineStyle.ChecklistCondition; + text += procState.itemsChecked[itemIndex] + ? `.AS ${item.name.substring(0, 2) === 'IF' ? item.name.substring(2) : item.name}` + : `.IF ${item.name.substring(0, 2) === 'IF' ? item.name.substring(2) : item.name}`; } else { - text += `${item.name.substring(0, 2) === 'IF' ? '.' : ''}${item.name}`; + text += item.name; } this.lineData.push({ abnormalProcedure: true, activeProcedure: procIndex === 0, - sensed: item.sensed, + sensed: isChecklistCondition(item) ? true : item.sensed, checked: procState.itemsChecked[itemIndex], text: text, - style: item.style ? item.style : ChecklistLineStyle.ChecklistItem, + style: clStyle, firstLine: procIndex !== 0 ? true : false, lastLine: procIndex !== 0 ? true : false, - originalItemIndex: itemIndex, + originalItemIndex: isChecklistCondition(item) ? undefined : itemIndex, }); + + if (isChecklistCondition(item) && !item.sensed) { + // Insert CONFIRM + const confirmText = `CONFIRM ${item.name}`; + this.lineData.push({ + abnormalProcedure: true, + activeProcedure: procIndex === 0, + sensed: item.sensed, + checked: procState.itemsChecked[itemIndex], + text: confirmText, + style: clStyle, + firstLine: procIndex !== 0 ? true : false, + lastLine: procIndex !== 0 ? true : false, + originalItemIndex: itemIndex, + }); + } }); this.lineData.push({ diff --git a/fbw-a380x/src/systems/instruments/src/EWD/elements/WdAbstractChecklistComponent.tsx b/fbw-a380x/src/systems/instruments/src/EWD/elements/WdAbstractChecklistComponent.tsx index f92e9ae7dcc..bc914f9cb05 100644 --- a/fbw-a380x/src/systems/instruments/src/EWD/elements/WdAbstractChecklistComponent.tsx +++ b/fbw-a380x/src/systems/instruments/src/EWD/elements/WdAbstractChecklistComponent.tsx @@ -137,6 +137,7 @@ export class EclLine extends DisplayComponent { ChecklistItem: this.props.data.map( (d) => !d.abnormalProcedure && d.style === ChecklistLineStyle.ChecklistItem, ), + ChecklistItemInactive: this.props.data.map((d) => d.style === ChecklistLineStyle.ChecklistItemInactive), AbnormalItem: this.props.data.map( (d) => d.abnormalProcedure === true && d.style === ChecklistLineStyle.ChecklistItem, ), @@ -145,6 +146,7 @@ export class EclLine extends DisplayComponent { ), Checked: this.props.data.map((d) => d.checked), ChecklistCompleted: this.props.data.map((d) => d.style === ChecklistLineStyle.CompletedChecklist), + ChecklistCondition: this.props.data.map((d) => d.style === ChecklistLineStyle.ChecklistCondition), Green: this.props.data.map((d) => d.style === ChecklistLineStyle.Green), Cyan: this.props.data.map((d) => d.style === ChecklistLineStyle.Cyan), Amber: this.props.data.map((d) => d.style === ChecklistLineStyle.Amber), @@ -159,9 +161,9 @@ export class EclLine extends DisplayComponent {
d.abnormalProcedure === true && d.style === ChecklistLineStyle.ChecklistItem, - ), + AbnormalItem: this.props.data.map((d) => d.abnormalProcedure === true), + ChecklistCondition: this.props.data.map((d) => d.style === ChecklistLineStyle.ChecklistCondition), + ChecklistItemInactive: this.props.data.map((d) => d.style === ChecklistLineStyle.ChecklistItemInactive), Checked: this.props.data.map((d) => d.checked), HiddenElement: this.props.data.map( (d) => diff --git a/fbw-a380x/src/systems/instruments/src/EWD/style.scss b/fbw-a380x/src/systems/instruments/src/EWD/style.scss index c269a69ed59..605bb51f86a 100644 --- a/fbw-a380x/src/systems/instruments/src/EWD/style.scss +++ b/fbw-a380x/src/systems/instruments/src/EWD/style.scss @@ -409,6 +409,10 @@ text, tspan, span { color: $display-white; } +.EclLine.ChecklistItemInactive { + color: $display-grey !important; +} + .EclLine.ChecklistCompleted { color: $display-grey !important; } @@ -435,6 +439,10 @@ text, tspan, span { text-decoration: underline; } +.EclLine.ChecklistCondition { + color: $display-white !important; +} + .EclLine.OmissionDots { color: $display-cyan !important; } @@ -471,6 +479,14 @@ text, tspan, span { color: $display-white; } +.EclLineCheckboxArea.ChecklistCondition { + color: $display-white !important; +} + +.EclLineCheckboxArea.AbnormalItem.ChecklistItemInactive { + color: $display-grey; +} + .EclLineText { margin: 0px 10px 0px 10px; font-size: 26px; diff --git a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata21-22-23.tsx b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata21-22-23.tsx index c7e72540f2d..3b61413cbdf 100644 --- a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata21-22-23.tsx +++ b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata21-22-23.tsx @@ -227,10 +227,9 @@ export const EcamAbnormalSensedAta212223: { [n: number]: AbnormalProcedure } = { }, // If there is pack overheat { - name: 'IF PACK OVHT OUT', + name: 'PACK OVHT OUT', sensed: true, - style: ChecklistLineStyle.Headline, - level: 1, + condition: true, }, { name: 'PACK 1', @@ -260,8 +259,8 @@ export const EcamAbnormalSensedAta212223: { [n: number]: AbnormalProcedure } = { { name: 'WHEN DIFF PRESS < 2 PSI & FL < 100/MEA-MORA :', sensed: true, - style: ChecklistLineStyle.Headline, - level: 2, + condition: true, + level: 1, }, { name: 'RAM AIR:', @@ -624,6 +623,11 @@ export const EcamAbnormalSensedAta212223: { [n: number]: AbnormalProcedure } = { sensed: true, labelNotCompleted: 'OVRD', }, + { + name: 'VLV STILL FULL OPEN AFTER 60 s:', + sensed: true, + condition: true, + }, { name: 'MAX FL : 100/MEA', sensed: false, @@ -810,7 +814,6 @@ export const EcamAbnormalSensedAta212223: { [n: number]: AbnormalProcedure } = { name: 'ALL THR LEVERS', sensed: true, labelNotCompleted: 'IDLE', - level: 1, }, { name: 'SPEED BRAKE LEVERS', @@ -843,20 +846,20 @@ export const EcamAbnormalSensedAta212223: { [n: number]: AbnormalProcedure } = { style: ChecklistLineStyle.Cyan, }, { - name: 'IF CAB ALT ABOVE 14000 FT:', + name: 'CAB ALT ABOVE 14000 FT:', sensed: true, - style: ChecklistLineStyle.Headline, + condition: true, }, { name: 'PAX OXY MASK MAN ON', sensed: true, labelNotCompleted: 'PRESS', + level: 1, }, { - name: 'WHEN DESCENT ESTABLISHED:', + name: 'DESCENT ESTABLISHED:', sensed: true, - level: 1, - style: ChecklistLineStyle.Headline, + condition: true, }, { name: 'CREW OXY MASKS DILUTION', @@ -865,38 +868,39 @@ export const EcamAbnormalSensedAta212223: { [n: number]: AbnormalProcedure } = { level: 1, }, { - name: 'WHEN DIFF PR < 2 PSI & FL < 100/MEA-MORA:', + name: 'DIFF PR<2 PSI & FL < 100/MEA-MORA:', sensed: true, - style: ChecklistLineStyle.Headline, + condition: true, }, { name: 'RAM AIR', sensed: true, labelNotCompleted: 'ON', + level: 1, }, { - name: 'IF DIFF PRESS > 1 PSI', + name: 'DIFF PRESS > 1 PSI', sensed: true, level: 1, - style: ChecklistLineStyle.Headline, + condition: true, }, { name: 'CABIN AIR EXTRACT', sensed: true, labelNotCompleted: 'OVRD', - level: 1, + level: 2, }, { - name: 'WHEN ALL OUTFLW VLVs OPEN', + name: 'ALL OUTFLW VLVs OPEN', sensed: true, - level: 1, - style: ChecklistLineStyle.Headline, + level: 2, + condition: true, }, { name: 'CABIN AIR EXTRACT (OVRD)', sensed: true, labelNotCompleted: 'DESELECT', - level: 1, + level: 3, }, ], }, @@ -918,7 +922,6 @@ export const EcamAbnormalSensedAta212223: { [n: number]: AbnormalProcedure } = { name: 'DESCENT TO FL 100/MEA', sensed: false, labelNotCompleted: 'INITIATE', - level: 1, }, { name: 'MAX FL: 100/MEA', @@ -926,10 +929,9 @@ export const EcamAbnormalSensedAta212223: { [n: number]: AbnormalProcedure } = { style: ChecklistLineStyle.Cyan, }, { - name: 'WHEN DIFF PRESS < 1 PSI & FL < 100/MEA :', + name: 'DIFF PRESS < 1 PSI & FL < 100/MEA :', sensed: true, - style: ChecklistLineStyle.Headline, - level: 1, + condition: true, }, { name: 'RAM AIR', @@ -958,13 +960,11 @@ export const EcamAbnormalSensedAta212223: { [n: number]: AbnormalProcedure } = { name: 'AIR FLOW', sensed: true, labelNotCompleted: 'HI', - level: 1, }, { name: 'RAM AIR', sensed: true, labelNotCompleted: 'ON', - level: 1, }, ], }, @@ -990,6 +990,7 @@ export const EcamAbnormalSensedAta212223: { [n: number]: AbnormalProcedure } = { { name: 'BEFORE OPENING ANY CABIN DOOR:', sensed: false, + condition: true, }, { name: 'RESIDUAL DIFF PRESS', @@ -1012,67 +1013,56 @@ export const EcamAbnormalSensedAta212223: { [n: number]: AbnormalProcedure } = { name: 'CAB PRESS IN BACKUP MODE', sensed: true, style: ChecklistLineStyle.Green, - level: 1, }, { name: 'CAB PRESS MAN MODES : DO NOT USE', sensed: true, style: ChecklistLineStyle.Cyan, - level: 1, }, { name: 'IN DES : CAB ALT REGULATED TO 7000 FT', sensed: true, style: ChecklistLineStyle.Green, - level: 1, }, { name: 'BELOW 7000 FT : CAB ALT = ACFT ALT', sensed: true, style: ChecklistLineStyle.Green, - level: 1, }, { name: 'BELOW 7000 FT : AVOID HI DES V/S', sensed: true, style: ChecklistLineStyle.Cyan, - level: 1, }, { name: 'CABIN ALT REGULATED TO 7500FT', sensed: true, style: ChecklistLineStyle.Green, - level: 2, }, { name: 'CAB PRESS MAN MODES : DO NOT USE', sensed: true, style: ChecklistLineStyle.Headline, - level: 2, }, { name: 'BELOW 7500 FT : CAB ALT = ACFT ALT', sensed: true, style: ChecklistLineStyle.Green, - level: 2, }, { name: 'BELOW 7500 FT : AVOID HI DES V/S', sensed: true, style: ChecklistLineStyle.Cyan, - level: 2, }, { name: 'CABIN ALT MODE', sensed: true, labelNotCompleted: 'MAN', - level: 1, }, { name: 'CABIN ALT TRGT', sensed: false, labelNotCompleted: 'AS RQRD', - level: 1, }, ], }, @@ -1181,10 +1171,9 @@ export const EcamAbnormalSensedAta212223: { [n: number]: AbnormalProcedure } = { labelNotCompleted: 'MONITOR', }, { - name: 'IF DIFF PRESS > 9.6 PSI :', + name: 'DIFF PRESS > 9.6 PSI :', sensed: true, - style: ChecklistLineStyle.Headline, - level: 1, + condition: true, }, { name: 'PACK 1', @@ -1202,7 +1191,7 @@ export const EcamAbnormalSensedAta212223: { [n: number]: AbnormalProcedure } = { name: 'DESCENT TO FL 100/MEA', sensed: false, labelNotCompleted: 'INITIATE', - level: 2, + level: 1, }, { name: 'MAX FL : 100/MEA', @@ -1211,22 +1200,10 @@ export const EcamAbnormalSensedAta212223: { [n: number]: AbnormalProcedure } = { level: 1, }, { - name: 'WHEN FL < 100 / MEA :', + name: 'WHEN DIFF PR < 2 PSI & FL < 100 / MEA :', sensed: true, - style: ChecklistLineStyle.Headline, - level: 3, - }, - { - name: 'RAM AIR', - sensed: true, - labelNotCompleted: 'ON', - level: 3, - }, - { - name: 'CABIN AIR EXTRACT', - sensed: true, - labelNotCompleted: 'OVRD', - level: 3, + condition: true, + level: 1, }, { name: 'RAM AIR', @@ -1243,8 +1220,7 @@ export const EcamAbnormalSensedAta212223: { [n: number]: AbnormalProcedure } = { { name: 'BEFORE OPENING ANY CABIN DOOR :', sensed: true, - style: ChecklistLineStyle.Headline, - level: 1, + condition: true, }, { name: 'PACK 1', @@ -1262,11 +1238,13 @@ export const EcamAbnormalSensedAta212223: { [n: number]: AbnormalProcedure } = { name: 'CABIN CREW', sensed: false, labelNotCompleted: 'ADVISE', + level: 1, }, { name: 'RESIDUAL DIFF PRESS', sensed: false, labelNotCompleted: 'CHECK', + level: 1, }, ], }, diff --git a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata24.tsx b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata24.tsx index 14aa7f8045c..1f0a1314e4e 100644 --- a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata24.tsx +++ b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata24.tsx @@ -809,6 +809,7 @@ export const EcamAbnormalSensedAta24: { [n: number]: AbnormalProcedure } = { { name: 'WHEN APU NOT RQRD:', sensed: false, + condition: true, }, { name: 'APU BAT', diff --git a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata26.tsx b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata26.tsx index 91d0a97e51b..be72870fda9 100644 --- a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata26.tsx +++ b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata26.tsx @@ -77,13 +77,11 @@ export const EcamAbnormalSensedAta26: { [n: number]: AbnormalProcedure } = { name: 'APU BLEED', sensed: true, labelNotCompleted: 'OFF', - level: 1, }, { name: 'APU BLEED : DO NOT USE', - sensed: false, + sensed: true, style: ChecklistLineStyle.Cyan, - level: 1, }, { // When timer elapsed, this should change to 'AGENT 1...DISCH' @@ -98,10 +96,9 @@ export const EcamAbnormalSensedAta26: { [n: number]: AbnormalProcedure } = { }, { // When timer elapsed, this should change to 'AS STILL FIRE AFTER 30 S' - name: 'IF STILL FIRE AFTER 30 S :', + name: 'STILL FIRE AFTER 30 S :', sensed: false, - style: ChecklistLineStyle.Headline, - level: 1, + condition: true, }, { name: 'AGENT 2', @@ -144,10 +141,9 @@ export const EcamAbnormalSensedAta26: { [n: number]: AbnormalProcedure } = { }, { // When timer elapsed, this should change to 'AS STILL FIRE AFTER 30 S' - name: 'IF STILL FIRE AFTER 30 S :', + name: 'STILL FIRE AFTER 30 S :', sensed: false, - style: ChecklistLineStyle.Headline, - level: 1, + condition: true, }, { name: 'AGENT 2', @@ -190,10 +186,9 @@ export const EcamAbnormalSensedAta26: { [n: number]: AbnormalProcedure } = { }, { // When timer elapsed, this should change to 'AS STILL FIRE AFTER 30 S' - name: 'IF STILL FIRE AFTER 30 S :', + name: 'STILL FIRE AFTER 30 S :', sensed: false, - style: ChecklistLineStyle.Headline, - level: 1, + condition: true, }, { name: 'AGENT 2', @@ -236,10 +231,9 @@ export const EcamAbnormalSensedAta26: { [n: number]: AbnormalProcedure } = { }, { // When timer elapsed, this should change to 'AS STILL FIRE AFTER 30 S' - name: 'IF STILL FIRE AFTER 30 S :', + name: 'STILL FIRE AFTER 30 S :', sensed: false, - style: ChecklistLineStyle.Headline, - level: 1, + condition: true, }, { name: 'AGENT 2', @@ -262,8 +256,7 @@ export const EcamAbnormalSensedAta26: { [n: number]: AbnormalProcedure } = { { name: 'WHEN ACFT STOPPED :', sensed: true, - style: ChecklistLineStyle.Headline, - level: 1, + condition: true, }, { name: 'PARK BRK', @@ -314,10 +307,10 @@ export const EcamAbnormalSensedAta26: { [n: number]: AbnormalProcedure } = { level: 1, }, { - name: 'IF EVAC RQRD :', + name: 'EVAC RQRD :', sensed: true, - style: ChecklistLineStyle.Headline, - level: 2, + condition: true, + level: 1, }, { name: 'EVAC (PA)', @@ -338,10 +331,10 @@ export const EcamAbnormalSensedAta26: { [n: number]: AbnormalProcedure } = { level: 2, }, { - name: 'IF EVAC NOT RQRD :', + name: 'EVAC NOT RQRD :', sensed: true, - style: ChecklistLineStyle.Headline, - level: 2, + condition: true, + level: 1, }, { name: 'CABIN CREW', @@ -363,8 +356,7 @@ export const EcamAbnormalSensedAta26: { [n: number]: AbnormalProcedure } = { { name: 'WHEN ACFT STOPPED :', sensed: true, - style: ChecklistLineStyle.Headline, - level: 1, + condition: true, }, { name: 'PARK BRK', @@ -415,10 +407,10 @@ export const EcamAbnormalSensedAta26: { [n: number]: AbnormalProcedure } = { level: 1, }, { - name: 'IF EVAC RQRD :', + name: 'EVAC RQRD :', sensed: true, - style: ChecklistLineStyle.Headline, - level: 2, + condition: true, + level: 1, }, { name: 'EVAC (PA)', @@ -439,10 +431,10 @@ export const EcamAbnormalSensedAta26: { [n: number]: AbnormalProcedure } = { level: 2, }, { - name: 'IF EVAC NOT RQRD :', + name: 'EVAC NOT RQRD :', sensed: true, - style: ChecklistLineStyle.Headline, - level: 2, + condition: true, + level: 1, }, { name: 'CABIN CREW', @@ -464,8 +456,7 @@ export const EcamAbnormalSensedAta26: { [n: number]: AbnormalProcedure } = { { name: 'WHEN ACFT STOPPED :', sensed: true, - style: ChecklistLineStyle.Headline, - level: 1, + condition: true, }, { name: 'PARK BRK', @@ -516,10 +507,10 @@ export const EcamAbnormalSensedAta26: { [n: number]: AbnormalProcedure } = { level: 1, }, { - name: 'IF EVAC RQRD :', + name: 'EVAC RQRD :', sensed: true, - style: ChecklistLineStyle.Headline, - level: 2, + condition: true, + level: 1, }, { name: 'EVAC (PA)', @@ -540,10 +531,10 @@ export const EcamAbnormalSensedAta26: { [n: number]: AbnormalProcedure } = { level: 2, }, { - name: 'IF EVAC NOT RQRD :', + name: 'EVAC NOT RQRD :', sensed: true, - style: ChecklistLineStyle.Headline, - level: 2, + condition: true, + level: 1, }, { name: 'CABIN CREW', @@ -565,8 +556,7 @@ export const EcamAbnormalSensedAta26: { [n: number]: AbnormalProcedure } = { { name: 'WHEN ACFT STOPPED :', sensed: true, - style: ChecklistLineStyle.Headline, - level: 1, + condition: true, }, { name: 'PARK BRK', @@ -617,10 +607,10 @@ export const EcamAbnormalSensedAta26: { [n: number]: AbnormalProcedure } = { level: 1, }, { - name: 'IF EVAC RQRD :', + name: 'EVAC RQRD :', sensed: true, - style: ChecklistLineStyle.Headline, - level: 2, + condition: true, + level: 1, }, { name: 'EVAC (PA)', @@ -641,10 +631,10 @@ export const EcamAbnormalSensedAta26: { [n: number]: AbnormalProcedure } = { level: 2, }, { - name: 'IF EVAC NOT RQRD :', + name: 'EVAC NOT RQRD :', sensed: true, - style: ChecklistLineStyle.Headline, - level: 2, + condition: true, + level: 1, }, { name: 'CABIN CREW', @@ -724,7 +714,6 @@ export const EcamAbnormalSensedAta26: { [n: number]: AbnormalProcedure } = { name: 'SPEED', sensed: false, labelNotCompleted: 'REDUCE BELOW 250/.55', - level: 1, }, { name: 'L/G LEVER', @@ -755,7 +744,7 @@ export const EcamAbnormalSensedAta26: { [n: number]: AbnormalProcedure } = { { name: 'WHEN ACFT STOPPED :', sensed: false, - level: 1, + condition: true, }, { name: 'PARK BRK', @@ -782,9 +771,10 @@ export const EcamAbnormalSensedAta26: { [n: number]: AbnormalProcedure } = { level: 1, }, { - name: 'IF EVAC RQRD :', + name: 'EVAC RQRD :', sensed: false, - level: 2, + level: 1, + condition: true, }, { name: 'EVAC (PA)', @@ -811,9 +801,10 @@ export const EcamAbnormalSensedAta26: { [n: number]: AbnormalProcedure } = { level: 2, }, { - name: 'IF EVAC NOT RQRD :', + name: 'EVAC NOT RQRD :', sensed: false, - level: 2, + level: 1, + condition: true, }, { name: 'CABIN CREW', @@ -893,22 +884,22 @@ export const EcamAbnormalSensedAta26: { [n: number]: AbnormalProcedure } = { { name: 'IF NO LIFESTOCK :', sensed: false, - level: 1, + condition: true, }, { - name: 'FWD ISOL VALVES', + name: 'CARGO FWD ISOL VALVES', sensed: true, labelNotCompleted: 'OFF', level: 1, }, { - name: 'BULK ISOL VALVES', + name: 'CARGO BULK ISOL VALVES', sensed: true, labelNotCompleted: 'OFF', level: 1, }, { - name: 'BULK CARGO HEAT', + name: 'CARGO BULK CARGO HEAT', sensed: true, labelNotCompleted: 'OFF', level: 1, @@ -1066,7 +1057,6 @@ export const EcamAbnormalSensedAta26: { [n: number]: AbnormalProcedure } = { name: 'NSS MASTER', sensed: true, labelNotCompleted: 'OFF', - level: 1, }, { name: 'SIGNS', @@ -1079,9 +1069,9 @@ export const EcamAbnormalSensedAta26: { [n: number]: AbnormalProcedure } = { labelNotCompleted: 'ESTABLISH', }, { - name: 'IF SMOKE PERSISTS :', + name: 'SMOKE PERSISTS :', sensed: false, - level: 1, + condition: true, }, { name: '[QRH] SMOKE/FUMES PROC', @@ -1116,7 +1106,6 @@ export const EcamAbnormalSensedAta26: { [n: number]: AbnormalProcedure } = { name: 'NSS MASTER', sensed: true, labelNotCompleted: 'OFF', - level: 1, }, { name: 'SIGNS', @@ -1129,9 +1118,9 @@ export const EcamAbnormalSensedAta26: { [n: number]: AbnormalProcedure } = { labelNotCompleted: 'ESTABLISH', }, { - name: 'IF SMOKE PERSISTS :', + name: 'SMOKE PERSISTS :', sensed: false, - level: 1, + condition: true, }, { name: '[QRH] SMOKE/FUMES PROC', @@ -1181,7 +1170,7 @@ export const EcamAbnormalSensedAta26: { [n: number]: AbnormalProcedure } = { { name: 'IF FWD CRG CLOSED :', sensed: false, - level: 1, + condition: true, }, { name: 'AGENT TO FWD', @@ -1232,7 +1221,7 @@ export const EcamAbnormalSensedAta26: { [n: number]: AbnormalProcedure } = { { name: 'IF AFT+BULK CRG CLOSED :', sensed: false, - level: 1, + condition: true, }, { name: 'AGENT TO AFT', @@ -1283,7 +1272,7 @@ export const EcamAbnormalSensedAta26: { [n: number]: AbnormalProcedure } = { { name: 'IF AFT+BULK CRG CLOSED :', sensed: false, - level: 1, + condition: true, }, { name: 'AGENT TO AFT', @@ -1326,8 +1315,9 @@ export const EcamAbnormalSensedAta26: { [n: number]: AbnormalProcedure } = { sensed: true, items: [ { - name: 'IF NO LIVESTOCK', + name: 'NO LIVESTOCK', sensed: false, + condition: true, }, { name: 'FWD ISOL VALVES', @@ -1342,8 +1332,9 @@ export const EcamAbnormalSensedAta26: { [n: number]: AbnormalProcedure } = { sensed: true, items: [ { - name: 'IF NO LIVESTOCK', + name: 'NO LIVESTOCK', sensed: false, + condition: true, }, { name: 'BULK ISOL VALVES', @@ -1364,8 +1355,9 @@ export const EcamAbnormalSensedAta26: { [n: number]: AbnormalProcedure } = { sensed: true, items: [ { - name: 'IF NO LIVESTOCK', + name: 'NO LIVESTOCK', sensed: false, + condition: true, }, { name: 'BULK ISOL VALVES', @@ -1426,9 +1418,9 @@ export const EcamAbnormalSensedAta26: { [n: number]: AbnormalProcedure } = { labelNotCompleted: 'ESTABLISH', }, { - name: 'IF FIRE PERSISTS :', + name: 'FIRE PERSISTS :', sensed: false, - level: 1, + condition: true, }, { name: 'LAND ASAP', @@ -1525,7 +1517,6 @@ export const EcamAbnormalSensedAta26: { [n: number]: AbnormalProcedure } = { name: 'CAB FANS', sensed: true, labelNotCompleted: 'OFF', - level: 1, }, { name: 'CKPT / CABIN COM', diff --git a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata28.tsx b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata28.tsx index c806e65b666..79393df9398 100644 --- a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata28.tsx +++ b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata28.tsx @@ -1,7 +1,7 @@ // Copyright (c) 2024 FlyByWire Simulations // SPDX-License-Identifier: GPL-3.0 -import { AbnormalProcedure, ChecklistLineStyle } from 'instruments/src/MsfsAvionicsCommon/EcamMessages'; +import { AbnormalProcedure } from 'instruments/src/MsfsAvionicsCommon/EcamMessages'; // Convention for IDs: // First two digits: ATA chapter @@ -30,43 +30,36 @@ export const EcamAbnormalSensedAta28: { [n: number]: AbnormalProcedure } = { name: 'CROSSFEED 1+2+3+4', sensed: true, labelNotCompleted: 'ON', - level: 1, }, { name: 'ALL FEED TKs PMPs', sensed: true, labelNotCompleted: 'ON', - level: 1, }, { name: 'TRIM TK FEED', // If gravity transfer from the trim tank is in progress sensed: true, labelNotCompleted: 'AUTO', - level: 2, }, { name: 'OUTR TK XFR', // For transfer tanks containing fuel sensed: true, labelNotCompleted: 'MAN', - level: 2, }, { name: 'TRIM TK XFR', // If at least one trim tank pump is running sensed: true, labelNotCompleted: 'FWD', - level: 2, }, { name: 'INR TK XFR', sensed: true, labelNotCompleted: 'MAN', - level: 2, }, { name: 'MID TK XFR', sensed: true, labelNotCompleted: 'MAN', - level: 2, }, ], }, @@ -175,9 +168,9 @@ export const EcamAbnormalSensedAta28: { [n: number]: AbnormalProcedure } = { sensed: true, items: [ { - name: 'IF NO FUEL LEAK', + name: 'NO FUEL LEAK', sensed: true, - style: ChecklistLineStyle.SubHeadline, + condition: true, }, { name: 'CROSSFEED 1', @@ -195,31 +188,31 @@ export const EcamAbnormalSensedAta28: { [n: number]: AbnormalProcedure } = { name: 'TRIM TK FEED', // If gravity transfer from the trim tank is in progress sensed: true, labelNotCompleted: 'AUTO', - level: 2, + level: 1, }, { name: 'OUTR TK XFR', // For transfer tanks containing fuel: sensed: true, labelNotCompleted: 'MAN', - level: 2, + level: 1, }, { name: 'TRIM TK XFR', // If at least one trim tank pump is running sensed: true, labelNotCompleted: 'FWD', - level: 2, + level: 1, }, { name: 'INR TK XFR', sensed: true, labelNotCompleted: 'MAN', - level: 2, + level: 1, }, { name: 'MID TK XFR', sensed: true, labelNotCompleted: 'MAN', - level: 2, + level: 1, }, ], }, @@ -230,7 +223,7 @@ export const EcamAbnormalSensedAta28: { [n: number]: AbnormalProcedure } = { { name: 'IF NO FUEL LEAK', sensed: true, - style: ChecklistLineStyle.SubHeadline, + condition: true, }, { name: 'CROSSFEED 1', @@ -248,31 +241,31 @@ export const EcamAbnormalSensedAta28: { [n: number]: AbnormalProcedure } = { name: 'TRIM TK FEED', sensed: true, labelNotCompleted: 'AUTO', - level: 2, + level: 1, }, { name: 'OUTR TK XFR', sensed: true, labelNotCompleted: 'MAN', - level: 2, + level: 1, }, { name: 'TRIM TK XFR', sensed: true, labelNotCompleted: 'FWD', - level: 2, + level: 1, }, { name: 'INR TK XFR', sensed: true, labelNotCompleted: 'MAN', - level: 2, + level: 1, }, { name: 'MID TK XFR', sensed: true, labelNotCompleted: 'MAN', - level: 2, + level: 1, }, ], }, @@ -283,7 +276,7 @@ export const EcamAbnormalSensedAta28: { [n: number]: AbnormalProcedure } = { { name: 'IF NO FUEL LEAK', sensed: true, - style: ChecklistLineStyle.SubHeadline, + condition: true, }, { name: 'CROSSFEED 3', @@ -301,31 +294,31 @@ export const EcamAbnormalSensedAta28: { [n: number]: AbnormalProcedure } = { name: 'TRIM TK FEED', sensed: true, labelNotCompleted: 'AUTO', - level: 2, + level: 1, }, { name: 'OUTR TK XFR', sensed: true, labelNotCompleted: 'MAN', - level: 2, + level: 1, }, { name: 'TRIM TK XFR', sensed: true, labelNotCompleted: 'FWD', - level: 2, + level: 1, }, { name: 'INR TK XFR', sensed: true, labelNotCompleted: 'MAN', - level: 2, + level: 1, }, { name: 'MID TK XFR', sensed: true, labelNotCompleted: 'MAN', - level: 2, + level: 1, }, ], }, @@ -336,7 +329,7 @@ export const EcamAbnormalSensedAta28: { [n: number]: AbnormalProcedure } = { { name: 'IF NO FUEL LEAK', sensed: true, - style: ChecklistLineStyle.SubHeadline, + condition: true, }, { name: 'CROSSFEED 3', @@ -354,31 +347,31 @@ export const EcamAbnormalSensedAta28: { [n: number]: AbnormalProcedure } = { name: 'TRIM TK FEED', sensed: true, labelNotCompleted: 'AUTO', - level: 2, + level: 1, }, { name: 'OUTR TK XFR', sensed: true, labelNotCompleted: 'MAN', - level: 2, + level: 1, }, { name: 'TRIM TK XFR', sensed: true, labelNotCompleted: 'FWD', - level: 2, + level: 1, }, { name: 'INR TK XFR', sensed: true, labelNotCompleted: 'MAN', - level: 2, + level: 1, }, { name: 'MID TK XFR', sensed: true, labelNotCompleted: 'MAN', - level: 2, + level: 1, }, ], }, @@ -769,8 +762,9 @@ export const EcamAbnormalSensedAta28: { [n: number]: AbnormalProcedure } = { sensed: true, items: [ { - name: 'IF NO FUEL LEAK:', - sensed: true, + name: 'NO FUEL LEAK:', + sensed: false, + condition: true, }, { name: 'ALL CROSSFEEDs', @@ -782,31 +776,31 @@ export const EcamAbnormalSensedAta28: { [n: number]: AbnormalProcedure } = { name: 'TRIM TK FEED', // If gravity transfer from trim tank in progress sensed: true, labelNotCompleted: 'AUTO', - level: 3, + level: 1, }, { name: 'OUTR TK XFR', // For transfer tanks containing fuel sensed: true, labelNotCompleted: 'MAN', - level: 3, + level: 1, }, { name: 'TRIM TK XFR', // If at least one trim tank pump is running sensed: true, labelNotCompleted: 'FWD', - level: 4, + level: 1, }, { name: 'INR TK XFR', sensed: true, labelNotCompleted: 'MAN', - level: 3, + level: 1, }, { name: 'MID TK XFR', sensed: true, labelNotCompleted: 'MAN', - level: 3, + level: 1, }, ], }, @@ -815,8 +809,9 @@ export const EcamAbnormalSensedAta28: { [n: number]: AbnormalProcedure } = { sensed: true, items: [ { - name: 'IF NO FUEL LEAK:', - sensed: true, + name: 'NO FUEL LEAK:', + sensed: false, + condition: true, }, { name: 'ALL CROSSFEEDs', @@ -828,31 +823,31 @@ export const EcamAbnormalSensedAta28: { [n: number]: AbnormalProcedure } = { name: 'TRIM TK FEED', // If gravity transfer from trim tank in progress sensed: true, labelNotCompleted: 'AUTO', - level: 3, + level: 1, }, { name: 'OUTR TK XFR', // For transfer tanks containing fuel sensed: true, labelNotCompleted: 'MAN', - level: 3, + level: 1, }, { name: 'TRIM TK XFR', // If at least one trim tank pump is running sensed: true, labelNotCompleted: 'FWD', - level: 4, + level: 1, }, { name: 'INR TK XFR', sensed: true, labelNotCompleted: 'MAN', - level: 3, + level: 1, }, { name: 'MID TK XFR', sensed: true, labelNotCompleted: 'MAN', - level: 3, + level: 1, }, ], }, diff --git a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata29-30.tsx b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata29-30.tsx index 9632384fa01..f15e4e6e38a 100644 --- a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata29-30.tsx +++ b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata29-30.tsx @@ -235,6 +235,7 @@ export const EcamAbnormalSensedAta2930: { [n: number]: AbnormalProcedure } = { { name: 'IF G SYS PRESSURE FLUCTUATES', sensed: false, + condition: true, }, { name: 'G ENG 1 PMP A AND B', @@ -264,6 +265,7 @@ export const EcamAbnormalSensedAta2930: { [n: number]: AbnormalProcedure } = { { name: 'IF Y SYS PRESSURE FLUCTUATES', sensed: false, + condition: true, }, { name: 'Y ENG 3 PMP A AND B', @@ -287,7 +289,7 @@ export const EcamAbnormalSensedAta2930: { [n: number]: AbnormalProcedure } = { ], }, 290800021: { - title: '\x1b<4m\x1b4mHYD\x1bm G RSVR LEVEL LO', + title: '\x1b<4m\x1b4mHYD\x1bm G RSVR LEVEL LO', sensed: true, items: [ { @@ -320,7 +322,7 @@ export const EcamAbnormalSensedAta2930: { [n: number]: AbnormalProcedure } = { ], }, 290800022: { - title: '\x1b<4m\x1b4mHYD\x1bm Y RSVR LEVEL LO', + title: '\x1b<4m\x1b4mHYD\x1bm Y RSVR LEVEL LO', sensed: true, items: [ { @@ -373,12 +375,12 @@ export const EcamAbnormalSensedAta2930: { [n: number]: AbnormalProcedure } = { items: [], }, 290800027: { - title: '\x1b<4m\x1b4mHYD\x1bm G SYS COOLING FAULT', + title: '\x1b<4m\x1b4mHYD\x1bm G SYS COOLING FAULT', sensed: true, items: [], }, 290800028: { - title: '\x1b<4m\x1b4mHYD\x1bm Y SYS COOLING FAULT', + title: '\x1b<4m\x1b4mHYD\x1bm Y SYS COOLING FAULT', sensed: true, items: [], }, diff --git a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata34.tsx b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata34.tsx index ab122dbc03b..638c2d25ba9 100644 --- a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata34.tsx +++ b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata34.tsx @@ -36,14 +36,12 @@ export const EcamAbnormalSensedAta34: { [n: number]: AbnormalProcedure } = { name: 'BEFORE LAST ENG SHUTDOWN:', // After landing sensed: true, style: ChecklistLineStyle.Green, - level: 1, }, { name: 'IR 1 MODE SEL', sensed: true, style: ChecklistLineStyle.Green, labelNotCompleted: 'OFF', - level: 1, }, ], }, @@ -81,14 +79,12 @@ export const EcamAbnormalSensedAta34: { [n: number]: AbnormalProcedure } = { name: 'BEFORE LAST ENG SHUTDOWN:', // After landing sensed: true, style: ChecklistLineStyle.Green, - level: 1, }, { name: 'IR 3 MODE SEL', sensed: true, style: ChecklistLineStyle.Green, labelNotCompleted: 'OFF', - level: 1, }, ], }, @@ -115,32 +111,27 @@ export const EcamAbnormalSensedAta34: { [n: number]: AbnormalProcedure } = { name: 'WXR & TAWS', sensed: true, labelNotCompleted: 'SYS 1', - level: 1, }, { name: 'XDPR & TCAS', sensed: true, labelNotCompleted: 'SYS 1', - level: 1, }, { name: 'GA THR : TOGA ONLY', // If soft GA is lost sensed: true, style: ChecklistLineStyle.Cyan, - level: 1, }, { name: 'BEFORE LAST ENG SHUTDOWN:', // After landing sensed: true, style: ChecklistLineStyle.Green, - level: 1, }, { name: 'IR 1 MODE SEL', sensed: true, style: ChecklistLineStyle.Green, labelNotCompleted: 'OFF', - level: 1, }, ], }, @@ -167,32 +158,27 @@ export const EcamAbnormalSensedAta34: { [n: number]: AbnormalProcedure } = { name: 'WXR & TAWS', sensed: true, labelNotCompleted: 'SYS 2', - level: 1, }, { name: 'XDPR & TCAS', sensed: true, labelNotCompleted: 'SYS 2', - level: 1, }, { name: 'GA THR : TOGA ONLY', // If soft GA is lost sensed: true, style: ChecklistLineStyle.Cyan, - level: 1, }, { name: 'BEFORE LAST ENG SHUTDOWN:', // After landing sensed: true, style: ChecklistLineStyle.Green, - level: 1, }, { name: 'IR 1 MODE SEL', sensed: true, style: ChecklistLineStyle.Green, labelNotCompleted: 'OFF', - level: 1, }, ], }, @@ -219,32 +205,27 @@ export const EcamAbnormalSensedAta34: { [n: number]: AbnormalProcedure } = { name: 'WXR & TAWS', sensed: true, labelNotCompleted: 'SYS 1', - level: 1, }, { name: 'XDPR & TCAS', sensed: true, labelNotCompleted: 'SYS 1', - level: 1, }, { name: 'GA THR : TOGA ONLY', // If soft GA is lost sensed: true, style: ChecklistLineStyle.Cyan, - level: 1, }, { name: 'BEFORE LAST ENG SHUTDOWN:', // After landing sensed: true, style: ChecklistLineStyle.Green, - level: 1, }, { name: 'IR 3 MODE SEL', sensed: true, style: ChecklistLineStyle.Green, labelNotCompleted: 'OFF', - level: 1, }, ], }, diff --git a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/index.tsx b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/index.tsx index 03b5506529f..f3e8ae52838 100644 --- a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/index.tsx +++ b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/index.tsx @@ -563,18 +563,20 @@ export enum ChecklistLineStyle { SubHeadline = 'SubHeadline', SeparationLine = 'SeparationLine', ChecklistItem = 'ChecklistItem', + ChecklistItemInactive = 'ChecklistItemInactive', CompletedChecklist = 'CompletedChecklist', OmissionDots = 'OmissionDots', LandAsap = 'LandAsap', LandAnsa = 'LandAnsa', + ChecklistCondition = 'ChecklistCondition', } interface AbstractChecklistItem { - /** The name of the item, displayed at the beginning of the line. Does not accept special formatting tokens. No leading dot. */ + /** The name of the item, displayed at the beginning of the line. Does not accept special formatting tokens. No leading dot. For conditions, don't include the leading "IF" */ name: string; /** Sensed or not sensed item. Sensed items are automatically checked. Non-sensed items will have a checkbox drawn in front of them on the EWD */ sensed: boolean; - /** On which level of indentation to print the item. 0 equals the first level. Optional, not set means first level. */ + /** On which level of indentation to print the item. 0 equals the first level. Optional, not set means first level. Important for items subordinated to conditions. */ level?: number; /** Manually define style. standard (cyan when not completed, white/green when completed), or always cyan/green/amber. Standard, if not set. */ style?: ChecklistLineStyle; @@ -588,7 +590,20 @@ export interface ChecklistAction extends AbstractChecklistItem { colonIfCompleted?: boolean; } -interface ChecklistCondition extends AbstractChecklistItem {} +interface ChecklistCondition extends AbstractChecklistItem { + /** If this line is a condition. Can be sensed or not sensed (i.e. manually activated). */ + condition: true; +} + +interface ChecklistSpecialItem extends AbstractChecklistItem {} + +export function isChecklistAction(c: AbstractChecklistItem): c is ChecklistAction { + return (c as ChecklistAction).labelNotCompleted !== undefined; +} + +export function isChecklistCondition(c: AbstractChecklistItem): c is ChecklistCondition { + return (c as ChecklistCondition).condition !== undefined; +} export interface AbnormalProcedure { /** Title of the fault, e.g. "_HYD_ G SYS PRESS LO". \n produces second line. Accepts special formatting tokens */ @@ -596,7 +611,7 @@ export interface AbnormalProcedure { /** sensed or not sensed abnormal procedure */ sensed: boolean; /** An array of possible checklist items. */ - items: (ChecklistAction | ChecklistCondition)[]; + items: (ChecklistAction | ChecklistCondition | ChecklistSpecialItem)[]; /** LAND ASAP or LAND ANSA displayed below title? Optional, don't fill if no recommendation */ recommendation?: 'LAND ASAP' | 'LAND ANSA'; } @@ -610,10 +625,6 @@ export interface NormalProcedure { deferred?: boolean; } -export function isChecklistAction(element: ChecklistAction | ChecklistCondition): element is ChecklistAction { - return 'labelNotCompleted' in element; -} - /** All abnormal sensed procedures (alerts, via ECL) should be here. */ export const EcamAbnormalSensedProcedures: { [n: string]: AbnormalProcedure } = { ...EcamAbnormalSensedAta212223, diff --git a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsAbnormalSensed.ts b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsAbnormalSensed.ts index bb193e9e584..6e0149eff95 100644 --- a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsAbnormalSensed.ts +++ b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsAbnormalSensed.ts @@ -5,6 +5,7 @@ import { ChecklistLineStyle, EcamAbnormalSensedProcedures, + isChecklistCondition, WD_NUM_LINES, } from '../../../instruments/src/MsfsAvionicsCommon/EcamMessages'; import { @@ -183,12 +184,26 @@ export class FwsAbnormalSensed { .filter((v) => v !== null); } + getActualShownItems() { + const proc = EcamAbnormalSensedProcedures[this.activeProcedureId.get()]; + const lines = [...this.fws.activeAbnormalSensedList.getValue(this.activeProcedureId.get()).itemsToShow]; + proc.items.forEach((v, i) => { + if (isChecklistCondition(v) && !v.sensed) { + // CONFIRM line + lines.splice(i + 1, 0, lines[i]); + } + }); + if (proc.recommendation) { + lines.splice(0, 0, true); + } + return lines; + } + /** Returns the index from selectedItem amongst the displayed items */ private lineInDisplay(selectedItem: number) { return this.fws.activeAbnormalSensedList.has(this.activeProcedureId.get()) - ? this.fws.activeAbnormalSensedList - .getValue(this.activeProcedureId.get()) - .itemsToShow.map((value, index) => (value ? index : null)) + ? this.getActualShownItems() + .map((value, index) => (value ? index : null)) .filter(Boolean) .findIndex((v) => v === selectedItem) : -1; @@ -217,7 +232,7 @@ export class FwsAbnormalSensed { }; const proc = EcamAbnormalSensedProcedures[this.activeProcedureId.get()]; if ( - this.selectedItem.get() < clState.itemsChecked.length && + this.selectedItem.get() < this.getActualShownItems().length && proc.items[this.selectedItem.get()]?.sensed === false ) { clState.itemsChecked[this.selectedItem.get()] = !clState.itemsChecked[this.selectedItem.get()]; @@ -236,20 +251,13 @@ export class FwsAbnormalSensed { } private scrollToSelectedLine() { + const itemsShown = this.getActualShownItems(); if ( this.fws.activeAbnormalSensedList.has(this.activeProcedureId.get()) && - this.selectedItem.get() >= - this.fws.activeAbnormalSensedList.getValue(this.activeProcedureId.get()).itemsToShow.length + this.selectedItem.get() >= itemsShown.length ) { // CLEAR - this.showFromLine.set( - Math.max( - 0, - this.fws.activeAbnormalSensedList.getValue(this.activeProcedureId.get()).itemsToShow.length - - WD_NUM_LINES + - 2, - ), - ); + this.showFromLine.set(Math.max(0, itemsShown.length - WD_NUM_LINES + 2)); } else { this.showFromLine.set(Math.max(0, this.lineInDisplay(this.selectedItem.get()) - WD_NUM_LINES + 2)); } diff --git a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsCore.ts b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsCore.ts index fbd884f4e6e..c65fcd100db 100644 --- a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsCore.ts +++ b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsCore.ts @@ -39,6 +39,7 @@ import { AbnormalProcedure, EcamAbnormalSensedProcedures, EcamMemos, + isChecklistCondition, pfdMemoDisplay, } from '../../../instruments/src/MsfsAvionicsCommon/EcamMessages'; import PitchTrimUtils from '@shared/PitchTrimUtils'; @@ -3833,6 +3834,7 @@ export class FwsCore { const itemsChecked = value.whichItemsChecked().map((v, i) => (proc.items[i].sensed === false ? false : !!v)); const itemsToShow = value.whichItemsToShow ? value.whichItemsToShow() : Array(itemsChecked.length).fill(true); const itemsActive = value.whichItemsActive ? value.whichItemsActive() : Array(itemsChecked.length).fill(true); + this.conditionalActiveItems(proc, itemsChecked, itemsActive); if (newWarning) { failureKeys.push(key); @@ -3878,20 +3880,20 @@ export class FwsCore { } else if (this.activeAbnormalSensedList.has(key)) { // Update internal map const prevEl = this.activeAbnormalSensedList.getValue(key); + this.conditionalActiveItems(proc, prevEl.itemsChecked, itemsActive); this.abnormalUpdatedItems.set(key, []); proc.items.forEach((item, idx) => { - if (item.sensed === true) { - if ( - prevEl.itemsToShow[idx] !== itemsToShow[idx] || - prevEl.itemsActive[idx] !== itemsActive[idx] || - prevEl.itemsChecked[idx] !== itemsChecked[idx] - ) { - this.abnormalUpdatedItems.get(key).push(idx); - } + if ( + prevEl.itemsToShow[idx] !== itemsToShow[idx] || + prevEl.itemsActive[idx] !== itemsActive[idx] || + (prevEl.itemsChecked[idx] !== itemsChecked[idx] && item.sensed) + ) { + this.abnormalUpdatedItems.get(key).push(idx); } }); if (this.abnormalUpdatedItems.has(key) && this.abnormalUpdatedItems.get(key).length > 0) { + console.log(this.abnormalUpdatedItems); this.activeAbnormalSensedList.setValue(key, { id: key, itemsChecked: [...prevEl.itemsChecked].map((val, index) => @@ -4172,6 +4174,26 @@ export class FwsCore { this.autoPilotInstinctiveDiscCountSinceLastFwsCycle = 0; } + conditionalActiveItems(proc: AbnormalProcedure, itemsChecked: boolean[], itemsActive: boolean[]) { + // Additional logic for conditions: Modify itemsActive based on condition activation status + if (proc.items.some((v) => isChecklistCondition(v))) { + proc.items.forEach((v, i) => { + if (v.level) { + // Look for parent condition(s) + let active = true; + for (let recI = i; recI > 0; recI--) { + active = + (proc.items[recI].level ?? 0) < v.level && isChecklistCondition(proc.items[recI]) + ? itemsChecked[recI] + : active; + } + itemsActive[i] = active; + } + }); + } + return itemsActive; + } + updateRowRopWarnings() { const w = Arinc429Word.fromSimVarValue('L:A32NX_ROW_ROP_WORD_1'); From 3fa719c94f2c04b119c078c12d0a7ca5c7f5f332 Mon Sep 17 00:00:00 2001 From: Florian Gross <63071941+flogross89@users.noreply.github.com> Date: Sun, 8 Dec 2024 10:13:14 +0200 Subject: [PATCH 06/40] condition fixes --- .../elements/WdAbnormalSensedProcedures.tsx | 12 ++++-- .../EcamMessages/AbnormalSensed/ata26.tsx | 22 +++++------ .../FlightWarningSystem/FwsAbnormalSensed.ts | 38 ++++++++++--------- .../systems/FlightWarningSystem/FwsCore.ts | 14 +++---- 4 files changed, 47 insertions(+), 39 deletions(-) diff --git a/fbw-a380x/src/systems/instruments/src/EWD/elements/WdAbnormalSensedProcedures.tsx b/fbw-a380x/src/systems/instruments/src/EWD/elements/WdAbnormalSensedProcedures.tsx index bc872e7bf63..1f8d2e6a94e 100644 --- a/fbw-a380x/src/systems/instruments/src/EWD/elements/WdAbnormalSensedProcedures.tsx +++ b/fbw-a380x/src/systems/instruments/src/EWD/elements/WdAbnormalSensedProcedures.tsx @@ -71,9 +71,13 @@ export class WdAbnormalSensedProcedures extends WdAbstractChecklistComponent { } } else if (isChecklistCondition(item)) { clStyle = ChecklistLineStyle.ChecklistCondition; - text += procState.itemsChecked[itemIndex] - ? `.AS ${item.name.substring(0, 2) === 'IF' ? item.name.substring(2) : item.name}` - : `.IF ${item.name.substring(0, 2) === 'IF' ? item.name.substring(2) : item.name}`; + if (item.name.substring(0, 4) === 'WHEN') { + text += `.${item.name}`; + } else { + text += procState.itemsChecked[itemIndex] + ? `.AS ${item.name.substring(0, 2) === 'IF' ? item.name.substring(2) : item.name}` + : `.IF ${item.name.substring(0, 2) === 'IF' ? item.name.substring(2) : item.name}`; + } } else { text += item.name; } @@ -92,7 +96,7 @@ export class WdAbnormalSensedProcedures extends WdAbstractChecklistComponent { if (isChecklistCondition(item) && !item.sensed) { // Insert CONFIRM - const confirmText = `CONFIRM ${item.name}`; + const confirmText = `${item.level ? '\xa0'.repeat(item.level) : ''}CONFIRM ${item.name}`; this.lineData.push({ abnormalProcedure: true, activeProcedure: procIndex === 0, diff --git a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata26.tsx b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata26.tsx index be72870fda9..1683b2d7585 100644 --- a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata26.tsx +++ b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata26.tsx @@ -308,7 +308,7 @@ export const EcamAbnormalSensedAta26: { [n: number]: AbnormalProcedure } = { }, { name: 'EVAC RQRD :', - sensed: true, + sensed: false, condition: true, level: 1, }, @@ -332,7 +332,7 @@ export const EcamAbnormalSensedAta26: { [n: number]: AbnormalProcedure } = { }, { name: 'EVAC NOT RQRD :', - sensed: true, + sensed: false, condition: true, level: 1, }, @@ -408,7 +408,7 @@ export const EcamAbnormalSensedAta26: { [n: number]: AbnormalProcedure } = { }, { name: 'EVAC RQRD :', - sensed: true, + sensed: false, condition: true, level: 1, }, @@ -432,7 +432,7 @@ export const EcamAbnormalSensedAta26: { [n: number]: AbnormalProcedure } = { }, { name: 'EVAC NOT RQRD :', - sensed: true, + sensed: false, condition: true, level: 1, }, @@ -508,7 +508,7 @@ export const EcamAbnormalSensedAta26: { [n: number]: AbnormalProcedure } = { }, { name: 'EVAC RQRD :', - sensed: true, + sensed: false, condition: true, level: 1, }, @@ -532,7 +532,7 @@ export const EcamAbnormalSensedAta26: { [n: number]: AbnormalProcedure } = { }, { name: 'EVAC NOT RQRD :', - sensed: true, + sensed: false, condition: true, level: 1, }, @@ -608,7 +608,7 @@ export const EcamAbnormalSensedAta26: { [n: number]: AbnormalProcedure } = { }, { name: 'EVAC RQRD :', - sensed: true, + sensed: false, condition: true, level: 1, }, @@ -632,7 +632,7 @@ export const EcamAbnormalSensedAta26: { [n: number]: AbnormalProcedure } = { }, { name: 'EVAC NOT RQRD :', - sensed: true, + sensed: false, condition: true, level: 1, }, @@ -722,17 +722,17 @@ export const EcamAbnormalSensedAta26: { [n: number]: AbnormalProcedure } = { }, { name: 'L/G : KEEP DOWN', - sensed: false, + sensed: true, style: ChecklistLineStyle.Cyan, }, { name: 'ATC', - sensed: true, + sensed: false, labelNotCompleted: 'NOTIFY', }, { name: 'MAX SPEED : 250/.55', - sensed: false, + sensed: true, style: ChecklistLineStyle.Cyan, }, // On ground diff --git a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsAbnormalSensed.ts b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsAbnormalSensed.ts index 6e0149eff95..aff8543d2cc 100644 --- a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsAbnormalSensed.ts +++ b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsAbnormalSensed.ts @@ -184,28 +184,29 @@ export class FwsAbnormalSensed { .filter((v) => v !== null); } - getActualShownItems() { + private getActualShownItems() { const proc = EcamAbnormalSensedProcedures[this.activeProcedureId.get()]; - const lines = [...this.fws.activeAbnormalSensedList.getValue(this.activeProcedureId.get()).itemsToShow]; + const lines = [...this.fws.activeAbnormalSensedList.getValue(this.activeProcedureId.get()).itemsToShow] + .map((value, index) => (value ? index : null)) + .filter((v) => v !== null); proc.items.forEach((v, i) => { if (isChecklistCondition(v) && !v.sensed) { // CONFIRM line - lines.splice(i + 1, 0, lines[i]); + lines.splice(i, 0, lines[i]); + lines[i] = NaN; } }); if (proc.recommendation) { - lines.splice(0, 0, true); + lines.splice(0, 0, NaN); } + return lines; } /** Returns the index from selectedItem amongst the displayed items */ private lineInDisplay(selectedItem: number) { return this.fws.activeAbnormalSensedList.has(this.activeProcedureId.get()) - ? this.getActualShownItems() - .map((value, index) => (value ? index : null)) - .filter(Boolean) - .findIndex((v) => v === selectedItem) + ? this.getActualShownItems().findIndex((v) => v === selectedItem) : -1; } @@ -231,13 +232,15 @@ export class FwsAbnormalSensed { itemsActive: [...cl.itemsActive], }; const proc = EcamAbnormalSensedProcedures[this.activeProcedureId.get()]; - if ( - this.selectedItem.get() < this.getActualShownItems().length && - proc.items[this.selectedItem.get()]?.sensed === false - ) { + const procItem = proc.items[this.selectedItem.get()]; + if (this.selectedItem.get() < this.getActualShownItems().length && !procItem?.sensed) { clState.itemsChecked[this.selectedItem.get()] = !clState.itemsChecked[this.selectedItem.get()]; this.fws.activeAbnormalSensedList.setValue(this.activeProcedureId.get(), clState); if (clState.itemsChecked[this.selectedItem.get()]) { + if (isChecklistCondition(procItem) && procItem.condition) { + // Force 'active' status update + this.fws.conditionalActiveItems(proc, clState.itemsChecked, clState.itemsActive); + } this.moveDown(false); } } else if (this.selectedItem.get() === clState.itemsChecked.length) { @@ -252,9 +255,10 @@ export class FwsAbnormalSensed { private scrollToSelectedLine() { const itemsShown = this.getActualShownItems(); + const lastItemIndex = itemsShown[itemsShown.length - 1]; if ( this.fws.activeAbnormalSensedList.has(this.activeProcedureId.get()) && - this.selectedItem.get() >= itemsShown.length + this.selectedItem.get() === lastItemIndex + 1 ) { // CLEAR this.showFromLine.set(Math.max(0, itemsShown.length - WD_NUM_LINES + 2)); @@ -1898,7 +1902,7 @@ export class FwsAbnormalSensed { whichItemsChecked: () => [ // When the fire pb is released, the FADEC is not powered and the throttle position is unknown which resets this condition this.fws.allThrottleIdle.get() && !this.fws.fireButtonEng1.get(), - false, + this.fws.parkBrake.get(), this.fws.parkBrake.get(), false, false, @@ -1949,7 +1953,7 @@ export class FwsAbnormalSensed { whichItemsChecked: () => [ // When the fire pb is released, the FADEC is not powered and the throttle position is unknown which resets this condition this.fws.allThrottleIdle.get() && !this.fws.fireButtonEng2.get(), - false, + this.fws.parkBrake.get(), this.fws.parkBrake.get(), false, false, @@ -2000,7 +2004,7 @@ export class FwsAbnormalSensed { whichItemsChecked: () => [ // When the fire pb is released, the FADEC is not powered and the throttle position is unknown which resets this condition this.fws.allThrottleIdle.get() && !this.fws.fireButtonEng3.get(), - false, + this.fws.parkBrake.get(), this.fws.parkBrake.get(), false, false, @@ -2051,7 +2055,7 @@ export class FwsAbnormalSensed { whichItemsChecked: () => [ // When the fire pb is released, the FADEC is not powered and the throttle position is unknown which resets this condition this.fws.allThrottleIdle.get() && !this.fws.fireButtonEng4.get(), - false, + this.fws.parkBrake.get(), this.fws.parkBrake.get(), false, false, diff --git a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsCore.ts b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsCore.ts index c65fcd100db..b599d698e38 100644 --- a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsCore.ts +++ b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsCore.ts @@ -3880,25 +3880,25 @@ export class FwsCore { } else if (this.activeAbnormalSensedList.has(key)) { // Update internal map const prevEl = this.activeAbnormalSensedList.getValue(key); - this.conditionalActiveItems(proc, prevEl.itemsChecked, itemsActive); + const fusedChecked = [...prevEl.itemsChecked].map((val, index) => + proc.items[index].sensed ? itemsChecked[index] : !!val, + ); + this.conditionalActiveItems(proc, fusedChecked, itemsActive); this.abnormalUpdatedItems.set(key, []); proc.items.forEach((item, idx) => { if ( prevEl.itemsToShow[idx] !== itemsToShow[idx] || prevEl.itemsActive[idx] !== itemsActive[idx] || - (prevEl.itemsChecked[idx] !== itemsChecked[idx] && item.sensed) + (prevEl.itemsChecked[idx] !== fusedChecked[idx] && item.sensed) ) { this.abnormalUpdatedItems.get(key).push(idx); } }); if (this.abnormalUpdatedItems.has(key) && this.abnormalUpdatedItems.get(key).length > 0) { - console.log(this.abnormalUpdatedItems); this.activeAbnormalSensedList.setValue(key, { id: key, - itemsChecked: [...prevEl.itemsChecked].map((val, index) => - proc.items[index].sensed ? itemsChecked[index] : !!val, - ), + itemsChecked: fusedChecked, itemsActive: [...prevEl.itemsActive].map((_, index) => itemsActive[index]), itemsToShow: [...prevEl.itemsToShow].map((_, index) => itemsToShow[index]), }); @@ -4184,7 +4184,7 @@ export class FwsCore { for (let recI = i; recI > 0; recI--) { active = (proc.items[recI].level ?? 0) < v.level && isChecklistCondition(proc.items[recI]) - ? itemsChecked[recI] + ? active && itemsChecked[recI] : active; } itemsActive[i] = active; From 75b2cdfe0ce015c2db26df9fbd90a306683edb07 Mon Sep 17 00:00:00 2001 From: Florian Gross <63071941+flogross89@users.noreply.github.com> Date: Sun, 8 Dec 2024 10:19:56 +0200 Subject: [PATCH 07/40] INOP update --- fbw-a380x/README.md | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/fbw-a380x/README.md b/fbw-a380x/README.md index 0a64831b3f0..b8538ba7588 100644 --- a/fbw-a380x/README.md +++ b/fbw-a380x/README.md @@ -86,13 +86,10 @@ This list is divided into standardized ATA chapters, if there are no noteworthy - Vertical Display: Only fixed vertical range (until FL240) w/o FMS trajectory - Independent QNH - KCCU soft keyboard -- ECAM abnormal sensed: No navigation up/down, only CLEAR selectable for manual completion -- ECAM: Abnormal non-sensed procedures -- ECAM Deferred procedures -- ECAM ABN secondary failures - ECAM: Completely accurate STS page implementation - ECAM: AUTO RCL - ECAM: Correct behavior of RCL / RCL LAST +- ECAM: Time limited failures - Video: ETACS due to sim limitation - Latest FMA indications for landing modes (e.g. LAND3 instead of CAT3) - SD VIDEO page From f6b44312265d61716c45a50b02cdc823ca70d7f3 Mon Sep 17 00:00:00 2001 From: Florian Gross <63071941+flogross89@users.noreply.github.com> Date: Mon, 9 Dec 2024 07:53:52 +0200 Subject: [PATCH 08/40] add abnormal non sensed procedures --- .../src/systems/instruments/src/EWD/EWD.tsx | 23 ++- .../src/EWD/elements/WdAbnormalNonSensed.tsx | 185 ++++++++++++++++++ .../elements/WdAbstractChecklistComponent.tsx | 4 +- .../AbnormalNonSensedProcedures.tsx | 40 ++++ .../AbnormalSensed/ata21-22-23.tsx | 3 +- .../EcamMessages/AbnormalSensed/ata24.tsx | 3 +- .../EcamMessages/AbnormalSensed/ata26.tsx | 14 +- .../EcamMessages/AbnormalSensed/ata27.tsx | 28 ++- .../EcamMessages/AbnormalSensed/ata28.tsx | 18 +- .../EcamMessages/AbnormalSensed/ata29-30.tsx | 3 +- .../AbnormalSensed/ata31-32-33.tsx | 33 +++- .../EcamMessages/AbnormalSensed/ata34.tsx | 18 +- .../AbnormalSensed/ata35-36-42.tsx | 3 +- .../AbnormalSensed/ata46-49-52-56.tsx | 3 +- .../EcamMessages/AbnormalSensed/ata70.tsx | 13 +- .../AbnormalSensed/ata80-rest.tsx | 61 +++++- .../MsfsAvionicsCommon/EcamMessages/index.tsx | 20 +- .../providers/FwsEwdPublisher.ts | 12 ++ .../FwsAbnormalNonSensed.ts | 135 ++++++++++++- .../FlightWarningSystem/FwsAbnormalSensed.ts | 26 +-- .../systems/FlightWarningSystem/FwsCore.ts | 55 ++++-- 21 files changed, 636 insertions(+), 64 deletions(-) create mode 100644 fbw-a380x/src/systems/instruments/src/EWD/elements/WdAbnormalNonSensed.tsx create mode 100644 fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalNonSensedProcedures.tsx diff --git a/fbw-a380x/src/systems/instruments/src/EWD/EWD.tsx b/fbw-a380x/src/systems/instruments/src/EWD/EWD.tsx index fbd924265f3..a9124bfc16e 100644 --- a/fbw-a380x/src/systems/instruments/src/EWD/EWD.tsx +++ b/fbw-a380x/src/systems/instruments/src/EWD/EWD.tsx @@ -20,6 +20,7 @@ import { WdLimitations } from 'instruments/src/EWD/elements/WdLimitations'; import { WdNormalChecklists } from 'instruments/src/EWD/elements/WdNormalChecklists'; import { FwsEwdEvents } from 'instruments/src/MsfsAvionicsCommon/providers/FwsEwdPublisher'; import { WdAbnormalSensedProcedures } from 'instruments/src/EWD/elements/WdAbnormalSensedProcedures'; +import { WdAbnormalNonSensedProcedures } from 'instruments/src/EWD/elements/WdAbnormalNonSensed'; export class EngineWarningDisplay extends DisplayComponent<{ bus: ArincEventBus }> { private readonly sub = this.props.bus.getSubscriber(); @@ -57,15 +58,11 @@ export class EngineWarningDisplay extends DisplayComponent<{ bus: ArincEventBus Subject.create(false), ]; - private readonly normalChecklistsRequested = ConsumerSubject.create(this.sub.on('fws_show_normal_checklists'), false); + private readonly normalChecklistsVisible = ConsumerSubject.create(this.sub.on('fws_show_normal_checklists'), false); - private readonly abnormalSensedRequested = ConsumerSubject.create(this.sub.on('fws_show_abn_sensed'), false); + private readonly abnormalSensedVisible = ConsumerSubject.create(this.sub.on('fws_show_abn_sensed'), false); - private readonly abnormalSensedVisible = MappedSubject.create( - ([ecl, abn]) => abn && !ecl, - this.normalChecklistsRequested, - this.abnormalSensedRequested, - ); + private readonly abnormalNonSensedVisible = ConsumerSubject.create(this.sub.on('fws_show_abn_non_sensed'), false); // Todo: This logic should be handled by the FADEC private readonly engFirePb: ConsumerSubject[] = [ @@ -77,8 +74,9 @@ export class EngineWarningDisplay extends DisplayComponent<{ bus: ArincEventBus private readonly memosLimitationVisible = MappedSubject.create( SubscribableMapFunctions.nor(), - this.normalChecklistsRequested, - this.abnormalSensedRequested, + this.normalChecklistsVisible, + this.abnormalSensedVisible, + this.abnormalNonSensedVisible, ); private readonly failurePendingIndicationRequested = ConsumerSubject.create( @@ -237,8 +235,13 @@ export class EngineWarningDisplay extends DisplayComponent<{ bus: ArincEventBus
- + +
v.category === null).length + + EcamAbNormalSensedSubMenuVector.length; + + EcamAbnormalNonSensedProcedures.forEach((proc, index) => { + if (proc.category === null) { + this.lineData.push({ + activeProcedure: true, + abnormalProcedure: true, + sensed: true, + checked: false, + text: `\xa0\xa0${removeUnderline(EcamAbnormalSensedProcedures[proc.id].title)}`, + style: ChecklistLineStyle.Headline, + firstLine: false, + lastLine: index === numItems - 1, + originalItemIndex: index, + }); + } + }); + + EcamAbNormalSensedSubMenuVector.forEach((cat, index) => { + this.lineData.push({ + activeProcedure: true, + abnormalProcedure: true, + sensed: true, + checked: false, + text: `\xa0\xa0${cat ?? ''}`, + style: ChecklistLineStyle.Headline, + firstLine: false, + lastLine: index === EcamAbNormalSensedSubMenuVector.length - 1, + originalItemIndex: index + EcamAbnormalNonSensedProcedures.filter((v) => v.category === null).length, + }); + }); + } else if (this.checklistId.get() > 0 && this.checklistId.get() <= 10) { + const category = EcamAbNormalSensedSubMenuVector[this.checklistId.get() - 1]; + + // sub categories + this.lineData.push({ + activeProcedure: true, + abnormalProcedure: true, + sensed: true, + checked: false, + text: '\x1b4mABNORMAL PROC\x1bm', + style: ChecklistLineStyle.Headline, + firstLine: true, + lastLine: false, + }); + + this.lineData.push({ + activeProcedure: true, + abnormalProcedure: true, + sensed: true, + checked: false, + text: `\xa0\xa0\x1b4m${EcamAbNormalSensedSubMenuVector[this.checklistId.get() - 1]}\x1bm`, + style: ChecklistLineStyle.Headline, + firstLine: false, + lastLine: false, + }); + + const numItems = EcamAbnormalNonSensedProcedures.filter((v) => v.category === category).length; + EcamAbnormalNonSensedProcedures.filter((v) => v.category === category).forEach((proc, index) => { + this.lineData.push({ + activeProcedure: true, + abnormalProcedure: true, + sensed: true, + checked: false, + text: `\xa0\xa0\xa0\xa0${removeUnderline(EcamAbnormalSensedProcedures[proc.id].title)}`, + style: ChecklistLineStyle.Headline, + firstLine: false, + lastLine: index === numItems - 1, + originalItemIndex: index, + }); + }); + } else if (EcamAbnormalSensedProcedures[this.checklistId.get()]) { + const abn = EcamAbnormalSensedProcedures[this.checklistId.get()]; + + this.lineData.push({ + activeProcedure: true, + abnormalProcedure: true, + sensed: true, + checked: false, + text: abn.title, + style: ChecklistLineStyle.Headline, + firstLine: true, + lastLine: false, + }); + + this.lineData.push({ + activeProcedure: true, + abnormalProcedure: true, + sensed: false, + checked: false, + text: `${'\xa0'.repeat(31)}ACTIVATE`, + style: ChecklistLineStyle.ChecklistItem, + firstLine: false, + lastLine: abn.items.length === 0 ? true : false, + originalItemIndex: 0, + }); + + abn.items.forEach((item, index) => { + let text = item.level ? '\xa0'.repeat(item.level) : ''; + if (isChecklistAction(item)) { + text += '-'; + text += item.name; + if (item.labelNotCompleted) { + // Pad to 39 characters max + const paddingNeeded = Math.max( + 0, + 39 - (item.labelNotCompleted.length + item.name.length + (item.level ?? 0) * 1 + 2), + ); + + text += ` ${'.'.repeat(paddingNeeded)}${item.labelNotCompleted}`; + } + } else if (isChecklistCondition(item)) { + if (item.name.substring(0, 4) === 'WHEN') { + text += `.${item.name}`; + } else { + text += `.IF ${item.name.substring(0, 2) === 'IF' ? item.name.substring(2) : item.name}`; + } + } else { + text += item.name; + } + + this.lineData.push({ + activeProcedure: true, + abnormalProcedure: true, + sensed: item.sensed, + checked: false, + text: text.substring(0, 39), + style: ChecklistLineStyle.ChecklistItemInactive, + firstLine: false, + lastLine: index === abn.items.length - 1, + originalItemIndex: index + 1, + }); + }); + } + super.updateChecklists(); + } + + public onAfterRender(node: VNode): void { + super.onAfterRender(node); + + this.checklistId.sub(() => this.updateChecklists(), true); + } + + // 17 lines + render() { + return super.render(); + } +} diff --git a/fbw-a380x/src/systems/instruments/src/EWD/elements/WdAbstractChecklistComponent.tsx b/fbw-a380x/src/systems/instruments/src/EWD/elements/WdAbstractChecklistComponent.tsx index bc914f9cb05..00c06456a56 100644 --- a/fbw-a380x/src/systems/instruments/src/EWD/elements/WdAbstractChecklistComponent.tsx +++ b/fbw-a380x/src/systems/instruments/src/EWD/elements/WdAbstractChecklistComponent.tsx @@ -187,12 +187,12 @@ export class EclLine extends DisplayComponent { ), }} > - {this.props.data.map((d) => d.text)} + {this.props.data.map((d) => d.text.substring(0, 39))} diff --git a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalNonSensedProcedures.tsx b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalNonSensedProcedures.tsx new file mode 100644 index 00000000000..956443ba9e3 --- /dev/null +++ b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalNonSensedProcedures.tsx @@ -0,0 +1,40 @@ +// Copyright (c) 2024 FlyByWire Simulations +// SPDX-License-Identifier: GPL-3.0 + +import { AbnormalNonSensedList } from 'instruments/src/MsfsAvionicsCommon/providers/FwsEwdPublisher'; + +/** All normal procedures (checklists, via ECL) should be here. + * Display is ordered by ID, ascending. That's why keys need to be numbers. */ +export const AbnormalNonSensedProcedures: AbnormalNonSensedList[] = [ + { id: 260900097, category: null }, + { id: 990900006, category: null }, + { id: 990900005, category: null }, + { id: 990900004, category: null }, + { id: 990900007, category: null }, + { id: 340900003, category: null }, + { id: 700900001, category: 'ENG' }, + { id: 700900002, category: 'ENG' }, + { id: 270900001, category: 'F/CTL' }, + { id: 270900004, category: 'F/CTL' }, + { id: 270900005, category: 'F/CTL' }, + { id: 270900002, category: 'F/CTL' }, + { id: 270900003, category: 'F/CTL' }, + { id: 280900001, category: 'FUEL' }, + { id: 280900002, category: 'FUEL' }, + { id: 280900003, category: 'FUEL' }, + { id: 320900001, category: 'L/G' }, + { id: 320900002, category: 'L/G' }, + { id: 320900003, category: 'L/G' }, + { id: 320900004, category: 'L/G' }, + { id: 320900005, category: 'L/G' }, + { id: 320900006, category: 'L/G' }, + { id: 340900001, category: 'NAV' }, + { id: 340900002, category: 'NAV' }, + { id: 990900011, category: 'MISCELLANEOUS' }, + { id: 990900009, category: 'MISCELLANEOUS' }, + { id: 990900002, category: 'MISCELLANEOUS' }, + { id: 990900003, category: 'MISCELLANEOUS' }, + { id: 990900001, category: 'MISCELLANEOUS' }, + { id: 990900010, category: 'MISCELLANEOUS' }, + { id: 990900008, category: 'MISCELLANEOUS' }, +]; diff --git a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata21-22-23.tsx b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata21-22-23.tsx index 3b61413cbdf..32c050f07c2 100644 --- a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata21-22-23.tsx +++ b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata21-22-23.tsx @@ -11,7 +11,8 @@ import { AbnormalProcedure, ChecklistLineStyle } from 'instruments/src/MsfsAvion // 1 for normal checklists, // 2 for infos, // 3 for INOP SYS, -// 4 for limitations (not populated yet here), +// 4 for limitations, +// 7 for deferred procedures, // 8 for ABN sensed procedures, // 9 for ABN non-sensed procedures diff --git a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata24.tsx b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata24.tsx index 1f0a1314e4e..6444f923c63 100644 --- a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata24.tsx +++ b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata24.tsx @@ -11,7 +11,8 @@ import { AbnormalProcedure, ChecklistLineStyle } from 'instruments/src/MsfsAvion // 1 for normal checklists, // 2 for infos, // 3 for INOP SYS, -// 4 for limitations (not populated yet here), +// 4 for limitations, +// 7 for deferred procedures, // 8 for ABN sensed procedures, // 9 for ABN non-sensed procedures diff --git a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata26.tsx b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata26.tsx index 1683b2d7585..de99e58e266 100644 --- a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata26.tsx +++ b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata26.tsx @@ -11,7 +11,8 @@ import { AbnormalProcedure, ChecklistLineStyle } from 'instruments/src/MsfsAvion // 1 for normal checklists, // 2 for infos, // 3 for INOP SYS, -// 4 for limitations (not populated yet here), +// 4 for limitations, +// 7 for deferred procedures, // 8 for ABN sensed procedures, // 9 for ABN non-sensed procedures @@ -2016,8 +2017,8 @@ export const EcamAbnormalSensedAta26: { [n: number]: AbnormalProcedure } = { }, ], }, - 260800097: { - title: '\x1b<2m\x1b2mFIRE\x1bm SMOKE/FUMES', + 260900097: { + title: '\x1b<2m\x1b4mFIRE\x1bm SMOKE / FUMES', sensed: false, items: [ { @@ -2031,12 +2032,7 @@ export const EcamAbnormalSensedAta26: { [n: number]: AbnormalProcedure } = { labelNotCompleted: 'OFF', }, { - name: 'CKPT / CABIN COM', - sensed: false, - labelNotCompleted: 'ESTABLISH', - }, - { - name: 'GALLEY', + name: 'ELEC GALLEY', sensed: true, labelNotCompleted: 'OFF', }, diff --git a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata27.tsx b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata27.tsx index 6eb859333a2..35571882e70 100644 --- a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata27.tsx +++ b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata27.tsx @@ -11,7 +11,8 @@ import { AbnormalProcedure } from 'instruments/src/MsfsAvionicsCommon/EcamMessag // 1 for normal checklists, // 2 for infos, // 3 for INOP SYS, -// 4 for limitations (not populated yet here), +// 4 for limitations, +// 7 for deferred procedures, // 8 for ABN sensed procedures, // 9 for ABN non-sensed procedures @@ -540,4 +541,29 @@ export const EcamAbnormalSensedAta27: { [n: number]: AbnormalProcedure } = { sensed: true, items: [], }, + 270900001: { + title: '\x1b<4m\x1b4mF/CTL\x1bm RUDDER PEDAL JAMMED', + sensed: false, + items: [], // TODO + }, + 270900002: { + title: '\x1b<4m\x1b4mF/CTL\x1bm RUDDER TRIM RUNAWAY', + sensed: false, + items: [], // TODO + }, + 270900003: { + title: '\x1b<4m\x1b4mF/CTL\x1bm SPEED BRAKES LEVER JAMMED', + sensed: false, + items: [], // TODO + }, + 270900004: { + title: '\x1b<4m\x1b4mF/CTL\x1bm LDG WITH FLAPS LEVER JAMMED', + sensed: false, + items: [], // TODO + }, + 270900005: { + title: '\x1b<4m\x1b4mF/CTL\x1bm LDG WITH NO SLATS NO FLAPS', + sensed: false, + items: [], // TODO + }, }; diff --git a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata28.tsx b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata28.tsx index 79393df9398..fe62c102934 100644 --- a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata28.tsx +++ b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata28.tsx @@ -11,7 +11,8 @@ import { AbnormalProcedure } from 'instruments/src/MsfsAvionicsCommon/EcamMessag // 1 for normal checklists, // 2 for infos, // 3 for INOP SYS, -// 4 for limitations (not populated yet here), +// 4 for limitations, +// 7 for deferred procedures, // 8 for ABN sensed procedures, // 9 for ABN non-sensed procedures @@ -851,4 +852,19 @@ export const EcamAbnormalSensedAta28: { [n: number]: AbnormalProcedure } = { }, ], }, + 280900001: { + title: '\x1b<4m\x1b4mFUEL\x1bm JETTISON', + sensed: false, + items: [], // TODO + }, + 280900002: { + title: '\x1b<4m\x1b4mFUEL\x1bm FUEL LEAK', + sensed: false, + items: [], // TODO + }, + 280900003: { + title: '\x1b<4m\x1b4mFUEL\x1bm MAN BALANCING PROCEDURE', + sensed: false, + items: [], // TODO + }, }; diff --git a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata29-30.tsx b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata29-30.tsx index f15e4e6e38a..fd7da67f209 100644 --- a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata29-30.tsx +++ b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata29-30.tsx @@ -11,7 +11,8 @@ import { AbnormalProcedure, ChecklistLineStyle } from 'instruments/src/MsfsAvion // 1 for normal checklists, // 2 for infos, // 3 for INOP SYS, -// 4 for limitations (not populated yet here), +// 4 for limitations, +// 7 for deferred procedures, // 8 for ABN sensed procedures, // 9 for ABN non-sensed procedures diff --git a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata31-32-33.tsx b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata31-32-33.tsx index 51062752bf6..5763902b684 100644 --- a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata31-32-33.tsx +++ b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata31-32-33.tsx @@ -11,7 +11,8 @@ import { AbnormalProcedure, ChecklistLineStyle } from 'instruments/src/MsfsAvion // 1 for normal checklists, // 2 for infos, // 3 for INOP SYS, -// 4 for limitations (not populated yet here), +// 4 for limitations, +// 7 for deferred procedures, // 8 for ABN sensed procedures, // 9 for ABN non-sensed procedures @@ -1106,4 +1107,34 @@ export const EcamAbnormalSensedAta313233: { [n: number]: AbnormalProcedure } = { sensed: true, items: [], }, + 320900001: { + title: '\x1b<4m\x1b4mL/G\x1bm LDG WITH ABNORM NOSE L/G', + sensed: false, + items: [], // TODO + }, + 320900002: { + title: '\x1b<4m\x1b4mL/G\x1bm LDG WITH 2 ABNORM L/Gs ON SAME SIDE', + sensed: false, + items: [], // TODO + }, + 320900003: { + title: '\x1b<4m\x1b4mL/G\x1bm LDG WITH 1 ABNORM WING OR BODY L/G', + sensed: false, + items: [], // TODO + }, + 320900004: { + title: '\x1b<4m\x1b4mL/G\x1bm LDG WITH 2 ABNORM BODY L/Gs', + sensed: false, + items: [], // TODO + }, + 320900005: { + title: '\x1b<4m\x1b4mL/G\x1bm LDG WITH 2 ABNORM WING L/Gs', + sensed: false, + items: [], // TODO + }, + 320900006: { + title: '\x1b<4m\x1b4mWHEEL\x1bm TIRE DAMAGE SUSPECTED', + sensed: false, + items: [], // TODO + }, }; diff --git a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata34.tsx b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata34.tsx index 638c2d25ba9..b4e78bbf54f 100644 --- a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata34.tsx +++ b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata34.tsx @@ -11,7 +11,8 @@ import { AbnormalProcedure, ChecklistLineStyle } from 'instruments/src/MsfsAvion // 1 for normal checklists, // 2 for infos, // 3 for INOP SYS, -// 4 for limitations (not populated yet here), +// 4 for limitations, +// 7 for deferred procedures, // 8 for ABN sensed procedures, // 9 for ABN non-sensed procedures @@ -787,4 +788,19 @@ export const EcamAbnormalSensedAta34: { [n: number]: AbnormalProcedure } = { sensed: true, items: [], }, + 340900001: { + title: '\x1b<4m\x1b4mNAV\x1bm IR ALIGNMENT IN ATT MODE', + sensed: false, + items: [], // TODO + }, + 340900002: { + title: '\x1b<4m\x1b4mNAV\x1bm FLUCTUATING VERTICAL SPEED', + sensed: false, + items: [], // TODO + }, + 340900003: { + title: '\x1b<2m\x1b4mNAV\x1bm UNRELIABLE AIRSPEED INDICATION', + sensed: false, + items: [], // TODO + }, }; diff --git a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata35-36-42.tsx b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata35-36-42.tsx index 5e29da8534d..1e4ab2e7cfa 100644 --- a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata35-36-42.tsx +++ b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata35-36-42.tsx @@ -11,7 +11,8 @@ import { AbnormalProcedure } from 'instruments/src/MsfsAvionicsCommon/EcamMessag // 1 for normal checklists, // 2 for infos, // 3 for INOP SYS, -// 4 for limitations (not populated yet here), +// 4 for limitations, +// 7 for deferred procedures, // 8 for ABN sensed procedures, // 9 for ABN non-sensed procedures diff --git a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata46-49-52-56.tsx b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata46-49-52-56.tsx index fdf2d4f5762..035ca8189fd 100644 --- a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata46-49-52-56.tsx +++ b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata46-49-52-56.tsx @@ -11,7 +11,8 @@ import { AbnormalProcedure } from 'instruments/src/MsfsAvionicsCommon/EcamMessag // 1 for normal checklists, // 2 for infos, // 3 for INOP SYS, -// 4 for limitations (not populated yet here), +// 4 for limitations, +// 7 for deferred procedures, // 8 for ABN sensed procedures, // 9 for ABN non-sensed procedures diff --git a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata70.tsx b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata70.tsx index 7d6c5814363..74c5ff3355a 100644 --- a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata70.tsx +++ b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata70.tsx @@ -11,7 +11,8 @@ import { AbnormalProcedure } from 'instruments/src/MsfsAvionicsCommon/EcamMessag // 1 for normal checklists, // 2 for infos, // 3 for INOP SYS, -// 4 for limitations (not populated yet here), +// 4 for limitations, +// 7 for deferred procedures, // 8 for ABN sensed procedures, // 9 for ABN non-sensed procedures @@ -823,4 +824,14 @@ export const EcamAbnormalSensedAta70: { [n: number]: AbnormalProcedure } = { sensed: true, items: [], }, + 700900001: { + title: '\x1b<4m\x1b4mENG\x1bm RELIGHT IN FLIGHT', + sensed: false, + items: [], // TODO + }, + 700900002: { + title: '\x1b<4m\x1b4mENG\x1bm TAIL PIPE FIRE', + sensed: false, + items: [], // TODO + }, }; diff --git a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata80-rest.tsx b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata80-rest.tsx index 3769680ebf4..6ff1a37c208 100644 --- a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata80-rest.tsx +++ b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata80-rest.tsx @@ -11,9 +11,66 @@ import { AbnormalProcedure } from 'instruments/src/MsfsAvionicsCommon/EcamMessag // 1 for normal checklists, // 2 for infos, // 3 for INOP SYS, -// 4 for limitations (not populated yet here), +// 4 for limitations, +// 7 for deferred procedures, // 8 for ABN sensed procedures, // 9 for ABN non-sensed procedures /** All abnormal sensed procedures (alerts, via ECL) should be here. */ -export const EcamAbnormalSensedAta80Rest: { [n: number]: AbnormalProcedure } = {}; +export const EcamAbnormalSensedAta80Rest: { [n: number]: AbnormalProcedure } = { + 990900001: { + title: '\x1b<4m\x1b4mMISC\x1bm BOMB ON BOARD', + sensed: false, + items: [], // TODO + }, + 990900002: { + title: '\x1b<4m\x1b4mMISC\x1bm CKPT WINDOW CRACKED', + sensed: false, + items: [], // TODO + }, + 990900003: { + title: '\x1b<4m\x1b4mMISC\x1bm CKPT WINDOW ELEC ARCING', + sensed: false, + items: [], // TODO + }, + 990900004: { + title: '\x1b<2m\x1b4mMISC\x1bm DITCHING', + sensed: false, + items: [], // TODO + }, + 990900005: { + title: '\x1b<2m\x1b4mMISC\x1bm EMER DESCENT', + sensed: false, + items: [], // TODO + }, + 990900006: { + title: '\x1b<2m\x1b4mMISC\x1bm EMER EVAC', + sensed: false, + items: [], // TODO + }, + 990900007: { + title: '\x1b<2m\x1b4mMISC\x1bm FORCED LANDING', + sensed: false, + items: [], // TODO + }, + 990900008: { + title: '\x1b<4m\x1b4mMISC\x1bm OIS FAULT', + sensed: false, + items: [], // TODO + }, + 990900009: { + title: '\x1b<4m\x1b4mMISC\x1bm OVERWEIGHT LDG', + sensed: false, + items: [], // TODO + }, + 990900010: { + title: '\x1b<4m\x1b4mMISC\x1bm SEVERE TURBULENCE', + sensed: false, + items: [], // TODO + }, + 990900011: { + title: '\x1b<4m\x1b4mMISC\x1bm VOLCANIC ASH ENCOUNTER', + sensed: false, + items: [], // TODO + }, +}; diff --git a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/index.tsx b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/index.tsx index f3e8ae52838..a8c6fd90f6c 100644 --- a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/index.tsx +++ b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/index.tsx @@ -3,6 +3,7 @@ export const WD_NUM_LINES = 17; +import { AbnormalNonSensedProcedures } from 'instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalNonSensedProcedures'; import { EcamAbnormalSensedAta212223 } from 'instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata21-22-23'; import { EcamAbnormalSensedAta24 } from 'instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata24'; import { EcamAbnormalSensedAta26 } from 'instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata26'; @@ -15,6 +16,7 @@ import { EcamAbnormalSensedAta353642 } from 'instruments/src/MsfsAvionicsCommon/ import { EcamAbnormalSensedAta46495256 } from 'instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata46-49-52-56'; import { EcamAbnormalSensedAta70 } from 'instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata70'; import { EcamAbnormalSensedAta80Rest } from 'instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata80-rest'; +import { AbnormalNonSensedCategory } from 'instruments/src/MsfsAvionicsCommon/providers/FwsEwdPublisher'; // Convention for IDs: // First two digits: ATA chapter. 00 for T.O and LDG memos @@ -625,6 +627,13 @@ export interface NormalProcedure { deferred?: boolean; } +export interface AbnormalNonSensedProcedure { + /** Title of the checklist, e.g. "BEFORE START". */ + title: string; + /** An array of possible checklist items.. */ + items: ChecklistAction[]; +} + /** All abnormal sensed procedures (alerts, via ECL) should be here. */ export const EcamAbnormalSensedProcedures: { [n: string]: AbnormalProcedure } = { ...EcamAbnormalSensedAta212223, @@ -642,7 +651,16 @@ export const EcamAbnormalSensedProcedures: { [n: string]: AbnormalProcedure } = }; /** All abnormal non-sensed procedures (via ECL) should be here. Don't start for now, format needs to be defined. */ -export const EcamAbnormalNonSensedProcedures: { [n: string]: AbnormalProcedure } = {}; +export const EcamAbnormalNonSensedProcedures = AbnormalNonSensedProcedures; + +export const EcamAbNormalSensedSubMenuVector: AbnormalNonSensedCategory[] = [ + 'ENG', + 'F/CTL', + 'L/G', + 'NAV', + 'FUEL', + 'MISCELLANEOUS', +]; /** Used for one common representation of data defining the visual appearance of ECAM lines on the WD (for the ECL part) */ export interface WdLineData { diff --git a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/providers/FwsEwdPublisher.ts b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/providers/FwsEwdPublisher.ts index bb884e157c3..32ac6c86f0c 100644 --- a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/providers/FwsEwdPublisher.ts +++ b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/providers/FwsEwdPublisher.ts @@ -15,6 +15,13 @@ export interface NormalChecklistState { itemsCompleted: boolean[]; } +export type AbnormalNonSensedCategory = null | 'ENG' | 'F/CTL' | 'L/G' | 'NAV' | 'FUEL' | 'MISCELLANEOUS'; +export interface AbnormalNonSensedList { + /** Refers to abnormal proc id */ + id: number; + category: AbnormalNonSensedCategory; +} + /** * Transmitted from FWS to EWD */ @@ -36,6 +43,11 @@ export interface FwsEwdEvents { /** (FWS -> EWD) List of abnormal sensed procedures to be displayed */ fws_abn_sensed_procedures: FwsEwdAbnormalSensedEntry[]; + /** (FWS -> EWD) Show abnormal non-sensed procedures selection menu */ + fws_show_abn_non_sensed: boolean; + /** (FWS -> EWD) Which checklist to display. 0-10 special overview (sub-)pages, other IDs refer to the respective procedure */ + fws_abn_non_sensed_id: number; + /** (FWS -> EWD) Show FAILURE PENDING indication at bottom of page */ fws_show_failure_pending: boolean; /** (FWS -> EWD) Show STS indication at bottom of page */ diff --git a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsAbnormalNonSensed.ts b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsAbnormalNonSensed.ts index dd08e503a29..c1e46a73783 100644 --- a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsAbnormalNonSensed.ts +++ b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsAbnormalNonSensed.ts @@ -1,9 +1,138 @@ -// Copyright (c) 2021-2024 FlyByWire Simulations -// +// Copyright (c) 2024 FlyByWire Simulations // SPDX-License-Identifier: GPL-3.0 +import { MapSubject, SimVarValueType, Subject } from '@microsoft/msfs-sdk'; +import { NormalChecklistState, FwsEwdEvents } from 'instruments/src/MsfsAvionicsCommon/providers/FwsEwdPublisher'; import { FwsCore } from 'systems-host/systems/FlightWarningSystem/FwsCore'; +import { + EcamAbnormalNonSensedProcedures, + EcamAbNormalSensedSubMenuVector, + WD_NUM_LINES, +} from 'instruments/src/MsfsAvionicsCommon/EcamMessages'; +import { EwdAbnormalDict } from 'systems-host/systems/FlightWarningSystem/FwsAbnormalSensed'; +import { SdPages } from '@shared/EcamSystemPages'; export class FwsAbnormalNonSensed { - constructor(private fws: FwsCore) {} + private readonly pub = this.fws.bus.getPublisher(); + + public readonly abnProcShown = Subject.create(false); + + public readonly showAbnProcRequested = Subject.create(false); + + /** ID of checklist or 0 for overview, 1-10 for sub-menus, >10 for procedure preview */ + public readonly checklistId = Subject.create(0); + + /** Marked with cyan box */ + public readonly selectedItem = Subject.create(0); + + /** For overflowing checklists */ + public readonly showFromLine = Subject.create(0); + + public readonly checklistState = MapSubject.create(); + + constructor(private fws: FwsCore) { + this.checklistId.sub((id) => this.pub.pub('fws_abn_non_sensed_id', id, true), true); + } + + getAbnormalNonSensedMenuSize(): number { + if (this.checklistId.get() === 0) { + // Overview page + return ( + EcamAbnormalNonSensedProcedures.map((val) => (val.category === null ? 1 : 0) as number).reduce( + (accumulator, currentValue) => accumulator + currentValue, + ) + EcamAbNormalSensedSubMenuVector.length + ); + } else if (this.checklistId.get() > 0 && this.checklistId.get() <= EcamAbNormalSensedSubMenuVector.length) { + const category = EcamAbNormalSensedSubMenuVector[this.checklistId.get() - 1]; + return EcamAbnormalNonSensedProcedures.map((val) => (val.category === category ? 1 : 0) as number).reduce( + (accumulator, currentValue) => accumulator + currentValue, + ); + } + } + + moveUp() { + if (this.checklistId.get() <= 10) { + this.selectedItem.set(Math.max(this.selectedItem.get() - 1, 0)); + } + } + + moveDown() { + if (this.checklistId.get() <= 10) { + this.selectedItem.set(Math.min(this.selectedItem.get() + 1, this.getAbnormalNonSensedMenuSize() - 1)); + } + } + + update() { + if (this.fws.abnProcPulseNode.read()) { + this.checklistId.set(0); + this.selectedItem.set(0); + this.showAbnProcRequested.set(!this.showAbnProcRequested.get()); + } + + if (!this.abnProcShown.get()) { + return; + } + + if (this.fws.clDownPulseNode.read()) { + this.moveDown(); + } + + if (this.fws.clUpPulseNode.read()) { + this.moveUp(); + } + + if (this.fws.clCheckPulseNode.read()) { + if (this.checklistId.get() === 0) { + const skipProcsFromTopMenu = EcamAbnormalNonSensedProcedures.map( + (val) => (val.category === null ? 1 : 0) as number, + ).reduce((accumulator, currentValue) => accumulator + currentValue); + if ( + this.selectedItem.get() >= skipProcsFromTopMenu && + this.selectedItem.get() < this.getAbnormalNonSensedMenuSize() + ) { + // Call sub menu + this.checklistId.set(this.selectedItem.get() - skipProcsFromTopMenu + 1); + this.selectedItem.set(0); + } else if (this.selectedItem.get() < skipProcsFromTopMenu) { + // Preview non-sensed procedure + this.checklistId.set(EcamAbnormalNonSensedProcedures[this.selectedItem.get()]?.id ?? 0); + this.selectedItem.set(0); + } + } else if (this.checklistId.get() > 0 && this.checklistId.get() <= 10) { + // Sub menu + const subMenuProcsStartAt = EcamAbnormalNonSensedProcedures.findIndex( + (v) => v.category === EcamAbNormalSensedSubMenuVector[this.checklistId.get() - 1], + ); + // Preview non-sensed procedure + this.checklistId.set(EcamAbnormalNonSensedProcedures[subMenuProcsStartAt + this.selectedItem.get()].id); + this.selectedItem.set(0); + } else { + // Activate non-sensed procedure (add to ECAM faults) and close dialog, i.e. return to abnormal procs + this.fws.activeAbnormalNonSensedKeys.push(this.checklistId.get()); + this.selectedItem.set(0); + this.showAbnProcRequested.set(false); + } + } + } + + public ewdAbnormalNonSensed: EwdAbnormalDict = { + 260900097: { + // SMOKE / FUMES + flightPhaseInhib: [], + simVarIsActive: Subject.create(false), + notActiveWhenFaults: [], + whichItemsToShow: () => [true, true, true, true, true, true], + whichItemsChecked: () => [ + false, + !SimVar.GetSimVarValue('L:A32NX_OVHD_VENT_CAB_FANS_PB_IS_ON', SimVarValueType.Bool), + !SimVar.GetSimVarValue('L:A32NX_OVHD_ELEC_GALY_AND_CAB_PB_IS_AUTO', SimVarValueType.Bool), + !!this.fws.seatBelt.get(), + false, + false, + ], + failure: 1, + sysPage: SdPages.None, + redundLoss: () => [], + }, + }; } diff --git a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsAbnormalSensed.ts b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsAbnormalSensed.ts index aff8543d2cc..4eca646ad1e 100644 --- a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsAbnormalSensed.ts +++ b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsAbnormalSensed.ts @@ -76,7 +76,7 @@ export class FwsAbnormalSensed { public readonly showFromLine = Subject.create(0); constructor(private fws: FwsCore) { - this.fws.activeAbnormalSensedList.sub( + this.fws.activeAbnormalProceduresList.sub( ( map: ReadonlyMap, _type: SubscribableMapEventType, @@ -118,11 +118,11 @@ export class FwsAbnormalSensed { } getAbnormalProceduresKeysSorted() { - return Array.from(this.fws.activeAbnormalSensedList.get().keys()); + return Array.from(this.fws.activeAbnormalProceduresList.get().keys()); } selectFirst() { - const clState = this.fws.activeAbnormalSensedList.getValue(this.activeProcedureId.get()); + const clState = this.fws.activeAbnormalProceduresList.getValue(this.activeProcedureId.get()); const selectableAndNotChecked = this.selectableItems(false); this.selectedItem.set( selectableAndNotChecked[0] !== undefined ? selectableAndNotChecked[0] - 1 : clState.itemsChecked.length - 1, @@ -168,7 +168,7 @@ export class FwsAbnormalSensed { */ private itemIsSelectable(itemIndex: number, skipCompletedSensed: boolean): boolean { const procId = this.activeProcedureId.get(); - const clState = this.fws.activeAbnormalSensedList.getValue(this.activeProcedureId.get()); + const clState = this.fws.activeAbnormalProceduresList.getValue(this.activeProcedureId.get()); return ( (!EcamAbnormalSensedProcedures[procId].items[itemIndex].sensed || (!skipCompletedSensed && !clState.itemsChecked[itemIndex])) && @@ -186,7 +186,7 @@ export class FwsAbnormalSensed { private getActualShownItems() { const proc = EcamAbnormalSensedProcedures[this.activeProcedureId.get()]; - const lines = [...this.fws.activeAbnormalSensedList.getValue(this.activeProcedureId.get()).itemsToShow] + const lines = [...this.fws.activeAbnormalProceduresList.getValue(this.activeProcedureId.get()).itemsToShow] .map((value, index) => (value ? index : null)) .filter((v) => v !== null); proc.items.forEach((v, i) => { @@ -205,13 +205,13 @@ export class FwsAbnormalSensed { /** Returns the index from selectedItem amongst the displayed items */ private lineInDisplay(selectedItem: number) { - return this.fws.activeAbnormalSensedList.has(this.activeProcedureId.get()) + return this.fws.activeAbnormalProceduresList.has(this.activeProcedureId.get()) ? this.getActualShownItems().findIndex((v) => v === selectedItem) : -1; } moveDown(skipCompletedSensed = true) { - const numItems = this.fws.activeAbnormalSensedList.getValue(this.activeProcedureId.get()).itemsToShow.length; + const numItems = this.fws.activeAbnormalProceduresList.getValue(this.activeProcedureId.get()).itemsToShow.length; const selectable = this.selectableItems(skipCompletedSensed); if (selectable.length == 0 || this.selectedItem.get() >= selectable[selectable.length - 1]) { // Last element before CLEAR @@ -224,7 +224,7 @@ export class FwsAbnormalSensed { } checkCurrentItem() { - const cl = this.fws.activeAbnormalSensedList.getValue(this.activeProcedureId.get()); + const cl = this.fws.activeAbnormalProceduresList.getValue(this.activeProcedureId.get()); const clState: FwsEwdAbnormalSensedEntry = { id: cl.id, itemsToShow: [...cl.itemsToShow], @@ -235,7 +235,7 @@ export class FwsAbnormalSensed { const procItem = proc.items[this.selectedItem.get()]; if (this.selectedItem.get() < this.getActualShownItems().length && !procItem?.sensed) { clState.itemsChecked[this.selectedItem.get()] = !clState.itemsChecked[this.selectedItem.get()]; - this.fws.activeAbnormalSensedList.setValue(this.activeProcedureId.get(), clState); + this.fws.activeAbnormalProceduresList.setValue(this.activeProcedureId.get(), clState); if (clState.itemsChecked[this.selectedItem.get()]) { if (isChecklistCondition(procItem) && procItem.condition) { // Force 'active' status update @@ -257,7 +257,7 @@ export class FwsAbnormalSensed { const itemsShown = this.getActualShownItems(); const lastItemIndex = itemsShown[itemsShown.length - 1]; if ( - this.fws.activeAbnormalSensedList.has(this.activeProcedureId.get()) && + this.fws.activeAbnormalProceduresList.has(this.activeProcedureId.get()) && this.selectedItem.get() === lastItemIndex + 1 ) { // CLEAR @@ -272,7 +272,7 @@ export class FwsAbnormalSensed { * This block deals mostly with the pilot interaction through the ECAM CP and transmission to the CDS/EWD */ update() { - if (this.fws.activeAbnormalSensedList.get().size > 0) { + if (this.fws.activeAbnormalProceduresList.get().size > 0) { this.showAbnormalSensedRequested.set(true); } else { this.showAbnormalSensedRequested.set(false); @@ -308,7 +308,9 @@ export class FwsAbnormalSensed { if ( changedEntries && changedEntries.includes(this.selectedItem.get()) && - this.fws.activeAbnormalSensedList.getValue(this.activeProcedureId.get()).itemsChecked[this.selectedItem.get()] + this.fws.activeAbnormalProceduresList.getValue(this.activeProcedureId.get()).itemsChecked[ + this.selectedItem.get() + ] ) { this.moveDown(false); } diff --git a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsCore.ts b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsCore.ts index b599d698e38..f4cfca67053 100644 --- a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsCore.ts +++ b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsCore.ts @@ -207,6 +207,7 @@ export class FwsCore { public readonly clCheckInputBuffer = new NXLogicMemoryNode(false); public readonly clUpInputBuffer = new NXLogicMemoryNode(false); public readonly clDownInputBuffer = new NXLogicMemoryNode(false); + public readonly abnProcInputBuffer = new NXLogicMemoryNode(false); public readonly aThrDiscInputBuffer = new NXLogicMemoryNode(false); public readonly apDiscInputBuffer = new NXLogicMemoryNode(false); @@ -221,8 +222,11 @@ export class FwsCore { /** Keys/IDs of only the failures which are currently presented on the EWD */ public readonly presentedFailures: string[] = []; + /** Keys/IDs of the active abnormal non-sensed procedures */ + public readonly activeAbnormalNonSensedKeys: number[] = []; + /** Map to hold all failures which are currently active */ - public readonly activeAbnormalSensedList = MapSubject.create(); + public readonly activeAbnormalProceduresList = MapSubject.create(); /** Indices of items which were updated */ public readonly abnormalUpdatedItems = new Map(); @@ -1097,6 +1101,8 @@ export class FwsCore { public readonly clDownPulseNode = new NXLogicPulseNode(); + public readonly abnProcPulseNode = new NXLogicPulseNode(); + public readonly flightPhase3PulseNode = new NXLogicPulseNode(); public readonly flightPhaseEndedPulseNode = new NXLogicPulseNode(); @@ -1845,6 +1851,10 @@ export class FwsCore { this.clDownInputBuffer.write(true, false); } + if (SimVar.GetSimVarValue('L:A32NX_BTN_ABNPROC', 'bool')) { + this.abnProcInputBuffer.write(true, false); + } + // Enforce cycle time for the logic computation (otherwise pulse nodes would be broken) if (deltaTime === -1 || _deltaTime === 0) { return; @@ -1861,6 +1871,7 @@ export class FwsCore { this.clCheckPulseNode.write(this.clCheckInputBuffer.read(), deltaTime); this.clUpPulseNode.write(this.clUpInputBuffer.read(), deltaTime); this.clDownPulseNode.write(this.clDownInputBuffer.read(), deltaTime); + this.abnProcPulseNode.write(this.abnProcInputBuffer.read(), deltaTime); this.autoThrustInstinctiveDiscPressed.write(this.aThrDiscInputBuffer.read(), deltaTime); this.autoPilotInstinctiveDiscPressedPulse.write(this.apDiscInputBuffer.read(), deltaTime); @@ -3806,7 +3817,9 @@ export class FwsCore { this.nonCancellableWarningCount = 0; // Abnormal sensed procedures - const ewdAbnormalEntries: [string, EwdAbnormalItem][] = Object.entries(this.abnormalSensed.ewdAbnormalSensed); + const ewdAbnormalEntries: [string, EwdAbnormalItem][] = Object.entries( + this.abnormalSensed.ewdAbnormalSensed, + ).concat(Object.entries(this.abnormalNonSensed.ewdAbnormalNonSensed)); this.abnormalUpdatedItems.clear(); for (const [key, value] of ewdAbnormalEntries) { if (value.flightPhaseInhib.some((e) => e === flightPhase)) { @@ -3817,7 +3830,7 @@ export class FwsCore { const newWarning = !this.presentedFailures.includes(key) && !recallFailureKeys.includes(key); const proc = EcamAbnormalSensedProcedures[key] as AbnormalProcedure; - if (value.simVarIsActive.get()) { + if (value.simVarIsActive.get() || this.activeAbnormalNonSensedKeys.includes(parseInt(key))) { // Skip if other fault overrides this one let overridden = false; value.notActiveWhenFaults.forEach((val) => { @@ -3847,7 +3860,7 @@ export class FwsCore { } } - if (!this.activeAbnormalSensedList.has(key) && !this.recallFailures.includes(key)) { + if (!this.activeAbnormalProceduresList.has(key) && !this.recallFailures.includes(key)) { // Insert into internal map if (value.whichItemsActive) { if (proc.items.length !== value.whichItemsActive().length) { @@ -3871,15 +3884,15 @@ export class FwsCore { 'ECAM alert definition error: whichItemsChecked() not the same size as number of procedure items', ); } - this.activeAbnormalSensedList.setValue(key, { + this.activeAbnormalProceduresList.setValue(key, { id: key, itemsActive: itemsActive, itemsChecked: itemsChecked, itemsToShow: itemsToShow, }); - } else if (this.activeAbnormalSensedList.has(key)) { + } else if (this.activeAbnormalProceduresList.has(key)) { // Update internal map - const prevEl = this.activeAbnormalSensedList.getValue(key); + const prevEl = this.activeAbnormalProceduresList.getValue(key); const fusedChecked = [...prevEl.itemsChecked].map((val, index) => proc.items[index].sensed ? itemsChecked[index] : !!val, ); @@ -3896,7 +3909,7 @@ export class FwsCore { }); if (this.abnormalUpdatedItems.has(key) && this.abnormalUpdatedItems.get(key).length > 0) { - this.activeAbnormalSensedList.setValue(key, { + this.activeAbnormalProceduresList.setValue(key, { id: key, itemsChecked: fusedChecked, itemsActive: [...prevEl.itemsActive].map((_, index) => itemsActive[index]), @@ -3965,9 +3978,9 @@ export class FwsCore { } // Delete inactive failures from internal map - this.activeAbnormalSensedList.get().forEach((_, key) => { + this.activeAbnormalProceduresList.get().forEach((_, key) => { if (!allFailureKeys.includes(key.toString()) || this.recallFailures.includes(key)) { - this.activeAbnormalSensedList.delete(key); + this.activeAbnormalProceduresList.delete(key); } }); @@ -4131,22 +4144,31 @@ export class FwsCore { this.normalChecklists.update(); this.abnormalSensed.update(); + this.abnormalNonSensed.update(); this.updateRowRopWarnings(); // Orchestrate display of normal or abnormal proc display const pub = this.bus.getPublisher(); - if (this.normalChecklists.showChecklistRequested.get()) { + if (this.abnormalNonSensed.showAbnProcRequested.get()) { + // ABN PROC always shown + this.abnormalNonSensed.abnProcShown.set(true); + this.normalChecklists.checklistShown.set(false); + this.abnormalSensed.abnormalShown.set(false); + + pub.pub('fws_active_line', this.abnormalNonSensed.selectedItem.get(), true); + pub.pub('fws_show_from_line', this.abnormalNonSensed.showFromLine.get(), true); + this.ecamEwdShowFailurePendingIndication.set(false); + } else if (this.normalChecklists.showChecklistRequested.get()) { // ECL always shown + this.abnormalNonSensed.abnProcShown.set(false); this.normalChecklists.checklistShown.set(true); this.abnormalSensed.abnormalShown.set(false); pub.pub('fws_active_line', this.normalChecklists.selectedLine.get(), true); pub.pub('fws_show_from_line', this.normalChecklists.showFromLine.get(), true); this.ecamEwdShowFailurePendingIndication.set(this.abnormalSensed.showAbnormalSensedRequested.get()); - } else if ( - this.abnormalSensed.showAbnormalSensedRequested.get() && - !this.normalChecklists.showChecklistRequested.get() - ) { + } else if (this.abnormalSensed.showAbnormalSensedRequested.get()) { + this.abnormalNonSensed.abnProcShown.set(false); this.normalChecklists.checklistShown.set(false); this.abnormalSensed.abnormalShown.set(true); @@ -4154,10 +4176,12 @@ export class FwsCore { pub.pub('fws_show_from_line', this.abnormalSensed.showFromLine.get(), true); this.ecamEwdShowFailurePendingIndication.set(false); } else { + this.abnormalNonSensed.abnProcShown.set(false); this.normalChecklists.checklistShown.set(false); this.abnormalSensed.abnormalShown.set(false); this.ecamEwdShowFailurePendingIndication.set(false); } + pub.pub('fws_show_abn_non_sensed', this.abnormalNonSensed.abnProcShown.get(), true); pub.pub('fws_show_abn_sensed', this.abnormalSensed.abnormalShown.get(), true); pub.pub('fws_show_normal_checklists', this.normalChecklists.checklistShown.get(), true); @@ -4169,6 +4193,7 @@ export class FwsCore { this.clCheckInputBuffer.write(false, true); this.clUpInputBuffer.write(false, true); this.clDownInputBuffer.write(false, true); + this.abnProcInputBuffer.write(false, true); this.aThrDiscInputBuffer.write(false, true); this.apDiscInputBuffer.write(false, true); this.autoPilotInstinctiveDiscCountSinceLastFwsCycle = 0; From f2d3c1c34558dd52902b6aef925af69a6e1914d9 Mon Sep 17 00:00:00 2001 From: Florian Gross <63071941+flogross89@users.noreply.github.com> Date: Tue, 10 Dec 2024 04:32:40 +0200 Subject: [PATCH 09/40] deferred procs pt 1 --- .../AbnormalSensed/ata21-22-23.tsx | 27 ++++++++++++++- .../EcamMessages/AbnormalSensed/ata34.tsx | 16 ++++++++- .../MsfsAvionicsCommon/EcamMessages/index.tsx | 26 +++++++++++++- .../FlightWarningSystem/FwsAbnormalSensed.ts | 12 +++++++ .../systems/FlightWarningSystem/FwsCore.ts | 34 ++++++++++++++++++- 5 files changed, 111 insertions(+), 4 deletions(-) diff --git a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata21-22-23.tsx b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata21-22-23.tsx index 32c050f07c2..ac57d68f233 100644 --- a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata21-22-23.tsx +++ b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata21-22-23.tsx @@ -1,7 +1,12 @@ // Copyright (c) 2024 FlyByWire Simulations // SPDX-License-Identifier: GPL-3.0 -import { AbnormalProcedure, ChecklistLineStyle } from 'instruments/src/MsfsAvionicsCommon/EcamMessages'; +import { + AbnormalProcedure, + ChecklistLineStyle, + DeferredProcedure, + DeferredProcedureType, +} from 'instruments/src/MsfsAvionicsCommon/EcamMessages'; // Convention for IDs: // First two digits: ATA chapter @@ -2120,3 +2125,23 @@ export const EcamAbnormalSensedAta212223: { [n: number]: AbnormalProcedure } = { items: [], }, }; + +export const EcamDeferredProcAta212223: { [n: number]: DeferredProcedure } = { + 221700001: { + fromAbnormalProc: '221800006', + title: '\x1b<4mLDG ELEVN', + type: DeferredProcedureType.AT_TOP_OF_DESCENT, + items: [ + { + name: 'CABIN ALT MODE', + sensed: false, + labelNotCompleted: 'MAN', + }, + { + name: 'CABIN ALT TRGT', + sensed: false, + labelNotCompleted: 'LDG ELEVN', + }, + ], + }, +}; diff --git a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata34.tsx b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata34.tsx index b4e78bbf54f..0dae04f5ced 100644 --- a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata34.tsx +++ b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata34.tsx @@ -1,7 +1,12 @@ // Copyright (c) 2024 FlyByWire Simulations // SPDX-License-Identifier: GPL-3.0 -import { AbnormalProcedure, ChecklistLineStyle } from 'instruments/src/MsfsAvionicsCommon/EcamMessages'; +import { + AbnormalProcedure, + ChecklistLineStyle, + DeferredProcedure, + DeferredProcedureType, +} from 'instruments/src/MsfsAvionicsCommon/EcamMessages'; // Convention for IDs: // First two digits: ATA chapter @@ -804,3 +809,12 @@ export const EcamAbnormalSensedAta34: { [n: number]: AbnormalProcedure } = { items: [], // TODO }, }; + +export const EcamDeferredProcAta34: { [n: number]: DeferredProcedure } = { + 340700001: { + fromAbnormalProc: '340800008', + title: '\x1b<4mLDG ELEVN', + type: DeferredProcedureType.AT_TOP_OF_DESCENT, + items: [], + }, +}; diff --git a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/index.tsx b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/index.tsx index a8c6fd90f6c..9d64bda5960 100644 --- a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/index.tsx +++ b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/index.tsx @@ -4,7 +4,10 @@ export const WD_NUM_LINES = 17; import { AbnormalNonSensedProcedures } from 'instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalNonSensedProcedures'; -import { EcamAbnormalSensedAta212223 } from 'instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata21-22-23'; +import { + EcamAbnormalSensedAta212223, + EcamDeferredProcAta212223, +} from 'instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata21-22-23'; import { EcamAbnormalSensedAta24 } from 'instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata24'; import { EcamAbnormalSensedAta26 } from 'instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata26'; import { EcamAbnormalSensedAta27 } from 'instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata27'; @@ -634,6 +637,22 @@ export interface AbnormalNonSensedProcedure { items: ChecklistAction[]; } +export enum DeferredProcedureType { + ALL_PHASES, + AT_TOP_OF_DESCENT, + FOR_APPROACH, + FOR_LANDING, +} +export interface DeferredProcedure { + /** Which abnormal procedure triggers this deferred procedure */ + fromAbnormalProc: string; + /** Title of the fault, e.g. "_HYD_ G SYS PRESS LO". \n produces second line. Accepts special formatting tokens */ + title: string; + /** An array of possible checklist items. */ + items: (ChecklistAction | ChecklistCondition | ChecklistSpecialItem)[]; + type: DeferredProcedureType; +} + /** All abnormal sensed procedures (alerts, via ECL) should be here. */ export const EcamAbnormalSensedProcedures: { [n: string]: AbnormalProcedure } = { ...EcamAbnormalSensedAta212223, @@ -662,6 +681,11 @@ export const EcamAbNormalSensedSubMenuVector: AbnormalNonSensedCategory[] = [ 'MISCELLANEOUS', ]; +/** All abnormal sensed procedures (alerts, via ECL) should be here. */ +export const EcamDeferredProcedures: { [n: string]: DeferredProcedure } = { + ...EcamDeferredProcAta212223, +}; + /** Used for one common representation of data defining the visual appearance of ECAM lines on the WD (for the ECL part) */ export interface WdLineData { activeProcedure: boolean; diff --git a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsAbnormalSensed.ts b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsAbnormalSensed.ts index 4eca646ad1e..f6568d0381a 100644 --- a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsAbnormalSensed.ts +++ b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsAbnormalSensed.ts @@ -3567,4 +3567,16 @@ export class FwsAbnormalSensed { sysPage: -1, }, }; + + public ewdDeferredProcs: EwdAbnormalDict = { + 221700001: { + flightPhaseInhib: [], + simVarIsActive: Subject.create(true), + notActiveWhenFaults: [], + whichItemsToShow: () => [], + whichItemsChecked: () => [], + failure: 0, + sysPage: SdPages.None, + }, + }; } diff --git a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsCore.ts b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsCore.ts index f4cfca67053..53289f899f8 100644 --- a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsCore.ts +++ b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsCore.ts @@ -38,6 +38,7 @@ import { FuelSystemEvents } from 'instruments/src/MsfsAvionicsCommon/providers/F import { AbnormalProcedure, EcamAbnormalSensedProcedures, + EcamDeferredProcedures, EcamMemos, isChecklistCondition, pfdMemoDisplay, @@ -228,6 +229,9 @@ export class FwsCore { /** Map to hold all failures which are currently active */ public readonly activeAbnormalProceduresList = MapSubject.create(); + /** Map to hold all deferred procs which are currently active */ + public readonly activeDeferredProceduresList = MapSubject.create(); + /** Indices of items which were updated */ public readonly abnormalUpdatedItems = new Map(); @@ -3820,6 +3824,7 @@ export class FwsCore { const ewdAbnormalEntries: [string, EwdAbnormalItem][] = Object.entries( this.abnormalSensed.ewdAbnormalSensed, ).concat(Object.entries(this.abnormalNonSensed.ewdAbnormalNonSensed)); + const ewdDeferredEntries = Object.entries(this.abnormalSensed.ewdDeferredProcs); this.abnormalUpdatedItems.clear(); for (const [key, value] of ewdAbnormalEntries) { if (value.flightPhaseInhib.some((e) => e === flightPhase)) { @@ -3890,6 +3895,24 @@ export class FwsCore { itemsChecked: itemsChecked, itemsToShow: itemsToShow, }); + + for (const [deferredKey, deferredValue] of ewdDeferredEntries) { + if ( + EcamDeferredProcedures[deferredKey].fromAbnormalProc === key && + this.abnormalSensed.ewdDeferredProcs[deferredKey] + ) { + this.activeDeferredProceduresList.setValue(deferredKey, { + id: key, + itemsActive: deferredValue.whichItemsActive(), + itemsChecked: deferredValue.whichItemsChecked + ? deferredValue.whichItemsChecked() + : Array(deferredValue.whichItemsActive().length).fill(true), + itemsToShow: deferredValue.whichItemsToShow + ? deferredValue.whichItemsToShow() + : Array(deferredValue.whichItemsActive().length).fill(true), + }); + } + } } else if (this.activeAbnormalProceduresList.has(key)) { // Update internal map const prevEl = this.activeAbnormalProceduresList.getValue(key); @@ -3979,9 +4002,18 @@ export class FwsCore { // Delete inactive failures from internal map this.activeAbnormalProceduresList.get().forEach((_, key) => { - if (!allFailureKeys.includes(key.toString()) || this.recallFailures.includes(key)) { + if (!allFailureKeys.includes(key) || this.recallFailures.includes(key)) { this.activeAbnormalProceduresList.delete(key); } + + if (!allFailureKeys.includes(key) && !this.recallFailures.includes(key)) { + // Delete associated deferred procedure + for (const [deferredKey, _] of ewdDeferredEntries) { + if (EcamDeferredProcedures[deferredKey].fromAbnormalProc === key) { + this.activeDeferredProceduresList.delete(key); + } + } + } }); this.auralCrcKeys = auralCrcKeys; From d102e78117bdf57b5fe6d3cadf02fac1ce426b79 Mon Sep 17 00:00:00 2001 From: Florian Gross <63071941+flogross89@users.noreply.github.com> Date: Thu, 12 Dec 2024 05:39:25 +0200 Subject: [PATCH 10/40] deferred pt 2 --- .../src/systems/instruments/src/EWD/EWD.tsx | 9 +- .../src/EWD/elements/WdNormalChecklists.tsx | 122 +++++++++++++++++- .../systems/instruments/src/EWD/style.scss | 18 +++ .../AbnormalSensed/ata21-22-23.tsx | 2 +- .../MsfsAvionicsCommon/EcamMessages/index.tsx | 2 + .../providers/FwsEwdPublisher.ts | 12 ++ .../FlightWarningSystem/FwsAbnormalSensed.ts | 32 ++++- .../systems/FlightWarningSystem/FwsCore.ts | 55 +++++++- 8 files changed, 241 insertions(+), 11 deletions(-) diff --git a/fbw-a380x/src/systems/instruments/src/EWD/EWD.tsx b/fbw-a380x/src/systems/instruments/src/EWD/EWD.tsx index a9124bfc16e..dfd29938946 100644 --- a/fbw-a380x/src/systems/instruments/src/EWD/EWD.tsx +++ b/fbw-a380x/src/systems/instruments/src/EWD/EWD.tsx @@ -86,6 +86,8 @@ export class EngineWarningDisplay extends DisplayComponent<{ bus: ArincEventBus private readonly stsIndicationRequested = ConsumerSubject.create(this.sub.on('fws_show_sts_indication'), false); + private readonly advIndicationRequested = ConsumerSubject.create(this.sub.on('fws_show_adv_indication'), false); + public onAfterRender(node: VNode): void { super.onAfterRender(node); } @@ -255,8 +257,13 @@ export class EngineWarningDisplay extends DisplayComponent<{ bus: ArincEventBus > STS
+
(s ? 'visible' : 'hidden')) }} + > + ADV +
- {/* Reserved for STS */}
diff --git a/fbw-a380x/src/systems/instruments/src/EWD/elements/WdNormalChecklists.tsx b/fbw-a380x/src/systems/instruments/src/EWD/elements/WdNormalChecklists.tsx index 105c6f836df..97f27525125 100644 --- a/fbw-a380x/src/systems/instruments/src/EWD/elements/WdNormalChecklists.tsx +++ b/fbw-a380x/src/systems/instruments/src/EWD/elements/WdNormalChecklists.tsx @@ -1,13 +1,31 @@ import { ConsumerSubject, FSComponent, VNode } from '@microsoft/msfs-sdk'; import { EcamNormalProcedures } from 'instruments/src/MsfsAvionicsCommon/EcamMessages/NormalProcedures'; -import { ChecklistLineStyle } from 'instruments/src/MsfsAvionicsCommon/EcamMessages'; +import { + ChecklistLineStyle, + DeferredProcedureType, + EcamDeferredProcedures, +} from 'instruments/src/MsfsAvionicsCommon/EcamMessages'; import { WdAbstractChecklistComponent } from 'instruments/src/EWD/elements/WdAbstractChecklistComponent'; export class WdNormalChecklists extends WdAbstractChecklistComponent { private readonly checklists = ConsumerSubject.create(this.sub.on('fws_normal_checklists'), []); + /** Special indices: + * -1 : all phases + * -2 : at top of descent + * -3 : for approach + * -4 : for landing + */ private readonly checklistId = ConsumerSubject.create(this.sub.on('fws_normal_checklists_id'), 0); + private readonly deferred = ConsumerSubject.create(this.sub.on('fws_deferred_procedures'), []); + + /** ALL PHASES, TOP OF DESCENT, FOR APPROACH, FOR LANDING */ + private readonly hasDeferred = [false, false, false, false]; + + /** ALL PHASES, TOP OF DESCENT, FOR APPROACH, FOR LANDING */ + private readonly deferredIsCompleted = [false, false, false, false]; + public updateChecklists() { this.lineData.length = 0; @@ -17,6 +35,39 @@ export class WdNormalChecklists extends WdAbstractChecklistComponent { .sort((a, b) => a.id - b.id); const clState = sorted.find((v) => v.id === this.checklistId.get()); + if (this.deferred.get().length > 0) { + // Status of deferred procedures + this.hasDeferred[0] = this.deferred + .get() + .some((p) => EcamDeferredProcedures[p.id]?.type === DeferredProcedureType.ALL_PHASES); + this.hasDeferred[1] = this.deferred + .get() + .some((p) => EcamDeferredProcedures[p.id]?.type === DeferredProcedureType.AT_TOP_OF_DESCENT); + this.hasDeferred[2] = this.deferred + .get() + .some((p) => EcamDeferredProcedures[p.id]?.type === DeferredProcedureType.FOR_APPROACH); + this.hasDeferred[3] = this.deferred + .get() + .some((p) => EcamDeferredProcedures[p.id]?.type === DeferredProcedureType.FOR_LANDING); + + this.deferredIsCompleted[0] = this.deferred + .get() + .every((p) => EcamDeferredProcedures[p.id]?.type === DeferredProcedureType.ALL_PHASES && p.checklistCompleted); + this.deferredIsCompleted[1] = this.deferred + .get() + .every( + (p) => EcamDeferredProcedures[p.id]?.type === DeferredProcedureType.AT_TOP_OF_DESCENT && p.checklistCompleted, + ); + this.deferredIsCompleted[2] = this.deferred + .get() + .every( + (p) => EcamDeferredProcedures[p.id]?.type === DeferredProcedureType.FOR_APPROACH && p.checklistCompleted, + ); + this.deferredIsCompleted[3] = this.deferred + .get() + .every((p) => EcamDeferredProcedures[p.id]?.type === DeferredProcedureType.FOR_LANDING && p.checklistCompleted); + } + if (this.checklistId.get() === 0) { // Render overview page this.lineData.push({ @@ -42,8 +93,72 @@ export class WdNormalChecklists extends WdAbstractChecklistComponent { originalItemIndex: index, }); } + + switch (state.id) { + case 1000006: + if (this.hasDeferred[0]) { + this.lineData.push({ + activeProcedure: true, + sensed: true, + checked: this.deferredIsCompleted[0], + text: 'ALL PHASES : DEFERRED PROCEDURE', + style: this.deferredIsCompleted[0] + ? ChecklistLineStyle.CompletedDeferredProcedure + : ChecklistLineStyle.DeferredProcedure, + firstLine: false, + lastLine: false, + originalItemIndex: -1, + }); + } + if (this.hasDeferred[1]) { + this.lineData.push({ + activeProcedure: true, + sensed: true, + checked: this.deferredIsCompleted[1], + text: 'AT TOP OF DESCENT : DEFERRED PROCEDURE', + style: this.deferredIsCompleted[1] + ? ChecklistLineStyle.CompletedDeferredProcedure + : ChecklistLineStyle.DeferredProcedure, + firstLine: false, + lastLine: false, + originalItemIndex: -2, + }); + } + + if (this.hasDeferred[2]) { + this.lineData.push({ + activeProcedure: true, + sensed: true, + checked: this.deferredIsCompleted[2], + text: 'FOR APPROACH : DEFERRED PROCEDURE', + style: this.deferredIsCompleted[2] + ? ChecklistLineStyle.CompletedDeferredProcedure + : ChecklistLineStyle.DeferredProcedure, + firstLine: false, + lastLine: false, + originalItemIndex: -3, + }); + } + break; + case 1000007: + if (this.hasDeferred[3]) { + this.lineData.push({ + activeProcedure: true, + sensed: true, + checked: this.deferredIsCompleted[3], + text: 'FOR LANDING : DEFERRED PROCEDURE', + style: this.deferredIsCompleted[3] + ? ChecklistLineStyle.CompletedDeferredProcedure + : ChecklistLineStyle.DeferredProcedure, + firstLine: false, + lastLine: false, + originalItemIndex: -4, + }); + } + break; + } }); - this.totalLines.set(sorted.length + 1); + this.totalLines.set(sorted.length + this.hasDeferred.reduce((acc, val) => acc + (val ? 1 : 0), 0) + 1); } else if (clState && EcamNormalProcedures[clState.id]) { const cl = EcamNormalProcedures[clState.id]; @@ -104,6 +219,8 @@ export class WdNormalChecklists extends WdAbstractChecklistComponent { lastLine: true, originalItemIndex: cl.items.length + 1, }); + } else if (this.checklistId.get() < 0) { + // Deferred procedures } super.updateChecklists(); } @@ -113,6 +230,7 @@ export class WdNormalChecklists extends WdAbstractChecklistComponent { this.checklists.sub(() => this.updateChecklists(), true); this.checklistId.sub(() => this.updateChecklists()); + this.deferred.sub(() => this.updateChecklists()); } // 17 lines diff --git a/fbw-a380x/src/systems/instruments/src/EWD/style.scss b/fbw-a380x/src/systems/instruments/src/EWD/style.scss index 605bb51f86a..44aee3aaead 100644 --- a/fbw-a380x/src/systems/instruments/src/EWD/style.scss +++ b/fbw-a380x/src/systems/instruments/src/EWD/style.scss @@ -310,6 +310,16 @@ text, tspan, span { padding: 2px; } +.AdvBox { + display: inline; + position: relative; + left: 80px; + top: 0px; + border: 2px outset $display-white; + font-size: 24px; + padding: 2px; +} + .MemosContainer { display: flex; flex-direction: column; @@ -417,6 +427,14 @@ text, tspan, span { color: $display-grey !important; } +.EclLine.DeferredProcedure { + color: $display-amber !important; +} + +.EclLine.CompletedDeferredProcedure { + color: $display-white !important; +} + .EclLine.Green { color: $display-green !important; } diff --git a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata21-22-23.tsx b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata21-22-23.tsx index ac57d68f233..29bc6e06ea8 100644 --- a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata21-22-23.tsx +++ b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata21-22-23.tsx @@ -794,7 +794,7 @@ export const EcamAbnormalSensedAta212223: { [n: number]: AbnormalProcedure } = { { name: 'CABIN CREW', sensed: false, - labelNotCompleted: 'ADVICE', + labelNotCompleted: 'ADVISE', }, { name: 'DESCENT', diff --git a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/index.tsx b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/index.tsx index 9d64bda5960..92ac7cf617a 100644 --- a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/index.tsx +++ b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/index.tsx @@ -570,6 +570,8 @@ export enum ChecklistLineStyle { ChecklistItem = 'ChecklistItem', ChecklistItemInactive = 'ChecklistItemInactive', CompletedChecklist = 'CompletedChecklist', + CompletedDeferredProcedure = 'CompletedDeferredProcedure', + DeferredProcedure = 'DeferredProcedure', OmissionDots = 'OmissionDots', LandAsap = 'LandAsap', LandAnsa = 'LandAnsa', diff --git a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/providers/FwsEwdPublisher.ts b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/providers/FwsEwdPublisher.ts index 32ac6c86f0c..4f376503455 100644 --- a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/providers/FwsEwdPublisher.ts +++ b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/providers/FwsEwdPublisher.ts @@ -15,6 +15,14 @@ export interface NormalChecklistState { itemsCompleted: boolean[]; } +export interface DeferredProcedureState { + id: string; + checklistCompleted: boolean; + itemsToShow: boolean[]; + itemsChecked: boolean[]; + itemsActive: boolean[]; +} + export type AbnormalNonSensedCategory = null | 'ENG' | 'F/CTL' | 'L/G' | 'NAV' | 'FUEL' | 'MISCELLANEOUS'; export interface AbnormalNonSensedList { /** Refers to abnormal proc id */ @@ -42,6 +50,8 @@ export interface FwsEwdEvents { fws_show_abn_sensed: boolean; /** (FWS -> EWD) List of abnormal sensed procedures to be displayed */ fws_abn_sensed_procedures: FwsEwdAbnormalSensedEntry[]; + /** (FWS -> EWD) List of deferred procedures to be displayed */ + fws_deferred_procedures: DeferredProcedureState[]; /** (FWS -> EWD) Show abnormal non-sensed procedures selection menu */ fws_show_abn_non_sensed: boolean; @@ -52,4 +62,6 @@ export interface FwsEwdEvents { fws_show_failure_pending: boolean; /** (FWS -> EWD) Show STS indication at bottom of page */ fws_show_sts_indication: boolean; + /** (FWS -> EWD) Show ADV indication at bottom of page */ + fws_show_adv_indication: boolean; } diff --git a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsAbnormalSensed.ts b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsAbnormalSensed.ts index f6568d0381a..b14bbb26b7e 100644 --- a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsAbnormalSensed.ts +++ b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsAbnormalSensed.ts @@ -16,7 +16,11 @@ import { SubscribableMapFunctions, } from '@microsoft/msfs-sdk'; import { SdPages } from '@shared/EcamSystemPages'; -import { FwsEwdAbnormalSensedEntry, FwsEwdEvents } from 'instruments/src/MsfsAvionicsCommon/providers/FwsEwdPublisher'; +import { + DeferredProcedureState, + FwsEwdAbnormalSensedEntry, + FwsEwdEvents, +} from 'instruments/src/MsfsAvionicsCommon/providers/FwsEwdPublisher'; import { FwcAuralWarning, FwsCore } from 'systems-host/systems/FlightWarningSystem/FwsCore'; export interface EwdAbnormalItem { @@ -102,6 +106,28 @@ export class FwsAbnormalSensed { true, ); + this.fws.activeDeferredProceduresList.sub( + ( + map: ReadonlyMap, + _type: SubscribableMapEventType, + _key: string, + _value: DeferredProcedureState, + ) => { + const flattened: DeferredProcedureState[] = []; + map.forEach((val, key) => + flattened.push({ + id: key, + checklistCompleted: val.checklistCompleted, + itemsChecked: val.itemsChecked, + itemsActive: val.itemsActive, + itemsToShow: val.itemsToShow, + }), + ); + this.pub.pub('fws_deferred_procedures', flattened, true); + }, + true, + ); + this.abnormalShown.sub((shown) => { if (shown) { this.selectFirst(); @@ -239,7 +265,7 @@ export class FwsAbnormalSensed { if (clState.itemsChecked[this.selectedItem.get()]) { if (isChecklistCondition(procItem) && procItem.condition) { // Force 'active' status update - this.fws.conditionalActiveItems(proc, clState.itemsChecked, clState.itemsActive); + FwsCore.conditionalActiveItems(proc, clState.itemsChecked, clState.itemsActive); } this.moveDown(false); } @@ -926,7 +952,7 @@ export class FwsAbnormalSensed { ], whichItemsChecked: () => [ false, // Crew oxy masks - false, // Crew advice + false, // Crew advise false, // Descent initiate false, // Emer descent false, // Emer descent announce diff --git a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsCore.ts b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsCore.ts index 53289f899f8..974fcc497ec 100644 --- a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsCore.ts +++ b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsCore.ts @@ -37,6 +37,7 @@ import { PseudoFwcSimvars } from 'instruments/src/MsfsAvionicsCommon/providers/P import { FuelSystemEvents } from 'instruments/src/MsfsAvionicsCommon/providers/FuelSystemPublisher'; import { AbnormalProcedure, + DeferredProcedure, EcamAbnormalSensedProcedures, EcamDeferredProcedures, EcamMemos, @@ -45,6 +46,7 @@ import { } from '../../../instruments/src/MsfsAvionicsCommon/EcamMessages'; import PitchTrimUtils from '@shared/PitchTrimUtils'; import { + DeferredProcedureState, FwsEwdAbnormalSensedEntry, FwsEwdEvents, } from '../../../instruments/src/MsfsAvionicsCommon/providers/FwsEwdPublisher'; @@ -230,11 +232,14 @@ export class FwsCore { public readonly activeAbnormalProceduresList = MapSubject.create(); /** Map to hold all deferred procs which are currently active */ - public readonly activeDeferredProceduresList = MapSubject.create(); + public readonly activeDeferredProceduresList = MapSubject.create(); /** Indices of items which were updated */ public readonly abnormalUpdatedItems = new Map(); + /** Indices of items which were updated */ + public readonly deferredUpdatedItems = new Map(); + public recallFailures: string[] = []; private requestMasterCautionFromFaults = false; @@ -2750,6 +2755,8 @@ export class FwsCore { this.fmcCFault.set(!SimVar.GetSimVarValue('L:A32NX_FMC_C_IS_HEALTHY', 'bool')); this.fms1Fault.set(this.fmcAFault.get() && this.fmcCFault.get()); this.fms2Fault.set(this.fmcBFault.get() && this.fmcCFault.get()); + this.fms1Fault.set(true); + this.fms2Fault.set(true); /* 21 - AIR CONDITIONING AND PRESSURIZATION */ @@ -3826,6 +3833,7 @@ export class FwsCore { ).concat(Object.entries(this.abnormalNonSensed.ewdAbnormalNonSensed)); const ewdDeferredEntries = Object.entries(this.abnormalSensed.ewdDeferredProcs); this.abnormalUpdatedItems.clear(); + this.deferredUpdatedItems.clear(); for (const [key, value] of ewdAbnormalEntries) { if (value.flightPhaseInhib.some((e) => e === flightPhase)) { continue; @@ -3852,7 +3860,7 @@ export class FwsCore { const itemsChecked = value.whichItemsChecked().map((v, i) => (proc.items[i].sensed === false ? false : !!v)); const itemsToShow = value.whichItemsToShow ? value.whichItemsToShow() : Array(itemsChecked.length).fill(true); const itemsActive = value.whichItemsActive ? value.whichItemsActive() : Array(itemsChecked.length).fill(true); - this.conditionalActiveItems(proc, itemsChecked, itemsActive); + FwsCore.conditionalActiveItems(proc, itemsChecked, itemsActive); if (newWarning) { failureKeys.push(key); @@ -3903,6 +3911,7 @@ export class FwsCore { ) { this.activeDeferredProceduresList.setValue(deferredKey, { id: key, + checklistCompleted: false, itemsActive: deferredValue.whichItemsActive(), itemsChecked: deferredValue.whichItemsChecked ? deferredValue.whichItemsChecked() @@ -3919,7 +3928,7 @@ export class FwsCore { const fusedChecked = [...prevEl.itemsChecked].map((val, index) => proc.items[index].sensed ? itemsChecked[index] : !!val, ); - this.conditionalActiveItems(proc, fusedChecked, itemsActive); + FwsCore.conditionalActiveItems(proc, fusedChecked, itemsActive); this.abnormalUpdatedItems.set(key, []); proc.items.forEach((item, idx) => { if ( @@ -3981,6 +3990,40 @@ export class FwsCore { } } + // Update deferred procedures + for (const [key, value] of Object.values(this.activeDeferredProceduresList.get())) { + const proc = EcamDeferredProcedures[key]; + const itemsChecked = value.whichItemsChecked().map((v, i) => (proc.items[i].sensed === false ? false : !!v)); + const itemsToShow = value.whichItemsToShow ? value.whichItemsToShow() : Array(itemsChecked.length).fill(true); + const itemsActive = value.whichItemsActive ? value.whichItemsActive() : Array(itemsChecked.length).fill(true); + FwsCore.conditionalActiveItems(proc, itemsChecked, itemsActive); + + const prevEl = value; + const fusedChecked = [...prevEl.itemsChecked].map((val, index) => + proc.items[index].sensed ? itemsChecked[index] : !!val, + ); + FwsCore.conditionalActiveItems(proc, fusedChecked, itemsActive); + this.deferredUpdatedItems.set(key, []); + proc.items.forEach((item, idx) => { + if ( + prevEl.itemsToShow[idx] !== itemsToShow[idx] || + prevEl.itemsActive[idx] !== itemsActive[idx] || + (prevEl.itemsChecked[idx] !== fusedChecked[idx] && item.sensed) + ) { + this.deferredUpdatedItems.get(key).push(idx); + } + }); + + if (this.deferredUpdatedItems.has(key) && this.deferredUpdatedItems.get(key).length > 0) { + value.setValue(key, { + id: key, + itemsChecked: fusedChecked, + itemsActive: [...prevEl.itemsActive].map((_, index) => itemsActive[index]), + itemsToShow: [...prevEl.itemsToShow].map((_, index) => itemsToShow[index]), + }); + } + } + if (value.auralWarning?.get() === FwcAuralWarning.Crc) { if (!this.auralCrcKeys.includes(key)) { this.auralCrcActive.set(true); @@ -4231,7 +4274,11 @@ export class FwsCore { this.autoPilotInstinctiveDiscCountSinceLastFwsCycle = 0; } - conditionalActiveItems(proc: AbnormalProcedure, itemsChecked: boolean[], itemsActive: boolean[]) { + static conditionalActiveItems( + proc: AbnormalProcedure | DeferredProcedure, + itemsChecked: boolean[], + itemsActive: boolean[], + ) { // Additional logic for conditions: Modify itemsActive based on condition activation status if (proc.items.some((v) => isChecklistCondition(v))) { proc.items.forEach((v, i) => { From b57c0988fb2efb8a3d752c2653414c70c7ba2f51 Mon Sep 17 00:00:00 2001 From: Florian Gross <63071941+flogross89@users.noreply.github.com> Date: Sat, 14 Dec 2024 06:25:35 +0200 Subject: [PATCH 11/40] deferred 3 --- .../src/EWD/elements/WdAbnormalNonSensed.tsx | 2 +- .../elements/WdAbnormalSensedProcedures.tsx | 70 +++++-- .../elements/WdAbstractChecklistComponent.tsx | 4 + .../src/EWD/elements/WdNormalChecklists.tsx | 157 ++++++-------- .../systems/instruments/src/EWD/style.scss | 2 +- .../AbnormalSensed/ata21-22-23.tsx | 2 +- .../EcamMessages/NormalProcedures.tsx | 24 ++- .../MsfsAvionicsCommon/EcamMessages/index.tsx | 4 + .../providers/FwsEwdPublisher.ts | 17 +- .../FlightWarningSystem/FwsAbnormalSensed.ts | 32 +-- .../systems/FlightWarningSystem/FwsCore.ts | 16 +- .../FwsNormalChecklists.ts | 192 +++++++++++++++--- 12 files changed, 332 insertions(+), 190 deletions(-) diff --git a/fbw-a380x/src/systems/instruments/src/EWD/elements/WdAbnormalNonSensed.tsx b/fbw-a380x/src/systems/instruments/src/EWD/elements/WdAbnormalNonSensed.tsx index 070945bffbe..32a4fa8a868 100644 --- a/fbw-a380x/src/systems/instruments/src/EWD/elements/WdAbnormalNonSensed.tsx +++ b/fbw-a380x/src/systems/instruments/src/EWD/elements/WdAbnormalNonSensed.tsx @@ -129,7 +129,7 @@ export class WdAbnormalNonSensedProcedures extends WdAbstractChecklistComponent style: ChecklistLineStyle.ChecklistItem, firstLine: false, lastLine: abn.items.length === 0 ? true : false, - originalItemIndex: 0, + originalItemIndex: -1, }); abn.items.forEach((item, index) => { diff --git a/fbw-a380x/src/systems/instruments/src/EWD/elements/WdAbnormalSensedProcedures.tsx b/fbw-a380x/src/systems/instruments/src/EWD/elements/WdAbnormalSensedProcedures.tsx index 1f8d2e6a94e..b66d520e251 100644 --- a/fbw-a380x/src/systems/instruments/src/EWD/elements/WdAbnormalSensedProcedures.tsx +++ b/fbw-a380x/src/systems/instruments/src/EWD/elements/WdAbnormalSensedProcedures.tsx @@ -2,11 +2,15 @@ import { ConsumerSubject, FSComponent, VNode } from '@microsoft/msfs-sdk'; import { ChecklistLineStyle, EcamAbnormalSensedProcedures, + EcamDeferredProcedures, + isAbnormalSensedProcedure, isChecklistAction, isChecklistCondition, + WdLineData, WdSpecialLine, } from 'instruments/src/MsfsAvionicsCommon/EcamMessages'; import { WdAbstractChecklistComponent } from 'instruments/src/EWD/elements/WdAbstractChecklistComponent'; +import { FwsEwdAbnormalSensedEntry } from 'instruments/src/MsfsAvionicsCommon/providers/FwsEwdPublisher'; export class WdAbnormalSensedProcedures extends WdAbstractChecklistComponent { private readonly procedures = ConsumerSubject.create(this.sub.on('fws_abn_sensed_procedures'), []); @@ -14,24 +18,40 @@ export class WdAbnormalSensedProcedures extends WdAbstractChecklistComponent { public updateChecklists() { this.lineData.length = 0; - this.procedures.get().forEach((procState, procIndex, array) => { - if (procState && EcamAbnormalSensedProcedures[procState.id]) { - const cl = EcamAbnormalSensedProcedures[procState.id]; + WdAbnormalSensedProcedures.generateProcedureLineData(this.procedures.get(), this.lineData); + super.updateChecklists(); + } + + public static generateProcedureLineData( + procedures: FwsEwdAbnormalSensedEntry[], + lineData: WdLineData[], + showOnlyFirst = true, + deferredProcedure = false, + ) { + procedures.forEach((procState, procIndex, array) => { + if ( + procState && + ((!deferredProcedure && EcamAbnormalSensedProcedures[procState.id]) || + (deferredProcedure && EcamDeferredProcedures[procState.id])) + ) { + const cl = deferredProcedure + ? EcamDeferredProcedures[procState.id] + : EcamAbnormalSensedProcedures[procState.id]; - this.lineData.push({ + lineData.push({ abnormalProcedure: true, - activeProcedure: procIndex === 0, + activeProcedure: procIndex === 0 || deferredProcedure, sensed: true, checked: false, text: cl.title, style: ChecklistLineStyle.Headline, - firstLine: true, + firstLine: !deferredProcedure, lastLine: procIndex !== 0 ? true : false, }); - if (procIndex === 0) { - if (cl.recommendation) { - this.lineData.push({ + if (showOnlyFirst || procIndex === 0) { + if (isAbnormalSensedProcedure(cl) && cl.recommendation) { + lineData.push({ abnormalProcedure: true, activeProcedure: procIndex === 0, sensed: true, @@ -42,6 +62,21 @@ export class WdAbnormalSensedProcedures extends WdAbstractChecklistComponent { lastLine: false, }); } + + if (deferredProcedure) { + lineData.push({ + abnormalProcedure: true, + activeProcedure: procIndex === 0 || deferredProcedure, + sensed: false, + checked: procState.procedureCompleted ?? false, + text: `${'\xa0'.repeat(31)}ACTIVATE`, + style: ChecklistLineStyle.ChecklistItem, + firstLine: procIndex !== 0 ? true : false, + lastLine: procIndex !== 0 ? true : false, + originalItemIndex: -1, + }); + } + // If first and most important procedure: Display in full cl.items.forEach((item, itemIndex) => { if (!procState.itemsToShow[itemIndex]) { @@ -82,9 +117,9 @@ export class WdAbnormalSensedProcedures extends WdAbstractChecklistComponent { text += item.name; } - this.lineData.push({ + lineData.push({ abnormalProcedure: true, - activeProcedure: procIndex === 0, + activeProcedure: procIndex === 0 || deferredProcedure, sensed: isChecklistCondition(item) ? true : item.sensed, checked: procState.itemsChecked[itemIndex], text: text, @@ -97,9 +132,9 @@ export class WdAbnormalSensedProcedures extends WdAbstractChecklistComponent { if (isChecklistCondition(item) && !item.sensed) { // Insert CONFIRM const confirmText = `${item.level ? '\xa0'.repeat(item.level) : ''}CONFIRM ${item.name}`; - this.lineData.push({ + lineData.push({ abnormalProcedure: true, - activeProcedure: procIndex === 0, + activeProcedure: procIndex === 0 || deferredProcedure, sensed: item.sensed, checked: procState.itemsChecked[itemIndex], text: confirmText, @@ -111,7 +146,7 @@ export class WdAbnormalSensedProcedures extends WdAbstractChecklistComponent { } }); - this.lineData.push({ + lineData.push({ abnormalProcedure: true, activeProcedure: true, sensed: false, @@ -124,7 +159,7 @@ export class WdAbnormalSensedProcedures extends WdAbstractChecklistComponent { }); } else { // Only three dots for following procedures - this.lineData.push({ + lineData.push({ abnormalProcedure: true, activeProcedure: false, sensed: true, @@ -138,9 +173,9 @@ export class WdAbnormalSensedProcedures extends WdAbstractChecklistComponent { // Empty line after procedure if (procIndex < array.length - 1) { - this.lineData.push({ + lineData.push({ abnormalProcedure: true, - activeProcedure: procIndex === 0, + activeProcedure: procIndex === 0 || deferredProcedure, sensed: true, checked: false, text: '', @@ -152,7 +187,6 @@ export class WdAbnormalSensedProcedures extends WdAbstractChecklistComponent { } } }); - super.updateChecklists(); } public onAfterRender(node: VNode): void { diff --git a/fbw-a380x/src/systems/instruments/src/EWD/elements/WdAbstractChecklistComponent.tsx b/fbw-a380x/src/systems/instruments/src/EWD/elements/WdAbstractChecklistComponent.tsx index 00c06456a56..83682b9b29d 100644 --- a/fbw-a380x/src/systems/instruments/src/EWD/elements/WdAbstractChecklistComponent.tsx +++ b/fbw-a380x/src/systems/instruments/src/EWD/elements/WdAbstractChecklistComponent.tsx @@ -146,6 +146,10 @@ export class EclLine extends DisplayComponent { ), Checked: this.props.data.map((d) => d.checked), ChecklistCompleted: this.props.data.map((d) => d.style === ChecklistLineStyle.CompletedChecklist), + DeferredProcedure: this.props.data.map((d) => d.style === ChecklistLineStyle.DeferredProcedure), + CompletedDeferredProcedure: this.props.data.map( + (d) => d.style === ChecklistLineStyle.CompletedDeferredProcedure, + ), ChecklistCondition: this.props.data.map((d) => d.style === ChecklistLineStyle.ChecklistCondition), Green: this.props.data.map((d) => d.style === ChecklistLineStyle.Green), Cyan: this.props.data.map((d) => d.style === ChecklistLineStyle.Cyan), diff --git a/fbw-a380x/src/systems/instruments/src/EWD/elements/WdNormalChecklists.tsx b/fbw-a380x/src/systems/instruments/src/EWD/elements/WdNormalChecklists.tsx index 97f27525125..f85675213df 100644 --- a/fbw-a380x/src/systems/instruments/src/EWD/elements/WdNormalChecklists.tsx +++ b/fbw-a380x/src/systems/instruments/src/EWD/elements/WdNormalChecklists.tsx @@ -1,21 +1,19 @@ import { ConsumerSubject, FSComponent, VNode } from '@microsoft/msfs-sdk'; -import { EcamNormalProcedures } from 'instruments/src/MsfsAvionicsCommon/EcamMessages/NormalProcedures'; +import { + deferredProcedureIds, + EcamNormalProcedures, +} from 'instruments/src/MsfsAvionicsCommon/EcamMessages/NormalProcedures'; import { ChecklistLineStyle, DeferredProcedureType, EcamDeferredProcedures, } from 'instruments/src/MsfsAvionicsCommon/EcamMessages'; import { WdAbstractChecklistComponent } from 'instruments/src/EWD/elements/WdAbstractChecklistComponent'; +import { WdAbnormalSensedProcedures } from 'instruments/src/EWD/elements/WdAbnormalSensedProcedures'; export class WdNormalChecklists extends WdAbstractChecklistComponent { private readonly checklists = ConsumerSubject.create(this.sub.on('fws_normal_checklists'), []); - /** Special indices: - * -1 : all phases - * -2 : at top of descent - * -3 : for approach - * -4 : for landing - */ private readonly checklistId = ConsumerSubject.create(this.sub.on('fws_normal_checklists_id'), 0); private readonly deferred = ConsumerSubject.create(this.sub.on('fws_deferred_procedures'), []); @@ -52,20 +50,20 @@ export class WdNormalChecklists extends WdAbstractChecklistComponent { this.deferredIsCompleted[0] = this.deferred .get() - .every((p) => EcamDeferredProcedures[p.id]?.type === DeferredProcedureType.ALL_PHASES && p.checklistCompleted); + .every((p) => EcamDeferredProcedures[p.id]?.type === DeferredProcedureType.ALL_PHASES && p.procedureCompleted); this.deferredIsCompleted[1] = this.deferred .get() .every( - (p) => EcamDeferredProcedures[p.id]?.type === DeferredProcedureType.AT_TOP_OF_DESCENT && p.checklistCompleted, + (p) => EcamDeferredProcedures[p.id]?.type === DeferredProcedureType.AT_TOP_OF_DESCENT && p.procedureCompleted, ); this.deferredIsCompleted[2] = this.deferred .get() .every( - (p) => EcamDeferredProcedures[p.id]?.type === DeferredProcedureType.FOR_APPROACH && p.checklistCompleted, + (p) => EcamDeferredProcedures[p.id]?.type === DeferredProcedureType.FOR_APPROACH && p.procedureCompleted, ); this.deferredIsCompleted[3] = this.deferred .get() - .every((p) => EcamDeferredProcedures[p.id]?.type === DeferredProcedureType.FOR_LANDING && p.checklistCompleted); + .every((p) => EcamDeferredProcedures[p.id]?.type === DeferredProcedureType.FOR_LANDING && p.procedureCompleted); } if (this.checklistId.get() === 0) { @@ -82,84 +80,40 @@ export class WdNormalChecklists extends WdAbstractChecklistComponent { sorted.forEach((state, index) => { if (EcamNormalProcedures[state.id]) { - this.lineData.push({ - activeProcedure: true, - sensed: true, - checked: state.checklistCompleted, - text: EcamNormalProcedures[state.id].title, - style: state.checklistCompleted ? ChecklistLineStyle.CompletedChecklist : ChecklistLineStyle.ChecklistItem, - firstLine: false, - lastLine: index === sorted.length - 1, - originalItemIndex: index, - }); - } - - switch (state.id) { - case 1000006: - if (this.hasDeferred[0]) { - this.lineData.push({ - activeProcedure: true, - sensed: true, - checked: this.deferredIsCompleted[0], - text: 'ALL PHASES : DEFERRED PROCEDURE', - style: this.deferredIsCompleted[0] - ? ChecklistLineStyle.CompletedDeferredProcedure - : ChecklistLineStyle.DeferredProcedure, - firstLine: false, - lastLine: false, - originalItemIndex: -1, - }); - } - if (this.hasDeferred[1]) { - this.lineData.push({ - activeProcedure: true, - sensed: true, - checked: this.deferredIsCompleted[1], - text: 'AT TOP OF DESCENT : DEFERRED PROCEDURE', - style: this.deferredIsCompleted[1] - ? ChecklistLineStyle.CompletedDeferredProcedure - : ChecklistLineStyle.DeferredProcedure, - firstLine: false, - lastLine: false, - originalItemIndex: -2, - }); - } - - if (this.hasDeferred[2]) { - this.lineData.push({ - activeProcedure: true, - sensed: true, - checked: this.deferredIsCompleted[2], - text: 'FOR APPROACH : DEFERRED PROCEDURE', - style: this.deferredIsCompleted[2] - ? ChecklistLineStyle.CompletedDeferredProcedure - : ChecklistLineStyle.DeferredProcedure, - firstLine: false, - lastLine: false, - originalItemIndex: -3, - }); + let lineStyle: ChecklistLineStyle; + let checked = false; + let display = true; + if (deferredProcedureIds.includes(state.id)) { + lineStyle = state.checklistCompleted + ? ChecklistLineStyle.CompletedDeferredProcedure + : ChecklistLineStyle.DeferredProcedure; + if (deferredProcedureIds.findIndex((p) => p === state.id) >= 0) { + checked = this.deferredIsCompleted[deferredProcedureIds.findIndex((p) => p === state.id)]; + display = this.hasDeferred[deferredProcedureIds.findIndex((p) => p === state.id)]; } - break; - case 1000007: - if (this.hasDeferred[3]) { - this.lineData.push({ - activeProcedure: true, - sensed: true, - checked: this.deferredIsCompleted[3], - text: 'FOR LANDING : DEFERRED PROCEDURE', - style: this.deferredIsCompleted[3] - ? ChecklistLineStyle.CompletedDeferredProcedure - : ChecklistLineStyle.DeferredProcedure, - firstLine: false, - lastLine: false, - originalItemIndex: -4, - }); - } - break; + } else { + lineStyle = state.checklistCompleted + ? ChecklistLineStyle.CompletedChecklist + : ChecklistLineStyle.ChecklistItem; + checked = state.checklistCompleted; + } + + if (display) { + this.lineData.push({ + activeProcedure: true, + sensed: true, + checked: checked, + text: EcamNormalProcedures[state.id].title, + style: lineStyle, + firstLine: false, + lastLine: index === sorted.length - 1, + originalItemIndex: index, + }); + } } }); this.totalLines.set(sorted.length + this.hasDeferred.reduce((acc, val) => acc + (val ? 1 : 0), 0) + 1); - } else if (clState && EcamNormalProcedures[clState.id]) { + } else if (clState && EcamNormalProcedures[clState.id] && !deferredProcedureIds.includes(clState.id)) { const cl = EcamNormalProcedures[clState.id]; this.lineData.push({ @@ -176,11 +130,11 @@ export class WdNormalChecklists extends WdAbstractChecklistComponent { let text = item.level ? '\xa0'.repeat(item.level * 2) : ''; text += item.style !== ChecklistLineStyle.SubHeadline ? '-' : ''; text += item.name; - if (clState.itemsCompleted[index] && item.labelCompleted) { + if (clState.itemsChecked[index] && item.labelCompleted) { text += `${item.colonIfCompleted === false ? ' ' : ' : '}${item.labelCompleted}`; - } else if (clState.itemsCompleted[index] && item.labelNotCompleted) { + } else if (clState.itemsChecked[index] && item.labelNotCompleted) { text += `${item.colonIfCompleted === false ? ' ' : ' : '}${item.labelNotCompleted}`; - } else if (!clState.itemsCompleted[index] && item.labelNotCompleted) { + } else if (!clState.itemsChecked[index] && item.labelNotCompleted) { // Pad to 39 characters max const paddingNeeded = 39 - (item.labelNotCompleted.length + item.name.length + (item.level ?? 0) * 2 + 2); text += ` ${'.'.repeat(paddingNeeded)}${item.labelNotCompleted}`; @@ -189,7 +143,7 @@ export class WdNormalChecklists extends WdAbstractChecklistComponent { this.lineData.push({ activeProcedure: true, sensed: item.sensed, - checked: clState.itemsCompleted[index], + checked: clState.itemsChecked[index], text: text.substring(0, 39), style: item.style ? item.style : ChecklistLineStyle.ChecklistItem, firstLine: false, @@ -219,8 +173,29 @@ export class WdNormalChecklists extends WdAbstractChecklistComponent { lastLine: true, originalItemIndex: cl.items.length + 1, }); - } else if (this.checklistId.get() < 0) { + } else if (clState && deferredProcedureIds.includes(clState.id)) { // Deferred procedures + this.lineData.push({ + activeProcedure: true, + abnormalProcedure: true, + sensed: true, + checked: false, + text: `\x1b4m${clState.checklistCompleted ? '\x1b<4m' : ''}${EcamNormalProcedures[clState.id].title} \x1bm`, + style: ChecklistLineStyle.Headline, + firstLine: true, + lastLine: false, + }); + this.lineData.push({ + abnormalProcedure: true, + activeProcedure: true, + sensed: true, + checked: false, + text: '', + style: ChecklistLineStyle.ChecklistItem, + firstLine: false, + lastLine: false, + }); + WdAbnormalSensedProcedures.generateProcedureLineData(this.deferred.get(), this.lineData, false, true); } super.updateChecklists(); } @@ -230,7 +205,7 @@ export class WdNormalChecklists extends WdAbstractChecklistComponent { this.checklists.sub(() => this.updateChecklists(), true); this.checklistId.sub(() => this.updateChecklists()); - this.deferred.sub(() => this.updateChecklists()); + this.deferred.sub(() => this.updateChecklists(), true); } // 17 lines diff --git a/fbw-a380x/src/systems/instruments/src/EWD/style.scss b/fbw-a380x/src/systems/instruments/src/EWD/style.scss index 44aee3aaead..11447761802 100644 --- a/fbw-a380x/src/systems/instruments/src/EWD/style.scss +++ b/fbw-a380x/src/systems/instruments/src/EWD/style.scss @@ -313,7 +313,7 @@ text, tspan, span { .AdvBox { display: inline; position: relative; - left: 80px; + left: 360px; top: 0px; border: 2px outset $display-white; font-size: 24px; diff --git a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata21-22-23.tsx b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata21-22-23.tsx index 29bc6e06ea8..5e0b21cb2c9 100644 --- a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata21-22-23.tsx +++ b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata21-22-23.tsx @@ -2129,7 +2129,7 @@ export const EcamAbnormalSensedAta212223: { [n: number]: AbnormalProcedure } = { export const EcamDeferredProcAta212223: { [n: number]: DeferredProcedure } = { 221700001: { fromAbnormalProc: '221800006', - title: '\x1b<4mLDG ELEVN', + title: '\x1b<4m> LDG ELEVN', type: DeferredProcedureType.AT_TOP_OF_DESCENT, items: [ { diff --git a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/NormalProcedures.tsx b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/NormalProcedures.tsx index b31abea2174..33b1a3e94a9 100644 --- a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/NormalProcedures.tsx +++ b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/NormalProcedures.tsx @@ -3,6 +3,8 @@ import { ChecklistLineStyle, NormalProcedure } from 'instruments/src/MsfsAvionicsCommon/EcamMessages'; +export const deferredProcedureIds = [1000007, 1000008, 1000009, 1000011]; + /** All normal procedures (checklists, via ECL) should be here. * Display is ordered by ID, ascending. That's why keys need to be numbers. */ export const EcamNormalProcedures: { [n: number]: NormalProcedure } = { @@ -192,6 +194,18 @@ export const EcamNormalProcedures: { [n: number]: NormalProcedure } = { ], }, 1000007: { + title: 'ALL PHASES : DEFERRED PROCEDURE', + items: [], + }, + 1000008: { + title: 'AT TOP OF DESCENT : DEFERRED PROCEDURE', + items: [], + }, + 1000009: { + title: 'FOR APPROACH : DEFERRED PROCEDURE', + items: [], + }, + 1000010: { title: 'APPROACH', items: [ { @@ -220,7 +234,11 @@ export const EcamNormalProcedures: { [n: number]: NormalProcedure } = { }, ], }, - 1000008: { + 1000011: { + title: 'FOR LANDING : DEFERRED PROCEDURE', + items: [], + }, + 1000012: { title: 'LANDING', items: [ { name: 'LDG', style: ChecklistLineStyle.SubHeadline, sensed: true, labelNotCompleted: '' }, @@ -249,7 +267,7 @@ export const EcamNormalProcedures: { [n: number]: NormalProcedure } = { }, ], }, - 1000009: { + 1000013: { title: 'PARKING', items: [ { @@ -276,7 +294,7 @@ export const EcamNormalProcedures: { [n: number]: NormalProcedure } = { }, ], }, - 1000010: { + 1000014: { title: 'SECURING THE AIRCRAFT', items: [ { diff --git a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/index.tsx b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/index.tsx index 92ac7cf617a..9e48af9169a 100644 --- a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/index.tsx +++ b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/index.tsx @@ -612,6 +612,10 @@ export function isChecklistCondition(c: AbstractChecklistItem): c is ChecklistCo return (c as ChecklistCondition).condition !== undefined; } +export function isAbnormalSensedProcedure(c: AbnormalProcedure | DeferredProcedure): c is AbnormalProcedure { + return (c as AbnormalProcedure).recommendation !== undefined; +} + export interface AbnormalProcedure { /** Title of the fault, e.g. "_HYD_ G SYS PRESS LO". \n produces second line. Accepts special formatting tokens */ title: string; diff --git a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/providers/FwsEwdPublisher.ts b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/providers/FwsEwdPublisher.ts index 4f376503455..9922706c3fd 100644 --- a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/providers/FwsEwdPublisher.ts +++ b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/providers/FwsEwdPublisher.ts @@ -4,6 +4,8 @@ export interface FwsEwdAbnormalSensedEntry { id: string; + procedureCompleted?: boolean; + procedureActivated?: boolean; itemsToShow: boolean[]; itemsChecked: boolean[]; itemsActive: boolean[]; @@ -12,14 +14,8 @@ export interface FwsEwdAbnormalSensedEntry { export interface NormalChecklistState { id: number; checklistCompleted: boolean; - itemsCompleted: boolean[]; -} - -export interface DeferredProcedureState { - id: string; - checklistCompleted: boolean; - itemsToShow: boolean[]; itemsChecked: boolean[]; + itemsToShow: boolean[]; itemsActive: boolean[]; } @@ -41,7 +37,7 @@ export interface FwsEwdEvents { /** (FWS -> EWD) Show normal procedures / ECL */ fws_show_normal_checklists: boolean; - /** (FWS -> EWD) List of all normal checklists, including checked state */ + /** (FWS -> EWD) List of all normal checklists including deferred procedures */ fws_normal_checklists: NormalChecklistState[]; /** (FWS -> EWD) Which checklist to display */ fws_normal_checklists_id: number; @@ -50,8 +46,11 @@ export interface FwsEwdEvents { fws_show_abn_sensed: boolean; /** (FWS -> EWD) List of abnormal sensed procedures to be displayed */ fws_abn_sensed_procedures: FwsEwdAbnormalSensedEntry[]; + + /** (FWS -> EWD) All deferred procedures to be displayed */ + fws_deferred_procedures: FwsEwdAbnormalSensedEntry[]; /** (FWS -> EWD) List of deferred procedures to be displayed */ - fws_deferred_procedures: DeferredProcedureState[]; + fws_deferred_procedures_show_tod: boolean; /** (FWS -> EWD) Show abnormal non-sensed procedures selection menu */ fws_show_abn_non_sensed: boolean; diff --git a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsAbnormalSensed.ts b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsAbnormalSensed.ts index b14bbb26b7e..69b7e3fd7e6 100644 --- a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsAbnormalSensed.ts +++ b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsAbnormalSensed.ts @@ -16,11 +16,7 @@ import { SubscribableMapFunctions, } from '@microsoft/msfs-sdk'; import { SdPages } from '@shared/EcamSystemPages'; -import { - DeferredProcedureState, - FwsEwdAbnormalSensedEntry, - FwsEwdEvents, -} from 'instruments/src/MsfsAvionicsCommon/providers/FwsEwdPublisher'; +import { FwsEwdAbnormalSensedEntry, FwsEwdEvents } from 'instruments/src/MsfsAvionicsCommon/providers/FwsEwdPublisher'; import { FwcAuralWarning, FwsCore } from 'systems-host/systems/FlightWarningSystem/FwsCore'; export interface EwdAbnormalItem { @@ -106,28 +102,6 @@ export class FwsAbnormalSensed { true, ); - this.fws.activeDeferredProceduresList.sub( - ( - map: ReadonlyMap, - _type: SubscribableMapEventType, - _key: string, - _value: DeferredProcedureState, - ) => { - const flattened: DeferredProcedureState[] = []; - map.forEach((val, key) => - flattened.push({ - id: key, - checklistCompleted: val.checklistCompleted, - itemsChecked: val.itemsChecked, - itemsActive: val.itemsActive, - itemsToShow: val.itemsToShow, - }), - ); - this.pub.pub('fws_deferred_procedures', flattened, true); - }, - true, - ); - this.abnormalShown.sub((shown) => { if (shown) { this.selectFirst(); @@ -3599,8 +3573,8 @@ export class FwsAbnormalSensed { flightPhaseInhib: [], simVarIsActive: Subject.create(true), notActiveWhenFaults: [], - whichItemsToShow: () => [], - whichItemsChecked: () => [], + whichItemsToShow: () => [true, true], + whichItemsChecked: () => [this.fws.manCabinAltMode.get(), false], failure: 0, sysPage: SdPages.None, }, diff --git a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsCore.ts b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsCore.ts index 974fcc497ec..08fb4cf54bd 100644 --- a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsCore.ts +++ b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsCore.ts @@ -46,7 +46,6 @@ import { } from '../../../instruments/src/MsfsAvionicsCommon/EcamMessages'; import PitchTrimUtils from '@shared/PitchTrimUtils'; import { - DeferredProcedureState, FwsEwdAbnormalSensedEntry, FwsEwdEvents, } from '../../../instruments/src/MsfsAvionicsCommon/providers/FwsEwdPublisher'; @@ -232,7 +231,7 @@ export class FwsCore { public readonly activeAbnormalProceduresList = MapSubject.create(); /** Map to hold all deferred procs which are currently active */ - public readonly activeDeferredProceduresList = MapSubject.create(); + public readonly activeDeferredProceduresList = MapSubject.create(); /** Indices of items which were updated */ public readonly abnormalUpdatedItems = new Map(); @@ -3910,15 +3909,18 @@ export class FwsCore { this.abnormalSensed.ewdDeferredProcs[deferredKey] ) { this.activeDeferredProceduresList.setValue(deferredKey, { - id: key, - checklistCompleted: false, - itemsActive: deferredValue.whichItemsActive(), + id: deferredKey, + procedureCompleted: false, + itemsChecked: deferredValue.whichItemsChecked ? deferredValue.whichItemsChecked() - : Array(deferredValue.whichItemsActive().length).fill(true), + : Array(deferredValue.whichItemsChecked().length).fill(true), + itemsActive: deferredValue.whichItemsActive + ? deferredValue.whichItemsActive() + : Array(deferredValue.whichItemsChecked().length).fill(true), itemsToShow: deferredValue.whichItemsToShow ? deferredValue.whichItemsToShow() - : Array(deferredValue.whichItemsActive().length).fill(true), + : Array(deferredValue.whichItemsChecked().length).fill(true), }); } } diff --git a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsNormalChecklists.ts b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsNormalChecklists.ts index a334036317b..8882c00d2f1 100644 --- a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsNormalChecklists.ts +++ b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsNormalChecklists.ts @@ -2,10 +2,23 @@ // SPDX-License-Identifier: GPL-3.0 import { MapSubject, SimVarValueType, Subject, SubscribableMapEventType } from '@microsoft/msfs-sdk'; -import { NormalChecklistState, FwsEwdEvents } from 'instruments/src/MsfsAvionicsCommon/providers/FwsEwdPublisher'; +import { + NormalChecklistState, + FwsEwdEvents, + FwsEwdAbnormalSensedEntry, +} from 'instruments/src/MsfsAvionicsCommon/providers/FwsEwdPublisher'; import { FwsCore } from 'systems-host/systems/FlightWarningSystem/FwsCore'; -import { EcamNormalProcedures } from 'instruments/src/MsfsAvionicsCommon/EcamMessages/NormalProcedures'; -import { ChecklistLineStyle, NormalProcedure, WD_NUM_LINES } from 'instruments/src/MsfsAvionicsCommon/EcamMessages'; +import { + deferredProcedureIds, + EcamNormalProcedures, +} from 'instruments/src/MsfsAvionicsCommon/EcamMessages/NormalProcedures'; +import { + ChecklistLineStyle, + DeferredProcedureType, + EcamDeferredProcedures, + NormalProcedure, + WD_NUM_LINES, +} from 'instruments/src/MsfsAvionicsCommon/EcamMessages'; export interface NormalEclSensedItems { /** Returns a boolean vector (same length as number of items). If true, item is marked as completed. If null, it's a non-sensed item */ @@ -33,6 +46,12 @@ export class FwsNormalChecklists { public readonly checklistState = MapSubject.create(); + /** ALL PHASES, TOP OF DESCENT, FOR APPROACH, FOR LANDING */ + private readonly hasDeferred = [false, false, false, false]; + + /** ALL PHASES, TOP OF DESCENT, FOR APPROACH, FOR LANDING */ + private readonly deferredIsCompleted = [false, false, false, false]; + constructor(private fws: FwsCore) { this.checklistState.sub( ( @@ -43,7 +62,13 @@ export class FwsNormalChecklists { ) => { const flattened: NormalChecklistState[] = []; map.forEach((val, key) => - flattened.push({ id: key, checklistCompleted: val.checklistCompleted, itemsCompleted: val.itemsCompleted }), + flattened.push({ + id: key, + checklistCompleted: val.checklistCompleted, + itemsChecked: val.itemsChecked, + itemsActive: val.itemsActive, + itemsToShow: val.itemsToShow, + }), ); this.pub.pub('fws_normal_checklists', flattened, true); }, @@ -51,36 +76,69 @@ export class FwsNormalChecklists { ); this.checklistId.sub((id) => this.pub.pub('fws_normal_checklists_id', id, true), true); + this.fws.activeDeferredProceduresList.sub( + ( + map: ReadonlyMap, + _type: SubscribableMapEventType, + _key: string, + _value: FwsEwdAbnormalSensedEntry, + ) => { + const flattened: FwsEwdAbnormalSensedEntry[] = []; + map.forEach((val, key) => + flattened.push({ + id: key, + procedureCompleted: val.procedureCompleted, + itemsChecked: val.itemsChecked, + itemsActive: val.itemsActive, + itemsToShow: val.itemsToShow, + }), + ); + this.pub.pub('fws_deferred_procedures', flattened, true); + }, + true, + ); + // Populate checklistState const keys = this.getNormalProceduresKeysSorted(); keys.forEach((k) => { const proc = EcamNormalProcedures[k] as NormalProcedure; this.checklistState.setValue(k, { id: k, - checklistCompleted: proc.deferred ? true : false, - itemsCompleted: Array(proc.items.length).fill(false), + checklistCompleted: false, + itemsChecked: Array(proc.items.length).fill(false), + itemsActive: Array(proc.items.length).fill(true), + itemsToShow: Array(proc.items.length).fill(true), }); }); this.checklistState.setValue(0, { id: 0, checklistCompleted: false, - itemsCompleted: Array(Object.keys(EcamNormalProcedures).length).fill(false), + itemsChecked: Array(Object.keys(EcamNormalProcedures).length).fill(false), + itemsActive: Array(Object.keys(EcamNormalProcedures).length).fill(true), + itemsToShow: Array(Object.keys(EcamNormalProcedures).length).fill(true), }); this.selectedLine.sub(() => this.scrollToSelectedLine()); } - getNormalProceduresKeysSorted() { + getNormalProceduresKeysSorted(onlyVisible = false) { return Object.keys(EcamNormalProcedures) .map((v) => parseInt(v)) + .filter((v, index) => { + if (onlyVisible && deferredProcedureIds.includes(v) && this.checklistState.getValue(0)?.itemsToShow[index]) { + return false; + } else { + return true; + } + }) .sort((a, b) => a - b); } selectFirst() { if (this.checklistId.get() === 0) { // Find first non-completed checklist - const keys = this.getNormalProceduresKeysSorted(); + const keys = this.getNormalProceduresKeysSorted(true); let firstIncompleteChecklist = 0; keys.some((key, index) => { if (!this.checklistState.getValue(key).checklistCompleted) { @@ -92,10 +150,10 @@ export class FwsNormalChecklists { } else { const clState = this.checklistState.getValue(this.checklistId.get()); const selectableAndNotChecked = EcamNormalProcedures[this.checklistId.get()].items - .map((_, index) => (clState.itemsCompleted[index] === false ? index : null)) + .map((_, index) => (clState.itemsChecked[index] === false ? index : null)) .filter((v) => v !== null); this.selectedLine.set( - selectableAndNotChecked[0] !== undefined ? selectableAndNotChecked[0] - 1 : clState.itemsCompleted.length - 1, + selectableAndNotChecked[0] !== undefined ? selectableAndNotChecked[0] - 1 : clState.itemsChecked.length - 1, ); } this.moveDown(false); @@ -103,10 +161,12 @@ export class FwsNormalChecklists { moveUp() { if (this.checklistId.get() === 0) { - this.selectedLine.set(Math.max(this.selectedLine.get() - 1, 0)); + const shownItems = this.getNormalProceduresKeysSorted() + .map((_, index) => (this.checklistState.getValue(0).itemsToShow[index] ? index : null)) + .filter((v) => v !== null); + this.selectedLine.set(Math.max(shownItems[shownItems.indexOf(this.selectedLine.get()) - 1] ?? 0, 0)); } else { const numItems = EcamNormalProcedures[this.checklistId.get()].items.length; - // const selectable = EcamNormalProcedures[this.checklistId.get()].items.map((_, index) => index); const selectable = this.selectableItems(true); if (this.selectedLine.get() == numItems + 1) { @@ -152,7 +212,7 @@ export class FwsNormalChecklists { const clState = this.checklistState.getValue(this.checklistId.get()); return ( (!EcamNormalProcedures[this.checklistId.get()].items[itemIndex].sensed || - (!skipCompletedSensed && !clState.itemsCompleted[itemIndex])) && + (!skipCompletedSensed && !clState.itemsChecked[itemIndex])) && !FwsNormalChecklists.nonSelectableItemStyles.includes( EcamNormalProcedures[this.checklistId.get()].items[itemIndex].style, ) @@ -167,7 +227,16 @@ export class FwsNormalChecklists { moveDown(skipCompletedSensed = true) { if (this.checklistId.get() === 0) { - this.selectedLine.set(Math.min(this.selectedLine.get() + 1, this.getNormalProceduresKeysSorted().length - 1)); + const shownItems = this.getNormalProceduresKeysSorted() + .map((_, index) => (this.checklistState.getValue(0).itemsToShow[index] ? index : null)) + .filter((v) => v !== null); + this.selectedLine.set( + Math.min( + shownItems[shownItems.indexOf(this.selectedLine.get()) + 1] ?? + this.getNormalProceduresKeysSorted(true).length, + this.getNormalProceduresKeysSorted(true).length, + ), + ); } else { const numItems = EcamNormalProcedures[this.checklistId.get()].items.length; const selectable = this.selectableItems(skipCompletedSensed); @@ -190,28 +259,30 @@ export class FwsNormalChecklists { const clState: NormalChecklistState = { id: cl.id, checklistCompleted: cl.checklistCompleted, - itemsCompleted: [...cl.itemsCompleted], + itemsChecked: [...cl.itemsChecked], + itemsActive: [...cl.itemsActive], + itemsToShow: [...cl.itemsToShow], }; const proc = EcamNormalProcedures[this.checklistId.get()]; if ( - this.selectedLine.get() < clState.itemsCompleted.length && + this.selectedLine.get() < clState.itemsChecked.length && proc.items[this.selectedLine.get()]?.sensed === false ) { - clState.itemsCompleted[this.selectedLine.get()] = !clState.itemsCompleted[this.selectedLine.get()]; + clState.itemsChecked[this.selectedLine.get()] = !clState.itemsChecked[this.selectedLine.get()]; this.checklistState.setValue(this.checklistId.get(), clState); - if (clState.itemsCompleted[this.selectedLine.get()]) { + if (clState.itemsChecked[this.selectedLine.get()]) { this.moveDown(false); } - } else if (this.selectedLine.get() === clState.itemsCompleted.length) { + } else if (this.selectedLine.get() === clState.itemsChecked.length) { // C/L complete clState.checklistCompleted = true; - clState.itemsCompleted = clState.itemsCompleted.map((val, index) => (proc.items[index].sensed ? val : true)); + clState.itemsChecked = clState.itemsChecked.map((val, index) => (proc.items[index].sensed ? val : true)); this.checklistState.setValue(this.checklistId.get(), clState); this.showChecklistRequested.set(false); - } else if (this.selectedLine.get() === clState.itemsCompleted.length + 1) { + } else if (this.selectedLine.get() === clState.itemsChecked.length + 1) { // RESET clState.checklistCompleted = false; - clState.itemsCompleted = clState.itemsCompleted.map((val, index) => (proc.items[index].sensed ? val : false)); + clState.itemsChecked = clState.itemsChecked.map((val, index) => (proc.items[index].sensed ? val : false)); // Reset all following checklists const fromId = this.getNormalProceduresKeysSorted().findIndex((v) => v === this.checklistId.get()); @@ -225,9 +296,11 @@ export class FwsNormalChecklists { const clStateFollowing: NormalChecklistState = { id: idFollowing, checklistCompleted: procFollowing.deferred ? true : false, - itemsCompleted: [...clFollowing.itemsCompleted].map((val, index) => + itemsChecked: [...clFollowing.itemsChecked].map((val, index) => procFollowing.items[index].sensed ? val : false, ), + itemsActive: clFollowing.itemsActive, + itemsToShow: clFollowing.itemsToShow, }; this.checklistState.setValue(idFollowing, clStateFollowing); } @@ -282,12 +355,12 @@ export class FwsNormalChecklists { const cl = this.checklistState.getValue(procId); const proc = EcamNormalProcedures[procId]; - if (!this.sensedItems[procId]) { + if (!this.sensedItems[procId] || deferredProcedureIds.includes(procId)) { continue; } const sensedResult = this.sensedItems[procId].whichItemsChecked(); const changedEntries = sensedResult.map((val, index) => - val !== null && val !== cl.itemsCompleted[index] ? index : null, + val !== null && val !== cl.itemsChecked[index] ? index : null, ); if (changedEntries.some((v) => v !== null)) { changed = true; @@ -299,14 +372,61 @@ export class FwsNormalChecklists { const clState: NormalChecklistState = { id: procId, checklistCompleted: cl.checklistCompleted, - itemsCompleted: [...cl.itemsCompleted].map((val, index) => + itemsChecked: [...cl.itemsChecked].map((val, index) => proc.items[index].sensed && sensedResult[index] != null ? sensedResult[index] : val, ), + itemsActive: cl.itemsActive, + itemsToShow: cl.itemsToShow, }; if (changed) { this.checklistState.setValue(procId, clState); } } + + // Update deferred proc status + for (let i = 0; i < 3; i++) { + this.hasDeferred[i] = false; + this.deferredIsCompleted[i] = true; + } + this.fws.activeDeferredProceduresList.get().forEach((val) => { + switch (EcamDeferredProcedures[val.id]?.type) { + case DeferredProcedureType.ALL_PHASES: + this.hasDeferred[0] = true; + if (!val.procedureCompleted) { + this.deferredIsCompleted[0] = false; + } + break; + case DeferredProcedureType.AT_TOP_OF_DESCENT: + this.hasDeferred[1] = true; + if (!val.procedureCompleted) { + this.deferredIsCompleted[1] = false; + } + break; + case DeferredProcedureType.FOR_APPROACH: + this.hasDeferred[2] = true; + if (!val.procedureCompleted) { + this.deferredIsCompleted[2] = false; + } + break; + case DeferredProcedureType.FOR_LANDING: + this.hasDeferred[3] = true; + if (!val.procedureCompleted) { + this.deferredIsCompleted[3] = false; + } + break; + } + }); + const overviewState = this.checklistState.getValue(0); + overviewState.itemsChecked[Object.keys(EcamNormalProcedures).indexOf('1000007')] = this.deferredIsCompleted[0]; + overviewState.itemsChecked[Object.keys(EcamNormalProcedures).indexOf('1000008')] = this.deferredIsCompleted[1]; + overviewState.itemsChecked[Object.keys(EcamNormalProcedures).indexOf('1000009')] = this.deferredIsCompleted[2]; + overviewState.itemsChecked[Object.keys(EcamNormalProcedures).indexOf('1000011')] = this.deferredIsCompleted[3]; + overviewState.itemsToShow[Object.keys(EcamNormalProcedures).indexOf('1000007')] = this.hasDeferred[0]; + overviewState.itemsToShow[Object.keys(EcamNormalProcedures).indexOf('1000008')] = this.hasDeferred[1]; + overviewState.itemsToShow[Object.keys(EcamNormalProcedures).indexOf('1000009')] = this.hasDeferred[2]; + overviewState.itemsToShow[Object.keys(EcamNormalProcedures).indexOf('1000011')] = this.hasDeferred[3]; + + this.checklistState.setValue(0, overviewState); } public sensedItems: FwsNormalChecklistsDict = { @@ -339,9 +459,21 @@ export class FwsNormalChecklists { whichItemsChecked: () => [null, null, null, null], }, 1000007: { - whichItemsChecked: () => [null, SimVar.GetSimVarValue('A:CABIN SEATBELTS ALERT SWITCH', 'bool'), null, null], + whichItemsChecked: () => [null], }, 1000008: { + whichItemsChecked: () => [null], + }, + 1000009: { + whichItemsChecked: () => [null], + }, + 1000010: { + whichItemsChecked: () => [null, SimVar.GetSimVarValue('A:CABIN SEATBELTS ALERT SWITCH', 'bool'), null, null], + }, + 1000011: { + whichItemsChecked: () => [null], + }, + 1000012: { whichItemsChecked: () => [ false, SimVar.GetSimVarValue('A:CABIN SEATBELTS ALERT SWITCH', 'bool'), @@ -353,7 +485,7 @@ export class FwsNormalChecklists { SimVar.GetSimVarValue('L:A32NX_FLAPS_HANDLE_INDEX', 'enum') === 3), ], }, - 1000009: { + 1000013: { whichItemsChecked: () => [ null, !this.fws.engine1Master.get() && @@ -364,7 +496,7 @@ export class FwsNormalChecklists { this.fws.allFuelPumpsOff.get(), ], }, - 1000010: { + 1000014: { whichItemsChecked: () => [ SimVar.GetSimVarValue('L:PUSH_OVHD_OXYGEN_CREW', 'bool'), SimVar.GetSimVarValue('L:XMLVAR_SWITCH_OVHD_INTLT_EMEREXIT_Position', 'number') === 2, From f51f65a5e1f4a86052e25273c20d8730ab5a5335 Mon Sep 17 00:00:00 2001 From: Florian Gross <63071941+flogross89@users.noreply.github.com> Date: Sun, 15 Dec 2024 13:45:38 +0200 Subject: [PATCH 12/40] before refactor --- .../elements/WdAbnormalSensedProcedures.tsx | 4 +- .../MsfsAvionicsCommon/EcamMessages/index.tsx | 8 ++-- .../FwsAbnormalNonSensed.ts | 10 +++-- .../FlightWarningSystem/FwsAbnormalSensed.ts | 19 ++++++++-- .../systems/FlightWarningSystem/FwsCore.ts | 37 ++++++++++++------- .../FwsNormalChecklists.ts | 9 ++++- 6 files changed, 60 insertions(+), 27 deletions(-) diff --git a/fbw-a380x/src/systems/instruments/src/EWD/elements/WdAbnormalSensedProcedures.tsx b/fbw-a380x/src/systems/instruments/src/EWD/elements/WdAbnormalSensedProcedures.tsx index b66d520e251..0cb5e6ec3d7 100644 --- a/fbw-a380x/src/systems/instruments/src/EWD/elements/WdAbnormalSensedProcedures.tsx +++ b/fbw-a380x/src/systems/instruments/src/EWD/elements/WdAbnormalSensedProcedures.tsx @@ -18,7 +18,7 @@ export class WdAbnormalSensedProcedures extends WdAbstractChecklistComponent { public updateChecklists() { this.lineData.length = 0; - WdAbnormalSensedProcedures.generateProcedureLineData(this.procedures.get(), this.lineData); + WdAbnormalSensedProcedures.generateProcedureLineData(this.procedures.get(), this.lineData, true, false); super.updateChecklists(); } @@ -49,7 +49,7 @@ export class WdAbnormalSensedProcedures extends WdAbstractChecklistComponent { lastLine: procIndex !== 0 ? true : false, }); - if (showOnlyFirst || procIndex === 0) { + if (!showOnlyFirst || procIndex === 0) { if (isAbnormalSensedProcedure(cl) && cl.recommendation) { lineData.push({ abnormalProcedure: true, diff --git a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/index.tsx b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/index.tsx index 9e48af9169a..575e7081d0a 100644 --- a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/index.tsx +++ b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/index.tsx @@ -605,15 +605,15 @@ interface ChecklistCondition extends AbstractChecklistItem { interface ChecklistSpecialItem extends AbstractChecklistItem {} export function isChecklistAction(c: AbstractChecklistItem): c is ChecklistAction { - return (c as ChecklistAction).labelNotCompleted !== undefined; + return (c as ChecklistAction)?.labelNotCompleted !== undefined; } export function isChecklistCondition(c: AbstractChecklistItem): c is ChecklistCondition { - return (c as ChecklistCondition).condition !== undefined; + return (c as ChecklistCondition)?.condition !== undefined; } export function isAbnormalSensedProcedure(c: AbnormalProcedure | DeferredProcedure): c is AbnormalProcedure { - return (c as AbnormalProcedure).recommendation !== undefined; + return (c as AbnormalProcedure)?.recommendation !== undefined; } export interface AbnormalProcedure { @@ -678,6 +678,8 @@ export const EcamAbnormalSensedProcedures: { [n: string]: AbnormalProcedure } = /** All abnormal non-sensed procedures (via ECL) should be here. Don't start for now, format needs to be defined. */ export const EcamAbnormalNonSensedProcedures = AbnormalNonSensedProcedures; +export const EcamAbnormalProcedures = { ...EcamAbnormalSensedProcedures, ...EcamAbnormalNonSensedProcedures }; + export const EcamAbNormalSensedSubMenuVector: AbnormalNonSensedCategory[] = [ 'ENG', 'F/CTL', diff --git a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsAbnormalNonSensed.ts b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsAbnormalNonSensed.ts index c1e46a73783..dab377b20eb 100644 --- a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsAbnormalNonSensed.ts +++ b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsAbnormalNonSensed.ts @@ -3,7 +3,7 @@ import { MapSubject, SimVarValueType, Subject } from '@microsoft/msfs-sdk'; import { NormalChecklistState, FwsEwdEvents } from 'instruments/src/MsfsAvionicsCommon/providers/FwsEwdPublisher'; -import { FwsCore } from 'systems-host/systems/FlightWarningSystem/FwsCore'; +import { FwcAuralWarning, FwsCore } from 'systems-host/systems/FlightWarningSystem/FwsCore'; import { EcamAbnormalNonSensedProcedures, EcamAbNormalSensedSubMenuVector, @@ -96,7 +96,7 @@ export class FwsAbnormalNonSensed { } else if (this.selectedItem.get() < skipProcsFromTopMenu) { // Preview non-sensed procedure this.checklistId.set(EcamAbnormalNonSensedProcedures[this.selectedItem.get()]?.id ?? 0); - this.selectedItem.set(0); + this.selectedItem.set(-1); } } else if (this.checklistId.get() > 0 && this.checklistId.get() <= 10) { // Sub menu @@ -105,8 +105,9 @@ export class FwsAbnormalNonSensed { ); // Preview non-sensed procedure this.checklistId.set(EcamAbnormalNonSensedProcedures[subMenuProcsStartAt + this.selectedItem.get()].id); - this.selectedItem.set(0); + this.selectedItem.set(-1); } else { + console.log('---'); // Activate non-sensed procedure (add to ECAM faults) and close dialog, i.e. return to abnormal procs this.fws.activeAbnormalNonSensedKeys.push(this.checklistId.get()); this.selectedItem.set(0); @@ -130,7 +131,8 @@ export class FwsAbnormalNonSensed { false, false, ], - failure: 1, + failure: 3, + auralWarning: Subject.create(FwcAuralWarning.None), sysPage: SdPages.None, redundLoss: () => [], }, diff --git a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsAbnormalSensed.ts b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsAbnormalSensed.ts index 69b7e3fd7e6..5f59d44f2b7 100644 --- a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsAbnormalSensed.ts +++ b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsAbnormalSensed.ts @@ -93,8 +93,9 @@ export class FwsAbnormalSensed { }), ); // Sort by decreasing importance + console.log(flattened); const sortedAbnormalsFlattened = flattened.sort( - (a, b) => this.ewdAbnormalSensed[b.id].failure - this.ewdAbnormalSensed[a.id].failure, + (a, b) => this.fws.ewdAbnormal[b.id].failure - this.fws.ewdAbnormal[a.id].failure, ); this.activeProcedureId.set(sortedAbnormalsFlattened.length > 0 ? sortedAbnormalsFlattened[0].id : null); this.pub.pub('fws_abn_sensed_procedures', sortedAbnormalsFlattened, true); @@ -248,9 +249,21 @@ export class FwsAbnormalSensed { } } - private clearActiveProcedure() { + public clearActiveProcedure() { + console.log( + this.fws.presentedFailures, + parseInt(this.activeProcedureId.get()), + this.fws.activeAbnormalNonSensedKeys.includes(parseInt(this.activeProcedureId.get())), + ); this.fws.presentedFailures.splice(0, 1); this.fws.recallFailures = this.fws.allCurrentFailures.filter((item) => !this.fws.presentedFailures.includes(item)); + + if (this.fws.activeAbnormalNonSensedKeys.includes(parseInt(this.activeProcedureId.get()))) { + this.fws.activeAbnormalNonSensedKeys.splice( + this.fws.activeAbnormalNonSensedKeys.indexOf(parseInt(this.activeProcedureId.get())), + 1, + ); + } } private scrollToSelectedLine() { @@ -300,7 +313,7 @@ export class FwsAbnormalSensed { for (let id = 0; id < ids.length; id++) { const procId = ids[id]; - if (!this.ewdAbnormalSensed[procId] || !this.fws.abnormalUpdatedItems.has(procId)) { + if (!this.fws.ewdAbnormal[procId] || !this.fws.abnormalUpdatedItems.has(procId)) { continue; } diff --git a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsCore.ts b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsCore.ts index 08fb4cf54bd..1e8b269d944 100644 --- a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsCore.ts +++ b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsCore.ts @@ -38,7 +38,7 @@ import { FuelSystemEvents } from 'instruments/src/MsfsAvionicsCommon/providers/F import { AbnormalProcedure, DeferredProcedure, - EcamAbnormalSensedProcedures, + EcamAbnormalProcedures, EcamDeferredProcedures, EcamMemos, isChecklistCondition, @@ -51,7 +51,11 @@ import { } from '../../../instruments/src/MsfsAvionicsCommon/providers/FwsEwdPublisher'; import { FwsMemos } from 'systems-host/systems/FlightWarningSystem/FwsMemos'; import { FwsNormalChecklists } from 'systems-host/systems/FlightWarningSystem/FwsNormalChecklists'; -import { EwdAbnormalItem, FwsAbnormalSensed } from 'systems-host/systems/FlightWarningSystem/FwsAbnormalSensed'; +import { + EwdAbnormalDict, + EwdAbnormalItem, + FwsAbnormalSensed, +} from 'systems-host/systems/FlightWarningSystem/FwsAbnormalSensed'; import { FwsAbnormalNonSensed } from 'systems-host/systems/FlightWarningSystem/FwsAbnormalNonSensed'; import { MfdSurvEvents } from 'instruments/src/MsfsAvionicsCommon/providers/MfdSurvPublisher'; import { Mle, Mmo, VfeF1, VfeF1F, VfeF2, VfeF3, VfeFF, Vle, Vmo } from '@shared/PerformanceConstants'; @@ -1502,13 +1506,20 @@ export class FwsCore { public readonly memos = new FwsMemos(this); public readonly normalChecklists = new FwsNormalChecklists(this); - public readonly abnormalSensed = new FwsAbnormalSensed(this); public readonly abnormalNonSensed = new FwsAbnormalNonSensed(this); + public readonly abnormalSensed = new FwsAbnormalSensed(this); + public ewdAbnormal: EwdAbnormalDict; constructor( public readonly fwsNumber: 1 | 2, public readonly bus: EventBus, ) { + this.ewdAbnormal = Object.assign( + {}, + this.abnormalSensed.ewdAbnormalSensed, + this.abnormalNonSensed.ewdAbnormalNonSensed, + ); + this.ewdMessageLinesLeft.forEach((ls, i) => ls.sub((l) => { SimVar.SetSimVarValue(FwsCore.ewdMessageSimVarsLeft[i], 'string', l ?? ''); @@ -3773,8 +3784,7 @@ export class FwsCore { /* CLEAR AND RECALL */ if (this.clrPulseNode.read()) { // delete the first failure - this.presentedFailures.splice(0, 1); - this.recallFailures = this.allCurrentFailures.filter((item) => !this.presentedFailures.includes(item)); + this.abnormalSensed.clearActiveProcedure(); } if (this.rclUpPulseNode.read()) { @@ -3815,7 +3825,7 @@ export class FwsCore { const auralScKeys: string[] = []; // Update memos and failures list in case failure has been resolved - for (const [key, value] of Object.entries(this.abnormalSensed.ewdAbnormalSensed)) { + for (const [key, value] of Object.entries(this.ewdAbnormal)) { if (!value.simVarIsActive.get() || value.flightPhaseInhib.some((e) => e === flightPhase)) { failureKeys = failureKeys.filter((e) => e !== key); recallFailureKeys = recallFailureKeys.filter((e) => e !== key); @@ -3827,9 +3837,7 @@ export class FwsCore { this.nonCancellableWarningCount = 0; // Abnormal sensed procedures - const ewdAbnormalEntries: [string, EwdAbnormalItem][] = Object.entries( - this.abnormalSensed.ewdAbnormalSensed, - ).concat(Object.entries(this.abnormalNonSensed.ewdAbnormalNonSensed)); + const ewdAbnormalEntries: [string, EwdAbnormalItem][] = Object.entries(this.ewdAbnormal); const ewdDeferredEntries = Object.entries(this.abnormalSensed.ewdDeferredProcs); this.abnormalUpdatedItems.clear(); this.deferredUpdatedItems.clear(); @@ -3840,14 +3848,14 @@ export class FwsCore { // new warning? const newWarning = !this.presentedFailures.includes(key) && !recallFailureKeys.includes(key); - const proc = EcamAbnormalSensedProcedures[key] as AbnormalProcedure; + const proc = EcamAbnormalProcedures[key]; if (value.simVarIsActive.get() || this.activeAbnormalNonSensedKeys.includes(parseInt(key))) { // Skip if other fault overrides this one let overridden = false; value.notActiveWhenFaults.forEach((val) => { - if (val && this.abnormalSensed.ewdAbnormalSensed[val]) { - const otherFault = this.abnormalSensed.ewdAbnormalSensed[val] as EwdAbnormalItem; + if (val && this.ewdAbnormal[val]) { + const otherFault = this.ewdAbnormal[val] as EwdAbnormalItem; if (otherFault.simVarIsActive.get()) { overridden = true; } @@ -3927,6 +3935,9 @@ export class FwsCore { } else if (this.activeAbnormalProceduresList.has(key)) { // Update internal map const prevEl = this.activeAbnormalProceduresList.getValue(key); + if (!proc.items) { + console.log(proc, prevEl); + } const fusedChecked = [...prevEl.itemsChecked].map((val, index) => proc.items[index].sensed ? itemsChecked[index] : !!val, ); @@ -4074,7 +4085,7 @@ export class FwsCore { const failOrder: string[] = []; - for (const [key] of Object.entries(this.abnormalSensed.ewdAbnormalSensed)) { + for (const [key] of Object.entries(this.ewdAbnormal)) { failOrder.push(...key); } diff --git a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsNormalChecklists.ts b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsNormalChecklists.ts index 8882c00d2f1..e215a4d9198 100644 --- a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsNormalChecklists.ts +++ b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsNormalChecklists.ts @@ -147,7 +147,7 @@ export class FwsNormalChecklists { } }); this.selectedLine.set(firstIncompleteChecklist - 1); - } else { + } else if (!deferredProcedureIds.includes(this.checklistId.get())) { const clState = this.checklistState.getValue(this.checklistId.get()); const selectableAndNotChecked = EcamNormalProcedures[this.checklistId.get()].items .map((_, index) => (clState.itemsChecked[index] === false ? index : null)) @@ -155,6 +155,9 @@ export class FwsNormalChecklists { this.selectedLine.set( selectableAndNotChecked[0] !== undefined ? selectableAndNotChecked[0] - 1 : clState.itemsChecked.length - 1, ); + } else { + // Deferred procedure + this.selectedLine.set(-2); } this.moveDown(false); } @@ -237,7 +240,7 @@ export class FwsNormalChecklists { this.getNormalProceduresKeysSorted(true).length, ), ); - } else { + } else if (!deferredProcedureIds.includes(this.checklistId.get())) { const numItems = EcamNormalProcedures[this.checklistId.get()].items.length; const selectable = this.selectableItems(skipCompletedSensed); if (this.selectedLine.get() >= selectable[selectable.length - 1] || selectable.length == 0) { @@ -251,6 +254,8 @@ export class FwsNormalChecklists { ), ); } + } else { + //... } } From 05b0fc7eb36a63010fa93fc137d37e2d5bce824f Mon Sep 17 00:00:00 2001 From: Florian Gross <63071941+flogross89@users.noreply.github.com> Date: Sun, 15 Dec 2024 23:26:13 +0200 Subject: [PATCH 13/40] rewrite 1 --- .../elements/WdAbnormalSensedProcedures.tsx | 194 +------- .../elements/WdAbstractChecklistComponent.tsx | 2 +- .../src/EWD/elements/WdNormalChecklists.tsx | 108 ++-- .../EcamMessages/ProcedureLinesGenerator.tsx | 470 ++++++++++++++++++ .../MsfsAvionicsCommon/EcamMessages/index.tsx | 8 +- .../providers/FwsEwdPublisher.ts | 24 +- .../FwsAbnormalNonSensed.ts | 4 +- .../FlightWarningSystem/FwsAbnormalSensed.ts | 241 +++------ .../systems/FlightWarningSystem/FwsCore.ts | 54 +- .../FwsNormalChecklists.ts | 234 +++------ 10 files changed, 688 insertions(+), 651 deletions(-) create mode 100644 fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/ProcedureLinesGenerator.tsx diff --git a/fbw-a380x/src/systems/instruments/src/EWD/elements/WdAbnormalSensedProcedures.tsx b/fbw-a380x/src/systems/instruments/src/EWD/elements/WdAbnormalSensedProcedures.tsx index 0cb5e6ec3d7..d806aff1e79 100644 --- a/fbw-a380x/src/systems/instruments/src/EWD/elements/WdAbnormalSensedProcedures.tsx +++ b/fbw-a380x/src/systems/instruments/src/EWD/elements/WdAbnormalSensedProcedures.tsx @@ -1,16 +1,10 @@ -import { ConsumerSubject, FSComponent, VNode } from '@microsoft/msfs-sdk'; +import { ConsumerSubject, FSComponent, Subject, VNode } from '@microsoft/msfs-sdk'; import { - ChecklistLineStyle, - EcamAbnormalSensedProcedures, - EcamDeferredProcedures, - isAbnormalSensedProcedure, - isChecklistAction, - isChecklistCondition, - WdLineData, - WdSpecialLine, -} from 'instruments/src/MsfsAvionicsCommon/EcamMessages'; + ProcedureLinesGenerator, + ProcedureType, +} from 'instruments/src/MsfsAvionicsCommon/EcamMessages/ProcedureLinesGenerator'; + import { WdAbstractChecklistComponent } from 'instruments/src/EWD/elements/WdAbstractChecklistComponent'; -import { FwsEwdAbnormalSensedEntry } from 'instruments/src/MsfsAvionicsCommon/providers/FwsEwdPublisher'; export class WdAbnormalSensedProcedures extends WdAbstractChecklistComponent { private readonly procedures = ConsumerSubject.create(this.sub.on('fws_abn_sensed_procedures'), []); @@ -18,175 +12,17 @@ export class WdAbnormalSensedProcedures extends WdAbstractChecklistComponent { public updateChecklists() { this.lineData.length = 0; - WdAbnormalSensedProcedures.generateProcedureLineData(this.procedures.get(), this.lineData, true, false); - super.updateChecklists(); - } - - public static generateProcedureLineData( - procedures: FwsEwdAbnormalSensedEntry[], - lineData: WdLineData[], - showOnlyFirst = true, - deferredProcedure = false, - ) { - procedures.forEach((procState, procIndex, array) => { - if ( - procState && - ((!deferredProcedure && EcamAbnormalSensedProcedures[procState.id]) || - (deferredProcedure && EcamDeferredProcedures[procState.id])) - ) { - const cl = deferredProcedure - ? EcamDeferredProcedures[procState.id] - : EcamAbnormalSensedProcedures[procState.id]; - - lineData.push({ - abnormalProcedure: true, - activeProcedure: procIndex === 0 || deferredProcedure, - sensed: true, - checked: false, - text: cl.title, - style: ChecklistLineStyle.Headline, - firstLine: !deferredProcedure, - lastLine: procIndex !== 0 ? true : false, - }); - - if (!showOnlyFirst || procIndex === 0) { - if (isAbnormalSensedProcedure(cl) && cl.recommendation) { - lineData.push({ - abnormalProcedure: true, - activeProcedure: procIndex === 0, - sensed: true, - checked: false, - text: cl.recommendation, - style: cl.recommendation === 'LAND ASAP' ? ChecklistLineStyle.LandAsap : ChecklistLineStyle.LandAnsa, - firstLine: false, - lastLine: false, - }); - } - - if (deferredProcedure) { - lineData.push({ - abnormalProcedure: true, - activeProcedure: procIndex === 0 || deferredProcedure, - sensed: false, - checked: procState.procedureCompleted ?? false, - text: `${'\xa0'.repeat(31)}ACTIVATE`, - style: ChecklistLineStyle.ChecklistItem, - firstLine: procIndex !== 0 ? true : false, - lastLine: procIndex !== 0 ? true : false, - originalItemIndex: -1, - }); - } - - // If first and most important procedure: Display in full - cl.items.forEach((item, itemIndex) => { - if (!procState.itemsToShow[itemIndex]) { - return; - } - - let clStyle: ChecklistLineStyle = item.style ? item.style : ChecklistLineStyle.ChecklistItem; - let text = item.level ? '\xa0'.repeat(item.level) : ''; - if (isChecklistAction(item)) { - text += clStyle !== ChecklistLineStyle.SubHeadline ? '-' : ''; - text += item.name; - if (!procState.itemsActive[itemIndex] && clStyle === ChecklistLineStyle.ChecklistItem) { - clStyle = ChecklistLineStyle.ChecklistItemInactive; - } - if (procState.itemsChecked[itemIndex] && item.labelCompleted) { - text += `${item.colonIfCompleted === false ? ' ' : ' : '}${item.labelCompleted}`; - } else if (procState.itemsChecked[itemIndex] && item.labelNotCompleted) { - text += `${item.colonIfCompleted === false ? ' ' : ' : '}${item.labelNotCompleted}`; - } else if (!procState.itemsChecked[itemIndex] && item.labelNotCompleted) { - // Pad to 39 characters max - const paddingNeeded = Math.max( - 0, - 39 - (item.labelNotCompleted.length + item.name.length + (item.level ?? 0) * 1 + 2), - ); - - text += ` ${'.'.repeat(paddingNeeded)}${item.labelNotCompleted}`; - } - } else if (isChecklistCondition(item)) { - clStyle = ChecklistLineStyle.ChecklistCondition; - if (item.name.substring(0, 4) === 'WHEN') { - text += `.${item.name}`; - } else { - text += procState.itemsChecked[itemIndex] - ? `.AS ${item.name.substring(0, 2) === 'IF' ? item.name.substring(2) : item.name}` - : `.IF ${item.name.substring(0, 2) === 'IF' ? item.name.substring(2) : item.name}`; - } - } else { - text += item.name; - } - - lineData.push({ - abnormalProcedure: true, - activeProcedure: procIndex === 0 || deferredProcedure, - sensed: isChecklistCondition(item) ? true : item.sensed, - checked: procState.itemsChecked[itemIndex], - text: text, - style: clStyle, - firstLine: procIndex !== 0 ? true : false, - lastLine: procIndex !== 0 ? true : false, - originalItemIndex: isChecklistCondition(item) ? undefined : itemIndex, - }); - - if (isChecklistCondition(item) && !item.sensed) { - // Insert CONFIRM - const confirmText = `${item.level ? '\xa0'.repeat(item.level) : ''}CONFIRM ${item.name}`; - lineData.push({ - abnormalProcedure: true, - activeProcedure: procIndex === 0 || deferredProcedure, - sensed: item.sensed, - checked: procState.itemsChecked[itemIndex], - text: confirmText, - style: clStyle, - firstLine: procIndex !== 0 ? true : false, - lastLine: procIndex !== 0 ? true : false, - originalItemIndex: itemIndex, - }); - } - }); - - lineData.push({ - abnormalProcedure: true, - activeProcedure: true, - sensed: false, - checked: false, - text: `${'\xa0'.repeat(34)}CLEAR`, - style: ChecklistLineStyle.ChecklistItem, - firstLine: false, - lastLine: true, - originalItemIndex: cl.items.length, - }); - } else { - // Only three dots for following procedures - lineData.push({ - abnormalProcedure: true, - activeProcedure: false, - sensed: true, - checked: false, - text: '...', - style: ChecklistLineStyle.OmissionDots, - firstLine: true, - lastLine: true, - }); - } - - // Empty line after procedure - if (procIndex < array.length - 1) { - lineData.push({ - abnormalProcedure: true, - activeProcedure: procIndex === 0 || deferredProcedure, - sensed: true, - checked: false, - text: '', - style: ChecklistLineStyle.ChecklistItem, - firstLine: true, - lastLine: true, - specialLine: WdSpecialLine.Empty, - }); - } - } + this.procedures.get().forEach((procState, procIndex) => { + const procGen = new ProcedureLinesGenerator( + procState.id, + Subject.create(procIndex === 0), + ProcedureType.Abnormal, + procState, + ); + this.lineData.push(...procGen.toLineData()); }); + + super.updateChecklists(); } public onAfterRender(node: VNode): void { diff --git a/fbw-a380x/src/systems/instruments/src/EWD/elements/WdAbstractChecklistComponent.tsx b/fbw-a380x/src/systems/instruments/src/EWD/elements/WdAbstractChecklistComponent.tsx index 83682b9b29d..28be37bf8d0 100644 --- a/fbw-a380x/src/systems/instruments/src/EWD/elements/WdAbstractChecklistComponent.tsx +++ b/fbw-a380x/src/systems/instruments/src/EWD/elements/WdAbstractChecklistComponent.tsx @@ -31,7 +31,7 @@ export class WdAbstractChecklistComponent extends DisplayComponent v.id !== 0) - .sort((a, b) => a.id - b.id); - const clState = sorted.find((v) => v.id === this.checklistId.get()); + .filter((v) => v.id !== '0') + .sort((a, b) => parseInt(a.id) - parseInt(b.id)); + const clState = sorted.find((v) => parseInt(v.id) === this.checklistId.get()); if (this.deferred.get().length > 0) { // Status of deferred procedures @@ -79,23 +82,23 @@ export class WdNormalChecklists extends WdAbstractChecklistComponent { }); sorted.forEach((state, index) => { - if (EcamNormalProcedures[state.id]) { + if (EcamNormalProcedures[parseInt(state.id)]) { let lineStyle: ChecklistLineStyle; let checked = false; let display = true; - if (deferredProcedureIds.includes(state.id)) { - lineStyle = state.checklistCompleted + if (deferredProcedureIds.includes(parseInt(state.id))) { + lineStyle = state.procedureCompleted ? ChecklistLineStyle.CompletedDeferredProcedure : ChecklistLineStyle.DeferredProcedure; - if (deferredProcedureIds.findIndex((p) => p === state.id) >= 0) { - checked = this.deferredIsCompleted[deferredProcedureIds.findIndex((p) => p === state.id)]; - display = this.hasDeferred[deferredProcedureIds.findIndex((p) => p === state.id)]; + if (deferredProcedureIds.findIndex((p) => p === parseInt(state.id)) >= 0) { + checked = this.deferredIsCompleted[deferredProcedureIds.findIndex((p) => p === parseInt(state.id))]; + display = this.hasDeferred[deferredProcedureIds.findIndex((p) => p === parseInt(state.id))]; } } else { - lineStyle = state.checklistCompleted + lineStyle = state.procedureCompleted ? ChecklistLineStyle.CompletedChecklist : ChecklistLineStyle.ChecklistItem; - checked = state.checklistCompleted; + checked = state.procedureCompleted ?? false; } if (display) { @@ -103,7 +106,7 @@ export class WdNormalChecklists extends WdAbstractChecklistComponent { activeProcedure: true, sensed: true, checked: checked, - text: EcamNormalProcedures[state.id].title, + text: EcamNormalProcedures[parseInt(state.id)].title, style: lineStyle, firstLine: false, lastLine: index === sorted.length - 1, @@ -113,74 +116,21 @@ export class WdNormalChecklists extends WdAbstractChecklistComponent { } }); this.totalLines.set(sorted.length + this.hasDeferred.reduce((acc, val) => acc + (val ? 1 : 0), 0) + 1); - } else if (clState && EcamNormalProcedures[clState.id] && !deferredProcedureIds.includes(clState.id)) { - const cl = EcamNormalProcedures[clState.id]; - - this.lineData.push({ - activeProcedure: true, - sensed: true, - checked: false, - text: cl.title, - style: ChecklistLineStyle.Headline, - firstLine: true, - lastLine: false, - }); - - cl.items.forEach((item, index) => { - let text = item.level ? '\xa0'.repeat(item.level * 2) : ''; - text += item.style !== ChecklistLineStyle.SubHeadline ? '-' : ''; - text += item.name; - if (clState.itemsChecked[index] && item.labelCompleted) { - text += `${item.colonIfCompleted === false ? ' ' : ' : '}${item.labelCompleted}`; - } else if (clState.itemsChecked[index] && item.labelNotCompleted) { - text += `${item.colonIfCompleted === false ? ' ' : ' : '}${item.labelNotCompleted}`; - } else if (!clState.itemsChecked[index] && item.labelNotCompleted) { - // Pad to 39 characters max - const paddingNeeded = 39 - (item.labelNotCompleted.length + item.name.length + (item.level ?? 0) * 2 + 2); - text += ` ${'.'.repeat(paddingNeeded)}${item.labelNotCompleted}`; - } - - this.lineData.push({ - activeProcedure: true, - sensed: item.sensed, - checked: clState.itemsChecked[index], - text: text.substring(0, 39), - style: item.style ? item.style : ChecklistLineStyle.ChecklistItem, - firstLine: false, - lastLine: false, - originalItemIndex: index, - }); - }); - - this.lineData.push({ - activeProcedure: true, - sensed: false, - checked: clState.checklistCompleted, - text: `${'\xa0'.repeat(27)}C/L COMPLETE`, - style: ChecklistLineStyle.ChecklistItem, - firstLine: false, - lastLine: false, - originalItemIndex: cl.items.length, - }); - - this.lineData.push({ - activeProcedure: true, - sensed: false, - checked: false, - text: `${'\xa0'.repeat(34)}RESET`, - style: ChecklistLineStyle.ChecklistItem, - firstLine: false, - lastLine: true, - originalItemIndex: cl.items.length + 1, - }); - } else if (clState && deferredProcedureIds.includes(clState.id)) { + } else if ( + clState && + EcamNormalProcedures[parseInt(clState.id)] && + !deferredProcedureIds.includes(parseInt(clState.id)) + ) { + const procGen = new ProcedureLinesGenerator(clState.id, Subject.create(true), ProcedureType.Normal, clState); + this.lineData.push(...procGen.toLineData()); + } else if (clState && deferredProcedureIds.includes(parseInt(clState.id))) { // Deferred procedures this.lineData.push({ activeProcedure: true, abnormalProcedure: true, sensed: true, checked: false, - text: `\x1b4m${clState.checklistCompleted ? '\x1b<4m' : ''}${EcamNormalProcedures[clState.id].title} \x1bm`, + text: `\x1b4m${clState.procedureCompleted ? '\x1b<4m' : ''}${EcamNormalProcedures[parseInt(clState.id)].title} \x1bm`, style: ChecklistLineStyle.Headline, firstLine: true, lastLine: false, @@ -195,7 +145,11 @@ export class WdNormalChecklists extends WdAbstractChecklistComponent { firstLine: false, lastLine: false, }); - WdAbnormalSensedProcedures.generateProcedureLineData(this.deferred.get(), this.lineData, false, true); + + this.deferred.get().forEach((proc, index) => { + const procGen = new ProcedureLinesGenerator(proc.id, Subject.create(index === 0), ProcedureType.Deferred, proc); + this.lineData.push(...procGen.toLineData()); + }); } super.updateChecklists(); } diff --git a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/ProcedureLinesGenerator.tsx b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/ProcedureLinesGenerator.tsx new file mode 100644 index 00000000000..7a9f9d9bd37 --- /dev/null +++ b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/ProcedureLinesGenerator.tsx @@ -0,0 +1,470 @@ +// Copyright (c) 2024 FlyByWire Simulations +// SPDX-License-Identifier: GPL-3.0 + +import { Subject } from '@microsoft/msfs-sdk'; +import { + AbnormalProcedure, + ChecklistAction, + ChecklistCondition, + ChecklistLineStyle, + ChecklistSpecialItem, + DeferredProcedure, + EcamAbnormalProcedures, + EcamDeferredProcedures, + isChecklistAction, + isChecklistCondition, + NormalProcedure, + WdLineData, + WdSpecialLine, +} from 'instruments/src/MsfsAvionicsCommon/EcamMessages'; +import { EcamNormalProcedures } from 'instruments/src/MsfsAvionicsCommon/EcamMessages/NormalProcedures'; +import { ChecklistState } from 'instruments/src/MsfsAvionicsCommon/providers/FwsEwdPublisher'; + +export enum ProcedureType { + Normal, + Abnormal, + Deferred, +} + +export interface ProcedureItemInfo { + procedureItem: ChecklistAction | ChecklistCondition | ChecklistSpecialItem; + isSelected: boolean; +} + +// Reserve -1 for moveDown (start before top of list and move down to select first selectable) +const SPECIAL_INDEX_ACTIVATE = -2; +const SPECIAL_INDEX_DEFERRED_PROC_COMPLETE = -3; +const SPECIAL_INDEX_DEFERRED_PROC_RECALL = -4; +const SPECIAL_INDEX_NORMAL_CL_COMPLETE = -5; +const SPECIAL_INDEX_NORMAL_RESET = -6; +const SPECIAL_INDEX_CLEAR = -7; +const HIGHEST_SPECIAL_INDEX = SPECIAL_INDEX_ACTIVATE; + +export class ProcedureLinesGenerator { + public readonly selectedItemIndex = Subject.create(0); + + private procedure: AbnormalProcedure | NormalProcedure | DeferredProcedure; + private items: (ChecklistAction | ChecklistCondition | ChecklistSpecialItem)[]; + + constructor( + public procedureId: string, + public procedureIsActive: Subject, + private type: ProcedureType, + public checklistState: ChecklistState, + private itemCheckedCallback?: (newState: ChecklistState) => void, + private procedureClearedOrResetCallback?: (newState: ChecklistState) => void, + private procedureCompletedCallback?: (newState: ChecklistState) => void, + private recommendation?: 'LAND ASAP' | 'LAND ANSA' | undefined, + ) { + if (type === ProcedureType.Normal) { + this.procedure = EcamNormalProcedures[procedureId]; + } else if (type === ProcedureType.Abnormal) { + this.procedure = EcamAbnormalProcedures[procedureId]; + } else if (type === ProcedureType.Deferred) { + this.procedure = EcamDeferredProcedures[procedureId]; + } + this.items = this.procedure.items; + } + + static readonly nonSelectableItemStyles = [ + ChecklistLineStyle.Headline, + ChecklistLineStyle.OmissionDots, + ChecklistLineStyle.SeparationLine, + ChecklistLineStyle.SubHeadline, + ChecklistLineStyle.Amber, + ChecklistLineStyle.Cyan, + ChecklistLineStyle.Green, + ]; + + static conditionalActiveItems( + proc: AbnormalProcedure | DeferredProcedure | NormalProcedure, + itemsChecked: boolean[], + itemsActive: boolean[], + ) { + // Additional logic for conditions: Modify itemsActive based on condition activation status + if (proc.items.some((v) => isChecklistCondition(v))) { + proc.items.forEach((v, i) => { + if (v.level) { + // Look for parent condition(s) + let active = true; + for (let recI = i; recI > 0; recI--) { + active = + (proc.items[recI].level ?? 0) < v.level && isChecklistCondition(proc.items[recI]) + ? active && itemsChecked[recI] + : active; + } + itemsActive[i] = active; + } + }); + } + return itemsActive; + } + + public numLinesUntilSelected(): number { + return this.getActualShownItems().findIndex((v) => v === this.sii); + } + + public numTotalLines(): number { + return this.getActualShownItems().length; + } + + private get selectedItem() { + return this.items[this.selectedItemIndex.get()]; + } + + /** Shorthand for this.selectedItemIndex.get() */ + private get sii() { + return this.selectedItemIndex.get(); + } + + moveUp() { + const selectable = this.selectableItems(true); + + if (selectable.length === 0) { + return; + } + const sii = this.selectedItemIndex.get(); + if (sii === SPECIAL_INDEX_NORMAL_RESET) { + this.selectedItemIndex.set(SPECIAL_INDEX_NORMAL_CL_COMPLETE); + } else if ( + sii === SPECIAL_INDEX_DEFERRED_PROC_COMPLETE || + sii === SPECIAL_INDEX_DEFERRED_PROC_RECALL || + sii === SPECIAL_INDEX_NORMAL_CL_COMPLETE || + sii === SPECIAL_INDEX_CLEAR + ) { + this.selectedItemIndex.set(selectable[selectable.length - 1]); + } else if (sii >= 0) { + const previousElement = () => { + for (let i = selectable.length - 1; i >= 0; i--) { + if (selectable[i] < sii) { + return selectable[i]; + } + } + return -1; + }; + const pEl = previousElement(); + + if (pEl >= 0) { + this.selectedItemIndex.set(Math.max(pEl, 0)); + } + } + } + + moveDown(skipCompletedSensed = true) { + const numItems = this.checklistState.itemsToShow.length; + const selectable = this.selectableItems(skipCompletedSensed); + if (selectable.length == 0 || this.selectedItemIndex.get() >= selectable[selectable.length - 1]) { + // Last element before first special line (CLEAR etc.) + if (this.type === ProcedureType.Normal) { + this.selectedItemIndex.set(SPECIAL_INDEX_NORMAL_CL_COMPLETE); + } else if (this.type === ProcedureType.Abnormal) { + this.selectedItemIndex.set(SPECIAL_INDEX_CLEAR); + } else if (this.type === ProcedureType.Deferred) { + this.selectedItemIndex.set( + !this.checklistState.procedureCompleted || !this.checklistState.procedureActivated + ? SPECIAL_INDEX_DEFERRED_PROC_COMPLETE + : SPECIAL_INDEX_DEFERRED_PROC_RECALL, + ); + } + } else { + const sii = this.selectedItemIndex.get(); + // Check for special lines + if (sii === SPECIAL_INDEX_NORMAL_CL_COMPLETE) { + // Do nothing + this.selectedItemIndex.set(SPECIAL_INDEX_NORMAL_RESET); + } else if (sii > HIGHEST_SPECIAL_INDEX) { + this.selectedItemIndex.set( + Math.min(selectable.find((v) => v > this.selectedItemIndex.get()) ?? numItems - 1, numItems - 1), + ); + } + } + } + + checkSelected() { + const clState: ChecklistState = { + id: this.checklistState.id, + itemsToShow: [...this.checklistState.itemsToShow], + itemsChecked: [...this.checklistState.itemsChecked], + itemsActive: [...this.checklistState.itemsActive], + }; + if ( + this.selectedItemIndex.get() >= 0 && + this.selectedItemIndex.get() < this.getActualShownItems().length && + !this.selectedItem?.sensed + ) { + clState.itemsChecked[this.sii] = !clState.itemsChecked[this.sii]; + this.itemCheckedCallback(clState); + + if (clState.itemsChecked[this.sii]) { + if (isChecklistCondition(this.selectedItem) && this.selectedItem.condition) { + // Force 'active' status update + ProcedureLinesGenerator.conditionalActiveItems(this.procedure, clState.itemsChecked, clState.itemsActive); + } + this.moveDown(false); + } + } else if (this.sii === SPECIAL_INDEX_CLEAR) { + this.procedureClearedOrResetCallback(clState); + } else if (this.sii === SPECIAL_INDEX_NORMAL_CL_COMPLETE) { + clState.procedureCompleted = true; + clState.itemsChecked = clState.itemsChecked.map((val, index) => (this.items[index].sensed ? val : true)); + this.procedureCompletedCallback(clState); + } else if (this.sii === SPECIAL_INDEX_NORMAL_RESET) { + clState.procedureCompleted = false; + clState.itemsChecked = clState.itemsChecked.map((val, index) => (this.items[index].sensed ? val : false)); + this.procedureClearedOrResetCallback(clState); + this.selectFirst(); + } + this.checklistState = clState; + } + + selectFirst() { + const selectableAndNotChecked = this.selectableItems(false); + this.selectedItemIndex.set( + selectableAndNotChecked[0] !== undefined + ? selectableAndNotChecked[0] - 1 + : this.checklistState.itemsChecked.length - 1, + ); + this.moveDown(false); + } + + private selectableItems(skipCompletedSensed: boolean) { + return this.procedure.items + .map((_, index) => (this.itemIsSelectable(index, skipCompletedSensed) ? index : null)) + .filter((v) => v !== null); + } + + private getActualShownItems() { + const lines = [...this.checklistState.itemsToShow] + .map((value, index) => (value ? index : null)) + .filter((v) => v !== null); + this.procedure.items.forEach((v, i) => { + if (isChecklistCondition(v) && !v.sensed) { + // CONFIRM line + lines.splice(i, 0, lines[i]); + lines[i] = NaN; + } + }); + if (this.recommendation) { + lines.splice(0, 0, NaN); + } + + return lines; + } + + /** + * Used for up/down navigation, to skip not selectable items + * @param skipCompletedSensed Whether sensed item is only selectable if unchecked. Not sensed items can't be skipped. + * @returns Procedure item is selectable with arrow keys + */ + private itemIsSelectable(itemIndex: number, skipCompletedSensed: boolean): boolean { + return ( + (!this.items[itemIndex].sensed || (!skipCompletedSensed && !this.checklistState.itemsChecked[itemIndex])) && + this.checklistState.itemsActive[itemIndex] && + this.checklistState.itemsToShow[itemIndex] && + !ProcedureLinesGenerator.nonSelectableItemStyles.includes(this.items[itemIndex].style) + ); + } + + public toLineData(): WdLineData[] { + const lineData: WdLineData[] = []; + + const isAbnormalOrDeferred = this.type === ProcedureType.Abnormal || this.type === ProcedureType.Deferred; + const isAbnormal = this.type === ProcedureType.Abnormal; + const isDeferred = this.type === ProcedureType.Deferred; + + lineData.push({ + abnormalProcedure: isAbnormalOrDeferred, + activeProcedure: this.procedureIsActive.get(), + sensed: true, + checked: false, + text: this.procedure.title, + style: ChecklistLineStyle.Headline, + firstLine: !isDeferred, + lastLine: this.procedureIsActive.get() ? false : true, + }); + + if (!isAbnormal || this.procedureIsActive.get()) { + if (this.recommendation) { + lineData.push({ + abnormalProcedure: isAbnormalOrDeferred, + activeProcedure: this.procedureIsActive.get() || !isAbnormal, + sensed: true, + checked: false, + text: this.recommendation, + style: this.recommendation === 'LAND ASAP' ? ChecklistLineStyle.LandAsap : ChecklistLineStyle.LandAnsa, + firstLine: false, + lastLine: false, + }); + } + + if (isDeferred) { + lineData.push({ + abnormalProcedure: isAbnormalOrDeferred, + activeProcedure: true, + sensed: false, + checked: this.checklistState.procedureCompleted ?? false, + text: `${'\xa0'.repeat(31)}ACTIVATE`, + style: ChecklistLineStyle.ChecklistItem, + firstLine: false, + lastLine: false, + originalItemIndex: -1, + }); + } + + this.items.forEach((item, itemIndex) => { + if (isAbnormal && !this.checklistState.itemsToShow[itemIndex]) { + return; + } + + let clStyle: ChecklistLineStyle = item.style ? item.style : ChecklistLineStyle.ChecklistItem; + let text = item.level ? '\xa0'.repeat(item.level) : ''; + if (isChecklistAction(item)) { + text += clStyle !== ChecklistLineStyle.SubHeadline ? '-' : ''; + text += item.name; + if (!this.checklistState.itemsActive[itemIndex] && clStyle === ChecklistLineStyle.ChecklistItem) { + clStyle = ChecklistLineStyle.ChecklistItemInactive; + } + if (this.checklistState.itemsChecked[itemIndex] && item.labelCompleted) { + text += `${item.colonIfCompleted === false ? ' ' : ' : '}${item.labelCompleted}`; + } else if (this.checklistState.itemsChecked[itemIndex] && item.labelNotCompleted) { + text += `${item.colonIfCompleted === false ? ' ' : ' : '}${item.labelNotCompleted}`; + } else if (!this.checklistState.itemsChecked[itemIndex] && item.labelNotCompleted) { + // Pad to 39 characters max + const paddingNeeded = Math.max( + 0, + 39 - (item.labelNotCompleted.length + item.name.length + (item.level ?? 0) * 1 + 2), + ); + + text += ` ${'.'.repeat(paddingNeeded)}${item.labelNotCompleted}`; + } + } else if (isChecklistCondition(item)) { + clStyle = ChecklistLineStyle.ChecklistCondition; + if (item.name.substring(0, 4) === 'WHEN') { + text += `.${item.name}`; + } else { + text += this.checklistState.itemsChecked[itemIndex] + ? `.AS ${item.name.substring(0, 2) === 'IF' ? item.name.substring(2) : item.name}` + : `.IF ${item.name.substring(0, 2) === 'IF' ? item.name.substring(2) : item.name}`; + } + } else { + text += item.name; + } + + lineData.push({ + abnormalProcedure: isAbnormalOrDeferred, + activeProcedure: this.procedureIsActive.get() || !isAbnormal, + sensed: isChecklistCondition(item) ? true : item.sensed, + checked: this.checklistState.itemsChecked[itemIndex], + text: text.substring(0, 39), + style: clStyle, + firstLine: !this.procedureIsActive.get() && isAbnormal, + lastLine: !this.procedureIsActive.get() && isAbnormal, + originalItemIndex: isChecklistCondition(item) ? undefined : itemIndex, + }); + + if (isChecklistCondition(item) && !item.sensed) { + // Insert CONFIRM + const confirmText = `${item.level ? '\xa0'.repeat(item.level) : ''}CONFIRM ${item.name}`; + lineData.push({ + abnormalProcedure: isAbnormalOrDeferred, + activeProcedure: this.procedureIsActive.get() || !isAbnormal, + sensed: item.sensed, + checked: this.checklistState.itemsChecked[itemIndex], + text: confirmText, + style: clStyle, + firstLine: !this.procedureIsActive.get() && isAbnormal, + lastLine: !this.procedureIsActive.get() && isAbnormal, + originalItemIndex: itemIndex, + }); + } + }); + + if (isAbnormal) { + lineData.push({ + abnormalProcedure: isAbnormalOrDeferred, + activeProcedure: true, + sensed: false, + checked: false, + text: `${'\xa0'.repeat(34)}CLEAR`, + style: ChecklistLineStyle.ChecklistItem, + firstLine: false, + lastLine: true, + originalItemIndex: SPECIAL_INDEX_CLEAR, + }); + } else if (this.type === ProcedureType.Normal) { + lineData.push({ + activeProcedure: true, + sensed: false, + checked: this.checklistState.procedureCompleted ?? false, + text: `${'\xa0'.repeat(27)}C/L COMPLETE`, + style: ChecklistLineStyle.ChecklistItem, + firstLine: false, + lastLine: false, + originalItemIndex: SPECIAL_INDEX_NORMAL_CL_COMPLETE, + }); + + lineData.push({ + activeProcedure: true, + sensed: false, + checked: false, + text: `${'\xa0'.repeat(34)}RESET`, + style: ChecklistLineStyle.ChecklistItem, + firstLine: false, + lastLine: true, + originalItemIndex: SPECIAL_INDEX_NORMAL_RESET, + }); + } else if (isDeferred) { + if (!this.checklistState.procedureCompleted || !this.checklistState.procedureActivated) { + lineData.push({ + activeProcedure: true, + sensed: false, + checked: this.checklistState.procedureCompleted ?? false, + text: `${'\xa0'.repeat(5)}DEFERRED PROC COMPLETE`, + style: ChecklistLineStyle.ChecklistItem, + firstLine: false, + lastLine: false, + originalItemIndex: SPECIAL_INDEX_DEFERRED_PROC_COMPLETE, + }); + } else { + lineData.push({ + activeProcedure: true, + sensed: false, + checked: false, + text: `${'\xa0'.repeat(5)}DEFERRED PROC RECALL`, + style: ChecklistLineStyle.ChecklistItem, + firstLine: false, + lastLine: true, + originalItemIndex: SPECIAL_INDEX_DEFERRED_PROC_RECALL, + }); + } + } + } else { + // Only three dots for following procedures + lineData.push({ + abnormalProcedure: isAbnormalOrDeferred, + activeProcedure: false, + sensed: true, + checked: false, + text: '...', + style: ChecklistLineStyle.OmissionDots, + firstLine: true, + lastLine: true, + }); + } + + // Empty line after procedure + lineData.push({ + abnormalProcedure: isAbnormalOrDeferred, + activeProcedure: this.procedureIsActive.get() || isDeferred, + sensed: true, + checked: false, + text: '', + style: ChecklistLineStyle.ChecklistItem, + firstLine: true, + lastLine: true, + specialLine: WdSpecialLine.Empty, + }); + + return lineData; + } +} diff --git a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/index.tsx b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/index.tsx index 575e7081d0a..4922b9b755b 100644 --- a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/index.tsx +++ b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/index.tsx @@ -597,12 +597,12 @@ export interface ChecklistAction extends AbstractChecklistItem { colonIfCompleted?: boolean; } -interface ChecklistCondition extends AbstractChecklistItem { +export interface ChecklistCondition extends AbstractChecklistItem { /** If this line is a condition. Can be sensed or not sensed (i.e. manually activated). */ condition: true; } -interface ChecklistSpecialItem extends AbstractChecklistItem {} +export interface ChecklistSpecialItem extends AbstractChecklistItem {} export function isChecklistAction(c: AbstractChecklistItem): c is ChecklistAction { return (c as ChecklistAction)?.labelNotCompleted !== undefined; @@ -612,7 +612,9 @@ export function isChecklistCondition(c: AbstractChecklistItem): c is ChecklistCo return (c as ChecklistCondition)?.condition !== undefined; } -export function isAbnormalSensedProcedure(c: AbnormalProcedure | DeferredProcedure): c is AbnormalProcedure { +export function isAbnormalSensedProcedure( + c: AbnormalProcedure | DeferredProcedure | NormalProcedure, +): c is AbnormalProcedure { return (c as AbnormalProcedure)?.recommendation !== undefined; } diff --git a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/providers/FwsEwdPublisher.ts b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/providers/FwsEwdPublisher.ts index 9922706c3fd..9f8f77a1ade 100644 --- a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/providers/FwsEwdPublisher.ts +++ b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/providers/FwsEwdPublisher.ts @@ -2,18 +2,10 @@ // // SPDX-License-Identifier: GPL-3.0 -export interface FwsEwdAbnormalSensedEntry { +export interface ChecklistState { id: string; procedureCompleted?: boolean; procedureActivated?: boolean; - itemsToShow: boolean[]; - itemsChecked: boolean[]; - itemsActive: boolean[]; -} - -export interface NormalChecklistState { - id: number; - checklistCompleted: boolean; itemsChecked: boolean[]; itemsToShow: boolean[]; itemsActive: boolean[]; @@ -30,27 +22,27 @@ export interface AbnormalNonSensedList { * Transmitted from FWS to EWD */ export interface FwsEwdEvents { - /** (FWS -> EWD) Which line to mark as next */ - fws_active_line: number; + /** (FWS -> EWD) Which item from procedure to mark as selected */ + fws_active_item: number; + /** (FWS -> EWD) Which procedure is currently active */ + fws_active_procedure: string; /** (FWS -> EWD) From which line on to show the items, for overflowing procedures */ fws_show_from_line: number; /** (FWS -> EWD) Show normal procedures / ECL */ fws_show_normal_checklists: boolean; /** (FWS -> EWD) List of all normal checklists including deferred procedures */ - fws_normal_checklists: NormalChecklistState[]; + fws_normal_checklists: ChecklistState[]; /** (FWS -> EWD) Which checklist to display */ fws_normal_checklists_id: number; /** (FWS -> EWD) Show abnormal sensed procedures */ fws_show_abn_sensed: boolean; /** (FWS -> EWD) List of abnormal sensed procedures to be displayed */ - fws_abn_sensed_procedures: FwsEwdAbnormalSensedEntry[]; + fws_abn_sensed_procedures: ChecklistState[]; /** (FWS -> EWD) All deferred procedures to be displayed */ - fws_deferred_procedures: FwsEwdAbnormalSensedEntry[]; - /** (FWS -> EWD) List of deferred procedures to be displayed */ - fws_deferred_procedures_show_tod: boolean; + fws_deferred_procedures: ChecklistState[]; /** (FWS -> EWD) Show abnormal non-sensed procedures selection menu */ fws_show_abn_non_sensed: boolean; diff --git a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsAbnormalNonSensed.ts b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsAbnormalNonSensed.ts index dab377b20eb..5d54578d05c 100644 --- a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsAbnormalNonSensed.ts +++ b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsAbnormalNonSensed.ts @@ -2,7 +2,7 @@ // SPDX-License-Identifier: GPL-3.0 import { MapSubject, SimVarValueType, Subject } from '@microsoft/msfs-sdk'; -import { NormalChecklistState, FwsEwdEvents } from 'instruments/src/MsfsAvionicsCommon/providers/FwsEwdPublisher'; +import { ChecklistState, FwsEwdEvents } from 'instruments/src/MsfsAvionicsCommon/providers/FwsEwdPublisher'; import { FwcAuralWarning, FwsCore } from 'systems-host/systems/FlightWarningSystem/FwsCore'; import { EcamAbnormalNonSensedProcedures, @@ -28,7 +28,7 @@ export class FwsAbnormalNonSensed { /** For overflowing checklists */ public readonly showFromLine = Subject.create(0); - public readonly checklistState = MapSubject.create(); + public readonly checklistState = MapSubject.create(); constructor(private fws: FwsCore) { this.checklistId.sub((id) => this.pub.pub('fws_abn_non_sensed_id', id, true), true); diff --git a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsAbnormalSensed.ts b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsAbnormalSensed.ts index 5f59d44f2b7..f33f409cbbd 100644 --- a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsAbnormalSensed.ts +++ b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsAbnormalSensed.ts @@ -2,12 +2,7 @@ // // SPDX-License-Identifier: GPL-3.0 -import { - ChecklistLineStyle, - EcamAbnormalSensedProcedures, - isChecklistCondition, - WD_NUM_LINES, -} from '../../../instruments/src/MsfsAvionicsCommon/EcamMessages'; +import { EcamAbnormalSensedProcedures, WD_NUM_LINES } from '../../../instruments/src/MsfsAvionicsCommon/EcamMessages'; import { MappedSubject, Subject, @@ -16,7 +11,11 @@ import { SubscribableMapFunctions, } from '@microsoft/msfs-sdk'; import { SdPages } from '@shared/EcamSystemPages'; -import { FwsEwdAbnormalSensedEntry, FwsEwdEvents } from 'instruments/src/MsfsAvionicsCommon/providers/FwsEwdPublisher'; +import { + ProcedureLinesGenerator, + ProcedureType, +} from 'instruments/src/MsfsAvionicsCommon/EcamMessages/ProcedureLinesGenerator'; +import { ChecklistState, FwsEwdEvents } from 'instruments/src/MsfsAvionicsCommon/providers/FwsEwdPublisher'; import { FwcAuralWarning, FwsCore } from 'systems-host/systems/FlightWarningSystem/FwsCore'; export interface EwdAbnormalItem { @@ -70,20 +69,24 @@ export class FwsAbnormalSensed { public readonly activeProcedureId = Subject.create(null); /** Marked with cyan box */ - public readonly selectedItem = Subject.create(1); + public readonly selectedItemIndex = Subject.create(1); /** For overflowing checklists */ public readonly showFromLine = Subject.create(0); + private procedures: ProcedureLinesGenerator[] = []; + + private activeProcedure: ProcedureLinesGenerator; + constructor(private fws: FwsCore) { this.fws.activeAbnormalProceduresList.sub( ( - map: ReadonlyMap, - _type: SubscribableMapEventType, - _key: string, - _value: FwsEwdAbnormalSensedEntry, + map: ReadonlyMap, + type: SubscribableMapEventType, + key: string, + value: ChecklistState, ) => { - const flattened: FwsEwdAbnormalSensedEntry[] = []; + const flattened: ChecklistState[] = []; map.forEach((val, key) => flattened.push({ id: key, @@ -93,10 +96,42 @@ export class FwsAbnormalSensed { }), ); // Sort by decreasing importance - console.log(flattened); const sortedAbnormalsFlattened = flattened.sort( (a, b) => this.fws.ewdAbnormal[b.id].failure - this.fws.ewdAbnormal[a.id].failure, ); + + if (type === SubscribableMapEventType.Added) { + const procGen = new ProcedureLinesGenerator( + value.id, + Subject.create(value.id === this.activeProcedureId.get()), + ProcedureType.Abnormal, + value, + (newState) => this.fws.activeAbnormalProceduresList.setValue(value.id, newState), + this.clearActiveProcedure.bind(this), + () => {}, + EcamAbnormalSensedProcedures[value.id].recommendation, + ); + this.procedures.push(procGen); + } else if (type === SubscribableMapEventType.Changed) { + const procGenIndex = this.procedures.findIndex((v) => v.procedureId === key); + if (procGenIndex !== -1) { + this.procedures[procGenIndex].checklistState = value; + } + } else if (type === SubscribableMapEventType.Deleted) { + const procGenIndex = this.procedures.findIndex((v) => v.procedureId === key); + this.procedures.splice(procGenIndex, 1); + } + + sortedAbnormalsFlattened.forEach((val) => { + if (val.id === this.activeProcedureId.get()) { + const procGenIndex = this.procedures.findIndex((v) => v.procedureId === val.id); + if (procGenIndex !== -1) { + this.activeProcedure = this.procedures[procGenIndex]; + this.activeProcedure.selectedItemIndex.pipe(this.selectedItemIndex); + } + } + }); + this.activeProcedureId.set(sortedAbnormalsFlattened.length > 0 ? sortedAbnormalsFlattened[0].id : null); this.pub.pub('fws_abn_sensed_procedures', sortedAbnormalsFlattened, true); }, @@ -105,156 +140,31 @@ export class FwsAbnormalSensed { this.abnormalShown.sub((shown) => { if (shown) { - this.selectFirst(); + this.activeProcedure.selectFirst(); } }); this.activeProcedureId.sub((id) => { if (id) { - this.selectFirst(); + this.procedures.forEach((val) => { + val.procedureIsActive.set(val.procedureId === id); + if (val.procedureId === id) { + this.activeProcedure = val; + this.activeProcedure.selectedItemIndex.pipe(this.selectedItemIndex); + } + }); + this.activeProcedure.selectFirst(); } }); - this.selectedItem.sub(() => this.scrollToSelectedLine()); + this.selectedItemIndex.sub(() => this.scrollToSelectedLine()); } getAbnormalProceduresKeysSorted() { return Array.from(this.fws.activeAbnormalProceduresList.get().keys()); } - selectFirst() { - const clState = this.fws.activeAbnormalProceduresList.getValue(this.activeProcedureId.get()); - const selectableAndNotChecked = this.selectableItems(false); - this.selectedItem.set( - selectableAndNotChecked[0] !== undefined ? selectableAndNotChecked[0] - 1 : clState.itemsChecked.length - 1, - ); - this.moveDown(false); - } - - moveUp() { - const selectable = this.selectableItems(true); - - if (selectable.length === 0) { - return; - } - const previousElement = () => { - for (let i = selectable.length - 1; i >= 0; i--) { - if (selectable[i] < this.selectedItem.get()) { - return selectable[i]; - } - } - return -1; - }; - const pEl = previousElement(); - - if (pEl >= 0) { - this.selectedItem.set(Math.max(pEl, 0)); - } - } - - static readonly nonSelectableItemStyles = [ - ChecklistLineStyle.Headline, - ChecklistLineStyle.OmissionDots, - ChecklistLineStyle.SeparationLine, - ChecklistLineStyle.SubHeadline, - ChecklistLineStyle.Amber, - ChecklistLineStyle.Cyan, - ChecklistLineStyle.Green, - ]; - - /** - * Used for up/down navigation, to skip not selectable items - * @param skipCompletedSensed Whether sensed item is only selectable if unchecked. Not sensed items can't be skipped. - * @returns Procedure item is selectable with arrow keys - */ - private itemIsSelectable(itemIndex: number, skipCompletedSensed: boolean): boolean { - const procId = this.activeProcedureId.get(); - const clState = this.fws.activeAbnormalProceduresList.getValue(this.activeProcedureId.get()); - return ( - (!EcamAbnormalSensedProcedures[procId].items[itemIndex].sensed || - (!skipCompletedSensed && !clState.itemsChecked[itemIndex])) && - clState.itemsActive[itemIndex] && - clState.itemsToShow[itemIndex] && - !FwsAbnormalSensed.nonSelectableItemStyles.includes(EcamAbnormalSensedProcedures[procId].items[itemIndex].style) - ); - } - - private selectableItems(skipCompletedSensed: boolean) { - return EcamAbnormalSensedProcedures[this.activeProcedureId.get()].items - .map((_, index) => (this.itemIsSelectable(index, skipCompletedSensed) ? index : null)) - .filter((v) => v !== null); - } - - private getActualShownItems() { - const proc = EcamAbnormalSensedProcedures[this.activeProcedureId.get()]; - const lines = [...this.fws.activeAbnormalProceduresList.getValue(this.activeProcedureId.get()).itemsToShow] - .map((value, index) => (value ? index : null)) - .filter((v) => v !== null); - proc.items.forEach((v, i) => { - if (isChecklistCondition(v) && !v.sensed) { - // CONFIRM line - lines.splice(i, 0, lines[i]); - lines[i] = NaN; - } - }); - if (proc.recommendation) { - lines.splice(0, 0, NaN); - } - - return lines; - } - - /** Returns the index from selectedItem amongst the displayed items */ - private lineInDisplay(selectedItem: number) { - return this.fws.activeAbnormalProceduresList.has(this.activeProcedureId.get()) - ? this.getActualShownItems().findIndex((v) => v === selectedItem) - : -1; - } - - moveDown(skipCompletedSensed = true) { - const numItems = this.fws.activeAbnormalProceduresList.getValue(this.activeProcedureId.get()).itemsToShow.length; - const selectable = this.selectableItems(skipCompletedSensed); - if (selectable.length == 0 || this.selectedItem.get() >= selectable[selectable.length - 1]) { - // Last element before CLEAR - this.selectedItem.set(numItems); - } else { - this.selectedItem.set( - Math.min(selectable.find((v) => v > this.selectedItem.get()) ?? numItems - 1, numItems - 1), - ); - } - } - - checkCurrentItem() { - const cl = this.fws.activeAbnormalProceduresList.getValue(this.activeProcedureId.get()); - const clState: FwsEwdAbnormalSensedEntry = { - id: cl.id, - itemsToShow: [...cl.itemsToShow], - itemsChecked: [...cl.itemsChecked], - itemsActive: [...cl.itemsActive], - }; - const proc = EcamAbnormalSensedProcedures[this.activeProcedureId.get()]; - const procItem = proc.items[this.selectedItem.get()]; - if (this.selectedItem.get() < this.getActualShownItems().length && !procItem?.sensed) { - clState.itemsChecked[this.selectedItem.get()] = !clState.itemsChecked[this.selectedItem.get()]; - this.fws.activeAbnormalProceduresList.setValue(this.activeProcedureId.get(), clState); - if (clState.itemsChecked[this.selectedItem.get()]) { - if (isChecklistCondition(procItem) && procItem.condition) { - // Force 'active' status update - FwsCore.conditionalActiveItems(proc, clState.itemsChecked, clState.itemsActive); - } - this.moveDown(false); - } - } else if (this.selectedItem.get() === clState.itemsChecked.length) { - this.clearActiveProcedure(); - } - } - public clearActiveProcedure() { - console.log( - this.fws.presentedFailures, - parseInt(this.activeProcedureId.get()), - this.fws.activeAbnormalNonSensedKeys.includes(parseInt(this.activeProcedureId.get())), - ); this.fws.presentedFailures.splice(0, 1); this.fws.recallFailures = this.fws.allCurrentFailures.filter((item) => !this.fws.presentedFailures.includes(item)); @@ -267,17 +177,7 @@ export class FwsAbnormalSensed { } private scrollToSelectedLine() { - const itemsShown = this.getActualShownItems(); - const lastItemIndex = itemsShown[itemsShown.length - 1]; - if ( - this.fws.activeAbnormalProceduresList.has(this.activeProcedureId.get()) && - this.selectedItem.get() === lastItemIndex + 1 - ) { - // CLEAR - this.showFromLine.set(Math.max(0, itemsShown.length - WD_NUM_LINES + 2)); - } else { - this.showFromLine.set(Math.max(0, this.lineInDisplay(this.selectedItem.get()) - WD_NUM_LINES + 2)); - } + this.showFromLine.set(Math.max(0, this.activeProcedure.numLinesUntilSelected() - WD_NUM_LINES + 2)); } /** @@ -296,15 +196,15 @@ export class FwsAbnormalSensed { } if (this.fws.clDownPulseNode.read()) { - this.moveDown(true); + this.activeProcedure.moveDown(true); } if (this.fws.clUpPulseNode.read()) { - this.moveUp(); + this.activeProcedure.moveUp(); } if (this.fws.clCheckPulseNode.read()) { - this.checkCurrentItem(); + this.activeProcedure.checkSelected(); } // Auto-move-down if currently marked item was sensed as completed @@ -317,15 +217,12 @@ export class FwsAbnormalSensed { continue; } - const changedEntries = this.fws.abnormalUpdatedItems.get(procId); - if ( - changedEntries && - changedEntries.includes(this.selectedItem.get()) && - this.fws.activeAbnormalProceduresList.getValue(this.activeProcedureId.get()).itemsChecked[ - this.selectedItem.get() - ] - ) { - this.moveDown(false); + if (procId === this.activeProcedureId.get()) { + const changedEntries = this.fws.abnormalUpdatedItems.get(procId); + const sii = this.activeProcedure.selectedItemIndex.get(); + if (changedEntries && changedEntries.includes(sii) && this.activeProcedure.checklistState.itemsChecked[sii]) { + this.activeProcedure.moveDown(false); + } } } } diff --git a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsCore.ts b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsCore.ts index 1e8b269d944..18a073bfc32 100644 --- a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsCore.ts +++ b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsCore.ts @@ -36,19 +36,14 @@ import { VhfComManagerDataEvents } from '@flybywiresim/rmp'; import { PseudoFwcSimvars } from 'instruments/src/MsfsAvionicsCommon/providers/PseudoFwcPublisher'; import { FuelSystemEvents } from 'instruments/src/MsfsAvionicsCommon/providers/FuelSystemPublisher'; import { - AbnormalProcedure, - DeferredProcedure, EcamAbnormalProcedures, EcamDeferredProcedures, EcamMemos, - isChecklistCondition, pfdMemoDisplay, -} from '../../../instruments/src/MsfsAvionicsCommon/EcamMessages'; +} from 'instruments/src/MsfsAvionicsCommon/EcamMessages'; +import { ProcedureLinesGenerator } from 'instruments/src/MsfsAvionicsCommon/EcamMessages/ProcedureLinesGenerator'; import PitchTrimUtils from '@shared/PitchTrimUtils'; -import { - FwsEwdAbnormalSensedEntry, - FwsEwdEvents, -} from '../../../instruments/src/MsfsAvionicsCommon/providers/FwsEwdPublisher'; +import { ChecklistState, FwsEwdEvents } from 'instruments/src/MsfsAvionicsCommon/providers/FwsEwdPublisher'; import { FwsMemos } from 'systems-host/systems/FlightWarningSystem/FwsMemos'; import { FwsNormalChecklists } from 'systems-host/systems/FlightWarningSystem/FwsNormalChecklists'; import { @@ -232,10 +227,10 @@ export class FwsCore { public readonly activeAbnormalNonSensedKeys: number[] = []; /** Map to hold all failures which are currently active */ - public readonly activeAbnormalProceduresList = MapSubject.create(); + public readonly activeAbnormalProceduresList = MapSubject.create(); /** Map to hold all deferred procs which are currently active */ - public readonly activeDeferredProceduresList = MapSubject.create(); + public readonly activeDeferredProceduresList = MapSubject.create(); /** Indices of items which were updated */ public readonly abnormalUpdatedItems = new Map(); @@ -3867,7 +3862,7 @@ export class FwsCore { const itemsChecked = value.whichItemsChecked().map((v, i) => (proc.items[i].sensed === false ? false : !!v)); const itemsToShow = value.whichItemsToShow ? value.whichItemsToShow() : Array(itemsChecked.length).fill(true); const itemsActive = value.whichItemsActive ? value.whichItemsActive() : Array(itemsChecked.length).fill(true); - FwsCore.conditionalActiveItems(proc, itemsChecked, itemsActive); + ProcedureLinesGenerator.conditionalActiveItems(proc, itemsChecked, itemsActive); if (newWarning) { failureKeys.push(key); @@ -3941,7 +3936,7 @@ export class FwsCore { const fusedChecked = [...prevEl.itemsChecked].map((val, index) => proc.items[index].sensed ? itemsChecked[index] : !!val, ); - FwsCore.conditionalActiveItems(proc, fusedChecked, itemsActive); + ProcedureLinesGenerator.conditionalActiveItems(proc, fusedChecked, itemsActive); this.abnormalUpdatedItems.set(key, []); proc.items.forEach((item, idx) => { if ( @@ -4009,13 +4004,13 @@ export class FwsCore { const itemsChecked = value.whichItemsChecked().map((v, i) => (proc.items[i].sensed === false ? false : !!v)); const itemsToShow = value.whichItemsToShow ? value.whichItemsToShow() : Array(itemsChecked.length).fill(true); const itemsActive = value.whichItemsActive ? value.whichItemsActive() : Array(itemsChecked.length).fill(true); - FwsCore.conditionalActiveItems(proc, itemsChecked, itemsActive); + ProcedureLinesGenerator.conditionalActiveItems(proc, itemsChecked, itemsActive); const prevEl = value; const fusedChecked = [...prevEl.itemsChecked].map((val, index) => proc.items[index].sensed ? itemsChecked[index] : !!val, ); - FwsCore.conditionalActiveItems(proc, fusedChecked, itemsActive); + ProcedureLinesGenerator.conditionalActiveItems(proc, fusedChecked, itemsActive); this.deferredUpdatedItems.set(key, []); proc.items.forEach((item, idx) => { if ( @@ -4243,7 +4238,7 @@ export class FwsCore { this.normalChecklists.checklistShown.set(false); this.abnormalSensed.abnormalShown.set(false); - pub.pub('fws_active_line', this.abnormalNonSensed.selectedItem.get(), true); + pub.pub('fws_active_item', this.abnormalNonSensed.selectedItem.get(), true); pub.pub('fws_show_from_line', this.abnormalNonSensed.showFromLine.get(), true); this.ecamEwdShowFailurePendingIndication.set(false); } else if (this.normalChecklists.showChecklistRequested.get()) { @@ -4252,7 +4247,7 @@ export class FwsCore { this.normalChecklists.checklistShown.set(true); this.abnormalSensed.abnormalShown.set(false); - pub.pub('fws_active_line', this.normalChecklists.selectedLine.get(), true); + pub.pub('fws_active_item', this.normalChecklists.selectedLine.get(), true); pub.pub('fws_show_from_line', this.normalChecklists.showFromLine.get(), true); this.ecamEwdShowFailurePendingIndication.set(this.abnormalSensed.showAbnormalSensedRequested.get()); } else if (this.abnormalSensed.showAbnormalSensedRequested.get()) { @@ -4260,7 +4255,8 @@ export class FwsCore { this.normalChecklists.checklistShown.set(false); this.abnormalSensed.abnormalShown.set(true); - pub.pub('fws_active_line', this.abnormalSensed.selectedItem.get(), true); + pub.pub('fws_active_item', this.abnormalSensed.selectedItemIndex.get(), true); + pub.pub('fws_active_procedure', this.abnormalSensed.activeProcedureId.get(), true); pub.pub('fws_show_from_line', this.abnormalSensed.showFromLine.get(), true); this.ecamEwdShowFailurePendingIndication.set(false); } else { @@ -4287,30 +4283,6 @@ export class FwsCore { this.autoPilotInstinctiveDiscCountSinceLastFwsCycle = 0; } - static conditionalActiveItems( - proc: AbnormalProcedure | DeferredProcedure, - itemsChecked: boolean[], - itemsActive: boolean[], - ) { - // Additional logic for conditions: Modify itemsActive based on condition activation status - if (proc.items.some((v) => isChecklistCondition(v))) { - proc.items.forEach((v, i) => { - if (v.level) { - // Look for parent condition(s) - let active = true; - for (let recI = i; recI > 0; recI--) { - active = - (proc.items[recI].level ?? 0) < v.level && isChecklistCondition(proc.items[recI]) - ? active && itemsChecked[recI] - : active; - } - itemsActive[i] = active; - } - }); - } - return itemsActive; - } - updateRowRopWarnings() { const w = Arinc429Word.fromSimVarValue('L:A32NX_ROW_ROP_WORD_1'); diff --git a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsNormalChecklists.ts b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsNormalChecklists.ts index e215a4d9198..1e7fb271b4d 100644 --- a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsNormalChecklists.ts +++ b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsNormalChecklists.ts @@ -2,23 +2,22 @@ // SPDX-License-Identifier: GPL-3.0 import { MapSubject, SimVarValueType, Subject, SubscribableMapEventType } from '@microsoft/msfs-sdk'; -import { - NormalChecklistState, - FwsEwdEvents, - FwsEwdAbnormalSensedEntry, -} from 'instruments/src/MsfsAvionicsCommon/providers/FwsEwdPublisher'; +import { ChecklistState, FwsEwdEvents } from 'instruments/src/MsfsAvionicsCommon/providers/FwsEwdPublisher'; import { FwsCore } from 'systems-host/systems/FlightWarningSystem/FwsCore'; import { deferredProcedureIds, EcamNormalProcedures, } from 'instruments/src/MsfsAvionicsCommon/EcamMessages/NormalProcedures'; import { - ChecklistLineStyle, DeferredProcedureType, EcamDeferredProcedures, NormalProcedure, WD_NUM_LINES, } from 'instruments/src/MsfsAvionicsCommon/EcamMessages'; +import { + ProcedureLinesGenerator, + ProcedureType, +} from 'instruments/src/MsfsAvionicsCommon/EcamMessages/ProcedureLinesGenerator'; export interface NormalEclSensedItems { /** Returns a boolean vector (same length as number of items). If true, item is marked as completed. If null, it's a non-sensed item */ @@ -44,7 +43,7 @@ export class FwsNormalChecklists { /** For overflowing checklists */ public readonly showFromLine = Subject.create(0); - public readonly checklistState = MapSubject.create(); + public readonly checklistState = MapSubject.create(); /** ALL PHASES, TOP OF DESCENT, FOR APPROACH, FOR LANDING */ private readonly hasDeferred = [false, false, false, false]; @@ -52,19 +51,21 @@ export class FwsNormalChecklists { /** ALL PHASES, TOP OF DESCENT, FOR APPROACH, FOR LANDING */ private readonly deferredIsCompleted = [false, false, false, false]; + private activeProcedure: ProcedureLinesGenerator; + constructor(private fws: FwsCore) { this.checklistState.sub( ( - map: ReadonlyMap, + map: ReadonlyMap, _type: SubscribableMapEventType, _key: number, - _value: NormalChecklistState, + _value: ChecklistState, ) => { - const flattened: NormalChecklistState[] = []; + const flattened: ChecklistState[] = []; map.forEach((val, key) => flattened.push({ - id: key, - checklistCompleted: val.checklistCompleted, + id: key.toString(), + procedureCompleted: val.procedureCompleted, itemsChecked: val.itemsChecked, itemsActive: val.itemsActive, itemsToShow: val.itemsToShow, @@ -74,16 +75,40 @@ export class FwsNormalChecklists { }, true, ); - this.checklistId.sub((id) => this.pub.pub('fws_normal_checklists_id', id, true), true); + this.checklistId.sub((id) => { + if (id !== 0) { + const clState = this.checklistState.getValue(id); + const procGen = new ProcedureLinesGenerator( + clState.id, + Subject.create(true), + ProcedureType.Normal, + clState, + (newState) => { + this.checklistState.setValue(this.checklistId.get(), newState); + }, + (newState) => { + this.checklistState.setValue(this.checklistId.get(), newState); + this.resetFollowingChecklists(); + }, + (newState) => { + this.checklistState.setValue(this.checklistId.get(), newState); + this.showChecklistRequested.set(false); + }, + ); + this.activeProcedure = procGen; + this.activeProcedure.selectedItemIndex.pipe(this.selectedLine); + } + this.pub.pub('fws_normal_checklists_id', id, true); + }, true); this.fws.activeDeferredProceduresList.sub( ( - map: ReadonlyMap, + map: ReadonlyMap, _type: SubscribableMapEventType, _key: string, - _value: FwsEwdAbnormalSensedEntry, + _value: ChecklistState, ) => { - const flattened: FwsEwdAbnormalSensedEntry[] = []; + const flattened: ChecklistState[] = []; map.forEach((val, key) => flattened.push({ id: key, @@ -103,8 +128,8 @@ export class FwsNormalChecklists { keys.forEach((k) => { const proc = EcamNormalProcedures[k] as NormalProcedure; this.checklistState.setValue(k, { - id: k, - checklistCompleted: false, + id: k.toString(), + procedureCompleted: false, itemsChecked: Array(proc.items.length).fill(false), itemsActive: Array(proc.items.length).fill(true), itemsToShow: Array(proc.items.length).fill(true), @@ -112,8 +137,8 @@ export class FwsNormalChecklists { }); this.checklistState.setValue(0, { - id: 0, - checklistCompleted: false, + id: '0', + procedureCompleted: false, itemsChecked: Array(Object.keys(EcamNormalProcedures).length).fill(false), itemsActive: Array(Object.keys(EcamNormalProcedures).length).fill(true), itemsToShow: Array(Object.keys(EcamNormalProcedures).length).fill(true), @@ -141,25 +166,15 @@ export class FwsNormalChecklists { const keys = this.getNormalProceduresKeysSorted(true); let firstIncompleteChecklist = 0; keys.some((key, index) => { - if (!this.checklistState.getValue(key).checklistCompleted) { + if (!this.checklistState.getValue(key).procedureCompleted) { firstIncompleteChecklist = index; return true; } }); - this.selectedLine.set(firstIncompleteChecklist - 1); - } else if (!deferredProcedureIds.includes(this.checklistId.get())) { - const clState = this.checklistState.getValue(this.checklistId.get()); - const selectableAndNotChecked = EcamNormalProcedures[this.checklistId.get()].items - .map((_, index) => (clState.itemsChecked[index] === false ? index : null)) - .filter((v) => v !== null); - this.selectedLine.set( - selectableAndNotChecked[0] !== undefined ? selectableAndNotChecked[0] - 1 : clState.itemsChecked.length - 1, - ); + this.selectedLine.set(firstIncompleteChecklist); } else { - // Deferred procedure - this.selectedLine.set(-2); + this.activeProcedure.selectFirst(); } - this.moveDown(false); } moveUp() { @@ -169,65 +184,10 @@ export class FwsNormalChecklists { .filter((v) => v !== null); this.selectedLine.set(Math.max(shownItems[shownItems.indexOf(this.selectedLine.get()) - 1] ?? 0, 0)); } else { - const numItems = EcamNormalProcedures[this.checklistId.get()].items.length; - const selectable = this.selectableItems(true); - - if (this.selectedLine.get() == numItems + 1) { - // RESET - this.selectedLine.set(this.selectedLine.get() - 1); - } else { - if (selectable.length === 0) { - return; - } - const previousElement = () => { - for (let i = selectable.length - 1; i >= 0; i--) { - if (selectable[i] < this.selectedLine.get()) { - return selectable[i]; - } - } - return -1; - }; - const pEl = previousElement(); - - if (pEl >= 0) { - this.selectedLine.set(Math.max(pEl, 0)); - } - } + this.activeProcedure.moveUp(); } } - static readonly nonSelectableItemStyles = [ - ChecklistLineStyle.Headline, - ChecklistLineStyle.OmissionDots, - ChecklistLineStyle.SeparationLine, - ChecklistLineStyle.SubHeadline, - ChecklistLineStyle.Amber, - ChecklistLineStyle.Cyan, - ChecklistLineStyle.Green, - ]; - - /** - * Used for up/down navigation, to skip not selectable items - * @param skipCompletedSensed Whether sensed item is only selectable if unchecked. Not sensed items can't be skipped. - * @returns Procedure item is selectable with arrow keys - */ - private itemIsSelectable(itemIndex: number, skipCompletedSensed: boolean): boolean { - const clState = this.checklistState.getValue(this.checklistId.get()); - return ( - (!EcamNormalProcedures[this.checklistId.get()].items[itemIndex].sensed || - (!skipCompletedSensed && !clState.itemsChecked[itemIndex])) && - !FwsNormalChecklists.nonSelectableItemStyles.includes( - EcamNormalProcedures[this.checklistId.get()].items[itemIndex].style, - ) - ); - } - - private selectableItems(skipCompletedSensed: boolean) { - return EcamNormalProcedures[this.checklistId.get()].items - .map((_, index) => (this.itemIsSelectable(index, skipCompletedSensed) ? index : null)) - .filter((v) => v !== null); - } - moveDown(skipCompletedSensed = true) { if (this.checklistId.get() === 0) { const shownItems = this.getNormalProceduresKeysSorted() @@ -240,78 +200,32 @@ export class FwsNormalChecklists { this.getNormalProceduresKeysSorted(true).length, ), ); - } else if (!deferredProcedureIds.includes(this.checklistId.get())) { - const numItems = EcamNormalProcedures[this.checklistId.get()].items.length; - const selectable = this.selectableItems(skipCompletedSensed); - if (this.selectedLine.get() >= selectable[selectable.length - 1] || selectable.length == 0) { - // Last element before C/L complete - this.selectedLine.set(Math.max(numItems, Math.min(this.selectedLine.get() + 1, numItems + 1))); - } else { - this.selectedLine.set( - Math.min( - selectable.find((v) => v > this.selectedLine.get()), - numItems - 1, - ), - ); - } } else { - //... + this.activeProcedure.moveDown(skipCompletedSensed); } } - checkCurrentItem() { - const cl = this.checklistState.getValue(this.checklistId.get()); - const clState: NormalChecklistState = { - id: cl.id, - checklistCompleted: cl.checklistCompleted, - itemsChecked: [...cl.itemsChecked], - itemsActive: [...cl.itemsActive], - itemsToShow: [...cl.itemsToShow], - }; - const proc = EcamNormalProcedures[this.checklistId.get()]; - if ( - this.selectedLine.get() < clState.itemsChecked.length && - proc.items[this.selectedLine.get()]?.sensed === false - ) { - clState.itemsChecked[this.selectedLine.get()] = !clState.itemsChecked[this.selectedLine.get()]; - this.checklistState.setValue(this.checklistId.get(), clState); - if (clState.itemsChecked[this.selectedLine.get()]) { - this.moveDown(false); - } - } else if (this.selectedLine.get() === clState.itemsChecked.length) { - // C/L complete - clState.checklistCompleted = true; - clState.itemsChecked = clState.itemsChecked.map((val, index) => (proc.items[index].sensed ? val : true)); - this.checklistState.setValue(this.checklistId.get(), clState); - this.showChecklistRequested.set(false); - } else if (this.selectedLine.get() === clState.itemsChecked.length + 1) { - // RESET - clState.checklistCompleted = false; - clState.itemsChecked = clState.itemsChecked.map((val, index) => (proc.items[index].sensed ? val : false)); - - // Reset all following checklists - const fromId = this.getNormalProceduresKeysSorted().findIndex((v) => v === this.checklistId.get()); - const ids = this.getNormalProceduresKeysSorted(); - - if (fromId !== -1) { - for (let id = fromId + 1; id < ids.length; id++) { - const idFollowing = ids[id]; - const clFollowing = this.checklistState.getValue(idFollowing); - const procFollowing = EcamNormalProcedures[idFollowing]; - const clStateFollowing: NormalChecklistState = { - id: idFollowing, - checklistCompleted: procFollowing.deferred ? true : false, - itemsChecked: [...clFollowing.itemsChecked].map((val, index) => - procFollowing.items[index].sensed ? val : false, - ), - itemsActive: clFollowing.itemsActive, - itemsToShow: clFollowing.itemsToShow, - }; - this.checklistState.setValue(idFollowing, clStateFollowing); - } + resetFollowingChecklists() { + // Reset all following checklists + const fromId = this.getNormalProceduresKeysSorted().findIndex((v) => v === this.checklistId.get()); + const ids = this.getNormalProceduresKeysSorted(); + + if (fromId !== -1) { + for (let id = fromId + 1; id < ids.length; id++) { + const idFollowing = ids[id]; + const clFollowing = this.checklistState.getValue(idFollowing); + const procFollowing = EcamNormalProcedures[idFollowing]; + const clStateFollowing: ChecklistState = { + id: idFollowing.toString(), + procedureCompleted: procFollowing.deferred ? true : false, + itemsChecked: [...clFollowing.itemsChecked].map((val, index) => + procFollowing.items[index].sensed ? val : false, + ), + itemsActive: clFollowing.itemsActive, + itemsToShow: clFollowing.itemsToShow, + }; + this.checklistState.setValue(idFollowing, clStateFollowing); } - this.checklistState.setValue(this.checklistId.get(), clState); - this.selectFirst(); } } @@ -347,7 +261,7 @@ export class FwsNormalChecklists { // Navigate to check list this.navigateToChecklist(this.getNormalProceduresKeysSorted()[this.selectedLine.get()]); } else { - this.checkCurrentItem(); + this.activeProcedure.checkSelected(); } } @@ -374,9 +288,9 @@ export class FwsNormalChecklists { this.moveDown(); } } - const clState: NormalChecklistState = { - id: procId, - checklistCompleted: cl.checklistCompleted, + const clState: ChecklistState = { + id: procId.toString(), + procedureCompleted: cl.procedureCompleted, itemsChecked: [...cl.itemsChecked].map((val, index) => proc.items[index].sensed && sensedResult[index] != null ? sensedResult[index] : val, ), From bda2fbf17f8451e7f1d0d8033a29fc90010affe2 Mon Sep 17 00:00:00 2001 From: Florian Gross <63071941+flogross89@users.noreply.github.com> Date: Mon, 16 Dec 2024 01:34:54 +0200 Subject: [PATCH 14/40] deferred proc fixes --- .../EcamMessages/ProcedureLinesGenerator.tsx | 6 ++-- .../systems/FlightWarningSystem/FwsCore.ts | 3 -- .../FwsNormalChecklists.ts | 28 +++++++++++++++++-- 3 files changed, 29 insertions(+), 8 deletions(-) diff --git a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/ProcedureLinesGenerator.tsx b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/ProcedureLinesGenerator.tsx index 7a9f9d9bd37..57d4355cf38 100644 --- a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/ProcedureLinesGenerator.tsx +++ b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/ProcedureLinesGenerator.tsx @@ -419,10 +419,10 @@ export class ProcedureLinesGenerator { activeProcedure: true, sensed: false, checked: this.checklistState.procedureCompleted ?? false, - text: `${'\xa0'.repeat(5)}DEFERRED PROC COMPLETE`, + text: `${'\xa0'.repeat(17)}DEFERRED PROC COMPLETE`, style: ChecklistLineStyle.ChecklistItem, firstLine: false, - lastLine: false, + lastLine: true, originalItemIndex: SPECIAL_INDEX_DEFERRED_PROC_COMPLETE, }); } else { @@ -430,7 +430,7 @@ export class ProcedureLinesGenerator { activeProcedure: true, sensed: false, checked: false, - text: `${'\xa0'.repeat(5)}DEFERRED PROC RECALL`, + text: `${'\xa0'.repeat(18)}DEFERRED PROC RECALL`, style: ChecklistLineStyle.ChecklistItem, firstLine: false, lastLine: true, diff --git a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsCore.ts b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsCore.ts index 18a073bfc32..6a51ccf2946 100644 --- a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsCore.ts +++ b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsCore.ts @@ -3930,9 +3930,6 @@ export class FwsCore { } else if (this.activeAbnormalProceduresList.has(key)) { // Update internal map const prevEl = this.activeAbnormalProceduresList.getValue(key); - if (!proc.items) { - console.log(proc, prevEl); - } const fusedChecked = [...prevEl.itemsChecked].map((val, index) => proc.items[index].sensed ? itemsChecked[index] : !!val, ); diff --git a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsNormalChecklists.ts b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsNormalChecklists.ts index 1e7fb271b4d..1376f2de84f 100644 --- a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsNormalChecklists.ts +++ b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsNormalChecklists.ts @@ -51,6 +51,11 @@ export class FwsNormalChecklists { /** ALL PHASES, TOP OF DESCENT, FOR APPROACH, FOR LANDING */ private readonly deferredIsCompleted = [false, false, false, false]; + /** ID of active deferred procedure */ + public readonly activeDeferredProcedureId = Subject.create(null); + + private deferredProcedures: ProcedureLinesGenerator[] = []; + private activeProcedure: ProcedureLinesGenerator; constructor(private fws: FwsCore) { @@ -76,7 +81,7 @@ export class FwsNormalChecklists { true, ); this.checklistId.sub((id) => { - if (id !== 0) { + if (id !== 0 && !deferredProcedureIds.includes(id)) { const clState = this.checklistState.getValue(id); const procGen = new ProcedureLinesGenerator( clState.id, @@ -97,6 +102,25 @@ export class FwsNormalChecklists { ); this.activeProcedure = procGen; this.activeProcedure.selectedItemIndex.pipe(this.selectedLine); + } else if (deferredProcedureIds.includes(id)) { + this.deferredProcedures = []; + const firstProcedureKey = Object.keys(this.fws.activeDeferredProceduresList.get())[0]; + this.fws.activeDeferredProceduresList.get().forEach((proc, key) => { + const procGen = new ProcedureLinesGenerator( + proc.id, + Subject.create(proc.id === firstProcedureKey), + ProcedureType.Deferred, + proc, + (newState) => { + this.fws.activeDeferredProceduresList.setValue(key, newState); + }, + ); + this.deferredProcedures.push(procGen); + }); + + this.activeDeferredProcedureId.set(firstProcedureKey); + this.activeProcedure = this.deferredProcedures[0]; + this.activeProcedure.selectedItemIndex.pipe(this.selectedLine); } this.pub.pub('fws_normal_checklists_id', id, true); }, true); @@ -129,7 +153,7 @@ export class FwsNormalChecklists { const proc = EcamNormalProcedures[k] as NormalProcedure; this.checklistState.setValue(k, { id: k.toString(), - procedureCompleted: false, + procedureCompleted: proc.deferred ? true : false, itemsChecked: Array(proc.items.length).fill(false), itemsActive: Array(proc.items.length).fill(true), itemsToShow: Array(proc.items.length).fill(true), From 8e5561fefc33b148f2f951350b9d2522e89c7d5e Mon Sep 17 00:00:00 2001 From: Florian Gross <63071941+flogross89@users.noreply.github.com> Date: Wed, 18 Dec 2024 04:21:01 +0200 Subject: [PATCH 15/40] deferred work --- .../src/EWD/elements/WdNormalChecklists.tsx | 2 +- .../EcamMessages/ProcedureLinesGenerator.tsx | 66 ++++++++++++++----- .../systems/FlightWarningSystem/FwsCore.ts | 3 +- .../FwsNormalChecklists.ts | 6 ++ 4 files changed, 59 insertions(+), 18 deletions(-) diff --git a/fbw-a380x/src/systems/instruments/src/EWD/elements/WdNormalChecklists.tsx b/fbw-a380x/src/systems/instruments/src/EWD/elements/WdNormalChecklists.tsx index 16422b0e619..f8c092505b8 100644 --- a/fbw-a380x/src/systems/instruments/src/EWD/elements/WdNormalChecklists.tsx +++ b/fbw-a380x/src/systems/instruments/src/EWD/elements/WdNormalChecklists.tsx @@ -130,7 +130,7 @@ export class WdNormalChecklists extends WdAbstractChecklistComponent { abnormalProcedure: true, sensed: true, checked: false, - text: `\x1b4m${clState.procedureCompleted ? '\x1b<4m' : ''}${EcamNormalProcedures[parseInt(clState.id)].title} \x1bm`, + text: `\x1b4m${clState.procedureCompleted ? '' : '\x1b<4m'}${EcamNormalProcedures[parseInt(clState.id)].title} \x1bm`, style: ChecklistLineStyle.Headline, firstLine: true, lastLine: false, diff --git a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/ProcedureLinesGenerator.tsx b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/ProcedureLinesGenerator.tsx index 57d4355cf38..423d597d6cd 100644 --- a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/ProcedureLinesGenerator.tsx +++ b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/ProcedureLinesGenerator.tsx @@ -118,6 +118,11 @@ export class ProcedureLinesGenerator { } moveUp() { + if (!this.checklistState.procedureActivated) { + this.selectedItemIndex.set(SPECIAL_INDEX_ACTIVATE); + return; + } + const selectable = this.selectableItems(true); if (selectable.length === 0) { @@ -128,7 +133,6 @@ export class ProcedureLinesGenerator { this.selectedItemIndex.set(SPECIAL_INDEX_NORMAL_CL_COMPLETE); } else if ( sii === SPECIAL_INDEX_DEFERRED_PROC_COMPLETE || - sii === SPECIAL_INDEX_DEFERRED_PROC_RECALL || sii === SPECIAL_INDEX_NORMAL_CL_COMPLETE || sii === SPECIAL_INDEX_CLEAR ) { @@ -151,6 +155,11 @@ export class ProcedureLinesGenerator { } moveDown(skipCompletedSensed = true) { + if (!this.checklistState.procedureActivated) { + this.selectedItemIndex.set(SPECIAL_INDEX_ACTIVATE); + return; + } + const numItems = this.checklistState.itemsToShow.length; const selectable = this.selectableItems(skipCompletedSensed); if (selectable.length == 0 || this.selectedItemIndex.get() >= selectable[selectable.length - 1]) { @@ -161,9 +170,9 @@ export class ProcedureLinesGenerator { this.selectedItemIndex.set(SPECIAL_INDEX_CLEAR); } else if (this.type === ProcedureType.Deferred) { this.selectedItemIndex.set( - !this.checklistState.procedureCompleted || !this.checklistState.procedureActivated - ? SPECIAL_INDEX_DEFERRED_PROC_COMPLETE - : SPECIAL_INDEX_DEFERRED_PROC_RECALL, + this.checklistState.procedureCompleted + ? SPECIAL_INDEX_DEFERRED_PROC_RECALL + : SPECIAL_INDEX_DEFERRED_PROC_COMPLETE, ); } } else { @@ -213,11 +222,31 @@ export class ProcedureLinesGenerator { clState.itemsChecked = clState.itemsChecked.map((val, index) => (this.items[index].sensed ? val : false)); this.procedureClearedOrResetCallback(clState); this.selectFirst(); + } else if (this.sii === SPECIAL_INDEX_ACTIVATE) { + clState.procedureActivated = true; + this.procedureClearedOrResetCallback(clState); + this.selectFirst(); + } else if (this.sii === SPECIAL_INDEX_DEFERRED_PROC_COMPLETE) { + clState.procedureCompleted = true; + this.selectedItemIndex.set(SPECIAL_INDEX_DEFERRED_PROC_RECALL); + this.procedureClearedOrResetCallback(clState); + } else if (this.sii === SPECIAL_INDEX_DEFERRED_PROC_RECALL) { + clState.procedureCompleted = false; + this.selectedItemIndex.set(SPECIAL_INDEX_DEFERRED_PROC_COMPLETE); + this.procedureClearedOrResetCallback(clState); } this.checklistState = clState; } selectFirst() { + if (!this.checklistState.procedureActivated) { + this.selectedItemIndex.set(SPECIAL_INDEX_ACTIVATE); + return; + } else if (this.type === ProcedureType.Deferred && this.checklistState.procedureCompleted) { + this.selectedItemIndex.set(SPECIAL_INDEX_DEFERRED_PROC_RECALL); + return; + } + const selectableAndNotChecked = this.selectableItems(false); this.selectedItemIndex.set( selectableAndNotChecked[0] !== undefined @@ -229,7 +258,7 @@ export class ProcedureLinesGenerator { private selectableItems(skipCompletedSensed: boolean) { return this.procedure.items - .map((_, index) => (this.itemIsSelectable(index, skipCompletedSensed) ? index : null)) + .map((_, index: number) => (this.itemIsSelectable(index, skipCompletedSensed) ? index : null)) .filter((v) => v !== null); } @@ -297,7 +326,7 @@ export class ProcedureLinesGenerator { }); } - if (isDeferred) { + if (isDeferred && !this.checklistState.procedureCompleted) { lineData.push({ abnormalProcedure: isAbnormalOrDeferred, activeProcedure: true, @@ -307,12 +336,15 @@ export class ProcedureLinesGenerator { style: ChecklistLineStyle.ChecklistItem, firstLine: false, lastLine: false, - originalItemIndex: -1, + originalItemIndex: SPECIAL_INDEX_ACTIVATE, }); } this.items.forEach((item, itemIndex) => { - if (isAbnormal && !this.checklistState.itemsToShow[itemIndex]) { + if ( + (isAbnormal && !this.checklistState.itemsToShow[itemIndex]) || + (isDeferred && this.checklistState.procedureCompleted) + ) { return; } @@ -414,27 +446,29 @@ export class ProcedureLinesGenerator { originalItemIndex: SPECIAL_INDEX_NORMAL_RESET, }); } else if (isDeferred) { - if (!this.checklistState.procedureCompleted || !this.checklistState.procedureActivated) { + if (this.checklistState.procedureCompleted) { lineData.push({ activeProcedure: true, sensed: false, - checked: this.checklistState.procedureCompleted ?? false, - text: `${'\xa0'.repeat(17)}DEFERRED PROC COMPLETE`, + checked: false, + text: `${'\xa0'.repeat(18)}DEFERRED PROC RECALL`, style: ChecklistLineStyle.ChecklistItem, firstLine: false, lastLine: true, - originalItemIndex: SPECIAL_INDEX_DEFERRED_PROC_COMPLETE, + originalItemIndex: SPECIAL_INDEX_DEFERRED_PROC_RECALL, }); } else { lineData.push({ activeProcedure: true, sensed: false, - checked: false, - text: `${'\xa0'.repeat(18)}DEFERRED PROC RECALL`, - style: ChecklistLineStyle.ChecklistItem, + checked: this.checklistState.procedureCompleted ?? false, + text: `${'\xa0'.repeat(17)}DEFERRED PROC COMPLETE`, + style: this.checklistState.procedureActivated + ? ChecklistLineStyle.ChecklistItem + : ChecklistLineStyle.ChecklistItemInactive, firstLine: false, lastLine: true, - originalItemIndex: SPECIAL_INDEX_DEFERRED_PROC_RECALL, + originalItemIndex: SPECIAL_INDEX_DEFERRED_PROC_COMPLETE, }); } } diff --git a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsCore.ts b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsCore.ts index 6a51ccf2946..306904aead1 100644 --- a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsCore.ts +++ b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsCore.ts @@ -3914,13 +3914,14 @@ export class FwsCore { this.activeDeferredProceduresList.setValue(deferredKey, { id: deferredKey, procedureCompleted: false, + procedureActivated: false, itemsChecked: deferredValue.whichItemsChecked ? deferredValue.whichItemsChecked() : Array(deferredValue.whichItemsChecked().length).fill(true), itemsActive: deferredValue.whichItemsActive ? deferredValue.whichItemsActive() - : Array(deferredValue.whichItemsChecked().length).fill(true), + : Array(deferredValue.whichItemsChecked().length).fill(false), itemsToShow: deferredValue.whichItemsToShow ? deferredValue.whichItemsToShow() : Array(deferredValue.whichItemsChecked().length).fill(true), diff --git a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsNormalChecklists.ts b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsNormalChecklists.ts index 1376f2de84f..f2548372000 100644 --- a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsNormalChecklists.ts +++ b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsNormalChecklists.ts @@ -114,6 +114,12 @@ export class FwsNormalChecklists { (newState) => { this.fws.activeDeferredProceduresList.setValue(key, newState); }, + (newState) => { + this.fws.activeDeferredProceduresList.setValue(key, newState); + }, + (newState) => { + this.fws.activeDeferredProceduresList.setValue(key, newState); + }, ); this.deferredProcedures.push(procGen); }); From ae6d0bf0849c0cc53abf9e3dce2331b316a045e3 Mon Sep 17 00:00:00 2001 From: flogross89 <63071941+flogross89@users.noreply.github.com> Date: Sat, 21 Dec 2024 03:50:52 +0100 Subject: [PATCH 16/40] some fixes --- .../AbnormalNonSensedProcedures.tsx | 2 +- .../EcamMessages/AbnormalSensed/ata28.tsx | 10 +++---- .../EcamMessages/ProcedureLinesGenerator.tsx | 12 +++++--- .../MsfsAvionicsCommon/EcamMessages/index.tsx | 7 ++--- .../FwsAbnormalNonSensed.ts | 19 +++++------- .../FlightWarningSystem/FwsAbnormalSensed.ts | 10 +++++-- .../systems/FlightWarningSystem/FwsCore.ts | 29 ++++++++++++------- .../FwsNormalChecklists.ts | 4 +++ 8 files changed, 54 insertions(+), 39 deletions(-) diff --git a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalNonSensedProcedures.tsx b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalNonSensedProcedures.tsx index 956443ba9e3..916482fe86d 100644 --- a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalNonSensedProcedures.tsx +++ b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalNonSensedProcedures.tsx @@ -5,7 +5,7 @@ import { AbnormalNonSensedList } from 'instruments/src/MsfsAvionicsCommon/provid /** All normal procedures (checklists, via ECL) should be here. * Display is ordered by ID, ascending. That's why keys need to be numbers. */ -export const AbnormalNonSensedProcedures: AbnormalNonSensedList[] = [ +export const AbnormalNonSensedProceduresOverview: AbnormalNonSensedList[] = [ { id: 260900097, category: null }, { id: 990900006, category: null }, { id: 990900005, category: null }, diff --git a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata28.tsx b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata28.tsx index fe62c102934..5532af00ab1 100644 --- a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata28.tsx +++ b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata28.tsx @@ -169,8 +169,8 @@ export const EcamAbnormalSensedAta28: { [n: number]: AbnormalProcedure } = { sensed: true, items: [ { - name: 'NO FUEL LEAK', - sensed: true, + name: 'IF NO FUEL LEAK', + sensed: false, condition: true, }, { @@ -223,7 +223,7 @@ export const EcamAbnormalSensedAta28: { [n: number]: AbnormalProcedure } = { items: [ { name: 'IF NO FUEL LEAK', - sensed: true, + sensed: false, condition: true, }, { @@ -276,7 +276,7 @@ export const EcamAbnormalSensedAta28: { [n: number]: AbnormalProcedure } = { items: [ { name: 'IF NO FUEL LEAK', - sensed: true, + sensed: false, condition: true, }, { @@ -329,7 +329,7 @@ export const EcamAbnormalSensedAta28: { [n: number]: AbnormalProcedure } = { items: [ { name: 'IF NO FUEL LEAK', - sensed: true, + sensed: false, condition: true, }, { diff --git a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/ProcedureLinesGenerator.tsx b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/ProcedureLinesGenerator.tsx index 423d597d6cd..e1f8ffc4e60 100644 --- a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/ProcedureLinesGenerator.tsx +++ b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/ProcedureLinesGenerator.tsx @@ -87,7 +87,7 @@ export class ProcedureLinesGenerator { if (v.level) { // Look for parent condition(s) let active = true; - for (let recI = i; recI > 0; recI--) { + for (let recI = i; recI >= 0; recI--) { active = (proc.items[recI].level ?? 0) < v.level && isChecklistCondition(proc.items[recI]) ? active && itemsChecked[recI] @@ -160,7 +160,6 @@ export class ProcedureLinesGenerator { return; } - const numItems = this.checklistState.itemsToShow.length; const selectable = this.selectableItems(skipCompletedSensed); if (selectable.length == 0 || this.selectedItemIndex.get() >= selectable[selectable.length - 1]) { // Last element before first special line (CLEAR etc.) @@ -183,7 +182,10 @@ export class ProcedureLinesGenerator { this.selectedItemIndex.set(SPECIAL_INDEX_NORMAL_RESET); } else if (sii > HIGHEST_SPECIAL_INDEX) { this.selectedItemIndex.set( - Math.min(selectable.find((v) => v > this.selectedItemIndex.get()) ?? numItems - 1, numItems - 1), + Math.min( + selectable.find((v) => v > this.selectedItemIndex.get()) ?? selectable[selectable.length - 1], + selectable[selectable.length - 1], + ), ); } } @@ -192,6 +194,8 @@ export class ProcedureLinesGenerator { checkSelected() { const clState: ChecklistState = { id: this.checklistState.id, + procedureActivated: this.checklistState.procedureActivated, + procedureCompleted: this.checklistState.procedureCompleted, itemsToShow: [...this.checklistState.itemsToShow], itemsChecked: [...this.checklistState.itemsChecked], itemsActive: [...this.checklistState.itemsActive], @@ -396,7 +400,7 @@ export class ProcedureLinesGenerator { if (isChecklistCondition(item) && !item.sensed) { // Insert CONFIRM - const confirmText = `${item.level ? '\xa0'.repeat(item.level) : ''}CONFIRM ${item.name}`; + const confirmText = `${item.level ? '\xa0'.repeat(item.level) : ''}CONFIRM ${item.name.substring(2)}`; lineData.push({ abnormalProcedure: isAbnormalOrDeferred, activeProcedure: this.procedureIsActive.get() || !isAbnormal, diff --git a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/index.tsx b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/index.tsx index 4922b9b755b..8d36162eac0 100644 --- a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/index.tsx +++ b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/index.tsx @@ -3,7 +3,6 @@ export const WD_NUM_LINES = 17; -import { AbnormalNonSensedProcedures } from 'instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalNonSensedProcedures'; import { EcamAbnormalSensedAta212223, EcamDeferredProcAta212223, @@ -677,10 +676,8 @@ export const EcamAbnormalSensedProcedures: { [n: string]: AbnormalProcedure } = ...EcamAbnormalSensedAta80Rest, }; -/** All abnormal non-sensed procedures (via ECL) should be here. Don't start for now, format needs to be defined. */ -export const EcamAbnormalNonSensedProcedures = AbnormalNonSensedProcedures; - -export const EcamAbnormalProcedures = { ...EcamAbnormalSensedProcedures, ...EcamAbnormalNonSensedProcedures }; +// Abnormal non-sensed are also contained in EcamAbnormalSensedProcedures +export const EcamAbnormalProcedures: { [n: string]: AbnormalProcedure } = EcamAbnormalSensedProcedures; export const EcamAbNormalSensedSubMenuVector: AbnormalNonSensedCategory[] = [ 'ENG', diff --git a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsAbnormalNonSensed.ts b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsAbnormalNonSensed.ts index 5d54578d05c..ae615580552 100644 --- a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsAbnormalNonSensed.ts +++ b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsAbnormalNonSensed.ts @@ -4,11 +4,8 @@ import { MapSubject, SimVarValueType, Subject } from '@microsoft/msfs-sdk'; import { ChecklistState, FwsEwdEvents } from 'instruments/src/MsfsAvionicsCommon/providers/FwsEwdPublisher'; import { FwcAuralWarning, FwsCore } from 'systems-host/systems/FlightWarningSystem/FwsCore'; -import { - EcamAbnormalNonSensedProcedures, - EcamAbNormalSensedSubMenuVector, - WD_NUM_LINES, -} from 'instruments/src/MsfsAvionicsCommon/EcamMessages'; +import { EcamAbNormalSensedSubMenuVector, WD_NUM_LINES } from 'instruments/src/MsfsAvionicsCommon/EcamMessages'; +import { AbnormalNonSensedProceduresOverview } from 'instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalNonSensedProcedures'; import { EwdAbnormalDict } from 'systems-host/systems/FlightWarningSystem/FwsAbnormalSensed'; import { SdPages } from '@shared/EcamSystemPages'; @@ -38,13 +35,13 @@ export class FwsAbnormalNonSensed { if (this.checklistId.get() === 0) { // Overview page return ( - EcamAbnormalNonSensedProcedures.map((val) => (val.category === null ? 1 : 0) as number).reduce( + AbnormalNonSensedProceduresOverview.map((val) => (val.category === null ? 1 : 0) as number).reduce( (accumulator, currentValue) => accumulator + currentValue, ) + EcamAbNormalSensedSubMenuVector.length ); } else if (this.checklistId.get() > 0 && this.checklistId.get() <= EcamAbNormalSensedSubMenuVector.length) { const category = EcamAbNormalSensedSubMenuVector[this.checklistId.get() - 1]; - return EcamAbnormalNonSensedProcedures.map((val) => (val.category === category ? 1 : 0) as number).reduce( + return AbnormalNonSensedProceduresOverview.map((val) => (val.category === category ? 1 : 0) as number).reduce( (accumulator, currentValue) => accumulator + currentValue, ); } @@ -83,7 +80,7 @@ export class FwsAbnormalNonSensed { if (this.fws.clCheckPulseNode.read()) { if (this.checklistId.get() === 0) { - const skipProcsFromTopMenu = EcamAbnormalNonSensedProcedures.map( + const skipProcsFromTopMenu = AbnormalNonSensedProceduresOverview.map( (val) => (val.category === null ? 1 : 0) as number, ).reduce((accumulator, currentValue) => accumulator + currentValue); if ( @@ -95,16 +92,16 @@ export class FwsAbnormalNonSensed { this.selectedItem.set(0); } else if (this.selectedItem.get() < skipProcsFromTopMenu) { // Preview non-sensed procedure - this.checklistId.set(EcamAbnormalNonSensedProcedures[this.selectedItem.get()]?.id ?? 0); + this.checklistId.set(AbnormalNonSensedProceduresOverview[this.selectedItem.get()]?.id ?? 0); this.selectedItem.set(-1); } } else if (this.checklistId.get() > 0 && this.checklistId.get() <= 10) { // Sub menu - const subMenuProcsStartAt = EcamAbnormalNonSensedProcedures.findIndex( + const subMenuProcsStartAt = AbnormalNonSensedProceduresOverview.findIndex( (v) => v.category === EcamAbNormalSensedSubMenuVector[this.checklistId.get() - 1], ); // Preview non-sensed procedure - this.checklistId.set(EcamAbnormalNonSensedProcedures[subMenuProcsStartAt + this.selectedItem.get()].id); + this.checklistId.set(AbnormalNonSensedProceduresOverview[subMenuProcsStartAt + this.selectedItem.get()].id); this.selectedItem.set(-1); } else { console.log('---'); diff --git a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsAbnormalSensed.ts b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsAbnormalSensed.ts index f33f409cbbd..56d9dce4549 100644 --- a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsAbnormalSensed.ts +++ b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsAbnormalSensed.ts @@ -90,6 +90,8 @@ export class FwsAbnormalSensed { map.forEach((val, key) => flattened.push({ id: key, + procedureActivated: val.procedureActivated, + procedureCompleted: val.procedureCompleted, itemsChecked: val.itemsChecked, itemsActive: val.itemsActive, itemsToShow: val.itemsToShow, @@ -165,14 +167,16 @@ export class FwsAbnormalSensed { } public clearActiveProcedure() { - this.fws.presentedFailures.splice(0, 1); - this.fws.recallFailures = this.fws.allCurrentFailures.filter((item) => !this.fws.presentedFailures.includes(item)); - if (this.fws.activeAbnormalNonSensedKeys.includes(parseInt(this.activeProcedureId.get()))) { this.fws.activeAbnormalNonSensedKeys.splice( this.fws.activeAbnormalNonSensedKeys.indexOf(parseInt(this.activeProcedureId.get())), 1, ); + } else { + this.fws.presentedFailures.splice(0, 1); + this.fws.recallFailures = this.fws.allCurrentFailures.filter( + (item) => !this.fws.presentedFailures.includes(item), + ); } } diff --git a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsCore.ts b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsCore.ts index 306904aead1..9f71bbac9ee 100644 --- a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsCore.ts +++ b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsCore.ts @@ -2760,8 +2760,6 @@ export class FwsCore { this.fmcCFault.set(!SimVar.GetSimVarValue('L:A32NX_FMC_C_IS_HEALTHY', 'bool')); this.fms1Fault.set(this.fmcAFault.get() && this.fmcCFault.get()); this.fms2Fault.set(this.fmcBFault.get() && this.fmcCFault.get()); - this.fms1Fault.set(true); - this.fms2Fault.set(true); /* 21 - AIR CONDITIONING AND PRESSURIZATION */ @@ -3901,6 +3899,8 @@ export class FwsCore { } this.activeAbnormalProceduresList.setValue(key, { id: key, + procedureActivated: true, + procedureCompleted: false, itemsActive: itemsActive, itemsChecked: itemsChecked, itemsToShow: itemsToShow, @@ -3911,17 +3911,23 @@ export class FwsCore { EcamDeferredProcedures[deferredKey].fromAbnormalProc === key && this.abnormalSensed.ewdDeferredProcs[deferredKey] ) { + const deferredItemsActive = deferredValue.whichItemsActive + ? deferredValue.whichItemsActive() + : Array(deferredValue.whichItemsChecked().length).fill(false); + const deferredItemsChecked = deferredValue.whichItemsChecked + ? deferredValue.whichItemsChecked() + : Array(deferredValue.whichItemsChecked().length).fill(true); + ProcedureLinesGenerator.conditionalActiveItems( + EcamDeferredProcedures[deferredKey], + deferredItemsChecked, + deferredItemsActive, + ); this.activeDeferredProceduresList.setValue(deferredKey, { id: deferredKey, procedureCompleted: false, procedureActivated: false, - - itemsChecked: deferredValue.whichItemsChecked - ? deferredValue.whichItemsChecked() - : Array(deferredValue.whichItemsChecked().length).fill(true), - itemsActive: deferredValue.whichItemsActive - ? deferredValue.whichItemsActive() - : Array(deferredValue.whichItemsChecked().length).fill(false), + itemsChecked: deferredItemsChecked, + itemsActive: deferredItemsActive, itemsToShow: deferredValue.whichItemsToShow ? deferredValue.whichItemsToShow() : Array(deferredValue.whichItemsChecked().length).fill(true), @@ -3949,6 +3955,8 @@ export class FwsCore { if (this.abnormalUpdatedItems.has(key) && this.abnormalUpdatedItems.get(key).length > 0) { this.activeAbnormalProceduresList.setValue(key, { id: key, + procedureActivated: prevEl.procedureActivated, + procedureCompleted: prevEl.procedureCompleted, itemsChecked: fusedChecked, itemsActive: [...prevEl.itemsActive].map((_, index) => itemsActive[index]), itemsToShow: [...prevEl.itemsToShow].map((_, index) => itemsToShow[index]), @@ -4002,7 +4010,6 @@ export class FwsCore { const itemsChecked = value.whichItemsChecked().map((v, i) => (proc.items[i].sensed === false ? false : !!v)); const itemsToShow = value.whichItemsToShow ? value.whichItemsToShow() : Array(itemsChecked.length).fill(true); const itemsActive = value.whichItemsActive ? value.whichItemsActive() : Array(itemsChecked.length).fill(true); - ProcedureLinesGenerator.conditionalActiveItems(proc, itemsChecked, itemsActive); const prevEl = value; const fusedChecked = [...prevEl.itemsChecked].map((val, index) => @@ -4023,6 +4030,8 @@ export class FwsCore { if (this.deferredUpdatedItems.has(key) && this.deferredUpdatedItems.get(key).length > 0) { value.setValue(key, { id: key, + procedureActivated: prevEl.procedureActivated, + procedureCompleted: prevEl.procedureCompleted, itemsChecked: fusedChecked, itemsActive: [...prevEl.itemsActive].map((_, index) => itemsActive[index]), itemsToShow: [...prevEl.itemsToShow].map((_, index) => itemsToShow[index]), diff --git a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsNormalChecklists.ts b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsNormalChecklists.ts index f2548372000..2438ab09671 100644 --- a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsNormalChecklists.ts +++ b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsNormalChecklists.ts @@ -71,6 +71,7 @@ export class FwsNormalChecklists { flattened.push({ id: key.toString(), procedureCompleted: val.procedureCompleted, + procedureActivated: val.procedureActivated, itemsChecked: val.itemsChecked, itemsActive: val.itemsActive, itemsToShow: val.itemsToShow, @@ -143,6 +144,7 @@ export class FwsNormalChecklists { flattened.push({ id: key, procedureCompleted: val.procedureCompleted, + procedureActivated: val.procedureActivated, itemsChecked: val.itemsChecked, itemsActive: val.itemsActive, itemsToShow: val.itemsToShow, @@ -160,6 +162,7 @@ export class FwsNormalChecklists { this.checklistState.setValue(k, { id: k.toString(), procedureCompleted: proc.deferred ? true : false, + procedureActivated: true, itemsChecked: Array(proc.items.length).fill(false), itemsActive: Array(proc.items.length).fill(true), itemsToShow: Array(proc.items.length).fill(true), @@ -169,6 +172,7 @@ export class FwsNormalChecklists { this.checklistState.setValue(0, { id: '0', procedureCompleted: false, + procedureActivated: true, itemsChecked: Array(Object.keys(EcamNormalProcedures).length).fill(false), itemsActive: Array(Object.keys(EcamNormalProcedures).length).fill(true), itemsToShow: Array(Object.keys(EcamNormalProcedures).length).fill(true), From f6094b179d5f29f929727a7b213aa71b7655306b Mon Sep 17 00:00:00 2001 From: flogross89 <63071941+flogross89@users.noreply.github.com> Date: Sat, 21 Dec 2024 04:22:22 +0100 Subject: [PATCH 17/40] deferred fixes --- .../src/EWD/elements/WdAbnormalNonSensed.tsx | 12 ++++++------ .../EcamMessages/ProcedureLinesGenerator.tsx | 9 ++++++--- .../FlightWarningSystem/FwsNormalChecklists.ts | 7 +++++++ 3 files changed, 19 insertions(+), 9 deletions(-) diff --git a/fbw-a380x/src/systems/instruments/src/EWD/elements/WdAbnormalNonSensed.tsx b/fbw-a380x/src/systems/instruments/src/EWD/elements/WdAbnormalNonSensed.tsx index 32a4fa8a868..11035129e6a 100644 --- a/fbw-a380x/src/systems/instruments/src/EWD/elements/WdAbnormalNonSensed.tsx +++ b/fbw-a380x/src/systems/instruments/src/EWD/elements/WdAbnormalNonSensed.tsx @@ -1,12 +1,12 @@ import { ConsumerSubject, FSComponent, VNode } from '@microsoft/msfs-sdk'; import { ChecklistLineStyle, - EcamAbnormalNonSensedProcedures, EcamAbnormalSensedProcedures, EcamAbNormalSensedSubMenuVector, isChecklistAction, isChecklistCondition, } from 'instruments/src/MsfsAvionicsCommon/EcamMessages'; +import { AbnormalNonSensedProceduresOverview } from 'instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalNonSensedProcedures'; import { WdAbstractChecklistComponent } from 'instruments/src/EWD/elements/WdAbstractChecklistComponent'; function removeUnderline(text: string): string { @@ -34,10 +34,10 @@ export class WdAbnormalNonSensedProcedures extends WdAbstractChecklistComponent }); const numItems = - EcamAbnormalNonSensedProcedures.filter((v) => v.category === null).length + + AbnormalNonSensedProceduresOverview.filter((v) => v.category === null).length + EcamAbNormalSensedSubMenuVector.length; - EcamAbnormalNonSensedProcedures.forEach((proc, index) => { + AbnormalNonSensedProceduresOverview.forEach((proc, index) => { if (proc.category === null) { this.lineData.push({ activeProcedure: true, @@ -63,7 +63,7 @@ export class WdAbnormalNonSensedProcedures extends WdAbstractChecklistComponent style: ChecklistLineStyle.Headline, firstLine: false, lastLine: index === EcamAbNormalSensedSubMenuVector.length - 1, - originalItemIndex: index + EcamAbnormalNonSensedProcedures.filter((v) => v.category === null).length, + originalItemIndex: index + AbnormalNonSensedProceduresOverview.filter((v) => v.category === null).length, }); }); } else if (this.checklistId.get() > 0 && this.checklistId.get() <= 10) { @@ -92,8 +92,8 @@ export class WdAbnormalNonSensedProcedures extends WdAbstractChecklistComponent lastLine: false, }); - const numItems = EcamAbnormalNonSensedProcedures.filter((v) => v.category === category).length; - EcamAbnormalNonSensedProcedures.filter((v) => v.category === category).forEach((proc, index) => { + const numItems = AbnormalNonSensedProceduresOverview.filter((v) => v.category === category).length; + AbnormalNonSensedProceduresOverview.filter((v) => v.category === category).forEach((proc, index) => { this.lineData.push({ activeProcedure: true, abnormalProcedure: true, diff --git a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/ProcedureLinesGenerator.tsx b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/ProcedureLinesGenerator.tsx index e1f8ffc4e60..eeb3040f433 100644 --- a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/ProcedureLinesGenerator.tsx +++ b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/ProcedureLinesGenerator.tsx @@ -126,6 +126,7 @@ export class ProcedureLinesGenerator { const selectable = this.selectableItems(true); if (selectable.length === 0) { + this.selectFirst(); return; } const sii = this.selectedItemIndex.get(); @@ -225,11 +226,9 @@ export class ProcedureLinesGenerator { clState.procedureCompleted = false; clState.itemsChecked = clState.itemsChecked.map((val, index) => (this.items[index].sensed ? val : false)); this.procedureClearedOrResetCallback(clState); - this.selectFirst(); } else if (this.sii === SPECIAL_INDEX_ACTIVATE) { clState.procedureActivated = true; this.procedureClearedOrResetCallback(clState); - this.selectFirst(); } else if (this.sii === SPECIAL_INDEX_DEFERRED_PROC_COMPLETE) { clState.procedureCompleted = true; this.selectedItemIndex.set(SPECIAL_INDEX_DEFERRED_PROC_RECALL); @@ -240,6 +239,10 @@ export class ProcedureLinesGenerator { this.procedureClearedOrResetCallback(clState); } this.checklistState = clState; + + if (this.sii === SPECIAL_INDEX_NORMAL_RESET || this.sii === SPECIAL_INDEX_ACTIVATE) { + this.selectFirst(); + } } selectFirst() { @@ -335,7 +338,7 @@ export class ProcedureLinesGenerator { abnormalProcedure: isAbnormalOrDeferred, activeProcedure: true, sensed: false, - checked: this.checklistState.procedureCompleted ?? false, + checked: this.checklistState.procedureActivated ?? false, text: `${'\xa0'.repeat(31)}ACTIVATE`, style: ChecklistLineStyle.ChecklistItem, firstLine: false, diff --git a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsNormalChecklists.ts b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsNormalChecklists.ts index 2438ab09671..5ca8212224a 100644 --- a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsNormalChecklists.ts +++ b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsNormalChecklists.ts @@ -116,6 +116,13 @@ export class FwsNormalChecklists { this.fws.activeDeferredProceduresList.setValue(key, newState); }, (newState) => { + // Handle procedure activation/deactivation + const deferredItemsActive = this.fws.abnormalSensed.ewdDeferredProcs[proc.id].whichItemsActive + ? this.fws.abnormalSensed.ewdDeferredProcs[proc.id].whichItemsActive() + : Array(this.fws.abnormalSensed.ewdDeferredProcs[proc.id].whichItemsChecked().length).fill( + newState.procedureActivated, + ); + newState.itemsActive = deferredItemsActive; this.fws.activeDeferredProceduresList.setValue(key, newState); }, (newState) => { From 5366a6da15cd159c7a010662e3e1ef501efd7876 Mon Sep 17 00:00:00 2001 From: flogross89 <63071941+flogross89@users.noreply.github.com> Date: Sun, 22 Dec 2024 06:06:55 +0100 Subject: [PATCH 18/40] deferred pt 4 --- .../elements/WdAbnormalSensedProcedures.tsx | 15 ++- .../elements/WdAbstractChecklistComponent.tsx | 4 +- .../src/EWD/elements/WdNormalChecklists.tsx | 40 ++++++- .../AbnormalSensed/ata21-22-23.tsx | 36 ++++++- .../EcamMessages/NormalProcedures.tsx | 2 +- .../EcamMessages/ProcedureLinesGenerator.tsx | 101 ++++++++++++------ .../MsfsAvionicsCommon/EcamMessages/index.tsx | 8 +- .../instruments/src/SD/SystemDisplay.tsx | 1 - .../FwsAbnormalNonSensed.ts | 5 + .../FlightWarningSystem/FwsAbnormalSensed.ts | 28 ++++- .../systems/FlightWarningSystem/FwsCore.ts | 15 ++- .../FwsNormalChecklists.ts | 94 +++++++++++++--- 12 files changed, 285 insertions(+), 64 deletions(-) diff --git a/fbw-a380x/src/systems/instruments/src/EWD/elements/WdAbnormalSensedProcedures.tsx b/fbw-a380x/src/systems/instruments/src/EWD/elements/WdAbnormalSensedProcedures.tsx index d806aff1e79..27ab9ff6841 100644 --- a/fbw-a380x/src/systems/instruments/src/EWD/elements/WdAbnormalSensedProcedures.tsx +++ b/fbw-a380x/src/systems/instruments/src/EWD/elements/WdAbnormalSensedProcedures.tsx @@ -1,23 +1,31 @@ -import { ConsumerSubject, FSComponent, Subject, VNode } from '@microsoft/msfs-sdk'; +import { ConsumerSubject, VNode } from '@microsoft/msfs-sdk'; import { ProcedureLinesGenerator, ProcedureType, } from 'instruments/src/MsfsAvionicsCommon/EcamMessages/ProcedureLinesGenerator'; import { WdAbstractChecklistComponent } from 'instruments/src/EWD/elements/WdAbstractChecklistComponent'; +import { EcamAbnormalSensedProcedures } from 'instruments/src/MsfsAvionicsCommon/EcamMessages'; export class WdAbnormalSensedProcedures extends WdAbstractChecklistComponent { private readonly procedures = ConsumerSubject.create(this.sub.on('fws_abn_sensed_procedures'), []); + private readonly activeProcedureId = ConsumerSubject.create(this.sub.on('fws_active_procedure'), '0'); + public updateChecklists() { this.lineData.length = 0; - this.procedures.get().forEach((procState, procIndex) => { + this.procedures.get().forEach((procState, index) => { const procGen = new ProcedureLinesGenerator( procState.id, - Subject.create(procIndex === 0), + this.activeProcedureId.map((id) => id === procState.id), ProcedureType.Abnormal, procState, + undefined, + undefined, + undefined, + EcamAbnormalSensedProcedures[procState.id].recommendation, + index === 0, ); this.lineData.push(...procGen.toLineData()); }); @@ -29,6 +37,7 @@ export class WdAbnormalSensedProcedures extends WdAbstractChecklistComponent { super.onAfterRender(node); this.procedures.sub(() => this.updateChecklists(), true); + this.activeProcedureId.sub(() => this.updateChecklists()); } render() { diff --git a/fbw-a380x/src/systems/instruments/src/EWD/elements/WdAbstractChecklistComponent.tsx b/fbw-a380x/src/systems/instruments/src/EWD/elements/WdAbstractChecklistComponent.tsx index 28be37bf8d0..38b4a94a197 100644 --- a/fbw-a380x/src/systems/instruments/src/EWD/elements/WdAbstractChecklistComponent.tsx +++ b/fbw-a380x/src/systems/instruments/src/EWD/elements/WdAbstractChecklistComponent.tsx @@ -68,7 +68,9 @@ export class WdAbstractChecklistComponent extends DisplayComponent= this.showFromLine.get() && lineIdx < WD_NUM_LINES) { this.lineDataSubject[lineIdx].set(ld); this.lineSelected[lineIdx].set( - ld.originalItemIndex !== undefined ? ld.originalItemIndex === this.activeLine.get() : false, + ld.originalItemIndex !== undefined && ld.activeProcedure + ? ld.originalItemIndex === this.activeLine.get() + : false, ); lineIdx++; } diff --git a/fbw-a380x/src/systems/instruments/src/EWD/elements/WdNormalChecklists.tsx b/fbw-a380x/src/systems/instruments/src/EWD/elements/WdNormalChecklists.tsx index f8c092505b8..9b3c02863b4 100644 --- a/fbw-a380x/src/systems/instruments/src/EWD/elements/WdNormalChecklists.tsx +++ b/fbw-a380x/src/systems/instruments/src/EWD/elements/WdNormalChecklists.tsx @@ -12,6 +12,7 @@ import { WdAbstractChecklistComponent } from 'instruments/src/EWD/elements/WdAbs import { ProcedureLinesGenerator, ProcedureType, + SPECIAL_INDEX_DEFERRED_PAGE_CLEAR, } from 'instruments/src/MsfsAvionicsCommon/EcamMessages/ProcedureLinesGenerator'; export class WdNormalChecklists extends WdAbstractChecklistComponent { @@ -19,6 +20,8 @@ export class WdNormalChecklists extends WdAbstractChecklistComponent { private readonly checklistId = ConsumerSubject.create(this.sub.on('fws_normal_checklists_id'), 0); + private readonly activeDeferredProcedureId = ConsumerSubject.create(this.sub.on('fws_active_procedure'), '0'); + private readonly deferred = ConsumerSubject.create(this.sub.on('fws_deferred_procedures'), []); /** ALL PHASES, TOP OF DESCENT, FOR APPROACH, FOR LANDING */ @@ -130,7 +133,7 @@ export class WdNormalChecklists extends WdAbstractChecklistComponent { abnormalProcedure: true, sensed: true, checked: false, - text: `\x1b4m${clState.procedureCompleted ? '' : '\x1b<4m'}${EcamNormalProcedures[parseInt(clState.id)].title} \x1bm`, + text: `${clState.procedureCompleted ? '\x1b<7m' : '\x1b<4m'}${EcamNormalProcedures[parseInt(clState.id)].title} \x1bm`, style: ChecklistLineStyle.Headline, firstLine: true, lastLine: false, @@ -146,11 +149,41 @@ export class WdNormalChecklists extends WdAbstractChecklistComponent { lastLine: false, }); - this.deferred.get().forEach((proc, index) => { - const procGen = new ProcedureLinesGenerator(proc.id, Subject.create(index === 0), ProcedureType.Deferred, proc); + const currentDeferredType = + deferredProcedureIds.indexOf(parseInt(clState.id)) !== -1 + ? (deferredProcedureIds.indexOf(parseInt(clState.id)) as DeferredProcedureType) + : null; + const visibleDeferred = this.deferred + .get() + .filter((v) => currentDeferredType !== null && EcamDeferredProcedures[v.id].type === currentDeferredType); + visibleDeferred.forEach((proc, index) => { + const procGen = new ProcedureLinesGenerator( + proc.id, + this.activeDeferredProcedureId.map((id) => proc.id === id), + ProcedureType.Deferred, + proc, + undefined, + undefined, + undefined, + undefined, + index === visibleDeferred.length - 1, + ); this.lineData.push(...procGen.toLineData()); }); + + this.lineData.push({ + abnormalProcedure: true, + activeProcedure: true, + sensed: false, + checked: false, + text: `${'\xa0'.repeat(34)}CLEAR`, + style: ChecklistLineStyle.ChecklistItem, + firstLine: false, + lastLine: true, + originalItemIndex: SPECIAL_INDEX_DEFERRED_PAGE_CLEAR, + }); } + console.log(this.activeDeferredProcedureId.get(), this.activeLine.get()); super.updateChecklists(); } @@ -160,6 +193,7 @@ export class WdNormalChecklists extends WdAbstractChecklistComponent { this.checklists.sub(() => this.updateChecklists(), true); this.checklistId.sub(() => this.updateChecklists()); this.deferred.sub(() => this.updateChecklists(), true); + this.activeDeferredProcedureId.sub(() => this.updateChecklists()); } // 17 lines diff --git a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata21-22-23.tsx b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata21-22-23.tsx index 5e0b21cb2c9..2b860ca6aab 100644 --- a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata21-22-23.tsx +++ b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata21-22-23.tsx @@ -2127,9 +2127,43 @@ export const EcamAbnormalSensedAta212223: { [n: number]: AbnormalProcedure } = { }; export const EcamDeferredProcAta212223: { [n: number]: DeferredProcedure } = { + 210700001: { + fromAbnormalProc: '211800021', + title: 'WHEN PACK OVHT OUT', + type: DeferredProcedureType.ALL_PHASES, + items: [ + { + name: 'PACK 1', + sensed: true, + labelNotCompleted: 'ON', + }, + { + name: 'PACK 2', + sensed: true, + labelNotCompleted: 'ON', + }, + ], + }, + 210700002: { + fromAbnormalProc: '211800021', + title: 'WHEN DIFF PR<2 PSI & FL<100/MEA-MORA', + type: DeferredProcedureType.ALL_PHASES, + items: [ + { + name: 'RAM AIR', + sensed: true, + labelNotCompleted: 'ON', + }, + { + name: 'CABIN AIR EXTRACT', + sensed: true, + labelNotCompleted: 'OVRD', + }, + ], + }, 221700001: { fromAbnormalProc: '221800006', - title: '\x1b<4m> LDG ELEVN', + title: 'LDG ELEVN', type: DeferredProcedureType.AT_TOP_OF_DESCENT, items: [ { diff --git a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/NormalProcedures.tsx b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/NormalProcedures.tsx index 33b1a3e94a9..b752ccc8755 100644 --- a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/NormalProcedures.tsx +++ b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/NormalProcedures.tsx @@ -166,7 +166,7 @@ export const EcamNormalProcedures: { [n: number]: NormalProcedure } = { }, 1000006: { title: '<>', - deferred: true, + onlyActivatedByRequest: true, items: [ { name: 'RWY & SID', diff --git a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/ProcedureLinesGenerator.tsx b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/ProcedureLinesGenerator.tsx index eeb3040f433..e53953bf3ef 100644 --- a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/ProcedureLinesGenerator.tsx +++ b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/ProcedureLinesGenerator.tsx @@ -1,7 +1,7 @@ // Copyright (c) 2024 FlyByWire Simulations // SPDX-License-Identifier: GPL-3.0 -import { Subject } from '@microsoft/msfs-sdk'; +import { Subject, Subscribable } from '@microsoft/msfs-sdk'; import { AbnormalProcedure, ChecklistAction, @@ -15,7 +15,6 @@ import { isChecklistCondition, NormalProcedure, WdLineData, - WdSpecialLine, } from 'instruments/src/MsfsAvionicsCommon/EcamMessages'; import { EcamNormalProcedures } from 'instruments/src/MsfsAvionicsCommon/EcamMessages/NormalProcedures'; import { ChecklistState } from 'instruments/src/MsfsAvionicsCommon/providers/FwsEwdPublisher'; @@ -39,6 +38,7 @@ const SPECIAL_INDEX_NORMAL_CL_COMPLETE = -5; const SPECIAL_INDEX_NORMAL_RESET = -6; const SPECIAL_INDEX_CLEAR = -7; const HIGHEST_SPECIAL_INDEX = SPECIAL_INDEX_ACTIVATE; +export const SPECIAL_INDEX_DEFERRED_PAGE_CLEAR = -99; export class ProcedureLinesGenerator { public readonly selectedItemIndex = Subject.create(0); @@ -48,13 +48,14 @@ export class ProcedureLinesGenerator { constructor( public procedureId: string, - public procedureIsActive: Subject, + public procedureIsActive: Subscribable, private type: ProcedureType, public checklistState: ChecklistState, private itemCheckedCallback?: (newState: ChecklistState) => void, private procedureClearedOrResetCallback?: (newState: ChecklistState) => void, private procedureCompletedCallback?: (newState: ChecklistState) => void, private recommendation?: 'LAND ASAP' | 'LAND ANSA' | undefined, + private isLastProcedure: boolean = false, ) { if (type === ProcedureType.Normal) { this.procedure = EcamNormalProcedures[procedureId]; @@ -104,7 +105,7 @@ export class ProcedureLinesGenerator { return this.getActualShownItems().findIndex((v) => v === this.sii); } - public numTotalLines(): number { + private numTotalLines(): number { return this.getActualShownItems().length; } @@ -117,6 +118,34 @@ export class ProcedureLinesGenerator { return this.selectedItemIndex.get(); } + public firstLineIsSelected() { + if (this.type === ProcedureType.Deferred) { + return this.checklistState.procedureActivated + ? this.getActualShownItems()[0] + : this.sii === SPECIAL_INDEX_ACTIVATE; + } else if (this.type === ProcedureType.Abnormal) { + return this.checklistState.procedureActivated + ? this.getActualShownItems()[0] + : this.sii === SPECIAL_INDEX_ACTIVATE; + } else { + return false; + } + } + + public lastLineIsSelected() { + if (this.type === ProcedureType.Deferred) { + return this.checklistState.procedureActivated + ? this.sii === SPECIAL_INDEX_DEFERRED_PROC_COMPLETE || this.sii === SPECIAL_INDEX_DEFERRED_PROC_RECALL + : this.sii === SPECIAL_INDEX_ACTIVATE; + } else if (this.type === ProcedureType.Abnormal) { + return this.checklistState.procedureActivated + ? this.sii === SPECIAL_INDEX_CLEAR + : this.sii === SPECIAL_INDEX_ACTIVATE; + } else { + return false; + } + } + moveUp() { if (!this.checklistState.procedureActivated) { this.selectedItemIndex.set(SPECIAL_INDEX_ACTIVATE); @@ -308,22 +337,35 @@ export class ProcedureLinesGenerator { const isAbnormal = this.type === ProcedureType.Abnormal; const isDeferred = this.type === ProcedureType.Deferred; - lineData.push({ - abnormalProcedure: isAbnormalOrDeferred, - activeProcedure: this.procedureIsActive.get(), - sensed: true, - checked: false, - text: this.procedure.title, - style: ChecklistLineStyle.Headline, - firstLine: !isDeferred, - lastLine: this.procedureIsActive.get() ? false : true, - }); + if (isDeferred) { + lineData.push({ + abnormalProcedure: true, + activeProcedure: this.procedureIsActive.get(), + sensed: true, + checked: false, + text: `${this.checklistState.procedureCompleted ? '\x1b<7m> ' : '\x1b<4m> '}${this.procedure.title}`, + style: ChecklistLineStyle.Headline, + firstLine: false, + lastLine: false, + }); + } else { + lineData.push({ + abnormalProcedure: isAbnormalOrDeferred, + activeProcedure: this.procedureIsActive.get(), + sensed: true, + checked: false, + text: this.procedure.title, + style: ChecklistLineStyle.Headline, + firstLine: true, + lastLine: this.procedureIsActive.get() ? false : true, + }); + } if (!isAbnormal || this.procedureIsActive.get()) { if (this.recommendation) { lineData.push({ abnormalProcedure: isAbnormalOrDeferred, - activeProcedure: this.procedureIsActive.get() || !isAbnormal, + activeProcedure: this.procedureIsActive.get(), sensed: true, checked: false, text: this.recommendation, @@ -336,7 +378,7 @@ export class ProcedureLinesGenerator { if (isDeferred && !this.checklistState.procedureCompleted) { lineData.push({ abnormalProcedure: isAbnormalOrDeferred, - activeProcedure: true, + activeProcedure: this.procedureIsActive.get(), sensed: false, checked: this.checklistState.procedureActivated ?? false, text: `${'\xa0'.repeat(31)}ACTIVATE`, @@ -391,7 +433,7 @@ export class ProcedureLinesGenerator { lineData.push({ abnormalProcedure: isAbnormalOrDeferred, - activeProcedure: this.procedureIsActive.get() || !isAbnormal, + activeProcedure: this.procedureIsActive.get(), sensed: isChecklistCondition(item) ? true : item.sensed, checked: this.checklistState.itemsChecked[itemIndex], text: text.substring(0, 39), @@ -406,7 +448,7 @@ export class ProcedureLinesGenerator { const confirmText = `${item.level ? '\xa0'.repeat(item.level) : ''}CONFIRM ${item.name.substring(2)}`; lineData.push({ abnormalProcedure: isAbnormalOrDeferred, - activeProcedure: this.procedureIsActive.get() || !isAbnormal, + activeProcedure: this.procedureIsActive.get(), sensed: item.sensed, checked: this.checklistState.itemsChecked[itemIndex], text: confirmText, @@ -421,18 +463,18 @@ export class ProcedureLinesGenerator { if (isAbnormal) { lineData.push({ abnormalProcedure: isAbnormalOrDeferred, - activeProcedure: true, + activeProcedure: this.procedureIsActive.get(), sensed: false, checked: false, text: `${'\xa0'.repeat(34)}CLEAR`, style: ChecklistLineStyle.ChecklistItem, firstLine: false, - lastLine: true, + lastLine: this.isLastProcedure, originalItemIndex: SPECIAL_INDEX_CLEAR, }); } else if (this.type === ProcedureType.Normal) { lineData.push({ - activeProcedure: true, + activeProcedure: this.procedureIsActive.get(), sensed: false, checked: this.checklistState.procedureCompleted ?? false, text: `${'\xa0'.repeat(27)}C/L COMPLETE`, @@ -443,7 +485,7 @@ export class ProcedureLinesGenerator { }); lineData.push({ - activeProcedure: true, + activeProcedure: this.procedureIsActive.get(), sensed: false, checked: false, text: `${'\xa0'.repeat(34)}RESET`, @@ -455,18 +497,18 @@ export class ProcedureLinesGenerator { } else if (isDeferred) { if (this.checklistState.procedureCompleted) { lineData.push({ - activeProcedure: true, + activeProcedure: this.procedureIsActive.get(), sensed: false, checked: false, - text: `${'\xa0'.repeat(18)}DEFERRED PROC RECALL`, + text: `${'\xa0'.repeat(19)}DEFERRED PROC RECALL`, style: ChecklistLineStyle.ChecklistItem, firstLine: false, - lastLine: true, + lastLine: false, originalItemIndex: SPECIAL_INDEX_DEFERRED_PROC_RECALL, }); } else { lineData.push({ - activeProcedure: true, + activeProcedure: this.procedureIsActive.get(), sensed: false, checked: this.checklistState.procedureCompleted ?? false, text: `${'\xa0'.repeat(17)}DEFERRED PROC COMPLETE`, @@ -474,7 +516,7 @@ export class ProcedureLinesGenerator { ? ChecklistLineStyle.ChecklistItem : ChecklistLineStyle.ChecklistItemInactive, firstLine: false, - lastLine: true, + lastLine: false, originalItemIndex: SPECIAL_INDEX_DEFERRED_PROC_COMPLETE, }); } @@ -501,9 +543,8 @@ export class ProcedureLinesGenerator { checked: false, text: '', style: ChecklistLineStyle.ChecklistItem, - firstLine: true, - lastLine: true, - specialLine: WdSpecialLine.Empty, + firstLine: !isDeferred, + lastLine: !isDeferred, }); return lineData; diff --git a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/index.tsx b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/index.tsx index 8d36162eac0..ee32e4600fa 100644 --- a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/index.tsx +++ b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/index.tsx @@ -633,8 +633,8 @@ export interface NormalProcedure { title: string; /** An array of possible checklist items.. */ items: ChecklistAction[]; - /** Checklist is deferred, i.e. only activated by request */ - deferred?: boolean; + /** Checklist is only activated by request, deactivated per default */ + onlyActivatedByRequest?: boolean; } export interface AbnormalNonSensedProcedure { @@ -653,8 +653,8 @@ export enum DeferredProcedureType { export interface DeferredProcedure { /** Which abnormal procedure triggers this deferred procedure */ fromAbnormalProc: string; - /** Title of the fault, e.g. "_HYD_ G SYS PRESS LO". \n produces second line. Accepts special formatting tokens */ - title: string; + /** (optional, only used from batch 7) Title of the procedure, Accepts special formatting tokens */ + title?: string; /** An array of possible checklist items. */ items: (ChecklistAction | ChecklistCondition | ChecklistSpecialItem)[]; type: DeferredProcedureType; diff --git a/fbw-a380x/src/systems/instruments/src/SD/SystemDisplay.tsx b/fbw-a380x/src/systems/instruments/src/SD/SystemDisplay.tsx index 3c3c5e53592..85be9292ef7 100644 --- a/fbw-a380x/src/systems/instruments/src/SD/SystemDisplay.tsx +++ b/fbw-a380x/src/systems/instruments/src/SD/SystemDisplay.tsx @@ -113,7 +113,6 @@ export const SystemDisplay = () => { SimVar.SetSimVarValue('L:A32NX_ECAM_SD_CURRENT_PAGE_INDEX', 'number', stsPrevPage); } } else { - setPageWhenUnselected(SdPages.Status); setStsPressedTimer(STS_DISPLAY_TIMER_DURATION); } }; diff --git a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsAbnormalNonSensed.ts b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsAbnormalNonSensed.ts index ae615580552..268a91c3c1d 100644 --- a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsAbnormalNonSensed.ts +++ b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsAbnormalNonSensed.ts @@ -59,6 +59,11 @@ export class FwsAbnormalNonSensed { } } + navigateToParent() { + this.checklistId.set(0); + this.selectedItem.set(0); + } + update() { if (this.fws.abnProcPulseNode.read()) { this.checklistId.set(0); diff --git a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsAbnormalSensed.ts b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsAbnormalSensed.ts index 56d9dce4549..e9efd6ae71d 100644 --- a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsAbnormalSensed.ts +++ b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsAbnormalSensed.ts @@ -5,6 +5,7 @@ import { EcamAbnormalSensedProcedures, WD_NUM_LINES } from '../../../instruments/src/MsfsAvionicsCommon/EcamMessages'; import { MappedSubject, + SimVarValueType, Subject, Subscribable, SubscribableMapEventType, @@ -105,7 +106,7 @@ export class FwsAbnormalSensed { if (type === SubscribableMapEventType.Added) { const procGen = new ProcedureLinesGenerator( value.id, - Subject.create(value.id === this.activeProcedureId.get()), + this.activeProcedureId.map((id) => value.id === id), ProcedureType.Abnormal, value, (newState) => this.fws.activeAbnormalProceduresList.setValue(value.id, newState), @@ -149,7 +150,6 @@ export class FwsAbnormalSensed { this.activeProcedureId.sub((id) => { if (id) { this.procedures.forEach((val) => { - val.procedureIsActive.set(val.procedureId === id); if (val.procedureId === id) { this.activeProcedure = val; this.activeProcedure.selectedItemIndex.pipe(this.selectedItemIndex); @@ -167,6 +167,12 @@ export class FwsAbnormalSensed { } public clearActiveProcedure() { + const numFailures = this.fws.activeAbnormalNonSensedKeys.length + this.fws.presentedFailures.length; + if (numFailures === 1 && !this.fws.ecamStsNormal.get()) { + // Call STS page on SD + SimVar.SetSimVarValue('L:A32NX_ECAM_SD_CURRENT_PAGE_INDEX', SimVarValueType.Enum, SdPages.Status); + } + if (this.fws.activeAbnormalNonSensedKeys.includes(parseInt(this.activeProcedureId.get()))) { this.fws.activeAbnormalNonSensedKeys.splice( this.fws.activeAbnormalNonSensedKeys.indexOf(parseInt(this.activeProcedureId.get())), @@ -3483,6 +3489,24 @@ export class FwsAbnormalSensed { }; public ewdDeferredProcs: EwdAbnormalDict = { + 210700001: { + flightPhaseInhib: [], + simVarIsActive: Subject.create(true), + notActiveWhenFaults: [], + whichItemsToShow: () => [true, true], + whichItemsChecked: () => [this.fws.pack1On.get(), this.fws.pack2On.get()], + failure: 0, + sysPage: SdPages.None, + }, + 210700002: { + flightPhaseInhib: [], + simVarIsActive: Subject.create(true), + notActiveWhenFaults: [], + whichItemsToShow: () => [true, true], + whichItemsChecked: () => [this.fws.ramAirOn.get(), this.fws.cabinAirExtractOn.get()], + failure: 0, + sysPage: SdPages.None, + }, 221700001: { flightPhaseInhib: [], simVarIsActive: Subject.create(true), diff --git a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsCore.ts b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsCore.ts index 9f71bbac9ee..22273b871a4 100644 --- a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsCore.ts +++ b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsCore.ts @@ -443,6 +443,8 @@ export class FwsCore { public readonly excessDiffPressure = Subject.create(false); + public readonly diffPressure = Arinc429Register.empty(); + public readonly allOutflowValvesOpen = Subject.create(false); public readonly ocsm1AutoFailure = Subject.create(false); @@ -2973,6 +2975,8 @@ export class FwsCore { this.excessDiffPressure.set(cpcsDiscreteWordToUse.bitValueOr(14, false)); + this.diffPressure.setFromSimVar(`L:A32NX_PRESS_CABIN_DELTA_PRESSURE_B${cpcsToUseId}`); + const outflowValve1OpenAmount = Arinc429Register.empty(); const outflowValve2OpenAmount = Arinc429Register.empty(); const outflowValve3OpenAmount = Arinc429Register.empty(); @@ -3776,8 +3780,14 @@ export class FwsCore { /* CLEAR AND RECALL */ if (this.clrPulseNode.read()) { - // delete the first failure - this.abnormalSensed.clearActiveProcedure(); + if (this.abnormalSensed.abnormalShown.get()) { + // delete the first failure + this.abnormalSensed.clearActiveProcedure(); + } else if (this.normalChecklists.checklistShown.get()) { + this.normalChecklists.navigateToParent(); + } else if (this.abnormalNonSensed.abnProcShown.get()) { + this.abnormalNonSensed.navigateToParent(); + } } if (this.rclUpPulseNode.read()) { @@ -4255,6 +4265,7 @@ export class FwsCore { this.abnormalSensed.abnormalShown.set(false); pub.pub('fws_active_item', this.normalChecklists.selectedLine.get(), true); + pub.pub('fws_active_procedure', this.normalChecklists.activeDeferredProcedureId.get(), true); pub.pub('fws_show_from_line', this.normalChecklists.showFromLine.get(), true); this.ecamEwdShowFailurePendingIndication.set(this.abnormalSensed.showAbnormalSensedRequested.get()); } else if (this.abnormalSensed.showAbnormalSensedRequested.get()) { diff --git a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsNormalChecklists.ts b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsNormalChecklists.ts index 5ca8212224a..da6b3713265 100644 --- a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsNormalChecklists.ts +++ b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsNormalChecklists.ts @@ -17,6 +17,7 @@ import { import { ProcedureLinesGenerator, ProcedureType, + SPECIAL_INDEX_DEFERRED_PAGE_CLEAR, } from 'instruments/src/MsfsAvionicsCommon/EcamMessages/ProcedureLinesGenerator'; export interface NormalEclSensedItems { @@ -51,9 +52,12 @@ export class FwsNormalChecklists { /** ALL PHASES, TOP OF DESCENT, FOR APPROACH, FOR LANDING */ private readonly deferredIsCompleted = [false, false, false, false]; - /** ID of active deferred procedure */ + /** ID of active deferred procedure. null means no procedure is selected, but CLEAR at the end of the page is */ public readonly activeDeferredProcedureId = Subject.create(null); + /** IDs of all visible deferred procedures. */ + public visibleDeferredProcedureKeys: string[] = []; + private deferredProcedures: ProcedureLinesGenerator[] = []; private activeProcedure: ProcedureLinesGenerator; @@ -105,11 +109,24 @@ export class FwsNormalChecklists { this.activeProcedure.selectedItemIndex.pipe(this.selectedLine); } else if (deferredProcedureIds.includes(id)) { this.deferredProcedures = []; - const firstProcedureKey = Object.keys(this.fws.activeDeferredProceduresList.get())[0]; - this.fws.activeDeferredProceduresList.get().forEach((proc, key) => { + + const currentDeferredType = + deferredProcedureIds.indexOf(id) !== -1 ? (deferredProcedureIds.indexOf(id) as DeferredProcedureType) : null; + this.visibleDeferredProcedureKeys = Array.from(this.fws.activeDeferredProceduresList.get().values()) + .filter((v) => currentDeferredType !== null && EcamDeferredProcedures[v.id].type === currentDeferredType) + .map((v) => v.id); + + if (this.visibleDeferredProcedureKeys.length === 0) { + this.activeDeferredProcedureId.set(null); + return; + } + const firstProcedureKey = this.visibleDeferredProcedureKeys[0]; + this.activeDeferredProcedureId.set(firstProcedureKey); + this.visibleDeferredProcedureKeys.forEach((key) => { + const proc = this.fws.activeDeferredProceduresList.getValue(key); const procGen = new ProcedureLinesGenerator( proc.id, - Subject.create(proc.id === firstProcedureKey), + this.activeDeferredProcedureId.map((id) => id === proc.id), ProcedureType.Deferred, proc, (newState) => { @@ -132,7 +149,6 @@ export class FwsNormalChecklists { this.deferredProcedures.push(procGen); }); - this.activeDeferredProcedureId.set(firstProcedureKey); this.activeProcedure = this.deferredProcedures[0]; this.activeProcedure.selectedItemIndex.pipe(this.selectedLine); } @@ -162,13 +178,23 @@ export class FwsNormalChecklists { true, ); + this.activeDeferredProcedureId.sub((id) => { + if (id !== null && this.deferredProcedures.find((v) => v.procedureId === id)) { + this.activeProcedure = this.deferredProcedures.find((v) => v.procedureId === id); + this.activeProcedure.selectedItemIndex.pipe(this.selectedLine); + this.activeProcedure.selectFirst(); + } else if (id === null) { + this.selectedLine.set(SPECIAL_INDEX_DEFERRED_PAGE_CLEAR); + } + }); + // Populate checklistState const keys = this.getNormalProceduresKeysSorted(); keys.forEach((k) => { const proc = EcamNormalProcedures[k] as NormalProcedure; this.checklistState.setValue(k, { id: k.toString(), - procedureCompleted: proc.deferred ? true : false, + procedureCompleted: proc.onlyActivatedByRequest ? true : false, procedureActivated: true, itemsChecked: Array(proc.items.length).fill(false), itemsActive: Array(proc.items.length).fill(true), @@ -225,7 +251,21 @@ export class FwsNormalChecklists { .filter((v) => v !== null); this.selectedLine.set(Math.max(shownItems[shownItems.indexOf(this.selectedLine.get()) - 1] ?? 0, 0)); } else { - this.activeProcedure.moveUp(); + if (this.activeDeferredProcedureId.get() !== null) { + if (this.activeProcedure.lastLineIsSelected()) { + const curDefIndex = this.visibleDeferredProcedureKeys.indexOf(this.activeDeferredProcedureId.get()); + if (curDefIndex !== -1 && curDefIndex > 0) { + this.activeDeferredProcedureId.set(this.visibleDeferredProcedureKeys[curDefIndex - 1]); + } + } else { + this.activeProcedure.moveUp(); + } + } else { + // CLEAR of page selected, select last procedure + this.activeDeferredProcedureId.set( + this.visibleDeferredProcedureKeys[this.visibleDeferredProcedureKeys.length - 1], + ); + } } } @@ -241,8 +281,19 @@ export class FwsNormalChecklists { this.getNormalProceduresKeysSorted(true).length, ), ); - } else { - this.activeProcedure.moveDown(skipCompletedSensed); + } else if (this.activeDeferredProcedureId.get() !== null) { + if (this.activeProcedure.lastLineIsSelected()) { + const curDefIndex = this.visibleDeferredProcedureKeys.indexOf(this.activeDeferredProcedureId.get()); + if (curDefIndex !== -1) { + this.activeDeferredProcedureId.set( + curDefIndex < this.visibleDeferredProcedureKeys.length - 1 + ? this.visibleDeferredProcedureKeys[curDefIndex + 1] + : null, + ); + } + } else { + this.activeProcedure.moveDown(skipCompletedSensed); + } } } @@ -258,7 +309,7 @@ export class FwsNormalChecklists { const procFollowing = EcamNormalProcedures[idFollowing]; const clStateFollowing: ChecklistState = { id: idFollowing.toString(), - procedureCompleted: procFollowing.deferred ? true : false, + procedureCompleted: procFollowing.onlyActivatedByRequest ? true : false, itemsChecked: [...clFollowing.itemsChecked].map((val, index) => procFollowing.items[index].sensed ? val : false, ), @@ -275,6 +326,10 @@ export class FwsNormalChecklists { this.selectFirst(); } + navigateToParent() { + this.navigateToChecklist(0); + } + private scrollToSelectedLine() { this.showFromLine.set(Math.max(0, this.selectedLine.get() - WD_NUM_LINES + 2)); } @@ -302,7 +357,11 @@ export class FwsNormalChecklists { // Navigate to check list this.navigateToChecklist(this.getNormalProceduresKeysSorted()[this.selectedLine.get()]); } else { - this.activeProcedure.checkSelected(); + if (deferredProcedureIds.includes(this.checklistId.get()) && this.activeDeferredProcedureId.get() === null) { + this.navigateToChecklist(0); + } else { + this.activeProcedure.checkSelected(); + } } } @@ -315,23 +374,26 @@ export class FwsNormalChecklists { const cl = this.checklistState.getValue(procId); const proc = EcamNormalProcedures[procId]; - if (!this.sensedItems[procId] || deferredProcedureIds.includes(procId)) { - continue; - } + const deferredProcIndex = deferredProcedureIds.indexOf(procId); + const procCompleted = + deferredProcIndex !== -1 ? this.deferredIsCompleted[deferredProcIndex] : cl.procedureCompleted; + const sensedResult = this.sensedItems[procId].whichItemsChecked(); const changedEntries = sensedResult.map((val, index) => val !== null && val !== cl.itemsChecked[index] ? index : null, ); - if (changedEntries.some((v) => v !== null)) { + if (changedEntries.some((v) => v !== null) || procCompleted !== cl.procedureCompleted) { changed = true; if (changedEntries.includes(this.selectedLine.get()) && sensedResult[this.selectedLine.get()]) { this.moveDown(); } } + const clState: ChecklistState = { id: procId.toString(), - procedureCompleted: cl.procedureCompleted, + procedureCompleted: procCompleted, + procedureActivated: cl.procedureActivated, itemsChecked: [...cl.itemsChecked].map((val, index) => proc.items[index].sensed && sensedResult[index] != null ? sensedResult[index] : val, ), From 37beca43bf052d0f3efcf3fc0e5aa74f5c3e579f Mon Sep 17 00:00:00 2001 From: flogross89 <63071941+flogross89@users.noreply.github.com> Date: Sun, 22 Dec 2024 06:18:39 +0100 Subject: [PATCH 19/40] reuse FwcFormatter from EWD --- .../src/EWD/elements/FormattedFwcText.tsx | 9 +- .../systems/instruments/src/PFD/LowerArea.tsx | 12 +- .../instruments/src/PFD/MemoFormatter.tsx | 194 ------------------ 3 files changed, 13 insertions(+), 202 deletions(-) delete mode 100644 fbw-a380x/src/systems/instruments/src/PFD/MemoFormatter.tsx diff --git a/fbw-a380x/src/systems/instruments/src/EWD/elements/FormattedFwcText.tsx b/fbw-a380x/src/systems/instruments/src/EWD/elements/FormattedFwcText.tsx index 8d9dc51d062..d2f0a0e070f 100644 --- a/fbw-a380x/src/systems/instruments/src/EWD/elements/FormattedFwcText.tsx +++ b/fbw-a380x/src/systems/instruments/src/EWD/elements/FormattedFwcText.tsx @@ -8,6 +8,8 @@ interface FormattedFwcTextProps { message: Subscribable; x: number; y: number; + /** Whether this line will be rendered in the PFD. Has impact on font-size */ + pfd?: boolean; } export class FormattedFwcText extends DisplayComponent { private linesRef = FSComponent.createRef(); @@ -163,7 +165,10 @@ export class FormattedFwcText extends DisplayComponent { if (buffer !== '') { spans.push( - + {buffer} , ); @@ -179,7 +184,7 @@ export class FormattedFwcText extends DisplayComponent { this.linesRef.instance.appendChild(e); yOffset += LINE_SPACING; } - }); + }, true); } render(): VNode { diff --git a/fbw-a380x/src/systems/instruments/src/PFD/LowerArea.tsx b/fbw-a380x/src/systems/instruments/src/PFD/LowerArea.tsx index 6864a159983..c3b0ad6cbb4 100644 --- a/fbw-a380x/src/systems/instruments/src/PFD/LowerArea.tsx +++ b/fbw-a380x/src/systems/instruments/src/PFD/LowerArea.tsx @@ -17,10 +17,10 @@ import { ArincEventBus, MathUtils, } from '@flybywiresim/fbw-sdk'; +import { FormattedFwcText } from 'instruments/src/EWD/elements/FormattedFwcText'; import { FwsPfdSimvars } from '../MsfsAvionicsCommon/providers/FwsPfdPublisher'; import { PFDSimvars } from 'instruments/src/PFD/shared/PFDSimvarPublisher'; import { EcamLimitations, EcamMemos } from '../MsfsAvionicsCommon/EcamMessages'; -import { MemoFormatter } from 'instruments/src/PFD/MemoFormatter'; import { FwcDataEvents, SecDataEvents } from '@flybywiresim/msfs-avionics-common'; export class LowerArea extends DisplayComponent<{ @@ -689,7 +689,7 @@ class Limitations extends DisplayComponent<{ bus: ArincEventBus; visible: Subscr return ( (it ? 'visible' : 'hidden'))}> {this.limitationsLine.map((line, index) => ( - + ))} ); @@ -714,10 +714,10 @@ class Memos extends DisplayComponent<{ bus: ArincEventBus }> { render(): VNode { return ( - - - - + + + + ); } diff --git a/fbw-a380x/src/systems/instruments/src/PFD/MemoFormatter.tsx b/fbw-a380x/src/systems/instruments/src/PFD/MemoFormatter.tsx deleted file mode 100644 index fda6002d1ef..00000000000 --- a/fbw-a380x/src/systems/instruments/src/PFD/MemoFormatter.tsx +++ /dev/null @@ -1,194 +0,0 @@ -// Copyright (c) 2021-2023 FlyByWire Simulations -// -// SPDX-License-Identifier: GPL-3.0 - -import { DisplayComponent, FSComponent, Subscribable, VNode } from '@microsoft/msfs-sdk'; - -// Taken from a32nx EWD. FIXME Consider replacing when EWD ported to avionics framework -interface MemoFormatterProps { - message: Subscribable; - x: number; - y: number; -} -export class MemoFormatter extends DisplayComponent { - private linesRef = FSComponent.createRef(); - - private decorationRef = FSComponent.createRef(); - - onAfterRender(node: VNode): void { - super.onAfterRender(node); - - this.props.message.sub((message) => { - const LINE_SPACING = 30; - const LETTER_WIDTH = 16; - - this.linesRef.instance.innerHTML = ''; - this.decorationRef.instance.innerHTML = ''; - - let spans: VNode[] = []; - let yOffset = 0; - - let color = 'White'; - let underlined = false; - // const flashing = false; TODO - let framed = false; - - let buffer = ''; - let startCol = 0; - let col = 0; - for (let i = 0; i < message.length; i++) { - const char = message[i]; - if (char === '\x1b' || char === '\r') { - if (buffer !== '') { - // close current part - spans.push( - - {buffer} - , - ); - buffer = ''; - - if (underlined) { - const d = document.createElementNS('http://www.w3.org/2000/svg', 'path'); - d.setAttribute('class', `Undeline ${color}Line`); - d.setAttribute('strokeLinecap', 'round'); - d.setAttribute( - 'd', - `M ${this.props.x + startCol * LETTER_WIDTH} ${this.props.y + (yOffset + 4)} h ${(col - startCol) * LETTER_WIDTH + 5}`, - ); - this.decorationRef.instance.appendChild(d); - } - - if (framed) { - const d = document.createElementNS('http://www.w3.org/2000/svg', 'path'); - d.setAttribute('class', `Undeline ${color}Line`); - d.setAttribute('strokeLinecap', 'round'); - d.setAttribute( - 'd', - `M ${this.props.x + startCol * LETTER_WIDTH} - ${this.props.y + yOffset - 22} h ${(col - startCol) * LETTER_WIDTH + 12} v 27 h ${-((col - startCol) * LETTER_WIDTH + 12)} v -27`, - ); - this.decorationRef.instance.appendChild(d); - } - - startCol = col; - } - - if (char === '\x1B') { - let ctrlBuffer = ''; - i++; - for (; i < message.length; i++) { - ctrlBuffer += message[i]; - - let match = true; - switch (ctrlBuffer) { - case 'm': - // Reset attribute - underlined = false; - // flashing = false; - framed = false; - break; - case '4m': - // Underlined attribute - underlined = true; - break; - case ')m': - // Flashing attribute - // flashing = true; - break; - case "'m": - // Characters which follow must be framed - framed = true; - break; - case '<1m': - // Select YELLOW - color = 'Yellow'; - break; - case '<2m': - // Select RED - color = 'Red'; - break; - case '<3m': - // Select GREEN - color = 'Green'; - break; - case '<4m': - // Select AMBER - color = 'Amber'; - break; - case '<5m': - // Select CYAN (blue-green) - color = 'Cyan'; - break; - case '<6m': - // Select MAGENTA - color = 'Magenta'; - break; - case '<7m': - // Select WHITE - color = 'White'; - break; - default: - match = false; - break; - } - - if (match) { - break; - } - } - - continue; - } - - if (char === '\r') { - const e = document.createElementNS('http://www.w3.org/2000/svg', 'text'); - e.setAttribute('x', this.props.x.toString()); - e.setAttribute('y', (this.props.y + yOffset).toString()); - spans.forEach((s) => { - FSComponent.render(s, e); - }); - this.linesRef.instance.appendChild(e); - yOffset += LINE_SPACING; - - spans = []; - col = 0; - startCol = 0; - continue; - } - } - - buffer += char; - col++; - } - - if (buffer !== '') { - spans.push( - - {buffer} - , - ); - } - - if (spans.length) { - const e = document.createElementNS('http://www.w3.org/2000/svg', 'text'); - e.setAttribute('x', this.props.x.toString()); - e.setAttribute('y', (this.props.y + yOffset).toString()); - spans.forEach((s) => { - FSComponent.render(s, e); - }); - this.linesRef.instance.appendChild(e); - yOffset += LINE_SPACING; - } - }, true); - } - - render(): VNode { - return ( - - - - - ); - } -} From e012fcc2b62932b130f27fc2406796ec12eb8c1d Mon Sep 17 00:00:00 2001 From: flogross89 <63071941+flogross89@users.noreply.github.com> Date: Sun, 22 Dec 2024 07:10:20 +0100 Subject: [PATCH 20/40] fix ECAM CP integ lighting --- .../model/behaviour/ecam-cp.xml | 95 +++++++++++-------- 1 file changed, 54 insertions(+), 41 deletions(-) diff --git a/fbw-a380x/src/base/flybywire-aircraft-a380-842/SimObjects/AirPlanes/FlyByWire_A380_842/model/behaviour/ecam-cp.xml b/fbw-a380x/src/base/flybywire-aircraft-a380-842/SimObjects/AirPlanes/FlyByWire_A380_842/model/behaviour/ecam-cp.xml index 7dd66b3f170..f142761de8c 100644 --- a/fbw-a380x/src/base/flybywire-aircraft-a380-842/SimObjects/AirPlanes/FlyByWire_A380_842/model/behaviour/ecam-cp.xml +++ b/fbw-a380x/src/base/flybywire-aircraft-a380-842/SimObjects/AirPlanes/FlyByWire_A380_842/model/behaviour/ecam-cp.xml @@ -54,18 +54,24 @@ + + @@ -150,6 +155,7 @@ False (L:A32NX_ELEC_DC_1_BUS_IS_POWERED, Bool) 85 + (L:A32NX_ELEC_DC_1_BUS_IS_POWERED, Bool) False False @@ -165,7 +171,7 @@ 0 (>L:#SIMVAR#) - (L:A32NX_SD_MORE_SHOWN, Bool) + (L:A32NX_SD_MORE_SHOWN, Bool) #SEQ2_POWERED# and diff --git a/fbw-a380x/src/base/flybywire-aircraft-a380-842/SimObjects/AirPlanes/FlyByWire_A380_842/model/behaviour/kccu.xml b/fbw-a380x/src/base/flybywire-aircraft-a380-842/SimObjects/AirPlanes/FlyByWire_A380_842/model/behaviour/kccu.xml index 463c252d1ee..31d2dce1cdf 100644 --- a/fbw-a380x/src/base/flybywire-aircraft-a380-842/SimObjects/AirPlanes/FlyByWire_A380_842/model/behaviour/kccu.xml +++ b/fbw-a380x/src/base/flybywire-aircraft-a380-842/SimObjects/AirPlanes/FlyByWire_A380_842/model/behaviour/kccu.xml @@ -10,7 +10,6 @@ 0.1 0.5 1 - A32NX @@ -20,6 +19,7 @@ 85 PUSH_KCCU#SIDE#_#KEY#_ANIM (L:A32NX_ELEC_DC_1_BUS_IS_POWERED, Bool) + (L:A32NX_ELEC_DC_1_BUS_IS_POWERED, Bool) (>H:#PLANE_NAME#_KCCU_#SIDE#_#KEY#) From 157db979ec6acb1d7968acf56f7411a1cdd1d22c Mon Sep 17 00:00:00 2001 From: flogross89 <63071941+flogross89@users.noreply.github.com> Date: Sun, 22 Dec 2024 18:17:36 +0100 Subject: [PATCH 23/40] improve abnormal non sensed activation --- .../FwsAbnormalNonSensed.ts | 5 ++--- .../FlightWarningSystem/FwsAbnormalSensed.ts | 2 +- .../systems/FlightWarningSystem/FwsCore.ts | 20 +++++-------------- 3 files changed, 8 insertions(+), 19 deletions(-) diff --git a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsAbnormalNonSensed.ts b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsAbnormalNonSensed.ts index 268a91c3c1d..c24b02c1d5d 100644 --- a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsAbnormalNonSensed.ts +++ b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsAbnormalNonSensed.ts @@ -109,9 +109,8 @@ export class FwsAbnormalNonSensed { this.checklistId.set(AbnormalNonSensedProceduresOverview[subMenuProcsStartAt + this.selectedItem.get()].id); this.selectedItem.set(-1); } else { - console.log('---'); // Activate non-sensed procedure (add to ECAM faults) and close dialog, i.e. return to abnormal procs - this.fws.activeAbnormalNonSensedKeys.push(this.checklistId.get()); + this.fws.activeAbnormalNonSensedKeys.add(this.checklistId.get()); this.selectedItem.set(0); this.showAbnProcRequested.set(false); } @@ -122,7 +121,7 @@ export class FwsAbnormalNonSensed { 260900097: { // SMOKE / FUMES flightPhaseInhib: [], - simVarIsActive: Subject.create(false), + simVarIsActive: this.fws.activeAbnormalNonSensedKeys.map((set) => set.has(260900097)), notActiveWhenFaults: [], whichItemsToShow: () => [true, true, true, true, true, true], whichItemsChecked: () => [ diff --git a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsAbnormalSensed.ts b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsAbnormalSensed.ts index 2a6eaf1a9c9..617c753c58e 100644 --- a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsAbnormalSensed.ts +++ b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsAbnormalSensed.ts @@ -167,7 +167,7 @@ export class FwsAbnormalSensed { } public clearActiveProcedure() { - const numFailures = this.fws.activeAbnormalNonSensedKeys.length + this.fws.presentedFailures.length; + const numFailures = this.fws.activeAbnormalNonSensedKeys.size + this.fws.presentedFailures.length; if (numFailures === 1 && !this.fws.ecamStsNormal.get()) { // Call STS page on SD SimVar.SetSimVarValue('L:A32NX_ECAM_SD_CURRENT_PAGE_INDEX', SimVarValueType.Enum, SdPages.Status); diff --git a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsCore.ts b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsCore.ts index 5960932664c..f46e77f984a 100644 --- a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsCore.ts +++ b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsCore.ts @@ -17,6 +17,7 @@ import { KeyEventManager, GameStateProvider, Wait, + SetSubject, } from '@microsoft/msfs-sdk'; import { @@ -225,7 +226,7 @@ export class FwsCore { public readonly presentedFailures: string[] = []; /** Keys/IDs of the active abnormal non-sensed procedures */ - public readonly activeAbnormalNonSensedKeys: number[] = []; + public readonly activeAbnormalNonSensedKeys: SetSubject = SetSubject.create([]); /** Map to hold all failures which are currently active */ public readonly activeAbnormalProceduresList = MapSubject.create(); @@ -3830,10 +3831,7 @@ export class FwsCore { // Update memos and failures list in case failure has been resolved for (const [key, value] of Object.entries(this.ewdAbnormal)) { - if ( - (!value.simVarIsActive.get() && !this.activeAbnormalNonSensedKeys.includes(parseInt(key))) || - value.flightPhaseInhib.some((e) => e === flightPhase) - ) { + if (!value.simVarIsActive.get() || value.flightPhaseInhib.some((e) => e === flightPhase)) { failureKeys = failureKeys.filter((e) => e !== key); recallFailureKeys = recallFailureKeys.filter((e) => e !== key); } @@ -3857,10 +3855,7 @@ export class FwsCore { const newWarning = !this.presentedFailures.includes(key) && !recallFailureKeys.includes(key); const proc = EcamAbnormalProcedures[key]; - if ( - value.simVarIsActive.get() || - (this.activeAbnormalNonSensedKeys.includes(parseInt(key)) && !this.recallFailures.includes(key)) - ) { + if (value.simVarIsActive.get()) { // Skip if other fault overrides this one let overridden = false; value.notActiveWhenFaults.forEach((val) => { @@ -3880,12 +3875,7 @@ export class FwsCore { ProcedureLinesGenerator.conditionalActiveItems(proc, itemsChecked, itemsActive); if (newWarning) { - console.log('newwarning'); - if (this.activeAbnormalNonSensedKeys.includes(parseInt(key))) { - failureKeys.unshift(key); - } else { - failureKeys.push(key); - } + failureKeys.push(key); if (value.failure === 3) { this.requestMasterWarningFromFaults = true; From 8f22271251691e769d6cea8f7211d4118563671b Mon Sep 17 00:00:00 2001 From: flogross89 <63071941+flogross89@users.noreply.github.com> Date: Sun, 22 Dec 2024 23:18:45 +0100 Subject: [PATCH 24/40] some more fixes --- .../src/EWD/elements/WdNormalChecklists.tsx | 1 - .../AbnormalSensed/ata21-22-23.tsx | 18 +-- .../EcamMessages/AbnormalSensed/ata24.tsx | 22 +-- .../EcamMessages/AbnormalSensed/ata29-30.tsx | 6 +- .../AbnormalSensed/ata31-32-33.tsx | 42 ++++- .../EcamMessages/AbnormalSensed/ata34.tsx | 2 +- .../EcamMessages/AbnormalSensed/ata70.tsx | 12 +- .../AbnormalSensed/secondary-failures.tsx | 57 +++++++ .../EcamMessages/ProcedureLinesGenerator.tsx | 11 +- .../MsfsAvionicsCommon/EcamMessages/index.tsx | 69 +++++--- .../FlightWarningSystem/FwsAbnormalSensed.ts | 147 +++++++++++++++++- .../systems/FlightWarningSystem/FwsCore.ts | 80 ++++++---- .../FwsNormalChecklists.ts | 68 ++++---- 13 files changed, 397 insertions(+), 138 deletions(-) create mode 100644 fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/secondary-failures.tsx diff --git a/fbw-a380x/src/systems/instruments/src/EWD/elements/WdNormalChecklists.tsx b/fbw-a380x/src/systems/instruments/src/EWD/elements/WdNormalChecklists.tsx index 9b3c02863b4..13ecf2d6d40 100644 --- a/fbw-a380x/src/systems/instruments/src/EWD/elements/WdNormalChecklists.tsx +++ b/fbw-a380x/src/systems/instruments/src/EWD/elements/WdNormalChecklists.tsx @@ -183,7 +183,6 @@ export class WdNormalChecklists extends WdAbstractChecklistComponent { originalItemIndex: SPECIAL_INDEX_DEFERRED_PAGE_CLEAR, }); } - console.log(this.activeDeferredProcedureId.get(), this.activeLine.get()); super.updateChecklists(); } diff --git a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata21-22-23.tsx b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata21-22-23.tsx index 2b860ca6aab..7055b77d93f 100644 --- a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata21-22-23.tsx +++ b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata21-22-23.tsx @@ -254,50 +254,44 @@ export const EcamAbnormalSensedAta212223: { [n: number]: AbnormalProcedure } = { name: 'DESCENT TO FL 100/MEA-MORA', sensed: false, labelNotCompleted: 'INITIATE', - level: 1, }, { name: 'MAX FL : 100/MEA-MORA', sensed: true, style: ChecklistLineStyle.Cyan, - level: 1, }, { - name: 'WHEN DIFF PRESS < 2 PSI & FL < 100/MEA-MORA :', + name: 'WHEN DIFF PRESS<2PSI & FL<100/MEA-MORA :', sensed: true, condition: true, - level: 1, }, { name: 'RAM AIR:', sensed: true, labelNotCompleted: 'ON', - level: 2, + level: 1, }, { name: 'CABIN AIR EXTRACT', sensed: true, labelNotCompleted: 'OVRD', - level: 2, + level: 1, }, // In flight, if below FL 100 { name: 'MAX FL : 100/MEA-MORA', sensed: true, style: ChecklistLineStyle.Cyan, - level: 1, }, { name: 'RAM AIR:', sensed: true, labelNotCompleted: 'ON', - level: 1, }, { name: 'CABIN AIR EXTRACT', sensed: true, labelNotCompleted: 'OVRD', - level: 1, }, ], }, @@ -2128,7 +2122,7 @@ export const EcamAbnormalSensedAta212223: { [n: number]: AbnormalProcedure } = { export const EcamDeferredProcAta212223: { [n: number]: DeferredProcedure } = { 210700001: { - fromAbnormalProc: '211800021', + fromAbnormalProcs: ['211800021'], title: 'WHEN PACK OVHT OUT', type: DeferredProcedureType.ALL_PHASES, items: [ @@ -2145,7 +2139,7 @@ export const EcamDeferredProcAta212223: { [n: number]: DeferredProcedure } = { ], }, 210700002: { - fromAbnormalProc: '211800021', + fromAbnormalProcs: ['211800021'], title: 'WHEN DIFF PR<2 PSI & FL<100/MEA-MORA', type: DeferredProcedureType.ALL_PHASES, items: [ @@ -2162,7 +2156,7 @@ export const EcamDeferredProcAta212223: { [n: number]: DeferredProcedure } = { ], }, 221700001: { - fromAbnormalProc: '221800006', + fromAbnormalProcs: ['221800006'], title: 'LDG ELEVN', type: DeferredProcedureType.AT_TOP_OF_DESCENT, items: [ diff --git a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata24.tsx b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata24.tsx index 6444f923c63..2bae8ca56eb 100644 --- a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata24.tsx +++ b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata24.tsx @@ -37,7 +37,7 @@ export const EcamAbnormalSensedAta24: { [n: number]: AbnormalProcedure } = { ], }, 240800003: { - title: '\x1b<4m\x1b4mELEC\x1bm AC BUS 1+2 & DC BUS 1 FAULT', + title: "\x1b<4m\x1b4mELEC\x1bm \x1b'mAC BUS 1+2 & DC BUS 1 FAULT\x1bm", sensed: true, items: [ { @@ -120,7 +120,7 @@ export const EcamAbnormalSensedAta24: { [n: number]: AbnormalProcedure } = { ], }, 240800005: { - title: '\x1b<4m\x1b4mELEC\x1bm AC BUS 2+3 & DC BUS 1+2 FAULT', + title: "\x1b<4m\x1b4mELEC\x1bm \x1b'mAC BUS 2+3 & DC BUS 1+2 FAULT\x1bm", sensed: true, items: [ { @@ -323,7 +323,7 @@ export const EcamAbnormalSensedAta24: { [n: number]: AbnormalProcedure } = { ], }, 240800006: { - title: '\x1b<4m\x1b4mELEC\x1bm AC BUS 2+4 FAULT', + title: "\x1b<4m\x1b4mELEC\x1bm \x1b'mAC BUS 2+4 FAULT\x1bm", sensed: true, items: [ // after landing @@ -540,7 +540,7 @@ export const EcamAbnormalSensedAta24: { [n: number]: AbnormalProcedure } = { ], }, 240800008: { - title: '\x1b<4m\x1b4mELEC\x1bm AC BUS 3+4 & DC BUS 2 FAULT', + title: "\x1b<4m\x1b4mELEC\x1bm \x1b'mAC BUS 3+4 & DC BUS 2 FAULT\x1bm", sensed: true, items: [ // in flight @@ -892,7 +892,7 @@ export const EcamAbnormalSensedAta24: { [n: number]: AbnormalProcedure } = { items: [], }, 240800026: { - title: '\x1b<4m\x1b4mELEC\x1bm DC BUS 1 FAULT', + title: "\x1b<4m\x1b4mELEC\x1bm \x1b'mDC BUS 1 FAULT\x1bm", sensed: true, items: [ { @@ -955,7 +955,7 @@ export const EcamAbnormalSensedAta24: { [n: number]: AbnormalProcedure } = { ], }, 240800027: { - title: '\x1b<4m\x1b4mELEC\x1bm DC BUS 1 +2 FAULT', + title: "\x1b<4m\x1b4mELEC\x1bm \x1b'mDC BUS 1+2 FAULT\x1bm", sensed: true, items: [ { @@ -1068,7 +1068,7 @@ export const EcamAbnormalSensedAta24: { [n: number]: AbnormalProcedure } = { ], }, 240800028: { - title: '\x1b<4m\x1b4mELEC\x1bm DC BUS 1+ESS FAULT', + title: "\x1b<4m\x1b4mELEC\x1bm \x1b'mDC BUS 1+ESS FAULT\x1bm", recommendation: 'LAND ANSA', sensed: true, items: [ @@ -1171,7 +1171,7 @@ export const EcamAbnormalSensedAta24: { [n: number]: AbnormalProcedure } = { ], }, 240800029: { - title: '\x1b<4m\x1b4mELEC\x1bm DC BUS 2 FAULT', + title: "\x1b<4m\x1b4mELEC\x1bm \x1b'mDC BUS 2 FAULT\x1bm", sensed: true, items: [ { @@ -1237,7 +1237,7 @@ export const EcamAbnormalSensedAta24: { [n: number]: AbnormalProcedure } = { ], }, 240800030: { - title: '\x1b<4m\x1b4mELEC\x1bm DC ESS BUS FAULT', + title: "\x1b<4m\x1b4mELEC\x1bm \x1b'mDC ESS BUS FAULT\x1bm", sensed: true, items: [ { @@ -1342,7 +1342,7 @@ export const EcamAbnormalSensedAta24: { [n: number]: AbnormalProcedure } = { ], }, 240800031: { - title: '\x1b<4m\x1b4mELEC\x1bm DC ESS BUS PART FAULT', + title: "\x1b<4m\x1b4mELEC\x1bm \x1b'mDC ESS BUS PART FAULT\x1bm", sensed: true, items: [ { @@ -1691,7 +1691,7 @@ export const EcamAbnormalSensedAta24: { [n: number]: AbnormalProcedure } = { items: [], }, 240800055: { - title: '\x1b<2m\x1b4mELEC\x1bm EMER CONFIG', + title: "\x1b<2m\x1b4mELEC\x1bm \x1b'mEMER CONFIG\x1bm", sensed: true, recommendation: 'LAND ASAP', items: [ diff --git a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata29-30.tsx b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata29-30.tsx index fd7da67f209..fe517b4b119 100644 --- a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata29-30.tsx +++ b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata29-30.tsx @@ -470,7 +470,7 @@ export const EcamAbnormalSensedAta2930: { [n: number]: AbnormalProcedure } = { items: [], }, 290800035: { - title: '\x1b<4m\x1b4mHYD\x1bm G SYS PRESS LO', + title: "\x1b<4m\x1b4mHYD\x1bm \x1b'mG SYS PRESS LO\x1bm", sensed: true, items: [ { @@ -511,7 +511,7 @@ export const EcamAbnormalSensedAta2930: { [n: number]: AbnormalProcedure } = { ], }, 290800036: { - title: '\x1b<4m\x1b4mHYD\x1bm Y SYS PRESS LO', + title: "\x1b<4m\x1b4mHYD\x1bm \x1b'mY SYS PRESS LO\x1bm", sensed: true, items: [ { @@ -607,7 +607,7 @@ export const EcamAbnormalSensedAta2930: { [n: number]: AbnormalProcedure } = { ], }, 290800039: { - title: '\x1b<4m\x1b4mHYD\x1bm G+Y SYS PRESS LO', + title: "\x1b<4m\x1b4mHYD\x1bm \x1b'mG+Y SYS PRESS LO\x1bm", sensed: true, items: [ { diff --git a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata31-32-33.tsx b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata31-32-33.tsx index 5763902b684..e6fbe1e878d 100644 --- a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata31-32-33.tsx +++ b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata31-32-33.tsx @@ -1,7 +1,12 @@ // Copyright (c) 2024 FlyByWire Simulations // SPDX-License-Identifier: GPL-3.0 -import { AbnormalProcedure, ChecklistLineStyle } from 'instruments/src/MsfsAvionicsCommon/EcamMessages'; +import { + AbnormalProcedure, + ChecklistLineStyle, + DeferredProcedure, + DeferredProcedureType, +} from 'instruments/src/MsfsAvionicsCommon/EcamMessages'; // Convention for IDs: // First two digits: ATA chapter @@ -1138,3 +1143,38 @@ export const EcamAbnormalSensedAta313233: { [n: number]: AbnormalProcedure } = { items: [], // TODO }, }; + +export const EcamDeferredProcAta313233: { [n: number]: DeferredProcedure } = { + 320700001: { + fromAbnormalProcs: ['290800035', '290800036', '290800039'], + title: 'L/G GRVTY EXTN', + type: DeferredProcedureType.FOR_LANDING, + items: [ + { + name: 'FOR L/G GRVTY EXTN: MAX SPEED 220 KT', + sensed: false, + }, + { + name: 'L/G LEVER', + sensed: true, + labelNotCompleted: 'UP', + }, + { + name: 'L/G GRVTY (EXTN MAX 2 MIN)', + sensed: true, + labelNotCompleted: 'DOWN', + }, + { + name: 'WHEN L/G LOCKED DOWN OR AFTER 120S', + condition: true, + sensed: true, + }, + { + name: 'L/G LEVER', + sensed: true, + labelNotCompleted: 'DOWN', + level: 1, + }, + ], + }, +}; diff --git a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata34.tsx b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata34.tsx index 0dae04f5ced..f3beeff2bde 100644 --- a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata34.tsx +++ b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata34.tsx @@ -812,7 +812,7 @@ export const EcamAbnormalSensedAta34: { [n: number]: AbnormalProcedure } = { export const EcamDeferredProcAta34: { [n: number]: DeferredProcedure } = { 340700001: { - fromAbnormalProc: '340800008', + fromAbnormalProcs: ['340800008'], title: '\x1b<4mLDG ELEVN', type: DeferredProcedureType.AT_TOP_OF_DESCENT, items: [], diff --git a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata70.tsx b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata70.tsx index 74c5ff3355a..55cfefbe891 100644 --- a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata70.tsx +++ b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata70.tsx @@ -560,22 +560,22 @@ export const EcamAbnormalSensedAta70: { [n: number]: AbnormalProcedure } = { items: [], }, 701800109: { - title: '\x1b<4m\x1b4mENG\x1bm 1 SHUT DOWN', + title: "\x1b<4m\x1b4mENG\x1bm \x1b'm1 SHUT DOWN\x1bm", sensed: true, items: [], }, 701800110: { - title: '\x1b<4m\x1b4mENG\x1bm 2 SHUT DOWN', + title: "\x1b<4m\x1b4mENG\x1bm \x1b'm2 SHUT DOWN\x1bm", sensed: true, items: [], }, 701800111: { - title: '\x1b<4m\x1b4mENG\x1bm 3 SHUT DOWN', + title: "\x1b<4m\x1b4mENG\x1bm \x1b'm3 SHUT DOWN\x1bm", sensed: true, items: [], }, 701800112: { - title: '\x1b<4m\x1b4mENG\x1bm 4 SHUT DOWN', + title: "\x1b<4m\x1b4mENG\x1bm \x1b'm4 SHUT DOWN\x1bm", sensed: true, items: [], }, @@ -810,12 +810,12 @@ export const EcamAbnormalSensedAta70: { [n: number]: AbnormalProcedure } = { items: [], }, 701800159: { - title: '\x1b<4m\x1b4mENG\x1bm TWO ENG OUT ON SAME SIDE', + title: "\x1b<4m\x1b4mENG\x1bm \x1b'mTWO ENG OUT ON SAME SIDE\x1bm", sensed: true, items: [], }, 701800160: { - title: '\x1b<4m\x1b4mENG\x1bm TWO ENG OUT ON OPPOSITE SIDE', + title: "\x1b<4m\x1b4mENG\x1bm \x1b'mTWO ENG OUT ON OPPOSITE SIDE\x1bm", sensed: true, items: [], }, diff --git a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/secondary-failures.tsx b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/secondary-failures.tsx new file mode 100644 index 00000000000..8769928b986 --- /dev/null +++ b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/secondary-failures.tsx @@ -0,0 +1,57 @@ +// Copyright (c) 2024 FlyByWire Simulations +// SPDX-License-Identifier: GPL-3.0 + +import { AbnormalProcedure } from 'instruments/src/MsfsAvionicsCommon/EcamMessages'; + +// Convention for IDs: +// First two digits: ATA chapter +// Third digit: Sub chapter, if needed +// Fourth digit: +// 0 for MEMOs, +// 1 for normal checklists, +// 2 for infos, +// 3 for INOP SYS, +// 4 for limitations, +// 7 for deferred procedures, +// 8 for ABN sensed procedures, +// 9 for ABN non-sensed procedures + +export const EcamAbnormalSecondaryFailures: { [n: number]: AbnormalProcedure } = { + 999800001: { + title: '\x1b<4m*F/CTL', + sensed: true, + items: [], + }, + 999800002: { + title: '\x1b<4m*FUEL', + sensed: true, + items: [], + }, + 999800003: { + title: '\x1b<4m*WHEEL', + sensed: true, + items: [], + }, + 999800004: { + // AC + title: '\x1b<4m*ELEC', + sensed: true, + items: [], + }, + 999800005: { + // DC + title: '\x1b<4m*ELEC', + sensed: true, + items: [], + }, + 999800006: { + title: '\x1b<4m*BLEED', + sensed: true, + items: [], + }, + 999800007: { + title: '\x1b<4m*HYD', + sensed: true, + items: [], + }, +}; diff --git a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/ProcedureLinesGenerator.tsx b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/ProcedureLinesGenerator.tsx index e53953bf3ef..8ec7b635477 100644 --- a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/ProcedureLinesGenerator.tsx +++ b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/ProcedureLinesGenerator.tsx @@ -83,7 +83,7 @@ export class ProcedureLinesGenerator { itemsActive: boolean[], ) { // Additional logic for conditions: Modify itemsActive based on condition activation status - if (proc.items.some((v) => isChecklistCondition(v))) { + if (proc.items && proc.items.some((v) => isChecklistCondition(v))) { proc.items.forEach((v, i) => { if (v.level) { // Look for parent condition(s) @@ -230,9 +230,10 @@ export class ProcedureLinesGenerator { itemsChecked: [...this.checklistState.itemsChecked], itemsActive: [...this.checklistState.itemsActive], }; + const lastItemIndex = this.getActualShownItems()[this.getActualShownItems().length - 1]; if ( this.selectedItemIndex.get() >= 0 && - this.selectedItemIndex.get() < this.getActualShownItems().length && + this.selectedItemIndex.get() <= lastItemIndex && !this.selectedItem?.sensed ) { clState.itemsChecked[this.sii] = !clState.itemsChecked[this.sii]; @@ -261,11 +262,11 @@ export class ProcedureLinesGenerator { } else if (this.sii === SPECIAL_INDEX_DEFERRED_PROC_COMPLETE) { clState.procedureCompleted = true; this.selectedItemIndex.set(SPECIAL_INDEX_DEFERRED_PROC_RECALL); - this.procedureClearedOrResetCallback(clState); + this.procedureCompletedCallback(clState); } else if (this.sii === SPECIAL_INDEX_DEFERRED_PROC_RECALL) { clState.procedureCompleted = false; this.selectedItemIndex.set(SPECIAL_INDEX_DEFERRED_PROC_COMPLETE); - this.procedureClearedOrResetCallback(clState); + this.procedureCompletedCallback(clState); } this.checklistState = clState; @@ -521,7 +522,7 @@ export class ProcedureLinesGenerator { }); } } - } else { + } else if (this.items.length > 0) { // Only three dots for following procedures lineData.push({ abnormalProcedure: isAbnormalOrDeferred, diff --git a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/index.tsx b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/index.tsx index ee32e4600fa..088d65df4a9 100644 --- a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/index.tsx +++ b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/index.tsx @@ -12,12 +12,16 @@ import { EcamAbnormalSensedAta26 } from 'instruments/src/MsfsAvionicsCommon/Ecam import { EcamAbnormalSensedAta27 } from 'instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata27'; import { EcamAbnormalSensedAta28 } from 'instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata28'; import { EcamAbnormalSensedAta2930 } from 'instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata29-30'; -import { EcamAbnormalSensedAta313233 } from 'instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata31-32-33'; +import { + EcamAbnormalSensedAta313233, + EcamDeferredProcAta313233, +} from 'instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata31-32-33'; import { EcamAbnormalSensedAta34 } from 'instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata34'; import { EcamAbnormalSensedAta353642 } from 'instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata35-36-42'; import { EcamAbnormalSensedAta46495256 } from 'instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata46-49-52-56'; import { EcamAbnormalSensedAta70 } from 'instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata70'; import { EcamAbnormalSensedAta80Rest } from 'instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata80-rest'; +import { EcamAbnormalSecondaryFailures } from 'instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/secondary-failures'; import { AbnormalNonSensedCategory } from 'instruments/src/MsfsAvionicsCommon/providers/FwsEwdPublisher'; // Convention for IDs: @@ -469,28 +473,39 @@ export const EcamInopSys: { [n: string]: string } = { 260300060: '\x1b<4mU3R RCC SMK DET', 260300061: '\x1b<4mU1L SHOWER SMK DET', 260300062: '\x1b<4mU1R SHOWER SMK DET', - 290300001: '\x1b<4m G ELEC PMP A', - 290300002: '\x1b<4m G ELEC PMP B', - 290300003: '\x1b<4m Y ELEC PMP A', - 290300004: '\x1b<4m Y ELEC PMP B', - 290300005: '\x1b<4m G ENG 1 PMP A', - 290300006: '\x1b<4m G ENG 1 PMP B', - 290300007: '\x1b<4m G ENG 2 PMP A', - 290300008: '\x1b<4m G ENG 2 PMP B', - 290300009: '\x1b<4m Y ENG 3 PMP A', - 290300010: '\x1b<4m Y ENG 3 PMP B', - 290300011: '\x1b<4m Y ENG 4 PMP A', - 290300012: '\x1b<4m Y ENG 4 PMP B', - 290300013: '\x1b<4m G SYS CHAN A OVHT DET', - 290300014: '\x1b<4m G SYS CHAN B OVHT DET', - 290300015: '\x1b<4m Y SYS CHAN A OVHT DET', - 290300016: '\x1b<4m Y SYS CHAN B OVHT DET', - 290300017: '\x1b<4m G HSMU', - 290300018: '\x1b<4m Y HSMU', - 290300019: '\x1b<4m G SYS OVHT DET', - 290300020: '\x1b<4m Y SYS OVHT DET', - 290300021: '\x1b<4m G HYD SYS', - 290300022: '\x1b<4m Y HYD SYS', + 290100001: '\x1b<4mPART SPLRs', + 290100003: '\x1b<4mFLAPS SYS 1', + 290100004: '\x1b<4mFLAPS SYS 2', + 290100005: '\x1b<4mSLATS SYS 1', + 290100006: '\x1b<4mSLATS SYS 2', + 290100007: '\x1b<4mSTABILIZER', + 290100008: '\x1b<4mF/CTL PROT', + 290100009: '\x1b<4mL OUTR AILERON', + 290100010: '\x1b<4mR OUTR AILERON', + 290100011: '\x1b<4mMOST SPLRs', + 290100012: '\x1b<4mFLAPS', + 290300001: '\x1b<4mG ELEC PMP A', + 290300002: '\x1b<4mG ELEC PMP B', + 290300003: '\x1b<4mY ELEC PMP A', + 290300004: '\x1b<4mY ELEC PMP B', + 290300005: '\x1b<4mG ENG 1 PMP A', + 290300006: '\x1b<4mG ENG 1 PMP B', + 290300007: '\x1b<4mG ENG 2 PMP A', + 290300008: '\x1b<4mG ENG 2 PMP B', + 290300009: '\x1b<4mY ENG 3 PMP A', + 290300010: '\x1b<4mY ENG 3 PMP B', + 290300011: '\x1b<4mY ENG 4 PMP A', + 290300012: '\x1b<4mY ENG 4 PMP B', + 290300013: '\x1b<4mG SYS CHAN A OVHT DET', + 290300014: '\x1b<4mG SYS CHAN B OVHT DET', + 290300015: '\x1b<4mY SYS CHAN A OVHT DET', + 290300016: '\x1b<4mY SYS CHAN B OVHT DET', + 290300017: '\x1b<4mG HSMU', + 290300018: '\x1b<4mY HSMU', + 290300019: '\x1b<4mG SYS OVHT DET', + 290300020: '\x1b<4mY SYS OVHT DET', + 290300021: '\x1b<4mG HYD SYS', + 290300022: '\x1b<4mY HYD SYS', 310300001: '\x1b<4mAUTO CALLOUT', 320300001: '\x1b<4mA-SKID', 320300002: '\x1b<4mAUTO BRK', @@ -514,6 +529,8 @@ export const EcamInopSys: { [n: string]: string } = { 320300020: '\x1b<4mNORM N/W STEER', 320300021: '\x1b<4mPEDAL STEER CTL', 320300022: '\x1b<4mROW/ROP', + 320300023: '\x1b<4mPART L/G RETRACTION', + 320300024: '\x1b<4mNORM B/W STEER', 340300001: '\x1b<4mGPWS 1', 340300002: '\x1b<4mGPWS 2', 340300003: '\x1b<4mGPWS 1+2', @@ -651,8 +668,8 @@ export enum DeferredProcedureType { FOR_LANDING, } export interface DeferredProcedure { - /** Which abnormal procedure triggers this deferred procedure */ - fromAbnormalProc: string; + /** Which abnormal procedures triggers this deferred procedure */ + fromAbnormalProcs: string[]; /** (optional, only used from batch 7) Title of the procedure, Accepts special formatting tokens */ title?: string; /** An array of possible checklist items. */ @@ -674,6 +691,7 @@ export const EcamAbnormalSensedProcedures: { [n: string]: AbnormalProcedure } = ...EcamAbnormalSensedAta46495256, ...EcamAbnormalSensedAta70, ...EcamAbnormalSensedAta80Rest, + ...EcamAbnormalSecondaryFailures, }; // Abnormal non-sensed are also contained in EcamAbnormalSensedProcedures @@ -691,6 +709,7 @@ export const EcamAbNormalSensedSubMenuVector: AbnormalNonSensedCategory[] = [ /** All abnormal sensed procedures (alerts, via ECL) should be here. */ export const EcamDeferredProcedures: { [n: string]: DeferredProcedure } = { ...EcamDeferredProcAta212223, + ...EcamDeferredProcAta313233, }; /** Used for one common representation of data defining the visual appearance of ECAM lines on the WD (for the ECL part) */ diff --git a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsAbnormalSensed.ts b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsAbnormalSensed.ts index 617c753c58e..a049becf163 100644 --- a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsAbnormalSensed.ts +++ b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsAbnormalSensed.ts @@ -39,9 +39,11 @@ export interface EwdAbnormalItem { sysPage: SdPages; /** Cancel flag for level 3 warning audio (only emergency cancel can cancel if false), defaults to true. */ cancel?: boolean; - /** Optional for now: Message IDs of INOP SYS to be displayed on STS page for ALL PHASES */ + /** Optional for now: Message IDs of INOP SYS to be displayed on STS page for ALL PHASES. + * Ideally they're not triggered from faults but rather taken from the system's health status */ inopSysAllPhases?: () => string[]; - /** Optional for now: Message IDs of INOP SYS to be displayed on STS page for APPR&LDG */ + /** Optional for now: Message IDs of INOP SYS to be displayed on STS page for APPR&LDG. + * Ideally they're not triggered from faults but rather taken from the system's health status */ inopSysApprLdg?: () => string[]; /** Optional for now: Message IDs of INFO to be displayed on STS page */ info?: () => string[]; @@ -59,6 +61,13 @@ export interface EwdAbnormalDict { [key: keyof typeof EcamAbnormalSensedProcedures]: EwdAbnormalItem; } +/** + * Sorts abnormal procedures by decreasing priority, for display on the EWD. Show secondary failures last + * @param idA first procedure ID + * @param idB second procedure ID + * @returns comparison result, i.e. relative priority of procedures A and B + */ + export class FwsAbnormalSensed { private readonly pub = this.fws.bus.getPublisher(); @@ -79,6 +88,12 @@ export class FwsAbnormalSensed { private activeProcedure: ProcedureLinesGenerator; + static compareAbnormalProceduresByPriority(idA: string, idB: string, failureLevelA: number, failureLevelB: number) { + const bPriority = idB.substring(0, 4) === '9998' ? 0 : failureLevelA; + const aPriority = idA.substring(0, 4) === '9998' ? 0 : failureLevelB; + return bPriority - aPriority; + } + constructor(private fws: FwsCore) { this.fws.activeAbnormalProceduresList.sub( ( @@ -99,9 +114,14 @@ export class FwsAbnormalSensed { }), ); // Sort by decreasing importance - const sortedAbnormalsFlattened = flattened.sort( - (a, b) => this.fws.ewdAbnormal[b.id].failure - this.fws.ewdAbnormal[a.id].failure, - ); + const sortedAbnormalsFlattened = flattened.sort((a, b) => { + return FwsAbnormalSensed.compareAbnormalProceduresByPriority( + a.id, + b.id, + this.fws.ewdAbnormal[a.id].failure, + this.fws.ewdAbnormal[b.id].failure, + ); + }); if (type === SubscribableMapEventType.Added) { const procGen = new ProcedureLinesGenerator( @@ -2746,9 +2766,11 @@ export class FwsAbnormalSensed { whichItemsChecked: () => [false, false, false, false, false, false, false, false], failure: 2, limitationsPfd: () => ['320400001'], - limitationsAllPhases: () => [!this.fws.prim3Healthy ? '800400001' : ''], + limitationsAllPhases: () => [!this.fws.prim3Healthy ? '800400001' : null], limitationsApprLdg: () => ['320400001', '290400001', '290400002', '320400002', '320400003', '800400002'], info: () => ['800200001', '800200002', '220200005'], + inopSysAllPhases: () => ['290100001', '320300023', '290300021'], + inopSysApprLdg: () => ['290100003', '290100006', '320300007', '320300020'], notActiveWhenFaults: ['290800039'], sysPage: SdPages.Hyd, }, @@ -2765,9 +2787,11 @@ export class FwsAbnormalSensed { ], whichItemsChecked: () => [false, false, false, false, false], failure: 2, - limitationsAllPhases: () => [!this.fws.prim2Healthy ? '800400001' : ''], + limitationsAllPhases: () => [!this.fws.prim2Healthy ? '800400001' : null], limitationsApprLdg: () => ['800400002'], info: () => ['800400003', '800200004', '800200004', '220200005'], + inopSysAllPhases: () => ['290100001', '320300023', '290300022'], + inopSysApprLdg: () => ['290100004', '320300007', '320300024'], notActiveWhenFaults: ['290800039'], sysPage: SdPages.Hyd, }, @@ -2822,6 +2846,17 @@ export class FwsAbnormalSensed { '800400003', ], info: () => ['340200002', '800200001', '320200001', '800200004', '800200005'], + inopSysAllPhases: () => [ + '290100007', + '290100008', + '290100009', + '290100010', + '290100011', + '320300013', + '290300021', + '290300022', + ], + inopSysApprLdg: () => ['290100012', '290100006', '320300007', '320300008', '320300014', '320300020', '220300026'], notActiveWhenFaults: [], sysPage: SdPages.Hyd, }, @@ -2850,7 +2885,7 @@ export class FwsAbnormalSensed { info: () => [ '320200002', '320200003', - this.fws.oneEngineRunning.get() ? '800200003' : '', + this.fws.oneEngineRunning.get() ? '800200003' : null, '800200005', '220200005', ], @@ -3476,6 +3511,87 @@ export class FwsAbnormalSensed { failure: 2, sysPage: -1, }, + // SECONDARY FAILURES + 999800001: { + // *F/CTL + flightPhaseInhib: [], + simVarIsActive: MappedSubject.create( + SubscribableMapFunctions.or(), + this.fws.greenAbnormLoPressure, + this.fws.yellowAbnormLoPressure, + this.fws.greenYellowAbnormLoPressure, + ), + notActiveWhenFaults: [], + whichItemsToShow: () => [], + whichItemsChecked: () => [], + failure: 2, + sysPage: SdPages.Fctl, + }, + 999800002: { + // *FUEL + flightPhaseInhib: [], + simVarIsActive: MappedSubject.create(SubscribableMapFunctions.or()), + notActiveWhenFaults: [], + whichItemsToShow: () => [], + whichItemsChecked: () => [], + failure: 2, + sysPage: SdPages.Fuel, + }, + 999800003: { + // *WHEEL + flightPhaseInhib: [], + simVarIsActive: MappedSubject.create( + SubscribableMapFunctions.or(), + this.fws.greenAbnormLoPressure, + this.fws.yellowAbnormLoPressure, + this.fws.greenYellowAbnormLoPressure, + ), + notActiveWhenFaults: [], + whichItemsToShow: () => [], + whichItemsChecked: () => [], + failure: 2, + sysPage: SdPages.Wheel, + }, + 999800004: { + // *ELEC + flightPhaseInhib: [], + simVarIsActive: MappedSubject.create(SubscribableMapFunctions.or()), + notActiveWhenFaults: [], + whichItemsToShow: () => [], + whichItemsChecked: () => [], + failure: 2, + sysPage: SdPages.ElecAc, + }, + 999800005: { + // *ELEC + flightPhaseInhib: [], + simVarIsActive: MappedSubject.create(SubscribableMapFunctions.or()), + notActiveWhenFaults: [], + whichItemsToShow: () => [], + whichItemsChecked: () => [], + failure: 2, + sysPage: SdPages.ElecDc, + }, + 999800006: { + // *BLEED + flightPhaseInhib: [], + simVarIsActive: MappedSubject.create(SubscribableMapFunctions.or()), + notActiveWhenFaults: [], + whichItemsToShow: () => [], + whichItemsChecked: () => [], + failure: 2, + sysPage: SdPages.Bleed, + }, + 999800007: { + // *HYD + flightPhaseInhib: [], + simVarIsActive: MappedSubject.create(SubscribableMapFunctions.or()), + notActiveWhenFaults: [], + whichItemsToShow: () => [], + whichItemsChecked: () => [], + failure: 2, + sysPage: SdPages.Hyd, + }, }; public ewdDeferredProcs: EwdAbnormalDict = { @@ -3506,5 +3622,20 @@ export class FwsAbnormalSensed { failure: 0, sysPage: SdPages.None, }, + 320700001: { + flightPhaseInhib: [], + simVarIsActive: Subject.create(true), + notActiveWhenFaults: [], + whichItemsToShow: () => [true, true, true, true, true], + whichItemsChecked: () => [ + false, + SimVar.GetSimVarValue('L:A32NX_GEAR_LEVER_POSITION_REQUEST', SimVarValueType.Number) === 0, + SimVar.GetSimVarValue('L:A32NX_LG_GRVTY_SWITCH_POS', SimVarValueType.Number) === 2, + this.fws.isAllGearDownlocked, + SimVar.GetSimVarValue('L:A32NX_GEAR_LEVER_POSITION_REQUEST', SimVarValueType.Number) === 1, + ], + failure: 0, + sysPage: SdPages.None, + }, }; } diff --git a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsCore.ts b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsCore.ts index f46e77f984a..5e502ee1300 100644 --- a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsCore.ts +++ b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsCore.ts @@ -1496,7 +1496,7 @@ export class FwsCore { if (val) { // Push only unique keys for (const key of val()) { - if (!pushTo.includes(key)) { + if (key && !pushTo.includes(key)) { pushTo.push(key); } } @@ -3825,7 +3825,6 @@ export class FwsCore { let failureKeys: string[] = this.presentedFailures; let recallFailureKeys: string[] = this.recallFailures; let failureSystemCount = 0; - const rightFailureSystemCount = 0; const auralCrcKeys: string[] = []; const auralScKeys: string[] = []; @@ -3920,7 +3919,7 @@ export class FwsCore { for (const [deferredKey, deferredValue] of ewdDeferredEntries) { if ( - EcamDeferredProcedures[deferredKey].fromAbnormalProc === key && + EcamDeferredProcedures[deferredKey].fromAbnormalProcs.includes(key) && this.abnormalSensed.ewdDeferredProcs[deferredKey] ) { const deferredItemsActive = deferredValue.whichItemsActive @@ -4018,46 +4017,56 @@ export class FwsCore { failureSystemCount++; } } - - if (value.sysPage > -1) { - SimVar.SetSimVarValue('L:A32NX_ECAM_SFAIL', 'number', value.sysPage); - } } // Update deferred procedures - for (const [key, value] of Object.values(this.activeDeferredProceduresList.get())) { + this.activeDeferredProceduresList.get().forEach((value, key) => { const proc = EcamDeferredProcedures[key]; - const itemsChecked = value.whichItemsChecked().map((v, i) => (proc.items[i].sensed === false ? false : !!v)); - const itemsToShow = value.whichItemsToShow ? value.whichItemsToShow() : Array(itemsChecked.length).fill(true); - const itemsActive = value.whichItemsActive ? value.whichItemsActive() : Array(itemsChecked.length).fill(true); - - const prevEl = value; - const fusedChecked = [...prevEl.itemsChecked].map((val, index) => + const itemsChecked = this.abnormalSensed.ewdDeferredProcs[key] + .whichItemsChecked() + .map((v, i) => (proc.items[i].sensed === false ? false : !!v)); + const itemsToShow = this.abnormalSensed.ewdDeferredProcs[key].whichItemsToShow + ? this.abnormalSensed.ewdDeferredProcs[key].whichItemsToShow() + : Array(itemsChecked.length).fill(true); + const itemsActive = this.abnormalSensed.ewdDeferredProcs[key].whichItemsActive + ? this.abnormalSensed.ewdDeferredProcs[key].whichItemsActive() + : Array(itemsChecked.length).fill(true); + + const fusedChecked = [...value.itemsChecked].map((val, index) => proc.items[index].sensed ? itemsChecked[index] : !!val, ); + ProcedureLinesGenerator.conditionalActiveItems(proc, fusedChecked, itemsActive); this.deferredUpdatedItems.set(key, []); proc.items.forEach((item, idx) => { if ( - prevEl.itemsToShow[idx] !== itemsToShow[idx] || - prevEl.itemsActive[idx] !== itemsActive[idx] || - (prevEl.itemsChecked[idx] !== fusedChecked[idx] && item.sensed) + value.itemsToShow[idx] !== itemsToShow[idx] || + value.itemsActive[idx] !== itemsActive[idx] || + (value.itemsChecked[idx] !== fusedChecked[idx] && item.sensed) ) { this.deferredUpdatedItems.get(key).push(idx); } }); if (this.deferredUpdatedItems.has(key) && this.deferredUpdatedItems.get(key).length > 0) { - value.setValue(key, { + console.log('set', { + id: key, + procedureActivated: value.procedureActivated, + procedureCompleted: value.procedureCompleted, + itemsChecked: fusedChecked, + itemsActive: [...value.itemsActive].map((_, index) => itemsActive[index]), + itemsToShow: [...value.itemsToShow].map((_, index) => itemsToShow[index]), + }); + this.activeDeferredProceduresList.setValue(key, { id: key, - procedureActivated: prevEl.procedureActivated, - procedureCompleted: prevEl.procedureCompleted, + procedureActivated: value.procedureActivated, + procedureCompleted: value.procedureCompleted, itemsChecked: fusedChecked, - itemsActive: [...prevEl.itemsActive].map((_, index) => itemsActive[index]), - itemsToShow: [...prevEl.itemsToShow].map((_, index) => itemsToShow[index]), + itemsActive: [...value.itemsActive].map((_, index) => itemsActive[index]), + itemsToShow: [...value.itemsToShow].map((_, index) => itemsToShow[index]), }); } - } + }); if (value.auralWarning?.get() === FwcAuralWarning.Crc) { if (!this.auralCrcKeys.includes(key)) { @@ -4087,7 +4096,7 @@ export class FwsCore { if (!allFailureKeys.includes(key) && !this.recallFailures.includes(key)) { // Delete associated deferred procedure for (const [deferredKey, _] of ewdDeferredEntries) { - if (EcamDeferredProcedures[deferredKey].fromAbnormalProc === key) { + if (EcamDeferredProcedures[deferredKey].fromAbnormalProcs.includes(key)) { this.activeDeferredProceduresList.delete(key); } } @@ -4105,12 +4114,6 @@ export class FwsCore { this.auralSingleChimePending = false; } - const failOrder: string[] = []; - - for (const [key] of Object.entries(this.ewdAbnormal)) { - failOrder.push(...key); - } - this.allCurrentFailures.length = 0; this.allCurrentFailures.push(...allFailureKeys); @@ -4191,8 +4194,20 @@ export class FwsCore { this.masterWarning.set(this.requestMasterWarningFromFaults || this.requestMasterWarningFromApOff); - if (failureSystemCount + rightFailureSystemCount === 0) { + if (failureSystemCount === 0) { SimVar.SetSimVarValue('L:A32NX_ECAM_SFAIL', 'number', -1); + } else { + const sortedAbnormals = this.presentedFailures.sort((a, b) => { + return FwsAbnormalSensed.compareAbnormalProceduresByPriority( + a, + b, + this.ewdAbnormal[a].failure, + this.ewdAbnormal[b].failure, + ); + }); + if (sortedAbnormals.length > 0 && this.ewdAbnormal[sortedAbnormals[0]].sysPage > -1) { + SimVar.SetSimVarValue('L:A32NX_ECAM_SFAIL', 'number', this.ewdAbnormal[sortedAbnormals[0]].sysPage); + } } this.ewdMessageLinesLeft.forEach((l, i) => l.set(orderedMemoArrayLeft[i])); @@ -4379,6 +4394,9 @@ export class FwsCore { } messagePriority(message: string): number { + if (!message) { + return 10; + } // Highest importance: priority 0 switch (message.trim().substring(0, 3)) { case '\x1b<6': diff --git a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsNormalChecklists.ts b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsNormalChecklists.ts index da6b3713265..ee1995014df 100644 --- a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsNormalChecklists.ts +++ b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsNormalChecklists.ts @@ -365,6 +365,40 @@ export class FwsNormalChecklists { } } + // Update deferred proc status + for (let i = 0; i <= 3; i++) { + this.hasDeferred[i] = false; + this.deferredIsCompleted[i] = true; + } + this.fws.activeDeferredProceduresList.get().forEach((val) => { + switch (EcamDeferredProcedures[val.id]?.type) { + case DeferredProcedureType.ALL_PHASES: + this.hasDeferred[0] = true; + if (!val.procedureCompleted) { + this.deferredIsCompleted[0] = false; + } + break; + case DeferredProcedureType.AT_TOP_OF_DESCENT: + this.hasDeferred[1] = true; + if (!val.procedureCompleted) { + this.deferredIsCompleted[1] = false; + } + break; + case DeferredProcedureType.FOR_APPROACH: + this.hasDeferred[2] = true; + if (!val.procedureCompleted) { + this.deferredIsCompleted[2] = false; + } + break; + case DeferredProcedureType.FOR_LANDING: + this.hasDeferred[3] = true; + if (!val.procedureCompleted) { + this.deferredIsCompleted[3] = false; + } + break; + } + }); + // Update sensed items const ids = this.getNormalProceduresKeysSorted(); @@ -377,7 +411,6 @@ export class FwsNormalChecklists { const deferredProcIndex = deferredProcedureIds.indexOf(procId); const procCompleted = deferredProcIndex !== -1 ? this.deferredIsCompleted[deferredProcIndex] : cl.procedureCompleted; - const sensedResult = this.sensedItems[procId].whichItemsChecked(); const changedEntries = sensedResult.map((val, index) => val !== null && val !== cl.itemsChecked[index] ? index : null, @@ -405,39 +438,6 @@ export class FwsNormalChecklists { } } - // Update deferred proc status - for (let i = 0; i < 3; i++) { - this.hasDeferred[i] = false; - this.deferredIsCompleted[i] = true; - } - this.fws.activeDeferredProceduresList.get().forEach((val) => { - switch (EcamDeferredProcedures[val.id]?.type) { - case DeferredProcedureType.ALL_PHASES: - this.hasDeferred[0] = true; - if (!val.procedureCompleted) { - this.deferredIsCompleted[0] = false; - } - break; - case DeferredProcedureType.AT_TOP_OF_DESCENT: - this.hasDeferred[1] = true; - if (!val.procedureCompleted) { - this.deferredIsCompleted[1] = false; - } - break; - case DeferredProcedureType.FOR_APPROACH: - this.hasDeferred[2] = true; - if (!val.procedureCompleted) { - this.deferredIsCompleted[2] = false; - } - break; - case DeferredProcedureType.FOR_LANDING: - this.hasDeferred[3] = true; - if (!val.procedureCompleted) { - this.deferredIsCompleted[3] = false; - } - break; - } - }); const overviewState = this.checklistState.getValue(0); overviewState.itemsChecked[Object.keys(EcamNormalProcedures).indexOf('1000007')] = this.deferredIsCompleted[0]; overviewState.itemsChecked[Object.keys(EcamNormalProcedures).indexOf('1000008')] = this.deferredIsCompleted[1]; From b5021cd1a5c4b2db428a7e8b963d4032efa6f26d Mon Sep 17 00:00:00 2001 From: flogross89 <63071941+flogross89@users.noreply.github.com> Date: Mon, 23 Dec 2024 00:35:44 +0100 Subject: [PATCH 25/40] changelog --- .github/CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/CHANGELOG.md b/.github/CHANGELOG.md index 27d3ea96b20..a9dfc3b301b 100644 --- a/.github/CHANGELOG.md +++ b/.github/CHANGELOG.md @@ -98,6 +98,7 @@ 1. [ELEC] Improved elec system startup behaviour - @Gurgel100 (Pascal) - @saschl 1. [A380X] Improve pilot and copilot camera positions - @heclak (Heclak) 1. [A380X/EFIS] Illuminate ND range and mode selectors during light test - @BravoMike99 (bruno_pt99) +1. [A380X/FWS] Add support for deferred procedures, abnormal (non-)sensed procedures - @flogross89 (floridude) ## 0.12.0 From de6f5459690a70b3026839276f864c8b99f3ba13 Mon Sep 17 00:00:00 2001 From: flogross89 <63071941+flogross89@users.noreply.github.com> Date: Sun, 29 Dec 2024 02:05:35 +0100 Subject: [PATCH 26/40] make FWS resettable through reset panel --- .../FlyByWire_A380_842/model/A380_COCKPIT.xml | 10 +++ .../model/behaviour/overhead/reset.xml | 17 +++++ .../src/systems/instruments/src/EWD/EWD.tsx | 44 +++++++++++- .../src/EWD/elements/FormattedFwcText.tsx | 8 ++- .../src/EWD/shared/EwdSimvarPublisher.tsx | 12 ++++ .../systems/instruments/src/EWD/style.scss | 7 ++ .../providers/CpiomAvailablePublisher.tsx | 21 ++++++ .../providers/FwsPfdPublisher.tsx | 12 ++++ .../providers/ResetPanelPublisher.tsx | 21 ++++++ .../systems/instruments/src/PFD/LowerArea.tsx | 61 +++++++++++++--- .../src/SD/Pages/Status/StatusPage.tsx | 14 +++- fbw-a380x/src/systems/systems-host/index.ts | 69 +++++++++++++++++-- .../FwsAbnormalNonSensed.ts | 6 ++ .../FlightWarningSystem/FwsAbnormalSensed.ts | 4 ++ .../systems/FlightWarningSystem/FwsCore.ts | 14 ++++ 15 files changed, 299 insertions(+), 21 deletions(-) create mode 100644 fbw-a380x/src/base/flybywire-aircraft-a380-842/SimObjects/AirPlanes/FlyByWire_A380_842/model/behaviour/overhead/reset.xml create mode 100644 fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/providers/CpiomAvailablePublisher.tsx create mode 100644 fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/providers/ResetPanelPublisher.tsx diff --git a/fbw-a380x/src/base/flybywire-aircraft-a380-842/SimObjects/AirPlanes/FlyByWire_A380_842/model/A380_COCKPIT.xml b/fbw-a380x/src/base/flybywire-aircraft-a380-842/SimObjects/AirPlanes/FlyByWire_A380_842/model/A380_COCKPIT.xml index 0a1ada10219..13c880767eb 100644 --- a/fbw-a380x/src/base/flybywire-aircraft-a380-842/SimObjects/AirPlanes/FlyByWire_A380_842/model/A380_COCKPIT.xml +++ b/fbw-a380x/src/base/flybywire-aircraft-a380-842/SimObjects/AirPlanes/FlyByWire_A380_842/model/A380_COCKPIT.xml @@ -35,6 +35,7 @@ + @@ -4979,6 +4980,15 @@ False + + + + FWS1 + + + FWS2 + + OverheadLower diff --git a/fbw-a380x/src/base/flybywire-aircraft-a380-842/SimObjects/AirPlanes/FlyByWire_A380_842/model/behaviour/overhead/reset.xml b/fbw-a380x/src/base/flybywire-aircraft-a380-842/SimObjects/AirPlanes/FlyByWire_A380_842/model/behaviour/overhead/reset.xml new file mode 100644 index 00000000000..540f6250ca0 --- /dev/null +++ b/fbw-a380x/src/base/flybywire-aircraft-a380-842/SimObjects/AirPlanes/FlyByWire_A380_842/model/behaviour/overhead/reset.xml @@ -0,0 +1,17 @@ + + + + + + diff --git a/fbw-a380x/src/systems/instruments/src/EWD/EWD.tsx b/fbw-a380x/src/systems/instruments/src/EWD/EWD.tsx index dfd29938946..8355e54a933 100644 --- a/fbw-a380x/src/systems/instruments/src/EWD/EWD.tsx +++ b/fbw-a380x/src/systems/instruments/src/EWD/EWD.tsx @@ -3,6 +3,7 @@ import { CdsDisplayUnit, DisplayUnitID } from '../MsfsAvionicsCommon/CdsDisplayU import { ConsumerSubject, DisplayComponent, + EventSubscriber, FSComponent, MappedSubject, Subject, @@ -21,10 +22,13 @@ import { WdNormalChecklists } from 'instruments/src/EWD/elements/WdNormalCheckli import { FwsEwdEvents } from 'instruments/src/MsfsAvionicsCommon/providers/FwsEwdPublisher'; import { WdAbnormalSensedProcedures } from 'instruments/src/EWD/elements/WdAbnormalSensedProcedures'; import { WdAbnormalNonSensedProcedures } from 'instruments/src/EWD/elements/WdAbnormalNonSensed'; +import { FormattedFwcText } from 'instruments/src/EWD/elements/FormattedFwcText'; export class EngineWarningDisplay extends DisplayComponent<{ bus: ArincEventBus }> { private readonly sub = this.props.bus.getSubscriber(); + private readonly availChecker = new FwsEwdAvailabilityChecker(this.sub); + private readonly engineStateSubs: ConsumerSubject[] = [ ConsumerSubject.create(this.sub.on('engine_state_1'), 0), ConsumerSubject.create(this.sub.on('engine_state_2'), 0), @@ -234,7 +238,10 @@ export class EngineWarningDisplay extends DisplayComponent<{ bus: ArincEventBus -
+
(s ? 'flex' : 'none')) }} + > @@ -265,8 +272,43 @@ export class EngineWarningDisplay extends DisplayComponent<{ bus: ArincEventBus
+
(s ? 'none' : 'flex')) }}> + + + +
); } } + +class FwsEwdAvailabilityChecker { + constructor(private sub: EventSubscriber) {} + + private readonly fws1IsHealthy = ConsumerSubject.create(this.sub.on('fws1_is_healthy'), true); + private readonly fws2IsHealthy = ConsumerSubject.create(this.sub.on('fws2_is_healthy'), true); + private readonly fwsIsHealthy = MappedSubject.create( + SubscribableMapFunctions.and(), + this.fws1IsHealthy, + this.fws2IsHealthy, + ); + + private readonly afdx_3_3_reachable = ConsumerSubject.create(this.sub.on('afdx_3_3_reachable'), true); + private readonly afdx_13_13_reachable = ConsumerSubject.create(this.sub.on('afdx_13_13_reachable'), true); + private readonly afdx_4_3_reachable = ConsumerSubject.create(this.sub.on('afdx_4_3_reachable'), true); + private readonly afdx_14_13_reachable = ConsumerSubject.create(this.sub.on('afdx_14_13_reachable'), true); + private readonly fwsPfdReachable = MappedSubject.create( + ([r_3_3, r_13_13, r_4_3, r_14_13]) => (r_3_3 && r_4_3) || (r_13_13 && r_14_13), + this.afdx_3_3_reachable, + this.afdx_13_13_reachable, + this.afdx_4_3_reachable, + this.afdx_14_13_reachable, + ); + + public readonly fwsAvail = MappedSubject.create( + SubscribableMapFunctions.and(), + this.fwsIsHealthy, + this.fwsPfdReachable, + ); +} diff --git a/fbw-a380x/src/systems/instruments/src/EWD/elements/FormattedFwcText.tsx b/fbw-a380x/src/systems/instruments/src/EWD/elements/FormattedFwcText.tsx index d2f0a0e070f..a99d6549342 100644 --- a/fbw-a380x/src/systems/instruments/src/EWD/elements/FormattedFwcText.tsx +++ b/fbw-a380x/src/systems/instruments/src/EWD/elements/FormattedFwcText.tsx @@ -2,10 +2,10 @@ // // SPDX-License-Identifier: GPL-3.0 -import { DisplayComponent, FSComponent, Subscribable, VNode } from '@microsoft/msfs-sdk'; +import { DisplayComponent, FSComponent, Subscribable, SubscribableUtils, VNode } from '@microsoft/msfs-sdk'; interface FormattedFwcTextProps { - message: Subscribable; + message: Subscribable | string; x: number; y: number; /** Whether this line will be rendered in the PFD. Has impact on font-size */ @@ -16,10 +16,12 @@ export class FormattedFwcText extends DisplayComponent { private decorationRef = FSComponent.createRef(); + private readonly messageSub = SubscribableUtils.toSubscribable(this.props.message, true); + onAfterRender(node: VNode): void { super.onAfterRender(node); - this.props.message.sub((message) => { + this.messageSub.sub((message) => { const LINE_SPACING = 30; const LETTER_WIDTH = 16; diff --git a/fbw-a380x/src/systems/instruments/src/EWD/shared/EwdSimvarPublisher.tsx b/fbw-a380x/src/systems/instruments/src/EWD/shared/EwdSimvarPublisher.tsx index 9c42cbe26d9..e4bbd35b708 100644 --- a/fbw-a380x/src/systems/instruments/src/EWD/shared/EwdSimvarPublisher.tsx +++ b/fbw-a380x/src/systems/instruments/src/EWD/shared/EwdSimvarPublisher.tsx @@ -43,6 +43,12 @@ export interface BaseEwdSimvars { nose_gear_compressed: boolean; engine_fire_pb: boolean; cas: number; + fws1_is_healthy: boolean; + fws2_is_healthy: boolean; + afdx_3_3_reachable: boolean; + afdx_13_13_reachable: boolean; + afdx_4_3_reachable: boolean; + afdx_14_13_reachable: boolean; } type IndexedTopics = @@ -124,6 +130,12 @@ export class EwdSimvarPublisher extends SimVarPublisher { ], ['engine_fire_pb', { name: 'L:A32NX_FIRE_BUTTON_ENG#index#', type: SimVarValueType.Bool, indexed: true }], ['cas', { name: 'L:A32NX_ADIRS_ADR_#index#_COMPUTED_AIRSPEED', type: SimVarValueType.Number, indexed: true }], + ['fws1_is_healthy', { name: 'L:A32NX_FWS1_IS_HEALTHY', type: SimVarValueType.Bool }], + ['fws2_is_healthy', { name: 'L:A32NX_FWS2_IS_HEALTHY', type: SimVarValueType.Bool }], + ['afdx_3_3_reachable', { name: 'L:A32NX_AFDX_3_3_REACHABLE', type: SimVarValueType.Bool }], + ['afdx_13_13_reachable', { name: 'L:A32NX_AFDX_13_13_REACHABLE', type: SimVarValueType.Bool }], + ['afdx_4_3_reachable', { name: 'L:A32NX_AFDX_4_3_REACHABLE', type: SimVarValueType.Bool }], + ['afdx_14_13_reachable', { name: 'L:A32NX_AFDX_14_13_REACHABLE', type: SimVarValueType.Bool }], ]; super(new Map(simvars), bus, pacer); diff --git a/fbw-a380x/src/systems/instruments/src/EWD/style.scss b/fbw-a380x/src/systems/instruments/src/EWD/style.scss index 11447761802..18dd7f81d58 100644 --- a/fbw-a380x/src/systems/instruments/src/EWD/style.scss +++ b/fbw-a380x/src/systems/instruments/src/EWD/style.scss @@ -320,6 +320,13 @@ text, tspan, span { padding: 2px; } +.WdNotAvailArea { + display: flex; + flex: 1; + justify-content: center; + align-items: center; +} + .MemosContainer { display: flex; flex-direction: column; diff --git a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/providers/CpiomAvailablePublisher.tsx b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/providers/CpiomAvailablePublisher.tsx new file mode 100644 index 00000000000..bcdc00f75c1 --- /dev/null +++ b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/providers/CpiomAvailablePublisher.tsx @@ -0,0 +1,21 @@ +// Copyright (c) 2021-2023 FlyByWire Simulations +// +// SPDX-License-Identifier: GPL-3.0 + +import { EventBus, SimVarDefinition, SimVarValueType, SimVarPublisher } from '@microsoft/msfs-sdk'; + +export type CpiomAvailableSimvars = { + cpiomC1Avail: boolean; + cpiomC2Avail: boolean; +}; + +export class CpiomAvailableSimvarPublisher extends SimVarPublisher { + private static simvars = new Map([ + ['cpiomC1Avail', { name: 'L:A32NX_CPIOM_C1_AVAIL', type: SimVarValueType.Bool }], + ['cpiomC2Avail', { name: 'L:A32NX_CPIOM_C2_AVAIL', type: SimVarValueType.Bool }], + ]); + + public constructor(bus: EventBus) { + super(CpiomAvailableSimvarPublisher.simvars, bus); + } +} diff --git a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/providers/FwsPfdPublisher.tsx b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/providers/FwsPfdPublisher.tsx index e3db0bb3eb2..fc9b5a1a6b2 100644 --- a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/providers/FwsPfdPublisher.tsx +++ b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/providers/FwsPfdPublisher.tsx @@ -10,6 +10,12 @@ import { interface FwsPfdBaseSimvars { memo_line: number; limitations_line: number; + fws1_is_healthy: boolean; + fws2_is_healthy: boolean; + afdx_3_1_reachable: boolean; + afdx_13_11_reachable: boolean; + afdx_4_2_reachable: boolean; + afdx_14_12_reachable: boolean; } enum FwsPfdVars { @@ -30,6 +36,12 @@ export class FwsPfdSimvarPublisher extends SimVarPublisher { const simvars: [keyof FwsPfdSimvars, SimVarPublisherEntry][] = [ ['memo_line', { name: FwsPfdVars.memoLineX, type: SimVarValueType.Number, indexed: true }], ['limitations_line', { name: FwsPfdVars.limitationsLineX, type: SimVarValueType.Number, indexed: true }], + ['fws1_is_healthy', { name: 'L:A32NX_FWS1_IS_HEALTHY', type: SimVarValueType.Bool }], + ['fws2_is_healthy', { name: 'L:A32NX_FWS2_IS_HEALTHY', type: SimVarValueType.Bool }], + ['afdx_3_1_reachable', { name: 'L:A32NX_AFDX_3_1_REACHABLE', type: SimVarValueType.Bool }], + ['afdx_13_11_reachable', { name: 'L:A32NX_AFDX_13_11_REACHABLE', type: SimVarValueType.Bool }], + ['afdx_4_2_reachable', { name: 'L:A32NX_AFDX_4_2_REACHABLE', type: SimVarValueType.Bool }], + ['afdx_14_12_reachable', { name: 'L:A32NX_AFDX_14_12_REACHABLE', type: SimVarValueType.Bool }], ]; super(new Map(simvars), bus, pacer); diff --git a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/providers/ResetPanelPublisher.tsx b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/providers/ResetPanelPublisher.tsx new file mode 100644 index 00000000000..626a9f06f36 --- /dev/null +++ b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/providers/ResetPanelPublisher.tsx @@ -0,0 +1,21 @@ +// Copyright (c) 2021-2023 FlyByWire Simulations +// +// SPDX-License-Identifier: GPL-3.0 + +import { EventBus, SimVarDefinition, SimVarValueType, SimVarPublisher } from '@microsoft/msfs-sdk'; + +export type ResetPanelSimvars = { + fws1Reset: boolean; + fws2Reset: boolean; +}; + +export class ResetPanelSimvarPublisher extends SimVarPublisher { + private static simvars = new Map([ + ['fws1Reset', { name: 'L:A32NX_RESET_PANEL_FWS1', type: SimVarValueType.Bool }], + ['fws2Reset', { name: 'L:A32NX_RESET_PANEL_FWS2', type: SimVarValueType.Bool }], + ]); + + public constructor(bus: EventBus) { + super(ResetPanelSimvarPublisher.simvars, bus); + } +} diff --git a/fbw-a380x/src/systems/instruments/src/PFD/LowerArea.tsx b/fbw-a380x/src/systems/instruments/src/PFD/LowerArea.tsx index b4b5bb70af3..24ea70f3fef 100644 --- a/fbw-a380x/src/systems/instruments/src/PFD/LowerArea.tsx +++ b/fbw-a380x/src/systems/instruments/src/PFD/LowerArea.tsx @@ -9,6 +9,7 @@ import { MappedSubject, Subject, Subscribable, + SubscribableMapFunctions, VNode, } from '@microsoft/msfs-sdk'; import { @@ -668,6 +669,8 @@ class RudderTrimIndicator extends DisplayComponent<{ bus: ArincEventBus }> { class Limitations extends DisplayComponent<{ bus: ArincEventBus; visible: Subscribable }> { private readonly sub = this.props.bus.getSubscriber(); + private readonly availChecker = new FwsPfdAvailabilityChecker(this.sub); + private static lineSubject(index: number, sub: EventSubscriber) { return ConsumerSubject.create(sub.on(`limitations_line_${index}`).whenChanged(), 0).map( (it) => EcamLimitations[it] ?? '', @@ -688,9 +691,14 @@ class Limitations extends DisplayComponent<{ bus: ArincEventBus; visible: Subscr render(): VNode { return ( (it ? 'visible' : 'hidden'))}> - {this.limitationsLine.map((line, index) => ( - - ))} + (it ? 'visible' : 'hidden'))}> + {this.limitationsLine.map((line, index) => ( + + ))} + + (it ? 'hidden' : 'visible'))}> + + ); } @@ -700,6 +708,8 @@ const padMemoCode = (code: number) => code.toString().padStart(9, '0'); class Memos extends DisplayComponent<{ bus: ArincEventBus }> { private readonly sub = this.props.bus.getSubscriber(); + private readonly availChecker = new FwsPfdAvailabilityChecker(this.sub); + private readonly memoLine1 = ConsumerSubject.create(this.sub.on('memo_line_1').whenChanged(), 0).map( (it) => EcamMemos[padMemoCode(it)] ?? '', ); @@ -714,11 +724,46 @@ class Memos extends DisplayComponent<{ bus: ArincEventBus }> { render(): VNode { return ( - - - - - + <> + (it ? 'visible' : 'hidden'))}> + + + + + (it ? 'hidden' : 'visible'))}> + + + ); } } + +class FwsPfdAvailabilityChecker { + constructor(private sub: EventSubscriber) {} + + private readonly fws1IsHealthy = ConsumerSubject.create(this.sub.on('fws1_is_healthy'), true); + private readonly fws2IsHealthy = ConsumerSubject.create(this.sub.on('fws2_is_healthy'), true); + private readonly fwsIsHealthy = MappedSubject.create( + SubscribableMapFunctions.and(), + this.fws1IsHealthy, + this.fws2IsHealthy, + ); + + private readonly afdx_3_1_reachable = ConsumerSubject.create(this.sub.on('afdx_3_1_reachable'), true); + private readonly afdx_13_11_reachable = ConsumerSubject.create(this.sub.on('afdx_13_11_reachable'), true); + private readonly afdx_4_2_reachable = ConsumerSubject.create(this.sub.on('afdx_4_2_reachable'), true); + private readonly afdx_14_12_reachable = ConsumerSubject.create(this.sub.on('afdx_14_12_reachable'), true); + private readonly fwsPfdReachable = MappedSubject.create( + ([r_3_1, r_13_11, r_4_2, r_14_12]) => (r_3_1 && r_4_2) || (r_13_11 && r_14_12), + this.afdx_3_1_reachable, + this.afdx_13_11_reachable, + this.afdx_4_2_reachable, + this.afdx_14_12_reachable, + ); + + public readonly fwsAvail = MappedSubject.create( + SubscribableMapFunctions.and(), + this.fwsIsHealthy, + this.fwsPfdReachable, + ); +} diff --git a/fbw-a380x/src/systems/instruments/src/SD/Pages/Status/StatusPage.tsx b/fbw-a380x/src/systems/instruments/src/SD/Pages/Status/StatusPage.tsx index bd0ff37cb18..aeda1bda3e0 100644 --- a/fbw-a380x/src/systems/instruments/src/SD/Pages/Status/StatusPage.tsx +++ b/fbw-a380x/src/systems/instruments/src/SD/Pages/Status/StatusPage.tsx @@ -39,12 +39,17 @@ export const StatusPage: React.FC = () => { const statusNormal = !(limitationsVisible || maxInopLines > 0); + // Skip ADCN reachability check for now, add when ported to avionics framework + const [fws1IsHealthy] = useSimVar('L:A32NX_FWS1_IS_HEALTHY', 'number', 1000); + const [fws2IsHealthy] = useSimVar('L:A32NX_FWS1_IS_HEALTHY', 'number', 1000); + const statusNotAvailable = !fws1IsHealthy && !fws2IsHealthy; + return ( <> STATUS - {!statusNormal && ( + {!statusNormal && !statusNotAvailable && ( <> @@ -92,11 +97,16 @@ export const StatusPage: React.FC = () => { )} - {statusNormal && ( + {statusNormal && !statusNotAvailable && ( NORMAL )} + {statusNotAvailable && ( + + STATUS NOT AVAILABLE + + )} ); }; diff --git a/fbw-a380x/src/systems/systems-host/index.ts b/fbw-a380x/src/systems/systems-host/index.ts index b8ebac5a4de..f63035bda67 100644 --- a/fbw-a380x/src/systems/systems-host/index.ts +++ b/fbw-a380x/src/systems/systems-host/index.ts @@ -12,6 +12,7 @@ import { SubscribableMapFunctions, WeightBalanceSimvarPublisher, StallWarningPublisher, + SimVarValueType, } from '@microsoft/msfs-sdk'; import { LegacyGpws } from 'systems-host/systems/LegacyGpws'; import { LegacyFuel } from 'systems-host/systems/LegacyFuel'; @@ -35,11 +36,20 @@ import { FwsCore } from 'systems-host/systems/FlightWarningSystem/FwsCore'; import { FuelSystemPublisher } from 'systems-host/systems/FuelSystemPublisher'; import { BrakeToVacateDistanceUpdater } from 'systems-host/systems/BrakeToVacateDistanceUpdater'; import { PseudoFwcSimvarPublisher } from 'instruments/src/MsfsAvionicsCommon/providers/PseudoFwcPublisher'; +import { + ResetPanelSimvarPublisher, + ResetPanelSimvars, +} from 'instruments/src/MsfsAvionicsCommon/providers/ResetPanelPublisher'; +import { + CpiomAvailableSimvarPublisher, + CpiomAvailableSimvars, +} from 'instruments/src/MsfsAvionicsCommon/providers/CpiomAvailablePublisher'; +CpiomAvailableSimvarPublisher; class SystemsHost extends BaseInstrument { private readonly bus = new ArincEventBus(); - private readonly sub = this.bus.getSubscriber(); + private readonly sub = this.bus.getSubscriber(); private readonly backplane = new InstrumentBackplane(); @@ -50,9 +60,9 @@ class SystemsHost extends BaseInstrument { private readonly failuresConsumer = new FailuresConsumer('A32NX'); // TODO: Migrate PowerSupplyBusses, if needed - private gpws: LegacyGpws; + private gpws: LegacyGpws | undefined; - private soundManager: LegacySoundManager; + private soundManager: LegacySoundManager | undefined; private readonly acEssBusPowered = ConsumerSubject.create(this.sub.on('acBusEss'), false); private readonly acBus2Powered = ConsumerSubject.create(this.sub.on('acBus2'), false); @@ -99,7 +109,33 @@ class SystemsHost extends BaseInstrument { private readonly pseudoFwcPublisher = new PseudoFwcSimvarPublisher(this.bus); - private readonly fwsCore = new FwsCore(1, this.bus); + private readonly resetPanelPublisher = new ResetPanelSimvarPublisher(this.bus); + + private readonly fws1ResetPbStatus = ConsumerSubject.create(this.sub.on('fws1Reset'), false); + private readonly fws2ResetPbStatus = ConsumerSubject.create(this.sub.on('fws2Reset'), false); + private readonly fwsResetStatus = MappedSubject.create( + SubscribableMapFunctions.and(), + this.fws1ResetPbStatus, + this.fws2ResetPbStatus, + ); + + private readonly cpiomAvailablePublisher = new CpiomAvailableSimvarPublisher(this.bus); + + private readonly fws1Powered = ConsumerSubject.create(this.sub.on('cpiomC1Avail'), true); + private readonly fws2Powered = ConsumerSubject.create(this.sub.on('cpiomC2Avail'), true); + private readonly bothFwsPowered = MappedSubject.create( + SubscribableMapFunctions.and(), + this.fws1Powered, + this.fws2Powered, + ); + + private readonly fwsAvailable = MappedSubject.create( + ([reset, powered]) => !reset && powered, + this.fwsResetStatus, + this.bothFwsPowered, + ); + + private fwsCore: FwsCore | undefined = new FwsCore(1, this.bus); //FIXME add some deltatime functionality to backplane instruments so we dont have to pass SystemHost private readonly legacyFuel = new LegacyFuel(this.bus, this); @@ -133,6 +169,8 @@ class SystemsHost extends BaseInstrument { this.backplane.addPublisher('FuelPublisher', this.fuelSystemPublisher); this.backplane.addPublisher('StallWarning', this.stallWarningPublisher); this.backplane.addPublisher('PseudoFwc', this.pseudoFwcPublisher); + this.backplane.addPublisher('ResetPanel', this.resetPanelPublisher); + this.backplane.addPublisher('CpiomAvailable', this.cpiomAvailablePublisher); this.backplane.addInstrument('LegacyFuel', this.legacyFuel); this.hEventPublisher = new HEventPublisher(this.bus); @@ -152,10 +190,27 @@ class SystemsHost extends BaseInstrument { const dt = lastUpdateTime === undefined ? 0 : now - lastUpdateTime; lastUpdateTime = now; - this.soundManager.update(dt); - this.gpws.update(dt); - this.fwsCore.update(dt); + this.soundManager?.update(dt); + this.gpws?.update(dt); + this.fwsCore?.update(dt); }); + + this.fwsAvailable.sub((a) => { + console.log(a); + SimVar.SetSimVarValue('L:A32NX_FWS1_IS_HEALTHY', SimVarValueType.Bool, a); + SimVar.SetSimVarValue('L:A32NX_FWS2_IS_HEALTHY', SimVarValueType.Bool, a); + if (!a && this.fwsCore !== undefined) { + this.fwsCore = undefined; + this.soundManager = undefined; + this.gpws = undefined; + } else if (a && this.fwsCore === undefined) { + this.fwsCore = new FwsCore(1, this.bus); + this.soundManager = new LegacySoundManager(); + this.gpws = new LegacyGpws(this.bus, this.soundManager); + this.gpws.init(); + this.fwsCore.init(); + } + }, true); } get templateID(): string { diff --git a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsAbnormalNonSensed.ts b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsAbnormalNonSensed.ts index c24b02c1d5d..6481414dcb7 100644 --- a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsAbnormalNonSensed.ts +++ b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsAbnormalNonSensed.ts @@ -117,6 +117,12 @@ export class FwsAbnormalNonSensed { } } + reset() { + this.fws.activeAbnormalNonSensedKeys.clear(); + this.checklistState.clear(); + this.showAbnProcRequested.set(false); + } + public ewdAbnormalNonSensed: EwdAbnormalDict = { 260900097: { // SMOKE / FUMES diff --git a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsAbnormalSensed.ts b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsAbnormalSensed.ts index 1cdd302a427..a9a15d15654 100644 --- a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsAbnormalSensed.ts +++ b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsAbnormalSensed.ts @@ -247,6 +247,10 @@ export class FwsAbnormalSensed { } } + reset() { + this.showAbnormalSensedRequested.set(false); + } + public ewdAbnormalSensed: EwdAbnormalDict = { // 21 - AIR CONDITIONING AND PRESSURIZATION 211800001: { diff --git a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsCore.ts b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsCore.ts index 55330129573..646da66108d 100644 --- a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsCore.ts +++ b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsCore.ts @@ -4412,4 +4412,18 @@ export class FwsCore { return 10; } } + + turnaroundReset() { + // Reset after flight phase xx, to reset some parts during turnaround + // Resets normal checklists, resets state of abnormal sensed procedures, deactivation of deferred procedures and abormal non-sensed procedures + // this.normalChecklists.reset(); // Wait for BM's PR + this.abnormalNonSensed.reset(); + this.abnormalSensed.reset(); + + this.activeDeferredProceduresList.clear(); + this.activeAbnormalProceduresList.clear(); + this.allCurrentFailures.length = 0; + this.presentedFailures.length = 0; + this.recallFailures.length = 0; + } } From 19f22f2a7629d631ab507038b5cd0de6df1ff8ee Mon Sep 17 00:00:00 2001 From: flogross89 <63071941+flogross89@users.noreply.github.com> Date: Sun, 29 Dec 2024 04:10:34 +0100 Subject: [PATCH 27/40] add deferred check list auto display --- .../FlightWarningSystem/FwsNormalChecklists.ts | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsNormalChecklists.ts b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsNormalChecklists.ts index ee1995014df..6122daf6773 100644 --- a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsNormalChecklists.ts +++ b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsNormalChecklists.ts @@ -334,6 +334,18 @@ export class FwsNormalChecklists { this.showFromLine.set(Math.max(0, this.selectedLine.get() - WD_NUM_LINES + 2)); } + private checkIfDeferredAutoDisplay() { + if ( + this.fws.adrPressureAltitude.get() < 20_000 && + this.fws.slatsAngle.get() > 0 && + Simplane.getPressureSelectedMode(Aircraft.A320_NEO) !== 'STD' && + !this.showChecklistRequested.get() && + this.hasDeferred.some((v) => v) + ) { + this.showChecklistRequested.set(true); + } + } + update() { if (this.fws.clPulseNode.read()) { this.navigateToChecklist(0); @@ -397,6 +409,8 @@ export class FwsNormalChecklists { } break; } + + this.checkIfDeferredAutoDisplay(); }); // Update sensed items From 473dc3a1a925957951bcaf024756bc04cbe93c38 Mon Sep 17 00:00:00 2001 From: flogross89 <63071941+flogross89@users.noreply.github.com> Date: Sun, 29 Dec 2024 17:48:00 +0100 Subject: [PATCH 28/40] refactor turnaround reset --- .../systems/FlightWarningSystem/FwsCore.ts | 16 ++++++++++++++-- .../FwsNormalChecklists.ts | 19 +++---------------- 2 files changed, 17 insertions(+), 18 deletions(-) diff --git a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsCore.ts b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsCore.ts index 2c442615e84..e04b0503b35 100644 --- a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsCore.ts +++ b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsCore.ts @@ -1520,6 +1520,18 @@ export class FwsCore { this.abnormalNonSensed.ewdAbnormalNonSensed, ); + this.startupCompleted.sub((v) => { + if (v) { + this.turnaroundReset(); + } + }); + + this.shutDownFor50MinutesCheckListReset.sub((v) => { + if (v) { + this.turnaroundReset(); + } + }); + this.ewdMessageLinesLeft.forEach((ls, i) => ls.sub((l) => { SimVar.SetSimVarValue(FwsCore.ewdMessageSimVarsLeft[i], 'string', l ?? ''); @@ -4436,9 +4448,9 @@ export class FwsCore { } turnaroundReset() { - // Reset after flight phase xx, to reset some parts during turnaround + // Reset some parts during turnaround // Resets normal checklists, resets state of abnormal sensed procedures, deactivation of deferred procedures and abormal non-sensed procedures - // this.normalChecklists.reset(); // Wait for BM's PR + this.normalChecklists.reset(null); this.abnormalNonSensed.reset(); this.abnormalSensed.reset(); diff --git a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsNormalChecklists.ts b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsNormalChecklists.ts index d497c0b9e35..45e71ff850a 100644 --- a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsNormalChecklists.ts +++ b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsNormalChecklists.ts @@ -195,18 +195,6 @@ export class FwsNormalChecklists { } }); - this.fws.startupCompleted.sub((v) => { - if (v) { - this.reset(null); - } - }); - - this.fws.shutDownFor50MinutesCheckListReset.sub((v) => { - if (v) { - this.reset(null); - } - }); - this.fws.flightPhase.sub((phase) => { if (phase !== 1) { this.fws.manualCheckListReset.set(false); @@ -333,11 +321,10 @@ export class FwsNormalChecklists { } reset(fromId: number | null) { - // Reset all following checklists - const ids = this.getNormalProceduresKeysSorted(); - if (fromId !== -1) { - for (let id = fromId + 1; id < ids.length; id++) { + const ids = this.getNormalProceduresKeysSorted(); + this.fws.manualCheckListReset.set(fromId !== null); + for (let id = fromId === null ? 0 : fromId + 1; id < ids.length; id++) { const idFollowing = ids[id]; const clFollowing = this.checklistState.getValue(idFollowing); const procFollowing = EcamNormalProcedures[idFollowing]; From 8f812e9e7c4b8cf457ebb2d15594f2d5451a86ec Mon Sep 17 00:00:00 2001 From: flogross89 <63071941+flogross89@users.noreply.github.com> Date: Sun, 29 Dec 2024 17:54:29 +0100 Subject: [PATCH 29/40] don't kill GPWS with FWS --- fbw-a380x/src/systems/systems-host/index.ts | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/fbw-a380x/src/systems/systems-host/index.ts b/fbw-a380x/src/systems/systems-host/index.ts index f63035bda67..64bb577422e 100644 --- a/fbw-a380x/src/systems/systems-host/index.ts +++ b/fbw-a380x/src/systems/systems-host/index.ts @@ -190,24 +190,18 @@ class SystemsHost extends BaseInstrument { const dt = lastUpdateTime === undefined ? 0 : now - lastUpdateTime; lastUpdateTime = now; - this.soundManager?.update(dt); - this.gpws?.update(dt); + this.soundManager.update(dt); + this.gpws.update(dt); this.fwsCore?.update(dt); }); this.fwsAvailable.sub((a) => { - console.log(a); SimVar.SetSimVarValue('L:A32NX_FWS1_IS_HEALTHY', SimVarValueType.Bool, a); SimVar.SetSimVarValue('L:A32NX_FWS2_IS_HEALTHY', SimVarValueType.Bool, a); if (!a && this.fwsCore !== undefined) { this.fwsCore = undefined; - this.soundManager = undefined; - this.gpws = undefined; } else if (a && this.fwsCore === undefined) { this.fwsCore = new FwsCore(1, this.bus); - this.soundManager = new LegacySoundManager(); - this.gpws = new LegacyGpws(this.bus, this.soundManager); - this.gpws.init(); this.fwsCore.init(); } }, true); From 0f755f82ec33b5a938c81e40ea9fe03b51e1de82 Mon Sep 17 00:00:00 2001 From: flogross89 <63071941+flogross89@users.noreply.github.com> Date: Sun, 29 Dec 2024 20:57:26 +0100 Subject: [PATCH 30/40] ECP FAULT, AUDIO FUNCTION LOST, FWS1+2 FAULT --- .../model/behaviour/ecam-cp.xml | 4 + fbw-a380x/src/systems/failures/src/a380.ts | 11 +++ .../src/systems/instruments/src/EWD/EWD.tsx | 26 ++--- .../elements/WdAbnormalSensedProcedures.tsx | 46 ++++++--- .../elements/WdAbstractChecklistComponent.tsx | 1 + .../AbnormalSensed/ata31-32-33.tsx | 99 ++++++++++++++++++- .../MsfsAvionicsCommon/EcamMessages/index.tsx | 2 + fbw-a380x/src/systems/systems-host/index.ts | 60 +++++++---- .../FlightWarningSystem/FwsAbnormalSensed.ts | 47 +++++++++ .../systems/FlightWarningSystem/FwsCore.ts | 30 +++++- .../FlightWarningSystem/FwsSoundManager.ts | 14 ++- 11 files changed, 287 insertions(+), 53 deletions(-) diff --git a/fbw-a380x/src/base/flybywire-aircraft-a380-842/SimObjects/AirPlanes/FlyByWire_A380_842/model/behaviour/ecam-cp.xml b/fbw-a380x/src/base/flybywire-aircraft-a380-842/SimObjects/AirPlanes/FlyByWire_A380_842/model/behaviour/ecam-cp.xml index 5fcec72124c..008a018058d 100644 --- a/fbw-a380x/src/base/flybywire-aircraft-a380-842/SimObjects/AirPlanes/FlyByWire_A380_842/model/behaviour/ecam-cp.xml +++ b/fbw-a380x/src/base/flybywire-aircraft-a380-842/SimObjects/AirPlanes/FlyByWire_A380_842/model/behaviour/ecam-cp.xml @@ -41,6 +41,10 @@ #NODE_ID# + (L:A32NX_FWS_ECP_FAILED, Bool) if{ + quit + } + (#STATE_SIMVAR#) #STATE_ID# != if{ #STATE_ID# (>#STATE_SIMVAR#) } els{ diff --git a/fbw-a380x/src/systems/failures/src/a380.ts b/fbw-a380x/src/systems/failures/src/a380.ts index 237dece47c3..bb182e00041 100644 --- a/fbw-a380x/src/systems/failures/src/a380.ts +++ b/fbw-a380x/src/systems/failures/src/a380.ts @@ -140,6 +140,12 @@ export const A380Failure = Object.freeze({ LeftPfdDisplay: 31000, RightPfdDisplay: 31001, + Fws1: 31100, + Fws2: 31101, + Fws1AudioFunction: 31102, + Fws2AudioFunction: 31103, + FwsEcp: 31104, + LgciuPowerSupply1: 32000, LgciuPowerSupply2: 32001, LgciuInternalError1: 32002, @@ -299,6 +305,11 @@ export const A380FailureDefinitions: FailureDefinition[] = [ [31, A380Failure.LeftPfdDisplay, 'Captain PFD display'], [31, A380Failure.RightPfdDisplay, 'F/O PFD display'], + [31, A380Failure.Fws1, 'FWS 1'], + [31, A380Failure.Fws2, 'FWS 2'], + [31, A380Failure.Fws1AudioFunction, 'FWS 1 Audio Function'], + [31, A380Failure.Fws2AudioFunction, 'FWS 2 Audio Function'], + [31, A380Failure.FwsEcp, 'ECAM Control Panel'], [32, A380Failure.LgciuPowerSupply1, 'LGCIU 1 Power supply'], [32, A380Failure.LgciuPowerSupply2, 'LGCIU 2 Power supply'], diff --git a/fbw-a380x/src/systems/instruments/src/EWD/EWD.tsx b/fbw-a380x/src/systems/instruments/src/EWD/EWD.tsx index 8355e54a933..c0f2362ac56 100644 --- a/fbw-a380x/src/systems/instruments/src/EWD/EWD.tsx +++ b/fbw-a380x/src/systems/instruments/src/EWD/EWD.tsx @@ -22,7 +22,6 @@ import { WdNormalChecklists } from 'instruments/src/EWD/elements/WdNormalCheckli import { FwsEwdEvents } from 'instruments/src/MsfsAvionicsCommon/providers/FwsEwdPublisher'; import { WdAbnormalSensedProcedures } from 'instruments/src/EWD/elements/WdAbnormalSensedProcedures'; import { WdAbnormalNonSensedProcedures } from 'instruments/src/EWD/elements/WdAbnormalNonSensed'; -import { FormattedFwcText } from 'instruments/src/EWD/elements/FormattedFwcText'; export class EngineWarningDisplay extends DisplayComponent<{ bus: ArincEventBus }> { private readonly sub = this.props.bus.getSubscriber(); @@ -238,14 +237,20 @@ export class EngineWarningDisplay extends DisplayComponent<{ bus: ArincEventBus -
(s ? 'flex' : 'none')) }} - > +
- + visible || !avail, + this.abnormalSensedVisible, + this.availChecker.fwsAvail, + )} + abnormal={true} + fwsAvail={this.availChecker.fwsAvail} + />
-
(s ? 'none' : 'flex')) }}> - - - -
); @@ -298,7 +298,7 @@ class FwsEwdAvailabilityChecker { private readonly afdx_13_13_reachable = ConsumerSubject.create(this.sub.on('afdx_13_13_reachable'), true); private readonly afdx_4_3_reachable = ConsumerSubject.create(this.sub.on('afdx_4_3_reachable'), true); private readonly afdx_14_13_reachable = ConsumerSubject.create(this.sub.on('afdx_14_13_reachable'), true); - private readonly fwsPfdReachable = MappedSubject.create( + private readonly fwsEwdReachable = MappedSubject.create( ([r_3_3, r_13_13, r_4_3, r_14_13]) => (r_3_3 && r_4_3) || (r_13_13 && r_14_13), this.afdx_3_3_reachable, this.afdx_13_13_reachable, @@ -309,6 +309,6 @@ class FwsEwdAvailabilityChecker { public readonly fwsAvail = MappedSubject.create( SubscribableMapFunctions.and(), this.fwsIsHealthy, - this.fwsPfdReachable, + this.fwsEwdReachable, ); } diff --git a/fbw-a380x/src/systems/instruments/src/EWD/elements/WdAbnormalSensedProcedures.tsx b/fbw-a380x/src/systems/instruments/src/EWD/elements/WdAbnormalSensedProcedures.tsx index 27ab9ff6841..a5df2a61142 100644 --- a/fbw-a380x/src/systems/instruments/src/EWD/elements/WdAbnormalSensedProcedures.tsx +++ b/fbw-a380x/src/systems/instruments/src/EWD/elements/WdAbnormalSensedProcedures.tsx @@ -1,4 +1,4 @@ -import { ConsumerSubject, VNode } from '@microsoft/msfs-sdk'; +import { ConsumerSubject, Subject, VNode } from '@microsoft/msfs-sdk'; import { ProcedureLinesGenerator, ProcedureType, @@ -6,6 +6,7 @@ import { import { WdAbstractChecklistComponent } from 'instruments/src/EWD/elements/WdAbstractChecklistComponent'; import { EcamAbnormalSensedProcedures } from 'instruments/src/MsfsAvionicsCommon/EcamMessages'; +import { ChecklistState } from 'instruments/src/MsfsAvionicsCommon/providers/FwsEwdPublisher'; export class WdAbnormalSensedProcedures extends WdAbstractChecklistComponent { private readonly procedures = ConsumerSubject.create(this.sub.on('fws_abn_sensed_procedures'), []); @@ -15,20 +16,39 @@ export class WdAbnormalSensedProcedures extends WdAbstractChecklistComponent { public updateChecklists() { this.lineData.length = 0; - this.procedures.get().forEach((procState, index) => { - const procGen = new ProcedureLinesGenerator( - procState.id, - this.activeProcedureId.map((id) => id === procState.id), + if (!this.props.fwsAvail || this.props.fwsAvail.get()) { + this.procedures.get().forEach((procState, index) => { + const procGen = new ProcedureLinesGenerator( + procState.id, + this.activeProcedureId.map((id) => id === procState.id), + ProcedureType.Abnormal, + procState, + undefined, + undefined, + undefined, + EcamAbnormalSensedProcedures[procState.id].recommendation, + index === 0, + ); + this.lineData.push(...procGen.toLineData()); + }); + } else { + // FWS 1+2 failed, show fallback + const fallbackClState: ChecklistState = { + id: '314800004', + procedureActivated: true, + procedureCompleted: false, + itemsActive: [true, true, true, true, true, true, true, true, true], + itemsChecked: [true, true, true, true, true, true, true, true, true], + itemsToShow: [true, true, true, true, true, true, true, true, true], + }; + const procGenFallback = new ProcedureLinesGenerator( + '314800004', + Subject.create(false), ProcedureType.Abnormal, - procState, - undefined, - undefined, - undefined, - EcamAbnormalSensedProcedures[procState.id].recommendation, - index === 0, + fallbackClState, ); - this.lineData.push(...procGen.toLineData()); - }); + this.lineData.push(...procGenFallback.toLineData()); + } super.updateChecklists(); } diff --git a/fbw-a380x/src/systems/instruments/src/EWD/elements/WdAbstractChecklistComponent.tsx b/fbw-a380x/src/systems/instruments/src/EWD/elements/WdAbstractChecklistComponent.tsx index 38b4a94a197..f993d5b2d1a 100644 --- a/fbw-a380x/src/systems/instruments/src/EWD/elements/WdAbstractChecklistComponent.tsx +++ b/fbw-a380x/src/systems/instruments/src/EWD/elements/WdAbstractChecklistComponent.tsx @@ -24,6 +24,7 @@ interface WdAbstractChecklistComponentProps { bus: EventBus; visible: Subscribable; abnormal: boolean; + fwsAvail?: Subscribable; } export class WdAbstractChecklistComponent extends DisplayComponent { diff --git a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata31-32-33.tsx b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata31-32-33.tsx index e6fbe1e878d..5e082d31cd1 100644 --- a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata31-32-33.tsx +++ b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata31-32-33.tsx @@ -137,7 +137,60 @@ export const EcamAbnormalSensedAta313233: { [n: number]: AbnormalProcedure } = { 314800004: { title: '\x1b<4m\x1b4mFWS\x1bm FWS 1+2 FAULT', sensed: true, - items: [], + items: [ + { + name: 'ECAM SD', + labelNotCompleted: 'MONITOR', + sensed: true, + }, + { + name: 'OVHD PNL', + labelNotCompleted: 'MONITOR', + sensed: true, + }, + { + name: 'FUNCTIONS NOT AVAIL:', + sensed: true, + style: ChecklistLineStyle.SubHeadline, + level: 1, + }, + { + name: 'ECAM WARNINGS & CAUTIONS', + sensed: true, + style: ChecklistLineStyle.Amber, + level: 1, + }, + { + name: 'ABN PROCEDURES', + sensed: true, + style: ChecklistLineStyle.Amber, + level: 1, + }, + { + name: 'LIMITATIONS & STATUS', + sensed: true, + style: ChecklistLineStyle.Amber, + level: 1, + }, + { + name: 'ALTITUDE ALERT', + sensed: true, + style: ChecklistLineStyle.Amber, + level: 1, + }, + { + name: 'AUTO CALLOUT', + sensed: true, + style: ChecklistLineStyle.Amber, + level: 1, + }, + { + name: 'NORM C/L & MEMO', + sensed: true, + style: ChecklistLineStyle.Amber, + level: 1, + }, + ], }, 314800005: { title: '\x1b<4m\x1b4mFWS\x1bm ATQC DATABASE REJECTED', @@ -145,14 +198,52 @@ export const EcamAbnormalSensedAta313233: { [n: number]: AbnormalProcedure } = { items: [], }, 314800006: { - title: '\x1b<4m\x1b4mFWS\x1bm AUDIO FUNCTION LOSS', + title: '\x1b<4m\x1b4mFWS\x1bm AUDIO FUNCTION LOST', sensed: true, - items: [], + items: [ + { + name: 'AUDIOS NOT AVAIL:', + style: ChecklistLineStyle.CompletedChecklist, + sensed: true, + }, + { + name: 'ALTITUDE ALERT', + style: ChecklistLineStyle.Cyan, + sensed: true, + }, + { + name: 'AUTO CALLOUT', + style: ChecklistLineStyle.Cyan, + sensed: true, + }, + { + name: 'AURAL ATTENTION GETTERS', + style: ChecklistLineStyle.Cyan, + sensed: true, + }, + ], }, 314800007: { title: '\x1b<4m\x1b4mFWS\x1bm ECP FAULT', sensed: true, - items: [], + items: [ + { + name: 'ECP KEYS NOT AVAIL:', + style: ChecklistLineStyle.Green, + sensed: true, + }, + { + name: 'SYSTEMS, MORE, TO CONFIG, RCL LAST', + style: ChecklistLineStyle.Green, + sensed: true, + level: 1, + }, + { + name: 'FOR SYS PAGES: "ALL" AVAIL', + style: ChecklistLineStyle.Green, + sensed: true, + }, + ], }, 314800008: { title: '\x1b<4m\x1b4mFWS\x1bm FWS 1 FAULT', diff --git a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/index.tsx b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/index.tsx index 088d65df4a9..d167ead6e71 100644 --- a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/index.tsx +++ b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/index.tsx @@ -507,6 +507,8 @@ export const EcamInopSys: { [n: string]: string } = { 290300021: '\x1b<4mG HYD SYS', 290300022: '\x1b<4mY HYD SYS', 310300001: '\x1b<4mAUTO CALLOUT', + 310300002: '\x1b<4mFWS 1', + 310300003: '\x1b<4mFWS 2', 320300001: '\x1b<4mA-SKID', 320300002: '\x1b<4mAUTO BRK', 320300003: '\x1b<4mPART A-SKID', diff --git a/fbw-a380x/src/systems/systems-host/index.ts b/fbw-a380x/src/systems/systems-host/index.ts index 64bb577422e..6411acb644e 100644 --- a/fbw-a380x/src/systems/systems-host/index.ts +++ b/fbw-a380x/src/systems/systems-host/index.ts @@ -13,6 +13,7 @@ import { WeightBalanceSimvarPublisher, StallWarningPublisher, SimVarValueType, + Subject, } from '@microsoft/msfs-sdk'; import { LegacyGpws } from 'systems-host/systems/LegacyGpws'; import { LegacyFuel } from 'systems-host/systems/LegacyFuel'; @@ -44,6 +45,7 @@ import { CpiomAvailableSimvarPublisher, CpiomAvailableSimvars, } from 'instruments/src/MsfsAvionicsCommon/providers/CpiomAvailablePublisher'; +import { A380Failure } from '@failures'; CpiomAvailableSimvarPublisher; class SystemsHost extends BaseInstrument { @@ -111,31 +113,32 @@ class SystemsHost extends BaseInstrument { private readonly resetPanelPublisher = new ResetPanelSimvarPublisher(this.bus); + private readonly cpiomAvailablePublisher = new CpiomAvailableSimvarPublisher(this.bus); + private readonly fws1ResetPbStatus = ConsumerSubject.create(this.sub.on('fws1Reset'), false); private readonly fws2ResetPbStatus = ConsumerSubject.create(this.sub.on('fws2Reset'), false); - private readonly fwsResetStatus = MappedSubject.create( - SubscribableMapFunctions.and(), - this.fws1ResetPbStatus, - this.fws2ResetPbStatus, - ); - - private readonly cpiomAvailablePublisher = new CpiomAvailableSimvarPublisher(this.bus); private readonly fws1Powered = ConsumerSubject.create(this.sub.on('cpiomC1Avail'), true); private readonly fws2Powered = ConsumerSubject.create(this.sub.on('cpiomC2Avail'), true); - private readonly bothFwsPowered = MappedSubject.create( - SubscribableMapFunctions.and(), - this.fws1Powered, - this.fws2Powered, - ); + + private readonly fws1Failed = Subject.create(false); + private readonly fws2Failed = Subject.create(false); + + private readonly fwsEcpFailed = Subject.create(false); private readonly fwsAvailable = MappedSubject.create( - ([reset, powered]) => !reset && powered, - this.fwsResetStatus, - this.bothFwsPowered, + ([failed1, failed2]) => !(failed1 && failed2), + this.fws1Failed, + this.fws2Failed, ); - private fwsCore: FwsCore | undefined = new FwsCore(1, this.bus); + private fwsCore: FwsCore | undefined = new FwsCore( + 1, + this.bus, + this.failuresConsumer, + this.fws1Failed, + this.fws2Failed, + ); //FIXME add some deltatime functionality to backplane instruments so we dont have to pass SystemHost private readonly legacyFuel = new LegacyFuel(this.bus, this); @@ -201,10 +204,12 @@ class SystemsHost extends BaseInstrument { if (!a && this.fwsCore !== undefined) { this.fwsCore = undefined; } else if (a && this.fwsCore === undefined) { - this.fwsCore = new FwsCore(1, this.bus); + this.fwsCore = new FwsCore(1, this.bus, this.failuresConsumer, this.fws1Failed, this.fws2Failed); this.fwsCore.init(); } }, true); + + this.fwsEcpFailed.sub((v) => SimVar.SetSimVarValue('L:A32NX_FWS_ECP_FAILED', SimVarValueType.Bool, v), true); } get templateID(): string { @@ -231,6 +236,12 @@ class SystemsHost extends BaseInstrument { true, ); + this.failuresConsumer.register(A380Failure.Fws1); + this.failuresConsumer.register(A380Failure.Fws2); + this.failuresConsumer.register(A380Failure.Fws1AudioFunction); + this.failuresConsumer.register(A380Failure.Fws2AudioFunction); + this.failuresConsumer.register(A380Failure.FwsEcp); + this.backplane.init(); } @@ -238,6 +249,21 @@ class SystemsHost extends BaseInstrument { super.Update(); this.failuresConsumer.update(); + this.fws1Failed.set( + this.failuresConsumer.isActive(A380Failure.Fws1) || this.fws1ResetPbStatus.get() || !this.fws1Powered.get(), + ); + this.fws2Failed.set( + this.failuresConsumer.isActive(A380Failure.Fws2) || this.fws2ResetPbStatus.get() || !this.fws2Powered.get(), + ); + + const ecpReachable = + !SimVar.GetSimVarValue('L:A32NX_AFDX_3_3_REACHABLE', SimVarValueType.Bool) && + !SimVar.GetSimVarValue('L:A32NX_AFDX_13_13_REACHABLE', SimVarValueType.Bool) && + !SimVar.GetSimVarValue('L:A32NX_AFDX_4_4_REACHABLE', SimVarValueType.Bool) && + !SimVar.GetSimVarValue('L:A32NX_AFDX_14_14_REACHABLE', SimVarValueType.Bool); + this.fwsEcpFailed.set( + this.failuresConsumer.isActive(A380Failure.FwsEcp) || !this.dcEssBusPowered.get() || !ecpReachable, + ); if (this.gameState !== 3) { const gamestate = this.getGameState(); diff --git a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsAbnormalSensed.ts b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsAbnormalSensed.ts index a9a15d15654..43cce185df8 100644 --- a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsAbnormalSensed.ts +++ b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsAbnormalSensed.ts @@ -2874,6 +2874,53 @@ export class FwsAbnormalSensed { failure: -1, sysPage: -1, }, + // 31 Display/Recording + 314800006: { + // AUDIO FUNCTION LOST + flightPhaseInhib: [3, 4, 5, 6, 7, 10, 11], + simVarIsActive: this.fws.audioFunctionLost, + whichItemsToShow: () => [true, true, true, true], + whichItemsChecked: () => [true, true, true, true], + notActiveWhenFaults: ['314800004'], + failure: -1, + sysPage: -1, + inopSysApprLdg: () => ['220300026', '320300007', '320300022'], + info: () => ['220200010'], + }, + 314800007: { + // ECP FAULT + flightPhaseInhib: [3, 4, 5, 6, 7, 9, 10], + simVarIsActive: this.fws.fwsEcpFailed, + whichItemsToShow: () => [true, true, true], + whichItemsChecked: () => [true, true, true], + notActiveWhenFaults: [], + failure: 1, + sysPage: -1, + }, + 314800008: { + // FWS 1 FAULT + flightPhaseInhib: [3, 4, 5, 6, 7, 9, 10], + simVarIsActive: this.fws.fws1Failed, + whichItemsToShow: () => [], + whichItemsChecked: () => [], + notActiveWhenFaults: ['314800004'], + failure: 1, + sysPage: -1, + info: () => ['220200005'], + redundLoss: () => ['310300002'], + }, + 314800009: { + // FWS 2 FAULT + flightPhaseInhib: [3, 4, 5, 6, 7, 9, 10], + simVarIsActive: this.fws.fws2Failed, + whichItemsToShow: () => [], + whichItemsChecked: () => [], + notActiveWhenFaults: ['314800004'], + failure: 1, + sysPage: -1, + info: () => ['220200005'], + redundLoss: () => ['310300003'], + }, // 32 Landing Gear & Brakes 320800008: { // BRAKES A_SKID OFF diff --git a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsCore.ts b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsCore.ts index e04b0503b35..ffbcc17720b 100644 --- a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsCore.ts +++ b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsCore.ts @@ -18,6 +18,7 @@ import { GameStateProvider, Wait, SetSubject, + Subscribable, } from '@microsoft/msfs-sdk'; import { @@ -25,6 +26,7 @@ import { Arinc429RegisterSubject, Arinc429SignStatusMatrix, Arinc429Word, + FailuresConsumer, FrequencyMode, NXLogicConfirmNode, NXLogicMemoryNode, @@ -58,6 +60,7 @@ import { MfdSurvEvents } from 'instruments/src/MsfsAvionicsCommon/providers/MfdS import { Mle, Mmo, VfeF1, VfeF1F, VfeF2, VfeF3, VfeFF, Vle, Vmo } from '@shared/PerformanceConstants'; import { FwsAuralVolume, FwsSoundManager } from 'systems-host/systems/FlightWarningSystem/FwsSoundManager'; import { FwcFlightPhase, FwsFlightPhases } from 'systems-host/systems/FlightWarningSystem/FwsFlightPhases'; +import { A380Failure } from '@failures'; export function xor(a: boolean, b: boolean): boolean { return !!((a ? 1 : 0) ^ (b ? 1 : 0)); @@ -93,7 +96,11 @@ export class FwsCore { public readonly startupCompleted = Subject.create(false); - public readonly soundManager = new FwsSoundManager(this.bus, this.startupCompleted); + public readonly audioFunctionLost = Subject.create(false); + + public readonly fwsEcpFailed = Subject.create(false); + + public readonly soundManager = new FwsSoundManager(this.bus, this.startupCompleted, this.audioFunctionLost); private readonly flightPhases = new FwsFlightPhases(this); @@ -1513,6 +1520,9 @@ export class FwsCore { constructor( public readonly fwsNumber: 1 | 2, public readonly bus: EventBus, + private readonly failuresConsumer: FailuresConsumer, + public readonly fws1Failed: Subscribable, + public readonly fws2Failed: Subscribable, ) { this.ewdAbnormal = Object.assign( {}, @@ -1837,7 +1847,7 @@ export class FwsCore { // Acquire discrete inputs at a higher frequency, buffer them until the next FWS cycle. // T.O CONFIG button - if (SimVar.GetSimVarValue('L:A32NX_BTN_TOCONFIG', 'bool')) { + if (SimVar.GetSimVarValue('L:A32NX_BTN_TOCONFIG', 'bool') && !this.failuresConsumer.isActive(A380Failure.FwsEcp)) { this.toConfigInputBuffer.write(true, false); } @@ -1850,7 +1860,7 @@ export class FwsCore { // RCL button const recallButton = SimVar.GetSimVarValue('L:A32NX_BTN_RCL', 'bool'); - if (recallButton) { + if (recallButton && !this.failuresConsumer.isActive(A380Failure.FwsEcp)) { this.recallButtonInputBuffer.write(true, false); } @@ -1885,6 +1895,20 @@ export class FwsCore { // A380X hack: Inject healthy messages for some systems which are not yet implemented this.healthInjector(); + this.audioFunctionLost.set( + this.failuresConsumer.isActive(A380Failure.Fws1AudioFunction) && + this.failuresConsumer.isActive(A380Failure.Fws2AudioFunction), + ); + + const ecpReachable = + !SimVar.GetSimVarValue('L:A32NX_AFDX_3_3_REACHABLE', SimVarValueType.Bool) && + !SimVar.GetSimVarValue('L:A32NX_AFDX_13_13_REACHABLE', SimVarValueType.Bool) && + !SimVar.GetSimVarValue('L:A32NX_AFDX_4_4_REACHABLE', SimVarValueType.Bool) && + !SimVar.GetSimVarValue('L:A32NX_AFDX_14_14_REACHABLE', SimVarValueType.Bool); + this.fwsEcpFailed.set( + this.failuresConsumer.isActive(A380Failure.FwsEcp) || !this.dcESSBusPowered.get() || !ecpReachable, + ); + // Update flight phases this.flightPhases.update(deltaTime); diff --git a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsSoundManager.ts b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsSoundManager.ts index 36696baec36..ffc6f43105d 100644 --- a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsSoundManager.ts +++ b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsSoundManager.ts @@ -282,8 +282,9 @@ export class FwsSoundManager { private currentSoundPlayTimeRemaining = 0; constructor( - private bus: EventBus, - private startupCompleted: Subscribable, + private readonly bus: EventBus, + private readonly startupCompleted: Subscribable, + private readonly audioFunctionLost: Subscribable, ) { // Stop all sounds Object.values(FwsAuralsList).forEach((a) => { @@ -368,7 +369,7 @@ export class FwsSoundManager { /** Find most important sound from soundQueue and play */ private selectAndPlayMostImportantSound(): keyof typeof FwsAuralsList | null { - if (!this.startupCompleted.get()) { + if (!this.startupCompleted.get() || this.audioFunctionLost.get()) { return; } @@ -403,6 +404,13 @@ export class FwsSoundManager { } onUpdate(deltaTime: number) { + if (this.audioFunctionLost.get()) { + while (this.currentSoundPlaying) { + this.stopCurrentSound(); + } + return; + } + // Either wait for the current sound to finish, or schedule the next sound if (this.currentSoundPlaying && this.currentSoundPlayTimeRemaining > 0) { if (this.currentSoundPlayTimeRemaining - deltaTime / 1_000 > 0) { From e5bd05c8bcbad9e8b888aa28bb093fef45c51bd8 Mon Sep 17 00:00:00 2001 From: flogross89 <63071941+flogross89@users.noreply.github.com> Date: Mon, 30 Dec 2024 01:01:24 +0100 Subject: [PATCH 31/40] EWD fallback fixes --- .../model/behaviour/ecam-cp.xml | 2 +- .../Fonts/fbw-a380x/FBW-Display-EIS-A380.ttf | Bin 14324 -> 14568 bytes fbw-a380x/src/fonts/FBW-Display-EIS-A380.sfd | 119 ++++++++++++++---- fbw-a380x/src/fonts/FBW-Display-EIS-A380.ttf | Bin 0 -> 14568 bytes fbw-a380x/src/systems/failures/src/a380.ts | 4 +- .../src/systems/instruments/src/EWD/EWD.tsx | 40 +++--- .../elements/WdAbnormalSensedProcedures.tsx | 4 +- .../elements/WdAbstractChecklistComponent.tsx | 1 + .../systems/instruments/src/EWD/style.scss | 4 + .../AbnormalSensed/ata31-32-33.tsx | 18 +-- .../EcamMessages/ProcedureLinesGenerator.tsx | 15 ++- .../MsfsAvionicsCommon/EcamMessages/index.tsx | 1 + fbw-a380x/src/systems/systems-host/index.ts | 8 +- .../systems/FlightWarningSystem/FwsCore.ts | 4 +- 14 files changed, 153 insertions(+), 67 deletions(-) create mode 100644 fbw-a380x/src/fonts/FBW-Display-EIS-A380.ttf diff --git a/fbw-a380x/src/base/flybywire-aircraft-a380-842/SimObjects/AirPlanes/FlyByWire_A380_842/model/behaviour/ecam-cp.xml b/fbw-a380x/src/base/flybywire-aircraft-a380-842/SimObjects/AirPlanes/FlyByWire_A380_842/model/behaviour/ecam-cp.xml index 008a018058d..c31e700c10e 100644 --- a/fbw-a380x/src/base/flybywire-aircraft-a380-842/SimObjects/AirPlanes/FlyByWire_A380_842/model/behaviour/ecam-cp.xml +++ b/fbw-a380x/src/base/flybywire-aircraft-a380-842/SimObjects/AirPlanes/FlyByWire_A380_842/model/behaviour/ecam-cp.xml @@ -41,7 +41,7 @@ #NODE_ID# - (L:A32NX_FWS_ECP_FAILED, Bool) if{ + (L:A32NX_FWS_ECP_FAILED, Bool) #STATE_ID# 14 != and if{ quit } diff --git a/fbw-a380x/src/base/flybywire-aircraft-a380-842/html_ui/Fonts/fbw-a380x/FBW-Display-EIS-A380.ttf b/fbw-a380x/src/base/flybywire-aircraft-a380-842/html_ui/Fonts/fbw-a380x/FBW-Display-EIS-A380.ttf index 9ae6c7ef0e0beddc625bfeb1fed1c8405ea3a848..6a6e1f2e3f0d7dd471733f06aaab92571827ad2b 100644 GIT binary patch delta 1202 zcmey8|Dw=?fsuiMK@do=FbKH0h4?NwQYOT}V37b6m2r1*bz@LxT+YB?z5&Qra}V$j z-tm9OKcKt;kZ<4~9O|Tf*5m+C{>DTPIVOvmi5Yr+<|}}59O*fgY5Ql*ab;lODq&zy zJd%-`n4%@X+{(bfCUSaKTy`5{2QN=9x;g?Fd)Wg!0t0|PTxPJVLY+1_hP z6Q3yA=~yr@F!dGW7niK=^83ZWpmzdj!9B3cfez6~{TvpAQaV9HEz{tT%mPwF5ieWP!e~3gqD2K3bVVWc|0Asnset$ofwrqcrCyMrlp0(%^4=L1n=}ttjRQDk`Y~ zT?{e=$S^lEHc~VYWZ(8D);cKIimCN)wRMn|rWF_SOh!KGe@}zUf;c|~muhMLd%8JZ PT~&Yul$9rUnCAchi#nDV delta 962 zcmaD+_$A+ifsuiMK@do=FbKH0h4?NI*&)KfV4edMm2r1*bz@LxT+YB?wg<>pa}V$j z-tm9OKcKt~kZ<4~9O|Tf*5m+C{>elSIVSUti5Yr+W?O)A9O*fgY5XkQh71f`B@7G- z7cx>4Q#2FY7Bes~$^hlfGJpaSmfS`_eh84Sl95|d;UOe)9LWE{z`)Fvlb@W}Jimu& z;u9r1Z5IXxroMvw;*!-}e!mzPbguv{xCeGQ(BWKv4)DhF+k9n^7XTW>z;HKAB@RSC zdVZpXf#Lu6%`S`*j7$s+ljE3T*gz5t44V%y@w3+ZF{LpzG0kK8#H_+x!TgRzg{6+= z1FHn<8a5d=Keh(8BWy?5Ie^fKy^j43hZjc&$2N`^oPC`8IA3wua20V);JU!gz#YOp zh5HYW7tb?Z4qi9jI^I)!B7AOqWpLQThXdB5O7II{Kqr1$!g_?^S^NV4>j%P8Bs=Q| vz|Tn5XK5jGu(B8MAK`x?AR&;kxrA#T%jPov0Ex|E8cG5zprk#y#v%s*JcZ^E diff --git a/fbw-a380x/src/fonts/FBW-Display-EIS-A380.sfd b/fbw-a380x/src/fonts/FBW-Display-EIS-A380.sfd index c27a91db8fb..f595b2e7077 100644 --- a/fbw-a380x/src/fonts/FBW-Display-EIS-A380.sfd +++ b/fbw-a380x/src/fonts/FBW-Display-EIS-A380.sfd @@ -22,7 +22,7 @@ OS2Version: 4 OS2_WeightWidthSlopeOnly: 0 OS2_UseTypoMetrics: 1 CreationTime: 1630565342 -ModificationTime: 1723996164 +ModificationTime: 1735513602 PfmFamily: 17 TTFWeight: 400 TTFWidth: 5 @@ -91,7 +91,7 @@ NameList: AGL For New Fonts DisplaySize: -48 AntiAlias: 1 FitToEm: 0 -WinInfo: 0 29 10 +WinInfo: 0 33 11 BeginPrivate: 0 EndPrivate Grid @@ -1568,31 +1568,31 @@ VStem: 905 283<283 2829> LayerCount: 2 Fore SplineSet -120 2970.5 m 128,-1,1 - 120 3029 120 3029 161 3070.5 c 128,-1,2 - 202 3112 202 3112 261 3112 c 2,3,-1 - 1833 3112 l 2,4,5 - 1891 3112 1891 3112 1932.5 3070.5 c 128,-1,6 - 1974 3029 1974 3029 1974 2970.5 c 128,-1,7 - 1974 2912 1974 2912 1933 2870.5 c 128,-1,8 - 1892 2829 1892 2829 1833 2829 c 2,9,-1 - 1188 2829 l 1,10,-1 - 1188 283 l 1,11,-1 - 1833 283 l 2,12,13 - 1891 283 1891 283 1932.5 242 c 128,-1,14 - 1974 201 1974 201 1974 142 c 128,-1,15 - 1974 83 1974 83 1933 42 c 128,-1,16 - 1892 1 1892 1 1833 1 c 2,17,-1 - 261 1 l 2,18,19 - 203 1 203 1 161.5 42 c 128,-1,20 - 120 83 120 83 120 142 c 128,-1,21 - 120 201 120 201 161 242 c 128,-1,22 - 202 283 202 283 261 283 c 2,23,-1 - 905 283 l 1,24,-1 - 905 2829 l 1,25,-1 - 261 2829 l 2,26,27 - 203 2829 203 2829 161.5 2870.5 c 128,-1,0 - 120 2912 120 2912 120 2970.5 c 128,-1,1 +120 2970.5 m 132,-1,1 + 120 3029 120 3029 161 3070.5 c 132,-1,2 + 202 3112 202 3112 261 3112 c 6,3,-1 + 1833 3112 l 6,4,5 + 1891 3112 1891 3112 1932.5 3070.5 c 132,-1,6 + 1974 3029 1974 3029 1974 2970.5 c 132,-1,7 + 1974 2912 1974 2912 1933 2870.5 c 132,-1,8 + 1892 2829 1892 2829 1833 2829 c 6,9,-1 + 1188 2829 l 5,10,-1 + 1188 283 l 5,11,-1 + 1833 283 l 6,12,13 + 1891 283 1891 283 1932.5 242 c 132,-1,14 + 1974 201 1974 201 1974 142 c 132,-1,15 + 1974 83 1974 83 1933 42 c 132,-1,16 + 1892 1 1892 1 1833 1 c 6,17,-1 + 261 1 l 6,18,19 + 203 1 203 1 161.5 42 c 132,-1,20 + 120 83 120 83 120 142 c 132,-1,21 + 120 201 120 201 161 242 c 132,-1,22 + 202 283 202 283 261 283 c 6,23,-1 + 905 283 l 5,24,-1 + 905 2829 l 5,25,-1 + 261 2829 l 6,26,27 + 203 2829 203 2829 161.5 2870.5 c 132,-1,0 + 120 2912 120 2912 120 2970.5 c 132,-1,1 EndSplineSet Validated: 1 EndChar @@ -2913,6 +2913,7 @@ SplineSet 1038 1689 1038 1689 997 1646 c 0,28,29 957 1604 957 1604 897 1604 c 0,15,16 EndSplineSet +Validated: 1 EndChar StartChar: numbersign @@ -2952,6 +2953,7 @@ SplineSet 1038 1689 1038 1689 997 1646 c 4,13,14 957 1604 957 1604 897 1604 c 4,0,1 EndSplineSet +Validated: 1 EndChar StartChar: comma @@ -2960,6 +2962,28 @@ Width: 2568 Flags: W LayerCount: 2 Fore +SplineSet +934 795 m 2,0,1 + 934 860 934 860 980 906 c 128,-1,2 + 1026 952 1026 952 1091 952 c 2,3,-1 + 1405 952 l 2,4,5 + 1470 952 1470 952 1516 906 c 128,-1,6 + 1562 860 1562 860 1562 795 c 2,7,-1 + 1562 480 l 2,8,9 + 1544 461 1544 461 1522 401 c 0,10,11 + 1473 269 1473 269 1473 253 c 1,12,-1 + 1473 185 l 1,13,14 + 1473 15 1473 15 1299 -141 c 0,15,16 + 1299 -141 1299 -141 1127 -293 c 1,17,18 + 1127 -293 1127 -293 887 -89 c 1,19,20 + 967 17 967 17 967 17 c 0,21,22 + 1038 123 1038 123 1043 139 c 2,23,24 + 1080 189 1080 189 1080 253 c 1,25,26 + 1068 327 1068 327 1007 356 c 2,27,28 + 1005 358 1005 358 968 375 c 0,29,30 + 934 390 934 390 934 480 c 2,31,-1 + 934 795 l 2,0,1 +EndSplineSet Validated: 1 EndChar @@ -2994,6 +3018,7 @@ SplineSet 1710 252 1710 252 1702 252 c 0,39,40 1655 252 1655 252 1617 282 c 2,0,1 EndSplineSet +Validated: 1 EndChar StartChar: equal @@ -3087,6 +3112,25 @@ Width: 2568 Flags: W LayerCount: 2 Fore +SplineSet +902 283 m 5,0,-1 + 902 2829 l 5,1,-1 + 902 3112 l 29,2,3 + 1823 3112 1823 3112 1833 3112 c 6,4,5 + 1891 3112 1891 3112 1932 3071 c 4,6,7 + 1974 3029 1974 3029 1974 2970.5 c 132,-1,8 + 1974 2912 1974 2912 1933 2870.5 c 132,-1,9 + 1892 2829 1892 2829 1833 2829 c 6,10,11 + 1833 2829 1833 2829 1188 2829 c 5,12,-1 + 1188 283 l 5,13,-1 + 1833 283 l 6,14,15 + 1891 283 1891 283 1932.5 242 c 132,-1,16 + 1974 201 1974 201 1974 142 c 132,-1,17 + 1974 83 1974 83 1933 41.5 c 132,-1,18 + 1892 0 1892 0 1833 0 c 6,19,20 + 1833 0 1833 0 906 0 c 29,21,-1 + 902 283 l 5,0,-1 +EndSplineSet Validated: 1 EndChar @@ -3105,6 +3149,25 @@ Width: 2568 Flags: W LayerCount: 2 Fore +SplineSet +1974 283 m 1,0,-1 + 1974 0 l 25,1,-1 + 1043 0 l 2,2,3 + 984 0 984 0 943 41.5 c 128,-1,4 + 902 83 902 83 902 142 c 128,-1,5 + 902 201 902 201 943.5 242 c 128,-1,6 + 985 283 985 283 1043 283 c 2,7,8 + 1043 283 1043 283 1688 283 c 1,9,-1 + 1688 2829 l 1,10,-1 + 1043 2829 l 2,11,12 + 984 2829 984 2829 943 2870.5 c 128,-1,13 + 902 2912 902 2912 902 2970.5 c 128,-1,14 + 902 3029 902 3029 944 3071 c 0,15,16 + 985 3112 985 3112 1043 3112 c 2,17,18 + 1053 3112 1053 3112 1974 3112 c 25,19,20 + 1974 3112 1974 3112 1974 2829 c 1,21,-1 + 1974 283 l 1,0,-1 +EndSplineSet Validated: 1 EndChar @@ -3136,6 +3199,7 @@ SplineSet 101 18 101 18 60 59.5 c 128,-1,0 19 101 19 101 19 159.5 c 128,-1,1 EndSplineSet +Validated: 1 EndChar StartChar: grave @@ -5773,6 +5837,7 @@ SplineSet 485 2632 l 1,28,-1 485 332 l 1,25,-1 EndSplineSet +Validated: 1 EndChar EndChars EndSplineFont diff --git a/fbw-a380x/src/fonts/FBW-Display-EIS-A380.ttf b/fbw-a380x/src/fonts/FBW-Display-EIS-A380.ttf new file mode 100644 index 0000000000000000000000000000000000000000..6a6e1f2e3f0d7dd471733f06aaab92571827ad2b GIT binary patch literal 14568 zcmeHu2Y3@#w(vbO>JskQV8BSW+?$H4WDM?L8yj0PrWs>wxq!PZ+Ynl40YYej&{F70 z=&-w#6krn)N+9emNq{9wdRf9IYy!mC((uk54VYy2y|>^0zxTfX|GuZebIaVh=ghgM z-E$8F2qB($6A_Q>Z0qPPr#rj|Nt%MagL5*ovPmesOi1EEY=`8GDYP7WaE!y}I&AB5 zEG6lY7voOh^Q+h%TWEN&%$Q6D>St7+-1K}FA&PcFG^cBA6;%-)>>`|h zFg{PH#f|~VN&~j7*w)rIw0Gq#9dsGn-Gs1;`liZ?i_d&S=WoWgsG*{(8P1Ze_`D0p zs~amCY~LMz`zb=Ak`SL2%}s6XdzKaS5E641!QUX1Hu$H?aweC%r`#n&J+On2zl_yR zrsWsw7tbezyDtAhbrG8~!q8s)(RZ#qa6*fc(uv4_;Af)Mhd&YRfhS2b5%XR2P2fk3 zATfN8NFjq&^r@m+X+-RXxk~ANazUiUHWAAoPDUx#_oGxN^9Tf=QC)CcfELvi{yF^? zBD=+7swRM#Em6n_p%~Kg|Mth+;b&+foy;BPUFJ>FMLO9|{M$tuNGE9}O{5Eqh903caXpF{axe;ofG@*eA~`0#x=!1;>|<;&u_>> zzx=_qU$+0dTB5T5u9^RL-v46?tRw4?pH9Fyeg-N*^lz{rsgtlpC1x<{#SvJlcWJX`1+;m$AlU9$9R)43R(~he+UU6Ly4MbNFWI!S`th`NGJ&-;Ut1Yk|+|5 z`XZL-h@KdTk;IXBl0Xtk5=kZ|VkRkM7)d3=@f*@eI>{iJB#UH|95RxOBDo}w2l73+P5w@PB6rCha*uSApNWI?5+^~cLk^Q2WG8tQYsbiEamAE z-qzuo{nuQRaCIh;Hy{_PVJ)0y)Jy?0kJ-TdmiYs#Wyi9+MQYJl(Lr&bI9Gf_QXrWp zIV`y+xhFN@)h<0KbCb=Iy(ars?k_(jzpWUoXjJS_yrpE62IXSqyQ&z~tbPOfnfi70 zJJ`?RmhIN%_KMpDyl%VQc9;B%*E08CUvIeo&s<-+|L^tx7zI51JyJcUdaUvI9G#aX z=_&|!B{7G9#HJjUipbv#ha}>UQx3BXR>>ijcB8BKH^X761RN=cf%Y3cHJ-s5 zPt6ihnj?qRJ1!}9-yOR|z6phlVeUvWB@wD=s8ffa1P6wO#Cygi7<~JC`bZ_3UpB=r z6nljicNB+*IbV5LlVnCr5s6jiqGD6eo#e=fU$#(pHxZCMsR~Dp?T6afh#HoVz!)Yj zl`#Y`K5n2jB*cXTN_gqnXMQYb-dGz5tHd$4XGl><^rf`zXegoJ`S zNTiaWz!*_HeqCZhVrU2xALj+BkeCo37sCVvO5LEpkMB_M#&P|90vMwqF=05sj0zaA zfAX=d%PJGU&V6kLGaaJBJ1h{+y$fj}vT^O9+=ZpErhVbA&KpP9*CuN-3XHWUKCGWR zkx8}hPTQW-wQJIcGZM{~G4RIWNn7%lU7lAts-X2*rNKTwwq*ADZew!CwmUPR|LT?C>0l~f%>Vt1mi3Kk ztJ4opwH%oM&L`H_{BB9r!9@ky(1x`HDDQ~ec;5Ln=de%ydklgkWZos~#BV8|LyjO? z2@;O-Tq4qmvVg?T)5i~d#k*`RL%FeOX|Ow>)iyYQD;Wp_U{AmwQwAHDckAb}FsGh5 zYZx-D#pp~9*Et^O!ks1q&iy7?D?YAVN9QI9zBm)*KTX7m}|Dy0N9*qKg%&B)K8HS{^8kn=;Iu>-{%)7X0LflCg%$AkNCm=r%(0Nh@ z!09!3mjr15?}4GB2ly z++pEX&_~ebyh9%`N^IjJXti_{%Pu{M z2jP5l{$d{QPR1rVFFTI@5ye|TSin?3(S=(KJ62_p&cEZt&L4SL zZU`R7SuAvJwv)Rq@n?^r*F}JSD^(xJ;zPhks*~zM6Z8ov0U@Dy#k0F6rGY7Jl9#W3 z|K8hUa>T)^VN7r!J1A|^q%`gw@05ienY*9gaADds55tJuA&jT{1Q*>q*=FhQL{Fm! zNW5GyD8&OiEhdSUB6bZQRQ@{=&V|R$Eh}2x{c6ZFdxJ=dL!~yx9O@+u8lw zA++)4s9h(FQ|1*t$1OhRC_c+AT(|4QiJi~E6X)3dXW&!z zlX?n*k_zn4g9kJG3Y&Y*x|o2Qs%UZvyuC#H&wYWnFOa_9p}jSWh^DBgn-2yND?ewD4mRjNS=W20+U zZn=oj2X5(7=Xr+ylL%CheI{LS5p5izRV_L#NX;wCTO^QX4fb6aP}MoxeBl`EZ#zd8JrF?zV# zEi!gc=A^FdxaNeQxb4;;OQl}sXe;502c%8Jnk<*CQ?P=x(DFb z20;IZi_oV7;&~;^dV=_agggjD&0*$l;7q;mnTrRC-sqp(>Uc{PCN4_suEt*HtGp&C zwV0xUWdYidpFb3@>}lcGzXR!dR252fq<5dJB0!N}0PBHNMb=lNIzVHe3P@C6qd|*u z;(=14MVStX@0yk;-cRB89D{F{`_QnsF4@E<8ZVZO+9Q_029wZ0kD>Itxs^jnCSN4sIjLWkQX0}J2D3*T>cUo=FOV9 zdf5VQD_75LU9fD`y2Wpn_Ciu`>6hIn0BpJ8DliIe$k}wqdi1E3#+pzr zAKaITQ7(NS>CnfG<1jQ;U8qj;@}|Yze^t{~;j599vOR;$$_gq&+@(qR_jc%f)6rj= zBoeD9AP`fec-yj`OCQ<=~0=%)sq9Cy-Na)dpKJtyIOre`3qP`TB zGl__&FC`)`Un%%HRSKe$9Cv-4b$a>uKkWF!`0{C%bxVdNjG0%H6p}urF>U0I=agXeHAffseys^JuRi+qyxKR`FSLcnWN1A-wHYztwuS58 zsGaxq(beWKjjx}fbIrlYt(SK%FE<*?m+$^lTls-CorVGX@^X)JzvbT8oN6`=-wbIC z!vF(0$0&1A+dyS69AggYgalLO59WCaxrOI34Q2m<@W>#ULr#;s%aIZ@fU?j4Y zb2sMq;c8eI)eg z@j{)5tAu+Jqk(FJ{GeRcyRJge*Jf$-6sgM}CJUJLGYjn>!abmO- z0< zMi@h4-PqM$=5&+ZZIB}R-hI`2T~f4ICIw(bqL}0ur6JkRUo#|<`l$>V{lJ0yMGBLL zsPWdZ8r*B4sqm)Dz{5iNd($nKsK&WjbZ&h{&#DaZ1bd#i5R_~}|D+KqQQmBVf+>*X z*(WHXdkP#9=2NHIl&6?zVki6iNw-sg17o`<3>fIxVVKSy)l|AcoQN&;_c}{)g|>6(3|9)Y@N%??zE(^9=Blj zLOd4X9xUP(eCN1rw!$E0A&fsVxw?At5$CbM57q&U-~ipZttN3g*YHkX*}z}Fo9;SnZt zF`YdkGT9Un-n&jHr8vN9;$aY(4tW|~K-}~BAX@|o?iST)!bQ!#OO2qKM#vPXaAAl; z!aHin=B^9*=iz&_G#ZR*aH)ilP@)M8q8GaH=*SOdKp_hon%%bM+qqXuibsqvq((-0 zcshsJRCSzpj*e{nYe~~+L?X?=sfC0*W5($8}Ph@n4DJy5<__n5* zA`xR@d_%DH z2oFo4)QU{zI`fMr6pbw(ZyleL-5e0GwBu@4@tDjpX(P;$!`S0fYp1t%Of4Ca9v?Sk zu=B}ilQ|fnMKgoA=}*q*Z3B`}79sEg-QQ~X-7->(-|OR2@g-7cg~=kmgG-J7dQ^Ce z2v>z$%)K&EH)W7Jcj#SozgJ32r3$gb>2a;lKbIasUkdkSkL_>!c#K+6Pjt|V%@VE2 zQfziU!7QTX{g3ILS?HW)QcmHa-g86u7yrqBr1R4F+ijdT0iitRi~G2VF;a!w8rS98 z+)zv7r7_@k3?Yg36`R>GiY3<*GP?e`{nt9`-&wb)ENryiT`6Xj8EsRPAd;)XFv=J) z@#Xn-S;5?W#DT)LbXS)g+V|q(%A`1JXGg~TO}gj-9;PY%(@k=ZpwK6(xyy!e?Tc4r zNofoc$ZHRrvOP#!dPYrY>x!xfVKv+?^0XZYaiC}}6nBR;7l!r*ioOVzSet`;!?>>s zo5!fa3zK?k@L6GVSZ`p@?1<)EX@s~FHKjADurNtvmVAnv5rNLUOyj|{7r&0K&<#qN zXWV;s3yLiU6R6nIRlEBnE}+${RGRsBJCK%6&Y8+hmQgZjS!TN zFWNQCHRjLixK!g{cMqJ(d3tD7)llbYtb)QlNTv7DJEUxHl+rEOXUNbX7jww1j?bgi z>L@ng-d>(b3JSO&(Rf3>hFnKoNiJDI(dd1nlxd6coo86w3(q{ znO;3@6rRe@KP3F#ez}s)dB+)=6BZsMAAJv_OvPrU0uQw@RE##>kN4-J5uAka^zicY zQhO(OdGcE`wFn~^=$3lnHpqi+jn(MUhu|pYO!<^)RcD#AXRD@7DWA-J!*$``zWK13 z3587yzMMHLZReTqx$f`J>`0$AQ+{eE7sy@V{=#Wq;SNFJEAR;fK{(vlx#QJW{l4h# z#=wVj9LsVioLBzPxOY}Y#;kn}mzYTOs`t`0blC)|I|oot&83-Lmf8(Xf{XsZv$4w} zYp6}Qc?NRY8(UKwx19LA!?6|R1N_`%u@C-Mgs-6%mjt?rkOKlRypgCwKLvNRkbuk-!vd;XH;Co^ z`WP`ay<&BM7{@ZAxBh&3(-Xy!kwvpMoo)c}F)k(oXzcFj#3<}yaT%Dt6+PTB)>Qi>W`Ea`xW5z|VeZn4? zb{6}7mVC)~UFw*hZr^(Hqfc7c1I?d&baJab-PLY(6m8{BBR#wL7vlU}D%$<%T&d&Yw zO2-!Jz;&Ht)%9axEsQl@(R`$^v@U(KE>?c(ao}dy442k8v za;=89Q2o)OiO>Y05u&CI-5!2Vj^`G*DQ9`j7LO{=z&p^qPlWp{>ZehihtV6JdtLss z2F(~9(cecRs|ii>8Wa#Txt_bpUA}f?!5C}(IMAPBMXU(apIHj?=T99Ryr8rFg`c>O zx!#MtE8^6?QYbdX7fQwM14FC#t~zxRhSe2W{RW$-a@+s1=;!x#r50G1wjH~Ne7+uR zPd4R-c@@j-p_<6(=oyoLgxb8O_O_F2x>l5`V`Dlul(x*-#$9h~&25GHh2UM)m>Vxw zn2NKFLB^8&(-TK`))c;3U7T&nXlhTiEwxMo^325(TkD?T&bO>AAE^#D6}#*SulK!C zS3R!xUFM2z^re%js&m|+!IB$hm*OtIJCAlM<{@9Z{7SlSMJeNTC1rBnItV93j2k0T zYhxH1!aQ%c=*Q1qe{gcyf%S97>v8eZI`@CTJwPHlFYoV6qw2JKd&kuSD=XsTD^?!3 z+955YOWwVGE%)sYXPzl2c;?IxFkmhA@~~;FVuDIXbzLxesJQMdAA<9igE#NhvbY;^ z15rWfFqPxBh%HcLwM~(aW|lBZMk~tOGUbJg$Z^|aA|s6pk?Z=o!w05vpR8og*j+2# z02fV}KIJAZLZ!NQQBOnp#Evphg7L9%Z0P9Wjs(5pP&tBd)dc9M^ZAgK3kg~A3!v46 zMrl(#ov%5Mdz!V;p&Bhb&yKc_V;8_>??BCHO^_FSuz)SK7bw@>xgR{j+fT%X4Q0P} z_zw+ZMSk8Rf|XKJskFd+?>wss^6>^ApCHF4@&r?%wDi#$gkk1_YYosGK0Kd81NqSO zJT#K%p5d<0wH(YIW-l&-*6GIlsKtuY>MWsc=0~TSRuyJ3ad#cf>?%;w73VIe=p5b- zZ(R!aC)&oH)G9|acbBinr0CecvA1-1euRtjkT1fhU(EBxV>sy^TA^QK;rI?=JHB%P zzT;?NR|0?b!Tl*k*ZXA;Z+69{qQSZph@t+m9b-$|R1uidfzh}CJXr(b%tC^~i#tKr znT56@hH6FyD0EoGDQO-Q z?{D?T#z0Wh?L7u4bkzNJRoKPsMujOnqR-WGRKOtlk1!}a!fv5X)<4XHUK5Q7(@C&G z-D8c;Q+mWvMsZ;lIiD~WM}(Uc>_!;GeT63|@*gesh;Z&JN>gv*CI11U>A6EfpS%Wo zTTHUI=<7eHnr*J*4ZxfcA{{K7iCHH|8$4G)#YJ5Yy!dS#AA{pJfmA8d02``H4UIYR z)(JH@t zX2hUxP)FPQ+%w$!+?BPHBE@6uks0kbZ-W1##N=G7ab-=#5O0-sYU`mi<5+8QkX?Fn z)g@akf9P0P_(EAon{`-uguiak0GWtU3zVxvEs1Q;q!!X z1NDOjNX4vdK)^5@XDOrOP)A_g3D3j}q-FnFOz7W_J4sIQaiD)1cM_G!ZpnsW4j?_h zMqB?+POc?~&mUV@Sh(=m`D2R;3Knrs9bd5E_yXCj!bL~1r?7C*vGYe4y@g#1j$@o* z-2sgf> z|6wNA*+CTgh5S6iPWTb7fLkGS1SHRytyc5>X}H(+7td90#654you6r+V)i|E`QIr% zC-B>KDAQgv0*xWH1bRG+$EWnrl={nZRweHTrO1JW)mY0g4I%DhL>O#Y5q77rWsw{I>hT#hOKxcMoJWB1=WiYwxV*;E+d<9|Mgp{ou^*K(oGU|!p5p^nKMn7-i}BO*R9NvMm7 zJ3JgC!G0Qv$Bh`yigsG41IDq23v~vm(InJa%uU-S)I}r=3_@LuXPqrVU4s2vG25XI zv)62xt48ltIENkUG@Gpz>p7VJmXG@pBO&>9mA1x8Tb0`0SY>Nf=Zwkkz}{>Ob(iA6 zOq`|-lilhu9c~7u-eqALodqAKm#Q=C+M4StW<+O=!j6AFE*g{YjCdr2Zs}vAqtlEA z?8(NjYD8T~%U1LcZ3xbQxqUh;P5Ad8qo95?wQIBykxRxu3d}&yaI>2l+q0WmYiw#m zj81J*{|aR_MFP8x(aF&Uoq@jaAAWKlykCDjKNBW{^Q3J3Z3Y*2#+dFub;3{D6{k6jDF5Q1_Y zhC&|!kq`yZxXp{j69QC6V8pOQJS1S+QW7Mi=`=$M48u*}a2Nq;kPaD`L%EPF!raN{ zFsE`cSwWsAFJMOI4#*_SFb8u1c^0xDn><6-V~*F`)`WDi5Fx+(zy35oT3>i05(N;eLK8=A71H)@cI@ zU?bUrtkr_TNb^qZC^svrlhfX6b7%5=LRZWFF+h zXqr=s$C-sN28zf73}6=HX|olxK1*OMl)^X|4-;S_OoB3)jOR{MFcNk} zuo<3*7vM#B3AVsi*aq8S2keAh@G`stuflHF1A9@e?pP3uS^(CJJSeP$mmynoy<-Wrk2@3T2j1X1hwg0ADY_*9-9V0(`vy zUoXJd3-I*fS)YDPZr>(3GmZ|=jj6cbOC;PvNWxsqO!HAQCi_DC23Pz zZ5=jA1z$+hnrfOFZPTR{u2Pv%S=U-=Z>X-fbtxWYl2ruK?TG^_23%12d6W@QCV zEva%9nFyz%U795Tv5K-3j)fG99 zCQ#scmVh76pn8Lg5PE}AIkN8!Wo=(wG;(T1tEd)ll2Pq-^;I@W9bZUC3Ha9u_>Xeo zU*{s&C;`(tSILaZW$LCWbNl91PV1|?a51_TU2jZOO|NOS*&6FB8msCmCHWPV_I8`3 zo-c%+V-0I-tdSN9pVuUOUZLyrn)sq$VXeKfrlQr}P+wth@7MHrOH%BD-1->gc;VCH z6D7qi$gQrz;u_n=7fMSXNtA7Ub=Nm12uqbMYUf$XjYDiOZG zE_^|W>kI6BAuegHYpfC5>AhdcyTx)Fl~dFz6C_xiiG4@$zYi&q$Qdw6!+H&>Qd20REp7mj|uFwlDg`v;{B^ z?;`A>9uNqBu9^Z}tyIEfX6IXpTYW`)BgP--NP;ubk&oAbha(f-r!%_dl3^)<0=xry zk`L#NLRaqbc?Ue2t8Z2u%>U>- - + visible && avail, + this.normalChecklistsVisible, + this.availChecker.fwsAvail, + )} + abnormal={false} + /> visible || !avail, + ([visible, fail]) => visible || fail, this.abnormalSensedVisible, - this.availChecker.fwsAvail, + this.availChecker.fwsFailed, )} abnormal={true} fwsAvail={this.availChecker.fwsAvail} /> visible && avail, + this.abnormalNonSensedVisible, + this.availChecker.fwsAvail, + )} abnormal={true} />
@@ -288,27 +301,22 @@ class FwsEwdAvailabilityChecker { private readonly fws1IsHealthy = ConsumerSubject.create(this.sub.on('fws1_is_healthy'), true); private readonly fws2IsHealthy = ConsumerSubject.create(this.sub.on('fws2_is_healthy'), true); - private readonly fwsIsHealthy = MappedSubject.create( - SubscribableMapFunctions.and(), - this.fws1IsHealthy, - this.fws2IsHealthy, - ); private readonly afdx_3_3_reachable = ConsumerSubject.create(this.sub.on('afdx_3_3_reachable'), true); private readonly afdx_13_13_reachable = ConsumerSubject.create(this.sub.on('afdx_13_13_reachable'), true); private readonly afdx_4_3_reachable = ConsumerSubject.create(this.sub.on('afdx_4_3_reachable'), true); private readonly afdx_14_13_reachable = ConsumerSubject.create(this.sub.on('afdx_14_13_reachable'), true); - private readonly fwsEwdReachable = MappedSubject.create( - ([r_3_3, r_13_13, r_4_3, r_14_13]) => (r_3_3 && r_4_3) || (r_13_13 && r_14_13), + + public readonly fwsAvail = MappedSubject.create( + ([healthy1, healthy2, r_3_3, r_13_13, r_4_3, r_14_13]) => + (healthy1 && r_3_3 && r_13_13) || (healthy2 && r_4_3 && r_14_13), + this.fws1IsHealthy, + this.fws2IsHealthy, this.afdx_3_3_reachable, this.afdx_13_13_reachable, this.afdx_4_3_reachable, this.afdx_14_13_reachable, ); - public readonly fwsAvail = MappedSubject.create( - SubscribableMapFunctions.and(), - this.fwsIsHealthy, - this.fwsEwdReachable, - ); + public readonly fwsFailed = this.fwsAvail.map((it) => !it); } diff --git a/fbw-a380x/src/systems/instruments/src/EWD/elements/WdAbnormalSensedProcedures.tsx b/fbw-a380x/src/systems/instruments/src/EWD/elements/WdAbnormalSensedProcedures.tsx index a5df2a61142..0e06e7a9f6c 100644 --- a/fbw-a380x/src/systems/instruments/src/EWD/elements/WdAbnormalSensedProcedures.tsx +++ b/fbw-a380x/src/systems/instruments/src/EWD/elements/WdAbnormalSensedProcedures.tsx @@ -38,13 +38,13 @@ export class WdAbnormalSensedProcedures extends WdAbstractChecklistComponent { procedureActivated: true, procedureCompleted: false, itemsActive: [true, true, true, true, true, true, true, true, true], - itemsChecked: [true, true, true, true, true, true, true, true, true], + itemsChecked: [false, false, true, true, true, true, true, true, true], itemsToShow: [true, true, true, true, true, true, true, true, true], }; const procGenFallback = new ProcedureLinesGenerator( '314800004', Subject.create(false), - ProcedureType.Abnormal, + ProcedureType.FwsFailedFallback, fallbackClState, ); this.lineData.push(...procGenFallback.toLineData()); diff --git a/fbw-a380x/src/systems/instruments/src/EWD/elements/WdAbstractChecklistComponent.tsx b/fbw-a380x/src/systems/instruments/src/EWD/elements/WdAbstractChecklistComponent.tsx index f993d5b2d1a..8fee44664e7 100644 --- a/fbw-a380x/src/systems/instruments/src/EWD/elements/WdAbstractChecklistComponent.tsx +++ b/fbw-a380x/src/systems/instruments/src/EWD/elements/WdAbstractChecklistComponent.tsx @@ -157,6 +157,7 @@ export class EclLine extends DisplayComponent { Green: this.props.data.map((d) => d.style === ChecklistLineStyle.Green), Cyan: this.props.data.map((d) => d.style === ChecklistLineStyle.Cyan), Amber: this.props.data.map((d) => d.style === ChecklistLineStyle.Amber), + White: this.props.data.map((d) => d.style === ChecklistLineStyle.White), OmissionDots: this.props.data.map((d) => d.style === ChecklistLineStyle.OmissionDots), LandAnsa: this.props.data.map((d) => d.style === ChecklistLineStyle.LandAnsa), LandAsap: this.props.data.map((d) => d.style === ChecklistLineStyle.LandAsap), diff --git a/fbw-a380x/src/systems/instruments/src/EWD/style.scss b/fbw-a380x/src/systems/instruments/src/EWD/style.scss index 18dd7f81d58..4129f4a6b12 100644 --- a/fbw-a380x/src/systems/instruments/src/EWD/style.scss +++ b/fbw-a380x/src/systems/instruments/src/EWD/style.scss @@ -454,6 +454,10 @@ text, tspan, span { color: $display-amber !important; } +.EclLine.White { + color: $display-white !important; +} + .EclLine.Selected { border: 3px solid $display-cyan; border-right: 3px solid transparent; diff --git a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata31-32-33.tsx b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata31-32-33.tsx index 5e082d31cd1..7caa7c507bd 100644 --- a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata31-32-33.tsx +++ b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/AbnormalSensed/ata31-32-33.tsx @@ -151,44 +151,44 @@ export const EcamAbnormalSensedAta313233: { [n: number]: AbnormalProcedure } = { { name: 'FUNCTIONS NOT AVAIL:', sensed: true, - style: ChecklistLineStyle.SubHeadline, - level: 1, + style: ChecklistLineStyle.White, + level: 2, }, { name: 'ECAM WARNINGS & CAUTIONS', sensed: true, style: ChecklistLineStyle.Amber, - level: 1, + level: 2, }, { name: 'ABN PROCEDURES', sensed: true, style: ChecklistLineStyle.Amber, - level: 1, + level: 2, }, { name: 'LIMITATIONS & STATUS', sensed: true, style: ChecklistLineStyle.Amber, - level: 1, + level: 2, }, { name: 'ALTITUDE ALERT', sensed: true, style: ChecklistLineStyle.Amber, - level: 1, + level: 2, }, { name: 'AUTO CALLOUT', sensed: true, style: ChecklistLineStyle.Amber, - level: 1, + level: 2, }, { name: 'NORM C/L & MEMO', sensed: true, style: ChecklistLineStyle.Amber, - level: 1, + level: 2, }, ], }, @@ -203,7 +203,7 @@ export const EcamAbnormalSensedAta313233: { [n: number]: AbnormalProcedure } = { items: [ { name: 'AUDIOS NOT AVAIL:', - style: ChecklistLineStyle.CompletedChecklist, + style: ChecklistLineStyle.White, sensed: true, }, { diff --git a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/ProcedureLinesGenerator.tsx b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/ProcedureLinesGenerator.tsx index 8ec7b635477..c169e81c4ba 100644 --- a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/ProcedureLinesGenerator.tsx +++ b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/ProcedureLinesGenerator.tsx @@ -23,6 +23,7 @@ export enum ProcedureType { Normal, Abnormal, Deferred, + FwsFailedFallback, } export interface ProcedureItemInfo { @@ -63,6 +64,8 @@ export class ProcedureLinesGenerator { this.procedure = EcamAbnormalProcedures[procedureId]; } else if (type === ProcedureType.Deferred) { this.procedure = EcamDeferredProcedures[procedureId]; + } else if (type === ProcedureType.FwsFailedFallback) { + this.procedure = EcamAbnormalProcedures[procedureId]; } this.items = this.procedure.items; } @@ -75,6 +78,7 @@ export class ProcedureLinesGenerator { ChecklistLineStyle.Amber, ChecklistLineStyle.Cyan, ChecklistLineStyle.Green, + ChecklistLineStyle.White, ]; static conditionalActiveItems( @@ -334,7 +338,10 @@ export class ProcedureLinesGenerator { public toLineData(): WdLineData[] { const lineData: WdLineData[] = []; - const isAbnormalOrDeferred = this.type === ProcedureType.Abnormal || this.type === ProcedureType.Deferred; + const isAbnormalOrDeferred = + this.type === ProcedureType.Abnormal || + this.type === ProcedureType.Deferred || + this.type === ProcedureType.FwsFailedFallback; const isAbnormal = this.type === ProcedureType.Abnormal; const isDeferred = this.type === ProcedureType.Deferred; @@ -439,8 +446,8 @@ export class ProcedureLinesGenerator { checked: this.checklistState.itemsChecked[itemIndex], text: text.substring(0, 39), style: clStyle, - firstLine: !this.procedureIsActive.get() && isAbnormal, - lastLine: !this.procedureIsActive.get() && isAbnormal, + firstLine: (!this.procedureIsActive.get() && isAbnormal) || this.type === ProcedureType.FwsFailedFallback, + lastLine: (!this.procedureIsActive.get() && isAbnormal) || this.type === ProcedureType.FwsFailedFallback, originalItemIndex: isChecklistCondition(item) ? undefined : itemIndex, }); @@ -522,7 +529,7 @@ export class ProcedureLinesGenerator { }); } } - } else if (this.items.length > 0) { + } else if (this.items.length > 0 && this.type !== ProcedureType.FwsFailedFallback) { // Only three dots for following procedures lineData.push({ abnormalProcedure: isAbnormalOrDeferred, diff --git a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/index.tsx b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/index.tsx index d167ead6e71..8e8eb797a6b 100644 --- a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/index.tsx +++ b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/index.tsx @@ -582,6 +582,7 @@ export enum ChecklistLineStyle { Cyan = 'Cyan', Green = 'Green', Amber = 'Amber', + White = 'White', Headline = 'Headline', SubHeadline = 'SubHeadline', SeparationLine = 'SeparationLine', diff --git a/fbw-a380x/src/systems/systems-host/index.ts b/fbw-a380x/src/systems/systems-host/index.ts index 6411acb644e..1e577b34f48 100644 --- a/fbw-a380x/src/systems/systems-host/index.ts +++ b/fbw-a380x/src/systems/systems-host/index.ts @@ -199,8 +199,6 @@ class SystemsHost extends BaseInstrument { }); this.fwsAvailable.sub((a) => { - SimVar.SetSimVarValue('L:A32NX_FWS1_IS_HEALTHY', SimVarValueType.Bool, a); - SimVar.SetSimVarValue('L:A32NX_FWS2_IS_HEALTHY', SimVarValueType.Bool, a); if (!a && this.fwsCore !== undefined) { this.fwsCore = undefined; } else if (a && this.fwsCore === undefined) { @@ -208,6 +206,8 @@ class SystemsHost extends BaseInstrument { this.fwsCore.init(); } }, true); + this.fws1Failed.sub((f) => SimVar.SetSimVarValue('L:A32NX_FWS1_IS_HEALTHY', SimVarValueType.Bool, !f)); + this.fws2Failed.sub((f) => SimVar.SetSimVarValue('L:A32NX_FWS2_IS_HEALTHY', SimVarValueType.Bool, !f)); this.fwsEcpFailed.sub((v) => SimVar.SetSimVarValue('L:A32NX_FWS_ECP_FAILED', SimVarValueType.Bool, v), true); } @@ -256,13 +256,13 @@ class SystemsHost extends BaseInstrument { this.failuresConsumer.isActive(A380Failure.Fws2) || this.fws2ResetPbStatus.get() || !this.fws2Powered.get(), ); - const ecpReachable = + const ecpNotReachable = !SimVar.GetSimVarValue('L:A32NX_AFDX_3_3_REACHABLE', SimVarValueType.Bool) && !SimVar.GetSimVarValue('L:A32NX_AFDX_13_13_REACHABLE', SimVarValueType.Bool) && !SimVar.GetSimVarValue('L:A32NX_AFDX_4_4_REACHABLE', SimVarValueType.Bool) && !SimVar.GetSimVarValue('L:A32NX_AFDX_14_14_REACHABLE', SimVarValueType.Bool); this.fwsEcpFailed.set( - this.failuresConsumer.isActive(A380Failure.FwsEcp) || !this.dcEssBusPowered.get() || !ecpReachable, + this.failuresConsumer.isActive(A380Failure.FwsEcp) || !this.dcEssBusPowered.get() || ecpNotReachable, ); if (this.gameState !== 3) { diff --git a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsCore.ts b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsCore.ts index ffbcc17720b..2097cc1d7bc 100644 --- a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsCore.ts +++ b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsCore.ts @@ -1900,13 +1900,13 @@ export class FwsCore { this.failuresConsumer.isActive(A380Failure.Fws2AudioFunction), ); - const ecpReachable = + const ecpNotReachable = !SimVar.GetSimVarValue('L:A32NX_AFDX_3_3_REACHABLE', SimVarValueType.Bool) && !SimVar.GetSimVarValue('L:A32NX_AFDX_13_13_REACHABLE', SimVarValueType.Bool) && !SimVar.GetSimVarValue('L:A32NX_AFDX_4_4_REACHABLE', SimVarValueType.Bool) && !SimVar.GetSimVarValue('L:A32NX_AFDX_14_14_REACHABLE', SimVarValueType.Bool); this.fwsEcpFailed.set( - this.failuresConsumer.isActive(A380Failure.FwsEcp) || !this.dcESSBusPowered.get() || !ecpReachable, + this.failuresConsumer.isActive(A380Failure.FwsEcp) || !this.dcESSBusPowered.get() || ecpNotReachable, ); // Update flight phases From 24954d32db2445a7a9a3d5ef5d93806237ed48e9 Mon Sep 17 00:00:00 2001 From: flogross89 <63071941+flogross89@users.noreply.github.com> Date: Mon, 30 Dec 2024 01:41:09 +0100 Subject: [PATCH 32/40] communication fixes --- .../src/systems/instruments/src/EWD/EWD.tsx | 2 +- .../systems/instruments/src/PFD/LowerArea.tsx | 30 ++++++++----------- 2 files changed, 13 insertions(+), 19 deletions(-) diff --git a/fbw-a380x/src/systems/instruments/src/EWD/EWD.tsx b/fbw-a380x/src/systems/instruments/src/EWD/EWD.tsx index 1cd052d0571..4f9f82d52c8 100644 --- a/fbw-a380x/src/systems/instruments/src/EWD/EWD.tsx +++ b/fbw-a380x/src/systems/instruments/src/EWD/EWD.tsx @@ -309,7 +309,7 @@ class FwsEwdAvailabilityChecker { public readonly fwsAvail = MappedSubject.create( ([healthy1, healthy2, r_3_3, r_13_13, r_4_3, r_14_13]) => - (healthy1 && r_3_3 && r_13_13) || (healthy2 && r_4_3 && r_14_13), + (healthy1 && (r_3_3 || r_13_13)) || (healthy2 && (r_4_3 || r_14_13)), this.fws1IsHealthy, this.fws2IsHealthy, this.afdx_3_3_reachable, diff --git a/fbw-a380x/src/systems/instruments/src/PFD/LowerArea.tsx b/fbw-a380x/src/systems/instruments/src/PFD/LowerArea.tsx index 24ea70f3fef..347dd14d502 100644 --- a/fbw-a380x/src/systems/instruments/src/PFD/LowerArea.tsx +++ b/fbw-a380x/src/systems/instruments/src/PFD/LowerArea.tsx @@ -9,7 +9,6 @@ import { MappedSubject, Subject, Subscribable, - SubscribableMapFunctions, VNode, } from '@microsoft/msfs-sdk'; import { @@ -690,13 +689,13 @@ class Limitations extends DisplayComponent<{ bus: ArincEventBus; visible: Subscr render(): VNode { return ( - (it ? 'visible' : 'hidden'))}> - (it ? 'visible' : 'hidden'))}> + (it ? 'inherit' : 'hidden'))}> + (it ? 'inherit' : 'hidden'))}> {this.limitationsLine.map((line, index) => ( ))} - (it ? 'hidden' : 'visible'))}> + (it ? 'hidden' : 'inherit'))}> @@ -725,12 +724,12 @@ class Memos extends DisplayComponent<{ bus: ArincEventBus }> { render(): VNode { return ( <> - (it ? 'visible' : 'hidden'))}> + (it ? 'inherit' : 'hidden'))}> - (it ? 'hidden' : 'visible'))}> + (it ? 'hidden' : 'inherit'))}> @@ -743,27 +742,22 @@ class FwsPfdAvailabilityChecker { private readonly fws1IsHealthy = ConsumerSubject.create(this.sub.on('fws1_is_healthy'), true); private readonly fws2IsHealthy = ConsumerSubject.create(this.sub.on('fws2_is_healthy'), true); - private readonly fwsIsHealthy = MappedSubject.create( - SubscribableMapFunctions.and(), - this.fws1IsHealthy, - this.fws2IsHealthy, - ); private readonly afdx_3_1_reachable = ConsumerSubject.create(this.sub.on('afdx_3_1_reachable'), true); private readonly afdx_13_11_reachable = ConsumerSubject.create(this.sub.on('afdx_13_11_reachable'), true); private readonly afdx_4_2_reachable = ConsumerSubject.create(this.sub.on('afdx_4_2_reachable'), true); private readonly afdx_14_12_reachable = ConsumerSubject.create(this.sub.on('afdx_14_12_reachable'), true); - private readonly fwsPfdReachable = MappedSubject.create( - ([r_3_1, r_13_11, r_4_2, r_14_12]) => (r_3_1 && r_4_2) || (r_13_11 && r_14_12), + + public readonly fwsAvail = MappedSubject.create( + ([healthy1, healthy2, r_3_1, r_13_11, r_4_2, r_14_12]) => + (healthy1 && (r_3_1 || r_13_11)) || (healthy2 && (r_4_2 || r_14_12)), + this.fws1IsHealthy, + this.fws2IsHealthy, this.afdx_3_1_reachable, this.afdx_13_11_reachable, this.afdx_4_2_reachable, this.afdx_14_12_reachable, ); - public readonly fwsAvail = MappedSubject.create( - SubscribableMapFunctions.and(), - this.fwsIsHealthy, - this.fwsPfdReachable, - ); + public readonly fwsFailed = this.fwsAvail.map((it) => !it); } From 0e0401dae1f8c19af7d0d0f6c9843458cc7a5934 Mon Sep 17 00:00:00 2001 From: flogross89 <63071941+flogross89@users.noreply.github.com> Date: Fri, 3 Jan 2025 02:06:04 +0100 Subject: [PATCH 33/40] BM's review comments --- .../FlightWarningSystem/FwsAbnormalSensed.ts | 12 ++++++---- .../systems/FlightWarningSystem/FwsCore.ts | 22 +++++++++++-------- 2 files changed, 21 insertions(+), 13 deletions(-) diff --git a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsAbnormalSensed.ts b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsAbnormalSensed.ts index 43cce185df8..f316ed9cce5 100644 --- a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsAbnormalSensed.ts +++ b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsAbnormalSensed.ts @@ -2900,10 +2900,14 @@ export class FwsAbnormalSensed { 314800008: { // FWS 1 FAULT flightPhaseInhib: [3, 4, 5, 6, 7, 9, 10], - simVarIsActive: this.fws.fws1Failed, + simVarIsActive: MappedSubject.create( + SubscribableMapFunctions.and(), + this.fws.fws1Failed, + this.fws.dcESSBusPowered, + ), whichItemsToShow: () => [], whichItemsChecked: () => [], - notActiveWhenFaults: ['314800004'], + notActiveWhenFaults: ['314800002', '314800003', '314800004'], failure: 1, sysPage: -1, info: () => ['220200005'], @@ -2912,10 +2916,10 @@ export class FwsAbnormalSensed { 314800009: { // FWS 2 FAULT flightPhaseInhib: [3, 4, 5, 6, 7, 9, 10], - simVarIsActive: this.fws.fws2Failed, + simVarIsActive: MappedSubject.create(SubscribableMapFunctions.and(), this.fws.fws2Failed, this.fws.dc2BusPowered), whichItemsToShow: () => [], whichItemsChecked: () => [], - notActiveWhenFaults: ['314800004'], + notActiveWhenFaults: ['314800002', '314800003', '314800004'], failure: 1, sysPage: -1, info: () => ['220200005'], diff --git a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsCore.ts b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsCore.ts index 2097cc1d7bc..8500edf0482 100644 --- a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsCore.ts +++ b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsCore.ts @@ -1482,6 +1482,10 @@ export class FwsCore { public readonly eng3Or4TakeoffPower = Subject.create(false); + /** 42 AVIONICS NETWORK */ + public readonly cpiomC1Available = Subject.create(false); + public readonly cpiomC2Available = Subject.create(false); + /* ICE */ public readonly iceDetectedTimer1 = new NXLogicConfirmNode(40, false); @@ -1536,12 +1540,6 @@ export class FwsCore { } }); - this.shutDownFor50MinutesCheckListReset.sub((v) => { - if (v) { - this.turnaroundReset(); - } - }); - this.ewdMessageLinesLeft.forEach((ls, i) => ls.sub((l) => { SimVar.SetSimVarValue(FwsCore.ewdMessageSimVarsLeft[i], 'string', l ?? ''); @@ -1905,9 +1903,7 @@ export class FwsCore { !SimVar.GetSimVarValue('L:A32NX_AFDX_13_13_REACHABLE', SimVarValueType.Bool) && !SimVar.GetSimVarValue('L:A32NX_AFDX_4_4_REACHABLE', SimVarValueType.Bool) && !SimVar.GetSimVarValue('L:A32NX_AFDX_14_14_REACHABLE', SimVarValueType.Bool); - this.fwsEcpFailed.set( - this.failuresConsumer.isActive(A380Failure.FwsEcp) || !this.dcESSBusPowered.get() || ecpNotReachable, - ); + this.fwsEcpFailed.set(this.failuresConsumer.isActive(A380Failure.FwsEcp) || ecpNotReachable); // Update flight phases this.flightPhases.update(deltaTime); @@ -1958,6 +1954,10 @@ export class FwsCore { ), ); + if (this.phase12ShutdownMemoryNode.read()) { + this.turnaroundReset(); + } + // TO CONFIG button this.toConfigTestRaw = SimVar.GetSimVarValue('L:A32NX_BTN_TOCONFIG', 'bool') > 0; this.toConfigPulseNode.write(this.toConfigTestRaw, _deltaTime); @@ -3765,6 +3765,10 @@ export class FwsCore { this.fireTestPb.set(SimVar.GetSimVarValue('L:A32NX_OVHD_FIRE_TEST_PB_IS_PRESSED', 'bool')); + /* 42 AVIONICS NETWORK */ + this.cpiomC1Available.set(SimVar.GetSimVarValue('L:A32NX_CPIOM_C1_AVAIL', 'bool')); + this.cpiomC2Available.set(SimVar.GetSimVarValue('L:A32NX_CPIOM_C1_AVAIL', 'bool')); + /* ANTI ICE */ const icePercentage = SimVar.GetSimVarValue('STRUCTURAL ICE PCT', 'percent over 100'); From d91b7c98e739e22330f2e62b74bd63b7b706bce6 Mon Sep 17 00:00:00 2001 From: floridude <63071941+flogross89@users.noreply.github.com> Date: Fri, 3 Jan 2025 03:02:26 +0100 Subject: [PATCH 34/40] Update fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsCore.ts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Pascal Störzbach --- .../systems/systems-host/systems/FlightWarningSystem/FwsCore.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsCore.ts b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsCore.ts index 8500edf0482..b3af768ecb4 100644 --- a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsCore.ts +++ b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsCore.ts @@ -3767,7 +3767,7 @@ export class FwsCore { /* 42 AVIONICS NETWORK */ this.cpiomC1Available.set(SimVar.GetSimVarValue('L:A32NX_CPIOM_C1_AVAIL', 'bool')); - this.cpiomC2Available.set(SimVar.GetSimVarValue('L:A32NX_CPIOM_C1_AVAIL', 'bool')); + this.cpiomC2Available.set(SimVar.GetSimVarValue('L:A32NX_CPIOM_C2_AVAIL', 'bool')); /* ANTI ICE */ From 8af710922ea4365141c5b2306ecbbb75cf801612 Mon Sep 17 00:00:00 2001 From: flogross89 <63071941+flogross89@users.noreply.github.com> Date: Fri, 3 Jan 2025 20:36:01 +0100 Subject: [PATCH 35/40] reset overhaul after discussion with BM --- .../systems/FlightWarningSystem/FwsCore.ts | 49 ++++++++++++------- 1 file changed, 30 insertions(+), 19 deletions(-) diff --git a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsCore.ts b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsCore.ts index b3af768ecb4..531f1772c06 100644 --- a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsCore.ts +++ b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsCore.ts @@ -1126,6 +1126,8 @@ export class FwsCore { public readonly shutDownFor50MinutesCheckListReset = Subject.create(false); + public readonly flightPhase12Entered = Subject.create(false); + /** If one of the ADR's CAS is above V1 - 4kts, confirm for 0.3s */ public readonly v1SpeedConfirmNode = new NXLogicConfirmNode(0.3); @@ -1536,7 +1538,33 @@ export class FwsCore { this.startupCompleted.sub((v) => { if (v) { - this.turnaroundReset(); + this.normalChecklists.reset(null); + this.abnormalNonSensed.reset(); + this.activeDeferredProceduresList.clear(); + this.abnormalSensed.reset(); + this.activeAbnormalProceduresList.clear(); + this.allCurrentFailures.length = 0; + this.presentedFailures.length = 0; + this.recallFailures.length = 0; + } + }); + + // Not a lot of references on which parts of the FWS to reset when + this.shutDownFor50MinutesCheckListReset.sub((v) => { + if (v) { + this.normalChecklists.reset(null); + this.abnormalNonSensed.reset(); + this.activeDeferredProceduresList.clear(); + } + }); + + this.flightPhase12Entered.sub((v) => { + if (v) { + this.abnormalSensed.reset(); + this.activeAbnormalProceduresList.clear(); + this.allCurrentFailures.length = 0; + this.presentedFailures.length = 0; + this.recallFailures.length = 0; } }); @@ -1946,6 +1974,7 @@ export class FwsCore { this.phase112.set(flightPhase112); this.phase12ShutdownMemoryNode.write(this.flightPhase.get() == 12, !this.phase112.get()); + this.flightPhase12Entered.set(this.flightPhase.get() === 12); this.shutDownFor50MinutesCheckListReset.set( this.shutDownFor50MinutesClResetConfNode.write( @@ -1954,10 +1983,6 @@ export class FwsCore { ), ); - if (this.phase12ShutdownMemoryNode.read()) { - this.turnaroundReset(); - } - // TO CONFIG button this.toConfigTestRaw = SimVar.GetSimVarValue('L:A32NX_BTN_TOCONFIG', 'bool') > 0; this.toConfigPulseNode.write(this.toConfigTestRaw, _deltaTime); @@ -4474,18 +4499,4 @@ export class FwsCore { return 10; } } - - turnaroundReset() { - // Reset some parts during turnaround - // Resets normal checklists, resets state of abnormal sensed procedures, deactivation of deferred procedures and abormal non-sensed procedures - this.normalChecklists.reset(null); - this.abnormalNonSensed.reset(); - this.abnormalSensed.reset(); - - this.activeDeferredProceduresList.clear(); - this.activeAbnormalProceduresList.clear(); - this.allCurrentFailures.length = 0; - this.presentedFailures.length = 0; - this.recallFailures.length = 0; - } } From 2fe26b8ff503e94fd01bd0cfb4ff48f322ffd210 Mon Sep 17 00:00:00 2001 From: flogross89 <63071941+flogross89@users.noreply.github.com> Date: Wed, 8 Jan 2025 22:26:00 +0100 Subject: [PATCH 36/40] reset ECL only if not manually reset, but still reset rest after 50min shutdown --- .../systems/FlightWarningSystem/FwsCore.ts | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsCore.ts b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsCore.ts index 531f1772c06..a8c36e5b9a2 100644 --- a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsCore.ts +++ b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsCore.ts @@ -1552,7 +1552,9 @@ export class FwsCore { // Not a lot of references on which parts of the FWS to reset when this.shutDownFor50MinutesCheckListReset.sub((v) => { if (v) { - this.normalChecklists.reset(null); + if (!this.manualCheckListReset.get()) { + this.normalChecklists.reset(null); + } this.abnormalNonSensed.reset(); this.activeDeferredProceduresList.clear(); } @@ -1973,14 +1975,11 @@ export class FwsCore { this.phase815MinConfNode.write(this.flightPhase.get() === 8, deltaTime); this.phase112.set(flightPhase112); - this.phase12ShutdownMemoryNode.write(this.flightPhase.get() == 12, !this.phase112.get()); + this.phase12ShutdownMemoryNode.write(this.flightPhase.get() === 12, !this.phase112.get()); this.flightPhase12Entered.set(this.flightPhase.get() === 12); this.shutDownFor50MinutesCheckListReset.set( - this.shutDownFor50MinutesClResetConfNode.write( - !this.manualCheckListReset.get() && this.phase12ShutdownMemoryNode.read(), - deltaTime, - ), + this.shutDownFor50MinutesClResetConfNode.write(this.phase12ShutdownMemoryNode.read(), deltaTime), ); // TO CONFIG button From 9e531954fc72aefd81ffe77c11dcf0df9f848a49 Mon Sep 17 00:00:00 2001 From: flogross89 <63071941+flogross89@users.noreply.github.com> Date: Tue, 14 Jan 2025 05:03:03 +0100 Subject: [PATCH 37/40] fix reset button names --- .../AirPlanes/FlyByWire_A380_842/model/A380_COCKPIT.xml | 4 ++-- fbw-a380x/src/systems/systems-host/index.ts | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/fbw-a380x/src/base/flybywire-aircraft-a380-842/SimObjects/AirPlanes/FlyByWire_A380_842/model/A380_COCKPIT.xml b/fbw-a380x/src/base/flybywire-aircraft-a380-842/SimObjects/AirPlanes/FlyByWire_A380_842/model/A380_COCKPIT.xml index 20f7304ed37..90a74cd2037 100644 --- a/fbw-a380x/src/base/flybywire-aircraft-a380-842/SimObjects/AirPlanes/FlyByWire_A380_842/model/A380_COCKPIT.xml +++ b/fbw-a380x/src/base/flybywire-aircraft-a380-842/SimObjects/AirPlanes/FlyByWire_A380_842/model/A380_COCKPIT.xml @@ -4992,10 +4992,10 @@ FMC_C - FWS1 + FWS1 - FWS2 + FWS2 diff --git a/fbw-a380x/src/systems/systems-host/index.ts b/fbw-a380x/src/systems/systems-host/index.ts index 1e577b34f48..13a33e565dd 100644 --- a/fbw-a380x/src/systems/systems-host/index.ts +++ b/fbw-a380x/src/systems/systems-host/index.ts @@ -115,8 +115,8 @@ class SystemsHost extends BaseInstrument { private readonly cpiomAvailablePublisher = new CpiomAvailableSimvarPublisher(this.bus); - private readonly fws1ResetPbStatus = ConsumerSubject.create(this.sub.on('fws1Reset'), false); - private readonly fws2ResetPbStatus = ConsumerSubject.create(this.sub.on('fws2Reset'), false); + private readonly fws1ResetPbStatus = ConsumerSubject.create(this.sub.on('a380x_reset_panel_fws1'), false); + private readonly fws2ResetPbStatus = ConsumerSubject.create(this.sub.on('a380x_reset_panel_fws2'), false); private readonly fws1Powered = ConsumerSubject.create(this.sub.on('cpiomC1Avail'), true); private readonly fws2Powered = ConsumerSubject.create(this.sub.on('cpiomC2Avail'), true); From bb8af64f7027124a8c32dfa710cf704f71409752 Mon Sep 17 00:00:00 2001 From: Florian Gross <63071941+flogross89@users.noreply.github.com> Date: Sat, 18 Jan 2025 21:27:26 +0200 Subject: [PATCH 38/40] some ECL fixes --- .../EcamMessages/ProcedureLinesGenerator.tsx | 19 +++++++++++---- .../systems/FlightWarningSystem/FwsCore.ts | 12 ++++++---- .../FwsNormalChecklists.ts | 23 +++++++++---------- 3 files changed, 33 insertions(+), 21 deletions(-) diff --git a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/ProcedureLinesGenerator.tsx b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/ProcedureLinesGenerator.tsx index c169e81c4ba..988b471fd2b 100644 --- a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/ProcedureLinesGenerator.tsx +++ b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/ProcedureLinesGenerator.tsx @@ -151,7 +151,10 @@ export class ProcedureLinesGenerator { } moveUp() { - if (!this.checklistState.procedureActivated) { + if ( + (this.type === ProcedureType.Deferred || this.type === ProcedureType.Abnormal) && + !this.checklistState.procedureActivated + ) { this.selectedItemIndex.set(SPECIAL_INDEX_ACTIVATE); return; } @@ -189,7 +192,10 @@ export class ProcedureLinesGenerator { } moveDown(skipCompletedSensed = true) { - if (!this.checklistState.procedureActivated) { + if ( + (this.type === ProcedureType.Deferred || this.type === ProcedureType.Abnormal) && + !this.checklistState.procedureActivated + ) { this.selectedItemIndex.set(SPECIAL_INDEX_ACTIVATE); return; } @@ -212,7 +218,6 @@ export class ProcedureLinesGenerator { const sii = this.selectedItemIndex.get(); // Check for special lines if (sii === SPECIAL_INDEX_NORMAL_CL_COMPLETE) { - // Do nothing this.selectedItemIndex.set(SPECIAL_INDEX_NORMAL_RESET); } else if (sii > HIGHEST_SPECIAL_INDEX) { this.selectedItemIndex.set( @@ -280,12 +285,18 @@ export class ProcedureLinesGenerator { } selectFirst() { - if (!this.checklistState.procedureActivated) { + if ( + (this.type === ProcedureType.Deferred || this.type === ProcedureType.Abnormal) && + !this.checklistState.procedureActivated === false + ) { this.selectedItemIndex.set(SPECIAL_INDEX_ACTIVATE); return; } else if (this.type === ProcedureType.Deferred && this.checklistState.procedureCompleted) { this.selectedItemIndex.set(SPECIAL_INDEX_DEFERRED_PROC_RECALL); return; + } else if (this.type === ProcedureType.Normal && this.checklistState.procedureCompleted) { + this.selectedItemIndex.set(SPECIAL_INDEX_NORMAL_RESET); + return; } const selectableAndNotChecked = this.selectableItems(false); diff --git a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsCore.ts b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsCore.ts index a8c36e5b9a2..153506e710b 100644 --- a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsCore.ts +++ b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsCore.ts @@ -1624,14 +1624,16 @@ export class FwsCore { }), ); - this.statusNormal.sub((s) => SimVar.SetSimVarValue('L:A32NX_STATUS_NORMAL', 'boolean', s)); + this.statusNormal.sub((s) => SimVar.SetSimVarValue('L:A32NX_STATUS_NORMAL', 'boolean', s), true); - this.ecamEwdShowStsIndication.sub((s) => - this.bus.getPublisher().pub('fws_show_sts_indication', s, true), + this.ecamEwdShowStsIndication.sub( + (s) => this.bus.getPublisher().pub('fws_show_sts_indication', s, true), + true, ); - this.ecamEwdShowFailurePendingIndication.sub((s) => - this.bus.getPublisher().pub('fws_show_failure_pending', s, true), + this.ecamEwdShowFailurePendingIndication.sub( + (s) => this.bus.getPublisher().pub('fws_show_failure_pending', s, true), + true, ); SimVar.SetSimVarValue('L:A32NX_STATUS_LEFT_LINE_8', 'string', '000000001'); diff --git a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsNormalChecklists.ts b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsNormalChecklists.ts index 45e71ff850a..7e9b6e132ca 100644 --- a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsNormalChecklists.ts +++ b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsNormalChecklists.ts @@ -304,19 +304,17 @@ export class FwsNormalChecklists { this.getNormalProceduresKeysSorted(true).length, ), ); - } else if (this.activeDeferredProcedureId.get() !== null) { - if (this.activeProcedure.lastLineIsSelected()) { - const curDefIndex = this.visibleDeferredProcedureKeys.indexOf(this.activeDeferredProcedureId.get()); - if (curDefIndex !== -1) { - this.activeDeferredProcedureId.set( - curDefIndex < this.visibleDeferredProcedureKeys.length - 1 - ? this.visibleDeferredProcedureKeys[curDefIndex + 1] - : null, - ); - } - } else { - this.activeProcedure.moveDown(skipCompletedSensed); + } else if (this.activeDeferredProcedureId.get() !== null && this.activeProcedure.lastLineIsSelected()) { + const curDefIndex = this.visibleDeferredProcedureKeys.indexOf(this.activeDeferredProcedureId.get()); + if (curDefIndex !== -1) { + this.activeDeferredProcedureId.set( + curDefIndex < this.visibleDeferredProcedureKeys.length - 1 + ? this.visibleDeferredProcedureKeys[curDefIndex + 1] + : null, + ); } + } else { + this.activeProcedure.moveDown(skipCompletedSensed); } } @@ -331,6 +329,7 @@ export class FwsNormalChecklists { const clStateFollowing: ChecklistState = { id: idFollowing.toString(), procedureCompleted: procFollowing.onlyActivatedByRequest ? true : false, + procedureActivated: true, itemsChecked: [...clFollowing.itemsChecked].map((val, index) => procFollowing.items[index].sensed ? val : false, ), From a712e6b73ad0fb6309360f3c2cfa854d8b905f1d Mon Sep 17 00:00:00 2001 From: Florian Gross <63071941+flogross89@users.noreply.github.com> Date: Sat, 18 Jan 2025 21:54:37 +0200 Subject: [PATCH 39/40] FWS healthy subscriptions fixed --- fbw-a380x/src/systems/instruments/src/EWD/EWD.tsx | 8 +++++--- .../src/EWD/elements/WdAbnormalSensedProcedures.tsx | 3 ++- .../EcamMessages/ProcedureLinesGenerator.tsx | 2 +- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/fbw-a380x/src/systems/instruments/src/EWD/EWD.tsx b/fbw-a380x/src/systems/instruments/src/EWD/EWD.tsx index 4f9f82d52c8..0aa598216ce 100644 --- a/fbw-a380x/src/systems/instruments/src/EWD/EWD.tsx +++ b/fbw-a380x/src/systems/instruments/src/EWD/EWD.tsx @@ -3,7 +3,7 @@ import { CdsDisplayUnit, DisplayUnitID } from '../MsfsAvionicsCommon/CdsDisplayU import { ConsumerSubject, DisplayComponent, - EventSubscriber, + EventBus, FSComponent, MappedSubject, Subject, @@ -26,7 +26,7 @@ import { WdAbnormalNonSensedProcedures } from 'instruments/src/EWD/elements/WdAb export class EngineWarningDisplay extends DisplayComponent<{ bus: ArincEventBus }> { private readonly sub = this.props.bus.getSubscriber(); - private readonly availChecker = new FwsEwdAvailabilityChecker(this.sub); + private readonly availChecker = new FwsEwdAvailabilityChecker(this.props.bus); private readonly engineStateSubs: ConsumerSubject[] = [ ConsumerSubject.create(this.sub.on('engine_state_1'), 0), @@ -297,7 +297,9 @@ export class EngineWarningDisplay extends DisplayComponent<{ bus: ArincEventBus } class FwsEwdAvailabilityChecker { - constructor(private sub: EventSubscriber) {} + constructor(private bus: EventBus) {} + + private readonly sub = this.bus.getSubscriber(); private readonly fws1IsHealthy = ConsumerSubject.create(this.sub.on('fws1_is_healthy'), true); private readonly fws2IsHealthy = ConsumerSubject.create(this.sub.on('fws2_is_healthy'), true); diff --git a/fbw-a380x/src/systems/instruments/src/EWD/elements/WdAbnormalSensedProcedures.tsx b/fbw-a380x/src/systems/instruments/src/EWD/elements/WdAbnormalSensedProcedures.tsx index 0e06e7a9f6c..e210cfc6690 100644 --- a/fbw-a380x/src/systems/instruments/src/EWD/elements/WdAbnormalSensedProcedures.tsx +++ b/fbw-a380x/src/systems/instruments/src/EWD/elements/WdAbnormalSensedProcedures.tsx @@ -57,7 +57,8 @@ export class WdAbnormalSensedProcedures extends WdAbstractChecklistComponent { super.onAfterRender(node); this.procedures.sub(() => this.updateChecklists(), true); - this.activeProcedureId.sub(() => this.updateChecklists()); + this.activeProcedureId.sub(() => this.updateChecklists(), true); + this.props.fwsAvail?.sub(() => this.updateChecklists(), true); } render() { diff --git a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/ProcedureLinesGenerator.tsx b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/ProcedureLinesGenerator.tsx index 988b471fd2b..2960712f4fa 100644 --- a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/ProcedureLinesGenerator.tsx +++ b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/ProcedureLinesGenerator.tsx @@ -287,7 +287,7 @@ export class ProcedureLinesGenerator { selectFirst() { if ( (this.type === ProcedureType.Deferred || this.type === ProcedureType.Abnormal) && - !this.checklistState.procedureActivated === false + this.checklistState.procedureActivated === false ) { this.selectedItemIndex.set(SPECIAL_INDEX_ACTIVATE); return; From a44597aa9ed7e0c7f882e9eb05cb9f1440ef4086 Mon Sep 17 00:00:00 2001 From: Florian Gross <63071941+flogross89@users.noreply.github.com> Date: Sun, 19 Jan 2025 01:37:33 +0200 Subject: [PATCH 40/40] ECL indexing fixes --- .../FwsNormalChecklists.ts | 107 +++++++++--------- 1 file changed, 53 insertions(+), 54 deletions(-) diff --git a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsNormalChecklists.ts b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsNormalChecklists.ts index 7e9b6e132ca..6514528f9de 100644 --- a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsNormalChecklists.ts +++ b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsNormalChecklists.ts @@ -67,6 +67,8 @@ export class FwsNormalChecklists { private deferredProcedures: ProcedureLinesGenerator[] = []; + private deferredAutoDisplayWasTriggered = false; + private activeProcedure: ProcedureLinesGenerator; constructor(private fws: FwsCore) { @@ -127,7 +129,7 @@ export class FwsNormalChecklists { this.activeDeferredProcedureId.set(null); return; } - const firstProcedureKey = this.visibleDeferredProcedureKeys[0]; + const firstProcedureKey = this.visibleDeferredProcedureKeys[0] ?? null; this.activeDeferredProcedureId.set(firstProcedureKey); this.visibleDeferredProcedureKeys.forEach((key) => { const proc = this.fws.activeDeferredProceduresList.getValue(key); @@ -237,31 +239,21 @@ export class FwsNormalChecklists { this.selectedLine.sub(() => this.scrollToSelectedLine()); } - getNormalProceduresKeysSorted(onlyVisible = false) { + getNormalProceduresKeysSorted() { return Object.keys(EcamNormalProcedures) .map((v) => parseInt(v)) - .filter((v, index) => { - if (onlyVisible && deferredProcedureIds.includes(v) && this.checklistState.getValue(0)?.itemsToShow[index]) { - return false; - } else { - return true; - } - }) .sort((a, b) => a - b); } selectFirst() { if (this.checklistId.get() === 0) { // Find first non-completed checklist - const keys = this.getNormalProceduresKeysSorted(true); - let firstIncompleteChecklist = 0; - keys.some((key, index) => { - if (!this.checklistState.getValue(key).procedureCompleted) { - firstIncompleteChecklist = index; - return true; - } - }); - this.selectedLine.set(firstIncompleteChecklist); + const keys = this.getNormalProceduresKeysSorted(); + const firstIncompleteChecklist = keys.findIndex( + (key, index) => + this.checklistState.getValue(0).itemsToShow[index] && !this.checklistState.getValue(key).procedureCompleted, + ); + this.selectedLine.set(firstIncompleteChecklist !== -1 ? firstIncompleteChecklist : 0); } else { this.activeProcedure.selectFirst(); } @@ -273,12 +265,12 @@ export class FwsNormalChecklists { .map((_, index) => (this.checklistState.getValue(0).itemsToShow[index] ? index : null)) .filter((v) => v !== null); this.selectedLine.set(Math.max(shownItems[shownItems.indexOf(this.selectedLine.get()) - 1] ?? 0, 0)); - } else { + } else if (deferredProcedureIds.includes(this.checklistId.get())) { if (this.activeDeferredProcedureId.get() !== null) { - if (this.activeProcedure.lastLineIsSelected()) { + if (this.activeProcedure.firstLineIsSelected()) { const curDefIndex = this.visibleDeferredProcedureKeys.indexOf(this.activeDeferredProcedureId.get()); if (curDefIndex !== -1 && curDefIndex > 0) { - this.activeDeferredProcedureId.set(this.visibleDeferredProcedureKeys[curDefIndex - 1]); + this.activeDeferredProcedureId.set(this.visibleDeferredProcedureKeys[curDefIndex - 1] ?? null); } } else { this.activeProcedure.moveUp(); @@ -286,9 +278,11 @@ export class FwsNormalChecklists { } else { // CLEAR of page selected, select last procedure this.activeDeferredProcedureId.set( - this.visibleDeferredProcedureKeys[this.visibleDeferredProcedureKeys.length - 1], + this.visibleDeferredProcedureKeys[this.visibleDeferredProcedureKeys.length - 1] ?? null, ); } + } else { + this.activeProcedure.moveUp(); } } @@ -299,9 +293,8 @@ export class FwsNormalChecklists { .filter((v) => v !== null); this.selectedLine.set( Math.min( - shownItems[shownItems.indexOf(this.selectedLine.get()) + 1] ?? - this.getNormalProceduresKeysSorted(true).length, - this.getNormalProceduresKeysSorted(true).length, + shownItems[shownItems.indexOf(this.selectedLine.get()) + 1] ?? shownItems[shownItems.length - 1], + shownItems[shownItems.length - 1], ), ); } else if (this.activeDeferredProcedureId.get() !== null && this.activeProcedure.lastLineIsSelected()) { @@ -359,10 +352,15 @@ export class FwsNormalChecklists { this.fws.adrPressureAltitude.get() < 20_000 && this.fws.slatsAngle.get() > 0 && Simplane.getPressureSelectedMode(Aircraft.A320_NEO) !== 'STD' && - !this.showChecklistRequested.get() && this.hasDeferred.some((v) => v) ) { - this.showChecklistRequested.set(true); + if (!this.deferredAutoDisplayWasTriggered && !this.showChecklistRequested.get()) { + this.showChecklistRequested.set(true); + this.navigateToChecklist(0); + this.deferredAutoDisplayWasTriggered = true; + } else if (this.showChecklistRequested.get()) { + this.deferredAutoDisplayWasTriggered = true; + } } } @@ -372,31 +370,6 @@ export class FwsNormalChecklists { this.showChecklistRequested.set(!this.showChecklistRequested.get()); } - if (!this.checklistShown.get()) { - return; - } - - if (this.fws.clDownPulseNode.read()) { - this.moveDown(); - } - - if (this.fws.clUpPulseNode.read()) { - this.moveUp(); - } - - if (this.fws.clCheckPulseNode.read()) { - if (this.checklistId.get() === 0) { - // Navigate to check list - this.navigateToChecklist(this.getNormalProceduresKeysSorted()[this.selectedLine.get()]); - } else { - if (deferredProcedureIds.includes(this.checklistId.get()) && this.activeDeferredProcedureId.get() === null) { - this.navigateToChecklist(0); - } else { - this.activeProcedure.checkSelected(); - } - } - } - // Update deferred proc status for (let i = 0; i <= 3; i++) { this.hasDeferred[i] = false; @@ -429,10 +402,36 @@ export class FwsNormalChecklists { } break; } - - this.checkIfDeferredAutoDisplay(); }); + this.checkIfDeferredAutoDisplay(); + + if (!this.checklistShown.get()) { + return; + } + + if (this.fws.clDownPulseNode.read()) { + this.moveDown(); + } + + if (this.fws.clUpPulseNode.read()) { + this.moveUp(); + } + + if (this.fws.clCheckPulseNode.read()) { + if (this.checklistId.get() === 0) { + // Navigate to check list + this.navigateToChecklist(this.getNormalProceduresKeysSorted()[this.selectedLine.get()]); + } else if ( + deferredProcedureIds.includes(this.checklistId.get()) && + this.activeDeferredProcedureId.get() === null + ) { + this.navigateToChecklist(0); + } else { + this.activeProcedure.checkSelected(); + } + } + // Update sensed items const ids = this.getNormalProceduresKeysSorted();