Initial commit
This commit is contained in:
@@ -0,0 +1,42 @@
|
||||
package com.ruoyi.playingmethod.config;
|
||||
|
||||
import com.rabbitmq.client.Channel;
|
||||
import com.ruoyi.admin.service.TtFightService;
|
||||
import com.ruoyi.common.rabbitmq.config.DelayedQueueConfig;
|
||||
import com.ruoyi.common.rabbitmq.config.FightQueueConfig;
|
||||
import com.ruoyi.common.utils.DateUtils;
|
||||
import com.ruoyi.playingmethod.service.ApiRollService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.amqp.core.Message;
|
||||
import org.springframework.amqp.rabbit.annotation.RabbitListener;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Date;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
public class FightRabbitConsumer {
|
||||
|
||||
// private final TtFightService ttFightService;
|
||||
//
|
||||
// public FightRabbitConsumer(TtFightService ttFightService) {
|
||||
// this.ttFightService = ttFightService;
|
||||
// }
|
||||
//
|
||||
// @RabbitListener(queues = FightQueueConfig.FIGHT_QUEUE)
|
||||
// public void rollReceiveDelayed(String fightId,Message message, Channel channel) throws IOException {
|
||||
// log.info("===============接收对战队列消息====================" + fightId);
|
||||
//
|
||||
// // 通知 MQ 消息已被接收,可以ACK(从队列中删除)了
|
||||
// channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
|
||||
// try {
|
||||
// ttFightService.endFight(fightId);
|
||||
// } catch (Exception e) {
|
||||
// log.error("============消费失败,尝试消息补发再次消费!==============");
|
||||
// log.error(e.getMessage());
|
||||
// // 消息补发 true=消息退回到queue(有可能被其它的consumer(集群)接收到) false=只补发给当前的consumer
|
||||
// channel.basicRecover(false);
|
||||
// }
|
||||
// }
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package com.ruoyi.playingmethod.config;
|
||||
|
||||
import com.ruoyi.admin.mapper.TtBoxOrnamentsMapper;
|
||||
import com.ruoyi.admin.util.core.fight.LotteryMachine;
|
||||
import com.ruoyi.admin.util.core.fight.PrizePool;
|
||||
import com.ruoyi.common.core.redis.RedisCache;
|
||||
import com.ruoyi.common.redis.config.RedisLock;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
@Configuration
|
||||
public class LotteryMachineConfig {
|
||||
|
||||
@Autowired
|
||||
RedisLock redisLock;
|
||||
@Autowired
|
||||
RedisCache redisCache;
|
||||
@Autowired
|
||||
TtBoxOrnamentsMapper boxOrnamentsMapper;
|
||||
|
||||
@Bean
|
||||
public LotteryMachine lotteryMachine(){
|
||||
|
||||
LotteryMachine machine = LotteryMachine.builder()
|
||||
.boxOrnamentsMapper(boxOrnamentsMapper)
|
||||
.redisLock(redisLock)
|
||||
.redisCache(redisCache)
|
||||
.prizePools(new HashMap<String, PrizePool>())
|
||||
.build();
|
||||
|
||||
machine.preheat();
|
||||
|
||||
return machine;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
package com.ruoyi.playingmethod.config;
|
||||
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import com.rabbitmq.client.Channel;
|
||||
import com.ruoyi.common.core.domain.R;
|
||||
import com.ruoyi.common.rabbitmq.config.DelayedQueueConfig;
|
||||
import com.ruoyi.common.utils.DateUtils;
|
||||
import com.ruoyi.playingmethod.service.ApiRollService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.amqp.core.ExchangeTypes;
|
||||
import org.springframework.amqp.core.Message;
|
||||
import org.springframework.amqp.rabbit.annotation.*;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
public class RollRabbitConsumer {
|
||||
|
||||
private final ApiRollService apiRollService;
|
||||
|
||||
public RollRabbitConsumer(ApiRollService apiRollService) {
|
||||
this.apiRollService = apiRollService;
|
||||
}
|
||||
|
||||
@RabbitListener(queues = DelayedQueueConfig.DLK_QUEUE)
|
||||
public void rollReceiveDelayed(Message message, Channel channel) throws IOException {
|
||||
|
||||
long deliveryTag = message.getMessageProperties().getDeliveryTag();
|
||||
|
||||
Integer rollId = Integer.valueOf(new String(message.getBody()));
|
||||
log.info("【死信队列消费】 roll房开奖,接受到的Roll房ID:{}", rollId);
|
||||
|
||||
try {
|
||||
// Roll房分配结果逻辑
|
||||
R r = apiRollService.endROLL(rollId);
|
||||
if (!r.getCode().equals(200)) {
|
||||
log.error("roll开奖 消费失败,尝试消息补发再次消费!" + r.getMsg());
|
||||
channel.basicNack(deliveryTag, true, true);
|
||||
}
|
||||
if (ObjectUtil.isNotEmpty(r.getMsg())) log.info("{}", r.getMsg());
|
||||
|
||||
// 通知 MQ 消息已被接收,可以ACK(从队列中删除)了
|
||||
channel.basicAck(deliveryTag, true);
|
||||
} catch (Exception e) {
|
||||
log.error("roll开奖 消费失败,尝试消息补发再次消费!");
|
||||
log.error(e.getMessage());
|
||||
channel.basicNack(deliveryTag, true, true);
|
||||
}
|
||||
}
|
||||
|
||||
//@RabbitListener(queues = DelayedQueueConfig.DLK_QUEUE)
|
||||
public void t1(Message message, Channel channel) throws IOException {
|
||||
|
||||
// long deliveryTag = message.getMessageProperties().getDeliveryTag();
|
||||
|
||||
log.info("mq 测试");
|
||||
|
||||
System.out.println(new String(message.getBody()));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package com.ruoyi.playingmethod.controller;
|
||||
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/battleRoyale")
|
||||
public class ApiBattleRoyaleController {
|
||||
}
|
||||
@@ -0,0 +1,217 @@
|
||||
package com.ruoyi.playingmethod.controller;
|
||||
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import com.ruoyi.admin.mapper.TtUserBlendErcashMapper;
|
||||
import com.ruoyi.admin.service.TtUserAmountRecordsService;
|
||||
import com.ruoyi.admin.service.TtBoxService;
|
||||
import com.ruoyi.admin.service.TtUserService;
|
||||
import com.ruoyi.common.annotation.Anonymous;
|
||||
import com.ruoyi.common.annotation.UpdateUserCache;
|
||||
import com.ruoyi.common.core.controller.BaseController;
|
||||
import com.ruoyi.common.core.domain.AjaxResult;
|
||||
import com.ruoyi.common.core.domain.R;
|
||||
import com.ruoyi.common.utils.PageUtils;
|
||||
import com.ruoyi.domain.common.constant.TtAccountRecordSource;
|
||||
import com.ruoyi.domain.common.constant.TtAccountRecordType;
|
||||
import com.ruoyi.domain.common.constant.TtboxRecordSource;
|
||||
import com.ruoyi.domain.common.constant.TtboxRecordStatus;
|
||||
import com.ruoyi.domain.dto.boxRecords.TenTopQuery;
|
||||
import com.ruoyi.domain.dto.boxRecords.queryCondition;
|
||||
import com.ruoyi.domain.entity.TtUserBlendErcash;
|
||||
import com.ruoyi.domain.entity.recorde.TtUserAmountRecords;
|
||||
import com.ruoyi.domain.entity.sys.TtUser;
|
||||
import com.ruoyi.domain.other.*;
|
||||
import com.ruoyi.domain.vo.boxRecords.TtBoxRecordsVO;
|
||||
import com.ruoyi.playingmethod.service.ApiBindBoxService;
|
||||
import com.ruoyi.playingmethod.service.ApiBoxRecordsService;
|
||||
import com.ruoyi.system.service.ISysConfigService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiImplicitParam;
|
||||
import io.swagger.annotations.ApiImplicitParams;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.*;
|
||||
|
||||
@Api(tags = "玩转盲盒模式")
|
||||
@RestController
|
||||
@RequestMapping("/api/bindbox")
|
||||
public class ApiBindBoxController extends BaseController {
|
||||
|
||||
private final ISysConfigService sysConfigService;
|
||||
private final ApiBindBoxService bindBoxService;
|
||||
private final TtUserService userService;
|
||||
private final TtBoxService boxService;
|
||||
private final TtUserAmountRecordsService userAmountRecordsService;
|
||||
|
||||
public ApiBindBoxController(ISysConfigService sysConfigService,
|
||||
ApiBindBoxService bindBoxService,
|
||||
TtUserAmountRecordsService userAmountRecordsService,
|
||||
TtUserService userService,
|
||||
TtBoxService boxService) {
|
||||
this.sysConfigService = sysConfigService;
|
||||
this.bindBoxService = bindBoxService;
|
||||
this.userService = userService;
|
||||
this.userAmountRecordsService = userAmountRecordsService;
|
||||
this.boxService = boxService;
|
||||
}
|
||||
|
||||
@Autowired
|
||||
private ApiBoxRecordsService apiBoxRecordsService;
|
||||
|
||||
@Autowired
|
||||
private TtUserBlendErcashMapper ttUserBlendErcashMapper;
|
||||
|
||||
@ApiOperation("获取宝箱信息")
|
||||
@Anonymous
|
||||
@GetMapping("/{boxId}")
|
||||
public R<TtBoxA> getBoxData(@PathVariable(value = "boxId") Integer boxId) {
|
||||
String websiteMaintenance = sysConfigService.selectConfigByKey("websiteMaintenance");
|
||||
if ("1".equals(websiteMaintenance)) {
|
||||
return R.fail("网站维护中......");
|
||||
}
|
||||
String bindBoxMaintenance = sysConfigService.selectConfigByKey("bindBoxMaintenance");
|
||||
if ("1".equals(bindBoxMaintenance)) {
|
||||
return R.fail("盲盒开箱功能正在维护中......");
|
||||
}
|
||||
TtBoxA boxData = bindBoxService.getBoxData(boxId);
|
||||
return R.ok(boxData);
|
||||
}
|
||||
|
||||
@ApiOperation("获取补偿箱信息")
|
||||
@GetMapping("/getCompBoxData/{boxId}")
|
||||
public AjaxResult getCompBoxData(@PathVariable("boxId") Integer boxId) {
|
||||
List<TtOrnamentsA> compBoxData = bindBoxService.getCompBoxData(boxId);
|
||||
return success(compBoxData);
|
||||
}
|
||||
|
||||
@ApiOperation("获取宝箱列表")
|
||||
@ApiImplicitParams({
|
||||
@ApiImplicitParam(name = "boxType", value = "宝箱类型(1普通箱 2对战箱 3补偿箱 4九宫格)", dataType = "String", dataTypeClass = String.class)
|
||||
})
|
||||
@Anonymous
|
||||
@GetMapping("/getBoxList")
|
||||
public R<List<TtBoxVO>> getBoxList(
|
||||
@RequestParam(value = "boxTypeId", required = false) Integer boxTypeId,
|
||||
@RequestParam(value = "homeFlag", required = false) String homeFlag,
|
||||
@RequestParam(value = "boxType", required = false) String boxType
|
||||
) {
|
||||
List<TtBoxVO> boxData = bindBoxService.getBoxList(boxTypeId, homeFlag, boxType);
|
||||
if (boxData.isEmpty()) {
|
||||
return R.ok(null, "没有匹配的数据。");
|
||||
}
|
||||
return R.ok(boxData);
|
||||
}
|
||||
|
||||
/**
|
||||
* 盲盒开箱模式开箱
|
||||
*/
|
||||
@ApiOperation("盲盒开箱")
|
||||
@UpdateUserCache
|
||||
@PostMapping("/openBox")
|
||||
public R openBox(@RequestParam("boxId") Integer boxId, @RequestParam("num") Integer num) {
|
||||
String websiteMaintenance = sysConfigService.selectConfigByKey("websiteMaintenance");
|
||||
if ("1".equals(websiteMaintenance)) {
|
||||
return R.fail("网站维护中......");
|
||||
}
|
||||
String bindBoxMaintenance = sysConfigService.selectConfigByKey("bindBoxMaintenance");
|
||||
if ("1".equals(bindBoxMaintenance)) {
|
||||
return R.fail("盲盒开箱功能正在维护中......");
|
||||
}
|
||||
TtUser ttUser = userService.getById(getUserId());
|
||||
TtBox ttBox = boxService.getById(boxId);
|
||||
/*if ("0".equals(ttUser.getIsRealCheck())) {
|
||||
return R.fail("您的账户未进行实名认证,请先进行实名认证!");
|
||||
}*/
|
||||
LambdaQueryWrapper<TtUserBlendErcash> queryWrapper = Wrappers.lambdaQuery();
|
||||
queryWrapper.eq(TtUserBlendErcash::getUserId, ttUser.getUserId())
|
||||
.eq(TtUserBlendErcash::getType, TtAccountRecordType.INPUT.getCode())
|
||||
.eq(TtUserBlendErcash::getSource, TtAccountRecordSource.RECHARGE.getCode())
|
||||
.select(TtUserBlendErcash::getTotal);
|
||||
List<TtUserBlendErcash> ercash = ttUserBlendErcashMapper.selectList(queryWrapper);
|
||||
if (CollectionUtils.isEmpty(ercash)) {
|
||||
return R.fail("您的账户未进行充过值!");
|
||||
}
|
||||
|
||||
// BigDecimal openBoxBeanTotal = ttBox.getPrice().multiply(new BigDecimal(num));
|
||||
// if (ttUser.getAccountAmount().compareTo(openBoxBeanTotal) < 0) return R.fail("您的账户游戏币不足!");
|
||||
return bindBoxService.blindBox(ttUser, ttBox, num);
|
||||
}
|
||||
|
||||
@ApiOperation("获取历史开箱信息")
|
||||
@Anonymous
|
||||
@PostMapping("/getBindBoxHistory")
|
||||
public R getBindBoxHistory(@RequestBody @Validated queryCondition param) {
|
||||
if (param.getStatus().equals(1) || param.getStatus().equals(10)) {
|
||||
return R.fail("非法的状态参数。");
|
||||
}
|
||||
PageUtils.clearPage();
|
||||
List<TtBoxRecordsVO> ttBoxRecordsVOS = apiBoxRecordsService.byCondition(param);
|
||||
return R.ok(ttBoxRecordsVOS);
|
||||
}
|
||||
|
||||
// @ApiOperation("获取历史个人开箱信息")
|
||||
// @Anonymous
|
||||
// @GetMapping("/selectBoxRecordsUserLogList")
|
||||
// public R selectBoxRecordsUserLogList(TtUserAmountRecordsBody ttUserAmountRecordsBody) {
|
||||
// System.out.println("==================个人开箱记录====================");
|
||||
// ttUserAmountRecordsBody.setUserId(getUserId().intValue());
|
||||
// return userAmountRecordsService.queryList(ttUserAmountRecordsBody);
|
||||
// //return R.ok(list);
|
||||
// }
|
||||
|
||||
@ApiOperation("获取当前补偿值")
|
||||
@GetMapping("/getCompValue/{boxId}")
|
||||
public AjaxResult getCompValue(@PathVariable("boxId") Integer boxId) {
|
||||
Long userId = getUserId();
|
||||
TtUser ttUser = userService.getById(userId);
|
||||
TtBox ttBox = boxService.getById(boxId);
|
||||
if (Objects.isNull(ttBox))
|
||||
return error("宝箱不存在");
|
||||
if (!"3".equals(ttBox.getBoxType()))
|
||||
return error("该宝箱不是补偿宝箱");
|
||||
return success(bindBoxService.getCompValue(ttUser, ttBox));
|
||||
}
|
||||
|
||||
@ApiOperation("盲盒top")
|
||||
@GetMapping("/top")
|
||||
public R<List<TtBoxRecordsVO>> topBlinkBox() {
|
||||
Long userId = getUserId();
|
||||
if (ObjectUtil.isNull(userId)) {
|
||||
return R.fail("登录过期。");
|
||||
}
|
||||
queryCondition param = new queryCondition();
|
||||
param.setUserId(userId.intValue());
|
||||
param.setOrderByFie(2);
|
||||
param.setSource(Collections.singletonList(TtboxRecordSource.BLIND_BOX.getCode()));
|
||||
param.setStatus(Arrays.asList(TtboxRecordStatus.IN_PACKSACK_ON.getCode(), TtboxRecordStatus.APPLY_DELIVERY.getCode(), TtboxRecordStatus.DELIVERY_YET.getCode()));
|
||||
param.setPage(1);
|
||||
param.setSize(1);
|
||||
PageUtils.clearPage();
|
||||
List<TtBoxRecordsVO> ttBoxRecordsVOS = new ArrayList<>(apiBoxRecordsService.byCondition(param));
|
||||
param.setSource(Collections.singletonList(TtboxRecordSource.FIGHT.getCode()));
|
||||
ttBoxRecordsVOS.addAll(apiBoxRecordsService.byCondition(param));
|
||||
param.setSource(Collections.singletonList(TtboxRecordSource.UPGRADE.getCode()));
|
||||
ttBoxRecordsVOS.addAll(apiBoxRecordsService.byCondition(param));
|
||||
return R.ok(ttBoxRecordsVOS);
|
||||
}
|
||||
|
||||
@ApiOperation("十佳掉落")
|
||||
@GetMapping("/tenTop")
|
||||
public R<List<TtBoxRecordsVO>> tenTop() {
|
||||
TenTopQuery param = new TenTopQuery();
|
||||
param.setSource(Collections.singletonList(TtboxRecordSource.BLIND_BOX.getCode()));
|
||||
param.setStatus(Arrays.asList(TtboxRecordStatus.IN_PACKSACK_ON.getCode(), TtboxRecordStatus.APPLY_DELIVERY.getCode(), TtboxRecordStatus.DELIVERY_YET.getCode()));
|
||||
param.setPage(1);
|
||||
param.setSize(10);
|
||||
PageUtils.clearPage();
|
||||
List<TtBoxRecordsVO> ttBoxRecordsVOS = apiBoxRecordsService.tenTopQuery(param);
|
||||
return R.ok(ttBoxRecordsVOS);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package com.ruoyi.playingmethod.controller;
|
||||
|
||||
import com.ruoyi.common.annotation.Anonymous;
|
||||
import com.ruoyi.common.core.domain.R;
|
||||
import com.ruoyi.common.utils.PageUtils;
|
||||
import com.ruoyi.domain.dto.boxRecords.queryCondition;
|
||||
import com.ruoyi.domain.vo.boxRecords.TtBoxRecordsVO;
|
||||
import com.ruoyi.playingmethod.service.ApiBoxRecordsService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Api(tags = "出货记录")
|
||||
@RestController
|
||||
@RequestMapping("/api/boxRecords")
|
||||
public class ApiBoxRecordsController {
|
||||
|
||||
@Autowired
|
||||
private ApiBoxRecordsService apiBoxRecordsService;
|
||||
|
||||
@ApiOperation("获取历史出货记录")
|
||||
@PostMapping("/historyByCondition")
|
||||
public R getBindBoxHistory(@RequestBody @Validated queryCondition param) {
|
||||
if (param.getStatus().contains(1) || param.getStatus().contains(10)) {
|
||||
return R.fail("非法的状态参数。");
|
||||
}
|
||||
PageUtils.clearPage();
|
||||
List<TtBoxRecordsVO> ttBoxRecordsVOS = apiBoxRecordsService.byCondition(param);
|
||||
return R.ok(ttBoxRecordsVOS);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
package com.ruoyi.playingmethod.controller;
|
||||
|
||||
import com.ruoyi.domain.entity.sys.TtUser;
|
||||
import com.ruoyi.admin.service.TtUserService;
|
||||
import com.ruoyi.common.core.controller.BaseController;
|
||||
import com.ruoyi.common.core.domain.R;
|
||||
import com.ruoyi.common.core.page.PageDataInfo;
|
||||
import com.ruoyi.playingmethod.service.ApiCompoundService;
|
||||
import com.ruoyi.system.service.ISysConfigService;
|
||||
import com.ruoyi.domain.vo.UserPackSackDataVO;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Api(tags = "合成")
|
||||
@RestController
|
||||
@RequestMapping("/api/compound")
|
||||
public class ApiCompoundController extends BaseController {
|
||||
|
||||
private final ISysConfigService sysConfigService;
|
||||
private final TtUserService userService;
|
||||
private final ApiCompoundService compoundService;
|
||||
|
||||
public ApiCompoundController(ISysConfigService sysConfigService,
|
||||
TtUserService userService,
|
||||
ApiCompoundService compoundService) {
|
||||
this.sysConfigService = sysConfigService;
|
||||
this.userService = userService;
|
||||
this.compoundService = compoundService;
|
||||
}
|
||||
|
||||
@ApiOperation("合成")
|
||||
@PostMapping("/compound")
|
||||
public R<UserPackSackDataVO> compound(@RequestBody List<Long> packSackIds) {
|
||||
String websiteMaintenance = sysConfigService.selectConfigByKey("websiteMaintenance");
|
||||
if ("1".equals(websiteMaintenance)) {
|
||||
return R.fail("网站维护中......");
|
||||
}
|
||||
String compoundMaintenance = sysConfigService.selectConfigByKey("compoundMaintenance");
|
||||
if ("1".equals(compoundMaintenance)) {
|
||||
return R.fail("汰换合成功能正在维护中......");
|
||||
}
|
||||
TtUser ttUser = userService.getById(getUserId());
|
||||
return compoundService.compound(packSackIds, ttUser);
|
||||
}
|
||||
|
||||
@ApiOperation("获取用户合成记录")
|
||||
@GetMapping("/getUserCompoundRecord")
|
||||
public PageDataInfo<UserPackSackDataVO> getUserCompoundRecord() {
|
||||
startPage();
|
||||
List<UserPackSackDataVO> userCompoundRecord = compoundService.getUserCompoundRecord(getUserId().intValue());
|
||||
return getPageData(userCompoundRecord);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,125 @@
|
||||
package com.ruoyi.playingmethod.controller;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import com.ruoyi.admin.mapper.TtUserBlendErcashMapper;
|
||||
import com.ruoyi.admin.service.TtBoxService;
|
||||
import com.ruoyi.admin.service.TtUserService;
|
||||
import com.ruoyi.common.annotation.Anonymous;
|
||||
import com.ruoyi.common.annotation.UpdateUserCache;
|
||||
import com.ruoyi.common.core.controller.BaseController;
|
||||
import com.ruoyi.common.core.domain.R;
|
||||
import com.ruoyi.common.utils.PageUtils;
|
||||
import com.ruoyi.domain.common.constant.TtAccountRecordSource;
|
||||
import com.ruoyi.domain.common.constant.TtAccountRecordType;
|
||||
import com.ruoyi.domain.dto.exponent.ExponentJoinParam;
|
||||
import com.ruoyi.domain.entity.TtUserBlendErcash;
|
||||
import com.ruoyi.domain.entity.sys.TtUser;
|
||||
import com.ruoyi.domain.other.TtBox;
|
||||
import com.ruoyi.playingmethod.mapper.ApiBindBoxMapper;
|
||||
import com.ruoyi.playingmethod.service.ApiExponentService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiImplicitParam;
|
||||
import io.swagger.annotations.ApiImplicitParams;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
||||
@Api(tags = "指数盲盒")
|
||||
@RestController
|
||||
@RequestMapping("/api/exponent")
|
||||
public class ApiExponentController extends BaseController {
|
||||
|
||||
@Autowired
|
||||
private ApiExponentService apiExponentService;
|
||||
|
||||
@Autowired
|
||||
private TtUserService ttUserService;
|
||||
|
||||
@Autowired
|
||||
private ApiBindBoxMapper bindBoxMapper;
|
||||
|
||||
@Autowired
|
||||
private TtBoxService boxService;
|
||||
|
||||
@Autowired
|
||||
private TtUserBlendErcashMapper ttUserBlendErcashMapper;
|
||||
|
||||
@ApiOperation("加入指数盲盒")
|
||||
@Anonymous
|
||||
@UpdateUserCache
|
||||
@PostMapping("/join")
|
||||
public R join(@RequestBody @Validated ExponentJoinParam param) {
|
||||
TtUser ttUser = ttUserService.getById(getUserId());
|
||||
|
||||
LambdaQueryWrapper<TtUserBlendErcash> queryWrapper = Wrappers.lambdaQuery();
|
||||
queryWrapper.eq(TtUserBlendErcash::getUserId, ttUser.getUserId())
|
||||
.eq(TtUserBlendErcash::getType, TtAccountRecordType.INPUT.getCode())
|
||||
.eq(TtUserBlendErcash::getSource, TtAccountRecordSource.RECHARGE.getCode())
|
||||
.select(TtUserBlendErcash::getTotal);
|
||||
List<TtUserBlendErcash> ercash = ttUserBlendErcashMapper.selectList(queryWrapper);
|
||||
if (CollectionUtils.isEmpty(ercash)) {
|
||||
return R.fail("您的账户未进行充过值!");
|
||||
}
|
||||
|
||||
return apiExponentService.join(ttUser, param);
|
||||
}
|
||||
|
||||
@ApiOperation("获取宝箱列表")
|
||||
@ApiImplicitParams({
|
||||
@ApiImplicitParam(name = "boxType", value = "宝箱类型(1普通箱 2对战箱 3补偿箱 4九宫格 5指数盲盒)", dataType = "String", dataTypeClass = String.class)
|
||||
})
|
||||
@Anonymous
|
||||
@GetMapping("/box")
|
||||
public R box(@RequestParam("id") Integer id) {
|
||||
TtUser ttUser = ttUserService.getById(getUserId());
|
||||
return apiExponentService.box(ttUser, id);
|
||||
}
|
||||
|
||||
@ApiOperation("最近十期结果")
|
||||
@Anonymous
|
||||
@GetMapping("/recenttenperiod")
|
||||
public R recenttenperiod() {
|
||||
PageUtils.clearPage();
|
||||
return apiExponentService.recenttenperiod();
|
||||
}
|
||||
|
||||
@ApiOperation("结果信息")
|
||||
@Anonymous
|
||||
@GetMapping("/info")
|
||||
public R info() {
|
||||
PageUtils.clearPage();
|
||||
TtUser ttUser = ttUserService.getById(getUserId());
|
||||
return apiExponentService.info(ttUser);
|
||||
}
|
||||
|
||||
@ApiOperation("指数记录")
|
||||
@Anonymous
|
||||
@GetMapping("/records")
|
||||
public R records() {
|
||||
startPage();
|
||||
TtUser ttUser = ttUserService.getById(getUserId());
|
||||
return apiExponentService.records(ttUser);
|
||||
}
|
||||
|
||||
@ApiOperation("我的箱子")
|
||||
@Anonymous
|
||||
@GetMapping("/mybox")
|
||||
public R mybox() {
|
||||
TtUser ttUser = ttUserService.getById(getUserId());
|
||||
return apiExponentService.mybox(ttUser);
|
||||
}
|
||||
@ApiOperation("盲盒开箱")
|
||||
@UpdateUserCache
|
||||
@GetMapping("/openBox")
|
||||
public R openBox(@RequestParam("boxId") Integer boxId, @RequestParam("num") Integer num) {
|
||||
TtUser ttUser = ttUserService.getById(getUserId());
|
||||
TtBox ttBox = boxService.getById(boxId);
|
||||
return apiExponentService.openbox(ttUser, ttBox, num);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,492 @@
|
||||
package com.ruoyi.playingmethod.controller;
|
||||
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
|
||||
import com.ruoyi.admin.mapper.TtUserBlendErcashMapper;
|
||||
import com.ruoyi.admin.mapper.TtUserMapper;
|
||||
import com.ruoyi.admin.service.*;
|
||||
import com.ruoyi.admin.util.core.fight.LotteryMachine;
|
||||
import com.ruoyi.common.annotation.Anonymous;
|
||||
import com.ruoyi.common.annotation.UpdateUserCache;
|
||||
import com.ruoyi.common.core.controller.BaseController;
|
||||
import com.ruoyi.common.core.domain.AjaxResult;
|
||||
import com.ruoyi.common.core.domain.R;
|
||||
import com.ruoyi.common.core.page.PageDataInfo;
|
||||
import com.ruoyi.common.core.redis.RedisCache;
|
||||
import com.ruoyi.common.utils.RandomUtil;
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
import com.ruoyi.domain.common.constant.TtAccountRecordSource;
|
||||
import com.ruoyi.domain.common.constant.TtAccountRecordType;
|
||||
import com.ruoyi.domain.common.constant.UserType;
|
||||
import com.ruoyi.domain.dto.fight.FightDetailParam;
|
||||
import com.ruoyi.domain.dto.fight.FightOnMyOwnParam;
|
||||
import com.ruoyi.domain.entity.TtUserBlendErcash;
|
||||
import com.ruoyi.domain.entity.fight.TtFight;
|
||||
import com.ruoyi.domain.entity.sys.TtUser;
|
||||
import com.ruoyi.domain.other.CreateFightBody;
|
||||
import com.ruoyi.domain.other.FightBoutData;
|
||||
import com.ruoyi.domain.other.TtBox;
|
||||
import com.ruoyi.domain.other.TtBoxVO;
|
||||
import com.ruoyi.domain.vo.ApiFightListDataVO;
|
||||
import com.ruoyi.domain.vo.FightResultDataVO;
|
||||
import com.ruoyi.domain.vo.fight.FightResultVO;
|
||||
import com.ruoyi.domain.vo.upgrade.SimpleOrnamentVO;
|
||||
import com.ruoyi.playingmethod.model.vo.ApiFightRankingVO;
|
||||
import com.ruoyi.playingmethod.service.ApiFightService;
|
||||
import com.ruoyi.system.service.ISysConfigService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@Api(tags = "对战模式")
|
||||
@Slf4j
|
||||
@RestController
|
||||
@RequestMapping("/api/fight")
|
||||
public class ApiFightController extends BaseController {
|
||||
|
||||
private final TtFightResultService fightResultService;
|
||||
private final ISysConfigService sysConfigService;
|
||||
private final TtUserService userService;
|
||||
private final ApiFightService apiFightService;
|
||||
private final RedisCache redisCache;
|
||||
|
||||
@Autowired
|
||||
private TtBoxOrnamentsService boxOrnamentsService;
|
||||
|
||||
@Autowired
|
||||
private TtOrnamentService ttOrnamentService;
|
||||
|
||||
@Autowired
|
||||
private LotteryMachine lotteryMachine;
|
||||
|
||||
@Autowired
|
||||
private TtBoxService boxService;
|
||||
|
||||
@Autowired
|
||||
private TtUserMapper ttUserMapper;
|
||||
|
||||
public ApiFightController(TtFightResultService fightResultService,
|
||||
ISysConfigService sysConfigService,
|
||||
TtUserService userService,
|
||||
ApiFightService apiFightService,
|
||||
RedisCache redisCache) {
|
||||
this.fightResultService = fightResultService;
|
||||
this.sysConfigService = sysConfigService;
|
||||
this.userService = userService;
|
||||
this.apiFightService = apiFightService;
|
||||
this.redisCache = redisCache;
|
||||
}
|
||||
|
||||
@Autowired
|
||||
private TtUserBlendErcashMapper ttUserBlendErcashMapper;
|
||||
|
||||
public R checkLogin() {
|
||||
Long userId;
|
||||
try {
|
||||
userId = getUserId();
|
||||
if (ObjectUtil.isEmpty(userId)) return R.fail(401, "登录过期,请重新登录。");
|
||||
return R.ok(userId);
|
||||
} catch (Exception e) {
|
||||
return R.fail("登录过期,请重新登录。");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Step1 创建对战房间
|
||||
*/
|
||||
@ApiOperation("创建对战房间")
|
||||
@UpdateUserCache
|
||||
@PostMapping("/createFight")
|
||||
public R createFight(@Validated @RequestBody CreateFightBody createFightParam) {
|
||||
String websiteMaintenance = sysConfigService.selectConfigByKey("websiteMaintenance");
|
||||
if ("1".equals(websiteMaintenance)) {
|
||||
return R.fail("网站维护中......");
|
||||
}
|
||||
String fightMaintenance = sysConfigService.selectConfigByKey("fightMaintenance");
|
||||
if ("1".equals(fightMaintenance)) {
|
||||
return R.fail("开箱对战功能正在维护中......");
|
||||
}
|
||||
R checkLogin = checkLogin();
|
||||
if (!checkLogin.getCode().equals(200)) {
|
||||
return checkLogin;
|
||||
}
|
||||
Integer userId = ((Long) checkLogin.getData()).intValue();
|
||||
TtUser player = userService.getById(userId);
|
||||
|
||||
LambdaQueryWrapper<TtUserBlendErcash> queryWrapper = Wrappers.lambdaQuery();
|
||||
queryWrapper.eq(TtUserBlendErcash::getUserId, userId)
|
||||
.eq(TtUserBlendErcash::getType, TtAccountRecordType.INPUT.getCode())
|
||||
.eq(TtUserBlendErcash::getSource, TtAccountRecordSource.RECHARGE.getCode())
|
||||
.select(TtUserBlendErcash::getTotal);
|
||||
List<TtUserBlendErcash> ercash = ttUserBlendErcashMapper.selectList(queryWrapper);
|
||||
if (CollectionUtils.isEmpty(ercash)) {
|
||||
return R.fail("您的账户未进行充过值!");
|
||||
}
|
||||
|
||||
return apiFightService.createFight(createFightParam, player);
|
||||
}
|
||||
|
||||
/**
|
||||
* Step2 加入房间(占座),先行HTTP
|
||||
*/
|
||||
@ApiOperation("加入对战房间")
|
||||
@PostMapping("/joinFightRoom")
|
||||
public R joinFightRoom(@RequestParam("fightId") Integer fightId) {
|
||||
String websiteMaintenance = sysConfigService.selectConfigByKey("websiteMaintenance");
|
||||
if ("1".equals(websiteMaintenance)) {
|
||||
return R.fail("网站维护中......");
|
||||
}
|
||||
String fightMaintenance = sysConfigService.selectConfigByKey("fightMaintenance");
|
||||
if ("1".equals(fightMaintenance)) {
|
||||
return R.fail("开箱对战功能正在维护中......");
|
||||
}
|
||||
R checkLogin = checkLogin();
|
||||
if (!checkLogin.getCode().equals(200)) return checkLogin;
|
||||
Integer userId = ((Long) checkLogin.getData()).intValue();
|
||||
|
||||
LambdaQueryWrapper<TtUserBlendErcash> queryWrapper = Wrappers.lambdaQuery();
|
||||
queryWrapper.eq(TtUserBlendErcash::getUserId, userId)
|
||||
.eq(TtUserBlendErcash::getType, TtAccountRecordType.INPUT.getCode())
|
||||
.eq(TtUserBlendErcash::getSource, TtAccountRecordSource.RECHARGE.getCode())
|
||||
.select(TtUserBlendErcash::getTotal);
|
||||
List<TtUserBlendErcash> ercash = ttUserBlendErcashMapper.selectList(queryWrapper);
|
||||
if (CollectionUtils.isEmpty(ercash)) {
|
||||
return R.fail("您的账户未进行充过值!");
|
||||
}
|
||||
|
||||
TtUser player = userService.getById(userId);
|
||||
|
||||
return apiFightService.joinFight(fightId, player);
|
||||
}
|
||||
|
||||
/**
|
||||
* 退出房间
|
||||
*/
|
||||
@ApiOperation("退出房间")
|
||||
@PostMapping("/fightRoomExit")
|
||||
public R fightRoomExit(@RequestParam("fightId") Integer fightId) {
|
||||
String websiteMaintenance = sysConfigService.selectConfigByKey("websiteMaintenance");
|
||||
if ("1".equals(websiteMaintenance)) return R.fail("网站维护中......");
|
||||
String fightMaintenance = sysConfigService.selectConfigByKey("fightMaintenance");
|
||||
if ("1".equals(fightMaintenance)) return R.fail("开箱对战功能正在维护中......");
|
||||
|
||||
R checkLogin = checkLogin();
|
||||
if (!checkLogin.getCode().equals(200)) return checkLogin;
|
||||
Integer userId = ((Long) checkLogin.getData()).intValue();
|
||||
|
||||
TtUser player = userService.getById(userId);
|
||||
|
||||
return apiFightService.fightRoomExit(fightId, player);
|
||||
}
|
||||
|
||||
/**
|
||||
* Step3 玩家准备游戏
|
||||
*/
|
||||
@ApiOperation("玩家准备游戏")
|
||||
@UpdateUserCache
|
||||
@GetMapping("/seatrReady")
|
||||
public R seatrReady(@RequestParam("fightId") Integer fightId) {
|
||||
String websiteMaintenance = sysConfigService.selectConfigByKey("websiteMaintenance");
|
||||
if ("1".equals(websiteMaintenance)) {
|
||||
return R.fail("网站维护中......");
|
||||
}
|
||||
String fightMaintenance = sysConfigService.selectConfigByKey("fightMaintenance");
|
||||
if ("1".equals(fightMaintenance)) {
|
||||
return R.fail("开箱对战功能正在维护中......");
|
||||
}
|
||||
|
||||
R checkLogin = checkLogin();
|
||||
if (!checkLogin.getCode().equals(200)) return checkLogin;
|
||||
Integer userId = ((Long) checkLogin.getData()).intValue();
|
||||
|
||||
TtUser player = userService.getById(userId);
|
||||
|
||||
return apiFightService.seatrReady(fightId, player);
|
||||
}
|
||||
|
||||
/**
|
||||
* Step4 开始游戏(前端满人自动开始)
|
||||
*/
|
||||
@ApiOperation("开始游戏")
|
||||
@GetMapping("/fightBegin")
|
||||
public R fightBegin(@RequestParam("fightId") Integer fightId) {
|
||||
String websiteMaintenance = sysConfigService.selectConfigByKey("websiteMaintenance");
|
||||
if ("1".equals(websiteMaintenance)) {
|
||||
return R.fail("网站维护中......");
|
||||
}
|
||||
String fightMaintenance = sysConfigService.selectConfigByKey("fightMaintenance");
|
||||
if ("1".equals(fightMaintenance)) {
|
||||
return R.fail("开箱对战功能正在维护中......");
|
||||
}
|
||||
|
||||
R checkLogin = checkLogin();
|
||||
if (!checkLogin.getCode().equals(200)) return checkLogin;
|
||||
Integer userId = ((Long) checkLogin.getData()).intValue();
|
||||
|
||||
TtUser player = userService.getById(userId);
|
||||
|
||||
return apiFightService.fightBegin(fightId, player);
|
||||
}
|
||||
|
||||
/**
|
||||
* 观战
|
||||
*/
|
||||
@ApiOperation("观战")
|
||||
@GetMapping("/audience")
|
||||
public R audience(@RequestParam("fightId") Integer fightId) {
|
||||
String websiteMaintenance = sysConfigService.selectConfigByKey("websiteMaintenance");
|
||||
if ("1".equals(websiteMaintenance)) {
|
||||
return R.fail("网站维护中......");
|
||||
}
|
||||
String fightMaintenance = sysConfigService.selectConfigByKey("fightMaintenance");
|
||||
if ("1".equals(fightMaintenance)) {
|
||||
return R.fail("开箱对战功能正在维护中......");
|
||||
}
|
||||
|
||||
R checkLogin = checkLogin();
|
||||
if (!checkLogin.getCode().equals(200)) return checkLogin;
|
||||
|
||||
return apiFightService.audience(fightId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 游戏结束标记
|
||||
*/
|
||||
@ApiOperation("游戏结束标记")
|
||||
@GetMapping("/fightEnd")
|
||||
public R fightEnd(@RequestParam("fightId") Integer fightId) {
|
||||
String websiteMaintenance = sysConfigService.selectConfigByKey("websiteMaintenance");
|
||||
if ("1".equals(websiteMaintenance)) return R.fail("网站维护中......");
|
||||
String fightMaintenance = sysConfigService.selectConfigByKey("fightMaintenance");
|
||||
if ("1".equals(fightMaintenance)) return R.fail("开箱对战功能正在维护中......");
|
||||
|
||||
R checkLogin = checkLogin();
|
||||
if (!checkLogin.getCode().equals(200)) return checkLogin;
|
||||
|
||||
return apiFightService.fightEnd(fightId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 抽奖机测试
|
||||
*/
|
||||
// @ApiOperation("抽奖机测试")
|
||||
// @GetMapping("LotteryMachineTest")
|
||||
public R LotteryMachineTest() {
|
||||
R checkLogin = checkLogin();
|
||||
if (!checkLogin.getCode().equals(200)) return checkLogin;
|
||||
Integer userId = ((Long) checkLogin.getData()).intValue();
|
||||
TtUser player = userService.getById(userId);
|
||||
|
||||
TtBox box = boxService.getById(2L);
|
||||
String ornamentId = lotteryMachine.singleLottery(player, box);
|
||||
|
||||
return R.ok(ornamentId);
|
||||
}
|
||||
|
||||
@ApiOperation("我参与的历史对战记录")
|
||||
@PostMapping("/fightOnMyOwn")
|
||||
public R fightOnMyOwn(@RequestBody FightOnMyOwnParam param) {
|
||||
Long userId = getUserId();
|
||||
if (ObjectUtil.isNull(userId)) return R.fail(401, "登录过期。");
|
||||
|
||||
param.setPlayerId(userId.intValue());
|
||||
|
||||
List<ApiFightListDataVO> list = apiFightService.getFightList(param);
|
||||
return R.ok(list);
|
||||
}
|
||||
|
||||
@ApiOperation("全服历史对战记录")
|
||||
@PostMapping("/fightOnAll")
|
||||
public R fightOnAll(@RequestBody FightOnMyOwnParam param) {
|
||||
List<ApiFightListDataVO> list = apiFightService.getFightList(param);
|
||||
return R.ok(list);
|
||||
}
|
||||
|
||||
@ApiOperation("历史对战详情")
|
||||
@PostMapping("/fightDetail")
|
||||
public R fightDetail(@RequestBody FightDetailParam param) {
|
||||
return apiFightService.fightDetail(param);
|
||||
}
|
||||
|
||||
@ApiOperation("获取指定记录更早的历史对战")
|
||||
@PostMapping("/earlierHistory")
|
||||
public R earlierHistory(@RequestBody FightDetailParam param) {
|
||||
return apiFightService.earlierHistory(param);
|
||||
}
|
||||
|
||||
@ApiOperation("获取对战宝箱详情")
|
||||
@GetMapping("/simpleBoxDetail")
|
||||
public PageDataInfo<SimpleOrnamentVO> simpleBoxDetail(Integer boxId) {
|
||||
startPage();
|
||||
List<SimpleOrnamentVO> list = boxOrnamentsService.simpleBoxDetail(boxId);
|
||||
return getPageData(list);
|
||||
}
|
||||
|
||||
@ApiOperation("获取对战宝箱")
|
||||
@GetMapping("/getFightBoxList")
|
||||
@Anonymous
|
||||
public R<List<TtBoxVO>> getFightBoxList(@RequestParam(value = "boxTypeId", required = false) Integer boxTypeId) {
|
||||
List<TtBoxVO> boxData = apiFightService.getFightBoxList(boxTypeId);
|
||||
if (ObjectUtil.isEmpty(boxData) || boxData.isEmpty()) return R.ok(null, "没有匹配的数据。");
|
||||
return R.ok(boxData);
|
||||
}
|
||||
|
||||
@ApiOperation("获取对战列表")
|
||||
@Anonymous
|
||||
@GetMapping("/getFightList")
|
||||
public PageDataInfo<ApiFightListDataVO> getFightList(@RequestParam(required = false) String model,
|
||||
@RequestParam(required = false) String status,
|
||||
@RequestParam(required = false) Integer userId) {
|
||||
startPage();
|
||||
List<ApiFightListDataVO> list = apiFightService.getFightList(model, status, userId, null);
|
||||
return getPageData(list);
|
||||
}
|
||||
|
||||
@ApiOperation("获取对战数据")
|
||||
@GetMapping("/getFightData/{fightId}")
|
||||
public R<ApiFightListDataVO> getFightData(@PathVariable("fightId") Integer fightId) {
|
||||
ApiFightListDataVO apiFightListDataVO = apiFightService.getFightList(null, null, null, fightId).get(0);
|
||||
return R.ok(apiFightListDataVO);
|
||||
}
|
||||
|
||||
// @ApiOperation("获取对战结果")
|
||||
// @GetMapping("/getFightResult/{fightId}")
|
||||
// public R<FightResultDataVO> getFightResult(@PathVariable("fightId") Integer fightId) {
|
||||
// FightResultDataVO fightResultDataVO = fightResultService.getFightResult(fightId);
|
||||
// return R.ok(fightResultDataVO);
|
||||
// }
|
||||
|
||||
@ApiOperation("获取对战结果")
|
||||
@GetMapping("/getFightResult/{fightId}")
|
||||
public R<FightResultVO> getFightResult(@PathVariable("fightId") Integer fightId) {
|
||||
FightResultVO fightResultVO = fightResultService.getFightResult(fightId);
|
||||
return R.ok(fightResultVO);
|
||||
}
|
||||
|
||||
@ApiOperation("存储对战回合数据")
|
||||
@PostMapping("/saveFightBoutData")
|
||||
public R<Boolean> saveFightBoutData(@RequestBody FightBoutData fightBoutData) {
|
||||
String key = "fight_bout_data:fight_" + fightBoutData.getFightId();
|
||||
redisCache.setCacheObject(key, fightBoutData, fightBoutData.getExpirationTime(), TimeUnit.MILLISECONDS);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
@ApiOperation("获取对战回合数")
|
||||
@PostMapping("/getFightBoutNum/{fightId}")
|
||||
public R<Integer> getFightBoutNum(@PathVariable Integer fightId) {
|
||||
String key = "fight_bout_data:fight_" + fightId;
|
||||
FightBoutData fightBoutData = redisCache.getCacheObject(key);
|
||||
if (StringUtils.isNotNull(fightBoutData)) {
|
||||
return R.ok(fightBoutData.getBoutNum());
|
||||
} else {
|
||||
// return R.fail("对战回合不存在");
|
||||
return R.ok();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前回合开箱结果
|
||||
*/
|
||||
// @GetMapping("/getFightRecord")
|
||||
public R<FightResultDataVO> getFightRecord(@RequestParam(value = "fightId", required = false) Integer fightId,
|
||||
@RequestParam(value = "round", required = false) Integer round,
|
||||
@RequestParam(value = "rounds", required = false) Integer rounds) {
|
||||
// System.out.println("=========================获取当前回合开箱结果=============================");
|
||||
// System.out.println("fightId:" + fightId);
|
||||
// System.out.println("round:" + round);
|
||||
// System.out.println("rounds:" + rounds);
|
||||
|
||||
log.info("获取当前回合开箱结果 api /{} 参数fightId{} round{} rounds{}", "getFightRecord", fightId, round, rounds);
|
||||
|
||||
// 检查是否已经开始游戏
|
||||
TtFight fight = apiFightService.getById(fightId);
|
||||
if (ObjectUtil.isEmpty(fight)) return R.fail("不存在的对局");
|
||||
if (fight.getStatus().equals(0)) return R.fail("对局尚未开始,请稍后重试。");
|
||||
|
||||
FightResultDataVO fightResultDataVO = apiFightService.getFightRecord(fightId, round, rounds);
|
||||
if (ObjectUtil.isEmpty(fightResultDataVO)) {
|
||||
return R.fail("对局fightId 没有产生结果");
|
||||
}
|
||||
return R.ok(fightResultDataVO);
|
||||
}
|
||||
|
||||
@ApiOperation("获取对战排行榜")
|
||||
@Anonymous
|
||||
@GetMapping("/fightRanking")
|
||||
public AjaxResult getFightRanking() {
|
||||
// 创建日期格式化对象,指定日期格式
|
||||
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
|
||||
|
||||
// 获取今天日期
|
||||
Date today = new Date();
|
||||
String formattedTodayDate = formatter.format(today);
|
||||
List<ApiFightRankingVO> todayFightRanking = apiFightService.getFightRankingByDate(formattedTodayDate);
|
||||
|
||||
// 获取昨天日期
|
||||
Calendar cal = Calendar.getInstance();
|
||||
cal.add(Calendar.DATE, -1);
|
||||
Date yesterday = cal.getTime();
|
||||
String formattedYesterdayDate = formatter.format(yesterday);
|
||||
List<ApiFightRankingVO> yesterdayFightRanking = apiFightService.getFightRankingByDate(formattedYesterdayDate);
|
||||
|
||||
Map<String, List<ApiFightRankingVO>> map = new HashMap<>();
|
||||
map.put("todayFightRanking", todayFightRanking);
|
||||
map.put("yesterdayFightRanking", yesterdayFightRanking);
|
||||
return AjaxResult.success(map);
|
||||
}
|
||||
|
||||
@ApiOperation("十佳对战, 1:最大金额,2:最大增长,3:最大倍数")
|
||||
@Anonymous
|
||||
@GetMapping("/tenTopFight")
|
||||
public AjaxResult tenTopFight(@RequestParam("maxType") Integer maxType) {
|
||||
return AjaxResult.success(apiFightService.tenTopFight(maxType));
|
||||
}
|
||||
|
||||
@ApiOperation("邀请机器人加入对战房间")
|
||||
@PostMapping({"/joinFightRoomForRobot"})
|
||||
public R joinFightRoomForRobot(@RequestParam("fightId") Integer fightId) {
|
||||
String websiteMaintenance = this.sysConfigService.selectConfigByKey("websiteMaintenance");
|
||||
if ("1".equals(websiteMaintenance)) {
|
||||
return R.fail("网站维护中......");
|
||||
} else {
|
||||
String fightMaintenance = this.sysConfigService.selectConfigByKey("fightMaintenance");
|
||||
if ("1".equals(fightMaintenance)) {
|
||||
return R.fail("开箱对战功能正在维护中......");
|
||||
} else {
|
||||
List<TtUser> robotIdList = new LambdaQueryChainWrapper<TtUser>(this.ttUserMapper)
|
||||
.eq(TtUser::getUserType, UserType.ROBOT_USER.getCode()).list();
|
||||
if (CollectionUtils.isEmpty(robotIdList)) {
|
||||
return R.ok();
|
||||
} else {
|
||||
TtUser player = RandomUtil.choice(robotIdList);
|
||||
R<Object> objectR = this.apiFightService.joinFight(fightId, player);
|
||||
if (objectR.getCode() == 500) {
|
||||
return objectR;
|
||||
} else {
|
||||
log.info("机器人{}加入对战{}", player.getUserId(), fightId);
|
||||
R fight = this.apiFightService.seatrReady(fightId, player);
|
||||
log.info("fight robot task fight is {}", fight == null ? "null" : fight.toString());
|
||||
FightBoutData fightBoutData = new FightBoutData();
|
||||
fightBoutData.setFightId(fightId);
|
||||
fightBoutData.setBoutNum(1);
|
||||
fightBoutData.setExpirationTime(16000);
|
||||
String key = "fight_bout_data:fight_" + fightBoutData.getFightId();
|
||||
this.redisCache.setCacheObject(key, fightBoutData, fightBoutData.getExpirationTime(), TimeUnit.MILLISECONDS);
|
||||
this.apiFightService.fightBegin(fightId, player);
|
||||
return R.ok();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,128 @@
|
||||
package com.ruoyi.playingmethod.controller;
|
||||
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import com.ruoyi.admin.mapper.TtUserBlendErcashMapper;
|
||||
import com.ruoyi.common.core.domain.AjaxResult;
|
||||
import com.ruoyi.admin.service.TtUserService;
|
||||
import com.ruoyi.common.annotation.Anonymous;
|
||||
import com.ruoyi.common.annotation.UpdateUserCache;
|
||||
import com.ruoyi.common.core.controller.BaseController;
|
||||
import com.ruoyi.common.core.domain.R;
|
||||
import com.ruoyi.domain.common.constant.TtAccountRecordSource;
|
||||
import com.ruoyi.domain.common.constant.TtAccountRecordType;
|
||||
import com.ruoyi.domain.dto.upgrade.UpgradeCondition;
|
||||
import com.ruoyi.domain.entity.TtUserBlendErcash;
|
||||
import com.ruoyi.domain.other.ApiLuckyUpgradeBody;
|
||||
import com.ruoyi.domain.entity.sys.TtUser;
|
||||
import com.ruoyi.domain.other.UpgradeBodyA;
|
||||
import com.ruoyi.domain.vo.ApiLuckyOrnamentsDataVO;
|
||||
import com.ruoyi.playingmethod.service.ApiLuckyUpgradeService;
|
||||
import com.ruoyi.playingmethod.service.ApiUpgradeRecordService;
|
||||
import com.ruoyi.system.service.ISysConfigService;
|
||||
import com.ruoyi.user.service.ApiUserPackSackService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.hibernate.validator.constraints.Range;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import jakarta.validation.constraints.Min;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.List;
|
||||
|
||||
@Api(tags = "幸运升级模式")
|
||||
@RestController
|
||||
@RequestMapping("/api/luckyUpgrade")
|
||||
public class ApiLuckyUpgradeController extends BaseController {
|
||||
|
||||
@Autowired
|
||||
private ApiUserPackSackService userPackSackService;
|
||||
|
||||
@Autowired
|
||||
private ApiUpgradeRecordService upgradeRecordService;
|
||||
|
||||
private final TtUserService userService;
|
||||
private final ApiLuckyUpgradeService apiLuckyUpgradeService;
|
||||
private final ISysConfigService sysConfigService;
|
||||
|
||||
public ApiLuckyUpgradeController(TtUserService userService,
|
||||
ApiLuckyUpgradeService apiLuckyUpgradeService,
|
||||
ISysConfigService sysConfigService) {
|
||||
this.userService = userService;
|
||||
this.apiLuckyUpgradeService = apiLuckyUpgradeService;
|
||||
this.sysConfigService = sysConfigService;
|
||||
}
|
||||
|
||||
@Autowired
|
||||
private TtUserBlendErcashMapper ttUserBlendErcashMapper;
|
||||
|
||||
public R checkLogin(){
|
||||
Long userId;
|
||||
try {
|
||||
userId = getUserId();
|
||||
if (ObjectUtil.isEmpty(userId)) AjaxResult.error(401,"登录过期,请重新登录。");
|
||||
return R.ok(userId);
|
||||
}catch (Exception e){
|
||||
return R.fail(401,"登录过期,请重新登录。");
|
||||
}
|
||||
}
|
||||
|
||||
@ApiOperation("获取可升级的饰品列表")
|
||||
@Anonymous
|
||||
@GetMapping("/getOrnamentsList")
|
||||
public R<List<ApiLuckyOrnamentsDataVO>> getOrnamentsList(ApiLuckyUpgradeBody apiLuckyUpgradeBody){
|
||||
List<ApiLuckyOrnamentsDataVO> list = apiLuckyUpgradeService.getOrnamentsList(apiLuckyUpgradeBody);
|
||||
return R.ok(list);
|
||||
}
|
||||
|
||||
@ApiOperation("幸运升级")
|
||||
@UpdateUserCache
|
||||
@PostMapping("/upgrade")
|
||||
public R upgrade(@RequestBody @Validated UpgradeBodyA upgradeParam){
|
||||
String websiteMaintenance = sysConfigService.selectConfigByKey("websiteMaintenance");
|
||||
if ("1".equals(websiteMaintenance)) return R.fail("网站维护中......");
|
||||
|
||||
R check = checkLogin();
|
||||
if (!check.getCode().equals(200)) return R.fail(401,"登录过期,请重新登录。");
|
||||
Integer userId = ((Long)check.getData()).intValue();
|
||||
|
||||
TtUser ttUser = userService.getById(userId);
|
||||
BigDecimal add = ttUser.getAccountAmount();
|
||||
|
||||
if (add.compareTo(upgradeParam.getPrice()) <= 0) {
|
||||
return R.fail("余额不足!");
|
||||
}
|
||||
|
||||
LambdaQueryWrapper<TtUserBlendErcash> queryWrapper = Wrappers.lambdaQuery();
|
||||
queryWrapper.eq(TtUserBlendErcash::getUserId, userId)
|
||||
.eq(TtUserBlendErcash::getType, TtAccountRecordType.INPUT.getCode())
|
||||
.eq(TtUserBlendErcash::getSource, TtAccountRecordSource.RECHARGE.getCode())
|
||||
.select(TtUserBlendErcash::getTotal);
|
||||
List<TtUserBlendErcash> ercash = ttUserBlendErcashMapper.selectList(queryWrapper);
|
||||
if (CollectionUtils.isEmpty(ercash)) {
|
||||
return R.fail("您的账户未进行充过值!");
|
||||
}
|
||||
|
||||
return apiLuckyUpgradeService.upgrade(ttUser, upgradeParam);
|
||||
}
|
||||
|
||||
@ApiOperation("获取幸运升级历史记录")
|
||||
@PostMapping("/getUpgradeRecord")
|
||||
public R getUpgradeRecord(@RequestBody @Validated UpgradeCondition param){
|
||||
return upgradeRecordService.historyDetail(param);
|
||||
}
|
||||
|
||||
@ApiOperation("获取幸运升级十佳记录")
|
||||
@GetMapping("/tenTopUpgradeRecord")
|
||||
public R tenTopUpgradeRecord(@RequestParam(required = false) Boolean isVictory){
|
||||
return upgradeRecordService.tenTopDetail(isVictory);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
package com.ruoyi.playingmethod.controller;
|
||||
|
||||
import com.ruoyi.common.annotation.NoRepeatSubmit;
|
||||
import com.ruoyi.common.annotation.UserPermission;
|
||||
import com.ruoyi.common.core.controller.BaseController;
|
||||
import com.ruoyi.common.core.domain.AjaxResult;
|
||||
import com.ruoyi.common.core.domain.model.LoginUser;
|
||||
import com.ruoyi.common.core.page.TableDataInfo;
|
||||
import com.ruoyi.domain.other.TtRedPack;
|
||||
import com.ruoyi.domain.other.TtRedPacketRecord;
|
||||
import com.ruoyi.playingmethod.service.ApiRedPackService;
|
||||
import com.ruoyi.thirdparty.wechat.domain.PtLoginUser;
|
||||
import com.ruoyi.thirdparty.wechat.service.ApiTokenService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 不用这个api领红包了
|
||||
*
|
||||
* @see com.ruoyi.user.controller.ApiBonusController
|
||||
*/
|
||||
@Deprecated
|
||||
@RestController
|
||||
@RequestMapping("/api/redPackData")
|
||||
@Api(tags = "红包")
|
||||
public class ApiRedPackContoller extends BaseController {
|
||||
|
||||
@Autowired
|
||||
private ApiTokenService tokenService;
|
||||
|
||||
@Autowired
|
||||
private ApiRedPackService redPackService;
|
||||
|
||||
@PostMapping("/getRedPackList")
|
||||
@UserPermission
|
||||
@NoRepeatSubmit
|
||||
@ApiOperation(value = "获取红包列表")
|
||||
public TableDataInfo getRedPackList(HttpServletRequest request, Integer type) {
|
||||
PtLoginUser user = tokenService.getLoginUser(request);
|
||||
|
||||
startPage();
|
||||
List<TtRedPack> redPacks = redPackService.getRedPackList(user, type);
|
||||
|
||||
return getDataTable(redPacks);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@PostMapping("/getRedPack")
|
||||
@UserPermission
|
||||
@NoRepeatSubmit
|
||||
@ApiOperation(value = "领取红包")
|
||||
public AjaxResult getRedPack(@RequestParam("redPackId") Long redPackId) {
|
||||
Long userId = getUserId();
|
||||
return redPackService.getRedPack(userId, redPackId);
|
||||
}
|
||||
|
||||
@PostMapping("/getRedPackByKey")
|
||||
@UserPermission
|
||||
@NoRepeatSubmit
|
||||
@ApiOperation(value = "根据红包口令兑换红包")
|
||||
public AjaxResult getRedPackByKey(@RequestParam("redPackKey") String redPackKey) {
|
||||
LoginUser loginUser = getLoginUser();
|
||||
if (redPackKey == null || "".equals(redPackKey)) {
|
||||
return AjaxResult.error("没有填写红包口令");
|
||||
}
|
||||
return redPackService.getRedPackByKey(loginUser, redPackKey);
|
||||
}
|
||||
|
||||
@PostMapping("/getActivityDataHis")
|
||||
@UserPermission
|
||||
@NoRepeatSubmit
|
||||
@ApiOperation(value = "查询参与的红包活动记录")
|
||||
public TableDataInfo getBoxDataHis(HttpServletRequest request) {
|
||||
PtLoginUser user = tokenService.getLoginUser(request);
|
||||
startPage();
|
||||
List<TtRedPacketRecord> boxRecords = redPackService.getActivityDataHis(user);
|
||||
|
||||
return getDataTable(boxRecords);
|
||||
}
|
||||
|
||||
@PostMapping("/getRedPackDataDetail")
|
||||
@UserPermission
|
||||
@NoRepeatSubmit
|
||||
@ApiOperation(value = "查询历史记录")
|
||||
public AjaxResult getRedPackDataDetail(HttpServletRequest request, @RequestParam("recordId") Long recordId) {
|
||||
PtLoginUser user = tokenService.getLoginUser(request);
|
||||
return redPackService.getRedPackDataDetail(user, recordId);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package com.ruoyi.playingmethod.controller;
|
||||
|
||||
import com.ruoyi.common.annotation.UserPermission;
|
||||
import com.ruoyi.common.core.controller.BaseController;
|
||||
import com.ruoyi.common.core.domain.AjaxResult;
|
||||
import com.ruoyi.common.core.domain.model.LoginUser;
|
||||
import com.ruoyi.framework.web.service.TokenService;
|
||||
import com.ruoyi.playingmethod.model.body.SynthesizeRequest;
|
||||
import com.ruoyi.playingmethod.service.IApiReplacementRecordService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
|
||||
|
||||
/**
|
||||
* 汰换记录Controller
|
||||
*
|
||||
* @author junhai
|
||||
* @date 2023-09-10
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/api/replacementRecord")
|
||||
@Api(tags = "汰换记录")
|
||||
public class ApiReplacementRecordController extends BaseController {
|
||||
|
||||
@Autowired
|
||||
private IApiReplacementRecordService ttReplacementRecordService;
|
||||
|
||||
@PostMapping("/synthesizeItems")
|
||||
@UserPermission
|
||||
@ApiOperation("汰换饰品")
|
||||
public AjaxResult synthesizeItems(@RequestBody SynthesizeRequest synthesizeRequest) {
|
||||
LoginUser loginUser = getLoginUser();
|
||||
return ttReplacementRecordService.synthesizeItems(loginUser, synthesizeRequest.getBoIds());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,176 @@
|
||||
package com.ruoyi.playingmethod.controller;
|
||||
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import com.ruoyi.common.core.domain.entity.SysUser;
|
||||
import com.ruoyi.common.core.page.TableDataInfo;
|
||||
import com.ruoyi.common.rabbitmq.config.DelayedQueueConfig;
|
||||
import com.ruoyi.domain.dto.roll.GetRollOpenPrizeParam;
|
||||
import com.ruoyi.domain.dto.roll.GetRollPlayersParam;
|
||||
import com.ruoyi.domain.dto.roll.GetRollPrizePool;
|
||||
import com.ruoyi.domain.entity.sys.TtUser;
|
||||
import com.ruoyi.admin.service.TtUserService;
|
||||
import com.ruoyi.common.annotation.RepeatSubmit;
|
||||
import com.ruoyi.common.core.controller.BaseController;
|
||||
import com.ruoyi.common.core.domain.R;
|
||||
import com.ruoyi.common.core.page.PageDataInfo;
|
||||
import com.ruoyi.domain.vo.boxRecords.TtBoxRecordsVO;
|
||||
import com.ruoyi.domain.vo.roll.RollJackpotOrnamentsVO;
|
||||
import com.ruoyi.domain.vo.roll.RollUserVO;
|
||||
import com.ruoyi.playingmethod.service.ApiRollService;
|
||||
import com.ruoyi.system.service.ISysConfigService;
|
||||
import com.ruoyi.domain.vo.RollDetailsDataVO;
|
||||
import com.ruoyi.domain.vo.RollListDataVO;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.springframework.amqp.core.Message;
|
||||
import org.springframework.amqp.core.MessageProperties;
|
||||
import org.springframework.amqp.rabbit.core.RabbitTemplate;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import jakarta.validation.constraints.Max;
|
||||
import jakarta.validation.constraints.Min;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import java.util.List;
|
||||
|
||||
@Api(tags = "ROLL房模式")
|
||||
@RestController
|
||||
@RequestMapping("/api/roll")
|
||||
public class ApiRollController extends BaseController {
|
||||
|
||||
private final ISysConfigService sysConfigService;
|
||||
private final TtUserService userService;
|
||||
private final ApiRollService apiRollService;
|
||||
|
||||
public ApiRollController(ISysConfigService sysConfigService,
|
||||
TtUserService userService,
|
||||
ApiRollService apiRollService) {
|
||||
this.sysConfigService = sysConfigService;
|
||||
this.userService = userService;
|
||||
this.apiRollService = apiRollService;
|
||||
}
|
||||
|
||||
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Data
|
||||
public static class JoinRollParam {
|
||||
@NotNull(message = "roll房id不能为空。")
|
||||
private Integer rollId;
|
||||
private String rollPassword;
|
||||
}
|
||||
|
||||
@ApiOperation("加入ROLL房")
|
||||
@RepeatSubmit(message = "操作过于频繁,请稍后重试!")
|
||||
@PostMapping("/joinRoll")
|
||||
public R joinRoll(@RequestBody @Validated JoinRollParam param) {
|
||||
String websiteMaintenance = sysConfigService.selectConfigByKey("websiteMaintenance");
|
||||
if ("1".equals(websiteMaintenance)) return R.fail("网站维护中......");
|
||||
String rollMaintenance = sysConfigService.selectConfigByKey("rollMaintenance");
|
||||
if ("1".equals(rollMaintenance)) return R.fail("Roll房功能正在维护中......");
|
||||
|
||||
Long userId = getUserId();
|
||||
if (ObjectUtil.isEmpty(userId)) return R.fail(401, "登录过期,请重新登录。");
|
||||
TtUser player = userService.getById(userId);
|
||||
if (ObjectUtil.isEmpty(player)) return R.fail("异常的用户状态。");
|
||||
|
||||
return apiRollService.joinRoll(param, player);
|
||||
// return StringUtils.isEmpty(msg) ? R.ok("成功加入Roll房!") : R.fail(msg, "加入失败!");
|
||||
}
|
||||
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Data
|
||||
public static class GetRollListParam {
|
||||
|
||||
private String rollName;
|
||||
|
||||
// 0官方 1主播
|
||||
@ApiModelProperty("0官方 1主播")
|
||||
private Integer rollType;
|
||||
|
||||
// 0未开奖 1已开奖
|
||||
@ApiModelProperty("0未开奖 1已开奖")
|
||||
private Integer rollStatus;
|
||||
|
||||
private Integer userId;
|
||||
}
|
||||
|
||||
@ApiOperation("获取ROLL房列表")
|
||||
@GetMapping("/getRollList")
|
||||
public TableDataInfo getRollList(GetRollListParam param) {
|
||||
startPage();
|
||||
List<RollListDataVO> list = apiRollService.getRollList(param);
|
||||
return getDataTable(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 我参与的ROLL房列表
|
||||
*/
|
||||
// @GetMapping("/getMyPartRollList")
|
||||
public PageDataInfo<RollListDataVO> getMyPartRollList(@RequestBody GetRollListParam param) {
|
||||
startPage();
|
||||
List<RollListDataVO> list = apiRollService.getRollList(param);
|
||||
return getPageData(list);
|
||||
}
|
||||
|
||||
@ApiOperation("获取ROLL房详情")
|
||||
@GetMapping("/getRollDetails/{rollId}")
|
||||
public R<RollDetailsDataVO> getRollDetails(@PathVariable("rollId") Integer rollId) {
|
||||
return apiRollService.getRollDetails(rollId);
|
||||
}
|
||||
|
||||
@ApiOperation("获取ROLL房参与人员详情")
|
||||
@PostMapping("/getRollPlayers")
|
||||
public R<List<RollUserVO>> getRollPlayers(@RequestBody @Validated GetRollPlayersParam param) {
|
||||
return apiRollService.getRollPlayers(param);
|
||||
}
|
||||
|
||||
@ApiOperation("获取ROLL房奖池详情")
|
||||
@PostMapping("/getRollPrizePool")
|
||||
public R<List<RollJackpotOrnamentsVO>> getRollPrizePool(@RequestBody @Validated GetRollPrizePool param) {
|
||||
return apiRollService.getRollPrizePool(param);
|
||||
}
|
||||
|
||||
@ApiOperation("获取ROLL开奖详情")
|
||||
@PostMapping("/getRollOpenPrize")
|
||||
public R<List<TtBoxRecordsVO>> getRollOpenPrize(@RequestBody @Validated GetRollOpenPrizeParam param) {
|
||||
return apiRollService.getRollOpenPrize(param);
|
||||
}
|
||||
|
||||
@ApiOperation("开奖测试,正式环境删除")
|
||||
@GetMapping("/endRoll/{rollId}")
|
||||
public R endRoll(@PathVariable("rollId") Integer rollId){
|
||||
return apiRollService.endROLL(rollId);
|
||||
}
|
||||
|
||||
// @Autowired
|
||||
private RabbitTemplate rabbitTemplate;
|
||||
|
||||
// @GetMapping("/endRoll/{rollId}")
|
||||
public String mqTest(@PathVariable("rollId") Integer rollId) {
|
||||
|
||||
// Calendar c = Calendar.getInstance();
|
||||
// long timeInMillis = c.getTimeInMillis();
|
||||
// c.add(Calendar.SECOND, 3);
|
||||
// long timeInMillis1 = c.getTimeInMillis();
|
||||
// long l = timeInMillis1 - timeInMillis;
|
||||
|
||||
MessageProperties messageProperties = new MessageProperties();
|
||||
messageProperties.setExpiration("3000"); // 消息的过期属性,单位 ms
|
||||
Message message = new Message("这条消息 4 秒后过期".getBytes(), messageProperties);
|
||||
|
||||
rabbitTemplate.convertAndSend(
|
||||
DelayedQueueConfig.OPEN_ROLL_EXCHANGE,
|
||||
DelayedQueueConfig.OPEN_ROLL_KEY,
|
||||
message
|
||||
);
|
||||
|
||||
return "1";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
package com.ruoyi.playingmethod.controller;
|
||||
|
||||
import com.ruoyi.common.core.controller.BaseController;
|
||||
import com.ruoyi.common.core.domain.R;
|
||||
import com.ruoyi.playingmethod.entity.TtAttendanceRecord;
|
||||
import com.ruoyi.playingmethod.service.IApiAttendanceRecordService;
|
||||
import io.swagger.annotations.Api;
|
||||
import org.apache.poi.ss.formula.functions.T;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Api(tags = "签到记录")
|
||||
@RestController
|
||||
@RequestMapping("/api/attendanceRecord")
|
||||
public class ApiTtAttendanceRecordController extends BaseController {
|
||||
private final IApiAttendanceRecordService iApiAttendanceRecordService;
|
||||
|
||||
public ApiTtAttendanceRecordController(IApiAttendanceRecordService iApiAttendanceRecordService) {
|
||||
this.iApiAttendanceRecordService = iApiAttendanceRecordService;
|
||||
}
|
||||
|
||||
/**
|
||||
* 签到
|
||||
*/
|
||||
// @GetMapping("/attendance")
|
||||
public R<String> attendance() {
|
||||
System.out.println("==================签到=================");
|
||||
TtAttendanceRecord ttAttendanceRecord = iApiAttendanceRecordService.selectByUid(getUserId().intValue());
|
||||
if (ttAttendanceRecord == null){
|
||||
// 增加签到记录
|
||||
iApiAttendanceRecordService.insert(getUserId().intValue());
|
||||
return R.ok("签到成功");
|
||||
}
|
||||
// List<UserPackSackDataVO> userCompoundRecord = iApiAttendanceRecordService.getUserCompoundRecord(getUserId().intValue());
|
||||
return R.fail("签到失败,一天只能签到一次");
|
||||
}
|
||||
|
||||
/**
|
||||
* 七天签到记录
|
||||
*/
|
||||
// @GetMapping("/sevenAttendance")
|
||||
public R<List<TtAttendanceRecord>> sevenAttendance() {
|
||||
System.out.println("==================七天签到=================");
|
||||
// TtAttendanceRecord ttAttendanceRecord = iApiAttendanceRecordService.selectByUid(getUserId().intValue());
|
||||
List<TtAttendanceRecord> ttAttendanceRecordList = iApiAttendanceRecordService.selectSevenAttendance(getUserId().intValue());
|
||||
return R.ok(ttAttendanceRecordList);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package com.ruoyi.playingmethod.controller;
|
||||
|
||||
import com.ruoyi.admin.service.TtUserAvatarService;
|
||||
import com.ruoyi.common.core.controller.BaseController;
|
||||
import com.ruoyi.common.core.domain.R;
|
||||
import com.ruoyi.domain.other.TtUserAvatar;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Api(tags = "用户头像")
|
||||
@RestController
|
||||
@RequestMapping("/api/userAvatar")
|
||||
public class ApiUserAvatarController extends BaseController {
|
||||
|
||||
private final TtUserAvatarService userAvatarService;
|
||||
|
||||
public ApiUserAvatarController(TtUserAvatarService userAvatarService) {
|
||||
this.userAvatarService = userAvatarService;
|
||||
}
|
||||
|
||||
@ApiOperation("用户头像列表")
|
||||
@GetMapping("/list")
|
||||
public R<List<TtUserAvatar>> list() {
|
||||
List<TtUserAvatar> list = userAvatarService.list();
|
||||
return R.ok(list);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
package com.ruoyi.playingmethod.controller;
|
||||
|
||||
import com.ruoyi.admin.service.TtUserService;
|
||||
import com.ruoyi.admin.service.TtWelfareService;
|
||||
import com.ruoyi.common.core.controller.BaseController;
|
||||
import com.ruoyi.common.core.domain.AjaxResult;
|
||||
import com.ruoyi.common.core.domain.R;
|
||||
import com.ruoyi.common.core.page.TableDataInfo;
|
||||
import com.ruoyi.common.utils.DateUtils;
|
||||
import com.ruoyi.common.utils.SecurityUtils;
|
||||
import com.ruoyi.domain.entity.sys.TtUser;
|
||||
import com.ruoyi.domain.other.TtBox;
|
||||
import com.ruoyi.domain.other.TtWelfare;
|
||||
import com.ruoyi.domain.other.TtWelfareMonthlyRecharges;
|
||||
import com.ruoyi.domain.vo.OpenBoxVO;
|
||||
import com.ruoyi.playingmethod.model.ApiWelfare;
|
||||
import com.ruoyi.playingmethod.model.ApiWelfareRecord;
|
||||
import com.ruoyi.playingmethod.service.ApiWelfareService;
|
||||
import com.ruoyi.system.service.ISysConfigService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import io.swagger.annotations.ApiResponse;
|
||||
import io.swagger.annotations.ApiResponses;
|
||||
import org.springframework.amqp.core.Message;
|
||||
import org.springframework.amqp.core.MessageProperties;
|
||||
import org.springframework.amqp.rabbit.core.RabbitTemplate;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
@Api(tags = "福利")
|
||||
@RestController
|
||||
@RequestMapping("/api/welfare")
|
||||
public class ApiWelfareController extends BaseController {
|
||||
|
||||
@Autowired
|
||||
private ApiWelfareService apiWelfareService;
|
||||
|
||||
@Autowired
|
||||
private TtWelfareService ttWelfareService;
|
||||
|
||||
@Autowired
|
||||
private ISysConfigService sysConfigService;
|
||||
|
||||
@Autowired
|
||||
private TtUserService userService;
|
||||
|
||||
@ApiOperation("获取福利列表")
|
||||
@ApiResponse(code = 200, message = "eligible【是否具备领取条件(0否 1是)】" +
|
||||
"<br>claimStatus【领取状态(0未领取 1已领取)】")
|
||||
@GetMapping("/getWelfareList")
|
||||
public TableDataInfo getWelfareList() {
|
||||
startPage();
|
||||
Long userId = SecurityUtils.getUserId();
|
||||
List<ApiWelfare> list = apiWelfareService.getWelfareList(userId);
|
||||
return getDataTable(list);
|
||||
}
|
||||
|
||||
@ApiOperation("领取福利")
|
||||
@GetMapping("/claimWelfare/{welfareId}")
|
||||
public AjaxResult claimWelfare(@PathVariable Integer welfareId) {
|
||||
Long userId = SecurityUtils.getUserId();
|
||||
// 检查福利是否存在
|
||||
TtWelfare ttWelfare = ttWelfareService.selectTtWelfareByWelfareId(welfareId);
|
||||
if (Objects.isNull(ttWelfare)) {
|
||||
return error("福利不存在");
|
||||
}
|
||||
// 检查是否尚未具备领取条件
|
||||
if (apiWelfareService.checkNotEligible(welfareId, userId)) {
|
||||
return AjaxResult.error("尚未达到领取条件");
|
||||
}
|
||||
// 检查是否已领取
|
||||
if (apiWelfareService.checkClaimed(welfareId, userId)) {
|
||||
return AjaxResult.error("该福利已被领取");
|
||||
}
|
||||
// 进入开箱流程
|
||||
String bindBoxMaintenance = sysConfigService.selectConfigByKey("bindBoxMaintenance");
|
||||
if ("1".equals(bindBoxMaintenance)) {
|
||||
return AjaxResult.error("盲盒开箱功能正在维护中......");
|
||||
}
|
||||
TtUser ttUser = userService.getById(getUserId());
|
||||
if ("0".equals(ttUser.getIsRealCheck())) {
|
||||
return AjaxResult.error("您的账户未进行实名认证,请先进行实名认证!");
|
||||
}
|
||||
OpenBoxVO openBoxVO = apiWelfareService.claimWelfare(welfareId, userId);
|
||||
return AjaxResult.success(openBoxVO);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
package com.ruoyi.playingmethod.controller;
|
||||
|
||||
import com.ruoyi.admin.service.ITtWelfareMonthlyRechargesService;
|
||||
import com.ruoyi.admin.service.TtUserService;
|
||||
import com.ruoyi.common.core.controller.BaseController;
|
||||
import com.ruoyi.common.core.domain.AjaxResult;
|
||||
import com.ruoyi.common.core.page.TableDataInfo;
|
||||
import com.ruoyi.common.utils.SecurityUtils;
|
||||
import com.ruoyi.domain.entity.sys.TtUser;
|
||||
import com.ruoyi.domain.other.TtWelfareMonthlyRecharges;
|
||||
import com.ruoyi.domain.vo.OpenBoxVO;
|
||||
import com.ruoyi.playingmethod.model.ApiWelfare;
|
||||
import com.ruoyi.playingmethod.model.vo.ApiWelfareMonthlyRechargesVO;
|
||||
import com.ruoyi.playingmethod.service.ApiWelfareMonthlyRechargesService;
|
||||
import com.ruoyi.system.service.ISysConfigService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import io.swagger.annotations.ApiResponse;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
@Api(tags = "每月充值福利")
|
||||
@RestController
|
||||
@RequestMapping("/api/welfare/monthlyRecharges")
|
||||
public class ApiWelfareMonthlyRechargesController extends BaseController {
|
||||
|
||||
@Autowired
|
||||
private ApiWelfareMonthlyRechargesService apiWelfareMonthlyRechargesService;
|
||||
|
||||
@Autowired
|
||||
private ITtWelfareMonthlyRechargesService ttWelfareMonthlyRechargesService;
|
||||
|
||||
@Autowired
|
||||
private ISysConfigService sysConfigService;
|
||||
|
||||
@Autowired
|
||||
private TtUserService userService;
|
||||
|
||||
@ApiOperation("获取每月充值福利列表")
|
||||
@ApiResponse(code = 200, message = "eligible【是否具备领取条件(0否 1是)】" +
|
||||
"<br>claimStatus【领取状态(0未领取 1已领取)】")
|
||||
@GetMapping("/list")
|
||||
public TableDataInfo getWelfareList() {
|
||||
startPage();
|
||||
Long userId = SecurityUtils.getUserId();
|
||||
List<ApiWelfareMonthlyRechargesVO> list = apiWelfareMonthlyRechargesService.getWelfareList(userId);
|
||||
return getDataTable(list);
|
||||
}
|
||||
|
||||
@ApiOperation("领取福利")
|
||||
@GetMapping("/claimWelfare/{welfareId}")
|
||||
public AjaxResult claimWelfare(@PathVariable Integer welfareId) {
|
||||
Long userId = SecurityUtils.getUserId();
|
||||
// 检查福利是否存在
|
||||
TtWelfareMonthlyRecharges ttWelfareMonthlyRecharges = ttWelfareMonthlyRechargesService.selectTtWelfareMonthlyRechargesById(welfareId);
|
||||
if (Objects.isNull(ttWelfareMonthlyRecharges)) {
|
||||
return error("福利不存在");
|
||||
}
|
||||
// 检查是否尚未具备领取条件
|
||||
if (!apiWelfareMonthlyRechargesService.checkEligible(welfareId, userId)) {
|
||||
return AjaxResult.error("尚未达到领取条件");
|
||||
}
|
||||
// 检查是否已领取
|
||||
if (apiWelfareMonthlyRechargesService.checkClaimed(welfareId, userId)) {
|
||||
return AjaxResult.error("该福利已被领取");
|
||||
}
|
||||
// 进入开箱流程
|
||||
String bindBoxMaintenance = sysConfigService.selectConfigByKey("bindBoxMaintenance");
|
||||
if ("1".equals(bindBoxMaintenance)) {
|
||||
return AjaxResult.error("盲盒开箱功能正在维护中......");
|
||||
}
|
||||
TtUser ttUser = userService.getById(getUserId());
|
||||
if ("0".equals(ttUser.getIsRealCheck())) {
|
||||
return AjaxResult.error("您的账户未进行实名认证,请先进行实名认证!");
|
||||
}
|
||||
OpenBoxVO openBoxVO = apiWelfareMonthlyRechargesService.claimWelfare(welfareId, userId);
|
||||
return AjaxResult.success(openBoxVO);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.ruoyi.playingmethod.customException;
|
||||
|
||||
public class CreateFightException extends RuntimeException{
|
||||
public CreateFightException(String msg){
|
||||
super(msg);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package com.ruoyi.playingmethod.customException;
|
||||
|
||||
// websocket用户重复连接异常
|
||||
public class WsRepetitiontException extends RuntimeException{
|
||||
public WsRepetitiontException(String msg){
|
||||
super(msg);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.ruoyi.playingmethod.domain.vo;
|
||||
|
||||
import com.ruoyi.domain.other.TtRobotFightGroupBox;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class ApiRobotFightGroupVO {
|
||||
|
||||
private Integer groupId;
|
||||
|
||||
private String groupName;
|
||||
|
||||
private Integer seatNum;
|
||||
|
||||
private String model;
|
||||
|
||||
private List<TtRobotFightGroupBox> ttRobotFightGroupBoxList;
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.ruoyi.playingmethod.domain.vo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class CompValueVO {
|
||||
|
||||
/** 当前补偿值 */
|
||||
private Integer currentCompValue;
|
||||
|
||||
/** 设定补偿值 */
|
||||
private Integer desiredCompValue;
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package com.ruoyi.playingmethod.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import com.ruoyi.common.annotation.Excel;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Accessors(chain = true)
|
||||
@Builder
|
||||
@TableName(value = "tt_attendance_record")
|
||||
public class TtAttendanceRecord {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/** */
|
||||
private Integer id;
|
||||
|
||||
/** 用户ID */
|
||||
@Excel(name = "用户ID")
|
||||
private Integer userId;
|
||||
|
||||
/** 创建时间 */
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date createTime;
|
||||
|
||||
/** 更新时间 */
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date updateTime;
|
||||
|
||||
/** 获取金币数 */
|
||||
@Excel(name = "获取金币数")
|
||||
private Integer coin;
|
||||
|
||||
@Excel(name = "是否删除")
|
||||
private String delFlag;
|
||||
|
||||
|
||||
private String isStatus = "0";
|
||||
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.ruoyi.playingmethod.mapper;
|
||||
|
||||
import com.ruoyi.playingmethod.entity.TtAttendanceRecord;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
@Mapper
|
||||
public interface ApiAttendanceRecordMapper {
|
||||
TtAttendanceRecord selectByUid(@Param("uid") Integer uid);
|
||||
|
||||
int insertAttendanceRecord(TtAttendanceRecord ttAttendanceRecord);
|
||||
|
||||
|
||||
TtAttendanceRecord selectSevenAttendance(@Param("uid") Integer uid,@Param("createTime") String createTime);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.ruoyi.playingmethod.mapper;
|
||||
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
@Mapper
|
||||
public interface ApiBattleRoyaleMapper {
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package com.ruoyi.playingmethod.mapper;
|
||||
|
||||
import com.ruoyi.domain.other.TtBoxUser;
|
||||
import com.ruoyi.domain.other.TtBoxA;
|
||||
import com.ruoyi.domain.other.TtOrnamentsA;
|
||||
import com.ruoyi.domain.other.TtBoxLevelA;
|
||||
import com.ruoyi.playingmethod.controller.ApiBindBoxController;
|
||||
import com.ruoyi.playingmethod.domain.vo.CompValueVO;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Mapper
|
||||
public interface ApiBindBoxMapper {
|
||||
|
||||
TtBoxA getBoxData(Integer boxId);
|
||||
|
||||
List<TtOrnamentsA> getBoxOrnamentsList(Integer boxId);
|
||||
|
||||
List<TtBoxA> getBoxList(
|
||||
@Param("boxTypeId") Integer boxTypeId,
|
||||
@Param("homeFlag") String homeFlag,
|
||||
@Param("boxType") String boxType
|
||||
);
|
||||
|
||||
TtOrnamentsA getOrnamentsData(@Param("boxId") Integer boxId, @Param("ornamentsId") Integer ornamentsId, @Param("id") Long id);
|
||||
|
||||
// List<TtBoxUser> getBindBoxHistory(ApiBindBoxController.boxHistoryParam param);
|
||||
|
||||
List<TtBoxLevelA> getProbabilityDistribution(Integer boxId);
|
||||
|
||||
TtOrnamentsA ornamentsInfo(@Param("boxId") Integer boxId,@Param("ornamentId") String ornamentId);
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package com.ruoyi.playingmethod.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.ruoyi.domain.other.TtBoxOrnaments;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
@Mapper
|
||||
public interface ApiBoxOrnamentsMapper extends BaseMapper<TtBoxOrnaments> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.ruoyi.playingmethod.mapper;
|
||||
|
||||
import com.ruoyi.domain.vo.UserPackSackDataVO;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Mapper
|
||||
public interface ApiCompoundMapper {
|
||||
UserPackSackDataVO selectCompoundDataById(Long packSackId);
|
||||
|
||||
List<UserPackSackDataVO> selectCompoundRecordByUserId(Integer userId);
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package com.ruoyi.playingmethod.mapper;
|
||||
|
||||
import com.ruoyi.domain.other.TtBoxA;
|
||||
import com.ruoyi.domain.vo.ApiFightListDataVO;
|
||||
import com.ruoyi.domain.vo.JoinFightUserDataVO;
|
||||
import com.ruoyi.domain.vo.UserPackSackDataVO;
|
||||
import com.ruoyi.playingmethod.model.vo.ApiFightRankingVO;
|
||||
import com.ruoyi.playingmethod.model.vo.ApiFightTenTopVo;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
@Mapper
|
||||
public interface ApiFightMapper {
|
||||
|
||||
JoinFightUserDataVO selectJoinFightUserData(Integer fightUserId);
|
||||
|
||||
List<UserPackSackDataVO> selectOrnamentsDataListByUserIdAndFightId(@Param("userId") Integer userId, @Param("fightId") Integer fightId);
|
||||
|
||||
List<ApiFightListDataVO> getFightList(@Param("model") String model, @Param("status") String status, @Param("userId") Integer userId, @Param("fightId") Integer fightId);
|
||||
|
||||
List<TtBoxA> getFightBoxList(Integer boxTypeId);
|
||||
|
||||
/**
|
||||
* 获取指定日期的对战排行榜
|
||||
*/
|
||||
List<ApiFightRankingVO> getFightRankingByDate(String date);
|
||||
|
||||
/**
|
||||
* 盲盒对战十佳对战
|
||||
*/
|
||||
List<ApiFightTenTopVo> tenTopFight(@Param("startDate") String startDate, @Param("endDate") String endDate, @Param("maxType") Integer maxType);
|
||||
/**
|
||||
* 查看对战开箱出来的总金额
|
||||
*/
|
||||
List<ApiFightTenTopVo> fightOrnamentsPrice(@Param("fightIds") List<Integer> fightIds);
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.ruoyi.playingmethod.mapper;
|
||||
|
||||
import com.ruoyi.domain.dto.upgrade.UpgradeCondition;
|
||||
import com.ruoyi.domain.vo.ApiLuckyOrnamentsDataVO;
|
||||
import com.ruoyi.domain.other.ApiLuckyUpgradeBody;
|
||||
import com.ruoyi.domain.vo.ApiLuckyUpgradeRecordDataVO;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Mapper
|
||||
public interface ApiLuckyUpgradeMapper {
|
||||
List<ApiLuckyOrnamentsDataVO> getOrnamentsList(ApiLuckyUpgradeBody apiLuckyUpgradeBody);
|
||||
|
||||
List<ApiLuckyUpgradeRecordDataVO> getUpgradeRecord(UpgradeCondition param);
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
package com.ruoyi.playingmethod.mapper;
|
||||
|
||||
import com.ruoyi.domain.entity.TtOrnament;
|
||||
import com.ruoyi.domain.other.TtReplacementRecord;
|
||||
import com.ruoyi.domain.vo.UserPackSackDataVO;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 汰换记录Mapper接口
|
||||
*
|
||||
* @author junhai
|
||||
* @date 2023-09-10
|
||||
*/
|
||||
public interface ApiReplacementRecordMapper {
|
||||
/**
|
||||
* 查询汰换记录
|
||||
*
|
||||
* @param id 汰换记录主键
|
||||
* @return 汰换记录
|
||||
*/
|
||||
public TtReplacementRecord selectTtReplacementRecordById(Long id);
|
||||
|
||||
/**
|
||||
* 查询汰换记录列表
|
||||
*
|
||||
* @param ttReplacementRecord 汰换记录
|
||||
* @return 汰换记录集合
|
||||
*/
|
||||
public List<TtReplacementRecord> selectTtReplacementRecordList(TtReplacementRecord ttReplacementRecord);
|
||||
|
||||
/**
|
||||
* 新增汰换记录
|
||||
*
|
||||
* @param ttReplacementRecord 汰换记录
|
||||
* @return 结果
|
||||
*/
|
||||
public int insertTtReplacementRecord(TtReplacementRecord ttReplacementRecord);
|
||||
|
||||
/**
|
||||
* 修改汰换记录
|
||||
*
|
||||
* @param ttReplacementRecord 汰换记录
|
||||
* @return 结果
|
||||
*/
|
||||
public int updateTtReplacementRecord(TtReplacementRecord ttReplacementRecord);
|
||||
|
||||
/**
|
||||
* 删除汰换记录
|
||||
*
|
||||
* @param id 汰换记录主键
|
||||
* @return 结果
|
||||
*/
|
||||
public int deleteTtReplacementRecordById(Long id);
|
||||
|
||||
/**
|
||||
* 批量删除汰换记录
|
||||
*
|
||||
* @param ids 需要删除的数据主键集合
|
||||
* @return 结果
|
||||
*/
|
||||
public int deleteTtReplacementRecordByIds(Long[] ids);
|
||||
|
||||
/**
|
||||
* 根据以下参数进行饰品的查询
|
||||
*
|
||||
* @param map
|
||||
* @return
|
||||
*/
|
||||
List<TtOrnament> findByPriceRange(Map<String, BigDecimal> map);
|
||||
|
||||
/**
|
||||
* 查询背包饰品
|
||||
*/
|
||||
List<UserPackSackDataVO> selectUserPackSack(@Param("userId") Integer userId,
|
||||
@Param("itemIds") List<Long> itemIds);
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package com.ruoyi.playingmethod.mapper;
|
||||
|
||||
import com.ruoyi.playingmethod.domain.vo.ApiRobotFightGroupVO;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Mapper
|
||||
public interface ApiRobotFightGroupMapper {
|
||||
|
||||
public List<ApiRobotFightGroupVO> selectApiRobotFightGroupBoxVOList();
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.ruoyi.playingmethod.mapper;
|
||||
|
||||
import com.ruoyi.domain.other.JackpotData;
|
||||
import com.ruoyi.domain.vo.RollDetailsDataVO;
|
||||
import com.ruoyi.domain.vo.RollListDataVO;
|
||||
import com.ruoyi.playingmethod.controller.ApiRollController.GetRollListParam;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Mapper
|
||||
public interface ApiRollMapper {
|
||||
|
||||
List<RollListDataVO> getRollList(GetRollListParam param);
|
||||
|
||||
RollDetailsDataVO getRollDetails(Integer rollId);
|
||||
|
||||
List<JackpotData> getJackpotData(Integer jackpotId);
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package com.ruoyi.playingmethod.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.ruoyi.domain.entity.TtUserBlendErcash;
|
||||
import com.ruoyi.domain.other.TtUpgradeRecord;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
@Mapper
|
||||
public interface ApiTtUserBlendErcashMapper extends BaseMapper<TtUserBlendErcash> {
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package com.ruoyi.playingmethod.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.ruoyi.domain.other.TtUpgradeRecord;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
@Mapper
|
||||
public interface ApiUpgradeRecordMapper extends BaseMapper<TtUpgradeRecord> {
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.ruoyi.playingmethod.mapper;
|
||||
|
||||
import com.ruoyi.common.core.domain.AjaxResult;
|
||||
import com.ruoyi.playingmethod.model.ApiWelfare;
|
||||
import com.ruoyi.playingmethod.model.ApiWelfareRecord;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.List;
|
||||
|
||||
@Mapper
|
||||
public interface ApiWelfareMapper {
|
||||
|
||||
List<ApiWelfare> getWelfareList(Long userId);
|
||||
|
||||
/**
|
||||
* 检查是否已领取
|
||||
*/
|
||||
boolean checkClaimed(
|
||||
@Param("welfareId") Integer welfareId,
|
||||
@Param("userId") Long userId,
|
||||
@Param("type") String type);
|
||||
|
||||
Integer getBoxIdByWelfareId(Integer welfareId);
|
||||
|
||||
int saveClaimWelfareRecord(ApiWelfareRecord apiWelfareRecord);
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package com.ruoyi.playingmethod.mapper;
|
||||
|
||||
import com.ruoyi.playingmethod.model.ApiWelfare;
|
||||
import com.ruoyi.playingmethod.model.ApiWelfareRecord;
|
||||
import com.ruoyi.playingmethod.model.vo.ApiWelfareMonthlyRechargesVO;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.List;
|
||||
|
||||
@Mapper
|
||||
public interface ApiWelfareMonthlyRechargesMapper {
|
||||
|
||||
List<ApiWelfareMonthlyRechargesVO> getWelfareList(Long userId);
|
||||
|
||||
/**
|
||||
* 查询当月充值量
|
||||
*/
|
||||
BigDecimal selectRechargeRecordsOfMonth(Long userId);
|
||||
|
||||
/**
|
||||
* 检查是否已领取
|
||||
*/
|
||||
boolean checkClaimed(
|
||||
@Param("welfareId") Integer welfareId,
|
||||
@Param("userId") Long userId,
|
||||
@Param("type") String type);
|
||||
|
||||
Integer getBoxIdByWelfareId(Integer welfareId);
|
||||
|
||||
int saveClaimWelfareRecord(ApiWelfareRecord apiWelfareRecord);
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package com.ruoyi.playingmethod.model;
|
||||
|
||||
import com.ruoyi.domain.other.TtBox;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
@Data
|
||||
public class ApiWelfare {
|
||||
|
||||
/**
|
||||
* 福利ID
|
||||
*/
|
||||
private Integer welfareId;
|
||||
|
||||
/**
|
||||
* 福利名称
|
||||
*/
|
||||
private String welfareName;
|
||||
|
||||
/**
|
||||
* 福利类型
|
||||
*/
|
||||
private String type;
|
||||
|
||||
/**
|
||||
* VIP等级
|
||||
*/
|
||||
private Integer vipLevel;
|
||||
|
||||
/**
|
||||
* 是否具备领取条件(0否 1是)
|
||||
*/
|
||||
private String eligible;
|
||||
|
||||
/**
|
||||
* 领取状态(0未领取 1已领取)
|
||||
*/
|
||||
private String claimStatus;
|
||||
|
||||
/**
|
||||
* 对应等级达标金额
|
||||
*/
|
||||
private BigDecimal rechargeThreshold;
|
||||
|
||||
/**
|
||||
* 宝箱信息
|
||||
*/
|
||||
private TtBox ttBox;
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.ruoyi.playingmethod.model;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
@Data
|
||||
public class ApiWelfareRecord {
|
||||
|
||||
private Integer welfareId;
|
||||
|
||||
private Long userId;
|
||||
|
||||
private String type;
|
||||
|
||||
private Date createTime;
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package com.ruoyi.playingmethod.model.body;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class SynthesizeRequest {
|
||||
|
||||
private List<Long> boIds;
|
||||
// private List<Long> yoIds;
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.ruoyi.playingmethod.model.vo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
@Data
|
||||
public class ApiFightRankingVO {
|
||||
|
||||
private Long userId;
|
||||
|
||||
private String nickName;
|
||||
|
||||
private String avatar;
|
||||
|
||||
private BigDecimal totalBoxPrice;
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.ruoyi.playingmethod.model.vo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
@Data
|
||||
public class ApiFightTenTopVo {
|
||||
/**
|
||||
* 对战ID
|
||||
*/
|
||||
private Integer id;
|
||||
/**
|
||||
* 宝箱开出来饰品总价值
|
||||
*/
|
||||
private BigDecimal totalOrnamentsPrice;
|
||||
/**
|
||||
* 宝箱开出来饰品减去宝箱总金额 * 玩家个数
|
||||
*/
|
||||
private BigDecimal increaseOrnamentsPrice;
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.ruoyi.playingmethod.model.vo;
|
||||
|
||||
import com.ruoyi.domain.other.TtBox;
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
@Data
|
||||
public class ApiWelfareMonthlyRechargesVO {
|
||||
|
||||
/** 福利ID */
|
||||
private Integer welfareId;
|
||||
|
||||
/** 福利名称 */
|
||||
private String welfareName;
|
||||
|
||||
/** 充值金额 */
|
||||
private BigDecimal amount;
|
||||
|
||||
/** 是否具备领取条件(0否 1是) */
|
||||
private String eligible;
|
||||
|
||||
/** 领取状态(0未领取 1已领取) */
|
||||
private String claimStatus;
|
||||
|
||||
/** 宝箱信息 */
|
||||
private TtBox ttBox;
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package com.ruoyi.playingmethod.model.vo;
|
||||
|
||||
import com.ruoyi.domain.other.TtBox;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class ApiWelfareVO {
|
||||
|
||||
/** 福利ID */
|
||||
private Integer welfareId;
|
||||
|
||||
/** 福利名称 */
|
||||
private String welfareName;
|
||||
|
||||
/** 福利类型 */
|
||||
private String type;
|
||||
|
||||
/** 是否具备领取条件(0否 1是) */
|
||||
private String eligible;
|
||||
|
||||
/** 领取状态(0未领取 1已领取) */
|
||||
private String claimStatus;
|
||||
|
||||
/** 宝箱信息 */
|
||||
private TtBox ttBox;
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
package com.ruoyi.playingmethod.scheduled;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
||||
import com.ruoyi.admin.mapper.TtUserBlendErcashMapper;
|
||||
import com.ruoyi.admin.service.TtFightRankingRewardService;
|
||||
import com.ruoyi.admin.service.TtUserService;
|
||||
import com.ruoyi.domain.common.constant.TtAccountRecordSource;
|
||||
import com.ruoyi.domain.common.constant.TtAccountRecordType;
|
||||
import com.ruoyi.domain.entity.TtUserBlendErcash;
|
||||
import com.ruoyi.domain.entity.sys.TtUser;
|
||||
import com.ruoyi.domain.other.TtFightRankingReward;
|
||||
import com.ruoyi.playingmethod.model.vo.ApiFightRankingVO;
|
||||
import com.ruoyi.playingmethod.service.ApiFightService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.sql.Timestamp;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
@Slf4j
|
||||
@Component("FightRankingRewardTask")
|
||||
public class FightRankingRewardTask {
|
||||
|
||||
@Autowired
|
||||
private ApiFightService apiFightService;
|
||||
|
||||
@Autowired
|
||||
private TtFightRankingRewardService ttFightRankingRewardService;
|
||||
|
||||
@Autowired
|
||||
private TtUserService userService;
|
||||
|
||||
@Autowired
|
||||
private TtUserBlendErcashMapper ttUserBlendErcashMapper;
|
||||
|
||||
/** 发放对战排行榜奖励 */
|
||||
public void distributeFightRankingReward() {
|
||||
log.info("开始发放对战排行榜奖励");
|
||||
// 查询昨日排行榜
|
||||
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
|
||||
Calendar cal = Calendar.getInstance();
|
||||
cal.add(Calendar.DATE, -1);
|
||||
Date yesterday = cal.getTime();
|
||||
String formattedYesterdayDate = formatter.format(yesterday);
|
||||
List<ApiFightRankingVO> yesterdayFightRanking = apiFightService.getFightRankingByDate(formattedYesterdayDate);
|
||||
for (int i = 0; i < yesterdayFightRanking.size(); i++) {
|
||||
// 查询排行榜对应奖励
|
||||
TtFightRankingReward ttFightRankingReward = ttFightRankingRewardService.selectTtFightRankingRewardById(i + 1);
|
||||
Long userId = yesterdayFightRanking.get(i).getUserId();
|
||||
BigDecimal reward = ttFightRankingReward.getReward();
|
||||
// 加钱
|
||||
LambdaUpdateWrapper<TtUser> userUpdate = new LambdaUpdateWrapper<>();
|
||||
userUpdate
|
||||
.eq(TtUser::getUserId, userId)
|
||||
.setSql("account_amount = account_amount + " + reward);
|
||||
userService.update(userUpdate);
|
||||
// 综合消费日志
|
||||
TtUser ttUser = userService.getById(userId);
|
||||
TtUserBlendErcash blendErcash = TtUserBlendErcash.builder()
|
||||
.userId(userId.intValue())
|
||||
.amount(reward.compareTo(BigDecimal.ZERO) > 0 ? reward : null)
|
||||
.finalAmount(reward.compareTo(BigDecimal.ZERO) > 0 ? ttUser.getAccountAmount().add(reward) : null)
|
||||
.total(reward.add(reward)) // 收支合计
|
||||
.type(TtAccountRecordType.INPUT.getCode())
|
||||
.source(TtAccountRecordSource.FIGHT_RANKING_REWARD.getCode())
|
||||
.remark(TtAccountRecordSource.FIGHT_RANKING_REWARD.getMsg())
|
||||
.createTime(new Timestamp(System.currentTimeMillis()))
|
||||
.updateTime(new Timestamp(System.currentTimeMillis()))
|
||||
.build();
|
||||
ttUserBlendErcashMapper.insert(blendErcash);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,325 @@
|
||||
package com.ruoyi.playingmethod.scheduled;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
|
||||
import com.ruoyi.admin.mapper.TtBoxMapper;
|
||||
import com.ruoyi.admin.mapper.TtFightMapper;
|
||||
import com.ruoyi.admin.mapper.TtUserMapper;
|
||||
import com.ruoyi.common.core.domain.R;
|
||||
import com.ruoyi.common.core.redis.RedisCache;
|
||||
import com.ruoyi.common.utils.DateTimeUtils;
|
||||
import com.ruoyi.common.utils.RandomUtil;
|
||||
import com.ruoyi.domain.common.constant.UserType;
|
||||
import com.ruoyi.domain.entity.fight.FightSeat;
|
||||
import com.ruoyi.domain.entity.fight.TtFight;
|
||||
import com.ruoyi.domain.entity.sys.TtUser;
|
||||
import com.ruoyi.domain.other.CreateFightBody;
|
||||
import com.ruoyi.domain.other.FightBoutData;
|
||||
import com.ruoyi.domain.other.TtBox;
|
||||
import com.ruoyi.domain.other.TtRobotFightGroupBox;
|
||||
import com.ruoyi.domain.vo.ApiFightListDataVO;
|
||||
import com.ruoyi.framework.manager.AsyncManager;
|
||||
import com.ruoyi.playingmethod.domain.vo.ApiRobotFightGroupVO;
|
||||
import com.ruoyi.playingmethod.mapper.ApiFightMapper;
|
||||
import com.ruoyi.playingmethod.mapper.ApiRobotFightGroupMapper;
|
||||
import com.ruoyi.playingmethod.service.ApiFightService;
|
||||
import com.ruoyi.system.service.ISysConfigService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Slf4j
|
||||
@Component("FightRobotTask")
|
||||
public class FightRobotTask {
|
||||
|
||||
@Value("${mkcsgo.fight.roundTime}")
|
||||
private final Integer fightRoundTimeMs = 4000;
|
||||
|
||||
@Autowired
|
||||
private TtFightMapper ttFightMapper;
|
||||
|
||||
@Autowired
|
||||
private TtUserMapper ttUserMapper;
|
||||
|
||||
@Autowired
|
||||
private ISysConfigService sysConfigService;
|
||||
|
||||
@Autowired
|
||||
private ApiFightService apiFightService;
|
||||
|
||||
@Autowired
|
||||
private RedisCache redisCache;
|
||||
|
||||
@Autowired
|
||||
private ApiRobotFightGroupMapper robotFightGroupMapper;
|
||||
|
||||
@Autowired
|
||||
private ApiFightMapper apiFightMapper;
|
||||
|
||||
@Autowired
|
||||
private TtBoxMapper boxMapper;
|
||||
|
||||
private static final List<Integer[]> roomExistTime = new ArrayList<>() {{
|
||||
add(new Integer[]{200, 30});
|
||||
add(new Integer[]{800, 60});
|
||||
add(new Integer[]{1500, 240});
|
||||
}};
|
||||
|
||||
/**
|
||||
* 机器人加入对战
|
||||
*/
|
||||
public void robotJoinFight() {
|
||||
log.info("机器人加入对战");
|
||||
|
||||
// 查询所有处于等待中的对战房间ID
|
||||
QueryWrapper<TtFight> queryWrapper = new QueryWrapper<>();
|
||||
queryWrapper.eq("status", 0);
|
||||
queryWrapper.eq("model", 0);
|
||||
List<TtFight> fightList = ttFightMapper.selectList(queryWrapper);
|
||||
if (CollectionUtils.isEmpty(fightList)) {
|
||||
log.info("没有等待中的对战房间");
|
||||
return;
|
||||
}
|
||||
|
||||
// 查询所有机器人ID
|
||||
List<Integer> robotIdList = ttUserMapper.selectObjs(
|
||||
new QueryWrapper<TtUser>()
|
||||
.select("user_id")
|
||||
.eq("user_type", UserType.ROBOT_USER.getCode())
|
||||
);
|
||||
if (robotIdList.isEmpty()) {
|
||||
log.info("没有机器人");
|
||||
return;
|
||||
}
|
||||
|
||||
// 打乱对战ID列表顺序,取前面指定数量的对战ID
|
||||
Collections.shuffle(fightList);
|
||||
|
||||
List<Integer> userIdList = fightList.stream().map(TtFight::getUserId).filter(Objects::nonNull)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
if (userIdList.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Map<Integer, TtUser> userMap = ttUserMapper.selectByIds(userIdList).stream()
|
||||
.collect(Collectors.toMap(TtUser::getUserId, v -> v));
|
||||
|
||||
for (TtFight ttFight : fightList) {
|
||||
TtUser user = userMap.get(ttFight.getUserId());
|
||||
if (user == null || user.getUserType().equals(UserType.ROBOT_USER.getCode())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Optional<Integer[]> config = roomExistTime.stream()
|
||||
.filter(arr -> ttFight.getBoxPriceTotal().doubleValue() <= arr[0]).findFirst();
|
||||
if (config.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
var time = config.get()[1];
|
||||
if (ttFight.getCreateTime().getTime() + time * 1000 >= DateTimeUtils.now() * 1000) {
|
||||
continue;
|
||||
}
|
||||
|
||||
List<Integer> availableRobotIds = new ArrayList<>(robotIdList);
|
||||
List<FightSeat> seats = ttFight.getSeats();
|
||||
|
||||
var inRoomPlayerIds = seats.stream()
|
||||
.map(FightSeat::getPlayerId)
|
||||
.filter(Objects::nonNull)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
// 只有一个空位才加入机器人
|
||||
if (inRoomPlayerIds.size() != seats.size() - 1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
availableRobotIds.removeAll(inRoomPlayerIds);
|
||||
if (availableRobotIds.isEmpty()) {
|
||||
log.warn("No available robots for fight: {}", ttFight.getId());
|
||||
return;
|
||||
}
|
||||
|
||||
for (FightSeat seat : seats) {
|
||||
// 随机机器人进入空座位
|
||||
if (Objects.isNull(seat.getPlayerId())) {
|
||||
Integer robotId = availableRobotIds.get(RandomUtil.rand(availableRobotIds.size()));
|
||||
TtUser player = ttUserMapper.selectById(robotId);
|
||||
R<Object> objectR = apiFightService.joinFight(ttFight.getId(), player);
|
||||
if (objectR.getCode() == 500) {
|
||||
return;
|
||||
}
|
||||
log.info("机器人{}加入对战{}", robotId, ttFight.getId());
|
||||
// 座位就绪
|
||||
R fight = apiFightService.seatrReady(ttFight.getId(), player);
|
||||
FightBoutData fightBoutData = new FightBoutData();
|
||||
fightBoutData.setFightId(ttFight.getId());
|
||||
fightBoutData.setBoutNum(1);
|
||||
fightBoutData.setExpirationTime(16000);
|
||||
String key = "fight_bout_data:fight_" + fightBoutData.getFightId();
|
||||
redisCache.setCacheObject(key, fightBoutData, fightBoutData.getExpirationTime(), TimeUnit.MILLISECONDS);
|
||||
// 调用开始对战方法
|
||||
apiFightService.fightBegin(ttFight.getId(), player);
|
||||
|
||||
int gameTime = ttFight.getRoundNumber() * fightRoundTimeMs;
|
||||
AsyncManager.me().timeout(new TimerTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
apiFightService.fightEnd(ttFight.getId());
|
||||
}
|
||||
}, gameTime, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 机器人创建对战
|
||||
*/
|
||||
public void robotCreateFight() {
|
||||
log.info("机器人创建对战");
|
||||
|
||||
// 查询所有机器人ID
|
||||
List<Integer> robotIdList = ttUserMapper.selectObjs(
|
||||
new QueryWrapper<TtUser>()
|
||||
.select("user_id")
|
||||
.eq("user_type", UserType.ROBOT_USER.getCode())
|
||||
);
|
||||
if (robotIdList.isEmpty()) {
|
||||
log.warn("无可用机器人,停止创建对战");
|
||||
return;
|
||||
}
|
||||
|
||||
// 定义价格档位配置
|
||||
BigDecimal[] priceLimits = {BigDecimal.valueOf(200), BigDecimal.valueOf(800), BigDecimal.valueOf(1500)};
|
||||
int[] targetCounts = {6, 4, 1};
|
||||
|
||||
List<ApiFightListDataVO> vos = apiFightMapper.getFightList(null, "0", null, null);
|
||||
if (CollectionUtils.isEmpty(vos)) {
|
||||
vos = new ArrayList<>();
|
||||
}
|
||||
vos.forEach(v -> {
|
||||
if (v.getBoxPriceTotal() == null) {
|
||||
v.setBoxPriceTotal(BigDecimal.ZERO);
|
||||
}
|
||||
});
|
||||
|
||||
// 统计当前各价位对战的存量
|
||||
int[] currentCounts = new int[3]; // 对应 200, 800, 1500
|
||||
for (ApiFightListDataVO vo : vos) {
|
||||
if (vo.getBoxPriceTotal().compareTo(BigDecimal.valueOf(200)) <= 0) {
|
||||
currentCounts[0]++;
|
||||
} else if (vo.getBoxPriceTotal().compareTo(BigDecimal.valueOf(800)) <= 0) {
|
||||
currentCounts[1]++;
|
||||
} else if (vo.getBoxPriceTotal().compareTo(BigDecimal.valueOf(1500)) <= 0) {
|
||||
currentCounts[2]++;
|
||||
}
|
||||
}
|
||||
|
||||
// 计算需要创建的数量
|
||||
int[] needCreateCounts = new int[3];
|
||||
for (int i = 0; i < 3; i++) {
|
||||
needCreateCounts[i] = Math.max(targetCounts[i] - currentCounts[i], 0);
|
||||
}
|
||||
|
||||
// 查询机器人宝箱分组
|
||||
List<ApiRobotFightGroupVO> apiRobotFightGroupVOList = robotFightGroupMapper.selectApiRobotFightGroupBoxVOList();
|
||||
if (CollectionUtils.isEmpty(apiRobotFightGroupVOList)) {
|
||||
return;
|
||||
}
|
||||
Set<Integer> boxIds = apiRobotFightGroupVOList.stream()
|
||||
.flatMap(v -> v.getTtRobotFightGroupBoxList().stream())
|
||||
.map(TtRobotFightGroupBox::getBoxId)
|
||||
.filter(Objects::nonNull)
|
||||
.collect(Collectors.toSet());
|
||||
List<TtBox> allBoxes = Collections.emptyList();
|
||||
if (!boxIds.isEmpty()) {
|
||||
allBoxes = new LambdaQueryChainWrapper<>(boxMapper)
|
||||
.in(TtBox::getBoxId, boxIds)
|
||||
.eq(TtBox::getIsFight, "0")
|
||||
.eq(TtBox::getStatus, "0")
|
||||
.list();
|
||||
}
|
||||
// 构建 BoxId -> Box 的 Map,方便快速查找
|
||||
Map<Integer, TtBox> boxMap = allBoxes.stream()
|
||||
.collect(Collectors.toMap(TtBox::getBoxId, v -> v, (v1, v2) -> v1));
|
||||
|
||||
|
||||
var groupMap = apiRobotFightGroupVOList.stream().collect(Collectors.toMap(ApiRobotFightGroupVO::getGroupId, v -> v));
|
||||
|
||||
Map<Integer, BigDecimal> groupPriceMap = new HashMap<>();
|
||||
for (ApiRobotFightGroupVO groupVO : apiRobotFightGroupVOList) {
|
||||
BigDecimal boxTotalPrice = BigDecimal.ZERO;
|
||||
if (CollectionUtils.isNotEmpty(groupVO.getTtRobotFightGroupBoxList())) {
|
||||
for (TtRobotFightGroupBox groupBox : groupVO.getTtRobotFightGroupBoxList()) {
|
||||
TtBox box = boxMap.get(groupBox.getBoxId());
|
||||
if (box != null) {
|
||||
BigDecimal multiply = BigDecimal.valueOf(groupBox.getBoxNum()).multiply(box.getPrice());
|
||||
boxTotalPrice = boxTotalPrice.add(multiply);
|
||||
}
|
||||
}
|
||||
}
|
||||
groupPriceMap.put(groupVO.getGroupId(), boxTotalPrice);
|
||||
}
|
||||
|
||||
// 6. 循环处理不同价位的创建任务
|
||||
for (int i = 0; i < needCreateCounts.length; i++) {
|
||||
int needCount = needCreateCounts[i];
|
||||
if (needCount <= 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
BigDecimal limitPrice = priceLimits[i];
|
||||
BigDecimal lowPrice;
|
||||
if (i > 0) {
|
||||
lowPrice = priceLimits[i - 1];
|
||||
} else {
|
||||
lowPrice = BigDecimal.ZERO;
|
||||
}
|
||||
|
||||
// 筛选出符合当前价位的分组
|
||||
List<ApiRobotFightGroupVO> matchedGroups = groupPriceMap.entrySet().stream()
|
||||
.filter(entry -> entry.getValue().compareTo(lowPrice) > 0 && entry.getValue().compareTo(limitPrice) <= 0)
|
||||
.map(entry -> groupMap.get(entry.getKey()))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
if (CollectionUtils.isNotEmpty(matchedGroups)) {
|
||||
createFight(matchedGroups, needCount, robotIdList);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void createFight(List<ApiRobotFightGroupVO> groupList, int canCreateCount, List<Integer> robotIdList) {
|
||||
if (CollectionUtils.isEmpty(groupList) || CollectionUtils.isEmpty(robotIdList)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 创建指定数量的房间
|
||||
for (int i = 0; i < canCreateCount; i++) {
|
||||
// 随机取一个机器人
|
||||
Integer robotId = robotIdList.get(RandomUtil.rand(robotIdList.size()));
|
||||
TtUser player = ttUserMapper.selectById(robotId);
|
||||
// 随机取一个宝箱分组
|
||||
ApiRobotFightGroupVO apiRobotFightGroupVO = groupList.get(RandomUtil.rand(groupList.size()));
|
||||
log.info("机器人{}使用宝箱分组{}", robotId, apiRobotFightGroupVO.getGroupId());
|
||||
// 创建对战
|
||||
CreateFightBody createFightBody = new CreateFightBody();
|
||||
createFightBody.setModel(apiRobotFightGroupVO.getModel());
|
||||
createFightBody.setPlayerNumber(apiRobotFightGroupVO.getSeatNum());
|
||||
Map<Integer, Integer> boxIdAndNumber = new HashMap<>();
|
||||
for (TtRobotFightGroupBox ttRobotFightGroupBox : apiRobotFightGroupVO.getTtRobotFightGroupBoxList()) {
|
||||
boxIdAndNumber.put(ttRobotFightGroupBox.getBoxId(), ttRobotFightGroupBox.getBoxNum());
|
||||
}
|
||||
createFightBody.setBoxIdAndNumber(boxIdAndNumber);
|
||||
apiFightService.createFight(createFightBody, player);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,134 @@
|
||||
package com.ruoyi.playingmethod.scheduled;
|
||||
|
||||
|
||||
import cn.hutool.core.date.DateUnit;
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.conditions.update.LambdaUpdateChainWrapper;
|
||||
import com.ruoyi.admin.mapper.TtBoxRecordsMapper;
|
||||
import com.ruoyi.admin.service.TtBoxRecordsService;
|
||||
import com.ruoyi.admin.service.TtRollService;
|
||||
import com.ruoyi.common.core.domain.AjaxResult;
|
||||
import com.ruoyi.common.core.domain.R;
|
||||
import com.ruoyi.common.rabbitmq.config.DelayedQueueConfig;
|
||||
import com.ruoyi.common.utils.DateUtils;
|
||||
import com.ruoyi.domain.entity.TtBoxRecords;
|
||||
import com.ruoyi.domain.entity.fight.TtFight;
|
||||
import com.ruoyi.domain.entity.roll.TtRoll;
|
||||
import com.ruoyi.playingmethod.service.ApiFightService;
|
||||
import com.ruoyi.playingmethod.service.ApiRollService;
|
||||
import com.ruoyi.playingmethod.websocket.WsFightHall;
|
||||
import com.ruoyi.playingmethod.websocket.WsFightRoom;
|
||||
import com.ruoyi.playingmethod.websocket.util.WsResult;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.amqp.core.Message;
|
||||
import org.springframework.amqp.core.MessageProperties;
|
||||
import org.springframework.amqp.rabbit.core.RabbitTemplate;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.scheduling.annotation.EnableScheduling;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
|
||||
import java.sql.Timestamp;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
|
||||
import static com.ruoyi.domain.common.constant.TtboxRecordStatus.IN_PACKSACK_ON;
|
||||
import static com.ruoyi.playingmethod.websocket.constant.SMsgKey.ALL_FIGHT_ROOM;
|
||||
|
||||
@Slf4j
|
||||
@Configuration // 1.主要用于标记配置类,兼备Component的效果。
|
||||
@EnableScheduling // 2.开启定时任务
|
||||
public class RollTask {
|
||||
|
||||
@Value("${mkcsgo.fight.roundTime}")
|
||||
private final Integer fightRoundTime = null;
|
||||
|
||||
@Autowired
|
||||
private ApiFightService fightService;
|
||||
|
||||
@Autowired
|
||||
private TtBoxRecordsMapper boxRecordsMapper;
|
||||
|
||||
@Autowired
|
||||
private TtBoxRecordsService boxRecordsService;
|
||||
|
||||
@Autowired
|
||||
private TtRollService ttRollService;
|
||||
|
||||
@Autowired
|
||||
private Executor customThreadPoolExecutor;
|
||||
|
||||
@Autowired
|
||||
private RabbitTemplate rabbitTemplate;
|
||||
|
||||
@Autowired
|
||||
private ApiRollService apiRollService;
|
||||
|
||||
// 定时检查即将开奖的roll房(临界区:1分钟)
|
||||
@Scheduled(cron = "0 */1 * * * ?")
|
||||
private void refreshDayTask() {
|
||||
|
||||
// System.out.println("11111111111111111");
|
||||
|
||||
//System.out.println("roll 开奖临界区检查");
|
||||
|
||||
// 查询两分钟以内将要开奖的roll房
|
||||
Calendar c = Calendar.getInstance();
|
||||
c.add(Calendar.MINUTE, 2);
|
||||
Timestamp criticalTime = new Timestamp(c.getTimeInMillis());
|
||||
LambdaQueryWrapper<TtRoll> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper
|
||||
.eq(TtRoll::getRollStatus, 0)
|
||||
.eq(TtRoll::getDelFlag, 0)
|
||||
.lt(TtRoll::getEndTime, criticalTime);
|
||||
List<TtRoll> criticalRoll = ttRollService.list(wrapper);
|
||||
|
||||
if (criticalRoll.isEmpty()) return;
|
||||
|
||||
log.info("roll开奖临界区检查,{}个roll房进入临界区", criticalRoll.size());
|
||||
|
||||
// 加入延时队列
|
||||
for (TtRoll roll : criticalRoll) {
|
||||
|
||||
if (DateUtils.getNowDate().compareTo(roll.getEndTime()) > 0) {
|
||||
|
||||
log.info("roll房{}已经超时,直接开奖。", roll.getId());
|
||||
|
||||
R r = apiRollService.endROLL(roll.getId());
|
||||
if (!r.getCode().equals(200)) {
|
||||
log.error("roll开奖 消费失败,尝试消息补发再次消费!" + r.getMsg());
|
||||
}
|
||||
if (ObjectUtil.isNotEmpty(r.getMsg())) log.info("{}", r.getMsg());
|
||||
// 已超时直接开奖,不再加入延时队列,避免重复开奖
|
||||
continue;
|
||||
}
|
||||
|
||||
// 相差时间(未超时的roll房才加入延时队列)
|
||||
long betweenDay = DateUtil.between(DateUtils.getNowDate(), roll.getEndTime(), DateUnit.MS);
|
||||
|
||||
System.out.println("设置消息超时时间");
|
||||
log.info("设置消息超时时间:{}",betweenDay);
|
||||
MessageProperties messageProperties = new MessageProperties();
|
||||
messageProperties.setExpiration(String.valueOf(betweenDay)); // 消息的过期属性,单位 ms
|
||||
Message message = new Message(String.valueOf(roll.getId()).getBytes(), messageProperties);
|
||||
|
||||
// 延时队列实现开奖
|
||||
rabbitTemplate.convertAndSend(
|
||||
DelayedQueueConfig.OPEN_ROLL_EXCHANGE,
|
||||
DelayedQueueConfig.OPEN_ROLL_KEY,
|
||||
message);
|
||||
|
||||
log.info("Roll房{}-{}加入临界区,{}秒后开奖", roll.getId(), roll.getRollName(), betweenDay / 1000);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
package com.ruoyi.playingmethod.scheduled;
|
||||
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.conditions.update.LambdaUpdateChainWrapper;
|
||||
import com.ruoyi.admin.mapper.TtBoxRecordsMapper;
|
||||
import com.ruoyi.admin.service.TtBoxRecordsService;
|
||||
import com.ruoyi.domain.entity.TtBoxRecords;
|
||||
import com.ruoyi.domain.entity.fight.TtFight;
|
||||
import com.ruoyi.playingmethod.service.ApiFightService;
|
||||
import com.ruoyi.playingmethod.websocket.WsFightHall;
|
||||
import com.ruoyi.playingmethod.websocket.WsFightRoom;
|
||||
import com.ruoyi.playingmethod.websocket.util.WsResult;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.scheduling.annotation.EnableScheduling;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
|
||||
import java.sql.Timestamp;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
|
||||
import static com.ruoyi.domain.common.constant.TtboxRecordStatus.IN_PACKSACK_ON;
|
||||
import static com.ruoyi.playingmethod.websocket.constant.SMsgKey.ALL_FIGHT_ROOM;
|
||||
|
||||
@Slf4j
|
||||
@Configuration //1.主要用于标记配置类,兼备Component的效果。
|
||||
@EnableScheduling // 2.开启定时任务
|
||||
public class fightTask {
|
||||
|
||||
@Value("${mkcsgo.fight.roundTime}")
|
||||
private final Integer fightRoundTime = null;
|
||||
|
||||
@Autowired
|
||||
private ApiFightService fightService;
|
||||
|
||||
@Autowired
|
||||
private TtBoxRecordsMapper boxRecordsMapper;
|
||||
|
||||
@Autowired
|
||||
private TtBoxRecordsService boxRecordsService;
|
||||
|
||||
@Autowired
|
||||
private Executor customThreadPoolExecutor;
|
||||
|
||||
// 定时更新超时未结束的对局
|
||||
@Scheduled(cron = "0/6 * * * * ?")
|
||||
private void refreshDayTask() {
|
||||
log.info("定时更新超时未结束的对局");
|
||||
// Timestamp now = new Timestamp(System.currentTimeMillis());
|
||||
LambdaQueryWrapper<TtFight> fightQuery = new LambdaQueryWrapper<>();
|
||||
fightQuery
|
||||
.eq(TtFight::getStatus,1)
|
||||
.and(wrapper->{
|
||||
wrapper.isNull(TtFight::getEndTime);
|
||||
})
|
||||
.and(wrapper->{
|
||||
wrapper.isNotNull(TtFight::getBeginTime);
|
||||
})
|
||||
// TODO: 2024/4/13 优化sql
|
||||
// 对局开始时间早于当前时间减去一定时间间隔(再减去6秒),就会被认为是超时的对局
|
||||
// begin_time < DATE_SUB(NOW(), INTERVAL 100 SECOND)
|
||||
.last("AND begin_time < DATE_SUB(NOW(), INTERVAL " + fightRoundTime / 1000 + "* round_number + 60"+" second)");
|
||||
|
||||
List<TtFight> list = fightService.list(fightQuery);
|
||||
|
||||
if (list.isEmpty()) return;
|
||||
|
||||
List<Integer> fightIds = new ArrayList<>();
|
||||
// 更新fight
|
||||
list.stream().forEach(item->{
|
||||
item.setEndTime(new Timestamp(System.currentTimeMillis()));
|
||||
item.setStatus(3);
|
||||
item.setRemark("超时强制更新结束状态");
|
||||
fightIds.add(item.getId());
|
||||
|
||||
// 断开房间所有连接
|
||||
WsFightRoom.batchClose(item);
|
||||
});
|
||||
fightService.updateBatchById(list);
|
||||
|
||||
// 异步更新对局数据
|
||||
CompletableFuture.runAsync(() -> {
|
||||
WsFightHall.broadcast(WsResult.ok(ALL_FIGHT_ROOM.name(), list));
|
||||
}, customThreadPoolExecutor);
|
||||
|
||||
// 更新openBoxRecords
|
||||
new LambdaUpdateChainWrapper<>(boxRecordsMapper)
|
||||
// .eq(TtBoxRecords::getStatus,IN_PACKSACK_ON.getCode())
|
||||
.in(TtBoxRecords::getFightId,fightIds)
|
||||
.set(TtBoxRecords::getStatus,IN_PACKSACK_ON.getCode())
|
||||
.update();
|
||||
|
||||
log.info("更新 {} 条超时未结束的对局记录",list.size());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
package com.ruoyi.playingmethod.service;
|
||||
|
||||
public interface ApiBattleRoyaleService {
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package com.ruoyi.playingmethod.service;
|
||||
|
||||
import com.ruoyi.common.core.domain.R;
|
||||
import com.ruoyi.domain.other.TtBox;
|
||||
import com.ruoyi.domain.entity.TtBoxRecords;
|
||||
import com.ruoyi.domain.entity.sys.TtUser;
|
||||
import com.ruoyi.domain.other.TtBoxA;
|
||||
import com.ruoyi.domain.other.TtOrnamentsA;
|
||||
import com.ruoyi.domain.other.TtBoxVO;
|
||||
import com.ruoyi.playingmethod.domain.vo.CompValueVO;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface ApiBindBoxService {
|
||||
|
||||
TtBoxA getBoxData(Integer boxId);
|
||||
|
||||
List<TtOrnamentsA> getCompBoxData(Integer boxId);
|
||||
|
||||
List<TtBoxVO> getBoxList(Integer boxTypeId, String homeFlag, String boxType);
|
||||
|
||||
List<TtBoxVO> groupByBoxType(List<TtBoxA> boxData);
|
||||
|
||||
List<TtOrnamentsA> openBox(TtBox ttBox, Integer num, TtUser ttUser);
|
||||
|
||||
List<TtBoxRecords> addBoxRecord(TtUser ttUser, TtBox ttBox, Integer num);
|
||||
|
||||
List<TtBoxRecords> openBoxArithmetic(Integer fightId,TtUser ttUser, TtBox ttBox, Integer num);
|
||||
|
||||
// List<TtBoxUser> getBindBoxHistory(ApiBindBoxController.boxHistoryParam param);
|
||||
|
||||
R blindBox(TtUser ttUser, TtBox ttBox, Integer num);
|
||||
|
||||
CompValueVO getCompValue(TtUser ttUser, TtBox ttBox);
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package com.ruoyi.playingmethod.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.ruoyi.domain.other.TtBoxOrnaments;
|
||||
|
||||
public interface ApiBoxOrnamentsService extends IService<TtBoxOrnaments> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.ruoyi.playingmethod.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.ruoyi.domain.dto.boxRecords.TenTopQuery;
|
||||
import com.ruoyi.domain.dto.boxRecords.queryCondition;
|
||||
import com.ruoyi.domain.entity.TtBoxRecords;
|
||||
import com.ruoyi.domain.vo.boxRecords.TtBoxRecordsVO;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface ApiBoxRecordsService extends IService<TtBoxRecords> {
|
||||
|
||||
List<TtBoxRecordsVO> byCondition(queryCondition condition);
|
||||
|
||||
List<TtBoxRecordsVO> tenTopQuery(TenTopQuery query);
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package com.ruoyi.playingmethod.service;
|
||||
|
||||
import com.ruoyi.domain.entity.sys.TtUser;
|
||||
import com.ruoyi.common.core.domain.R;
|
||||
import com.ruoyi.domain.vo.UserPackSackDataVO;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface ApiCompoundService {
|
||||
|
||||
R<UserPackSackDataVO> compound(List<Long> packSackIds, TtUser ttUser);
|
||||
|
||||
List<UserPackSackDataVO> getUserCompoundRecord(Integer userId);
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package com.ruoyi.playingmethod.service;
|
||||
|
||||
import com.ruoyi.common.core.domain.R;
|
||||
import com.ruoyi.domain.dto.exponent.ExponentJoinParam;
|
||||
import com.ruoyi.domain.entity.sys.TtUser;
|
||||
import com.ruoyi.domain.other.TtBox;
|
||||
|
||||
public interface ApiExponentService {
|
||||
/**
|
||||
* 加入指数
|
||||
* @param param
|
||||
* @return
|
||||
*/
|
||||
R join(TtUser ttUser, ExponentJoinParam param);
|
||||
|
||||
/**
|
||||
* 宝箱信息
|
||||
*/
|
||||
R box(TtUser ttUser, Integer id);
|
||||
|
||||
/**
|
||||
* 最近十期指数
|
||||
*/
|
||||
R recenttenperiod();
|
||||
|
||||
/**
|
||||
* 返回信息
|
||||
* @param ttUser
|
||||
* @return
|
||||
*/
|
||||
R info(TtUser ttUser);
|
||||
|
||||
R records(TtUser ttUser);
|
||||
|
||||
R mybox(TtUser ttUser);
|
||||
|
||||
R openbox(TtUser ttUser, TtBox ttBox, Integer num);
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
package com.ruoyi.playingmethod.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.ruoyi.common.core.domain.R;
|
||||
import com.ruoyi.domain.dto.fight.FightDetailParam;
|
||||
import com.ruoyi.domain.dto.fight.FightOnMyOwnParam;
|
||||
import com.ruoyi.domain.other.CreateFightBody;
|
||||
import com.ruoyi.domain.other.TtBoxVO;
|
||||
import com.ruoyi.domain.entity.fight.TtFight;
|
||||
import com.ruoyi.domain.entity.sys.TtUser;
|
||||
import com.ruoyi.domain.vo.ApiFightListDataVO;
|
||||
import com.ruoyi.domain.vo.FightResultDataVO;
|
||||
import com.ruoyi.domain.vo.fight.FightResultVO;
|
||||
import com.ruoyi.domain.vo.fight.TtFightVO;
|
||||
import com.ruoyi.playingmethod.model.vo.ApiFightRankingVO;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public interface ApiFightService extends IService<TtFight> {
|
||||
|
||||
R<Object> createFight(CreateFightBody createFightParamVO, TtUser ttUser);
|
||||
|
||||
R<Object> joinFight(Integer fightId, TtUser player);
|
||||
|
||||
List<TtBoxVO> getFightBoxList(Integer boxTypeId);
|
||||
|
||||
List<ApiFightListDataVO> getFightList(String model, String status, Integer userId, Integer fightId);
|
||||
|
||||
FightResultDataVO getFightRecord(Integer fightId, Integer round, Integer rounds);
|
||||
|
||||
R fightBegin(Integer fightId, TtUser player);
|
||||
|
||||
R audience(Integer fightId);
|
||||
|
||||
R fightEnd(Integer fightId);
|
||||
|
||||
R seatrReady(Integer fightId, TtUser player);
|
||||
|
||||
R fightRoomExit(Integer fightId, TtUser player);
|
||||
|
||||
List<ApiFightListDataVO> getFightList(FightOnMyOwnParam param);
|
||||
|
||||
R fightDetail(FightDetailParam param);
|
||||
|
||||
R earlierHistory(FightDetailParam param);
|
||||
|
||||
// AjaxResult joinFightRoom(Integer userId,Integer fightId);
|
||||
|
||||
List<ApiFightRankingVO> getFightRankingByDate(String date);
|
||||
|
||||
Map<String, List<FightResultVO>> tenTopFight(Integer maxType);
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.ruoyi.playingmethod.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.ruoyi.domain.other.TtFightUser;
|
||||
|
||||
public interface ApiFightUserService extends IService<TtFightUser> {
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.ruoyi.playingmethod.service;
|
||||
|
||||
import com.ruoyi.common.core.domain.R;
|
||||
import com.ruoyi.domain.other.ApiLuckyUpgradeBody;
|
||||
import com.ruoyi.domain.entity.sys.TtUser;
|
||||
import com.ruoyi.domain.other.UpgradeBodyA;
|
||||
import com.ruoyi.domain.vo.ApiLuckyOrnamentsDataVO;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface ApiLuckyUpgradeService {
|
||||
|
||||
List<ApiLuckyOrnamentsDataVO> getOrnamentsList(ApiLuckyUpgradeBody apiLuckyUpgradeBody);
|
||||
|
||||
R upgrade(TtUser ttUser, UpgradeBodyA upgradeBodyA);
|
||||
|
||||
// List<ApiLuckyUpgradeRecordDataVO> getUpgradeRecord(getUpgradeRecord param);
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.ruoyi.playingmethod.service;
|
||||
|
||||
import com.ruoyi.common.core.domain.AjaxResult;
|
||||
import com.ruoyi.common.core.domain.model.LoginUser;
|
||||
import com.ruoyi.domain.other.TtRedPack;
|
||||
import com.ruoyi.domain.other.TtRedPacketRecord;
|
||||
import com.ruoyi.thirdparty.wechat.domain.PtLoginUser;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface ApiRedPackService {
|
||||
|
||||
List<TtRedPack> getRedPackList(PtLoginUser user, Integer type);
|
||||
|
||||
AjaxResult getRedPack(Long userId, Long redPackId);
|
||||
|
||||
List<TtRedPacketRecord> getActivityDataHis(PtLoginUser user);
|
||||
|
||||
AjaxResult getRedPackDataDetail(PtLoginUser user, Long recordId);
|
||||
|
||||
AjaxResult getRedPackByKey(LoginUser user, String redPackKey);
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package com.ruoyi.playingmethod.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.ruoyi.common.core.domain.R;
|
||||
import com.ruoyi.domain.dto.roll.GetRollOpenPrizeParam;
|
||||
import com.ruoyi.domain.dto.roll.GetRollPlayersParam;
|
||||
import com.ruoyi.domain.dto.roll.GetRollPrizePool;
|
||||
import com.ruoyi.domain.entity.roll.TtRoll;
|
||||
import com.ruoyi.domain.entity.sys.TtUser;
|
||||
import com.ruoyi.domain.vo.RollDetailsDataVO;
|
||||
import com.ruoyi.domain.vo.RollListDataVO;
|
||||
import com.ruoyi.domain.vo.boxRecords.TtBoxRecordsVO;
|
||||
import com.ruoyi.domain.vo.roll.RollJackpotOrnamentsVO;
|
||||
import com.ruoyi.domain.vo.roll.RollUserVO;
|
||||
import com.ruoyi.playingmethod.controller.ApiRollController.GetRollListParam;
|
||||
import com.ruoyi.playingmethod.controller.ApiRollController.JoinRollParam;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface ApiRollService extends IService<TtRoll> {
|
||||
|
||||
R joinRoll(JoinRollParam param, TtUser player);
|
||||
|
||||
R endROLL(Integer rollId);
|
||||
|
||||
// List<RollListDataVO> getRollList(GetRollListParam param);
|
||||
|
||||
List<RollListDataVO> getRollList(GetRollListParam param);
|
||||
|
||||
R<RollDetailsDataVO> getRollDetails(Integer rollId);
|
||||
|
||||
R<List<RollUserVO>> getRollPlayers(GetRollPlayersParam param);
|
||||
|
||||
R<List<RollJackpotOrnamentsVO>> getRollPrizePool(GetRollPrizePool param);
|
||||
|
||||
R<List<TtBoxRecordsVO>> getRollOpenPrize(GetRollOpenPrizeParam param);
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.ruoyi.playingmethod.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.ruoyi.common.core.domain.R;
|
||||
import com.ruoyi.domain.dto.upgrade.UpgradeCondition;
|
||||
import com.ruoyi.domain.other.*;
|
||||
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface ApiUpgradeRecordService extends IService<TtUpgradeRecord> {
|
||||
|
||||
R historyDetail(UpgradeCondition param);
|
||||
|
||||
R tenTopDetail(Boolean isVictory);
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package com.ruoyi.playingmethod.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.ruoyi.domain.entity.TtUserBlendErcash;
|
||||
|
||||
public interface ApiUserBlendErcashService extends IService<TtUserBlendErcash> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package com.ruoyi.playingmethod.service;
|
||||
|
||||
import com.ruoyi.domain.vo.OpenBoxVO;
|
||||
import com.ruoyi.playingmethod.model.ApiWelfare;
|
||||
import com.ruoyi.playingmethod.model.vo.ApiWelfareMonthlyRechargesVO;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface ApiWelfareMonthlyRechargesService {
|
||||
|
||||
/**
|
||||
* 获取福利列表
|
||||
*/
|
||||
List<ApiWelfareMonthlyRechargesVO> getWelfareList(Long userId);
|
||||
|
||||
/**
|
||||
* 领取福利
|
||||
*/
|
||||
OpenBoxVO claimWelfare(Integer welfareId, Long userId);
|
||||
|
||||
/**
|
||||
* 检查是否符合领取条件
|
||||
*/
|
||||
boolean checkEligible(Integer welfareId, Long userId);
|
||||
|
||||
/**
|
||||
* 检查是否已领取
|
||||
*/
|
||||
boolean checkClaimed(Integer welfareId, Long userId);
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package com.ruoyi.playingmethod.service;
|
||||
|
||||
import com.ruoyi.common.core.domain.AjaxResult;
|
||||
import com.ruoyi.domain.vo.OpenBoxVO;
|
||||
import com.ruoyi.playingmethod.model.ApiWelfare;
|
||||
import com.ruoyi.playingmethod.model.ApiWelfareRecord;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface ApiWelfareService {
|
||||
|
||||
/**
|
||||
* 获取福利列表
|
||||
*/
|
||||
List<ApiWelfare> getWelfareList(Long userId);
|
||||
|
||||
/**
|
||||
* 领取福利
|
||||
*/
|
||||
OpenBoxVO claimWelfare(Integer welfareId, Long userId);
|
||||
|
||||
/**
|
||||
* 检查是否不符合领取条件
|
||||
*/
|
||||
boolean checkNotEligible(Integer welfareId, Long userId);
|
||||
|
||||
/**
|
||||
* 检查是否已领取
|
||||
*/
|
||||
boolean checkClaimed(Integer welfareId, Long userId);
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package com.ruoyi.playingmethod.service;
|
||||
|
||||
import com.ruoyi.playingmethod.entity.TtAttendanceRecord;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface IApiAttendanceRecordService {
|
||||
|
||||
TtAttendanceRecord selectByUid(int uid);
|
||||
|
||||
int insert(int uid);
|
||||
|
||||
List<TtAttendanceRecord> selectSevenAttendance(int uid);
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.ruoyi.playingmethod.service;
|
||||
|
||||
import com.ruoyi.common.core.domain.AjaxResult;
|
||||
import com.ruoyi.common.core.domain.model.LoginUser;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface IApiReplacementRecordService {
|
||||
|
||||
AjaxResult synthesizeItems(LoginUser user, List<Long> itemIds);
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
package com.ruoyi.playingmethod.service.impl;
|
||||
|
||||
import cn.hutool.core.date.DateTime;
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import com.ruoyi.playingmethod.entity.TtAttendanceRecord;
|
||||
import com.ruoyi.playingmethod.mapper.ApiAttendanceRecordMapper;
|
||||
import com.ruoyi.playingmethod.service.IApiAttendanceRecordService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.*;
|
||||
|
||||
@Service
|
||||
@Slf4j
|
||||
public class ApiAttendanceRecordServiceImpl implements IApiAttendanceRecordService{
|
||||
private final ApiAttendanceRecordMapper apiTtAttendanceRecordMapper;
|
||||
|
||||
public ApiAttendanceRecordServiceImpl(ApiAttendanceRecordMapper apiTtAttendanceRecordMapper) {
|
||||
this.apiTtAttendanceRecordMapper = apiTtAttendanceRecordMapper;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public TtAttendanceRecord selectByUid(int uid) {
|
||||
return apiTtAttendanceRecordMapper.selectByUid(uid);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int insert(int uid) {
|
||||
TtAttendanceRecord ttAttendanceRecord = new TtAttendanceRecord();
|
||||
ttAttendanceRecord.setUserId(uid);
|
||||
ttAttendanceRecord.setCreateTime(new Date());
|
||||
ttAttendanceRecord.setCoin(1);
|
||||
return apiTtAttendanceRecordMapper.insertAttendanceRecord(ttAttendanceRecord);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<TtAttendanceRecord> selectSevenAttendance(int uid) {
|
||||
List<TtAttendanceRecord> ttAttendanceRecords = new ArrayList<>();
|
||||
//周一
|
||||
DateTime dateTime = DateUtil.beginOfWeek(new Date());
|
||||
System.out.println(new SimpleDateFormat("yyyy-MM-dd").format(dateTime));
|
||||
TtAttendanceRecord zhouYittAttendanceRecor = new TtAttendanceRecord();
|
||||
|
||||
if (apiTtAttendanceRecordMapper.selectSevenAttendance(uid,new SimpleDateFormat("yyyy-MM-dd").format(dateTime)) != null )zhouYittAttendanceRecor.setIsStatus("1");
|
||||
zhouYittAttendanceRecor.setCreateTime(dateTime);
|
||||
ttAttendanceRecords.add(zhouYittAttendanceRecor);
|
||||
//周二
|
||||
Calendar calendar = new GregorianCalendar();
|
||||
calendar.setTime(dateTime);
|
||||
calendar.add(Calendar.DATE, 1);
|
||||
System.out.println(new SimpleDateFormat("yyyy-MM-dd").format(calendar.getTime()));
|
||||
|
||||
TtAttendanceRecord zhouErttAttendanceRecord = new TtAttendanceRecord();
|
||||
if (apiTtAttendanceRecordMapper.selectSevenAttendance(uid,new SimpleDateFormat("yyyy-MM-dd").format(calendar.getTime())) != null)zhouErttAttendanceRecord.setIsStatus("1");
|
||||
zhouErttAttendanceRecord.setCreateTime(calendar.getTime());
|
||||
ttAttendanceRecords.add(zhouErttAttendanceRecord);
|
||||
|
||||
//周三
|
||||
calendar.add(Calendar.DATE, 1);
|
||||
System.out.println(new SimpleDateFormat("yyyy-MM-dd").format(calendar.getTime()));
|
||||
|
||||
TtAttendanceRecord zhouSanttAttendanceRecord = new TtAttendanceRecord();
|
||||
if (apiTtAttendanceRecordMapper.selectSevenAttendance(uid,new SimpleDateFormat("yyyy-MM-dd").format(calendar.getTime())) != null )zhouSanttAttendanceRecord.setIsStatus("1");
|
||||
zhouSanttAttendanceRecord.setCreateTime(calendar.getTime());
|
||||
ttAttendanceRecords.add(zhouSanttAttendanceRecord);
|
||||
|
||||
//周四
|
||||
calendar.add(Calendar.DATE, 1);
|
||||
System.out.println(new SimpleDateFormat("yyyy-MM-dd").format(calendar.getTime()));
|
||||
|
||||
TtAttendanceRecord zhouSittAttendanceRecord = new TtAttendanceRecord();
|
||||
if (apiTtAttendanceRecordMapper.selectSevenAttendance(uid,new SimpleDateFormat("yyyy-MM-dd").format(calendar.getTime())) != null )zhouSittAttendanceRecord.setIsStatus("1");
|
||||
zhouSittAttendanceRecord.setCreateTime(calendar.getTime());
|
||||
ttAttendanceRecords.add(zhouSittAttendanceRecord);
|
||||
|
||||
//周五
|
||||
calendar.add(Calendar.DATE, 1);
|
||||
System.out.println(new SimpleDateFormat("yyyy-MM-dd").format(calendar.getTime()));
|
||||
|
||||
TtAttendanceRecord zhouWuttAttendanceRecord = new TtAttendanceRecord();
|
||||
if (apiTtAttendanceRecordMapper.selectSevenAttendance(uid,new SimpleDateFormat("yyyy-MM-dd").format(calendar.getTime())) != null )zhouWuttAttendanceRecord.setIsStatus("1");
|
||||
zhouWuttAttendanceRecord.setCreateTime(calendar.getTime());
|
||||
ttAttendanceRecords.add(zhouWuttAttendanceRecord);
|
||||
|
||||
//周六
|
||||
calendar.add(Calendar.DATE, 1);
|
||||
System.out.println(new SimpleDateFormat("yyyy-MM-dd").format(calendar.getTime()));
|
||||
|
||||
TtAttendanceRecord zhouLiuttAttendanceRecord = new TtAttendanceRecord();
|
||||
if (apiTtAttendanceRecordMapper.selectSevenAttendance(uid,new SimpleDateFormat("yyyy-MM-dd").format(calendar.getTime())) != null )zhouLiuttAttendanceRecord.setIsStatus("1");
|
||||
zhouLiuttAttendanceRecord.setCreateTime(calendar.getTime());
|
||||
ttAttendanceRecords.add(zhouLiuttAttendanceRecord);
|
||||
|
||||
//周天
|
||||
calendar.add(Calendar.DATE, 1);
|
||||
System.out.println(new SimpleDateFormat("yyyy-MM-dd").format(calendar.getTime()));
|
||||
|
||||
TtAttendanceRecord zhouRittAttendanceRecord = new TtAttendanceRecord();
|
||||
if (apiTtAttendanceRecordMapper.selectSevenAttendance(uid,new SimpleDateFormat("yyyy-MM-dd").format(calendar.getTime())) != null )zhouRittAttendanceRecord.setIsStatus("1");
|
||||
zhouRittAttendanceRecord.setCreateTime(calendar.getTime());
|
||||
ttAttendanceRecords.add(zhouRittAttendanceRecord);
|
||||
|
||||
return ttAttendanceRecords;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package com.ruoyi.playingmethod.service.impl;
|
||||
|
||||
import com.ruoyi.playingmethod.service.ApiBattleRoyaleService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class ApiBattleRoyaleServiceImpl implements ApiBattleRoyaleService {
|
||||
}
|
||||
@@ -0,0 +1,481 @@
|
||||
package com.ruoyi.playingmethod.service.impl;
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.hutool.core.map.MapUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
||||
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
|
||||
import com.ruoyi.admin.mapper.TtBoxOrnamentsMapper;
|
||||
import com.ruoyi.admin.mapper.TtBoxRecordsMapper;
|
||||
import com.ruoyi.admin.mapper.TtBoxTypeMapper;
|
||||
import com.ruoyi.admin.mapper.TtCompRecordMapper;
|
||||
import com.ruoyi.admin.model.UpdateUserAccountBo;
|
||||
import com.ruoyi.admin.service.TtBoxRecordsService;
|
||||
import com.ruoyi.admin.service.TtBoxService;
|
||||
import com.ruoyi.admin.service.TtOrnamentsLevelService;
|
||||
import com.ruoyi.admin.service.TtUserService;
|
||||
import com.ruoyi.admin.util.core.fight.LotteryMachine;
|
||||
import com.ruoyi.common.core.domain.R;
|
||||
import com.ruoyi.common.core.redis.RedisCache;
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
import com.ruoyi.domain.common.constant.TtAccountRecordSource;
|
||||
import com.ruoyi.domain.common.constant.TtAccountRecordType;
|
||||
import com.ruoyi.domain.common.constant.TtboxRecordSource;
|
||||
import com.ruoyi.domain.dto.boxRecords.TtBoxRecordsNum;
|
||||
import com.ruoyi.domain.entity.TtBoxRecords;
|
||||
import com.ruoyi.domain.entity.TtUserBlendErcash;
|
||||
import com.ruoyi.domain.entity.sys.TtUser;
|
||||
import com.ruoyi.domain.other.*;
|
||||
import com.ruoyi.domain.vo.OpenBoxVO;
|
||||
import com.ruoyi.playingmethod.domain.vo.CompValueVO;
|
||||
import com.ruoyi.playingmethod.mapper.ApiBindBoxMapper;
|
||||
import com.ruoyi.playingmethod.mapper.ApiTtUserBlendErcashMapper;
|
||||
import com.ruoyi.playingmethod.service.ApiBindBoxService;
|
||||
import com.ruoyi.playingmethod.utils.customException.OrnamentNullException;
|
||||
import com.ruoyi.playingmethod.websocket.WsBindBox;
|
||||
import com.ruoyi.playingmethod.websocket.constant.SMsgKey;
|
||||
import com.ruoyi.playingmethod.websocket.util.WsResult;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.springframework.amqp.rabbit.core.RabbitTemplate;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.sql.Timestamp;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static com.ruoyi.domain.common.constant.TtboxRecordStatus.IN_PACKSACK_ON;
|
||||
import static java.math.BigDecimal.ROUND_HALF_UP;
|
||||
|
||||
@Service
|
||||
@Slf4j
|
||||
public class ApiBindBoxServiceImpl implements ApiBindBoxService {
|
||||
|
||||
private final TtUserService userService;
|
||||
private final TtBoxService boxService;
|
||||
private final TtBoxTypeMapper boxTypeMapper;
|
||||
private final ApiBindBoxMapper bindBoxMapper;
|
||||
private final TtBoxOrnamentsMapper boxOrnamentsMapper;
|
||||
private final TtBoxRecordsService boxRecordsService;
|
||||
private final RedisCache redisCache;
|
||||
private final Executor customThreadPoolExecutor;
|
||||
|
||||
@Autowired
|
||||
private RabbitTemplate rabbitTemplate;
|
||||
|
||||
@Autowired
|
||||
private LotteryMachine lotteryMachine;
|
||||
|
||||
@Autowired
|
||||
private TtCompRecordMapper ttCompRecordMapper;
|
||||
|
||||
@Autowired
|
||||
private ApiTtUserBlendErcashMapper apiTtUserBlendErcashMapper;
|
||||
|
||||
@Autowired
|
||||
private TtBoxRecordsMapper ttBoxRecordsMapper;
|
||||
|
||||
@Autowired
|
||||
private TtOrnamentsLevelService ornamentsLevelService;
|
||||
|
||||
public ApiBindBoxServiceImpl(TtUserService userService,
|
||||
TtBoxService boxService,
|
||||
TtBoxTypeMapper boxTypeMapper,
|
||||
ApiBindBoxMapper bindBoxMapper,
|
||||
TtBoxOrnamentsMapper boxOrnamentsMapper,
|
||||
TtBoxRecordsService boxRecordsService,
|
||||
RedisCache redisCache,
|
||||
Executor customThreadPoolExecutor) {
|
||||
this.userService = userService;
|
||||
this.boxService = boxService;
|
||||
this.boxTypeMapper = boxTypeMapper;
|
||||
this.bindBoxMapper = bindBoxMapper;
|
||||
this.boxOrnamentsMapper = boxOrnamentsMapper;
|
||||
this.boxRecordsService = boxRecordsService;
|
||||
this.redisCache = redisCache;
|
||||
this.customThreadPoolExecutor = customThreadPoolExecutor;
|
||||
}
|
||||
|
||||
//@PostConstruct
|
||||
public void postConstruct() {
|
||||
List<Integer> boxIds = boxOrnamentsMapper.selectBoxIdList();
|
||||
if (ObjectUtils.isEmpty(boxIds)) return;
|
||||
for (Integer boxId : boxIds) {
|
||||
boxService.isReplenishment(boxId);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public TtBoxA getBoxData(Integer boxId) {
|
||||
|
||||
TtBoxA boxData = bindBoxMapper.getBoxData(boxId);
|
||||
if (ObjectUtils.isEmpty(boxData)) return null;
|
||||
|
||||
List<TtOrnamentsA> boxOrnamentsList = bindBoxMapper.getBoxOrnamentsList(boxId);
|
||||
if (ObjectUtils.isEmpty(boxOrnamentsList)) return null;
|
||||
|
||||
// 计算概率
|
||||
BigDecimal sum = new BigDecimal(boxOrnamentsList.stream().mapToInt(TtOrnamentsA::getOdds).sum());
|
||||
BigDecimal oneHundred = new BigDecimal("100").setScale(2);
|
||||
BigDecimal max = BigDecimal.ZERO;
|
||||
Integer maxId = null;
|
||||
BigDecimal add = BigDecimal.ZERO;
|
||||
List<Long> ornamentIds = new ArrayList<>();
|
||||
for (TtOrnamentsA vo : boxOrnamentsList) {
|
||||
Integer odds = vo.getOdds();
|
||||
BigDecimal oddsResult = new BigDecimal(odds).divide(sum, 4, ROUND_HALF_UP).multiply(oneHundred).setScale(2);
|
||||
add = oddsResult.add(add);
|
||||
if (max.compareTo(oddsResult) <= 0) {
|
||||
max = oddsResult;
|
||||
maxId = vo.getOrnamentId();
|
||||
}
|
||||
vo.setOddsResult(oddsResult);
|
||||
ornamentIds.add(Long.valueOf(vo.getOrnamentId()));
|
||||
}
|
||||
|
||||
// 平差
|
||||
BigDecimal erroValue = oneHundred.subtract(add);
|
||||
for (TtOrnamentsA vo : boxOrnamentsList) {
|
||||
if (vo.getOrnamentId().equals(maxId)) {
|
||||
vo.setOddsResult(vo.getOddsResult().add(erroValue));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (ObjectUtils.isEmpty(boxOrnamentsList)) return null;
|
||||
boxOrnamentsList = boxOrnamentsList.stream().peek(boxOrnamentsDataVO -> boxOrnamentsDataVO.setOdds(null)).collect(Collectors.toList());
|
||||
List<TtBoxLevelA> probabilityDistribution = bindBoxMapper.getProbabilityDistribution(boxId);
|
||||
boxOrnamentsList.sort((o1, o2) -> o2.getUsePrice().compareTo(o1.getUsePrice()));
|
||||
boxData.setBoxOrnamentsList(boxOrnamentsList);
|
||||
boxData.setProbabilityDistribution(probabilityDistribution);
|
||||
// 计算真实开奖
|
||||
List<TtBoxRecordsNum> boxRecordsNums = ttBoxRecordsMapper.selectBoxRecordsByOrnamentIds(boxId, ornamentIds, null);
|
||||
Map<Integer, Integer> ornamentIdNum = new HashMap<>();
|
||||
sum = new BigDecimal(0);
|
||||
add = BigDecimal.ZERO;
|
||||
max = BigDecimal.ZERO;
|
||||
maxId = null;
|
||||
oneHundred = new BigDecimal("100").setScale(2);
|
||||
if (CollectionUtils.isNotEmpty(boxRecordsNums)) {
|
||||
for (TtBoxRecordsNum num : boxRecordsNums) {
|
||||
ornamentIdNum.put(num.getOrnamentId().intValue(), num.getNum());
|
||||
sum = sum.add(new BigDecimal(num.getNum()));
|
||||
}
|
||||
}
|
||||
boxData.setTotalOpenOdds(sum.intValue());
|
||||
// 某个颜色等级真是开奖的数量
|
||||
Map<Integer, Integer> levelNum = new HashMap<>();
|
||||
for (TtOrnamentsA vo : boxOrnamentsList) {
|
||||
Integer openOdds = ornamentIdNum.getOrDefault(vo.getOrnamentId(), 0);
|
||||
vo.setOpenOdds(openOdds);
|
||||
levelNum.put(vo.getOrnamentsLevelId(), levelNum.getOrDefault(vo.getOrnamentsLevelId(), 0) + openOdds);
|
||||
BigDecimal openOddsResult = new BigDecimal(0);
|
||||
if (sum.compareTo(new BigDecimal(0)) > 0) {
|
||||
openOddsResult = new BigDecimal(openOdds).divide(sum, 4, RoundingMode.HALF_UP).multiply(oneHundred).setScale(2);
|
||||
}
|
||||
add = openOddsResult.add(add);
|
||||
if (max.compareTo(openOddsResult) <= 0) {
|
||||
max = openOddsResult;
|
||||
maxId = vo.getOrnamentId();
|
||||
}
|
||||
vo.setOpenOddsResult(openOddsResult);
|
||||
}
|
||||
|
||||
// 平差
|
||||
erroValue = oneHundred.subtract(add);
|
||||
for (TtOrnamentsA vo : boxOrnamentsList) {
|
||||
if (vo.getOrnamentId().equals(maxId)) {
|
||||
vo.setOpenOddsResult(vo.getOpenOddsResult().add(erroValue));
|
||||
break;
|
||||
}
|
||||
}
|
||||
List<TtBoxLevelA> openProbabilityDistribution = new ArrayList<>();
|
||||
List<TtOrnamentsLevel> levels = ornamentsLevelService.list();
|
||||
if (CollectionUtils.isNotEmpty(levels)) {
|
||||
for (TtOrnamentsLevel level : levels) {
|
||||
TtBoxLevelA a = new TtBoxLevelA();
|
||||
a.setLevel(level.getLevel());
|
||||
a.setOrnamentsLevelId(level.getId());
|
||||
BigDecimal probability = new BigDecimal(0);
|
||||
if (sum.compareTo(new BigDecimal(0)) > 0) {
|
||||
probability = new BigDecimal(levelNum.getOrDefault(level.getId(), 0)).divide(sum, 4, RoundingMode.HALF_UP).multiply(oneHundred).setScale(2);
|
||||
}
|
||||
a.setProbability(probability.toString());
|
||||
openProbabilityDistribution.add(a);
|
||||
}
|
||||
}
|
||||
boxData.setOpenProbabilityDistribution(openProbabilityDistribution);
|
||||
return boxData;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<TtOrnamentsA> getCompBoxData(Integer boxId) {
|
||||
List<TtOrnamentsA> boxOrnamentsList = bindBoxMapper.getBoxOrnamentsList(boxId);
|
||||
if (ObjectUtils.isEmpty(boxOrnamentsList))
|
||||
return null;
|
||||
// 剔除非补偿物品
|
||||
boxOrnamentsList.removeIf(ttOrnamentsA -> ttOrnamentsA.getCompOdds() == 0);
|
||||
// 计算概率
|
||||
BigDecimal sum = new BigDecimal(boxOrnamentsList.stream().mapToInt(TtOrnamentsA::getCompOdds).sum());
|
||||
BigDecimal oneHundred = new BigDecimal("100").setScale(2);
|
||||
BigDecimal max = BigDecimal.ZERO;
|
||||
Integer maxId = null;
|
||||
BigDecimal add = BigDecimal.ZERO;
|
||||
for (TtOrnamentsA ttOrnamentsA : boxOrnamentsList) {
|
||||
Integer compOdds = ttOrnamentsA.getCompOdds();
|
||||
BigDecimal compOddsResult = new BigDecimal(compOdds).divide(sum, 4, ROUND_HALF_UP).multiply(oneHundred).setScale(2);
|
||||
add = compOddsResult.add(add);
|
||||
if (max.compareTo(compOddsResult) <= 0) {
|
||||
max = compOddsResult;
|
||||
maxId = ttOrnamentsA.getOrnamentId();
|
||||
}
|
||||
ttOrnamentsA.setCompOddsResult(compOddsResult);
|
||||
}
|
||||
// 平差
|
||||
BigDecimal errorValue = oneHundred.subtract(add);
|
||||
for (TtOrnamentsA vo : boxOrnamentsList) {
|
||||
if (vo.getOrnamentId().equals(maxId)) {
|
||||
vo.setOddsResult(vo.getCompOddsResult().add(errorValue));
|
||||
break;
|
||||
}
|
||||
}
|
||||
return boxOrnamentsList;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<TtBoxVO> getBoxList(Integer boxTypeId, String homeFlag, String boxType) {
|
||||
|
||||
List<TtBoxA> boxList = bindBoxMapper.getBoxList(boxTypeId, homeFlag, boxType);
|
||||
|
||||
// 过滤空箱子
|
||||
List<TtBoxA> collect = boxList.stream().filter(item -> {
|
||||
|
||||
List<TtBoxOrnaments> list = new LambdaQueryChainWrapper<>(boxOrnamentsMapper)
|
||||
.eq(TtBoxOrnaments::getBoxId, item.getBoxId())
|
||||
.list();
|
||||
if (ObjectUtil.isEmpty(list) || list.isEmpty()) return false;
|
||||
|
||||
boolean flag = false;
|
||||
for (TtBoxOrnaments ornaments : list) {
|
||||
if (ornaments.getRealOdds() > 0) {
|
||||
return !flag;
|
||||
}
|
||||
}
|
||||
return flag;
|
||||
|
||||
}).collect(Collectors.toList());
|
||||
|
||||
return groupByBoxType(collect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<TtBoxVO> groupByBoxType(List<TtBoxA> boxData) {
|
||||
Map<Integer, List<TtBoxA>> collect = boxData.stream().collect(Collectors.groupingBy(TtBoxA::getBoxTypeId));
|
||||
List<TtBoxVO> resultList = new ArrayList<>();
|
||||
for (Map.Entry<Integer, List<TtBoxA>> entry : collect.entrySet()) {
|
||||
Integer key = entry.getKey();
|
||||
List<TtBoxA> value = entry.getValue();
|
||||
TtBoxType ttBoxType = boxTypeMapper.selectById(key);
|
||||
if (StringUtils.isNull(ttBoxType)) continue;
|
||||
TtBoxVO boxTypeA = TtBoxVO.builder().build();
|
||||
boxTypeA.setBoxTypeId(ttBoxType.getId());
|
||||
boxTypeA.setBoxTypeName(ttBoxType.getName());
|
||||
boxTypeA.setIcon(ttBoxType.getIcon());
|
||||
boxTypeA.setBoxList(value);
|
||||
resultList.add(boxTypeA);
|
||||
}
|
||||
return resultList;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<TtOrnamentsA> openBox(TtBox ttBox, Integer num, TtUser ttUser) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<TtBoxRecords> addBoxRecord(TtUser ttUser, TtBox ttBox, Integer num) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<TtBoxRecords> openBoxArithmetic(Integer fightId, TtUser ttUser, TtBox ttBox, Integer num) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public R blindBox(TtUser user, TtBox box, Integer num) {
|
||||
|
||||
// 同步扣款
|
||||
BigDecimal totalmoney = box.getPrice().multiply(new BigDecimal(num));
|
||||
R r = upgradeAccounting(totalmoney, user);
|
||||
if (R.isError(r)) {
|
||||
return R.fail(r.getMsg());
|
||||
}
|
||||
|
||||
// 抽奖
|
||||
List<TtBoxRecords> boxRecords = new ArrayList<>();
|
||||
Map<Long, TtOrnamentsA> boxToOrnament = new HashMap<>();
|
||||
for (int i = 0; i < num; i++) {
|
||||
|
||||
String ornamentId = lotteryMachine.singleLottery(user, box);
|
||||
|
||||
if (StringUtils.isBlank(ornamentId)) {
|
||||
throw new OrnamentNullException("单次抽奖无结果#"+box.getBoxId()+"#"+ornamentId);
|
||||
//return R.fail("系统繁忙,请稍后重试。");
|
||||
}
|
||||
|
||||
// 宝箱详细信息
|
||||
TtOrnamentsA ornamentsData = bindBoxMapper.ornamentsInfo(box.getBoxId(), ornamentId);
|
||||
|
||||
if (ObjectUtil.isEmpty(ornamentsData)){
|
||||
throw new OrnamentNullException("没有符合条件的宝箱信息#"+box.getBoxId()+"#"+ornamentId);
|
||||
}
|
||||
|
||||
// 比对补偿箱类型开箱价格和奖品价值,记录补偿值。如果饰品大于等于门票,清空补偿值
|
||||
if ("3".equals(box.getBoxType()) && ornamentsData.getUsePrice().compareTo(box.getPrice()) < 0) {
|
||||
compRecord(user.getUserId(), box.getBoxId());
|
||||
} else {
|
||||
ttCompRecordMapper.deleteTtCompRecord(user.getUserId(), box.getBoxId());
|
||||
}
|
||||
|
||||
// 抽奖成功,构建开箱记录数据
|
||||
TtBoxRecords boxRecord = TtBoxRecords.builder()
|
||||
.userId(user.getUserId())
|
||||
|
||||
.boxId(box.getBoxId())
|
||||
.boxName(box.getBoxName())
|
||||
.boxPrice(box.getPrice())
|
||||
|
||||
.ornamentId(Long.valueOf(ornamentId))
|
||||
// .marketHashName(ornamentsData.)
|
||||
.ornamentName(ObjectUtil.isNotEmpty(ornamentsData.getName()) ? ornamentsData.getName() : ObjectUtil.isNotEmpty(ornamentsData.getShortName()) ? ornamentsData.getShortName() : "无名称")
|
||||
.imageUrl(ornamentsData.getImageUrl())
|
||||
.ornamentsPrice(ornamentsData.getUsePrice())
|
||||
.ornamentsLevelId(ornamentsData.getOrnamentsLevelId())
|
||||
.ornamentLevelImg(ornamentsData.getLevelImg())
|
||||
|
||||
.holderUserId(user.getUserId())
|
||||
|
||||
.source(TtboxRecordSource.BLIND_BOX.getCode())
|
||||
.status(IN_PACKSACK_ON.getCode())
|
||||
|
||||
.createTime(new Timestamp(System.currentTimeMillis()))
|
||||
.updateTime(new Timestamp(System.currentTimeMillis()))
|
||||
.build();
|
||||
|
||||
boxRecords.add(boxRecord);
|
||||
boxToOrnament.put(Long.valueOf(ornamentId), ornamentsData);
|
||||
}
|
||||
|
||||
// 同步保存游戏记录
|
||||
boxRecordsService.saveBatch(boxRecords);
|
||||
|
||||
// 返回值
|
||||
List<OpenBoxVO> openBoxVOs = boxRecords.stream().map(item -> {
|
||||
OpenBoxVO openBoxVO = new OpenBoxVO();
|
||||
BeanUtil.copyProperties(item, openBoxVO);
|
||||
TtOrnamentsA ornamentsData = boxToOrnament.get(item.getOrnamentId());
|
||||
if (ornamentsData != null) {
|
||||
openBoxVO.setShortName(ornamentsData.getShortName());
|
||||
openBoxVO.setExteriorName(ornamentsData.getExteriorName());
|
||||
}
|
||||
openBoxVO.setUsePrice(openBoxVO.getOrnamentsPrice());
|
||||
openBoxVO.setLevelImg(item.getOrnamentLevelImg());
|
||||
return openBoxVO;
|
||||
}).collect(Collectors.toList());
|
||||
|
||||
// 异步任务 广播开箱消息
|
||||
broadcastToBoxRoom(boxRecords);
|
||||
|
||||
return R.ok(openBoxVOs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompValueVO getCompValue(TtUser ttUser, TtBox ttBox) {
|
||||
CompValueVO compValueVO = new CompValueVO();
|
||||
// 查询宝箱设定的补偿值
|
||||
compValueVO.setDesiredCompValue(ttBox.getCompAmount());
|
||||
// 查询用户当前补偿值
|
||||
TtCompRecord ttCompRecord = ttCompRecordMapper.selectTtCompRecord(ttUser.getUserId(), ttBox.getBoxId());
|
||||
if (Objects.isNull(ttCompRecord))
|
||||
compValueVO.setCurrentCompValue(0);
|
||||
else
|
||||
compValueVO.setCurrentCompValue(ttCompRecord.getCompAmount());
|
||||
return compValueVO;
|
||||
}
|
||||
|
||||
// 扣款
|
||||
public R upgradeAccounting(BigDecimal consumption, TtUser player) {
|
||||
|
||||
// 再次检查余额
|
||||
player = userService.getById(player.getUserId());
|
||||
if (player.getAccountAmount() == null || player.getAccountAmount().compareTo(consumption) < 0) {
|
||||
return R.fail("余额不足");
|
||||
}
|
||||
return userService.updateUserAccount(player.getUserId(), consumption.negate(), TtAccountRecordSource.GAME_TYPE_01);
|
||||
}
|
||||
|
||||
// 异步任务 广播开箱消息
|
||||
public void broadcastToBoxRoom(List<TtBoxRecords> boxRecords) {
|
||||
|
||||
CompletableFuture.runAsync(() -> {
|
||||
|
||||
// 数据按boxId排序
|
||||
Collections.sort(boxRecords, new Comparator<TtBoxRecords>() {
|
||||
@Override
|
||||
public int compare(TtBoxRecords o1, TtBoxRecords o2) {
|
||||
return o1.getBoxId().compareTo(o2.getBoxId());
|
||||
}
|
||||
});
|
||||
|
||||
// 缓冲区
|
||||
List<TtBoxRecords> cache = new ArrayList<>();
|
||||
|
||||
Integer flagBoxId = -1;
|
||||
for (TtBoxRecords record : boxRecords) {
|
||||
|
||||
if (cache.isEmpty()) {
|
||||
// 缓冲区为空,直接加入
|
||||
cache.add(record);
|
||||
flagBoxId = record.getBoxId();
|
||||
continue;
|
||||
} else {
|
||||
// 不为空
|
||||
if (record.getBoxId().equals(flagBoxId)) {
|
||||
cache.add(record);
|
||||
} else {
|
||||
Integer bid = cache.get(0).getBoxId();
|
||||
// 广播最新数据
|
||||
WsBindBox.broadcastToBoxRoom(bid, WsResult.ok(SMsgKey.Blind_Box_Current_Data.name(), cache, "开盒子更新。"));
|
||||
cache.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
Integer bid = cache.get(0).getBoxId();
|
||||
// 广播最新数据
|
||||
WsBindBox.broadcastToBoxRoom(bid, WsResult.ok(SMsgKey.Blind_Box_Current_Data.name(), cache, "开盒子更新。"));
|
||||
|
||||
}, customThreadPoolExecutor);
|
||||
}
|
||||
|
||||
// 记录补偿值
|
||||
public void compRecord(Integer userId, Integer boxId) {
|
||||
// 查询当前补偿值
|
||||
TtCompRecord ttCompRecord = ttCompRecordMapper.selectTtCompRecord(userId, boxId);
|
||||
if (!Objects.isNull(ttCompRecord)) {
|
||||
// 补偿值+1
|
||||
ttCompRecord.setCompAmount(ttCompRecord.getCompAmount() + 1);
|
||||
ttCompRecordMapper.updateTtCompRecord(ttCompRecord);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.ruoyi.playingmethod.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.ruoyi.domain.other.TtBoxOrnaments;
|
||||
import com.ruoyi.playingmethod.mapper.ApiBoxOrnamentsMapper;
|
||||
import com.ruoyi.playingmethod.service.ApiBoxOrnamentsService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class ApiBoxOrnamentsServiceImpl extends ServiceImpl<ApiBoxOrnamentsMapper, TtBoxOrnaments> implements ApiBoxOrnamentsService {
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
package com.ruoyi.playingmethod.service.impl;
|
||||
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.ruoyi.admin.mapper.*;
|
||||
import com.ruoyi.domain.dto.boxRecords.TenTopQuery;
|
||||
import com.ruoyi.domain.dto.boxRecords.queryCondition;
|
||||
import com.ruoyi.domain.entity.TtBoxRecords;
|
||||
import com.ruoyi.domain.vo.boxRecords.TtBoxRecordsVO;
|
||||
import com.ruoyi.playingmethod.service.ApiBoxRecordsService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
@Service
|
||||
@Slf4j
|
||||
public class ApiBoxRecordsServiceImpl extends ServiceImpl<TtBoxRecordsMapper, TtBoxRecords> implements ApiBoxRecordsService {
|
||||
@Override
|
||||
public List<TtBoxRecordsVO> byCondition(queryCondition condition) {
|
||||
|
||||
condition.setLimit((condition.getPage() - 1) * condition.getSize());
|
||||
if (ObjectUtil.isNull(condition.getOrderByFie())) condition.setOrderByFie(1);
|
||||
|
||||
List<TtBoxRecordsVO> list = this.baseMapper.byCondition(
|
||||
condition.getUserId(),
|
||||
condition.getLimit(),
|
||||
condition.getSize(),
|
||||
condition.getOrderByFie(),
|
||||
condition.getBoxRecordId(),
|
||||
condition.getBoxId(),
|
||||
condition.getUserType(),
|
||||
condition.getSource(),
|
||||
condition.getStatus(),
|
||||
condition.getOrnamentPriceMin(),
|
||||
condition.getOrnamentPriceMax(),
|
||||
condition.getOrnamentLevelIds()
|
||||
);
|
||||
|
||||
// 排序
|
||||
// Comparator<TtBoxRecordsVO> comparator = null;
|
||||
// if (ObjectUtil.isNull(condition.getOrderByFie()) || condition.getOrderByFie().equals(1)) {
|
||||
// comparator = new Comparator<TtBoxRecordsVO>() {
|
||||
// @Override
|
||||
// public int compare(TtBoxRecordsVO o1, TtBoxRecordsVO o2) {
|
||||
// return o1.getCreateTime().compareTo(o2.getCreateTime());
|
||||
// }
|
||||
// };
|
||||
// } else if (condition.getOrderByFie().equals(0)) {
|
||||
// comparator = new Comparator<TtBoxRecordsVO>() {
|
||||
// @Override
|
||||
// public int compare(TtBoxRecordsVO o1, TtBoxRecordsVO o2) {
|
||||
// return o2.getCreateTime().compareTo(o1.getCreateTime());
|
||||
// }
|
||||
// };
|
||||
// }
|
||||
//
|
||||
// Collections.sort(list, comparator);
|
||||
|
||||
return list;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<TtBoxRecordsVO> tenTopQuery(TenTopQuery query) {
|
||||
query.setLimit((query.getPage() - 1) * query.getSize());
|
||||
|
||||
return this.baseMapper.tenTopQuery(
|
||||
query.getLimit(),
|
||||
query.getSize(),
|
||||
query.getSource(),
|
||||
query.getStatus()
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
package com.ruoyi.playingmethod.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
|
||||
import com.ruoyi.admin.mapper.TtOrnamentMapper;
|
||||
import com.ruoyi.domain.common.constant.TtboxRecordStatus;
|
||||
import com.ruoyi.domain.entity.TtBoxRecords;
|
||||
import com.ruoyi.domain.entity.TtOrnament;
|
||||
import com.ruoyi.domain.other.TtOrnamentsLevel;
|
||||
import com.ruoyi.domain.entity.sys.TtUser;
|
||||
import com.ruoyi.admin.service.TtBoxRecordsService;
|
||||
import com.ruoyi.admin.service.TtOrnamentsLevelService;
|
||||
import com.ruoyi.admin.service.WebsitePropertyService;
|
||||
import com.ruoyi.admin.util.RandomUtils;
|
||||
import com.ruoyi.domain.vo.WebsitePropertyDataVO;
|
||||
import com.ruoyi.common.core.domain.R;
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
import com.ruoyi.playingmethod.mapper.ApiCompoundMapper;
|
||||
import com.ruoyi.playingmethod.service.ApiCompoundService;
|
||||
import com.ruoyi.system.service.ISysConfigService;
|
||||
import com.ruoyi.user.service.ApiUserPackSackService;
|
||||
import com.ruoyi.domain.vo.UserPackSackDataVO;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.util.Comparator;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static com.ruoyi.domain.common.constant.TtboxRecordSource.MALL_EXCHANGE;
|
||||
|
||||
@Service
|
||||
@Slf4j
|
||||
public class ApiCompoundServiceImpl implements ApiCompoundService {
|
||||
|
||||
private final ISysConfigService configService;
|
||||
private final ApiUserPackSackService userPackSackService;
|
||||
private final WebsitePropertyService websitePropertyService;
|
||||
private final TtBoxRecordsService boxRecordsService;
|
||||
private final TtOrnamentMapper ornamentsMapper;
|
||||
private final TtOrnamentsLevelService ornamentsLevelService;
|
||||
private final ApiCompoundMapper apiCompoundMapper;
|
||||
|
||||
public ApiCompoundServiceImpl(ISysConfigService configService,
|
||||
ApiUserPackSackService userPackSackService,
|
||||
WebsitePropertyService websitePropertyService,
|
||||
TtBoxRecordsService boxRecordsService,
|
||||
TtOrnamentMapper ornamentsMapper,
|
||||
TtOrnamentsLevelService ornamentsLevelService,
|
||||
ApiCompoundMapper apiCompoundMapper) {
|
||||
this.configService = configService;
|
||||
this.userPackSackService = userPackSackService;
|
||||
this.websitePropertyService = websitePropertyService;
|
||||
this.boxRecordsService = boxRecordsService;
|
||||
this.ornamentsMapper = ornamentsMapper;
|
||||
this.ornamentsLevelService = ornamentsLevelService;
|
||||
this.apiCompoundMapper = apiCompoundMapper;
|
||||
}
|
||||
|
||||
@Override
|
||||
public R<UserPackSackDataVO> compound(List<Long> packSackIds, TtUser ttUser) {
|
||||
List<TtBoxRecords> boxRecordsList = userPackSackService.packSackHandle(packSackIds, ttUser, 3);
|
||||
if (ObjectUtils.isEmpty(boxRecordsList)) return R.fail("请选择饰品后再进行合成!");
|
||||
List<Long> ornamentsIds = boxRecordsList.stream().map(TtBoxRecords::getOrnamentId).collect(Collectors.toList());
|
||||
List<Long> websitePropertyIds = websitePropertyService.list().stream().map(WebsitePropertyDataVO::getId).collect(Collectors.toList());
|
||||
websitePropertyIds.retainAll(ornamentsIds);
|
||||
if (!websitePropertyIds.isEmpty()) return R.fail("选择的饰品中存在网站专属道具,请重新选择!");
|
||||
String maxCompoundNumStr = configService.selectConfigByKey("maxCompoundNum");
|
||||
int maxCompoundNum = Integer.parseInt(maxCompoundNumStr);
|
||||
if (boxRecordsList.size() > maxCompoundNum) return R.fail("最多选择" + maxCompoundNum + "个饰品!");
|
||||
BigDecimal compoundBeanTotal = boxRecordsList.stream().map(TtBoxRecords::getOrnamentsPrice).reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||
String compoundMinPriceStr = configService.selectConfigByKey("compoundMinPrice"); // 获取配置中的汰换最低价
|
||||
BigDecimal compoundMinPrice = new BigDecimal(compoundMinPriceStr);
|
||||
if (compoundBeanTotal.compareTo(compoundMinPrice) < 0)
|
||||
return R.fail("选择的饰品总价必须大于" + compoundMinPrice + "游戏币才可以汰换哦!");
|
||||
Optional<BigDecimal> maxPriceOptional = boxRecordsList.stream().map(TtBoxRecords::getOrnamentsPrice).max(Comparator.naturalOrder());
|
||||
if (!maxPriceOptional.isPresent()) return null;
|
||||
try {
|
||||
String compoundMinPremiumRateStr = configService.selectConfigByKey("compoundMinPremiumRate");
|
||||
BigDecimal minPremiumRatePrice = new BigDecimal(compoundMinPremiumRateStr).divide(new BigDecimal(100), 2, RoundingMode.HALF_UP)
|
||||
.multiply(maxPriceOptional.get());
|
||||
String compoundMaxPremiumRateStr = configService.selectConfigByKey("compoundMaxPremiumRate");
|
||||
BigDecimal maxPremiumRatePrice = new BigDecimal(compoundMaxPremiumRateStr).divide(new BigDecimal(100), 2, RoundingMode.HALF_UP)
|
||||
.multiply(compoundBeanTotal);
|
||||
BigDecimal minPrice = maxPriceOptional.get().subtract(minPremiumRatePrice);
|
||||
BigDecimal maxPrice = compoundBeanTotal.subtract(maxPremiumRatePrice);
|
||||
List<TtOrnament> ornamentsList = new LambdaQueryChainWrapper<>(ornamentsMapper).in(TtOrnament::getType, 2, 3, 4, 5)
|
||||
.between(TtOrnament::getUsePrice, minPrice, maxPrice).list();
|
||||
if (StringUtils.isNull(ornamentsList) || ornamentsList.isEmpty())
|
||||
return R.fail("汰换失败,饰品池中未筛选出符合您价格区间的饰品!");
|
||||
int randomIndex = RandomUtils.getRandomIndex(ornamentsList.size());
|
||||
TtOrnament ttOrnament = ornamentsList.get(randomIndex);
|
||||
List<Integer> levelIds = ornamentsLevelService.list().stream().map(TtOrnamentsLevel::getId).collect(Collectors.toList());
|
||||
Integer ornamentsLevelId = levelIds.get(RandomUtils.getRandomIndex(levelIds.size()));
|
||||
boxRecordsService.updateBatchById(boxRecordsList, 1);
|
||||
TtBoxRecords boxRecords = TtBoxRecords.builder().build();
|
||||
boxRecords.setUserId(ttUser.getUserId());
|
||||
boxRecords.setOrnamentId(ttOrnament.getId());
|
||||
boxRecords.setOrnamentsPrice(ttOrnament.getUsePrice());
|
||||
boxRecords.setOrnamentsLevelId(ornamentsLevelId);
|
||||
boxRecords.setStatus(TtboxRecordStatus.IN_PACKSACK_ON.getCode());
|
||||
boxRecords.setCreateTime(new Date());
|
||||
boxRecords.setSource(MALL_EXCHANGE.getCode()); //// TODO: 2024/4/1 类型不对
|
||||
boxRecords.setHolderUserId(ttUser.getUserId());
|
||||
boxRecordsService.save(boxRecords);
|
||||
UserPackSackDataVO compoundData = apiCompoundMapper.selectCompoundDataById(boxRecords.getId());
|
||||
return R.ok(compoundData);
|
||||
} catch (Exception e) {
|
||||
return R.fail("数据异常!");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<UserPackSackDataVO> getUserCompoundRecord(Integer userId) {
|
||||
return apiCompoundMapper.selectCompoundRecordByUserId(userId);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,555 @@
|
||||
package com.ruoyi.playingmethod.service.impl;
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.hutool.core.map.MapUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import com.ruoyi.admin.mapper.TtBoxMapper;
|
||||
import com.ruoyi.admin.mapper.TtExponentMapper;
|
||||
import com.ruoyi.admin.mapper.TtExponentUserBoxMapper;
|
||||
import com.ruoyi.admin.mapper.TtExponentUserMapper;
|
||||
import com.ruoyi.admin.service.TtBoxRecordsService;
|
||||
import com.ruoyi.admin.service.TtBoxService;
|
||||
import com.ruoyi.admin.service.TtUserService;
|
||||
import com.ruoyi.admin.util.core.fight.LotteryMachine;
|
||||
import com.ruoyi.common.core.domain.R;
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
import com.ruoyi.domain.common.constant.TtAccountRecordSource;
|
||||
import com.ruoyi.domain.common.constant.TtAccountRecordType;
|
||||
import com.ruoyi.domain.common.constant.TtboxRecordSource;
|
||||
import com.ruoyi.domain.dto.exponent.*;
|
||||
import com.ruoyi.domain.entity.TtBoxRecords;
|
||||
import com.ruoyi.domain.entity.TtUserBlendErcash;
|
||||
import com.ruoyi.domain.entity.exponent.TtExponent;
|
||||
import com.ruoyi.domain.entity.exponent.TtExponentUser;
|
||||
import com.ruoyi.domain.entity.exponent.TtExponentUserBox;
|
||||
import com.ruoyi.domain.entity.sys.TtUser;
|
||||
import com.ruoyi.domain.other.TtBox;
|
||||
import com.ruoyi.domain.other.TtBoxA;
|
||||
import com.ruoyi.domain.other.TtOrnamentsA;
|
||||
import com.ruoyi.domain.vo.OpenBoxVO;
|
||||
import com.ruoyi.playingmethod.mapper.ApiBindBoxMapper;
|
||||
import com.ruoyi.playingmethod.mapper.ApiTtUserBlendErcashMapper;
|
||||
import com.ruoyi.playingmethod.service.ApiExponentService;
|
||||
import com.ruoyi.playingmethod.utils.customException.OrnamentNullException;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.apache.commons.collections4.MapUtils;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.sql.Timestamp;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.*;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static com.ruoyi.domain.common.constant.TtboxRecordStatus.IN_PACKSACK_ON;
|
||||
|
||||
@Service
|
||||
@Slf4j
|
||||
public class ApiExponentServiceImpl implements ApiExponentService {
|
||||
|
||||
@Autowired
|
||||
private TtExponentMapper ttExponentMapper;
|
||||
|
||||
@Autowired
|
||||
private TtExponentUserMapper ttExponentUserMapper;
|
||||
|
||||
@Autowired
|
||||
private TtBoxService boxService;
|
||||
|
||||
@Autowired
|
||||
private TtUserService userService;
|
||||
|
||||
@Autowired
|
||||
private LotteryMachine lotteryMachine;
|
||||
|
||||
@Autowired
|
||||
private ApiBindBoxMapper bindBoxMapper;
|
||||
|
||||
@Autowired
|
||||
private TtBoxRecordsService boxRecordsService;
|
||||
|
||||
@Autowired
|
||||
private ApiTtUserBlendErcashMapper apiTtUserBlendErcashMapper;
|
||||
|
||||
@Autowired
|
||||
private TtBoxMapper ttBoxMapper;
|
||||
|
||||
@Autowired
|
||||
private TtExponentUserBoxMapper ttExponentUserBoxMapper;
|
||||
|
||||
@Override
|
||||
public R join(TtUser ttUser, ExponentJoinParam param) {
|
||||
if (param == null || param.getId() == null || param.getBoxId() == null || param.getForward() == null) {
|
||||
return R.fail("参数不合法");
|
||||
}
|
||||
TtBox ttBox = boxService.getById(param.getBoxId());
|
||||
if (ttBox == null) {
|
||||
return R.fail("宝箱参数不合法");
|
||||
}
|
||||
// 同步扣款
|
||||
R<Map<String, BigDecimal>> mapR = upgradeAccounting(ttBox.getPrice(), ttUser);
|
||||
if (!mapR.getCode().equals(200)) {
|
||||
return mapR;
|
||||
}
|
||||
TtExponentUser exponentUser = new TtExponentUser();
|
||||
exponentUser.setExponentId(param.getId());
|
||||
exponentUser.setBoxId(param.getBoxId());
|
||||
exponentUser.setUserId(ttUser.getUserId());
|
||||
exponentUser.setPrice(ttBox.getPrice());
|
||||
exponentUser.setForward(param.getForward());
|
||||
exponentUser.setStatus(0);
|
||||
exponentUser.setBoxRecordId(0L);
|
||||
exponentUser.setCreateTime(new Date());
|
||||
exponentUser.setUpdateTime(new Date());
|
||||
ttExponentUserMapper.insert(exponentUser);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
// 扣款
|
||||
public R<Map<String, BigDecimal>> upgradeAccounting(BigDecimal consumption, TtUser player) {
|
||||
// 再次检查余额
|
||||
player = userService.getById(player.getUserId());
|
||||
if (player.getAccountAmount() == null || player.getAccountAmount().compareTo(consumption) < 0) {
|
||||
return R.fail("余额不足");
|
||||
}
|
||||
LambdaUpdateWrapper<TtUser> userUpdate = new LambdaUpdateWrapper<>();
|
||||
userUpdate.eq(TtUser::getUserId, player.getUserId());
|
||||
Map<String, BigDecimal> map;
|
||||
if (player.getAccountAmount().compareTo(consumption) >= 0) {
|
||||
userUpdate.set(TtUser::getAccountAmount, player.getAccountAmount().subtract(consumption));
|
||||
map = MapUtil.builder("Amount", consumption).map();
|
||||
} else {
|
||||
BigDecimal subtract = consumption.subtract(player.getAccountAmount());
|
||||
userUpdate
|
||||
.set(TtUser::getAccountAmount, 0)
|
||||
.set(TtUser::getAccountCredits, player.getAccountCredits().subtract(subtract));
|
||||
map = MapUtil.builder("Amount", player.getAccountAmount()).map();
|
||||
map.put("Credits", subtract);
|
||||
}
|
||||
userService.update(userUpdate);
|
||||
|
||||
// 综合消费日志
|
||||
TtUserBlendErcash blendErcash = TtUserBlendErcash.builder()
|
||||
.userId(player.getUserId())
|
||||
.amount(null)
|
||||
.finalAmount(null)
|
||||
.credits(null)
|
||||
.finalCredits(null)
|
||||
.total(consumption.negate()) // 收支合计
|
||||
.type(TtAccountRecordType.OUTPUT.getCode())
|
||||
.source(TtAccountRecordSource.EXPONENT_GAME_TYPE_01.getCode())
|
||||
.remark(TtAccountRecordSource.EXPONENT_GAME_TYPE_01.getMsg())
|
||||
.createTime(new Timestamp(System.currentTimeMillis()))
|
||||
.updateTime(new Timestamp(System.currentTimeMillis()))
|
||||
.build();
|
||||
|
||||
apiTtUserBlendErcashMapper.insert(blendErcash);
|
||||
|
||||
return R.ok(map);
|
||||
}
|
||||
|
||||
@Override
|
||||
public R box(TtUser ttUser, Integer id) {
|
||||
List<TtBoxA> boxList = bindBoxMapper.getBoxList(null, null, "5");
|
||||
if (boxList.isEmpty()) {
|
||||
return R.ok(new ArrayList<>(), "没有匹配的数据。");
|
||||
}
|
||||
List<ExponentBoxVo> boxVos = new ArrayList<>();
|
||||
List<Integer> boxIds = new ArrayList<>();
|
||||
for (TtBoxA ttBoxA : boxList) {
|
||||
ExponentBoxVo boxVo = new ExponentBoxVo();
|
||||
BeanUtils.copyProperties(ttBoxA, boxVo);
|
||||
boxVo.setBoxId(ttBoxA.getBoxId());
|
||||
boxIds.add(ttBoxA.getBoxId());
|
||||
boxVos.add(boxVo);
|
||||
}
|
||||
|
||||
// 查看当前登录者是否购买本期指数
|
||||
LambdaQueryWrapper<TtExponentUser> wrapper1 = Wrappers.lambdaQuery();
|
||||
wrapper1.in(TtExponentUser::getBoxId, boxIds);
|
||||
wrapper1.eq(TtExponentUser::getExponentId, id);
|
||||
wrapper1.eq(TtExponentUser::getUserId, ttUser.getUserId());
|
||||
List<TtExponentUser> exponentUsers = ttExponentUserMapper.selectList(wrapper1);
|
||||
Map<Integer, Integer> boxIdToUp = new HashMap<>();
|
||||
Map<Integer, Integer> boxIdToDown = new HashMap<>();
|
||||
if (CollectionUtils.isNotEmpty(exponentUsers)) {
|
||||
for (TtExponentUser user : exponentUsers) {
|
||||
if (user == null) {
|
||||
continue;
|
||||
}
|
||||
if (Objects.equals(user.getForward(), 1)) {
|
||||
int num = boxIdToUp.getOrDefault(user.getBoxId(), 0);
|
||||
boxIdToUp.put(user.getBoxId(), num + 1);
|
||||
}
|
||||
if (Objects.equals(user.getForward(), 2)) {
|
||||
int num = boxIdToDown.getOrDefault(user.getBoxId(), 0);
|
||||
boxIdToDown.put(user.getBoxId(), num + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (ExponentBoxVo vo : boxVos) {
|
||||
vo.setBuy_forward_up(boxIdToUp.getOrDefault(vo.getBoxId(), 0));
|
||||
vo.setBuy_forward_down(boxIdToDown.getOrDefault(vo.getBoxId(), 0));
|
||||
}
|
||||
return R.ok(boxVos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public R recenttenperiod() {
|
||||
LambdaQueryWrapper<TtExponent> wrapper = Wrappers.lambdaQuery();
|
||||
wrapper.orderByDesc(TtExponent::getId);
|
||||
wrapper.last("limit 10");
|
||||
List<TtExponent> db = ttExponentMapper.selectList(wrapper);
|
||||
return R.ok(db);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@Override
|
||||
public R info(TtUser ttUser) {
|
||||
LambdaQueryWrapper<TtExponent> wrapper = Wrappers.lambdaQuery();
|
||||
wrapper.orderByDesc(TtExponent::getId);
|
||||
wrapper.last("limit 1");
|
||||
TtExponent db = ttExponentMapper.selectOne(wrapper);
|
||||
if (db == null) {
|
||||
return R.fail("指数信息不存在");
|
||||
}
|
||||
ExponentInfoVo vo = new ExponentInfoVo();
|
||||
Integer id = db.getId() + 1;
|
||||
vo.setId(id);
|
||||
vo.setExponent(0);
|
||||
// 创建日期格式化对象,指定日期格式
|
||||
SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMdd");
|
||||
// 获取Calendar实例
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
// 设置时间为今天凌晨
|
||||
calendar.set(Calendar.HOUR_OF_DAY, 0);
|
||||
calendar.set(Calendar.MINUTE, 0);
|
||||
calendar.set(Calendar.SECOND, 0);
|
||||
calendar.set(Calendar.MILLISECOND, 0);
|
||||
// 获取今天凌晨时间
|
||||
Date todayMidnight = calendar.getTime();
|
||||
String period = "";
|
||||
if (db.getCreateTime().after(todayMidnight)) {
|
||||
period = formatter.format(new Date()) + String.format("%04d", (db.getNumber() + 1));
|
||||
} else {
|
||||
period = formatter.format(new Date()) + "0001";
|
||||
}
|
||||
vo.setPeriod(period);
|
||||
int createTime = (int) (db.getCreateTime().getTime() / 1000);
|
||||
vo.setEnd_time(createTime + 60);
|
||||
vo.setPoints("");
|
||||
vo.setState(0);
|
||||
vo.setNumber(db.getNumber() + 1);
|
||||
vo.setForward(0);
|
||||
vo.setCreatetime(createTime + 30);
|
||||
vo.setUpdatetime(createTime + 30);
|
||||
int nowTime = (int) (System.currentTimeMillis() / 1000);
|
||||
vo.setTimer(vo.getCreatetime() - nowTime);
|
||||
|
||||
// 查看当前登录者是否购买本期指数
|
||||
LambdaQueryWrapper<TtExponentUser> wrapper2 = Wrappers.lambdaQuery();
|
||||
wrapper2.eq(TtExponentUser::getExponentId, id);
|
||||
wrapper2.eq(TtExponentUser::getUserId, ttUser.getUserId());
|
||||
List<TtExponentUser> exponentUsers2 = ttExponentUserMapper.selectList(wrapper2);
|
||||
// 若购买
|
||||
if (CollectionUtils.isNotEmpty(exponentUsers2)) {
|
||||
vo.setBuy(exponentUsers2.size());
|
||||
BigDecimal up = BigDecimal.ZERO;
|
||||
BigDecimal down = BigDecimal.ZERO;
|
||||
for (TtExponentUser exponentUser : exponentUsers2) {
|
||||
if (exponentUser == null) {
|
||||
continue;
|
||||
}
|
||||
if (Objects.equals(exponentUser.getForward(), 1)) {
|
||||
up = up.add(exponentUser.getPrice());
|
||||
}
|
||||
if (Objects.equals(exponentUser.getForward(), 2)) {
|
||||
down = down.add(exponentUser.getPrice());
|
||||
}
|
||||
}
|
||||
vo.setBuy_forward_up(up);
|
||||
vo.setBuy_forward_down(down);
|
||||
}
|
||||
|
||||
ExponentInfoVo last = new ExponentInfoVo();
|
||||
last.setId(db.getId());
|
||||
last.setExponent(db.getExponent());
|
||||
period = formatter.format(db.getCreateTime()) + String.format("%04d", db.getNumber());
|
||||
last.setPeriod(period);
|
||||
int lastCreateTime = (int) (db.getCreateTime().getTime() / 1000);
|
||||
last.setEnd_time(lastCreateTime + 30);
|
||||
last.setPoints(db.getPoints());
|
||||
last.setState(2);
|
||||
last.setNumber(db.getNumber());
|
||||
last.setForward(db.getForward());
|
||||
last.setCreatetime(lastCreateTime);
|
||||
last.setUpdatetime(lastCreateTime);
|
||||
|
||||
vo.setLast(last);
|
||||
|
||||
// 查看当前登录者是否购买本期指数
|
||||
LambdaQueryWrapper<TtExponentUser> wrapper1 = Wrappers.lambdaQuery();
|
||||
wrapper1.eq(TtExponentUser::getExponentId, db.getId());
|
||||
wrapper1.eq(TtExponentUser::getUserId, ttUser.getUserId());
|
||||
List<TtExponentUser> exponentUsers = ttExponentUserMapper.selectList(wrapper1);
|
||||
ExponentJieguoVo jieguo = new ExponentJieguoVo();
|
||||
jieguo.setPeriod(period);
|
||||
jieguo.setExponent(db.getExponent());
|
||||
jieguo.setForward(db.getForward());
|
||||
// 若购买
|
||||
if (CollectionUtils.isNotEmpty(exponentUsers)) {
|
||||
jieguo.setSkinarr(openExponent(db.getForward(), ttUser, exponentUsers));
|
||||
jieguo.setBuy(exponentUsers.size());
|
||||
BigDecimal up = BigDecimal.ZERO;
|
||||
BigDecimal down = BigDecimal.ZERO;
|
||||
BigDecimal price = BigDecimal.ZERO;
|
||||
for (TtExponentUser exponentUser : exponentUsers) {
|
||||
if (exponentUser == null) {
|
||||
continue;
|
||||
}
|
||||
price = price.add(exponentUser.getPrice());
|
||||
if (Objects.equals(exponentUser.getForward(), 1)) {
|
||||
up = up.add(exponentUser.getPrice());
|
||||
}
|
||||
if (Objects.equals(exponentUser.getForward(), 2)) {
|
||||
down = down.add(exponentUser.getPrice());
|
||||
}
|
||||
}
|
||||
jieguo.setBuy_money(price);
|
||||
jieguo.setBuy_forward_up(up);
|
||||
jieguo.setBuy_forward_down(down);
|
||||
}
|
||||
vo.setJieguo(jieguo);
|
||||
return R.ok(vo);
|
||||
}
|
||||
|
||||
/**
|
||||
* 指数开箱
|
||||
*/
|
||||
private List<ExponentSkinarrVo> openExponent(int forward, TtUser ttUser, List<TtExponentUser> exponentUsers) {
|
||||
Map<Integer, Integer> boxIdToNum = new HashMap<>();
|
||||
// 判断箱子是否已判定结果
|
||||
Map<Integer, Boolean> boxIdToOpen = new HashMap<>();
|
||||
for (TtExponentUser user : exponentUsers) {
|
||||
if (user == null) {
|
||||
continue;
|
||||
}
|
||||
// 等于1,则代表指数结果已判定结果
|
||||
if (Objects.equals(user.getStatus(), 1)) {
|
||||
boxIdToOpen.put(user.getBoxId(), true);
|
||||
int num = boxIdToNum.getOrDefault(user.getBoxId(), 0);
|
||||
boxIdToNum.put(user.getBoxId(), num + 1);
|
||||
continue;
|
||||
}
|
||||
// 等于2,则代表指数结果已判定结果
|
||||
if (Objects.equals(user.getStatus(), 2)) {
|
||||
boxIdToOpen.put(user.getBoxId(), true);
|
||||
boxIdToNum.put(user.getBoxId(), 0);
|
||||
continue;
|
||||
}
|
||||
if (Objects.equals(user.getForward(), forward)) {
|
||||
int num = boxIdToNum.getOrDefault(user.getBoxId(), 0);
|
||||
boxIdToNum.put(user.getBoxId(), num + 1);
|
||||
user.setStatus(1);
|
||||
} else {
|
||||
user.setStatus(2);
|
||||
}
|
||||
user.setUpdateTime(new Date());
|
||||
ttExponentUserMapper.updateById(user);
|
||||
}
|
||||
if (MapUtils.isEmpty(boxIdToNum)) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
// 查询箱子信息
|
||||
LambdaQueryWrapper<TtBox> wrapper = Wrappers.lambdaQuery();
|
||||
wrapper.in(TtBox::getBoxId, boxIdToNum.keySet());
|
||||
List<TtBox> ttBoxes = ttBoxMapper.selectList(wrapper);
|
||||
Map<Integer, TtBox> ttBoxMap = ttBoxes.stream().collect(Collectors.toMap(TtBox::getBoxId, Function.identity()));
|
||||
|
||||
// 查询该用户已拥有的箱子信息
|
||||
LambdaQueryWrapper<TtExponentUserBox> wrapper1 = Wrappers.lambdaQuery();
|
||||
wrapper1.in(TtExponentUserBox::getBoxId, boxIdToNum.keySet());
|
||||
wrapper1.eq(TtExponentUserBox::getUserId, ttUser.getUserId());
|
||||
List<TtExponentUserBox> userBoxes = ttExponentUserBoxMapper.selectList(wrapper1);
|
||||
Map<Integer, TtExponentUserBox> userBoxeMap = userBoxes.stream().collect(Collectors.toMap(TtExponentUserBox::getBoxId, Function.identity()));
|
||||
|
||||
List<ExponentSkinarrVo> vos = new ArrayList<>();
|
||||
for (Map.Entry<Integer, Integer> entry : boxIdToNum.entrySet()) {
|
||||
ExponentSkinarrVo vo = new ExponentSkinarrVo();
|
||||
vo.setId(entry.getKey());
|
||||
vo.setCount(entry.getValue());
|
||||
TtBox ttBox = ttBoxMap.get(entry.getKey());
|
||||
if (ttBox != null) {
|
||||
vo.setImage(ttBox.getBoxImg01());
|
||||
vo.setImage2(ttBox.getBoxImg02());
|
||||
}
|
||||
vos.add(vo);
|
||||
// 若指数没有判定过,则进行放入箱子数量
|
||||
if (!boxIdToOpen.getOrDefault(entry.getKey(), false)) {
|
||||
TtExponentUserBox userBox = userBoxeMap.get(entry.getKey());
|
||||
if (userBox == null) {
|
||||
userBox = new TtExponentUserBox();
|
||||
userBox.setBoxId(entry.getKey());
|
||||
userBox.setUserId(ttUser.getUserId());
|
||||
userBox.setNumber(entry.getValue());
|
||||
userBox.setCreateTime(new Date());
|
||||
userBox.setUpdateTime(new Date());
|
||||
ttExponentUserBoxMapper.insert(userBox);
|
||||
} else {
|
||||
userBox.setNumber(userBox.getNumber() + entry.getValue());
|
||||
userBox.setUpdateTime(new Date());
|
||||
ttExponentUserBoxMapper.updateById(userBox);
|
||||
}
|
||||
}
|
||||
}
|
||||
return vos;
|
||||
}
|
||||
|
||||
@Override
|
||||
public R records(TtUser ttUser) {
|
||||
List<ExponentOpenBoxVo> vos = ttExponentMapper.exponentOpenBox(ttUser.getUserId());
|
||||
if (CollectionUtils.isEmpty(vos)) {
|
||||
return R.ok(new ArrayList<>());
|
||||
}
|
||||
List<Integer> boxIds = new ArrayList<>();
|
||||
for (ExponentOpenBoxVo vo : vos) {
|
||||
boxIds.add(vo.getBoxId());
|
||||
if (vo.getFailed() != null && vo.getFailed() > 0) {
|
||||
vo.setState(2);
|
||||
}
|
||||
if (vo.getSuccess() != null && vo.getSuccess() > 0) {
|
||||
vo.setState(1);
|
||||
}
|
||||
}
|
||||
|
||||
// 查询箱子信息
|
||||
LambdaQueryWrapper<TtBox> wrapper = Wrappers.lambdaQuery();
|
||||
wrapper.in(TtBox::getBoxId, boxIds);
|
||||
List<TtBox> ttBoxes = ttBoxMapper.selectList(wrapper);
|
||||
Map<Integer, TtBox> ttBoxMap = ttBoxes.stream().collect(Collectors.toMap(TtBox::getBoxId, Function.identity()));
|
||||
for (ExponentOpenBoxVo vo : vos) {
|
||||
TtBox ttBox = ttBoxMap.get(vo.getBoxId());
|
||||
if (ttBox != null) {
|
||||
vo.setImage(ttBox.getBoxImg01());
|
||||
vo.setImage2(ttBox.getBoxImg02());
|
||||
}
|
||||
}
|
||||
return R.ok(vos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public R mybox(TtUser ttUser) {
|
||||
// 查询该用户已拥有的箱子信息
|
||||
LambdaQueryWrapper<TtExponentUserBox> wrapper1 = Wrappers.lambdaQuery();
|
||||
wrapper1.eq(TtExponentUserBox::getUserId, ttUser.getUserId());
|
||||
List<TtExponentUserBox> userBoxes = ttExponentUserBoxMapper.selectList(wrapper1);
|
||||
if (CollectionUtils.isEmpty(userBoxes)) {
|
||||
return R.ok(new ArrayList<>());
|
||||
}
|
||||
List<ExponentSkinarrVo> vos = new ArrayList<>();
|
||||
List<Integer> boxIds = new ArrayList<>();
|
||||
for (TtExponentUserBox userBox : userBoxes) {
|
||||
ExponentSkinarrVo vo = new ExponentSkinarrVo();
|
||||
vo.setId(userBox.getBoxId());
|
||||
boxIds.add(userBox.getBoxId());
|
||||
vo.setCount(userBox.getNumber());
|
||||
vos.add(vo);
|
||||
}
|
||||
// 查询箱子信息
|
||||
LambdaQueryWrapper<TtBox> wrapper = Wrappers.lambdaQuery();
|
||||
wrapper.in(TtBox::getBoxId, boxIds);
|
||||
List<TtBox> ttBoxes = ttBoxMapper.selectList(wrapper);
|
||||
Map<Integer, TtBox> ttBoxMap = ttBoxes.stream().collect(Collectors.toMap(TtBox::getBoxId, Function.identity()));
|
||||
for (ExponentSkinarrVo vo : vos) {
|
||||
TtBox ttBox = ttBoxMap.get(vo.getId());
|
||||
if (ttBox != null) {
|
||||
vo.setImage(ttBox.getBoxImg01());
|
||||
vo.setImage2(ttBox.getBoxImg02());
|
||||
}
|
||||
}
|
||||
return R.ok(vos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public R openbox(TtUser user, TtBox box, Integer num) {
|
||||
// 查询该用户已拥有的箱子信息
|
||||
LambdaQueryWrapper<TtExponentUserBox> wrapper1 = Wrappers.lambdaQuery();
|
||||
wrapper1.eq(TtExponentUserBox::getUserId, user.getUserId());
|
||||
wrapper1.eq(TtExponentUserBox::getBoxId, box.getBoxId());
|
||||
List<TtExponentUserBox> userBoxes = ttExponentUserBoxMapper.selectList(wrapper1);
|
||||
if (CollectionUtils.isEmpty(userBoxes) || userBoxes.get(0) == null || userBoxes.get(0).getNumber() < num) {
|
||||
return R.ok(new ArrayList<>());
|
||||
}
|
||||
TtExponentUserBox userBox = userBoxes.get(0);
|
||||
// 抽奖
|
||||
List<TtBoxRecords> boxRecords = new ArrayList<>();
|
||||
Map<Long, TtOrnamentsA> boxToOrnament = new HashMap<>();
|
||||
for (int i = 0; i < num; i++) {
|
||||
String ornamentId = lotteryMachine.singleLottery(user, box);
|
||||
if (StringUtils.isBlank(ornamentId)) {
|
||||
throw new OrnamentNullException("单次抽奖无结果#"+box.getBoxId()+"#"+ornamentId);
|
||||
//return R.fail("系统繁忙,请稍后重试。");
|
||||
}
|
||||
// 宝箱详细信息
|
||||
TtOrnamentsA ornamentsData = bindBoxMapper.ornamentsInfo(box.getBoxId(), ornamentId);
|
||||
if (ObjectUtil.isEmpty(ornamentsData)){
|
||||
throw new OrnamentNullException("没有符合条件的宝箱信息#"+box.getBoxId()+"#"+ornamentId);
|
||||
}
|
||||
// 抽奖成功,构建开箱记录数据
|
||||
TtBoxRecords boxRecord = TtBoxRecords.builder()
|
||||
.userId(user.getUserId())
|
||||
|
||||
.boxId(box.getBoxId())
|
||||
.boxName(box.getBoxName())
|
||||
.boxPrice(box.getPrice())
|
||||
|
||||
.ornamentId(Long.valueOf(ornamentId))
|
||||
// .marketHashName(ornamentsData.)
|
||||
.ornamentName(ObjectUtil.isNotEmpty(ornamentsData.getName()) ? ornamentsData.getName() : ObjectUtil.isNotEmpty(ornamentsData.getShortName()) ? ornamentsData.getShortName() : "无名称")
|
||||
.imageUrl(ornamentsData.getImageUrl())
|
||||
.ornamentsPrice(ornamentsData.getUsePrice())
|
||||
.ornamentsLevelId(ornamentsData.getOrnamentsLevelId())
|
||||
.ornamentLevelImg(ornamentsData.getLevelImg())
|
||||
.holderUserId(user.getUserId())
|
||||
.source(TtboxRecordSource.EXPONENT_BOX.getCode())
|
||||
.status(IN_PACKSACK_ON.getCode())
|
||||
|
||||
.createTime(new Timestamp(System.currentTimeMillis()))
|
||||
.updateTime(new Timestamp(System.currentTimeMillis()))
|
||||
.build();
|
||||
boxRecords.add(boxRecord);
|
||||
boxToOrnament.put(Long.valueOf(ornamentId), ornamentsData);
|
||||
}
|
||||
// 同步保存游戏记录
|
||||
boxRecordsService.saveBatch(boxRecords);
|
||||
// 返回值
|
||||
List<OpenBoxVO> openBoxVOs = boxRecords.stream().map(item -> {
|
||||
OpenBoxVO openBoxVO = new OpenBoxVO();
|
||||
BeanUtil.copyProperties(item, openBoxVO);
|
||||
TtOrnamentsA ornamentsData = boxToOrnament.get(item.getOrnamentId());
|
||||
if (ornamentsData != null) {
|
||||
openBoxVO.setShortName(ornamentsData.getShortName());
|
||||
openBoxVO.setExteriorName(ornamentsData.getExteriorName());
|
||||
}
|
||||
openBoxVO.setUsePrice(openBoxVO.getOrnamentsPrice());
|
||||
openBoxVO.setLevelImg(item.getOrnamentLevelImg());
|
||||
return openBoxVO;
|
||||
}).collect(Collectors.toList());
|
||||
|
||||
userBox.setNumber(userBox.getNumber() - num);
|
||||
userBox.setUpdateTime(new Date());
|
||||
ttExponentUserBoxMapper.updateById(userBox);
|
||||
|
||||
return R.ok(openBoxVOs);
|
||||
}
|
||||
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,11 @@
|
||||
package com.ruoyi.playingmethod.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.ruoyi.admin.mapper.TtFightUserMapper;
|
||||
import com.ruoyi.domain.other.TtFightUser;
|
||||
import com.ruoyi.playingmethod.service.ApiFightUserService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class ApiFightUserServiceImpl extends ServiceImpl<TtFightUserMapper, TtFightUser> implements ApiFightUserService {
|
||||
}
|
||||
@@ -0,0 +1,489 @@
|
||||
package com.ruoyi.playingmethod.service.impl;
|
||||
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
||||
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
|
||||
import com.ruoyi.admin.config.RedisConstants;
|
||||
import com.ruoyi.admin.mapper.TtBoxRecordsMapper;
|
||||
import com.ruoyi.admin.mapper.TtOrnamentMapper;
|
||||
import com.ruoyi.admin.mapper.TtOrnamentsLevelMapper;
|
||||
import com.ruoyi.admin.mapper.TtUpgradeFailOrnamentsMapper;
|
||||
import com.ruoyi.admin.mapper.TtUpgradeOrnamentsMapper;
|
||||
import com.ruoyi.admin.mapper.TtUpgradeRecordMapper;
|
||||
import com.ruoyi.admin.model.UpdateUserAccountBo;
|
||||
import com.ruoyi.admin.service.TtBoxRecordsService;
|
||||
import com.ruoyi.admin.service.TtUpgradeOrnamentsService;
|
||||
import com.ruoyi.admin.service.TtUpgradeRecordService;
|
||||
import com.ruoyi.admin.service.TtUserService;
|
||||
import com.ruoyi.common.core.domain.R;
|
||||
import com.ruoyi.common.core.redis.RedisCache;
|
||||
import com.ruoyi.common.redis.config.RedisLock;
|
||||
import com.ruoyi.domain.common.constant.LockKey.UpgradeLock;
|
||||
import com.ruoyi.domain.common.constant.TtAccountRecordSource;
|
||||
import com.ruoyi.domain.common.constant.TtboxRecordSource;
|
||||
import com.ruoyi.domain.common.constant.TtboxRecordStatus;
|
||||
import com.ruoyi.domain.common.constant.UserType;
|
||||
import com.ruoyi.domain.entity.TtBoxRecords;
|
||||
import com.ruoyi.domain.entity.sys.TtUser;
|
||||
import com.ruoyi.domain.other.ApiLuckyUpgradeBody;
|
||||
import com.ruoyi.domain.other.TtUpgradeOrnaments;
|
||||
import com.ruoyi.domain.other.TtUpgradeRecord;
|
||||
import com.ruoyi.domain.other.UpgradeBodyA;
|
||||
import com.ruoyi.domain.vo.ApiLuckyOrnamentsDataVO;
|
||||
import com.ruoyi.domain.vo.upgrade.SimpleOrnamentVO;
|
||||
import com.ruoyi.playingmethod.mapper.ApiLuckyUpgradeMapper;
|
||||
import com.ruoyi.playingmethod.mapper.ApiTtUserBlendErcashMapper;
|
||||
import com.ruoyi.playingmethod.service.ApiLuckyUpgradeService;
|
||||
import com.ruoyi.system.service.ISysConfigService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.amqp.rabbit.core.RabbitTemplate;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
public class ApiLuckyUpgradeServiceImpl implements ApiLuckyUpgradeService {
|
||||
|
||||
@Value("${mkcsgo.upgrade.defaultRequired}")
|
||||
private Integer defaultRequired;
|
||||
|
||||
@Value("${mkcsgo.upgrade.anchorDefaultRequired}")
|
||||
private Integer anchorDefaultRequired;
|
||||
|
||||
@Autowired
|
||||
private Executor customThreadPoolExecutor;
|
||||
|
||||
@Autowired
|
||||
private ApiTtUserBlendErcashMapper apiTtUserBlendErcashMapper;
|
||||
|
||||
private final TtUserService userService;
|
||||
private final ISysConfigService configService;
|
||||
private final ApiLuckyUpgradeMapper apiLuckyUpgradeMapper;
|
||||
private final TtUpgradeOrnamentsMapper upgradeOrnamentsMapper;
|
||||
private final TtUpgradeFailOrnamentsMapper upgradeFailOrnamentsMapper;
|
||||
private final TtUpgradeRecordMapper upgradeRecordMapper;
|
||||
private final TtOrnamentMapper ornamentsMapper;
|
||||
private final TtBoxRecordsMapper boxRecordsMapper;
|
||||
private final TtOrnamentsLevelMapper ornamentsLevelMapper;
|
||||
|
||||
@Autowired
|
||||
private RabbitTemplate rabbitTemplate;
|
||||
|
||||
@Autowired
|
||||
private RedisLock redisLock;
|
||||
|
||||
@Autowired
|
||||
private RedisCache redisCache;
|
||||
|
||||
public ApiLuckyUpgradeServiceImpl(TtUserService userService,
|
||||
ISysConfigService configService,
|
||||
ApiLuckyUpgradeMapper apiLuckyUpgradeMapper,
|
||||
TtUpgradeOrnamentsMapper upgradeOrnamentsMapper,
|
||||
TtUpgradeFailOrnamentsMapper upgradeFailOrnamentsMapper,
|
||||
TtUpgradeRecordMapper upgradeRecordMapper,
|
||||
TtOrnamentMapper ornamentsMapper,
|
||||
TtBoxRecordsMapper boxRecordsMapper,
|
||||
TtOrnamentsLevelMapper ornamentsLevelMapper) {
|
||||
this.userService = userService;
|
||||
this.configService = configService;
|
||||
this.apiLuckyUpgradeMapper = apiLuckyUpgradeMapper;
|
||||
this.upgradeOrnamentsMapper = upgradeOrnamentsMapper;
|
||||
this.upgradeFailOrnamentsMapper = upgradeFailOrnamentsMapper;
|
||||
this.upgradeRecordMapper = upgradeRecordMapper;
|
||||
this.ornamentsMapper = ornamentsMapper;
|
||||
this.boxRecordsMapper = boxRecordsMapper;
|
||||
this.ornamentsLevelMapper = ornamentsLevelMapper;
|
||||
}
|
||||
|
||||
@Autowired
|
||||
private TtUpgradeOrnamentsService ttUpgradeOrnamentsService;
|
||||
|
||||
@Autowired
|
||||
private TtUpgradeOrnamentsMapper ttUpgradeOrnamentsMapper;
|
||||
|
||||
@Autowired
|
||||
private TtBoxRecordsService ttBoxRecordsService;
|
||||
|
||||
@Autowired
|
||||
private TtUpgradeRecordService ttUpgradeRecordService;
|
||||
|
||||
@Override
|
||||
public List<ApiLuckyOrnamentsDataVO> getOrnamentsList(ApiLuckyUpgradeBody apiLuckyUpgradeBody) {
|
||||
apiLuckyUpgradeBody.setType(null);
|
||||
return apiLuckyUpgradeMapper.getOrnamentsList(apiLuckyUpgradeBody);
|
||||
}
|
||||
|
||||
public R upgradeCheck(TtUser player, UpgradeBodyA param) {
|
||||
|
||||
if (player.getAccountAmount() == null || player.getAccountAmount().compareTo(param.getPrice()) <= 0) {
|
||||
return R.fail("余额不足");
|
||||
}
|
||||
|
||||
if (!player.getUserType().equals(UserType.ANCHOR.getCode()) && !player.getUserType().equals(UserType.COMMON_USER.getCode())) {
|
||||
return R.fail("非法的用户类型");
|
||||
}
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public R upgrade(TtUser ttUser, UpgradeBodyA upgradeParam) {
|
||||
|
||||
TtUpgradeOrnaments upgradeOrnament = new LambdaQueryChainWrapper<>(upgradeOrnamentsMapper)
|
||||
.eq(TtUpgradeOrnaments::getId, upgradeParam.getUpgradeOrnamentId())
|
||||
.eq(TtUpgradeOrnaments::getStatus, "0")
|
||||
.one();
|
||||
if (ObjectUtil.isNull(upgradeOrnament)) {
|
||||
return R.fail("该饰品未在幸运升级开放。");
|
||||
}
|
||||
|
||||
// 检查
|
||||
R check = upgradeCheck(ttUser, upgradeParam);
|
||||
if (!check.getCode().equals(200)) return check;
|
||||
|
||||
// lock_key
|
||||
Integer upgradeOrnamentId = upgradeParam.getUpgradeOrnamentId();
|
||||
String userType = ttUser.getUserType();
|
||||
String upgradeLock = UpgradeLock.UPGRADE_LOCK.getLock() + upgradeOrnamentId + ":" + userType;
|
||||
|
||||
// 2 尝试获取锁
|
||||
Boolean lock = false;
|
||||
for (int t = 0; t < 2; t++) {
|
||||
|
||||
lock = redisLock.tryLock(upgradeLock, 2L, 7L, TimeUnit.SECONDS);
|
||||
|
||||
if (!lock) {
|
||||
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!lock) return R.fail("系统繁忙,请稍后重试。");
|
||||
|
||||
// 3 扣款
|
||||
R<Map<String, BigDecimal>> mapR = upgradeAccounting(upgradeParam.getPrice(), ttUser);
|
||||
if (!mapR.getCode().equals(200)) {
|
||||
redisLock.unlock(upgradeLock);
|
||||
return mapR;
|
||||
}
|
||||
|
||||
// 4 计算游戏
|
||||
boolean isVictory;
|
||||
try {
|
||||
|
||||
// 升级核心
|
||||
isVictory = playing(ttUser, upgradeOrnament, upgradeParam);
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return R.fail("系统繁忙,请稍后重试。");
|
||||
} finally {
|
||||
redisLock.unlock(upgradeLock);
|
||||
}
|
||||
|
||||
// 5 同步保存本次结果。
|
||||
TtUpgradeRecord upgradeRecord; // 升级记录
|
||||
List<TtBoxRecords> boxRecords; // 获得物品记录
|
||||
if (isVictory) {
|
||||
|
||||
Long ornamentId = upgradeOrnament.getOrnamentsId();
|
||||
|
||||
// 胜
|
||||
List<SimpleOrnamentVO> prizeList = ornamentsMapper.simpleOrnamentInfo(Arrays.asList(ornamentId));
|
||||
SimpleOrnamentVO ornament = prizeList.get(0);
|
||||
|
||||
// 奖励集合 并统计奖励总价值
|
||||
// List<SimpleOrnamentVO> prizeList = Arrays.asList(ornament);
|
||||
BigDecimal prizeTotal = BigDecimal.ZERO;
|
||||
for (SimpleOrnamentVO vo : prizeList) prizeTotal = prizeTotal.add(vo.getOrnamentPrice());
|
||||
|
||||
// 构造升级记录
|
||||
upgradeRecord = TtUpgradeRecord.builder()
|
||||
.userId(ttUser.getUserId())
|
||||
.userType(ttUser.getUserType())
|
||||
.nickName(ObjectUtil.isNotEmpty(ttUser.getNickName()) ? ttUser.getNickName() : ttUser.getUserName())
|
||||
.isVictory(isVictory)
|
||||
|
||||
.amountConsumed(upgradeParam.getPrice())
|
||||
.probability(upgradeParam.getProbability())
|
||||
|
||||
.targetUpgradeId(upgradeOrnament.getId())
|
||||
.targetOrnamentId(ornamentId)
|
||||
.targetOrnamentPrice(ornament.getOrnamentPrice())
|
||||
|
||||
.gainOrnamentList(JSONUtil.toJsonStr(prizeList))
|
||||
.gainOrnamentsPrice(prizeTotal)
|
||||
|
||||
.openTime(new Date())
|
||||
.build();
|
||||
|
||||
// 构造获得物品记录
|
||||
boxRecords = Arrays.asList(TtBoxRecords.builder()
|
||||
.source(TtboxRecordSource.UPGRADE.getCode())
|
||||
.ornamentId(ornamentId)
|
||||
.ornamentName(ornament.getOrnamentName())
|
||||
.userId(ttUser.getUserId())
|
||||
.holderUserId(ttUser.getUserId())
|
||||
.imageUrl(ornament.getOrnamentImgUrl())
|
||||
.ornamentsPrice(ornament.getOrnamentPrice())
|
||||
.status(TtboxRecordStatus.IN_PACKSACK_ON.getCode())
|
||||
.marketHashName(ornament.getOrnamentHashName())
|
||||
.createTime(new Date())
|
||||
.updateTime(new Date())
|
||||
.build());
|
||||
|
||||
} else {
|
||||
|
||||
// 负
|
||||
// 奖励集合 并统计奖励总价值
|
||||
List<SimpleOrnamentVO> failPrize = upgradeFailOrnamentsMapper.ornamentInfoByUpgradeId(upgradeOrnament.getId());
|
||||
|
||||
BigDecimal prizeTotal = BigDecimal.ZERO;
|
||||
if (!failPrize.isEmpty()) {
|
||||
for (SimpleOrnamentVO item : failPrize) {
|
||||
prizeTotal = prizeTotal.add(item.getOrnamentPrice().multiply(new BigDecimal(item.getOrnamentNumber())));
|
||||
}
|
||||
}
|
||||
|
||||
// 构造升级记录
|
||||
upgradeRecord = TtUpgradeRecord.builder()
|
||||
.userId(ttUser.getUserId())
|
||||
.userType(ttUser.getUserType())
|
||||
.nickName(ObjectUtil.isNotEmpty(ttUser.getNickName()) ? ttUser.getNickName() : ttUser.getUserName())
|
||||
|
||||
.amountConsumed(upgradeParam.getPrice())
|
||||
.probability(upgradeParam.getProbability())
|
||||
|
||||
.isVictory(isVictory)
|
||||
|
||||
.targetUpgradeId(upgradeOrnament.getId())
|
||||
.targetOrnamentId(upgradeOrnament.getOrnamentsId())
|
||||
.targetOrnamentPrice(upgradeOrnament.getOrnamentPrice())
|
||||
|
||||
.gainOrnamentList(failPrize.isEmpty() ? "" : JSONUtil.toJsonStr(failPrize))
|
||||
.gainOrnamentsPrice(prizeTotal)
|
||||
|
||||
.openTime(new Date())
|
||||
.build();
|
||||
|
||||
// 构造获得物品记录
|
||||
boxRecords = failPrize.stream().map(item -> {
|
||||
return TtBoxRecords.builder()
|
||||
.source(TtboxRecordSource.UPGRADE.getCode())
|
||||
.ornamentId(item.getOrnamentId())
|
||||
.ornamentName(item.getOrnamentName())
|
||||
.userId(ttUser.getUserId())
|
||||
.holderUserId(ttUser.getUserId())
|
||||
.imageUrl(item.getOrnamentImgUrl())
|
||||
.ornamentsPrice(item.getOrnamentPrice())
|
||||
.status(TtboxRecordStatus.IN_PACKSACK_ON.getCode())
|
||||
.marketHashName(item.getOrnamentHashName())
|
||||
.createTime(new Date())
|
||||
.updateTime(new Date())
|
||||
.build();
|
||||
}).collect(Collectors.toList());
|
||||
|
||||
}
|
||||
|
||||
// 游戏记录
|
||||
ttUpgradeRecordService.save(upgradeRecord);
|
||||
ttBoxRecordsService.saveBatch(boxRecords);
|
||||
|
||||
return R.ok(upgradeRecord);
|
||||
|
||||
}
|
||||
|
||||
public Boolean playing(TtUser ttUser, TtUpgradeOrnaments upgradeOrnament, UpgradeBodyA upgradeParam) {
|
||||
|
||||
Integer upgradeOrnamentId = upgradeOrnament.getId();
|
||||
String userType = ttUser.getUserType();
|
||||
|
||||
String rangeFixedKey = RedisConstants.UPGRADE_RANGE_FIXED + upgradeOrnamentId + ":" + userType;
|
||||
String rangeFloatKey = RedisConstants.UPGRADE_RANGE + upgradeOrnamentId + ":" + userType;
|
||||
|
||||
// 读redis的固定概率 [x,y] x进度,y空间大小
|
||||
Object rangeFixedObj = redisCache.getCacheObject(rangeFixedKey);
|
||||
String rangeFixedStr = JSONUtil.toJsonStr(rangeFixedObj);
|
||||
Integer[] rangeFixed = JSONUtil.parseArray(rangeFixedStr).toArray(new Integer[2]);
|
||||
// 读redis的饰品概率区间 [begin,end]
|
||||
Object rangeFloatObj = redisCache.getCacheObject(rangeFloatKey);
|
||||
String rangeFloatStr = JSONUtil.toJsonStr(rangeFloatObj);
|
||||
Integer[] rangeFloat = JSONUtil.parseArray(rangeFloatStr).toArray(new Integer[2]);
|
||||
|
||||
if (ObjectUtil.isNotEmpty(rangeFixed)) {
|
||||
// 抽奖
|
||||
return doUpgrade(
|
||||
ttUser,
|
||||
upgradeOrnament,
|
||||
rangeFixed,
|
||||
upgradeParam,
|
||||
rangeFixedKey,
|
||||
rangeFloatKey,
|
||||
rangeFloat);
|
||||
}
|
||||
|
||||
// 没有,使用redis的概率区间新建,
|
||||
if (ObjectUtil.isNotEmpty(rangeFloat)) {
|
||||
|
||||
// 创建固定概率,
|
||||
Integer[] newRangeFixed = new Integer[]{0, null};
|
||||
for (int i = 0; i < 5; i++) {
|
||||
Random random = new Random();
|
||||
int r = random.nextInt(rangeFloat[1] - rangeFloat[0]) + rangeFloat[0];
|
||||
newRangeFixed[1] = r;
|
||||
}
|
||||
|
||||
// 抽奖
|
||||
return doUpgrade(
|
||||
ttUser,
|
||||
upgradeOrnament,
|
||||
newRangeFixed,
|
||||
upgradeParam,
|
||||
rangeFixedKey,
|
||||
rangeFloatKey,
|
||||
rangeFloat);
|
||||
}
|
||||
|
||||
// 也没有概率区间,用mysql的数据,创建固定概率,抽奖
|
||||
if (userType.equals(UserType.ANCHOR.getCode())) {
|
||||
String anchorLuckSection = upgradeOrnament.getAnchorLuckSection();
|
||||
List<Integer> list = JSONUtil.toList(anchorLuckSection, Integer.class);
|
||||
rangeFloat = list.toArray(new Integer[2]);
|
||||
} else if (userType.equals(UserType.COMMON_USER.getCode())) {
|
||||
String luckSection = upgradeOrnament.getLuckSection();
|
||||
List<Integer> list = JSONUtil.toList(luckSection, Integer.class);
|
||||
rangeFloat = list.toArray(new Integer[2]);
|
||||
}
|
||||
|
||||
rangeFixed = createRangeFixed(rangeFloat, 0);
|
||||
|
||||
// 缓存固定概率
|
||||
// redisCache.setCacheList(rangeFixedKey, Arrays.asList(rangeFixed));
|
||||
// redisCache.setCacheObject(rangeFixedKey, Arrays.asList(rangeFixed));
|
||||
// 缓存概率区间
|
||||
redisCache.setCacheObject(rangeFloatKey, rangeFloat, 1, TimeUnit.DAYS);
|
||||
|
||||
// 抽奖
|
||||
return doUpgrade(
|
||||
ttUser,
|
||||
upgradeOrnament,
|
||||
rangeFixed,
|
||||
upgradeParam,
|
||||
rangeFixedKey,
|
||||
rangeFloatKey,
|
||||
rangeFloat);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param rangeFixed 本次的固定概率
|
||||
* @param param http请求参数
|
||||
* @param rangeFixedKey redis固定概率key
|
||||
* @param rangeFloat 升级饰品的概率区间
|
||||
* @return
|
||||
*/
|
||||
public Boolean doUpgrade(TtUser ttUser,
|
||||
TtUpgradeOrnaments upgradeOrnament,
|
||||
Integer[] rangeFixed,
|
||||
UpgradeBodyA param,
|
||||
String rangeFixedKey,
|
||||
String rangeFloatKey,
|
||||
Integer[] rangeFloat) {
|
||||
|
||||
// 计算进度
|
||||
Integer currentV = rangeFixed[0];
|
||||
Integer fullV = rangeFixed[1];
|
||||
|
||||
int sub = fullV - (param.getProbability() + currentV);
|
||||
|
||||
if (sub > 0) {
|
||||
// 失败,记录进度
|
||||
int i = param.getProbability() + currentV;
|
||||
rangeFixed[0] = i;
|
||||
// redisCache.setCacheList(rangeFixedKey, Arrays.asList(rangeFixed));
|
||||
redisCache.setCacheObject(rangeFixedKey, rangeFixed, 1, TimeUnit.DAYS);
|
||||
return false;
|
||||
}
|
||||
|
||||
// 成功
|
||||
// 如果没有概率区间,新建
|
||||
if (ObjectUtil.isNotEmpty(rangeFloat)) {
|
||||
|
||||
if (ttUser.getUserType().equals(UserType.ANCHOR.getCode())) {
|
||||
String anchorLuckSection = upgradeOrnament.getAnchorLuckSection();
|
||||
List<Integer> list = JSONUtil.toList(anchorLuckSection, Integer.class);
|
||||
rangeFloat = list.toArray(new Integer[2]);
|
||||
} else if (ttUser.getUserType().equals(UserType.COMMON_USER.getCode())) {
|
||||
String luckSection = upgradeOrnament.getLuckSection();
|
||||
List<Integer> list = JSONUtil.toList(luckSection, Integer.class);
|
||||
rangeFloat = list.toArray(new Integer[2]);
|
||||
}
|
||||
|
||||
// 缓存概率区间
|
||||
redisCache.setCacheObject(rangeFloatKey, rangeFloat, 1, TimeUnit.DAYS);
|
||||
|
||||
// rangeFixed = createRangeFixed(rangeFloat,0);
|
||||
|
||||
}
|
||||
|
||||
// 成功,随机创建新的固定概率
|
||||
Integer[] newRangeFixed = createRangeFixed(rangeFloat, Math.abs(sub));
|
||||
|
||||
// 保存新的固定概率
|
||||
// redisCache.setCacheList(rangeFixedKey, Arrays.asList(newRangeFixed));
|
||||
redisCache.setCacheObject(rangeFixedKey, newRangeFixed, 1, TimeUnit.DAYS);
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
|
||||
public Integer[] createRangeFixed(Integer[] rangeFloat, Integer initVal) {
|
||||
|
||||
// 创建固定概率,
|
||||
Integer[] newRangeFixed = new Integer[2];
|
||||
newRangeFixed[0] = initVal;
|
||||
int r = -1;
|
||||
for (int i = 0; i < 5; i++) {
|
||||
Random random = new Random();
|
||||
r = random.nextInt(rangeFloat[1] - rangeFloat[0]) + rangeFloat[0];
|
||||
}
|
||||
newRangeFixed[1] = r;
|
||||
|
||||
return newRangeFixed;
|
||||
}
|
||||
|
||||
// 扣款
|
||||
public R<Map<String, BigDecimal>> upgradeAccounting(BigDecimal consumption, TtUser player) {
|
||||
R<UpdateUserAccountBo> updateResult = userService.updateUserAccount(player.getUserId(), consumption.negate(),
|
||||
TtAccountRecordSource.GOLD_DEVICE);
|
||||
if (R.isError(updateResult)) {
|
||||
return R.fail(updateResult.getMsg());
|
||||
}
|
||||
|
||||
LambdaUpdateWrapper<TtUser> userUpdate = new LambdaUpdateWrapper<>();
|
||||
userUpdate.eq(TtUser::getUserId, player.getUserId());
|
||||
|
||||
Map<String, BigDecimal> map = new HashMap<>();
|
||||
map.put("Amount", updateResult.getData().getAccountAmount());
|
||||
map.put("Credits", updateResult.getData().getAccountCredits());
|
||||
map.put("total", consumption);
|
||||
|
||||
return R.ok(map);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,282 @@
|
||||
package com.ruoyi.playingmethod.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
||||
import com.ruoyi.admin.mapper.TtRedPacketMapper;
|
||||
import com.ruoyi.admin.mapper.TtRedPacketRecordMapper;
|
||||
import com.ruoyi.admin.mapper.TtUserBlendErcashMapper;
|
||||
import com.ruoyi.admin.service.TtRedPackService;
|
||||
import com.ruoyi.admin.service.TtUserService;
|
||||
import com.ruoyi.admin.util.RandomUtils;
|
||||
import com.ruoyi.common.core.domain.AjaxResult;
|
||||
import com.ruoyi.common.core.domain.model.LoginUser;
|
||||
import com.ruoyi.common.redis.config.RedisLock;
|
||||
import com.ruoyi.domain.common.constant.TtAccountRecordSource;
|
||||
import com.ruoyi.domain.common.constant.TtAccountRecordType;
|
||||
import com.ruoyi.domain.entity.TtUserBlendErcash;
|
||||
import com.ruoyi.domain.entity.fight.TtFight;
|
||||
import com.ruoyi.domain.entity.sys.TtUser;
|
||||
import com.ruoyi.domain.other.TtRedPack;
|
||||
import com.ruoyi.domain.other.TtRedPacket;
|
||||
import com.ruoyi.domain.other.TtRedPacketRecord;
|
||||
import com.ruoyi.domain.param.RedPackRecordParam;
|
||||
import com.ruoyi.playingmethod.service.ApiRedPackService;
|
||||
import com.ruoyi.thirdparty.wechat.domain.PtLoginUser;
|
||||
import com.ruoyi.thirdparty.wechat.entity.TtCoinRechargeParam;
|
||||
import com.ruoyi.thirdparty.wechat.entity.TtCoinRechargeRecord;
|
||||
import com.ruoyi.thirdparty.wechat.service.ITtCoinRechargeRecordService;
|
||||
import com.ruoyi.thirdparty.wechat.service.ITtCoinRecordService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.sql.Timestamp;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Service
|
||||
@Slf4j
|
||||
public class ApiRedPackServiceImpl implements ApiRedPackService {
|
||||
|
||||
@Autowired
|
||||
private TtRedPackService ttRedPackService;
|
||||
|
||||
@Autowired
|
||||
private ITtCoinRechargeRecordService coinRechargeRecordService;
|
||||
|
||||
@Autowired
|
||||
private ITtCoinRecordService recordService;
|
||||
|
||||
@Autowired
|
||||
private TtUserService ttUserService;
|
||||
|
||||
@Autowired
|
||||
private TtUserBlendErcashMapper ttUserBlendErcashMapper;
|
||||
|
||||
@Autowired
|
||||
private TtRedPacketRecordMapper ttRedPacketRecordMapper;
|
||||
|
||||
@Autowired
|
||||
private TtRedPacketMapper ttRedPacketMapper;
|
||||
|
||||
@Autowired
|
||||
private TtUserService userService;
|
||||
|
||||
@Autowired
|
||||
private RedisLock redisLock;
|
||||
|
||||
@Override
|
||||
public List<TtRedPack> getRedPackList(PtLoginUser user, Integer type) {
|
||||
TtRedPack redPackParam = new TtRedPack();
|
||||
// redPackParam.setStatus(1L);
|
||||
// redPackParam.setPackType(type + "");
|
||||
return ttRedPackService.selectTtRedPackList(redPackParam);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public AjaxResult getRedPack(Long userId, Long redPackId) {
|
||||
TtUser user = ttUserService.getById(userId);
|
||||
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||
TtRedPack redPack = ttRedPackService.selectTtRedPackById(redPackId);
|
||||
TtCoinRechargeParam rechargeParam = new TtCoinRechargeParam();
|
||||
rechargeParam.setUid(user.getUserId().longValue());
|
||||
rechargeParam.setBeginTime(format.format(redPack.getBeginTime()));
|
||||
rechargeParam.setEndTime(format.format(redPack.getEndTime()));
|
||||
rechargeParam.setCoin(redPack.getRechargeLimit());
|
||||
|
||||
// 查询用户在指定时间内的大于最小充值金额的充值记录
|
||||
LambdaQueryWrapper<TtUserBlendErcash> queryWrapper = new LambdaQueryWrapper<>();
|
||||
queryWrapper.eq(TtUserBlendErcash::getUserId, rechargeParam.getUid())
|
||||
.eq(TtUserBlendErcash::getType, 1)
|
||||
.eq(TtUserBlendErcash::getSource, 0)
|
||||
.gt(TtUserBlendErcash::getTotal, rechargeParam.getCoin())
|
||||
.gt(TtUserBlendErcash::getCreateTime, rechargeParam.getBeginTime())
|
||||
.lt(TtUserBlendErcash::getCreateTime, rechargeParam.getEndTime());
|
||||
List<TtUserBlendErcash> rechargeRecords = ttUserBlendErcashMapper.selectList(queryWrapper);
|
||||
|
||||
// 根据红包ID和用户ID查询红包记录,检查用户是否已经领取过某个特定的红包
|
||||
LambdaQueryWrapper<TtRedPacketRecord> ttRedPacketRecordWrapper = new LambdaQueryWrapper<>();
|
||||
ttRedPacketRecordWrapper
|
||||
.eq(TtRedPacketRecord::getRedPacketId, redPack.getId())
|
||||
.eq(TtRedPacketRecord::getUserId, user.getUserId());
|
||||
List<TtRedPacketRecord> redPackRecords = ttRedPacketRecordMapper.selectList(ttRedPacketRecordWrapper);
|
||||
if (redPackRecords.size() >= rechargeRecords.size()) {
|
||||
return AjaxResult.error("可领取次数不足");
|
||||
}
|
||||
// TODO 减红包剩余数
|
||||
String lockName = "RED_PACK_LOCK:" + redPackId;
|
||||
boolean lock = false;
|
||||
try {
|
||||
// 尝试获取锁,最多尝试10次,每次等待3秒,锁定时间7秒
|
||||
for (int i = 0; i < 10; i++) {
|
||||
lock = redisLock.tryLock(lockName, 3, 7, TimeUnit.SECONDS);
|
||||
if (lock) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!lock) {
|
||||
return AjaxResult.error("服务器繁忙,稍后重试。");
|
||||
}
|
||||
|
||||
// 执行业务逻辑
|
||||
TtRedPack ttRedPack = ttRedPackService.selectTtRedPackById(redPackId);
|
||||
if (ttRedPack.getValidCount() <= 0) {
|
||||
return AjaxResult.error("红包已被领完");
|
||||
} else {
|
||||
ttRedPack.setValidCount(ttRedPack.getValidCount() - 1);
|
||||
ttRedPackService.updateTtRedPack(ttRedPack);
|
||||
}
|
||||
} finally {
|
||||
if (lock) {
|
||||
redisLock.unlock(lockName);
|
||||
}
|
||||
}
|
||||
|
||||
TtRedPacketRecord ttRedPackRecord = new TtRedPacketRecord();
|
||||
|
||||
BigDecimal randomValue = RandomUtils.getRandomaBigdecimal(redPack.getValueMin(), redPack.getValueMax());
|
||||
|
||||
ttRedPackRecord.setRedPacketId(redPackId.intValue());
|
||||
ttRedPackRecord.setUserId(user.getUserId());
|
||||
ttRedPackRecord.setReceiveAmount(randomValue);
|
||||
ttRedPackRecord.setReceiveTime(new Date());
|
||||
|
||||
ttRedPacketRecordMapper.insert(ttRedPackRecord);
|
||||
|
||||
// 加钱
|
||||
LambdaUpdateWrapper<TtUser> userUpdate = new LambdaUpdateWrapper<>();
|
||||
userUpdate
|
||||
.eq(TtUser::getUserId, user.getUserId())
|
||||
.setSql("account_credits = account_credits + " + randomValue);
|
||||
userService.update(userUpdate);
|
||||
|
||||
// 综合消费日志
|
||||
TtUser ttUser = userService.getById(user.getUserId());
|
||||
TtUserBlendErcash blendErcash = TtUserBlendErcash.builder()
|
||||
.userId(user.getUserId())
|
||||
.credits(randomValue.compareTo(BigDecimal.ZERO) > 0 ? randomValue : null)
|
||||
.finalCredits(randomValue.compareTo(BigDecimal.ZERO) > 0 ? ttUser.getAccountCredits().add(randomValue) : null)
|
||||
.total(randomValue.add(randomValue)) // 收支合计
|
||||
.type(TtAccountRecordType.INPUT.getCode())
|
||||
.source(TtAccountRecordSource.CHARGE_RED_PACKET.getCode())
|
||||
.remark(TtAccountRecordSource.CHARGE_RED_PACKET.getMsg())
|
||||
.createTime(new Timestamp(System.currentTimeMillis()))
|
||||
.updateTime(new Timestamp(System.currentTimeMillis()))
|
||||
.build();
|
||||
|
||||
ttUserBlendErcashMapper.insert(blendErcash);
|
||||
|
||||
return AjaxResult.success(ttRedPackRecord);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public AjaxResult getRedPackByKey(LoginUser user, String redPackKey) {
|
||||
|
||||
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
|
||||
// 根据KEY查询红包
|
||||
LambdaUpdateWrapper<TtRedPacket> selectRedPackByKeyWrapper = new LambdaUpdateWrapper<>();
|
||||
selectRedPackByKeyWrapper
|
||||
.eq(TtRedPacket::getPassword, redPackKey);
|
||||
TtRedPacket redPack = ttRedPacketMapper.selectOne(selectRedPackByKeyWrapper);
|
||||
if (redPack == null){
|
||||
return AjaxResult.error("未找到红包,请检查口令是否正确");
|
||||
}
|
||||
TtCoinRechargeParam rechargeParam = new TtCoinRechargeParam();
|
||||
rechargeParam.setUid(user.getUserId());
|
||||
rechargeParam.setBeginTime(format.format(new Date()) + " 00:00:00");
|
||||
rechargeParam.setEndTime(format.format(new Date()) + " 23:59:59");
|
||||
|
||||
|
||||
LambdaQueryWrapper<TtRedPacketRecord> ttRedPacketRecordWrapper = new LambdaQueryWrapper<>();
|
||||
ttRedPacketRecordWrapper
|
||||
.eq(TtRedPacketRecord::getRedPacketId, redPack.getId())
|
||||
.eq(TtRedPacketRecord::getUserId, user.getUserId().intValue());
|
||||
List<TtRedPacketRecord> redPackRecords = ttRedPacketRecordMapper.selectList(ttRedPacketRecordWrapper);
|
||||
if (redPackRecords.size() > 0){
|
||||
return AjaxResult.error("您已经领取过。");
|
||||
}
|
||||
|
||||
TtRedPacketRecord ttRedPackRecord = new TtRedPacketRecord();
|
||||
|
||||
// 此处解析最小值和最大值[1, 5]
|
||||
String amount = redPack.getAmount();
|
||||
// 去除方括号和空格,得到 "1,5"
|
||||
String cleanString = amount.replaceAll("\\[|\\]|\\s", "");
|
||||
// 分割字符串,得到字符串数组 ["1", "5"]
|
||||
String[] parts = cleanString.split(",");
|
||||
// 转换为 BigDecimal
|
||||
BigDecimal minValue = new BigDecimal(parts[0]);
|
||||
BigDecimal maxValue = new BigDecimal(parts[1]);
|
||||
BigDecimal randomValue = RandomUtils.getRandomaBigdecimal(minValue, maxValue);
|
||||
|
||||
ttRedPackRecord.setRedPacketId(redPack.getId());
|
||||
ttRedPackRecord.setUserId(user.getUserId().intValue());
|
||||
ttRedPackRecord.setReceivePassword(redPackKey);
|
||||
ttRedPackRecord.setReceiveAmount(randomValue);
|
||||
ttRedPackRecord.setReceiveTime(new Date());
|
||||
|
||||
ttRedPacketRecordMapper.insert(ttRedPackRecord);
|
||||
|
||||
// 加钱
|
||||
userService.updateOnlyUserAccount(user.getUserId().intValue(), randomValue, TtAccountRecordSource.RECEIVE_RED_PACKET);
|
||||
|
||||
return AjaxResult.success(ttRedPackRecord);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<TtRedPacketRecord> getActivityDataHis(PtLoginUser user) {
|
||||
RedPackRecordParam redPackRecordParam = new RedPackRecordParam();
|
||||
redPackRecordParam.setuId(user.getUserId().intValue());
|
||||
LambdaQueryWrapper<TtRedPacketRecord> ttRedPacketRecordWrapper = new LambdaQueryWrapper<>();
|
||||
ttRedPacketRecordWrapper
|
||||
.eq(TtRedPacketRecord::getUserId, user.getUserId().intValue());
|
||||
List<TtRedPacketRecord> redPackRecords = ttRedPacketRecordMapper.selectList(ttRedPacketRecordWrapper);
|
||||
return redPackRecords;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AjaxResult getRedPackDataDetail(PtLoginUser user, Long recordId) {
|
||||
|
||||
TtRedPacketRecord ttRedPackRecord = ttRedPacketRecordMapper.selectById(recordId);
|
||||
if (ttRedPackRecord.getReceivePassword() != null) {
|
||||
TtRedPacket redPackKey = ttRedPacketMapper.selectById(ttRedPackRecord.getRedPacketId());
|
||||
// TODO 缺少属性
|
||||
// ttRedPackRecord.setRedPackKey(redPackKey);
|
||||
} else {
|
||||
TtRedPack redPack = ttRedPackService.selectTtRedPackById(ttRedPackRecord.getRedPacketId().longValue());
|
||||
// TODO 缺少属性
|
||||
// ttRedPackRecord.setRedPack(redPack);
|
||||
}
|
||||
|
||||
return AjaxResult.success(ttRedPackRecord);
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析红包最小值和最大值
|
||||
*/
|
||||
public static List<BigDecimal> parseBigDecimalList(String input) {
|
||||
// 去掉中括号和空格
|
||||
String cleanInput = input.replace("[", "").replace("]", "").replaceAll("\\s+", "");
|
||||
|
||||
// 按逗号分割成字符串数组
|
||||
String[] parts = cleanInput.split(",");
|
||||
|
||||
// 转换为 BigDecimal 对象列表
|
||||
List<BigDecimal> bigDecimals = Arrays.stream(parts)
|
||||
.map(BigDecimal::new) // 使用 BigDecimal 的构造方法转换为 BigDecimal 对象
|
||||
.collect(Collectors.toList());
|
||||
|
||||
return bigDecimals;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,198 @@
|
||||
package com.ruoyi.playingmethod.service.impl;
|
||||
|
||||
import com.ruoyi.admin.mapper.TtBoxMapper;
|
||||
import com.ruoyi.admin.mapper.TtBoxRecordsMapper;
|
||||
import com.ruoyi.admin.mapper.TtOrnamentMapper;
|
||||
import com.ruoyi.admin.service.TtBoxRecordsService;
|
||||
import com.ruoyi.admin.service.TtOrnamentService;
|
||||
import com.ruoyi.admin.service.TtUserService;
|
||||
import com.ruoyi.common.core.domain.AjaxResult;
|
||||
import com.ruoyi.common.core.domain.model.LoginUser;
|
||||
import com.ruoyi.common.utils.DateUtils;
|
||||
import com.ruoyi.domain.common.constant.TtboxRecordSource;
|
||||
import com.ruoyi.domain.dto.packSack.PackSackCondition;
|
||||
import com.ruoyi.domain.entity.TtBoxRecords;
|
||||
import com.ruoyi.domain.entity.TtOrnament;
|
||||
import com.ruoyi.domain.entity.sys.TtUser;
|
||||
import com.ruoyi.domain.other.TtBox;
|
||||
import com.ruoyi.domain.other.TtReplacementRecord;
|
||||
import com.ruoyi.domain.vo.UserPackSackDataVO;
|
||||
import com.ruoyi.playingmethod.mapper.ApiReplacementRecordMapper;
|
||||
import com.ruoyi.playingmethod.service.IApiReplacementRecordService;
|
||||
import com.ruoyi.system.service.ISysConfigService;
|
||||
import com.ruoyi.thirdparty.wechat.domain.PtLoginUser;
|
||||
import com.ruoyi.user.mapper.ApiUserPackSackMapper;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* 业务端汰换逻辑实现
|
||||
*
|
||||
* @author junhai
|
||||
*/
|
||||
@Service
|
||||
public class ApiReplacementRecordServiceImpl implements IApiReplacementRecordService {
|
||||
|
||||
@Autowired
|
||||
private ApiReplacementRecordMapper apiReplacementRecordMapper;
|
||||
|
||||
@Autowired
|
||||
private TtBoxRecordsService ttBoxRecordsService;
|
||||
|
||||
@Autowired
|
||||
private TtBoxRecordsMapper ttBoxRecordsMapper;
|
||||
|
||||
@Autowired
|
||||
private ISysConfigService sysConfigService;
|
||||
|
||||
@Autowired
|
||||
private TtOrnamentMapper ttOrnamentMapper;
|
||||
|
||||
// 概率配置数组
|
||||
private static final double[][] percent = {
|
||||
{0.5, 0.6},
|
||||
{0.6, 0.7},
|
||||
{0.7, 0.8},
|
||||
{0.8, 0.9},
|
||||
{0.9, 1},
|
||||
{1, 2}
|
||||
};
|
||||
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public AjaxResult synthesizeItems(LoginUser user, List<Long> itemIds) {
|
||||
int size = 0;
|
||||
int size1 = 0;
|
||||
if (itemIds != null) {
|
||||
size = itemIds.size();
|
||||
}
|
||||
|
||||
int allCount = size + size1;
|
||||
if (allCount < 3 || allCount > 9) {
|
||||
return AjaxResult.error("汰换数量在3~9个");
|
||||
}
|
||||
|
||||
BigDecimal totalPrice = new BigDecimal(0);
|
||||
|
||||
//查询饰品列表
|
||||
// 1.先查询宝箱记录里面的饰品
|
||||
if(!itemIds.isEmpty()){
|
||||
// 从我的背包中查询饰品总价值
|
||||
List<UserPackSackDataVO> boxs = apiReplacementRecordMapper
|
||||
.selectUserPackSack(user.getUserId().intValue(), itemIds);
|
||||
for (int i = 0; i < boxs.size(); i++) {
|
||||
BigDecimal bigDecimal = boxs.get(i).getOrnamentsPrice();
|
||||
totalPrice = totalPrice.add(bigDecimal);
|
||||
}
|
||||
}
|
||||
//累加装备总价值
|
||||
String status = "8";
|
||||
//更新记录的状态 updateStatusByIds
|
||||
if(!itemIds.isEmpty()){
|
||||
ttBoxRecordsMapper.updateStatusByIds(itemIds, status);
|
||||
}
|
||||
|
||||
//获取最小汰换金额
|
||||
BigDecimal minPrice = new BigDecimal(sysConfigService.selectConfigByKey("minExchangeAmount"));
|
||||
// 汰换饰品合计总价不得低于
|
||||
if (totalPrice.compareTo(minPrice) < 0) {
|
||||
return AjaxResult.error("汰换饰品合计总价不得低于" + minPrice);
|
||||
}
|
||||
|
||||
//获取饰品的id
|
||||
Long id = getOId(totalPrice);
|
||||
//获取饰品详情
|
||||
TtOrnament ttOrnament = ttOrnamentMapper.selectOrnamentById(id);
|
||||
//进行汰换的日志记录
|
||||
TtReplacementRecord replacementRecord = new TtReplacementRecord();
|
||||
replacementRecord.setUid(user.getUserId());
|
||||
replacementRecord.setUname(user.getUserData().getNickName());
|
||||
replacementRecord.setAwardOid(ttOrnament.getId());
|
||||
replacementRecord.setAwardOname(ttOrnament.getName());
|
||||
replacementRecord.setAwardOimg(ttOrnament.getImageUrl());
|
||||
replacementRecord.setAwardOprice(ttOrnament.getUsePrice());
|
||||
replacementRecord.setTime(DateUtils.getNowDate());
|
||||
replacementRecord.setCreateTime(DateUtils.getNowDate());
|
||||
apiReplacementRecordMapper.insertTtReplacementRecord(replacementRecord);
|
||||
//将汰换的奖品加入背包
|
||||
TtBoxRecords ttBoxRecords = new TtBoxRecords();
|
||||
ttBoxRecords.setSource(TtboxRecordSource.REPLACEMENT.getCode());
|
||||
ttBoxRecords.setUserId(user.getUserId().intValue());
|
||||
ttBoxRecords.setHolderUserId(user.getUserId().intValue());
|
||||
ttBoxRecords.setBoxName("汰换奖品");
|
||||
ttBoxRecords.setOrnamentName(ttOrnament.getName());
|
||||
ttBoxRecords.setImageUrl(ttOrnament.getImageUrl());
|
||||
ttBoxRecords.setOrnamentId(ttOrnament.getId());
|
||||
ttBoxRecords.setOrnamentsPrice(ttOrnament.getUsePrice());
|
||||
ttBoxRecords.setStatus(0);
|
||||
ttBoxRecords.setCreateTime(DateUtils.getNowDate());
|
||||
ttBoxRecordsService.save(ttBoxRecords);
|
||||
|
||||
return AjaxResult.success(replacementRecord);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 随机产生饰品id
|
||||
*
|
||||
* @param bean
|
||||
* @return
|
||||
*/
|
||||
public Long getOId(BigDecimal bean) {
|
||||
List<TtOrnament> ornament = new ArrayList<>();
|
||||
initArray(bean, ornament);
|
||||
Random random = new Random();
|
||||
int randomIndex = random.nextInt(ornament.size());
|
||||
return ornament.get(randomIndex).getId();
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化 饰品列表
|
||||
*
|
||||
* @param bean
|
||||
* @param ornaments
|
||||
*/
|
||||
private void initArray(BigDecimal bean, List<TtOrnament> ornaments) {
|
||||
for (double[] range : percent) {
|
||||
BigDecimal start = bean.multiply(BigDecimal.valueOf(range[0]));
|
||||
BigDecimal end = bean.multiply(BigDecimal.valueOf(range[1]));
|
||||
|
||||
Map<String, BigDecimal> map = new HashMap<>();
|
||||
map.put("start", start);
|
||||
map.put("end", end);
|
||||
|
||||
int configQuantity = 1;
|
||||
|
||||
if (configQuantity > 0) {
|
||||
List<TtOrnament> eligibleOrnaments = apiReplacementRecordMapper.findByPriceRange(map);
|
||||
shuffleList(eligibleOrnaments);
|
||||
int quantityToAdd = Math.min(configQuantity, eligibleOrnaments.size());
|
||||
|
||||
for (int i = 0; i < quantityToAdd; i++) {
|
||||
ornaments.add(eligibleOrnaments.get(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 采用了 Fisher-Yates 随机洗牌算法,
|
||||
*
|
||||
* @param list
|
||||
*/
|
||||
private void shuffleList(List<TtOrnament> list) {
|
||||
Random random = new Random();
|
||||
int n = list.size();
|
||||
for (int i = n - 1; i > 0; i--) {
|
||||
int j = random.nextInt(i + 1);
|
||||
TtOrnament temp = list.get(i);
|
||||
list.set(i, list.get(j));
|
||||
list.set(j, temp);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,651 @@
|
||||
package com.ruoyi.playingmethod.service.impl;
|
||||
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
|
||||
import com.baomidou.mybatisplus.extension.conditions.update.LambdaUpdateChainWrapper;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.ruoyi.admin.config.RedisConstants;
|
||||
import com.ruoyi.admin.mapper.*;
|
||||
import com.ruoyi.admin.service.TtBoxRecordsService;
|
||||
import com.ruoyi.admin.service.TtOrnamentsLevelService;
|
||||
import com.ruoyi.admin.service.TtRollUserService;
|
||||
import com.ruoyi.admin.util.RandomUtils;
|
||||
import com.ruoyi.common.core.domain.R;
|
||||
import com.ruoyi.common.redis.config.RedisLock;
|
||||
import com.ruoyi.common.utils.DateUtils;
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
import com.ruoyi.domain.common.constant.TtboxRecordSource;
|
||||
import com.ruoyi.domain.common.constant.UserType;
|
||||
import com.ruoyi.domain.common.constant.roll.RollGetPrizeWay;
|
||||
import com.ruoyi.domain.common.constant.roll.RollStatus;
|
||||
import com.ruoyi.domain.common.constant.roll.RollType;
|
||||
import com.ruoyi.domain.dto.roll.GetRollOpenPrizeParam;
|
||||
import com.ruoyi.domain.dto.roll.GetRollPlayersParam;
|
||||
import com.ruoyi.domain.dto.roll.GetRollPrizePool;
|
||||
import com.ruoyi.domain.entity.*;
|
||||
import com.ruoyi.domain.entity.roll.*;
|
||||
import com.ruoyi.domain.entity.sys.TtUser;
|
||||
import com.ruoyi.domain.other.*;
|
||||
import com.ruoyi.domain.vo.boxRecords.TtBoxRecordsVO;
|
||||
import com.ruoyi.domain.vo.roll.RollJackpotOrnamentsVO;
|
||||
import com.ruoyi.domain.vo.roll.RollUserPrizeVO;
|
||||
import com.ruoyi.domain.vo.roll.RollUserVO;
|
||||
import com.ruoyi.domain.vo.roll.SimpleRollOrnamentVO;
|
||||
import com.ruoyi.framework.manager.AsyncManager;
|
||||
import com.ruoyi.playingmethod.controller.ApiRollController.GetRollListParam;
|
||||
import com.ruoyi.playingmethod.controller.ApiRollController.JoinRollParam;
|
||||
import com.ruoyi.playingmethod.mapper.ApiRollMapper;
|
||||
import com.ruoyi.playingmethod.service.ApiRollService;
|
||||
import com.ruoyi.domain.vo.RollDetailsDataVO;
|
||||
import com.ruoyi.domain.vo.RollListDataVO;
|
||||
import com.ruoyi.thirdparty.common.service.ApiNoticeService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.sql.Timestamp;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static com.ruoyi.domain.common.constant.TtboxRecordStatus.IN_PACKSACK_ON;
|
||||
|
||||
@Service
|
||||
@Slf4j
|
||||
public class ApiRollServiceImpl extends ServiceImpl<TtRollMapper, TtRoll> implements ApiRollService {
|
||||
|
||||
private final ApiRollMapper apiRollMapper;
|
||||
private final TtUserMapper userMapper;
|
||||
private final TtOrnamentMapper ornamentsMapper;
|
||||
private final TtBoxRecordsService boxRecordsService;
|
||||
private final TtRollMapper rollMapper;
|
||||
private final TtRollUserService rollUserService;
|
||||
private final TtRollJackpotOrnamentsMapper rollJackpotOrnamentsMapper;
|
||||
private final TtRechargeRecordMapper rechargeRecordMapper;
|
||||
private final RedisLock redisLock;
|
||||
|
||||
public ApiRollServiceImpl(ApiRollMapper apiRollMapper,
|
||||
TtUserMapper userMapper,
|
||||
TtOrnamentMapper ornamentsMapper,
|
||||
TtBoxRecordsService boxRecordsService,
|
||||
TtRollMapper rollMapper,
|
||||
TtRollUserService rollUserService,
|
||||
TtRollJackpotOrnamentsMapper rollJackpotOrnamentsMapper,
|
||||
TtRechargeRecordMapper rechargeRecordMapper,
|
||||
RedisLock redisLock) {
|
||||
this.apiRollMapper = apiRollMapper;
|
||||
this.userMapper = userMapper;
|
||||
this.ornamentsMapper = ornamentsMapper;
|
||||
this.boxRecordsService = boxRecordsService;
|
||||
this.rollMapper = rollMapper;
|
||||
this.rollUserService = rollUserService;
|
||||
this.rollJackpotOrnamentsMapper = rollJackpotOrnamentsMapper;
|
||||
this.rechargeRecordMapper = rechargeRecordMapper;
|
||||
this.redisLock = redisLock;
|
||||
}
|
||||
|
||||
@Autowired
|
||||
private TtRollUserMapper ttRollUserMapper;
|
||||
|
||||
@Autowired
|
||||
private ApiNoticeService apiNoticeService;
|
||||
|
||||
@Autowired
|
||||
private TtRollUserPrizeMapper ttRollUserPrizeMapper;
|
||||
|
||||
@Autowired
|
||||
private TtRollJackpotMapper ttRollJackpotMapper;
|
||||
|
||||
@Autowired
|
||||
private TtRollJackpotOrnamentsMapper ttRollJackpotOrnamentsMapper;
|
||||
|
||||
@Autowired
|
||||
private TtRollMapper ttRollMapper;
|
||||
|
||||
@Autowired
|
||||
private TtOrnamentMapper ttOrnamentMapper;
|
||||
|
||||
@Autowired
|
||||
private TtBoxRecordsService ttBoxRecordsService;
|
||||
|
||||
@Autowired
|
||||
private TtOrnamentsLevelMapper ttOrnamentsLevelMapper;
|
||||
|
||||
@Autowired
|
||||
private TtOrnamentsLevelService ttOrnamentsLevelService;
|
||||
|
||||
@Autowired
|
||||
private TtBoxRecordsMapper ttBoxRecordsMapper;
|
||||
|
||||
public R<TtRoll> joinRollCheck(TtRoll ttRoll, TtRollUser rollUser, TtUser player, JoinRollParam param) {
|
||||
|
||||
if (StringUtils.isNull(ttRoll)) return R.fail("当前Roll房已结束");
|
||||
if (StringUtils.isNotNull(rollUser)) return R.fail("您当前已在该房间内,请勿重复加入房间!");
|
||||
|
||||
String password = ttRoll.getRollPassword();
|
||||
if (StringUtils.isNotEmpty(password)) {
|
||||
if (StringUtils.isEmpty(param.getRollPassword())) return R.fail("请输入密码!");
|
||||
if (!password.equals(param.getRollPassword())) return R.fail("密码错误!");
|
||||
}
|
||||
|
||||
// 检查加入条件:充值下限
|
||||
BigDecimal minRecharge = ttRoll.getMinRecharge();
|
||||
if (minRecharge.compareTo(BigDecimal.ZERO) > 0) {
|
||||
BigDecimal rechargeTotalAmount = getRechargeTotalAmount(player.getUserId(), ttRoll.getRechargeStartTime());
|
||||
if (minRecharge.compareTo(rechargeTotalAmount) > 0) return R.fail("未满足该房间的充值条件!");
|
||||
}
|
||||
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
@Override
|
||||
public R joinRoll(JoinRollParam param, TtUser player) {
|
||||
|
||||
// roll房
|
||||
TtRoll ttRoll = new LambdaQueryChainWrapper<>(rollMapper)
|
||||
.eq(TtRoll::getId, param.getRollId())
|
||||
.eq(TtRoll::getRollStatus, "0")
|
||||
.gt(TtRoll::getEndTime, DateUtils.getNowDate())
|
||||
.one();
|
||||
// roll房成员
|
||||
TtRollUser rollUser = new LambdaQueryChainWrapper<>(rollUserService.getBaseMapper())
|
||||
.eq(TtRollUser::getUserId, player.getUserId())
|
||||
.eq(TtRollUser::getRollId, param.getRollId())
|
||||
.one();
|
||||
|
||||
// 检查
|
||||
R<TtRoll> check = joinRollCheck(ttRoll, rollUser, player, param);
|
||||
if (!check.getCode().equals(200)) return check;
|
||||
|
||||
// 如果是主播房
|
||||
if (ttRoll.getRollType().equals(RollType.ANCHOR.getCode())) {
|
||||
TtUser anchor = new LambdaQueryChainWrapper<>(userMapper)
|
||||
.eq(TtUser::getUserId, ttRoll.getUserId())
|
||||
.eq(TtUser::getUserType, UserType.ANCHOR.getCode())
|
||||
.eq(TtUser::getDelFlag, "0")
|
||||
.one();
|
||||
// 检查是否粉丝
|
||||
Integer parentId = player.getParentId();
|
||||
if (StringUtils.isNull(parentId) || !anchor.getUserId().equals(parentId)) {
|
||||
return R.fail("您不是该主播的粉丝,请先加入主播粉丝团才可加入房间!");
|
||||
}
|
||||
}
|
||||
|
||||
// 加入房间
|
||||
Boolean lock = false;
|
||||
for (int i = 0; i < 2; i++) {
|
||||
|
||||
lock = redisLock.tryLock(RedisConstants.JOIN_ROLL_LOCK + param.getRollId(), 2L, 7L, TimeUnit.SECONDS);
|
||||
|
||||
if (!lock) {
|
||||
try {
|
||||
TimeUnit.SECONDS.sleep(1L);
|
||||
} catch (Exception e) {
|
||||
log.warn("try lock sleep warn");
|
||||
} finally {
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (lock) {
|
||||
try {
|
||||
|
||||
List<TtRollUser> rollUserList = new LambdaQueryChainWrapper<>(rollUserService.getBaseMapper())
|
||||
.eq(TtRollUser::getRollId, param.getRollId())
|
||||
.list();
|
||||
|
||||
if (ttRoll.getPeopleNum() <= rollUserList.size()) {
|
||||
return R.fail("roll房人满。");
|
||||
}
|
||||
|
||||
TtRollUser ttRollUser = TtRollUser.builder()
|
||||
.rollId(param.getRollId())
|
||||
.userId(player.getUserId())
|
||||
.userName(player.getUserName())
|
||||
.nickName(player.getNickName())
|
||||
.avatar(player.getAvatar())
|
||||
.joinTime(DateUtils.getNowDate())
|
||||
.build();
|
||||
|
||||
rollUserService.getBaseMapper().insert(ttRollUser);
|
||||
|
||||
return R.ok();
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return R.fail("加入失败,请稍后重试。");
|
||||
} finally {
|
||||
redisLock.unlock(RedisConstants.JOIN_ROLL_LOCK + param.getRollId());
|
||||
}
|
||||
}
|
||||
|
||||
redisLock.unlock(RedisConstants.JOIN_ROLL_LOCK + param.getRollId());
|
||||
return R.fail("服务器繁忙。");
|
||||
|
||||
}
|
||||
|
||||
// roll房开奖
|
||||
@Override
|
||||
public R endROLL(Integer rollId) {
|
||||
|
||||
System.out.println("server roll房开奖" + rollId);
|
||||
|
||||
// 1 检查
|
||||
TtRoll ttRoll = new LambdaQueryChainWrapper<>(rollMapper)
|
||||
.eq(TtRoll::getId, rollId)
|
||||
.eq(TtRoll::getDelFlag, "0")
|
||||
.one();
|
||||
if (ObjectUtil.isEmpty(ttRoll)) return R.fail("不存在的roll房。");
|
||||
if(ttRoll.getRollStatus().equals("1")) return R.ok("已开奖,拒绝重复开奖");
|
||||
|
||||
// 用数据库乐观锁:将 rollStatus 从 0 改为 1(原子操作),防止并发重复开奖
|
||||
boolean locked = new LambdaUpdateChainWrapper<>(rollMapper)
|
||||
.eq(TtRoll::getId, rollId)
|
||||
.eq(TtRoll::getRollStatus, "0")
|
||||
.set(TtRoll::getRollStatus, "1")
|
||||
.update();
|
||||
if (!locked) {
|
||||
return R.ok("已开奖,拒绝重复开奖");
|
||||
}
|
||||
// 重新查询,final 变量供 lambda 使用
|
||||
final TtRoll finalRoll = new LambdaQueryChainWrapper<>(rollMapper)
|
||||
.eq(TtRoll::getId, rollId)
|
||||
.eq(TtRoll::getDelFlag, "0")
|
||||
.one();
|
||||
ttRoll = finalRoll;
|
||||
|
||||
List<TtRollUser> list = new LambdaQueryChainWrapper<>(rollUserService.getBaseMapper())
|
||||
.eq(TtRollUser::getRollId, rollId)
|
||||
.list();
|
||||
if (ObjectUtil.isEmpty(list) || list.isEmpty()) {
|
||||
ttRoll.setRollStatus(RollStatus.END.getCode());
|
||||
rollMapper.updateById(ttRoll);
|
||||
return R.ok("roll房无人参与。");
|
||||
}
|
||||
|
||||
// 2 分配系统指定,并返回剩余奖品
|
||||
List<TtRollUser> rollUsers = new LambdaQueryChainWrapper<>(ttRollUserMapper)
|
||||
.eq(TtRollUser::getRollId, ttRoll.getId())
|
||||
.eq(TtRollUser::getGetPrizeWay, RollGetPrizeWay.SYS.getCode())
|
||||
.list();
|
||||
|
||||
log.info("所有参与人员" + rollUsers);
|
||||
|
||||
Map<Long, TtRollJackpotOrnaments> surplusPrize = rollSurplusOrnaments(rollUsers, ttRoll);
|
||||
|
||||
// 3 过滤出未分配奖品的用户
|
||||
LambdaQueryWrapper<TtRollUser> rollUserQuery = new LambdaQueryWrapper<>();
|
||||
rollUserQuery
|
||||
.eq(TtRollUser::getRollId, rollId)
|
||||
.eq(TtRollUser::getStatus, "0");
|
||||
if (!rollUsers.isEmpty()) {
|
||||
List<Integer> rollUserIds = rollUsers.stream()
|
||||
.map(TtRollUser::getId)
|
||||
.collect(Collectors.toList());
|
||||
rollUserQuery.notIn(TtRollUser::getId, rollUserIds);
|
||||
}
|
||||
List<TtRollUser> rollUserList = rollUserService.list(rollUserQuery);
|
||||
|
||||
// 4 打乱用户顺序
|
||||
Collections.shuffle(rollUserList);
|
||||
log.info("过滤系统指定以后" + rollUserList);
|
||||
|
||||
// 5 分配奖品、
|
||||
List<TtBoxRecords> res = new ArrayList<>();
|
||||
|
||||
|
||||
// 一人拿一件
|
||||
boolean iGetIt = false;
|
||||
for (TtRollUser rollUser : rollUserList) {
|
||||
|
||||
// if (iGetIt) continue;
|
||||
|
||||
Set<Map.Entry<Long, TtRollJackpotOrnaments>> entries = surplusPrize.entrySet();
|
||||
|
||||
for (Map.Entry<Long, TtRollJackpotOrnaments> entry : entries) {
|
||||
|
||||
Integer numb = entry.getValue().getOrnamentsNum();
|
||||
if (numb <= 0) continue;
|
||||
|
||||
// 等级信息
|
||||
TtOrnamentsLevel level = ttOrnamentsLevelService.getById(entry.getValue().getOrnamentLevelId());
|
||||
|
||||
TtBoxRecords boxRecords = TtBoxRecords.builder()
|
||||
.rollId(rollId)
|
||||
.createTime(new Timestamp(System.currentTimeMillis()))
|
||||
.holderUserId(rollUser.getUserId())
|
||||
.ornamentId(entry.getKey())
|
||||
.ornamentsPrice(entry.getValue().getPrice())
|
||||
.imageUrl(entry.getValue().getImgUrl())
|
||||
.ornamentName(entry.getValue().getOrnamentName())
|
||||
.ornamentLevelImg(level.getLevelImg())
|
||||
.source(TtboxRecordSource.ROLL.getCode())
|
||||
.userId(rollUser.getUserId())
|
||||
.updateTime(new Timestamp(System.currentTimeMillis()))
|
||||
.status(IN_PACKSACK_ON.getCode())
|
||||
.build();
|
||||
res.add(boxRecords);
|
||||
|
||||
log.info("{}获得{}", rollUser.getNickName(), entry.getValue().getOrnamentName());
|
||||
|
||||
// 扣减数量
|
||||
TtRollJackpotOrnaments value = entry.getValue();
|
||||
value.setOrnamentsNum(numb - 1);
|
||||
surplusPrize.put(entry.getKey(), value);
|
||||
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
log.info("保存开奖结果:" + res);
|
||||
|
||||
boxRecordsService.saveBatch(res);
|
||||
|
||||
// ===== 新增:Roll房开奖通知(过滤机器人用户 userType=03)=====
|
||||
TtRoll finalTtRoll = ttRoll;
|
||||
AsyncManager.me().run(() -> sendRollResultNotice(res, finalTtRoll));
|
||||
// ===== 新增roll房开奖通知结束 =====
|
||||
|
||||
// 6 更新roll房状态
|
||||
new LambdaUpdateChainWrapper<>(rollMapper)
|
||||
.eq(TtRoll::getId, ttRoll.getId())
|
||||
.set(TtRoll::getRollStatus, RollStatus.END.getCode())
|
||||
.set(TtRoll::getUpdateTime, new Date())
|
||||
.update();
|
||||
|
||||
System.out.println("server roll房开奖" + ttRoll.getId() + ttRoll.getRollName() + "成功");
|
||||
|
||||
return R.ok();
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Roll房开奖结果通知(过滤机器人用户)
|
||||
* 示例:【roll房名字】 张三的开奖结果:AK-47(120元)、蝴蝶刀(500元),共获得价值 620 元的饰品。
|
||||
*/
|
||||
private void sendRollResultNotice(List<TtBoxRecords> res, TtRoll ttRoll) {
|
||||
try {
|
||||
if (res.isEmpty()) return;
|
||||
// 按用户分组饰品
|
||||
Map<Integer, List<TtBoxRecords>> userItemsMap = res.stream()
|
||||
.filter(r -> r.getHolderUserId() != null)
|
||||
.collect(Collectors.groupingBy(TtBoxRecords::getHolderUserId));
|
||||
if (userItemsMap.isEmpty()) return;
|
||||
|
||||
// 过滤机器人,只取真实用户
|
||||
List<Integer> userIds = new ArrayList<>(userItemsMap.keySet());
|
||||
List<TtUser> realUsers = new LambdaQueryChainWrapper<>(userMapper)
|
||||
.in(TtUser::getUserId, userIds)
|
||||
.ne(TtUser::getUserType, UserType.ROBOT_USER.getCode())
|
||||
.list();
|
||||
|
||||
String rollName = ttRoll.getRollName();
|
||||
for (TtUser user : realUsers) {
|
||||
List<TtBoxRecords> items = userItemsMap.get(user.getUserId());
|
||||
if (items == null || items.isEmpty()) continue;
|
||||
// 拼接通知内容
|
||||
StringBuilder contentBuilder = new StringBuilder();
|
||||
contentBuilder.append("【").append(rollName).append("】 ")
|
||||
.append(user.getNickName()).append("的开奖结果:");
|
||||
BigDecimal totalPrice = BigDecimal.ZERO;
|
||||
for (TtBoxRecords item : items) {
|
||||
contentBuilder.append(item.getOrnamentName())
|
||||
.append("(").append(item.getOrnamentsPrice()).append("元)、");
|
||||
if (item.getOrnamentsPrice() != null) {
|
||||
totalPrice = totalPrice.add(item.getOrnamentsPrice());
|
||||
}
|
||||
}
|
||||
String contentStr = contentBuilder.toString();
|
||||
if (contentStr.endsWith("、")) {
|
||||
contentStr = contentStr.substring(0, contentStr.length() - 1);
|
||||
}
|
||||
contentStr += ",共获得价值 " + totalPrice + " 元的饰品。";
|
||||
apiNoticeService.sendNotice(Long.valueOf(user.getUserId()), "Roll房开奖通知", contentStr);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("Roll房开奖通知推送失败,rollId={}, error={}", ttRoll.getId(), e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
//{ornamentId:TtRollJackpotOrnaments} TtRollJackpotOrnaments中有数量
|
||||
public Map<Long, TtRollJackpotOrnaments> rollSurplusOrnaments(List<TtRollUser> rollUsers, TtRoll ttRoll) {
|
||||
|
||||
// 奖池所有物品
|
||||
List<TtRollJackpotOrnaments> jackpotOrnaments = new LambdaQueryChainWrapper<>(rollJackpotOrnamentsMapper)
|
||||
.eq(TtRollJackpotOrnaments::getJackpotId, ttRoll.getJackpotId())
|
||||
.list();
|
||||
|
||||
HashMap<Long, TtRollJackpotOrnaments> AllPrizePool = new HashMap<>();
|
||||
for (TtRollJackpotOrnaments i : jackpotOrnaments) {
|
||||
AllPrizePool.put(i.getOrnamentsId(), i);
|
||||
}
|
||||
|
||||
// 没有系统指定,直接返回奖池所有物品
|
||||
if (rollUsers.isEmpty()) return AllPrizePool;
|
||||
|
||||
List<Integer> rollUserIds = rollUsers.stream()
|
||||
.map(TtRollUser::getId)
|
||||
.collect(Collectors.toList());
|
||||
// 系统指定信息
|
||||
List<RollUserPrizeVO> RollUserPrizeVOs = ttRollUserPrizeMapper.byRollUserIds(rollUserIds);
|
||||
// 没有系统指定,直接返回奖池所有物品
|
||||
if (RollUserPrizeVOs.isEmpty()) return AllPrizePool;
|
||||
|
||||
// 分配系统指定
|
||||
List<TtBoxRecords> res = new ArrayList<>();
|
||||
for (RollUserPrizeVO userPrize : RollUserPrizeVOs) {
|
||||
|
||||
// 分配奖品
|
||||
for (int i = 0; i < userPrize.getNumber(); i++) {
|
||||
|
||||
TtBoxRecords boxRecords = TtBoxRecords.builder()
|
||||
.rollId(ttRoll.getId())
|
||||
.createTime(new Timestamp(System.currentTimeMillis()))
|
||||
.holderUserId(userPrize.getUserId())
|
||||
.ornamentsPrice(userPrize.getPrice())
|
||||
.imageUrl(userPrize.getImgUrl())
|
||||
.ornamentId(userPrize.getOrnamentId())
|
||||
.source(TtboxRecordSource.ROLL.getCode())
|
||||
.userId(userPrize.getUserId())
|
||||
.updateTime(new Timestamp(System.currentTimeMillis()))
|
||||
.status(IN_PACKSACK_ON.getCode())
|
||||
.build();
|
||||
res.add(boxRecords);
|
||||
|
||||
}
|
||||
|
||||
// 在所有奖品中减去当前用户获得的奖品
|
||||
for (Long ornamentId : AllPrizePool.keySet()) {
|
||||
if (ornamentId.equals(userPrize.getOrnamentId())) {
|
||||
// 减去
|
||||
TtRollJackpotOrnaments ornaments = AllPrizePool.get(ornamentId);
|
||||
int i = ornaments.getOrnamentsNum() - userPrize.getNumber();
|
||||
ornaments.setOrnamentsNum(Math.max(i, 0));
|
||||
AllPrizePool.put(ornamentId, ornaments);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// 保存已分配
|
||||
boxRecordsService.saveBatch(res, 1);
|
||||
|
||||
return AllPrizePool;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<RollListDataVO> getRollList(GetRollListParam param) {
|
||||
|
||||
List<RollListDataVO> rollList = apiRollMapper.getRollList(param);
|
||||
|
||||
if (CollectionUtils.isEmpty(rollList)) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
// 对数据进行处理
|
||||
rollList.forEach(item -> {
|
||||
// 补充奖池信息
|
||||
TtRoll roll = this.getById(item.getId());
|
||||
List<SimpleRollOrnamentVO> prizeList = ttRollJackpotOrnamentsMapper.rollShow(roll.getJackpotId());
|
||||
item.setOrnamentsList(JSONUtil.toJsonStr(prizeList));
|
||||
if (CollectionUtils.isNotEmpty(prizeList)) {
|
||||
Integer ornamentsNumberOfRoll = ttRollJackpotOrnamentsMapper.ornamentsNumberOfRoll(prizeList.get(0).getJackpotId());
|
||||
item.setOrnamentsNum(ornamentsNumberOfRoll);
|
||||
}
|
||||
|
||||
if (!StringUtils.isBlank(item.getRollPassword())) {
|
||||
item.setHasPW(true);
|
||||
item.setRollPassword(null);
|
||||
} else {
|
||||
item.setHasPW(false);
|
||||
}
|
||||
});
|
||||
|
||||
return rollList;
|
||||
}
|
||||
|
||||
@Override
|
||||
public R<RollDetailsDataVO> getRollDetails(Integer rollId) {
|
||||
|
||||
TtRoll ttRoll = getById(rollId);
|
||||
if (ObjectUtil.isEmpty(ttRoll)) return R.fail("不存在的roll房。");
|
||||
|
||||
RollDetailsDataVO data = apiRollMapper.getRollDetails(rollId);
|
||||
data.setHasPW(!StringUtils.isBlank(ttRoll.getRollPassword()));
|
||||
|
||||
// 成员
|
||||
// List<TtRollUser> list = new LambdaQueryChainWrapper<>(ttRollUserMapper)
|
||||
// .eq(TtRollUser::getRollId, rollId)
|
||||
// .list();
|
||||
// List<SimpleRollUserVO> players = list.stream().map(item -> {
|
||||
// SimpleRollUserVO playerVo = new SimpleRollUserVO();
|
||||
// BeanUtil.copyProperties(item, playerVo);
|
||||
// playerVo.setUserName(null);
|
||||
// return playerVo;
|
||||
// }).collect(Collectors.toList());
|
||||
// data.setPlayerList(players);
|
||||
|
||||
// 奖池
|
||||
List<SimpleRollOrnamentVO> prizeList = ttRollJackpotOrnamentsMapper.rollShow(ttRoll.getJackpotId());
|
||||
data.setJackpotOrnamentsDataList(prizeList);
|
||||
|
||||
// 获奖名单
|
||||
// List<TtBoxRecordsVO> boxRecords = ttBoxRecordsMapper.rollOpenPrize(rollId);
|
||||
// data.setOpenPrizeList(boxRecords);
|
||||
return R.ok(data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public R<List<RollUserVO>> getRollPlayers(GetRollPlayersParam param) {
|
||||
|
||||
param.setLimit((param.getPage() - 1) * param.getSize());
|
||||
|
||||
List<RollUserVO> collect = ttRollUserMapper.pageByRollId(param);
|
||||
|
||||
return R.ok(collect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public R<List<RollJackpotOrnamentsVO>> getRollPrizePool(GetRollPrizePool param) {
|
||||
|
||||
param.setLimit((param.getPage() - 1) * param.getSize());
|
||||
|
||||
TtRoll one = new LambdaQueryChainWrapper<>(ttRollMapper)
|
||||
.eq(TtRoll::getId, param.getRollId())
|
||||
.eq(TtRoll::getDelFlag, 0)
|
||||
.one();
|
||||
if (ObjectUtil.isNull(one)) return R.fail("不存在的roll房。");
|
||||
|
||||
param.setJackpotId(one.getJackpotId());
|
||||
List<RollJackpotOrnamentsVO> list = ttRollJackpotOrnamentsMapper.listByRollId(param);
|
||||
|
||||
return R.ok(list);
|
||||
}
|
||||
|
||||
@Override
|
||||
public R<List<TtBoxRecordsVO>> getRollOpenPrize(GetRollOpenPrizeParam param) {
|
||||
|
||||
param.setLimit((param.getPage() - 1) * param.getSize());
|
||||
|
||||
// 获奖名单
|
||||
List<TtBoxRecordsVO> boxRecords = ttBoxRecordsMapper.rollOpenPrize(param);
|
||||
return R.ok(boxRecords);
|
||||
}
|
||||
|
||||
private TtBoxRecords addBoxRecordsData(Integer rollId, Long ornamentsId, Integer userId, TtRollJackpotOrnaments rollJackpotOrnaments) {
|
||||
TtOrnament ttOrnament = new LambdaQueryChainWrapper<>(ornamentsMapper).eq(TtOrnament::getId, ornamentsId).one();
|
||||
TtBoxRecords boxRecords = TtBoxRecords.builder().build();
|
||||
boxRecords.setUserId(userId);
|
||||
boxRecords.setOrnamentId(ornamentsId);
|
||||
boxRecords.setOrnamentsPrice(ttOrnament.getUsePrice());
|
||||
boxRecords.setOrnamentsLevelId(rollJackpotOrnaments.getOrnamentLevelId());
|
||||
boxRecords.setStatus(IN_PACKSACK_ON.getCode());
|
||||
boxRecords.setCreateTime(DateUtils.getNowDate());
|
||||
boxRecords.setSource(TtboxRecordSource.ROLL.getCode());
|
||||
boxRecords.setRollId(rollId);
|
||||
boxRecords.setHolderUserId(userId);
|
||||
return boxRecords;
|
||||
}
|
||||
|
||||
private TtRollJackpotOrnaments getRollJackpotOrnaments(Long ornamentsId, Map<Long, TtRollJackpotOrnaments> map, Integer jackpotId) {
|
||||
TtRollJackpotOrnaments ttRollJackpotOrnaments = map.get(ornamentsId);
|
||||
if (ttRollJackpotOrnaments == null) {
|
||||
ttRollJackpotOrnaments = new LambdaQueryChainWrapper<>(rollJackpotOrnamentsMapper).eq(TtRollJackpotOrnaments::getJackpotId, jackpotId)
|
||||
.eq(TtRollJackpotOrnaments::getOrnamentsId, ornamentsId).one();
|
||||
map.put(ornamentsId, ttRollJackpotOrnaments);
|
||||
}
|
||||
return ttRollJackpotOrnaments;
|
||||
}
|
||||
|
||||
private List<Long> getSurplusOrnamentsList(Integer rollId, Integer jackpotId) {
|
||||
|
||||
// roll房奖池
|
||||
List<TtRollJackpotOrnaments> ornamentsList = new LambdaQueryChainWrapper<>(rollJackpotOrnamentsMapper)
|
||||
.eq(TtRollJackpotOrnaments::getJackpotId, jackpotId)
|
||||
.list();
|
||||
|
||||
Map<Long, Integer> data = new HashMap<>();
|
||||
for (TtRollJackpotOrnaments ornaments : ornamentsList) {
|
||||
data.put(ornaments.getOrnamentsId(), ornaments.getOrnamentsNum());
|
||||
}
|
||||
|
||||
// 打乱奖池
|
||||
List<Long> surplusOrnamentsList = RandomUtils.toList(data);
|
||||
|
||||
// 系统指定的获奖者
|
||||
List<TtRollUser> allocatedRollUserList = new LambdaQueryChainWrapper<>(rollUserService.getBaseMapper())
|
||||
.eq(TtRollUser::getRollId, rollId)
|
||||
.eq(TtRollUser::getStatus, "2")
|
||||
.list();
|
||||
List<Long> allocated = allocatedRollUserList.stream().map(TtRollUser::getOrnamentsId).collect(Collectors.toList());
|
||||
|
||||
for (Long i : allocated) {
|
||||
Iterator<Long> iterator = surplusOrnamentsList.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
Long next = iterator.next();
|
||||
if (Objects.equals(next, i)) {
|
||||
iterator.remove();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return surplusOrnamentsList;
|
||||
}
|
||||
|
||||
private BigDecimal getRechargeTotalAmount(Integer userId, Date rechargeStartTime) {
|
||||
LambdaQueryChainWrapper<TtRechargeRecord> wrapper = new LambdaQueryChainWrapper<>(rechargeRecordMapper).eq(TtRechargeRecord::getUserId, userId);
|
||||
if (StringUtils.isNotNull(rechargeStartTime)) wrapper.gt(TtRechargeRecord::getCreateTime, rechargeStartTime);
|
||||
return wrapper.list().stream().map(TtRechargeRecord::getAmountActuallyPaid).reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
package com.ruoyi.playingmethod.service.impl;
|
||||
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
|
||||
import com.ruoyi.admin.service.TtUserService;
|
||||
import com.ruoyi.common.core.domain.R;
|
||||
import com.ruoyi.domain.dto.upgrade.UpgradeCondition;
|
||||
import com.ruoyi.domain.entity.sys.TtUser;
|
||||
import com.ruoyi.domain.other.*;
|
||||
import com.ruoyi.playingmethod.mapper.ApiUpgradeRecordMapper;
|
||||
|
||||
import com.ruoyi.playingmethod.service.ApiUpgradeRecordService;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
|
||||
@Service
|
||||
@Slf4j
|
||||
public class ApiUpgradeRecordServiceImpl extends ServiceImpl<ApiUpgradeRecordMapper, TtUpgradeRecord> implements ApiUpgradeRecordService {
|
||||
|
||||
|
||||
@Autowired
|
||||
TtUserService userService;
|
||||
|
||||
@Override
|
||||
public R historyDetail(UpgradeCondition param) {
|
||||
|
||||
Page<TtUpgradeRecord> pageInfo = new Page<>(param.getPage(), param.getSize());
|
||||
pageInfo.setOptimizeCountSql(false);
|
||||
|
||||
LambdaQueryWrapper<TtUpgradeRecord> wrapper = new LambdaQueryWrapper<>();
|
||||
|
||||
wrapper.eq(ObjectUtil.isNotNull(param.getUpgradeRecordId()),TtUpgradeRecord::getId,param.getUpgradeRecordId());
|
||||
|
||||
wrapper.eq(ObjectUtil.isNotNull(param.getOrnamentId()),TtUpgradeRecord::getTargetOrnamentId,param.getOrnamentId());
|
||||
|
||||
wrapper.eq(ObjectUtil.isNotNull(param.getUserType()),TtUpgradeRecord::getUserType,param.getUserType());
|
||||
|
||||
wrapper.eq(ObjectUtil.isNotNull(param.getUserId()),TtUpgradeRecord::getUserId,param.getUserId());
|
||||
wrapper.orderByDesc(TtUpgradeRecord::getOpenTime);
|
||||
|
||||
pageInfo = this.page(pageInfo, wrapper);
|
||||
|
||||
if (pageInfo.getRecords().size() == 0){
|
||||
return R.ok(pageInfo);
|
||||
}
|
||||
|
||||
Set<Integer> userIds = pageInfo.getRecords().stream().map(TtUpgradeRecord::getUserId).collect(Collectors.toSet());
|
||||
|
||||
//<2F><>װ<EFBFBD>û<EFBFBD>ͷ<EFBFBD><CDB7>
|
||||
List<TtUser> list = userService.list(Wrappers.lambdaQuery(TtUser.class)
|
||||
.in(TtUser::getUserId, userIds));
|
||||
//ͷ<><CDB7>map
|
||||
Map<Integer, String> avatarMap = list.stream().collect(Collectors.toMap(TtUser::getUserId, TtUser::getAvatar));
|
||||
pageInfo.getRecords().forEach(r->{
|
||||
if (r.getUserId() !=null){
|
||||
r.setUserAvatar(avatarMap.get(r.getUserId()));
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
return R.ok(pageInfo);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public R tenTopDetail(Boolean isVictory) {
|
||||
Page<TtUpgradeRecord> pageInfo = new Page<>(1, 10);
|
||||
pageInfo.setOptimizeCountSql(false);
|
||||
LambdaQueryWrapper<TtUpgradeRecord> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(isVictory != null, TtUpgradeRecord::getIsVictory, isVictory);
|
||||
wrapper.orderByDesc(TtUpgradeRecord::getTargetOrnamentPrice);
|
||||
pageInfo = this.page(pageInfo, wrapper);
|
||||
if (pageInfo.getRecords().size() == 0){
|
||||
return R.ok(pageInfo);
|
||||
}
|
||||
Set<Integer> userIds = pageInfo.getRecords().stream().map(TtUpgradeRecord::getUserId).collect(Collectors.toSet());
|
||||
List<TtUser> list = userService.list(Wrappers.lambdaQuery(TtUser.class)
|
||||
.in(TtUser::getUserId, userIds));
|
||||
Map<Integer, String> avatarMap = list.stream().collect(Collectors.toMap(TtUser::getUserId, TtUser::getAvatar));
|
||||
pageInfo.getRecords().forEach(r->{
|
||||
if (r.getUserId() !=null){
|
||||
r.setUserAvatar(avatarMap.get(r.getUserId()));
|
||||
}
|
||||
});
|
||||
return R.ok(pageInfo);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.ruoyi.playingmethod.service.impl;
|
||||
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.ruoyi.domain.entity.TtUserBlendErcash;
|
||||
import com.ruoyi.playingmethod.mapper.ApiTtUserBlendErcashMapper;
|
||||
|
||||
import com.ruoyi.playingmethod.service.ApiUserBlendErcashService;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
|
||||
@Service
|
||||
@Slf4j
|
||||
public class ApiUserBlendErcashServiceImpl extends ServiceImpl<ApiTtUserBlendErcashMapper, TtUserBlendErcash> implements ApiUserBlendErcashService {
|
||||
}
|
||||
@@ -0,0 +1,147 @@
|
||||
package com.ruoyi.playingmethod.service.impl;
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import com.ruoyi.admin.mapper.TtWelfareMonthlyRechargesMapper;
|
||||
import com.ruoyi.admin.service.TtBoxRecordsService;
|
||||
import com.ruoyi.admin.service.TtBoxService;
|
||||
import com.ruoyi.admin.service.TtUserService;
|
||||
import com.ruoyi.admin.util.core.fight.LotteryMachine;
|
||||
import com.ruoyi.domain.common.constant.TtboxRecordSource;
|
||||
import com.ruoyi.domain.common.constant.TtboxRecordStatus;
|
||||
import com.ruoyi.domain.entity.TtBoxRecords;
|
||||
import com.ruoyi.domain.entity.sys.TtUser;
|
||||
import com.ruoyi.domain.other.TtBox;
|
||||
import com.ruoyi.domain.other.TtOrnamentsA;
|
||||
import com.ruoyi.domain.other.TtWelfareMonthlyRecharges;
|
||||
import com.ruoyi.domain.vo.OpenBoxVO;
|
||||
import com.ruoyi.playingmethod.mapper.ApiBindBoxMapper;
|
||||
import com.ruoyi.playingmethod.mapper.ApiWelfareMonthlyRechargesMapper;
|
||||
import com.ruoyi.playingmethod.model.ApiWelfare;
|
||||
import com.ruoyi.playingmethod.model.ApiWelfareRecord;
|
||||
import com.ruoyi.playingmethod.model.vo.ApiWelfareMonthlyRechargesVO;
|
||||
import com.ruoyi.playingmethod.service.ApiWelfareMonthlyRechargesService;
|
||||
import com.ruoyi.playingmethod.utils.customException.OrnamentNullException;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.sql.Timestamp;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
@Service
|
||||
public class ApiWelfareMonthlyRechargesServiceImpl implements ApiWelfareMonthlyRechargesService {
|
||||
|
||||
@Autowired
|
||||
private ApiWelfareMonthlyRechargesMapper apiWelfareMonthlyRechargesMapper;
|
||||
|
||||
@Autowired
|
||||
private TtUserService ttUserService;
|
||||
|
||||
@Autowired
|
||||
private TtBoxService ttBoxService;
|
||||
|
||||
@Autowired
|
||||
private LotteryMachine lotteryMachine;
|
||||
|
||||
@Autowired
|
||||
private ApiBindBoxMapper bindBoxMapper;
|
||||
|
||||
@Autowired
|
||||
private TtBoxRecordsService boxRecordsService;
|
||||
|
||||
@Autowired
|
||||
private TtWelfareMonthlyRechargesMapper ttWelfareMonthlyRechargesMapper;
|
||||
|
||||
@Override
|
||||
public List<ApiWelfareMonthlyRechargesVO> getWelfareList(Long userId) {
|
||||
List<ApiWelfareMonthlyRechargesVO> apiWelfareMonthlyRechargesVOS =
|
||||
apiWelfareMonthlyRechargesMapper.getWelfareList(userId);
|
||||
for (ApiWelfareMonthlyRechargesVO apiWelfareMonthlyRechargesVO : apiWelfareMonthlyRechargesVOS) {
|
||||
// 检查领取条件
|
||||
// BigDecimal rechargeRecordsOfMonth = apiWelfareMonthlyRechargesMapper.selectRechargeRecordsOfMonth(userId);
|
||||
// if (rechargeRecordsOfMonth.compareTo(apiWelfareMonthlyRechargesVO.getAmount()) >= 0) {
|
||||
// apiWelfareMonthlyRechargesVO.setEligible("1");
|
||||
// } else {
|
||||
// apiWelfareMonthlyRechargesVO.setEligible("0");
|
||||
// }
|
||||
if (checkEligible(apiWelfareMonthlyRechargesVO.getWelfareId(), userId))
|
||||
apiWelfareMonthlyRechargesVO.setEligible("1");
|
||||
else
|
||||
apiWelfareMonthlyRechargesVO.setEligible("0");
|
||||
// 检查是否领取
|
||||
boolean isClaimed = apiWelfareMonthlyRechargesMapper.checkClaimed(
|
||||
apiWelfareMonthlyRechargesVO.getWelfareId(),
|
||||
userId,
|
||||
"2");
|
||||
apiWelfareMonthlyRechargesVO.setClaimStatus(isClaimed ? "1" : "0");
|
||||
}
|
||||
return apiWelfareMonthlyRechargesVOS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public OpenBoxVO claimWelfare(Integer welfareId, Long userId) {
|
||||
// 1.获取福利对应的宝箱信息
|
||||
Integer boxId = apiWelfareMonthlyRechargesMapper.getBoxIdByWelfareId(welfareId);
|
||||
TtUser ttUser = ttUserService.getById(userId);
|
||||
TtBox ttBox = ttBoxService.getById(boxId);
|
||||
// 2.抽奖
|
||||
String ornamentId = lotteryMachine.singleLottery(ttUser, ttBox);
|
||||
if (Objects.isNull(ornamentId)) {
|
||||
throw new OrnamentNullException("福利开箱未抽中");
|
||||
}
|
||||
// 3.获取宝箱详细信息
|
||||
TtOrnamentsA ornamentsData = bindBoxMapper.ornamentsInfo(boxId, ornamentId);
|
||||
if (Objects.isNull(ornamentsData)) {
|
||||
throw new OrnamentNullException("福利开箱未抽中");
|
||||
}
|
||||
// 4.构建并存储开箱记录
|
||||
TtBoxRecords ttBoxRecords = new TtBoxRecords();
|
||||
ttBoxRecords.setUserId(ttUser.getUserId());
|
||||
ttBoxRecords.setBoxId(ttBox.getBoxId());
|
||||
ttBoxRecords.setBoxName(ttBox.getBoxName());
|
||||
ttBoxRecords.setBoxPrice(ttBox.getPrice());
|
||||
ttBoxRecords.setOrnamentId(Long.valueOf(ornamentId));
|
||||
ttBoxRecords.setOrnamentName(ornamentsData.getName());
|
||||
ttBoxRecords.setImageUrl(ornamentsData.getImageUrl());
|
||||
ttBoxRecords.setOrnamentsPrice(ornamentsData.getUsePrice());
|
||||
ttBoxRecords.setOrnamentsLevelId(ornamentsData.getOrnamentsLevelId());
|
||||
ttBoxRecords.setOrnamentLevelImg(ornamentsData.getLevelImg());
|
||||
ttBoxRecords.setHolderUserId(ttUser.getUserId());
|
||||
ttBoxRecords.setSource(TtboxRecordSource.BLIND_BOX.getCode());
|
||||
ttBoxRecords.setStatus(TtboxRecordStatus.IN_PACKSACK_ON.getCode());
|
||||
ttBoxRecords.setCreateTime(new Timestamp(System.currentTimeMillis()));
|
||||
boxRecordsService.save(ttBoxRecords);
|
||||
// 5.存储领取记录
|
||||
ApiWelfareRecord apiWelfareRecord = new ApiWelfareRecord();
|
||||
apiWelfareRecord.setWelfareId(welfareId);
|
||||
apiWelfareRecord.setUserId(userId);
|
||||
apiWelfareRecord.setType("2");
|
||||
apiWelfareRecord.setCreateTime(new Date());
|
||||
apiWelfareMonthlyRechargesMapper.saveClaimWelfareRecord(apiWelfareRecord);
|
||||
// 6.返回前端数据
|
||||
OpenBoxVO openBoxVO = new OpenBoxVO();
|
||||
BeanUtil.copyProperties(ttBoxRecords, openBoxVO);
|
||||
openBoxVO.setUsePrice(openBoxVO.getOrnamentsPrice());
|
||||
openBoxVO.setLevelImg(ttBoxRecords.getOrnamentLevelImg());
|
||||
return openBoxVO;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkEligible(Integer welfareId, Long userId) {
|
||||
BigDecimal rechargeRecordsOfMonth = apiWelfareMonthlyRechargesMapper.selectRechargeRecordsOfMonth(userId);
|
||||
if (Objects.isNull(rechargeRecordsOfMonth))
|
||||
return false;
|
||||
TtWelfareMonthlyRecharges ttWelfareMonthlyRecharges = ttWelfareMonthlyRechargesMapper.selectTtWelfareMonthlyRechargesById(welfareId);
|
||||
TtUser ttUser = ttUserService.getById(userId);
|
||||
boolean isRechargeAmountSufficient = rechargeRecordsOfMonth.compareTo(ttWelfareMonthlyRecharges.getAmount()) >= 0;
|
||||
boolean isVipLevelSufficient = ttUser.getVipLevel() >= ttWelfareMonthlyRecharges.getVipLevel();
|
||||
return isRechargeAmountSufficient && isVipLevelSufficient;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkClaimed(Integer welfareId, Long userId) {
|
||||
return apiWelfareMonthlyRechargesMapper.checkClaimed(welfareId, userId, "2");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,141 @@
|
||||
package com.ruoyi.playingmethod.service.impl;
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import com.ruoyi.admin.mapper.TtWelfareMapper;
|
||||
import com.ruoyi.admin.service.TtBoxRecordsService;
|
||||
import com.ruoyi.admin.service.TtBoxService;
|
||||
import com.ruoyi.admin.service.TtUserService;
|
||||
import com.ruoyi.admin.util.core.fight.LotteryMachine;
|
||||
import com.ruoyi.domain.common.constant.TtboxRecordSource;
|
||||
import com.ruoyi.domain.common.constant.TtboxRecordStatus;
|
||||
import com.ruoyi.domain.entity.TtBoxRecords;
|
||||
import com.ruoyi.domain.entity.sys.TtUser;
|
||||
import com.ruoyi.domain.other.TtBox;
|
||||
import com.ruoyi.domain.other.TtOrnamentsA;
|
||||
import com.ruoyi.domain.other.TtWelfare;
|
||||
import com.ruoyi.domain.vo.OpenBoxVO;
|
||||
import com.ruoyi.playingmethod.mapper.ApiBindBoxMapper;
|
||||
import com.ruoyi.playingmethod.mapper.ApiWelfareMapper;
|
||||
import com.ruoyi.playingmethod.model.ApiWelfare;
|
||||
import com.ruoyi.playingmethod.model.ApiWelfareRecord;
|
||||
import com.ruoyi.playingmethod.service.ApiWelfareService;
|
||||
import com.ruoyi.playingmethod.utils.customException.OrnamentNullException;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.sql.Timestamp;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
@Service
|
||||
public class ApiWelfareServiceImpl implements ApiWelfareService {
|
||||
|
||||
@Autowired
|
||||
private ApiWelfareMapper apiWelfareMapper;
|
||||
|
||||
@Autowired
|
||||
private TtUserService ttUserService;
|
||||
|
||||
@Autowired
|
||||
private TtBoxService ttBoxService;
|
||||
|
||||
@Autowired
|
||||
private LotteryMachine lotteryMachine;
|
||||
|
||||
@Autowired
|
||||
private ApiBindBoxMapper bindBoxMapper;
|
||||
|
||||
@Autowired
|
||||
private TtBoxRecordsService boxRecordsService;
|
||||
|
||||
@Autowired
|
||||
private TtWelfareMapper ttWelfareMapper;
|
||||
|
||||
@Override
|
||||
public List<ApiWelfare> getWelfareList(Long userId) {
|
||||
List<ApiWelfare> welfareList = apiWelfareMapper.getWelfareList(userId);
|
||||
for (ApiWelfare apiWelfare : welfareList) {
|
||||
if ("1".equals(apiWelfare.getType())) {
|
||||
boolean isEligible = checkVipUpgradeEligibility(userId, apiWelfare.getVipLevel());
|
||||
apiWelfare.setEligible(isEligible ? "1" : "0");
|
||||
boolean isClaimed = apiWelfareMapper.checkClaimed(apiWelfare.getWelfareId(), userId, "1");
|
||||
apiWelfare.setClaimStatus(isClaimed ? "1" : "0");
|
||||
}
|
||||
}
|
||||
return welfareList;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@Override
|
||||
public OpenBoxVO claimWelfare(Integer welfareId, Long userId) {
|
||||
// 1.获取福利对应的宝箱信息
|
||||
Integer boxId = apiWelfareMapper.getBoxIdByWelfareId(welfareId);
|
||||
TtUser ttUser = ttUserService.getById(userId);
|
||||
TtBox ttBox = ttBoxService.getById(boxId);
|
||||
// 2.抽奖
|
||||
String ornamentId = lotteryMachine.singleLottery(ttUser, ttBox);
|
||||
if (Objects.isNull(ornamentId)) {
|
||||
throw new OrnamentNullException("福利开箱未抽中");
|
||||
}
|
||||
// 3.获取宝箱详细信息
|
||||
TtOrnamentsA ornamentsData = bindBoxMapper.ornamentsInfo(boxId, ornamentId);
|
||||
if (Objects.isNull(ornamentsData)) {
|
||||
throw new OrnamentNullException("福利开箱未抽中");
|
||||
}
|
||||
// 4.构建并存储开箱记录
|
||||
TtBoxRecords ttBoxRecords = new TtBoxRecords();
|
||||
ttBoxRecords.setUserId(ttUser.getUserId());
|
||||
ttBoxRecords.setBoxId(ttBox.getBoxId());
|
||||
ttBoxRecords.setBoxName(ttBox.getBoxName());
|
||||
ttBoxRecords.setBoxPrice(ttBox.getPrice());
|
||||
ttBoxRecords.setOrnamentId(Long.valueOf(ornamentId));
|
||||
ttBoxRecords.setOrnamentName(ornamentsData.getName());
|
||||
ttBoxRecords.setImageUrl(ornamentsData.getImageUrl());
|
||||
ttBoxRecords.setOrnamentsPrice(ornamentsData.getUsePrice());
|
||||
ttBoxRecords.setOrnamentsLevelId(ornamentsData.getOrnamentsLevelId());
|
||||
ttBoxRecords.setOrnamentLevelImg(ornamentsData.getLevelImg());
|
||||
ttBoxRecords.setHolderUserId(ttUser.getUserId());
|
||||
ttBoxRecords.setSource(TtboxRecordSource.BLIND_BOX.getCode());
|
||||
ttBoxRecords.setStatus(TtboxRecordStatus.IN_PACKSACK_ON.getCode());
|
||||
ttBoxRecords.setCreateTime(new Timestamp(System.currentTimeMillis()));
|
||||
boxRecordsService.save(ttBoxRecords);
|
||||
// 5.存储领取记录
|
||||
ApiWelfareRecord apiWelfareRecord = new ApiWelfareRecord();
|
||||
apiWelfareRecord.setWelfareId(welfareId);
|
||||
apiWelfareRecord.setUserId(userId);
|
||||
apiWelfareRecord.setType("1");
|
||||
apiWelfareRecord.setCreateTime(new Date());
|
||||
apiWelfareMapper.saveClaimWelfareRecord(apiWelfareRecord);
|
||||
// 6.返回前端数据
|
||||
OpenBoxVO openBoxVO = new OpenBoxVO();
|
||||
BeanUtil.copyProperties(ttBoxRecords, openBoxVO);
|
||||
openBoxVO.setUsePrice(openBoxVO.getOrnamentsPrice());
|
||||
openBoxVO.setLevelImg(ttBoxRecords.getOrnamentLevelImg());
|
||||
return openBoxVO;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkNotEligible(Integer welfareId, Long userId) {
|
||||
TtWelfare ttWelfare = ttWelfareMapper.selectTtWelfareByWelfareId(welfareId);
|
||||
if ("1".equals(ttWelfare.getType())) {
|
||||
return !checkVipUpgradeEligibility(userId, ttWelfare.getVipLevel());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkClaimed(Integer welfareId, Long userId) {
|
||||
return apiWelfareMapper.checkClaimed(welfareId, userId, "1");
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查是否具备VIP等级福利领取条件
|
||||
*/
|
||||
private boolean checkVipUpgradeEligibility(Long userId, Integer vipLevel) {
|
||||
TtUser ttUser = ttUserService.getById(userId);
|
||||
return ttUser.getVipLevel() >= vipLevel;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package com.ruoyi.playingmethod.utils.Constant;
|
||||
|
||||
public enum OPPS {
|
||||
// 展示爆率
|
||||
OPPS,
|
||||
// 真实爆率
|
||||
REAL_OPPS,
|
||||
// 主播爆率
|
||||
ANCHOR_ODDS;
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
package com.ruoyi.playingmethod.utils.Constant;
|
||||
|
||||
public enum RedisLockKey {
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.ruoyi.playingmethod.utils.customException;
|
||||
|
||||
public class OrnamentNullException extends RuntimeException {
|
||||
public OrnamentNullException(String msg){
|
||||
super(msg);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
package com.ruoyi.playingmethod.websocket;
|
||||
|
||||
import com.ruoyi.playingmethod.websocket.entity.SessionData;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
public class WebSocketUsers {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(WebSocketUsers.class);
|
||||
|
||||
private static Map<String, SessionData> USERS = new ConcurrentHashMap<String, SessionData>();
|
||||
|
||||
public static void put(String key, SessionData sessionData) {
|
||||
USERS.put(key, sessionData);
|
||||
}
|
||||
|
||||
public static boolean remove(SessionData sessionData) {
|
||||
String key = null;
|
||||
boolean flag = USERS.containsValue(sessionData);
|
||||
if (flag) {
|
||||
Set<Map.Entry<String, SessionData>> entries = USERS.entrySet();
|
||||
for (Map.Entry<String, SessionData> entry : entries) {
|
||||
SessionData value = entry.getValue();
|
||||
if (value.getSession().equals(sessionData.getSession())) {
|
||||
key = entry.getKey();
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
return remove(key);
|
||||
}
|
||||
|
||||
public static boolean remove(String key) {
|
||||
LOGGER.info("\n 正在移出用户 - {}", key);
|
||||
SessionData remove = USERS.remove(key);
|
||||
if (remove.getSession() != null) {
|
||||
boolean containsValue = USERS.containsValue(remove);
|
||||
LOGGER.info("\n 移出结果 - {}", containsValue ? "失败" : "成功");
|
||||
LOGGER.info("\n 当前人数 - {}", WebSocketUsers.getUsers().size());
|
||||
return containsValue;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public static Map<String, SessionData> getUsers() {
|
||||
return USERS;
|
||||
}
|
||||
|
||||
public static void sendMessageToUsersByText(String message) {
|
||||
Collection<SessionData> values = USERS.values();
|
||||
for (SessionData value : values) {
|
||||
try {
|
||||
value.getSession().getBasicRemote().sendText(message);
|
||||
} catch (IOException e) {
|
||||
//LOGGER.error("\n[发送消息异常]", e);
|
||||
LOGGER.error("\n[发送消息异常]");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void sendMessageToUserByText(Integer userId, String message) {
|
||||
Collection<SessionData> values = USERS.values();
|
||||
if (userId == 0) {
|
||||
for (SessionData value : values) {
|
||||
if (value.getSession() != null && Objects.equals(value.getUserId(), userId)) {
|
||||
try {
|
||||
value.getSession().getBasicRemote().sendText(message);
|
||||
} catch (IOException e) {
|
||||
LOGGER.error("\n[发送消息异常]", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (SessionData value : values) {
|
||||
if (value.getSession() != null && Objects.equals(value.getUserId(), userId)) {
|
||||
try {
|
||||
value.getSession().getBasicRemote().sendText(message);
|
||||
return;
|
||||
} catch (IOException e) {
|
||||
LOGGER.error("\n[发送消息异常]", e);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,233 @@
|
||||
package com.ruoyi.playingmethod.websocket;
|
||||
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
|
||||
import com.ruoyi.admin.mapper.TtUserMapper;
|
||||
import com.ruoyi.admin.service.TtBoxService;
|
||||
import com.ruoyi.admin.service.TtUserService;
|
||||
import com.ruoyi.common.core.domain.R;
|
||||
import com.ruoyi.domain.common.constant.TtboxRecordSource;
|
||||
import com.ruoyi.domain.common.constant.TtboxRecordStatus;
|
||||
import com.ruoyi.domain.common.constant.sys.UserStatus;
|
||||
import com.ruoyi.domain.dto.boxRecords.queryCondition;
|
||||
import com.ruoyi.domain.entity.sys.TtUser;
|
||||
import com.ruoyi.domain.other.TtBox;
|
||||
import com.ruoyi.domain.vo.boxRecords.TtBoxRecordsVO;
|
||||
import com.ruoyi.playingmethod.service.ApiBoxRecordsService;
|
||||
import com.ruoyi.playingmethod.websocket.constant.SMsgKey;
|
||||
import com.ruoyi.playingmethod.websocket.util.WsResult;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import jakarta.websocket.*;
|
||||
import jakarta.websocket.server.PathParam;
|
||||
import jakarta.websocket.server.ServerEndpoint;
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* 绑定箱子
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
@ServerEndpoint("/ws/bindBox/{boxId}/{userId}")
|
||||
public class WsBindBox {
|
||||
|
||||
// 用来记录当前连接数的变量
|
||||
private static volatile int onlineCount = 0;
|
||||
// concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象
|
||||
private static ConcurrentHashMap<String, WsBindBox> allRoomUserMap = new ConcurrentHashMap<>();
|
||||
// 与某个客户端的连接会话,需要通过它来与客户端进行数据收发
|
||||
private Session session;
|
||||
private static ApiBoxRecordsService apiBoxRecordsService;
|
||||
private static TtBoxService boxService;
|
||||
private static TtUserService userService;
|
||||
private static TtUserMapper userMapper;
|
||||
private Integer userId = null;
|
||||
private Integer boxId = null;
|
||||
private String key = "";
|
||||
|
||||
@Autowired
|
||||
public void ttFightService(ApiBoxRecordsService apiBoxRecordsService){
|
||||
WsBindBox.apiBoxRecordsService = apiBoxRecordsService;
|
||||
}
|
||||
|
||||
@Autowired
|
||||
public void ttFightService(TtBoxService boxService){
|
||||
WsBindBox.boxService = boxService;
|
||||
}
|
||||
|
||||
@Autowired
|
||||
public void ttFightService(TtUserService userService){
|
||||
WsBindBox.userService = userService;
|
||||
}
|
||||
|
||||
@Autowired
|
||||
public void ttFightService(TtUserMapper userMapper){
|
||||
WsBindBox.userMapper = userMapper;
|
||||
}
|
||||
|
||||
@OnOpen
|
||||
public void onOpen(Session session,
|
||||
@PathParam("boxId") Integer boxId,
|
||||
@PathParam("userId") Integer userId) throws IOException {
|
||||
// 更新连接池
|
||||
addBoxRoomUser(userId, boxId, session);
|
||||
|
||||
// 用户信息
|
||||
TtUser player = new LambdaQueryChainWrapper<>(userMapper)
|
||||
.eq(TtUser::getUserId, userId)
|
||||
.eq(TtUser::getStatus, UserStatus.NORMAL.getCode())
|
||||
.eq(TtUser::getDelFlag, 0)
|
||||
.one();
|
||||
// 检查连接
|
||||
R check = connectCheck(player, boxId);
|
||||
if (!check.getCode().equals(200)) {
|
||||
session.getBasicRemote().sendText(check.getMsg());
|
||||
session.close();
|
||||
return;
|
||||
}
|
||||
|
||||
log.debug("/ws/bindBox > > onOpen");
|
||||
log.info("用户{}进入盲盒游戏房间,在线人数{}", userId, WsBindBox.onlineCount);
|
||||
sendMessage("用户" + userId + "进入盲盒游戏房间,在线人数" + WsBindBox.onlineCount);
|
||||
|
||||
// 首次连接获取最新的一组盲盒开箱数据
|
||||
List<Integer> sources = Arrays.asList(TtboxRecordSource.BLIND_BOX.getCode());
|
||||
List<Integer> status = Arrays.asList(
|
||||
TtboxRecordStatus.IN_PACKSACK_ON.getCode(),
|
||||
TtboxRecordStatus.DELIVERY_YET.getCode(),
|
||||
TtboxRecordStatus.APPLY_DELIVERY.getCode(),
|
||||
TtboxRecordStatus.RESOLVE.getCode());
|
||||
queryCondition param = queryCondition.builder()
|
||||
.boxId(boxId)
|
||||
// .userType(player.getUserType())
|
||||
.source(sources)
|
||||
.status(status)
|
||||
.orderByFie(0)
|
||||
.page(1)
|
||||
.size(10)
|
||||
.build();
|
||||
List<TtBoxRecordsVO> ttBoxRecordsVOS = apiBoxRecordsService.byCondition(param);
|
||||
|
||||
sendMessage(WsResult.ok(SMsgKey.Blind_Box_Init_Data.name(),ttBoxRecordsVOS,"初始化历史开箱记录"));
|
||||
}
|
||||
|
||||
@OnClose
|
||||
public void onClose(Session session) {
|
||||
removeRoomUser();
|
||||
log.info("关闭连接,正常在线人数:" + WsBindBox.onlineCount);
|
||||
}
|
||||
|
||||
@OnMessage
|
||||
public void onMessage(String message, Session session) {
|
||||
log.info("收到消息");
|
||||
}
|
||||
|
||||
@OnError
|
||||
public void onError(Session session, Throwable exception) throws Exception {
|
||||
log.info("出现错误");
|
||||
}
|
||||
|
||||
/**
|
||||
* 连接检查
|
||||
*/
|
||||
private R connectCheck(TtUser player, Integer boxId) {
|
||||
if (ObjectUtil.isNotEmpty(WsFightRoom.allRoomUserMap.get(player.getUserId() + "_" + boxId))) {
|
||||
R.fail("用户" + player.getUserId() + "已经连接宝箱房间" + boxId + "。请勿重复调用。");
|
||||
}
|
||||
TtBox box = boxService.getById(boxId);
|
||||
if (ObjectUtil.isEmpty(box)) {
|
||||
return R.fail("不存在的宝箱,id:" + boxId);
|
||||
}
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新在线人数
|
||||
*/
|
||||
private int addOnlineCount(int number) {
|
||||
synchronized (this){
|
||||
WsBindBox.onlineCount += number;
|
||||
return WsBindBox.onlineCount;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 全局广播
|
||||
*/
|
||||
public static void broadcast(Object message) {
|
||||
|
||||
// ObjectMapper objectMapper = new ObjectMapper();
|
||||
String msg = JSON.toJSONString(message);
|
||||
|
||||
Collection<WsBindBox> wss = WsBindBox.allRoomUserMap.values();
|
||||
for (WsBindBox ws : wss){
|
||||
try {
|
||||
ws.session.getBasicRemote().sendText(msg);
|
||||
} catch (IOException e) {
|
||||
log.warn("WS大厅广播消息异常。错误信息:{}", msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 房间广播
|
||||
*/
|
||||
public static void broadcastToBoxRoom(Integer boxId, Object message) {
|
||||
|
||||
String msg = JSON.toJSONString(message);
|
||||
|
||||
Collection<WsBindBox> wslist = WsBindBox.allRoomUserMap.values();
|
||||
|
||||
for (WsBindBox ws : wslist) {
|
||||
try {
|
||||
if (!ws.boxId.equals(boxId)) continue;
|
||||
// log.info(String.valueOf(ws.session.isOpen()));
|
||||
if (!ws.session.isOpen()) continue;
|
||||
RemoteEndpoint.Basic basicRemote = ws.session.getBasicRemote();
|
||||
basicRemote.sendText(msg);
|
||||
} catch (IOException e) {
|
||||
log.warn("WS推送广播给{}_{}消息异常。", ws.userId, ws.boxId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 实现服务器主动推送
|
||||
*/
|
||||
public void sendMessage(Object message) {
|
||||
try {
|
||||
this.session.getBasicRemote().sendText(JSON.toJSONString(message));
|
||||
} catch (IOException e) {
|
||||
log.warn("服务器推送消息异常。");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加连接用户
|
||||
*/
|
||||
private WsBindBox addBoxRoomUser(Integer userId, Integer boxId, Session session) {
|
||||
addOnlineCount(1);
|
||||
this.userId = userId;
|
||||
this.boxId = boxId;
|
||||
this.key = userId + "_" + boxId;
|
||||
this.session = session;
|
||||
WsBindBox.allRoomUserMap.put(key, this);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 移除连接用户
|
||||
*/
|
||||
private WsBindBox removeRoomUser(){
|
||||
addOnlineCount(-1);
|
||||
WsBindBox.allRoomUserMap.remove(this.key);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,290 @@
|
||||
package com.ruoyi.playingmethod.websocket;
|
||||
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.ruoyi.admin.mapper.TtBoxMapper;
|
||||
import com.ruoyi.domain.entity.fight.TtFight;
|
||||
import com.ruoyi.domain.other.TtBox;
|
||||
import com.ruoyi.domain.vo.fight.FightBoxVO;
|
||||
import com.ruoyi.playingmethod.service.ApiFightService;
|
||||
import com.ruoyi.playingmethod.websocket.constant.SMsgKey;
|
||||
import com.ruoyi.playingmethod.websocket.util.WsResult;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.apache.commons.collections4.MapUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import jakarta.websocket.OnClose;
|
||||
import jakarta.websocket.OnError;
|
||||
import jakarta.websocket.OnMessage;
|
||||
import jakarta.websocket.OnOpen;
|
||||
import jakarta.websocket.Session;
|
||||
import jakarta.websocket.server.PathParam;
|
||||
import jakarta.websocket.server.ServerEndpoint;
|
||||
import java.io.IOException;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 对战大厅
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
@ServerEndpoint("/ws/fight/hall/{userId}")
|
||||
public class WsFightHall {
|
||||
|
||||
// 用来记录当前连接数的变量
|
||||
private static int onlineCount = 0;
|
||||
|
||||
public static synchronized void increaseOnlineCount() {
|
||||
onlineCount++;
|
||||
}
|
||||
|
||||
public static synchronized void decreaseOnlineCount() {
|
||||
if (onlineCount > 0) {
|
||||
onlineCount--;
|
||||
}
|
||||
}
|
||||
|
||||
// concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象
|
||||
private static ConcurrentHashMap<String, WsFightHall> allHallUserMap = new ConcurrentHashMap<>();
|
||||
// 与某个客户端的连接会话,需要通过它来与客户端进行数据收发
|
||||
private Session session;
|
||||
private static ApiFightService apiFightService;
|
||||
private String userId = "";
|
||||
|
||||
@Autowired
|
||||
public void ttFightService(ApiFightService apiFightService) {
|
||||
WsFightHall.apiFightService = apiFightService;
|
||||
}
|
||||
|
||||
private static TtBoxMapper ttBoxMapper;
|
||||
|
||||
@Autowired
|
||||
public void ttBoxMapper(TtBoxMapper ttBoxMapper) {
|
||||
WsFightHall.ttBoxMapper = ttBoxMapper;
|
||||
}
|
||||
|
||||
@OnOpen
|
||||
public void onOpen(Session session, @PathParam("userId") String userId) throws IOException {
|
||||
// 获取请求参数
|
||||
Map<String, List<String>> parameters = session.getRequestParameterMap();
|
||||
int pageNum = 1;
|
||||
int pageSize = 10;
|
||||
String status = null;
|
||||
String model = null;
|
||||
BigDecimal boxPriceTotalMin = null;
|
||||
BigDecimal boxPriceTotalMax = null;
|
||||
List<String> pageNums = parameters.get("pageNum");
|
||||
if (!Objects.isNull(pageNums) && !pageNums.isEmpty()) {
|
||||
pageNum = Integer.parseInt(pageNums.get(0));
|
||||
}
|
||||
List<String> pageSizes = parameters.get("pageSize");
|
||||
if (!Objects.isNull(pageSizes) && !pageSizes.isEmpty()) {
|
||||
pageSize = Integer.parseInt(pageSizes.get(0));
|
||||
pageSize = Math.min(pageSize, 10);
|
||||
}
|
||||
List<String> statuses = parameters.get("status");
|
||||
if (!Objects.isNull(statuses) && !statuses.isEmpty()) {
|
||||
status = statuses.get(0);
|
||||
}
|
||||
List<String> models = parameters.get("model");
|
||||
if (!Objects.isNull(models) && !models.isEmpty()) {
|
||||
model = models.get(0);
|
||||
}
|
||||
List<String> boxPriceTotalMines = parameters.get("boxPriceTotalMin");
|
||||
if (!Objects.isNull(boxPriceTotalMines) && !boxPriceTotalMines.isEmpty()) {
|
||||
boxPriceTotalMin = new BigDecimal(boxPriceTotalMines.get(0));
|
||||
}
|
||||
List<String> boxPriceTotalMaxes = parameters.get("boxPriceTotalMax");
|
||||
if (!Objects.isNull(boxPriceTotalMaxes) && !boxPriceTotalMaxes.isEmpty()) {
|
||||
boxPriceTotalMax = new BigDecimal(boxPriceTotalMaxes.get(0));
|
||||
}
|
||||
|
||||
if (ObjectUtil.isNotEmpty(WsFightHall.allHallUserMap.get(userId))) {
|
||||
session.getBasicRemote().sendText("用户" + userId + "已连接,请勿重复调用");
|
||||
session.close();
|
||||
return;
|
||||
}
|
||||
addHallUser(userId, session);
|
||||
|
||||
|
||||
Page<TtFight> pageInfo = new Page<>(pageNum, pageSize);
|
||||
pageInfo.setOptimizeCountSql(false);
|
||||
|
||||
LambdaQueryWrapper<TtFight> fightQuery = new LambdaQueryWrapper<>();
|
||||
fightQuery
|
||||
.eq(status != null, TtFight::getStatus, status)
|
||||
.eq(model != null, TtFight::getModel, model)
|
||||
.between(boxPriceTotalMin != null && boxPriceTotalMax != null,
|
||||
TtFight::getBoxPriceTotal, boxPriceTotalMin, boxPriceTotalMax)
|
||||
.ge(boxPriceTotalMin == null && boxPriceTotalMax != null,
|
||||
TtFight::getBoxPriceTotal, boxPriceTotalMax)
|
||||
.orderByDesc(TtFight::getCreateTime);
|
||||
List<TtFight> fightList = apiFightService.page(pageInfo, fightQuery).getRecords();
|
||||
if (CollectionUtils.isEmpty(fightList)) {
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
map.put("rows", new ArrayList<>());
|
||||
map.put("total", 0);
|
||||
sendMessage(WsResult.ok(SMsgKey.ALL_FIGHT_ROOM.name(), map, "所有对战房间"));
|
||||
} else {
|
||||
List<Integer> boxIds = new ArrayList<>();
|
||||
for (TtFight fight : fightList) {
|
||||
if (fight == null || MapUtils.isEmpty(fight.getBoxData())) {
|
||||
continue;
|
||||
}
|
||||
for (Map.Entry<String, FightBoxVO> entry : fight.getBoxData().entrySet()) {
|
||||
Object value = entry.getValue();
|
||||
if (value == null) {
|
||||
continue;
|
||||
}
|
||||
Integer boxId;
|
||||
if (value instanceof LinkedHashMap) {
|
||||
Map<String, Object> map = (LinkedHashMap) value;
|
||||
boxId = map.get("boxId") != null ? Integer.valueOf(map.get("boxId").toString()) : null;
|
||||
} else {
|
||||
boxId = ((FightBoxVO) value).getBoxId();
|
||||
}
|
||||
if (boxId == null) {
|
||||
continue;
|
||||
}
|
||||
boxIds.add(boxId);
|
||||
}
|
||||
}
|
||||
LambdaQueryWrapper<TtBox> queryWrapper = new LambdaQueryWrapper<>();
|
||||
queryWrapper.in(TtBox::getBoxId, boxIds);
|
||||
List<TtBox> boxes = ttBoxMapper.selectList(queryWrapper);
|
||||
Map<Integer, BigDecimal> boxMap = boxes.stream().filter(Objects::nonNull).collect(Collectors.toMap(TtBox::getBoxId, TtBox::getPrice));
|
||||
for (TtFight fight : fightList) {
|
||||
if (fight == null || MapUtils.isEmpty(fight.getBoxData())) {
|
||||
continue;
|
||||
}
|
||||
for (Map.Entry<String, FightBoxVO> entry : fight.getBoxData().entrySet()) {
|
||||
Object value = entry.getValue();
|
||||
if (value == null) {
|
||||
continue;
|
||||
}
|
||||
FightBoxVO vo;
|
||||
Integer boxId;
|
||||
if (value instanceof LinkedHashMap) {
|
||||
Map<String, Object> map = (LinkedHashMap) value;
|
||||
vo = new FightBoxVO(map.get("boxId") != null ? Integer.valueOf(map.get("boxId").toString()) : null,
|
||||
map.get("number") != null ? Integer.valueOf(map.get("number").toString()) : null,
|
||||
map.get("boxImg01") != null ? map.get("boxImg01").toString() : null,
|
||||
map.get("boxImg02") != null ? map.get("boxImg02").toString() : null);
|
||||
vo.setPrice(boxMap.getOrDefault(vo.getBoxId(), new BigDecimal(0)));
|
||||
} else {
|
||||
vo = (FightBoxVO) value;
|
||||
vo.setPrice(boxMap.getOrDefault(vo.getBoxId(), new BigDecimal(0)));
|
||||
}
|
||||
fight.getBoxData().put(vo.getBoxId().toString(), vo);
|
||||
}
|
||||
}
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
map.put("rows", fightList);
|
||||
map.put("total", apiFightService.page(pageInfo, fightQuery).getTotal());
|
||||
|
||||
sendMessage(WsResult.ok(SMsgKey.ALL_FIGHT_ROOM.name(), map, "所有对战房间"));
|
||||
}
|
||||
|
||||
|
||||
log.info("用户{}进入对战游戏大厅,广播{}个房间,在线人数{}", userId, fightList.size(), WsFightHall.onlineCount);
|
||||
}
|
||||
|
||||
@OnClose
|
||||
public void onClose(Session session) {
|
||||
// removeHallUser();
|
||||
removeHallUser(session.getPathParameters().get("userId"));
|
||||
log.info("关闭连接,正常在线人数:" + WsFightHall.onlineCount);
|
||||
}
|
||||
|
||||
@OnMessage
|
||||
public void onMessage(String message, Session session) {
|
||||
log.info("收到消息");
|
||||
}
|
||||
|
||||
@OnError
|
||||
public void onError(Session session, Throwable exception) throws Exception {
|
||||
log.error("出现错误", exception);
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新在线人数
|
||||
*/
|
||||
private int addOnlineCount(int number) {
|
||||
synchronized (new Object()) {
|
||||
WsFightHall.onlineCount += number;
|
||||
return WsFightHall.onlineCount;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 全局广播
|
||||
*/
|
||||
public static void broadcast(Object message) {
|
||||
|
||||
// ObjectMapper objectMapper = new ObjectMapper();
|
||||
String msg = JSON.toJSONString(message);
|
||||
|
||||
Collection<WsFightHall> wss = WsFightHall.allHallUserMap.values();
|
||||
|
||||
for (WsFightHall ws : wss) {
|
||||
try {
|
||||
ws.session.getBasicRemote().sendText(msg);
|
||||
} catch (IOException e) {
|
||||
log.warn("ws大厅广播给消息异常。msg:{}", msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 实现服务器主动推送
|
||||
*/
|
||||
public void sendMessage(Object message) {
|
||||
try {
|
||||
this.session.getBasicRemote().sendText(JSON.toJSONString(message));
|
||||
} catch (IOException e) {
|
||||
log.warn("服务器推送消息异常");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加连接用户
|
||||
*/
|
||||
private WsFightHall addHallUser(String userId, Session session) {
|
||||
addOnlineCount(1);
|
||||
this.userId = userId;
|
||||
this.session = session;
|
||||
WsFightHall.allHallUserMap.put(userId, this);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 移除连接用户
|
||||
*/
|
||||
private WsFightHall removeHallUser() {
|
||||
addOnlineCount(-1);
|
||||
WsFightHall.allHallUserMap.remove(userId);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 移除连接用户
|
||||
*/
|
||||
private WsFightHall removeHallUser(String userId) {
|
||||
addOnlineCount(-1);
|
||||
WsFightHall.allHallUserMap.remove(userId);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,406 @@
|
||||
package com.ruoyi.playingmethod.websocket;
|
||||
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.ruoyi.admin.mapper.TtBoxMapper;
|
||||
import com.ruoyi.admin.mapper.TtBoxOrnamentsMapper;
|
||||
import com.ruoyi.admin.service.TtBoxRecordsService;
|
||||
import com.ruoyi.common.core.domain.R;
|
||||
import com.ruoyi.common.core.redis.RedisCache;
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
import com.ruoyi.domain.entity.TtBoxRecords;
|
||||
import com.ruoyi.domain.entity.fight.FightSeat;
|
||||
import com.ruoyi.domain.entity.fight.TtFight;
|
||||
import com.ruoyi.domain.other.FightBoutData;
|
||||
import com.ruoyi.domain.other.TtBox;
|
||||
import com.ruoyi.domain.vo.TtBoxOrnamentsDataVO;
|
||||
import com.ruoyi.domain.vo.fight.FightBoxVO;
|
||||
import com.ruoyi.domain.vo.fight.FightResultVO;
|
||||
import com.ruoyi.playingmethod.service.ApiFightService;
|
||||
import com.ruoyi.playingmethod.service.ApiFightUserService;
|
||||
import com.ruoyi.playingmethod.websocket.constant.SMsgKey;
|
||||
import com.ruoyi.playingmethod.websocket.util.WsResult;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import jakarta.websocket.*;
|
||||
import jakarta.websocket.server.PathParam;
|
||||
import jakarta.websocket.server.ServerEndpoint;
|
||||
import java.io.IOException;
|
||||
import java.math.BigDecimal;
|
||||
import java.sql.Timestamp;
|
||||
import java.time.Duration;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 对战房间
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
@ServerEndpoint("/ws/fight/room/{userId}/{fightId}")
|
||||
public class WsFightRoom {
|
||||
|
||||
static Map<String, Session> sessionMap = new ConcurrentHashMap<>();
|
||||
|
||||
static volatile AtomicInteger viewersCount = new AtomicInteger(0);
|
||||
|
||||
// 用来记录当前连接数的变量
|
||||
private static volatile int onlineCount = 0;
|
||||
// concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象
|
||||
public static ConcurrentHashMap<String, WsFightRoom> allRoomUserMap = new ConcurrentHashMap<>();
|
||||
// 与某个客户端的连接会话,需要通过它来与客户端进行数据收发
|
||||
private Session session;
|
||||
private static ApiFightService apiFightService;
|
||||
private static TtBoxRecordsService boxRecordsService;
|
||||
private static TtBoxOrnamentsMapper boxOrnamentsMapper;
|
||||
// private static TtBoxOrnamentsService ttBoxOrnamentsService;
|
||||
private static ApiFightUserService apiFightUserService;
|
||||
private static Integer fightRoundTime = null; // 战斗回合时间
|
||||
private Integer userId = null;
|
||||
private Integer fightId = null;
|
||||
private String key = "";
|
||||
private static RedisCache redisCache;
|
||||
|
||||
private static TtBoxMapper ttBoxMapper;
|
||||
|
||||
@Value("${mkcsgo.fight.roundTime}")
|
||||
public void ttFightService(Integer fightRoundTime) {
|
||||
WsFightRoom.fightRoundTime = fightRoundTime;
|
||||
}
|
||||
|
||||
@Autowired
|
||||
public void ttFightService(ApiFightService apiFightService) {
|
||||
WsFightRoom.apiFightService = apiFightService;
|
||||
}
|
||||
|
||||
@Autowired
|
||||
public void boxOrnamentsMapper(TtBoxOrnamentsMapper boxOrnamentsMapper) {
|
||||
WsFightRoom.boxOrnamentsMapper = boxOrnamentsMapper;
|
||||
}
|
||||
|
||||
@Autowired
|
||||
public void boxRecordsService(TtBoxRecordsService boxRecordsService) {
|
||||
WsFightRoom.boxRecordsService = boxRecordsService;
|
||||
}
|
||||
|
||||
public void apiFightUserService(ApiFightUserService apiFightUserService) {
|
||||
WsFightRoom.apiFightUserService = apiFightUserService;
|
||||
}
|
||||
|
||||
@Autowired
|
||||
public void ttBoxMapper(TtBoxMapper ttBoxMapper) {
|
||||
WsFightRoom.ttBoxMapper = ttBoxMapper;
|
||||
}
|
||||
|
||||
@Autowired
|
||||
public void redisCache(RedisCache redisCache) {
|
||||
WsFightRoom.redisCache = redisCache;
|
||||
}
|
||||
|
||||
@OnOpen
|
||||
public void onOpen(Session session,
|
||||
@PathParam("userId") Integer userId,
|
||||
@PathParam("fightId") Integer fightId) {
|
||||
try {
|
||||
addFightRoomUser(userId, fightId, session);
|
||||
|
||||
R check = connectCheck(userId, fightId);
|
||||
if (!check.getCode().equals(200)) {
|
||||
session.getBasicRemote().sendText(check.getMsg());
|
||||
session.close();
|
||||
return;
|
||||
}
|
||||
|
||||
log.debug("/ws/fight/room > > onOpen");
|
||||
log.info("用户{}进入房间{}," + "在线人数{}", userId, fightId, WsFightRoom.onlineCount);
|
||||
sendMsgToPlayers("用户:" + userId + "进入房间," + fightId + "在线人数" + WsFightRoom.onlineCount, null);
|
||||
|
||||
// 首次连接获取房间最新数据
|
||||
LambdaQueryWrapper<TtFight> fightQuery = new LambdaQueryWrapper<>();
|
||||
fightQuery
|
||||
.eq(TtFight::getId, fightId);
|
||||
// .eq(TtFight::getStatus,0);
|
||||
TtFight fight = apiFightService.getOne(fightQuery);
|
||||
|
||||
// 构建结果集
|
||||
// 根据宝箱id查询关联的所有饰品
|
||||
Map<String, FightBoxVO> boxData = fight.getBoxData();
|
||||
|
||||
ArrayList<FightBoxVO> fightBoxVOList = new ArrayList<>();
|
||||
boxData.keySet().forEach(boxId -> {
|
||||
List<TtBoxOrnamentsDataVO> boxOrnamentsVOS = boxOrnamentsMapper.selectTtBoxOrnamentsList(Integer.valueOf(boxId));
|
||||
FightBoxVO fightBoxVO = JSONUtil.toBean(JSONUtil.toJsonStr(boxData.get(boxId)), FightBoxVO.class);
|
||||
fightBoxVO.setOrnaments(boxOrnamentsVOS);
|
||||
boxData.put(boxId,fightBoxVO);
|
||||
fightBoxVOList.add(boxData.get(boxId));
|
||||
});
|
||||
|
||||
LambdaQueryWrapper<TtBox> queryWrapper = new LambdaQueryWrapper<>();
|
||||
queryWrapper.in(TtBox::getBoxId, boxData.keySet());
|
||||
List<TtBox> boxes = ttBoxMapper.selectList(queryWrapper);
|
||||
var boxMapObj = boxes.stream().filter(Objects::nonNull).collect(Collectors.groupingBy(TtBox::getBoxId));
|
||||
Map<Integer, BigDecimal> boxMap = boxes.stream().filter(Objects::nonNull).collect(Collectors.toMap(TtBox::getBoxId, TtBox::getPrice));
|
||||
|
||||
for (FightBoxVO vo : fightBoxVOList) {
|
||||
vo.setPrice(boxMap.getOrDefault(vo.getBoxId(), new BigDecimal(0)));
|
||||
if (boxMapObj.get(vo.getBoxId()) != null) {
|
||||
vo.setBoxName(boxMapObj.get(vo.getBoxId()).getFirst().getBoxName());
|
||||
}
|
||||
}
|
||||
|
||||
fight.getBoxData().keySet().forEach(boxId -> {
|
||||
Object value = fight.getBoxData().get(boxId);
|
||||
FightBoxVO a = null;
|
||||
if (value instanceof LinkedHashMap) {
|
||||
Map<String, Object> map = (LinkedHashMap) value;
|
||||
a = new FightBoxVO(map.get("boxId") != null ? Integer.valueOf(map.get("boxId").toString()) : null,
|
||||
map.get("number") != null ? Integer.valueOf(map.get("number").toString()) : null,
|
||||
map.get("boxImg01") != null ? map.get("boxImg01").toString() : null,
|
||||
map.get("boxImg02") != null ? map.get("boxImg02").toString() : null);
|
||||
a.setPrice(boxMap.getOrDefault(a.getBoxId(), BigDecimal.ZERO));
|
||||
} else {
|
||||
a = (FightBoxVO) value;
|
||||
a.setPrice(boxMap.getOrDefault(a.getBoxId(), BigDecimal.ZERO));
|
||||
}
|
||||
fight.getBoxData().put(boxId, a);
|
||||
});
|
||||
|
||||
// 如果游戏结束,发送结果集数据
|
||||
if (fight.getStatus().equals(2) || fight.getStatus().equals(3)) {
|
||||
|
||||
// 所有对战结果记录
|
||||
LambdaQueryWrapper<TtBoxRecords> boxRecordsQuery = new LambdaQueryWrapper<>();
|
||||
boxRecordsQuery
|
||||
.eq(TtBoxRecords::getFightId, fightId);
|
||||
List<TtBoxRecords> allBoxRecords = boxRecordsService.list(boxRecordsQuery);
|
||||
|
||||
FightResultVO resultVO = FightResultVO.builder()
|
||||
.currentRound(-1L)
|
||||
.fight(fight)
|
||||
.winnerIds(fight.getWinnerIds())
|
||||
.fightResult(allBoxRecords)
|
||||
.fightBoxVOList(fightBoxVOList)
|
||||
.build();
|
||||
|
||||
broadcastFight(fightId, WsResult.ok(SMsgKey.FIGHT_RESULT.name(), resultVO, "对局已结束,对局最新信息"));
|
||||
log.info("room onOpen 广播数据成功。");
|
||||
|
||||
} else if (fight.getStatus().equals(1)) {
|
||||
|
||||
// 所有对战结果记录
|
||||
LambdaQueryWrapper<TtBoxRecords> boxRecordsQuery = new LambdaQueryWrapper<>();
|
||||
boxRecordsQuery
|
||||
.eq(TtBoxRecords::getFightId, fightId)
|
||||
.eq(TtBoxRecords::getStatus, 0);
|
||||
// 首先从Redis中查询对战结果,没有则在从数据库中查询
|
||||
List<TtBoxRecords> allBoxRecords;
|
||||
String key = "fight_result:fight_" + fightId;
|
||||
allBoxRecords = redisCache.getCacheObject(key);
|
||||
|
||||
if (Objects.isNull(allBoxRecords)) {
|
||||
allBoxRecords = boxRecordsService.list(boxRecordsQuery);
|
||||
}
|
||||
|
||||
// 时间差,计算当前进行到第几回合
|
||||
// LocalDateTime now = LocalDateTime.now();
|
||||
// Timestamp beginTime = fight.getBeginTime();
|
||||
// LocalDateTime beginTime1 = beginTime.toLocalDateTime();
|
||||
// Duration duration = Duration.between(beginTime1, now);
|
||||
// Long currentRound = duration.toMillis() / fightRoundTime; // 这个秒要和前端的【每回合时间】同步
|
||||
|
||||
// 获取当前回合数
|
||||
Integer currentRound = 0;
|
||||
FightBoutData fightBoutData = redisCache.getCacheObject("fight_bout_data:fight_" + fightId);
|
||||
if (!Objects.isNull(fightBoutData)) {
|
||||
currentRound = fightBoutData.getBoutNum();
|
||||
}
|
||||
|
||||
FightResultVO resultVO = FightResultVO.builder()
|
||||
.currentRound(currentRound.longValue())
|
||||
.fight(fight)
|
||||
.winnerIds(fight.getWinnerIds())
|
||||
.fightResult(allBoxRecords)
|
||||
.fightBoxVOList(fightBoxVOList)
|
||||
.build();
|
||||
|
||||
// broadcastFight(fightId, WsResult.ok(SMsgKey.FIGHT_RESULT.name(), resultVO, "对局进行中,对局最新信息"));
|
||||
sendMsgToPlayers(WsResult.ok(SMsgKey.FIGHT_RESULT.name(), resultVO, "对局进行中,对局最新信息"), null);
|
||||
|
||||
log.info("room onOpen 广播数据成功。");
|
||||
} else if (fight.getStatus().equals(0)) {
|
||||
// 没有结束,返回房间信息即可
|
||||
sendMsgToPlayers(WsResult.ok(SMsgKey.FIGHT_ROOM_INFO.name(), fight, "对局准备中,对战房间最新信息"), null);
|
||||
log.info("room onOpen 广播数据成功。");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
log.warn("onopen warn");
|
||||
}
|
||||
}
|
||||
|
||||
@OnClose
|
||||
public void onClose(Session session) {
|
||||
removeFightRoomUser();
|
||||
log.info("onClose");
|
||||
log.info("正常在线人数:" + WsFightRoom.onlineCount);
|
||||
}
|
||||
|
||||
@OnError
|
||||
public void onError(Session session, Throwable exception) throws Exception {
|
||||
log.info("onError");
|
||||
}
|
||||
|
||||
@OnMessage
|
||||
public void onMessage(String message, Session session) {
|
||||
log.info("onMessage");
|
||||
}
|
||||
|
||||
/**
|
||||
* 连接检查
|
||||
*/
|
||||
private R connectCheck(Integer userId, Integer fightId) {
|
||||
if (ObjectUtil.isNotEmpty(WsFightRoom.allRoomUserMap.get(userId + "_" + fightId))) {
|
||||
R.fail("用户" + userId + "已经连接对局" + fightId + "。请勿重复调用。");
|
||||
}
|
||||
TtFight fight = apiFightService.getById(fightId);
|
||||
if (ObjectUtil.isEmpty(fight)) {
|
||||
return R.fail("不存在的对局ID:" + fightId);
|
||||
}
|
||||
// if (fight.getStatus().equals(2) || fight.getStatus().equals(3)){
|
||||
// return R.fail("对局"+fightId+"已结束。");
|
||||
// }
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新在线人数
|
||||
*/
|
||||
private int addOnlineCount(int number) {
|
||||
synchronized (new Object()) {
|
||||
WsFightRoom.onlineCount = WsFightRoom.onlineCount + number;
|
||||
return WsFightRoom.onlineCount;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 单点推送
|
||||
*/
|
||||
public void sendMsgToPlayers(Object message, List<String> keys) {
|
||||
String msg = JSON.toJSONString(message);
|
||||
|
||||
try {
|
||||
if (ObjectUtil.isEmpty(keys) || keys.size() == 0) {
|
||||
// 推送给自己
|
||||
this.session.getBasicRemote().sendText(msg);
|
||||
} else {
|
||||
for (String key : keys) {
|
||||
WsFightRoom ws = WsFightRoom.allRoomUserMap.get(key);
|
||||
ws.session.getBasicRemote().sendText(msg);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.warn("推送消息异常。msg:" + msg);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 房间广播
|
||||
*/
|
||||
public static void broadcastFight(Integer fightId, Object message) {
|
||||
String msg = JSON.toJSONString(message);
|
||||
|
||||
Collection<WsFightRoom> wslist = WsFightRoom.allRoomUserMap.values();
|
||||
|
||||
for (WsFightRoom ws : wslist) {
|
||||
try {
|
||||
if (!ws.fightId.equals(fightId)) continue;
|
||||
log.info(String.valueOf(ws.session.isOpen()));
|
||||
if (!ws.session.isOpen()) continue;
|
||||
RemoteEndpoint.Basic basicRemote = ws.session.getBasicRemote();
|
||||
basicRemote.sendText(msg);
|
||||
} catch (IOException e) {
|
||||
log.warn("ws推送广播给{}_{}消息异常。", ws.userId, ws.fightId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 全局广播
|
||||
*/
|
||||
public static void broadcast(Object message) {
|
||||
|
||||
ObjectMapper objectMapper = new ObjectMapper();
|
||||
String msg = "";
|
||||
try {
|
||||
msg = objectMapper.writeValueAsString(message);
|
||||
} catch (JsonProcessingException e) {
|
||||
log.warn("ws解析广播消息异常。");
|
||||
}
|
||||
|
||||
Collection<WsFightRoom> wss = WsFightRoom.allRoomUserMap.values();
|
||||
for (WsFightRoom ws : wss) {
|
||||
try {
|
||||
ws.session.getBasicRemote().sendText(msg);
|
||||
} catch (IOException e) {
|
||||
log.warn("ws推送广播给{}_{}消息异常。", ws.userId, ws.fightId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加连接用户
|
||||
*/
|
||||
private WsFightRoom addFightRoomUser(Integer userId, Integer fightId, Session session) {
|
||||
addOnlineCount(1);
|
||||
this.userId = userId;
|
||||
this.fightId = fightId;
|
||||
this.key = userId + "_" + fightId;
|
||||
this.session = session;
|
||||
WsFightRoom.allRoomUserMap.put(key, this);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 移除连接用户
|
||||
*/
|
||||
private WsFightRoom removeFightRoomUser() {
|
||||
addOnlineCount(-1);
|
||||
WsFightRoom.allRoomUserMap.remove(userId + "_" + fightId);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 断开房间所有连接
|
||||
*/
|
||||
public static Boolean batchClose(TtFight fight) {
|
||||
List<FightSeat> seats = fight.getSeats();
|
||||
|
||||
for (int i = 0; i < seats.size(); i++) {
|
||||
FightSeat seat = JSONUtil.toBean(JSONUtil.toJsonStr(seats.get(i)), FightSeat.class);
|
||||
|
||||
Integer playerId = seat.getPlayerId();
|
||||
String key = ObjectUtil.isNotEmpty(playerId) ? String.valueOf(playerId) : "" + "_" + fight.getId();
|
||||
|
||||
WsFightRoom ws = WsFightRoom.allRoomUserMap.get(key);
|
||||
if (ObjectUtil.isEmpty(ws)) continue;
|
||||
|
||||
try {
|
||||
ws.session.close();
|
||||
} catch (IOException e) {
|
||||
log.warn("关闭连接异常");
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,256 @@
|
||||
package com.ruoyi.playingmethod.websocket;
|
||||
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.ruoyi.admin.mapper.TtBoxOrnamentsMapper;
|
||||
import com.ruoyi.admin.service.TtBoxRecordsService;
|
||||
import com.ruoyi.domain.entity.TtBoxRecords;
|
||||
import com.ruoyi.domain.entity.fight.TtFight;
|
||||
import com.ruoyi.domain.vo.TtBoxOrnamentsDataVO;
|
||||
import com.ruoyi.domain.vo.fight.FightBoxVO;
|
||||
import com.ruoyi.domain.vo.fight.FightResultVO;
|
||||
import com.ruoyi.playingmethod.service.ApiFightService;
|
||||
import com.ruoyi.playingmethod.websocket.constant.SMsgKey;
|
||||
import com.ruoyi.playingmethod.websocket.util.WsResult;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import jakarta.websocket.*;
|
||||
import jakarta.websocket.server.PathParam;
|
||||
import jakarta.websocket.server.ServerEndpoint;
|
||||
import java.io.IOException;
|
||||
import java.sql.Timestamp;
|
||||
import java.time.Duration;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
|
||||
/**
|
||||
* 对战房间
|
||||
*/
|
||||
@Slf4j
|
||||
@ServerEndpoint("/ws/fight/room2/{userId}/{fightId}")
|
||||
@Component
|
||||
public class WsFightRoom2 {
|
||||
|
||||
static Map<String, Session> sessionMap = new ConcurrentHashMap<>();
|
||||
|
||||
static Map<String, Session> viewersSessionMap = new ConcurrentHashMap<>();
|
||||
|
||||
private String sessionKey;
|
||||
|
||||
private static Integer fightRoundTime;
|
||||
|
||||
private static ApiFightService apiFightService;
|
||||
|
||||
private static TtBoxRecordsService ttBoxRecordsService;
|
||||
|
||||
private static TtBoxOrnamentsMapper ttBoxOrnamentsMapper;
|
||||
|
||||
@Value("${mkcsgo.fight.roundTime}")
|
||||
public void setFightRoundTime(Integer fightRoundTime) {
|
||||
WsFightRoom2.fightRoundTime = fightRoundTime;
|
||||
}
|
||||
|
||||
@Autowired
|
||||
public void ttFightService(ApiFightService apiFightService) {
|
||||
WsFightRoom2.apiFightService = apiFightService;
|
||||
}
|
||||
|
||||
@Autowired
|
||||
public void boxRecordsService(TtBoxRecordsService ttBoxRecordsService) {
|
||||
WsFightRoom2.ttBoxRecordsService = ttBoxRecordsService;
|
||||
}
|
||||
|
||||
@Autowired
|
||||
public void boxOrnamentsMapper(TtBoxOrnamentsMapper ttBoxOrnamentsMapper) {
|
||||
WsFightRoom2.ttBoxOrnamentsMapper = ttBoxOrnamentsMapper;
|
||||
}
|
||||
|
||||
@OnOpen
|
||||
public void onOpen(Session session,
|
||||
@PathParam("userId") Integer userId,
|
||||
@PathParam("fightId") Integer fightId) {
|
||||
|
||||
sessionKey = fightId.toString() + "#" + userId.toString();
|
||||
|
||||
// 检查用户是否已经进入某个房间
|
||||
if (!Objects.isNull(sessionMap.get(sessionKey))) {
|
||||
try {
|
||||
session.getBasicRemote().sendText("用户" + userId + "已加入" + fightId +"房间,不得重复进入");
|
||||
session.close();
|
||||
return;
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
} else {
|
||||
sessionMap.put(sessionKey, session);
|
||||
}
|
||||
|
||||
// 首次连接获取房间最新数据
|
||||
LambdaQueryWrapper<TtFight> fightQuery = new LambdaQueryWrapper<>();
|
||||
fightQuery
|
||||
.eq(TtFight::getId, fightId);
|
||||
TtFight ttFight = apiFightService.getOne(fightQuery);
|
||||
|
||||
// 检查房间是否存在
|
||||
if (Objects.isNull(ttFight)) {
|
||||
try {
|
||||
session.getBasicRemote().sendText("房间" + fightId + "不存在");
|
||||
session.close();
|
||||
return;
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
// 判断对战状态
|
||||
if (ttFight.getStatus() == 2) {
|
||||
// 构建结果集
|
||||
// 根据宝箱ID查询关联的所有饰品
|
||||
Map<String, FightBoxVO> boxData = ttFight.getBoxData();
|
||||
ArrayList<FightBoxVO> fightBoxVOList = new ArrayList<>();
|
||||
boxData.keySet().forEach(boxId -> {
|
||||
fightBoxVOList.add(boxData.get(boxId));
|
||||
});
|
||||
|
||||
// 所有对战结果记录
|
||||
LambdaQueryWrapper<TtBoxRecords> boxRecordsQuery = new LambdaQueryWrapper<>();
|
||||
boxRecordsQuery
|
||||
.eq(TtBoxRecords::getFightId, fightId)
|
||||
.eq(TtBoxRecords::getStatus, 0);
|
||||
List<TtBoxRecords> allBoxRecords = ttBoxRecordsService.list(boxRecordsQuery);
|
||||
|
||||
FightResultVO resultVO = FightResultVO.builder()
|
||||
.currentRound(-1L)
|
||||
.fight(ttFight)
|
||||
.winnerIds(ttFight.getWinnerIds())
|
||||
.fightResult(allBoxRecords)
|
||||
.fightBoxVOList(fightBoxVOList)
|
||||
.build();
|
||||
|
||||
WsResult<FightResultVO> result = WsResult.ok(SMsgKey.FIGHT_RESULT.name(), resultVO, "对局已结束,对局最新信息");
|
||||
String message = JSON.toJSONString(result);
|
||||
broadcastMessageToFight(fightId, message);
|
||||
} else if (ttFight.getStatus() == 1) {
|
||||
// 构建结果集
|
||||
// 根据宝箱ID查询关联的所有饰品
|
||||
Map<String, FightBoxVO> boxData = ttFight.getBoxData();
|
||||
ArrayList<FightBoxVO> fightBoxVOList = new ArrayList<>();
|
||||
boxData.keySet().forEach(boxId -> {
|
||||
List<TtBoxOrnamentsDataVO> boxOrnamentsVOS = ttBoxOrnamentsMapper.selectTtBoxOrnamentsList(Integer.valueOf(boxId));
|
||||
FightBoxVO fightBoxVO = JSONUtil.toBean(JSONUtil.toJsonStr(boxData.get(boxId)), FightBoxVO.class);
|
||||
fightBoxVO.setOrnaments(boxOrnamentsVOS);
|
||||
boxData.put(boxId,fightBoxVO);
|
||||
fightBoxVOList.add(boxData.get(boxId));
|
||||
});
|
||||
|
||||
// 所有对战结果记录
|
||||
LambdaQueryWrapper<TtBoxRecords> boxRecordsQuery = new LambdaQueryWrapper<>();
|
||||
boxRecordsQuery
|
||||
.eq(TtBoxRecords::getFightId, fightId)
|
||||
.eq(TtBoxRecords::getStatus, 0);
|
||||
List<TtBoxRecords> allBoxRecords = ttBoxRecordsService.list(boxRecordsQuery);
|
||||
|
||||
// 时间差,计算当前进行到第几回合
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
Timestamp beginTime = ttFight.getBeginTime();
|
||||
LocalDateTime localDateTime = beginTime.toLocalDateTime();
|
||||
|
||||
Duration duration = Duration.between(localDateTime, now);
|
||||
Long currentRound = duration.toMillis() / fightRoundTime; // 这个秒要和前端的【每回合时间】同步
|
||||
|
||||
FightResultVO resultVO = FightResultVO.builder()
|
||||
.currentRound(currentRound)
|
||||
.fight(ttFight)
|
||||
.winnerIds(ttFight.getWinnerIds())
|
||||
.fightResult(allBoxRecords)
|
||||
.fightBoxVOList(fightBoxVOList)
|
||||
.build();
|
||||
|
||||
WsResult<FightResultVO> result = WsResult.ok(SMsgKey.FIGHT_RESULT.name(), resultVO, "对局进行中,对局最新信息");
|
||||
String message = JSON.toJSONString(result);
|
||||
broadcastMessageToFight(fightId, message);
|
||||
|
||||
// 存储观战人,广播房间内观战人数
|
||||
viewersSessionMap.put(sessionKey, session);
|
||||
broadcastViewersCountToFight(fightId);
|
||||
} else if (ttFight.getStatus() == 0) {
|
||||
WsResult<TtFight> result = WsResult.ok(SMsgKey.FIGHT_ROOM_INFO.name(), ttFight, "对局准备中,对战房间最新信息");
|
||||
String message = JSON.toJSONString(result);
|
||||
try {
|
||||
session.getBasicRemote().sendText(message);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@OnMessage
|
||||
public void onMessage(Session session, String message) {
|
||||
}
|
||||
|
||||
@OnClose
|
||||
public void onClose(Session session) {
|
||||
if (session.equals(sessionMap.get(sessionKey))) {
|
||||
sessionMap.remove(sessionKey);
|
||||
}
|
||||
if (session.equals(viewersSessionMap.get(sessionKey))) {
|
||||
viewersSessionMap.remove(sessionKey);
|
||||
Integer fightId = Integer.parseInt(sessionKey.substring(0, sessionKey.indexOf('#')));
|
||||
broadcastViewersCountToFight(fightId);
|
||||
}
|
||||
}
|
||||
|
||||
@OnError
|
||||
public void onError(Session session, Throwable throwable) {
|
||||
}
|
||||
|
||||
// 向指定房间的用户广播消息
|
||||
private void broadcastMessageToFight(Integer fightId, String message) {
|
||||
for (Map.Entry<String, Session> entry : sessionMap.entrySet()) {
|
||||
String sessionKey = entry.getKey();
|
||||
Session session = entry.getValue();
|
||||
if (sessionKey.substring(0, sessionKey.indexOf('#')).equals(fightId.toString())) {
|
||||
try {
|
||||
session.getBasicRemote().sendText(message);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 向指定房间的用户广播观战人数
|
||||
private void broadcastViewersCountToFight(Integer fightId) {
|
||||
int viewersCount = 0;
|
||||
// 统计本房间的观战人数
|
||||
for (Map.Entry<String, Session> entry : viewersSessionMap.entrySet()) {
|
||||
String sessionKey = entry.getKey();
|
||||
if (sessionKey.substring(0, sessionKey.indexOf('#')).equals(fightId.toString())) {
|
||||
viewersCount++;
|
||||
}
|
||||
}
|
||||
// 向该房间所有用户广播
|
||||
for (Map.Entry<String, Session> entry : sessionMap.entrySet()) {
|
||||
String sessionKey = entry.getKey();
|
||||
Session session = entry.getValue();
|
||||
if (sessionKey.substring(0, sessionKey.indexOf('#')).equals(fightId.toString())) {
|
||||
try {
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
map.put("viewersCount", viewersCount);
|
||||
map.put("message", "当前房间观战人数");
|
||||
String message = JSON.toJSONString(map);
|
||||
session.getBasicRemote().sendText(message);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.ruoyi.playingmethod.websocket.config;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.socket.server.standard.ServerEndpointExporter;
|
||||
|
||||
@Configuration
|
||||
public class WebSocketConfig {
|
||||
@Bean
|
||||
public ServerEndpointExporter serverEndpointExporter() {
|
||||
return new ServerEndpointExporter();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package com.ruoyi.playingmethod.websocket.constant;
|
||||
|
||||
// 客户端发送消息key
|
||||
public enum CMsgKey {
|
||||
|
||||
FIGHT_END;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.ruoyi.playingmethod.websocket.constant;
|
||||
|
||||
// 服务端发送消息key
|
||||
public enum SMsgKey {
|
||||
|
||||
// 所有对战房间列表
|
||||
ALL_FIGHT_ROOM,
|
||||
|
||||
// 对战结果
|
||||
FIGHT_RESULT,
|
||||
|
||||
// 房间信息
|
||||
FIGHT_ROOM_INFO,
|
||||
|
||||
// 盲盒房间连接第一次数据
|
||||
Blind_Box_Init_Data,
|
||||
|
||||
// 盲盒房间实时数据
|
||||
Blind_Box_Current_Data;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.ruoyi.playingmethod.websocket.entity;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
@Data
|
||||
public class ResultData<T> implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private int code;
|
||||
|
||||
private String typeName;
|
||||
|
||||
private T data;
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.ruoyi.playingmethod.websocket.entity;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import jakarta.websocket.Session;
|
||||
|
||||
@Data
|
||||
public class SessionData {
|
||||
private Integer userId = 0;
|
||||
private Session session;
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package com.ruoyi.playingmethod.websocket.util;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.concurrent.Semaphore;
|
||||
|
||||
public class SemaphoreUtils {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(SemaphoreUtils.class);
|
||||
|
||||
public static boolean tryAcquire(Semaphore semaphore) {
|
||||
boolean flag = false;
|
||||
|
||||
try {
|
||||
flag = semaphore.tryAcquire();
|
||||
} catch (Exception e) {
|
||||
LOGGER.error("获取信号量异常", e);
|
||||
}
|
||||
|
||||
return flag;
|
||||
}
|
||||
|
||||
public static void release(Semaphore semaphore) {
|
||||
|
||||
try {
|
||||
semaphore.release();
|
||||
} catch (Exception e) {
|
||||
LOGGER.error("释放信号量异常", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
package com.ruoyi.playingmethod.websocket.util;
|
||||
|
||||
import com.ruoyi.common.constant.HttpStatus;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 响应信息主体
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class WsResult<T> implements Serializable
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/** 成功 */
|
||||
public static final int SUCCESS = HttpStatus.SUCCESS;
|
||||
|
||||
/** 失败 */
|
||||
public static final int FAIL = HttpStatus.ERROR;
|
||||
|
||||
private String key;
|
||||
|
||||
private T data;
|
||||
|
||||
private int code;
|
||||
|
||||
private String msg;
|
||||
|
||||
public static <T> WsResult<T> ok()
|
||||
{
|
||||
return new WsResult(null,null, SUCCESS, "操作成功");
|
||||
}
|
||||
|
||||
public static <T> WsResult<T> ok(String key, T data)
|
||||
{
|
||||
return new WsResult(key,data, SUCCESS, "操作成功");
|
||||
}
|
||||
|
||||
public static <T> WsResult<T> ok(String key,T data,String msg)
|
||||
{
|
||||
return new WsResult(key,data, SUCCESS, msg);
|
||||
}
|
||||
|
||||
public static <T> WsResult<T> ok(String msg)
|
||||
{
|
||||
return new WsResult(null,null, SUCCESS, msg);
|
||||
}
|
||||
|
||||
public static <T> WsResult<T> fail()
|
||||
{
|
||||
return new WsResult(null,null, FAIL, "操作失败");
|
||||
}
|
||||
|
||||
public static <T> WsResult<T> fail(String key,T data,String msg)
|
||||
{
|
||||
return new WsResult(key,data, FAIL, msg);
|
||||
}
|
||||
|
||||
public static <T> WsResult<T> fail(String msg)
|
||||
{
|
||||
return new WsResult(null,null, FAIL, msg);
|
||||
}
|
||||
|
||||
public static <T> Boolean isError(WsResult<T> ret)
|
||||
{
|
||||
return !isSuccess(ret);
|
||||
}
|
||||
|
||||
public static <T> Boolean isSuccess(WsResult<T> ret)
|
||||
{
|
||||
return WsResult.SUCCESS == ret.getCode();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!DOCTYPE mapper
|
||||
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.ruoyi.playingmethod.mapper.ApiAttendanceRecordMapper">
|
||||
|
||||
<resultMap type="com.ruoyi.playingmethod.entity.TtAttendanceRecord" id="TtCoinRecordResult">
|
||||
<result property="id" column="id" />
|
||||
<result property="userId" column="user_id" />
|
||||
<result property="coin" column="coin" />
|
||||
<result property="createTime" column="create_time" />
|
||||
<result property="updateTime" column="update_time" />
|
||||
<result property="delFlag" column="del_flag" />
|
||||
</resultMap>
|
||||
|
||||
|
||||
<select id="selectByUid" resultType="com.ruoyi.playingmethod.entity.TtAttendanceRecord">
|
||||
SELECT
|
||||
id,
|
||||
user_id,
|
||||
coin
|
||||
FROM tt_attendance_record
|
||||
<where>
|
||||
<if test="uid != null">and user_id = #{uid}</if>
|
||||
AND del_flag = '0'
|
||||
AND (create_time >= DATE_FORMAT(NOW() - INTERVAL 1 HOUR, '%Y-%m-%d %H:00:00')
|
||||
or create_time < DATE_FORMAT(NOW() - INTERVAL 1 HOUR, '%Y-%m-%d %H:59:59')
|
||||
)
|
||||
</where>
|
||||
</select>
|
||||
|
||||
<insert id="insertAttendanceRecord" parameterType="com.ruoyi.playingmethod.entity.TtAttendanceRecord" useGeneratedKeys="true" keyProperty="id">
|
||||
insert into tt_attendance_record
|
||||
<trim prefix="(" suffix=")" suffixOverrides=",">
|
||||
<if test="userId != null">user_id,</if>
|
||||
<if test="coin != null">coin,</if>
|
||||
<if test="createTime != null">create_time,</if>
|
||||
<if test="updateTime != null">update_time,</if>
|
||||
</trim>
|
||||
<trim prefix="values (" suffix=")" suffixOverrides=",">
|
||||
<if test="userId != null">#{userId},</if>
|
||||
<if test="coin != null">#{coin},</if>
|
||||
<if test="createTime != null">#{createTime},</if>
|
||||
<if test="updateTime != null">#{updateTime},</if>
|
||||
</trim>
|
||||
</insert>
|
||||
|
||||
|
||||
<select id="selectSevenAttendance" resultType="com.ruoyi.playingmethod.entity.TtAttendanceRecord">
|
||||
SELECT
|
||||
id,
|
||||
user_id,
|
||||
coin,
|
||||
create_time
|
||||
FROM tt_attendance_record
|
||||
<where>
|
||||
<if test="uid != null">and user_id = #{uid}</if>
|
||||
|
||||
<!-- <if test="beginTime != null"> <![CDATA[ and create_time >= #{beginTime} ]]></if>-->
|
||||
<!-- <if test="endTime != null"> <![CDATA[ and create_time <= #{endTime} ]]></if>-->
|
||||
<if test="createTime != null and createTime != ''"> and DATE_FORMAT(create_time, '%Y-%m-%d') = #{createTime}</if>
|
||||
AND del_flag = '0'
|
||||
</where>
|
||||
</select>
|
||||
|
||||
</mapper>
|
||||
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!DOCTYPE mapper
|
||||
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.ruoyi.playingmethod.mapper.ApiBattleRoyaleMapper">
|
||||
|
||||
|
||||
</mapper>
|
||||
@@ -0,0 +1,133 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!DOCTYPE mapper
|
||||
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.ruoyi.playingmethod.mapper.ApiBindBoxMapper">
|
||||
|
||||
<select id="getBoxData" resultType="com.ruoyi.domain.other.TtBoxA">
|
||||
SELECT box_id,
|
||||
box_name,
|
||||
box_type_id,
|
||||
price,
|
||||
box_img01,
|
||||
box_img02
|
||||
FROM tt_box
|
||||
WHERE box_id = #{boxId}
|
||||
AND del_flag = '0'
|
||||
AND status = '0';
|
||||
</select>
|
||||
|
||||
<select id="getBoxOrnamentsList" resultType="com.ruoyi.domain.other.TtOrnamentsA">
|
||||
SELECT tto.id AS ornament_id,
|
||||
tto.name,
|
||||
tto.short_name,
|
||||
tto.use_price,
|
||||
tto.image_url,
|
||||
tto.exterior_name,
|
||||
tol.id AS ornamentsLevelId,
|
||||
tol.level_img,
|
||||
tbo.odds,
|
||||
tbo.comp_odds
|
||||
FROM tt_box_ornaments tbo
|
||||
LEFT JOIN tt_ornament tto ON tbo.ornament_id = tto.id
|
||||
LEFT JOIN tt_ornaments_level tol ON tbo.level = tol.id
|
||||
WHERE tbo.box_id = #{boxId}
|
||||
</select>
|
||||
|
||||
<select id="getBoxList" resultType="com.ruoyi.domain.other.TtBoxA">
|
||||
SELECT
|
||||
box_id,
|
||||
box_name,
|
||||
price,
|
||||
box_img01,
|
||||
box_img02,
|
||||
box_type_id,
|
||||
box_type
|
||||
FROM tt_box
|
||||
<where>
|
||||
<if test="boxTypeId != null">and box_type_id = #{boxTypeId}</if>
|
||||
<if test="homeFlag != null">and is_home = '0'</if>
|
||||
<if test="boxType != null">and box_type = #{boxType}</if>
|
||||
AND del_flag = '0' AND status = '0'
|
||||
</where>
|
||||
</select>
|
||||
|
||||
<select id="getOrnamentsData" resultType="com.ruoyi.domain.other.TtOrnamentsA">
|
||||
SELECT #{id} as id,
|
||||
tbo.ornaments_id,
|
||||
tto.name,
|
||||
tto.short_name,
|
||||
tto.use_price,
|
||||
tto.image_url,
|
||||
tto.exterior_name,
|
||||
tbo.level as ornamentsLevelId,
|
||||
tol.level_img
|
||||
FROM tt_box_ornaments tbo
|
||||
LEFT JOIN tt_ornament tto ON tbo.ornaments_id = tto.id
|
||||
LEFT JOIN tt_ornaments_level tol ON tbo.level = tol.id
|
||||
WHERE tbo.box_id = #{boxId}
|
||||
AND tbo.ornaments_id = #{ornamentsId}
|
||||
LIMIT 1
|
||||
</select>
|
||||
|
||||
<select id="getBindBoxHistory" resultType="com.ruoyi.domain.other.TtBoxUser">
|
||||
SELECT tbr.id,
|
||||
tbr.box_id,
|
||||
tbr.user_id,
|
||||
ttu.user_name,
|
||||
ttu.nick_name,
|
||||
ttu.avatar,
|
||||
tbr.ornament_id,
|
||||
tto.name,
|
||||
tto.short_name,
|
||||
tto.use_price,
|
||||
tto.image_url,
|
||||
tto.exterior_name,
|
||||
tbr.ornaments_level_id,
|
||||
tol.level_img,
|
||||
tbr.source
|
||||
FROM tt_box_records tbr
|
||||
LEFT JOIN tt_user ttu ON tbr.user_id = ttu.user_id
|
||||
LEFT JOIN tt_ornament tto ON tbr.ornament_id = tto.id
|
||||
LEFT JOIN tt_ornaments_level tol ON tbr.ornaments_level_id = tol.id
|
||||
<where>
|
||||
<if test="boxId != null"> AND tbr.box_id = #{boxId} </if>
|
||||
<if test="userType != null"> AND ttu.user_type = #{userType} </if>
|
||||
AND tbr.source = '1'
|
||||
</where>
|
||||
ORDER BY tbr.create_time DESC
|
||||
</select>
|
||||
|
||||
<select id="getProbabilityDistribution"
|
||||
resultType="com.ruoyi.domain.other.TtBoxLevelA">
|
||||
SELECT
|
||||
tbo.`level` AS ornamentsLevelId,
|
||||
tol.`level`,
|
||||
CONCAT(FORMAT(SUM(tbo.odds) / (SELECT SUM(odds) FROM tt_box_ornaments WHERE box_id = #{boxId}) * 100, 2), '%') AS probability
|
||||
FROM tt_box_ornaments tbo
|
||||
LEFT JOIN tt_ornaments_level tol ON tbo.`level` = tol.id
|
||||
WHERE tbo.box_id = #{boxId}
|
||||
GROUP BY tbo.`level`;
|
||||
</select>
|
||||
<select id="ornamentsInfo" resultType="com.ruoyi.domain.other.TtOrnamentsA">
|
||||
|
||||
SELECT
|
||||
tto.id as ornament_id,
|
||||
tto.name as name,
|
||||
tto.short_name,
|
||||
tto.use_price,
|
||||
tto.image_url,
|
||||
tto.exterior_name,
|
||||
tbo.level as ornamentsLevelId,
|
||||
tol.level_img
|
||||
FROM tt_box_ornaments tbo
|
||||
LEFT JOIN tt_ornament tto ON tbo.ornament_id = tto.id
|
||||
LEFT JOIN tt_ornaments_level tol ON tbo.level = tol.id
|
||||
WHERE tbo.box_id = #{boxId}
|
||||
AND tbo.ornament_id = #{ornamentId}
|
||||
LIMIT 1
|
||||
|
||||
</select>
|
||||
|
||||
|
||||
</mapper>
|
||||
@@ -0,0 +1,41 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!DOCTYPE mapper
|
||||
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.ruoyi.playingmethod.mapper.ApiCompoundMapper">
|
||||
|
||||
<select id="selectCompoundDataById" resultType="com.ruoyi.domain.vo.UserPackSackDataVO">
|
||||
SELECT tbr.id,
|
||||
tbr.ornaments_id,
|
||||
tbr.ornaments_price,
|
||||
tto.name,
|
||||
tto.short_name,
|
||||
tto.image_url,
|
||||
tto.exterior_name,
|
||||
tbr.ornaments_level_id,
|
||||
tol.level_img
|
||||
FROM tt_box_records tbr
|
||||
LEFT JOIN tt_ornament tto ON tbr.ornaments_id = tto.id
|
||||
LEFT JOIN tt_ornaments_level tol ON tbr.ornaments_level_id = tol.id
|
||||
WHERE tbr.id = #{packSackId}
|
||||
</select>
|
||||
|
||||
<select id="selectCompoundRecordByUserId" resultType="com.ruoyi.domain.vo.UserPackSackDataVO">
|
||||
SELECT tbr.id,
|
||||
tbr.ornaments_id,
|
||||
tbr.ornaments_price,
|
||||
tto.name,
|
||||
tto.short_name,
|
||||
tto.image_url,
|
||||
tto.exterior_name,
|
||||
tbr.ornaments_level_id,
|
||||
tol.level_img
|
||||
FROM tt_box_records tbr
|
||||
LEFT JOIN tt_ornament tto ON tbr.ornaments_id = tto.id
|
||||
LEFT JOIN tt_ornaments_level tol ON tbr.ornaments_level_id = tol.id
|
||||
WHERE tbr.user_id = #{userId}
|
||||
AND tbr.source = '3'
|
||||
order by tbr.create_time DESC
|
||||
</select>
|
||||
|
||||
</mapper>
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user