Commit e19e942a by 吕明尚

增加抽奖接口

parent e5d6e325
......@@ -46,6 +46,9 @@ public class Constants
/** 订单支付成功后Task */
public static final String ORDER_TASK_PAY_SUCCESS_AFTER = "orderPaySuccessTask";
//抽奖锁定key
public static final String LOTTERY_LOCK_KEY = "lottery_lock_key";
//订单操作redis队列
public static final String ORDER_TASK_REDIS_KEY_AFTER_DELETE_BY_USER = "alterOrderDeleteByUser"; // 用户删除订单后续操作
......
......@@ -7,29 +7,38 @@ public enum PrizeTypeEnum {
INTEGRAL(3, "积分"),
THANK(4, "谢谢参与");
private Integer index;
private Integer code;
private String name;
PrizeTypeEnum() {
}
PrizeTypeEnum(Integer index, String name) {
this.index = index;
PrizeTypeEnum(Integer code, String name) {
this.code = code;
this.name = name;
}
public Integer getIndex() {
return index;
public static PrizeTypeEnum getTypeCode(Integer code) {
for (PrizeTypeEnum type : PrizeTypeEnum.values()) {
if (type.getCode().equals(code)) {
return type;
}
}
return null;
}
public void setIndex(Integer index) {
this.index = index;
public Integer getCode() {
return code;
}
public String getName() {
return name;
}
public void setCode(Integer code) {
this.code = code;
}
public void setName(String name) {
this.name = name;
}
......
package share.web.controller.system;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import share.common.annotation.Log;
import share.common.core.controller.BaseController;
......@@ -30,7 +29,6 @@ public class WheelGameController extends BaseController {
/**
* 查询转盘游戏列表
*/
@PreAuthorize("@ss.hasPermi('system:wheelGame:list')")
@GetMapping("/list")
public TableDataInfo list(WheelGame wheelGame) {
startPage();
......@@ -41,7 +39,6 @@ public class WheelGameController extends BaseController {
/**
* 导出转盘游戏列表
*/
@PreAuthorize("@ss.hasPermi('system:wheelGame:export')")
@Log(title = "转盘游戏", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(HttpServletResponse response, WheelGame wheelGame) {
......@@ -53,7 +50,6 @@ public class WheelGameController extends BaseController {
/**
* 获取转盘游戏详细信息
*/
@PreAuthorize("@ss.hasPermi('system:wheelGame:query')")
@GetMapping(value = "/{id}")
public AjaxResult getInfo(@PathVariable("id") Long id) {
return success(wheelGameService.selectWheelGameById(id));
......@@ -62,7 +58,6 @@ public class WheelGameController extends BaseController {
/**
* 新增转盘游戏
*/
@PreAuthorize("@ss.hasPermi('system:wheelGame:add')")
@Log(title = "转盘游戏", businessType = BusinessType.INSERT)
@PostMapping
public AjaxResult add(@RequestBody WheelGame wheelGame) {
......@@ -72,7 +67,6 @@ public class WheelGameController extends BaseController {
/**
* 修改转盘游戏
*/
@PreAuthorize("@ss.hasPermi('system:wheelGame:edit')")
@Log(title = "转盘游戏", businessType = BusinessType.UPDATE)
@PutMapping
public AjaxResult edit(@RequestBody WheelGame wheelGame) {
......@@ -82,10 +76,15 @@ public class WheelGameController extends BaseController {
/**
* 删除转盘游戏
*/
@PreAuthorize("@ss.hasPermi('system:wheelGame:remove')")
@Log(title = "转盘游戏", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public AjaxResult remove(@PathVariable Long[] ids) {
return toAjax(wheelGameService.deleteWheelGameByIds(ids));
}
//抽奖接口
@PostMapping("/draw")
public AjaxResult draw(@RequestBody WheelGame wheelGame) {
return success(wheelGameService.draw(wheelGame));
}
}
......@@ -155,7 +155,6 @@ public class RedisTask {
wrapper.isNotNull(SConsumerCoupon::getCouponCode);
List<SConsumerCoupon> coupons = isConsumerCouponService.list(wrapper);
List<SStore> stores = storeService.list();
List<Long> expiredCoupons = new ArrayList<>();
if (!CollectionUtils.isEmpty(coupons)) {
for (SConsumerCoupon coupon : coupons) {
......
......@@ -61,7 +61,7 @@ public class LotteryRecordsLog extends BaseEntity {
* 是否中奖 0:未中奖 1:中奖
*/
@Excel(name = "是否中奖 0:未中奖 1:中奖")
private Long isHit;
private Integer isHit;
/**
* 中奖奖品
......@@ -73,7 +73,7 @@ public class LotteryRecordsLog extends BaseEntity {
* 是否发放 1未发放,2 已发放 3 发放失败
*/
@Excel(name = " 是否发放 1未发放,2 已发放 3 发放失败")
private Long isSend;
private Integer isSend;
/**
* 发放结果
......
......@@ -7,8 +7,6 @@ import org.apache.commons.lang3.builder.ToStringStyle;
import share.common.annotation.Excel;
import share.common.core.domain.BaseEntity;
import java.math.BigDecimal;
/**
* 奖品对象 s_prize
*
......@@ -71,7 +69,7 @@ public class Prize extends BaseEntity {
* 中奖几率
*/
@Excel(name = "中奖几率")
private BigDecimal ratio;
private Double ratio;
@Override
......@@ -82,8 +80,8 @@ public class Prize extends BaseEntity {
.append("prizeType", getPrizeType())
.append("prizeName", getPrizeName())
.append("prizeValue", getPrizeValue())
.append("currentNum", getCurrentNum())
.append("maxNum", getMaxNum())
// .append("currentNum", getCurrentNum())
// .append("maxNum", getMaxNum())
.append("ratio", getRatio())
.append("createBy", getCreateBy())
.append("createTime", getCreateTime())
......
......@@ -74,7 +74,7 @@ public interface ISConsumerCouponService extends IService<SConsumerCoupon>
List<SConsumerCouponVo> availableCouponList(CouponRequest couponRequest);
int give(SConsumerCoupon sConsumerCoupon);
SConsumerCoupon give(SConsumerCoupon sConsumerCoupon);
public Integer give(Long consumerId, Long couponId, Integer giveDay);
......
......@@ -59,4 +59,6 @@ public interface WheelGameService extends IService<WheelGame> {
* @return 结果
*/
public int deleteWheelGameById(Long id);
String draw(WheelGame wheelGame);
}
......@@ -496,11 +496,11 @@ public class SConsumerCouponServiceImpl extends ServiceImpl<SConsumerCouponMappe
}
@Override
public int give(SConsumerCoupon sConsumerCoupon) {
public SConsumerCoupon give(SConsumerCoupon sConsumerCoupon) {
//根据优惠券id查询优惠券信息
SCoupon sCoupon = sCouponService.selectSCouponById(sConsumerCoupon.getCouponId());
if (ObjectUtils.isEmpty(sCoupon)) {
return 0;
return new SConsumerCoupon();
}
if (sCoupon.getNumber().equals(ZERO)) {
throw new RuntimeException("优惠券数量为0");
......@@ -546,7 +546,7 @@ public class SConsumerCouponServiceImpl extends ServiceImpl<SConsumerCouponMappe
sCoupon.setNumber(sCoupon.getNumber() - 1);
sCouponService.updateById(sCoupon);
}
return insert;
return newSConsumerCoupon;
}
@Override
......
package share.system.service.impl;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import share.common.constant.Constants;
import share.common.core.redis.RedisUtil;
import share.common.enums.PrizeTypeEnum;
import share.common.enums.YesNoEnum;
import share.common.exception.base.BaseException;
import share.common.utils.DateUtils;
import share.system.domain.WheelGame;
import share.system.domain.*;
import share.system.domain.vo.FrontTokenComponent;
import share.system.mapper.WheelGameMapper;
import share.system.service.ISConsumerCouponService;
import share.system.service.LotteryRecordsLogService;
import share.system.service.PrizeService;
import share.system.service.WheelGameService;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Random;
import java.util.stream.Collectors;
/**
* 转盘游戏Service业务层处理
......@@ -18,8 +37,17 @@ import java.util.List;
*/
@Service
public class WheelGameServiceImpl extends ServiceImpl<WheelGameMapper, WheelGame> implements WheelGameService {
private static final Logger logger = LoggerFactory.getLogger(WheelGameServiceImpl.class);
@Autowired
private WheelGameMapper wheelGameMapper;
@Autowired
private PrizeService prizeService;
@Autowired
private RedisUtil redisUtil;
@Autowired
private ISConsumerCouponService sConsumerCouponService;
@Autowired
private LotteryRecordsLogService lotteryRecordsLogService;
/**
* 查询转盘游戏
......@@ -88,4 +116,157 @@ public class WheelGameServiceImpl extends ServiceImpl<WheelGameMapper, WheelGame
public int deleteWheelGameById(Long id) {
return wheelGameMapper.deleteWheelGameById(id);
}
@Override
public String draw(WheelGame wheelGame) {
if (wheelGame == null || wheelGame.getId() == null) {
throw new IllegalArgumentException("无效的游戏对象或游戏ID为空");
}
SConsumer user = FrontTokenComponent.getWxSConsumerEntry();
if (ObjectUtil.isNull(user)) {
throw new BaseException("您的登录已过期,请先登录");
}
if (Objects.equals(user.getPrizeDrawNumbr(), YesNoEnum.no.getIndex())) {
throw new BaseException("用户抽奖次数为0,请联系客服");
}
List<Prize> prizeList = prizeService.list(new LambdaQueryWrapper<Prize>().eq(Prize::getGameId, wheelGame.getId()));
Prize prize = luckDraw(prizeList, wheelGame.getId());
LotteryRecordsLog log = new LotteryRecordsLog();
log.setGameId(wheelGame.getId());
log.setUserId(user.getId());
log.setUserName(user.getNickName());
log.setPhone(user.getPhone());
log.setDrawTime(DateUtils.getNowDate());
if (ObjectUtil.isNotEmpty(prize)) {
PrizeTypeEnum couponType = PrizeTypeEnum.getTypeCode(prize.getPrizeType());
try {
switch (couponType) {
case COUPON:
SConsumerCoupon sConsumerCoupon = new SConsumerCoupon();
sConsumerCoupon.setConsumerId(user.getId());
sConsumerCoupon.setCouponId(prize.getCouponId());
SConsumerCoupon give = sConsumerCouponService.give(sConsumerCoupon);
log.setIsHit(YesNoEnum.yes.getIndex());
log.setIsSend(YesNoEnum.yes.getIndex());
log.setHitPrize(prize.getPrizeName() + ":" + give.getName());
log.setSendMsg(PrizeTypeEnum.COUPON.getName() + ":" + give.getName() + "以发放");
lotteryRecordsLogService.save(log);
break;
case GOODS:
log.setIsHit(YesNoEnum.yes.getIndex());
log.setIsSend(YesNoEnum.yes.getIndex());
log.setHitPrize(PrizeTypeEnum.GOODS.getName() + ":" + prize.getPrizeName());
log.setSendMsg(PrizeTypeEnum.GOODS.getName() + ":" + prize.getPrizeName() + "以发放");
lotteryRecordsLogService.save(log);
break;
case INTEGRAL:
log.setIsHit(YesNoEnum.yes.getIndex());
log.setIsSend(YesNoEnum.yes.getIndex());
log.setHitPrize(PrizeTypeEnum.INTEGRAL.getName());
log.setSendMsg(prize.getPrizeValue() + ":" + PrizeTypeEnum.INTEGRAL.getName() + "以发放");
lotteryRecordsLogService.save(log);
break;
case THANK:
log.setIsHit(YesNoEnum.no.getIndex());
log.setIsSend(YesNoEnum.no.getIndex());
log.setHitPrize("谢谢参与");
log.setSendMsg("谢谢参与");
lotteryRecordsLogService.save(log);
break;
default:
throw new BaseException("奖品类型异常");
}
} catch (BaseException be) {
logger.error("抽奖过程中发生业务异常: {}", be.getMessage(), be);
throw be;
} catch (Exception e) {
logger.error("抽奖过程中发生未知异常: {}", e.getMessage(), e);
throw new RuntimeException(e);
}
} else {
log.setIsHit(YesNoEnum.no.getIndex());
log.setIsSend(YesNoEnum.no.getIndex());
log.setHitPrize("谢谢参与");
log.setSendMsg("谢谢参与");
lotteryRecordsLogService.save(log);
return "谢谢参与";
}
return null;
}
private Prize luckDraw(List<Prize> prizeList, Long gameId) {
// 奖品列表中的概率为累加概率
// 需要按照添加进列表的顺序进行累加,为了数据处理方便中奖几率*100
String lockResult = "";
try {
lockResult = lockGame(gameId);
double sum = 0;
List<Prize> newList = new ArrayList<>();
for (int i = 0; i < prizeList.size(); i++) {
Prize entity = prizeList.get(i);
Prize newEntity = new Prize();
BeanUtils.copyProperties(entity, newEntity);
sum = sum + (entity.getRatio() * 100);
newEntity.setRatio(sum);
newList.add(newEntity);
}
// 生成一个随机数
Random random = new Random();
Double userSelect = random.nextDouble() * 10000;
for (Prize prize : prizeList) {
// 随机数小于中奖几率,则中奖
if (userSelect < prize.getRatio()) {
// 最大中奖数(0:代表不限制次数)
int maxNum = prize.getMaxNum();
// 判断游戏奖品当前中奖数及最大中奖数
if (maxNum != 0 && maxNum <= prize.getCurrentNum()) {
// 超过最大中奖数则不中
break;
} else {
return prize;
}
}
}
// 谢谢参与
List<Prize> prize = prizeList.stream().filter(item -> item.getPrizeType() == 4).collect(Collectors.toList());
if (prize.size() > 0) {
return prize.get(0);
}
return null;
} catch (BaseException e) {
throw e;
} finally {
unLockGame(gameId, lockResult);
}
}
private String lockGame(Long gameId) throws BaseException {
try {
//自旋10次,每次等待1秒
String lockResult = "";
for (int i = 0; i < 10; i++) {
lockResult = redisUtil.lockWithTimeout(Constants.LOTTERY_LOCK_KEY + gameId, 11, 2);
if (StringUtils.isBlank(lockResult)) {
Thread.sleep(1000L);
} else {
break;
}
}
return lockResult;
} catch (Exception e) {
throw new BaseException("当前抽奖太火爆了,请稍后再试!");
}
}
private void unLockGame(Long gameId, String keyValue) {
if (StringUtils.isNotBlank(keyValue)) {
redisUtil.unLock(Constants.LOTTERY_LOCK_KEY + gameId, keyValue, 2);
}
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment