mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-08-30 00:29:02 +01:00
Apc, Canister, PowerMonitor, Smes
This commit is contained in:
@@ -1,10 +1,21 @@
|
||||
import { Fragment } from 'inferno';
|
||||
import { useBackend } from '../backend';
|
||||
import { Box, Button, LabeledList, NoticeBox, ProgressBar, Section } from '../components';
|
||||
import { Window } from '../layouts';
|
||||
import { InterfaceLockNoticeBox } from './common/InterfaceLockNoticeBox';
|
||||
|
||||
export const Apc = props => {
|
||||
const { act, data } = useBackend(props);
|
||||
export const Apc = (props, context) => {
|
||||
return (
|
||||
<Window resizable>
|
||||
<Window.Content scrollable>
|
||||
<ApcContent />
|
||||
</Window.Content>
|
||||
</Window>
|
||||
);
|
||||
};
|
||||
|
||||
const ApcContent = (props, context) => {
|
||||
const { act, data } = useBackend(context);
|
||||
const locked = data.locked && !data.siliconUser;
|
||||
const powerStatusMap = {
|
||||
2: {
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import { Fragment } from 'inferno';
|
||||
import { useBackend } from '../backend';
|
||||
import { AnimatedNumber, Box, Button, Flex, Knob, LabeledList, NoticeBox, Section } from '../components';
|
||||
import { Window } from '../layouts';
|
||||
|
||||
export const Canister = props => {
|
||||
const { act, data } = useBackend(props);
|
||||
export const Canister = (props, context) => {
|
||||
const { act, data } = useBackend(context);
|
||||
const {
|
||||
portConnected,
|
||||
tankPressure,
|
||||
@@ -18,109 +19,111 @@ export const Canister = props => {
|
||||
restricted,
|
||||
} = data;
|
||||
return (
|
||||
<Fragment>
|
||||
<NoticeBox>
|
||||
The regulator {hasHoldingTank ? 'is' : 'is not'} connected
|
||||
to a tank.
|
||||
</NoticeBox>
|
||||
<Section
|
||||
title="Canister"
|
||||
buttons={(
|
||||
<Button
|
||||
icon="pencil-alt"
|
||||
content="Relabel"
|
||||
onClick={() => act('relabel')} />
|
||||
)}>
|
||||
<Flex mx={-1}>
|
||||
<Flex.Item
|
||||
mx={1}
|
||||
align="center"
|
||||
textAlign="center">
|
||||
<Knob
|
||||
size={2}
|
||||
color={!!valveOpen && 'yellow'}
|
||||
value={releasePressure}
|
||||
unit="kPa"
|
||||
minValue={minReleasePressure}
|
||||
maxValue={maxReleasePressure}
|
||||
step={5}
|
||||
stepPixelSize={2}
|
||||
onDrag={(e, value) => act('pressure', {
|
||||
pressure: value,
|
||||
})} />
|
||||
</Flex.Item>
|
||||
<Flex.Item
|
||||
mx={1}
|
||||
my={-0.5}
|
||||
align="center"
|
||||
textAlign="center">
|
||||
<Box my={0.5} color="label">
|
||||
Valve
|
||||
</Box>
|
||||
<Box my={0.5} width="60px">
|
||||
<AnimatedNumber value={releasePressure} /> kPa
|
||||
</Box>
|
||||
<Window>
|
||||
<Window.Content>
|
||||
<NoticeBox>
|
||||
The regulator {hasHoldingTank ? 'is' : 'is not'} connected
|
||||
to a tank.
|
||||
</NoticeBox>
|
||||
<Section
|
||||
title="Canister"
|
||||
buttons={(
|
||||
<Button
|
||||
my={0.5}
|
||||
color={valveOpen
|
||||
? (hasHoldingTank ? 'caution' : 'danger')
|
||||
: null}
|
||||
content={valveOpen ? 'Open' : 'Closed'}
|
||||
onClick={() => act('valve')} />
|
||||
</Flex.Item>
|
||||
<Flex.Item
|
||||
mx={1}
|
||||
grow={1}
|
||||
basis={0}>
|
||||
<LabeledList>
|
||||
<LabeledList.Item label="Pressure">
|
||||
<AnimatedNumber value={tankPressure} /> kPa
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item
|
||||
label="Port"
|
||||
color={portConnected ? 'good' : 'average'}>
|
||||
{portConnected ? 'Connected' : 'Not Connected'}
|
||||
</LabeledList.Item>
|
||||
{!!isPrototype && (
|
||||
<LabeledList.Item label="Access">
|
||||
<Button
|
||||
icon={restricted ? 'lock' : 'unlock'}
|
||||
color="caution"
|
||||
content={restricted
|
||||
? 'Engineering'
|
||||
: 'Public'}
|
||||
onClick={() => act('restricted')} />
|
||||
icon="pencil-alt"
|
||||
content="Relabel"
|
||||
onClick={() => act('relabel')} />
|
||||
)}>
|
||||
<Flex mx={-1}>
|
||||
<Flex.Item
|
||||
mx={1}
|
||||
align="center"
|
||||
textAlign="center">
|
||||
<Knob
|
||||
size={2}
|
||||
color={!!valveOpen && 'yellow'}
|
||||
value={releasePressure}
|
||||
unit="kPa"
|
||||
minValue={minReleasePressure}
|
||||
maxValue={maxReleasePressure}
|
||||
step={5}
|
||||
stepPixelSize={1}
|
||||
onDrag={(e, value) => act('pressure', {
|
||||
pressure: value,
|
||||
})} />
|
||||
</Flex.Item>
|
||||
<Flex.Item
|
||||
mx={1}
|
||||
my={-0.5}
|
||||
align="center"
|
||||
textAlign="center">
|
||||
<Box my={0.5} color="label">
|
||||
Valve
|
||||
</Box>
|
||||
<Box my={0.5} width="60px">
|
||||
<AnimatedNumber value={releasePressure} /> kPa
|
||||
</Box>
|
||||
<Button
|
||||
my={0.5}
|
||||
color={valveOpen
|
||||
? (hasHoldingTank ? 'caution' : 'danger')
|
||||
: null}
|
||||
content={valveOpen ? 'Open' : 'Closed'}
|
||||
onClick={() => act('valve')} />
|
||||
</Flex.Item>
|
||||
<Flex.Item
|
||||
mx={1}
|
||||
grow={1}
|
||||
basis={0}>
|
||||
<LabeledList>
|
||||
<LabeledList.Item label="Pressure">
|
||||
<AnimatedNumber value={tankPressure} /> kPa
|
||||
</LabeledList.Item>
|
||||
)}
|
||||
<LabeledList.Item
|
||||
label="Port"
|
||||
color={portConnected ? 'good' : 'average'}>
|
||||
{portConnected ? 'Connected' : 'Not Connected'}
|
||||
</LabeledList.Item>
|
||||
{!!isPrototype && (
|
||||
<LabeledList.Item label="Access">
|
||||
<Button
|
||||
icon={restricted ? 'lock' : 'unlock'}
|
||||
color="caution"
|
||||
content={restricted
|
||||
? 'Engineering'
|
||||
: 'Public'}
|
||||
onClick={() => act('restricted')} />
|
||||
</LabeledList.Item>
|
||||
)}
|
||||
</LabeledList>
|
||||
</Flex.Item>
|
||||
</Flex>
|
||||
</Section>
|
||||
<Section
|
||||
title="Holding Tank"
|
||||
buttons={!!hasHoldingTank && (
|
||||
<Button
|
||||
icon="eject"
|
||||
color={valveOpen && 'danger'}
|
||||
content="Eject"
|
||||
onClick={() => act('eject')} />
|
||||
)}>
|
||||
{!!hasHoldingTank && (
|
||||
<LabeledList>
|
||||
<LabeledList.Item label="Label">
|
||||
{holdingTank.name}
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Pressure">
|
||||
<AnimatedNumber value={holdingTank.tankPressure} /> kPa
|
||||
</LabeledList.Item>
|
||||
</LabeledList>
|
||||
</Flex.Item>
|
||||
</Flex>
|
||||
</Section>
|
||||
<Section
|
||||
title="Holding Tank"
|
||||
buttons={!!hasHoldingTank && (
|
||||
<Button
|
||||
icon="eject"
|
||||
color={valveOpen && 'danger'}
|
||||
content="Eject"
|
||||
onClick={() => act('eject')} />
|
||||
)}>
|
||||
{!!hasHoldingTank && (
|
||||
<LabeledList>
|
||||
<LabeledList.Item label="Label">
|
||||
{holdingTank.name}
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Pressure">
|
||||
<AnimatedNumber value={holdingTank.tankPressure} /> kPa
|
||||
</LabeledList.Item>
|
||||
</LabeledList>
|
||||
)}
|
||||
{!hasHoldingTank && (
|
||||
<Box color="average">
|
||||
No Holding Tank
|
||||
</Box>
|
||||
)}
|
||||
</Section>
|
||||
</Fragment>
|
||||
)}
|
||||
{!hasHoldingTank && (
|
||||
<Box color="average">
|
||||
No Holding Tank
|
||||
</Box>
|
||||
)}
|
||||
</Section>
|
||||
</Window.Content>
|
||||
</Window>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
import { NtosWindow } from '../layouts';
|
||||
import { PowerMonitorContent } from './PowerMonitor';
|
||||
|
||||
export const NtosPowerMonitor = () => {
|
||||
return (
|
||||
<NtosWindow resizable>
|
||||
<NtosWindow.Content scrollable>
|
||||
<PowerMonitorContent />
|
||||
</NtosWindow.Content>
|
||||
</NtosWindow>
|
||||
);
|
||||
};
|
||||
@@ -4,6 +4,8 @@ import { toFixed } from 'common/math';
|
||||
import { pureComponentHooks } from 'common/react';
|
||||
import { Component, Fragment } from 'inferno';
|
||||
import { Box, Button, Chart, ColorBox, Flex, Icon, LabeledList, ProgressBar, Section, Table } from '../components';
|
||||
import { Window } from '../layouts';
|
||||
import { useBackend } from '../backend';
|
||||
|
||||
const PEAK_DRAW = 500000;
|
||||
|
||||
@@ -12,7 +14,17 @@ const powerRank = str => {
|
||||
return ['w', 'kw', 'mw', 'gw'].indexOf(unit);
|
||||
};
|
||||
|
||||
export class PowerMonitor extends Component {
|
||||
export const PowerMonitor = () => {
|
||||
return (
|
||||
<Window resizable>
|
||||
<Window.Content scrollable>
|
||||
<PowerMonitorContent />
|
||||
</Window.Content>
|
||||
</Window>
|
||||
);
|
||||
};
|
||||
|
||||
export class PowerMonitorContent extends Component {
|
||||
constructor() {
|
||||
super();
|
||||
this.state = {
|
||||
@@ -21,8 +33,7 @@ export class PowerMonitor extends Component {
|
||||
}
|
||||
|
||||
render() {
|
||||
const { state } = this.props;
|
||||
const { data } = state;
|
||||
const { data } = useBackend(this.context);
|
||||
const { history } = data;
|
||||
const { sortByField } = this.state;
|
||||
const supply = history.supply[history.supply.length - 1] || 0;
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import { Fragment } from 'inferno';
|
||||
import { useBackend } from '../backend';
|
||||
import { Box, Button, Flex, LabeledList, ProgressBar, Section, Slider } from '../components';
|
||||
import { formatPower } from '../format';
|
||||
import { Window } from '../layouts';
|
||||
|
||||
// Common power multiplier
|
||||
const POWER_MUL = 1e3;
|
||||
|
||||
export const Smes = props => {
|
||||
const { act, data } = useBackend(props);
|
||||
export const Smes = (props, context) => {
|
||||
const { act, data } = useBackend(context);
|
||||
const {
|
||||
capacityPercent,
|
||||
capacity,
|
||||
@@ -34,153 +34,155 @@ export const Smes = props => {
|
||||
|| 'bad'
|
||||
);
|
||||
return (
|
||||
<Fragment>
|
||||
<Section title="Stored Energy">
|
||||
<ProgressBar
|
||||
value={capacityPercent * 0.01}
|
||||
ranges={{
|
||||
good: [0.5, Infinity],
|
||||
average: [0.15, 0.5],
|
||||
bad: [-Infinity, 0.15],
|
||||
}} />
|
||||
</Section>
|
||||
<Section title="Input">
|
||||
<LabeledList>
|
||||
<LabeledList.Item
|
||||
label="Charge Mode"
|
||||
buttons={
|
||||
<Button
|
||||
icon={inputAttempt ? 'sync-alt' : 'times'}
|
||||
selected={inputAttempt}
|
||||
onClick={() => act('tryinput')}>
|
||||
{inputAttempt ? 'Auto' : 'Off'}
|
||||
</Button>
|
||||
}>
|
||||
<Box color={inputState}>
|
||||
{capacityPercent >= 100 && 'Fully Charged'
|
||||
|| inputting && 'Charging'
|
||||
|| 'Not Charging'}
|
||||
</Box>
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Target Input">
|
||||
<Flex inline width="100%">
|
||||
<Flex.Item>
|
||||
<Window>
|
||||
<Window.Content>
|
||||
<Section title="Stored Energy">
|
||||
<ProgressBar
|
||||
value={capacityPercent * 0.01}
|
||||
ranges={{
|
||||
good: [0.5, Infinity],
|
||||
average: [0.15, 0.5],
|
||||
bad: [-Infinity, 0.15],
|
||||
}} />
|
||||
</Section>
|
||||
<Section title="Input">
|
||||
<LabeledList>
|
||||
<LabeledList.Item
|
||||
label="Charge Mode"
|
||||
buttons={
|
||||
<Button
|
||||
icon="fast-backward"
|
||||
disabled={inputLevel === 0}
|
||||
onClick={() => act('input', {
|
||||
target: 'min',
|
||||
})} />
|
||||
icon={inputAttempt ? 'sync-alt' : 'times'}
|
||||
selected={inputAttempt}
|
||||
onClick={() => act('tryinput')}>
|
||||
{inputAttempt ? 'Auto' : 'Off'}
|
||||
</Button>
|
||||
}>
|
||||
<Box color={inputState}>
|
||||
{capacityPercent >= 100 && 'Fully Charged'
|
||||
|| inputting && 'Charging'
|
||||
|| 'Not Charging'}
|
||||
</Box>
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Target Input">
|
||||
<Flex inline width="100%">
|
||||
<Flex.Item>
|
||||
<Button
|
||||
icon="fast-backward"
|
||||
disabled={inputLevel === 0}
|
||||
onClick={() => act('input', {
|
||||
target: 'min',
|
||||
})} />
|
||||
<Button
|
||||
icon="backward"
|
||||
disabled={inputLevel === 0}
|
||||
onClick={() => act('input', {
|
||||
adjust: -10000,
|
||||
})} />
|
||||
</Flex.Item>
|
||||
<Flex.Item grow={1} mx={1}>
|
||||
<Slider
|
||||
value={inputLevel / POWER_MUL}
|
||||
fillValue={inputAvailable / POWER_MUL}
|
||||
minValue={0}
|
||||
maxValue={inputLevelMax / POWER_MUL}
|
||||
step={5}
|
||||
stepPixelSize={4}
|
||||
format={value => formatPower(value * POWER_MUL, 1)}
|
||||
onDrag={(e, value) => act('input', {
|
||||
target: value * POWER_MUL,
|
||||
})} />
|
||||
</Flex.Item>
|
||||
<Flex.Item>
|
||||
<Button
|
||||
icon="forward"
|
||||
disabled={inputLevel === inputLevelMax}
|
||||
onClick={() => act('input', {
|
||||
adjust: 10000,
|
||||
})} />
|
||||
<Button
|
||||
icon="fast-forward"
|
||||
disabled={inputLevel === inputLevelMax}
|
||||
onClick={() => act('input', {
|
||||
target: 'max',
|
||||
})} />
|
||||
</Flex.Item>
|
||||
</Flex>
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Available">
|
||||
{formatPower(inputAvailable)}
|
||||
</LabeledList.Item>
|
||||
</LabeledList>
|
||||
</Section>
|
||||
<Section title="Output">
|
||||
<LabeledList>
|
||||
<LabeledList.Item
|
||||
label="Output Mode"
|
||||
buttons={
|
||||
<Button
|
||||
icon="backward"
|
||||
disabled={inputLevel === 0}
|
||||
onClick={() => act('input', {
|
||||
adjust: -10000,
|
||||
})} />
|
||||
</Flex.Item>
|
||||
<Flex.Item grow={1} mx={1}>
|
||||
<Slider
|
||||
value={inputLevel / POWER_MUL}
|
||||
fillValue={inputAvailable / POWER_MUL}
|
||||
minValue={0}
|
||||
maxValue={inputLevelMax / POWER_MUL}
|
||||
step={5}
|
||||
stepPixelSize={4}
|
||||
format={value => formatPower(value * POWER_MUL, 1)}
|
||||
onDrag={(e, value) => act('input', {
|
||||
target: value * POWER_MUL,
|
||||
})} />
|
||||
</Flex.Item>
|
||||
<Flex.Item>
|
||||
<Button
|
||||
icon="forward"
|
||||
disabled={inputLevel === inputLevelMax}
|
||||
onClick={() => act('input', {
|
||||
adjust: 10000,
|
||||
})} />
|
||||
<Button
|
||||
icon="fast-forward"
|
||||
disabled={inputLevel === inputLevelMax}
|
||||
onClick={() => act('input', {
|
||||
target: 'max',
|
||||
})} />
|
||||
</Flex.Item>
|
||||
</Flex>
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Available">
|
||||
{formatPower(inputAvailable)}
|
||||
</LabeledList.Item>
|
||||
</LabeledList>
|
||||
</Section>
|
||||
<Section title="Output">
|
||||
<LabeledList>
|
||||
<LabeledList.Item
|
||||
label="Output Mode"
|
||||
buttons={
|
||||
<Button
|
||||
icon={outputAttempt ? 'power-off' : 'times'}
|
||||
selected={outputAttempt}
|
||||
onClick={() => act('tryoutput')}>
|
||||
{outputAttempt ? 'On' : 'Off'}
|
||||
</Button>
|
||||
}>
|
||||
<Box color={outputState}>
|
||||
{outputting
|
||||
? 'Sending'
|
||||
: charge > 0
|
||||
? 'Not Sending'
|
||||
: 'No Charge'}
|
||||
</Box>
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Target Output">
|
||||
<Flex inline width="100%">
|
||||
<Flex.Item>
|
||||
<Button
|
||||
icon="fast-backward"
|
||||
disabled={outputLevel === 0}
|
||||
onClick={() => act('output', {
|
||||
target: 'min',
|
||||
})} />
|
||||
<Button
|
||||
icon="backward"
|
||||
disabled={outputLevel === 0}
|
||||
onClick={() => act('output', {
|
||||
adjust: -10000,
|
||||
})} />
|
||||
</Flex.Item>
|
||||
<Flex.Item grow={1} mx={1}>
|
||||
<Slider
|
||||
value={outputLevel / POWER_MUL}
|
||||
minValue={0}
|
||||
maxValue={outputLevelMax / POWER_MUL}
|
||||
step={5}
|
||||
stepPixelSize={4}
|
||||
format={value => formatPower(value * POWER_MUL, 1)}
|
||||
onDrag={(e, value) => act('output', {
|
||||
target: value * POWER_MUL,
|
||||
})} />
|
||||
</Flex.Item>
|
||||
<Flex.Item>
|
||||
<Button
|
||||
icon="forward"
|
||||
disabled={outputLevel === outputLevelMax}
|
||||
onClick={() => act('output', {
|
||||
adjust: 10000,
|
||||
})} />
|
||||
<Button
|
||||
icon="fast-forward"
|
||||
disabled={outputLevel === outputLevelMax}
|
||||
onClick={() => act('output', {
|
||||
target: 'max',
|
||||
})} />
|
||||
</Flex.Item>
|
||||
</Flex>
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Outputting">
|
||||
{formatPower(outputUsed)}
|
||||
</LabeledList.Item>
|
||||
</LabeledList>
|
||||
</Section>
|
||||
</Fragment>
|
||||
icon={outputAttempt ? 'power-off' : 'times'}
|
||||
selected={outputAttempt}
|
||||
onClick={() => act('tryoutput')}>
|
||||
{outputAttempt ? 'On' : 'Off'}
|
||||
</Button>
|
||||
}>
|
||||
<Box color={outputState}>
|
||||
{outputting
|
||||
? 'Sending'
|
||||
: charge > 0
|
||||
? 'Not Sending'
|
||||
: 'No Charge'}
|
||||
</Box>
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Target Output">
|
||||
<Flex inline width="100%">
|
||||
<Flex.Item>
|
||||
<Button
|
||||
icon="fast-backward"
|
||||
disabled={outputLevel === 0}
|
||||
onClick={() => act('output', {
|
||||
target: 'min',
|
||||
})} />
|
||||
<Button
|
||||
icon="backward"
|
||||
disabled={outputLevel === 0}
|
||||
onClick={() => act('output', {
|
||||
adjust: -10000,
|
||||
})} />
|
||||
</Flex.Item>
|
||||
<Flex.Item grow={1} mx={1}>
|
||||
<Slider
|
||||
value={outputLevel / POWER_MUL}
|
||||
minValue={0}
|
||||
maxValue={outputLevelMax / POWER_MUL}
|
||||
step={5}
|
||||
stepPixelSize={4}
|
||||
format={value => formatPower(value * POWER_MUL, 1)}
|
||||
onDrag={(e, value) => act('output', {
|
||||
target: value * POWER_MUL,
|
||||
})} />
|
||||
</Flex.Item>
|
||||
<Flex.Item>
|
||||
<Button
|
||||
icon="forward"
|
||||
disabled={outputLevel === outputLevelMax}
|
||||
onClick={() => act('output', {
|
||||
adjust: 10000,
|
||||
})} />
|
||||
<Button
|
||||
icon="fast-forward"
|
||||
disabled={outputLevel === outputLevelMax}
|
||||
onClick={() => act('output', {
|
||||
target: 'max',
|
||||
})} />
|
||||
</Flex.Item>
|
||||
</Flex>
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Outputting">
|
||||
{formatPower(outputUsed)}
|
||||
</LabeledList.Item>
|
||||
</LabeledList>
|
||||
</Section>
|
||||
</Window.Content>
|
||||
</Window>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { useBackend } from '../backend';
|
||||
import { Box, Button } from '../components';
|
||||
import { Layout, refocusLayout } from './Layout';
|
||||
import { refocusLayout } from './Layout';
|
||||
import { Window } from './Window';
|
||||
|
||||
export const NtosWindow = (props, context) => {
|
||||
const { children } = props;
|
||||
@@ -16,7 +17,7 @@ export const NtosWindow = (props, context) => {
|
||||
PC_showexitprogram,
|
||||
} = data;
|
||||
return (
|
||||
<Layout theme="ntos">
|
||||
<Window theme="ntos">
|
||||
<div className="NtosWindow">
|
||||
<div
|
||||
className="NtosWindow__header NtosHeader"
|
||||
@@ -104,14 +105,14 @@ export const NtosWindow = (props, context) => {
|
||||
</div>
|
||||
{children}
|
||||
</div>
|
||||
</Layout>
|
||||
</Window>
|
||||
);
|
||||
};
|
||||
|
||||
const NtosWindowContent = props => {
|
||||
return (
|
||||
<div className="NtosWindow__content">
|
||||
<Layout.Content {...props} />
|
||||
<Window.Content {...props} />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user