h-lab/src/main/java/com/hlab/yanalyst/domain/channel/DiscoveryRanker.java
2026-06-26 10:41:52 +09:00

46 lines
1.9 KiB
Java

package com.hlab.yanalyst.domain.channel;
import com.hlab.yanalyst.web.dto.YoutubeSearchResultDto;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
/** 검색된 Shorts 목록 → 채널별 최고 배율 후보 집계·필터·정렬(순수 로직). */
public final class DiscoveryRanker {
private DiscoveryRanker() {}
public record Candidate(String channelId, String channelTitle, String thumbnailUrl, Long subscriberCount,
String topVideoId, String topVideoTitle, Long topVideoViewCount,
double ratio, String region) {}
public static List<Candidate> rank(List<YoutubeSearchResultDto> items, long maxSubscribers,
double minRatio, Set<String> excludeChannelIds) {
Map<String, Candidate> best = new LinkedHashMap<>();
for (YoutubeSearchResultDto it : items) {
String ch = it.getChannelId();
Long subs = it.getSubscriberCount();
Long views = it.getViewCount();
if (ch == null || subs == null || subs <= 0 || views == null) continue;
if (excludeChannelIds.contains(ch)) continue;
if (subs > maxSubscribers) continue;
double ratio = (double) views / subs;
if (ratio < minRatio) continue;
Candidate prev = best.get(ch);
if (prev == null || ratio > prev.ratio()) {
best.put(ch, new Candidate(ch, it.getChannelTitle(), it.getThumbnailUrl(), subs,
it.getVideoId(), it.getTitle(), views, ratio, it.getChannelCountry()));
}
}
List<Candidate> out = new ArrayList<>(best.values());
out.sort(Comparator.comparingDouble(Candidate::ratio).reversed());
return out;
}
}