From 55b81e993b161087f3b9cee253d39c5cbab8d905 Mon Sep 17 00:00:00 2001 From: rowing0328 Date: Fri, 14 Feb 2025 18:30:04 +0900 Subject: [PATCH 01/12] =?UTF-8?q?=F0=9F=93=9B=20=ED=8C=8C=EC=9D=BC=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=20:=20=ED=80=B4=EC=A6=88=20=EC=B9=B4?= =?UTF-8?q?=ED=85=8C=EA=B3=A0=EB=A6=AC=20=ED=8C=A8=ED=82=A4=EC=A7=80?= =?UTF-8?q?=EB=AA=85=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../itzip/feature/csQuiz/service/QuizService.java | 2 +- .../itzip/feature/csQuiz/service/QuizServiceImpl.java | 4 +--- .../sub/{quizCategory => quizcategory}/FindQuizCategory.java | 2 +- .../{quizCategory => quizcategory}/FindQuizCategoryImpl.java | 2 +- 4 files changed, 4 insertions(+), 6 deletions(-) rename src/main/java/darkoverload/itzip/feature/csQuiz/service/sub/{quizCategory => quizcategory}/FindQuizCategory.java (85%) rename src/main/java/darkoverload/itzip/feature/csQuiz/service/sub/{quizCategory => quizcategory}/FindQuizCategoryImpl.java (96%) diff --git a/src/main/java/darkoverload/itzip/feature/csQuiz/service/QuizService.java b/src/main/java/darkoverload/itzip/feature/csQuiz/service/QuizService.java index 6e14aa91..d67f7434 100644 --- a/src/main/java/darkoverload/itzip/feature/csQuiz/service/QuizService.java +++ b/src/main/java/darkoverload/itzip/feature/csQuiz/service/QuizService.java @@ -3,7 +3,7 @@ import darkoverload.itzip.feature.csQuiz.service.sub.quiz.CheckAnswer; import darkoverload.itzip.feature.csQuiz.service.sub.quiz.CreateQuiz; import darkoverload.itzip.feature.csQuiz.service.sub.quiz.GivenPointToQuiz; -import darkoverload.itzip.feature.csQuiz.service.sub.quizCategory.FindQuizCategory; +import darkoverload.itzip.feature.csQuiz.service.sub.quizcategory.FindQuizCategory; import darkoverload.itzip.feature.csQuiz.service.sub.quizzes.FindQiuzQuery; //컨트롤러가 사용할 service계층 진입점 상속을 통해서 서브 시스템들을 받아온다. diff --git a/src/main/java/darkoverload/itzip/feature/csQuiz/service/QuizServiceImpl.java b/src/main/java/darkoverload/itzip/feature/csQuiz/service/QuizServiceImpl.java index 1d79ee29..06f79786 100644 --- a/src/main/java/darkoverload/itzip/feature/csQuiz/service/QuizServiceImpl.java +++ b/src/main/java/darkoverload/itzip/feature/csQuiz/service/QuizServiceImpl.java @@ -8,11 +8,10 @@ import darkoverload.itzip.feature.csQuiz.controller.response.QuizDetailResponse; import darkoverload.itzip.feature.csQuiz.entity.QuizCategory; import darkoverload.itzip.feature.csQuiz.entity.UserQuizStatus; -import darkoverload.itzip.feature.csQuiz.repository.quiz.QuizRepository; import darkoverload.itzip.feature.csQuiz.service.sub.quiz.CheckAnswer; import darkoverload.itzip.feature.csQuiz.service.sub.quiz.CreateQuiz; import darkoverload.itzip.feature.csQuiz.service.sub.quiz.GivenPointToQuiz; -import darkoverload.itzip.feature.csQuiz.service.sub.quizCategory.FindQuizCategory; +import darkoverload.itzip.feature.csQuiz.service.sub.quizcategory.FindQuizCategory; import darkoverload.itzip.feature.csQuiz.service.sub.quizzes.FindQiuzQuery; import darkoverload.itzip.feature.jwt.infrastructure.CustomUserDetails; import lombok.RequiredArgsConstructor; @@ -42,7 +41,6 @@ public class QuizServiceImpl implements QuizService { @Qualifier("createQuizImpl") private final CreateQuiz createQuiz; - private final QuizRepository quizRepository; /** * 주어진 필터와 정렬 기준, 사용자 정보를 기반으로 퀴즈 목록을 조회하는 메서드 diff --git a/src/main/java/darkoverload/itzip/feature/csQuiz/service/sub/quizCategory/FindQuizCategory.java b/src/main/java/darkoverload/itzip/feature/csQuiz/service/sub/quizcategory/FindQuizCategory.java similarity index 85% rename from src/main/java/darkoverload/itzip/feature/csQuiz/service/sub/quizCategory/FindQuizCategory.java rename to src/main/java/darkoverload/itzip/feature/csQuiz/service/sub/quizcategory/FindQuizCategory.java index 03e64b88..e3db1445 100644 --- a/src/main/java/darkoverload/itzip/feature/csQuiz/service/sub/quizCategory/FindQuizCategory.java +++ b/src/main/java/darkoverload/itzip/feature/csQuiz/service/sub/quizcategory/FindQuizCategory.java @@ -1,4 +1,4 @@ -package darkoverload.itzip.feature.csQuiz.service.sub.quizCategory; +package darkoverload.itzip.feature.csQuiz.service.sub.quizcategory; import darkoverload.itzip.feature.csQuiz.controller.response.QuizCategoryDetailResponse; import darkoverload.itzip.feature.csQuiz.entity.QuizCategory; diff --git a/src/main/java/darkoverload/itzip/feature/csQuiz/service/sub/quizCategory/FindQuizCategoryImpl.java b/src/main/java/darkoverload/itzip/feature/csQuiz/service/sub/quizcategory/FindQuizCategoryImpl.java similarity index 96% rename from src/main/java/darkoverload/itzip/feature/csQuiz/service/sub/quizCategory/FindQuizCategoryImpl.java rename to src/main/java/darkoverload/itzip/feature/csQuiz/service/sub/quizcategory/FindQuizCategoryImpl.java index 22ea638d..10dde3d7 100644 --- a/src/main/java/darkoverload/itzip/feature/csQuiz/service/sub/quizCategory/FindQuizCategoryImpl.java +++ b/src/main/java/darkoverload/itzip/feature/csQuiz/service/sub/quizcategory/FindQuizCategoryImpl.java @@ -1,4 +1,4 @@ -package darkoverload.itzip.feature.csQuiz.service.sub.quizCategory; +package darkoverload.itzip.feature.csQuiz.service.sub.quizcategory; import darkoverload.itzip.feature.csQuiz.controller.response.QuizCategoryDetailResponse; import darkoverload.itzip.feature.csQuiz.entity.QuizCategory; From fab2fe3ad83e3d6a59451c85349efdf2dcafa3ea Mon Sep 17 00:00:00 2001 From: rowing0328 Date: Fri, 14 Feb 2025 18:41:48 +0900 Subject: [PATCH 02/12] =?UTF-8?q?=E2=9C=A8=09=EC=83=88=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20:=20=ED=80=B4=EC=A6=88=20=EC=A0=95=EB=8B=B5=20?= =?UTF-8?q?=ED=99=95=EC=9D=B8=20=EC=8B=9C=20=EC=A0=90=EC=88=98=20=EC=8B=9C?= =?UTF-8?q?=EC=8A=A4=ED=85=9C=20=EC=B6=94=EA=B0=80=20-=20=EC=82=AC?= =?UTF-8?q?=EC=9A=A9=EC=9E=90=EC=9D=98=20=EC=A0=95=EB=8B=B5=20=EC=97=AC?= =?UTF-8?q?=EB=B6=80=EC=97=90=20=EB=94=B0=EB=9D=BC=20=EC=A0=90=EC=88=98?= =?UTF-8?q?=EB=A5=BC=20=EB=B6=80=EC=97=AC=ED=95=98=EB=8A=94=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20=EC=B6=94=EA=B0=80=20-=20QuizScore=20=EC=97=94?= =?UTF-8?q?=ED=8B=B0=ED=8B=B0=EB=A5=BC=20=ED=99=9C=EC=9A=A9=ED=95=98?= =?UTF-8?q?=EC=97=AC=20=EC=82=AC=EC=9A=A9=EC=9E=90=20=EC=A0=90=EC=88=98=20?= =?UTF-8?q?=EC=A0=80=EC=9E=A5=20=EB=B0=8F=20=EA=B0=B1=EC=8B=A0=20-=20?= =?UTF-8?q?=ED=80=B4=EC=A6=88=20=EB=82=9C=EC=9D=B4=EB=8F=84(EASY,=20MEDIUM?= =?UTF-8?q?,=20HARD)=EC=97=90=20=EB=94=B0=EB=9D=BC=20=EC=A0=90=EC=88=98=20?= =?UTF-8?q?=EC=B0=A8=EB=93=B1=20=EB=B6=80=EC=97=AC=20-=20=EA=B8=B0?= =?UTF-8?q?=EC=A1=B4=20=EC=A0=95=EB=8B=B5=20=EC=B2=B4=ED=81=AC=20=EB=A1=9C?= =?UTF-8?q?=EC=A7=81=EC=9D=84=20=EC=9C=A0=EC=A7=80=ED=95=98=EB=A9=B4?= =?UTF-8?q?=EC=84=9C=20=EC=A0=90=EC=88=98=20=EA=B8=B0=EB=8A=A5=20=EC=97=B0?= =?UTF-8?q?=EB=8F=99=20-=20=EC=A0=90=EC=88=98=20=EA=B3=84=EC=82=B0=20?= =?UTF-8?q?=EB=A1=9C=EC=A7=81=EC=9D=84=20=EB=B3=84=EB=8F=84=20=EB=A9=94?= =?UTF-8?q?=EC=84=9C=EB=93=9C=EB=A1=9C=20=EB=B6=84=EB=A6=AC=ED=95=98?= =?UTF-8?q?=EC=97=AC=20=EA=B0=80=EB=8F=85=EC=84=B1=20=EB=B0=8F=20=EC=9C=A0?= =?UTF-8?q?=EC=A7=80=EB=B3=B4=EC=88=98=EC=84=B1=20=ED=96=A5=EC=83=81=20Ref?= =?UTF-8?q?=20:=20#211?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/sub/quiz/CheckAnswerImpl.java | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/src/main/java/darkoverload/itzip/feature/csQuiz/service/sub/quiz/CheckAnswerImpl.java b/src/main/java/darkoverload/itzip/feature/csQuiz/service/sub/quiz/CheckAnswerImpl.java index f3976343..d63d1358 100644 --- a/src/main/java/darkoverload/itzip/feature/csQuiz/service/sub/quiz/CheckAnswerImpl.java +++ b/src/main/java/darkoverload/itzip/feature/csQuiz/service/sub/quiz/CheckAnswerImpl.java @@ -2,9 +2,11 @@ import darkoverload.itzip.feature.csQuiz.controller.request.QuizAnswerRequest; import darkoverload.itzip.feature.csQuiz.entity.QuizDocument; +import darkoverload.itzip.feature.csQuiz.entity.QuizScore; import darkoverload.itzip.feature.csQuiz.entity.QuizUserSolvedMapping; import darkoverload.itzip.feature.csQuiz.entity.UserQuizStatus; import darkoverload.itzip.feature.csQuiz.repository.quiz.QuizRepository; +import darkoverload.itzip.feature.csQuiz.repository.quizscore.QuizScoreRepository; import darkoverload.itzip.feature.csQuiz.repository.quizusersolvedmapping.QuizUserSolvedMappingRepository; import darkoverload.itzip.feature.jwt.infrastructure.CustomUserDetails; import darkoverload.itzip.feature.user.domain.User; @@ -22,8 +24,18 @@ @Service @RequiredArgsConstructor public class CheckAnswerImpl implements CheckAnswer { + + private static final int EASY = 1; + private static final int MEDIUM = 2; + private static final int HARD = 3; + + private static final int EASY_SCORE = 10; + private static final int MEDIUM_SCORE = 20; + private static final int HARD_SCORE = 30; + //퀴즈 정답 체크에 필요한 리파지토리 private final QuizRepository quizRepository; + private final QuizScoreRepository quizScoreRepository; private final QuizUserSolvedMappingRepository quizUserSolvedMappingRepository; //User객체를 받아올 userRepository; @@ -86,6 +98,31 @@ public UserQuizStatus checkAnswer(QuizAnswerRequest quizAnswerRequest, CustomUse .modifyDate(LocalDateTime.now()) .build()); + if (isCorrect) { + final QuizScore quizScore = quizScoreRepository.findById(userEntity.getId()) + .orElseGet(() -> { + QuizScore newQuizScore = QuizScore.create(userEntity); + return quizScoreRepository.save(newQuizScore); + }); + + switch (quizDocument.getDifficulty()) { + case HARD -> quizScore.incrementScore(calculateScore(HARD)); + case MEDIUM -> quizScore.incrementScore(calculateScore(MEDIUM)); + case EASY -> quizScore.incrementScore(calculateScore(EASY)); + default -> throw new RestApiException(CommonExceptionCode.NOT_FOUND_DIFFICULTY); + } + } + return quizStatus; } + + private int calculateScore(final int difficulty) { + return switch (difficulty) { + case HARD -> HARD_SCORE; + case MEDIUM -> MEDIUM_SCORE; + case EASY -> EASY_SCORE; + default -> throw new RestApiException(CommonExceptionCode.NOT_FOUND_DIFFICULTY); + }; + } + } \ No newline at end of file From fe49fde4c3f5612f3eb205564f8bd7fa7593df8c Mon Sep 17 00:00:00 2001 From: rowing0328 Date: Fri, 14 Feb 2025 18:43:43 +0900 Subject: [PATCH 03/12] =?UTF-8?q?=E2=9C=A8=20=EC=83=88=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20:=20=ED=80=B4=EC=A6=88=20=EB=B0=8F=20=EB=9E=AD?= =?UTF-8?q?=ED=82=B9=20=EA=B4=80=EB=A0=A8=20=EC=98=88=EC=99=B8=20=EC=BD=94?= =?UTF-8?q?=EB=93=9C=20=EC=B6=94=EA=B0=80=20-=20NOT=5FFOUND=5FDIFFICULTY(?= =?UTF-8?q?=EB=82=9C=EC=9D=B4=EB=8F=84=20=EC=97=86=EC=9D=8C)=20=EC=98=88?= =?UTF-8?q?=EC=99=B8=20=EC=BD=94=EB=93=9C=20=EC=B6=94=EA=B0=80=20-=20QUIZ?= =?UTF-8?q?=5FPROCESSING=5FERROR(=ED=80=B4=EC=A6=88=20=EC=B2=98=EB=A6=AC?= =?UTF-8?q?=20=EC=A4=91=20=EB=AC=B8=EC=A0=9C=20=EB=B0=9C=EC=83=9D)=20?= =?UTF-8?q?=EC=98=88=EC=99=B8=20=EC=BD=94=EB=93=9C=20=EC=B6=94=EA=B0=80=20?= =?UTF-8?q?-=20NOT=5FFOUND=5FQUIZ=5FSCORE(=ED=80=B4=EC=A6=88=20=EC=A0=90?= =?UTF-8?q?=EC=88=98=20=EC=97=86=EC=9D=8C)=20=EC=98=88=EC=99=B8=20?= =?UTF-8?q?=EC=BD=94=EB=93=9C=20=EC=B6=94=EA=B0=80=20-=20NOT=5FFOUND=5FQUI?= =?UTF-8?q?Z=5FSCORE=5FRANKING(=ED=80=B4=EC=A6=88=20=EB=9E=AD=ED=82=B9=20?= =?UTF-8?q?=EC=97=86=EC=9D=8C)=20=EC=98=88=EC=99=B8=20=EC=BD=94=EB=93=9C?= =?UTF-8?q?=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ref : #211 --- .../global/config/response/code/CommonExceptionCode.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/main/java/darkoverload/itzip/global/config/response/code/CommonExceptionCode.java b/src/main/java/darkoverload/itzip/global/config/response/code/CommonExceptionCode.java index 160642ee..629ece26 100644 --- a/src/main/java/darkoverload/itzip/global/config/response/code/CommonExceptionCode.java +++ b/src/main/java/darkoverload/itzip/global/config/response/code/CommonExceptionCode.java @@ -130,6 +130,14 @@ public enum CommonExceptionCode implements ResponseCode { ALREADY_CORRECT(HttpStatus.BAD_REQUEST, "이미 정답을 맞췄습니다."), //카테고리가 없음 NOT_FOUND_CATEGORY(HttpStatus.NOT_FOUND, "카테고리가 없습니다."), + //난이도 없음 + NOT_FOUND_DIFFICULTY(HttpStatus.NOT_FOUND, "난이도가 없습니다."), + //퀴즈 처리 중 문제 발생 + QUIZ_PROCESSING_ERROR(HttpStatus.BAD_REQUEST, "퀴즈 처리 중 문제가 발생했습니다."), + //퀴즈 점수가 없음 + NOT_FOUND_QUIZ_SCORE(HttpStatus.NOT_FOUND, "퀴즈 점수를 찾을 수 없습니다"), + //퀴즈 랭킹이 없음 + NOT_FOUND_QUIZ_SCORE_RANKING(HttpStatus.NOT_FOUND, "랭킹을 찾을 수 없습니다."), /** * Algorithm Error From 6c15234931b1de1ba258d43ec788817adf67afec Mon Sep 17 00:00:00 2001 From: rowing0328 Date: Fri, 14 Feb 2025 18:54:49 +0900 Subject: [PATCH 04/12] =?UTF-8?q?=E2=9C=A8=20=EC=83=88=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20:=20=ED=80=B4=EC=A6=88=20=EC=A0=90=EC=88=98=20?= =?UTF-8?q?=EB=B0=8F=20=EB=9E=AD=ED=82=B9=20=EC=A1=B0=ED=9A=8C=20API=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80=20-=20=ED=80=B4=EC=A6=88=20=EC=A0=90?= =?UTF-8?q?=EC=88=98=EB=A5=BC=20=EC=A1=B0=ED=9A=8C=ED=95=98=EB=8A=94=20`/s?= =?UTF-8?q?core`=20=EC=97=94=EB=93=9C=ED=8F=AC=EC=9D=B8=ED=8A=B8=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80=20-=20=ED=80=B4=EC=A6=88=20=EB=9E=AD?= =?UTF-8?q?=ED=82=B9=EC=9D=84=20=EC=A1=B0=ED=9A=8C=ED=95=98=EB=8A=94=20`/r?= =?UTF-8?q?ankings`=20=EC=97=94=EB=93=9C=ED=8F=AC=EC=9D=B8=ED=8A=B8=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80=20(=EC=83=81=EC=9C=84=206=EB=AA=85)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ref : #211 --- .../csQuiz/controller/CsQuizController.java | 45 ++++++++++++++++++- 1 file changed, 44 insertions(+), 1 deletion(-) diff --git a/src/main/java/darkoverload/itzip/feature/csQuiz/controller/CsQuizController.java b/src/main/java/darkoverload/itzip/feature/csQuiz/controller/CsQuizController.java index 7a764b1a..bb52b6e5 100644 --- a/src/main/java/darkoverload/itzip/feature/csQuiz/controller/CsQuizController.java +++ b/src/main/java/darkoverload/itzip/feature/csQuiz/controller/CsQuizController.java @@ -4,9 +4,13 @@ import darkoverload.itzip.feature.csQuiz.controller.request.QuizCreatedRequest; import darkoverload.itzip.feature.csQuiz.controller.request.QuizPointRequest; import darkoverload.itzip.feature.csQuiz.controller.response.QuizCategoryDetailResponse; +import darkoverload.itzip.feature.csQuiz.controller.response.QuizRankingResponse; +import darkoverload.itzip.feature.csQuiz.controller.response.QuizRankingResponses; +import darkoverload.itzip.feature.csQuiz.controller.response.QuizScoreResponse; import darkoverload.itzip.feature.csQuiz.entity.QuizCategory; import darkoverload.itzip.feature.csQuiz.entity.UserQuizStatus; import darkoverload.itzip.feature.csQuiz.service.QuizService; +import darkoverload.itzip.feature.csQuiz.service.sub.quizscore.QuizScoreService; import darkoverload.itzip.feature.jwt.infrastructure.CustomUserDetails; import darkoverload.itzip.global.config.response.code.CommonExceptionCode; import darkoverload.itzip.global.config.response.code.CommonResponseCode; @@ -18,6 +22,7 @@ import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.extern.slf4j.Slf4j; import org.springframework.security.core.annotation.AuthenticationPrincipal; import org.springframework.web.bind.annotation.RequestBody; import lombok.RequiredArgsConstructor; @@ -31,7 +36,10 @@ @RequestMapping("cs-quiz") @RequiredArgsConstructor public class CsQuizController { + private final QuizService quizService; + private final QuizScoreService quizScoreService; + /** * 주어진 카테고리 ID에 해당하는 카테고리 정보를 조회하는 메서드 * @@ -111,4 +119,39 @@ public String createQuiz( quizService.createQuiz(quizCreatedRequest, customUserDetails); return "문제를 생성했습니다."; } -} \ No newline at end of file + + @Operation( + summary = "퀴즈 점수 조회", + description = "현재 인증된 사용자의 퀴즈 점수를 조회하여 반환합니다." + ) + @ResponseCodeAnnotation(CommonResponseCode.SUCCESS) + @ExceptionCodeAnnotations({ + CommonExceptionCode.NOT_FOUND_USER, + CommonExceptionCode.NOT_FOUND_QUIZ_SCORE + }) + @GetMapping("/score") + public QuizScoreResponse getScore(@AuthenticationPrincipal final CustomUserDetails customUserDetails) { + return QuizScoreResponse.from( + quizScoreService.findQuizScoreById(customUserDetails) + ); + } + + @Operation( + summary = "퀴즈 랭킹 조회", + description = "퀴즈 점수를 기준으로 상위 6명의 랭킹 정보를 조회하여 반환합니다." + ) + @ResponseCodeAnnotation(CommonResponseCode.SUCCESS) + @ExceptionCodeAnnotations({ + CommonExceptionCode.NOT_FOUND_QUIZ_SCORE_RANKING, + CommonExceptionCode.QUIZ_PROCESSING_ERROR + }) + @GetMapping("/rankings") + public QuizRankingResponses getRankings() { + return QuizRankingResponses.of( + quizScoreService.getTop6Ranking().getRankings().stream() + .map(QuizRankingResponse::from) + .toList() + ); + } + +} From ffaa49d78b418f7c7860d3de52155ddf59e9a13a Mon Sep 17 00:00:00 2001 From: rowing0328 Date: Fri, 14 Feb 2025 18:55:44 +0900 Subject: [PATCH 05/12] =?UTF-8?q?=E2=9C=A8=20=EC=83=88=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20:=20=ED=80=B4=EC=A6=88=20=EB=9E=AD=ED=82=B9=20?= =?UTF-8?q?=EC=97=94=ED=8B=B0=ED=8B=B0(QuizRanking)=20=EC=B6=94=EA=B0=80?= =?UTF-8?q?=20-=20=EC=82=AC=EC=9A=A9=EC=9E=90=EC=9D=98=20=EB=9E=AD?= =?UTF-8?q?=ED=82=B9=20=EC=A0=95=EB=B3=B4=EB=A5=BC=20=EC=A0=80=EC=9E=A5?= =?UTF-8?q?=ED=95=98=EB=8A=94=20QuizRanking=20=ED=81=B4=EB=9E=98=EC=8A=A4?= =?UTF-8?q?=20=EA=B5=AC=ED=98=84=20-=20=EB=9E=AD=ED=82=B9,=20=EC=82=AC?= =?UTF-8?q?=EC=9A=A9=EC=9E=90=20=EB=8B=89=EB=84=A4=EC=9E=84,=20=EC=A0=90?= =?UTF-8?q?=EC=88=98=EB=A5=BC=20=ED=95=84=EB=93=9C=EB=A1=9C=20=ED=8F=AC?= =?UTF-8?q?=ED=95=A8=20-=20=EC=82=AC=EC=9A=A9=EC=9E=90=20=EC=9D=B4?= =?UTF-8?q?=EB=A6=84=EC=9D=B4=20null=EC=9D=BC=20=EA=B2=BD=EC=9A=B0=20?= =?UTF-8?q?=EC=98=88=EC=99=B8=20=EC=B2=98=EB=A6=AC=20=EC=B6=94=EA=B0=80=20?= =?UTF-8?q?(QUIZ=5FPROCESSING=5FERROR)=20-=20QuizScore=20=EC=97=94?= =?UTF-8?q?=ED=8B=B0=ED=8B=B0=EB=A5=BC=20=EA=B8=B0=EB=B0=98=EC=9C=BC?= =?UTF-8?q?=EB=A1=9C=20=EB=9E=AD=ED=82=B9=20=EA=B0=9D=EC=B2=B4=EB=A5=BC=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1=ED=95=98=EB=8A=94=20=EC=A0=95=EC=A0=81=20?= =?UTF-8?q?=ED=8C=A9=ED=86=A0=EB=A6=AC=20=EB=A9=94=EC=84=9C=EB=93=9C=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ref : #211 --- .../feature/csQuiz/entity/QuizRanking.java | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 src/main/java/darkoverload/itzip/feature/csQuiz/entity/QuizRanking.java diff --git a/src/main/java/darkoverload/itzip/feature/csQuiz/entity/QuizRanking.java b/src/main/java/darkoverload/itzip/feature/csQuiz/entity/QuizRanking.java new file mode 100644 index 00000000..e45f6adc --- /dev/null +++ b/src/main/java/darkoverload/itzip/feature/csQuiz/entity/QuizRanking.java @@ -0,0 +1,33 @@ +package darkoverload.itzip.feature.csQuiz.entity; + +import darkoverload.itzip.global.config.response.code.CommonExceptionCode; +import darkoverload.itzip.global.config.response.exception.RestApiException; +import lombok.Getter; + +import java.util.Objects; + +@Getter +public class QuizRanking { + + private final int rank; + private final String name; + private final int score; + + private QuizRanking(final int rank, final String name, final int score) { + checkNameNotNull(name); + this.rank = rank; + this.name = name; + this.score = score; + } + + private void checkNameNotNull(final String name) { + if (Objects.isNull(name)) { + throw new RestApiException(CommonExceptionCode.QUIZ_PROCESSING_ERROR); + } + } + + public static QuizRanking create(final int rank, final QuizScore score) { + return new QuizRanking(rank, score.getUser().getNickname(), score.getScore()); + } + +} From 61b1f2a9b88a622283509b38b4763e224471720c Mon Sep 17 00:00:00 2001 From: rowing0328 Date: Fri, 14 Feb 2025 18:56:29 +0900 Subject: [PATCH 06/12] =?UTF-8?q?=E2=9C=A8=20=EC=83=88=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20:=20=ED=80=B4=EC=A6=88=20=EB=9E=AD=ED=82=B9=20?= =?UTF-8?q?=EC=9D=91=EB=8B=B5=20=EA=B0=9D=EC=B2=B4=20QuizRankingResponses?= =?UTF-8?q?=20=EC=B6=94=EA=B0=80=20-=20QuizRankingResponse=20=EB=A6=AC?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=EB=A5=BC=20=EB=B6=88=EB=B3=80=20=EA=B0=9D?= =?UTF-8?q?=EC=B2=B4=EB=A1=9C=20=EA=B0=90=EC=8B=B8=EB=8A=94=20=ED=81=B4?= =?UTF-8?q?=EB=9E=98=EC=8A=A4=20=EA=B5=AC=ED=98=84=20-=20=EC=99=B8?= =?UTF-8?q?=EB=B6=80=EC=97=90=EC=84=9C=20=EB=A6=AC=EC=8A=A4=ED=8A=B8?= =?UTF-8?q?=EB=A5=BC=20=EC=88=98=EC=A0=95=ED=95=A0=20=EC=88=98=20=EC=97=86?= =?UTF-8?q?=EB=8F=84=EB=A1=9D=20unmodifiableList=20=EC=A0=81=EC=9A=A9=20-?= =?UTF-8?q?=20=EC=A0=95=EC=A0=81=20=ED=8C=A9=ED=86=A0=EB=A6=AC=20=EB=A9=94?= =?UTF-8?q?=EC=84=9C=EB=93=9C=20`of()`=20=EC=B6=94=EA=B0=80=ED=95=98?= =?UTF-8?q?=EC=97=AC=20=EA=B0=9D=EC=B2=B4=20=EC=83=9D=EC=84=B1=20=EB=B0=A9?= =?UTF-8?q?=EC=8B=9D=20=ED=86=B5=EC=9D=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ref : #211 --- .../response/QuizRankingResponses.java | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 src/main/java/darkoverload/itzip/feature/csQuiz/controller/response/QuizRankingResponses.java diff --git a/src/main/java/darkoverload/itzip/feature/csQuiz/controller/response/QuizRankingResponses.java b/src/main/java/darkoverload/itzip/feature/csQuiz/controller/response/QuizRankingResponses.java new file mode 100644 index 00000000..b2dc1104 --- /dev/null +++ b/src/main/java/darkoverload/itzip/feature/csQuiz/controller/response/QuizRankingResponses.java @@ -0,0 +1,21 @@ +package darkoverload.itzip.feature.csQuiz.controller.response; + +import lombok.Getter; + +import java.util.Collections; +import java.util.List; + +@Getter +public class QuizRankingResponses { + + private final List responses; + + private QuizRankingResponses(final List responses) { + this.responses = Collections.unmodifiableList(responses); + } + + public static QuizRankingResponses of(final List responses) { + return new QuizRankingResponses(responses); + } + +} From d563a3682f808f82f764d58d61dbcd49875336ab Mon Sep 17 00:00:00 2001 From: rowing0328 Date: Fri, 14 Feb 2025 18:57:10 +0900 Subject: [PATCH 07/12] =?UTF-8?q?=E2=9C=A8=20=EC=83=88=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20:=20=ED=80=B4=EC=A6=88=20=EC=A0=90=EC=88=98=20?= =?UTF-8?q?=EC=84=9C=EB=B9=84=EC=8A=A4(QuizScoreService)=20=EB=B0=8F=20?= =?UTF-8?q?=EB=9E=AD=ED=82=B9=20=EC=A1=B0=ED=9A=8C=20=EA=B8=B0=EB=8A=A5=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80=20-=20=EC=82=AC=EC=9A=A9=EC=9E=90=EC=9D=98?= =?UTF-8?q?=20=ED=80=B4=EC=A6=88=20=EC=A0=90=EC=88=98=EB=A5=BC=20=EC=A1=B0?= =?UTF-8?q?=ED=9A=8C=ED=95=98=EB=8A=94=20`findQuizScoreById`=20=EB=A9=94?= =?UTF-8?q?=EC=84=9C=EB=93=9C=20=EA=B5=AC=ED=98=84=20-=20=ED=80=B4?= =?UTF-8?q?=EC=A6=88=20=EC=A0=90=EC=88=98=EB=A5=BC=20=EA=B8=B0=EC=A4=80?= =?UTF-8?q?=EC=9C=BC=EB=A1=9C=20=EC=83=81=EC=9C=84=206=EB=AA=85=EC=9D=98?= =?UTF-8?q?=20=EB=9E=AD=ED=82=B9=EC=9D=84=20=EC=A1=B0=ED=9A=8C=ED=95=98?= =?UTF-8?q?=EB=8A=94=20`getTop6Ranking`=20=EB=A9=94=EC=84=9C=EB=93=9C=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80=20-=20`QuizScoreRepository`=20=ED=99=9C?= =?UTF-8?q?=EC=9A=A9=ED=95=98=EC=97=AC=20=EC=A0=90=EC=88=98=20=EB=8D=B0?= =?UTF-8?q?=EC=9D=B4=ED=84=B0=20=EC=A1=B0=ED=9A=8C=20-=20=EC=82=AC?= =?UTF-8?q?=EC=9A=A9=EC=9E=90=20=EC=A1=B4=EC=9E=AC=20=EC=97=AC=EB=B6=80=20?= =?UTF-8?q?=ED=99=95=EC=9D=B8=20=ED=9B=84=20=EC=98=88=EC=99=B8=20=EC=B2=98?= =?UTF-8?q?=EB=A6=AC=20(NOT=5FFOUND=5FUSER,=20NOT=5FFOUND=5FQUIZ=5FSCORE)?= =?UTF-8?q?=20-=20=EB=9E=AD=ED=82=B9=20=EB=8D=B0=EC=9D=B4=ED=84=B0?= =?UTF-8?q?=EB=A5=BC=20`QuizRanking`=20=EA=B0=9D=EC=B2=B4=EB=A1=9C=20?= =?UTF-8?q?=EB=B3=80=ED=99=98=ED=95=98=EC=97=AC=20`QuizRankings`=EB=A1=9C?= =?UTF-8?q?=20=EA=B0=90=EC=8B=B8=EC=84=9C=20=EB=B0=98=ED=99=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ref : #211 --- .../sub/quizscore/QuizScoreService.java | 13 +++++ .../sub/quizscore/QuizScoreServiceImpl.java | 54 +++++++++++++++++++ 2 files changed, 67 insertions(+) create mode 100644 src/main/java/darkoverload/itzip/feature/csQuiz/service/sub/quizscore/QuizScoreService.java create mode 100644 src/main/java/darkoverload/itzip/feature/csQuiz/service/sub/quizscore/QuizScoreServiceImpl.java diff --git a/src/main/java/darkoverload/itzip/feature/csQuiz/service/sub/quizscore/QuizScoreService.java b/src/main/java/darkoverload/itzip/feature/csQuiz/service/sub/quizscore/QuizScoreService.java new file mode 100644 index 00000000..3ca0ab2a --- /dev/null +++ b/src/main/java/darkoverload/itzip/feature/csQuiz/service/sub/quizscore/QuizScoreService.java @@ -0,0 +1,13 @@ +package darkoverload.itzip.feature.csQuiz.service.sub.quizscore; + +import darkoverload.itzip.feature.csQuiz.entity.QuizRankings; +import darkoverload.itzip.feature.csQuiz.entity.QuizScore; +import darkoverload.itzip.feature.jwt.infrastructure.CustomUserDetails; + +public interface QuizScoreService { + + QuizScore findQuizScoreById(CustomUserDetails userDetails); + + QuizRankings getTop6Ranking(); + +} diff --git a/src/main/java/darkoverload/itzip/feature/csQuiz/service/sub/quizscore/QuizScoreServiceImpl.java b/src/main/java/darkoverload/itzip/feature/csQuiz/service/sub/quizscore/QuizScoreServiceImpl.java new file mode 100644 index 00000000..c66b8848 --- /dev/null +++ b/src/main/java/darkoverload/itzip/feature/csQuiz/service/sub/quizscore/QuizScoreServiceImpl.java @@ -0,0 +1,54 @@ +package darkoverload.itzip.feature.csQuiz.service.sub.quizscore; + +import darkoverload.itzip.feature.csQuiz.entity.QuizRanking; +import darkoverload.itzip.feature.csQuiz.entity.QuizRankings; +import darkoverload.itzip.feature.csQuiz.entity.QuizScore; +import darkoverload.itzip.feature.csQuiz.repository.quizscore.QuizScoreRepository; +import darkoverload.itzip.feature.jwt.infrastructure.CustomUserDetails; +import darkoverload.itzip.feature.user.domain.User; +import darkoverload.itzip.feature.user.entity.UserEntity; +import darkoverload.itzip.feature.user.service.UserService; +import darkoverload.itzip.global.config.response.code.CommonExceptionCode; +import darkoverload.itzip.global.config.response.exception.RestApiException; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.ArrayList; +import java.util.List; + +@Service +@RequiredArgsConstructor +@Transactional(readOnly = true) +public class QuizScoreServiceImpl implements QuizScoreService { + + private final UserService userService; + + private final QuizScoreRepository quizScoreRepository; + + @Override + public QuizScore findQuizScoreById(CustomUserDetails userDetails) { + final UserEntity user = userService.findByEmail(userDetails.getEmail()) + .map(User::convertToEntity) + .orElseThrow(() -> new RestApiException(CommonExceptionCode.NOT_FOUND_USER)); + + return quizScoreRepository.findById(user.getId()) + .orElseThrow(() -> new RestApiException(CommonExceptionCode.NOT_FOUND_QUIZ_SCORE)); + } + + @Override + public QuizRankings getTop6Ranking() { + final List scores = quizScoreRepository.findTop6ByOrderByScoreDesc() + .orElseThrow(() -> new RestApiException(CommonExceptionCode.NOT_FOUND_QUIZ_SCORE_RANKING)); + + final List rankings = new ArrayList<>(); + int rank = 1; + for (QuizScore score : scores) { + rankings.add(QuizRanking.create(rank, score)); + rank++; + } + + return QuizRankings.of(rankings); + } + +} From 8cc1516ad81a5b76648be2594fe4fe6882e04082 Mon Sep 17 00:00:00 2001 From: rowing0328 Date: Fri, 14 Feb 2025 18:57:54 +0900 Subject: [PATCH 08/12] =?UTF-8?q?=E2=9C=A8=20=EC=83=88=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20:=20=ED=80=B4=EC=A6=88=20=EB=9E=AD=ED=82=B9=20?= =?UTF-8?q?=EC=9D=91=EB=8B=B5=20DTO(QuizRankingResponse)=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80=20-=20=EC=82=AC=EC=9A=A9=EC=9E=90=EC=9D=98=20?= =?UTF-8?q?=EC=88=9C=EC=9C=84,=20=EC=9D=B4=EB=A6=84,=20=EC=A0=90=EC=88=98?= =?UTF-8?q?=EB=A5=BC=20=ED=8F=AC=ED=95=A8=ED=95=98=EB=8A=94=20DTO=20?= =?UTF-8?q?=ED=81=B4=EB=9E=98=EC=8A=A4=20=EA=B5=AC=ED=98=84=20-=20Swagger?= =?UTF-8?q?=20API=20=EB=AC=B8=EC=84=9C=EB=A5=BC=20=EC=9C=84=ED=95=9C=20@Sc?= =?UTF-8?q?hema=20=EC=96=B4=EB=85=B8=ED=85=8C=EC=9D=B4=EC=85=98=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80=20-=20`QuizRanking`=20=EA=B0=9D=EC=B2=B4?= =?UTF-8?q?=EB=A5=BC=20=EB=B3=80=ED=99=98=ED=95=98=EB=8A=94=20=EC=A0=95?= =?UTF-8?q?=EC=A0=81=20=EB=A9=94=EC=84=9C=EB=93=9C=20`from()`=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ref : #211 --- .../response/QuizRankingResponse.java | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 src/main/java/darkoverload/itzip/feature/csQuiz/controller/response/QuizRankingResponse.java diff --git a/src/main/java/darkoverload/itzip/feature/csQuiz/controller/response/QuizRankingResponse.java b/src/main/java/darkoverload/itzip/feature/csQuiz/controller/response/QuizRankingResponse.java new file mode 100644 index 00000000..c8c2f093 --- /dev/null +++ b/src/main/java/darkoverload/itzip/feature/csQuiz/controller/response/QuizRankingResponse.java @@ -0,0 +1,30 @@ +package darkoverload.itzip.feature.csQuiz.controller.response; + +import darkoverload.itzip.feature.csQuiz.entity.QuizRanking; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; + +@Getter +@Schema(description = "퀴즈 랭킹 응답 DTO로 사용자의 순위, 이름, 그리고 점수를 포함합니다.") +public class QuizRankingResponse { + + @Schema(description = "사용자의 순위", example = "1") + private final int rank; + + @Schema(description = "사용자 이름", example = "홍길동") + private final String name; + + @Schema(description = "퀴즈 점수", example = "100") + private final int score; + + public QuizRankingResponse(final int rank, final String name, final int score) { + this.rank = rank; + this.name = name; + this.score = score; + } + + public static QuizRankingResponse from(final QuizRanking ranking) { + return new QuizRankingResponse(ranking.getRank(), ranking.getName(), ranking.getScore()); + } + +} From e244bde5dbbf0ad1ef7c03cb295a1cc38fbca447 Mon Sep 17 00:00:00 2001 From: rowing0328 Date: Fri, 14 Feb 2025 18:58:57 +0900 Subject: [PATCH 09/12] =?UTF-8?q?=E2=9C=A8=20=EC=83=88=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20:=20=ED=80=B4=EC=A6=88=20=EB=9E=AD=ED=82=B9=20?= =?UTF-8?q?=EB=AA=A9=EB=A1=9D=20=EC=97=94=ED=8B=B0=ED=8B=B0(QuizRankings)?= =?UTF-8?q?=20=EC=B6=94=EA=B0=80=20-=20`QuizRanking`=20=EA=B0=9D=EC=B2=B4?= =?UTF-8?q?=20=EB=A6=AC=EC=8A=A4=ED=8A=B8=EB=A5=BC=20=EA=B4=80=EB=A6=AC?= =?UTF-8?q?=ED=95=98=EB=8A=94=20`QuizRankings`=20=ED=81=B4=EB=9E=98?= =?UTF-8?q?=EC=8A=A4=20=EA=B5=AC=ED=98=84=20-=20=EB=9E=AD=ED=82=B9=20?= =?UTF-8?q?=EB=AA=A9=EB=A1=9D=EC=9D=84=20=EB=B6=88=EB=B3=80=20=EB=A6=AC?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=EB=A1=9C=20=EC=84=A4=EC=A0=95=ED=95=98?= =?UTF-8?q?=EC=97=AC=20=EC=99=B8=EB=B6=80=20=EC=88=98=EC=A0=95=20=EB=B0=A9?= =?UTF-8?q?=EC=A7=80=20-=20=EC=A0=95=EC=A0=81=20=ED=8C=A9=ED=86=A0?= =?UTF-8?q?=EB=A6=AC=20=EB=A9=94=EC=84=9C=EB=93=9C=20`of()`=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80=ED=95=98=EC=97=AC=20=EA=B0=9D=EC=B2=B4=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1=20=EB=B0=A9=EC=8B=9D=20=ED=86=B5=EC=9D=BC=20-=20`getR?= =?UTF-8?q?ankings()`=20=EB=A9=94=EC=84=9C=EB=93=9C=20=EC=A0=9C=EA=B3=B5?= =?UTF-8?q?=ED=95=98=EC=97=AC=20=EB=9E=AD=ED=82=B9=20=EB=A6=AC=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=EB=B0=98=ED=99=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ref : #211 --- .../feature/csQuiz/entity/QuizRankings.java | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 src/main/java/darkoverload/itzip/feature/csQuiz/entity/QuizRankings.java diff --git a/src/main/java/darkoverload/itzip/feature/csQuiz/entity/QuizRankings.java b/src/main/java/darkoverload/itzip/feature/csQuiz/entity/QuizRankings.java new file mode 100644 index 00000000..40c5ad53 --- /dev/null +++ b/src/main/java/darkoverload/itzip/feature/csQuiz/entity/QuizRankings.java @@ -0,0 +1,22 @@ +package darkoverload.itzip.feature.csQuiz.entity; + +import java.util.Collections; +import java.util.List; + +public class QuizRankings { + + private final List rankings; + + private QuizRankings(final List rankings) { + this.rankings = Collections.unmodifiableList(rankings); + } + + public static QuizRankings of(final List rankings) { + return new QuizRankings(rankings); + } + + public List getRankings() { + return rankings; + } + +} From 8d787b99c41bf386acdb181f5ade9b7f5d56d5b6 Mon Sep 17 00:00:00 2001 From: rowing0328 Date: Fri, 14 Feb 2025 18:59:28 +0900 Subject: [PATCH 10/12] =?UTF-8?q?=E2=9C=A8=20=EC=83=88=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20:=20=ED=80=B4=EC=A6=88=20=EC=A0=90=EC=88=98=20?= =?UTF-8?q?=EC=97=94=ED=8B=B0=ED=8B=B0(QuizScore)=20=EC=B6=94=EA=B0=80=20-?= =?UTF-8?q?=20=EC=82=AC=EC=9A=A9=EC=9E=90=EC=9D=98=20=ED=80=B4=EC=A6=88=20?= =?UTF-8?q?=EC=A0=90=EC=88=98=EB=A5=BC=20=EA=B4=80=EB=A6=AC=ED=95=98?= =?UTF-8?q?=EB=8A=94=20`QuizScore`=20=EC=97=94=ED=8B=B0=ED=8B=B0=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84=20-=20`UserEntity`=EC=99=80=20`OneToOne`=20?= =?UTF-8?q?=EA=B4=80=EA=B3=84=20=EC=84=A4=EC=A0=95=ED=95=98=EC=97=AC=20?= =?UTF-8?q?=EC=82=AC=EC=9A=A9=EC=9E=90=EB=B3=84=20=EC=A0=90=EC=88=98=20?= =?UTF-8?q?=EA=B4=80=EB=A6=AC=20-=20=EC=A0=90=EC=88=98=20=EA=B8=B0?= =?UTF-8?q?=EB=B3=B8=EA=B0=92=EC=9D=84=200=EC=9C=BC=EB=A1=9C=20=EC=84=A4?= =?UTF-8?q?=EC=A0=95=ED=95=98=EB=8A=94=20`create()`=20=EC=A0=95=EC=A0=81?= =?UTF-8?q?=20=ED=8C=A9=ED=86=A0=EB=A6=AC=20=EB=A9=94=EC=84=9C=EB=93=9C=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80=20-=20=EC=A0=90=EC=88=98=EB=A5=BC=20?= =?UTF-8?q?=EC=A6=9D=EA=B0=80=EC=8B=9C=ED=82=A4=EB=8A=94=20`incrementScore?= =?UTF-8?q?()`=20=EB=A9=94=EC=84=9C=EB=93=9C=20=EA=B5=AC=ED=98=84=20-=20?= =?UTF-8?q?=EC=82=AC=EC=9A=A9=EC=9E=90=20=EC=A0=95=EB=B3=B4=EA=B0=80=20nul?= =?UTF-8?q?l=EC=9D=BC=20=EA=B2=BD=EC=9A=B0=20=EC=98=88=EC=99=B8=20?= =?UTF-8?q?=EC=B2=98=EB=A6=AC=20(QUIZ=5FPROCESSING=5FERROR)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ref : #211 --- .../feature/csQuiz/entity/QuizScore.java | 49 +++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 src/main/java/darkoverload/itzip/feature/csQuiz/entity/QuizScore.java diff --git a/src/main/java/darkoverload/itzip/feature/csQuiz/entity/QuizScore.java b/src/main/java/darkoverload/itzip/feature/csQuiz/entity/QuizScore.java new file mode 100644 index 00000000..9bf9770d --- /dev/null +++ b/src/main/java/darkoverload/itzip/feature/csQuiz/entity/QuizScore.java @@ -0,0 +1,49 @@ +package darkoverload.itzip.feature.csQuiz.entity; + +import darkoverload.itzip.feature.user.entity.UserEntity; +import darkoverload.itzip.global.config.response.code.CommonExceptionCode; +import darkoverload.itzip.global.config.response.exception.RestApiException; +import jakarta.persistence.*; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.util.Objects; + +@Getter +@Entity +@Table(name = "quiz_scores") +@NoArgsConstructor(access = AccessLevel.PROTECTED) +public class QuizScore { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @OneToOne + @JoinColumn(name = "user_id") + private UserEntity user; + + private Integer score; + + private QuizScore(final UserEntity user) { + notNullParameters(user); + this.user = user; + this.score = 0; + } + + private void notNullParameters(final UserEntity user) { + if (Objects.isNull(user)) { + throw new RestApiException(CommonExceptionCode.QUIZ_PROCESSING_ERROR); + } + } + + public static QuizScore create(final UserEntity user) { + return new QuizScore(user); + } + + public void incrementScore(final Integer score) { + this.score += score; + } + +} From a3ed0c9c243f4ac80d62de86413449693c4eaef5 Mon Sep 17 00:00:00 2001 From: rowing0328 Date: Fri, 14 Feb 2025 19:01:50 +0900 Subject: [PATCH 11/12] =?UTF-8?q?=E2=9C=A8=20=EC=83=88=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20:=20=ED=80=B4=EC=A6=88=20=EC=A0=90=EC=88=98=20?= =?UTF-8?q?=EC=A1=B0=ED=9A=8C=20=EA=B8=B0=EB=8A=A5=20=EC=B6=94=EA=B0=80=20?= =?UTF-8?q?-=20`QuizScoreRepository`=20=EA=B5=AC=ED=98=84=ED=95=98?= =?UTF-8?q?=EC=97=AC=20=ED=80=B4=EC=A6=88=20=EC=A0=90=EC=88=98=20=EB=8D=B0?= =?UTF-8?q?=EC=9D=B4=ED=84=B0=20=EC=A1=B0=ED=9A=8C=20=EA=B8=B0=EB=8A=A5=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80=20=20=20-=20=EC=83=81=EC=9C=84=206=EB=AA=85?= =?UTF-8?q?=EC=9D=98=20=EC=A0=90=EC=88=98=EB=A5=BC=20=EC=A1=B0=ED=9A=8C?= =?UTF-8?q?=ED=95=98=EB=8A=94=20`findTop6ByOrderByScoreDesc()`=20=EB=A9=94?= =?UTF-8?q?=EC=84=9C=EB=93=9C=20=EC=B6=94=EA=B0=80=20-=20`QuizScoreRespons?= =?UTF-8?q?e`=20DTO=20=EC=B6=94=EA=B0=80=ED=95=98=EC=97=AC=20=ED=80=B4?= =?UTF-8?q?=EC=A6=88=20=EC=A0=90=EC=88=98=20=EC=9D=91=EB=8B=B5=20=EC=B2=98?= =?UTF-8?q?=EB=A6=AC=20=20=20-=20=EC=82=AC=EC=9A=A9=EC=9E=90=20=EB=8B=89?= =?UTF-8?q?=EB=84=A4=EC=9E=84=EA=B3=BC=20=EC=A0=90=EC=88=98=EB=A5=BC=20?= =?UTF-8?q?=ED=8F=AC=ED=95=A8=ED=95=98=EB=8A=94=20=EC=9D=91=EB=8B=B5=20?= =?UTF-8?q?=EA=B0=9D=EC=B2=B4=20=EC=83=9D=EC=84=B1=20=20=20-=20`QuizScore`?= =?UTF-8?q?=20=EC=97=94=ED=8B=B0=ED=8B=B0=EB=A5=BC=20=EB=B3=80=ED=99=98?= =?UTF-8?q?=ED=95=98=EB=8A=94=20`from()`=20=EC=A0=95=EC=A0=81=20=EB=A9=94?= =?UTF-8?q?=EC=84=9C=EB=93=9C=20=EC=B6=94=EA=B0=80=20-=20Swagger=20?= =?UTF-8?q?=EB=AC=B8=EC=84=9C=ED=99=94=EB=A5=BC=20=EC=9C=84=ED=95=9C=20`@S?= =?UTF-8?q?chema`=20=EC=96=B4=EB=85=B8=ED=85=8C=EC=9D=B4=EC=85=98=20?= =?UTF-8?q?=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ref : #211 --- .../response/QuizScoreResponse.java | 26 +++++++++++++++++++ .../quizscore/QuizScoreRepository.java | 13 ++++++++++ 2 files changed, 39 insertions(+) create mode 100644 src/main/java/darkoverload/itzip/feature/csQuiz/controller/response/QuizScoreResponse.java create mode 100644 src/main/java/darkoverload/itzip/feature/csQuiz/repository/quizscore/QuizScoreRepository.java diff --git a/src/main/java/darkoverload/itzip/feature/csQuiz/controller/response/QuizScoreResponse.java b/src/main/java/darkoverload/itzip/feature/csQuiz/controller/response/QuizScoreResponse.java new file mode 100644 index 00000000..516b48ae --- /dev/null +++ b/src/main/java/darkoverload/itzip/feature/csQuiz/controller/response/QuizScoreResponse.java @@ -0,0 +1,26 @@ +package darkoverload.itzip.feature.csQuiz.controller.response; + +import darkoverload.itzip.feature.csQuiz.entity.QuizScore; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; + +@Getter +@Schema(description = "퀴즈 점수 응답 DTO로 해당 객체는 사용자의 닉네임과 현재 퀴즈 점수를 포함합니다.") +public class QuizScoreResponse { + + @Schema(description = "사용자 닉네임", example = "홍길동") + private final String name; + + @Schema(description = "사용자의 퀴즈 점수", example = "120") + private final int score; + + public QuizScoreResponse(final String name, final int score) { + this.name = name; + this.score = score; + } + + public static QuizScoreResponse from(final QuizScore score) { + return new QuizScoreResponse(score.getUser().getNickname(), score.getScore()); + } + +} diff --git a/src/main/java/darkoverload/itzip/feature/csQuiz/repository/quizscore/QuizScoreRepository.java b/src/main/java/darkoverload/itzip/feature/csQuiz/repository/quizscore/QuizScoreRepository.java new file mode 100644 index 00000000..2cde0bae --- /dev/null +++ b/src/main/java/darkoverload/itzip/feature/csQuiz/repository/quizscore/QuizScoreRepository.java @@ -0,0 +1,13 @@ +package darkoverload.itzip.feature.csQuiz.repository.quizscore; + +import darkoverload.itzip.feature.csQuiz.entity.QuizScore; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.List; +import java.util.Optional; + +public interface QuizScoreRepository extends JpaRepository { + + Optional> findTop6ByOrderByScoreDesc(); + +} From 72339a46d7cbed4bc9a8fcc76b06a699dafa2a6d Mon Sep 17 00:00:00 2001 From: rowing0328 Date: Mon, 17 Feb 2025 19:06:05 +0900 Subject: [PATCH 12/12] =?UTF-8?q?=F0=9F=90=9B=20=EB=B2=84=EA=B7=B8=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=20:=20=EC=82=AC=EC=9A=A9=EC=9E=90=EA=B0=80?= =?UTF-8?q?=20=ED=91=BC=20=EB=AC=B8=EC=A0=9C=EB=A5=BC=20=EC=A0=9C=EC=99=B8?= =?UTF-8?q?=ED=95=98=EC=A7=80=20=EB=AA=BB=ED=95=9C=20=EB=B2=84=EA=B7=B8=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=20-=20@AuthenticationPrincipal=20=EB=A5=BC?= =?UTF-8?q?=20=ED=86=B5=ED=95=B4=20=EC=82=AC=EC=9A=A9=EC=9E=90=20Email?= =?UTF-8?q?=EB=A5=BC=20=EA=B8=B0=EC=A4=80=EC=9C=BC=EB=A1=9C=20=EC=A1=B0?= =?UTF-8?q?=ED=9A=8C=ED=95=A0=20=EC=88=98=20=EC=9E=88=EB=8F=84=EB=A1=9D=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../csQuiz/controller/CsQuizzesController.java | 11 ++++++----- .../csQuiz/controller/request/QuizQueryRequest.java | 2 +- .../service/sub/quizzes/FindQuizQuerytImpl.java | 4 ++-- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/src/main/java/darkoverload/itzip/feature/csQuiz/controller/CsQuizzesController.java b/src/main/java/darkoverload/itzip/feature/csQuiz/controller/CsQuizzesController.java index f8679559..a20ebdd3 100644 --- a/src/main/java/darkoverload/itzip/feature/csQuiz/controller/CsQuizzesController.java +++ b/src/main/java/darkoverload/itzip/feature/csQuiz/controller/CsQuizzesController.java @@ -4,6 +4,7 @@ import darkoverload.itzip.feature.csQuiz.entity.SortBy; import darkoverload.itzip.feature.csQuiz.controller.response.QuizDetailResponse; import darkoverload.itzip.feature.csQuiz.service.QuizService; +import darkoverload.itzip.feature.jwt.infrastructure.CustomUserDetails; import darkoverload.itzip.global.config.response.code.CommonExceptionCode; import darkoverload.itzip.global.config.response.code.CommonResponseCode; import darkoverload.itzip.global.config.swagger.ExceptionCodeAnnotations; @@ -14,9 +15,9 @@ import lombok.RequiredArgsConstructor; import org.springframework.hateoas.EntityModel; import org.springframework.hateoas.PagedModel; +import org.springframework.security.core.annotation.AuthenticationPrincipal; import org.springframework.web.bind.annotation.*; - //퀴즈(복수) 관련 엔드포인트 모음 @Tag(name = "Computer Science Quiz", description = "퀴즈(복수) 관련 엔드포인트 모음") @RestController @@ -31,7 +32,6 @@ public class CsQuizzesController { * @param difficulty 퀴즈 난이도 (선택 사항) * @param categoryId 카테고리 ID (선택 사항) * @param sortBy 정렬 기준 (기본값: NEWEST) - * @param userId 사용자 ID (기본값: 0) * @param inUserSolved 사용자가 푼 퀴즈 포함 여부 (기본값: false) * @param page 페이지 번호 (기본값: 0) * @param size 페이지 크기 (기본값: 10) @@ -46,19 +46,20 @@ public class CsQuizzesController { @ExceptionCodeAnnotations({CommonExceptionCode.NOT_FOUND_USER}) @GetMapping("/search") public PagedModel> getFilteredAndSortedQuizzes( + @AuthenticationPrincipal CustomUserDetails userDetails, @Parameter(description = "퀴즈 난이도 입력칸 1~3") @RequestParam(required = false) Integer difficulty, @Parameter(description = "카테고리 식별값 입력칸") @RequestParam(required = false) Long categoryId, @Parameter(description = "NEWEST 새로운 순, OLDEST 오래된 순, RECOMMENED 추천순 아무것도 없으면 새로운순") @RequestParam(required = false, defaultValue = "NEWEST") SortBy sortBy, - @Parameter(description = "사용자 ID") @RequestParam(required = false) Long userId, @Parameter(description = "사용자가 푼 문제를 포함 하는지 true면 포함 false면 미포함") @RequestParam(required = false, defaultValue = "false") boolean inUserSolved, @Parameter(description = "문제 페이지 0부터 시작") @RequestParam(defaultValue = "0") int page, @Parameter(description = "가져올 문제 수") @RequestParam(defaultValue = "10") int size, - @Parameter(description = "검색할 단어") @RequestParam(required = false) String keyword) { + @Parameter(description = "검색할 단어") @RequestParam(required = false) String keyword + ) { QuizQueryRequest quizQueryRequest = QuizQueryRequest.builder() .difficulty(difficulty) .categoryId(categoryId) .sortBy(sortBy) - .userId(userId) + .email(userDetails.getEmail()) .inUserSolved(inUserSolved) .page(page) .size(size) diff --git a/src/main/java/darkoverload/itzip/feature/csQuiz/controller/request/QuizQueryRequest.java b/src/main/java/darkoverload/itzip/feature/csQuiz/controller/request/QuizQueryRequest.java index 798eb790..a37db9c8 100644 --- a/src/main/java/darkoverload/itzip/feature/csQuiz/controller/request/QuizQueryRequest.java +++ b/src/main/java/darkoverload/itzip/feature/csQuiz/controller/request/QuizQueryRequest.java @@ -15,7 +15,7 @@ public class QuizQueryRequest { //NEWEST, OLDEST private SortBy sortBy; //사용자 ID - private Long userId; + private String email; //사용자가 푼문제를 포함하는지 ture면 포함 false면 미포함 private boolean inUserSolved; //문제 페이지 0부터 시작 diff --git a/src/main/java/darkoverload/itzip/feature/csQuiz/service/sub/quizzes/FindQuizQuerytImpl.java b/src/main/java/darkoverload/itzip/feature/csQuiz/service/sub/quizzes/FindQuizQuerytImpl.java index 797e3731..07b29eca 100644 --- a/src/main/java/darkoverload/itzip/feature/csQuiz/service/sub/quizzes/FindQuizQuerytImpl.java +++ b/src/main/java/darkoverload/itzip/feature/csQuiz/service/sub/quizzes/FindQuizQuerytImpl.java @@ -51,9 +51,9 @@ public PagedModel> findQuizzesByQuery(QuizQueryR // 사용자가 푼 문제의 Id값들만 저장할 리스트 초기화 List solvedProblemIds = new ArrayList<>(); - if (quizQueryRequest.getUserId() != null){ + if (quizQueryRequest.isInUserSolved() != true && quizQueryRequest.getEmail() != null) { //사용자를 찾고 사용자가 없을시 사용자가 없음 예외 출력 - UserEntity userEntity = userService.getById(quizQueryRequest.getUserId()) + UserEntity userEntity = userService.getByEmail(quizQueryRequest.getEmail()) .convertToEntity(); //사용자가 푼문제매핑 테이블 list로 받아옴