bravo-super

This commit is contained in:
khalil
2025-03-24 15:30:05 +08:00
parent 9ff12968fc
commit d141758f85
3 changed files with 157 additions and 13 deletions

View File

@@ -10,6 +10,7 @@ import com.accompany.business.service.mq.RocketMQService;
import com.accompany.common.constant.Constant;
import com.accompany.common.redis.RedisKey;
import com.accompany.common.status.BusiStatus;
import com.accompany.common.utils.RandomUtil;
import com.accompany.core.exception.ServiceException;
import com.accompany.core.model.Room;
import com.accompany.core.service.SysConfService;
@@ -20,6 +21,7 @@ import com.baomidou.mybatisplus.core.incrementer.DefaultIdentifierGenerator;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import java.math.BigDecimal;
@@ -53,14 +55,20 @@ public class BravoGiftSendService {
private JedisService jedisService;
private final BigDecimal divisor = new BigDecimal("125");
private final BigDecimal oneThousand = new BigDecimal("1000");
private final BigDecimal fiveHundred = new BigDecimal("500");
public void draw(long senderUid, Integer partitionId, Room room, List<Long> receiverList,
Gift gift, int everyGiftNum, Date sendGiftTime) {
BigDecimal everyoneGoldNum = BigDecimal.valueOf(everyGiftNum).multiply(BigDecimal.valueOf(gift.getGoldPrice()));
BigDecimal everyGiftNumB = BigDecimal.valueOf(everyGiftNum);
BigDecimal everyoneGoldNum = everyGiftNumB.multiply(BigDecimal.valueOf(gift.getGoldPrice()));
int multiple = everyoneGoldNum.divide(divisor, 0, RoundingMode.DOWN).intValue();
int multipleGiftNum = multiple * everyGiftNum;
BigDecimal userNum = BigDecimal.valueOf(receiverList.size());
long totalTimes = everyGiftNumB.multiply(userNum).longValue();
long totalInput = userNum.multiply(everyGiftNumB).longValue();
BravoGiftConfig config = getConfig();
BravoGiftConfig partitionConfig = config.getRatioByPartitionId(partitionId);
SuperLuckyGiftIncomeAllot incomeAllot = incomeAllotService.calculate(partitionConfig, gift, everyGiftNum, receiverList);
@@ -70,19 +78,57 @@ public class BravoGiftSendService {
log.info("[brave] uid {}, partitionId {}, addStockGoldNum {}, afterStock {}",
senderUid, partitionId, incomeAllot.getRemainValue(), afterStock);
Map<Long, BravoRecord> recordMap = draw(config, senderUid, partitionId, gift, everyGiftNum, everyoneGoldNum, divisor, multipleGiftNum, receiverList, room, sendGiftTime);
int userTicketNum = userMetaService.updateUserMetaBefore(senderUid, totalTimes, totalInput);
Map<Long, BravoRecord> recordMap = draw(config, senderUid, partitionId, gift, everyGiftNum, everyoneGoldNum,
divisor, multiple, multipleGiftNum, userTicketNum, receiverList, room, sendGiftTime);
log.info("[brave] uid {}, totalWinGoldNum {}", senderUid, JSON.toJSONString(recordMap));
sendMq(recordMap);
}
public Map<Long, BravoRecord> draw(BravoGiftConfig config, Long senderUid, int partitionId,
Gift gift, int everyGiftNum, BigDecimal totalInput, BigDecimal divisor, int multipleGiftNum,
List<Long> receiverList, Room room, Date sendGiftTime) {
Gift gift, int everyGiftNum, BigDecimal everyInput, BigDecimal divisor, int multiple, int multipleGiftNum,
int userTicketNum, List<Long> receiverList, Room room, Date sendGiftTime) {
if (multipleGiftNum > 1 && userTicketNum > 1){
int needTicketNum = multipleGiftNum == 2? 1 : multipleGiftNum == 4 ? 2 : 8;
int superNum = Math.min(userTicketNum / needTicketNum, receiverList.size());
if (superNum < 1){
return drawMultiple(config, senderUid, partitionId, gift, everyGiftNum, everyInput, divisor, multipleGiftNum, receiverList, room, sendGiftTime);
}
int superTicketNum = needTicketNum * superNum;
int subSuperNum = userMetaService.subSuperNum(senderUid, needTicketNum, superNum, superTicketNum);
if (subSuperNum < 1){
return drawMultiple(config, senderUid, partitionId, gift, everyGiftNum, everyInput, divisor, multipleGiftNum, receiverList, room, sendGiftTime);
}
superNum = subSuperNum;
List<Long> superGrilList = receiverList.subList(0, superNum);
receiverList.removeAll(superGrilList);
if (CollectionUtils.isEmpty(receiverList)){
return drawSuper(config, senderUid, partitionId, gift, everyGiftNum, everyInput, multiple, superGrilList, room, sendGiftTime);
}
Map<Long, BravoRecord> recordMap = new HashMap<>();
recordMap.putAll(drawSuper(config, senderUid, partitionId, gift, everyGiftNum, everyInput, multiple, superGrilList, room, sendGiftTime));
recordMap.putAll(drawMultiple(config, senderUid, partitionId, gift, everyGiftNum, everyInput, divisor, multipleGiftNum, receiverList, room, sendGiftTime));
return recordMap;
}
return drawMultiple(config, senderUid, partitionId, gift, everyGiftNum, everyInput, divisor, multipleGiftNum, receiverList, room, sendGiftTime);
}
private Map<Long, BravoRecord> drawSuper(BravoGiftConfig config, Long senderUid, int partitionId, Gift gift, int giftNum,
BigDecimal everyInput, int multiple, List<Long> superGrilList, Room room, Date sendGiftTime) {
return superGrilList.parallelStream()
.collect(Collectors.toMap(receiverUid-> receiverUid,
receiverUid-> drawSuper(config, senderUid, partitionId, gift, giftNum, receiverUid, everyInput, divisor, multiple, room, sendGiftTime)));
}
private Map<Long, BravoRecord> drawMultiple(BravoGiftConfig config, Long senderUid, int partitionId, Gift gift, int everyGiftNum, BigDecimal everyInput, BigDecimal divisor, int multipleGiftNum, List<Long> receiverList, Room room, Date sendGiftTime){
return receiverList.parallelStream()
.collect(Collectors.toMap(receiverUid-> receiverUid,
receiverUid-> drawMultiple(config, senderUid, partitionId, gift, everyGiftNum,
receiverUid, totalInput, divisor, multipleGiftNum, room, sendGiftTime)));
receiverUid, everyInput, divisor, multipleGiftNum, room, sendGiftTime)));
}
private void sendMq(Map<Long, BravoRecord> recordMap) {
@@ -119,12 +165,52 @@ public class BravoGiftSendService {
rocketMQService.sendBatchBravoMessage(messageList);
}
public BravoRecord drawSuper(BravoGiftConfig config, long senderUid, int partitionId, Gift gift, int giftNum, long receiverUid, BigDecimal everyInput,
BigDecimal divisor, int multiple, Room room, Date sendGiftTime) {
BravoResult drawResult = new BravoResult();
drawResult.setInput(everyInput);
drawResult.setOutput(BigDecimal.ZERO);
int random = RandomUtil.randomByRange(0, 10);
if (random < 3){
BigDecimal superMultiple = multiple >= 8? oneThousand: fiveHundred;
BigDecimal output = everyInput.multiply(superMultiple);
drawResult.setOutput(output);
log.info("[bravo] super yes, uid {} receiver {} random {} multiple {} superMultiple {} output {} ",
senderUid, receiverUid, random, multiple, superMultiple, output);
}
return updateMeta(config, senderUid, partitionId, gift, giftNum, receiverUid, everyInput, divisor, room, sendGiftTime, drawResult);
}
public BravoRecord drawMultiple(BravoGiftConfig config, long senderUid, int partitionId,
Gift gift, int giftNum, long receiverUid, BigDecimal totalInput, BigDecimal divisor, int multipleGiftNum, Room room, Date sendGiftTime) {
List<BravoResult> drawResultList = poolService.drawMultipleFromPool(config, senderUid, partitionId, multipleGiftNum);
return updateMeta(config, senderUid, partitionId, gift, giftNum, receiverUid, totalInput, divisor, room, sendGiftTime, drawResultList);
}
private BravoRecord updateMeta(BravoGiftConfig config, long senderUid, int partitionId,
Gift gift, int giftNum, long receiverUid, BigDecimal totalInput, BigDecimal divisor, Room room, Date sendGiftTime,
BravoResult drawResult){
BigDecimal afterMultiple = drawResult.getOutput();
// 平台库存
if (afterMultiple.compareTo(BigDecimal.ZERO) > 0L){
BigDecimal preWinGoldNum = afterMultiple.multiply(divisor);
if (!judgeStock(partitionId, preWinGoldNum, senderUid, receiverUid)){
afterMultiple = BigDecimal.ZERO;
}
}
drawResult.setAfterOutput(afterMultiple);
BigDecimal winGoldNum = afterMultiple.multiply(divisor);
userMetaService.updateUserMetaAfter(senderUid, totalInput, winGoldNum);
if (winGoldNum.compareTo(BigDecimal.ZERO) > 0){
settlementService.syncSendReward(config, senderUid, room, gift, winGoldNum, afterMultiple);
}
return recordService.buildRecord(senderUid, partitionId, gift, giftNum, null != room? room.getUid(): null,
receiverUid,false, afterMultiple, winGoldNum, sendGiftTime);
}
private BravoRecord updateMeta(BravoGiftConfig config, long senderUid, int partitionId,
Gift gift, int giftNum, long receiverUid, BigDecimal totalInput, BigDecimal divisor, Room room, Date sendGiftTime,
List<BravoResult> drawResultList){
@@ -142,7 +228,7 @@ public class BravoGiftSendService {
BigDecimal multiple = drawResultList.stream().map(BravoResult::getAfterOutput).reduce(BigDecimal.ZERO, BigDecimal::add);
BigDecimal winGoldNum = multiple.multiply(divisor);
userMetaService.updateUserMeta(senderUid, totalInput, winGoldNum);
userMetaService.updateUserMetaAfter(senderUid, totalInput, winGoldNum);
if (winGoldNum.compareTo(BigDecimal.ZERO) > 0){
settlementService.syncSendReward(config, senderUid, room, gift, winGoldNum, multiple);

View File

@@ -36,6 +36,24 @@ public class BravoRecordService extends ServiceImpl<BravoRecordMapper, BravoReco
@Resource(name = "bizExecutor")
private ThreadPoolExecutor bizExecutor;
public BravoRecord buildRecord(long senderUid, int partitionId, Gift gift, int giftNum, Long roomUid, long receiverUid,
boolean isSupplement, BigDecimal afterMultiple, BigDecimal winGoldNum, Date sendGiftTime) {
BravoRecord record = new BravoRecord();
record.setUid(senderUid);
record.setPartitionId(partitionId);
record.setReceiverUid(receiverUid);
record.setRoomUid(roomUid);
record.setGiftId(gift.getGiftId());
record.setGiftNum(giftNum);
record.setGiftGoldPrice(gift.getGoldPrice());
record.setResultGroupByPool(null);
record.setIsSupplement(isSupplement);
record.setAfterMultiple(afterMultiple);
record.setWinGoldNum(winGoldNum);
record.setCreateTime(sendGiftTime);
return record;
}
public BravoRecord buildRecord(long senderUid, int partitionId, Gift gift, int giftNum, Long roomUid, long receiverUid, List<BravoResult> resultList,
boolean isSupplement, BigDecimal afterMultiple, BigDecimal winGoldNum, Date sendGiftTime) {
BravoRecord record = new BravoRecord();

View File

@@ -1,7 +1,6 @@
package com.accompany.business.service.lucky;
import com.accompany.business.dto.lucky.BravoResult;
import com.accompany.business.dto.lucky.Lucky24Result;
import com.accompany.common.redis.RedisKey;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RList;
@@ -23,8 +22,10 @@ public class BravoUserMetaService {
private static final String TIMES_KEY = "times";
public static final String INPUT_KEY = "input";
public static final String OUTPUT_KEY = "output";
public static final String TICKET_NUM_KEY = "ticket_num";
private static final int HISTORY_QUEUE_SIZE = 2000;
private static final long TICKET_PRICE = 2000000L;
@Autowired
private RedissonClient redissonClient;
@@ -60,18 +61,37 @@ public class BravoUserMetaService {
return productionRatio;
}
public void updateUserMeta(long senderUid, BigDecimal input, BigDecimal output) {
public int updateUserMetaBefore(long senderUid, long num, long input) {
RMap<String, Number> userMetaMap = getUserMeta(senderUid);
long times = userMetaMap.addAndGet(TIMES_KEY, num).longValue();
long totalInputAfter = userMetaMap.addAndGet(INPUT_KEY, input).longValue();
long totalInputBefore = totalInputAfter - input;
long addTicketNum = 0L;
int remainTicketNum = 0;
long ticketNumAfter = totalInputAfter / TICKET_PRICE;
long tickerNumBefore = totalInputBefore / TICKET_PRICE;
if (ticketNumAfter > tickerNumBefore) {
addTicketNum = ticketNumAfter - tickerNumBefore;
remainTicketNum = userMetaMap.addAndGet(TICKET_NUM_KEY, addTicketNum).intValue();
}
log.info("[bravo] updateUserMetaBefore uid {} times {} totalInput {} addTicketNum {} remainTicketNum {}",
senderUid, times, totalInputAfter, addTicketNum, remainTicketNum);
return remainTicketNum;
}
public void updateUserMetaAfter(long senderUid, BigDecimal input, BigDecimal output) {
RList<BravoResult> historyQueue = getUserHistoryQueue(senderUid);
historyQueue.add(0, new BravoResult(null, input, output, null, null));
historyQueue.expireAsync(Duration.of(14, ChronoUnit.DAYS));
RMap<String, Number> userMetaMap = getUserMeta(senderUid);
long times = userMetaMap.addAndGet(TIMES_KEY, 1L).longValue();
long totalInput = userMetaMap.addAndGet(INPUT_KEY, input).longValue();
long totalOutput = userMetaMap.addAndGet(OUTPUT_KEY, output).longValue();
log.info("[bravo] updateUserMeta uid {} times {} totalInput {} totalOutput {}",
senderUid, times, totalInput, totalOutput);
log.info("[bravo] updateUserMetaAfter uid {} totalOutput {}",
senderUid, totalOutput);
}
public RMap<String, Number> getUserMeta(Long uid) {
@@ -82,4 +102,24 @@ public class BravoUserMetaService {
return redissonClient.getList(RedisKey.bravo_user_history.getKey(uid.toString()));
}
public int subSuperNum(long uid, int needTicketNum, int superNum, int superTicketNum) {
RMap<String, Number> userMetaMap = getUserMeta(uid);
int afterNum = userMetaMap.addAndGet(TICKET_NUM_KEY, -superTicketNum).intValue();
if (afterNum >= 0){
return superNum;
}
for (int i = superNum - 1; i > 0; i--) {
afterNum += needTicketNum;
if (afterNum >= 0){
int returnNum = superNum - i;
int returnTicketNum = returnNum * needTicketNum;
int userTicketNumAfterReturn = userMetaMap.addAndGet(TICKET_NUM_KEY, returnTicketNum).intValue();
log.info("[bravo] subTicketNum uid {} not enough ticket num, return {} {} after {}", uid, returnNum, returnTicketNum, userTicketNumAfterReturn);
return i;
}
}
int userTicketNumAfterReturn = userMetaMap.addAndGet(TICKET_NUM_KEY, superTicketNum).intValue();
log.info("[bravo] subTicketNum uid {} not enough ticket num, return all {} after {}", uid, superTicketNum, userTicketNumAfterReturn);
return 0;
}
}