Skip to content

Commit

Permalink
fix(EFB): Fuel capacity lookup
Browse files Browse the repository at this point in the history
  • Loading branch information
masterrob94 committed Feb 28, 2024
1 parent a1d3d99 commit 55c6a66
Show file tree
Hide file tree
Showing 6 changed files with 112 additions and 103 deletions.
2 changes: 1 addition & 1 deletion hsim-a321neo/src/wasm/systems/a320_systems/src/fuel/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ impl A320Fuel {
FuelInfo {
fuel_tank_id: "FUEL TANK CENTER QUANTITY",
position: (-20.53, 0., 1.),
total_capacity_gallons: 2117.,
total_capacity_gallons: 3698.,
},
FuelInfo {
fuel_tank_id: "FUEL TANK LEFT MAIN QUANTITY",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,14 @@
// Copyright (c) 2023-2024 FlyByWire Simulations
// SPDX-License-Identifier: GPL-3.0

/* eslint-disable max-len */
import React, { useState } from 'react';
import { getAirframeType } from '../../../Efb'; //DO NOT REMOVE UNDER ANY CIRCUMSTANCES
import { Fuel } from './Constants' //DO NOT REMOVE UNDER ANY CIRCUMSTANCES
import { Units, usePersistentNumberProperty, usePersistentProperty, useSimVar } from '@flybywiresim/fbw-sdk';
import { OverWingOutline, ProgressBar, SelectGroup, SelectItem, SimpleInput, TooltipWrapper, getAirframeType, t } from '@flybywiresim/flypad'; // BE CAREFUL
import { round } from 'lodash';
import { CloudArrowDown, PlayFill, StopCircleFill } from 'react-bootstrap-icons';
import { useSimVar, Units, usePersistentNumberProperty, usePersistentProperty } from '@flybywiresim/fbw-sdk';
import Slider from 'rc-slider';
import { t } from '../../../translation';
import { TooltipWrapper } from '../../../UtilComponents/TooltipWrapper';
import { isSimbriefDataLoaded } from '../../../Store/features/simBrief';
import { useAppSelector } from '../../../Store/store';
import { SelectGroup, SelectItem } from '../../../UtilComponents/Form/Select';
import { ProgressBar } from '../../../UtilComponents/Progress/Progress';
import { SimpleInput } from '../../../UtilComponents/Form/SimpleInput/SimpleInput';
import { OverWingOutline } from '../../../Assets/OverWingOutline';
import React, { useState } from 'react';
import { CloudArrowDown, PlayFill, StopCircleFill } from 'react-bootstrap-icons';
import { FuelCapacity } from './Constants'; //CUSTOM LOOKUP BY HORIZON SIMULATIONS

interface TankReadoutProps {
title: string;
Expand All @@ -32,7 +27,7 @@ const TankReadoutWidget = ({ title, current, target, capacity, currentUnit, tank
const getFuelBarPercent = (curr: number, max: number) => (Math.max(curr, 0) / max) * 100;

return (
<div className={`bg-theme-body w-min space-y-3 overflow-hidden p-4 ${className}`} style={{ width: `${width}px` }}>
<div className={`w-min space-y-3 overflow-hidden bg-theme-body p-4 ${className}`} style={{ width: `${width}px` }}>
<div className={inlinedTitle ? 'flex flex-row items-center justify-between' : undefined}>
<h2>{title}</h2>
<p>{`${convertedFuelValue}/${round(tankValue)} ${currentUnit}`}</p>
Expand All @@ -50,30 +45,37 @@ const TankReadoutWidget = ({ title, current, target, capacity, currentUnit, tank
);
};

export const FuelPage = () => {
interface FuelProps {
simbriefDataLoaded: boolean,
simbriefPlanRamp: number,
simbriefUnits: string,
massUnitForDisplay: string,
convertUnit: number,
isOnGround: boolean,
}
export const A320Fuel: React.FC<FuelProps> = ({
simbriefDataLoaded,
simbriefPlanRamp,
simbriefUnits,
massUnitForDisplay,
convertUnit,
isOnGround,
}) => {
const [airframe] = useState(getAirframeType());
const TOTAL_FUEL_GALLONS = Fuel[(airframe !== null ? airframe : 'A320_214')].total;
const OUTER_CELL_GALLONS = Fuel[(airframe !== null ? airframe : 'A320_214')].outer_cell;
const INNER_CELL_GALLONS = Fuel[(airframe !== null ? airframe : 'A320_214')].inner_cell;
const CENTER_TANK_GALLONS = Fuel[(airframe !== null ? airframe : 'A320_214')].center;
const TOTAL_FUEL_GALLONS = FuelCapacity[(airframe !== null ? airframe : 'A320_214')].total;
const OUTER_CELL_GALLONS = FuelCapacity[(airframe !== null ? airframe : 'A320_214')].outer_cell;
const INNER_CELL_GALLONS = FuelCapacity[(airframe !== null ? airframe : 'A320_214')].inner_cell;
const CENTER_TANK_GALLONS = FuelCapacity[(airframe !== null ? airframe : 'A320_214')].center;
const wingTotalRefuelTimeSeconds = 1020;
const CenterTotalRefuelTimeSeconds = 180;

const { usingMetric } = Units;
const [currentUnit] = useState(usingMetric ? 'KG' : 'LB');
const [convertUnit] = useState(usingMetric ? 1 : (1 / 0.4535934));

const [galToKg] = useSimVar('FUEL WEIGHT PER GALLON', 'kilograms', 1_000);
const outerCell = () => OUTER_CELL_GALLONS * galToKg * convertUnit;
const outerCells = () => outerCell() * 2;
const innerCell = () => INNER_CELL_GALLONS * galToKg * convertUnit;
const innerCells = () => innerCell() * 2;
const centerTank = () => CENTER_TANK_GALLONS * galToKg * convertUnit;
const totalFuel = () => centerTank() + innerCells() + outerCells();
const [busDC2] = useSimVar('L:A32NX_ELEC_DC_2_BUS_IS_POWERED', 'Bool', 1_000);
const [busDCHot1] = useSimVar('L:A32NX_ELEC_DC_HOT_1_BUS_IS_POWERED', 'Bool', 1_000);
const [simGroundSpeed] = useSimVar('GPS GROUND SPEED', 'knots', 1_000);
const [isOnGround] = useSimVar('SIM ON GROUND', 'Bool', 1_000);
const [eng1Running] = useSimVar('ENG COMBUSTION:1', 'Bool', 1_000);
const [eng2Running] = useSimVar('ENG COMBUSTION:2', 'Bool', 1_000);
const [refuelRate, setRefuelRate] = usePersistentProperty('REFUEL_RATE_SETTING');
Expand All @@ -97,17 +99,13 @@ export const FuelPage = () => {
const [gsxFuelHoseConnected] = useSimVar('L:FSDT_GSX_FUELHOSE_CONNECTED', 'Number');
const [gsxRefuelState] = useSimVar('L:FSDT_GSX_REFUELING_STATE', 'Number');

const { units } = useAppSelector((state) => state.simbrief.data);
const { planRamp } = useAppSelector((state) => state.simbrief.data.fuels);
const simbriefDataLoaded = isSimbriefDataLoaded();

const gsxRefuelActive = () => (gsxRefuelState === 4 || gsxRefuelState === 5);

const isAirplaneCnD = () => !(simGroundSpeed > 0.1 || eng1Running || eng2Running || !isOnGround || (!busDC2 && !busDCHot1));
const canRefuel = () => !(eng1Running || eng2Running || !isOnGround);

const airplaneCanRefuel = () => {
if (refuelRate !== '2') {
if (!isAirplaneCnD()) {
if (!canRefuel()) {
setRefuelRate('2');
}
}
Expand All @@ -118,7 +116,7 @@ export const FuelPage = () => {
}

// In-flight refueling with GSX Sync enabled
return !isAirplaneCnD() && refuelRate === '2';
return !canRefuel() && refuelRate === '2';
}
return true;
};
Expand Down Expand Up @@ -270,18 +268,18 @@ export const FuelPage = () => {
};

const handleFuelAutoFill = () => {
let fuelToLoad = -1;
let fuelToLoad: number;

if (usingMetric) {
if (units === 'kgs') {
fuelToLoad = roundUpNearest100(planRamp);
if (Units.usingMetric) {
if (simbriefUnits === 'kgs') {
fuelToLoad = roundUpNearest100(simbriefPlanRamp);
} else {
fuelToLoad = roundUpNearest100(Units.poundToKilogram(planRamp));
fuelToLoad = roundUpNearest100(Units.poundToKilogram(simbriefPlanRamp));
}
} else if (units === 'kgs') {
fuelToLoad = roundUpNearest100(Units.kilogramToPound(planRamp));
} else if (simbriefUnits === 'kgs') {
fuelToLoad = roundUpNearest100(Units.kilogramToPound(simbriefPlanRamp));
} else {
fuelToLoad = roundUpNearest100(planRamp);
fuelToLoad = roundUpNearest100(simbriefPlanRamp);
}

updateDesiredFuel(fuelToLoad.toString());
Expand All @@ -290,18 +288,18 @@ export const FuelPage = () => {
const roundUpNearest100 = (plannedFuel: number) => Math.ceil(plannedFuel / 100) * 100;

return (
<div className="h-content-section-reduced relative mt-6 flex flex-col justify-between">
<div className="relative mt-6 flex h-content-section-reduced flex-col justify-between">
<div className="z-30">
<div className="absolute inset-x-0 top-0 mx-auto flex flex-col items-center space-y-3">
<TankReadoutWidget
title={t('Ground.Fuel.TotalFuel')}
current={totalCurrent()}
target={totalTarget}
capacity={totalFuel()}
currentUnit={currentUnit}
currentUnit={massUnitForDisplay}
tankValue={totalFuel()}
convertedFuelValue={totalCurrent()}
className="border-theme-accent overflow-hidden rounded-2xl border-2"
className="overflow-hidden rounded-2xl border-2 border-theme-accent"
inlinedTitle
width={420}
/>
Expand All @@ -310,22 +308,22 @@ export const FuelPage = () => {
current={centerCurrent}
target={centerTarget}
capacity={CENTER_TANK_GALLONS}
currentUnit={currentUnit}
currentUnit={massUnitForDisplay}
tankValue={centerTank()}
convertedFuelValue={convertFuelValueCenter(centerCurrent)}
className="border-theme-accent overflow-hidden rounded-2xl border-2"
className="overflow-hidden rounded-2xl border-2 border-theme-accent"
inlinedTitle
width={420}
/>
</div>
<div className="absolute inset-x-0 top-40 flex flex-row justify-between">
<div className="border-theme-accent divide-theme-accent w-min divide-y overflow-hidden rounded-2xl border-2">
<div className="w-min divide-y divide-theme-accent overflow-hidden rounded-2xl border-2 border-theme-accent">
<TankReadoutWidget
title={t('Ground.Fuel.LeftInnerTank')}
current={LInnCurrent}
target={LInnTarget}
capacity={INNER_CELL_GALLONS}
currentUnit={currentUnit}
currentUnit={massUnitForDisplay}
tankValue={innerCell()}
convertedFuelValue={convertFuelValue(LInnCurrent)}
/>
Expand All @@ -334,18 +332,18 @@ export const FuelPage = () => {
current={LOutCurrent}
target={LOutTarget}
capacity={OUTER_CELL_GALLONS}
currentUnit={currentUnit}
currentUnit={massUnitForDisplay}
tankValue={outerCell()}
convertedFuelValue={convertFuelValueCenter(LOutCurrent)}
/>
</div>
<div className="border-theme-accent divide-theme-accent w-min divide-y overflow-hidden rounded-2xl border-2">
<div className="w-min divide-y divide-theme-accent overflow-hidden rounded-2xl border-2 border-theme-accent">
<TankReadoutWidget
title={t('Ground.Fuel.RightInnerTank')}
current={RInnCurrent}
target={RInnTarget}
capacity={INNER_CELL_GALLONS}
currentUnit={currentUnit}
currentUnit={massUnitForDisplay}
tankValue={innerCell()}
convertedFuelValue={convertFuelValueCenter(RInnCurrent)}
/>
Expand All @@ -354,7 +352,7 @@ export const FuelPage = () => {
current={ROutCurrent}
target={ROutTarget}
capacity={OUTER_CELL_GALLONS}
currentUnit={currentUnit}
currentUnit={massUnitForDisplay}
tankValue={outerCell()}
convertedFuelValue={convertFuelValueCenter(ROutCurrent)}
/>
Expand Down Expand Up @@ -388,22 +386,22 @@ export const FuelPage = () => {
/>
{/* tl overlay */}
<div
className="bottom-overlay-t-y left-overlay-tl bg-theme-body -rotate-26.5 absolute z-10"
className="absolute bottom-overlay-t-y left-overlay-tl z-10 -rotate-26.5 bg-theme-body"
style={{ transform: 'rotate(-26.5deg)', width: '490px', height: '140px', bottom: '240px', left: '82px' }}
/>
{/* tr overlay */}
<div
className="right-overlay-tr bottom-overlay-t-y bg-theme-body rotate-26.5 absolute z-10"
className="absolute bottom-overlay-t-y right-overlay-tr z-10 rotate-26.5 bg-theme-body"
style={{ transform: 'rotate(26.5deg)', width: '490px', height: '140px', bottom: '240px', right: '82px' }}
/>
{/* bl overlay */}
<div
className="bottom-overlay-b-y left-overlay-bl bg-theme-body -rotate-18.5 absolute z-10"
className="absolute bottom-overlay-b-y left-overlay-bl z-10 -rotate-18.5 bg-theme-body"
style={{ transform: 'rotate(-18.5deg)', width: '484px', height: '101px', bottom: '78px', left: '144px' }}
/>
{/* br overlay */}
<div
className="right-overlay-br bottom-overlay-b-y bg-theme-body rotate-18.5 absolute z-10"
className="absolute bottom-overlay-b-y right-overlay-br z-10 rotate-18.5 bg-theme-body"
style={{ transform: 'rotate(18.5deg)', width: '484px', height: '101px', bottom: '78px', right: '144px' }}
/>
</div>
Expand Down Expand Up @@ -434,12 +432,12 @@ export const FuelPage = () => {
value={inputValue}
onChange={(x) => updateDesiredFuel(x)}
/>
<div className="absolute right-4 top-2 text-lg text-gray-400">{currentUnit}</div>
<div className="absolute right-4 top-2 text-lg text-gray-400">{massUnitForDisplay}</div>
</div>
{simbriefDataLoaded && (
<TooltipWrapper text={t('Ground.Fuel.TT.FillBlockFuelFromSimBrief')}>
<div
className="text-theme-body hover:text-theme-highlight bg-theme-highlight hover:bg-theme-body border-theme-highlight flex h-auto items-center justify-center rounded-md rounded-l-none border-2 px-2 transition duration-100"
className="flex h-auto items-center justify-center rounded-md rounded-l-none border-2 border-theme-highlight bg-theme-highlight px-2 text-theme-body transition duration-100 hover:bg-theme-body hover:text-theme-highlight"
onClick={simbriefDataLoaded ? handleFuelAutoFill : undefined}
>
<CloudArrowDown size={26} />
Expand All @@ -463,21 +461,21 @@ export const FuelPage = () => {
)}
</div>

<div className="border-theme-accent absolute bottom-0 right-6 flex flex-col items-center justify-center space-y-2 overflow-x-hidden rounded-2xl border px-6 py-3">
<div className="absolute bottom-0 right-6 flex flex-col items-center justify-center space-y-2 overflow-x-hidden rounded-2xl border border-theme-accent px-6 py-3">
<h2 className="flex font-medium">{t('Ground.Fuel.RefuelTime')}</h2>

<SelectGroup>
<SelectItem selected={isAirplaneCnD() ? refuelRate === '2' : !isAirplaneCnD()} onSelect={() => setRefuelRate('2')}>{t('Settings.Instant')}</SelectItem>
<SelectItem selected={canRefuel() ? refuelRate === '2' : !canRefuel()} onSelect={() => setRefuelRate('2')}>{t('Settings.Instant')}</SelectItem>

<TooltipWrapper text={`${!isAirplaneCnD() && t('Ground.Fuel.TT.AircraftMustBeColdAndDarkToChangeRefuelTimes')}`}>
<TooltipWrapper text={`${!canRefuel() && t('Ground.Fuel.TT.AircraftMustBeColdAndDarkToChangeRefuelTimes')}`}>
<div>
<SelectItem className={`${!isAirplaneCnD() && 'opacity-20'}`} disabled={!isAirplaneCnD()} selected={refuelRate === '1'} onSelect={() => setRefuelRate('1')}>{t('Settings.Fast')}</SelectItem>
<SelectItem className={`${!canRefuel() && 'opacity-20'}`} disabled={!canRefuel()} selected={refuelRate === '1'} onSelect={() => setRefuelRate('1')}>{t('Settings.Fast')}</SelectItem>
</div>
</TooltipWrapper>

<TooltipWrapper text={`${!isAirplaneCnD() && t('Ground.Fuel.TT.AircraftMustBeColdAndDarkToChangeRefuelTimes')}`}>
<TooltipWrapper text={`${!canRefuel() && t('Ground.Fuel.TT.AircraftMustBeColdAndDarkToChangeRefuelTimes')}`}>
<div>
<SelectItem className={`${!isAirplaneCnD() && 'opacity-20'}`} disabled={!isAirplaneCnD()} selected={refuelRate === '0'} onSelect={() => setRefuelRate('0')}>{t('Settings.Real')}</SelectItem>
<SelectItem className={`${!canRefuel() && 'opacity-20'}`} disabled={!canRefuel()} selected={refuelRate === '0'} onSelect={() => setRefuelRate('0')}>{t('Settings.Real')}</SelectItem>
</div>
</TooltipWrapper>
</SelectGroup>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export const Fuel = Object.freeze({
export const FuelCapacity = Object.freeze({
A318_115: { total: 6303, outer_cell: 228, inner_cell: 1816, center: 2215},
A318_ACJ: { total: 6303, outer_cell: 228, inner_cell: 1816, center: 2215},
A318_BAW: { total: 6303, outer_cell: 228, inner_cell: 1816, center: 2215},
Expand All @@ -16,4 +16,4 @@ export const Fuel = Object.freeze({
A321_271N: { total: 6205, outer_cell: 228, inner_cell: 1816, center: 2117},
A321_271NX: { total: 6205, outer_cell: 228, inner_cell: 1816, center: 2117},
A321_271N_LR: { total: 7786, outer_cell: 228, inner_cell: 1816, center: 3698},
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// Copyright (c) 2023-2024 FlyByWire Simulations
// SPDX-License-Identifier: GPL-3.0

/* eslint-disable max-len */
import { Units, useSimVar } from '@flybywiresim/fbw-sdk';
import { isSimbriefDataLoaded } from '@flybywiresim/flypad';
import React, { useState } from 'react';
import { useAppSelector } from '../../../Store/store';
import { A320Fuel } from './A320_LVFR/A320Fuel';

export const Fuel = () => {
const [isOnGround] = useSimVar('SIM ON GROUND', 'Bool', 8_059);
const simbriefUnits = useAppSelector((state) => state.simbrief.data.units);
const simbriefPlanRamp = useAppSelector((state) => state.simbrief.data.fuels.planRamp);

const simbriefDataLoaded = isSimbriefDataLoaded();

const [massUnitForDisplay] = useState(Units.usingMetric ? 'KGS' : 'LBS');
const [convertUnit] = useState(Units.usingMetric ? 1 : (1 / 0.4535934));


return (
<A320Fuel
simbriefDataLoaded={simbriefDataLoaded}
simbriefUnits={simbriefUnits}
simbriefPlanRamp={simbriefPlanRamp}
massUnitForDisplay={massUnitForDisplay}
convertUnit={convertUnit}
isOnGround={isOnGround}
/>
);
};
Loading

0 comments on commit 55c6a66

Please sign in to comment.