feat(ranking): 크리에이터 랭킹 점수 정책을 추가한다
This commit is contained in:
@@ -0,0 +1,49 @@
|
|||||||
|
package kr.co.vividnext.sodalive.v2.ranking.domain
|
||||||
|
|
||||||
|
class CreatorRankingScorePolicy {
|
||||||
|
fun calculateContentLiveScore(
|
||||||
|
liveCanAmount: Long,
|
||||||
|
contentPurchaseCanAmount: Long
|
||||||
|
): Double {
|
||||||
|
return (liveCanAmount * CreatorRankingScoreSpec.CONTENT_LIVE_CAN_WEIGHT) +
|
||||||
|
(contentPurchaseCanAmount * CreatorRankingScoreSpec.CONTENT_PURCHASE_CAN_WEIGHT)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun calculateEngagementScore(
|
||||||
|
contentLikeCount: Long,
|
||||||
|
contentCommentCount: Long
|
||||||
|
): Double {
|
||||||
|
return (contentLikeCount * CreatorRankingScoreSpec.CONTENT_LIKE_COUNT_WEIGHT) +
|
||||||
|
(contentCommentCount * CreatorRankingScoreSpec.CONTENT_COMMENT_COUNT_WEIGHT)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun calculateSupportScore(
|
||||||
|
channelDonationCanAmount: Long,
|
||||||
|
channelDonationCount: Long,
|
||||||
|
fanTalkCount: Long
|
||||||
|
): Double {
|
||||||
|
return (channelDonationCanAmount * CreatorRankingScoreSpec.CHANNEL_DONATION_CAN_WEIGHT) +
|
||||||
|
(channelDonationCount * CreatorRankingScoreSpec.CHANNEL_DONATION_COUNT_WEIGHT) +
|
||||||
|
(fanTalkCount * CreatorRankingScoreSpec.FAN_TALK_COUNT_WEIGHT)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun calculateFanLoyaltyScore(
|
||||||
|
finalFollowerCount: Long,
|
||||||
|
followIncrease: Long
|
||||||
|
): Double {
|
||||||
|
return (finalFollowerCount * CreatorRankingScoreSpec.FINAL_FOLLOWER_COUNT_WEIGHT) +
|
||||||
|
(followIncrease * CreatorRankingScoreSpec.FOLLOW_INCREASE_WEIGHT)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun calculateFinalScore(
|
||||||
|
contentLiveScore: Double,
|
||||||
|
engagementScore: Double,
|
||||||
|
supportScore: Double,
|
||||||
|
fanLoyaltyScore: Double
|
||||||
|
): Double {
|
||||||
|
return (contentLiveScore * CreatorRankingScoreSpec.CONTENT_LIVE_SCORE_WEIGHT) +
|
||||||
|
(engagementScore * CreatorRankingScoreSpec.ENGAGEMENT_SCORE_WEIGHT) +
|
||||||
|
(supportScore * CreatorRankingScoreSpec.SUPPORT_SCORE_WEIGHT) +
|
||||||
|
(fanLoyaltyScore * CreatorRankingScoreSpec.FAN_LOYALTY_SCORE_WEIGHT)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
package kr.co.vividnext.sodalive.v2.ranking.domain
|
||||||
|
|
||||||
|
object CreatorRankingScoreSpec {
|
||||||
|
const val CONTENT_LIVE_CAN_WEIGHT = 0.7
|
||||||
|
const val CONTENT_PURCHASE_CAN_WEIGHT = 0.3
|
||||||
|
|
||||||
|
const val CONTENT_LIKE_COUNT_WEIGHT = 0.5
|
||||||
|
const val CONTENT_COMMENT_COUNT_WEIGHT = 0.5
|
||||||
|
|
||||||
|
const val CHANNEL_DONATION_CAN_WEIGHT = 0.6
|
||||||
|
const val CHANNEL_DONATION_COUNT_WEIGHT = 0.2
|
||||||
|
const val FAN_TALK_COUNT_WEIGHT = 0.2
|
||||||
|
|
||||||
|
const val FINAL_FOLLOWER_COUNT_WEIGHT = 0.7
|
||||||
|
const val FOLLOW_INCREASE_WEIGHT = 0.3
|
||||||
|
|
||||||
|
const val CONTENT_LIVE_SCORE_WEIGHT = 0.35
|
||||||
|
const val ENGAGEMENT_SCORE_WEIGHT = 0.3
|
||||||
|
const val SUPPORT_SCORE_WEIGHT = 0.25
|
||||||
|
const val FAN_LOYALTY_SCORE_WEIGHT = 0.1
|
||||||
|
}
|
||||||
@@ -0,0 +1,76 @@
|
|||||||
|
package kr.co.vividnext.sodalive.v2.ranking.domain
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Assertions.assertEquals
|
||||||
|
import org.junit.jupiter.api.DisplayName
|
||||||
|
import org.junit.jupiter.api.Test
|
||||||
|
|
||||||
|
class CreatorRankingScorePolicyTest {
|
||||||
|
private val policy = CreatorRankingScorePolicy()
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("콘텐츠/라이브 점수는 라이브 계열 캔 70%와 콘텐츠 구매 캔 30%를 raw value로 계산한다")
|
||||||
|
fun shouldCalculateContentLiveScore() {
|
||||||
|
assertEquals(0.7, CreatorRankingScoreSpec.CONTENT_LIVE_CAN_WEIGHT, 0.0001)
|
||||||
|
assertEquals(0.3, CreatorRankingScoreSpec.CONTENT_PURCHASE_CAN_WEIGHT, 0.0001)
|
||||||
|
|
||||||
|
val score = policy.calculateContentLiveScore(liveCanAmount = 1000, contentPurchaseCanAmount = 200)
|
||||||
|
|
||||||
|
assertEquals(760.0, score, 0.0001)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("참여 반응 점수는 좋아요 수와 댓글 수를 각각 50% raw value로 계산한다")
|
||||||
|
fun shouldCalculateEngagementScore() {
|
||||||
|
assertEquals(0.5, CreatorRankingScoreSpec.CONTENT_LIKE_COUNT_WEIGHT, 0.0001)
|
||||||
|
assertEquals(0.5, CreatorRankingScoreSpec.CONTENT_COMMENT_COUNT_WEIGHT, 0.0001)
|
||||||
|
|
||||||
|
val score = policy.calculateEngagementScore(contentLikeCount = 40, contentCommentCount = 20)
|
||||||
|
|
||||||
|
assertEquals(30.0, score, 0.0001)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("응원 점수는 채널 후원 캔/건수와 팬 Talk 수를 raw value로 계산한다")
|
||||||
|
fun shouldCalculateSupportScore() {
|
||||||
|
assertEquals(0.6, CreatorRankingScoreSpec.CHANNEL_DONATION_CAN_WEIGHT, 0.0001)
|
||||||
|
assertEquals(0.2, CreatorRankingScoreSpec.CHANNEL_DONATION_COUNT_WEIGHT, 0.0001)
|
||||||
|
assertEquals(0.2, CreatorRankingScoreSpec.FAN_TALK_COUNT_WEIGHT, 0.0001)
|
||||||
|
|
||||||
|
val score = policy.calculateSupportScore(
|
||||||
|
channelDonationCanAmount = 1000,
|
||||||
|
channelDonationCount = 10,
|
||||||
|
fanTalkCount = 20
|
||||||
|
)
|
||||||
|
|
||||||
|
assertEquals(606.0, score, 0.0001)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("팬 충성도 점수는 음수 팔로우 증가 수를 최종 점수에 그대로 반영한다")
|
||||||
|
fun shouldCalculateFanLoyaltyScoreWithNegativeFollowIncrease() {
|
||||||
|
assertEquals(0.7, CreatorRankingScoreSpec.FINAL_FOLLOWER_COUNT_WEIGHT, 0.0001)
|
||||||
|
assertEquals(0.3, CreatorRankingScoreSpec.FOLLOW_INCREASE_WEIGHT, 0.0001)
|
||||||
|
|
||||||
|
val score = policy.calculateFanLoyaltyScore(finalFollowerCount = 100, followIncrease = -10)
|
||||||
|
|
||||||
|
assertEquals(67.0, score, 0.0001)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("최종 점수는 카테고리별 점수에 PRD 가중치를 적용하고 0~100 정규화하지 않는다")
|
||||||
|
fun shouldCalculateFinalScoreWithoutNormalization() {
|
||||||
|
assertEquals(0.35, CreatorRankingScoreSpec.CONTENT_LIVE_SCORE_WEIGHT, 0.0001)
|
||||||
|
assertEquals(0.3, CreatorRankingScoreSpec.ENGAGEMENT_SCORE_WEIGHT, 0.0001)
|
||||||
|
assertEquals(0.25, CreatorRankingScoreSpec.SUPPORT_SCORE_WEIGHT, 0.0001)
|
||||||
|
assertEquals(0.1, CreatorRankingScoreSpec.FAN_LOYALTY_SCORE_WEIGHT, 0.0001)
|
||||||
|
|
||||||
|
val score = policy.calculateFinalScore(
|
||||||
|
contentLiveScore = 760.0,
|
||||||
|
engagementScore = 30.0,
|
||||||
|
supportScore = 606.0,
|
||||||
|
fanLoyaltyScore = 67.0
|
||||||
|
)
|
||||||
|
|
||||||
|
assertEquals(433.2, score, 0.0001)
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user