Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
KnowledgePlanet
road-map
xfg-frame-archetype-lite
提交
d9161499
xfg-frame-archetype-lite
项目概览
KnowledgePlanet
/
road-map
/
xfg-frame-archetype-lite
通知
1165
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看板
提交
d9161499
编写于
4月 11, 2024
作者:
H
hudingrong
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
完成策略权重分配
上级
a4d23f5c
变更
16
隐藏空白更改
内联
并排
Showing
16 changed file
with
351 addition
and
48 deletion
+351
-48
xfg-frame-archetype-lite-app/src/main/resources/mybatis/mapper/strategy_mapper.xml
...app/src/main/resources/mybatis/mapper/strategy_mapper.xml
+6
-0
xfg-frame-archetype-lite-app/src/main/resources/mybatis/mapper/strategy_rule_mapper.xml
...rc/main/resources/mybatis/mapper/strategy_rule_mapper.xml
+5
-0
xfg-frame-archetype-lite-app/src/test/java/cn/bugstack/test/domain/StrategyTest.java
...p/src/test/java/cn/bugstack/test/domain/StrategyTest.java
+20
-4
xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/model/entity/StrategyAwardEntity.java
...ack/domain/strategy/model/entity/StrategyAwardEntity.java
+2
-1
xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/model/entity/StrategyEntity.java
...bugstack/domain/strategy/model/entity/StrategyEntity.java
+42
-0
xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/model/entity/StrategyRuleEntity.java
...tack/domain/strategy/model/entity/StrategyRuleEntity.java
+70
-0
xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/repository/IStrategyRepository.java
...stack/domain/strategy/repository/IStrategyRepository.java
+29
-5
xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/service/armory/IStrategyArmory.java
...stack/domain/strategy/service/armory/IStrategyArmory.java
+2
-7
xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/service/armory/IStrategyDispatch.java
...ack/domain/strategy/service/armory/IStrategyDispatch.java
+24
-0
xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/service/armory/StrategyArmory.java
...gstack/domain/strategy/service/armory/StrategyArmory.java
+58
-19
xfg-frame-archetype-lite-infrastructure/src/main/java/cn/bugstack/infrastructure/persistent/dao/IStrategyDao.java
.../bugstack/infrastructure/persistent/dao/IStrategyDao.java
+7
-0
xfg-frame-archetype-lite-infrastructure/src/main/java/cn/bugstack/infrastructure/persistent/dao/IStrategyRuleDao.java
...stack/infrastructure/persistent/dao/IStrategyRuleDao.java
+6
-0
xfg-frame-archetype-lite-infrastructure/src/main/java/cn/bugstack/infrastructure/persistent/po/Strategy.java
...va/cn/bugstack/infrastructure/persistent/po/Strategy.java
+2
-0
xfg-frame-archetype-lite-infrastructure/src/main/java/cn/bugstack/infrastructure/persistent/repository/StrategyRepository.java
...rastructure/persistent/repository/StrategyRepository.java
+74
-12
xfg-frame-archetype-lite-types/src/main/java/cn/bugstack/types/common/Constants.java
...pes/src/main/java/cn/bugstack/types/common/Constants.java
+3
-0
xfg-frame-archetype-lite-types/src/main/java/cn/bugstack/types/enums/ResponseCode.java
...s/src/main/java/cn/bugstack/types/enums/ResponseCode.java
+1
-0
未找到文件。
xfg-frame-archetype-lite-app/src/main/resources/mybatis/mapper/strategy_mapper.xml
浏览文件 @
d9161499
...
@@ -6,6 +6,7 @@
...
@@ -6,6 +6,7 @@
<id
column=
"id"
property=
"id"
/>
<id
column=
"id"
property=
"id"
/>
<result
column=
"strategy_id"
property=
"strategyId"
/>
<result
column=
"strategy_id"
property=
"strategyId"
/>
<result
column=
"strategy_desc"
property=
"strategyDesc"
/>
<result
column=
"strategy_desc"
property=
"strategyDesc"
/>
<result
column=
"rule_models"
property=
"ruleModels"
/>
<result
column=
"create_time"
property=
"createTime"
/>
<result
column=
"create_time"
property=
"createTime"
/>
<result
column=
"update_time"
property=
"updateTime"
/>
<result
column=
"update_time"
property=
"updateTime"
/>
</resultMap>
</resultMap>
...
@@ -15,5 +16,10 @@
...
@@ -15,5 +16,10 @@
from strategy
from strategy
limit 10
limit 10
</select>
</select>
<select
id=
"queryStrategyByStrategyId"
resultMap=
"dataMap"
>
select strategy_id, strategy_desc, rule_models
from strategy
where strategy_id = #{strategyId}
</select>
</mapper>
</mapper>
xfg-frame-archetype-lite-app/src/main/resources/mybatis/mapper/strategy_rule_mapper.xml
浏览文件 @
d9161499
...
@@ -19,5 +19,10 @@
...
@@ -19,5 +19,10 @@
from strategy_rule
from strategy_rule
limit 10
limit 10
</select>
</select>
<select
id=
"queryStrategyRule"
resultMap=
"dataMap"
>
select strategy_id, award_id, rule_type, rule_model, rule_value, rule_desc
from strategy_rule
where strategy_id = #{strategyId} and rule_model = #{ruleModel}
</select>
</mapper>
</mapper>
xfg-frame-archetype-lite-app/src/test/java/cn/bugstack/test/domain/StrategyTest.java
浏览文件 @
d9161499
package
cn.bugstack.test.domain
;
package
cn.bugstack.test.domain
;
import
cn.bugstack.domain.strategy.service.armory.IStrategyArmory
;
import
cn.bugstack.domain.strategy.service.armory.IStrategyArmory
;
import
cn.bugstack.domain.strategy.service.armory.IStrategyDispatch
;
import
cn.bugstack.infrastructure.persistent.redis.IRedisService
;
import
cn.bugstack.infrastructure.persistent.redis.IRedisService
;
import
lombok.extern.slf4j.Slf4j
;
import
lombok.extern.slf4j.Slf4j
;
import
org.junit.Before
;
import
org.junit.Test
;
import
org.junit.Test
;
import
org.junit.runner.RunWith
;
import
org.junit.runner.RunWith
;
import
org.redisson.api.RMap
;
import
org.redisson.api.RMap
;
...
@@ -25,21 +27,34 @@ public class StrategyTest {
...
@@ -25,21 +27,34 @@ public class StrategyTest {
@Resource
@Resource
private
IStrategyArmory
strategyArmory
;
private
IStrategyArmory
strategyArmory
;
@Resource
private
IStrategyDispatch
strategyDispatch
;
/**
/**
* 策略ID;100001L、100002L 装配的时候创建策略表写入到 Redis Map 中
* 策略ID;100001L、100002L 装配的时候创建策略表写入到 Redis Map 中
*/
*/
@Test
@Test
public
void
test_strategyArmory
()
{
public
void
test_strategyArmory
()
{
strategyArmory
.
assembleLotteryStrategy
(
100002
L
);
boolean
success
=
strategyArmory
.
assembleLotteryStrategy
(
100001
L
);
log
.
info
(
"测试结果:{}"
);
log
.
info
(
"测试结果:{}"
,
success
);
}
}
/**
/**
* 从装配的策略中随机获取奖品ID值
* 从装配的策略中随机获取奖品ID值
*/
*/
@Test
@Test
public
void
test_getAssembleRandomVal
()
{
public
void
test_getRandomAwardId
()
{
log
.
info
(
"测试结果:{} - 奖品ID值"
,
strategyArmory
.
getRandomAwardId
(
100002L
));
log
.
info
(
"测试结果:{} - 奖品ID值"
,
strategyDispatch
.
getRandomAwardId
(
100001L
));
}
/**
* 根据策略ID+权重值,从装配的策略中随机获取奖品ID值
*/
@Test
public
void
test_getRandomAwardId_ruleWeightValue
()
{
log
.
info
(
"测试结果:{} - 4000 策略配置"
,
strategyDispatch
.
getRandomAwardId
(
100001L
,
"4000:102,103,104,105"
));
log
.
info
(
"测试结果:{} - 5000 策略配置"
,
strategyDispatch
.
getRandomAwardId
(
100001L
,
"5000:102,103,104,105,106,107"
));
log
.
info
(
"测试结果:{} - 6000 策略配置"
,
strategyDispatch
.
getRandomAwardId
(
100001L
,
"6000:102,103,104,105,106,107,108,109"
));
}
}
@Resource
@Resource
...
@@ -90,4 +105,5 @@ public class StrategyTest {
...
@@ -90,4 +105,5 @@ public class StrategyTest {
}
}
}
}
}
}
xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/model/entity/StrategyAwardEntity.java
浏览文件 @
d9161499
...
@@ -5,6 +5,7 @@ import lombok.Builder;
...
@@ -5,6 +5,7 @@ import lombok.Builder;
import
lombok.Data
;
import
lombok.Data
;
import
lombok.NoArgsConstructor
;
import
lombok.NoArgsConstructor
;
import
java.io.Serializable
;
import
java.math.BigDecimal
;
import
java.math.BigDecimal
;
/**
/**
...
@@ -17,7 +18,7 @@ import java.math.BigDecimal;
...
@@ -17,7 +18,7 @@ import java.math.BigDecimal;
@Builder
@Builder
@AllArgsConstructor
@AllArgsConstructor
@NoArgsConstructor
@NoArgsConstructor
public
class
StrategyAwardEntity
{
public
class
StrategyAwardEntity
implements
Serializable
{
/** 抽奖策略ID */
/** 抽奖策略ID */
private
Long
strategyId
;
private
Long
strategyId
;
/** 抽奖奖品ID - 内部流转使用 */
/** 抽奖奖品ID - 内部流转使用 */
...
...
xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/model/entity/StrategyEntity.java
0 → 100644
浏览文件 @
d9161499
package
cn.bugstack.domain.strategy.model.entity
;
import
cn.bugstack.types.common.Constants
;
import
lombok.AllArgsConstructor
;
import
lombok.Builder
;
import
lombok.Data
;
import
lombok.NoArgsConstructor
;
import
org.apache.commons.lang3.StringUtils
;
/**
* @description: 策略实体
* @author: hdr
* @PACKAGE_NAME: cn.bugstack.domain.strategy.model.entity
* @DATE: 2024/4/9
*/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public
class
StrategyEntity
{
/** 抽奖策略ID */
private
Long
strategyId
;
/** 抽奖策略描述 */
private
String
strategyDesc
;
/** 抽奖规则模型 rule_weight,rule_blacklist */
private
String
ruleModels
;
public
String
[]
ruleModels
()
{
if
(
StringUtils
.
isBlank
(
ruleModels
))
return
null
;
return
ruleModels
.
split
(
Constants
.
SPLIT
);
}
public
String
getRuleWeight
()
{
String
[]
ruleModels
=
this
.
ruleModels
();
for
(
String
ruleModel
:
ruleModels
)
{
if
(
"rule_weight"
.
equals
(
ruleModel
))
return
ruleModel
;
}
return
null
;
}
}
xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/model/entity/StrategyRuleEntity.java
0 → 100644
浏览文件 @
d9161499
package
cn.bugstack.domain.strategy.model.entity
;
import
cn.bugstack.types.common.Constants
;
import
lombok.AllArgsConstructor
;
import
lombok.Builder
;
import
lombok.Data
;
import
lombok.NoArgsConstructor
;
import
java.util.ArrayList
;
import
java.util.HashMap
;
import
java.util.List
;
import
java.util.Map
;
/**
* @description:
* @author: hdr
* @PACKAGE_NAME: cn.bugstack.domain.strategy.model.entity
* @DATE: 2024/4/9
*/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public
class
StrategyRuleEntity
{
/** 抽奖策略ID */
private
Long
strategyId
;
/** 抽奖奖品ID【规则类型为策略,则不需要奖品ID】 */
private
Integer
awardId
;
/** 抽象规则类型;1-策略规则、2-奖品规则 */
private
Integer
ruleType
;
/** 抽奖规则类型【rule_random - 随机值计算、rule_lock - 抽奖几次后解锁、rule_luck_award - 幸运奖(兜底奖品)】 */
private
String
ruleModel
;
/** 抽奖规则比值 */
private
String
ruleValue
;
/** 抽奖规则描述 */
private
String
ruleDesc
;
/**
* 获取权重值
* 数据案例;4000:102,103,104,105 5000:102,103,104,105,106,107 6000:102,103,104,105,106,107,108,109
*/
public
Map
<
String
,
List
<
Integer
>>
getRuleWeightValues
()
{
if
(!
"rule_weight"
.
equals
(
ruleModel
))
return
null
;
String
[]
ruleValueGroups
=
ruleValue
.
split
(
Constants
.
SPACE
);
Map
<
String
,
List
<
Integer
>>
resultMap
=
new
HashMap
<>();
for
(
String
ruleValueGroup
:
ruleValueGroups
)
{
// 检查输入是否为空
if
(
ruleValueGroup
==
null
||
ruleValueGroup
.
isEmpty
())
{
return
resultMap
;
}
// 分割字符串以获取键和值
String
[]
parts
=
ruleValueGroup
.
split
(
Constants
.
COLON
);
if
(
parts
.
length
!=
2
)
{
throw
new
IllegalArgumentException
(
"rule_weight rule_rule invalid input format"
+
ruleValueGroup
);
}
// 解析值
String
[]
valueStrings
=
parts
[
1
].
split
(
Constants
.
SPLIT
);
List
<
Integer
>
values
=
new
ArrayList
<>();
for
(
String
valueString
:
valueStrings
)
{
values
.
add
(
Integer
.
parseInt
(
valueString
));
}
// 将键和值放入Map中
resultMap
.
put
(
ruleValueGroup
,
values
);
}
return
resultMap
;
}
}
xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/repository/IStrategyRepository.java
浏览文件 @
d9161499
package
cn.bugstack.domain.strategy.repository
;
package
cn.bugstack.domain.strategy.repository
;
import
cn.bugstack.domain.strategy.model.entity.StrategyAwardEntity
;
import
cn.bugstack.domain.strategy.model.entity.StrategyAwardEntity
;
import
cn.bugstack.domain.strategy.model.entity.StrategyEntity
;
import
cn.bugstack.domain.strategy.model.entity.StrategyRuleEntity
;
import
java.math.BigDecimal
;
import
java.math.BigDecimal
;
import
java.util.HashMap
;
import
java.util.HashMap
;
...
@@ -23,11 +25,11 @@ public interface IStrategyRepository {
...
@@ -23,11 +25,11 @@ public interface IStrategyRepository {
List
<
StrategyAwardEntity
>
queryStrategyAwardList
(
Long
strategy
);
List
<
StrategyAwardEntity
>
queryStrategyAwardList
(
Long
strategy
);
/**
/**
* @param
strategyId
策略id
* @param
key
策略id
* @param rateRange 概率
* @param rateRange 概率
* @param shuffleStrategyAwardSearchRateTables 所有保存的概率
* @param shuffleStrategyAwardSearchRateTables 所有保存的概率
*/
*/
void
storeStrategyAwardSearchRateTables
(
Long
strategyId
,
Integer
rateRange
,
HashMap
<
Integer
,
Integer
>
shuffleStrategyAwardSearchRateTables
);
void
storeStrategyAwardSearchRateTables
(
String
key
,
Integer
rateRange
,
HashMap
<
Integer
,
Integer
>
shuffleStrategyAwardSearchRateTables
);
/**
/**
*
*
...
@@ -37,10 +39,32 @@ public interface IStrategyRepository {
...
@@ -37,10 +39,32 @@ public interface IStrategyRepository {
int
getRandomAwardId
(
Long
strategyId
);
int
getRandomAwardId
(
Long
strategyId
);
/**
/**
* 获取
哦
奖品id
* 获取奖品id
* @param
strategyId
* @param
key
* @param nextInt
* @param nextInt
* @return
* @return
*/
*/
Integer
getStrategyAwardAssemble
(
Long
strategyId
,
int
nextInt
);
Integer
getStrategyAwardAssemble
(
String
key
,
int
nextInt
);
/**
* 获取抽奖策略
* @param strategy 策略id
* @return
*/
StrategyEntity
queryStrategyEntityByStrategyId
(
Long
strategy
);
/**
* 查询抽奖策略规则
* @param strategy 策略id
* @param ruleWeight 策略id
* @return
*/
StrategyRuleEntity
queryStrategyRule
(
Long
strategyId
,
String
ruleWeight
);
/**
* 获取概率值
* @param key
* @return
*/
int
getRateRange
(
String
key
);
}
}
xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/service/armory/IStrategyArmory.java
浏览文件 @
d9161499
...
@@ -12,12 +12,7 @@ public interface IStrategyArmory {
...
@@ -12,12 +12,7 @@ public interface IStrategyArmory {
* 抽奖策略
* 抽奖策略
* @param strategy
* @param strategy
*/
*/
void
assembleLotteryStrategy
(
Long
strategy
);
boolean
assembleLotteryStrategy
(
Long
strategy
);
/**
* 获取随机奖品id
* @param strategyId
* @return
*/
Integer
getRandomAwardId
(
Long
strategyId
);
}
}
xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/service/armory/IStrategyDispatch.java
0 → 100644
浏览文件 @
d9161499
package
cn.bugstack.domain.strategy.service.armory
;
/**
* @description: 策略抽奖调度
* @author: hdr
* @PACKAGE_NAME: cn.bugstack.domain.strategy.service.armory
* @DATE: 2024/4/8
*/
public
interface
IStrategyDispatch
{
/**
* 获取随机奖品id
* @param strategyId
* @return
*/
Integer
getRandomAwardId
(
Long
strategyId
);
/**
* 随机获取奖品
* @param strategyId
* @param ruleWeightValue
* @return
*/
Integer
getRandomAwardId
(
Long
strategyId
,
String
ruleWeightValue
);
}
xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/service/armory/StrategyArmory.java
浏览文件 @
d9161499
package
cn.bugstack.domain.strategy.service.armory
;
package
cn.bugstack.domain.strategy.service.armory
;
import
cn.bugstack.domain.strategy.model.entity.StrategyAwardEntity
;
import
cn.bugstack.domain.strategy.model.entity.StrategyAwardEntity
;
import
cn.bugstack.domain.strategy.model.entity.StrategyEntity
;
import
cn.bugstack.domain.strategy.model.entity.StrategyRuleEntity
;
import
cn.bugstack.domain.strategy.repository.IStrategyRepository
;
import
cn.bugstack.domain.strategy.repository.IStrategyRepository
;
import
cn.bugstack.types.enums.ResponseCode
;
import
cn.bugstack.types.exception.AppException
;
import
com.alibaba.fastjson.JSONObject
;
import
lombok.extern.slf4j.Slf4j
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.stereotype.Service
;
import
org.springframework.stereotype.Service
;
...
@@ -10,7 +15,6 @@ import java.math.BigDecimal;
...
@@ -10,7 +15,6 @@ import java.math.BigDecimal;
import
java.math.RoundingMode
;
import
java.math.RoundingMode
;
import
java.security.SecureRandom
;
import
java.security.SecureRandom
;
import
java.util.*
;
import
java.util.*
;
import
java.util.stream.Collectors
;
/**
/**
* @description:
* @description:
...
@@ -20,28 +24,60 @@ import java.util.stream.Collectors;
...
@@ -20,28 +24,60 @@ import java.util.stream.Collectors;
*/
*/
@Slf4j
@Slf4j
@Service
@Service
public
class
StrategyArmory
implements
IStrategyArmory
{
public
class
StrategyArmory
implements
IStrategyArmory
,
IStrategyDispatch
{
@Autowired
@Autowired
private
IStrategyRepository
repository
;
private
IStrategyRepository
repository
;
public
static
void
main
(
String
[]
args
)
{
StrategyArmory
strategyArmory
=
new
StrategyArmory
();
strategyArmory
.
assembleLotteryStrategy
(
100001L
);
}
@Override
@Override
public
void
assembleLotteryStrategy
(
Long
strategy
)
{
public
boolean
assembleLotteryStrategy
(
Long
strategy
)
{
// 1. 查询策略配置
// 1. 查询策略配置
List
<
StrategyAwardEntity
>
awardEntityList
=
repository
.
queryStrategyAwardList
(
strategy
);
List
<
StrategyAwardEntity
>
awardEntityList
=
repository
.
queryStrategyAwardList
(
strategy
);
assembleLotteryStrategy
(
String
.
valueOf
(
strategy
),
awardEntityList
);
// 2. 权重策略陪住 - 使用于 rule_weight 权重规则配置
StrategyEntity
strategyEntity
=
repository
.
queryStrategyEntityByStrategyId
(
strategy
);
System
.
out
.
println
(
JSONObject
.
toJSONString
(
strategyEntity
));
if
(
null
==
strategyEntity
.
getRuleWeight
()||
null
==
strategyEntity
)
return
true
;
String
ruleWeight
=
strategyEntity
.
getRuleWeight
();
// 2.2 查询策略规则
StrategyRuleEntity
strategyRuleEntity
=
repository
.
queryStrategyRule
(
strategy
,
ruleWeight
);
if
(
null
==
strategyRuleEntity
)
{
throw
new
AppException
(
ResponseCode
.
STRATEGY_RULE_WEIGHT_IS_NULL
.
getCode
(),
ResponseCode
.
STRATEGY_RULE_WEIGHT_IS_NULL
.
getInfo
());
}
Map
<
String
,
List
<
Integer
>>
ruleWeightValueMap
=
strategyRuleEntity
.
getRuleWeightValues
();
Set
<
String
>
keys
=
ruleWeightValueMap
.
keySet
();
// 2.3 将获取到的所有 规则写入缓存
for
(
String
key
:
keys
)
{
List
<
Integer
>
ruleWeightValues
=
ruleWeightValueMap
.
get
(
key
);
ArrayList
<
StrategyAwardEntity
>
strategyAwardEntitiesClone
=
new
ArrayList
<>(
awardEntityList
);
strategyAwardEntitiesClone
.
removeIf
(
entity
->
!
ruleWeightValues
.
contains
(
entity
.
getAwardId
()));
assembleLotteryStrategy
(
String
.
valueOf
(
strategy
).
concat
(
"_"
).
concat
(
key
),
strategyAwardEntitiesClone
);
}
return
true
;
// 2. 获取最小概率值
}
BigDecimal
minAwardRate
=
awardEntityList
.
stream
().
map
(
StrategyAwardEntity:
:
getAwardRate
)
private
void
assembleLotteryStrategy
(
String
key
,
List
<
StrategyAwardEntity
>
awardEntityList
)
{
// 1. 获取最小概率值
BigDecimal
minAwardRate
=
awardEntityList
.
stream
()
.
map
(
StrategyAwardEntity:
:
getAwardRate
)
.
min
(
BigDecimal:
:
compareTo
)
.
min
(
BigDecimal:
:
compareTo
)
.
orElse
(
BigDecimal
.
ZERO
);
.
orElse
(
BigDecimal
.
ZERO
);
//
3
. 获取概率值总和
//
2
. 获取概率值总和
BigDecimal
totalAwardRate
=
awardEntityList
.
stream
()
BigDecimal
totalAwardRate
=
awardEntityList
.
stream
()
.
map
(
StrategyAwardEntity:
:
getAwardRate
)
.
map
(
StrategyAwardEntity:
:
getAwardRate
)
.
reduce
(
BigDecimal
.
ZERO
,
BigDecimal:
:
add
);
.
reduce
(
BigDecimal
.
ZERO
,
BigDecimal:
:
add
);
//
4
. 用 1% 0.001获取概率范围,百分位、千分位、万分位
//
3
. 用 1% 0.001获取概率范围,百分位、千分位、万分位
BigDecimal
rateRange
=
totalAwardRate
.
divide
(
minAwardRate
,
0
,
RoundingMode
.
CEILING
);
BigDecimal
rateRange
=
totalAwardRate
.
divide
(
minAwardRate
,
0
,
RoundingMode
.
CEILING
);
...
@@ -50,34 +86,37 @@ public class StrategyArmory implements IStrategyArmory {
...
@@ -50,34 +86,37 @@ public class StrategyArmory implements IStrategyArmory {
Integer
awardId
=
strategyAwardEntity
.
getAwardId
();
Integer
awardId
=
strategyAwardEntity
.
getAwardId
();
BigDecimal
awardRate
=
strategyAwardEntity
.
getAwardRate
();
BigDecimal
awardRate
=
strategyAwardEntity
.
getAwardRate
();
// 5. 计算出每个概率值需要存储到查找表的数量,循环填充
// 4. 计算出每个概率值需要存储到查找表的数量,循环填充
log
.
info
(
"rateRange.multiply(awardRate).setScale(0, RoundingMode.CEILING).intValue()"
+
rateRange
.
multiply
(
awardRate
).
setScale
(
0
,
RoundingMode
.
CEILING
).
intValue
());
for
(
int
i
=
0
;
i
<
rateRange
.
multiply
(
awardRate
).
setScale
(
0
,
RoundingMode
.
CEILING
).
intValue
();
i
++)
{
for
(
int
i
=
0
;
i
<
rateRange
.
multiply
(
awardRate
).
setScale
(
0
,
RoundingMode
.
CEILING
).
intValue
();
i
++)
{
strategyAwardSearchRateTables
.
add
(
awardId
);
strategyAwardSearchRateTables
.
add
(
awardId
);
}
}
//
6
. 乱序
//
5
. 乱序
Collections
.
shuffle
(
strategyAwardSearchRateTables
);
Collections
.
shuffle
(
strategyAwardSearchRateTables
);
//
7.
//
6. 组装抽奖表
HashMap
<
Integer
,
Integer
>
shuffleStrategyAwardSearchRateTables
=
new
HashMap
<>();
HashMap
<
Integer
,
Integer
>
shuffleStrategyAwardSearchRateTables
=
new
HashMap
<>();
for
(
int
i
=
0
;
i
<
strategyAwardSearchRateTables
.
size
();
i
++)
{
for
(
int
i
=
0
;
i
<
strategyAwardSearchRateTables
.
size
();
i
++)
{
shuffleStrategyAwardSearchRateTables
.
put
(
i
,
(
Integer
)
strategyAwardSearchRateTables
.
get
(
i
));
shuffleStrategyAwardSearchRateTables
.
put
(
i
,
(
Integer
)
strategyAwardSearchRateTables
.
get
(
i
));
}
}
log
.
info
(
shuffleStrategyAwardSearchRateTables
.
size
()+
""
);
// 7. 存储到 redis中
// 8. 存储到 redis中
repository
.
storeStrategyAwardSearchRateTables
(
key
,
shuffleStrategyAwardSearchRateTables
.
size
(),
shuffleStrategyAwardSearchRateTables
);
repository
.
storeStrategyAwardSearchRateTables
(
strategy
,
shuffleStrategyAwardSearchRateTables
.
size
(),
shuffleStrategyAwardSearchRateTables
);
}
}
}
}
@Override
@Override
public
Integer
getRandomAwardId
(
Long
strategyId
)
{
public
Integer
getRandomAwardId
(
Long
strategyId
)
{
int
rateRange
=
repository
.
getRandomAwardId
(
strategyId
);
int
rateRange
=
repository
.
getRandomAwardId
(
strategyId
);
return
repository
.
getStrategyAwardAssemble
(
strategyId
,
new
SecureRandom
().
nextInt
(
rateRange
));
return
repository
.
getStrategyAwardAssemble
(
String
.
valueOf
(
strategyId
),
new
SecureRandom
().
nextInt
(
rateRange
));
}
@Override
public
Integer
getRandomAwardId
(
Long
strategyId
,
String
ruleWeightValue
)
{
String
key
=
String
.
valueOf
(
strategyId
).
concat
(
"_"
).
concat
(
ruleWeightValue
);
// 分布式部署下,不一定为当前应用做的策略装配。也就是值不一定会保存到本应用,而是分布式应用,所以需要从 Redis 中获取。
int
rateRange
=
repository
.
getRateRange
(
key
);
// 通过生成的随机值,获取概率值奖品查找表的结果
return
repository
.
getStrategyAwardAssemble
(
key
,
new
SecureRandom
().
nextInt
(
rateRange
));
}
}
}
}
xfg-frame-archetype-lite-infrastructure/src/main/java/cn/bugstack/infrastructure/persistent/dao/IStrategyDao.java
浏览文件 @
d9161499
...
@@ -2,6 +2,7 @@ package cn.bugstack.infrastructure.persistent.dao;
...
@@ -2,6 +2,7 @@ package cn.bugstack.infrastructure.persistent.dao;
import
cn.bugstack.infrastructure.persistent.po.Strategy
;
import
cn.bugstack.infrastructure.persistent.po.Strategy
;
import
org.apache.ibatis.annotations.Mapper
;
import
org.apache.ibatis.annotations.Mapper
;
import
org.apache.ibatis.annotations.Param
;
import
java.util.List
;
import
java.util.List
;
...
@@ -15,4 +16,10 @@ public interface IStrategyDao {
...
@@ -15,4 +16,10 @@ public interface IStrategyDao {
List
<
Strategy
>
queryStrategyList
();
List
<
Strategy
>
queryStrategyList
();
/**
* 通过策略id查询策略
* @param strategyId 策略id
* @return
*/
Strategy
queryStrategyByStrategyId
(
@Param
(
"strategyId"
)
Long
strategyId
);
}
}
xfg-frame-archetype-lite-infrastructure/src/main/java/cn/bugstack/infrastructure/persistent/dao/IStrategyRuleDao.java
浏览文件 @
d9161499
...
@@ -15,4 +15,10 @@ public interface IStrategyRuleDao {
...
@@ -15,4 +15,10 @@ public interface IStrategyRuleDao {
List
<
StrategyRule
>
queryStrategyRuleList
();
List
<
StrategyRule
>
queryStrategyRuleList
();
/**
* 策略规则和策略id查询
* @param strategyRuleReq
* @return
*/
StrategyRule
queryStrategyRule
(
StrategyRule
strategyRuleReq
);
}
}
xfg-frame-archetype-lite-infrastructure/src/main/java/cn/bugstack/infrastructure/persistent/po/Strategy.java
浏览文件 @
d9161499
...
@@ -19,6 +19,8 @@ public class Strategy {
...
@@ -19,6 +19,8 @@ public class Strategy {
private
Long
strategyId
;
private
Long
strategyId
;
/** 抽奖策略描述 */
/** 抽奖策略描述 */
private
String
strategyDesc
;
private
String
strategyDesc
;
/** 抽奖规则模型 rule_weight,rule_blacklist */
private
String
ruleModels
;
/** 创建时间 */
/** 创建时间 */
private
Date
createTime
;
private
Date
createTime
;
/** 更新时间 */
/** 更新时间 */
...
...
xfg-frame-archetype-lite-infrastructure/src/main/java/cn/bugstack/infrastructure/persistent/repository/StrategyRepository.java
浏览文件 @
d9161499
package
cn.bugstack.infrastructure.persistent.repository
;
package
cn.bugstack.infrastructure.persistent.repository
;
import
cn.bugstack.domain.strategy.model.entity.StrategyAwardEntity
;
import
cn.bugstack.domain.strategy.model.entity.StrategyAwardEntity
;
import
cn.bugstack.domain.strategy.model.entity.StrategyEntity
;
import
cn.bugstack.domain.strategy.model.entity.StrategyRuleEntity
;
import
cn.bugstack.domain.strategy.repository.IStrategyRepository
;
import
cn.bugstack.domain.strategy.repository.IStrategyRepository
;
import
cn.bugstack.infrastructure.persistent.dao.IStrategyAwardDao
;
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.StrategyAward
;
import
cn.bugstack.infrastructure.persistent.po.StrategyRule
;
import
cn.bugstack.infrastructure.persistent.redis.IRedisService
;
import
cn.bugstack.infrastructure.persistent.redis.IRedisService
;
import
cn.bugstack.infrastructure.persistent.redis.RedisService
;
import
cn.bugstack.types.common.Constants
;
import
cn.bugstack.types.common.Constants
;
import
com.alibaba.fastjson.JSON
;
import
com.alibaba.fastjson.JSONObject
;
import
lombok.extern.slf4j.Slf4j
;
import
lombok.extern.slf4j.Slf4j
;
import
org.
redisson.misc.Hash
;
import
org.
apache.commons.lang3.ObjectUtils
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.data.redis.core.RedisTemplate
;
import
org.springframework.stereotype.Repository
;
import
org.springframework.stereotype.Repository
;
import
org.springframework.stereotype.Service
;
import
java.math.BigDecimal
;
import
java.lang.reflect.Type
;
import
java.nio.charset.StandardCharsets
;
import
java.util.ArrayList
;
import
java.util.ArrayList
;
import
java.util.HashMap
;
import
java.util.HashMap
;
import
java.util.List
;
import
java.util.List
;
...
@@ -35,11 +43,20 @@ public class StrategyRepository implements IStrategyRepository {
...
@@ -35,11 +43,20 @@ public class StrategyRepository implements IStrategyRepository {
@Autowired
@Autowired
private
IRedisService
redisService
;
private
IRedisService
redisService
;
@Autowired
private
IStrategyDao
strategyDao
;
@Autowired
private
IStrategyRuleDao
strategyRuleDao
;
@Override
@Override
public
List
<
StrategyAwardEntity
>
queryStrategyAwardList
(
Long
strategy
)
{
public
List
<
StrategyAwardEntity
>
queryStrategyAwardList
(
Long
strategy
)
{
// 1. 查询redis中是否有保存策略数据有的话直接返回
// 1. 查询redis中是否有保存策略数据有的话直接返回
String
cacheKey
=
Constants
.
RedisKey
.
STRATEGY_AWARD_KEY
+
strategy
;
String
cacheKey
=
Constants
.
RedisKey
.
STRATEGY_AWARD_KEY
+
strategy
;
List
<
StrategyAwardEntity
>
strategyAwardEntities
=
redisService
.
getValue
(
cacheKey
);
Object
json
=
redisService
.
getValue
(
cacheKey
);
List
<
StrategyAwardEntity
>
strategyAwardEntities
=
JSON
.
parseArray
(
json
.
toString
(),
StrategyAwardEntity
.
class
);
if
(
strategyAwardEntities
!=
null
&&
!
strategyAwardEntities
.
isEmpty
())
{
if
(
strategyAwardEntities
!=
null
&&
!
strategyAwardEntities
.
isEmpty
())
{
return
strategyAwardEntities
;
return
strategyAwardEntities
;
}
}
...
@@ -57,28 +74,73 @@ public class StrategyRepository implements IStrategyRepository {
...
@@ -57,28 +74,73 @@ public class StrategyRepository implements IStrategyRepository {
}).
collect
(
Collectors
.
toList
());
}).
collect
(
Collectors
.
toList
());
// 2.1 保存到redis中
// 2.1 保存到redis中
redisService
.
setValue
(
cacheKey
,
strategyAwardEntityList
);
// redisService.setValue(cacheKey, strategyAwardEntityList);
return
strategyAwardEntityList
;
return
strategyAwardEntityList
;
}
}
@Override
@Override
public
void
storeStrategyAwardSearchRateTables
(
Long
strategyId
,
Integer
rateRange
,
HashMap
<
Integer
,
Integer
>
shuffleStrategyAwardSearchRateTables
)
{
public
void
storeStrategyAwardSearchRateTables
(
String
key
,
Integer
rateRange
,
HashMap
<
Integer
,
Integer
>
shuffleStrategyAwardSearchRateTables
)
{
// 1. 存储概率值
// 1. 存储概率值
redisService
.
setValue
(
Constants
.
RedisKey
.
STRATEGY_RATE_RANGE_KEY
+
strategyId
,
rateRange
.
intValue
());
redisService
.
setValue
(
Constants
.
RedisKey
.
STRATEGY_RATE_RANGE_KEY
+
key
,
rateRange
.
intValue
());
// 2. 存储概率查找表
// 2. 存储概率查找表
Map
<
Integer
,
Integer
>
cacheRateTable
=
redisService
.
getMap
(
Constants
.
RedisKey
.
STRATEGY_RATE_TABLE_KEY
+
strategyId
);
Map
<
Integer
,
Integer
>
cacheRateTable
=
redisService
.
getMap
(
Constants
.
RedisKey
.
STRATEGY_RATE_TABLE_KEY
+
key
);
cacheRateTable
.
putAll
(
shuffleStrategyAwardSearchRateTables
);
cacheRateTable
.
putAll
(
shuffleStrategyAwardSearchRateTables
);
}
}
@Override
@Override
public
int
getRandomAwardId
(
Long
strategyId
)
{
public
int
getRandomAwardId
(
Long
strategyId
)
{
return
redisService
.
getValue
(
Constants
.
RedisKey
.
STRATEGY_RATE_RANGE_KEY
+
strategyId
);
return
getRateRange
(
String
.
valueOf
(
strategyId
));
}
@Override
public
Integer
getStrategyAwardAssemble
(
String
key
,
int
nextInt
)
{
return
redisService
.
getFromMap
(
Constants
.
RedisKey
.
STRATEGY_RATE_TABLE_KEY
+
key
,
nextInt
);
}
@Override
public
StrategyEntity
queryStrategyEntityByStrategyId
(
Long
strategyId
)
{
// 1. 优先从缓存获取
String
cacheKey
=
Constants
.
RedisKey
.
STRATEGY_KEY
+
strategyId
;
Map
<
String
,
Object
>
maps
=
redisService
.
getValue
(
cacheKey
);
StrategyEntity
strategyEntity
=
StrategyEntity
.
builder
()
.
strategyId
(
Long
.
parseLong
(
maps
.
get
(
"strategyId"
).
toString
()))
.
strategyDesc
((
String
)
maps
.
get
(
"strategyDesc"
))
.
ruleModels
((
String
)
maps
.
get
(
"ruleModels"
))
.
build
();
if
(
null
!=
strategyEntity
)
return
strategyEntity
;
// 2. 没有数据从数据库获取
Strategy
strategy
=
strategyDao
.
queryStrategyByStrategyId
(
strategyId
);
strategyEntity
=
StrategyEntity
.
builder
()
.
strategyId
(
strategy
.
getStrategyId
())
.
strategyDesc
(
strategy
.
getStrategyDesc
())
.
ruleModels
(
strategy
.
getRuleModels
())
.
build
();
// 3. 写入缓存
redisService
.
setValue
(
cacheKey
,
strategyEntity
);
return
strategyEntity
;
}
@Override
public
StrategyRuleEntity
queryStrategyRule
(
Long
strategyId
,
String
ruleModel
)
{
StrategyRule
strategyRuleReq
=
new
StrategyRule
();
strategyRuleReq
.
setStrategyId
(
strategyId
);
strategyRuleReq
.
setRuleModel
(
ruleModel
);
StrategyRule
strategyRuleRes
=
strategyRuleDao
.
queryStrategyRule
(
strategyRuleReq
);
return
StrategyRuleEntity
.
builder
()
.
strategyId
(
strategyRuleRes
.
getStrategyId
())
.
awardId
(
strategyRuleRes
.
getAwardId
())
.
ruleType
(
strategyRuleRes
.
getRuleType
())
.
ruleModel
(
strategyRuleRes
.
getRuleModel
())
.
ruleValue
(
strategyRuleRes
.
getRuleValue
())
.
ruleDesc
(
strategyRuleRes
.
getRuleDesc
())
.
build
();
}
}
@Override
@Override
public
Integer
getStrategyAwardAssemble
(
Long
strategyId
,
int
nextInt
)
{
public
int
getRateRange
(
String
key
)
{
return
redisService
.
get
FromMap
(
Constants
.
RedisKey
.
STRATEGY_RATE_TABLE_KEY
+
strategyId
,
nextInt
);
return
redisService
.
get
Value
(
Constants
.
RedisKey
.
STRATEGY_RATE_RANGE_KEY
+
key
);
}
}
}
}
xfg-frame-archetype-lite-types/src/main/java/cn/bugstack/types/common/Constants.java
浏览文件 @
d9161499
...
@@ -3,8 +3,11 @@ package cn.bugstack.types.common;
...
@@ -3,8 +3,11 @@ package cn.bugstack.types.common;
public
class
Constants
{
public
class
Constants
{
public
final
static
String
SPLIT
=
","
;
public
final
static
String
SPLIT
=
","
;
public
final
static
String
COLON
=
":"
;
public
final
static
String
SPACE
=
" "
;
public
static
class
RedisKey
{
public
static
class
RedisKey
{
public
static
final
String
STRATEGY_KEY
=
"big_market_strategy_key_"
;
public
static
String
STRATEGY_AWARD_KEY
=
"big_market_strategy_award_key_"
;
public
static
String
STRATEGY_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_TABLE_KEY
=
"big_market_strategy_rate_table_key_"
;
public
static
String
STRATEGY_RATE_RANGE_KEY
=
"big_market_strategy_rate_range_key_"
;
public
static
String
STRATEGY_RATE_RANGE_KEY
=
"big_market_strategy_rate_range_key_"
;
...
...
xfg-frame-archetype-lite-types/src/main/java/cn/bugstack/types/enums/ResponseCode.java
浏览文件 @
d9161499
...
@@ -12,6 +12,7 @@ public enum ResponseCode {
...
@@ -12,6 +12,7 @@ public enum ResponseCode {
SUCCESS
(
"0000"
,
"成功"
),
SUCCESS
(
"0000"
,
"成功"
),
UN_ERROR
(
"0001"
,
"未知失败"
),
UN_ERROR
(
"0001"
,
"未知失败"
),
ILLEGAL_PARAMETER
(
"0002"
,
"非法参数"
),
ILLEGAL_PARAMETER
(
"0002"
,
"非法参数"
),
STRATEGY_RULE_WEIGHT_IS_NULL
(
"ERR_BIZ_001"
,
"业务异常,策略规则中 rule_weight 权重规则已适用但未配置"
)
;
;
private
String
code
;
private
String
code
;
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录