Compare commits
	
		
			5 Commits
		
	
	
		
			23081e0220
			...
			a0fd6ca6ab
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| a0fd6ca6ab | |||
| 20b4f2e7e8 | |||
| 33689d9c76 | |||
| 50a9f3369c | |||
| 31c44eab6e | 
| @@ -1,5 +1,5 @@ | |||||||
| -- CreateEnum | -- CreateEnum | ||||||
| CREATE TYPE "MoneyUpdateType" AS ENUM ('START', 'WIN_CHALLENGE', 'BUY_TRAIN'); | CREATE TYPE "MoneyUpdateType" AS ENUM ('START', 'NEW_RUN', 'WIN_CHALLENGE', 'BUY_TRAIN'); | ||||||
| 
 | 
 | ||||||
| -- CreateTable | -- CreateTable | ||||||
| CREATE TABLE "Player" ( | CREATE TABLE "Player" ( | ||||||
| @@ -15,11 +15,22 @@ CREATE TABLE "Player" ( | |||||||
| CREATE TABLE "Game" ( | CREATE TABLE "Game" ( | ||||||
|     "id" SERIAL NOT NULL, |     "id" SERIAL NOT NULL, | ||||||
|     "started" BOOLEAN NOT NULL DEFAULT false, |     "started" BOOLEAN NOT NULL DEFAULT false, | ||||||
|     "currentRunnerId" INTEGER, |     "currentRunId" INTEGER, | ||||||
| 
 | 
 | ||||||
|     CONSTRAINT "Game_pkey" PRIMARY KEY ("id") |     CONSTRAINT "Game_pkey" PRIMARY KEY ("id") | ||||||
| ); | ); | ||||||
| 
 | 
 | ||||||
|  | -- CreateTable | ||||||
|  | CREATE TABLE "PlayerRun" ( | ||||||
|  |     "id" SERIAL NOT NULL, | ||||||
|  |     "gameId" INTEGER NOT NULL, | ||||||
|  |     "runnerId" INTEGER NOT NULL, | ||||||
|  |     "start" TIMESTAMPTZ(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, | ||||||
|  |     "end" TIMESTAMPTZ(3), | ||||||
|  | 
 | ||||||
|  |     CONSTRAINT "PlayerRun_pkey" PRIMARY KEY ("id") | ||||||
|  | ); | ||||||
|  | 
 | ||||||
| -- CreateTable | -- CreateTable | ||||||
| CREATE TABLE "Geolocation" ( | CREATE TABLE "Geolocation" ( | ||||||
|     "id" SERIAL NOT NULL, |     "id" SERIAL NOT NULL, | ||||||
| @@ -56,6 +67,7 @@ CREATE TABLE "ChallengeAction" ( | |||||||
|     "end" TIMESTAMPTZ(3), |     "end" TIMESTAMPTZ(3), | ||||||
|     "penaltyStart" TIMESTAMPTZ(3), |     "penaltyStart" TIMESTAMPTZ(3), | ||||||
|     "penaltyEnd" TIMESTAMPTZ(3), |     "penaltyEnd" TIMESTAMPTZ(3), | ||||||
|  |     "runId" INTEGER NOT NULL, | ||||||
| 
 | 
 | ||||||
|     CONSTRAINT "ChallengeAction_pkey" PRIMARY KEY ("id") |     CONSTRAINT "ChallengeAction_pkey" PRIMARY KEY ("id") | ||||||
| ); | ); | ||||||
| @@ -70,6 +82,7 @@ CREATE TABLE "TrainTrip" ( | |||||||
|     "departureTime" TIMESTAMPTZ(3) NOT NULL, |     "departureTime" TIMESTAMPTZ(3) NOT NULL, | ||||||
|     "arrivalTime" TIMESTAMPTZ(3) NOT NULL, |     "arrivalTime" TIMESTAMPTZ(3) NOT NULL, | ||||||
|     "infoJson" JSONB NOT NULL, |     "infoJson" JSONB NOT NULL, | ||||||
|  |     "runId" INTEGER NOT NULL, | ||||||
| 
 | 
 | ||||||
|     CONSTRAINT "TrainTrip_pkey" PRIMARY KEY ("id") |     CONSTRAINT "TrainTrip_pkey" PRIMARY KEY ("id") | ||||||
| ); | ); | ||||||
| @@ -82,6 +95,7 @@ CREATE TABLE "MoneyUpdate" ( | |||||||
|     "reason" "MoneyUpdateType" NOT NULL, |     "reason" "MoneyUpdateType" NOT NULL, | ||||||
|     "actionId" INTEGER, |     "actionId" INTEGER, | ||||||
|     "tripId" TEXT, |     "tripId" TEXT, | ||||||
|  |     "runId" INTEGER, | ||||||
|     "timestamp" TIMESTAMPTZ(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, |     "timestamp" TIMESTAMPTZ(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, | ||||||
| 
 | 
 | ||||||
|     CONSTRAINT "MoneyUpdate_pkey" PRIMARY KEY ("id") |     CONSTRAINT "MoneyUpdate_pkey" PRIMARY KEY ("id") | ||||||
| @@ -91,7 +105,7 @@ CREATE TABLE "MoneyUpdate" ( | |||||||
| CREATE UNIQUE INDEX "Player_name_key" ON "Player"("name"); | CREATE UNIQUE INDEX "Player_name_key" ON "Player"("name"); | ||||||
| 
 | 
 | ||||||
| -- CreateIndex | -- CreateIndex | ||||||
| CREATE UNIQUE INDEX "Game_currentRunnerId_key" ON "Game"("currentRunnerId"); | CREATE UNIQUE INDEX "Game_currentRunId_key" ON "Game"("currentRunId"); | ||||||
| 
 | 
 | ||||||
| -- CreateIndex | -- CreateIndex | ||||||
| CREATE UNIQUE INDEX "Challenge_title_key" ON "Challenge"("title"); | CREATE UNIQUE INDEX "Challenge_title_key" ON "Challenge"("title"); | ||||||
| @@ -105,8 +119,17 @@ CREATE UNIQUE INDEX "MoneyUpdate_actionId_key" ON "MoneyUpdate"("actionId"); | |||||||
| -- CreateIndex | -- CreateIndex | ||||||
| CREATE UNIQUE INDEX "MoneyUpdate_tripId_key" ON "MoneyUpdate"("tripId"); | CREATE UNIQUE INDEX "MoneyUpdate_tripId_key" ON "MoneyUpdate"("tripId"); | ||||||
| 
 | 
 | ||||||
|  | -- CreateIndex | ||||||
|  | CREATE UNIQUE INDEX "MoneyUpdate_runId_key" ON "MoneyUpdate"("runId"); | ||||||
|  | 
 | ||||||
| -- AddForeignKey | -- AddForeignKey | ||||||
| ALTER TABLE "Game" ADD CONSTRAINT "Game_currentRunnerId_fkey" FOREIGN KEY ("currentRunnerId") REFERENCES "Player"("id") ON DELETE SET NULL ON UPDATE CASCADE; | ALTER TABLE "Game" ADD CONSTRAINT "Game_currentRunId_fkey" FOREIGN KEY ("currentRunId") REFERENCES "PlayerRun"("id") ON DELETE SET NULL ON UPDATE CASCADE; | ||||||
|  | 
 | ||||||
|  | -- AddForeignKey | ||||||
|  | ALTER TABLE "PlayerRun" ADD CONSTRAINT "PlayerRun_gameId_fkey" FOREIGN KEY ("gameId") REFERENCES "Game"("id") ON DELETE RESTRICT ON UPDATE CASCADE; | ||||||
|  | 
 | ||||||
|  | -- AddForeignKey | ||||||
|  | ALTER TABLE "PlayerRun" ADD CONSTRAINT "PlayerRun_runnerId_fkey" FOREIGN KEY ("runnerId") REFERENCES "Player"("id") ON DELETE RESTRICT ON UPDATE CASCADE; | ||||||
| 
 | 
 | ||||||
| -- AddForeignKey | -- AddForeignKey | ||||||
| ALTER TABLE "Geolocation" ADD CONSTRAINT "Geolocation_playerId_fkey" FOREIGN KEY ("playerId") REFERENCES "Player"("id") ON DELETE RESTRICT ON UPDATE CASCADE; | ALTER TABLE "Geolocation" ADD CONSTRAINT "Geolocation_playerId_fkey" FOREIGN KEY ("playerId") REFERENCES "Player"("id") ON DELETE RESTRICT ON UPDATE CASCADE; | ||||||
| @@ -117,9 +140,15 @@ ALTER TABLE "ChallengeAction" ADD CONSTRAINT "ChallengeAction_playerId_fkey" FOR | |||||||
| -- AddForeignKey | -- AddForeignKey | ||||||
| ALTER TABLE "ChallengeAction" ADD CONSTRAINT "ChallengeAction_challengeId_fkey" FOREIGN KEY ("challengeId") REFERENCES "Challenge"("id") ON DELETE RESTRICT ON UPDATE CASCADE; | ALTER TABLE "ChallengeAction" ADD CONSTRAINT "ChallengeAction_challengeId_fkey" FOREIGN KEY ("challengeId") REFERENCES "Challenge"("id") ON DELETE RESTRICT ON UPDATE CASCADE; | ||||||
| 
 | 
 | ||||||
|  | -- AddForeignKey | ||||||
|  | ALTER TABLE "ChallengeAction" ADD CONSTRAINT "ChallengeAction_runId_fkey" FOREIGN KEY ("runId") REFERENCES "PlayerRun"("id") ON DELETE RESTRICT ON UPDATE CASCADE; | ||||||
|  | 
 | ||||||
| -- AddForeignKey | -- AddForeignKey | ||||||
| ALTER TABLE "TrainTrip" ADD CONSTRAINT "TrainTrip_playerId_fkey" FOREIGN KEY ("playerId") REFERENCES "Player"("id") ON DELETE RESTRICT ON UPDATE CASCADE; | ALTER TABLE "TrainTrip" ADD CONSTRAINT "TrainTrip_playerId_fkey" FOREIGN KEY ("playerId") REFERENCES "Player"("id") ON DELETE RESTRICT ON UPDATE CASCADE; | ||||||
| 
 | 
 | ||||||
|  | -- AddForeignKey | ||||||
|  | ALTER TABLE "TrainTrip" ADD CONSTRAINT "TrainTrip_runId_fkey" FOREIGN KEY ("runId") REFERENCES "PlayerRun"("id") ON DELETE RESTRICT ON UPDATE CASCADE; | ||||||
|  | 
 | ||||||
| -- AddForeignKey | -- AddForeignKey | ||||||
| ALTER TABLE "MoneyUpdate" ADD CONSTRAINT "MoneyUpdate_playerId_fkey" FOREIGN KEY ("playerId") REFERENCES "Player"("id") ON DELETE RESTRICT ON UPDATE CASCADE; | ALTER TABLE "MoneyUpdate" ADD CONSTRAINT "MoneyUpdate_playerId_fkey" FOREIGN KEY ("playerId") REFERENCES "Player"("id") ON DELETE RESTRICT ON UPDATE CASCADE; | ||||||
| 
 | 
 | ||||||
| @@ -128,3 +157,6 @@ ALTER TABLE "MoneyUpdate" ADD CONSTRAINT "MoneyUpdate_actionId_fkey" FOREIGN KEY | |||||||
| 
 | 
 | ||||||
| -- AddForeignKey | -- AddForeignKey | ||||||
| ALTER TABLE "MoneyUpdate" ADD CONSTRAINT "MoneyUpdate_tripId_fkey" FOREIGN KEY ("tripId") REFERENCES "TrainTrip"("id") ON DELETE SET NULL ON UPDATE CASCADE; | ALTER TABLE "MoneyUpdate" ADD CONSTRAINT "MoneyUpdate_tripId_fkey" FOREIGN KEY ("tripId") REFERENCES "TrainTrip"("id") ON DELETE SET NULL ON UPDATE CASCADE; | ||||||
|  | 
 | ||||||
|  | -- AddForeignKey | ||||||
|  | ALTER TABLE "MoneyUpdate" ADD CONSTRAINT "MoneyUpdate_runId_fkey" FOREIGN KEY ("runId") REFERENCES "PlayerRun"("id") ON DELETE SET NULL ON UPDATE CASCADE; | ||||||
| @@ -16,14 +16,29 @@ model Player { | |||||||
|   geolocations  Geolocation[] |   geolocations  Geolocation[] | ||||||
|   moneyUpdates  MoneyUpdate[] |   moneyUpdates  MoneyUpdate[] | ||||||
|   trips         TrainTrip[] |   trips         TrainTrip[] | ||||||
|   runningGame   Game? |   runs          PlayerRun[] | ||||||
| } | } | ||||||
|  |  | ||||||
| model Game { | model Game { | ||||||
|   id              Int         @id @default(autoincrement()) |   id              Int         @id @default(autoincrement()) | ||||||
|   started         Boolean     @default(false) |   started         Boolean     @default(false) | ||||||
|   currentRunner   Player? @relation(fields: [currentRunnerId], references: [id]) |   currentRun      PlayerRun?  @relation("CurrentRun", fields: [currentRunId], references: [id]) | ||||||
|   currentRunnerId Int?    @unique |   currentRunId    Int?        @unique | ||||||
|  |   runs            PlayerRun[] @relation("GameRuns") | ||||||
|  | } | ||||||
|  |  | ||||||
|  | model PlayerRun { | ||||||
|  |   id               Int               @id @default(autoincrement()) | ||||||
|  |   game             Game              @relation("GameRuns", fields: [gameId], references: [id]) | ||||||
|  |   runningGame      Game?             @relation("CurrentRun") | ||||||
|  |   gameId           Int | ||||||
|  |   runner           Player            @relation(fields: [runnerId], references: [id]) | ||||||
|  |   runnerId         Int | ||||||
|  |   start            DateTime          @default(now()) @db.Timestamptz(3) | ||||||
|  |   end              DateTime?         @db.Timestamptz(3) | ||||||
|  |   moneyUpdate      MoneyUpdate? | ||||||
|  |   challengeActions ChallengeAction[] | ||||||
|  |   trains           TrainTrip[] | ||||||
| } | } | ||||||
|  |  | ||||||
| model Geolocation { | model Geolocation { | ||||||
| @@ -59,6 +74,8 @@ model ChallengeAction { | |||||||
|   end          DateTime?    @db.Timestamptz(3) |   end          DateTime?    @db.Timestamptz(3) | ||||||
|   penaltyStart DateTime?    @db.Timestamptz(3) |   penaltyStart DateTime?    @db.Timestamptz(3) | ||||||
|   penaltyEnd   DateTime?    @db.Timestamptz(3) |   penaltyEnd   DateTime?    @db.Timestamptz(3) | ||||||
|  |   run          PlayerRun    @relation(fields: [runId], references: [id]) | ||||||
|  |   runId        Int | ||||||
|   moneyUpdate  MoneyUpdate? |   moneyUpdate  MoneyUpdate? | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -72,6 +89,8 @@ model TrainTrip { | |||||||
|   departureTime DateTime     @db.Timestamptz(3) |   departureTime DateTime     @db.Timestamptz(3) | ||||||
|   arrivalTime   DateTime     @db.Timestamptz(3) |   arrivalTime   DateTime     @db.Timestamptz(3) | ||||||
|   infoJson      Json |   infoJson      Json | ||||||
|  |   run           PlayerRun    @relation(fields: [runId], references: [id]) | ||||||
|  |   runId         Int | ||||||
|   moneyUpdate   MoneyUpdate? |   moneyUpdate   MoneyUpdate? | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -85,11 +104,14 @@ model MoneyUpdate { | |||||||
|   actionId     Int?             @unique |   actionId     Int?             @unique | ||||||
|   trip         TrainTrip?       @relation(fields: [tripId], references: [id]) |   trip         TrainTrip?       @relation(fields: [tripId], references: [id]) | ||||||
|   tripId       String?          @unique |   tripId       String?          @unique | ||||||
|  |   run          PlayerRun?       @relation(fields: [runId], references: [id]) | ||||||
|  |   runId        Int?             @unique | ||||||
|   timestamp    DateTime         @default(now()) @db.Timestamptz(3) |   timestamp    DateTime         @default(now()) @db.Timestamptz(3) | ||||||
| } | } | ||||||
|  |  | ||||||
| enum MoneyUpdateType { | enum MoneyUpdateType { | ||||||
|   START |   START | ||||||
|  |   NEW_RUN | ||||||
|   WIN_CHALLENGE |   WIN_CHALLENGE | ||||||
|   BUY_TRAIN |   BUY_TRAIN | ||||||
| } | } | ||||||
|   | |||||||
| @@ -9,9 +9,10 @@ import { ChallengeActionsModule } from './challenge-actions/challenge-actions.mo | |||||||
| import { TrainsModule } from './trains/trains.module' | import { TrainsModule } from './trains/trains.module' | ||||||
| import { MoneyUpdatesModule } from './money-updates/money-updates.module' | import { MoneyUpdatesModule } from './money-updates/money-updates.module' | ||||||
| import { GameModule } from './game/game.module' | import { GameModule } from './game/game.module' | ||||||
|  | import { RunsModule } from './runs/runs.module' | ||||||
|  |  | ||||||
| @Module({ | @Module({ | ||||||
|   imports: [PrismaModule, AuthModule, PlayersModule, GameModule, GeolocationsModule, ChallengesModule, ChallengeActionsModule, TrainsModule, MoneyUpdatesModule], |   imports: [PrismaModule, AuthModule, PlayersModule, GameModule, RunsModule, GeolocationsModule, ChallengesModule, ChallengeActionsModule, TrainsModule, MoneyUpdatesModule], | ||||||
|   providers: [PrismaService], |   providers: [PrismaService], | ||||||
| }) | }) | ||||||
| export class AppModule {} | export class AppModule {} | ||||||
|   | |||||||
| @@ -12,7 +12,8 @@ export class ChallengeActionsService { | |||||||
|   constructor(private prisma: PrismaService) { } |   constructor(private prisma: PrismaService) { } | ||||||
|  |  | ||||||
|   async create(authenticatedPlayer: Player, createChallengeActionDto: CreateChallengeActionDto): Promise<ChallengeAction> { |   async create(authenticatedPlayer: Player, createChallengeActionDto: CreateChallengeActionDto): Promise<ChallengeAction> { | ||||||
|     const data = { ...createChallengeActionDto, playerId: authenticatedPlayer.id } |     const game = await this.prisma.game.findUnique({ where: { id: 1 } }) | ||||||
|  |     const data = { ...createChallengeActionDto, playerId: authenticatedPlayer.id, runId: game.currentRunId } | ||||||
|     return await this.prisma.challengeAction.create({ |     return await this.prisma.challengeAction.create({ | ||||||
|       data: data, |       data: data, | ||||||
|     }) |     }) | ||||||
| @@ -86,7 +87,7 @@ export class ChallengeActionsService { | |||||||
|         active: false, |         active: false, | ||||||
|         end: now, |         end: now, | ||||||
|         penaltyStart: now, |         penaltyStart: now, | ||||||
|         penaltyEnd: new Date(now.getTime() + 45 * 60 * 1000), |         penaltyEnd: new Date(now.getTime() + 30 * 60 * 1000), | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
|     return await this.prisma.challengeAction.update({ |     return await this.prisma.challengeAction.update({ | ||||||
|   | |||||||
| @@ -7,33 +7,55 @@ export class ChallengeActionEntity implements ChallengeAction { | |||||||
|     Object.assign(this, partial) |     Object.assign(this, partial) | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   @ApiProperty({ description: "Identifiant unique" }) |   /** | ||||||
|  |    * Identifiant unique | ||||||
|  |    */ | ||||||
|   id: number |   id: number | ||||||
|  |  | ||||||
|   @ApiProperty({ description: "Identifiant de læ joueur⋅se effectuant le défi" }) |   /** | ||||||
|  |    * Identifiant de læ joueur⋅se effectuant le défi | ||||||
|  |    */ | ||||||
|   playerId: number |   playerId: number | ||||||
|  |  | ||||||
|   @ApiProperty({ description: "Identifiant du défi rattaché à l'action" }) |   /** | ||||||
|  |    * Identifiant du défi rattaché à l'action | ||||||
|  |    */ | ||||||
|   challengeId: number |   challengeId: number | ||||||
|  |  | ||||||
|   @ApiProperty({ description: "Est-ce que le défi est actuellement en train d'être réalisé" }) |   /** | ||||||
|  |    * Est-ce que le défi est actuellement en train d'être réalisé | ||||||
|  |    */ | ||||||
|   active: boolean |   active: boolean | ||||||
|  |  | ||||||
|   @ApiProperty({ description: "Est-ce que le défi a été réussi" }) |   /** | ||||||
|  |    * Est-ce que le défi a été réussi | ||||||
|  |    */ | ||||||
|   success: boolean |   success: boolean | ||||||
|  |  | ||||||
|   @ApiProperty({ description: "Heure à laquelle le défi a été démarré" }) |   /** | ||||||
|  |    * Heure à laquelle le défi a été démarré | ||||||
|  |    */ | ||||||
|   start: Date |   start: Date | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * Heure à laquelle le défi a été terminé | ||||||
|  |    */ | ||||||
|   @IsOptional() |   @IsOptional() | ||||||
|   @ApiProperty({ description: "Heure à laquelle le défi a été terminé", required: false, nullable: true }) |   end: Date | null = null | ||||||
|   end: Date |  | ||||||
|  |  | ||||||
|   @IsOptional() |   /** | ||||||
|   @ApiProperty({ description: "Heure à laquelle la pénalité a commencé, si applicable", required: false, nullable: true }) |    * Heure à laquelle la pénalité a commencé, si applicable | ||||||
|   penaltyStart: Date |    */ | ||||||
|  |   penaltyStart: Date | null = null | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * Heure à laquelle la pénalité s'est terminée, si applicable | ||||||
|  |    */ | ||||||
|   @IsOptional() |   @IsOptional() | ||||||
|   @ApiProperty({ description: "Heure à laquelle la pénalité s'est terminée, si applicable", required: false, nullable: true }) |   penaltyEnd: Date | null = null | ||||||
|   penaltyEnd: Date |  | ||||||
|  |   /** | ||||||
|  |    * Identifiant de la course pendant laquelle le challenge est réalisé | ||||||
|  |    */ | ||||||
|  |   runId: number | ||||||
| } | } | ||||||
|   | |||||||
| @@ -61,8 +61,8 @@ export class ChallengesService { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   async drawRandom(player: Player): Promise<ChallengeEntity> { |   async drawRandom(player: Player): Promise<ChallengeEntity> { | ||||||
|     const game = await this.prisma.game.findUnique({ where: { id: 1 } }) |     const game = await this.prisma.game.findUnique({ where: { id: 1 }, include: { currentRun: true } }) | ||||||
|     if (game.currentRunnerId != player.id) |     if (game.currentRun?.runnerId !== player.id) | ||||||
|       throw new ConflictException("Vous n'êtes pas en course, ce n'est pas à vous de tirer un défi.") |       throw new ConflictException("Vous n'êtes pas en course, ce n'est pas à vous de tirer un défi.") | ||||||
|     const currentChallengeAction = await this.prisma.challengeAction.findFirst({ |     const currentChallengeAction = await this.prisma.challengeAction.findFirst({ | ||||||
|       where: { |       where: { | ||||||
| @@ -91,6 +91,7 @@ export class ChallengesService { | |||||||
|       data: { |       data: { | ||||||
|         playerId: player.id, |         playerId: player.id, | ||||||
|         challengeId: challenge.id, |         challengeId: challenge.id, | ||||||
|  |         runId: game.currentRunId, | ||||||
|         active: true, |         active: true, | ||||||
|         success: false, |         success: false, | ||||||
|       } |       } | ||||||
|   | |||||||
| @@ -6,12 +6,18 @@ export class GameEntity implements Game { | |||||||
|     Object.assign(this, partial) |     Object.assign(this, partial) | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   @ApiProperty({ description: "Identifiant unique du jeu" }) |   /** | ||||||
|  |    * Identifiant unique du jeu | ||||||
|  |    */ | ||||||
|   id: number |   id: number | ||||||
|  |  | ||||||
|   @ApiProperty({ description: "Est-ce que la partie est en cours" }) |   /** | ||||||
|  |    * Est-ce que la partie est en cours | ||||||
|  |    */ | ||||||
|   started: boolean |   started: boolean | ||||||
|  |  | ||||||
|   @ApiProperty({ description: "Identifiant de læ joueur⋅se en course" }) |   /** | ||||||
|   currentRunnerId: number |    * Identifiant de læ joueur⋅se en course | ||||||
|  |    */ | ||||||
|  |   currentRunId: number | ||||||
| } | } | ||||||
|   | |||||||
| @@ -39,6 +39,7 @@ export class GameController { | |||||||
|    * Change de joueur⋅se en course après une capture |    * Change de joueur⋅se en course après une capture | ||||||
|    *  |    *  | ||||||
|    * @throws {401} Non authentifié⋅e |    * @throws {401} Non authentifié⋅e | ||||||
|  |    * @throws {409} La partie n'est pas démarrée | ||||||
|    */ |    */ | ||||||
|   @Post('/switch-running-player') |   @Post('/switch-running-player') | ||||||
|   @UseGuards(JwtAuthGuard) |   @UseGuards(JwtAuthGuard) | ||||||
|   | |||||||
| @@ -7,8 +7,8 @@ import { RepairGame } from './dto/repair-game.dto' | |||||||
| export class GameService { | export class GameService { | ||||||
|   constructor (private prisma: PrismaService) {} |   constructor (private prisma: PrismaService) {} | ||||||
|  |  | ||||||
|   async find(): Promise<Game> { |   async find() { | ||||||
|     return await this.prisma.game.findUnique({ where: { id: 1 } }) |     return await this.prisma.game.findUnique({ where: { id: 1 }, include: { currentRun: true } }) | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   async start(): Promise<Game> { |   async start(): Promise<Game> { | ||||||
| @@ -16,7 +16,8 @@ export class GameService { | |||||||
|     if (game.started) |     if (game.started) | ||||||
|       throw new ConflictException("La partie a déjà démarré.") |       throw new ConflictException("La partie a déjà démarré.") | ||||||
|     const players = await this.prisma.player.findMany() |     const players = await this.prisma.player.findMany() | ||||||
|     const alreadyStarted = game.currentRunnerId !== null |     const alreadyStarted = game.currentRunId !== null | ||||||
|  |     let run | ||||||
|     if (!alreadyStarted) { |     if (!alreadyStarted) { | ||||||
|       for (const player of players) { |       for (const player of players) { | ||||||
|         await this.prisma.moneyUpdate.create({ |         await this.prisma.moneyUpdate.create({ | ||||||
| @@ -27,30 +28,74 @@ export class GameService { | |||||||
|           } |           } | ||||||
|         }) |         }) | ||||||
|       } |       } | ||||||
|  |       const runnerId = players[Math.floor(players.length * Math.random())].id | ||||||
|  |       run = await this.prisma.playerRun.create({ | ||||||
|  |         data: { | ||||||
|  |           gameId: game.id, | ||||||
|  |           runnerId: runnerId, | ||||||
|  |         } | ||||||
|  |       }) | ||||||
|  |     } | ||||||
|  |     else { | ||||||
|  |       run = await this.prisma.playerRun.update({ | ||||||
|  |         where: { id: game.currentRunId }, | ||||||
|  |         data: { end: null }, | ||||||
|  |       }) | ||||||
|     } |     } | ||||||
|     const runnerId = alreadyStarted ? game.currentRunnerId : players[Math.floor(players.length * Math.random())].id |  | ||||||
|     return await this.prisma.game.update({ |     return await this.prisma.game.update({ | ||||||
|       where: { id: 1 }, |       where: { id: 1 }, | ||||||
|       data: { |       data: { | ||||||
|         started: true, |         started: true, | ||||||
|         currentRunnerId: runnerId, |         currentRunId: run.id, | ||||||
|       }, |       }, | ||||||
|     }) |     }) | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   async switchRunningPlayer(): Promise<Game> { |   async switchRunningPlayer(): Promise<Game> { | ||||||
|     const game = await this.find() |     const game = await this.find() | ||||||
|     const newRunnerId = game.currentRunnerId == 1 ? 2 : 1 |     if (!game.started) | ||||||
|  |       throw new ConflictException("La partie n'a pas encore démarré.") | ||||||
|  |  | ||||||
|  |     // Clôture de l'éventuel défi en cours, qui n'a alors pas été réussi | ||||||
|  |     await this.prisma.challengeAction.updateMany({ | ||||||
|  |       where: { | ||||||
|  |         playerId: game.currentRun.runnerId, | ||||||
|  |         runId: game.currentRunId, | ||||||
|  |         active: true, | ||||||
|  |       }, | ||||||
|  |       data: { | ||||||
|  |         active: false, | ||||||
|  |         success: false, | ||||||
|  |       }, | ||||||
|  |     }) | ||||||
|  |  | ||||||
|  |     await this.prisma.playerRun.update({ | ||||||
|  |       where: { id: game.currentRunId }, | ||||||
|  |       data: { end: new Date() }, | ||||||
|  |     }) | ||||||
|  |  | ||||||
|  |     const newRunnerId = game.currentRun.runnerId == 1 ? 2 : 1 | ||||||
|  |     const firstRun = await this.prisma.playerRun.findFirst({ where: { runnerId: newRunnerId } }) !== null | ||||||
|  |     const newRun = await this.prisma.playerRun.create({ | ||||||
|  |       data: { | ||||||
|  |         gameId: game.id, | ||||||
|  |         runnerId: newRunnerId, | ||||||
|  |       } | ||||||
|  |     }) | ||||||
|  |     if (!firstRun) { | ||||||
|  |       // Si c'est une nouvelle course (pas la première), on accorde un bonus de points de départ | ||||||
|       await this.prisma.moneyUpdate.create({ |       await this.prisma.moneyUpdate.create({ | ||||||
|         data: { |         data: { | ||||||
|           playerId: newRunnerId, |           playerId: newRunnerId, | ||||||
|           amount: 300, |           amount: 300, | ||||||
|         reason: MoneyUpdateType.START, |           reason: MoneyUpdateType.NEW_RUN, | ||||||
|  |           runId: newRun.id, | ||||||
|         } |         } | ||||||
|       }) |       }) | ||||||
|  |     } | ||||||
|     return await this.prisma.game.update({ |     return await this.prisma.game.update({ | ||||||
|       where: { id: game.id }, |       where: { id: game.id }, | ||||||
|       data: { currentRunnerId: newRunnerId }, |       data: { currentRunId: newRun.id }, | ||||||
|     }) |     }) | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @@ -58,27 +103,30 @@ export class GameService { | |||||||
|     const game = await this.find() |     const game = await this.find() | ||||||
|     if (!game.started) |     if (!game.started) | ||||||
|       throw new ConflictException("La partie n'a pas encore démarré.") |       throw new ConflictException("La partie n'a pas encore démarré.") | ||||||
|  |     await this.prisma.playerRun.update({ | ||||||
|  |       where: { id: game.currentRunId }, | ||||||
|  |       data: { end: new Date() }, | ||||||
|  |     }) | ||||||
|     return await this.prisma.game.update({ |     return await this.prisma.game.update({ | ||||||
|       where: { id: 1 }, |       where: { id: 1 }, | ||||||
|       data: { |       data: { started: false }, | ||||||
|         started: false, |  | ||||||
|       }, |  | ||||||
|     }) |     }) | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   async reset(): Promise<Game> { |   async reset(): Promise<Game> { | ||||||
|     await this.prisma.moneyUpdate.deleteMany() |  | ||||||
|     await this.prisma.challengeAction.deleteMany() |  | ||||||
|     await this.prisma.trainTrip.deleteMany() |  | ||||||
|     await this.prisma.geolocation.deleteMany() |  | ||||||
|     await this.prisma.player.updateMany({ data: { money: 0 } }) |  | ||||||
|     await this.prisma.game.update({ |     await this.prisma.game.update({ | ||||||
|       where: { id: 1 }, |       where: { id: 1 }, | ||||||
|       data: { |       data: { | ||||||
|         started: false, |         started: false, | ||||||
|         currentRunnerId: null, |         currentRunId: null, | ||||||
|       }, |       }, | ||||||
|     }) |     }) | ||||||
|  |     await this.prisma.player.updateMany({ data: { money: 0 } }) | ||||||
|  |     await this.prisma.moneyUpdate.deleteMany() | ||||||
|  |     await this.prisma.challengeAction.deleteMany() | ||||||
|  |     await this.prisma.trainTrip.deleteMany() | ||||||
|  |     await this.prisma.playerRun.deleteMany() | ||||||
|  |     await this.prisma.geolocation.deleteMany() | ||||||
|     return await this.find() |     return await this.find() | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -42,6 +42,20 @@ export class GeolocationsController { | |||||||
|     return paginateOutput<GeolocationEntity>(geolocations.map(geolocation => new GeolocationEntity(geolocation)), total, queryPagination) |     return paginateOutput<GeolocationEntity>(geolocations.map(geolocation => new GeolocationEntity(geolocation)), total, queryPagination) | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * Récupération des dernières posititons de tout le monde | ||||||
|  |    *  | ||||||
|  |    * @throws {401} Non authentifié⋅e | ||||||
|  |    * @throws {404} Aucune localisation envoyée | ||||||
|  |    */ | ||||||
|  |   @Get('/last-locations') | ||||||
|  |   @UseGuards(JwtAuthGuard) | ||||||
|  |   @ApiBearerAuth() | ||||||
|  |   async findLastLocations(): Promise<GeolocationEntity[]> { | ||||||
|  |     const lastGeolocations = await this.geolocationsService.findLastLocations() | ||||||
|  |     return lastGeolocations.map(geolocation => new GeolocationEntity(geolocation)) | ||||||
|  |   } | ||||||
|  |  | ||||||
|   /** |   /** | ||||||
|    * Recherche d'une géolocalisation par identifiant |    * Recherche d'une géolocalisation par identifiant | ||||||
|    *  |    *  | ||||||
| @@ -58,22 +72,6 @@ export class GeolocationsController { | |||||||
|     return new GeolocationEntity(geolocation) |     return new GeolocationEntity(geolocation) | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   /** |  | ||||||
|    * Récupération de la dernière posititon |  | ||||||
|    *  |  | ||||||
|    * @throws {401} Non authentifié⋅e |  | ||||||
|    * @throws {404} Aucune localisation envoyée |  | ||||||
|    */ |  | ||||||
|   @Get('/last-location/:playerId') |  | ||||||
|   @UseGuards(JwtAuthGuard) |  | ||||||
|   @ApiBearerAuth() |  | ||||||
|   async findLastLocation(@Param('playerId', ParseIntPipe) playerId: number): Promise<GeolocationEntity> { |  | ||||||
|     const geolocation = await this.geolocationsService.findLastLocation(playerId) |  | ||||||
|     if (!geolocation) |  | ||||||
|       throw new NotFoundException(`Géolocalisation inexistante pour læ joueur⋅se ${playerId}`) |  | ||||||
|     return new GeolocationEntity(geolocation) |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   /** |   /** | ||||||
|    * Suppression d'une localisation |    * Suppression d'une localisation | ||||||
|    *  |    *  | ||||||
|   | |||||||
| @@ -33,14 +33,20 @@ export class GeolocationsService { | |||||||
|     return await this.prisma.geolocation.findUnique({ where: { id } }) |     return await this.prisma.geolocation.findUnique({ where: { id } }) | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   async findLastLocation(playerId: number): Promise<Geolocation> { |   async findLastLocations(): Promise<Geolocation[]> { | ||||||
|     return await this.prisma.geolocation.findFirst({ |     const players = await this.prisma.player.findMany() | ||||||
|       where: { playerId: playerId }, |     const lastGeolocations = [] | ||||||
|       orderBy: { timestamp: Prisma.SortOrder.desc }, |     for (const player of players) { | ||||||
|       take: 1 |       const lastGeolocationPlayer = await this.prisma.geolocation.findFirst({ | ||||||
|  |         where: { playerId: player.id }, | ||||||
|  |         orderBy: { timestamp: 'desc' }, | ||||||
|  |         take: 1, | ||||||
|       }) |       }) | ||||||
|  |       if (lastGeolocationPlayer) | ||||||
|  |         lastGeolocations.push(lastGeolocationPlayer) | ||||||
|  |     } | ||||||
|  |     return lastGeolocations | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |  | ||||||
|   async remove(id: number): Promise<Geolocation> { |   async remove(id: number): Promise<Geolocation> { | ||||||
|     if (!this.findOne(id)) |     if (!this.findOne(id)) | ||||||
|   | |||||||
| @@ -1,29 +1,49 @@ | |||||||
| import { ApiProperty } from "@nestjs/swagger" | import { ApiProperty } from "@nestjs/swagger" | ||||||
| import { MoneyUpdate, MoneyUpdateType } from "@prisma/client" | import { MoneyUpdate, MoneyUpdateType } from "@prisma/client" | ||||||
|  | import { IsOptional } from "class-validator" | ||||||
|  |  | ||||||
| export class MoneyUpdateEntity implements MoneyUpdate { | export class MoneyUpdateEntity implements MoneyUpdate { | ||||||
|   constructor (partial: Partial<MoneyUpdateEntity>) { |   constructor (partial: Partial<MoneyUpdateEntity>) { | ||||||
|     Object.assign(this, partial) |     Object.assign(this, partial) | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   @ApiProperty({ description: "Identifiant unique de la mise à jour de solde" }) |   /** | ||||||
|  |    * Identifiant unique de la mise à jour de solde | ||||||
|  |    */ | ||||||
|   id: number |   id: number | ||||||
|  |  | ||||||
|   @ApiProperty({ description: "Joueur⋅se concerné⋅e par la mise à jour de solde" }) |   /** | ||||||
|  |    * Joueur⋅se concerné⋅e par la mise à jour de solde | ||||||
|  |    */ | ||||||
|   playerId: number |   playerId: number | ||||||
|  |  | ||||||
|   @ApiProperty({ description: "Montant de la modification du solde" }) |   /** | ||||||
|  |    * Montant de la modification du solde | ||||||
|  |    */ | ||||||
|   amount: number |   amount: number | ||||||
|  |  | ||||||
|   @ApiProperty({ description: "Type de modification de solde" }) |   /** | ||||||
|  |    * Type de modification de solde | ||||||
|  |    */ | ||||||
|   reason: MoneyUpdateType |   reason: MoneyUpdateType | ||||||
|  |  | ||||||
|   @ApiProperty({ description: "Identifiant de la réalisation de défi, si la mise à jour est liée à un défi", nullable: true }) |   /** | ||||||
|   actionId: number |    * Identifiant de la réalisation de défi, si la mise à jour est liée à un défi | ||||||
|  |    */ | ||||||
|  |   actionId: number | null = null | ||||||
|  |  | ||||||
|   @ApiProperty({ description: "Identifiant du trajet acheté, si la mise à jour est liée à la réservation d'un train", nullable: true }) |   /** | ||||||
|   tripId: string |    * Identifiant du trajet acheté, si la mise à jour est liée à la réservation d'un train | ||||||
|  |    */ | ||||||
|  |   tripId: string | null = null | ||||||
|  |  | ||||||
|   @ApiProperty({ description: "Date et heure de la modification de solde" }) |   /** | ||||||
|  |    * Idenifiant de la course rattachée, si la mise à jour est liée à une nouvelle tentative de course | ||||||
|  |    */ | ||||||
|  |   runId: number | null = null | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * Date et heure de la modification de solde | ||||||
|  |    */ | ||||||
|   timestamp: Date |   timestamp: Date | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										32
									
								
								server/src/runs/entities/run.entity.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								server/src/runs/entities/run.entity.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,32 @@ | |||||||
|  | import { PlayerRun } from "@prisma/client" | ||||||
|  |  | ||||||
|  | export class RunEntity implements PlayerRun { | ||||||
|  |   constructor(partial: Partial<RunEntity>) { | ||||||
|  |     Object.assign(this, partial) | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * Identifiant unique de la tentative | ||||||
|  |    */ | ||||||
|  |   id: number | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * Identifant de l'objet de la partie | ||||||
|  |    */ | ||||||
|  |   gameId: number | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * Identifiant de læ joueur⋅se actuellement en course | ||||||
|  |    */ | ||||||
|  |   runnerId: number | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * Date et heure de début de course | ||||||
|  |    */ | ||||||
|  |   start: Date | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * Date et heure de fin de course | ||||||
|  |    */ | ||||||
|  |   end: Date | null | ||||||
|  | } | ||||||
							
								
								
									
										20
									
								
								server/src/runs/runs.controller.spec.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								server/src/runs/runs.controller.spec.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,20 @@ | |||||||
|  | import { Test, TestingModule } from '@nestjs/testing' | ||||||
|  | import { RunsController } from './runs.controller' | ||||||
|  | import { RunsService } from './runs.service' | ||||||
|  |  | ||||||
|  | describe('RunsController', () => { | ||||||
|  |   let controller: RunsController | ||||||
|  |  | ||||||
|  |   beforeEach(async () => { | ||||||
|  |     const module: TestingModule = await Test.createTestingModule({ | ||||||
|  |       controllers: [RunsController], | ||||||
|  |       providers: [RunsService], | ||||||
|  |     }).compile() | ||||||
|  |  | ||||||
|  |     controller = module.get<RunsController>(RunsController) | ||||||
|  |   }) | ||||||
|  |  | ||||||
|  |   it('should be defined', () => { | ||||||
|  |     expect(controller).toBeDefined() | ||||||
|  |   }) | ||||||
|  | }) | ||||||
							
								
								
									
										40
									
								
								server/src/runs/runs.controller.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								server/src/runs/runs.controller.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,40 @@ | |||||||
|  | import { Controller, Get, Param, Query, UseGuards } from '@nestjs/common' | ||||||
|  | import { RunsService } from './runs.service' | ||||||
|  | import { RunEntity } from './entities/run.entity' | ||||||
|  | import { PaginateOutputDto } from 'src/common/dto/pagination-output.dto' | ||||||
|  | import { QueryPaginationDto } from 'src/common/dto/pagination-query.dto' | ||||||
|  | import { JwtAuthGuard } from 'src/auth/jwt-auth.guard' | ||||||
|  | import { ApiBearerAuth } from '@nestjs/swagger' | ||||||
|  | import { ApiOkResponsePaginated, paginateOutput } from 'src/common/utils/pagination.utils' | ||||||
|  |  | ||||||
|  | @Controller('runs') | ||||||
|  | export class RunsController { | ||||||
|  |   constructor(private readonly runsService: RunsService) {} | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * Recherche de tentatives de course | ||||||
|  |    *  | ||||||
|  |    * @throws {401} Non authentifié⋅e | ||||||
|  |    */ | ||||||
|  |   @Get() | ||||||
|  |   @UseGuards(JwtAuthGuard) | ||||||
|  |   @ApiBearerAuth() | ||||||
|  |   @ApiOkResponsePaginated(RunEntity) | ||||||
|  |   async findAll(@Query() queryPagination: QueryPaginationDto): Promise<PaginateOutputDto<RunEntity>> { | ||||||
|  |     const [runs, total] = await this.runsService.findAll(queryPagination) | ||||||
|  |     return paginateOutput<RunEntity>(runs.map(challenge => new RunEntity(challenge)), total, queryPagination) | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * Recherche d'une tentative de course par identifiant | ||||||
|  |    *  | ||||||
|  |    * @throws {401} Non authentifié⋅e | ||||||
|  |    * @throws {404} Essai non trouvé | ||||||
|  |    */ | ||||||
|  |   @Get(':id') | ||||||
|  |   @UseGuards(JwtAuthGuard) | ||||||
|  |   @ApiBearerAuth() | ||||||
|  |   async findOne(@Param('id') id: number): Promise<RunEntity> { | ||||||
|  |     return new RunEntity(await this.runsService.findOne(id)) | ||||||
|  |   } | ||||||
|  | } | ||||||
							
								
								
									
										11
									
								
								server/src/runs/runs.module.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								server/src/runs/runs.module.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,11 @@ | |||||||
|  | import { Module } from '@nestjs/common' | ||||||
|  | import { RunsService } from './runs.service' | ||||||
|  | import { RunsController } from './runs.controller' | ||||||
|  | import { PrismaModule } from 'src/prisma/prisma.module' | ||||||
|  |  | ||||||
|  | @Module({ | ||||||
|  |   controllers: [RunsController], | ||||||
|  |   providers: [RunsService], | ||||||
|  |   imports: [PrismaModule], | ||||||
|  | }) | ||||||
|  | export class RunsModule {} | ||||||
							
								
								
									
										18
									
								
								server/src/runs/runs.service.spec.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								server/src/runs/runs.service.spec.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,18 @@ | |||||||
|  | import { Test, TestingModule } from '@nestjs/testing' | ||||||
|  | import { RunsService } from './runs.service' | ||||||
|  |  | ||||||
|  | describe('RunsService', () => { | ||||||
|  |   let service: RunsService | ||||||
|  |  | ||||||
|  |   beforeEach(async () => { | ||||||
|  |     const module: TestingModule = await Test.createTestingModule({ | ||||||
|  |       providers: [RunsService], | ||||||
|  |     }).compile() | ||||||
|  |  | ||||||
|  |     service = module.get<RunsService>(RunsService) | ||||||
|  |   }) | ||||||
|  |  | ||||||
|  |   it('should be defined', () => { | ||||||
|  |     expect(service).toBeDefined() | ||||||
|  |   }) | ||||||
|  | }) | ||||||
							
								
								
									
										21
									
								
								server/src/runs/runs.service.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								server/src/runs/runs.service.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | |||||||
|  | import { Injectable } from '@nestjs/common' | ||||||
|  | import { PlayerRun } from '@prisma/client' | ||||||
|  | import { QueryPaginationDto } from 'src/common/dto/pagination-query.dto' | ||||||
|  | import { paginate } from 'src/common/utils/pagination.utils' | ||||||
|  | import { PrismaService } from 'src/prisma/prisma.service' | ||||||
|  |  | ||||||
|  | @Injectable() | ||||||
|  | export class RunsService { | ||||||
|  |   constructor(private prisma: PrismaService) {} | ||||||
|  |  | ||||||
|  |   async findAll(queryPagination: QueryPaginationDto): Promise<[PlayerRun[], number]> { | ||||||
|  |     return [ | ||||||
|  |       await this.prisma.playerRun.findMany({ ...paginate(queryPagination) }), | ||||||
|  |       await this.prisma.playerRun.count(), | ||||||
|  |     ] | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   async findOne(id: number): Promise<PlayerRun> { | ||||||
|  |     return await this.prisma.playerRun.findUnique({ where: { id } }) | ||||||
|  |   } | ||||||
|  | } | ||||||
| @@ -7,27 +7,48 @@ export class TrainEntity implements TrainTrip { | |||||||
|     Object.assign(this, partial) |     Object.assign(this, partial) | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   @ApiProperty({ description: "Identifiant du train, donné par l'identifiant de partage Interrail" }) |   /** | ||||||
|  |    * Identifiant du train, donné par l'identifiant de partage Interrail | ||||||
|  |    */ | ||||||
|   id: string |   id: string | ||||||
|  |  | ||||||
|   @ApiProperty({ description: "Identifiant de læ joueur⋅se effectuant le trajet" }) |   /** | ||||||
|  |    * Identifiant de læ joueur⋅se effectuant le trajet | ||||||
|  |    */ | ||||||
|   playerId: number |   playerId: number | ||||||
|  |  | ||||||
|   @ApiProperty({ description: "Distance estimée en mètres du trajet" }) |   /** | ||||||
|  |    * Distance estimée en mètres du trajet | ||||||
|  |    */  | ||||||
|   distance: number |   distance: number | ||||||
|  |  | ||||||
|   @ApiProperty({ description: "Nom de la gare de départ" }) |   /** | ||||||
|  |    * Nom de la gare de départ | ||||||
|  |    */ | ||||||
|   from: string |   from: string | ||||||
|  |  | ||||||
|   @ApiProperty({ description: "Nom de la gare d'arrivée" }) |   /** | ||||||
|  |    * Nom de la gare d'arrivée | ||||||
|  |    */ | ||||||
|   to: string |   to: string | ||||||
|  |  | ||||||
|   @ApiProperty({ description: "Date et heure de départ du train" }) |   /** | ||||||
|  |    * Date et heure de départ du train | ||||||
|  |    */ | ||||||
|   departureTime: Date |   departureTime: Date | ||||||
|  |  | ||||||
|   @ApiProperty({ description: "Date et heure d'arrivée du train" }) |   /** | ||||||
|  |    * Date et heure d'arrivée du train" | ||||||
|  |    */ | ||||||
|   arrivalTime: Date |   arrivalTime: Date | ||||||
|  |  | ||||||
|   @ApiProperty({ description: "Informations JSON supplémentaires transmises par Interrail" }) |   /** | ||||||
|  |    * Informations JSON supplémentaires transmises par Interrail | ||||||
|  |    */ | ||||||
|   infoJson: JsonValue |   infoJson: JsonValue | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * Identifiant de la course pendant laquelle ce train a été emprunté | ||||||
|  |    */ | ||||||
|  |   runId: number | ||||||
| } | } | ||||||
|   | |||||||
| @@ -15,7 +15,9 @@ export class TrainsService { | |||||||
|   constructor(private prisma: PrismaService) { } |   constructor(private prisma: PrismaService) { } | ||||||
|  |  | ||||||
|   async create(createTrainDto: CreateTrainDto): Promise<TrainTrip> { |   async create(createTrainDto: CreateTrainDto): Promise<TrainTrip> { | ||||||
|     return await this.prisma.trainTrip.create({ data: createTrainDto }) |     const game = await this.prisma.game.findUnique({ where: { id: 1 } }) | ||||||
|  |     const data = { ...createTrainDto, runId: game.currentRunId } | ||||||
|  |     return await this.prisma.trainTrip.create({ data: data }) | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   async findAll(queryPagination: QueryPaginationDto, playerFilter: PlayerFilterDto): Promise<[TrainTrip[], number]> { |   async findAll(queryPagination: QueryPaginationDto, playerFilter: PlayerFilterDto): Promise<[TrainTrip[], number]> { | ||||||
| @@ -54,6 +56,8 @@ export class TrainsService { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   async import(player: Player, { id: trainId }: ImportTrainDto): Promise<TrainTrip> { |   async import(player: Player, { id: trainId }: ImportTrainDto): Promise<TrainTrip> { | ||||||
|  |     const game = await this.prisma.game.findUnique({ where: { id: 1 } }) | ||||||
|  |  | ||||||
|     if (this.findOne(trainId)) |     if (this.findOne(trainId)) | ||||||
|       throw new ConflictException(`Le train avec l'identifiant ${trainId} est déjà importé`) |       throw new ConflictException(`Le train avec l'identifiant ${trainId} est déjà importé`) | ||||||
|  |  | ||||||
| @@ -95,6 +99,7 @@ export class TrainsService { | |||||||
|         departureTime: departure, |         departureTime: departure, | ||||||
|         arrivalTime: arrival, |         arrivalTime: arrival, | ||||||
|         infoJson: leg.infoJson, |         infoJson: leg.infoJson, | ||||||
|  |         runId: game.currentRunId, | ||||||
|       }, |       }, | ||||||
|     }) |     }) | ||||||
|     // Ajout du trajet en points |     // Ajout du trajet en points | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user