Skip to content

Commit

Permalink
Updated a bit and added some docker stuff
Browse files Browse the repository at this point in the history
  • Loading branch information
csprance committed Jul 4, 2022
1 parent b89d1d0 commit eab2fc9
Show file tree
Hide file tree
Showing 11 changed files with 565 additions and 186 deletions.
3 changes: 3 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
node_modules
.idea
build
14 changes: 14 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
FROM node:17

# install the application
RUN mkdir /app
WORKDIR /app
COPY package.json .
RUN yarn install
COPY . .

EXPOSE 3000

# build and start
RUN npm run build
CMD serve -s build
22 changes: 22 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
version: '3'

services:
graphtoy-plus:
restart: always
container_name: graphtoy-plus
build:
context: .
networks:
- web
environment:
NODE_ENV: 'production'
labels:
traefik.docker.network: 'web'
traefik.enable: 'true'
traefik.backend: 'graphtoy-plus'
traefik.frontend.rule: 'Host:graphtoy.csprance.com,www.graphtoy.csprance.com'
traefik.port: '3000'

networks:
web:
external: true
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,14 @@
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-scripts": "5.0.1",
"serve": "^13.0.2",
"styled-components": "^5.3.5",
"typescript": "^4.7.4",
"web-vitals": "^2.1.4",
"zustand": "^4.0.0-rc.1"
},
"scripts": {
"serve": "serve -s build",
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
Expand Down
9 changes: 3 additions & 6 deletions public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,10 @@
work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`.
-->
<title>React App</title>
<title>GraphToy</title>
<script>

function stepNaN(a, x) {
return Number.isNaN(x) || Number.isNaN(a) || x > a ? x :Number.NaN;
return Number.isNaN(x) || Number.isNaN(a) || x > a ? x : Number.NaN;
}
function clamp(x, a, b) {
if (x < a) return a;
Expand Down Expand Up @@ -150,12 +149,10 @@
const b = (2.0 * cellnoise(i + 1) - 1.0) * (f - 1.0);
return 2.0 * (a + (b - a) * w);
}

</script>
</head>
<body >
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>

</body>
</html>
14 changes: 7 additions & 7 deletions src/components/Formula.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,29 +6,29 @@ interface Props {
formula: Formula;
}
const FormulaComponent: React.FC<Props> = ({ formula }) => {
const [enabled, setEnabled] = React.useState(true);
const {
setFocusedFormula,
toggleFormulaVisibility,
setFormulaValue,
formulaColors,
grapher
} = useStore();

return (
<div className="formulaSection">
<div
id={`f${formula.index}`}
onClick={() => toggleFormulaVisibility(formula.index)}
onClick={() => {
setEnabled(!enabled)
grapher?.toggleVisibility(formula.index)
}}
style={{
color: formula.enabled ? formulaColors[formula.index - 1] : '#808080',
color: enabled ? formulaColors[formula.index - 1] : '#808080',
}}
>
f<sub>{formula.index}</sub>(x,t) = &nbsp;
</div>
<input
type="text"
onFocus={() => {
setFocusedFormula(formula.index);
}}
autoCorrect="off"
autoCapitalize="none"
className="userInput"
Expand Down
69 changes: 36 additions & 33 deletions src/components/Graph.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,51 +7,48 @@ import ResetIcon from './ResetIcon';

interface Props {}
const Graph: React.FC<Props> = ({}) => {
const [paused, setPaused] = React.useState(false);
const {
paused,
setTime,
togglePlay,
toggleTheme,
toggleGridType,
toggleRange,
setGrapher,
} = useStore();

const grapherRef = React.useRef<Grapher | null>(null);
const canvasRef = React.useRef(null);

React.useEffect(() => {
const grapher = new Grapher(useStore);
setGrapher(grapher);
grapher.setCanvas(canvasRef.current);
grapher.start();
useStore.subscribe((state, previousState) => {
// If the state says the grapher should be paused and it's not paused pause it
if (state.paused && !grapher.mPaused) {
grapher.togglePlay();
}
// If the state says the grapher should not be paused and grapher says it's paused unpause it
if (!state.paused && grapher.mPaused) {
grapher.togglePlay();
}
// for (let i = 0; i < state.formulas.length; i++) {
if (state.variables !== previousState.variables) {
grapher.newFormula(1);
// Compile our formulas
}
// }
for (let i = 0; i < state.formulas.length; i++) {
if (state.formulas[i].value !== previousState.formulas[i].value) {
grapher.newFormula(i + 1);
if (!grapherRef.current) {
console.log('Using effect');
const grapher = new Grapher(useStore);
setGrapher(grapher);
grapherRef.current = grapher;
grapher.setCanvas(canvasRef.current);
grapher.start();
useStore.subscribe((state, previousState) => {
// for (let i = 0; i < state.formulas.length; i++) {
if (state.variables !== previousState.variables) {
grapher.newFormula(1);
// Compile our formulas
}
}
// }
for (let i = 0; i < state.formulas.length; i++) {
if (state.formulas[i].value !== previousState.formulas[i].value) {
grapher.newFormula(i + 1);
// Compile our formulas
}
}

// TODO: Add in the new formulas when the old change
});
// const args = decodeURIComponent(
// window.location.href.slice(window.location.href.indexOf('?') + 1)
// ).split('&');
// grapher.parseUrlFormulas(args);
}, []);
// TODO: Add in the new formulas when the old change
});
// const args = decodeURIComponent(
// window.location.href.slice(window.location.href.indexOf('?') + 1)
// ).split('&');
// grapher.parseUrlFormulas(args);
}
}, [setGrapher]);

return (
<div
Expand Down Expand Up @@ -117,7 +114,13 @@ Zoom: Mouse Wheel, or Shift+Left Mouse Button"
>
<ResetIcon />
</div>
<div className="userInputButtonsMedium" onClick={togglePlay}>
<div
className="userInputButtonsMedium"
onClick={() => {
setPaused(!paused);
grapherRef.current!.togglePlay();
}}
>
{paused ? <PlayIcon /> : <PauseIcon />}
</div>
</div>
Expand Down
26 changes: 23 additions & 3 deletions src/components/VariableComponent.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import * as React from 'react';
import {useStore, Variable} from '../store';
import { useStore, Variable } from '../store';
import styled from 'styled-components';

const Wrapper = styled.div`
display: grid;
grid-template-columns: 50px auto 50px;
grid-template-columns: 50px auto 50px 50px;
align-items: center;
//justify-content: center;
`;

interface Props extends Variable {}
Expand All @@ -29,7 +31,25 @@ const VariableComponent: React.FC<Props> = ({
className="slider"
id="a"
onChange={(e) => {
setVariable(id, Number(e.target.value));
setVariable(id, { value: Number(e.target.value) });
}}
/>

<input
style={{height: 20, marginLeft: 5, marginRight: 5}}
type="text"
value={min}
onChange={(e) => {
setVariable(id, { min: Number(e.target.value) });
}}
/>

<input
style={{height: 20, marginLeft: 5,marginRight: 5}}
type="text"
value={max}
onChange={(e) => {
setVariable(id, { max: Number(e.target.value) });
}}
/>
</Wrapper>
Expand Down
56 changes: 47 additions & 9 deletions src/lib/graphtoy/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,19 @@
// TODO: Allow Grapher to have a canvas set and then take in an arbitary amount of formulas with colors
import { StoreApi, UseBoundStore } from 'zustand';
import { MyStore } from '../../store';
import graph from '../../components/Graph';

// A formula is the data structure that describes a math formula and metadata
export interface Formula {
// The value is the expression to evaluate
value: string;
// Should this formula show up in the graph
enabled: boolean;
// What is the id of this formula
index: number;
// the compiled function
compiledFunc: () => void;
}

export default class Grapher {
// --- private ----------------------------------------------
Expand Down Expand Up @@ -56,6 +69,7 @@ export default class Grapher {
mStartMS: number = 0;
mTimeS: number = 0.0;
mTheme: number = 0;
formulas: Formula[] = [];
mFocusFormula: Element | null = null;
mFunctionFun = [null, null, null, null, null, null];
mFunctionVis = [true, true, true, true, true, true];
Expand Down Expand Up @@ -157,12 +171,13 @@ export default class Grapher {
window.onresize = (ev) => {
this.iResize(ev);
};

this.store.getState().formulas.forEach((val, idx) => {
this.iCompile(idx);
});
this.iAdjustCanvas();
this.iDraw();
this.togglePlay();
this.iDraw();
}

private iMouseUp(e: any) {
Expand Down Expand Up @@ -456,14 +471,14 @@ export default class Grapher {
const t = this.mTimeS;
this.mContext.beginPath();
let oldy = 0.0;
let A,
B,
C,
D,
E,
F,
G,
H = 0.0;
let A: number,
B: number,
C: number,
D: number,
E: number,
F: number,
G: number,
H: number = 0.0;

for (let i = 0; i < this.mXres; i++) {
const x = this.mCx + rx * (-1.0 + (2.0 * i) / this.mXres);
Expand Down Expand Up @@ -526,6 +541,29 @@ export default class Grapher {
ctx.fillStyle = theme.mBackground;
ctx.fillRect(0, 0, this.mXres, this.mYres);

// Set the fill style and draw a rectangle
const gradient = this.mContext.createLinearGradient(20, 0, 220, 0);

const gradVals = Array(256)
.fill(null)
.map((_, idx) => {
let f = this.mFunctionFun[0];
if (f) {
// @ts-ignore
return f(idx / 256, this.mTimeS, 0, 0, 0, 0, 0, 0, 0, 0);
}
return 0;
})
.map((val) => (isNaN(val) || val === Infinity ? 0 : val));
gradVals.forEach((val, idx) => {
gradient.addColorStop(
idx / 256,
`rgb(${val * 255}, ${val * 255}, ${val * 255})`
);
});
this.mContext.fillStyle = gradient;
this.mContext.fillRect(20, 20, 200, 200);

if (this.mRangeType === 0 || this.mRangeType === 1) {
ctx.fillStyle = theme.mBackgroundOut;
let ww = (this.mXres - this.mYres) / 2;
Expand Down
Loading

0 comments on commit eab2fc9

Please sign in to comment.