1010@ Component
1111public class ScoreCalculator {
1212
13- // 가중치 상수 (Redis ZSET과 동일하게 유지)
14- private static final int VIEW_WEIGHT = 1 ;
15- private static final int LIKE_WEIGHT = 3 ;
16- private static final int SALES_WEIGHT = 5 ;
17- private static final int ORDER_WEIGHT = 2 ;
13+ // CachePayloads의 EventType 가중치와 일치하도록 조정 (비율 유지)
14+ private static final double VIEW_WEIGHT = 0.1 ;
15+ private static final double LIKE_WEIGHT = 0.2 ;
16+ private static final double SALES_WEIGHT = 0.6 ; // 주문(결제성공) 가중치
1817
1918 /**
2019 * 메트릭 데이터를 기반으로 랭킹 점수를 계산합니다.
@@ -26,17 +25,26 @@ public class ScoreCalculator {
2625 * @return 계산된 총 점수
2726 */
2827 public long calculate (long viewCount , long likeCount , long salesCount , long orderCount ) {
29- return viewCount * VIEW_WEIGHT
30- + likeCount * LIKE_WEIGHT
31- + salesCount * SALES_WEIGHT
32- + orderCount * ORDER_WEIGHT ;
28+ // 1. 조회와 좋아요는 단순 수량 기반 가중치 적용
29+ double viewScore = viewCount * VIEW_WEIGHT ;
30+ double likeScore = likeCount * LIKE_WEIGHT ;
31+
32+ // 2. 판매량(Sales)은 CachePayloads.forPaymentSuccess와 동일하게 로그 정규화 적용
33+ // 배치에서는 이미 집계된 salesCount(수량)를 기반으로 하므로,
34+ // 만약 금액 기반 정규화가 필요하다면 매개변수로 총액을 받아야 하지만,
35+ // 수량 기반으로 로그 정규화를 적용한다면 아래와 같이 작성합니다.
36+ double normalizedSalesScore = Math .log1p (salesCount ) * SALES_WEIGHT ;
37+
38+ // 3. 최종 점수 계산 (소수점 처리를 위해 적절한 스케일 곱산 후 long 변환)
39+ // Redis ZSET의 score가 double임을 감안하여 정밀도를 유지합니다.
40+ return (long ) ((viewScore + likeScore + normalizedSalesScore ) * 1000 );
3341 }
3442
3543 /**
3644 * 가중치 정보를 반환합니다. (테스트 및 디버깅용)
3745 */
3846 public String getWeightInfo () {
39- return String .format ("VIEW=%d , LIKE=%d , SALES=%d, ORDER=%d " ,
40- VIEW_WEIGHT , LIKE_WEIGHT , SALES_WEIGHT , ORDER_WEIGHT );
47+ return String .format ("VIEW=%f , LIKE=%f , SALES=%f, " ,
48+ VIEW_WEIGHT , LIKE_WEIGHT , SALES_WEIGHT );
4149 }
4250}
0 commit comments