|
@@ -0,0 +1,124 @@
|
|
|
+package com.tzld.longarticle.recommend.server.service.recommend.rank.strategy;
|
|
|
+
|
|
|
+import com.tzld.longarticle.recommend.server.common.enums.recommend.RankStrategyEnum;
|
|
|
+import com.tzld.longarticle.recommend.server.common.enums.recommend.ScoreStrategyEnum;
|
|
|
+import com.tzld.longarticle.recommend.server.model.dto.Content;
|
|
|
+import com.tzld.longarticle.recommend.server.repository.crawler.ArticleRepository;
|
|
|
+import com.tzld.longarticle.recommend.server.service.recommend.config.AccountContentPoolConfigService;
|
|
|
+import com.tzld.longarticle.recommend.server.service.recommend.config.StrategyIndexScoreWeightService;
|
|
|
+import com.tzld.longarticle.recommend.server.service.recommend.rank.*;
|
|
|
+import com.tzld.longarticle.recommend.server.service.recommend.score.AccountIndexReplacePoolConfig;
|
|
|
+import com.tzld.longarticle.recommend.server.service.recommend.score.ScoreResult;
|
|
|
+import com.tzld.longarticle.recommend.server.service.recommend.score.ScoreService;
|
|
|
+import com.tzld.longarticle.recommend.server.util.CommonCollectionUtils;
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
+import org.apache.commons.collections4.CollectionUtils;
|
|
|
+import org.apache.commons.lang3.RandomUtils;
|
|
|
+import org.springframework.beans.factory.annotation.Autowired;
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
+
|
|
|
+import java.util.*;
|
|
|
+
|
|
|
+@Service
|
|
|
+@Slf4j
|
|
|
+public class HisJumpRankStrategy implements RankStrategy {
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private ScoreService scoreService;
|
|
|
+ @Autowired
|
|
|
+ private AccountContentPoolConfigService accountContentPoolConfigService;
|
|
|
+ @Autowired
|
|
|
+ private ArticleRepository articleRepository;
|
|
|
+ @Autowired
|
|
|
+ private StrategyIndexScoreWeightService weightService;
|
|
|
+
|
|
|
+ public RankResult rank(RankParam param) {
|
|
|
+ List<Content> result = new ArrayList<>();
|
|
|
+
|
|
|
+ ScoreResult scoreResult = scoreService.score(RankStrategy.convertToScoreParam(param));
|
|
|
+
|
|
|
+ Map<String, Map<String, Double>> scoreMap = scoreResult.getScoreMap();
|
|
|
+ String[] contentPools = accountContentPoolConfigService.getContentPools(param.getAccountName());
|
|
|
+ Map<Integer, AccountIndexReplacePoolConfig> indexReplacePoolConfigMap = accountContentPoolConfigService.getContentReplacePools(param.getAccountName());
|
|
|
+
|
|
|
+ List<RankItem> items = CommonCollectionUtils.toList(param.getContents(), c -> {
|
|
|
+ RankItem item = new RankItem();
|
|
|
+ item.setContent(c);
|
|
|
+ c.setScoreMap(scoreMap.get(c.getId()));
|
|
|
+ item.setScoreMap(scoreMap.get(c.getId()));
|
|
|
+ double score;
|
|
|
+ int index = weightService.getIndex(item.getContent().getContentPoolType(), contentPools);
|
|
|
+ if (contentPools[0].equals(item.getContent().getContentPoolType())
|
|
|
+ || contentPools[1].equals(item.getContent().getContentPoolType())) {
|
|
|
+ score = item.getScore(ScoreStrategyEnum.FLOW_CTL_DECREASE.value())
|
|
|
+ + item.getScore(ScoreStrategyEnum.CRAWLER_DAYS_DECREASE_STRATEGY.value());
|
|
|
+ if (item.getScore(ScoreStrategyEnum.PUBLISH_TIMES.value()) >= 0) {
|
|
|
+ score += item.getScore(ScoreStrategyEnum.VIEW_COUNT_RATE.value())
|
|
|
+ * weightService.getWeight(param.getStrategy(), param.getGhId(), index,
|
|
|
+ ScoreStrategyEnum.VIEW_COUNT_RATE.value());
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ score = item.getScore(ScoreStrategyEnum.ACCOUNT_PRE_DISTRIBUTE.value())
|
|
|
+ + item.getScore(ScoreStrategyEnum.PUBLISH_TIMES.value())
|
|
|
+ + item.getScore(ScoreStrategyEnum.CRAWLER_DAYS_DECREASE_STRATEGY.value())
|
|
|
+ + item.getScore(ScoreStrategyEnum.FLOW_CTL_DECREASE.value());
|
|
|
+ }
|
|
|
+ c.setScore(score);
|
|
|
+ item.setScore(score);
|
|
|
+ return item;
|
|
|
+ });
|
|
|
+
|
|
|
+ // 1 排序
|
|
|
+ Collections.sort(items, (o1, o2) -> -Double.compare(o1.getScore(), o2.getScore()));
|
|
|
+ // 2 相似去重
|
|
|
+ List<Content> contents = CommonCollectionUtils.toList(items, RankItem::getContent);
|
|
|
+
|
|
|
+ // 3 文章按照内容池分组
|
|
|
+ Map<String, List<Content>> contentMap = new HashMap<>();
|
|
|
+ for (Content c : contents) {
|
|
|
+ List<Content> data = contentMap.computeIfAbsent(c.getContentPoolType(), k -> new ArrayList<>());
|
|
|
+ data.add(c);
|
|
|
+ }
|
|
|
+ // 4 选文章
|
|
|
+ String[] publishPool = Arrays.copyOf(contentPools, contentPools.length);
|
|
|
+
|
|
|
+ // 头
|
|
|
+ List<Content> pool1 = contentMap.get(contentPools[0]);
|
|
|
+ RankService.printSortLog(RankStrategyEnum.HIS_JUMP_STRATEGY.getStrategy(), param.getAccountName(), pool1);
|
|
|
+ if (CollectionUtils.isNotEmpty(pool1)) {
|
|
|
+ int i = RandomUtils.nextInt(0, Math.min(pool1.size(), 20));
|
|
|
+ result.add(pool1.get(i));
|
|
|
+ } else {
|
|
|
+ RankStrategy.sendFeishuFirstPoolEmpty(param, contentPools[0]);
|
|
|
+ return new RankResult(result);
|
|
|
+ }
|
|
|
+ // 次
|
|
|
+ List<Content> pool2 = contentMap.get(contentPools[1]);
|
|
|
+ if (CollectionUtils.isNotEmpty(pool2)) {
|
|
|
+ int i = RandomUtils.nextInt(0, Math.min(pool2.size(), 20));
|
|
|
+ result.add(pool2.get(i));
|
|
|
+ } else {
|
|
|
+ // 替补 根据设置替补内容池查找内容尽心替补
|
|
|
+ AccountIndexReplacePoolConfig replacePoolConfig = indexReplacePoolConfigMap.get(2);
|
|
|
+ if (Objects.nonNull(replacePoolConfig)) {
|
|
|
+ List<Content> pool2Replace = contentMap.get(replacePoolConfig.getContentPool());
|
|
|
+ if (CollectionUtils.isNotEmpty(pool2Replace)) {
|
|
|
+ publishPool[1] = replacePoolConfig.getContentPool();
|
|
|
+ int i = RandomUtils.nextInt(0, Math.min(pool2Replace.size(), 20));
|
|
|
+ result.add(pool2Replace.get(i));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 3-8
|
|
|
+ List<Content> pool = contentMap.get(contentPools[2]);
|
|
|
+ if (CollectionUtils.isNotEmpty(pool) && param.getSize() > result.size()) {
|
|
|
+ result.addAll(pool.subList(0, Math.min(pool.size(), param.getSize() - result.size())));
|
|
|
+ }
|
|
|
+
|
|
|
+ RankStrategy.deduplication(result, contentMap, publishPool);
|
|
|
+
|
|
|
+ return new RankResult(result);
|
|
|
+ }
|
|
|
+
|
|
|
+}
|