package kr.co.vividnext.sodalive.rank import kr.co.vividnext.sodalive.content.ContentType import kr.co.vividnext.sodalive.content.main.ContentCreatorResponse import kr.co.vividnext.sodalive.content.main.GetAudioContentRankingItem import kr.co.vividnext.sodalive.content.series.GetSeriesListResponse import kr.co.vividnext.sodalive.content.series.content.ContentSeriesContentRepository import kr.co.vividnext.sodalive.creator.admin.content.series.Series import kr.co.vividnext.sodalive.creator.admin.content.series.SeriesPublishedDaysOfWeek import kr.co.vividnext.sodalive.creator.admin.content.series.SeriesState import kr.co.vividnext.sodalive.explorer.GetExplorerSectionResponse import kr.co.vividnext.sodalive.member.MemberService import org.springframework.beans.factory.annotation.Value import org.springframework.stereotype.Service import java.time.LocalDateTime @Service class RankingService( private val repository: RankingRepository, private val memberService: MemberService, private val seriesContentRepository: ContentSeriesContentRepository, @Value("\${cloud.aws.cloud-front.host}") private val imageHost: String ) { fun getCreatorRanking(memberId: Long?, rankingDate: String): GetExplorerSectionResponse { val creatorRankings = repository .getCreatorRankings() .filter { if (memberId != null) { !memberService.isBlocked(blockedMemberId = memberId, memberId = it.id!!) } else { true } } .map { it.toExplorerSectionCreator(imageHost) } return GetExplorerSectionResponse( title = "인기 크리에이터", coloredTitle = "인기", color = "FF5C49", desc = rankingDate, creators = creatorRankings ) } fun getContentRanking( memberId: Long?, isAdult: Boolean, contentType: ContentType, startDate: LocalDateTime, endDate: LocalDateTime, offset: Long = 0, limit: Long = 12, sortType: String = "매출", theme: String = "" ): List { var loopCount = 0L var contentList: List do { contentList = repository.getAudioContentRanking( memberId = memberId, isAdult = isAdult, contentType = contentType, startDate = startDate.minusWeeks(loopCount), endDate = endDate, offset = offset, limit = limit, sortType = sortType, theme = theme ) loopCount++ } while (contentList.size < 5 && loopCount < 5) return contentList } fun getSeriesRanking( memberId: Long?, isAdult: Boolean, contentType: ContentType, startDate: LocalDateTime, endDate: LocalDateTime ): List { var loopCount = 0L var seriesList: List do { seriesList = repository.getSeriesRanking( memberId = memberId, isAdult = isAdult, contentType = contentType, startDate = startDate.minusWeeks(loopCount), endDate = endDate ) loopCount++ } while (seriesList.size < 5 && loopCount < 5) return seriesToSeriesListItem(seriesList = seriesList, isAdult = isAdult, contentType = contentType) } fun getSeriesAllRankingByGenre( memberId: Long, isAdult: Boolean, contentType: ContentType, genreId: Long ): List { val seriesList = repository.getSeriesAllRankingByGenre( memberId = memberId, isAdult = isAdult, contentType = contentType, genreId = genreId ) return seriesToSeriesListItem(seriesList = seriesList, isAdult = isAdult, contentType = contentType) } fun getCompleteSeriesRankingTotalCount( memberId: Long, isAdult: Boolean, contentType: ContentType ): Int { return repository.getCompleteSeriesRankingTotalCount( memberId = memberId, isAdult = isAdult, contentType = contentType ) } fun getCompleteSeriesRanking( memberId: Long, isAdult: Boolean, contentType: ContentType, startDate: LocalDateTime, endDate: LocalDateTime, offset: Long = 0, limit: Long = 10 ): List { val seriesList = repository.getCompleteSeriesRanking( memberId = memberId, isAdult = isAdult, contentType = contentType, startDate = startDate, endDate = endDate, offset = offset, limit = limit ) return seriesToSeriesListItem(seriesList = seriesList, isAdult = isAdult, contentType = contentType) } private fun seriesToSeriesListItem( seriesList: List, isAdult: Boolean, contentType: ContentType ): List { return seriesList .map { GetSeriesListResponse.SeriesListItem( seriesId = it.id!!, title = it.title, coverImage = "$imageHost/${it.coverImage!!}", publishedDaysOfWeek = publishedDaysOfWeekText(it.publishedDaysOfWeek), isComplete = it.state == SeriesState.COMPLETE, creator = GetSeriesListResponse.SeriesListItemCreator( creatorId = it.member!!.id!!, nickname = it.member!!.nickname, profileImage = "$imageHost/${it.member!!.profileImage!!}" ) ) } .map { it.numberOfContent = seriesContentRepository.getContentCount( seriesId = it.seriesId, isAdult = isAdult, contentType = contentType ) it } .map { val nowDateTime = LocalDateTime.now() it.isNew = seriesContentRepository.isNewContent( seriesId = it.seriesId, isAdult = isAdult, fromDate = nowDateTime.minusDays(7), nowDate = nowDateTime ) it } } private fun publishedDaysOfWeekText(publishedDaysOfWeek: Set): String { val dayOfWeekText = publishedDaysOfWeek.toList().sortedBy { it.ordinal } .map { when (it) { SeriesPublishedDaysOfWeek.SUN -> "일" SeriesPublishedDaysOfWeek.MON -> "월" SeriesPublishedDaysOfWeek.TUE -> "화" SeriesPublishedDaysOfWeek.WED -> "수" SeriesPublishedDaysOfWeek.THU -> "목" SeriesPublishedDaysOfWeek.FRI -> "금" SeriesPublishedDaysOfWeek.SAT -> "토" SeriesPublishedDaysOfWeek.RANDOM -> "랜덤" } } .joinToString(", ") { it } return if (publishedDaysOfWeek.contains(SeriesPublishedDaysOfWeek.RANDOM)) { dayOfWeekText } else if (publishedDaysOfWeek.size < 7) { "매주 $dayOfWeekText" } else { "매일" } } fun fetchCreatorBySellContentCountRankTop20( memberId: Long?, isAdult: Boolean, contentType: ContentType, startDate: LocalDateTime, endDate: LocalDateTime ): List { return repository.fetchCreatorBySellContentCountRankTop20(memberId, isAdult, contentType, startDate, endDate) } fun fetchCreatorContentBySalesCountTop4( creatorId: Long, isAdult: Boolean, contentType: ContentType, theme: String = "" ): List { return repository.fetchCreatorContentBySalesCountTop4(creatorId, isAdult, contentType, theme) } fun fetchCreatorContentByLikeCountTop4( creatorId: Long, isAdult: Boolean, contentType: ContentType ): List { return repository.fetchCreatorContentByLikeCountTop4(creatorId, isAdult, contentType) } fun fetchCreatorBySeriesRevenueRankTop20( memberId: Long, contentType: ContentType, startDate: LocalDateTime, endDate: LocalDateTime ): List { return repository.fetchCreatorBySeriesRevenueRankTop20(memberId, contentType, startDate, endDate) } fun fetchCreatorSeriesBySales( creatorId: Long, isAdult: Boolean, contentType: ContentType ): List { val seriesList = repository.fetchCreatorSeriesBySales( creatorId = creatorId, isAdult = isAdult, contentType = contentType ) return seriesToSeriesListItem(seriesList, isAdult, contentType = contentType) } fun fetchFreeContentByCreatorIdTop4( creatorId: Long, isAdult: Boolean, contentType: ContentType ): List { return repository.fetchFreeContentByCreatorIdTop4(creatorId, isAdult, contentType) } }