Skip to content

Commit d9f452b

Browse files
committed
♻️ [Refact] 퀴즈 이미지 생성 로직 분리
1 parent 48f4c82 commit d9f452b

File tree

1 file changed

+51
-28
lines changed

1 file changed

+51
-28
lines changed

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

Lines changed: 51 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import com.going.server.domain.graph.entity.Graph;
44
import com.going.server.domain.graph.entity.GraphNode;
5+
import com.going.server.domain.graph.repository.GraphRepository;
56
import com.going.server.domain.openai.dto.ImageCreateRequestDto;
67
import com.going.server.domain.openai.service.ImageCreateService;
78
import com.going.server.domain.quiz.dto.PictureQuizDto;
@@ -14,50 +15,51 @@
1415
@AllArgsConstructor
1516
public class PictureQuizGenerator implements QuizGenerator<PictureQuizDto> {
1617
private final ImageCreateService imageCreateService;
18+
private final GraphRepository graphRepository;
1719

1820
@Override
19-
public PictureQuizDto generate(Graph graph) {
21+
public PictureQuizDto generate(Graph currentGraph) {
2022
Random random = new Random();
21-
// Set<String> shuffled = new HashSet<>(); // 보기로 제공할 랜덤 문장들(중복 방지)
22-
int shuffledListSize = 3; // 총 보기 수 (정답 포함)
23-
List<String> candidateSentences = new ArrayList<>(); // 전처리한 includeSentence
23+
int shuffledListSize = 3;
2424

25-
// 그래프 노드를 돌면서 문장 후보 수집
26-
for (GraphNode node : graph.getNodes()) {
27-
// IncludeSentence가 비어있는 경우 넘어가기
28-
if (node.getIncludeSentence() == null || node.getIncludeSentence().isBlank()) continue;
25+
// 정답 후보 문장: 현재 그래프에서 수집
26+
List<String> answerCandidates = extractCandidateSentences(currentGraph);
2927

30-
// "." 으로 문장 나누기
31-
String[] splitSentences = node.getIncludeSentence().split("\\.");
28+
if (answerCandidates.isEmpty()) {
29+
throw new IllegalStateException("현재 그래프에서 사용할 수 있는 문장이 없습니다.");
30+
}
3231

33-
for (String rawSentence : splitSentences) {
34-
String sentence = rawSentence.trim();
35-
if (sentence.isBlank()) continue; // 공백은 스킵
36-
if (sentence.split("\\s+").length < 5) continue; // 5단어 미만은 스킵
32+
// 정답 1개 선택
33+
Collections.shuffle(answerCandidates, random);
34+
String answer = answerCandidates.get(0);
3735

38-
candidateSentences.add(sentence);
36+
// 오답 후보 문장: 다른 그래프들에서 수집
37+
List<Graph> allGraphs = graphRepository.findAll();
38+
List<String> distractorCandidates = new ArrayList<>();
39+
for (Graph graph : allGraphs) {
40+
if (!graph.equals(currentGraph)) {
41+
distractorCandidates.addAll(extractCandidateSentences(graph));
3942
}
4043
}
4144

42-
// 후보 문장이 부족할 경우 방어
43-
if (candidateSentences.size() < shuffledListSize) {
44-
throw new IllegalStateException("생성 가능한 문장이 부족합니다.");
45+
// 오답이 부족한 경우: 현재 그래프에서 추가 확보
46+
if (distractorCandidates.size() < shuffledListSize - 1) {
47+
distractorCandidates.addAll(answerCandidates.subList(1, Math.min(answerCandidates.size(), shuffledListSize)));
4548
}
4649

47-
// 랜덤으로 문장 선택
48-
Collections.shuffle(candidateSentences, random);
49-
50-
// 보기용 문장 추가
50+
// 선지 셔플 및 정답 포함해서 뽑기
51+
Collections.shuffle(distractorCandidates, random);
5152
Set<String> selectedSentences = new LinkedHashSet<>();
53+
selectedSentences.add(answer);
5254
int index = 0;
53-
while (selectedSentences.size() < shuffledListSize && index < candidateSentences.size()) {
54-
selectedSentences.add(candidateSentences.get(index));
55+
while (selectedSentences.size() < shuffledListSize && index < distractorCandidates.size()) {
56+
selectedSentences.add(distractorCandidates.get(index));
5557
index++;
5658
}
5759

58-
// 무작위로 정답 보기 설정
59-
int answerIndex = random.nextInt(shuffledListSize);
60-
String answer = new ArrayList<>(selectedSentences).get(answerIndex);
60+
if (selectedSentences.size() < shuffledListSize) {
61+
throw new IllegalStateException("문제가 될 문장이 충분하지 않습니다.");
62+
}
6163

6264
String prompt = buildQuizImagePrompt(answer);
6365
ImageCreateRequestDto requestDto = new ImageCreateRequestDto(
@@ -66,7 +68,8 @@ public PictureQuizDto generate(Graph graph) {
6668
"vivid",
6769
"standard",
6870
"1024x1024",
69-
1);
71+
1
72+
);
7073
String imageUrl = imageCreateService.generatePicture(requestDto);
7174

7275
return PictureQuizDto.builder()
@@ -76,6 +79,26 @@ public PictureQuizDto generate(Graph graph) {
7679
.build();
7780
}
7881

82+
// 문장 후보 추출 메서드 분리
83+
private List<String> extractCandidateSentences(Graph graph) {
84+
List<String> sentences = new ArrayList<>();
85+
86+
for (GraphNode node : graph.getNodes()) {
87+
String raw = node.getIncludeSentence();
88+
if (raw == null || raw.isBlank()) continue;
89+
90+
String[] split = raw.split("\\.");
91+
for (String s : split) {
92+
String trimmed = s.trim();
93+
if (trimmed.isBlank()) continue;
94+
if (trimmed.split("\\s+").length < 5) continue;
95+
sentences.add(trimmed);
96+
}
97+
}
98+
99+
return sentences;
100+
}
101+
79102
// 이미지 생성 프롬프트 생성 메서드
80103
public static String buildQuizImagePrompt(String answer) {
81104
return "You are given an educational description in natural language.\n\n" +

0 commit comments

Comments
 (0)