package com.ylcm.sys.service.impl;
import java.time.LocalDate;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import javax.annotation.Resource;
import com.ylcm.sys.common.Util;
import com.ylcm.sys.domain.*;
import com.ylcm.sys.dto.AdTvQueryDTO;
import com.ylcm.sys.mapper.AdSpecialMapper;
import com.ylcm.sys.service.*;
import com.ylcm.sys.vo.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.core.task.TaskExecutor;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ylcm.sys.common.EnumHelperUtil;
import com.ylcm.sys.common.ProjectUtil;
import com.ylcm.sys.enums.AdTheatreTimeEnum;
import com.ylcm.sys.enums.MediaRankEnum;
import com.ylcm.sys.form.AdTheatreAnalysisDetailQueryForm;
import com.ylcm.sys.form.AdTheatreAnalysisQueryForm;
import com.ylcm.sys.mapper.AdTheatreMapper;
import com.ylcm.sys.mapper.AdTheatreTvStatMapper;
import org.springframework.transaction.annotation.Transactional;
/**
*
* 关联电视剧数据 服务实现类
*
*
* @author admin
* @since 2020-07-01
*/
@Slf4j
@Service
public class AdTheatreTvStatServiceImpl extends ServiceImpl implements AdTheatreTvStatService {
@Resource
private AdTheatreMapper adTheatreMapper;
@Resource
private AdMediaService adMediaService;
@Resource
private AdTheatreTvStatService adTheatreTvStatService;
@Resource
private AdTheatreTvService adTheatreTvService;
@Resource
private AdSpecialMapper adSpecialMapper;
@Resource
private TaskExecutor taskExecutor;
@Resource
private AdTvService adTvService;
@Resource
private AdTheatreService adTheatreService;
/**
* 计算 某个频道的收视率
* @param mediaName
* @param theatreTime
* @param startDate
* @param endDate
* @return
*/
@Cacheable(value = "TheatreAnalysis",keyGenerator = "cacheKeyGenerator")
@Override
public AdTheatreTvStat statByMedia(String mediaName, Integer theatreTime, String startDate, String endDate) {
return baseMapper.statByMedia(mediaName, theatreTime, startDate, endDate);
}
@Cacheable(value = "TheatreAnalysis",keyGenerator = "cacheKeyGenerator")
@Override
public IPage getPage(AdTheatreAnalysisQueryForm queryForm) {
if(StringUtils.isNotBlank(queryForm.getName())) {
queryForm.setName(queryForm.getName().trim());
}
IPage adTheatreTvs = baseMapper.getPage(new Page(queryForm.getPageNo(), queryForm.getPageSize()), queryForm);
IPage analysisPage = new Page();
BeanUtils.copyProperties(adTheatreTvs, analysisPage);
List analysisVOs = Collections.synchronizedList(new ArrayList());
if (CollectionUtils.isNotEmpty(adTheatreTvs.getRecords())) {
CompletableFuture[] completableFutures = adTheatreTvs.getRecords().stream().map(adTheatreTvStat -> CompletableFuture.runAsync(() -> {
AdTheatreAnalysisVO adTheatreAnalysisVO = new AdTheatreAnalysisVO();
BeanUtils.copyProperties(adTheatreTvStat, adTheatreAnalysisVO);
AdTheatreTimeEnum adTheatreTimeEnum = EnumHelperUtil.getOneByCode(AdTheatreTimeEnum.class, adTheatreTvStat.getTheatreTime() + "");
adTheatreAnalysisVO.setTheatreTimeName(adTheatreTimeEnum.getName());
MediaRankEnum mediaRankEnum = EnumHelperUtil.getOneByCode(MediaRankEnum.class, adTheatreTvStat.getChannelSystem() + "");
adTheatreAnalysisVO.setChannelSystem(mediaRankEnum.getName());
adTheatreAnalysisVO.setRating29(Util.newScale(adTheatreAnalysisVO.getRating29(), 3));
// 获取频道收视率
List seasons = ProjectUtil.getLocalDateByString(adTheatreTvStat.getSeason());
AdTheatreTvStat mediaStat = adTheatreTvStatService.statByMedia(adTheatreTvStat.getMediaName(), adTheatreTvStat.getTheatreTime(),
seasons.get(0).format(DateTimeFormatter.ISO_DATE), seasons.get(1).format(DateTimeFormatter.ISO_DATE));
adTheatreAnalysisVO.setMediaDk29(mediaStat.getDk29());
float mediaRating29 = mediaStat.getRating29();
// 收视率保留四位小数
adTheatreAnalysisVO.setMediaRating29(Util.newScale(mediaRating29, 3));
adTheatreAnalysisVO.setEffect(ProjectUtil.getMediaEffect(adTheatreAnalysisVO.getRating29(), adTheatreAnalysisVO.getMediaRating29()));
// 剧id
AdTv adTv = adTvService.getByName(adTheatreAnalysisVO.getName());
adTheatreAnalysisVO.setTvId(adTv == null ? 0 : adTv.getId());
analysisVOs.add(adTheatreAnalysisVO);
},taskExecutor)).toArray(CompletableFuture[]::new);
CompletableFuture.allOf(completableFutures).join();
analysisVOs.sort(new Comparator() {
@Override
public int compare(AdTheatreAnalysisVO o1, AdTheatreAnalysisVO o2) {
return o2.getRating29().compareTo(o1.getRating29());
}
});
analysisPage.setRecords(analysisVOs);
}
return analysisPage;
}
@Override
public IPage getDetailPage(AdTheatreAnalysisDetailQueryForm queryForm) {
AdTvQueryDTO adTvQueryDTO = AdTvQueryDTO.from(queryForm);
LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper();
queryWrapper.eq(AdTheatre::getName, adTvQueryDTO.getName());
queryWrapper.eq(AdTheatre::getMediaName, adTvQueryDTO.getMediaName());
if (!adTvQueryDTO.getStartTime().equals(ProjectUtil.MORNING_STR)) {
queryWrapper.ge(AdTheatre::getShowTime, adTvQueryDTO.getStartTime());
queryWrapper.lt(AdTheatre::getShowTime, adTvQueryDTO.getEndTime());
} else {
queryWrapper.apply("( (show_time >={0} ) or (show_time < {1}))", adTvQueryDTO.getStartTime(), adTvQueryDTO.getEndTime());
}
queryWrapper.ge(AdTheatre::getShowDate, adTvQueryDTO.getStartDate());
queryWrapper.le(AdTheatre::getShowDate, adTvQueryDTO.getEndDate());
IPage adTheatreTvs = adTheatreMapper.selectPage(new Page(queryForm.getPageNo(), queryForm.getPageSize()), queryWrapper);
IPage analysisPage = new Page();
BeanUtils.copyProperties(adTheatreTvs, analysisPage);
List analysisVOs = new ArrayList();
if (CollectionUtils.isNotEmpty(adTheatreTvs.getRecords())) {
CompletableFuture[] completableFutures = adTheatreTvs.getRecords().stream().map(adTheatre -> CompletableFuture.runAsync(() -> {
AdTheatreAnalysisDetailVO detailVO = new AdTheatreAnalysisDetailVO();
BeanUtils.copyProperties(adTheatre, detailVO);
detailVO.setProductName(adTheatre.getTypeName());
detailVO.setJinxian(adTheatre.getJinxian() != null ? adTheatre.getJinxian().toString() : "");
// 省网数据
AdTheatreTv adTheatreTv = adTheatreTvService.getByTheatreId(adTheatre.getId());
if (adTheatreTv != null) {
BeanUtils.copyProperties(adTheatreTv, detailVO);
}
detailVO.setShowDuration(adTheatre.getDuration() == null ? "" :adTheatre.getDuration().toString());
analysisVOs.add(detailVO);
},taskExecutor)).toArray(CompletableFuture[]::new);
CompletableFuture.allOf(completableFutures).join();
analysisVOs.sort(new Comparator() {
@Override
public int compare(AdTheatreAnalysisDetailVO o1, AdTheatreAnalysisDetailVO o2) {
return o1.getMediaNum().compareTo(o2.getMediaNum());
}
});
analysisPage.setRecords(analysisVOs);
}
return analysisPage;
}
private void saveOrUpd(AdTheatreTvStat adTheatreTvStat) {
LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper()
.eq(AdTheatreTvStat::getName, adTheatreTvStat.getName())
.eq(AdTheatreTvStat::getMediaName, adTheatreTvStat.getMediaName())
.eq(AdTheatreTvStat::getTheatreTime, adTheatreTvStat.getTheatreTime())
.eq(AdTheatreTvStat::getShowDate, adTheatreTvStat.getShowDate());
AdTheatreTvStat domainInDb = baseMapper.selectOne(lambdaQueryWrapper);
if (domainInDb == null) {
baseMapper.insert(adTheatreTvStat);
} else {
Integer id = domainInDb.getId();
BeanUtils.copyProperties(adTheatreTvStat, domainInDb);
domainInDb.setId(id);
baseMapper.updateById(domainInDb);
}
}
private void delete(AdTheatre adTheatre, Integer theatreTime) {
LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper()
.eq(AdTheatreTvStat::getName, adTheatre.getName())
.eq(AdTheatreTvStat::getMediaName, adTheatre.getMediaName())
.eq(AdTheatreTvStat::getTheatreTime, theatreTime)
.eq(AdTheatreTvStat::getShowDate, adTheatre.getShowDate());
baseMapper.delete(lambdaQueryWrapper);
}
@Transactional(rollbackFor = Exception.class)
@CacheEvict(value = "TheatreAnalysis", allEntries=true)
@Override
public void saveStatByTheatreTv(AdTheatre adTheatre) {
Integer theatreTime = ProjectUtil.getTypeByLocalTime(adTheatre.getShowTime());
List localTimes = ProjectUtil.getLocalTimeByType(theatreTime);
LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper().eq(AdTheatre::getName, adTheatre.getName())
.eq(AdTheatre::getMediaName, adTheatre.getMediaName())
.eq(AdTheatre::getShowDate, adTheatre.getShowDate());
if (!localTimes.get(0).format(DateTimeFormatter.ISO_TIME).equals(ProjectUtil.MORNING_STR)) {
queryWrapper.ge(AdTheatre::getShowTime, localTimes.get(0))
.lt(AdTheatre::getShowTime, localTimes.get(1));
} else {
queryWrapper.apply("( (show_time >={0} ) or (show_time < {1}))", localTimes.get(0), localTimes.get(1));
}
long start = System.currentTimeMillis();
List adTheatres = adTheatreMapper.selectList(queryWrapper);
long end = System.currentTimeMillis();
log.info("list 耗时, {} ", end - start);
if (CollectionUtils.isEmpty(adTheatres)) {
log.info("AdTheatre数据为空,删掉, {}, {}", queryWrapper.getCustomSqlSegment(), queryWrapper.getParamNameValuePairs());
// 没有就要删掉
this.delete(adTheatre, theatreTime);
} else {
AdTheatreTvStat adTheatreTvStat = new AdTheatreTvStat();
adTheatre.setId(null);
BeanUtils.copyProperties(adTheatre, adTheatreTvStat);
adTheatreTvStat.setTheatreTime(ProjectUtil.getTypeByLocalTime(adTheatre.getShowTime()));
adTheatreTvStat.setSeason(ProjectUtil.getSeasonByLocalDate(adTheatre.getShowDate()));
AdMedia adMedia = adMediaService.getByName(adTheatre.getMediaName());
adTheatreTvStat.setChannelSystem(adMedia.getRank());
float ratio29 = 0;
int dk29 = 0;
float ratio51 = 0;
int dk51 = 0;
int total = 0;
int total_d = 0;
// Set tvNumSet = new HashSet<>();
for(AdTheatre tmp: adTheatres) {
AdTheatreTv adTheatreTv = adTheatreTvService.getByTheatreId(tmp.getId());
if (adTheatreTv == null) {
continue;
}
// if (!tvNumSet.contains(tmp.getMediaNum())) {
// // 一个电视剧对应多个广告
// tvNumSet.add(tmp.getMediaNum());
total ++;
// }
if (adTheatreTv.getRating29() != null && adTheatreTv.getRating29() != 0) {
total_d ++;
}
ratio29 += (adTheatreTv.getRating29() == null ? 0f : adTheatreTv.getRating29());
dk29 += (adTheatreTv.getDk29() == null ? 0 : adTheatreTv.getDk29());
ratio51 += (adTheatreTv.getRating51() == null ? 0f : adTheatreTv.getRating51());
dk51 += (adTheatreTv.getDk51() == null ? 0 : adTheatreTv.getDk51());
}
adTheatreTvStat.setDk29(dk29);
adTheatreTvStat.setRating29(ratio29);
adTheatreTvStat.setDk51(dk51);
adTheatreTvStat.setRating51(ratio51);
adTheatreTvStat.setTvNum(total);
adTheatreTvStat.setTvNumD(total_d);
start = System.currentTimeMillis();
saveOrUpd(adTheatreTvStat);
end = System.currentTimeMillis();
log.info("save 耗时, {} ", end - start);
}
}
@Cacheable(value = "TheatreAnalysis",keyGenerator = "cacheKeyGenerator")
@Override
public List getTvTop(Integer theatreTime, String startDate, String endDate) {
List list = baseMapper.tvTop(theatreTime, startDate, endDate);
list.stream().forEach(i -> {
i.init();
int count = adTheatreService.countTvNum(i.getName(), i.getMediaName(), startDate, endDate);
i.setMediaNum(count);
});
return list;
}
@Cacheable(value = "TheatreAnalysis",keyGenerator = "cacheKeyGenerator")
@Override
public List getMediaTop(String name, Integer theatreTime, String startDate, String endDate, Integer limitSize) {
limitSize = (limitSize == null ? 30 : limitSize);
List list = baseMapper.mediaTop(name, theatreTime, startDate, endDate, limitSize);
list.stream().forEach(i -> i.init());
list.stream().forEach(i -> {
MediaRankEnum mediaRankEnum = EnumHelperUtil.getOneByCode(MediaRankEnum.class, i.getMediaRank());
i.setMediaRank(mediaRankEnum.getName());
int count = adTheatreService.countTvNum(null, i.getMediaName(), startDate, endDate);
i.setMediaNum(count);
});
return list;
}
@Override
public AdTvRatioVO getTvRatioVO(AdTheatreAnalysisDetailQueryForm queryForm) {
AdTvRatioVO adTvRatioVO = new AdTvRatioVO();
List trendVOS = baseMapper.tvRatioTrend(queryForm);
trendVOS.stream().forEach(i -> i.init());
trendVOS.sort(new Comparator() {
@Override
public int compare(AdTvRatioTrendVO o1, AdTvRatioTrendVO o2) {
return o1.getShowDate().compareTo(o2.getShowDate());
}
});
adTvRatioVO.setTrendVOS(trendVOS);
AdTheatreTv adTheatreTv = baseMapper.tvRatioPeople(AdTvQueryDTO.from(queryForm));
List peopleVOS = AdTvRatioPeopleVO.from(adTheatreTv);
adTvRatioVO.setPeopleVOS(peopleVOS);
return adTvRatioVO;
}
@Override
public AdTvZoneVO getTvZoneVO(AdTheatreAnalysisDetailQueryForm queryForm) {
AdTheatreTv adTheatreTv = baseMapper.tvRatioZone(AdTvQueryDTO.from(queryForm));
List tvZone = AdTvZonePeopleVO.from(adTheatreTv);
// 去掉电视剧
queryForm.setName(null);
AdTheatreTv adTheatreMedia = baseMapper.tvRatioZone(AdTvQueryDTO.from(queryForm));
List mediaZone = AdTvZonePeopleVO.from(adTheatreMedia);
AdTvZoneVO adTvZoneVO = new AdTvZoneVO();
adTvZoneVO.setTvNum(tvZone);
adTvZoneVO.setMediaNum(mediaZone);
return adTvZoneVO;
}
@Override
public List getProductVO(AdTheatreAnalysisDetailQueryForm queryForm) {
return baseMapper.productDist(AdTvQueryDTO.from(queryForm));
}
@Override
public List getThemeDistVO(AdTheatreAnalysisDetailQueryForm queryForm) {
AdTvQueryDTO queryDTO = AdTvQueryDTO.from(queryForm);
List distVOS = baseMapper.themeDist(queryForm);
distVOS.sort(new Comparator() {
@Override
public int compare(AdThemeDistVO o1, AdThemeDistVO o2) {
if (o1.getRatio() > o2.getRatio()) {
return -1;
}
if (o1.getRatio() < o2.getRatio()) {
return 1;
}
return 0;
}
});
distVOS.parallelStream().forEach(i -> {
int total = adTheatreService.countThemeNum(i.getFirstTheme(), queryForm.getMediaName(), queryDTO.getTimeQuery(), queryForm.getStartDate(), queryForm.getEndDate());
i.setTotal(total);
i.setRatio(Util.newScale(i.getRatio(), 3));
});
return distVOS;
}
@CacheEvict(value = "TheatreAnalysis", allEntries=true)
@Override
public void batchUpdateByName(String newName, String oldName, String firstTheme, String oldFirstTheme, String secondTheme) {
LambdaQueryWrapper statQueryWrapper = new LambdaQueryWrapper();
statQueryWrapper.eq(AdTheatreTvStat::getName, oldName);
AdTheatreTvStat adTheatreTvStat = new AdTheatreTvStat();
if (!newName.equals(oldName)) {
adTheatreTvStat.setName(newName);
}
if (!firstTheme.equals(oldFirstTheme)) {
adTheatreTvStat.setFirstTheme(firstTheme);
adTheatreTvStat.setSecondTheme(secondTheme);
}
baseMapper.update(adTheatreTvStat, statQueryWrapper);
}
}