活动分为限时活动和永久活动,活动开放时间读取活动配置表,我们来看下通过活动解析器管理活动类
公司大佬写的活动,直接贴代码看吧
/** * 活动解析抽象类 * @author CharonWang * */ public abstract class AbstractActivityParser extends ScheduleCronJob implements ActivityParser { protected final Logger LOGGER = LoggerFactory.getLogger(this.getClass()); @Autowired private ActivityContext context; @Autowired protected ActivityGlobalDao activityGlobalDao; @Autowired protected ActivityRecordDao activityRecordDao; @Autowired protected DBQueue dbQueue; @Autowired protected GlobalConfigService globalConfigService; @Autowired protected Schedule schedule; @PostConstruct private void initialize() { context.register(getType(), this); } protected abstract ActivityType getType(); /** * 活动开始时触发一次 */ protected abstract void onActivityOpen(List<ActivityOpenConfig> openActivityIds); /** * 活动结束时触发一次 */ protected abstract void onActivityEnd(List<ActivityOpenConfig> endActivityIds); /** * 活动展示状态触发一次 */ protected void onActivityShow(List<ActivityOpenConfig> endActivityIds) { }; @Override public String jobName() { return "ActivityParser:" + getType(); } @Override protected String[] getCronExpressions() { return new String[] { "*/1 * * * * ?" }; } @Override public void execute() { // LOGGER.error("AbstractActivityParser every second excute, className:{}", // this.getClass().getName()); Collection<ActivityOpenConfig> result = ActivityOpenConfigService.getByType(getType()); if (result.isEmpty()) { return; } List<ActivityOpenConfig> listClose = Lists.newArrayList(); List<ActivityOpenConfig> listOpen = Lists.newArrayList(); List<ActivityOpenConfig> listShow = Lists.newArrayList(); for (ActivityOpenConfig activityOpenConfig : result) { ActivityGlobal activityGlobal = activityGlobalDao.getActivityGlobal(activityOpenConfig.getId()); if (activityGlobal == null || activityGlobal.getStatus() == ActivityStatus.CLOSE.getId()) { Date now = new Date(); ActivityTime activityTime = ActivityOpenConfigService.getOpenTime(activityOpenConfig.getId(), new Date()); if (activityTime == null) { continue; } if (now.before(activityTime.getCloseTime()) && now.after(activityTime.getOpenTime())) { activityGlobalDao.createActivityGlobal(activityOpenConfig.getId(), activityTime.getOpenTime().getTime(), activityTime.getCloseTime().getTime(), activityTime.getShowTime().getTime()); listOpen.add(activityOpenConfig); } } else { if (activityGlobal.getStatus() == ActivityStatus.RUNNING.getId() || activityGlobal.getStatus() == ActivityStatus.SHOW.getId()) { if (System.currentTimeMillis() >= activityGlobal.getCloseTime()) { LOGGER.info("activityGlobal:{},status:{},closeTime:{}", activityGlobal.getActivityId(), activityGlobal.getStatus(), DateUtils.formatTime(activityGlobal.getCloseTime())); listClose.add(activityOpenConfig); activityGlobal.setStatus(ActivityStatus.CLOSE); dbQueue.updateQueue(activityGlobal); } else { ActivityTime activityTime = ActivityOpenConfigService.getOpenTime(activityOpenConfig.getId(), new Date()); if (activityTime == null) { LOGGER.info("activityGlobal:{},status:{},closeTime:{}", activityGlobal.getActivityId(), activityGlobal.getStatus(), DateUtils.formatTime(activityGlobal.getCloseTime())); listClose.add(activityOpenConfig); activityGlobal.setStatus(ActivityStatus.CLOSE); dbQueue.updateQueue(activityGlobal); continue; } if (activityGlobal.getOpenTime() != activityTime.getOpenTime().getTime() || activityGlobal.getCloseTime() != activityTime.getCloseTime().getTime()) { try { boolean isClose = activityGlobal.refreshTime(activityTime.getOpenTime().getTime(), activityTime.getCloseTime().getTime(), activityTime.getShowTime().getTime()); if (isClose) { LOGGER.info("Close activity activityId:{}, status:{}", activityGlobal.getActivityId(), activityGlobal.getStatus()); listClose.add(activityOpenConfig); } dbQueue.updateQueue(activityGlobal); LOGGER.info("RefreshActivityTime activityId:{},status:{},openTime:{},closeTime:{}", activityGlobal.getActivityId(), activityGlobal.getStatus(), DateUtils.formatTime(activityGlobal.getOpenTime()), DateUtils.formatTime(activityGlobal.getCloseTime())); } catch (Exception e) { LOGGER.error("{}", e); } } } } if (activityGlobal.getStatus() == ActivityStatus.RUNNING.getId()) { if (System.currentTimeMillis() > activityGlobal.getShowTime()) { LOGGER.debug("activityGlobal:{},status:{},closeTime:{}", activityGlobal.getActivityId(), activityGlobal.getStatus(), DateUtils.formatTime(activityGlobal.getCloseTime())); listShow.add(activityOpenConfig); activityGlobal.setStatus(ActivityStatus.SHOW); dbQueue.updateQueue(activityGlobal); } } } } if (!listClose.isEmpty()) { LOGGER.debug("activity end:{}", StringUtils.collection2SplitString(listClose, ",")); onActivityEnd(listClose); for (ActivityOpenConfig openConfig : listClose) { List<Long> actorIds = activityRecordDao.getActorIds(openConfig.getId()); for (Long actorId : actorIds) { activityRecordDao.delete(actorId, openConfig.getId()); } } } if (!listOpen.isEmpty()) { LOGGER.debug("activity open:{}", StringUtils.collection2SplitString(listOpen, ",")); long mergeServerTime = SettingsHelper.getSettingValue(SettingKey.MERGE_SERVER_TIME); List<Integer> activityTypeList = globalConfigService .findGlobalObject(GlobalConfigKey.MERGE_SERVER_NOT_CLOSE_ACTIVITY_TYPE, IntListConfig.class).getVs(); for (ActivityOpenConfig openConfig : listOpen) { if (DateUtils.isToday(mergeServerTime)) { if (activityTypeList.contains(openConfig.getActivityType())) { continue; } } List<Long> actorIds = activityRecordDao.getActorIds(openConfig.getId()); for (Long actorId : actorIds) { activityRecordDao.delete(actorId, openConfig.getId()); } } onActivityOpen(listOpen); Set<Long> onlineActorList = PlayerChannel.onlineActorList(); for (ActivityOpenConfig activityOpenConfig : listOpen) { for (Long actorId : onlineActorList) { this.pushActivity(actorId, activityOpenConfig.getId()); } } } if (!listShow.isEmpty()) { onActivityShow(listShow); Set<Long> onlineActorList = PlayerChannel.onlineActorList(); for (ActivityOpenConfig activityOpenConfig : listOpen) { for (Long actorId : onlineActorList) { this.pushActivity(actorId, activityOpenConfig.getId()); } } } } /** * 推送活动信息 * @param actorId * @param activityId */ protected void pushActivity(long actorId, int activityId) { TResult<ActivityRecordVO> recordResult = this.getRecord2Client(actorId, activityId); if (recordResult.isFail()) { return; } TResult<ActivityGlobalVO> globalResult = this.getGlobal2Client(actorId, activityId); pushActivity(actorId, activityId, globalResult.item, recordResult.item); } /** * 推送活动信息 * @param actorId * @param activityId * @param global * @param record */ protected void pushActivity(long actorId, int activityId, ActivityGlobalVO global, ActivityRecordVO record) { ActivityInfoVO vo = ActivityInfoVO.valueOf(activityId, global, record); ActivityInfoResponse response = ActivityInfoResponse.valueOf(Lists.newArrayList(vo)); ActivityPushHelper.pushActivity(actorId, response); } @EventOnline(trigger = TriggerTime.FIXED_HOUR, triggerValue = 24) public void onEvery0Hour(GameEvent e) { List<ActivityOpenConfig> activityOpenConfigList = ActivityOpenConfigService.getActivityOpenConfigList(getType()); for (ActivityOpenConfig activityOpenConfig : activityOpenConfigList) { pushActivity(e.getUniqueId(), activityOpenConfig.getId()); } } }冲级大赛活动示例,活动主要接口是getRecord2Client查询活动数据,receiveReward领取奖励,onEvent事件触发,onActivityOpen活动开启,onActivityEnd活动结束。 这个活动只需要在活动关闭时调用sendActorLevelActivityReard,计算玩家等级发放奖励邮件即可
** * 冲级大赛活动解析器 * @author xyq */ @Component public class ActivityParser8 extends AbstractActivityParser { @Autowired private DataConfig dataConfig; @Autowired private ActorFacade actorFacade; @Override public TResult<ActivityActionResponse> receiveReward(long actorId, int activityId, int id, Map<Integer, Object> parmeterMap) { return null; } @Override public TResult<ActivityRecordVO> getRecord2Client(long actorId, int activityId) { return TResult.sucess(new ActivityRecordVO() { @Override public ActivityType getType() { return ActivityType.ACTIVITY_TYPE_8; } }); } @Override public TResult<ActivityGlobalVO> getGlobal2Client(long actorId, int activityId) { return TResult.fail(); } @Override public void registerEvent(Set<String> eventSet) { } @Override public void onEvent(GameEvent e) { } @Override protected ActivityType getType() { return ActivityType.ACTIVITY_TYPE_8; } @Override protected void onActivityOpen(List<ActivityOpenConfig> openActivityIds) { } @Override protected void onActivityEnd(List<ActivityOpenConfig> endActivityIds) { for (ActivityOpenConfig activityOpenConfig : endActivityIds) { sendActorLevelActivityReard(activityOpenConfig); } } /** * 发放邮件奖励 * @param activityOpenConfig */ private void sendActorLevelActivityReard(ActivityOpenConfig activityOpenConfig) { TreeMap<Long, List<RewardObject>> rewardMap = Maps.newTreeMap(); Collection<LevelRankActivityConfig> configList = dataConfig.getList(LevelRankActivityConfig.class); for (LevelRankActivityConfig config : configList) { if (activityOpenConfig.getData() == config.getData()) { rewardMap.put(config.getRank(), config.getRewardList()); } } String date = DateUtils.SDF_SHORT_DATE.format(new Date()); TResult<ActorLevelRankResponse> result = actorFacade.getLevelRankResponse(1); if (result.isFail()) { return; } ActorLevelRankResponse response = result.item; int maxRank = globalConfigService.findGlobalConfig(GlobalConfigKey.ACTOR_LEVEL_MAX_RANK).findInt(); for (ActorLevelRankVO actorLevelRankVO : response.getRanks()) { if (actorLevelRankVO.getRank() > maxRank || actorLevelRankVO.getRank() > rewardMap.lastKey()) { continue; } List<RewardObject> rewardList = rewardMap.ceilingEntry(actorLevelRankVO.getRank()).getValue(); Map<String, String> params = Maps.newHashMap(); params.put("name", (String) actorLevelRankVO.getAttributes().get(ActorKey.ACTOR_NAME.getId())); params.put("rank", String.valueOf(actorLevelRankVO.getRank())); params.put("date", date); MailAddEvent event = new MailAddEvent((Long) actorLevelRankVO.getAttributes().get(ActorKey.ACTOR_ID.getId()), MailTemplateType.ACTOR_LEVEL_ACTIVITY_REWARD, params, rewardList); DispatchHelper.postEvent(event); LOGGER.debug("sendActorLevelActivityReward actorId:{},params:{}", (Long) actorLevelRankVO.getAttributes().get(ActorKey.ACTOR_ID.getId()), params); } LOGGER.info("sendActorLevelActivityReward Completed !"); } }定时任务
/** * 定时任务 * @author CharonWang */ public interface ScheduleJob extends Runnable { /** * 准备任务 */ void ready(); /** * 任务名称 * @return */ String jobName(); }主要难点就是活动解析器,大部分时间我也是在使用,分享下一起学习
