Compare commits
14 Commits
0297cfb600
..
Panel
| Author | SHA1 | Date | |
|---|---|---|---|
| 80cb726501 | |||
| 2047c84d8d | |||
| 390edd29b8 | |||
| 4b60f8eec2 | |||
| 9da2abdad7 | |||
| cbd7d4e0ae | |||
| c394cd4d7b | |||
| f7304c5c7b | |||
| 8975ea17af | |||
| 896a459bba | |||
| 890622453e | |||
| ee46d0bff1 | |||
| 9224300c85 | |||
| a34c532484 |
+6
-1
@@ -4,5 +4,10 @@ PackageSources/js-bundle/__generated__
|
||||
PackageSources/js-bundle/.rollup.cache
|
||||
PackageSources/js-bundle/node_modules
|
||||
PackageSources/html_ui
|
||||
PackageSources/wasm-module/.vs
|
||||
PackageSources/wasm-module/MSFS
|
||||
PackageSources/wasm-module/x64
|
||||
|
||||
*.blend1
|
||||
*.blend1
|
||||
|
||||
PackageSources/SimObjects/Airplanes/**/panel/*.wasm
|
||||
@@ -35,6 +35,14 @@
|
||||
<AssetDir>PackageSources\load-manager-panel\</AssetDir>
|
||||
<OutputDir>InGamePanels\</OutputDir>
|
||||
</AssetGroup>
|
||||
<AssetGroup Name="md-11-panel-config">
|
||||
<Type>Copy</Type>
|
||||
<Flags>
|
||||
<FSXCompatibility>false</FSXCompatibility>
|
||||
</Flags>
|
||||
<AssetDir>PackageSources\SimObjects\Airplanes\</AssetDir>
|
||||
<OutputDir>SimObjects\Airplanes\</OutputDir>
|
||||
</AssetGroup>
|
||||
</AssetGroups>
|
||||
</AssetPackage>
|
||||
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
// Panel Configuration File
|
||||
// TFDi Design MD-11
|
||||
|
||||
[VCockpit01]
|
||||
size_mm=2048,2048
|
||||
visible=1
|
||||
pixel_size=2048,2048
|
||||
texture=$vc1
|
||||
background_color=0,0,0
|
||||
htmlgauge00=WasmInstrument/WasmInstrument.html?wasm_module=md11host.wasm&wasm_gauge=Core, 0,0,509,510
|
||||
htmlgauge01=WasmInstrument/WasmInstrument.html?wasm_module=md11host.wasm&wasm_gauge=DU1,0,0,508,508
|
||||
htmlgauge02=WasmInstrument/WasmInstrument.html?wasm_module=md11host.wasm&wasm_gauge=DU2,514,0,510,510
|
||||
htmlgauge03=WasmInstrument/WasmInstrument.html?wasm_module=md11host.wasm&wasm_gauge=DU3,1027,0,510,510
|
||||
htmlgauge04=WasmInstrument/WasmInstrument.html?wasm_module=md11host.wasm&wasm_gauge=DU4,1539,0,510,508
|
||||
htmlgauge05=WasmInstrument/WasmInstrument.html?wasm_module=md11host.wasm&wasm_gauge=DU5,0,513,511,509
|
||||
htmlgauge06=WasmInstrument/WasmInstrument.html?wasm_module=md11host.wasm&wasm_gauge=DU6,513,512,510,511
|
||||
htmlgauge07=WasmInstrument/WasmInstrument.html?wasm_module=md11host.wasm&wasm_gauge=LMCDU, 0,1046,333,287
|
||||
htmlgauge08=WasmInstrument/WasmInstrument.html?wasm_module=md11host.wasm&wasm_gauge=RMCDU,0,1386,334,288
|
||||
htmlgauge09=WasmInstrument/WasmInstrument.html?wasm_module=md11host.wasm&wasm_gauge=CMCDU,0,1728,333,285
|
||||
htmlgauge10=WasmInstrument/WasmInstrument.html?wasm_module=md11host.wasm&wasm_gauge=ISFD,1032,519,544,505
|
||||
//KH new gauge
|
||||
htmlgauge11=WasmInstrument/WasmInstrument.html?wasm_module=load-manager.wasm&wasm_gauge=Load_Manager,0,0,509,510
|
||||
|
||||
[VIEWS]
|
||||
VIEW_FORWARD_DIR=2.000, 0.000, 0.000
|
||||
|
||||
[Color]
|
||||
Day=255,255,255
|
||||
Night=255,255,255
|
||||
Luminous=201,64,64
|
||||
|
||||
[Vcockpit02]
|
||||
Background_color=0,0,0
|
||||
size_mm=1024,1024
|
||||
visible=1
|
||||
pixel_size=1024,1024
|
||||
texture=$vc2
|
||||
|
||||
htmlgauge00=WasmInstrument/WasmInstrument.html?wasm_module=md11host.wasm&wasm_gauge=AFS,3,0,1015,185
|
||||
htmlgauge01=WasmInstrument/WasmInstrument.html?wasm_module=md11host.wasm&wasm_gauge=FUEL,4,200,1016,196
|
||||
//above should actually be 3,192,1018,199 - moved due to visual offset
|
||||
|
||||
[Vcockpit03]
|
||||
Background_color=0,0,0
|
||||
size_mm=1024,1024
|
||||
visible=1
|
||||
pixel_size=1024,1024
|
||||
texture=$RADIOS_XPNDR
|
||||
|
||||
htmlgauge00=WasmInstrument/WasmInstrument.html?wasm_module=md11host.wasm&wasm_gauge=RADIOS_XPNDR,0,5,1019,295
|
||||
|
||||
[VCockpit04]
|
||||
Background_color=0,0,0
|
||||
size_mm=1536,1024
|
||||
visible=1
|
||||
pixel_size=1536,1024
|
||||
texture=$EFB
|
||||
|
||||
htmlgauge00=aircraft_efb/TFDi_MD11_efb/efb.html,0,0,1536,1024
|
||||
@@ -0,0 +1,59 @@
|
||||
// Panel Configuration File
|
||||
// TFDi Design MD-11
|
||||
|
||||
[VCockpit01]
|
||||
size_mm=2048,2048
|
||||
visible=1
|
||||
pixel_size=2048,2048
|
||||
texture=$vc1
|
||||
background_color=0,0,0
|
||||
htmlgauge00=WasmInstrument/WasmInstrument.html?wasm_module=md11host.wasm&wasm_gauge=Core, 0,0,509,510,PW
|
||||
htmlgauge01=WasmInstrument/WasmInstrument.html?wasm_module=md11host.wasm&wasm_gauge=DU1,0,0,508,508
|
||||
htmlgauge02=WasmInstrument/WasmInstrument.html?wasm_module=md11host.wasm&wasm_gauge=DU2,514,0,510,510
|
||||
htmlgauge03=WasmInstrument/WasmInstrument.html?wasm_module=md11host.wasm&wasm_gauge=DU3,1027,0,510,510
|
||||
htmlgauge04=WasmInstrument/WasmInstrument.html?wasm_module=md11host.wasm&wasm_gauge=DU4,1539,0,510,508
|
||||
htmlgauge05=WasmInstrument/WasmInstrument.html?wasm_module=md11host.wasm&wasm_gauge=DU5,0,513,511,509
|
||||
htmlgauge06=WasmInstrument/WasmInstrument.html?wasm_module=md11host.wasm&wasm_gauge=DU6,513,512,510,511
|
||||
htmlgauge07=WasmInstrument/WasmInstrument.html?wasm_module=md11host.wasm&wasm_gauge=LMCDU, 0,1046,333,287
|
||||
htmlgauge08=WasmInstrument/WasmInstrument.html?wasm_module=md11host.wasm&wasm_gauge=RMCDU,0,1386,334,288
|
||||
htmlgauge09=WasmInstrument/WasmInstrument.html?wasm_module=md11host.wasm&wasm_gauge=CMCDU,0,1728,333,285
|
||||
htmlgauge10=WasmInstrument/WasmInstrument.html?wasm_module=md11host.wasm&wasm_gauge=ISFD,1032,519,544,505
|
||||
//KH new gauge
|
||||
htmlgauge11=WasmInstrument/WasmInstrument.html?wasm_module=load-manager.wasm&wasm_gauge=Load_Manager,0,0,509,510
|
||||
|
||||
[VIEWS]
|
||||
VIEW_FORWARD_DIR=2.000, 0.000, 0.000
|
||||
|
||||
[Color]
|
||||
Day=255,255,255
|
||||
Night=255,255,255
|
||||
Luminous=201,64,64
|
||||
|
||||
[Vcockpit02]
|
||||
Background_color=0,0,0
|
||||
size_mm=1024,1024
|
||||
visible=1
|
||||
pixel_size=1024,1024
|
||||
texture=$vc2
|
||||
|
||||
htmlgauge00=WasmInstrument/WasmInstrument.html?wasm_module=md11host.wasm&wasm_gauge=AFS,3,0,1015,185
|
||||
htmlgauge01=WasmInstrument/WasmInstrument.html?wasm_module=md11host.wasm&wasm_gauge=FUEL,4,200,1016,196
|
||||
//above should actually be 3,192,1018,199 - moved due to visual offset
|
||||
|
||||
[Vcockpit03]
|
||||
Background_color=0,0,0
|
||||
size_mm=1024,1024
|
||||
visible=1
|
||||
pixel_size=1024,1024
|
||||
texture=$RADIOS_XPNDR
|
||||
|
||||
htmlgauge00=WasmInstrument/WasmInstrument.html?wasm_module=md11host.wasm&wasm_gauge=RADIOS_XPNDR,0,5,1019,295
|
||||
|
||||
[VCockpit04]
|
||||
Background_color=0,0,0
|
||||
size_mm=1536,1024
|
||||
visible=1
|
||||
pixel_size=1536,1024
|
||||
texture=$EFB
|
||||
|
||||
htmlgauge00=aircraft_efb/TFDi_MD11_efb/efb.html,0,0,1536,1024
|
||||
@@ -0,0 +1,59 @@
|
||||
// Panel Configuration File
|
||||
// TFDi Design MD-11
|
||||
|
||||
[VCockpit01]
|
||||
size_mm=2048,2048
|
||||
visible=1
|
||||
pixel_size=2048,2048
|
||||
texture=$vc1
|
||||
background_color=0,0,0
|
||||
htmlgauge00=WasmInstrument/WasmInstrument.html?wasm_module=md11host.wasm&wasm_gauge=Core, 0,0,509,510
|
||||
htmlgauge01=WasmInstrument/WasmInstrument.html?wasm_module=md11host.wasm&wasm_gauge=DU1,0,0,508,508
|
||||
htmlgauge02=WasmInstrument/WasmInstrument.html?wasm_module=md11host.wasm&wasm_gauge=DU2,514,0,510,510
|
||||
htmlgauge03=WasmInstrument/WasmInstrument.html?wasm_module=md11host.wasm&wasm_gauge=DU3,1027,0,510,510
|
||||
htmlgauge04=WasmInstrument/WasmInstrument.html?wasm_module=md11host.wasm&wasm_gauge=DU4,1539,0,510,508
|
||||
htmlgauge05=WasmInstrument/WasmInstrument.html?wasm_module=md11host.wasm&wasm_gauge=DU5,0,513,511,509
|
||||
htmlgauge06=WasmInstrument/WasmInstrument.html?wasm_module=md11host.wasm&wasm_gauge=DU6,513,512,510,511
|
||||
htmlgauge07=WasmInstrument/WasmInstrument.html?wasm_module=md11host.wasm&wasm_gauge=LMCDU, 0,1046,333,287
|
||||
htmlgauge08=WasmInstrument/WasmInstrument.html?wasm_module=md11host.wasm&wasm_gauge=RMCDU,0,1386,334,288
|
||||
htmlgauge09=WasmInstrument/WasmInstrument.html?wasm_module=md11host.wasm&wasm_gauge=CMCDU,0,1728,333,285
|
||||
htmlgauge10=WasmInstrument/WasmInstrument.html?wasm_module=md11host.wasm&wasm_gauge=ISFD,1032,519,544,505
|
||||
//KH new gauge
|
||||
htmlgauge11=WasmInstrument/WasmInstrument.html?wasm_module=load-manager.wasm&wasm_gauge=Load_Manager,0,0,509,510
|
||||
|
||||
[VIEWS]
|
||||
VIEW_FORWARD_DIR=2.000, 0.000, 0.000
|
||||
|
||||
[Color]
|
||||
Day=255,255,255
|
||||
Night=255,255,255
|
||||
Luminous=201,64,64
|
||||
|
||||
[Vcockpit02]
|
||||
Background_color=0,0,0
|
||||
size_mm=1024,1024
|
||||
visible=1
|
||||
pixel_size=1024,1024
|
||||
texture=$vc2
|
||||
|
||||
htmlgauge00=WasmInstrument/WasmInstrument.html?wasm_module=md11host.wasm&wasm_gauge=AFS,3,0,1015,185
|
||||
htmlgauge01=WasmInstrument/WasmInstrument.html?wasm_module=md11host.wasm&wasm_gauge=FUEL,4,200,1016,196
|
||||
//above should actually be 3,192,1018,199 - moved due to visual offset
|
||||
|
||||
[Vcockpit03]
|
||||
Background_color=0,0,0
|
||||
size_mm=1024,1024
|
||||
visible=1
|
||||
pixel_size=1024,1024
|
||||
texture=$RADIOS_XPNDR
|
||||
|
||||
htmlgauge00=WasmInstrument/WasmInstrument.html?wasm_module=md11host.wasm&wasm_gauge=RADIOS_XPNDR,0,5,1019,295
|
||||
|
||||
[VCockpit04]
|
||||
Background_color=0,0,0
|
||||
size_mm=1536,1024
|
||||
visible=1
|
||||
pixel_size=1536,1024
|
||||
texture=$EFB
|
||||
|
||||
htmlgauge00=aircraft_efb/TFDi_MD11_efb/efb.html,0,0,1536,1024
|
||||
@@ -0,0 +1,59 @@
|
||||
// Panel Configuration File
|
||||
// TFDi Design MD-11
|
||||
|
||||
[VCockpit01]
|
||||
size_mm=2048,2048
|
||||
visible=1
|
||||
pixel_size=2048,2048
|
||||
texture=$vc1
|
||||
background_color=0,0,0
|
||||
htmlgauge00=WasmInstrument/WasmInstrument.html?wasm_module=md11host.wasm&wasm_gauge=Core, 0,0,509,510,PW
|
||||
htmlgauge01=WasmInstrument/WasmInstrument.html?wasm_module=md11host.wasm&wasm_gauge=DU1,0,0,508,508
|
||||
htmlgauge02=WasmInstrument/WasmInstrument.html?wasm_module=md11host.wasm&wasm_gauge=DU2,514,0,510,510
|
||||
htmlgauge03=WasmInstrument/WasmInstrument.html?wasm_module=md11host.wasm&wasm_gauge=DU3,1027,0,510,510
|
||||
htmlgauge04=WasmInstrument/WasmInstrument.html?wasm_module=md11host.wasm&wasm_gauge=DU4,1539,0,510,508
|
||||
htmlgauge05=WasmInstrument/WasmInstrument.html?wasm_module=md11host.wasm&wasm_gauge=DU5,0,513,511,509
|
||||
htmlgauge06=WasmInstrument/WasmInstrument.html?wasm_module=md11host.wasm&wasm_gauge=DU6,513,512,510,511
|
||||
htmlgauge07=WasmInstrument/WasmInstrument.html?wasm_module=md11host.wasm&wasm_gauge=LMCDU, 0,1046,333,287
|
||||
htmlgauge08=WasmInstrument/WasmInstrument.html?wasm_module=md11host.wasm&wasm_gauge=RMCDU,0,1386,334,288
|
||||
htmlgauge09=WasmInstrument/WasmInstrument.html?wasm_module=md11host.wasm&wasm_gauge=CMCDU,0,1728,333,285
|
||||
htmlgauge10=WasmInstrument/WasmInstrument.html?wasm_module=md11host.wasm&wasm_gauge=ISFD,1032,519,544,505
|
||||
//KH new gauge
|
||||
htmlgauge11=WasmInstrument/WasmInstrument.html?wasm_module=load-manager.wasm&wasm_gauge=Load_Manager,0,0,509,510
|
||||
|
||||
[VIEWS]
|
||||
VIEW_FORWARD_DIR=2.000, 0.000, 0.000
|
||||
|
||||
[Color]
|
||||
Day=255,255,255
|
||||
Night=255,255,255
|
||||
Luminous=201,64,64
|
||||
|
||||
[Vcockpit02]
|
||||
Background_color=0,0,0
|
||||
size_mm=1024,1024
|
||||
visible=1
|
||||
pixel_size=1024,1024
|
||||
texture=$vc2
|
||||
|
||||
htmlgauge00=WasmInstrument/WasmInstrument.html?wasm_module=md11host.wasm&wasm_gauge=AFS,3,0,1015,185
|
||||
htmlgauge01=WasmInstrument/WasmInstrument.html?wasm_module=md11host.wasm&wasm_gauge=FUEL,4,200,1016,196
|
||||
//above should actually be 3,192,1018,199 - moved due to visual offset
|
||||
|
||||
[Vcockpit03]
|
||||
Background_color=0,0,0
|
||||
size_mm=1024,1024
|
||||
visible=1
|
||||
pixel_size=1024,1024
|
||||
texture=$RADIOS_XPNDR
|
||||
|
||||
htmlgauge00=WasmInstrument/WasmInstrument.html?wasm_module=md11host.wasm&wasm_gauge=RADIOS_XPNDR,0,5,1019,295
|
||||
|
||||
[VCockpit04]
|
||||
Background_color=0,0,0
|
||||
size_mm=1536,1024
|
||||
visible=1
|
||||
pixel_size=1536,1024
|
||||
texture=$EFB
|
||||
|
||||
htmlgauge00=aircraft_efb/TFDi_MD11_efb/efb.html,0,0,1536,1024
|
||||
Vendored
+5
@@ -1 +1,6 @@
|
||||
/// <reference types="@microsoft/msfs-types/js/common.d.ts" />
|
||||
/// <reference types="@microsoft/msfs-types/pages/vcockpit/instruments/shared/baseinstrument.d.ts" />
|
||||
/// <reference types="@microsoft/msfs-types/js/datastorage.d.ts" />
|
||||
/// <reference types="@microsoft/msfs-types/js/buttons.d.ts" />
|
||||
/// <reference types="@microsoft/msfs-types/js/services/toolbarpanels.d.ts" />
|
||||
/// <reference types="@microsoft/msfs-types/js/simvar.d.ts" />
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "tfdidesign-md11-load-manager",
|
||||
"version": "0.1.14",
|
||||
"version": "0.1.22",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"type": "module",
|
||||
@@ -13,7 +13,9 @@
|
||||
"dev": "npx rollup -c -w",
|
||||
"clean": "rimraf ../html_ui/InGamePanels/tfdidesign-md11-load-manager-panel/ && rimraf .rollup.cache",
|
||||
"build": "npm version patch && npx rollup -c",
|
||||
"release": "pnpm types && pnpm lint && pnpm run licenses && pnpm clean && npm version patch && cross-env NODE_ENV=production npx rollup -c"
|
||||
"build-efb": "npm version patch && cross-env SPLIT=true npx rollup -c",
|
||||
"release": "pnpm types && pnpm lint && pnpm run licenses && pnpm clean && npm version patch && cross-env NODE_ENV=production npx rollup -c",
|
||||
"release-efb": "pnpm types && pnpm lint && pnpm run licenses && pnpm clean && npm version patch && cross-env NODE_ENV=production SPLIT=true npx rollup -c"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=22"
|
||||
@@ -58,14 +60,9 @@
|
||||
"typescript": "5.8.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"@emotion/react": "^11.11.1",
|
||||
"@emotion/styled": "^11.11.0",
|
||||
"@mui/icons-material": "^5.14.16",
|
||||
"@mui/material": "^5.14.17",
|
||||
"postcss-import": "^15.1.0",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"uuid": "^9.0.1"
|
||||
"react": "^19.1.0",
|
||||
"react-dom": "^19.1.0",
|
||||
"uuid": "^11.1.0"
|
||||
},
|
||||
"packageManager": "pnpm@10.11.1+sha512.e519b9f7639869dc8d5c3c5dfef73b3f091094b0a006d7317353c72b124e80e1afd429732e28705ad6bfa1ee879c1fce46c128ccebd3192101f43dd67c667912"
|
||||
}
|
||||
|
||||
Generated
+363
-928
File diff suppressed because it is too large
Load Diff
@@ -27,6 +27,15 @@ export default {
|
||||
dir: panelDirBase,
|
||||
format: 'es',
|
||||
sourcemap: targetEnv !== 'production',
|
||||
manualChunks: process.env.SPLIT
|
||||
? (id) => {
|
||||
if (id.includes('node_modules')) {
|
||||
return 'vendor';
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
: undefined,
|
||||
},
|
||||
plugins: [
|
||||
replace({
|
||||
|
||||
@@ -1,126 +1,61 @@
|
||||
import { FC, StrictMode, useCallback, useEffect, useRef, useState } from 'react';
|
||||
import Freight from './components/freight/Freight';
|
||||
import { FC, useCallback, useEffect, useState } from 'react';
|
||||
import Freighter from './components/freighter/Freighter';
|
||||
import Pax from './components/pax/Pax';
|
||||
import { PayloadFreight, calculateCGsFreight, getWeightsFreight } from './configs/freighter';
|
||||
import { PaxConfig, PayloadPax } from './configs/pax';
|
||||
import { Fuel, getFuel, initialFuel, initialPayload } from './configs/shared';
|
||||
import {
|
||||
COHERENT_COMM_BUS_WASM_CALL,
|
||||
COMM_BUS_LIVE_DATA_EVENT,
|
||||
TFDI_SIMBRIEF_USERNAME_CALL,
|
||||
TFDI_SIMBRIEF_USERNAME_EVENT,
|
||||
} from './constants';
|
||||
import { WASMDataF, WASMDataPax } from './types/WASMData';
|
||||
|
||||
interface IAppProps {
|
||||
commBus: ViewListener.ViewListener;
|
||||
}
|
||||
|
||||
const App: FC<IAppProps> = ({ commBus }) => {
|
||||
// Inferred
|
||||
const [unit, setUnit] = useState<'lbs' | 'kg'>('lbs');
|
||||
const [isCargo, setIsCargo] = useState(false);
|
||||
const [isER, setIsER] = useState(false);
|
||||
const [SBUsername, setSBUsername] = useState<string>();
|
||||
|
||||
// From sim
|
||||
const [payloadLive, setPayloadLive] = useState<PayloadPax | PayloadFreight>(initialPayload);
|
||||
const [fuel, setFuel] = useState<Fuel>(initialFuel);
|
||||
const [GSXPaxNum, setGSXPaxNum] = useState(0);
|
||||
const [GSXCargoPercent, setGSXCargoPercent] = useState(0);
|
||||
const [GSXState, setGSXState] = useState<'boarding' | 'deboarding' | 'idle'>('idle');
|
||||
|
||||
// Calculated
|
||||
const [CGs, setCGs] = useState<[number, number]>([0, 0]);
|
||||
|
||||
const [WASMData, setWASMData] = useState<WASMDataPax | WASMDataF>();
|
||||
const [isReady, setIsReady] = useState(false);
|
||||
|
||||
const requestRef = useRef<number | undefined>(undefined);
|
||||
|
||||
// Main Loop for Live Payload
|
||||
const mainLoop = () => {
|
||||
try {
|
||||
if (SimVar.IsReady()) {
|
||||
setIsER(SimVar.GetSimVarValue('L:MD11_OPT_ER', 'bool'));
|
||||
setIsCargo(SimVar.GetSimVarValue('L:MD11_EFB_IS_CARGO', 'bool'));
|
||||
setUnit((SimVar.GetSimVarValue('L:MD11_EFB_OPTIONS_GENERAL', 'number') & 1) << 0 ? 'lbs' : 'kg');
|
||||
|
||||
// GSX
|
||||
const boardingState = SimVar.GetSimVarValue('L:FSDT_GSX_BOARDING_STATE', 'number');
|
||||
const deboardingState = SimVar.GetSimVarValue('L:FSDT_GSX_DEBOARDING_STATE', 'number');
|
||||
setGSXState(boardingState === 5 ? 'boarding' : deboardingState === 5 ? 'deboarding' : 'idle');
|
||||
setGSXPaxNum(
|
||||
boardingState === 5
|
||||
? SimVar.GetSimVarValue('L:FSDT_GSX_NUMPASSENGERS_BOARDING_TOTAL', 'number')
|
||||
: deboardingState === 5
|
||||
? SimVar.GetSimVarValue('L:FSDT_GSX_NUMPASSENGERS_DEBOARDING_TOTAL', 'number')
|
||||
: 0
|
||||
);
|
||||
setGSXCargoPercent(
|
||||
boardingState === 5
|
||||
? SimVar.GetSimVarValue('L:FSDT_GSX_BOARDING_CARGO_PERCENT', 'number')
|
||||
: deboardingState === 5
|
||||
? 100 - SimVar.GetSimVarValue('L:FSDT_GSX_DEBOARDING_CARGO_PERCENT', 'number')
|
||||
: 0
|
||||
);
|
||||
|
||||
const payload = isCargo ? getWeightsFreight(unit) : PaxConfig.getWeights(unit);
|
||||
const _fuel = getFuel(unit);
|
||||
|
||||
setCGs(
|
||||
isCargo
|
||||
? calculateCGsFreight(payload as PayloadFreight, _fuel)
|
||||
: PaxConfig.calculateCGs(payload as PayloadPax, _fuel)
|
||||
);
|
||||
setPayloadLive(payload);
|
||||
setFuel(_fuel);
|
||||
}
|
||||
} catch {}
|
||||
|
||||
requestRef.current = requestAnimationFrame(mainLoop);
|
||||
};
|
||||
useEffect(() => {
|
||||
requestRef.current = requestAnimationFrame(mainLoop);
|
||||
|
||||
if (requestRef.current !== undefined) return () => cancelAnimationFrame(requestRef.current as number);
|
||||
}, [unit, isCargo]);
|
||||
|
||||
// CommBus
|
||||
const usernameCallback = useCallback((username: string) => {
|
||||
setSBUsername(username);
|
||||
setIsReady(true);
|
||||
}, []);
|
||||
const wasmCallback = useCallback((data: string) => {
|
||||
setWASMData(JSON.parse(data));
|
||||
}, []);
|
||||
useEffect(() => {
|
||||
console.log('Initializing CommBus');
|
||||
|
||||
commBus.on('receiveSimBriefUsername', usernameCallback);
|
||||
commBus.on(TFDI_SIMBRIEF_USERNAME_EVENT, usernameCallback);
|
||||
commBus.on(COMM_BUS_LIVE_DATA_EVENT, wasmCallback);
|
||||
|
||||
setTimeout(() => {
|
||||
Coherent.call('COMM_BUS_WASM_CALLBACK', 'requestSimBriefUsername', 'null');
|
||||
Coherent.call(COHERENT_COMM_BUS_WASM_CALL, TFDI_SIMBRIEF_USERNAME_CALL, 'null');
|
||||
}, 1000);
|
||||
|
||||
return () => commBus.off('receiveSimBriefUsername', usernameCallback);
|
||||
return () => {
|
||||
commBus.off(TFDI_SIMBRIEF_USERNAME_EVENT, usernameCallback);
|
||||
commBus.off(COMM_BUS_LIVE_DATA_EVENT, wasmCallback);
|
||||
};
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<StrictMode>
|
||||
<div className="flex w-full justify-center pt-2 bg-zinc-900">
|
||||
<div className="flex w-3/4 flex-col items-center">
|
||||
{isReady ? (
|
||||
isCargo ? (
|
||||
<Freight isER={isER} unit={unit} OEW={payloadLive.empty} CGs={CGs} />
|
||||
) : (
|
||||
<Pax
|
||||
isER={isER}
|
||||
unit={unit}
|
||||
CGs={CGs}
|
||||
fuelLive={fuel}
|
||||
payloadLive={payloadLive as PayloadPax}
|
||||
username={SBUsername}
|
||||
GSXPaxNum={GSXPaxNum}
|
||||
GSXCargoPercent={GSXCargoPercent}
|
||||
GSXState={GSXState}
|
||||
/>
|
||||
)
|
||||
<div className="flex w-full justify-center pt-2 bg-zinc-900">
|
||||
<div className="flex w-3/4 flex-col items-center">
|
||||
{isReady && WASMData ? (
|
||||
WASMData.userData.isCargo ? (
|
||||
<Freighter WASMData={WASMData as WASMDataF} username={SBUsername} />
|
||||
) : (
|
||||
<h1 className="text-sm font-medium">LOADING</h1>
|
||||
)}
|
||||
</div>
|
||||
<Pax WASMData={WASMData as WASMDataPax} username={SBUsername} />
|
||||
)
|
||||
) : (
|
||||
<h1 className="text-sm font-medium">LOADING</h1>
|
||||
)}
|
||||
</div>
|
||||
</StrictMode>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -1,44 +1,40 @@
|
||||
| Department | Related to | Name | License period | Material not material | License type | Link | Remote version | Installed version | Defined version | Author |
|
||||
| :--------- | :--------- | :------------------------------- | :------------- | :-------------------- | :----------- | :------------------------------------------------------------------------ | :------------- | :---------------- | :-------------- | :---------------------------------------------------------- |
|
||||
| kessler | stuff | @emotion/react | perpetual | material | MIT | git+https://github.com/emotion-js/emotion.git#main | 11.14.0 | 11.14.0 | ^11.11.1 | Emotion Contributors |
|
||||
| kessler | stuff | @emotion/styled | perpetual | material | MIT | git+https://github.com/emotion-js/emotion.git#main | 11.14.0 | 11.14.0 | ^11.11.0 | n/a |
|
||||
| kessler | stuff | @mui/icons-material | perpetual | material | MIT | git+https://github.com/mui/material-ui.git | 5.17.1 | 5.17.1 | ^5.14.16 | MUI Team |
|
||||
| kessler | stuff | @mui/material | perpetual | material | MIT | git+https://github.com/mui/material-ui.git | 5.17.1 | 5.17.1 | ^5.14.17 | MUI Team |
|
||||
| kessler | stuff | postcss-import | perpetual | material | MIT | git+https://github.com/postcss/postcss-import.git | 15.1.0 | 15.1.0 | ^15.1.0 | Maxime Thirouin |
|
||||
| kessler | stuff | react | perpetual | material | MIT | git+https://github.com/facebook/react.git | 18.3.1 | 18.3.1 | ^18.2.0 | n/a |
|
||||
| kessler | stuff | react-dom | perpetual | material | MIT | git+https://github.com/facebook/react.git | 18.3.1 | 18.3.1 | ^18.2.0 | n/a |
|
||||
| kessler | stuff | uuid | perpetual | material | MIT | git+https://github.com/uuidjs/uuid.git | 9.0.1 | 9.0.1 | ^9.0.1 | n/a |
|
||||
| kessler | stuff | react | perpetual | material | MIT | git+https://github.com/facebook/react.git | 19.1.0 | 19.1.0 | ^19.1.0 | n/a |
|
||||
| kessler | stuff | react-dom | perpetual | material | MIT | git+https://github.com/facebook/react.git | 19.1.0 | 19.1.0 | ^19.1.0 | n/a |
|
||||
| kessler | stuff | uuid | perpetual | material | MIT | git+https://github.com/uuidjs/uuid.git | 11.1.0 | 11.1.0 | ^11.1.0 | n/a |
|
||||
| kessler | stuff | @microsoft/msfs-types | perpetual | material | MIT | git+https://github.com/microsoft/msfs-avionics-mirror.git | 1.14.6 | 1.14.6 | ^1.14.6 | Asobo Studio / Working Title Simulations |
|
||||
| kessler | stuff | @rollup/plugin-commonjs | perpetual | material | MIT | git+https://github.com/rollup/plugins.git | 25.0.8 | 25.0.8 | ^25.0.0 | Rich Harris <richard.a.harris@gmail.com> |
|
||||
| kessler | stuff | @rollup/plugin-json | perpetual | material | MIT | git+https://github.com/rollup/plugins.git | 6.1.0 | 6.1.0 | ^6.0.0 | rollup |
|
||||
| kessler | stuff | @rollup/plugin-node-resolve | perpetual | material | MIT | git+https://github.com/rollup/plugins.git | 15.3.1 | 15.3.1 | ^15.1.0 | Rich Harris <richard.a.harris@gmail.com> |
|
||||
| kessler | stuff | @rollup/plugin-commonjs | perpetual | material | MIT | git+https://github.com/rollup/plugins.git | 28.0.5 | 28.0.3 | ^28.0.3 | Rich Harris <richard.a.harris@gmail.com> |
|
||||
| kessler | stuff | @rollup/plugin-json | perpetual | material | MIT | git+https://github.com/rollup/plugins.git | 6.1.0 | 6.1.0 | ^6.1.0 | rollup |
|
||||
| kessler | stuff | @rollup/plugin-node-resolve | perpetual | material | MIT | git+https://github.com/rollup/plugins.git | 16.0.1 | 16.0.1 | ^16.0.1 | Rich Harris <richard.a.harris@gmail.com> |
|
||||
| kessler | stuff | @rollup/plugin-replace | perpetual | material | MIT | git+https://github.com/rollup/plugins.git | 6.0.2 | 6.0.2 | ^6.0.2 | Rich Harris <richard.a.harris@gmail.com> |
|
||||
| kessler | stuff | @rollup/plugin-terser | perpetual | material | MIT | git+https://github.com/rollup/plugins.git | 0.4.4 | 0.4.4 | ^0.4.3 | Peter Placzek <peter.placzek1996@gmail.com> |
|
||||
| kessler | stuff | @rollup/plugin-typescript | perpetual | material | MIT | git+https://github.com/rollup/plugins.git | 11.1.6 | 11.1.6 | ^11.1.1 | Oskar Segersvärd |
|
||||
| kessler | stuff | @types/react | perpetual | material | MIT | https://github.com/DefinitelyTyped/DefinitelyTyped.git | 18.3.23 | 18.3.23 | ^18.2.8 | n/a |
|
||||
| kessler | stuff | @types/react-dom | perpetual | material | MIT | https://github.com/DefinitelyTyped/DefinitelyTyped.git | 18.3.7 | 18.3.7 | ^18.2.4 | n/a |
|
||||
| kessler | stuff | @types/uuid | perpetual | material | MIT | https://github.com/DefinitelyTyped/DefinitelyTyped.git | 9.0.8 | 9.0.8 | ^9.0.7 | n/a |
|
||||
| kessler | stuff | @typescript-eslint/eslint-plugin | perpetual | material | MIT | git+https://github.com/typescript-eslint/typescript-eslint.git | 6.21.0 | 6.21.0 | ^6.10.0 | n/a |
|
||||
| kessler | stuff | @typescript-eslint/parser | perpetual | material | BSD-2-Clause | git+https://github.com/typescript-eslint/typescript-eslint.git | 6.21.0 | 6.21.0 | ^6.10.0 | n/a |
|
||||
| kessler | stuff | autoprefixer | perpetual | material | MIT | git+https://github.com/postcss/autoprefixer.git | 10.4.21 | 10.4.21 | ^10.4.14 | Andrey Sitnik <andrey@sitnik.ru> |
|
||||
| kessler | stuff | @rollup/plugin-terser | perpetual | material | MIT | git+https://github.com/rollup/plugins.git | 0.4.4 | 0.4.4 | ^0.4.4 | Peter Placzek <peter.placzek1996@gmail.com> |
|
||||
| kessler | stuff | @rollup/plugin-typescript | perpetual | material | MIT | git+https://github.com/rollup/plugins.git | 12.1.2 | 12.1.2 | ^12.1.2 | Oskar Segersvärd |
|
||||
| kessler | stuff | @types/react | perpetual | material | MIT | https://github.com/DefinitelyTyped/DefinitelyTyped.git | 19.1.8 | 19.1.6 | ^19.1.6 | n/a |
|
||||
| kessler | stuff | @types/react-dom | perpetual | material | MIT | https://github.com/DefinitelyTyped/DefinitelyTyped.git | 19.1.6 | 19.1.6 | ^19.1.6 | n/a |
|
||||
| kessler | stuff | @types/uuid | perpetual | material | MIT | https://github.com/DefinitelyTyped/DefinitelyTyped.git | 10.0.0 | 10.0.0 | ^10.0.0 | n/a |
|
||||
| kessler | stuff | @typescript-eslint/eslint-plugin | perpetual | material | MIT | git+https://github.com/typescript-eslint/typescript-eslint.git | 6.21.0 | 6.21.0 | ^6.21.0 | n/a |
|
||||
| kessler | stuff | @typescript-eslint/parser | perpetual | material | BSD-2-Clause | git+https://github.com/typescript-eslint/typescript-eslint.git | 6.21.0 | 6.21.0 | ^6.21.0 | n/a |
|
||||
| kessler | stuff | autoprefixer | perpetual | material | MIT | git+https://github.com/postcss/autoprefixer.git | 10.4.21 | 10.4.21 | ^10.4.21 | Andrey Sitnik <andrey@sitnik.ru> |
|
||||
| kessler | stuff | cross-env | perpetual | material | MIT | git+https://github.com/kentcdodds/cross-env.git | 7.0.3 | 7.0.3 | ^7.0.3 | Kent C. Dodds <me@kentcdodds.com> (https://kentcdodds.com) |
|
||||
| kessler | stuff | eslint | perpetual | material | MIT | git+https://github.com/eslint/eslint.git | 8.57.1 | 8.57.1 | ^8.42.0 | Nicholas C. Zakas <nicholas+npm@nczconsulting.com> |
|
||||
| kessler | stuff | eslint-plugin-import | perpetual | material | MIT | git+https://github.com/import-js/eslint-plugin-import.git | 2.31.0 | 2.31.0 | ^2.27.5 | Ben Mosher <me@benmosher.com> |
|
||||
| kessler | stuff | eslint-plugin-react | perpetual | material | MIT | git+https://github.com/jsx-eslint/eslint-plugin-react.git | 7.37.5 | 7.37.5 | ^7.32.2 | Yannick Croissant <yannick.croissant+npm@gmail.com> |
|
||||
| kessler | stuff | eslint-plugin-react-hooks | perpetual | material | MIT | git+https://github.com/facebook/react.git | 4.6.2 | 4.6.2 | ^4.6.0 | n/a |
|
||||
| kessler | stuff | license-report | perpetual | material | MIT | git+https://github.com/kessler/license-report.git | 6.7.2 | 6.7.2 | ^6.5.0 | Yaniv Kessler |
|
||||
| kessler | stuff | postcss | perpetual | material | MIT | git+https://github.com/postcss/postcss.git | 8.5.4 | 8.5.4 | ^8.4.24 | Andrey Sitnik <andrey@sitnik.ru> |
|
||||
| kessler | stuff | prettier | perpetual | material | MIT | git+https://github.com/prettier/prettier.git | 3.5.3 | 3.5.3 | ^3.0.3 | James Long |
|
||||
| kessler | stuff | prettier-plugin-organize-imports | perpetual | material | MIT | git+https://github.com/simonhaenisch/prettier-plugin-organize-imports.git | 3.2.4 | 3.2.4 | ^3.2.4 | Simon Haenisch (https://github.com/simonhaenisch) |
|
||||
| kessler | stuff | rimraf | perpetual | material | ISC | git://github.com/isaacs/rimraf.git | 5.0.10 | 5.0.10 | ^5.0.1 | Isaac Z. Schlueter <i@izs.me> (http://blog.izs.me/) |
|
||||
| kessler | stuff | rollup | perpetual | material | MIT | git+https://github.com/rollup/rollup.git | 4.41.1 | 4.41.1 | ^4.3.1 | Rich Harris |
|
||||
| kessler | stuff | rollup-plugin-copy | perpetual | material | MIT | git+https://github.com/vladshcherbin/rollup-plugin-copy.git | 3.5.0 | 3.5.0 | ^3.4.0 | Vlad Shcherbin <vlad.shcherbin@gmail.com> |
|
||||
| kessler | stuff | eslint | perpetual | material | MIT | git+https://github.com/eslint/eslint.git | 8.57.1 | 8.57.1 | ^8.57.1 | Nicholas C. Zakas <nicholas+npm@nczconsulting.com> |
|
||||
| kessler | stuff | eslint-plugin-import | perpetual | material | MIT | git+https://github.com/import-js/eslint-plugin-import.git | 2.31.0 | 2.31.0 | ^2.31.0 | Ben Mosher <me@benmosher.com> |
|
||||
| kessler | stuff | eslint-plugin-react | perpetual | material | MIT | git+https://github.com/jsx-eslint/eslint-plugin-react.git | 7.37.5 | 7.37.5 | ^7.37.5 | Yannick Croissant <yannick.croissant+npm@gmail.com> |
|
||||
| kessler | stuff | eslint-plugin-react-hooks | perpetual | material | MIT | git+https://github.com/facebook/react.git | 4.6.2 | 4.6.2 | ^4.6.2 | n/a |
|
||||
| kessler | stuff | license-report | perpetual | material | MIT | git+https://github.com/kessler/license-report.git | 6.8.0 | 6.7.2 | ^6.7.2 | Yaniv Kessler |
|
||||
| kessler | stuff | postcss | perpetual | material | MIT | git+https://github.com/postcss/postcss.git | 8.5.5 | 8.5.4 | ^8.5.4 | Andrey Sitnik <andrey@sitnik.ru> |
|
||||
| kessler | stuff | postcss-import | perpetual | material | MIT | git+https://github.com/postcss/postcss-import.git | 16.1.0 | 16.1.0 | ^16.1.0 | Maxime Thirouin |
|
||||
| kessler | stuff | prettier | perpetual | material | MIT | git+https://github.com/prettier/prettier.git | 3.5.3 | 3.5.3 | ^3.5.3 | James Long |
|
||||
| kessler | stuff | prettier-plugin-organize-imports | perpetual | material | MIT | git+https://github.com/simonhaenisch/prettier-plugin-organize-imports.git | 4.1.0 | 4.1.0 | ^4.1.0 | Simon Haenisch (https://github.com/simonhaenisch) |
|
||||
| kessler | stuff | rimraf | perpetual | material | ISC | git://github.com/isaacs/rimraf.git | 6.0.1 | 6.0.1 | ^6.0.1 | Isaac Z. Schlueter <i@izs.me> (http://blog.izs.me/) |
|
||||
| kessler | stuff | rollup | perpetual | material | MIT | git+https://github.com/rollup/rollup.git | 4.43.0 | 4.42.0 | ^4.42.0 | Rich Harris |
|
||||
| kessler | stuff | rollup-plugin-copy | perpetual | material | MIT | git+https://github.com/vladshcherbin/rollup-plugin-copy.git | 3.5.0 | 3.5.0 | ^3.5.0 | Vlad Shcherbin <vlad.shcherbin@gmail.com> |
|
||||
| kessler | stuff | rollup-plugin-postcss | perpetual | material | MIT | git+https://github.com/egoist/rollup-plugin-postcss.git | 4.0.2 | 4.0.2 | ^4.0.2 | EGOIST <0x142857@gmail.com> |
|
||||
| kessler | stuff | rollup-plugin-react-svg | perpetual | material | MIT | git+https://github.com/boopathi/react-svg-loader.git | 3.0.3 | 3.0.3 | ^3.0.3 | boopathi |
|
||||
| kessler | stuff | rollup-plugin-version-injector | perpetual | material | ISC | git+https://github.com/djhouseknecht/rollup-plugin-version-injector.git | 1.3.3 | 1.3.3 | ^1.3.3 | David Houseknecht <david.j.houseknecht@gmail.com> |
|
||||
| kessler | stuff | sass | perpetual | material | MIT | git+https://github.com/sass/dart-sass.git | 1.89.1 | 1.89.1 | ^1.89.1 | Natalie Weizenbaum nweiz@google.com https://github.com/nex3 |
|
||||
| kessler | stuff | sass | perpetual | material | MIT | git+https://github.com/sass/dart-sass.git | 1.89.2 | 1.89.1 | ^1.89.1 | Natalie Weizenbaum nweiz@google.com https://github.com/nex3 |
|
||||
| kessler | stuff | svg-slim | perpetual | material | MIT | git+https://github.com/benboba/svg-slim.git | 2.0.5 | 2.0.5 | ^2.0.5 | Wang Feng <benboba@gmail.com> |
|
||||
| kessler | stuff | tslib | perpetual | material | 0BSD | git+https://github.com/Microsoft/tslib.git | 2.8.1 | 2.8.1 | ^2.5.3 | Microsoft Corp. |
|
||||
| kessler | stuff | typed-scss-modules | perpetual | material | MIT | git+https://github.com/skovy/typed-scss-modules.git | 7.1.4 | 7.1.4 | ^7.1.0 | Spencer Miskoviak <smiskoviak@gmail.com> |
|
||||
| kessler | stuff | typescript | perpetual | material | Apache-2.0 | git+https://github.com/Microsoft/TypeScript.git | 5.2.2 | 5.2.2 | 5.2.2 | Microsoft Corp. |
|
||||
| kessler | stuff | tslib | perpetual | material | 0BSD | git+https://github.com/Microsoft/tslib.git | 2.8.1 | 2.8.1 | ^2.8.1 | Microsoft Corp. |
|
||||
| kessler | stuff | typed-scss-modules | perpetual | material | MIT | git+https://github.com/skovy/typed-scss-modules.git | 8.1.1 | 8.1.1 | ^8.1.1 | Spencer Miskoviak <smiskoviak@gmail.com> |
|
||||
| kessler | stuff | typescript | perpetual | material | Apache-2.0 | git+https://github.com/microsoft/TypeScript.git | 5.8.3 | 5.8.3 | 5.8.3 | Microsoft Corp. |
|
||||
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
import { FC } from 'react';
|
||||
import { SharedConfig } from '../../configs/shared';
|
||||
|
||||
interface CGSelectProps {
|
||||
minCG: number;
|
||||
maxCG: number;
|
||||
value: number;
|
||||
disabled: boolean;
|
||||
increase: () => void;
|
||||
decrease: () => void;
|
||||
}
|
||||
|
||||
const CGSelect: FC<CGSelectProps> = ({ value, disabled, increase, decrease }) => {
|
||||
const CGSelect: FC<CGSelectProps> = ({ minCG, maxCG, value, disabled, increase, decrease }) => {
|
||||
return (
|
||||
<div className="relative">
|
||||
<input
|
||||
@@ -17,7 +18,7 @@ const CGSelect: FC<CGSelectProps> = ({ value, disabled, increase, decrease }) =>
|
||||
value={value.toFixed(1)}
|
||||
/>
|
||||
<button
|
||||
disabled={disabled || value <= SharedConfig.CGLimits.min}
|
||||
disabled={disabled || value <= minCG}
|
||||
className="absolute right-2 top-0 -mt-[.5px] border-t bg-zinc-700 text-white disabled:text-zinc-400"
|
||||
onClick={increase}
|
||||
>
|
||||
@@ -45,7 +46,7 @@ const CGSelect: FC<CGSelectProps> = ({ value, disabled, increase, decrease }) =>
|
||||
</svg>
|
||||
</button>
|
||||
<button
|
||||
disabled={disabled || value >= SharedConfig.CGLimits.max}
|
||||
disabled={disabled || value >= maxCG}
|
||||
className="absolute bottom-0 right-2 -mt-[.5px] border-b bg-zinc-700 text-white disabled:text-zinc-400"
|
||||
onClick={decrease}
|
||||
>
|
||||
|
||||
@@ -0,0 +1,227 @@
|
||||
import { FC, useEffect, useState } from 'react';
|
||||
import { GSX_SERVICE_CALLED, GSX_SERVICE_FINISHED } from '../../constants';
|
||||
import { WASMDataF } from '../../types/WASMData';
|
||||
import { LoadingState, SimBrief } from '../../types/general';
|
||||
import { ImportFlightPlan } from '../../utils/TFDISBImport';
|
||||
import { CoherentCallSBEntryF, inRangeOf, loadAircraft, unloadAircraft } from '../../utils/utils';
|
||||
import CGSelect from '../CGSelect/CGSelect';
|
||||
import ActionBar from '../actionbar/ActionBar';
|
||||
|
||||
interface SBEntryProps {
|
||||
WASMData: WASMDataF;
|
||||
loadingState: LoadingState;
|
||||
username: string;
|
||||
setLoadingState: (newState: LoadingState) => void;
|
||||
}
|
||||
|
||||
const SBEntryF: FC<SBEntryProps> = ({ WASMData, loadingState, username, setLoadingState }) => {
|
||||
const [CGTarget, setCGTarget] = useState(WASMData.targetPayload.CGTarget);
|
||||
const [fuel, setFuel] = useState(Math.round(WASMData.livePayload.fuel));
|
||||
const [fuelEnabled, setFuelEnabled] = useState(true);
|
||||
const [SBInFlight, setSBInFlight] = useState(false);
|
||||
|
||||
const ZFW = () => {
|
||||
if (loadingState !== 'loaded' && !GSXActive()) return Math.round(WASMData.targetPayload.total);
|
||||
|
||||
return Math.round(WASMData.livePayload.total);
|
||||
};
|
||||
const ZFWValid = () => {
|
||||
return ZFW() <= WASMData.limits.maxZFW;
|
||||
};
|
||||
const GW = () => {
|
||||
return fuel + ZFW();
|
||||
};
|
||||
const GWValid = () => {
|
||||
return GW() <= WASMData.limits.maxTOW;
|
||||
};
|
||||
|
||||
const GSXActive = () => {
|
||||
return (
|
||||
(WASMData.GSX.boardingState >= GSX_SERVICE_CALLED || WASMData.GSX.deboardingState >= GSX_SERVICE_CALLED) &&
|
||||
WASMData.GSX.deboardingState !== GSX_SERVICE_FINISHED
|
||||
);
|
||||
};
|
||||
|
||||
const handleInput = (input: string, maxValue: number, setter: (value: number) => void) => {
|
||||
if (!input) {
|
||||
setter(0);
|
||||
return;
|
||||
}
|
||||
|
||||
const converted = parseInt(input);
|
||||
if (converted) {
|
||||
if (converted < 0) setter(0);
|
||||
else if (converted > maxValue) setter(maxValue);
|
||||
else setter(converted);
|
||||
}
|
||||
};
|
||||
|
||||
const handleSB = async () => {
|
||||
setSBInFlight(true);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
updateData(undefined, SBResponse.message);
|
||||
|
||||
setFuel(parseFloat(SBResponse.message.fuel) ?? 0);
|
||||
setSBInFlight(false);
|
||||
};
|
||||
|
||||
useEffect(
|
||||
() =>
|
||||
setFuel((prev) => {
|
||||
if (prev > WASMData.limits.maxFuel) return WASMData.limits.maxFuel;
|
||||
return prev;
|
||||
}),
|
||||
[WASMData.userData.isER]
|
||||
);
|
||||
useEffect(() => {
|
||||
setFuelEnabled(inRangeOf(Math.round(WASMData.livePayload.fuel), fuel));
|
||||
}, [WASMData.livePayload.fuel]);
|
||||
|
||||
const updateData = (_CGTarget?: number, SBPlan?: SimBrief) => {
|
||||
CoherentCallSBEntryF(_CGTarget ?? CGTarget, SBPlan);
|
||||
};
|
||||
|
||||
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' || GSXActive()}
|
||||
/>
|
||||
<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(WASMData.livePayload.fuel === fuel);
|
||||
}}
|
||||
disabled={loadingState !== 'preview' || !fuelEnabled || GSXActive()}
|
||||
>
|
||||
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="relative flex w-full items-center justify-between rounded-t-md bg-zinc-600 p-2 px-4">
|
||||
<label>Planned 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={WASMData.sbPlanned.ZFW}
|
||||
disabled
|
||||
/>
|
||||
</div>
|
||||
<div className="relative flex w-full items-center justify-between bg-zinc-700 p-2 px-4">
|
||||
<label>Planned GW ({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={WASMData.sbPlanned.GW}
|
||||
disabled
|
||||
/>
|
||||
</div>
|
||||
<div className="relative flex w-full items-center justify-between rounded-b-md bg-zinc-600 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' || GSXActive()}
|
||||
increase={() =>
|
||||
setCGTarget((prev) => {
|
||||
const _new = prev + 0.1;
|
||||
updateData(_new);
|
||||
return _new;
|
||||
})
|
||||
}
|
||||
decrease={() =>
|
||||
setCGTarget((prev) => {
|
||||
const _new = prev - 0.1;
|
||||
updateData(_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="relative flex w-full items-center justify-between rounded-t-md bg-zinc-600 p-2 px-4">
|
||||
<label>
|
||||
{loadingState !== 'loaded' && !GSXActive() ? 'Expected' : 'Actual'} ZFW (
|
||||
{WASMData.userData.isImperial ? 'lbs' : 'kg'})
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
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`}
|
||||
disabled
|
||||
value={ZFW()}
|
||||
/>
|
||||
</div>
|
||||
<div className="relative flex w-full items-center justify-between rounded-b-md bg-zinc-700 p-2 px-4">
|
||||
<label>
|
||||
{loadingState !== 'loaded' && !GSXActive() ? 'Expected' : 'Actual'} GW (
|
||||
{WASMData.userData.isImperial ? 'lbs' : 'kg'})
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
placeholder=""
|
||||
className={`w-1/2 rounded-lg border ${GWValid() ? 'border-white' : 'border-red-500 text-red-500'} bg-zinc-700 px-3 py-2 text-right`}
|
||||
disabled
|
||||
value={GW()}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<ActionBar
|
||||
loadingState={loadingState}
|
||||
loadDisabled={!GWValid() || SBInFlight}
|
||||
GSXSync={WASMData.options.GSXSync}
|
||||
GSXActive={GSXActive()}
|
||||
importSB={handleSB}
|
||||
load={() => {
|
||||
setLoadingState('loaded');
|
||||
|
||||
loadAircraft();
|
||||
}}
|
||||
unload={() => {
|
||||
setLoadingState('preview');
|
||||
|
||||
unloadAircraft();
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default SBEntryF;
|
||||
@@ -1,111 +1,45 @@
|
||||
import { FC, useEffect, useState } from 'react';
|
||||
import { PaxConfig, PayloadPax } from '../../configs/pax';
|
||||
import { Fuel, SharedConfig } from '../../configs/shared';
|
||||
import { GSX_SERVICE_CALLED, GSX_SERVICE_FINISHED } from '../../constants';
|
||||
import { WASMDataPax } from '../../types/WASMData';
|
||||
import { LoadingState, SimBrief } from '../../types/general';
|
||||
import { ImportFlightPlan } from '../../utils/TFDISBImport';
|
||||
import { CoherentCallSBEntryPax, inRangeOf, loadAircraft, unloadAircraft } from '../../utils/utils';
|
||||
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;
|
||||
loadAircraft: () => void;
|
||||
setLoadingState: (newState: LoadingState) => void;
|
||||
}
|
||||
|
||||
const SBEntryPax: FC<StationEntryProps> = ({
|
||||
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 [SBPlan, setSBPlan] = useState<any>();
|
||||
const SBEntryPax: FC<SBEntryProps> = ({ WASMData, loadingState, username, setLoadingState }) => {
|
||||
const [CGTarget, setCGTarget] = useState(WASMData.targetPayload.CGTarget);
|
||||
const [fuel, setFuel] = useState(Math.round(WASMData.livePayload.fuel));
|
||||
const [fuelEnabled, setFuelEnabled] = useState(true);
|
||||
const [SBInFlight, setSBInFlight] = useState(false);
|
||||
|
||||
const _ZFW = () => {
|
||||
if (loadingState !== 'loaded') return ZFW;
|
||||
const ZFW = () => {
|
||||
if (loadingState !== 'loaded' && !GSXActive()) return Math.round(WASMData.targetPayload.total);
|
||||
|
||||
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
|
||||
);
|
||||
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 GSXActive = () => {
|
||||
return (
|
||||
(WASMData.GSX.boardingState >= GSX_SERVICE_CALLED || WASMData.GSX.deboardingState >= GSX_SERVICE_CALLED) &&
|
||||
WASMData.GSX.deboardingState !== GSX_SERVICE_FINISHED
|
||||
);
|
||||
};
|
||||
|
||||
const handleInput = (input: string, maxValue: number, setter: (value: number) => void) => {
|
||||
@@ -125,117 +59,67 @@ const SBEntryPax: FC<StationEntryProps> = ({
|
||||
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;
|
||||
updateData(undefined, SBResponse.message);
|
||||
|
||||
updateView(
|
||||
PaxConfig.distribute(__ZFW, targetZFWCG, payloadLive.empty, fuelLive, unit, isER, SBResponse.message.pax)
|
||||
);
|
||||
|
||||
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((prev) => (!prev ? inRangeOf(Math.round(WASMData.livePayload.fuel), fuel) : prev));
|
||||
}, [WASMData.livePayload.fuel]);
|
||||
|
||||
const updateData = (_CGTarget?: number, SBPlan?: SimBrief) => {
|
||||
CoherentCallSBEntryPax(_CGTarget ?? CGTarget, SBPlan);
|
||||
};
|
||||
|
||||
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>Planned ZFW ({unit})</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={SBPlan?.plannedZFW ?? 0}
|
||||
disabled
|
||||
/>
|
||||
</div>
|
||||
<div className="relative flex w-full items-center justify-between bg-zinc-700 p-2 px-4">
|
||||
<label>Planned ZFW ({unit})</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={SBPlan?.plannedGW ?? 0}
|
||||
disabled
|
||||
/>
|
||||
</div>
|
||||
<div className="relative flex w-full items-center justify-between rounded-b-md bg-zinc-600 p-2 px-4">
|
||||
<label>
|
||||
Target ZFWCG ({SharedConfig.CGLimits.min} - {SharedConfig.CGLimits.max})
|
||||
</label>
|
||||
<CGSelect
|
||||
value={targetZFWCG}
|
||||
disabled={loadingState !== 'preview'}
|
||||
increase={() =>
|
||||
setTargetZFWCG((prev) => {
|
||||
const _new = prev + 0.1;
|
||||
updateView(PaxConfig.distribute(ZFW, _new, payloadLive.empty, fuelLive, unit, isER));
|
||||
return _new;
|
||||
})
|
||||
}
|
||||
decrease={() =>
|
||||
setTargetZFWCG((prev) => {
|
||||
const _new = prev - 0.1;
|
||||
updateView(PaxConfig.distribute(ZFW, _new, payloadLive.empty, fuelLive, unit, isER));
|
||||
return _new;
|
||||
})
|
||||
}
|
||||
/>
|
||||
</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>
|
||||
<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,
|
||||
isER ? SharedConfig.maxFuel.er[unit] : SharedConfig.maxFuel.norm[unit],
|
||||
setFuel
|
||||
)
|
||||
}
|
||||
disabled
|
||||
onChange={(e) => handleInput(e.target.value, WASMData.limits.maxFuel, setFuel)}
|
||||
disabled={loadingState !== 'preview' || GSXActive()}
|
||||
/>
|
||||
<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_PAYLOAD_FUEL',
|
||||
'lbs',
|
||||
WASMData.userData.isImperial ? fuel : fuel * 2.20462262185
|
||||
);
|
||||
SimVar.SetSimVarValue('L:MD11_EFB_READ_READY', 'bool', true);
|
||||
setFuelEnabled(WASMData.livePayload.fuel === fuel);
|
||||
}}
|
||||
disabled={loadingState !== 'preview' || SBInFlight}
|
||||
disabled={loadingState !== 'preview' || !fuelEnabled || GSXActive()}
|
||||
>
|
||||
Load Fuel
|
||||
</button>
|
||||
@@ -244,20 +128,70 @@ const SBEntryPax: FC<StationEntryProps> = ({
|
||||
|
||||
<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>Planned 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={WASMData.sbPlanned.ZFW}
|
||||
disabled
|
||||
/>
|
||||
</div>
|
||||
<div className="relative flex w-full items-center justify-between bg-zinc-700 p-2 px-4">
|
||||
<label>Planned GW ({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={WASMData.sbPlanned.GW}
|
||||
disabled
|
||||
/>
|
||||
</div>
|
||||
<div className="relative flex w-full items-center justify-between rounded-b-md bg-zinc-600 p-2 px-4">
|
||||
<label>
|
||||
{loadingState !== 'loaded' ? 'Expected' : 'Actual'} ZFW ({unit})
|
||||
Target ZFWCG ({WASMData.limits.minCG} - {WASMData.limits.maxCG})
|
||||
</label>
|
||||
<CGSelect
|
||||
minCG={WASMData.limits.minCG}
|
||||
maxCG={WASMData.limits.maxCG}
|
||||
value={CGTarget}
|
||||
disabled={loadingState !== 'preview' || GSXActive()}
|
||||
increase={() =>
|
||||
setCGTarget((prev) => {
|
||||
const _new = prev + 0.1;
|
||||
updateData(_new);
|
||||
return _new;
|
||||
})
|
||||
}
|
||||
decrease={() =>
|
||||
setCGTarget((prev) => {
|
||||
const _new = prev - 0.1;
|
||||
updateData(_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="relative flex w-full items-center justify-between rounded-t-md bg-zinc-600 p-2 px-4">
|
||||
<label>
|
||||
{loadingState !== 'loaded' && !GSXActive() ? 'Expected' : 'Actual'} ZFW (
|
||||
{WASMData.userData.isImperial ? 'lbs' : 'kg'})
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
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`}
|
||||
disabled
|
||||
value={_ZFW()}
|
||||
value={ZFW()}
|
||||
/>
|
||||
</div>
|
||||
<div className="relative flex w-full items-center justify-between rounded-b-md bg-zinc-700 p-2 px-4">
|
||||
<label>
|
||||
{loadingState !== 'loaded' ? 'Expected' : 'Actual'} GW ({unit})
|
||||
{loadingState !== 'loaded' && !GSXActive() ? 'Expected' : 'Actual'} GW (
|
||||
{WASMData.userData.isImperial ? 'lbs' : 'kg'})
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
@@ -271,10 +205,9 @@ const SBEntryPax: FC<StationEntryProps> = ({
|
||||
|
||||
<ActionBar
|
||||
loadingState={loadingState}
|
||||
acceptDisabled={!GWValid() || SBInFlight}
|
||||
//TODO: Make GSX optional (accepted state for NON GSX)
|
||||
accept={() => setLoadingState('loaded')}
|
||||
reject={() => setLoadingState('preview')}
|
||||
loadDisabled={!GWValid() || SBInFlight}
|
||||
GSXSync={WASMData.options.GSXSync}
|
||||
GSXActive={GSXActive()}
|
||||
importSB={handleSB}
|
||||
load={() => {
|
||||
setLoadingState('loaded');
|
||||
@@ -284,7 +217,7 @@ const SBEntryPax: FC<StationEntryProps> = ({
|
||||
unload={() => {
|
||||
setLoadingState('preview');
|
||||
|
||||
PaxConfig.unload(unit, isER);
|
||||
unloadAircraft();
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
|
||||
@@ -1,36 +1,36 @@
|
||||
import { FC } from 'react';
|
||||
import { LoadingState } from '../../types/general';
|
||||
|
||||
interface ActionBarProps {
|
||||
loadingState: 'preview' | 'accepted' | 'loaded';
|
||||
acceptDisabled: boolean;
|
||||
accept: () => void;
|
||||
reject: () => void;
|
||||
loadingState: LoadingState;
|
||||
loadDisabled: boolean;
|
||||
GSXSync: boolean;
|
||||
GSXActive: boolean;
|
||||
importSB?: () => void;
|
||||
load: () => void;
|
||||
unload: () => void;
|
||||
}
|
||||
|
||||
const ActionBar: FC<ActionBarProps> = ({ loadingState, acceptDisabled, accept, reject, importSB, load, unload }) => {
|
||||
const ActionBar: FC<ActionBarProps> = ({ loadingState, loadDisabled, GSXSync, GSXActive, importSB, load, unload }) => {
|
||||
return (
|
||||
<div className="relative flex w-full items-center justify-start gap-x-6">
|
||||
{loadingState === 'preview' && (
|
||||
{loadingState === 'preview' && !GSXSync && (
|
||||
<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={accept}
|
||||
disabled={acceptDisabled}
|
||||
onClick={load}
|
||||
disabled={loadDisabled}
|
||||
>
|
||||
Accept
|
||||
Load
|
||||
</button>
|
||||
)}
|
||||
{/*TODO: Make GSX optional (accepted state for NON GSX) */}
|
||||
{loadingState === 'loaded' && (
|
||||
{loadingState === 'loaded' && !GSXSync && (
|
||||
<button
|
||||
className="middle none center rounded-lg bg-red-600 px-6 py-3 font-sans text-xs font-bold uppercase text-white shadow-md shadow-red-500/20 transition-all hover:shadow-lg hover:shadow-red-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={reject}
|
||||
onClick={unload}
|
||||
>
|
||||
Reject
|
||||
Unload
|
||||
</button>
|
||||
)}
|
||||
|
||||
@@ -41,31 +41,11 @@ const ActionBar: FC<ActionBarProps> = ({ loadingState, acceptDisabled, accept, r
|
||||
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={importSB}
|
||||
disabled={GSXActive}
|
||||
>
|
||||
Import from SimBrief
|
||||
</button>
|
||||
)}
|
||||
{/*TODO: Make GSX optional */}
|
||||
{/*
|
||||
{loadingState === 'accepted' && (
|
||||
<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={load}
|
||||
>
|
||||
Load
|
||||
</button>
|
||||
)}
|
||||
{loadingState === 'loaded' && (
|
||||
<button
|
||||
className="middle none center rounded-lg bg-red-600 px-6 py-3 font-sans text-xs font-bold uppercase text-white shadow-md shadow-red-500/20 transition-all hover:shadow-lg hover:shadow-red-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={unload}
|
||||
>
|
||||
Unload
|
||||
</button>
|
||||
)}
|
||||
*/}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,92 +0,0 @@
|
||||
import { FC, useState } from 'react';
|
||||
import { PayloadFreight } from '../../configs/freighter';
|
||||
import { initialPayload, SharedConfig } from '../../configs/shared';
|
||||
import Profile from '../profile/Profile';
|
||||
import Tabbar from '../tabbar/Tabbar';
|
||||
|
||||
interface FreightProps {
|
||||
isER: boolean;
|
||||
unit: 'kg' | 'lbs';
|
||||
OEW: number;
|
||||
CGs: [number, number];
|
||||
}
|
||||
|
||||
const Freight: FC<FreightProps> = ({ isER, unit, OEW, CGs }) => {
|
||||
const [selectedTab, setSelectedTab] = useState(0);
|
||||
const [payload, setPayload] = useState<PayloadFreight>(initialPayload);
|
||||
const [inPreview, setInPreview] = useState(true);
|
||||
|
||||
const upper1 = () => {
|
||||
return Math.round(payload.upper1Left + payload.upper1Right);
|
||||
};
|
||||
const upper2 = () => {
|
||||
return Math.round(payload.upper2Left + payload.upper2Right);
|
||||
};
|
||||
const upper3 = () => {
|
||||
return Math.round(payload.upper3Left + payload.upper3Right);
|
||||
};
|
||||
const upper4 = () => {
|
||||
return Math.round(payload.upper4Left + payload.upper4Right);
|
||||
};
|
||||
const lower1 = () => {
|
||||
return Math.round(payload.lowerForward);
|
||||
};
|
||||
const lower2 = () => {
|
||||
return Math.round(payload.lowerRear);
|
||||
};
|
||||
const _OEW = () => {
|
||||
return Math.round(OEW + (isER ? SharedConfig.erExtraWeight[unit] * 2 : 1));
|
||||
};
|
||||
const crew = () => {
|
||||
return Math.round(payload.pilot + payload.firstOfficer + payload.engineer);
|
||||
};
|
||||
const cgs = (): [string, string] => {
|
||||
return [CGs[0].toFixed(1), CGs[1].toFixed(1)];
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<Profile
|
||||
type="F"
|
||||
isER={isER}
|
||||
upper1={`${upper1()}`}
|
||||
upper2={`${upper2()}`}
|
||||
upper3={`${upper3()}`}
|
||||
upper4={`${upper4()}`}
|
||||
lower1={`${lower1()}`}
|
||||
lower2={`${lower2()}`}
|
||||
OEW={`${_OEW()}`}
|
||||
crew={`${crew()}`}
|
||||
unit={unit.toUpperCase()}
|
||||
inPreview={inPreview}
|
||||
CGs={cgs()}
|
||||
/>
|
||||
<Tabbar tabs={['Simbrief', 'ZFW', 'Cargo']} selectedTab={selectedTab} setSelectedTab={setSelectedTab} />
|
||||
|
||||
<div className="relative flex w-full items-center justify-start gap-x-6">
|
||||
<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={() => {
|
||||
console.log('TODO: SET PAYLOAD IN SIM');
|
||||
setInPreview(false);
|
||||
}}
|
||||
>
|
||||
Load
|
||||
</button>
|
||||
<button
|
||||
className="middle none center rounded-lg bg-red-600 px-6 py-3 font-sans text-xs font-bold uppercase text-white shadow-md shadow-red-500/20 transition-all hover:shadow-lg hover:shadow-red-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={() => {
|
||||
console.log('TODO: CLEAR PAYLOAD IN SIM');
|
||||
setInPreview(true);
|
||||
}}
|
||||
>
|
||||
Unload
|
||||
</button>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default Freight;
|
||||
@@ -0,0 +1,132 @@
|
||||
import { FC, useState } from 'react';
|
||||
import { GSX_SERVICE_CALLED, GSX_SERVICE_FINISHED } from '../../constants';
|
||||
import { LoadingState } from '../../types/general';
|
||||
import { WASMDataF } from '../../types/WASMData';
|
||||
import OptionsF from '../options/OptionsF';
|
||||
import Profile from '../profile/Profile';
|
||||
import SBEntryF from '../SBEntry/SBEntryF';
|
||||
import StationEntryF from '../stationEntry/StationEntryF';
|
||||
import Tabbar from '../tabbar/Tabbar';
|
||||
import ZFWEntryF from '../zfwEntry/ZFWEntryF';
|
||||
|
||||
interface FreighterProps {
|
||||
WASMData: WASMDataF;
|
||||
username?: string;
|
||||
}
|
||||
|
||||
const Freighter: FC<FreighterProps> = ({ WASMData, username }) => {
|
||||
const [selectedTab, setSelectedTab] = useState(0);
|
||||
const [loadingState, setLoadingState] = useState<LoadingState>('preview');
|
||||
|
||||
const upper1 = (overrideState: LoadingState = loadingState) => {
|
||||
if (overrideState !== 'loaded') return Math.round(WASMData.targetPayload.upper1);
|
||||
|
||||
return Math.round(WASMData.livePayload.upper1);
|
||||
};
|
||||
const upper2 = (overrideState: LoadingState = loadingState) => {
|
||||
if (overrideState !== 'loaded') return Math.round(WASMData.targetPayload.upper2);
|
||||
|
||||
return Math.round(WASMData.livePayload.upper2);
|
||||
};
|
||||
const upper3 = (overrideState: LoadingState = loadingState) => {
|
||||
if (overrideState !== 'loaded') return Math.round(WASMData.targetPayload.upper3);
|
||||
|
||||
return Math.round(WASMData.livePayload.upper3);
|
||||
};
|
||||
const upper4 = (overrideState: LoadingState = loadingState) => {
|
||||
if (overrideState !== 'loaded') return Math.round(WASMData.targetPayload.upper4);
|
||||
|
||||
return Math.round(WASMData.livePayload.upper4);
|
||||
};
|
||||
const lower1 = () => {
|
||||
if (loadingState !== 'loaded' && !GSXActive()) return Math.round(WASMData.targetPayload.lowerForward);
|
||||
|
||||
return Math.round(WASMData.livePayload.lowerForward);
|
||||
};
|
||||
const lower2 = () => {
|
||||
if (loadingState !== 'loaded' && !GSXActive()) return Math.round(WASMData.targetPayload.lowerRear);
|
||||
|
||||
return Math.round(WASMData.livePayload.lowerRear);
|
||||
};
|
||||
const OEW = () => {
|
||||
if (loadingState !== 'loaded' && !GSXActive()) return Math.round(WASMData.targetPayload.empty);
|
||||
|
||||
return Math.round(WASMData.livePayload.empty);
|
||||
};
|
||||
const crew = () => {
|
||||
if (loadingState !== 'loaded' && !GSXActive()) return Math.round(WASMData.targetPayload.crew);
|
||||
|
||||
return Math.round(WASMData.livePayload.crew);
|
||||
};
|
||||
|
||||
const GSXActive = () => {
|
||||
return (
|
||||
(WASMData.GSX.boardingState >= GSX_SERVICE_CALLED || WASMData.GSX.deboardingState >= GSX_SERVICE_CALLED) &&
|
||||
WASMData.GSX.deboardingState !== GSX_SERVICE_FINISHED
|
||||
);
|
||||
};
|
||||
|
||||
const CGs = (): [string, boolean, string, boolean] => {
|
||||
if (loadingState !== 'loaded' && !GSXActive()) {
|
||||
return [
|
||||
WASMData.targetPayload.ZFWCG.toFixed(1),
|
||||
WASMData.targetPayload.ZFWCG < WASMData.limits.minCG || WASMData.targetPayload.ZFWCG > WASMData.limits.maxCG,
|
||||
WASMData.targetPayload.TOCG.toFixed(1),
|
||||
WASMData.targetPayload.TOCG < WASMData.limits.minCG || WASMData.targetPayload.TOCG > WASMData.limits.maxCG,
|
||||
];
|
||||
}
|
||||
|
||||
return [
|
||||
WASMData.livePayload.ZFWCG.toFixed(1),
|
||||
WASMData.livePayload.ZFWCG < WASMData.limits.minCG || WASMData.livePayload.ZFWCG > WASMData.limits.maxCG,
|
||||
WASMData.livePayload.TOCG.toFixed(1),
|
||||
WASMData.livePayload.TOCG < WASMData.limits.minCG || WASMData.livePayload.TOCG > WASMData.limits.maxCG,
|
||||
];
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<Profile
|
||||
type="F"
|
||||
isER={WASMData.userData.isER}
|
||||
upper1={`${upper1(GSXActive() ? 'loaded' : loadingState)}`}
|
||||
upper2={`${upper2(GSXActive() ? 'loaded' : loadingState)}`}
|
||||
upper3={`${upper3(GSXActive() ? 'loaded' : loadingState)}`}
|
||||
upper4={`${upper4(GSXActive() ? 'loaded' : loadingState)}`}
|
||||
lower1={`${lower1()}`}
|
||||
lower2={`${lower2()}`}
|
||||
OEW={`${OEW()}`}
|
||||
crew={`${crew()}`}
|
||||
unit={WASMData.userData.isImperial ? 'LBS' : 'KG'}
|
||||
inPreview={loadingState !== 'loaded' && !GSXActive()}
|
||||
CGs={CGs()}
|
||||
/>
|
||||
<Tabbar
|
||||
tabs={
|
||||
username ? ['Simbrief', 'ZFW', 'Passengers & Cargo', 'Options'] : ['ZFW', 'Passengers & Cargo', 'Options']
|
||||
}
|
||||
selectedTab={selectedTab}
|
||||
setSelectedTab={setSelectedTab}
|
||||
/>
|
||||
{username && selectedTab === 0 && (
|
||||
<SBEntryF
|
||||
WASMData={WASMData}
|
||||
loadingState={loadingState}
|
||||
username={username}
|
||||
setLoadingState={setLoadingState}
|
||||
/>
|
||||
)}
|
||||
{((username && selectedTab === 1) || (!username && selectedTab === 0)) && (
|
||||
<ZFWEntryF WASMData={WASMData} loadingState={loadingState} setLoadingState={setLoadingState} />
|
||||
)}
|
||||
{((username && selectedTab === 2) || (!username && selectedTab === 1)) && (
|
||||
<StationEntryF WASMData={WASMData} loadingState={loadingState} setLoadingState={setLoadingState} />
|
||||
)}
|
||||
{((username && selectedTab === 3) || (!username && selectedTab === 2)) && (
|
||||
<OptionsF WASMData={WASMData} loadingState={loadingState} />
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default Freighter;
|
||||
@@ -0,0 +1,42 @@
|
||||
import { FC } from 'react';
|
||||
import { GSX_SERVICE_CALLED, GSX_SERVICE_FINISHED } from '../../constants';
|
||||
import { LoadingState } from '../../types/general';
|
||||
import { WASMDataF } from '../../types/WASMData';
|
||||
import { CoherentCallOptionsSet } from '../../utils/utils';
|
||||
import ToggleComponent from '../toggleComponent/ToggleComponent';
|
||||
|
||||
interface OptionsFProps {
|
||||
WASMData: WASMDataF;
|
||||
loadingState: LoadingState;
|
||||
}
|
||||
|
||||
const OptionsF: FC<OptionsFProps> = ({ WASMData, loadingState }) => {
|
||||
const GSXActive = () => {
|
||||
return (
|
||||
(WASMData.GSX.boardingState >= GSX_SERVICE_CALLED || WASMData.GSX.deboardingState >= GSX_SERVICE_CALLED) &&
|
||||
WASMData.GSX.deboardingState !== GSX_SERVICE_FINISHED
|
||||
);
|
||||
};
|
||||
|
||||
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">
|
||||
<ToggleComponent
|
||||
optionName="GSX Sync"
|
||||
value={WASMData.options.GSXSync}
|
||||
leftLabel={{ value: true }}
|
||||
rightLabel={{ value: false }}
|
||||
backgroundColor="bg-zinc-700"
|
||||
setValue={(value) => {
|
||||
CoherentCallOptionsSet(value);
|
||||
}}
|
||||
disabled={loadingState !== 'preview' || GSXActive()}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default OptionsF;
|
||||
@@ -0,0 +1,90 @@
|
||||
import { FC, useEffect, useState } from 'react';
|
||||
import { GSX_SERVICE_CALLED, GSX_SERVICE_FINISHED } from '../../constants';
|
||||
import { LoadingState } from '../../types/general';
|
||||
import { WASMDataPax } from '../../types/WASMData';
|
||||
import { CoherentCallOptionsSet } from '../../utils/utils';
|
||||
import ToggleComponent from '../toggleComponent/ToggleComponent';
|
||||
|
||||
interface OptionsPaxProps {
|
||||
WASMData: WASMDataPax;
|
||||
loadingState: LoadingState;
|
||||
}
|
||||
|
||||
const OptionsPax: FC<OptionsPaxProps> = ({ WASMData, loadingState }) => {
|
||||
const [paxWeight, setPaxWeight] = useState(WASMData.options.paxWeight);
|
||||
const [bagWeight, setBagWeight] = useState(WASMData.options.bagWeight);
|
||||
|
||||
const GSXActive = () => {
|
||||
return (
|
||||
(WASMData.GSX.boardingState >= GSX_SERVICE_CALLED || WASMData.GSX.deboardingState >= GSX_SERVICE_CALLED) &&
|
||||
WASMData.GSX.deboardingState !== GSX_SERVICE_FINISHED
|
||||
);
|
||||
};
|
||||
|
||||
const updateData = () => {
|
||||
CoherentCallOptionsSet(undefined, paxWeight, bagWeight);
|
||||
};
|
||||
|
||||
const handleInput = (input: string, maxValue: number, setter: (value: number) => void) => {
|
||||
if (!input) {
|
||||
setter(0);
|
||||
return;
|
||||
}
|
||||
|
||||
const converted = parseInt(input);
|
||||
if (converted) {
|
||||
if (converted < 0) setter(0);
|
||||
else if (converted > maxValue) setter(maxValue);
|
||||
else setter(converted);
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => updateData(), [paxWeight, bagWeight]);
|
||||
|
||||
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">
|
||||
<ToggleComponent
|
||||
optionName="GSX Sync"
|
||||
value={WASMData.options.GSXSync}
|
||||
leftLabel={{ value: true }}
|
||||
rightLabel={{ value: false }}
|
||||
backgroundColor="bg-zinc-700"
|
||||
setValue={(value) => {
|
||||
CoherentCallOptionsSet(value);
|
||||
}}
|
||||
disabled={loadingState !== 'preview' || GSXActive()}
|
||||
/>
|
||||
</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>Pax Weight ({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={paxWeight}
|
||||
onChange={(e) => handleInput(e.target.value, Number.MAX_VALUE, setPaxWeight)}
|
||||
disabled={loadingState !== 'preview' || GSXActive()}
|
||||
/>
|
||||
</div>
|
||||
<div className="relative flex w-full items-center justify-between bg-zinc-700 p-2 px-4">
|
||||
<label>Bag Weight ({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={bagWeight}
|
||||
onChange={(e) => handleInput(e.target.value, Number.MAX_VALUE, setBagWeight)}
|
||||
disabled={loadingState !== 'preview' || GSXActive()}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default OptionsPax;
|
||||
@@ -1,167 +1,109 @@
|
||||
import { FC, useEffect, useState } from 'react';
|
||||
import { PaxConfig, PayloadPax } from '../../configs/pax';
|
||||
import { Fuel, initialPayload, SharedConfig } from '../../configs/shared';
|
||||
import { FC, useState } from 'react';
|
||||
import { GSX_SERVICE_CALLED, GSX_SERVICE_FINISHED } from '../../constants';
|
||||
import { LoadingState } from '../../types/general';
|
||||
import { WASMDataPax } from '../../types/WASMData';
|
||||
import OptionsPax from '../options/OptionsPax';
|
||||
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';
|
||||
import ZFWEntryPax from '../zfwEntry/ZFWEntryPax';
|
||||
|
||||
interface PaxProps {
|
||||
isER: boolean;
|
||||
unit: 'kg' | 'lbs';
|
||||
CGs: [number, number];
|
||||
payloadLive: PayloadPax;
|
||||
fuelLive: Fuel;
|
||||
WASMData: WASMDataPax;
|
||||
username?: string;
|
||||
GSXPaxNum: number;
|
||||
GSXCargoPercent: number;
|
||||
GSXState: 'boarding' | 'deboarding' | 'idle';
|
||||
}
|
||||
|
||||
const Pax: FC<PaxProps> = ({
|
||||
isER,
|
||||
unit,
|
||||
CGs,
|
||||
fuelLive,
|
||||
payloadLive,
|
||||
username,
|
||||
GSXPaxNum,
|
||||
GSXCargoPercent,
|
||||
GSXState,
|
||||
}) => {
|
||||
const Pax: FC<PaxProps> = ({ WASMData, username }) => {
|
||||
const [selectedTab, setSelectedTab] = useState(0);
|
||||
const [payload, setPayload] = useState<PayloadPax>(initialPayload);
|
||||
const [loadingState, setLoadingState] = useState<'preview' | 'accepted' | 'loaded'>('preview');
|
||||
const [loadingState, setLoadingState] = useState<LoadingState>('preview');
|
||||
|
||||
const upper1 = (overrideState: 'preview' | 'accepted' | 'loaded' = loadingState) => {
|
||||
if (overrideState !== 'loaded')
|
||||
return PaxConfig.weightToPax(payload.business1Left + payload.business1Center + payload.business1Right, unit);
|
||||
const upper1 = (overrideState: LoadingState = loadingState) => {
|
||||
if (overrideState !== 'loaded') return WASMData.targetPayload.business1;
|
||||
|
||||
return PaxConfig.weightToPax(
|
||||
payloadLive.business1Left + payloadLive.business1Center + payloadLive.business1Right,
|
||||
unit
|
||||
);
|
||||
return WASMData.livePayload.business1;
|
||||
};
|
||||
const upper2 = (overrideState: 'preview' | 'accepted' | 'loaded' = loadingState) => {
|
||||
if (overrideState !== 'loaded')
|
||||
return PaxConfig.weightToPax(payload.business2Left + payload.business2Center + payload.business2Right, unit);
|
||||
const upper2 = (overrideState: LoadingState = loadingState) => {
|
||||
if (overrideState !== 'loaded') return WASMData.targetPayload.business2;
|
||||
|
||||
return PaxConfig.weightToPax(
|
||||
payloadLive.business2Left + payloadLive.business2Center + payloadLive.business2Right,
|
||||
unit
|
||||
);
|
||||
return WASMData.livePayload.business2;
|
||||
};
|
||||
const upper3 = (overrideState: 'preview' | 'accepted' | 'loaded' = loadingState) => {
|
||||
if (overrideState !== 'loaded')
|
||||
return PaxConfig.weightToPax(payload.economy1Left + payload.economy1Center + payload.economy1Right, unit);
|
||||
const upper3 = (overrideState: LoadingState = loadingState) => {
|
||||
if (overrideState !== 'loaded') return WASMData.targetPayload.economy1;
|
||||
|
||||
return PaxConfig.weightToPax(
|
||||
payloadLive.economy1Left + payloadLive.economy1Center + payloadLive.economy1Right,
|
||||
unit
|
||||
);
|
||||
return WASMData.livePayload.economy1;
|
||||
};
|
||||
const upper4 = (overrideState: 'preview' | 'accepted' | 'loaded' = loadingState) => {
|
||||
if (overrideState !== 'loaded')
|
||||
return PaxConfig.weightToPax(payload.economy2Left + payload.economy2Center + payload.economy2Right, unit);
|
||||
const upper4 = (overrideState: LoadingState = loadingState) => {
|
||||
if (overrideState !== 'loaded') return WASMData.targetPayload.economy2;
|
||||
|
||||
return PaxConfig.weightToPax(
|
||||
payloadLive.economy2Left + payloadLive.economy2Center + payloadLive.economy2Right,
|
||||
unit
|
||||
);
|
||||
return WASMData.livePayload.economy2;
|
||||
};
|
||||
const lower1 = () => {
|
||||
if (loadingState !== 'loaded') return Math.round(payload.forwardCargo);
|
||||
if (loadingState !== 'loaded' && !GSXActive()) return Math.round(WASMData.targetPayload.forwardCargo);
|
||||
|
||||
return Math.round(payloadLive.forwardCargo);
|
||||
return Math.round(WASMData.livePayload.forwardCargo);
|
||||
};
|
||||
const lower2 = () => {
|
||||
if (loadingState !== 'loaded') return Math.round(payload.rearCargo);
|
||||
if (loadingState !== 'loaded' && !GSXActive()) return Math.round(WASMData.targetPayload.rearCargo);
|
||||
|
||||
return Math.round(payloadLive.rearCargo);
|
||||
return Math.round(WASMData.livePayload.rearCargo);
|
||||
};
|
||||
const _OEW = () => {
|
||||
if (loadingState !== 'loaded')
|
||||
return Math.round(payloadLive.empty + (isER ? SharedConfig.erExtraWeight[unit] * 2 : 1));
|
||||
const OEW = () => {
|
||||
if (loadingState !== 'loaded' && !GSXActive()) return Math.round(WASMData.targetPayload.empty);
|
||||
|
||||
return Math.round(payloadLive.empty + payloadLive.leftAuxPax + payloadLive.rightAuxPax);
|
||||
return Math.round(WASMData.livePayload.empty);
|
||||
};
|
||||
const crew = () => {
|
||||
if (loadingState !== 'loaded') return PaxConfig.weights.base[unit].total;
|
||||
if (loadingState !== 'loaded' && !GSXActive()) return Math.round(WASMData.targetPayload.crew);
|
||||
|
||||
return Math.round(
|
||||
payloadLive.cabinCrewFront +
|
||||
payloadLive.cabinCrewRear +
|
||||
payloadLive.pilot +
|
||||
payloadLive.firstOfficer +
|
||||
payloadLive.engineer
|
||||
return Math.round(WASMData.livePayload.crew);
|
||||
};
|
||||
|
||||
const GSXActive = () => {
|
||||
return (
|
||||
(WASMData.GSX.boardingState >= GSX_SERVICE_CALLED || WASMData.GSX.deboardingState >= GSX_SERVICE_CALLED) &&
|
||||
WASMData.GSX.deboardingState !== GSX_SERVICE_FINISHED
|
||||
);
|
||||
};
|
||||
|
||||
const _CGs = (): [string, boolean, string, boolean] => {
|
||||
if (loadingState !== 'loaded') {
|
||||
const __CGs = PaxConfig.calculateCGs(
|
||||
{
|
||||
...payload,
|
||||
empty: payloadLive.empty,
|
||||
cabinCrewFront: PaxConfig.weights.base[unit].cabinCrewFront,
|
||||
cabinCrewRear: PaxConfig.weights.base[unit].cabinCrewRear,
|
||||
pilot: PaxConfig.weights.base[unit].pilot,
|
||||
firstOfficer: PaxConfig.weights.base[unit].firstOfficer,
|
||||
engineer: PaxConfig.weights.base[unit].engineer,
|
||||
leftAuxPax: isER ? SharedConfig.erExtraWeight[unit] : 0,
|
||||
rightAuxPax: isER ? SharedConfig.erExtraWeight[unit] : 0,
|
||||
},
|
||||
fuelLive
|
||||
);
|
||||
const CGs = (): [string, boolean, string, boolean] => {
|
||||
if (loadingState !== 'loaded' && !GSXActive()) {
|
||||
return [
|
||||
__CGs[0].toFixed(1),
|
||||
__CGs[0] < SharedConfig.CGLimits.min || __CGs[0] > SharedConfig.CGLimits.max,
|
||||
__CGs[1].toFixed(1),
|
||||
__CGs[1] < SharedConfig.CGLimits.min || __CGs[1] > SharedConfig.CGLimits.max,
|
||||
WASMData.targetPayload.ZFWCG.toFixed(1),
|
||||
WASMData.targetPayload.ZFWCG < WASMData.limits.minCG || WASMData.targetPayload.ZFWCG > WASMData.limits.maxCG,
|
||||
WASMData.targetPayload.TOCG.toFixed(1),
|
||||
WASMData.targetPayload.TOCG < WASMData.limits.minCG || WASMData.targetPayload.TOCG > WASMData.limits.maxCG,
|
||||
];
|
||||
}
|
||||
|
||||
return [
|
||||
CGs[0].toFixed(1),
|
||||
CGs[0] < SharedConfig.CGLimits.min || CGs[0] > SharedConfig.CGLimits.max,
|
||||
CGs[1].toFixed(1),
|
||||
CGs[1] < SharedConfig.CGLimits.min || CGs[1] > SharedConfig.CGLimits.max,
|
||||
WASMData.livePayload.ZFWCG.toFixed(1),
|
||||
WASMData.livePayload.ZFWCG < WASMData.limits.minCG || WASMData.livePayload.ZFWCG > WASMData.limits.maxCG,
|
||||
WASMData.livePayload.TOCG.toFixed(1),
|
||||
WASMData.livePayload.TOCG < WASMData.limits.minCG || WASMData.livePayload.TOCG > WASMData.limits.maxCG,
|
||||
];
|
||||
};
|
||||
|
||||
//TODO: Make GSX optional
|
||||
useEffect(() => {
|
||||
if (GSXState === 'idle') return;
|
||||
|
||||
PaxConfig.setWeightsProgressive(
|
||||
payload,
|
||||
GSXState === 'boarding' ? GSXPaxNum : payload.paxCount.total - GSXPaxNum,
|
||||
GSXCargoPercent,
|
||||
unit
|
||||
);
|
||||
}, [GSXPaxNum, GSXCargoPercent, GSXState]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Profile
|
||||
type="PAX"
|
||||
isER={isER}
|
||||
upper1={`${upper1()}`}
|
||||
upper1max={loadingState === 'loaded' ? `${upper1('preview')}` : `${PaxConfig.stationMax.business1}`}
|
||||
upper2={`${upper2()}`}
|
||||
upper2max={loadingState === 'loaded' ? `${upper2('preview')}` : `${PaxConfig.stationMax.business2}`}
|
||||
upper3={`${upper3()}`}
|
||||
upper3max={loadingState === 'loaded' ? `${upper3('preview')}` : `${PaxConfig.stationMax.economy1}`}
|
||||
upper4={`${upper4()}`}
|
||||
upper4max={loadingState === 'loaded' ? `${upper4('preview')}` : `${PaxConfig.stationMax.economy2}`}
|
||||
isER={WASMData.userData.isER}
|
||||
upper1={`${upper1(GSXActive() ? 'loaded' : loadingState)}`}
|
||||
upper1max={loadingState === 'loaded' || GSXActive() ? `${upper1('preview')}` : `${WASMData.limits.business1}`}
|
||||
upper2={`${upper2(GSXActive() ? 'loaded' : loadingState)}`}
|
||||
upper2max={loadingState === 'loaded' || GSXActive() ? `${upper2('preview')}` : `${WASMData.limits.business2}`}
|
||||
upper3={`${upper3(GSXActive() ? 'loaded' : loadingState)}`}
|
||||
upper3max={loadingState === 'loaded' || GSXActive() ? `${upper3('preview')}` : `${WASMData.limits.economy1}`}
|
||||
upper4={`${upper4(GSXActive() ? 'loaded' : loadingState)}`}
|
||||
upper4max={loadingState === 'loaded' || GSXActive() ? `${upper4('preview')}` : `${WASMData.limits.economy2}`}
|
||||
lower1={`${lower1()}`}
|
||||
lower2={`${lower2()}`}
|
||||
OEW={`${_OEW()}`}
|
||||
OEW={`${OEW()}`}
|
||||
crew={`${crew()}`}
|
||||
unit={unit.toUpperCase()}
|
||||
inPreview={loadingState !== 'loaded'}
|
||||
CGs={_CGs()}
|
||||
unit={WASMData.userData.isImperial ? 'LBS' : 'KG'}
|
||||
inPreview={loadingState !== 'loaded' && !GSXActive()}
|
||||
CGs={CGs()}
|
||||
/>
|
||||
<Tabbar
|
||||
tabs={
|
||||
@@ -170,63 +112,22 @@ const Pax: FC<PaxProps> = ({
|
||||
selectedTab={selectedTab}
|
||||
setSelectedTab={setSelectedTab}
|
||||
/>
|
||||
|
||||
{username && selectedTab === 0 && (
|
||||
<SBEntryPax
|
||||
unit={unit}
|
||||
isER={isER}
|
||||
initialPayload={payload}
|
||||
fuelLive={fuelLive}
|
||||
payloadLive={payloadLive}
|
||||
WASMData={WASMData}
|
||||
loadingState={loadingState}
|
||||
username={username}
|
||||
setLoadingState={setLoadingState}
|
||||
updateView={(_payload) => {
|
||||
setPayload(_payload);
|
||||
}}
|
||||
loadAircraft={() => {
|
||||
PaxConfig.setBaseWeight(unit, isER);
|
||||
PaxConfig.setWeights(payload, unit);
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
|
||||
{((username && selectedTab === 1) || (!username && selectedTab === 0)) && (
|
||||
<ZFWEntryPax
|
||||
unit={unit}
|
||||
isER={isER}
|
||||
initialPayload={payload}
|
||||
fuelLive={fuelLive}
|
||||
payloadLive={payloadLive}
|
||||
loadingState={loadingState}
|
||||
setLoadingState={setLoadingState}
|
||||
updateView={(_payload) => {
|
||||
setPayload(_payload);
|
||||
}}
|
||||
loadAircraft={() => {
|
||||
PaxConfig.setBaseWeight(unit, isER);
|
||||
PaxConfig.setWeights(payload, unit);
|
||||
}}
|
||||
/>
|
||||
<ZFWEntryPax WASMData={WASMData} loadingState={loadingState} setLoadingState={setLoadingState} />
|
||||
)}
|
||||
|
||||
{((username && selectedTab === 2) || (!username && selectedTab === 1)) && (
|
||||
<StationEntryPax
|
||||
unit={unit}
|
||||
isER={isER}
|
||||
initialPayload={payload}
|
||||
fuelLive={fuelLive}
|
||||
payloadLive={payloadLive}
|
||||
loadingState={loadingState}
|
||||
setLoadingState={setLoadingState}
|
||||
updateView={(_payload) => {
|
||||
setPayload(_payload);
|
||||
}}
|
||||
loadAircraft={() => {
|
||||
PaxConfig.setBaseWeight(unit, isER);
|
||||
PaxConfig.setWeights(payload, unit);
|
||||
}}
|
||||
/>
|
||||
<StationEntryPax WASMData={WASMData} loadingState={loadingState} setLoadingState={setLoadingState} />
|
||||
)}
|
||||
{((username && selectedTab === 3) || (!username && selectedTab === 2)) && (
|
||||
<OptionsPax WASMData={WASMData} loadingState={loadingState} />
|
||||
)}
|
||||
</>
|
||||
);
|
||||
|
||||
@@ -0,0 +1,227 @@
|
||||
import { FC, useEffect, useState } from 'react';
|
||||
import { GSX_SERVICE_CALLED, GSX_SERVICE_FINISHED } from '../../constants';
|
||||
import { LoadingState } from '../../types/general';
|
||||
import { WASMDataF } from '../../types/WASMData';
|
||||
import { CoherentCallStationEntryF, inRangeOf, loadAircraft, unloadAircraft } from '../../utils/utils';
|
||||
import ActionBar from '../actionbar/ActionBar';
|
||||
|
||||
interface StationEntryProps {
|
||||
WASMData: WASMDataF;
|
||||
loadingState: LoadingState;
|
||||
setLoadingState: (newState: LoadingState) => void;
|
||||
}
|
||||
|
||||
const StationEntryF: FC<StationEntryProps> = ({ WASMData, loadingState, setLoadingState }) => {
|
||||
const [upper1, setUpper1] = useState(WASMData.targetPayload.upper1);
|
||||
const [upper2, setUpper2] = useState(WASMData.targetPayload.upper2);
|
||||
const [upper3, setUpper3] = useState(WASMData.targetPayload.upper3);
|
||||
const [upper4, setUpper4] = useState(WASMData.targetPayload.upper4);
|
||||
const [lowerForward, setLowerForward] = useState(WASMData.targetPayload.lowerForward);
|
||||
const [lowerRear, setLowerRear] = useState(WASMData.targetPayload.lowerRear);
|
||||
const [fuel, setFuel] = useState(Math.round(WASMData.livePayload.fuel));
|
||||
const [fuelEnabled, setFuelEnabled] = useState(true);
|
||||
|
||||
const ZFW = () => {
|
||||
if (loadingState !== 'loaded' && !GSXActive()) return Math.round(WASMData.targetPayload.total);
|
||||
|
||||
return Math.round(WASMData.livePayload.total);
|
||||
};
|
||||
const ZFWValid = () => {
|
||||
return ZFW() <= WASMData.limits.maxZFW;
|
||||
};
|
||||
const GW = () => {
|
||||
return fuel + ZFW();
|
||||
};
|
||||
const GWValid = () => {
|
||||
return GW() <= WASMData.limits.maxTOW;
|
||||
};
|
||||
|
||||
const GSXActive = () => {
|
||||
return (
|
||||
(WASMData.GSX.boardingState >= GSX_SERVICE_CALLED || WASMData.GSX.deboardingState >= GSX_SERVICE_CALLED) &&
|
||||
WASMData.GSX.deboardingState !== GSX_SERVICE_FINISHED
|
||||
);
|
||||
};
|
||||
|
||||
const handleInput = (input: string, maxValue: number, setter: (value: number) => void) => {
|
||||
if (!input) {
|
||||
setter(0);
|
||||
return;
|
||||
}
|
||||
|
||||
const converted = parseInt(input);
|
||||
if (converted) {
|
||||
if (converted < 0) setter(0);
|
||||
else if (converted > maxValue) setter(maxValue);
|
||||
else setter(converted);
|
||||
}
|
||||
};
|
||||
|
||||
const updateData = () => {
|
||||
CoherentCallStationEntryF(upper1, upper2, upper3, upper4, lowerForward, lowerRear);
|
||||
};
|
||||
|
||||
useEffect(() => updateData(), [upper1, upper2, upper3, upper4, lowerForward, lowerRear]);
|
||||
useEffect(
|
||||
() =>
|
||||
setFuel((prev) => {
|
||||
if (prev > WASMData.limits.maxFuel) return WASMData.limits.maxFuel;
|
||||
return prev;
|
||||
}),
|
||||
[WASMData.userData.isER]
|
||||
);
|
||||
useEffect(() => {
|
||||
setFuelEnabled(inRangeOf(Math.round(WASMData.livePayload.fuel), fuel));
|
||||
}, [WASMData.livePayload.fuel]);
|
||||
|
||||
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' || GSXActive()}
|
||||
/>
|
||||
<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(WASMData.livePayload.fuel === fuel);
|
||||
}}
|
||||
disabled={loadingState !== 'preview' || !fuelEnabled || GSXActive()}
|
||||
>
|
||||
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="relative flex w-full items-center justify-between rounded-t-md bg-zinc-600 p-2 px-4">
|
||||
<label>Upper 1</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={upper1}
|
||||
onChange={(e) => handleInput(e.target.value, WASMData.limits.upper1, setUpper1)}
|
||||
disabled={loadingState !== 'preview' || GSXActive()}
|
||||
/>
|
||||
</div>
|
||||
<div className="relative flex w-full items-center justify-between bg-zinc-700 p-2 px-4">
|
||||
<label>Upper 2</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={upper2}
|
||||
onChange={(e) => handleInput(e.target.value, WASMData.limits.upper2, setUpper2)}
|
||||
disabled={loadingState !== 'preview' || GSXActive()}
|
||||
/>
|
||||
</div>
|
||||
<div className="relative flex w-full items-center justify-between bg-zinc-600 p-2 px-4">
|
||||
<label>Upper 3</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={upper3}
|
||||
onChange={(e) => handleInput(e.target.value, WASMData.limits.upper3, setUpper3)}
|
||||
disabled={loadingState !== 'preview' || GSXActive()}
|
||||
/>
|
||||
</div>
|
||||
<div className="relative flex w-full items-center justify-between bg-zinc-700 p-2 px-4">
|
||||
<label>Upper 4</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={upper4}
|
||||
onChange={(e) => handleInput(e.target.value, WASMData.limits.upper4, setUpper4)}
|
||||
disabled={loadingState !== 'preview' || GSXActive()}
|
||||
/>
|
||||
</div>
|
||||
<div className="relative flex w-full items-center justify-between bg-zinc-600 p-2 px-4">
|
||||
<label>Forward Cargo ({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={lowerForward}
|
||||
onChange={(e) => handleInput(e.target.value, WASMData.limits.lowerForward, setLowerForward)}
|
||||
disabled={loadingState !== 'preview' || GSXActive()}
|
||||
/>
|
||||
</div>
|
||||
<div className="relative flex w-full items-center justify-between rounded-b-md bg-zinc-700 p-2 px-4">
|
||||
<label>Aft Cargo ({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={lowerRear}
|
||||
onChange={(e) => handleInput(e.target.value, WASMData.limits.lowerRear, setLowerRear)}
|
||||
disabled={loadingState !== 'preview' || GSXActive()}
|
||||
/>
|
||||
</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>
|
||||
{loadingState !== 'loaded' && !GSXActive() ? 'Expected' : 'Actual'} ZFW (
|
||||
{WASMData.userData.isImperial ? 'lbs' : 'kg'})
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
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`}
|
||||
disabled
|
||||
value={ZFW()}
|
||||
/>
|
||||
</div>
|
||||
<div className="relative flex w-full items-center justify-between rounded-b-md bg-zinc-700 p-2 px-4">
|
||||
<label>
|
||||
{loadingState !== 'loaded' && !GSXActive() ? 'Expected' : 'Actual'} GW (
|
||||
{WASMData.userData.isImperial ? 'lbs' : 'kg'})
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
placeholder=""
|
||||
className={`w-1/2 rounded-lg border ${GWValid() ? 'border-white' : 'border-red-500 text-red-500'} bg-zinc-700 px-3 py-2 text-right`}
|
||||
disabled
|
||||
value={GW()}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<ActionBar
|
||||
loadingState={loadingState}
|
||||
loadDisabled={!ZFWValid() || !GWValid()}
|
||||
GSXSync={WASMData.options.GSXSync}
|
||||
GSXActive={GSXActive()}
|
||||
load={() => {
|
||||
setLoadingState('loaded');
|
||||
|
||||
loadAircraft();
|
||||
}}
|
||||
unload={() => {
|
||||
setLoadingState('preview');
|
||||
|
||||
unloadAircraft();
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default StationEntryF;
|
||||
@@ -1,117 +1,46 @@
|
||||
import { FC, useEffect, useState } from 'react';
|
||||
import { PaxConfig, PayloadPax } from '../../configs/pax';
|
||||
import { Fuel, SharedConfig } from '../../configs/shared';
|
||||
import { GSX_SERVICE_CALLED, GSX_SERVICE_FINISHED } from '../../constants';
|
||||
import { LoadingState } from '../../types/general';
|
||||
import { WASMDataPax } from '../../types/WASMData';
|
||||
import { CoherentCallStationEntryPax, inRangeOf, loadAircraft, unloadAircraft } from '../../utils/utils';
|
||||
import ActionBar from '../actionbar/ActionBar';
|
||||
|
||||
interface StationEntryProps {
|
||||
unit: 'kg' | 'lbs';
|
||||
isER: boolean;
|
||||
initialPayload: PayloadPax;
|
||||
fuelLive: Fuel;
|
||||
payloadLive: PayloadPax;
|
||||
loadingState: 'preview' | 'accepted' | 'loaded';
|
||||
setLoadingState: (newState: StationEntryProps['loadingState']) => void;
|
||||
updateView: (payload: PayloadPax) => void;
|
||||
loadAircraft: () => void;
|
||||
WASMData: WASMDataPax;
|
||||
loadingState: LoadingState;
|
||||
setLoadingState: (newState: LoadingState) => void;
|
||||
}
|
||||
|
||||
const StationEntryPax: FC<StationEntryProps> = ({
|
||||
unit,
|
||||
isER,
|
||||
initialPayload,
|
||||
fuelLive,
|
||||
payloadLive,
|
||||
loadingState,
|
||||
setLoadingState,
|
||||
updateView,
|
||||
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 StationEntryPax: FC<StationEntryProps> = ({ WASMData, loadingState, setLoadingState }) => {
|
||||
const [business1, setBusiness1] = useState(WASMData.targetPayload.business1);
|
||||
const [business2, setBusiness2] = useState(WASMData.targetPayload.business2);
|
||||
const [economy1, setEconomy1] = useState(WASMData.targetPayload.economy1);
|
||||
const [economy2, setEconomy2] = useState(WASMData.targetPayload.economy2);
|
||||
const [forwardCargo, setForwardCargo] = useState(WASMData.targetPayload.forwardCargo);
|
||||
const [rearCargo, setRearCargo] = useState(WASMData.targetPayload.rearCargo);
|
||||
const [fuel, setFuel] = useState(Math.round(WASMData.livePayload.fuel));
|
||||
const [fuelEnabled, setFuelEnabled] = useState(true);
|
||||
|
||||
const ZFW = () => {
|
||||
if (loadingState !== 'loaded')
|
||||
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
|
||||
);
|
||||
if (loadingState !== 'loaded' && !GSXActive()) return Math.round(WASMData.targetPayload.total);
|
||||
|
||||
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
|
||||
);
|
||||
return Math.round(WASMData.livePayload.total);
|
||||
};
|
||||
const ZFWValid = () => {
|
||||
return ZFW() <= PaxConfig.maxZWF[unit];
|
||||
return ZFW() <= WASMData.limits.maxZFW;
|
||||
};
|
||||
|
||||
const GW = () => {
|
||||
return fuel + ZFW();
|
||||
};
|
||||
const GWValid = () => {
|
||||
return GW() <= (isER ? SharedConfig.maxTOW.er[unit] : SharedConfig.maxTOW.norm[unit]);
|
||||
return GW() <= WASMData.limits.maxTOW;
|
||||
};
|
||||
|
||||
const GSXActive = () => {
|
||||
return (
|
||||
(WASMData.GSX.boardingState >= GSX_SERVICE_CALLED || WASMData.GSX.deboardingState >= GSX_SERVICE_CALLED) &&
|
||||
WASMData.GSX.deboardingState !== GSX_SERVICE_FINISHED
|
||||
);
|
||||
};
|
||||
|
||||
const handleInput = (input: string, maxValue: number, setter: (value: number) => void) => {
|
||||
@@ -128,37 +57,55 @@ const StationEntryPax: FC<StationEntryProps> = ({
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => _updateView(), [business1, business2, economy1, economy2, forwardCargo, rearCargo]);
|
||||
const updateData = () => {
|
||||
CoherentCallStationEntryPax(business1, business2, economy1, economy2, forwardCargo, rearCargo);
|
||||
};
|
||||
|
||||
useEffect(() => updateData(), [business1, business2, economy1, economy2, forwardCargo, rearCargo]);
|
||||
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]
|
||||
);
|
||||
|
||||
const _updateView = () => {
|
||||
const payload = PaxConfig.generateDistribution(
|
||||
payloadLive.empty,
|
||||
business1,
|
||||
business2,
|
||||
economy1,
|
||||
economy2,
|
||||
forwardCargo,
|
||||
rearCargo,
|
||||
unit,
|
||||
isER
|
||||
);
|
||||
|
||||
updateView(payload);
|
||||
};
|
||||
useEffect(() => {
|
||||
setFuelEnabled(inRangeOf(Math.round(WASMData.livePayload.fuel), fuel));
|
||||
}, [WASMData.livePayload.fuel]);
|
||||
|
||||
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' || GSXActive()}
|
||||
/>
|
||||
<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(WASMData.livePayload.fuel === fuel);
|
||||
}}
|
||||
disabled={loadingState !== 'preview' || !fuelEnabled || GSXActive()}
|
||||
>
|
||||
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="relative flex w-full items-center justify-between rounded-t-md bg-zinc-600 p-2 px-4">
|
||||
<label>Business</label>
|
||||
@@ -167,8 +114,8 @@ const StationEntryPax: FC<StationEntryProps> = ({
|
||||
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={business1}
|
||||
onChange={(e) => handleInput(e.target.value, PaxConfig.stationMax.business1, setBusiness1)}
|
||||
disabled={loadingState !== 'preview'}
|
||||
onChange={(e) => handleInput(e.target.value, WASMData.limits.business1, setBusiness1)}
|
||||
disabled={loadingState !== 'preview' || GSXActive()}
|
||||
/>
|
||||
</div>
|
||||
<div className="relative flex w-full items-center justify-between bg-zinc-700 p-2 px-4">
|
||||
@@ -178,8 +125,8 @@ const StationEntryPax: FC<StationEntryProps> = ({
|
||||
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={business2}
|
||||
onChange={(e) => handleInput(e.target.value, PaxConfig.stationMax.business2, setBusiness2)}
|
||||
disabled={loadingState !== 'preview'}
|
||||
onChange={(e) => handleInput(e.target.value, WASMData.limits.business2, setBusiness2)}
|
||||
disabled={loadingState !== 'preview' || GSXActive()}
|
||||
/>
|
||||
</div>
|
||||
<div className="relative flex w-full items-center justify-between bg-zinc-600 p-2 px-4">
|
||||
@@ -189,8 +136,8 @@ const StationEntryPax: FC<StationEntryProps> = ({
|
||||
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={economy1}
|
||||
onChange={(e) => handleInput(e.target.value, PaxConfig.stationMax.economy1, setEconomy1)}
|
||||
disabled={loadingState !== 'preview'}
|
||||
onChange={(e) => handleInput(e.target.value, WASMData.limits.economy1, setEconomy1)}
|
||||
disabled={loadingState !== 'preview' || GSXActive()}
|
||||
/>
|
||||
</div>
|
||||
<div className="relative flex w-full items-center justify-between bg-zinc-700 p-2 px-4">
|
||||
@@ -200,69 +147,39 @@ const StationEntryPax: FC<StationEntryProps> = ({
|
||||
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={economy2}
|
||||
onChange={(e) => handleInput(e.target.value, PaxConfig.stationMax.economy2, setEconomy2)}
|
||||
disabled={loadingState !== 'preview'}
|
||||
onChange={(e) => handleInput(e.target.value, WASMData.limits.economy2, setEconomy2)}
|
||||
disabled={loadingState !== 'preview' || GSXActive()}
|
||||
/>
|
||||
</div>
|
||||
<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
|
||||
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={forwardCargo}
|
||||
onChange={(e) => handleInput(e.target.value, SharedConfig.stationMax.forward[unit], setForwardCargo)}
|
||||
disabled={loadingState !== 'preview'}
|
||||
onChange={(e) => handleInput(e.target.value, WASMData.limits.forwardCargo, setForwardCargo)}
|
||||
disabled={loadingState !== 'preview' || GSXActive()}
|
||||
/>
|
||||
</div>
|
||||
<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
|
||||
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={rearCargo}
|
||||
onChange={(e) => handleInput(e.target.value, SharedConfig.stationMax.rear[unit], setRearCargo)}
|
||||
disabled={loadingState !== 'preview'}
|
||||
onChange={(e) => handleInput(e.target.value, WASMData.limits.rearCargo, setRearCargo)}
|
||||
disabled={loadingState !== 'preview' || GSXActive()}
|
||||
/>
|
||||
</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="relative flex w-full items-center justify-between rounded-t-md bg-zinc-600 p-2 px-4">
|
||||
<label>
|
||||
{loadingState !== 'loaded' ? 'Expected' : 'Actual'} ZFW ({unit})
|
||||
{loadingState !== 'loaded' && !GSXActive() ? 'Expected' : 'Actual'} ZFW (
|
||||
{WASMData.userData.isImperial ? 'lbs' : 'kg'})
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
@@ -274,7 +191,8 @@ const StationEntryPax: FC<StationEntryProps> = ({
|
||||
</div>
|
||||
<div className="relative flex w-full items-center justify-between rounded-b-md bg-zinc-700 p-2 px-4">
|
||||
<label>
|
||||
{loadingState !== 'loaded' ? 'Expected' : 'Actual'} GW ({unit})
|
||||
{loadingState !== 'loaded' && !GSXActive() ? 'Expected' : 'Actual'} GW (
|
||||
{WASMData.userData.isImperial ? 'lbs' : 'kg'})
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
@@ -288,9 +206,9 @@ const StationEntryPax: FC<StationEntryProps> = ({
|
||||
|
||||
<ActionBar
|
||||
loadingState={loadingState}
|
||||
acceptDisabled={!ZFWValid() || !GWValid()}
|
||||
accept={() => setLoadingState('accepted')}
|
||||
reject={() => setLoadingState('preview')}
|
||||
loadDisabled={!ZFWValid() || !GWValid()}
|
||||
GSXSync={WASMData.options.GSXSync}
|
||||
GSXActive={GSXActive()}
|
||||
load={() => {
|
||||
setLoadingState('loaded');
|
||||
|
||||
@@ -299,7 +217,7 @@ const StationEntryPax: FC<StationEntryProps> = ({
|
||||
unload={() => {
|
||||
setLoadingState('preview');
|
||||
|
||||
PaxConfig.unload(unit, isER);
|
||||
unloadAircraft();
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
interface ToggleComponentProps<T> {
|
||||
optionName: string;
|
||||
value: T;
|
||||
leftLabel: {
|
||||
value: T;
|
||||
label?: string;
|
||||
};
|
||||
rightLabel: {
|
||||
value: T;
|
||||
label?: string;
|
||||
};
|
||||
backgroundColor: string;
|
||||
disabled?: boolean;
|
||||
setValue: (value: T) => void;
|
||||
}
|
||||
|
||||
const ToggleComponent = <T,>({
|
||||
optionName,
|
||||
value,
|
||||
leftLabel,
|
||||
rightLabel,
|
||||
backgroundColor,
|
||||
disabled,
|
||||
setValue,
|
||||
}: ToggleComponentProps<T>) => {
|
||||
return (
|
||||
<div className="flex w-full items-center justify-between text-xs">
|
||||
<span>{optionName}</span>
|
||||
<div className="inline-flex w-1/2 rounded-md shadow-sm">
|
||||
<button
|
||||
type="button"
|
||||
className={`${value === leftLabel.value ? 'bg-green-700' : backgroundColor} w-1/2 rounded-l-lg border border-white px-4 py-2 text-white disabled:pointer-events-none disabled:opacity-50`}
|
||||
onClick={() => setValue(leftLabel.value)}
|
||||
disabled={disabled}
|
||||
>
|
||||
{leftLabel.label || 'Enabled'}
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
className={`${value === rightLabel.value ? 'bg-green-700' : backgroundColor} w-1/2 rounded-r-md border border-white px-4 py-2 text-white disabled:pointer-events-none disabled:opacity-50`}
|
||||
onClick={() => setValue(rightLabel.value)}
|
||||
disabled={disabled}
|
||||
>
|
||||
{rightLabel.label || 'Disabled'}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default ToggleComponent;
|
||||
@@ -0,0 +1,221 @@
|
||||
import { FC, useEffect, useState } from 'react';
|
||||
import { GSX_SERVICE_CALLED, GSX_SERVICE_FINISHED } from '../../constants';
|
||||
import { WASMDataF } from '../../types/WASMData';
|
||||
import { LoadingState } from '../../types/general';
|
||||
import { CoherentCallZFWEntry, inRangeOf, loadAircraft, unloadAircraft } from '../../utils/utils';
|
||||
import CGSelect from '../CGSelect/CGSelect';
|
||||
import ActionBar from '../actionbar/ActionBar';
|
||||
|
||||
interface ZFWEntryProps {
|
||||
WASMData: WASMDataF;
|
||||
loadingState: LoadingState;
|
||||
setLoadingState: (newState: LoadingState) => void;
|
||||
}
|
||||
|
||||
const ZFWEntryF: FC<ZFWEntryProps> = ({ WASMData, loadingState, setLoadingState }) => {
|
||||
const [CGTarget, setCGTarget] = useState(WASMData.targetPayload.CGTarget);
|
||||
const [fuel, setFuel] = useState(Math.round(WASMData.livePayload.fuel));
|
||||
const [ZFWTarget, setZFWTarget] = useState(Math.round(WASMData.targetPayload.total));
|
||||
const [fuelEnabled, setFuelEnabled] = useState(true);
|
||||
|
||||
const ZFW = () => {
|
||||
if (loadingState !== 'loaded' && !GSXActive()) return ZFWTarget;
|
||||
|
||||
return Math.round(WASMData.livePayload.total);
|
||||
};
|
||||
const ZFWValid = () => {
|
||||
return ZFW() <= WASMData.limits.maxZFW;
|
||||
};
|
||||
const GW = () => {
|
||||
return fuel + ZFW();
|
||||
};
|
||||
const GWValid = () => {
|
||||
return GW() <= WASMData.limits.maxTOW;
|
||||
};
|
||||
|
||||
const GSXActive = () => {
|
||||
return (
|
||||
(WASMData.GSX.boardingState >= GSX_SERVICE_CALLED || WASMData.GSX.deboardingState >= GSX_SERVICE_CALLED) &&
|
||||
WASMData.GSX.deboardingState !== GSX_SERVICE_FINISHED
|
||||
);
|
||||
};
|
||||
|
||||
const handleInput = (input: string, maxValue: number, setter: (value: number) => void) => {
|
||||
if (!input) {
|
||||
setter(0);
|
||||
return;
|
||||
}
|
||||
|
||||
const converted = parseInt(input);
|
||||
if (converted) {
|
||||
if (converted < 0) setter(0);
|
||||
else if (converted > maxValue) setter(maxValue);
|
||||
else setter(converted);
|
||||
}
|
||||
};
|
||||
const handleInputZFW = (input: string) => {
|
||||
if (!input) return;
|
||||
|
||||
const converted = parseInt(input);
|
||||
if (converted) {
|
||||
if (converted < 0) setZFWTarget(Math.round(WASMData.targetPayload.empty + WASMData.targetPayload.crew));
|
||||
else if (converted > WASMData.limits.maxZFW) setZFWTarget(WASMData.limits.maxZFW);
|
||||
else setZFWTarget(converted);
|
||||
}
|
||||
};
|
||||
const handleBlur = (input: string) => {
|
||||
const minZFW = Math.round(WASMData.targetPayload.empty + WASMData.targetPayload.crew);
|
||||
|
||||
if (!input) {
|
||||
setZFWTarget(minZFW);
|
||||
return;
|
||||
}
|
||||
|
||||
const converted = parseInt(input);
|
||||
if (converted) {
|
||||
if (converted < minZFW) setZFWTarget(minZFW);
|
||||
else if (converted > WASMData.limits.maxZFW) setZFWTarget(WASMData.limits.maxZFW);
|
||||
else setZFWTarget(converted);
|
||||
}
|
||||
|
||||
updateData(converted);
|
||||
};
|
||||
|
||||
useEffect(
|
||||
() =>
|
||||
setFuel((prev) => {
|
||||
if (prev > WASMData.limits.maxFuel) return WASMData.limits.maxFuel;
|
||||
return prev;
|
||||
}),
|
||||
[WASMData.userData.isER]
|
||||
);
|
||||
useEffect(() => {
|
||||
setFuelEnabled(inRangeOf(Math.round(WASMData.livePayload.fuel), fuel));
|
||||
}, [WASMData.livePayload.fuel]);
|
||||
|
||||
const updateData = (_ZFWTarget?: number, _CGTarget?: number) => {
|
||||
CoherentCallZFWEntry(_ZFWTarget ?? ZFWTarget, _CGTarget ?? CGTarget);
|
||||
};
|
||||
|
||||
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' || GSXActive()}
|
||||
/>
|
||||
<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(WASMData.livePayload.fuel === fuel);
|
||||
}}
|
||||
disabled={loadingState !== 'preview' || !fuelEnabled || GSXActive()}
|
||||
>
|
||||
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="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' || GSXActive()}
|
||||
/>
|
||||
</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' || GSXActive()}
|
||||
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="relative flex w-full items-center justify-between rounded-t-md bg-zinc-600 p-2 px-4">
|
||||
<label>
|
||||
{loadingState !== 'loaded' && !GSXActive() ? 'Expected' : 'Actual'} ZFW (
|
||||
{WASMData.userData.isImperial ? 'lbs' : 'kg'})
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
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`}
|
||||
disabled
|
||||
value={ZFW()}
|
||||
/>
|
||||
</div>
|
||||
<div className="relative flex w-full items-center justify-between rounded-b-md bg-zinc-700 p-2 px-4">
|
||||
<label>
|
||||
{loadingState !== 'loaded' && !GSXActive() ? 'Expected' : 'Actual'} GW (
|
||||
{WASMData.userData.isImperial ? 'lbs' : 'kg'})
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
placeholder=""
|
||||
className={`w-1/2 rounded-lg border ${GWValid() ? 'border-white' : 'border-red-500 text-red-500'} bg-zinc-700 px-3 py-2 text-right`}
|
||||
disabled
|
||||
value={GW()}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<ActionBar
|
||||
loadingState={loadingState}
|
||||
loadDisabled={!GWValid()}
|
||||
GSXSync={WASMData.options.GSXSync}
|
||||
GSXActive={GSXActive()}
|
||||
load={() => {
|
||||
setLoadingState('loaded');
|
||||
|
||||
loadAircraft();
|
||||
}}
|
||||
unload={() => {
|
||||
setLoadingState('preview');
|
||||
|
||||
unloadAircraft();
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default ZFWEntryF;
|
||||
@@ -1,106 +1,43 @@
|
||||
import { FC, useEffect, useState } from 'react';
|
||||
import { PaxConfig, PayloadPax } from '../../configs/pax';
|
||||
import { Fuel, SharedConfig } from '../../configs/shared';
|
||||
import { GSX_SERVICE_CALLED, GSX_SERVICE_FINISHED } from '../../constants';
|
||||
import { WASMDataPax } from '../../types/WASMData';
|
||||
import { LoadingState } from '../../types/general';
|
||||
import { CoherentCallZFWEntry, inRangeOf, loadAircraft, unloadAircraft } from '../../utils/utils';
|
||||
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';
|
||||
setLoadingState: (newState: StationEntryProps['loadingState']) => void;
|
||||
updateView: (payload: PayloadPax) => void;
|
||||
loadAircraft: () => void;
|
||||
interface ZFWEntryProps {
|
||||
WASMData: WASMDataPax;
|
||||
loadingState: LoadingState;
|
||||
setLoadingState: (newState: LoadingState) => void;
|
||||
}
|
||||
|
||||
const ZFWEntryPax: FC<StationEntryProps> = ({
|
||||
unit,
|
||||
isER,
|
||||
initialPayload,
|
||||
fuelLive,
|
||||
payloadLive,
|
||||
loadingState,
|
||||
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 ZFWEntryPax: FC<ZFWEntryProps> = ({ WASMData, loadingState, setLoadingState }) => {
|
||||
const [CGTarget, setCGTarget] = useState(WASMData.targetPayload.CGTarget);
|
||||
const [fuel, setFuel] = useState(Math.round(WASMData.livePayload.fuel));
|
||||
const [ZFWTarget, setZFWTarget] = useState(Math.round(WASMData.targetPayload.total));
|
||||
const [fuelEnabled, setFuelEnabled] = useState(true);
|
||||
|
||||
const _ZFW = () => {
|
||||
if (loadingState !== 'loaded') return ZFW;
|
||||
const ZFW = () => {
|
||||
if (loadingState !== 'loaded' && !GSXActive()) return ZFWTarget;
|
||||
|
||||
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
|
||||
);
|
||||
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 GSXActive = () => {
|
||||
return (
|
||||
(WASMData.GSX.boardingState >= GSX_SERVICE_CALLED || WASMData.GSX.deboardingState >= GSX_SERVICE_CALLED) &&
|
||||
WASMData.GSX.deboardingState !== GSX_SERVICE_FINISHED
|
||||
);
|
||||
};
|
||||
|
||||
const handleInput = (input: string, maxValue: number, setter: (value: number) => void) => {
|
||||
@@ -121,113 +58,71 @@ const ZFWEntryPax: FC<StationEntryProps> = ({
|
||||
|
||||
const converted = parseInt(input);
|
||||
if (converted) {
|
||||
if (converted < 0)
|
||||
setZFW(
|
||||
Math.round(
|
||||
PaxConfig.weights.base[unit].total + (isER ? SharedConfig.erExtraWeight[unit] * 2 : 0) + payloadLive.empty
|
||||
)
|
||||
);
|
||||
else if (converted > PaxConfig.maxZWF[unit]) setZFW(PaxConfig.maxZWF[unit]);
|
||||
else setZFW(converted);
|
||||
if (converted < 0) setZFWTarget(Math.round(WASMData.targetPayload.empty + WASMData.targetPayload.crew));
|
||||
else if (converted > WASMData.limits.maxZFW) setZFWTarget(WASMData.limits.maxZFW);
|
||||
else setZFWTarget(converted);
|
||||
}
|
||||
};
|
||||
const handleBlur = (input: string) => {
|
||||
const minZFW = Math.round(
|
||||
PaxConfig.weights.base[unit].total + (isER ? SharedConfig.erExtraWeight[unit] * 2 : 0) + payloadLive.empty
|
||||
);
|
||||
const minZFW = Math.round(WASMData.targetPayload.empty + WASMData.targetPayload.crew);
|
||||
|
||||
if (!input) {
|
||||
setZFW(minZFW);
|
||||
setZFWTarget(minZFW);
|
||||
return;
|
||||
}
|
||||
|
||||
const converted = parseInt(input);
|
||||
if (converted) {
|
||||
if (converted < minZFW) setZFW(minZFW);
|
||||
else if (converted > PaxConfig.maxZWF[unit]) setZFW(PaxConfig.maxZWF[unit]);
|
||||
else setZFW(converted);
|
||||
if (converted < minZFW) setZFWTarget(minZFW);
|
||||
else if (converted > WASMData.limits.maxZFW) setZFWTarget(WASMData.limits.maxZFW);
|
||||
else setZFWTarget(converted);
|
||||
}
|
||||
|
||||
updateView(PaxConfig.distribute(converted, targetZFWCG, payloadLive.empty, fuelLive, unit, isER));
|
||||
updateData(converted);
|
||||
};
|
||||
|
||||
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(inRangeOf(Math.round(WASMData.livePayload.fuel), fuel));
|
||||
}, [WASMData.livePayload.fuel]);
|
||||
|
||||
const updateData = (_ZFWTarget?: number, _CGTarget?: number) => {
|
||||
CoherentCallZFWEntry(_ZFWTarget ?? ZFWTarget, _CGTarget ?? CGTarget);
|
||||
};
|
||||
|
||||
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 ({unit})</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 ({SharedConfig.CGLimits.min} - {SharedConfig.CGLimits.max})
|
||||
</label>
|
||||
<CGSelect
|
||||
value={targetZFWCG}
|
||||
disabled={loadingState !== 'preview'}
|
||||
increase={() =>
|
||||
setTargetZFWCG((prev) => {
|
||||
const _new = prev + 0.1;
|
||||
updateView(PaxConfig.distribute(ZFW, _new, payloadLive.empty, fuelLive, unit, isER));
|
||||
return _new;
|
||||
})
|
||||
}
|
||||
decrease={() =>
|
||||
setTargetZFWCG((prev) => {
|
||||
const _new = prev - 0.1;
|
||||
updateView(PaxConfig.distribute(ZFW, _new, payloadLive.empty, fuelLive, unit, isER));
|
||||
return _new;
|
||||
})
|
||||
}
|
||||
/>
|
||||
</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>
|
||||
<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,
|
||||
isER ? SharedConfig.maxFuel.er[unit] : SharedConfig.maxFuel.norm[unit],
|
||||
setFuel
|
||||
)
|
||||
}
|
||||
disabled={loadingState !== 'preview'}
|
||||
onChange={(e) => handleInput(e.target.value, WASMData.limits.maxFuel, setFuel)}
|
||||
disabled={loadingState !== 'preview' || GSXActive()}
|
||||
/>
|
||||
<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_PAYLOAD_FUEL',
|
||||
'lbs',
|
||||
WASMData.userData.isImperial ? fuel : fuel * 2.20462262185
|
||||
);
|
||||
SimVar.SetSimVarValue('L:MD11_EFB_READ_READY', 'bool', true);
|
||||
setFuelEnabled(WASMData.livePayload.fuel === fuel);
|
||||
}}
|
||||
disabled={loadingState !== 'preview'}
|
||||
disabled={loadingState !== 'preview' || !fuelEnabled || GSXActive()}
|
||||
>
|
||||
Load Fuel
|
||||
</button>
|
||||
@@ -236,20 +131,62 @@ const ZFWEntryPax: FC<StationEntryProps> = ({
|
||||
|
||||
<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' || GSXActive()}
|
||||
/>
|
||||
</div>
|
||||
<div className="relative flex w-full items-center justify-between rounded-b-md bg-zinc-700 p-2 px-4">
|
||||
<label>
|
||||
{loadingState !== 'loaded' ? 'Expected' : 'Actual'} ZFW ({unit})
|
||||
Target ZFWCG ({WASMData.limits.minCG} - {WASMData.limits.maxCG})
|
||||
</label>
|
||||
<CGSelect
|
||||
minCG={WASMData.limits.minCG}
|
||||
maxCG={WASMData.limits.maxCG}
|
||||
value={CGTarget}
|
||||
disabled={loadingState !== 'preview' || GSXActive()}
|
||||
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="relative flex w-full items-center justify-between rounded-t-md bg-zinc-600 p-2 px-4">
|
||||
<label>
|
||||
{loadingState !== 'loaded' && !GSXActive() ? 'Expected' : 'Actual'} ZFW (
|
||||
{WASMData.userData.isImperial ? 'lbs' : 'kg'})
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
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`}
|
||||
disabled
|
||||
value={_ZFW()}
|
||||
value={ZFW()}
|
||||
/>
|
||||
</div>
|
||||
<div className="relative flex w-full items-center justify-between rounded-b-md bg-zinc-700 p-2 px-4">
|
||||
<label>
|
||||
{loadingState !== 'loaded' ? 'Expected' : 'Actual'} GW ({unit})
|
||||
{loadingState !== 'loaded' && !GSXActive() ? 'Expected' : 'Actual'} GW (
|
||||
{WASMData.userData.isImperial ? 'lbs' : 'kg'})
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
@@ -263,9 +200,9 @@ const ZFWEntryPax: FC<StationEntryProps> = ({
|
||||
|
||||
<ActionBar
|
||||
loadingState={loadingState}
|
||||
acceptDisabled={!GWValid()}
|
||||
accept={() => setLoadingState('accepted')}
|
||||
reject={() => setLoadingState('preview')}
|
||||
loadDisabled={!GWValid()}
|
||||
GSXSync={WASMData.options.GSXSync}
|
||||
GSXActive={GSXActive()}
|
||||
load={() => {
|
||||
setLoadingState('loaded');
|
||||
|
||||
@@ -274,7 +211,7 @@ const ZFWEntryPax: FC<StationEntryProps> = ({
|
||||
unload={() => {
|
||||
setLoadingState('preview');
|
||||
|
||||
PaxConfig.unload(unit, isER);
|
||||
unloadAircraft();
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
|
||||
@@ -1,153 +0,0 @@
|
||||
import { ArmsFuel, Fuel, toPercentMAC } from './shared';
|
||||
|
||||
// TODO: Extract from CFG at runtime.
|
||||
const ArmsFreight = {
|
||||
empty: -159.6,
|
||||
pilot: 984,
|
||||
firstOfficer: 984,
|
||||
engineer: 960,
|
||||
upper1Left: 660,
|
||||
upper1Right: 660,
|
||||
upper2Left: 240,
|
||||
upper2Right: 240,
|
||||
upper3Left: -240,
|
||||
upper3Right: -240,
|
||||
upper4Left: -600,
|
||||
upper4Right: -600,
|
||||
lowerForward: 360,
|
||||
lowerRear: -360,
|
||||
leftAuxF: 60,
|
||||
rightAuxF: 60,
|
||||
};
|
||||
|
||||
export interface PayloadFreight {
|
||||
empty: number;
|
||||
pilot: number;
|
||||
firstOfficer: number;
|
||||
engineer: number;
|
||||
upper1Left: number;
|
||||
upper1Right: number;
|
||||
upper2Left: number;
|
||||
upper2Right: number;
|
||||
upper3Left: number;
|
||||
upper3Right: number;
|
||||
upper4Left: number;
|
||||
upper4Right: number;
|
||||
lowerForward: number;
|
||||
lowerRear: number;
|
||||
leftAuxF: number;
|
||||
rightAuxF: number;
|
||||
}
|
||||
|
||||
//PMC pallet
|
||||
export const maxUpperStationWeight = {
|
||||
lbs: (26 / 8) * 15000,
|
||||
kg: (26 / 8) * 6804,
|
||||
};
|
||||
|
||||
export const baseWeightFreight = {
|
||||
pilot: {
|
||||
lbs: 190,
|
||||
kg: 86,
|
||||
},
|
||||
firstOfficer: {
|
||||
lbs: 190,
|
||||
kg: 86,
|
||||
},
|
||||
};
|
||||
|
||||
export const maxZFWFreight = {
|
||||
lbs: 451300,
|
||||
kg: 204706,
|
||||
};
|
||||
|
||||
export const calculateCGsFreight = (payload: PayloadFreight, fuel: Fuel): [number, number] => {
|
||||
let totalMoment =
|
||||
payload.empty * ArmsFreight.empty +
|
||||
payload.pilot * ArmsFreight.pilot +
|
||||
payload.firstOfficer * ArmsFreight.firstOfficer +
|
||||
payload.engineer * ArmsFreight.engineer +
|
||||
payload.upper1Left * ArmsFreight.upper1Left +
|
||||
payload.upper1Right * ArmsFreight.upper1Right +
|
||||
payload.upper2Left * ArmsFreight.upper2Left +
|
||||
payload.upper2Right * ArmsFreight.upper2Right +
|
||||
payload.upper3Left * ArmsFreight.upper3Left +
|
||||
payload.upper3Right * ArmsFreight.upper3Right +
|
||||
payload.upper4Left * ArmsFreight.upper4Left +
|
||||
payload.upper4Right * ArmsFreight.upper4Right +
|
||||
payload.lowerForward * ArmsFreight.lowerForward +
|
||||
payload.lowerRear * ArmsFreight.lowerRear +
|
||||
payload.leftAuxF * ArmsFreight.leftAuxF +
|
||||
payload.rightAuxF * ArmsFreight.rightAuxF;
|
||||
|
||||
let totalWeight =
|
||||
payload.empty +
|
||||
payload.pilot +
|
||||
payload.firstOfficer +
|
||||
payload.engineer +
|
||||
payload.upper1Left +
|
||||
payload.upper1Right +
|
||||
payload.upper2Left +
|
||||
payload.upper2Right +
|
||||
payload.upper3Left +
|
||||
payload.upper3Right +
|
||||
payload.upper4Left +
|
||||
payload.upper4Right +
|
||||
payload.lowerForward +
|
||||
payload.lowerRear +
|
||||
payload.leftAuxF +
|
||||
payload.rightAuxF;
|
||||
|
||||
const ZFWCG = toPercentMAC(totalMoment / totalWeight);
|
||||
|
||||
totalMoment +=
|
||||
fuel.main1 * ArmsFuel.main1 +
|
||||
fuel.main3 * ArmsFuel.main3 +
|
||||
fuel.main2 * ArmsFuel.main2 +
|
||||
fuel.upperAux * ArmsFuel.upperAux +
|
||||
fuel.lowerAux * ArmsFuel.lowerAux +
|
||||
fuel.main1Tip * ArmsFuel.main1Tip +
|
||||
fuel.main3Tip * ArmsFuel.main3Tip +
|
||||
fuel.tail * ArmsFuel.tail +
|
||||
fuel.forwardAux1 * ArmsFuel.forwardAux1 +
|
||||
fuel.forwardAux2 * ArmsFuel.forwardAux2;
|
||||
|
||||
totalWeight +=
|
||||
fuel.main1 +
|
||||
fuel.main3 +
|
||||
fuel.main2 +
|
||||
fuel.upperAux +
|
||||
fuel.lowerAux +
|
||||
fuel.main1Tip +
|
||||
fuel.main3Tip +
|
||||
fuel.tail +
|
||||
fuel.forwardAux1 +
|
||||
fuel.forwardAux2;
|
||||
|
||||
const TOCG = toPercentMAC(totalMoment / totalWeight);
|
||||
|
||||
return [ZFWCG, TOCG];
|
||||
};
|
||||
|
||||
export const getWeightsFreight = (unit: 'kg' | 'lbs') => {
|
||||
const payload: PayloadFreight = {
|
||||
empty: SimVar.GetSimVarValue('EMPTY WEIGHT', unit),
|
||||
pilot: SimVar.GetSimVarValue('PAYLOAD STATION WEIGHT:1', unit),
|
||||
firstOfficer: SimVar.GetSimVarValue('PAYLOAD STATION WEIGHT:2', unit),
|
||||
engineer: SimVar.GetSimVarValue('PAYLOAD STATION WEIGHT:3', unit),
|
||||
upper1Left: SimVar.GetSimVarValue('PAYLOAD STATION WEIGHT:4', unit),
|
||||
upper1Right: SimVar.GetSimVarValue('PAYLOAD STATION WEIGHT:5', unit),
|
||||
upper2Left: SimVar.GetSimVarValue('PAYLOAD STATION WEIGHT:6', unit),
|
||||
upper2Right: SimVar.GetSimVarValue('PAYLOAD STATION WEIGHT:7', unit),
|
||||
upper3Left: SimVar.GetSimVarValue('PAYLOAD STATION WEIGHT:8', unit),
|
||||
upper3Right: SimVar.GetSimVarValue('PAYLOAD STATION WEIGHT:9', unit),
|
||||
upper4Left: SimVar.GetSimVarValue('PAYLOAD STATION WEIGHT:10', unit),
|
||||
upper4Right: SimVar.GetSimVarValue('PAYLOAD STATION WEIGHT:11', unit),
|
||||
lowerForward: SimVar.GetSimVarValue('PAYLOAD STATION WEIGHT:12', unit),
|
||||
lowerRear: SimVar.GetSimVarValue('PAYLOAD STATION WEIGHT:13', unit),
|
||||
leftAuxF: SimVar.GetSimVarValue('PAYLOAD STATION WEIGHT:14', unit),
|
||||
rightAuxF: SimVar.GetSimVarValue('PAYLOAD STATION WEIGHT:15', unit),
|
||||
};
|
||||
|
||||
return payload;
|
||||
};
|
||||
@@ -1,598 +0,0 @@
|
||||
import { ArmsFuel, Fuel, SharedConfig, toPercentMAC } from './shared';
|
||||
|
||||
export interface PayloadPax {
|
||||
empty: number;
|
||||
pilot: number;
|
||||
firstOfficer: number;
|
||||
engineer: number;
|
||||
cabinCrewFront: number;
|
||||
business1Left: number;
|
||||
business1Center: number;
|
||||
business1Right: number;
|
||||
business2Left: number;
|
||||
business2Center: number;
|
||||
business2Right: number;
|
||||
economy1Left: number;
|
||||
economy1Center: number;
|
||||
economy1Right: number;
|
||||
economy2Left: number;
|
||||
economy2Center: number;
|
||||
economy2Right: number;
|
||||
cabinCrewRear: number;
|
||||
forwardCargo: number;
|
||||
rearCargo: number;
|
||||
leftAuxPax: number;
|
||||
rightAuxPax: number;
|
||||
|
||||
paxCount: {
|
||||
business1: number;
|
||||
business2: number;
|
||||
economy1: number;
|
||||
economy2: number;
|
||||
total: number;
|
||||
};
|
||||
}
|
||||
|
||||
export const PaxConfig = {
|
||||
// TODO: Extract from CFG at runtime.
|
||||
arms: {
|
||||
empty: -159.6,
|
||||
pilot: 984,
|
||||
firstOfficer: 984,
|
||||
engineer: 960,
|
||||
cabinCrewFront: 792,
|
||||
business1Left: 540,
|
||||
business1Center: 540,
|
||||
business1Right: 540,
|
||||
business2Left: 300,
|
||||
business2Center: 300,
|
||||
business2Right: 300,
|
||||
economy1Left: -240,
|
||||
economy1Center: -240,
|
||||
economy1Right: -240,
|
||||
economy2Left: -600,
|
||||
economy2Center: -600,
|
||||
economy2Right: -600,
|
||||
cabinCrewRear: -660,
|
||||
forwardCargo: 360,
|
||||
rearCargo: -360,
|
||||
leftAuxPax: 60,
|
||||
rightAuxPax: 60,
|
||||
},
|
||||
// TODO: Make user adjustable
|
||||
weights: {
|
||||
pax: {
|
||||
lbs: 190,
|
||||
kg: 86,
|
||||
},
|
||||
baggage: {
|
||||
lbs: 50,
|
||||
kg: 23,
|
||||
},
|
||||
base: {
|
||||
lbs: {
|
||||
pilot: 190,
|
||||
firstOfficer: 190,
|
||||
engineer: 190,
|
||||
cabinCrewFront: 380,
|
||||
cabinCrewRear: 950,
|
||||
total: 190 + 190 + 190 + 380 + 950,
|
||||
},
|
||||
kg: {
|
||||
pilot: 86,
|
||||
firstOfficer: 86,
|
||||
engineer: 86,
|
||||
cabinCrewFront: 172,
|
||||
cabinCrewRear: 430,
|
||||
total: 86 + 86 + 86 + 172 + 430,
|
||||
},
|
||||
},
|
||||
},
|
||||
stationMax: {
|
||||
business1: 30,
|
||||
business2: 45,
|
||||
economy1: 86,
|
||||
economy2: 137,
|
||||
total: 30 + 45 + 86 + 137,
|
||||
},
|
||||
maxZWF: {
|
||||
lbs: 400000,
|
||||
kg: 181437,
|
||||
},
|
||||
weightToPax: (weight: number, unit: 'kg' | 'lbs') => {
|
||||
return Math.round(weight / PaxConfig.weights.pax[unit]);
|
||||
},
|
||||
calculateCGs: (payload: PayloadPax, fuel: Fuel): [number, number] => {
|
||||
let totalMoment =
|
||||
payload.empty * PaxConfig.arms.empty +
|
||||
payload.pilot * PaxConfig.arms.pilot +
|
||||
payload.firstOfficer * PaxConfig.arms.firstOfficer +
|
||||
payload.engineer * PaxConfig.arms.engineer +
|
||||
payload.cabinCrewFront * PaxConfig.arms.cabinCrewFront +
|
||||
payload.business1Left * PaxConfig.arms.business1Left +
|
||||
payload.business1Center * PaxConfig.arms.business1Center +
|
||||
payload.business1Right * PaxConfig.arms.business1Right +
|
||||
payload.business2Left * PaxConfig.arms.business2Left +
|
||||
payload.business2Center * PaxConfig.arms.business2Center +
|
||||
payload.business2Right * PaxConfig.arms.business2Right +
|
||||
payload.economy1Left * PaxConfig.arms.economy1Left +
|
||||
payload.economy1Center * PaxConfig.arms.economy1Center +
|
||||
payload.economy1Right * PaxConfig.arms.economy1Right +
|
||||
payload.economy2Left * PaxConfig.arms.economy2Left +
|
||||
payload.economy2Center * PaxConfig.arms.economy2Center +
|
||||
payload.economy2Right * PaxConfig.arms.economy2Right +
|
||||
payload.cabinCrewRear * PaxConfig.arms.cabinCrewRear +
|
||||
payload.forwardCargo * PaxConfig.arms.forwardCargo +
|
||||
payload.rearCargo * PaxConfig.arms.rearCargo +
|
||||
payload.leftAuxPax * PaxConfig.arms.leftAuxPax +
|
||||
payload.rightAuxPax * PaxConfig.arms.rightAuxPax;
|
||||
|
||||
let totalWeight =
|
||||
payload.empty +
|
||||
payload.pilot +
|
||||
payload.firstOfficer +
|
||||
payload.engineer +
|
||||
payload.cabinCrewFront +
|
||||
payload.business1Left +
|
||||
payload.business1Center +
|
||||
payload.business1Right +
|
||||
payload.business2Left +
|
||||
payload.business2Center +
|
||||
payload.business2Right +
|
||||
payload.economy1Left +
|
||||
payload.economy1Center +
|
||||
payload.economy1Right +
|
||||
payload.economy2Left +
|
||||
payload.economy2Center +
|
||||
payload.economy2Right +
|
||||
payload.cabinCrewRear +
|
||||
payload.forwardCargo +
|
||||
payload.rearCargo +
|
||||
payload.leftAuxPax +
|
||||
payload.rightAuxPax;
|
||||
|
||||
const ZFWCG = toPercentMAC(totalMoment / totalWeight);
|
||||
|
||||
totalMoment +=
|
||||
fuel.main1 * ArmsFuel.main1 +
|
||||
fuel.main3 * ArmsFuel.main3 +
|
||||
fuel.main2 * ArmsFuel.main2 +
|
||||
fuel.upperAux * ArmsFuel.upperAux +
|
||||
fuel.lowerAux * ArmsFuel.lowerAux +
|
||||
fuel.main1Tip * ArmsFuel.main1Tip +
|
||||
fuel.main3Tip * ArmsFuel.main3Tip +
|
||||
fuel.tail * ArmsFuel.tail +
|
||||
fuel.forwardAux1 * ArmsFuel.forwardAux1 +
|
||||
fuel.forwardAux2 * ArmsFuel.forwardAux2;
|
||||
|
||||
totalWeight +=
|
||||
fuel.main1 +
|
||||
fuel.main3 +
|
||||
fuel.main2 +
|
||||
fuel.upperAux +
|
||||
fuel.lowerAux +
|
||||
fuel.main1Tip +
|
||||
fuel.main3Tip +
|
||||
fuel.tail +
|
||||
fuel.forwardAux1 +
|
||||
fuel.forwardAux2;
|
||||
|
||||
const toCG = toPercentMAC(totalMoment / totalWeight);
|
||||
|
||||
return [ZFWCG, toCG];
|
||||
},
|
||||
generateDistribution: (
|
||||
OEW: number,
|
||||
business1: number,
|
||||
business2: number,
|
||||
economy1: number,
|
||||
economy2: number,
|
||||
forwardCargo: number,
|
||||
rearCargo: number,
|
||||
unit: 'kg' | 'lbs',
|
||||
isER: boolean
|
||||
): PayloadPax => {
|
||||
const distribution: PayloadPax = {
|
||||
empty: OEW,
|
||||
|
||||
...PaxConfig.weights.base[unit],
|
||||
|
||||
business1Left: (business1 / 3) * PaxConfig.weights.pax[unit],
|
||||
business1Center: (business1 / 3) * PaxConfig.weights.pax[unit],
|
||||
business1Right: (business1 / 3) * PaxConfig.weights.pax[unit],
|
||||
business2Left: (business2 / 3) * PaxConfig.weights.pax[unit],
|
||||
business2Center: (business2 / 3) * PaxConfig.weights.pax[unit],
|
||||
business2Right: (business2 / 3) * PaxConfig.weights.pax[unit],
|
||||
economy1Left: (economy1 / 3) * PaxConfig.weights.pax[unit],
|
||||
economy1Center: (economy1 / 3) * PaxConfig.weights.pax[unit],
|
||||
economy1Right: (economy1 / 3) * PaxConfig.weights.pax[unit],
|
||||
economy2Left: (economy2 / 3) * PaxConfig.weights.pax[unit],
|
||||
economy2Center: (economy2 / 3) * PaxConfig.weights.pax[unit],
|
||||
economy2Right: (economy2 / 3) * PaxConfig.weights.pax[unit],
|
||||
|
||||
forwardCargo: forwardCargo,
|
||||
rearCargo: rearCargo,
|
||||
|
||||
leftAuxPax: isER ? SharedConfig.erExtraWeight[unit] : 0,
|
||||
rightAuxPax: isER ? SharedConfig.erExtraWeight[unit] : 0,
|
||||
|
||||
paxCount: {
|
||||
business1,
|
||||
business2,
|
||||
economy1,
|
||||
economy2,
|
||||
total: business1 + business2 + economy1 + economy2,
|
||||
},
|
||||
};
|
||||
|
||||
return distribution;
|
||||
},
|
||||
distribute: (
|
||||
ZFWTarget: number,
|
||||
CGTarget: number,
|
||||
OEW: number,
|
||||
fuelLive: Fuel,
|
||||
unit: 'kg' | 'lbs',
|
||||
isER: boolean,
|
||||
numPax?: number
|
||||
) => {
|
||||
const payload =
|
||||
ZFWTarget -
|
||||
OEW -
|
||||
PaxConfig.weights.base[unit].pilot -
|
||||
PaxConfig.weights.base[unit].firstOfficer -
|
||||
PaxConfig.weights.base[unit].engineer -
|
||||
PaxConfig.weights.base[unit].cabinCrewFront -
|
||||
PaxConfig.weights.base[unit].cabinCrewRear -
|
||||
(isER ? SharedConfig.erExtraWeight[unit] * 2 : 0);
|
||||
|
||||
let _numPax =
|
||||
numPax ??
|
||||
Math.max(
|
||||
0,
|
||||
Math.min(
|
||||
PaxConfig.stationMax.total,
|
||||
Math.floor(payload / (PaxConfig.weights.pax[unit] + PaxConfig.weights.baggage[unit]))
|
||||
)
|
||||
);
|
||||
let cargo = Math.round(payload - _numPax * PaxConfig.weights.pax[unit] - _numPax * PaxConfig.weights.baggage[unit]);
|
||||
|
||||
let business1 = 0;
|
||||
let business2 = 0;
|
||||
let economy1 = 0;
|
||||
let economy2 = 0;
|
||||
let forwardCargo = 0;
|
||||
let rearCargo = 0;
|
||||
let __numPax = 0;
|
||||
let count = PaxConfig.stationMax.economy2;
|
||||
// initial distribution
|
||||
while (_numPax > 0 && count > 0) {
|
||||
if (_numPax >= 4) {
|
||||
if (business1 < PaxConfig.stationMax.business1) {
|
||||
business1++;
|
||||
__numPax++;
|
||||
}
|
||||
if (business2 < PaxConfig.stationMax.business2) {
|
||||
business2++;
|
||||
__numPax++;
|
||||
}
|
||||
if (economy1 < PaxConfig.stationMax.economy1) {
|
||||
economy1++;
|
||||
__numPax++;
|
||||
}
|
||||
if (economy2 < PaxConfig.stationMax.economy2) {
|
||||
economy2++;
|
||||
__numPax++;
|
||||
}
|
||||
} else if (_numPax === 3) {
|
||||
if (business2 < PaxConfig.stationMax.business2) {
|
||||
business2++;
|
||||
__numPax++;
|
||||
}
|
||||
if (economy1 < PaxConfig.stationMax.economy1) {
|
||||
economy1++;
|
||||
__numPax++;
|
||||
}
|
||||
if (economy2 < PaxConfig.stationMax.economy2) {
|
||||
economy2++;
|
||||
__numPax++;
|
||||
}
|
||||
} else if (_numPax === 2) {
|
||||
if (economy1 < PaxConfig.stationMax.economy1) {
|
||||
economy1++;
|
||||
__numPax++;
|
||||
}
|
||||
if (economy2 < PaxConfig.stationMax.economy2) {
|
||||
economy2++;
|
||||
__numPax++;
|
||||
}
|
||||
} else if (_numPax === 1) {
|
||||
if (economy2 < PaxConfig.stationMax.economy2) {
|
||||
economy2++;
|
||||
__numPax++;
|
||||
}
|
||||
}
|
||||
_numPax -= __numPax;
|
||||
|
||||
if (__numPax % 2 === 0) {
|
||||
forwardCargo += (__numPax / 2) * PaxConfig.weights.baggage[unit];
|
||||
rearCargo += (__numPax / 2) * PaxConfig.weights.baggage[unit];
|
||||
} else {
|
||||
__numPax--;
|
||||
forwardCargo += (__numPax / 2 + 1) * PaxConfig.weights.baggage[unit];
|
||||
rearCargo += (__numPax / 2) * PaxConfig.weights.baggage[unit];
|
||||
}
|
||||
|
||||
__numPax = 0;
|
||||
|
||||
count--;
|
||||
}
|
||||
count = SharedConfig.stationMax.forward[unit];
|
||||
while (cargo > 0 && count > 0) {
|
||||
if (forwardCargo < SharedConfig.stationMax.forward[unit]) {
|
||||
forwardCargo++;
|
||||
cargo--;
|
||||
}
|
||||
if (rearCargo < SharedConfig.stationMax.rear[unit]) {
|
||||
rearCargo++;
|
||||
cargo--;
|
||||
}
|
||||
|
||||
count--;
|
||||
}
|
||||
// Refinement pax
|
||||
count = PaxConfig.stationMax.total;
|
||||
while (count > 0) {
|
||||
const distribution = PaxConfig.generateDistribution(
|
||||
OEW,
|
||||
business1,
|
||||
business2,
|
||||
economy1,
|
||||
economy2,
|
||||
forwardCargo,
|
||||
rearCargo,
|
||||
unit,
|
||||
isER
|
||||
);
|
||||
const _CGs = PaxConfig.calculateCGs(distribution, fuelLive);
|
||||
|
||||
// in front of target
|
||||
if (_CGs[0] < CGTarget - SharedConfig.CGLimits.tolerance) {
|
||||
if (business1 > 0) {
|
||||
business1--;
|
||||
} else if (business2 > 0) {
|
||||
business2--;
|
||||
} else if (economy1 > 0) {
|
||||
economy1--;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
|
||||
if (economy2 < PaxConfig.stationMax.economy2) {
|
||||
economy2++;
|
||||
} else if (economy1 < PaxConfig.stationMax.economy1) {
|
||||
economy1++;
|
||||
} else if (business2 < PaxConfig.stationMax.business2) {
|
||||
business2++;
|
||||
} else {
|
||||
business1++;
|
||||
}
|
||||
}
|
||||
// behind target
|
||||
else if (_CGs[0] > CGTarget + SharedConfig.CGLimits.tolerance) {
|
||||
if (economy2 > 0) {
|
||||
economy2--;
|
||||
} else if (economy1 > 0) {
|
||||
economy1--;
|
||||
} else if (business2 > 0) {
|
||||
business2--;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
|
||||
if (business1 < PaxConfig.stationMax.business1) {
|
||||
business1++;
|
||||
} else if (business2 < PaxConfig.stationMax.business2) {
|
||||
business2++;
|
||||
} else if (economy1 < PaxConfig.stationMax.economy1) {
|
||||
economy1++;
|
||||
} else {
|
||||
economy2++;
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
|
||||
count--;
|
||||
}
|
||||
// Refinement cargo
|
||||
count = SharedConfig.stationMax.forward[unit] + SharedConfig.stationMax.rear[unit];
|
||||
while (count > 0) {
|
||||
const distribution = PaxConfig.generateDistribution(
|
||||
OEW,
|
||||
business1,
|
||||
business2,
|
||||
economy1,
|
||||
economy2,
|
||||
forwardCargo,
|
||||
rearCargo,
|
||||
unit,
|
||||
isER
|
||||
);
|
||||
const _CGs = PaxConfig.calculateCGs(distribution, fuelLive);
|
||||
|
||||
// in front of target
|
||||
if (_CGs[0] < CGTarget - SharedConfig.CGLimits.tolerance) {
|
||||
if (forwardCargo > 0 && rearCargo < SharedConfig.stationMax.rear[unit]) {
|
||||
if (
|
||||
forwardCargo > PaxConfig.weights.baggage[unit] &&
|
||||
rearCargo < SharedConfig.stationMax.forward[unit] - PaxConfig.weights.baggage[unit]
|
||||
) {
|
||||
forwardCargo -= PaxConfig.weights.baggage[unit];
|
||||
rearCargo += PaxConfig.weights.baggage[unit];
|
||||
} else {
|
||||
forwardCargo--;
|
||||
rearCargo++;
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
// behind target
|
||||
else if (_CGs[0] > CGTarget + SharedConfig.CGLimits.tolerance) {
|
||||
if (rearCargo > 0 && forwardCargo < SharedConfig.stationMax.forward[unit]) {
|
||||
if (
|
||||
rearCargo > PaxConfig.weights.baggage[unit] &&
|
||||
forwardCargo < SharedConfig.stationMax.rear[unit] - PaxConfig.weights.baggage[unit]
|
||||
) {
|
||||
rearCargo -= PaxConfig.weights.baggage[unit];
|
||||
forwardCargo += PaxConfig.weights.baggage[unit];
|
||||
} else {
|
||||
rearCargo--;
|
||||
forwardCargo++;
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
|
||||
count--;
|
||||
}
|
||||
|
||||
const distribution = PaxConfig.generateDistribution(
|
||||
OEW,
|
||||
business1,
|
||||
business2,
|
||||
economy1,
|
||||
economy2,
|
||||
forwardCargo,
|
||||
rearCargo,
|
||||
unit,
|
||||
isER
|
||||
);
|
||||
|
||||
return distribution;
|
||||
},
|
||||
// SIM access
|
||||
getWeights: (unit: 'kg' | 'lbs') => {
|
||||
const payload: PayloadPax = {
|
||||
empty: SimVar.GetSimVarValue('EMPTY WEIGHT', unit),
|
||||
pilot: SimVar.GetSimVarValue('PAYLOAD STATION WEIGHT:1', unit),
|
||||
firstOfficer: SimVar.GetSimVarValue('PAYLOAD STATION WEIGHT:2', unit),
|
||||
engineer: SimVar.GetSimVarValue('PAYLOAD STATION WEIGHT:3', unit),
|
||||
cabinCrewFront: SimVar.GetSimVarValue('PAYLOAD STATION WEIGHT:4', unit),
|
||||
business1Left: SimVar.GetSimVarValue('PAYLOAD STATION WEIGHT:5', unit),
|
||||
business1Center: SimVar.GetSimVarValue('PAYLOAD STATION WEIGHT:6', unit),
|
||||
business1Right: SimVar.GetSimVarValue('PAYLOAD STATION WEIGHT:7', unit),
|
||||
business2Left: SimVar.GetSimVarValue('PAYLOAD STATION WEIGHT:8', unit),
|
||||
business2Center: SimVar.GetSimVarValue('PAYLOAD STATION WEIGHT:9', unit),
|
||||
business2Right: SimVar.GetSimVarValue('PAYLOAD STATION WEIGHT:10', unit),
|
||||
economy1Left: SimVar.GetSimVarValue('PAYLOAD STATION WEIGHT:11', unit),
|
||||
economy1Center: SimVar.GetSimVarValue('PAYLOAD STATION WEIGHT:12', unit),
|
||||
economy1Right: SimVar.GetSimVarValue('PAYLOAD STATION WEIGHT:13', unit),
|
||||
economy2Left: SimVar.GetSimVarValue('PAYLOAD STATION WEIGHT:14', unit),
|
||||
economy2Center: SimVar.GetSimVarValue('PAYLOAD STATION WEIGHT:15', unit),
|
||||
economy2Right: SimVar.GetSimVarValue('PAYLOAD STATION WEIGHT:16', unit),
|
||||
cabinCrewRear: SimVar.GetSimVarValue('PAYLOAD STATION WEIGHT:17', unit),
|
||||
forwardCargo: SimVar.GetSimVarValue('PAYLOAD STATION WEIGHT:18', unit),
|
||||
rearCargo: SimVar.GetSimVarValue('PAYLOAD STATION WEIGHT:19', unit),
|
||||
leftAuxPax: SimVar.GetSimVarValue('PAYLOAD STATION WEIGHT:20', unit),
|
||||
rightAuxPax: SimVar.GetSimVarValue('PAYLOAD STATION WEIGHT:21', unit),
|
||||
|
||||
paxCount: {
|
||||
business1: 0,
|
||||
business2: 0,
|
||||
economy1: 0,
|
||||
economy2: 0,
|
||||
total: 0,
|
||||
},
|
||||
};
|
||||
|
||||
return payload;
|
||||
},
|
||||
setBaseWeight: (unit: 'kg' | 'lbs', isER: boolean) => {
|
||||
SimVar.SetSimVarValue('PAYLOAD STATION WEIGHT:1', unit, PaxConfig.weights.base[unit].pilot); // Pilot
|
||||
SimVar.SetSimVarValue('PAYLOAD STATION WEIGHT:2', unit, PaxConfig.weights.base[unit].firstOfficer); // First officer
|
||||
SimVar.SetSimVarValue('PAYLOAD STATION WEIGHT:3', unit, PaxConfig.weights.base[unit].engineer); // Engineer
|
||||
SimVar.SetSimVarValue('PAYLOAD STATION WEIGHT:4', unit, PaxConfig.weights.base[unit].cabinCrewFront); // Cabin Crew front
|
||||
SimVar.SetSimVarValue('PAYLOAD STATION WEIGHT:17', unit, PaxConfig.weights.base[unit].cabinCrewRear); // Cabin Crew rear
|
||||
if (isER) {
|
||||
SimVar.SetSimVarValue('PAYLOAD STATION WEIGHT:20', unit, SharedConfig.erExtraWeight[unit]); // Forward Aux 1
|
||||
SimVar.SetSimVarValue('PAYLOAD STATION WEIGHT:21', unit, SharedConfig.erExtraWeight[unit]); // Forward Aux 2
|
||||
}
|
||||
},
|
||||
setWeights: (payload: PayloadPax, unit: 'kg' | 'lbs') => {
|
||||
SimVar.SetSimVarValue('PAYLOAD STATION WEIGHT:4', unit, payload.cabinCrewFront); // Cabin Crew front
|
||||
SimVar.SetSimVarValue('PAYLOAD STATION WEIGHT:5', unit, payload.business1Left); // Business 1L
|
||||
SimVar.SetSimVarValue('PAYLOAD STATION WEIGHT:6', unit, payload.business1Center); // Business 1C
|
||||
SimVar.SetSimVarValue('PAYLOAD STATION WEIGHT:7', unit, payload.business1Right); // Business 1R
|
||||
SimVar.SetSimVarValue('PAYLOAD STATION WEIGHT:8', unit, payload.business2Left); // Business 2L
|
||||
SimVar.SetSimVarValue('PAYLOAD STATION WEIGHT:9', unit, payload.business2Center); // Business 2C
|
||||
SimVar.SetSimVarValue('PAYLOAD STATION WEIGHT:10', unit, payload.business2Right); // Business 2R
|
||||
SimVar.SetSimVarValue('PAYLOAD STATION WEIGHT:11', unit, payload.economy1Left); // Economy 1L
|
||||
SimVar.SetSimVarValue('PAYLOAD STATION WEIGHT:12', unit, payload.economy1Center); // Economy 1C
|
||||
SimVar.SetSimVarValue('PAYLOAD STATION WEIGHT:13', unit, payload.economy1Right); // Economy 1R
|
||||
SimVar.SetSimVarValue('PAYLOAD STATION WEIGHT:14', unit, payload.economy2Left); // Economy 2L
|
||||
SimVar.SetSimVarValue('PAYLOAD STATION WEIGHT:15', unit, payload.economy2Center); // Economy 2C
|
||||
SimVar.SetSimVarValue('PAYLOAD STATION WEIGHT:16', unit, payload.economy2Right); // Economy 2R
|
||||
SimVar.SetSimVarValue('PAYLOAD STATION WEIGHT:17', unit, payload.cabinCrewRear); //Cabin Crew rear
|
||||
SimVar.SetSimVarValue('PAYLOAD STATION WEIGHT:18', unit, payload.forwardCargo); // Forward Cargo
|
||||
SimVar.SetSimVarValue('PAYLOAD STATION WEIGHT:19', unit, payload.rearCargo); // Rear Cargo
|
||||
},
|
||||
setWeightsProgressive: (payload: PayloadPax, paxNum: number, cargoPercent: number, unit: 'kg' | 'lbs') => {
|
||||
const business1Scalar = Math.min(1, paxNum / payload.paxCount.business1);
|
||||
paxNum -= payload.paxCount.business1 * business1Scalar;
|
||||
const business2Scalar = Math.min(1, paxNum / payload.paxCount.business2);
|
||||
paxNum -= payload.paxCount.business2 * business2Scalar;
|
||||
const economy1Scalar = Math.min(1, paxNum / payload.paxCount.economy1);
|
||||
paxNum -= payload.paxCount.economy1 * economy1Scalar;
|
||||
const economy2Scalar = Math.min(1, paxNum / payload.paxCount.economy2);
|
||||
|
||||
SimVar.SetSimVarValue('PAYLOAD STATION WEIGHT:4', unit, payload.cabinCrewFront); // Cabin Crew front
|
||||
SimVar.SetSimVarValue('PAYLOAD STATION WEIGHT:5', unit, payload.business1Left * business1Scalar); // Business 1L
|
||||
SimVar.SetSimVarValue('PAYLOAD STATION WEIGHT:6', unit, payload.business1Center * business1Scalar); // Business 1C
|
||||
SimVar.SetSimVarValue('PAYLOAD STATION WEIGHT:7', unit, payload.business1Right * business1Scalar); // Business 1R
|
||||
SimVar.SetSimVarValue('PAYLOAD STATION WEIGHT:8', unit, payload.business2Left * business2Scalar); // Business 2L
|
||||
SimVar.SetSimVarValue('PAYLOAD STATION WEIGHT:9', unit, payload.business2Center * business2Scalar); // Business 2C
|
||||
SimVar.SetSimVarValue('PAYLOAD STATION WEIGHT:10', unit, payload.business2Right * business2Scalar); // Business 2R
|
||||
SimVar.SetSimVarValue('PAYLOAD STATION WEIGHT:11', unit, payload.economy1Left * economy1Scalar); // Economy 1L
|
||||
SimVar.SetSimVarValue('PAYLOAD STATION WEIGHT:12', unit, payload.economy1Center * economy1Scalar); // Economy 1C
|
||||
SimVar.SetSimVarValue('PAYLOAD STATION WEIGHT:13', unit, payload.economy1Right * economy1Scalar); // Economy 1R
|
||||
SimVar.SetSimVarValue('PAYLOAD STATION WEIGHT:14', unit, payload.economy2Left * economy2Scalar); // Economy 2L
|
||||
SimVar.SetSimVarValue('PAYLOAD STATION WEIGHT:15', unit, payload.economy2Center * economy2Scalar); // Economy 2C
|
||||
SimVar.SetSimVarValue('PAYLOAD STATION WEIGHT:16', unit, payload.economy2Right * economy2Scalar); // Economy 2R
|
||||
SimVar.SetSimVarValue('PAYLOAD STATION WEIGHT:17', unit, payload.cabinCrewRear); //Cabin Crew rear
|
||||
SimVar.SetSimVarValue('PAYLOAD STATION WEIGHT:18', unit, payload.forwardCargo * (cargoPercent / 100)); // Forward Cargo
|
||||
SimVar.SetSimVarValue('PAYLOAD STATION WEIGHT:19', unit, payload.rearCargo * (cargoPercent / 100)); // Rear Cargo
|
||||
},
|
||||
unload: (unit: 'kg' | 'lbs', isER: boolean) => {
|
||||
SimVar.SetSimVarValue('PAYLOAD STATION WEIGHT:1', unit, 0); // Pilot
|
||||
SimVar.SetSimVarValue('PAYLOAD STATION WEIGHT:2', unit, 0); // First officer
|
||||
SimVar.SetSimVarValue('PAYLOAD STATION WEIGHT:3', unit, 0); // Engineer
|
||||
SimVar.SetSimVarValue('PAYLOAD STATION WEIGHT:4', unit, 0); // Cabin Crew front
|
||||
SimVar.SetSimVarValue('PAYLOAD STATION WEIGHT:17', unit, 0); // Cabin Crew rear
|
||||
if (!isER) {
|
||||
SimVar.SetSimVarValue('PAYLOAD STATION WEIGHT:20', unit, 0); // Forward Aux 1
|
||||
SimVar.SetSimVarValue('PAYLOAD STATION WEIGHT:21', unit, 0); // Forward Aux 2
|
||||
}
|
||||
|
||||
SimVar.SetSimVarValue('PAYLOAD STATION WEIGHT:4', unit, 0); // Cabin Crew front
|
||||
SimVar.SetSimVarValue('PAYLOAD STATION WEIGHT:5', unit, 0); // Business 1L
|
||||
SimVar.SetSimVarValue('PAYLOAD STATION WEIGHT:6', unit, 0); // Business 1C
|
||||
SimVar.SetSimVarValue('PAYLOAD STATION WEIGHT:7', unit, 0); // Business 1R
|
||||
SimVar.SetSimVarValue('PAYLOAD STATION WEIGHT:8', unit, 0); // Business 2L
|
||||
SimVar.SetSimVarValue('PAYLOAD STATION WEIGHT:9', unit, 0); // Business 2C
|
||||
SimVar.SetSimVarValue('PAYLOAD STATION WEIGHT:10', unit, 0); // Business 2R
|
||||
SimVar.SetSimVarValue('PAYLOAD STATION WEIGHT:11', unit, 0); // Economy 1L
|
||||
SimVar.SetSimVarValue('PAYLOAD STATION WEIGHT:12', unit, 0); // Economy 1C
|
||||
SimVar.SetSimVarValue('PAYLOAD STATION WEIGHT:13', unit, 0); // Economy 1R
|
||||
SimVar.SetSimVarValue('PAYLOAD STATION WEIGHT:14', unit, 0); // Economy 2L
|
||||
SimVar.SetSimVarValue('PAYLOAD STATION WEIGHT:15', unit, 0); // Economy 2C
|
||||
SimVar.SetSimVarValue('PAYLOAD STATION WEIGHT:16', unit, 0); // Economy 2R
|
||||
SimVar.SetSimVarValue('PAYLOAD STATION WEIGHT:17', unit, 0); //Cabin Crew rear
|
||||
SimVar.SetSimVarValue('PAYLOAD STATION WEIGHT:18', unit, 0); // Forward Cargo
|
||||
SimVar.SetSimVarValue('PAYLOAD STATION WEIGHT:19', unit, 0); // Rear Cargo
|
||||
},
|
||||
};
|
||||
@@ -1,166 +0,0 @@
|
||||
export interface Fuel {
|
||||
main1: number;
|
||||
main3: number;
|
||||
main2: number;
|
||||
upperAux: number;
|
||||
lowerAux: number;
|
||||
main1Tip: number;
|
||||
main3Tip: number;
|
||||
tail: number;
|
||||
forwardAux1: number;
|
||||
forwardAux2: number;
|
||||
}
|
||||
|
||||
// TODO: Extract from CFG at runtime.
|
||||
export const ArmsFuel = {
|
||||
main1: -240,
|
||||
main3: -240,
|
||||
main2: 120,
|
||||
upperAux: 0,
|
||||
lowerAux: 0,
|
||||
main1Tip: -468,
|
||||
main3Tip: -468,
|
||||
tail: -840,
|
||||
forwardAux1: 60,
|
||||
forwardAux2: 60,
|
||||
};
|
||||
|
||||
// TODO: Extract following four from CFG at runtime
|
||||
const rootChord = 34.68;
|
||||
const wingSpan = 170.5;
|
||||
const wingArea = 3648;
|
||||
const quarterMAC = -165; //aero_center
|
||||
|
||||
const tipChord = (2 * wingArea) / wingSpan - rootChord;
|
||||
const taperRatio = tipChord / rootChord;
|
||||
|
||||
const MAC = (2 / 3) * rootChord * ((1 + taperRatio + taperRatio ** 2) / (1 + taperRatio)) * 12;
|
||||
const LEMAC = quarterMAC + (1 / 4) * MAC;
|
||||
|
||||
export const toPercentMAC = (positionInInches: number) => {
|
||||
return ((positionInInches - LEMAC) / MAC) * -100;
|
||||
};
|
||||
|
||||
export const SharedConfig = {
|
||||
stationMax: {
|
||||
//PMC pallet due to 104in door
|
||||
forward: {
|
||||
lbs: 6 * 15000,
|
||||
kg: 6 * 6804,
|
||||
},
|
||||
//LD3s due to 70in door
|
||||
rear: {
|
||||
lbs: 14 * 3500,
|
||||
kg: 14 * 1588,
|
||||
},
|
||||
},
|
||||
maxTOW: {
|
||||
er: {
|
||||
lbs: 630500,
|
||||
kg: 285990,
|
||||
},
|
||||
norm: {
|
||||
lbs: 625500,
|
||||
kg: 283722,
|
||||
},
|
||||
},
|
||||
maxFuel: {
|
||||
er: {
|
||||
lbs: 282619,
|
||||
kg: 128193,
|
||||
},
|
||||
norm: {
|
||||
lbs: 256207,
|
||||
kg: 116213,
|
||||
},
|
||||
},
|
||||
erExtraWeight: {
|
||||
lbs: 200,
|
||||
kg: 91,
|
||||
},
|
||||
CGLimits: {
|
||||
min: 12,
|
||||
default: 20.5,
|
||||
max: 34,
|
||||
tolerance: 0.05,
|
||||
},
|
||||
};
|
||||
|
||||
export const initialPayload = {
|
||||
empty: 0,
|
||||
pilot: 0,
|
||||
firstOfficer: 0,
|
||||
engineer: 0,
|
||||
cabinCrewFront: 0,
|
||||
business1Left: 0,
|
||||
business1Center: 0,
|
||||
business1Right: 0,
|
||||
business2Left: 0,
|
||||
business2Center: 0,
|
||||
business2Right: 0,
|
||||
economy1Left: 0,
|
||||
economy1Center: 0,
|
||||
economy1Right: 0,
|
||||
economy2Left: 0,
|
||||
economy2Center: 0,
|
||||
economy2Right: 0,
|
||||
cabinCrewRear: 0,
|
||||
forwardCargo: 0,
|
||||
rearCargo: 0,
|
||||
leftAuxPax: 0,
|
||||
rightAuxPax: 0,
|
||||
upper1Left: 0,
|
||||
upper1Right: 0,
|
||||
upper2Left: 0,
|
||||
upper2Right: 0,
|
||||
upper3Left: 0,
|
||||
upper3Right: 0,
|
||||
upper4Left: 0,
|
||||
upper4Right: 0,
|
||||
lowerForward: 0,
|
||||
lowerRear: 0,
|
||||
leftAuxF: 0,
|
||||
rightAuxF: 0,
|
||||
|
||||
paxCount: {
|
||||
business1: 0,
|
||||
business2: 0,
|
||||
economy1: 0,
|
||||
economy2: 0,
|
||||
total: 0,
|
||||
},
|
||||
};
|
||||
|
||||
export const initialFuel = {
|
||||
main1: 0,
|
||||
main3: 0,
|
||||
main2: 0,
|
||||
upperAux: 0,
|
||||
lowerAux: 0,
|
||||
main1Tip: 0,
|
||||
main3Tip: 0,
|
||||
tail: 0,
|
||||
forwardAux1: 0,
|
||||
forwardAux2: 0,
|
||||
};
|
||||
|
||||
// SIM access
|
||||
|
||||
export const getFuel = (unit: 'kg' | 'lbs') => {
|
||||
const conversion = SimVar.GetSimVarValue('FUEL WEIGHT PER GALLON', unit);
|
||||
|
||||
const fuel = {
|
||||
main1: SimVar.GetSimVarValue('FUEL TANK LEFT MAIN QUANTITY', 'gal') * conversion,
|
||||
main3: SimVar.GetSimVarValue('FUEL TANK RIGHT MAIN QUANTITY', 'gal') * conversion,
|
||||
main2: SimVar.GetSimVarValue('FUEL TANK CENTER QUANTITY', 'gal') * conversion,
|
||||
upperAux: SimVar.GetSimVarValue('FUEL TANK CENTER2 QUANTITY', 'gal') * conversion,
|
||||
lowerAux: SimVar.GetSimVarValue('FUEL TANK CENTER3 QUANTITY', 'gal') * conversion,
|
||||
main1Tip: SimVar.GetSimVarValue('FUEL TANK LEFT TIP QUANTITY', 'gal') * conversion,
|
||||
main3Tip: SimVar.GetSimVarValue('FUEL TANK RIGHT TIP QUANTITY', 'gal') * conversion,
|
||||
tail: SimVar.GetSimVarValue('FUEL TANK EXTERNAL1 QUANTITY', 'gal') * conversion,
|
||||
forwardAux1: SimVar.GetSimVarValue('FUEL TANK LEFT AUX QUANTITY', 'gal') * conversion,
|
||||
forwardAux2: SimVar.GetSimVarValue('FUEL TANK RIGHT AUX QUANTITY', 'gal') * conversion,
|
||||
};
|
||||
|
||||
return fuel;
|
||||
};
|
||||
@@ -1,6 +1,20 @@
|
||||
export const COMMANDS = 'KHOFMANN_PDF_READER_COMMANDS';
|
||||
export const DATA = 'KHOFMANN_PDF_READER_DATA';
|
||||
export const LIST = 'LIST';
|
||||
export const LOAD = 'LOAD';
|
||||
export const SAVE = 'SAVE';
|
||||
export const MAX_LIST = 10;
|
||||
export const COHERENT_COMM_BUS_WASM_CALL = 'COMM_BUS_WASM_CALLBACK';
|
||||
|
||||
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';
|
||||
|
||||
export const CG_ADJUST = 0.05;
|
||||
|
||||
export const GSX_SERVICE_CALLED = 4;
|
||||
export const GSX_SERVICE_ACTIVE = 5;
|
||||
export const GSX_SERVICE_FINISHED = 6;
|
||||
|
||||
export const MODE_SB_SET = 0;
|
||||
export const MODE_ZFW_SET = 1;
|
||||
export const MODE_STATION_SET = 2;
|
||||
export const MODE_LOAD_SET = 3;
|
||||
export const MODE_UNLOAD_SET = 4;
|
||||
export const MODE_OPTIONS_SET = 5;
|
||||
|
||||
@@ -32,9 +32,7 @@
|
||||
class="ingameUiFrame panelInvisible"
|
||||
content-fit="true"
|
||||
>
|
||||
<virtual-scroll direction="y">
|
||||
<div id="react" style="display: flex"></div>
|
||||
</virtual-scroll>
|
||||
<div id="react" style="display: flex"></div>
|
||||
</ingame-ui>
|
||||
</tfdidesign-md11-load-manager-panel>
|
||||
<script src="index.js" type="text/javascript"></script>
|
||||
|
||||
@@ -16,6 +16,7 @@ class TFDiDesignMD11LoadManagerPanel extends TemplateElement {
|
||||
|
||||
const container = document.getElementById('react');
|
||||
if (container) {
|
||||
console.log('Starting React');
|
||||
const root = createRoot(container);
|
||||
root.render(createElement(App, { commBus: this.commBus }));
|
||||
}
|
||||
|
||||
@@ -0,0 +1,102 @@
|
||||
interface WASMData {
|
||||
GSX: GSX;
|
||||
userData: UserData;
|
||||
options: Options;
|
||||
sbPlanned: {
|
||||
ZFW: number;
|
||||
GW: number;
|
||||
};
|
||||
}
|
||||
|
||||
export interface WASMDataPax extends WASMData {
|
||||
livePayload: LivePayloadPax;
|
||||
targetPayload: TargetPayloadPax;
|
||||
limits: LimitsPax;
|
||||
}
|
||||
|
||||
export interface WASMDataF extends WASMData {
|
||||
livePayload: LivePayloadF;
|
||||
targetPayload: TargetPayloadF;
|
||||
limits: LimitsF;
|
||||
}
|
||||
|
||||
interface TargetPayload {
|
||||
CGTarget: number;
|
||||
ZFWCG: number;
|
||||
TOCG: number;
|
||||
total: number;
|
||||
}
|
||||
|
||||
interface TargetPayloadPax extends TargetPayload {
|
||||
empty: number;
|
||||
crew: number;
|
||||
business1: number;
|
||||
business2: number;
|
||||
economy1: number;
|
||||
economy2: number;
|
||||
forwardCargo: number;
|
||||
rearCargo: number;
|
||||
}
|
||||
|
||||
interface LivePayloadPax extends TargetPayloadPax {
|
||||
fuel: number;
|
||||
}
|
||||
|
||||
interface TargetPayloadF extends TargetPayload {
|
||||
empty: number;
|
||||
crew: number;
|
||||
upper1: number;
|
||||
upper2: number;
|
||||
upper3: number;
|
||||
upper4: number;
|
||||
lowerForward: number;
|
||||
lowerRear: number;
|
||||
}
|
||||
|
||||
interface LivePayloadF extends TargetPayloadF {
|
||||
fuel: number;
|
||||
}
|
||||
|
||||
interface GSX {
|
||||
boardingState: number;
|
||||
deboardingState: number;
|
||||
}
|
||||
|
||||
interface Limits {
|
||||
minCG: number;
|
||||
maxCG: number;
|
||||
maxFuel: number;
|
||||
maxTOW: number;
|
||||
maxZFW: number;
|
||||
minZFW: number;
|
||||
}
|
||||
|
||||
interface LimitsPax extends Limits {
|
||||
business1: number;
|
||||
business2: number;
|
||||
economy1: number;
|
||||
economy2: number;
|
||||
forwardCargo: number;
|
||||
rearCargo: number;
|
||||
}
|
||||
|
||||
interface LimitsF extends Limits {
|
||||
upper1: number;
|
||||
upper2: number;
|
||||
upper3: number;
|
||||
upper4: number;
|
||||
lowerForward: number;
|
||||
lowerRear: number;
|
||||
}
|
||||
|
||||
interface UserData {
|
||||
isCargo: boolean;
|
||||
isER: boolean;
|
||||
isImperial: boolean;
|
||||
}
|
||||
|
||||
interface Options {
|
||||
GSXSync: boolean;
|
||||
paxWeight: number;
|
||||
bagWeight: number;
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
export type LoadingState = 'preview' | 'loaded';
|
||||
|
||||
export interface SimBrief {
|
||||
plannedZFW: number;
|
||||
plannedGW: number;
|
||||
pax: number;
|
||||
cargo: number;
|
||||
fuel: number;
|
||||
}
|
||||
-10
@@ -1,10 +0,0 @@
|
||||
import '@mui/material';
|
||||
|
||||
declare module '@mui/material/styles' {
|
||||
interface Theme {
|
||||
screenHeight: number;
|
||||
}
|
||||
interface ThemeOptions {
|
||||
screenHeight: number;
|
||||
}
|
||||
}
|
||||
@@ -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 flightPlanURL = `https://www.simbrief.com/api/xml.fetcher.php?username=${simBriefUsername}&json=1`;
|
||||
let response: Response;
|
||||
@@ -8,6 +5,7 @@ const getSimBriefFlightPlan = async (simBriefUsername: string) => {
|
||||
try {
|
||||
response = await fetch(flightPlanURL);
|
||||
success = true;
|
||||
//eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
} catch (e: any) {
|
||||
response = e.response;
|
||||
}
|
||||
@@ -19,9 +17,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 +40,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)),
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
@@ -0,0 +1,134 @@
|
||||
import {
|
||||
COHERENT_COMM_BUS_WASM_CALL,
|
||||
COMM_BUS_UPDATE_TARGET_EVENT,
|
||||
MODE_LOAD_SET,
|
||||
MODE_OPTIONS_SET,
|
||||
MODE_SB_SET,
|
||||
MODE_STATION_SET,
|
||||
MODE_UNLOAD_SET,
|
||||
MODE_ZFW_SET,
|
||||
} from '../constants';
|
||||
import { SimBrief } from '../types/general';
|
||||
|
||||
export const loadAircraft = () => {
|
||||
Coherent.call(
|
||||
COHERENT_COMM_BUS_WASM_CALL,
|
||||
COMM_BUS_UPDATE_TARGET_EVENT,
|
||||
JSON.stringify({
|
||||
mode: MODE_LOAD_SET,
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
export const unloadAircraft = () => {
|
||||
Coherent.call(
|
||||
COHERENT_COMM_BUS_WASM_CALL,
|
||||
COMM_BUS_UPDATE_TARGET_EVENT,
|
||||
JSON.stringify({
|
||||
mode: MODE_UNLOAD_SET,
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
export const inRangeOf = (value: number, target: number, tolerance: number = 10) => {
|
||||
return Math.abs(value - target) < tolerance;
|
||||
};
|
||||
|
||||
export const CoherentCallZFWEntry = (ZFWTarget: number, CGTarget: number) => {
|
||||
Coherent.call(
|
||||
COHERENT_COMM_BUS_WASM_CALL,
|
||||
COMM_BUS_UPDATE_TARGET_EVENT,
|
||||
JSON.stringify({
|
||||
mode: MODE_ZFW_SET,
|
||||
ZFWTarget: ZFWTarget,
|
||||
CGTarget: CGTarget,
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
export const CoherentCallStationEntryPax = (
|
||||
business1: number,
|
||||
business2: number,
|
||||
economy1: number,
|
||||
economy2: number,
|
||||
forwardCargo: number,
|
||||
rearCargo: number
|
||||
) => {
|
||||
Coherent.call(
|
||||
COHERENT_COMM_BUS_WASM_CALL,
|
||||
COMM_BUS_UPDATE_TARGET_EVENT,
|
||||
JSON.stringify({
|
||||
mode: MODE_STATION_SET,
|
||||
business1,
|
||||
business2,
|
||||
economy1,
|
||||
economy2,
|
||||
forwardCargo,
|
||||
rearCargo,
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
export const CoherentCallStationEntryF = (
|
||||
upper1: number,
|
||||
upper2: number,
|
||||
upper3: number,
|
||||
upper4: number,
|
||||
lowerForward: number,
|
||||
lowerRear: number
|
||||
) => {
|
||||
Coherent.call(
|
||||
COHERENT_COMM_BUS_WASM_CALL,
|
||||
COMM_BUS_UPDATE_TARGET_EVENT,
|
||||
JSON.stringify({
|
||||
mode: MODE_STATION_SET,
|
||||
upper1,
|
||||
upper2,
|
||||
upper3,
|
||||
upper4,
|
||||
lowerForward,
|
||||
lowerRear,
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
export const CoherentCallSBEntryPax = (CGTarget: number, SBPlan?: SimBrief) => {
|
||||
const payload = {
|
||||
mode: MODE_SB_SET,
|
||||
cargo: SBPlan?.cargo,
|
||||
numPax: SBPlan ? parseInt(SBPlan.pax as unknown as string) : undefined,
|
||||
CGTarget: CGTarget,
|
||||
plannedZFW: SBPlan?.plannedZFW,
|
||||
plannedGW: SBPlan?.plannedGW,
|
||||
};
|
||||
const string = JSON.stringify(payload);
|
||||
|
||||
Coherent.call(COHERENT_COMM_BUS_WASM_CALL, COMM_BUS_UPDATE_TARGET_EVENT, string);
|
||||
};
|
||||
|
||||
export const CoherentCallSBEntryF = (CGTarget: number, SBPlan?: SimBrief) => {
|
||||
Coherent.call(
|
||||
COHERENT_COMM_BUS_WASM_CALL,
|
||||
COMM_BUS_UPDATE_TARGET_EVENT,
|
||||
JSON.stringify({
|
||||
mode: MODE_SB_SET,
|
||||
cargo: SBPlan?.cargo,
|
||||
CGTarget: CGTarget,
|
||||
plannedZFW: SBPlan?.plannedZFW,
|
||||
plannedGW: SBPlan?.plannedGW,
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
export const CoherentCallOptionsSet = (GSXSync?: boolean, paxWeight?: number, bagWeight?: number) => {
|
||||
Coherent.call(
|
||||
COHERENT_COMM_BUS_WASM_CALL,
|
||||
COMM_BUS_UPDATE_TARGET_EVENT,
|
||||
JSON.stringify({
|
||||
mode: MODE_OPTIONS_SET,
|
||||
GSXSync,
|
||||
paxWeight,
|
||||
bagWeight,
|
||||
})
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,306 @@
|
||||
#include "freighter.h"
|
||||
|
||||
// ZFW Entry
|
||||
void distribute(fPayloadData_t* const targetPayload, const FuelData_t* const fuel, const double ZFWTarget, const UserData_t* const userData) {
|
||||
// Find payload, num pax and extra cargo
|
||||
double payload = ZFWTarget - targetPayload->empty - targetPayload->pilot - targetPayload->firstOfficer - targetPayload->engineer -
|
||||
targetPayload->leftAux - targetPayload->rightAux;
|
||||
unsigned int cargo = round(payload);
|
||||
|
||||
distribute(targetPayload, fuel, cargo, userData);
|
||||
}
|
||||
|
||||
// SimBrief Entry
|
||||
void distribute(fPayloadData_t* const targetPayload, const FuelData_t* const fuel, unsigned int cargo, const UserData_t* const userData) {
|
||||
// Clear
|
||||
targetPayload->stations.upper1 = targetPayload->stations.upper2 = targetPayload->stations.upper3 = targetPayload->stations.upper4 =
|
||||
targetPayload->stations.total = 0;
|
||||
targetPayload->lowerForward = targetPayload->lowerRear = 0;
|
||||
|
||||
unsigned short _cargo = 0;
|
||||
unsigned int count = MAX_UPPER_CARGO(userData->isImperial) * 4 + MAX_FRONT_CARGO(userData->isImperial) + MAX_REAR_CARGO(userData->isImperial, userData->isER);
|
||||
// Initial distributiob
|
||||
while (cargo > 0 && count > 0) {
|
||||
if (cargo >= 6) {
|
||||
if (targetPayload->stations.upper1 < MAX_UPPER_CARGO(userData->isImperial)) {
|
||||
targetPayload->stations.upper1++;
|
||||
_cargo++;
|
||||
}
|
||||
if (targetPayload->stations.upper2 < MAX_UPPER_CARGO(userData->isImperial)) {
|
||||
targetPayload->stations.upper2++;
|
||||
_cargo++;
|
||||
}
|
||||
if (targetPayload->stations.upper3 < MAX_UPPER_CARGO(userData->isImperial)) {
|
||||
targetPayload->stations.upper3++;
|
||||
_cargo++;
|
||||
}
|
||||
if (targetPayload->stations.upper4 < MAX_UPPER_CARGO(userData->isImperial)) {
|
||||
targetPayload->stations.upper4++;
|
||||
_cargo++;
|
||||
}
|
||||
if (targetPayload->lowerForward < MAX_FRONT_CARGO(userData->isImperial)) {
|
||||
targetPayload->lowerForward++;
|
||||
_cargo++;
|
||||
}
|
||||
if (targetPayload->lowerRear < MAX_REAR_CARGO(userData->isImperial, userData->isER)) {
|
||||
targetPayload->lowerRear++;
|
||||
_cargo++;
|
||||
}
|
||||
} else if (cargo == 5) {
|
||||
if (targetPayload->stations.upper1 < MAX_UPPER_CARGO(userData->isImperial)) {
|
||||
targetPayload->stations.upper1++;
|
||||
_cargo++;
|
||||
}
|
||||
if (targetPayload->stations.upper2 < MAX_UPPER_CARGO(userData->isImperial)) {
|
||||
targetPayload->stations.upper2++;
|
||||
_cargo++;
|
||||
}
|
||||
if (targetPayload->stations.upper3 < MAX_UPPER_CARGO(userData->isImperial)) {
|
||||
targetPayload->stations.upper3++;
|
||||
_cargo++;
|
||||
}
|
||||
if (targetPayload->stations.upper4 < MAX_UPPER_CARGO(userData->isImperial)) {
|
||||
targetPayload->stations.upper4++;
|
||||
_cargo++;
|
||||
}
|
||||
if (targetPayload->lowerForward < MAX_FRONT_CARGO(userData->isImperial)) {
|
||||
targetPayload->lowerForward++;
|
||||
_cargo++;
|
||||
}
|
||||
}
|
||||
else if (cargo == 4) {
|
||||
if (targetPayload->stations.upper1 < MAX_UPPER_CARGO(userData->isImperial)) {
|
||||
targetPayload->stations.upper1++;
|
||||
_cargo++;
|
||||
}
|
||||
if (targetPayload->stations.upper2 < MAX_UPPER_CARGO(userData->isImperial)) {
|
||||
targetPayload->stations.upper2++;
|
||||
_cargo++;
|
||||
}
|
||||
if (targetPayload->stations.upper3 < MAX_UPPER_CARGO(userData->isImperial)) {
|
||||
targetPayload->stations.upper3++;
|
||||
_cargo++;
|
||||
}
|
||||
if (targetPayload->stations.upper4 < MAX_UPPER_CARGO(userData->isImperial)) {
|
||||
targetPayload->stations.upper4++;
|
||||
_cargo++;
|
||||
}
|
||||
}
|
||||
else if (cargo == 3) {
|
||||
if (targetPayload->stations.upper1 < MAX_UPPER_CARGO(userData->isImperial)) {
|
||||
targetPayload->stations.upper1++;
|
||||
_cargo++;
|
||||
}
|
||||
if (targetPayload->stations.upper2 < MAX_UPPER_CARGO(userData->isImperial)) {
|
||||
targetPayload->stations.upper2++;
|
||||
_cargo++;
|
||||
}
|
||||
if (targetPayload->stations.upper3 < MAX_UPPER_CARGO(userData->isImperial)) {
|
||||
targetPayload->stations.upper3++;
|
||||
_cargo++;
|
||||
}
|
||||
}
|
||||
else if (cargo == 2) {
|
||||
if (targetPayload->stations.upper1 < MAX_UPPER_CARGO(userData->isImperial)) {
|
||||
targetPayload->stations.upper1++;
|
||||
_cargo++;
|
||||
}
|
||||
if (targetPayload->stations.upper2 < MAX_UPPER_CARGO(userData->isImperial)) {
|
||||
targetPayload->stations.upper2++;
|
||||
_cargo++;
|
||||
}
|
||||
}
|
||||
else if (cargo == 1) {
|
||||
if (targetPayload->stations.upper1 < MAX_UPPER_CARGO(userData->isImperial)) {
|
||||
targetPayload->stations.upper1++;
|
||||
_cargo++;
|
||||
}
|
||||
}
|
||||
cargo -= _cargo;
|
||||
targetPayload->stations.total += _cargo;
|
||||
|
||||
_cargo = 0;
|
||||
|
||||
count--;
|
||||
}
|
||||
// Refinement
|
||||
count = MAX_UPPER_CARGO(userData->isImperial) * 4 + MAX_FRONT_CARGO(userData->isImperial) + MAX_REAR_CARGO(userData->isImperial, userData->isER);
|
||||
while (count > 0) {
|
||||
generatePayload(targetPayload, userData->isImperial);
|
||||
calculateCGs(targetPayload, fuel, &targetPayload->ZFWCG, &targetPayload->TOCG, userData->isImperial);
|
||||
|
||||
// in front of target
|
||||
if (targetPayload->ZFWCG < targetPayload->CGTarget - CG_TOLERANCE) {
|
||||
if (targetPayload->stations.upper1 > 0) {
|
||||
targetPayload->stations.upper1--;
|
||||
}
|
||||
else if (targetPayload->stations.upper2 > 0) {
|
||||
targetPayload->stations.upper2--;
|
||||
}
|
||||
else if (targetPayload->stations.upper3 > 0) {
|
||||
targetPayload->stations.upper3--;
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
|
||||
if (targetPayload->stations.upper4 < MAX_UPPER_CARGO(userData->isImperial)) {
|
||||
targetPayload->stations.upper4++;
|
||||
}
|
||||
else if (targetPayload->stations.upper3 < MAX_UPPER_CARGO(userData->isImperial)) {
|
||||
targetPayload->stations.upper3++;
|
||||
}
|
||||
else if (targetPayload->stations.upper2 < MAX_UPPER_CARGO(userData->isImperial)) {
|
||||
targetPayload->stations.upper2++;
|
||||
}
|
||||
else {
|
||||
targetPayload->stations.upper1++;
|
||||
}
|
||||
}
|
||||
// behind target
|
||||
else if (targetPayload->ZFWCG > targetPayload->CGTarget + CG_TOLERANCE) {
|
||||
if (targetPayload->stations.upper4 > 0) {
|
||||
targetPayload->stations.upper4--;
|
||||
}
|
||||
else if (targetPayload->stations.upper3 > 0) {
|
||||
targetPayload->stations.upper3--;
|
||||
}
|
||||
else if (targetPayload->stations.upper2 > 0) {
|
||||
targetPayload->stations.upper2--;
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
|
||||
if (targetPayload->stations.upper1 < MAX_UPPER_CARGO(userData->isImperial)) {
|
||||
targetPayload->stations.upper1++;
|
||||
}
|
||||
else if (targetPayload->stations.upper2 < MAX_UPPER_CARGO(userData->isImperial)) {
|
||||
targetPayload->stations.upper2++;
|
||||
}
|
||||
else if (targetPayload->stations.upper3 < MAX_UPPER_CARGO(userData->isImperial)) {
|
||||
targetPayload->stations.upper3++;
|
||||
}
|
||||
else {
|
||||
targetPayload->stations.upper4++;
|
||||
}
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
|
||||
count--;
|
||||
}
|
||||
// Refinement cargo
|
||||
count = MAX_FRONT_CARGO(userData->isImperial) + MAX_REAR_CARGO(userData->isImperial, userData->isER);
|
||||
while (count > 0) {
|
||||
generatePayload(targetPayload, userData->isImperial);
|
||||
calculateCGs(targetPayload, fuel, &targetPayload->ZFWCG, &targetPayload->TOCG, userData->isImperial);
|
||||
|
||||
// in front of target
|
||||
if (targetPayload->ZFWCG < targetPayload->CGTarget - CG_TOLERANCE) {
|
||||
if (targetPayload->lowerForward > 0 && targetPayload->lowerRear < MAX_REAR_CARGO(userData->isImperial, userData->isER)) {
|
||||
targetPayload->lowerForward--;
|
||||
targetPayload->lowerRear++;
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
// behind target
|
||||
else if (targetPayload->ZFWCG > targetPayload->CGTarget + CG_TOLERANCE) {
|
||||
if (targetPayload->lowerRear > 0 && targetPayload->lowerForward < MAX_FRONT_CARGO(userData->isImperial)) {
|
||||
targetPayload->lowerRear--;
|
||||
targetPayload->lowerForward++;
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
|
||||
count--;
|
||||
}
|
||||
}
|
||||
|
||||
// Updates pax stations with their respective weights
|
||||
// Used internally and used for Station Entry (pax only, cargo is set directly)
|
||||
void generatePayload(fPayloadData_t* const targetPayload, const bool isImperial) {
|
||||
targetPayload->upper1Left = targetPayload->upper1Right = (targetPayload->stations.upper1 / 2.0);
|
||||
targetPayload->upper2Left = targetPayload->upper2Right = (targetPayload->stations.upper2 / 2.0);
|
||||
targetPayload->upper3Left = targetPayload->upper3Right = (targetPayload->stations.upper3 / 2.0);
|
||||
targetPayload->upper4Left = targetPayload->upper4Right = (targetPayload->stations.upper4 / 2.0);
|
||||
targetPayload->total = targetPayload->empty + targetPayload->pilot + targetPayload->firstOfficer + targetPayload->engineer + targetPayload->upper1Left +
|
||||
targetPayload->upper1Right + targetPayload->upper2Left + targetPayload->upper2Right + targetPayload->upper3Left +
|
||||
targetPayload->upper3Right + targetPayload->upper4Left + targetPayload->upper4Right + targetPayload->lowerForward +
|
||||
targetPayload->lowerRear + targetPayload->leftAux + targetPayload->rightAux;
|
||||
}
|
||||
|
||||
// Normalise to Pounds
|
||||
// MANDATORY BEFORE SETTING WEIGHTS
|
||||
// USE ON COPY OF GLOBAL STATE ONLY
|
||||
void normalisePayload(fPayloadData_t* const targetPayload, const bool isImperial) {
|
||||
targetPayload->empty = TO_POUNDS(isImperial, targetPayload->empty);
|
||||
targetPayload->pilot = TO_POUNDS(isImperial, targetPayload->pilot);
|
||||
targetPayload->firstOfficer = TO_POUNDS(isImperial, targetPayload->firstOfficer);
|
||||
targetPayload->engineer = TO_POUNDS(isImperial, targetPayload->engineer);
|
||||
targetPayload->upper1Left = TO_POUNDS(isImperial, targetPayload->upper1Left);
|
||||
targetPayload->upper1Right = TO_POUNDS(isImperial, targetPayload->upper1Right);
|
||||
targetPayload->upper2Left = TO_POUNDS(isImperial, targetPayload->upper2Left);
|
||||
targetPayload->upper2Right = TO_POUNDS(isImperial, targetPayload->upper2Right);
|
||||
targetPayload->upper3Left = TO_POUNDS(isImperial, targetPayload->upper3Left);
|
||||
targetPayload->upper3Right = TO_POUNDS(isImperial, targetPayload->upper3Right);
|
||||
targetPayload->upper4Left = TO_POUNDS(isImperial, targetPayload->upper4Left);
|
||||
targetPayload->upper4Right = TO_POUNDS(isImperial, targetPayload->upper4Right);
|
||||
targetPayload->lowerForward = TO_POUNDS(isImperial, targetPayload->lowerForward);
|
||||
targetPayload->lowerRear = TO_POUNDS(isImperial, targetPayload->lowerRear);
|
||||
targetPayload->leftAux = TO_POUNDS(isImperial, targetPayload->leftAux);
|
||||
targetPayload->rightAux = TO_POUNDS(isImperial, targetPayload->rightAux);
|
||||
}
|
||||
|
||||
void calculateCGs(const fPayloadData_t* const targetPayload, const FuelData_t* const fuel, double* const ZFWCG, double* const TOCG, const bool isImperial) {
|
||||
fPayloadData_t localPayload = {};
|
||||
memcpy(&localPayload, targetPayload, sizeof(localPayload));
|
||||
normalisePayload(&localPayload, isImperial);
|
||||
|
||||
double totalMoment = localPayload.empty * ARM_EMPTY + localPayload.pilot * ARM_PILOT + localPayload.firstOfficer * ARM_FIRST_OFFICER +
|
||||
localPayload.engineer * ARM_ENGINEER + localPayload.upper1Left * ARM_F_UPPER1_LEFT + localPayload.upper1Right * ARM_F_UPPER1_RIGHT +
|
||||
localPayload.upper2Left * ARM_F_UPPER2_LEFT + localPayload.upper2Right * ARM_F_UPPER2_RIGHT + localPayload.upper3Left * ARM_F_UPPER3_LEFT +
|
||||
localPayload.upper3Right * ARM_F_UPPER3_RIGHT + localPayload.upper4Left * ARM_F_UPPER4_LEFT + localPayload.upper4Right * ARM_F_UPPER4_RIGHT +
|
||||
localPayload.lowerForward * ARM_FORWARD_CARGO + localPayload.lowerRear * ARM_REAR_CARGO + localPayload.leftAux * ARM_LEFT_AUX +
|
||||
localPayload.rightAux * ARM_RIGHT_AUX;
|
||||
|
||||
double totalWeight = localPayload.empty + localPayload.pilot + localPayload.firstOfficer + localPayload.engineer + localPayload.upper1Left +
|
||||
localPayload.upper1Right + localPayload.upper2Left + localPayload.upper2Right + localPayload.upper3Left + localPayload.upper3Right +
|
||||
localPayload.upper4Left + localPayload.upper4Right + localPayload.lowerForward + localPayload.lowerRear + localPayload.leftAux +
|
||||
localPayload.rightAux;
|
||||
|
||||
*ZFWCG = TO_PERCENT_MAC(totalMoment / totalWeight);
|
||||
|
||||
totalMoment += fuel->main1 * ARM_MAIN1 + fuel->main3 * ARM_MAIN3 + fuel->main2 * ARM_MAIN2 + fuel->upperAux * ARM_UPPER_AUX +
|
||||
fuel->lowerAux * ARM_LOWER_AUX + fuel->main1Tip * ARM_MAIN1_TIP + fuel->main3Tip * ARM_MAIN3_TIP +
|
||||
fuel->tail * ARM_TAIL + fuel->forwardAux1 * ARM_FORWARD_AUX1 + fuel->forwardAux2 * ARM_FORWARD_AUX2;
|
||||
|
||||
totalWeight += fuel->total;
|
||||
|
||||
*TOCG = TO_PERCENT_MAC(totalMoment / totalWeight);
|
||||
}
|
||||
|
||||
void load(const fPayloadData_t* const targetPayload, const HANDLE simConnect, const bool isImperial) {
|
||||
fPayloadData_t localPayload = {};
|
||||
memcpy(&localPayload, targetPayload, sizeof(localPayload));
|
||||
normalisePayload(&localPayload, isImperial);
|
||||
|
||||
SimConnect_SetDataOnSimObject(simConnect, DATA_DEFINITION_PAYLOAD_F, SIMCONNECT_OBJECT_ID_USER, 0, 0, sizeof(fPayloadDataSet_t), &localPayload);
|
||||
}
|
||||
|
||||
void unloadF(const HANDLE simConnect, const bool isER) {
|
||||
fPayloadData_t localPayload = {};
|
||||
|
||||
localPayload.leftAux = localPayload.rightAux = isER ? AUX_WEIGHT(true) : 0;
|
||||
localPayload.pilot = localPayload.firstOfficer = localPayload.engineer = PILOT_WEIGHT(true);
|
||||
|
||||
SimConnect_SetDataOnSimObject(simConnect, DATA_DEFINITION_PAYLOAD_F, SIMCONNECT_OBJECT_ID_USER, 0, 0, sizeof(fPayloadDataSet_t), &localPayload);
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef __INTELLISENSE__
|
||||
# define MODULE_EXPORT __attribute__( ( visibility( "default" ) ) )
|
||||
# define MODULE_WASM_MODNAME(mod) __attribute__((import_module(mod)))
|
||||
#else
|
||||
# define MODULE_EXPORT
|
||||
# define MODULE_WASM_MODNAME(mod)
|
||||
# define __attribute__(x)
|
||||
# define __restrict__
|
||||
#endif
|
||||
|
||||
/********************************* Headers *********************************/
|
||||
// MSFS headers
|
||||
#include <MSFS/MSFS_WindowsTypes.h>
|
||||
#include <SimConnect.h>
|
||||
// C headers
|
||||
#include <math.h>
|
||||
// C++ headers
|
||||
#include <algorithm>
|
||||
// Own headers
|
||||
#include "shared.h"
|
||||
|
||||
/******************************** Constants ********************************/
|
||||
//PMC pallet due to 104in door
|
||||
#define MAX_FRONT_CARGO(IS_IMPERIAL) ((IS_IMPERIAL) ? (6.0 * 15000.0) : (6.0 * 6804.0))
|
||||
// Max ZFW
|
||||
#define MAX_F_ZFW(IS_IMPERIAL) ((IS_IMPERIAL) ? (451300) : (204706))
|
||||
// Arms
|
||||
#define ARM_F_UPPER1_LEFT 660
|
||||
#define ARM_F_UPPER1_RIGHT 660
|
||||
#define ARM_F_UPPER2_LEFT 240
|
||||
#define ARM_F_UPPER2_RIGHT 240
|
||||
#define ARM_F_UPPER3_LEFT -240
|
||||
#define ARM_F_UPPER3_RIGHT -240
|
||||
#define ARM_F_UPPER4_LEFT -600
|
||||
#define ARM_F_UPPER4_RIGHT -600
|
||||
|
||||
/***************************** Data structures *****************************/
|
||||
typedef struct {
|
||||
// SimConnect mapped
|
||||
double pilot;
|
||||
double firstOfficer;
|
||||
double engineer;
|
||||
double upper1Left;
|
||||
double upper1Right;
|
||||
double upper2Left;
|
||||
double upper2Right;
|
||||
double upper3Left;
|
||||
double upper3Right;
|
||||
double upper4Left;
|
||||
double upper4Right;
|
||||
double lowerForward;
|
||||
double lowerRear;
|
||||
double leftAux;
|
||||
double rightAux;
|
||||
|
||||
// Additional properties
|
||||
double empty;
|
||||
double total;
|
||||
double CGTarget;
|
||||
double ZFWCG;
|
||||
double TOCG;
|
||||
struct stations {
|
||||
unsigned int upper1;
|
||||
unsigned int upper2;
|
||||
unsigned int upper3;
|
||||
unsigned int upper4;
|
||||
unsigned int total;
|
||||
} stations;
|
||||
struct sbPlanned {
|
||||
double ZFW;
|
||||
double GW;
|
||||
unsigned int cargo;
|
||||
} sbPlanned;
|
||||
} fPayloadData_t;
|
||||
|
||||
typedef struct {
|
||||
// SimConnect mapped
|
||||
double pilot;
|
||||
double firstOfficer;
|
||||
double engineer;
|
||||
double upper1Left;
|
||||
double upper1Right;
|
||||
double upper2Left;
|
||||
double upper2Right;
|
||||
double upper3Left;
|
||||
double upper3Right;
|
||||
double upper4Left;
|
||||
double upper4Right;
|
||||
double lowerForward;
|
||||
double lowerRear;
|
||||
double leftAux;
|
||||
double rightAux;
|
||||
} fPayloadDataSet_t;
|
||||
|
||||
/******************************** Functions ********************************/
|
||||
// ZFW Entry
|
||||
void distribute(fPayloadData_t* const targetPayload, const FuelData_t* const fuel, const double ZFWTarget, const UserData_t* const userData);
|
||||
// SimBrief Entry
|
||||
void distribute(fPayloadData_t* const targetPayload, const FuelData_t* const fuel, unsigned int cargo, const UserData_t* const userData);
|
||||
// Updates pax stations with their respective weights
|
||||
// Used internally and used for Station Entry (pax only, cargo is ste directly)
|
||||
// STATION WEIGHTS ARE NOT NORMALISED TO POUNDS
|
||||
void generatePayload(fPayloadData_t* const targetPayload, const bool isImperial);
|
||||
// Normalise to Pounds
|
||||
// For Station Entry: CALL AFTER `generatePayload`
|
||||
void normalisePayload(fPayloadData_t* const targetPayload, const bool isImperial);
|
||||
void calculateCGs(const fPayloadData_t* const targetPayload, const FuelData_t* const fuel, double* const ZFWCG, double* const TOCG, const bool isImperial);
|
||||
void load(const fPayloadData_t* const targetPayload, const HANDLE simConnect, const bool isImperial);
|
||||
void unloadF(const HANDLE simConnect, const bool isER);
|
||||
@@ -0,0 +1,25 @@
|
||||
// load-manager-cli.cpp : This file contains the 'main' function. Program execution begins and ends there.
|
||||
//
|
||||
|
||||
#include "../wasm-module/pax.h"
|
||||
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
bool isImperial = false;
|
||||
bool isER = true;
|
||||
|
||||
paxPayloadData_t targetPaxPayloadData = paxPayloadData_t();
|
||||
targetPaxPayloadData.empty = FROM_POUNDS(isImperial, 283975);
|
||||
targetPaxPayloadData.pilot = PAX_WEIGHT(isImperial);
|
||||
targetPaxPayloadData.firstOfficer = PAX_WEIGHT(isImperial);
|
||||
targetPaxPayloadData.engineer = PAX_WEIGHT(isImperial);
|
||||
targetPaxPayloadData.cabinCrewFront = FRONT_CREW_WEIGHT(isImperial);
|
||||
targetPaxPayloadData.cabinCrewRear = REAR_CREW_WEIGHT(isImperial);
|
||||
targetPaxPayloadData.leftAux = isER ? AUX_WEIGHT(isImperial) : 0;
|
||||
targetPaxPayloadData.rightAux = isER ? AUX_WEIGHT(isImperial) : 0;
|
||||
FuelData_t liveFuelData = FuelData_t();
|
||||
|
||||
distribute(&targetPaxPayloadData, &liveFuelData, 162000.0, 20.5, isImperial);
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCProjectVersion>17.0</VCProjectVersion>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<ProjectGuid>{992caf4b-b3f6-4a86-a1c1-663686082c5e}</ProjectGuid>
|
||||
<RootNamespace>loadmanagercli</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="Shared">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<IntDir>$(Platform)\$(Configuration)\</IntDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<IntDir>$(Platform)\$(Configuration)\</IntDir>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="pax.cpp" />
|
||||
<ClCompile Include="load-manager-cli.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="pax.h" />
|
||||
<ClInclude Include="types.h" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,34 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Header Files">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Resource Files">
|
||||
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||
<Extensions>
|
||||
rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="load-manager-cli.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="pax.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="pax.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="types.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup />
|
||||
</Project>
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,45 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef __INTELLISENSE__
|
||||
# define MODULE_EXPORT __attribute__( ( visibility( "default" ) ) )
|
||||
# define MODULE_WASM_MODNAME(mod) __attribute__((import_module(mod)))
|
||||
#else
|
||||
# define MODULE_EXPORT
|
||||
# define MODULE_WASM_MODNAME(mod)
|
||||
# define __attribute__(x)
|
||||
# define __restrict__
|
||||
#endif
|
||||
|
||||
/********************************* Headers *********************************/
|
||||
// MSFS headers
|
||||
#include <MSFS/MSFS.h>
|
||||
#include <MSFS/MSFS_CommBus.h>
|
||||
#include <MSFS/Legacy/gauges.h>
|
||||
#include <rapidjson/document.h>
|
||||
#include <rapidjson/filereadstream.h>
|
||||
#include "rapidjson/filewritestream.h"
|
||||
#include <rapidjson/writer.h>
|
||||
#include <SimConnect.h>
|
||||
// C headers
|
||||
#include <string.h>
|
||||
// C++ headers
|
||||
#include <ctime>
|
||||
// Own headers
|
||||
#include "shared.h"
|
||||
#include "pax.h"
|
||||
#include "freighter.h"
|
||||
|
||||
/******************************** Constants ********************************/
|
||||
// Module identification
|
||||
#define MODULE_NAME "[KHOFMANN TFDi MD-11 Load Manager] "
|
||||
#define VERSION_STRING " 1.0 "
|
||||
// COMM BUS
|
||||
#define COMM_BUS_LIVE_DATA_EVENT "khofmann_tfdi_md-11_load_manager_live_data"
|
||||
#define COMM_BUS_UPDATE_TARGET_EVENT "khofmann_tfdi_md-11_load_manager_update_target"
|
||||
|
||||
/******************************** Functions ********************************/
|
||||
void commBusUpdateTargetCallback(const char* args, unsigned int size, void* ctx);
|
||||
int receiveData(const char* buf);
|
||||
void sendData();
|
||||
void CALLBACK MyDispatchProc(SIMCONNECT_RECV* pData, DWORD cbData, void* pContext);
|
||||
void log(FILE* file, const char* format, void* optionalElement = NULL);
|
||||
@@ -0,0 +1,37 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.13.36105.23
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "load-manager", "load-manager.vcxproj", "{A5468B35-BBBD-4C55-97ED-81BFE343B0E4}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "load-manager-cli", "load-manager-cli.vcxproj", "{992CAF4B-B3F6-4A86-A1C1-663686082C5E}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|MSFS = Debug|MSFS
|
||||
Debug|x64 = Debug|x64
|
||||
Release|MSFS = Release|MSFS
|
||||
Release|x64 = Release|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{A5468B35-BBBD-4C55-97ED-81BFE343B0E4}.Debug|MSFS.ActiveCfg = Debug|MSFS
|
||||
{A5468B35-BBBD-4C55-97ED-81BFE343B0E4}.Debug|MSFS.Build.0 = Debug|MSFS
|
||||
{A5468B35-BBBD-4C55-97ED-81BFE343B0E4}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{A5468B35-BBBD-4C55-97ED-81BFE343B0E4}.Release|MSFS.ActiveCfg = Release|MSFS
|
||||
{A5468B35-BBBD-4C55-97ED-81BFE343B0E4}.Release|MSFS.Build.0 = Release|MSFS
|
||||
{A5468B35-BBBD-4C55-97ED-81BFE343B0E4}.Release|x64.ActiveCfg = Release|MSFS
|
||||
{992CAF4B-B3F6-4A86-A1C1-663686082C5E}.Debug|MSFS.ActiveCfg = Debug|x64
|
||||
{992CAF4B-B3F6-4A86-A1C1-663686082C5E}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{992CAF4B-B3F6-4A86-A1C1-663686082C5E}.Debug|x64.Build.0 = Debug|x64
|
||||
{992CAF4B-B3F6-4A86-A1C1-663686082C5E}.Release|MSFS.ActiveCfg = Release|x64
|
||||
{992CAF4B-B3F6-4A86-A1C1-663686082C5E}.Release|x64.ActiveCfg = Release|x64
|
||||
{992CAF4B-B3F6-4A86-A1C1-663686082C5E}.Release|x64.Build.0 = Release|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {835CA9EE-0C67-4B32-B910-3F3A40943047}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup />
|
||||
</Project>
|
||||
@@ -0,0 +1,299 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|MSFS">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>MSFS</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|MSFS">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>MSFS</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCProjectVersion>16.0</VCProjectVersion>
|
||||
<ProjectGuid>{A5468B35-BBBD-4C55-97ED-81BFE343B0E4}</ProjectGuid>
|
||||
<RootNamespace>Module</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
||||
<ProjectName>load-manager</ProjectName>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|MSFS'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>MSFS</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>MSFS</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|MSFS'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>MSFS</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>MSFS</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="Shared">
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|MSFS'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|MSFS'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|MSFS'">
|
||||
<TargetExt>.wasm</TargetExt>
|
||||
<GenerateManifest />
|
||||
<LinkIncremental />
|
||||
<IncludePath>$(MSFS_IncludePath)</IncludePath>
|
||||
<TargetName>$(ProjectName)</TargetName>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<TargetExt>.wasm</TargetExt>
|
||||
<GenerateManifest />
|
||||
<LinkIncremental />
|
||||
<IncludePath>$(MSFS_IncludePath)</IncludePath>
|
||||
<TargetName>$(ProjectName)</TargetName>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|MSFS'">
|
||||
<TargetExt>.wasm</TargetExt>
|
||||
<IncludePath>$(MSFS_IncludePath)</IncludePath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<TargetExt>.wasm</TargetExt>
|
||||
<IncludePath>$(MSFS_IncludePath)</IncludePath>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|MSFS'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<SDLCheck>
|
||||
</SDLCheck>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<BufferSecurityCheck>false</BufferSecurityCheck>
|
||||
<AdditionalIncludeDirectories>
|
||||
</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>__wasi__;_STRING_H_CPLUSPLUS_98_CONFORMANCE_;_WCHAR_H_CPLUSPLUS_98_CONFORMANCE_;_LIBCPP_HAS_NO_THREADS;_WINDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ShowIncludes>false</ShowIncludes>
|
||||
<ExceptionHandling>false</ExceptionHandling>
|
||||
<RuntimeTypeInfo>
|
||||
</RuntimeTypeInfo>
|
||||
<SupportJustMyCode>
|
||||
</SupportJustMyCode>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<BasicRuntimeChecks>
|
||||
</BasicRuntimeChecks>
|
||||
<LanguageStandard>stdcpp14</LanguageStandard>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>
|
||||
</SubSystem>
|
||||
<AdditionalDependencies>
|
||||
</AdditionalDependencies>
|
||||
<IgnoreAllDefaultLibraries>
|
||||
</IgnoreAllDefaultLibraries>
|
||||
<NoEntryPoint>true</NoEntryPoint>
|
||||
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
|
||||
<RandomizedBaseAddress>
|
||||
</RandomizedBaseAddress>
|
||||
<DataExecutionPrevention>
|
||||
</DataExecutionPrevention>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<ProgramDatabaseFile>
|
||||
</ProgramDatabaseFile>
|
||||
<ImportLibrary>
|
||||
</ImportLibrary>
|
||||
<ProfileGuidedDatabase>
|
||||
</ProfileGuidedDatabase>
|
||||
<AdditionalLibraryDirectories>
|
||||
</AdditionalLibraryDirectories>
|
||||
</Link>
|
||||
<PostBuildEvent>
|
||||
<Command>cd $(SolutionDir)..\..\
|
||||
Powershell.exe -File .\copy-debug.ps1</Command>
|
||||
</PostBuildEvent>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<SDLCheck>
|
||||
</SDLCheck>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<BufferSecurityCheck>false</BufferSecurityCheck>
|
||||
<AdditionalIncludeDirectories>
|
||||
</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>__wasi__;_STRING_H_CPLUSPLUS_98_CONFORMANCE_;_WCHAR_H_CPLUSPLUS_98_CONFORMANCE_;_LIBCPP_HAS_NO_THREADS;_WINDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ShowIncludes>false</ShowIncludes>
|
||||
<ExceptionHandling>false</ExceptionHandling>
|
||||
<RuntimeTypeInfo>
|
||||
</RuntimeTypeInfo>
|
||||
<SupportJustMyCode>
|
||||
</SupportJustMyCode>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<BasicRuntimeChecks>
|
||||
</BasicRuntimeChecks>
|
||||
<LanguageStandard>stdcpp14</LanguageStandard>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>
|
||||
</SubSystem>
|
||||
<AdditionalDependencies>
|
||||
</AdditionalDependencies>
|
||||
<IgnoreAllDefaultLibraries>
|
||||
</IgnoreAllDefaultLibraries>
|
||||
<NoEntryPoint>true</NoEntryPoint>
|
||||
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
|
||||
<RandomizedBaseAddress>
|
||||
</RandomizedBaseAddress>
|
||||
<DataExecutionPrevention>
|
||||
</DataExecutionPrevention>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<ProgramDatabaseFile>
|
||||
</ProgramDatabaseFile>
|
||||
<ImportLibrary>
|
||||
</ImportLibrary>
|
||||
<ProfileGuidedDatabase>
|
||||
</ProfileGuidedDatabase>
|
||||
<AdditionalLibraryDirectories>
|
||||
</AdditionalLibraryDirectories>
|
||||
</Link>
|
||||
<PostBuildEvent>
|
||||
<Command>
|
||||
</Command>
|
||||
</PostBuildEvent>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|MSFS'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<AdditionalIncludeDirectories>
|
||||
</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>__wasi__;__wasm32__;_STRING_H_CPLUSPLUS_98_CONFORMANCE_;_WCHAR_H_CPLUSPLUS_98_CONFORMANCE_;_LIBCPP_NO_EXCEPTIONS;_LIBCPP_HAS_NO_THREADS;_LIBCPP_STD_VER=14;_WINDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<BufferSecurityCheck>false</BufferSecurityCheck>
|
||||
<ExceptionHandling>false</ExceptionHandling>
|
||||
<DebugInformationFormat>false</DebugInformationFormat>
|
||||
<SupportJustMyCode>
|
||||
</SupportJustMyCode>
|
||||
<LanguageStandard>stdcpp14</LanguageStandard>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>
|
||||
</SubSystem>
|
||||
<AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<IgnoreAllDefaultLibraries>
|
||||
</IgnoreAllDefaultLibraries>
|
||||
<NoEntryPoint>true</NoEntryPoint>
|
||||
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
|
||||
<RandomizedBaseAddress>
|
||||
</RandomizedBaseAddress>
|
||||
<DataExecutionPrevention>
|
||||
</DataExecutionPrevention>
|
||||
<GenerateDebugInformation>false</GenerateDebugInformation>
|
||||
<ProgramDatabaseFile>
|
||||
</ProgramDatabaseFile>
|
||||
<ImportLibrary>
|
||||
</ImportLibrary>
|
||||
<ProfileGuidedDatabase>
|
||||
</ProfileGuidedDatabase>
|
||||
<AdditionalLibraryDirectories>$(OutDir)</AdditionalLibraryDirectories>
|
||||
</Link>
|
||||
<PostBuildEvent>
|
||||
<Command>cd $(SolutionDir)..\..\
|
||||
Powershell.exe -File .\copy-release.ps1</Command>
|
||||
</PostBuildEvent>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<AdditionalIncludeDirectories>
|
||||
</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>__wasi__;__wasm32__;_STRING_H_CPLUSPLUS_98_CONFORMANCE_;_WCHAR_H_CPLUSPLUS_98_CONFORMANCE_;_LIBCPP_NO_EXCEPTIONS;_LIBCPP_HAS_NO_THREADS;_LIBCPP_STD_VER=14;_WINDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<BufferSecurityCheck>false</BufferSecurityCheck>
|
||||
<ExceptionHandling>false</ExceptionHandling>
|
||||
<DebugInformationFormat>false</DebugInformationFormat>
|
||||
<SupportJustMyCode>
|
||||
</SupportJustMyCode>
|
||||
<LanguageStandard>stdcpp14</LanguageStandard>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>
|
||||
</SubSystem>
|
||||
<AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<IgnoreAllDefaultLibraries>
|
||||
</IgnoreAllDefaultLibraries>
|
||||
<NoEntryPoint>true</NoEntryPoint>
|
||||
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
|
||||
<RandomizedBaseAddress>
|
||||
</RandomizedBaseAddress>
|
||||
<DataExecutionPrevention>
|
||||
</DataExecutionPrevention>
|
||||
<GenerateDebugInformation>false</GenerateDebugInformation>
|
||||
<ProgramDatabaseFile>
|
||||
</ProgramDatabaseFile>
|
||||
<ImportLibrary>
|
||||
</ImportLibrary>
|
||||
<ProfileGuidedDatabase>
|
||||
</ProfileGuidedDatabase>
|
||||
<AdditionalLibraryDirectories>$(OutDir)</AdditionalLibraryDirectories>
|
||||
</Link>
|
||||
<PostBuildEvent>
|
||||
<Command>
|
||||
</Command>
|
||||
</PostBuildEvent>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="freighter.cpp" />
|
||||
<ClCompile Include="load-manager.cpp" />
|
||||
<ClCompile Include="pax.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="freighter.h" />
|
||||
<ClInclude Include="load-manager.h" />
|
||||
<ClInclude Include="pax.h" />
|
||||
<ClInclude Include="shared.h" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,38 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<ClCompile Include="load-manager.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="pax.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="freighter.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="pax.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="load-manager.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="shared.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="freighter.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Filter Include="Header Files">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Source Files">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup />
|
||||
</Project>
|
||||
@@ -0,0 +1,323 @@
|
||||
#include "pax.h"
|
||||
|
||||
// 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 UserData_t* const userData,
|
||||
const UserOptions_t* const userOptions) {
|
||||
// Find payload, num pax and extra cargo
|
||||
double payload = ZFWTarget - targetPayload->empty - targetPayload->pilot - targetPayload->firstOfficer - targetPayload->engineer -
|
||||
targetPayload->cabinCrewFront - targetPayload->cabinCrewRear - targetPayload->leftAux - targetPayload->rightAux;
|
||||
unsigned short numPax = max(0.0, min((double)MAX_PAX, floor(payload / (PAX_WEIGHT(userData->isImperial, userOptions) +
|
||||
BAG_WEIGHT(userData->isImperial, userOptions)))));
|
||||
unsigned int cargo = round(payload - numPax * PAX_WEIGHT(userData->isImperial, userOptions) - numPax * BAG_WEIGHT(userData->isImperial, userOptions));
|
||||
|
||||
distribute(targetPayload, fuel, numPax, cargo, userData, userOptions);
|
||||
}
|
||||
|
||||
// SimBrief Entry, SB pax count and extra cargo
|
||||
void distribute(paxPayloadData_t* const targetPayload, const FuelData_t* const fuel, unsigned short numPax, unsigned int cargo, const UserData_t* const userData,
|
||||
const UserOptions_t* const userOptions) {
|
||||
// Clear
|
||||
targetPayload->paxCount.business1 = targetPayload->paxCount.business2 = targetPayload->paxCount.economy1 = targetPayload->paxCount.economy2 =
|
||||
targetPayload->paxCount.total = 0;
|
||||
targetPayload->forwardCargo = targetPayload->rearCargo = 0;
|
||||
|
||||
unsigned short _numPax = 0;
|
||||
unsigned int count = MAX_PAX;
|
||||
// Initial distribution pax + bags
|
||||
while (numPax > 0 && count > 0) {
|
||||
if (numPax >= 4) {
|
||||
if (targetPayload->paxCount.business1 < MAX_BUSINESS_1) {
|
||||
targetPayload->paxCount.business1++;
|
||||
_numPax++;
|
||||
}
|
||||
if (targetPayload->paxCount.business2 < MAX_BUSINESS_2) {
|
||||
targetPayload->paxCount.business2++;
|
||||
_numPax++;
|
||||
}
|
||||
if (targetPayload->paxCount.economy1 < MAX_ECONOMY_1) {
|
||||
targetPayload->paxCount.economy1++;
|
||||
_numPax++;
|
||||
}
|
||||
if (targetPayload->paxCount.economy2 < MAX_ECONOMY_2) {
|
||||
targetPayload->paxCount.economy2++;
|
||||
_numPax++;
|
||||
}
|
||||
}
|
||||
else if (numPax == 3) {
|
||||
if (targetPayload->paxCount.business2 < MAX_BUSINESS_2) {
|
||||
targetPayload->paxCount.business2++;
|
||||
_numPax++;
|
||||
}
|
||||
if (targetPayload->paxCount.economy1 < MAX_ECONOMY_1) {
|
||||
targetPayload->paxCount.economy1++;
|
||||
_numPax++;
|
||||
}
|
||||
if (targetPayload->paxCount.economy2 < MAX_ECONOMY_2) {
|
||||
targetPayload->paxCount.economy2++;
|
||||
_numPax++;
|
||||
}
|
||||
}
|
||||
else if (numPax == 2) {
|
||||
if (targetPayload->paxCount.economy1 < MAX_ECONOMY_1) {
|
||||
targetPayload->paxCount.economy1++;
|
||||
_numPax++;
|
||||
}
|
||||
if (targetPayload->paxCount.economy2 < MAX_ECONOMY_2) {
|
||||
targetPayload->paxCount.economy2++;
|
||||
_numPax++;
|
||||
}
|
||||
}
|
||||
else if (numPax == 1) {
|
||||
if (targetPayload->paxCount.economy2 < MAX_ECONOMY_2) {
|
||||
targetPayload->paxCount.economy2++;
|
||||
_numPax++;
|
||||
}
|
||||
}
|
||||
numPax -= _numPax;
|
||||
targetPayload->paxCount.total += _numPax;
|
||||
|
||||
if (_numPax % 2 == 0) {
|
||||
targetPayload->forwardCargo += (_numPax / 2) * BAG_WEIGHT(userData->isImperial, userOptions);
|
||||
targetPayload->rearCargo += (_numPax / 2) * BAG_WEIGHT(userData->isImperial, userOptions);
|
||||
}
|
||||
else {
|
||||
_numPax--;
|
||||
targetPayload->forwardCargo += (_numPax / 2 + 1) * BAG_WEIGHT(userData->isImperial, userOptions);
|
||||
targetPayload->rearCargo += (_numPax / 2) * BAG_WEIGHT(userData->isImperial, userOptions);
|
||||
}
|
||||
|
||||
_numPax = 0;
|
||||
|
||||
count--;
|
||||
}
|
||||
count = MAX_FRONT_CARGO(userData->isImperial);
|
||||
// Initial distibution of remaining cargo
|
||||
while (cargo > 0 && count > 0) {
|
||||
if (targetPayload->forwardCargo < MAX_FRONT_CARGO(userData->isImperial)) {
|
||||
targetPayload->forwardCargo++;
|
||||
cargo--;
|
||||
}
|
||||
if (targetPayload->rearCargo < MAX_REAR_CARGO(userData->isImperial, userData->isER) && cargo > 0) {
|
||||
targetPayload->rearCargo++;
|
||||
cargo--;
|
||||
}
|
||||
|
||||
count--;
|
||||
}
|
||||
// Refinement pax
|
||||
count = MAX_PAX;
|
||||
while (count > 0) {
|
||||
generatePayload(targetPayload, userData->isImperial, userOptions);
|
||||
calculateCGs(targetPayload, fuel, &targetPayload->ZFWCG, &targetPayload->TOCG, userData->isImperial);
|
||||
|
||||
// in front of target
|
||||
if (targetPayload->ZFWCG < targetPayload->CGTarget - CG_TOLERANCE) {
|
||||
if (targetPayload->paxCount.business1 > 0) {
|
||||
targetPayload->paxCount.business1--;
|
||||
}
|
||||
else if (targetPayload->paxCount.business2 > 0) {
|
||||
targetPayload->paxCount.business2--;
|
||||
}
|
||||
else if (targetPayload->paxCount.economy1 > 0) {
|
||||
targetPayload->paxCount.economy1--;
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
|
||||
if (targetPayload->paxCount.economy2 < MAX_ECONOMY_2) {
|
||||
targetPayload->paxCount.economy2++;
|
||||
}
|
||||
else if (targetPayload->paxCount.economy1 < MAX_ECONOMY_1) {
|
||||
targetPayload->paxCount.economy1++;
|
||||
}
|
||||
else if (targetPayload->paxCount.business2 < MAX_BUSINESS_2) {
|
||||
targetPayload->paxCount.business2++;
|
||||
}
|
||||
else {
|
||||
targetPayload->paxCount.business1++;
|
||||
}
|
||||
}
|
||||
// behind target
|
||||
else if (targetPayload->ZFWCG > targetPayload->CGTarget + CG_TOLERANCE) {
|
||||
if (targetPayload->paxCount.economy2 > 0) {
|
||||
targetPayload->paxCount.economy2--;
|
||||
}
|
||||
else if (targetPayload->paxCount.economy1 > 0) {
|
||||
targetPayload->paxCount.economy1--;
|
||||
}
|
||||
else if (targetPayload->paxCount.business2 > 0) {
|
||||
targetPayload->paxCount.business2--;
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
|
||||
if (targetPayload->paxCount.business1 < MAX_BUSINESS_1) {
|
||||
targetPayload->paxCount.business1++;
|
||||
}
|
||||
else if (targetPayload->paxCount.business2 < MAX_BUSINESS_2) {
|
||||
targetPayload->paxCount.business2++;
|
||||
}
|
||||
else if (targetPayload->paxCount.economy1 < MAX_ECONOMY_1) {
|
||||
targetPayload->paxCount.economy1++;
|
||||
}
|
||||
else {
|
||||
targetPayload->paxCount.economy2++;
|
||||
}
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
|
||||
count--;
|
||||
}
|
||||
// Refinement cargo
|
||||
count = MAX_FRONT_CARGO(userData->isImperial) + MAX_REAR_CARGO(userData->isImperial, userData->isER);
|
||||
while (count > 0) {
|
||||
generatePayload(targetPayload, userData->isImperial, userOptions);
|
||||
calculateCGs(targetPayload, fuel, &targetPayload->ZFWCG, &targetPayload->TOCG, userData->isImperial);
|
||||
|
||||
// in front of target
|
||||
if (targetPayload->ZFWCG < targetPayload->CGTarget - CG_TOLERANCE) {
|
||||
if (targetPayload->forwardCargo > 0 && targetPayload->rearCargo < MAX_REAR_CARGO(userData->isImperial, userData->isER)) {
|
||||
if (targetPayload->forwardCargo > BAG_WEIGHT(userData->isImperial, userOptions) &&
|
||||
targetPayload->rearCargo < MAX_FRONT_CARGO(userData->isImperial) - BAG_WEIGHT(userData->isImperial, userOptions)) {
|
||||
targetPayload->forwardCargo -= BAG_WEIGHT(userData->isImperial, userOptions);
|
||||
targetPayload->rearCargo += BAG_WEIGHT(userData->isImperial, userOptions);
|
||||
}
|
||||
else {
|
||||
targetPayload->forwardCargo--;
|
||||
targetPayload->rearCargo++;
|
||||
}
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
// behind target
|
||||
else if (targetPayload->ZFWCG > targetPayload->CGTarget + CG_TOLERANCE) {
|
||||
if (targetPayload->rearCargo > 0 && targetPayload->forwardCargo < MAX_FRONT_CARGO(userData->isImperial)) {
|
||||
if (targetPayload->rearCargo > BAG_WEIGHT(userData->isImperial, userOptions) &&
|
||||
targetPayload->forwardCargo < MAX_REAR_CARGO(userData->isImperial, userData->isER) - BAG_WEIGHT(userData->isImperial, userOptions)) {
|
||||
targetPayload->rearCargo -= BAG_WEIGHT(userData->isImperial, userOptions);
|
||||
targetPayload->forwardCargo += BAG_WEIGHT(userData->isImperial, userOptions);
|
||||
}
|
||||
else {
|
||||
targetPayload->rearCargo--;
|
||||
targetPayload->forwardCargo++;
|
||||
}
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
|
||||
count--;
|
||||
}
|
||||
}
|
||||
|
||||
// Updates pax stations with their respective weights
|
||||
// Used internally and used for Station Entry (pax only, cargo is set directly)
|
||||
void generatePayload(paxPayloadData_t* const targetPayload, const bool isImperial, const UserOptions_t* const userOptions) {
|
||||
targetPayload->business1Left = targetPayload->business1Center = targetPayload->business1Right = (targetPayload->paxCount.business1 / 3.0) * PAX_WEIGHT(isImperial, userOptions);
|
||||
targetPayload->business2Left = targetPayload->business2Center = targetPayload->business2Right = (targetPayload->paxCount.business2 / 3.0) * PAX_WEIGHT(isImperial, userOptions);
|
||||
targetPayload->economy1Left = targetPayload->economy1Center = targetPayload->economy1Right = (targetPayload->paxCount.economy1 / 3.0) * PAX_WEIGHT(isImperial, userOptions);
|
||||
targetPayload->economy2Left = targetPayload->economy2Center = targetPayload->economy2Right = (targetPayload->paxCount.economy2 / 3.0) * PAX_WEIGHT(isImperial, userOptions);
|
||||
targetPayload->total = targetPayload->empty + targetPayload->pilot + targetPayload->firstOfficer + targetPayload->engineer + targetPayload->cabinCrewFront +
|
||||
targetPayload->business1Left + targetPayload->business1Center + targetPayload->business1Right + targetPayload->business2Left +
|
||||
targetPayload->business2Center + targetPayload->business2Right + targetPayload->economy1Left + targetPayload->economy1Center +
|
||||
targetPayload->economy1Right + targetPayload->economy2Left + targetPayload->economy2Center + targetPayload->economy2Right +
|
||||
targetPayload->cabinCrewRear + targetPayload->forwardCargo + targetPayload->rearCargo + targetPayload->leftAux + targetPayload->rightAux;
|
||||
}
|
||||
|
||||
// Normalise to Pounds
|
||||
// MANDATORY BEFORE SETTING WEIGHTS
|
||||
// USE ON COPY OF GLOBAL STATE ONLY
|
||||
void normalisePayload(paxPayloadData_t* const targetPayload, const bool isImperial) {
|
||||
targetPayload->empty = TO_POUNDS(isImperial, targetPayload->empty);
|
||||
targetPayload->pilot = TO_POUNDS(isImperial, targetPayload->pilot);
|
||||
targetPayload->firstOfficer = TO_POUNDS(isImperial, targetPayload->firstOfficer);
|
||||
targetPayload->engineer = TO_POUNDS(isImperial, targetPayload->engineer);
|
||||
targetPayload->cabinCrewFront = TO_POUNDS(isImperial, targetPayload->cabinCrewFront);
|
||||
targetPayload->business1Left = TO_POUNDS(isImperial, targetPayload->business1Left);
|
||||
targetPayload->business1Center = TO_POUNDS(isImperial, targetPayload->business1Center);
|
||||
targetPayload->business1Right = TO_POUNDS(isImperial, targetPayload->business1Right);
|
||||
targetPayload->business2Left = TO_POUNDS(isImperial, targetPayload->business2Left);
|
||||
targetPayload->business2Center = TO_POUNDS(isImperial, targetPayload->business2Center);
|
||||
targetPayload->business2Right = TO_POUNDS(isImperial, targetPayload->business2Right);
|
||||
targetPayload->economy1Left = TO_POUNDS(isImperial, targetPayload->economy1Left);
|
||||
targetPayload->economy1Center = TO_POUNDS(isImperial, targetPayload->economy1Center);
|
||||
targetPayload->economy1Right = TO_POUNDS(isImperial, targetPayload->economy1Right);
|
||||
targetPayload->economy2Left = TO_POUNDS(isImperial, targetPayload->economy2Left);
|
||||
targetPayload->economy2Center = TO_POUNDS(isImperial, targetPayload->economy2Center);
|
||||
targetPayload->economy2Right = TO_POUNDS(isImperial, targetPayload->economy2Right);
|
||||
targetPayload->cabinCrewRear = TO_POUNDS(isImperial, targetPayload->cabinCrewRear);
|
||||
targetPayload->forwardCargo = TO_POUNDS(isImperial, targetPayload->forwardCargo);
|
||||
targetPayload->rearCargo = TO_POUNDS(isImperial, targetPayload->rearCargo);
|
||||
targetPayload->leftAux = TO_POUNDS(isImperial, targetPayload->leftAux);
|
||||
targetPayload->rightAux = TO_POUNDS(isImperial, targetPayload->rightAux);
|
||||
}
|
||||
|
||||
void calculateCGs(const paxPayloadData_t* const targetPayload, const FuelData_t* const fuel, double* const ZFWCG, double* const TOCG, const bool isImperial) {
|
||||
paxPayloadData_t localPayload = {};
|
||||
memcpy(&localPayload, targetPayload, sizeof(localPayload));
|
||||
normalisePayload(&localPayload, isImperial);
|
||||
|
||||
double totalMoment = localPayload.empty * ARM_EMPTY + localPayload.pilot * ARM_PILOT + localPayload.firstOfficer * ARM_FIRST_OFFICER +
|
||||
localPayload.engineer * ARM_ENGINEER + localPayload.cabinCrewFront * ARM_PAX_CABIN_CREW_FRONT +
|
||||
localPayload.business1Left * ARM_PAX_BUSINESS1_LEFT + localPayload.business1Center * ARM_PAX_BUSINESS1_CENTER +
|
||||
localPayload.business1Right * ARM_PAX_BUSINESS1_RIGHT + localPayload.business2Left * ARM_PAX_BUSINESS2_LEFT +
|
||||
localPayload.business2Center * ARM_PAX_BUSINESS2_CENTER + localPayload.business2Right * ARM_PAX_BUSINESS2_RIGHT +
|
||||
localPayload.economy1Left * ARM_PAX_ECONOMY1_LEFT + localPayload.economy1Center * ARM_PAX_ECONOMY1_CENTER +
|
||||
localPayload.economy1Right * ARM_PAX_ECONOMY1_RIGHT + localPayload.economy2Left * ARM_PAX_ECONOMY2_LEFT +
|
||||
localPayload.economy2Center * ARM_PAX_ECONOMY2_CENTER + localPayload.economy2Right * ARM_PAX_ECONOMY2_RIGHT +
|
||||
localPayload.cabinCrewRear * ARM_PAX_CABIN_CREW_REAR + localPayload.forwardCargo * ARM_FORWARD_CARGO +
|
||||
localPayload.rearCargo * ARM_REAR_CARGO + localPayload.leftAux * ARM_LEFT_AUX + localPayload.rightAux * ARM_RIGHT_AUX;
|
||||
|
||||
double totalWeight = localPayload.empty + localPayload.pilot + localPayload.firstOfficer + localPayload.engineer + localPayload.cabinCrewFront +
|
||||
localPayload.business1Left + localPayload.business1Center + localPayload.business1Right + localPayload.business2Left +
|
||||
localPayload.business2Center + localPayload.business2Right + localPayload.economy1Left + localPayload.economy1Center +
|
||||
localPayload.economy1Right + localPayload.economy2Left + localPayload.economy2Center + localPayload.economy2Right +
|
||||
localPayload.cabinCrewRear + localPayload.forwardCargo + localPayload.rearCargo + localPayload.leftAux + localPayload.rightAux;
|
||||
|
||||
*ZFWCG = TO_PERCENT_MAC(totalMoment / totalWeight);
|
||||
|
||||
totalMoment += fuel->main1 * ARM_MAIN1 + fuel->main3 * ARM_MAIN3 + fuel->main2 * ARM_MAIN2 + fuel->upperAux * ARM_UPPER_AUX +
|
||||
fuel->lowerAux * ARM_LOWER_AUX + fuel->main1Tip * ARM_MAIN1_TIP + fuel->main3Tip * ARM_MAIN3_TIP +
|
||||
fuel->tail * ARM_TAIL + fuel->forwardAux1 * ARM_FORWARD_AUX1 + fuel->forwardAux2 * ARM_FORWARD_AUX2;
|
||||
|
||||
totalWeight += fuel->total;
|
||||
|
||||
*TOCG = TO_PERCENT_MAC(totalMoment / totalWeight);
|
||||
}
|
||||
|
||||
void load(const paxPayloadData_t* const targetPayload, const HANDLE simConnect, const bool isImperial) {
|
||||
paxPayloadData_t localPayload = {};
|
||||
memcpy(&localPayload, targetPayload, sizeof(localPayload));
|
||||
normalisePayload(&localPayload, isImperial);
|
||||
|
||||
SimConnect_SetDataOnSimObject(simConnect, DATA_DEFINITION_PAYLOAD_PAX, SIMCONNECT_OBJECT_ID_USER, 0, 0, sizeof(paxPayloadDataSet_t), &localPayload);
|
||||
}
|
||||
|
||||
void unload(const HANDLE simConnect, const bool isER) {
|
||||
paxPayloadDataSet_t localPayload = {};
|
||||
|
||||
localPayload.cabinCrewFront = FRONT_CREW_WEIGHT(true);
|
||||
localPayload.cabinCrewRear = REAR_CREW_WEIGHT(true);
|
||||
localPayload.leftAux = localPayload.rightAux = isER ? AUX_WEIGHT(true) : 0;
|
||||
localPayload.pilot = localPayload.firstOfficer = localPayload.engineer = PILOT_WEIGHT(true);
|
||||
|
||||
SimConnect_SetDataOnSimObject(simConnect, DATA_DEFINITION_PAYLOAD_PAX, SIMCONNECT_OBJECT_ID_USER, 0, 0, sizeof(paxPayloadDataSet_t), &localPayload);
|
||||
}
|
||||
|
||||
const double PAX_WEIGHT(const bool isImperial, const UserOptions_t* const options) {
|
||||
return (isImperial) ? (options->paxWeightLBS) : (options->paxWeightKG);
|
||||
}
|
||||
|
||||
const double BAG_WEIGHT(const bool isImperial, const UserOptions_t* const options) {
|
||||
return (isImperial) ? (options->bagWeightLBS) : (options->bagWeightKG);
|
||||
}
|
||||
@@ -0,0 +1,147 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef __INTELLISENSE__
|
||||
# define MODULE_EXPORT __attribute__( ( visibility( "default" ) ) )
|
||||
# define MODULE_WASM_MODNAME(mod) __attribute__((import_module(mod)))
|
||||
#else
|
||||
# define MODULE_EXPORT
|
||||
# define MODULE_WASM_MODNAME(mod)
|
||||
# define __attribute__(x)
|
||||
# define __restrict__
|
||||
#endif
|
||||
|
||||
/********************************* Headers *********************************/
|
||||
// MSFS headers
|
||||
#include <MSFS/MSFS_WindowsTypes.h>
|
||||
#include <SimConnect.h>
|
||||
// C headers
|
||||
#include <math.h>
|
||||
// C++ headers
|
||||
#include <algorithm>
|
||||
// Own headers
|
||||
#include "shared.h"
|
||||
|
||||
/******************************** Constants ********************************/
|
||||
// 2x 190lbs default
|
||||
#define FRONT_CREW_WEIGHT(IS_IMPERIAL) ((IS_IMPERIAL) ? (380.0) : (172.0))
|
||||
// 5x 190lbs default
|
||||
#define REAR_CREW_WEIGHT(IS_IMPERIAL) ((IS_IMPERIAL) ? (950.0) : (430.0))
|
||||
// All actual Business seats
|
||||
#define MAX_BUSINESS_1 30
|
||||
// First 5 rows of economy
|
||||
#define MAX_BUSINESS_2 45
|
||||
// Next 14 rows
|
||||
#define MAX_ECONOMY_1 86
|
||||
// Remaining rows
|
||||
#define MAX_ECONOMY_2 137
|
||||
// Total
|
||||
#define MAX_PAX 298
|
||||
// Max ZFW
|
||||
#define MAX_PAX_ZFW(IS_IMPERIAL) ((IS_IMPERIAL) ? (400000) : (181437))
|
||||
// Arms
|
||||
#define ARM_PAX_CABIN_CREW_FRONT 792.0
|
||||
#define ARM_PAX_BUSINESS1_LEFT 540.0
|
||||
#define ARM_PAX_BUSINESS1_CENTER 540.0
|
||||
#define ARM_PAX_BUSINESS1_RIGHT 540.0
|
||||
#define ARM_PAX_BUSINESS2_LEFT 300.0
|
||||
#define ARM_PAX_BUSINESS2_CENTER 300.0
|
||||
#define ARM_PAX_BUSINESS2_RIGHT 300.0
|
||||
#define ARM_PAX_ECONOMY1_LEFT -240.0
|
||||
#define ARM_PAX_ECONOMY1_CENTER -240.0
|
||||
#define ARM_PAX_ECONOMY1_RIGHT -240.0
|
||||
#define ARM_PAX_ECONOMY2_LEFT -600.0
|
||||
#define ARM_PAX_ECONOMY2_CENTER -600.0
|
||||
#define ARM_PAX_ECONOMY2_RIGHT -600.0
|
||||
#define ARM_PAX_CABIN_CREW_REAR -660.0
|
||||
|
||||
/***************************** Data structures *****************************/
|
||||
typedef struct {
|
||||
// SimConnect mapped
|
||||
double pilot;
|
||||
double firstOfficer;
|
||||
double engineer;
|
||||
double cabinCrewFront;
|
||||
double business1Left;
|
||||
double business1Center;
|
||||
double business1Right;
|
||||
double business2Left;
|
||||
double business2Center;
|
||||
double business2Right;
|
||||
double economy1Left;
|
||||
double economy1Center;
|
||||
double economy1Right;
|
||||
double economy2Left;
|
||||
double economy2Center;
|
||||
double economy2Right;
|
||||
double cabinCrewRear;
|
||||
double forwardCargo;
|
||||
double rearCargo;
|
||||
double leftAux;
|
||||
double rightAux;
|
||||
|
||||
// Additional properties
|
||||
double empty;
|
||||
double total;
|
||||
double CGTarget;
|
||||
double ZFWCG;
|
||||
double TOCG;
|
||||
struct paxCount {
|
||||
unsigned char business1;
|
||||
unsigned char business2;
|
||||
unsigned char economy1;
|
||||
unsigned char economy2;
|
||||
unsigned short total;
|
||||
} paxCount;
|
||||
struct sbPlanned {
|
||||
double ZFW;
|
||||
double GW;
|
||||
unsigned short pax;
|
||||
unsigned int cargo;
|
||||
} sbPlanned;
|
||||
} paxPayloadData_t;
|
||||
|
||||
typedef struct {
|
||||
double pilot;
|
||||
double firstOfficer;
|
||||
double engineer;
|
||||
double cabinCrewFront;
|
||||
double business1Left;
|
||||
double business1Center;
|
||||
double business1Right;
|
||||
double business2Left;
|
||||
double business2Center;
|
||||
double business2Right;
|
||||
double economy1Left;
|
||||
double economy1Center;
|
||||
double economy1Right;
|
||||
double economy2Left;
|
||||
double economy2Center;
|
||||
double economy2Right;
|
||||
double cabinCrewRear;
|
||||
double forwardCargo;
|
||||
double rearCargo;
|
||||
double leftAux;
|
||||
double rightAux;
|
||||
} paxPayloadDataSet_t;
|
||||
|
||||
/******************************** Functions ********************************/
|
||||
//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 UserData_t* const userData,
|
||||
const UserOptions_t* const userOptions);
|
||||
//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 UserData_t* const userData,
|
||||
const UserOptions_t* const userOptions);
|
||||
// Updates pax stations with their respective weights
|
||||
// Used internally and used for Station Entry (pax only, cargo is ste directly)
|
||||
// STATION WEIGHTS ARE NOT NORMALISED TO POUNDS
|
||||
void generatePayload(paxPayloadData_t* const targetPayload, const bool isImperial, const UserOptions_t* const userOptions);
|
||||
// Normalise to Pounds
|
||||
// For Station Entry: CALL AFTER `generatePayload`
|
||||
void normalisePayload(paxPayloadData_t* const targetPayload, const bool isImperial);
|
||||
void calculateCGs(const paxPayloadData_t* const targetPayload, const FuelData_t* const fuel, double* const ZFWCG, double* const TOCG, const bool isImperial);
|
||||
void load(const paxPayloadData_t* const targetPayload, const HANDLE simConnect, const bool isImperial);
|
||||
void unload(const HANDLE simConnect, const bool isER);
|
||||
// Based on ICAO/LH findings
|
||||
const double PAX_WEIGHT(const bool isImperial, const UserOptions_t* const options);
|
||||
// Based on ICAO/LH findings
|
||||
const double BAG_WEIGHT(const bool isImperial, const UserOptions_t* const options);
|
||||
@@ -0,0 +1,131 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef __INTELLISENSE__
|
||||
# define MODULE_EXPORT __attribute__( ( visibility( "default" ) ) )
|
||||
# define MODULE_WASM_MODNAME(mod) __attribute__((import_module(mod)))
|
||||
#else
|
||||
# define MODULE_EXPORT
|
||||
# define MODULE_WASM_MODNAME(mod)
|
||||
# define __attribute__(x)
|
||||
# define __restrict__
|
||||
#endif
|
||||
|
||||
/******************************** Constants ********************************/
|
||||
// 190lbs default
|
||||
#define PILOT_WEIGHT(IS_IMPERIAL) ((IS_IMPERIAL) ? (190.0) : (86.0))
|
||||
// 200lbs per tank (one LD3)
|
||||
#define AUX_WEIGHT(IS_IMPERIAL) ((IS_IMPERIAL) ? (200.0) : (91.0))
|
||||
//PMC pallet due to 104in door
|
||||
#define MAX_FRONT_CARGO(IS_IMPERIAL) ((IS_IMPERIAL) ? (6.0 * 15000.0) : (6.0 * 6804.0))
|
||||
#define MAX_UPPER_CARGO(IS_IMPERIAL) ((IS_IMPERIAL) ? (6.5 * 15000.0) : (6.5 * 6804.0))
|
||||
//LD3s due to 70in door, ER option takes up two slots
|
||||
#define MAX_REAR_CARGO(IS_IMPERIAL, IS_ER) ((IS_IMPERIAL) ? ((IS_ER ? 12.0 : 14.0) * 3500.0) : ((IS_ER ? 12.0 : 14.0) * 1588.0))
|
||||
// Max TOW
|
||||
#define MAX_TOW(IS_IMPERIAL) ((IS_IMPERIAL) ? (625500) : (283722))
|
||||
#define MAX_TOW_ER(IS_IMPERIAL) ((IS_IMPERIAL) ? (630500) : (285990))
|
||||
// Max Fuel
|
||||
#define MAX_FUEL(IS_IMPERIAL) ((IS_IMPERIAL) ? (256207) : (116213))
|
||||
#define MAX_FUEL_ER(IS_IMPERIAL) ((IS_IMPERIAL) ? (282619) : (128193))
|
||||
// Arms Shared
|
||||
#define ARM_EMPTY -159.6
|
||||
#define ARM_PILOT 984.0
|
||||
#define ARM_FIRST_OFFICER 984.0
|
||||
#define ARM_ENGINEER 960.0
|
||||
#define ARM_FORWARD_CARGO 360.0
|
||||
#define ARM_REAR_CARGO -360.0
|
||||
#define ARM_LEFT_AUX 60.0
|
||||
#define ARM_RIGHT_AUX 60.0
|
||||
// Arms Fuel
|
||||
#define ARM_MAIN1 -240.0
|
||||
#define ARM_MAIN3 -240.0
|
||||
#define ARM_MAIN2 120.0
|
||||
#define ARM_UPPER_AUX 0.0
|
||||
#define ARM_LOWER_AUX 0.0
|
||||
#define ARM_MAIN1_TIP -468.0
|
||||
#define ARM_MAIN3_TIP -468.0
|
||||
#define ARM_TAIL -840.0
|
||||
#define ARM_FORWARD_AUX1 60.0
|
||||
#define ARM_FORWARD_AUX2 60.0
|
||||
// MAC
|
||||
#define ROOT_CHORD 34.68
|
||||
#define WING_SPAN 170.5
|
||||
#define WING_AREA 3648.0
|
||||
#define QUARTER_MAC -165.0 //aero_center
|
||||
#define TIP_CHORD ((2.0 * WING_AREA) / WING_SPAN - ROOT_CHORD)
|
||||
#define TAPER_RATIO (TIP_CHORD / ROOT_CHORD)
|
||||
#define MAC ((2.0 / 3.0) * ROOT_CHORD * ((1.0 + TAPER_RATIO + (TAPER_RATIO * TAPER_RATIO)) / (1.0 + TAPER_RATIO)) * 12.0)
|
||||
#define LEMAC (QUARTER_MAC + (1.0 / 4.0) * MAC)
|
||||
// CG Limits
|
||||
#define MIN_CG 12.0
|
||||
#define MAX_CG 34.0
|
||||
#define CG_TOLERANCE 0.05
|
||||
// GSX States
|
||||
#define GSX_SERVICE_ACTIVE 5
|
||||
|
||||
/********************************* Macros **********************************/
|
||||
// Conversions
|
||||
#define TO_POUNDS(IS_IMPERIAL, VALUE) ((IS_IMPERIAL) ? (VALUE) : (VALUE) * 2.20462262185)
|
||||
#define FROM_POUNDS(IS_IMPERIAL, VALUE) ((IS_IMPERIAL) ? (VALUE) : (VALUE) * (1.0 / 2.20462262185))
|
||||
// MAC
|
||||
#define TO_PERCENT_MAC(POS) ((((POS) - LEMAC) / MAC) * -100.0)
|
||||
|
||||
/********************************** ENUMS **********************************/
|
||||
enum DATA_DEFINITIONS {
|
||||
DATA_DEFINITION_EMPTY_WEIGHT,
|
||||
DATA_DEFINITION_PAYLOAD_PAX,
|
||||
DATA_DEFINITION_PAYLOAD_F,
|
||||
DATA_DEFINITION_FUEL,
|
||||
DATA_DEFINITION_GSX,
|
||||
DATA_DEFINITION_USER_DATA,
|
||||
};
|
||||
|
||||
enum DATA_REQUESTS {
|
||||
DATA_REQUEST_EMPTY_WEIGHT,
|
||||
DATA_REQUEST_PAYLOAD_PAX,
|
||||
DATA_REQUEST_PAYLOAD_F,
|
||||
DATA_REQUEST_FUEL,
|
||||
DATA_REQUEST_GSX,
|
||||
DATA_REQUEST_USER_DATA,
|
||||
};
|
||||
|
||||
/***************************** Data structures *****************************/
|
||||
typedef struct {
|
||||
double isCargo;
|
||||
double isER;
|
||||
double isImperial;
|
||||
} UserData_t;
|
||||
|
||||
typedef struct {
|
||||
double boardingState; // See manual, 5 => active
|
||||
double deboardingState; // See manual, 5 => active
|
||||
double passengersBoarded; // Num pax
|
||||
double passengersDeboarded; // Num pax
|
||||
double cargoBoarded; // In percent
|
||||
double cargoDeboarded; // In percent
|
||||
} GSXData_t;
|
||||
|
||||
typedef struct {
|
||||
// SimConnect mapped
|
||||
double poundsPerGallon; // DO NOT USE
|
||||
double main1;
|
||||
double main3;
|
||||
double main2;
|
||||
double upperAux;
|
||||
double lowerAux;
|
||||
double main1Tip;
|
||||
double main3Tip;
|
||||
double tail;
|
||||
double forwardAux1;
|
||||
double forwardAux2;
|
||||
|
||||
// Additional properties
|
||||
double total;
|
||||
} FuelData_t;
|
||||
|
||||
typedef struct {
|
||||
bool GSXSync;
|
||||
double paxWeightKG;
|
||||
double bagWeightKG;
|
||||
double paxWeightLBS;
|
||||
double bagWeightLBS;
|
||||
} UserOptions_t;
|
||||
@@ -1,6 +1,21 @@
|
||||
# How to build
|
||||
|
||||
Build WASM module from VS
|
||||
`pnpm build` from `js-bundle`
|
||||
Build in sim
|
||||
|
||||
# Sources
|
||||
|
||||
- https://www.boeing.com/content/dam/boeing/boeingdotcom/company/about_bca/startup/pdf/freighters/MD11BCF.pdf
|
||||
- LAMM
|
||||
- https://www.satco-inc.com/product-pallet/?part_number=31086-595
|
||||
- https://www.satco-inc.com/product-container/?part_number=34124-901
|
||||
- https://www.satco-inc.com/product-container/?part_number=34124-901
|
||||
|
||||
TODO:
|
||||
|
||||
- EFB integration (BRANCH)
|
||||
- Check if including bundle is getting loaded
|
||||
- Add to bundle global scoped react "import"
|
||||
- Automate this?
|
||||
- Add to EFB.js and EFB.html
|
||||
- Automate this?
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
Copy-Item .\PackageSources\wasm-module\MSFS\Debug\load-manager.wasm .\PackageSources\SimObjects\Airplanes\TFDi_Design_MD-11_GE\panel
|
||||
Copy-Item .\PackageSources\wasm-module\MSFS\Debug\load-manager.wasm .\PackageSources\SimObjects\Airplanes\TFDi_Design_MD-11_PW\panel
|
||||
Copy-Item .\PackageSources\wasm-module\MSFS\Debug\load-manager.wasm .\PackageSources\SimObjects\Airplanes\TFDi_Design_MD-11F_GE\panel
|
||||
Copy-Item .\PackageSources\wasm-module\MSFS\Debug\load-manager.wasm .\PackageSources\SimObjects\Airplanes\TFDi_Design_MD-11F_PW\panel
|
||||
@@ -0,0 +1,4 @@
|
||||
Copy-Item .\PackageSources\wasm-module\MSFS\Release\load-manager.wasm .\PackageSources\SimObjects\Airplanes\TFDi_Design_MD-11_GE\panel
|
||||
Copy-Item .\PackageSources\wasm-module\MSFS\Release\load-manager.wasm .\PackageSources\SimObjects\Airplanes\TFDi_Design_MD-11_PW\panel
|
||||
Copy-Item .\PackageSources\wasm-module\MSFS\Release\load-manager.wasm .\PackageSources\SimObjects\Airplanes\TFDi_Design_MD-11F_GE\panel
|
||||
Copy-Item .\PackageSources\wasm-module\MSFS\Release\load-manager.wasm .\PackageSources\SimObjects\Airplanes\TFDi_Design_MD-11F_PW\panel
|
||||
@@ -1,8 +1,10 @@
|
||||
{
|
||||
"folders": [
|
||||
{
|
||||
"path": "."
|
||||
}
|
||||
],
|
||||
"settings": {}
|
||||
}
|
||||
"folders": [
|
||||
{
|
||||
"path": "."
|
||||
}
|
||||
],
|
||||
"settings": {
|
||||
"cSpell.words": ["deboarding", "khofmann", "tfdi", "TFDI", "TOCG", "ZFWCG"]
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user