| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567 |
- package handler
- import (
- "encoding/json"
- "sort"
- "time"
- "bet24.com/log"
- "bet24.com/servers/common"
- pb "bet24.com/servers/micros/badge/proto"
- notification "bet24.com/servers/micros/notification/proto"
- user "bet24.com/servers/micros/userservices/proto"
- )
- const (
- idle_seconds = 900 // 过期时长(秒)
- )
- // 用户信息
- type userInfo struct {
- userId int // 用户id
- badgeList []*pb.UserBadge // 用户徽章
- timeStamp int // 时间戳
- endChan chan int
- }
- func newUserInfo(userId int) *userInfo {
- ret := new(userInfo)
- ret.userId = userId
- ret.endChan = make(chan int)
- ret.updateTimeStamp()
- ret.loadData()
- return ret
- }
- // 更新时间戳
- func (ub *userInfo) updateTimeStamp() {
- ub.timeStamp = common.GetTimeStamp() + idle_seconds
- return
- }
- // 加载用户数据
- func (ub *userInfo) loadData() {
- ub.badgeList = transGetUserBadgeList(ub.userId)
- ub.checkBadgeIsShow()
- ub.loadBadgeUnlockTime()
- ub.doCheck()
- pos := []int{1, 1, 1}
- for _, v := range ub.badgeList {
- if v.Position == 0 {
- pos[0] = 0
- }
- if v.Position == 1 {
- pos[1] = 0
- }
- if v.Position == 2 {
- pos[2] = 0
- }
- }
- for _, v := range ub.badgeList {
- if v.Position != -1 {
- continue
- }
- for i := 0; i < 3; i++ {
- if pos[i] == 1 {
- ub.autoWearBadge(v.BadgeId, i)
- pos[i] = 0
- break
- }
- }
- }
- return
- }
- // 轮询检查
- func (ub *userInfo) doCheck() {
- ticker := time.NewTicker(10 * time.Minute)
- go func(t *time.Ticker) {
- for {
- select {
- case <-ub.endChan:
- t.Stop()
- return
- case <-t.C:
- // 每十分钟执行一次
- go ub.checkBadgeExpires()
- }
- }
- }(ticker)
- }
- // 检查徽章是否显示
- func (ub *userInfo) checkBadgeIsShow() {
- badgeList := []*pb.UserBadge{}
- for _, v := range ub.badgeList {
- sysBadge := mgr.getSysBadgeInfo(v.BadgeId)
- if sysBadge == nil {
- log.Debug("userInfo.checkBadgeIsShow config not found. userId[%d]", ub.userId)
- continue
- }
- if sysBadge.Model == 0 && !sysBadge.IsShow {
- continue
- }
- level, lvPoints := pb.GetLevel(v.Exps, sysBadge.Levels)
- if level != v.Level {
- addPoints := ub.addUnlockTimeAndPoint(level, lvPoints, v)
- v.Level = level
- v.Points = addPoints
- go transSaveUserBadge(ub.userId, v)
- }
- badgeList = append(badgeList, v)
- }
- ub.badgeList = badgeList
- }
- // 徽章等级的解锁时间
- func (ub *userInfo) loadBadgeUnlockTime() {
- for k, v := range ub.badgeList {
- if v.Level >= pb.UsageLevel {
- ub.badgeList[k].Wearable = true
- }
- var arr []string
- if err := json.Unmarshal([]byte(v.ObtainDate), &arr); err != nil {
- log.Debug("userInfo.loadBadgeUnlockTime Unmarshal fail. err:%+v", err)
- continue
- }
- for _, s := range arr {
- ub.badgeList[k].UnlockTime = append(ub.badgeList[k].UnlockTime, int(common.ParseTime(s).Unix()))
- }
- }
- }
- // 析构,停止计时器等
- func (ub *userInfo) destructor() {
- close(ub.endChan)
- }
- // 检查徽章过期
- func (ub *userInfo) checkBadgeExpires() {
- for k, v := range ub.badgeList {
- if v.ExpiresTime == 0 {
- continue
- }
- if !v.IsExpires() {
- continue
- }
- ub.badgeList[k].Level = 0
- ub.badgeList[k].Position = -1
- ub.badgeList[k].ExpiresTime = 0
- go transSaveUserBadge(ub.userId, v)
- go user.UpdateUserInfo(ub.userId)
- log.Debug("userInfo.checkBadgeExpires userId=%d badgeId=%d 已取下所有用户对应的荣耀徽章", ub.userId, v.BadgeId)
- }
- }
- // 是否过期
- func (ub *userInfo) isExpire() bool {
- return ub.timeStamp < common.GetTimeStamp()
- }
- // 获取用户徽章列表
- func (ub *userInfo) getUserBadgeList() []*pb.UserBadge {
- return ub.badgeList
- }
- // 获取用户佩戴与展示的徽章
- func (ub *userInfo) getBadgeWearAndShow() []pb.BadgePosition {
- var list []pb.BadgePosition
- for _, v := range mgr.sysList {
- if v.Model == 0 && !v.IsShow {
- continue
- }
- info := ub.getUserBadge(v.BadgeId)
- if info == nil {
- continue
- }
- if v.Model == 0 && info.Position < 0 {
- continue
- }
- if info.Level < pb.UsageLevel {
- continue
- }
- list = append(list, pb.BadgePosition{
- Position: info.Position,
- BadgeId: info.BadgeId,
- Level: info.Level,
- })
- }
- sort.SliceStable(list, func(i, j int) bool {
- return list[i].Position < list[j].Position
- })
- return list
- }
- func (ub *userInfo) autoWearBadge(badgeId, position int) {
- userBadge := ub.getUserBadge(badgeId)
- if userBadge == nil || !userBadge.IsWearable() {
- return
- }
- oldPosition := -1
- existBadgeId := 0
- // 如果已佩戴,先卸掉
- for _, v := range ub.badgeList {
- if v.BadgeId == badgeId {
- // 如果已佩戴,可能涉及交换位置
- oldPosition = v.Position
- v.Position = -1
- }
- // 找出占位徽章ID
- if position > -1 && v.Position == position {
- existBadgeId = v.BadgeId
- }
- }
- // 如果卸下
- if position == -1 {
- go transSaveUserBadge(ub.userId, userBadge)
- user.UpdateUserInfo(ub.userId)
- return
- }
- sysBadge := mgr.getSysBadgeInfo(badgeId)
- if sysBadge == nil {
- log.Debug("userInfo.wearBadge config not found. userId[%d]", ub.userId)
- return
- }
- for _, v := range ub.badgeList {
- if v.BadgeId == badgeId {
- // 禁止换到新位置
- if existBadgeId == 0 {
- if !sysBadge.IsShow {
- v.Position = oldPosition
- continue
- }
- }
- // 已佩戴的可互调位置
- v.Position = position
- if oldPosition == -1 {
- if !sysBadge.IsShow {
- v.Position = -1
- }
- }
- go transSaveUserBadge(ub.userId, userBadge)
- continue
- }
- // 如果存在交换
- if existBadgeId == v.BadgeId {
- v.Position = oldPosition
- existBadge := ub.getUserBadge(v.BadgeId)
- if existBadge == nil {
- log.Debug("userInfo.wearBadge badgeId not fount, badgeId[%d]", v.BadgeId)
- continue
- }
- go transSaveUserBadge(ub.userId, existBadge)
- }
- }
- user.UpdateUserInfo(ub.userId)
- }
- // 佩戴成就徽章
- // @param badgeId int 徽章id
- // @param position int 位置(-1:未佩戴,0-2对应位置)
- func (ub *userInfo) wearBadge(badgeId, position int) []pb.BadgePosition {
- userBadge := ub.getUserBadge(badgeId)
- if userBadge == nil || !userBadge.IsWearable() {
- return ub.getBadgeWearAndShow()
- }
- oldPosition := -1
- existBadgeId := 0
- // 如果已佩戴,先卸掉
- for _, v := range ub.badgeList {
- if v.BadgeId == badgeId {
- // 如果已佩戴,可能涉及交换位置
- oldPosition = v.Position
- v.Position = -1
- }
- // 找出占位徽章ID
- if position > -1 && v.Position == position {
- existBadgeId = v.BadgeId
- }
- }
- // 如果卸下
- if position == -1 {
- go transSaveUserBadge(ub.userId, userBadge)
- user.UpdateUserInfo(ub.userId)
- return ub.getBadgeWearAndShow()
- }
- sysBadge := mgr.getSysBadgeInfo(badgeId)
- if sysBadge == nil {
- log.Debug("userInfo.wearBadge config not found. userId[%d]", ub.userId)
- return ub.getBadgeWearAndShow()
- }
- for _, v := range ub.badgeList {
- if v.BadgeId == badgeId {
- // 禁止换到新位置
- if existBadgeId == 0 {
- if !sysBadge.IsShow {
- v.Position = oldPosition
- continue
- }
- }
- // 已佩戴的可互调位置
- v.Position = position
- if oldPosition == -1 {
- if !sysBadge.IsShow {
- v.Position = -1
- }
- }
- go transSaveUserBadge(ub.userId, userBadge)
- continue
- }
- // 如果存在交换
- if existBadgeId == v.BadgeId {
- v.Position = oldPosition
- existBadge := ub.getUserBadge(v.BadgeId)
- if existBadge == nil {
- log.Debug("userInfo.wearBadge badgeId not fount, badgeId[%d]", v.BadgeId)
- continue
- }
- go transSaveUserBadge(ub.userId, existBadge)
- }
- }
- user.UpdateUserInfo(ub.userId)
- return ub.getBadgeWearAndShow()
- }
- // 获取用户徽章
- func (ub *userInfo) getUserBadge(badgeId int) *pb.UserBadge {
- for k, v := range ub.badgeList {
- if v.BadgeId == badgeId {
- return ub.badgeList[k]
- }
- }
- return nil
- }
- // 触发动作,根据经验值重新计算 level
- func (ub *userInfo) doAction(action, progress int, param pb.Scope) {
- // 消耗金币暂不处理,金币进度只统计购买道具消耗金币
- if action == pb.Action_ConsumeGold {
- return
- }
- now := common.GetNowTime()
- //currIndex := common.GetWeekIndex(int(now.Unix()))
- //crdateTime := int(common.ParseTime(param.RankCrdate).Unix())
- //crdateIndex := common.GetWeekIndex(crdateTime)
- //multiple := currIndex - crdateIndex + 1
- // badge 信息
- for _, v := range mgr.sysList {
- if v.Action != action {
- continue
- }
- if !v.IsCollection {
- log.Debug("userInfo.doAction Currently badges are not collected. userId[%d], action[%d], v[%+v]",
- ub.userId, action, v)
- continue
- }
- if pb.Action_Game_CallPoints == action && !pb.CheckRankingScore(v.BadgeScope.Ranks, param.RankInfo) {
- log.Debug("userInfo.doAction Insufficient score. userId[%d], action[%d], RankInfo[%+v], v[%+v]",
- ub.userId, action, param.RankInfo, v)
- continue
- }
- if len(v.BadgeScope.GameNames) > 0 && !v.IsApplicative(param) {
- log.Debug("userInfo.doAction gameNames config nod found. userId[%d], action[%d], GameName[%s], v[%+v]",
- ub.userId, action, param.GameName, v)
- continue
- }
- if len(v.BadgeScope.GiftIds) > 0 && !pb.GameMatch(v.BadgeScope.GiftIds, param.GiftId) {
- log.Debug("userInfo.doAction giftId config nod found. userId[%d], action[%d], GiftId[%+v], v[%+v]",
- ub.userId, action, param.GiftId, v)
- continue
- }
- if len(v.BadgeScope.ItemIds) > 0 && !pb.GiftIdMatch(v.BadgeScope.ItemIds, param.Items) {
- log.Debug("userInfo.doAction itemId config nod found. userId[%d], action[%d], ItemId[%+v], v[%+v]",
- ub.userId, action, param.Items, v)
- continue
- }
- if len(v.BadgeScope.TaskIds) > 0 && !pb.GameMatch(v.BadgeScope.TaskIds, param.TaskId) {
- log.Debug("userInfo.doAction taskId config nod found. userId[%d], action[%d], TaskId[%+v], v[%+v]",
- ub.userId, action, param.TaskId, v)
- continue
- }
- var isNew, isChange, isLevelChange bool
- var noticePoints int
- userBadge := ub.getUserBadge(v.BadgeId)
- if userBadge == nil {
- // 新增徽章
- isNew = true
- userBadge = &pb.UserBadge{}
- userBadge.BadgeId = v.BadgeId
- userBadge.ObtainDate = "[]"
- userBadge.Position = -1
- userBadge.Crdate = common.GetNowTimeStr()
- }
- // 成就徽章(生涯)
- if v.BadgeType == pb.BadgeType_Achievement {
- userBadge.Exps += progress
- level, lvPoints := pb.GetLevel(userBadge.Exps, v.Levels) // 计算 level、点数
- if level > userBadge.Level {
- isChange = true
- isLevelChange = true
- addPoints := ub.addUnlockTimeAndPoint(level, lvPoints, userBadge)
- userBadge.Level = level
- userBadge.Points += addPoints
- noticePoints = lvPoints[level]
- }
- }
- // 荣耀徽章
- if v.BadgeType == pb.BadgeType_Honor {
- if v.Action != pb.Action_NoviceGuide {
- // 只取零点且前三十分钟的数据才有效[00:30]
- if !(now.Hour() == 0 && now.Minute() < 30) {
- continue
- }
- if !pb.CheckRankingScore(v.BadgeScope.Ranks, param.RankInfo) {
- continue
- }
- }
- //expiresTime := crdateTime + v.Duration*multiple - 1
- //if common.IsSameWeek(expiresTime, userBadge.ExpiresTime) {
- // // 已统计过,无需重复统计
- // continue
- //}
- // TODO Start 测试,验收成功后将删除此逻辑。为了方便测试徽章到期时间,直接获取当天到零点剩余时间
- endOfDay := time.Date(now.Year(), now.Month(), now.Day(), 23, 59, 59, 0, now.Location())
- expiresTime := int(endOfDay.Unix())
- if common.IsSameDay(expiresTime, userBadge.ExpiresTime) {
- // 已统计过,无需重复统计
- continue
- }
- log.Debug("-------------------\r\n"+
- "用户ID:%d\r\n"+
- "榜单日期:%s\r\n"+
- "榜单类型:%d\r\n"+
- "榜单排名:%d\r\n"+
- "当前系统榜单:%v\r\n"+
- "过期时间:%s\r\n"+
- "-------------------",
- ub.userId, param.RankCrdate, param.Type, param.Rank, v.BadgeScope.Ranks, common.TimeStampToString(endOfDay.Unix()))
- // TODO End
- // 只记录第一次解锁的时间
- if len(userBadge.UnlockTime) == 0 {
- ub.addUnlockTimeAndPoint(0, nil, userBadge)
- }
- isChange = true
- userBadge.Times++
- userBadge.Level = pb.MaxLevel
- userBadge.ExpiresTime = expiresTime
- }
- if userBadge.Level >= pb.UsageLevel {
- userBadge.Wearable = true
- }
- if isNew {
- ub.badgeList = append(ub.badgeList, userBadge)
- }
- // 存入数据库
- go transSaveUserBadge(ub.userId, userBadge)
- if isLevelChange && userBadge.Position != -1 {
- ub.autoWearBadge(userBadge.BadgeId, userBadge.Position)
- } else {
- pos := []int{1, 1, 1}
- for _, v := range ub.badgeList {
- if v.Position == 0 {
- pos[0] = 0
- }
- if v.Position == 1 {
- pos[1] = 0
- }
- if v.Position == 2 {
- pos[2] = 0
- }
- }
- for i := 0; i < 3; i++ {
- if pos[i] == 1 {
- ub.autoWearBadge(userBadge.BadgeId, i)
- break
- }
- }
- }
- // 通知客户端,属性有变化
- if isChange {
- noticeUser := pb.UserBadge{
- BadgeId: userBadge.BadgeId,
- Badge_Level: pb.Badge_Level{
- Level: userBadge.Level,
- Exps: userBadge.Exps,
- Points: noticePoints,
- },
- Times: userBadge.Times,
- Position: userBadge.Position,
- Wearable: userBadge.Wearable,
- ExpiresTime: userBadge.ExpiresTime,
- ObtainDate: userBadge.ObtainDate,
- UnlockTime: userBadge.UnlockTime,
- }
- d, _ := json.Marshal(noticeUser)
- notification.AddNotification(ub.userId, notification.Notification_BadgeChange, string(d))
- }
- user.UpdateUserInfo(ub.userId)
- log.Debug("userInfo.doAction success!"+
- "userId[%d], action[%d], progress[%d], param[%+v], userBadge[%+v], configBadge[%+v],"+
- "current Time:[%s]",
- ub.userId, action, progress, param, userBadge, v, common.TimeStampToString(int64(common.GetTimeStamp())))
- }
- }
- // 添加解锁的时间和点数
- func (ub *userInfo) addUnlockTimeAndPoint(level int, lvPoints map[int]int, userBadge *pb.UserBadge) int {
- var point int
- if level != 0 && level != userBadge.Level+1 {
- var unlockTime []int
- // 处理跨等级
- for i := 0; i < level; i++ {
- if userBadge.Level > 0 && userBadge.Level == i+1 {
- if len(userBadge.UnlockTime) > i {
- unlockTime = append(unlockTime, userBadge.UnlockTime[i])
- }
- continue
- }
- point += lvPoints[i+1]
- unlockTime = append(unlockTime, common.GetTimeStamp())
- }
- userBadge.UnlockTime = unlockTime
- } else {
- if v, ok := lvPoints[level]; ok {
- point = v
- }
- userBadge.UnlockTime = append(userBadge.UnlockTime, common.GetTimeStamp())
- }
- var arr []string
- for _, v := range userBadge.UnlockTime {
- arr = append(arr, common.TimeStampToString(int64(v)))
- }
- d, _ := json.Marshal(arr)
- userBadge.ObtainDate = string(d)
- return point
- }
|