Skip to content

Commit 0030d55

Browse files
meganrmShrimpCryptidCopilottoloudis
authored
Feature/3rd module (#208)
* make indicator clickable * switch module and save which have been completed * add pop confirm * Update src/components/PageIndicator.tsx Co-authored-by: Peyton Lee <peytonalee@gmail.com> * type index as number * add key * make sure index is a number * use a set for completed modules * show cursor * fix merge conflict * fix merge conflict * Update src/components/PageIndicator.tsx Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * clean up css * display adjustments * add competitive content * remove unused imports * change data structure * use type id * content adjustments * change vis control * remove log * lift state up * Update src/content/Competitive.tsx Co-authored-by: toloudis <toloudis@users.noreply.github.com> * Update src/App.tsx Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * changes based on comments * changes based on comments * write logic consistently * add comment * fix error * fix ic50 * Update src/simulation/BindingSimulator2D.ts Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * remove duplicate call * add comment and error check * Update src/simulation/BindingSimulator2D.ts Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * more explicit checks --------- Co-authored-by: Peyton Lee <peytonalee@gmail.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: toloudis <toloudis@users.noreply.github.com>
1 parent 9793ab1 commit 0030d55

14 files changed

Lines changed: 500 additions & 152 deletions

src/App.tsx

Lines changed: 71 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import {
2626
ScatterTrace,
2727
Section,
2828
TrajectoryStatus,
29+
ViewType,
2930
} from "./types";
3031
import LeftPanel from "./components/main-layout/LeftPanel";
3132
import RightPanel from "./components/main-layout/RightPanel";
@@ -56,6 +57,7 @@ import useModule from "./hooks/useModule";
5657
import LandingPage from "./components/LandingPage";
5758

5859
function App() {
60+
const [currentView, setCurrentView] = useState<ViewType>(ViewType.Lab);
5961
const [page, setPage] = useState(FIRST_PAGE[Module.A_B_AB]);
6062
const [time, setTime] = useState(0);
6163
const [isPlaying, setIsPlaying] = useState(false);
@@ -85,9 +87,13 @@ function App() {
8587
const [inputConcentration, setInputConcentration] =
8688
useState<InputConcentration>({
8789
[AgentName.A]:
88-
LiveSimulationData.INITIAL_CONCENTRATIONS[AgentName.A],
90+
LiveSimulationData.INITIAL_CONCENTRATIONS[Module.A_B_AB][
91+
AgentName.A
92+
],
8993
[AgentName.B]:
90-
LiveSimulationData.INITIAL_CONCENTRATIONS[AgentName.B],
94+
LiveSimulationData.INITIAL_CONCENTRATIONS[Module.A_B_AB][
95+
AgentName.B
96+
],
9197
});
9298
const [timeFactor, setTimeFactor] = useState(
9399
LiveSimulationData.INITIAL_TIME_FACTOR
@@ -108,9 +114,13 @@ function App() {
108114
const [liveConcentration, setLiveConcentration] =
109115
useState<CurrentConcentration>({
110116
[AgentName.A]:
111-
LiveSimulationData.INITIAL_CONCENTRATIONS[AgentName.A],
117+
LiveSimulationData.INITIAL_CONCENTRATIONS[Module.A_B_AB][
118+
AgentName.A
119+
],
112120
[AgentName.B]:
113-
LiveSimulationData.INITIAL_CONCENTRATIONS[AgentName.B],
121+
LiveSimulationData.INITIAL_CONCENTRATIONS[Module.A_B_AB][
122+
AgentName.B
123+
],
114124
[productName]: 0,
115125
});
116126
const [recordedInputConcentration, setRecordedInputConcentration] =
@@ -182,21 +192,26 @@ function App() {
182192
const clientSimulator = useMemo(() => {
183193
const activeAgents = simulationData.getActiveAgents(currentModule);
184194
setInputConcentration(
185-
simulationData.getInitialConcentrations(activeAgents)
195+
simulationData.getInitialConcentrations(
196+
activeAgents,
197+
currentModule,
198+
sectionType === Section.Experiment
199+
)
186200
);
187201
resetCurrentRunAnalysisState();
188-
const trajectory =
189-
simulationData.createAgentsFromConcentrations(activeAgents);
202+
const trajectory = simulationData.createAgentsFromConcentrations(
203+
activeAgents,
204+
currentModule,
205+
sectionType === Section.Experiment
206+
);
190207
if (!trajectory) {
191208
return null;
192209
}
193210
const longestAxis = Math.max(viewportSize.width, viewportSize.height);
194-
const productColor = simulationData.getAgentColor(productName);
195211
const startMixed = sectionType !== Section.Introduction;
196212
return new BindingSimulator(
197213
trajectory,
198214
longestAxis / 3,
199-
productColor,
200215
startMixed ? InitialCondition.RANDOM : InitialCondition.SORTED
201216
);
202217
}, [
@@ -205,7 +220,6 @@ function App() {
205220
resetCurrentRunAnalysisState,
206221
viewportSize.width,
207222
viewportSize.height,
208-
productName,
209223
sectionType,
210224
]);
211225

@@ -304,6 +318,21 @@ function App() {
304318
[currentProductConcentrationArray, productOverTimeTraces]
305319
);
306320

321+
const setExperiment = () => {
322+
setIsPlaying(false);
323+
324+
const activeAgents = simulationData.getActiveAgents(currentModule);
325+
const concentrations = simulationData.getInitialConcentrations(
326+
activeAgents,
327+
currentModule,
328+
true
329+
);
330+
clientSimulator?.mixAgents();
331+
setTimeFactor(LiveSimulationData.INITIAL_TIME_FACTOR);
332+
setInputConcentration(concentrations);
333+
setLiveConcentration(concentrations);
334+
};
335+
307336
const handleMixAgents = useCallback(() => {
308337
if (clientSimulator) {
309338
setIsPlaying(false);
@@ -350,23 +379,28 @@ function App() {
350379
]
351380
);
352381
const totalReset = useCallback(() => {
382+
setCurrentView(ViewType.Lab);
383+
const activeAgents = [AgentName.A, AgentName.B];
384+
setCurrentModule(Module.A_B_AB);
385+
const concentrations = simulationData.getInitialConcentrations(
386+
activeAgents,
387+
Module.A_B_AB
388+
);
353389
setLiveConcentration({
354-
[AgentName.A]:
355-
LiveSimulationData.INITIAL_CONCENTRATIONS[AgentName.A],
356-
[AgentName.B]:
357-
LiveSimulationData.INITIAL_CONCENTRATIONS[AgentName.B],
390+
[AgentName.A]: concentrations[AgentName.A],
391+
[AgentName.B]: concentrations[AgentName.B],
358392
[productName]: 0,
359393
});
360-
setCurrentModule(Module.A_B_AB);
361394
setInputConcentration({
362-
[AgentName.A]:
363-
LiveSimulationData.INITIAL_CONCENTRATIONS[AgentName.A],
364-
[AgentName.B]:
365-
LiveSimulationData.INITIAL_CONCENTRATIONS[AgentName.B],
395+
[AgentName.A]: concentrations[AgentName.A],
396+
[AgentName.B]: concentrations[AgentName.B],
366397
});
367398
handleNewInputConcentration(
368399
adjustableAgentName,
369-
LiveSimulationData.INITIAL_CONCENTRATIONS[AgentName.B]
400+
concentrations[AgentName.B] ??
401+
LiveSimulationData.INITIAL_CONCENTRATIONS[Module.A_B_AB][
402+
AgentName.B
403+
]
370404
);
371405
setIsPlaying(false);
372406
clearAllAnalysisState();
@@ -376,6 +410,7 @@ function App() {
376410
handleNewInputConcentration,
377411
productName,
378412
adjustableAgentName,
413+
simulationData,
379414
]);
380415
// Special events in page navigation
381416
// usePageNumber takes a page number, a conditional and a callback
@@ -491,11 +526,17 @@ function App() {
491526
clearAllAnalysisState();
492527
setCurrentModule(module);
493528
setIsPlaying(false);
529+
// the first module is the only one that starts with the lab view
530+
if (module === Module.A_B_AB) {
531+
setCurrentView(ViewType.Lab);
532+
} else {
533+
setCurrentView(ViewType.Simulation);
534+
}
494535
};
495536

496537
const handleStartExperiment = () => {
497-
simulariumController.pause();
498-
totalReset();
538+
clearAllAnalysisState();
539+
setExperiment();
499540
setPage(page + 1);
500541
};
501542

@@ -588,6 +629,12 @@ function App() {
588629
}, 3000);
589630
};
590631

632+
const handleSwitchView = () => {
633+
setCurrentView((prevView) =>
634+
prevView === ViewType.Lab ? ViewType.Simulation : ViewType.Lab
635+
);
636+
};
637+
591638
const handleRecordEquilibrium = () => {
592639
if (!clientSimulator) {
593640
return false;
@@ -687,11 +734,13 @@ function App() {
687734
setModule,
688735
setPage,
689736
setViewportSize,
737+
setViewportType: handleSwitchView,
690738
simulariumController,
691739
timeFactor,
692740
timeUnit: simulationData.timeUnit,
693741
trajectoryName,
694742
viewportSize,
743+
viewportType: currentView,
695744
addCompletedModule,
696745
completedModules,
697746
}}

src/components/ViewSwitch.tsx

Lines changed: 8 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React, { useContext, useState } from "react";
1+
import React, { useContext } from "react";
22

33
import Viewer from "./Viewer";
44
import { SimulariumContext } from "../simulation/context";
@@ -9,47 +9,19 @@ import LabIcon from "./icons/Lab";
99
import Molecules from "./icons/Molecules";
1010
import LabView from "./LabView";
1111
import VisibilityControl from "./shared/VisibilityControl";
12-
import { Module, Section } from "../types";
12+
import { Module, ViewType } from "../types";
1313
import { FIRST_PAGE } from "../content";
14-
import useModule from "../hooks/useModule";
1514
import { VIEW_SWITCH_ID } from "../constants";
1615

17-
enum View {
18-
Lab = "lab",
19-
Simulation = "simulation",
20-
}
21-
2216
const ViewSwitch: React.FC = () => {
23-
const [currentView, setCurrentView] = useState<View>(View.Lab);
24-
const [previousModule, setPreviousModule] = useState<Module>(Module.A_B_AB);
17+
const { viewportType, setViewportType } = useContext(SimulariumContext);
2518

26-
const switchView = () => {
27-
setCurrentView((prevView) =>
28-
prevView === View.Lab ? View.Simulation : View.Lab
29-
);
30-
};
3119
const { page, isPlaying, setIsPlaying, handleTimeChange, module } =
3220
useContext(SimulariumContext);
3321

3422
const isFirstPageOfFirstModule =
3523
page === FIRST_PAGE[module] + 1 && module === Module.A_B_AB;
3624

37-
if (isFirstPageOfFirstModule && currentView === View.Simulation) {
38-
setCurrentView(View.Lab);
39-
}
40-
41-
const { contentData } = useModule(module);
42-
43-
// Show the sim view at the beginning of the module
44-
if (module !== previousModule) {
45-
setPreviousModule(module);
46-
if (contentData[page].section === Section.Experiment) {
47-
if (currentView === View.Lab) {
48-
setCurrentView(View.Simulation);
49-
}
50-
}
51-
}
52-
5325
let buttonStyle: React.CSSProperties = {
5426
top: 16,
5527
right: 16,
@@ -73,22 +45,23 @@ const ViewSwitch: React.FC = () => {
7345
<VisibilityControl notInBonusMaterial>
7446
<ProgressionControl elementId={VIEW_SWITCH_ID}>
7547
<OverlayButton
76-
onClick={switchView}
48+
onClick={setViewportType}
7749
style={buttonStyle}
7850
icon={
79-
currentView === View.Lab ? (
51+
viewportType === ViewType.Lab ? (
8052
<Molecules />
8153
) : (
8254
<LabIcon />
8355
)
8456
}
8557
>
86-
{currentView === View.Lab ? "Molecular" : "Lab"} view
58+
{viewportType === ViewType.Lab ? "Molecular" : "Lab"}{" "}
59+
view
8760
</OverlayButton>
8861
</ProgressionControl>
8962
</VisibilityControl>
9063
<PlayButton />
91-
{currentView === View.Lab ? <LabView /> : null}
64+
{viewportType === ViewType.Lab ? <LabView /> : null}
9265
<Viewer
9366
isPlaying={isPlaying}
9467
setIsPlaying={setIsPlaying}

src/components/concentration-display/ConcentrationSlider.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,11 @@ const ConcentrationSlider: React.FC<SliderProps> = ({
6969
marks[index] = {
7070
label: (
7171
<Mark
72-
index={index}
72+
index={
73+
index < 1 && index > 0
74+
? Number(index.toFixed(1))
75+
: index
76+
}
7377
disabledNumbers={disabledNumbers}
7478
onMouseUp={() => onChangeComplete?.(name, index)}
7579
/>

src/components/concentration-display/LiveConcentrationDisplay.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ const LiveConcentrationDisplay: React.FC<LiveConcentrationDisplayProps> = ({
1919
const { maxConcentration, getAgentColor } = useContext(SimulariumContext);
2020
// the steps have a 2px gap, so we are adjusting the
2121
// size of the step based on the total number we want
22-
const steps = Math.min(maxConcentration, 10);
22+
const steps = maxConcentration;
2323
const size = width / steps - 2;
2424
return (
2525
<div className={styles.container}>

src/components/main-layout/LeftPanel.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@ const LeftPanel: React.FC<LeftPanelProps> = ({
3838
const eventsOverTimeExcludedPages = {
3939
[Module.A_B_AB]: [0, 1, 2],
4040
[Module.A_C_AC]: [],
41-
[Module.A_B_D_AB]: [],
4241
};
4342
return (
4443
<>
@@ -53,6 +52,7 @@ const LeftPanel: React.FC<LeftPanelProps> = ({
5352
</VisibilityControl>
5453
<VisibilityControl
5554
excludedPages={eventsOverTimeExcludedPages}
55+
includedPages={{ [Module.A_B_D_AB]: [] }} // don't show at all in last module
5656
notInBonusMaterial
5757
>
5858
<EventsOverTimePlot

0 commit comments

Comments
 (0)