Browse Source

matchs result save in back and display in profile

master
nicolas-arnaud 2 years ago
parent
commit
54d53a1d73
  1. 20
      back/volume/src/pong/entity/result.entity.ts
  2. 8
      back/volume/src/pong/game/Game.ts
  3. 1
      back/volume/src/pong/game/constants.ts
  4. 10
      back/volume/src/pong/pong.module.ts
  5. 38
      back/volume/src/pong/pong.service.ts
  6. 1
      back/volume/src/users/dto/user.dto.ts
  7. 14
      back/volume/src/users/entity/user.entity.ts
  8. 10
      back/volume/src/users/users.service.ts
  9. 6
      front/volume/src/App.svelte
  10. 8
      front/volume/src/components/Profile.svelte

20
back/volume/src/pong/entity/result.entity.ts

@ -0,0 +1,20 @@
import {
Entity,
PrimaryGeneratedColumn,
Column,
ManyToMany,
} from 'typeorm'
import User from 'src/users/entity/user.entity'
@Entity()
export default class Result {
@PrimaryGeneratedColumn()
id:number
@ManyToMany(() => User, (player: User) => player.results)
players: User[]
@Column('text', {array: true})
public score: number[]
}

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

@ -7,15 +7,15 @@ import {
DEFAULT_PADDLE_SIZE, DEFAULT_PADDLE_SIZE,
DEFAULT_PLAYER_X_OFFSET, DEFAULT_PLAYER_X_OFFSET,
DEFAULT_WIN_SCORE, DEFAULT_WIN_SCORE,
GAME_EVENTS GAME_EVENTS,
GAME_TICKS
} from './constants' } from './constants'
import { randomUUID } from 'crypto' import { randomUUID } from 'crypto'
import { Spectator } from './Spectator' import { Spectator } from './Spectator'
import { type MapDtoValidated } from '../dtos/MapDtoValidated' import { type MapDtoValidated } from '../dtos/MapDtoValidated'
import { type GameUpdate } from '../dtos/GameUpdate' import { type GameUpdate } from '../dtos/GameUpdate'
import { type GameInfo } from '../dtos/GameInfo' import { type GameInfo } from '../dtos/GameInfo'
import { PongService } from '../pong.service'
const GAME_TICKS = 30
function gameLoop (game: Game): void { function gameLoop (game: Game): void {
const canvasRect: Rect = new Rect( const canvasRect: Rect = new Rect(
@ -50,6 +50,7 @@ function gameLoop (game: Game): void {
} }
export class Game { export class Game {
private readonly pongService: PongService
id: string id: string
timer: NodeJS.Timer | null timer: NodeJS.Timer | null
map: MapDtoValidated map: MapDtoValidated
@ -147,6 +148,7 @@ export class Game {
stop (): void { stop (): void {
if (this.timer !== null) { if (this.timer !== null) {
this.gameStoppedCallback(this.players[0].name) this.gameStoppedCallback(this.players[0].name)
this.pongService.saveResult(this.players)
clearInterval(this.timer) clearInterval(this.timer)
this.timer = null this.timer = null

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

@ -17,3 +17,4 @@ export const DEFAULT_PADDLE_SIZE = new Point(6, 50)
export const DEFAULT_BALL_SIZE = new Point(20, 20) export const DEFAULT_BALL_SIZE = new Point(20, 20)
export const DEFAULT_PLAYER_X_OFFSET = 50 export const DEFAULT_PLAYER_X_OFFSET = 50
export const DEFAULT_WIN_SCORE = 5 export const DEFAULT_WIN_SCORE = 5
export const GAME_TICKS = 30

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

@ -1,7 +1,15 @@
import { Module } from '@nestjs/common' import { Module } from '@nestjs/common'
import { PongGateway } from './pong.gateway' import { PongGateway } from './pong.gateway'
import Result from './entity/result.entity'
import {TypeOrmModule } from '@nestjs/typeorm'
import {PongService } from './pong.service'
import { UsersModule } from 'src/users/users.module'
@Module({ @Module({
providers: [PongGateway] imports: [
UsersModule,
TypeOrmModule.forFeature([Result])
],
providers: [PongGateway, PongService],
}) })
export class PongModule {} export class PongModule {}

38
back/volume/src/pong/pong.service.ts

@ -0,0 +1,38 @@
import { Inject, Injectable } from "@nestjs/common";
import { InjectRepository } from "@nestjs/typeorm";
import { Repository } from 'typeorm'
import { UsersService } from 'src/users/users.service'
import Result from './entity/result.entity'
import User from 'src/users/entity/user.entity'
import { Player } from './game/Player'
@Injectable()
export class PongService {
constructor(
@InjectRepository(Result)private readonly resultsRepository: Repository<Result>,
private readonly usersService: UsersService
) { }
async saveResult(players: Player[]) {
let result = new Result;
result.players = await Promise.all(players.map(async (p): Promise<User> => {
return await this.usersService.findUserByName(p.name)
}))
result.score = players.map((p) => p.score);
result.players.forEach((p) => p.matchs++)
if (result.score[0] > result.score[1]) {
result.players[0].wins++;
result.players[1].looses++;
}
else if (result.score[1] > result.score[0]) {
result.players[1].wins++
result.players[0].looses++
}
result.players[0].results.push(result)
result.players[1].results.push(result)
this.resultsRepository.save(result)
this.usersService.save(result.players[0],)
this.usersService.save(result.players[1])
}
}

1
back/volume/src/users/dto/user.dto.ts

@ -14,6 +14,7 @@ export class UserDto {
@IsOptional() @IsOptional()
readonly status: string readonly status: string
} }
export class AvatarUploadDto { export class AvatarUploadDto {

14
back/volume/src/users/entity/user.entity.ts

@ -9,6 +9,7 @@ import {
import Message from 'src/chat/entity/message.entity' import Message from 'src/chat/entity/message.entity'
import Channel from 'src/chat/entity/channel.entity' import Channel from 'src/chat/entity/channel.entity'
import Result from 'src/pong/entity/result.entity'
@Entity() @Entity()
export class User { export class User {
@ -27,6 +28,19 @@ export class User {
@Column({ name: 'avatar' }) @Column({ name: 'avatar' })
public avatar?: string public avatar?: string
@Column({default: 0})
wins: number
@Column({default: 0})
looses: number
@Column({default: 0})
matchs: number
@ManyToMany(() => Result, (result: Result) => result.players)
@JoinTable()
results: Result[]
@OneToMany(() => Message, (message: Message) => message.author) @OneToMany(() => Message, (message: Message) => message.author)
messages: Message[] messages: Message[]

10
back/volume/src/users/users.service.ts

@ -11,12 +11,18 @@ export class UsersService {
@InjectRepository(User) private readonly usersRepository: Repository<User> @InjectRepository(User) private readonly usersRepository: Repository<User>
) {} ) {}
save(user: User) {
this.usersRepository.save(user)
}
async findUsers (): Promise<User[]> { async findUsers (): Promise<User[]> {
return await this.usersRepository.find({}) return await this.usersRepository.find({})
} }
async findUserByName (username: string): Promise<User | null> { async findUserByName (username: string): Promise<User> {
return await this.usersRepository.findOneBy({ username }) let user = await this.usersRepository.findOneBy({ username })
if (!user) return Promise.reject()
else return user;
} }
async findUser (ftId: number): Promise<User | null> { async findUser (ftId: number): Promise<User | null> {

6
front/volume/src/App.svelte

@ -167,9 +167,9 @@
> >
<Profile <Profile
username={$store.username} username={$store.username}
wins={10} wins={$store.wins}
losses={5} losses={$store.looses}
elo={256} winrate={$store.matchs? $store.wins / $store.matchs : 0}
rank={23} rank={23}
is2faEnabled={false} is2faEnabled={false}
/> />

8
front/volume/src/components/Profile.svelte

@ -1,10 +1,10 @@
<script lang="ts"> <script lang="ts">
import { API_URL, store, logout } from "../Auth"; import { API_URL, store, logout } from "../Auth";
export let username = $store.userame; export let username = "";
export let realname = "";
export let wins = 0; export let wins = 0;
export let losses = 0; export let losses = 0;
export let winrate = 0;
export let elo = 0; export let elo = 0;
export let rank = -1; export let rank = -1;
export let is2faEnabled = false; export let is2faEnabled = false;
@ -37,8 +37,6 @@
<div class="overlay"> <div class="overlay">
<div class="profile" on:click|stopPropagation on:keydown|stopPropagation> <div class="profile" on:click|stopPropagation on:keydown|stopPropagation>
<div class="profile-header"> <div class="profile-header">
<h3>{realname}</h3>
<form action={API_URL + "/avatar"} method="post" <form action={API_URL + "/avatar"} method="post"
enctype="multipart/form-data" id= "upload_avatar"> enctype="multipart/form-data" id= "upload_avatar">
<div class=input-avatar> <div class=input-avatar>
@ -64,7 +62,7 @@
</form> </form>
<p>Wins: {wins}</p> <p>Wins: {wins}</p>
<p>Losses: {losses}</p> <p>Losses: {losses}</p>
<p>Winrate: {(wins / (wins + losses)) * 100}%</p> <p>Winrate: {winrate}%</p>
<p>Elo : {elo}</p> <p>Elo : {elo}</p>
<p>Rank: {rank}</p> <p>Rank: {rank}</p>
<form class="two-factor-auth" on:submit={handle2fa}> <form class="two-factor-auth" on:submit={handle2fa}>

Loading…
Cancel
Save