diff --git a/START.bat b/START.bat
index a90b644..741e3b5 100644
--- a/START.bat
+++ b/START.bat
@@ -1,2 +1 @@
-npm run server
-pause
\ No newline at end of file
+node -r esbuild-register server/index.ts
\ No newline at end of file
diff --git a/components/ConnectionState.tsx b/components/ConnectionState.tsx
deleted file mode 100644
index 8cf7919..0000000
--- a/components/ConnectionState.tsx
+++ /dev/null
@@ -1,54 +0,0 @@
-import { ListGroupItem, ListGroup, Card } from "react-bootstrap";
-import { BCI2K_OperatorConnection } from "bci2k";
-import React, { useState, useEffect } from "react";
-import localConfig from "../server/config/localconfig.json";
-import { useStore } from "./store";
-const ConnectionState = () => {
- const [connectionStatus, setConnectionStatus] = useState("Not Connected");
-
- useEffect(() => {
- (async () => {
- let bci = useStore.getState().bci;
- await bci.connect(`ws://localhost:3000`);
-
- bci.execute("Reset System");
- bci.stateListen();
- bci.onStateChange = (e) => setConnectionStatus(e);
- })();
- }, []);
-
- return (
-
-
-
-
- System
-
-
-
-
-
- {connectionStatus}
-
-
- {useStore.getState().config.subject}
-
-
- {useStore.getState().config.source}
-
-
-
-
- );
-};
-
-export default ConnectionState;
diff --git a/components/ConnectionStatus/ConnectionState.tsx b/components/ConnectionStatus/ConnectionState.tsx
new file mode 100644
index 0000000..541516e
--- /dev/null
+++ b/components/ConnectionStatus/ConnectionState.tsx
@@ -0,0 +1,114 @@
+import { ListGroupItem, ListGroup, Card, Button, Row, Col } from "react-bootstrap";
+import React, { useState, useEffect } from "react";
+import localConfig from "../../server/config/localconfig.json";
+import { useStore } from "../store";
+import SourceButton from "./SourceButton";
+import ParticipantButton from "./ParticipantButton";
+const ConnectionState = () => {
+ const [connectionStatus, setConnectionStatus] = useState("Not Connected");
+ const [subj, setSubj] = useState(useStore.getState().config.subject);
+ useStore.subscribe((state) => state.config.subject, (st) => setSubj(st));
+
+ const [amp, setAmp] = useState(useStore.getState().config.source);
+ useStore.subscribe((state) => state.config.source, (st) => setAmp(st));
+
+ //present buttons to use based on localconfig setting
+ const showButtons = useStore.getState().config.editable ? "flex" : "none";
+ //const [vis, setVis] = useState(useStore.getState().config.editable);
+
+ useEffect(() => {
+ (async () => {
+ let bci = useStore.getState().bci;
+ await bci.connect(`ws://localhost:3000`);
+
+ //bci.execute("Reset System");
+ console.log("Connected!")
+ bci.stateListen();
+ bci.onStateChange = (e) => setConnectionStatus(e);
+ })();
+ }, []);
+
+ return (
+
+
+
+
+ System
+
+
+
+
+
+
+ Status:
+
+ {connectionStatus}
+
+
+
+
+
+
+
+
+ Participant:
+
+ {subj}
+
+
+
+
+
+
+
+
+ Amplifier:
+
+ {amp}
+
+
+
+
+
+
+
+
+
+ );
+};
+const updateLocalConfig = async () => {
+ try {
+ const paradigmsReq = await fetch(`/api/saveLocalConfig`, {method: "POST",
+ headers: {
+ "Content-Type": "application/json",
+ },
+ body: JSON.stringify(useStore.getState().config)});
+ //let pReq = await fetch("/api/paradigms/newGo");
+ console.log("created json")
+ console.log(paradigmsReq);
+ const result = await paradigmsReq.json();
+ console.log("success:", result);
+ } catch (error) {
+ console.error(`error: ${error}`);
+ }
+}
+const UpdateLocalConfig = () => {
+ return (
+
+
+
+ );
+}
+
+export { ConnectionState, updateLocalConfig };
diff --git a/components/ConnectionStatus/ParticipantButton.tsx b/components/ConnectionStatus/ParticipantButton.tsx
new file mode 100644
index 0000000..913270a
--- /dev/null
+++ b/components/ConnectionStatus/ParticipantButton.tsx
@@ -0,0 +1,57 @@
+import { Container, Card, ListGroupItem, Button, Modal, Form, FloatingLabel, Row, Col, ToggleButton, ToggleButtonGroup } from "react-bootstrap";
+import React, { useState, useEffect, useContext } from "react";
+import { useStore } from "../store";
+import { updateLocalConfig } from "./ConnectionState";
+
+const SourceButton = (settings) => {
+ const [show, setShow] = useState(false);
+ const [subject, setParticipant] = useState(useStore.getState().config.subject);
+
+ const handleClose = () => {
+ setShow(false);
+ }
+ const handleShow = async () => {
+ console.log(useStore.getState().config.subject);
+ setParticipant(useStore.getState().config.subject)
+ setShow(true);
+ }
+ const handleChange = (e) => {
+ let newSourceName = e.target.value;
+ setParticipant(newSourceName)
+ }
+ const handleSubmit = () => {
+ let newConfig = useStore.getState().config;
+ newConfig.subject = subject;
+ useStore.setState({config : newConfig})
+ updateLocalConfig();
+ setShow(false);
+ }
+
+ return (
+ <>
+
+
+
+ Change your participant!
+
+
+
+ New participant name:
+
+
+
+
+
+
+
+
+
+ >
+ );
+};
+export default SourceButton;
diff --git a/components/ConnectionStatus/SourceButton.tsx b/components/ConnectionStatus/SourceButton.tsx
new file mode 100644
index 0000000..ea1babe
--- /dev/null
+++ b/components/ConnectionStatus/SourceButton.tsx
@@ -0,0 +1,113 @@
+import { Container, Card, ListGroupItem, Button, Modal, Form, FloatingLabel, Row, Col, ToggleButton, ToggleButtonGroup } from "react-bootstrap";
+import React, { useState, useEffect, useContext } from "react";
+import { useStore } from "../store";
+import { updateLocalConfig } from "./ConnectionState";
+//import fs from "fs";
+const ParameterDescription = (input) => {
+ const prm = input.prm;
+ const checkPrm = (prm) => {
+ //recursively print object
+ if (prm.constructor === ({}).constructor) {
+ return (<>>)
+ }
+ else {
+ return (<>{prm}>);
+ }
+ }
+ return (
+
+ {Object.values(prm).map((x: any, idx) => (
+ - {Object.keys(prm)[idx]}: {checkPrm(x)}
+ ))}
+
+ );
+}
+
+const SourceButton = (settings) => {
+ //let setDispTxt = settings.dispSt;
+ const [show, setShow] = useState(false);
+ const [amps, setAmps] = useState({});
+ const [source, setLocalSource] = useState(useStore.getState().config.source);
+
+ const handleClose = () => {
+ setShow(false);
+ }
+ const handleShow = async () => {
+ let ampsReq = await fetch("/api/amplifiers");
+ let ampsRes = await ampsReq.json();
+ setAmps(ampsRes);
+ console.log(useStore.getState().config.source);
+ setLocalSource(useStore.getState().config.source)
+ setShow(true);
+ }
+ const handleClick = (e) => {
+ let newSourceName = e.target.innerHTML;
+ setLocalSource(newSourceName)
+ }
+ // const updateLocalConfig = async () => {
+ // try {
+ // const paradigmsReq = await fetch(`/api/saveLocalConfig`, {method: "POST",
+ // headers: {
+ // "Content-Type": "application/json",
+ // },
+ // body: JSON.stringify(useStore.getState().config)});
+ // //let pReq = await fetch("/api/paradigms/newGo");
+ // console.log("created json")
+ // console.log(paradigmsReq);
+ // const result = await paradigmsReq.json();
+ // console.log("success:", result);
+ // } catch (error) {
+ // console.error(`error: ${error}`);
+ // }
+ // }
+ const handleSubmit = () => {
+ let newConfig = useStore.getState().config;
+ newConfig.source = source;
+ useStore.setState({config : newConfig})
+ updateLocalConfig();
+ setShow(false);
+ }
+
+ return (
+ <>
+
+
+
+ Choose from available amplifiers
+
+
+
+
+
+
+ {Array(Object.keys(amps).length)
+ .fill(0)
+ .map((x, idx) => (
+
+ {Object.keys(amps)[idx]}
+
+ ))}
+
+
+
+
+
+
+
+
+
+
+
+
+
+ >
+ );
+};
+export default SourceButton;
diff --git a/components/ExperimentConfiguration.tsx b/components/ExperimentConfiguration.tsx
new file mode 100644
index 0000000..1d1dcd2
--- /dev/null
+++ b/components/ExperimentConfiguration.tsx
@@ -0,0 +1,44 @@
+import { useState, useContext, useEffect } from "react";
+import { Row, Col, Navbar, Container, Form, Button } from "react-bootstrap";
+import { ConnectionState } from "./ConnectionStatus/ConnectionState";
+import Toolbox from "./Toolbox";
+import {
+ ReplayParadigms,
+ ReplayTasks,
+} from "./ToolboxComps/Replay";
+import Paradigms from "./Paradigms";
+import Tasks from "./Tasks";
+import { useStore } from "./store";
+import Notes from "./Notes";
+
+export default function ExperimentConfiguration() {
+
+ return (
+
+
+
+
+
+
+
+ {useStore.getState().replayMode ? (
+
+ ) : (
+
+ )}
+
+
+ {useStore.getState().replayMode &&
+ useStore.getState().replayTask != null ? (
+
+ ) : (
+
+ )}
+
+
+
+
+
+
+ );
+}
diff --git a/components/NewParadigm/NewBlock.tsx b/components/NewParadigm/NewBlock.tsx
new file mode 100644
index 0000000..f791cbb
--- /dev/null
+++ b/components/NewParadigm/NewBlock.tsx
@@ -0,0 +1,38 @@
+import { ListGroup, Card, ListGroupItem, Button, Modal, Form, FloatingLabel, Row, Col, Accordion } from "react-bootstrap";
+import React, { useState, useEffect, useContext } from "react";
+import Parameter from "./Parameters"
+
+const NewBlock = (data) => {
+ let task = data.pState[0]
+ let setNewTask = data.pState[1]
+ const [blockName, setBlockName] = useState("");
+ const [prms, setPrms] = useState([]);
+
+ const handlePrms = (e) => {
+ console.log(e.target.value)
+ prms.push(e.target.value);
+ setPrms(prms)
+ }
+
+ const setParadigmState = () => {
+ //organize for task.json
+ let thisP = {
+ title: blockName,
+ loadParameters: prms}
+ task["Block_" + data.n] = thisP
+ setNewTask(task)
+ }
+
+ return (
+
+ Block {data.n}
+
+
+ setBlockName(e.target.value)}/>
+
+
+
+
+ );
+};
+export default NewBlock;
diff --git a/components/NewParadigm/NewTask.tsx b/components/NewParadigm/NewTask.tsx
new file mode 100644
index 0000000..8981912
--- /dev/null
+++ b/components/NewParadigm/NewTask.tsx
@@ -0,0 +1,187 @@
+import { ListGroup, Card, InputGroup, Button, Modal, Form, FloatingLabel, Row, Col, Accordion } from "react-bootstrap";
+import React, { useState, useEffect, useContext } from "react";
+import NewBlock from "./NewBlock";
+import Parameter from "./Parameters";
+import { useStore } from "../store";
+
+const NewTask = (data) => {
+ let pName = data.pName
+ let paradigm = data.pState[0]
+ let setNewParadigm = data.pState[1]
+ const [procEnabled, setProcMod] = useState(false);
+ const [procValid, setProcValid] = useState(true);
+ const [appEnabled, setAppMod] = useState(false);
+ const [appValid, setAppValid] = useState(true);
+ const [prms, setPrms] = useState([]);
+ //task control
+ const exeProc = "procID";
+ const exeApp = "appID";
+ let defaultTask = {
+ name: "",
+ description: "",
+ [exeProc]: "",
+ [exeApp]: "",
+ nBlocks: 1
+ }
+ const [task, setTask] = useState(defaultTask);
+ //task name control
+ const handleTaskNameChange = async (e) => {
+ let t = e.target.value;
+ if (t.length === 0)
+ setTask({
+ ...task,
+ name: ""
+ });
+ else
+ setTask({
+ ...task,
+ name: "(" + t + ")"
+ });
+
+ //setParadigmState();
+ }
+
+ const setParadigmState = () => {
+ //organize for task.json
+ let thisP = {
+ title: task.name.replace(new RegExp("\\(|\\)", "g"), ""),
+ description: task.description,
+ executables: {
+ processing: task[exeProc],
+ application: task[exeApp]
+ },
+ setParameters: {},
+ loadParameters: prms,
+ Blocks: newTask
+ }
+ paradigm["Task_" + data.n] = thisP
+ setNewParadigm(paradigm)
+ }
+ const handleFileInput = (e) => {
+ if (e.target.files.length != 0) {
+ let newFile = e.target.files[0].name
+ useStore.getState().bci.execute(`Categorize Executable ${newFile}`).then((value) => {
+ console.log(value);
+ let enabled = false;
+ switch (e.target.id) {
+ case exeProc:
+ if (value === 'SignalProcessing') {
+ enabled = true;
+ setProcValid(true);
+ console.log(newFile)
+ if (newFile === 'DummySignalProcessing.exe') {
+ setProcMod(false);
+ }
+ }
+ else {
+ setProcValid(false);
+ }
+ break;
+ case exeApp:
+ if (value === 'Application') {
+ enabled = true;
+ setAppValid(true);
+ if (newFile === 'DummyApplication.exe') {
+ setAppMod(false);
+ }
+ }
+ else {
+ setAppValid(false);
+ }
+ //setAppMod(enabled);
+ break;
+ }
+ if (enabled === true) {
+ setTask({...task, [e.target.id]: newFile})
+ }
+ });
+ }
+ else {
+ switch (e.target.id) {
+ case exeProc:
+ setProcMod(false);
+ break;
+ case exeApp:
+ setAppMod(false);
+ break;
+ }
+ }
+ }
+
+ const handleDefaultModuleClick= (e) => {
+ console.log(e)
+ }
+
+ const [newTask, setNewTask] = useState({});
+
+ return (
+
+ Task {data.n} {task.name}
+
+
+ Signal Processing Module
+
+ setProcMod(!procEnabled)}
+ //defaultChecked
+ checked={!procEnabled}
+ />
+
+
+
+
+ Please choose a Signal Processing module.
+
+
+
+
+
+ Application Module
+
+ setAppMod(!appEnabled)}
+ onChange={(e) => setAppMod(!appEnabled)}
+ //defaultChecked
+ checked={!appEnabled}
+ />
+
+
+
+
+ Please choose an Application module.
+
+
+
+
+
+ {Array(task.nBlocks)
+ .fill(0)
+ .map((x, idx) => (
+
+ ))}
+
+
+
+
+
+ );
+};
+export default NewTask;
diff --git a/components/NewParadigm/Parameters.tsx b/components/NewParadigm/Parameters.tsx
new file mode 100644
index 0000000..4ae7460
--- /dev/null
+++ b/components/NewParadigm/Parameters.tsx
@@ -0,0 +1,46 @@
+import { ListGroup, Card, ListGroupItem, Button, Modal, Form, InputGroup, Tooltip, OverlayTrigger} from "react-bootstrap";
+import React, { useState, useEffect, useContext } from "react";
+
+const Parameter = (data) => {
+ let pName = data.pName;
+ let prms = data.prmState[0]
+ let setPrms = data.prmState[1]
+ let pTitle = "Choose parameter files (relative from prog folder or full path)"
+ if (data.title != null)
+ pTitle = data.title;
+ const [paramNum, setParamNum] = useState(1);
+
+ const handlePrms = (e) => {
+ prms[e.target.id] = e.target.value;
+ setPrms(prms)
+ }
+ //button tooltip
+ const renderTooltip = (props) => (
+
+ Click to add another parameter file
+
+ );
+ return (
+ <>
+ {pTitle}
+ {Array(paramNum)
+ .fill(0)
+ .map((x, idx) => (
+
+
+
+
+
+
+
+ ))}
+ >
+ );
+};
+export default Parameter;
diff --git a/components/Notes.tsx b/components/Notes.tsx
index a830258..277b6a9 100644
--- a/components/Notes.tsx
+++ b/components/Notes.tsx
@@ -56,7 +56,7 @@ const Notes = () => {
/>
-