-
Notifications
You must be signed in to change notification settings - Fork 3
[feat] 게임방 퇴장 및 삭제 구현 #33
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
d8e82fe
2604aee
97d5ce4
938f205
140d082
f220c52
2f85c23
ed0c577
8a77425
55ce888
d331470
5a9db09
0a0c98e
14bff7c
01996ac
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,17 +1,27 @@ | ||
| package io.f1.backend.domain.game.app; | ||
|
|
||
| import static io.f1.backend.domain.game.mapper.RoomMapper.*; | ||
|
|
||
| import static io.f1.backend.domain.game.mapper.RoomMapper.ofPlayerEvent; | ||
| import static io.f1.backend.domain.game.mapper.RoomMapper.toGameSetting; | ||
| import static io.f1.backend.domain.game.mapper.RoomMapper.toGameSettingResponse; | ||
| import static io.f1.backend.domain.game.mapper.RoomMapper.toPlayerListResponse; | ||
| import static io.f1.backend.domain.game.mapper.RoomMapper.toRoomResponse; | ||
| import static io.f1.backend.domain.game.mapper.RoomMapper.toRoomSetting; | ||
| import static io.f1.backend.domain.game.mapper.RoomMapper.toRoomSettingResponse; | ||
| import static io.f1.backend.global.util.SecurityUtils.getCurrentUserId; | ||
| import static io.f1.backend.global.util.SecurityUtils.getCurrentUserNickname; | ||
|
|
||
| import io.f1.backend.domain.game.dto.RoomEventType; | ||
| import io.f1.backend.domain.game.dto.RoomExitData; | ||
| import io.f1.backend.domain.game.dto.RoomInitialData; | ||
| import io.f1.backend.domain.game.dto.request.RoomCreateRequest; | ||
| import io.f1.backend.domain.game.dto.request.RoomValidationRequest; | ||
| import io.f1.backend.domain.game.dto.response.GameSettingResponse; | ||
| import io.f1.backend.domain.game.dto.response.PlayerListResponse; | ||
| import io.f1.backend.domain.game.dto.response.QuizResponse; | ||
| import io.f1.backend.domain.game.dto.response.RoomCreateResponse; | ||
| import io.f1.backend.domain.game.dto.response.RoomListResponse; | ||
| import io.f1.backend.domain.game.dto.response.RoomResponse; | ||
| import io.f1.backend.domain.game.dto.response.RoomSettingResponse; | ||
| import io.f1.backend.domain.game.dto.response.SystemNoticeResponse; | ||
| import io.f1.backend.domain.game.event.RoomCreatedEvent; | ||
| import io.f1.backend.domain.game.model.GameSetting; | ||
| import io.f1.backend.domain.game.model.Player; | ||
|
|
@@ -29,6 +39,7 @@ | |
|
|
||
| import java.util.List; | ||
| import java.util.Map; | ||
| import java.util.Optional; | ||
| import java.util.concurrent.atomic.AtomicLong; | ||
|
|
||
| @Service | ||
|
|
@@ -40,12 +51,15 @@ public class RoomService { | |
| private final AtomicLong roomIdGenerator = new AtomicLong(0); | ||
| private final ApplicationEventPublisher eventPublisher; | ||
|
|
||
| public RoomCreateResponse saveRoom(RoomCreateRequest request, Map<String, Object> loginUser) { | ||
| public RoomCreateResponse saveRoom(RoomCreateRequest request) { | ||
|
|
||
| Long quizMinId = quizService.getQuizMinId(); | ||
| Quiz quiz = quizService.getQuizById(quizMinId); | ||
|
|
||
| GameSetting gameSetting = toGameSetting(quiz); | ||
|
|
||
| Player host = createPlayer(); | ||
|
|
||
| // todo 제일 작은 index quizId 가져와서 gameSetting(round 설정) | ||
| GameSetting gameSetting = new GameSetting(1L, 10, 60); | ||
| // todo security에서 가져오는걸로 변경 | ||
| Player host = new Player((Long) loginUser.get("id"), loginUser.get("nickname").toString()); | ||
| RoomSetting roomSetting = toRoomSetting(request); | ||
|
|
||
| Long newId = roomIdGenerator.incrementAndGet(); | ||
|
|
@@ -54,9 +68,6 @@ public RoomCreateResponse saveRoom(RoomCreateRequest request, Map<String, Object | |
|
|
||
| roomRepository.saveRoom(room); | ||
|
|
||
| Long quizId = room.getGameSetting().getQuizId(); | ||
| Quiz quiz = quizService.getQuizById(quizId); | ||
|
|
||
| eventPublisher.publishEvent(new RoomCreatedEvent(room, quiz)); | ||
|
|
||
| return new RoomCreateResponse(newId); | ||
|
|
@@ -67,7 +78,7 @@ public void validateRoom(RoomValidationRequest request) { | |
| Room room = | ||
| roomRepository | ||
| .findRoom(request.roomId()) | ||
| .orElseThrow(() -> new IllegalArgumentException("404 존재하지 않는 방입니다.")); | ||
| .orElseThrow(() -> new IllegalArgumentException("404 존재하지 않는 방입니다.-1")); | ||
|
|
||
| if (room.getState().equals(RoomState.PLAYING)) { | ||
| throw new IllegalArgumentException("403 게임이 진행중입니다."); | ||
|
|
@@ -92,26 +103,69 @@ public RoomInitialData enterRoom(Long roomId, String sessionId) { | |
| .findRoom(roomId) | ||
| .orElseThrow(() -> new IllegalArgumentException("404 존재하지 않는 방입니다.")); | ||
|
|
||
| // todo security | ||
| Player player = new Player(1L, "빵야빵야"); | ||
| Player player = createPlayer(); | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [L3-중요질문]
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 웹소켓 명세에 빠져있는 부분이라 놓쳤군요..! 감사합니다. 추가하겠습니다. 😇 |
||
|
|
||
| Map<String, Player> playerSessionMap = room.getPlayerSessionMap(); | ||
|
|
||
| playerSessionMap.put(sessionId, player); | ||
|
|
||
| String destination = "/sub/room/" + roomId; | ||
|
|
||
| RoomSettingResponse roomSettingResponse = toRoomSettingResponse(room); | ||
| // todo quiz 생성 api 완성 후 수정 | ||
| QuizResponse quiz = | ||
| new QuizResponse(room.getGameSetting().getQuizId(), "title", "설명", "url", 10); | ||
|
|
||
| Long quizId = room.getGameSetting().getQuizId(); | ||
| Quiz quiz = quizService.getQuizById(quizId); | ||
|
|
||
| GameSettingResponse gameSettingResponse = | ||
| toGameSettingResponse(room.getGameSetting(), quiz); | ||
|
|
||
| PlayerListResponse playerListResponse = toPlayerListResponse(room); | ||
|
|
||
| SystemNoticeResponse systemNoticeResponse = ofPlayerEvent(player, RoomEventType.ENTER); | ||
|
|
||
| return new RoomInitialData( | ||
| destination, roomSettingResponse, gameSettingResponse, playerListResponse); | ||
| getDestination(roomId), | ||
| roomSettingResponse, | ||
| gameSettingResponse, | ||
| playerListResponse, | ||
| systemNoticeResponse); | ||
| } | ||
|
|
||
| public RoomExitData exitRoom(Long roomId, String sessionId) { | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [L4-변경제안]
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 안그래도 private static 으로 몇개는 분리해놨는데, 요 부분은 동시성 진행하면서 더 분리해보도록 하겠습니다! 감사합니다 |
||
| Room room = | ||
| roomRepository | ||
| .findRoom(roomId) | ||
| .orElseThrow(() -> new IllegalArgumentException("404 존재하지 않는 방입니다.")); | ||
|
|
||
| Map<String, Player> playerSessionMap = room.getPlayerSessionMap(); | ||
|
|
||
| String destination = getDestination(roomId); | ||
|
|
||
| if (playerSessionMap.size() == 1 && playerSessionMap.get(sessionId) != null) { | ||
| roomRepository.removeRoom(roomId); | ||
| return RoomExitData.builder().destination(destination).removedRoom(true).build(); | ||
| } | ||
|
|
||
| Player removedPlayer = playerSessionMap.remove(sessionId); | ||
| if (removedPlayer == null) { | ||
| throw new IllegalArgumentException("퇴장 처리 불가 - 404 해당 세션 플레이어는 존재하지않습니다."); | ||
| } | ||
|
|
||
| if (room.getHost().getId().equals(removedPlayer.getId())) { | ||
| Optional<String> nextHostSessionId = playerSessionMap.keySet().stream().findFirst(); | ||
| Player nextHost = | ||
| playerSessionMap.get( | ||
| nextHostSessionId.orElseThrow( | ||
| () -> | ||
| new IllegalArgumentException( | ||
| "방장 교체 불가 - 404 해당 세션 플레이어는 존재하지않습니다."))); | ||
| room.updateHost(nextHost); | ||
| } | ||
|
|
||
| SystemNoticeResponse systemNoticeResponse = | ||
| ofPlayerEvent(removedPlayer, RoomEventType.EXIT); | ||
|
|
||
| PlayerListResponse playerListResponse = toPlayerListResponse(room); | ||
|
|
||
| return new RoomExitData(destination, playerListResponse, systemNoticeResponse, false); | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
방이 삭제되었을때는 따로 응답 값을 보내주지 보내주지 않아도되고, 삭제가 안되었을때만 응답값을 보내줘야하기에 구분 필드를 넣었습니다. 원래 record로 사용시에는 true로 생성했는데, 빌더로 바꾸면서 true가 빠진 것 같습니다! 알려주셔서.. 감사합니다 ^_^ |
||
| } | ||
|
|
||
| public RoomListResponse getAllRooms() { | ||
|
|
@@ -128,4 +182,12 @@ public RoomListResponse getAllRooms() { | |
| .toList(); | ||
| return new RoomListResponse(roomResponses); | ||
| } | ||
|
|
||
| private static String getDestination(Long roomId) { | ||
| return "/sub/room/" + roomId; | ||
| } | ||
|
|
||
| private static Player createPlayer() { | ||
| return new Player(getCurrentUserId(), getCurrentUserNickname()); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -4,4 +4,5 @@ public enum MessageType { | |
| ROOM_SETTING, | ||
| GAME_SETTING, | ||
| PLAYER_LIST, | ||
| SYSTEM_NOTICE, | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| package io.f1.backend.domain.game.dto; | ||
|
|
||
| public enum RoomEventType { | ||
| ENTER, | ||
| EXIT, | ||
| START, | ||
| END, | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,28 @@ | ||
| package io.f1.backend.domain.game.dto; | ||
|
|
||
| import io.f1.backend.domain.game.dto.response.PlayerListResponse; | ||
| import io.f1.backend.domain.game.dto.response.SystemNoticeResponse; | ||
|
|
||
| import lombok.Builder; | ||
| import lombok.Getter; | ||
|
|
||
| @Getter | ||
| public class RoomExitData { | ||
|
|
||
| private final String destination; | ||
| private final PlayerListResponse playerListResponses; | ||
| private final SystemNoticeResponse systemNoticeResponse; | ||
| private final boolean removedRoom; | ||
|
|
||
| @Builder | ||
| public RoomExitData( | ||
| String destination, | ||
| PlayerListResponse playerListResponses, | ||
| SystemNoticeResponse systemNoticeResponse, | ||
| boolean removedRoom) { | ||
| this.destination = destination; | ||
| this.playerListResponses = playerListResponses; | ||
| this.systemNoticeResponse = systemNoticeResponse; | ||
| this.removedRoom = removedRoom; | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| package io.f1.backend.domain.game.dto.response; | ||
|
|
||
| import java.time.Instant; | ||
|
|
||
| public record SystemNoticeResponse(String noticeMessage, Instant timestamp) {} |
Uh oh!
There was an error while loading. Please reload this page.