Skip to content

Commit

Permalink
Merge pull request #41 from thutasann/feat/type-race
Browse files Browse the repository at this point in the history
feat: scoreboard
  • Loading branch information
thutasann authored Apr 9, 2023
2 parents 43fbb85 + 1edd860 commit 8f63496
Show file tree
Hide file tree
Showing 8 changed files with 149 additions and 7 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ This is the Chat + Game Application crafted with MERN Stack & Socket.
- 🚀 Real-Time Typing
- 🚀 Canvas Drawing (MultiPlayer)
- 🚀 TIC-TAC-TOE Game (One vs One)
- 🚀 Type Race Game (MultiPlayer) [Beta]
- 🚀 Type Race Game (MultiPlayer)

## Onboarding and Games Screen

Expand Down
4 changes: 2 additions & 2 deletions frontend/src/components/type-race/counter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ const Counter: React.FC<ICounter> = ({ socket }) => {
return (
<div
className={`w-[300px] text-center text-white ${
msg && countDown ? 'block' : 'hidden'
} rounded-md py-5 px-7 bg-gradient-to-tr from-teal-400 to-teal-600 shadow-sm `}
msg && countDown ? 'block py-5' : 'hidden py-0'
} rounded-md px-7 bg-gradient-to-tr from-teal-400 to-teal-600 shadow-sm `}
>
<div className="flex items-center justify-center gap-2">
{msg === 'Starting Game in...' ? <Spinner /> : null}
Expand Down
65 changes: 65 additions & 0 deletions frontend/src/components/type-race/progress.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import { Progress } from '@chakra-ui/react';
import React from 'react';
import { PlayerProps } from '../../types';
import { Alert, AlertIcon, AlertTitle, useToast } from '@chakra-ui/react';

interface IProgress {
players: PlayerProps[];
player: PlayerProps;
wordsLength: number;
}

function calPercentage(player: PlayerProps, wordsLength: number): number {
if (player.currentWordIndex !== 0) {
return Number(((player.currentWordIndex! / wordsLength) * 100).toFixed(2));
}
return 0;
}

const CustomProgress: React.FC<IProgress> = ({
players,
player,
wordsLength,
}) => {
const percentage = calPercentage(player, wordsLength);
console.log('players', players);

return (
<div className="w-[90%] mt-[50px] border-t pt-[50px]">
<h2 className="text-center mb-7 text-2xl font-[600]">Progresses</h2>
<div className="flex items-center justify-between font-[500]">
<h5>
{player.nickName} <span className="font-[600]">(You)</span>
</h5>
<span>{percentage} %</span>
</div>
<Progress
value={percentage}
rounded="md"
colorScheme="teal"
/>

{/* Oponents */}
<div className="mt-7">
{players?.map((playerObj) => {
const percentage = calPercentage(playerObj, wordsLength);
return playerObj._id !== player._id ? (
<div key={playerObj._id}>
<div className="flex items-center justify-between font-[500]">
<h5>{playerObj.nickName}</h5>
<span>{percentage} %</span>
</div>
<Progress
value={percentage}
rounded="md"
colorScheme="teal"
/>
</div>
) : null;
})}
</div>
</div>
);
};

export default CustomProgress;
65 changes: 65 additions & 0 deletions frontend/src/components/type-race/score-board.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import React from 'react';
import {
Table,
Thead,
Tbody,
Tfoot,
Tr,
Th,
Td,
TableCaption,
TableContainer,
} from '@chakra-ui/react';

import { PlayerProps } from '../../types';

interface IScoreBoard {
players: PlayerProps[];
}

function getScoreBoard(players: PlayerProps[]): PlayerProps[] {
const scoreboard = players.filter((player) => player.WPM !== -1);
return scoreboard.sort((a, b) =>
a.WPM > b.WPM ? -1 : b.WPM > a.WPM ? 1 : 0,
);
}

const ScoreBoard: React.FC<IScoreBoard> = ({ players }) => {
const scoreBoard = getScoreBoard(players);

if (scoreBoard.length === 0) {
return null;
}

return (
<div className="my-[50px] w-[90%]">
<h2 className="text-center mb-3 text-2xl font-[600]">Scoreboard</h2>
<div>
<TableContainer
border="1px solid lightGray"
rounded="md"
p={5}
>
<Table variant="striped">
<Thead>
<Tr>
<Th>Player</Th>
<Th>Words Per Minutes (WPM)</Th>
</Tr>
</Thead>
<Tbody>
{scoreBoard?.map((player) => (
<Tr key={player._id}>
<Td>{player.nickName}</Td>
<Td>{player.WPM}</Td>
</Tr>
))}
</Tbody>
</Table>
</TableContainer>
</div>
</div>
);
};

export default ScoreBoard;
2 changes: 1 addition & 1 deletion frontend/src/components/type-race/type-race-input.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ const TypeRaceInput: React.FC<InputProps> = ({
return (
<div className="w-[350px] md:w-[750px]">
<input
className={`input mt-5 w-full ${
className={`input read-only:rounded-md mt-5 w-full ${
isOpen || isOver ? 'cursor-not-allowed' : 'cursor-auto'
}`}
placeholder="Enter Words"
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/miscellaneous/spinner.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ const Spinner = () => {
role="status"
>
<svg
className="h-6 w-6 animate-spin stroke-gray-500"
className="h-6 w-6 animate-spin stroke-white"
viewBox="0 0 256 256"
>
<line
Expand Down
14 changes: 13 additions & 1 deletion frontend/src/pages/type-race-page.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import { useToast } from '@chakra-ui/react';
import React, { useEffect, useState } from 'react';
import React, { useEffect } from 'react';
import { useNavigate, useParams } from 'react-router-dom';
import { Socket } from 'socket.io-client';
import Counter from '../components/type-race/counter';
import DisplayWords from '../components/type-race/display-words';
import CustomProgress from '../components/type-race/progress';
import ScoreBoard from '../components/type-race/score-board';
import StartBtn from '../components/type-race/start-btn';
import TypeRaceHeader from '../components/type-race/type-race-header';
import TypeRaceInput from '../components/type-race/type-race-input';
Expand Down Expand Up @@ -51,6 +53,7 @@ const TypeRacePage: React.FC<ITypeRacePage> = ({ socket }) => {
gameId={params.gameId!}
onClick={HanldeCopy}
/>

<Counter socket={socket} />

{player ? (
Expand All @@ -73,6 +76,15 @@ const TypeRacePage: React.FC<ITypeRacePage> = ({ socket }) => {
gameId={_id}
socket={socket}
/>
{player ? (
<CustomProgress
players={players}
player={player}
wordsLength={words.length}
/>
) : null}

{players ? <ScoreBoard players={players} /> : null}
</div>
</div>
);
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ export type PlayerProps = {
currentWordIndex?: number;
socketId: string;
isPartyLeader: boolean;
WPM?: number;
WPM: number;
nickName: string;
};

Expand Down

1 comment on commit 8f63496

@vercel
Copy link

@vercel vercel bot commented on 8f63496 Apr 9, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

chat-t – ./

chat-t-thutasann.vercel.app
mern-t-chat.vercel.app
chat-t-git-main-thutasann.vercel.app

Please sign in to comment.