cp榜单发送徽章处理
This commit is contained in:
parent
6a2af57fd3
commit
8ed2a132c2
@ -124,6 +124,7 @@ public class LotteryRecordQryExe {
|
|||||||
prizeCO.setPrizeValue(prize.getPrizeValue());
|
prizeCO.setPrizeValue(prize.getPrizeValue());
|
||||||
prizeCO.setPrizeImage(prize.getPrizeImage());
|
prizeCO.setPrizeImage(prize.getPrizeImage());
|
||||||
prizeCO.setPrizeLevel(prize.getPrizeLevel());
|
prizeCO.setPrizeLevel(prize.getPrizeLevel());
|
||||||
|
prizeCO.setDays(prize.getDays());
|
||||||
co.setPrize(prizeCO);
|
co.setPrize(prizeCO);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
package com.red.circle.other.app.scheduler;
|
package com.red.circle.other.app.scheduler.cp;
|
||||||
|
|
||||||
import com.google.common.collect.Sets;
|
import com.google.common.collect.Sets;
|
||||||
import com.red.circle.other.domain.gateway.user.UserProfileGateway;
|
import com.red.circle.other.domain.gateway.user.UserProfileGateway;
|
||||||
@ -0,0 +1,171 @@
|
|||||||
|
package com.red.circle.other.app.scheduler.cp;
|
||||||
|
|
||||||
|
import com.red.circle.common.business.core.enums.SysOriginPlatformEnum;
|
||||||
|
import com.red.circle.component.redis.annotation.TaskCacheLock;
|
||||||
|
import com.red.circle.mq.business.model.event.BadgeOperateEvent;
|
||||||
|
import com.red.circle.mq.rocket.business.producer.UserMqMessageService;
|
||||||
|
import com.red.circle.other.infra.database.mongo.entity.ranking.RankingRewardSnapshot;
|
||||||
|
import com.red.circle.other.infra.database.mongo.entity.user.count.WeekCpValueCount;
|
||||||
|
import com.red.circle.other.infra.database.mongo.service.user.count.WeekCpValueCountService;
|
||||||
|
import com.red.circle.other.infra.database.rds.entity.badge.BadgeBackpack;
|
||||||
|
import com.red.circle.other.infra.database.rds.service.badge.BadgeBackpackService;
|
||||||
|
import com.red.circle.other.inner.enums.material.BadgeBackpackExpireType;
|
||||||
|
import com.red.circle.other.inner.enums.material.BadgeKeyEnum;
|
||||||
|
import com.red.circle.tool.core.collection.CollectionUtils;
|
||||||
|
import com.red.circle.tool.core.date.TimestampUtils;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.apache.commons.lang3.tuple.ImmutablePair;
|
||||||
|
import org.springframework.scheduling.annotation.Scheduled;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
@Component
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class CpRankingBadgeTask {
|
||||||
|
|
||||||
|
private final WeekCpValueCountService weekCpValueCountService;
|
||||||
|
private final BadgeBackpackService badgeBackpackService;
|
||||||
|
private final UserMqMessageService userMqMessageService;
|
||||||
|
|
||||||
|
// CP排名徽章ID数组:[第一名, 第二名, 第三名]
|
||||||
|
private final static Long[] CP_BADGE_IDS = new Long[]{
|
||||||
|
2012070776778235906L, // 第一名
|
||||||
|
2012070846403682305L, // 第二名
|
||||||
|
2012070905480708098L // 第三名
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 每30秒发放和收回CP排名徽章
|
||||||
|
* 支持用户同时在多对CP中,持有多个排名徽章
|
||||||
|
*/
|
||||||
|
@Scheduled(cron = "0/20 * * * * *", zone = "Asia/Riyadh")
|
||||||
|
@TaskCacheLock(key = "CP_RANKING_BADGE_TASK", expireSecond = 20)
|
||||||
|
public void sendWeekRankingReward() {
|
||||||
|
try {
|
||||||
|
// 1. 获取本周前三名CP对
|
||||||
|
List<WeekCpValueCount> thisWeekTop3 = weekCpValueCountService.listThisWeekTop(SysOriginPlatformEnum.LIKEI.name(), 3);
|
||||||
|
if (CollectionUtils.isEmpty(thisWeekTop3)) {
|
||||||
|
log.warn("CP排名徽章任务:本周前三名数据为空");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 查询所有持有CP排名徽章的用户
|
||||||
|
List<BadgeBackpack> allBackpackList = badgeBackpackService.query()
|
||||||
|
.in(BadgeBackpack::getBadgeId, Arrays.asList(CP_BADGE_IDS))
|
||||||
|
.list()
|
||||||
|
.stream()
|
||||||
|
.filter(CpRankingBadgeTask::filterAvailable)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
// 3. 构建"用户应得徽章集合":Map<userId, Set<badgeId>>
|
||||||
|
// 一个用户可能在多对CP中,所以可以有多个徽章
|
||||||
|
Map<Long, Set<Long>> userShouldHaveBadgesMap = new HashMap<>();
|
||||||
|
|
||||||
|
for (int rank = 0; rank < thisWeekTop3.size() && rank < 3; rank++) {
|
||||||
|
WeekCpValueCount rankingData = thisWeekTop3.get(rank);
|
||||||
|
Long badgeId = CP_BADGE_IDS[rank];
|
||||||
|
|
||||||
|
// 解析该CP对中的两个用户
|
||||||
|
ImmutablePair<Long, Long> userPair = weekCpValueCountService.parseUserIdPair(rankingData.getId());
|
||||||
|
Long userOne = userPair.getLeft();
|
||||||
|
Long userTwo = userPair.getRight();
|
||||||
|
|
||||||
|
// 给两个用户都添加这个徽章到应得集合
|
||||||
|
userShouldHaveBadgesMap.computeIfAbsent(userOne, k -> new HashSet<>()).add(badgeId);
|
||||||
|
userShouldHaveBadgesMap.computeIfAbsent(userTwo, k -> new HashSet<>()).add(badgeId);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. 构建"用户当前持有徽章集合":Map<userId, Set<badgeId>>
|
||||||
|
Map<Long, Set<Long>> userCurrentBadgesMap = new HashMap<>();
|
||||||
|
for (BadgeBackpack backpack : allBackpackList) {
|
||||||
|
userCurrentBadgesMap.computeIfAbsent(backpack.getUserId(), k -> new HashSet<>())
|
||||||
|
.add(backpack.getBadgeId());
|
||||||
|
}
|
||||||
|
|
||||||
|
// 5. 发放缺失的徽章
|
||||||
|
for (Map.Entry<Long, Set<Long>> entry : userShouldHaveBadgesMap.entrySet()) {
|
||||||
|
Long userId = entry.getKey();
|
||||||
|
Set<Long> shouldHaveBadges = entry.getValue();
|
||||||
|
Set<Long> currentBadges = userCurrentBadgesMap.getOrDefault(userId, Collections.emptySet());
|
||||||
|
|
||||||
|
// 找出缺失的徽章(应得但当前没有的)
|
||||||
|
for (Long badgeId : shouldHaveBadges) {
|
||||||
|
if (!currentBadges.contains(badgeId)) {
|
||||||
|
grantBadge(userId, badgeId);
|
||||||
|
int rank = Arrays.asList(CP_BADGE_IDS).indexOf(badgeId) + 1;
|
||||||
|
log.info("CP排名徽章发放:rank={}, userId={}, badgeId={}", rank, userId, badgeId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 6. 收回多余的徽章
|
||||||
|
for (Map.Entry<Long, Set<Long>> entry : userCurrentBadgesMap.entrySet()) {
|
||||||
|
Long userId = entry.getKey();
|
||||||
|
Set<Long> currentBadges = entry.getValue();
|
||||||
|
Set<Long> shouldHaveBadges = userShouldHaveBadgesMap.getOrDefault(userId, Collections.emptySet());
|
||||||
|
|
||||||
|
// 找出多余的徽章(当前有但不应得的)
|
||||||
|
for (Long badgeId : currentBadges) {
|
||||||
|
if (!shouldHaveBadges.contains(badgeId)) {
|
||||||
|
revokeBadge(userId, badgeId);
|
||||||
|
int rank = Arrays.asList(CP_BADGE_IDS).indexOf(badgeId) + 1;
|
||||||
|
log.info("CP排名徽章收回:rank={}, userId={}, badgeId={} (用户不在该排名CP中)",
|
||||||
|
rank, userId, badgeId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
log.info("CP排名徽章任务执行完成:处理{}对CP,涉及{}个用户(可能重复)",
|
||||||
|
thisWeekTop3.size(), userShouldHaveBadgesMap.size());
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("CP排名徽章任务执行异常", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查用户是否已持有该徽章
|
||||||
|
*/
|
||||||
|
private boolean hasUserBadge(List<BadgeBackpack> backpackList, Long userId, Long badgeId) {
|
||||||
|
return backpackList.stream()
|
||||||
|
.anyMatch(b -> Objects.equals(b.getUserId(), userId)
|
||||||
|
&& Objects.equals(b.getBadgeId(), badgeId));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean filterAvailable(BadgeBackpack badgeBackpack) {
|
||||||
|
return Objects.equals(badgeBackpack.getExpireType(),
|
||||||
|
BadgeBackpackExpireType.PERMANENT.name())
|
||||||
|
|| badgeBackpack.getExpireTime().after(TimestampUtils.now());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发放徽章
|
||||||
|
*/
|
||||||
|
private void grantBadge(Long userId, Long badgeId) {
|
||||||
|
BadgeOperateEvent event = new BadgeOperateEvent()
|
||||||
|
.setUserId(userId)
|
||||||
|
.setBadgeId(badgeId)
|
||||||
|
.setDays(1L)
|
||||||
|
.setOperationType(BadgeOperateEvent.OperationType.WEAR.name());
|
||||||
|
|
||||||
|
userMqMessageService.sendBadgeOperateEvent(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 收回徽章
|
||||||
|
*/
|
||||||
|
private void revokeBadge(Long userId, Long badgeId) {
|
||||||
|
BadgeOperateEvent event = new BadgeOperateEvent()
|
||||||
|
.setUserId(userId)
|
||||||
|
.setBadgeId(badgeId)
|
||||||
|
.setDays(1L)
|
||||||
|
.setOperationType(BadgeOperateEvent.OperationType.REMOVE.name());
|
||||||
|
|
||||||
|
userMqMessageService.sendBadgeOperateEvent(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -1,10 +1,9 @@
|
|||||||
package com.red.circle.other.app.scheduler;
|
package com.red.circle.other.app.scheduler.cp;
|
||||||
|
|
||||||
import com.red.circle.common.business.core.enums.SysOriginPlatformEnum;
|
import com.red.circle.common.business.core.enums.SysOriginPlatformEnum;
|
||||||
import com.red.circle.component.redis.annotation.TaskCacheLock;
|
import com.red.circle.component.redis.annotation.TaskCacheLock;
|
||||||
import com.red.circle.other.app.manager.activity.award.CpRankingRewardManager;
|
import com.red.circle.other.app.manager.activity.award.CpRankingRewardManager;
|
||||||
import com.red.circle.other.infra.utils.SeasonUtils;
|
import com.red.circle.other.infra.utils.SeasonUtils;
|
||||||
import com.red.circle.tool.core.date.LocalDateTimeUtils;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.data.redis.core.StringRedisTemplate;
|
import org.springframework.data.redis.core.StringRedisTemplate;
|
||||||
@ -1,12 +1,9 @@
|
|||||||
import com.red.circle.OtherServiceApplication;
|
import com.red.circle.OtherServiceApplication;
|
||||||
import com.red.circle.common.business.core.enums.SysOriginPlatformEnum;
|
import com.red.circle.common.business.core.enums.SysOriginPlatformEnum;
|
||||||
import com.red.circle.common.business.enums.SendPropsOrigin;
|
import com.red.circle.common.business.enums.SendPropsOrigin;
|
||||||
import com.red.circle.other.app.scheduler.CleanExpiredDismissingCpTask;
|
|
||||||
import com.red.circle.other.app.scheduler.DailyTask;
|
|
||||||
import com.red.circle.other.app.scheduler.RankingActivityRewardTask;
|
import com.red.circle.other.app.scheduler.RankingActivityRewardTask;
|
||||||
import com.red.circle.other.app.scheduler.RocketStatusSyncTask;
|
import com.red.circle.other.app.scheduler.RocketStatusSyncTask;
|
||||||
import com.red.circle.other.app.scheduler.activity.GameKingRewardTask;
|
import com.red.circle.other.app.scheduler.cp.CleanExpiredDismissingCpTask;
|
||||||
import com.red.circle.other.app.service.room.RocketStatusCacheService;
|
|
||||||
import com.red.circle.other.inner.endpoint.activity.PropsActivityClient;
|
import com.red.circle.other.inner.endpoint.activity.PropsActivityClient;
|
||||||
import com.red.circle.other.inner.model.cmd.activity.SendActivityRewardCmd;
|
import com.red.circle.other.inner.model.cmd.activity.SendActivityRewardCmd;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user