Browse Source

some more make rules

master
nicolas-arnaud 2 years ago
parent
commit
843494c6ce
  1. 3
      Makefile
  2. 3
      Makesudo
  3. 4
      back/Dockerfile
  4. 16
      back/volume/.eslintrc.json
  5. 2164
      back/volume/package-lock.json
  6. 12
      back/volume/package.json
  7. 4
      back/volume/src/app.module.ts
  8. 14
      back/volume/src/main.ts
  9. 63
      back/volume/src/pong/game/Ball.ts
  10. 143
      back/volume/src/pong/game/Game.ts
  11. 30
      back/volume/src/pong/game/Paddle.ts
  12. 48
      back/volume/src/pong/game/Player.ts
  13. 26
      back/volume/src/pong/game/constants.ts
  14. 75
      back/volume/src/pong/game/utils.ts
  15. 18
      back/volume/src/pong/pong.gateway.spec.ts
  16. 76
      back/volume/src/pong/pong.gateway.ts
  17. 4
      back/volume/src/pong/pong.module.ts
  18. 18
      back/volume/src/pong/pong.spec.ts
  19. 42
      back/volume/src/pong/pong.ts
  20. 11
      back/volume/test/app.e2e-spec.ts
  21. 4
      docker-compose.yml
  22. 6
      front/Dockerfile

3
Makefile

@ -9,6 +9,9 @@ prod:
dev:
NODE_ENV="development" docker compose -f docker-compose.yml up --build
lint:
NODE_ENV="beautify" docker compose -f docker-compose.yml up --build
debug:
NODE_ENV="debug" BUILDKIT_PROGRESS=plain docker compose -f docker-compose.yml up --build

3
Makesudo

@ -9,6 +9,9 @@ prod:
dev:
sudo NODE_ENV="development" docker compose -f docker-compose.yml up --build
lint:
sudo NODE_ENV="beautify" docker compose -f docker-compose.yml up --build
debug:
sudo NODE_ENV="debug" BUILDKIT_PROGRESS=plain docker compose -f docker-compose.yml up --build

4
back/Dockerfile

@ -8,7 +8,9 @@ ENTRYPOINT npm install; \
if [[ $NODE_ENV == "production" ]]; then \
npm run build && npm run start:prod; \
elif [[ $NODE_ENV == "debug" ]]; then \
npm run test:debug; \
npm run start:debug; \
elif [[ $NODE_ENV == "beautify" ]]; then \
npm run format && npm run lint; \
elif [[ $NODE_ENV == "development" ]]; then \
npm run dev; \
else echo "NODE_ENV value isn't known."; \

16
back/volume/.eslintrc.json

@ -0,0 +1,16 @@
{
"env": {
"browser": true,
"es2021": true
},
"extends": "standard-with-typescript",
"overrides": [
],
"parserOptions": {
"ecmaVersion": "latest",
"sourceType": "module",
"project": ["./tsconfig.json"]
},
"rules": {
}
}

2164
back/volume/package-lock.json

File diff suppressed because it is too large

12
back/volume/package.json

@ -30,9 +30,9 @@
"@nestjs/websockets": "^9.2.0",
"@types/node": "^16.0.0",
"@types/ws": "^8.5.3",
"rxjs": "^7.2.0",
"reflect-metadata": "^0.1.13",
"rimraf": "^3.0.2",
"rxjs": "^7.2.0",
"ws": "^8.11.0"
},
"devDependencies": {
@ -40,11 +40,15 @@
"@types/express": "^4.17.13",
"@types/jest": "28.1.8",
"@types/supertest": "^2.0.11",
"@typescript-eslint/eslint-plugin": "^5.0.0",
"@typescript-eslint/eslint-plugin": "^5.53.0",
"@typescript-eslint/parser": "^5.0.0",
"eslint": "^8.0.1",
"eslint": "^8.34.0",
"eslint-config-prettier": "^8.5.0",
"eslint-config-standard-with-typescript": "^34.0.0",
"eslint-plugin-import": "^2.27.5",
"eslint-plugin-n": "^15.6.1",
"eslint-plugin-prettier": "^4.2.1",
"eslint-plugin-promise": "^6.1.1",
"jest": "28.1.3",
"prettier": "^2.3.2",
"source-map-support": "^0.5.20",
@ -53,7 +57,7 @@
"ts-loader": "^9.2.3",
"ts-node": "^10.0.0",
"tsconfig-paths": "4.1.0",
"typescript": "^4.7.4"
"typescript": "^4.9.5"
},
"jest": {
"moduleFileExtensions": [

4
back/volume/src/app.module.ts

@ -1,5 +1,5 @@
import { Module } from '@nestjs/common';
import { PongModule } from './pong/pong.module';
import { Module } from '@nestjs/common'
import { PongModule } from './pong/pong.module'
@Module({
imports: [PongModule]

14
back/volume/src/main.ts

@ -1,10 +1,10 @@
import { NestFactory } from '@nestjs/core';
import { WsAdapter } from '@nestjs/platform-ws';
import { AppModule } from './app.module';
import { NestFactory } from '@nestjs/core'
import { WsAdapter } from '@nestjs/platform-ws'
import { AppModule } from './app.module'
async function bootstrap () {
const app = await NestFactory.create(AppModule);
app.useWebSocketAdapter(new WsAdapter(app));
await app.listen(3001);
const app = await NestFactory.create(AppModule)
app.useWebSocketAdapter(new WsAdapter(app))
await app.listen(3001)
}
bootstrap();
bootstrap()

63
back/volume/src/pong/game/Ball.ts

@ -1,58 +1,65 @@
import { gameInfoConstants } from './constants';
import { Paddle } from './Paddle';
import { Point, Rect } from './utils';
import { gameInfoConstants } from './constants'
import { type Paddle } from './Paddle'
import { Point, Rect } from './utils'
export class Ball {
rect: Rect;
speed: Point;
spawn: Point;
indexPlayerScored: number;
rect: Rect
speed: Point
spawn: Point
indexPlayerScored: number
constructor(spawn: Point, size: Point = gameInfoConstants.ballSize, speed: Point = new Point(10, 2)) {
this.rect = new Rect(spawn, size);
this.speed = speed;
this.spawn = spawn.clone();
constructor (
spawn: Point,
size: Point = gameInfoConstants.ballSize,
speed: Point = new Point(10, 2)
) {
this.rect = new Rect(spawn, size)
this.speed = speed
this.spawn = spawn.clone()
}
getIndexPlayerScored (): number {
return this.indexPlayerScored;
return this.indexPlayerScored
}
update (canvas_rect: Rect, paddles: Paddle[]) {
if (!canvas_rect.contains_x(this.rect)) {
this.indexPlayerScored = this.score();
this.indexPlayerScored = this.score()
} else {
this.indexPlayerScored = -1;
this.move(canvas_rect, paddles);
this.indexPlayerScored = -1
this.move(canvas_rect, paddles)
}
}
move (canvas_rect: Rect, paddles: Paddle[]) {
for (const paddle of paddles) {
if (paddle.rect.collides(this.rect)) {
if (this.speed.x < 0) this.rect.center.x = paddle.rect.center.x + paddle.rect.size.x;
else this.rect.center.x = paddle.rect.center.x - paddle.rect.size.x;
this.speed.x = this.speed.x * -1;
this.speed.y = ((this.rect.center.y - paddle.rect.center.y) / paddle.rect.size.y) * 20;
break;
if (this.speed.x < 0) {
this.rect.center.x = paddle.rect.center.x + paddle.rect.size.x
} else this.rect.center.x = paddle.rect.center.x - paddle.rect.size.x
this.speed.x = this.speed.x * -1
this.speed.y =
((this.rect.center.y - paddle.rect.center.y) / paddle.rect.size.y) *
20
break
}
}
if (!canvas_rect.contains_y(this.rect)) this.speed.y = this.speed.y * -1;
this.rect.center.add_inplace(this.speed);
if (!canvas_rect.contains_y(this.rect)) this.speed.y = this.speed.y * -1
this.rect.center.add_inplace(this.speed)
}
// A player scored: return his index and reposition the ball
score (): number {
let index_player_scored: number;
let index_player_scored: number
if (this.rect.center.x <= this.spawn.x) {
index_player_scored = 1;
index_player_scored = 1
} else {
index_player_scored = 0;
index_player_scored = 0
}
this.rect.center = this.spawn.clone();
this.speed.x = this.speed.x * -1;
this.rect.center = this.spawn.clone()
this.speed.x = this.speed.x * -1
return index_player_scored;
return index_player_scored
}
}

143
back/volume/src/pong/game/Game.ts

@ -1,27 +1,32 @@
import { Ball } from './Ball';
import { WebSocket } from 'ws';
import { formatWebsocketData, Point, Rect } from './utils';
import { Player } from './Player';
import { GameInfo, gameInfoConstants, GameUpdate, GAME_EVENTS } from './constants';
import { randomUUID } from 'crypto';
const GAME_TICKS = 30;
import { Ball } from './Ball'
import { type WebSocket } from 'ws'
import { formatWebsocketData, Point, Rect } from './utils'
import { Player } from './Player'
import {
type GameInfo,
gameInfoConstants,
type GameUpdate,
GAME_EVENTS
} from './constants'
import { randomUUID } from 'crypto'
const GAME_TICKS = 30
function gameLoop (game: Game) {
const canvas_rect = new Rect(
new Point(gameInfoConstants.mapSize.x / 2, gameInfoConstants.mapSize.y / 2),
new Point(gameInfoConstants.mapSize.x, gameInfoConstants.mapSize.y)
);
)
game.ball.update(
canvas_rect,
game.players.map((p) => p.paddle)
);
const index_player_scored: number = game.ball.getIndexPlayerScored();
)
const index_player_scored: number = game.ball.getIndexPlayerScored()
if (index_player_scored != -1) {
game.players[index_player_scored].score += 1;
game.players[index_player_scored].score += 1
if (game.players[index_player_scored].score >= gameInfoConstants.winScore) {
console.log(`${game.players[index_player_scored].name} won!`);
game.stop();
console.log(`${game.players[index_player_scored].name} won!`)
game.stop()
}
}
@ -29,105 +34,127 @@ function gameLoop(game: Game) {
paddlesPositions: game.players.map((p) => p.paddle.rect.center),
ballPosition: game.ball.rect.center,
scores: game.players.map((p) => p.score)
};
const websocketData: string = formatWebsocketData(GAME_EVENTS.GAME_TICK, data);
game.broadcastGame(websocketData);
}
const websocketData: string = formatWebsocketData(
GAME_EVENTS.GAME_TICK,
data
)
game.broadcastGame(websocketData)
}
export class Game {
id: string;
timer: NodeJS.Timer;
ball: Ball;
players: Player[] = [];
playing: boolean;
constructor(sockets: Array<WebSocket>, uuids: Array<string>, names: Array<string>) {
this.id = randomUUID();
this.timer = null;
this.ball = new Ball(new Point(gameInfoConstants.mapSize.x / 2, gameInfoConstants.mapSize.y / 2));
id: string
timer: NodeJS.Timer
ball: Ball
players: Player[] = []
playing: boolean
constructor (sockets: WebSocket[], uuids: string[], names: string[]) {
this.id = randomUUID()
this.timer = null
this.ball = new Ball(
new Point(
gameInfoConstants.mapSize.x / 2,
gameInfoConstants.mapSize.y / 2
)
)
for (let i = 0; i < uuids.length; i++) {
this.addPlayer(sockets[i], uuids[i], names[i]);
this.addPlayer(sockets[i], uuids[i], names[i])
}
}
getGameInfo (uuid: string): GameInfo {
const yourPaddleIndex = this.players.findIndex((p) => p.uuid == uuid);
const yourPaddleIndex = this.players.findIndex((p) => p.uuid == uuid)
return {
...gameInfoConstants,
yourPaddleIndex: yourPaddleIndex,
yourPaddleIndex,
gameId: this.id
};
}
}
private addPlayer (socket: WebSocket, uuid: string, name: string) {
let paddleCoords = new Point(gameInfoConstants.playerXOffset, gameInfoConstants.mapSize.y / 2);
let paddleCoords = new Point(
gameInfoConstants.playerXOffset,
gameInfoConstants.mapSize.y / 2
)
if (this.players.length == 1) {
paddleCoords = new Point(
gameInfoConstants.mapSize.x - gameInfoConstants.playerXOffset,
gameInfoConstants.mapSize.y / 2
);
)
}
this.players.push(new Player(socket, uuid, name, paddleCoords, gameInfoConstants.mapSize));
this.players.push(
new Player(socket, uuid, name, paddleCoords, gameInfoConstants.mapSize)
)
}
removePlayer (uuid: string) {
const player_index = this.players.findIndex((p) => p.uuid == uuid);
const player_index = this.players.findIndex((p) => p.uuid == uuid)
if (player_index != -1) {
this.players.splice(player_index, 1);
this.players.splice(player_index, 1)
if (this.players.length < 2) {
this.stop();
this.stop()
}
}
}
ready (uuid: string) {
const player_index = this.players.findIndex((p) => p.uuid == uuid);
const player_index = this.players.findIndex((p) => p.uuid == uuid)
if (player_index != -1) {
this.players[player_index].ready = true;
console.log(`${this.players[player_index].name} is ready!`);
this.players[player_index].ready = true
console.log(`${this.players[player_index].name} is ready!`)
if (this.players.every((p) => p.ready)) {
this.start();
this.start()
}
}
}
private start (): boolean {
if (!this.timer && this.players.length == 2) {
this.ball = new Ball(new Point(gameInfoConstants.mapSize.x / 2, gameInfoConstants.mapSize.y / 2));
this.players.forEach((p) => p.newGame());
this.ball = new Ball(
new Point(
gameInfoConstants.mapSize.x / 2,
gameInfoConstants.mapSize.y / 2
)
)
this.players.forEach((p) => {
p.newGame()
})
this.timer = setInterval(gameLoop, 1000 / GAME_TICKS, this);
this.broadcastGame(formatWebsocketData(GAME_EVENTS.START_GAME));
console.log('Started game');
this.playing = true;
return true;
this.timer = setInterval(gameLoop, 1000 / GAME_TICKS, this)
this.broadcastGame(formatWebsocketData(GAME_EVENTS.START_GAME))
console.log('Started game')
this.playing = true
return true
}
return false;
return false
}
stop () {
if (this.timer) {
clearInterval(this.timer);
this.timer = null;
this.players = [];
this.playing = false;
console.log('Stopped game');
clearInterval(this.timer)
this.timer = null
this.players = []
this.playing = false
console.log('Stopped game')
}
}
movePaddle (uuid: string, position: Point) {
const playerIndex = this.players.findIndex((p) => p.uuid == uuid);
const playerIndex = this.players.findIndex((p) => p.uuid == uuid)
if (this.timer && playerIndex != -1) {
this.players[playerIndex].paddle.move(position.y);
this.players[playerIndex].paddle.move(position.y)
}
}
broadcastGame (data: string) {
this.players.forEach((p) => p.socket.send(data));
this.players.forEach((p) => {
p.socket.send(data)
})
}
isPlaying (): boolean {
return this.playing;
return this.playing
}
}

30
back/volume/src/pong/game/Paddle.ts

@ -1,28 +1,32 @@
import { gameInfoConstants } from './constants';
import { Point, Rect } from './utils';
import { gameInfoConstants } from './constants'
import { type Point, Rect } from './utils'
export class Paddle {
rect: Rect;
color: string | CanvasGradient | CanvasPattern = 'white';
mapSize: Point;
rect: Rect
color: string | CanvasGradient | CanvasPattern = 'white'
mapSize: Point
constructor(spawn: Point, gameSize: Point, size: Point = gameInfoConstants.paddleSize) {
this.rect = new Rect(spawn, size);
this.mapSize = gameSize;
constructor (
spawn: Point,
gameSize: Point,
size: Point = gameInfoConstants.paddleSize
) {
this.rect = new Rect(spawn, size)
this.mapSize = gameSize
}
draw (context: CanvasRenderingContext2D) {
this.rect.draw(context, this.color);
this.rect.draw(context, this.color)
}
move (new_y: number) {
const offset: number = this.rect.size.y / 2;
const offset: number = this.rect.size.y / 2
if (new_y - offset < 0) {
this.rect.center.y = offset;
this.rect.center.y = offset
} else if (new_y + offset > this.mapSize.y) {
this.rect.center.y = this.mapSize.y - offset;
this.rect.center.y = this.mapSize.y - offset
} else {
this.rect.center.y = new_y;
this.rect.center.y = new_y
}
}
}

48
back/volume/src/pong/game/Player.ts

@ -1,29 +1,35 @@
import { WebSocket } from 'ws';
import { Paddle } from './Paddle';
import { Point } from './utils';
import { type WebSocket } from 'ws'
import { Paddle } from './Paddle'
import { type Point } from './utils'
export class Player {
socket: WebSocket;
uuid: string;
name: string;
ready: boolean;
paddle: Paddle;
paddleCoords: Point;
mapSize: Point;
score: number;
socket: WebSocket
uuid: string
name: string
ready: boolean
paddle: Paddle
paddleCoords: Point
mapSize: Point
score: number
constructor(socket: WebSocket, uuid: string, name: string, paddleCoords: Point, mapSize: Point) {
this.socket = socket;
this.uuid = uuid;
this.name = name;
this.paddle = new Paddle(paddleCoords, mapSize);
this.paddleCoords = paddleCoords;
this.mapSize = mapSize;
this.score = 0;
constructor (
socket: WebSocket,
uuid: string,
name: string,
paddleCoords: Point,
mapSize: Point
) {
this.socket = socket
this.uuid = uuid
this.name = name
this.paddle = new Paddle(paddleCoords, mapSize)
this.paddleCoords = paddleCoords
this.mapSize = mapSize
this.score = 0
}
newGame () {
this.score = 0;
this.paddle = new Paddle(this.paddleCoords, this.mapSize);
this.score = 0
this.paddle = new Paddle(this.paddleCoords, this.mapSize)
}
}

26
back/volume/src/pong/game/constants.ts

@ -1,4 +1,4 @@
import { Point } from './utils';
import { Point } from './utils'
export const GAME_EVENTS = {
START_GAME: 'START_GAME',
@ -8,18 +8,18 @@ export const GAME_EVENTS = {
GET_GAME_INFO: 'GET_GAME_INFO',
CREATE_GAME: 'CREATE_GAME',
REGISTER_PLAYER: 'REGISTER_PLAYER'
};
}
export interface GameInfo extends GameInfoConstants {
yourPaddleIndex: number;
gameId: string;
yourPaddleIndex: number
gameId: string
}
export interface GameInfoConstants {
mapSize: Point;
paddleSize: Point;
playerXOffset: number;
ballSize: Point;
winScore: number;
mapSize: Point
paddleSize: Point
playerXOffset: number
ballSize: Point
winScore: number
}
export const gameInfoConstants: GameInfoConstants = {
mapSize: new Point(600, 400),
@ -27,10 +27,10 @@ export const gameInfoConstants: GameInfoConstants = {
playerXOffset: 50,
ballSize: new Point(20, 20),
winScore: 2
};
}
export interface GameUpdate {
paddlesPositions: Point[];
ballPosition: Point;
scores: number[];
paddlesPositions: Point[]
ballPosition: Point
scores: number[]
}

75
back/volume/src/pong/game/utils.ts

@ -1,82 +1,93 @@
export class Point {
x: number;
y: number;
x: number
y: number
constructor (x: number, y: number) {
this.x = x;
this.y = y;
this.x = x
this.y = y
}
// Returns a new point
add (other: Point) {
return new Point(this.x + other.x, this.y + other.y);
return new Point(this.x + other.x, this.y + other.y)
}
// Modifies `this` point
add_inplace (other: Point) {
this.x += other.x;
this.y += other.y;
this.x += other.x
this.y += other.y
}
clone (): Point {
return new Point(this.x, this.y);
return new Point(this.x, this.y)
}
}
export class Rect {
center: Point;
size: Point;
center: Point
size: Point
constructor (center: Point, size: Point) {
this.center = center;
this.size = size;
this.center = center
this.size = size
}
draw(context: CanvasRenderingContext2D, color: string | CanvasGradient | CanvasPattern) {
const offset: Point = new Point(this.size.x / 2, this.size.y / 2);
draw (
context: CanvasRenderingContext2D,
color: string | CanvasGradient | CanvasPattern
) {
const offset: Point = new Point(this.size.x / 2, this.size.y / 2)
context.fillStyle = color;
context.fillRect(this.center.x - offset.x, this.center.y - offset.y, this.size.x, this.size.y);
context.fillStyle = color
context.fillRect(
this.center.x - offset.x,
this.center.y - offset.y,
this.size.x,
this.size.y
)
}
// True if `this` rect contains `other` rect in the x-axis
contains_x (other: Rect): boolean {
const offset: number = this.size.x / 2;
const offset_other: number = other.size.x / 2;
const offset: number = this.size.x / 2
const offset_other: number = other.size.x / 2
if (
this.center.x - offset <= other.center.x - offset_other &&
this.center.x + offset >= other.center.x + offset_other
)
return true;
return false;
) {
return true
}
return false
}
// True if `this` rect contains `other` rect in the y-axis
contains_y (other: Rect): boolean {
const offset: number = this.size.y / 2;
const offset_other: number = other.size.y / 2;
const offset: number = this.size.y / 2
const offset_other: number = other.size.y / 2
if (
this.center.y - offset <= other.center.y - offset_other &&
this.center.y + offset >= other.center.y + offset_other
)
return true;
return false;
) {
return true
}
return false
}
collides (other: Rect): boolean {
const offset: Point = new Point(this.size.x / 2, this.size.y / 2);
const offset_other: Point = new Point(other.size.x / 2, other.size.y / 2);
const offset: Point = new Point(this.size.x / 2, this.size.y / 2)
const offset_other: Point = new Point(other.size.x / 2, other.size.y / 2)
if (
this.center.x - offset.x < other.center.x + offset_other.x &&
this.center.x + offset.x > other.center.x - offset_other.x &&
this.center.y - offset.y < other.center.y + offset_other.y &&
this.center.y + offset.y > other.center.y - offset_other.y
)
return true;
return false;
) {
return true
}
return false
}
}
@ -84,5 +95,5 @@ export function formatWebsocketData(event: string, data?: any): string {
return JSON.stringify({
event,
data
});
})
}

18
back/volume/src/pong/pong.gateway.spec.ts

@ -1,18 +1,18 @@
import { Test, TestingModule } from '@nestjs/testing';
import { PongGateway } from './pong.gateway';
import { Test, type TestingModule } from '@nestjs/testing'
import { PongGateway } from './pong.gateway'
describe('PongGateway', () => {
let gateway: PongGateway;
let gateway: PongGateway
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [PongGateway]
}).compile();
}).compile()
gateway = module.get<PongGateway>(PongGateway);
});
gateway = module.get<PongGateway>(PongGateway)
})
it('should be defined', () => {
expect(gateway).toBeDefined();
});
});
expect(gateway).toBeDefined()
})
})

76
back/volume/src/pong/pong.gateway.ts

@ -1,29 +1,29 @@
import { WebSocket } from 'ws';
import { type WebSocket } from 'ws'
import {
ConnectedSocket,
MessageBody,
OnGatewayConnection,
OnGatewayDisconnect,
type OnGatewayConnection,
type OnGatewayDisconnect,
SubscribeMessage,
WebSocketGateway
} from '@nestjs/websockets';
import { randomUUID } from 'crypto';
import { Pong } from './pong';
import { formatWebsocketData, Point } from './game/utils';
import { GAME_EVENTS } from './game/constants';
} from '@nestjs/websockets'
import { randomUUID } from 'crypto'
import { Pong } from './pong'
import { formatWebsocketData, Point } from './game/utils'
import { GAME_EVENTS } from './game/constants'
interface WebSocketWithId extends WebSocket {
id: string;
id: string
}
@WebSocketGateway()
export class PongGateway implements OnGatewayConnection, OnGatewayDisconnect {
private pong: Pong = new Pong();
private socketToPlayerName: Map<WebSocketWithId, string> = new Map();
private readonly pong: Pong = new Pong()
private readonly socketToPlayerName = new Map<WebSocketWithId, string>()
handleConnection (client: WebSocketWithId) {
const uuid = randomUUID();
client.id = uuid;
const uuid = randomUUID()
client.id = uuid
}
handleDisconnect (
@ -31,11 +31,11 @@ export class PongGateway implements OnGatewayConnection, OnGatewayDisconnect {
client: WebSocketWithId
) {
if (this.pong.isInAGame(client.id)) {
console.log(`Disconnected ${this.socketToPlayerName.get(client)}`);
console.log(`Disconnected ${this.socketToPlayerName.get(client)}`)
if (this.pong.playerGame(client.id).isPlaying()) {
this.pong.playerGame(client.id).stop();
this.pong.playerGame(client.id).stop()
}
this.socketToPlayerName.delete(client);
this.socketToPlayerName.delete(client)
}
}
@ -45,13 +45,18 @@ export class PongGateway implements OnGatewayConnection, OnGatewayDisconnect {
client: WebSocketWithId,
@MessageBody('playerName') playerName: string
) {
this.socketToPlayerName.set(client, playerName);
console.log(`Connected ${this.socketToPlayerName.get(client)}`);
this.socketToPlayerName.set(client, playerName)
console.log(`Connected ${this.socketToPlayerName.get(client)}`)
}
@SubscribeMessage(GAME_EVENTS.GET_GAME_INFO)
getPlayerCount (@ConnectedSocket() client: WebSocketWithId) {
client.send(formatWebsocketData(GAME_EVENTS.GET_GAME_INFO, this.pong.getGameInfo(client.id)));
client.send(
formatWebsocketData(
GAME_EVENTS.GET_GAME_INFO,
this.pong.getGameInfo(client.id)
)
)
}
@SubscribeMessage(GAME_EVENTS.PLAYER_MOVE)
@ -60,7 +65,7 @@ export class PongGateway implements OnGatewayConnection, OnGatewayDisconnect {
client: WebSocketWithId,
@MessageBody('position') position: Point
) {
this.pong.movePlayer(client.id, position);
this.pong.movePlayer(client.id, position)
}
@SubscribeMessage(GAME_EVENTS.CREATE_GAME)
@ -69,14 +74,21 @@ export class PongGateway implements OnGatewayConnection, OnGatewayDisconnect {
client: WebSocketWithId,
@MessageBody('playerNames') playerNames: string[]
) {
const allPlayerNames: Array<string> = Array.from(this.socketToPlayerName.values());
if (playerNames && playerNames.length === 2 && allPlayerNames && allPlayerNames.length >= 2) {
const player1Socket: WebSocketWithId = Array.from(this.socketToPlayerName.keys()).find(
(key) => this.socketToPlayerName.get(key) === playerNames[0]
);
const player2Socket: WebSocketWithId = Array.from(this.socketToPlayerName.keys()).find(
(key) => this.socketToPlayerName.get(key) === playerNames[1]
);
const allPlayerNames: string[] = Array.from(
this.socketToPlayerName.values()
)
if (
playerNames &&
playerNames.length === 2 &&
allPlayerNames &&
allPlayerNames.length >= 2
) {
const player1Socket: WebSocketWithId = Array.from(
this.socketToPlayerName.keys()
).find((key) => this.socketToPlayerName.get(key) === playerNames[0])
const player2Socket: WebSocketWithId = Array.from(
this.socketToPlayerName.keys()
).find((key) => this.socketToPlayerName.get(key) === playerNames[1])
if (
player1Socket &&
@ -84,7 +96,11 @@ export class PongGateway implements OnGatewayConnection, OnGatewayDisconnect {
(client.id === player1Socket.id || client.id === player2Socket.id) &&
player1Socket.id !== player2Socket.id
) {
this.pong.newGame([player1Socket, player2Socket], [player1Socket.id, player2Socket.id], playerNames);
this.pong.newGame(
[player1Socket, player2Socket],
[player1Socket.id, player2Socket.id],
playerNames
)
}
}
}
@ -94,6 +110,6 @@ export class PongGateway implements OnGatewayConnection, OnGatewayDisconnect {
@ConnectedSocket()
client: WebSocketWithId
) {
this.pong.ready(client.id);
this.pong.ready(client.id)
}
}

4
back/volume/src/pong/pong.module.ts

@ -1,5 +1,5 @@
import { Module } from '@nestjs/common';
import { PongGateway } from './pong.gateway';
import { Module } from '@nestjs/common'
import { PongGateway } from './pong.gateway'
@Module({
providers: [PongGateway]

18
back/volume/src/pong/pong.spec.ts

@ -1,18 +1,18 @@
import { Test, TestingModule } from '@nestjs/testing';
import { Pong } from './pong';
import { Test, type TestingModule } from '@nestjs/testing'
import { Pong } from './pong'
describe('Pong', () => {
let provider: Pong;
let provider: Pong
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [Pong]
}).compile();
}).compile()
provider = module.get<Pong>(Pong);
});
provider = module.get<Pong>(Pong)
})
it('should be defined', () => {
expect(provider).toBeDefined();
});
});
expect(provider).toBeDefined()
})
})

42
back/volume/src/pong/pong.ts

@ -1,59 +1,59 @@
import { WebSocket } from 'ws';
import { GameInfo } from './game/constants';
import { Game } from './game/Game';
import { Point } from './game/utils';
import { type WebSocket } from 'ws'
import { type GameInfo } from './game/constants'
import { Game } from './game/Game'
import { type Point } from './game/utils'
export class Pong {
private playerUUIDToGameIndex = new Map<string, number>();
private games = new Array<Game>();
private playerUUIDToGameIndex = new Map<string, number>()
private readonly games = new Array<Game>()
newGame(sockets: Array<WebSocket>, uuids: Array<string>, names: Array<string>) {
this.games.push(new Game(sockets, uuids, names));
this.playerUUIDToGameIndex[uuids[0]] = this.games.length - 1;
this.playerUUIDToGameIndex[uuids[1]] = this.games.length - 1;
console.log(`Created game ${names[0]} vs ${names[1]}`);
newGame (sockets: WebSocket[], uuids: string[], names: string[]) {
this.games.push(new Game(sockets, uuids, names))
this.playerUUIDToGameIndex[uuids[0]] = this.games.length - 1
this.playerUUIDToGameIndex[uuids[1]] = this.games.length - 1
console.log(`Created game ${names[0]} vs ${names[1]}`)
}
removePlayer (uuid: string) {
this.playerGame(uuid).removePlayer(uuid);
this.playerGame(uuid).removePlayer(uuid)
}
ready (uuid: string) {
if (this.isInAGame(uuid)) {
this.playerGame(uuid).ready(uuid);
this.playerGame(uuid).ready(uuid)
}
}
stopGame (uuid: string) {
if (this.isInAGame(uuid)) {
this.playerGame(uuid).stop();
delete this.playerUUIDToGameIndex[uuid];
delete this.games[this.playerUUIDToGameIndex[uuid]];
this.playerGame(uuid).stop()
delete this.playerUUIDToGameIndex[uuid]
delete this.games[this.playerUUIDToGameIndex[uuid]]
}
}
getGameInfo (uuid: string): GameInfo {
if (this.isInAGame(uuid)) {
return this.playerGame(uuid).getGameInfo(uuid);
return this.playerGame(uuid).getGameInfo(uuid)
}
}
movePlayer (uuid: string, position: Point) {
if (this.isInAGame(uuid)) {
this.playerGame(uuid).movePaddle(uuid, position);
this.playerGame(uuid).movePaddle(uuid, position)
}
}
isInAGame (uuid: string): boolean {
if (this.playerUUIDToGameIndex[uuid] === undefined) {
return false;
return false
}
return true;
return true
}
playerGame (uuid: string): Game {
if (this.isInAGame(uuid)) {
return this.games[this.playerUUIDToGameIndex[uuid]];
return this.games[this.playerUUIDToGameIndex[uuid]]
}
}
}

11
back/volume/test/app.e2e-spec.ts

@ -1,5 +1,5 @@
import { Test, TestingModule } from '@nestjs/testing'
import { INestApplication } from '@nestjs/common'
import { Test, type TestingModule } from '@nestjs/testing'
import { type INestApplication } from '@nestjs/common'
import * as request from 'supertest'
import { AppModule } from './../src/app.module'
@ -15,7 +15,10 @@ describe('AppController (e2e)', () => {
await app.init()
})
it('/ (GET)', () => {
return request(app.getHttpServer()).get('/').expect(200).expect('Hello World!')
it('/ (GET)', async () => {
return await request(app.getHttpServer())
.get('/')
.expect(200)
.expect('Hello World!')
})
})

4
docker-compose.yml

@ -14,7 +14,7 @@ services:
ports: [80:80]
volumes: [./front/volume:/var/www/html]
networks: [transcendence]
restart: always
restart: on-failure
back:
container_name: back
build: back/
@ -25,7 +25,7 @@ services:
ports: [3001:3001]
networks: [transcendence]
volumes: [./back/volume:/var/www/html]
restart: always
restart: on-failure
postgres:
container_name: postgres
image: postgres

6
front/Dockerfile

@ -6,7 +6,9 @@ WORKDIR /var/www/html
ENTRYPOINT npm install; \
if [[ $NODE_ENV == "production" ]]; then \
npm run build && npm run preview; \
elif [[ $NODE_ENV == "development" || $NODE_ENV == "debug" ]]; then \
elif [[ $NODE_ENV == "development" ]]; then \
npm run dev; \
else echo "NODE_ENV value isn't known."; \
elif [[ $NODE_ENV == "debug" ]]; then \
npm run check && npm run dev; \
else echo "Nothing to do for that NODE_ENV context."; \
fi;

Loading…
Cancel
Save