sto-k-odnomu/backend/src/rooms/rooms.service.ts

265 lines
6.3 KiB
TypeScript
Raw Normal View History

2026-01-07 14:23:06 +00:00
import { Injectable, Inject, forwardRef } from '@nestjs/common';
2026-01-03 14:07:04 +00:00
import { PrismaService } from '../prisma/prisma.service';
import { customAlphabet } from 'nanoid';
2026-01-07 14:32:51 +00:00
import { RoomEventsService } from '../game/room-events.service';
2026-01-03 14:07:04 +00:00
const nanoid = customAlphabet('ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789', 6);
@Injectable()
export class RoomsService {
2026-01-07 14:23:06 +00:00
constructor(
private prisma: PrismaService,
2026-01-07 14:32:51 +00:00
@Inject(forwardRef(() => RoomEventsService))
private roomEventsService: RoomEventsService,
2026-01-07 14:23:06 +00:00
) {}
2026-01-03 14:07:04 +00:00
2026-01-06 20:12:36 +00:00
async createRoom(hostId: string, questionPackId?: string, settings?: any) {
2026-01-03 14:07:04 +00:00
const code = nanoid();
const expiresAt = new Date(Date.now() + 24 * 60 * 60 * 1000); // 24 hours
2026-01-06 20:33:44 +00:00
// Remove undefined values from settings and ensure questionPackId is handled correctly
const cleanSettings = settings ? { ...settings } : {};
if ('questionPackId' in cleanSettings) {
delete cleanSettings.questionPackId;
}
2026-01-03 14:07:04 +00:00
const room = await this.prisma.room.create({
data: {
code,
hostId,
expiresAt,
2026-01-06 20:33:44 +00:00
...cleanSettings,
questionPackId: questionPackId || null,
2026-01-03 14:07:04 +00:00
},
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') {
2026-01-07 14:23:06 +00:00
const participant = await this.prisma.participant.create({
2026-01-03 14:07:04 +00:00
data: {
userId,
roomId,
name,
role,
},
});
2026-01-07 14:23:06 +00:00
// Получаем обновленную комнату со всеми участниками
const room = await this.prisma.room.findUnique({
where: { id: roomId },
include: {
host: true,
participants: {
include: { user: true },
},
questionPack: true,
},
});
// Отправляем событие roomUpdate всем клиентам в комнате
2026-01-07 14:32:51 +00:00
if (room) {
this.roomEventsService.emitRoomUpdate(room.code, room);
2026-01-07 14:23:06 +00:00
}
return participant;
2026-01-03 14:07:04 +00:00
}
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 },
});
}
2026-01-06 20:12:36 +00:00
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,
},
});
}
2026-01-08 13:18:07 +00:00
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;
}
2026-01-03 14:07:04 +00:00
}