From 78ebb8d4dd03590ac5bddadeb5375ca3de9e685e Mon Sep 17 00:00:00 2001 From: Amepistheo Date: Thu, 6 Feb 2025 23:50:28 +0900 Subject: [PATCH 1/5] =?UTF-8?q?refactor:=20=EC=A4=91=EB=B3=B5=20=EB=AC=B8?= =?UTF-8?q?=EC=A0=9C=20=EB=82=98=EC=98=A4=EB=8A=94=20=EC=98=A4=EB=A5=98=20?= =?UTF-8?q?=ED=95=B4=EA=B2=B0=20#109?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kidbean/server/wordquiz/application/WordQuizService.java | 3 ++- .../server/wordquiz/repository/WordQuizRepository.java | 5 +++-- .../server/wordquiz/application/WordQuizServiceTest.java | 2 +- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/main/java/soongsil/kidbean/server/wordquiz/application/WordQuizService.java b/src/main/java/soongsil/kidbean/server/wordquiz/application/WordQuizService.java index b122e37..0a5d75b 100644 --- a/src/main/java/soongsil/kidbean/server/wordquiz/application/WordQuizService.java +++ b/src/main/java/soongsil/kidbean/server/wordquiz/application/WordQuizService.java @@ -3,6 +3,7 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.springframework.data.domain.PageRequest; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import soongsil.kidbean.server.global.util.RandNumUtil; @@ -64,7 +65,7 @@ private int getWordQuizCount(Member member) { } private WordQuiz generateRandomWordQuizPage(Member member, int quizIdx) { - return wordQuizRepository.findSingleResultByMember(member, (long) quizIdx).get(0); + return wordQuizRepository.findSingleResultByMember(member, PageRequest.of(quizIdx, 1)).get(0); } @Transactional diff --git a/src/main/java/soongsil/kidbean/server/wordquiz/repository/WordQuizRepository.java b/src/main/java/soongsil/kidbean/server/wordquiz/repository/WordQuizRepository.java index d185783..2ecb40d 100644 --- a/src/main/java/soongsil/kidbean/server/wordquiz/repository/WordQuizRepository.java +++ b/src/main/java/soongsil/kidbean/server/wordquiz/repository/WordQuizRepository.java @@ -1,5 +1,6 @@ package soongsil.kidbean.server.wordquiz.repository; +import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; import org.springframework.stereotype.Repository; @@ -15,8 +16,8 @@ public interface WordQuizRepository extends JpaRepository { @Query("SELECT count(*) FROM WordQuiz wq WHERE wq.member = :member OR wq.member.role = 'ADMIN'") Integer countByMemberOrAdmin(Member member); - @Query("SELECT wq FROM WordQuiz wq JOIN FETCH wq.words WHERE wq.quizId = :quizId AND wq.member = :member OR wq.member.role = 'ADMIN'") - List findSingleResultByMember(Member member, Long quizId); + @Query("SELECT wq FROM WordQuiz wq JOIN FETCH wq.words WHERE wq.member = :member OR wq.member.role = 'ADMIN'") + List findSingleResultByMember(Member member, Pageable pageable); Optional findByQuizIdAndMember_MemberId(Long quizId, Long memberId); diff --git a/src/test/java/soongsil/kidbean/server/wordquiz/application/WordQuizServiceTest.java b/src/test/java/soongsil/kidbean/server/wordquiz/application/WordQuizServiceTest.java index 1b8b26f..84587f7 100644 --- a/src/test/java/soongsil/kidbean/server/wordquiz/application/WordQuizServiceTest.java +++ b/src/test/java/soongsil/kidbean/server/wordquiz/application/WordQuizServiceTest.java @@ -53,7 +53,7 @@ void selectRandomWordQuiz() { //given given(memberRepository.findById(anyLong())).willReturn(Optional.of(MEMBER1)); given(wordQuizRepository.countByMemberOrAdmin(any(Member.class))).willReturn(4); - given(wordQuizRepository.findSingleResultByMember(any(Member.class), any(Long.class))) + given(wordQuizRepository.findSingleResultByMember(any(Member.class), any(Pageable.class))) .willReturn(List.of(WORD_QUIZ)); //when From 1af1fe522b25c413c20aef4f1914276e1960f9cb Mon Sep 17 00:00:00 2001 From: Amepistheo Date: Fri, 7 Feb 2025 19:03:12 +0900 Subject: [PATCH 2/5] =?UTF-8?q?refactor:=20rand()=EB=A5=BC=20=EC=82=AC?= =?UTF-8?q?=EC=9A=A9=ED=95=B4=20ID=20=EA=B8=B0=EB=B0=98=20=EB=9E=9C?= =?UTF-8?q?=EB=8D=A4=20WordQuiz=20=EC=A1=B0=ED=9A=8C=20#109?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../wordquiz/application/WordQuizService.java | 13 +++++-------- .../dto/response/WordQuizSolveListResponse.java | 10 +++++++++- .../wordquiz/repository/WordQuizRepository.java | 7 +++++++ 3 files changed, 21 insertions(+), 9 deletions(-) diff --git a/src/main/java/soongsil/kidbean/server/wordquiz/application/WordQuizService.java b/src/main/java/soongsil/kidbean/server/wordquiz/application/WordQuizService.java index 0a5d75b..7dae8c2 100644 --- a/src/main/java/soongsil/kidbean/server/wordquiz/application/WordQuizService.java +++ b/src/main/java/soongsil/kidbean/server/wordquiz/application/WordQuizService.java @@ -6,7 +6,6 @@ import org.springframework.data.domain.PageRequest; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import soongsil.kidbean.server.global.util.RandNumUtil; import soongsil.kidbean.server.member.domain.Member; import soongsil.kidbean.server.member.exception.MemberNotFoundException; import soongsil.kidbean.server.member.repository.MemberRepository; @@ -45,19 +44,17 @@ public class WordQuizService { * @return 랜덤 문제가 들어 있는 DTO */ public WordQuizSolveListResponse selectRandomWordQuiz(Long memberId, Integer quizNum) { - Member member = memberRepository.findById(memberId) .orElseThrow(() -> new MemberNotFoundException(MEMBER_NOT_FOUND)); - int totalQuizNum = getWordQuizCount(member); + List randomQuizIds = wordQuizRepository.findRandomWordQuizIds(member, quizNum); List wordQuizSolveResponseList = - RandNumUtil.generateRandomNumbers(0, totalQuizNum - 1, quizNum).stream() - .map(quizIdx -> generateRandomWordQuizPage(member, quizIdx)) - .map(WordQuizSolveResponse::from) - .toList(); + wordQuizRepository.findByIdsWithWords(randomQuizIds).stream() + .map(WordQuizSolveResponse::from) + .toList(); - return new WordQuizSolveListResponse(wordQuizSolveResponseList); + return WordQuizSolveListResponse.from(wordQuizSolveResponseList); } private int getWordQuizCount(Member member) { diff --git a/src/main/java/soongsil/kidbean/server/wordquiz/dto/response/WordQuizSolveListResponse.java b/src/main/java/soongsil/kidbean/server/wordquiz/dto/response/WordQuizSolveListResponse.java index a58c254..913c82e 100644 --- a/src/main/java/soongsil/kidbean/server/wordquiz/dto/response/WordQuizSolveListResponse.java +++ b/src/main/java/soongsil/kidbean/server/wordquiz/dto/response/WordQuizSolveListResponse.java @@ -1,8 +1,16 @@ package soongsil.kidbean.server.wordquiz.dto.response; +import lombok.Builder; + import java.util.List; +@Builder public record WordQuizSolveListResponse( List wordQuizSolveResponseList ) { -} + public static WordQuizSolveListResponse from(List wordQuizSolveResponseList) { + return WordQuizSolveListResponse.builder() + .wordQuizSolveResponseList(wordQuizSolveResponseList) + .build(); + } +} \ No newline at end of file diff --git a/src/main/java/soongsil/kidbean/server/wordquiz/repository/WordQuizRepository.java b/src/main/java/soongsil/kidbean/server/wordquiz/repository/WordQuizRepository.java index 2ecb40d..e1902f3 100644 --- a/src/main/java/soongsil/kidbean/server/wordquiz/repository/WordQuizRepository.java +++ b/src/main/java/soongsil/kidbean/server/wordquiz/repository/WordQuizRepository.java @@ -19,6 +19,13 @@ public interface WordQuizRepository extends JpaRepository { @Query("SELECT wq FROM WordQuiz wq JOIN FETCH wq.words WHERE wq.member = :member OR wq.member.role = 'ADMIN'") List findSingleResultByMember(Member member, Pageable pageable); + @Query("SELECT wq.quizId FROM WordQuiz wq WHERE wq.member = :member OR wq.member.role = 'ADMIN' ORDER BY RAND() LIMIT :quizNum") + List findRandomWordQuizIds(Member member, int quizNum); + + @Query("SELECT wq FROM WordQuiz wq JOIN FETCH wq.words w WHERE wq.quizId IN :quizIds") + List findByIdsWithWords(List quizIds); + + Optional findByQuizIdAndMember_MemberId(Long quizId, Long memberId); List findAllByMember_MemberId(Long memberId); From 5fd15682d87b7e642dd550393ee979e32c3f85d9 Mon Sep 17 00:00:00 2001 From: Amepistheo Date: Fri, 7 Feb 2025 21:51:17 +0900 Subject: [PATCH 3/5] =?UTF-8?q?refactor:=20=EB=8D=94=EB=AF=B8=EB=8D=B0?= =?UTF-8?q?=EC=9D=B4=ED=84=B0=20=EB=B0=8F=20=EB=82=9C=EC=88=98=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1,=20=EA=B4=80=EB=A6=AC=EC=9E=90=20=EB=93=B1=EB=A1=9D?= =?UTF-8?q?=20=EB=AC=B8=EC=A0=9C=20=EC=97=AC=EB=B6=80=20column=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80=20#109?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../server/wordquiz/domain/WordQuiz.java | 14 +- .../repository/init/WordQuizInitializer.java | 320 ++++++++++++++++++ 2 files changed, 332 insertions(+), 2 deletions(-) diff --git a/src/main/java/soongsil/kidbean/server/wordquiz/domain/WordQuiz.java b/src/main/java/soongsil/kidbean/server/wordquiz/domain/WordQuiz.java index 78e4946..096c028 100644 --- a/src/main/java/soongsil/kidbean/server/wordquiz/domain/WordQuiz.java +++ b/src/main/java/soongsil/kidbean/server/wordquiz/domain/WordQuiz.java @@ -10,6 +10,8 @@ import java.util.ArrayList; import java.util.List; +import java.util.concurrent.ThreadLocalRandom; + import soongsil.kidbean.server.quizsolve.domain.type.QuizCategory; @Table(name = "word_quiz") @@ -36,6 +38,12 @@ public class WordQuiz { @Enumerated(EnumType.STRING) private Level level; + @Column(name = "is_default") + private Boolean isDefault; + + @Column(name = "rand_val") + private Long randVal; + @JoinColumn(name = "member_id") @ManyToOne(fetch = FetchType.LAZY) private Member member; @@ -44,14 +52,16 @@ public class WordQuiz { private List words = new ArrayList<>(); @Builder - public WordQuiz(QuizCategory quizCategory, String title, String answer, Level level, Member member, - List words) { + public WordQuiz(QuizCategory quizCategory, String title, String answer, Level level, + Boolean isDefault, Member member, List words) { this.quizCategory = quizCategory; this.title = title; this.answer = answer; this.level = level; + this.isDefault = isDefault; this.member = member; this.words = words; + this.randVal = ThreadLocalRandom.current().nextLong(Long.MAX_VALUE); } public void updateWordQuiz(String title, String answer) { diff --git a/src/main/java/soongsil/kidbean/server/wordquiz/repository/init/WordQuizInitializer.java b/src/main/java/soongsil/kidbean/server/wordquiz/repository/init/WordQuizInitializer.java index 747a663..6711df5 100644 --- a/src/main/java/soongsil/kidbean/server/wordquiz/repository/init/WordQuizInitializer.java +++ b/src/main/java/soongsil/kidbean/server/wordquiz/repository/init/WordQuizInitializer.java @@ -45,6 +45,7 @@ public void run(ApplicationArguments args) { .answer("자동차") .level(SILVER) .member(DUMMY_MEMBER) + .isDefault(false) .build(); WordQuiz WordQuiz2 = WordQuiz.builder() @@ -53,6 +54,7 @@ public void run(ApplicationArguments args) { .answer("자") .level(GOLD) .member(DUMMY_MEMBER) + .isDefault(false) .build(); WordQuiz WordQuiz3 = WordQuiz.builder() @@ -61,6 +63,7 @@ public void run(ApplicationArguments args) { .answer("물병") .level(GOLD) .member(DUMMY_MEMBER) + .isDefault(false) .build(); WordQuiz WordQuiz4 = WordQuiz.builder() @@ -69,6 +72,7 @@ public void run(ApplicationArguments args) { .answer("비행기") .level(SILVER) .member(DUMMY_MEMBER) + .isDefault(false) .build(); WordQuiz WordQuiz5 = WordQuiz.builder() @@ -77,6 +81,7 @@ public void run(ApplicationArguments args) { .answer("시계") .level(DIAMOND) .member(DUMMY_MEMBER) + .isDefault(false) .build(); WordQuiz WordQuiz6 = WordQuiz.builder() @@ -85,6 +90,7 @@ public void run(ApplicationArguments args) { .answer("물고기") .level(BRONZE) .member(DUMMY_MEMBER) + .isDefault(false) .build(); WordQuiz WordQuiz7 = WordQuiz.builder() @@ -93,6 +99,7 @@ public void run(ApplicationArguments args) { .answer("코끼리") .level(SILVER) .member(DUMMY_MEMBER) + .isDefault(false) .build(); WordQuiz WordQuiz8 = WordQuiz.builder() @@ -101,6 +108,7 @@ public void run(ApplicationArguments args) { .answer("학교") .level(PLATINUM) .member(DUMMY_MEMBER) + .isDefault(false) .build(); WordQuiz WordQuiz9 = WordQuiz.builder() @@ -109,6 +117,7 @@ public void run(ApplicationArguments args) { .answer("기차") .level(SILVER) .member(DUMMY_MEMBER) + .isDefault(false) .build(); WordQuiz WordQuiz10 = WordQuiz.builder() @@ -117,6 +126,7 @@ public void run(ApplicationArguments args) { .answer("우산") .level(DIAMOND) .member(DUMMY_MEMBER) + .isDefault(false) .build(); WordQuiz WordQuiz11 = WordQuiz.builder() @@ -125,6 +135,7 @@ public void run(ApplicationArguments args) { .answer("고양이") .level(DIAMOND) .member(DUMMY_ADMIN) + .isDefault(true) .build(); WordQuiz WordQuiz12 = WordQuiz.builder() @@ -133,6 +144,7 @@ public void run(ApplicationArguments args) { .answer("신발") .level(GOLD) .member(DUMMY_ADMIN) + .isDefault(true) .build(); WordQuiz WordQuiz13 = WordQuiz.builder() @@ -141,6 +153,7 @@ public void run(ApplicationArguments args) { .answer("동그라미") .level(PLATINUM) .member(DUMMY_ADMIN) + .isDefault(true) .build(); WordQuiz WordQuiz14 = WordQuiz.builder() @@ -149,6 +162,7 @@ public void run(ApplicationArguments args) { .answer("사과") .level(BRONZE) .member(DUMMY_ADMIN) + .isDefault(true) .build(); WordQuiz WordQuiz15 = WordQuiz.builder() @@ -157,6 +171,7 @@ public void run(ApplicationArguments args) { .answer("손") .level(GOLD) .member(DUMMY_ADMIN) + .isDefault(true) .build(); WordQuiz WordQuiz16 = WordQuiz.builder() @@ -165,6 +180,7 @@ public void run(ApplicationArguments args) { .answer("엄마") .level(DIAMOND) .member(DUMMY_ADMIN) + .isDefault(true) .build(); WordQuiz WordQuiz17 = WordQuiz.builder() @@ -173,6 +189,7 @@ public void run(ApplicationArguments args) { .answer("태양") .level(DIAMOND) .member(DUMMY_ADMIN) + .isDefault(true) .build(); WordQuiz WordQuiz18 = WordQuiz.builder() @@ -181,6 +198,7 @@ public void run(ApplicationArguments args) { .answer("다람쥐") .level(SILVER) .member(DUMMY_ADMIN) + .isDefault(true) .build(); WordQuiz WordQuiz19 = WordQuiz.builder() @@ -189,6 +207,7 @@ public void run(ApplicationArguments args) { .answer("보석") .level(PLATINUM) .member(DUMMY_ADMIN) + .isDefault(true) .build(); WordQuiz WordQuiz20 = WordQuiz.builder() @@ -197,6 +216,187 @@ public void run(ApplicationArguments args) { .answer("아빠") .level(DIAMOND) .member(DUMMY_ADMIN) + .isDefault(true) + .build(); + + WordQuiz WordQuiz21 = WordQuiz.builder() + .quizCategory(QuizCategory.NONE) + .title("교통수단") + .answer("버스") + .level(SILVER) + .member(DUMMY_MEMBER) + .isDefault(false) + .build(); + + WordQuiz WordQuiz22 = WordQuiz.builder() + .quizCategory(QuizCategory.ANIMAL) + .title("동물") + .answer("고양이") + .level(GOLD) + .member(DUMMY_MEMBER) + .isDefault(false) + .build(); + + WordQuiz WordQuiz23 = WordQuiz.builder() + .quizCategory(QuizCategory.PLANT) + .title("식물") + .answer("나무") + .level(GOLD) + .member(DUMMY_MEMBER) + .isDefault(false) + .build(); + + WordQuiz WordQuiz24 = WordQuiz.builder() + .quizCategory(QuizCategory.FOOD) + .title("과일") + .answer("딸기") + .level(SILVER) + .member(DUMMY_MEMBER) + .isDefault(false) + .build(); + + WordQuiz WordQuiz25 = WordQuiz.builder() + .quizCategory(QuizCategory.NONE) + .title("가족") + .answer("형") + .level(DIAMOND) + .member(DUMMY_MEMBER) + .isDefault(false) + .build(); + + WordQuiz WordQuiz26 = WordQuiz.builder() + .quizCategory(QuizCategory.FOOD) + .title("음식") + .answer("김밥") + .level(BRONZE) + .member(DUMMY_MEMBER) + .isDefault(false) + .build(); + + WordQuiz WordQuiz27 = WordQuiz.builder() + .quizCategory(QuizCategory.NONE) + .title("신체") + .answer("눈") + .level(SILVER) + .member(DUMMY_MEMBER) + .isDefault(false) + .build(); + + WordQuiz WordQuiz28 = WordQuiz.builder() + .quizCategory(QuizCategory.NONE) + .title("인물") + .answer("영화배우") + .level(PLATINUM) + .member(DUMMY_MEMBER) + .isDefault(false) + .build(); + + WordQuiz WordQuiz29 = WordQuiz.builder() + .quizCategory(QuizCategory.ANIMAL) + .title("동물") + .answer("코끼리") + .level(SILVER) + .member(DUMMY_MEMBER) + .isDefault(false) + .build(); + + WordQuiz WordQuiz30 = WordQuiz.builder() + .quizCategory(QuizCategory.NONE) + .title("날씨") + .answer("비") + .level(DIAMOND) + .member(DUMMY_MEMBER) + .isDefault(false) + .build(); + + WordQuiz WordQuiz31 = WordQuiz.builder() + .quizCategory(QuizCategory.OBJECT) + .title("음악기기") + .answer("피아노") + .level(DIAMOND) + .member(DUMMY_ADMIN) + .isDefault(true) + .build(); + + WordQuiz WordQuiz32 = WordQuiz.builder() + .quizCategory(QuizCategory.NONE) + .title("모양") + .answer("사각형") + .level(GOLD) + .member(DUMMY_ADMIN) + .isDefault(true) + .build(); + + WordQuiz WordQuiz33 = WordQuiz.builder() + .quizCategory(QuizCategory.NONE) + .title("우주") + .answer("별자리") + .level(PLATINUM) + .member(DUMMY_ADMIN) + .isDefault(true) + .build(); + + WordQuiz WordQuiz34 = WordQuiz.builder() + .quizCategory(QuizCategory.ANIMAL) + .title("동물") + .answer("사자") + .level(BRONZE) + .member(DUMMY_ADMIN) + .isDefault(true) + .build(); + + WordQuiz WordQuiz35 = WordQuiz.builder() + .quizCategory(QuizCategory.OBJECT) + .title("사물") + .answer("책") + .level(GOLD) + .member(DUMMY_ADMIN) + .isDefault(true) + .build(); + + WordQuiz WordQuiz36 = WordQuiz.builder() + .quizCategory(QuizCategory.OBJECT) + .title("기계") + .answer("전화기") + .level(DIAMOND) + .member(DUMMY_ADMIN) + .isDefault(true) + .build(); + + WordQuiz WordQuiz37 = WordQuiz.builder() + .quizCategory(QuizCategory.NONE) + .title("모양") + .answer("원") + .level(DIAMOND) + .member(DUMMY_ADMIN) + .isDefault(true) + .build(); + + WordQuiz WordQuiz38 = WordQuiz.builder() + .quizCategory(QuizCategory.OBJECT) + .title("기계") + .answer("냉장고") + .level(SILVER) + .member(DUMMY_ADMIN) + .isDefault(true) + .build(); + + WordQuiz WordQuiz39 = WordQuiz.builder() + .quizCategory(QuizCategory.NONE) + .title("가족") + .answer("삼촌") + .level(PLATINUM) + .member(DUMMY_ADMIN) + .isDefault(true) + .build(); + + WordQuiz WordQuiz40 = WordQuiz.builder() + .quizCategory(QuizCategory.NONE) + .title("시간") + .answer("분") + .level(DIAMOND) + .member(DUMMY_ADMIN) + .isDefault(true) .build(); WordQuizList.add(WordQuiz1); @@ -219,6 +419,26 @@ public void run(ApplicationArguments args) { WordQuizList.add(WordQuiz18); WordQuizList.add(WordQuiz19); WordQuizList.add(WordQuiz20); + WordQuizList.add(WordQuiz21); + WordQuizList.add(WordQuiz22); + WordQuizList.add(WordQuiz23); + WordQuizList.add(WordQuiz24); + WordQuizList.add(WordQuiz25); + WordQuizList.add(WordQuiz26); + WordQuizList.add(WordQuiz27); + WordQuizList.add(WordQuiz28); + WordQuizList.add(WordQuiz29); + WordQuizList.add(WordQuiz30); + WordQuizList.add(WordQuiz31); + WordQuizList.add(WordQuiz32); + WordQuizList.add(WordQuiz33); + WordQuizList.add(WordQuiz34); + WordQuizList.add(WordQuiz35); + WordQuizList.add(WordQuiz36); + WordQuizList.add(WordQuiz37); + WordQuizList.add(WordQuiz38); + WordQuizList.add(WordQuiz39); + WordQuizList.add(WordQuiz40); List wordList = new ArrayList<>(); wordList.add(new Word("엄마", WordQuiz1)); @@ -321,6 +541,106 @@ public void run(ApplicationArguments args) { wordList.add(new Word("점심", WordQuiz20)); wordList.add(new Word("저녁", WordQuiz20)); + wordList.add(new Word("버스", WordQuiz21)); + wordList.add(new Word("지하철", WordQuiz21)); + wordList.add(new Word("택시", WordQuiz21)); + wordList.add(new Word("자전거", WordQuiz21)); + + wordList.add(new Word("고양이", WordQuiz22)); + wordList.add(new Word("강아지", WordQuiz22)); + wordList.add(new Word("말", WordQuiz22)); + wordList.add(new Word("토끼", WordQuiz22)); + + wordList.add(new Word("나무", WordQuiz23)); + wordList.add(new Word("꽃", WordQuiz23)); + wordList.add(new Word("풀", WordQuiz23)); + wordList.add(new Word("선인장", WordQuiz23)); + + wordList.add(new Word("딸기", WordQuiz24)); + wordList.add(new Word("바나나", WordQuiz24)); + wordList.add(new Word("사과", WordQuiz24)); + wordList.add(new Word("포도", WordQuiz24)); + + wordList.add(new Word("형", WordQuiz25)); + wordList.add(new Word("동생", WordQuiz25)); + wordList.add(new Word("아빠", WordQuiz25)); + wordList.add(new Word("엄마", WordQuiz25)); + + wordList.add(new Word("김밥", WordQuiz26)); + wordList.add(new Word("떡볶이", WordQuiz26)); + wordList.add(new Word("초밥", WordQuiz26)); + wordList.add(new Word("라면", WordQuiz26)); + + wordList.add(new Word("눈", WordQuiz27)); + wordList.add(new Word("귀", WordQuiz27)); + wordList.add(new Word("입", WordQuiz27)); + wordList.add(new Word("손", WordQuiz27)); + + wordList.add(new Word("영화배우", WordQuiz28)); + wordList.add(new Word("가수", WordQuiz28)); + wordList.add(new Word("작가", WordQuiz28)); + wordList.add(new Word("스포츠선수", WordQuiz28)); + + wordList.add(new Word("코끼리", WordQuiz29)); + wordList.add(new Word("호랑이", WordQuiz29)); + wordList.add(new Word("사슴", WordQuiz29)); + wordList.add(new Word("개구리", WordQuiz29)); + + wordList.add(new Word("비", WordQuiz30)); + wordList.add(new Word("눈", WordQuiz30)); + wordList.add(new Word("안개", WordQuiz30)); + wordList.add(new Word("바람", WordQuiz30)); + + wordList.add(new Word("피아노", WordQuiz31)); + wordList.add(new Word("기타", WordQuiz31)); + wordList.add(new Word("드럼", WordQuiz31)); + wordList.add(new Word("바이올린", WordQuiz31)); + + wordList.add(new Word("사각형", WordQuiz32)); + wordList.add(new Word("삼각형", WordQuiz32)); + wordList.add(new Word("원", WordQuiz32)); + wordList.add(new Word("다각형", WordQuiz32)); + + wordList.add(new Word("별자리", WordQuiz33)); + wordList.add(new Word("행성", WordQuiz33)); + wordList.add(new Word("우주선", WordQuiz33)); + wordList.add(new Word("은하", WordQuiz33)); + + wordList.add(new Word("사자", WordQuiz34)); + wordList.add(new Word("호랑이", WordQuiz34)); + wordList.add(new Word("곰", WordQuiz34)); + wordList.add(new Word("늑대", WordQuiz34)); + + wordList.add(new Word("책", WordQuiz35)); + wordList.add(new Word("연필", WordQuiz35)); + wordList.add(new Word("종이", WordQuiz35)); + wordList.add(new Word("노트", WordQuiz35)); + + wordList.add(new Word("전화기", WordQuiz36)); + wordList.add(new Word("컴퓨터", WordQuiz36)); + wordList.add(new Word("텔레비전", WordQuiz36)); + wordList.add(new Word("프린터", WordQuiz36)); + + wordList.add(new Word("원", WordQuiz37)); + wordList.add(new Word("정사각형", WordQuiz37)); + wordList.add(new Word("타원", WordQuiz37)); + wordList.add(new Word("삼각형", WordQuiz37)); + + wordList.add(new Word("냉장고", WordQuiz38)); + wordList.add(new Word("세탁기", WordQuiz38)); + wordList.add(new Word("에어컨", WordQuiz38)); + wordList.add(new Word("전자레인지", WordQuiz38)); + + wordList.add(new Word("삼촌", WordQuiz39)); + wordList.add(new Word("이모", WordQuiz39)); + wordList.add(new Word("조부모", WordQuiz39)); + wordList.add(new Word("사촌", WordQuiz39)); + + wordList.add(new Word("분", WordQuiz40)); + wordList.add(new Word("초", WordQuiz40)); + wordList.add(new Word("시간", WordQuiz40)); + wordList.add(new Word("날", WordQuiz40)); + wordQuizRepository.saveAll(WordQuizList); wordRepository.saveAll(wordList); } From d4424fa2b11f517092b5067a083e5fb64d22593b Mon Sep 17 00:00:00 2001 From: Amepistheo Date: Fri, 7 Feb 2025 21:54:15 +0900 Subject: [PATCH 4/5] =?UTF-8?q?refactor:=20Member=20=ED=85=8C=EC=9D=B4?= =?UTF-8?q?=EB=B8=94=EA=B3=BC=EC=9D=98=20join=20=EC=A0=9C=EA=B1=B0=20?= =?UTF-8?q?=EB=B0=8F=20rand()=20=EC=A0=9C=EA=B1=B0=20#109?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../wordquiz/application/WordQuizService.java | 13 +++++++------ .../wordquiz/repository/WordQuizRepository.java | 10 ++++++---- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/src/main/java/soongsil/kidbean/server/wordquiz/application/WordQuizService.java b/src/main/java/soongsil/kidbean/server/wordquiz/application/WordQuizService.java index 7dae8c2..5b28db9 100644 --- a/src/main/java/soongsil/kidbean/server/wordquiz/application/WordQuizService.java +++ b/src/main/java/soongsil/kidbean/server/wordquiz/application/WordQuizService.java @@ -21,6 +21,7 @@ import soongsil.kidbean.server.wordquiz.repository.WordRepository; import java.util.List; +import java.util.concurrent.ThreadLocalRandom; import static soongsil.kidbean.server.member.exception.errorcode.MemberErrorCode.MEMBER_NOT_FOUND; import static soongsil.kidbean.server.quizsolve.application.vo.QuizType.WORD_QUIZ; @@ -44,17 +45,17 @@ public class WordQuizService { * @return 랜덤 문제가 들어 있는 DTO */ public WordQuizSolveListResponse selectRandomWordQuiz(Long memberId, Integer quizNum) { - Member member = memberRepository.findById(memberId) - .orElseThrow(() -> new MemberNotFoundException(MEMBER_NOT_FOUND)); + long count = wordQuizRepository.countByMemberId(memberId); + int randomOffset = ThreadLocalRandom.current().nextInt((int) (count / quizNum)); - List randomQuizIds = wordQuizRepository.findRandomWordQuizIds(member, quizNum); + List randomQuizIds = wordQuizRepository.findRandomQuizIds(memberId, PageRequest.of(randomOffset, quizNum)); List wordQuizSolveResponseList = wordQuizRepository.findByIdsWithWords(randomQuizIds).stream() - .map(WordQuizSolveResponse::from) - .toList(); + .map(WordQuizSolveResponse::from) + .toList(); - return WordQuizSolveListResponse.from(wordQuizSolveResponseList); + return new WordQuizSolveListResponse(wordQuizSolveResponseList); } private int getWordQuizCount(Member member) { diff --git a/src/main/java/soongsil/kidbean/server/wordquiz/repository/WordQuizRepository.java b/src/main/java/soongsil/kidbean/server/wordquiz/repository/WordQuizRepository.java index e1902f3..93c5f20 100644 --- a/src/main/java/soongsil/kidbean/server/wordquiz/repository/WordQuizRepository.java +++ b/src/main/java/soongsil/kidbean/server/wordquiz/repository/WordQuizRepository.java @@ -19,12 +19,14 @@ public interface WordQuizRepository extends JpaRepository { @Query("SELECT wq FROM WordQuiz wq JOIN FETCH wq.words WHERE wq.member = :member OR wq.member.role = 'ADMIN'") List findSingleResultByMember(Member member, Pageable pageable); - @Query("SELECT wq.quizId FROM WordQuiz wq WHERE wq.member = :member OR wq.member.role = 'ADMIN' ORDER BY RAND() LIMIT :quizNum") - List findRandomWordQuizIds(Member member, int quizNum); + @Query("SELECT COUNT(wq) FROM WordQuiz wq WHERE wq.member.memberId = :memberId OR wq.isDefault = TRUE") + long countByMemberId(Long memberId); - @Query("SELECT wq FROM WordQuiz wq JOIN FETCH wq.words w WHERE wq.quizId IN :quizIds") - List findByIdsWithWords(List quizIds); + @Query("SELECT wq.quizId FROM WordQuiz wq WHERE wq.member.memberId = :memberId OR wq.isDefault = TRUE ORDER BY wq.randVal") + List findRandomQuizIds(Long memberId, Pageable pageable); + @Query("SELECT wq FROM WordQuiz wq JOIN FETCH wq.words w WHERE wq.quizId IN :quizIds ORDER BY wq.randVal") + List findByIdsWithWords(List quizIds); Optional findByQuizIdAndMember_MemberId(Long quizId, Long memberId); From af9991fd0a8e38e838c72cde95e78da46613d9e1 Mon Sep 17 00:00:00 2001 From: Amepistheo Date: Sat, 8 Feb 2025 23:06:39 +0900 Subject: [PATCH 5/5] =?UTF-8?q?test:=20=EB=9E=9C=EB=8D=A4=20WordQuiz=20?= =?UTF-8?q?=EC=A1=B0=ED=9A=8C=20=EA=B4=80=EB=A0=A8=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=EC=BD=94=EB=93=9C=20=EC=88=98=EC=A0=95=20#109?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/WordQuizServiceTest.java | 24 ++++++++++++------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/src/test/java/soongsil/kidbean/server/wordquiz/application/WordQuizServiceTest.java b/src/test/java/soongsil/kidbean/server/wordquiz/application/WordQuizServiceTest.java index 84587f7..d386e4f 100644 --- a/src/test/java/soongsil/kidbean/server/wordquiz/application/WordQuizServiceTest.java +++ b/src/test/java/soongsil/kidbean/server/wordquiz/application/WordQuizServiceTest.java @@ -49,18 +49,26 @@ class WordQuizServiceTest { @Test @DisplayName("랜덤 WordQuiz 선택") void selectRandomWordQuiz() { + // given + Long memberId = MEMBER1.getMemberId(); - //given - given(memberRepository.findById(anyLong())).willReturn(Optional.of(MEMBER1)); - given(wordQuizRepository.countByMemberOrAdmin(any(Member.class))).willReturn(4); - given(wordQuizRepository.findSingleResultByMember(any(Member.class), any(Pageable.class))) - .willReturn(List.of(WORD_QUIZ)); + // Mocking the count of quizzes for the member + given(wordQuizRepository.countByMemberId(memberId)).willReturn(9L); // 예시로 9개의 퀴즈가 있다고 가정 + + // Mocking the random quiz IDs returned + given(wordQuizRepository.findRandomQuizIds(eq(memberId), any(Pageable.class))) + .willReturn(List.of(1L, 2L, 3L)); // 예시로 3개의 ID 반환 - //when + // Mocking the quizzes returned based on IDs + given(wordQuizRepository.findByIdsWithWords(any(List.class))) + .willReturn(List.of(WORD_QUIZ)); // 여러 퀴즈를 반환 + + // when WordQuizSolveListResponse wordQuizSolveListResponse = - wordQuizService.selectRandomWordQuiz(MEMBER1.getMemberId(), 3); + wordQuizService.selectRandomWordQuiz(memberId, 1); - //then + // then + assertThat(wordQuizSolveListResponse.wordQuizSolveResponseList()).hasSize(1); assertThat(wordQuizSolveListResponse.wordQuizSolveResponseList().get(0).title()) .isEqualTo(WORD_QUIZ.getTitle()); assertThat(wordQuizSolveListResponse.wordQuizSolveResponseList().get(0).words())