Browse Source

* Fixed backend eslint errors

* Removed unused tests
master
vvandenb 2 years ago
parent
commit
4329e6a020
  1. 13
      back/volume/.eslintrc.js
  2. 16
      back/volume/.eslintrc.json
  3. 4
      back/volume/package.json
  4. 4
      back/volume/src/main.ts
  5. 2
      back/volume/src/pong/dtos/PlayerNamesDto.ts
  6. 8
      back/volume/src/pong/dtos/UserDto.ts
  7. 19
      back/volume/src/pong/game/Ball.ts
  8. 59
      back/volume/src/pong/game/Game.ts
  9. 10
      back/volume/src/pong/game/Paddle.ts
  10. 3
      back/volume/src/pong/game/Player.ts
  11. 28
      back/volume/src/pong/game/utils.ts
  12. 52
      back/volume/src/pong/pong.gateway.ts
  13. 69
      back/volume/src/pong/pong.ts
  14. 24
      back/volume/test/app.e2e-spec.ts
  15. 9
      back/volume/test/jest-e2e.json
  16. 6
      back/volume/tsconfig.json

13
back/volume/.eslintrc.js

@ -0,0 +1,13 @@
module.exports = {
env: {
browser: true,
es2021: true
},
extends: 'standard-with-typescript',
parserOptions: {
ecmaVersion: 'latest',
sourceType: 'module',
project: ['./tsconfig.json'],
tsconfigRootDir: __dirname
}
}

16
back/volume/.eslintrc.json

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

4
back/volume/package.json

@ -8,12 +8,12 @@
"scripts": {
"prebuild": "rimraf dist",
"build": "nest build",
"format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
"format": "prettier --write \".eslintrc.js\" \"src/**/*.ts\"",
"start": "nest start",
"dev": "nest start --watch",
"start:debug": "nest start --debug --watch",
"start:prod": "node dist/main",
"lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix",
"lint": "eslint \".eslintrc.js\" \"{src,apps,libs,test}/**/*.ts\" --fix",
"test": "jest",
"test:watch": "jest --watch",
"test:cov": "jest --coverage",

4
back/volume/src/main.ts

@ -2,9 +2,9 @@ import { NestFactory } from '@nestjs/core'
import { WsAdapter } from '@nestjs/platform-ws'
import { AppModule } from './app.module'
async function bootstrap () {
async function bootstrap (): Promise<void> {
const app = await NestFactory.create(AppModule)
app.useWebSocketAdapter(new WsAdapter(app))
await app.listen(3001)
}
bootstrap()
void bootstrap()

2
back/volume/src/pong/dtos/PlayerNamesDto.ts

@ -4,5 +4,5 @@ export class PlayerNamesDto {
@IsString({ each: true })
@ArrayMaxSize(2)
@ArrayMinSize(2)
playerNames: string[]
playerNames!: string[]
}

8
back/volume/src/pong/dtos/UserDto.ts

@ -1,12 +1,12 @@
import { ArrayMaxSize, ArrayMinSize, IsString } from 'class-validator'
import { IsString } from 'class-validator'
export class UserDto {
@IsString()
username: string
username!: string
@IsString()
avatar: string
avatar!: string
@IsString()
status: string
status!: string
}

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

@ -16,22 +16,23 @@ export class Ball {
this.rect = new Rect(spawn, size)
this.speed = speed
this.spawn = spawn.clone()
this.indexPlayerScored = -1
}
getIndexPlayerScored (): number {
return this.indexPlayerScored
}
update (canvas_rect: Rect, paddles: Paddle[]) {
if (!canvas_rect.contains_x(this.rect)) {
update (canvasRect: Rect, paddles: Paddle[]): void {
if (!canvasRect.contains_x(this.rect)) {
this.indexPlayerScored = this.score()
} else {
this.indexPlayerScored = -1
this.move(canvas_rect, paddles)
this.move(canvasRect, paddles)
}
}
move (canvas_rect: Rect, paddles: Paddle[]) {
move (canvasRect: Rect, paddles: Paddle[]): void {
for (const paddle of paddles) {
if (paddle.rect.collides(this.rect)) {
if (this.speed.x < 0) {
@ -44,22 +45,22 @@ export class Ball {
break
}
}
if (!canvas_rect.contains_y(this.rect)) this.speed.y = this.speed.y * -1
if (!canvasRect.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 indexPlayerScored: number
if (this.rect.center.x <= this.spawn.x) {
index_player_scored = 1
indexPlayerScored = 1
} else {
index_player_scored = 0
indexPlayerScored = 0
}
this.rect.center = this.spawn.clone()
this.speed.x = this.speed.x * -1
return index_player_scored
return indexPlayerScored
}
}

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

@ -13,20 +13,20 @@ import { Spectator } from './Spectator'
const GAME_TICKS = 30
function gameLoop (game: Game) {
const canvas_rect = new Rect(
function gameLoop (game: Game): void {
const canvasRect = 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,
canvasRect,
game.players.map((p) => p.paddle)
)
const index_player_scored: number = game.ball.getIndexPlayerScored()
if (index_player_scored != -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!`)
const indexPlayerScored: number = game.ball.getIndexPlayerScored()
if (indexPlayerScored !== -1) {
game.players[indexPlayerScored].score += 1
if (game.players[indexPlayerScored].score >= gameInfoConstants.winScore) {
console.log(`${game.players[indexPlayerScored].name} won!`)
game.stop()
}
}
@ -45,7 +45,7 @@ function gameLoop (game: Game) {
export class Game {
id: string
timer: NodeJS.Timer
timer: NodeJS.Timer | null
ball: Ball
players: Player[] = []
spectators: Spectator[] = []
@ -54,6 +54,7 @@ export class Game {
constructor (sockets: WebSocket[], uuids: string[], names: string[]) {
this.id = randomUUID()
this.timer = null
this.playing = false
this.ball = new Ball(
new Point(
gameInfoConstants.mapSize.x / 2,
@ -66,7 +67,7 @@ export class Game {
}
getGameInfo (name: string): GameInfo {
const yourPaddleIndex = this.players.findIndex((p) => p.name == name)
const yourPaddleIndex = this.players.findIndex((p) => p.name === name)
return {
...gameInfoConstants,
yourPaddleIndex,
@ -74,17 +75,17 @@ export class Game {
}
}
addSpectator (socket: WebSocket, uuid: string, name: string) {
addSpectator (socket: WebSocket, uuid: string, name: string): void {
this.spectators.push(new Spectator(socket, uuid, name))
console.log(`Added spectator ${name}`)
}
private addPlayer (socket: WebSocket, uuid: string, name: string) {
private addPlayer (socket: WebSocket, uuid: string, name: string): void {
let paddleCoords = new Point(
gameInfoConstants.playerXOffset,
gameInfoConstants.mapSize.y / 2
)
if (this.players.length == 1) {
if (this.players.length === 1) {
paddleCoords = new Point(
gameInfoConstants.mapSize.x - gameInfoConstants.playerXOffset,
gameInfoConstants.mapSize.y / 2
@ -95,21 +96,21 @@ export class Game {
)
}
removePlayer (name: string) {
const player_index = this.players.findIndex((p) => p.name == name)
if (player_index != -1) {
this.players.splice(player_index, 1)
removePlayer (name: string): void {
const playerIndex: number = this.players.findIndex((p) => p.name === name)
if (playerIndex !== -1) {
this.players.splice(playerIndex, 1)
if (this.players.length < 2) {
this.stop()
}
}
}
ready (name: string) {
const player_index = this.players.findIndex((p) => p.name == name)
if (player_index != -1) {
this.players[player_index].ready = true
console.log(`${this.players[player_index].name} is ready!`)
ready (name: string): void {
const playerIndex: number = this.players.findIndex((p) => p.name === name)
if (playerIndex !== -1) {
this.players[playerIndex].ready = true
console.log(`${this.players[playerIndex].name} is ready!`)
if (this.players.every((p) => p.ready)) {
this.start()
}
@ -117,7 +118,7 @@ export class Game {
}
private start (): boolean {
if (!this.timer && this.players.length == 2) {
if (this.timer === null && this.players.length === 2) {
this.ball = new Ball(
new Point(
gameInfoConstants.mapSize.x / 2,
@ -137,8 +138,8 @@ export class Game {
return false
}
stop () {
if (this.timer) {
stop (): void {
if (this.timer !== null) {
clearInterval(this.timer)
this.timer = null
this.players = []
@ -147,15 +148,15 @@ export class Game {
}
}
movePaddle (name: string, position: Point) {
const playerIndex = this.players.findIndex((p) => p.name == name)
movePaddle (name: string | undefined, position: Point): void {
const playerIndex: number = this.players.findIndex((p) => p.name === name)
if (this.timer && playerIndex != -1) {
if (this.timer !== null && playerIndex !== -1) {
this.players[playerIndex].paddle.move(position.y)
}
}
broadcastGame (data: string) {
broadcastGame (data: string): void {
this.players.forEach((p) => {
p.socket.send(data)
})

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

@ -15,18 +15,18 @@ export class Paddle {
this.mapSize = gameSize
}
draw (context: CanvasRenderingContext2D) {
draw (context: CanvasRenderingContext2D): void {
this.rect.draw(context, this.color)
}
move (new_y: number) {
move (newY: number): void {
const offset: number = this.rect.size.y / 2
if (new_y - offset < 0) {
if (newY - offset < 0) {
this.rect.center.y = offset
} else if (new_y + offset > this.mapSize.y) {
} else if (newY + offset > this.mapSize.y) {
this.rect.center.y = this.mapSize.y - offset
} else {
this.rect.center.y = new_y
this.rect.center.y = newY
}
}
}

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

@ -22,13 +22,14 @@ export class Player {
this.socket = socket
this.uuid = uuid
this.name = name
this.ready = false
this.paddle = new Paddle(paddleCoords, mapSize)
this.paddleCoords = paddleCoords
this.mapSize = mapSize
this.score = 0
}
newGame () {
newGame (): void {
this.score = 0
this.paddle = new Paddle(this.paddleCoords, this.mapSize)
}

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

@ -8,12 +8,12 @@ export class Point {
}
// Returns a new point
add (other: Point) {
add (other: Point): Point {
return new Point(this.x + other.x, this.y + other.y)
}
// Modifies `this` point
add_inplace (other: Point) {
add_inplace (other: Point): void {
this.x += other.x
this.y += other.y
}
@ -35,7 +35,7 @@ export class Rect {
draw (
context: CanvasRenderingContext2D,
color: string | CanvasGradient | CanvasPattern
) {
): void {
const offset: Point = new Point(this.size.x / 2, this.size.y / 2)
context.fillStyle = color
@ -50,11 +50,11 @@ export class Rect {
// 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 offsetOther: number = other.size.x / 2
if (
this.center.x - offset <= other.center.x - offset_other &&
this.center.x + offset >= other.center.x + offset_other
this.center.x - offset <= other.center.x - offsetOther &&
this.center.x + offset >= other.center.x + offsetOther
) {
return true
}
@ -64,11 +64,11 @@ export class Rect {
// 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 offsetOther: number = other.size.y / 2
if (
this.center.y - offset <= other.center.y - offset_other &&
this.center.y + offset >= other.center.y + offset_other
this.center.y - offset <= other.center.y - offsetOther &&
this.center.y + offset >= other.center.y + offsetOther
) {
return true
}
@ -77,13 +77,13 @@ export class Rect {
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 offsetOther: 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
this.center.x - offset.x < other.center.x + offsetOther.x &&
this.center.x + offset.x > other.center.x - offsetOther.x &&
this.center.y - offset.y < other.center.y + offsetOther.y &&
this.center.y + offset.y > other.center.y - offsetOther.y
) {
return true
}

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

@ -13,6 +13,7 @@ import { formatWebsocketData, Point } from './game/utils'
import { GAME_EVENTS } from './game/constants'
import { PlayerNamesDto } from './dtos/PlayerNamesDto'
import { UsePipes, ValidationPipe } from '@nestjs/common'
import { type Game } from './game/Game'
interface WebSocketWithId extends WebSocket {
id: string
@ -23,7 +24,7 @@ export class PongGateway implements OnGatewayConnection, OnGatewayDisconnect {
private readonly games: Games = new Games()
private readonly socketToPlayerName = new Map<WebSocketWithId, string>()
handleConnection (client: WebSocketWithId) {
handleConnection (client: WebSocketWithId): void {
const uuid = randomUUID()
client.id = uuid
}
@ -31,12 +32,13 @@ export class PongGateway implements OnGatewayConnection, OnGatewayDisconnect {
handleDisconnect (
@ConnectedSocket()
client: WebSocketWithId
) {
const name: string = this.socketToPlayerName.get(client)
if (this.games.isInAGame(name)) {
console.log(`Disconnected ${this.socketToPlayerName.get(client)}`)
if (this.games.playerGame(name).isPlaying()) {
this.games.playerGame(name).stop()
): void {
const name: string | undefined = this.socketToPlayerName.get(client)
const game: Game | null = this.games.playerGame(name)
if (game !== null) {
console.log('Disconnected ', this.socketToPlayerName.get(client))
if (game.isPlaying()) {
game.stop()
}
this.socketToPlayerName.delete(client)
}
@ -47,15 +49,15 @@ export class PongGateway implements OnGatewayConnection, OnGatewayDisconnect {
@ConnectedSocket()
client: WebSocketWithId,
@MessageBody('playerName') playerName: string
) {
): void {
this.socketToPlayerName.set(client, playerName)
console.log(`Connected ${this.socketToPlayerName.get(client)}`)
console.log('Connected ', this.socketToPlayerName.get(client))
}
@SubscribeMessage(GAME_EVENTS.GET_GAME_INFO)
getPlayerCount (@ConnectedSocket() client: WebSocketWithId) {
const name: string = this.socketToPlayerName.get(client)
if (name) {
getPlayerCount (@ConnectedSocket() client: WebSocketWithId): void {
const name: string | undefined = this.socketToPlayerName.get(client)
if (name !== undefined) {
client.send(
formatWebsocketData(
GAME_EVENTS.GET_GAME_INFO,
@ -70,8 +72,8 @@ export class PongGateway implements OnGatewayConnection, OnGatewayDisconnect {
@ConnectedSocket()
client: WebSocketWithId,
@MessageBody('position') position: Point
) {
const name: string = this.socketToPlayerName.get(client)
): void {
const name: string | undefined = this.socketToPlayerName.get(client)
this.games.movePlayer(name, position)
}
@ -81,15 +83,15 @@ export class PongGateway implements OnGatewayConnection, OnGatewayDisconnect {
@ConnectedSocket()
client: WebSocketWithId,
@MessageBody() playerNamesDto: PlayerNamesDto
) {
): void {
if (this.socketToPlayerName.size >= 2) {
const player1Socket: WebSocketWithId = Array.from(
const player1Socket: WebSocketWithId | undefined = Array.from(
this.socketToPlayerName.keys()
).find(
(key) =>
this.socketToPlayerName.get(key) === playerNamesDto.playerNames[0]
)
const player2Socket: WebSocketWithId = Array.from(
const player2Socket: WebSocketWithId | undefined = Array.from(
this.socketToPlayerName.keys()
).find(
(key) =>
@ -97,8 +99,8 @@ export class PongGateway implements OnGatewayConnection, OnGatewayDisconnect {
)
if (
player1Socket &&
player2Socket &&
player1Socket !== undefined &&
player2Socket !== undefined &&
(client.id === player1Socket.id || client.id === player2Socket.id) &&
player1Socket.id !== player2Socket.id
) {
@ -115,9 +117,9 @@ export class PongGateway implements OnGatewayConnection, OnGatewayDisconnect {
ready (
@ConnectedSocket()
client: WebSocketWithId
) {
const name: string = this.socketToPlayerName.get(client)
if (name) {
): void {
const name: string | undefined = this.socketToPlayerName.get(client)
if (name !== undefined) {
this.games.ready(name)
}
}
@ -127,9 +129,9 @@ export class PongGateway implements OnGatewayConnection, OnGatewayDisconnect {
@ConnectedSocket()
client: WebSocketWithId,
@MessageBody('playerToSpectate') playerToSpectate: string
) {
const name: string = this.socketToPlayerName.get(client)
if (name) {
): void {
const name: string | undefined = this.socketToPlayerName.get(client)
if (name !== undefined) {
this.games.spectateGame(playerToSpectate, client, client.id, name)
}
}

69
back/volume/src/pong/pong.ts

@ -2,56 +2,72 @@ import { type WebSocket } from 'ws'
import { type GameInfo } from './game/constants'
import { Game } from './game/Game'
import { type Point } from './game/utils'
import { gameInfoConstants } from './game/constants'
export class Games {
private readonly playerNameToGameIndex = new Map<string, number>()
private readonly games = new Array<Game>()
newGame (sockets: WebSocket[], uuids: string[], names: string[]) {
newGame (sockets: WebSocket[], uuids: string[], names: string[]): void {
this.games.push(new Game(sockets, uuids, names))
this.playerNameToGameIndex.set(names[0], this.games.length - 1)
this.playerNameToGameIndex.set(names[1], this.games.length - 1)
console.log(`Created game ${names[0]} vs ${names[1]}`)
}
removePlayer (name: string) {
this.playerGame(name).removePlayer(name)
removePlayer (name: string): void {
const game: Game | null = this.playerGame(name)
if (game !== null) {
game.removePlayer(name)
}
}
ready (name: string) {
if (this.isInAGame(name)) {
this.playerGame(name).ready(name)
ready (name: string): void {
const game: Game | null = this.playerGame(name)
if (game !== null) {
game.ready(name)
}
}
stopGame (uuid: string) {
// if (this.isInAGame(uuid)) {
// this.playerGame(uuid).stop()
// delete this.playerNameToGameIndex[uuid]
// delete this.games[this.playerNameToGameIndex[uuid]]
// stopGame (uuid: string): void {
// // if (this.isInAGame(uuid)) {
// // this.playerGame(uuid).stop()
// // delete this.playerNameToGameIndex[uuid]
// // delete this.games[this.playerNameToGameIndex[uuid]]
// // }
// }
}
getGameInfo (name: string): GameInfo {
if (this.isInAGame(name)) {
return this.playerGame(name).getGameInfo(name)
const game: Game | null = this.playerGame(name)
if (game !== null) {
return game.getGameInfo(name)
}
return {
...gameInfoConstants,
yourPaddleIndex: 0,
gameId: ''
}
}
movePlayer (name: string, position: Point) {
if (this.isInAGame(name)) {
this.playerGame(name).movePaddle(name, position)
movePlayer (name: string | undefined, position: Point): void {
const game: Game | null = this.playerGame(name)
if (game !== null) {
game.movePaddle(name, position)
}
}
isInAGame (name: string): boolean {
isInAGame (name: string | undefined): boolean {
if (name === undefined) return false
return this.playerNameToGameIndex.get(name) !== undefined
}
playerGame (name: string): Game {
if (this.isInAGame(name)) {
return this.games[this.playerNameToGameIndex.get(name)]
playerGame (name: string | undefined): Game | null {
if (name === undefined) return null
const gameIndex: number | undefined = this.playerNameToGameIndex.get(name)
if (gameIndex !== undefined) {
return this.games[gameIndex]
}
return null
}
spectateGame (
@ -59,13 +75,12 @@ export class Games {
socket: WebSocket,
uuid: string,
name: string
) {
if (this.isInAGame(nameToSpectate)) {
this.playerNameToGameIndex.set(
name,
): void {
const gameIndex: number | undefined =
this.playerNameToGameIndex.get(nameToSpectate)
)
this.playerGame(nameToSpectate).addSpectator(socket, uuid, name)
if (gameIndex !== undefined) {
this.playerNameToGameIndex.set(name, gameIndex)
this.games[gameIndex].addSpectator(socket, uuid, name)
}
}
}

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

@ -1,24 +0,0 @@
import { Test, type TestingModule } from '@nestjs/testing'
import { type INestApplication } from '@nestjs/common'
import * as request from 'supertest'
import { AppModule } from './../src/app.module'
describe('AppController (e2e)', () => {
let app: INestApplication
beforeEach(async () => {
const moduleFixture: TestingModule = await Test.createTestingModule({
imports: [AppModule]
}).compile()
app = moduleFixture.createNestApplication()
await app.init()
})
it('/ (GET)', async () => {
return await request(app.getHttpServer())
.get('/')
.expect(200)
.expect('Hello World!')
})
})

9
back/volume/test/jest-e2e.json

@ -1,9 +0,0 @@
{
"moduleFileExtensions": ["js", "json", "ts"],
"rootDir": ".",
"testEnvironment": "node",
"testRegex": ".e2e-spec.ts$",
"transform": {
"^.+\\.(t|j)s$": "ts-jest"
}
}

6
back/volume/tsconfig.json

@ -12,10 +12,6 @@
"baseUrl": "./",
"incremental": true,
"skipLibCheck": true,
"strictNullChecks": false,
"noImplicitAny": false,
"strictBindCallApply": false,
"forceConsistentCasingInFileNames": false,
"noFallthroughCasesInSwitch": false
"strict": true
}
}
Loading…
Cancel
Save