Skip to content

Commit 9ab7281

Browse files
committed
✨ 대기중 채팅, 게임중 채팅(정답판별) 구현
1 parent c4834de commit 9ab7281

File tree

13 files changed

+237
-61
lines changed

13 files changed

+237
-61
lines changed

backend/src/main/java/io/f1/backend/domain/game/app/RoomService.java

Lines changed: 66 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,24 @@
11
package io.f1.backend.domain.game.app;
22

33
import static io.f1.backend.domain.game.mapper.RoomMapper.ofPlayerEvent;
4+
import static io.f1.backend.domain.game.mapper.RoomMapper.toChatMessage;
45
import static io.f1.backend.domain.game.mapper.RoomMapper.toGameSetting;
56
import static io.f1.backend.domain.game.mapper.RoomMapper.toGameSettingResponse;
67
import static io.f1.backend.domain.game.mapper.RoomMapper.toPlayerListResponse;
8+
import static io.f1.backend.domain.game.mapper.RoomMapper.toQuestionResultResponse;
9+
import static io.f1.backend.domain.game.mapper.RoomMapper.toRankUpdateResponse;
710
import static io.f1.backend.domain.game.mapper.RoomMapper.toRoomResponse;
811
import static io.f1.backend.domain.game.mapper.RoomMapper.toRoomSetting;
912
import static io.f1.backend.domain.game.mapper.RoomMapper.toRoomSettingResponse;
1013
import static io.f1.backend.global.util.SecurityUtils.getCurrentUserId;
1114
import static io.f1.backend.global.util.SecurityUtils.getCurrentUserNickname;
1215

16+
import io.f1.backend.domain.game.dto.ChatMessage;
1317
import io.f1.backend.domain.game.dto.RoomEventType;
1418
import io.f1.backend.domain.game.dto.RoomExitData;
1519
import io.f1.backend.domain.game.dto.RoomInitialData;
20+
import io.f1.backend.domain.game.dto.RoundResult;
21+
import io.f1.backend.domain.game.dto.request.AnswerMessage;
1622
import io.f1.backend.domain.game.dto.request.RoomCreateRequest;
1723
import io.f1.backend.domain.game.dto.request.RoomValidationRequest;
1824
import io.f1.backend.domain.game.dto.response.GameSettingResponse;
@@ -29,22 +35,21 @@
2935
import io.f1.backend.domain.game.model.RoomSetting;
3036
import io.f1.backend.domain.game.model.RoomState;
3137
import io.f1.backend.domain.game.store.RoomRepository;
38+
import io.f1.backend.domain.question.entity.Question;
3239
import io.f1.backend.domain.quiz.app.QuizService;
3340
import io.f1.backend.domain.quiz.entity.Quiz;
3441
import io.f1.backend.global.exception.CustomException;
42+
import io.f1.backend.global.exception.errorcode.QuestionErrorCode;
3543
import io.f1.backend.global.exception.errorcode.RoomErrorCode;
36-
37-
import lombok.RequiredArgsConstructor;
38-
import lombok.extern.slf4j.Slf4j;
39-
40-
import org.springframework.context.ApplicationEventPublisher;
41-
import org.springframework.stereotype.Service;
42-
4344
import java.util.List;
4445
import java.util.Map;
4546
import java.util.Optional;
4647
import java.util.concurrent.ConcurrentHashMap;
4748
import java.util.concurrent.atomic.AtomicLong;
49+
import lombok.RequiredArgsConstructor;
50+
import lombok.extern.slf4j.Slf4j;
51+
import org.springframework.context.ApplicationEventPublisher;
52+
import org.springframework.stereotype.Service;
4853

4954
@Slf4j
5055
@Service
@@ -102,7 +107,7 @@ public void enterRoom(RoomValidationRequest request) {
102107
}
103108

104109
if (room.getRoomSetting().locked()
105-
&& !room.getRoomSetting().password().equals(request.password())) {
110+
&& !room.getRoomSetting().password().equals(request.password())) {
106111
throw new CustomException(RoomErrorCode.WRONG_PASSWORD);
107112
}
108113

@@ -136,18 +141,19 @@ public RoomInitialData initializeRoomSocket(Long roomId, String sessionId) {
136141
Quiz quiz = quizService.getQuizWithQuestionsById(quizId);
137142

138143
GameSettingResponse gameSettingResponse =
139-
toGameSettingResponse(room.getGameSetting(), quiz);
144+
toGameSettingResponse(room.getGameSetting(), quiz);
140145

141146
PlayerListResponse playerListResponse = toPlayerListResponse(room);
142147

143-
SystemNoticeResponse systemNoticeResponse = ofPlayerEvent(player, RoomEventType.ENTER);
148+
SystemNoticeResponse systemNoticeResponse = ofPlayerEvent(player.getNickname(),
149+
RoomEventType.ENTER);
144150

145151
return new RoomInitialData(
146-
getDestination(roomId),
147-
roomSettingResponse,
148-
gameSettingResponse,
149-
playerListResponse,
150-
systemNoticeResponse);
152+
getDestination(roomId),
153+
roomSettingResponse,
154+
gameSettingResponse,
155+
playerListResponse,
156+
systemNoticeResponse);
151157
}
152158

153159
public RoomExitData exitRoom(Long roomId, String sessionId) {
@@ -175,7 +181,7 @@ public RoomExitData exitRoom(Long roomId, String sessionId) {
175181
removePlayer(room, sessionId, removePlayer);
176182

177183
SystemNoticeResponse systemNoticeResponse =
178-
ofPlayerEvent(removePlayer, RoomEventType.EXIT);
184+
ofPlayerEvent(removePlayer.nickname, RoomEventType.EXIT);
179185

180186
PlayerListResponse playerListResponse = toPlayerListResponse(room);
181187

@@ -186,18 +192,45 @@ public RoomExitData exitRoom(Long roomId, String sessionId) {
186192
public RoomListResponse getAllRooms() {
187193
List<Room> rooms = roomRepository.findAll();
188194
List<RoomResponse> roomResponses =
189-
rooms.stream()
190-
.map(
191-
room -> {
192-
Long quizId = room.getGameSetting().getQuizId();
193-
Quiz quiz = quizService.getQuizWithQuestionsById(quizId);
194-
195-
return toRoomResponse(room, quiz);
196-
})
197-
.toList();
195+
rooms.stream()
196+
.map(
197+
room -> {
198+
Long quizId = room.getGameSetting().getQuizId();
199+
Quiz quiz = quizService.getQuizWithQuestionsById(quizId);
200+
201+
return toRoomResponse(room, quiz);
202+
})
203+
.toList();
198204
return new RoomListResponse(roomResponses);
199205
}
200206

207+
public RoundResult chatInPlaying(Long roomId, String sessionId, AnswerMessage chatMessage) {
208+
Room room = findRoom(roomId);
209+
210+
String destination = getDestination(roomId);
211+
212+
Question question = room.getQuestions().stream()
213+
.filter(q -> q.getId().equals(chatMessage.questionId()))
214+
.findFirst().orElseThrow(() -> new CustomException(
215+
QuestionErrorCode.QUESTION_NOT_FOUND));
216+
217+
ChatMessage broadCastChat = toChatMessage(chatMessage);
218+
219+
String answer = question.getAnswer();
220+
221+
if (!answer.equals(chatMessage.message())) {
222+
return RoundResult.builder().destination(destination).chat(broadCastChat).build();
223+
}
224+
225+
room.increasePlayerCorrectCount(sessionId);
226+
227+
return RoundResult.builder().destination(destination)
228+
.questionResult(toQuestionResultResponse(chatMessage, answer))
229+
.rankUpdate(toRankUpdateResponse(room))
230+
.systemNotice(ofPlayerEvent(chatMessage.nickname(), RoomEventType.ENTER))
231+
.chat(broadCastChat).build();
232+
}
233+
201234
private Player getRemovePlayer(Room room, String sessionId) {
202235
Player removePlayer = room.getPlayerSessionMap().get(sessionId);
203236
if (removePlayer == null) {
@@ -217,8 +250,8 @@ private Player createPlayer() {
217250

218251
private Room findRoom(Long roomId) {
219252
return roomRepository
220-
.findRoom(roomId)
221-
.orElseThrow(() -> new CustomException(RoomErrorCode.ROOM_NOT_FOUND));
253+
.findRoom(roomId)
254+
.orElseThrow(() -> new CustomException(RoomErrorCode.ROOM_NOT_FOUND));
222255
}
223256

224257
private boolean isLastPlayer(Room room, String sessionId) {
@@ -238,14 +271,14 @@ private void changeHost(Room room, String hostSessionId) {
238271
Map<String, Player> playerSessionMap = room.getPlayerSessionMap();
239272

240273
Optional<String> nextHostSessionId =
241-
playerSessionMap.keySet().stream()
242-
.filter(key -> !key.equals(hostSessionId))
243-
.findFirst();
274+
playerSessionMap.keySet().stream()
275+
.filter(key -> !key.equals(hostSessionId))
276+
.findFirst();
244277

245278
Player nextHost =
246-
playerSessionMap.get(
247-
nextHostSessionId.orElseThrow(
248-
() -> new CustomException(RoomErrorCode.SOCKET_SESSION_NOT_FOUND)));
279+
playerSessionMap.get(
280+
nextHostSessionId.orElseThrow(
281+
() -> new CustomException(RoomErrorCode.SOCKET_SESSION_NOT_FOUND)));
249282

250283
room.updateHost(nextHost);
251284
log.info("user_id:{} 방장 변경 완료 ", nextHost.getId());
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package io.f1.backend.domain.game.dto;
2+
3+
import java.time.Instant;
4+
5+
public record ChatMessage ( String nickname, String message, Instant timestamp) {
6+
7+
}

backend/src/main/java/io/f1/backend/domain/game/dto/MessageType.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,7 @@ public enum MessageType {
66
PLAYER_LIST,
77
SYSTEM_NOTICE,
88
GAME_START,
9+
CHAT,
10+
QUESTION_RESULT,
11+
RANK_UPDATE,
912
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package io.f1.backend.domain.game.dto;
2+
3+
public record Rank(String nickName, int correctCount) {
4+
5+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package io.f1.backend.domain.game.dto;
2+
3+
import io.f1.backend.domain.game.dto.response.QuestionResultResponse;
4+
import io.f1.backend.domain.game.dto.response.RankUpdateResponse;
5+
import io.f1.backend.domain.game.dto.response.SystemNoticeResponse;
6+
import lombok.Builder;
7+
import lombok.Getter;
8+
9+
@Getter
10+
public class RoundResult {
11+
String destination;
12+
QuestionResultResponse questionResult;
13+
RankUpdateResponse rankUpdate;
14+
SystemNoticeResponse systemNotice;
15+
ChatMessage chat;
16+
17+
@Builder
18+
public RoundResult(String destination,QuestionResultResponse questionResult, RankUpdateResponse rankUpdate,
19+
SystemNoticeResponse systemNotice, ChatMessage chat) {
20+
this.questionResult = questionResult;
21+
this.rankUpdate = rankUpdate;
22+
this.systemNotice = systemNotice;
23+
this.chat = chat;
24+
}
25+
26+
public boolean hasChat(){
27+
return chat != null;
28+
}
29+
30+
public boolean hasOnlyChat() {
31+
return chat != null
32+
&& questionResult == null
33+
&& rankUpdate == null
34+
&& systemNotice == null;
35+
}
36+
37+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package io.f1.backend.domain.game.dto.request;
2+
3+
import java.time.Instant;
4+
5+
public record AnswerMessage (String nickname, String message, Instant timestamp, Long questionId) {
6+
7+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package io.f1.backend.domain.game.dto.request;
2+
3+
import io.f1.backend.domain.game.dto.MessageType;
4+
import io.f1.backend.domain.game.dto.WebSocketDto;
5+
import lombok.AllArgsConstructor;
6+
import lombok.Getter;
7+
8+
@Getter
9+
@AllArgsConstructor
10+
public class DefaultWebSocketRequest<T> implements WebSocketDto<T> {
11+
private final MessageType type;
12+
private final T message;
13+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package io.f1.backend.domain.game.dto.response;
2+
3+
public record QuestionResultResponse(Long questionId, String correctUser, String answer) {
4+
5+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package io.f1.backend.domain.game.dto.response;
2+
3+
4+
import io.f1.backend.domain.game.dto.Rank;
5+
import java.util.List;
6+
7+
public record RankUpdateResponse(List<Rank> rank) {
8+
9+
}

0 commit comments

Comments
 (0)