xiongzhu %!s(int64=2) %!d(string=hai) anos
pai
achega
12bc08c015

+ 7 - 1
src/danmu/danmu.service.ts

@@ -190,10 +190,16 @@ export class DanmuService implements OnModuleInit {
         return res[index]
     }
 
-    async findDanmuUser(danmuUserId: number) {
+    async findDanmuUser(danmuUserId: number, updateAvatar: boolean = false) {
         const danmuUser = await this.danmuUserRepository.findOneBy({
             id: danmuUserId
         })
+        if (!danmuUser) {
+            return null
+        }
+        if (!updateAvatar) {
+            return danmuUser
+        }
         const {
             data: {
                 data: [user]

+ 23 - 0
src/game/entities/survival.entity.ts

@@ -0,0 +1,23 @@
+import { Column, Entity, PrimaryGeneratedColumn, Unique } from 'typeorm'
+
+@Entity()
+@Unique(['roomId', 'danmuUserId'])
+export class Survival {
+    constructor(survival: Partial<Survival>) {
+        Object.assign(this, survival)
+    }
+
+    @PrimaryGeneratedColumn()
+    id: number
+
+    @Column()
+    roomId: number
+
+    @Column()
+    danmuUserId: number
+
+    @Column({ default: 0 })
+    survival: number
+
+    userInfo: any
+}

+ 2 - 1
src/game/game.module.ts

@@ -10,10 +10,11 @@ import { PromptModule } from '../prompt/prompt.module'
 import { SysConfigModule } from 'src/sys-config/sys-config.module'
 import { DanmuModule } from 'src/danmu/danmu.module'
 import { RoomModule } from 'src/room/room.module'
+import { Survival } from './entities/survival.entity'
 
 @Module({
     imports: [
-        TypeOrmModule.forFeature([Game, GameState, Charactor]),
+        TypeOrmModule.forFeature([Game, GameState, Charactor, Survival]),
         forwardRef(() => EventsModule),
         PromptModule,
         SysConfigModule,

+ 68 - 13
src/game/game.service.ts

@@ -45,6 +45,7 @@ import { RoomService } from 'src/room/room.service'
 import { InitGame } from './dto/init-game.dto'
 import { PlotOption } from './models/plot-option.model'
 import { VoteCallback } from './types'
+import { Survival } from './entities/survival.entity'
 
 @Injectable()
 export class GameService implements OnModuleInit {
@@ -66,6 +67,8 @@ export class GameService implements OnModuleInit {
         private readonly gameStateRepository: Repository<GameState>,
         @InjectRepository(Charactor)
         private readonly charactorRepository: Repository<Charactor>,
+        @InjectRepository(Survival)
+        private readonly survivalRepository: Repository<Survival>,
         @Inject(forwardRef(() => EventsGateway))
         private readonly eventsGateway: EventsGateway,
         private readonly promptService: PromptService,
@@ -332,12 +335,14 @@ export class GameService implements OnModuleInit {
         })
 
         gameState.charactors = [...game.charactors].map((i) => {
-            i.hp = 100
-            i.joinAt = initGame.date
-            i.survival = 0
-            i.dead = false
-
-            return i
+            return {
+                ...i,
+                gameId: id,
+                roomId: game.roomId,
+                hp: 100,
+                joinAt: initGame.date,
+                dead: false
+            }
         })
 
         if (initGame.plot) {
@@ -420,8 +425,11 @@ export class GameService implements OnModuleInit {
             } else {
                 newCharactor = new Charactor({
                     ...newCharactor,
+                    gameId: id,
+                    roomId: game.roomId,
                     hp: 100,
-                    joinAt: date
+                    joinAt: date,
+                    dead: false
                 })
                 this.send(`${id}`, {
                     type: 'newCharactor',
@@ -469,6 +477,8 @@ export class GameService implements OnModuleInit {
             charactorsAlive.push(newCharactor)
         }
 
+        await this.addSurvival(charactorsAlive)
+
         const willEnd = charactorsAlive.filter((i) => !i.dead).length === 0
 
         if (!willEnd && createOptions) {
@@ -783,12 +793,14 @@ export class GameService implements OnModuleInit {
             try {
                 const addCharactor = danmu.content.replace(/^我是/, '')
                 const danmuUser = await this.danmuService.findDanmuUser(danmu.danmuUserId)
-                const charactor = await this.createNewCharactor(id, addCharactor)
-                this.logger.log(`已创建角色: ${JSON.stringify(charactor)}`)
-                charactor.name = danmuUser.name
-                charactor.avatar = danmuUser.avatar
-                charactor.danmuUserId = danmu.danmuUserId
-                return charactor
+                if (danmuUser) {
+                    const charactor = await this.createNewCharactor(id, addCharactor)
+                    this.logger.log(`已创建角色: ${JSON.stringify(charactor)}`)
+                    charactor.name = danmuUser.name
+                    charactor.avatar = danmuUser.avatar
+                    charactor.danmuUserId = danmu.danmuUserId
+                    return charactor
+                }
             } catch (error) {
                 this.logger.error(error)
             }
@@ -959,4 +971,47 @@ export class GameService implements OnModuleInit {
         }
         return death
     }
+
+    async addSurvival(charactors: Charactor[]) {
+        for (const c of charactors) {
+            if (c.danmuUserId) {
+                const damuUser = await this.danmuService.findDanmuUser(c.danmuUserId)
+                if (damuUser) {
+                    let s = await this.survivalRepository.findOneBy({
+                        roomId: c.roomId,
+                        danmuUserId: c.danmuUserId
+                    })
+                    if (!s) {
+                        s = new Survival({
+                            roomId: c.roomId,
+                            danmuUserId: c.danmuUserId,
+                            survival: 0
+                        })
+                    }
+                    s.survival++
+                    await this.survivalRepository.save(s)
+                }
+            }
+        }
+    }
+
+    async survivalRank(roomId: number) {
+        const rank = await this.survivalRepository.find({
+            where: {
+                roomId
+            },
+            order: {
+                survival: 'DESC'
+            },
+            take: 10
+        })
+
+        for (const r of rank) {
+            const danmuUser = await this.danmuService.findDanmuUser(r.danmuUserId)
+            if (danmuUser) {
+                r.userInfo = danmuUser
+            }
+        }
+        return rank
+    }
 }

+ 8 - 10
src/game/models/charactor.model.ts

@@ -1,32 +1,30 @@
 export class Charactor {
     id?: number
+    
+    roomId: number
 
-    gameId?: number
+    gameId: number
 
-    avatar?: string
+    avatar: string
 
-    name?: string
+    name: string
 
-    age?: string
+    age: string
 
-    gender?: string
+    gender: string
 
-    occupation?: string
+    occupation: string
 
     personality?: string
 
     background?: string
 
-    episode?: string
-
     properties?: any
 
     hp?: number
 
     joinAt?: Date
 
-    survival?: number
-
     dead?: boolean
 
     deadAt?: Date

+ 6 - 0
src/room/room.controller.ts

@@ -42,4 +42,10 @@ export class RoomController {
     public async stop(@Param('id') id: string) {
         return await this.roomService.stopRoom(Number(id))
     }
+
+    @Get('/:id/survivalRank')
+    @Public()
+    public async survivalRank(@Param('id') id: string) {
+        return await this.roomService.survivalRank(Number(id))
+    }
 }

+ 3 - 2
src/room/room.module.ts

@@ -3,10 +3,11 @@ import { RoomController } from './room.controller'
 import { RoomService } from './room.service'
 import { TypeOrmModule } from '@nestjs/typeorm'
 import { Room } from './entities/room.entity'
-import { DanmuModule } from 'src/danmu/danmu.module'
+import { DanmuModule } from '../danmu/danmu.module'
+import { GameModule } from '../game/game.module'
 
 @Module({
-    imports: [TypeOrmModule.forFeature([Room]), forwardRef(() => DanmuModule)],
+    imports: [TypeOrmModule.forFeature([Room]), forwardRef(() => DanmuModule), forwardRef(() => GameModule)],
     controllers: [RoomController],
     providers: [RoomService],
     exports: [RoomService]

+ 9 - 2
src/room/room.service.ts

@@ -4,7 +4,8 @@ import { Room } from './entities/room.entity'
 import { Pagination, paginate } from 'nestjs-typeorm-paginate'
 import { InjectRepository } from '@nestjs/typeorm'
 import { Repository } from 'typeorm'
-import { DanmuService } from 'src/danmu/danmu.service'
+import { DanmuService } from '../danmu/danmu.service'
+import { GameService } from '../game/game.service'
 
 @Injectable()
 export class RoomService {
@@ -12,7 +13,9 @@ export class RoomService {
         @InjectRepository(Room)
         private readonly roomRepository: Repository<Room>,
         @Inject(forwardRef(() => DanmuService))
-        private readonly danmuService: DanmuService
+        private readonly danmuService: DanmuService,
+        @Inject(forwardRef(() => GameService))
+        private readonly gameService: GameService
     ) {}
 
     async findAllRooms(req: PageRequest<Room>): Promise<Pagination<Room>> {
@@ -58,4 +61,8 @@ export class RoomService {
         const room = await this.roomRepository.findOne({ where: { id } })
         await this.danmuService.stopDanmu(room)
     }
+
+    async survivalRank(roomId: number) {
+        return await this.gameService.survivalRank(roomId)
+    }
 }