홈 - 무료 콘텐츠, 포인트 사용가능 콘텐츠 랜덤 추천 로직을 추천 콘텐츠와 동일하게 수정

This commit is contained in:
2026-02-12 19:16:35 +09:00
parent e690bf8aec
commit 9d0c8d063e

View File

@@ -237,29 +237,28 @@ class HomeService(
recommendChannelList
}
val freeContentList = contentService.getLatestContentByTheme(
val freeContentList = getRandomizedContentList(
memberId = memberId,
isAdult = isAdult,
contentType = contentType,
theme = contentThemeService.getActiveThemeOfContent(
isAdult = isAdult,
isFree = true,
contentType = contentType
),
contentType = contentType,
isFree = true,
isAdult = isAdult,
orderByRandom = true
isPointAvailableOnly = false
)
val translatedFreeContentList = getTranslatedContentList(contentList = freeContentList)
// 포인트 사용가능 콘텐츠 리스트 - 랜덤으로 가져오기 (DB에서 isPointAvailable 조건 적용)
val pointAvailableContentList = contentService.getLatestContentByTheme(
val pointAvailableContentList = getRandomizedContentList(
memberId = memberId,
theme = emptyList(),
contentType = contentType,
isFree = false,
isAdult = isAdult,
orderByRandom = true,
contentType = contentType,
theme = emptyList(),
isFree = false,
isPointAvailableOnly = true
)
@@ -501,6 +500,61 @@ class HomeService(
return candidates.lastIndex
}
private fun getRandomizedContentList(
memberId: Long?,
isAdult: Boolean,
contentType: ContentType,
theme: List<String>,
isFree: Boolean,
isPointAvailableOnly: Boolean,
targetSize: Int = 20
): List<AudioContentMainItem> {
val buckets = listOf(
RecommendBucket(offset = 0L, limit = 50L),
RecommendBucket(offset = 50L, limit = 100L),
RecommendBucket(offset = 150L, limit = 150L)
)
val result = mutableListOf<AudioContentMainItem>()
val seenIds = mutableSetOf<Long>()
repeat(RECOMMEND_MAX_ATTEMPTS) {
if (result.size >= targetSize) return@repeat
val remaining = targetSize - result.size
val targetPerBucket = maxOf(1, (remaining + buckets.size - 1) / buckets.size)
for (bucket in buckets) {
if (result.size >= targetSize) break
val batch = contentService.getLatestContentByTheme(
memberId = memberId,
theme = theme,
contentType = contentType,
offset = bucket.offset,
limit = bucket.limit,
sortType = SortType.NEWEST,
isFree = isFree,
isAdult = isAdult,
orderByRandom = false,
isPointAvailableOnly = isPointAvailableOnly,
excludeContentIds = seenIds.toList()
)
val selected = pickByTimeDecay(
batch = batch,
targetSize = minOf(targetPerBucket, targetSize - result.size),
seenIds = seenIds
)
if (selected.isNotEmpty()) {
result.addAll(selected)
}
}
}
return getTranslatedContentList(contentList = result.take(targetSize).shuffled())
}
/**
* 콘텐츠 리스트의 제목을 현재 언어(locale)에 맞춰 일괄 번역한다.
*