Compare commits
2 Commits
41c8d0367d
...
7f3589dcfb
Author | SHA1 | Date | |
---|---|---|---|
7f3589dcfb | |||
b134c28c10 |
@@ -2,6 +2,10 @@ package kr.co.vividnext.sodalive.admin.chat.character.dto
|
|||||||
|
|
||||||
import kr.co.vividnext.sodalive.chat.character.ChatCharacter
|
import kr.co.vividnext.sodalive.chat.character.ChatCharacter
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 관리자 캐릭터 상세 응답 DTO
|
||||||
|
* - 원작이 연결되어 있으면 원작 요약 정보(originalWork)를 함께 반환한다.
|
||||||
|
*/
|
||||||
data class ChatCharacterDetailResponse(
|
data class ChatCharacterDetailResponse(
|
||||||
val id: Long,
|
val id: Long,
|
||||||
val characterUUID: String,
|
val characterUUID: String,
|
||||||
@@ -24,7 +28,8 @@ data class ChatCharacterDetailResponse(
|
|||||||
val relationships: List<RelationshipResponse>,
|
val relationships: List<RelationshipResponse>,
|
||||||
val personalities: List<PersonalityResponse>,
|
val personalities: List<PersonalityResponse>,
|
||||||
val backgrounds: List<BackgroundResponse>,
|
val backgrounds: List<BackgroundResponse>,
|
||||||
val memories: List<MemoryResponse>
|
val memories: List<MemoryResponse>,
|
||||||
|
val originalWork: OriginalWorkBriefResponse? // 추가: 원작 요약 정보
|
||||||
) {
|
) {
|
||||||
companion object {
|
companion object {
|
||||||
fun from(chatCharacter: ChatCharacter, imageHost: String = ""): ChatCharacterDetailResponse {
|
fun from(chatCharacter: ChatCharacter, imageHost: String = ""): ChatCharacterDetailResponse {
|
||||||
@@ -34,6 +39,20 @@ data class ChatCharacterDetailResponse(
|
|||||||
chatCharacter.imagePath ?: ""
|
chatCharacter.imagePath ?: ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val ow = chatCharacter.originalWork
|
||||||
|
val originalWorkBrief = ow?.let {
|
||||||
|
val owImage = if (it.imagePath != null && imageHost.isNotEmpty()) {
|
||||||
|
"$imageHost/${it.imagePath}"
|
||||||
|
} else {
|
||||||
|
it.imagePath
|
||||||
|
}
|
||||||
|
OriginalWorkBriefResponse(
|
||||||
|
id = it.id!!,
|
||||||
|
imageUrl = owImage,
|
||||||
|
title = it.title
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
return ChatCharacterDetailResponse(
|
return ChatCharacterDetailResponse(
|
||||||
id = chatCharacter.id!!,
|
id = chatCharacter.id!!,
|
||||||
characterUUID = chatCharacter.characterUUID,
|
characterUUID = chatCharacter.characterUUID,
|
||||||
@@ -71,7 +90,8 @@ data class ChatCharacterDetailResponse(
|
|||||||
},
|
},
|
||||||
memories = chatCharacter.memories.map {
|
memories = chatCharacter.memories.map {
|
||||||
MemoryResponse(it.title, it.content, it.emotion)
|
MemoryResponse(it.title, it.content, it.emotion)
|
||||||
}
|
},
|
||||||
|
originalWork = originalWorkBrief
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -101,3 +121,12 @@ data class RelationshipResponse(
|
|||||||
val relationshipType: String,
|
val relationshipType: String,
|
||||||
val currentStatus: String
|
val currentStatus: String
|
||||||
)
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 원작 요약 응답 DTO(관리자 캐릭터 상세용)
|
||||||
|
*/
|
||||||
|
data class OriginalWorkBriefResponse(
|
||||||
|
val id: Long,
|
||||||
|
val imageUrl: String?,
|
||||||
|
val title: String
|
||||||
|
)
|
||||||
|
@@ -45,10 +45,10 @@ class ChatCharacterService(
|
|||||||
@Transactional(readOnly = true)
|
@Transactional(readOnly = true)
|
||||||
@Cacheable(
|
@Cacheable(
|
||||||
cacheNames = ["popularCharacters_24h"],
|
cacheNames = ["popularCharacters_24h"],
|
||||||
key = "T(kr.co.vividnext.sodalive.chat.character.service.RankingWindowCalculator).now('popular-chat-character').cacheKey"
|
key = "T(kr.co.vividnext.sodalive.chat.character.service.RankingWindowCalculator).now('popular-character').cacheKey"
|
||||||
)
|
)
|
||||||
fun getPopularCharacters(limit: Long = 20): List<Character> {
|
fun getPopularCharacters(limit: Long = 20): List<Character> {
|
||||||
val window = RankingWindowCalculator.now("popular-chat-character")
|
val window = RankingWindowCalculator.now("popular-character")
|
||||||
val topIds = popularCharacterQuery.findPopularCharacterIds(window.windowStart, window.nextBoundary, limit)
|
val topIds = popularCharacterQuery.findPopularCharacterIds(window.windowStart, window.nextBoundary, limit)
|
||||||
val list = loadCharactersInOrder(topIds)
|
val list = loadCharactersInOrder(topIds)
|
||||||
return list.map {
|
return list.map {
|
||||||
|
@@ -20,7 +20,7 @@ object RankingWindowCalculator {
|
|||||||
private const val BOUNDARY_HOUR = 20 // 20:00:00 UTC
|
private const val BOUNDARY_HOUR = 20 // 20:00:00 UTC
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun now(prefix: String = "popular-chat-character"): RankingWindow {
|
fun now(prefix: String = "popular-character"): RankingWindow {
|
||||||
val now = ZonedDateTime.now(ZONE)
|
val now = ZonedDateTime.now(ZONE)
|
||||||
val todayBoundary = now.toLocalDate().atTime(BOUNDARY_HOUR, 0, 0).atZone(ZONE)
|
val todayBoundary = now.toLocalDate().atTime(BOUNDARY_HOUR, 0, 0).atZone(ZONE)
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user