Jelajahi Sumber

MOD:节日 apollo 配置规则

sunxy 1 tahun lalu
induk
melakukan
56fe9a6791

+ 15 - 39
recommend-server-service/src/main/java/com/tzld/piaoquan/recommend/server/service/rank/processor/RankProcessorBoost.java

@@ -1,6 +1,7 @@
 package com.tzld.piaoquan.recommend.server.service.rank.processor;
 
 import com.tzld.piaoquan.recommend.server.model.Video;
+import com.tzld.piaoquan.recommend.server.util.ProbabilityCalculator;
 import org.apache.commons.collections4.CollectionUtils;
 import org.apache.commons.lang3.StringUtils;
 
@@ -22,47 +23,29 @@ public class RankProcessorBoost {
         if (CollectionUtils.isEmpty(rovList) || rulesMap == null || rulesMap.isEmpty()) {
             return;
         }
-        Map<String, String> densityRules = new HashMap<>();
-        Map<String, String> dateMap = new HashMap<>();
+        Map<String, Double> boostMap = new HashMap<>(rulesMap.size());
         for (Map.Entry<String, Map<String, String>> entry : rulesMap.entrySet()) {
             String key = entry.getKey();
-            Map<String, String> value = entry.getValue();
-            if (value.containsKey("boost")) {
-                densityRules.put(key, value.get("boost"));
-            }
-            if (value.containsKey("boost_date")) {
-                dateMap.put(key, value.get("boost_date"));
-            }
+            Map<String, String> rule = entry.getValue();
+            String boostRate = rule.get("boost");
+            String boostDate = rule.get("boost_date");
+
+            // 使用 calculateCurrentProbability 方法计算当前概率
+            double currentProbability = ProbabilityCalculator.calculateCurrentProbability(boostRate, boostDate);
+            boostMap.put(key, currentProbability);
         }
 
-        for (Map.Entry<String, String> entry : densityRules.entrySet()) {
-            String dateRange = dateMap.get(entry.getKey());
-            if (StringUtils.isNotBlank(dateRange)) {
-                String[] dateRangeArray = dateRange.split("-");
-                if (dateRangeArray.length != 2) {
-                    continue;
-                }
-                String start = dateRangeArray[0];
-                String end = dateRangeArray[1];
-                String nowHour = DateTimeFormatter.ofPattern("yyyyMMddHH").format(LocalDateTime.now());
-                if (!ifFilter(start, end, nowHour)) {
-                    continue;
-                }
+        for (Map.Entry<String, Double> entry : boostMap.entrySet()) {
+            if (entry.getValue() <= 0) {
+                continue;
             }
             try {
-                String value = entry.getValue();
-                String[] boostArray = value.split("-");
-                if (boostArray.length != 2) {
-                    continue;
-                }
-                double min = Double.parseDouble(boostArray[0]);
-                double max = Double.parseDouble(boostArray[1]);
-                // 生成min到max之间的随机数
-                double randomValue = min + (Math.random() * (max - min));
+                Double value = entry.getValue();
+                // 给每个tag的视频提权(乘 value)
                 rovList.stream().filter(video -> video.getTags().contains(entry.getKey()))
                         .forEach(video -> video.setSortScore(
                                 BigDecimal.valueOf(video.getSortScore())
-                                        .multiply(BigDecimal.valueOf(randomValue))
+                                        .multiply(BigDecimal.valueOf(value))
                                         .doubleValue()));
             } catch (Exception ignored) {
             }
@@ -71,11 +54,4 @@ public class RankProcessorBoost {
 
     }
 
-    public static boolean ifFilter(String start, String end, String dateHour) {
-        if (StringUtils.isBlank(start) || StringUtils.isBlank(end) || StringUtils.isBlank(dateHour)) {
-            return false;
-        }
-        return dateHour.compareTo(start) >= 0 && dateHour.compareTo(end) < 0;
-    }
-
 }

+ 30 - 26
recommend-server-service/src/main/java/com/tzld/piaoquan/recommend/server/service/rank/processor/RankProcessorInsert.java

@@ -2,6 +2,7 @@ package com.tzld.piaoquan.recommend.server.service.rank.processor;
 
 import com.tzld.piaoquan.recommend.server.model.Video;
 import com.tzld.piaoquan.recommend.server.service.rank.RankParam;
+import com.tzld.piaoquan.recommend.server.util.DateUtils;
 import com.tzld.piaoquan.recommend.server.util.MathUtil;
 import com.tzld.piaoquan.recommend.server.util.WeightRandom;
 import org.apache.commons.collections4.CollectionUtils;
@@ -24,10 +25,11 @@ public class RankProcessorInsert {
         if (CollectionUtils.isEmpty(rovList) || rulesMap == null || rulesMap.isEmpty()) {
             return;
         }
-        String insertRules = null, tagName = null;
+        String tagName = null, insertWeight = null;
         for (Map.Entry<String, Map<String, String>> entry : rulesMap.entrySet()) {
             Map<String, String> value = entry.getValue();
 
+            // 硬编码,南北小年逻辑
             if ("小年".equals(entry.getKey())){
                 String provinceCn = param.getProvince();
                 if (provinceCn == null){
@@ -38,20 +40,37 @@ public class RankProcessorInsert {
                 boolean ifNorth = NORTHERN_PROVINCES.contains(provinceCn);
                 Calendar calendar = Calendar.getInstance();
                 String date = new SimpleDateFormat("yyyyMMdd").format(calendar.getTime());
-                if (ifNorth && date.compareTo("20240202")>0){
+                if (ifNorth && date.compareTo("20240202") > 0) {
                     continue;
                 }
             }
 
-            if (value.containsKey("insert")) {
-                insertRules = value.get("insert");
-                tagName = entry.getKey();
+            String insertDates = value.get("insert_date");
+            String insertRules = value.get("insert");
+            if (StringUtils.isBlank(insertDates) || StringUtils.isBlank(insertRules)) {
+                continue;
+            }
+            String[] insertDateArr = insertDates.split(",");
+            String[] insertWeights = insertRules.split(";");
+            if (insertDateArr.length != insertWeights.length) {
+                continue;
+            }
+            for (int i = 0; i < insertDateArr.length; i++) {
+                String insertDate = insertDateArr[i];
+                // 判断是否在允许强插的时间范围内
+                boolean ifTimeRangeInNow = DateUtils.ifTimeRangeInNow(insertDate);
+                if (ifTimeRangeInNow) {
+                    tagName = entry.getKey();
+                    insertWeight = insertWeights[i];
+                    break;
+                }
+            }
+            // 如果已经筛选出强插的tag以及对应权重,就不再继续遍历
+            if (StringUtils.isNotBlank(tagName) && StringUtils.isNotBlank(insertWeight)) {
                 break;
             }
         }
-        if (StringUtils.isBlank(insertRules) || StringUtils.isBlank(tagName)) {
-            return;
-        }
+
         final String finalTagName = tagName;
 
         // 判断是否前几个已经有该tag的视频了
@@ -62,25 +81,10 @@ public class RankProcessorInsert {
             return;
         }
 
-        // 判断是否在允许强插的时间范围内
-        String dateRange = rulesMap.get(tagName).get("insert_date");
-        if (StringUtils.isNotBlank(dateRange)) {
-            String[] dateRangeArray = dateRange.split("-");
-            if (dateRangeArray.length != 2) {
-                return;
-            }
-            String start = dateRangeArray[0];
-            String end = dateRangeArray[1];
-            String nowHour = new SimpleDateFormat("yyyyMMddHH").format(new Date());
-            if (!ifFilter(start, end, nowHour)) {
-                return;
-            }
-        }
-
         // 获取需要插入的视频
         Video insertTagVideo = null;
         int tagVideoIndex = -1;
-        for (int i = 0; i < rovList.size(); i++) {
+        for (int i = param.getSize(); i < rovList.size(); i++) {
             if (rovList.get(i).getTags().contains(finalTagName)) {
                 insertTagVideo = rovList.get(i);
                 tagVideoIndex = i;
@@ -92,8 +96,8 @@ public class RankProcessorInsert {
         }
 
         // 获取插入的权重
-        String[] insertWeight = insertRules.split(",");
-        List<Double> insertWeightList = Arrays.stream(insertWeight)
+        String[] insertWeightArr = insertWeight.split(",");
+        List<Double> insertWeightList = Arrays.stream(insertWeightArr)
                 .map(Double::valueOf).collect(Collectors.toList());
 
         if (CollectionUtils.size(insertWeightList) != 5) {

+ 27 - 75
recommend-server-service/src/main/java/com/tzld/piaoquan/recommend/server/service/rank/processor/RankProcessorTagFilter.java

@@ -1,109 +1,61 @@
 package com.tzld.piaoquan.recommend.server.service.rank.processor;
+
 import com.tzld.piaoquan.recommend.server.model.Video;
-import org.apache.commons.lang3.tuple.Pair;
+import com.tzld.piaoquan.recommend.server.util.ProbabilityCalculator;
 
-import java.text.SimpleDateFormat;
 import java.util.*;
 public class RankProcessorTagFilter {
 
-    public static void processor(List<Video> rov, List<Video> flow, Map<String, Map<String, String>> rule) {
+    public static void processor(List<Video> rov, List<Video> flow, Map<String, Map<String, String>> rules) {
+
+        Set<String> filterTags = new HashSet<>();
+        Random random = new Random();
 
-        Map<String, String> tag2Rate = new HashMap<>();
-        Map<String, List<Pair<String, String>>> tag2Dates = new HashMap<>();
-        for (Map.Entry<String, Map<String, String>> entry : rule.entrySet()){
+        // 遍历每一个规则条目
+        for (Map.Entry<String, Map<String, String>> entry : rules.entrySet()) {
             String key = entry.getKey();
-            Map<String, String> value = entry.getValue();
-            if (value.containsKey("filter_rate")){
-                tag2Rate.put(key, value.get("filter_rate"));
-            }
-            if (value.containsKey("filter_date")){
-                List<Pair<String, String>> tmpList = new ArrayList<>();
-                for (String tmp : value.get("filter_date").split(",")){
-                    String start = tmp.split("-")[0];
-                    String end = tmp.split("-")[1];
-                    tmpList.add(Pair.of(start, end));
-                }
-                tag2Dates.put(key, tmpList);
-            }
-        }
+            Map<String, String> rule = entry.getValue();
+            String filterRate = rule.get("filter_rate");
+            String filterDate = rule.get("filter_date");
 
-        // 通过过滤概率获取本轮过滤tag集合
-        Set<String> filterTags = new HashSet<>();
-        for (Map.Entry<String, String> entry : tag2Rate.entrySet()) {
-            try {
-                String key = entry.getKey();
-                String value = entry.getValue();
-                String[] boostArray = value.split("-");
-                if (boostArray.length != 2) {
-                    continue;
-                }
-                double min = Double.parseDouble(boostArray[0]);
-                double max = Double.parseDouble(boostArray[1]);
-                // 生成min到max之间的随机数
-                double randomValue = min + (Math.random() * (max - min));
-                if (Math.random() <= randomValue) {
+            // 使用 calculateCurrentProbability 方法计算当前概率
+            double currentProbability = ProbabilityCalculator.calculateCurrentProbability(filterRate, filterDate);
+
+            // 生成随机浮点数并与 filter_rate 比较
+            if (currentProbability > 0) { // 确保有有效的概率
+                double randomValue = random.nextDouble();
+                if (randomValue < currentProbability) {
                     filterTags.add(key);
                 }
-            } catch (Exception ignored) {
             }
         }
 
-        // 获取系统时间
-        Calendar calendar = Calendar.getInstance();
-        String dateHour = new SimpleDateFormat("yyyyMMddHH").format(calendar.getTime());
+        if (filterTags.isEmpty()) {
+            return;
+        }
 
         //执行过滤
         Iterator<Video> iterator = rov.iterator();
         while (iterator.hasNext()) {
             Video video = iterator.next();
             List<String> tags = video.getTags();
-            boolean filter = false;
-            for (String tag : tags){
-                if (!filterTags.contains(tag)){
-                    continue;
-                }
-                boolean flag = ifFiter(tag2Dates, tag, dateHour);
-                if (flag){
-                    filter = true;
-                    break;
+            for (String tag : tags) {
+                if (filterTags.contains(tag)) {
+                    iterator.remove();
                 }
             }
-            if (filter){
-                iterator.remove();
-            }
         }
 
         iterator = flow.iterator();
         while (iterator.hasNext()) {
             Video video = iterator.next();
             List<String> tags = video.getTags();
-            boolean filter = false;
-            for (String tag : tags){
-                if (!filterTags.contains(tag)){
-                    continue;
+            for (String tag : tags) {
+                if (filterTags.contains(tag)) {
+                    iterator.remove();
                 }
-                boolean flag = ifFiter(tag2Dates, tag, dateHour);
-                if (flag){
-                    filter = true;
-                    break;
-                }
-            }
-            if (filter){
-                iterator.remove();
-            }
-        }
-    }
-
-    public static boolean ifFiter(Map<String, List<Pair<String, String>>> tag2Dates, String tag, String dateHour){
-        if (!tag2Dates.containsKey(tag) || tag2Dates.get(tag).isEmpty()){
-            return false;
-        }
-        for (Pair<String, String> d: tag2Dates.get(tag)){
-            if (dateHour.compareTo(d.getLeft()) >= 0 && dateHour.compareTo(d.getRight()) < 0){
-                return true;
             }
         }
-        return false;
     }
 
 }

+ 3 - 1
recommend-server-service/src/main/java/com/tzld/piaoquan/recommend/server/service/rank/strategy/RankStrategy4Density.java

@@ -29,8 +29,10 @@ import java.util.stream.Collectors;
 @Service
 @Slf4j
 public class RankStrategy4Density extends RankService {
-    @ApolloJsonValue("${RankStrategy4DensityFilter:}")
+    @ApolloJsonValue("${RankStrategy4DensityFilterV2:}")
     private Map<String,Map<String, Map<String, String>>> filterRules = new HashMap<>();
+
+
     @Override
     public RankResult mergeAndSort(RankParam param, List<Video> rovVideos, List<Video> flowVideos) {
 

+ 28 - 2
recommend-server-service/src/main/java/com/tzld/piaoquan/recommend/server/util/DateUtils.java

@@ -1,6 +1,8 @@
 package com.tzld.piaoquan.recommend.server.util;
 
 import java.text.SimpleDateFormat;
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
 import java.util.Calendar;
 import java.util.Date;
 
@@ -28,10 +30,34 @@ public final class DateUtils {
         return dateFormat.format(previousDate);
     }
 
-    public static void main(String[] args){
+
+    public static boolean ifTimeRangeInNow(String timeRange) {
+        try {
+
+            String[] split = timeRange.split("-");
+            if (split.length != 2) {
+                return false;
+            }
+            String startTime = split[0];
+            String endTime = split[1];
+            if (startTime.length() != 10 || endTime.length() != 10) {
+                return false;
+            }
+            LocalDateTime now = LocalDateTime.now();
+            LocalDateTime start = LocalDateTime.parse(startTime, DateTimeFormatter.ofPattern("yyyyMMddHH"));
+            LocalDateTime end = LocalDateTime.parse(endTime, DateTimeFormatter.ofPattern("yyyyMMddHH"));
+            return now.equals(start) || (now.isAfter(start) && now.isBefore(end));
+        } catch (Exception e) {
+//            e.printStackTrace();
+            return false;
+        }
+    }
+
+
+    public static void main(String[] args) {
         Calendar calendar = Calendar.getInstance();
 
-        System.out.println((calendar.get(Calendar.DAY_OF_WEEK) + 6) % 7 );
+        System.out.println((calendar.get(Calendar.DAY_OF_WEEK) + 6) % 7);
         System.out.println(new SimpleDateFormat("yyyyMMdd").format(calendar.getTime()));
         System.out.println(new SimpleDateFormat("HH").format(calendar.getTime()));
 

+ 79 - 0
recommend-server-service/src/main/java/com/tzld/piaoquan/recommend/server/util/ProbabilityCalculator.java

@@ -0,0 +1,79 @@
+package com.tzld.piaoquan.recommend.server.util;
+
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author sunxy
+ */
+public class ProbabilityCalculator {
+
+    static class DateRange {
+        LocalDateTime start;
+        LocalDateTime end;
+
+        DateRange(LocalDateTime start, LocalDateTime end) {
+            this.start = start;
+            this.end = end;
+        }
+    }
+
+    static class RateRange {
+        double start;
+        double end;
+
+        RateRange(double start, double end) {
+            this.start = start;
+            this.end = end;
+        }
+    }
+
+    public static double calculateCurrentProbability(String filterRate, String filterDate) {
+        // 解析日期区间
+        String[] dateRanges = filterDate.split(",");
+        List<DateRange> parsedDateRanges = new ArrayList<>();
+        for (String range : dateRanges) {
+            String[] dates = range.split("-");
+            LocalDateTime start = LocalDateTime.parse(dates[0], DateTimeFormatter.ofPattern("yyyyMMddHH"));
+            LocalDateTime end = LocalDateTime.parse(dates[1], DateTimeFormatter.ofPattern("yyyyMMddHH"));
+            parsedDateRanges.add(new DateRange(start, end));
+        }
+
+        // 解析概率区间
+        String[] rateRanges = filterRate.split(",");
+        List<RateRange> parsedRateRanges = new ArrayList<>();
+        for (String range : rateRanges) {
+            String[] rates = range.split("-");
+            double start = Double.parseDouble(rates[0]);
+            double end = Double.parseDouble(rates[1]);
+            parsedRateRanges.add(new RateRange(start, end));
+        }
+
+        // 获取当前时间
+        LocalDateTime now = LocalDateTime.now();
+
+        // 确定当前时间属于哪个日期区间,并计算概率
+        for (int i = 0; i < parsedDateRanges.size(); i++) {
+            DateRange dateRange = parsedDateRanges.get(i);
+            if (now.isEqual(dateRange.start) || (now.isAfter(dateRange.start) && now.isBefore(dateRange.end))) {
+                RateRange rateRange = parsedRateRanges.get(i);
+                long totalMinutes = dateRange.end.atZone(java.time.ZoneId.systemDefault()).toEpochSecond() - dateRange.start.atZone(java.time.ZoneId.systemDefault()).toEpochSecond();
+                long elapsedMinutes = now.atZone(java.time.ZoneId.systemDefault()).toEpochSecond() - dateRange.start.atZone(java.time.ZoneId.systemDefault()).toEpochSecond();
+                double elapsedRatio = (double) elapsedMinutes / totalMinutes;
+                return rateRange.start + ((rateRange.end - rateRange.start) * elapsedRatio);
+            }
+        }
+
+        // 如果当前时间不在任何配置的日期区间内,返回-1表示无效
+        return -1;
+    }
+
+    public static void main(String[] args) {
+        double probability = calculateCurrentProbability("0.8-1.0,0.5-0.6", "2024020312-2024020400," +
+                "2024020400-2024020702");
+        System.out.println("Current Probability: " + probability);
+    }
+
+}