Skip to content

Commit e9a5a38

Browse files
committed
✨ feat : 게임 시작, 진행, 타이머 기능 추가
1 parent aee9991 commit e9a5a38

File tree

7 files changed

+55
-42
lines changed

7 files changed

+55
-42
lines changed

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

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

3+
import static io.f1.backend.domain.game.mapper.RoomMapper.toQuestionStartResponse;
34
import static io.f1.backend.domain.quiz.mapper.QuizMapper.toGameStartResponse;
45

56
import io.f1.backend.domain.game.dto.GameStartData;
7+
import io.f1.backend.domain.game.dto.MessageType;
68
import io.f1.backend.domain.game.dto.response.GameStartResponse;
79
import io.f1.backend.domain.game.dto.response.QuestionStartResponse;
810
import io.f1.backend.domain.game.event.RoomUpdatedEvent;
911
import io.f1.backend.domain.game.model.Player;
1012
import io.f1.backend.domain.game.model.Room;
1113
import io.f1.backend.domain.game.model.RoomState;
1214
import io.f1.backend.domain.game.store.RoomRepository;
15+
import io.f1.backend.domain.game.websocket.MessageSender;
1316
import io.f1.backend.domain.question.entity.Question;
1417
import io.f1.backend.domain.quiz.app.QuizService;
1518
import io.f1.backend.domain.quiz.entity.Quiz;
@@ -35,6 +38,7 @@ public class GameService {
3538
private static final int START_DELAY = 5;
3639
private static final int CONTINUE_DELAY = 3;
3740

41+
private final MessageSender messageSender;
3842
private final TimerService timerService;
3943
private final QuizService quizService;
4044
private final RoomRepository roomRepository;
@@ -43,6 +47,8 @@ public class GameService {
4347

4448
public void gameStart(Long roomId, UserPrincipal principal) {
4549

50+
String destination = getDestination(roomId);
51+
4652
Room room =
4753
roomRepository
4854
.findRoom(roomId)
@@ -55,24 +61,17 @@ public void gameStart(Long roomId, UserPrincipal principal) {
5561
List<Question> questions = prepareQuestions(room, quiz);
5662

5763
room.updateQuestions(questions);
58-
59-
// 방 정보 게임 중으로 변경
64+
room.increaseCurrentRound();
6065
room.updateRoomState(RoomState.PLAYING);
6166

6267
eventPublisher.publishEvent(new RoomUpdatedEvent(room, quiz));
6368

64-
QuestionStartResponse questionStartResponse
65-
= new QuestionStartResponse(
66-
questions.getFirst().getId()
67-
, room.getGameSetting().getRound()
68-
, Instant.now().plusSeconds(START_DELAY)
69-
);
70-
7169
timerService.startTimer(room, START_DELAY);
7270

73-
// return new GameStartData(gameStartResponse, questionStartResponse);
74-
}
71+
messageSender.send(destination, MessageType.GAME_START, toGameStartResponse(questions));
72+
messageSender.send(destination, MessageType.QUESTION_START, toQuestionStartResponse(room, START_DELAY));
7573

74+
}
7675

7776
private boolean validateReadyStatus(Room room) {
7877

@@ -101,4 +100,8 @@ private List<Question> prepareQuestions(Room room, Quiz quiz) {
101100
Integer round = room.getGameSetting().getRound();
102101
return quizService.getRandomQuestionsWithoutAnswer(quizId, round);
103102
}
103+
104+
private String getDestination(Long roomId) {
105+
return "/sub/room/" + roomId;
106+
}
104107
}

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

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -252,18 +252,22 @@ public void chat(Long roomId, String sessionId, ChatMessage chatMessage) {
252252
messageSender.send(
253253
destination,
254254
MessageType.QUESTION_RESULT,
255-
toQuestionResultResponse(currentQuestion.getId(), chatMessage, answer));
255+
toQuestionResultResponse(chatMessage.nickname(), answer));
256256
messageSender.send(destination, MessageType.RANK_UPDATE, toRankUpdateResponse(room));
257257
messageSender.send(
258258
destination,
259259
MessageType.SYSTEM_NOTICE,
260-
ofPlayerEvent(chatMessage.nickname(), RoomEventType.ENTER));
260+
ofPlayerEvent(chatMessage.nickname(), RoomEventType.CORRECT_ANSWER));
261261
}
262262

263-
264263
timerService.cancelTimer(room);
265264

266-
room.increasePlayerCorrectCount(sessionId);
265+
// TODO : 게임 종료 로직 추가
266+
if(!timerService.validateCurrentRound(room)) {
267+
// 게임 종료 로직
268+
return;
269+
}
270+
267271
room.increaseCurrentRound();
268272

269273
// 타이머 추가하기

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

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
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.toQuestionResultResponse;
45
import static io.f1.backend.domain.game.mapper.RoomMapper.toQuestionStartResponse;
56
import static io.f1.backend.domain.game.mapper.RoomMapper.toRankUpdateResponse;
67

@@ -19,34 +20,51 @@ public class TimerService {
1920

2021
private final MessageSender messageSender;
2122

23+
private static final String NONE_CORRECT_USER = "";
2224
private static final int CONTINUE_DELAY = 3;
2325

2426
public void startTimer(Room room, int delaySec) {
27+
cancelTimer(room);
2528
ScheduledFuture<?> timer = room.getTimer();
2629
timer = room.getScheduler().schedule(() -> {
2730
handleTimeout(room);
2831
}, delaySec + room.getGameSetting().getTimeLimit(), TimeUnit.SECONDS);
2932
}
3033

3134
private void handleTimeout(Room room) {
32-
// TIMEOUT 일 때 처리 !
35+
3336
String destination = getDestination(room.getId());
3437

38+
messageSender.send(destination, MessageType.QUESTION_RESULT, toQuestionResultResponse(NONE_CORRECT_USER, room.getCurrentQuestion().getAnswer()));
39+
messageSender.send(destination, MessageType.SYSTEM_NOTICE, ofPlayerEvent(NONE_CORRECT_USER, RoomEventType.TIMEOUT));
40+
41+
// TODO : 게임 종료 로직
42+
if(!validateCurrentRound(room)){
43+
// 게임 종료 로직
44+
// GAME_SETTING, PLAYER_LIST, GAME_RESULT, ROOM_SETTING
45+
return;
46+
}
47+
48+
// 다음 문제 출제
3549
room.increaseCurrentRound();
3650

37-
// QuestionResult는 ChatMessage 받지 않고 String 받도록
38-
messageSender.send(destination, MessageType.RANK_UPDATE, toRankUpdateResponse(room));
39-
messageSender.send(destination, MessageType.SYSTEM_NOTICE, ofPlayerEvent("", RoomEventType.TIMEOUT));
4051
startTimer(room, CONTINUE_DELAY);
41-
messageSender.send(destination, MessageType.QUESTION_START, toQuestionStartResponse(room.getCurrentQuestion().getId(), room.getCurrentRound()));
52+
messageSender.send(destination, MessageType.QUESTION_START, toQuestionStartResponse(room, CONTINUE_DELAY));
53+
}
4254

43-
// TIMEOUT 처리 해주고 또 타이머 시작 !
55+
public boolean validateCurrentRound(Room room) {
56+
if(room.getGameSetting().getRound() != room.getCurrentRound()) {
57+
return true;
58+
}
59+
cancelTimer(room);
60+
room.getScheduler().shutdown();
61+
return false;
4462
}
4563

4664
public void cancelTimer(Room room) {
4765
// 정답 맞혔어요 ~ 타이머 캔슬 부탁
4866
ScheduledFuture<?> timer = room.getTimer();
49-
if(timer != null) {
67+
if(timer != null && !timer.isDone()) {
5068
timer.cancel(false);
5169
}
5270
}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
package io.f1.backend.domain.game.dto.response;
22

3-
public record QuestionResultResponse(Long questionId, String correctUser, String answer) {}
3+
public record QuestionResultResponse(String correctUser, String answer) {}

backend/src/main/java/io/f1/backend/domain/game/mapper/RoomMapper.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@
2828
public class RoomMapper {
2929

3030
private static final int DEFAULT_TIME_LIMIT = 60;
31-
private static final int CONTINUE_DELAY = 3;
3231

3332
public static RoomSetting toRoomSetting(RoomCreateRequest request) {
3433
return new RoomSetting(
@@ -102,8 +101,8 @@ public static SystemNoticeResponse ofPlayerEvent(String nickname, RoomEventType
102101
}
103102

104103
public static QuestionResultResponse toQuestionResultResponse(
105-
Long questionId, ChatMessage chatMessage, String answer) {
106-
return new QuestionResultResponse(questionId, chatMessage.nickname(), answer);
104+
String correctUser, String answer) {
105+
return new QuestionResultResponse(correctUser, answer);
107106
}
108107

109108
public static RankUpdateResponse toRankUpdateResponse(Room room) {
@@ -114,8 +113,9 @@ public static RankUpdateResponse toRankUpdateResponse(Room room) {
114113
.toList());
115114
}
116115

117-
public static QuestionStartResponse toQuestionStartResponse(Long questionId, int currentRound) {
116+
public static QuestionStartResponse toQuestionStartResponse(Room room, int delay) {
118117
return new QuestionStartResponse(
119-
questionId, currentRound, Instant.now().plusSeconds(CONTINUE_DELAY));
118+
room.getCurrentQuestion().getId(), room.getCurrentRound(), Instant.now().plusSeconds(delay));
120119
}
120+
121121
}

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

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,6 @@
2121
@RequiredArgsConstructor
2222
public class GameSocketController {
2323

24-
// todo 삭제
25-
private final MessageSender messageSender;
2624
private final RoomService roomService;
2725
private final GameService gameService;
2826

@@ -48,16 +46,10 @@ public void exitRoom(@DestinationVariable Long roomId, Message<?> message) {
4846
@MessageMapping("/room/start/{roomId}")
4947
public void gameStart(@DestinationVariable Long roomId, Message<?> message) {
5048

51-
5249
UserPrincipal principal = getSessionUser(message);
5350

5451
gameService.gameStart(roomId, principal);
5552

56-
String destination = getDestination(roomId);
57-
58-
// messageSender.send(destination, MessageType.GAME_START, gameStartData.gameStartResponse());
59-
// messageSender.send(destination, MessageType.QUESTION_START, gameStartData.questionStartResponse());
60-
6153
}
6254

6355
@MessageMapping("room/chat/{roomId}")
@@ -74,9 +66,4 @@ public void playerReady(@DestinationVariable Long roomId, Message<?> message) {
7466

7567
roomService.handlePlayerReady(roomId, getSessionId(message));
7668
}
77-
78-
// todo 삭제
79-
private String getDestination(Long roomId) {
80-
return "/sub/room/" + roomId;
81-
}
8269
}

backend/src/test/java/io/f1/backend/domain/game/app/RoomServiceTests.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,13 +45,14 @@ class RoomServiceTests {
4545

4646
@Mock private RoomRepository roomRepository;
4747
@Mock private QuizService quizService;
48+
@Mock private TimerService timerService;
4849
@Mock private ApplicationEventPublisher eventPublisher;
4950
@Mock private MessageSender messageSender;
5051

5152
@BeforeEach
5253
void setUp() {
5354
MockitoAnnotations.openMocks(this); // @Mock 어노테이션이 붙은 필드들을 초기화합니다.
54-
roomService = new RoomService(quizService, roomRepository, eventPublisher, messageSender);
55+
roomService = new RoomService(timerService, quizService, roomRepository, eventPublisher, messageSender);
5556

5657
SecurityContextHolder.clearContext();
5758
}

0 commit comments

Comments
 (0)