Compare commits
2 Commits
890622453e
...
8975ea17af
| Author | SHA1 | Date | |
|---|---|---|---|
| 8975ea17af | |||
| 896a459bba |
@ -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 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';
|
import { WASMDataPax } from './types/WASMData';
|
||||||
|
|
||||||
interface IAppProps {
|
interface IAppProps {
|
||||||
@ -23,21 +28,20 @@ const App: FC<IAppProps> = ({ commBus }) => {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
console.log('Initializing CommBus');
|
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);
|
commBus.on(COMM_BUS_LIVE_DATA_EVENT, wasmCallback);
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
Coherent.call(COHERENT_COMBUS_WASM_CALL, TFDI_SIMBRIEF_USERNAME_EVENT, 'null');
|
Coherent.call(COHERENT_COMBUS_WASM_CALL, TFDI_SIMBRIEF_USERNAME_CALL, 'null');
|
||||||
}, 1000);
|
}, 1000);
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
commBus.off('receiveSimBriefUsername', usernameCallback);
|
commBus.off(TFDI_SIMBRIEF_USERNAME_EVENT, usernameCallback);
|
||||||
commBus.off(COMM_BUS_LIVE_DATA_EVENT, wasmCallback);
|
commBus.off(COMM_BUS_LIVE_DATA_EVENT, wasmCallback);
|
||||||
};
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<StrictMode>
|
|
||||||
<div className="flex w-full justify-center pt-2 bg-zinc-900">
|
<div className="flex w-full justify-center pt-2 bg-zinc-900">
|
||||||
<div className="flex w-3/4 flex-col items-center">
|
<div className="flex w-3/4 flex-col items-center">
|
||||||
{isReady && WASMData ? (
|
{isReady && WASMData ? (
|
||||||
@ -51,7 +55,6 @@ const App: FC<IAppProps> = ({ commBus }) => {
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</StrictMode>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -1,111 +1,43 @@
|
|||||||
import { FC, useEffect, useState } from 'react';
|
import { FC, useEffect, useRef, useState } from 'react';
|
||||||
import { PaxConfig, PayloadPax } from '../../configs/pax';
|
import { emptyAircraft } from '../../configs/shared';
|
||||||
import { Fuel, SharedConfig } 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 { ImportFlightPlan } from '../../utils/TFDISBImport';
|
||||||
import CGSelect from '../CGSelect/CGSelect';
|
import CGSelect from '../CGSelect/CGSelect';
|
||||||
import ActionBar from '../actionbar/ActionBar';
|
import ActionBar from '../actionbar/ActionBar';
|
||||||
|
|
||||||
interface StationEntryProps {
|
interface SBEntryProps {
|
||||||
unit: 'kg' | 'lbs';
|
WASMData: WASMDataPax;
|
||||||
isER: boolean;
|
loadingState: LoadingState;
|
||||||
initialPayload: PayloadPax;
|
|
||||||
fuelLive: Fuel;
|
|
||||||
payloadLive: PayloadPax;
|
|
||||||
loadingState: 'preview' | 'accepted' | 'loaded';
|
|
||||||
username: string;
|
username: string;
|
||||||
setLoadingState: (newState: StationEntryProps['loadingState']) => void;
|
setLoadingState: (newState: LoadingState) => void;
|
||||||
updateView: (payload: PayloadPax) => void;
|
|
||||||
loadAircraft: () => void;
|
loadAircraft: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const SBEntryPax: FC<StationEntryProps> = ({
|
const SBEntryPax: FC<SBEntryProps> = ({ WASMData, loadingState, username, setLoadingState, loadAircraft }) => {
|
||||||
unit,
|
const [CGTarget, setCGTarget] = useState(WASMData.targetPayload.CGTarget);
|
||||||
isER,
|
const [fuel, setFuel] = useState(Math.round(WASMData.livePayload.fuel));
|
||||||
initialPayload,
|
const [fuelEnabled, setFuelEnabled] = useState(true);
|
||||||
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 [SBPlan, setSBPlan] = useState<any>();
|
const [SBPlan, setSBPlan] = useState<any>();
|
||||||
const [SBInFlight, setSBInFlight] = useState(false);
|
const [SBInFlight, setSBInFlight] = useState(false);
|
||||||
|
|
||||||
const _ZFW = () => {
|
const numPax = useRef(0);
|
||||||
if (loadingState !== 'loaded') return ZFW;
|
const cargo = useRef(0);
|
||||||
|
|
||||||
return Math.round(
|
const ZFW = () => {
|
||||||
payloadLive.empty +
|
if (loadingState !== 'loaded') return Math.round(WASMData.targetPayload.total);
|
||||||
payloadLive.pilot +
|
|
||||||
payloadLive.firstOfficer +
|
return Math.round(WASMData.livePayload.total);
|
||||||
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 ZFWValid = () => {
|
const ZFWValid = () => {
|
||||||
return _ZFW() <= PaxConfig.maxZWF[unit];
|
return ZFW() <= WASMData.limits.maxZFW;
|
||||||
};
|
};
|
||||||
|
|
||||||
const GW = () => {
|
const GW = () => {
|
||||||
return fuel + _ZFW();
|
return fuel + ZFW();
|
||||||
};
|
};
|
||||||
const GWValid = () => {
|
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) => {
|
const handleInput = (input: string, maxValue: number, setter: (value: number) => void) => {
|
||||||
@ -125,49 +57,89 @@ const SBEntryPax: FC<StationEntryProps> = ({
|
|||||||
const handleSB = async () => {
|
const handleSB = async () => {
|
||||||
setSBInFlight(true);
|
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') {
|
if (SBResponse.type === 'error') {
|
||||||
console.error('TODO: ERROR', SBResponse.message);
|
console.error('TODO: ERROR', SBResponse.message);
|
||||||
setSBInFlight(false);
|
setSBInFlight(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const __ZFW = Math.round(
|
cargo.current = parseFloat(SBResponse.message.cargo) ?? 0;
|
||||||
PaxConfig.weights.base[unit].total +
|
numPax.current = parseInt(SBResponse.message.pax) ?? 0;
|
||||||
(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;
|
|
||||||
|
|
||||||
updateView(
|
updateData();
|
||||||
PaxConfig.distribute(__ZFW, targetZFWCG, payloadLive.empty, fuelLive, unit, isER, SBResponse.message.pax)
|
|
||||||
);
|
|
||||||
|
|
||||||
setSBPlan(SBResponse.message);
|
setSBPlan(SBResponse.message);
|
||||||
setZFW(__ZFW);
|
setFuel(parseFloat(SBResponse.message.fuel) ?? 0);
|
||||||
setFuel(_fuel);
|
|
||||||
setSBInFlight(false);
|
setSBInFlight(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(
|
useEffect(
|
||||||
() =>
|
() =>
|
||||||
setFuel((prev) =>
|
setFuel((prev) => {
|
||||||
prev > (isER ? SharedConfig.maxFuel.er[unit] : SharedConfig.maxFuel.norm[unit])
|
if (prev > WASMData.limits.maxFuel) return WASMData.limits.maxFuel;
|
||||||
? isER
|
return prev;
|
||||||
? SharedConfig.maxFuel.er[unit]
|
}),
|
||||||
: SharedConfig.maxFuel.norm[unit]
|
[WASMData.userData.isER]
|
||||||
: prev
|
|
||||||
),
|
|
||||||
[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 (
|
return (
|
||||||
<>
|
<>
|
||||||
|
<div className="block flex w-full flex-col opacity-100 transition-opacity duration-150 ease-linear mb-4">
|
||||||
|
<div className="relative flex w-full items-center justify-between rounded-md bg-zinc-600 p-2 px-4">
|
||||||
|
<label>Fuel ({WASMData.userData.isImperial ? 'lbs' : 'kg'})</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
placeholder=""
|
||||||
|
className={`w-1/2 rounded-lg border border-white bg-zinc-700 px-3 py-2 text-right`}
|
||||||
|
value={fuel}
|
||||||
|
onChange={(e) => handleInput(e.target.value, WASMData.limits.maxFuel, setFuel)}
|
||||||
|
disabled={loadingState !== 'preview'}
|
||||||
|
/>
|
||||||
|
<button
|
||||||
|
className="middle none center rounded-lg bg-green-600 px-6 py-3 font-sans text-xs font-bold uppercase text-white shadow-md shadow-green-500/20 transition-all hover:shadow-lg hover:shadow-green-500/40 focus:opacity-[0.85] focus:shadow-none active:opacity-[0.85] active:shadow-none disabled:pointer-events-none disabled:opacity-50 disabled:shadow-none"
|
||||||
|
data-ripple-light="true"
|
||||||
|
onClick={() => {
|
||||||
|
SimVar.SetSimVarValue(
|
||||||
|
'L:MD11_EFB_PAYLOAD_FUEL',
|
||||||
|
'lbs',
|
||||||
|
WASMData.userData.isImperial ? fuel : fuel * 2.20462262185
|
||||||
|
);
|
||||||
|
SimVar.SetSimVarValue('L:MD11_EFB_READ_READY', 'bool', true);
|
||||||
|
setFuelEnabled(false);
|
||||||
|
}}
|
||||||
|
disabled={loadingState !== 'preview' || !fuelEnabled}
|
||||||
|
>
|
||||||
|
Load Fuel
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div className="block flex w-full flex-col opacity-100 transition-opacity duration-150 ease-linear mb-4">
|
<div className="block flex w-full flex-col opacity-100 transition-opacity duration-150 ease-linear mb-4">
|
||||||
<div className="relative flex w-full items-center justify-between rounded-t-md bg-zinc-600 p-2 px-4">
|
<div className="relative flex w-full items-center justify-between rounded-t-md bg-zinc-600 p-2 px-4">
|
||||||
<label>Planned ZFW ({unit})</label>
|
<label>Planned ZFW ({WASMData.userData.isImperial ? 'lbs' : 'kg'})</label>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
placeholder=""
|
placeholder=""
|
||||||
@ -177,7 +149,7 @@ const SBEntryPax: FC<StationEntryProps> = ({
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="relative flex w-full items-center justify-between bg-zinc-700 p-2 px-4">
|
<div className="relative flex w-full items-center justify-between bg-zinc-700 p-2 px-4">
|
||||||
<label>Planned ZFW ({unit})</label>
|
<label>Planned ZFW ({WASMData.userData.isImperial ? 'lbs' : 'kg'})</label>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
placeholder=""
|
placeholder=""
|
||||||
@ -188,22 +160,24 @@ const SBEntryPax: FC<StationEntryProps> = ({
|
|||||||
</div>
|
</div>
|
||||||
<div className="relative flex w-full items-center justify-between rounded-b-md bg-zinc-600 p-2 px-4">
|
<div className="relative flex w-full items-center justify-between rounded-b-md bg-zinc-600 p-2 px-4">
|
||||||
<label>
|
<label>
|
||||||
Target ZFWCG ({SharedConfig.CGLimits.min} - {SharedConfig.CGLimits.max})
|
Target ZFWCG ({WASMData.limits.minCG} - {WASMData.limits.maxCG})
|
||||||
</label>
|
</label>
|
||||||
<CGSelect
|
<CGSelect
|
||||||
value={targetZFWCG}
|
minCG={WASMData.limits.minCG}
|
||||||
|
maxCG={WASMData.limits.maxCG}
|
||||||
|
value={CGTarget}
|
||||||
disabled={loadingState !== 'preview'}
|
disabled={loadingState !== 'preview'}
|
||||||
increase={() =>
|
increase={() =>
|
||||||
setTargetZFWCG((prev) => {
|
setCGTarget((prev) => {
|
||||||
const _new = prev + 0.1;
|
const _new = prev + 0.1;
|
||||||
updateView(PaxConfig.distribute(ZFW, _new, payloadLive.empty, fuelLive, unit, isER));
|
updateData(_new);
|
||||||
return _new;
|
return _new;
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
decrease={() =>
|
decrease={() =>
|
||||||
setTargetZFWCG((prev) => {
|
setCGTarget((prev) => {
|
||||||
const _new = prev - 0.1;
|
const _new = prev - 0.1;
|
||||||
updateView(PaxConfig.distribute(ZFW, _new, payloadLive.empty, fuelLive, unit, isER));
|
updateData(_new);
|
||||||
return _new;
|
return _new;
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -211,53 +185,22 @@ const SBEntryPax: FC<StationEntryProps> = ({
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="block flex w-full flex-col opacity-100 transition-opacity duration-150 ease-linear mb-4">
|
|
||||||
<div className="relative flex w-full items-center justify-between rounded-md bg-zinc-600 p-2 px-4">
|
|
||||||
<label>Fuel ({unit})</label>
|
|
||||||
<input
|
|
||||||
type="text"
|
|
||||||
placeholder=""
|
|
||||||
className={`w-1/2 rounded-lg border border-white bg-zinc-700 px-3 py-2 text-right`}
|
|
||||||
value={fuel}
|
|
||||||
onChange={(e) =>
|
|
||||||
handleInput(
|
|
||||||
e.target.value,
|
|
||||||
isER ? SharedConfig.maxFuel.er[unit] : SharedConfig.maxFuel.norm[unit],
|
|
||||||
setFuel
|
|
||||||
)
|
|
||||||
}
|
|
||||||
disabled
|
|
||||||
/>
|
|
||||||
<button
|
|
||||||
className="middle none center rounded-lg bg-green-600 px-6 py-3 font-sans text-xs font-bold uppercase text-white shadow-md shadow-green-500/20 transition-all hover:shadow-lg hover:shadow-green-500/40 focus:opacity-[0.85] focus:shadow-none active:opacity-[0.85] active:shadow-none disabled:pointer-events-none disabled:opacity-50 disabled:shadow-none"
|
|
||||||
data-ripple-light="true"
|
|
||||||
onClick={() => {
|
|
||||||
SimVar.SetSimVarValue('L:MD11_EFB_PAYLOAD_FUEL', 'lbs', unit === 'kg' ? fuel * 2.20462262185 : fuel);
|
|
||||||
SimVar.SetSimVarValue('L:MD11_EFB_READ_READY', 'bool', true);
|
|
||||||
}}
|
|
||||||
disabled={loadingState !== 'preview' || SBInFlight}
|
|
||||||
>
|
|
||||||
Load Fuel
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="block flex w-full flex-col opacity-100 transition-opacity duration-150 ease-linear mb-4">
|
<div className="block flex w-full flex-col opacity-100 transition-opacity duration-150 ease-linear mb-4">
|
||||||
<div className="relative flex w-full items-center justify-between rounded-t-md bg-zinc-600 p-2 px-4">
|
<div className="relative flex w-full items-center justify-between rounded-t-md bg-zinc-600 p-2 px-4">
|
||||||
<label>
|
<label>
|
||||||
{loadingState !== 'loaded' ? 'Expected' : 'Actual'} ZFW ({unit})
|
{loadingState !== 'loaded' ? 'Expected' : 'Actual'} ZFW ({WASMData.userData.isImperial ? 'lbs' : 'kg'})
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
placeholder=""
|
placeholder=""
|
||||||
className={`w-1/2 rounded-lg border ${ZFWValid() ? 'border-white' : 'border-red-500 text-red-500'} bg-zinc-700 px-3 py-2 text-right`}
|
className={`w-1/2 rounded-lg border ${ZFWValid() ? 'border-white' : 'border-red-500 text-red-500'} bg-zinc-700 px-3 py-2 text-right`}
|
||||||
disabled
|
disabled
|
||||||
value={_ZFW()}
|
value={ZFW()}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="relative flex w-full items-center justify-between rounded-b-md bg-zinc-700 p-2 px-4">
|
<div className="relative flex w-full items-center justify-between rounded-b-md bg-zinc-700 p-2 px-4">
|
||||||
<label>
|
<label>
|
||||||
{loadingState !== 'loaded' ? 'Expected' : 'Actual'} GW ({unit})
|
{loadingState !== 'loaded' ? 'Expected' : 'Actual'} GW ({WASMData.userData.isImperial ? 'lbs' : 'kg'})
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
@ -272,7 +215,6 @@ const SBEntryPax: FC<StationEntryProps> = ({
|
|||||||
<ActionBar
|
<ActionBar
|
||||||
loadingState={loadingState}
|
loadingState={loadingState}
|
||||||
acceptDisabled={!GWValid() || SBInFlight}
|
acceptDisabled={!GWValid() || SBInFlight}
|
||||||
//TODO: Make GSX optional (accepted state for NON GSX)
|
|
||||||
accept={() => setLoadingState('loaded')}
|
accept={() => setLoadingState('loaded')}
|
||||||
reject={() => setLoadingState('preview')}
|
reject={() => setLoadingState('preview')}
|
||||||
importSB={handleSB}
|
importSB={handleSB}
|
||||||
@ -284,7 +226,7 @@ const SBEntryPax: FC<StationEntryProps> = ({
|
|||||||
unload={() => {
|
unload={() => {
|
||||||
setLoadingState('preview');
|
setLoadingState('preview');
|
||||||
|
|
||||||
PaxConfig.unload(unit, isER);
|
emptyAircraft();
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
|
|||||||
@ -1,7 +1,8 @@
|
|||||||
import { FC } from 'react';
|
import { FC } from 'react';
|
||||||
|
import { LoadingState } from '../../types/general';
|
||||||
|
|
||||||
interface ActionBarProps {
|
interface ActionBarProps {
|
||||||
loadingState: 'preview' | 'accepted' | 'loaded';
|
loadingState: LoadingState;
|
||||||
acceptDisabled: boolean;
|
acceptDisabled: boolean;
|
||||||
accept: () => void;
|
accept: () => void;
|
||||||
reject: () => void;
|
reject: () => void;
|
||||||
|
|||||||
@ -1,6 +1,9 @@
|
|||||||
import { FC, useState } from 'react';
|
import { FC, useState } from 'react';
|
||||||
|
import { LoadingState } from '../../types/general';
|
||||||
import { WASMDataPax } from '../../types/WASMData';
|
import { WASMDataPax } from '../../types/WASMData';
|
||||||
import Profile from '../profile/Profile';
|
import Profile from '../profile/Profile';
|
||||||
|
import SBEntryPax from '../SBEntry/SBEntryPax';
|
||||||
|
import StationEntryPax from '../stationEntry/StationEntryPax';
|
||||||
import Tabbar from '../tabbar/Tabbar';
|
import Tabbar from '../tabbar/Tabbar';
|
||||||
import ZFWEntryPax from '../zfwEntry/ZFWEntryPax';
|
import ZFWEntryPax from '../zfwEntry/ZFWEntryPax';
|
||||||
|
|
||||||
@ -11,24 +14,24 @@ interface PaxProps {
|
|||||||
|
|
||||||
const Pax: FC<PaxProps> = ({ WASMData, username }) => {
|
const Pax: FC<PaxProps> = ({ WASMData, username }) => {
|
||||||
const [selectedTab, setSelectedTab] = useState(0);
|
const [selectedTab, setSelectedTab] = useState(0);
|
||||||
const [loadingState, setLoadingState] = useState<'preview' | 'accepted' | 'loaded'>('preview');
|
const [loadingState, setLoadingState] = useState<LoadingState>('preview');
|
||||||
|
|
||||||
const upper1 = (overrideState: 'preview' | 'accepted' | 'loaded' = loadingState) => {
|
const upper1 = (overrideState: LoadingState = loadingState) => {
|
||||||
if (overrideState !== 'loaded') return WASMData.targetPayload.business1;
|
if (overrideState !== 'loaded') return WASMData.targetPayload.business1;
|
||||||
|
|
||||||
return WASMData.livePayload.business1;
|
return WASMData.livePayload.business1;
|
||||||
};
|
};
|
||||||
const upper2 = (overrideState: 'preview' | 'accepted' | 'loaded' = loadingState) => {
|
const upper2 = (overrideState: LoadingState = loadingState) => {
|
||||||
if (overrideState !== 'loaded') return WASMData.targetPayload.business2;
|
if (overrideState !== 'loaded') return WASMData.targetPayload.business2;
|
||||||
|
|
||||||
return WASMData.livePayload.business2;
|
return WASMData.livePayload.business2;
|
||||||
};
|
};
|
||||||
const upper3 = (overrideState: 'preview' | 'accepted' | 'loaded' = loadingState) => {
|
const upper3 = (overrideState: LoadingState = loadingState) => {
|
||||||
if (overrideState !== 'loaded') return WASMData.targetPayload.economy1;
|
if (overrideState !== 'loaded') return WASMData.targetPayload.economy1;
|
||||||
|
|
||||||
return WASMData.livePayload.economy1;
|
return WASMData.livePayload.economy1;
|
||||||
};
|
};
|
||||||
const upper4 = (overrideState: 'preview' | 'accepted' | 'loaded' = loadingState) => {
|
const upper4 = (overrideState: LoadingState = loadingState) => {
|
||||||
if (overrideState !== 'loaded') return WASMData.targetPayload.economy2;
|
if (overrideState !== 'loaded') return WASMData.targetPayload.economy2;
|
||||||
|
|
||||||
return WASMData.livePayload.economy2;
|
return WASMData.livePayload.economy2;
|
||||||
@ -100,58 +103,37 @@ const Pax: FC<PaxProps> = ({ WASMData, username }) => {
|
|||||||
selectedTab={selectedTab}
|
selectedTab={selectedTab}
|
||||||
setSelectedTab={setSelectedTab}
|
setSelectedTab={setSelectedTab}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{/*
|
|
||||||
{username && selectedTab === 0 && (
|
{username && selectedTab === 0 && (
|
||||||
<SBEntryPax
|
<SBEntryPax
|
||||||
unit={unit}
|
WASMData={WASMData}
|
||||||
isER={isER}
|
|
||||||
initialPayload={payload}
|
|
||||||
fuelLive={fuelLive}
|
|
||||||
payloadLive={payloadLive}
|
|
||||||
loadingState={loadingState}
|
loadingState={loadingState}
|
||||||
username={username}
|
username={username}
|
||||||
setLoadingState={setLoadingState}
|
setLoadingState={setLoadingState}
|
||||||
updateView={(_payload) => {
|
|
||||||
setPayload(_payload);
|
|
||||||
}}
|
|
||||||
loadAircraft={() => {
|
loadAircraft={() => {
|
||||||
PaxConfig.setBaseWeight(unit, isER);
|
console.log('SET WEIGHT SB');
|
||||||
PaxConfig.setWeights(payload, unit);
|
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
*/}
|
|
||||||
{((username && selectedTab === 1) || (!username && selectedTab === 0)) && (
|
{((username && selectedTab === 1) || (!username && selectedTab === 0)) && (
|
||||||
<ZFWEntryPax
|
<ZFWEntryPax
|
||||||
WASMData={WASMData}
|
WASMData={WASMData}
|
||||||
loadingState={loadingState}
|
loadingState={loadingState}
|
||||||
setLoadingState={setLoadingState}
|
setLoadingState={setLoadingState}
|
||||||
loadAircraft={() => {
|
loadAircraft={() => {
|
||||||
console.log('SET WEIGHT');
|
console.log('SET WEIGHT ZFW');
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{/*
|
|
||||||
{((username && selectedTab === 2) || (!username && selectedTab === 1)) && (
|
{((username && selectedTab === 2) || (!username && selectedTab === 1)) && (
|
||||||
<StationEntryPax
|
<StationEntryPax
|
||||||
unit={unit}
|
WASMData={WASMData}
|
||||||
isER={isER}
|
|
||||||
initialPayload={payload}
|
|
||||||
fuelLive={fuelLive}
|
|
||||||
payloadLive={payloadLive}
|
|
||||||
loadingState={loadingState}
|
loadingState={loadingState}
|
||||||
setLoadingState={setLoadingState}
|
setLoadingState={setLoadingState}
|
||||||
updateView={(_payload) => {
|
|
||||||
setPayload(_payload);
|
|
||||||
}}
|
|
||||||
loadAircraft={() => {
|
loadAircraft={() => {
|
||||||
PaxConfig.setBaseWeight(unit, isER);
|
console.log('SET WEIGHT STATIONS');
|
||||||
PaxConfig.setWeights(payload, unit);
|
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
*/}
|
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,117 +1,40 @@
|
|||||||
import { FC, useEffect, useState } from 'react';
|
import { FC, useEffect, useState } from 'react';
|
||||||
import { PaxConfig, PayloadPax } from '../../configs/pax';
|
import { emptyAircraft } from '../../configs/shared';
|
||||||
import { Fuel, SharedConfig } from '../../configs/shared';
|
import { COHERENT_COMBUS_WASM_CALL, COMM_BUS_UPDATE_TARGET_EVENT } from '../../constants';
|
||||||
|
import { LoadingState } from '../../types/general';
|
||||||
|
import { WASMDataPax } from '../../types/WASMData';
|
||||||
import ActionBar from '../actionbar/ActionBar';
|
import ActionBar from '../actionbar/ActionBar';
|
||||||
|
|
||||||
interface StationEntryProps {
|
interface StationEntryProps {
|
||||||
unit: 'kg' | 'lbs';
|
WASMData: WASMDataPax;
|
||||||
isER: boolean;
|
loadingState: LoadingState;
|
||||||
initialPayload: PayloadPax;
|
setLoadingState: (newState: LoadingState) => void;
|
||||||
fuelLive: Fuel;
|
|
||||||
payloadLive: PayloadPax;
|
|
||||||
loadingState: 'preview' | 'accepted' | 'loaded';
|
|
||||||
setLoadingState: (newState: StationEntryProps['loadingState']) => void;
|
|
||||||
updateView: (payload: PayloadPax) => void;
|
|
||||||
loadAircraft: () => void;
|
loadAircraft: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const StationEntryPax: FC<StationEntryProps> = ({
|
const StationEntryPax: FC<StationEntryProps> = ({ WASMData, loadingState, setLoadingState, loadAircraft }) => {
|
||||||
unit,
|
const [business1, setBusiness1] = useState(WASMData.targetPayload.business1);
|
||||||
isER,
|
const [business2, setBusiness2] = useState(WASMData.targetPayload.business2);
|
||||||
initialPayload,
|
const [economy1, setEconomy1] = useState(WASMData.targetPayload.economy1);
|
||||||
fuelLive,
|
const [economy2, setEconomy2] = useState(WASMData.targetPayload.economy2);
|
||||||
payloadLive,
|
const [forwardCargo, setForwardCargo] = useState(WASMData.targetPayload.forwardCargo);
|
||||||
loadingState,
|
const [rearCargo, setRearCargo] = useState(WASMData.targetPayload.rearCargo);
|
||||||
setLoadingState,
|
const [fuel, setFuel] = useState(Math.round(WASMData.livePayload.fuel));
|
||||||
updateView,
|
const [fuelEnabled, setFuelEnabled] = useState(true);
|
||||||
loadAircraft,
|
|
||||||
}) => {
|
|
||||||
const [business1, setBusiness1] = useState(
|
|
||||||
PaxConfig.weightToPax(
|
|
||||||
initialPayload.business1Left + initialPayload.business1Center + initialPayload.business1Right,
|
|
||||||
unit
|
|
||||||
)
|
|
||||||
);
|
|
||||||
const [business2, setBusiness2] = useState(
|
|
||||||
PaxConfig.weightToPax(
|
|
||||||
initialPayload.business2Left + initialPayload.business2Center + initialPayload.business2Right,
|
|
||||||
unit
|
|
||||||
)
|
|
||||||
);
|
|
||||||
const [economy1, setEconomy1] = useState(
|
|
||||||
PaxConfig.weightToPax(
|
|
||||||
initialPayload.economy1Left + initialPayload.economy1Center + initialPayload.economy1Right,
|
|
||||||
unit
|
|
||||||
)
|
|
||||||
);
|
|
||||||
const [economy2, setEconomy2] = useState(
|
|
||||||
PaxConfig.weightToPax(
|
|
||||||
initialPayload.economy2Left + initialPayload.economy2Center + initialPayload.economy2Right,
|
|
||||||
unit
|
|
||||||
)
|
|
||||||
);
|
|
||||||
const [forwardCargo, setForwardCargo] = useState(initialPayload.forwardCargo);
|
|
||||||
const [rearCargo, setRearCargo] = useState(initialPayload.rearCargo);
|
|
||||||
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 = () => {
|
const ZFW = () => {
|
||||||
if (loadingState !== 'loaded')
|
if (loadingState !== 'loaded') return Math.round(WASMData.targetPayload.total);
|
||||||
return Math.round(
|
|
||||||
(business1 + business2 + economy1 + economy2) * PaxConfig.weights.pax[unit] +
|
|
||||||
forwardCargo +
|
|
||||||
rearCargo +
|
|
||||||
PaxConfig.weights.base[unit].total +
|
|
||||||
(isER ? SharedConfig.erExtraWeight[unit] * 2 : 0) +
|
|
||||||
payloadLive.empty
|
|
||||||
);
|
|
||||||
|
|
||||||
return Math.round(
|
return Math.round(WASMData.livePayload.total);
|
||||||
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 ZFWValid = () => {
|
const ZFWValid = () => {
|
||||||
return ZFW() <= PaxConfig.maxZWF[unit];
|
return ZFW() <= WASMData.limits.maxZFW;
|
||||||
};
|
};
|
||||||
|
|
||||||
const GW = () => {
|
const GW = () => {
|
||||||
return fuel + ZFW();
|
return fuel + ZFW();
|
||||||
};
|
};
|
||||||
const GWValid = () => {
|
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) => {
|
const handleInput = (input: string, maxValue: number, setter: (value: number) => void) => {
|
||||||
@ -128,37 +51,67 @@ const StationEntryPax: FC<StationEntryProps> = ({
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => _updateView(), [business1, business2, economy1, economy2, forwardCargo, rearCargo]);
|
useEffect(() => updateData(), [business1, business2, economy1, economy2, forwardCargo, rearCargo]);
|
||||||
useEffect(
|
useEffect(
|
||||||
() =>
|
() =>
|
||||||
setFuel((prev) =>
|
setFuel((prev) => {
|
||||||
prev > (isER ? SharedConfig.maxFuel.er[unit] : SharedConfig.maxFuel.norm[unit])
|
if (prev > WASMData.limits.maxFuel) return WASMData.limits.maxFuel;
|
||||||
? isER
|
return prev;
|
||||||
? SharedConfig.maxFuel.er[unit]
|
}),
|
||||||
: SharedConfig.maxFuel.norm[unit]
|
[WASMData.userData.isER]
|
||||||
: prev
|
|
||||||
),
|
|
||||||
[isER]
|
|
||||||
);
|
);
|
||||||
|
useEffect(() => {
|
||||||
|
setFuelEnabled(Math.round(WASMData.livePayload.fuel) === fuel);
|
||||||
|
}, [WASMData.livePayload.fuel]);
|
||||||
|
|
||||||
const _updateView = () => {
|
const updateData = () => {
|
||||||
const payload = PaxConfig.generateDistribution(
|
Coherent.call(
|
||||||
payloadLive.empty,
|
COHERENT_COMBUS_WASM_CALL,
|
||||||
|
COMM_BUS_UPDATE_TARGET_EVENT,
|
||||||
|
JSON.stringify({
|
||||||
|
mode: 2,
|
||||||
business1,
|
business1,
|
||||||
business2,
|
business2,
|
||||||
economy1,
|
economy1,
|
||||||
economy2,
|
economy2,
|
||||||
forwardCargo,
|
forwardCargo,
|
||||||
rearCargo,
|
rearCargo,
|
||||||
unit,
|
})
|
||||||
isER
|
|
||||||
);
|
);
|
||||||
|
|
||||||
updateView(payload);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
<div className="block flex w-full flex-col opacity-100 transition-opacity duration-150 ease-linear mb-4">
|
||||||
|
<div className="relative flex w-full items-center justify-between rounded-md bg-zinc-600 p-2 px-4">
|
||||||
|
<label>Fuel ({WASMData.userData.isImperial ? 'lbs' : 'kg'})</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
placeholder=""
|
||||||
|
className={`w-1/2 rounded-lg border border-white bg-zinc-700 px-3 py-2 text-right`}
|
||||||
|
value={fuel}
|
||||||
|
onChange={(e) => handleInput(e.target.value, WASMData.limits.maxFuel, setFuel)}
|
||||||
|
disabled={loadingState !== 'preview'}
|
||||||
|
/>
|
||||||
|
<button
|
||||||
|
className="middle none center rounded-lg bg-green-600 px-6 py-3 font-sans text-xs font-bold uppercase text-white shadow-md shadow-green-500/20 transition-all hover:shadow-lg hover:shadow-green-500/40 focus:opacity-[0.85] focus:shadow-none active:opacity-[0.85] active:shadow-none disabled:pointer-events-none disabled:opacity-50 disabled:shadow-none"
|
||||||
|
data-ripple-light="true"
|
||||||
|
onClick={() => {
|
||||||
|
SimVar.SetSimVarValue(
|
||||||
|
'L:MD11_EFB_PAYLOAD_FUEL',
|
||||||
|
'lbs',
|
||||||
|
WASMData.userData.isImperial ? fuel : fuel * 2.20462262185
|
||||||
|
);
|
||||||
|
SimVar.SetSimVarValue('L:MD11_EFB_READ_READY', 'bool', true);
|
||||||
|
setFuelEnabled(false);
|
||||||
|
}}
|
||||||
|
disabled={loadingState !== 'preview' || !fuelEnabled}
|
||||||
|
>
|
||||||
|
Load Fuel
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div className="block flex w-full flex-col opacity-100 transition-opacity duration-150 ease-linear mb-4">
|
<div className="block flex w-full flex-col opacity-100 transition-opacity duration-150 ease-linear mb-4">
|
||||||
<div className="relative flex w-full items-center justify-between rounded-t-md bg-zinc-600 p-2 px-4">
|
<div className="relative flex w-full items-center justify-between rounded-t-md bg-zinc-600 p-2 px-4">
|
||||||
<label>Business</label>
|
<label>Business</label>
|
||||||
@ -167,7 +120,7 @@ const StationEntryPax: FC<StationEntryProps> = ({
|
|||||||
placeholder=""
|
placeholder=""
|
||||||
className="w-1/2 rounded-lg border border-white bg-zinc-700 px-3 py-2 text-right focus:border-blue-600 focus:ring-blue-600"
|
className="w-1/2 rounded-lg border border-white bg-zinc-700 px-3 py-2 text-right focus:border-blue-600 focus:ring-blue-600"
|
||||||
value={business1}
|
value={business1}
|
||||||
onChange={(e) => handleInput(e.target.value, PaxConfig.stationMax.business1, setBusiness1)}
|
onChange={(e) => handleInput(e.target.value, WASMData.limits.business1, setBusiness1)}
|
||||||
disabled={loadingState !== 'preview'}
|
disabled={loadingState !== 'preview'}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@ -178,7 +131,7 @@ const StationEntryPax: FC<StationEntryProps> = ({
|
|||||||
placeholder=""
|
placeholder=""
|
||||||
className="w-1/2 rounded-lg border border-white bg-zinc-700 px-3 py-2 text-right focus:border-blue-600 focus:ring-blue-600"
|
className="w-1/2 rounded-lg border border-white bg-zinc-700 px-3 py-2 text-right focus:border-blue-600 focus:ring-blue-600"
|
||||||
value={business2}
|
value={business2}
|
||||||
onChange={(e) => handleInput(e.target.value, PaxConfig.stationMax.business2, setBusiness2)}
|
onChange={(e) => handleInput(e.target.value, WASMData.limits.business2, setBusiness2)}
|
||||||
disabled={loadingState !== 'preview'}
|
disabled={loadingState !== 'preview'}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@ -189,7 +142,7 @@ const StationEntryPax: FC<StationEntryProps> = ({
|
|||||||
placeholder=""
|
placeholder=""
|
||||||
className="w-1/2 rounded-lg border border-white bg-zinc-700 px-3 py-2 text-right focus:border-blue-600 focus:ring-blue-600"
|
className="w-1/2 rounded-lg border border-white bg-zinc-700 px-3 py-2 text-right focus:border-blue-600 focus:ring-blue-600"
|
||||||
value={economy1}
|
value={economy1}
|
||||||
onChange={(e) => handleInput(e.target.value, PaxConfig.stationMax.economy1, setEconomy1)}
|
onChange={(e) => handleInput(e.target.value, WASMData.limits.economy1, setEconomy1)}
|
||||||
disabled={loadingState !== 'preview'}
|
disabled={loadingState !== 'preview'}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@ -200,69 +153,38 @@ const StationEntryPax: FC<StationEntryProps> = ({
|
|||||||
placeholder=""
|
placeholder=""
|
||||||
className="w-1/2 rounded-lg border border-white bg-zinc-700 px-3 py-2 text-right focus:border-blue-600 focus:ring-blue-600"
|
className="w-1/2 rounded-lg border border-white bg-zinc-700 px-3 py-2 text-right focus:border-blue-600 focus:ring-blue-600"
|
||||||
value={economy2}
|
value={economy2}
|
||||||
onChange={(e) => handleInput(e.target.value, PaxConfig.stationMax.economy2, setEconomy2)}
|
onChange={(e) => handleInput(e.target.value, WASMData.limits.economy2, setEconomy2)}
|
||||||
disabled={loadingState !== 'preview'}
|
disabled={loadingState !== 'preview'}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="relative flex w-full items-center justify-between bg-zinc-600 p-2 px-4">
|
<div className="relative flex w-full items-center justify-between bg-zinc-600 p-2 px-4">
|
||||||
<label>Forward Cargo ({unit})</label>
|
<label>Forward Cargo ({WASMData.userData.isImperial ? 'lbs' : 'kg'})</label>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
placeholder=""
|
placeholder=""
|
||||||
className="w-1/2 rounded-lg border border-white bg-zinc-700 px-3 py-2 text-right focus:border-blue-600 focus:ring-blue-600"
|
className="w-1/2 rounded-lg border border-white bg-zinc-700 px-3 py-2 text-right focus:border-blue-600 focus:ring-blue-600"
|
||||||
value={forwardCargo}
|
value={forwardCargo}
|
||||||
onChange={(e) => handleInput(e.target.value, SharedConfig.stationMax.forward[unit], setForwardCargo)}
|
onChange={(e) => handleInput(e.target.value, WASMData.limits.forwardCargo, setForwardCargo)}
|
||||||
disabled={loadingState !== 'preview'}
|
disabled={loadingState !== 'preview'}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="relative flex w-full items-center justify-between rounded-b-md bg-zinc-700 p-2 px-4">
|
<div className="relative flex w-full items-center justify-between rounded-b-md bg-zinc-700 p-2 px-4">
|
||||||
<label>Aft Cargo ({unit})</label>
|
<label>Aft Cargo ({WASMData.userData.isImperial ? 'lbs' : 'kg'})</label>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
placeholder=""
|
placeholder=""
|
||||||
className="w-1/2 rounded-lg border border-white bg-zinc-700 px-3 py-2 text-right focus:border-blue-600 focus:ring-blue-600"
|
className="w-1/2 rounded-lg border border-white bg-zinc-700 px-3 py-2 text-right focus:border-blue-600 focus:ring-blue-600"
|
||||||
value={rearCargo}
|
value={rearCargo}
|
||||||
onChange={(e) => handleInput(e.target.value, SharedConfig.stationMax.rear[unit], setRearCargo)}
|
onChange={(e) => handleInput(e.target.value, WASMData.limits.rearCargo, setRearCargo)}
|
||||||
disabled={loadingState !== 'preview'}
|
disabled={loadingState !== 'preview'}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="block flex w-full flex-col opacity-100 transition-opacity duration-150 ease-linear mb-4">
|
|
||||||
<div className="relative flex w-full items-center justify-between rounded-md bg-zinc-600 p-2 px-4">
|
|
||||||
<label>Fuel ({unit})</label>
|
|
||||||
<input
|
|
||||||
type="text"
|
|
||||||
placeholder=""
|
|
||||||
className={`w-1/2 rounded-lg border border-white bg-zinc-700 px-3 py-2 text-right`}
|
|
||||||
value={fuel}
|
|
||||||
onChange={(e) =>
|
|
||||||
handleInput(
|
|
||||||
e.target.value,
|
|
||||||
isER ? SharedConfig.maxFuel.er[unit] : SharedConfig.maxFuel.norm[unit],
|
|
||||||
setFuel
|
|
||||||
)
|
|
||||||
}
|
|
||||||
disabled={loadingState !== 'preview'}
|
|
||||||
/>
|
|
||||||
<button
|
|
||||||
className="middle none center rounded-lg bg-green-600 px-6 py-3 font-sans text-xs font-bold uppercase text-white shadow-md shadow-green-500/20 transition-all hover:shadow-lg hover:shadow-green-500/40 focus:opacity-[0.85] focus:shadow-none active:opacity-[0.85] active:shadow-none disabled:pointer-events-none disabled:opacity-50 disabled:shadow-none"
|
|
||||||
data-ripple-light="true"
|
|
||||||
onClick={() => {
|
|
||||||
SimVar.SetSimVarValue('L:MD11_EFB_PAYLOAD_FUEL', 'lbs', unit === 'kg' ? fuel * 2.20462262185 : fuel);
|
|
||||||
SimVar.SetSimVarValue('L:MD11_EFB_READ_READY', 'bool', true);
|
|
||||||
}}
|
|
||||||
disabled={loadingState !== 'preview'}
|
|
||||||
>
|
|
||||||
Load Fuel
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="block flex w-full flex-col opacity-100 transition-opacity duration-150 ease-linear mb-4">
|
<div className="block flex w-full flex-col opacity-100 transition-opacity duration-150 ease-linear mb-4">
|
||||||
<div className="relative flex w-full items-center justify-between rounded-t-md bg-zinc-600 p-2 px-4">
|
<div className="relative flex w-full items-center justify-between rounded-t-md bg-zinc-600 p-2 px-4">
|
||||||
<label>
|
<label>
|
||||||
{loadingState !== 'loaded' ? 'Expected' : 'Actual'} ZFW ({unit})
|
{loadingState !== 'loaded' ? 'Expected' : 'Actual'} ZFW ({WASMData.userData.isImperial ? 'lbs' : 'kg'})
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
@ -274,7 +196,7 @@ const StationEntryPax: FC<StationEntryProps> = ({
|
|||||||
</div>
|
</div>
|
||||||
<div className="relative flex w-full items-center justify-between rounded-b-md bg-zinc-700 p-2 px-4">
|
<div className="relative flex w-full items-center justify-between rounded-b-md bg-zinc-700 p-2 px-4">
|
||||||
<label>
|
<label>
|
||||||
{loadingState !== 'loaded' ? 'Expected' : 'Actual'} GW ({unit})
|
{loadingState !== 'loaded' ? 'Expected' : 'Actual'} GW ({WASMData.userData.isImperial ? 'lbs' : 'kg'})
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
@ -299,7 +221,7 @@ const StationEntryPax: FC<StationEntryProps> = ({
|
|||||||
unload={() => {
|
unload={() => {
|
||||||
setLoadingState('preview');
|
setLoadingState('preview');
|
||||||
|
|
||||||
PaxConfig.unload(unit, isER);
|
emptyAircraft();
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
|
|||||||
@ -2,32 +2,33 @@ import { FC, useEffect, useState } from 'react';
|
|||||||
import { emptyAircraft } from '../../configs/shared';
|
import { emptyAircraft } from '../../configs/shared';
|
||||||
import { COHERENT_COMBUS_WASM_CALL, COMM_BUS_UPDATE_TARGET_EVENT } from '../../constants';
|
import { COHERENT_COMBUS_WASM_CALL, COMM_BUS_UPDATE_TARGET_EVENT } from '../../constants';
|
||||||
import { WASMDataPax } from '../../types/WASMData';
|
import { WASMDataPax } from '../../types/WASMData';
|
||||||
|
import { LoadingState } from '../../types/general';
|
||||||
import CGSelect from '../CGSelect/CGSelect';
|
import CGSelect from '../CGSelect/CGSelect';
|
||||||
import ActionBar from '../actionbar/ActionBar';
|
import ActionBar from '../actionbar/ActionBar';
|
||||||
|
|
||||||
interface StationEntryProps {
|
interface ZFWEntryProps {
|
||||||
WASMData: WASMDataPax;
|
WASMData: WASMDataPax;
|
||||||
loadingState: 'preview' | 'accepted' | 'loaded';
|
loadingState: LoadingState;
|
||||||
setLoadingState: (newState: StationEntryProps['loadingState']) => void;
|
setLoadingState: (newState: LoadingState) => void;
|
||||||
loadAircraft: () => void;
|
loadAircraft: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ZFWEntryPax: FC<StationEntryProps> = ({ WASMData, loadingState, setLoadingState, loadAircraft }) => {
|
const ZFWEntryPax: FC<ZFWEntryProps> = ({ WASMData, loadingState, setLoadingState, loadAircraft }) => {
|
||||||
const [targetZFWCG, setTargetZFWCG] = useState(WASMData.targetPayload.ZFWCG);
|
const [CGTarget, setCGTarget] = useState(WASMData.targetPayload.CGTarget);
|
||||||
const [fuel, setFuel] = useState(Math.round(WASMData.livePayload.fuel));
|
const [fuel, setFuel] = useState(Math.round(WASMData.livePayload.fuel));
|
||||||
const [ZFW, setZFW] = 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 = () => {
|
const ZFW = () => {
|
||||||
if (loadingState !== 'loaded') return ZFW;
|
if (loadingState !== 'loaded') return ZFWTarget;
|
||||||
|
|
||||||
return Math.round(WASMData.livePayload.total);
|
return Math.round(WASMData.livePayload.total);
|
||||||
};
|
};
|
||||||
const ZFWValid = () => {
|
const ZFWValid = () => {
|
||||||
return _ZFW() <= WASMData.limits.maxZFW;
|
return ZFW() <= WASMData.limits.maxZFW;
|
||||||
};
|
};
|
||||||
|
|
||||||
const GW = () => {
|
const GW = () => {
|
||||||
return fuel + _ZFW();
|
return fuel + ZFW();
|
||||||
};
|
};
|
||||||
const GWValid = () => {
|
const GWValid = () => {
|
||||||
return GW() <= WASMData.limits.maxTOW;
|
return GW() <= WASMData.limits.maxTOW;
|
||||||
@ -51,24 +52,24 @@ const ZFWEntryPax: FC<StationEntryProps> = ({ WASMData, loadingState, setLoading
|
|||||||
|
|
||||||
const converted = parseInt(input);
|
const converted = parseInt(input);
|
||||||
if (converted) {
|
if (converted) {
|
||||||
if (converted < 0) setZFW(Math.round(WASMData.targetPayload.empty + WASMData.targetPayload.crew));
|
if (converted < 0) setZFWTarget(Math.round(WASMData.targetPayload.empty + WASMData.targetPayload.crew));
|
||||||
else if (converted > WASMData.limits.maxZFW) setZFW(WASMData.limits.maxZFW);
|
else if (converted > WASMData.limits.maxZFW) setZFWTarget(WASMData.limits.maxZFW);
|
||||||
else setZFW(converted);
|
else setZFWTarget(converted);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const handleBlur = (input: string) => {
|
const handleBlur = (input: string) => {
|
||||||
const minZFW = Math.round(WASMData.targetPayload.empty + WASMData.targetPayload.crew);
|
const minZFW = Math.round(WASMData.targetPayload.empty + WASMData.targetPayload.crew);
|
||||||
|
|
||||||
if (!input) {
|
if (!input) {
|
||||||
setZFW(minZFW);
|
setZFWTarget(minZFW);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const converted = parseInt(input);
|
const converted = parseInt(input);
|
||||||
if (converted) {
|
if (converted) {
|
||||||
if (converted < minZFW) setZFW(minZFW);
|
if (converted < minZFW) setZFWTarget(minZFW);
|
||||||
else if (converted > WASMData.limits.maxZFW) setZFW(WASMData.limits.maxZFW);
|
else if (converted > WASMData.limits.maxZFW) setZFWTarget(WASMData.limits.maxZFW);
|
||||||
else setZFW(converted);
|
else setZFWTarget(converted);
|
||||||
}
|
}
|
||||||
|
|
||||||
updateData(converted);
|
updateData(converted);
|
||||||
@ -82,61 +83,24 @@ const ZFWEntryPax: FC<StationEntryProps> = ({ WASMData, loadingState, setLoading
|
|||||||
}),
|
}),
|
||||||
[WASMData.userData.isER]
|
[WASMData.userData.isER]
|
||||||
);
|
);
|
||||||
|
useEffect(() => {
|
||||||
|
setFuelEnabled(Math.round(WASMData.livePayload.fuel) === fuel);
|
||||||
|
}, [WASMData.livePayload.fuel]);
|
||||||
|
|
||||||
const updateData = (ZFWTarget?: number, CGTarget?: number) => {
|
const updateData = (_ZFWTarget?: number, _CGTarget?: number) => {
|
||||||
Coherent.call(
|
Coherent.call(
|
||||||
COHERENT_COMBUS_WASM_CALL,
|
COHERENT_COMBUS_WASM_CALL,
|
||||||
COMM_BUS_UPDATE_TARGET_EVENT,
|
COMM_BUS_UPDATE_TARGET_EVENT,
|
||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
mode: 1,
|
mode: 1,
|
||||||
ZFWTarget: ZFWTarget ?? ZFW,
|
ZFWTarget: _ZFWTarget ?? ZFWTarget,
|
||||||
CGTarget: CGTarget ?? targetZFWCG,
|
CGTarget: _CGTarget ?? CGTarget,
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="block flex w-full flex-col opacity-100 transition-opacity duration-150 ease-linear mb-4">
|
|
||||||
<div className="relative flex w-full items-center justify-between rounded-t-md bg-zinc-600 p-2 px-4">
|
|
||||||
<label>Target ZFW ({WASMData.userData.isImperial ? 'lbs' : 'kg'})</label>
|
|
||||||
<input
|
|
||||||
type="text"
|
|
||||||
placeholder=""
|
|
||||||
className="w-1/2 rounded-lg border border-white bg-zinc-700 px-3 py-2 text-right focus:border-blue-600 focus:ring-blue-600"
|
|
||||||
value={ZFW}
|
|
||||||
onChange={(e) => handleInputZFW(e.target.value)}
|
|
||||||
onBlur={(e) => handleBlur(e.target.value)}
|
|
||||||
disabled={loadingState !== 'preview'}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className="relative flex w-full items-center justify-between rounded-b-md bg-zinc-700 p-2 px-4">
|
|
||||||
<label>
|
|
||||||
Target ZFWCG ({WASMData.limits.minCG} - {WASMData.limits.maxCG})
|
|
||||||
</label>
|
|
||||||
<CGSelect
|
|
||||||
minCG={WASMData.limits.minCG}
|
|
||||||
maxCG={WASMData.limits.maxCG}
|
|
||||||
value={targetZFWCG}
|
|
||||||
disabled={loadingState !== 'preview'}
|
|
||||||
increase={() =>
|
|
||||||
setTargetZFWCG((prev) => {
|
|
||||||
const _new = prev + 0.1;
|
|
||||||
updateData(undefined, _new);
|
|
||||||
return _new;
|
|
||||||
})
|
|
||||||
}
|
|
||||||
decrease={() =>
|
|
||||||
setTargetZFWCG((prev) => {
|
|
||||||
const _new = prev - 0.1;
|
|
||||||
updateData(undefined, _new);
|
|
||||||
return _new;
|
|
||||||
})
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="block flex w-full flex-col opacity-100 transition-opacity duration-150 ease-linear mb-4">
|
<div className="block flex w-full flex-col opacity-100 transition-opacity duration-150 ease-linear mb-4">
|
||||||
<div className="relative flex w-full items-center justify-between rounded-md bg-zinc-600 p-2 px-4">
|
<div className="relative flex w-full items-center justify-between rounded-md bg-zinc-600 p-2 px-4">
|
||||||
<label>Fuel ({WASMData.userData.isImperial ? 'lbs' : 'kg'})</label>
|
<label>Fuel ({WASMData.userData.isImperial ? 'lbs' : 'kg'})</label>
|
||||||
@ -158,14 +122,55 @@ const ZFWEntryPax: FC<StationEntryProps> = ({ WASMData, loadingState, setLoading
|
|||||||
WASMData.userData.isImperial ? fuel : fuel * 2.20462262185
|
WASMData.userData.isImperial ? fuel : fuel * 2.20462262185
|
||||||
);
|
);
|
||||||
SimVar.SetSimVarValue('L:MD11_EFB_READ_READY', 'bool', true);
|
SimVar.SetSimVarValue('L:MD11_EFB_READ_READY', 'bool', true);
|
||||||
|
setFuelEnabled(false);
|
||||||
}}
|
}}
|
||||||
disabled={loadingState !== 'preview' || fuel === Math.round(WASMData.livePayload.fuel)}
|
disabled={loadingState !== 'preview' || !fuelEnabled}
|
||||||
>
|
>
|
||||||
Load Fuel
|
Load Fuel
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div className="block flex w-full flex-col opacity-100 transition-opacity duration-150 ease-linear mb-4">
|
||||||
|
<div className="relative flex w-full items-center justify-between rounded-t-md bg-zinc-600 p-2 px-4">
|
||||||
|
<label>Target ZFW ({WASMData.userData.isImperial ? 'lbs' : 'kg'})</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
placeholder=""
|
||||||
|
className="w-1/2 rounded-lg border border-white bg-zinc-700 px-3 py-2 text-right focus:border-blue-600 focus:ring-blue-600"
|
||||||
|
value={ZFWTarget}
|
||||||
|
onChange={(e) => handleInputZFW(e.target.value)}
|
||||||
|
onBlur={(e) => handleBlur(e.target.value)}
|
||||||
|
disabled={loadingState !== 'preview'}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="relative flex w-full items-center justify-between rounded-b-md bg-zinc-700 p-2 px-4">
|
||||||
|
<label>
|
||||||
|
Target ZFWCG ({WASMData.limits.minCG} - {WASMData.limits.maxCG})
|
||||||
|
</label>
|
||||||
|
<CGSelect
|
||||||
|
minCG={WASMData.limits.minCG}
|
||||||
|
maxCG={WASMData.limits.maxCG}
|
||||||
|
value={CGTarget}
|
||||||
|
disabled={loadingState !== 'preview'}
|
||||||
|
increase={() =>
|
||||||
|
setCGTarget((prev) => {
|
||||||
|
const _new = prev + 0.1;
|
||||||
|
updateData(undefined, _new);
|
||||||
|
return _new;
|
||||||
|
})
|
||||||
|
}
|
||||||
|
decrease={() =>
|
||||||
|
setCGTarget((prev) => {
|
||||||
|
const _new = prev - 0.1;
|
||||||
|
updateData(undefined, _new);
|
||||||
|
return _new;
|
||||||
|
})
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div className="block flex w-full flex-col opacity-100 transition-opacity duration-150 ease-linear mb-4">
|
<div className="block flex w-full flex-col opacity-100 transition-opacity duration-150 ease-linear mb-4">
|
||||||
<div className="relative flex w-full items-center justify-between rounded-t-md bg-zinc-600 p-2 px-4">
|
<div className="relative flex w-full items-center justify-between rounded-t-md bg-zinc-600 p-2 px-4">
|
||||||
<label>
|
<label>
|
||||||
@ -176,7 +181,7 @@ const ZFWEntryPax: FC<StationEntryProps> = ({ WASMData, loadingState, setLoading
|
|||||||
placeholder=""
|
placeholder=""
|
||||||
className={`w-1/2 rounded-lg border ${ZFWValid() ? 'border-white' : 'border-red-500 text-red-500'} bg-zinc-700 px-3 py-2 text-right`}
|
className={`w-1/2 rounded-lg border ${ZFWValid() ? 'border-white' : 'border-red-500 text-red-500'} bg-zinc-700 px-3 py-2 text-right`}
|
||||||
disabled
|
disabled
|
||||||
value={_ZFW()}
|
value={ZFW()}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="relative flex w-full items-center justify-between rounded-b-md bg-zinc-700 p-2 px-4">
|
<div className="relative flex w-full items-center justify-between rounded-b-md bg-zinc-700 p-2 px-4">
|
||||||
|
|||||||
@ -1,5 +1,8 @@
|
|||||||
export const COHERENT_COMBUS_WASM_CALL = 'COMM_BUS_WASM_CALLBACK';
|
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_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';
|
export const COMM_BUS_UPDATE_TARGET_EVENT = 'khofmann_tfdi_md-11_load_manager_update_target';
|
||||||
|
|
||||||
|
|||||||
17
PackageSources/js-bundle/src/types/WASMData.d.ts
vendored
17
PackageSources/js-bundle/src/types/WASMData.d.ts
vendored
@ -6,7 +6,14 @@ export interface WASMDataPax {
|
|||||||
limits: LimitsPax;
|
limits: LimitsPax;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface TargetPayloadPax {
|
interface TargetPayload {
|
||||||
|
CGTarget: number;
|
||||||
|
ZFWCG: number;
|
||||||
|
TOCG: number;
|
||||||
|
total: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface TargetPayloadPax extends TargetPayload {
|
||||||
empty: number;
|
empty: number;
|
||||||
crew: number;
|
crew: number;
|
||||||
business1: number;
|
business1: number;
|
||||||
@ -15,16 +22,13 @@ interface TargetPayloadPax {
|
|||||||
economy2: number;
|
economy2: number;
|
||||||
forwardCargo: number;
|
forwardCargo: number;
|
||||||
rearCargo: number;
|
rearCargo: number;
|
||||||
ZFWCG: number;
|
|
||||||
TOCG: number;
|
|
||||||
total: number;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
interface LivePayloadPax extends TargetPayloadPax {
|
interface LivePayloadPax extends TargetPayloadPax {
|
||||||
fuel: number;
|
fuel: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface TargetPayloadF {
|
interface TargetPayloadF extends TargetPayload {
|
||||||
empty: number;
|
empty: number;
|
||||||
crew: number;
|
crew: number;
|
||||||
upper1: number;
|
upper1: number;
|
||||||
@ -33,9 +37,6 @@ interface TargetPayloadF {
|
|||||||
upper4: number;
|
upper4: number;
|
||||||
lowerForward: number;
|
lowerForward: number;
|
||||||
lowerRear: number;
|
lowerRear: number;
|
||||||
ZFWCG: number;
|
|
||||||
TOCG: number;
|
|
||||||
total: number;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
interface LivePayloadF extends TargetPayloadF {
|
interface LivePayloadF extends TargetPayloadF {
|
||||||
|
|||||||
1
PackageSources/js-bundle/src/types/general.d.ts
vendored
Normal file
1
PackageSources/js-bundle/src/types/general.d.ts
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
export type LoadingState = 'preview' | 'accepted' | 'loaded';
|
||||||
@ -1,11 +0,0 @@
|
|||||||
import { CSSProperties, DOMAttributes, ReactNode } from 'react';
|
|
||||||
|
|
||||||
type CustomElement<T> = Partial<T & DOMAttributes<T> & { children: ReactNode }>;
|
|
||||||
|
|
||||||
declare global {
|
|
||||||
namespace JSX {
|
|
||||||
interface IntrinsicElements {
|
|
||||||
['virtual-scroll']: CustomElement<{ class?: string; direction: 'x' | 'y'; style?: CSSProperties }>;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,6 +1,3 @@
|
|||||||
import { PaxConfig } from '../configs/pax';
|
|
||||||
import { SharedConfig } from '../configs/shared';
|
|
||||||
|
|
||||||
const getSimBriefFlightPlan = async (simBriefUsername: string) => {
|
const getSimBriefFlightPlan = async (simBriefUsername: string) => {
|
||||||
const flightPlanURL = `https://www.simbrief.com/api/xml.fetcher.php?username=${simBriefUsername}&json=1`;
|
const flightPlanURL = `https://www.simbrief.com/api/xml.fetcher.php?username=${simBriefUsername}&json=1`;
|
||||||
let response: Response;
|
let response: Response;
|
||||||
@ -19,9 +16,10 @@ const getSimBriefFlightPlan = async (simBriefUsername: string) => {
|
|||||||
|
|
||||||
export const ImportFlightPlan = async (
|
export const ImportFlightPlan = async (
|
||||||
username: string,
|
username: string,
|
||||||
config: typeof PaxConfig,
|
maxZFW: number,
|
||||||
unit: 'kg' | 'lbs',
|
maxTOW: number,
|
||||||
isER: boolean
|
maxFuel: number,
|
||||||
|
isImperial: boolean
|
||||||
) => {
|
) => {
|
||||||
const flightPlan = await getSimBriefFlightPlan(username);
|
const flightPlan = await getSimBriefFlightPlan(username);
|
||||||
if (!flightPlan.success) {
|
if (!flightPlan.success) {
|
||||||
@ -41,23 +39,17 @@ export const ImportFlightPlan = async (
|
|||||||
}
|
}
|
||||||
|
|
||||||
let convFactor = 1;
|
let convFactor = 1;
|
||||||
if (data.params.units === 'kgs' && unit === 'lbs') convFactor = 2.20462262185;
|
if (data.params.units === 'kgs' && isImperial) convFactor = 2.20462262185;
|
||||||
if (data.params.units === 'lbs' && unit === 'kg') convFactor = 1 / 2.20462262185;
|
if (data.params.units === 'lbs' && !isImperial) convFactor = 1 / 2.20462262185;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
type: 'data',
|
type: 'data',
|
||||||
message: {
|
message: {
|
||||||
plannedZFW: Math.min(config.maxZWF[unit], Math.round(data.weights.est_zfw * convFactor)),
|
plannedZFW: Math.min(maxZFW, Math.round(data.weights.est_zfw * convFactor)),
|
||||||
plannedGW: Math.min(
|
plannedGW: Math.min(maxTOW, Math.round(data.weights.est_ramp * convFactor)),
|
||||||
isER ? SharedConfig.maxTOW.er[unit] : SharedConfig.maxTOW.norm[unit],
|
|
||||||
Math.round(data.weights.est_ramp * convFactor)
|
|
||||||
),
|
|
||||||
pax: data.weights.pax_count_actual,
|
pax: data.weights.pax_count_actual,
|
||||||
cargo: Math.round(data.weights.freight_added * convFactor),
|
cargo: Math.round(data.weights.freight_added * convFactor),
|
||||||
fuel: Math.min(
|
fuel: Math.min(maxFuel, Math.round(data.fuel.plan_ramp * convFactor)),
|
||||||
isER ? SharedConfig.maxFuel.er[unit] : SharedConfig.maxFuel.norm[unit],
|
|
||||||
Math.round(data.fuel.plan_ramp * convFactor)
|
|
||||||
),
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@ -35,7 +35,7 @@ extern "C" MSFS_CALLBACK void module_init(void) {
|
|||||||
targetFPayloadData = new fPayloadData_t();
|
targetFPayloadData = new fPayloadData_t();
|
||||||
liveFuelData = new FuelData_t();
|
liveFuelData = new FuelData_t();
|
||||||
|
|
||||||
targetFPayloadData->ZFWCG = targetPaxPayloadData->ZFWCG = 21;
|
targetFPayloadData->CGTarget = targetPaxPayloadData->CGTarget = 21;
|
||||||
|
|
||||||
#pragma region SimConnect
|
#pragma region SimConnect
|
||||||
|
|
||||||
@ -454,13 +454,14 @@ int receiveData(const char* buf) {
|
|||||||
double CGTarget = document["CGTarget"].GetDouble();
|
double CGTarget = document["CGTarget"].GetDouble();
|
||||||
|
|
||||||
if (UserData->isCargo) {
|
if (UserData->isCargo) {
|
||||||
|
targetPaxPayloadData->CGTarget = CGTarget;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (!document.HasMember("numPax")) return -1;
|
if (!document.HasMember("numPax")) return -1;
|
||||||
unsigned short numPax = document["numPax"].GetInt();
|
unsigned short numPax = document["numPax"].GetInt();
|
||||||
|
|
||||||
distribute(targetPaxPayloadData, liveFuelData, numPax, cargo, CGTarget, UserData->isImperial);
|
targetPaxPayloadData->CGTarget = CGTarget;
|
||||||
|
distribute(targetPaxPayloadData, liveFuelData, numPax, cargo, UserData->isImperial);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -471,10 +472,11 @@ int receiveData(const char* buf) {
|
|||||||
double CGTarget = document["CGTarget"].GetDouble();
|
double CGTarget = document["CGTarget"].GetDouble();
|
||||||
|
|
||||||
if (UserData->isCargo) {
|
if (UserData->isCargo) {
|
||||||
|
targetPaxPayloadData->CGTarget = CGTarget;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
distribute(targetPaxPayloadData, liveFuelData, ZFWTarget, CGTarget, UserData->isImperial);
|
targetPaxPayloadData->CGTarget = CGTarget;
|
||||||
|
distribute(targetPaxPayloadData, liveFuelData, ZFWTarget, UserData->isImperial);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -495,7 +497,6 @@ int receiveData(const char* buf) {
|
|||||||
targetPaxPayloadData->rearCargo = document["rearCargo"].GetDouble();
|
targetPaxPayloadData->rearCargo = document["rearCargo"].GetDouble();
|
||||||
|
|
||||||
generatePayload(targetPaxPayloadData, UserData->isImperial);
|
generatePayload(targetPaxPayloadData, UserData->isImperial);
|
||||||
normalisePayload(targetPaxPayloadData, UserData->isImperial);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -557,8 +558,8 @@ void sendData () {
|
|||||||
// CGs
|
// CGs
|
||||||
//TODO: Enable for F
|
//TODO: Enable for F
|
||||||
//calculateCGs(liveFPayloadData, liveFuelData, &liveFPayloadData->ZFWCG, &liveFPayloadData->TOCG, true);
|
//calculateCGs(liveFPayloadData, liveFuelData, &liveFPayloadData->ZFWCG, &liveFPayloadData->TOCG, true);
|
||||||
targetPayload.AddMember("ZFWCG", liveFPayloadData->ZFWCG, allocator);
|
livePayload.AddMember("ZFWCG", liveFPayloadData->ZFWCG, allocator);
|
||||||
targetPayload.AddMember("TOCG", liveFPayloadData->TOCG, allocator);
|
livePayload.AddMember("TOCG", liveFPayloadData->TOCG, allocator);
|
||||||
}
|
}
|
||||||
// Pax only (converted to passengers)
|
// Pax only (converted to passengers)
|
||||||
else {
|
else {
|
||||||
@ -613,6 +614,7 @@ void sendData () {
|
|||||||
targetPayload.AddMember("lowerForward", targetFPayloadData->lowerForward, allocator);
|
targetPayload.AddMember("lowerForward", targetFPayloadData->lowerForward, allocator);
|
||||||
targetPayload.AddMember("lowerRear", targetFPayloadData->lowerRear, allocator);
|
targetPayload.AddMember("lowerRear", targetFPayloadData->lowerRear, allocator);
|
||||||
targetPayload.AddMember("total", targetFPayloadData->total, allocator);
|
targetPayload.AddMember("total", targetFPayloadData->total, allocator);
|
||||||
|
targetPayload.AddMember("CGTarget", targetFPayloadData->CGTarget, allocator);
|
||||||
// CGs
|
// CGs
|
||||||
//TODO: Enable for F
|
//TODO: Enable for F
|
||||||
//calculateCGs(targetFPayloadData, liveFuelData, &targetFPayloadData->ZFWCG, &targetFPayloadData->TOCG, UserData->isImperial);
|
//calculateCGs(targetFPayloadData, liveFuelData, &targetFPayloadData->ZFWCG, &targetFPayloadData->TOCG, UserData->isImperial);
|
||||||
@ -632,6 +634,7 @@ void sendData () {
|
|||||||
targetPayload.AddMember("forwardCargo", targetPaxPayloadData->forwardCargo, allocator);
|
targetPayload.AddMember("forwardCargo", targetPaxPayloadData->forwardCargo, allocator);
|
||||||
targetPayload.AddMember("rearCargo", targetPaxPayloadData->rearCargo, allocator);
|
targetPayload.AddMember("rearCargo", targetPaxPayloadData->rearCargo, allocator);
|
||||||
targetPayload.AddMember("total", targetPaxPayloadData->total, allocator);
|
targetPayload.AddMember("total", targetPaxPayloadData->total, allocator);
|
||||||
|
targetPayload.AddMember("CGTarget", targetPaxPayloadData->CGTarget, allocator);
|
||||||
// CGs
|
// CGs
|
||||||
calculateCGs(targetPaxPayloadData, liveFuelData, &targetPaxPayloadData->ZFWCG, &targetPaxPayloadData->TOCG, UserData->isImperial);
|
calculateCGs(targetPaxPayloadData, liveFuelData, &targetPaxPayloadData->ZFWCG, &targetPaxPayloadData->TOCG, UserData->isImperial);
|
||||||
targetPayload.AddMember("ZFWCG", targetPaxPayloadData->ZFWCG, allocator);
|
targetPayload.AddMember("ZFWCG", targetPaxPayloadData->ZFWCG, allocator);
|
||||||
|
|||||||
@ -1,18 +1,18 @@
|
|||||||
#include "pax.h"
|
#include "pax.h"
|
||||||
|
|
||||||
//ZFW Entry, fill pax first (pax+bag), rest is cargo
|
//ZFW Entry, fill pax first (pax+bag), rest is cargo
|
||||||
void distribute(paxPayloadData_t* const targetPayload, const FuelData_t* const fuel, const double ZFWTarget, const double CGTarget, const bool isImperial) {
|
void distribute(paxPayloadData_t* const targetPayload, const FuelData_t* const fuel, const double ZFWTarget, const bool isImperial) {
|
||||||
// Find payload, num pax and extra cargo
|
// Find payload, num pax and extra cargo
|
||||||
double payload = ZFWTarget - targetPayload->empty - targetPayload->pilot - targetPayload->firstOfficer - targetPayload->engineer -
|
double payload = ZFWTarget - targetPayload->empty - targetPayload->pilot - targetPayload->firstOfficer - targetPayload->engineer -
|
||||||
targetPayload->cabinCrewFront - targetPayload->cabinCrewRear - targetPayload->leftAux - targetPayload->rightAux;
|
targetPayload->cabinCrewFront - targetPayload->cabinCrewRear - targetPayload->leftAux - targetPayload->rightAux;
|
||||||
unsigned short numPax = std::max(0.0, std::min((double)MAX_PAX, floor(payload / (PAX_WEIGHT(isImperial) + BAG_WEIGHT(isImperial)))));
|
unsigned short numPax = std::max(0.0, std::min((double)MAX_PAX, floor(payload / (PAX_WEIGHT(isImperial) + BAG_WEIGHT(isImperial)))));
|
||||||
unsigned int cargo = round(payload - numPax * PAX_WEIGHT(isImperial) - numPax * BAG_WEIGHT(isImperial));
|
unsigned int cargo = round(payload - numPax * PAX_WEIGHT(isImperial) - numPax * BAG_WEIGHT(isImperial));
|
||||||
|
|
||||||
distribute(targetPayload, fuel, numPax, cargo, CGTarget, isImperial);
|
distribute(targetPayload, fuel, numPax, cargo, isImperial);
|
||||||
}
|
}
|
||||||
|
|
||||||
//SimBrief Entry, SB pax count and total cargo
|
//SimBrief Entry, SB pax count and total cargo
|
||||||
void distribute(paxPayloadData_t* const targetPayload, const FuelData_t* const fuel, unsigned short numPax, unsigned int cargo, const double CGTarget, const bool isImperial) {
|
void distribute(paxPayloadData_t* const targetPayload, const FuelData_t* const fuel, unsigned short numPax, unsigned int cargo, const bool isImperial) {
|
||||||
// Clear
|
// Clear
|
||||||
targetPayload->paxCount.business1 = targetPayload->paxCount.business2 = targetPayload->paxCount.economy1 = targetPayload->paxCount.economy2 =
|
targetPayload->paxCount.business1 = targetPayload->paxCount.business2 = targetPayload->paxCount.economy1 = targetPayload->paxCount.economy2 =
|
||||||
targetPayload->paxCount.total = 0;
|
targetPayload->paxCount.total = 0;
|
||||||
@ -108,7 +108,7 @@ void distribute(paxPayloadData_t* const targetPayload, const FuelData_t* const f
|
|||||||
calculateCGs(targetPayload, fuel, &targetPayload->ZFWCG, &targetPayload->TOCG, isImperial);
|
calculateCGs(targetPayload, fuel, &targetPayload->ZFWCG, &targetPayload->TOCG, isImperial);
|
||||||
|
|
||||||
// in front of target
|
// in front of target
|
||||||
if (targetPayload->ZFWCG < CGTarget - CG_TOLERANCE) {
|
if (targetPayload->ZFWCG < targetPayload->CGTarget - CG_TOLERANCE) {
|
||||||
if (targetPayload->paxCount.business1 > 0) {
|
if (targetPayload->paxCount.business1 > 0) {
|
||||||
targetPayload->paxCount.business1--;
|
targetPayload->paxCount.business1--;
|
||||||
}
|
}
|
||||||
@ -136,7 +136,7 @@ void distribute(paxPayloadData_t* const targetPayload, const FuelData_t* const f
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// behind target
|
// behind target
|
||||||
else if (targetPayload->ZFWCG > CGTarget + CG_TOLERANCE) {
|
else if (targetPayload->ZFWCG > targetPayload->CGTarget + CG_TOLERANCE) {
|
||||||
if (targetPayload->paxCount.economy2 > 0) {
|
if (targetPayload->paxCount.economy2 > 0) {
|
||||||
targetPayload->paxCount.economy2--;
|
targetPayload->paxCount.economy2--;
|
||||||
}
|
}
|
||||||
@ -176,7 +176,7 @@ void distribute(paxPayloadData_t* const targetPayload, const FuelData_t* const f
|
|||||||
calculateCGs(targetPayload, fuel, &targetPayload->ZFWCG, &targetPayload->TOCG, isImperial);
|
calculateCGs(targetPayload, fuel, &targetPayload->ZFWCG, &targetPayload->TOCG, isImperial);
|
||||||
|
|
||||||
// in front of target
|
// in front of target
|
||||||
if (targetPayload->ZFWCG < CGTarget - CG_TOLERANCE) {
|
if (targetPayload->ZFWCG < targetPayload->CGTarget - CG_TOLERANCE) {
|
||||||
if (targetPayload->forwardCargo > 0 && targetPayload->rearCargo < MAX_REAR_CARGO(isImperial)) {
|
if (targetPayload->forwardCargo > 0 && targetPayload->rearCargo < MAX_REAR_CARGO(isImperial)) {
|
||||||
if (targetPayload->forwardCargo > BAG_WEIGHT(isImperial) &&
|
if (targetPayload->forwardCargo > BAG_WEIGHT(isImperial) &&
|
||||||
targetPayload->rearCargo < MAX_FRONT_CARGO(isImperial) - BAG_WEIGHT(isImperial)) {
|
targetPayload->rearCargo < MAX_FRONT_CARGO(isImperial) - BAG_WEIGHT(isImperial)) {
|
||||||
@ -193,7 +193,7 @@ void distribute(paxPayloadData_t* const targetPayload, const FuelData_t* const f
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// behind target
|
// behind target
|
||||||
else if (targetPayload->ZFWCG > CGTarget + CG_TOLERANCE) {
|
else if (targetPayload->ZFWCG > targetPayload->CGTarget + CG_TOLERANCE) {
|
||||||
if (targetPayload->rearCargo > 0 && targetPayload->forwardCargo < MAX_FRONT_CARGO(isImperial)) {
|
if (targetPayload->rearCargo > 0 && targetPayload->forwardCargo < MAX_FRONT_CARGO(isImperial)) {
|
||||||
if (targetPayload->rearCargo > BAG_WEIGHT(isImperial) &&
|
if (targetPayload->rearCargo > BAG_WEIGHT(isImperial) &&
|
||||||
targetPayload->forwardCargo < MAX_REAR_CARGO(isImperial) - BAG_WEIGHT(isImperial)) {
|
targetPayload->forwardCargo < MAX_REAR_CARGO(isImperial) - BAG_WEIGHT(isImperial)) {
|
||||||
@ -233,7 +233,7 @@ void generatePayload(paxPayloadData_t* const targetPayload, const bool isImperia
|
|||||||
|
|
||||||
// Normalise to Pounds
|
// Normalise to Pounds
|
||||||
// MANDATORY BEFORE SETTING WEIGHTS
|
// MANDATORY BEFORE SETTING WEIGHTS
|
||||||
// ENSURE ONLY EVER CALLED ONCE PER SET CYCLE
|
// USE ON COPY OF GLOBAL STATE ONLY
|
||||||
void normalisePayload(paxPayloadData_t* const targetPayload, const bool isImperial) {
|
void normalisePayload(paxPayloadData_t* const targetPayload, const bool isImperial) {
|
||||||
targetPayload->empty = TO_POUNDS(isImperial, targetPayload->empty);
|
targetPayload->empty = TO_POUNDS(isImperial, targetPayload->empty);
|
||||||
targetPayload->pilot = TO_POUNDS(isImperial, targetPayload->pilot);
|
targetPayload->pilot = TO_POUNDS(isImperial, targetPayload->pilot);
|
||||||
|
|||||||
@ -17,9 +17,9 @@
|
|||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
|
||||||
//ZFW Entry, fill pax first (pax+bag), rest is cargo
|
//ZFW Entry, fill pax first (pax+bag), rest is cargo
|
||||||
void distribute(paxPayloadData_t* const targetPayload, const FuelData_t* const fuel, const double ZFWTarget, const double CGTarget, bool isImperial);
|
void distribute(paxPayloadData_t* const targetPayload, const FuelData_t* const fuel, const double ZFWTarget, bool isImperial);
|
||||||
//SimBrief Entry, SB pax count and total cargo
|
//SimBrief Entry, SB pax count and total cargo
|
||||||
void distribute(paxPayloadData_t* const targetPayload, const FuelData_t* const fuel, unsigned short numPax, unsigned int cargo, const double CGTarget, bool isImperial);
|
void distribute(paxPayloadData_t* const targetPayload, const FuelData_t* const fuel, unsigned short numPax, unsigned int cargo, bool isImperial);
|
||||||
// Updates pax stations with their respective weights
|
// Updates pax stations with their respective weights
|
||||||
// Used internally and used for Station Entry (pax only, cargo is ste directly)
|
// Used internally and used for Station Entry (pax only, cargo is ste directly)
|
||||||
// STATION WEIGHTS ARE NOT NORMALISED TO POUNDS
|
// STATION WEIGHTS ARE NOT NORMALISED TO POUNDS
|
||||||
|
|||||||
@ -144,6 +144,7 @@ typedef struct {
|
|||||||
// Additional properties
|
// Additional properties
|
||||||
double empty;
|
double empty;
|
||||||
double total;
|
double total;
|
||||||
|
double CGTarget;
|
||||||
double ZFWCG;
|
double ZFWCG;
|
||||||
double TOCG;
|
double TOCG;
|
||||||
struct paxCount {
|
struct paxCount {
|
||||||
@ -176,6 +177,7 @@ typedef struct {
|
|||||||
// Additional properties
|
// Additional properties
|
||||||
double empty;
|
double empty;
|
||||||
double total;
|
double total;
|
||||||
|
double CGTarget;
|
||||||
double ZFWCG;
|
double ZFWCG;
|
||||||
double TOCG;
|
double TOCG;
|
||||||
} fPayloadData_t;
|
} fPayloadData_t;
|
||||||
|
|||||||
@ -10,12 +10,9 @@ Coherent.call("COMM_BUS_WASM_CALLBACK", "khofmann_tfdi_md-11_load_manager_update
|
|||||||
TODO:
|
TODO:
|
||||||
|
|
||||||
- JS
|
- JS
|
||||||
- Connect to WASM as Data Source (sans SB username)
|
- GSX State for displaying status fo prog. loading
|
||||||
- Setting target
|
- Persist SB data across page changes
|
||||||
- SB
|
|
||||||
- Stations
|
|
||||||
- GSX State?
|
|
||||||
- Duplicate Input pages for F
|
- Duplicate Input pages for F
|
||||||
- WASM
|
- WASM
|
||||||
- Setting of payload
|
- Setting of payload
|
||||||
- GSX synced setting
|
- GSX synced setting of payload
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user