| 
					
				 | 
			
			
				@@ -0,0 +1,102 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+package com.tzld.piaoquan.recommend.server.service.recall.strategy; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import com.tzld.piaoquan.recommend.server.model.Video; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import com.tzld.piaoquan.recommend.server.service.filter.FilterParam; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import com.tzld.piaoquan.recommend.server.service.filter.FilterResult; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import com.tzld.piaoquan.recommend.server.service.filter.FilterService; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import com.tzld.piaoquan.recommend.server.service.recall.FilterParamFactory; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import com.tzld.piaoquan.recommend.server.service.recall.RecallParam; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import com.tzld.piaoquan.recommend.server.service.recall.RecallStrategy; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import lombok.extern.slf4j.Slf4j; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import org.apache.commons.collections4.CollectionUtils; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import org.apache.commons.lang3.StringUtils; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import org.apache.commons.lang3.tuple.MutablePair; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import org.apache.commons.lang3.tuple.Pair; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import org.springframework.beans.factory.annotation.Autowired; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import org.springframework.beans.factory.annotation.Qualifier; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import org.springframework.data.redis.core.RedisTemplate; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import org.springframework.stereotype.Component; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import java.util.*; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import java.util.stream.Collectors; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+@Component 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+@Slf4j 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+public class PrioriProvinceRovnRecallStrategy implements RecallStrategy { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    private final String CLASS_NAME = this.getClass().getSimpleName(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    @Autowired 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    private FilterService filterService; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    @Autowired 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    @Qualifier("redisTemplate") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    public RedisTemplate<String, String> redisTemplate; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    public static final String PUSH_FROM = "priori_province_rovn"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    public static final String redisKeyPrefix = "priori_province_rovn_recall"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    @Override 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    public String pushFrom() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return PUSH_FROM; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    @Override 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    public List<Video> recall(RecallParam param) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        List<Video> videosResult = new ArrayList<>(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        try { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            String province = param.getProvince().replaceAll("省$", ""); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            String redisKey = String.format("%s:%s", redisKeyPrefix, province); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            String redisValue = redisTemplate.opsForValue().get(redisKey); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if (null == redisValue || redisValue.isEmpty()) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                return videosResult; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            Pair<List<Long>, Map<Long, Double>> pair = parsePair(redisValue, param.getVideoId(), 50); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            fillVideoResult(param, pair, videosResult); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } catch (Exception e) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            log.error("recall is wrong in {}, error={}", CLASS_NAME, e); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return videosResult; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    private Pair<List<Long>, Map<Long, Double>> parsePair(String data, long headVid, int size) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        List<Long> idsList = new ArrayList<>(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        Map<Long, Double> scoresMap = new HashMap<>(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (!StringUtils.isBlank(data)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            String[] cells = data.split("\t"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if (2 == cells.length) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                List<Long> ids = Arrays.stream(cells[0].split(",")).map(Long::valueOf).collect(Collectors.toList()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                List<Double> scores = Arrays.stream(cells[1].split(",")).map(Double::valueOf).collect(Collectors.toList()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                if (!ids.isEmpty() && ids.size() == scores.size()) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    int minSize = Math.min(size, ids.size()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    for (int i = 0; i < minSize; ++i) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        long id = ids.get(i); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        double score = scores.get(i); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        if (headVid != id && !scoresMap.containsKey(id)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            idsList.add(id); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            scoresMap.put(id, score); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return new MutablePair<>(idsList, scoresMap); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    private void fillVideoResult(RecallParam param, Pair<List<Long>, Map<Long, Double>> pair, List<Video> videosResult) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (null != pair) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            List<Long> ids = pair.getLeft(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            Map<Long, Double> scoresMap = pair.getRight(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if (null != ids && null != scoresMap && !ids.isEmpty()) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                FilterParam filterParam = FilterParamFactory.create(param, ids); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                FilterResult filterResult = filterService.filter(filterParam); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                if (null != filterResult && CollectionUtils.isNotEmpty(filterResult.getVideoIds())) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    filterResult.getVideoIds().forEach(vid -> { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        Video video = new Video(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        video.setVideoId(vid); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        video.setRovScore(scoresMap.getOrDefault(vid, 0D)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        video.setPushFrom(pushFrom()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        videosResult.add(video); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 |