AdTheatreTvStatServiceImpl.java 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429
  1. package com.ylcm.sys.service.impl;
  2. import java.time.LocalDate;
  3. import java.time.LocalTime;
  4. import java.time.format.DateTimeFormatter;
  5. import java.util.*;
  6. import java.util.concurrent.CompletableFuture;
  7. import javax.annotation.Resource;
  8. import com.ylcm.sys.common.Util;
  9. import com.ylcm.sys.domain.*;
  10. import com.ylcm.sys.dto.AdTvQueryDTO;
  11. import com.ylcm.sys.mapper.AdSpecialMapper;
  12. import com.ylcm.sys.service.*;
  13. import com.ylcm.sys.vo.*;
  14. import lombok.extern.slf4j.Slf4j;
  15. import org.apache.commons.collections.CollectionUtils;
  16. import org.apache.commons.lang.StringUtils;
  17. import org.springframework.beans.BeanUtils;
  18. import org.springframework.cache.annotation.CacheEvict;
  19. import org.springframework.cache.annotation.Cacheable;
  20. import org.springframework.core.task.TaskExecutor;
  21. import org.springframework.stereotype.Service;
  22. import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
  23. import com.baomidou.mybatisplus.core.metadata.IPage;
  24. import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
  25. import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
  26. import com.ylcm.sys.common.EnumHelperUtil;
  27. import com.ylcm.sys.common.ProjectUtil;
  28. import com.ylcm.sys.enums.AdTheatreTimeEnum;
  29. import com.ylcm.sys.enums.MediaRankEnum;
  30. import com.ylcm.sys.form.AdTheatreAnalysisDetailQueryForm;
  31. import com.ylcm.sys.form.AdTheatreAnalysisQueryForm;
  32. import com.ylcm.sys.mapper.AdTheatreMapper;
  33. import com.ylcm.sys.mapper.AdTheatreTvStatMapper;
  34. import org.springframework.transaction.annotation.Transactional;
  35. /**
  36. * <p>
  37. * 关联电视剧数据 服务实现类
  38. * </p>
  39. *
  40. * @author admin
  41. * @since 2020-07-01
  42. */
  43. @Slf4j
  44. @Service
  45. public class AdTheatreTvStatServiceImpl extends ServiceImpl<AdTheatreTvStatMapper, AdTheatreTvStat> implements AdTheatreTvStatService {
  46. @Resource
  47. private AdTheatreMapper adTheatreMapper;
  48. @Resource
  49. private AdMediaService adMediaService;
  50. @Resource
  51. private AdTheatreTvStatService adTheatreTvStatService;
  52. @Resource
  53. private AdTheatreTvService adTheatreTvService;
  54. @Resource
  55. private AdSpecialMapper adSpecialMapper;
  56. @Resource
  57. private TaskExecutor taskExecutor;
  58. @Resource
  59. private AdTvService adTvService;
  60. @Resource
  61. private AdTheatreService adTheatreService;
  62. /**
  63. * 计算 某个频道的收视率
  64. * @param mediaName
  65. * @param theatreTime
  66. * @param startDate
  67. * @param endDate
  68. * @return
  69. */
  70. @Cacheable(value = "TheatreAnalysis",keyGenerator = "cacheKeyGenerator")
  71. @Override
  72. public AdTheatreTvStat statByMedia(String mediaName, Integer theatreTime, String startDate, String endDate) {
  73. return baseMapper.statByMedia(mediaName, theatreTime, startDate, endDate);
  74. }
  75. @Cacheable(value = "TheatreAnalysis",keyGenerator = "cacheKeyGenerator")
  76. @Override
  77. public IPage<AdTheatreAnalysisVO> getPage(AdTheatreAnalysisQueryForm queryForm) {
  78. if(StringUtils.isNotBlank(queryForm.getName())) {
  79. queryForm.setName(queryForm.getName().trim());
  80. }
  81. IPage<AdTheatreTvStat> adTheatreTvs = baseMapper.getPage(new Page<AdTheatreTvStat>(queryForm.getPageNo(), queryForm.getPageSize()), queryForm);
  82. IPage<AdTheatreAnalysisVO> analysisPage = new Page<AdTheatreAnalysisVO>();
  83. BeanUtils.copyProperties(adTheatreTvs, analysisPage);
  84. List<AdTheatreAnalysisVO> analysisVOs = Collections.synchronizedList(new ArrayList<AdTheatreAnalysisVO>());
  85. if (CollectionUtils.isNotEmpty(adTheatreTvs.getRecords())) {
  86. CompletableFuture[] completableFutures = adTheatreTvs.getRecords().stream().map(adTheatreTvStat -> CompletableFuture.runAsync(() -> {
  87. AdTheatreAnalysisVO adTheatreAnalysisVO = new AdTheatreAnalysisVO();
  88. BeanUtils.copyProperties(adTheatreTvStat, adTheatreAnalysisVO);
  89. AdTheatreTimeEnum adTheatreTimeEnum = EnumHelperUtil.getOneByCode(AdTheatreTimeEnum.class, adTheatreTvStat.getTheatreTime() + "");
  90. adTheatreAnalysisVO.setTheatreTimeName(adTheatreTimeEnum.getName());
  91. MediaRankEnum mediaRankEnum = EnumHelperUtil.getOneByCode(MediaRankEnum.class, adTheatreTvStat.getChannelSystem() + "");
  92. adTheatreAnalysisVO.setChannelSystem(mediaRankEnum.getName());
  93. adTheatreAnalysisVO.setRating29(Util.newScale(adTheatreAnalysisVO.getRating29(), 3));
  94. // 获取频道收视率
  95. List<LocalDate> seasons = ProjectUtil.getLocalDateByString(adTheatreTvStat.getSeason());
  96. AdTheatreTvStat mediaStat = adTheatreTvStatService.statByMedia(adTheatreTvStat.getMediaName(), adTheatreTvStat.getTheatreTime(),
  97. seasons.get(0).format(DateTimeFormatter.ISO_DATE), seasons.get(1).format(DateTimeFormatter.ISO_DATE));
  98. adTheatreAnalysisVO.setMediaDk29(mediaStat.getDk29());
  99. float mediaRating29 = mediaStat.getRating29();
  100. // 收视率保留四位小数
  101. adTheatreAnalysisVO.setMediaRating29(Util.newScale(mediaRating29, 3));
  102. adTheatreAnalysisVO.setEffect(ProjectUtil.getMediaEffect(adTheatreAnalysisVO.getRating29(), adTheatreAnalysisVO.getMediaRating29()));
  103. // 剧id
  104. AdTv adTv = adTvService.getByName(adTheatreAnalysisVO.getName());
  105. adTheatreAnalysisVO.setTvId(adTv == null ? 0 : adTv.getId());
  106. analysisVOs.add(adTheatreAnalysisVO);
  107. },taskExecutor)).toArray(CompletableFuture[]::new);
  108. CompletableFuture.allOf(completableFutures).join();
  109. analysisVOs.sort(new Comparator<AdTheatreAnalysisVO>() {
  110. @Override
  111. public int compare(AdTheatreAnalysisVO o1, AdTheatreAnalysisVO o2) {
  112. return o2.getRating29().compareTo(o1.getRating29());
  113. }
  114. });
  115. analysisPage.setRecords(analysisVOs);
  116. }
  117. return analysisPage;
  118. }
  119. @Override
  120. public IPage<AdTheatreAnalysisDetailVO> getDetailPage(AdTheatreAnalysisDetailQueryForm queryForm) {
  121. AdTvQueryDTO adTvQueryDTO = AdTvQueryDTO.from(queryForm);
  122. LambdaQueryWrapper<AdTheatre> queryWrapper = new LambdaQueryWrapper<AdTheatre>();
  123. queryWrapper.eq(AdTheatre::getName, adTvQueryDTO.getName());
  124. queryWrapper.eq(AdTheatre::getMediaName, adTvQueryDTO.getMediaName());
  125. if (!adTvQueryDTO.getStartTime().equals(ProjectUtil.MORNING_STR)) {
  126. queryWrapper.ge(AdTheatre::getShowTime, adTvQueryDTO.getStartTime());
  127. queryWrapper.lt(AdTheatre::getShowTime, adTvQueryDTO.getEndTime());
  128. } else {
  129. queryWrapper.apply("( (show_time >={0} ) or (show_time < {1}))", adTvQueryDTO.getStartTime(), adTvQueryDTO.getEndTime());
  130. }
  131. queryWrapper.ge(AdTheatre::getShowDate, adTvQueryDTO.getStartDate());
  132. queryWrapper.le(AdTheatre::getShowDate, adTvQueryDTO.getEndDate());
  133. IPage<AdTheatre> adTheatreTvs = adTheatreMapper.selectPage(new Page<AdTheatre>(queryForm.getPageNo(), queryForm.getPageSize()), queryWrapper);
  134. IPage<AdTheatreAnalysisDetailVO> analysisPage = new Page<AdTheatreAnalysisDetailVO>();
  135. BeanUtils.copyProperties(adTheatreTvs, analysisPage);
  136. List<AdTheatreAnalysisDetailVO> analysisVOs = new ArrayList<AdTheatreAnalysisDetailVO>();
  137. if (CollectionUtils.isNotEmpty(adTheatreTvs.getRecords())) {
  138. CompletableFuture[] completableFutures = adTheatreTvs.getRecords().stream().map(adTheatre -> CompletableFuture.runAsync(() -> {
  139. AdTheatreAnalysisDetailVO detailVO = new AdTheatreAnalysisDetailVO();
  140. BeanUtils.copyProperties(adTheatre, detailVO);
  141. detailVO.setProductName(adTheatre.getTypeName());
  142. detailVO.setJinxian(adTheatre.getJinxian() != null ? adTheatre.getJinxian().toString() : "");
  143. // 省网数据
  144. AdTheatreTv adTheatreTv = adTheatreTvService.getByTheatreId(adTheatre.getId());
  145. if (adTheatreTv != null) {
  146. BeanUtils.copyProperties(adTheatreTv, detailVO);
  147. }
  148. detailVO.setShowDuration(adTheatre.getDuration() == null ? "" :adTheatre.getDuration().toString());
  149. analysisVOs.add(detailVO);
  150. },taskExecutor)).toArray(CompletableFuture[]::new);
  151. CompletableFuture.allOf(completableFutures).join();
  152. analysisVOs.sort(new Comparator<AdTheatreAnalysisDetailVO>() {
  153. @Override
  154. public int compare(AdTheatreAnalysisDetailVO o1, AdTheatreAnalysisDetailVO o2) {
  155. return o1.getMediaNum().compareTo(o2.getMediaNum());
  156. }
  157. });
  158. analysisPage.setRecords(analysisVOs);
  159. }
  160. return analysisPage;
  161. }
  162. private void saveOrUpd(AdTheatreTvStat adTheatreTvStat) {
  163. LambdaQueryWrapper<AdTheatreTvStat> lambdaQueryWrapper = new LambdaQueryWrapper<AdTheatreTvStat>()
  164. .eq(AdTheatreTvStat::getName, adTheatreTvStat.getName())
  165. .eq(AdTheatreTvStat::getMediaName, adTheatreTvStat.getMediaName())
  166. .eq(AdTheatreTvStat::getTheatreTime, adTheatreTvStat.getTheatreTime())
  167. .eq(AdTheatreTvStat::getShowDate, adTheatreTvStat.getShowDate());
  168. AdTheatreTvStat domainInDb = baseMapper.selectOne(lambdaQueryWrapper);
  169. if (domainInDb == null) {
  170. baseMapper.insert(adTheatreTvStat);
  171. } else {
  172. Integer id = domainInDb.getId();
  173. BeanUtils.copyProperties(adTheatreTvStat, domainInDb);
  174. domainInDb.setId(id);
  175. baseMapper.updateById(domainInDb);
  176. }
  177. }
  178. private void delete(AdTheatre adTheatre, Integer theatreTime) {
  179. LambdaQueryWrapper<AdTheatreTvStat> lambdaQueryWrapper = new LambdaQueryWrapper<AdTheatreTvStat>()
  180. .eq(AdTheatreTvStat::getName, adTheatre.getName())
  181. .eq(AdTheatreTvStat::getMediaName, adTheatre.getMediaName())
  182. .eq(AdTheatreTvStat::getTheatreTime, theatreTime)
  183. .eq(AdTheatreTvStat::getShowDate, adTheatre.getShowDate());
  184. baseMapper.delete(lambdaQueryWrapper);
  185. }
  186. @Transactional(rollbackFor = Exception.class)
  187. @CacheEvict(value = "TheatreAnalysis", allEntries=true)
  188. @Override
  189. public void saveStatByTheatreTv(AdTheatre adTheatre) {
  190. Integer theatreTime = ProjectUtil.getTypeByLocalTime(adTheatre.getShowTime());
  191. List<LocalTime> localTimes = ProjectUtil.getLocalTimeByType(theatreTime);
  192. LambdaQueryWrapper<AdTheatre> queryWrapper = new LambdaQueryWrapper<AdTheatre>().eq(AdTheatre::getName, adTheatre.getName())
  193. .eq(AdTheatre::getMediaName, adTheatre.getMediaName())
  194. .eq(AdTheatre::getShowDate, adTheatre.getShowDate());
  195. if (!localTimes.get(0).format(DateTimeFormatter.ISO_TIME).equals(ProjectUtil.MORNING_STR)) {
  196. queryWrapper.ge(AdTheatre::getShowTime, localTimes.get(0))
  197. .lt(AdTheatre::getShowTime, localTimes.get(1));
  198. } else {
  199. queryWrapper.apply("( (show_time >={0} ) or (show_time < {1}))", localTimes.get(0), localTimes.get(1));
  200. }
  201. List<AdTheatre> adTheatres = adTheatreMapper.selectList(queryWrapper);
  202. if (CollectionUtils.isEmpty(adTheatres)) {
  203. log.info("AdTheatre数据为空,删掉, {}, {}", queryWrapper.getCustomSqlSegment(), queryWrapper.getParamNameValuePairs());
  204. // 没有就要删掉
  205. this.delete(adTheatre, theatreTime);
  206. } else {
  207. AdTheatreTvStat adTheatreTvStat = new AdTheatreTvStat();
  208. adTheatre.setId(null);
  209. BeanUtils.copyProperties(adTheatre, adTheatreTvStat);
  210. adTheatreTvStat.setTheatreTime(ProjectUtil.getTypeByLocalTime(adTheatre.getShowTime()));
  211. adTheatreTvStat.setSeason(ProjectUtil.getSeasonByLocalDate(adTheatre.getShowDate()));
  212. AdMedia adMedia = adMediaService.getByName(adTheatre.getMediaName());
  213. adTheatreTvStat.setChannelSystem(adMedia.getRank());
  214. float ratio29 = 0;
  215. int dk29 = 0;
  216. float ratio51 = 0;
  217. int dk51 = 0;
  218. int total = 0;
  219. int total_d = 0;
  220. // Set<Integer> tvNumSet = new HashSet<>();
  221. for(AdTheatre tmp: adTheatres) {
  222. AdTheatreTv adTheatreTv = adTheatreTvService.getByTheatreId(tmp.getId());
  223. if (adTheatreTv == null) {
  224. continue;
  225. }
  226. // if (!tvNumSet.contains(tmp.getMediaNum())) {
  227. // // 一个电视剧对应多个广告
  228. // tvNumSet.add(tmp.getMediaNum());
  229. total ++;
  230. // }
  231. if (adTheatreTv.getRating29() != null && adTheatreTv.getRating29() != 0) {
  232. total_d ++;
  233. }
  234. ratio29 += (adTheatreTv.getRating29() == null ? 0f : adTheatreTv.getRating29());
  235. dk29 += (adTheatreTv.getDk29() == null ? 0 : adTheatreTv.getDk29());
  236. ratio51 += (adTheatreTv.getRating51() == null ? 0f : adTheatreTv.getRating51());
  237. dk51 += (adTheatreTv.getDk51() == null ? 0 : adTheatreTv.getDk51());
  238. }
  239. adTheatreTvStat.setDk29(dk29);
  240. adTheatreTvStat.setRating29(ratio29);
  241. adTheatreTvStat.setDk51(dk51);
  242. adTheatreTvStat.setRating51(ratio51);
  243. adTheatreTvStat.setTvNum(total);
  244. adTheatreTvStat.setTvNumD(total_d);
  245. saveOrUpd(adTheatreTvStat);
  246. }
  247. }
  248. @Cacheable(value = "TheatreAnalysis",keyGenerator = "cacheKeyGenerator")
  249. @Override
  250. public List<AdTheatreTopVO> getTvTop(Integer theatreTime, String startDate, String endDate) {
  251. List<AdTheatreTopVO> list = baseMapper.tvTop(theatreTime, startDate, endDate);
  252. list.stream().forEach(i -> {
  253. i.init();
  254. int count = adTheatreService.countTvNum(i.getName(), i.getMediaName(), startDate, endDate);
  255. i.setMediaNum(count);
  256. });
  257. return list;
  258. }
  259. @Cacheable(value = "TheatreAnalysis",keyGenerator = "cacheKeyGenerator")
  260. @Override
  261. public List<AdTheatreTopVO> getMediaTop(String name, Integer theatreTime, String startDate, String endDate, Integer limitSize) {
  262. limitSize = (limitSize == null ? 30 : limitSize);
  263. List<AdTheatreTopVO> list = baseMapper.mediaTop(name, theatreTime, startDate, endDate, limitSize);
  264. list.stream().forEach(i -> i.init());
  265. list.stream().forEach(i -> {
  266. MediaRankEnum mediaRankEnum = EnumHelperUtil.getOneByCode(MediaRankEnum.class, i.getMediaRank());
  267. i.setMediaRank(mediaRankEnum.getName());
  268. int count = adTheatreService.countTvNum(null, i.getMediaName(), startDate, endDate);
  269. i.setMediaNum(count);
  270. });
  271. return list;
  272. }
  273. @Override
  274. public AdTvRatioVO getTvRatioVO(AdTheatreAnalysisDetailQueryForm queryForm) {
  275. AdTvRatioVO adTvRatioVO = new AdTvRatioVO();
  276. List<AdTvRatioTrendVO> trendVOS = baseMapper.tvRatioTrend(queryForm);
  277. trendVOS.stream().forEach(i -> i.init());
  278. trendVOS.sort(new Comparator<AdTvRatioTrendVO>() {
  279. @Override
  280. public int compare(AdTvRatioTrendVO o1, AdTvRatioTrendVO o2) {
  281. return o1.getShowDate().compareTo(o2.getShowDate());
  282. }
  283. });
  284. adTvRatioVO.setTrendVOS(trendVOS);
  285. AdTheatreTv adTheatreTv = baseMapper.tvRatioPeople(AdTvQueryDTO.from(queryForm));
  286. List<AdTvRatioPeopleVO> peopleVOS = AdTvRatioPeopleVO.from(adTheatreTv);
  287. adTvRatioVO.setPeopleVOS(peopleVOS);
  288. return adTvRatioVO;
  289. }
  290. @Override
  291. public AdTvZoneVO getTvZoneVO(AdTheatreAnalysisDetailQueryForm queryForm) {
  292. AdTheatreTv adTheatreTv = baseMapper.tvRatioZone(AdTvQueryDTO.from(queryForm));
  293. List<AdTvZonePeopleVO> tvZone = AdTvZonePeopleVO.from(adTheatreTv);
  294. // 去掉电视剧
  295. queryForm.setName(null);
  296. AdTheatreTv adTheatreMedia = baseMapper.tvRatioZone(AdTvQueryDTO.from(queryForm));
  297. List<AdTvZonePeopleVO> mediaZone = AdTvZonePeopleVO.from(adTheatreMedia);
  298. AdTvZoneVO adTvZoneVO = new AdTvZoneVO();
  299. adTvZoneVO.setTvNum(tvZone);
  300. adTvZoneVO.setMediaNum(mediaZone);
  301. return adTvZoneVO;
  302. }
  303. @Override
  304. public List<AdTheatreProductDistVO> getProductVO(AdTheatreAnalysisDetailQueryForm queryForm) {
  305. return baseMapper.productDist(AdTvQueryDTO.from(queryForm));
  306. }
  307. @Override
  308. public List<AdThemeDistVO> getThemeDistVO(AdTheatreAnalysisDetailQueryForm queryForm) {
  309. AdTvQueryDTO queryDTO = AdTvQueryDTO.from(queryForm);
  310. List<AdThemeDistVO> distVOS = baseMapper.themeDist(queryForm);
  311. distVOS.sort(new Comparator<AdThemeDistVO>() {
  312. @Override
  313. public int compare(AdThemeDistVO o1, AdThemeDistVO o2) {
  314. if (o1.getRatio() > o2.getRatio()) {
  315. return -1;
  316. }
  317. if (o1.getRatio() < o2.getRatio()) {
  318. return 1;
  319. }
  320. return 0;
  321. }
  322. });
  323. distVOS.parallelStream().forEach(i -> {
  324. int total = adTheatreService.countThemeNum(i.getFirstTheme(), queryForm.getMediaName(), queryDTO.getTimeQuery(), queryForm.getStartDate(), queryForm.getEndDate());
  325. i.setTotal(total);
  326. i.setRatio(Util.newScale(i.getRatio(), 3));
  327. });
  328. return distVOS;
  329. }
  330. @CacheEvict(value = "TheatreAnalysis", allEntries=true)
  331. @Override
  332. public void batchUpdateByName(String newName, String oldName, String firstTheme, String oldFirstTheme, String secondTheme) {
  333. LambdaQueryWrapper<AdTheatreTvStat> statQueryWrapper = new LambdaQueryWrapper<AdTheatreTvStat>();
  334. statQueryWrapper.eq(AdTheatreTvStat::getName, oldName);
  335. AdTheatreTvStat adTheatreTvStat = new AdTheatreTvStat();
  336. if (!newName.equals(oldName)) {
  337. adTheatreTvStat.setName(newName);
  338. }
  339. if (!firstTheme.equals(oldFirstTheme)) {
  340. adTheatreTvStat.setFirstTheme(firstTheme);
  341. adTheatreTvStat.setSecondTheme(secondTheme);
  342. }
  343. baseMapper.update(adTheatreTvStat, statQueryWrapper);
  344. }
  345. @Override
  346. @Transactional(rollbackFor = Exception.class)
  347. public void batchSaveStatByTheatreTv(List<AdTheatre> adTheatres) {
  348. for(AdTheatre adTheatre : adTheatres){
  349. saveStatByTheatreTv(adTheatre);
  350. }
  351. }
  352. }