Skip to content

Commit e845d18

Browse files
authored
๐Ÿ”– release: v0.0.7
2 parents fc1b85d + 6cb182c commit e845d18

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+602
-207
lines changed

โ€Žbackend/build.gradleโ€Ž

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,17 +24,22 @@ repositories {
2424
}
2525

2626
dependencies {
27+
/* SPRING BOOT STARTER */
2728
implementation 'org.springframework.boot:spring-boot-starter-validation'
2829
implementation 'org.springframework.boot:spring-boot-starter-web'
2930
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
3031
implementation 'org.springframework.boot:spring-boot-starter-data-redis'
3132
implementation 'org.springframework.boot:spring-boot-starter-websocket'
3233
implementation 'org.springframework.boot:spring-boot-starter-security'
3334
implementation 'org.springframework.boot:spring-boot-starter-oauth2-client'
35+
implementation 'org.springframework.boot:spring-boot-starter-actuator'
3436

3537
/* DATABASE */
3638
runtimeOnly 'com.mysql:mysql-connector-j'
3739

40+
/* MONITORING */
41+
implementation 'io.micrometer:micrometer-registry-prometheus'
42+
3843
/* TEST */
3944
testImplementation 'org.springframework.boot:spring-boot-starter-test'
4045
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'

โ€Žbackend/src/main/java/io/f1/backend/domain/auth/dto/CurrentUserAndAdminResponse.javaโ€Ž

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,21 +3,19 @@
33
import io.f1.backend.domain.admin.dto.AdminPrincipal;
44
import io.f1.backend.domain.user.dto.UserPrincipal;
55

6-
public record CurrentUserAndAdminResponse(Long id, String name, String role, String providerId) {
6+
public record CurrentUserAndAdminResponse(Long id, String name, String role) {
77

88
public static CurrentUserAndAdminResponse from(UserPrincipal userPrincipal) {
99
return new CurrentUserAndAdminResponse(
1010
userPrincipal.getUserId(),
1111
userPrincipal.getUserNickname(),
12-
UserPrincipal.ROLE_USER,
13-
userPrincipal.getName());
12+
UserPrincipal.ROLE_USER);
1413
}
1514

1615
public static CurrentUserAndAdminResponse from(AdminPrincipal adminPrincipal) {
1716
return new CurrentUserAndAdminResponse(
1817
adminPrincipal.getAuthenticationAdmin().adminId(),
1918
adminPrincipal.getUsername(),
20-
AdminPrincipal.ROLE_ADMIN,
21-
null);
19+
AdminPrincipal.ROLE_ADMIN);
2220
}
2321
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
package io.f1.backend.domain.game.app;
2+
3+
import static io.f1.backend.domain.game.websocket.WebSocketUtils.getDestination;
4+
5+
import io.f1.backend.domain.game.dto.ChatMessage;
6+
import io.f1.backend.domain.game.dto.MessageType;
7+
import io.f1.backend.domain.game.event.GameCorrectAnswerEvent;
8+
import io.f1.backend.domain.game.model.Room;
9+
import io.f1.backend.domain.game.websocket.MessageSender;
10+
import io.f1.backend.domain.question.entity.Question;
11+
12+
import lombok.RequiredArgsConstructor;
13+
14+
import org.springframework.context.ApplicationEventPublisher;
15+
import org.springframework.stereotype.Service;
16+
17+
@Service
18+
@RequiredArgsConstructor
19+
public class ChatService {
20+
21+
private final RoomService roomService;
22+
private final TimerService timerService;
23+
private final MessageSender messageSender;
24+
private final ApplicationEventPublisher eventPublisher;
25+
26+
// todo ๋™์‹œ์„ฑ์ ์šฉ
27+
public void chat(Long roomId, String sessionId, ChatMessage chatMessage) {
28+
29+
Room room = roomService.findRoom(roomId);
30+
31+
String destination = getDestination(roomId);
32+
33+
messageSender.sendBroadcast(destination, MessageType.CHAT, chatMessage);
34+
35+
if (!room.isPlaying()) {
36+
return;
37+
}
38+
39+
Question currentQuestion = room.getCurrentQuestion();
40+
41+
String answer = currentQuestion.getAnswer();
42+
43+
if (answer.equals(chatMessage.message())) {
44+
eventPublisher.publishEvent(
45+
new GameCorrectAnswerEvent(room, sessionId, chatMessage, answer));
46+
}
47+
}
48+
}

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

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

3+
import static io.f1.backend.domain.game.mapper.RoomMapper.ofPlayerEvent;
4+
import static io.f1.backend.domain.game.mapper.RoomMapper.toGameResultListResponse;
35
import static io.f1.backend.domain.game.mapper.RoomMapper.toGameSettingResponse;
46
import static io.f1.backend.domain.game.mapper.RoomMapper.toPlayerListResponse;
7+
import static io.f1.backend.domain.game.mapper.RoomMapper.toQuestionResultResponse;
58
import static io.f1.backend.domain.game.mapper.RoomMapper.toQuestionStartResponse;
9+
import static io.f1.backend.domain.game.mapper.RoomMapper.toRankUpdateResponse;
10+
import static io.f1.backend.domain.game.mapper.RoomMapper.toRoomSettingResponse;
11+
import static io.f1.backend.domain.game.websocket.WebSocketUtils.getDestination;
612
import static io.f1.backend.domain.quiz.mapper.QuizMapper.toGameStartResponse;
713

14+
import io.f1.backend.domain.game.dto.ChatMessage;
815
import io.f1.backend.domain.game.dto.MessageType;
16+
import io.f1.backend.domain.game.dto.RoomEventType;
917
import io.f1.backend.domain.game.dto.request.GameSettingChanger;
1018
import io.f1.backend.domain.game.dto.response.PlayerListResponse;
19+
import io.f1.backend.domain.game.event.GameCorrectAnswerEvent;
20+
import io.f1.backend.domain.game.event.GameTimeoutEvent;
1121
import io.f1.backend.domain.game.event.RoomUpdatedEvent;
1222
import io.f1.backend.domain.game.model.Player;
1323
import io.f1.backend.domain.game.model.Room;
@@ -26,21 +36,26 @@
2636
import lombok.extern.slf4j.Slf4j;
2737

2838
import org.springframework.context.ApplicationEventPublisher;
39+
import org.springframework.context.event.EventListener;
2940
import org.springframework.stereotype.Service;
3041

3142
import java.util.List;
43+
import java.util.Map;
3244
import java.util.Objects;
3345

3446
@Slf4j
3547
@Service
3648
@RequiredArgsConstructor
3749
public class GameService {
3850

39-
public static final int START_DELAY = 5;
51+
private static final int START_DELAY = 5;
52+
private static final int CONTINUE_DELAY = 3;
53+
private static final String NONE_CORRECT_USER = "";
4054

41-
private final MessageSender messageSender;
42-
private final TimerService timerService;
4355
private final QuizService quizService;
56+
private final RoomService roomService;
57+
private final TimerService timerService;
58+
private final MessageSender messageSender;
4459
private final RoomRepository roomRepository;
4560
private final ApplicationEventPublisher eventPublisher;
4661

@@ -67,13 +82,114 @@ public void gameStart(Long roomId, UserPrincipal principal) {
6782

6883
timerService.startTimer(room, START_DELAY);
6984

70-
messageSender.send(destination, MessageType.GAME_START, toGameStartResponse(questions));
71-
messageSender.send(
85+
messageSender.sendBroadcast(
86+
destination, MessageType.GAME_START, toGameStartResponse(questions));
87+
messageSender.sendBroadcast(
88+
destination, MessageType.RANK_UPDATE, toRankUpdateResponse(room));
89+
messageSender.sendBroadcast(
7290
destination,
7391
MessageType.QUESTION_START,
7492
toQuestionStartResponse(room, START_DELAY));
7593
}
7694

95+
@EventListener
96+
public void onCorrectAnswer(GameCorrectAnswerEvent event) {
97+
98+
Room room = event.room();
99+
String sessionId = event.sessionId();
100+
ChatMessage chatMessage = event.chatMessage();
101+
String answer = event.answer();
102+
103+
String destination = getDestination(room.getId());
104+
105+
room.increasePlayerCorrectCount(sessionId);
106+
107+
messageSender.sendBroadcast(
108+
destination,
109+
MessageType.QUESTION_RESULT,
110+
toQuestionResultResponse(chatMessage.nickname(), answer));
111+
messageSender.sendBroadcast(
112+
destination, MessageType.RANK_UPDATE, toRankUpdateResponse(room));
113+
messageSender.sendBroadcast(
114+
destination,
115+
MessageType.SYSTEM_NOTICE,
116+
ofPlayerEvent(chatMessage.nickname(), RoomEventType.CORRECT_ANSWER));
117+
118+
timerService.cancelTimer(room);
119+
120+
if (!timerService.validateCurrentRound(room)) {
121+
gameEnd(room);
122+
return;
123+
}
124+
125+
room.increaseCurrentRound();
126+
127+
// ํƒ€์ด๋จธ ์ถ”๊ฐ€ํ•˜๊ธฐ
128+
timerService.startTimer(room, CONTINUE_DELAY);
129+
messageSender.sendBroadcast(
130+
destination,
131+
MessageType.QUESTION_START,
132+
toQuestionStartResponse(room, CONTINUE_DELAY));
133+
}
134+
135+
@EventListener
136+
public void onTimeout(GameTimeoutEvent event) {
137+
Room room = event.room();
138+
String destination = getDestination(room.getId());
139+
140+
messageSender.sendBroadcast(
141+
destination,
142+
MessageType.QUESTION_RESULT,
143+
toQuestionResultResponse(NONE_CORRECT_USER, room.getCurrentQuestion().getAnswer()));
144+
messageSender.sendBroadcast(
145+
destination,
146+
MessageType.SYSTEM_NOTICE,
147+
ofPlayerEvent(NONE_CORRECT_USER, RoomEventType.TIMEOUT));
148+
149+
if (!timerService.validateCurrentRound(room)) {
150+
gameEnd(room);
151+
return;
152+
}
153+
154+
room.increaseCurrentRound();
155+
156+
timerService.startTimer(room, CONTINUE_DELAY);
157+
messageSender.sendBroadcast(
158+
destination,
159+
MessageType.QUESTION_START,
160+
toQuestionStartResponse(room, CONTINUE_DELAY));
161+
}
162+
163+
public void gameEnd(Room room) {
164+
Long roomId = room.getId();
165+
String destination = getDestination(roomId);
166+
167+
Map<String, Player> playerSessionMap = room.getPlayerSessionMap();
168+
169+
// TODO : ๋žญํ‚น ์ •๋ณด ์—…๋ฐ์ดํŠธ
170+
messageSender.sendBroadcast(
171+
destination,
172+
MessageType.GAME_RESULT,
173+
toGameResultListResponse(playerSessionMap, room.getGameSetting().getRound()));
174+
175+
room.initializeRound();
176+
room.initializePlayers();
177+
178+
List<Player> disconnectedPlayers = room.getDisconnectedPlayers();
179+
roomService.handleDisconnectedPlayers(room, disconnectedPlayers);
180+
181+
room.updateRoomState(RoomState.WAITING);
182+
183+
messageSender.sendBroadcast(
184+
destination,
185+
MessageType.GAME_SETTING,
186+
toGameSettingResponse(
187+
room.getGameSetting(),
188+
quizService.getQuizWithQuestionsById(room.getGameSetting().getQuizId())));
189+
messageSender.sendBroadcast(
190+
destination, MessageType.ROOM_SETTING, toRoomSettingResponse(room));
191+
}
192+
77193
public void handlePlayerReady(Long roomId, String sessionId) {
78194

79195
Room room = findRoom(roomId);
@@ -86,7 +202,7 @@ public void handlePlayerReady(Long roomId, String sessionId) {
86202

87203
PlayerListResponse playerListResponse = toPlayerListResponse(room);
88204
log.info(playerListResponse.toString());
89-
messageSender.send(destination, MessageType.PLAYER_LIST, playerListResponse);
205+
messageSender.sendBroadcast(destination, MessageType.PLAYER_LIST, playerListResponse);
90206
}
91207

92208
public void changeGameSetting(
@@ -136,10 +252,6 @@ private Room findRoom(Long roomId) {
136252
.orElseThrow(() -> new CustomException(RoomErrorCode.ROOM_NOT_FOUND));
137253
}
138254

139-
private String getDestination(Long roomId) {
140-
return "/sub/room/" + roomId;
141-
}
142-
143255
private void validateHostAndState(Room room, UserPrincipal principal) {
144256
if (!room.isHost(principal.getUserId())) {
145257
throw new CustomException(RoomErrorCode.NOT_ROOM_OWNER);
@@ -161,7 +273,7 @@ private void toggleReadyIfPossible(Room room, Player player) {
161273
private void broadcastGameSetting(Room room) {
162274
String destination = getDestination(room.getId());
163275
Quiz quiz = quizService.getQuizWithQuestionsById(room.getGameSetting().getQuizId());
164-
messageSender.send(
276+
messageSender.sendBroadcast(
165277
destination,
166278
MessageType.GAME_SETTING,
167279
toGameSettingResponse(room.getGameSetting(), quiz));

0 commit comments

Comments
ย (0)