From d9161499ad7b0ebaf8849f503a1dad27940d42c8 Mon Sep 17 00:00:00 2001 From: hudingrong <1649576115@qq.com> Date: Thu, 11 Apr 2024 15:40:15 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E6=88=90=E7=AD=96=E7=95=A5=E6=9D=83?= =?UTF-8?q?=E9=87=8D=E5=88=86=E9=85=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mybatis/mapper/strategy_mapper.xml | 6 ++ .../mybatis/mapper/strategy_rule_mapper.xml | 5 ++ .../cn/bugstack/test/domain/StrategyTest.java | 24 +++++- .../model/entity/StrategyAwardEntity.java | 3 +- .../strategy/model/entity/StrategyEntity.java | 42 +++++++++ .../model/entity/StrategyRuleEntity.java | 70 +++++++++++++++ .../repository/IStrategyRepository.java | 34 ++++++-- .../service/armory/IStrategyArmory.java | 9 +- .../service/armory/IStrategyDispatch.java | 24 ++++++ .../service/armory/StrategyArmory.java | 77 +++++++++++++---- .../persistent/dao/IStrategyDao.java | 7 ++ .../persistent/dao/IStrategyRuleDao.java | 6 ++ .../persistent/po/Strategy.java | 2 + .../repository/StrategyRepository.java | 86 ++++++++++++++++--- .../cn/bugstack/types/common/Constants.java | 3 + .../cn/bugstack/types/enums/ResponseCode.java | 1 + 16 files changed, 351 insertions(+), 48 deletions(-) create mode 100644 xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/model/entity/StrategyEntity.java create mode 100644 xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/model/entity/StrategyRuleEntity.java create mode 100644 xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/service/armory/IStrategyDispatch.java diff --git a/xfg-frame-archetype-lite-app/src/main/resources/mybatis/mapper/strategy_mapper.xml b/xfg-frame-archetype-lite-app/src/main/resources/mybatis/mapper/strategy_mapper.xml index 33ec1d5..c60fd38 100644 --- a/xfg-frame-archetype-lite-app/src/main/resources/mybatis/mapper/strategy_mapper.xml +++ b/xfg-frame-archetype-lite-app/src/main/resources/mybatis/mapper/strategy_mapper.xml @@ -6,6 +6,7 @@ + @@ -15,5 +16,10 @@ from strategy limit 10 + diff --git a/xfg-frame-archetype-lite-app/src/main/resources/mybatis/mapper/strategy_rule_mapper.xml b/xfg-frame-archetype-lite-app/src/main/resources/mybatis/mapper/strategy_rule_mapper.xml index 4b3556b..f160d79 100644 --- a/xfg-frame-archetype-lite-app/src/main/resources/mybatis/mapper/strategy_rule_mapper.xml +++ b/xfg-frame-archetype-lite-app/src/main/resources/mybatis/mapper/strategy_rule_mapper.xml @@ -19,5 +19,10 @@ from strategy_rule limit 10 + diff --git a/xfg-frame-archetype-lite-app/src/test/java/cn/bugstack/test/domain/StrategyTest.java b/xfg-frame-archetype-lite-app/src/test/java/cn/bugstack/test/domain/StrategyTest.java index 665bde5..0cd9ee1 100644 --- a/xfg-frame-archetype-lite-app/src/test/java/cn/bugstack/test/domain/StrategyTest.java +++ b/xfg-frame-archetype-lite-app/src/test/java/cn/bugstack/test/domain/StrategyTest.java @@ -1,8 +1,10 @@ package cn.bugstack.test.domain; import cn.bugstack.domain.strategy.service.armory.IStrategyArmory; +import cn.bugstack.domain.strategy.service.armory.IStrategyDispatch; import cn.bugstack.infrastructure.persistent.redis.IRedisService; import lombok.extern.slf4j.Slf4j; +import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.redisson.api.RMap; @@ -25,21 +27,34 @@ public class StrategyTest { @Resource private IStrategyArmory strategyArmory; + @Resource + private IStrategyDispatch strategyDispatch; + /** * 策略ID;100001L、100002L 装配的时候创建策略表写入到 Redis Map 中 */ @Test public void test_strategyArmory() { - strategyArmory.assembleLotteryStrategy(100002L); - log.info("测试结果:{}"); + boolean success = strategyArmory.assembleLotteryStrategy(100001L); + log.info("测试结果:{}", success); } /** * 从装配的策略中随机获取奖品ID值 */ @Test - public void test_getAssembleRandomVal() { - log.info("测试结果:{} - 奖品ID值", strategyArmory.getRandomAwardId(100002L)); + public void test_getRandomAwardId() { + log.info("测试结果:{} - 奖品ID值", strategyDispatch.getRandomAwardId(100001L)); + } + + /** + * 根据策略ID+权重值,从装配的策略中随机获取奖品ID值 + */ + @Test + public void test_getRandomAwardId_ruleWeightValue() { + log.info("测试结果:{} - 4000 策略配置", strategyDispatch.getRandomAwardId(100001L, "4000:102,103,104,105")); + log.info("测试结果:{} - 5000 策略配置", strategyDispatch.getRandomAwardId(100001L, "5000:102,103,104,105,106,107")); + log.info("测试结果:{} - 6000 策略配置", strategyDispatch.getRandomAwardId(100001L, "6000:102,103,104,105,106,107,108,109")); } @Resource @@ -90,4 +105,5 @@ public class StrategyTest { } } + } diff --git a/xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/model/entity/StrategyAwardEntity.java b/xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/model/entity/StrategyAwardEntity.java index 85416c3..d05e8ca 100644 --- a/xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/model/entity/StrategyAwardEntity.java +++ b/xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/model/entity/StrategyAwardEntity.java @@ -5,6 +5,7 @@ import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; +import java.io.Serializable; import java.math.BigDecimal; /** @@ -17,7 +18,7 @@ import java.math.BigDecimal; @Builder @AllArgsConstructor @NoArgsConstructor -public class StrategyAwardEntity { +public class StrategyAwardEntity implements Serializable { /** 抽奖策略ID */ private Long strategyId; /** 抽奖奖品ID - 内部流转使用 */ diff --git a/xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/model/entity/StrategyEntity.java b/xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/model/entity/StrategyEntity.java new file mode 100644 index 0000000..dfa2ee2 --- /dev/null +++ b/xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/model/entity/StrategyEntity.java @@ -0,0 +1,42 @@ +package cn.bugstack.domain.strategy.model.entity; + +import cn.bugstack.types.common.Constants; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.apache.commons.lang3.StringUtils; + +/** + * @description: 策略实体 + * @author: hdr + * @PACKAGE_NAME: cn.bugstack.domain.strategy.model.entity + * @DATE: 2024/4/9 + */ +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class StrategyEntity { + + /** 抽奖策略ID */ + private Long strategyId; + /** 抽奖策略描述 */ + private String strategyDesc; + /** 抽奖规则模型 rule_weight,rule_blacklist */ + private String ruleModels; + + public String[] ruleModels() { + if (StringUtils.isBlank(ruleModels)) return null; + return ruleModels.split(Constants.SPLIT); + } + + public String getRuleWeight() { + String[] ruleModels = this.ruleModels(); + for (String ruleModel : ruleModels) { + if ("rule_weight".equals(ruleModel)) return ruleModel; + } + return null; + } + +} diff --git a/xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/model/entity/StrategyRuleEntity.java b/xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/model/entity/StrategyRuleEntity.java new file mode 100644 index 0000000..748d364 --- /dev/null +++ b/xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/model/entity/StrategyRuleEntity.java @@ -0,0 +1,70 @@ +package cn.bugstack.domain.strategy.model.entity; + +import cn.bugstack.types.common.Constants; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * @description: + * @author: hdr + * @PACKAGE_NAME: cn.bugstack.domain.strategy.model.entity + * @DATE: 2024/4/9 + */ +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class StrategyRuleEntity { + + /** 抽奖策略ID */ + private Long strategyId; + /** 抽奖奖品ID【规则类型为策略,则不需要奖品ID】 */ + private Integer awardId; + /** 抽象规则类型;1-策略规则、2-奖品规则 */ + private Integer ruleType; + /** 抽奖规则类型【rule_random - 随机值计算、rule_lock - 抽奖几次后解锁、rule_luck_award - 幸运奖(兜底奖品)】 */ + private String ruleModel; + /** 抽奖规则比值 */ + private String ruleValue; + /** 抽奖规则描述 */ + private String ruleDesc; + + /** + * 获取权重值 + * 数据案例;4000:102,103,104,105 5000:102,103,104,105,106,107 6000:102,103,104,105,106,107,108,109 + */ + public Map> getRuleWeightValues() { + if (!"rule_weight".equals(ruleModel)) return null; + String[] ruleValueGroups = ruleValue.split(Constants.SPACE); + Map> resultMap = new HashMap<>(); + for (String ruleValueGroup : ruleValueGroups) { + // 检查输入是否为空 + if (ruleValueGroup == null || ruleValueGroup.isEmpty()) { + return resultMap; + } + // 分割字符串以获取键和值 + String[] parts = ruleValueGroup.split(Constants.COLON); + if (parts.length != 2) { + throw new IllegalArgumentException("rule_weight rule_rule invalid input format" + ruleValueGroup); + } + // 解析值 + String[] valueStrings = parts[1].split(Constants.SPLIT); + List values = new ArrayList<>(); + for (String valueString : valueStrings) { + values.add(Integer.parseInt(valueString)); + } + // 将键和值放入Map中 + resultMap.put(ruleValueGroup, values); + } + + return resultMap; + } + +} diff --git a/xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/repository/IStrategyRepository.java b/xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/repository/IStrategyRepository.java index 07d3a95..d0908f6 100644 --- a/xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/repository/IStrategyRepository.java +++ b/xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/repository/IStrategyRepository.java @@ -1,6 +1,8 @@ package cn.bugstack.domain.strategy.repository; import cn.bugstack.domain.strategy.model.entity.StrategyAwardEntity; +import cn.bugstack.domain.strategy.model.entity.StrategyEntity; +import cn.bugstack.domain.strategy.model.entity.StrategyRuleEntity; import java.math.BigDecimal; import java.util.HashMap; @@ -23,11 +25,11 @@ public interface IStrategyRepository { List queryStrategyAwardList(Long strategy); /** - * @param strategyId 策略id + * @param key 策略id * @param rateRange 概率 * @param shuffleStrategyAwardSearchRateTables 所有保存的概率 */ - void storeStrategyAwardSearchRateTables(Long strategyId, Integer rateRange, HashMap shuffleStrategyAwardSearchRateTables); + void storeStrategyAwardSearchRateTables(String key, Integer rateRange, HashMap shuffleStrategyAwardSearchRateTables); /** * @@ -37,10 +39,32 @@ public interface IStrategyRepository { int getRandomAwardId(Long strategyId); /** - * 获取哦奖品id - * @param strategyId + * 获取奖品id + * @param key * @param nextInt * @return */ - Integer getStrategyAwardAssemble(Long strategyId, int nextInt); + Integer getStrategyAwardAssemble(String key, int nextInt); + + /** + * 获取抽奖策略 + * @param strategy 策略id + * @return + */ + StrategyEntity queryStrategyEntityByStrategyId(Long strategy); + + /** + * 查询抽奖策略规则 + * @param strategy 策略id + * @param ruleWeight 策略id + * @return + */ + StrategyRuleEntity queryStrategyRule(Long strategyId, String ruleWeight); + + /** + * 获取概率值 + * @param key + * @return + */ + int getRateRange(String key); } diff --git a/xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/service/armory/IStrategyArmory.java b/xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/service/armory/IStrategyArmory.java index de41f53..afce43c 100644 --- a/xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/service/armory/IStrategyArmory.java +++ b/xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/service/armory/IStrategyArmory.java @@ -12,12 +12,7 @@ public interface IStrategyArmory { * 抽奖策略 * @param strategy */ - void assembleLotteryStrategy(Long strategy); + boolean assembleLotteryStrategy(Long strategy); + - /** - * 获取随机奖品id - * @param strategyId - * @return - */ - Integer getRandomAwardId(Long strategyId); } diff --git a/xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/service/armory/IStrategyDispatch.java b/xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/service/armory/IStrategyDispatch.java new file mode 100644 index 0000000..da2be9f --- /dev/null +++ b/xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/service/armory/IStrategyDispatch.java @@ -0,0 +1,24 @@ +package cn.bugstack.domain.strategy.service.armory; + +/** + * @description: 策略抽奖调度 + * @author: hdr + * @PACKAGE_NAME: cn.bugstack.domain.strategy.service.armory + * @DATE: 2024/4/8 + */ +public interface IStrategyDispatch { + /** + * 获取随机奖品id + * @param strategyId + * @return + */ + Integer getRandomAwardId(Long strategyId); + + /** + * 随机获取奖品 + * @param strategyId + * @param ruleWeightValue + * @return + */ + Integer getRandomAwardId(Long strategyId, String ruleWeightValue); +} diff --git a/xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/service/armory/StrategyArmory.java b/xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/service/armory/StrategyArmory.java index 4373380..280c2ae 100644 --- a/xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/service/armory/StrategyArmory.java +++ b/xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/service/armory/StrategyArmory.java @@ -1,7 +1,12 @@ package cn.bugstack.domain.strategy.service.armory; import cn.bugstack.domain.strategy.model.entity.StrategyAwardEntity; +import cn.bugstack.domain.strategy.model.entity.StrategyEntity; +import cn.bugstack.domain.strategy.model.entity.StrategyRuleEntity; import cn.bugstack.domain.strategy.repository.IStrategyRepository; +import cn.bugstack.types.enums.ResponseCode; +import cn.bugstack.types.exception.AppException; +import com.alibaba.fastjson.JSONObject; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -10,7 +15,6 @@ import java.math.BigDecimal; import java.math.RoundingMode; import java.security.SecureRandom; import java.util.*; -import java.util.stream.Collectors; /** * @description: @@ -20,28 +24,60 @@ import java.util.stream.Collectors; */ @Slf4j @Service -public class StrategyArmory implements IStrategyArmory { +public class StrategyArmory implements IStrategyArmory, IStrategyDispatch { @Autowired private IStrategyRepository repository; + public static void main(String[] args) { + StrategyArmory strategyArmory = new StrategyArmory(); + strategyArmory.assembleLotteryStrategy(100001L); + } + @Override - public void assembleLotteryStrategy(Long strategy) { + public boolean assembleLotteryStrategy(Long strategy) { // 1. 查询策略配置 List awardEntityList = repository.queryStrategyAwardList(strategy); + assembleLotteryStrategy(String.valueOf(strategy),awardEntityList); + + // 2. 权重策略陪住 - 使用于 rule_weight 权重规则配置 + StrategyEntity strategyEntity = repository.queryStrategyEntityByStrategyId(strategy); + + System.out.println(JSONObject.toJSONString(strategyEntity)); + if (null == strategyEntity.getRuleWeight()||null == strategyEntity) return true; + String ruleWeight = strategyEntity.getRuleWeight(); + // 2.2 查询策略规则 + StrategyRuleEntity strategyRuleEntity = repository.queryStrategyRule(strategy, ruleWeight); + if (null == strategyRuleEntity) { + throw new AppException(ResponseCode.STRATEGY_RULE_WEIGHT_IS_NULL.getCode(), ResponseCode.STRATEGY_RULE_WEIGHT_IS_NULL.getInfo()); + } + Map> ruleWeightValueMap = strategyRuleEntity.getRuleWeightValues(); + Set keys = ruleWeightValueMap.keySet(); + // 2.3 将获取到的所有 规则写入缓存 + for (String key : keys) { + List ruleWeightValues = ruleWeightValueMap.get(key); + ArrayList strategyAwardEntitiesClone = new ArrayList<>(awardEntityList); + strategyAwardEntitiesClone.removeIf(entity -> !ruleWeightValues.contains(entity.getAwardId())); + assembleLotteryStrategy(String.valueOf(strategy).concat("_").concat(key), strategyAwardEntitiesClone); + } + return true; - // 2. 获取最小概率值 - BigDecimal minAwardRate = awardEntityList.stream().map(StrategyAwardEntity::getAwardRate) + } + + private void assembleLotteryStrategy(String key,List awardEntityList) { + // 1. 获取最小概率值 + BigDecimal minAwardRate = awardEntityList.stream() + .map(StrategyAwardEntity::getAwardRate) .min(BigDecimal::compareTo) .orElse(BigDecimal.ZERO); - // 3. 获取概率值总和 + // 2. 获取概率值总和 BigDecimal totalAwardRate = awardEntityList.stream() .map(StrategyAwardEntity::getAwardRate) .reduce(BigDecimal.ZERO, BigDecimal::add); - // 4. 用 1% 0.001获取概率范围,百分位、千分位、万分位 + // 3. 用 1% 0.001获取概率范围,百分位、千分位、万分位 BigDecimal rateRange = totalAwardRate.divide(minAwardRate, 0, RoundingMode.CEILING); @@ -50,34 +86,37 @@ public class StrategyArmory implements IStrategyArmory { Integer awardId = strategyAwardEntity.getAwardId(); BigDecimal awardRate = strategyAwardEntity.getAwardRate(); - // 5. 计算出每个概率值需要存储到查找表的数量,循环填充 - - log.info("rateRange.multiply(awardRate).setScale(0, RoundingMode.CEILING).intValue()"+rateRange.multiply(awardRate).setScale(0, RoundingMode.CEILING).intValue()); + // 4. 计算出每个概率值需要存储到查找表的数量,循环填充 for (int i = 0; i < rateRange.multiply(awardRate).setScale(0, RoundingMode.CEILING).intValue(); i++) { strategyAwardSearchRateTables.add(awardId); } - // 6. 乱序 + // 5. 乱序 Collections.shuffle(strategyAwardSearchRateTables); - // 7. + // 6. 组装抽奖表 HashMap shuffleStrategyAwardSearchRateTables = new HashMap<>(); for (int i = 0; i < strategyAwardSearchRateTables.size(); i++) { shuffleStrategyAwardSearchRateTables.put(i, (Integer) strategyAwardSearchRateTables.get(i)); } - log.info(shuffleStrategyAwardSearchRateTables.size()+""); - // 8. 存储到 redis中 - repository.storeStrategyAwardSearchRateTables(strategy,shuffleStrategyAwardSearchRateTables.size(), shuffleStrategyAwardSearchRateTables); + // 7. 存储到 redis中 + repository.storeStrategyAwardSearchRateTables(key,shuffleStrategyAwardSearchRateTables.size(), shuffleStrategyAwardSearchRateTables); } - - - } @Override public Integer getRandomAwardId(Long strategyId) { int rateRange = repository.getRandomAwardId(strategyId); - return repository.getStrategyAwardAssemble(strategyId,new SecureRandom().nextInt(rateRange)); + return repository.getStrategyAwardAssemble(String.valueOf(strategyId),new SecureRandom().nextInt(rateRange)); + } + + @Override + public Integer getRandomAwardId(Long strategyId, String ruleWeightValue) { + String key = String.valueOf(strategyId).concat("_").concat(ruleWeightValue); + // 分布式部署下,不一定为当前应用做的策略装配。也就是值不一定会保存到本应用,而是分布式应用,所以需要从 Redis 中获取。 + int rateRange = repository.getRateRange(key); + // 通过生成的随机值,获取概率值奖品查找表的结果 + return repository.getStrategyAwardAssemble(key, new SecureRandom().nextInt(rateRange)); } } diff --git a/xfg-frame-archetype-lite-infrastructure/src/main/java/cn/bugstack/infrastructure/persistent/dao/IStrategyDao.java b/xfg-frame-archetype-lite-infrastructure/src/main/java/cn/bugstack/infrastructure/persistent/dao/IStrategyDao.java index 4d2cc6c..4159f8c 100644 --- a/xfg-frame-archetype-lite-infrastructure/src/main/java/cn/bugstack/infrastructure/persistent/dao/IStrategyDao.java +++ b/xfg-frame-archetype-lite-infrastructure/src/main/java/cn/bugstack/infrastructure/persistent/dao/IStrategyDao.java @@ -2,6 +2,7 @@ package cn.bugstack.infrastructure.persistent.dao; import cn.bugstack.infrastructure.persistent.po.Strategy; import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; import java.util.List; @@ -15,4 +16,10 @@ public interface IStrategyDao { List queryStrategyList(); + /** + * 通过策略id查询策略 + * @param strategyId 策略id + * @return + */ + Strategy queryStrategyByStrategyId(@Param("strategyId") Long strategyId); } diff --git a/xfg-frame-archetype-lite-infrastructure/src/main/java/cn/bugstack/infrastructure/persistent/dao/IStrategyRuleDao.java b/xfg-frame-archetype-lite-infrastructure/src/main/java/cn/bugstack/infrastructure/persistent/dao/IStrategyRuleDao.java index 5306871..d37bbe7 100644 --- a/xfg-frame-archetype-lite-infrastructure/src/main/java/cn/bugstack/infrastructure/persistent/dao/IStrategyRuleDao.java +++ b/xfg-frame-archetype-lite-infrastructure/src/main/java/cn/bugstack/infrastructure/persistent/dao/IStrategyRuleDao.java @@ -15,4 +15,10 @@ public interface IStrategyRuleDao { List queryStrategyRuleList(); + /** + * 策略规则和策略id查询 + * @param strategyRuleReq + * @return + */ + StrategyRule queryStrategyRule(StrategyRule strategyRuleReq); } diff --git a/xfg-frame-archetype-lite-infrastructure/src/main/java/cn/bugstack/infrastructure/persistent/po/Strategy.java b/xfg-frame-archetype-lite-infrastructure/src/main/java/cn/bugstack/infrastructure/persistent/po/Strategy.java index 017dd76..3f2e16e 100644 --- a/xfg-frame-archetype-lite-infrastructure/src/main/java/cn/bugstack/infrastructure/persistent/po/Strategy.java +++ b/xfg-frame-archetype-lite-infrastructure/src/main/java/cn/bugstack/infrastructure/persistent/po/Strategy.java @@ -19,6 +19,8 @@ public class Strategy { private Long strategyId; /** 抽奖策略描述 */ private String strategyDesc; + /** 抽奖规则模型 rule_weight,rule_blacklist */ + private String ruleModels; /** 创建时间 */ private Date createTime; /** 更新时间 */ diff --git a/xfg-frame-archetype-lite-infrastructure/src/main/java/cn/bugstack/infrastructure/persistent/repository/StrategyRepository.java b/xfg-frame-archetype-lite-infrastructure/src/main/java/cn/bugstack/infrastructure/persistent/repository/StrategyRepository.java index fc41464..40069d7 100644 --- a/xfg-frame-archetype-lite-infrastructure/src/main/java/cn/bugstack/infrastructure/persistent/repository/StrategyRepository.java +++ b/xfg-frame-archetype-lite-infrastructure/src/main/java/cn/bugstack/infrastructure/persistent/repository/StrategyRepository.java @@ -1,19 +1,27 @@ package cn.bugstack.infrastructure.persistent.repository; import cn.bugstack.domain.strategy.model.entity.StrategyAwardEntity; +import cn.bugstack.domain.strategy.model.entity.StrategyEntity; +import cn.bugstack.domain.strategy.model.entity.StrategyRuleEntity; import cn.bugstack.domain.strategy.repository.IStrategyRepository; import cn.bugstack.infrastructure.persistent.dao.IStrategyAwardDao; +import cn.bugstack.infrastructure.persistent.dao.IStrategyDao; +import cn.bugstack.infrastructure.persistent.dao.IStrategyRuleDao; +import cn.bugstack.infrastructure.persistent.po.Strategy; import cn.bugstack.infrastructure.persistent.po.StrategyAward; +import cn.bugstack.infrastructure.persistent.po.StrategyRule; import cn.bugstack.infrastructure.persistent.redis.IRedisService; -import cn.bugstack.infrastructure.persistent.redis.RedisService; import cn.bugstack.types.common.Constants; +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; import lombok.extern.slf4j.Slf4j; -import org.redisson.misc.Hash; +import org.apache.commons.lang3.ObjectUtils; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Repository; -import org.springframework.stereotype.Service; -import java.math.BigDecimal; +import java.lang.reflect.Type; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -35,11 +43,20 @@ public class StrategyRepository implements IStrategyRepository { @Autowired private IRedisService redisService; + + @Autowired + private IStrategyDao strategyDao; + + @Autowired + private IStrategyRuleDao strategyRuleDao; + + @Override public List queryStrategyAwardList(Long strategy) { // 1. 查询redis中是否有保存策略数据有的话直接返回 String cacheKey = Constants.RedisKey.STRATEGY_AWARD_KEY + strategy; - List strategyAwardEntities = redisService.getValue(cacheKey); + Object json = redisService.getValue(cacheKey); + List strategyAwardEntities = JSON.parseArray(json.toString(), StrategyAwardEntity.class); if (strategyAwardEntities != null && !strategyAwardEntities.isEmpty()) { return strategyAwardEntities; } @@ -57,28 +74,73 @@ public class StrategyRepository implements IStrategyRepository { }).collect(Collectors.toList()); // 2.1 保存到redis中 - redisService.setValue(cacheKey,strategyAwardEntityList); + +// redisService.setValue(cacheKey, strategyAwardEntityList); return strategyAwardEntityList; } @Override - public void storeStrategyAwardSearchRateTables(Long strategyId, Integer rateRange, HashMap shuffleStrategyAwardSearchRateTables) { + public void storeStrategyAwardSearchRateTables(String key, Integer rateRange, HashMap shuffleStrategyAwardSearchRateTables) { // 1. 存储概率值 - redisService.setValue(Constants.RedisKey.STRATEGY_RATE_RANGE_KEY + strategyId, rateRange.intValue()); + redisService.setValue(Constants.RedisKey.STRATEGY_RATE_RANGE_KEY + key, rateRange.intValue()); // 2. 存储概率查找表 - Map cacheRateTable = redisService.getMap(Constants.RedisKey.STRATEGY_RATE_TABLE_KEY + strategyId); + Map cacheRateTable = redisService.getMap(Constants.RedisKey.STRATEGY_RATE_TABLE_KEY + key); cacheRateTable.putAll(shuffleStrategyAwardSearchRateTables); } @Override public int getRandomAwardId(Long strategyId) { - return redisService.getValue(Constants.RedisKey.STRATEGY_RATE_RANGE_KEY + strategyId); + return getRateRange(String.valueOf(strategyId)); + } + + @Override + public Integer getStrategyAwardAssemble(String key, int nextInt) { + return redisService.getFromMap(Constants.RedisKey.STRATEGY_RATE_TABLE_KEY + key,nextInt); + } + + @Override + public StrategyEntity queryStrategyEntityByStrategyId(Long strategyId) { + // 1. 优先从缓存获取 + String cacheKey = Constants.RedisKey.STRATEGY_KEY + strategyId; + Map maps = redisService.getValue(cacheKey); + StrategyEntity strategyEntity = StrategyEntity.builder() + .strategyId(Long.parseLong(maps.get("strategyId").toString())) + .strategyDesc((String) maps.get("strategyDesc")) + .ruleModels((String) maps.get("ruleModels")) + .build(); + if (null != strategyEntity) return strategyEntity; + // 2. 没有数据从数据库获取 + Strategy strategy = strategyDao.queryStrategyByStrategyId(strategyId); + strategyEntity = StrategyEntity.builder() + .strategyId(strategy.getStrategyId()) + .strategyDesc(strategy.getStrategyDesc()) + .ruleModels(strategy.getRuleModels()) + .build(); + // 3. 写入缓存 + redisService.setValue(cacheKey,strategyEntity); + return strategyEntity; + } + + @Override + public StrategyRuleEntity queryStrategyRule(Long strategyId, String ruleModel) { + StrategyRule strategyRuleReq = new StrategyRule(); + strategyRuleReq.setStrategyId(strategyId); + strategyRuleReq.setRuleModel(ruleModel); + StrategyRule strategyRuleRes = strategyRuleDao.queryStrategyRule(strategyRuleReq); + return StrategyRuleEntity.builder() + .strategyId(strategyRuleRes.getStrategyId()) + .awardId(strategyRuleRes.getAwardId()) + .ruleType(strategyRuleRes.getRuleType()) + .ruleModel(strategyRuleRes.getRuleModel()) + .ruleValue(strategyRuleRes.getRuleValue()) + .ruleDesc(strategyRuleRes.getRuleDesc()) + .build(); } @Override - public Integer getStrategyAwardAssemble(Long strategyId, int nextInt) { - return redisService.getFromMap(Constants.RedisKey.STRATEGY_RATE_TABLE_KEY + strategyId,nextInt); + public int getRateRange(String key) { + return redisService.getValue(Constants.RedisKey.STRATEGY_RATE_RANGE_KEY + key); } } diff --git a/xfg-frame-archetype-lite-types/src/main/java/cn/bugstack/types/common/Constants.java b/xfg-frame-archetype-lite-types/src/main/java/cn/bugstack/types/common/Constants.java index 008bc32..0c21914 100644 --- a/xfg-frame-archetype-lite-types/src/main/java/cn/bugstack/types/common/Constants.java +++ b/xfg-frame-archetype-lite-types/src/main/java/cn/bugstack/types/common/Constants.java @@ -3,8 +3,11 @@ package cn.bugstack.types.common; public class Constants { public final static String SPLIT = ","; + public final static String COLON = ":"; + public final static String SPACE = " "; public static class RedisKey { + public static final String STRATEGY_KEY = "big_market_strategy_key_"; public static String STRATEGY_AWARD_KEY = "big_market_strategy_award_key_"; public static String STRATEGY_RATE_TABLE_KEY = "big_market_strategy_rate_table_key_"; public static String STRATEGY_RATE_RANGE_KEY = "big_market_strategy_rate_range_key_"; diff --git a/xfg-frame-archetype-lite-types/src/main/java/cn/bugstack/types/enums/ResponseCode.java b/xfg-frame-archetype-lite-types/src/main/java/cn/bugstack/types/enums/ResponseCode.java index 7460d4b..e901536 100644 --- a/xfg-frame-archetype-lite-types/src/main/java/cn/bugstack/types/enums/ResponseCode.java +++ b/xfg-frame-archetype-lite-types/src/main/java/cn/bugstack/types/enums/ResponseCode.java @@ -12,6 +12,7 @@ public enum ResponseCode { SUCCESS("0000", "成功"), UN_ERROR("0001", "未知失败"), ILLEGAL_PARAMETER("0002", "非法参数"), + STRATEGY_RULE_WEIGHT_IS_NULL("ERR_BIZ_001", "业务异常,策略规则中 rule_weight 权重规则已适用但未配置") ; private String code; -- GitLab