Prechádzať zdrojové kódy

Merge branch 'master' of 450099795/FragrantTown_Server_Local into master

slambb 4 rokov pred
rodič
commit
08090ca453
21 zmenil súbory, kde vykonal 912 pridanie a 12 odobranie
  1. 16 0
      src/main/java/com/td/boss/common/pojo/ComConfig.java
  2. 14 0
      src/main/java/com/td/boss/common/repository/ComConfigRepository.java
  3. 11 0
      src/main/java/com/td/boss/common/service/ComConfigService.java
  4. 53 0
      src/main/java/com/td/boss/common/service/ComConfigServiceImpl.java
  5. 4 0
      src/main/java/com/td/boss/config/enums/ResultEnum.java
  6. 28 3
      src/main/java/com/td/boss/game/complayergoods/controller/ComPlayerGoodsController.java
  7. 2 0
      src/main/java/com/td/boss/game/complayerland/pojo/ComPlayerLand.java
  8. 2 0
      src/main/java/com/td/boss/game/complayerland/vo/ComPlayerLandVo.java
  9. 28 2
      src/main/java/com/td/boss/game/complayerprofit/service/ComPlayerProfitServiceImpl.java
  10. 81 0
      src/main/java/com/td/boss/game/complayersattri/controller/ComPlayersLuckyController.java
  11. 18 0
      src/main/java/com/td/boss/game/complayersattri/enums/ComPlayerLuckyLogEnum.java
  12. 60 0
      src/main/java/com/td/boss/game/complayersattri/pojo/ComPlayersLucky.java
  13. 12 0
      src/main/java/com/td/boss/game/complayersattri/repository/ComPlayersLuckyRepository.java
  14. 55 0
      src/main/java/com/td/boss/game/complayersattri/service/ComPlayersLuckyService.java
  15. 319 0
      src/main/java/com/td/boss/game/complayersattri/service/ComPlayersLuckyServiceImpl.java
  16. 24 0
      src/main/java/com/td/boss/game/complayersattri/vo/ComPlayersLuckyLandLevelUpVo.java
  17. 27 0
      src/main/java/com/td/boss/game/complayersattri/vo/ComPlayersLuckyToolsVo.java
  18. 34 0
      src/main/java/com/td/boss/game/complayersattri/vo/ComPlayersLuckyVo.java
  19. 16 2
      src/main/java/com/td/boss/util/RedisData.java
  20. 5 5
      src/main/resources/application.yml
  21. 103 0
      src/test/java/com/td/boss/ComPlayerLuckyTests.java

+ 16 - 0
src/main/java/com/td/boss/common/pojo/ComConfig.java

@@ -0,0 +1,16 @@
+package com.td.boss.common.pojo;
+
+import lombok.Data;
+
+import javax.persistence.*;
+import java.io.Serializable;
+
+@Entity
+@Data
+@Table(name = "com_players_lucky_tools")
+public class ComConfig implements Serializable {
+     @Id
+     @GeneratedValue(strategy = GenerationType.AUTO)
+     private String configKey;
+     private String configValue;
+}

+ 14 - 0
src/main/java/com/td/boss/common/repository/ComConfigRepository.java

@@ -0,0 +1,14 @@
+package com.td.boss.common.repository;
+
+import com.td.boss.common.pojo.ComConfig;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.stereotype.Repository;
+
+import java.util.List;
+
+@Repository
+public interface ComConfigRepository extends CommonRepository<ComConfig, Integer> {
+
+    @Query(value = "select * from com_config", nativeQuery = true)
+    public List<ComConfig> list();
+}

+ 11 - 0
src/main/java/com/td/boss/common/service/ComConfigService.java

@@ -0,0 +1,11 @@
+package com.td.boss.common.service;
+
+import com.td.boss.game.complayersattri.vo.ComPlayersLuckyLandLevelUpVo;
+
+import java.util.List;
+
+public interface ComConfigService {
+    String selectByKey(String key);
+
+    List<ComPlayersLuckyLandLevelUpVo> selectLandLevel();
+}

+ 53 - 0
src/main/java/com/td/boss/common/service/ComConfigServiceImpl.java

@@ -0,0 +1,53 @@
+package com.td.boss.common.service;
+
+import cn.hutool.core.util.StrUtil;
+import cn.hutool.json.JSONUtil;
+import com.td.boss.common.pojo.ComConfig;
+import com.td.boss.common.repository.ComConfigRepository;
+import com.td.boss.game.complayersattri.vo.ComPlayersLuckyLandLevelUpVo;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.core.StringRedisTemplate;
+import org.springframework.stereotype.Service;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@Service
+public class ComConfigServiceImpl implements ComConfigService {
+
+    private String redisKey = "data:com:config";
+    @Autowired
+    private StringRedisTemplate redisTemplate;
+
+    @Autowired
+    private ComConfigRepository repository;
+
+    private List<ComConfig> list() {
+        List<ComConfig> list = null;
+        String s = redisTemplate.opsForValue().get(redisKey);
+        if (StrUtil.isBlank(s)) {
+            list = repository.list();
+            redisTemplate.opsForValue().set(redisKey, JSONUtil.toJsonStr(list));
+        } else {
+            list = JSONUtil.toList(s, ComConfig.class);
+        }
+        return list;
+    }
+
+    @Override
+    public String selectByKey(String key) {
+        List<ComConfig> list = list();
+        return list.stream().filter(a -> a.getConfigKey().equals(key)).map(a -> a.getConfigValue()).findFirst().orElse("");
+    }
+    @Override
+    public List<ComPlayersLuckyLandLevelUpVo> selectLandLevel() {
+        String levelUp = "land_level";
+        List<ComConfig> list = list();
+        String land_tools = list.stream().filter(a -> a.getConfigKey().equals(levelUp)).map(a -> a.getConfigValue()).findFirst().orElse("");
+        if (StrUtil.isBlank(land_tools)) {
+            return new ArrayList<>();
+        } else {
+            return JSONUtil.toList(land_tools, ComPlayersLuckyLandLevelUpVo.class);
+        }
+    }
+}

+ 4 - 0
src/main/java/com/td/boss/config/enums/ResultEnum.java

@@ -71,6 +71,10 @@ public enum ResultEnum {
     LAND_CAN_STEAL_IS_NULL(712,"没有可收取果实的土地!"),
 
     LAND_CAN_STEAL_IS_MAX(713,"已无多余利润!"),//达到最大值
+    LAND_USE_TOOL(714,"该土地正在使用工具中!"),
+    LAND_LAND_LEVELUPPING(715,"该土地正在升级中!"),
+
+
     //种子数据不能存在
     SEED_DATA_ERROR(801,"种子数据不存在!"),
     FRUIT_DATA_ERROR(802,"果实数据不存在!"),

+ 28 - 3
src/main/java/com/td/boss/game/complayergoods/controller/ComPlayerGoodsController.java

@@ -1,7 +1,9 @@
 package com.td.boss.game.complayergoods.controller;
 
+import cn.hutool.core.convert.Convert;
 import com.td.boss.common.controller.*;
 import com.td.boss.common.pojo.Result;
+import com.td.boss.common.service.ComConfigService;
 import com.td.boss.config.enums.ResultEnum;
 import com.td.boss.game.comexplainland.service.ComExplainLandService;
 import com.td.boss.game.comexplainland.vo.ComExplainLandVo;
@@ -35,6 +37,7 @@ 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.complayersattri.vo.ComPlayersLuckyLandLevelUpVo;
 import com.td.boss.game.comsetting.pojo.ComSetting;
 import com.td.boss.game.comsetting.service.ComSettingService;
 import com.td.boss.game.comsetting.vo.ComSettingVo;
@@ -281,8 +284,8 @@ public class ComPlayerGoodsController extends CommonController<ComPlayerGoodsVo,
             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 landLevelInCome = getLandLevelInCome(comPlayerLand, comMallSeedVo.getPriceSnb());
+            Double _profitDouble = _profit.doubleValue()+landLevelInCome;
             Double _residualProfit = DoubleUtil.mul(_profitDouble, DoubleUtil.sub(1d, profitConfig));//如果 profitConfig 0.2,剩余利润就是0.8;
             Double _stealAmount = DoubleUtil.sub(_profitDouble, _residualProfit); //可偷取的利润
 
@@ -525,7 +528,8 @@ public class ComPlayerGoodsController extends CommonController<ComPlayerGoodsVo,
                 _otherAmount = otherPlayerLand.getLeaseMultiple() * comMallSeedVo.getHarvest3();
             }
             //todo 拿出计算利润,收获量减去种子的成本(snb)后的百分之30 ,后面需要后台可调整
-            Integer _profit = _otherAmount - otherPlayerLand.getLeaseMultiple() * comMallSeedVo.getPriceSnb();
+            Double landLevelInCome = getLandLevelInCome(otherPlayerLand, comMallSeedVo.getPriceSnb());
+            Double _profit = _otherAmount - otherPlayerLand.getLeaseMultiple() * comMallSeedVo.getPriceSnb()+landLevelInCome;
             // 配置的参数。这里先直接定义
             // 需要根据 狗是否生效,小偷是否装备打狗棒来确定参数
             Double profitConfig = _dogWork ? comSettingVo.getProfitDog() : comSettingVo.getProfit(),
@@ -972,6 +976,27 @@ public class ComPlayerGoodsController extends CommonController<ComPlayerGoodsVo,
 //
 //        return Result.of(map);
 //    }
+    @Autowired
+    private ComConfigService comConfigService;
+    /**
+     * 获得土地级别收益,普通土地最后结果为0
+     * @param comPlayerLand
+     * @param priceSnb
+     * @return
+     */
+    private Double getLandLevelInCome(ComPlayerLand comPlayerLand, Integer priceSnb) {
+        List<ComPlayersLuckyLandLevelUpVo> comPlayersLuckyLandLevelUpVos = comConfigService.selectLandLevel();
+        ComPlayersLuckyLandLevelUpVo first = comPlayersLuckyLandLevelUpVos.stream()
+                .filter(a -> a.getId().equals(comPlayerLand.getLandLevel()))
+                .findFirst().orElse(null);
+        //土地级别不存在
+        if (first == null) {
+            first = new ComPlayersLuckyLandLevelUpVo();
+            first.setProduct(0);
+        }
+        Integer all = comPlayerLand.getLeaseMultiple() * priceSnb;
+        return Convert.toDouble(all * first.getProduct() * 0.01);
+    }
 
 
     /**

+ 2 - 0
src/main/java/com/td/boss/game/complayerland/pojo/ComPlayerLand.java

@@ -47,4 +47,6 @@ public class ComPlayerLand implements Serializable {
     private Date createTime;
 
     private Date updateTime;
+
+    private Integer landLevel;//土地级别
 }

+ 2 - 0
src/main/java/com/td/boss/game/complayerland/vo/ComPlayerLandVo.java

@@ -44,4 +44,6 @@ public class ComPlayerLandVo extends PageCondition implements Serializable {
     private Date createTime;
 
     private Date updateTime;
+
+    private Integer landLevel;//土地级别
 }

+ 28 - 2
src/main/java/com/td/boss/game/complayerprofit/service/ComPlayerProfitServiceImpl.java

@@ -1,5 +1,6 @@
 package com.td.boss.game.complayerprofit.service;
 
+import cn.hutool.core.convert.Convert;
 import com.td.boss.common.service.*;
 import com.td.boss.game.commallseed.pojo.ComMallSeed;
 import com.td.boss.game.commallseed.vo.ComMallSeedVo;
@@ -7,6 +8,7 @@ import com.td.boss.game.complayerland.pojo.ComPlayerLand;
 import com.td.boss.game.complayerprofit.pojo.ComPlayerProfit;
 import com.td.boss.game.complayerprofit.vo.ComPlayerProfitVo;
 import com.td.boss.game.complayerprofit.repository.ComPlayerProfitRepository;
+import com.td.boss.game.complayersattri.vo.ComPlayersLuckyLandLevelUpVo;
 import com.td.boss.util.CopyUtil;
 import com.td.boss.util.DoubleUtil;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -78,7 +80,8 @@ public class ComPlayerProfitServiceImpl extends CommonServiceImpl<ComPlayerProfi
             _otherAmount = comPlayerLand.getLeaseMultiple() * comMallSeedVo.getHarvest3();
         }
         //todo 拿出全部利润
-        Integer _profit = _otherAmount - comPlayerLand.getLeaseMultiple() * comMallSeedVo.getPriceSnb();
+        Double landLevelInCome = getLandLevelInCome(comPlayerLand, comMallSeedVo.getPriceSnb());
+        Double _profit = _otherAmount - comPlayerLand.getLeaseMultiple() * comMallSeedVo.getPriceSnb()+landLevelInCome;
         //todo 计算减产,第一次灾难按利润的 50% 减产,两次就是减到 0 了。
 
         //必然发生的灾难,减产50%
@@ -133,7 +136,8 @@ public class ComPlayerProfitServiceImpl extends CommonServiceImpl<ComPlayerProfi
             _otherAmount = comPlayerLand.getLeaseMultiple() * comMallSeedVo.getHarvest3();
         }
         //todo 拿出全部利润
-        Integer _profit = _otherAmount - comPlayerLand.getLeaseMultiple() * comMallSeedVo.getPriceSnb();
+        Double landLevelInCome = getLandLevelInCome(comPlayerLand, comMallSeedVo.getPriceSnb());
+        Double _profit = _otherAmount - comPlayerLand.getLeaseMultiple() * comMallSeedVo.getPriceSnb()+landLevelInCome;
         //todo 计算减产,第一次灾难按利润的 50% 减产,两次就是减到 0 了。
 
         //额外发生的灾难,按照次数计算减产 50% 发生已经发生1次计算后当次等于 25%,
@@ -173,4 +177,26 @@ public class ComPlayerProfitServiceImpl extends CommonServiceImpl<ComPlayerProfi
 
         return comPlayerProfitVo;
     }
+    @Autowired
+    private ComConfigService comConfigService;
+
+    /**
+     * 获得土地级别收益,普通土地最后结果为0
+     * @param comPlayerLand
+     * @param priceSnb
+     * @return
+     */
+    private Double getLandLevelInCome( ComPlayerLand comPlayerLand, Integer priceSnb) {
+        List<ComPlayersLuckyLandLevelUpVo> comPlayersLuckyLandLevelUpVos = comConfigService.selectLandLevel();
+        ComPlayersLuckyLandLevelUpVo first = comPlayersLuckyLandLevelUpVos.stream()
+                .filter(a -> a.getId().equals(comPlayerLand.getLandLevel()))
+                .findFirst().orElse(null);
+        //土地级别不存在
+        if (first == null) {
+            first = new ComPlayersLuckyLandLevelUpVo();
+            first.setProduct(0);
+        }
+        Integer all = comPlayerLand.getLeaseMultiple() * priceSnb;
+        return Convert.toDouble(all * first.getProduct() * 0.01);
+    }
 }

+ 81 - 0
src/main/java/com/td/boss/game/complayersattri/controller/ComPlayersLuckyController.java

@@ -0,0 +1,81 @@
+package com.td.boss.game.complayersattri.controller;
+
+import com.td.boss.common.pojo.Result;
+import com.td.boss.game.complayersattri.service.ComPlayersLuckyService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+/**
+ * 工具功能模块
+ */
+@RequestMapping("/game/land")
+@RestController
+public class ComPlayersLuckyController {
+
+    //todo 土地升级还差一个 计算收益
+    @Autowired
+    private ComPlayersLuckyService service;
+
+    /**
+     * 获取所有工具列表,方便用户选择使用哪种工具来获取幸运值
+     *
+     * @return
+     */
+    @GetMapping("/tools")
+    public Result<?> getLandTools() {
+        return Result.of(service.getLandTools(), true, "查询成功");
+    }
+
+    /**
+     * 获取土地升级列表
+     *
+     * @return
+     */
+    @GetMapping("/level")
+    public Result<?> getLandLevelUp() {
+        return Result.of(service.getLandLevelUp(), true, "查询成功");
+    }
+
+    /**
+     * 使用某个工具 获得幸运值
+     *
+     * @param userId
+     * @param toolId
+     * @param landId
+     * @return
+     */
+    @PostMapping("/tools")
+    public Result<?> useLuckyTools(@RequestParam(value = "userId") String userId,
+                                   @RequestParam(value = "toolId") Integer toolId,
+                                   @RequestParam(value = "landId") Integer landId) {
+        return service.useLuckyTools(userId, toolId, landId);
+    }
+
+    /**
+     * 土地升级
+     *
+     * @param userId
+     * @param level
+     * @param landId
+     * @return
+     */
+    @PostMapping("/level")
+    public Result<?> landLevelUp(@RequestParam(value = "userId") String userId,
+                                 @RequestParam(value = "level") Integer level,
+                                 @RequestParam(value = "landId") Integer landId) {
+        return service.landLevelUp(userId, level, landId);
+    }
+
+    /**
+     * 兑换snb
+     *
+     * @param userId
+     * @param luckNum
+     * @return
+     */
+    @GetMapping("/snb")
+    public Result<?> toSNB(@RequestParam(value = "userId") String userId,
+                           @RequestParam(value = "luckNum") Integer luckNum) {
+        return service.toSNB(userId, luckNum);
+    }
+}

+ 18 - 0
src/main/java/com/td/boss/game/complayersattri/enums/ComPlayerLuckyLogEnum.java

@@ -0,0 +1,18 @@
+package com.td.boss.game.complayersattri.enums;
+
+import lombok.Getter;
+
+@Getter
+public enum ComPlayerLuckyLogEnum {
+    tool(0, "工具"),
+    level(1, "升级土地"),
+    cnb(2, "兑换CNB");
+
+    ComPlayerLuckyLogEnum(Integer code, String msg) {
+        this.code = code;
+        this.msg = msg;
+    }
+
+    private Integer code;
+    private String msg;
+}

+ 60 - 0
src/main/java/com/td/boss/game/complayersattri/pojo/ComPlayersLucky.java

@@ -0,0 +1,60 @@
+package com.td.boss.game.complayersattri.pojo;
+
+import lombok.Data;
+
+import javax.persistence.*;
+import java.io.Serializable;
+import java.util.Date;
+
+@Entity
+@Data
+@Table(name = "com_players_lucky")
+public class ComPlayersLucky implements Serializable {
+    /**
+     * 主键id
+     */
+    @Id
+    @GeneratedValue(strategy = GenerationType.IDENTITY)
+    private int id;
+    /**
+     * 用户id
+     */
+    private String userId;
+    /**
+     * 操作数量
+     */
+    private int amount;
+    /**
+     *操作名称
+     */
+    private String luckyName;
+    /**
+     * 幸运值来源类型
+     */
+    private int luckyType;
+    /**
+     * 操作前
+     */
+    private int beforeLucky;
+    /**
+     * 操作后
+     */
+    private int afterLucky;
+    /**
+     * 创建时间
+     */
+    private Date createTime;
+    /**
+     * 工具id
+     */
+    private Integer toolsId;
+    /**
+     * 土地id
+     */
+    private Integer landId;
+    /**
+     * 级别id
+     */
+    private Integer levelId;
+
+}

+ 12 - 0
src/main/java/com/td/boss/game/complayersattri/repository/ComPlayersLuckyRepository.java

@@ -0,0 +1,12 @@
+package com.td.boss.game.complayersattri.repository;
+
+import com.td.boss.common.repository.CommonRepository;
+import com.td.boss.game.complayersattri.pojo.ComPlayersLucky;
+import org.springframework.stereotype.Repository;
+
+import java.util.Optional;
+
+@Repository
+public interface ComPlayersLuckyRepository extends CommonRepository<ComPlayersLucky, Integer> {
+    Optional<ComPlayersLucky> findFirstByUserIdOrderByCreateTimeDesc(String userId);
+}

+ 55 - 0
src/main/java/com/td/boss/game/complayersattri/service/ComPlayersLuckyService.java

@@ -0,0 +1,55 @@
+package com.td.boss.game.complayersattri.service;
+
+import com.td.boss.common.pojo.Result;
+import com.td.boss.common.service.CommonService;
+import com.td.boss.game.complayersattri.pojo.ComPlayersLucky;
+import com.td.boss.game.complayersattri.vo.ComPlayersLuckyLandLevelUpVo;
+import com.td.boss.game.complayersattri.vo.ComPlayersLuckyToolsVo;
+import com.td.boss.game.complayersattri.vo.ComPlayersLuckyVo;
+import java.util.List;
+
+public interface ComPlayersLuckyService extends CommonService<ComPlayersLuckyVo, ComPlayersLucky, Integer> {
+
+    /**
+     * 使用某个工具 获得幸运值
+     *
+     * @param userId
+     * @param id
+     * @param landId
+     * @return
+     */
+    Result useLuckyTools(String userId, Integer id, Integer landId);
+
+    /**
+     * 土地升级
+     *
+     * @param userId
+     * @param levelId
+     * @param landId
+     * @return
+     */
+    Result<?> landLevelUp(String userId, Integer levelId, Integer landId);
+
+    /**
+     * 兑换snb
+     *
+     * @param userId
+     * @param luckNum
+     * @return
+     */
+    Result<?> toSNB(String userId, Integer luckNum);
+
+    /**
+     * 获取所有工具列表,方便用户选择使用哪种工具来获取幸运值
+     *
+     * @return
+     */
+    List<ComPlayersLuckyToolsVo> getLandTools();
+
+    /**
+     * 获取土地升级列表
+     *
+     * @return
+     */
+    List<ComPlayersLuckyLandLevelUpVo> getLandLevelUp();
+}

+ 319 - 0
src/main/java/com/td/boss/game/complayersattri/service/ComPlayersLuckyServiceImpl.java

@@ -0,0 +1,319 @@
+package com.td.boss.game.complayersattri.service;
+
+import cn.hutool.core.convert.Convert;
+import cn.hutool.core.date.DateField;
+import cn.hutool.core.date.DateTime;
+import cn.hutool.core.date.DateUtil;
+import cn.hutool.core.util.NumberUtil;
+import cn.hutool.core.util.StrUtil;
+import cn.hutool.json.JSONUtil;
+import com.td.boss.common.pojo.Result;
+import com.td.boss.common.service.ComConfigService;
+import com.td.boss.common.service.CommonServiceImpl;
+import com.td.boss.config.enums.ResultEnum;
+import com.td.boss.game.complayerland.pojo.ComPlayerLand;
+import com.td.boss.game.complayerland.repository.ComPlayerLandRepository;
+import com.td.boss.game.complayersattri.enums.ComPlayerLuckyLogEnum;
+import com.td.boss.game.complayersattri.pojo.ComPlayersAttri;
+import com.td.boss.game.complayersattri.pojo.ComPlayersLucky;
+import com.td.boss.game.complayersattri.repository.ComPlayersAttriRepository;
+import com.td.boss.game.complayersattri.repository.ComPlayersLuckyRepository;
+import com.td.boss.game.complayersattri.vo.ComPlayersLuckyLandLevelUpVo;
+import com.td.boss.game.complayersattri.vo.ComPlayersLuckyToolsVo;
+import com.td.boss.game.complayersattri.vo.ComPlayersLuckyVo;
+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.RedisData;
+import com.td.boss.util.RedisLock;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import javax.persistence.EntityManager;
+import javax.persistence.PersistenceContext;
+import java.util.Date;
+import java.util.List;
+import java.util.Optional;
+
+@Slf4j
+@Service
+@Transactional
+public class ComPlayersLuckyServiceImpl extends CommonServiceImpl<ComPlayersLuckyVo, ComPlayersLucky, Integer> implements ComPlayersLuckyService {
+
+    private String toolskey = "land_tools";
+    private String levelUp = "land_level";
+
+    @Autowired
+    private ComConfigService comConfigService;
+    @Autowired
+    private ComPlayersLuckyRepository repository;
+    @Autowired
+    private ComPlayersAttriRepository comPlayersAttriRepository;
+    @Autowired
+    private ComPlayerLandRepository comPlayerLandRepository;
+    @Autowired
+    private ComUsersService comUsersService;
+    @Autowired
+    private ComSnbTranService comSnbTranService;
+    @Autowired
+    private RedisLock redisLock;
+
+    /**
+     * 使用的工具 获得幸运值,12小时获取一次
+     *
+     * @param userId
+     * @param toolId
+     * @return
+     */
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public Result useLuckyTools(String userId, Integer toolId, Integer landId) {
+        //验证工具是否存在
+        ComPlayersLuckyToolsVo tools = getLandTools().stream().filter(a -> a.getId().equals(toolId)).findFirst().orElse(null);
+        if (tools == null || tools.isEnable() == false) {
+            return Result.of(null, false, "无效工具");
+        }
+        //验证土地是否存在
+        ComPlayerLand comPlayerLand = comPlayerLandRepository.findById(landId).orElse(null);
+        if (comPlayerLand == null || comPlayerLand.getUserId().equals(userId) == false) {
+            return Result.of(null, false, "升级失败,无效土地!");
+        }
+        //土地租赁到期了,不能使用工具
+        if (comPlayerLand.getLeaseTime().before(new Date())) {
+            return Result.of(null, false, "升级失败,土地已到期!");
+        }
+        //验证用户是否存在
+        ComPlayersAttri playersAttri = comPlayersAttriRepository.findByUserId(userId).orElse(null);
+        if (playersAttri == null) {
+            return Result.of(null, false, "无效用户");
+        }
+
+        long time = System.currentTimeMillis() + RedisData.getPlayerLandToolTimeout();
+        String _redisKey = "LOCK:COM_PLAYER_LAND_TOOL:" + userId;
+        if (!redisLock.lock(_redisKey, String.valueOf(time))) {
+            return Result.of(null, false, ResultEnum.LAND_USE_TOOL.getMessage(), ResultEnum.LAND_USE_TOOL.getCode());
+        }
+        //验证工具是否可用:每隔一段时间才可使用
+        Optional<ComPlayersLucky> lastComPlayersLuckyLog = repository.findFirstByUserIdOrderByCreateTimeDesc(userId);
+        if (lastComPlayersLuckyLog.isPresent()) {
+            DateTime nextTime = DateUtil.offset(lastComPlayersLuckyLog.get().getCreateTime(), DateField.HOUR_OF_DAY, tools.getUseHour());
+            if (nextTime.isAfter(new Date())) {
+                return Result.of(null, false, "请在" + nextTime.toDateStr() + "后使用工具");
+            }
+        }
+        int afterLucky = playersAttri.getLucky() + tools.getToolLucky();
+        //写入使用工具明细
+        ComPlayersLucky comPlayersLucky = new ComPlayersLucky();
+        comPlayersLucky.setAfterLucky(afterLucky);
+        comPlayersLucky.setBeforeLucky(playersAttri.getLucky());
+        comPlayersLucky.setAmount(tools.getToolLucky());
+        comPlayersLucky.setLuckyType(ComPlayerLuckyLogEnum.tool.getCode());
+        comPlayersLucky.setToolsId(toolId);
+        comPlayersLucky.setUserId(userId);
+        comPlayersLucky.setLevelId(0);
+        comPlayersLucky.setLandId(landId);
+        comPlayersLucky.setLuckyName(tools.getToolName());
+        comPlayersLucky.setCreateTime(new Date());
+        repository.save(comPlayersLucky);
+
+        //更新幸运值
+        playersAttri.setLucky(afterLucky);
+        comPlayersAttriRepository.save(playersAttri);
+        return Result.of(null, true, "使用工具成功");
+    }
+
+    /**
+     * 土地升级
+     *
+     * @param userId
+     * @param levelId
+     * @param landId
+     * @return
+     */
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public Result<?> landLevelUp(String userId, Integer levelId, Integer landId) {
+        //验证土地级别是否存在
+        ComPlayersLuckyLandLevelUpVo landLevelUpVo = getLandLevelUp().stream().filter(a -> a.getId().equals(levelId)).findFirst().orElse(null);
+        if (landLevelUpVo == null) {
+            return Result.of(null, false, "升级失败,无效升级!");
+        }
+        //验证土地是否存在
+        ComPlayerLand comPlayerLand = comPlayerLandRepository.findById(landId).orElse(null);
+        if (comPlayerLand == null || comPlayerLand.getUserId().equals(userId) == false) {
+            return Result.of(null, false, "升级失败,无效土地!");
+        }
+        //验证 将要升级的土地级别是否大于当前土地级别
+        if (comPlayerLand.getLandLevel() >= levelId) {
+            return Result.of(null, false, "升级失败,无效级别!");
+        }
+        //土地租赁到期了,不能升级
+        if (comPlayerLand.getLeaseTime().before(new Date())) {
+            return Result.of(null, false, "升级失败,土地已到期!");
+        }
+
+        long time = System.currentTimeMillis() + RedisData.getPlayerLandLevelupTimeout();
+        String _redisKey = "LOCK:COM_PLAYER_LAND_LEVELUP:" + userId;
+        if (!redisLock.lock(_redisKey, String.valueOf(time))) {
+            return Result.of(null, false, ResultEnum.LAND_LAND_LEVELUPPING.getMessage(), ResultEnum.LAND_LAND_LEVELUPPING.getCode());
+        }
+        //验证用户是否存在
+        ComPlayersAttri playersAttri = comPlayersAttriRepository.findByUserId(userId).orElse(null);
+        if (playersAttri == null) {
+            return Result.of(null, false, "升级失败");
+        }
+        //验证幸运值是否够用
+        int sub = Convert.toInt(NumberUtil.sub(playersAttri.getLucky(), landLevelUpVo.getCostLucky()));
+        if (sub < 0) {
+            return Result.of(null, false, "升级失败,幸运值不足!");
+        }
+        //写入使用工具明细
+        ComPlayersLucky comPlayersLucky = new ComPlayersLucky();
+        comPlayersLucky.setAfterLucky(sub);
+        comPlayersLucky.setBeforeLucky(playersAttri.getLucky());
+        comPlayersLucky.setAmount(landLevelUpVo.getCostLucky());
+        comPlayersLucky.setLuckyType(ComPlayerLuckyLogEnum.level.getCode());
+        comPlayersLucky.setLuckyName(landLevelUpVo.getName());
+        comPlayersLucky.setLevelId(levelId);
+        comPlayersLucky.setLandId(landId);
+        comPlayersLucky.setUserId(userId);
+        comPlayersLucky.setCreateTime(new Date());
+        repository.save(comPlayersLucky);
+
+        //更新用户剩余幸运值
+        playersAttri.setLucky(sub);
+        comPlayersAttriRepository.save(playersAttri);
+
+        //更新土地级别
+        comPlayerLand.setLandLevel(levelId);
+        comPlayerLandRepository.save(comPlayerLand);
+        return Result.of(null, true, "升级成功");
+    }
+
+    /**
+     * 兑换snb
+     *
+     * @param userId
+     * @param luckNum 消耗幸运值数量
+     * @return
+     */
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public Result<?> toSNB(String userId, Integer luckNum) {
+        //兑换snb倍数
+        int snb = Convert.toInt(comConfigService.selectByKey("land_luck_tosnb"), 0);
+        if (luckNum < 1000) {
+            return Result.of(null, false, "幸运值满1000才能兑换SNB");
+        }
+        if (luckNum > 100000) {
+            return Result.of(null, false, "幸运值最多不能大于100000");
+        }
+        if (luckNum % snb != 0) {
+            return Result.of(null, false, StrUtil.format("幸运值必须为{}的倍数", snb));
+        }
+        ComUsersVo comUsersVo = comUsersService.findByUserId(userId);
+        if (comUsersVo == null || StrUtil.isBlank(comUsersVo.getAddress())) {
+            return Result.of(null, false, "未找到用户或钱包地址");
+        }
+        long time = System.currentTimeMillis() + RedisData.getSnbTimeout();
+        String redisKey = StrUtil.format("SNB_SAVE_{}", userId);
+        // redis锁
+        if (!redisLock.lock(redisKey, String.valueOf(time))) {
+            return Result.of(null, false, ResultEnum.SEED_SALE_SAVE_LOCK.getMessage(), ResultEnum.SEED_SALE_SAVE_LOCK.getCode());
+        }
+        //获得snb用户对象
+        ComUsersVo player = comUsersService.findByUserId(userId);
+        //获得幸运值用户对象
+        ComPlayersAttri playersAttri = comPlayersAttriRepository.findByUserId(userId).orElse(null);
+        if (playersAttri == null || player == null) {
+            return Result.of(null, false, "无效用户");
+        }
+        //剩余幸运值
+        int num = playersAttri.getLucky() - luckNum;
+        if (num < 0) {
+            return Result.of(null, false, "幸运值不足!");
+        }
+        //兑换snb数量
+        int snbNum = luckNum / snb;
+        //插入明细
+        mingxi(userId, luckNum, playersAttri.getLucky(), player.getSnb(), snbNum);
+
+        //更新用户snb
+        player.setSnb(player.getSnb() + snbNum);
+        comUsersService.save(player);
+
+        //更新用户幸运值
+        playersAttri.setLucky(num);
+        comPlayersAttriRepository.save(playersAttri);
+        return Result.of(null, true, StrUtil.format("成功兑换{}个snb,消耗{}个幸运值", snbNum, luckNum));
+    }
+
+    /**
+     * @param userId
+     * @param luckNum    消耗的幸运值
+     * @param beforeLuck 兑换前的幸运值
+     * @param beforeSNB  兑换前的snb数量
+     * @param snbNum     兑换snb的数量
+     */
+    private void mingxi(String userId, int luckNum, int beforeLuck, int beforeSNB, int snbNum) {
+        //记录幸运值明细
+        ComPlayersLucky comPlayersLucky = new ComPlayersLucky();
+        comPlayersLucky.setAfterLucky(beforeLuck - luckNum);
+        comPlayersLucky.setBeforeLucky(beforeLuck);
+        comPlayersLucky.setAmount(luckNum);
+        comPlayersLucky.setLuckyType(ComPlayerLuckyLogEnum.cnb.getCode());
+        comPlayersLucky.setLuckyName(ComPlayerLuckyLogEnum.cnb.getMsg());
+        comPlayersLucky.setLevelId(0);
+        comPlayersLucky.setLandId(0);
+        comPlayersLucky.setToolsId(0);
+        comPlayersLucky.setUserId(userId);
+        comPlayersLucky.setCreateTime(new Date());
+        comPlayersLucky = repository.save(comPlayersLucky);
+
+
+        //记录snb明细
+        ComSnbTranVo snbTran = new ComSnbTranVo();
+        //记录兑换id
+        snbTran.setTranId(Convert.toStr(comPlayersLucky.getId()));
+        snbTran.setUserId(userId);
+        snbTran.setTranName("兑换SNB");
+        snbTran.setTranType(9);
+        snbTran.setTranAmount(snbNum);
+        snbTran.setTranDescribe(StrUtil.format("user幸运值兑换SNB、本次兑换:{},消耗:{}幸运值", snbNum, luckNum));
+        snbTran.setIsAdd(1);
+        snbTran.setBeforeSnb(beforeSNB);
+        snbTran.setTranSnb(snbNum);
+        snbTran.setAfterSnb(beforeSNB + snbNum);
+        snbTran.setCreateTime(new Date());
+        snbTran.setTranSnbPart(0d);
+        snbTran.setAfterSnbPart(0d);
+        snbTran.setBeforeSnbPart(0d);
+        snbTran.setTranAmountPart(0d);
+        snbTran.setTranPrice(0);
+        comSnbTranService.save(snbTran);
+    }
+
+    /**
+     * 获取所有工具列表,方便用户选择使用哪种工具来获取幸运值
+     *
+     * @return
+     */
+    @Override
+    public List<ComPlayersLuckyToolsVo> getLandTools() {
+        String land_tools = comConfigService.selectByKey(toolskey);
+        return JSONUtil.toList(land_tools, ComPlayersLuckyToolsVo.class);
+    }
+
+    /**
+     * 获取土地升级列表
+     *
+     * @return
+     */
+    @Override
+    public List<ComPlayersLuckyLandLevelUpVo> getLandLevelUp() {
+        return comConfigService.selectLandLevel();
+    }
+}

+ 24 - 0
src/main/java/com/td/boss/game/complayersattri/vo/ComPlayersLuckyLandLevelUpVo.java

@@ -0,0 +1,24 @@
+package com.td.boss.game.complayersattri.vo;
+
+import lombok.Data;
+
+@Data
+public class ComPlayersLuckyLandLevelUpVo {
+    /**
+     * id
+     */
+    private Integer id;
+    /**
+     * 级别名称
+     */
+    private String name;
+    /**
+     * 收益产出百分比
+     */
+    private Integer product;
+
+    /**
+     * 消耗多少幸运值
+     */
+    private Integer costLucky;
+}

+ 27 - 0
src/main/java/com/td/boss/game/complayersattri/vo/ComPlayersLuckyToolsVo.java

@@ -0,0 +1,27 @@
+package com.td.boss.game.complayersattri.vo;
+
+import lombok.Data;
+
+import java.util.Date;
+
+@Data
+public class ComPlayersLuckyToolsVo {
+    private Integer id;
+    /**
+     * 工具名称
+     */
+    private String toolName;
+    /**
+     * 工具使用间隔
+     */
+    private int useHour;
+    /**
+     * 幸运值
+     */
+    private int toolLucky;
+    /**
+     * 创建时间
+     */
+    private Date createTime;
+    private boolean isEnable;
+}

+ 34 - 0
src/main/java/com/td/boss/game/complayersattri/vo/ComPlayersLuckyVo.java

@@ -0,0 +1,34 @@
+package com.td.boss.game.complayersattri.vo;
+
+import lombok.Data;
+import java.io.Serializable;
+import java.util.Date;
+
+@Data
+public class ComPlayersLuckyVo implements Serializable {
+    private int id ;
+    /** 用户id */
+    private String userId ;
+    /** 操作数量 */
+    private int amount ;
+    /** 幸运值来源类型 */
+    private Integer luckyType ;
+    /** 操作前 */
+    private int beforeLucky ;
+    /** 操作后 */
+    private int afterLucky ;
+    /** 创建时间 */
+    private Date createTime ;
+    /**
+     * 工具id
+     */
+    private Integer toolsId;
+    /**
+     * 土地id
+     */
+    private Integer landId;
+    /**
+     *操作名称
+     */
+    private String luckyName;
+}

+ 16 - 2
src/main/java/com/td/boss/util/RedisData.java

@@ -61,12 +61,26 @@ public class RedisData {
         return PLAYER_DISASTERS_DAY_TIMEOUT;
     }
 
+    /**
+     * 5s 工具模块锁
+     */
+    private static final int PLAYER_LAND_TOOL_TIMEOUT = 5 * 1000; //超时时间 10s
+    public static int getPlayerLandToolTimeout() {
+        return PLAYER_LAND_TOOL_TIMEOUT;
+    }
 
+    /**
+     * 5s 工具模块锁
+     */
+    private static final int PLAYER_LAND_LEVELUP_TIMEOUT = 5 * 1000; //超时时间 10s
+    public static int getPlayerLandLevelupTimeout() {
+        return PLAYER_LAND_LEVELUP_TIMEOUT;
+    }
     /**
      * 20s 自动审核锁
      */
-    private static final int AUTO_APPLY_TIMEOUT = 1000*20;
-    public static int getAutoApplyTimeout() {
+    private static final int AUTO_APPLY_TIMEOUT = 1000 * 20;
+    public static int getAutoApplyTimeout () {
         return AUTO_APPLY_TIMEOUT;
     }
 }

+ 5 - 5
src/main/resources/application.yml

@@ -48,9 +48,9 @@ spring:
 
   #数据库配置
   datasource:
-    url: jdbc:mysql://127.0.0.1:6688/dragon_town?useSSL=false&serverTimezone=GMT%2B8&characterEncoding=utf-8
-    username: dragon_town #dragon_town #root
-    password:  zddeiBmp8c5T6TR6 #zddeiBmp8c5T6TR6 #9ab8fad748dead93
+    url: jdbc:mysql://123.57.252.53:6688/dragon_town?useSSL=false&serverTimezone=GMT%2B8&characterEncoding=utf-8
+    username: root #dragon_town #root
+    password:  7a829d0ecde828 #zddeiBmp8c5T6TR6 #9ab8fad748dead93
     driver-class-name: com.mysql.cj.jdbc.Driver
     hikari:
       minimum-idle: 5
@@ -62,9 +62,9 @@ spring:
       connection-test-query: SELECT 1
 
   redis:
-    host: 127.0.0.1
+    host: 123.57.252.53
     port: 6379
-    password:
+    password: heihei
     data: #工程中只是把redis作为缓存,并未使用redis作为数据持久化存储源repository使用.
       redis:
         repositories:

+ 103 - 0
src/test/java/com/td/boss/ComPlayerLuckyTests.java

@@ -0,0 +1,103 @@
+package com.td.boss;
+
+import cn.hutool.json.JSONUtil;
+import com.td.boss.common.pojo.Result;
+import com.td.boss.game.complayersattri.controller.ComPlayersLuckyController;
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringRunner;
+
+/**
+ * 工具模块
+ */
+@RunWith(SpringRunner.class)
+@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
+public class ComPlayerLuckyTests {
+    private String userId = "1002";
+    private int landId = 169;
+    private int levelId = 2;
+
+    @Autowired
+    ComPlayersLuckyController comPlayersLuckyController;
+
+    @Test
+    public void getLandTools() {
+        Result<?> landTools = comPlayersLuckyController.getLandTools();
+        System.out.println(JSONUtil.toJsonStr(landTools));
+    }
+
+    @Test
+    public void getLandLevelUp() {
+        Result<?> landLevelUp = comPlayersLuckyController.getLandLevelUp();
+        System.out.println(JSONUtil.toJsonStr(landLevelUp));
+    }
+
+    /**
+     * 测试使用工具
+     */
+    @Test
+    public void useLuckyTools() {
+        Result<?> result_tool = comPlayersLuckyController.useLuckyTools(userId, 9999999, landId);
+        Assert.assertFalse(result_tool.isFlag());
+
+        Result<?> result_land = comPlayersLuckyController.useLuckyTools(userId, 2, 9999999);
+        Assert.assertFalse(result_land.isFlag());
+
+        Result<?> result_endDate = comPlayersLuckyController.useLuckyTools(userId, 2, 3);
+        Assert.assertFalse(result_endDate.isFlag());
+
+        Result<?> result_user = comPlayersLuckyController.useLuckyTools("9999999", 2, landId);
+        Assert.assertFalse(result_user.isFlag());
+
+        Result<?> result = comPlayersLuckyController.useLuckyTools(userId, 2, landId);
+        Assert.assertTrue(result.isFlag());
+    }
+
+    /**
+     * 测试土地升级
+     */
+    @Test
+    public void landLevelUp() {
+        Result<?> result_user = comPlayersLuckyController.landLevelUp("9999999", levelId, landId);
+        Assert.assertFalse(result_user.isFlag());
+        Result<?> result_level = comPlayersLuckyController.landLevelUp(userId, 9999999, landId);
+        Assert.assertFalse(result_level.isFlag());
+        Result<?> result_land = comPlayersLuckyController.landLevelUp(userId, levelId, 9999999);
+        Assert.assertFalse(result_land.isFlag());
+        //幸运值不够
+        Result<?> result_no = comPlayersLuckyController.landLevelUp("1024", levelId, 3);
+        Assert.assertFalse(result_no.isFlag());
+        //测试到期
+        Result<?> result_endDate = comPlayersLuckyController.useLuckyTools(userId, 2, 170);
+        Assert.assertFalse(result_endDate.isFlag());
+        //测试正常升级
+        Result<?> result = comPlayersLuckyController.landLevelUp(userId, levelId, landId);
+        Assert.assertTrue(result.isFlag());
+        //重复升级
+        Result<?> result2 = comPlayersLuckyController.landLevelUp(userId, levelId, landId);
+        Assert.assertFalse(result2.isFlag());
+    }
+
+    /**
+     * 兑换snb
+     */
+    @Test
+    public void toSNB() {
+        Result<?> result_user = comPlayersLuckyController.toSNB("9999999", 50 * 20);
+        Assert.assertFalse(result_user.isFlag());
+        //幸运值不够
+        Result<?> result_land = comPlayersLuckyController.toSNB(userId, 100000);
+        Assert.assertFalse(result_land.isFlag());
+        //幸运值边界
+        Result<?> result_land1 = comPlayersLuckyController.toSNB(userId, 999);
+        Assert.assertFalse(result_land1.isFlag());
+        Result<?> result_land2 = comPlayersLuckyController.toSNB(userId, 100001);
+        Assert.assertFalse(result_land2.isFlag());
+        //正常兑换
+        Result<?> result = comPlayersLuckyController.toSNB(userId, 50 * 20);
+        System.out.println(JSONUtil.toJsonStr(result));
+    }
+}