时空幸运儿活动-实现

This commit is contained in:
khalil
2023-12-08 14:39:38 +08:00
parent 34b3f70db7
commit 7c4233fba4
10 changed files with 410 additions and 6 deletions

View File

@@ -6,16 +6,11 @@ import lombok.Data;
@Data @Data
@ApiModel @ApiModel
public class ActivityRankItemVo { public class ActivityRankItemVo extends ActivityUserVo {
@ApiModelProperty("排名0=未上榜)") @ApiModelProperty("排名0=未上榜)")
private Integer ranking; private Integer ranking;
@ApiModelProperty("得分") @ApiModelProperty("得分")
private Long score; private Long score;
private Long uid;
private Long erbanNo;
private String nick;
private String avatar;
} }

View File

@@ -0,0 +1,20 @@
package com.accompany.business.common.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@ApiModel
@AllArgsConstructor
@NoArgsConstructor
public class ActivityUserVo {
private Long uid;
private Long erbanNo;
private String nick;
private String avatar;
}

View File

@@ -0,0 +1,12 @@
package com.accompany.business.luckyprocessbar.constant;
public class LuckyProcessBarConstant {
public static String actName = "act_lucky_process_bar_2023";
public static class SysConfId {
public static final String ACT_CONFIG = actName + "_config";
}
public static String LUCKY_TIP = "恭喜您在【时空幸运儿】成为第%d个幸运儿获得奖励奖励已经发放至您的背包注意查收哦~";
}

View File

@@ -0,0 +1,28 @@
package com.accompany.business.luckyprocessbar.dto;
import com.accompany.business.common.dto.RewardDto;
import com.accompany.business.common.dto.TimeRangeActConfigDto;
import lombok.Data;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Set;
@Data
public class LuckyProcessBarConfigDto extends TimeRangeActConfigDto {
private Set<Integer> giftIds;
private Map<Long, StageReward> stageRewardMap;
@Data
public static class StageReward {
private Long stage;
private List<RewardDto> rewardList;
}
public Long getMax(){
return stageRewardMap.keySet().stream().max(Comparator.comparing(Long::longValue)).get();
}
}

View File

@@ -0,0 +1,17 @@
package com.accompany.business.luckyprocessbar.model;
import lombok.Data;
import java.io.Serializable;
@Data
public class LuckyProcessBarRewardRecord implements Serializable {
private String date;
private Long uid;
private Byte type;
private Integer taskId;
private Integer proc;
private Integer need;
}

View File

@@ -0,0 +1,39 @@
package com.accompany.business.luckyprocessbar.vo;
import com.accompany.business.common.vo.ActivityRankItemVo;
import com.accompany.business.common.vo.ActivityUserVo;
import com.accompany.business.common.vo.RewardVo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.Date;
import java.util.List;
import java.util.Map;
@ApiModel
@Data
public class LuckyProcessBarConfigVo {
@ApiModelProperty("开始时间")
private Date startTime;
@ApiModelProperty("结束时间")
private Date endTime;
@ApiModelProperty("用户uid")
private Long uid;
@ApiModelProperty("上限")
private Long max;
@ApiModelProperty("当前")
private Long cur;
@ApiModelProperty("stage")
private Map<Long, StageReward> stageMap;
@Data
public static class StageReward {
private Long stage;
private ActivityUserVo luckyUser;
//private List<RewardVo> rewardList;
}
}

View File

@@ -0,0 +1,50 @@
package com.accompany.business.luckyprocessbar.listener;
import com.accompany.business.event.GiftMessageEvent;
import com.accompany.business.luckyprocessbar.dto.LuckyProcessBarConfigDto;
import com.accompany.business.luckyprocessbar.service.LuckyProcessBarService;
import com.accompany.business.message.GiftMessage;
import com.accompany.common.utils.DateTimeUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationListener;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import java.time.LocalDateTime;
import java.util.Date;
@Slf4j
@Component
public class LuckyProcessBarGiftListener implements ApplicationListener<GiftMessageEvent> {
@Autowired
private LuckyProcessBarService service;
@Override
@Async
public void onApplicationEvent(GiftMessageEvent giftMessageEvent) {
GiftMessage giftMessage = (GiftMessage) giftMessageEvent.getSource();
Date sendGiftTime = DateTimeUtil.convertMsToDate(giftMessage.getMessTime());
LocalDateTime sendGiftLocalDateTime = DateTimeUtil.converDateToLocalDateTime(sendGiftTime);
LuckyProcessBarConfigDto config = service.getConfig();
if (!config.inActTimeRange(sendGiftLocalDateTime)){
return;
}
Integer giftId = giftMessage.getGiftId();
if (CollectionUtils.isEmpty(config.getGiftIds()) || !config.getGiftIds().contains(giftId)) {
return;
}
// 送礼人Uid
Long sendUid = giftMessage.getSendUid();
String giftRecordId = giftMessage.getMessId();
Integer giftNum = giftMessage.getGiftNum();
service.process(config, sendUid, giftRecordId, giftId, giftNum);
}
}

View File

@@ -0,0 +1,61 @@
package com.accompany.business.luckyprocessbar.service;
import com.accompany.business.doubleeleven.DoubleElevenTaskDao;
import com.accompany.business.doubleeleven.model.DoubleElevenTaskRecord;
import com.accompany.business.mapper.DoubleElevenTaskRecordDao;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@Service
@Slf4j
public class LuckyProcessBarRewardRecordService extends ServiceImpl<DoubleElevenTaskRecordDao, DoubleElevenTaskRecord> {
@Autowired
private DoubleElevenTaskDao dao;
public void writeDb() {
List<DoubleElevenTaskRecord> dailyTaskRecord = new ArrayList<>();
Map<String, Integer> dailyTaskMap = dao.getAllUserDailyTaskProgress();
for (String key: dailyTaskMap.keySet()) {
String[] keys = key.split("_");
Long uid = Long.parseLong(keys[0]);
String date = keys[1];
Integer taskId = Integer.parseInt(keys[2]);
Integer proc = dailyTaskMap.get(key);
DoubleElevenTaskRecord record = new DoubleElevenTaskRecord();
record.setDate(date);
record.setUid(uid);
record.setTaskId(taskId);
record.setType((byte) 1);
record.setProc(proc);
dailyTaskRecord.add(record);
}
saveBatch(dailyTaskRecord);
List<DoubleElevenTaskRecord> loopTaskRecord = new ArrayList<>();
Map<String, Integer> loopTaskMap = dao.getAllUserLoopTaskProgress();
for (String key: loopTaskMap.keySet()) {
String[] keys = key.split("_");
Long uid = Long.parseLong(keys[0]);
String date = keys[1];
Integer taskId = Integer.parseInt(keys[2]);
Integer proc = loopTaskMap.get(key);
DoubleElevenTaskRecord record = new DoubleElevenTaskRecord();
record.setDate(date);
record.setUid(uid);
record.setTaskId(taskId);
record.setType((byte) 2);
record.setProc(proc);
loopTaskRecord.add(record);
}
saveBatch(loopTaskRecord);
}
}

View File

@@ -0,0 +1,146 @@
package com.accompany.business.luckyprocessbar.service;
import com.accompany.business.common.dto.RewardDto;
import com.accompany.business.common.vo.ActivityUserVo;
import com.accompany.business.luckyprocessbar.constant.LuckyProcessBarConstant;
import com.accompany.business.luckyprocessbar.dto.LuckyProcessBarConfigDto;
import com.accompany.business.luckyprocessbar.vo.LuckyProcessBarConfigVo;
import com.accompany.business.qixi.common.RewardUtil;
import com.accompany.business.service.SendSysMsgService;
import com.accompany.business.service.user.UsersService;
import com.accompany.common.config.SystemConfig;
import com.accompany.common.constant.AppEnum;
import com.accompany.common.status.BusiStatus;
import com.accompany.common.utils.DateTimeUtil;
import com.accompany.core.exception.ServiceException;
import com.accompany.core.model.Users;
import com.accompany.core.service.SysConfService;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RAtomicLong;
import org.redisson.api.RMap;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import java.util.*;
import java.util.stream.Collectors;
@Service
@Slf4j
public class LuckyProcessBarService implements InitializingBean {
@Autowired
private RedissonClient redissonClient;
private RAtomicLong process;
private RMap<Long, Long> luckyUserMap;
@Autowired
private SysConfService sysConfService;
@Autowired
private UsersService usersService;
@Autowired
private RewardUtil rewardUtil;
@Autowired
private SendSysMsgService sendSysMsgService;
@Async
public void sendSecretMsg(Long uid, Long stage) {
String tip = String.format(LuckyProcessBarConstant.LUCKY_TIP, stage);
sendSysMsgService.sendPersonTextMsg(SystemConfig.secretaryUid, uid, tip);
}
public LuckyProcessBarConfigVo getConfigVo(Long uid){
LuckyProcessBarConfigDto dto = getConfig();
LuckyProcessBarConfigVo vo = new LuckyProcessBarConfigVo();
vo.setUid(uid);
vo.setStartTime(DateTimeUtil.localDateTime2Date(dto.getStartTime()));
vo.setEndTime(DateTimeUtil.localDateTime2Date(dto.getEndTime()));
vo.setMax(dto.getMax());
vo.setCur(process.get());
Map<Long, Long> luckyUidMap = luckyUserMap.readAllMap();
Map<Long, Users> usersMap = CollectionUtils.isEmpty(luckyUidMap)?
Collections.emptyMap():
usersService.getUsersMapByUids(luckyUidMap.values().stream().distinct().collect(Collectors.toList()));
Map<Long, LuckyProcessBarConfigVo.StageReward> stageRewardMap = dto.getStageRewardMap().values().stream().map(stageReward->{
LuckyProcessBarConfigVo.StageReward stageVo = new LuckyProcessBarConfigVo.StageReward();
stageVo.setStage(stageReward.getStage());
Long luckyUid = luckyUidMap.get(stageReward.getStage());
if (null == luckyUid){
return stageVo;
}
Users luckyUser = usersMap.get(luckyUid);
if (null == luckyUser){
return stageVo;
}
ActivityUserVo luckyUserVo = new ActivityUserVo(luckyUid, luckyUser.getErbanNo(), luckyUser.getNick(), luckyUser.getAvatar());
stageVo.setLuckyUser(luckyUserVo);
return stageVo;
}).collect(Collectors.toMap(LuckyProcessBarConfigVo.StageReward::getStage, s->s));
vo.setStageMap(stageRewardMap);
return vo;
}
public void process(LuckyProcessBarConfigDto config, Long uid, String giftRecordId, Integer giftId, Integer giftNum) {
Long max = config.getMax();
long cur;
long target;
do {
cur = process.get();
if (cur >= max){
return;
}
target = Math.min(cur + giftNum, max);
} while (!process.compareAndSet(cur, target));
log.info("[2023时空幸运儿活动]-进度 {} 送出 {} 个 {} 进度从 {} 增加到 {}, 送礼记录id {}",
uid, giftNum, giftId, cur, target, giftRecordId);
for (LuckyProcessBarConfigDto.StageReward stageReward: config.getStageRewardMap().values()){
if (cur >= stageReward.getStage() || target < stageReward.getStage()){
continue;
}
boolean success = luckyUserMap.fastPut(stageReward.getStage(), uid);
log.info("[2023时空幸运儿活动]-阶段奖励 {} 进度从 {} 增加到 {},获得第 {} 阶段奖励 {},保存幸运儿结果 {}",
uid, cur, target, stageReward.getStage(), JSON.toJSONString(stageReward.getRewardList()), success);
for (RewardDto reward: stageReward.getRewardList()) {
rewardUtil.sendRewardByType(uid, reward, "[2023时空幸运儿活动]-阶段奖励");
}
sendSecretMsg(uid, stageReward.getStage());
}
}
public LuckyProcessBarConfigDto getConfig(){
String configStr = sysConfService.getSysConfValueById(LuckyProcessBarConstant.SysConfId.ACT_CONFIG);
if (!StringUtils.hasText(configStr)){
throw new ServiceException(BusiStatus.ALREADY_NOTEXISTS_CONFIG);
}
return JSON.parseObject(configStr, LuckyProcessBarConfigDto.class);
}
@Override
public void afterPropertiesSet() throws Exception {
String processKey = String.join("_", AppEnum.getCurApp().getValue(), LuckyProcessBarConstant.actName, "process");
process = redissonClient.getAtomicLong(processKey);
String luckyUserKey = String.join("_", AppEnum.getCurApp().getValue(), LuckyProcessBarConstant.actName, "lucky_user");
luckyUserMap = redissonClient.getMap(luckyUserKey);
}
}

View File

@@ -0,0 +1,36 @@
package com.accompany.business.luckyprocessbar;
import com.accompany.business.common.vo.ActivityRankVo;
import com.accompany.business.luckyprocessbar.service.LuckyProcessBarService;
import com.accompany.business.luckyprocessbar.vo.LuckyProcessBarConfigVo;
import com.accompany.common.annotation.Authorization;
import com.accompany.common.constant.ApplicationConstant;
import com.accompany.common.result.BusiResult;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
@Api(tags = "2023时空幸运儿",value = "2023时空幸运儿")
@RequestMapping("/act/2023LuckyProcessBar/")
@RestController
public class LuckyProcessBarController {
@Autowired
private LuckyProcessBarService service;
@ApiOperation("首页")
@GetMapping("/getConfig")
@Authorization
public BusiResult<LuckyProcessBarConfigVo> getRank(HttpServletRequest request){
String uidStr = request.getHeader(ApplicationConstant.PublicParameters.PUB_UID);
Long uid = Long.parseLong(uidStr);
LuckyProcessBarConfigVo configVo = service.getConfigVo(uid);
return new BusiResult<>(configVo);
}
}