() {{
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_";
}