幸运24-额外-分充值等级取值判断
This commit is contained in:
@@ -6,6 +6,7 @@ import java.math.BigDecimal;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.TreeMap;
|
||||
|
||||
@Data
|
||||
public class Lucky24GiftConfig {
|
||||
@@ -63,11 +64,26 @@ public class Lucky24GiftConfig {
|
||||
private BigDecimal storeRatio;
|
||||
private Integer startHour;
|
||||
private Integer endHour;
|
||||
@Deprecated
|
||||
private Integer inputThreshold;
|
||||
@Deprecated
|
||||
private Set<String> userRechargeLevels;
|
||||
@Deprecated
|
||||
private BigDecimal todayProductionRatio;
|
||||
@Deprecated
|
||||
private Long todayDiff;
|
||||
@Deprecated
|
||||
private Integer twoDayCountLimit;
|
||||
|
||||
private Integer dayCountLimit;
|
||||
private List<Integer> timesJudgeArray;
|
||||
private Map<String, UserRechargeLevelJudgeConfig> userRechargeLevelJudgeConfigMap;
|
||||
|
||||
@Data
|
||||
public static class UserRechargeLevelJudgeConfig{
|
||||
private int historyTimes;
|
||||
private TreeMap<BigDecimal, Integer> productionRatioMultipleMap;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -102,22 +102,24 @@ public class Lucky24GiftSendService {
|
||||
private Map<Long, Lucky24Record> draw(Lucky24GiftConfig config, Lucky24GiftConfig partitionConfig, long senderUid, Integer partitionId,
|
||||
Gift gift, int everyGiftNum, long everyoneGoldNum,
|
||||
List<Long> receiverList, Room room, Date sendGiftTime, boolean extraSwitch) {
|
||||
if (!extraSwitch){
|
||||
if (!extraSwitch
|
||||
|| config.getBlackUidList().contains(senderUid)
|
||||
|| userMetaService.getTimes(senderUid) <= (long) config.getNewUserPoolCount() * config.getPoolSize()){
|
||||
return draw(config, partitionConfig, senderUid, partitionId, gift, everyGiftNum, everyoneGoldNum, receiverList, room, sendGiftTime);
|
||||
}
|
||||
|
||||
Lucky24GiftConfig.Lucky24ExtraPoolConfig extraPoolConfig = partitionConfig.getExtraPoolConfig();
|
||||
Long extraLucker = extraService.selectExtraLucker(extraPoolConfig, senderUid, partitionId, everyoneGoldNum, receiverList);
|
||||
if (null == extraLucker){
|
||||
Long extraLuckerUid = extraService.selectExtraLucker(extraPoolConfig, senderUid, partitionId, receiverList);
|
||||
if (null == extraLuckerUid){
|
||||
return draw(config, partitionConfig, senderUid, partitionId, gift, everyGiftNum, everyoneGoldNum, receiverList, room, sendGiftTime);
|
||||
}
|
||||
|
||||
Lucky24Record extraRecord = extraService.randomExtraRecord(config, senderUid, partitionId, extraLucker, gift, everyGiftNum, everyoneGoldNum, room, sendGiftTime);
|
||||
Lucky24Record extraRecord = extraService.randomExtraRecord(config, extraPoolConfig, senderUid, partitionId, extraLuckerUid, gift, everyGiftNum, everyoneGoldNum, room, sendGiftTime);
|
||||
|
||||
List<Long> receiverUidList = new ArrayList<>(receiverList);
|
||||
receiverUidList.remove(extraLucker);
|
||||
receiverUidList.remove(extraLuckerUid);
|
||||
Map<Long, Lucky24Record> recordMap = draw(config, partitionConfig, senderUid, partitionId, gift, everyGiftNum, everyoneGoldNum, receiverUidList, room, sendGiftTime);
|
||||
recordMap.put(extraLucker, extraRecord);
|
||||
recordMap.put(extraLuckerUid, extraRecord);
|
||||
return recordMap;
|
||||
}
|
||||
|
||||
|
@@ -2,6 +2,7 @@ package com.accompany.business.service.lucky;
|
||||
|
||||
import com.accompany.business.constant.Lucky24PoolTypeEnum;
|
||||
import com.accompany.business.dto.lucky.Lucky24GiftConfig;
|
||||
import com.accompany.business.dto.lucky.Lucky24Result;
|
||||
import com.accompany.business.model.Gift;
|
||||
import com.accompany.common.utils.DateTimeUtil;
|
||||
import com.accompany.common.utils.RandomUtil;
|
||||
@@ -10,7 +11,9 @@ import com.accompany.core.model.Room;
|
||||
import com.accompany.payment.service.UserRechargeLevelService;
|
||||
import com.accompany.sharding.model.Lucky24Record;
|
||||
import com.accompany.sharding.vo.Lucky24StockResultVo;
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.redisson.api.RList;
|
||||
import org.redisson.api.RMap;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
@@ -18,9 +21,7 @@ import org.springframework.stereotype.Service;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.*;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
@@ -38,83 +39,109 @@ public class Lucky24ExtraService {
|
||||
private Lucky24SettlementService settlementService;
|
||||
@Autowired
|
||||
private Lucky24RecordService recordService;
|
||||
|
||||
public BigDecimal addStock(Integer partitionId, BigDecimal addScore) {
|
||||
return stockService.addStock(partitionId, addScore);
|
||||
}
|
||||
|
||||
public Long selectExtraLucker(Lucky24GiftConfig.Lucky24ExtraPoolConfig extraPoolConfig, long senderUid, Integer partitionId, long everyoneGoldNum, List<Long> receiverList) {
|
||||
public Long selectExtraLucker(Lucky24GiftConfig.Lucky24ExtraPoolConfig extraPoolConfig, long senderUid, Integer partitionId, List<Long> receiverList) {
|
||||
PartitionEnum partitionEnum = PartitionEnum.getByPartitionId(partitionId);
|
||||
ZonedDateTime zdt = DateTimeUtil.getDateTimeByZoneId(partitionEnum.getZoneId());
|
||||
if (zdt.getHour() < extraPoolConfig.getStartHour() || zdt.getHour() > extraPoolConfig.getEndHour()){
|
||||
return null;
|
||||
}
|
||||
|
||||
if (everyoneGoldNum < extraPoolConfig.getInputThreshold()){
|
||||
return null;
|
||||
}
|
||||
|
||||
String userRechargeLevel = userRechargeLevelService.getLevelByUid(senderUid);
|
||||
if (!extraPoolConfig.getUserRechargeLevels().contains(userRechargeLevel)){
|
||||
return null;
|
||||
}
|
||||
|
||||
RMap<String, Number> userMetaMap = userMetaService.getUserMeta(senderUid);
|
||||
Map<String, Number> userMetaSnapshot = userMetaMap.readAllMap();
|
||||
long todayStartTimeLong = DateTimeUtil.getZonedTodayTime(partitionEnum.getZoneId());
|
||||
String today = String.valueOf(todayStartTimeLong);
|
||||
String todayInputKey = String.join("_", today, Lucky24UserMetaService.INPUT_KEY);
|
||||
long todayInput = userMetaSnapshot.getOrDefault(todayInputKey, 0L).longValue();
|
||||
String todayOutputKey = String.join("_", today, Lucky24UserMetaService.OUTPUT_KEY);
|
||||
long todayOutput = userMetaSnapshot.getOrDefault(todayOutputKey, 0L).longValue();
|
||||
|
||||
BigDecimal todayProductionRatio = todayInput > 0L && todayOutput > 0L ? BigDecimal.valueOf(todayOutput).divide(BigDecimal.valueOf(todayInput), 4, RoundingMode.HALF_UP) : BigDecimal.ZERO;
|
||||
if (todayProductionRatio.compareTo(extraPoolConfig.getTodayProductionRatio()) >= 0){
|
||||
log.info("[lucky24] extra todayProductionRation fail uid {} partitionId {} todayInput {} todayOutput {} pr {} configPr {}",
|
||||
senderUid, partitionId, todayInput, todayOutput, todayProductionRatio, extraPoolConfig.getTodayProductionRatio());
|
||||
String todayDayCountKey = String.join("_", today, Lucky24UserMetaService.EXTRA_POOL_COUNT);
|
||||
int todayDayCount = userMetaSnapshot.getOrDefault(todayDayCountKey, 0).intValue();
|
||||
if (todayDayCount >= extraPoolConfig.getDayCountLimit()){
|
||||
return null;
|
||||
}
|
||||
|
||||
long todayDiff = todayInput - todayOutput;
|
||||
if (todayDiff < extraPoolConfig.getTodayDiff()){
|
||||
log.info("[lucky24] extra todayDiff fail uid {} partitionId {} todayInput {} todayOutput {} todayDiff {} configTodayDiff {}",
|
||||
senderUid, partitionId, todayInput, todayOutput, todayDiff, extraPoolConfig.getTodayDiff());
|
||||
return null;
|
||||
}
|
||||
String todayTimesKey = String.join("_", today, Lucky24UserMetaService.TIMES_KEY);
|
||||
long todayTimes = userMetaSnapshot.getOrDefault(todayTimesKey, 0L).longValue();
|
||||
|
||||
String yesterday = zdt.minusDays(1L).format(DateTimeUtil.dateFormatter);
|
||||
String lastTwoDayKey = String.join("_", Lucky24UserMetaService.EXTRA_POOL_COUNT, yesterday);
|
||||
int lastTwoDayCount = userMetaSnapshot.getOrDefault(lastTwoDayKey, 0).intValue();
|
||||
if (lastTwoDayCount >= extraPoolConfig.getTwoDayCountLimit()){
|
||||
return null;
|
||||
}
|
||||
List<Integer> timesJudgeList = extraPoolConfig.getTimesJudgeArray();
|
||||
int maxJudgeTimes = timesJudgeList.get(timesJudgeList.size() - 1);
|
||||
|
||||
int expectedValue = lastTwoDayCount + 1;
|
||||
int result = userMetaMap.compute(lastTwoDayKey, (key, currentVal) -> {
|
||||
if (currentVal == null || currentVal.intValue() == lastTwoDayCount) {
|
||||
return expectedValue;
|
||||
Long luckyer = null;
|
||||
|
||||
long todayTimesBefore = todayTimes;
|
||||
for (Long receiver: receiverList){
|
||||
long todayTimesAfter = todayTimesBefore + 1;
|
||||
if (todayTimesBefore < maxJudgeTimes){
|
||||
|
||||
for (Integer judgeTimes: timesJudgeList){
|
||||
if (todayTimesBefore < judgeTimes && todayTimesAfter >= judgeTimes){
|
||||
luckyer = receiver;
|
||||
break;
|
||||
} else if (judgeTimes == maxJudgeTimes && todayTimesAfter >= maxJudgeTimes){
|
||||
long beforeMod = todayTimesBefore % maxJudgeTimes;
|
||||
long afterMod = todayTimesAfter % maxJudgeTimes;
|
||||
if (beforeMod < afterMod){
|
||||
luckyer = receiver;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (null != luckyer){
|
||||
break;
|
||||
}
|
||||
|
||||
} else {
|
||||
long beforeMod = todayTimesBefore % maxJudgeTimes;
|
||||
long afterMod = todayTimesAfter % maxJudgeTimes;
|
||||
if (beforeMod < afterMod){
|
||||
luckyer = receiver;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return currentVal; // 如果当前值不等于期望值,则返回原值,不做修改
|
||||
}).intValue();
|
||||
if (result != expectedValue){
|
||||
log.error("[lucky24] extra cas failure uid {} partitionId {} lastTwoDayKey {} expectedValue {} result {}",
|
||||
senderUid, partitionId, lastTwoDayCount, expectedValue, result);
|
||||
|
||||
todayTimesBefore = todayTimesAfter;
|
||||
}
|
||||
|
||||
if (null == luckyer){
|
||||
return null;
|
||||
}
|
||||
|
||||
String todayKey = String.join("_", Lucky24UserMetaService.EXTRA_POOL_COUNT, zdt.format(DateTimeUtil.dateFormatter));
|
||||
int todayAfter = userMetaMap.addAndGet(todayKey, 1).intValue();
|
||||
// cas 当天剩余额外次数
|
||||
int afterValue = userMetaMap.addAndGet(todayDayCountKey, 1).intValue();
|
||||
if (afterValue > extraPoolConfig.getDayCountLimit()){
|
||||
log.error("[lucky24] extra addAndGet fail uid {} partitionId {} todayDayKey {} afterValue {}", senderUid, partitionId, todayDayCount, afterValue);
|
||||
return null;
|
||||
}
|
||||
|
||||
log.error("[lucky24] extra cas success uid {} partitionId {} lastTwoDayKey {} expectedValue {} result {} todayKey {} todayAfter {} lucker {}",
|
||||
senderUid, partitionId, lastTwoDayKey, expectedValue, result, todayKey, todayAfter, receiverList.get(0));
|
||||
log.info("[lucky24] extra addAndGet true uid {} partitionId {} todayDayKey {} afterValue {}", senderUid, partitionId, todayDayCount, afterValue);
|
||||
|
||||
return receiverList.get(0);
|
||||
return luckyer;
|
||||
}
|
||||
|
||||
public Lucky24Record randomExtraRecord(Lucky24GiftConfig config, long senderUid, Integer partitionId, Long receiverUid,
|
||||
public Lucky24Record randomExtraRecord(Lucky24GiftConfig config, Lucky24GiftConfig.Lucky24ExtraPoolConfig extraPoolConfig, long senderUid, Integer partitionId, Long receiverUid,
|
||||
Gift gift, int giftNum, long everyoneGoldNum, Room room, Date sendGiftTime) {
|
||||
int random = RandomUtil.randomByRange(0, 10);
|
||||
int drawMultiple = random < 5 ? 1000: random < 9 ? 500: 250;
|
||||
|
||||
String userRechargeLevel = userRechargeLevelService.getLevelByUid(senderUid);
|
||||
Lucky24GiftConfig.Lucky24ExtraPoolConfig.UserRechargeLevelJudgeConfig judgeConfig = extraPoolConfig.getUserRechargeLevelJudgeConfigMap().get(userRechargeLevel);
|
||||
|
||||
RList<Lucky24Result> historyQueue = userMetaService.getUserHistoryQueue(senderUid);
|
||||
int historySize = historyQueue.size();
|
||||
int num = Math.min(historySize, judgeConfig.getHistoryTimes());
|
||||
List<Lucky24Result> historyResultList = historyQueue.range(num);
|
||||
|
||||
BigDecimal totalInput = historyResultList.stream().map(Lucky24Result::getInput).map(BigDecimal::valueOf).reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||
BigDecimal totalOutput = historyResultList.stream().map(Lucky24Result::getOutput).map(BigDecimal::valueOf).reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||
BigDecimal totalProductionRatio = totalOutput.compareTo(BigDecimal.ZERO) <= 0 || totalInput.compareTo(BigDecimal.ZERO) <= 0 ? BigDecimal.ZERO:
|
||||
totalOutput.divide(totalInput, 4, RoundingMode.HALF_UP);
|
||||
|
||||
//nullable
|
||||
Map.Entry<BigDecimal, Integer> drawMultipleEntry = judgeConfig.getProductionRatioMultipleMap().ceilingEntry(totalProductionRatio);
|
||||
int drawMultiple = drawMultipleEntry == null ? 0: drawMultipleEntry.getValue();
|
||||
|
||||
log.info("[lucky24] extra randomExtra uid {} partitionId {} totalInput {} totalOutput {} totalProductionRatio {} drawMultipleEntry {} drawMultiple {}",
|
||||
senderUid, partitionId, totalInput, totalOutput, totalProductionRatio, drawMultipleEntry, drawMultiple);
|
||||
|
||||
long afterMultiple = drawMultiple;
|
||||
|
||||
@@ -132,8 +159,8 @@ public class Lucky24ExtraService {
|
||||
|
||||
userMetaService.updateExtraUserMeta(senderUid, partitionId, everyoneGoldNum, winGoldNum);
|
||||
|
||||
log.info("[lucky24] extra uid {} partitionId {} receiverUid {} random {} drawMultiple {} preWinGoldNum {} afterMultiple {} winGoldNum {}",
|
||||
senderUid, partitionId, receiverUid, random, drawMultiple, preWinGoldNum, afterMultiple, winGoldNum);
|
||||
log.info("[lucky24] extra uid {} partitionId {} receiverUid {} drawMultiple {} preWinGoldNum {} afterMultiple {} winGoldNum {}",
|
||||
senderUid, partitionId, receiverUid, drawMultiple, preWinGoldNum, afterMultiple, winGoldNum);
|
||||
|
||||
return recordService.buildRecord(senderUid, partitionId, gift, giftNum, null != room? room.getUid(): null,
|
||||
receiverUid, Lucky24PoolTypeEnum.EXTRA_POOL.getType(), null,
|
||||
|
@@ -25,7 +25,7 @@ import java.util.Set;
|
||||
@Service
|
||||
public class Lucky24UserMetaService {
|
||||
|
||||
private static final String TIMES_KEY = "times";
|
||||
public static final String TIMES_KEY = "times";
|
||||
public static final String INPUT_KEY = "input";
|
||||
public static final String OUTPUT_KEY = "output";
|
||||
|
||||
@@ -181,36 +181,25 @@ public class Lucky24UserMetaService {
|
||||
long todayStartTimeLong = DateTimeUtil.getZonedTodayTime(partitionEnum.getZoneId());
|
||||
|
||||
String today = String.valueOf(todayStartTimeLong);
|
||||
String todayInputKey = String.join("_", today, INPUT_KEY);
|
||||
long todayInput = userMetaMap.addAndGet(todayInputKey, input).longValue();
|
||||
String todayOutputKey = String.join("_", today, OUTPUT_KEY);
|
||||
long todayOutput = userMetaMap.addAndGet(todayOutputKey, output).longValue();
|
||||
String todayTimesKey = String.join("_", today, TIMES_KEY);
|
||||
long todayTimes = userMetaMap.addAndGet(todayTimesKey, 1L).longValue();
|
||||
|
||||
long userMetaToday = userMetaMap.computeIfAbsent(TODAY, k->todayStartTimeLong).longValue();
|
||||
if (userMetaToday < todayStartTimeLong
|
||||
&& userMetaMap.replace(TODAY, userMetaToday, todayStartTimeLong)){
|
||||
// 清理昨天
|
||||
String oldToday = String.valueOf(userMetaToday);
|
||||
String oldTodayTimesKey = String.join("_", oldToday, TIMES_KEY);
|
||||
String oldTodayInputKey = String.join("_", oldToday, INPUT_KEY);
|
||||
String oldTodayOutputKey = String.join("_", oldToday, OUTPUT_KEY);
|
||||
userMetaMap.fastRemove(oldTodayInputKey, oldTodayOutputKey);
|
||||
|
||||
// 清理额外线计数器
|
||||
String todayExtraPoolKey = String.join("_", EXTRA_POOL_COUNT, today);
|
||||
String yesterday = DateTimeUtil.getDateTimeByZoneId(partitionEnum.getZoneId()).minusDays(1L).format(DateTimeUtil.dateFormatter);
|
||||
String yesterdayExtraPoolKey = String.join("_", EXTRA_POOL_COUNT, yesterday);
|
||||
String oldTodayExtraPoolKey = String.join("_", oldToday, EXTRA_POOL_COUNT);
|
||||
|
||||
String extraPoolKeyPattern = EXTRA_POOL_COUNT + "*";
|
||||
Set<String> extraPoolKeySet = userMetaMap.keySet(extraPoolKeyPattern);
|
||||
for (String extraPoolKey : extraPoolKeySet){
|
||||
if (!extraPoolKey.equals(todayExtraPoolKey) && !extraPoolKey.equals(yesterdayExtraPoolKey)){
|
||||
userMetaMap.fastRemove(extraPoolKey);
|
||||
}
|
||||
}
|
||||
userMetaMap.fastRemove(oldTodayTimesKey, oldTodayInputKey, oldTodayOutputKey, oldTodayExtraPoolKey);
|
||||
}
|
||||
|
||||
log.info("[Lucky24] updateUserMeta uid {} times {} today {} todayInput {} todayOutput {}",
|
||||
senderUid, times, todayStartTimeLong, todayInput, todayOutput);
|
||||
log.info("[Lucky24] updateUserMeta uid {} times {} today {} todayTimes {}",
|
||||
senderUid, times, todayStartTimeLong, todayTimes);
|
||||
}
|
||||
|
||||
public RMap<String, Number> getUserMeta(Long uid) {
|
||||
|
Reference in New Issue
Block a user