From 824950a1809a853824bc8e920ff02b10af4150ef Mon Sep 17 00:00:00 2001 From: JunWoo Park <97427744+always97@users.noreply.github.com> Date: Wed, 4 Dec 2024 23:40:19 +0900 Subject: [PATCH 1/6] =?UTF-8?q?fix:=20=EB=8C=80=EA=B8=B0=EB=B0=A9=20?= =?UTF-8?q?=EC=83=88=EB=A1=9C=EA=B3=A0=EC=B9=A8=20=EA=B8=B0=EB=8A=A5=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- FE/src/features/lobby/GameLobbyPage.tsx | 12 +++++++++++- FE/src/features/lobby/LobbyList.tsx | 6 +++--- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/FE/src/features/lobby/GameLobbyPage.tsx b/FE/src/features/lobby/GameLobbyPage.tsx index 1889aa1..f939e0c 100644 --- a/FE/src/features/lobby/GameLobbyPage.tsx +++ b/FE/src/features/lobby/GameLobbyPage.tsx @@ -46,6 +46,16 @@ export const GameLobbyPage = () => { }, [isLoading, paging] ); + const refreshRooms = useCallback(() => { + if (isLoading) return; + setRooms([]); + setPaging(null); + loadRooms(null); + }, [isLoading, loadRooms]); + + useEffect(() => { + loadRooms(null); + }, [loadRooms]); useEffect(() => { loadRooms(null); @@ -70,7 +80,7 @@ export const GameLobbyPage = () => { return (
- + {isLoading &&
Loading...
}
); diff --git a/FE/src/features/lobby/LobbyList.tsx b/FE/src/features/lobby/LobbyList.tsx index d6a6f18..a0e3259 100644 --- a/FE/src/features/lobby/LobbyList.tsx +++ b/FE/src/features/lobby/LobbyList.tsx @@ -11,11 +11,11 @@ type Room = { type LobbyListProps = { rooms: Room[]; - loadRooms: (cursor: string | null, take: number) => Promise; + refreshRooms: () => void; }; import { useNavigate } from 'react-router-dom'; -export const LobbyList: React.FC = ({ rooms, loadRooms }) => { +export const LobbyList: React.FC = ({ rooms, refreshRooms }) => { const navigate = useNavigate(); const handleJoinRoom = (gameId: string) => { @@ -35,7 +35,7 @@ export const LobbyList: React.FC = ({ rooms, loadRooms }) => { width: '50px', height: '50px' }} - onClick={() => loadRooms(null, 10)} + onClick={() => refreshRooms} />
From e1bd9df9fe68c4364b32ae69d8ad34cbe7b5e19d Mon Sep 17 00:00:00 2001 From: JunWoo Park <97427744+always97@users.noreply.github.com> Date: Wed, 4 Dec 2024 23:50:57 +0900 Subject: [PATCH 2/6] =?UTF-8?q?fix:=20=EC=83=88=EB=A1=9C=EA=B3=A0=EC=B9=A8?= =?UTF-8?q?=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- FE/src/features/lobby/LobbyList.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/FE/src/features/lobby/LobbyList.tsx b/FE/src/features/lobby/LobbyList.tsx index a0e3259..1a8b2cc 100644 --- a/FE/src/features/lobby/LobbyList.tsx +++ b/FE/src/features/lobby/LobbyList.tsx @@ -35,7 +35,7 @@ export const LobbyList: React.FC = ({ rooms, refreshRooms }) => width: '50px', height: '50px' }} - onClick={() => refreshRooms} + onClick={refreshRooms} />
From 69e97cba30acd05490bf5edd2d1f770406b5ebd2 Mon Sep 17 00:00:00 2001 From: ijun17 Date: Wed, 4 Dec 2024 00:14:11 +0900 Subject: [PATCH 3/6] =?UTF-8?q?feat:=20=EB=A6=AC=EB=93=9C=EB=AF=B8?= =?UTF-8?q?=EC=9A=A9=20=EC=86=8C=EC=BC=93=20=EB=AA=A9=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...ForReadme.ts => SocketMockForReadme200.ts} | 22 ++++- .../socketMocks/SocketMockForReadmeRanking.ts | 97 +++++++++++++++++++ .../SocketMockForReadmeSurvival.ts | 97 +++++++++++++++++++ FE/src/api/socket/mocks/socketMocks/index.ts | 8 +- 4 files changed, 217 insertions(+), 7 deletions(-) rename FE/src/api/socket/mocks/socketMocks/{SocketMockForReadme.ts => SocketMockForReadme200.ts} (75%) create mode 100644 FE/src/api/socket/mocks/socketMocks/SocketMockForReadmeRanking.ts create mode 100644 FE/src/api/socket/mocks/socketMocks/SocketMockForReadmeSurvival.ts diff --git a/FE/src/api/socket/mocks/socketMocks/SocketMockForReadme.ts b/FE/src/api/socket/mocks/socketMocks/SocketMockForReadme200.ts similarity index 75% rename from FE/src/api/socket/mocks/socketMocks/SocketMockForReadme.ts rename to FE/src/api/socket/mocks/socketMocks/SocketMockForReadme200.ts index 3c562e2..7e88454 100644 --- a/FE/src/api/socket/mocks/socketMocks/SocketMockForReadme.ts +++ b/FE/src/api/socket/mocks/socketMocks/SocketMockForReadme200.ts @@ -24,7 +24,7 @@ const chatMessages = [ '고마워!' ]; -export default class SocketMockForReadme extends SocketMock { +export default class SocketMockForReadme200 extends SocketMock { constructor() { super(); this.test(); @@ -37,7 +37,7 @@ export default class SocketMockForReadme extends SocketMock { await this.initialrized; const playerCount = Object.keys(this.players).length; this.addPlayers( - Array(77) + Array(200) .fill(null) .map((_, i) => ({ playerId: String(playerCount + i + 1), @@ -59,9 +59,21 @@ export default class SocketMockForReadme extends SocketMock { this.emitServer('startGame', {}); //퀴즈 전송 - await this.progressQuiz('1+1=?', 5, ['1', '2', '3'], 1); + await this.progressQuiz( + '우리 팀의 이름은?', + 5, + ['시크릿주주', '시크릿추추', '시크릿쥬쥬', '시크릿츄츄'], + 0 + ); + await this.delay(3); + await this.progressQuiz( + '이 서비스의 이름은?', + 5, + ['퀴즈 그라운드', '배틀 그라운드', '큐플레이', '카훗'], + 0 + ); await this.delay(3); - await this.progressQuiz('2+2=?', 5, ['1', '2', '4'], 2); + await this.progressQuiz('네이버 부스트캠프는 국내 최고의 부트캠트다', 5, ['O', 'X'], 0); // 퀴즈 종료 await this.delay(5); @@ -74,7 +86,7 @@ export default class SocketMockForReadme extends SocketMock { for (let j = 0; j < 20; j++) { for (const player of this.getPlayerList()) { if (player.playerId === this.id) continue; - await this.delay(1 / playerCount / 0.01); + await this.delay(1 / playerCount / 0.05); this.chatMessage( player.playerId, chatMessages[Math.floor(Math.random() * chatMessages.length)] diff --git a/FE/src/api/socket/mocks/socketMocks/SocketMockForReadmeRanking.ts b/FE/src/api/socket/mocks/socketMocks/SocketMockForReadmeRanking.ts new file mode 100644 index 0000000..4269d96 --- /dev/null +++ b/FE/src/api/socket/mocks/socketMocks/SocketMockForReadmeRanking.ts @@ -0,0 +1,97 @@ +import { getRandomNickname } from '@/features/game/utils/nickname'; +import { SocketMock } from '../SocketMock'; + +const chatMessages = [ + '안녕하세요?', + '이 문제 뭐지?', + '점심 먹었어?', + '뭐 하고 있어?', + '오늘 날씨 좋다!', + '잠깐 시간 돼?', + '여기 봐봐!', + '도움이 필요해.', + '언제 만날까?', + '진짜야?', + '좋은 하루 보내!', + '이거 어때?', + '잘 모르겠어.', + '대박!', + '좀 더 설명해줘.', + '같이 할래?', + '괜찮아?', + '나중에 이야기하자.', + '너무 웃겨!', + '고마워!' +]; + +export default class SocketMockForReadmeRanking extends SocketMock { + constructor() { + super(); + this.test(); + + this.moveRandom(15, 0.5); + this.testChat(); + } + + async test() { + await this.initialrized; + const playerCount = Object.keys(this.players).length; + this.addPlayers( + Array(35) + .fill(null) + .map((_, i) => ({ + playerId: String(playerCount + i + 1), + playerName: getRandomNickname(), + playerPosition: [this.random(), this.random()], + isHost: false + })) + ); + + this.emitServer('updateRoomOption', { + title: '즐거운 퀴즈 시간~~', + gameMode: 'RANKING', + maxPlayerCount: 200, + isPublic: true + }); + + //2초후 게임 시작 + await this.delay(2); + this.emitServer('startGame', {}); + + //퀴즈 전송 + await this.progressQuiz( + '우리 팀의 이름은?', + 5, + ['시크릿주주', '시크릿추추', '시크릿쥬쥬', '시크릿츄츄'], + 0 + ); + await this.delay(3); + await this.progressQuiz( + '이 서비스의 이름은?', + 5, + ['퀴즈 그라운드', '배틀 그라운드', '큐플레이', '카훗'], + 0 + ); + await this.delay(3); + await this.progressQuiz('네이버 부스트캠프는 국내 최고의 부트캠트다', 5, ['O', 'X'], 0); + + // 퀴즈 종료 + await this.delay(5); + this.emitServer('endGame', { hostId: this.id }); + } + + async testChat() { + await this.initialrized; + const playerCount = this.getPlayerList().length; + for (let j = 0; j < 20; j++) { + for (const player of this.getPlayerList()) { + if (player.playerId === this.id) continue; + await this.delay(1 / playerCount / 0.1); + this.chatMessage( + player.playerId, + chatMessages[Math.floor(Math.random() * chatMessages.length)] + ); + } + } + } +} diff --git a/FE/src/api/socket/mocks/socketMocks/SocketMockForReadmeSurvival.ts b/FE/src/api/socket/mocks/socketMocks/SocketMockForReadmeSurvival.ts new file mode 100644 index 0000000..0b56b09 --- /dev/null +++ b/FE/src/api/socket/mocks/socketMocks/SocketMockForReadmeSurvival.ts @@ -0,0 +1,97 @@ +import { getRandomNickname } from '@/features/game/utils/nickname'; +import { SocketMock } from '../SocketMock'; + +const chatMessages = [ + '안녕하세요?', + '이 문제 뭐지?', + '점심 먹었어?', + '뭐 하고 있어?', + '오늘 날씨 좋다!', + '잠깐 시간 돼?', + '여기 봐봐!', + '도움이 필요해.', + '언제 만날까?', + '진짜야?', + '좋은 하루 보내!', + '이거 어때?', + '잘 모르겠어.', + '대박!', + '좀 더 설명해줘.', + '같이 할래?', + '괜찮아?', + '나중에 이야기하자.', + '너무 웃겨!', + '고마워!' +]; + +export default class SocketMockForReadmeSurvival extends SocketMock { + constructor() { + super(); + this.test(); + + this.moveRandom(15, 0.5); + this.testChat(); + } + + async test() { + await this.initialrized; + const playerCount = Object.keys(this.players).length; + this.addPlayers( + Array(35) + .fill(null) + .map((_, i) => ({ + playerId: String(playerCount + i + 1), + playerName: getRandomNickname(), + playerPosition: [this.random(), this.random()], + isHost: false + })) + ); + + this.emitServer('updateRoomOption', { + title: '즐거운 퀴즈 시간~~', + gameMode: 'SURVIVAL', + maxPlayerCount: 200, + isPublic: true + }); + + //2초후 게임 시작 + await this.delay(2); + this.emitServer('startGame', {}); + + //퀴즈 전송 + await this.progressQuiz( + '우리 팀의 이름은?', + 5, + ['시크릿주주', '시크릿추추', '시크릿쥬쥬', '시크릿츄츄'], + 0 + ); + await this.delay(3); + await this.progressQuiz( + '이 서비스의 이름은?', + 5, + ['퀴즈 그라운드', '배틀 그라운드', '큐플레이', '카훗'], + 0 + ); + await this.delay(3); + await this.progressQuiz('네이버 부스트캠프는 국내 최고의 부트캠트다', 5, ['O', 'X'], 0); + + // 퀴즈 종료 + await this.delay(5); + this.emitServer('endGame', { hostId: this.id }); + } + + async testChat() { + await this.initialrized; + const playerCount = this.getPlayerList().length; + for (let j = 0; j < 20; j++) { + for (const player of this.getPlayerList()) { + if (player.playerId === this.id) continue; + await this.delay(1 / playerCount / 0.1); + this.chatMessage( + player.playerId, + chatMessages[Math.floor(Math.random() * chatMessages.length)] + ); + } + } + } +} diff --git a/FE/src/api/socket/mocks/socketMocks/index.ts b/FE/src/api/socket/mocks/socketMocks/index.ts index 2c39e2c..031c56e 100644 --- a/FE/src/api/socket/mocks/socketMocks/index.ts +++ b/FE/src/api/socket/mocks/socketMocks/index.ts @@ -1,5 +1,7 @@ import SocketMockChat from './SocketMockChat'; -import SocketMockForReadme from './SocketMockForReadme'; +import SocketMockForReadmeSurvival from './SocketMockForReadmeSurvival'; +import SocketMockForReadmeRanking from './SocketMockForReadmeRanking'; +import SocketMockForReadme200 from './SocketMockForReadme200'; import SocketMockHost from './SocketMockHost'; import SocketMockLoadTest from './SocketMockLoadTest'; import SocketMockLoadTestOnlyMove from './SocketMockLoadTestOnlyMove'; @@ -17,7 +19,9 @@ const mockMap = { 'test-load-with-quiz': SocketMockLoadTestWithQuiz, 'test-start-end': SocketMockStartEnd, 'test-load-only-move': SocketMockLoadTestOnlyMove, - readme: SocketMockForReadme + 'readme-survival': SocketMockForReadmeSurvival, + 'readme-ranking': SocketMockForReadmeRanking, + 'readme-200': SocketMockForReadme200 } as const; export default mockMap; From 3f09e3ab8f9fff0bc599e8066ec2cb2daa58ddb0 Mon Sep 17 00:00:00 2001 From: ijun17 Date: Thu, 5 Dec 2024 00:28:26 +0900 Subject: [PATCH 4/6] =?UTF-8?q?fix:=20=EA=B2=8C=EC=9E=84=20=EC=8B=9C?= =?UTF-8?q?=EC=9E=91=20=EB=B2=84=ED=8A=BC=20=EC=97=AC=EB=9F=AC=EB=B2=88=20?= =?UTF-8?q?=EB=88=8C=EB=9F=AC=EB=8F=84=20=ED=95=9C=EB=B2=88=EB=A7=8C=20?= =?UTF-8?q?=EA=B2=8C=EC=9E=84=20=EC=8B=9C=EC=9E=91=20=EC=9A=94=EC=B2=AD=20?= =?UTF-8?q?=EA=B0=80=EB=8F=84=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- FE/src/features/game/components/GameHeader.tsx | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/FE/src/features/game/components/GameHeader.tsx b/FE/src/features/game/components/GameHeader.tsx index f21261d..ab0aa07 100644 --- a/FE/src/features/game/components/GameHeader.tsx +++ b/FE/src/features/game/components/GameHeader.tsx @@ -3,7 +3,7 @@ import { useNavigate, useParams } from 'react-router-dom'; import { useRoomStore } from '@/features/game/data/store/useRoomStore'; import React, { useState } from 'react'; import { QuizSettingModal } from './QuizSettingModal'; -import { socketService } from '@/api/socket'; +import { socketService, useSocketEvent, useSocketException } from '@/api/socket'; import { usePlayerStore } from '@/features/game/data/store/usePlayerStore'; import { useQuizStore } from '@/features/game/data/store/useQuizStore'; import CustomButton from '@/components/CustomButton'; @@ -17,14 +17,20 @@ export const GameHeader = React.memo( const gameTitle = useRoomStore((state) => state.title); const [isQuizModalOpen, setIsQuizModalOpen] = useState(false); const { quizSetTitle, quizSetCategory } = useQuizStore(); + const [gameLoading, setGameLoading] = useState(false); const pinNum = String(gameId); const linkURL = window.location.hostname + `/game/${gameId}`; const gameMode = useRoomStore((state) => state.gameMode); + const navigate = useNavigate(); const handleStartGame = () => { + if (gameLoading) return; + setGameLoading(true); if (gameId) socketService.emit('startGame', { gameId }); }; - const navigate = useNavigate(); + + useSocketEvent('startGame', () => setGameLoading(false)); + useSocketException('startGame', () => setGameLoading(false)); return (
From fa5bb2f9e10a00911025b8b056ad039a1448b5e2 Mon Sep 17 00:00:00 2001 From: ijun17 Date: Thu, 5 Dec 2024 17:18:06 +0900 Subject: [PATCH 5/6] =?UTF-8?q?feat:=20=EC=86=8C=EC=BC=93=20=EB=A1=9C?= =?UTF-8?q?=EA=B7=B8=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- FE/src/api/socket/mocks/SocketMock.ts | 1 - FE/src/api/socket/socket.ts | 10 +++++++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/FE/src/api/socket/mocks/SocketMock.ts b/FE/src/api/socket/mocks/SocketMock.ts index 3f2a80c..e553d57 100644 --- a/FE/src/api/socket/mocks/SocketMock.ts +++ b/FE/src/api/socket/mocks/SocketMock.ts @@ -48,7 +48,6 @@ export class SocketMock { this.onAnyListenerList.push(listener); } emit(event: T, data: SocketDataMap[T]['request']) { - console.log(`%c SERVER_SOCKET[${event}]`, 'background:blue; color:white', data); switch (event) { case SocketEvents.CHAT_MESSAGE: return this.handleChat(data as SocketDataMap[typeof SocketEvents.CHAT_MESSAGE]['request']); diff --git a/FE/src/api/socket/socket.ts b/FE/src/api/socket/socket.ts index 9911527..69773ac 100644 --- a/FE/src/api/socket/socket.ts +++ b/FE/src/api/socket/socket.ts @@ -34,6 +34,7 @@ class SocketService { private handlerMap: Partial< Record void)[]> > = {}; + private log = true; constructor(url: string) { this.socket = null; @@ -65,7 +66,13 @@ class SocketService { handlers.forEach((h) => socket.on(event, h)) ); this.socket.onAny((eventName, ...args) => { - console.log(`SOCKET[${eventName}]`, ...args); + if (this.log) { + if (eventName === 'exception') + console.log(`%cSOCKET[${eventName}]`, 'color:red', Date.now(), ...args); + else if (eventName !== 'updatePosition' && eventName !== 'chatMessage') + console.log(`%cSOCKET[${eventName}]`, 'color:green', Date.now(), ...args); + else console.log(`SOCKET[${eventName}]`, ...args); + } }); } @@ -92,6 +99,7 @@ class SocketService { emit(event: T, data: SocketDataMap[T]['request']) { if (!this.socket) return; this.socket.emit(event, data); + if (this.log) console.log(`%cSOCKET[${event}]`, 'background-color:blue', Date.now(), data); } async createRoom(option: { From f72d99cf70749ebf7b9455b182d1372e37dda909 Mon Sep 17 00:00:00 2001 From: ijun17 Date: Thu, 5 Dec 2024 17:43:29 +0900 Subject: [PATCH 6/6] =?UTF-8?q?design:=20=ED=80=B4=EC=A6=88=20=EB=B3=B4?= =?UTF-8?q?=EB=93=9C=20=EC=82=B4=EC=A7=9D=20=EB=8D=94=20=ED=88=AC=EB=AA=85?= =?UTF-8?q?=ED=95=98=EA=B2=8C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- FE/tailwind.config.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/FE/tailwind.config.js b/FE/tailwind.config.js index a81a3a9..a4ea23d 100644 --- a/FE/tailwind.config.js +++ b/FE/tailwind.config.js @@ -85,11 +85,11 @@ export default { borderWidth: '1px', borderColor: theme('borderColor.default'), borderRadius: theme('borderRadius.m'), - backgroundColor: '#FFFD' + backgroundColor: '#FFFC' }, '.component-popup': { borderRadius: theme('borderRadius.m'), - backgroundColor: '#FFFD', + backgroundColor: '#FFFC', boxShadow: theme('boxShadow.default') }, '.center': {