|  | @@ -1,10 +1,20 @@
 | 
	
		
			
				|  |  |  package com.tzld.piaoquan.recommend.server.service;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +import com.alibaba.fastjson.JSONObject;
 | 
	
		
			
				|  |  | +import com.ctrip.framework.apollo.spring.annotation.ApolloJsonValue;
 | 
	
		
			
				|  |  | +import com.google.common.cache.CacheBuilder;
 | 
	
		
			
				|  |  | +import com.google.common.cache.CacheLoader;
 | 
	
		
			
				|  |  | +import com.google.common.cache.LoadingCache;
 | 
	
		
			
				|  |  |  import com.tzld.piaoquan.recommend.server.gen.common.Result;
 | 
	
		
			
				|  |  |  import com.tzld.piaoquan.recommend.server.gen.recommend.HomepageRecommendRequest;
 | 
	
		
			
				|  |  |  import com.tzld.piaoquan.recommend.server.gen.recommend.HomepageRecommendResponse;
 | 
	
		
			
				|  |  |  import com.tzld.piaoquan.recommend.server.gen.recommend.Video;
 | 
	
		
			
				|  |  |  import com.tzld.piaoquan.recommend.server.model.param.HomepageRecommendParam;
 | 
	
		
			
				|  |  | +import com.tzld.piaoquan.recommend.server.util.DateUtils;
 | 
	
		
			
				|  |  | +import com.tzld.piaoquan.recommend.server.util.JSONUtils;
 | 
	
		
			
				|  |  | +import lombok.extern.slf4j.Slf4j;
 | 
	
		
			
				|  |  | +import org.apache.commons.collections4.MapUtils;
 | 
	
		
			
				|  |  | +import org.apache.commons.lang3.RandomUtils;
 | 
	
		
			
				|  |  |  import org.apache.commons.lang3.StringUtils;
 | 
	
		
			
				|  |  |  import org.springframework.beans.factory.annotation.Autowired;
 | 
	
		
			
				|  |  |  import org.springframework.data.redis.core.RedisTemplate;
 | 
	
	
		
			
				|  | @@ -16,22 +26,46 @@ import javax.annotation.PostConstruct;
 | 
	
		
			
				|  |  |  import java.text.SimpleDateFormat;
 | 
	
		
			
				|  |  |  import java.util.*;
 | 
	
		
			
				|  |  |  import java.util.concurrent.TimeUnit;
 | 
	
		
			
				|  |  | +import java.util.concurrent.atomic.AtomicInteger;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  /**
 | 
	
		
			
				|  |  |   * @author dyp
 | 
	
		
			
				|  |  |   */
 | 
	
		
			
				|  |  |  @Service
 | 
	
		
			
				|  |  | +@Slf4j
 | 
	
		
			
				|  |  |  public class RecommendService {
 | 
	
		
			
				|  |  | -    @Autowired
 | 
	
		
			
				|  |  | -    private MidService midService;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      @Autowired
 | 
	
		
			
				|  |  |      private RedisTemplate<String, String> redisTemplate;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    private String abExpCode;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      private Map<String, String> ab_initial_config_map = new HashMap<>();
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +    @ApolloJsonValue("ab_exp_code")
 | 
	
		
			
				|  |  | +    private Map<String, Map<String, String>> abExpCodeMap = new HashMap<>();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    @ApolloJsonValue("app_ab_code")
 | 
	
		
			
				|  |  | +    private Map<String, Map<String, Map<String, String>>> appAbCodeMap = new HashMap<>();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    private int[] flowPoolIdList = {7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // {"control_group": [], "experimental_flow_set_level": [10, 11, 12, 13, 14, 15, 16, 17], "experimental_flow_set_level_score": [9, 18]}
 | 
	
		
			
				|  |  | +    private LoadingCache<String, Map<String, List<Integer>>> flowPoolConfigCache = CacheBuilder.newBuilder()
 | 
	
		
			
				|  |  | +            .maximumSize(10)
 | 
	
		
			
				|  |  | +            .refreshAfterWrite(600, TimeUnit.SECONDS)
 | 
	
		
			
				|  |  | +            .expireAfterWrite(600, TimeUnit.SECONDS)
 | 
	
		
			
				|  |  | +            .expireAfterAccess(600, TimeUnit.SECONDS)
 | 
	
		
			
				|  |  | +            .build(new CacheLoader<String, Map<String, List<Integer>>>() {
 | 
	
		
			
				|  |  | +                @Override
 | 
	
		
			
				|  |  | +                public Map<String, List<Integer>> load(String key) throws Exception {
 | 
	
		
			
				|  |  | +                    String value = redisTemplate.opsForValue().get(key);
 | 
	
		
			
				|  |  | +                    if (StringUtils.isEmpty(value)) {
 | 
	
		
			
				|  |  | +                        return Collections.emptyMap();
 | 
	
		
			
				|  |  | +                    }
 | 
	
		
			
				|  |  | +                    return JSONObject.parseObject(value, Map.class);
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +            });
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |      @PostConstruct
 | 
	
		
			
				|  |  |      public void init() {
 | 
	
		
			
				|  |  |          ab_initial_config_map.put("VLOG", "095");
 | 
	
	
		
			
				|  | @@ -52,12 +86,48 @@ public class RecommendService {
 | 
	
		
			
				|  |  |              return specialMidRecommend(request);
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        HomepageRecommendParam param = genHomepageRecommendParam(request);
 | 
	
		
			
				|  |  | +        HomepageRecommendParam param = genHomepageRecommendParam(request, 0);
 | 
	
		
			
				|  |  | +        log.info("genHomepageRecommendParam : {}", JSONUtils.toJson(param));
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        List<Video> videos;
 | 
	
		
			
				|  |  | +        String ab_code = param.getAb_code();
 | 
	
		
			
				|  |  | +        if (ab_code.equals("60054") || ab_code.equals("60056") || ab_code.equals("60067")
 | 
	
		
			
				|  |  | +                || ab_code.equals("60068") || ab_code.equals("60066") || ab_code.equals("60069")
 | 
	
		
			
				|  |  | +                || ab_code.equals("60070") || ab_code.equals("60071") || ab_code.equals("60072")
 | 
	
		
			
				|  |  | +                || ab_code.equals("60073") || ab_code.equals("60074") || ab_code.equals("60075")
 | 
	
		
			
				|  |  | +                || ab_code.equals("60076") || ab_code.equals("60077") || ab_code.equals("60078")
 | 
	
		
			
				|  |  | +                || ab_code.equals("60079") || ab_code.equals("60080") || ab_code.equals("60081")
 | 
	
		
			
				|  |  | +                || ab_code.equals("60082") || ab_code.equals("60083") || ab_code.equals("60084")
 | 
	
		
			
				|  |  | +                || ab_code.equals("60085") || ab_code.equals("60086")) {
 | 
	
		
			
				|  |  | +            videos = videoRecommendOld(request, param);
 | 
	
		
			
				|  |  | +        } else {
 | 
	
		
			
				|  |  | +            videos = videoRecommendNew(request, param);
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        List<Video> result = new ArrayList<>();
 | 
	
		
			
				|  |  | +        int i = 0;
 | 
	
		
			
				|  |  | +        for (Video v : videos) {
 | 
	
		
			
				|  |  | +            result.add(v.toBuilder().setPosition(i++).build());
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        //updateCache()
 | 
	
		
			
				|  |  | +        //    update_redis_data(result=rank_result, app_type=app_type, mid=mid, top_K=top_K,
 | 
	
		
			
				|  |  | +        //                      level_weight=level_weight, flow_pool_abtest_group=flow_pool_abtest_group)
 | 
	
		
			
				|  |  | +        return null;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    private List<Video> videoRecommendNew(HomepageRecommendRequest request, HomepageRecommendParam param) {
 | 
	
		
			
				|  |  | +        // TODO
 | 
	
		
			
				|  |  |          return null;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +    private List<Video> videoRecommendOld(HomepageRecommendRequest request, HomepageRecommendParam param) {
 | 
	
		
			
				|  |  | +        // TODO
 | 
	
		
			
				|  |  | +        return null;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    private HomepageRecommendParam genHomepageRecommendParam(HomepageRecommendRequest request) {
 | 
	
		
			
				|  |  | +    private HomepageRecommendParam genHomepageRecommendParam(HomepageRecommendRequest request, int recommendType) {
 | 
	
		
			
				|  |  |          HomepageRecommendParam param = new HomepageRecommendParam();
 | 
	
		
			
				|  |  |          param.setTop_K(3);
 | 
	
		
			
				|  |  |          param.setFlow_pool_P(0.3);
 | 
	
	
		
			
				|  | @@ -69,22 +139,102 @@ public class RecommendService {
 | 
	
		
			
				|  |  |                  ? ab_initial_config_map.get(request.getAppType())
 | 
	
		
			
				|  |  |                  : ab_initial_config_map.get("other");
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +        Map<String, String> abExpCode = abExpCodeMap.get(abInitialConfig);
 | 
	
		
			
				|  |  | +        param.setAb_code(abExpCode.get("ab_code"));
 | 
	
		
			
				|  |  | +        param.setRule_key(abExpCode.get("rule_key"));
 | 
	
		
			
				|  |  | +        param.setData_key(abExpCode.get("data_key"));
 | 
	
		
			
				|  |  | +        param.setRule_key_30day(abExpCode.get("30day_rule_key"));
 | 
	
		
			
				|  |  | +        param.setShield_config("");
 | 
	
		
			
				|  |  | +        param.setRank_key_prefix("rank:score1:");
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        // 实验配置
 | 
	
		
			
				|  |  | +        if (StringUtils.isNotBlank(request.getAbExpInfo())) {
 | 
	
		
			
				|  |  | +            Map<String, List<Map<String, String>>> map = JSONObject.parseObject(request.getAbExpInfo(), Map.class);
 | 
	
		
			
				|  |  | +            Set<String> abExpCodes = new HashSet<>();
 | 
	
		
			
				|  |  | +            for (List<Map<String, String>> list : map.values()) {
 | 
	
		
			
				|  |  | +                list.stream().forEach(m -> abExpCodes.add(m.get("abExpCode")));
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            // 流量池视频分发概率
 | 
	
		
			
				|  |  | +            if (abExpCodes.contains("211")) {
 | 
	
		
			
				|  |  | +                param.setFlow_pool_P(0.9);
 | 
	
		
			
				|  |  | +            } else if (abExpCodes.contains("221")) {
 | 
	
		
			
				|  |  | +                param.setFlow_pool_P(0.7);
 | 
	
		
			
				|  |  | +            } else if (abExpCodes.contains("299")) {
 | 
	
		
			
				|  |  | +                param.setFlow_pool_P(0.5);
 | 
	
		
			
				|  |  | +            } else if (abExpCodes.contains("300")) {
 | 
	
		
			
				|  |  | +                param.setFlow_pool_P(0.4);
 | 
	
		
			
				|  |  | +            } else if (abExpCodes.contains("301")) {
 | 
	
		
			
				|  |  | +                param.setFlow_pool_P(0.6);
 | 
	
		
			
				|  |  | +            } else if (abExpCodes.contains("339")) {
 | 
	
		
			
				|  |  | +                param.setFlow_pool_P(0);
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            for (Map.Entry<String, Map<String, String>> entry : abExpCodeMap.entrySet()) {
 | 
	
		
			
				|  |  | +                if (abExpCodes.contains(entry.getKey())) {
 | 
	
		
			
				|  |  | +                    param.setAb_code(entry.getValue().get("ab_code"));
 | 
	
		
			
				|  |  | +                    param.setRule_key(entry.getValue().get("rule_key"));
 | 
	
		
			
				|  |  | +                    param.setData_key(entry.getValue().get("data_key"));
 | 
	
		
			
				|  |  | +                    param.setRank_key_prefix(StringUtils.isNotBlank(entry.getValue().get("rank_key_prefix"))
 | 
	
		
			
				|  |  | +                            ? entry.getValue().get("rank_key_prefix")
 | 
	
		
			
				|  |  | +                            : "rank:score1:");
 | 
	
		
			
				|  |  | +                    param.setRule_key_30day(entry.getValue().get("30day_rule_key"));
 | 
	
		
			
				|  |  | +                    param.setShield_config(entry.getValue().get("ab_code"));
 | 
	
		
			
				|  |  | +                    break;
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        // app实验组
 | 
	
		
			
				|  |  | +        // {"10018":{"eventId":"100182","ifAddedRootEventId":true},"10020":{"eventId":"100201","ifAddedRootEventId":true}}
 | 
	
		
			
				|  |  | +        if (StringUtils.isNotBlank(request.getAbInfoData())) {
 | 
	
		
			
				|  |  | +            Map<String, Map<String, String>> map = JSONObject.parseObject(request.getAbInfoData(), Map.class);
 | 
	
		
			
				|  |  | +            Map<String, String> abInfoAppMap = new HashMap<>();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            for (Map.Entry<String, Map<String, String>> entry : map.entrySet()) {
 | 
	
		
			
				|  |  | +                if (MapUtils.isEmpty(entry.getValue())) {
 | 
	
		
			
				|  |  | +                    continue;
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +                String eventId = entry.getValue().get("eventId");
 | 
	
		
			
				|  |  | +                if (StringUtils.isNotBlank(eventId)) {
 | 
	
		
			
				|  |  | +                    abInfoAppMap.put(entry.getKey(), eventId);
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            if (recommendType == 0) {
 | 
	
		
			
				|  |  | +                String eventId = abInfoAppMap.get("10003");
 | 
	
		
			
				|  |  | +                Map<String, Map<String, String>> appAbCode = appAbCodeMap.get("10003");
 | 
	
		
			
				|  |  | +                if (StringUtils.isNotBlank(eventId) && appAbCode.containsKey(eventId)) {
 | 
	
		
			
				|  |  | +                    param.setAb_code(appAbCode.get(eventId).get("ab_code"));
 | 
	
		
			
				|  |  | +                    param.setRule_key(appAbCode.get(eventId).get("rule_key"));
 | 
	
		
			
				|  |  | +                    param.setData_key(appAbCode.get(eventId).get("data_key"));
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            // 流量池分发实验组划分
 | 
	
		
			
				|  |  | +            int flowPoolIdChoice = flowPoolIdList[RandomUtils.nextInt(0, flowPoolIdList.length - 1)];
 | 
	
		
			
				|  |  | +            param.setFlow_pool_abtest_group("control_group");
 | 
	
		
			
				|  |  | +            try {
 | 
	
		
			
				|  |  | +                Map<String, List<Integer>> flowPoolConfig = flowPoolConfigCache.get("flow:pool:abtest:config");
 | 
	
		
			
				|  |  | +                for (Map.Entry<String, List<Integer>> entry : flowPoolConfig.entrySet()) {
 | 
	
		
			
				|  |  | +                    if (entry.getValue().contains(flowPoolIdChoice)) {
 | 
	
		
			
				|  |  | +                        param.setFlow_pool_abtest_group(entry.getKey());
 | 
	
		
			
				|  |  | +                    }
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +            } catch (Exception e) {
 | 
	
		
			
				|  |  | +                log.error("flowPoolConfigCache get error", e);
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          return param;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      private HomepageRecommendResponse specialMidRecommend(HomepageRecommendRequest request) {
 | 
	
		
			
				|  |  |          String keyNamePrefix = "special:videos:item:";
 | 
	
		
			
				|  |  | -        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");
 | 
	
		
			
				|  |  | -        Date currentDate = new Date();
 | 
	
		
			
				|  |  | -        String dateStr = dateFormat.format(currentDate);
 | 
	
		
			
				|  |  | +        String dateStr = DateUtils.getCurrentDateStr("yyyyMMdd");
 | 
	
		
			
				|  |  |          String specialKeyName = keyNamePrefix + dateStr;
 | 
	
		
			
				|  |  |          if (!redisTemplate.hasKey(specialKeyName)) {
 | 
	
		
			
				|  |  | -            Calendar calendar = Calendar.getInstance();
 | 
	
		
			
				|  |  | -            calendar.setTime(currentDate);
 | 
	
		
			
				|  |  | -            calendar.add(Calendar.DAY_OF_MONTH, -1);
 | 
	
		
			
				|  |  | -            Date previousDate = calendar.getTime();
 | 
	
		
			
				|  |  | -            dateStr = dateFormat.format(previousDate);
 | 
	
		
			
				|  |  | +            dateStr = DateUtils.getBeforeDaysDateStr("yyyyMMdd", 1);
 | 
	
		
			
				|  |  |              specialKeyName = keyNamePrefix + dateStr;
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -129,4 +279,10 @@ public class RecommendService {
 | 
	
		
			
				|  |  |                  .build();
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +    public static void main(String[] args) {
 | 
	
		
			
				|  |  | +        String json = "{\"ab_test001\":[{\"ab_code\":\"1\",\"config_value\":\"v1\"},{\"ab_code\":\"2\",\"config_value\":\"v2\"}],\"ab_test002\":[{\"ab_code\":\"3\",\"config_value\":\"v3\"},{\"ab_code\":\"4\",\"config_value\":\"v4\"}]}";
 | 
	
		
			
				|  |  | +        Map<String, List<Map<String, String>>> map = JSONObject.parseObject(json, Map.class);
 | 
	
		
			
				|  |  | +        System.out.println("");
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  }
 |