|  | @@ -7,6 +7,7 @@ import com.tzld.piaoquan.recommend.server.service.filter.FilterParam;
 | 
	
		
			
				|  |  |  import com.tzld.piaoquan.recommend.server.service.filter.FilterStrategy;
 | 
	
		
			
				|  |  |  import lombok.extern.slf4j.Slf4j;
 | 
	
		
			
				|  |  |  import org.apache.commons.collections.CollectionUtils;
 | 
	
		
			
				|  |  | +import org.apache.commons.collections.MapUtils;
 | 
	
		
			
				|  |  |  import org.apache.commons.lang3.StringUtils;
 | 
	
		
			
				|  |  |  import org.springframework.beans.factory.annotation.Autowired;
 | 
	
		
			
				|  |  |  import org.springframework.beans.factory.annotation.Qualifier;
 | 
	
	
		
			
				|  | @@ -56,7 +57,7 @@ public class VovLowerStrategy implements FilterStrategy {
 | 
	
		
			
				|  |  |          for (int i = 0; i < videoIds.size(); i++) {
 | 
	
		
			
				|  |  |              Long videoId = videoIds.get(i);
 | 
	
		
			
				|  |  |              String vovInfo = vovInfos.get(i);
 | 
	
		
			
				|  |  | -            if (isFilter(vovInfo)) {
 | 
	
		
			
				|  |  | +            if (isShouldFilter(vovInfo)) {
 | 
	
		
			
				|  |  |                  removeIds.add(videoId);
 | 
	
		
			
				|  |  |                  continue;
 | 
	
		
			
				|  |  |              }
 | 
	
	
		
			
				|  | @@ -69,7 +70,8 @@ public class VovLowerStrategy implements FilterStrategy {
 | 
	
		
			
				|  |  |          return result;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    private boolean isFilter(String vovInfo) {
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    private boolean isShouldFilter(String vovInfo) {
 | 
	
		
			
				|  |  |          try {
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |              if (StringUtils.isEmpty(vovInfo)) {
 | 
	
	
		
			
				|  | @@ -78,37 +80,59 @@ public class VovLowerStrategy implements FilterStrategy {
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |              Map<String, Double> vovInfoMap = JSON.parseObject(vovInfo, new TypeReference<Map<String, Double>>() {
 | 
	
		
			
				|  |  |              });
 | 
	
		
			
				|  |  | +            if (MapUtils.isEmpty(vovInfoMap)) {
 | 
	
		
			
				|  |  | +                return false;
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -            // 获取阈值
 | 
	
		
			
				|  |  | -            double t0ViewPvCondition = vovFilterCondition.getOrDefault("t_0_view_pv", 1000d);
 | 
	
		
			
				|  |  | -            double t1ViewPvCondition = vovFilterCondition.getOrDefault("t_1_view_pv", 1000d);
 | 
	
		
			
				|  |  | -            double t2ViewPvCondition = vovFilterCondition.getOrDefault("t_2_view_pv", -1d);
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -            double t0VovCondition = vovFilterCondition.getOrDefault("t_0_vov", 0.34d);
 | 
	
		
			
				|  |  | -            double t1VovCondition = vovFilterCondition.getOrDefault("t_1_vov", 0.54d);
 | 
	
		
			
				|  |  | -            double t2VovCondition = vovFilterCondition.getOrDefault("t_2_vov", 100000d);
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -            // 获取视频VOV表现
 | 
	
		
			
				|  |  | -            double t0TodayDistViewPv = vovInfoMap.getOrDefault("t_0_today_dist_view_pv", 0d);
 | 
	
		
			
				|  |  | -            double t1TodayDistViewPv = vovInfoMap.getOrDefault("t_1_today_dist_view_pv", 0d);
 | 
	
		
			
				|  |  | -            double t2TodayDistViewPv = vovInfoMap.getOrDefault("t_2_today_dist_view_pv", 0d);
 | 
	
		
			
				|  |  | +            if (isNewVideo(vovInfoMap) || isUptrendVideo(vovInfoMap)) {
 | 
	
		
			
				|  |  | +                return false;
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -            double t0AllVov = vovInfoMap.getOrDefault("t_0_all_vov", 0d);
 | 
	
		
			
				|  |  | -            double t1AllVov = vovInfoMap.getOrDefault("t_1_all_vov", 0d);
 | 
	
		
			
				|  |  | -            double t2AllVov = vovInfoMap.getOrDefault("t_2_all_vov", 0d);
 | 
	
		
			
				|  |  | +            // 预估VOV
 | 
	
		
			
				|  |  | +            double t1Vov0 = vovInfoMap.getOrDefault("1_vov0", 0d);
 | 
	
		
			
				|  |  | +            double t2Vov0 = vovInfoMap.getOrDefault("2_vov0", 0d);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -            // 判断曝光是否置信
 | 
	
		
			
				|  |  | -            boolean viewResult = (t0TodayDistViewPv > t0ViewPvCondition) && (t1TodayDistViewPv > t1ViewPvCondition) && (t2TodayDistViewPv > t2ViewPvCondition);
 | 
	
		
			
				|  |  | +            double estimated2Vov0Alpha = vovFilterCondition.getOrDefault("estimated_2_vov_0_alpha", 0.2d);
 | 
	
		
			
				|  |  | +            double estimated1Vov0Alpha = vovFilterCondition.getOrDefault("estimated_1_vov_0_alpha", 0.8d);
 | 
	
		
			
				|  |  | +            double estimatedVovThreshold = vovFilterCondition.getOrDefault("estimated_vov_threshold", 0.19d);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -            // 判断VOV是否小于阈值
 | 
	
		
			
				|  |  | -            boolean vovResult = (t0AllVov < t0VovCondition) && (t1AllVov < t1VovCondition) && (t2AllVov < t2VovCondition);
 | 
	
		
			
				|  |  | +            double estimatedVov = t1Vov0;
 | 
	
		
			
				|  |  | +            if (t2Vov0 != 0) {
 | 
	
		
			
				|  |  | +                estimatedVov = estimated2Vov0Alpha * t2Vov0 + estimated1Vov0Alpha * t1Vov0;
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -            // 曝光置信 & VOV小于阈值 & VOV全不为0
 | 
	
		
			
				|  |  | -            return viewResult && vovResult;
 | 
	
		
			
				|  |  | +            return estimatedVov < estimatedVovThreshold;
 | 
	
		
			
				|  |  |          } catch (Exception e) {
 | 
	
		
			
				|  |  |              log.info("VOV过滤 -- 异常: ", e);
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |          return false;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +    // 三天曝光都小于阈值的 认定为新视频
 | 
	
		
			
				|  |  | +    private boolean isNewVideo(Map<String, Double> vovInfoMap) {
 | 
	
		
			
				|  |  | +        double t1ViewPvCondition = vovFilterCondition.getOrDefault("t_1_view_pv", 50d);
 | 
	
		
			
				|  |  | +        double t2ViewPvCondition = vovFilterCondition.getOrDefault("t_2_view_pv", 50d);
 | 
	
		
			
				|  |  | +        double t3ViewPvCondition = vovFilterCondition.getOrDefault("t_3_view_pv", 50d);
 | 
	
		
			
				|  |  | +        double t1ViewPv = vovInfoMap.getOrDefault("1_vov0_分母", 0d);
 | 
	
		
			
				|  |  | +        double t2ViewPv = vovInfoMap.getOrDefault("2_vov0_分母", 0d);
 | 
	
		
			
				|  |  | +        double t3ViewPv = vovInfoMap.getOrDefault("3_vov0_分母", 0d);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        return t1ViewPv < t1ViewPvCondition && t2ViewPv < t2ViewPvCondition && t3ViewPv < t3ViewPvCondition;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // 最近两天的vov满足并值,且昨天的vov-前天的vov 达到一定的涨幅认定为上升趋势视频
 | 
	
		
			
				|  |  | +    private boolean isUptrendVideo(Map<String, Double> vovInfoMap) {
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        double t1VovCondition = vovFilterCondition.getOrDefault("t_1_vov", 0.2d);
 | 
	
		
			
				|  |  | +        double t2VovCondition = vovFilterCondition.getOrDefault("t_2_vov", 0d);
 | 
	
		
			
				|  |  | +        double vovDiff = vovFilterCondition.getOrDefault("12_vov_diff", 0.1);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        double t1Vov0 = vovInfoMap.getOrDefault("1_vov0", 0d);
 | 
	
		
			
				|  |  | +        double t2Vov0 = vovInfoMap.getOrDefault("2_vov0", 0d);
 | 
	
		
			
				|  |  | +        double t12VovDiff = t1Vov0 - t2Vov0;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        return t2Vov0 > t2VovCondition && t1Vov0 > t1VovCondition && t12VovDiff > vovDiff;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  }
 |