Skip to content

Commit

Permalink
feat: implement the simulation speed (#106)
Browse files Browse the repository at this point in the history
  • Loading branch information
ReidyT authored Dec 13, 2024
1 parent 4e6dc93 commit e201531
Show file tree
Hide file tree
Showing 6 changed files with 112 additions and 24 deletions.
21 changes: 20 additions & 1 deletion src/context/SimulationContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,17 @@ import {
loadTemperaturesFromCSV,
} from '@/utils/temperatures';

type SpeedState = {
text: string;
multiply: number;
};

const SPEED_STATES: SpeedState[] = [
{ text: 'x1', multiply: 1 },
{ text: 'x3', multiply: 3 },
{ text: 'x5', multiply: 5 },
];

// TODO: regroup by type like windowSize: { value, update }...
type SimulationContextType = UseHouseComponentsReturnType & {
status: SimulationStatus;
Expand Down Expand Up @@ -69,6 +80,8 @@ type SimulationContextType = UseHouseComponentsReturnType & {
numberOfFloors: number;
updateNumberOfFloors: (numberOfFloors: number) => void;
houseComponentsConfigurator: HouseComponentsConfigurator;
speed: string;
nextSpeed: () => void;
};

const SimulationContext = createContext<SimulationContextType | null>(null);
Expand Down Expand Up @@ -99,6 +112,7 @@ export const SimulationProvider = ({
const [simulationStatus, setSimulationStatus] = useState<SimulationStatus>(
SimulationStatus.LOADING, // waiting for the temperatures...
);
const [simulationSpeedIdx, setSimulationSpeedIdx] = useState(0);

// Computed states
const csv =
Expand Down Expand Up @@ -209,7 +223,7 @@ export const SimulationProvider = ({
} else {
setSimulationStatus(SimulationStatus.FINISHED);
}
}, simulationFrameMS);
}, simulationFrameMS / SPEED_STATES[simulationSpeedIdx].multiply);
}

return () => {
Expand All @@ -224,6 +238,7 @@ export const SimulationProvider = ({
simulationFrameMS,
dispatchHistory,
currentDayIdx,
simulationSpeedIdx,
]);

// Update simulation's current state
Expand Down Expand Up @@ -317,6 +332,9 @@ export const SimulationProvider = ({
numberOfFloors: simulationSettings.numberOfFloors,
updateNumberOfFloors,
houseComponentsConfigurator: simulationSettings.houseConfigurator,
speed: SPEED_STATES[simulationSpeedIdx].text,
nextSpeed: () =>
setSimulationSpeedIdx((curr) => (curr + 1) % SPEED_STATES.length),
...houseComponentsHook,
}),
[
Expand Down Expand Up @@ -344,6 +362,7 @@ export const SimulationProvider = ({
gotToDay,
updateWindowSize,
updateNumberOfFloors,
simulationSpeedIdx,
houseComponentsHook,
],
);
Expand Down
28 changes: 16 additions & 12 deletions src/modules/common/SimulationControl.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { useSimulation } from '@/context/SimulationContext';
import { SimulationStatus } from '@/types/simulation';

import { LabelledSlider } from './LabelledSlider';
import { SpeedButton } from './SpeedButton';

export const SimulationControl = (): JSX.Element => {
const {
Expand All @@ -26,18 +27,21 @@ export const SimulationControl = (): JSX.Element => {

return (
<Stack mt={2} alignItems="center" spacing={2}>
<LabelledSlider
dataTestId="simulation-control-dates"
value={currDayIdx}
sx={{ minWidth: '350px', maxWidth: '500px' }}
onChange={(v) => handleGoToDay(v)}
min={0}
max={numberOfDays - 1}
hideValue
hideLabels={status === SimulationStatus.LOADING}
formatValue={(v) => getDateOf(v).toLocaleDateString()}
disabled={status === SimulationStatus.LOADING}
/>
<Stack alignItems="end">
<SpeedButton />
<LabelledSlider
dataTestId="simulation-control-dates"
value={currDayIdx}
sx={{ minWidth: '350px', maxWidth: '500px' }}
onChange={(v) => handleGoToDay(v)}
min={0}
max={numberOfDays - 1}
hideValue
hideLabels={status === SimulationStatus.LOADING}
formatValue={(v) => getDateOf(v).toLocaleDateString()}
disabled={status === SimulationStatus.LOADING}
/>
</Stack>
<Fab
data-testid={`simulation-control-button-${status === SimulationStatus.RUNNING ? 'pause' : 'start'}`}
color="primary"
Expand Down
17 changes: 17 additions & 0 deletions src/modules/common/SpeedButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { Button, Typography } from '@mui/material';

import { useSimulation } from '@/context/SimulationContext';

export const SpeedButton = (): JSX.Element => {
const { speed, nextSpeed } = useSimulation();

return (
<Button
data-testid={`speed-button-${speed}`}
onClick={() => nextSpeed()}
variant="outlined"
>
<Typography textTransform="lowercase">{speed}</Typography>
</Button>
);
};
6 changes: 5 additions & 1 deletion tests/player/SimulationControlPage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,14 @@ export class SimulationControlPage {
this.lastDate = this.page.getByTestId(`${this.testId}-max`);
}

getButton(action: 'start' | 'pause'): Locator {
getControlButton(action: 'start' | 'pause'): Locator {
return this.page.getByTestId(`simulation-control-button-${action}`);
}

getSpeedButton(speed: number): Locator {
return this.page.getByTestId(`speed-button-x${speed}`);
}

async startSimulation(): Promise<void> {
await clickOnButton(
this.page.getByTestId('simulation-control-button-start'),
Expand Down
62 changes: 53 additions & 9 deletions tests/player/simulation-control.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ test('clicking on start should run the simulation', async ({ page }) => {
// Wait for *any* change in the current date
await page.waitForTimeout(1_000);

await expect(control.getButton('pause')).toBeVisible();
await expect(control.getControlButton('pause')).toBeVisible();
await control.pauseSimulation();

const date = await info.dateInfo.textContent();
Expand All @@ -21,7 +21,7 @@ test('clicking on start should run the simulation', async ({ page }) => {
const totElectricityCost = await info.totElectricityCostInfo.textContent();

expect(date).toBeDefined();
await expect(control.getButton('start')).toBeVisible();
await expect(control.getControlButton('start')).toBeVisible();
await control.startSimulation();

// Wait for *any* change in the current date
Expand Down Expand Up @@ -71,7 +71,7 @@ test('moving in the futur should work when the simulation is not runned', async
// the user should be able to resume the simulation
await control.startSimulation();
await page.waitForTimeout(1_000);
await expect(control.getButton('pause')).toBeVisible();
await expect(control.getControlButton('pause')).toBeVisible();
const finalDate = await info.dateInfo.textContent();
expect(finalDate).toBeDefined();
expect(new Date(finalDate!).getTime()).toBeGreaterThan(
Expand All @@ -88,18 +88,18 @@ test('moving in the futur should pause the simulation when running', async ({
await control.startSimulation();
// Wait for *any* change in the current date
await page.waitForTimeout(1_000);
await expect(control.getButton('pause')).toBeVisible();
await expect(control.getControlButton('pause')).toBeVisible();

await control.moveDateSlider(50);

const date = await info.dateInfo.textContent();
expect(date).toBeDefined();
await expect(control.getButton('start')).toBeVisible();
await expect(control.getControlButton('start')).toBeVisible();

// the user should be able to resume the simulation
await control.startSimulation();
await page.waitForTimeout(1_000);
await expect(control.getButton('pause')).toBeVisible();
await expect(control.getControlButton('pause')).toBeVisible();
const newDate = await info.dateInfo.textContent();
expect(newDate).toBeDefined();
expect(new Date(newDate!).getTime()).toBeGreaterThan(
Expand All @@ -121,7 +121,7 @@ test('should move in the futur and in the past', async ({ page }) => {
await control.startSimulation();
// Wait for *any* change in the current date
await page.waitForTimeout(1_000);
await expect(control.getButton('pause')).toBeVisible();
await expect(control.getControlButton('pause')).toBeVisible();

const newDate = await info.dateInfo.textContent();
expect(newDate).toBeDefined();
Expand All @@ -131,7 +131,7 @@ test('should move in the futur and in the past', async ({ page }) => {

// move to the past
await control.moveDateSlider(10);
await expect(control.getButton('start')).toBeVisible();
await expect(control.getControlButton('start')).toBeVisible();
const dateInThePast = await info.dateInfo.textContent();
expect(dateInThePast).toBeDefined();
expect(new Date(dateInThePast!).getTime()).toBeLessThan(
Expand All @@ -141,10 +141,54 @@ test('should move in the futur and in the past', async ({ page }) => {
// the user should be able to resume the simulation
await control.startSimulation();
await page.waitForTimeout(1_000);
await expect(control.getButton('pause')).toBeVisible();
await expect(control.getControlButton('pause')).toBeVisible();
const finalDate = await info.dateInfo.textContent();
expect(finalDate).toBeDefined();
expect(new Date(finalDate!).getTime()).toBeGreaterThan(
new Date(dateInThePast!).getTime(),
);
});

test('increasing speed should reach a greater date after 1 second', async ({
page,
}) => {
const housePage = new HousePage(page);
const { info, control } = housePage;
await housePage.goto();

// start the simulation in normal speed (x1)
await control.startSimulation();
await page.waitForTimeout(1_000);
await control.pauseSimulation();

const x1Date = await info.dateInfo.textContent();
expect(x1Date).toBeDefined();

// set speed from x1 to x3 and restart the simulation
await control.getSpeedButton(1).click();
expect(await control.getSpeedButton(3).textContent()).toBe('x3');
await control.moveDateSlider(0);
await control.startSimulation();
await page.waitForTimeout(1_000);
await control.pauseSimulation();

const x3Date = await info.dateInfo.textContent();
expect(x3Date).toBeDefined();
expect(new Date(x3Date!).getTime()).toBeGreaterThan(
new Date(x1Date!).getTime(),
);

// set speed from x3 to x5 and restart the simulation
await control.getSpeedButton(3).click();
expect(await control.getSpeedButton(5).textContent()).toBe('x5');
await control.moveDateSlider(0);
await control.startSimulation();
await page.waitForTimeout(1_000);
await control.pauseSimulation();

const x5Date = await info.dateInfo.textContent();
expect(x5Date).toBeDefined();
expect(new Date(x5Date!).getTime()).toBeGreaterThan(
new Date(x3Date!).getTime(),
);
});
2 changes: 1 addition & 1 deletion tests/player/simulation-duration.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ test('simulation duration should be disabled when simulation is running', async
const { settings, control } = housePage;
await housePage.goto();
await settings.setSimulationDuration(25);
await control.getButton('start').click();
await control.getControlButton('start').click();
await expect(settings.simulationDuration).toBeDisabled();
});

Expand Down

0 comments on commit e201531

Please sign in to comment.