|  | @@ -0,0 +1,166 @@
 | 
	
		
			
				|  |  | +package com.tzld.longarticle.recommend.server.service.rank.strategy;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +import com.tzld.longarticle.recommend.server.common.enums.ArticleTypeEnum;
 | 
	
		
			
				|  |  | +import com.tzld.longarticle.recommend.server.common.enums.RankStrategyEnum;
 | 
	
		
			
				|  |  | +import com.tzld.longarticle.recommend.server.model.dto.Content;
 | 
	
		
			
				|  |  | +import com.tzld.longarticle.recommend.server.model.entity.crawler.Article;
 | 
	
		
			
				|  |  | +import com.tzld.longarticle.recommend.server.repository.crawler.ArticleRepository;
 | 
	
		
			
				|  |  | +import com.tzld.longarticle.recommend.server.service.AccountContentPoolConfigService;
 | 
	
		
			
				|  |  | +import com.tzld.longarticle.recommend.server.service.StrategyIndexScoreWeightService;
 | 
	
		
			
				|  |  | +import com.tzld.longarticle.recommend.server.service.rank.*;
 | 
	
		
			
				|  |  | +import com.tzld.longarticle.recommend.server.service.score.AccountIndexReplacePoolConfig;
 | 
	
		
			
				|  |  | +import com.tzld.longarticle.recommend.server.service.score.ScoreResult;
 | 
	
		
			
				|  |  | +import com.tzld.longarticle.recommend.server.service.score.ScoreService;
 | 
	
		
			
				|  |  | +import com.tzld.longarticle.recommend.server.service.score.strategy.*;
 | 
	
		
			
				|  |  | +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.*;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +/**
 | 
	
		
			
				|  |  | + * @author dyp
 | 
	
		
			
				|  |  | + */
 | 
	
		
			
				|  |  | +@Service
 | 
	
		
			
				|  |  | +@Slf4j
 | 
	
		
			
				|  |  | +public class RankV14Strategy 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;
 | 
	
		
			
				|  |  | +            if (contentPools[0].equals(item.getContent().getContentPoolType())) {
 | 
	
		
			
				|  |  | +                double similarityScore = Math.pow(item.getScore(SimilarityStrategy.class.getSimpleName()),
 | 
	
		
			
				|  |  | +                        weightService.getWeight(param.getStrategy(), 1,
 | 
	
		
			
				|  |  | +                                SimilarityStrategy.class.getSimpleName()));
 | 
	
		
			
				|  |  | +                score = item.getScore(HisFissionDeWeightAvgReadSumRateStrategy.class.getSimpleName())
 | 
	
		
			
				|  |  | +                        * weightService.getWeight(param.getStrategy(), 1,
 | 
	
		
			
				|  |  | +                        HisFissionDeWeightAvgReadSumRateStrategy.class.getSimpleName());
 | 
	
		
			
				|  |  | +                if (item.getScore(PublishTimesStrategy.class.getSimpleName()) >= 0) {
 | 
	
		
			
				|  |  | +                    score += item.getScore(ViewCountRateStrategy.class.getSimpleName())
 | 
	
		
			
				|  |  | +                            * weightService.getWeight(param.getStrategy(), 1,
 | 
	
		
			
				|  |  | +                            ViewCountRateStrategy.class.getSimpleName());
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +                score = score * similarityScore;
 | 
	
		
			
				|  |  | +            } else if (contentPools[1].equals(item.getContent().getContentPoolType())) {
 | 
	
		
			
				|  |  | +                score = (item.getScore(SimilarityStrategy.class.getSimpleName())
 | 
	
		
			
				|  |  | +                        * weightService.getWeight(param.getStrategy(), 2,
 | 
	
		
			
				|  |  | +                        SimilarityStrategy.class.getSimpleName()))
 | 
	
		
			
				|  |  | +                        + item.getScore(CategoryStrategy.class.getSimpleName())
 | 
	
		
			
				|  |  | +                        + item.getScore(FlowCtlDecreaseStrategy.class.getSimpleName());
 | 
	
		
			
				|  |  | +                if (item.getScore(PublishTimesStrategy.class.getSimpleName()) >= 0) {
 | 
	
		
			
				|  |  | +                    score += item.getScore(ViewCountRateStrategy.class.getSimpleName())
 | 
	
		
			
				|  |  | +                            * weightService.getWeight(param.getStrategy(), 2,
 | 
	
		
			
				|  |  | +                            ViewCountRateStrategy.class.getSimpleName());
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +            } else {
 | 
	
		
			
				|  |  | +                score = (item.getScore(SimilarityStrategy.class.getSimpleName())
 | 
	
		
			
				|  |  | +                        * weightService.getWeight(param.getStrategy(), 3,
 | 
	
		
			
				|  |  | +                        SimilarityStrategy.class.getSimpleName()))
 | 
	
		
			
				|  |  | +                        + item.getScore(CategoryStrategy.class.getSimpleName())
 | 
	
		
			
				|  |  | +                        + (item.getScore(AccountPreDistributeStrategy.class.getSimpleName())
 | 
	
		
			
				|  |  | +                        * weightService.getWeight(param.getStrategy(), 3,
 | 
	
		
			
				|  |  | +                        AccountPreDistributeStrategy.class.getSimpleName()))
 | 
	
		
			
				|  |  | +                        + item.getScore(PublishTimesStrategy.class.getSimpleName())
 | 
	
		
			
				|  |  | +                        + item.getScore(FlowCtlDecreaseStrategy.class.getSimpleName());
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +            c.setScore(score);
 | 
	
		
			
				|  |  | +            c.setHisPublishArticleList(null);
 | 
	
		
			
				|  |  | +            item.setScore(score);
 | 
	
		
			
				|  |  | +            return item;
 | 
	
		
			
				|  |  | +        });
 | 
	
		
			
				|  |  | +        // 相似度评分为0 报警返回
 | 
	
		
			
				|  |  | +        List<Article> hisPublishFirstArticleList = articleRepository.getByGhIdAndItemIndexAndTypeEqualsAndStatusEquals(
 | 
	
		
			
				|  |  | +                param.getGhId(), 1, ArticleTypeEnum.QUNFA.getVal(), 1);
 | 
	
		
			
				|  |  | +        if (RankStrategy.SimilarityScoreZero(items, param, hisPublishFirstArticleList)) {
 | 
	
		
			
				|  |  | +            return new RankResult(result);
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        // 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.ArticleRankV14.getStrategy(), param.getAccountName(), pool1);
 | 
	
		
			
				|  |  | +        if (CollectionUtils.isNotEmpty(pool1)) {
 | 
	
		
			
				|  |  | +            result.add(pool1.get(0));
 | 
	
		
			
				|  |  | +        } 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(), 5));
 | 
	
		
			
				|  |  | +            int j = RandomUtils.nextInt(0, Math.min(pool2.size(), 5));
 | 
	
		
			
				|  |  | +            result.add(pool2.get(i));
 | 
	
		
			
				|  |  | +            // 替补 头条内容不足使用次条内容
 | 
	
		
			
				|  |  | +            if (result.size() == 1 && pool2.size() > 1) {
 | 
	
		
			
				|  |  | +                while (i == j && pool2.size() > 1) {
 | 
	
		
			
				|  |  | +                    j = RandomUtils.nextInt(0, Math.min(pool2.size(), 5));
 | 
	
		
			
				|  |  | +                    if (i != j) {
 | 
	
		
			
				|  |  | +                        publishPool[0] = contentPools[1];
 | 
	
		
			
				|  |  | +                        result.add(pool2.get(1));
 | 
	
		
			
				|  |  | +                        break;
 | 
	
		
			
				|  |  | +                    }
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +        } 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();
 | 
	
		
			
				|  |  | +                    result.add(pool2Replace.get(0));
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        // 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);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +}
 |