UNPKG

gamecloud

Version:
439 lines (406 loc) 15.8 kB
let facade = require('../../../Facade') let {EntityType, ReturnCode, ActivityScoreRate, ActivityType, ActivityStatus, ActivityRankMax} = facade.const let CoreOfBase = facade.CoreOfBase /** * 活动管理类 */ class activity extends facade.Service { /** * 构造函数 * @param {CoreOfBase} core */ constructor(core){ super(core, { init: ActivityStatus.Idle, transitions: [ { name: 'setToActive', from: ActivityStatus.Idle, to: ActivityStatus.Active }, //系统启动,初始化对象 { name: 'setToBonus', from: ActivityStatus.Idle, to: ActivityStatus.Bonus }, //系统启动,初始化对象 { name: 'end', from: ActivityStatus.Active, to: ActivityStatus.Bonus }, //活动结束,系统兑奖 { name: 'start', from: [ActivityStatus.Bonus, ActivityStatus.Idle], to: ActivityStatus.Active },//系统重新开启 ], methods: { onSetToActive: (event, id, type)=>{ this.users = new Map(); //参与活动的用户列表 this.sorted = []; //排位表 this._id = id; //设置活动编号 this._type = type; //设置活动类型 }, onSetToBonus: (event, id, type)=>{ this.users = new Map(); //参与活动的用户列表 this.sorted = []; //排位表 this._id = id; //设置活动编号 this._type = type; //设置活动类型 }, onStart: () => { this.users = new Map(); //参与活动的用户列表 this.sorted = []; //排位表 this._id = this.getActivityId(); //设置活动编号 this._type = this._id % ActivityType.len; //设置活动类型 this.Save(); }, onEnd: () => { //发放排行奖励 for(let uo of this.sorted){ if(uo.rank <= 0 || uo.rank > ActivityRankMax){ continue; } for(let rank in this.core.fileMap.activity.ActivityRankBonus[this.type]){ if(uo.rank <= rank){ //发放奖励,并下行奖励通知 - 改为事件模式 let user = this.core.GetObject(EntityType.User, uo.uid); if(!!user){ this.core.notifyEvent("user.Activity.RankBonus", {user:user, rank: rank}); } break; } } } this.Save(); }, } }); this.core = core; } /** * 将活动信息存入数据库 */ Save(){ this.sysObj.activity = JSON.stringify(this.getInfo()); this.sysObj.save(); } /** * 用户领取活动奖励 * @param {UserEntity} $user * @param {*} $id */ getBonus($user, $id){ let $ui = this.users.get($user.id); if(!$ui){ return {code: ReturnCode.activityNoRankBonus}; } if($id == 0){ //领取排名奖 if($ui.rank <=0 || $ui.rank > ActivityRankMax){ return {code: ReturnCode.activityNoRankBonus}; } for(let rank in this.core.fileMap.activity.ActivityRankBonus[this.type]){ if($ui.rank <= rank){ if(!$user.baseMgr.vip.readActivityBonus(0)){ $user.baseMgr.vip.writeActivityBonus(0); $user.getBonus(this.core.fileMap.activity.ActivityRankBonus[this.type][rank].bonus); return {code: ReturnCode.Success, data:{rank: $ui.rank, bonus:this.core.fileMap.activity.ActivityRankBonus[this.type][rank].bonus}}; } else{ return {code: ReturnCode.activityBonusGot}; } } } } else{//领取分段积分奖 if($id - 1 <= $ui.lv){ if(!$user.baseMgr.vip.readActivityBonus($id)){ $user.baseMgr.vip.writeActivityBonus($id); $user.getBonus(this.core.fileMap.activity.ActivityScoreBonus[this.type][$id - 1].bonus); return {code: ReturnCode.Success, data:{id: $id, bonus:this.core.fileMap.activity.ActivityScoreBonus[this.type][$id - 1].bonus}}; } else{ return {code: ReturnCode.activityBonusGot}; } } } return {code: ReturnCode.illegalData}; } /** * 获取活动状态参数 */ getInfo($user){ let time = new Date(); let nowday = 1; if(time.getDay() == 0){ nowday = 7; } else { nowday = time.getDay(); } let start = time.getDate() - nowday + 1; let end = time.getDate() + (7 - nowday) - 1; let starttime = String(time.getFullYear())+"/"+String(time.getMonth()+1)+"/"+String(start); let endtime = String(time.getFullYear())+"/"+String(time.getMonth()+1)+"/"+String(end); let actarr = [0,0,0,0,0,0]; if(!!$user){ for(let i = 0; i< 6; i++){ if($user.baseMgr.vip.v.act[i] == true){ actarr[i] = 1; } } let ui = this.users.get($user.id); return { id: this.id, type: this.type, state: this.state, starttime: starttime, endtime: endtime, score: !!ui ? ui.score : 0, //当前积分 rank: !!ui ? ui.rank : 0, //当前排名 act: actarr //历史领奖记录 }; } else{ return { id: this.id, type: this.type, state: this.state, starttime: starttime, endtime: endtime }; } } /** * 从数据库载入活动信息 */ async loadDb(){ let it = await this.core.models.system(this.core.options.mysql).findCreateFind({ where:{ id:1 }, defaults: {activity:"{}"}, }); this.sysObj = it[0]; let $info = JSON.parse(this.sysObj.activity); if(!!$info.id){ //存在历史活动信息 if($info.state == ActivityStatus.Active){ this.setToActive($info.id, $info.type); } else if($info.state == ActivityStatus.Bonus){ this.setToBonus($info.id, $info.type); } } this.checkStatus(true); } /** * 活动编号 */ get id(){ return this._id; } /** * 活动类型 */ get type(){ return this._type; } /** * 获取或自动创建排行榜用户信息对象,并进行必要的数据检测 * @param {*} */ getUserOrDefault($uid){ if(!this.users.has($uid)){//如果不存在指定记录,就创建一条新记录 let uo = this.core.GetObject(EntityType.User, $uid); if(!!uo){ this.users.set($uid, { uid:$uid, //玩家ID aid:this.id, //活动ID openid: uo.openid, name: uo.name, icon: uo.baseMgr.info.GetHeadIcon(), score:0, //活动积分 lv:0, //分段积分进度 rank:0, //排名,0表示未上榜 }); this.sorted.push(this.users.get($uid)); //添加到排序列表中 } } let ui = this.users.get($uid); if(!!ui){ if(ui.aid != this.id){//现有记录的活动ID和当前活动ID不符 ui.aid = this.id; //重新设置活动ID ui.score = 0; //分数清零 ui.lv = 0; //分段积分进度清零 } } return ui; } /** * 获取用户排名列表, 传入页数 */ rankList($uid) { let $rank = 0; let ui = this.users.get($uid); if(!!ui){ $rank = ui.rank; } let ret = {list:[]}; //todo:自身排名判断,若自身排名在前14名以内则改为获取前14名,若排行不足14位则显示全部 if (this.sorted.length >= 14) { if($rank == 0){ //没有排名,显示前14名 for (let j = 0; j < 14; j++) { ret.list.push(this.sorted[j]); } } else if ($rank > 13) {//在14名外 for (let j = 0; j < 3; j++) { ret.list.push(this.sorted[j]); } for (let j = $rank - 5; j < $rank + 6; j++) { ret.list.push(this.sorted[j]); } } else {//在14名以内 for (let j = 0; j < 14; j++) { ret.list.push(this.sorted[j]); } } } else { //总参与用户不足14,全部显示 for (let j = 0; j < this.sorted.length; j++) { ret.list.push(this.sorted[j]); } } return ret; } /** * 定时检测当前活动是否有效,并执行相关操作: * @note * 1、每周一零点,自动生成新的一期互动,自动编号、设定类型。 * 2、玩家通过游戏环节累积积分,当积分达到分段积分各个标准时,实时、自动下发积分奖励。玩家可以在活动界面看到各阶段的奖励内容,以及各段激活情况 * 3、周六晚9点自动结算活动排名奖励,奖励自动发放到用户背包,玩家可以在活动界面上看到自己实时或最终排名,排行榜上各个玩家的获奖情况 * 4、结算活动后,本期活动结束,活动信息保留供用所有玩家查看,直至下一期活动开启,周天轮休。 */ checkStatus($init){ //判断并推动状态机演变 let cur = new Date(); if(!$init){ //定时检测而非初次载入数据库信息时,需要对数据进行重新排序 this.sortUser(); } switch(this.state){ case ActivityStatus.Active: //如果时间大于周六晚上9点则立即结算 if((cur.getDay() == 6 && cur.getHours()>=21) || cur.getDay() == 0){ this.end(); } break; case ActivityStatus.Bonus: //如果时间大于周一零点则立即重启活动 if(cur.getDay() != 0){ if((cur.getDay() == 6 && cur.getHours()>=21) ) return; this.start(); } break; default: this.start();//状态机重启 break; } } /** * 对参与活动的用户进行排序 */ sortUser(){ let rank = 1; this.sorted.sort((a,b)=>{ return b.score - a.score; }); this.sorted.map(item=>{ item.rank = rank++; }); } /** * 设置玩家活动分数,用于数据库载入 * @param {*} * @param {*} * @param {*} * @param {*} */ setScore(user, $aid, $score, $lv){ if($aid == this.id && $score > 0){ //否则就不加入列表中 let ui = this.getUserOrDefault(user.id); ui.score = $score; if(!!$lv){ ui.lv = $lv; } } } /** * 为指定用户添加积分 * @param {*} * @param {*} */ addScore($uid, $type, $added){ if($type != this.type || this.state != ActivityStatus.Active) {//类型不匹配,或者活动处于非激活状态 return; } $added = $added || 0; if(typeof $added == "string"){ $added = parseInt($added); } if($added <= 0){ return; } let ui = this.getUserOrDefault($uid); let user = this.core.GetObject(EntityType.User, $uid); if(!!user){ ui.score += $added * ActivityScoreRate[this.type]; //不同活动具有不同的分数转化率 for(let i = 0;i < 5;i++){ if(!!this.core.fileMap.activity.ActivityScoreBonus[this.type][i] && ui.score >= this.core.fileMap.activity.ActivityScoreBonus[this.type][i].score){ ui.lv = i; } } this.core.notifyEvent("user.Activity.ScoreBonus", {user:user, score: ui.score, lv: ui.lv}); //活动积分发生变化 this.core.notifyEvent("user.Activity.ScoreChanged", {user:user, score: ui.score, lv: ui.lv}); } } /** * 获得当前时间对应的活动编号 */ getActivityId(){ let now = new Date(); return this.getYear(now)*100 + this.getWeekNumber(now); } /** * 获取当前年份 * @param {*} now */ getYear(now){ return now.getFullYear(); } /** * 计算当前日期是一年中的第几周 */ getWeekNumber(now) { /** * 判断年份是否为润年 * * @param {Number} year */ function isLeapYear(year) { return (year % 400 == 0) || (year % 4 == 0 && year % 100 != 0); } /** * 获取某一年份的某一月份的天数 * * @param {Number} year * @param {Number} month */ function getMonthDays(year, month) { return [31, null, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month] || (isLeapYear(year) ? 29 : 28); } let year = now.getFullYear(), month = now.getMonth(), days = now.getDate(); //那一天是那一年中的第多少天 for (var i = 0; i < month; i++) { days += getMonthDays(year, i); } //那一年第一天是星期几 var yearFirstDay = new Date(year, 0, 1).getDay() || 7; var week = null; if (yearFirstDay == 1) { week = Math.ceil(days / yearFirstDay); } else { days -= (7 - yearFirstDay + 1); week = Math.ceil(days / 7) + 1; } return week; } } module.exports = activity;