package novicewelfare import ( "bet24.com/log" "bet24.com/servers/common" pb "bet24.com/servers/micros/activityservice/proto" dotservice "bet24.com/servers/micros/dotservice/proto" inventory "bet24.com/servers/micros/item_inventory/proto" notification "bet24.com/servers/micros/notification/proto" task "bet24.com/servers/micros/task/proto" "encoding/json" "strconv" "time" ) const ( idle_seconds = 900 // 过期时长(秒) ) type userTask struct { userId int // 用户id finalPackageClaimed bool // 最终礼包领取 taskList []*pb.UserNoviceTaskSchedule // 任务列表 timeStamp int // 当前时间戳 endChan chan int } func newUserTask(userId int) *userTask { ret := new(userTask) ret.userId = userId ret.endChan = make(chan int) ret.loadData() ret.doCheck() ret.updateTimeStamp() return ret } // 是否过期 func (ut *userTask) isExpire() bool { return ut.timeStamp < common.GetTimeStamp() } // 更新时间戳 func (ut *userTask) updateTimeStamp() { ut.timeStamp = common.GetTimeStamp() + idle_seconds return } // 加载数据 func (ut *userTask) loadData() { ut.taskList = transGetUserTaskList(ut.userId) if len(ut.taskList) == 0 { ut.createNoviceTasks() ut.noviceWelfareChangeNotice() return } if transGetUserBigAwardStatus(ut.userId) > 0 { ut.finalPackageClaimed = true } if ut.isEnd() { ut.taskList = []*pb.UserNoviceTaskSchedule{} return } ut.checkTaskUnlocking() } // 创建新手任务 func (ut *userTask) createNoviceTasks() { for k, v := range mgr.getSysNoviceTasks() { var status, unlockDayIndex int if k == 0 { status = pb.TaskStatus_Uncompleted unlockDayIndex = common.GetDayIndex(common.GetTimeStamp()) } taskInfo := &pb.UserNoviceTaskSchedule{ DayIndex: v.DayIndex, Scheduled: 0, Status: status, UnlockDayIndex: unlockDayIndex, } ut.taskList = append(ut.taskList, taskInfo) ut.updateUserTask(taskInfo) } return } // 轮询检查 func (ut *userTask) doCheck() { ticker := time.NewTicker(10 * time.Minute) go func(t *time.Ticker) { for { select { case <-ut.endChan: t.Stop() return case <-t.C: // 每十分钟执行一次 ut.checkActivityExpire() } } }(ticker) } // 析构,停止计时器等 func (ut *userTask) destructor() { defer func() { if recover() != nil { log.Release("userTask.destructor panic on close chan") } }() close(ut.endChan) } // 检查活动过期 func (ut *userTask) checkActivityExpire() { if len(ut.taskList) == 0 { //ut.destructor() return } if !ut.isEnd() { return } ut.taskList = []*pb.UserNoviceTaskSchedule{} ut.noviceWelfareChangeNotice() //ut.destructor() return } // 是否结束 func (ut *userTask) isEnd() bool { if len(ut.taskList) == 0 { return true } return common.GetDayIndex(common.GetTimeStamp()) >= ut.taskList[0].UnlockDayIndex+mgr.getActivityDuration() } // 检查任务解锁 func (ut *userTask) checkTaskUnlocking() { taskLen := len(ut.taskList) - 1 unlockDayIndex := common.GetDayIndex(common.GetTimeStamp()) for i := taskLen; i >= 0; i-- { if ut.taskList[i].Status == pb.TaskStatus_Locked { continue } if ut.taskList[i].UnlockDayIndex == unlockDayIndex { return } if taskLen == i { return } ut.taskList[i+1].UnlockDayIndex = unlockDayIndex ut.taskList[i+1].Status = pb.TaskStatus_Uncompleted ut.updateUserTask(ut.taskList[i+1]) ut.noviceWelfareChangeNotice() return } } // 获取剩余天数 func (ut *userTask) getDaysRemaining() int { if len(ut.taskList) == 0 { return 0 } toDayIndex := common.GetDayIndex(common.GetTimeStamp()) endDayIndex := ut.taskList[0].UnlockDayIndex + mgr.getActivityDuration() daysRemaining := endDayIndex - toDayIndex if daysRemaining <= 0 { return 0 } return daysRemaining } // 获取用户新手福利 func (ut *userTask) getUserNoviceWelfare() pb.UserNoviceWelfare { var resp pb.UserNoviceWelfare resp.DaysRemaining = ut.getDaysRemaining() resp.IsFinalPackage = ut.finalPackageClaimed resp.Schedule = ut.taskList return resp } // 获取用户任务 func (ut *userTask) getUserTask(dayIndex int) *pb.UserNoviceTaskSchedule { for k, v := range ut.taskList { if v.DayIndex != dayIndex { continue } return ut.taskList[k] } return nil } // 领取新手福利奖励 func (ut *userTask) claimNoviceWelfareAward(dayIndex int, isFinalPackage bool) bool { if ut.isEnd() { // 活动已结束 return false } if isFinalPackage { if ut.finalPackageClaimed { return false } if !ut.isFinalPackageClaimable() { return false } ut.finalPackageClaimed = true go transUpdateUserBigAward(ut.userId) inventory.AddItems(ut.userId, mgr.getGiftPacks(), "Novice Welfare Gift Packs", common.LOGTYPE_NOVICE_WELFARE_AWARD) ut.noviceWelfareChangeNotice() return true } config := mgr.getNoviceTaskConfig(dayIndex) if config == nil { log.Debug("userTask.claimNoviceWelfareAward config does not exist! dayIndex[%d] userId[%d]", dayIndex, ut.userId) return false } taskInfo := ut.getUserTask(dayIndex) if taskInfo == nil { log.Debug("userTask.claimNoviceWelfareAward user taskInfo not exist! dayIndex[%d] userId[%d]", dayIndex, ut.userId) return false } if taskInfo.Status < pb.TaskStatus_Completed || taskInfo.Status == pb.TaskStatus_Claimed { log.Debug("userTask.claimNoviceWelfareAward Task has been claimed or not completed! dayIndex[%d] status[%d]", dayIndex, taskInfo.Status) return false } if config.Target != taskInfo.Scheduled { log.Debug("userTask.claimNoviceWelfareAward Condition not satisfied! dayIndex[%d], scheduled[%d]", dayIndex, taskInfo.Scheduled) return false } taskInfo.Status = pb.TaskStatus_Claimed ut.updateUserTask(taskInfo) // 发放道具 inventory.AddItems(ut.userId, config.Awards, "Novice Welfare Award", common.LOGTYPE_NOVICE_WELFARE_AWARD) ut.noviceWelfareChangeNotice() // 打点统计 go dotservice.AddDot(ut.userId, dotservice.DotScope{ Scene: dotservice.Scene_NoviceWelfare_Task, Action: dotservice.Action_Awarded, Extra: strconv.Itoa(dayIndex), }) return true } // 新手福利变更通知 func (ut *userTask) noviceWelfareChangeNotice() { d, _ := json.Marshal(ut.getUserNoviceWelfare()) go notification.AddNotification(ut.userId, notification.Notification_NoviceWelfare, string(d)) } // 是否新手福利提醒 func (ut *userTask) isNoviceWelfareTip() bool { for _, v := range ut.taskList { if v.Status == pb.TaskStatus_Completed { return true } } return false } // 最终礼包是否可领取 func (ut *userTask) isFinalPackageClaimable() bool { for _, v := range ut.taskList { if v.Status < pb.TaskStatus_Completed { return false } } return true } // 用户动作 func (ut *userTask) doAction(action int, progress int, param task.TaskScope) { //log.Debug("userTask.doAction user[%d] Have entered. action[%d], progress[%d], param:%+v", // ut.userId, action, progress, param) if ut.isEnd() { // 活动已结束 return } var isNotice bool for _, v := range mgr.getSysNoviceTasks() { if v.Action != action { continue } if len(v.GameNames) > 0 && !v.IsApplicative(param) { //log.Debug("userTask.doAction config Parameter mismatch. userId[%d], action[%d], progress[%d], sys:%+v, param:%+v", // ut.userId, action, progress, v.GameNames, param) continue } taskInfo := ut.getUserTask(v.DayIndex) if taskInfo == nil { log.Debug("userTask.doAction Task does not exist! userId[%d], action[%d], progress[%d], dayIndex[%d], param:%+v", ut.userId, action, progress, v.DayIndex, param) continue } if taskInfo.Status == pb.TaskStatus_Locked || taskInfo.Status >= pb.TaskStatus_Completed { continue } taskInfo.Scheduled += progress if taskInfo.Scheduled < v.Target { isNotice = true ut.updateUserTask(taskInfo) continue } if len(v.Awards) == 0 { taskInfo.Status = pb.TaskStatus_Claimed } else { taskInfo.Status = pb.TaskStatus_Completed // 打点统计 go dotservice.AddDot(ut.userId, dotservice.DotScope{ Scene: dotservice.Scene_NoviceWelfare_Task, Action: dotservice.Action_Complete, Extra: strconv.Itoa(v.DayIndex), }) } isNotice = true taskInfo.Scheduled = v.Target ut.updateUserTask(taskInfo) } if isNotice { ut.noviceWelfareChangeNotice() } } // 更新用户任务 func (ut *userTask) updateUserTask(taskInfo *pb.UserNoviceTaskSchedule) { go transUpdateUserTask(ut.userId, taskInfo) } func (ut *userTask) dump() { log.Release("timeout timeStamp: [%s]", common.TimeStampToString(int64(ut.timeStamp))) for _, v := range ut.taskList { log.Release("DayIndex:[%d], Scheduled[%d], Status[%d], UnlockDayIndex[%d]", v.DayIndex, v.Scheduled, v.Status, v.UnlockDayIndex) } }