前言
活动分为限时活动和永久活动,活动开放时间读取活动配置表,我们来看下通过活动解析器管理活动类
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();
}
主要难点就是活动解析器,大部分时间我也是在使用,分享下一起学习