test #173
| @@ -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.QCreatorCheers.creatorCheers | ||||
| 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.LiveRoomType | ||||
| 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.stereotype.Repository | ||||
| import java.time.Duration | ||||
| import java.time.LocalDate | ||||
| import java.time.LocalDateTime | ||||
| import java.time.ZoneId | ||||
| import java.time.format.DateTimeFormatter | ||||
| @@ -172,36 +171,38 @@ class ExplorerQueryRepository( | ||||
|             .where( | ||||
|                 member.role.eq(MemberRole.CREATOR) | ||||
|                     .and(member.createdAt.goe(LocalDateTime.now().minusDays(30))) | ||||
|                     .and(member.isActive.isTrue) | ||||
|             ) | ||||
|             .orderBy(Expressions.numberTemplate(Double::class.java, "function('rand')").asc()) | ||||
|             .limit(20) | ||||
|             .fetch() | ||||
|     } | ||||
|  | ||||
|     fun getExplorerSectionData(isAdult: Boolean): List<ExplorerSection> { | ||||
|         var explorerSectionCondition = explorerSection.isActive.eq(true) | ||||
|         if (!isAdult) { | ||||
|             explorerSectionCondition = explorerSectionCondition.and(explorerSection.isAdult.isFalse) | ||||
|     fun findCreatorByGender(gender: Int): List<Member> { | ||||
|         val today = LocalDate.now() | ||||
|         val offset = (today.dayOfMonth - 1) % 26 | ||||
|         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 | ||||
|             .selectFrom(explorerSection) | ||||
|             .where(explorerSectionCondition) | ||||
|             .orderBy(explorerSection.orders.asc()) | ||||
|             .fetch() | ||||
|     } | ||||
|         val randomExpression = Expressions.numberTemplate(Double::class.java, "function('rand')").asc() | ||||
|  | ||||
|     fun findMemberByTag(tags: List<String>): List<Member> { | ||||
|         return queryFactory | ||||
|             .selectFrom(member) | ||||
|             .leftJoin(member.tags, memberCreatorTag) | ||||
|             .join(memberCreatorTag.tag, creatorTag) | ||||
|             .innerJoin(member.auth, auth) | ||||
|             .where( | ||||
|                 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() | ||||
|             .distinct() | ||||
|     } | ||||
|  | ||||
|     fun getSearchChannel(channel: String, memberId: Long): List<Member> { | ||||
|   | ||||
| @@ -29,6 +29,7 @@ import java.time.LocalDate | ||||
| import java.time.LocalDateTime | ||||
| import java.time.format.DateTimeFormatter | ||||
| import java.time.temporal.TemporalAdjusters | ||||
| import kotlin.random.Random | ||||
|  | ||||
| @Service | ||||
| @Transactional(readOnly = true) | ||||
| @@ -52,25 +53,8 @@ class ExplorerService( | ||||
|         // 인기 크리에이터 | ||||
|         val creatorRankings = queryRepository | ||||
|             .getCreatorRankings() | ||||
|             .asSequence() | ||||
|             .filter { !memberService.isBlocked(blockedMemberId = member.id!!, memberId = it.id!!) } | ||||
|             .map { | ||||
|                 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() | ||||
|             .map { it.toExplorerSectionCreator(cloudFrontHost) } | ||||
|  | ||||
|         val currentDateTime = LocalDateTime.now() | ||||
|         val lastMonday = currentDateTime | ||||
| @@ -97,25 +81,8 @@ class ExplorerService( | ||||
|         // 새로 시작 (newCreators) | ||||
|         val newCreators = queryRepository | ||||
|             .getNewCreators() | ||||
|             .asSequence() | ||||
|             .filter { !memberService.isBlocked(blockedMemberId = member.id!!, memberId = it.id!!) } | ||||
|             .map { | ||||
|                 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() | ||||
|             .map { it.toExplorerSectionCreator(cloudFrontHost) } | ||||
|  | ||||
|         val newCreatorsSection = GetExplorerSectionResponse( | ||||
|             title = "새로 시작", | ||||
| @@ -125,52 +92,35 @@ class ExplorerService( | ||||
|         ) | ||||
|         sections.add(newCreatorsSection) | ||||
|  | ||||
|         // 관리자에서 설정한 타이틀과 크리에이터 | ||||
|         sections.addAll( | ||||
|             queryRepository | ||||
|                 .getExplorerSectionData(isAdult = member.auth != null) | ||||
|                 .asSequence() | ||||
|                 .map { | ||||
|                     val tags = it.tags.asSequence().map { explorerSectionTag -> explorerSectionTag.tag!!.tag }.toList() | ||||
|                     val creators = queryRepository.findMemberByTag(tags) | ||||
|                         .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 maleCreatorSection = GetExplorerSectionResponse( | ||||
|             title = "남자 크리에이터", | ||||
|             coloredTitle = "남자", | ||||
|             color = "39abde", | ||||
|             creators = queryRepository | ||||
|                 .findCreatorByGender(1) | ||||
|                 .filter { !memberService.isBlocked(blockedMemberId = member.id!!, memberId = it.id!!) } | ||||
|                 .map { it.toExplorerSectionCreator(cloudFrontHost) } | ||||
|         ) | ||||
|  | ||||
|         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) | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -1,6 +1,7 @@ | ||||
| package kr.co.vividnext.sodalive.member | ||||
|  | ||||
| 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.following.CreatorFollowing | ||||
| 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 { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user