From 8975ea17afb0c6dca1fc0e06583e23f12db1521c Mon Sep 17 00:00:00 2001 From: Kilian Hofmann Date: Wed, 11 Jun 2025 23:49:35 +0200 Subject: [PATCH] SB fetch and entry --- PackageSources/js-bundle/src/App.tsx | 39 +-- .../src/components/SBEntry/SBEntryPax.tsx | 254 +++++++----------- .../src/components/actionbar/ActionBar.tsx | 3 +- .../js-bundle/src/components/pax/Pax.tsx | 27 +- .../stationEntry/StationEntryPax.tsx | 5 +- .../src/components/zfwEntry/ZFWEntryPax.tsx | 13 +- PackageSources/js-bundle/src/constants.ts | 5 +- .../js-bundle/src/types/general.d.ts | 1 + .../js-bundle/src/types/virtual-scroll.d.ts | 11 - .../js-bundle/src/utils/TFDISBImport.ts | 26 +- README.md | 9 +- 11 files changed, 156 insertions(+), 237 deletions(-) create mode 100644 PackageSources/js-bundle/src/types/general.d.ts delete mode 100644 PackageSources/js-bundle/src/types/virtual-scroll.d.ts diff --git a/PackageSources/js-bundle/src/App.tsx b/PackageSources/js-bundle/src/App.tsx index 5e00747..60616f6 100644 --- a/PackageSources/js-bundle/src/App.tsx +++ b/PackageSources/js-bundle/src/App.tsx @@ -1,6 +1,11 @@ -import { FC, StrictMode, useCallback, useEffect, useState } from 'react'; +import { FC, useCallback, useEffect, useState } from 'react'; import Pax from './components/pax/Pax'; -import { COHERENT_COMBUS_WASM_CALL, COMM_BUS_LIVE_DATA_EVENT, TFDI_SIMBRIEF_USERNAME_EVENT } from './constants'; +import { + COHERENT_COMBUS_WASM_CALL, + COMM_BUS_LIVE_DATA_EVENT, + TFDI_SIMBRIEF_USERNAME_CALL, + TFDI_SIMBRIEF_USERNAME_EVENT, +} from './constants'; import { WASMDataPax } from './types/WASMData'; interface IAppProps { @@ -23,35 +28,33 @@ const App: FC = ({ commBus }) => { useEffect(() => { console.log('Initializing CommBus'); - commBus.on(COMM_BUS_LIVE_DATA_EVENT, usernameCallback); + commBus.on(TFDI_SIMBRIEF_USERNAME_EVENT, usernameCallback); commBus.on(COMM_BUS_LIVE_DATA_EVENT, wasmCallback); setTimeout(() => { - Coherent.call(COHERENT_COMBUS_WASM_CALL, TFDI_SIMBRIEF_USERNAME_EVENT, 'null'); + Coherent.call(COHERENT_COMBUS_WASM_CALL, TFDI_SIMBRIEF_USERNAME_CALL, 'null'); }, 1000); return () => { - commBus.off('receiveSimBriefUsername', usernameCallback); + commBus.off(TFDI_SIMBRIEF_USERNAME_EVENT, usernameCallback); commBus.off(COMM_BUS_LIVE_DATA_EVENT, wasmCallback); }; }, []); return ( - -
-
- {isReady && WASMData ? ( - WASMData.userData.isCargo ? ( - <>Not yet Implemented - ) : ( - - ) +
+
+ {isReady && WASMData ? ( + WASMData.userData.isCargo ? ( + <>Not yet Implemented ) : ( -

LOADING

- )} -
+ + ) + ) : ( +

LOADING

+ )}
- +
); }; diff --git a/PackageSources/js-bundle/src/components/SBEntry/SBEntryPax.tsx b/PackageSources/js-bundle/src/components/SBEntry/SBEntryPax.tsx index d7cfbcb..4500b7b 100644 --- a/PackageSources/js-bundle/src/components/SBEntry/SBEntryPax.tsx +++ b/PackageSources/js-bundle/src/components/SBEntry/SBEntryPax.tsx @@ -1,111 +1,43 @@ -import { FC, useEffect, useState } from 'react'; -import { PaxConfig, PayloadPax } from '../../configs/pax'; -import { Fuel, SharedConfig } from '../../configs/shared'; +import { FC, useEffect, useRef, useState } from 'react'; +import { emptyAircraft } from '../../configs/shared'; +import { COHERENT_COMBUS_WASM_CALL, COMM_BUS_UPDATE_TARGET_EVENT } from '../../constants'; +import { WASMDataPax } from '../../types/WASMData'; +import { LoadingState } from '../../types/general'; import { ImportFlightPlan } from '../../utils/TFDISBImport'; import CGSelect from '../CGSelect/CGSelect'; import ActionBar from '../actionbar/ActionBar'; -interface StationEntryProps { - unit: 'kg' | 'lbs'; - isER: boolean; - initialPayload: PayloadPax; - fuelLive: Fuel; - payloadLive: PayloadPax; - loadingState: 'preview' | 'accepted' | 'loaded'; +interface SBEntryProps { + WASMData: WASMDataPax; + loadingState: LoadingState; username: string; - setLoadingState: (newState: StationEntryProps['loadingState']) => void; - updateView: (payload: PayloadPax) => void; + setLoadingState: (newState: LoadingState) => void; loadAircraft: () => void; } -const SBEntryPax: FC = ({ - unit, - isER, - initialPayload, - fuelLive, - payloadLive, - loadingState, - username, - setLoadingState, - updateView, - loadAircraft, -}) => { - const [targetZFWCG, setTargetZFWCG] = useState(SharedConfig.CGLimits.default); - const [fuel, setFuel] = useState( - Math.round( - fuelLive.main1 + - fuelLive.main1Tip + - fuelLive.main2 + - fuelLive.main3 + - fuelLive.main3Tip + - fuelLive.upperAux + - fuelLive.lowerAux + - fuelLive.tail + - fuelLive.forwardAux1 + - fuelLive.forwardAux2 - ) - ); - const [ZFW, setZFW] = useState( - Math.round( - PaxConfig.weights.base[unit].total + - (isER ? SharedConfig.erExtraWeight[unit] * 2 : 0) + - payloadLive.empty + - initialPayload.business1Left + - initialPayload.business1Center + - initialPayload.business1Right + - initialPayload.business2Left + - initialPayload.business2Center + - initialPayload.business2Right + - initialPayload.economy1Left + - initialPayload.economy1Center + - initialPayload.economy1Right + - initialPayload.economy2Left + - initialPayload.economy2Center + - initialPayload.economy2Right + - initialPayload.forwardCargo + - initialPayload.rearCargo - ) - ); +const SBEntryPax: FC = ({ WASMData, loadingState, username, setLoadingState, loadAircraft }) => { + const [CGTarget, setCGTarget] = useState(WASMData.targetPayload.CGTarget); + const [fuel, setFuel] = useState(Math.round(WASMData.livePayload.fuel)); + const [fuelEnabled, setFuelEnabled] = useState(true); const [SBPlan, setSBPlan] = useState(); const [SBInFlight, setSBInFlight] = useState(false); - const _ZFW = () => { - if (loadingState !== 'loaded') return ZFW; + const numPax = useRef(0); + const cargo = useRef(0); - return Math.round( - payloadLive.empty + - payloadLive.pilot + - payloadLive.firstOfficer + - payloadLive.engineer + - payloadLive.cabinCrewFront + - payloadLive.business1Left + - payloadLive.business1Center + - payloadLive.business1Right + - payloadLive.business2Left + - payloadLive.business2Center + - payloadLive.business2Right + - payloadLive.economy1Left + - payloadLive.economy1Center + - payloadLive.economy1Right + - payloadLive.economy2Left + - payloadLive.economy2Center + - payloadLive.economy2Right + - payloadLive.cabinCrewRear + - payloadLive.forwardCargo + - payloadLive.rearCargo + - payloadLive.leftAuxPax + - payloadLive.rightAuxPax - ); + const ZFW = () => { + if (loadingState !== 'loaded') return Math.round(WASMData.targetPayload.total); + + return Math.round(WASMData.livePayload.total); }; const ZFWValid = () => { - return _ZFW() <= PaxConfig.maxZWF[unit]; + return ZFW() <= WASMData.limits.maxZFW; }; - const GW = () => { - return fuel + _ZFW(); + return fuel + ZFW(); }; const GWValid = () => { - return GW() <= (isER ? SharedConfig.maxTOW.er[unit] : SharedConfig.maxTOW.norm[unit]); + return GW() <= WASMData.limits.maxTOW; }; const handleInput = (input: string, maxValue: number, setter: (value: number) => void) => { @@ -125,49 +57,89 @@ const SBEntryPax: FC = ({ const handleSB = async () => { setSBInFlight(true); - const SBResponse = await ImportFlightPlan(username, PaxConfig, unit, isER); + const SBResponse = await ImportFlightPlan( + username, + WASMData.limits.maxZFW, + WASMData.limits.maxTOW, + WASMData.limits.maxFuel, + WASMData.userData.isImperial + ); if (SBResponse.type === 'error') { console.error('TODO: ERROR', SBResponse.message); setSBInFlight(false); return; } - const __ZFW = Math.round( - PaxConfig.weights.base[unit].total + - (isER ? SharedConfig.erExtraWeight[unit] * 2 : 0) + - payloadLive.empty + - SBResponse.message.pax * (PaxConfig.weights.pax[unit] + PaxConfig.weights.baggage[unit]) + - SBResponse.message.cargo - ); - const _fuel = SBResponse.message.fuel; + cargo.current = parseFloat(SBResponse.message.cargo) ?? 0; + numPax.current = parseInt(SBResponse.message.pax) ?? 0; - updateView( - PaxConfig.distribute(__ZFW, targetZFWCG, payloadLive.empty, fuelLive, unit, isER, SBResponse.message.pax) - ); + updateData(); setSBPlan(SBResponse.message); - setZFW(__ZFW); - setFuel(_fuel); + setFuel(parseFloat(SBResponse.message.fuel) ?? 0); setSBInFlight(false); }; useEffect( () => - setFuel((prev) => - prev > (isER ? SharedConfig.maxFuel.er[unit] : SharedConfig.maxFuel.norm[unit]) - ? isER - ? SharedConfig.maxFuel.er[unit] - : SharedConfig.maxFuel.norm[unit] - : prev - ), - [isER] + setFuel((prev) => { + if (prev > WASMData.limits.maxFuel) return WASMData.limits.maxFuel; + return prev; + }), + [WASMData.userData.isER] ); + useEffect(() => { + setFuelEnabled(Math.round(WASMData.livePayload.fuel) === fuel); + }, [WASMData.livePayload.fuel]); + + const updateData = (_CGTarget?: number) => { + Coherent.call( + COHERENT_COMBUS_WASM_CALL, + COMM_BUS_UPDATE_TARGET_EVENT, + JSON.stringify({ + mode: 0, + cargo: cargo.current ?? 0, + numPax: numPax.current ?? 0, + CGTarget: _CGTarget ?? CGTarget, + }) + ); + }; return ( <> +
+
+ + handleInput(e.target.value, WASMData.limits.maxFuel, setFuel)} + disabled={loadingState !== 'preview'} + /> + +
+
+
- + = ({ />
- + = ({
- setTargetZFWCG((prev) => { + setCGTarget((prev) => { const _new = prev + 0.1; - updateView(PaxConfig.distribute(ZFW, _new, payloadLive.empty, fuelLive, unit, isER)); + updateData(_new); return _new; }) } decrease={() => - setTargetZFWCG((prev) => { + setCGTarget((prev) => { const _new = prev - 0.1; - updateView(PaxConfig.distribute(ZFW, _new, payloadLive.empty, fuelLive, unit, isER)); + updateData(_new); return _new; }) } @@ -211,53 +185,22 @@ const SBEntryPax: FC = ({
-
-
- - - handleInput( - e.target.value, - isER ? SharedConfig.maxFuel.er[unit] : SharedConfig.maxFuel.norm[unit], - setFuel - ) - } - disabled - /> - -
-
-
= ({ setLoadingState('loaded')} reject={() => setLoadingState('preview')} importSB={handleSB} @@ -284,7 +226,7 @@ const SBEntryPax: FC = ({ unload={() => { setLoadingState('preview'); - PaxConfig.unload(unit, isER); + emptyAircraft(); }} /> diff --git a/PackageSources/js-bundle/src/components/actionbar/ActionBar.tsx b/PackageSources/js-bundle/src/components/actionbar/ActionBar.tsx index 782afba..cf78ae9 100644 --- a/PackageSources/js-bundle/src/components/actionbar/ActionBar.tsx +++ b/PackageSources/js-bundle/src/components/actionbar/ActionBar.tsx @@ -1,7 +1,8 @@ import { FC } from 'react'; +import { LoadingState } from '../../types/general'; interface ActionBarProps { - loadingState: 'preview' | 'accepted' | 'loaded'; + loadingState: LoadingState; acceptDisabled: boolean; accept: () => void; reject: () => void; diff --git a/PackageSources/js-bundle/src/components/pax/Pax.tsx b/PackageSources/js-bundle/src/components/pax/Pax.tsx index bff3c43..0ef8d0a 100644 --- a/PackageSources/js-bundle/src/components/pax/Pax.tsx +++ b/PackageSources/js-bundle/src/components/pax/Pax.tsx @@ -1,6 +1,8 @@ import { FC, useState } from 'react'; +import { LoadingState } from '../../types/general'; import { WASMDataPax } from '../../types/WASMData'; import Profile from '../profile/Profile'; +import SBEntryPax from '../SBEntry/SBEntryPax'; import StationEntryPax from '../stationEntry/StationEntryPax'; import Tabbar from '../tabbar/Tabbar'; import ZFWEntryPax from '../zfwEntry/ZFWEntryPax'; @@ -12,24 +14,24 @@ interface PaxProps { const Pax: FC = ({ WASMData, username }) => { const [selectedTab, setSelectedTab] = useState(0); - const [loadingState, setLoadingState] = useState<'preview' | 'accepted' | 'loaded'>('preview'); + const [loadingState, setLoadingState] = useState('preview'); - const upper1 = (overrideState: 'preview' | 'accepted' | 'loaded' = loadingState) => { + const upper1 = (overrideState: LoadingState = loadingState) => { if (overrideState !== 'loaded') return WASMData.targetPayload.business1; return WASMData.livePayload.business1; }; - const upper2 = (overrideState: 'preview' | 'accepted' | 'loaded' = loadingState) => { + const upper2 = (overrideState: LoadingState = loadingState) => { if (overrideState !== 'loaded') return WASMData.targetPayload.business2; return WASMData.livePayload.business2; }; - const upper3 = (overrideState: 'preview' | 'accepted' | 'loaded' = loadingState) => { + const upper3 = (overrideState: LoadingState = loadingState) => { if (overrideState !== 'loaded') return WASMData.targetPayload.economy1; return WASMData.livePayload.economy1; }; - const upper4 = (overrideState: 'preview' | 'accepted' | 'loaded' = loadingState) => { + const upper4 = (overrideState: LoadingState = loadingState) => { if (overrideState !== 'loaded') return WASMData.targetPayload.economy2; return WASMData.livePayload.economy2; @@ -101,28 +103,17 @@ const Pax: FC = ({ WASMData, username }) => { selectedTab={selectedTab} setSelectedTab={setSelectedTab} /> - - {/* {username && selectedTab === 0 && ( { - setPayload(_payload); - }} loadAircraft={() => { - PaxConfig.setBaseWeight(unit, isER); - PaxConfig.setWeights(payload, unit); + console.log('SET WEIGHT SB'); }} /> )} - */} {((username && selectedTab === 1) || (!username && selectedTab === 0)) && ( void; + loadingState: LoadingState; + setLoadingState: (newState: LoadingState) => void; loadAircraft: () => void; } diff --git a/PackageSources/js-bundle/src/components/zfwEntry/ZFWEntryPax.tsx b/PackageSources/js-bundle/src/components/zfwEntry/ZFWEntryPax.tsx index 5970f2c..4a59bfd 100644 --- a/PackageSources/js-bundle/src/components/zfwEntry/ZFWEntryPax.tsx +++ b/PackageSources/js-bundle/src/components/zfwEntry/ZFWEntryPax.tsx @@ -2,22 +2,21 @@ import { FC, useEffect, useState } from 'react'; import { emptyAircraft } from '../../configs/shared'; import { COHERENT_COMBUS_WASM_CALL, COMM_BUS_UPDATE_TARGET_EVENT } from '../../constants'; import { WASMDataPax } from '../../types/WASMData'; +import { LoadingState } from '../../types/general'; import CGSelect from '../CGSelect/CGSelect'; import ActionBar from '../actionbar/ActionBar'; -interface StationEntryProps { +interface ZFWEntryProps { WASMData: WASMDataPax; - loadingState: 'preview' | 'accepted' | 'loaded'; - setLoadingState: (newState: StationEntryProps['loadingState']) => void; + loadingState: LoadingState; + setLoadingState: (newState: LoadingState) => void; loadAircraft: () => void; } -const ZFWEntryPax: FC = ({ WASMData, loadingState, setLoadingState, loadAircraft }) => { +const ZFWEntryPax: FC = ({ WASMData, loadingState, setLoadingState, loadAircraft }) => { const [CGTarget, setCGTarget] = useState(WASMData.targetPayload.CGTarget); const [fuel, setFuel] = useState(Math.round(WASMData.livePayload.fuel)); - const [ZFWTarget, setZFWTarget] = useState( - Math.round(Math.max(WASMData.limits.minZFW, WASMData.targetPayload.total)) - ); + const [ZFWTarget, setZFWTarget] = useState(Math.round(WASMData.targetPayload.total)); const [fuelEnabled, setFuelEnabled] = useState(true); const ZFW = () => { diff --git a/PackageSources/js-bundle/src/constants.ts b/PackageSources/js-bundle/src/constants.ts index 4a055b3..caa4804 100644 --- a/PackageSources/js-bundle/src/constants.ts +++ b/PackageSources/js-bundle/src/constants.ts @@ -1,5 +1,8 @@ export const COHERENT_COMBUS_WASM_CALL = 'COMM_BUS_WASM_CALLBACK'; -export const TFDI_SIMBRIEF_USERNAME_EVENT = 'requestSimBriefUsername'; + +export const TFDI_SIMBRIEF_USERNAME_CALL = 'requestSimBriefUsername'; +export const TFDI_SIMBRIEF_USERNAME_EVENT = 'receiveSimBriefUsername'; + export const COMM_BUS_LIVE_DATA_EVENT = 'khofmann_tfdi_md-11_load_manager_live_data'; export const COMM_BUS_UPDATE_TARGET_EVENT = 'khofmann_tfdi_md-11_load_manager_update_target'; diff --git a/PackageSources/js-bundle/src/types/general.d.ts b/PackageSources/js-bundle/src/types/general.d.ts new file mode 100644 index 0000000..8adadd5 --- /dev/null +++ b/PackageSources/js-bundle/src/types/general.d.ts @@ -0,0 +1 @@ +export type LoadingState = 'preview' | 'accepted' | 'loaded'; diff --git a/PackageSources/js-bundle/src/types/virtual-scroll.d.ts b/PackageSources/js-bundle/src/types/virtual-scroll.d.ts deleted file mode 100644 index 05a3fa3..0000000 --- a/PackageSources/js-bundle/src/types/virtual-scroll.d.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { CSSProperties, DOMAttributes, ReactNode } from 'react'; - -type CustomElement = Partial & { children: ReactNode }>; - -declare global { - namespace JSX { - interface IntrinsicElements { - ['virtual-scroll']: CustomElement<{ class?: string; direction: 'x' | 'y'; style?: CSSProperties }>; - } - } -} diff --git a/PackageSources/js-bundle/src/utils/TFDISBImport.ts b/PackageSources/js-bundle/src/utils/TFDISBImport.ts index 4b772f5..205a9cf 100644 --- a/PackageSources/js-bundle/src/utils/TFDISBImport.ts +++ b/PackageSources/js-bundle/src/utils/TFDISBImport.ts @@ -1,6 +1,3 @@ -import { PaxConfig } from '../configs/pax'; -import { SharedConfig } from '../configs/shared'; - const getSimBriefFlightPlan = async (simBriefUsername: string) => { const flightPlanURL = `https://www.simbrief.com/api/xml.fetcher.php?username=${simBriefUsername}&json=1`; let response: Response; @@ -19,9 +16,10 @@ const getSimBriefFlightPlan = async (simBriefUsername: string) => { export const ImportFlightPlan = async ( username: string, - config: typeof PaxConfig, - unit: 'kg' | 'lbs', - isER: boolean + maxZFW: number, + maxTOW: number, + maxFuel: number, + isImperial: boolean ) => { const flightPlan = await getSimBriefFlightPlan(username); if (!flightPlan.success) { @@ -41,23 +39,17 @@ export const ImportFlightPlan = async ( } let convFactor = 1; - if (data.params.units === 'kgs' && unit === 'lbs') convFactor = 2.20462262185; - if (data.params.units === 'lbs' && unit === 'kg') convFactor = 1 / 2.20462262185; + if (data.params.units === 'kgs' && isImperial) convFactor = 2.20462262185; + if (data.params.units === 'lbs' && !isImperial) convFactor = 1 / 2.20462262185; return { type: 'data', message: { - plannedZFW: Math.min(config.maxZWF[unit], Math.round(data.weights.est_zfw * convFactor)), - plannedGW: Math.min( - isER ? SharedConfig.maxTOW.er[unit] : SharedConfig.maxTOW.norm[unit], - Math.round(data.weights.est_ramp * convFactor) - ), + plannedZFW: Math.min(maxZFW, Math.round(data.weights.est_zfw * convFactor)), + plannedGW: Math.min(maxTOW, Math.round(data.weights.est_ramp * convFactor)), pax: data.weights.pax_count_actual, cargo: Math.round(data.weights.freight_added * convFactor), - fuel: Math.min( - isER ? SharedConfig.maxFuel.er[unit] : SharedConfig.maxFuel.norm[unit], - Math.round(data.fuel.plan_ramp * convFactor) - ), + fuel: Math.min(maxFuel, Math.round(data.fuel.plan_ramp * convFactor)), }, }; }; diff --git a/README.md b/README.md index 3399cb0..32955e5 100644 --- a/README.md +++ b/README.md @@ -10,12 +10,9 @@ Coherent.call("COMM_BUS_WASM_CALLBACK", "khofmann_tfdi_md-11_load_manager_update TODO: - JS - - Connect to WASM as Data Source (sans SB username) - - Setting target - - SB - - Stations - - GSX State? + - GSX State for displaying status fo prog. loading + - Persist SB data across page changes - Duplicate Input pages for F - WASM - Setting of payload - - GSX synced setting + - GSX synced setting of payload