Skip to content

Commit

Permalink
feat: allow to pause the simulation (#80)
Browse files Browse the repository at this point in the history
* feat: improve accordion container
  • Loading branch information
ReidyT authored Dec 5, 2024
1 parent 70709c8 commit 8be0ad0
Show file tree
Hide file tree
Showing 15 changed files with 217 additions and 101 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
"pre-commit": "yarn prettier:check && yarn lint",
"playwright": "playwright test --project chromium",
"playwright:ui": "playwright test --ui",
"playwright:trace": "playwright show-trace",
"unittest": "vitest",
"cov:report": "open ./coverage/lcov-report/index.html"
},
Expand Down
4 changes: 3 additions & 1 deletion playwright.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,9 @@ export default defineConfig({
baseURL: `http://localhost:${process.env.VITE_PORT || 4001}`,

/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
trace: 'on-first-retry',
trace: 'on',

screenshot: 'only-on-failure',
},

/* Configure projects for major browsers */
Expand Down
2 changes: 1 addition & 1 deletion src/config/simulation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {
} from './houseInsulations';

export const SIMULATION_FRAME_MS = 150;
export const SIMULATION_SLIDING_WINDOW = { window: 2, unit: TimeUnit.Days };
export const SIMULATION_SLIDING_WINDOW = { window: 1, unit: TimeUnit.Days };
export const SIMULATION_CSV_FILES = {
1: {
path: 'temperatures/predictions_1_year.csv',
Expand Down
22 changes: 18 additions & 4 deletions src/context/SimulationContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ type SimulationContextType = {
duration: Pick<FormattedTime, 'value'> & { unit: typeof TimeUnit.Years },
) => void;
startSimulation: () => void;
pauseSimulation: () => void;
};

const SimulationContext = createContext<SimulationContextType | null>(null);
Expand Down Expand Up @@ -133,6 +134,8 @@ export const SimulationProvider = ({
});
}, [csv.measurementFrequency, csv.path]);

const intervalId = useRef<NodeJS.Timeout | null>(null);

const startSimulation = useCallback((): void => {
if (
simulationStatus === SimulationStatus.RUNNING ||
Expand All @@ -145,20 +148,29 @@ export const SimulationProvider = ({
throw new Error('The temperatures are not loaded!');
}

if (simulationStatus !== SimulationStatus.PAUSED) {
temperatureIterator.current.reset();
}
setSimulationStatus(SimulationStatus.RUNNING);
temperatureIterator.current.reset();

const intervalId = setInterval(() => {
intervalId.current = setInterval(() => {
if (temperatureIterator.current?.hasMore()) {
// TODO: should update this to use the overrided temperature in the calculation
setCurrentWindow(temperatureIterator.current.getNext());
} else {
clearInterval(intervalId);
} else if (intervalId.current) {
clearInterval(intervalId.current);
setSimulationStatus(SimulationStatus.FINISHED);
}
}, simulationFrameMS);
}, [simulationFrameMS, simulationStatus]);

const pauseSimulation = useCallback((): void => {
if (simulationStatus === SimulationStatus.RUNNING && intervalId.current) {
clearInterval(intervalId.current);
setSimulationStatus(SimulationStatus.PAUSED);
}
}, [simulationStatus]);

const updateOutdoorTemperature = ({
override,
value,
Expand Down Expand Up @@ -198,6 +210,7 @@ export const SimulationProvider = ({
}),
setPricekWh,
startSimulation,
pauseSimulation,
}),
[
currentWindow.mean,
Expand All @@ -206,6 +219,7 @@ export const SimulationProvider = ({
indoorTemperature,
outdoorTemperature.override,
outdoorTemperature.value,
pauseSimulation,
pricekWh,
progression,
simulationDuration,
Expand Down
1 change: 1 addition & 0 deletions src/langs/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
}
},
"SIMULATION_CONTROL_PANEL": {
"TITLE": "Settings",
"DURATION_CONTROL_PANEL": {
"TITLE": "Simulation",
"LABEL": "Duration of Simulation"
Expand Down
12 changes: 6 additions & 6 deletions src/modules/scenes/FirstScene.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import { SimulationControlPanel } from './SimulationControlPanel/SimulationContr
import { SimulationInformations } from './SimulationInformations/SimulationInformations';

const FirstSceneComponent = (): JSX.Element => {
const { startSimulation, status } = useSimulation();
const { startSimulation, pauseSimulation, status } = useSimulation();
const { numberOfFloors } = useHouseComponents();

const theme = useTheme();
Expand Down Expand Up @@ -73,12 +73,12 @@ const FirstSceneComponent = (): JSX.Element => {

<Stack mt={2}>
<Fab
data-testid="simulation-control-button"
data-testid={`simulation-control-button-${status === SimulationStatus.RUNNING ? 'pause' : 'start'}`}
color="primary"
onClick={startSimulation}
disabled={
status === SimulationStatus.RUNNING ||
status === SimulationStatus.LOADING
onClick={
status === SimulationStatus.RUNNING
? pauseSimulation
: startSimulation
}
>
{status === SimulationStatus.RUNNING ? (
Expand Down
133 changes: 71 additions & 62 deletions src/modules/scenes/SimulationControlPanel/SimulationControlPanel.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { useTranslation } from 'react-i18next';

import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
import { useMediaQuery, useTheme } from '@mui/material';
import { styled, useMediaQuery, useTheme } from '@mui/material';
import Accordion from '@mui/material/Accordion';
import AccordionDetails from '@mui/material/AccordionDetails';
import AccordionSummary from '@mui/material/AccordionSummary';
Expand All @@ -11,74 +11,83 @@ import { HouseControl } from './HouseControl';
import { SimulationDurationControl } from './SimulationDurationControl';
import { TemperatureControl } from './TemperatureControl/TemperatureControl';

const AccordionContainer = styled(Accordion, {
shouldForwardProp: (prop) => prop !== 'sm',
})<{ md: boolean }>(({ md }) => ({
maxHeight: md ? '95vh' : undefined,
overflowY: md ? 'auto' : undefined,
padding: md ? 2 : undefined,
paddingRight: md ? 4 : undefined,
backgroundColor: '#f5f5f8',
}));

export const SimulationControlPanel = (): JSX.Element => {
const { t } = useTranslation('SIMULATION_CONTROL_PANEL');
const theme = useTheme();
const sm = useMediaQuery(theme.breakpoints.down('md'));
const md = useMediaQuery(theme.breakpoints.up('sm'));

return (
<div
style={
sm
? {}
: {
maxHeight: '95vh',
overflowY: 'auto',
padding: 3,
}
}
>
<Accordion defaultExpanded>
<AccordionSummary
expandIcon={<ExpandMoreIcon />}
aria-controls="panel-duration-content"
id="panel-duration-header"
>
{t('DURATION_CONTROL_PANEL.TITLE')}
</AccordionSummary>
<AccordionDetails>
<SimulationDurationControl />
</AccordionDetails>
</Accordion>
<AccordionContainer defaultExpanded={md} md={md}>
<AccordionSummary
expandIcon={<ExpandMoreIcon />}
aria-controls="panel-simulation-content"
id="panel-simulation-header"
>
{t('TITLE')}
</AccordionSummary>
<AccordionDetails>
<Accordion defaultExpanded>
<AccordionSummary
expandIcon={<ExpandMoreIcon />}
aria-controls="panel-duration-content"
id="panel-duration-header"
>
{t('DURATION_CONTROL_PANEL.TITLE')}
</AccordionSummary>
<AccordionDetails>
<SimulationDurationControl />
</AccordionDetails>
</Accordion>

<Accordion defaultExpanded>
<AccordionSummary
expandIcon={<ExpandMoreIcon />}
aria-controls="panel-house-content"
id="panel-house-header"
>
{t('HOUSE_CONTROL_PANEL.TITLE')}
</AccordionSummary>
<AccordionDetails>
<HouseControl />
</AccordionDetails>
</Accordion>
<Accordion defaultExpanded>
<AccordionSummary
expandIcon={<ExpandMoreIcon />}
aria-controls="panel-house-content"
id="panel-house-header"
>
{t('HOUSE_CONTROL_PANEL.TITLE')}
</AccordionSummary>
<AccordionDetails>
<HouseControl />
</AccordionDetails>
</Accordion>

<Accordion defaultExpanded>
<AccordionSummary
expandIcon={<ExpandMoreIcon />}
aria-controls="panel-electricity-content"
id="panel-electricity-header"
>
{t('ELECTRICITY_CONTROL_PANEL.TITLE')}
</AccordionSummary>
<AccordionDetails>
<ElectricityCostControl />
</AccordionDetails>
</Accordion>
<Accordion defaultExpanded>
<AccordionSummary
expandIcon={<ExpandMoreIcon />}
aria-controls="panel-electricity-content"
id="panel-electricity-header"
>
{t('ELECTRICITY_CONTROL_PANEL.TITLE')}
</AccordionSummary>
<AccordionDetails>
<ElectricityCostControl />
</AccordionDetails>
</Accordion>

<Accordion defaultExpanded>
<AccordionSummary
expandIcon={<ExpandMoreIcon />}
aria-controls="panel-temperature-content"
id="panel-temperature-header"
>
{t('TEMPERATURES_CONTROL_PANEL.TITLE')}
</AccordionSummary>
<AccordionDetails>
<TemperatureControl />
</AccordionDetails>
</Accordion>
</div>
<Accordion defaultExpanded>
<AccordionSummary
expandIcon={<ExpandMoreIcon />}
aria-controls="panel-temperature-content"
id="panel-temperature-header"
>
{t('TEMPERATURES_CONTROL_PANEL.TITLE')}
</AccordionSummary>
<AccordionDetails>
<TemperatureControl />
</AccordionDetails>
</Accordion>
</AccordionDetails>
</AccordionContainer>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export const SimulationDurationControl = (): JSX.Element => {
const { duration, updateSimulationDuration, status } = useSimulation();

const selectIsDisabled =
status === SimulationStatus.LOADING || status === SimulationStatus.RUNNING;
status !== SimulationStatus.IDLE && status !== SimulationStatus.FINISHED;

const handleChange = (newDuration: string | number): void => {
if (selectIsDisabled) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,9 @@ export const SimulationInformations = (): JSX.Element => {
<Stack spacing={1} direction="column">
<Stack direction="row" alignItems="center" spacing={1}>
<CalendarRange />
<Typography>{period.from.toLocaleDateString()}</Typography>
<Typography data-testid="simulation-info-date">
{period.to.toLocaleDateString()}
</Typography>
</Stack>

<Stack pl={2} spacing={1}>
Expand Down Expand Up @@ -75,7 +77,7 @@ export const SimulationInformations = (): JSX.Element => {
<Stack direction="row" alignItems="center" spacing={1}>
<Heater />
<Typography>{tInformations('CURRENT_PERIOD.HEAT_LOSS')}</Typography>
<Typography>
<Typography data-testid="simulation-info-heatloss">
{heatLoss.value} {heatLoss.unit}
</Typography>
</Stack>
Expand All @@ -93,15 +95,17 @@ export const SimulationInformations = (): JSX.Element => {
<Stack direction="row" alignItems="center" spacing={1}>
<Heater />
<Typography>{tInformations('TOTAL.HEAT_LOSS')}</Typography>
<Typography>
<Typography data-testid="simulation-info-tot-heatloss">
{totalHeatLoss.value} {totalHeatLoss.unit}
</Typography>
</Stack>

<Stack direction="row" alignItems="center" spacing={1}>
<Plug />
<Typography>{tInformations('TOTAL.ELECTRICITY_COST')}</Typography>
<Typography>{electricityCost} CHF</Typography>
<Typography data-testid="simulation-info-tot-electricity-cost">
{electricityCost} CHF
</Typography>
</Stack>

<Stack direction="row" alignItems="center" spacing={1}>
Expand Down
1 change: 1 addition & 0 deletions src/types/simulation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ export enum SimulationStatus {
IDLE,
LOADING,
RUNNING,
PAUSED,
FINISHED,
}

Expand Down
Loading

0 comments on commit 8be0ad0

Please sign in to comment.