Compare commits

...

2 Commits

Author SHA1 Message Date
52ea904ad6 Initial SVG 2025-06-09 06:31:32 +02:00
ea788bdd04 Getting station data 2025-06-09 06:00:14 +02:00
23 changed files with 932 additions and 7104 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 475 KiB

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,19 @@
Mains y: 457,626
Mains X:
344,088 + (1126,566 - 344,088) / 2
1126,566 + (1910,904 - 1126,566) / 2
1910,904 + (2693,220 - 1910,904) / 2
2693,220 + (3477,993 - 2693,220) / 2
Lower y: 623,816
Lower Y:
679,888 + (1734,862 - 679,888) / 2
2392,429 + (3409,288 - 2392,429) / 2

View File

@ -0,0 +1,136 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="4000"
height="777"
viewBox="0 0 4000 777"
version="1.1"
id="svg1"
xml:space="preserve"
sodipodi:docname="MD11_Profile.svg"
inkscape:export-xdpi="96"
inkscape:export-ydpi="96"
inkscape:version="1.3.2 (091e20e, 2023-11-25, custom)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"><sodipodi:namedview
id="namedview2"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
showgrid="false"
inkscape:zoom="0.68589358"
inkscape:cx="1406.1948"
inkscape:cy="543.08717"
inkscape:window-width="1920"
inkscape:window-height="1009"
inkscape:window-x="-8"
inkscape:window-y="-8"
inkscape:window-maximized="1"
inkscape:current-layer="svg1" /><defs
id="defs1" />
<g
id="layer1"
transform="matrix(1.0068517,0,0,1.0069072,-24.265193,-12.003831)"><path
style="fill:none;stroke:#000000;stroke-width:2;stroke-dasharray:none;stroke-opacity:1"
d="M 680.84609,782.08906 C 549.70893,776.57617 458.39197,765.86739 324.268,740.27364 246.14504,725.36614 162.88028,702.65084 114.71005,683.10491 64.294422,662.64808 29.662286,634.19107 25.770394,610.02401 c -3.768309,-23.39909 7.45579,-38.27601 50.497871,-66.9322 6.041267,-4.02167 12.708198,-9.25866 14.816502,-11.63777 2.108011,-2.3791 4.524337,-4.47417 4.524337,-4.47417 0,0 45.054846,-44.16802 69.744156,-58.51947 72.48238,-42.13286 238.75805,-76.34072 425.62931,-87.56471 14.00364,-0.84087 33.99811,-2.06795 44.43237,-2.72604 26.21714,-1.65429 1973.23226,-2.44974 2062.35136,-0.84335 156.7308,2.8263 269.4991,7.73127 530.5484,23.07714 47.1492,2.77159 85.8529,4.90003 86.0115,4.72947 0.6463,-0.69343 3.1799,-46.29263 2.6116,-46.94111 -0.3392,-0.38556 -8.4798,-1.62861 -18.0916,-2.7617 -35.342,-4.16857 -67.3987,-11.80933 -77.0775,-18.373 -3.9158,-2.65461 -3.9645,-3.9457 -1.9416,-51.05288 2.108,-49.09699 3.1187,-81.38198 3.1285,-99.87491 0,-21.74527 -0.1657,-21.35031 11.1205,-24.91522 37.4056,-11.81592 117.8805,-11.055 171.1113,1.6182 15.227,3.62513 19.5889,3.51038 35.537,-0.93493 21.7,-6.04964 21.06,-5.5085 96.6369,-81.945831 C 3570.4998,46.436494 3606.118,14 3606.118,14 c 0,0 83.3791,-1.078541 169.2378,-1.078541 136.9775,0 171.6157,0.25301 171.2171,1.248541 -4.4107,10.98979 -56.581,125.3361 -58.6915,128.64097 -4.61,7.2154 -3.2138,7.87286 16.7587,7.89172 9.0621,0.008 22.5342,1.10149 37.2287,3.01945 4.1187,0.5379 15.3535,1.65128 24.9605,2.47427 9.6121,0.82315 19.8324,1.75527 22.7174,2.07148 5.068,0.5564 9.0513,198.14866 3.9933,198.1233 -3.6048,-0.0227 -31.7006,3.23162 -34.6989,4.01342 -1.9198,0.50096 -6.9751,1.19108 -11.2311,1.53277 -7.7386,0.62134 -7.7386,0.62134 -7.7386,8.40744 0,8.9212 0.045,8.96677 9.985,9.01912 7.5949,0.034 9.8123,1.6324 3.4137,2.45002 -2.7018,0.34529 -6.0356,0.83128 -7.4075,1.08125 -1.3721,0.24985 -13.4623,0.8929 -26.8656,1.4305 -13.401,0.53782 -28.9024,1.43993 -34.4461,2.0055 -15.6071,1.5929 -41.7206,3.00651 -55.6343,3.01162 -20.6343,0.008 -19.0304,-1.48657 -18.6619,17.39371 0.3714,18.99365 2.3135,23.83102 11.5516,28.75828 5.5848,2.97987 0.3035,2.54463 88.3394,7.28049 84.7137,4.55708 75.1577,-2.80725 75.1577,57.90224 0,54.0198 0.038,53.89862 -18.7911,59.76707 -20.408,6.36127 -118.4491,34.26355 -182.9035,52.0539 -74.4101,20.53866 -152.6313,42.46259 -160.2532,44.9152 -10.5871,3.40625 -57.116,16.36682 -105.4328,29.36671 -184.6218,49.67348 -402.045,89.66531 -516.1192,94.93296 -19.1653,0.88463 -2300.05965,1.25451 -2320.95791,0.37647 z M 2395.2284,766.17343 c 14.31,-1.72636 35.0044,-5.58482 45.9317,-8.56349 47.3731,-12.91382 34.3569,-20.54665 -70.3937,-41.28467 -9.3343,-1.84814 -21.9155,-4.52456 -27.9567,-5.94725 -119.2237,-28.08138 -135.9351,-31.12662 -227.3855,-41.43261 -32.4777,-3.66009 -84.0044,-11.38065 -126.5741,-18.96537 -77.5998,-13.826 -129.5464,-21.92668 -156.7612,-24.44667 -178.2006,-16.50013 -260.2484,38.63673 -109.1218,73.33233 7.2585,1.66581 18.9421,5.28886 25.9627,8.05145 39.3006,15.46148 111.0206,26.31652 233.4285,35.33072 97.5086,7.18033 247.1863,10.12384 247.9332,4.8756 0.6641,-4.65753 1.511,-4.79372 36.7152,-5.87802 22.9807,-0.70754 26.3782,-0.21453 26.3782,3.83336 0,2.58433 2.9594,14.00646 3.8761,14.95714 0.4007,0.41397 15.6685,2.27546 33.9287,4.13576 18.2638,1.86026 33.4271,3.60433 33.6979,3.87551 0.7657,0.76535 16.5437,-0.20885 30.3408,-1.87379 z"
id="path1" /><path
id="path3"
style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
d="m 699.36138,622.53287 -5e-5,160.30077 z m 1047.79482,83.25424 v 76.82812 z"
sodipodi:nodetypes="cccccc" /><path
id="path5"
style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:2, 2;stroke-dashoffset:0;stroke-opacity:1"
d="m 1747.1562,623.05078 v 83.23047 z m 653.1368,99.8086 v 43.08593 z" /><path
id="path6"
style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
d="m 3410.1876,600.50195 -1e-4,113.16993 z m -1009.9392,22.51172 0,99.26367 z m -4e-4,142.40625 v 17.8418 z"
sodipodi:nodetypes="ccccccccc" /><path
id="path8"
style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
d="M 1922.0002,622.875 V 376.62305 Z m -779.0005,-245.79297 3e-4,246.25 z m 1555.9925,1.08399 3e-4,245.38671 0.01,-245.38671 z M 118.5,505.71875 V 684.5625 Z" /><path
style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
d="m 365.87135,407.31939 -0.0248,215.69515 1275.64058,-4.1e-4 h 1275.1884 l 132.9514,-2.4633 132.9514,-2.46329 147.9234,-11.43029 147.9234,-11.43029 1.0236,-90.7622 1.0235,-90.7622 -83.301,-4.34855 -83.301,-4.34856"
id="path2"
sodipodi:nodetypes="cccccccccccc" /><path
style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
d="m 118.53125,572 h 128.07224 v 29.04076 h 119.14749"
id="path10" /></g><text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:176px;line-height:1.25;font-family:sans-serif;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none"
x="725.61609"
y="591.34473"
id="text5"
inkscape:label="upper1"><tspan
sodipodi:role="line"
id="tspan5"
x="725.61609"
y="591.34473"
>999/999</tspan></text><text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:176px;line-height:1.25;font-family:sans-serif;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none"
x="1509.024"
y="591.34473"
id="text5-5"
inkscape:label="upper1"><tspan
sodipodi:role="line"
id="tspan5-8"
x="1509.024"
y="591.34473"
>999/999</tspan></text><text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:176px;line-height:1.25;font-family:sans-serif;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none"
x="2292.3511"
y="591.34473"
id="text5-6"
inkscape:label="upper1"><tspan
sodipodi:role="line"
id="tspan5-7"
x="2292.3511"
y="591.34473"
>999/999</tspan></text><text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:176px;line-height:1.25;font-family:sans-serif;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none"
x="3075.8955"
y="591.34473"
id="upper4"
inkscape:label="upper4"><tspan
sodipodi:role="line"
id="tspan5-0"
x="3075.8955"
y="591.34473"
>999/999</tspan></text><text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:176px;line-height:1.25;font-family:sans-serif;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none"
x="1197.6641"
y="754.35504"
id="upper4-2"
inkscape:label="lower1"><tspan
sodipodi:role="line"
id="tspan5-0-0"
x="1197.6641"
y="754.35504"
>99999</tspan></text><text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:176px;line-height:1.25;font-family:sans-serif;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none"
x="2891.1475"
y="754.35504"
id="upper4-1"
inkscape:label="upper4"><tspan
sodipodi:role="line"
id="tspan5-0-03"
x="2891.1475"
y="754.35504"
>99999</tspan></text></svg>

After

Width:  |  Height:  |  Size: 8.8 KiB

View File

@ -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" />

View File

@ -1,6 +1,6 @@
{
"name": "tfdidesign-md11-load-manager",
"version": "0.1.0",
"version": "0.1.1",
"description": "",
"main": "index.js",
"type": "module",
@ -23,15 +23,15 @@
"license": "ISC",
"devDependencies": {
"@microsoft/msfs-types": "^1.14.6",
"@rollup/plugin-commonjs": "^25.0.0",
"@rollup/plugin-commonjs": "^28.0.3",
"@rollup/plugin-json": "^6.0.0",
"@rollup/plugin-node-resolve": "^15.1.0",
"@rollup/plugin-node-resolve": "^16.0.1",
"@rollup/plugin-replace": "^6.0.2",
"@rollup/plugin-terser": "^0.4.3",
"@rollup/plugin-typescript": "^11.1.1",
"@types/react": "^18.2.8",
"@types/react-dom": "^18.2.4",
"@types/uuid": "^9.0.7",
"@rollup/plugin-typescript": "^12.1.2",
"@types/react": "^19.1.6",
"@types/react-dom": "^19.1.5",
"@types/uuid": "^10.0.0",
"@typescript-eslint/eslint-plugin": "^6.10.0",
"@typescript-eslint/parser": "^6.10.0",
"autoprefixer": "^10.4.14",
@ -42,9 +42,10 @@
"eslint-plugin-react-hooks": "^4.6.0",
"license-report": "^6.5.0",
"postcss": "^8.4.24",
"postcss-import": "^16.1.0",
"prettier": "^3.0.3",
"prettier-plugin-organize-imports": "^3.2.4",
"rimraf": "^5.0.1",
"prettier-plugin-organize-imports": "^4.1.0",
"rimraf": "^6.0.1",
"rollup": "^4.3.1",
"rollup-plugin-copy": "^3.4.0",
"rollup-plugin-postcss": "^4.0.2",
@ -53,18 +54,13 @@
"sass": "^1.89.1",
"svg-slim": "^2.0.5",
"tslib": "^2.5.3",
"typed-scss-modules": "^7.1.0",
"typescript": "5.2.2"
"typed-scss-modules": "^8.1.1",
"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"
}

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,7 @@
import ThemeProvider from '@mui/material/styles/ThemeProvider';
import { FC, StrictMode } from 'react';
import { FC, StrictMode, useEffect, useRef, useState } from 'react';
import styles from './App.module.scss';
import Freight from './components/freight/Freight';
import Pax from './components/pax/Pax';
import { ArmsFreight, PayloadFreight } from './configs/freighter';
import { ArmsPax, PayloadPax } from './configs/pax';
import { ArmsFuel, EmptyArm, Fuel, toPercentMAC } from './configs/shared';
@ -9,26 +10,74 @@ interface IAppProps {
dataListener: ViewListener.ViewListener;
}
interface PayloadFreight {
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;
}
interface PayloadPax {
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;
}
interface Fuel {
main1: number;
main3: number;
main2: number;
upperAux: number;
lowerAux: number;
main1Tip: number;
main3Tip: number;
tail: number;
forwardAux1: number;
forwardAux2: number;
}
const App: FC<IAppProps> = () => {
// TODO: Get from EFB settings
const [unit, setUnit] = useState<'lbs' | 'kg'>('lbs');
// TODO: Look into EFB, infer the same way
const [aircraft, setAircraft] = useState<'f' | 'pax'>('f');
const [payload, setPayload] = useState<PayloadPax | PayloadFreight>();
const [fuel, setFuel] = useState<Fuel>();
const [ZFWCG, setZFWCG] = useState(0);
const [TOCG, setTOCG] = useState(0);
const requestRef = useRef<number | undefined>(undefined);
const mainLoop = () => {
try {
if (SimVar.IsReady()) {
const conversion = SimVar.GetSimVarValue('FUEL WEIGHT PER GALLON', unit);
const emptyWeight = SimVar.GetSimVarValue('EMPTY WEIGHT', unit);
const payload: PayloadPax | PayloadFreight = {
setPayload({
pilot: SimVar.GetSimVarValue('PAYLOAD STATION WEIGHT:1', unit),
firstOfficer: SimVar.GetSimVarValue('PAYLOAD STATION WEIGHT:2', unit),
engineer: SimVar.GetSimVarValue('PAYLOAD STATION WEIGHT:3', unit),
@ -62,9 +111,9 @@ const App: FC<IAppProps> = () => {
rearCargo: SimVar.GetSimVarValue('PAYLOAD STATION WEIGHT:19', unit),
leftAuxPax: SimVar.GetSimVarValue('PAYLOAD STATION WEIGHT:20', unit),
rightAuxPax: SimVar.GetSimVarValue('PAYLOAD STATION WEIGHT:21', unit),
};
});
const fuel = {
setFuel({
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,
@ -75,35 +124,7 @@ const App: FC<IAppProps> = () => {
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,
};
let totalMoment = EmptyArm * emptyWeight;
let totalWeight = emptyWeight;
const arms = aircraft === 'f' ? ArmsFreight : ArmsPax;
for (const key in arms) {
if (Object.prototype.hasOwnProperty.call(payload, key)) {
const stationWeight = payload[key as keyof (PayloadFreight | PayloadPax)];
const arm = arms[key as keyof typeof arms];
totalWeight += stationWeight;
totalMoment += arm * stationWeight;
}
}
setZFWCG(toPercentMAC(totalMoment / totalWeight));
for (const key in ArmsFuel) {
if (Object.prototype.hasOwnProperty.call(fuel, key)) {
const stationWeight = fuel[key as keyof Fuel];
const arm = ArmsFuel[key as keyof typeof ArmsFuel];
totalWeight += stationWeight;
totalMoment += arm * stationWeight;
}
}
setTOCG(toPercentMAC(totalMoment / totalWeight));
setPayload(payload);
setFuel(fuel);
});
}
} catch {}
@ -116,6 +137,14 @@ const App: FC<IAppProps> = () => {
if (requestRef.current !== undefined) return () => cancelAnimationFrame(requestRef.current as number);
}, [unit, aircraft]);
//DEBUG
useEffect(() => {
console.log('Payload', payload);
console.log('Fuel', fuel);
console.log('ZFWCG', ZFWCG);
console.log('TOCG', TOCG);
}, [ZFWCG, TOCG]);
return (
<StrictMode>
<div className={styles.app}>
@ -123,16 +152,7 @@ const App: FC<IAppProps> = () => {
<button onClick={() => (aircraft === 'f' ? setAircraft('pax') : setAircraft('f'))}>
Change aircraft from {aircraft}
</button>
<div style={{ display: 'flex' }}>
<div>
<pre>{JSON.stringify(payload, null, 2)}</pre>
<strong>ZFWCG: {ZFWCG}</strong>
</div>
<div>
<pre>{JSON.stringify(fuel, null, 2)}</pre>
<strong>TOCG: {TOCG}</strong>
</div>
</div>
{aircraft === 'f' ? <Freight /> : <Pax unit={unit} payload={payload as PayloadPax} />}
</div>
</StrictMode>
);

View File

@ -0,0 +1,9 @@
const Freight = () => {
return (
<div>
<img src="assets/img/MD11_Profile.svg" style={{ width: '100%' }} />
</div>
);
};
export default Freight;

View File

@ -0,0 +1,52 @@
import { FC } from 'react';
import {
maxBusiness1StationCount,
maxBusiness2StationCount,
maxEconomy1StationCount,
maxEconomy2StationCount,
paxWeight,
PayloadPax,
} from '../../configs/pax';
import Profile from '../profile/Profile';
interface PaxProps {
unit: 'kg' | 'lbs';
payload: PayloadPax;
}
const Pax: FC<PaxProps> = ({ unit, payload }) => {
const upper1 = () => {
return Math.round((payload.business1Left + payload.business1Center + payload.business1Right) / paxWeight[unit]);
};
const upper2 = () => {
return Math.round((payload.business2Left + payload.business2Center + payload.business2Right) / paxWeight[unit]);
};
const upper3 = () => {
return Math.round((payload.economy1Left + payload.economy1Center + payload.economy1Right) / paxWeight[unit]);
};
const upper4 = () => {
return Math.round((payload.economy2Left + payload.economy2Center + payload.economy2Right) / paxWeight[unit]);
};
const lower1 = () => {
return Math.round(payload.forwardCargo);
};
const lower2 = () => {
return Math.round(payload.rearCargo);
};
return (
<div style={{ position: 'relative' }}>
<Profile
upper1={`${upper1()}/${maxBusiness1StationCount}`}
upper2={`${upper2()}/${maxBusiness2StationCount}`}
upper3={`${upper3()}/${maxEconomy1StationCount}`}
upper4={`${upper4()}/${maxEconomy2StationCount}`}
lower1={`${lower1()}`}
lower2={`${lower2()}`}
/>
</div>
);
};
export default Pax;

View File

@ -0,0 +1,84 @@
import { FC } from 'react';
interface ProfileProps {
upper1: string;
upper2: string;
upper3: string;
upper4: string;
lower1: string;
lower2: string;
}
const Profile: FC<ProfileProps> = ({ upper1, upper2, upper3, upper4, lower1, lower2 }) => {
return (
<svg
width="4000"
height="777"
viewBox="0 0 4000 777"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
style={{ width: '100%', height: '100%' }}
>
<g transform="matrix(1.0068517,0,0,1.0069072,-24.265193,-12.003831)">
<path
style={{ fill: 'none', stroke: '#000000', strokeWidth: 2 }}
d="M 680.84609,782.08906 C 549.70893,776.57617 458.39197,765.86739 324.268,740.27364 246.14504,725.36614 162.88028,702.65084 114.71005,683.10491 64.294422,662.64808 29.662286,634.19107 25.770394,610.02401 c -3.768309,-23.39909 7.45579,-38.27601 50.497871,-66.9322 6.041267,-4.02167 12.708198,-9.25866 14.816502,-11.63777 2.108011,-2.3791 4.524337,-4.47417 4.524337,-4.47417 0,0 45.054846,-44.16802 69.744156,-58.51947 72.48238,-42.13286 238.75805,-76.34072 425.62931,-87.56471 14.00364,-0.84087 33.99811,-2.06795 44.43237,-2.72604 26.21714,-1.65429 1973.23226,-2.44974 2062.35136,-0.84335 156.7308,2.8263 269.4991,7.73127 530.5484,23.07714 47.1492,2.77159 85.8529,4.90003 86.0115,4.72947 0.6463,-0.69343 3.1799,-46.29263 2.6116,-46.94111 -0.3392,-0.38556 -8.4798,-1.62861 -18.0916,-2.7617 -35.342,-4.16857 -67.3987,-11.80933 -77.0775,-18.373 -3.9158,-2.65461 -3.9645,-3.9457 -1.9416,-51.05288 2.108,-49.09699 3.1187,-81.38198 3.1285,-99.87491 0,-21.74527 -0.1657,-21.35031 11.1205,-24.91522 37.4056,-11.81592 117.8805,-11.055 171.1113,1.6182 15.227,3.62513 19.5889,3.51038 35.537,-0.93493 21.7,-6.04964 21.06,-5.5085 96.6369,-81.945831 C 3570.4998,46.436494 3606.118,14 3606.118,14 c 0,0 83.3791,-1.078541 169.2378,-1.078541 136.9775,0 171.6157,0.25301 171.2171,1.248541 -4.4107,10.98979 -56.581,125.3361 -58.6915,128.64097 -4.61,7.2154 -3.2138,7.87286 16.7587,7.89172 9.0621,0.008 22.5342,1.10149 37.2287,3.01945 4.1187,0.5379 15.3535,1.65128 24.9605,2.47427 9.6121,0.82315 19.8324,1.75527 22.7174,2.07148 5.068,0.5564 9.0513,198.14866 3.9933,198.1233 -3.6048,-0.0227 -31.7006,3.23162 -34.6989,4.01342 -1.9198,0.50096 -6.9751,1.19108 -11.2311,1.53277 -7.7386,0.62134 -7.7386,0.62134 -7.7386,8.40744 0,8.9212 0.045,8.96677 9.985,9.01912 7.5949,0.034 9.8123,1.6324 3.4137,2.45002 -2.7018,0.34529 -6.0356,0.83128 -7.4075,1.08125 -1.3721,0.24985 -13.4623,0.8929 -26.8656,1.4305 -13.401,0.53782 -28.9024,1.43993 -34.4461,2.0055 -15.6071,1.5929 -41.7206,3.00651 -55.6343,3.01162 -20.6343,0.008 -19.0304,-1.48657 -18.6619,17.39371 0.3714,18.99365 2.3135,23.83102 11.5516,28.75828 5.5848,2.97987 0.3035,2.54463 88.3394,7.28049 84.7137,4.55708 75.1577,-2.80725 75.1577,57.90224 0,54.0198 0.038,53.89862 -18.7911,59.76707 -20.408,6.36127 -118.4491,34.26355 -182.9035,52.0539 -74.4101,20.53866 -152.6313,42.46259 -160.2532,44.9152 -10.5871,3.40625 -57.116,16.36682 -105.4328,29.36671 -184.6218,49.67348 -402.045,89.66531 -516.1192,94.93296 -19.1653,0.88463 -2300.05965,1.25451 -2320.95791,0.37647 z M 2395.2284,766.17343 c 14.31,-1.72636 35.0044,-5.58482 45.9317,-8.56349 47.3731,-12.91382 34.3569,-20.54665 -70.3937,-41.28467 -9.3343,-1.84814 -21.9155,-4.52456 -27.9567,-5.94725 -119.2237,-28.08138 -135.9351,-31.12662 -227.3855,-41.43261 -32.4777,-3.66009 -84.0044,-11.38065 -126.5741,-18.96537 -77.5998,-13.826 -129.5464,-21.92668 -156.7612,-24.44667 -178.2006,-16.50013 -260.2484,38.63673 -109.1218,73.33233 7.2585,1.66581 18.9421,5.28886 25.9627,8.05145 39.3006,15.46148 111.0206,26.31652 233.4285,35.33072 97.5086,7.18033 247.1863,10.12384 247.9332,4.8756 0.6641,-4.65753 1.511,-4.79372 36.7152,-5.87802 22.9807,-0.70754 26.3782,-0.21453 26.3782,3.83336 0,2.58433 2.9594,14.00646 3.8761,14.95714 0.4007,0.41397 15.6685,2.27546 33.9287,4.13576 18.2638,1.86026 33.4271,3.60433 33.6979,3.87551 0.7657,0.76535 16.5437,-0.20885 30.3408,-1.87379 z"
/>
<path
style={{ fill: 'none', stroke: '#000000', strokeWidth: 2, strokeLinecap: 'butt', strokeLinejoin: 'miter' }}
d="m 699.36133,622.5332 v 160.30078 z m 1047.79487,83.25391 -0.023,76.82812 z"
/>
<path
style={{
fill: 'none',
stroke: '#000000',
strokeWidth: 2,
strokeLinecap: 'butt',
strokeLinejoin: 'miter',
strokeDasharray: '2, 2',
strokeDashoffset: 0,
}}
d="m 1747.1562,623.05078 v 83.23047 z m 653.1368,99.8086 v 43.08593 z"
/>
<path
style={{ fill: 'none', stroke: '#000000', strokeWidth: 2, strokeLinecap: 'butt', strokeLinejoin: 'miter' }}
d="M 3410.1875,600.50195 V 713.67188 Z M 2400.248,623.01367 v 99.26367 z m 0,142.40625 v 17.8418 z"
/>
<path
style={{ fill: 'none', stroke: '#000000', strokeWidth: 2, strokeLinecap: 'butt', strokeLinejoin: 'miter' }}
d="M 1921,376.62305 V 622.875 l 1,-246.25195 z m -778,0.45898 v 246.25 z m 1555.9922,1.08399 v 245.38671 l 0.01,-245.38671 z M 118.5,505.71875 V 684.5625 Z"
/>
<path
style={{ fill: 'none', stroke: '#000000', strokeWidth: 2, strokeLinecap: 'butt', strokeLinejoin: 'round' }}
d="m 365.87116,407.31944 -0.0244,215.69469 H 1641.4871 2916.6755 l 132.9514,-2.4633 132.9514,-2.46329 147.9234,-11.43029 147.9235,-11.43029 1.0235,-90.7622 1.0235,-90.7622 -83.301,-4.34855 -83.301,-4.34856"
/>
<path
style={{ fill: 'none', stroke: '#000000', strokeWidth: 2, strokeLinecap: 'butt', strokeLinejoin: 'round' }}
d="m 118.53125,572 h 128.07224 v 29.04076 h 119.14749"
/>
</g>
<text style={{ fill: '#000000', fontSize: '160px' }} x="725.61609" y="591.34473" textAnchor="middle" id="upper1">
{upper1}
</text>
<text style={{ fill: '#000000', fontSize: '160px' }} x="1509.024" y="591.34473" textAnchor="middle" id="upper2">
{upper2}
</text>
<text style={{ fill: '#000000', fontSize: '160px' }} x="2292.3511" y="591.34473" textAnchor="middle" id="upper3">
{upper3}
</text>
<text style={{ fill: '#000000', fontSize: '160px' }} x="3075.8955" y="591.34473" textAnchor="middle" id="upper4">
{upper4}
</text>
<text style={{ fill: '#000000', fontSize: '160px' }} x="1197.6641" y="754.35504" textAnchor="middle" id="lower1">
{lower1}
</text>
<text style={{ fill: '#000000', fontSize: '160px' }} x="2891.1475" y="754.35504" textAnchor="middle" id="lower2">
{lower2}
</text>
</svg>
);
};
export default Profile;

View File

@ -33,4 +33,21 @@ export const ArmsFreight = {
lowerRear: -360,
leftAuxF: 60,
rightAuxF: 60,
}
};
//PMC pallet
export const maxUpperStationWeight = {
kg: (26 / 8) * 6804,
lbs: (26 / 8) * 15000,
};
export const baseWeightFreight = {
pilot: {
lbs: 190,
kg: 86,
},
firstOfficer: {
lbs: 190,
kg: 86,
},
};

View File

@ -23,27 +23,60 @@ export interface PayloadPax {
}
// TODO: Extract from CFG at runtime.
// FIXME: Copy over values
export const ArmsPax = {
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,
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
export const paxWeight = {
kg: 86,
lbs: 190,
};
export const maxBusiness1StationCount = 30; // all Business rows
export const maxBusiness2StationCount = 45; // first 5 "Economy" as "Premium Economy"
export const maxEconomy1StationCount = 86; // up to and including the 5 seat Economy row
export const maxEconomy2StationCount = 137; // rest of Economy rows
export const baseWeightPax = {
pilot: {
lbs: 190,
kg: 86,
},
firstOfficer: {
lbs: 190,
kg: 86,
},
engineer: {
lbs: 190,
kg: 86,
},
cabinCrewFront: {
lbs: 380,
kg: 172,
},
cabinCrewRear: {
lbs: 950,
kg: 430,
},
};

View File

@ -43,3 +43,15 @@ const LEMAC = quarterMAC + (1 / 4) * MAC;
export const toPercentMAC = (positionInInches: number) => {
return Math.abs(((positionInInches - LEMAC) / MAC) * 100);
};
//PMC pallet due to 104in door
export const maxForwardLowerStationWeight = {
kg: 6 * 6804,
lbs: 6 * 15000,
};
//LD3s due to 70in door
export const maxRearLowerStationWeight = {
kg: 14 * 1588,
lbs: 14 * 3500,
};

View File

@ -31,9 +31,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>

View File

@ -3,8 +3,6 @@ import { createRoot } from 'react-dom/client';
import App from './App';
class TFDiDesignMD11LoadManagerPanel extends TemplateElement {
dataListener?: ViewListener.ViewListener;
constructor() {
super();
}
@ -12,12 +10,11 @@ class TFDiDesignMD11LoadManagerPanel extends TemplateElement {
connectedCallback() {
super.connectedCallback();
this.dataListener = RegisterViewListener('JS_LISTENER_COMM_BUS');
const container = document.getElementById('react');
if (container) {
console.log('Starting React');
const root = createRoot(container);
root.render(createElement(App, { dataListener: this.dataListener }));
root.render(createElement(App));
}
}

View File

@ -1,10 +0,0 @@
import '@mui/material';
declare module '@mui/material/styles' {
interface Theme {
screenHeight: number;
}
interface ThemeOptions {
screenHeight: number;
}
}

View File

@ -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 }>;
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -6,9 +6,9 @@
url="html_UI/InGamePanels/tfdidesign-md11-load-manager-panel/index.html"
resizeDirections="both"
minWidth="100"
minHeight="60"
minHeight="70"
defaultWidth="100"
defaultHeight="60"
defaultHeight="70"
defaultTop="10"
defaultLeft="10"
icon="ICON_TFDIDESIGN_MD11_LOAD_MANAGER"

6
README.md Normal file
View File

@ -0,0 +1,6 @@
# 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

65
WB MD-11 calc.txt Normal file
View File

@ -0,0 +1,65 @@
F
MAC Pos as found in DEBUG: 24.16ft
LEMAC Pos as found in DEBUG: -7.71ft
Empty weight
Arm: -13.3ft
Weight: 112748kg
Moment: Arm * Weight = -1499548.4 kg*ft
77kg in Pilot station
Arm: 82ft
Weight: 77kg
Moment: Arm * Weight = 6314 kg*ft
77kg in FO station
Arm: 82ft
Weight: 77kg
Moment: Arm * Weight = 6314 kg*ft
77kg in FE station
Arm: 80ft
Weight: 77kg
Moment: Arm * Weight = 6160 kg*ft
Total:
Weight: Sum = 112979kg
Moment: Sum = -1480760.4 kg*ft
CG: Moment / Weight = -13.11ft (-13.1065065189)
As %MAC
abs(((CG - LEMAC) / MAC) * 100)
abs(((-13.11 - -7.71) / 24.16) * 100)
22.35
PAX
MAC Pos as found in DEBUG: 24.16ft
LEMAC Pos as found in DEBUG: -7.71ft
Empty weight
Arm: -13.3ft
Weight: 128809kg
Moment: Arm * Weight = -1713159.7 kg*ft
77kg in Pilot station
Arm: 82ft
Weight: 77kg
Moment: Arm * Weight = 6314 kg*ft
77kg in FO station
Arm: 82ft
Weight: 77kg
Moment: Arm * Weight = 6314 kg*ft
77kg in FE station
Arm: 80ft
Weight: 77kg
Moment: Arm * Weight = 6160 kg*ft
Total:
Weight: Sum = 129040kg
Moment: Sum = -1694371.7 kg*ft
CG: Moment / Weight = -13.13ft (-13.1305928394)
As %MAC
abs(((CG - LEMAC) / MAC) * 100)
abs(((-13.13 - -7.71) / 24.16) * 100)
22.35