Skip to content

Commit 232e6a9

Browse files
author
kim
committed
feat: use final pink coral, move graph below
1 parent cce0d44 commit 232e6a9

File tree

22 files changed

+4976
-267
lines changed

22 files changed

+4976
-267
lines changed

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,8 @@
2828
"react-i18next": "15.4.1",
2929
"react-toastify": "11.0.5",
3030
"recharts": "^3.1.0",
31-
"typescript": "5.8.3"
31+
"typescript": "5.8.3",
32+
"vite-plugin-svgr": "^4.5.0"
3233
},
3334
"scripts": {
3435
"dev": "yarn vite",

src/config/constants.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
export const THERMOMETER_COLOR = 'red';
22
export const THERMOMETER_WIDTH = 20;
33
export const THERMOMETER_RADIUS = 20;
4-
export const THERMOMETER_POSITION_X = 50;
4+
export const THERMOMETER_POSITION_X = 70;
55
export const THERMOMETER_STROKE_WIDTH = 3;
66
export const THERMOMETER_STROKE_COLOR = 'black';
77
// these factors are used as percentage depending on stage dimensions
8-
export const THERMOMETER_POSITION_Y_FACTOR = 0.2;
8+
export const THERMOMETER_POSITION_Y_FACTOR = 0.15;
99
export const THERMOMETER_HEIGHT_FACTOR = 0.5;
1010
export const SCALE_UNITS = {
1111
KELVIN: { name: 'kelvin', unit: 'K' },
@@ -57,12 +57,12 @@ export const PLAYING_STRING = 'playing';
5757

5858
export const CORAL_COLOR = '#F08080';
5959

60-
export const INIT_KELP_AMOUNT = 50;
60+
export const INIT_KELP_AMOUNT = 100;
6161
export const INIT_GROWTH_SCALE = 50;
6262
export const INIT_CURRENT_TEMPERATURE = 25;
6363

64-
export const KELP_SPEED = 0.6;
65-
export const TIME_SPEED = 0.1; // Macro: 0.1 Micro: 0.02
64+
export const KELP_SPEED = 1.2;
65+
export const TIME_SPEED = 0.2; // Macro: 0.1 Micro: 0.02
6666
export const DEATH_DAY = 14;
6767

6868
export const MIN_TEMP_GROWTH = 23;

src/modules/Controls.tsx

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
/* eslint-disable @typescript-eslint/explicit-function-return-type */
2+
import PauseIcon from '@mui/icons-material/Pause';
3+
import PlayArrowIcon from '@mui/icons-material/PlayArrow';
4+
import RestartAltIcon from '@mui/icons-material/RestartAlt';
5+
import { Button, IconButton, Stack } from '@mui/material';
6+
7+
import { View } from '@/config/types';
8+
import { useAnimation, useContext, useSetAnimation } from '@/utils/hooks';
9+
10+
const backgroundColor = 'rgba(200, 200, 200, 0.5)';
11+
12+
const Debug = () => {
13+
// const { data: kelpAmount } = useKelpAmount();
14+
const { data: isPlaying } = useAnimation();
15+
const {
16+
data: { view },
17+
} = useContext();
18+
19+
// const { data: growthScale } = useGrowthScale();
20+
const { mutate: setAnimation } = useSetAnimation();
21+
// const { data: isDead } = useIsDead();
22+
23+
return (
24+
<Stack>
25+
<Stack direction="row" spacing={1} mb={1}>
26+
{/* <IconButton
27+
title="reset"
28+
onClick={() => reset()}
29+
sx={{ background: backgroundColor }}
30+
>
31+
<RestartAltIcon />
32+
</IconButton> */}
33+
{isPlaying ? (
34+
<IconButton
35+
title="pause"
36+
onClick={() => setAnimation(false)}
37+
sx={{ background: backgroundColor }}
38+
color="warning"
39+
>
40+
<PauseIcon fontSize="large" />
41+
</IconButton>
42+
) : (
43+
<IconButton
44+
title="play"
45+
onClick={() => setAnimation(true)}
46+
sx={{ background: backgroundColor }}
47+
color="success"
48+
>
49+
<PlayArrowIcon fontSize="large" />
50+
</IconButton>
51+
)}
52+
</Stack>
53+
{/* <FormControl>
54+
<RadioGroup
55+
aria-labelledby="demo-radio-buttons-group-label"
56+
value={view}
57+
name="radio-buttons-group"
58+
onChange={(e) => {
59+
if (e.target.value) {
60+
setView(e.target.value as View);
61+
}
62+
}}
63+
>
64+
<FormControlLabel
65+
value={View.Macro}
66+
control={<Radio />}
67+
label="Macro"
68+
/>
69+
<FormControlLabel
70+
value={View.Micro}
71+
control={<Radio />}
72+
label="Micro"
73+
/>
74+
</RadioGroup>
75+
</FormControl> */}
76+
</Stack>
77+
);
78+
};
79+
80+
export default Debug;

src/modules/DayCounter.tsx

Lines changed: 0 additions & 67 deletions
This file was deleted.

src/modules/DayGraph.tsx

Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
import { JSX } from 'react';
2+
3+
import {
4+
Area,
5+
AreaChart,
6+
Bar,
7+
CartesianGrid,
8+
ComposedChart,
9+
DotItemDotProps,
10+
Line,
11+
Tooltip,
12+
XAxis,
13+
YAxis,
14+
} from 'recharts';
15+
16+
import { useTemperatureHistory, useTime } from '@/utils/hooks';
17+
18+
const DAY_INTERVAL = 10;
19+
const controlsWidth = 150;
20+
21+
function humanizeDays(value) {
22+
const days = Math.floor(value);
23+
const hours = Math.round((value - days) * 24);
24+
25+
let result = [];
26+
27+
if (days > 0) {
28+
result.push(days === 1 ? '1 day' : `${days} days`);
29+
}
30+
31+
if (hours > 0) {
32+
result.push(hours === 1 ? '1 hour' : `${hours} hours`);
33+
}
34+
35+
return result.join(' and ');
36+
}
37+
38+
const CustomTooltip = ({
39+
active,
40+
payload,
41+
label,
42+
}: TooltipContentProps<string | number, string>) => {
43+
const isVisible = active && payload && payload.length;
44+
console.log(payload);
45+
return (
46+
<div
47+
style={{
48+
visibility: isVisible ? 'visible' : 'hidden',
49+
backgroundColor: 'white',
50+
padding: '2px',
51+
border: '1px solid #ccc',
52+
}}
53+
>
54+
{isVisible && (
55+
<>
56+
<div>{`${humanizeDays(label)}`}</div>
57+
<div style={{ fontWeight: 'bold' }}>
58+
{`${payload[0].value.toFixed(1)}°C`}{' '}
59+
</div>
60+
</>
61+
)}
62+
</div>
63+
);
64+
};
65+
66+
// const CustomizedDot = (props: DotItemDotProps) => {
67+
// const { cx, cy, value, payload } = props;
68+
69+
// if (cx == null || cy == null) {
70+
// return <g />;
71+
// }
72+
73+
// return (
74+
// <svg
75+
// x={cx - 10}
76+
// y={cy - 10}
77+
// width={20}
78+
// height={20}
79+
// fill="red"
80+
// viewBox="0 0 1024 1024"
81+
// >
82+
// <path d="M512 1009.984c-274.912 0-497.76-222.848-497.76-497.76s222.848-497.76 497.76-497.76c274.912 0 497.76 222.848 497.76 497.76s-222.848 497.76-497.76 497.76zM340.768 295.936c-39.488 0-71.52 32.8-71.52 73.248s32.032 73.248 71.52 73.248c39.488 0 71.52-32.8 71.52-73.248s-32.032-73.248-71.52-73.248zM686.176 296.704c-39.488 0-71.52 32.8-71.52 73.248s32.032 73.248 71.52 73.248c39.488 0 71.52-32.8 71.52-73.248s-32.032-73.248-71.52-73.248zM772.928 555.392c-18.752-8.864-40.928-0.576-49.632 18.528-40.224 88.576-120.256 143.552-208.832 143.552-85.952 0-164.864-52.64-205.952-137.376-9.184-18.912-31.648-26.592-50.08-17.28-18.464 9.408-21.216 21.472-15.936 32.64 52.8 111.424 155.232 186.784 269.76 186.784 117.984 0 217.12-70.944 269.76-186.784 8.672-19.136 9.568-31.2-9.12-40.096z" />
83+
// </svg>
84+
// );
85+
// };
86+
87+
// eslint-disable-next-line react/function-component-definition
88+
function DayGraph(): JSX.Element {
89+
const { data: time } = useTime();
90+
const { data: log } = useTemperatureHistory();
91+
92+
const slicedData = log.filter(
93+
({ t }) => t > Math.max(time - DAY_INTERVAL, 0),
94+
);
95+
96+
return (
97+
<AreaChart
98+
// minus padding, minus controls width
99+
width={window.innerWidth - 100 - controlsWidth}
100+
height={150}
101+
data={slicedData}
102+
margin={{ right: 20 }}
103+
style={{
104+
borderRadius: 30,
105+
}}
106+
>
107+
<CartesianGrid strokeDasharray="3 3" />
108+
<Area
109+
type="monotone"
110+
dataKey="temp"
111+
stroke="#8884d8"
112+
isAnimationActive={false}
113+
/>
114+
{/* <Line
115+
type="monotone"
116+
dataKey="temp"
117+
stroke="#8884d8"
118+
dot={CustomizedDot}
119+
/> */}
120+
<XAxis
121+
dataKey="t"
122+
tickFormatter={(t) => Math.floor(t).toString()}
123+
type="number"
124+
label={{ value: 'days', position: 'insideBottom' }}
125+
minTickGap={0}
126+
ticks={Array.from(
127+
{ length: DAY_INTERVAL },
128+
(x, k) => Math.max(time - DAY_INTERVAL, 0) + k,
129+
)}
130+
style={{
131+
fontSize: '0.8rem',
132+
}}
133+
/>
134+
<YAxis
135+
label={{
136+
value: 'temperature',
137+
angle: -90,
138+
position: 'inside',
139+
textAnchor: 'middle',
140+
}}
141+
includeHidden
142+
domain={[20, 38]}
143+
tickFormatter={(t) => Math.floor(t).toString()}
144+
style={{
145+
fontSize: '0.8rem',
146+
}}
147+
/>
148+
<Tooltip content={CustomTooltip} />
149+
</AreaChart>
150+
);
151+
}
152+
153+
export default DayGraph;

src/modules/Debug.tsx

Lines changed: 7 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,26 @@
11
/* eslint-disable @typescript-eslint/explicit-function-return-type */
22
import { Button } from '@mui/material';
33

4-
import { useAnimation, useReset, useSetAnimation } from '@/utils/hooks';
4+
import { useContext, useReset } from '@/utils/hooks';
55

66
const Debug = () => {
77
// const { data: kelpAmount } = useKelpAmount();
8-
const { data: isPlaying } = useAnimation();
98

109
// const { data: growthScale } = useGrowthScale();
1110
const { mutate: reset } = useReset();
12-
const { mutate: setAnimation } = useSetAnimation();
11+
const {
12+
data: { alive },
13+
} = useContext();
1314
// const { data: isDead } = useIsDead();
1415

1516
return (
16-
<div style={{ position: 'absolute', top: 0, left: 200, zIndex: 1000000 }}>
17+
<div style={{ position: 'absolute', top: 0, right: 200, zIndex: 1000000 }}>
1718
<br />
1819
<Button title="reset" onClick={() => reset()}>
1920
Reset
2021
</Button>
21-
{isPlaying ? (
22-
<Button title="stop" onClick={() => setAnimation(false)}>
23-
Stop
24-
</Button>
25-
) : (
26-
<Button title="stop" onClick={() => setAnimation(true)}>
27-
Start
28-
</Button>
29-
)}
22+
<br />
23+
Alive: {alive}
3024
</div>
3125
);
3226
};

src/modules/Root.tsx

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -55,12 +55,7 @@ const Root = (): ReactNode => (
5555
<ToastContainer />
5656

5757
<App />
58-
{import.meta.env.DEV && (
59-
<>
60-
<ReactQueryDevtools position="bottom" />
61-
<Debug />
62-
</>
63-
)}
58+
{import.meta.env.DEV && <ReactQueryDevtools position="bottom" />}
6459
</QueryClientProvider>
6560
</I18nextProvider>
6661
</ThemeProvider>

0 commit comments

Comments
 (0)