Skip to content

Commit 10443ac

Browse files
authored
release: 1.1.2 (#121)
2 parents dd66cb6 + 93cc8d7 commit 10443ac

16 files changed

+168
-34
lines changed

src/main/kotlin/org/gitanimals/notification/app/NotApprovedQuizCreatedMessageListener.kt

+1
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ class NotApprovedQuizCreatedMessageListener(
3838
category: ${notApprovedQuizCreatedNotification.category}
3939
problem: ${notApprovedQuizCreatedNotification.problem}
4040
expectedAnswer: ${notApprovedQuizCreatedNotification.expectedAnswer}
41+
language: ${notApprovedQuizCreatedNotification.language}
4142
---유사하다고 판단된 퀴즈들 :point_down:---
4243
${notApprovedQuizCreatedNotification.similarityQuizTexts.joinToString("\n---\n")}
4344
""".trimIndent()

src/main/kotlin/org/gitanimals/notification/app/QuizCreatedMessageListener.kt

+1
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ class QuizCreatedMessageListener(
3636
category: ${newQuizCreatedNotification.category}
3737
problem: ${newQuizCreatedNotification.problem}
3838
expectedAnswer: ${newQuizCreatedNotification.expectedAnswer}
39+
language: ${newQuizCreatedNotification.language}
3940
""".trimIndent()
4041
)
4142
}.onFailure {

src/main/kotlin/org/gitanimals/notification/app/event/NewQuizCreatedNotification.kt

+1
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,5 @@ data class NewQuizCreatedNotification(
88
val category: String,
99
val expectedAnswer: String,
1010
val traceId: String,
11+
val language: String,
1112
)
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,13 @@
11
package org.gitanimals.notification.app.event
22

3-
import org.gitanimals.quiz.domain.core.Category
4-
53
data class NotApprovedQuizCreatedNotification(
64
val id: Long,
75
val userId: Long,
86
val problem: String,
97
val level: String,
10-
val category: Category,
8+
val category: String,
119
val expectedAnswer: String,
1210
val traceId: String,
11+
val language: String,
1312
val similarityQuizTexts: List<String>,
1413
)

src/main/kotlin/org/gitanimals/quiz/app/AIApi.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ class AIApi(
1313
fun isDevelopmentQuiz(text: String): Boolean {
1414
val request = OpenAI.Request(messages = listOf(Message(role = "user", content = text)))
1515
val aiResponseContent = openAI.invoke(request).choices.first().message.content
16-
return when (aiResponseContent.trim()) {
16+
return when (aiResponseContent.trim().lowercase()) {
1717
"true" -> true
1818
"false" -> false
1919
else -> error("Cannot parsing content cause content is not \"true\" or \"false\". content: \"${aiResponseContent.trim()}\"")

src/main/kotlin/org/gitanimals/quiz/app/SolveQuizFacade.kt

+12-2
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import org.gitanimals.quiz.app.response.QuizContextResponse
55
import org.gitanimals.quiz.domain.approved.QuizService
66
import org.gitanimals.quiz.domain.context.QuizSolveContext
77
import org.gitanimals.quiz.domain.context.QuizSolveContextService
8+
import org.gitanimals.quiz.domain.core.Language
89
import org.gitanimals.quiz.domain.core.Level
910
import org.springframework.stereotype.Service
1011

@@ -15,8 +16,17 @@ class SolveQuizFacade(
1516
private val quizSolveContextService: QuizSolveContextService,
1617
) {
1718

18-
fun createContext(token: String, request: CreateSolveQuizRequest): Long {
19-
val pickedQuizs = quizService.findAllQuizByLevel(quizLevels)
19+
fun createContext(token: String, locale: String, request: CreateSolveQuizRequest): Long {
20+
val language = when (locale.uppercase()) {
21+
"EN_US" -> Language.ENGLISH
22+
else -> Language.KOREA
23+
}
24+
val pickedQuizs = quizService.findAllQuizByLevelAndCategoryAndLanguage(
25+
levels = quizLevels,
26+
language = language,
27+
category = request.category,
28+
)
29+
2030
val user = identityApi.getUserByToken(token)
2131

2232
val quizSolveContext = quizSolveContextService.createQuizSolveContext(

src/main/kotlin/org/gitanimals/quiz/app/event/NotApprovedQuizCreated.kt

+3
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import org.gitanimals.core.filter.MDCFilter
55
import org.gitanimals.core.redis.AsyncRedisPubSubEvent
66
import org.gitanimals.core.redis.RedisPubSubChannel
77
import org.gitanimals.quiz.domain.core.Category
8+
import org.gitanimals.quiz.domain.core.Language
89
import org.gitanimals.quiz.domain.not_approved.NotApprovedQuiz
910
import org.slf4j.MDC
1011

@@ -16,6 +17,7 @@ data class NotApprovedQuizCreated(
1617
val category: Category,
1718
val expectedAnswer: String,
1819
val similarityQuizTexts: List<String>,
20+
val language: Language,
1921
) : AsyncRedisPubSubEvent(
2022
channel = RedisPubSubChannel.NOT_APPROVED_QUIZ_CREATED,
2123
traceId = runCatching { MDC.get(MDCFilter.TRACE_ID) }
@@ -32,6 +34,7 @@ data class NotApprovedQuizCreated(
3234
category = entity.category,
3335
expectedAnswer = entity.expectedAnswer,
3436
similarityQuizTexts = similarityQuizTexts,
37+
language = entity.language,
3538
)
3639
}
3740
}

src/main/kotlin/org/gitanimals/quiz/controller/QuizContextController.kt

+2-1
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,9 @@ class QuizContextController(
2020
fun createQuizContext(
2121
@RequestHeader(HttpHeaders.AUTHORIZATION) token: String,
2222
@RequestBody createSolveQuizRequest: CreateSolveQuizRequest,
23+
@RequestHeader("Locale") locale: String,
2324
): CreateQuizContextResponse {
24-
val contextId = solveQuizFacade.createContext(token, createSolveQuizRequest)
25+
val contextId = solveQuizFacade.createContext(token, locale, createSolveQuizRequest)
2526
return CreateQuizContextResponse(contextId.toString())
2627
}
2728

src/main/kotlin/org/gitanimals/quiz/domain/approved/Quiz.kt

+9
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ import org.gitanimals.core.AggregateRoot
55
import org.gitanimals.core.IdGenerator
66
import org.gitanimals.quiz.domain.core.AbstractTime
77
import org.gitanimals.quiz.domain.core.Category
8+
import org.gitanimals.quiz.domain.core.Language
9+
import org.gitanimals.quiz.domain.core.Language.Companion.containsKorean
810
import org.gitanimals.quiz.domain.core.Level
911

1012
@Entity
@@ -31,6 +33,9 @@ class Quiz(
3133

3234
@Column(name = "expected_answer", columnDefinition = "TEXT", nullable = false)
3335
val expectedAnswer: String,
36+
37+
@Column(name = "language", columnDefinition = "TEXT DEFAULT 'KOREA'", nullable = true)
38+
val language: Language,
3439
) : AbstractTime() {
3540

3641
companion object {
@@ -49,6 +54,10 @@ class Quiz(
4954
problem = problem,
5055
category = category,
5156
expectedAnswer = expectedAnswer,
57+
language = when {
58+
problem.containsKorean() -> Language.KOREA
59+
else -> Language.ENGLISH
60+
}
5261
)
5362
}
5463
}

src/main/kotlin/org/gitanimals/quiz/domain/approved/QuizService.kt

+39-20
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package org.gitanimals.quiz.domain.approved
22

33
import org.gitanimals.quiz.domain.core.Category
4+
import org.gitanimals.quiz.domain.core.Language
45
import org.gitanimals.quiz.domain.core.Level
56
import org.slf4j.LoggerFactory
67
import org.springframework.data.domain.PageRequest
@@ -12,7 +13,7 @@ class QuizService(
1213
private val quizRepository: QuizRepository,
1314
) {
1415

15-
private var quizIdsAssociatedByLevelCache: Map<Level, List<Long>> = getQuizIdsAssociatedLevel()
16+
private var quizIdsAssociatedByLevelCache: Map<Level, List<Quiz>> = getQuizIdsAssociatedLevel()
1617
private val logger = LoggerFactory.getLogger(this::class.simpleName)
1718

1819
fun createNewQuiz(
@@ -36,34 +37,52 @@ class QuizService(
3637
fun findAllByIds(similarityQuizIds: List<Long>): List<Quiz> =
3738
quizRepository.findAllById(similarityQuizIds)
3839

39-
fun findAllQuizByLevel(levels: List<Level>): List<Quiz> {
40-
val allQuizs: Map<Level, MutableList<Long>> = this.quizIdsAssociatedByLevelCache
40+
fun findAllQuizByLevelAndCategoryAndLanguage(
41+
levels: List<Level>,
42+
category: Category,
43+
language: Language,
44+
): List<Quiz> {
45+
val allQuizs: Map<Level, MutableList<Quiz>> = this.quizIdsAssociatedByLevelCache
4146
.mapValues { it.value.toMutableList() }
4247

43-
checkQuizPickable(levels, allQuizs)
48+
checkAndCalibratePickableQuiz(
49+
levels = levels,
50+
category = category,
51+
language = language,
52+
allQuizs = allQuizs,
53+
)
4454

4555
return runCatching {
46-
val quizIds = levels.map {
47-
val quizId = quizIdsAssociatedByLevelCache[it]?.random()
48-
allQuizs[it]?.remove(quizId)
49-
quizId
56+
levels.map {
57+
val quiz = quizIdsAssociatedByLevelCache[it]?.random()
58+
?: throw IllegalStateException("Cannot pick quiz cause list is empty")
59+
allQuizs[it]?.remove(quiz)
60+
quiz
5061
}
51-
52-
quizRepository.findAllById(quizIds)
5362
}.getOrElse {
5463
logger.error("Cannot call findAllQuizByLevel. levels: $levels", it)
5564
throw it
5665
}
5766
}
5867

59-
private fun checkQuizPickable(levels: List<Level>, allQuizs: Map<Level, MutableList<Long>>) {
68+
private fun checkAndCalibratePickableQuiz(
69+
levels: List<Level>,
70+
category: Category,
71+
language: Language,
72+
allQuizs: Map<Level, MutableList<Quiz>>,
73+
) {
6074
levels.forEach { level ->
61-
val isPickable = allQuizs[level]?.let { quizIds ->
62-
quizIds.size >= levels.count { it == level }
63-
} ?: false
75+
allQuizs[level]?.removeIf { it.category != category || it.language != language }
76+
77+
val isPickable = allQuizs[level]
78+
?.filter { it.category == category && it.language == language }
79+
?.let { quizs ->
80+
quizs.size >= levels.count { it == level }
81+
} ?: false
6482

6583
check(isPickable) {
66-
val message = "Fail to checkQuizPickable cause level: \"$level\" pickable size is smaller than request level size: \"${levels.count { it == level }}\""
84+
val message =
85+
"Fail to checkQuizPickable cause level: \"$level\" pickable size is smaller than request level size: \"${levels.count { it == level }}\""
6786
logger.warn(message)
6887
message
6988
}
@@ -75,19 +94,19 @@ class QuizService(
7594
this.quizIdsAssociatedByLevelCache = getQuizIdsAssociatedLevel()
7695
}
7796

78-
private fun getQuizIdsAssociatedLevel(): Map<Level, List<Long>> {
79-
val quizCountCache: MutableMap<Level, MutableList<Long>> =
80-
Level.entries.associateWith { mutableListOf<Long>() }.toMutableMap()
97+
private fun getQuizIdsAssociatedLevel(): Map<Level, List<Quiz>> {
98+
val quizCountCache: MutableMap<Level, MutableList<Quiz>> =
99+
Level.entries.associateWith { mutableListOf<Quiz>() }.toMutableMap()
81100

82101
var currentPage = 0
83102
val pageSize = 100
84103
var quizs = quizRepository.findAll(PageRequest.of(currentPage, pageSize))
85-
quizs.forEach { quizCountCache[it.level]?.add(it.id) }
104+
quizs.forEach { quizCountCache[it.level]?.add(it) }
86105

87106
while (quizs.hasNext()) {
88107
currentPage += 1
89108
quizs = quizRepository.findAll(PageRequest.of(currentPage, pageSize))
90-
quizs.forEach { quizCountCache[it.level]?.add(it.id) }
109+
quizs.forEach { quizCountCache[it.level]?.add(it) }
91110
}
92111

93112
return quizCountCache
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package org.gitanimals.quiz.domain.core
2+
3+
enum class Language {
4+
KOREA,
5+
ENGLISH,
6+
;
7+
8+
companion object {
9+
10+
fun String.containsKorean(): Boolean {
11+
val koreanRegex = Regex("[가-힣]")
12+
return this.contains(koreanRegex)
13+
}
14+
}
15+
}

src/main/kotlin/org/gitanimals/quiz/domain/not_approved/NotApprovedQuiz.kt

+9
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ import org.gitanimals.core.AggregateRoot
55
import org.gitanimals.core.IdGenerator
66
import org.gitanimals.quiz.domain.core.AbstractTime
77
import org.gitanimals.quiz.domain.core.Category
8+
import org.gitanimals.quiz.domain.core.Language
9+
import org.gitanimals.quiz.domain.core.Language.Companion.containsKorean
810
import org.gitanimals.quiz.domain.core.Level
911

1012
@Entity
@@ -31,6 +33,9 @@ class NotApprovedQuiz(
3133

3234
@Column(name = "expected_answer", columnDefinition = "TEXT", nullable = false)
3335
val expectedAnswer: String,
36+
37+
@Column(name = "language", columnDefinition = "TEXT DEFAULT 'KOREA'", nullable = true)
38+
val language: Language,
3439
) : AbstractTime() {
3540

3641
companion object {
@@ -49,6 +54,10 @@ class NotApprovedQuiz(
4954
problem = problem,
5055
category = category,
5156
expectedAnswer = expectedAnswer,
57+
language = when {
58+
problem.containsKorean() -> Language.KOREA
59+
else -> Language.ENGLISH
60+
}
5261
)
5362
}
5463
}

src/main/kotlin/org/gitanimals/quiz/infra/event/NewQuizCreated.kt

+3
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import org.gitanimals.core.redis.AsyncRedisPubSubEvent
66
import org.gitanimals.core.redis.RedisPubSubChannel
77
import org.gitanimals.quiz.domain.core.Category
88
import org.gitanimals.quiz.domain.approved.Quiz
9+
import org.gitanimals.quiz.domain.core.Language
910
import org.slf4j.MDC
1011

1112
data class NewQuizCreated(
@@ -15,6 +16,7 @@ data class NewQuizCreated(
1516
val level: String,
1617
val category: Category,
1718
val expectedAnswer: String,
19+
val language: Language,
1820
) : AsyncRedisPubSubEvent(
1921
channel = RedisPubSubChannel.NEW_QUIZ_CREATED,
2022
traceId = runCatching { MDC.get(TRACE_ID) }
@@ -30,6 +32,7 @@ data class NewQuizCreated(
3032
level = entity.level.name,
3133
category = entity.category,
3234
expectedAnswer = entity.expectedAnswer,
35+
language = entity.language,
3336
)
3437
}
3538
}

src/test/kotlin/org/gitanimals/quiz/app/SolveQuizFacadeTest.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ internal class SolveQuizFacadeTest(
6868

6969
it("새로운 quizContext를 생성한다") {
7070
shouldNotThrowAny {
71-
solveQuizFacade.createContext(token, request)
71+
solveQuizFacade.createContext(token,"KR" , request)
7272
}
7373
}
7474
}

src/test/kotlin/org/gitanimals/quiz/domain/quiz/Fixture.kt

+3
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package org.gitanimals.quiz.domain.quiz
33
import org.gitanimals.core.IdGenerator
44
import org.gitanimals.quiz.domain.approved.Quiz
55
import org.gitanimals.quiz.domain.core.Category
6+
import org.gitanimals.quiz.domain.core.Language
67
import org.gitanimals.quiz.domain.core.Level
78
import org.gitanimals.quiz.domain.not_approved.NotApprovedQuiz
89

@@ -20,6 +21,7 @@ fun quiz(
2021
category = category,
2122
problem = problem,
2223
expectedAnswer = expectedAnswer,
24+
language = Language.KOREA,
2325
)
2426

2527
fun notApprovedQuiz(
@@ -36,4 +38,5 @@ fun notApprovedQuiz(
3638
category = category,
3739
problem = problem,
3840
expectedAnswer = expectedAnswer,
41+
language = Language.KOREA,
3942
)

0 commit comments

Comments
 (0)