diff --git a/xfg-frame-archetype-lite-app/src/main/resources/mybatis/mapper/rule_tree_mapper.xml b/xfg-frame-archetype-lite-app/src/main/resources/mybatis/mapper/rule_tree_mapper.xml new file mode 100644 index 0000000000000000000000000000000000000000..282a39f6fc4c940879434bab4f7328cc2d6254ef --- /dev/null +++ b/xfg-frame-archetype-lite-app/src/main/resources/mybatis/mapper/rule_tree_mapper.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + diff --git a/xfg-frame-archetype-lite-app/src/main/resources/mybatis/mapper/rule_tree_node_line_mapper.xml b/xfg-frame-archetype-lite-app/src/main/resources/mybatis/mapper/rule_tree_node_line_mapper.xml new file mode 100644 index 0000000000000000000000000000000000000000..f05c8c6193c8bb77688dc5a8150598331007e21c --- /dev/null +++ b/xfg-frame-archetype-lite-app/src/main/resources/mybatis/mapper/rule_tree_node_line_mapper.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + diff --git a/xfg-frame-archetype-lite-app/src/main/resources/mybatis/mapper/rule_tree_node_mapper.xml b/xfg-frame-archetype-lite-app/src/main/resources/mybatis/mapper/rule_tree_node_mapper.xml new file mode 100644 index 0000000000000000000000000000000000000000..57be38764a45dd5dc11451c95b6674f1d1afde0b --- /dev/null +++ b/xfg-frame-archetype-lite-app/src/main/resources/mybatis/mapper/rule_tree_node_mapper.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + diff --git a/xfg-frame-archetype-lite-app/src/test/java/cn/bugstack/test/domain/LogicChainTest.java b/xfg-frame-archetype-lite-app/src/test/java/cn/bugstack/test/domain/LogicChainTest.java index 3c007ee9803ff62136c41caa28595cd6d1a6244f..60f330b034881f8038da9a4370338b792453b32b 100644 --- a/xfg-frame-archetype-lite-app/src/test/java/cn/bugstack/test/domain/LogicChainTest.java +++ b/xfg-frame-archetype-lite-app/src/test/java/cn/bugstack/test/domain/LogicChainTest.java @@ -42,8 +42,8 @@ public class LogicChainTest { @Test public void test_LogicChain_rule_blacklist() { ILogicChain logicChain = defaultChainFactory.openLogicChain(100003L); - Integer awardId = logicChain.logic("user001", 100003L); - log.info("测试结果:{}", awardId); +// Integer awardId = logicChain.logic("user001", 100003L); +// log.info("测试结果:{}", awardId); } @Test @@ -52,16 +52,16 @@ public class LogicChainTest { ReflectionTestUtils.setField(ruleWeightLogicChain, "userScore", 4900L); ILogicChain logicChain = defaultChainFactory.openLogicChain(100001L); - Integer awardId = logicChain.logic("xiaofuge", 100001L); - log.info("测试结果:{}", awardId); +// Integer awardId = logicChain.logic("xiaofuge", 100001L); +// log.info("测试结果:{}", awardId); } @Test public void test_LogicChain_rule_default() { ILogicChain logicChain = defaultChainFactory.openLogicChain(100001L); - Integer awardId = logicChain.logic("xiaofuge", 100001L); - log.info("测试结果:{}", awardId); +// Integer awardId = logicChain.logic("xiaofuge", 100001L); +// log.info("测试结果:{}", awardId); } } diff --git a/xfg-frame-archetype-lite-app/src/test/java/cn/bugstack/test/domain/LogicTreeTest.java b/xfg-frame-archetype-lite-app/src/test/java/cn/bugstack/test/domain/LogicTreeTest.java index a01e048b5c550a7fe791d35b76d77bc40687995a..84641c0dce7ae75b77bae4bab1a3a23d2d52c5b8 100644 --- a/xfg-frame-archetype-lite-app/src/test/java/cn/bugstack/test/domain/LogicTreeTest.java +++ b/xfg-frame-archetype-lite-app/src/test/java/cn/bugstack/test/domain/LogicTreeTest.java @@ -35,13 +35,13 @@ public class LogicTreeTest { public void test_tree_rule() { // 构建参数 RuleTreeNodeVO rule_lock = RuleTreeNodeVO.builder() - .treeId(100000001) + .treeId("100000001") .ruleKey("rule_lock") .ruleDesc("限定用户已完成N次抽奖后解锁") .ruleValue("1") .treeNodeLineVOList(new ArrayList() {{ add(RuleTreeNodeLineVO.builder() - .treeId(100000001) + .treeId("100000001") .ruleNodeFrom("rule_lock") .ruleNodeTo("rule_luck_award") .ruleLimitType(RuleLimitTypeVO.EQUAL) @@ -49,7 +49,7 @@ public class LogicTreeTest { .build()); add(RuleTreeNodeLineVO.builder() - .treeId(100000001) + .treeId("100000001") .ruleNodeFrom("rule_lock") .ruleNodeTo("rule_stock") .ruleLimitType(RuleLimitTypeVO.EQUAL) @@ -59,7 +59,7 @@ public class LogicTreeTest { .build(); RuleTreeNodeVO rule_luck_award = RuleTreeNodeVO.builder() - .treeId(100000001) + .treeId("100000001") .ruleKey("rule_luck_award") .ruleDesc("限定用户已完成N次抽奖后解锁") .ruleValue("1") @@ -67,13 +67,13 @@ public class LogicTreeTest { .build(); RuleTreeNodeVO rule_stock = RuleTreeNodeVO.builder() - .treeId(100000001) + .treeId("100000001") .ruleKey("rule_stock") .ruleDesc("库存处理规则") .ruleValue(null) .treeNodeLineVOList(new ArrayList() {{ add(RuleTreeNodeLineVO.builder() - .treeId(100000001) + .treeId("100000001") .ruleNodeFrom("rule_lock") .ruleNodeTo("rule_luck_award") .ruleLimitType(RuleLimitTypeVO.EQUAL) @@ -83,7 +83,7 @@ public class LogicTreeTest { .build(); RuleTreeVO ruleTreeVO = new RuleTreeVO(); - ruleTreeVO.setTreeId(100000001); + ruleTreeVO.setTreeId("100000001"); ruleTreeVO.setTreeName("决策树规则;增加dall-e-3画图模型"); ruleTreeVO.setTreeDesc("决策树规则;增加dall-e-3画图模型"); ruleTreeVO.setTreeRootRuleNode("rule_lock"); @@ -95,9 +95,9 @@ public class LogicTreeTest { }}); IDecisionTreeEngine treeEngine = defaultTreeFactory.openLogicTree(ruleTreeVO); - - DefaultTreeFactory.StrategyAwardData data = treeEngine.process("xiaofuge", 100001L, 100); - log.info("测试结果:{}", JSON.toJSONString(data)); +// +// DefaultTreeFactory.StrategyAwardData data = treeEngine.process("xiaofuge", 100001L, 100); +// log.info("测试结果:{}", JSON.toJSONString(data)); } diff --git a/xfg-frame-archetype-lite-app/src/test/java/cn/bugstack/test/domain/RaffleStrategyTest.java b/xfg-frame-archetype-lite-app/src/test/java/cn/bugstack/test/domain/RaffleStrategyTest.java index 65d0b14cd799e0f30d35dff66ec0edcd5073fb45..460d4989916a7a19c2e46185fbd7cd90a7e0b2ce 100644 --- a/xfg-frame-archetype-lite-app/src/test/java/cn/bugstack/test/domain/RaffleStrategyTest.java +++ b/xfg-frame-archetype-lite-app/src/test/java/cn/bugstack/test/domain/RaffleStrategyTest.java @@ -4,8 +4,7 @@ import cn.bugstack.domain.strategy.model.entity.RaffleAwardEntity; import cn.bugstack.domain.strategy.model.entity.RaffleFactorEntity; import cn.bugstack.domain.strategy.service.IRaffleStrategy; import cn.bugstack.domain.strategy.service.armory.IStrategyArmory; -import cn.bugstack.domain.strategy.service.rule.filter.impl.RuleLockLogicFilter; -import cn.bugstack.domain.strategy.service.rule.filter.impl.RuleWeightLogicFilter; +import cn.bugstack.domain.strategy.service.rule.chain.impl.RuleWeightLogicChain; import com.alibaba.fastjson.JSON; import lombok.extern.slf4j.Slf4j; import org.junit.Before; @@ -32,35 +31,23 @@ public class RaffleStrategyTest { @Resource private IRaffleStrategy raffleStrategy; @Resource - private RuleWeightLogicFilter ruleWeightLogicFilter; - @Resource - private RuleLockLogicFilter ruleLockLogicFilter; + private RuleWeightLogicChain ruleWeightLogicChain; @Before public void setUp() { // 策略装配 100001、100002、100003 log.info("测试结果:{}", strategyArmory.assembleLotteryStrategy(100001L)); - log.info("测试结果:{}", strategyArmory.assembleLotteryStrategy(100002L)); - log.info("测试结果:{}", strategyArmory.assembleLotteryStrategy(100003L)); + log.info("测试结果:{}", strategyArmory.assembleLotteryStrategy(100006L)); // 通过反射 mock 规则中的值 - ReflectionTestUtils.setField(ruleWeightLogicFilter, "userScore", 40500L); - ReflectionTestUtils.setField(ruleLockLogicFilter, "userRaffleCount", 10L); + ReflectionTestUtils.setField(ruleWeightLogicChain, "userScore", 4900L); } - @Test - public void test() { - log.info("测试结果:{}", strategyArmory.assembleLotteryStrategy(100001L)); - log.info("测试结果:{}", strategyArmory.assembleLotteryStrategy(100002L)); - log.info("测试结果:{}", strategyArmory.assembleLotteryStrategy(100003L)); - } - - @Test public void test_performRaffle() { RaffleFactorEntity raffleFactorEntity = RaffleFactorEntity.builder() .userId("xiaofuge") - .strategyId(100001L) + .strategyId(100006L) .build(); RaffleAwardEntity raffleAwardEntity = raffleStrategy.performRaffle(raffleFactorEntity); @@ -73,7 +60,7 @@ public class RaffleStrategyTest { public void test_performRaffle_blacklist() { RaffleFactorEntity raffleFactorEntity = RaffleFactorEntity.builder() .userId("user003") // 黑名单用户 user001,user002,user003 - .strategyId(100003L) + .strategyId(100001L) .build(); RaffleAwardEntity raffleAwardEntity = raffleStrategy.performRaffle(raffleFactorEntity); diff --git a/xfg-frame-archetype-lite-app/src/test/java/cn/bugstack/test/infrastructure/StrategyRepositoryTest.java b/xfg-frame-archetype-lite-app/src/test/java/cn/bugstack/test/infrastructure/StrategyRepositoryTest.java new file mode 100644 index 0000000000000000000000000000000000000000..0b805a3a2fed7a99c4f180f1550d3940fd77ce8a --- /dev/null +++ b/xfg-frame-archetype-lite-app/src/test/java/cn/bugstack/test/infrastructure/StrategyRepositoryTest.java @@ -0,0 +1,33 @@ +package cn.bugstack.test.infrastructure; + +import cn.bugstack.domain.strategy.model.valobj.RuleTreeVO; +import cn.bugstack.domain.strategy.repository.IStrategyRepository; +import com.alibaba.fastjson2.JSON; +import lombok.extern.slf4j.Slf4j; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +import javax.annotation.Resource; + +/** + * @author Fuzhengwei bugstack.cn @小傅哥 + * @description 策略仓储测试 + * @create 2024-02-03 09:43 + */ +@Slf4j +@RunWith(SpringRunner.class) +@SpringBootTest +public class StrategyRepositoryTest { + + @Resource + private IStrategyRepository strategyRepository; + + @Test + public void queryRuleTreeVOByTreeId() { + RuleTreeVO ruleTreeVO = strategyRepository.queryRuleTreeVOByTreeId("tree_lock"); + log.info("测试结果:{}", JSON.toJSONString(ruleTreeVO)); + } + +} diff --git a/xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/model/valobj/RuleTreeNodeLineVO.java b/xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/model/valobj/RuleTreeNodeLineVO.java index 8d0d69545b9191973f62d50917aed2d5cd9a4468..3d12f74bba13360d9ba86b0fe5a4234d26f08a10 100644 --- a/xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/model/valobj/RuleTreeNodeLineVO.java +++ b/xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/model/valobj/RuleTreeNodeLineVO.java @@ -18,7 +18,7 @@ import lombok.NoArgsConstructor; public class RuleTreeNodeLineVO { /** 规则树ID */ - private Integer treeId; + private String treeId; /** 规则Key节点 From */ private String ruleNodeFrom; /** 规则Key节点 To */ diff --git a/xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/model/valobj/RuleTreeNodeVO.java b/xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/model/valobj/RuleTreeNodeVO.java index 4bb259b13b1f07ef5d4b6138642ea700647039d9..cb84ffabac91094756a90bf41e03c6c49845ff1c 100644 --- a/xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/model/valobj/RuleTreeNodeVO.java +++ b/xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/model/valobj/RuleTreeNodeVO.java @@ -20,7 +20,7 @@ import java.util.List; public class RuleTreeNodeVO { /** 规则树ID */ - private Integer treeId; + private String treeId; /** 规则Key */ private String ruleKey; /** 规则描述 */ diff --git a/xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/model/valobj/RuleTreeVO.java b/xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/model/valobj/RuleTreeVO.java index 61a2312bda65a98c23cb60d9852ae1a0b1ee386f..53c963d720551cdead11ff3af173253aac09d555 100644 --- a/xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/model/valobj/RuleTreeVO.java +++ b/xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/model/valobj/RuleTreeVO.java @@ -19,7 +19,7 @@ import java.util.Map; @NoArgsConstructor public class RuleTreeVO { /** 规则树ID */ - private Integer treeId; + private String treeId; /** 规则树名称 */ private String treeName; /** 规则树描述 */ diff --git a/xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/model/valobj/StrategyAwardRuleModelVO.java b/xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/model/valobj/StrategyAwardRuleModelVO.java index 0b480b3d410a64944cdffeb2fd42dd257ebfb0d1..21c9bc597a1874c08223717db800877f1bc76577 100644 --- a/xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/model/valobj/StrategyAwardRuleModelVO.java +++ b/xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/model/valobj/StrategyAwardRuleModelVO.java @@ -1,6 +1,5 @@ package cn.bugstack.domain.strategy.model.valobj; -import cn.bugstack.domain.strategy.service.rule.filter.factory.DefaultLogicFactory; import cn.bugstack.types.common.Constants; import lombok.AllArgsConstructor; import lombok.Builder; @@ -25,26 +24,5 @@ public class StrategyAwardRuleModelVO { private String ruleModels; - /** - * 获取抽奖中规则;或者使用 lambda 表达式 - *

- * List ruleModelList = Arrays.stream(ruleModels.split(Constants.SPLIT)) - * .filter(DefaultLogicFactory.LogicModel::isCenter) - * .collect(Collectors.toList()); - * return ruleModelList; - *

- * List collect = Arrays.stream(ruleModelValues).filter(DefaultLogicFactory.LogicModel::isCenter).collect(Collectors.toList()); - */ - public String[] raffleCenterRuleModelList() { - List ruleModelList = new ArrayList<>(); - String[] ruleModeValues = ruleModels.split(Constants.SPLIT); - Arrays.stream(ruleModeValues).forEach(item-> { - if (DefaultLogicFactory.LogicModel.isCenter(item)) { - ruleModelList.add(item); - } - }); - - return ruleModelList.toArray(new String[0]); - } } 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 0119b67e722851a97258921a15a6262e6e05c349..ea077132811cf802e57dcef622c973013af7d6a4 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 @@ -3,6 +3,7 @@ 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 cn.bugstack.domain.strategy.model.valobj.RuleTreeVO; import cn.bugstack.domain.strategy.model.valobj.StrategyAwardRuleModelVO; import java.math.BigDecimal; @@ -93,4 +94,14 @@ public interface IStrategyRepository { * @return */ StrategyAwardRuleModelVO queryStrategyAwardRuleModelVO(Long strategyId, Integer awardId); + + /** + * 根据规则树ID,查询树结构信息 + * + * @param treeId 规则树ID + * @return 树结构信息 + */ + RuleTreeVO queryRuleTreeVOByTreeId(String treeId); + + } diff --git a/xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/service/annotation/LogicStrategy.java b/xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/service/annotation/LogicStrategy.java deleted file mode 100644 index 5bd418b1b969eb5095eed5060f5a46f829864893..0000000000000000000000000000000000000000 --- a/xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/service/annotation/LogicStrategy.java +++ /dev/null @@ -1,21 +0,0 @@ -package cn.bugstack.domain.strategy.service.annotation; - -import cn.bugstack.domain.strategy.service.rule.filter.factory.DefaultLogicFactory; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * @author Fuzhengwei bugstack.cn @小傅哥 - * @description 策略自定义枚举 - * @create 2023-12-31 11:29 - */ -@Target({ElementType.TYPE}) -@Retention(RetentionPolicy.RUNTIME) -public @interface LogicStrategy { - - DefaultLogicFactory.LogicModel logicMode(); - -} diff --git a/xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/service/raffle/AbstractRaffleStrategy.java b/xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/service/raffle/AbstractRaffleStrategy.java deleted file mode 100644 index 30d23185e03e92118c19f7a04432456a28afa594..0000000000000000000000000000000000000000 --- a/xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/service/raffle/AbstractRaffleStrategy.java +++ /dev/null @@ -1,113 +0,0 @@ -package cn.bugstack.domain.strategy.service.raffle; - -import cn.bugstack.domain.strategy.model.entity.RaffleAwardEntity; -import cn.bugstack.domain.strategy.model.entity.RaffleFactorEntity; -import cn.bugstack.domain.strategy.model.entity.RuleActionEntity; -import cn.bugstack.domain.strategy.model.entity.StrategyEntity; -import cn.bugstack.domain.strategy.model.valobj.RuleLogicCheckTypeVO; -import cn.bugstack.domain.strategy.model.valobj.StrategyAwardRuleModelVO; -import cn.bugstack.domain.strategy.repository.IStrategyRepository; -import cn.bugstack.domain.strategy.service.IRaffleStrategy; -import cn.bugstack.domain.strategy.service.armory.IStrategyDispatch; -import cn.bugstack.domain.strategy.service.rule.chain.ILogicChain; -import cn.bugstack.domain.strategy.service.rule.chain.factory.DefaultChainFactory; -import cn.bugstack.domain.strategy.service.rule.filter.factory.DefaultLogicFactory; -import cn.bugstack.types.enums.ResponseCode; -import cn.bugstack.types.exception.AppException; -import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; - -/** - * @description: - * @author: hdr - * @PACKAGE_NAME: cn.bugstack.domain.strategy.service.raffle - * @DATE: 2024/4/12 - */ -@Slf4j -public abstract class AbstractRaffleStrategy implements IRaffleStrategy { - - // 策略仓储服务 -> domain层像一个大厨,仓储层提供米面粮油 - protected IStrategyRepository repository; - // 策略调度服务 -> 只负责抽奖处理,通过新增接口的方式,隔离职责,不需要使用方关心或者调用抽奖的初始化 - protected IStrategyDispatch strategyDispatch; - // 抽奖的职责链 -> 抽奖的规则中,解耦出前置规则为职责链处理 - protected final DefaultChainFactory defaultChainFactory; - - public AbstractRaffleStrategy(IStrategyRepository repository, IStrategyDispatch strategyDispatch, DefaultChainFactory defaultChainFactory) { - this.repository = repository; - this.strategyDispatch = strategyDispatch; - this.defaultChainFactory = defaultChainFactory; - } - - @Override - public RaffleAwardEntity performRaffle(RaffleFactorEntity raffleFactorEntity) { - - // 1. 参数校验 - String userId = raffleFactorEntity.getUserId(); - Long strategyId = raffleFactorEntity.getStrategyId(); - if (null == strategyId || StringUtils.isBlank(userId)) { - throw new AppException(ResponseCode.ILLEGAL_PARAMETER.getCode(), ResponseCode.ILLEGAL_PARAMETER.getInfo()); - } - -// // 2. 获取抽奖职责链 -> 前置规则的责任链处理 -// ILogicChain logicChain = defaultChainFactory.openLogicChain(strategyId); -// -// // 3. 通过职责链获取,获奖id -// Integer awardId = logicChain.logic(userId, strategyId); - - - // 2. 策略查询 - StrategyEntity strategy = repository.queryStrategyEntityByStrategyId(strategyId) ; - - // 3. 抽奖前 - 规则过滤 - RuleActionEntity ruleActionEntity = this.doCheckRaffleBeforeLogic(RaffleFactorEntity.builder() - .userId(userId) - .strategyId(strategyId) - .build(), strategy.ruleModels()); - - if (RuleLogicCheckTypeVO.TAKE_OVER.getCode().equals(ruleActionEntity.getCode())) { - if (DefaultLogicFactory.LogicModel.RULE_BLACKLIST.getCode().equals(ruleActionEntity.getRuleModel())) { - // 黑名单返回固定的奖品ID - return RaffleAwardEntity.builder() - .awardId(ruleActionEntity.getData().getAwardId()) - .build(); - } else if (DefaultLogicFactory.LogicModel.RULE_WIGHT.getCode().equals(ruleActionEntity.getRuleModel())) { - // 权重根据返回的信息进行抽奖 - RuleActionEntity.RaffleBeforeEntity raffleBeforeEntity = ruleActionEntity.getData(); - String ruleWeightValueKey = raffleBeforeEntity.getRuleWeightValueKey(); - Integer awardId = strategyDispatch.getRandomAwardId(strategyId,ruleWeightValueKey); - return RaffleAwardEntity.builder() - .awardId(awardId) - .build(); - } - } - - // 4. 默认抽奖流程 - Integer awardId = strategyDispatch.getRandomAwardId(strategyId); - - // 5. 查询奖品规则「抽奖中(拿到奖品ID时,过滤规则)、抽奖后(扣减完奖品库存后过滤,抽奖中拦截和无库存则走兜底)」 - StrategyAwardRuleModelVO strategyAwardRuleModelVO = repository.queryStrategyAwardRuleModelVO(strategyId, awardId); - - // 6. 抽奖中 - 规则过滤 - RuleActionEntity ruleActionCenterEntity = this.doCheckRaffleCenterLogic(RaffleFactorEntity.builder() - .userId(userId) - .strategyId(strategyId) - .awardId(awardId) - .build(), strategyAwardRuleModelVO.raffleCenterRuleModelList()); - - if (RuleLogicCheckTypeVO.TAKE_OVER.getCode().equals(ruleActionCenterEntity.getCode())){ - log.info("【临时日志】中奖中规则拦截,通过抽奖后规则 rule_luck_award 走兜底奖励。"); - return RaffleAwardEntity.builder() - .awardDesc("中奖中规则拦截,通过抽奖后规则 rule_luck_award 走兜底奖励。") - .build(); - } - - return RaffleAwardEntity.builder() - .awardId(awardId) - .build(); - } - - protected abstract RuleActionEntity doCheckRaffleCenterLogic(RaffleFactorEntity raffleFactorEntity, String... logics); - - protected abstract RuleActionEntity doCheckRaffleBeforeLogic(RaffleFactorEntity factorEntity, String... logics); -} diff --git a/xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/service/raffle/DefaultRaffleStrategy.java b/xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/service/raffle/DefaultRaffleStrategy.java index 7f7fd194c053d1b283976747c2c5ed5c41ff5e8a..28f4024f330e593c15703c05ce07eddac9e53c31 100644 --- a/xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/service/raffle/DefaultRaffleStrategy.java +++ b/xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/service/raffle/DefaultRaffleStrategy.java @@ -4,11 +4,15 @@ import cn.bugstack.domain.strategy.model.entity.RaffleFactorEntity; import cn.bugstack.domain.strategy.model.entity.RuleActionEntity; import cn.bugstack.domain.strategy.model.entity.RuleMatterEntity; import cn.bugstack.domain.strategy.model.valobj.RuleLogicCheckTypeVO; +import cn.bugstack.domain.strategy.model.valobj.RuleTreeVO; +import cn.bugstack.domain.strategy.model.valobj.StrategyAwardRuleModelVO; import cn.bugstack.domain.strategy.repository.IStrategyRepository; import cn.bugstack.domain.strategy.service.armory.IStrategyDispatch; -import cn.bugstack.domain.strategy.service.rule.filter.ILogicFilter; +import cn.bugstack.domain.strategy.service.rule.AbstractRaffleStrategy; +import cn.bugstack.domain.strategy.service.rule.chain.ILogicChain; import cn.bugstack.domain.strategy.service.rule.chain.factory.DefaultChainFactory; -import cn.bugstack.domain.strategy.service.rule.filter.factory.DefaultLogicFactory; +import cn.bugstack.domain.strategy.service.rule.tree.factory.DefaultTreeFactory; +import cn.bugstack.domain.strategy.service.rule.tree.factory.engine.IDecisionTreeEngine; import com.alibaba.fastjson.JSON; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; @@ -28,91 +32,32 @@ import java.util.stream.Collectors; */ @Slf4j @Service -public class DefaultRaffleStrategy extends AbstractRaffleStrategy{ +public class DefaultRaffleStrategy extends AbstractRaffleStrategy { - @Resource - private DefaultLogicFactory logicFactory; - - public DefaultRaffleStrategy(IStrategyRepository repository, IStrategyDispatch strategyDispatch, DefaultChainFactory defaultChainFactory) { - super(repository, strategyDispatch, defaultChainFactory); + public DefaultRaffleStrategy(IStrategyRepository repository, IStrategyDispatch strategyDispatch, DefaultChainFactory defaultChainFactory, DefaultTreeFactory defaultTreeFactory) { + super(repository, strategyDispatch, defaultChainFactory, defaultTreeFactory); } @Override - protected RuleActionEntity doCheckRaffleCenterLogic(RaffleFactorEntity raffleFactorEntity, String... logics) { - if (logics == null || 0 == logics.length) return RuleActionEntity.builder() - .code(RuleLogicCheckTypeVO.ALLOW.getCode()) - .info(RuleLogicCheckTypeVO.ALLOW.getInfo()) - .build(); - - Map> logicFilterGroup = logicFactory.openLogicFilter(); - - RuleActionEntity ruleActionEntity = null; - for (String ruleModel : logics) { - ILogicFilter logicFilter = logicFilterGroup.get(ruleModel); - RuleMatterEntity ruleMatterEntity = new RuleMatterEntity(); - ruleMatterEntity.setUserId(raffleFactorEntity.getUserId()); - ruleMatterEntity.setAwardId(raffleFactorEntity.getAwardId()); - ruleMatterEntity.setStrategyId(raffleFactorEntity.getStrategyId()); - ruleMatterEntity.setRuleModel(ruleModel); - ruleActionEntity = logicFilter.filter(ruleMatterEntity); - // 非放行结果则顺序过滤 - log.info("抽奖中规则过滤 userId: {} ruleModel: {} code: {} info: {}", raffleFactorEntity.getUserId(), ruleModel, ruleActionEntity.getCode(), ruleActionEntity.getInfo()); - if (!RuleLogicCheckTypeVO.ALLOW.getCode().equals(ruleActionEntity.getCode())) return ruleActionEntity; - } - return ruleActionEntity; + public DefaultChainFactory.StrategyAwardVO raffleLogicChain(String userId, Long strategyId) { + ILogicChain logicChain = defaultChainFactory.openLogicChain(strategyId); + return logicChain.logic(userId, strategyId); } @Override - protected RuleActionEntity doCheckRaffleBeforeLogic(RaffleFactorEntity raffleFactorEntity, String... logics) { - - if (logics == null || 0 == logics.length) return RuleActionEntity.builder() - .code(RuleLogicCheckTypeVO.ALLOW.getCode()) - .info(RuleLogicCheckTypeVO.ALLOW.getInfo()) - .build(); - log.info("raffleFactorEntity:{},logics:{}", JSON.toJSONString(raffleFactorEntity),logics); - Map> logicFilterGroup = logicFactory.openLogicFilter(); - - // 黑名单规则优先过滤 - String ruleBackList = Arrays.stream(logics) - .filter(str-> str.contains(DefaultLogicFactory.LogicModel.RULE_BLACKLIST.getCode())) - .findFirst() - .orElse(null); - - if (StringUtils.isNotBlank(ruleBackList)) { - ILogicFilter logicFilter = logicFilterGroup.get(DefaultLogicFactory.LogicModel.RULE_BLACKLIST.getCode()); - RuleMatterEntity ruleMatterEntity = new RuleMatterEntity(); - ruleMatterEntity.setUserId(raffleFactorEntity.getUserId()); - ruleMatterEntity.setAwardId(ruleMatterEntity.getAwardId()); - ruleMatterEntity.setStrategyId(raffleFactorEntity.getStrategyId()); - ruleMatterEntity.setRuleModel(DefaultLogicFactory.LogicModel.RULE_BLACKLIST.getCode()); - RuleActionEntity ruleActionEntity = logicFilter.filter(ruleMatterEntity); - if (!RuleLogicCheckTypeVO.ALLOW.getCode().equals(ruleActionEntity.getCode())) { - return ruleActionEntity; - } + public DefaultTreeFactory.StrategyAwardVO raffleLogicTree(String userId, Long strategyId, Integer awardId) { + StrategyAwardRuleModelVO strategyAwardRuleModelVO = repository.queryStrategyAwardRuleModelVO(strategyId, awardId); + if (null == strategyAwardRuleModelVO) { + return DefaultTreeFactory.StrategyAwardVO.builder() + .awardId(awardId) + .build(); } - - // 顺序过滤剩余规则 - List ruleList = Arrays.stream(logics) - .filter(str-> !str.contains(DefaultLogicFactory.LogicModel.RULE_BLACKLIST.getCode())) - .collect(Collectors.toList()); - - RuleActionEntity ruleActionEntity = null; - for (String ruleModel : ruleList) { - ILogicFilter logicFilter = logicFilterGroup.get(ruleModel); - RuleMatterEntity ruleMatterEntity = new RuleMatterEntity(); - ruleMatterEntity.setUserId(raffleFactorEntity.getUserId()); - // todo 数据不对 - ruleMatterEntity.setAwardId(ruleMatterEntity.getAwardId()); - ruleMatterEntity.setStrategyId(raffleFactorEntity.getStrategyId()); - ruleMatterEntity.setRuleModel(ruleModel); - ruleActionEntity = logicFilter.filter(ruleMatterEntity); - log.info("ruleActionEntity:{}",JSON.toJSONString(ruleActionEntity)); - log.info("抽奖前规则过滤 userId: {} ruleModel: {} code: {} info: {}", raffleFactorEntity.getUserId(), ruleModel, ruleActionEntity.getCode(), ruleActionEntity.getInfo()); - if (!RuleLogicCheckTypeVO.ALLOW.getCode().equals(ruleActionEntity.getCode())) { - return ruleActionEntity; - } + RuleTreeVO ruleTreeVO = repository.queryRuleTreeVOByTreeId(strategyAwardRuleModelVO.getRuleModels()); + if (null == ruleTreeVO) { + throw new RuntimeException("存在抽奖策略配置的规则模型 Key,未在库表 rule_tree、rule_tree_node、rule_tree_line 配置对应的规则树信息 \" + strategyAwardRuleModelVO.getRuleModels()"); } + IDecisionTreeEngine treeEngine = defaultTreeFactory.openLogicTree(ruleTreeVO); + return treeEngine.process(userId, strategyId, awardId); - return ruleActionEntity; } } diff --git a/xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/AbstractRaffleStrategy.java b/xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/AbstractRaffleStrategy.java new file mode 100644 index 0000000000000000000000000000000000000000..7be88a42364ef6625e39f3ed776ccf3dad5a81f8 --- /dev/null +++ b/xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/AbstractRaffleStrategy.java @@ -0,0 +1,87 @@ +package cn.bugstack.domain.strategy.service.rule; + +import cn.bugstack.domain.strategy.model.entity.RaffleAwardEntity; +import cn.bugstack.domain.strategy.model.entity.RaffleFactorEntity; +import cn.bugstack.domain.strategy.repository.IStrategyRepository; +import cn.bugstack.domain.strategy.service.IRaffleStrategy; +import cn.bugstack.domain.strategy.service.armory.IStrategyDispatch; +import cn.bugstack.domain.strategy.service.rule.chain.factory.DefaultChainFactory; +import cn.bugstack.domain.strategy.service.rule.tree.factory.DefaultTreeFactory; +import cn.bugstack.types.enums.ResponseCode; +import cn.bugstack.types.exception.AppException; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; + +/** + * @description: 抽奖策略抽象类,定义抽奖的标准流程 + * @author: hdr + * @PACKAGE_NAME: cn.bugstack.domain.strategy.service.rule + * @DATE: 2024/4/23 + */ +@Slf4j +public abstract class AbstractRaffleStrategy implements IRaffleStrategy { + // 策略仓储服务 -> domain层像一个大厨,仓储层提供米面粮油 + protected IStrategyRepository repository; + // 策略调度服务 -> 只负责抽奖处理,通过新增接口的方式,隔离职责,不需要使用方关心或者调用抽奖的初始化 + protected IStrategyDispatch strategyDispatch; + // 抽奖的责任链 -> 从抽奖的规则中,解耦出前置规则为责任链处理 + protected final DefaultChainFactory defaultChainFactory; + // 抽奖的决策树 -> 负责抽奖中到抽奖后的规则过滤,如抽奖到A奖品ID,之后要做次数的判断和库存的扣减等。 + protected final DefaultTreeFactory defaultTreeFactory; + + public AbstractRaffleStrategy(IStrategyRepository repository, IStrategyDispatch strategyDispatch, DefaultChainFactory defaultChainFactory, DefaultTreeFactory defaultTreeFactory) { + this.repository = repository; + this.strategyDispatch = strategyDispatch; + this.defaultChainFactory = defaultChainFactory; + this.defaultTreeFactory = defaultTreeFactory; + } + + @Override + public RaffleAwardEntity performRaffle(RaffleFactorEntity raffleFactorEntity) { + // 1. 参数校验 + String userId = raffleFactorEntity.getUserId(); + Long strategyId = raffleFactorEntity.getStrategyId(); + if (null == strategyId || StringUtils.isBlank(userId)) { + throw new AppException(ResponseCode.ILLEGAL_PARAMETER.getCode(), ResponseCode.ILLEGAL_PARAMETER.getInfo()); + } + + // 2. 责任链抽奖计算【这步拿到的是初步的抽奖ID,之后需要根据ID处理抽奖】注意;黑名单、权重等非默认抽奖的直接返回抽奖结果 + DefaultChainFactory.StrategyAwardVO chainStrategyAwardVO = raffleLogicChain(userId, strategyId); + log.info("抽奖策略计算-责任链 {} {} {} {}", userId, strategyId, chainStrategyAwardVO.getAwardId(), chainStrategyAwardVO.getLogicModel()); + if (!DefaultChainFactory.LogicModel.RULE_DEFAULT.getCode().equals(chainStrategyAwardVO.getLogicModel())) { + return RaffleAwardEntity.builder() + .awardId(chainStrategyAwardVO.getAwardId()) + .build(); + } + + // 3. 规则树抽奖过滤【奖品ID,会根据抽奖次数判断、库存判断、兜底兜里返回最终的可获得奖品信息】 + DefaultTreeFactory.StrategyAwardVO treeStrategyAwardVO = raffleLogicTree(userId, strategyId, chainStrategyAwardVO.getAwardId()); + log.info("抽奖策略计算-规则树 {} {} {} {}", userId, strategyId, treeStrategyAwardVO.getAwardId(), treeStrategyAwardVO.getAwardRuleValue()); + + // 4. 返回抽奖结果 + return RaffleAwardEntity.builder() + .awardId(treeStrategyAwardVO.getAwardId()) + .awardConfig(treeStrategyAwardVO.getAwardRuleValue()) + .build(); + } + + /** + * 抽奖计算,责任链抽象方法 + * + * @param userId 用户ID + * @param strategyId 策略ID + * @return 奖品ID + */ + public abstract DefaultChainFactory.StrategyAwardVO raffleLogicChain(String userId, Long strategyId); + + /** + * 抽奖结果过滤,决策树抽象方法 + * + * @param userId 用户ID + * @param strategyId 策略ID + * @param awardId 奖品ID + * @return 过滤结果【奖品ID,会根据抽奖次数判断、库存判断、兜底兜里返回最终的可获得奖品信息】 + */ + public abstract DefaultTreeFactory.StrategyAwardVO raffleLogicTree(String userId, Long strategyId, Integer awardId); + +} diff --git a/xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/chain/ILogicChain.java b/xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/chain/ILogicChain.java index a9761bb6543c781814b654cd334cd2d112bc6df8..933a8d575fdc713784141a94df325999a3db9da1 100644 --- a/xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/chain/ILogicChain.java +++ b/xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/chain/ILogicChain.java @@ -1,5 +1,7 @@ package cn.bugstack.domain.strategy.service.rule.chain; +import cn.bugstack.domain.strategy.service.rule.chain.factory.DefaultChainFactory; + /** * @description: 抽奖策略规则责任链接口 * @author: hdr @@ -15,5 +17,5 @@ public interface ILogicChain extends ILogicChainArmory { * @param strategyId 策略id * @return 奖品id */ - Integer logic(String userId, Long strategyId); + DefaultChainFactory.StrategyAwardVO logic(String userId, Long strategyId); } diff --git a/xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/chain/factory/DefaultChainFactory.java b/xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/chain/factory/DefaultChainFactory.java index 9e638e0284dc06a26e2c2dd73198fced8382b62a..8d9873ce3ab9964505e7e66c863d8984c02fb18f 100644 --- a/xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/chain/factory/DefaultChainFactory.java +++ b/xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/chain/factory/DefaultChainFactory.java @@ -3,6 +3,7 @@ package cn.bugstack.domain.strategy.service.rule.chain.factory; import cn.bugstack.domain.strategy.model.entity.StrategyEntity; import cn.bugstack.domain.strategy.repository.IStrategyRepository; import cn.bugstack.domain.strategy.service.rule.chain.ILogicChain; +import lombok.*; import org.springframework.stereotype.Service; import java.util.Map; @@ -47,4 +48,29 @@ public class DefaultChainFactory { return logicChain; } + @Data + @Builder + @AllArgsConstructor + @NoArgsConstructor + public static class StrategyAwardVO { + /** 抽奖奖品ID - 内部流转使用 */ + private Integer awardId; + /** */ + private String logicModel; + } + + @Getter + @AllArgsConstructor + public enum LogicModel { + + RULE_DEFAULT("rule_default", "默认抽奖"), + RULE_BLACKLIST("rule_blacklist", "黑名单抽奖"), + RULE_WEIGHT("rule_weight", "权重规则"), + ; + + private final String code; + private final String info; + + } + } diff --git a/xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/chain/impl/BackListLogicChain.java b/xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/chain/impl/BackListLogicChain.java index 65be467878d6e83e423249bdb8100c0fe7006465..d36b01660e6f662e5ee08709096f875572714e92 100644 --- a/xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/chain/impl/BackListLogicChain.java +++ b/xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/chain/impl/BackListLogicChain.java @@ -2,6 +2,7 @@ package cn.bugstack.domain.strategy.service.rule.chain.impl; import cn.bugstack.domain.strategy.repository.IStrategyRepository; import cn.bugstack.domain.strategy.service.rule.chain.AbstractLogicChain; +import cn.bugstack.domain.strategy.service.rule.chain.factory.DefaultChainFactory; import cn.bugstack.types.common.Constants; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; @@ -22,7 +23,7 @@ public class BackListLogicChain extends AbstractLogicChain { private IStrategyRepository repository; @Override - public Integer logic(String userId, Long strategyId) { + public DefaultChainFactory.StrategyAwardVO logic(String userId, Long strategyId) { log.info("抽奖责任链-黑名单开始 userId: {} strategyId: {} ruleModel: {}", userId, strategyId, ruleModel()); // 查询规则值配置 @@ -36,7 +37,10 @@ public class BackListLogicChain extends AbstractLogicChain { for (String userBlackId : userBlackIds) { if (userId.equals(userBlackId)) { log.info("抽奖责任链-黑名单接管 userId: {} strategyId: {} ruleModel: {} awardId: {}", userId, strategyId, ruleModel(), awardId); - return awardId; + return DefaultChainFactory.StrategyAwardVO.builder() + .awardId(awardId) + .logicModel(ruleModel()) + .build(); } } @@ -48,7 +52,7 @@ public class BackListLogicChain extends AbstractLogicChain { @Override protected String ruleModel() { - return "rule_blacklist"; + return DefaultChainFactory.LogicModel.RULE_BLACKLIST.getCode(); } } diff --git a/xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/chain/impl/DefaultLogicChain.java b/xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/chain/impl/DefaultLogicChain.java index 595e30cf8b96b52fbd41d118a56e3fdb9863d981..139e869c5eba1d5a10d26810f3b1bc195b19b46e 100644 --- a/xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/chain/impl/DefaultLogicChain.java +++ b/xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/chain/impl/DefaultLogicChain.java @@ -2,6 +2,7 @@ package cn.bugstack.domain.strategy.service.rule.chain.impl; import cn.bugstack.domain.strategy.service.armory.IStrategyDispatch; import cn.bugstack.domain.strategy.service.rule.chain.AbstractLogicChain; +import cn.bugstack.domain.strategy.service.rule.chain.factory.DefaultChainFactory; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; @@ -22,13 +23,16 @@ public class DefaultLogicChain extends AbstractLogicChain { @Override protected String ruleModel() { - return "default"; + return DefaultChainFactory.LogicModel.RULE_DEFAULT.getCode(); } @Override - public Integer logic(String userId, Long strategyId) { + public DefaultChainFactory.StrategyAwardVO logic(String userId, Long strategyId) { Integer awardId = strategyDispatch.getRandomAwardId(strategyId); log.info("抽奖责任链-默认处理 userId: {} strategyId: {} ruleModel: {} awardId: {}", userId, strategyId, ruleModel(), awardId); - return awardId; + return DefaultChainFactory.StrategyAwardVO.builder() + .awardId(awardId) + .logicModel(ruleModel()) + .build(); } } diff --git a/xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/chain/impl/RuleWeightLogicChain.java b/xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/chain/impl/RuleWeightLogicChain.java index ee0b8bce1a8dc93d26f1c05f8bf012fe93744109..367a3af30c7993dfda5797f513f9ad269bfc5ff6 100644 --- a/xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/chain/impl/RuleWeightLogicChain.java +++ b/xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/chain/impl/RuleWeightLogicChain.java @@ -3,6 +3,7 @@ package cn.bugstack.domain.strategy.service.rule.chain.impl; import cn.bugstack.domain.strategy.repository.IStrategyRepository; import cn.bugstack.domain.strategy.service.armory.IStrategyDispatch; import cn.bugstack.domain.strategy.service.rule.chain.AbstractLogicChain; +import cn.bugstack.domain.strategy.service.rule.chain.factory.DefaultChainFactory; import cn.bugstack.types.common.Constants; import com.alibaba.fastjson.JSON; import lombok.extern.slf4j.Slf4j; @@ -40,7 +41,7 @@ public class RuleWeightLogicChain extends AbstractLogicChain { * 2. 解析数据格式;判断哪个范围符合用户的特定抽奖范围 */ @Override - public Integer logic(String userId, Long strategyId) { + public DefaultChainFactory.StrategyAwardVO logic(String userId, Long strategyId) { log.info("抽奖责任链-权重开始 userId: {} strategyId: {} ruleModel: {}", userId, strategyId, ruleModel()); String ruleValue = repository.queryStrategyRuleValue(strategyId, ruleModel()); @@ -66,7 +67,10 @@ public class RuleWeightLogicChain extends AbstractLogicChain { if (null != nextValue) { Integer awardId = strategyDispatch.getRandomAwardId(strategyId, analyticalValueGroup.get(nextValue)); log.info("抽奖责任链-权重接管 userId: {} strategyId: {} ruleModel: {} awardId: {}", userId, strategyId, ruleModel(), awardId); - return awardId; + return DefaultChainFactory.StrategyAwardVO.builder() + .awardId(awardId) + .logicModel(ruleModel()) + .build(); } // 5. 过滤其他责任链 diff --git a/xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/filter/ILogicFilter.java b/xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/filter/ILogicFilter.java deleted file mode 100644 index 715ddae7159fa9464f2cede040978306656b98c3..0000000000000000000000000000000000000000 --- a/xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/filter/ILogicFilter.java +++ /dev/null @@ -1,16 +0,0 @@ -package cn.bugstack.domain.strategy.service.rule.filter; - -import cn.bugstack.domain.strategy.model.entity.RuleActionEntity; -import cn.bugstack.domain.strategy.model.entity.RuleMatterEntity; - -/** - * @description: 抽奖规则过滤接口 - * @author: hdr - * @PACKAGE_NAME: cn.bugstack.domain.strategy.service.rule - * @DATE: 2024/4/12 - */ -public interface ILogicFilter { - - RuleActionEntity filter(RuleMatterEntity ruleMatterEntity); - -} diff --git a/xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/filter/factory/DefaultLogicFactory.java b/xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/filter/factory/DefaultLogicFactory.java deleted file mode 100644 index 9e537fbf6d939a63c7c912f63777b739e37adb73..0000000000000000000000000000000000000000 --- a/xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/filter/factory/DefaultLogicFactory.java +++ /dev/null @@ -1,62 +0,0 @@ -package cn.bugstack.domain.strategy.service.rule.filter.factory; - -import cn.bugstack.domain.strategy.model.entity.RuleActionEntity; -import cn.bugstack.domain.strategy.service.annotation.LogicStrategy; -import cn.bugstack.domain.strategy.service.rule.filter.ILogicFilter; -import lombok.AllArgsConstructor; -import lombok.Getter; -import org.springframework.core.annotation.AnnotationUtils; -import org.springframework.stereotype.Service; - -import java.util.List; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - -/** - * @description: 规则工厂 - * @author: hdr - * @PACKAGE_NAME: cn.bugstack.domain.strategy.service.rule.filter.factory - * @DATE: 2024/4/12 - */ -@Service -public class DefaultLogicFactory { - - public Map> logicFilterMap = new ConcurrentHashMap<>(); - - public DefaultLogicFactory(List> logicFilters) { - logicFilters.forEach(logic -> { - LogicStrategy strategy = AnnotationUtils.findAnnotation(logic.getClass(), LogicStrategy.class); - if (null != strategy) { - logicFilterMap.put(strategy.logicMode().getCode(), logic); - } - }); - } - - public Map> openLogicFilter() { - return (Map>) (Map) logicFilterMap; - } - - @Getter - @AllArgsConstructor - public enum LogicModel { - - RULE_WIGHT("rule_weight", "【抽奖前规则】根据抽奖权重返回可抽奖范围KEY", "before"), - RULE_BLACKLIST("rule_blacklist", "【抽奖前规则】黑名单规则过滤,命中黑名单则直接返回", "before"), - RULE_LOCK("rule_lock", "【抽奖中规则】抽奖n次后,对应奖品可解锁抽奖", "center"), - RULE_LUCK_AWARD("rule_luck_award", "【抽奖后规则】抽奖n次后,对应奖品可解锁抽奖", "after"), - ; - - private final String code; - private final String info; - private final String type; - - public static boolean isCenter(String code){ - return "center".equals(LogicModel.valueOf(code.toUpperCase()).type); - } - - public static boolean isAfter(String code){ - return "after".equals(LogicModel.valueOf(code.toUpperCase()).type); - } - } - -} diff --git a/xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/filter/impl/RuleBackListLogicFilter.java b/xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/filter/impl/RuleBackListLogicFilter.java deleted file mode 100644 index 44cfb778b58c1ee9057303d1b10c5c2a22859589..0000000000000000000000000000000000000000 --- a/xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/filter/impl/RuleBackListLogicFilter.java +++ /dev/null @@ -1,65 +0,0 @@ -package cn.bugstack.domain.strategy.service.rule.filter.impl; - -import cn.bugstack.domain.strategy.model.entity.RuleActionEntity; -import cn.bugstack.domain.strategy.model.entity.RuleMatterEntity; -import cn.bugstack.domain.strategy.model.valobj.RuleLogicCheckTypeVO; -import cn.bugstack.domain.strategy.repository.IStrategyRepository; -import cn.bugstack.domain.strategy.service.annotation.LogicStrategy; -import cn.bugstack.domain.strategy.service.rule.filter.ILogicFilter; -import cn.bugstack.domain.strategy.service.rule.filter.factory.DefaultLogicFactory; -import cn.bugstack.types.common.Constants; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Component; - -import javax.annotation.Resource; - -/** - * @description: [抽奖前规则]黑名单用户过滤规则 - * @author: hdr - * @PACKAGE_NAME: cn.bugstack.domain.strategy.service.rule.filter.impl - * @DATE: 2024/4/12 - */ -@Slf4j -@Component -@LogicStrategy(logicMode = DefaultLogicFactory.LogicModel.RULE_BLACKLIST) -public class RuleBackListLogicFilter implements ILogicFilter { - - @Resource - private IStrategyRepository repository; - - @Override - public RuleActionEntity filter(RuleMatterEntity ruleMatterEntity) { - - log.info("规则过滤-黑名单 userId:{} strategyId:{} ruleModel:{}", ruleMatterEntity.getUserId(), ruleMatterEntity.getStrategyId(), ruleMatterEntity.getRuleModel()); - - String userId = ruleMatterEntity.getUserId(); - - // 100:user001,user002,user003 - // 查询规则值配置 - String ruleValue = repository.queryStrategyRuleValue(ruleMatterEntity.getStrategyId(), ruleMatterEntity.getAwardId(), ruleMatterEntity.getRuleModel()); - String[] splitRuleValue = ruleValue.split(Constants.COLON); - // - Integer awardId = Integer.parseInt(splitRuleValue[0]); - - // 过滤其他规则 - String[] userBlackIds = splitRuleValue[1].split(Constants.SPLIT); - for (String userBlackId : userBlackIds) { - if (userId.equals(userBlackId)) { - return RuleActionEntity.builder() - .ruleModel(DefaultLogicFactory.LogicModel.RULE_BLACKLIST.getCode()) - .data(RuleActionEntity.RaffleBeforeEntity.builder() - .strategyId(ruleMatterEntity.getStrategyId()) - .awardId(awardId) - .build()) - .code(RuleLogicCheckTypeVO.TAKE_OVER.getCode()) - .info(RuleLogicCheckTypeVO.TAKE_OVER.getInfo()) - .build(); - } - } - - return RuleActionEntity.builder() - .code(RuleLogicCheckTypeVO.ALLOW.getCode()) - .info(RuleLogicCheckTypeVO.ALLOW.getInfo()) - .build(); - } -} diff --git a/xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/filter/impl/RuleLockLogicFilter.java b/xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/filter/impl/RuleLockLogicFilter.java deleted file mode 100644 index 58014f181f4dcc079a73a3b219766cd130a22bb6..0000000000000000000000000000000000000000 --- a/xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/filter/impl/RuleLockLogicFilter.java +++ /dev/null @@ -1,54 +0,0 @@ -package cn.bugstack.domain.strategy.service.rule.filter.impl; - -import cn.bugstack.domain.strategy.model.entity.RuleActionEntity; -import cn.bugstack.domain.strategy.model.entity.RuleMatterEntity; -import cn.bugstack.domain.strategy.model.valobj.RuleLogicCheckTypeVO; -import cn.bugstack.domain.strategy.repository.IStrategyRepository; -import cn.bugstack.domain.strategy.service.annotation.LogicStrategy; -import cn.bugstack.domain.strategy.service.rule.filter.ILogicFilter; -import cn.bugstack.domain.strategy.service.rule.filter.factory.DefaultLogicFactory; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Component; - -import javax.annotation.Resource; - -/** - * @description: 用户抽奖n次后,对应奖品可解锁抽奖 - * @author: hdr - * @PACKAGE_NAME: cn.bugstack.domain.strategy.service.raffle - * @DATE: 2024/4/16 - */ -@Slf4j -@Component -@LogicStrategy(logicMode = DefaultLogicFactory.LogicModel.RULE_LOCK) -public class RuleLockLogicFilter implements ILogicFilter { - - @Resource - private IStrategyRepository repository; - - // 测试数据 - private Long userRaffleCount = 0L; - - @Override - public RuleActionEntity filter(RuleMatterEntity ruleMatterEntity) { - log.info("规则过滤-次数锁 userId:{} strategyId:{} ruleModel:{}", ruleMatterEntity.getUserId(), ruleMatterEntity.getStrategyId(), ruleMatterEntity.getRuleModel()); - - // 查询规则值配置;当前奖品ID,抽奖中规则对应的校验值。如;1、2、6 - String ruleValue = repository.queryStrategyRuleValue(ruleMatterEntity.getStrategyId(), ruleMatterEntity.getAwardId(), ruleMatterEntity.getRuleModel()); - long raffleCount = Long.parseLong(ruleValue); - - // 用户抽奖次数大于规则限定值,规则放行 - if (userRaffleCount>= raffleCount) { - return RuleActionEntity.builder() - .code(RuleLogicCheckTypeVO.ALLOW.getCode()) - .info(RuleLogicCheckTypeVO.ALLOW.getInfo()) - .build(); - } - - // 用户抽奖次数小于规则限定值,规则拦截 - return RuleActionEntity.builder() - .code(RuleLogicCheckTypeVO.TAKE_OVER.getCode()) - .info(RuleLogicCheckTypeVO.TAKE_OVER.getInfo()) - .build(); - } -} diff --git a/xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/filter/impl/RuleWeightLogicFilter.java b/xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/filter/impl/RuleWeightLogicFilter.java deleted file mode 100644 index 25e36db5d05b4bd492f7a903373be72c453e9046..0000000000000000000000000000000000000000 --- a/xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/filter/impl/RuleWeightLogicFilter.java +++ /dev/null @@ -1,102 +0,0 @@ -package cn.bugstack.domain.strategy.service.rule.filter.impl; - -import cn.bugstack.domain.strategy.model.entity.RuleActionEntity; -import cn.bugstack.domain.strategy.model.entity.RuleMatterEntity; -import cn.bugstack.domain.strategy.model.valobj.RuleLogicCheckTypeVO; -import cn.bugstack.domain.strategy.repository.IStrategyRepository; -import cn.bugstack.domain.strategy.service.annotation.LogicStrategy; -import cn.bugstack.domain.strategy.service.rule.filter.ILogicFilter; -import cn.bugstack.domain.strategy.service.rule.filter.factory.DefaultLogicFactory; -import cn.bugstack.types.common.Constants; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Component; - -import javax.annotation.Resource; -import java.util.*; - -/** - * @description: [抽奖前规则] 根据抽奖鉴权重返可抽奖范围key - * @author: hdr - * @PACKAGE_NAME: cn.bugstack.domain.strategy.service.rule.filter.impl - * @DATE: 2024/4/12 - */ -@Slf4j -@Component -@LogicStrategy(logicMode = DefaultLogicFactory.LogicModel.RULE_WIGHT) -public class RuleWeightLogicFilter implements ILogicFilter { - - @Resource - private IStrategyRepository repository; - - public Long userScore = 4500L; - - /** - * 1. 权重规则格式;4000:102,103,104,105 5000:102,103,104,105,106,107 6000:102,103,104,105,106,107,108,109 - * 2. 解析数据格式;判断哪个范围符合用户的特定抽奖范围 - * @param ruleMatterEntity - * @return - */ - @Override - public RuleActionEntity filter(RuleMatterEntity ruleMatterEntity) { - log.info("规则过滤-权重范围 userId:{} strategyId:{} ruleModel:{}", ruleMatterEntity.getUserId(), ruleMatterEntity.getStrategyId(), ruleMatterEntity.getRuleModel()); - - String userId = ruleMatterEntity.getUserId(); - Long strategyId = ruleMatterEntity.getStrategyId(); - String ruleValue = repository.queryStrategyRuleValue(ruleMatterEntity.getStrategyId(), ruleMatterEntity.getAwardId(), ruleMatterEntity.getRuleModel()); - - // 1. 根据用户ID查询用户抽奖消耗的积分值,本章节我们先写死为固定的值。后续需要从数据库中查询。 - Map analyticalValueGroup = getAnalyticalValue(ruleValue); - if (null == analyticalValueGroup || analyticalValueGroup.isEmpty()) { - return RuleActionEntity.builder() - .code(RuleLogicCheckTypeVO.ALLOW.getCode()) - .info(RuleLogicCheckTypeVO.ALLOW.getInfo()) - .build(); - } - - // 2. 转换Keys值,并默认排序 - List analyticalSortedKeys = new ArrayList<>(analyticalValueGroup.keySet()); - Collections.sort(analyticalSortedKeys); - - // 3. 找出最小符合的值,也就是【4500 积分,能找到 4000:102,103,104,105】、【5000 积分,能找到 5000:102,103,104,105,106,107】 - Long nextValue = analyticalSortedKeys.stream() - .filter(key -> userScore >= key) - .findFirst() - .orElse(null); - - if (null != nextValue) { - return RuleActionEntity.builder() - .data(RuleActionEntity.RaffleBeforeEntity.builder() - .strategyId(strategyId) - .ruleWeightValueKey(analyticalValueGroup.get(nextValue)) - .build()) - .ruleModel(DefaultLogicFactory.LogicModel.RULE_WIGHT.getCode()) - .code(RuleLogicCheckTypeVO.TAKE_OVER.getCode()) - .info(RuleLogicCheckTypeVO.TAKE_OVER.getInfo()) - .build(); - } - - return RuleActionEntity.builder() - .code(RuleLogicCheckTypeVO.ALLOW.getCode()) - .info(RuleLogicCheckTypeVO.ALLOW.getInfo()) - .build(); - } - - private Map getAnalyticalValue(String ruleValue) { - String[] ruleValueGroups = ruleValue.split(Constants.SPACE); - Map ruleValueMap = new HashMap<>(); - for (String ruleValueGroup : ruleValueGroups) { - // 检查驶入是否为空 - if (ruleValueGroup == null || ruleValueGroup.isEmpty()) { - return ruleValueMap; - } - - // 分割字符串以获取键和值 - String[] parts = ruleValueGroup.split(Constants.COLON); - if (parts.length < 2) { - throw new IllegalArgumentException("rule_weight rule_rule invalid input format" + ruleValueGroup); - } - ruleValueMap.put(Long.parseLong(parts[0]),ruleValueGroup); - } - return ruleValueMap; - } -} diff --git a/xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/tree/factory/DefaultTreeFactory.java b/xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/tree/factory/DefaultTreeFactory.java index 5075462c87bd5d2b6f96f7533d3d2321d44c81d4..c36269dfefbdb389785ab579bcc71209fe3a3d59 100644 --- a/xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/tree/factory/DefaultTreeFactory.java +++ b/xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/tree/factory/DefaultTreeFactory.java @@ -5,10 +5,7 @@ import cn.bugstack.domain.strategy.model.valobj.RuleTreeVO; import cn.bugstack.domain.strategy.service.rule.tree.ILogicTreeNode; import cn.bugstack.domain.strategy.service.rule.tree.factory.engine.IDecisionTreeEngine; import cn.bugstack.domain.strategy.service.rule.tree.factory.engine.impl.DecisionTreeEngine; -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Data; -import lombok.NoArgsConstructor; +import lombok.*; import org.springframework.stereotype.Service; import java.util.Map; @@ -31,35 +28,28 @@ public class DefaultTreeFactory { return new DecisionTreeEngine(logicTreeNodeGroup, ruleTreeVO); } + /** - * 决策树动作实现 + * 决策树个动作实习 */ - @Data @Builder @AllArgsConstructor @NoArgsConstructor - public static class TreeActionEntity { + public static class TreeActionEntity { private RuleLogicCheckTypeVO ruleLogicCheckType; - private StrategyAwardData strategyAwardData; + private StrategyAwardVO strategyAwardVO; } @Data @Builder @AllArgsConstructor @NoArgsConstructor - public static class StrategyAwardData { - - /** - * 抽奖奖品ID - 内部流转 - */ + public static class StrategyAwardVO { + /** 抽奖奖品ID - 内部流转使用 */ private Integer awardId; - - /** - * 抽奖奖品规则 - */ + /** 抽奖奖品规则 */ private String awardRuleValue; } - } diff --git a/xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/tree/factory/engine/IDecisionTreeEngine.java b/xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/tree/factory/engine/IDecisionTreeEngine.java index a524ccbaf524b456b11bdfbf570fc4fd5fd3af37..724edcae2d5b32741d4b769d0bd06179536c088d 100644 --- a/xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/tree/factory/engine/IDecisionTreeEngine.java +++ b/xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/tree/factory/engine/IDecisionTreeEngine.java @@ -10,5 +10,5 @@ import cn.bugstack.domain.strategy.service.rule.tree.factory.DefaultTreeFactory; */ public interface IDecisionTreeEngine { - DefaultTreeFactory.StrategyAwardData process(String userId, Long strategyId, Integer awardId); + DefaultTreeFactory.StrategyAwardVO process(String userId, Long strategyId, Integer awardId); } diff --git a/xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/tree/factory/engine/impl/DecisionTreeEngine.java b/xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/tree/factory/engine/impl/DecisionTreeEngine.java index e4a2b4c06e2d0f65d70443f359c644fd1e4af233..c7f3ee3ef4ed5e939a7ecebc9601cd92210cc097 100644 --- a/xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/tree/factory/engine/impl/DecisionTreeEngine.java +++ b/xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/tree/factory/engine/impl/DecisionTreeEngine.java @@ -31,9 +31,9 @@ public class DecisionTreeEngine implements IDecisionTreeEngine { } @Override - public DefaultTreeFactory.StrategyAwardData process(String userId, Long strategyId, Integer awardId) { + public DefaultTreeFactory.StrategyAwardVO process(String userId, Long strategyId, Integer awardId) { - DefaultTreeFactory.StrategyAwardData strategyAwardData = null; + DefaultTreeFactory.StrategyAwardVO strategyAwardData = null; // 获取基础信息 String nextNode = ruleTreeVO.getTreeRootRuleNode(); @@ -46,7 +46,7 @@ public class DecisionTreeEngine implements IDecisionTreeEngine { DefaultTreeFactory.TreeActionEntity logicEntity = logicTreeNode.logic(userId, strategyId, awardId); RuleLogicCheckTypeVO ruleLogicCheckTypeVO = logicEntity.getRuleLogicCheckType(); - strategyAwardData = logicEntity.getStrategyAwardData(); + strategyAwardData = logicEntity.getStrategyAwardVO(); log.info("决策树引擎【{}】treeId:{} node:{} code:{}", ruleTreeVO.getTreeName(), ruleTreeVO.getTreeId(), nextNode, ruleLogicCheckTypeVO.getCode()); // 获取下个节点 diff --git a/xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/tree/impl/RuleLuckAwardLogicTreeNode.java b/xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/tree/impl/RuleLuckAwardLogicTreeNode.java index 1953c9c37c2d0265e1415a937500a0cb76ce7f83..f4d0a86fad01cf4e9ff97b95b9dbda74e42a790f 100644 --- a/xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/tree/impl/RuleLuckAwardLogicTreeNode.java +++ b/xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/tree/impl/RuleLuckAwardLogicTreeNode.java @@ -20,7 +20,7 @@ public class RuleLuckAwardLogicTreeNode implements ILogicTreeNode { return DefaultTreeFactory.TreeActionEntity.builder() .ruleLogicCheckType(RuleLogicCheckTypeVO.TAKE_OVER) - .strategyAwardData(DefaultTreeFactory.StrategyAwardData.builder() + .strategyAwardVO(DefaultTreeFactory.StrategyAwardVO.builder() .awardId(101) .awardRuleValue("1,100") .build()) diff --git a/xfg-frame-archetype-lite-infrastructure/src/main/java/cn/bugstack/infrastructure/persistent/dao/IRuleTreeDao.java b/xfg-frame-archetype-lite-infrastructure/src/main/java/cn/bugstack/infrastructure/persistent/dao/IRuleTreeDao.java new file mode 100644 index 0000000000000000000000000000000000000000..cec6cc0760695999036dcb9ed569d5b4bcdfb94d --- /dev/null +++ b/xfg-frame-archetype-lite-infrastructure/src/main/java/cn/bugstack/infrastructure/persistent/dao/IRuleTreeDao.java @@ -0,0 +1,16 @@ +package cn.bugstack.infrastructure.persistent.dao; + +import cn.bugstack.infrastructure.persistent.po.RuleTree; +import org.apache.ibatis.annotations.Mapper; + +/** + * @author Fuzhengwei bugstack.cn @小傅哥 + * @description 规则树表DAO + * @create 2024-02-03 08:42 + */ +@Mapper +public interface IRuleTreeDao { + + RuleTree queryRuleTreeByTreeId(String treeId); + +} diff --git a/xfg-frame-archetype-lite-infrastructure/src/main/java/cn/bugstack/infrastructure/persistent/dao/IRuleTreeNodeDao.java b/xfg-frame-archetype-lite-infrastructure/src/main/java/cn/bugstack/infrastructure/persistent/dao/IRuleTreeNodeDao.java new file mode 100644 index 0000000000000000000000000000000000000000..1939f8cccb624392f3de9373e9945aadc34f28aa --- /dev/null +++ b/xfg-frame-archetype-lite-infrastructure/src/main/java/cn/bugstack/infrastructure/persistent/dao/IRuleTreeNodeDao.java @@ -0,0 +1,18 @@ +package cn.bugstack.infrastructure.persistent.dao; + +import cn.bugstack.infrastructure.persistent.po.RuleTreeNode; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * @author Fuzhengwei bugstack.cn @小傅哥 + * @description 规则树节点表DAO + * @create 2024-02-03 08:43 + */ +@Mapper +public interface IRuleTreeNodeDao { + + List queryRuleTreeNodeListByTreeId(String treeId); + +} diff --git a/xfg-frame-archetype-lite-infrastructure/src/main/java/cn/bugstack/infrastructure/persistent/dao/IRuleTreeNodeLineDao.java b/xfg-frame-archetype-lite-infrastructure/src/main/java/cn/bugstack/infrastructure/persistent/dao/IRuleTreeNodeLineDao.java new file mode 100644 index 0000000000000000000000000000000000000000..2143ac9b29ea1bbf532100590b0c4a1f4a0ece37 --- /dev/null +++ b/xfg-frame-archetype-lite-infrastructure/src/main/java/cn/bugstack/infrastructure/persistent/dao/IRuleTreeNodeLineDao.java @@ -0,0 +1,18 @@ +package cn.bugstack.infrastructure.persistent.dao; + +import cn.bugstack.infrastructure.persistent.po.RuleTreeNodeLine; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * @author Fuzhengwei bugstack.cn @小傅哥 + * @description 规则树节点连线表DAO + * @create 2024-02-03 08:44 + */ +@Mapper +public interface IRuleTreeNodeLineDao { + + List queryRuleTreeNodeLineListByTreeId(String treeId); + +} diff --git a/xfg-frame-archetype-lite-infrastructure/src/main/java/cn/bugstack/infrastructure/persistent/po/RuleTree.java b/xfg-frame-archetype-lite-infrastructure/src/main/java/cn/bugstack/infrastructure/persistent/po/RuleTree.java new file mode 100644 index 0000000000000000000000000000000000000000..9c568b1e5700afe2d57da9b5f49e57f7f56a2345 --- /dev/null +++ b/xfg-frame-archetype-lite-infrastructure/src/main/java/cn/bugstack/infrastructure/persistent/po/RuleTree.java @@ -0,0 +1,50 @@ +package cn.bugstack.infrastructure.persistent.po; + +import lombok.Data; + +import java.util.Date; + +/** + * @description: 规则树 + * @author: hdr + * @PACKAGE_NAME: cn.bugstack.infrastructure.persistent.po + * @DATE: 2024/4/23 + */ +@Data +public class RuleTree { + + /** + * 自增ID + */ + private Long id; + + /** + * 规则树ID + */ + private String treeId; + + /** + * 规则树名称 + */ + private String treeName; + + /** + * 规则树描述 + */ + private String treeDesc; + + /** + * 规则根节点 + */ + private String treeRootRuleKey; + + /** + * 创建时间 + */ + private Date createTime; + + /** + * 更新时间 + */ + private Date updateTime; +} diff --git a/xfg-frame-archetype-lite-infrastructure/src/main/java/cn/bugstack/infrastructure/persistent/po/RuleTreeNode.java b/xfg-frame-archetype-lite-infrastructure/src/main/java/cn/bugstack/infrastructure/persistent/po/RuleTreeNode.java new file mode 100644 index 0000000000000000000000000000000000000000..ebb452a81b5870ada951b4c77c934dd4793ed869 --- /dev/null +++ b/xfg-frame-archetype-lite-infrastructure/src/main/java/cn/bugstack/infrastructure/persistent/po/RuleTreeNode.java @@ -0,0 +1,50 @@ +package cn.bugstack.infrastructure.persistent.po; + +import lombok.Data; + +import java.util.Date; + +/** + * @description: 规则树节点 + * @author: hdr + * @PACKAGE_NAME: cn.bugstack.infrastructure.persistent.po + * @DATE: 2024/4/23 + */ +@Data +public class RuleTreeNode { + + /** + * 自增ID + */ + private Long id; + + /** + * 规则树ID + */ + private String treeId; + + /** + * 规则key + */ + private String ruleKey; + + /** + * 规则描述 + */ + private String ruleDesc; + + /** + * 规则比值 + */ + private String ruleValue; + + /** + * 创建时间 + */ + private Date createTime; + + /** + * 更新时间 + */ + private Date updateTime; +} diff --git a/xfg-frame-archetype-lite-infrastructure/src/main/java/cn/bugstack/infrastructure/persistent/po/RuleTreeNodeLine.java b/xfg-frame-archetype-lite-infrastructure/src/main/java/cn/bugstack/infrastructure/persistent/po/RuleTreeNodeLine.java new file mode 100644 index 0000000000000000000000000000000000000000..4482c142590a57b7291ece76b243fb215af35f8e --- /dev/null +++ b/xfg-frame-archetype-lite-infrastructure/src/main/java/cn/bugstack/infrastructure/persistent/po/RuleTreeNodeLine.java @@ -0,0 +1,48 @@ +package cn.bugstack.infrastructure.persistent.po; + +import lombok.Data; + +import java.util.Date; + +/** + * @description: 规则树节点连线 + * @author: hdr + * @PACKAGE_NAME: cn.bugstack.infrastructure.persistent.po + * @DATE: 2024/4/23 + */ +@Data +public class RuleTreeNodeLine { + + /** + * 自增ID + */ + private Long id; + /** + * 规则树ID + */ + private String treeId; + /** + * 规则key节点 from + */ + private String ruleNodeFrom; + /** + * 规则key节点 to + */ + private String ruleNodeTo; + /** + * 限定类型:1:=;2:>;3:<;4:>=;5<=;6:enum[枚举范围] + */ + private String ruleLimitType; + /** + * 限定值(到下个节点) + */ + private String ruleLimitValue; + /** + * 创建时间 + */ + private Date createTime; + /** + * 更新时间 + */ + private Date updateTime; +} 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 843c514b895ff05d5596e99129bd974c85a56efc..9b68f269ff5c711b8dddbd074ce0596d4d75d55f 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 @@ -3,14 +3,10 @@ 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.model.valobj.StrategyAwardRuleModelVO; +import cn.bugstack.domain.strategy.model.valobj.*; 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.dao.*; +import cn.bugstack.infrastructure.persistent.po.*; import cn.bugstack.infrastructure.persistent.redis.IRedisService; import cn.bugstack.types.common.Constants; import com.alibaba.fastjson.JSON; @@ -52,6 +48,15 @@ public class StrategyRepository implements IStrategyRepository { @Autowired private IStrategyRuleDao strategyRuleDao; + @Autowired + private IRuleTreeNodeDao ruleTreeNodeDao; + + @Autowired + private IRuleTreeDao ruleTreeDao; + + @Autowired + private IRuleTreeNodeLineDao ruleTreeNodeLineDao; + @Override public List queryStrategyAwardList(Long strategy) { @@ -182,4 +187,58 @@ public class StrategyRepository implements IStrategyRepository { return StrategyAwardRuleModelVO.builder().ruleModels(ruleModels).build(); } + @Override + public RuleTreeVO queryRuleTreeVOByTreeId(String treeId) { + + // 优先从缓存获取 + String cacheKey = Constants.RedisKey.RULE_TREE_VO_KEY + treeId; + RuleTreeVO ruleTreeVOCache = redisService.getValue(cacheKey); + if (null != ruleTreeVOCache) return ruleTreeVOCache; + + // 从数据库中获取 + RuleTree ruleTree = ruleTreeDao.queryRuleTreeByTreeId(treeId); + List ruleTreeNodes = ruleTreeNodeDao.queryRuleTreeNodeListByTreeId(treeId); + List ruleTreeNodeLines = ruleTreeNodeLineDao.queryRuleTreeNodeLineListByTreeId(treeId); + + // 1. 转Map结构 + Map> ruleTreeNodeLineMap = new HashMap<>(); + for (RuleTreeNodeLine ruleTreeNodeLine : ruleTreeNodeLines) { + RuleTreeNodeLineVO ruleTreeNodeLineVO = RuleTreeNodeLineVO.builder() + .treeId(ruleTreeNodeLine.getTreeId()) + .ruleNodeFrom(ruleTreeNodeLine.getRuleNodeFrom()) + .ruleNodeTo(ruleTreeNodeLine.getRuleNodeTo()) + .ruleLimitType(RuleLimitTypeVO.valueOf(ruleTreeNodeLine.getRuleLimitType())) + .ruleLimitValue(RuleLogicCheckTypeVO.valueOf(ruleTreeNodeLine.getRuleLimitValue())) + .build(); + + List ruleTreeNodeLineVOList = ruleTreeNodeLineMap.computeIfAbsent(ruleTreeNodeLine.getRuleNodeFrom(), k-> new ArrayList<>()); + ruleTreeNodeLineVOList.add(ruleTreeNodeLineVO); + } + + // 2. 转map结构 + Map treeNodeMap = new HashMap<>(); + for (RuleTreeNode ruleTreeNode : ruleTreeNodes) { + RuleTreeNodeVO ruleTreeNodeVO = RuleTreeNodeVO.builder() + .treeId(ruleTreeNode.getTreeId()) + .ruleKey(ruleTreeNode.getRuleKey()) + .ruleDesc(ruleTreeNode.getRuleDesc()) + .ruleValue(ruleTreeNode.getRuleValue()) + .treeNodeLineVOList(ruleTreeNodeLineMap.get(ruleTreeNode.getRuleKey())) + .build(); + treeNodeMap.put(ruleTreeNode.getRuleKey(), ruleTreeNodeVO); + } + + // 3. 构建 Rule Tree + RuleTreeVO ruleTreeVODB = RuleTreeVO.builder() + .treeId(ruleTree.getTreeId()) + .treeName(ruleTree.getTreeName()) + .treeDesc(ruleTree.getTreeDesc()) + .treeRootRuleNode(ruleTree.getTreeRootRuleKey()) + .treeNodeMap(treeNodeMap) + .build(); + + redisService.setValue(cacheKey, ruleTreeVODB); + return ruleTreeVODB; + } + } 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 0c21914eefa30758b56af35ab298e2b6b03483e8..a325b3cad4f0212ccc6cff5806b98bb03a65bf7c 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 @@ -11,6 +11,7 @@ public class Constants { 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_"; + public static String RULE_TREE_VO_KEY = "rule_tree_vo_key_"; }