-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathGeneralFeedRankingService.java
More file actions
127 lines (108 loc) · 5.7 KB
/
GeneralFeedRankingService.java
File metadata and controls
127 lines (108 loc) · 5.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
package ddingdong.ddingdongBE.domain.feed.service;
import ddingdong.ddingdongBE.domain.club.entity.Club;
import ddingdong.ddingdongBE.domain.club.service.ClubService;
import ddingdong.ddingdongBE.domain.feed.entity.FeedMonthlyRanking;
import ddingdong.ddingdongBE.domain.feed.repository.FeedMonthlyRankingRepository;
import ddingdong.ddingdongBE.domain.feed.repository.FeedRepository;
import ddingdong.ddingdongBE.domain.feed.repository.dto.MonthlyFeedRankingDto;
import ddingdong.ddingdongBE.domain.feed.service.dto.query.ClubFeedRankingQuery;
import ddingdong.ddingdongBE.domain.feed.service.dto.query.ClubMonthlyStatusQuery;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
@RequiredArgsConstructor
@Transactional(readOnly = true)
public class GeneralFeedRankingService implements FeedRankingService {
private static final int FEED_WEIGHT = 10;
private static final int VIEW_WEIGHT = 1;
private static final int LIKE_WEIGHT = 3;
private static final int COMMENT_WEIGHT = 5;
private final FeedRepository feedRepository;
private final FeedMonthlyRankingRepository feedMonthlyRankingRepository;
private final ClubService clubService;
@Override
public List<ClubFeedRankingQuery> getClubFeedRanking(int year, int month) {
List<MonthlyFeedRankingDto> rawRankings = feedRepository.findMonthlyRankingByClub(year, month);
List<MonthlyFeedRankingDto> sorted = rawRankings.stream()
.sorted(Comparator.comparingLong(this::calculateScore).reversed())
.toList();
List<ClubFeedRankingQuery> result = new ArrayList<>();
long previousScore = Long.MAX_VALUE;
int rank = 1;
for (int i = 0; i < sorted.size(); i++) {
long totalScore = calculateScore(sorted.get(i));
if (i > 0 && totalScore < previousScore) {
rank = i + 1;
}
result.add(toClubFeedRankingQuery(rank, sorted.get(i)));
previousScore = totalScore;
}
return result;
}
@Override
public ClubMonthlyStatusQuery getClubMonthlyStatus(Long userId, int year, int month) {
Club club = clubService.getByUserId(userId);
List<ClubFeedRankingQuery> rankings = getClubFeedRanking(year, month);
int lastMonthRank = getLastMonthRank(club.getId(), year, month);
return rankings.stream()
.filter(rankingQuery -> rankingQuery.clubId().equals(club.getId()))
.findFirst()
.filter(rankingQuery -> rankingQuery.totalScore() > 0)
.map(rankingQuery -> toMonthlyStatus(year, month, rankingQuery, lastMonthRank))
.orElse(ClubMonthlyStatusQuery.createEmpty(year, month, lastMonthRank));
}
private ClubMonthlyStatusQuery toMonthlyStatus(int year, int month,
ClubFeedRankingQuery ranking, int lastMonthRank) {
return ClubMonthlyStatusQuery.of(year, month, ranking.rank(), lastMonthRank,
ranking.feedScore(), ranking.viewScore(), ranking.likeScore(), ranking.commentScore());
}
private int getLastMonthRank(Long clubId, int year, int month) {
int lastYear = month == 1 ? year - 1 : year;
int lastMonth = month == 1 ? 12 : month - 1;
List<ClubFeedRankingQuery> lastMonthRankings = getClubFeedRanking(lastYear, lastMonth);
return lastMonthRankings.stream()
.filter(ranking -> ranking.clubId().equals(clubId))
.filter(ranking -> ranking.totalScore() > 0)
.findFirst()
.map(ClubFeedRankingQuery::rank)
.orElse(0);
}
@Override
public List<ClubFeedRankingQuery> getClubFeedRankingSnapshot(int year, int month) {
List<FeedMonthlyRanking> snapshots = feedMonthlyRankingRepository
.findAllByTargetYearAndTargetMonthOrderByRankingAsc(year, month);
return snapshots.stream()
.map(this::toClubFeedRankingQueryFromSnapshot)
.toList();
}
private ClubFeedRankingQuery toClubFeedRankingQuery(int rank, Long clubId, String clubName,
long feedCount, long viewCount, long likeCount, long commentCount) {
long feedScore = feedCount * FEED_WEIGHT;
long viewScore = viewCount * VIEW_WEIGHT;
long likeScore = likeCount * LIKE_WEIGHT;
long commentScore = commentCount * COMMENT_WEIGHT;
long totalScore = feedScore + viewScore + likeScore + commentScore;
return ClubFeedRankingQuery.of(rank, clubId, clubName,
feedScore, viewScore, likeScore, commentScore, totalScore);
}
private ClubFeedRankingQuery toClubFeedRankingQueryFromSnapshot(FeedMonthlyRanking snapshot) {
return toClubFeedRankingQuery(snapshot.getRanking(), snapshot.getClubId(), snapshot.getClubName(),
snapshot.getFeedCount(), snapshot.getViewCount(),
snapshot.getLikeCount(), snapshot.getCommentCount());
}
private ClubFeedRankingQuery toClubFeedRankingQuery(int rank, MonthlyFeedRankingDto rawRanking) {
return toClubFeedRankingQuery(rank, rawRanking.getClubId(), rawRanking.getClubName(),
rawRanking.getFeedCount(), rawRanking.getViewCount(),
rawRanking.getLikeCount(), rawRanking.getCommentCount());
}
private long calculateScore(MonthlyFeedRankingDto rawRanking) {
return rawRanking.getFeedCount() * FEED_WEIGHT
+ rawRanking.getViewCount() * VIEW_WEIGHT
+ rawRanking.getLikeCount() * LIKE_WEIGHT
+ rawRanking.getCommentCount() * COMMENT_WEIGHT;
}
}