user.go 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567
  1. package handler
  2. import (
  3. "encoding/json"
  4. "sort"
  5. "time"
  6. "bet24.com/log"
  7. "bet24.com/servers/common"
  8. pb "bet24.com/servers/micros/badge/proto"
  9. notification "bet24.com/servers/micros/notification/proto"
  10. user "bet24.com/servers/micros/userservices/proto"
  11. )
  12. const (
  13. idle_seconds = 900 // 过期时长(秒)
  14. )
  15. // 用户信息
  16. type userInfo struct {
  17. userId int // 用户id
  18. badgeList []*pb.UserBadge // 用户徽章
  19. timeStamp int // 时间戳
  20. endChan chan int
  21. }
  22. func newUserInfo(userId int) *userInfo {
  23. ret := new(userInfo)
  24. ret.userId = userId
  25. ret.endChan = make(chan int)
  26. ret.updateTimeStamp()
  27. ret.loadData()
  28. return ret
  29. }
  30. // 更新时间戳
  31. func (ub *userInfo) updateTimeStamp() {
  32. ub.timeStamp = common.GetTimeStamp() + idle_seconds
  33. return
  34. }
  35. // 加载用户数据
  36. func (ub *userInfo) loadData() {
  37. ub.badgeList = transGetUserBadgeList(ub.userId)
  38. ub.checkBadgeIsShow()
  39. ub.loadBadgeUnlockTime()
  40. ub.doCheck()
  41. pos := []int{1, 1, 1}
  42. for _, v := range ub.badgeList {
  43. if v.Position == 0 {
  44. pos[0] = 0
  45. }
  46. if v.Position == 1 {
  47. pos[1] = 0
  48. }
  49. if v.Position == 2 {
  50. pos[2] = 0
  51. }
  52. }
  53. for _, v := range ub.badgeList {
  54. if v.Position != -1 {
  55. continue
  56. }
  57. for i := 0; i < 3; i++ {
  58. if pos[i] == 1 {
  59. ub.autoWearBadge(v.BadgeId, i)
  60. pos[i] = 0
  61. break
  62. }
  63. }
  64. }
  65. return
  66. }
  67. // 轮询检查
  68. func (ub *userInfo) doCheck() {
  69. ticker := time.NewTicker(10 * time.Minute)
  70. go func(t *time.Ticker) {
  71. for {
  72. select {
  73. case <-ub.endChan:
  74. t.Stop()
  75. return
  76. case <-t.C:
  77. // 每十分钟执行一次
  78. go ub.checkBadgeExpires()
  79. }
  80. }
  81. }(ticker)
  82. }
  83. // 检查徽章是否显示
  84. func (ub *userInfo) checkBadgeIsShow() {
  85. badgeList := []*pb.UserBadge{}
  86. for _, v := range ub.badgeList {
  87. sysBadge := mgr.getSysBadgeInfo(v.BadgeId)
  88. if sysBadge == nil {
  89. log.Debug("userInfo.checkBadgeIsShow config not found. userId[%d]", ub.userId)
  90. continue
  91. }
  92. if sysBadge.Model == 0 && !sysBadge.IsShow {
  93. continue
  94. }
  95. level, lvPoints := pb.GetLevel(v.Exps, sysBadge.Levels)
  96. if level != v.Level {
  97. addPoints := ub.addUnlockTimeAndPoint(level, lvPoints, v)
  98. v.Level = level
  99. v.Points = addPoints
  100. go transSaveUserBadge(ub.userId, v)
  101. }
  102. badgeList = append(badgeList, v)
  103. }
  104. ub.badgeList = badgeList
  105. }
  106. // 徽章等级的解锁时间
  107. func (ub *userInfo) loadBadgeUnlockTime() {
  108. for k, v := range ub.badgeList {
  109. if v.Level >= pb.UsageLevel {
  110. ub.badgeList[k].Wearable = true
  111. }
  112. var arr []string
  113. if err := json.Unmarshal([]byte(v.ObtainDate), &arr); err != nil {
  114. log.Debug("userInfo.loadBadgeUnlockTime Unmarshal fail. err:%+v", err)
  115. continue
  116. }
  117. for _, s := range arr {
  118. ub.badgeList[k].UnlockTime = append(ub.badgeList[k].UnlockTime, int(common.ParseTime(s).Unix()))
  119. }
  120. }
  121. }
  122. // 析构,停止计时器等
  123. func (ub *userInfo) destructor() {
  124. close(ub.endChan)
  125. }
  126. // 检查徽章过期
  127. func (ub *userInfo) checkBadgeExpires() {
  128. for k, v := range ub.badgeList {
  129. if v.ExpiresTime == 0 {
  130. continue
  131. }
  132. if !v.IsExpires() {
  133. continue
  134. }
  135. ub.badgeList[k].Level = 0
  136. ub.badgeList[k].Position = -1
  137. ub.badgeList[k].ExpiresTime = 0
  138. go transSaveUserBadge(ub.userId, v)
  139. go user.UpdateUserInfo(ub.userId)
  140. log.Debug("userInfo.checkBadgeExpires userId=%d badgeId=%d 已取下所有用户对应的荣耀徽章", ub.userId, v.BadgeId)
  141. }
  142. }
  143. // 是否过期
  144. func (ub *userInfo) isExpire() bool {
  145. return ub.timeStamp < common.GetTimeStamp()
  146. }
  147. // 获取用户徽章列表
  148. func (ub *userInfo) getUserBadgeList() []*pb.UserBadge {
  149. return ub.badgeList
  150. }
  151. // 获取用户佩戴与展示的徽章
  152. func (ub *userInfo) getBadgeWearAndShow() []pb.BadgePosition {
  153. var list []pb.BadgePosition
  154. for _, v := range mgr.sysList {
  155. if v.Model == 0 && !v.IsShow {
  156. continue
  157. }
  158. info := ub.getUserBadge(v.BadgeId)
  159. if info == nil {
  160. continue
  161. }
  162. if v.Model == 0 && info.Position < 0 {
  163. continue
  164. }
  165. if info.Level < pb.UsageLevel {
  166. continue
  167. }
  168. list = append(list, pb.BadgePosition{
  169. Position: info.Position,
  170. BadgeId: info.BadgeId,
  171. Level: info.Level,
  172. })
  173. }
  174. sort.SliceStable(list, func(i, j int) bool {
  175. return list[i].Position < list[j].Position
  176. })
  177. return list
  178. }
  179. func (ub *userInfo) autoWearBadge(badgeId, position int) {
  180. userBadge := ub.getUserBadge(badgeId)
  181. if userBadge == nil || !userBadge.IsWearable() {
  182. return
  183. }
  184. oldPosition := -1
  185. existBadgeId := 0
  186. // 如果已佩戴,先卸掉
  187. for _, v := range ub.badgeList {
  188. if v.BadgeId == badgeId {
  189. // 如果已佩戴,可能涉及交换位置
  190. oldPosition = v.Position
  191. v.Position = -1
  192. }
  193. // 找出占位徽章ID
  194. if position > -1 && v.Position == position {
  195. existBadgeId = v.BadgeId
  196. }
  197. }
  198. // 如果卸下
  199. if position == -1 {
  200. go transSaveUserBadge(ub.userId, userBadge)
  201. user.UpdateUserInfo(ub.userId)
  202. return
  203. }
  204. sysBadge := mgr.getSysBadgeInfo(badgeId)
  205. if sysBadge == nil {
  206. log.Debug("userInfo.wearBadge config not found. userId[%d]", ub.userId)
  207. return
  208. }
  209. for _, v := range ub.badgeList {
  210. if v.BadgeId == badgeId {
  211. // 禁止换到新位置
  212. if existBadgeId == 0 {
  213. if !sysBadge.IsShow {
  214. v.Position = oldPosition
  215. continue
  216. }
  217. }
  218. // 已佩戴的可互调位置
  219. v.Position = position
  220. if oldPosition == -1 {
  221. if !sysBadge.IsShow {
  222. v.Position = -1
  223. }
  224. }
  225. go transSaveUserBadge(ub.userId, userBadge)
  226. continue
  227. }
  228. // 如果存在交换
  229. if existBadgeId == v.BadgeId {
  230. v.Position = oldPosition
  231. existBadge := ub.getUserBadge(v.BadgeId)
  232. if existBadge == nil {
  233. log.Debug("userInfo.wearBadge badgeId not fount, badgeId[%d]", v.BadgeId)
  234. continue
  235. }
  236. go transSaveUserBadge(ub.userId, existBadge)
  237. }
  238. }
  239. user.UpdateUserInfo(ub.userId)
  240. }
  241. // 佩戴成就徽章
  242. // @param badgeId int 徽章id
  243. // @param position int 位置(-1:未佩戴,0-2对应位置)
  244. func (ub *userInfo) wearBadge(badgeId, position int) []pb.BadgePosition {
  245. userBadge := ub.getUserBadge(badgeId)
  246. if userBadge == nil || !userBadge.IsWearable() {
  247. return ub.getBadgeWearAndShow()
  248. }
  249. oldPosition := -1
  250. existBadgeId := 0
  251. // 如果已佩戴,先卸掉
  252. for _, v := range ub.badgeList {
  253. if v.BadgeId == badgeId {
  254. // 如果已佩戴,可能涉及交换位置
  255. oldPosition = v.Position
  256. v.Position = -1
  257. }
  258. // 找出占位徽章ID
  259. if position > -1 && v.Position == position {
  260. existBadgeId = v.BadgeId
  261. }
  262. }
  263. // 如果卸下
  264. if position == -1 {
  265. go transSaveUserBadge(ub.userId, userBadge)
  266. user.UpdateUserInfo(ub.userId)
  267. return ub.getBadgeWearAndShow()
  268. }
  269. sysBadge := mgr.getSysBadgeInfo(badgeId)
  270. if sysBadge == nil {
  271. log.Debug("userInfo.wearBadge config not found. userId[%d]", ub.userId)
  272. return ub.getBadgeWearAndShow()
  273. }
  274. for _, v := range ub.badgeList {
  275. if v.BadgeId == badgeId {
  276. // 禁止换到新位置
  277. if existBadgeId == 0 {
  278. if !sysBadge.IsShow {
  279. v.Position = oldPosition
  280. continue
  281. }
  282. }
  283. // 已佩戴的可互调位置
  284. v.Position = position
  285. if oldPosition == -1 {
  286. if !sysBadge.IsShow {
  287. v.Position = -1
  288. }
  289. }
  290. go transSaveUserBadge(ub.userId, userBadge)
  291. continue
  292. }
  293. // 如果存在交换
  294. if existBadgeId == v.BadgeId {
  295. v.Position = oldPosition
  296. existBadge := ub.getUserBadge(v.BadgeId)
  297. if existBadge == nil {
  298. log.Debug("userInfo.wearBadge badgeId not fount, badgeId[%d]", v.BadgeId)
  299. continue
  300. }
  301. go transSaveUserBadge(ub.userId, existBadge)
  302. }
  303. }
  304. user.UpdateUserInfo(ub.userId)
  305. return ub.getBadgeWearAndShow()
  306. }
  307. // 获取用户徽章
  308. func (ub *userInfo) getUserBadge(badgeId int) *pb.UserBadge {
  309. for k, v := range ub.badgeList {
  310. if v.BadgeId == badgeId {
  311. return ub.badgeList[k]
  312. }
  313. }
  314. return nil
  315. }
  316. // 触发动作,根据经验值重新计算 level
  317. func (ub *userInfo) doAction(action, progress int, param pb.Scope) {
  318. // 消耗金币暂不处理,金币进度只统计购买道具消耗金币
  319. if action == pb.Action_ConsumeGold {
  320. return
  321. }
  322. now := common.GetNowTime()
  323. //currIndex := common.GetWeekIndex(int(now.Unix()))
  324. //crdateTime := int(common.ParseTime(param.RankCrdate).Unix())
  325. //crdateIndex := common.GetWeekIndex(crdateTime)
  326. //multiple := currIndex - crdateIndex + 1
  327. // badge 信息
  328. for _, v := range mgr.sysList {
  329. if v.Action != action {
  330. continue
  331. }
  332. if !v.IsCollection {
  333. log.Debug("userInfo.doAction Currently badges are not collected. userId[%d], action[%d], v[%+v]",
  334. ub.userId, action, v)
  335. continue
  336. }
  337. if pb.Action_Game_CallPoints == action && !pb.CheckRankingScore(v.BadgeScope.Ranks, param.RankInfo) {
  338. log.Debug("userInfo.doAction Insufficient score. userId[%d], action[%d], RankInfo[%+v], v[%+v]",
  339. ub.userId, action, param.RankInfo, v)
  340. continue
  341. }
  342. if len(v.BadgeScope.GameNames) > 0 && !v.IsApplicative(param) {
  343. log.Debug("userInfo.doAction gameNames config nod found. userId[%d], action[%d], GameName[%s], v[%+v]",
  344. ub.userId, action, param.GameName, v)
  345. continue
  346. }
  347. if len(v.BadgeScope.GiftIds) > 0 && !pb.GameMatch(v.BadgeScope.GiftIds, param.GiftId) {
  348. log.Debug("userInfo.doAction giftId config nod found. userId[%d], action[%d], GiftId[%+v], v[%+v]",
  349. ub.userId, action, param.GiftId, v)
  350. continue
  351. }
  352. if len(v.BadgeScope.ItemIds) > 0 && !pb.GiftIdMatch(v.BadgeScope.ItemIds, param.Items) {
  353. log.Debug("userInfo.doAction itemId config nod found. userId[%d], action[%d], ItemId[%+v], v[%+v]",
  354. ub.userId, action, param.Items, v)
  355. continue
  356. }
  357. if len(v.BadgeScope.TaskIds) > 0 && !pb.GameMatch(v.BadgeScope.TaskIds, param.TaskId) {
  358. log.Debug("userInfo.doAction taskId config nod found. userId[%d], action[%d], TaskId[%+v], v[%+v]",
  359. ub.userId, action, param.TaskId, v)
  360. continue
  361. }
  362. var isNew, isChange, isLevelChange bool
  363. var noticePoints int
  364. userBadge := ub.getUserBadge(v.BadgeId)
  365. if userBadge == nil {
  366. // 新增徽章
  367. isNew = true
  368. userBadge = &pb.UserBadge{}
  369. userBadge.BadgeId = v.BadgeId
  370. userBadge.ObtainDate = "[]"
  371. userBadge.Position = -1
  372. userBadge.Crdate = common.GetNowTimeStr()
  373. }
  374. // 成就徽章(生涯)
  375. if v.BadgeType == pb.BadgeType_Achievement {
  376. userBadge.Exps += progress
  377. level, lvPoints := pb.GetLevel(userBadge.Exps, v.Levels) // 计算 level、点数
  378. if level > userBadge.Level {
  379. isChange = true
  380. isLevelChange = true
  381. addPoints := ub.addUnlockTimeAndPoint(level, lvPoints, userBadge)
  382. userBadge.Level = level
  383. userBadge.Points += addPoints
  384. noticePoints = lvPoints[level]
  385. }
  386. }
  387. // 荣耀徽章
  388. if v.BadgeType == pb.BadgeType_Honor {
  389. if v.Action != pb.Action_NoviceGuide {
  390. // 只取零点且前三十分钟的数据才有效[00:30]
  391. if !(now.Hour() == 0 && now.Minute() < 30) {
  392. continue
  393. }
  394. if !pb.CheckRankingScore(v.BadgeScope.Ranks, param.RankInfo) {
  395. continue
  396. }
  397. }
  398. //expiresTime := crdateTime + v.Duration*multiple - 1
  399. //if common.IsSameWeek(expiresTime, userBadge.ExpiresTime) {
  400. // // 已统计过,无需重复统计
  401. // continue
  402. //}
  403. // TODO Start 测试,验收成功后将删除此逻辑。为了方便测试徽章到期时间,直接获取当天到零点剩余时间
  404. endOfDay := time.Date(now.Year(), now.Month(), now.Day(), 23, 59, 59, 0, now.Location())
  405. expiresTime := int(endOfDay.Unix())
  406. if common.IsSameDay(expiresTime, userBadge.ExpiresTime) {
  407. // 已统计过,无需重复统计
  408. continue
  409. }
  410. log.Debug("-------------------\r\n"+
  411. "用户ID:%d\r\n"+
  412. "榜单日期:%s\r\n"+
  413. "榜单类型:%d\r\n"+
  414. "榜单排名:%d\r\n"+
  415. "当前系统榜单:%v\r\n"+
  416. "过期时间:%s\r\n"+
  417. "-------------------",
  418. ub.userId, param.RankCrdate, param.Type, param.Rank, v.BadgeScope.Ranks, common.TimeStampToString(endOfDay.Unix()))
  419. // TODO End
  420. // 只记录第一次解锁的时间
  421. if len(userBadge.UnlockTime) == 0 {
  422. ub.addUnlockTimeAndPoint(0, nil, userBadge)
  423. }
  424. isChange = true
  425. userBadge.Times++
  426. userBadge.Level = pb.MaxLevel
  427. userBadge.ExpiresTime = expiresTime
  428. }
  429. if userBadge.Level >= pb.UsageLevel {
  430. userBadge.Wearable = true
  431. }
  432. if isNew {
  433. ub.badgeList = append(ub.badgeList, userBadge)
  434. }
  435. // 存入数据库
  436. go transSaveUserBadge(ub.userId, userBadge)
  437. if isLevelChange && userBadge.Position != -1 {
  438. ub.autoWearBadge(userBadge.BadgeId, userBadge.Position)
  439. } else {
  440. pos := []int{1, 1, 1}
  441. for _, v := range ub.badgeList {
  442. if v.Position == 0 {
  443. pos[0] = 0
  444. }
  445. if v.Position == 1 {
  446. pos[1] = 0
  447. }
  448. if v.Position == 2 {
  449. pos[2] = 0
  450. }
  451. }
  452. for i := 0; i < 3; i++ {
  453. if pos[i] == 1 {
  454. ub.autoWearBadge(userBadge.BadgeId, i)
  455. break
  456. }
  457. }
  458. }
  459. // 通知客户端,属性有变化
  460. if isChange {
  461. noticeUser := pb.UserBadge{
  462. BadgeId: userBadge.BadgeId,
  463. Badge_Level: pb.Badge_Level{
  464. Level: userBadge.Level,
  465. Exps: userBadge.Exps,
  466. Points: noticePoints,
  467. },
  468. Times: userBadge.Times,
  469. Position: userBadge.Position,
  470. Wearable: userBadge.Wearable,
  471. ExpiresTime: userBadge.ExpiresTime,
  472. ObtainDate: userBadge.ObtainDate,
  473. UnlockTime: userBadge.UnlockTime,
  474. }
  475. d, _ := json.Marshal(noticeUser)
  476. notification.AddNotification(ub.userId, notification.Notification_BadgeChange, string(d))
  477. }
  478. user.UpdateUserInfo(ub.userId)
  479. log.Debug("userInfo.doAction success!"+
  480. "userId[%d], action[%d], progress[%d], param[%+v], userBadge[%+v], configBadge[%+v],"+
  481. "current Time:[%s]",
  482. ub.userId, action, progress, param, userBadge, v, common.TimeStampToString(int64(common.GetTimeStamp())))
  483. }
  484. }
  485. // 添加解锁的时间和点数
  486. func (ub *userInfo) addUnlockTimeAndPoint(level int, lvPoints map[int]int, userBadge *pb.UserBadge) int {
  487. var point int
  488. if level != 0 && level != userBadge.Level+1 {
  489. var unlockTime []int
  490. // 处理跨等级
  491. for i := 0; i < level; i++ {
  492. if userBadge.Level > 0 && userBadge.Level == i+1 {
  493. if len(userBadge.UnlockTime) > i {
  494. unlockTime = append(unlockTime, userBadge.UnlockTime[i])
  495. }
  496. continue
  497. }
  498. point += lvPoints[i+1]
  499. unlockTime = append(unlockTime, common.GetTimeStamp())
  500. }
  501. userBadge.UnlockTime = unlockTime
  502. } else {
  503. if v, ok := lvPoints[level]; ok {
  504. point = v
  505. }
  506. userBadge.UnlockTime = append(userBadge.UnlockTime, common.GetTimeStamp())
  507. }
  508. var arr []string
  509. for _, v := range userBadge.UnlockTime {
  510. arr = append(arr, common.TimeStampToString(int64(v)))
  511. }
  512. d, _ := json.Marshal(arr)
  513. userBadge.ObtainDate = string(d)
  514. return point
  515. }