前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >活动系统解析

活动系统解析

作者头像
深雾
发布2020-07-10 10:36:07
2.2K0
发布2020-07-10 10:36:07
举报
文章被收录于专栏:工具类工具类

前言

活动分为限时活动和永久活动,活动开放时间读取活动配置表,我们来看下通过活动解析器管理活动类

ActivityParser活动解析接口

代码语言:javascript
复制
/**
 * 活动解析接口
 * @author CharonWang
 */
public interface ActivityParser extends OnEventListener {
	/**
	 * 记录玩家活动
	 * @param gamerId
	 * @param activityId
	 * @param id
	 * @return
	 */
	TResult<ActivityActionResponse> receiveReward(long actorId, int activityId, int id, Map<Integer, Object> parmeterMap);
	/**
	 * 获取登录时客户端数据
	 * @return
	 */
	TResult<ActivityRecordVO> getRecord2Client(long actorId, int activityId);
	/**
	 * 获取活动公共数据
	 * @param activityId
	 * @return
	 */
	TResult<ActivityGlobalVO> getGlobal2Client(long actorId, int activityId);
}

AbstractActivityParser活动解析抽象类

公司大佬写的活动,直接贴代码看吧

代码语言:javascript
复制
/**
 * 活动解析抽象类
 * @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,计算玩家等级发放奖励邮件即可

代码语言:javascript
复制
**
 * 冲级大赛活动解析器
 * @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 !");
	}
}

ScheduleCronJob活动调度器

代码语言:javascript
复制
/**
 * Cron表达式调度
 * @author CharonWan
 */
public abstract class ScheduleCronJob implements ScheduleJob {
	protected final Logger LOGGER = LoggerFactory.getLogger(this.getClass());
	@Autowired
	private TaskScheduler taskScheduler;
	@Override
	public void ready() {
		String[] crons = getCronExpressions();
		for (String cron : crons) {
			Trigger trigger = new CronTrigger(cron);
			taskScheduler.schedule(this, trigger);
			LOGGER.info("ScheduleCronJob:{},cron:{} ready!...", jobName(), cron);
		}
	}
	/**
	 * 调度时间
	 * @return
	 */
	protected abstract String[] getCronExpressions();

	@Override
	public void run() {
		try {
			LOGGER.trace("ScheduleCronJob:{},execute start...", jobName());
			execute();
			LOGGER.trace("ScheduleCronJob:{},execute complete...", jobName());
		} catch (Exception e) {
			LOGGER.error("ScheduleCronJob:{},execute error...", jobName());
			LOGGER.info("{}", e);
		}
	}
	/**
	 * 执行任务
	 */
	public abstract void execute();
}

定时任务

代码语言:javascript
复制
/**
 * 定时任务
 * @author CharonWang
 */
public interface ScheduleJob extends Runnable {
	/**
	 * 准备任务
	 */
	void ready();
	/**
	 * 任务名称
	 * @return
	 */
	String jobName();
}

主要难点就是活动解析器,大部分时间我也是在使用,分享下一起学习

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2020/07/04 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • ActivityParser活动解析接口
  • AbstractActivityParser活动解析抽象类
  • 具体活动实现
  • ScheduleCronJob活动调度器
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档