Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix/game screen/typing #120

Merged
merged 13 commits into from
Apr 16, 2024
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion typing-app/src/app/game/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ export default function Typing() {
`src/assets/texts/${filenames[Math.floor(Math.random() * filenames.length)]}`,
"utf-8"
);
const subjectTextOneLine = subjectText.replace(/\n/gm, " ");

return <GamePage subjectText={subjectText} />;
return <GamePage subjectText={subjectTextOneLine} />;
}
2 changes: 1 addition & 1 deletion typing-app/src/assets/texts/text4.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FellowCitizens of the Senate and House of Representatives:
Fellow-Citizens of the Senate and House of Representatives:

I embrace with great satisfaction the opportunity which now presents itself of congratulating you on the present favorable prospects of our public affairs. The recent accession of the important state of north Carolina to the Constitution of the United States (of which official information has been received), the rising credit and respectability of our country, the general and increasing good will toward the government of the Union, and the concord, peace, and plenty with which we are blessed are circumstances auspicious in an eminent degree to our national prosperity.
In resuming your consultations for the general good you can not but derive encouragement from the reflection that the measures of the last session have been as satisfactory to your constituents as the novelty and difficulty of the work allowed you to hope. Still further to realize their expectations and to secure the blessings which a gracious Providence has placed within our reach will in the course of the present important session call for the cool and deliberate exertion of your patriotism, firmness, and wisdom.
Expand Down
122 changes: 63 additions & 59 deletions typing-app/src/components/templates/GameTyping.tsx
h-takeyeah marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -1,17 +1,16 @@
import RegisterScore, { ResultScore } from "@/types/RegisterScore";
import RegisterScore from "@/types/RegisterScore";
import { Box } from "@chakra-ui/react";
import Image from "next/image";
import { client } from "@/libs/api";
import React, { useCallback, useEffect, useRef, useState } from "react";
import ProgressBar from "../atoms/ProgressBar";
import { GameTypingProps } from "../pages/Game";
import styles from "./GameTyping.module.css";

import { getCurrentUser } from "@/app/actions";
import gaugePositionImg from "../../../public/img/gauge_position.png";
import gaugeSpeedImg from "../../../public/img/gauge_speed.png";
import gaugeTimeImg from "../../../public/img/gauge_time.png";
import { User } from "@/types/user";
import { getCurrentUser } from "@/app/actions";
import { showErrorToast } from "@/utils/toast";
import { useRouter } from "next/navigation";

Expand Down Expand Up @@ -98,64 +97,69 @@ const GameTyping: React.FC<GameTypingProps> = ({ nextPage, subjectText, setResul
const [typingQueueList] = useState<number[]>([]);
const [currentTypeSpeed, setCurrentTypeSpeed] = useState(0);
const [averageTypeSpeed, setAverageTypeSpeed] = useState(0);
const addTypingQueueList = () => {
const time = new Date().valueOf();
typingQueueList.push(time);
if (typingQueueList.length > typingQueueListSize) {
typingQueueList.shift();
}
};

const getTypingQueueListIndex = (index: number): number => {
if (index < 0) {
return 0;
}
if (index >= typingQueueList.length) {
return typingQueueList.length - 1;
}
return 0;
};
const typeIndexRef = useRef(typeIndex);
useEffect(() => {
// setTypeIndexの結果を反映する
typeIndexRef.current = typeIndex;
}, [typeIndex]);

useEffect(() => {
const calcCurrentTypingSpeed = (): number => {
if (typingQueueList.length <= 1) {
return 0;
}
const typeTime = getTypingQueueListIndex(typingQueueList.length - 1) - getTypingQueueListIndex(0);
const currentWpm = (typingQueueList.length / typeTime) * 60000;
return currentWpm;
};

const calcAverageTypingSpeed = (): number => {
const timeFromStart: number = new Date().valueOf() - startedAt.valueOf();
const averageTypingSpeed: number = (correctType / timeFromStart) * 60000;
return averageTypingSpeed;
};

const addTypingQueueList = () => {
const time = new Date().valueOf();
typingQueueList.push(time);
if (typingQueueList.length > typingQueueListSize) {
typingQueueList.shift();
}
};

const calcCurrentTypingSpeed = (): number => {
if (typingQueueList.length <= 1) {
const getTypingQueueListIndex = (index: number): number => {
if (index < 0) {
return 0;
}
if (index >= typingQueueList.length) {
return typingQueueList.length - 1;
}
return 0;
}
const typeTime = getTypingQueueListIndex(typingQueueList.length - 1) - getTypingQueueListIndex(0);
const currentWpm = (typingQueueList.length / typeTime) * 60000; // TODO:マジックナンバー確認
return toLogarithmWpm(currentWpm);
};

const calcAverageTypingSpeed = (): number => {
const timeFromStart = new Date().valueOf() - startedAt.valueOf();
const averageTypingSpeed = (correctType / timeFromStart) * 60000; // TODO: マジックナンバー確認
return toLogarithmWpm(averageTypingSpeed);
};

const toLogarithmWpm = (wpm: number) => {
// TODO: マジックナンバー確認
const wpmForProgressBar = (1000 / 3) * Math.log10((999 / 1000) * wpm + 1);
if (wpmForProgressBar > 1000) {
return 1000;
}
return wpmForProgressBar;
};
};

const handleOnKeyDown = (e: React.KeyboardEvent) => {
const key = e.key;
if (key.length !== 1) {
return; // アルファベット等以外のキーは無視 shiftなどがここに入る
}
const currentType = subjectText[typeIndex];
if (key === currentType) {
setTypeIndex(typeIndex + 1);
setCorrectType(correctType + 1);
addTypingQueueList();
setCurrentTypeSpeed(calcCurrentTypingSpeed());
setAverageTypeSpeed(calcAverageTypingSpeed());
} else {
setIncorrectType(incorrectType + 1);
}
};
const handleOnKeyDown = (e: KeyboardEvent) => {
const key = e.key;
if (key.length !== 1) {
return; // アルファベット等以外のキーは無視 shiftなどがここに入る
}
const currentType = subjectText[typeIndexRef.current];
if (key === currentType) {
setTypeIndex((prev) => prev + 1);
setCorrectType((prev) => prev + 1);
addTypingQueueList();
setCurrentTypeSpeed(calcCurrentTypingSpeed());
setAverageTypeSpeed(calcAverageTypingSpeed());
} else {
setIncorrectType((prev) => prev + 1);
}
};

window.addEventListener("keydown", handleOnKeyDown);
return () => {
window.removeEventListener("keydown", handleOnKeyDown);
};
}, [correctType, startedAt, typingQueueList, subjectText]);

// ゲーム開始直後にフォーカスする
const boxRef = useRef<HTMLDivElement>(null);
Expand All @@ -166,7 +170,7 @@ const GameTyping: React.FC<GameTypingProps> = ({ nextPage, subjectText, setResul
}, []);

return (
<Box onKeyDown={handleOnKeyDown} tabIndex={0} ref={boxRef}>
<Box tabIndex={0} ref={boxRef}>
<div className={styles.box}>
{/* TODO: Article Nameって消すんじゃなかったっけ */}
<div className={`${styles.heading} ${styles.heading_name}`}>Article Name</div>
Expand All @@ -182,7 +186,7 @@ const GameTyping: React.FC<GameTypingProps> = ({ nextPage, subjectText, setResul
<div className={`${styles.progress} ${styles.progress_speed}`}>
<ProgressBar maxWidth={330} height={20} maxValue={1000} value={averageTypeSpeed} />
</div>
<Image className={styles.gauge_time} id="gauge_time" src={gaugeTimeImg} alt={""} width={281} height={22} />
<Image className={styles.gauge_time} id="gauge_time" src={gaugeTimeImg} alt={""} width={281} height={24} />
<Image
className={styles.gauge_position}
id="gauge_position"
Expand Down