sto-k-odnomu/backend/src/rooms/rooms.service.ts
2026-01-08 16:18:07 +03:00

264 lines
6.3 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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;
}
}