bws.go 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331
  1. package bws
  2. import (
  3. "context"
  4. "strconv"
  5. "time"
  6. "go-common/app/interface/main/activity/conf"
  7. "go-common/app/interface/main/activity/dao/bws"
  8. bwsmdl "go-common/app/interface/main/activity/model/bws"
  9. accapi "go-common/app/service/main/account/api"
  10. suitmdl "go-common/app/service/main/usersuit/model"
  11. suitrpc "go-common/app/service/main/usersuit/rpc/client"
  12. "go-common/library/ecode"
  13. "go-common/library/log"
  14. "go-common/library/sync/errgroup"
  15. "go-common/library/sync/pipeline/fanout"
  16. )
  17. const (
  18. _accountBlocked = 1
  19. _allType = 0
  20. _dpType = 1
  21. _gameType = 2
  22. _clockinType = 3
  23. _eggType = 4
  24. _dp = "dp"
  25. _game = "game"
  26. _clockin = "clockin"
  27. _egg = "egg"
  28. _noAward = 0
  29. _awardAlready = 2
  30. _initLinkType = 5
  31. )
  32. var (
  33. _emptPoints = make([]*bwsmdl.Point, 0)
  34. _emptUserPoints = make([]*bwsmdl.UserPointDetail, 0)
  35. _emptyUserAchieves = make([]*bwsmdl.UserAchieveDetail, 0)
  36. )
  37. // Service struct
  38. type Service struct {
  39. c *conf.Config
  40. dao *bws.Dao
  41. accClient accapi.AccountClient
  42. suitRPC *suitrpc.Service2
  43. // bws admin mids
  44. allowMids map[int64]struct{}
  45. awardMids map[int64]struct{}
  46. lotteryMids map[int64]struct{}
  47. lotteryAids map[int64]struct{}
  48. cache *fanout.Fanout
  49. }
  50. // New Service
  51. func New(c *conf.Config) (s *Service) {
  52. s = &Service{
  53. c: c,
  54. dao: bws.New(c),
  55. suitRPC: suitrpc.New(c.RPCClient2.Suit),
  56. cache: fanout.New("cache", fanout.Worker(1), fanout.Buffer(1024)),
  57. }
  58. var err error
  59. if s.accClient, err = accapi.NewClient(c.AccClient); err != nil {
  60. panic(err)
  61. }
  62. s.initMids()
  63. s.initLotteryAids()
  64. return
  65. }
  66. func (s *Service) initMids() {
  67. tmpMids := make(map[int64]struct{}, len(s.c.Rule.BwsMids))
  68. tmpAward := make(map[int64]struct{}, len(s.c.Rule.BwsMids)+len(s.c.Rule.BwsAwardMids))
  69. tmpLottery := make(map[int64]struct{}, len(s.c.Rule.BwsMids)+len(s.c.Rule.BwsLotteryMids))
  70. for _, id := range s.c.Rule.BwsMids {
  71. tmpMids[id] = struct{}{}
  72. tmpAward[id] = struct{}{}
  73. tmpLottery[id] = struct{}{}
  74. }
  75. for _, id := range s.c.Rule.BwsAwardMids {
  76. tmpAward[id] = struct{}{}
  77. }
  78. for _, id := range s.c.Rule.BwsLotteryMids {
  79. tmpLottery[id] = struct{}{}
  80. }
  81. s.allowMids = tmpMids
  82. s.awardMids = tmpAward
  83. s.lotteryMids = tmpLottery
  84. }
  85. func (s *Service) initLotteryAids() {
  86. tmp := make(map[int64]struct{}, len(s.c.Rule.BwsLotteryAids))
  87. for _, id := range s.c.Rule.BwsLotteryAids {
  88. tmp[id] = struct{}{}
  89. }
  90. s.lotteryAids = tmp
  91. }
  92. // User user info.
  93. func (s *Service) User(c context.Context, bid, mid int64, key string) (user *bwsmdl.User, err error) {
  94. var (
  95. hp, keyID int64
  96. ac *accapi.CardReply
  97. points, dps, games, clockins, eggs []*bwsmdl.UserPointDetail
  98. achErr, pointErr error
  99. )
  100. if key == "" {
  101. if key, err = s.midToKey(c, mid); err != nil {
  102. return
  103. }
  104. } else {
  105. if mid, keyID, err = s.keyToMid(c, key); err != nil {
  106. return
  107. }
  108. }
  109. user = new(bwsmdl.User)
  110. if mid != 0 {
  111. if ac, err = s.accCard(c, mid); err != nil {
  112. log.Error("User s.accCard(%d) error(%v)", mid, err)
  113. return
  114. }
  115. }
  116. if ac != nil && ac.Card != nil {
  117. user.User = &bwsmdl.UserInfo{
  118. Mid: ac.Card.Mid,
  119. Name: ac.Card.Name,
  120. Face: ac.Card.Face,
  121. Key: key,
  122. }
  123. } else {
  124. user.User = &bwsmdl.UserInfo{
  125. Name: strconv.FormatInt(keyID, 10),
  126. Key: key,
  127. }
  128. }
  129. group, errCtx := errgroup.WithContext(c)
  130. group.Go(func() error {
  131. if user.Achievements, achErr = s.userAchieves(errCtx, bid, key); achErr != nil {
  132. log.Error("User s.userAchieves(%d,%s) error(%v)", bid, key, achErr)
  133. }
  134. return nil
  135. })
  136. group.Go(func() error {
  137. if points, pointErr = s.userPoints(errCtx, bid, key); pointErr != nil {
  138. log.Error("User s.userPoints(%d,%s) error(%v)", bid, key, pointErr)
  139. }
  140. return nil
  141. })
  142. group.Wait()
  143. if len(user.Achievements) == 0 {
  144. user.Achievements = _emptyUserAchieves
  145. }
  146. user.Items = make(map[string][]*bwsmdl.UserPointDetail, 4)
  147. gidMap := make(map[int64]int64, len(points))
  148. for _, v := range points {
  149. switch v.LockType {
  150. case _dpType:
  151. dps = append(dps, v)
  152. case _gameType:
  153. if v.Points == v.Unlocked {
  154. if _, ok := gidMap[v.Pid]; !ok {
  155. games = append(games, v)
  156. }
  157. gidMap[v.Pid] = v.Pid
  158. }
  159. case _clockinType:
  160. clockins = append(clockins, v)
  161. case _eggType:
  162. eggs = append(eggs, v)
  163. }
  164. hp += v.Points
  165. }
  166. user.User.Hp = hp
  167. if len(dps) == 0 {
  168. user.Items[_dp] = _emptUserPoints
  169. } else {
  170. user.Items[_dp] = dps
  171. }
  172. if len(games) == 0 {
  173. user.Items[_game] = _emptUserPoints
  174. } else {
  175. user.Items[_game] = games
  176. }
  177. if len(clockins) == 0 {
  178. user.Items[_clockin] = _emptUserPoints
  179. } else {
  180. user.Items[_clockin] = clockins
  181. }
  182. if len(eggs) == 0 {
  183. user.Items[_egg] = _emptUserPoints
  184. } else {
  185. user.Items[_egg] = eggs
  186. }
  187. return
  188. }
  189. func (s *Service) accCard(c context.Context, mid int64) (ac *accapi.CardReply, err error) {
  190. var (
  191. arg = &accapi.MidReq{Mid: mid}
  192. )
  193. if ac, err = s.accClient.Card3(c, arg); err != nil || ac == nil {
  194. log.Error("s.accRPC.Card3(%d) error(%v)", mid, err)
  195. err = ecode.AnswerAccCallErr
  196. } else if ac.Card.Silence == _accountBlocked {
  197. err = ecode.UserDisabled
  198. }
  199. return
  200. }
  201. // Binding binding by mid
  202. func (s *Service) Binding(c context.Context, loginMid int64, p *bwsmdl.ParamBinding) (err error) {
  203. var (
  204. achieves *bwsmdl.Achievements
  205. users *bwsmdl.Users
  206. checkMid int64
  207. )
  208. if _, err = s.accCard(c, loginMid); err != nil {
  209. log.Error("s.accCard(%d) error(%v)", loginMid, err)
  210. return
  211. }
  212. if checkMid, _, err = s.keyToMid(c, p.Key); err != nil {
  213. return
  214. }
  215. if checkMid != 0 {
  216. err = ecode.ActivityKeyBindAlready
  217. return
  218. }
  219. if users, err = s.dao.UsersMid(c, loginMid); err != nil {
  220. err = ecode.ActivityKeyFail
  221. return
  222. }
  223. if users != nil && users.Key != "" {
  224. err = ecode.ActivityMidBindAlready
  225. return
  226. }
  227. if err = s.dao.Binding(c, loginMid, p); err != nil {
  228. log.Error("s.dao.Binding mid(%d) key(%s) error(%v)", loginMid, p.Key, err)
  229. return
  230. }
  231. if s.c.Rule.NeedInitAchieve {
  232. if achieves, err = s.dao.Achievements(c, p.Bid); err != nil {
  233. log.Error("s.dao.Achievements error(%v)", err)
  234. err = ecode.ActivityAchieveFail
  235. return
  236. }
  237. if achieves == nil || len(achieves.Achievements) == 0 {
  238. err = ecode.ActivityNoAchieve
  239. return
  240. }
  241. for _, achieve := range achieves.Achievements {
  242. if achieve.LockType == _initLinkType {
  243. s.addAchieve(c, loginMid, achieve, p.Key)
  244. break
  245. }
  246. }
  247. var userAchieves []*bwsmdl.UserAchieveDetail
  248. if userAchieves, err = s.userAchieves(c, p.Bid, p.Key); err != nil {
  249. log.Error("Binding add suit key(%s) mid(%d) %+v", p.Key, loginMid, err)
  250. err = nil
  251. } else {
  252. for _, v := range userAchieves {
  253. if v.LockType == _initLinkType {
  254. continue
  255. }
  256. if suitID := v.SuitID; suitID != 0 {
  257. log.Warn("Binding suit mid(%d) suitID(%d) expire(%d)", loginMid, suitID, s.c.Rule.BwsSuitExpire)
  258. s.cache.Do(c, func(c context.Context) {
  259. arg := &suitmdl.ArgGrantByMids{Mids: []int64{loginMid}, Pid: suitID, Expire: s.c.Rule.BwsSuitExpire}
  260. if e := s.suitRPC.GrantByMids(c, arg); e != nil {
  261. log.Error("Binding s.suit.GrantByMids(%d,%d) error(%v)", loginMid, suitID, e)
  262. }
  263. })
  264. }
  265. if _, ok := s.lotteryAids[v.Aid]; ok {
  266. lotteryAid := v.Aid
  267. log.Warn("Binding lottery mid(%d) achieve id(%d) expire(%d)", loginMid, lotteryAid, s.c.Rule.BwsSuitExpire)
  268. s.cache.Do(c, func(c context.Context) {
  269. s.dao.AddLotteryMidCache(c, lotteryAid, loginMid)
  270. })
  271. }
  272. }
  273. }
  274. }
  275. s.dao.DelCacheUsersKey(c, p.Key)
  276. s.dao.DelCacheUsersMid(c, loginMid)
  277. return
  278. }
  279. func (s *Service) isAdmin(mid int64) bool {
  280. if _, ok := s.allowMids[mid]; ok {
  281. return true
  282. }
  283. return false
  284. }
  285. func (s *Service) midToKey(c context.Context, mid int64) (key string, err error) {
  286. var users *bwsmdl.Users
  287. if users, err = s.dao.UsersMid(c, mid); err != nil {
  288. err = ecode.ActivityKeyFail
  289. return
  290. }
  291. if users == nil || users.Key == "" {
  292. err = ecode.ActivityNotBind
  293. return
  294. }
  295. key = users.Key
  296. return
  297. }
  298. func (s *Service) keyToMid(c context.Context, key string) (mid, keyID int64, err error) {
  299. var users *bwsmdl.Users
  300. if users, err = s.dao.UsersKey(c, key); err != nil {
  301. err = ecode.ActivityKeyFail
  302. return
  303. }
  304. if users == nil || users.Key == "" {
  305. err = ecode.ActivityKeyNotExists
  306. return
  307. }
  308. if users.Mid > 0 {
  309. mid = users.Mid
  310. }
  311. keyID = users.ID
  312. return
  313. }
  314. func today() string {
  315. return time.Now().Format("20060102")
  316. }