From ba87e0b2b25725564c273830d3d1a384e9c5ebe8 Mon Sep 17 00:00:00 2001 From: mario Date: Wed, 4 Dec 2024 11:13:47 +0900 Subject: [PATCH 1/5] =?UTF-8?q?fix:=20=ED=98=B8=EC=8A=A4=ED=8A=B8=EC=9D=98?= =?UTF-8?q?=20=EB=8C=80=EA=B8=B0=EC=8B=A4=20=ED=87=B4=EC=9E=A5=20=EC=B2=98?= =?UTF-8?q?=EB=A6=AC=20=EA=B4=80=EB=A0=A8=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/backend/src/play/play.gateway.ts | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/apps/backend/src/play/play.gateway.ts b/apps/backend/src/play/play.gateway.ts index d83309b3e..5cf7a7c39 100644 --- a/apps/backend/src/play/play.gateway.ts +++ b/apps/backend/src/play/play.gateway.ts @@ -15,11 +15,10 @@ import { SendEventMessage } from './entities/send-event.entity'; import { ClientInfo } from './entities/client-info.entity'; import { WebSocketWithSession } from '../core/SessionWsAdapter'; import { RuntimeException } from '@nestjs/core/errors/exceptions'; -import { CLOSE_CODE } from '../common/constants'; import { SubmitResponseDto } from './dto/submit-response.dto'; -import { clearTimeout } from 'node:timers'; import { ChatMessage } from 'src/chat/entities/chat-message.entity'; -import { ChatService } from '../chat/chat.service'; // 경로 수정 +import { ChatService } from '../chat/chat.service'; +import { CLOSE_CODE } from '../common/constants'; // 경로 수정 /** * 퀴즈 게임에 대한 WebSocket 연결을 관리하는 Gateway입니다. @@ -248,7 +247,7 @@ export class PlayGateway implements OnGatewayInit { const clientsIds = summaries.map(({ id }) => id); - this.clearQuizZone(clientsIds, quizZoneId, endSocketTime); + this.clearQuizZone(clientsIds, quizZoneId, endSocketTime - Date.now()); } /** @@ -258,16 +257,16 @@ export class PlayGateway implements OnGatewayInit { * - 일반 플레이어가 나가면 퀴즈 존에서 나가고 다른 플레이어에게 나갔다고 알립니다. * @param clientIds - 퀴즈존에 참여하고 있는 클라이언트 id 리스트 * @param quizZoneId - 퀴즈가 끝난 퀴즈존 id - * @param endSocketTime - 소켓 연결 종료 시간 종료 시간 + * @param time - 소켓 연결 종료 시간 종료 시간 */ - private clearQuizZone(clientIds: string[], quizZoneId: string, endSocketTime: number) { + private clearQuizZone(clientIds: string[], quizZoneId: string, time: number) { setTimeout(() => { clientIds.forEach((id) => { this.clearClient(id, 'finish'); }); this.playService.clearQuizZone(quizZoneId); this.chatService.delete(quizZoneId); - }, endSocketTime - Date.now()); + }, time); } /** @@ -286,7 +285,7 @@ export class PlayGateway implements OnGatewayInit { if (isHost) { this.broadcast(playerIds, 'close'); - playerIds.forEach((id) => this.clearClient(id, 'Host leave.')); + this.clearQuizZone(playerIds, quizZoneId, 0); } else { this.broadcast(playerIds, 'someone_leave', clientId); this.clearClient(clientId, 'Client leave'); From ffb313d61a6f00186f29db9cbd283f545fe43ca0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=84=ED=98=84=EB=AF=BC?= <77275989+joyjhm@users.noreply.github.com> Date: Wed, 4 Dec 2024 15:35:11 +0900 Subject: [PATCH 2/5] =?UTF-8?q?fix:=20=EA=B2=B0=EA=B3=BC=20=ED=8E=98?= =?UTF-8?q?=EC=9D=B4=EC=A7=80=EC=97=90=EC=84=9C=20=EC=83=88=EB=A1=9C?= =?UTF-8?q?=EA=B3=A0=EC=B9=A8=ED=95=B4=EB=8F=84=20=ED=8E=98=EC=9D=B4?= =?UTF-8?q?=EC=A7=80=20=EB=B3=B4=EC=9D=B4=EB=8F=84=EB=A1=9D=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/backend/src/play/entities/quiz-summary.entity.ts | 6 ++++++ apps/backend/src/play/entities/rank.entity.ts | 6 ++++++ apps/backend/src/play/play.service.ts | 6 +++++- apps/backend/src/quiz-zone/dto/find-quiz-zone.dto.ts | 8 ++++++++ .../src/quiz-zone/entities/quiz-zone.entity.ts | 2 ++ apps/backend/src/quiz-zone/quiz-zone.service.ts | 10 +++++++--- apps/frontend/src/hook/quizZone/useQuizZone.tsx | 11 ++--------- 7 files changed, 36 insertions(+), 13 deletions(-) create mode 100644 apps/backend/src/play/entities/quiz-summary.entity.ts create mode 100644 apps/backend/src/play/entities/rank.entity.ts diff --git a/apps/backend/src/play/entities/quiz-summary.entity.ts b/apps/backend/src/play/entities/quiz-summary.entity.ts new file mode 100644 index 000000000..1edc0de4d --- /dev/null +++ b/apps/backend/src/play/entities/quiz-summary.entity.ts @@ -0,0 +1,6 @@ +import { Rank } from './rank.entity'; + +export interface QuizSummary { + readonly ranks: Rank[]; + readonly endSocketTime?: number; +} \ No newline at end of file diff --git a/apps/backend/src/play/entities/rank.entity.ts b/apps/backend/src/play/entities/rank.entity.ts new file mode 100644 index 000000000..7854840df --- /dev/null +++ b/apps/backend/src/play/entities/rank.entity.ts @@ -0,0 +1,6 @@ +export interface Rank { + readonly id: string; + readonly nickname: string; + readonly score: number; + readonly ranking: number; +} \ No newline at end of file diff --git a/apps/backend/src/play/play.service.ts b/apps/backend/src/play/play.service.ts index 2badf6b3a..fd033c338 100644 --- a/apps/backend/src/play/play.service.ts +++ b/apps/backend/src/play/play.service.ts @@ -304,7 +304,8 @@ export class PlayService { const now = Date.now(); const endSocketTime = now + socketConnectTime; - return [...players.values()].map(({ id, score, submits }) => ({ + + const summaries = [...players.values()].map(({ id, score, submits }) => ({ id, score, submits, @@ -312,6 +313,9 @@ export class PlayService { ranks, endSocketTime })); + + quizZone.summaries = {ranks, endSocketTime}; + return summaries; } public clearQuizZone(quizZoneId: string) { diff --git a/apps/backend/src/quiz-zone/dto/find-quiz-zone.dto.ts b/apps/backend/src/quiz-zone/dto/find-quiz-zone.dto.ts index c5f708f85..37e3b3da1 100644 --- a/apps/backend/src/quiz-zone/dto/find-quiz-zone.dto.ts +++ b/apps/backend/src/quiz-zone/dto/find-quiz-zone.dto.ts @@ -2,6 +2,8 @@ import { PLAYER_STATE, QUIZ_ZONE_STAGE } from '../../common/constants'; import { CurrentQuizDto } from '../../play/dto/current-quiz.dto'; import { SubmittedQuiz } from '../entities/submitted-quiz.entity'; import { ChatMessage } from 'src/chat/entities/chat-message.entity'; +import { Rank } from '../../play/entities/rank.entity'; +import { Quiz } from '../entities/quiz.entity'; /** * 퀴즈 게임에 참여하는 플레이어 엔티티 @@ -42,4 +44,10 @@ export interface FindQuizZoneDto { readonly currentQuiz?: CurrentQuizDto; readonly maxPlayers?: number; readonly chatMessages?: ChatMessage[]; + + readonly ranks?: Rank[]; + readonly endSocketTime?: number; + readonly score?: number; + readonly quizzes?: Quiz[]; + readonly submits?: SubmittedQuiz[]; } diff --git a/apps/backend/src/quiz-zone/entities/quiz-zone.entity.ts b/apps/backend/src/quiz-zone/entities/quiz-zone.entity.ts index 59c762e5e..4e6bbbffc 100644 --- a/apps/backend/src/quiz-zone/entities/quiz-zone.entity.ts +++ b/apps/backend/src/quiz-zone/entities/quiz-zone.entity.ts @@ -1,6 +1,7 @@ import { Quiz } from './quiz.entity'; import { Player } from './player.entity'; import { QUIZ_ZONE_STAGE } from '../../common/constants'; +import { QuizSummary } from '../../play/entities/quiz-summary.entity'; /** * 퀴즈 게임을 진행하는 공간을 나타내는 퀴즈존 인터페이스 * @@ -28,4 +29,5 @@ export interface QuizZone { currentQuizStartTime: number; currentQuizDeadlineTime: number; intervalTime: number; + summaries?: QuizSummary; } diff --git a/apps/backend/src/quiz-zone/quiz-zone.service.ts b/apps/backend/src/quiz-zone/quiz-zone.service.ts index 135b6914f..d2aeda3e2 100644 --- a/apps/backend/src/quiz-zone/quiz-zone.service.ts +++ b/apps/backend/src/quiz-zone/quiz-zone.service.ts @@ -172,7 +172,7 @@ export class QuizZoneService { } private async getResultInfo(clientId: string, quizZoneId: string): Promise { - const { players, stage, title, description, hostId, quizzes, maxPlayers } = + const { players, stage, title, description, hostId, quizzes, summaries } = await this.findOne(quizZoneId); const { id, nickname, state, submits, score } = players.get(clientId); const chatMessages = await this.chatService.get(quizZoneId); @@ -181,11 +181,15 @@ export class QuizZoneService { currentPlayer: { id, nickname, state, score, submits }, title, description, - maxPlayers: maxPlayers, quizCount: quizzes.length, stage: stage, hostId, - chatMessages: chatMessages, + chatMessages, + ranks: summaries.ranks, + endSocketTime: summaries.endSocketTime, + quizzes, + score, + submits }; } diff --git a/apps/frontend/src/hook/quizZone/useQuizZone.tsx b/apps/frontend/src/hook/quizZone/useQuizZone.tsx index 3a18a2a34..a475197e9 100644 --- a/apps/frontend/src/hook/quizZone/useQuizZone.tsx +++ b/apps/frontend/src/hook/quizZone/useQuizZone.tsx @@ -39,15 +39,10 @@ const quizZoneReducer: Reducer = (state, action) => { switch (type) { case 'init': + console.log(payload); return { ...state, - stage: payload.stage, - title: payload.title, - description: payload.description, - quizCount: payload.quizCount, - hostId: payload.hostId, - currentPlayer: payload.currentPlayer, - chatMessages: payload.chatMessages, + ...payload, currentQuiz: payload.currentQuiz !== undefined ? { @@ -55,8 +50,6 @@ const quizZoneReducer: Reducer = (state, action) => { question: atob(payload.currentQuiz?.question ?? ''), } : undefined, - maxPlayers: payload.maxPlayers, - players: [], }; case 'join': return { ...state, players: payload }; From fd98cf112222687a02b8aa4a27af180336dfce18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=84=ED=98=84=EB=AF=BC?= <77275989+joyjhm@users.noreply.github.com> Date: Wed, 4 Dec 2024 17:31:41 +0900 Subject: [PATCH 3/5] =?UTF-8?q?test:=20result=20=EB=B0=98=ED=99=98?= =?UTF-8?q?=EA=B0=92=20=EB=B3=80=EA=B2=BD=EC=97=90=20=EB=94=B0=EB=A5=B8=20?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=BD=94=EB=93=9C=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/quiz-zone/quiz-zone.service.spec.ts | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/apps/backend/src/quiz-zone/quiz-zone.service.spec.ts b/apps/backend/src/quiz-zone/quiz-zone.service.spec.ts index a2e8b9281..847367989 100644 --- a/apps/backend/src/quiz-zone/quiz-zone.service.spec.ts +++ b/apps/backend/src/quiz-zone/quiz-zone.service.spec.ts @@ -6,7 +6,6 @@ import { IQuizZoneRepository } from './repository/quiz-zone.repository.interface import { Quiz } from './entities/quiz.entity'; import { PLAYER_STATE, QUIZ_TYPE, QUIZ_ZONE_STAGE } from '../common/constants'; import { QuizService } from '../quiz/quiz.service'; -import { max } from 'class-validator'; import { ChatService } from '../chat/chat.service'; const nickNames: string[] = [ @@ -571,6 +570,13 @@ describe('QuizZoneService', () => { currentQuizStartTime: Date.now(), currentQuizDeadlineTime: Date.now() + playTime, intervalTime: 5000, + summaries: { + ranks: [ + {id: "player1", nickname: "미친투사", score: 0, ranking: 1}, + {id: "player2", nickname: "미친투사", score: 0, ranking: 1} + ], + endSocketTime: Date.now(), + } }; mockQuizZoneRepository.get.mockResolvedValue(mockQuizZone); @@ -579,7 +585,7 @@ describe('QuizZoneService', () => { const result = await service.getQuizZoneInfo(clientId, quizZoneId); // then - expect(result).toEqual({ + expect(result).toMatchObject({ currentPlayer: { id: clientId, nickname: '닉네임', @@ -591,8 +597,12 @@ describe('QuizZoneService', () => { description: '테스트 퀴즈입니다', quizCount: quizzes.length, stage: QUIZ_ZONE_STAGE.RESULT, - maxPlayers: 10, hostId: 'adminId', + ranks: [ + {id: "player1", nickname: "미친투사", score: 0, ranking: 1}, + {id: "player2", nickname: "미친투사", score: 0, ranking: 1} + ], + endSocketTime: Date.now(), }); }); From 8b42ef4c3b3bcc9139002a9ad5dd1682e2157b7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=84=A0=EB=B9=88?= Date: Wed, 4 Dec 2024 19:45:11 +0900 Subject: [PATCH 4/5] =?UTF-8?q?fix:=20=ED=80=B4=EC=A6=88=EC=A1=B4=20?= =?UTF-8?q?=EC=84=A4=EB=AA=85=20=EC=B5=9C=EB=8C=80=20=EA=B8=B8=EC=9D=B4?= =?UTF-8?q?=EB=A5=BC=20500=EC=9E=90=EC=97=90=EC=84=9C=20300=EC=9E=90?= =?UTF-8?q?=EB=A1=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/blocks/CreateQuizZone/CreateQuizZoneBasic.tsx | 4 ++-- apps/frontend/src/components/common/Input.tsx | 2 +- apps/frontend/src/hook/quizZone/useQuizZone.tsx | 1 - apps/frontend/src/utils/validators.ts | 2 +- 4 files changed, 4 insertions(+), 5 deletions(-) diff --git a/apps/frontend/src/blocks/CreateQuizZone/CreateQuizZoneBasic.tsx b/apps/frontend/src/blocks/CreateQuizZone/CreateQuizZoneBasic.tsx index b433f259d..8df873058 100644 --- a/apps/frontend/src/blocks/CreateQuizZone/CreateQuizZoneBasic.tsx +++ b/apps/frontend/src/blocks/CreateQuizZone/CreateQuizZoneBasic.tsx @@ -129,9 +129,9 @@ const CreateQuizZoneBasic = ({ onChange={(e) => handleChangeQuizZoneBasic(e, 'DESC')} isBorder={true} placeholder="퀴즈존 설명을 입력하세요" - error={validationError == '500자 이하로 입력해주세요.' ? validationError : ''} + error={validationError == '300자 이하로 입력해주세요.' ? validationError : ''} isShowCount={true} - max={500} + max={300} /> diff --git a/apps/frontend/src/components/common/Input.tsx b/apps/frontend/src/components/common/Input.tsx index a9e0e137e..7c96b645d 100644 --- a/apps/frontend/src/components/common/Input.tsx +++ b/apps/frontend/src/components/common/Input.tsx @@ -148,7 +148,7 @@ const Input = forwardRef( )} {typeof value === 'string' && isShowCount && ( -
+
= (state, action) => { switch (type) { case 'init': - console.log(payload); return { ...state, ...payload, diff --git a/apps/frontend/src/utils/validators.ts b/apps/frontend/src/utils/validators.ts index fd7e4724f..8397f4c72 100644 --- a/apps/frontend/src/utils/validators.ts +++ b/apps/frontend/src/utils/validators.ts @@ -32,7 +32,7 @@ export const validateQuizZoneSetName = (name: string) => { //퀴즈존 설명 유효성 검사 export const validateQuizZoneSetDescription = (description: string) => { - if (description.length > 500) return '500자 이하로 입력해주세요.'; + if (description.length > 300) return '300자 이하로 입력해주세요.'; }; //퀴즈존 입장 코드 유효성 검사 From d338537e89730b133e4ab668915be694b0236898 Mon Sep 17 00:00:00 2001 From: mario Date: Thu, 5 Dec 2024 10:41:12 +0900 Subject: [PATCH 5/5] =?UTF-8?q?fix:=20quizZoneReducer=20=EC=83=81=ED=83=9C?= =?UTF-8?q?=20=EC=97=85=EB=8D=B0=EC=9D=B4=ED=8A=B8=20=EC=BD=94=EB=93=9C=20?= =?UTF-8?q?=EC=A0=95=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/frontend/src/hook/quizZone/useQuizZone.tsx | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/apps/frontend/src/hook/quizZone/useQuizZone.tsx b/apps/frontend/src/hook/quizZone/useQuizZone.tsx index d15f14429..530bc1be0 100644 --- a/apps/frontend/src/hook/quizZone/useQuizZone.tsx +++ b/apps/frontend/src/hook/quizZone/useQuizZone.tsx @@ -76,13 +76,11 @@ const quizZoneReducer: Reducer = (state, action) => { ...state.currentPlayer, state: 'SUBMIT', }, - chatMessages: payload.chatMessages, currentQuizResult: { + ...payload, fastestPlayers: payload.fastestPlayerIds .map((id) => state.players?.find((p) => p.id === id)) .filter((p) => !!p), - submittedCount: payload.submittedCount, - totalPlayerCount: payload.totalPlayerCount, }, }; case 'someone_submit': @@ -110,11 +108,8 @@ const quizZoneReducer: Reducer = (state, action) => { }, currentQuiz: { ...state.currentQuiz, + ...nextQuiz, question: atob(nextQuiz.question), - currentIndex: nextQuiz.currentIndex, - playTime: nextQuiz.playTime, - startTime: nextQuiz.startTime, - deadlineTime: nextQuiz.deadlineTime, quizType: 'SHORT', }, currentQuizResult: { @@ -149,12 +144,8 @@ const quizZoneReducer: Reducer = (state, action) => { case 'summary': return { ...state, + ...payload, stage: 'RESULT', - score: payload.score, - submits: payload.submits, - quizzes: payload.quizzes, - ranks: payload.ranks, - endSocketTime: payload.endSocketTime, }; case 'chat': return {