幸运24-额外-根据三天内投产比比较

This commit is contained in:
2025-10-15 17:06:09 +08:00
parent 991a245d41
commit 0c52961043
3 changed files with 89 additions and 41 deletions

View File

@@ -77,13 +77,9 @@ public class Lucky24GiftConfig {
private Integer dayCountLimit; private Integer dayCountLimit;
private List<Integer> timesJudgeArray; private List<Integer> timesJudgeArray;
private Map<String, UserRechargeLevelJudgeConfig> userRechargeLevelJudgeConfigMap; // 今天avg(input)-三天内sum(input)-三天内productionRatio-drawMultiple
private TreeMap<BigDecimal, TreeMap<Long, TreeMap<BigDecimal, Integer>>> judgeConfig;
@Data
public static class UserRechargeLevelJudgeConfig{
private int historyTimes;
private TreeMap<BigDecimal, Integer> productionRatioMultipleMap;
}
} }
} }

View File

@@ -2,18 +2,13 @@ package com.accompany.business.service.lucky;
import com.accompany.business.constant.Lucky24PoolTypeEnum; import com.accompany.business.constant.Lucky24PoolTypeEnum;
import com.accompany.business.dto.lucky.Lucky24GiftConfig; import com.accompany.business.dto.lucky.Lucky24GiftConfig;
import com.accompany.business.dto.lucky.Lucky24Result;
import com.accompany.business.model.Gift; import com.accompany.business.model.Gift;
import com.accompany.common.utils.DateTimeUtil; import com.accompany.common.utils.DateTimeUtil;
import com.accompany.common.utils.RandomUtil;
import com.accompany.core.enumeration.PartitionEnum; import com.accompany.core.enumeration.PartitionEnum;
import com.accompany.core.model.Room; import com.accompany.core.model.Room;
import com.accompany.payment.service.UserRechargeLevelService;
import com.accompany.sharding.model.Lucky24Record; import com.accompany.sharding.model.Lucky24Record;
import com.accompany.sharding.vo.Lucky24StockResultVo; import com.accompany.sharding.vo.Lucky24StockResultVo;
import com.alibaba.fastjson2.JSON;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RList;
import org.redisson.api.RMap; import org.redisson.api.RMap;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@@ -23,6 +18,8 @@ import java.math.RoundingMode;
import java.time.ZonedDateTime; import java.time.ZonedDateTime;
import java.util.*; import java.util.*;
import static com.accompany.business.service.lucky.Lucky24UserMetaService.*;
@Slf4j @Slf4j
@Service @Service
public class Lucky24ExtraService { public class Lucky24ExtraService {
@@ -30,8 +27,6 @@ public class Lucky24ExtraService {
@Autowired @Autowired
private Lucky24ExtraStockService stockService; private Lucky24ExtraStockService stockService;
@Autowired @Autowired
private UserRechargeLevelService userRechargeLevelService;
@Autowired
private Lucky24UserMetaService userMetaService; private Lucky24UserMetaService userMetaService;
@Autowired @Autowired
private Lucky24RobotMsgService robotMsgService; private Lucky24RobotMsgService robotMsgService;
@@ -61,7 +56,7 @@ public class Lucky24ExtraService {
return null; return null;
} }
String todayTimesKey = String.join("_", today, Lucky24UserMetaService.TIMES_KEY); String todayTimesKey = String.join("_", today, TIMES_KEY);
long todayTimes = userMetaSnapshot.getOrDefault(todayTimesKey, 0L).longValue(); long todayTimes = userMetaSnapshot.getOrDefault(todayTimesKey, 0L).longValue();
List<Integer> timesJudgeList = extraPoolConfig.getTimesJudgeArray(); List<Integer> timesJudgeList = extraPoolConfig.getTimesJudgeArray();
@@ -123,37 +118,19 @@ public class Lucky24ExtraService {
public Lucky24Record randomExtraRecord(Lucky24GiftConfig config, Lucky24GiftConfig.Lucky24ExtraPoolConfig extraPoolConfig, 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) { Gift gift, int giftNum, long everyoneGoldNum, Room room, Date sendGiftTime) {
String userRechargeLevel = userRechargeLevelService.getLevelByUid(senderUid); int drawMultiple = drawMultiple(extraPoolConfig, senderUid, partitionId);
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; long afterMultiple = drawMultiple;
// 平台库存 // 平台库存
BigDecimal preWinGoldNum = BigDecimal.valueOf(afterMultiple * everyoneGoldNum); BigDecimal preWinGoldNum = BigDecimal.valueOf(afterMultiple * everyoneGoldNum);
Lucky24StockResultVo stockResultVo = judgeStock(partitionId, preWinGoldNum, senderUid, receiverUid, gift, giftNum, everyoneGoldNum, room, sendGiftTime); Lucky24StockResultVo stockResultVo = judgeStock(partitionId, preWinGoldNum, senderUid, receiverUid, gift, giftNum, everyoneGoldNum, room, sendGiftTime);
if (!stockResultVo.isSuccess()){ if (!stockResultVo.isSuccess()) {
afterMultiple = 0L; afterMultiple = 0L;
} }
long winGoldNum = afterMultiple * everyoneGoldNum; long winGoldNum = afterMultiple * everyoneGoldNum;
if (winGoldNum > 0L){ if (winGoldNum > 0L) {
settlementService.sendReward(config, senderUid, room, gift, winGoldNum, afterMultiple); settlementService.sendReward(config, senderUid, room, gift, winGoldNum, afterMultiple);
} }
@@ -162,9 +139,82 @@ public class Lucky24ExtraService {
log.info("[lucky24] extra uid {} partitionId {} receiverUid {} drawMultiple {} preWinGoldNum {} afterMultiple {} winGoldNum {}", log.info("[lucky24] extra uid {} partitionId {} receiverUid {} drawMultiple {} preWinGoldNum {} afterMultiple {} winGoldNum {}",
senderUid, 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, return recordService.buildRecord(senderUid, partitionId, gift, giftNum, null != room ? room.getUid() : null,
receiverUid, Lucky24PoolTypeEnum.EXTRA_POOL.getType(), null, receiverUid, Lucky24PoolTypeEnum.EXTRA_POOL.getType(), null,
Boolean.FALSE, drawMultiple, afterMultiple, !stockResultVo.isSuccess()? stockResultVo: null, sendGiftTime); Boolean.FALSE, drawMultiple, afterMultiple, !stockResultVo.isSuccess() ? stockResultVo : null, sendGiftTime);
}
public int drawMultiple(Lucky24GiftConfig.Lucky24ExtraPoolConfig extraPoolConfig, long senderUid, Integer partitionId) {
Map<String, Number> userMetaMapSnapshot = userMetaService.getUserMeta(senderUid).readAllMap();
PartitionEnum partitionEnum = PartitionEnum.getByPartitionId(partitionId);
long todayStartTimeLong = DateTimeUtil.getZonedTodayTime(partitionEnum.getZoneId());
String today = String.valueOf(todayStartTimeLong);
String todayTimesKey = String.join("_", today, TIMES_KEY);
long todayTimes = userMetaMapSnapshot.getOrDefault(todayTimesKey, 0L).longValue();
String todayInputKey = String.join("_", today, INPUT_KEY);
long todayInput = userMetaMapSnapshot.getOrDefault(todayInputKey, 0L).longValue();
String todayOutputKey = String.join("_", today, INPUT_KEY);
long todayOutput = userMetaMapSnapshot.getOrDefault(todayOutputKey, 0L).longValue();
// 第一层
// 今天avg(input)
BigDecimal todayAvgInput = todayInput <= 0L? BigDecimal.ZERO:
BigDecimal.valueOf(todayInput).divide(BigDecimal.valueOf(todayTimes), 4, RoundingMode.HALF_UP);
// floor返回小于或等于 key 的最大键值对
Map.Entry<BigDecimal, TreeMap<Long, TreeMap<BigDecimal, Integer>>> inputJudgeEntry = extraPoolConfig.getJudgeConfig().floorEntry(todayAvgInput);
if (null == inputJudgeEntry){
return 0;
}
TreeMap<Long, TreeMap<BigDecimal, Integer>> inputJudgeMap = inputJudgeEntry.getValue();
if (null == inputJudgeMap){
return 0;
}
log.info("[lucky24] extra randomExtra first uid {} partitionId {} todayInput {} todayTimes {} todayAvgInput {} ceilingKey {}",
senderUid, partitionId, todayInput, todayTimes, todayAvgInput.toPlainString(), inputJudgeEntry.getKey());
// 第二层
// 三天内sum(input)
String twoDayAgoInputKey = String.join("_", INPUT_KEY, TWO_DAY_AGO);
long twoDayAgoInput = userMetaMapSnapshot.getOrDefault(twoDayAgoInputKey, 0L).longValue();
long threeDayAgoInput = todayInput + twoDayAgoInput;
// ceiling返回大于或等于 key 的最小键值对
Map.Entry<Long, TreeMap<BigDecimal, Integer>> threeDayAgoInputEntry = inputJudgeMap.ceilingEntry(threeDayAgoInput);
if (null == threeDayAgoInputEntry){
return 0;
}
TreeMap<BigDecimal, Integer> threeDayAgoInputMap = threeDayAgoInputEntry.getValue();
if (null == threeDayAgoInputMap){
return 0;
}
log.info("[lucky24] extra randomExtra second uid {} partitionId {} todayInput {} twoDayAgoInput {} threeDayAgoInput {} floorKey {}",
senderUid, partitionId, todayInput, twoDayAgoInput, threeDayAgoInput, threeDayAgoInputEntry.getKey());
// 第三层
// 三天内productionRation
String twoDayAgoOutputKey = String.join("_", OUTPUT_KEY, TWO_DAY_AGO);
long twoDayAgoOutput = userMetaMapSnapshot.getOrDefault(twoDayAgoOutputKey, 0L).longValue();
long threeDayAgoOutput = todayOutput + twoDayAgoOutput;
BigDecimal threeDayProductionRatio = threeDayAgoOutput <= 0L || threeDayAgoInput <= 0 ? BigDecimal.ZERO:
BigDecimal.valueOf(threeDayAgoOutput).divide(BigDecimal.valueOf(threeDayAgoInput), 4, RoundingMode.HALF_UP);
// floor返回小于或等于 key 的最大键值对
Map.Entry<BigDecimal, Integer> threeDayProductionRatioEntry = threeDayAgoInputMap.ceilingEntry(threeDayProductionRatio);
int drawMultiple = null == threeDayProductionRatioEntry || null == threeDayProductionRatioEntry.getValue()? 0: threeDayProductionRatioEntry.getValue();
log.info("[lucky24] extra randomExtra uid {} partitionId {} todayOutput {} twoDayAgoOutput {} threeDayAgoOutput {} threeDayAgoInput {} productionRation {} floorKey {} result {}",
senderUid, partitionId, todayOutput, twoDayAgoOutput, threeDayAgoOutput, threeDayAgoInput, threeDayProductionRatio.toPlainString(), threeDayAgoInputEntry.getKey(), drawMultiple);
return drawMultiple;
} }
private Lucky24StockResultVo judgeStock(Integer partitionId, BigDecimal winGoldNum, Long senderUid, Long receiverUid, private Lucky24StockResultVo judgeStock(Integer partitionId, BigDecimal winGoldNum, Long senderUid, Long receiverUid,

View File

@@ -28,7 +28,7 @@ public class Lucky24UserMetaService {
public static final String OUTPUT_KEY = "output"; public static final String OUTPUT_KEY = "output";
private static final String TODAY = "today"; private static final String TODAY = "today";
private static final String TWO_DAY_AGO = "two_day_ago"; public static final String TWO_DAY_AGO = "two_day_ago";
public static final String EXTRA_POOL_COUNT = "extra_pool_count"; public static final String EXTRA_POOL_COUNT = "extra_pool_count";
@@ -151,13 +151,15 @@ public class Lucky24UserMetaService {
long todayStartTimeLong = DateTimeUtil.getZonedTodayTime(partitionEnum.getZoneId()); long todayStartTimeLong = DateTimeUtil.getZonedTodayTime(partitionEnum.getZoneId());
String today = String.valueOf(todayStartTimeLong); String today = String.valueOf(todayStartTimeLong);
String todayTimesKey = String.join("_", today, TIMES_KEY);
long todayTimes = userMetaMap.addAndGet(todayTimesKey, 1L).longValue();
String todayInputKey = String.join("_", today, INPUT_KEY); String todayInputKey = String.join("_", today, INPUT_KEY);
long todayInput = userMetaMap.addAndGet(todayInputKey, input).longValue(); long todayInput = userMetaMap.addAndGet(todayInputKey, input).longValue();
String todayOutputKey = String.join("_", today, OUTPUT_KEY); String todayOutputKey = String.join("_", today, OUTPUT_KEY);
long todayOutput = userMetaMap.addAndGet(todayOutputKey, output).longValue(); long todayOutput = userMetaMap.addAndGet(todayOutputKey, output).longValue();
log.info("[Lucky24] updateExtraUserMeta uid {} times {} today {} todayInput {} todayOutput {}", log.info("[Lucky24] updateExtraUserMeta uid {} times {} today {} todayTime {} todayInput {} todayOutput {}",
senderUid, times, todayStartTimeLong, todayInput, todayOutput); senderUid, times, todayStartTimeLong, todayTimes, todayInput, todayOutput);
} }
public void updateUserMeta(long senderUid, int partitionId, long input, long output) { public void updateUserMeta(long senderUid, int partitionId, long input, long output) {
@@ -241,7 +243,7 @@ public class Lucky24UserMetaService {
} }
String twoDayAgoInputKey = String.join("_", INPUT_KEY, TWO_DAY_AGO); String twoDayAgoInputKey = String.join("_", INPUT_KEY, TWO_DAY_AGO);
String twoDayAgoOutputKey = String.join("_", INPUT_KEY, TWO_DAY_AGO); String twoDayAgoOutputKey = String.join("_", OUTPUT_KEY, TWO_DAY_AGO);
// cache // cache
userMetaMap.putAll(Map.of(oldDayInputKey, oldTodayInput, oldDayOutputKey, oldTodayOutput, userMetaMap.putAll(Map.of(oldDayInputKey, oldTodayInput, oldDayOutputKey, oldTodayOutput,