package com.tanpu.community.service; import com.tanpu.common.util.JsonUtil; import com.tanpu.community.api.beans.qo.ThemeAnalysDO; import com.tanpu.community.api.beans.resp.PythonResponse; import com.tanpu.community.dao.entity.community.ThemeEntity; import com.tanpu.community.util.ConvertUtil; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import org.springframework.web.client.RestTemplate; import java.util.*; import java.util.stream.Collectors; @Slf4j @Service public class RecommendService { @Value("${recommend.python.enable}") public String enablePython; @Value("${recommend.python.url}") public String pythonUrl; @Value("${recommend.ratio.hot}") public Integer hotRatio; @Value("${recommend.ratio.new}") public Integer newRatio; @Value("${recommend.ratio.python}") public Integer pythonRatio; @Autowired private RankService rankService; @Autowired private ThemeService themeService; @Autowired private VisitSummaryService visitSummaryService; //最新 private List<ThemeAnalysDO> recentThemeList = new ArrayList<>(); //推荐 private Map<String, List<String>> recommondList = new HashMap<>(); // private Map<String, Set<String>> returnedIdsMap = new HashMap<>(); public List<String> getRecommendThemes(String lastId, Integer pageSize, String userId) { //最热话题,剔除当前用户的主题 List<String> hotThemeIds = rankService.getRankThemeList().stream() .filter(o -> !userId.equals(o.getAuthorId())) .map(ThemeAnalysDO::getThemeId) .collect(Collectors.toList()); //最新话题,剔除当前用户的主题 List<String> newThemeIds = this.getRecentThemeList().stream() .filter(o -> !userId.equals(o.getAuthorId())) .map(ThemeAnalysDO::getThemeId) .collect(Collectors.toList()); //推荐话题 List<String> recThemeIds = getPythonRecommendList(userId); //混合 Set<String> returnedIds = (StringUtils.isEmpty(lastId)) ? new HashSet<>() : returnedIdsMap.get(userId); List<String> result = new ArrayList<>(); getResultList(hotThemeIds, 0, newThemeIds, 0, recThemeIds, 0, returnedIds, result, pageSize,userId); result = result.stream().limit(pageSize).collect(Collectors.toList()); //记录已返回主题id if(StringUtils.isEmpty(lastId)){ returnedIdsMap.put(userId,new HashSet<>(result)); }else { HashSet<String> newSet = new HashSet<>(); newSet.addAll(returnedIdsMap.get(userId)); newSet.addAll(result); returnedIdsMap.put(userId,newSet); } return result; } public List<ThemeAnalysDO> getRecentThemeList() { if (recentThemeList.size() == 0) { refreshNewestThemes(); } return recentThemeList; } //从数据库查询最新主题 public void refreshNewestThemes() { List<ThemeEntity> themeEntities = themeService.queryLatestThemes(100); this.recentThemeList = ConvertUtil.themeEntityToAnalysDOs(themeEntities); } //查询python计算推荐列表 public List<String> getPythonRecommendList(String userId) { if (recommondList.containsKey(userId)) { return recommondList.get(userId); } else { return refreshPythonRecommendList(userId); } } //HTTP查询python推荐主题 public List<String> refreshPythonRecommendList(String userId) { if (!"true".equals(enablePython)) { return Collections.emptyList(); } RestTemplate restTemplate = new RestTemplate(); HashMap<String, String> param = new HashMap<>(); param.put("user_id", userId); try { String response = restTemplate.getForObject(pythonUrl, String.class, param); PythonResponse pythonResponse = JsonUtil.toBean(response, PythonResponse.class); recommondList.put(userId, pythonResponse.getAttributes()); return pythonResponse.getAttributes(); } catch (Exception e) { log.error("调用python失败"); return Collections.emptyList(); } } //逐个插入 private void getResultList(List<String> hotThemeIds, Integer hotTag, List<String> newThemeIds, Integer newTag, List<String> recThemeIds, Integer recTag, Set<String> returnedIds, List<String> result, Integer pageSize, String userId) { if (hotThemeIds.size() <= hotTag && newThemeIds.size() <= newTag && recThemeIds.size() <= recTag) { //所有列表已循环结束,返回 return; } while (result.size() < pageSize * 1.5) { int hotTimes = hotRatio; int newTimes = newRatio; int recTimes = pythonRatio; String id; while (hotTimes > 0 && hotThemeIds.size() > hotTag) { id = hotThemeIds.get(hotTag); if (!returnedIds.contains(id)) { result.add(id); returnedIds.add(id); } hotTag++; hotTimes--; } while (newTimes > 0 && newThemeIds.size() > newTag) { id = newThemeIds.get(newTag); if (!returnedIds.contains(id)) { result.add(id); returnedIds.add(id); } newTag++; newTimes--; } while (recTimes > 0 && recThemeIds.size() > recTag) { id = recThemeIds.get(recTag); if (!returnedIds.contains(id)) { result.add(id); returnedIds.add(id); } recTag++; recTimes--; } } //去重已看过(查看正文) result = visitSummaryService.filterUserNotVisited(userId,result); if (result.size() < pageSize) { getResultList(hotThemeIds, hotTag, newThemeIds, newTag, recThemeIds, recTag, returnedIds, result, pageSize, userId); } } }