Skip to content

Commit e4789b1

Browse files
authored
Merge pull request #84 from capgoing/feat/#69
✨ [feat] Picture Quiz 생성 로직 구현 API
2 parents d64c04d + 4905ce7 commit e4789b1

File tree

7 files changed

+103
-18
lines changed

7 files changed

+103
-18
lines changed

src/main/java/com/going/server/domain/quiz/dto/PictureQuizDto.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,12 @@
22

33
import lombok.Builder;
44
import lombok.Getter;
5+
import java.util.Set;
56

67
@Builder
78
@Getter
89
public class PictureQuizDto {
10+
private final String imageUrl;
11+
private final Set<String> shuffled;
12+
private final String answer;
913
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package com.going.server.domain.quiz.exception;
2+
3+
import com.going.server.global.exception.BaseErrorCode;
4+
import lombok.AllArgsConstructor;
5+
import lombok.Getter;
6+
import org.springframework.http.HttpStatus;
7+
8+
import static com.going.server.global.constant.StaticValue.BAD_REQUEST;
9+
import static com.going.server.global.constant.StaticValue.INTERNAL_SERVER_ERROR;
10+
11+
@Getter
12+
@AllArgsConstructor
13+
public enum QuizErrorCode implements BaseErrorCode {
14+
// 400
15+
UNSUPPORTED_QUIZ_MODE(BAD_REQUEST, "QUIZ_400_1", "지원하지 않는 mode 입니다."),
16+
17+
// 500
18+
QUIZ_IMAGE_GENERATION_FAILED(INTERNAL_SERVER_ERROR, "QUIZ_500_1", "퀴즈 이미지 생성 중 서버 오류가 발생했습니다.");
19+
20+
private final int httpStatus;
21+
private final String code;
22+
private final String message;
23+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package com.going.server.domain.quiz.exception;
2+
3+
import com.going.server.global.exception.BaseException;
4+
5+
public class QuizImageException extends BaseException {
6+
public QuizImageException(){super(QuizErrorCode.QUIZ_IMAGE_GENERATION_FAILED);}
7+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package com.going.server.domain.quiz.exception;
2+
3+
import com.going.server.global.exception.BaseException;
4+
5+
public class UnsupportedQuizModeException extends BaseException {
6+
public UnsupportedQuizModeException() {super(QuizErrorCode.UNSUPPORTED_QUIZ_MODE);}
7+
}

src/main/java/com/going/server/domain/quiz/generate/ListenUpQuizGenerator.java

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,11 @@ public ListenUpQuizDto generate(Graph graph) {
1515
Random random = new Random();
1616
List<ListenUpQuizDto.ListenUpQuiz> quizzes = new ArrayList<>();
1717
Set<String> usedSentences = new HashSet<>();
18-
List<String> options = new ArrayList<>();
18+
List<String> candidateSentences = new ArrayList<>(); // 전처리한 includeSentence
1919

2020
// 1. 그래프 노드에서 문장 추출
2121
for (GraphNode node : graph.getNodes()) {
22+
// IncludeSentence가 비어있는 경우 넘어가기
2223
if (node.getIncludeSentence() == null || node.getIncludeSentence().isBlank()) continue;
2324

2425
// "." 으로 문장 나누기
@@ -32,18 +33,18 @@ public ListenUpQuizDto generate(Graph graph) {
3233
String[] words = sentence.split("\\s+");
3334
if (words.length < 5) continue; // 5단어 미만은 스킵
3435

35-
options.add(sentence);
36+
candidateSentences.add(sentence);
3637
}
3738
}
3839

3940
// 2. 단어 수 기준 정렬 (5단어에 가까운 순서)
40-
options.sort(Comparator.comparingInt(
41+
candidateSentences.sort(Comparator.comparingInt(
4142
s -> Math.abs(s.trim().split("\\s+").length - 5)
4243
));
4344

4445
int count = 0;
4546

46-
for (String sentence : options) {
47+
for (String sentence : candidateSentences) {
4748
if (count >= 3) break;
4849

4950
String[] words = sentence.split("\\s+");
Lines changed: 55 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,68 @@
11
package com.going.server.domain.quiz.generate;
22

33
import com.going.server.domain.graph.entity.Graph;
4+
import com.going.server.domain.graph.entity.GraphNode;
45
import com.going.server.domain.quiz.dto.PictureQuizDto;
56
import org.springframework.stereotype.Component;
67

8+
import java.util.*;
9+
710
@Component
811
public class PictureQuizGenerator implements QuizGenerator<PictureQuizDto> {
912

1013
@Override
1114
public PictureQuizDto generate(Graph graph) {
12-
// TODO: picture 퀴즈 생성 로직
13-
return null;
15+
Random random = new Random();
16+
Set<String> shuffled = new HashSet<>(); // 보기로 제공할 랜덤 문장들(중복 방지)
17+
int shuffledListSize = 3; // 총 보기 수 (정답 포함)
18+
List<String> candidateSentences = new ArrayList<>(); // 전처리한 includeSentence
19+
20+
// 그래프 노드를 돌면서 문장 후보 수집
21+
for (GraphNode node : graph.getNodes()) {
22+
// IncludeSentence가 비어있는 경우 넘어가기
23+
if (node.getIncludeSentence() == null || node.getIncludeSentence().isBlank()) continue;
24+
25+
// "." 으로 문장 나누기
26+
String[] splitSentences = node.getIncludeSentence().split("\\.");
27+
28+
for (String rawSentence : splitSentences) {
29+
String sentence = rawSentence.trim();
30+
if (sentence.isBlank()) continue; // 공백은 스킵
31+
if (sentence.split("\\s+").length < 5) continue; // 5단어 미만은 스킵
32+
33+
candidateSentences.add(sentence);
34+
}
35+
}
36+
37+
// 후보 문장이 부족할 경우 방어
38+
if (candidateSentences.size() < shuffledListSize) {
39+
throw new IllegalStateException("생성 가능한 문장이 부족합니다.");
40+
}
41+
42+
// 랜덤으로 문장 선택
43+
Collections.shuffle(candidateSentences, random);
44+
45+
// 보기용 문장 추가
46+
Set<String> selectedSentences = new LinkedHashSet<>();
47+
for (int i = 0; i < shuffledListSize; i++) {
48+
selectedSentences.add(candidateSentences.get(i));
49+
}
50+
51+
// 무작위로 정답 보기 설정
52+
int answerIndex = random.nextInt(shuffledListSize);
53+
String answer = new ArrayList<>(selectedSentences).get(answerIndex);
54+
55+
// TODO : 정답 보기 기반으로 이미지 생성
56+
57+
// TODO : S3에 이미지 업로드
58+
59+
// TODO : S3 업로드 후 이미지 URL 받아오기
60+
String imageUrl = "https://s3-ap-northeast-2.amazonaws.com/~.png"; // 예시 url
61+
62+
return PictureQuizDto.builder()
63+
.imageUrl(imageUrl)
64+
.shuffled(selectedSentences)
65+
.answer(answer)
66+
.build();
1467
}
1568
}

src/main/java/com/going/server/domain/quiz/service/QuizServiceImpl.java

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,15 @@
11
package com.going.server.domain.quiz.service;
22

3-
import com.going.server.domain.graph.dto.EdgeDto;
4-
import com.going.server.domain.graph.dto.KnowledgeGraphDto;
5-
import com.going.server.domain.graph.dto.NodeDto;
63
import com.going.server.domain.graph.entity.Graph;
7-
import com.going.server.domain.graph.entity.GraphEdge;
8-
import com.going.server.domain.graph.entity.GraphNode;
94
import com.going.server.domain.graph.repository.GraphRepository;
10-
import com.going.server.domain.quiz.dto.ConnectQuizDto;
11-
import com.going.server.domain.quiz.dto.ListenUpQuizDto;
12-
import com.going.server.domain.quiz.dto.PictureQuizDto;
135
import com.going.server.domain.quiz.dto.QuizCreateResponseDto;
6+
import com.going.server.domain.quiz.exception.UnsupportedQuizModeException;
147
import com.going.server.domain.quiz.generate.ConnectQuizGenerator;
158
import com.going.server.domain.quiz.generate.ListenUpQuizGenerator;
169
import com.going.server.domain.quiz.generate.PictureQuizGenerator;
17-
import com.going.server.domain.quiz.generate.QuizGenerator;
1810
import lombok.AllArgsConstructor;
1911
import org.springframework.stereotype.Service;
2012

21-
import java.util.*;
22-
2313
@Service
2414
@AllArgsConstructor
2515
public class QuizServiceImpl implements QuizService{
@@ -39,7 +29,7 @@ public QuizCreateResponseDto quizCreate(String graphIdStr, String mode) {
3929
case "listenUp" -> listenUpQuizGenerator.generate(graph);
4030
case "connect" -> connectQuizGenerator.generate(graph);
4131
case "picture" -> pictureQuizGenerator.generate(graph);
42-
default -> throw new IllegalArgumentException("지원하지 않는 모드입니다: " + mode);
32+
default -> throw new UnsupportedQuizModeException();
4333
};
4434

4535
return new QuizCreateResponseDto<>(graphIdStr, mode, quizDto);

0 commit comments

Comments
 (0)