Skip to content

Commit 4315e9e

Browse files
committed
♻️ refactor: gameStart 리팩토링
- 방장만 게임 시작 가능 - 이미 플레이 중인 방의 중복 게임시작 방지
1 parent 3c89ab6 commit 4315e9e

File tree

4 files changed

+57
-44
lines changed

4 files changed

+57
-44
lines changed

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

Lines changed: 27 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,11 @@
1313
import io.f1.backend.domain.question.entity.Question;
1414
import io.f1.backend.domain.quiz.app.QuizService;
1515
import io.f1.backend.domain.quiz.entity.Quiz;
16+
import io.f1.backend.domain.user.dto.UserPrincipal;
1617
import io.f1.backend.global.exception.CustomException;
17-
import io.f1.backend.global.exception.errorcode.GameErrorCode;
1818
import io.f1.backend.global.exception.errorcode.RoomErrorCode;
1919

20+
import java.util.Objects;
2021
import lombok.RequiredArgsConstructor;
2122

2223
import org.springframework.context.ApplicationEventPublisher;
@@ -33,53 +34,54 @@ public class GameService {
3334
private final RoomRepository roomRepository;
3435
private final ApplicationEventPublisher eventPublisher;
3536

36-
public GameStartResponse gameStart(Long roomId, GameStartRequest gameStartRequest) {
37-
38-
Long quizId = gameStartRequest.quizId();
37+
public GameStartResponse gameStart(Long roomId, UserPrincipal principal) {
3938

4039
Room room =
4140
roomRepository
4241
.findRoom(roomId)
4342
.orElseThrow(() -> new CustomException(RoomErrorCode.ROOM_NOT_FOUND));
4443

45-
if (!validateReadyStatus(room)) {
46-
throw new CustomException(RoomErrorCode.PLAYER_NOT_READY);
47-
}
48-
49-
// 방의 gameSetting에 설정된 퀴즈랑 요청 퀴즈랑 같은지 체크 후 GameSetting에서 라운드 가져오기
50-
Integer round = checkGameSetting(room, quizId);
44+
validateRoomStart(room, principal);
5145

46+
Long quizId = room.getGameSetting().getQuizId();
5247
Quiz quiz = quizService.getQuizWithQuestionsById(quizId);
48+
List<Question> questions = prepareQuestions(room, quiz);
5349

54-
// 라운드 수만큼 랜덤 Question 추출
55-
List<Question> questions = quizService.getRandomQuestionsWithoutAnswer(quizId, round);
5650
room.updateQuestions(questions);
5751

58-
GameStartResponse gameStartResponse = toGameStartResponse(questions);
59-
6052
// 방 정보 게임 중으로 변경
6153
room.updateRoomState(RoomState.PLAYING);
6254

6355
eventPublisher.publishEvent(new RoomUpdatedEvent(room, quiz));
6456

65-
return gameStartResponse;
57+
return toGameStartResponse(questions);
6658
}
6759

68-
private Integer checkGameSetting(Room room, Long quizId) {
69-
70-
GameSetting gameSetting = room.getGameSetting();
60+
private boolean validateReadyStatus(Room room) {
7161

72-
if (!gameSetting.validateQuizId(quizId)) {
73-
throw new CustomException(GameErrorCode.GAME_SETTING_CONFLICT);
74-
}
62+
Map<String, Player> playerSessionMap = room.getPlayerSessionMap();
7563

76-
return gameSetting.getRound();
64+
return playerSessionMap.values().stream().allMatch(Player::isReady);
7765
}
7866

79-
private boolean validateReadyStatus(Room room) {
67+
private void validateRoomStart(Room room, UserPrincipal principal) {
68+
if (!Objects.equals(principal.getUserId(), room.getHost().getId())) {
69+
throw new CustomException(RoomErrorCode.NOT_ROOM_OWNER);
70+
}
8071

81-
Map<String, Player> playerSessionMap = room.getPlayerSessionMap();
72+
if (!validateReadyStatus(room)) {
73+
throw new CustomException(RoomErrorCode.PLAYER_NOT_READY);
74+
}
8275

83-
return playerSessionMap.values().stream().allMatch(Player::isReady);
76+
if (room.getState() == RoomState.PLAYING) {
77+
throw new CustomException(RoomErrorCode.GAME_ALREADY_PLAYING);
78+
}
79+
}
80+
81+
// 라운드 수만큼 랜덤 Question 추출
82+
public List<Question> prepareQuestions(Room room, Quiz quiz) {
83+
Long quizId = quiz.getId();
84+
Integer round = room.getGameSetting().getRound();
85+
return quizService.getRandomQuestionsWithoutAnswer(quizId, round);
8486
}
8587
}

backend/src/main/java/io/f1/backend/domain/game/websocket/GameSocketController.java

Lines changed: 7 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
import io.f1.backend.domain.game.dto.RoomInitialData;
99
import io.f1.backend.domain.game.dto.RoundResult;
1010
import io.f1.backend.domain.game.dto.request.DefaultWebSocketRequest;
11-
import io.f1.backend.domain.game.dto.request.GameStartRequest;
1211
import io.f1.backend.domain.game.dto.response.GameStartResponse;
1312
import io.f1.backend.domain.game.dto.response.PlayerListResponse;
1413
import io.f1.backend.domain.user.dto.UserPrincipal;
@@ -18,10 +17,11 @@
1817
import org.springframework.messaging.Message;
1918
import org.springframework.messaging.handler.annotation.DestinationVariable;
2019
import org.springframework.messaging.handler.annotation.MessageMapping;
21-
import org.springframework.messaging.simp.stomp.StompHeaderAccessor;
22-
import org.springframework.security.core.Authentication;
2320
import org.springframework.stereotype.Controller;
2421

22+
import static io.f1.backend.domain.game.websocket.WebSocketUtils.getSessionId;
23+
import static io.f1.backend.domain.game.websocket.WebSocketUtils.getSessionUser;
24+
2525
@Controller
2626
@RequiredArgsConstructor
2727
public class GameSocketController {
@@ -72,11 +72,11 @@ public void exitRoom(@DestinationVariable Long roomId, Message<?> message) {
7272

7373
@MessageMapping("/room/start/{roomId}")
7474
public void gameStart(
75-
@DestinationVariable Long roomId,
76-
Message<DefaultWebSocketRequest<GameStartRequest>> message) {
75+
@DestinationVariable Long roomId, Message<?> message) {
76+
77+
UserPrincipal principal = getSessionUser(message);
7778

78-
GameStartResponse gameStartResponse =
79-
gameService.gameStart(roomId, message.getPayload().getMessage());
79+
GameStartResponse gameStartResponse = gameService.gameStart(roomId, principal);
8080

8181
String destination = getDestination(roomId);
8282

@@ -112,17 +112,6 @@ public void playerReady(@DestinationVariable Long roomId, Message<?> message) {
112112
messageSender.send(getDestination(roomId), MessageType.PLAYER_LIST, playerListResponse);
113113
}
114114

115-
private static String getSessionId(Message<?> message) {
116-
StompHeaderAccessor accessor = StompHeaderAccessor.wrap(message);
117-
return accessor.getSessionId();
118-
}
119-
120-
private static UserPrincipal getSessionUser(Message<?> message) {
121-
StompHeaderAccessor accessor = StompHeaderAccessor.wrap(message);
122-
Authentication auth = (Authentication) accessor.getUser();
123-
return (UserPrincipal) auth.getPrincipal();
124-
}
125-
126115
private String getDestination(Long roomId) {
127116
return "/sub/room/" + roomId;
128117
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package io.f1.backend.domain.game.websocket;
2+
3+
import io.f1.backend.domain.user.dto.UserPrincipal;
4+
import org.springframework.messaging.Message;
5+
import org.springframework.messaging.simp.stomp.StompHeaderAccessor;
6+
import org.springframework.security.core.Authentication;
7+
8+
public class WebSocketUtils {
9+
10+
public static String getSessionId(Message<?> message) {
11+
StompHeaderAccessor accessor = StompHeaderAccessor.wrap(message);
12+
return accessor.getSessionId();
13+
}
14+
15+
public static UserPrincipal getSessionUser(Message<?> message) {
16+
StompHeaderAccessor accessor = StompHeaderAccessor.wrap(message);
17+
Authentication auth = (Authentication) accessor.getUser();
18+
return (UserPrincipal) auth.getPrincipal();
19+
}
20+
}

backend/src/main/java/io/f1/backend/global/exception/errorcode/RoomErrorCode.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,9 @@ public enum RoomErrorCode implements ErrorCode {
1414
ROOM_NOT_FOUND("E404005", HttpStatus.NOT_FOUND, "존재하지 않는 방입니다."),
1515
WRONG_PASSWORD("E401006", HttpStatus.UNAUTHORIZED, "비밀번호가 일치하지않습니다."),
1616
PLAYER_NOT_FOUND("E404007", HttpStatus.NOT_FOUND, "존재하지 않는 플레이어입니다."),
17-
SOCKET_SESSION_NOT_FOUND("E404006", HttpStatus.NOT_FOUND, "존재하지 않는 소켓 세션입니다.");
17+
SOCKET_SESSION_NOT_FOUND("E404006", HttpStatus.NOT_FOUND, "존재하지 않는 소켓 세션입니다."),
18+
GAME_ALREADY_PLAYING("E400015", HttpStatus.BAD_REQUEST, "이미 게임이 진행 중 입니다."),
19+
NOT_ROOM_OWNER("E403005", HttpStatus.FORBIDDEN, "방장만 게임 시작이 가능합니다.");
1820

1921
private final String code;
2022

0 commit comments

Comments
 (0)