Skip to content

Commit

Permalink
#57 Add Static Configurations
Browse files Browse the repository at this point in the history
  • Loading branch information
m-abdulhak committed Jul 16, 2023
1 parent 3d1967a commit 6d3b93a
Show file tree
Hide file tree
Showing 18 changed files with 427 additions and 43 deletions.
56 changes: 45 additions & 11 deletions src/client/App.jsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
/* eslint-disable no-console */
import React, { useState, useRef, useEffect, useCallback } from 'react';

import { get, set, cloneDeep } from 'lodash';

import Select from '@mui/material/Select';
import MenuItem from '@mui/material/MenuItem';
import CircularProgress from '@mui/material/CircularProgress';
Expand Down Expand Up @@ -56,12 +58,14 @@ const App = () => {
const [loading, setLoading] = useState(true);
const [selectedScene, setSelectedScene] = useState(getSceneFromUrlQuery(options));
const [config, setConfig] = useState(exampleConfigs[selectedScene].simConfig);
const [configWithUserOptions, setConfigWithUserOptions] = useState(config);
const [selectedBackgroundField, setSelectedBackgroundField] = useState(getDefaultField(config?.env?.fields) ?? null);
const [benchSettings, setBenchSettings] = useState(exampleConfigs[selectedScene].benchmarkConfig);
const [description, setDescription] = useState(exampleConfigs[selectedScene].description);
const [uiEnabled, setUiEnabled] = useState(true);
const [time, setTime] = useState(0);
const [dynamicParams, setDynamicParams] = useState({});
const [staticParams, setStaticParams] = useState({});
const [renderSkip, setRenderSkip] = useState(1);
const [paused, setPaused] = useState(false);
const [benchmarkData, setBenchmarkData] = useState({});
Expand All @@ -84,6 +88,8 @@ const App = () => {

const setScene = (newScene) => {
setSelectedScene(newScene);
setDynamicParams({});
setStaticParams({});
};

const onDynamicPropsChange = useCallback((props) => {
Expand All @@ -95,6 +101,10 @@ const App = () => {
});
}, []);

const onStaticPropsChange = useCallback((props) => {
setStaticParams((oldParams) => ({ ...oldParams, ...props }));
}, []);

const onRenderSkipChange = (newRS) => {
const rs = parseInt(newRS);
setRenderSkip(rs);
Expand All @@ -113,8 +123,14 @@ const App = () => {
stopBenchmark();
}

// TODO: check for userDefined config and merge
const usedConfig = { ...newConfig };
const usedConfig = cloneDeep(newConfig);

for (const [key, val] of Object.entries(staticParams)) {
const pDef = (usedConfig.staticPropertyDefinitions || []).find((def) => def.name === key);
if (val != null && pDef?.path) {
set(usedConfig, pDef.path, val);
}
}

if (!useDefaultController) {
if (controllerCode.onLoopCode) {
Expand Down Expand Up @@ -144,7 +160,7 @@ const App = () => {

resetSimulation(usedConfig, onUpdate, updateDefaultControllerCode);

const defaultDynamicValues = usedConfig.dynamicPropertyDefinitions.reduce((acc, pDef) => {
const defaultDynamicValues = (usedConfig.dynamicPropertyDefinitions || []).reduce((acc, pDef) => {
let defaultVal = pDef.defaultValue;

if (defaultVal && typeof defaultVal === 'function') {
Expand All @@ -157,7 +173,16 @@ const App = () => {
}, {});

onDynamicPropsChange(defaultDynamicValues);
onRenderSkipChange(newConfig.env.renderSkip);

const defaultStaticValues = (usedConfig.staticPropertyDefinitions || []).reduce((acc, pDef) => {
acc[pDef.name] = get(usedConfig, pDef.path) ?? pDef.defaultValue;

return acc;
}, {});

onStaticPropsChange(defaultStaticValues);

onRenderSkipChange(usedConfig.env.renderSkip);
setPaused(false);
resetRenderer();

Expand All @@ -166,11 +191,11 @@ const App = () => {
}

if (
newConfig.env.fields
&& typeof newConfig.env.fields === 'object'
&& Object.keys(newConfig.env.fields).length > 0
usedConfig.env.fields
&& typeof usedConfig.env.fields === 'object'
&& Object.keys(usedConfig.env.fields).length > 0
) {
for (const [fieldKey, field] of Object.entries(newConfig.env.fields)) {
for (const [fieldKey, field] of Object.entries(usedConfig.env.fields)) {
if (!field.url) {
console.error(`Field ${fieldKey} has no url!`);
return;
Expand All @@ -190,7 +215,8 @@ const App = () => {
}
}

setSelectedBackgroundField(getDefaultField(newConfig?.env?.fields) ?? null);
setSelectedBackgroundField(getDefaultField(usedConfig?.env?.fields) ?? null);
setConfigWithUserOptions(usedConfig);
};

const onTogglePause = () => {
Expand Down Expand Up @@ -255,6 +281,8 @@ const App = () => {
sceneConfig={config}
dynamicParams={dynamicParams}
onDynamicPropsChange={onDynamicPropsChange}
staticParams={staticParams}
onStaticPropsChange={onStaticPropsChange}
/>;

const benchElem = initialized ? (
Expand Down Expand Up @@ -349,9 +377,15 @@ const App = () => {
/>
<div id="main-section">
<div id='env-section'>
<div id='env-container' style={{ width: config.env.width, height: config.env.height }}>
<div
id='env-container'
style={{ width: configWithUserOptions.env.width, height: configWithUserOptions.env.height }}
>
<div id='fields-canvas-container' ref={fieldsElemRef}/>
<svg id='simulation-svg' ref={svgRef} width={config.env.width} height={config.env.height}/>
<svg
id='simulation-svg'
ref={svgRef} width={configWithUserOptions.env.width} height={configWithUserOptions.env.height}
/>
</div>
</div>
{sceneDescriptionElem}
Expand Down
4 changes: 2 additions & 2 deletions src/client/components/Inputs/TitledSlider.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { Box, Grid, Slider, Typography, Tooltip } from '@mui/material';

const TitledSlider = ({ title, value, setValue, toolTip, min, max, step }) => (
<Grid container spacing={2} item sm={12} lg={12} xl={12}>
<Grid item sm={2} md={2} lg={1}>
<Grid item sm={3} md={3} lg={1.5}>
<Box display="flex" justifyContent="left" alignItems="center">
<Tooltip title={toolTip}>
<Typography variant="h7">
Expand All @@ -13,7 +13,7 @@ const TitledSlider = ({ title, value, setValue, toolTip, min, max, step }) => (
</Tooltip>
</Box>
</Grid>
<Grid item xs sm={10} md={10} lg={11}>
<Grid item xs sm={9} md={9} lg={10.5} sx={{ maxWidth: '300px' }}>
<Slider
min={min || 0}
max={max || 50}
Expand Down
33 changes: 29 additions & 4 deletions src/client/components/Options/SceneConfigurations.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,10 @@ const paramParser = (type) => {

function SceneConfigurations({
sceneConfig,
dynamicParams = { velocityScale: 1 },
onDynamicPropsChange
dynamicParams = {},
staticParams = {},
onDynamicPropsChange,
onStaticPropsChange
}) {
const dynamicParamElems = (sceneConfig.dynamicPropertyDefinitions || []).map((def) => {
// eslint-disable-next-line no-unused-vars
Expand Down Expand Up @@ -49,11 +51,32 @@ function SceneConfigurations({
</TitledInputSection>
);

const staticParamElems = (sceneConfig.staticPropertyDefinitions || []).map((def) => (
<TitledSlider
className="input-section-header"
key={`static-prop-${def.name}`}
title={def.title}
value={staticParams[def.name] ?? 0}
min={def.min || 0}
max={def.max || 50}
step={def.step || 1}
setValue={(newV) => onStaticPropsChange({ [def.name]: paramParser(def.type)(newV) })}
toolTip={def.desc}
/>
));

const staticConfigurationsElem = staticParamElems?.length === 0 ? null : (
<TitledInputSection title='Static Configurations (Require Scene Restart)'>
{staticParamElems}
</TitledInputSection>
);

return (
<>
{dynamicConfigurationsElem}
{staticConfigurationsElem}
<CodeEditorSection
title='Full Scene Configuration (Read Only)'
title='Full Scene Configurations (Read Only)'
code={JSON.stringify(sceneConfig, null, 2)}
setCode={() => {
// TODO: update current configuration
Expand All @@ -69,7 +92,9 @@ function SceneConfigurations({
SceneConfigurations.propTypes = {
sceneConfig: PropTypes.object.isRequired,
dynamicParams: PropTypes.object.isRequired,
onDynamicPropsChange: PropTypes.func.isRequired
staticParams: PropTypes.object.isRequired,
onDynamicPropsChange: PropTypes.func.isRequired,
onStaticPropsChange: PropTypes.func.isRequired
};

export default memo(SceneConfigurations);
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
/* eslint-disable no-param-reassign */
import { Delaunay } from 'd3-delaunay';

// DO NOT MODIFY, ALL SCENES WILL BE AFFECTED
// Import in scene configurations, clone, and override with desired values instead
const dynamicPropertyDefinitions = {
robotCount: {
name: 'robotCount',
Expand Down
171 changes: 171 additions & 0 deletions src/common/configurationTemplate/staticPropertyDefinitions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
// DO NOT MODIFY, ALL SCENES WILL BE AFFECTED
// Import in scene configurations, clone, and override with desired values instead
const staticPropertyDefinitions = {
envWidth: {
name: 'envWidth',
title: 'Env Width',
type: 'int',
defaultValue: 0,
min: 300,
max: 800,
step: 1,
desc: 'Controls the width of the environment.',
path: 'env.width'
},
envHeight: {
name: 'envHeight',
title: 'Env Height',
type: 'int',
defaultValue: 0,
min: 300,
max: 800,
step: 1,
desc: 'Controls the width of the environment.',
path: 'env.height'
},
robotCount: {
name: 'robotCount',
title: 'Robots',
type: 'int',
defaultValue: 0,
min: 1,
max: 50,
step: 1,
desc: 'Controls number of robots.',
path: 'robots.count'
},
robotRadius: {
name: 'robotRadius',
title: 'Robot Radius',
type: 'float',
defaultValue: 0,
min: 5,
max: 20,
step: 0.1,
desc: 'Controls number of robots.',
path: 'robots.radius'
},
velocityScale: {
name: 'velocityScale',
title: 'Velocity',
type: 'float',
defaultValue: 15,
min: 1,
max: 50,
step: 0.1,
desc: 'Controls robots velocity, only works when supported in robot controller.',
path: 'robots.params.velocityScale'
},
pucksCountG1: {
name: 'pucksCountG1',
title: 'Pucks (G1)',
type: 'int',
defaultValue: 0,
min: 0,
max: 200,
step: 1,
desc: 'Controls number of pucks in group 1, if supported by scene.',
path: 'pucks.groups.[0].count'
},
pucksRadiusG1: {
name: 'pucksRadiusG1',
title: 'Puck Radius (G1)',
type: 'float',
defaultValue: 0,
min: 3,
max: 10,
step: 0.1,
desc: 'Controls number of pucks in group 1, if supported by scene.',
path: 'pucks.groups.[0].radius'
},
pucksGoalXG1: {
name: 'pucksGoalXG1',
title: 'Pucks Goal X (G1)',
type: 'int',
defaultValue: 0,
min: 0,
max: 800,
step: 1,
desc: 'Controls number of pucks in group 1, if supported by scene.',
path: 'pucks.groups.[0].goal.x'
},
pucksGoalYG1: {
name: 'pucksGoalYG1',
title: 'Pucks Goal Y (G1)',
type: 'int',
defaultValue: 0,
min: 0,
max: 500,
step: 1,
desc: 'Controls number of pucks in group 1, if supported by scene.',
path: 'pucks.groups.[0].goal.y'
},
pucksGoalRadiusG1: {
name: 'pucksGoalRadiusG1',
title: 'Pucks Goal Radius (G1)',
type: 'int',
defaultValue: 0,
min: 50,
max: 150,
step: 1,
desc: 'Controls number of pucks in group 1, if supported by scene.',
path: 'pucks.groups.[0].goalRadius'
},
pucksCountG2: {
name: 'pucksCountG2',
title: 'Pucks (G2)',
type: 'int',
defaultValue: 0,
min: 0,
max: 200,
step: 1,
desc: 'Controls number of pucks in group 1, if supported by scene.',
path: 'pucks.groups.[1].count'
},
pucksRadiusG2: {
name: 'pucksRadiusG2',
title: 'Puck Radius (G2)',
type: 'float',
defaultValue: 0,
min: 3,
max: 10,
step: 0.1,
desc: 'Controls number of pucks in group 1, if supported by scene.',
path: 'pucks.groups.[1].radius'
},
pucksGoalXG2: {
name: 'pucksGoalXG2',
title: 'Pucks Goal X (G2)',
type: 'int',
defaultValue: 0,
min: 0,
max: 800,
step: 1,
desc: 'Controls number of pucks in group 1, if supported by scene.',
path: 'pucks.groups.[1].goal.x'
},
pucksGoalYG2: {
name: 'pucksGoalYG2',
title: 'Pucks Goal Y (G2)',
type: 'int',
defaultValue: 0,
min: 0,
max: 500,
step: 1,
desc: 'Controls number of pucks in group 1, if supported by scene.',
path: 'pucks.groups.[1].goal.y'
},
pucksGoalRadiusG2: {
name: 'pucksGoalRadiusG2',
title: 'Pucks Goal Radius (G2)',
type: 'int',
defaultValue: 0,
min: 50,
max: 150,
step: 1,
desc: 'Controls number of pucks in group 1, if supported by scene.',
path: 'pucks.groups.[1].goalRadius'
}
};

export default staticPropertyDefinitions;
Loading

0 comments on commit 6d3b93a

Please sign in to comment.