Kaynağa Gözat

Merge branch 'master' into feature_gufengshou_20240125_pid

# Conflicts:
#	ad-engine-service/src/main/java/com/tzld/piaoquan/ad/engine/service/predict/container/AbTestConfigContainer.java
gufengshou1 1 yıl önce
ebeveyn
işleme
eb6385963a
25 değiştirilmiş dosya ile 861 ekleme ve 213 silme
  1. 2 0
      ad-engine-commons/src/main/java/com/tzld/piaoquan/ad/engine/commons/score/ScoreParam.java
  2. 2 0
      ad-engine-commons/src/main/java/com/tzld/piaoquan/ad/engine/commons/score/ScorerUtils.java
  3. 3 3
      ad-engine-commons/src/main/java/com/tzld/piaoquan/ad/engine/commons/score/model/ThompsonSamplingModel.java
  4. 13 0
      ad-engine-commons/src/main/java/com/tzld/piaoquan/ad/engine/commons/util/TimerWatchUtil.java
  5. 25 0
      ad-engine-server/src/main/resources/feeds_score_config_share0.conf
  6. 6 0
      ad-engine-service/pom.xml
  7. 4 0
      ad-engine-service/src/main/java/com/tzld/piaoquan/ad/engine/service/predict/container/AbTestConfigContainer.java
  8. 184 0
      ad-engine-service/src/main/java/com/tzld/piaoquan/ad/engine/service/predict/container/PredictPidContainer.java
  9. 101 0
      ad-engine-service/src/main/java/com/tzld/piaoquan/ad/engine/service/predict/container/RandWContainer.java
  10. 74 0
      ad-engine-service/src/main/java/com/tzld/piaoquan/ad/engine/service/predict/container/ThresholdModelContainer.java
  11. 1 1
      ad-engine-service/src/main/java/com/tzld/piaoquan/ad/engine/service/predict/helper/RuleParamHelper.java
  12. 112 164
      ad-engine-service/src/main/java/com/tzld/piaoquan/ad/engine/service/predict/impl/PredictModelServiceImpl.java
  13. 10 1
      ad-engine-service/src/main/java/com/tzld/piaoquan/ad/engine/service/predict/model/threshold/AddThresholdPredictModel.java
  14. 7 1
      ad-engine-service/src/main/java/com/tzld/piaoquan/ad/engine/service/predict/model/threshold/BasicThresholdPredictModel.java
  15. 7 1
      ad-engine-service/src/main/java/com/tzld/piaoquan/ad/engine/service/predict/model/threshold/MultiplyThresholdPredictModel.java
  16. 65 0
      ad-engine-service/src/main/java/com/tzld/piaoquan/ad/engine/service/predict/model/threshold/NoShareUserThresholdPredictModel.java
  17. 50 0
      ad-engine-service/src/main/java/com/tzld/piaoquan/ad/engine/service/predict/model/threshold/RandomPredictModel.java
  18. 2 1
      ad-engine-service/src/main/java/com/tzld/piaoquan/ad/engine/service/predict/model/threshold/RoiThresholdPredictModel.java
  19. 8 1
      ad-engine-service/src/main/java/com/tzld/piaoquan/ad/engine/service/predict/model/threshold/ScoreThresholdPredictModel.java
  20. 39 4
      ad-engine-service/src/main/java/com/tzld/piaoquan/ad/engine/service/predict/model/threshold/ScoreV2ThresholdPredictModel.java
  21. 17 0
      ad-engine-service/src/main/java/com/tzld/piaoquan/ad/engine/service/predict/param/ThresholdPredictModelParam.java
  22. 48 0
      ad-engine-service/src/main/java/com/tzld/piaoquan/ad/engine/service/score/Share0MergeBreakScorer.java
  23. 11 7
      ad-engine-service/src/main/java/com/tzld/piaoquan/ad/engine/service/score/VlogMergeBreakScorer.java
  24. 47 27
      ad-engine-service/src/main/java/com/tzld/piaoquan/ad/engine/service/score/VlogMergeEcpmScorer.java
  25. 23 2
      ad-engine-service/src/main/java/com/tzld/piaoquan/ad/engine/service/score/impl/RankServiceImpl.java

+ 2 - 0
ad-engine-commons/src/main/java/com/tzld/piaoquan/ad/engine/commons/score/ScoreParam.java

@@ -2,6 +2,7 @@ package com.tzld.piaoquan.ad.engine.commons.score;
 
 import com.tzld.piaoquan.recommend.feature.domain.ad.base.AdRequestContext;
 import lombok.Data;
+import java.util.*;
 
 /**
  * @author dyp
@@ -15,6 +16,7 @@ public class ScoreParam {
     private String uid;
     private String city;
     private String province;
+    private Map<String,Object> extraParam=new HashMap<>();
 
 
 }

+ 2 - 0
ad-engine-commons/src/main/java/com/tzld/piaoquan/ad/engine/commons/score/ScorerUtils.java

@@ -24,6 +24,7 @@ public final class ScorerUtils {
     public static String THOMPSON_CONF = "feeds_score_config_thompson.conf";
 
     public static String BREAK_CONFIG = "feeds_score_config_break.conf";
+    public static String SHARE0_CONFIG = "feeds_score_config_share0.conf";
 
 
     public static void warmUp() {
@@ -31,6 +32,7 @@ public final class ScorerUtils {
         ScorerUtils.init(BASE_CONF);
         ScorerUtils.init(THOMPSON_CONF);
         ScorerUtils.init(BREAK_CONFIG);
+        ScorerUtils.init(SHARE0_CONFIG);
 
     }
 

+ 3 - 3
ad-engine-commons/src/main/java/com/tzld/piaoquan/ad/engine/commons/score/model/ThompsonSamplingModel.java

@@ -30,9 +30,9 @@ public class ThompsonSamplingModel extends Model {
     // key = adid, value = <exp, click, conversation>
     private Map<Long, AdActionFeature> thompsonSamplingModel;
 
-    private static final int alpha = 6;
-    private static final int beta_click = 100;
-    private static final int beta_conversion = 100;
+    private static final int alpha = 60;
+    private static final int beta_click = 2000;
+    private static final int beta_conversion = 2000;
 
     public ThompsonSamplingModel() {
         //配置不同环境的hdfs conf

+ 13 - 0
ad-engine-commons/src/main/java/com/tzld/piaoquan/ad/engine/commons/util/TimerWatchUtil.java

@@ -0,0 +1,13 @@
+package com.tzld.piaoquan.ad.engine.commons.util;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class TimerWatchUtil {
+
+    private final static Logger log = LoggerFactory.getLogger(TimerWatchUtil.class);
+
+    public static void printCost(String method,int step,long begin){
+        log.info("svc={}_byTimerWatchUtil step={} begin={} cost={}",method,step,begin,System.currentTimeMillis()-begin);
+    }
+}

+ 25 - 0
ad-engine-server/src/main/resources/feeds_score_config_share0.conf

@@ -0,0 +1,25 @@
+scorer-config = {
+  lr-ctr-score-config = {
+    scorer-name = "com.tzld.piaoquan.ad.engine.service.score.VlogAdCtrLRScorer"
+    scorer-priority = 99
+    model-path = "ad_ctr_model/model_ad_ctr.txt"
+  }
+  lr-cvr-score-config = {
+      scorer-name = "com.tzld.piaoquan.ad.engine.service.score.VlogAdCvrLRScorer"
+      scorer-priority = 98
+      model-path = "ad_cvr_model/model_ad_cvr.txt"
+  }
+  str-ros-score-config = {
+      scorer-name = "com.tzld.piaoquan.ad.engine.service.score.VlogAdRosAndStrScorer"
+      scorer-priority = 97
+  }
+  break-score-config = {
+      scorer-name = "com.tzld.piaoquan.ad.engine.service.score.VlogAdBreakScorer"
+      scorer-priority = 96
+  }
+  break-merge-config = {
+      scorer-name = "com.tzld.piaoquan.ad.engine.service.score.Share0MergeBreakScorer"
+      scorer-priority = 1
+  }
+
+}

+ 6 - 0
ad-engine-service/pom.xml

@@ -30,5 +30,11 @@
             <artifactId>odps-sdk-core</artifactId>
             <version>0.45.6-public</version>
         </dependency>
+        <!-- t-digest算法包       -->
+        <dependency>
+            <groupId>com.tdunning</groupId>
+            <artifactId>t-digest</artifactId>
+            <version>3.3</version>
+        </dependency>
     </dependencies>
 </project>

+ 4 - 0
ad-engine-service/src/main/java/com/tzld/piaoquan/ad/engine/service/predict/container/AbTestConfigContainer.java

@@ -25,6 +25,7 @@ public class AbTestConfigContainer {
     @Value("${ad.abtest.time.plan.code:555}")
     String adTestCode;
 
+
     public Boolean containsCode(Map<String,List<JSONObject>> configMap,String code){
         return configMap.keySet().contains(code);
     }
@@ -36,16 +37,19 @@ public class AbTestConfigContainer {
                 return true;
             }
         }
+        //
         return flag;
     }
 
     public Boolean inAdTimeTest(JSONObject abExpInfo){
+        //todo youhua
         List<Map<String,Object>> mapList=(List)abExpInfo.get("ab_test002");
         for(Map<String,Object> map:mapList){
             if(adTestCode.equals(map.getOrDefault("abExpCode",""))){
                 return true;
             }
         }
+        //
         return false;
     }
 

+ 184 - 0
ad-engine-service/src/main/java/com/tzld/piaoquan/ad/engine/service/predict/container/PredictPidContainer.java

@@ -0,0 +1,184 @@
+package com.tzld.piaoquan.ad.engine.service.predict.container;
+
+import com.alibaba.fastjson.JSONObject;
+import com.alibaba.fastjson.TypeReference;
+import com.aliyun.oss.OSS;
+import com.aliyun.oss.OSSClientBuilder;
+import com.aliyun.oss.common.auth.CredentialsProvider;
+import com.aliyun.oss.common.auth.DefaultCredentialProvider;
+import com.aliyun.oss.model.CopyObjectResult;
+import com.aliyun.oss.model.OSSObject;
+import com.aliyun.oss.model.PutObjectResult;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.PostConstruct;
+import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+
+@Component
+public class PredictPidContainer {
+    private final static Logger log = LoggerFactory.getLogger(PredictPidContainer.class);
+
+    private static final int SCHEDULE_PERIOD = 10;
+    private static final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
+    @Value("${model.oss.internal.endpoint:oss-cn-hangzhou.aliyuncs.com}")
+    String endpoint = "";
+    @Value("${model.oss.accessKeyId:LTAIP6x1l3DXfSxm}")
+    String accessKeyId = "";
+    @Value("${model.oss.accessKetSecret:KbTaM9ars4OX3PMS6Xm7rtxGr1FLon}")
+    String accessKetSecret = "";
+    @Value("${model.oss.bucketName:art-recommend}")
+    String bucketName = "";
+
+    @Value("${model.oss.pid.predict.filename.lambda:pid/predict_lambda}")
+    String lambdaFileName = "";
+
+    @Value("${model.oss.pid.predict.filename.dThreshold:pid/predict_dThreshold.txt}")
+    String dThresholdFileName = "";
+
+    @Value("${ad.model.pid.predict_threshold.kp:0.8}")
+    Double kp = 0d;
+
+    @Value("${ad.model.pid.predict_threshold.ki:0.01}")
+    Double ki = 0d;
+
+    @Value("${ad.model.pid.predict_threshold.kd:0.002}")
+    Double kd = 0d;
+
+    OSS client;
+
+    private static ConcurrentHashMap<String,Double>  lambdaCache=new ConcurrentHashMap<>();
+
+    private static ConcurrentHashMap<String,Double>  latestThresholdCache=new ConcurrentHashMap<>();
+    private Date cacheDate;
+
+    @PostConstruct
+    private void init(){
+        instanceClient();
+        final Runnable task = new Runnable() {
+            public void run() {
+                try {
+                    loadAndCalIfNeed();
+                }catch (Exception e){
+                    e.printStackTrace();
+                }
+            }
+        };
+        scheduler.scheduleAtFixedRate(task, 0, SCHEDULE_PERIOD, TimeUnit.MINUTES); // 10分钟
+    }
+
+    private void instanceClient(){
+        CredentialsProvider credentialsProvider = new DefaultCredentialProvider(accessKeyId, accessKetSecret);
+        this.client = new OSSClientBuilder().build(endpoint, credentialsProvider);
+    }
+
+    private void loadAndCalIfNeed(){
+        loadLambdaFile();
+        OSSObject dCpaFileOjb=client.getObject(bucketName,dThresholdFileName);
+        loadLatestThresholdCache(dCpaFileOjb);
+        if(cacheDate==null||dCpaFileOjb.getObjectMetadata().getLastModified().after(cacheDate)){
+            calNewLambda(dCpaFileOjb);
+            writeLambdaFileToOss();
+        }
+    }
+
+    private void calNewLambda(OSSObject object) {
+        try {
+            InputStream is=object.getObjectContent();
+            InputStreamReader isr=new InputStreamReader(is);
+            BufferedReader bufferedReader = new BufferedReader(isr);
+            String line = null;
+            while ((line = bufferedReader.readLine()) != null){
+                try {
+                    String[] cols=line.split(",");
+                    String group=cols[0].trim();
+                    Double lambdaNew=lambdaCache.getOrDefault(group,0d)+
+                            kp*Double.parseDouble(cols[1])+ki*Double.parseDouble(cols[2])+kd*Double.parseDouble(cols[3]);
+                    lambdaCache.put(group,lambdaNew);
+                    latestThresholdCache.put(group,Double.parseDouble(cols[4].trim()));
+                }catch (Exception e){
+                    e.printStackTrace();
+                }
+            }
+        }catch (Exception e){
+            log.error("svc=calNewPredictLambda status=failed error={}", Arrays.toString(e.getStackTrace()));
+        }
+    }
+
+    private void loadLatestThresholdCache(OSSObject object) {
+        try {
+            InputStream is=object.getObjectContent();
+            InputStreamReader isr=new InputStreamReader(is);
+            BufferedReader bufferedReader = new BufferedReader(isr);
+            String line = null;
+            while ((line = bufferedReader.readLine()) != null){
+                try {
+                    String[] cols=line.split(",");
+                    String group=cols[0].trim();
+                    if(group!=null&&cols[4].trim()!=null){
+                        latestThresholdCache.put(group,Double.parseDouble(cols[4].trim()));
+                    }
+                }catch (Exception e){
+                    e.printStackTrace();
+                }
+            }
+        }catch (Exception e){
+            log.error("svc=calNewPredictLambda status=failed error={}", Arrays.toString(e.getStackTrace()));
+        }
+    }
+
+    private void writeLambdaFileToOss(){
+        //先不考虑各种更新失败及重复更新问题。
+        try {
+            String tempFile=lambdaFileName+"_temp";
+            String content= JSONObject.toJSONString(lambdaCache);
+            PutObjectResult putObjectResult=client.putObject(bucketName,tempFile,new ByteArrayInputStream(content.getBytes()));
+            CopyObjectResult copyObjectResult=client.copyObject(bucketName, tempFile, bucketName, lambdaFileName);
+            this.cacheDate= copyObjectResult.getLastModified();
+            client.deleteObject(bucketName, tempFile);
+        }catch (Exception e){
+            log.error("svc=writePredictLambdaFileToOss status=failed error={}", Arrays.toString(e.getStackTrace()));
+            e.printStackTrace();
+        }
+    }
+
+    private void loadLambdaFile(){
+        try {
+            OSSObject object=client.getObject(bucketName,lambdaFileName);
+            if(object==null) return;
+            if(cacheDate!=null&& !cacheDate.before(object.getObjectMetadata().getLastModified())) return;
+            StringBuilder builder=new StringBuilder();
+            InputStream is=object.getObjectContent();
+            InputStreamReader isr=new InputStreamReader(is);
+            BufferedReader bufferedReader = new BufferedReader(isr);
+            String line = null;
+            while ((line=bufferedReader.readLine())!=null){
+                builder.append(line);
+            }
+            lambdaCache=JSONObject.parseObject(builder.toString(),new TypeReference<ConcurrentHashMap<String,Double>>(){});
+            this.cacheDate=object.getObjectMetadata().getLastModified();
+        }catch (Exception e){
+            log.error("svc=loadPredictLambdaFile status=failed error={}", Arrays.toString(e.getStackTrace()));
+            e.printStackTrace();
+        }
+    }
+
+    public static Double getPidLambda(String group){
+        return lambdaCache.getOrDefault(group,0d);
+    }
+
+    public static Double getLatestThreshold(String group){
+        return latestThresholdCache.getOrDefault(group,0d);
+    }
+}

+ 101 - 0
ad-engine-service/src/main/java/com/tzld/piaoquan/ad/engine/service/predict/container/RandWContainer.java

@@ -0,0 +1,101 @@
+package com.tzld.piaoquan.ad.engine.service.predict.container;
+
+import com.alibaba.fastjson.JSONObject;
+import com.alibaba.fastjson.TypeReference;
+import com.aliyun.oss.OSS;
+import com.aliyun.oss.OSSClientBuilder;
+import com.aliyun.oss.common.auth.CredentialsProvider;
+import com.aliyun.oss.common.auth.DefaultCredentialProvider;
+import com.aliyun.oss.model.CopyObjectResult;
+import com.aliyun.oss.model.OSSObject;
+import com.aliyun.oss.model.PutObjectResult;
+import com.tzld.piaoquan.ad.engine.commons.redis.AlgorithmRedisHelper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.PostConstruct;
+import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.Random;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+
+@Component
+public class RandWContainer {
+    private final static Logger log = LoggerFactory.getLogger(RandWContainer.class);
+
+    @Autowired
+    private AlgorithmRedisHelper redisHelper;
+
+    private static final int SCHEDULE_PERIOD = 10;
+    private static final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
+
+    String randWKey = "ad:engine:random:w";
+
+    OSS client;
+
+    public static Integer randW=0;
+
+    private static Random random=new Random();
+    private Date cacheDate;
+
+    @PostConstruct
+    private void init(){
+        final Runnable task = new Runnable() {
+            public void run() {
+                try {
+                    loadAndCalIfNeed();
+                }catch (Exception e){
+                    e.printStackTrace();
+                }
+            }
+        };
+        scheduler.scheduleAtFixedRate(task, 0, SCHEDULE_PERIOD, TimeUnit.SECONDS); // 60分钟
+    }
+
+
+    private void loadAndCalIfNeed(){
+        loadRandW();
+        Date now=new Date(System.currentTimeMillis()-60*60*1000);
+        if(cacheDate==null||now.after(cacheDate)){
+            calNewRandomW();
+            writeToRedis();
+        }
+    }
+
+    private void calNewRandomW() {
+        randW=random.nextInt(100);
+    }
+
+    private void writeToRedis(){
+        //先不考虑各种更新失败及重复更新问题。
+        redisHelper.set(randWKey,randW.toString()+"_"+System.currentTimeMillis(),0);
+    }
+
+    private void loadRandW(){
+        try {
+            String str=redisHelper.getString(randWKey);
+            if(str==null) return;
+            String[] arr=str.split("_");
+            randW=Integer.parseInt(arr[0]);
+            this.cacheDate=new Date(Long.parseLong(arr[1]));
+            System.out.println("randW="+randW);
+        }catch (Exception e){
+            log.error("svc=load_randomW status=failed error={}", Arrays.toString(e.getStackTrace()));
+            e.printStackTrace();
+        }
+    }
+
+    public static Integer getRandW(){
+        return randW;
+    }
+
+}

+ 74 - 0
ad-engine-service/src/main/java/com/tzld/piaoquan/ad/engine/service/predict/container/ThresholdModelContainer.java

@@ -1,27 +1,60 @@
 package com.tzld.piaoquan.ad.engine.service.predict.container;
 
+import com.tdunning.math.stats.Centroid;
+import com.tdunning.math.stats.MergingDigest;
+import com.tzld.piaoquan.ad.engine.service.predict.model.threshold.ScoreV2ThresholdPredictModel;
 import com.tzld.piaoquan.ad.engine.service.predict.model.threshold.ThresholdPredictModel;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
 import org.springframework.context.ApplicationContext;
 import org.springframework.stereotype.Component;
 
+
 import javax.annotation.PostConstruct;
 import java.util.HashMap;
 import java.util.Map;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
 
 @Component
 public class ThresholdModelContainer {
 
+    private final static Logger log = LoggerFactory.getLogger(ScoreV2ThresholdPredictModel.class);
+
     @Autowired
     private ApplicationContext applicationContext;
+    @Value("${ad.predict.t-digest.position:0.52}")
+    private double position;
 
     public static Map<String,ThresholdPredictModel> modelMap=new HashMap<>();
+    public static Map<Integer,MergingDigest> mergingDigestMap=new HashMap<>();
+
+    private static final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
     @PostConstruct
     public void init() {
         Map<String,ThresholdPredictModel> beanMap= applicationContext.getBeansOfType(ThresholdPredictModel.class);
         beanMap.forEach((s,model)->{
             modelMap.put(model.getName(), model);
         });
+        //只关注重点app
+        mergingDigestMap.put(0, new MergingDigest(10000));
+        mergingDigestMap.put(3, new MergingDigest(10000));
+        mergingDigestMap.put(4, new MergingDigest(10000));
+        mergingDigestMap.put(5, new MergingDigest(10000));
+        mergingDigestMap.put(21, new MergingDigest(10000));
+        final Runnable task = new Runnable() {
+            public void run() {
+                try {
+                    printDigestThreshold();
+                }catch (Exception e){
+                    e.printStackTrace();
+                }
+            }
+        };
+        scheduler.scheduleAtFixedRate(task, 0, 1, TimeUnit.MINUTES); // 10分钟
     }
 
     public static ThresholdPredictModel getThresholdPredictModel(String modelName){
@@ -31,4 +64,45 @@ public class ThresholdModelContainer {
     public static ThresholdPredictModel getBasicPredictModel(){
         return modelMap.get("basic");
     }
+
+    public static void mergingDigestAddScore(Integer appType,Double score){
+        mergingDigestMap.getOrDefault(appType,new MergingDigest(1)).add(score);
+    }
+
+    public static double getThresholdByTDigest(Integer appType,Double sortPosition){
+        return  mergingDigestMap.getOrDefault(appType,new MergingDigest(1)).quantile(sortPosition);
+    }
+
+    public void printDigestThreshold(){
+        try {
+            for(Map.Entry<Integer,MergingDigest> entry:mergingDigestMap.entrySet()){
+                log.info("svc=printDigestThreshold modelName=modelV2 appType={} mergingDigestThreshold={}"
+                        , entry.getKey(),entry.getValue().quantile(position));
+            }
+
+        }catch (Exception e){
+            e.printStackTrace();
+        }
+    }
+
+
+//    public static void main(String[] args){
+//        MergingDigest mergingDigest = new MergingDigest(100);
+//        for(long i=0;i<1000;i++){
+//            double newDataPoint = Math.random() * 100;
+//            // 向MergingDigest中添加新数据
+//            mergingDigest.add(newDataPoint);
+//        }
+//        System.out.println(mergingDigest.quantile(0.12));
+//        System.out.println(mergingDigest.quantile(0.6));
+//        Iterable<Centroid> centroids = mergingDigest.centroids();
+//        Integer totalW=0;
+//        Integer totalS=0;
+//        // 遍历质点列表并输出
+//        for (Centroid centroid : centroids) {
+//            System.out.println("值: " + centroid.mean() + ", 权重: " + centroid.count());
+//        }
+//        System.out.println(totalW);
+//        System.out.println(totalS);
+//    }
 }

+ 1 - 1
ad-engine-service/src/main/java/com/tzld/piaoquan/ad/engine/service/predict/param/RuleParamHelper.java → ad-engine-service/src/main/java/com/tzld/piaoquan/ad/engine/service/predict/helper/RuleParamHelper.java

@@ -1,4 +1,4 @@
-package com.tzld.piaoquan.ad.engine.service.predict.param;
+package com.tzld.piaoquan.ad.engine.service.predict.helper;
 
 import com.tzld.piaoquan.ad.engine.commons.redis.AlgorithmRedisHelper;
 import com.tzld.piaoquan.ad.engine.service.predict.constant.RuleRedisKeyConst;

+ 112 - 164
ad-engine-service/src/main/java/com/tzld/piaoquan/ad/engine/service/predict/impl/PredictModelServiceImpl.java

@@ -2,11 +2,13 @@ package com.tzld.piaoquan.ad.engine.service.predict.impl;
 
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
+import com.alibaba.fastjson.TypeReference;
 import com.google.common.reflect.TypeToken;
 import com.tzld.piaoquan.ad.engine.commons.enums.AppTypeEnum;
 import com.tzld.piaoquan.ad.engine.commons.redis.AlgorithmRedisHelper;
 import com.tzld.piaoquan.ad.engine.commons.util.DateUtils;
 import com.tzld.piaoquan.ad.engine.commons.util.JSONUtils;
+import com.tzld.piaoquan.ad.engine.commons.util.TimerWatchUtil;
 import com.tzld.piaoquan.ad.engine.service.predict.config.RoiModelConfig;
 import com.tzld.piaoquan.ad.engine.service.predict.constant.RuleRedisKeyConst;
 import com.tzld.piaoquan.ad.engine.service.predict.PredictModelService;
@@ -15,7 +17,6 @@ import com.tzld.piaoquan.ad.engine.service.predict.container.AbTestConfigContain
 import com.tzld.piaoquan.ad.engine.service.predict.container.ThresholdModelContainer;
 import com.tzld.piaoquan.ad.engine.service.predict.container.TopOneVideoContainer;
 import com.tzld.piaoquan.ad.engine.service.predict.param.RoiThresholdPredictModelParam;
-import com.tzld.piaoquan.ad.engine.service.predict.param.RuleParamHelper;
 import com.tzld.piaoquan.ad.engine.service.predict.param.ThresholdPredictModelParam;
 import com.tzld.piaoquan.ad.engine.service.predict.param.request.RoiPredictModelRequestParam;
 import com.tzld.piaoquan.ad.engine.service.predict.param.request.ThresholdPredictModelRequestParam;
@@ -52,176 +53,57 @@ public class PredictModelServiceImpl implements PredictModelService {
 
     @Value("${ad.predict.break.switch:false}")
     private boolean adPredictBreakSwitch;
-    @Value("${ad.predict.break.exp.code:0}")
+    @Value("${ad.predict.break.exp.code:570}")
     private String adPredictBreakExpCode;
 
-    public Map<String, Object> adPredict(ThresholdPredictModelRequestParam requestParam) {
+    @Value("${ad.predict.share0.exp.code:000}")
+    private String adPredictNoShareUserExpCode;
 
-        boolean isHit = false;
+    @Value("${ad.predict.param.testIds:0}")
+    private String testIds;
+    @Value("${ad.predict.without.ad.video_ids:0}")
+    private String withoutAdVideoIds;
 
-        try {
-            JSONObject object = requestParam.getAbExpInfo();
-            if (object != null) {
-                JSONArray array = object.getJSONArray("ab_test002");
-                if (array != null) {
-                    List<Map<String, String>> abExps = JSONUtils.fromJson(array.toJSONString(),
-                            new TypeToken<List<Map<String, String>>>() {
-                            }, Collections.emptyList());
-                    for (Map<String, String> abExpMap : abExps) {
-                        if (StringUtils.equals(abExpMap.get("abExpCode"), adPredictBreakExpCode)) {
-                            isHit = true;
-                            break;
-                        }
-                    }
+    public Map<String, Object> adPredict(ThresholdPredictModelRequestParam requestParam) {
+        String[] withoutAdVideoIdsArr=withoutAdVideoIds.split(",");
+        for(String videoId:withoutAdVideoIdsArr){
+            if(videoId.equals(requestParam.getVideoId()+"")){
+                if(requestParam.getAppType().equals(0)
+                        ||requestParam.getAppType().equals(4)
+                        ||requestParam.getAppType().equals(5)
+                        ||requestParam.getAppType().equals(21)
+                ){
+                    Map<String,Object> result=new HashMap<>();
+                    result.put("ad_predict", 1);
+                    result.put("no_ad_strategy", "no_ad_with_video_in_white_list");
+                    return result;
                 }
             }
-        } catch (Exception e) {
-            log.error("adPredict hit error", e);
         }
 
-        if (adPredictBreakSwitch || isHit) {
-            return adPredictNew(requestParam);
-        } else {
-            return adPredictOld(requestParam);
-        }
-    }
-
-    public Map<String, Object> adPredictNew(ThresholdPredictModelRequestParam requestParam) {
-        JSONObject object=requestParam.getAbExpInfo();
-        //临时解决方案
-        List<Map<String,Object>> mapList=(List)requestParam.getAbExpInfo().get("ab_test002");
-        Map<String,List<JSONObject>> configMap=new HashMap<>();
-        for(Map<String,Object> map:mapList){
-            if("555".equals(map.getOrDefault("abExpCode",""))){
-                configMap=JSONObject.parseObject(map.get("configValue").toString(),Map.class);
-                break;
-            }
-        }
         //先判断是否开启实验 和是否不出广告时间 而后判断默认0-8
+        //不出广告时间判定
         Map<String,Object> result=new HashMap<>();
-        int hourOfDay= DateUtils.getCurrentHour();
-        Boolean condition1=abTestConfigContainer.inAdTimeTest(requestParam.getAbExpInfo());
-        Boolean condition2=abTestConfigContainer.containsCode(configMap,requestParam.getAbTestCode());
-
-
-        if(condition1
-                &&
-                condition2
-                &&
-                abTestConfigContainer.inWithoutAdTime(configMap,requestParam.getAbTestCode(),hourOfDay)){
-            result.put("ad_predict", 1);
-            result.put("no_ad_strategy", "no_ad_time_with_time_plan");
-            return result;
-        } else if (
-                (!condition1 || (condition1 && !condition2))
-                        &&
-                        (0 <= hourOfDay && hourOfDay < 8)) {
-            result.put("ad_predict", 1);
-            result.put("no_ad_strategy", "no_ad_time_with_fixed_time");
-            return result;
-        }
-
-
-        String[] abParamArr = abConfig.getAbParams(requestParam.getAbTestCode(), requestParam.getAbExpInfo());
-        if (abParamArr == null) {
-            result.put("msg", "abConfig_error");
-            return result;
-        }
-        String abtestId = abParamArr[0];
-        String abTestConfigTag = abParamArr[1];
-
-        if("173".equals(abtestId)&&(requestParam.getAbTestCode().equals("ab3")||requestParam.getAbTestCode().equals("ab4"))){
-            requestParam.setAbTestCode("ab5");
-        }
-        if("243".equals(abtestId)&&(requestParam.getAbTestCode().equals("ab1")||requestParam.getAbTestCode().equals("ab2")||requestParam.getAbTestCode().equals("ab3"))){
-            requestParam.setAbTestCode("ab5");
-        }
-
-        HashMap<String, Map<String, Object>> abConfigMap = abConfig.getAbConfigMap();
-        Map<String, Object> abtestParam = abConfigMap.getOrDefault(abtestId + "-" + abTestConfigTag, null);
-        if (abtestParam == null) {
-            result.put("msg", "abConfig_error");
-            return result;
-        }
-        //市-中文
-        requestParam.setRegion(requestParam.getRegion().replace("省", ""));
-        requestParam.setCity(requestParam.getCity().replace("市", ""));
-
-
-        // Determine the group to which mid belongs
-        String groupClassKey = (String) abtestParam.get("group_class_key");
-        String midGroupKeyName = RuleRedisKeyConst.KEY_NAME_PREFIX_MID_GROUP + groupClassKey + ":" + requestParam.getMid();
-        String midGroup = redisHelper.getString(midGroupKeyName);
-        if (midGroup == null) {
-            midGroup = "mean_group";
-        }
-
-        String[] noAdMidGroupList = new String[0];
-        noAdMidGroupList = ((JSONArray) abtestParam.get("no_ad_mid_group_list")).toArray(noAdMidGroupList);
-
-        boolean inNoAdGroup = false;
-        for (String group : noAdMidGroupList) {
-            if (group.equals(midGroup)) {
-                inNoAdGroup = true;
-                break;
-            }
-        }
-        //不出广告组
-        if (inNoAdGroup) {
-            // User is in the no-ad group, no ad should be shown
-            result.put("mid_group", midGroup);
-            result.put("ad_predict", 1);
-            result.put("no_ad_strategy", "no_ad_mid_group_with_video");
-            return result;
-        }
-
-        //top1广告不出视频
-        Map<String, List<String>> noAdGroupWithVideoMapping = (Map) abtestParam.getOrDefault("no_ad_group_with_video_mapping", new HashMap<>());
-        if (noAdGroupWithVideoMapping.keySet().contains(midGroup)
-                &&
-                topOneVideoContainer.inNoAdTopVideo(requestParam.getAppType().longValue(), requestParam.getVideoId())
-        ) {
-            result.put("mid_group", midGroup);
-            result.put("ad_predict", 1);
-            result.put("no_ad_strategy", "no_ad_mid_group_with_video");
-            return result;
-        }
-
-        //设置信息
-        ThresholdPredictModelParam modelParam = ThresholdPredictModelParam.builder()
-                .build();
-        BeanUtils.copyProperties(requestParam, modelParam);
-        modelParam.setDate(new Date());
-        modelParam.setAbtestId(abtestId);
-        modelParam.setAbTestConfigTag(abTestConfigTag);
-        modelParam.setAbtestParam(abtestParam);
-        modelParam.setMidGroup(midGroup);
-        result = ThresholdModelContainer.
-                getThresholdPredictModel("modelV2")
-                .predict(modelParam);
-
-        return result;
-    }
-
-    public Map<String, Object> adPredictOld(ThresholdPredictModelRequestParam requestParam) {
-
-        JSONObject object=requestParam.getAbExpInfo();
-        //临时解决方案
         List<Map<String,Object>> mapList=(List)requestParam.getAbExpInfo().get("ab_test002");
         Map<String,List<JSONObject>> configMap=new HashMap<>();
+        //该用户所有实验合集
+        Set<String> expCodes=new HashSet<>();
+        boolean isHit = false;
         for(Map<String,Object> map:mapList){
-            if("555".equals(map.getOrDefault("abExpCode",""))){
+            String expCode=map.getOrDefault("abExpCode","").toString();
+            expCodes.add(expCode);
+            if("555".equals(expCode)){
                 configMap=JSONObject.parseObject(map.get("configValue").toString(),Map.class);
-                break;
+            }
+            //判断570是否命中
+            if (StringUtils.equals(expCode, adPredictBreakExpCode)) {
+                isHit = true;
             }
         }
-        //先判断是否开启实验 和是否不出广告时间 而后判断默认0-8
-        Map<String,Object> result=new HashMap<>();
+
         int hourOfDay= DateUtils.getCurrentHour();
         Boolean condition1=abTestConfigContainer.inAdTimeTest(requestParam.getAbExpInfo());
         Boolean condition2=abTestConfigContainer.containsCode(configMap,requestParam.getAbTestCode());
-
-
         if(condition1
                 &&
                 condition2
@@ -239,6 +121,26 @@ public class PredictModelServiceImpl implements PredictModelService {
             return result;
         }
 
+        //人群选择算法判定-570
+//        try {
+//            JSONObject object = requestParam.getAbExpInfo();
+//            if (object != null) {
+//                JSONArray array = object.getJSONArray("ab_test002");
+//                if (array != null) {
+//                    List<Map<String, String>> abExps = JSONUtils.fromJson(array.toJSONString(),
+//                            new TypeToken<List<Map<String, String>>>() {
+//                            }, Collections.emptyList());
+//                    for (Map<String, String> abExpMap : abExps) {
+//                        if (StringUtils.equals(abExpMap.get("abExpCode"), adPredictBreakExpCode)) {
+//                            isHit = true;
+//                            break;
+//                        }
+//                    }
+//                }
+//            }
+//        } catch (Exception e) {
+//            log.error("adPredict hit error", e);
+//        }
 
         String[] abParamArr = abConfig.getAbParams(requestParam.getAbTestCode(), requestParam.getAbExpInfo());
         if (abParamArr == null) {
@@ -247,13 +149,12 @@ public class PredictModelServiceImpl implements PredictModelService {
         }
         String abtestId = abParamArr[0];
         String abTestConfigTag = abParamArr[1];
-        if("173".equals(abtestId)&&(requestParam.getAbTestCode().equals("ab3")||requestParam.getAbTestCode().equals("ab4"))){
-            requestParam.setAbTestCode("ab5");
-        }
-        if("243".equals(abtestId)&&(requestParam.getAbTestCode().equals("ab1")||requestParam.getAbTestCode().equals("ab2")||requestParam.getAbTestCode().equals("ab3"))){
-            requestParam.setAbTestCode("ab5");
-        }
-
+//        if("173".equals(abtestId)&&(requestParam.getAbTestCode().equals("ab3")||requestParam.getAbTestCode().equals("ab4"))){
+//            requestParam.setAbTestCode("ab5");
+//        }
+//        if("243".equals(abtestId)&&(requestParam.getAbTestCode().equals("ab1")||requestParam.getAbTestCode().equals("ab2")||requestParam.getAbTestCode().equals("ab3"))){
+//            requestParam.setAbTestCode("ab5");
+//        }
 
         HashMap<String, Map<String, Object>> abConfigMap = abConfig.getAbConfigMap();
         Map<String, Object> abtestParam = abConfigMap.getOrDefault(abtestId + "-" + abTestConfigTag, null);
@@ -265,13 +166,15 @@ public class PredictModelServiceImpl implements PredictModelService {
         requestParam.setRegion(requestParam.getRegion().replace("省", ""));
         requestParam.setCity(requestParam.getCity().replace("市", ""));
 
-
         // Determine the group to which mid belongs
         String groupClassKey = (String) abtestParam.get("group_class_key");
         String midGroupKeyName = RuleRedisKeyConst.KEY_NAME_PREFIX_MID_GROUP + groupClassKey + ":" + requestParam.getMid();
+        //没有时为新用户或者无分享用户
         String midGroup = redisHelper.getString(midGroupKeyName);
+        String shareType =midGroup;
         if (midGroup == null) {
             midGroup = "mean_group";
+            shareType="noShare";
         }
 
         String[] noAdMidGroupList = new String[0];
@@ -314,10 +217,33 @@ public class PredictModelServiceImpl implements PredictModelService {
         modelParam.setAbTestConfigTag(abTestConfigTag);
         modelParam.setAbtestParam(abtestParam);
         modelParam.setMidGroup(midGroup);
-        Object thresholdMixFunc = abtestParam.getOrDefault("threshold_mix_func", "basic");
-        result = ThresholdModelContainer.
-                getThresholdPredictModel(thresholdMixFunc.toString())
-                .predict(modelParam);
+        modelParam.setExtraParam(new HashMap<>());
+        modelParam.addUserExtraFuture("shareType",shareType);
+        setExtraParam(modelParam);
+        if(expCodes.contains("599")){
+            result = ThresholdModelContainer.
+                    getThresholdPredictModel("random")
+                    .predict(modelParam);
+        } else if (adPredictBreakSwitch || isHit) {
+            if(expCodes.contains(adPredictNoShareUserExpCode)&&"noShare".equals(shareType)){
+                result = ThresholdModelContainer.
+                        getThresholdPredictModel("share0")
+                        .predict(modelParam);
+            }else if(expCodes.contains(adPredictNoShareUserExpCode)&&"return25_nmids".equals(shareType)){
+                result.put("mid_group", midGroup);
+                result.put("ad_predict", 1);
+                result.put("no_ad_strategy", adPredictNoShareUserExpCode+"_"+midGroup);
+            }else {
+                result = ThresholdModelContainer.
+                        getThresholdPredictModel("modelV2")
+                        .predict(modelParam);
+            }
+        } else {
+            Object thresholdMixFunc = abtestParam.getOrDefault("threshold_mix_func", "basic");
+            result = ThresholdModelContainer.
+                    getThresholdPredictModel(thresholdMixFunc.toString())
+                    .predict(modelParam);
+        }
 
         return result;
     }
@@ -350,4 +276,26 @@ public class PredictModelServiceImpl implements PredictModelService {
                 .predict(modelParam);
     }
 
+    public void setExtraParam(ThresholdPredictModelParam modelParam){
+        String[] ids=testIds.split(",");
+        List<String> idList=Arrays.asList(ids);
+        List<Map<String,Object>> mapList=(List)modelParam.getAbExpInfo().get("ab_test002");
+        Collections.sort(mapList,new Comparator<Map<String, Object>>() {
+            @Override
+            public int compare(Map<String, Object> map1, Map<String, Object> map2) {
+                int abExpCode1 =Integer.parseInt(map1.get("abExpCode").toString()) ;
+                int abExpCode2 =Integer.parseInt(map2.get("abExpCode").toString());
+                return Integer.compare(abExpCode1, abExpCode2);
+            }
+        });
+        Map<String,Object> configMap;
+        for(Map<String,Object> map:mapList){
+            if(idList.contains(map.getOrDefault("abExpCode",""))){
+                configMap=JSONObject.parseObject(map.get("configValue").toString(),new TypeReference<Map<String,Object>>(){});
+                for(Map.Entry<String,Object> entry:configMap.entrySet()){
+                    modelParam.getExtraParam().put(entry.getKey(),entry.getValue());
+                }
+            }
+        }
+    }
 }

+ 10 - 1
ad-engine-service/src/main/java/com/tzld/piaoquan/ad/engine/service/predict/model/threshold/AddThresholdPredictModel.java

@@ -2,8 +2,9 @@ package com.tzld.piaoquan.ad.engine.service.predict.model.threshold;
 
 
 import com.tzld.piaoquan.ad.engine.commons.redis.AlgorithmRedisHelper;
+import com.tzld.piaoquan.ad.engine.commons.util.TimerWatchUtil;
 import com.tzld.piaoquan.ad.engine.service.predict.calculator.ThresholdPredictCalculator;
-import com.tzld.piaoquan.ad.engine.service.predict.param.RuleParamHelper;
+import com.tzld.piaoquan.ad.engine.service.predict.helper.RuleParamHelper;
 import com.tzld.piaoquan.ad.engine.service.predict.param.ThresholdCalculateParam;
 import com.tzld.piaoquan.ad.engine.service.predict.param.ThresholdPredictModelParam;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -30,14 +31,19 @@ public class AddThresholdPredictModel extends ThresholdPredictModel {
     }
     @Override
     public Map<String, Object> predict(ThresholdPredictModelParam modelParam) {
+
         Map<String, Object> result = new HashMap<>();
         // Get group and video share rates
         Double groupShareRate = paramHelper.getGroupShareRate(modelParam.getAbtestParam(),modelParam.getDate(), modelParam.getMidGroup());
+
         Double videoShareRate = paramHelper.getVideoShareRate(modelParam.getAbtestParam(), modelParam.getDate(),modelParam.getVideoId());
+
         // Get group and video out rates
         Double groupOutRate = paramHelper.getGroupOutRate(modelParam.getAbtestParam(),modelParam.getDate(),modelParam.getMidGroup());
+
         Double videoOutRate = paramHelper.getVideoOutRate(modelParam.getAbtestParam(), modelParam.getDate(),modelParam.getVideoId());
 
+
         // Calculate mid-video prediction result
         if (groupShareRate == null || videoShareRate == null || groupOutRate == null || videoOutRate == null) {
             return null;
@@ -52,6 +58,7 @@ public class AddThresholdPredictModel extends ThresholdPredictModel {
                 .shareWeight(shareWeight).outWeight(outWeight).build();
         double midVideoPredictRes = ThresholdPredictCalculator.addWeightCalculate(calculateParam);
 
+
         // Get the threshold
         double threshold = paramHelper.getThreshold(
                 modelParam.getAbtestId(),
@@ -61,6 +68,7 @@ public class AddThresholdPredictModel extends ThresholdPredictModel {
                 modelParam.getCareModelStatus(),
                 modelParam.getAbtestParam()
         );
+
         // Threshold check
         int adPredict=midVideoPredictRes > threshold?2:1;
         result.put("mid_group", modelParam.getMidGroup());
@@ -74,6 +82,7 @@ public class AddThresholdPredictModel extends ThresholdPredictModel {
         result.put("mid_video_predict_res", midVideoPredictRes);
         result.put("threshold", threshold);
         result.put("ad_predict", adPredict);
+
         return result;
     }
 }

+ 7 - 1
ad-engine-service/src/main/java/com/tzld/piaoquan/ad/engine/service/predict/model/threshold/BasicThresholdPredictModel.java

@@ -1,8 +1,9 @@
 package com.tzld.piaoquan.ad.engine.service.predict.model.threshold;
 
 import com.tzld.piaoquan.ad.engine.commons.redis.AlgorithmRedisHelper;
+import com.tzld.piaoquan.ad.engine.commons.util.TimerWatchUtil;
 import com.tzld.piaoquan.ad.engine.service.predict.calculator.ThresholdPredictCalculator;
-import com.tzld.piaoquan.ad.engine.service.predict.param.RuleParamHelper;
+import com.tzld.piaoquan.ad.engine.service.predict.helper.RuleParamHelper;
 import com.tzld.piaoquan.ad.engine.service.predict.param.ThresholdCalculateParam;
 import com.tzld.piaoquan.ad.engine.service.predict.param.ThresholdPredictModelParam;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -34,8 +35,10 @@ public class BasicThresholdPredictModel extends ThresholdPredictModel{
 
 //        Double groupShareRate=paramHelper.getGroupShareRate(modelParam.getAbtestParam(),modelParam.getDate(),midGroup);
         Double groupShareRate=paramHelper.getGroupShareRateForBasic(modelParam.getAbtestParam(),modelParam.getDate(),midGroup);
+
 //        Double videoShareRate=paramHelper.getVideoShareRate(modelParam.getAbtestParam(),modelParam.getDate(),modelParam.getVideoId());
         Double videoShareRate=paramHelper.getVideoShareRateForBasic(modelParam.getAbtestParam(),modelParam.getDate(),modelParam.getVideoId());
+
         double threshold = paramHelper.getThreshold(
                 modelParam.getAbtestId(),
                 modelParam.getAbTestConfigTag(),
@@ -44,11 +47,13 @@ public class BasicThresholdPredictModel extends ThresholdPredictModel{
                 modelParam.getCareModelStatus(),
                 modelParam.getAbtestParam()
         );
+
         ThresholdCalculateParam calculateParam=ThresholdCalculateParam.builder()
                 .groupShareRate(groupShareRate)
                 .videoShareRate(videoShareRate).build();
 
         Double midVideoPredictRes=ThresholdPredictCalculator.basicCalculate(calculateParam);
+
         int adPredict=midVideoPredictRes > threshold?2:1;
         Map<String, Object> result=new HashMap<>();
         result.put("mid_group", midGroup);
@@ -57,6 +62,7 @@ public class BasicThresholdPredictModel extends ThresholdPredictModel{
         result.put("mid_video_predict_res", midVideoPredictRes);
         result.put("threshold", threshold);
         result.put("ad_predict", adPredict);
+
         return result;
     }
 }

+ 7 - 1
ad-engine-service/src/main/java/com/tzld/piaoquan/ad/engine/service/predict/model/threshold/MultiplyThresholdPredictModel.java

@@ -1,8 +1,9 @@
 package com.tzld.piaoquan.ad.engine.service.predict.model.threshold;
 
 import com.tzld.piaoquan.ad.engine.commons.redis.AlgorithmRedisHelper;
+import com.tzld.piaoquan.ad.engine.commons.util.TimerWatchUtil;
 import com.tzld.piaoquan.ad.engine.service.predict.calculator.ThresholdPredictCalculator;
-import com.tzld.piaoquan.ad.engine.service.predict.param.RuleParamHelper;
+import com.tzld.piaoquan.ad.engine.service.predict.helper.RuleParamHelper;
 import com.tzld.piaoquan.ad.engine.service.predict.param.ThresholdCalculateParam;
 import com.tzld.piaoquan.ad.engine.service.predict.param.ThresholdPredictModelParam;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -29,13 +30,17 @@ public class MultiplyThresholdPredictModel  extends ThresholdPredictModel{
 
     @Override
     public Map<String, Object> predict(ThresholdPredictModelParam modelParam) {
+
         Map<String, Object> result = new HashMap<>();
 
         // Get group and video share rates
         Double groupShareRate = paramHelper.getGroupShareRate(modelParam.getAbtestParam(),modelParam.getDate(),modelParam.getMidGroup());
+
         Double videoShareRate = paramHelper.getVideoShareRate(modelParam.getAbtestParam(), modelParam.getDate(),modelParam.getVideoId());
+
         // Get group and video out rates
         Double groupOutRate = paramHelper.getGroupOutRate(modelParam.getAbtestParam(),modelParam.getDate(),modelParam.getMidGroup());
+
         Double videoOutRate = paramHelper.getVideoOutRate(modelParam.getAbtestParam(), modelParam.getDate(),modelParam.getVideoId());
 
         // Calculate mid-video prediction result
@@ -58,6 +63,7 @@ public class MultiplyThresholdPredictModel  extends ThresholdPredictModel{
                 modelParam.getCareModelStatus(),
                 modelParam.getAbtestParam()
         );
+
         // Threshold check
         int adPredict=midVideoPredictRes > threshold?2:1;
 //            if (midVideoPredictRes > threshold) {

+ 65 - 0
ad-engine-service/src/main/java/com/tzld/piaoquan/ad/engine/service/predict/model/threshold/NoShareUserThresholdPredictModel.java

@@ -0,0 +1,65 @@
+package com.tzld.piaoquan.ad.engine.service.predict.model.threshold;
+
+import com.alibaba.fastjson.JSONObject;
+import com.tzld.piaoquan.ad.engine.commons.score.AdConfig;
+import com.tzld.piaoquan.ad.engine.commons.score.ScoreParam;
+import com.tzld.piaoquan.ad.engine.commons.score.ScorerUtils;
+import com.tzld.piaoquan.ad.engine.commons.util.CommonCollectionUtils;
+import com.tzld.piaoquan.ad.engine.service.predict.container.PredictPidContainer;
+import com.tzld.piaoquan.ad.engine.service.predict.container.RandWContainer;
+import com.tzld.piaoquan.ad.engine.service.predict.container.ThresholdModelContainer;
+import com.tzld.piaoquan.ad.engine.service.predict.param.ThresholdPredictModelParam;
+import com.tzld.piaoquan.ad.engine.service.remote.FeatureRemoteService;
+import com.tzld.piaoquan.recommend.feature.domain.ad.base.AdRankItem;
+import com.tzld.piaoquan.recommend.feature.domain.ad.base.AdRequestContext;
+import com.tzld.piaoquan.recommend.feature.domain.ad.base.UserAdFeature;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.PostConstruct;
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Random;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+
+import static com.tzld.piaoquan.ad.engine.commons.score.ScorerUtils.BREAK_CONFIG;
+import static com.tzld.piaoquan.ad.engine.commons.score.ScorerUtils.SHARE0_CONFIG;
+
+@Component
+public class NoShareUserThresholdPredictModel extends ThresholdPredictModel {
+    private final static Logger log = LoggerFactory.getLogger(NoShareUserThresholdPredictModel.class);
+
+    @Value("${ad.predict.threshold.share0:0.4}")
+    private double threshold;
+    @Value("${ad.model.pid.type.share0:-1}")
+    private double pidType;
+
+
+    @Override
+    String initName() {
+        return "share0";
+    }
+
+    @Override
+    public Map<String, Object> predict(ThresholdPredictModelParam modelParam) {
+
+        double score=(modelParam.getMid().hashCode()+ RandWContainer.getRandW())%100/100d;
+        score=score<0?-score:score;
+
+        Map<String, Object> result = new HashMap<>();
+//        result.put("threshold", realThreshold);
+//        result.put("score", maxItem == null ? -1 : maxItem.getScore());
+        result.put("ad_predict", score<threshold?2:1);
+        result.put("score", score);
+
+        return result;
+    }
+}

+ 50 - 0
ad-engine-service/src/main/java/com/tzld/piaoquan/ad/engine/service/predict/model/threshold/RandomPredictModel.java

@@ -0,0 +1,50 @@
+package com.tzld.piaoquan.ad.engine.service.predict.model.threshold;
+
+import com.tzld.piaoquan.ad.engine.service.predict.container.RandWContainer;
+import com.tzld.piaoquan.ad.engine.service.predict.param.ThresholdPredictModelParam;
+import com.tzld.piaoquan.ad.engine.service.remote.FeatureRemoteService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.PostConstruct;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Random;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+
+@Component
+public class RandomPredictModel extends ThresholdPredictModel {
+    private final static Logger log = LoggerFactory.getLogger(RandomPredictModel.class);
+
+    @Override
+    String initName() {
+        return "random";
+    }
+
+
+    @Override
+    public Map<String, Object> predict(ThresholdPredictModelParam modelParam) {
+        int hash=modelParam.getMid().hashCode();
+        hash=hash<0?-hash:hash;
+        double score=(hash+ RandWContainer.getRandW())%100/100d;
+        double threshold=Double.parseDouble(
+                modelParam.getExtraParam().getOrDefault(modelParam.getAppType()+"_"+modelParam.getUserExtraFuture("shareType"),-1
+                ).toString());
+        if(threshold<0d){
+            threshold=Double.parseDouble(
+                    modelParam.getExtraParam().getOrDefault("default_threshold","0.5")
+                    .toString());
+        }
+        Map<String, Object> result = new HashMap<>();
+        result.put("ad_predict", score<threshold?2:1);
+        result.put("score", score);
+
+        return result;
+    }
+
+}

+ 2 - 1
ad-engine-service/src/main/java/com/tzld/piaoquan/ad/engine/service/predict/model/threshold/RoiThresholdPredictModel.java

@@ -6,7 +6,7 @@ import com.tzld.piaoquan.ad.engine.service.predict.config.RoiModelConfig;
 import com.tzld.piaoquan.ad.engine.service.predict.constant.RuleRedisKeyConst;
 import com.tzld.piaoquan.ad.engine.service.predict.container.RoiPredictParamContainer;
 import com.tzld.piaoquan.ad.engine.service.predict.param.RoiThresholdPredictModelParam;
-import com.tzld.piaoquan.ad.engine.service.predict.param.RuleParamHelper;
+import com.tzld.piaoquan.ad.engine.service.predict.helper.RuleParamHelper;
 import com.tzld.piaoquan.ad.engine.service.predict.param.ThresholdPredictModelParam;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
@@ -37,6 +37,7 @@ public class RoiThresholdPredictModel extends ThresholdPredictModel{
     RoiModelConfig roiModelConfig;
     @Override
     public <T extends ThresholdPredictModelParam> Map<String, Object> predict(T param) {
+
         RoiThresholdPredictModelParam modelParam=(RoiThresholdPredictModelParam)param;
         Date previousDate = new Date(modelParam.getDate().getTime() - (24 * 60 * 60 * 1000)); // Subtract one day
         String nowDt = new SimpleDateFormat("yyyyMMdd").format(modelParam.getDate());

+ 8 - 1
ad-engine-service/src/main/java/com/tzld/piaoquan/ad/engine/service/predict/model/threshold/ScoreThresholdPredictModel.java

@@ -2,10 +2,11 @@ package com.tzld.piaoquan.ad.engine.service.predict.model.threshold;
 
 import com.alibaba.fastjson.JSONObject;
 import com.tzld.piaoquan.ad.engine.commons.redis.AlgorithmRedisHelper;
+import com.tzld.piaoquan.ad.engine.commons.util.TimerWatchUtil;
 import com.tzld.piaoquan.ad.engine.service.predict.config.AdOutV1OnlineWeightConfig;
 import com.tzld.piaoquan.ad.engine.service.predict.constant.RuleRedisKeyConst;
 import com.tzld.piaoquan.ad.engine.service.predict.container.ThresholdModelContainer;
-import com.tzld.piaoquan.ad.engine.service.predict.param.RuleParamHelper;
+import com.tzld.piaoquan.ad.engine.service.predict.helper.RuleParamHelper;
 import com.tzld.piaoquan.ad.engine.service.predict.param.ThresholdPredictModelParam;
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -36,8 +37,10 @@ public class ScoreThresholdPredictModel extends ThresholdPredictModel{
         String itemKeyName = RuleRedisKeyConst.KEY_NAME_PREFIX_AD_OUT_MODEL_SCORE_ITEM + modelKey + ":" + modelParam.getVideoId();
 
         String userScore = redisHelper.get(userKeyName);
+
         String itemScore = redisHelper.get(itemKeyName);
 
+
         //加载配置数据
         String configKeyNamePrefix = RuleRedisKeyConst.KEY_NAME_PREFIX_AD_OUT_MODEL_CONFIG
                 + modelKey + ":" + modelParam.getAbtestId() + ":"
@@ -45,6 +48,7 @@ public class ScoreThresholdPredictModel extends ThresholdPredictModel{
                 + modelParam.getAbtestParam().get("abtest_config_tag");
         String configKey = configKeyNamePrefix + ":config";
         String configStr = redisHelper.get(configKey);
+
         Map<String, Object> configMap = new HashMap<>();
         String hitStrategy="model";
         if (configStr != null) {
@@ -97,6 +101,7 @@ public class ScoreThresholdPredictModel extends ThresholdPredictModel{
                     (double)configMap.getOrDefault("user_threshold", 0);
             hitStrategy=isUserScoreBlank?"item":"user";
         }
+
         //获取计算参数
         SimpleDateFormat hourFormat = new SimpleDateFormat("HH");
         SimpleDateFormat weekDayFormat = new SimpleDateFormat("u");
@@ -114,6 +119,7 @@ public class ScoreThresholdPredictModel extends ThresholdPredictModel{
                 rankScore = Double.parseDouble(rankScoreStr);
             }
         }
+
         offlineScore=Double.parseDouble(userScore) + Double.parseDouble(itemScore);
         double onlineScore=getOlineScore(onlineFeatures);
         double rankScoreBias = (double)configMap.getOrDefault("rank_score_bias", 0.0);
@@ -131,6 +137,7 @@ public class ScoreThresholdPredictModel extends ThresholdPredictModel{
             // Otherwise, do not show the ad
             adPredict = 1;
         }
+
         result=new HashMap<>();
         result.put("user_score", userScore);
         result.put("item_score", itemScore);

+ 39 - 4
ad-engine-service/src/main/java/com/tzld/piaoquan/ad/engine/service/predict/model/threshold/ScoreV2ThresholdPredictModel.java

@@ -1,14 +1,22 @@
 package com.tzld.piaoquan.ad.engine.service.predict.model.threshold;
 
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
 import com.tzld.piaoquan.ad.engine.commons.score.AdConfig;
 import com.tzld.piaoquan.ad.engine.commons.score.ScoreParam;
 import com.tzld.piaoquan.ad.engine.commons.score.ScorerUtils;
 import com.tzld.piaoquan.ad.engine.commons.util.CommonCollectionUtils;
+import com.tzld.piaoquan.ad.engine.commons.util.TimerWatchUtil;
+import com.tzld.piaoquan.ad.engine.service.predict.container.PredictPidContainer;
+import com.tzld.piaoquan.ad.engine.service.predict.container.ThresholdModelContainer;
+import com.tzld.piaoquan.ad.engine.service.predict.impl.PredictModelServiceImpl;
 import com.tzld.piaoquan.ad.engine.service.predict.param.ThresholdPredictModelParam;
 import com.tzld.piaoquan.ad.engine.service.remote.FeatureRemoteService;
 import com.tzld.piaoquan.recommend.feature.domain.ad.base.AdRankItem;
 import com.tzld.piaoquan.recommend.feature.domain.ad.base.AdRequestContext;
 import com.tzld.piaoquan.recommend.feature.domain.ad.base.UserAdFeature;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Component;
@@ -23,12 +31,14 @@ import static com.tzld.piaoquan.ad.engine.commons.score.ScorerUtils.BREAK_CONFIG
 
 @Component
 public class ScoreV2ThresholdPredictModel extends ThresholdPredictModel {
-
+    private final static Logger log = LoggerFactory.getLogger(ScoreV2ThresholdPredictModel.class);
     @Autowired
     private FeatureRemoteService featureRemoteService;
 
     @Value("${ad.predict.threshold:1}")
     private double threshold;
+    @Value("${ad.model.pid.type:0.0}")
+    private double pidType;
 
     @Override
     String initName() {
@@ -65,7 +75,7 @@ public class ScoreV2ThresholdPredictModel extends ThresholdPredictModel {
         scoreParam.setUid("");
         scoreParam.setProvince(modelParam.getRegion());
         scoreParam.setCity(modelParam.getCity());
-
+        scoreParam.setExtraParam(modelParam.getExtraParam());
 
         List<AdRankItem> scoreResult = ScorerUtils
                 .getScorerPipeline(BREAK_CONFIG)
@@ -83,18 +93,43 @@ public class ScoreV2ThresholdPredictModel extends ThresholdPredictModel {
             }
         }
 
+        double realThreshold=Double.parseDouble(
+                scoreParam.getExtraParam().getOrDefault("ScoreV2ThresholdPredict_"+modelParam.getAppType(),threshold).toString()
+        );
         int adPredict;
-        if (maxItem != null && maxItem.getScore() < threshold) {
+        //加入pid逻辑
+        if(pidType>1){
+            realThreshold=realThreshold+ PredictPidContainer.getPidLambda(
+                    scoreParam.getExtraParam().getOrDefault("predict_test_id","default")+"_"+modelParam.getAppType());
+        }else if(pidType>=0){
+            realThreshold=PredictPidContainer.getLatestThreshold(
+                    scoreParam.getExtraParam().getOrDefault("predict_test_id","default")+"_"+modelParam.getAppType());
+        }
+
+
+        if (maxItem != null && maxItem.getScore() < realThreshold) {
             // If final score is below threshold, do not show the ad
             adPredict = 1;
         } else {
             // Otherwise, show the ad
             adPredict = 2;
         }
+        if(maxItem != null){
+            ThresholdModelContainer.mergingDigestAddScore(modelParam.getAppType(),maxItem.getScore());
+            //删除多余打印
+            maxItem.setItemFeature(null);
+            maxItem.setLrSampleString(null);
+            maxItem.setLrSampleStringOrgin(null);
+            log.info("svc=ScoreV2ThresholdPredictModel_predict modelName=ScoreV2ThresholdPredictModel maxItem={} extraParam={} app_type={} realThreshold={}",
+                    JSONObject.toJSONString(maxItem), JSONObject.toJSONString(scoreParam.getExtraParam()),modelParam.getAppType(),realThreshold);
+        }
+
         Map<String, Object> result = new HashMap<>();
-        result.put("threshold", threshold);
+        result.put("threshold", realThreshold);
         result.put("score", maxItem == null ? -1 : maxItem.getScore());
         result.put("ad_predict", adPredict);
+
+
         return result;
     }
 }

+ 17 - 0
ad-engine-service/src/main/java/com/tzld/piaoquan/ad/engine/service/predict/param/ThresholdPredictModelParam.java

@@ -6,8 +6,10 @@ import lombok.AllArgsConstructor;
 import lombok.Builder;
 import lombok.Data;
 import lombok.NoArgsConstructor;
+import org.apache.poi.ss.formula.functions.T;
 
 import java.util.Date;
+import java.util.HashMap;
 import java.util.Map;
 
 /**
@@ -40,4 +42,19 @@ public class ThresholdPredictModelParam {
     String city = "-1";
     MachineInfoParam machineInfo = new MachineInfoParam();
 
+    Map<String,Object> extraParam=new HashMap<>();
+    Map<String,Object> userExtraFutureMap=new HashMap<>();
+
+    public void addUserExtraFuture(String key,Object val){
+        if(userExtraFutureMap!=null){
+            userExtraFutureMap.put(key,val);
+        }
+    }
+
+    public T getUserExtraFuture(String key){
+        if(userExtraFutureMap!=null){
+            return (T)userExtraFutureMap.getOrDefault(key,new T());
+        }
+        return null;
+    }
 }

+ 48 - 0
ad-engine-service/src/main/java/com/tzld/piaoquan/ad/engine/service/score/Share0MergeBreakScorer.java

@@ -0,0 +1,48 @@
+package com.tzld.piaoquan.ad.engine.service.score;
+
+
+import com.tzld.piaoquan.ad.engine.commons.score.BaseLRModelScorer;
+import com.tzld.piaoquan.ad.engine.commons.score.ScoreParam;
+import com.tzld.piaoquan.ad.engine.commons.score.ScorerConfigInfo;
+import com.tzld.piaoquan.recommend.feature.domain.ad.base.AdRankItem;
+import com.tzld.piaoquan.recommend.feature.domain.ad.base.UserAdFeature;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.math.BigDecimal;
+import java.util.Collections;
+import java.util.List;
+
+
+//@Service
+public class Share0MergeBreakScorer extends BaseLRModelScorer {
+
+    private final static Logger log = LoggerFactory.getLogger(Share0MergeBreakScorer.class);
+
+
+    public Share0MergeBreakScorer(ScorerConfigInfo configInfo) {
+        super(configInfo);
+    }
+
+
+    @Override
+    public List<AdRankItem> scoring(final ScoreParam param,
+                                    final UserAdFeature userFeature,
+                                    final List<AdRankItem> rankItems) {
+
+        for (AdRankItem item : rankItems) {
+           try {
+               item.setScore(item.getCtr()*item.getCvr()/(item.getStr()*item.getRos()*0.2));
+           }catch (Exception e){
+               item.setScore(0);
+           }
+        }
+        Collections.sort(rankItems);
+        return rankItems;
+    }
+
+    @Override
+    public void loadModel() {
+        // nothing;
+    }
+}

+ 11 - 7
ad-engine-service/src/main/java/com/tzld/piaoquan/ad/engine/service/score/VlogMergeBreakScorer.java

@@ -1,6 +1,7 @@
 package com.tzld.piaoquan.ad.engine.service.score;
 
 
+import com.alibaba.fastjson.JSONArray;
 import com.tzld.piaoquan.ad.engine.commons.score.BaseLRModelScorer;
 import com.tzld.piaoquan.ad.engine.commons.score.ScoreParam;
 import com.tzld.piaoquan.ad.engine.commons.score.ScorerConfigInfo;
@@ -17,7 +18,7 @@ import java.util.List;
 //@Service
 public class VlogMergeBreakScorer extends BaseLRModelScorer {
 
-    private final static Logger LOGGER = LoggerFactory.getLogger(VlogMergeBreakScorer.class);
+    private final static Logger log = LoggerFactory.getLogger(VlogMergeBreakScorer.class);
 
 
     public VlogMergeBreakScorer(ScorerConfigInfo configInfo) {
@@ -29,6 +30,12 @@ public class VlogMergeBreakScorer extends BaseLRModelScorer {
     public List<AdRankItem> scoring(final ScoreParam param,
                                     final UserAdFeature userFeature,
                                     final List<AdRankItem> rankItems) {
+        double a,b,c,strW,rosW;
+        a=Double.parseDouble(param.getExtraParam().getOrDefault("mergeBreakCtrCvrW",0.2).toString());
+        b=Double.parseDouble(param.getExtraParam().getOrDefault("mergeBreakStrRosW",1d).toString());
+        strW=Double.parseDouble(param.getExtraParam().getOrDefault("mergeBreakStrW",b).toString());
+        rosW=Double.parseDouble(param.getExtraParam().getOrDefault("mergeBreakRosW",b).toString());
+        c=Double.parseDouble(param.getExtraParam().getOrDefault("mergeBreakW",1d).toString());
 
         for (AdRankItem item : rankItems) {
             double ctr = item.getCtr();
@@ -36,14 +43,11 @@ public class VlogMergeBreakScorer extends BaseLRModelScorer {
             double str = item.getStr();
             double ros = item.getRos();
 
-            double a = 0.2;
-            double b = 1.0;
-            double c = 1.0;
-
             BigDecimal ctrCvr = new BigDecimal(Math.pow(70 * ctr * cvr, a));
-            BigDecimal strRos = new BigDecimal(Math.pow(str * ros, b));
+            BigDecimal strBG = new BigDecimal(Math.pow(str, strW));
+            BigDecimal rosBG = new BigDecimal(Math.pow(ros, rosW));
             BigDecimal breakRate = new BigDecimal(Math.pow(item.getBreakRate(), c));
-            BigDecimal score = ctrCvr.divide(strRos.multiply(breakRate), 5, BigDecimal.ROUND_HALF_UP);
+            BigDecimal score = ctrCvr.divide(strBG.multiply(rosBG).multiply(breakRate), 5, BigDecimal.ROUND_HALF_UP);
 
             item.setScore(score.doubleValue());
         }

+ 47 - 27
ad-engine-service/src/main/java/com/tzld/piaoquan/ad/engine/service/score/VlogMergeEcpmScorer.java

@@ -6,20 +6,25 @@ import com.tzld.piaoquan.ad.engine.commons.score.ScoreParam;
 import com.tzld.piaoquan.ad.engine.commons.score.ScorerConfigInfo;
 import com.tzld.piaoquan.ad.engine.commons.score.model.LRModel;
 import com.tzld.piaoquan.recommend.feature.domain.ad.base.AdRankItem;
+import com.tzld.piaoquan.recommend.feature.domain.ad.base.AdRequestContext;
+import com.tzld.piaoquan.recommend.feature.domain.ad.base.UserAdBytesFeature;
 import com.tzld.piaoquan.recommend.feature.domain.ad.base.UserAdFeature;
+import org.apache.commons.lang.exception.ExceptionUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
+import java.util.concurrent.*;
 
 
 //@Service
 public class VlogMergeEcpmScorer extends BaseLRModelScorer {
 
     private final static Logger LOGGER = LoggerFactory.getLogger(VlogMergeEcpmScorer.class);
-
-
+    private static final ExecutorService executorService = Executors.newFixedThreadPool(128);
+    private static final int LOCAL_TIME_OUT = 150;
     public VlogMergeEcpmScorer(ScorerConfigInfo configInfo) {
         super(configInfo);
     }
@@ -40,36 +45,51 @@ public class VlogMergeEcpmScorer extends BaseLRModelScorer {
     }
 
 
-    public List<AdRankItem> mergetEcpm(List<AdRankItem> items) {
-
 
+    public List<AdRankItem> mergetEcpm(List<AdRankItem> items) {
+        CountDownLatch countDownLatch = new CountDownLatch(items.size());
         for (AdRankItem item : items) {
-            try {
-                boolean isTfType=item.getItemFeature().getCreative_7day_cnt_features().getAdView()<10000;
-                double cpa = item.getCpa();
-                double bid1 = item.getBid1();
-                double bid2 = item.getBid2();
-                double pctr = isTfType?item.getTf_ctr():item.getCtr();
-                double pcvr = isTfType?item.getTf_cvr():item.getCvr();
-                item.setScore_type( isTfType?1:0);
-                //todo
-                double ecpm;
-                if(isTfType){
-                    ecpm = cpa * bid1 * bid2 * pcvr * pctr * 1000d;
-                }else {
-                    ecpm = (cpa+item.getPidLambda()) * bid1 * bid2 * pcvr * pctr * 1000d;
-                }
-//                double ecpm = cpa * bid1 * bid2 * pcvr * pctr;
-                item.setEcpm1(ecpm/1000d);
-                item.setScore(ecpm/1000d);
-            } catch (Exception e) {
-                LOGGER.error("merge Ecpm Score: {} error", "");
-                item.setCtr(0.0);
-            }
-            LOGGER.debug("merge Ecpm ranker , score: {}->{}", item.getScore());
+            executorService.execute(() -> {
+                callMergeScore(item,countDownLatch);
+            });
+        }
+        try {
+            countDownLatch.await(200, TimeUnit.MILLISECONDS);
+        } catch (InterruptedException e) {
+            LOGGER.error("mergetEcpm countDownLatch error ...", e);
         }
         Collections.sort(items);
         return items;
     }
 
+
+    public void callMergeScore(AdRankItem item,CountDownLatch countDownLatch){
+        try {
+            boolean isTfType=item.getItemFeature().getCreative_7day_cnt_features().getAdView()<5000;
+            double cpa = item.getCpa();
+            double bid1 = item.getBid1();
+            double bid2 = item.getBid2();
+            double pctr = isTfType?item.getTf_ctr():item.getCtr();
+            double pcvr = isTfType?item.getTf_cvr():item.getCvr();
+            item.setScore_type( isTfType?1:0);
+            //todo
+            double ecpm;
+//            if(isTfType){
+//                ecpm = cpa * bid1 * bid2 * pcvr * pctr * 1000d;
+//            }else {
+//                ecpm = (cpa+item.getPidLambda()) * bid1 * bid2 * pcvr * pctr * 1000d;
+//            }
+            ecpm = cpa * bid1 * bid2 * pcvr * pctr * 1000d;
+
+//                double ecpm = cpa * bid1 * bid2 * pcvr * pctr;
+            item.setEcpm1(ecpm/1000d);
+            item.setScore(ecpm/1000d);
+//            item.setScore(ecpm);
+        } catch (Exception e) {
+            LOGGER.error("merge Ecpm Score: {} error", "");
+            item.setCtr(0.0);
+        }finally {
+            countDownLatch.countDown();
+        }
+    }
 }

+ 23 - 2
ad-engine-service/src/main/java/com/tzld/piaoquan/ad/engine/service/score/impl/RankServiceImpl.java

@@ -22,9 +22,11 @@ import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Service;
 import org.springframework.util.CollectionUtils;
 
+import javax.annotation.PostConstruct;
 import java.time.LocalDateTime;
 import java.time.format.DateTimeFormatter;
 import java.util.*;
+import java.util.concurrent.TimeUnit;
 import java.util.stream.Collectors;
 
 @Service
@@ -42,6 +44,13 @@ public class RankServiceImpl implements RankService {
     @Value("${ad.model.cpm.min:30}")
     Double cpmMin=30d;
 
+    static Map<String,Double> bidMap=new HashMap<>();
+    @PostConstruct
+    private void init(){
+        bidMap.put("42",200d);
+    }
+
+
     public AdRankItem adItemRank(RankRecommendRequestParam request){
         ScoreParam param= RequestConvert.requestConvert(request);
         LocalDateTime currentTime = LocalDateTime.now();
@@ -72,10 +81,21 @@ public class RankServiceImpl implements RankService {
             }
         }
         for(AdRankItem item:rankItems){
-            item.setBid1(1d);
+            item.setBid1(bidMap.getOrDefault(item.getItemFeature().getAdvertiserId(),1d));
+//            item.setBid1(1d);
             item.setBid2(1d);
+//            if(item.getAdId()==267) {
+//                item.setCpa(150d);
+//            }else {
+//                item.setCpa(75d+bidMap.getOrDefault(item.getItemFeature().getAdvertiserId(),0d));
             item.setCpa(75d);
-            item.setPidLambda(PidLambdaContainer.getPidLambda(item.getAdId()));
+//            }
+
+//            if(item.getAdId()==409||item.getAdId()==487){
+//                item.setPidLambda(10000d);
+//            }else{
+                item.setPidLambda(PidLambdaContainer.getPidLambda(item.getAdId()));
+//            }
         }
 
         //兜底方案
@@ -89,6 +109,7 @@ public class RankServiceImpl implements RankService {
             object.put("type",rankResult.get(0).getScore_type());
             object.put("pctr",rankResult.get(0).getCtr());
             object.put("pcvr",rankResult.get(0).getCvr());
+            object.put("score",rankResult.get(0).getScore());
             object.put("lrsamples",rankResult.get(0).getLrSampleString());
             object.put("dataTime",currentTime.format(timeFormatter));
             log.info("svc=adItemRank {}", JSONObject.toJSONString(object));