diff --git a/src/main/java/com/sajang/devracebackend/controller/AuthController.java b/src/main/java/com/sajang/devracebackend/controller/AuthController.java index de5533a..8f2668b 100644 --- a/src/main/java/com/sajang/devracebackend/controller/AuthController.java +++ b/src/main/java/com/sajang/devracebackend/controller/AuthController.java @@ -28,7 +28,7 @@ public class AuthController { @PutMapping(value = "/signup", consumes = MediaType.MULTIPART_FORM_DATA_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(summary = "회원가입 [jwt O]", description = "isImageChange==1 : 새 사진으로 변경 / isImageChange==0 : 기본 사진으로 변경") + @Operation(summary = "회원가입 [jwt O]", description = "isImageChange==0 : 기본 사진으로 변경 / isImageChange==1 : 새 사진으로 변경") public ResponseEntity> signup( @RequestPart(value="imageFile", required = false) MultipartFile imageFile, @RequestPart(value="signupRequestDto") SignupRequestDto signupRequestDto) throws IOException { // 여기서 Role을 USER로 교체해주지 않으면 다른 로그인 필수 API를 사용하지 못함. diff --git a/src/main/java/com/sajang/devracebackend/controller/RoomController.java b/src/main/java/com/sajang/devracebackend/controller/RoomController.java index 2b8dcea..f076444 100644 --- a/src/main/java/com/sajang/devracebackend/controller/RoomController.java +++ b/src/main/java/com/sajang/devracebackend/controller/RoomController.java @@ -6,7 +6,7 @@ import com.sajang.devracebackend.dto.room.RoomEnterRequestDto; import com.sajang.devracebackend.dto.room.RoomWaitRequestDto; import com.sajang.devracebackend.dto.room.RoomWaitResponseDto; -import com.sajang.devracebackend.dto.userroom.CheckIsPassDto; +import com.sajang.devracebackend.dto.userroom.UserPassRequestDto; import com.sajang.devracebackend.dto.userroom.RoomCheckAccessResponseDto; import com.sajang.devracebackend.dto.room.RoomCheckStateResponseDto; import com.sajang.devracebackend.dto.userroom.SolvingPageResponseDto; @@ -61,18 +61,27 @@ public ResponseEntity> loadSolvingPage(@Pat @GetMapping("/rooms/{roomId}/access-check") @Operation(summary = "문제풀이 페이지 접근허용 검사 [jwt O]", description = "isLeave == 0 or 1 or null") - public ResponseEntity> checkAccess(@PathVariable(value = "roomId") Long roomId) { // value=""를 작성해주어야만, Swagger에서 api테스트할때 이름값이 뜸. + public ResponseEntity> checkAccess(@PathVariable(value = "roomId") Long roomId) { RoomCheckAccessResponseDto roomCheckAccessResponseDto = userRoomService.checkAccess(roomId); return ResponseData.toResponseEntity(ResponseCode.READ_USERROOM, roomCheckAccessResponseDto); } @GetMapping("/rooms/{roomId}/state-check") @Operation(summary = "방 상태 검사 [jwt O]") - public ResponseEntity> checkState(@PathVariable(value = "roomId") Long roomId) { // value=""를 작성해주어야만, Swagger에서 api테스트할때 이름값이 뜸. + public ResponseEntity> checkState(@PathVariable(value = "roomId") Long roomId) { RoomCheckStateResponseDto roomCheckStateResponseDto = roomService.checkState(roomId); return ResponseData.toResponseEntity(ResponseCode.READ_USERROOM, roomCheckStateResponseDto); } + @PutMapping("/room/{roomId}") + @Operation(summary = "문제풀이 실패 및 성공 [jwt O]", description = "isRetry==0 : 첫풀이 경우 / isRetry==1 : 재풀이 경우") + public ResponseEntity passSolvingProblem( + @PathVariable(value = "roomId") Long roomId, + @RequestBody UserPassRequestDto userPassRequestDto) { + userRoomService.passSolvingProblem(roomId, userPassRequestDto); + return ResponseData.toResponseEntity(ResponseCode.UPDATE_USERROOM); + } + @MessageMapping("wait.enter") // 웹소켓 메시지 처리 (백엔드로 '/pub/wait.enter'를 호출시 이 브로커에서 처리) public void userWaitRoom(@Payload RoomWaitRequestDto roomWaitRequestDto) { // '/exchange/wait.exchange/waitingroom.{roomId}' 구독되어있는 프론트엔드에게 메세지 전달. @@ -80,14 +89,6 @@ public void userWaitRoom(@Payload RoomWaitRequestDto roomWaitRequestDto) { rabbitTemplate.convertAndSend(RabbitConfig.WAIT_EXCHANGE_NAME, "waitingroom." + roomWaitResponseDto.getRoomId(), roomWaitResponseDto); } - @PutMapping("/room/{roomId}") - public ResponseEntity success( - @RequestBody CheckIsPassDto checkIsPassDto, - @PathVariable(name ="roomId") Long roomId){ - userRoomService.checkIsPass(checkIsPassDto,roomId); - return ResponseData.toResponseEntity(ResponseCode.UPDATE_USERROOM); - } - // ========== STOMP Test 임시 용도 ========== // // @RabbitListener(queues = RabbitConfig.WAIT_QUEUE_NAME) // 프로듀서(백엔드)->컨슈머(프론트엔드) 과정에서 큐에 도착할 때, 메소드 자동 호출됨. diff --git a/src/main/java/com/sajang/devracebackend/dto/userroom/CheckIsPassDto.java b/src/main/java/com/sajang/devracebackend/dto/userroom/UserPassRequestDto.java similarity index 75% rename from src/main/java/com/sajang/devracebackend/dto/userroom/CheckIsPassDto.java rename to src/main/java/com/sajang/devracebackend/dto/userroom/UserPassRequestDto.java index 64a82ff..1f748b2 100644 --- a/src/main/java/com/sajang/devracebackend/dto/userroom/CheckIsPassDto.java +++ b/src/main/java/com/sajang/devracebackend/dto/userroom/UserPassRequestDto.java @@ -1,6 +1,5 @@ package com.sajang.devracebackend.dto.userroom; - import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Getter; @@ -10,7 +9,9 @@ @Getter @NoArgsConstructor @AllArgsConstructor -public class CheckIsPassDto { +public class UserPassRequestDto { + + private Integer isRetry; // 문제 재풀이 여부 private String code; private Integer isPass; diff --git a/src/main/java/com/sajang/devracebackend/service/UserRoomService.java b/src/main/java/com/sajang/devracebackend/service/UserRoomService.java index 17cf060..8f63016 100644 --- a/src/main/java/com/sajang/devracebackend/service/UserRoomService.java +++ b/src/main/java/com/sajang/devracebackend/service/UserRoomService.java @@ -3,7 +3,7 @@ import com.sajang.devracebackend.domain.Room; import com.sajang.devracebackend.domain.User; import com.sajang.devracebackend.dto.room.RoomEnterRequestDto; -import com.sajang.devracebackend.dto.userroom.CheckIsPassDto; +import com.sajang.devracebackend.dto.userroom.UserPassRequestDto; import com.sajang.devracebackend.dto.userroom.RoomCheckAccessResponseDto; import com.sajang.devracebackend.dto.userroom.SolvingPageResponseDto; @@ -12,5 +12,5 @@ public interface UserRoomService { void usersEnterRoom(Long roomId, RoomEnterRequestDto roomEnterRequestDto); SolvingPageResponseDto loadSolvingPage(Long roomId); RoomCheckAccessResponseDto checkAccess(Long roomId); - void checkIsPass(CheckIsPassDto checkIsPassDto, Long roomId); + void passSolvingProblem(Long roomId, UserPassRequestDto userPassRequestDto); } diff --git a/src/main/java/com/sajang/devracebackend/service/impl/ProblemServiceImpl.java b/src/main/java/com/sajang/devracebackend/service/impl/ProblemServiceImpl.java index 0f887b2..10e00b1 100644 --- a/src/main/java/com/sajang/devracebackend/service/impl/ProblemServiceImpl.java +++ b/src/main/java/com/sajang/devracebackend/service/impl/ProblemServiceImpl.java @@ -2,9 +2,9 @@ import com.sajang.devracebackend.domain.Problem; import com.sajang.devracebackend.repository.ProblemRepository; +import com.sajang.devracebackend.response.exception.exception404.NoSuchProblemException; import com.sajang.devracebackend.service.ProblemService; import lombok.RequiredArgsConstructor; -import org.json.simple.JSONObject; import org.jsoup.nodes.Element; import org.springframework.stereotype.Service; import org.jsoup.Jsoup; @@ -28,7 +28,12 @@ public class ProblemServiceImpl implements ProblemService { @Override public Problem crawlAndSaveProblem(Integer problemNumber) throws IOException { // Service 클래스 내에서만 호출되며 방 생성에 이용될 것이기에 Dto가 아닌, Entity를 반환받음. String url = "https://www.acmicpc.net/problem/" + problemNumber; - Document doc = Jsoup.connect(url).get(); + Document doc = null; + try { + doc = Jsoup.connect(url).get(); + } catch (Exception e) { + throw new NoSuchProblemException("problemNumber = " + problemNumber); + } Elements contents = doc.select("#problem-body"); // #problem-body에 접근 Elements contentHead = doc.select(".page-header h1"); // 문제 title 추출을 위한 page-header에 접근 diff --git a/src/main/java/com/sajang/devracebackend/service/impl/UserRoomServiceImpl.java b/src/main/java/com/sajang/devracebackend/service/impl/UserRoomServiceImpl.java index e91f504..4112124 100644 --- a/src/main/java/com/sajang/devracebackend/service/impl/UserRoomServiceImpl.java +++ b/src/main/java/com/sajang/devracebackend/service/impl/UserRoomServiceImpl.java @@ -7,7 +7,7 @@ import com.sajang.devracebackend.domain.enums.RoomState; import com.sajang.devracebackend.domain.mapping.UserRoom; import com.sajang.devracebackend.dto.room.RoomEnterRequestDto; -import com.sajang.devracebackend.dto.userroom.CheckIsPassDto; +import com.sajang.devracebackend.dto.userroom.UserPassRequestDto; import com.sajang.devracebackend.dto.userroom.RoomCheckAccessResponseDto; import com.sajang.devracebackend.dto.userroom.SolvingPageResponseDto; import com.sajang.devracebackend.repository.ChatRepository; @@ -123,27 +123,28 @@ public RoomCheckAccessResponseDto checkAccess(Long roomId) { @Transactional @Override - public void checkIsPass(CheckIsPassDto checkIsPassDto, Long roomId) { - User user = userService.findLoginUser(); // 현재 유저 데이터 가져오기 - Room room = roomService.findRoom(roomId); // 현재 입장된 방 데이터 가져오기 - UserRoom userRoom = userRoomRepository.findByUserAndRoom(user,room).orElseThrow( // api를 호출한 유저와 유저의 room 요소 가져오기 - () -> new NoSuchUserRoomException(String.format("userId = %d & roomId = %d", user.getId(), room.getId())) - ); - - userRoom.updateCode(checkIsPassDto.getCode()); - userRoom.updateIsPass(checkIsPassDto.getIsPass()); - userRoom.updateIsLeave(1); + public void passSolvingProblem(Long roomId, UserPassRequestDto userPassRequestDto) { + User user = userService.findLoginUser(); + Room room = roomService.findRoom(roomId); + UserRoom userRoom = userRoomRepository.findByUserAndRoom(user, room).orElseThrow( + ()->new NoSuchUserRoomException(String.format("userId = %d & roomId = %d", user.getId(), room.getId()))); + + userRoom.updateCode(userPassRequestDto.getCode()); + userRoom.updateIsLeave(1); userRoom.updateLeaveTime(LocalDateTime.now()); - if(checkIsPassDto.getIsPass() == 1){ - room.updateRanking(userRoom.getUser().getNickname()); // 성공시에만 닉네임 랭킹 등록. + if(userPassRequestDto.getIsRetry() == 0 || (userPassRequestDto.getIsRetry() == 1 && userPassRequestDto.getIsPass() == 1)) { + // 재풀이인 경우, 성공인 경우에만 성공여부를 업데이트함. (재풀이의 퇴장인 경우에는 성공여부를 업데이트 하지않음) + userRoom.updateIsPass(userPassRequestDto.getIsPass()); } - boolean isUsersLeave = userRoomRepository.findAllByRoom(room).stream() - .allMatch(users -> users.getIsLeave() == 1); //모든 유저의 isLeave를 찾아 1인지 확인 - if(isUsersLeave) { - room.updateRoomState(RoomState.FINISH); - } - } + // 밑의 랭킹 업데이트 파트는 STOMP 실시간 처리를 위하여, 주석처리 해두었음. +// if(userPassRequestDto.getIsPass() == 1) { +// room.updateRanking(user.getNickname()); // 성공시에만 닉네임 랭킹 등록. +// } + boolean isLeaveAllUsers = userRoomRepository.findAllByRoom(room).stream() + .allMatch(users -> users.getIsLeave() == 1); // 모든 유저의 isLeave 값이 1인지 확인 + if(isLeaveAllUsers == true) room.updateRoomState(RoomState.FINISH); + } } diff --git a/src/main/java/com/sajang/devracebackend/util/StringListConverter.java b/src/main/java/com/sajang/devracebackend/util/StringListConverter.java index 126c54b..23311bf 100644 --- a/src/main/java/com/sajang/devracebackend/util/StringListConverter.java +++ b/src/main/java/com/sajang/devracebackend/util/StringListConverter.java @@ -25,6 +25,6 @@ public List convertToEntityAttribute(String dbData) { // DB의 String if (dbData == null || dbData.equals("__null__")) { return new ArrayList<>(); } - return new ArrayList<>(Arrays.asList(dbData.split(SPLIT_CHAR))); // else 경우 + return new ArrayList<>(Arrays.asList(dbData.split(SPLIT_CHAR))); // else 경우 } } \ No newline at end of file