Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
KnowledgePlanet
road-map
xfg-frame-archetype-lite
提交
d10092a1
xfg-frame-archetype-lite
项目概览
KnowledgePlanet
/
road-map
/
xfg-frame-archetype-lite
通知
1164
Star
58
Fork
71
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
xfg-frame-archetype-lite
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
提交
d10092a1
编写于
11月 18, 2024
作者:
鲸落和鲨掉
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
添加 抽奖中规则过滤(锁定奖品)、 改写抽奖模式为责任链模式
上级
b647fac1
变更
27
展开全部
隐藏空白更改
内联
并排
Showing
27 changed file
with
1666 addition
and
79 deletion
+1666
-79
xfg-frame-archetype-lite-app/data/log/log-error-2024-11-17.0.log
...me-archetype-lite-app/data/log/log-error-2024-11-17.0.log
+301
-0
xfg-frame-archetype-lite-app/data/log/log-info-2024-11-17.0.log
...ame-archetype-lite-app/data/log/log-info-2024-11-17.0.log
+688
-0
xfg-frame-archetype-lite-app/src/main/resources/mybatis/mapper/strategy_award_mapper.xml
...c/main/resources/mybatis/mapper/strategy_award_mapper.xml
+5
-0
xfg-frame-archetype-lite-app/src/test/java/cn/bugstack/test/domain/LogicChainTest.java
...src/test/java/cn/bugstack/test/domain/LogicChainTest.java
+67
-0
xfg-frame-archetype-lite-app/src/test/java/cn/bugstack/test/domain/RaffleStrategyTest.java
...test/java/cn/bugstack/test/domain/RaffleStrategyTest.java
+37
-5
xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/AbstractRaffleStrategy.java
...a/cn/bugstack/domain/strategy/AbstractRaffleStrategy.java
+29
-27
xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/IRaffleStrategy.java
...ain/java/cn/bugstack/domain/strategy/IRaffleStrategy.java
+1
-1
xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/model/entity/RaffleFactorEntity.java
...tack/domain/strategy/model/entity/RaffleFactorEntity.java
+3
-0
xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/model/entity/RuleActionEntity.java
...gstack/domain/strategy/model/entity/RuleActionEntity.java
+38
-0
xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/model/valobj/RuleLogicCheckTypeVO.java
...ck/domain/strategy/model/valobj/RuleLogicCheckTypeVO.java
+2
-0
xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/model/valobj/StrategyAwardRuleModelVO.java
...omain/strategy/model/valobj/StrategyAwardRuleModelVO.java
+60
-0
xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/repository/IStrategyRepository.java
...stack/domain/strategy/repository/IStrategyRepository.java
+4
-1
xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/service/annotation/LogicStrategy.java
...ack/domain/strategy/service/annotation/LogicStrategy.java
+3
-1
xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/service/raffle/DefaultRaffleStrategy.java
...domain/strategy/service/raffle/DefaultRaffleStrategy.java
+21
-35
xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/chain/AbstractLogicChain.java
...omain/strategy/service/rule/chain/AbstractLogicChain.java
+30
-0
xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/chain/ILogicChain.java
...stack/domain/strategy/service/rule/chain/ILogicChain.java
+21
-0
xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/chain/ILogicChainArmory.java
...domain/strategy/service/rule/chain/ILogicChainArmory.java
+12
-0
xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/chain/factory/DefaultChainFactory.java
...ategy/service/rule/chain/factory/DefaultChainFactory.java
+54
-0
xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/chain/impl/BackListLogicChain.java
.../strategy/service/rule/chain/impl/BackListLogicChain.java
+52
-0
xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/chain/impl/DefaultLogicChain.java
...n/strategy/service/rule/chain/impl/DefaultLogicChain.java
+34
-0
xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/chain/impl/RuleWeightLogicChain.java
...trategy/service/rule/chain/impl/RuleWeightLogicChain.java
+109
-0
xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/filter/ILogicFilter.java
...ack/domain/strategy/service/rule/filter/ILogicFilter.java
+1
-1
xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/filter/factory/DefaultLogicFactory.java
...tegy/service/rule/filter/factory/DefaultLogicFactory.java
+16
-7
xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/filter/impl/RuleLockLogicFilter.java
...trategy/service/rule/filter/impl/RuleLockLogicFilter.java
+55
-0
xfg-frame-archetype-lite-infrastructure/src/main/java/cn/bugstack/infrastructure/persistent/dao/IStrategyAwardDao.java
...tack/infrastructure/persistent/dao/IStrategyAwardDao.java
+1
-0
xfg-frame-archetype-lite-infrastructure/src/main/java/cn/bugstack/infrastructure/persistent/po/Strategy.java
...va/cn/bugstack/infrastructure/persistent/po/Strategy.java
+4
-0
xfg-frame-archetype-lite-infrastructure/src/main/java/cn/bugstack/infrastructure/persistent/repository/StrategyRepository.java
...rastructure/persistent/repository/StrategyRepository.java
+18
-1
未找到文件。
xfg-frame-archetype-lite-app/data/log/log-error-2024-11-17.0.log
0 → 100644
浏览文件 @
d10092a1
此差异已折叠。
点击以展开。
xfg-frame-archetype-lite-app/data/log/log-info-2024-11-17.0.log
0 → 100644
浏览文件 @
d10092a1
此差异已折叠。
点击以展开。
xfg-frame-archetype-lite-app/src/main/resources/mybatis/mapper/strategy_award_mapper.xml
浏览文件 @
d10092a1
...
...
@@ -28,5 +28,10 @@
where strategy_id = #{strategy_id}
</select>
<select
id=
"queryStrategyAwardRuleModels"
parameterType=
"java.lang.Long"
resultMap=
"dataMap"
>
select rule_models from strategy_award
where strategy_id = #{strategyId} and award_id = #{awardId}
</select>
</mapper>
xfg-frame-archetype-lite-app/src/test/java/cn/bugstack/test/domain/LogicChainTest.java
0 → 100644
浏览文件 @
d10092a1
package
cn.bugstack.test.domain
;
import
cn.bugstack.domain.strategy.service.armory.IStrategyArmory
;
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.chain.impl.RuleWeightLogicChain
;
import
lombok.extern.slf4j.Slf4j
;
import
org.junit.Before
;
import
org.junit.Test
;
import
org.junit.runner.RunWith
;
import
org.springframework.boot.test.context.SpringBootTest
;
import
org.springframework.test.context.junit4.SpringRunner
;
import
org.springframework.test.util.ReflectionTestUtils
;
import
javax.annotation.Resource
;
/**
* @ClassName: LogicChainTest
* @Description:
* @Author: zhaoyongfeng
* @Date: 2024/11/18 22:49
*/
@Slf4j
@RunWith
(
SpringRunner
.
class
)
@SpringBootTest
public
class
LogicChainTest
{
@Resource
private
IStrategyArmory
strategyArmory
;
@Resource
private
RuleWeightLogicChain
ruleWeightLogicChain
;
@Resource
private
DefaultChainFactory
defaultChainFactory
;
@Before
public
void
setUp
()
{
// 策略装配 100001、100002、100003
log
.
info
(
"测试结果:{}"
,
strategyArmory
.
assembleLotteryStrategy
(
100001L
));
// log.info("测试结果:{}", strategyArmory.assembleLotteryStrategy(100002L));
// log.info("测试结果:{}", strategyArmory.assembleLotteryStrategy(100003L));
}
@Test
public
void
test_LogicChain_rule_blacklist
()
{
ILogicChain
logicChain
=
defaultChainFactory
.
openLogicChain
(
100001L
);
Integer
awardId
=
logicChain
.
logic
(
"user001"
,
100001L
);
log
.
info
(
"测试结果:{}"
,
awardId
);
}
@Test
public
void
test_LogicChain_rule_weight
()
{
// 通过反射 mock 规则中的值
ReflectionTestUtils
.
setField
(
ruleWeightLogicChain
,
"userScore"
,
4900L
);
ILogicChain
logicChain
=
defaultChainFactory
.
openLogicChain
(
100001L
);
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
);
}
}
xfg-frame-archetype-lite-app/src/test/java/cn/bugstack/test/domain/RaffleStrategyTest.java
浏览文件 @
d10092a1
...
...
@@ -2,8 +2,10 @@ package cn.bugstack.test.domain;
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.rule.impl.RuleWeightLogicFilter
;
import
cn.bugstack.domain.strategy.IRaffleStrategy
;
import
cn.bugstack.domain.strategy.service.armory.IStrategyArmory
;
import
cn.bugstack.domain.strategy.service.rule.chain.impl.DefaultLogicChain
;
import
cn.bugstack.domain.strategy.service.rule.chain.impl.RuleWeightLogicChain
;
import
com.alibaba.fastjson.JSON
;
import
lombok.extern.slf4j.Slf4j
;
import
org.junit.Before
;
...
...
@@ -14,7 +16,6 @@ import org.springframework.test.context.junit4.SpringRunner;
import
org.springframework.test.util.ReflectionTestUtils
;
import
javax.annotation.Resource
;
import
java.security.PrivateKey
;
/**
* @ClassName: RaffleStrategyTest
...
...
@@ -26,14 +27,27 @@ import java.security.PrivateKey;
@Slf4j
@RunWith
(
SpringRunner
.
class
)
public
class
RaffleStrategyTest
{
@Resource
private
IStrategyArmory
strategyArmory
;
@Resource
private
IRaffleStrategy
raffleStrategy
;
@Resource
private
RuleWeightLogicFilter
ruleWeightLogicFilter
;
private
RuleWeightLogicChain
ruleWeightLogicChain
;
@Resource
private
DefaultLogicChain
defaultLogicChain
;
@Before
public
void
setUp
()
{
ReflectionTestUtils
.
setField
(
ruleWeightLogicFilter
,
"userScore"
,
4500L
);
// 策略装配 100001、100002、100003
log
.
info
(
"测试结果:{}"
,
strategyArmory
.
assembleLotteryStrategy
(
100001L
));
/* log.info("测试结果:{}", strategyArmory.assembleLotteryStrategy(100002L));
log.info("测试结果:{}", strategyArmory.assembleLotteryStrategy(100003L));*/
// 通过反射 mock 规则中的值
ReflectionTestUtils
.
setField
(
ruleWeightLogicChain
,
"userScore"
,
40500L
);
ReflectionTestUtils
.
setField
(
defaultLogicChain
,
"userRaffleCount"
,
10L
);
}
@Test
public
void
test_performRaffle
()
{
RaffleFactorEntity
raffleFactorEntity
=
RaffleFactorEntity
.
builder
()
...
...
@@ -60,6 +74,24 @@ public class RaffleStrategyTest {
log
.
info
(
"测试结果:{}"
,
JSON
.
toJSONString
(
raffleAwardEntity
));
}
/**
* 次数错校验,抽奖n次后解锁。100003 策略,你可以通过调整 @Before 的 setUp 方法中个人抽奖次数来验证。比如最开始设置0,之后设置10
* ReflectionTestUtils.setField(ruleLockLogicFilter, "userRaffleCount", 10L);
*/
@Test
public
void
test_raffle_center_rule_lock
(){
RaffleFactorEntity
raffleFactorEntity
=
RaffleFactorEntity
.
builder
()
.
userId
(
"xiaofuge"
)
.
strategyId
(
100003L
)
.
build
();
RaffleAwardEntity
raffleAwardEntity
=
raffleStrategy
.
performRaffle
(
raffleFactorEntity
);
log
.
info
(
"请求参数:{}"
,
JSON
.
toJSONString
(
raffleFactorEntity
));
log
.
info
(
"测试结果:{}"
,
JSON
.
toJSONString
(
raffleAwardEntity
));
}
}
xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/
service/raffle/
AbstractRaffleStrategy.java
→
xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/AbstractRaffleStrategy.java
浏览文件 @
d10092a1
package
cn.bugstack.domain.strategy
.service.raffle
;
package
cn.bugstack.domain.strategy
;
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.factory.DefaultLogicFactory
;
import
cn.bugstack.domain.strategy.service.rule.chain.ILogicChain
;
import
cn.bugstack.domain.strategy.service.rule.chain.factory.DefaultChainFactory
;
import
cn.bugstack.types.enums.ResponseCode
;
import
cn.bugstack.types.exception.AppException
;
import
lombok.extern.slf4j.Slf4j
;
...
...
@@ -27,10 +28,13 @@ public abstract class AbstractRaffleStrategy implements IRaffleStrategy {
protected
IStrategyRepository
repository
;
// 策略调度服务 -> 只负责抽奖处理,通过新增接口的方式,隔离职责,不需要使用方关心或者调用抽奖的初始化
protected
IStrategyDispatch
strategyDispatch
;
// 抽奖的责任链 -> 从抽奖的规则中,解耦出前置规则为责任链处理
private
final
DefaultChainFactory
defaultChainFactory
;
public
AbstractRaffleStrategy
(
IStrategyRepository
repository
,
IStrategyDispatch
strategyDispatch
)
{
public
AbstractRaffleStrategy
(
IStrategyRepository
repository
,
IStrategyDispatch
strategyDispatch
,
DefaultChainFactory
defaultChainFactory
)
{
this
.
repository
=
repository
;
this
.
strategyDispatch
=
strategyDispatch
;
this
.
defaultChainFactory
=
defaultChainFactory
;
}
@Override
...
...
@@ -42,37 +46,35 @@ public abstract class AbstractRaffleStrategy implements IRaffleStrategy {
throw
new
AppException
(
ResponseCode
.
ILLEGAL_PARAMETER
.
getCode
(),
ResponseCode
.
ILLEGAL_PARAMETER
.
getInfo
());
}
// 2.
策略查询
StrategyEntity
strategy
=
repository
.
queryStrategyEntityByStrategyId
(
strategyId
);
// 2.
获取抽奖责任链 - 前置规则的责任链处理
ILogicChain
logicChain
=
defaultChainFactory
.
openLogicChain
(
strategyId
);
// 3.
抽奖前 - 规则过滤
RuleActionEntity
<
RuleActionEntity
.
RaffleBeforeEntity
>
ruleActionEntity
=
this
.
doCheckRaffleBeforeLogic
(
RaffleFactorEntity
.
builder
().
userId
(
userId
).
strategyId
(
strategyId
).
build
(),
strategy
.
ruleModels
()
);
// 3.
通过责任链获得,奖品ID
Integer
awardId
=
logicChain
.
logic
(
userId
,
strategyId
);
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. 查询奖品规则「抽奖中(拿到奖品ID时,过滤规则)、抽奖后(扣减完奖品库存后过滤,抽奖中拦截和无库存则走兜底)」
StrategyAwardRuleModelVO
strategyAwardRuleModelVO
=
repository
.
queryStrategyAwardRuleModelVO
(
strategyId
,
awardId
);
// 4. 默认抽奖流程
Integer
awardId
=
strategyDispatch
.
getRandomAwardId
(
strategyId
);
// 5. 抽奖中 - 规则过滤
RuleActionEntity
<
RuleActionEntity
.
RaffleCenterEntity
>
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
<
RuleActionEntity
.
RaffleBeforeEntity
>
doCheckRaffleBeforeLogic
(
RaffleFactorEntity
raffleFactorEntity
,
String
...
logics
);
protected
abstract
RuleActionEntity
<
RuleActionEntity
.
RaffleCenterEntity
>
doCheckRaffleCenterLogic
(
RaffleFactorEntity
raffleFactorEntity
,
String
...
logics
);
}
xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/
service/
IRaffleStrategy.java
→
xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/IRaffleStrategy.java
浏览文件 @
d10092a1
package
cn.bugstack.domain.strategy
.service
;
package
cn.bugstack.domain.strategy
;
import
cn.bugstack.domain.strategy.model.entity.RaffleAwardEntity
;
...
...
xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/model/entity/RaffleFactorEntity.java
浏览文件 @
d10092a1
...
...
@@ -21,5 +21,8 @@ public class RaffleFactorEntity {
private
String
userId
;
/** 策略ID */
private
Long
strategyId
;
/** 奖品ID */
private
Integer
awardId
;
}
xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/model/entity/RuleActionEntity.java
浏览文件 @
d10092a1
...
...
@@ -48,12 +48,50 @@ public class RuleActionEntity<T extends RuleActionEntity.RaffleEntity> {
}
// 抽奖之中
@EqualsAndHashCode
(
callSuper
=
true
)
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
static
public
class
RaffleCenterEntity
extends
RaffleEntity
{
/**
* 策略ID
*/
private
Long
strategyId
;
/**
* 权重值Key;用于抽奖时可以选择权重抽奖。
*/
private
String
ruleWeightValueKey
;
/**
* 奖品ID;
*/
private
Integer
awardId
;
}
// 抽奖之后
@EqualsAndHashCode
(
callSuper
=
true
)
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
static
public
class
RaffleAfterEntity
extends
RaffleEntity
{
/**
* 策略ID
*/
private
Long
strategyId
;
/**
* 权重值Key;用于抽奖时可以选择权重抽奖。
*/
private
String
ruleWeightValueKey
;
/**
* 奖品ID;
*/
private
Integer
awardId
;
}
...
...
xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/model/valobj/RuleLogicCheckTypeVO.java
浏览文件 @
d10092a1
package
cn.bugstack.domain.strategy.model.valobj
;
import
lombok.AllArgsConstructor
;
import
lombok.Builder
;
import
lombok.Getter
;
import
lombok.NoArgsConstructor
;
/**
* @ClassName: RuleLogicCheckTypeVO
...
...
xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/model/valobj/StrategyAwardRuleModelVO.java
0 → 100644
浏览文件 @
d10092a1
package
cn.bugstack.domain.strategy.model.valobj
;
import
cn.bugstack.domain.strategy.service.rule.chain.factory.DefaultChainFactory
;
import
cn.bugstack.domain.strategy.service.rule.filter.factory.DefaultLogicFactory
;
import
cn.bugstack.types.common.Constants
;
import
lombok.AllArgsConstructor
;
import
lombok.Builder
;
import
lombok.Getter
;
import
lombok.NoArgsConstructor
;
import
java.util.ArrayList
;
import
java.util.List
;
/**
* @ClassName: StrategyAwardRuleModelVO
* @Description:
* @Author: zhaoyongfeng
* @Date: 2024/11/18 20:39
*/
@Getter
@Builder
@AllArgsConstructor
@NoArgsConstructor
public
class
StrategyAwardRuleModelVO
{
private
String
ruleModels
;
/**
* 获取抽奖中规则;或者使用 lambda 表达式
* <p>
* List<String> ruleModelList = Arrays.stream(ruleModels.split(Constants.SPLIT))
* .filter(DefaultLogicFactory.LogicModel::isCenter)
* .collect(Collectors.toList());
* return ruleModelList;
* <p>
* List<String> collect = Arrays.stream(ruleModelValues).filter(DefaultLogicFactory.LogicModel::isCenter).collect(Collectors.toList());
*/
public
String
[]
raffleCenterRuleModelList
()
{
List
<
String
>
ruleModelList
=
new
ArrayList
<>();
String
[]
ruleModelValues
=
ruleModels
.
split
(
Constants
.
SPLIT
);
for
(
String
ruleModelValue
:
ruleModelValues
)
{
if
(
DefaultLogicFactory
.
LogicModel
.
isCenter
(
ruleModelValue
))
{
ruleModelList
.
add
(
ruleModelValue
);
}
}
return
ruleModelList
.
toArray
(
new
String
[
0
]);
}
public
String
[]
raffleAfterRuleModelList
()
{
List
<
String
>
ruleModelList
=
new
ArrayList
<>();
String
[]
ruleModelValues
=
ruleModels
.
split
(
Constants
.
SPLIT
);
for
(
String
ruleModelValue
:
ruleModelValues
)
{
if
(
DefaultLogicFactory
.
LogicModel
.
isAfter
(
ruleModelValue
))
{
ruleModelList
.
add
(
ruleModelValue
);
}
}
return
ruleModelList
.
toArray
(
new
String
[
0
]);
}
}
xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/repository/IStrategyRepository.java
浏览文件 @
d10092a1
...
...
@@ -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.StrategyAwardRuleModelVO
;
import
java.util.List
;
import
java.util.Map
;
...
...
@@ -11,7 +12,7 @@ public interface IStrategyRepository {
List
<
StrategyAwardEntity
>
queryStrategyAwardList
(
Long
strategyId
);
void
storeStrategyAwardSearchRateTable
(
String
key
,
Integer
rateRange
,
Map
<
Integer
,
Integer
>
strategyAwardSearchRateTable
);
void
storeStrategyAwardSearchRateTable
(
String
key
,
int
rateRange
,
Map
<
Integer
,
Integer
>
strategyAwardSearchRateTable
);
Integer
getStrategyAwardAssemble
(
String
key
,
Integer
rateKey
);
...
...
@@ -24,6 +25,8 @@ public interface IStrategyRepository {
StrategyRuleEntity
queryStrategyRule
(
Long
strategyId
,
String
ruleModel
);
String
queryStrategyRuleValue
(
Long
strategyId
,
Integer
awardId
,
String
ruleModel
);
String
queryStrategyRuleValue
(
Long
strategyId
,
String
ruleModel
);
StrategyAwardRuleModelVO
queryStrategyAwardRuleModelVO
(
Long
strategyId
,
Integer
awardId
);
}
xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/service/annotation/LogicStrategy.java
浏览文件 @
d10092a1
package
cn.bugstack.domain.strategy.service.annotation
;
import
cn.bugstack.domain.strategy.service.rule.factory.DefaultLogicFactory
;
import
cn.bugstack.domain.strategy.service.rule.chain.factory.DefaultChainFactory
;
import
cn.bugstack.domain.strategy.service.rule.filter.factory.DefaultLogicFactory
;
import
java.lang.annotation.ElementType
;
import
java.lang.annotation.Retention
;
...
...
@@ -21,3 +22,4 @@ public @interface LogicStrategy {
}
xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/service/raffle/DefaultRaffleStrategy.java
浏览文件 @
d10092a1
package
cn.bugstack.domain.strategy.service.raffle
;
import
cn.bugstack.domain.strategy.AbstractRaffleStrategy
;
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.repository.IStrategyRepository
;
import
cn.bugstack.domain.strategy.service.armory.IStrategyDispatch
;
import
cn.bugstack.domain.strategy.service.rule.ILogicFilter
;
import
cn.bugstack.domain.strategy.service.rule.factory.DefaultLogicFactory
;
import
cn.bugstack.domain.strategy.service.rule.filter.ILogicFilter
;
import
cn.bugstack.domain.strategy.service.rule.chain.factory.DefaultChainFactory
;
import
cn.bugstack.domain.strategy.service.rule.filter.factory.DefaultLogicFactory
;
import
lombok.extern.slf4j.Slf4j
;
import
org.apache.commons.lang3.StringUtils
;
import
org.springframework.stereotype.Service
;
...
...
@@ -31,54 +33,38 @@ public class DefaultRaffleStrategy extends AbstractRaffleStrategy {
@Resource
private
DefaultLogicFactory
logicFactory
;
public
DefaultRaffleStrategy
(
IStrategyRepository
repository
,
IStrategyDispatch
strategyDispatch
)
{
super
(
repository
,
strategyDispatch
);
}
@Override
protected
RuleActionEntity
<
RuleActionEntity
.
RaffleBeforeEntity
>
doCheckRaffleBeforeLogic
(
RaffleFactorEntity
raffleFactorEntity
,
String
...
logics
)
{
Map
<
String
,
ILogicFilter
<
RuleActionEntity
.
RaffleBeforeEntity
>>
logicFilterGroup
=
logicFactory
.
openLogicFilter
();
public
DefaultRaffleStrategy
(
IStrategyRepository
repository
,
IStrategyDispatch
strategyDispatch
,
DefaultChainFactory
defaultChainFactory
)
{
super
(
repository
,
strategyDispatch
,
defaultChainFactory
);
}
// 黑名单规则优先过滤
String
ruleBackList
=
Arrays
.
stream
(
logics
)
.
filter
(
str
->
str
.
contains
(
DefaultLogicFactory
.
LogicModel
.
RULE_BLACKLIST
.
getCode
()))
.
findFirst
()
.
orElse
(
null
);
if
(
StringUtils
.
isNotBlank
(
ruleBackList
))
{
ILogicFilter
<
RuleActionEntity
.
RaffleBeforeEntity
>
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
.
RaffleBeforeEntity
>
ruleActionEntity
=
logicFilter
.
filter
(
ruleMatterEntity
);
if
(!
RuleLogicCheckTypeVO
.
ALLOW
.
getCode
().
equals
(
ruleActionEntity
.
getCode
()))
{
return
ruleActionEntity
;
}
}
@Override
protected
RuleActionEntity
<
RuleActionEntity
.
RaffleCenterEntity
>
doCheckRaffleCenterLogic
(
RaffleFactorEntity
raffleFactorEntity
,
String
...
logics
)
{
if
(
logics
==
null
||
0
==
logics
.
length
)
return
RuleActionEntity
.<
RuleActionEntity
.
RaffleCenterEntity
>
builder
()
.
code
(
RuleLogicCheckTypeVO
.
ALLOW
.
getCode
())
.
info
(
RuleLogicCheckTypeVO
.
ALLOW
.
getInfo
())
.
build
();
// 顺序过滤剩余规则
List
<
String
>
ruleList
=
Arrays
.
stream
(
logics
)
.
filter
(
s
->
!
s
.
equals
(
DefaultLogicFactory
.
LogicModel
.
RULE_BLACKLIST
.
getCode
()))
.
collect
(
Collectors
.
toList
());
Map
<
String
,
ILogicFilter
<
RuleActionEntity
.
RaffleCenterEntity
>>
logicFilterGroup
=
logicFactory
.
openLogicFilter
();
RuleActionEntity
<
RuleActionEntity
.
Raffle
Before
Entity
>
ruleActionEntity
=
null
;
for
(
String
ruleModel
:
ruleList
)
{
ILogicFilter
<
RuleActionEntity
.
Raffle
Before
Entity
>
logicFilter
=
logicFilterGroup
.
get
(
ruleModel
);
RuleActionEntity
<
RuleActionEntity
.
Raffle
Center
Entity
>
ruleActionEntity
=
null
;
for
(
String
ruleModel
:
logics
)
{
ILogicFilter
<
RuleActionEntity
.
Raffle
Center
Entity
>
logicFilter
=
logicFilterGroup
.
get
(
ruleModel
);
RuleMatterEntity
ruleMatterEntity
=
new
RuleMatterEntity
();
ruleMatterEntity
.
setUserId
(
raffleFactorEntity
.
getUserId
());
ruleMatterEntity
.
setAwardId
(
r
uleMatte
rEntity
.
getAwardId
());
ruleMatterEntity
.
setAwardId
(
r
affleFacto
rEntity
.
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
());
log
.
info
(
"抽奖
中
规则过滤 userId: {} ruleModel: {} code: {} info: {}"
,
raffleFactorEntity
.
getUserId
(),
ruleModel
,
ruleActionEntity
.
getCode
(),
ruleActionEntity
.
getInfo
());
if
(!
RuleLogicCheckTypeVO
.
ALLOW
.
getCode
().
equals
(
ruleActionEntity
.
getCode
()))
return
ruleActionEntity
;
}
return
ruleActionEntity
;
}
}
xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/chain/AbstractLogicChain.java
0 → 100644
浏览文件 @
d10092a1
package
cn.bugstack.domain.strategy.service.rule.chain
;
import
lombok.extern.slf4j.Slf4j
;
/**
* @ClassName: AbstractLogicChain
* @Description: 抽奖策略责任链,判断走那种抽奖策略。如;默认抽象、权重抽奖、黑名单抽奖
* @Author: zhaoyongfeng
* @Date: 2024/11/18 22:03
*/
@Slf4j
public
abstract
class
AbstractLogicChain
implements
ILogicChain
{
private
ILogicChain
next
;
@Override
public
ILogicChain
next
()
{
return
next
;
}
@Override
public
ILogicChain
appendNext
(
ILogicChain
next
)
{
this
.
next
=
next
;
return
next
;
}
protected
abstract
String
ruleModel
();
}
xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/chain/ILogicChain.java
0 → 100644
浏览文件 @
d10092a1
package
cn.bugstack.domain.strategy.service.rule.chain
;
/*
* @return
* @author zhaoyongfeng
* @description 抽奖策略规则责任链接口
*
* @param null
*/
public
interface
ILogicChain
extends
ILogicChainArmory
{
/**
* 责任链接口
*
* @param userId 用户ID
* @param strategyId 策略ID
* @return 奖品ID
*/
Integer
logic
(
String
userId
,
Long
strategyId
);
}
xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/chain/ILogicChainArmory.java
0 → 100644
浏览文件 @
d10092a1
package
cn.bugstack.domain.strategy.service.rule.chain
;
/*
* @return
* @author zhaoyongfeng
* @description 责任链装配
*
* @param null
*/
public
interface
ILogicChainArmory
{
ILogicChain
next
();
ILogicChain
appendNext
(
ILogicChain
next
);
}
xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/chain/factory/DefaultChainFactory.java
0 → 100644
浏览文件 @
d10092a1
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
org.springframework.stereotype.Service
;
import
java.util.Map
;
/**
* @ClassName: DefaultLogicFactory
* @Description:
* @Author: zhaoyongfeng
* @Date: 2024/11/17 16:05
*/
@Service
public
class
DefaultChainFactory
{
private
final
Map
<
String
,
ILogicChain
>
logicChainGroup
;
protected
IStrategyRepository
repository
;
public
DefaultChainFactory
(
Map
<
String
,
ILogicChain
>
logicChainGroup
,
IStrategyRepository
repository
)
{
this
.
logicChainGroup
=
logicChainGroup
;
this
.
repository
=
repository
;
}
/**
* 通过策略ID,构建责任链
*
* @param strategyId 策略ID
* @return LogicChain
*/
public
ILogicChain
openLogicChain
(
Long
strategyId
)
{
StrategyEntity
strategy
=
repository
.
queryStrategyEntityByStrategyId
(
strategyId
);
String
[]
ruleModels
=
strategy
.
ruleModels
();
// 如果未配置策略规则,则只装填一个默认责任链
if
(
null
==
ruleModels
||
0
==
ruleModels
.
length
)
return
logicChainGroup
.
get
(
"default"
);
// 按照配置顺序装填用户配置的责任链;rule_blacklist、rule_weight 「注意此数据从Redis缓存中获取,如果更新库表,记得在测试阶段手动处理缓存」
ILogicChain
logicChain
=
logicChainGroup
.
get
(
ruleModels
[
0
]);
ILogicChain
current
=
logicChain
;
for
(
int
i
=
1
;
i
<
ruleModels
.
length
;
i
++)
{
ILogicChain
nextChain
=
logicChainGroup
.
get
(
ruleModels
[
i
]);
current
=
current
.
appendNext
(
nextChain
);
}
// 责任链的最后装填默认责任链
current
.
appendNext
(
logicChainGroup
.
get
(
"default"
));
return
logicChain
;
}
}
xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/chain/impl/BackListLogicChain.java
0 → 100644
浏览文件 @
d10092a1
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.types.common.Constants
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.stereotype.Component
;
import
javax.annotation.Resource
;
/**
* @ClassName: RuleBackListLogicFilter
* @Description: 【抽奖前规则】黑名单用户过滤规则
* @Author: zhaoyongfeng
* @Date: 2024/11/17 16:07
*/
@Slf4j
@Component
(
"rule_blacklist"
)
public
class
BackListLogicChain
extends
AbstractLogicChain
{
@Resource
private
IStrategyRepository
repository
;
@Override
public
Integer
logic
(
String
userId
,
Long
strategyId
)
{
log
.
info
(
"抽奖责任链-黑名单开始 userId: {} strategyId: {} ruleModel: {}"
,
userId
,
strategyId
,
ruleModel
());
// 查询规则值配置
String
ruleValue
=
repository
.
queryStrategyRuleValue
(
strategyId
,
ruleModel
());
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
))
{
log
.
info
(
"抽奖责任链-黑名单接管 userId: {} strategyId: {} ruleModel: {} awardId: {}"
,
userId
,
strategyId
,
ruleModel
(),
awardId
);
return
awardId
;
}
}
// 过滤其他责任链
log
.
info
(
"抽奖责任链-黑名单放行 userId: {} strategyId: {} ruleModel: {}"
,
userId
,
strategyId
,
ruleModel
());
return
next
().
logic
(
userId
,
strategyId
);
}
@Override
protected
String
ruleModel
()
{
return
"rule_blacklist"
;
}
}
xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/chain/impl/DefaultLogicChain.java
0 → 100644
浏览文件 @
d10092a1
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
lombok.extern.slf4j.Slf4j
;
import
org.springframework.stereotype.Component
;
import
javax.annotation.Resource
;
/**
* @ClassName: RuleLockLogicFilter
* @Description:
* @Author: zhaoyongfeng
* @Date: 2024/11/18 20:25
*/
@Slf4j
@Component
(
"default"
)
public
class
DefaultLogicChain
extends
AbstractLogicChain
{
@Resource
protected
IStrategyDispatch
strategyDispatch
;
@Override
public
Integer
logic
(
String
userId
,
Long
strategyId
)
{
Integer
awardId
=
strategyDispatch
.
getRandomAwardId
(
strategyId
);
log
.
info
(
"抽奖责任链-默认处理 userId: {} strategyId: {} ruleModel: {} awardId: {}"
,
userId
,
strategyId
,
ruleModel
(),
awardId
);
return
awardId
;
}
@Override
protected
String
ruleModel
()
{
return
"default"
;
}
}
xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/
impl/RuleWeightLogicFilter
.java
→
xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/
chain/impl/RuleWeightLogicChain
.java
浏览文件 @
d10092a1
package
cn.bugstack.domain.strategy.service.rule.impl
;
package
cn.bugstack.domain.strategy.service.rule.
chain.
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.ILogicFilter
;
import
cn.bugstack.domain.strategy.service.rule.factory.DefaultLogicFactory
;
import
cn.bugstack.domain.strategy.service.armory.IStrategyDispatch
;
import
cn.bugstack.domain.strategy.service.rule.chain.AbstractLogicChain
;
import
cn.bugstack.types.common.Constants
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.stereotype.Component
;
...
...
@@ -20,66 +16,74 @@ import java.util.*;
* @Date: 2024/11/17 16:08
*/
@Slf4j
@Component
@LogicStrategy
(
logicMode
=
DefaultLogicFactory
.
LogicModel
.
RULE_WIGHT
)
public
class
RuleWeightLogicFilter
implements
ILogicFilter
<
RuleActionEntity
.
RaffleBeforeEntity
>
{
@Component
(
"rule_weight"
)
public
class
RuleWeightLogicChain
extends
AbstractLogicChain
{
@Resource
private
IStrategyRepository
repository
;
public
Long
userScore
=
4500L
;
@Resource
protected
IStrategyDispatch
strategyDispatch
;
// 根据用户ID查询用户抽奖消耗的积分值,本章节我们先写死为固定的值。后续需要从数据库中查询。
/**
* 权重
规则
过滤;
* 权重
责任链
过滤;
* 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
<
RuleActionEntity
.
RaffleBeforeEntity
>
filter
(
RuleMatterEntity
ruleMatterEntity
)
{
log
.
info
(
"
规则过滤-权重范围 userId:{} strategyId:{} ruleModel:{}"
,
ruleMatterEntity
.
getUserId
(),
ruleMatterEntity
.
getStrategyId
(),
ruleMatterEntity
.
getR
uleModel
());
public
Integer
logic
(
String
userId
,
Long
strategyId
)
{
log
.
info
(
"
抽奖责任链-权重开始 userId: {} strategyId: {} ruleModel: {}"
,
userId
,
strategyId
,
r
uleModel
());
String
userId
=
ruleMatterEntity
.
getUserId
();
Long
strategyId
=
ruleMatterEntity
.
getStrategyId
();
String
ruleValue
=
repository
.
queryStrategyRuleValue
(
ruleMatterEntity
.
getStrategyId
(),
ruleMatterEntity
.
getAwardId
(),
ruleMatterEntity
.
getRuleModel
());
String
ruleValue
=
repository
.
queryStrategyRuleValue
(
strategyId
,
ruleModel
());
// 1. 根据用户ID查询用户抽奖消耗的积分值,本章节我们先写死为固定的值。后续需要从数据库中查询。
Map
<
Long
,
String
>
analyticalValueGroup
=
getAnalyticalValue
(
ruleValue
);
if
(
null
==
analyticalValueGroup
||
analyticalValueGroup
.
isEmpty
())
{
return
RuleActionEntity
.<
RuleActionEntity
.
RaffleBeforeEntity
>
builder
()
.
code
(
RuleLogicCheckTypeVO
.
ALLOW
.
getCode
())
.
info
(
RuleLogicCheckTypeVO
.
ALLOW
.
getInfo
())
.
build
();
}
if
(
null
==
analyticalValueGroup
||
analyticalValueGroup
.
isEmpty
())
return
null
;
// 2. 转换Keys值,并默认排序
List
<
Long
>
analyticalSortedKeys
=
new
ArrayList
<>(
analyticalValueGroup
.
keySet
());
Collections
.
sort
(
analyticalSortedKeys
);
// 3. 找出最小符合的值,也就是【4500 积分,能找到 4000:102,103,104,105】、【5000 积分,能找到 5000:102,103,104,105,106,107】
/* 找到最后一个符合的值[如用户传了一个 5900 应该返回正确结果为 5000],如果使用 Lambda findFirst 需要注意使用 sorted 反转结果
* Long nextValue = null;
* for (Long analyticalSortedKeyValue : analyticalSortedKeys) {
* if (userScore >= analyticalSortedKeyValue){
* nextValue = analyticalSortedKeyValue;
* }
* }
*
* Long nextValue = analyticalSortedKeys.stream()
* .filter(key -> userScore >= key)
* .max(Comparator.naturalOrder())
* .orElse(null);
*/
Long
nextValue
=
analyticalSortedKeys
.
stream
()
.
filter
(
key
->
userScore
>=
key
)
.
sorted
(
Comparator
.
reverseOrder
())
.
filter
(
analyticalSortedKeyValue
->
userScore
>=
analyticalSortedKeyValue
)
.
findFirst
()
.
orElse
(
null
);
// 4. 权重抽奖
if
(
null
!=
nextValue
)
{
return
RuleActionEntity
.<
RuleActionEntity
.
RaffleBeforeEntity
>
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
();
Integer
awardId
=
strategyDispatch
.
getRandomAwardId
(
strategyId
,
analyticalValueGroup
.
get
(
nextValue
));
log
.
info
(
"抽奖责任链-权重接管 userId: {} strategyId: {} ruleModel: {} awardId: {}"
,
userId
,
strategyId
,
ruleModel
(),
awardId
);
return
awardId
;
}
return
RuleActionEntity
.<
RuleActionEntity
.
RaffleBeforeEntity
>
builder
()
.
code
(
RuleLogicCheckTypeVO
.
ALLOW
.
getCode
())
.
info
(
RuleLogicCheckTypeVO
.
ALLOW
.
getInfo
())
.
build
();
// 5. 过滤其他责任链
log
.
info
(
"抽奖责任链-权重放行 userId: {} strategyId: {} ruleModel: {}"
,
userId
,
strategyId
,
ruleModel
());
return
next
().
logic
(
userId
,
strategyId
);
}
@Override
protected
String
ruleModel
()
{
return
"rule_weight"
;
}
private
Map
<
Long
,
String
>
getAnalyticalValue
(
String
ruleValue
)
{
...
...
xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/ILogicFilter.java
→
xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/
filter/
ILogicFilter.java
浏览文件 @
d10092a1
package
cn.bugstack.domain.strategy.service.rule
;
package
cn.bugstack.domain.strategy.service.rule
.filter
;
import
cn.bugstack.domain.strategy.model.entity.RuleActionEntity
;
import
cn.bugstack.domain.strategy.model.entity.RuleMatterEntity
;
...
...
xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/factory/DefaultLogicFactory.java
→
xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/f
ilter/f
actory/DefaultLogicFactory.java
浏览文件 @
d10092a1
package
cn.bugstack.domain.strategy.service.rule.factory
;
package
cn.bugstack.domain.strategy.service.rule.f
ilter.f
actory
;
import
cn.bugstack.domain.strategy.model.entity.RuleActionEntity
;
import
cn.bugstack.domain.strategy.service.annotation.LogicStrategy
;
import
cn.bugstack.domain.strategy.service.rule.ILogicFilter
;
import
cn.bugstack.domain.strategy.service.rule.
filter.
ILogicFilter
;
import
lombok.AllArgsConstructor
;
import
lombok.Getter
;
import
org.springframework.core.annotation.AnnotationUtils
;
...
...
@@ -14,12 +14,13 @@ import java.util.concurrent.ConcurrentHashMap;
/**
* @ClassName: DefaultLogicFactory
* @Description:
* @Description:
规则工厂
* @Author: zhaoyongfeng
* @Date: 2024/11/1
7 16:05
* @Date: 2024/11/1
8 22:27
*/
@Service
public
class
DefaultLogicFactory
{
public
Map
<
String
,
ILogicFilter
<?>>
logicFilterMap
=
new
ConcurrentHashMap
<>();
public
DefaultLogicFactory
(
List
<
ILogicFilter
<?>>
logicFilters
)
{
...
...
@@ -39,13 +40,21 @@ public class DefaultLogicFactory {
@AllArgsConstructor
public
enum
LogicModel
{
RULE_WIGHT
(
"rule_weight"
,
"【抽奖前规则】根据抽奖权重返回可抽奖范围KEY"
),
RULE_BLACKLIST
(
"rule_blacklist"
,
"【抽奖前规则】黑名单规则过滤,命中黑名单则直接返回"
),
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
);
}
}
...
...
xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/
impl/RuleBackList
LogicFilter.java
→
xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/
filter/impl/RuleLock
LogicFilter.java
浏览文件 @
d10092a1
package
cn.bugstack.domain.strategy.service.rule.impl
;
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.ILogicFilter
;
import
cn.bugstack.domain.strategy.service.rule.factory.DefaultLogicFactory
;
import
cn.bugstack.types.common.Constants
;
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
;
/**
* @ClassName: Rule
BackList
LogicFilter
* @Description:
【抽奖前规则】黑名单用户过滤规则
* @ClassName: Rule
Lock
LogicFilter
* @Description:
用户抽奖n次后,对应奖品可解锁抽奖
* @Author: zhaoyongfeng
* @Date: 2024/11/1
7 16:0
7
* @Date: 2024/11/1
8 22:2
7
*/
@Slf4j
@Component
@LogicStrategy
(
logicMode
=
DefaultLogicFactory
.
LogicModel
.
RULE_
BLACKLIST
)
public
class
Rule
BackListLogicFilter
implements
ILogicFilter
<
RuleActionEntity
.
RaffleBefore
Entity
>
{
@LogicStrategy
(
logicMode
=
DefaultLogicFactory
.
LogicModel
.
RULE_
LOCK
)
public
class
Rule
LockLogicFilter
implements
ILogicFilter
<
RuleActionEntity
.
RaffleCenter
Entity
>
{
@Resource
private
IStrategyRepository
repository
;
@Override
public
RuleActionEntity
<
RuleActionEntity
.
RaffleBeforeEntity
>
filter
(
RuleMatterEntity
ruleMatterEntity
)
{
log
.
info
(
"规则过滤-黑名单 userId:{} strategyId:{} ruleModel:{}"
,
ruleMatterEntity
.
getUserId
(),
ruleMatterEntity
.
getStrategyId
(),
ruleMatterEntity
.
getRuleModel
());
// 用户抽奖次数,后续完成这部分流程开发的时候,从数据库/Redis中读取
private
Long
userRaffleCount
=
0L
;
String
userId
=
ruleMatterEntity
.
getUserId
();
@Override
public
RuleActionEntity
<
RuleActionEntity
.
RaffleCenterEntity
>
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
());
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
.<
RuleActionEntity
.
RaffleBeforeEntity
>
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
();
}
long
raffleCount
=
Long
.
parseLong
(
ruleValue
);
// 用户抽奖次数大于规则限定值,规则放行
if
(
userRaffleCount
>=
raffleCount
)
{
return
RuleActionEntity
.<
RuleActionEntity
.
RaffleCenterEntity
>
builder
()
.
code
(
RuleLogicCheckTypeVO
.
ALLOW
.
getCode
())
.
info
(
RuleLogicCheckTypeVO
.
ALLOW
.
getInfo
())
.
build
();
}
return
RuleActionEntity
.<
RuleActionEntity
.
RaffleBeforeEntity
>
builder
()
.
code
(
RuleLogicCheckTypeVO
.
ALLOW
.
getCode
())
.
info
(
RuleLogicCheckTypeVO
.
ALLOW
.
getInfo
())
// 用户抽奖次数小于规则限定值,规则拦截
return
RuleActionEntity
.<
RuleActionEntity
.
RaffleCenterEntity
>
builder
()
.
code
(
RuleLogicCheckTypeVO
.
TAKE_OVER
.
getCode
())
.
info
(
RuleLogicCheckTypeVO
.
TAKE_OVER
.
getInfo
())
.
build
();
}
}
}
xfg-frame-archetype-lite-infrastructure/src/main/java/cn/bugstack/infrastructure/persistent/dao/IStrategyAwardDao.java
浏览文件 @
d10092a1
...
...
@@ -12,4 +12,5 @@ public interface IStrategyAwardDao {
List
<
StrategyAward
>
queryStrategyAwardListByStrategyId
(
Long
strategyId
);
String
queryStrategyAwardRuleModels
(
StrategyAward
strategyAward
);
}
xfg-frame-archetype-lite-infrastructure/src/main/java/cn/bugstack/infrastructure/persistent/po/Strategy.java
浏览文件 @
d10092a1
package
cn.bugstack.infrastructure.persistent.po
;
import
lombok.AllArgsConstructor
;
import
lombok.Builder
;
import
lombok.Data
;
import
lombok.NoArgsConstructor
;
import
java.util.Date
;
...
...
@@ -12,6 +14,8 @@ import java.util.Date;
* @Date: 2024/11/13 20:26
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public
class
Strategy
{
...
...
xfg-frame-archetype-lite-infrastructure/src/main/java/cn/bugstack/infrastructure/persistent/repository/StrategyRepository.java
浏览文件 @
d10092a1
...
...
@@ -4,6 +4,7 @@ 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.repository.IStrategyRepository
;
import
cn.bugstack.infrastructure.persistent.dao.IStrategyAwardDao
;
import
cn.bugstack.infrastructure.persistent.dao.IStrategyDao
;
...
...
@@ -63,7 +64,7 @@ public class StrategyRepository implements IStrategyRepository {
}
@Override
public
void
storeStrategyAwardSearchRateTable
(
String
key
,
Integer
rateRange
,
Map
<
Integer
,
Integer
>
strategyAwardSearchRateTable
)
{
public
void
storeStrategyAwardSearchRateTable
(
String
key
,
int
rateRange
,
Map
<
Integer
,
Integer
>
strategyAwardSearchRateTable
)
{
// 1. 存储抽奖策略范围值,如10000,用于生成1000以内的随机数
redisService
.
setValue
(
Constants
.
RedisKey
.
STRATEGY_RATE_RANGE_KEY
+
key
,
rateRange
);
// 2. 存储概率查找表
...
...
@@ -127,6 +128,22 @@ public class StrategyRepository implements IStrategyRepository {
return
strategyRuleDao
.
queryStrategyRuleValue
(
strategyRule
);
}
@Override
public
String
queryStrategyRuleValue
(
Long
strategyId
,
String
ruleModel
)
{
return
queryStrategyRuleValue
(
strategyId
,
null
,
ruleModel
);
}
@Override
public
StrategyAwardRuleModelVO
queryStrategyAwardRuleModelVO
(
Long
strategyId
,
Integer
awardId
)
{
StrategyAward
strategyAward
=
new
StrategyAward
();
strategyAward
.
setStrategyId
(
strategyId
);
strategyAward
.
setAwardId
(
awardId
);
String
ruleModels
=
strategyAwardDao
.
queryStrategyAwardRuleModels
(
strategyAward
);
return
StrategyAwardRuleModelVO
.
builder
().
ruleModels
(
ruleModels
).
build
();
}
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录