diff --git a/src/main/java/io/urdego/urdego_game_service/common/client/ContentServiceClient.java b/src/main/java/io/urdego/urdego_game_service/common/client/ContentServiceClient.java index 4e908c4..c966f19 100644 --- a/src/main/java/io/urdego/urdego_game_service/common/client/ContentServiceClient.java +++ b/src/main/java/io/urdego/urdego_game_service/common/client/ContentServiceClient.java @@ -7,14 +7,11 @@ import java.util.List; -@FeignClient(name = "content-service") +@FeignClient(name = "content-service", url = "${feign.client.config.content-service.url}") public interface ContentServiceClient { - @GetMapping("/random") - List getRandomContents(@RequestParam List players); + @GetMapping("/api/content-service/content") + ContentRes getContent(@RequestParam Long contentId); - @GetMapping("/content") - ContentRes getContent(@RequestParam String contentId); - - @GetMapping("/urdego-content") + @GetMapping("/api/content-service/urdego-content") List getUrdegoContents(@RequestParam int counts); } diff --git a/src/main/java/io/urdego/urdego_game_service/common/client/dto/ContentRes.java b/src/main/java/io/urdego/urdego_game_service/common/client/dto/ContentRes.java index b071081..f27a0b9 100644 --- a/src/main/java/io/urdego/urdego_game_service/common/client/dto/ContentRes.java +++ b/src/main/java/io/urdego/urdego_game_service/common/client/dto/ContentRes.java @@ -1,9 +1,11 @@ package io.urdego.urdego_game_service.common.client.dto; public record ContentRes( - String contentId, + Long contentId, + String contentName, + String address, double latitude, double longitude, String hint ) { -} +} \ No newline at end of file diff --git a/src/main/java/io/urdego/urdego_game_service/controller/game/GameController.java b/src/main/java/io/urdego/urdego_game_service/controller/game/GameController.java index fa6e806..5fba39a 100644 --- a/src/main/java/io/urdego/urdego_game_service/controller/game/GameController.java +++ b/src/main/java/io/urdego/urdego_game_service/controller/game/GameController.java @@ -1,5 +1,7 @@ package io.urdego.urdego_game_service.controller.game; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; import io.urdego.urdego_game_service.controller.game.dto.request.GameCreateReq; import io.urdego.urdego_game_service.controller.game.dto.response.GameCreateRes; import io.urdego.urdego_game_service.domain.game.service.GameService; @@ -19,6 +21,8 @@ public class GameController { private final GameService gameService; // 게임 생성 + @Tag(name = "게임 API") + @Operation(summary = "게임 생성", description = "roomId로 게임 생성") @PostMapping("/game/start") public ResponseEntity startGame(@RequestBody GameCreateReq request) { GameCreateRes response = gameService.createGame(request); diff --git a/src/main/java/io/urdego/urdego_game_service/controller/room/RoomController.java b/src/main/java/io/urdego/urdego_game_service/controller/room/RoomController.java index 8a329b1..ceab247 100644 --- a/src/main/java/io/urdego/urdego_game_service/controller/room/RoomController.java +++ b/src/main/java/io/urdego/urdego_game_service/controller/room/RoomController.java @@ -1,15 +1,17 @@ package io.urdego.urdego_game_service.controller.room; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; import io.urdego.urdego_game_service.controller.room.dto.request.RoomCreateReq; import io.urdego.urdego_game_service.controller.room.dto.response.RoomCreateRes; +import io.urdego.urdego_game_service.controller.room.dto.response.RoomInfoRes; import io.urdego.urdego_game_service.domain.room.service.RoomService; import lombok.RequiredArgsConstructor; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; + +import java.util.List; @RestController @RequiredArgsConstructor @@ -19,10 +21,21 @@ public class RoomController { private final RoomService roomService; // 대기방 생성 + @Tag(name = "대기방 API") + @Operation(summary = "대기방 생성", description = "방장이 입력한 정보로 대기방 생성") @PostMapping("/room/create") public ResponseEntity createRoom(@RequestBody RoomCreateReq request) { RoomCreateRes response = roomService.createRoom(request); return new ResponseEntity<>(response, HttpStatus.CREATED); } + // 대기방 목록 조회 + @Tag(name = "대기방 API") + @Operation(summary = "대기방 목록 조회", description = "현재 생성되어 있는 대기방 목록 전체 조회") + @GetMapping("/room/list") + public ResponseEntity> viewRooms() { + List response = roomService.getRoomList(); + return new ResponseEntity<>(response, HttpStatus.OK); + } + } diff --git a/src/main/java/io/urdego/urdego_game_service/controller/room/RoomSocketController.java b/src/main/java/io/urdego/urdego_game_service/controller/room/RoomSocketController.java index 97fe4c4..102a1b8 100644 --- a/src/main/java/io/urdego/urdego_game_service/controller/room/RoomSocketController.java +++ b/src/main/java/io/urdego/urdego_game_service/controller/room/RoomSocketController.java @@ -2,7 +2,7 @@ import io.urdego.urdego_game_service.controller.room.dto.request.ContentSelectReq; import io.urdego.urdego_game_service.controller.room.dto.request.PlayerReq; -import io.urdego.urdego_game_service.controller.room.dto.response.RoomInfoRes; +import io.urdego.urdego_game_service.controller.room.dto.response.PlayerRes; import io.urdego.urdego_game_service.domain.room.service.RoomService; import lombok.RequiredArgsConstructor; import org.springframework.messaging.handler.annotation.MessageMapping; @@ -19,7 +19,7 @@ public class RoomSocketController { // 친구 초대 @MessageMapping("/room/player/invite") public void invitePlayer(PlayerReq request) { - RoomInfoRes response = roomService.joinRoom(request); + PlayerRes response = roomService.joinRoom(request); messagingTemplate.convertAndSend("/game-service/sub/" + response.roomId(), response); } @@ -32,7 +32,7 @@ public void selectContent(ContentSelectReq request) { // 플레이어 삭제 @MessageMapping("/room/player/remove") public void removePlayer(PlayerReq request) { - RoomInfoRes response = roomService.removePlayer(request); + PlayerRes response = roomService.removePlayer(request); messagingTemplate.convertAndSend("/game-service/sub/" + response.roomId(), response); } } diff --git a/src/main/java/io/urdego/urdego_game_service/controller/room/dto/request/RoomCreateReq.java b/src/main/java/io/urdego/urdego_game_service/controller/room/dto/request/RoomCreateReq.java index 8ca8aa9..23984a3 100644 --- a/src/main/java/io/urdego/urdego_game_service/controller/room/dto/request/RoomCreateReq.java +++ b/src/main/java/io/urdego/urdego_game_service/controller/room/dto/request/RoomCreateReq.java @@ -2,6 +2,7 @@ public record RoomCreateReq( String userId, + String roomName, int maxPlayers, int totalRounds, int timer diff --git a/src/main/java/io/urdego/urdego_game_service/controller/room/dto/response/PlayerRes.java b/src/main/java/io/urdego/urdego_game_service/controller/room/dto/response/PlayerRes.java new file mode 100644 index 0000000..c02b68a --- /dev/null +++ b/src/main/java/io/urdego/urdego_game_service/controller/room/dto/response/PlayerRes.java @@ -0,0 +1,20 @@ +package io.urdego.urdego_game_service.controller.room.dto.response; + +import io.urdego.urdego_game_service.common.enums.Status; +import io.urdego.urdego_game_service.domain.room.entity.Room; + +import java.util.List; + +public record PlayerRes( + String roomId, + Status status, + List currentPlayers +) { + public static PlayerRes from(Room room) { + return new PlayerRes( + room.getRoomId(), + room.getStatus(), + room.getCurrentPlayers() + ); + } +} diff --git a/src/main/java/io/urdego/urdego_game_service/controller/room/dto/response/RoomInfoRes.java b/src/main/java/io/urdego/urdego_game_service/controller/room/dto/response/RoomInfoRes.java index ad9e3b0..2944af0 100644 --- a/src/main/java/io/urdego/urdego_game_service/controller/room/dto/response/RoomInfoRes.java +++ b/src/main/java/io/urdego/urdego_game_service/controller/room/dto/response/RoomInfoRes.java @@ -3,18 +3,22 @@ import io.urdego.urdego_game_service.common.enums.Status; import io.urdego.urdego_game_service.domain.room.entity.Room; -import java.util.List; - public record RoomInfoRes( String roomId, Status status, - List currentPlayers + String roomName, + int maxPlayers, + int currentPlayersCount, + int totalRounds ) { public static RoomInfoRes from(Room room) { return new RoomInfoRes( room.getRoomId(), room.getStatus(), - room.getCurrentPlayers() + room.getRoomName(), + room.getMaxPlayers(), + room.getCurrentPlayers().size(), + room.getTotalRounds() ); } } diff --git a/src/main/java/io/urdego/urdego_game_service/controller/round/RoundSocketController.java b/src/main/java/io/urdego/urdego_game_service/controller/round/RoundSocketController.java index bc9eb42..871a737 100644 --- a/src/main/java/io/urdego/urdego_game_service/controller/round/RoundSocketController.java +++ b/src/main/java/io/urdego/urdego_game_service/controller/round/RoundSocketController.java @@ -21,7 +21,7 @@ public class RoundSocketController { @MessageMapping("/round/question") public void giveQuestion(QuestionReq request) { QuestionRes response = roundService.getQuestion(request); - messagingTemplate.convertAndSend("game-service/sub/" + response.roomId(), response); + messagingTemplate.convertAndSend("/game-service/sub/" + response.roomId(), response); } // 플레이어 정답 제출 diff --git a/src/main/java/io/urdego/urdego_game_service/domain/game/service/GameServiceImpl.java b/src/main/java/io/urdego/urdego_game_service/domain/game/service/GameServiceImpl.java index 26b8c94..f980578 100644 --- a/src/main/java/io/urdego/urdego_game_service/domain/game/service/GameServiceImpl.java +++ b/src/main/java/io/urdego/urdego_game_service/domain/game/service/GameServiceImpl.java @@ -54,7 +54,7 @@ public GameCreateRes createGame(GameCreateReq request) { // Question 생성 for (int roundNum = 1; roundNum <= room.getTotalRounds(); roundNum++) { - Question question = roundService.createQuestion(game.getRoomId()); + Question question = roundService.createQuestion(game.getRoomId(), roundNum); game.getQuestionIds().add(question.getQuestionId()); } @@ -109,8 +109,17 @@ public Game updateGameStatusById(String gameId, Status status) { @Transactional(readOnly = true) @Override public Game findGameById(String gameId) { - return gameRepository.findById(gameId) + Game game = gameRepository.findById(gameId) .orElseThrow(() -> new GameException(ExceptionMessage.GAME_NOT_FOUND)); + + if (game.getRoundScores() == null) { + game.setRoundScores(new HashMap<>()); + } + if (game.getTotalScores() == null) { + game.setTotalScores(new HashMap<>()); + } + + return game; } // 라운드 점수 업뎃 diff --git a/src/main/java/io/urdego/urdego_game_service/domain/room/entity/Room.java b/src/main/java/io/urdego/urdego_game_service/domain/room/entity/Room.java index fb58c5c..e4f1e7c 100644 --- a/src/main/java/io/urdego/urdego_game_service/domain/room/entity/Room.java +++ b/src/main/java/io/urdego/urdego_game_service/domain/room/entity/Room.java @@ -16,6 +16,7 @@ public class Room { @Id private String roomId; + private String roomName; private Status status; private int maxPlayers; private int totalRounds; @@ -25,8 +26,9 @@ public class Room { // private String gameType; @Builder - public Room(String roomId, Status status, int maxPlayers, int totalRounds, int timer, List currentPlayers, Map> playerContents) { + public Room(String roomId, String roomName, Status status, int maxPlayers, int totalRounds, int timer, List currentPlayers, Map> playerContents) { this.roomId = roomId; + this.roomName = roomName; this.status = status; this.maxPlayers = maxPlayers; this.totalRounds = totalRounds; diff --git a/src/main/java/io/urdego/urdego_game_service/domain/room/service/RoomService.java b/src/main/java/io/urdego/urdego_game_service/domain/room/service/RoomService.java index 4709a51..5a0d2d7 100644 --- a/src/main/java/io/urdego/urdego_game_service/domain/room/service/RoomService.java +++ b/src/main/java/io/urdego/urdego_game_service/domain/room/service/RoomService.java @@ -3,25 +3,31 @@ import io.urdego.urdego_game_service.controller.room.dto.request.ContentSelectReq; import io.urdego.urdego_game_service.controller.room.dto.request.PlayerReq; import io.urdego.urdego_game_service.controller.room.dto.request.RoomCreateReq; +import io.urdego.urdego_game_service.controller.room.dto.response.PlayerRes; import io.urdego.urdego_game_service.controller.room.dto.response.RoomCreateRes; import io.urdego.urdego_game_service.controller.room.dto.response.RoomInfoRes; import io.urdego.urdego_game_service.common.enums.Status; import io.urdego.urdego_game_service.domain.room.entity.Room; import org.springframework.transaction.annotation.Transactional; +import java.util.List; + public interface RoomService { // 방 생성 RoomCreateRes createRoom(RoomCreateReq request); + // 대기방 리스트 조회 + List getRoomList(); + // 방 참가 - RoomInfoRes joinRoom(PlayerReq request); + PlayerRes joinRoom(PlayerReq request); // 컨텐츠 등록 void registerContents(ContentSelectReq request); // 플레이어 삭제 - RoomInfoRes removePlayer(PlayerReq request); + PlayerRes removePlayer(PlayerReq request); // 방 상태 변경 Room updateRoomStatusById(String roomId, Status status); diff --git a/src/main/java/io/urdego/urdego_game_service/domain/room/service/RoomServiceImpl.java b/src/main/java/io/urdego/urdego_game_service/domain/room/service/RoomServiceImpl.java index 2a0d5e1..a28e9b7 100644 --- a/src/main/java/io/urdego/urdego_game_service/domain/room/service/RoomServiceImpl.java +++ b/src/main/java/io/urdego/urdego_game_service/domain/room/service/RoomServiceImpl.java @@ -3,6 +3,7 @@ import io.urdego.urdego_game_service.controller.room.dto.request.ContentSelectReq; import io.urdego.urdego_game_service.controller.room.dto.request.PlayerReq; import io.urdego.urdego_game_service.controller.room.dto.request.RoomCreateReq; +import io.urdego.urdego_game_service.controller.room.dto.response.PlayerRes; import io.urdego.urdego_game_service.controller.room.dto.response.RoomCreateRes; import io.urdego.urdego_game_service.controller.room.dto.response.RoomInfoRes; import io.urdego.urdego_game_service.common.enums.Status; @@ -11,13 +12,11 @@ import io.urdego.urdego_game_service.domain.room.entity.Room; import io.urdego.urdego_game_service.domain.room.repository.RoomRepository; import lombok.RequiredArgsConstructor; +import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.UUID; +import java.util.*; @Service @Transactional @@ -25,6 +24,8 @@ public class RoomServiceImpl implements RoomService { private final RoomRepository roomRepository; + private final RedisTemplate redisTemplate; + // 대기방 생성 @Override @@ -32,8 +33,12 @@ public RoomCreateRes createRoom(RoomCreateReq request) { List currentPlayers = new ArrayList<>(); currentPlayers.add(request.userId()); + String roomName = (request.roomName() == null || request.roomName().isBlank()) + ? "어데고 게임방" : request.roomName(); + Room room = Room.builder() .roomId(UUID.randomUUID().toString()) + .roomName(roomName) .status(Status.WAITING) .maxPlayers(request.maxPlayers()) .totalRounds(request.totalRounds()) @@ -47,9 +52,24 @@ public RoomCreateRes createRoom(RoomCreateReq request) { return RoomCreateRes.from(room); } + // 대기방 리스트 조회 + @Override + public List getRoomList() { + Iterable rooms = roomRepository.findAll(); + List roomList = new ArrayList<>(); + + for (Room room : rooms) { + if (room != null) { + roomList.add(RoomInfoRes.from(room)); + } + } + + return roomList; + } + // 대기방 참여 @Override - public RoomInfoRes joinRoom(PlayerReq request) { + public PlayerRes joinRoom(PlayerReq request) { Room room = findRoomById(request.roomId()); if (room.getCurrentPlayers().size() >= room.getMaxPlayers()) { throw new RoomException(ExceptionMessage.ROOM_FULL); @@ -58,7 +78,7 @@ public RoomInfoRes joinRoom(PlayerReq request) { roomRepository.save(room); - return RoomInfoRes.from(room); + return PlayerRes.from(room); } // 컨텐츠 등록 @@ -75,7 +95,7 @@ public void registerContents(ContentSelectReq request) { // 플레이어 삭제 @Override - public RoomInfoRes removePlayer(PlayerReq request) { + public PlayerRes removePlayer(PlayerReq request) { Room room = findRoomById(request.roomId()); if (!room.getCurrentPlayers().contains(request.userId().toString())) { @@ -87,7 +107,7 @@ public RoomInfoRes removePlayer(PlayerReq request) { roomRepository.save(room); - return RoomInfoRes.from(room); + return PlayerRes.from(room); } // 대기방 상태 변경 diff --git a/src/main/java/io/urdego/urdego_game_service/domain/round/entity/Question.java b/src/main/java/io/urdego/urdego_game_service/domain/round/entity/Question.java index ac27db7..d0f7b74 100644 --- a/src/main/java/io/urdego/urdego_game_service/domain/round/entity/Question.java +++ b/src/main/java/io/urdego/urdego_game_service/domain/round/entity/Question.java @@ -22,8 +22,8 @@ public class Question { private List contents; @Builder - public Question(String questionId, String roomId, int roundNum, double latitude, double longitude, String hint, List contents) { - this.questionId = questionId; + public Question(String roomId, int roundNum, double latitude, double longitude, String hint, List contents) { + this.questionId = roomId + ":" + roundNum; this.roomId = roomId; this.roundNum = roundNum; this.latitude = latitude; diff --git a/src/main/java/io/urdego/urdego_game_service/domain/round/repository/QuestionRepository.java b/src/main/java/io/urdego/urdego_game_service/domain/round/repository/QuestionRepository.java index cf21ec2..9193ccb 100644 --- a/src/main/java/io/urdego/urdego_game_service/domain/round/repository/QuestionRepository.java +++ b/src/main/java/io/urdego/urdego_game_service/domain/round/repository/QuestionRepository.java @@ -9,7 +9,7 @@ @Repository public interface QuestionRepository extends CrudRepository { - Optional findByRoomId(String roomId); + Optional findByRoomIdAndRoundNum(String roomId, int roundNum); List findAllByRoomId(String roomId); } diff --git a/src/main/java/io/urdego/urdego_game_service/domain/round/service/RoundService.java b/src/main/java/io/urdego/urdego_game_service/domain/round/service/RoundService.java index 9bc7eef..a176886 100644 --- a/src/main/java/io/urdego/urdego_game_service/domain/round/service/RoundService.java +++ b/src/main/java/io/urdego/urdego_game_service/domain/round/service/RoundService.java @@ -11,7 +11,7 @@ public interface RoundService { // 문제 생성 - Question createQuestion(String roomId); + Question createQuestion(String roomId, int roundNum); // 문제 출제 QuestionRes getQuestion(QuestionReq request); diff --git a/src/main/java/io/urdego/urdego_game_service/domain/round/service/RoundServiceImpl.java b/src/main/java/io/urdego/urdego_game_service/domain/round/service/RoundServiceImpl.java index 1c281f6..6b82c76 100644 --- a/src/main/java/io/urdego/urdego_game_service/domain/round/service/RoundServiceImpl.java +++ b/src/main/java/io/urdego/urdego_game_service/domain/round/service/RoundServiceImpl.java @@ -35,7 +35,7 @@ public class RoundServiceImpl implements RoundService { // 문제 생성 @Override - public Question createQuestion(String roomId) { + public Question createQuestion(String roomId, int roundNum) { Room room = roomService.findRoomById(roomId); // 해당 게임의 기존 문제 조회 @@ -50,7 +50,7 @@ public Question createQuestion(String roomId) { if (allContents.size() < 3) { int needed = 3 - allContents.size(); List serviceContents = contentServiceClient.getUrdegoContents(needed); - serviceContents.forEach(content -> allContents.add(content.contentId())); + serviceContents.forEach(content -> allContents.add(content.contentId().toString())); } Collections.shuffle(allContents); @@ -58,21 +58,22 @@ public Question createQuestion(String roomId) { do { // 첫 번째 컨텐츠 기준으로 정답 설정 - ContentRes firstContent = contentServiceClient.getContent(allContents.get(0)); + ContentRes firstContent = contentServiceClient.getContent(Long.valueOf(allContents.get(0))); double targetLatitude = firstContent.latitude(); double targetLongitude = firstContent.longitude(); // 동일한 위치를 가진 컨텐츠들로 필터링 List selectedContents = allContents.stream() .filter(contentId -> { - ContentRes content = contentServiceClient.getContent(contentId); + ContentRes content = contentServiceClient.getContent(Long.valueOf(contentId)); return content.latitude() == targetLatitude && content.longitude() == targetLongitude; }) .limit(3) .collect(Collectors.toList()); newQuestion = Question.builder() - .questionId(UUID.randomUUID().toString()) + .roomId(roomId) + .roundNum(roundNum) .latitude(targetLatitude) .longitude(targetLongitude) .hint(firstContent.hint()) @@ -86,7 +87,7 @@ public Question createQuestion(String roomId) { // 문제 출제 @Override public QuestionRes getQuestion(QuestionReq request) { - Question question = findQuestionByRoomId(request.roomId()); + Question question = findQuestionByRoomIdAndRoundNum(request.roomId(), request.roundNum()); return QuestionRes.from(question); } @@ -120,8 +121,9 @@ public List findAnswersByQuestionId(String questionId) { } // roomId로 문제 정보 조회 - private Question findQuestionByRoomId(String roomId) { - return questionRepository.findByRoomId(roomId) + private Question findQuestionByRoomIdAndRoundNum(String roomId, int roundNum) { + String questionId = roomId + ":" + roundNum; + return questionRepository.findById(questionId) .orElseThrow(() -> new QuestionException(ExceptionMessage.QUESTION_NOT_FOUND)); }