Skip to content

Commit 04fd105

Browse files
authored
Merge pull request #18 from Nexters/feature/add-meme-quiz-serve-api
밈 퀴즈 전달 api 기능 추가
2 parents 63280be + 565e158 commit 04fd105

File tree

7 files changed

+184
-4
lines changed

7 files changed

+184
-4
lines changed

src/main/java/spring/memewikibe/api/controller/meme/response/QuizController.java

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,25 @@
11
package spring.memewikibe.api.controller.meme.response;
22

3+
import lombok.RequiredArgsConstructor;
34
import org.springframework.web.bind.annotation.*;
45
import spring.memewikibe.api.controller.meme.request.QuizAnswerRequest;
6+
import spring.memewikibe.application.QuizService;
57
import spring.memewikibe.support.response.ApiResponse;
68

79
import java.util.List;
810

911
@RestController
1012
@RequestMapping("/api/quizzes")
1113
public class QuizController {
14+
private final QuizService quizService;
15+
16+
public QuizController(QuizService quizService) {
17+
this.quizService = quizService;
18+
}
1219

1320
@GetMapping
1421
public ApiResponse<List<QuizProblemResponse>> getQuizzes() {
15-
// TODO: 퀴즈 목록 조회
16-
return null;
22+
return ApiResponse.success(quizService.getRandomQuizzes());
1723
}
1824

1925
@PostMapping

src/main/java/spring/memewikibe/api/controller/meme/response/QuizProblemResponse.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,7 @@
33
import java.util.List;
44

55
public record QuizProblemResponse(
6-
String title,
7-
String summary,
6+
String question,
87
String image,
98
List<QuizOption> questions
109
) {
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package spring.memewikibe.application;
2+
3+
import lombok.RequiredArgsConstructor;
4+
import org.springframework.stereotype.Service;
5+
import org.springframework.transaction.annotation.Transactional;
6+
import spring.memewikibe.api.controller.meme.request.QuizAnswerRequest;
7+
import spring.memewikibe.api.controller.meme.response.QuizProblemResponse;
8+
import spring.memewikibe.api.controller.meme.response.QuizResultResponse;
9+
import spring.memewikibe.domain.meme.quiz.MemeQuiz;
10+
import spring.memewikibe.infrastructure.MemeQuizRepository;
11+
12+
import java.util.List;
13+
14+
@Service
15+
@RequiredArgsConstructor
16+
@Transactional(readOnly = true)
17+
public class QuizService {
18+
private static final int quizLimit = 10;
19+
20+
private final MemeQuizRepository quizRepository;
21+
22+
public List<QuizProblemResponse> getRandomQuizzes() {
23+
return quizRepository.findRandomQuizzes(quizLimit).stream()
24+
.map(this::toProblem)
25+
.toList();
26+
}
27+
28+
private QuizProblemResponse toProblem(MemeQuiz q) {
29+
int ans = q.getAnswer();
30+
return new QuizProblemResponse(
31+
q.getQuestion(),
32+
q.getImageUrl(),
33+
List.of(
34+
new QuizProblemResponse.QuizOption(q.getOption1(), ans == 1),
35+
new QuizProblemResponse.QuizOption(q.getOption2(), ans == 2),
36+
new QuizProblemResponse.QuizOption(q.getOption3(), ans == 3),
37+
new QuizProblemResponse.QuizOption(q.getOption4(), ans == 4)
38+
)
39+
);
40+
}
41+
}
42+
43+
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
package spring.memewikibe.domain.meme.quiz;
2+
3+
import jakarta.persistence.*;
4+
import lombok.AccessLevel;
5+
import lombok.Builder;
6+
import lombok.Getter;
7+
import lombok.NoArgsConstructor;
8+
import spring.memewikibe.domain.BaseEntity;
9+
10+
@Getter
11+
@NoArgsConstructor(access = AccessLevel.PROTECTED)
12+
@Entity
13+
@Table(name = "meme_quiz")
14+
public class MemeQuiz extends BaseEntity {
15+
16+
@Column(name = "question", nullable = false, columnDefinition = "TEXT")
17+
private String question;
18+
19+
@Column(name = "option_1", nullable = false, length = 255)
20+
private String option1;
21+
22+
@Column(name = "option_2", nullable = false, length = 255)
23+
private String option2;
24+
25+
@Column(name = "option_3", nullable = false, length = 255)
26+
private String option3;
27+
28+
@Column(name = "option_4", nullable = false, length = 255)
29+
private String option4;
30+
31+
@Column(name = "answer", nullable = false)
32+
private int answer;
33+
34+
@Column(name = "image_url")
35+
private String imageUrl;
36+
37+
@Builder
38+
private MemeQuiz(String question, String option1, String option2, String option3, String option4, int answer, String imageUrl) {
39+
this.question = question;
40+
this.option1 = option1;
41+
this.option2 = option2;
42+
this.option3 = option3;
43+
this.option4 = option4;
44+
this.answer = answer;
45+
this.imageUrl = imageUrl;
46+
}
47+
}
48+
49+
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package spring.memewikibe.infrastructure;
2+
3+
import org.springframework.data.jpa.repository.JpaRepository;
4+
import org.springframework.data.jpa.repository.Query;
5+
import org.springframework.stereotype.Repository;
6+
import spring.memewikibe.domain.meme.quiz.MemeQuiz;
7+
8+
import java.util.List;
9+
10+
@Repository
11+
public interface MemeQuizRepository extends JpaRepository<MemeQuiz, Long> {
12+
@Query(value = "SELECT * FROM meme_quiz ORDER BY RAND() LIMIT ?", nativeQuery = true)
13+
List<MemeQuiz> findRandomQuizzes(int limit);
14+
}
15+
16+

src/main/resources/schema.sql

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,4 +59,19 @@ create table meme_category
5959
updated_at timestamp(6) default current_timestamp,
6060
meme_id bigint not null,
6161
category_id bigint not null,
62+
)
63+
64+
-- 밈 퀴즈 테이블
65+
create table meme_quiz
66+
(
67+
id bigint auto_increment primary key,
68+
created_at timestamp(6) default current_timestamp,
69+
updated_at timestamp(6) default current_timestamp,
70+
question text not null,
71+
option_1 varchar(255) not null,
72+
option_2 varchar(255) not null,
73+
option_3 varchar(255) not null,
74+
option_4 varchar(255) not null,
75+
answer int not null,
76+
image_url varchar(255) null,
6277
)
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
package spring.memewikibe.application;
2+
3+
import org.junit.jupiter.api.AfterEach;
4+
import org.junit.jupiter.api.Test;
5+
import org.springframework.boot.test.context.SpringBootTest;
6+
import org.springframework.test.context.TestConstructor;
7+
import org.springframework.transaction.annotation.Transactional;
8+
import spring.memewikibe.api.controller.meme.response.QuizProblemResponse;
9+
import spring.memewikibe.domain.meme.quiz.MemeQuiz;
10+
import spring.memewikibe.infrastructure.MemeQuizRepository;
11+
12+
import java.util.List;
13+
import java.util.stream.IntStream;
14+
15+
import static org.assertj.core.api.BDDAssertions.then;
16+
17+
@SpringBootTest
18+
@Transactional
19+
@TestConstructor(autowireMode = TestConstructor.AutowireMode.ALL)
20+
class QuizServiceTest {
21+
22+
private final QuizService quizService;
23+
private final MemeQuizRepository quizRepository;
24+
25+
QuizServiceTest(QuizService quizService, MemeQuizRepository quizRepository) {
26+
this.quizService = quizService;
27+
this.quizRepository = quizRepository;
28+
}
29+
30+
@Test
31+
void 랜덤_퀴즈_10개를_반환한다() {
32+
List<MemeQuiz> quizzes = IntStream.rangeClosed(1, 20)
33+
.mapToObj(i -> MemeQuiz.builder()
34+
.question("문제 " + i)
35+
.option1("보기1")
36+
.option2("보기2")
37+
.option3("보기3")
38+
.option4("보기4")
39+
.answer(1)
40+
.imageUrl("https://example.com/" + i + ".jpg")
41+
.build())
42+
.toList();
43+
quizRepository.saveAll(quizzes);
44+
45+
List<QuizProblemResponse> result = quizService.getRandomQuizzes();
46+
47+
then(result).hasSize(10);
48+
result.forEach(q -> then(q.questions()).hasSize(4));
49+
}
50+
}
51+
52+

0 commit comments

Comments
 (0)