Merge pull request 'test' (#173) from test into main

Reviewed-on: #173
This commit is contained in:
klaus 2024-05-02 16:41:50 +00:00
commit dd07d724a8
3 changed files with 65 additions and 97 deletions

View File

@ -18,8 +18,6 @@ import kr.co.vividnext.sodalive.explorer.profile.CreatorCheers
import kr.co.vividnext.sodalive.explorer.profile.QChannelNotice.channelNotice import kr.co.vividnext.sodalive.explorer.profile.QChannelNotice.channelNotice
import kr.co.vividnext.sodalive.explorer.profile.QCreatorCheers.creatorCheers import kr.co.vividnext.sodalive.explorer.profile.QCreatorCheers.creatorCheers
import kr.co.vividnext.sodalive.explorer.profile.TimeDifferenceResult import kr.co.vividnext.sodalive.explorer.profile.TimeDifferenceResult
import kr.co.vividnext.sodalive.explorer.section.ExplorerSection
import kr.co.vividnext.sodalive.explorer.section.QExplorerSection.explorerSection
import kr.co.vividnext.sodalive.live.room.LiveRoom import kr.co.vividnext.sodalive.live.room.LiveRoom
import kr.co.vividnext.sodalive.live.room.LiveRoomType import kr.co.vividnext.sodalive.live.room.LiveRoomType
import kr.co.vividnext.sodalive.live.room.QLiveRoom.liveRoom import kr.co.vividnext.sodalive.live.room.QLiveRoom.liveRoom
@ -36,6 +34,7 @@ import kr.co.vividnext.sodalive.member.tag.QMemberCreatorTag.memberCreatorTag
import org.springframework.beans.factory.annotation.Value import org.springframework.beans.factory.annotation.Value
import org.springframework.stereotype.Repository import org.springframework.stereotype.Repository
import java.time.Duration import java.time.Duration
import java.time.LocalDate
import java.time.LocalDateTime import java.time.LocalDateTime
import java.time.ZoneId import java.time.ZoneId
import java.time.format.DateTimeFormatter import java.time.format.DateTimeFormatter
@ -172,36 +171,38 @@ class ExplorerQueryRepository(
.where( .where(
member.role.eq(MemberRole.CREATOR) member.role.eq(MemberRole.CREATOR)
.and(member.createdAt.goe(LocalDateTime.now().minusDays(30))) .and(member.createdAt.goe(LocalDateTime.now().minusDays(30)))
.and(member.isActive.isTrue)
) )
.orderBy(Expressions.numberTemplate(Double::class.java, "function('rand')").asc()) .orderBy(Expressions.numberTemplate(Double::class.java, "function('rand')").asc())
.limit(20) .limit(20)
.fetch() .fetch()
} }
fun getExplorerSectionData(isAdult: Boolean): List<ExplorerSection> { fun findCreatorByGender(gender: Int): List<Member> {
var explorerSectionCondition = explorerSection.isActive.eq(true) val today = LocalDate.now()
if (!isAdult) { val offset = (today.dayOfMonth - 1) % 26
explorerSectionCondition = explorerSectionCondition.and(explorerSection.isAdult.isFalse) val characters = ('A'..'Z').map { it.toString() }
val rotatedChars = characters.drop(offset) + characters.take(offset)
val caseWhenClauses = rotatedChars.withIndex().joinToString(" ") {
"WHEN ${member.email} LIKE '${it.value}%' THEN ${it.index + 1}"
} }
val caseExpression = Expressions.stringTemplate("CASE $caseWhenClauses END")
return queryFactory val randomExpression = Expressions.numberTemplate(Double::class.java, "function('rand')").asc()
.selectFrom(explorerSection)
.where(explorerSectionCondition)
.orderBy(explorerSection.orders.asc())
.fetch()
}
fun findMemberByTag(tags: List<String>): List<Member> {
return queryFactory return queryFactory
.selectFrom(member) .selectFrom(member)
.leftJoin(member.tags, memberCreatorTag) .innerJoin(member.auth, auth)
.join(memberCreatorTag.tag, creatorTag)
.where( .where(
member.role.eq(MemberRole.CREATOR) member.role.eq(MemberRole.CREATOR)
.and(creatorTag.tag.`in`(tags)) .and(member.isActive.isTrue)
.and(auth.gender.eq(gender))
) )
.orderBy(caseExpression.asc(), randomExpression)
.offset(0)
.limit(10)
.fetch() .fetch()
.distinct()
} }
fun getSearchChannel(channel: String, memberId: Long): List<Member> { fun getSearchChannel(channel: String, memberId: Long): List<Member> {

View File

@ -29,6 +29,7 @@ import java.time.LocalDate
import java.time.LocalDateTime import java.time.LocalDateTime
import java.time.format.DateTimeFormatter import java.time.format.DateTimeFormatter
import java.time.temporal.TemporalAdjusters import java.time.temporal.TemporalAdjusters
import kotlin.random.Random
@Service @Service
@Transactional(readOnly = true) @Transactional(readOnly = true)
@ -52,25 +53,8 @@ class ExplorerService(
// 인기 크리에이터 // 인기 크리에이터
val creatorRankings = queryRepository val creatorRankings = queryRepository
.getCreatorRankings() .getCreatorRankings()
.asSequence()
.filter { !memberService.isBlocked(blockedMemberId = member.id!!, memberId = it.id!!) } .filter { !memberService.isBlocked(blockedMemberId = member.id!!, memberId = it.id!!) }
.map { .map { it.toExplorerSectionCreator(cloudFrontHost) }
GetExplorerSectionCreatorResponse(
id = it.id!!,
nickname = it.nickname,
tags = it.tags
.asSequence()
.filter { tag -> tag.tag.isActive }
.map { tag -> tag.tag.tag }
.joinToString(" ") { tag -> "#$tag" },
profileImageUrl = if (it.profileImage != null) {
"$cloudFrontHost/${it.profileImage}"
} else {
"$cloudFrontHost/profile/default-profile.png"
}
)
}
.toList()
val currentDateTime = LocalDateTime.now() val currentDateTime = LocalDateTime.now()
val lastMonday = currentDateTime val lastMonday = currentDateTime
@ -97,25 +81,8 @@ class ExplorerService(
// 새로 시작 (newCreators) // 새로 시작 (newCreators)
val newCreators = queryRepository val newCreators = queryRepository
.getNewCreators() .getNewCreators()
.asSequence()
.filter { !memberService.isBlocked(blockedMemberId = member.id!!, memberId = it.id!!) } .filter { !memberService.isBlocked(blockedMemberId = member.id!!, memberId = it.id!!) }
.map { .map { it.toExplorerSectionCreator(cloudFrontHost) }
GetExplorerSectionCreatorResponse(
id = it.id!!,
nickname = it.nickname,
tags = it.tags
.asSequence()
.filter { tag -> tag.tag.isActive }
.map { tag -> tag.tag.tag }
.joinToString(" ") { tag -> "#$tag" },
profileImageUrl = if (it.profileImage != null) {
"$cloudFrontHost/${it.profileImage}"
} else {
"$cloudFrontHost/profile/default-profile.png"
}
)
}
.toList()
val newCreatorsSection = GetExplorerSectionResponse( val newCreatorsSection = GetExplorerSectionResponse(
title = "새로 시작", title = "새로 시작",
@ -125,52 +92,35 @@ class ExplorerService(
) )
sections.add(newCreatorsSection) sections.add(newCreatorsSection)
// 관리자에서 설정한 타이틀과 크리에이터 val maleCreatorSection = GetExplorerSectionResponse(
sections.addAll( title = "남자 크리에이터",
queryRepository coloredTitle = "남자",
.getExplorerSectionData(isAdult = member.auth != null) color = "39abde",
.asSequence() creators = queryRepository
.map { .findCreatorByGender(1)
val tags = it.tags.asSequence().map { explorerSectionTag -> explorerSectionTag.tag!!.tag }.toList() .filter { !memberService.isBlocked(blockedMemberId = member.id!!, memberId = it.id!!) }
val creators = queryRepository.findMemberByTag(tags) .map { it.toExplorerSectionCreator(cloudFrontHost) }
.asSequence()
.filter { creator ->
!memberService.isBlocked(
blockedMemberId = member.id!!,
memberId = creator.id!!
)
}
.toList()
GetExplorerSectionResponse(
it.title,
it.coloredTitle,
it.color,
creators = creators
.asSequence()
.map { account ->
GetExplorerSectionCreatorResponse(
id = account.id!!,
nickname = account.nickname,
tags = account.tags
.asSequence()
.filter { counselorTag -> counselorTag.tag.isActive }
.toList()
.joinToString(" ") { counselorTag ->
"#${counselorTag.tag.tag}"
},
profileImageUrl = if (account.profileImage != null) {
"$cloudFrontHost/${account.profileImage}"
} else {
"$cloudFrontHost/profile/default-profile.png"
}
)
}.toList()
)
}
.toList()
) )
val femaleCreatorSection = GetExplorerSectionResponse(
title = "여자 크리에이터",
coloredTitle = "여자",
color = "ff5c49",
creators = queryRepository
.findCreatorByGender(0)
.filter { !memberService.isBlocked(blockedMemberId = member.id!!, memberId = it.id!!) }
.map { it.toExplorerSectionCreator(cloudFrontHost) }
)
val randomInt = Random.nextInt(0, 2)
if (randomInt == 0) {
sections.add(femaleCreatorSection)
sections.add(maleCreatorSection)
} else {
sections.add(maleCreatorSection)
sections.add(femaleCreatorSection)
}
return GetExplorerResponse(sections = sections) return GetExplorerResponse(sections = sections)
} }

View File

@ -1,6 +1,7 @@
package kr.co.vividnext.sodalive.member package kr.co.vividnext.sodalive.member
import kr.co.vividnext.sodalive.common.BaseEntity import kr.co.vividnext.sodalive.common.BaseEntity
import kr.co.vividnext.sodalive.explorer.GetExplorerSectionCreatorResponse
import kr.co.vividnext.sodalive.member.auth.Auth import kr.co.vividnext.sodalive.member.auth.Auth
import kr.co.vividnext.sodalive.member.following.CreatorFollowing import kr.co.vividnext.sodalive.member.following.CreatorFollowing
import kr.co.vividnext.sodalive.member.notification.MemberNotification import kr.co.vividnext.sodalive.member.notification.MemberNotification
@ -107,6 +108,22 @@ data class Member(
} }
} }
} }
fun toExplorerSectionCreator(imageHost: String): GetExplorerSectionCreatorResponse {
return GetExplorerSectionCreatorResponse(
id = id!!,
nickname = nickname,
tags = tags
.filter { tag -> tag.tag.isActive }
.map { tag -> tag.tag.tag }
.joinToString(" ") { tag -> "#$tag" },
profileImageUrl = if (profileImage != null) {
"$imageHost/$profileImage"
} else {
"$imageHost/profile/default-profile.png"
}
)
}
} }
enum class Gender { enum class Gender {