|
| 1 | +package com.loopers.application.ranking; |
| 2 | + |
| 3 | +import com.loopers.interfaces.api.ranking.RankingV1Dto; |
| 4 | +import lombok.RequiredArgsConstructor; |
| 5 | +import org.springframework.data.redis.core.StringRedisTemplate; |
| 6 | +import org.springframework.data.redis.core.ZSetOperations; |
| 7 | +import org.springframework.stereotype.Component; |
| 8 | + |
| 9 | +import java.time.LocalDate; |
| 10 | +import java.time.ZoneId; |
| 11 | +import java.time.format.DateTimeFormatter; |
| 12 | +import java.util.ArrayList; |
| 13 | +import java.util.List; |
| 14 | +import java.util.Set; |
| 15 | + |
| 16 | +@Component |
| 17 | +@RequiredArgsConstructor |
| 18 | +public class RankingFacade { |
| 19 | + private final StringRedisTemplate redisTemplate; |
| 20 | + private static final ZoneId KST = ZoneId.of("Asia/Seoul"); |
| 21 | + private static final DateTimeFormatter YYYYMMDD = DateTimeFormatter.BASIC_ISO_DATE; |
| 22 | + |
| 23 | + public RankingV1Dto.ProductRankingPageResponse getDailyProductRanking(int page, int size) { |
| 24 | + if (page < 1) page = 1; |
| 25 | + if (size < 1) size = 20; |
| 26 | + |
| 27 | + String date = LocalDate.now(KST).format(YYYYMMDD); |
| 28 | + |
| 29 | + String key = "ranking:all:" + date; |
| 30 | + ZSetOperations<String, String> zset = redisTemplate.opsForZSet(); |
| 31 | + |
| 32 | + Long total = zset.size(key); |
| 33 | + long totalElements = (total == null) ? 0 : total; |
| 34 | + |
| 35 | + if (totalElements == 0) { |
| 36 | + return new RankingV1Dto.ProductRankingPageResponse(date, page, size, 0, 0, List.of()); |
| 37 | + } |
| 38 | + |
| 39 | + long start = (long) (page - 1) * size; |
| 40 | + long end = start + size - 1; |
| 41 | + |
| 42 | + if (start >= totalElements) { |
| 43 | + int totalPages = (int) Math.ceil((double) totalElements / size); |
| 44 | + return new RankingV1Dto.ProductRankingPageResponse(date, page, size, totalElements, totalPages, List.of()); |
| 45 | + } |
| 46 | + |
| 47 | + Set<ZSetOperations.TypedTuple<String>> tuples = |
| 48 | + zset.reverseRangeWithScores(key, start, end); |
| 49 | + |
| 50 | + List<RankingV1Dto.ProductRankingResponse> items = new ArrayList<>(); |
| 51 | + if (tuples != null) { |
| 52 | + long rank = start + 1; |
| 53 | + for (var t : tuples) { |
| 54 | + String member = t.getValue(); |
| 55 | + Double score = t.getScore(); |
| 56 | + if (member == null || score == null) continue; |
| 57 | + |
| 58 | + items.add(new RankingV1Dto.ProductRankingResponse( |
| 59 | + rank++, |
| 60 | + Long.parseLong(member), |
| 61 | + score |
| 62 | + )); |
| 63 | + } |
| 64 | + } |
| 65 | + |
| 66 | + int totalPages = (int) Math.ceil((double) totalElements / size); |
| 67 | + return new RankingV1Dto.ProductRankingPageResponse(date, page, size, totalElements, totalPages, items); |
| 68 | + } |
| 69 | + |
| 70 | +} |
0 commit comments