| @@ -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> { | ||||||
|   | |||||||
| @@ -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) | ||||||
|     } |     } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -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 { | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user