package com.jd.car.member.service.index.impl;
import com.alibaba.fastjson.JSON;
import com.jd.car.member.common.contant.Constants;
import com.jd.car.member.common.exception.CarMemberErrorEnum;
import com.jd.car.member.common.exception.GameException;
import com.jd.car.member.common.util.DateUtil;
import com.jd.car.member.infrastructure.jd.cache.service.CacheLockService;
import com.jd.car.member.infrastructure.jd.cache.service.CacheService;
import com.jd.car.member.infrastructure.jd.ducc.DuccService;
import com.jd.car.member.infrastructure.utils.ValidateUtils;
import com.jd.car.member.service.coupon.monitor.CouponMonitorPoint;
import com.jd.car.member.service.es.CarMemberService;
import com.jd.car.member.service.es.bo.CarMemberBO;
import com.jd.car.member.service.index.GameIndexService;
import com.jd.car.member.service.index.bo.FirstLoginResultBO;
import com.jd.car.member.service.index.bo.GameBeginResultBO;
import com.jd.car.member.service.index.bo.GameIndexResultBO;
import com.jd.car.member.service.index.bo.GameBeginCheckResultBO;
import com.jd.car.member.service.index.enums.GameIndexCacheKeyEnum;
import com.jd.car.member.service.index.monitors.SiteInfoMonitor;
import com.jd.car.member.service.power.PowerDailyService;
import com.jd.car.member.service.power.monitor.PowerDailyMonitor;
import com.jd.car.member.service.prize.PrizeService;
import com.jd.car.member.service.prize.bo.PrizeBO;
import com.jd.car.member.service.site.GameSiteInfoService;
import com.jd.car.member.service.site.GameUserSiteInfoService;
import com.jd.car.member.service.site.bo.GameSiteInfoBO;
import com.jd.car.member.service.site.bo.GameUserSiteInfoBO;
import com.jd.ump.annotation.JProfiler;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;
/**
* 游戏首页 服务实现类
*
* @author xyd
*
* @date 2020/04/23
*/
@Slf4j
@Service
public class GameIndexServiceImpl implements GameIndexService {
@Autowired
private CacheService cacheService;
@Autowired
private GameSiteInfoService gameSiteInfoService;
@Autowired
private GameUserSiteInfoService gameUserSiteInfoService;
@Autowired
private PowerDailyService powerDailyService;
@Autowired
private CarMemberService carMemberService;
@Autowired
private CacheLockService cacheLockService;
@Autowired
private PrizeService prizeService;
@Autowired
private DuccService duccService;
/**
* 用户进入游戏首页
*
* @param pin
* @param activityId
* @return
*/
@Override
@Transactional(rollbackFor = Exception.class)
@JProfiler(jKey = "com.jd.car.member.service.index.GameIndexService.getGameIndexInfo")
public GameIndexResultBO getGameIndexInfo(String pin, Long activityId) {
Assert.hasLength(pin, "pin不能为空");
Assert.notNull(activityId, "活动id不能为空");
GameIndexResultBO gameIndexResultBo = new GameIndexResultBO();
String lock = null;
try {
lock = cacheLockService.tryLock(GameIndexCacheKeyEnum.USER_GAME_POWER_LOCK.getKey(activityId, pin), GameIndexCacheKeyEnum.USER_GAME_POWER_LOCK.getExpireTime(), TimeUnit.SECONDS);
if (null != lock) {
// 1.获取用户信息
gameIndexResultBo.setHeadImg("").setMatchPoint(0);
CarMemberBO carMember = carMemberService.queryMemberInfoByPin(pin);
if (null != carMember && null != carMember.getTotalPoint()) {
gameIndexResultBo.setMatchPoint(carMember.getTotalPoint());
}
if (null != carMember && StringUtils.isNotEmpty(carMember.getHeadImg())) {
gameIndexResultBo.setHeadImg(carMember.getHeadImg());
}
// 2.获取用户燃力值
gameIndexResultBo.setPower(powerDailyService.getIndexUserPower(activityId, pin, new Date()));
// 3.获取所有站点信息列表 + 用户当前站点信息
gameIndexResultBo.setSiteList(this.getGameSiteInfoList(pin, activityId, gameIndexResultBo));
}
} catch (GameException e) {
log.error("用户进入游戏首页获取信息异常:", e);
throw new GameException(CarMemberErrorEnum.GAME_INDEX_ERROR);
} finally {
if (null != lock) {
cacheLockService.unlock(GameIndexCacheKeyEnum.USER_GAME_POWER_LOCK.getKey(activityId, pin), lock);
}
}
return gameIndexResultBo;
}
/**
* 获取所有站点信息列表 + 用户当前站点信息
*
* @param pin
* @param activityId
* @param result
* @return
*/
private List<GameSiteInfoBO> getGameSiteInfoList(String pin, Long activityId, GameIndexResultBO result) {
result.setFirstRoundStatus(false).setIsLastSite(false);
// 1.获取游戏所有站点信息列表
List<GameSiteInfoBO> allSite = gameSiteInfoService.getAllSite(activityId);
// 异常捕获
ValidateUtils.isEmpty(allSite, CarMemberErrorEnum.SITE_LIST_NOT_EXISTS_ERROR, SiteInfoMonitor.SITE_LIST_NOT_EXISTS_ERROR, activityId);
// 2.获取用户当前站点(初始化进入没有数据需要添加游戏站点)
if (CollectionUtils.isNotEmpty(allSite)) {
GameUserSiteInfoBO userSiteInfoByPin = gameUserSiteInfoService.getUserSiteInfoByPin(pin, activityId);
if (userSiteInfoByPin == null) {
GameUserSiteInfoBO build = GameUserSiteInfoBO.builder().activityId(activityId)
.siteId(allSite.stream().min(Comparator.comparing(GameSiteInfoBO::getSiteNum)).map(GameSiteInfoBO::getId).get())
.pin(pin).total(0).build();
gameUserSiteInfoService.addUserSite(build);
result.setCurrentSite(allSite.stream().min(Comparator.comparing(GameSiteInfoBO::getSiteNum)).orElseGet(GameSiteInfoBO::new));
} else {
//判断是否是最后站点,且是否为第一圈结束
Long maxSiteId = allSite.stream().max(Comparator.comparing(GameSiteInfoBO::getSiteNum)).map(GameSiteInfoBO::getId).get();
if (userSiteInfoByPin.getSiteId().equals(maxSiteId)) {
result.setIsLastSite(true);
if (userSiteInfoByPin.getTotal() == 0) {
result.setFirstRoundStatus(true);
}
}
result.setCurrentSite(allSite.stream().filter(e -> e.getId().equals(userSiteInfoByPin.getSiteId())).findFirst().orElseGet(GameSiteInfoBO::new));
}
}
return allSite;
}
/**
* 用户开始游戏验证
*
* @param pin
* @param activityId
* @return
*/
@Override
@Transactional(rollbackFor = Exception.class)
@JProfiler(jKey = "com.jd.car.member.service.index.GameIndexService.startGameCheck")
public GameBeginCheckResultBO startGameCheck(String pin, Long activityId) {
Assert.hasLength(pin, "pin不能为空");
Assert.notNull(activityId, "活动id不能为空");
GameBeginCheckResultBO gameStartCheckResultBo = new GameBeginCheckResultBO();
// 1.查询当天的燃气值(通过后台取值,防止凌晨时刻调用接口,用户燃气值少于100的应当是刷新到100)
Date now = new Date();
Integer userPower = powerDailyService.getIndexUserPower(activityId, pin, now);
if (userPower < duccService.getDefaultOncePower()) {
gameStartCheckResultBo.setHasPower(false);
return gameStartCheckResultBo;
}
/* //用户燃力值大于阈值告警
ValidateUtils.validate(() -> userPower > duccService.getUserPowerMaxLevel(),
PowerDailyMonitor.USER_POWER_MAX_LEVEL, activityId, pin, DateUtil.getWholeDateForNow());*/
gameStartCheckResultBo.setHasPower(true);
return gameStartCheckResultBo;
}
/**
* 用户开始游戏
*
* @param pin
* @param activityId
* @return
*/
@Override
@Transactional(rollbackFor = Exception.class)
@JProfiler(jKey = "com.jd.car.member.service.index.GameIndexService.startGame")
public GameBeginResultBO startGame(String pin, Long activityId) {
Assert.hasLength(pin, "pin不能为空");
Assert.notNull(activityId, "活动id不能为空");
GameBeginResultBO result = new GameBeginResultBO();
String lock = null;
try {
lock = cacheLockService.tryLock(GameIndexCacheKeyEnum.USER_GAME_BEGIN_LOCK.getKey(activityId, pin), GameIndexCacheKeyEnum.USER_GAME_BEGIN_LOCK.getExpireTime(), TimeUnit.SECONDS);
if (null != lock) {
// 1.查询当天的燃气值(通过后台取值,防止凌晨时刻调用接口,用户燃气值少于100的应当是刷新到100)
Date now = new Date();
Integer userPower = powerDailyService.getIndexUserPower(activityId, pin, now);
//用户燃力值大于阈值告警
ValidateUtils.validate(() -> userPower > duccService.getUserPowerMaxLevel(),
PowerDailyMonitor.USER_POWER_MAX_LEVEL, activityId, pin, DateUtil.getWholeDateForNow());
// 2.判断当前用户站点位置是否为终点: (1)如果终点则圈数 +1 回到原点; (2)否则站点位置前进 +1;
boolean isLastSite = this.getUserNextSite(pin, activityId, result);
if (!isLastSite) {
// 3.燃气值-100
if (userPower < duccService.getDefaultOncePower()) {
throw new GameException(CarMemberErrorEnum.GAME_USER_POWER_ERROR);
}
int userCurrentPower = userPower - duccService.getDefaultOncePower();
powerDailyService.updatePower(activityId, pin, userCurrentPower, DateFormatUtils.format(now, Constants.DATA_FORMAT_YMD));
// 4.抽奖
PrizeBO prizeBo = prizeService.dealDraw(pin, activityId);
if (prizeBo != null) {
result.setDrawStatus(prizeBo.getDrawStatus()).setType(prizeBo.getType()).setName(prizeBo.getName()).setValue(prizeBo.getValue());
}
result.setCurrentPower(userCurrentPower);
log.info("开始游戏-返回结果1:pin:{}, activityId:{}, result:{}", pin, activityId, JSON.toJSONString(result));
return result;
}
result.setCurrentPower(userPower).setDrawStatus(false);
log.info("开始游戏-返回结果2:pin:{}, activityId:{}, result:{}", pin, activityId, JSON.toJSONString(result));
return result;
}
} catch (GameException e) {
log.error("用户开始游戏操作异常:", e);
throw new GameException(CarMemberErrorEnum.START_GAME_ERROR, e.getMsg());
} finally {
if (null != lock) {
cacheLockService.unlock(GameIndexCacheKeyEnum.USER_GAME_BEGIN_LOCK.getKey(activityId, pin), lock);
}
}
throw new GameException(CarMemberErrorEnum.GAME_INDEX_LOCK_ERROR);
}
@Override
@JProfiler(jKey = "com.jd.car.member.service.index.GameIndexService.isFirstLogin")
public FirstLoginResultBO isFirstLogin(String pin, Long activityId) {
Assert.hasLength(pin, "pin不能为空");
Assert.notNull(activityId, "活动id不能为空");
FirstLoginResultBO firstLoginResultBo = new FirstLoginResultBO();
GameIndexCacheKeyEnum firstLoginStatusEnum = GameIndexCacheKeyEnum.USER_FIRST_LOGIN_STATUS;
//缓存中是否存在用户登录过的状态
if (cacheService.exists(firstLoginStatusEnum.getKey(activityId, pin))) {
firstLoginResultBo.setIsFirstLogin(false);
return firstLoginResultBo;
}
//更新用户登录过游戏的缓存
cacheService.set(firstLoginStatusEnum.getKey(activityId, pin), "1");
firstLoginResultBo.setIsFirstLogin(true);
return firstLoginResultBo;
}
/**
* 开始游戏-用户前进一个站点
*
* @param pin
* @param activityId
* @param result
*/
private boolean getUserNextSite(String pin, Long activityId, GameBeginResultBO result) {
boolean response = false;
GameSiteInfoBO nextGameSite;
result.setIsLastSite(false).setFirstRoundStatus(false);
List<GameSiteInfoBO> allSite = gameSiteInfoService.getAllSite(activityId);
if (CollectionUtils.isEmpty(allSite)) {
throw new GameException(CarMemberErrorEnum.GAME_INDEX_ERROR);
}
GameUserSiteInfoBO userSiteInfo = gameUserSiteInfoService.getUserSiteInfoByPin(pin, activityId);
log.info("开始游戏-用户前进一个站点,获取到当前站点位置:{}", JSON.toJSONString(userSiteInfo));
if (userSiteInfo == null) {
throw new GameException(CarMemberErrorEnum.USER_SITE_NOT_EXISTS_ERROR);
}
Long maxSiteId = allSite.stream().max(Comparator.comparing(GameSiteInfoBO::getSiteNum)).map(GameSiteInfoBO::getId).get();
if (maxSiteId.equals(userSiteInfo.getSiteId())) {
nextGameSite = allSite.stream().min(Comparator.comparing(GameSiteInfoBO::getSiteNum)).orElseGet(GameSiteInfoBO::new);
GameUserSiteInfoBO build = GameUserSiteInfoBO.builder().id(userSiteInfo.getId()).total(userSiteInfo.getTotal() + 1)
.siteId(nextGameSite.getId()).build();
gameUserSiteInfoService.updateUserSiteInfo(build);
response = true;
} else {
//通过用户当前站点主键找对应序号,然后通过序号 +1 找下一个游戏站点主键id,将新的站点主键id更新到用户站点信息表中
Integer nextSiteNum = allSite.stream().filter(e -> e.getId().equals(userSiteInfo.getSiteId())).findFirst().map(GameSiteInfoBO::getSiteNum).get() + 1;
nextGameSite = allSite.stream().filter(s -> s.getSiteNum().equals(nextSiteNum)).findFirst().orElseGet(GameSiteInfoBO::new);
GameUserSiteInfoBO build = GameUserSiteInfoBO.builder().id(userSiteInfo.getId()).siteId(nextGameSite.getId()).build();
gameUserSiteInfoService.updateUserSiteInfo(build);
//如果前进一个站点是最后一个游戏站点,需要给前端提示
if (maxSiteId.equals(nextGameSite.getId())) {
result.setIsLastSite(true);
if (userSiteInfo.getTotal() == 0) {
result.setFirstRoundStatus(true);
}
}
}
result.setCurrentSiteNum(nextGameSite.getSiteNum()).setNextSiteX(nextGameSite.getSiteX()).setNextSiteY(nextGameSite.getSiteY());
return response;
}
}
小游戏项目分布式锁代码(留个纪念)
猜你喜欢
转载自blog.csdn.net/qq_39809613/article/details/106999137
今日推荐
周排行