|
|
@@ -94,10 +94,10 @@ public class PredictStrategyByRor extends BasicPredict {
|
|
|
String appType = ctx.getAppType();
|
|
|
|
|
|
// 获取默认概率阈值(基于 rootSessionId 尾号和 appType 匹配配置)
|
|
|
- Double defaultProbability = getDefaultProbability(rootSessionId, appType);
|
|
|
+ Boolean matchResult = getDefaultProbability(rootSessionId, appType);
|
|
|
|
|
|
// 用户不在实验分桶内,跳过该策略
|
|
|
- if (defaultProbability == null) {
|
|
|
+ if (!matchResult) {
|
|
|
return null;
|
|
|
}
|
|
|
|
|
|
@@ -107,6 +107,7 @@ public class PredictStrategyByRor extends BasicPredict {
|
|
|
String launchs = null; // 启动次数分桶(如 "0-5", "5-10" 等)
|
|
|
String ror = null; // 留存率分桶
|
|
|
String adLevel = null; // 广告等级(用户对广告的敏感度分层)
|
|
|
+ String return30day = null; // 用户回流率分桶
|
|
|
|
|
|
// 根据 mid 获取用户近一个月的历史行为特征
|
|
|
Feature feature = featureService.getMidBehaviorFeature(TABLE_NAME, ctx.getMid());
|
|
|
@@ -119,11 +120,16 @@ public class PredictStrategyByRor extends BasicPredict {
|
|
|
launchs = algMidHistoryBehavior1month.get("launchs");
|
|
|
ror = algMidHistoryBehavior1month.get("ror");
|
|
|
adLevel = algMidHistoryBehavior1month.get("ad_level");
|
|
|
+ return30day = algMidHistoryBehavior1month.get("return_30day");
|
|
|
}
|
|
|
|
|
|
// 计算最终的广告展示概率阈值
|
|
|
// 优先使用 Redis 中基于用户特征的精细化阈值,否则使用默认阈值
|
|
|
- double showAdProbability = getShowAdProbability(launchs, ror, adLevel, defaultProbability);
|
|
|
+ Double showAdProbability = getShowAdProbability(launchs, ror, adLevel,return30day);
|
|
|
+
|
|
|
+ if (showAdProbability == null) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
|
|
|
// 基于 mid 的 hash 值生成 [0, 1) 范围内的伪随机分数
|
|
|
// 同一个 mid 在同一小时内(RandW 每小时更新)会得到相同的分数
|
|
|
@@ -144,6 +150,7 @@ public class PredictStrategyByRor extends BasicPredict {
|
|
|
rtnMap.put("score", score);
|
|
|
rtnMap.put("threshold", showAdProbability);
|
|
|
rtnMap.put("launchs", launchs);
|
|
|
+ rtnMap.put("return_30day", return30day);
|
|
|
rtnMap.put("ror", ror);
|
|
|
rtnMap.put("ad_level", adLevel);
|
|
|
return rtnMap;
|
|
|
@@ -162,28 +169,28 @@ public class PredictStrategyByRor extends BasicPredict {
|
|
|
* @param launchs 启动次数分桶
|
|
|
* @param ror 留存率分桶
|
|
|
* @param ad_level 人群分层
|
|
|
- * @param defaultProbability 默认概率(兜底值)
|
|
|
+ *
|
|
|
* @return 广告展示概率阈值 [0, 1]
|
|
|
*/
|
|
|
- private double getShowAdProbability(String launchs, String ror, String ad_level, Double defaultProbability) {
|
|
|
+ private Double getShowAdProbability(String launchs, String ror, String ad_level,String return30day) {
|
|
|
// 任一特征为空,使用默认概率
|
|
|
- if (StringUtils.isAnyBlank(launchs, ror, ad_level)) {
|
|
|
- return defaultProbability;
|
|
|
+ if (StringUtils.isAnyBlank(launchs, ror, ad_level,return30day)) {
|
|
|
+ return null;
|
|
|
}
|
|
|
try {
|
|
|
// 构建 Redis key:格式为 "ad_level:launchs:ror",例如 "有转化:10:000"
|
|
|
- String keyId = ad_level + ":" + launchs + ":" + ror;
|
|
|
+ String keyId = ad_level + ":" + launchs + ":" + ror + ":" + return30day;
|
|
|
String key = String.format(RedisPrefixEnum.AD_USER_ROR_BEHAVIOR.getPrefix(), keyId);
|
|
|
|
|
|
// 从 Redis 获取概率值
|
|
|
String probability = adRedisHelper.get(key);
|
|
|
|
|
|
// 解析概率值,如果为 null 则使用默认值
|
|
|
- return probability == null ? defaultProbability : Double.parseDouble(probability);
|
|
|
+ return StringUtils.isBlank(probability) ? null : Double.parseDouble(probability);
|
|
|
} catch (Exception e) {
|
|
|
// 解析失败(如非数字字符串)或 Redis 异常,记录错误并使用默认值
|
|
|
log.error("getShowAdProbability error, launchs: {}, ror: {}, ad_level: {}, e = ", launchs, ror, ad_level, e);
|
|
|
- return defaultProbability;
|
|
|
+ return null;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -196,10 +203,10 @@ public class PredictStrategyByRor extends BasicPredict {
|
|
|
* @param appType 应用类型
|
|
|
* @return 默认概率,如果不匹配任何配置则返回 null
|
|
|
*/
|
|
|
- private Double getDefaultProbability(String rootSessionId, String appType) {
|
|
|
+ private Boolean getDefaultProbability(String rootSessionId, String appType) {
|
|
|
// 前置校验
|
|
|
if (CollectionUtils.isEmpty(configItems) || StringUtils.isAnyBlank(rootSessionId) || appType == null) {
|
|
|
- return null;
|
|
|
+ return false;
|
|
|
}
|
|
|
|
|
|
// 提取 rootSessionId 的最后一个字符作为尾号,用于流量分桶
|
|
|
@@ -209,14 +216,15 @@ public class PredictStrategyByRor extends BasicPredict {
|
|
|
for (RootSessionIdTailConfigItem item : configItems) {
|
|
|
if (item.getAppType() != null && item.getTail() != null) {
|
|
|
if (item.getAppType().contains(appType) && item.getTail().contains(tail)) {
|
|
|
- return item.getConfig().get("default_probability");
|
|
|
+// return item.getConfig().get("default_probability");
|
|
|
+ return true;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
// 未匹配到任何配置
|
|
|
- return null;
|
|
|
+ return false;
|
|
|
}
|
|
|
|
|
|
}
|