Skip to content

Commit

Permalink
refactored the game compoent
Browse files Browse the repository at this point in the history
  • Loading branch information
staranbeer committed Sep 15, 2022
1 parent d0aa6fa commit 4f3ca44
Show file tree
Hide file tree
Showing 9 changed files with 153 additions and 112 deletions.
103 changes: 54 additions & 49 deletions lib/generateKeywords.js
Original file line number Diff line number Diff line change
@@ -1,53 +1,58 @@
// a list of javascript keywords
// different types of javascript keywords

let keywords = [
"let",
"break",
"case",
"catch",
"continue",
"debugger",
"default",
"delete",
"do",
"else",
"finally",
"for",
"function",
"if",
"in",
"instanceof",
"new",
"return",
"switch",
"this",
"throw",
"try",
"typeof",
"let",
"while",
"class",
"const",
"enum",
"export",
"extends",
"import",
"super",
"static",
"yield",
"null",
"true",
"false",
"undefined",
"boolean",
];
let keywords = {
"Vanilla Js": [
"let",
"break",
"case",
"catch",
"continue",
"debugger",
"default",
"delete",
"do",
"else",
"finally",
"for",
"function",
"if",
"in",
"instanceof",
"new",
"return",
"switch",
"this",
"throw",
"try",
"typeof",
"let",
"while",
"class",
"const",
"enum",
"export",
"extends",
"import",
"super",
"static",
"yield",
"null",
"true",
"false",
"undefined",
"boolean",
],
};

// generate a random array of keywords from the above array
let randomKeywords = [];
const generateKeywords = (mode = "Vanilla Js") => {
// generate a random array of keywords from the array of mode type
let randomKeywords = [];

for (let i = 0; i < 100; i++) {
let randomIndex = Math.floor(Math.random() * keywords.length);
randomKeywords.push(keywords[randomIndex]);
}
for (let i = 0; i < 100; i++) {
let randomIndex = Math.floor(Math.random() * keywords[mode].length);
randomKeywords.push(keywords[mode][randomIndex]);
}
return randomKeywords;
};

export default randomKeywords;
export default generateKeywords;
16 changes: 15 additions & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-icons": "^4.4.0",
"react-redux": "^8.0.2"
"react-redux": "^8.0.2",
"uuid": "^9.0.0"
},
"devDependencies": {
"@types/react": "^18.0.17",
Expand Down
2 changes: 1 addition & 1 deletion src/App.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { Box, Button, useDisclosure, VStack } from "@chakra-ui/react";
import { useDispatch, useSelector } from "react-redux";
import Introduction from "./components/Layout/Introduction";
import Stats from "./components/Layout/Stats";
import Game from "./components/Layout/CodeArea/Game";
import Game from "./components/Layout/Game/Game";
import Header from "./components/Layout/Header";

/* actions */
Expand Down
7 changes: 0 additions & 7 deletions src/components/Layout/CodeArea/Char.jsx

This file was deleted.

7 changes: 7 additions & 0 deletions src/components/Layout/Game/Char.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import React from "react";

const Char = ({ children, isCorrect = false }) => {
return <span style={{ color: isCorrect ? "#fff" : "#333" }}>{children}</span>;
};

export default Char;
17 changes: 17 additions & 0 deletions src/components/Layout/Game/Characters.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import React from "react";
import { v4 as uuidv4 } from "uuid";
import Char from "./Char";

const Characters = ({ characters }) => {
return (
<>
{characters.map((i) => (
<Char key={uuidv4()} isCorrect={i.isCorrect}>
{i.key}
</Char>
))}
</>
);
};

export default Characters;
Original file line number Diff line number Diff line change
@@ -1,70 +1,63 @@
import React, { useState, useEffect, useCallback } from "react";
import { Box, HStack, Stack } from "@chakra-ui/react";
import React, { useCallback } from "react";
import { useState } from "react";
import { useEffect } from "react";
import keywords from "../../../../lib/generateKeywords";
import isValidKey from "../../../../lib/isValidKey";
import isInLimit from "../../../../lib/isInlimit";
import isSameKey from "../../../../lib/isSameKey";
import Char from "./Char";
import { useDispatch, useSelector } from "react-redux";
import { incrementCorrect, incrementWrong } from "../../../store/statsSlice";
import Characters from "./Characters";

const Game = ({ incrementRight, incrementWrong, hasStarted, hasEnded }) => {
const Game = () => {
const dispatch = useDispatch();

/* global state */
const { hasStarted, hasEnded } = useSelector((state) => state.game);
const { keywords } = useSelector((state) => state.code);

/* component state */
const [pressedKey, setPressedKey] = useState("");

const [arrayIndex, setArrayIndex] = useState(0);
const [index, setIndex] = useState(0);
const [arrayIndex, setArrayIndex] = useState(0);

const [currentKey, setCurrentKey] = useState("");
const [beforeKeys, setBeforeKeys] = useState([]);
const [afterKeys, setAfterKeys] = useState([]);

const [code, setCode] = useState(keywords[arrayIndex]);

const handleKeyDown = useCallback((e) => {
// 1. whenever a key is pressed, set the pressedKey to the key that was pressed
// 2. increment the index if index is less than the length of the code

if (isValidKey(e.key)) {
setPressedKey(e.key);
if (isInLimit(index, code.length)) {
setIndex((prevIndex) => prevIndex + 1);
}
}
}, []);

/* Add an event listener to the window */
useEffect(() => {
// add a keydown event listener when
// the game starts

if (hasStarted && !hasEnded) {
window.addEventListener("keydown", handleKeyDown);
}

// remove the listener when game ends

if (hasEnded) {
console.log("it has ended");
window.removeEventListener("keydown", handleKeyDown);
}

return () => window.removeEventListener("keydown", handleKeyDown);
}, [hasStarted, hasEnded]);

useEffect(() => {
// 1. whenever the index reaches the length of the code string,
// reset the index to 0 and add 1 to the arrayIndex

// 2. Reset all of the values to their initial state
/* check which key was pressed */
const handleKeyDown = useCallback((e) => {
// 1. whenever a key is pressed, set the pressedKey to the key that was pressed
// 2. increment the index if index is less than the length of the code

if (index === code.length) {
setIndex(0);
setArrayIndex((prevArrayIndex) => prevArrayIndex + 1);
setCode(keywords[arrayIndex]);
setBeforeKeys([]);
setAfterKeys([]);
setPressedKey("");
if (isValidKey(e.key)) {
setPressedKey(e.key);
if (isInLimit(index, code.length)) {
setIndex((prevIndex) => prevIndex + 1);
}
}
}, [index]);

useEffect(() => {
console.log(hasEnded);
}, [hasEnded]);
}, []);

/* if <pressedKey> is equal to the <currentKey>, change its color */
useEffect(() => {
// 1. whenever a valid key is pressed, set the currentKey to the next
// character in the code string.
Expand All @@ -82,26 +75,26 @@ const Game = ({ incrementRight, incrementWrong, hasStarted, hasEnded }) => {

if (isSameKey(pressedKey, currentKey)) {
// if the pressed key and the current key are the same
incrementRight();
dispatch(incrementCorrect());

if (index < code.length) {
// if the index is in bounds of the code string

setBeforeKeys((prev) => [
...prev,
{ key: currentKey, color: "white" },
{ key: currentKey, isCorrect: true },
]);
}
} else {
incrementWrong();
dispatch(incrementWrong());
// if the currentKey and pressed key are not the same

if (index < code.length) {
// if the index is in bounds of the code string

setBeforeKeys((prev) => [
...prev,
{ key: currentKey, color: "darkgray" },
{ key: currentKey, isCorrect: false },
]);
}
}
Expand All @@ -110,7 +103,24 @@ const Game = ({ incrementRight, incrementWrong, hasStarted, hasEnded }) => {
// if the pressed key is not an alphanumeric character
}

setAfterKeys(code.split("").slice(index + 1));
setAfterKeys(
code
.split("")
.slice(index + 1)
.map((i) => ({ key: i, isCorrect: false }))
);
}, [index]);

/* when the current word finishes, go to the next word */
useEffect(() => {
if (index === code.length) {
setIndex(0);
setArrayIndex((prevArrayIndex) => prevArrayIndex + 1);
setCode(keywords[arrayIndex]);
setBeforeKeys([]);
setAfterKeys([]);
setPressedKey("");
}
}, [index]);

return (
Expand All @@ -122,17 +132,9 @@ const Game = ({ incrementRight, incrementWrong, hasStarted, hasEnded }) => {
color="gray.400"
fontSize={"2xl"}
>
{beforeKeys.map((i, index) => {
return (
<Char key={index} color={i.color}>
{i.key}
</Char>
);
})}
<Characters characters={beforeKeys} />
<span className="cursor key">{currentKey}</span>
{afterKeys.map((i, index) => {
return <Char key={index}>{i}</Char>;
})}
<Characters characters={afterKeys} />
</Box>
</HStack>
);
Expand Down
4 changes: 3 additions & 1 deletion src/store/codeSlice.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import { createSlice } from "@reduxjs/toolkit";
import generateKeywords from "../../lib/generateKeywords";

const codeSlice = createSlice({
name: "code",
initialState: {
codeString: "",
mode: "",
keywords: generateKeywords(),
},
reducers: {
changeCode: (state, action) => {
Expand Down

0 comments on commit 4f3ca44

Please sign in to comment.