15 Commits

Author SHA1 Message Date
Kilian 80cb726501 Customisable pax/bag weight
Better log
2025-06-21 21:41:17 +02:00
Kilian 2047c84d8d Fix SB persist 2025-06-19 16:05:54 +02:00
Kilian 390edd29b8 SB persist
Options page for GSX Sync
2025-06-18 23:57:46 +02:00
Kilian 4b60f8eec2 Rmv wasm build artifact 2025-06-15 02:01:03 +02:00
Kilian 9da2abdad7 Freighter 2025-06-15 01:57:28 +02:00
Kilian cbd7d4e0ae Check prog pax load/unload 2025-06-14 16:47:27 +02:00
Kilian c394cd4d7b GSX Synced boarding/deboarding 2025-06-14 03:34:22 +02:00
Kilian f7304c5c7b Setting of payload 2025-06-12 14:30:00 +02:00
Kilian 8975ea17af SB fetch and entry 2025-06-11 23:49:35 +02:00
Kilian 896a459bba Pax Station Entry 2025-06-11 17:30:36 +02:00
Kilian 890622453e Cleanup old configs 2025-06-11 00:44:15 +02:00
Kilian ee46d0bff1 ZFW Target Set 2025-06-11 00:27:27 +02:00
Kilian 9224300c85 WASM PAX data export 2025-06-10 01:12:58 +02:00
Kilian a34c532484 initial wasm commit 2025-06-09 07:04:32 +02:00
Kilian 0297cfb600 initial commit 2025-06-09 07:02:26 +02:00
69 changed files with 13911 additions and 382 deletions
+8 -1
View File
@@ -3,4 +3,11 @@ _PackageInt
PackageSources/js-bundle/__generated__
PackageSources/js-bundle/.rollup.cache
PackageSources/js-bundle/node_modules
PackageSources/html_ui
PackageSources/html_ui
PackageSources/wasm-module/.vs
PackageSources/wasm-module/MSFS
PackageSources/wasm-module/x64
*.blend1
PackageSources/SimObjects/Airplanes/**/panel/*.wasm
Binary file not shown.

After

Width:  |  Height:  |  Size: 475 KiB

Binary file not shown.
Binary file not shown.
@@ -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
+196
View File
@@ -0,0 +1,196 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="4002"
height="780"
viewBox="0 0 4002 780"
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)"
inkscape:export-filename="MD11_Profile_EXP.svg"
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.5"
inkscape:cx="3634"
inkscape:cy="345"
inkscape:window-width="1920"
inkscape:window-height="1009"
inkscape:window-x="-8"
inkscape:window-y="-8"
inkscape:window-maximized="1"
inkscape:current-layer="layer7"
inkscape:export-bgcolor="#ffffff00" /><defs
id="defs1" />
<g
inkscape:groupmode="layer"
id="layer6"
inkscape:label="Static"><text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:176px;line-height:1.25;font-family:sans-serif;fill:#000000;fill-opacity:1;stroke:none"
x="-17.1875"
y="280.10175"
id="text1-3"><tspan
sodipodi:role="line"
id="tspan1-9"
x="-17.1875"
y="280.10175">Pilots &amp; Crew:</tspan></text><text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:176px;line-height:1.25;font-family:sans-serif;fill:#000000;fill-opacity:1;stroke:none"
x="-9.8828125"
y="130.625"
id="text1"><tspan
sodipodi:role="line"
id="tspan1"
x="-9.8828125"
y="130.625">OEW:</tspan></text></g><g
inkscape:groupmode="layer"
id="layer7"
inkscape:label="Generics"><text
xml:space="preserve"
style="font-size:176px;line-height:1.25;font-family:sans-serif"
x="1476.2501"
y="276.92206"
id="text2"><tspan
sodipodi:role="line"
id="tspan2"
x="1476.2501"
y="276.92206">9999</tspan></text><text
xml:space="preserve"
style="font-size:176px;line-height:1.25;font-family:sans-serif"
x="1252.4691"
y="130.53906"
id="text3"><tspan
sodipodi:role="line"
id="tspan3"
x="1252.4691"
y="130.53906">999999</tspan></text><text
xml:space="preserve"
style="font-size:133.333px;line-height:1.25;font-family:sans-serif;stroke-width:0.999998"
x="3752.9043"
y="778.24402"
id="text4"><tspan
sodipodi:role="line"
x="3752.9043"
y="778.24402"
style="font-size:133.333px;stroke-width:0.999998"
id="tspan6">LBS</tspan></text><text
xml:space="preserve"
style="font-size:176px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif"
x="3518"
y="320"
id="text7"><tspan
sodipodi:role="line"
id="tspan7"
x="3518"
y="320">ER</tspan></text></g><g
inkscape:groupmode="layer"
id="layer2"
inkscape:label="Stations"><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;-inkscape-font-specification:'sans-serif, Normal';font-stretch:normal;font-variant:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal"
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-variant:normal;font-weight:normal;font-stretch:normal;font-size:176px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none"
x="-179.32031"
y="143.71875"
id="text5-8"
inkscape:label="upper1"><tspan
sodipodi:role="line"
id="tspan5-3"
x="-179.32031"
y="143.71875"
style="text-align:start;text-anchor:start" /></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="lower1"
inkscape:label="upper4"><tspan
sodipodi:role="line"
id="tspan5-0-03"
x="2891.1475"
y="754.35504">99999</tspan></text></g><g
inkscape:groupmode="layer"
id="layer3"
inkscape:label="Sketch"><path
id="path5"
style="display:inline;fill:none;stroke:#646464;stroke-width:3.97267;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
d="m 1748.2487,624.45529 v 83.5816 z m 653.1368,98.40409 v 43.08593 z"
transform="matrix(1.0068517,0,0,1.0069072,-24.265193,-12.003831)"
inkscape:label="Dashed"
sodipodi:nodetypes="cccccc" /><path
id="path10"
style="display:inline;fill:none;fill-opacity:1;stroke:#000000;stroke-width:3.97527;stroke-linecap:butt;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
d="m 119.50997,573.71703 h 128.0729 v 29.07865 h 119.1481 M 1922.9882,624.6584 V 378.08519 Z M 1143.9838,378.54476 v 246.57126 z m 1556.0004,1.0854 3e-4,245.70686 0.01,-245.70686 z M 119.47872,507.3493 V 686.42638 Z M 681.8277,784.08016 C 550.68986,778.56008 459.37243,767.83734 325.24777,742.2102 247.12441,727.28325 163.85922,704.53832 115.68874,684.96689 65.272866,664.48337 30.640554,635.98924 26.748642,611.79065 c -3.768329,-23.42962 7.455828,-38.32595 50.49813,-67.01953 6.041298,-4.02691 12.708263,-9.27073 14.816577,-11.65295 2.108023,-2.3822 4.524361,-4.48001 4.524361,-4.48001 0,0 45.05507,-44.22564 69.74451,-58.59581 72.48275,-42.18783 238.75927,-76.44031 425.63149,-87.67895 14.00372,-0.84197 33.99829,-2.07064 44.43261,-2.72959 26.21726,-1.65646 1973.24248,-2.45294 2062.36198,-0.84445 156.7316,2.82998 269.5005,7.74134 530.5511,23.10724 47.1495,2.7752 85.8534,4.90642 86.012,4.73564 0.6463,-0.69433 3.18,-46.35302 2.6116,-47.00235 -0.3392,-0.38606 -8.4798,-1.63074 -18.0917,-2.7653 -35.3422,-4.17401 -67.399,-11.82474 -77.0779,-18.39697 -3.9158,-2.65808 -3.9645,-3.95085 -1.9416,-51.11949 2.108,-49.16104 3.1187,-81.48815 3.1285,-100.00521 0,-21.77363 -0.1657,-21.37816 11.1206,-24.94772 37.4058,-11.83133 117.8811,-11.06942 171.1122,1.62031 15.227,3.62986 19.589,3.51496 35.5372,-0.93615 21.7001,-6.05753 21.0601,-5.51568 96.6373,-82.052719 33.1386,-33.558758 68.757,-66.037569 68.757,-66.037569 0,0 83.3796,-1.079949 169.2388,-1.079949 136.9782,0 171.6165,0.253341 171.2179,1.25017 -4.4107,11.004128 -56.5812,125.499597 -58.6917,128.808777 -4.6101,7.22481 -3.2139,7.88313 16.7587,7.90201 9.0622,0.008 22.5343,1.10293 37.2289,3.0234 4.1187,0.5386 15.3536,1.65343 24.9606,2.47749 9.6122,0.82422 19.8325,1.75756 22.7175,2.07418 5.0681,0.55713 9.0514,198.40717 3.9934,198.38178 -3.6049,-0.0227 -31.7008,3.23584 -34.6991,4.01865 -1.9198,0.50162 -6.9752,1.19264 -11.2312,1.53478 -7.7386,0.62215 -7.7386,0.62215 -7.7386,8.4184 0,8.93284 0.045,8.97847 9.985,9.03089 7.595,0.034 9.8124,1.63453 3.4137,2.45321 -2.7018,0.34575 -6.0356,0.83238 -7.4075,1.08266 -1.3721,0.25018 -13.4624,0.89408 -26.8658,1.43238 -13.4009,0.53851 -28.9024,1.4418 -34.4462,2.00812 -15.6072,1.59497 -41.7208,3.01042 -55.6346,3.01554 -20.6343,0.008 -19.0304,-1.48851 -18.6619,17.4164 0.3714,19.01843 2.3134,23.86211 11.5516,28.7958 5.5848,2.98376 0.3035,2.54795 88.3399,7.28999 84.7141,4.56302 75.158,-2.81091 75.158,57.97778 0,54.09028 0.038,53.96894 -18.7912,59.84504 -20.4081,6.36957 -118.4497,34.30825 -182.9044,52.12181 -74.4105,20.56545 -152.6321,42.51798 -160.2541,44.9738 -10.5871,3.41069 -57.1162,16.38817 -105.4333,29.40502 -184.6228,49.73829 -402.0471,89.78228 -516.1218,95.05681 -19.1654,0.88577 -2300.07154,1.25614 -2320.9699,0.37695 z m 1714.3911,-15.93638 c 14.3101,-1.72862 35.0046,-5.59211 45.932,-8.57466 47.3734,-12.93067 34.3571,-20.57346 -70.3941,-41.33854 -9.3343,-1.85054 -21.9156,-4.53045 -27.9568,-5.955 -119.2244,-28.11802 -135.9358,-31.16723 -227.3866,-41.48667 -32.4779,-3.66487 -84.0049,-11.3955 -126.5748,-18.9901 -77.6003,-13.84405 -129.5471,-21.9553 -156.762,-24.47858 -178.2016,-16.52165 -260.2497,38.68714 -109.1224,73.42801 7.2586,1.66798 18.9422,5.29576 25.9629,8.06195 39.3007,15.48166 111.0211,26.35086 233.4296,35.37682 97.5092,7.1897 247.1876,10.13705 247.9345,4.88196 0.6641,-4.66361 1.511,-4.79998 36.7154,-5.88569 22.9808,-0.70847 26.3783,-0.21481 26.3783,3.83836 0,2.5877 2.9594,14.02473 3.8762,14.97665 0.4007,0.41452 15.6685,2.27843 33.9288,4.14116 18.264,1.86268 33.4272,3.60903 33.698,3.88056 0.7657,0.76635 16.5438,-0.20912 30.341,-1.87623 z m -2029.36746,-359.3222 -0.0248,215.97654 1275.64716,-4.1e-4 h 1275.1949 l 132.9522,-2.46652 132.952,-2.4665 147.9241,-11.4452 147.9243,-11.4452 1.0236,-90.88061 1.0235,-90.88061 -83.3015,-4.35422 -83.3014,-4.35424 m -2614.52231,217.81122 -5e-5,159.11801 z M 1748.1434,708.5565 v 75.45385 z m 1663.0399,-106.30033 -1e-4,113.31756 z m -1009.9445,22.54108 v 99.39317 z m -4e-4,143.38207 v 15.78331 z"
sodipodi:nodetypes="ccccccccccccccccccscscccccccsccccsccscscsccsssccssscsssssscsssssssccssscsscccscsscscsccccccccccccccccccccccccccc"
transform="matrix(1.0068517,0,0,1.0069072,-24.265193,-12.003831)"
inkscape:label="Solid" /></g></svg>

After

Width:  |  Height:  |  Size: 11 KiB

+54
View File
@@ -0,0 +1,54 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="4002"
height="780"
viewBox="0 0 4002 780"
version="1.1"
id="svg1"
xml:space="preserve"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"><defs
id="defs1" />
<text
xml:space="preserve"
style="font-size:160px;line-height:1.25;font-family:sans-serif;text-anchor:end;display:inline"
x="1476.2501"
y="276.92206"
id="text2"><tspan
id="tspan2"
x="1476.2501"
y="276.92206">9999</tspan></text><text
xml:space="preserve"
style="font-size:160px;line-height:1.25;font-family:sans-serif;text-anchor:end;display:inline"
x="1476.2501"
y="130.53906"
id="text3"><tspan
id="tspan3"
x="1476.2501"
y="130.53906">999999</tspan></text><text
xml:space="preserve"
style="font-size:133.333px;line-height:1.25;font-family:sans-serif;display:inline;stroke-width:0.999998"
x="3752.9043"
y="778.24402"
id="text4"><tspan
x="3752.9043"
y="778.24402"
style="font-size:133.333px;stroke-width:0.999998"
id="tspan6">LBS</tspan></text><path
id="text7"
style="font-size:160px;line-height:1.25;-inkscape-font-specification:sans-serif;display:inline;fill:none;fill-opacity:1;stroke:#000000;stroke-width:7.99861;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
d="m 3616.1269,203.67131 -115.4682,116.32951 h 76.6132 l 13.6484,-13.75016 h -61.1499 l 42.8836,-43.20365 h 61.1499 l 13.6485,-13.75016 h -61.1499 l 31.6393,-31.87538 h 61.1499 l 13.6484,-13.75016 z m 101.1357,0 -115.4682,116.32951 h 15.4631 l 45.9082,-46.25055 h 21.7891 l -7.0158,46.25055 h 20.0709 l 6.7491,-50.85999 c 10.2365,-2.8646 20.2552,-7.10948 30.0559,-12.73452 9.8522,-5.67714 18.9402,-12.70852 27.2636,-21.09401 6.1521,-6.19797 10.0211,-11.30222 11.6068,-15.31268 1.6896,-4.06255 1.7441,-7.42197 0.1635,-10.07824 -1.4223,-2.34378 -4.0367,-3.95839 -7.8438,-4.84382 -3.7552,-0.93749 -9.1472,-1.40626 -16.176,-1.40625 z m 2.2801,13.2814 h 18.1967 c 4.165,0 7.4735,0.31252 9.9248,0.93751 2.5032,0.57292 4.1244,1.61462 4.8641,3.12503 0.9495,1.77087 0.7045,3.9584 -0.735,6.56258 -1.3356,2.55212 -3.6579,5.49487 -6.9666,8.82824 -4.3426,4.37505 -8.5084,7.9949 -12.4972,10.8595 -3.8849,2.81253 -8.0847,5.31258 -12.5989,7.50009 -4.8776,2.34378 -9.5781,3.95838 -14.1015,4.84381 -4.4716,0.83333 -9.1546,1.25002 -14.0487,1.25002 h -15.6194 z" /><path
id="path10"
style="display:inline;fill:none;fill-opacity:1;stroke:#000000;stroke-width:4.00262;stroke-linecap:butt;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
d="M 96.063623,565.67598 H 225.01404 v 29.2795 H 344.97851 M 1911.8987,616.96921 V 368.69287 Z m -784.3419,-247.8136 v 248.27438 z m 1566.6617,1.0929 3e-4,247.40401 0.01,-247.40401 z M 96.032159,498.84983 v 180.314 z M 662.23419,777.49213 C 530.19783,771.93392 438.25472,761.13712 303.21108,735.33296 224.55244,720.30291 140.71674,697.40088 92.216212,677.69426 41.454903,657.06926 6.5853009,628.37831 2.6667227,604.01258 -1.1274258,580.42113 10.173636,565.4219 53.510851,536.53013 c 6.082691,-4.05472 12.795336,-9.33476 14.918095,-11.73344 2.122467,-2.39865 4.555361,-4.51095 4.555361,-4.51095 0,0 45.363773,-44.53112 70.222383,-59.00054 72.97938,-42.47923 240.39517,-76.9683 428.54778,-88.28457 14.09967,-0.84779 34.23124,-2.08494 44.73705,-2.74844 26.3969,-1.66791 1986.76258,-2.46989 2076.49268,-0.85029 157.8055,2.84953 271.347,7.79481 534.1863,23.26685 47.4725,2.79437 86.4416,4.94031 86.6013,4.76835 0.6507,-0.69913 3.2018,-46.67319 2.6295,-47.32701 -0.3415,-0.38872 -8.5379,-1.642 -18.2157,-2.7844 -35.5843,-4.20284 -67.8608,-11.90641 -77.606,-18.52404 -3.9426,-2.67644 -3.9916,-3.97814 -1.9549,-51.47258 2.1225,-49.50061 3.1401,-82.051 3.1499,-100.69597 0,-21.92402 -0.1668,-21.52582 11.1968,-25.12003 37.6621,-11.91306 118.6888,-11.14588 172.2847,1.6315 15.3313,3.65493 19.7232,3.53924 35.7806,-0.94262 21.8488,-6.09937 21.2044,-5.55378 97.2995,-82.619473 33.3656,-33.790555 69.2278,-66.4937035 69.2278,-66.4937035 0,0 83.9512,-1.0874084 170.3986,-1.0874084 137.9168,0 172.7927,0.2550909 172.3914,1.2588052 -4.4409,11.0801357 -56.9692,126.3664497 -59.0942,129.6984897 -4.6416,7.27471 -3.2359,7.93758 16.8736,7.95659 9.1243,0.008 22.6887,1.11054 37.484,3.04428 4.1469,0.54232 15.4587,1.66485 25.1316,2.4946 9.678,0.82991 19.9684,1.7697 22.8731,2.08851 5.1029,0.56098 9.1134,199.77761 4.0208,199.75204 -3.6296,-0.0229 -31.918,3.25819 -34.9369,4.04641 -1.9329,0.50508 -7.023,1.20088 -11.3081,1.54538 -7.7916,0.62645 -7.7916,0.62645 -7.7916,8.47655 0,8.99454 0.045,9.04048 10.0534,9.09327 7.647,0.0342 9.8796,1.64582 3.4371,2.47015 -2.7203,0.34814 -6.077,0.83813 -7.4583,1.09014 -1.3815,0.25191 -13.5546,0.90025 -27.0499,1.44227 -13.4927,0.54223 -29.1004,1.45176 -34.6822,2.02199 -15.7141,1.60599 -42.0066,3.03122 -56.0158,3.03637 -20.7756,0.008 -19.1608,-1.49879 -18.7897,17.5367 0.3739,19.14979 2.3292,24.02693 11.6307,28.9947 5.6231,3.00437 0.3056,2.56555 88.9452,7.34034 85.2945,4.59454 75.673,-2.83032 75.673,58.37825 0,54.46389 0.038,54.34171 -18.92,60.2584 -20.5479,6.41356 -119.2613,34.54522 -184.1576,52.48182 -74.9203,20.7075 -153.6779,42.81166 -161.3521,45.28445 -10.6597,3.43424 -57.5076,16.50136 -106.1557,29.60812 -185.8878,50.08185 -404.8018,90.40243 -519.6581,95.71339 -19.2967,0.89189 -2315.83097,1.26482 -2336.87252,0.37955 z M 2388.3718,761.44567 c 14.4081,-1.74056 35.2444,-5.63073 46.2467,-8.63389 47.698,-13.01998 34.5925,-20.71556 -70.8764,-41.62407 -9.3983,-1.86332 -22.0658,-4.56174 -28.1484,-5.99613 -120.0413,-28.31224 -136.8672,-31.38251 -228.9446,-41.77323 -32.7004,-3.69018 -84.5804,-11.47421 -127.442,-19.12127 -78.132,-13.93967 -130.4347,-22.10695 -157.8361,-24.64765 -179.4226,-16.63577 -262.0329,38.95436 -109.8701,73.93519 7.3084,1.6795 19.072,5.33234 26.1408,8.11763 39.57,15.5886 111.7818,26.53287 235.029,35.62118 98.1773,7.23936 248.8813,10.20707 249.6333,4.91568 0.6686,-4.69582 1.5213,-4.83314 36.9669,-5.92635 23.1383,-0.71336 26.5591,-0.21629 26.5591,3.86488 0,2.60557 2.9797,14.1216 3.9027,15.08009 0.4035,0.41739 15.7759,2.29417 34.1613,4.16977 18.3891,1.87554 33.6562,3.63396 33.9289,3.90736 0.7709,0.77164 16.6571,-0.21056 30.5489,-1.88919 z M 345.0997,399.64156 l -0.025,217.46833 1284.3875,-4.1e-4 h 1283.9322 l 133.8631,-2.48356 133.863,-2.48353 148.9376,-11.52426 148.9379,-11.52425 1.0306,-91.50834 1.0305,-91.50834 -83.8723,-4.3843 -83.8721,-4.38431 m -2632.43629,219.31568 -5e-5,160.21707 z M 1735.856,701.44681 v 75.97503 z m 1674.4345,-107.03457 -1e-4,114.10027 z m -1016.8643,22.69678 v 100.0797 z m -4e-4,144.37244 v 15.89233 z" /><path
id="path5"
style="display:inline;fill:none;stroke:#646464;stroke-width:4;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
d="m 1735.962,616.7647 v 84.15891 z m 657.6119,99.08378 v 43.38354 z" /></svg>

After

Width:  |  Height:  |  Size: 6.8 KiB

@@ -16,8 +16,8 @@
<Flags>
<FSXCompatibility>false</FSXCompatibility>
</Flags>
<AssetDir>PackageDefinitions\xkhofmann-tfdidesign-md11-load-manager\ContentInfo</AssetDir>
<OutputDir>ContentInfo\xkhofmann-tfdidesign-md11-load-manager</OutputDir>
<AssetDir>PackageDefinitions\xkhofmann-tfdidesign-md11-load-manager\ContentInfo\</AssetDir>
<OutputDir>ContentInfo\xkhofmann-tfdidesign-md11-load-manager\</OutputDir>
</AssetGroup>
<AssetGroup Name="html-ui">
<Type>Copy</Type>
@@ -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
+20 -18
View File
@@ -1,6 +1,6 @@
{
"name": "tfdidesign-md11-load-manager",
"version": "0.1.1",
"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"
@@ -24,36 +26,36 @@
"devDependencies": {
"@microsoft/msfs-types": "^1.14.6",
"@rollup/plugin-commonjs": "^28.0.3",
"@rollup/plugin-json": "^6.0.0",
"@rollup/plugin-json": "^6.1.0",
"@rollup/plugin-node-resolve": "^16.0.1",
"@rollup/plugin-replace": "^6.0.2",
"@rollup/plugin-terser": "^0.4.3",
"@rollup/plugin-terser": "^0.4.4",
"@rollup/plugin-typescript": "^12.1.2",
"@types/react": "^19.1.6",
"@types/react-dom": "^19.1.5",
"@types/react-dom": "^19.1.6",
"@types/uuid": "^10.0.0",
"@typescript-eslint/eslint-plugin": "^6.10.0",
"@typescript-eslint/parser": "^6.10.0",
"autoprefixer": "^10.4.14",
"@typescript-eslint/eslint-plugin": "^6.21.0",
"@typescript-eslint/parser": "^6.21.0",
"autoprefixer": "^10.4.21",
"cross-env": "^7.0.3",
"eslint": "^8.42.0",
"eslint-plugin-import": "^2.27.5",
"eslint-plugin-react": "^7.32.2",
"eslint-plugin-react-hooks": "^4.6.0",
"license-report": "^6.5.0",
"postcss": "^8.4.24",
"eslint": "^8.57.1",
"eslint-plugin-import": "^2.31.0",
"eslint-plugin-react": "^7.37.5",
"eslint-plugin-react-hooks": "^4.6.2",
"license-report": "^6.7.2",
"postcss": "^8.5.4",
"postcss-import": "^16.1.0",
"prettier": "^3.0.3",
"prettier": "^3.5.3",
"prettier-plugin-organize-imports": "^4.1.0",
"rimraf": "^6.0.1",
"rollup": "^4.3.1",
"rollup-plugin-copy": "^3.4.0",
"rollup": "^4.42.0",
"rollup-plugin-copy": "^3.5.0",
"rollup-plugin-postcss": "^4.0.2",
"rollup-plugin-react-svg": "^3.0.3",
"rollup-plugin-version-injector": "^1.3.3",
"sass": "^1.89.1",
"svg-slim": "^2.0.5",
"tslib": "^2.5.3",
"tslib": "^2.8.1",
"typed-scss-modules": "^8.1.1",
"typescript": "5.8.3"
},
+180 -175
View File
@@ -23,66 +23,66 @@ importers:
version: 1.14.6
'@rollup/plugin-commonjs':
specifier: ^28.0.3
version: 28.0.3(rollup@4.41.1)
version: 28.0.3(rollup@4.42.0)
'@rollup/plugin-json':
specifier: ^6.0.0
version: 6.1.0(rollup@4.41.1)
specifier: ^6.1.0
version: 6.1.0(rollup@4.42.0)
'@rollup/plugin-node-resolve':
specifier: ^16.0.1
version: 16.0.1(rollup@4.41.1)
version: 16.0.1(rollup@4.42.0)
'@rollup/plugin-replace':
specifier: ^6.0.2
version: 6.0.2(rollup@4.41.1)
version: 6.0.2(rollup@4.42.0)
'@rollup/plugin-terser':
specifier: ^0.4.3
version: 0.4.4(rollup@4.41.1)
specifier: ^0.4.4
version: 0.4.4(rollup@4.42.0)
'@rollup/plugin-typescript':
specifier: ^12.1.2
version: 12.1.2(rollup@4.41.1)(tslib@2.8.1)(typescript@5.8.3)
version: 12.1.2(rollup@4.42.0)(tslib@2.8.1)(typescript@5.8.3)
'@types/react':
specifier: ^19.1.6
version: 19.1.6
'@types/react-dom':
specifier: ^19.1.5
version: 19.1.5(@types/react@19.1.6)
specifier: ^19.1.6
version: 19.1.6(@types/react@19.1.6)
'@types/uuid':
specifier: ^10.0.0
version: 10.0.0
'@typescript-eslint/eslint-plugin':
specifier: ^6.10.0
specifier: ^6.21.0
version: 6.21.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.8.3))(eslint@8.57.1)(typescript@5.8.3)
'@typescript-eslint/parser':
specifier: ^6.10.0
specifier: ^6.21.0
version: 6.21.0(eslint@8.57.1)(typescript@5.8.3)
autoprefixer:
specifier: ^10.4.14
specifier: ^10.4.21
version: 10.4.21(postcss@8.5.4)
cross-env:
specifier: ^7.0.3
version: 7.0.3
eslint:
specifier: ^8.42.0
specifier: ^8.57.1
version: 8.57.1
eslint-plugin-import:
specifier: ^2.27.5
specifier: ^2.31.0
version: 2.31.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.8.3))(eslint@8.57.1)
eslint-plugin-react:
specifier: ^7.32.2
specifier: ^7.37.5
version: 7.37.5(eslint@8.57.1)
eslint-plugin-react-hooks:
specifier: ^4.6.0
specifier: ^4.6.2
version: 4.6.2(eslint@8.57.1)
license-report:
specifier: ^6.5.0
specifier: ^6.7.2
version: 6.7.2
postcss:
specifier: ^8.4.24
specifier: ^8.5.4
version: 8.5.4
postcss-import:
specifier: ^16.1.0
version: 16.1.0(postcss@8.5.4)
prettier:
specifier: ^3.0.3
specifier: ^3.5.3
version: 3.5.3
prettier-plugin-organize-imports:
specifier: ^4.1.0
@@ -91,10 +91,10 @@ importers:
specifier: ^6.0.1
version: 6.0.1
rollup:
specifier: ^4.3.1
version: 4.41.1
specifier: ^4.42.0
version: 4.42.0
rollup-plugin-copy:
specifier: ^3.4.0
specifier: ^3.5.0
version: 3.5.0
rollup-plugin-postcss:
specifier: ^4.0.2
@@ -112,7 +112,7 @@ importers:
specifier: ^2.0.5
version: 2.0.5
tslib:
specifier: ^2.5.3
specifier: ^2.8.1
version: 2.8.1
typed-scss-modules:
specifier: ^8.1.1
@@ -177,8 +177,8 @@ packages:
resolution: {integrity: sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==}
engines: {node: '>=6.9.0'}
'@babel/helpers@7.27.4':
resolution: {integrity: sha512-Y+bO6U+I7ZKaM5G5rDUZiYfUvQPUibYmAFe7EnKdnKBbVXDZxvp+MWOH5gYciY0EPk4EScsuFMQBbEfpdRKSCQ==}
'@babel/helpers@7.27.6':
resolution: {integrity: sha512-muE8Tt8M22638HU31A3CgfSUciwz1fhATfoVai05aPXGor//CdWDCbnlY1yvBPo07njuVOCNGCSp/GTt12lIug==}
engines: {node: '>=6.9.0'}
'@babel/parser@7.27.5':
@@ -230,8 +230,8 @@ packages:
resolution: {integrity: sha512-oNcu2QbHqts9BtOWJosOVJapWjBDSxGCpFvikNR5TGDYDQf3JwpIoMzIKrvfoti93cLfPJEG4tH9SPVeyCGgdA==}
engines: {node: '>=6.9.0'}
'@babel/types@7.27.3':
resolution: {integrity: sha512-Y1GkI4ktrtvmawoSq+4FCVHNryea6uR+qUQy0AGxLSsjCX0nVmkYQMBLHDkXZuo5hGx7eYdnIaslsdBFm7zbUw==}
'@babel/types@7.27.6':
resolution: {integrity: sha512-ETyHEk2VHHvl9b9jZP5IHPavHYk57EhanlRRuae9XCpb/j5bDCbPPMOBfCWhnl/7EDJz0jEMCi/RhccCE8r1+Q==}
engines: {node: '>=6.9.0'}
'@esbuild/android-arm64@0.17.19':
@@ -589,103 +589,103 @@ packages:
rollup:
optional: true
'@rollup/rollup-android-arm-eabi@4.41.1':
resolution: {integrity: sha512-NELNvyEWZ6R9QMkiytB4/L4zSEaBC03KIXEghptLGLZWJ6VPrL63ooZQCOnlx36aQPGhzuOMwDerC1Eb2VmrLw==}
'@rollup/rollup-android-arm-eabi@4.42.0':
resolution: {integrity: sha512-gldmAyS9hpj+H6LpRNlcjQWbuKUtb94lodB9uCz71Jm+7BxK1VIOo7y62tZZwxhA7j1ylv/yQz080L5WkS+LoQ==}
cpu: [arm]
os: [android]
'@rollup/rollup-android-arm64@4.41.1':
resolution: {integrity: sha512-DXdQe1BJ6TK47ukAoZLehRHhfKnKg9BjnQYUu9gzhI8Mwa1d2fzxA1aw2JixHVl403bwp1+/o/NhhHtxWJBgEA==}
'@rollup/rollup-android-arm64@4.42.0':
resolution: {integrity: sha512-bpRipfTgmGFdCZDFLRvIkSNO1/3RGS74aWkJJTFJBH7h3MRV4UijkaEUeOMbi9wxtxYmtAbVcnMtHTPBhLEkaw==}
cpu: [arm64]
os: [android]
'@rollup/rollup-darwin-arm64@4.41.1':
resolution: {integrity: sha512-5afxvwszzdulsU2w8JKWwY8/sJOLPzf0e1bFuvcW5h9zsEg+RQAojdW0ux2zyYAz7R8HvvzKCjLNJhVq965U7w==}
'@rollup/rollup-darwin-arm64@4.42.0':
resolution: {integrity: sha512-JxHtA081izPBVCHLKnl6GEA0w3920mlJPLh89NojpU2GsBSB6ypu4erFg/Wx1qbpUbepn0jY4dVWMGZM8gplgA==}
cpu: [arm64]
os: [darwin]
'@rollup/rollup-darwin-x64@4.41.1':
resolution: {integrity: sha512-egpJACny8QOdHNNMZKf8xY0Is6gIMz+tuqXlusxquWu3F833DcMwmGM7WlvCO9sB3OsPjdC4U0wHw5FabzCGZg==}
'@rollup/rollup-darwin-x64@4.42.0':
resolution: {integrity: sha512-rv5UZaWVIJTDMyQ3dCEK+m0SAn6G7H3PRc2AZmExvbDvtaDc+qXkei0knQWcI3+c9tEs7iL/4I4pTQoPbNL2SA==}
cpu: [x64]
os: [darwin]
'@rollup/rollup-freebsd-arm64@4.41.1':
resolution: {integrity: sha512-DBVMZH5vbjgRk3r0OzgjS38z+atlupJ7xfKIDJdZZL6sM6wjfDNo64aowcLPKIx7LMQi8vybB56uh1Ftck/Atg==}
'@rollup/rollup-freebsd-arm64@4.42.0':
resolution: {integrity: sha512-fJcN4uSGPWdpVmvLuMtALUFwCHgb2XiQjuECkHT3lWLZhSQ3MBQ9pq+WoWeJq2PrNxr9rPM1Qx+IjyGj8/c6zQ==}
cpu: [arm64]
os: [freebsd]
'@rollup/rollup-freebsd-x64@4.41.1':
resolution: {integrity: sha512-3FkydeohozEskBxNWEIbPfOE0aqQgB6ttTkJ159uWOFn42VLyfAiyD9UK5mhu+ItWzft60DycIN1Xdgiy8o/SA==}
'@rollup/rollup-freebsd-x64@4.42.0':
resolution: {integrity: sha512-CziHfyzpp8hJpCVE/ZdTizw58gr+m7Y2Xq5VOuCSrZR++th2xWAz4Nqk52MoIIrV3JHtVBhbBsJcAxs6NammOQ==}
cpu: [x64]
os: [freebsd]
'@rollup/rollup-linux-arm-gnueabihf@4.41.1':
resolution: {integrity: sha512-wC53ZNDgt0pqx5xCAgNunkTzFE8GTgdZ9EwYGVcg+jEjJdZGtq9xPjDnFgfFozQI/Xm1mh+D9YlYtl+ueswNEg==}
'@rollup/rollup-linux-arm-gnueabihf@4.42.0':
resolution: {integrity: sha512-UsQD5fyLWm2Fe5CDM7VPYAo+UC7+2Px4Y+N3AcPh/LdZu23YcuGPegQly++XEVaC8XUTFVPscl5y5Cl1twEI4A==}
cpu: [arm]
os: [linux]
'@rollup/rollup-linux-arm-musleabihf@4.41.1':
resolution: {integrity: sha512-jwKCca1gbZkZLhLRtsrka5N8sFAaxrGz/7wRJ8Wwvq3jug7toO21vWlViihG85ei7uJTpzbXZRcORotE+xyrLA==}
'@rollup/rollup-linux-arm-musleabihf@4.42.0':
resolution: {integrity: sha512-/i8NIrlgc/+4n1lnoWl1zgH7Uo0XK5xK3EDqVTf38KvyYgCU/Rm04+o1VvvzJZnVS5/cWSd07owkzcVasgfIkQ==}
cpu: [arm]
os: [linux]
'@rollup/rollup-linux-arm64-gnu@4.41.1':
resolution: {integrity: sha512-g0UBcNknsmmNQ8V2d/zD2P7WWfJKU0F1nu0k5pW4rvdb+BIqMm8ToluW/eeRmxCared5dD76lS04uL4UaNgpNA==}
'@rollup/rollup-linux-arm64-gnu@4.42.0':
resolution: {integrity: sha512-eoujJFOvoIBjZEi9hJnXAbWg+Vo1Ov8n/0IKZZcPZ7JhBzxh2A+2NFyeMZIRkY9iwBvSjloKgcvnjTbGKHE44Q==}
cpu: [arm64]
os: [linux]
'@rollup/rollup-linux-arm64-musl@4.41.1':
resolution: {integrity: sha512-XZpeGB5TKEZWzIrj7sXr+BEaSgo/ma/kCgrZgL0oo5qdB1JlTzIYQKel/RmhT6vMAvOdM2teYlAaOGJpJ9lahg==}
'@rollup/rollup-linux-arm64-musl@4.42.0':
resolution: {integrity: sha512-/3NrcOWFSR7RQUQIuZQChLND36aTU9IYE4j+TB40VU78S+RA0IiqHR30oSh6P1S9f9/wVOenHQnacs/Byb824g==}
cpu: [arm64]
os: [linux]
'@rollup/rollup-linux-loongarch64-gnu@4.41.1':
resolution: {integrity: sha512-bkCfDJ4qzWfFRCNt5RVV4DOw6KEgFTUZi2r2RuYhGWC8WhCA8lCAJhDeAmrM/fdiAH54m0mA0Vk2FGRPyzI+tw==}
'@rollup/rollup-linux-loongarch64-gnu@4.42.0':
resolution: {integrity: sha512-O8AplvIeavK5ABmZlKBq9/STdZlnQo7Sle0LLhVA7QT+CiGpNVe197/t8Aph9bhJqbDVGCHpY2i7QyfEDDStDg==}
cpu: [loong64]
os: [linux]
'@rollup/rollup-linux-powerpc64le-gnu@4.41.1':
resolution: {integrity: sha512-3mr3Xm+gvMX+/8EKogIZSIEF0WUu0HL9di+YWlJpO8CQBnoLAEL/roTCxuLncEdgcfJcvA4UMOf+2dnjl4Ut1A==}
'@rollup/rollup-linux-powerpc64le-gnu@4.42.0':
resolution: {integrity: sha512-6Qb66tbKVN7VyQrekhEzbHRxXXFFD8QKiFAwX5v9Xt6FiJ3BnCVBuyBxa2fkFGqxOCSGGYNejxd8ht+q5SnmtA==}
cpu: [ppc64]
os: [linux]
'@rollup/rollup-linux-riscv64-gnu@4.41.1':
resolution: {integrity: sha512-3rwCIh6MQ1LGrvKJitQjZFuQnT2wxfU+ivhNBzmxXTXPllewOF7JR1s2vMX/tWtUYFgphygxjqMl76q4aMotGw==}
'@rollup/rollup-linux-riscv64-gnu@4.42.0':
resolution: {integrity: sha512-KQETDSEBamQFvg/d8jajtRwLNBlGc3aKpaGiP/LvEbnmVUKlFta1vqJqTrvPtsYsfbE/DLg5CC9zyXRX3fnBiA==}
cpu: [riscv64]
os: [linux]
'@rollup/rollup-linux-riscv64-musl@4.41.1':
resolution: {integrity: sha512-LdIUOb3gvfmpkgFZuccNa2uYiqtgZAz3PTzjuM5bH3nvuy9ty6RGc/Q0+HDFrHrizJGVpjnTZ1yS5TNNjFlklw==}
'@rollup/rollup-linux-riscv64-musl@4.42.0':
resolution: {integrity: sha512-qMvnyjcU37sCo/tuC+JqeDKSuukGAd+pVlRl/oyDbkvPJ3awk6G6ua7tyum02O3lI+fio+eM5wsVd66X0jQtxw==}
cpu: [riscv64]
os: [linux]
'@rollup/rollup-linux-s390x-gnu@4.41.1':
resolution: {integrity: sha512-oIE6M8WC9ma6xYqjvPhzZYk6NbobIURvP/lEbh7FWplcMO6gn7MM2yHKA1eC/GvYwzNKK/1LYgqzdkZ8YFxR8g==}
'@rollup/rollup-linux-s390x-gnu@4.42.0':
resolution: {integrity: sha512-I2Y1ZUgTgU2RLddUHXTIgyrdOwljjkmcZ/VilvaEumtS3Fkuhbw4p4hgHc39Ypwvo2o7sBFNl2MquNvGCa55Iw==}
cpu: [s390x]
os: [linux]
'@rollup/rollup-linux-x64-gnu@4.41.1':
resolution: {integrity: sha512-cWBOvayNvA+SyeQMp79BHPK8ws6sHSsYnK5zDcsC3Hsxr1dgTABKjMnMslPq1DvZIp6uO7kIWhiGwaTdR4Og9A==}
'@rollup/rollup-linux-x64-gnu@4.42.0':
resolution: {integrity: sha512-Gfm6cV6mj3hCUY8TqWa63DB8Mx3NADoFwiJrMpoZ1uESbK8FQV3LXkhfry+8bOniq9pqY1OdsjFWNsSbfjPugw==}
cpu: [x64]
os: [linux]
'@rollup/rollup-linux-x64-musl@4.41.1':
resolution: {integrity: sha512-y5CbN44M+pUCdGDlZFzGGBSKCA4A/J2ZH4edTYSSxFg7ce1Xt3GtydbVKWLlzL+INfFIZAEg1ZV6hh9+QQf9YQ==}
'@rollup/rollup-linux-x64-musl@4.42.0':
resolution: {integrity: sha512-g86PF8YZ9GRqkdi0VoGlcDUb4rYtQKyTD1IVtxxN4Hpe7YqLBShA7oHMKU6oKTCi3uxwW4VkIGnOaH/El8de3w==}
cpu: [x64]
os: [linux]
'@rollup/rollup-win32-arm64-msvc@4.41.1':
resolution: {integrity: sha512-lZkCxIrjlJlMt1dLO/FbpZbzt6J/A8p4DnqzSa4PWqPEUUUnzXLeki/iyPLfV0BmHItlYgHUqJe+3KiyydmiNQ==}
'@rollup/rollup-win32-arm64-msvc@4.42.0':
resolution: {integrity: sha512-+axkdyDGSp6hjyzQ5m1pgcvQScfHnMCcsXkx8pTgy/6qBmWVhtRVlgxjWwDp67wEXXUr0x+vD6tp5W4x6V7u1A==}
cpu: [arm64]
os: [win32]
'@rollup/rollup-win32-ia32-msvc@4.41.1':
resolution: {integrity: sha512-+psFT9+pIh2iuGsxFYYa/LhS5MFKmuivRsx9iPJWNSGbh2XVEjk90fmpUEjCnILPEPJnikAU6SFDiEUyOv90Pg==}
'@rollup/rollup-win32-ia32-msvc@4.42.0':
resolution: {integrity: sha512-F+5J9pelstXKwRSDq92J0TEBXn2nfUrQGg+HK1+Tk7VOL09e0gBqUHugZv7SW4MGrYj41oNCUe3IKCDGVlis2g==}
cpu: [ia32]
os: [win32]
'@rollup/rollup-win32-x64-msvc@4.41.1':
resolution: {integrity: sha512-Wq2zpapRYLfi4aKxf2Xff0tN+7slj2d4R87WEzqw7ZLsVvO5zwYCIuEGSZYiK41+GlwUo1HiR+GdkLEJnCKTCw==}
'@rollup/rollup-win32-x64-msvc@4.42.0':
resolution: {integrity: sha512-LpHiJRwkaVz/LqjHjK8LCi8osq7elmpwujwbXKNW88bM8eeGxavJIKKjkjpMHAh/2xfnrt1ZSnhTv41WYUHYmA==}
cpu: [x64]
os: [win32]
@@ -695,8 +695,8 @@ packages:
'@sec-ant/readable-stream@0.4.1':
resolution: {integrity: sha512-831qok9r2t8AlxLko40y2ebgSDhenenCatLVeW/uBtnHPyhHOvG0C7TvfgecV+wHzIm5KUICgzmVpWS+IMEAeg==}
'@sindresorhus/is@7.0.1':
resolution: {integrity: sha512-QWLl2P+rsCJeofkDNIT3WFmb6NrRud1SUYW8dIhXK/46XFV8Q/g7Bsvib0Askb0reRLe+WYPeeE+l5cH7SlkuQ==}
'@sindresorhus/is@7.0.2':
resolution: {integrity: sha512-d9xRovfKNz1SKieM0qJdO+PQonjnnIfSNWfHYnBSJ9hkjm0ZPw6HlxscDXYstp3z+7V2GOFHc+J0CYrYTjqCJw==}
engines: {node: '>=18'}
'@szmarczak/http-timer@5.0.1':
@@ -714,6 +714,9 @@ packages:
'@types/estree@1.0.7':
resolution: {integrity: sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ==}
'@types/estree@1.0.8':
resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==}
'@types/fs-extra@8.1.5':
resolution: {integrity: sha512-0dzKcwO+S8s2kuF5Z9oUWatQJj5Uq/iqphEtE3GQJVRRYm/tD1LglU2UnXi2A8jLq5umkGouOXOR9y0n613ZwQ==}
@@ -732,14 +735,14 @@ packages:
'@types/minimatch@5.1.2':
resolution: {integrity: sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==}
'@types/node@22.15.29':
resolution: {integrity: sha512-LNdjOkUDlU1RZb8e1kOIUpN1qQUlzGkEtbVNo53vbrwDg5om6oduhm4SiUaPW5ASTXhAiP0jInWG8Qx9fVlOeQ==}
'@types/node@22.15.30':
resolution: {integrity: sha512-6Q7lr06bEHdlfplU6YRbgG1SFBdlsfNC4/lX+SkhiTs0cpJkOElmWls8PxDFv4yY/xKb8Y6SO0OmSX4wgqTZbA==}
'@types/q@1.5.8':
resolution: {integrity: sha512-hroOstUScF6zhIi+5+x0dzqrHA1EJi+Irri6b1fxolMTqqHIV/Cg77EtnQcZqZCu8hR3mX2BzIxN4/GzI68Kfw==}
'@types/react-dom@19.1.5':
resolution: {integrity: sha512-CMCjrWucUBZvohgZxkjd6S9h0nZxXjzus6yDfUb+xLxYM7VvjKNH1tQrE9GWLql1XoOP4/Ds3bwFqShHUYraGg==}
'@types/react-dom@19.1.6':
resolution: {integrity: sha512-4hOiT/dwO8Ko0gV1m/TJZYk3y0KBnY9vzDh7W+DH17b2HFSOGgdj33dhihPeuy3l0q23+4e+hoXHV6hCC4dCXw==}
peerDependencies:
'@types/react': ^19.0.0
@@ -995,8 +998,8 @@ packages:
caniuse-api@3.0.0:
resolution: {integrity: sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==}
caniuse-lite@1.0.30001720:
resolution: {integrity: sha512-Ec/2yV2nNPwb4DnTANEV99ZWwm3ZWfdlfkQbWSDDt+PsXEVYwlhPH8tdMaPunYTKKmz7AnHi2oNEi1GcmKCD8g==}
caniuse-lite@1.0.30001721:
resolution: {integrity: sha512-cOuvmUVtKrtEaoKiO0rSc29jcjwMwX5tOHDy4MgVFEWiUXj4uBMJkwI8MDySkgXidpMiHUcviogAvFi4pA2hDQ==}
capital-case@1.0.4:
resolution: {integrity: sha512-ds37W8CytHgwnhGGTi88pcPyR15qoNkOpYwmMMfnWqqWgESapLqvDx6huFjQ5vqWSn2Z06173XNA7LtMOeUh1A==}
@@ -1254,8 +1257,8 @@ packages:
eastasianwidth@0.2.0:
resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==}
electron-to-chromium@1.5.162:
resolution: {integrity: sha512-hQA+Zb5QQwoSaXJWEAGEw1zhk//O7qDzib05Z4qTqZfNju/FAkrm5ZInp0JbTp4Z18A6bilopdZWEYrFSsfllA==}
electron-to-chromium@1.5.165:
resolution: {integrity: sha512-naiMx1Z6Nb2TxPU6fiFrUrDTjyPMLdTtaOd2oLmG8zVSg2hCWGkhPyxwk+qRmZ1ytwVqUv0u7ZcDA5+ALhaUtw==}
emoji-regex@8.0.0:
resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==}
@@ -1466,8 +1469,8 @@ packages:
resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==}
engines: {node: '>=14'}
form-data-encoder@4.0.2:
resolution: {integrity: sha512-KQVhvhK8ZkWzxKxOr56CPulAhH3dobtuQ4+hNQ+HekH/Wp5gSOafqRAeTphQUJAIk0GBvHZgJ2ZGRWd5kphMuw==}
form-data-encoder@4.1.0:
resolution: {integrity: sha512-G6NsmEW15s0Uw9XnCg+33H3ViYRyiM0hMrMhhqQOR8NFc5GhYrI+6I3u7OTw7b91J2g8rtvMBZJDbcGb2YUniw==}
engines: {node: '>= 18'}
fraction.js@4.3.7:
@@ -2539,8 +2542,8 @@ packages:
rollup-pluginutils@2.8.2:
resolution: {integrity: sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==}
rollup@4.41.1:
resolution: {integrity: sha512-cPmwD3FnFv8rKMBc1MxWCwVQFxwf1JEmSX3iQXrRVVG15zerAIXRjMFVWnd5Q5QvgKF7Aj+5ykXFhUl+QGnyOw==}
rollup@4.42.0:
resolution: {integrity: sha512-LW+Vse3BJPyGJGAJt1j8pWDKPd73QM8cRXYK1IxOBgL2AGLu7Xd2YOW0M2sLUBCkF5MshXXtMApyEAEzMVMsnw==}
engines: {node: '>=18.0.0', npm: '>=8.0.0'}
hasBin: true
@@ -2774,8 +2777,8 @@ packages:
resolution: {integrity: sha512-IwO6f0SEzp1Z+zqz/7ANUmeEac4gaNlknWyj/S9aSg11wZmWYnLeyI/xXvEOU88BYUIf8y30y0wxB58xIKrVlQ==}
engines: {node: '>=14.16'}
terser@5.40.0:
resolution: {integrity: sha512-cfeKl/jjwSR5ar7d0FGmave9hFGJT8obyo0z+CrQOylLDbk7X81nPU6vq9VORa5jU30SkDnT2FXjLbR8HLP+xA==}
terser@5.41.0:
resolution: {integrity: sha512-H406eLPXpZbAX14+B8psIuvIr8+3c+2hkuYzpMkoE0ij+NdsVATbA78vb8neA/eqrj7rywa2pIkdmWRsXW6wmw==}
engines: {node: '>=10'}
hasBin: true
@@ -2987,11 +2990,11 @@ snapshots:
'@babel/generator': 7.27.5
'@babel/helper-compilation-targets': 7.27.2
'@babel/helper-module-transforms': 7.27.3(@babel/core@7.27.4)
'@babel/helpers': 7.27.4
'@babel/helpers': 7.27.6
'@babel/parser': 7.27.5
'@babel/template': 7.27.2
'@babel/traverse': 7.27.4
'@babel/types': 7.27.3
'@babel/types': 7.27.6
convert-source-map: 2.0.0
debug: 4.4.1
gensync: 1.0.0-beta.2
@@ -3003,14 +3006,14 @@ snapshots:
'@babel/generator@7.27.5':
dependencies:
'@babel/parser': 7.27.5
'@babel/types': 7.27.3
'@babel/types': 7.27.6
'@jridgewell/gen-mapping': 0.3.8
'@jridgewell/trace-mapping': 0.3.25
jsesc: 3.1.0
'@babel/helper-annotate-as-pure@7.27.3':
dependencies:
'@babel/types': 7.27.3
'@babel/types': 7.27.6
'@babel/helper-compilation-targets@7.27.2':
dependencies:
@@ -3023,7 +3026,7 @@ snapshots:
'@babel/helper-module-imports@7.27.1':
dependencies:
'@babel/traverse': 7.27.4
'@babel/types': 7.27.3
'@babel/types': 7.27.6
transitivePeerDependencies:
- supports-color
@@ -3044,14 +3047,14 @@ snapshots:
'@babel/helper-validator-option@7.27.1': {}
'@babel/helpers@7.27.4':
'@babel/helpers@7.27.6':
dependencies:
'@babel/template': 7.27.2
'@babel/types': 7.27.3
'@babel/types': 7.27.6
'@babel/parser@7.27.5':
dependencies:
'@babel/types': 7.27.3
'@babel/types': 7.27.6
'@babel/plugin-syntax-jsx@7.27.1(@babel/core@7.27.4)':
dependencies:
@@ -3077,7 +3080,7 @@ snapshots:
'@babel/helper-module-imports': 7.27.1
'@babel/helper-plugin-utils': 7.27.1
'@babel/plugin-syntax-jsx': 7.27.1(@babel/core@7.27.4)
'@babel/types': 7.27.3
'@babel/types': 7.27.6
transitivePeerDependencies:
- supports-color
@@ -3103,7 +3106,7 @@ snapshots:
dependencies:
'@babel/code-frame': 7.27.1
'@babel/parser': 7.27.5
'@babel/types': 7.27.3
'@babel/types': 7.27.6
'@babel/traverse@7.27.4':
dependencies:
@@ -3111,13 +3114,13 @@ snapshots:
'@babel/generator': 7.27.5
'@babel/parser': 7.27.5
'@babel/template': 7.27.2
'@babel/types': 7.27.3
'@babel/types': 7.27.6
debug: 4.4.1
globals: 11.12.0
transitivePeerDependencies:
- supports-color
'@babel/types@7.27.3':
'@babel/types@7.27.6':
dependencies:
'@babel/helper-string-parser': 7.27.1
'@babel/helper-validator-identifier': 7.27.1
@@ -3331,9 +3334,9 @@ snapshots:
'@parcel/watcher-win32-x64': 2.5.1
optional: true
'@rollup/plugin-commonjs@28.0.3(rollup@4.41.1)':
'@rollup/plugin-commonjs@28.0.3(rollup@4.42.0)':
dependencies:
'@rollup/pluginutils': 5.1.4(rollup@4.41.1)
'@rollup/pluginutils': 5.1.4(rollup@4.42.0)
commondir: 1.0.1
estree-walker: 2.0.2
fdir: 6.4.5(picomatch@4.0.2)
@@ -3341,121 +3344,121 @@ snapshots:
magic-string: 0.30.17
picomatch: 4.0.2
optionalDependencies:
rollup: 4.41.1
rollup: 4.42.0
'@rollup/plugin-json@6.1.0(rollup@4.41.1)':
'@rollup/plugin-json@6.1.0(rollup@4.42.0)':
dependencies:
'@rollup/pluginutils': 5.1.4(rollup@4.41.1)
'@rollup/pluginutils': 5.1.4(rollup@4.42.0)
optionalDependencies:
rollup: 4.41.1
rollup: 4.42.0
'@rollup/plugin-node-resolve@16.0.1(rollup@4.41.1)':
'@rollup/plugin-node-resolve@16.0.1(rollup@4.42.0)':
dependencies:
'@rollup/pluginutils': 5.1.4(rollup@4.41.1)
'@rollup/pluginutils': 5.1.4(rollup@4.42.0)
'@types/resolve': 1.20.2
deepmerge: 4.3.1
is-module: 1.0.0
resolve: 1.22.10
optionalDependencies:
rollup: 4.41.1
rollup: 4.42.0
'@rollup/plugin-replace@6.0.2(rollup@4.41.1)':
'@rollup/plugin-replace@6.0.2(rollup@4.42.0)':
dependencies:
'@rollup/pluginutils': 5.1.4(rollup@4.41.1)
'@rollup/pluginutils': 5.1.4(rollup@4.42.0)
magic-string: 0.30.17
optionalDependencies:
rollup: 4.41.1
rollup: 4.42.0
'@rollup/plugin-terser@0.4.4(rollup@4.41.1)':
'@rollup/plugin-terser@0.4.4(rollup@4.42.0)':
dependencies:
serialize-javascript: 6.0.2
smob: 1.5.0
terser: 5.40.0
terser: 5.41.0
optionalDependencies:
rollup: 4.41.1
rollup: 4.42.0
'@rollup/plugin-typescript@12.1.2(rollup@4.41.1)(tslib@2.8.1)(typescript@5.8.3)':
'@rollup/plugin-typescript@12.1.2(rollup@4.42.0)(tslib@2.8.1)(typescript@5.8.3)':
dependencies:
'@rollup/pluginutils': 5.1.4(rollup@4.41.1)
'@rollup/pluginutils': 5.1.4(rollup@4.42.0)
resolve: 1.22.10
typescript: 5.8.3
optionalDependencies:
rollup: 4.41.1
rollup: 4.42.0
tslib: 2.8.1
'@rollup/pluginutils@5.1.4(rollup@4.41.1)':
'@rollup/pluginutils@5.1.4(rollup@4.42.0)':
dependencies:
'@types/estree': 1.0.7
'@types/estree': 1.0.8
estree-walker: 2.0.2
picomatch: 4.0.2
optionalDependencies:
rollup: 4.41.1
rollup: 4.42.0
'@rollup/rollup-android-arm-eabi@4.41.1':
'@rollup/rollup-android-arm-eabi@4.42.0':
optional: true
'@rollup/rollup-android-arm64@4.41.1':
'@rollup/rollup-android-arm64@4.42.0':
optional: true
'@rollup/rollup-darwin-arm64@4.41.1':
'@rollup/rollup-darwin-arm64@4.42.0':
optional: true
'@rollup/rollup-darwin-x64@4.41.1':
'@rollup/rollup-darwin-x64@4.42.0':
optional: true
'@rollup/rollup-freebsd-arm64@4.41.1':
'@rollup/rollup-freebsd-arm64@4.42.0':
optional: true
'@rollup/rollup-freebsd-x64@4.41.1':
'@rollup/rollup-freebsd-x64@4.42.0':
optional: true
'@rollup/rollup-linux-arm-gnueabihf@4.41.1':
'@rollup/rollup-linux-arm-gnueabihf@4.42.0':
optional: true
'@rollup/rollup-linux-arm-musleabihf@4.41.1':
'@rollup/rollup-linux-arm-musleabihf@4.42.0':
optional: true
'@rollup/rollup-linux-arm64-gnu@4.41.1':
'@rollup/rollup-linux-arm64-gnu@4.42.0':
optional: true
'@rollup/rollup-linux-arm64-musl@4.41.1':
'@rollup/rollup-linux-arm64-musl@4.42.0':
optional: true
'@rollup/rollup-linux-loongarch64-gnu@4.41.1':
'@rollup/rollup-linux-loongarch64-gnu@4.42.0':
optional: true
'@rollup/rollup-linux-powerpc64le-gnu@4.41.1':
'@rollup/rollup-linux-powerpc64le-gnu@4.42.0':
optional: true
'@rollup/rollup-linux-riscv64-gnu@4.41.1':
'@rollup/rollup-linux-riscv64-gnu@4.42.0':
optional: true
'@rollup/rollup-linux-riscv64-musl@4.41.1':
'@rollup/rollup-linux-riscv64-musl@4.42.0':
optional: true
'@rollup/rollup-linux-s390x-gnu@4.41.1':
'@rollup/rollup-linux-s390x-gnu@4.42.0':
optional: true
'@rollup/rollup-linux-x64-gnu@4.41.1':
'@rollup/rollup-linux-x64-gnu@4.42.0':
optional: true
'@rollup/rollup-linux-x64-musl@4.41.1':
'@rollup/rollup-linux-x64-musl@4.42.0':
optional: true
'@rollup/rollup-win32-arm64-msvc@4.41.1':
'@rollup/rollup-win32-arm64-msvc@4.42.0':
optional: true
'@rollup/rollup-win32-ia32-msvc@4.41.1':
'@rollup/rollup-win32-ia32-msvc@4.42.0':
optional: true
'@rollup/rollup-win32-x64-msvc@4.41.1':
'@rollup/rollup-win32-x64-msvc@4.42.0':
optional: true
'@rtsao/scc@1.1.0': {}
'@sec-ant/readable-stream@0.4.1': {}
'@sindresorhus/is@7.0.1': {}
'@sindresorhus/is@7.0.2': {}
'@szmarczak/http-timer@5.0.1':
dependencies:
@@ -3469,14 +3472,16 @@ snapshots:
'@types/estree@1.0.7': {}
'@types/estree@1.0.8': {}
'@types/fs-extra@8.1.5':
dependencies:
'@types/node': 22.15.29
'@types/node': 22.15.30
'@types/glob@7.2.0':
dependencies:
'@types/minimatch': 5.1.2
'@types/node': 22.15.29
'@types/node': 22.15.30
'@types/http-cache-semantics@4.0.4': {}
@@ -3486,13 +3491,13 @@ snapshots:
'@types/minimatch@5.1.2': {}
'@types/node@22.15.29':
'@types/node@22.15.30':
dependencies:
undici-types: 6.21.0
'@types/q@1.5.8': {}
'@types/react-dom@19.1.5(@types/react@19.1.6)':
'@types/react-dom@19.1.6(@types/react@19.1.6)':
dependencies:
'@types/react': 19.1.6
@@ -3723,7 +3728,7 @@ snapshots:
autoprefixer@10.4.21(postcss@8.5.4):
dependencies:
browserslist: 4.25.0
caniuse-lite: 1.0.30001720
caniuse-lite: 1.0.30001721
fraction.js: 4.3.7
normalize-range: 0.1.2
picocolors: 1.1.1
@@ -3759,8 +3764,8 @@ snapshots:
browserslist@4.25.0:
dependencies:
caniuse-lite: 1.0.30001720
electron-to-chromium: 1.5.162
caniuse-lite: 1.0.30001721
electron-to-chromium: 1.5.165
node-releases: 2.0.19
update-browserslist-db: 1.1.3(browserslist@4.25.0)
@@ -3810,11 +3815,11 @@ snapshots:
caniuse-api@3.0.0:
dependencies:
browserslist: 4.25.0
caniuse-lite: 1.0.30001720
caniuse-lite: 1.0.30001721
lodash.memoize: 4.1.2
lodash.uniq: 4.5.0
caniuse-lite@1.0.30001720: {}
caniuse-lite@1.0.30001721: {}
capital-case@1.0.4:
dependencies:
@@ -4128,7 +4133,7 @@ snapshots:
eastasianwidth@0.2.0: {}
electron-to-chromium@1.5.162: {}
electron-to-chromium@1.5.165: {}
emoji-regex@8.0.0: {}
@@ -4473,7 +4478,7 @@ snapshots:
cross-spawn: 7.0.6
signal-exit: 4.1.0
form-data-encoder@4.0.2: {}
form-data-encoder@4.1.0: {}
fraction.js@4.3.7: {}
@@ -4601,12 +4606,12 @@ snapshots:
got@14.4.7:
dependencies:
'@sindresorhus/is': 7.0.1
'@sindresorhus/is': 7.0.2
'@szmarczak/http-timer': 5.0.1
cacheable-lookup: 7.0.0
cacheable-request: 12.0.1
decompress-response: 6.0.0
form-data-encoder: 4.0.2
form-data-encoder: 4.1.0
http2-wrapper: 2.2.1
lowercase-keys: 3.0.0
p-cancelable: 4.0.1
@@ -4777,7 +4782,7 @@ snapshots:
is-reference@1.2.1:
dependencies:
'@types/estree': 1.0.7
'@types/estree': 1.0.8
is-regex@1.2.1:
dependencies:
@@ -5552,30 +5557,30 @@ snapshots:
dependencies:
estree-walker: 0.6.1
rollup@4.41.1:
rollup@4.42.0:
dependencies:
'@types/estree': 1.0.7
optionalDependencies:
'@rollup/rollup-android-arm-eabi': 4.41.1
'@rollup/rollup-android-arm64': 4.41.1
'@rollup/rollup-darwin-arm64': 4.41.1
'@rollup/rollup-darwin-x64': 4.41.1
'@rollup/rollup-freebsd-arm64': 4.41.1
'@rollup/rollup-freebsd-x64': 4.41.1
'@rollup/rollup-linux-arm-gnueabihf': 4.41.1
'@rollup/rollup-linux-arm-musleabihf': 4.41.1
'@rollup/rollup-linux-arm64-gnu': 4.41.1
'@rollup/rollup-linux-arm64-musl': 4.41.1
'@rollup/rollup-linux-loongarch64-gnu': 4.41.1
'@rollup/rollup-linux-powerpc64le-gnu': 4.41.1
'@rollup/rollup-linux-riscv64-gnu': 4.41.1
'@rollup/rollup-linux-riscv64-musl': 4.41.1
'@rollup/rollup-linux-s390x-gnu': 4.41.1
'@rollup/rollup-linux-x64-gnu': 4.41.1
'@rollup/rollup-linux-x64-musl': 4.41.1
'@rollup/rollup-win32-arm64-msvc': 4.41.1
'@rollup/rollup-win32-ia32-msvc': 4.41.1
'@rollup/rollup-win32-x64-msvc': 4.41.1
'@rollup/rollup-android-arm-eabi': 4.42.0
'@rollup/rollup-android-arm64': 4.42.0
'@rollup/rollup-darwin-arm64': 4.42.0
'@rollup/rollup-darwin-x64': 4.42.0
'@rollup/rollup-freebsd-arm64': 4.42.0
'@rollup/rollup-freebsd-x64': 4.42.0
'@rollup/rollup-linux-arm-gnueabihf': 4.42.0
'@rollup/rollup-linux-arm-musleabihf': 4.42.0
'@rollup/rollup-linux-arm64-gnu': 4.42.0
'@rollup/rollup-linux-arm64-musl': 4.42.0
'@rollup/rollup-linux-loongarch64-gnu': 4.42.0
'@rollup/rollup-linux-powerpc64le-gnu': 4.42.0
'@rollup/rollup-linux-riscv64-gnu': 4.42.0
'@rollup/rollup-linux-riscv64-musl': 4.42.0
'@rollup/rollup-linux-s390x-gnu': 4.42.0
'@rollup/rollup-linux-x64-gnu': 4.42.0
'@rollup/rollup-linux-x64-musl': 4.42.0
'@rollup/rollup-win32-arm64-msvc': 4.42.0
'@rollup/rollup-win32-ia32-msvc': 4.42.0
'@rollup/rollup-win32-x64-msvc': 4.42.0
fsevents: 2.3.3
run-parallel@1.2.0:
@@ -5836,7 +5841,7 @@ snapshots:
dependencies:
'@types/browserslist': 4.15.4
browserslist: 4.25.0
caniuse-lite: 1.0.30001720
caniuse-lite: 1.0.30001721
css: 2.2.4
he: 1.2.0
known-css-properties: 0.19.0
@@ -5879,7 +5884,7 @@ snapshots:
sentence-case: 3.0.4
split-text-to-chunks: 1.0.0
terser@5.40.0:
terser@5.41.0:
dependencies:
'@jridgewell/source-map': 0.3.6
acorn: 8.14.1
@@ -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({
+48 -134
View File
@@ -1,147 +1,61 @@
import { FC, StrictMode, useEffect, useRef, useState } from 'react';
import styles from './App.module.scss';
import { FC, useCallback, useEffect, useState } from 'react';
import Freighter from './components/freighter/Freighter';
import Pax from './components/pax/Pax';
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 {
dataListener: ViewListener.ViewListener;
commBus: 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> = () => {
const [unit, setUnit] = useState<'lbs' | 'kg'>('lbs');
const [payload, setPayload] = useState<PayloadPax | PayloadFreight>();
const [fuel, setFuel] = useState<Fuel>();
const requestRef = useRef<number | undefined>(undefined);
const mainLoop = () => {
try {
if (SimVar.IsReady()) {
const conversion = SimVar.GetSimVarValue('FUEL WEIGHT PER GALLON', unit);
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),
upper1Left: SimVar.GetSimVarValue('PAYLOAD STATION WEIGHT:4', unit),
cabinCrewFront: SimVar.GetSimVarValue('PAYLOAD STATION WEIGHT:4', unit),
upper1Right: SimVar.GetSimVarValue('PAYLOAD STATION WEIGHT:5', unit),
business1Left: SimVar.GetSimVarValue('PAYLOAD STATION WEIGHT:5', unit),
upper2Left: SimVar.GetSimVarValue('PAYLOAD STATION WEIGHT:6', unit),
business1Center: SimVar.GetSimVarValue('PAYLOAD STATION WEIGHT:6', unit),
upper2Right: SimVar.GetSimVarValue('PAYLOAD STATION WEIGHT:7', unit),
business1Right: SimVar.GetSimVarValue('PAYLOAD STATION WEIGHT:7', unit),
upper3Left: SimVar.GetSimVarValue('PAYLOAD STATION WEIGHT:8', unit),
business2Left: SimVar.GetSimVarValue('PAYLOAD STATION WEIGHT:8', unit),
upper3Right: SimVar.GetSimVarValue('PAYLOAD STATION WEIGHT:9', unit),
business2Center: SimVar.GetSimVarValue('PAYLOAD STATION WEIGHT:9', unit),
upper4Left: SimVar.GetSimVarValue('PAYLOAD STATION WEIGHT:10', unit),
business2Right: SimVar.GetSimVarValue('PAYLOAD STATION WEIGHT:10', unit),
upper4Right: SimVar.GetSimVarValue('PAYLOAD STATION WEIGHT:11', unit),
economy1Left: SimVar.GetSimVarValue('PAYLOAD STATION WEIGHT:11', unit),
lowerForward: SimVar.GetSimVarValue('PAYLOAD STATION WEIGHT:12', unit),
economy1Center: SimVar.GetSimVarValue('PAYLOAD STATION WEIGHT:12', unit),
lowerRear: SimVar.GetSimVarValue('PAYLOAD STATION WEIGHT:13', unit),
economy1Right: SimVar.GetSimVarValue('PAYLOAD STATION WEIGHT:13', unit),
leftAuxF: SimVar.GetSimVarValue('PAYLOAD STATION WEIGHT:14', unit),
economy2Left: SimVar.GetSimVarValue('PAYLOAD STATION WEIGHT:14', unit),
rightAuxF: SimVar.GetSimVarValue('PAYLOAD STATION WEIGHT:15', 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),
});
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,
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,
});
}
} catch {}
requestRef.current = requestAnimationFrame(mainLoop);
};
const App: FC<IAppProps> = ({ commBus }) => {
const [SBUsername, setSBUsername] = useState<string>();
const [WASMData, setWASMData] = useState<WASMDataPax | WASMDataF>();
const [isReady, setIsReady] = useState(false);
// CommBus
const usernameCallback = useCallback((username: string) => {
setSBUsername(username);
setIsReady(true);
}, []);
const wasmCallback = useCallback((data: string) => {
setWASMData(JSON.parse(data));
}, []);
useEffect(() => {
requestRef.current = requestAnimationFrame(mainLoop);
console.log('Initializing CommBus');
if (requestRef.current !== undefined) return () => cancelAnimationFrame(requestRef.current as number);
}, [unit]);
commBus.on(TFDI_SIMBRIEF_USERNAME_EVENT, usernameCallback);
commBus.on(COMM_BUS_LIVE_DATA_EVENT, wasmCallback);
setTimeout(() => {
Coherent.call(COHERENT_COMM_BUS_WASM_CALL, TFDI_SIMBRIEF_USERNAME_CALL, 'null');
}, 1000);
return () => {
commBus.off(TFDI_SIMBRIEF_USERNAME_EVENT, usernameCallback);
commBus.off(COMM_BUS_LIVE_DATA_EVENT, wasmCallback);
};
}, []);
return (
<StrictMode>
<div className={styles.app}>
<button onClick={() => (unit === 'lbs' ? setUnit('kg') : setUnit('lbs'))}>Change unit from {unit}</button>
<div style={{ display: 'flex' }}>
<pre>{JSON.stringify(payload, null, 2)}</pre>
<pre>{JSON.stringify(fuel, null, 2)}</pre>
</div>
<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} />
) : (
<Pax WASMData={WASMData as WASMDataPax} username={SBUsername} />
)
) : (
<h1 className="text-sm font-medium">LOADING</h1>
)}
</div>
</StrictMode>
</div>
);
};
File diff suppressed because it is too large Load Diff
@@ -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. |
@@ -0,0 +1,80 @@
import { FC } from 'react';
interface CGSelectProps {
minCG: number;
maxCG: number;
value: number;
disabled: boolean;
increase: () => void;
decrease: () => void;
}
const CGSelect: FC<CGSelectProps> = ({ minCG, maxCG, value, disabled, increase, decrease }) => {
return (
<div className="relative">
<input
disabled
className="w-full rounded-lg border border-white bg-zinc-700 px-3 py-2 text-white shadow-sm focus:border-blue-600 focus:outline-none focus:ring-blue-600"
value={value.toFixed(1)}
/>
<button
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}
>
{/* FIXME: FONTAWESOME IN EFB */}
<svg
aria-hidden="true"
focusable="false"
data-prefix="fas"
data-icon="caret-up"
className="svg-inline--fa fa-caret-up "
role="img"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 320 512"
style={{
height: '1em',
verticalAlign: '-0.125em',
display: 'inline-block',
boxSizing: 'content-box',
}}
>
<path
fill="currentColor"
d="M182.6 137.4c-12.5-12.5-32.8-12.5-45.3 0l-128 128c-9.2 9.2-11.9 22.9-6.9 34.9s16.6 19.8 29.6 19.8H288c12.9 0 24.6-7.8 29.6-19.8s2.2-25.7-6.9-34.9l-128-128z"
></path>
</svg>
</button>
<button
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}
>
{/* FIXME: FONTAWESOME IN EFB */}
<svg
aria-hidden="true"
focusable="false"
data-prefix="fas"
data-icon="caret-down"
className="svg-inline--fa fa-caret-down "
role="img"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 320 512"
style={{
height: '1em',
verticalAlign: '-0.125em',
display: 'inline-block',
boxSizing: 'content-box',
}}
>
<path
fill="currentColor"
d="M137.4 374.6c12.5 12.5 32.8 12.5 45.3 0l128-128c9.2-9.2 11.9-22.9 6.9-34.9s-16.6-19.8-29.6-19.8L32 192c-12.9 0-24.6 7.8-29.6 19.8s-2.2 25.7 6.9 34.9l128 128z"
></path>
</svg>
</button>
</div>
);
};
export default CGSelect;
@@ -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;
@@ -0,0 +1,227 @@
import { FC, useEffect, useState } from 'react';
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 SBEntryProps {
WASMData: WASMDataPax;
loadingState: LoadingState;
username: string;
setLoadingState: (newState: LoadingState) => void;
}
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' && !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((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-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 SBEntryPax;
@@ -0,0 +1,53 @@
import { FC } from 'react';
import { LoadingState } from '../../types/general';
interface ActionBarProps {
loadingState: LoadingState;
loadDisabled: boolean;
GSXSync: boolean;
GSXActive: boolean;
importSB?: () => void;
load: () => void;
unload: () => void;
}
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' && !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={load}
disabled={loadDisabled}
>
Load
</button>
)}
{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={unload}
>
Unload
</button>
)}
<div className="grow" />
{!!importSB && 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={importSB}
disabled={GSXActive}
>
Import from SimBrief
</button>
)}
</div>
);
};
export default ActionBar;
@@ -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;
@@ -0,0 +1,136 @@
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';
interface PaxProps {
WASMData: WASMDataPax;
username?: string;
}
const Pax: FC<PaxProps> = ({ WASMData, username }) => {
const [selectedTab, setSelectedTab] = useState(0);
const [loadingState, setLoadingState] = useState<LoadingState>('preview');
const upper1 = (overrideState: LoadingState = loadingState) => {
if (overrideState !== 'loaded') return WASMData.targetPayload.business1;
return WASMData.livePayload.business1;
};
const upper2 = (overrideState: LoadingState = loadingState) => {
if (overrideState !== 'loaded') return WASMData.targetPayload.business2;
return WASMData.livePayload.business2;
};
const upper3 = (overrideState: LoadingState = loadingState) => {
if (overrideState !== 'loaded') return WASMData.targetPayload.economy1;
return WASMData.livePayload.economy1;
};
const upper4 = (overrideState: LoadingState = loadingState) => {
if (overrideState !== 'loaded') return WASMData.targetPayload.economy2;
return WASMData.livePayload.economy2;
};
const lower1 = () => {
if (loadingState !== 'loaded' && !GSXActive()) return Math.round(WASMData.targetPayload.forwardCargo);
return Math.round(WASMData.livePayload.forwardCargo);
};
const lower2 = () => {
if (loadingState !== 'loaded' && !GSXActive()) return Math.round(WASMData.targetPayload.rearCargo);
return Math.round(WASMData.livePayload.rearCargo);
};
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="PAX"
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()}`}
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 && (
<SBEntryPax
WASMData={WASMData}
loadingState={loadingState}
username={username}
setLoadingState={setLoadingState}
/>
)}
{((username && selectedTab === 1) || (!username && selectedTab === 0)) && (
<ZFWEntryPax WASMData={WASMData} loadingState={loadingState} setLoadingState={setLoadingState} />
)}
{((username && selectedTab === 2) || (!username && selectedTab === 1)) && (
<StationEntryPax WASMData={WASMData} loadingState={loadingState} setLoadingState={setLoadingState} />
)}
{((username && selectedTab === 3) || (!username && selectedTab === 2)) && (
<OptionsPax WASMData={WASMData} loadingState={loadingState} />
)}
</>
);
};
export default Pax;
@@ -0,0 +1,14 @@
.stroke-zinc-600 {
--tw-bg-opacity: 1;
stroke: rgba(82, 82, 91, var(--tw-bg-opacity));
}
.fill-neutral-500 {
--tw-text-opacity: 1;
fill: rgba(115, 115, 115, var(--tw-text-opacity));
}
.fill-red-500 {
--tw-bg-opacity: 1;
fill: rgba(239, 68, 68, var(--tw-bg-opacity));
}
@@ -0,0 +1,143 @@
import { FC } from 'react';
import styles from './Profile.module.scss';
interface ProfileProps {
type: 'F' | 'PAX';
isER: boolean;
upper1: string;
upper1max?: string;
upper2: string;
upper2max?: string;
upper3: string;
upper3max?: string;
upper4: string;
upper4max?: string;
lower1: string;
lower2: string;
OEW: string;
crew: string;
CGs: [string, boolean, string, boolean];
unit: string;
inPreview: boolean;
}
const Profile: FC<ProfileProps> = ({
type,
isER,
upper1,
upper1max,
upper2,
upper2max,
upper3,
upper3max,
upper4,
upper4max,
lower1,
lower2,
OEW,
crew,
CGs,
unit,
inPreview,
}) => {
const previewClass = inPreview ? styles['fill-neutral-500'] : undefined;
const ZFWCGClass = CGs[1] ? styles['fill-red-500'] : previewClass;
const TOCGClass = CGs[3] ? styles['fill-red-500'] : previewClass;
return (
<svg viewBox="0 0 4002 780" version="1.1" xmlns="http://www.w3.org/2000/svg" className="mb-4">
<path
style={{
fill: 'none',
strokeWidth: 4,
strokeLinecap: 'butt',
strokeLinejoin: 'miter',
}}
className={styles['stroke-zinc-600']}
d="m 1748.2487,624.45529 v 83.5816 z m 653.1368,98.40409 v 43.08593 z"
transform="matrix(1.0068517,0,0,1.0069072,-24.265193,-12.003831)"
/>
<path
style={{
fill: 'none',
stroke: 'white',
strokeWidth: 4,
strokeLinecap: 'butt',
strokeLinejoin: 'round',
}}
d="m 119.50997,573.71703 h 128.0729 v 29.07865 h 119.1481 M 1922.9882,624.6584 V 378.08519 Z M 1143.9838,378.54476 v 246.57126 z m 1556.0004,1.0854 3e-4,245.70686 0.01,-245.70686 z M 119.47872,507.3493 V 686.42638 Z M 681.8277,784.08016 C 550.68986,778.56008 459.37243,767.83734 325.24777,742.2102 247.12441,727.28325 163.85922,704.53832 115.68874,684.96689 65.272866,664.48337 30.640554,635.98924 26.748642,611.79065 c -3.768329,-23.42962 7.455828,-38.32595 50.49813,-67.01953 6.041298,-4.02691 12.708263,-9.27073 14.816577,-11.65295 2.108023,-2.3822 4.524361,-4.48001 4.524361,-4.48001 0,0 45.05507,-44.22564 69.74451,-58.59581 72.48275,-42.18783 238.75927,-76.44031 425.63149,-87.67895 14.00372,-0.84197 33.99829,-2.07064 44.43261,-2.72959 26.21726,-1.65646 1973.24248,-2.45294 2062.36198,-0.84445 156.7316,2.82998 269.5005,7.74134 530.5511,23.10724 47.1495,2.7752 85.8534,4.90642 86.012,4.73564 0.6463,-0.69433 3.18,-46.35302 2.6116,-47.00235 -0.3392,-0.38606 -8.4798,-1.63074 -18.0917,-2.7653 -35.3422,-4.17401 -67.399,-11.82474 -77.0779,-18.39697 -3.9158,-2.65808 -3.9645,-3.95085 -1.9416,-51.11949 2.108,-49.16104 3.1187,-81.48815 3.1285,-100.00521 0,-21.77363 -0.1657,-21.37816 11.1206,-24.94772 37.4058,-11.83133 117.8811,-11.06942 171.1122,1.62031 15.227,3.62986 19.589,3.51496 35.5372,-0.93615 21.7001,-6.05753 21.0601,-5.51568 96.6373,-82.052719 33.1386,-33.558758 68.757,-66.037569 68.757,-66.037569 0,0 83.3796,-1.079949 169.2388,-1.079949 136.9782,0 171.6165,0.253341 171.2179,1.25017 -4.4107,11.004128 -56.5812,125.499597 -58.6917,128.808777 -4.6101,7.22481 -3.2139,7.88313 16.7587,7.90201 9.0622,0.008 22.5343,1.10293 37.2289,3.0234 4.1187,0.5386 15.3536,1.65343 24.9606,2.47749 9.6122,0.82422 19.8325,1.75756 22.7175,2.07418 5.0681,0.55713 9.0514,198.40717 3.9934,198.38178 -3.6049,-0.0227 -31.7008,3.23584 -34.6991,4.01865 -1.9198,0.50162 -6.9752,1.19264 -11.2312,1.53478 -7.7386,0.62215 -7.7386,0.62215 -7.7386,8.4184 0,8.93284 0.045,8.97847 9.985,9.03089 7.595,0.034 9.8124,1.63453 3.4137,2.45321 -2.7018,0.34575 -6.0356,0.83238 -7.4075,1.08266 -1.3721,0.25018 -13.4624,0.89408 -26.8658,1.43238 -13.4009,0.53851 -28.9024,1.4418 -34.4462,2.00812 -15.6072,1.59497 -41.7208,3.01042 -55.6346,3.01554 -20.6343,0.008 -19.0304,-1.48851 -18.6619,17.4164 0.3714,19.01843 2.3134,23.86211 11.5516,28.7958 5.5848,2.98376 0.3035,2.54795 88.3399,7.28999 84.7141,4.56302 75.158,-2.81091 75.158,57.97778 0,54.09028 0.038,53.96894 -18.7912,59.84504 -20.4081,6.36957 -118.4497,34.30825 -182.9044,52.12181 -74.4105,20.56545 -152.6321,42.51798 -160.2541,44.9738 -10.5871,3.41069 -57.1162,16.38817 -105.4333,29.40502 -184.6228,49.73829 -402.0471,89.78228 -516.1218,95.05681 -19.1654,0.88577 -2300.07154,1.25614 -2320.9699,0.37695 z m 1714.3911,-15.93638 c 14.3101,-1.72862 35.0046,-5.59211 45.932,-8.57466 47.3734,-12.93067 34.3571,-20.57346 -70.3941,-41.33854 -9.3343,-1.85054 -21.9156,-4.53045 -27.9568,-5.955 -119.2244,-28.11802 -135.9358,-31.16723 -227.3866,-41.48667 -32.4779,-3.66487 -84.0049,-11.3955 -126.5748,-18.9901 -77.6003,-13.84405 -129.5471,-21.9553 -156.762,-24.47858 -178.2016,-16.52165 -260.2497,38.68714 -109.1224,73.42801 7.2586,1.66798 18.9422,5.29576 25.9629,8.06195 39.3007,15.48166 111.0211,26.35086 233.4296,35.37682 97.5092,7.1897 247.1876,10.13705 247.9345,4.88196 0.6641,-4.66361 1.511,-4.79998 36.7154,-5.88569 22.9808,-0.70847 26.3783,-0.21481 26.3783,3.83836 0,2.5877 2.9594,14.02473 3.8762,14.97665 0.4007,0.41452 15.6685,2.27843 33.9288,4.14116 18.264,1.86268 33.4272,3.60903 33.698,3.88056 0.7657,0.76635 16.5438,-0.20912 30.341,-1.87623 z m -2029.36746,-359.3222 -0.0248,215.97654 1275.64716,-4.1e-4 h 1275.1949 l 132.9522,-2.46652 132.952,-2.4665 147.9241,-11.4452 147.9243,-11.4452 1.0236,-90.88061 1.0235,-90.88061 -83.3015,-4.35422 -83.3014,-4.35424 m -2614.52231,217.81122 -5e-5,159.11801 z M 1748.1434,708.5565 v 75.45385 z m 1663.0399,-106.30033 -1e-4,113.31756 z m -1009.9445,22.54108 v 99.39317 z m -4e-4,143.38207 v 15.78331 z"
transform="matrix(1.0068517,0,0,1.0069072,-24.265193,-12.003831)"
/>
<text style={{ fill: 'white', fontSize: '160px' }} x="725.61609" y="591.34473" textAnchor="middle">
<tspan className={previewClass}>{upper1}</tspan>
{upper1max && <tspan>/{upper1max}</tspan>}
</text>
<text style={{ fill: 'white', fontSize: '160px' }} x="1509.024" y="591.34473" textAnchor="middle">
<tspan className={previewClass}>{upper2}</tspan>
{upper2max && <tspan>/{upper2max}</tspan>}
</text>
<text style={{ fill: 'white', fontSize: '160px' }} x="2292.3511" y="591.34473" textAnchor="middle">
<tspan className={previewClass}>{upper3}</tspan>
{upper3max && <tspan>/{upper3max}</tspan>}
</text>
<text style={{ fill: 'white', fontSize: '160px' }} x="3075.8955" y="591.34473" textAnchor="middle">
<tspan className={previewClass}>{upper4}</tspan>
{upper4max && <tspan>/{upper4max}</tspan>}
</text>
<text style={{ fill: 'white', fontSize: '160px' }} x="1197.6641" y="754.35504" textAnchor="middle">
<tspan className={previewClass}>{lower1}</tspan>
</text>
<text style={{ fill: 'white', fontSize: '160px' }} x="2891.1475" y="754.35504" textAnchor="middle">
<tspan className={previewClass}>{lower2}</tspan>
</text>
<text style={{ fill: 'white', fontSize: '160px' }} x="0" y="280.10175">
{type === 'F' ? 'Pilots:' : 'Pilots & FAs:'}
</text>
<text style={{ fill: 'white', fontSize: '160px' }} x="1476.2501" y="280.10175" textAnchor="end">
<tspan className={previewClass}>{crew}</tspan>
</text>
<text style={{ fill: 'white', fontSize: '160px' }} x="0" y="130.625">
OEW:
</text>
<text style={{ fill: 'white', fontSize: '160px' }} x="1476.2501" y="130.625" textAnchor="end">
{OEW}
</text>
<text style={{ fill: 'white', fontSize: '100px' }} x="4002" y="778.24402" textAnchor="end">
<tspan style={{ fontSize: '70px' }}>all in </tspan>
<tspan>{unit}</tspan>
</text>
<text style={{ fill: 'white', fontSize: '160px' }} x="1730.4194" y="142.15625">
ZFWCG:
</text>
<text style={{ fill: 'white', fontSize: '160px' }} x="2540.771" y="142.15625">
<tspan className={ZFWCGClass}>{CGs[0]}</tspan>
</text>
<text style={{ fill: 'white', fontSize: '160px' }} x="1730.4194" y="288.875">
TOCG:
</text>
<text style={{ fill: 'white', fontSize: '160px' }} x="2540.771" y="288.875">
<tspan className={TOCGClass}>{CGs[2]}</tspan>
</text>
<path
style={{
fill: 'none',
stroke: 'white',
strokeWidth: 8,
strokeLinecap: 'butt',
strokeLinejoin: 'round',
opacity: isER ? 1 : 0,
}}
d="m 3616.1269,203.67131 -115.4682,116.32951 h 76.6132 l 13.6484,-13.75016 h -61.1499 l 42.8836,-43.20365 h 61.1499 l 13.6485,-13.75016 h -61.1499 l 31.6393,-31.87538 h 61.1499 l 13.6484,-13.75016 z m 101.1357,0 -115.4682,116.32951 h 15.4631 l 45.9082,-46.25055 h 21.7891 l -7.0158,46.25055 h 20.0709 l 6.7491,-50.85999 c 10.2365,-2.8646 20.2552,-7.10948 30.0559,-12.73452 9.8522,-5.67714 18.9402,-12.70852 27.2636,-21.09401 6.1521,-6.19797 10.0211,-11.30222 11.6068,-15.31268 1.6896,-4.06255 1.7441,-7.42197 0.1635,-10.07824 -1.4223,-2.34378 -4.0367,-3.95839 -7.8438,-4.84382 -3.7552,-0.93749 -9.1472,-1.40626 -16.176,-1.40625 z m 2.2801,13.2814 h 18.1967 c 4.165,0 7.4735,0.31252 9.9248,0.93751 2.5032,0.57292 4.1244,1.61462 4.8641,3.12503 0.9495,1.77087 0.7045,3.9584 -0.735,6.56258 -1.3356,2.55212 -3.6579,5.49487 -6.9666,8.82824 -4.3426,4.37505 -8.5084,7.9949 -12.4972,10.8595 -3.8849,2.81253 -8.0847,5.31258 -12.5989,7.50009 -4.8776,2.34378 -9.5781,3.95838 -14.1015,4.84381 -4.4716,0.83333 -9.1546,1.25002 -14.0487,1.25002 h -15.6194 z"
/>
</svg>
);
};
export default Profile;
@@ -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;
@@ -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 { WASMDataPax } from '../../types/WASMData';
import { CoherentCallStationEntryPax, inRangeOf, loadAircraft, unloadAircraft } from '../../utils/utils';
import ActionBar from '../actionbar/ActionBar';
interface StationEntryProps {
WASMData: WASMDataPax;
loadingState: LoadingState;
setLoadingState: (newState: LoadingState) => void;
}
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' && !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 = () => {
CoherentCallStationEntryPax(business1, business2, economy1, economy2, forwardCargo, rearCargo);
};
useEffect(() => updateData(), [business1, business2, economy1, economy2, forwardCargo, rearCargo]);
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>Business</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={business1}
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">
<label>Premium Economy</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={business2}
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">
<label>Forward Economy</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={economy1}
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">
<label>Aft Economy</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={economy2}
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 ({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, 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 ({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, 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-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 StationEntryPax;
@@ -0,0 +1,27 @@
import { FC } from 'react';
interface TabbarProps {
tabs: string[];
selectedTab: number;
setSelectedTab: (tab: number) => void;
}
const Tabbar: FC<TabbarProps> = ({ tabs, selectedTab, setSelectedTab }) => {
return (
<ul className="mb-4 flex list-none flex-row flex-wrap border-b-0 pl-0">
{tabs.map((tab, i) => (
<li key={`${tab}-${i}`}>
<button
key={i}
className={`${selectedTab === i ? 'text-white underline' : 'text-neutral-500'} my-2 block border-x-0 border-b-2 border-t-0 border-slate-100 bg-zinc-900 px-7 text-sm font-medium uppercase`}
onClick={() => setSelectedTab(i)}
>
{tab}
</button>
</li>
))}
</ul>
);
};
export default Tabbar;
@@ -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;
@@ -0,0 +1,221 @@
import { FC, useEffect, useState } from 'react';
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 ZFWEntryProps {
WASMData: WASMDataPax;
loadingState: LoadingState;
setLoadingState: (newState: LoadingState) => void;
}
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' && !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 ZFWEntryPax;
+20 -6
View File
@@ -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;
@@ -5,3 +5,11 @@
font-weight: 300;
src: url(assets/fonts/Roboto-Light.ttf) format('truetype');
}
@font-face {
font-family: 'Roboto';
font-style: italic;
font-display: swap;
font-weight: 300;
src: url(assets/fonts/Roboto-LightItalic.ttf) format('truetype');
}
@@ -5,3 +5,11 @@
font-weight: 400;
src: url(assets/fonts/Roboto-Regular.ttf) format('truetype');
}
@font-face {
font-family: 'Roboto';
font-style: italic;
font-display: swap;
font-weight: 400;
src: url(assets/fonts/Roboto-Italic.ttf) format('truetype');
}
@@ -5,3 +5,11 @@
font-weight: 500;
src: url(assets/fonts/Roboto-Medium.ttf) format('truetype');
}
@font-face {
font-family: 'Roboto';
font-style: italic;
font-display: swap;
font-weight: 500;
src: url(assets/fonts/Roboto-MediumItalic.ttf) format('truetype');
}
@@ -5,3 +5,11 @@
font-weight: 700;
src: url(assets/fonts/Roboto-Bold.ttf) format('truetype');
}
@font-face {
font-family: 'Roboto';
font-style: italic;
font-display: swap;
font-weight: 700;
src: url(assets/fonts/Roboto-BoldItalic.ttf) format('truetype');
}
+1
View File
@@ -7,6 +7,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" href="/SCSS/common.css" />
<link rel="stylesheet" href="assets/efb.css" />
<link rel="stylesheet" href="index.css" />
<script type="text/javascript" src="/JS/coherent.js"></script>
+7 -1
View File
@@ -3,6 +3,8 @@ import { createRoot } from 'react-dom/client';
import App from './App';
class TFDiDesignMD11LoadManagerPanel extends TemplateElement {
private commBus: ViewListener.ViewListener | undefined;
constructor() {
super();
}
@@ -10,16 +12,20 @@ class TFDiDesignMD11LoadManagerPanel extends TemplateElement {
connectedCallback() {
super.connectedCallback();
this.commBus = RegisterViewListener('JS_LISTENER_COMM_BUS');
const container = document.getElementById('react');
if (container) {
console.log('Starting React');
const root = createRoot(container);
root.render(createElement(App));
root.render(createElement(App, { commBus: this.commBus }));
}
}
disconnectedCallback() {
super.disconnectedCallback();
this.commBus?.unregister();
}
}
@@ -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;
}
@@ -0,0 +1,56 @@
const getSimBriefFlightPlan = async (simBriefUsername: string) => {
const flightPlanURL = `https://www.simbrief.com/api/xml.fetcher.php?username=${simBriefUsername}&json=1`;
let response: Response;
let success = false;
try {
response = await fetch(flightPlanURL);
success = true;
//eslint-disable-next-line @typescript-eslint/no-explicit-any
} catch (e: any) {
response = e.response;
}
return {
success,
data: await response.json(),
};
};
export const ImportFlightPlan = async (
username: string,
maxZFW: number,
maxTOW: number,
maxFuel: number,
isImperial: boolean
) => {
const flightPlan = await getSimBriefFlightPlan(username);
if (!flightPlan.success) {
return {
type: 'error',
message: flightPlan.data.status,
};
}
const data = flightPlan.data;
if (!['MD11', 'MD1F'].includes(data.aircraft.icao_code)) {
return {
type: 'error',
message: `Your SimBrief plan is not for a MD-11`,
};
}
let convFactor = 1;
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(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(maxFuel, Math.round(data.fuel.plan_ramp * convFactor)),
},
};
};
+134
View File
@@ -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,
})
);
};
+2 -2
View File
@@ -12,7 +12,7 @@
// "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */
/* Language and Environment */
"target": "es2017",
"target": "es6",
/* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
"lib": ["es2017", "dom"],
/* Specify a set of bundled library declaration files that describe the target runtime environment. */
@@ -29,7 +29,7 @@
// "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */
/* Modules */
"module": "es2015",
"module": "es6",
/* Specify what module code is generated. */
// "rootDir": "./", /* Specify the root folder within your source files. */
"moduleResolution": "node",
File diff suppressed because it is too large Load Diff
@@ -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"
+306
View File
@@ -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);
}
+111
View File
@@ -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
+45
View File
@@ -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>
+323
View File
@@ -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);
}
+147
View File
@@ -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);
+131
View File
@@ -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;
+21
View File
@@ -0,0 +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
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?
+65
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
+4
View File
@@ -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
+4
View File
@@ -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"]
}
}