Apc, Canister, PowerMonitor, Smes

This commit is contained in:
Aleksej Komarov
2020-04-19 19:36:41 +03:00
parent 44358c2342
commit fe81f64dcb
6 changed files with 301 additions and 261 deletions
+13 -2
View File
@@ -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: {
+106 -103
View File
@@ -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>
);
};
+14 -3
View File
@@ -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;
+151 -149
View File
@@ -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>
);
};
+5 -4
View File
@@ -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>
);
};