diff --git a/back/volume/src/pong/entity/result.entity.ts b/back/volume/src/pong/entity/result.entity.ts index 53232dc..863f2ff 100644 --- a/back/volume/src/pong/entity/result.entity.ts +++ b/back/volume/src/pong/entity/result.entity.ts @@ -13,6 +13,9 @@ export default class Result { @PrimaryGeneratedColumn() id: number + @Column() + ranked: boolean + @ManyToMany(() => User, (player: User) => player.results, { cascade: true }) players: Array // TODO: change to User[] for final version diff --git a/back/volume/src/pong/game/Game.ts b/back/volume/src/pong/game/Game.ts index b3c3b99..2a63ad8 100644 --- a/back/volume/src/pong/game/Game.ts +++ b/back/volume/src/pong/game/Game.ts @@ -112,7 +112,7 @@ export class Game { async stop (): Promise { if (this.timer !== null) { - await this.pongService.saveResult(this.players) + await this.pongService.saveResult(this.players, this.ranked) if (this.players.length !== 0) { this.gameStoppedCallback(this.players[0].name) } diff --git a/back/volume/src/pong/pong.service.ts b/back/volume/src/pong/pong.service.ts index 8845150..1ea8201 100644 --- a/back/volume/src/pong/pong.service.ts +++ b/back/volume/src/pong/pong.service.ts @@ -14,14 +14,17 @@ export class PongService { private readonly usersService: UsersService ) {} - async updatePlayer (i: number, result: Result): Promise { - const player: User | null = result.players[i] - if (player == null) return + async updateStats (player: User, i: number, result: Result): Promise { player.matchs++ if (result.score[i] > result.score[Math.abs(i - 1)]) player.wins++ else player.looses++ player.winrate = (100 * player.wins) / player.matchs player.rank = (await this.usersService.getRank(player.ftId)) + 1 + } + async updatePlayer (i: number, result: Result) { + const player: User | null = result.players[i] + if (player == null) return + if (result.ranked) this.updateStats(player, i, result) player.results.push(result) player.status = "online" await this.usersService.save(player) @@ -33,11 +36,12 @@ export class PongService { await this.usersService.save(player) } - async saveResult (players: Player[]): Promise { + async saveResult (players: Player[], ranked: boolean): Promise { const result = new Result() const ply = new Array() ply.push(await this.usersService.findUserByName(players[0].name)) ply.push(await this.usersService.findUserByName(players[1].name)) + result.ranked = ranked; result.players = ply result.score = [players[0].score, players[1].score] await this.resultsRepository.save(result) @@ -45,14 +49,15 @@ export class PongService { await this.updatePlayer(1, result) } - async getHistory (): Promise { + async getHistory (ranked: boolean): Promise { return await this.resultsRepository.find({ + where: { ranked }, order: { date: 'DESC' } }) } async getHistoryById (ftId: number): Promise { - const results = await this.usersService.getResults(ftId) + const results = await this.usersService.getResultsById(ftId) return results.sort((a, b) => (a.date < b.date ? 1 : -1)) } } diff --git a/back/volume/src/users/entity/user.entity.ts b/back/volume/src/users/entity/user.entity.ts index 9a4ffef..5b853ea 100644 --- a/back/volume/src/users/entity/user.entity.ts +++ b/back/volume/src/users/entity/user.entity.ts @@ -6,7 +6,6 @@ import { ManyToMany, JoinTable } from 'typeorm' -import { randomUUID } from 'crypto' import Message from 'src/chat/entity/message.entity' import Channel from 'src/chat/entity/channel.entity' @@ -23,7 +22,7 @@ export class User { @Column({ unique: true }) ftId: number - @Column({ unique: true, default: randomUUID() }) + @Column({ unique: true}) socketKey: string @Column({ unique: true }) diff --git a/back/volume/src/users/users.controller.ts b/back/volume/src/users/users.controller.ts index 897d37e..9762b9f 100644 --- a/back/volume/src/users/users.controller.ts +++ b/back/volume/src/users/users.controller.ts @@ -73,10 +73,10 @@ export class UsersController { return await this.usersService.getRank(id) } - @Get('history') + @Get('rankedHistory') @UseGuards(AuthenticatedGuard) - async getHistory (): Promise { - return await this.pongService.getHistory() + async getRankedHistory (): Promise { + return await this.pongService.getHistory(true) } @Get('history/:id') @@ -169,6 +169,7 @@ export class UsersController { @Param('id', ParseIntPipe) ftId: number ): Promise { const user = await this.usersService.findUser(ftId) + if (!user) throw new BadRequestException('User unknown.') user.socketKey = '' return user } diff --git a/back/volume/src/users/users.service.ts b/back/volume/src/users/users.service.ts index bdd69e7..80d90f0 100644 --- a/back/volume/src/users/users.service.ts +++ b/back/volume/src/users/users.service.ts @@ -1,173 +1,173 @@ -import { BadRequestException, Catch, Injectable } from '@nestjs/common' -import { InjectRepository } from '@nestjs/typeorm' -import { EntityNotFoundError, QueryFailedError, Repository } from 'typeorm' -import { User } from './entity/user.entity' -import { type UserDto } from './dto/user.dto' -import { type Channel } from 'src/chat/entity/channel.entity' -import type Result from 'src/pong/entity/result.entity' -import { Cron } from '@nestjs/schedule' +import { BadRequestException, Catch, Injectable } from "@nestjs/common"; +import { InjectRepository } from "@nestjs/typeorm"; +import { EntityNotFoundError, QueryFailedError, Repository } from "typeorm"; +import { User } from "./entity/user.entity"; +import { type UserDto } from "./dto/user.dto"; +import { type Channel } from "src/chat/entity/channel.entity"; +import type Result from "src/pong/entity/result.entity"; +import { Cron } from "@nestjs/schedule"; +import { randomUUID } from "crypto"; @Injectable() @Catch(QueryFailedError, EntityNotFoundError) export class UsersService { - constructor ( + constructor( @InjectRepository(User) private readonly usersRepository: Repository ) {} - async save (user: User): Promise { - await this.usersRepository.save(user) + async save(user: User): Promise { + await this.usersRepository.save(user); } - async findUsers (): Promise { - const users = await this.usersRepository.find({}) + async findUsers(): Promise { + const users = await this.usersRepository.find({}); users.forEach((usr) => { - usr.socketKey = '' - }) - return users + usr.socketKey = ""; + }); + return users; } - async findUserByName (username: string): Promise { + async findUserByName(username: string): Promise { const user = await this.usersRepository.findOne({ where: { username }, - relations: { results: true } - }) - if (user == null) throw new BadRequestException('User not found.') - return user + relations: { results: true }, + }); + if (user == null) throw new BadRequestException("User not found."); + return user; } - @Cron('0 * * * * *') - async updateStatus (): Promise { - const users = await this.usersRepository.find({}) + @Cron("0 * * * * *") + async updateStatus(): Promise { + const users = await this.usersRepository.find({}); users.forEach((usr) => { if (Date.now() - usr.lastAccess > 60000) { - usr.status = 'offline' + usr.status = "offline"; this.usersRepository.save(usr).catch((err) => { - console.log(err) - }) + console.log(err); + }); } - }) + }); } - async findUser (ftId: number): Promise { - const user = await this.usersRepository.findOneBy({ ftId }) - if (user == null) throw new BadRequestException('User not found.') - user.lastAccess = Date.now() - if (user.status === 'offline') user.status = 'online' - await this.usersRepository.save(user) - return user + async findUser(ftId: number): Promise { + const user = await this.usersRepository.findOneBy({ ftId }); + if (user == null) return null; + user.lastAccess = Date.now(); + if (user.status === "offline") user.status = "online"; + await this.usersRepository.save(user); + return user; } - async findOnlineUsers (): Promise { + async findOnlineUsers(): Promise { const users = await this.usersRepository.find({ - where: { status: 'online' } - }) + where: { status: "online" }, + }); users.forEach((usr) => { - usr.socketKey = '' - }) - return users + usr.socketKey = ""; + }); + return users; } - async create (userData: UserDto): Promise { + async create(userData: UserDto): Promise { try { - const newUser = this.usersRepository.create(userData) - return await this.usersRepository.save(newUser) + const newUser = this.usersRepository.create(userData); + newUser.socketKey = randomUUID() + return await this.usersRepository.save(newUser); } catch (err) { - throw new BadRequestException('User already exists.') + throw new BadRequestException("User already exists."); } } - async findOnlineInChannel (channel: Channel): Promise { + async findOnlineInChannel(channel: Channel): Promise { return await this.usersRepository - .createQueryBuilder('user') - .where('user.channel = :chan', { chan: channel }) - .andWhere('user.status := status)', { status: 'online' }) - .getMany() + .createQueryBuilder("user") + .where("user.channel = :chan", { chan: channel }) + .andWhere("user.status := status)", { status: "online" }) + .getMany(); } - async update (user: User, changes: UserDto): Promise { - this.usersRepository.merge(user, changes) - return await this.usersRepository.save(user) + async update(user: User, changes: UserDto): Promise { + this.usersRepository.merge(user, changes); + return await this.usersRepository.save(user); } - async addAvatar (ftId: number, filename: string): Promise { - await this.usersRepository.update({ ftId }, { avatar: filename }) + async addAvatar(ftId: number, filename: string): Promise { + await this.usersRepository.update({ ftId }, { avatar: filename }); } - async getFriends (ftId: number): Promise { + async getFriends(ftId: number): Promise { const user = await this.usersRepository.findOne({ where: { ftId }, - relations: { friends: true } - }) - if (user == null) throw new BadRequestException('User not found.') - return user.friends + relations: { friends: true }, + }); + if (user == null) throw new BadRequestException("User not found."); + return user.friends; } - async getInvits (ftId: number): Promise { + async getInvits(ftId: number): Promise { const user = await this.usersRepository.findOne({ where: { ftId }, relations: { - followers: true - } - }) - if (user == null) throw new BadRequestException('User not found.') - return user.followers + followers: true, + }, + }); + if (user == null) throw new BadRequestException("User not found."); + return user.followers; } - async getResults (ftId: number): Promise { + async getResultsById(ftId: number): Promise { const user = await this.usersRepository.findOne({ where: { ftId }, - relations: { - results: { - players: true - } - } - }) - if (user == null) throw new BadRequestException('User not found.') - return user.results + relations: { results: { players: true } }, + }); + if (user == null) throw new BadRequestException("User not found."); + return user.results; } - async getLeaderboard (): Promise { - return await this.usersRepository.find({ + async getLeaderboard(): Promise { + let leaderboard = await this.usersRepository.find({ order: { - winrate: 'DESC' - } - }) + winrate: "DESC", + }, + }); + return leaderboard.filter((user) => user.rank !== 0); + } - async getRank (ftId: number): Promise { - const leader = await this.getLeaderboard() - return leader.findIndex((user) => user.ftId === ftId) + async getRank(ftId: number): Promise { + const leader = await this.getLeaderboard(); + return leader.findIndex((user) => user.ftId === ftId); } - async invit (ftId: number, targetFtId: number): Promise { + async invit(ftId: number, targetFtId: number): Promise { const user: User | null = await this.usersRepository.findOne({ where: { ftId }, relations: { followers: true, - friends: true - } - }) - if (user == null) throw new BadRequestException('User not found.') + friends: true, + }, + }); + if (user == null) throw new BadRequestException("User not found."); if (user.friends.findIndex((friend) => friend.ftId === targetFtId) !== -1) { - throw new BadRequestException('You are already friends.') + throw new BadRequestException("You are already friends."); } const target: User | null = await this.usersRepository.findOne({ where: { ftId: targetFtId }, relations: { followers: true, - friends: true - } - }) - if (target == null) throw new BadRequestException('Target not found.') + friends: true, + }, + }); + if (target == null) throw new BadRequestException("Target not found."); const id = user.followers.findIndex( (follower) => follower.ftId === targetFtId - ) + ); if (id !== -1) { - user.friends.push(target) - if (user.ftId !== target.ftId) target.friends.push(user) - user.followers.slice(id, 1) - await this.usersRepository.save(user) - } else target.followers.push(user) - await this.usersRepository.save(target) + user.friends.push(target); + if (user.ftId !== target.ftId) target.friends.push(user); + user.followers.slice(id, 1); + await this.usersRepository.save(user); + } else target.followers.push(user); + await this.usersRepository.save(target); } }