|  |  | @@ -11,11 +11,13 @@ import kr.co.vividnext.sodalive.chat.character.ChatCharacterGoal | 
			
		
	
		
		
			
				
					
					|  |  |  | import kr.co.vividnext.sodalive.chat.character.ChatCharacterHobby |  |  |  | import kr.co.vividnext.sodalive.chat.character.ChatCharacterHobby | 
			
		
	
		
		
			
				
					
					|  |  |  | import kr.co.vividnext.sodalive.chat.character.ChatCharacterTag |  |  |  | import kr.co.vividnext.sodalive.chat.character.ChatCharacterTag | 
			
		
	
		
		
			
				
					
					|  |  |  | import kr.co.vividnext.sodalive.chat.character.ChatCharacterValue |  |  |  | import kr.co.vividnext.sodalive.chat.character.ChatCharacterValue | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | import kr.co.vividnext.sodalive.chat.character.dto.Character | 
			
		
	
		
		
			
				
					
					|  |  |  | import kr.co.vividnext.sodalive.chat.character.repository.ChatCharacterGoalRepository |  |  |  | import kr.co.vividnext.sodalive.chat.character.repository.ChatCharacterGoalRepository | 
			
		
	
		
		
			
				
					
					|  |  |  | import kr.co.vividnext.sodalive.chat.character.repository.ChatCharacterHobbyRepository |  |  |  | import kr.co.vividnext.sodalive.chat.character.repository.ChatCharacterHobbyRepository | 
			
		
	
		
		
			
				
					
					|  |  |  | import kr.co.vividnext.sodalive.chat.character.repository.ChatCharacterRepository |  |  |  | import kr.co.vividnext.sodalive.chat.character.repository.ChatCharacterRepository | 
			
		
	
		
		
			
				
					
					|  |  |  | import kr.co.vividnext.sodalive.chat.character.repository.ChatCharacterTagRepository |  |  |  | import kr.co.vividnext.sodalive.chat.character.repository.ChatCharacterTagRepository | 
			
		
	
		
		
			
				
					
					|  |  |  | import kr.co.vividnext.sodalive.chat.character.repository.ChatCharacterValueRepository |  |  |  | import kr.co.vividnext.sodalive.chat.character.repository.ChatCharacterValueRepository | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | import org.springframework.beans.factory.annotation.Value | 
			
		
	
		
		
			
				
					
					|  |  |  | import org.springframework.cache.annotation.Cacheable |  |  |  | import org.springframework.cache.annotation.Cacheable | 
			
		
	
		
		
			
				
					
					|  |  |  | import org.springframework.data.domain.PageRequest |  |  |  | import org.springframework.data.domain.PageRequest | 
			
		
	
		
		
			
				
					
					|  |  |  | import org.springframework.stereotype.Service |  |  |  | import org.springframework.stereotype.Service | 
			
		
	
	
		
		
			
				
					
					|  |  | @@ -28,7 +30,10 @@ class ChatCharacterService( | 
			
		
	
		
		
			
				
					
					|  |  |  |     private val valueRepository: ChatCharacterValueRepository, |  |  |  |     private val valueRepository: ChatCharacterValueRepository, | 
			
		
	
		
		
			
				
					
					|  |  |  |     private val hobbyRepository: ChatCharacterHobbyRepository, |  |  |  |     private val hobbyRepository: ChatCharacterHobbyRepository, | 
			
		
	
		
		
			
				
					
					|  |  |  |     private val goalRepository: ChatCharacterGoalRepository, |  |  |  |     private val goalRepository: ChatCharacterGoalRepository, | 
			
		
	
		
		
			
				
					
					|  |  |  |     private val popularCharacterQuery: PopularCharacterQuery |  |  |  |     private val popularCharacterQuery: PopularCharacterQuery, | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     @Value("\${cloud.aws.cloud-front.host}") | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     private val imageHost: String | 
			
		
	
		
		
			
				
					
					|  |  |  | ) { |  |  |  | ) { | 
			
		
	
		
		
			
				
					
					|  |  |  |     /** |  |  |  |     /** | 
			
		
	
		
		
			
				
					
					|  |  |  |      * UTC 20:00 경계 기준 지난 윈도우의 메시지 수 상위 캐릭터 조회 |  |  |  |      * UTC 20:00 경계 기준 지난 윈도우의 메시지 수 상위 캐릭터 조회 | 
			
		
	
	
		
		
			
				
					
					|  |  | @@ -39,10 +44,18 @@ class ChatCharacterService( | 
			
		
	
		
		
			
				
					
					|  |  |  |         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-chat-character').cacheKey" | 
			
		
	
		
		
			
				
					
					|  |  |  |     ) |  |  |  |     ) | 
			
		
	
		
		
			
				
					
					|  |  |  |     fun getPopularCharacters(limit: Long = 20): List<ChatCharacter> { |  |  |  |     fun getPopularCharacters(limit: Long = 20): List<Character> { | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |         val window = RankingWindowCalculator.now("popular-chat-character") |  |  |  |         val window = RankingWindowCalculator.now("popular-chat-character") | 
			
		
	
		
		
			
				
					
					|  |  |  |         val topIds = popularCharacterQuery.findPopularCharacterIds(window.windowStart, window.nextBoundary, limit) |  |  |  |         val topIds = popularCharacterQuery.findPopularCharacterIds(window.windowStart, window.nextBoundary, limit) | 
			
		
	
		
		
			
				
					
					|  |  |  |         return loadCharactersInOrder(topIds) |  |  |  |         val list = loadCharactersInOrder(topIds) | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         return list.map { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             Character( | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 characterId = it.id!!, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 name = it.name, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 description = it.description, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 imageUrl = "$imageHost/${it.imagePath ?: "profile/default-profile.png"}" | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             ) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         } | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     private fun loadCharactersInOrder(ids: List<Long>): List<ChatCharacter> { |  |  |  |     private fun loadCharactersInOrder(ids: List<Long>): List<ChatCharacter> { | 
			
		
	
	
		
		
			
				
					
					|  |  |   |