diff --git a/app/api/src/app.module.ts b/app/api/src/app.module.ts index 5a61b6c..8610075 100644 --- a/app/api/src/app.module.ts +++ b/app/api/src/app.module.ts @@ -8,6 +8,8 @@ import { AppController } from './app.controller'; import { AppService } from './app.service'; import { GamesModule } from './games/games.module'; import { GameModule } from './game/game.module'; +import { PlayersModule } from './players/players.module'; +import { PlayerModule } from './player/player.module'; @Module({ imports: [ @@ -27,7 +29,9 @@ import { GameModule } from './game/game.module'; autoLoadEntities: true // models will be loaded automatically (you don't have to explicitly specify the entities: [] array) }), GamesModule, - GameModule + GameModule, + PlayersModule, + PlayerModule ], controllers: [ AppController ], providers: [ AppService ] diff --git a/app/api/src/game/entities/GameDetail.ts b/app/api/src/game/entities/GameDetail.ts index 80be141..5563528 100644 --- a/app/api/src/game/entities/GameDetail.ts +++ b/app/api/src/game/entities/GameDetail.ts @@ -1,6 +1,7 @@ import { Column, Entity, Index, JoinColumn, ManyToOne, PrimaryGeneratedColumn } from 'typeorm'; + import { Games } from '../../games/entities/Games'; -import { Players } from '../../entities/Players'; +import { Players } from '../../players/entities/Players'; @Index('games_pk', [ 'id' ], { unique: true }) @Index('game_detail_uuid_key', [ 'uuid' ], { unique: true }) @@ -12,7 +13,7 @@ export class GameDetail { @Column('text', { name: 'player_name' }) playerName: string; - @Column('numeric', { name: 'stat_overwrite' }) + @Column('numeric', { name: 'stat_overwrite', select: false }) statOverwrite: string; @Column('text', { name: 'map' }) @@ -40,7 +41,7 @@ export class GameDetail { @JoinColumn([ { name: 'game_id', referencedColumnName: 'gameId' } ]) game: Games; - // @ManyToOne(() => Players, (players) => players.gameDetails) - // @JoinColumn([ { name: 'player_guid', referencedColumnName: 'playerGuid' } ]) - // playerGuid: Players; + @ManyToOne(() => Players, (players) => players.gameDetails) + @JoinColumn([ { name: 'player_guid', referencedColumnName: 'playerGuid' } ]) + playerGuid: Players; } diff --git a/app/api/src/game/game.controller.ts b/app/api/src/game/game.controller.ts index 3ec34f0..cd06242 100644 --- a/app/api/src/game/game.controller.ts +++ b/app/api/src/game/game.controller.ts @@ -1,4 +1,4 @@ -import { Controller, Get, Param, Query } from '@nestjs/common'; +import { Controller, Get, Param } from '@nestjs/common'; import { GameService } from './game.service'; @Controller('game') diff --git a/app/api/src/game/game.module.ts b/app/api/src/game/game.module.ts index a3948dd..06cd534 100644 --- a/app/api/src/game/game.module.ts +++ b/app/api/src/game/game.module.ts @@ -8,8 +8,10 @@ import { GameService } from './game.service'; import { GameDetail } from './entities/GameDetail'; import { Games } from '../games/entities/Games'; +import { Players } from '../players/entities/Players'; + @Module({ - imports: [ TypeOrmModule.forFeature([ Games, GameDetail ]), ConfigModule ], + imports: [ TypeOrmModule.forFeature([ Games, GameDetail, Players ]), ConfigModule ], controllers: [ GameController ], providers: [ GameService ] }) diff --git a/app/api/src/game/game.service.ts b/app/api/src/game/game.service.ts index 9b7b6ff..f897a87 100644 --- a/app/api/src/game/game.service.ts +++ b/app/api/src/game/game.service.ts @@ -3,6 +3,7 @@ import { ConfigService } from '@nestjs/config'; import { InjectRepository } from '@nestjs/typeorm'; import { Connection, Repository } from 'typeorm'; +import { Games } from '../games/entities/Games'; import { GameDetail } from './entities/GameDetail'; @Injectable() @@ -10,11 +11,15 @@ export class GameService { constructor( private readonly connection: Connection, private readonly configService: ConfigService, + @InjectRepository(Games) private readonly gamesRepository: Repository, @InjectRepository(GameDetail) private readonly gameRepository: Repository ) {} async findOne(gameId: string) { - const game = await this.gameRepository.find({ where: { gameId: gameId } }); + const game = await this.gameRepository.find({ + relations: [ 'game', 'playerGuid' ], + where: [ { game: { gameId: gameId } } ] + }); if (!game) { throw new NotFoundException(`Game ID: ${gameId} not found`); } diff --git a/app/api/src/games/entities/Games.ts b/app/api/src/games/entities/Games.ts index 9722f31..103fd09 100644 --- a/app/api/src/games/entities/Games.ts +++ b/app/api/src/games/entities/Games.ts @@ -22,10 +22,6 @@ export class Games { }) createdAt: Date; - @OneToMany(() => GameDetail, (gameDetail) => Games.gameDetail) + @OneToMany(() => GameDetail, (gameDetail) => gameDetail.game) gameDetails: GameDetail[]; - - @ManyToOne(() => Games, (games) => games.gameDetail) - @JoinColumn([ { name: 'game_id', referencedColumnName: 'gameId' } ]) - game: Games; } diff --git a/app/api/src/games/games.controller.ts b/app/api/src/games/games.controller.ts index 651ced8..686ebc8 100644 --- a/app/api/src/games/games.controller.ts +++ b/app/api/src/games/games.controller.ts @@ -1,6 +1,6 @@ import { Controller, Get, Param, Query } from '@nestjs/common'; -import { GamesService } from './games.service'; +import { GamesService } from './games.service'; import { PaginationQueryDto } from '../common/dto/pagination-query.dto'; @Controller('games') diff --git a/app/api/src/player/player.controller.spec.ts b/app/api/src/player/player.controller.spec.ts new file mode 100644 index 0000000..a877382 --- /dev/null +++ b/app/api/src/player/player.controller.spec.ts @@ -0,0 +1,18 @@ +import { Test, TestingModule } from '@nestjs/testing'; +import { PlayerController } from './player.controller'; + +describe('PlayerController', () => { + let controller: PlayerController; + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + controllers: [PlayerController], + }).compile(); + + controller = module.get(PlayerController); + }); + + it('should be defined', () => { + expect(controller).toBeDefined(); + }); +}); diff --git a/app/api/src/player/player.controller.ts b/app/api/src/player/player.controller.ts new file mode 100644 index 0000000..7713ec3 --- /dev/null +++ b/app/api/src/player/player.controller.ts @@ -0,0 +1,15 @@ +import { Controller, Get, Param } from '@nestjs/common'; + +import { PlayerService } from './player.service'; +import { PaginationQueryDto } from '../common/dto/pagination-query.dto'; + +@Controller('player') +export class PlayerController { + constructor(private readonly playerService: PlayerService) {} + + // /player/:playerGuid + @Get(':playerGuid') + findOne(@Param('playerGuid') playerGuid: string) { + return this.playerService.findOne(playerGuid); + } +} diff --git a/app/api/src/player/player.module.ts b/app/api/src/player/player.module.ts new file mode 100644 index 0000000..5432b41 --- /dev/null +++ b/app/api/src/player/player.module.ts @@ -0,0 +1,16 @@ +import { Module } from '@nestjs/common'; +import { ConfigModule } from '@nestjs/config'; +import { TypeOrmModule } from '@nestjs/typeorm'; + +import { PlayerController } from './player.controller'; +import { PlayerService } from './player.service'; + +import { Players } from '../players/entities/Players'; +import { GameDetail } from '../game/entities/GameDetail'; + +@Module({ + imports: [ TypeOrmModule.forFeature([ Players, GameDetail ]), ConfigModule ], + controllers: [ PlayerController ], + providers: [ PlayerService ] +}) +export class PlayerModule {} diff --git a/app/api/src/player/player.service.spec.ts b/app/api/src/player/player.service.spec.ts new file mode 100644 index 0000000..06ea153 --- /dev/null +++ b/app/api/src/player/player.service.spec.ts @@ -0,0 +1,18 @@ +import { Test, TestingModule } from '@nestjs/testing'; +import { PlayerService } from './player.service'; + +describe('PlayerService', () => { + let service: PlayerService; + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + providers: [PlayerService], + }).compile(); + + service = module.get(PlayerService); + }); + + it('should be defined', () => { + expect(service).toBeDefined(); + }); +}); diff --git a/app/api/src/player/player.service.ts b/app/api/src/player/player.service.ts new file mode 100644 index 0000000..d88b4f5 --- /dev/null +++ b/app/api/src/player/player.service.ts @@ -0,0 +1,28 @@ +import { Injectable, NotFoundException } from '@nestjs/common'; +import { ConfigService } from '@nestjs/config'; +import { InjectRepository } from '@nestjs/typeorm'; +import { Connection, Repository } from 'typeorm'; + +import { Players } from '../players/entities/Players'; +import { GameDetail } from '../game/entities/GameDetail'; + +@Injectable() +export class PlayerService { + constructor( + private readonly connection: Connection, + private readonly configService: ConfigService, + @InjectRepository(Players) private readonly playersRepository: Repository, + @InjectRepository(GameDetail) private readonly gameRepository: Repository + ) {} + + async findOne(playerGuid: string) { + const player = await this.playersRepository.findOne({ + relations: [ 'gameDetails' ], + where: [ { playerGuid: playerGuid } ] + }); + if (!player) { + throw new NotFoundException(`Player GUID: ${playerGuid} not found`); + } + return player; + } +} diff --git a/app/api/src/entities/Players.ts b/app/api/src/players/entities/Players.ts similarity index 73% rename from app/api/src/entities/Players.ts rename to app/api/src/players/entities/Players.ts index cbf31dd..74024d4 100644 --- a/app/api/src/entities/Players.ts +++ b/app/api/src/players/entities/Players.ts @@ -1,13 +1,13 @@ import { Column, Entity, Index, OneToMany, PrimaryGeneratedColumn } from 'typeorm'; -import { GameDetail } from '../game/entities/GameDetail'; +import { GameDetail } from '../../game/entities/GameDetail'; @Index('players_pk', [ 'playerGuid' ], { unique: true }) @Index('players_player_name_key', [ 'playerName' ], { unique: true }) @Index('players_uuid_key', [ 'uuid' ], { unique: true }) @Entity('players', { schema: 'public' }) export class Players { - @PrimaryGeneratedColumn({ type: 'integer', name: 'id' }) - id: number; + // @PrimaryGeneratedColumn({ type: 'integer', name: 'id' }) + // id: number; @Column('numeric', { primary: true, name: 'player_guid' }) playerGuid: string; @@ -27,19 +27,20 @@ export class Players { @Column('numeric', { name: 'total_games_sctfgame', default: () => '0' }) totalGamesSctfgame: string; - @Column('numeric', { name: 'stat_overwrite_ctfgame', default: () => '0' }) + @Column('numeric', { name: 'stat_overwrite_ctfgame', select: false, default: () => '0' }) statOverwriteCtfgame: string; - @Column('numeric', { name: 'stat_overwrite_dmgame', default: () => '0' }) + @Column('numeric', { name: 'stat_overwrite_dmgame', select: false, default: () => '0' }) statOverwriteDmgame: string; @Column('numeric', { name: 'stat_overwrite_lakrabbitgame', + select: false, default: () => '0' }) statOverwriteLakrabbitgame: string; - @Column('numeric', { name: 'stat_overwrite_sctfgame', default: () => '0' }) + @Column('numeric', { name: 'stat_overwrite_sctfgame', select: false, default: () => '0' }) statOverwriteSctfgame: string; @Column('text', { name: 'uuid', unique: true }) @@ -57,6 +58,6 @@ export class Players { }) updatedAt: Date; - // @OneToMany(() => GameDetail, (gameDetail) => gameDetail.playerGuid) - // gameDetails: GameDetail[]; + @OneToMany(() => GameDetail, (gameDetail) => gameDetail.playerGuid) + gameDetails: GameDetail[]; } diff --git a/app/api/src/players/players.controller.spec.ts b/app/api/src/players/players.controller.spec.ts new file mode 100644 index 0000000..4741506 --- /dev/null +++ b/app/api/src/players/players.controller.spec.ts @@ -0,0 +1,18 @@ +import { Test, TestingModule } from '@nestjs/testing'; +import { PlayersController } from './players.controller'; + +describe('PlayersController', () => { + let controller: PlayersController; + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + controllers: [PlayersController], + }).compile(); + + controller = module.get(PlayersController); + }); + + it('should be defined', () => { + expect(controller).toBeDefined(); + }); +}); diff --git a/app/api/src/players/players.controller.ts b/app/api/src/players/players.controller.ts new file mode 100644 index 0000000..6b4dea9 --- /dev/null +++ b/app/api/src/players/players.controller.ts @@ -0,0 +1,22 @@ +import { Controller, Get, Query, Param } from '@nestjs/common'; + +import { PlayersService } from './players.service'; +import { PaginationQueryDto } from '../common/dto/pagination-query.dto'; + +@Controller('players') +export class PlayersController { + constructor(private readonly playerService: PlayersService) {} + + // /players + @Get() + findAll(@Query() paginationQuery: PaginationQueryDto) { + const { limit = 10, offset = 0 } = paginationQuery; + return this.playerService.findAll({ limit, offset }); + } + + // /players/:playerGuid + @Get(':playerGuid') + findOne(@Param('playerGuid') playerGuid: string) { + return this.playerService.findOne(playerGuid); + } +} diff --git a/app/api/src/players/players.module.ts b/app/api/src/players/players.module.ts new file mode 100644 index 0000000..89c0981 --- /dev/null +++ b/app/api/src/players/players.module.ts @@ -0,0 +1,16 @@ +import { Module } from '@nestjs/common'; +import { ConfigModule } from '@nestjs/config'; +import { TypeOrmModule } from '@nestjs/typeorm'; + +import { PlayersService } from './players.service'; +import { PlayersController } from './players.controller'; + +import { Players } from './entities/Players'; +import { GameDetail } from '../game/entities/GameDetail'; + +@Module({ + imports: [ TypeOrmModule.forFeature([ Players, GameDetail ]), ConfigModule ], + providers: [ PlayersService ], + controllers: [ PlayersController ] +}) +export class PlayersModule {} diff --git a/app/api/src/players/players.service.spec.ts b/app/api/src/players/players.service.spec.ts new file mode 100644 index 0000000..a825838 --- /dev/null +++ b/app/api/src/players/players.service.spec.ts @@ -0,0 +1,18 @@ +import { Test, TestingModule } from '@nestjs/testing'; +import { PlayersService } from './players.service'; + +describe('PlayersService', () => { + let service: PlayersService; + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + providers: [PlayersService], + }).compile(); + + service = module.get(PlayersService); + }); + + it('should be defined', () => { + expect(service).toBeDefined(); + }); +}); diff --git a/app/api/src/players/players.service.ts b/app/api/src/players/players.service.ts new file mode 100644 index 0000000..860f024 --- /dev/null +++ b/app/api/src/players/players.service.ts @@ -0,0 +1,42 @@ +import { Injectable, NotFoundException } from '@nestjs/common'; +import { ConfigService } from '@nestjs/config'; +import { InjectRepository } from '@nestjs/typeorm'; +import { Connection, Repository } from 'typeorm'; + +import { Players } from './entities/Players'; +import { GameDetail } from '../game/entities/GameDetail'; +import { PaginationQueryDto } from '../common/dto/pagination-query.dto'; + +@Injectable() +export class PlayersService { + constructor( + private readonly connection: Connection, + private readonly configService: ConfigService, + @InjectRepository(Players) private readonly playersRepository: Repository, + @InjectRepository(GameDetail) private readonly gameRepository: Repository + ) {} + + async findAll(paginationQuery: PaginationQueryDto) { + const { limit, offset } = paginationQuery; + const players = await this.playersRepository.find({ + skip: offset, + take: limit, + order: { + playerName: 'DESC' + } + }); + + return players; + } + + async findOne(playerGuid: string) { + const player = await this.playersRepository.findOne({ + relations: [ 'gameDetails' ], + where: [ { playerGuid: playerGuid } ] + }); + if (!player) { + throw new NotFoundException(`Player GUID: ${playerGuid} not found`); + } + return player; + } +}