import { Injectable, Inject, forwardRef } from '@nestjs/common'; import { PrismaService } from '../prisma/prisma.service'; import { customAlphabet } from 'nanoid'; import { RoomEventsService } from '../game/room-events.service'; const nanoid = customAlphabet('ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789', 6); @Injectable() export class RoomsService { constructor( private prisma: PrismaService, @Inject(forwardRef(() => RoomEventsService)) private roomEventsService: RoomEventsService, ) {} async createRoom(hostId: string, questionPackId?: string, settings?: any) { const code = nanoid(); const expiresAt = new Date(Date.now() + 24 * 60 * 60 * 1000); // 24 hours // Remove undefined values from settings and ensure questionPackId is handled correctly const cleanSettings = settings ? { ...settings } : {}; if ('questionPackId' in cleanSettings) { delete cleanSettings.questionPackId; } const room = await this.prisma.room.create({ data: { code, hostId, expiresAt, ...cleanSettings, questionPackId: questionPackId || null, }, include: { host: true, questionPack: true, }, }); await this.prisma.participant.create({ data: { userId: hostId, roomId: room.id, name: room.host.name || 'Host', role: 'HOST', }, }); return room; } async getRoomByCode(code: string) { return this.prisma.room.findUnique({ where: { code }, include: { host: true, participants: { include: { user: true }, }, questionPack: true, }, }); } async joinRoom(roomId: string, userId: string, name: string, role: 'PLAYER' | 'SPECTATOR') { const participant = await this.prisma.participant.create({ data: { userId, roomId, name, role, }, }); // Получаем обновленную комнату со всеми участниками const room = await this.prisma.room.findUnique({ where: { id: roomId }, include: { host: true, participants: { include: { user: true }, }, questionPack: true, }, }); // Отправляем событие roomUpdate всем клиентам в комнате if (room) { this.roomEventsService.emitRoomUpdate(room.code, room); } return participant; } async updateRoomStatus(roomId: string, status: 'WAITING' | 'PLAYING' | 'FINISHED') { return this.prisma.room.update({ where: { id: roomId }, data: { status }, }); } async updateParticipantScore(participantId: string, score: number) { return this.prisma.participant.update({ where: { id: participantId }, data: { score }, }); } async updateQuestionPack(roomId: string, questionPackId: string) { return this.prisma.room.update({ where: { id: roomId }, data: { questionPackId, currentQuestionIndex: 0, revealedAnswers: {}, }, include: { host: true, participants: { include: { user: true }, }, questionPack: true, }, }); } async updateCustomQuestions(roomId: string, questions: any) { const room = await this.prisma.room.update({ where: { id: roomId }, data: { customQuestions: questions, currentQuestionIndex: 0, revealedAnswers: {}, }, include: { host: true, participants: { include: { user: true }, }, questionPack: true, }, }); this.roomEventsService.emitCustomQuestionsUpdated(room.code, room); return room; } async getEffectiveQuestions(roomId: string) { const room = await this.prisma.room.findUnique({ where: { id: roomId }, include: { questionPack: true }, }); if (!room) { return null; } // Если есть кастомные вопросы, используем их if (room.customQuestions) { return room.customQuestions; } // Иначе используем вопросы из пака if (room.questionPack) { return room.questionPack.questions; } return null; } async updateRoomSettings(roomId: string, settings: any) { const room = await this.prisma.room.update({ where: { id: roomId }, data: settings, include: { host: true, participants: { include: { user: true }, }, questionPack: true, }, }); this.roomEventsService.emitRoomUpdate(room.code, room); return room; } async restartGame(roomId: string) { await this.prisma.room.update({ where: { id: roomId }, data: { status: 'WAITING', currentQuestionIndex: 0, revealedAnswers: {}, currentPlayerId: null, isGameOver: false, answeredQuestions: 0, }, }); await this.prisma.participant.updateMany({ where: { roomId }, data: { score: 0 }, }); const room = await this.prisma.room.findUnique({ where: { id: roomId }, include: { host: true, participants: { include: { user: true }, }, questionPack: true, }, }); if (room) { this.roomEventsService.emitGameRestarted(room.code, room); } return room; } async setCurrentPlayer(roomId: string, playerId: string) { const room = await this.prisma.room.update({ where: { id: roomId }, data: { currentPlayerId: playerId }, include: { host: true, participants: { include: { user: true }, }, questionPack: true, }, }); this.roomEventsService.emitCurrentPlayerChanged(room.code, { playerId }); return room; } async kickPlayer(roomId: string, participantId: string) { await this.prisma.participant.update({ where: { id: participantId }, data: { isActive: false }, }); const room = await this.prisma.room.findUnique({ where: { id: roomId }, include: { host: true, participants: { include: { user: true }, }, questionPack: true, }, }); if (room) { this.roomEventsService.emitPlayerKicked(room.code, { participantId, room }); } return room; } }