diff --git a/src/main/java/com/api/TaveShot/domain/recommend/controller/RecommendController.java b/src/main/java/com/api/TaveShot/domain/recommend/controller/RecommendController.java index ec0a0bb..2fd5c2e 100644 --- a/src/main/java/com/api/TaveShot/domain/recommend/controller/RecommendController.java +++ b/src/main/java/com/api/TaveShot/domain/recommend/controller/RecommendController.java @@ -1,6 +1,7 @@ package com.api.TaveShot.domain.recommend.controller; import com.api.TaveShot.domain.post.post.dto.response.PostResponse; +import com.api.TaveShot.domain.recommend.dto.RecProRequestDto; import com.api.TaveShot.domain.recommend.dto.RecProResponseDto; import com.api.TaveShot.domain.recommend.dto.RecResponseDto; import com.api.TaveShot.domain.recommend.service.RecommendService; @@ -8,6 +9,7 @@ import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.parameters.RequestBody; import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.responses.ApiResponses; import lombok.RequiredArgsConstructor; @@ -15,6 +17,7 @@ import org.springframework.http.MediaType; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import java.io.IOException; @@ -30,9 +33,7 @@ public class RecommendController { @Operation(summary = "사용자 기반 문제 추천", description = "해당 유저가 푼 문제들을 바탕으로" + " 같은 티어의 사용자가 푼 문제들을 관련성이 높은 순으로 추천합니다.") @ApiResponses(value = { - @ApiResponse(responseCode = "200", description = "추천 성공", - content = @Content(mediaType = MediaType.MULTIPART_FORM_DATA_VALUE, - schema = @Schema(implementation = PostResponse.class))) + @ApiResponse(responseCode = "200", description = "추천 성공") }) @GetMapping("/rival") public SuccessResponse getUserBasedProList() throws IOException { @@ -42,13 +43,11 @@ public SuccessResponse getUserBasedProList() throws IOException @Operation(summary = "태그 관련 문제 추천", description = "원하는 문제와 태그가 같은 관련성이 높은 문제를 추천합니다.") @ApiResponses(value = { - @ApiResponse(responseCode = "200", description = "추천 성공", - content = @Content(mediaType = MediaType.MULTIPART_FORM_DATA_VALUE, - schema = @Schema(implementation = PostResponse.class))) + @ApiResponse(responseCode = "200", description = "추천 성공") }) @GetMapping("/problem") - public SuccessResponse getSolvedProList() throws IOException { - RecResponseDto responseDto = recommendService.getListByProblem(); + public SuccessResponse getSolvedProList(@RequestParam(value = "solvedRecentId") int solvedNumber) throws IOException { + RecResponseDto responseDto = recommendService.getListByProblem(solvedNumber); return new SuccessResponse<>(responseDto); } } diff --git a/src/main/java/com/api/TaveShot/domain/recommend/dto/UserCrawlingDto.java b/src/main/java/com/api/TaveShot/domain/recommend/dto/UserCrawlingDto.java index f7d9a20..0c9a789 100644 --- a/src/main/java/com/api/TaveShot/domain/recommend/dto/UserCrawlingDto.java +++ b/src/main/java/com/api/TaveShot/domain/recommend/dto/UserCrawlingDto.java @@ -1,5 +1,6 @@ package com.api.TaveShot.domain.recommend.dto; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Builder; import lombok.Getter; import lombok.ToString; @@ -10,9 +11,19 @@ @Builder @ToString public class UserCrawlingDto { + + @Schema(description = "유저 순위") private String rank; + + @Schema(description = "맞은 문제 수") private String rightCnt; + + @Schema(description = "틀린 문제 수") private String wrongCnt; + + @Schema(description = "유저 레벨") private String tier; + + @Schema(description = "맞은 문제 리스트") private List solvedProblemList; } diff --git a/src/main/java/com/api/TaveShot/domain/recommend/service/RecommendService.java b/src/main/java/com/api/TaveShot/domain/recommend/service/RecommendService.java index 8d2bf98..4d34039 100644 --- a/src/main/java/com/api/TaveShot/domain/recommend/service/RecommendService.java +++ b/src/main/java/com/api/TaveShot/domain/recommend/service/RecommendService.java @@ -2,10 +2,9 @@ import com.api.TaveShot.domain.Member.domain.Member; import com.api.TaveShot.domain.Member.repository.MemberRepository; -import com.api.TaveShot.domain.recommend.domain.TierCount; -import com.api.TaveShot.domain.recommend.dto.RecResponseDto; -import com.api.TaveShot.domain.recommend.dto.UserCrawlingDto; -import com.api.TaveShot.domain.recommend.dto.RecProResponseDto; +import com.api.TaveShot.domain.recommend.domain.ProblemElement; +import com.api.TaveShot.domain.recommend.dto.*; +import com.api.TaveShot.domain.recommend.repository.ProblemElementRepository; import com.api.TaveShot.domain.recommend.repository.TierCountRepository; import com.api.TaveShot.global.exception.ApiException; import com.api.TaveShot.global.exception.ErrorType; @@ -18,6 +17,10 @@ import org.springframework.web.reactive.function.client.WebClient; import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; @Service @Slf4j @@ -27,6 +30,7 @@ public class RecommendService { private final CrawlingService crawlingService; private final MemberRepository memberRepository; private final TierCountRepository tierCountRepository; + private final ProblemElementRepository problemElementRepository; @Value("${lambda.secret.url1}") private String lambda1; @@ -36,10 +40,7 @@ public class RecommendService { // 사용자 기반 추천 서비스 public RecResponseDto getListByUser() throws IOException { - Member currentMember1 = getCurrentMember(); - String bojName = currentMember1.getBojName(); - - UserCrawlingDto dto = crawlingService.getUserInfo(bojName); + UserCrawlingDto dto = getUserInfo(); WebClient webClient = WebClient.builder() .baseUrl(lambda1) @@ -53,54 +54,128 @@ public RecResponseDto getListByUser() throws IOException { Integer tierCount = tierCountRepository.findByTier(Integer.parseInt(dto.getTier())); + List proDetailResponseDtos = getProblemDetail(proList); + RecResponseDto responseDto = RecResponseDto.builder() .rivalCnt(Integer.toString(tierCount)) .rightCnt(dto.getRightCnt()) .wrongCnt(dto.getWrongCnt()) .userRank(dto.getRank()) - .result(proList.getResult()) + .result(proDetailResponseDtos) .build(); return responseDto; } // 문제 기반 추천 서비스 - public RecResponseDto getListByProblem() throws IOException { - Member currentMember2 = getCurrentMember(); - String bojName = currentMember2.getBojName(); + public RecResponseDto getListByProblem(int solvedRecentId) throws IOException { - UserCrawlingDto dto = crawlingService.getUserInfo(bojName); + UserCrawlingDto dto = getUserInfo(); WebClient webClient = WebClient.builder() .baseUrl(lambda2) .build(); + RecProRequestDto requestDto = RecProRequestDto.builder() + .solvedRecentId(solvedRecentId) + .build(); + RecProResponseDto proList = webClient.post() - .body(BodyInserters.fromValue(dto)) + .body(BodyInserters.fromValue(requestDto)) .retrieve() .bodyToMono(RecProResponseDto.class) .block(); Integer tierCount = tierCountRepository.findByTier(Integer.parseInt(dto.getTier())); + List proDetailResponseDtos = getProblemDetail(proList); + RecResponseDto responseDto = RecResponseDto.builder() .rivalCnt(Integer.toString(tierCount)) .rightCnt(dto.getRightCnt()) .wrongCnt(dto.getWrongCnt()) .userRank(dto.getRank()) - .result(proList.getResult()) + .result(proDetailResponseDtos) .build(); return responseDto; } - private Member getCurrentMember(){ + public UserCrawlingDto getUserInfo() throws IOException { + Member currentMember2 = getCurrentMember(); + String bojName = currentMember2.getBojName(); +// String bojName = "wjdrhs3473"; + UserCrawlingDto dto = crawlingService.getUserInfo(bojName); + + return dto; + } + + private Member getCurrentMember(){ Member currentMember = SecurityUtil.getCurrentMember(); Long currentMemberId = currentMember.getId(); return memberRepository.findById(currentMemberId) .orElseThrow(() -> new ApiException(ErrorType._USER_NOT_FOUND_DB)); } + private String getTierName(Integer bojLevel){ + String[] tiers = {"BRONZE", "SILVER", "GOLD", "PLATINUM", "DIAMOND", "RUBY", "MASTER"}; + if(bojLevel <= 5) + return tiers[0]; + else if(bojLevel <= 10) + return tiers[1]; + else if(bojLevel <= 15) + return tiers[2]; + else if(bojLevel <= 20) + return tiers[3]; + else if(bojLevel <= 25) + return tiers[4]; + else if(bojLevel <= 30) + return tiers[5]; + + return tiers[6]; + } + + private List extractWords(String bojTags){ + List tags = new ArrayList<>(); + + Pattern pattern = Pattern.compile("\\b\\w+\\b"); + Matcher matcher = pattern.matcher(bojTags); + + while(matcher.find()){ + tags.add(matcher.group()); + } + + return tags; + } + + private List getProblemDetail(RecProResponseDto proList){ + List result = proList.getResult(); + List proDetailResponseDto = new ArrayList<>(); + + // 문제 세부 정보 찾기 + for(int i=0;i<15;i++){ + Integer num = Integer.parseInt(result.get(i)); + log.info("num:{}", num); + try { + ProblemElement problemElement = problemElementRepository.findByProblemId(num); + log.info("{}, {}, {}", problemElement.getProblemId(), problemElement.getBojLevel(), problemElement.getBojKey()); + String tierName = getTierName(problemElement.getBojLevel()); + List tags = extractWords(problemElement.getBojKey()); + RecProDetailResponseDto detailResponseDto = RecProDetailResponseDto.builder() + .title(problemElement.getTitle()) + .problemId(String.valueOf(num)) + .tier(tierName) + .bojTag(tags) + .build(); + proDetailResponseDto.add(detailResponseDto); + } catch(Exception e){ + continue; + } + + } + + return proDetailResponseDto; + } }