|
@@ -7,11 +7,15 @@ import com.ctrip.framework.apollo.spring.annotation.ApolloJsonValue;
|
|
|
import com.tzld.piaoquan.ad.engine.commons.dto.AdPlatformCreativeDTO;
|
|
|
import com.tzld.piaoquan.ad.engine.commons.enums.RedisPrefixEnum;
|
|
|
import com.tzld.piaoquan.ad.engine.commons.param.RankRecommendRequestParam;
|
|
|
+import com.tzld.piaoquan.ad.engine.commons.param.RecommendRequestParam;
|
|
|
import com.tzld.piaoquan.ad.engine.commons.redis.AdRedisHelper;
|
|
|
import com.tzld.piaoquan.ad.engine.commons.redis.AlgorithmRedisHelper;
|
|
|
import com.tzld.piaoquan.ad.engine.commons.score.ScoreParam;
|
|
|
import com.tzld.piaoquan.ad.engine.commons.util.DateUtils;
|
|
|
+import com.tzld.piaoquan.ad.engine.commons.util.NumUtil;
|
|
|
import com.tzld.piaoquan.ad.engine.commons.util.ObjUtil;
|
|
|
+import com.tzld.piaoquan.ad.engine.service.entity.CorrectCpaParam;
|
|
|
+import com.tzld.piaoquan.ad.engine.service.entity.CorrectCtcvrScoreParam;
|
|
|
import com.tzld.piaoquan.ad.engine.service.entity.CalibrationCtcvrData;
|
|
|
import com.tzld.piaoquan.ad.engine.service.entity.GuaranteeView;
|
|
|
import com.tzld.piaoquan.ad.engine.service.feature.Feature;
|
|
@@ -39,6 +43,7 @@ public abstract class RankStrategyBasic implements RankStrategy {
|
|
|
|
|
|
@Value("${guarantee.exp:742}")
|
|
|
protected String guaranteeExp;
|
|
|
+
|
|
|
@ApolloJsonValue("${alpha:1.0}")
|
|
|
protected Double alpha;
|
|
|
|
|
@@ -47,6 +52,49 @@ public abstract class RankStrategyBasic implements RankStrategy {
|
|
|
|
|
|
@ApolloJsonValue("${calibration.view.count:5000}")
|
|
|
protected Integer calibrationViewCount;
|
|
|
+
|
|
|
+ @Value("${correct.cpa.exp.1:}")
|
|
|
+ protected String correctCpaExp1;
|
|
|
+
|
|
|
+ @Value("${correct.cpa.exp.2:}")
|
|
|
+ protected String correctCpaExp2;
|
|
|
+
|
|
|
+ @Value("${correct.cpa.alpha.1:1.0}")
|
|
|
+ protected Double correctCpaAlpha1;
|
|
|
+
|
|
|
+ @Value("${correct.cpa.beta.1:1.0}")
|
|
|
+ protected Double correctCpaBeta1;
|
|
|
+
|
|
|
+ @Value("${correct.cpa.alpha.2:0.7}")
|
|
|
+ protected Double correctCpaAlpha2;
|
|
|
+
|
|
|
+ @Value("${correct.cpa.beta.2:0.2}")
|
|
|
+ protected Double correctCpaBeta2;
|
|
|
+
|
|
|
+ @Value("${correct.cpa.view:1000}")
|
|
|
+ protected Integer correctCpaView;
|
|
|
+
|
|
|
+ @Value("${exclude.exp:772}")
|
|
|
+ protected String excludeExp;
|
|
|
+
|
|
|
+ @Value("${target.crowd.exclude.exp:785}")
|
|
|
+ protected String targetCrowdExcludeExp;
|
|
|
+
|
|
|
+ @Value("${calibration.coefficient.exp:786}")
|
|
|
+ protected String calibrationCoefficientExp;
|
|
|
+
|
|
|
+ @Value("${calibration.view:2000}")
|
|
|
+ protected Integer calibrationView;
|
|
|
+
|
|
|
+ @Value("${calibration.alpha:0.5}")
|
|
|
+ protected Double calibrationAlpha;
|
|
|
+
|
|
|
+ @Value("${guarantee.weight:30}")
|
|
|
+ protected Integer guaranteeWeight;
|
|
|
+
|
|
|
+ @Value("${guarantee.switching.time:1754236800000}")
|
|
|
+ protected Long guaranteeSwitchingTime;
|
|
|
+
|
|
|
@Autowired
|
|
|
private FeatureService featureService;
|
|
|
@Autowired
|
|
@@ -61,6 +109,17 @@ public abstract class RankStrategyBasic implements RankStrategy {
|
|
|
String realCtcvrProfessionKey = "ad:platform:real:ctcvr:{model}:{layer}:{class}:{profession}";
|
|
|
|
|
|
|
|
|
+ String adCustomerLayerHourKey = "ad:platform:customer:hour:{layer}:{clazz}:{customerId}";
|
|
|
+
|
|
|
+ String adVerLayerHourKey = "ad:platform:adver:hour:{layer}:{clazz}:{adverId}";
|
|
|
+
|
|
|
+ String adCustomerLayerDayKey = "ad:platform:customer:day:{layer}:{clazz}:{customerId}";
|
|
|
+
|
|
|
+ String adVerLayerDayKey = "ad:platform:adver:day:{layer}:{clazz}:{adverId}";
|
|
|
+
|
|
|
+ String cidLayerKey = "ad:engine:cid:layer:info:{cid}:{userLayer}";
|
|
|
+
|
|
|
+
|
|
|
protected static final List<String> hasChannelScenes = new ArrayList<String>() {{
|
|
|
add("DaiTou");
|
|
|
add("GzhTouLiu");
|
|
@@ -194,10 +253,49 @@ public abstract class RankStrategyBasic implements RankStrategy {
|
|
|
|
|
|
}
|
|
|
|
|
|
- protected Map<String, GuaranteeView> getGuaranteeViewMap(RankRecommendRequestParam request, ScoreParam scoreParam) {
|
|
|
+ protected void filterRequestAdList(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 (Objects.equals(layer, "有转化") && Objects.equals(clazz, "中医") && scoreParam.getExpCodeSet().contains(excludeExp)) {
|
|
|
+ List<AdPlatformCreativeDTO> adIdList = request.getAdIdList();
|
|
|
+ Set<String> professions = adIdList.stream().map(AdPlatformCreativeDTO::getProfession).collect(Collectors.toSet());
|
|
|
+ //同时存在中医行业和兴趣教育行业
|
|
|
+ if (professions.contains("中医") && professions.contains("兴趣教育")) {
|
|
|
+ List<AdPlatformCreativeDTO> filteredAdList = adIdList.stream()
|
|
|
+ .filter(e -> !Objects.equals(e.getProfession(), "兴趣教育")).collect(Collectors.toList());
|
|
|
+ request.setAdIdList(filteredAdList);
|
|
|
+ }
|
|
|
+ log.info("excludeExp filtered request={}", JSONObject.toJSONString(request));
|
|
|
+ }
|
|
|
+
|
|
|
+ // 有曝光无转化-其他 过滤德瑞骅客户 客户id 26
|
|
|
+ if (Objects.equals(layer, "有曝光无转化") && Objects.equals(clazz, "其他") && scoreParam.getExpCodeSet().contains(targetCrowdExcludeExp)) {
|
|
|
+ List<AdPlatformCreativeDTO> adIdList = request.getAdIdList();
|
|
|
+ List<AdPlatformCreativeDTO> filteredAdList = adIdList.stream().filter(e -> e.getCustomerId() == null || e.getCustomerId() != 26L).collect(Collectors.toList());
|
|
|
+ request.setAdIdList(filteredAdList);
|
|
|
+ log.info("targetCrowdExcludeExp filtered request={}", JSONObject.toJSONString(request));
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ protected boolean getIsGuaranteedFlow(ScoreParam scoreParam) {
|
|
|
+ if (System.currentTimeMillis() < guaranteeSwitchingTime) {
|
|
|
+ return scoreParam.getExpCodeSet().contains(guaranteeExp);
|
|
|
+ }
|
|
|
+ Random random = new Random();
|
|
|
+ int i = random.nextInt(100);
|
|
|
+ return i < guaranteeWeight;
|
|
|
+ }
|
|
|
+
|
|
|
+ protected Map<String, GuaranteeView> getGuaranteeViewMap(RankRecommendRequestParam request, boolean isGuaranteedFlow) {
|
|
|
Map<String, GuaranteeView> map = new HashMap<>();
|
|
|
try {
|
|
|
- if (scoreParam.getExpCodeSet().contains(guaranteeExp)) {
|
|
|
+ if (isGuaranteedFlow) {
|
|
|
String thatDayDateString = DateUtils.getThatDayDateString();
|
|
|
String redisKey = adPlatformGuaranteeKey.replace("{date}", thatDayDateString);
|
|
|
List<String> adVerIds = request.getAdIdList().stream().map(AdPlatformCreativeDTO::getAdVerId).distinct()
|
|
@@ -221,8 +319,8 @@ public abstract class RankStrategyBasic implements RankStrategy {
|
|
|
return map;
|
|
|
}
|
|
|
|
|
|
- protected void setGuaranteeWeight(Map<String, GuaranteeView> map, String adVerId, Map<String, Object> ext) {
|
|
|
- if (MapUtils.isNotEmpty(map)) {
|
|
|
+ protected void setGuaranteeWeight(Map<String, GuaranteeView> map, String adVerId, Map<String, Object> ext, boolean isGuaranteedFlow) {
|
|
|
+ if (isGuaranteedFlow && MapUtils.isNotEmpty(map)) {
|
|
|
GuaranteeView guaranteeView = map.get(adVerId);
|
|
|
if (guaranteeView != null) {
|
|
|
double guaranteeWeight = calculateGuaranteedWeight(guaranteeView);
|
|
@@ -230,6 +328,7 @@ public abstract class RankStrategyBasic implements RankStrategy {
|
|
|
ext.put("guaranteeView", guaranteeView.toString());
|
|
|
ext.put("guaranteeWeight", guaranteeWeight);
|
|
|
ext.put("isGuaranteed", isGuaranteed);
|
|
|
+ ext.put("isGuaranteedFlow", isGuaranteedFlow);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
@@ -272,8 +371,8 @@ public abstract class RankStrategyBasic implements RankStrategy {
|
|
|
&& guaranteeView.getGuaranteeRate() != null && guaranteeView.getGuaranteeRate() != 0.0;
|
|
|
}
|
|
|
|
|
|
- protected double getGuaranteeScoreCoefficient(ScoreParam scoreParam, Map<String, Object> ext) {
|
|
|
- if (scoreParam.getExpCodeSet().contains(guaranteeExp)) {
|
|
|
+ protected double getGuaranteeScoreCoefficient(boolean isGuaranteedFlow, Map<String, Object> ext) {
|
|
|
+ if (isGuaranteedFlow) {
|
|
|
if (ext.get("guaranteeWeight") == null) {
|
|
|
return 1.0;
|
|
|
} else {
|
|
@@ -284,6 +383,235 @@ 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 void calculateCtcvrScore(List<AdRankItem> items, RankRecommendRequestParam request, ScoreParam scoreParam) {
|
|
|
+ if (scoreParam.getExpCodeSet().contains(calibrationCoefficientExp)) {
|
|
|
+ calibrationCtcvrScore(items, request);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ protected void calibrationCtcvrScore(List<AdRankItem> items, RankRecommendRequestParam request) {
|
|
|
+ Map<String, String> userLayer = this.getUserLayer(request.getMid());
|
|
|
+ String layer = userLayer.getOrDefault("layer", "无曝光");
|
|
|
+ String clazz = userLayer.getOrDefault("class", "近期未出现");
|
|
|
+ layer = "已转化".equals(layer) ? "有转化" : layer;
|
|
|
+ String userLayerClass = buildUserLayerClass(request.getIsFilterUser(), layer, clazz);
|
|
|
+ String cidLayerClassKey = cidLayerKey.replace("{userLayer}", userLayerClass);
|
|
|
+
|
|
|
+ // 3. 批量查询Redis
|
|
|
+ List<Long> cidList = items.stream().map(AdRankItem::getAdId).collect(Collectors.toList());
|
|
|
+ List<String> redisKeys = cidList.stream()
|
|
|
+ .map(cid -> cidLayerClassKey.replace("{cid}", cid.toString()))
|
|
|
+ .collect(Collectors.toList());
|
|
|
+
|
|
|
+ List<String> redisValues = algRedisHelper.mget(redisKeys);
|
|
|
+ Map<Long, CorrectCtcvrScoreParam> calibrationMap = parseRedisValues(cidList, redisValues);
|
|
|
+
|
|
|
+ // 4. 应用校准逻辑
|
|
|
+ applyCalibration(items, calibrationMap);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 解析Redis返回值到Map
|
|
|
+ private Map<Long, CorrectCtcvrScoreParam> parseRedisValues(List<Long> cidList, List<String> values) {
|
|
|
+ Map<Long, CorrectCtcvrScoreParam> map = new HashMap<>();
|
|
|
+ for (int i = 0; i < cidList.size(); i++) {
|
|
|
+ String value = values.get(i);
|
|
|
+ if (StringUtils.isEmpty(value)) continue;
|
|
|
+
|
|
|
+ try {
|
|
|
+ JSONObject json = JSONObject.parseObject(value);
|
|
|
+ Integer view = json.getInteger("view");
|
|
|
+ Double ctcvr = json.getDouble("ctcvr");
|
|
|
+ if (view != null && ctcvr != null) {
|
|
|
+ CorrectCtcvrScoreParam param = new CorrectCtcvrScoreParam();
|
|
|
+ param.setView(view);
|
|
|
+ param.setRealCtcvr(ctcvr);
|
|
|
+ map.put(cidList.get(i), param);
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("Failed to parse calibration data for cid={}", cidList.get(i), e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return map;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 应用校准到广告项
|
|
|
+ private void applyCalibration(List<AdRankItem> items, Map<Long, CorrectCtcvrScoreParam> calibrationMap) {
|
|
|
+ for (AdRankItem item : items) {
|
|
|
+ CorrectCtcvrScoreParam param = calibrationMap.get(item.getAdId());
|
|
|
+ if (param == null || param.getView() == null || param.getView() < calibrationView) {
|
|
|
+ continue; // 跳过无效数据
|
|
|
+ }
|
|
|
+
|
|
|
+ double realCtcvr = Optional.ofNullable(param.getRealCtcvr()).orElse(0.0);
|
|
|
+ double calibratedScore = item.getLrScore() * calibrationAlpha + (1 - calibrationAlpha) * realCtcvr;
|
|
|
+ item.getExt().put("correctCtcvrScoreParam", JSONObject.toJSONString(param));
|
|
|
+ item.getScoreMap().put("ctcvrScore", calibratedScore);
|
|
|
+ item.getScoreMap().put("realCtcvr", realCtcvr);
|
|
|
+ item.setLrScore(calibratedScore);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private String buildUserLayerClass(boolean isFilterUser, String layer, String clazz) {
|
|
|
+ if (Objects.equals(layer, "已转化")) layer = "有转化";
|
|
|
+ return isFilterUser ? layer + "-炸-" + clazz : layer + "-" + clazz;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
protected AdRankItem creativeCovertRankItem(AdPlatformCreativeDTO dto, RankRecommendRequestParam request, Set<String> noApiAdVerIds) {
|
|
|
AdRankItem adRankItem = new AdRankItem();
|
|
|
adRankItem.setAdId(dto.getCreativeId());
|