|
|
@@ -0,0 +1,1316 @@
|
|
|
+package com.td.boss.game.complayergoods.controller;
|
|
|
+
|
|
|
+import com.td.boss.common.controller.*;
|
|
|
+import com.td.boss.common.pojo.Result;
|
|
|
+import com.td.boss.config.enums.ResultEnum;
|
|
|
+import com.td.boss.game.comexplainland.service.ComExplainLandService;
|
|
|
+import com.td.boss.game.comexplainland.vo.ComExplainLandVo;
|
|
|
+import com.td.boss.game.comfruit.pojo.ComFruit;
|
|
|
+import com.td.boss.game.comfruit.service.ComFruitService;
|
|
|
+import com.td.boss.game.comfruit.vo.ComFruitAmountVo;
|
|
|
+import com.td.boss.game.comfruit.vo.ComFruitVo;
|
|
|
+import com.td.boss.game.commallother.pojo.ComMallOther;
|
|
|
+import com.td.boss.game.commallother.service.ComMallOtherService;
|
|
|
+import com.td.boss.game.commallother.vo.ComMallOtherVo;
|
|
|
+import com.td.boss.game.commallseed.service.ComMallSeedService;
|
|
|
+import com.td.boss.game.commallseed.vo.ComMallSeedVo;
|
|
|
+import com.td.boss.game.complayerdog.pojo.ComPlayerDog;
|
|
|
+import com.td.boss.game.complayerdog.service.ComPlayerDogService;
|
|
|
+import com.td.boss.game.complayerdog.vo.ComPlayerDogVo;
|
|
|
+import com.td.boss.game.complayergoods.pojo.ComPlayerGoods;
|
|
|
+import com.td.boss.game.complayergoods.vo.ComPlayerGoodsSimpleVo;
|
|
|
+import com.td.boss.game.complayergoods.vo.ComPlayerGoodsVo;
|
|
|
+import com.td.boss.game.complayergoods.service.ComPlayerGoodsService;
|
|
|
+import com.td.boss.game.complayerland.pojo.ComPlayerLand;
|
|
|
+import com.td.boss.game.complayerland.pojo.ComPlayerLandAndCanSteal;
|
|
|
+import com.td.boss.game.complayerland.service.ComPlayerLandService;
|
|
|
+import com.td.boss.game.complayerland.vo.ComPlayerLandVo;
|
|
|
+import com.td.boss.game.complayerlog.pojo.ComPlayerLog;
|
|
|
+import com.td.boss.game.complayerlog.service.ComPlayerLogService;
|
|
|
+import com.td.boss.game.complayerlog.vo.ComPlayerLogVo;
|
|
|
+import com.td.boss.game.complayerprofit.pojo.ComPlayerProfit;
|
|
|
+import com.td.boss.game.complayerprofit.service.ComPlayerProfitService;
|
|
|
+import com.td.boss.game.complayerprofit.vo.ComPlayerProfitVo;
|
|
|
+import com.td.boss.game.complayers.vo.ComPlayersVo;
|
|
|
+import com.td.boss.game.complayersattri.service.ComPlayersAttriService;
|
|
|
+import com.td.boss.game.complayersattri.vo.ComPlayersAttriSimpleVo;
|
|
|
+import com.td.boss.game.complayersattri.vo.ComPlayersAttriVo;
|
|
|
+import com.td.boss.game.comsetting.pojo.ComSetting;
|
|
|
+import com.td.boss.game.comsetting.service.ComSettingService;
|
|
|
+import com.td.boss.game.comsetting.vo.ComSettingVo;
|
|
|
+import com.td.boss.game.comsnbtran.pojo.ComSnbTran;
|
|
|
+import com.td.boss.game.comsnbtran.service.ComSnbTranService;
|
|
|
+import com.td.boss.game.comsnbtran.vo.ComSnbTranVo;
|
|
|
+import com.td.boss.game.comusers.service.ComUsersService;
|
|
|
+import com.td.boss.game.comusers.vo.ComUsersVo;
|
|
|
+import com.td.boss.util.*;
|
|
|
+import net.bytebuddy.asm.Advice;
|
|
|
+import org.springframework.beans.factory.annotation.Autowired;
|
|
|
+import org.springframework.transaction.annotation.Transactional;
|
|
|
+import org.springframework.util.StringUtils;
|
|
|
+import org.springframework.web.bind.annotation.*;
|
|
|
+
|
|
|
+import java.math.BigDecimal;
|
|
|
+import java.util.*;
|
|
|
+import java.util.stream.Collectors;
|
|
|
+
|
|
|
+@RestController
|
|
|
+@RequestMapping("/game/comPlayerGoods/")
|
|
|
+public class ComPlayerGoodsController extends CommonController<ComPlayerGoodsVo, ComPlayerGoods, String> {
|
|
|
+ @Autowired
|
|
|
+ private ComPlayerGoodsService comPlayerGoodsService;
|
|
|
+ @Autowired
|
|
|
+ private ComMallSeedService comMallSeedService;
|
|
|
+ @Autowired
|
|
|
+ private ComFruitService comFruitService;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private ComPlayerLandService comPlayerLandService;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private ComPlayerProfitService comPlayerProfitService;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private ComUsersService comUsersService;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private ComPlayersAttriService comPlayersAttriService;
|
|
|
+
|
|
|
+ //交易表service
|
|
|
+ @Autowired
|
|
|
+ private ComSnbTranService comSnbTranService;
|
|
|
+
|
|
|
+ //背包操作日志
|
|
|
+ @Autowired
|
|
|
+ private ComPlayerLogService comPlayerLogService;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private ComExplainLandService comExplainLandService;
|
|
|
+
|
|
|
+ //配置信息
|
|
|
+ @Autowired
|
|
|
+ private ComSettingService comSettingService;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private ComPlayerDogService comPlayerDogService;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private ComMallOtherService comMallOtherService;
|
|
|
+
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private RedisLock redisLock;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取仓库 全部数据,目前使用goods_type区分种子和果实
|
|
|
+ *
|
|
|
+ * @param userId
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ @GetMapping("getSeedAndFruit")
|
|
|
+ public Result<Map> getSeedAndFruitFunction(@RequestParam(value = "userId") String userId) {
|
|
|
+ List<ComPlayerGoods> comPlayerGoodsList = comPlayerGoodsService.findAllByUserId(userId);
|
|
|
+ List<ComMallSeedVo> seedList = new ArrayList<>();
|
|
|
+ List<ComFruitAmountVo> fruitList = new ArrayList<>();
|
|
|
+ comPlayerGoodsList.stream().map(e -> {
|
|
|
+ if (e.getGoodsType().equals(0)) {
|
|
|
+ //种子类型
|
|
|
+ ComMallSeedVo comMallSeedVo = comMallSeedService.findById(e.getGoodsIndex());
|
|
|
+ //数量要用背包的数量
|
|
|
+ comMallSeedVo.setAmount(e.getAmount());
|
|
|
+ seedList.add(comMallSeedVo);
|
|
|
+
|
|
|
+ } else if (e.getGoodsType().equals(1)) {
|
|
|
+ //果实类型
|
|
|
+ //数量要用背包的数量
|
|
|
+ ComFruitVo comFruitVo = comFruitService.findById(e.getGoodsIndex());
|
|
|
+ ComFruitAmountVo comFruitAmountVo = CopyUtil.copy(comFruitVo, ComFruitAmountVo.class);
|
|
|
+ comFruitAmountVo.setAmount(e.getAmount());
|
|
|
+ comFruitAmountVo.setAmountPart(e.getAmountPart());
|
|
|
+ fruitList.add(comFruitAmountVo);
|
|
|
+ }
|
|
|
+ return e;
|
|
|
+ }).collect(Collectors.toList());
|
|
|
+ Map map = new HashMap();
|
|
|
+ map.put("seed", seedList);
|
|
|
+ map.put("fruit", fruitList);
|
|
|
+ return Result.of(map);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取购买的种子状态,如果webSocket未通,
|
|
|
+ * 使用轮询方法查询更新状态
|
|
|
+ *
|
|
|
+ * @param userId
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ @GetMapping("getSeedState")
|
|
|
+ public Result<Map> getSeedStateFunction(
|
|
|
+ @RequestParam(value = "userId") String userId,
|
|
|
+ @RequestParam(value = "seedId") Integer seedId,
|
|
|
+ @RequestParam(value = "currentAmount") Integer currentAmount
|
|
|
+ ) {
|
|
|
+ //查询背包种子存在的数量
|
|
|
+ ComPlayerGoods comPlayerGood = comPlayerGoodsService.findByUserIdAndIndexAndType(userId, seedId, 0);
|
|
|
+ if (comPlayerGood == null) {
|
|
|
+ //如果背包种子是空的,说明还未添加上去
|
|
|
+ return Result.of(null, false, ResultEnum.SEED_DATA_ERROR.getMessage(), ResultEnum.SEED_DATA_ERROR.getCode());
|
|
|
+ }
|
|
|
+ if (comPlayerGood.getAmount() <= currentAmount) {
|
|
|
+ //如果背包数量等于或者小于传进来的,提示轮询未更新
|
|
|
+ return Result.of(null, false, ResultEnum.SEED_AMOUNT_ERROR.getMessage(), ResultEnum.SEED_AMOUNT_ERROR.getCode());
|
|
|
+ } else {
|
|
|
+ Map map = new HashMap();
|
|
|
+ map.put("msg", "背包种子更新成功!");
|
|
|
+ map.put("goodsAmount", comPlayerGood.getAmount());
|
|
|
+ map.put("currentAmount", currentAmount);
|
|
|
+ return Result.of(map);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 收获时候,传入土地id和种子id
|
|
|
+ * <p>
|
|
|
+ * <p>
|
|
|
+ * 收获时候,操作用户snb时候,需要加锁,防止用户收取时候遗漏计算snb
|
|
|
+ *
|
|
|
+ * @param userId
|
|
|
+ * @param landId
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ @PostMapping("addFruit")
|
|
|
+ @ResponseBody
|
|
|
+ @Transactional(rollbackFor = Exception.class)
|
|
|
+ public Result<Map> addFruitFunction(
|
|
|
+ @RequestParam(value = "userId") String userId,
|
|
|
+ @RequestParam(value = "landId") Integer landId) {
|
|
|
+ //todo 确认下是否多倍收成
|
|
|
+ ComPlayerLand comPlayerLand = comPlayerLandService.findByUserIdAndLandId(userId, landId);
|
|
|
+ //土地数据不存在
|
|
|
+ if (comPlayerLand == null) {
|
|
|
+ return Result.of(null, false, ResultEnum.LAND_DATA_ERROR.getMessage(), ResultEnum.LAND_DATA_ERROR.getCode());
|
|
|
+ }
|
|
|
+ //土地未租赁
|
|
|
+ if (!comPlayerLand.getIsLease().equals(1)) {
|
|
|
+ return Result.of(null, false, ResultEnum.LAND_NOT_LEASE.getMessage(), ResultEnum.LAND_NOT_LEASE.getCode());
|
|
|
+ }
|
|
|
+ //土地未种植
|
|
|
+ if (comPlayerLand.getIsPlant().equals(0)) {
|
|
|
+ return Result.of(null, false, ResultEnum.LAND_NOT_PLANT.getMessage(), ResultEnum.LAND_NOT_PLANT.getCode());
|
|
|
+ }
|
|
|
+ //todo 判断土地租赁是否到期,是到期不给种植
|
|
|
+ //租赁的剩余天数 。
|
|
|
+ Long leaseDaysMill = comPlayerLand.getLeaseTime().getTime() - DateUtil.getNowDate().getTime();
|
|
|
+ if (leaseDaysMill <= 0) {
|
|
|
+ // 清除记录的数据
|
|
|
+ // 1.土地租赁到期,删除土地租赁数据
|
|
|
+ comPlayerLandService.delete(comPlayerLand.getId());
|
|
|
+ // 2.把删除的这个土地的数据记录到com_explain_land中去
|
|
|
+ ComExplainLandVo comExplainLandVo = new ComExplainLandVo();
|
|
|
+ comExplainLandVo = CopyUtil.copy(comPlayerLand, ComExplainLandVo.class);
|
|
|
+ comExplainLandVo.setLandId(comPlayerLand.getConfigLandId());
|
|
|
+ comExplainLandVo.setLandCreate(comPlayerLand.getCreateTime());
|
|
|
+ comExplainLandVo.setExplainType(0);
|
|
|
+ comExplainLandVo.setExplainDescribe("收获果实时:土地租赁过期回收");
|
|
|
+ comExplainLandVo.setCreateTime(new Date());
|
|
|
+ comExplainLandVo.setUpdateTime(new Date());
|
|
|
+ comExplainLandService.save(comExplainLandVo);
|
|
|
+ return Result.of(null, false, ResultEnum.LAND_LEASE_EXPIRED.getMessage(), ResultEnum.LAND_LEASE_EXPIRED.getCode());
|
|
|
+ }
|
|
|
+
|
|
|
+ //获取种植的种子
|
|
|
+ ComMallSeedVo comMallSeedVo = comMallSeedService.findById(comPlayerLand.getPlantId());
|
|
|
+ if (comMallSeedVo == null) {
|
|
|
+ return Result.of(null, false, ResultEnum.SEED_DATA_ERROR.getMessage(), ResultEnum.SEED_DATA_ERROR.getCode());
|
|
|
+ }
|
|
|
+
|
|
|
+ // 收获,同时重置土地状态,先判断是否成熟
|
|
|
+ //当前时间减去 成熟期,判断是否成熟
|
|
|
+ Date _harvestTime = DateUtil.getNowDateMinusDay(comMallSeedVo.getMaturity());
|
|
|
+ // 两个时间差, 逻辑是_harvestTime 时间慢慢接近种植时间
|
|
|
+ long diff = comPlayerLand.getPlantStart().getTime() - _harvestTime.getTime();
|
|
|
+ //if (DateUtil.getNowDateMinusDay(comMallSeedVo.getMaturity()).getTime() < comPlayerLand.getPlantStart().getTime())
|
|
|
+ if (diff > 0) {
|
|
|
+ //如果当前时间减去种子的成熟期,还是小于种植日期,则判断未成熟
|
|
|
+ return Result.of(null, false, ResultEnum.SEED_DATE_ERROR.getMessage(), ResultEnum.SEED_DATE_ERROR.getCode());
|
|
|
+ }
|
|
|
+ //获取数据库相关配置
|
|
|
+ ComSettingVo comSettingVo = comSettingService.get("1").getData();
|
|
|
+ if (comSettingVo.equals(null)) {
|
|
|
+ return Result.of(null, false, ResultEnum.SETTING_IS_NULL.getMessage(), ResultEnum.SETTING_IS_NULL.getCode());
|
|
|
+ }
|
|
|
+
|
|
|
+ //需要redis 加锁
|
|
|
+ long time = System.currentTimeMillis() + RedisData.getPlayerGoodsTimeout();
|
|
|
+ //获取用户的plantFlag,因为之前的用户没有设置这个flag,所以设为第一次,用 userId 和 landId 组合成key
|
|
|
+ String _redisKey = comPlayerLand.getPlantFlag();
|
|
|
+ if (!StringUtils.hasText(_redisKey)) {
|
|
|
+ //return Result.of(null, false, ResultEnum.LAND_PLANT_FLAG_IS_NULL.getMessage(), ResultEnum.LAND_PLANT_FLAG_IS_NULL.getCode());
|
|
|
+ _redisKey = comPlayerLand.getUserId() + "or" + comPlayerLand.getConfigLandId();
|
|
|
+ }
|
|
|
+ Map map = new HashMap();
|
|
|
+ //todo 总共偷去的数量
|
|
|
+ Double _stealProfits = 0d;
|
|
|
+ try {
|
|
|
+ // 如果存在plantFlag 说明是新种植的
|
|
|
+ if (!redisLock.lock(_redisKey, String.valueOf(time))) {
|
|
|
+ return Result.of(null, false, ResultEnum.LAND_STEAL_LOCK.getMessage(), ResultEnum.LAND_STEAL_LOCK.getCode());
|
|
|
+ }
|
|
|
+
|
|
|
+ //设置一个未种植状态即可
|
|
|
+ comPlayerLand.setIsPlant(0);
|
|
|
+ ComPlayerLandVo comPlayerLandVo = CopyUtil.copy(comPlayerLand, ComPlayerLandVo.class);
|
|
|
+ comPlayerLandService.save(comPlayerLandVo);
|
|
|
+
|
|
|
+ //计算一个收获量, 租赁倍数* 租赁日期下的产量
|
|
|
+ Integer _amount = 0;
|
|
|
+ Double _amountPart = 0d;
|
|
|
+ if (comPlayerLand.getLeaseDate().equals(1)) {
|
|
|
+ _amount = comPlayerLand.getLeaseMultiple() * comMallSeedVo.getHarvest1();
|
|
|
+ } else if (comPlayerLand.getLeaseDate().equals(2)) {
|
|
|
+ _amount = comPlayerLand.getLeaseMultiple() * comMallSeedVo.getHarvest2();
|
|
|
+ } else if (comPlayerLand.getLeaseDate().equals(3)) {
|
|
|
+ _amount = comPlayerLand.getLeaseMultiple() * comMallSeedVo.getHarvest3();
|
|
|
+ }
|
|
|
+ //todo 收获果实时候,需要减去一个被偷取的利润,然后判断一个是否大于设置的利润,超出了报异常,并且收取的数量不能为小于0
|
|
|
+ // 拿出计算利润,收获量减去种子的成本(snb)后的百分之20 ,后面需要后台可调整
|
|
|
+ Integer _profit = _amount - comPlayerLand.getLeaseMultiple() * comMallSeedVo.getPriceSnb();
|
|
|
+ // 配置的参数。这里先直接定义
|
|
|
+ Double profitConfig = comSettingVo.getProfit(), stealRatioMaxConfig = comSettingVo.getStealMaxRatio(), stealRatioMinConfig = comSettingVo.getStealMinRatio(), finallyGetRatioConfig = comSettingVo.getFinalRatio();
|
|
|
+
|
|
|
+ Double _profitDouble = _profit.doubleValue();
|
|
|
+ Double _residualProfit = DoubleUtil.mul(_profitDouble, DoubleUtil.sub(1d, profitConfig));//如果 profitConfig 0.2,剩余利润就是0.8;
|
|
|
+ Double _stealAmount = DoubleUtil.sub(_profitDouble, _residualProfit); //可偷取的利润
|
|
|
+
|
|
|
+ //todo 计算总共损失的数量
|
|
|
+ List<ComPlayerProfit> comPlayerProfits = comPlayerProfitService.findByUserIdAndPlantFlagAndLandId(userId, _redisKey, comPlayerLand.getConfigLandId());
|
|
|
+ for (int i = 0; i < comPlayerProfits.size(); i++) {
|
|
|
+ ComPlayerProfit temp = comPlayerProfits.get(i);
|
|
|
+ _stealProfits = DoubleUtil.add(_stealProfits, temp.getStolen());
|
|
|
+ }
|
|
|
+ Double _userHarvestPart = DoubleUtil.sub(_stealAmount, _stealProfits);
|
|
|
+ if (_userHarvestPart < 0.0) {
|
|
|
+ //差值不能为负数
|
|
|
+ _userHarvestPart = 0d;
|
|
|
+ //相当于被偷取全部利润,这里返回一个被偷去的全部利润值
|
|
|
+ map.put("lossAmount", _stealAmount);
|
|
|
+ } else {
|
|
|
+ //todo 返回一个被偷的数量
|
|
|
+ map.put("lossAmount", _stealProfits);
|
|
|
+ }
|
|
|
+
|
|
|
+ //todo 利润
|
|
|
+ _amount -= _profit;
|
|
|
+ //用户收取的对应数量,固定收入+被偷取后剩余的部分
|
|
|
+ _amountPart = DoubleUtil.add(_residualProfit, _userHarvestPart);
|
|
|
+ //果实 Type =1
|
|
|
+ ComPlayerGoods comPlayerGoodsSimpleVo = comPlayerGoodsService.findByUserIdAndIndexAndType(userId, comMallSeedVo.getHarvestId(), 1);
|
|
|
+ Integer _beforeAmount = 0;
|
|
|
+ Double _beforeProfitPart = 0d, _afterProfitPart = 0d;
|
|
|
+ if (comPlayerGoodsSimpleVo == null) {
|
|
|
+ //背包增加果实
|
|
|
+ comPlayerGoodsSimpleVo = new ComPlayerGoods();
|
|
|
+ comPlayerGoodsSimpleVo.setUserId(userId);
|
|
|
+ comPlayerGoodsSimpleVo.setGoodsIndex(comMallSeedVo.getHarvestId());
|
|
|
+ comPlayerGoodsSimpleVo.setGoodsType(1);
|
|
|
+ comPlayerGoodsSimpleVo.setName(comMallSeedVo.getHarvestName());
|
|
|
+ //用种子的picture
|
|
|
+ comPlayerGoodsSimpleVo.setPictureName(comMallSeedVo.getPicture());
|
|
|
+ comPlayerGoodsSimpleVo.setAmount(_amount);
|
|
|
+ comPlayerGoodsSimpleVo.setAmountPart(_amountPart);
|
|
|
+
|
|
|
+ _beforeAmount = 0;
|
|
|
+ _beforeProfitPart = 0d;
|
|
|
+ _afterProfitPart = comPlayerGoodsSimpleVo.getAmountPart();
|
|
|
+ } else {
|
|
|
+ _beforeAmount = comPlayerGoodsSimpleVo.getAmount();
|
|
|
+ _beforeProfitPart = comPlayerGoodsSimpleVo.getAmountPart();
|
|
|
+
|
|
|
+ comPlayerGoodsSimpleVo.setAmount(comPlayerGoodsSimpleVo.getAmount() + _amount);
|
|
|
+ //用户利润部分
|
|
|
+ comPlayerGoodsSimpleVo.setAmountPart(DoubleUtil.add(comPlayerGoodsSimpleVo.getAmountPart(), _amountPart));
|
|
|
+
|
|
|
+ _afterProfitPart = comPlayerGoodsSimpleVo.getAmountPart();
|
|
|
+ }
|
|
|
+
|
|
|
+ ComPlayerGoodsVo comPlayerGoodsVo = CopyUtil.copy(comPlayerGoodsSimpleVo, ComPlayerGoodsVo.class);
|
|
|
+ comPlayerGoodsService.save(comPlayerGoodsVo);
|
|
|
+
|
|
|
+ //todo 记录一个收获的操作日志
|
|
|
+ ComPlayerLog _playerLog = new ComPlayerLog();
|
|
|
+ _playerLog.setUserId(userId);
|
|
|
+ _playerLog.setTId(comMallSeedVo.getHarvestId());
|
|
|
+ _playerLog.setTName(comMallSeedVo.getHarvestName());
|
|
|
+ _playerLog.setTType(0);//设置一个默认水果id
|
|
|
+ _playerLog.setTAmount(_amount);
|
|
|
+ _playerLog.setBeforeAmount(_beforeAmount);
|
|
|
+ ////交易后的数据
|
|
|
+ _playerLog.setAfterAmount(comPlayerGoodsSimpleVo.getAmount());
|
|
|
+ //收取时候信息记录
|
|
|
+ _playerLog.setTPart(_amountPart);
|
|
|
+ _playerLog.setTLoss(_stealProfits); //损失的部分
|
|
|
+ _playerLog.setBeforePart(_beforeProfitPart);
|
|
|
+ _playerLog.setAfterPart(_afterProfitPart);
|
|
|
+ _playerLog.setLMultiple(comPlayerLand.getLeaseMultiple());
|
|
|
+ ComPlayerLogVo _playerLogVo = CopyUtil.copy(_playerLog, ComPlayerLogVo.class);
|
|
|
+ comPlayerLogService.save(_playerLogVo);
|
|
|
+
|
|
|
+ //对应的,存在plantFlag则解锁
|
|
|
+ redisLock.unlock(_redisKey, String.valueOf(time));
|
|
|
+ } catch (Exception e) {
|
|
|
+ //对应的,存在plantFlag则解锁
|
|
|
+ redisLock.unlock(_redisKey, String.valueOf(time));
|
|
|
+ throw new RuntimeException(e.getMessage());
|
|
|
+ }
|
|
|
+ map.put("msg", "成功收取果实!");
|
|
|
+ return Result.of(map);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 按土地收取水果果实时候,传入对方用户id 和土地id
|
|
|
+ * <p>
|
|
|
+ * <p>
|
|
|
+ * 收获时候,操作用户snb时候,需要加锁,防止用户收取时候遗漏计算snb
|
|
|
+ *
|
|
|
+ * @param otherUserId
|
|
|
+ * @param otherLandId
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ @PostMapping("stealFruit")
|
|
|
+ @ResponseBody
|
|
|
+ @Transactional(rollbackFor = Exception.class)
|
|
|
+ public Result<Map> stealFruitFunction(
|
|
|
+ @RequestParam(value = "userId") String userId,
|
|
|
+ @RequestParam(value = "otherUserId") String otherUserId,
|
|
|
+ @RequestParam(value = "otherLandId") Integer otherLandId) {
|
|
|
+ Map map = new HashMap();
|
|
|
+
|
|
|
+ //todo 计入狗和打狗棒
|
|
|
+ Boolean _dogWork = false;//狗是否工作,默认不工作
|
|
|
+ Boolean _wasTheDogBitten = false; //默认没有被狗咬
|
|
|
+ Boolean _holdTheStick = false;//默认没持有棒子
|
|
|
+ Boolean _hasReduceSnb = false;//是否可以扣除偷菜的snb
|
|
|
+ //对方的狗
|
|
|
+ ComPlayerDog _otherDogVo = comPlayerDogService.findByUserIdAndType(otherUserId, 0);
|
|
|
+ if (_otherDogVo != null) {
|
|
|
+ //有狗或者有狗粮时候,处理狗的事件
|
|
|
+ //todo 计算狗是否到期
|
|
|
+ long _runDay = DateUtil.getDays(DateUtil.getNowDate().getTime() - _otherDogVo.getEffectiveStartTime().getTime());
|
|
|
+ int _remainingDay = _otherDogVo.getEffectiveDay() - (int) _runDay;
|
|
|
+ // 存在时间
|
|
|
+ if (_remainingDay > 0) {
|
|
|
+ //todo 这里判断狗粮是否足够
|
|
|
+ long _diffConsumptionMill = _otherDogVo.getConsumptionUpdate().getTime() - DateUtil.getNowDate().getTime();
|
|
|
+ long _workHours = DateUtil.getHours(_diffConsumptionMill);
|
|
|
+ //工作多少个小时,消耗多少狗粮
|
|
|
+ long _needConsumption = _otherDogVo.getConsumption() - _workHours;
|
|
|
+ if (_needConsumption > 0) {
|
|
|
+ //口粮足够,工作
|
|
|
+ _dogWork = true;
|
|
|
+ //狗存在并工作,获取狗的数据
|
|
|
+ ComMallOtherVo _mallDogData = comMallOtherService.get(_otherDogVo.getOtherIndex()).getData();
|
|
|
+ Double _triggerPro = _mallDogData.getTriggerPro();//触发概率
|
|
|
+ if (new Random().nextDouble() <= _triggerPro) {
|
|
|
+ //被狗咬了
|
|
|
+ _wasTheDogBitten = true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ //
|
|
|
+ //己方的打狗棒
|
|
|
+ ComPlayerDog _beatDogStick = comPlayerDogService.findByUserIdAndType(userId, 1);
|
|
|
+
|
|
|
+ if (_beatDogStick != null) {
|
|
|
+ //todo 判断打狗棒是否到期
|
|
|
+ long _stickRunDay = DateUtil.getDays(DateUtil.getNowDate().getTime() - _beatDogStick.getEffectiveStartTime().getTime());
|
|
|
+ int _stickRemainingDay = _beatDogStick.getEffectiveDay() - (int) _stickRunDay;
|
|
|
+ if(_stickRemainingDay>0){
|
|
|
+ //持有打狗棒
|
|
|
+ _holdTheStick = true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ //获取数据库相关配置
|
|
|
+ ComSettingVo comSettingVo = comSettingService.get("1").getData();
|
|
|
+ if (comSettingVo.equals(null)) {
|
|
|
+ return Result.of(null, false, ResultEnum.SETTING_IS_NULL.getMessage(), ResultEnum.SETTING_IS_NULL.getCode());
|
|
|
+ }
|
|
|
+ //todo 后台可配置,获取一个链上数据
|
|
|
+ Integer _configStrength = comSettingVo.getMaxStrength(), _chainStrength = DappUtil.getChildrenCount(userId);
|
|
|
+ //前端的显示,输出一个不小于0的体力值
|
|
|
+ Integer _maxStrength = _configStrength + _chainStrength;
|
|
|
+ //1.先判断用户是否有足够的体力,根据snb判断。2. 收取到果实,扣除用户一个体力值
|
|
|
+ ComUsersVo comUsersVo = comUsersService.findByUserId(userId);
|
|
|
+ ComPlayersAttriVo playersAttribute = comPlayersAttriService.findByUserId(userId);
|
|
|
+ Integer _out = _maxStrength - Math.abs(playersAttribute.getStrength());
|
|
|
+ Double _userAllSnb = DoubleUtil.add(comUsersVo.getSnb().doubleValue(), comUsersVo.getSnbPart());
|
|
|
+ //判断是否有足够的snb
|
|
|
+ if (DoubleUtil.compare(_userAllSnb, comSettingVo.getDeductSnb()) == -1) {
|
|
|
+ _hasReduceSnb = false;
|
|
|
+ //没有足够的snb
|
|
|
+ //如果没有被狗咬,,正常扣除1点体力
|
|
|
+ //如果被狗咬了,除了正常扣除1点体力外,额外扣除1点体力
|
|
|
+ if (_wasTheDogBitten) {
|
|
|
+ //判断是否有双倍体力
|
|
|
+ if (_out < comSettingVo.getSnbUnitStrength()) {
|
|
|
+ map.put("msg", "需要双倍体力:" + comSettingVo.getSnbUnitStrength());
|
|
|
+ return Result.of(map, false, ResultEnum.PLAYER_ATTRIBUTE_STRENGTH_IS_NOT.getMessage(), ResultEnum.PLAYER_ATTRIBUTE_STRENGTH_IS_NOT.getCode());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ _hasReduceSnb = true;
|
|
|
+ //正常判断体力
|
|
|
+ if (_out < comSettingVo.getUnitStrength()) {
|
|
|
+ map.put("msg", "需要单倍体力:" + comSettingVo.getUnitStrength());
|
|
|
+ return Result.of(map, false, ResultEnum.PLAYER_ATTRIBUTE_STRENGTH_IS_NOT.getMessage(), ResultEnum.PLAYER_ATTRIBUTE_STRENGTH_IS_NOT.getCode());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ //List<Map> _stealLandInfos = new ArrayList<>();
|
|
|
+ Double _finalStealAmountSum = 0d;
|
|
|
+ //todo 偷取用户目标的信息,即otherUserId和otherLandId
|
|
|
+ ComPlayerLand otherPlayerLand = comPlayerLandService.findByUserIdAndLandId(otherUserId, otherLandId);
|
|
|
+ if (otherPlayerLand == null) {
|
|
|
+ return Result.of(null, false, ResultEnum.LAND_CAN_STEAL_IS_NULL.getMessage(), ResultEnum.LAND_CAN_STEAL_IS_NULL.getCode());
|
|
|
+ }
|
|
|
+ //snb 的key
|
|
|
+ String _redisSNBKey = "SNB_SAVE_" + userId;
|
|
|
+ //获取用户的plantFlag,因为之前的用户没有设置这个flag,所以设为第一次,用 userId 和 landId 组合成key
|
|
|
+ String _redisKey = otherPlayerLand.getPlantFlag();
|
|
|
+ if (!StringUtils.hasText(_redisKey)) {
|
|
|
+ //return Result.of(null, false, ResultEnum.LAND_PLANT_FLAG_IS_NULL.getMessage(), ResultEnum.LAND_PLANT_FLAG_IS_NULL.getCode());
|
|
|
+ _redisKey = otherPlayerLand.getUserId() + "or" + otherPlayerLand.getConfigLandId();
|
|
|
+ }
|
|
|
+ //todo 先判断是否偷取过
|
|
|
+ ComPlayerProfit comPlayerProfit = comPlayerProfitService.findByUserIdAndOtherUserIdAndPlantFlag(userId, otherUserId, _redisKey);
|
|
|
+ if (comPlayerProfit != null) {
|
|
|
+ return Result.of(null, false, ResultEnum.LAND_HARVEST_STOLEN.getMessage(), ResultEnum.LAND_HARVEST_STOLEN.getCode());
|
|
|
+ }
|
|
|
+ //获取当前种植的种子
|
|
|
+ ComMallSeedVo comMallSeedVo = comMallSeedService.findById(otherPlayerLand.getPlantId());
|
|
|
+ //需要redis 加锁
|
|
|
+ long time = System.currentTimeMillis() + RedisData.getPlayerGoodsTimeout();
|
|
|
+
|
|
|
+ try {
|
|
|
+ if (!redisLock.lock(_redisSNBKey, String.valueOf(time))) {
|
|
|
+ //如果有snb冲突锁
|
|
|
+ return Result.of(null, false, ResultEnum.USER_LOGIN_LOCK.getMessage(), ResultEnum.USER_LOGIN_LOCK.getCode());
|
|
|
+
|
|
|
+ }
|
|
|
+ if (!redisLock.lock(_redisKey, String.valueOf(time))) {
|
|
|
+ //如果有冲突锁
|
|
|
+ return Result.of(null, false, ResultEnum.LAND_STEAL_LOCK.getMessage(), ResultEnum.LAND_STEAL_LOCK.getCode());
|
|
|
+ }
|
|
|
+ //todo 如果当前人员偷窃水果。记录一个信息,存储当前玩家已偷过的水果的信息
|
|
|
+ //计算一个偷取的收获量, 租赁倍数* 租赁日期下的产量
|
|
|
+ Integer _otherAmount = 0;
|
|
|
+ if (otherPlayerLand.getLeaseDate().equals(1)) {
|
|
|
+ _otherAmount = otherPlayerLand.getLeaseMultiple() * comMallSeedVo.getHarvest1();
|
|
|
+ } else if (otherPlayerLand.getLeaseDate().equals(2)) {
|
|
|
+ _otherAmount = otherPlayerLand.getLeaseMultiple() * comMallSeedVo.getHarvest2();
|
|
|
+ } else if (otherPlayerLand.getLeaseDate().equals(3)) {
|
|
|
+ _otherAmount = otherPlayerLand.getLeaseMultiple() * comMallSeedVo.getHarvest3();
|
|
|
+ }
|
|
|
+ //todo 拿出计算利润,收获量减去种子的成本(snb)后的百分之30 ,后面需要后台可调整
|
|
|
+ Integer _profit = _otherAmount - otherPlayerLand.getLeaseMultiple() * comMallSeedVo.getPriceSnb();
|
|
|
+ // 配置的参数。这里先直接定义
|
|
|
+ // 需要根据 狗是否生效,小偷是否装备打狗棒来确定参数
|
|
|
+ Double profitConfig = _dogWork ? comSettingVo.getProfitDog() : comSettingVo.getProfit(),
|
|
|
+ stealRatioMaxConfig = comSettingVo.getStealMaxRatio(),
|
|
|
+ stealRatioMinConfig = comSettingVo.getStealMinRatio(),
|
|
|
+ finallyGetRatioConfig = comSettingVo.getFinalRatio();
|
|
|
+ Double _stealRatio = new Random().nextDouble() * DoubleUtil.sub(stealRatioMaxConfig, stealRatioMinConfig) + stealRatioMinConfig;// 1%-3%
|
|
|
+ //todo 被偷取的人扣除 一个损失量,初利润算 _profit
|
|
|
+ // 如果狗生效,根据装备了打狗棒,设置对应的偷窃比例
|
|
|
+ if (_dogWork) {
|
|
|
+ _stealRatio = _holdTheStick ? comSettingVo.getStealRatioHasStick() : comSettingVo.getStealRatioNoStick();
|
|
|
+ }
|
|
|
+ Double _stolenAmount = DoubleUtil.mul(_profit.doubleValue(), _stealRatio);
|
|
|
+ //这里根据plantFlag判断目标用户当前种植被偷取完,记录更新用户 comPlayerLand plantSteal 字段;保存一个偷取状态
|
|
|
+ Double _sumStolen = comPlayerProfitService.getStolenSumByOtherUserIdAndPlantFlag(otherUserId, _redisKey);
|
|
|
+ //todo 这里的可偷利润应该是最大值,用户不能超过这个,需要限制判断
|
|
|
+ Double _maxAmount = DoubleUtil.mul(_profit.doubleValue(), profitConfig); //可偷取的利润
|
|
|
+ //1 单偷操作 就是 _sumStolen>_maxAmount 或者 _sumStolen == _maxAmount ,被偷完了
|
|
|
+ if (!DoubleUtil.compare(_sumStolen, _maxAmount).equals(-1)) {
|
|
|
+ // 需要redis 解锁
|
|
|
+ redisLock.unlock(_redisKey, String.valueOf(time));
|
|
|
+ redisLock.unlock(_redisSNBKey, String.valueOf(time));
|
|
|
+ //记录一个不可偷取的状态
|
|
|
+ otherPlayerLand.setPlantSteal(0);
|
|
|
+ comPlayerLandService.save(CopyUtil.copy(otherPlayerLand, ComPlayerLandVo.class));
|
|
|
+ map.put("plant_steal", otherPlayerLand.getPlantSteal());
|
|
|
+ return Result.of(map, false, ResultEnum.LAND_CAN_STEAL_IS_MAX.getMessage(), ResultEnum.LAND_CAN_STEAL_IS_MAX.getCode());
|
|
|
+ }
|
|
|
+ //计算剩下可偷利润的差,防止过多偷取用户利润 _stolenAmount
|
|
|
+ Double _diff = Math.abs(DoubleUtil.sub(_maxAmount, _sumStolen));
|
|
|
+ if (DoubleUtil.compare(_stolenAmount, _diff).equals(1)) {
|
|
|
+ //_stolenAmount>_diff
|
|
|
+ _stolenAmount = _diff;
|
|
|
+ }
|
|
|
+ //最终偷窃人获取的是偷取的是目标用户损失量的10% finallyGetRatioConfig
|
|
|
+ Double _finalStealAmount = DoubleUtil.mul(_stolenAmount, finallyGetRatioConfig);
|
|
|
+ //偷窃后,系统回收部分
|
|
|
+ Double _lostStealAmount = DoubleUtil.sub(1d, finallyGetRatioConfig) * _stolenAmount;
|
|
|
+ //果实 Type =1
|
|
|
+ //todo 增加一个字段处理背包果实,拿出当前用户背包果实
|
|
|
+ ComPlayerGoods comPlayerGoods = comPlayerGoodsService.findByUserIdAndIndexAndType(userId, comMallSeedVo.getHarvestId(), 1);
|
|
|
+ Double _beforeStealAmount = 0.0;
|
|
|
+ if (comPlayerGoods == null) {
|
|
|
+ //背包增加收取到别的用户对应的类型数量。比如当前是偷取到的果实
|
|
|
+ comPlayerGoods = new ComPlayerGoods();
|
|
|
+ comPlayerGoods.setUserId(userId);
|
|
|
+ comPlayerGoods.setGoodsIndex(comMallSeedVo.getHarvestId());
|
|
|
+ comPlayerGoods.setGoodsType(1);
|
|
|
+ comPlayerGoods.setName(comMallSeedVo.getHarvestName());
|
|
|
+ //用种子的picture
|
|
|
+ comPlayerGoods.setPictureName(comMallSeedVo.getPicture());
|
|
|
+ //amount 设置0
|
|
|
+ comPlayerGoods.setAmount(0);
|
|
|
+ comPlayerGoods.setAmountPart(_finalStealAmount);
|
|
|
+ _beforeStealAmount = 0.0;
|
|
|
+ } else {
|
|
|
+ _beforeStealAmount = comPlayerGoods.getAmountPart();
|
|
|
+ //修改偷取字段
|
|
|
+ comPlayerGoods.setAmountPart(DoubleUtil.add(comPlayerGoods.getAmountPart(), _finalStealAmount));
|
|
|
+ }
|
|
|
+ ComPlayerGoodsVo comPlayerGoodsVo = CopyUtil.copy(comPlayerGoods, ComPlayerGoodsVo.class);
|
|
|
+ comPlayerGoodsService.save(comPlayerGoodsVo);
|
|
|
+
|
|
|
+ //todo 偷窃损失,处理目标用户收取果实时候,减扣一部分被偷取的数量
|
|
|
+ comPlayerProfit = new ComPlayerProfit();
|
|
|
+ comPlayerProfit.setUserId(userId);
|
|
|
+ comPlayerProfit.setTargetId(otherUserId);
|
|
|
+ comPlayerProfit.setPlantFlag(_redisKey);
|
|
|
+ comPlayerProfit.setLandId(otherPlayerLand.getConfigLandId());
|
|
|
+ comPlayerProfit.setLeaseMultiple(otherPlayerLand.getLeaseMultiple());
|
|
|
+ comPlayerProfit.setLeaseDate(otherPlayerLand.getLeaseDate());
|
|
|
+ comPlayerProfit.setHarvest(_otherAmount);
|
|
|
+ comPlayerProfit.setProfit(_profit.doubleValue());//目标用户可偷的初始利润值
|
|
|
+ comPlayerProfit.setStolen(_stolenAmount);//目标用户被偷的数量
|
|
|
+ comPlayerProfit.setFinalSteal(_finalStealAmount);//用户最终偷取的量,是被偷的数量 10%左右
|
|
|
+ comPlayerProfit.setProfitAfter(DoubleUtil.sub(_profit.doubleValue(), DoubleUtil.add(_stolenAmount, _sumStolen))); //可偷的减去被偷的
|
|
|
+ //记录相关比例
|
|
|
+ comPlayerProfit.setProfitRatio(profitConfig);
|
|
|
+ comPlayerProfit.setStealRatio(_stealRatio);
|
|
|
+ comPlayerProfit.setFinalRatio(finallyGetRatioConfig);
|
|
|
+ ComPlayerProfitVo comPlayerProfitVo = CopyUtil.copy(comPlayerProfit, ComPlayerProfitVo.class);
|
|
|
+ comPlayerProfitService.save(comPlayerProfitVo);
|
|
|
+
|
|
|
+ //todo 记录一个收获的操作日志,这里的数量都与偷窃知道相关。amountPart,注意不是果实实际总数 amount
|
|
|
+ ComPlayerLog _playerLog = new ComPlayerLog();
|
|
|
+ _playerLog.setUserId(userId);
|
|
|
+ _playerLog.setTId(comMallSeedVo.getHarvestId());
|
|
|
+ _playerLog.setTName(comMallSeedVo.getHarvestName());
|
|
|
+ _playerLog.setTType(6);//偷取果实时候,type设置6
|
|
|
+ //偷水果时候这部分数据应该是不变的
|
|
|
+ _playerLog.setTAmount(0);
|
|
|
+ _playerLog.setBeforeAmount(comPlayerGoods.getAmount());
|
|
|
+ _playerLog.setAfterAmount(comPlayerGoods.getAmount());
|
|
|
+ //偷取用户果实时候,收取时候信息记录
|
|
|
+ _playerLog.setBeforePart(_beforeStealAmount);
|
|
|
+ _playerLog.setTPart(_finalStealAmount);
|
|
|
+ _playerLog.setTLoss(_lostStealAmount); //损失的部分
|
|
|
+ _playerLog.setAfterPart(comPlayerGoods.getAmountPart());
|
|
|
+ _playerLog.setLMultiple(otherPlayerLand.getLeaseMultiple());
|
|
|
+ ComPlayerLogVo _playerLogVo = CopyUtil.copy(_playerLog, ComPlayerLogVo.class);
|
|
|
+ comPlayerLogService.save(_playerLogVo);
|
|
|
+
|
|
|
+ //todo 成功收取记录一个土地id
|
|
|
+ Map _landMap = new HashMap();
|
|
|
+ //记录一个id
|
|
|
+ _landMap.put("landId", otherPlayerLand.getConfigLandId());
|
|
|
+ //
|
|
|
+ _landMap.put("stealAmount", _finalStealAmount);
|
|
|
+
|
|
|
+ //固定成本
|
|
|
+ _landMap.put("cost", otherPlayerLand.getLeaseMultiple() * comMallSeedVo.getPriceSnb());
|
|
|
+ //当前利润
|
|
|
+ _landMap.put("profit", _profit);
|
|
|
+ //打印一个比例
|
|
|
+ _landMap.put("profitRatio", profitConfig);
|
|
|
+ _landMap.put("intervalStealRatio", _stealRatio);
|
|
|
+ _landMap.put("finallyGetRatioConfig", finallyGetRatioConfig);
|
|
|
+
|
|
|
+ _finalStealAmountSum = DoubleUtil.add(_finalStealAmount, _finalStealAmountSum);
|
|
|
+ // 需要redis 解锁
|
|
|
+ redisLock.unlock(_redisKey, String.valueOf(time));
|
|
|
+
|
|
|
+ map.put("msg", "偷取果实.");
|
|
|
+ map.put("stealInfo", _landMap);
|
|
|
+ map.put("stealSum", _finalStealAmountSum);
|
|
|
+
|
|
|
+ //todo 体力值可以后台配置
|
|
|
+ Integer _addStrength = comSettingVo.getUnitStrength();
|
|
|
+ if (_hasReduceSnb) {
|
|
|
+ /**
|
|
|
+ * todo 偷取果实时候snb变动
|
|
|
+ */
|
|
|
+ ComSnbTranVo _snbTran = new ComSnbTranVo();
|
|
|
+ _snbTran.setBeforeSnb(comUsersVo.getSnb());
|
|
|
+ _snbTran.setBeforeSnbPart(comUsersVo.getSnbPart());
|
|
|
+
|
|
|
+ //如果有snb,扣除对应的snb
|
|
|
+ //先判断 SnbPart 部分是否有足够来扣取
|
|
|
+ if (DoubleUtil.compare(comUsersVo.getSnbPart(), comSettingVo.getDeductSnb()) == -1) {
|
|
|
+ //如果不足,取1扣取
|
|
|
+ Integer _deductSnbMaxInt = (int) Math.ceil(comSettingVo.getDeductSnb());
|
|
|
+ comUsersVo.setSnb(comUsersVo.getSnb() - _deductSnbMaxInt);
|
|
|
+ Double _deductSnbPart = DoubleUtil.sub(1d, comSettingVo.getDeductSnb());
|
|
|
+ comUsersVo.setSnbPart(DoubleUtil.add(comUsersVo.getSnbPart(), _deductSnbPart));
|
|
|
+
|
|
|
+ _snbTran.setTranSnb(0);
|
|
|
+ _snbTran.setTranSnbPart(comSettingVo.getDeductSnb());
|
|
|
+ } else {
|
|
|
+ //直接用snbPart 减去小数点部分即可
|
|
|
+ Double _deductSnbPart = DoubleUtil.sub(comUsersVo.getSnbPart(), comSettingVo.getDeductSnb());
|
|
|
+ comUsersVo.setSnbPart(_deductSnbPart);
|
|
|
+ _snbTran.setTranSnb(0);//整数部分没有进行交易
|
|
|
+ _snbTran.setTranSnbPart(comSettingVo.getDeductSnb());
|
|
|
+ }
|
|
|
+ //记录修改的数据
|
|
|
+ comUsersService.save(comUsersVo);
|
|
|
+
|
|
|
+ //记录果实id,记录交易数据
|
|
|
+ _snbTran.setTranId(comMallSeedVo.getHarvestId().toString());
|
|
|
+ _snbTran.setUserId(userId);
|
|
|
+ _snbTran.setTranName("偷取果实");
|
|
|
+ _snbTran.setTranType(4);
|
|
|
+ _snbTran.setTranAmount(0); //此数量会操作背包记录
|
|
|
+ _snbTran.setTranAmountPart(_finalStealAmount);
|
|
|
+ _snbTran.setTranPrice(0);
|
|
|
+ _snbTran.setTranDescribe("偷取用户果实消耗的snb");
|
|
|
+ _snbTran.setIsAdd(0);//减少
|
|
|
+ _snbTran.setAfterSnb(comUsersVo.getSnb());
|
|
|
+ _snbTran.setAfterSnbPart(comUsersVo.getSnbPart());
|
|
|
+ comSnbTranService.save(_snbTran);
|
|
|
+
|
|
|
+ } else {
|
|
|
+ //被狗咬掉双倍体力
|
|
|
+ if (_wasTheDogBitten) {
|
|
|
+ _addStrength = comSettingVo.getSnbUnitStrength();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ playersAttribute.setStrength(playersAttribute.getStrength() + _addStrength);
|
|
|
+ comPlayersAttriService.save(playersAttribute);
|
|
|
+ ComPlayersAttriSimpleVo comPlayersAttriSimpleVo = CopyUtil.copy(playersAttribute, ComPlayersAttriSimpleVo.class);
|
|
|
+ //前端的显示,输出一个不小于0的体力值
|
|
|
+ Integer _outEnd = _maxStrength - Math.abs(playersAttribute.getStrength());
|
|
|
+ comPlayersAttriSimpleVo.setCurrentStrength(_outEnd < 0 ? 0 : _outEnd);
|
|
|
+ //最大值是配置的值和链上数据的值相加
|
|
|
+ comPlayersAttriSimpleVo.setMaxStrength(_maxStrength);
|
|
|
+
|
|
|
+ map.put("playerAttribute", comPlayersAttriSimpleVo);
|
|
|
+
|
|
|
+ //输出对应的判定值
|
|
|
+ map.put("dogWork", _dogWork);
|
|
|
+ map.put("wasTheDogBitten", _wasTheDogBitten);
|
|
|
+ map.put("holdTheStick", _holdTheStick);
|
|
|
+ map.put("hasReduceSnb", _hasReduceSnb);
|
|
|
+ //如果被狗咬后扣除的snb,和对应扣除的体力
|
|
|
+ map.put("deductSnb", comSettingVo.getDeductSnb());
|
|
|
+ map.put("deductStrength", _addStrength);
|
|
|
+
|
|
|
+ //用户snb
|
|
|
+ map.put("snb", comUsersVo.getSnb());
|
|
|
+ map.put("snbPart", comUsersVo.getSnbPart());
|
|
|
+
|
|
|
+ //解除snb锁
|
|
|
+ redisLock.unlock(_redisSNBKey, String.valueOf(time));
|
|
|
+ return Result.of(map);
|
|
|
+ } catch (Exception e) {
|
|
|
+ // 需要redis 解锁
|
|
|
+ redisLock.unlock(_redisKey, String.valueOf(time));
|
|
|
+ redisLock.unlock(_redisSNBKey, String.valueOf(time));
|
|
|
+ throw new RuntimeException(e.getMessage());
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 处理一键收取水果果实时候,传入对方用户id 即可
|
|
|
+ * <p>
|
|
|
+ * <p>
|
|
|
+ * 收获时候,操作用户snb时候,需要加锁,防止用户收取时候遗漏计算snb
|
|
|
+ *
|
|
|
+ * @param otherUserId
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ @PostMapping("stealAllFruit")
|
|
|
+ @ResponseBody
|
|
|
+ @Transactional(rollbackFor = Exception.class)
|
|
|
+ public Result<Map> stealAllFruitFunction(
|
|
|
+ @RequestParam(value = "userId") String userId,
|
|
|
+ @RequestParam(value = "otherUserId") String otherUserId) {
|
|
|
+
|
|
|
+ Map map = new HashMap();
|
|
|
+
|
|
|
+ //获取数据库相关配置
|
|
|
+ ComSettingVo comSettingVo = comSettingService.get("1").getData();
|
|
|
+ if (comSettingVo.equals(null)) {
|
|
|
+ return Result.of(null, false, ResultEnum.SETTING_IS_NULL.getMessage(), ResultEnum.SETTING_IS_NULL.getCode());
|
|
|
+ }
|
|
|
+ //todo 后台可配置,获取一个链上数据
|
|
|
+ Integer _configStrength = comSettingVo.getMaxStrength(), _chainStrength = DappUtil.getChildrenCount(userId);
|
|
|
+ //前端的显示,输出一个不小于0的体力值
|
|
|
+ Integer _maxStrength = _configStrength + _chainStrength;
|
|
|
+ //1.先判断用户是否有足够的体力,根据snb判断。2. 收取到果实,扣除用户一个体力值
|
|
|
+ ComUsersVo comUsersVo = comUsersService.findByUserId(userId);
|
|
|
+ ComPlayersAttriVo playersAttribute = comPlayersAttriService.findByUserId(userId);
|
|
|
+ Integer _out = _maxStrength - Math.abs(playersAttribute.getStrength());
|
|
|
+ if (comUsersVo.getSnb() < comSettingVo.getDeductSnb()) {
|
|
|
+ //判断是否有双倍体力
|
|
|
+ if (_out < comSettingVo.getSnbUnitStrength()) {
|
|
|
+ map.put("msg", "需要双倍体力:" + comSettingVo.getSnbUnitStrength());
|
|
|
+ return Result.of(map, false, ResultEnum.PLAYER_ATTRIBUTE_STRENGTH_IS_NOT.getMessage(), ResultEnum.PLAYER_ATTRIBUTE_STRENGTH_IS_NOT.getCode());
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ //正常判断体力
|
|
|
+ if (_out < comSettingVo.getUnitStrength()) {
|
|
|
+ map.put("msg", "需要单倍体力:" + comSettingVo.getUnitStrength());
|
|
|
+ return Result.of(map, false, ResultEnum.PLAYER_ATTRIBUTE_STRENGTH_IS_NOT.getMessage(), ResultEnum.PLAYER_ATTRIBUTE_STRENGTH_IS_NOT.getCode());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ List<Map> _stealLandInfos = new ArrayList<>();
|
|
|
+ Double _finalStealAmountSum = 0d;
|
|
|
+ //todo 偷取用户的对象信息等id
|
|
|
+ List<ComPlayerLandAndCanSteal> otherPlayerLandAndCanSteal = comPlayerLandService.findCanStealByUserIdAndOtherUserId(userId, otherUserId);
|
|
|
+ //List<ComPlayerLand> otherPlayerLands = comPlayerLandService.findAllByCanStealOtherLands(userId, otherUserId);
|
|
|
+ List<ComPlayerLand> otherPlayerLands = new ArrayList<>();
|
|
|
+ for (int i = 0; i < otherPlayerLandAndCanSteal.size(); i++) {
|
|
|
+ if (otherPlayerLandAndCanSteal.get(i).getCanSteal().equals(1)) {
|
|
|
+ otherPlayerLands.add(CopyUtil.copy(otherPlayerLandAndCanSteal.get(i), ComPlayerLand.class));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (otherPlayerLands.size() == 0) {
|
|
|
+ return Result.of(null, false, ResultEnum.LAND_CAN_STEAL_IS_ZERO.getMessage(), ResultEnum.LAND_CAN_STEAL_IS_ZERO.getCode());
|
|
|
+ }
|
|
|
+
|
|
|
+ for (int i = 0; i < otherPlayerLands.size(); i++) {
|
|
|
+ ComPlayerLand otherPlayerLand = otherPlayerLands.get(i);
|
|
|
+ //获取当前种植的种子
|
|
|
+ ComMallSeedVo comMallSeedVo = comMallSeedService.findById(otherPlayerLand.getPlantId());
|
|
|
+ //需要redis 加锁
|
|
|
+ long time = System.currentTimeMillis() + RedisData.getPlayerGoodsTimeout();
|
|
|
+ //获取用户的plantFlag,因为之前的用户没有设置这个flag,所以设为第一次,用 userId 和 landId 组合成key
|
|
|
+ String _redisKey = otherPlayerLand.getPlantFlag();
|
|
|
+ if (!StringUtils.hasText(_redisKey)) {
|
|
|
+ //return Result.of(null, false, ResultEnum.LAND_PLANT_FLAG_IS_NULL.getMessage(), ResultEnum.LAND_PLANT_FLAG_IS_NULL.getCode());
|
|
|
+ _redisKey = otherPlayerLand.getUserId() + "or" + otherPlayerLand.getConfigLandId();
|
|
|
+ }
|
|
|
+ try {
|
|
|
+ if (!redisLock.lock(_redisKey, String.valueOf(time))) {
|
|
|
+ //如果有冲突锁,跳过
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ //todo 如果当前人员偷窃水果。记录一个信息,存储当前玩家已偷过的水果的信息
|
|
|
+ //计算一个偷取的收获量, 租赁倍数* 租赁日期下的产量
|
|
|
+ Integer _otherAmount = 0;
|
|
|
+ if (otherPlayerLand.getLeaseDate().equals(1)) {
|
|
|
+ _otherAmount = otherPlayerLand.getLeaseMultiple() * comMallSeedVo.getHarvest1();
|
|
|
+ } else if (otherPlayerLand.getLeaseDate().equals(2)) {
|
|
|
+ _otherAmount = otherPlayerLand.getLeaseMultiple() * comMallSeedVo.getHarvest2();
|
|
|
+ } else if (otherPlayerLand.getLeaseDate().equals(3)) {
|
|
|
+ _otherAmount = otherPlayerLand.getLeaseMultiple() * comMallSeedVo.getHarvest3();
|
|
|
+ }
|
|
|
+ //todo 拿出计算利润,收获量减去种子的成本(snb)后的百分之30 ,后面需要后台可调整
|
|
|
+ Integer _profit = _otherAmount - otherPlayerLand.getLeaseMultiple() * comMallSeedVo.getPriceSnb();
|
|
|
+ // 配置的参数。这里先直接定义
|
|
|
+ Double profitConfig = comSettingVo.getProfit(), stealRatioMaxConfig = comSettingVo.getStealMaxRatio(), stealRatioMinConfig = comSettingVo.getStealMinRatio(), finallyGetRatioConfig = comSettingVo.getFinalRatio();
|
|
|
+ Double _stealRatio = new Random().nextDouble() * DoubleUtil.sub(stealRatioMaxConfig, stealRatioMinConfig) + stealRatioMinConfig;// 1%-3%
|
|
|
+ //todo 被偷取的人扣除 一个损失量,初利润算 _profit
|
|
|
+ Double _stolenAmount = DoubleUtil.mul(_profit.doubleValue(), _stealRatio);
|
|
|
+ //这里根据plantFlag判断目标用户当前种植被偷取完,看下是否需要处理更新前端信息,暂不处理
|
|
|
+ Double _sumStolen = comPlayerProfitService.getStolenSumByOtherUserIdAndPlantFlag(otherUserId, _redisKey);
|
|
|
+ //todo 这里的可偷利润应该是最大值,用户不能超过这个,需要限制判断
|
|
|
+ Double _maxAmount = DoubleUtil.mul(_profit.doubleValue(), profitConfig); //可偷取的利润
|
|
|
+ //1 一键 就是 _sumStolen>_maxAmount 或者 _sumStolen == _maxAmount ,被偷完了
|
|
|
+ if (!DoubleUtil.compare(_sumStolen, _maxAmount).equals(-1)) {
|
|
|
+ // 需要redis 解锁
|
|
|
+ redisLock.unlock(_redisKey, String.valueOf(time));
|
|
|
+ //记录一个不可偷取的状态
|
|
|
+ otherPlayerLand.setPlantSteal(0);
|
|
|
+ comPlayerLandService.save(CopyUtil.copy(otherPlayerLand, ComPlayerLandVo.class));
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ //计算剩下可偷利润的差,防止过多偷取用户利润 _stolenAmount
|
|
|
+ Double _diff = Math.abs(DoubleUtil.sub(_maxAmount, _sumStolen));
|
|
|
+ if (DoubleUtil.compare(_stolenAmount, _diff).equals(1)) {
|
|
|
+ //_stolenAmount>_diff
|
|
|
+ _stolenAmount = _diff;
|
|
|
+ }
|
|
|
+ //最终偷窃人获取的是偷取的是目标用户损失量的10% finallyGetRatioConfig
|
|
|
+ Double _finalStealAmount = DoubleUtil.mul(_stolenAmount, finallyGetRatioConfig);
|
|
|
+ //偷窃后,系统回收部分
|
|
|
+ Double _lostStealAmount = DoubleUtil.sub(1d, finallyGetRatioConfig) * _stolenAmount;
|
|
|
+ //果实 Type =1
|
|
|
+ //todo 增加一个字段处理背包果实,拿出当前用户背包果实
|
|
|
+ ComPlayerGoods comPlayerGoods = comPlayerGoodsService.findByUserIdAndIndexAndType(userId, comMallSeedVo.getHarvestId(), 1);
|
|
|
+ Double _beforeStealAmount = 0.0;
|
|
|
+ if (comPlayerGoods == null) {
|
|
|
+ //背包增加收取到别的用户对应的类型数量。比如当前是偷取到的果实
|
|
|
+ comPlayerGoods = new ComPlayerGoods();
|
|
|
+ comPlayerGoods.setUserId(userId);
|
|
|
+ comPlayerGoods.setGoodsIndex(comMallSeedVo.getHarvestId());
|
|
|
+ comPlayerGoods.setGoodsType(1);
|
|
|
+ comPlayerGoods.setName(comMallSeedVo.getHarvestName());
|
|
|
+ //用种子的picture
|
|
|
+ comPlayerGoods.setPictureName(comMallSeedVo.getPicture());
|
|
|
+ //amount 设置0
|
|
|
+ comPlayerGoods.setAmount(0);
|
|
|
+ comPlayerGoods.setAmountPart(_finalStealAmount);
|
|
|
+ _beforeStealAmount = 0.0;
|
|
|
+ } else {
|
|
|
+ _beforeStealAmount = comPlayerGoods.getAmountPart();
|
|
|
+ //修改偷取字段
|
|
|
+ comPlayerGoods.setAmountPart(DoubleUtil.add(comPlayerGoods.getAmountPart(), _finalStealAmount));
|
|
|
+ }
|
|
|
+ ComPlayerGoodsVo comPlayerGoodsVo = CopyUtil.copy(comPlayerGoods, ComPlayerGoodsVo.class);
|
|
|
+ comPlayerGoodsService.save(comPlayerGoodsVo);
|
|
|
+
|
|
|
+ //todo 偷窃损失,处理目标用户收取果实时候,减扣一部分被偷取的数量
|
|
|
+ ComPlayerProfit comPlayerProfit = new ComPlayerProfit();
|
|
|
+ comPlayerProfit.setUserId(userId);
|
|
|
+ comPlayerProfit.setTargetId(otherUserId);
|
|
|
+ comPlayerProfit.setPlantFlag(_redisKey);
|
|
|
+ comPlayerProfit.setLandId(otherPlayerLand.getConfigLandId());
|
|
|
+ comPlayerProfit.setLeaseMultiple(otherPlayerLand.getLeaseMultiple());
|
|
|
+ comPlayerProfit.setLeaseDate(otherPlayerLand.getLeaseDate());
|
|
|
+ comPlayerProfit.setHarvest(_otherAmount);
|
|
|
+ comPlayerProfit.setProfit(_profit.doubleValue());//目标用户可偷的初始利润值
|
|
|
+ comPlayerProfit.setStolen(_stolenAmount);//目标用户被偷的数量
|
|
|
+ comPlayerProfit.setFinalSteal(_finalStealAmount);//用户最终偷取的量,是被偷的数量 10%左右
|
|
|
+ comPlayerProfit.setProfitAfter(DoubleUtil.sub(_profit.doubleValue(), DoubleUtil.add(_stolenAmount, _sumStolen))); //可偷的减去被偷的
|
|
|
+ //记录相关比例
|
|
|
+ comPlayerProfit.setProfitRatio(profitConfig);
|
|
|
+ comPlayerProfit.setStealRatio(_stealRatio);
|
|
|
+ comPlayerProfit.setFinalRatio(finallyGetRatioConfig);
|
|
|
+ ComPlayerProfitVo comPlayerProfitVo = CopyUtil.copy(comPlayerProfit, ComPlayerProfitVo.class);
|
|
|
+ comPlayerProfitService.save(comPlayerProfitVo);
|
|
|
+
|
|
|
+ //todo 记录一个收获的操作日志,这里由于偷取果实是有小数点的,小数点处理成整数,单位 暂定5位 100000
|
|
|
+ // 这里的数量都与偷窃知道相关。amountPart,注意不是果实实际总数 amount
|
|
|
+ ComPlayerLog _playerLog = new ComPlayerLog();
|
|
|
+ _playerLog.setUserId(userId);
|
|
|
+ _playerLog.setTId(comMallSeedVo.getHarvestId());
|
|
|
+ _playerLog.setTName(comMallSeedVo.getHarvestName());
|
|
|
+ _playerLog.setTType(6);//偷取果实时候,type设置6
|
|
|
+ //偷水果时候这部分数据应该是不变的
|
|
|
+ _playerLog.setTAmount(0);
|
|
|
+ _playerLog.setBeforeAmount(comPlayerGoods.getAmount());
|
|
|
+ _playerLog.setAfterAmount(comPlayerGoods.getAmount());
|
|
|
+ //偷取用户果实时候,收取时候信息记录
|
|
|
+ _playerLog.setBeforePart(_beforeStealAmount);
|
|
|
+ _playerLog.setTPart(_finalStealAmount);
|
|
|
+ _playerLog.setTLoss(_lostStealAmount); //损失的部分
|
|
|
+ _playerLog.setAfterPart(comPlayerGoods.getAmountPart());
|
|
|
+ _playerLog.setLMultiple(otherPlayerLand.getLeaseMultiple());
|
|
|
+ ComPlayerLogVo _playerLogVo = CopyUtil.copy(_playerLog, ComPlayerLogVo.class);
|
|
|
+ comPlayerLogService.save(_playerLogVo);
|
|
|
+
|
|
|
+ //todo 成功收取记录一个土地id
|
|
|
+ Map _landMap = new HashMap();
|
|
|
+ //记录一个id
|
|
|
+ _landMap.put("landId", otherPlayerLand.getConfigLandId());
|
|
|
+ //
|
|
|
+ _landMap.put("stealAmount", _finalStealAmount);
|
|
|
+
|
|
|
+ //固定成本
|
|
|
+ _landMap.put("cost", otherPlayerLand.getLeaseMultiple() * comMallSeedVo.getPriceSnb());
|
|
|
+ //当前利润
|
|
|
+ _landMap.put("profit", _profit);
|
|
|
+ //打印一个比例
|
|
|
+ _landMap.put("profitRatio", profitConfig);
|
|
|
+ _landMap.put("intervalStealRatio", _stealRatio);
|
|
|
+ _landMap.put("finallyGetRatioConfig", finallyGetRatioConfig);
|
|
|
+
|
|
|
+ _finalStealAmountSum = DoubleUtil.add(_finalStealAmount, _finalStealAmountSum);
|
|
|
+ _stealLandInfos.add(_landMap);
|
|
|
+ // 需要redis 解锁
|
|
|
+ redisLock.unlock(_redisKey, String.valueOf(time));
|
|
|
+ } catch (Exception e) {
|
|
|
+ // 需要redis 解锁
|
|
|
+ redisLock.unlock(_redisKey, String.valueOf(time));
|
|
|
+ throw new RuntimeException(e.getMessage());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ map.put("msg", "偷取果实.");
|
|
|
+ map.put("steals", _stealLandInfos);
|
|
|
+ map.put("stealSum", _finalStealAmountSum);
|
|
|
+
|
|
|
+ if (_stealLandInfos.size() > 0) {
|
|
|
+ //todo 体力值可以后台配置
|
|
|
+ Integer _addStrength = comUsersVo.getSnb() < comSettingVo.getDeductSnb() ? comSettingVo.getSnbUnitStrength() : comSettingVo.getUnitStrength();
|
|
|
+ playersAttribute.setStrength(playersAttribute.getStrength() + _addStrength);
|
|
|
+ comPlayersAttriService.save(playersAttribute);
|
|
|
+ ComPlayersAttriSimpleVo comPlayersAttriSimpleVo = CopyUtil.copy(playersAttribute, ComPlayersAttriSimpleVo.class);
|
|
|
+ //前端的显示,输出一个不小于0的体力值
|
|
|
+ Integer _outEnd = _maxStrength - Math.abs(playersAttribute.getStrength());
|
|
|
+ comPlayersAttriSimpleVo.setCurrentStrength(_outEnd < 0 ? 0 : _outEnd);
|
|
|
+ //最大值是配置的值和链上数据的值相加
|
|
|
+ comPlayersAttriSimpleVo.setMaxStrength(_maxStrength);
|
|
|
+
|
|
|
+ map.put("playerAttribute", comPlayersAttriSimpleVo);
|
|
|
+ }
|
|
|
+
|
|
|
+ return Result.of(map);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 出售果实
|
|
|
+ * <p>
|
|
|
+ * todo 需要记录出售果实的snb操作记录
|
|
|
+ *
|
|
|
+ * @param userId
|
|
|
+ * @param amount
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ @PostMapping("saleFruit")
|
|
|
+ @ResponseBody
|
|
|
+ @Transactional(rollbackFor = Exception.class)
|
|
|
+ public Result<Map> saleFruitFunction(
|
|
|
+ @RequestParam(value = "userId") String userId,
|
|
|
+ @RequestParam(value = "fruitId") Integer fruitId,
|
|
|
+ @RequestParam(value = "amount") Integer amount) {
|
|
|
+
|
|
|
+ //
|
|
|
+ ComFruitVo comFruitVo = comFruitService.findById(fruitId);
|
|
|
+
|
|
|
+ if (comFruitVo == null) {
|
|
|
+ return Result.of(null, false, ResultEnum.FRUIT_DATA_ERROR.getMessage(), ResultEnum.FRUIT_DATA_ERROR.getCode());
|
|
|
+ }
|
|
|
+ //果实
|
|
|
+ ComPlayerGoods comPlayerGoodsSimpleVo = comPlayerGoodsService.findByUserIdAndIndexAndType(userId, fruitId, 1);
|
|
|
+
|
|
|
+ //销售果实数量
|
|
|
+ if (comPlayerGoodsSimpleVo == null) {
|
|
|
+ return Result.of(null, false, ResultEnum.FRUIT_DATA_ERROR.getMessage(), ResultEnum.FRUIT_DATA_ERROR.getCode());
|
|
|
+ }
|
|
|
+ //添加了 amountPart,需要加入判断整数部分
|
|
|
+ Integer _userFloorAmount = comPlayerGoodsSimpleVo.getAmount() + (int) Math.floor(comPlayerGoodsSimpleVo.getAmountPart());
|
|
|
+ //旧判断 amount > comPlayerGoodsSimpleVo.getAmount()
|
|
|
+ if (amount > _userFloorAmount) {
|
|
|
+ return Result.of(null, false, ResultEnum.FRUIT_AMOUNT_ERROR.getMessage(), ResultEnum.FRUIT_AMOUNT_ERROR.getCode());
|
|
|
+ }
|
|
|
+ //todo 销售果实时候,收取5%手续费,最少出售20的倍数
|
|
|
+ // 1.判定销售数量, 如果果实输入是0,或者不是20的倍数,返回提示
|
|
|
+ // || amount % 20 != 0
|
|
|
+ if (amount.equals(0)) {
|
|
|
+ return Result.of(null, false, ResultEnum.FRUIT_AMOUNT_IS_ZERO_AND_NOT_MULTIPLE.getMessage(), ResultEnum.FRUIT_AMOUNT_IS_ZERO_AND_NOT_MULTIPLE.getCode());
|
|
|
+ }
|
|
|
+ //todo snb冻结加锁
|
|
|
+ long time = System.currentTimeMillis() + RedisData.getSnbTimeout();
|
|
|
+ String _redisKey = "SNB_SAVE_" + userId;
|
|
|
+
|
|
|
+ try {
|
|
|
+ //todo snb冻结加锁
|
|
|
+ if (!redisLock.lock(_redisKey, String.valueOf(time))) {
|
|
|
+ return Result.of(null, false, ResultEnum.PLAYER_GOODS_SAVE_LOCK.getMessage(), ResultEnum.PLAYER_GOODS_SAVE_LOCK.getCode());
|
|
|
+ }
|
|
|
+
|
|
|
+ Integer _selfBeforeFruitAmount = comPlayerGoodsSimpleVo.getAmount();
|
|
|
+ Integer _selfAfterFruitAmount = 0;
|
|
|
+ Double _selfBeforeFruitAmountPart = comPlayerGoodsSimpleVo.getAmountPart();
|
|
|
+ Double _selfAfterFruitAmountPart = 0d;
|
|
|
+ Integer _tAmount = 0;
|
|
|
+ Double _tAmountPart = 0d;
|
|
|
+
|
|
|
+ //if (comPlayerGoodsSimpleVo.getAmount().equals(amount)) {
|
|
|
+ // //如果库存量和出售的果实数量一样,删除
|
|
|
+ // comPlayerGoodsService.delete(comPlayerGoodsSimpleVo.getGoodsId());
|
|
|
+ // _selfAfterFruitAmount = 0;
|
|
|
+ //} else {
|
|
|
+ // comPlayerGoodsSimpleVo.setAmount(comPlayerGoodsSimpleVo.getAmount() - amount);
|
|
|
+ // _selfAfterFruitAmount = comPlayerGoodsSimpleVo.getAmount();
|
|
|
+ // ComPlayerGoodsVo comPlayerGoodsVo = CopyUtil.copy(comPlayerGoodsSimpleVo, ComPlayerGoodsVo.class);
|
|
|
+ // comPlayerGoodsService.save(comPlayerGoodsVo);
|
|
|
+ //}
|
|
|
+ Integer _amountDif = comPlayerGoodsSimpleVo.getAmount() - amount;
|
|
|
+ //优先处理背包的amount
|
|
|
+ if (_amountDif > 0) {
|
|
|
+ //当前交易值
|
|
|
+ _tAmount = amount;
|
|
|
+ //如果amount 数量足够,直接记录 他们的差值
|
|
|
+ comPlayerGoodsSimpleVo.setAmount(_amountDif);
|
|
|
+ _selfAfterFruitAmount = comPlayerGoodsSimpleVo.getAmount();
|
|
|
+ _selfAfterFruitAmountPart = comPlayerGoodsSimpleVo.getAmountPart();
|
|
|
+ ComPlayerGoodsVo comPlayerGoodsVo = CopyUtil.copy(comPlayerGoodsSimpleVo, ComPlayerGoodsVo.class);
|
|
|
+ comPlayerGoodsService.save(comPlayerGoodsVo);
|
|
|
+ } else {
|
|
|
+ _selfAfterFruitAmount = 0;
|
|
|
+
|
|
|
+ //保证精度
|
|
|
+ BigDecimal bigDecimal1 = new BigDecimal(Double.toString(_amountDif));
|
|
|
+ BigDecimal bigDecimal2 = new BigDecimal(Double.toString(comPlayerGoodsSimpleVo.getAmountPart()));
|
|
|
+ BigDecimal _amountPart = bigDecimal1.add(bigDecimal2);
|
|
|
+
|
|
|
+ //当前交易值,_amountDif 小于0 说明 amount 是全全部扣除,到小数部分了。
|
|
|
+ _tAmount = comPlayerGoodsSimpleVo.getAmount();
|
|
|
+ _tAmountPart = Math.abs(bigDecimal1.doubleValue());
|
|
|
+
|
|
|
+ System.out.print("_amountPart{}," + _amountPart.doubleValue());
|
|
|
+ //前面判断了。所以 _amountPart 不会比0.0小
|
|
|
+ if (_amountPart.compareTo(new BigDecimal(0.0)) <= 0) {
|
|
|
+ //如果库存量 amount 和 amountPart 都为零,删除
|
|
|
+ comPlayerGoodsService.delete(comPlayerGoodsSimpleVo.getGoodsId());
|
|
|
+ //这里记录一下,看是否会是一个负数
|
|
|
+ _selfAfterFruitAmountPart = _amountPart.doubleValue();
|
|
|
+ } else {
|
|
|
+ comPlayerGoodsSimpleVo.setAmount(0);
|
|
|
+ comPlayerGoodsSimpleVo.setAmountPart(_amountPart.doubleValue());
|
|
|
+ _selfAfterFruitAmountPart = comPlayerGoodsSimpleVo.getAmountPart();
|
|
|
+ ComPlayerGoodsVo comPlayerGoodsVo = CopyUtil.copy(comPlayerGoodsSimpleVo, ComPlayerGoodsVo.class);
|
|
|
+ comPlayerGoodsService.save(comPlayerGoodsVo);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ //todo 收取手续费之后
|
|
|
+ int _endAmount = (int) (amount * 1);
|
|
|
+ //添加SNB
|
|
|
+ ComUsersVo comUsersVo = comUsersService.findByUserId(userId);
|
|
|
+ ComSnbTranVo _snbTran = new ComSnbTranVo();
|
|
|
+ _snbTran.setBeforeSnbPart(comUsersVo.getSnbPart());
|
|
|
+ //交易前的snb数据
|
|
|
+ Integer _beforeSnb = comUsersVo.getSnb();
|
|
|
+ //数量乘以售价
|
|
|
+ int _saleSnb = comFruitVo.getPriceSnb() * _endAmount; //此时的售价数量已经扣除了手续费,相当于减少了几个果实
|
|
|
+ //当前操作的snb
|
|
|
+ Integer _currentSnb = comUsersVo.getSnb() + _saleSnb;
|
|
|
+ comUsersVo.setSnb(_currentSnb);
|
|
|
+ comUsersService.save(comUsersVo);
|
|
|
+
|
|
|
+ /**
|
|
|
+ * todo 果实出售snb数据记录
|
|
|
+ */
|
|
|
+
|
|
|
+ //记录果实id
|
|
|
+ _snbTran.setTranId(comFruitVo.getId().toString());
|
|
|
+ _snbTran.setUserId(userId);
|
|
|
+ _snbTran.setTranName(comFruitVo.getName());
|
|
|
+ _snbTran.setTranType(0);
|
|
|
+ _snbTran.setTranAmount(amount); //此数量会操作背包记录
|
|
|
+ _snbTran.setTranAmountPart(0d);
|
|
|
+ _snbTran.setTranPrice(comFruitVo.getPriceSnb());
|
|
|
+ //"出售果实价格:" + comFruitVo.getPriceSnb() + ",数量:" + amount
|
|
|
+ _snbTran.setTranDescribe("手续费系数:1,最终果实数量为:" + _endAmount + ",销售价格:" + _saleSnb);
|
|
|
+ _snbTran.setIsAdd(1);//增加收入
|
|
|
+ _snbTran.setBeforeSnb(_beforeSnb);
|
|
|
+ _snbTran.setTranSnb(_saleSnb);
|
|
|
+ _snbTran.setAfterSnb(_currentSnb);
|
|
|
+
|
|
|
+ _snbTran.setTranSnbPart(0d);
|
|
|
+ _snbTran.setAfterSnbPart(comUsersVo.getSnbPart());
|
|
|
+
|
|
|
+ comSnbTranService.save(_snbTran);
|
|
|
+
|
|
|
+ /**
|
|
|
+ * todo 出售果实时候,记录操作 PlayerLog
|
|
|
+ */
|
|
|
+ //当前用户
|
|
|
+ ComPlayerLog _saleFruitPlayerLog = new ComPlayerLog();
|
|
|
+ _saleFruitPlayerLog.setUserId(userId);
|
|
|
+ _saleFruitPlayerLog.setTId(comFruitVo.getId());
|
|
|
+ _saleFruitPlayerLog.setTName(comFruitVo.getName());
|
|
|
+ _saleFruitPlayerLog.setTType(5);//出售水果时候,type设置5
|
|
|
+ _saleFruitPlayerLog.setTAmount(_tAmount);
|
|
|
+ _saleFruitPlayerLog.setBeforeAmount(_selfBeforeFruitAmount);
|
|
|
+ ////交易后的数据
|
|
|
+ _saleFruitPlayerLog.setAfterAmount(_selfAfterFruitAmount);
|
|
|
+ //增加一个小数部分记录
|
|
|
+ _saleFruitPlayerLog.setTPart(_tAmountPart);
|
|
|
+ _saleFruitPlayerLog.setTLoss(0d);
|
|
|
+ _saleFruitPlayerLog.setBeforePart(_selfBeforeFruitAmountPart);
|
|
|
+ _saleFruitPlayerLog.setAfterPart(_selfAfterFruitAmountPart);
|
|
|
+ _saleFruitPlayerLog.setLMultiple(0);//收获时候,会有一个倍数
|
|
|
+ ComPlayerLogVo _saleFruitPlayerLogVo = CopyUtil.copy(_saleFruitPlayerLog, ComPlayerLogVo.class);
|
|
|
+ comPlayerLogService.save(_saleFruitPlayerLogVo);
|
|
|
+
|
|
|
+
|
|
|
+ redisLock.unlock(_redisKey, String.valueOf(time));
|
|
|
+ } catch (Exception e) {
|
|
|
+ redisLock.unlock(_redisKey, String.valueOf(time));
|
|
|
+ throw new RuntimeException(e.getMessage());
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ Map map = new HashMap();
|
|
|
+ map.put("msg", "成功出售果实!");
|
|
|
+ return Result.of(map);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 根据用户地址送果实
|
|
|
+ *
|
|
|
+ * @param userId
|
|
|
+ * @param address 目标用户地址
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ @PostMapping("grantFruit")
|
|
|
+ @ResponseBody
|
|
|
+ @Transactional(rollbackFor = Exception.class)
|
|
|
+ public Result<Map> grantFruitFunction(
|
|
|
+ @RequestParam(value = "userId") String userId,
|
|
|
+ @RequestParam(value = "fruitId") Integer fruitId,
|
|
|
+ @RequestParam(value = "amount") Integer amount,
|
|
|
+ @RequestParam(value = "address") String address) {
|
|
|
+
|
|
|
+ //目标用户的背包
|
|
|
+ ComUsersVo _targetUserVo = comUsersService.findByAddress(address);
|
|
|
+ if (_targetUserVo == null) {
|
|
|
+ return Result.of(null, false, ResultEnum.USER_NOT_ADDRESS.getMessage(), ResultEnum.USER_NOT_ADDRESS.getCode());
|
|
|
+ }
|
|
|
+
|
|
|
+ if (_targetUserVo.getUserId().equals(userId)) {
|
|
|
+ return Result.of(null, false, ResultEnum.FRUIT_SEND_SELF.getMessage(), ResultEnum.FRUIT_SEND_SELF.getCode());
|
|
|
+ }
|
|
|
+
|
|
|
+ ComFruitVo comFruitVo = comFruitService.findById(fruitId);
|
|
|
+
|
|
|
+ if (comFruitVo == null) {
|
|
|
+ return Result.of(null, false, ResultEnum.FRUIT_DATA_ERROR.getMessage(), ResultEnum.FRUIT_DATA_ERROR.getCode());
|
|
|
+ }
|
|
|
+ //果实type =1
|
|
|
+ ComPlayerGoods comPlayerGoodsSimpleVo = comPlayerGoodsService.findByUserIdAndIndexAndType(userId, fruitId, 1);
|
|
|
+
|
|
|
+ //销售果实数量
|
|
|
+ if (comPlayerGoodsSimpleVo == null) {
|
|
|
+ return Result.of(null, false, ResultEnum.FRUIT_DATA_ERROR.getMessage(), ResultEnum.FRUIT_DATA_ERROR.getCode());
|
|
|
+ }
|
|
|
+ //添加了 amountPart,需要加入判断整数部分
|
|
|
+ Integer _userFloorAmount = comPlayerGoodsSimpleVo.getAmount() + (int) Math.floor(comPlayerGoodsSimpleVo.getAmountPart());
|
|
|
+ if (amount > _userFloorAmount) {
|
|
|
+ return Result.of(null, false, ResultEnum.FRUIT_AMOUNT_ERROR.getMessage(), ResultEnum.FRUIT_AMOUNT_ERROR.getCode());
|
|
|
+ }
|
|
|
+ try {
|
|
|
+ Integer _selfBeforeAmount = comPlayerGoodsSimpleVo.getAmount();
|
|
|
+ Integer _selfAfterAmount = 0;
|
|
|
+ Double _selfBeforeFruitAmountPart = comPlayerGoodsSimpleVo.getAmountPart();
|
|
|
+ Double _selfAfterFruitAmountPart = 0d;
|
|
|
+ Integer _tAmount = 0;
|
|
|
+ Double _tAmountPart = 0d;
|
|
|
+
|
|
|
+ //if (comPlayerGoodsSimpleVo.getAmount().equals(amount)) {
|
|
|
+ // //如果库存量和出售的果实数量一样,删除
|
|
|
+ // comPlayerGoodsService.delete(comPlayerGoodsSimpleVo.getGoodsId());
|
|
|
+ // _selfAfterAmount = 0;
|
|
|
+ //} else {
|
|
|
+ // comPlayerGoodsSimpleVo.setAmount(comPlayerGoodsSimpleVo.getAmount() - amount);
|
|
|
+ // _selfAfterAmount = comPlayerGoodsSimpleVo.getAmount();
|
|
|
+ // ComPlayerGoodsVo comPlayerGoodsVo = CopyUtil.copy(comPlayerGoodsSimpleVo, ComPlayerGoodsVo.class);
|
|
|
+ // comPlayerGoodsService.save(comPlayerGoodsVo);
|
|
|
+ //}
|
|
|
+ Integer _amountDif = comPlayerGoodsSimpleVo.getAmount() - amount;
|
|
|
+ //优先处理背包的amount
|
|
|
+ if (_amountDif > 0) {
|
|
|
+ //当前交易值
|
|
|
+ _tAmount = amount;
|
|
|
+ //如果amount 数量足够,直接记录 他们的差值
|
|
|
+ comPlayerGoodsSimpleVo.setAmount(_amountDif);
|
|
|
+ _selfAfterAmount = comPlayerGoodsSimpleVo.getAmount();
|
|
|
+ _selfAfterFruitAmountPart = comPlayerGoodsSimpleVo.getAmountPart();
|
|
|
+ ComPlayerGoodsVo comPlayerGoodsVo = CopyUtil.copy(comPlayerGoodsSimpleVo, ComPlayerGoodsVo.class);
|
|
|
+ comPlayerGoodsService.save(comPlayerGoodsVo);
|
|
|
+ } else {
|
|
|
+ _selfAfterAmount = 0;
|
|
|
+ //保证精度
|
|
|
+ BigDecimal bigDecimal1 = new BigDecimal(Double.toString(_amountDif));
|
|
|
+ BigDecimal bigDecimal2 = new BigDecimal(Double.toString(comPlayerGoodsSimpleVo.getAmountPart()));
|
|
|
+ BigDecimal _amountPart = bigDecimal1.add(bigDecimal2);
|
|
|
+ //当前交易值,_amountDif 小于0 说明 amount 是全全部扣除,到小数部分了。
|
|
|
+ _tAmount = comPlayerGoodsSimpleVo.getAmount();
|
|
|
+ _tAmountPart = Math.abs(bigDecimal1.doubleValue());
|
|
|
+ System.out.print("_amountPart{}," + _amountPart.doubleValue());
|
|
|
+ //前面判断了。所以 _amountPart 不会比0.0小
|
|
|
+ if (_amountPart.compareTo(new BigDecimal(0.0)) <= 0) {
|
|
|
+ //如果库存量 amount 和 amountPart 都为零,删除
|
|
|
+ comPlayerGoodsService.delete(comPlayerGoodsSimpleVo.getGoodsId());
|
|
|
+ //这里记录一下,看是否会是一个负数
|
|
|
+ _selfAfterFruitAmountPart = _amountPart.doubleValue();
|
|
|
+ } else {
|
|
|
+ comPlayerGoodsSimpleVo.setAmount(0);
|
|
|
+ comPlayerGoodsSimpleVo.setAmountPart(_amountPart.doubleValue());
|
|
|
+ _selfAfterFruitAmountPart = comPlayerGoodsSimpleVo.getAmountPart();
|
|
|
+ ComPlayerGoodsVo comPlayerGoodsVo = CopyUtil.copy(comPlayerGoodsSimpleVo, ComPlayerGoodsVo.class);
|
|
|
+ comPlayerGoodsService.save(comPlayerGoodsVo);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ //todo 发送果实,记录当前用户的playerLog
|
|
|
+ //当前用户
|
|
|
+ ComPlayerLog _selfPlayerLog = new ComPlayerLog();
|
|
|
+ _selfPlayerLog.setUserId(userId);
|
|
|
+ _selfPlayerLog.setTId(comFruitVo.getId());
|
|
|
+ _selfPlayerLog.setTName(comFruitVo.getName());
|
|
|
+ _selfPlayerLog.setTType(2);//发送水果的类型:2
|
|
|
+ _selfPlayerLog.setTAmount(amount);
|
|
|
+ _selfPlayerLog.setBeforeAmount(_selfBeforeAmount);
|
|
|
+ ////交易后的数据
|
|
|
+ _selfPlayerLog.setAfterAmount(_selfAfterAmount);
|
|
|
+ _selfPlayerLog.setLMultiple(0);//收获时候,会有一个倍数
|
|
|
+ ComPlayerLogVo _selfPlayerLogVo = CopyUtil.copy(_selfPlayerLog, ComPlayerLogVo.class);
|
|
|
+ comPlayerLogService.save(_selfPlayerLogVo);
|
|
|
+
|
|
|
+ //接受人的背包数据
|
|
|
+ ComPlayerGoods _targetGoods = comPlayerGoodsService.findByUserIdAndIndexAndType(_targetUserVo.getUserId(), comFruitVo.getId(), 1);
|
|
|
+ Integer _targetBeforeAmount = 0;
|
|
|
+ Integer _targetAfterAmount = 0;
|
|
|
+ if (_targetGoods == null) {
|
|
|
+ //背包增加一个果实
|
|
|
+ _targetGoods = new ComPlayerGoods();
|
|
|
+ //目标id
|
|
|
+ _targetGoods.setUserId(_targetUserVo.getUserId());
|
|
|
+ _targetGoods.setGoodsIndex(comFruitVo.getId());
|
|
|
+ _targetGoods.setGoodsType(1);
|
|
|
+ _targetGoods.setName(comFruitVo.getName());
|
|
|
+ //用种子的picture
|
|
|
+ _targetGoods.setPictureName(comFruitVo.getPicture());
|
|
|
+ _targetGoods.setAmount(amount);
|
|
|
+ _targetGoods.setAmountPart(0d);
|
|
|
+ _targetAfterAmount = _targetGoods.getAmount();
|
|
|
+ } else {
|
|
|
+ _targetBeforeAmount = _targetGoods.getAmount();
|
|
|
+ _targetGoods.setAmount(_targetGoods.getAmount() + amount);
|
|
|
+ _targetAfterAmount = _targetGoods.getAmount();
|
|
|
+ }
|
|
|
+ ComPlayerGoodsVo _targetGoodsVo = CopyUtil.copy(_targetGoods, ComPlayerGoodsVo.class);
|
|
|
+ comPlayerGoodsService.save(_targetGoodsVo);
|
|
|
+ //todo 接收果实,记录目标用户的playerLog
|
|
|
+ ComPlayerLog _targetPlayerLog = new ComPlayerLog();
|
|
|
+ _targetPlayerLog.setUserId(_targetUserVo.getUserId());
|
|
|
+ _targetPlayerLog.setTId(comFruitVo.getId());
|
|
|
+ _targetPlayerLog.setTName(comFruitVo.getName());
|
|
|
+ _targetPlayerLog.setTType(3);//接收用户赠送水果,type设置 3
|
|
|
+ _targetPlayerLog.setTAmount(_tAmount);
|
|
|
+ _targetPlayerLog.setBeforeAmount(_targetBeforeAmount);
|
|
|
+ ////交易后的数据
|
|
|
+ _targetPlayerLog.setAfterAmount(_targetAfterAmount);
|
|
|
+ //增加一个小数部分记录
|
|
|
+ _targetPlayerLog.setTPart(_tAmountPart);
|
|
|
+ _targetPlayerLog.setTLoss(0d);
|
|
|
+ _targetPlayerLog.setBeforePart(_selfBeforeFruitAmountPart);
|
|
|
+ _targetPlayerLog.setAfterPart(_selfAfterFruitAmountPart);
|
|
|
+
|
|
|
+ _targetPlayerLog.setLMultiple(0);
|
|
|
+ ComPlayerLogVo _targetPlayerLogVo = CopyUtil.copy(_targetPlayerLog, ComPlayerLogVo.class);
|
|
|
+ comPlayerLogService.save(_targetPlayerLogVo);
|
|
|
+ } catch (Exception e) {
|
|
|
+ throw new RuntimeException(e.getMessage());
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ Map map = new HashMap();
|
|
|
+ map.put("msg", "成功发送果实!");
|
|
|
+ return Result.of(map);
|
|
|
+ }
|
|
|
+}
|