Ver código fonte

增加计费相关方法

xueyiming 2 dias atrás
pai
commit
52a35bdc09

+ 156 - 0
ad-engine-service/src/main/java/com/tzld/piaoquan/ad/engine/service/score/strategy/RankStrategyBasic.java

@@ -317,6 +317,162 @@ public abstract class RankStrategyBasic implements RankStrategy {
         }
     }
 
+    protected Map<Long, CorrectCpaParam> getCorrectCpaParamMap(RankRecommendRequestParam request, ScoreParam scoreParam) {
+        Map<String, String> userLayer = this.getUserLayer(request.getMid());
+
+        String layer = userLayer.getOrDefault("layer", "无曝光");
+        String clazz = userLayer.getOrDefault("class", "近期未出现");
+        if (StringUtils.isNotEmpty(layer) && layer.equals("已转化")) {
+            layer = "有转化";
+        }
+        if (request.getIsFilterUser()) {
+            layer = layer + "-炸";
+        }
+
+        String redisAdCustomerLayerHourKey = adCustomerLayerHourKey.replace("{layer}", layer).replace("{clazz}", clazz);
+        String redisAdVerLayerHourKey = adVerLayerHourKey.replace("{layer}", layer).replace("{clazz}", clazz);
+        String redisAadCustomerLayerDayKey = adCustomerLayerDayKey.replace("{layer}", layer).replace("{clazz}", clazz);
+        String redisAdVerLayerDayKey = adVerLayerDayKey.replace("{layer}", layer).replace("{clazz}", clazz);
+
+
+        Map<Long, CorrectCpaParam> resultMap = new HashMap<>();
+        try {
+            if (CollectionUtils.isEmpty(request.getAdIdList())) {
+                return resultMap;
+            }
+
+            // 抽取公共方法获取数据
+            List<Long> customerIds = request.getAdIdList().stream()
+                    .map(AdPlatformCreativeDTO::getCustomerId)
+                    .distinct()
+                    .collect(Collectors.toList());
+            Map<Long, JSONObject> customerLayerMap = getRedisData(
+                    customerIds,
+                    id -> redisAdCustomerLayerHourKey.replace("{customerId}", String.valueOf(id)),
+                    id -> redisAadCustomerLayerDayKey.replace("{customerId}", String.valueOf(id))
+            );
+
+            List<String> adVerIds = request.getAdIdList().stream()
+                    .map(AdPlatformCreativeDTO::getAdVerId)
+                    .distinct()
+                    .collect(Collectors.toList());
+            Map<String, JSONObject> adVerLayerMap = getRedisData(
+                    adVerIds,
+                    id -> redisAdVerLayerHourKey.replace("{adverId}", id),
+                    id -> redisAdVerLayerDayKey.replace("{adverId}", id)
+            );
+
+            for (AdPlatformCreativeDTO adPlatformCreativeDTO : request.getAdIdList()) {
+                Long creativeId = adPlatformCreativeDTO.getCreativeId();
+                Long customerId = adPlatformCreativeDTO.getCustomerId();
+                JSONObject jsonObject;
+                if (customerId != null && customerId != 0 && customerLayerMap.containsKey(customerId)) {
+                    jsonObject = customerLayerMap.get(customerId);
+                } else {
+                    jsonObject = adVerLayerMap.get(adPlatformCreativeDTO.getAdVerId());
+                }
+                CorrectCpaParam correctCpaParam = new CorrectCpaParam();
+                if (jsonObject == null) {
+                    correctCpaParam.setCorrectionFactor(1.0);
+                    resultMap.put(creativeId, correctCpaParam);
+                    continue;
+                }
+                Integer views = jsonObject.getInteger("viewsHour");
+                Double realCtcvrHour = jsonObject.getDouble("realCtcvrHour");
+                Double pCtcvrHour = jsonObject.getDouble("pCtcvrHour");
+                Double realCtcvrDay = jsonObject.getDouble("realCtcvrDay");
+                Double pCtcvrDay = jsonObject.getDouble("pCtcvrDay");
+                correctCpaParam.setRealCtcvrHour(realCtcvrHour);
+                correctCpaParam.setPCtcvrHour(pCtcvrHour);
+                correctCpaParam.setRealCtcvrDay(realCtcvrDay);
+                correctCpaParam.setPCtcvrDay(pCtcvrDay);
+                correctCpaParam.setView(views);
+                double correctionFactor = 1.0;
+                //曝光数小于目标曝光数,不进行修正
+                if (views == null || views < correctCpaView) {
+                    correctCpaParam.setCorrectionFactor(correctionFactor);
+                    resultMap.put(creativeId, correctCpaParam);
+                    continue;
+                }
+                if (realCtcvrHour != null && pCtcvrHour != null && realCtcvrDay != null && pCtcvrDay != null) {
+                    if (scoreParam.getExpCodeSet().contains(correctCpaExp2)) {
+                        correctionFactor = (1 - correctCpaAlpha2 - correctCpaBeta2) +
+                                NumUtil.div(realCtcvrHour, pCtcvrHour) * correctCpaAlpha2 +
+                                NumUtil.div(realCtcvrDay, pCtcvrDay) * correctCpaBeta2;
+                    } else {
+                        correctionFactor = Math.pow(NumUtil.div(realCtcvrHour, pCtcvrHour), correctCpaAlpha1) *
+                                Math.pow(NumUtil.div(realCtcvrDay, pCtcvrDay), correctCpaBeta1);
+                    }
+                    if (correctionFactor <= 0) {
+                        correctionFactor = 1;
+                    }
+                }
+                correctCpaParam.setCorrectionFactor(correctionFactor);
+                resultMap.put(creativeId, correctCpaParam);
+            }
+        } catch (Exception e) {
+            log.error("getCorrectCpaParamMap error", e);
+        }
+        return resultMap;
+    }
+
+    private <T> Map<T, JSONObject> getRedisData(
+            Collection<T> ids,
+            Function<T, String> hourKeyBuilder,
+            Function<T, String> dayKeyBuilder) {
+
+        Map<T, JSONObject> resultMap = new HashMap<>();
+        if (CollectionUtils.isEmpty(ids)) {
+            return resultMap;
+        }
+
+        // 构建Keys
+        List<String> hourKeys = ids.stream()
+                .map(hourKeyBuilder)
+                .collect(Collectors.toList());
+        List<String> dayKeys = ids.stream()
+                .map(dayKeyBuilder)
+                .collect(Collectors.toList());
+
+        // 批量获取Redis值
+        List<String> hourValues = adRedisHelper.mget(hourKeys);
+        List<String> dayValues = adRedisHelper.mget(dayKeys);
+
+        // 解析数据
+        Iterator<T> idIter = ids.iterator();
+        for (int i = 0; i < ids.size(); i++) {
+            T id = idIter.next();
+            JSONObject jsonObj = new JSONObject();
+
+            // 解析小时数据
+            parseRedisValue(hourValues.get(i), jsonObj, "Hour", "ctcvr", "pCtcvr", "views");
+            // 解析天数据
+            parseRedisValue(dayValues.get(i), jsonObj, "Day", "ctcvr", "pCtcvr", "views");
+
+            resultMap.put(id, jsonObj);
+        }
+        return resultMap;
+    }
+
+    private void parseRedisValue(String value, JSONObject target,
+                                 String suffix, String... keys) {
+        if (StringUtils.isEmpty(value)) return;
+
+        try {
+            JSONObject source = JSONObject.parseObject(value);
+            for (String key : keys) {
+                Object val = source.get(key);
+                if (val != null) {
+                    String newKey = (key.equals("ctcvr") ? "realCtcvr" : key) + suffix;
+                    target.put(newKey, val);
+                }
+            }
+        } catch (Exception e) {
+            log.warn("Parse redis value failed: {}", value, e);
+        }
+    }
+
+
     protected AdRankItem creativeCovertRankItem(AdPlatformCreativeDTO dto, RankRecommendRequestParam request, Set<String> noApiAdVerIds) {
         AdRankItem adRankItem = new AdRankItem();
         adRankItem.setAdId(dto.getCreativeId());