From 1e8bd448130df54435c371a6e34656601925d118 Mon Sep 17 00:00:00 2001
From: Ralex91 <95540504+Ralex91@users.noreply.github.com>
Date: Sun, 4 Feb 2024 17:53:45 +0100
Subject: [PATCH] Large patch
---
.eslintrc.json | 2 +-
next.config.mjs | 10 +++
socket/src/index.js | 26 ++++--
socket/src/quizz.config.js | 22 +++--
socket/src/roles/manager.js | 20 +++--
socket/src/roles/player.js | 4 +-
socket/src/utils/deepClone.js | 20 +++++
socket/src/utils/round.js | 53 ++++++------
src/components/ManagerPassword.jsx | 47 +++++++++++
src/components/Toaster.jsx | 1 -
src/components/game/join/Room.jsx | 23 ++---
src/components/game/join/Username.jsx | 23 ++---
src/components/game/states/Answers.jsx | 5 +-
src/components/game/states/Podium.jsx | 106 ++++++++++++++++++++++++
src/components/game/states/Question.jsx | 10 ++-
src/components/game/states/Room.jsx | 5 ++
src/components/icons/Pentagon.jsx | 39 +++++++++
src/constants.js | 52 ++++++++++--
src/pages/api/hello.js | 5 --
src/pages/game.jsx | 45 ++++------
src/pages/index.js | 8 --
src/pages/manager.jsx | 34 ++------
src/pages/managerold.jsx | 63 --------------
23 files changed, 402 insertions(+), 221 deletions(-)
create mode 100644 socket/src/utils/deepClone.js
create mode 100644 src/components/ManagerPassword.jsx
create mode 100644 src/components/game/states/Podium.jsx
create mode 100644 src/components/icons/Pentagon.jsx
delete mode 100644 src/pages/api/hello.js
delete mode 100644 src/pages/managerold.jsx
diff --git a/.eslintrc.json b/.eslintrc.json
index e5ace1d..095995b 100644
--- a/.eslintrc.json
+++ b/.eslintrc.json
@@ -6,7 +6,7 @@
"next/core-web-vitals",
"plugin:react/recommended"
],
- "plugins": ["react", "react-hooks"],
+ "plugins": ["react"],
"env": {
"browser": true,
"node": true,
diff --git a/next.config.mjs b/next.config.mjs
index 4f2edee..4d2ddd3 100644
--- a/next.config.mjs
+++ b/next.config.mjs
@@ -9,6 +9,16 @@ const nextConfig = {
},
]
},*/
+ images: {
+ remotePatterns: [
+ {
+ protocol: "https",
+ hostname: "images.unsplash.com",
+ port: "",
+ pathname: "/**",
+ },
+ ],
+ },
}
export default nextConfig
diff --git a/socket/src/index.js b/socket/src/index.js
index 1323832..efa5962 100644
--- a/socket/src/index.js
+++ b/socket/src/index.js
@@ -2,8 +2,10 @@ import { Server } from "socket.io"
import { GAME_STATE_INIT } from "./quizz.config.js"
import Manager from "./roles/manager.js"
import Player from "./roles/player.js"
+import { abortCooldown } from "./utils/cooldown.js"
+import deepClone from "./utils/deepClone.js"
-let gameState = GAME_STATE_INIT
+let gameState = deepClone(GAME_STATE_INIT)
const io = new Server({
cors: {
@@ -25,8 +27,8 @@ io.on("connection", (socket) => {
Player.join(gameState, io, socket, player),
)
- socket.on("manager:createRoom", () =>
- Manager.createRoom(gameState, io, socket),
+ socket.on("manager:createRoom", (password) =>
+ Manager.createRoom(gameState, io, socket, password),
)
socket.on("manager:kickPlayer", (playerId) =>
Manager.kickPlayer(gameState, io, socket, playerId),
@@ -48,9 +50,21 @@ io.on("connection", (socket) => {
socket.on("disconnect", () => {
console.log(`user disconnected ${socket.id}`)
- /*if (gameState.manager === socket.id) {
+ if (gameState.manager === socket.id) {
console.log("Reset game")
- gameState = gameStateInit
- }*/
+ io.to(gameState.room).emit("game:reset")
+ gameState.started = false
+ gameState = deepClone(GAME_STATE_INIT)
+
+ abortCooldown()
+ return
+ }
+
+ const player = gameState.players.find((p) => p.id === socket.id)
+
+ if (player) {
+ gameState.players = gameState.players.filter((p) => p.id !== socket.id)
+ socket.to(gameState.manager).emit("manager:removePlayer", player.id)
+ }
})
})
diff --git a/socket/src/quizz.config.js b/socket/src/quizz.config.js
index 1c9195b..46b7528 100644
--- a/socket/src/quizz.config.js
+++ b/socket/src/quizz.config.js
@@ -1,11 +1,13 @@
export const GAME_STATE_INIT = {
started: false,
+ password: "PASSWORD",
players: [],
playersAnswer: [],
manager: null,
room: null,
currentQuestion: 0,
roundStartTime: 0,
+ subject: "Adobe",
questions: [
{
question: "Who are the founders of Adobe?",
@@ -15,21 +17,24 @@ export const GAME_STATE_INIT = {
"Jhon Jonse and Charles Geskie",
"Bill Gate",
],
- image: "/question/Adobe-Logo.png",
solution: 1,
+ cooldow: 5,
time: 15,
},
{
question: "What is Adobe's most famous software?",
answers: ["Encore", "AfterEffect", "Creative Cloud", "Photoshop"],
- image: "/question/Adobe-Packages.webp",
+ image:
+ "https://images.unsplash.com/photo-1626785774573-4b799315345d?q=80&w=500&auto=webp",
solution: 3,
+ cooldown: 5,
time: 15,
},
{
question: "When was Adobe created?",
answers: ["2000", "1982", "2003", "1987"],
solution: 1,
+ cooldown: 5,
time: 15,
},
{
@@ -40,8 +45,8 @@ export const GAME_STATE_INIT = {
"DowTown, Texas",
"Tokyo, Japan",
],
- image: "/question/Adobe_World_Headquarters.jpg",
solution: 0,
+ cooldown: 5,
time: 15,
},
{
@@ -52,8 +57,10 @@ export const GAME_STATE_INIT = {
"25,988 employees",
"5,073 employees",
],
- image: "/question/000012204568_Large.jpg",
+ image:
+ "https://images.unsplash.com/photo-1504384308090-c894fdcc538d?q=80&w=500&auto=webp",
solution: 2,
+ cooldown: 5,
time: 15,
},
{
@@ -64,8 +71,10 @@ export const GAME_STATE_INIT = {
"Mark Java",
"Shantanu Narayen",
],
- image: "/question/guess-the-person.png",
+ image:
+ "https://images.unsplash.com/photo-1435348773030-a1d74f568bc2?q=80&w=500&auto=webp",
solution: 3,
+ cooldown: 5,
time: 15,
},
{
@@ -76,7 +85,10 @@ export const GAME_STATE_INIT = {
"Logistics software",
"Other",
],
+ image:
+ "https://images.unsplash.com/photo-1582736317407-371893d9e146?q=80&w=500&auto=webp",
solution: 0,
+ cooldown: 5,
time: 15,
},
],
diff --git a/socket/src/roles/manager.js b/socket/src/roles/manager.js
index ee52fb8..8a933fc 100644
--- a/socket/src/roles/manager.js
+++ b/socket/src/roles/manager.js
@@ -2,11 +2,17 @@ import { GAME_STATE_INIT } from "../quizz.config.js"
import { startRound } from "../utils/round.js"
import generateRoomId from "../utils/generateRoomId.js"
import { cooldown, sleep } from "../utils/cooldown.js"
+import deepClone from "../utils/deepClone.js"
const Manager = {
- createRoom: (game, io, socket) => {
+ createRoom: (game, io, socket, password) => {
+ if (game.password !== password) {
+ io.to(socket.id).emit("game:errorMessage", "Bad Password")
+ return
+ }
+
if (game.manager || game.room) {
- io.to(socket.id).emit("message", "Already manager")
+ io.to(socket.id).emit("game:errorMessage", "Already manager")
return
}
@@ -28,6 +34,7 @@ const Manager = {
const player = game.players.find((p) => p.id === playerId)
game.players = game.players.filter((p) => p.id !== playerId)
+ io.in(playerId).socketsLeave(game.room)
io.to(player.id).emit("game:kick")
io.to(game.manager).emit("manager:playerKicked", player.id)
},
@@ -72,18 +79,19 @@ const Manager = {
showLoaderboard: (game, io, socket) => {
if (!game.questions[game.currentQuestion + 1]) {
- io.to(socket).emit("game:status", {
+ socket.emit("game:status", {
name: "FINISH",
data: {
- winners: game.players.slice(0, 3).sort((a, b) => b.points - a.points),
+ subject: game.subject,
+ top: game.players.slice(0, 3).sort((a, b) => b.points - a.points),
},
})
- game = GAME_STATE_INIT
+ game = deepClone(GAME_STATE_INIT)
return
}
- io.to(socket.id).emit("game:status", {
+ socket.emit("game:status", {
name: "SHOW_LEADERBOARD",
data: {
leaderboard: game.players
diff --git a/socket/src/roles/player.js b/socket/src/roles/player.js
index 5b7c20f..aed2b31 100644
--- a/socket/src/roles/player.js
+++ b/socket/src/roles/player.js
@@ -51,7 +51,7 @@ const Player = {
game.players.push(playerData)
- io.to(socket.id).emit("game:successJoin")
+ socket.emit("game:successJoin")
},
selectedAnswer: (game, io, socket, answerKey) => {
@@ -72,7 +72,7 @@ const Player = {
points: convertTimeToPoint(game.roundStartTime, question.time),
})
- io.to(socket.id).emit("game:status", {
+ socket.emit("game:status", {
name: "WAIT",
data: { text: "Waiting for the players to answer" },
})
diff --git a/socket/src/utils/deepClone.js b/socket/src/utils/deepClone.js
new file mode 100644
index 0000000..b169b29
--- /dev/null
+++ b/socket/src/utils/deepClone.js
@@ -0,0 +1,20 @@
+const deepClone = (obj) => {
+ if (obj === null || typeof obj !== "object") {
+ return obj
+ }
+
+ if (Array.isArray(obj)) {
+ return obj.map(deepClone)
+ }
+
+ const clonedObj = {}
+ for (const key in obj) {
+ if (obj.hasOwnProperty(key)) {
+ clonedObj[key] = deepClone(obj[key])
+ }
+ }
+
+ return clonedObj
+}
+
+export default deepClone
diff --git a/socket/src/utils/round.js b/socket/src/utils/round.js
index 63612ef..3c27d7f 100644
--- a/socket/src/utils/round.js
+++ b/socket/src/utils/round.js
@@ -3,6 +3,8 @@ import { cooldown, sleep } from "./cooldown.js"
export const startRound = async (game, io, socket) => {
const question = game.questions[game.currentQuestion]
+ if (!game.started) return
+
io.to(game.room).emit("game:updateQuestion", {
current: game.currentQuestion + 1,
total: game.questions.length,
@@ -16,19 +18,22 @@ export const startRound = async (game, io, socket) => {
},
})
- await sleep(4)
+ await sleep(2)
+
+ if (!game.started) return
io.to(game.room).emit("game:status", {
name: "SHOW_QUESTION",
data: {
question: question.question,
- number: game.currentQuestion + 1,
image: question.image,
- cooldown: 6,
+ cooldown: question.cooldown,
},
})
- await sleep(6)
+ await sleep(question.cooldown)
+
+ if (!game.started) return
game.roundStartTime = Date.now()
@@ -45,6 +50,8 @@ export const startRound = async (game, io, socket) => {
await cooldown(question.time, io, game.room)
+ if (!game.started) return
+
game.players.map(async (player) => {
let playerAnswer = await game.playersAnswer.find((p) => p.id === player.id)
@@ -55,32 +62,30 @@ export const startRound = async (game, io, socket) => {
let points =
(isCorrect && Math.round(playerAnswer && playerAnswer.points)) || 0
- game.players.find((p) => p.id === player.id).points += points
+ player.points += points
- setTimeout(() => {
- let sortPlayers = game.players.sort((a, b) => b.points - a.points)
+ let sortPlayers = game.players.sort((a, b) => b.points - a.points)
- let rank = sortPlayers.findIndex((p) => p.id === player.id) + 1
- let aheadPlayer = sortPlayers[rank - 2]
+ let rank = sortPlayers.findIndex((p) => p.id === player.id) + 1
+ let aheadPlayer = sortPlayers[rank - 2]
- io.to(player.id).emit("game:status", {
- name: "SHOW_RESULT",
- data: {
- correct: isCorrect,
- message: isCorrect ? "Nice !" : "Too bad",
- points: points,
- myPoints: player.points,
- rank,
- aheadOfMe: aheadPlayer ? aheadPlayer.username : null,
- },
- })
- }, 200)
+ io.to(player.id).emit("game:status", {
+ name: "SHOW_RESULT",
+ data: {
+ correct: isCorrect,
+ message: isCorrect ? "Nice !" : "Too bad",
+ points: points,
+ myPoints: player.points,
+ rank,
+ aheadOfMe: aheadPlayer ? aheadPlayer.username : null,
+ },
+ })
})
- let totalParType = {}
+ let totalType = {}
game.playersAnswer.forEach(({ answer }) => {
- totalParType[answer] = (totalParType[answer] || 0) + 1
+ totalType[answer] = (totalType[answer] || 0) + 1
})
// Manager
@@ -88,7 +93,7 @@ export const startRound = async (game, io, socket) => {
name: "SHOW_RESPONSES",
data: {
question: game.questions[game.currentQuestion].question,
- responses: totalParType,
+ responses: totalType,
correct: game.questions[game.currentQuestion].solution,
answers: game.questions[game.currentQuestion].answers,
image: game.questions[game.currentQuestion].image,
diff --git a/src/components/ManagerPassword.jsx b/src/components/ManagerPassword.jsx
new file mode 100644
index 0000000..5674cfe
--- /dev/null
+++ b/src/components/ManagerPassword.jsx
@@ -0,0 +1,47 @@
+import Image from "next/image"
+import { usePlayerContext } from "@/context/player"
+import Form from "@/components/Form"
+import Button from "@/components/Button"
+import Input from "@/components/Input"
+import { useEffect, useState } from "react"
+import { socket } from "@/context/socket"
+import logo from "@/assets/logo.svg"
+import toast from "react-hot-toast"
+
+export default function ManagerPassword() {
+ const [loading, setLoading] = useState(false)
+ const [password, setPassword] = useState("")
+
+ const handleCreate = () => {
+ socket.emit("manager:createRoom", password)
+ }
+
+ useEffect(() => {
+ socket.on("game:errorMessage", (message) => {
+ toast.error(message)
+ })
+
+ return () => {
+ socket.off("game:errorMessage")
+ }
+ }, [])
+
+ return (
+
+ {top[1].username} +
++ 2 +
++ {top[1].points} +
+= 4 }, + )} + > + {top[0].username} +
++ 1 +
++ {top[0].points} +
++ {top[2].username} +
++ 3 +
+ ++ {top[2].points} +
+{JSON.stringify(gameState)}
-