From fc7069175fa5ece5e8720d4a123477f222fe6cb5 Mon Sep 17 00:00:00 2001 From: "alec.schmidt" <alec.schmidt@etu.hesge.ch> Date: Mon, 12 Jun 2023 21:12:52 +0200 Subject: [PATCH] it is finished, anything more is just bugfixes and details changes --- API/src/socket.io/ServerIO.ts | 73 +++++++++++-------- .../src/app/gameroom/gameroom.component.html | 32 ++++++-- .../src/app/gameroom/gameroom.component.ts | 28 ++++++- frontend/src/app/services/socket.service.ts | 18 +++++ 4 files changed, 114 insertions(+), 37 deletions(-) diff --git a/API/src/socket.io/ServerIO.ts b/API/src/socket.io/ServerIO.ts index 829fb6e..96d9901 100644 --- a/API/src/socket.io/ServerIO.ts +++ b/API/src/socket.io/ServerIO.ts @@ -12,6 +12,7 @@ class ServerIO extends IO.Server { private gameOngoing: boolean = false; private playerList: string[] = []; private questions : Question_t[] = []; + private scoreboard: { [username: string] : number; } = {} constructor(server: http.Server) { super(server, { @@ -38,18 +39,15 @@ class ServerIO extends IO.Server { if (this.gameOngoing) return socket.emit('Room Full'); - const token = socket.handshake.query.Authorization; + const token = socket.handshake.query.Authorization as string; - var user: User_t = null; - jwt.verify(token, process.env.TOKEN_SECRET, (err:any, res:User_t) => { - // console.log(err); - if (err) return false; - user = res; - }); + var user: User_t = this.decodeToken(token); logger.info(user.username + ` joined the game`); this.playerList.push(user.username); + this.scoreboard[user.username] = 0; + socket.emit('Players Waiting', this.playerList.length) socket.broadcast.emit('Players Waiting', this.playerList.length); @@ -58,19 +56,16 @@ class ServerIO extends IO.Server { }) socket.on('Leave Room', _ => { - const token = socket.handshake.query.Authorization; + const token = socket.handshake.query.Authorization as string; + + var user = this.decodeToken(token); + + var index: number = this.playerList.indexOf(user.username, 0); - var index: number; - var username: string; - jwt.verify(token, process.env.TOKEN_SECRET, (err:any, user:User_t) => { - if (err) return; - index = this.playerList.indexOf(user.username, 0); - username = user.username; - }); if (index != -1) { this.playerList.splice(index, 1); - logger.info(username + ` left the game`); + logger.info(user.username + ` left the game`); } socket.emit('Players Waiting', this.playerList.length) @@ -79,32 +74,45 @@ class ServerIO extends IO.Server { socket.on('disconnect', _ => { - const token = socket.handshake.query.Authorization; + const token = socket.handshake.query.Authorization as string; - var index = -1; - var username: string; - jwt.verify(token, process.env.TOKEN_SECRET, (err:any, user:User_t) => { - if (err) return; - index = this.playerList.indexOf(user.username, 0); - - username = user.username; - }); + var user = this.decodeToken(token); + var index = this.playerList.indexOf(user.username, 0); logger.info(`Socket disconnected on ${ socket.client.conn.remoteAddress }`); if (index == -1) return; + delete this.scoreboard[user.username] this.playerList.splice(index, 1); - logger.info(username + ` left the game`); + logger.info(user.username + ` left the game`); socket.emit('Players Waiting', this.playerList.length); }) socket.on(`Answer`, answer => { + const answerTyped = answer as Answer_t; + const token = socket.handshake.query.Authorization as string; + const user = this.decodeToken(token); + if (answerTyped.correct) + this.scoreboard[user.username]++; + else + this.scoreboard[user.username] -= 2; + + socket.emit("Points", this.scoreboard[user.username]) this.sendQuestion(); }) - } + } + + decodeToken(token: string): User_t { + var userDecoded: User_t = undefined; + jwt.verify(token, process.env.TOKEN_SECRET, (err:any, user:User_t) => { + if (err) return userDecoded; + userDecoded = user; + }); + return userDecoded; + } private async game() { this.gameOngoing = true; @@ -123,7 +131,7 @@ class ServerIO extends IO.Server { if (this.questions.length == 0) return this.gameEnd() - console.log(this.questions) + console.log(this.scoreboard) let currentQuestion = this.questions.pop() @@ -139,7 +147,14 @@ class ServerIO extends IO.Server { } gameEnd() { - + logger.info(`Game ended, kicking out every players...`) + + this.emit("Game End", this.scoreboard); + this.playerList = []; + this.scoreboard = {}; + + this.emit('Players Waiting', this.playerList.length) + this.gameOngoing = false; } } diff --git a/frontend/src/app/gameroom/gameroom.component.html b/frontend/src/app/gameroom/gameroom.component.html index fdb1511..2e0e432 100644 --- a/frontend/src/app/gameroom/gameroom.component.html +++ b/frontend/src/app/gameroom/gameroom.component.html @@ -1,20 +1,38 @@ <div class="m-10"> - <div *ngIf="!gameStart" class="bg-white flex flex-col items-center w-fit p-6 rounded-lg border-2 border-black"> + <div *ngIf="!gameStart && !endGame" class="bg-white flex flex-col items-center w-fit p-6 rounded-lg border-2 border-black"> <span class="w-fit">Player number : {{playerNumber}}/3</span> <button class="bg-white w-fit border-2 border-black rounded-lg px-2 hover:bg-gray-300 mt-2" *ngIf="!inRoom" (click)="joinRoom()">Join Room</button> <button class="bg-white w-fit border-2 border-black rounded-lg px-2 hover:bg-gray-300 mt-2" *ngIf="inRoom" (click)="leaveRoom()">Leave Room</button> </div> - <div *ngIf="gameStart"> - {{question}} - <table> - <thead><th>Answers</th></thead> + <div *ngIf="gameStart && !endGame" class="bg-white flex flex-col w-fit p-6 rounded-lg border-2 border-black"> + <span>Score : {{points}}</span> + <h1>{{question}}</h1> + + <table class="text-left"> + <thead class="border-b font-medium dark:border-neutral-500"><th class="px-6 py-4">Answers</th></thead> + <tbody> + <tr *ngFor="let answer of answers" class="border-b dark:border-neutral-500"> + <td><button (click)="sendAnswer(answer)" class="w-full hover:bg-gray-300">{{answer.text_answer}}</button></td> + </tr> + </tbody> + </table> + </div> + + <div *ngIf="gameStart && endGame" class="bg-white flex flex-col w-fit p-6 rounded-lg border-2 border-black"> + <table class="text-left"> + <thead class="border-b font-medium dark:border-neutral-500"> + <th class="py-4">Player</th> + <th class="py-4">Points</th> + </thead> <tbody> - <tr *ngFor="let answer of answers"> - <td><button (click)="sendAnswer(answer)">{{answer.text_answer}}</button></td> + <tr *ngFor="let score of scoreboard | keyvalue" class="border-b dark:border-neutral-500"> + <td>{{score.key}}</td> + <td>{{score.value}}</td> </tr> </tbody> </table> + <button class="bg-white w-fit border-2 border-black rounded-lg px-2 hover:bg-gray-300 mt-2" (click)="exitGame()">Nice</button> </div> </div> \ No newline at end of file diff --git a/frontend/src/app/gameroom/gameroom.component.ts b/frontend/src/app/gameroom/gameroom.component.ts index 55190c4..67763b7 100644 --- a/frontend/src/app/gameroom/gameroom.component.ts +++ b/frontend/src/app/gameroom/gameroom.component.ts @@ -1,4 +1,4 @@ -import { Component, OnDestroy, OnInit } from '@angular/core'; +import { Component, OnDestroy, OnInit, Pipe, PipeTransform } from '@angular/core'; import { Socket } from 'ngx-socket-io'; import { SocketService } from '../services/socket.service'; import { QuestionsService } from '../services/questions.service'; @@ -17,6 +17,9 @@ export class GameroomComponent implements OnInit, OnDestroy { question: string = ""; answers!: Answer[]; inRoom: boolean = false; + endGame: boolean = false; + scoreboard: { [username: string] : number; } = {}; + points!: number; constructor( private socket: SocketService) {} @@ -37,6 +40,16 @@ export class GameroomComponent implements OnInit, OnDestroy { this.socket.answers.subscribe(answers => { this.answers = answers; }) + + this.socket.points.subscribe(points => { + this.points = points; + }) + + this.socket.scoreboard.subscribe(scoreboard => { + this.scoreboard = scoreboard; + if (this.gameStart) + this.endGame = true; + }) } ngOnDestroy(): void { @@ -57,4 +70,17 @@ export class GameroomComponent implements OnInit, OnDestroy { this.socket.sendAnswer(answer); } + exitGame(): void { + this.endGame = false; + this.gameStart = false; + this.inRoom = false; + this.socket.leaveRoom(); + } } + +@Pipe({ name: 'keys', pure: false }) + export class KeysPipe implements PipeTransform { + transform(value: any, args: any[] = null): any { + return Object.keys(value)//.map(key => value[key]); + } + } \ No newline at end of file diff --git a/frontend/src/app/services/socket.service.ts b/frontend/src/app/services/socket.service.ts index 42b7b6e..7d910e8 100644 --- a/frontend/src/app/services/socket.service.ts +++ b/frontend/src/app/services/socket.service.ts @@ -17,6 +17,8 @@ export class SocketService { private _gameStart = new BehaviorSubject<boolean>(false); private _currentQuestion = new BehaviorSubject<string>(""); private _currentAnswers = new BehaviorSubject<Answer[]>([]); + private _points = new BehaviorSubject<number>(0); + private _scoreboard = new BehaviorSubject<{ [username: string] : number; }>({}); constructor( private socket: Socket @@ -43,6 +45,14 @@ export class SocketService { return this._currentAnswers.asObservable(); } + get points() { + return this._points.asObservable(); + } + + get scoreboard() { + return this._scoreboard.asObservable(); + } + refreshSocketToken(): void { this.socket.ioSocket.io.opts.query = { Authorization: localStorage.getItem("token")}; } @@ -61,6 +71,14 @@ export class SocketService { this.socket.on("Game Start", ()=> { this._gameStart.next(true); }) + + this.socket.on("Points", points => { + this._points.next(points); + }) + + this.socket.on("Game End", scoreboard => { + this._scoreboard.next(scoreboard); + }) } recievePlayerNumber(): void { -- GitLab