Skip to content

Commit

Permalink
✨ Feature - Quiz 생성하기 API 구현 (#45)
Browse files Browse the repository at this point in the history
  • Loading branch information
jjuuuunnii authored Nov 14, 2024
1 parent 03a651f commit a1c433d
Show file tree
Hide file tree
Showing 9 changed files with 263 additions and 2 deletions.
73 changes: 71 additions & 2 deletions http/roadmap/RoadmapControllerHttpRequest.http
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ Authorization: Bearer {{access_token}}

### 퀴즈 리스트 조회하기
//@no-log
GET {{host_url}}/v1/subtopics/1/check-points/quizzes/choices/summaries
GET {{host_url}}/v1/subtopics/11/check-points/quizzes/choices/summaries
Authorization: Bearer {{access_token}}


Expand All @@ -50,7 +50,7 @@ Authorization: Bearer {{access_token}}
Content-Disposition: form-data; name="file"; filename="pdf1.pdf"
Content-Type: application/pdf

< /Users/jjuuuunnii/Desktop/Lecture4_AI.pdf
< /Users/jjuuuunnii/Developments/on_road/dummy_data/10.pdf

--boundary

Expand Down Expand Up @@ -78,7 +78,76 @@ Content-Type: application/json
]
}


### 퀴즈 생성하기
//@no-log
POST {{host_url}}/v1/quizzes
Authorization: Bearer {{access_token}}
Content-Type: application/json

{
"quiz_list": [
{
"id": 1,
"content": "다음 중 REST API의 특징이 아닌 것은 무엇인가?",
"choice_list": [
{
"content": "무상태성",
"is_answer": false
},
{
"content": "클라이언트-서버 구조",
"is_answer": false
},
{
"content": "상태 저장성",
"is_answer": true
}
]
},
{
"id": 2,
"content": "Java의 메모리 영역 중 힙(heap) 영역에 저장되지 않는 것은?",
"choice_list": [
{
"content": "객체 인스턴스",
"is_answer": false
},
{
"content": "정적(static) 변수",
"is_answer": true
},
{
"content": "배열",
"is_answer": false
}
]
},
{
"id": 3,
"content": "HTTP 메서드 중 데이터를 생성하기 위한 메서드는?",
"choice_list": [
{
"content": "GET",
"is_answer": false
},
{
"content": "POST",
"is_answer": true
},
{
"content": "DELETE",
"is_answer": false
}
]
}
]
}


### 최근 추가된 로드맵 조회하기
//@no-log
GET {{host_url}}/v1/roadmaps/created-at
Authorization: Bearer {{access_token}}


Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@
import lombok.RequiredArgsConstructor;
import org.dongguk.onroad.core.annotation.security.UserID;
import org.dongguk.onroad.core.dto.ResponseDto;
import org.dongguk.onroad.roadmap.application.dto.request.CreateQuizRequestDto;
import org.dongguk.onroad.roadmap.application.dto.request.CreateUserChoiceRequestDto;
import org.dongguk.onroad.roadmap.application.usecase.CreateQuizUseCase;
import org.dongguk.onroad.roadmap.application.usecase.CreateUserChoiceUseCase;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
Expand All @@ -26,6 +28,7 @@ public class RoadmapCommandV1Controller {
private final CreateLectureUseCase createLectureUseCase;
private final CreateRoadmapUseCase createRoadmapUseCase;
private final CreateUserChoiceUseCase createUserChoiceUseCase;
private final CreateQuizUseCase createQuizUseCase;

@PostMapping("/lectures")
public ResponseDto<?> createLecture(
Expand Down Expand Up @@ -63,4 +66,17 @@ public ResponseDto<Void> createUserChoice(
createUserChoiceUseCase.execute(userId, requestDto);
return ResponseDto.created(null);
}

@PostMapping("/quizzes")
public ResponseDto<Void> createQuiz(
@UserID UUID userId,
@RequestBody @Valid CreateQuizRequestDto requestDto
) {
createQuizUseCase.execute(
userId,
requestDto
);
return ResponseDto.created(null);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package org.dongguk.onroad.roadmap.application.dto.request;

import com.fasterxml.jackson.annotation.JsonProperty;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;

import java.util.List;

public record CreateQuizRequestDto(

@NotNull(message = "퀴즈 목록은 필수 입력 값입니다.")
@JsonProperty("quiz_list")
List<Quiz> quizList

) {
public record Quiz(

@NotNull(message = "check Point id는 필수 입력 값입니다.")
@JsonProperty("id")
Long id,

@NotNull(message = "퀴즈 내용은 필수 입력 값입니다.")
@JsonProperty("content")
String content,

@NotNull(message = "선택지 목록은 필수 입력 값입니다.")
@Size(min = 3, max = 3, message = "선택지는 반드시 3개여야 합니다.")
@JsonProperty("choice_list")
List<Choice> choiceList

) {}

public record Choice(

@NotNull(message = "선택지 내용은 필수 입력 값입니다.")
@JsonProperty("content")
String content,

@NotNull(message = "정답 여부는 필수 입력 값입니다.")
@JsonProperty("is_answer")
Boolean isAnswer

) {}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package org.dongguk.onroad.roadmap.application.service;

import lombok.RequiredArgsConstructor;
import org.dongguk.onroad.core.exception.error.ErrorCode;
import org.dongguk.onroad.core.exception.type.CommonException;
import org.dongguk.onroad.roadmap.application.dto.request.CreateQuizRequestDto;
import org.dongguk.onroad.roadmap.application.usecase.CreateQuizUseCase;
import org.dongguk.onroad.roadmap.domain.CheckPoint;
import org.dongguk.onroad.roadmap.domain.Choice;
import org.dongguk.onroad.roadmap.domain.Quiz;
import org.dongguk.onroad.roadmap.domain.service.ChoiceService;
import org.dongguk.onroad.roadmap.domain.service.QuizService;
import org.dongguk.onroad.roadmap.domain.type.EQuizType;
import org.dongguk.onroad.roadmap.repository.CheckPointRepository;
import org.dongguk.onroad.roadmap.repository.QuizRepository;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.UUID;
import java.util.stream.Stream;

@Service
@RequiredArgsConstructor
public class CreateQuizService implements CreateQuizUseCase {

private final CheckPointRepository checkPointRepository;

private final QuizService quizService;
private final ChoiceService choiceService;
private final QuizRepository quizRepository;

@Override
@Transactional
public void execute(UUID userId, CreateQuizRequestDto requestDto) {

List<Quiz> quizList = requestDto.quizList().stream()
.map(quizRequestDto -> {
CheckPoint checkPoint = checkPointRepository.findById(quizRequestDto.id())
.orElseThrow(() -> new CommonException(ErrorCode.NOT_FOUND_RESOURCE));

Quiz quiz = quizService.createQuiz(
EQuizType.MULTIPLE_CHOICE,
quizRequestDto.content(),
checkPoint
);

quizRequestDto.choiceList().forEach(
choiceRequestDto -> choiceService.createChoice(
choiceRequestDto.content(),
choiceRequestDto.isAnswer(),
quiz
));

return quiz;
}).toList();

quizRepository.saveAll(quizList);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package org.dongguk.onroad.roadmap.application.usecase;

import org.dongguk.onroad.core.annotation.bean.UseCase;
import org.dongguk.onroad.roadmap.application.dto.request.CreateQuizRequestDto;

import java.util.UUID;

@UseCase
public interface CreateQuizUseCase {

void execute(
UUID userId,
CreateQuizRequestDto requestDto
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -55,5 +55,9 @@ public CheckPoint(String content, Subtopic subtopic) {
this.subtopic = subtopic;
this.createdAt = LocalDateTime.now();
}

public void updateQuiz(Quiz quiz) {
this.quiz = quiz;
}
}

9 changes: 9 additions & 0 deletions src/main/java/org/dongguk/onroad/roadmap/domain/Quiz.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
import lombok.NoArgsConstructor;
import org.dongguk.onroad.roadmap.domain.type.EQuizType;

import java.util.ArrayList;
import java.util.List;

@Entity
@Table(name = "quizzes")
@Getter
Expand All @@ -30,6 +33,12 @@ public class Quiz {
@Column(name = "content" ,length = 500, nullable = false)
private String content;

/* -------------------------------------------- */
/* One To Many Mapping ------------------------ */
/* -------------------------------------------- */
@OneToMany(mappedBy = "quiz", cascade = CascadeType.ALL, orphanRemoval = true)
private List<Choice> choices = new ArrayList<>();

/* -------------------------------------------- */
/* One To One Mapping ------------------------- */
/* -------------------------------------------- */
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package org.dongguk.onroad.roadmap.domain.service;

import org.dongguk.onroad.roadmap.domain.Choice;
import org.dongguk.onroad.roadmap.domain.Quiz;
import org.springframework.stereotype.Service;

@Service
public class ChoiceService {

public Choice createChoice(String content, boolean isAnswer, Quiz quiz) {

Choice choice = Choice.builder()
.content(content)
.isAnswer(isAnswer)
.quiz(quiz)
.build();

quiz.getChoices().add(choice);

return choice;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package org.dongguk.onroad.roadmap.domain.service;

import org.dongguk.onroad.roadmap.domain.CheckPoint;
import org.dongguk.onroad.roadmap.domain.Quiz;
import org.dongguk.onroad.roadmap.domain.type.EQuizType;
import org.springframework.stereotype.Service;

@Service
public class QuizService {

public Quiz createQuiz(EQuizType quizType, String content, CheckPoint checkPoint) {
Quiz quiz = Quiz.builder()
.type(quizType)
.content(content)
.checkPoint(checkPoint)
.build();

checkPoint.updateQuiz(quiz);

return quiz;
}
}

0 comments on commit a1c433d

Please sign in to comment.