mirror of
https://github.com/randyjc/Rahoot.git
synced 2026-03-13 20:15:35 +01:00
New config file and update README
This commit is contained in:
102
README.md
102
README.md
@@ -4,11 +4,101 @@
|
|||||||
<img align="center" src="https://api.visitorbadge.io/api/visitors?path=https://github.com/Ralex91/Rahoot/edit/main/README.md&countColor=%2337d67a">
|
<img align="center" src="https://api.visitorbadge.io/api/visitors?path=https://github.com/Ralex91/Rahoot/edit/main/README.md&countColor=%2337d67a">
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<h3 align="center">Rahoot is a straightforward and open-source clone of the Kahoot! platform, allowing users to host it on their own server for smaller events.</h3>
|
## 🧩 What is this project?
|
||||||
|
|
||||||
<hr>
|
Rahoot is a straightforward and open-source clone of the Kahoot! platform, allowing users to host it on their own server for smaller events.
|
||||||
|
|
||||||
<br>
|
> ⚠️ This project is still under development, please report any bugs or suggestions in the [issues](https://github.com/Ralex91/Rahoot/issues)
|
||||||
<h3 align="center">
|
|
||||||
Under development
|
## ⚙️ Prerequisites
|
||||||
<h3>
|
|
||||||
|
- Node.js version 20 or higher
|
||||||
|
|
||||||
|
## 📖 Getting Started
|
||||||
|
|
||||||
|
1. #### Clone the GitHub repository of your project.
|
||||||
|
```bash
|
||||||
|
git clone https://github.com/Ralex91/Rahoot.git
|
||||||
|
cd ./Rahoot
|
||||||
|
```
|
||||||
|
2. #### Install the dependencies using your preferred package manager
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install
|
||||||
|
```
|
||||||
|
|
||||||
|
<br>
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
## 📦 Running the Application in Production Mode:
|
||||||
|
|
||||||
|
1. #### Check websocket connfiguration in [config.mjs](config.mjs)
|
||||||
|
|
||||||
|
If you want the client to connect directly to the websocket server, edit the [config.mjs](config.mjs) file and change the localhost to your public IP address.
|
||||||
|
|
||||||
|
```js
|
||||||
|
export const WEBSOCKET_PUBLIC_URL = "http://1.2.3.4:3100/"
|
||||||
|
export const WEBSOCKET_SERVER_PORT = 3100
|
||||||
|
|
||||||
|
// Rest of the config ...
|
||||||
|
```
|
||||||
|
|
||||||
|
2. #### Start the application
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm run all
|
||||||
|
```
|
||||||
|
|
||||||
|
## ⚙️ Running the Application in Development Mode:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm run all-dev
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🔧 Configuration
|
||||||
|
|
||||||
|
Configuration can be found in [config.mjs](config.mjs)
|
||||||
|
|
||||||
|
```js
|
||||||
|
const QUIZZ_CONFIG = {
|
||||||
|
password: "PASSWORD", // Manager password
|
||||||
|
subject: "Adobe", // Subject of the quiz
|
||||||
|
questions: [
|
||||||
|
{ // Example question
|
||||||
|
question: "What is good answer ?", // Question
|
||||||
|
answers: [ // Possible answers
|
||||||
|
"No",
|
||||||
|
"Yes",
|
||||||
|
"No",
|
||||||
|
"No",
|
||||||
|
],
|
||||||
|
image:
|
||||||
|
"https://images.unsplash.com/....", // Image URL (optional)
|
||||||
|
solution: 1, // Index of the correct answer (index starts at 0)
|
||||||
|
cooldown: 5, // Show question cooldown in seconds
|
||||||
|
time: 15, // Time to answer in seconds
|
||||||
|
},
|
||||||
|
...
|
||||||
|
],
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🤔 How to use
|
||||||
|
|
||||||
|
- Go to [https://localhost:3000/manager](https://localhost:3000/manager) enter manager password.
|
||||||
|
|
||||||
|
- Share link [https://localhost:3000/](https://localhost:3000/) and code on manager screen with your friends and get ready to play.
|
||||||
|
|
||||||
|
- Once everyone is ready, start the game with button on the top left of the screen of manager.
|
||||||
|
|
||||||
|
## 📝 Contributing
|
||||||
|
|
||||||
|
- Create a fork
|
||||||
|
|
||||||
|
- Create work branch (Example: githubUsername/featureName).
|
||||||
|
|
||||||
|
- Commit and push your changes in the work branch.
|
||||||
|
|
||||||
|
- Open a pull request.
|
||||||
|
|
||||||
|
- Your pull request would be merged and changes will be reflected in the main repository.
|
||||||
|
|||||||
@@ -1,12 +1,8 @@
|
|||||||
export const GAME_STATE_INIT = {
|
export const WEBSOCKET_PUBLIC_URL = "http://localhost:5505/"
|
||||||
started: false,
|
export const WEBSOCKET_SERVER_PORT = 5505
|
||||||
|
|
||||||
|
const QUIZZ_CONFIG = {
|
||||||
password: "PASSWORD",
|
password: "PASSWORD",
|
||||||
players: [],
|
|
||||||
playersAnswer: [],
|
|
||||||
manager: null,
|
|
||||||
room: null,
|
|
||||||
currentQuestion: 0,
|
|
||||||
roundStartTime: 0,
|
|
||||||
subject: "Adobe",
|
subject: "Adobe",
|
||||||
questions: [
|
questions: [
|
||||||
{
|
{
|
||||||
@@ -93,3 +89,15 @@ export const GAME_STATE_INIT = {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DONT CHANGE
|
||||||
|
export const GAME_STATE_INIT = {
|
||||||
|
started: false,
|
||||||
|
players: [],
|
||||||
|
playersAnswer: [],
|
||||||
|
manager: null,
|
||||||
|
room: null,
|
||||||
|
currentQuestion: 0,
|
||||||
|
roundStartTime: 0,
|
||||||
|
...QUIZZ_CONFIG,
|
||||||
|
}
|
||||||
@@ -1,14 +1,6 @@
|
|||||||
/** @type {import('next').NextConfig} */
|
/** @type {import('next').NextConfig} */
|
||||||
const nextConfig = {
|
const nextConfig = {
|
||||||
reactStrictMode: true,
|
reactStrictMode: true,
|
||||||
/*async rewrites() {
|
|
||||||
return [
|
|
||||||
{
|
|
||||||
source: "/ws/",
|
|
||||||
destination: `http://localhost:5057/`,
|
|
||||||
},
|
|
||||||
]
|
|
||||||
},*/
|
|
||||||
images: {
|
images: {
|
||||||
remotePatterns: [
|
remotePatterns: [
|
||||||
{
|
{
|
||||||
|
|||||||
1400
package-lock.json
generated
1400
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -7,7 +7,7 @@
|
|||||||
"build": "next build",
|
"build": "next build",
|
||||||
"start": "next start",
|
"start": "next start",
|
||||||
"socket": "node ./socket/index.js",
|
"socket": "node ./socket/index.js",
|
||||||
"all": "concurrently --kill-others \"npm run start\" \"npm run socket\"",
|
"all": "npm run build && concurrently --kill-others \"npm run start\" \"npm run socket\"",
|
||||||
"all-dev": "concurrently --kill-others \"npm run dev\" \"npm run socket\"",
|
"all-dev": "concurrently --kill-others \"npm run dev\" \"npm run socket\"",
|
||||||
"lint": "next lint"
|
"lint": "next lint"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { Server } from "socket.io"
|
import { Server } from "socket.io"
|
||||||
import { GAME_STATE_INIT } from "./quizz.config.js"
|
import { GAME_STATE_INIT, WEBSOCKET_SERVER_PORT } from "../config.mjs"
|
||||||
import Manager from "./roles/manager.js"
|
import Manager from "./roles/manager.js"
|
||||||
import Player from "./roles/player.js"
|
import Player from "./roles/player.js"
|
||||||
import { abortCooldown } from "./utils/cooldown.js"
|
import { abortCooldown } from "./utils/cooldown.js"
|
||||||
@@ -11,10 +11,10 @@ const io = new Server({
|
|||||||
cors: {
|
cors: {
|
||||||
origin: "*",
|
origin: "*",
|
||||||
},
|
},
|
||||||
path: "/ws/",
|
|
||||||
})
|
})
|
||||||
|
|
||||||
io.listen(5157)
|
console.log(`Server running on port ${WEBSOCKET_SERVER_PORT}`)
|
||||||
|
io.listen(WEBSOCKET_SERVER_PORT)
|
||||||
|
|
||||||
io.on("connection", (socket) => {
|
io.on("connection", (socket) => {
|
||||||
console.log(`A user connected ${socket.id}`)
|
console.log(`A user connected ${socket.id}`)
|
||||||
@@ -59,6 +59,7 @@ io.on("connection", (socket) => {
|
|||||||
gameState = deepClone(GAME_STATE_INIT)
|
gameState = deepClone(GAME_STATE_INIT)
|
||||||
|
|
||||||
abortCooldown()
|
abortCooldown()
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import { GAME_STATE_INIT } from "../quizz.config.js"
|
import { GAME_STATE_INIT } from "../../config.mjs"
|
||||||
import { startRound } from "../utils/round.js"
|
|
||||||
import generateRoomId from "../utils/generateRoomId.js"
|
|
||||||
import { abortCooldown, cooldown, sleep } from "../utils/cooldown.js"
|
import { abortCooldown, cooldown, sleep } from "../utils/cooldown.js"
|
||||||
import deepClone from "../utils/deepClone.js"
|
import deepClone from "../utils/deepClone.js"
|
||||||
|
import generateRoomId from "../utils/generateRoomId.js"
|
||||||
|
import { startRound } from "../utils/round.js"
|
||||||
|
|
||||||
const Manager = {
|
const Manager = {
|
||||||
createRoom: (game, io, socket, password) => {
|
createRoom: (game, io, socket, password) => {
|
||||||
|
|||||||
@@ -3,7 +3,10 @@ let cooldownResolve
|
|||||||
|
|
||||||
export const abortCooldown = () => {
|
export const abortCooldown = () => {
|
||||||
clearInterval(cooldownTimeout)
|
clearInterval(cooldownTimeout)
|
||||||
cooldownResolve()
|
|
||||||
|
if (cooldownResolve) {
|
||||||
|
cooldownResolve()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const cooldown = (ms, io, room) => {
|
export const cooldown = (ms, io, room) => {
|
||||||
|
|||||||
@@ -3,17 +3,15 @@ import Leaderboard from "@/components/game/states/Leaderboard"
|
|||||||
import Prepared from "@/components/game/states/Prepared"
|
import Prepared from "@/components/game/states/Prepared"
|
||||||
import Question from "@/components/game/states/Question"
|
import Question from "@/components/game/states/Question"
|
||||||
import Result from "@/components/game/states/Result"
|
import Result from "@/components/game/states/Result"
|
||||||
import Room from "./components/game/states/Room"
|
|
||||||
import Podium from "./components/game/states/Podium"
|
|
||||||
import Wait from "@/components/game/states/Wait"
|
|
||||||
import Start from "@/components/game/states/Start"
|
import Start from "@/components/game/states/Start"
|
||||||
|
import Wait from "@/components/game/states/Wait"
|
||||||
|
import Podium from "./components/game/states/Podium"
|
||||||
|
import Room from "./components/game/states/Room"
|
||||||
|
|
||||||
import Circle from "@/components/icons/Circle"
|
import Circle from "@/components/icons/Circle"
|
||||||
import Triangle from "@/components/icons/Triangle"
|
|
||||||
import Square from "@/components/icons/Square"
|
|
||||||
import Rhombus from "@/components/icons/Rhombus"
|
import Rhombus from "@/components/icons/Rhombus"
|
||||||
|
import Square from "@/components/icons/Square"
|
||||||
export const WEBSOCKET_URL = "http://localhost:5157"
|
import Triangle from "@/components/icons/Triangle"
|
||||||
|
|
||||||
export const ANSWERS_COLORS = [
|
export const ANSWERS_COLORS = [
|
||||||
"bg-red-500",
|
"bg-red-500",
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
|
import { createContext, useContext } from "react"
|
||||||
import { io } from "socket.io-client"
|
import { io } from "socket.io-client"
|
||||||
import { createContext, useContext, useState } from "react"
|
import { WEBSOCKET_PUBLIC_URL } from "../../config.mjs"
|
||||||
import { WEBSOCKET_URL } from "@/constants"
|
|
||||||
|
|
||||||
export const socket = io(WEBSOCKET_URL, {
|
export const socket = io(WEBSOCKET_PUBLIC_URL, {
|
||||||
path: "/ws/",
|
|
||||||
//addTrailingSlash: false,
|
|
||||||
transports: ["websocket"],
|
transports: ["websocket"],
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -18,7 +16,6 @@ export const SocketContextProvider = ({ children }) => {
|
|||||||
|
|
||||||
export function useSocketContext() {
|
export function useSocketContext() {
|
||||||
const context = useContext(SocketContext)
|
const context = useContext(SocketContext)
|
||||||
const [isConnected, setIsConnected] = useState(false)
|
|
||||||
|
|
||||||
return { socket: context }
|
return { socket: context }
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user