match.go 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302
  1. package like
  2. import (
  3. "context"
  4. "encoding/json"
  5. "time"
  6. "go-common/app/interface/main/activity/conf"
  7. dao "go-common/app/interface/main/activity/dao/like"
  8. match "go-common/app/interface/main/activity/model/like"
  9. coinmdl "go-common/app/service/main/coin/model"
  10. suitmdl "go-common/app/service/main/usersuit/model"
  11. "go-common/library/ecode"
  12. "go-common/library/log"
  13. "go-common/library/net/metadata"
  14. "go-common/library/sync/errgroup"
  15. )
  16. const (
  17. _matchTable = "act_matchs"
  18. _objectTable = "act_matchs_object"
  19. _userLogTable = "act_match_user_log"
  20. _reason = "参与竞猜"
  21. )
  22. var (
  23. _emptyMatch = make([]*match.Match, 0)
  24. _emptyObjects = make([]*match.Object, 0)
  25. _emptyUserLog = make([]*match.UserLog, 0)
  26. _emptyFollow = make([]string, 0)
  27. )
  28. // Match get match.
  29. func (s *Service) Match(c context.Context, sid int64) (rs []*match.Match, err error) {
  30. // get from cache.
  31. if rs, err = s.dao.ActMatchCache(c, sid); err != nil || len(rs) == 0 {
  32. if rs, err = s.dao.ActMatch(c, sid); err != nil {
  33. log.Error("s.dao.Match sid(%d) error(%v)", sid, err)
  34. return
  35. }
  36. if len(rs) == 0 {
  37. rs = _emptyMatch
  38. return
  39. }
  40. s.cache.Do(c, func(c context.Context) {
  41. s.dao.SetActMatchCache(c, sid, rs)
  42. })
  43. }
  44. return
  45. }
  46. // AddGuess add match guess.
  47. func (s *Service) AddGuess(c context.Context, mid int64, p *match.ParamAddGuess) (rs int64, err error) {
  48. var (
  49. object *match.Object
  50. userGuess []*match.UserLog
  51. group *errgroup.Group
  52. coinErr, suitErr error
  53. count float64
  54. ip = metadata.String(c, metadata.RemoteIP)
  55. )
  56. if p.Stake > conf.Conf.Rule.MaxGuessCoin {
  57. err = ecode.ActivityOverCoin
  58. return
  59. }
  60. //check mid coin count
  61. if count, err = s.coin.UserCoins(c, &coinmdl.ArgCoinInfo{Mid: mid, RealIP: ip}); err != nil {
  62. dao.PromError("UserCoins接口错误", "s.coin.UserCoins(%d,%s) error(%v)", mid, ip, err)
  63. return
  64. }
  65. if count < float64(p.Stake) {
  66. err = ecode.ActivityNotEnoughCoin
  67. return
  68. }
  69. // get from cache.
  70. if object, err = s.dao.ObjectCache(c, p.ObjID); err != nil || object == nil {
  71. if object, err = s.dao.Object(c, p.ObjID); err != nil {
  72. log.Error("s.dao.Match id(%d) error(%v)", p.ObjID, err)
  73. return
  74. }
  75. if object == nil || object.ID == 0 {
  76. err = ecode.ActivityNotExist
  77. return
  78. }
  79. s.cache.Do(c, func(c context.Context) {
  80. s.dao.SetObjectCache(c, p.ObjID, object)
  81. })
  82. }
  83. if time.Now().Unix() < object.Stime.Time().Unix() {
  84. err = ecode.ActivityNotStart
  85. return
  86. } else if object.Result > 0 || time.Now().Unix() > object.Etime.Time().Unix() {
  87. err = ecode.ActivityOverEnd
  88. return
  89. }
  90. sid := object.Sid
  91. if userGuess, err = s.ListGuess(c, sid, mid); err != nil {
  92. log.Error("s.ListGuess(%d,%d) error(%v)", sid, mid, err)
  93. return
  94. }
  95. for _, userLog := range userGuess {
  96. if userLog.MOId == p.ObjID {
  97. err = ecode.ActivityHaveGuess
  98. return
  99. }
  100. }
  101. if rs, err = s.dao.AddGuess(c, mid, object.MatchId, p.ObjID, sid, p.Result, p.Stake); err != nil || rs == 0 {
  102. log.Error("s.dao.AddGuess matchID(%d) objectID(%d) sid(%d) error(%v)", object.MatchId, p.ObjID, sid, err)
  103. return
  104. }
  105. s.dao.DelUserLogCache(context.Background(), sid, mid)
  106. group, errCtx := errgroup.WithContext(c)
  107. if len(s.c.Rule.SuitPids) > 0 && len(userGuess)+1 == s.c.Rule.GuessCount {
  108. for _, v := range s.c.Rule.SuitPids {
  109. pid := v
  110. group.Go(func() error {
  111. mids := []int64{mid}
  112. if suitErr = s.suit.GrantByMids(errCtx, &suitmdl.ArgGrantByMids{Mids: mids, Pid: pid, Expire: s.c.Rule.SuitExpire}); suitErr != nil {
  113. dao.PromError("GrantByMids接口错误", "s.suit.GrantByMids(%d,%d,%s) error(%v)", mid, p.Stake, ip, suitErr)
  114. }
  115. return nil
  116. })
  117. }
  118. }
  119. group.Go(func() error {
  120. loseCoin := float64(-p.Stake)
  121. if _, coinErr = s.coin.ModifyCoin(errCtx, &coinmdl.ArgModifyCoin{Mid: mid, Count: loseCoin, Reason: _reason, IP: ip}); coinErr != nil {
  122. dao.PromError("ModifyCoin接口错误", "s.coin.ModifyCoin(%d,%d,%s) error(%v)", mid, p.Stake, ip, coinErr)
  123. }
  124. return nil
  125. })
  126. if s.c.Rule.MatchLotteryID > 0 {
  127. group.Go(func() error {
  128. if lotteryErr := s.dao.AddLotteryTimes(errCtx, s.c.Rule.MatchLotteryID, mid); lotteryErr != nil {
  129. log.Error("s.dao.AddLotteryTimes(%d,%d) error(%+v)", s.c.Rule.MatchLotteryID, mid, lotteryErr)
  130. }
  131. return nil
  132. })
  133. }
  134. group.Wait()
  135. return
  136. }
  137. // ListGuess get match guess list.
  138. func (s *Service) ListGuess(c context.Context, sid, mid int64) (rs []*match.UserLog, err error) {
  139. // get from cache.
  140. if rs, err = s.dao.UserLogCache(c, sid, mid); err != nil || len(rs) == 0 {
  141. if rs, err = s.dao.ListGuess(c, sid, mid); err != nil {
  142. log.Error("s.dao.ListGuess sid(%d) mid(%d) error(%v)", sid, mid, err)
  143. return
  144. }
  145. if len(rs) == 0 {
  146. rs = _emptyUserLog
  147. return
  148. }
  149. }
  150. var (
  151. moIDs []int64
  152. objects map[int64]*match.Object
  153. )
  154. for _, v := range rs {
  155. moIDs = append(moIDs, v.MOId)
  156. }
  157. if len(moIDs) == 0 {
  158. return
  159. }
  160. if objects, err = s.dao.MatchSubjects(c, moIDs); err == nil {
  161. for _, v := range rs {
  162. if obj, ok := objects[v.MOId]; ok {
  163. v.HomeName = obj.HomeName
  164. v.AwayName = obj.AwayName
  165. v.ObjResult = obj.Result
  166. v.GameStime = obj.GameStime
  167. }
  168. }
  169. }
  170. s.cache.Do(c, func(c context.Context) {
  171. s.dao.SetUserLogCache(c, sid, mid, rs)
  172. })
  173. return
  174. }
  175. // Guess user guess
  176. func (s *Service) Guess(c context.Context, mid int64, p *match.ParamSid) (rs *match.UserGuess, err error) {
  177. var (
  178. userGuess []*match.UserLog
  179. totalCont, winCount int64
  180. )
  181. if userGuess, err = s.ListGuess(c, p.Sid, mid); err != nil {
  182. log.Error("s.ListGuess(%d,%d) error(%v)", p.Sid, mid, err)
  183. return
  184. }
  185. for _, guess := range userGuess {
  186. if guess.ObjResult > 0 {
  187. if guess.Result == guess.ObjResult {
  188. winCount++
  189. }
  190. totalCont++
  191. }
  192. }
  193. rs = new(match.UserGuess)
  194. rs.Total = totalCont
  195. rs.Win = winCount
  196. return
  197. }
  198. // ClearCache del match and object cache
  199. func (s *Service) ClearCache(c context.Context, msg string) (err error) {
  200. var m struct {
  201. Table string `json:"table"`
  202. New struct {
  203. ID int64 `json:"id"`
  204. Sid int64 `json:"sid"`
  205. MatID int64 `json:"match_id"`
  206. Mid int64 `json:"mid"`
  207. MOId int64 `json:"m_o_id"`
  208. } `json:"new,omitempty"`
  209. }
  210. if err = json.Unmarshal([]byte(msg), &m); err != nil {
  211. log.Error("ClearCache json.Unmarshal msg(%s) error(%v)", msg, err)
  212. return
  213. }
  214. log.Info("ClearCache json.Unmarshal msg(%s)", msg)
  215. if m.Table == _matchTable {
  216. if err = s.dao.DelActMatchCache(c, m.New.Sid, m.New.ID); err != nil {
  217. log.Error("s.dao.DelActMatchCache sid(%d) matchID(%d) error(%v)", m.New.Sid, m.New.ID, err)
  218. }
  219. } else if m.Table == _objectTable {
  220. if err = s.dao.DelObjectCache(c, m.New.ID, m.New.Sid); err != nil {
  221. log.Error("s.dao.DelObjectCache objID(%d) Sid(%d) error(%v)", m.New.ID, m.New.Sid, err)
  222. }
  223. } else if m.Table == _userLogTable {
  224. if err = s.dao.DelUserLogCache(c, m.New.Sid, m.New.Mid); err != nil {
  225. log.Error("s.dao.DelUserLogCache mid(%d) error(%v)", m.New.Mid, err)
  226. }
  227. }
  228. return
  229. }
  230. // AddFollow add match follow
  231. func (s *Service) AddFollow(c context.Context, mid int64, teams []string) (err error) {
  232. if err = s.dao.AddFollow(c, mid, teams); err != nil {
  233. log.Error("s.dao.AddFollow mid(%d) teams(%v) error(%v)", mid, teams, err)
  234. }
  235. return
  236. }
  237. // Follow get match follow
  238. func (s *Service) Follow(c context.Context, mid int64) (res []string, err error) {
  239. if res, err = s.dao.Follow(c, mid); err != nil {
  240. log.Error("s.dao.Follow mid(%d) error(%v)", mid, err)
  241. }
  242. if len(res) == 0 {
  243. res = _emptyFollow
  244. }
  245. return
  246. }
  247. // ObjectsUnStart get unstart object list.
  248. func (s *Service) ObjectsUnStart(c context.Context, mid int64, p *match.ParamObject) (rs []*match.Object, count int, err error) {
  249. var (
  250. userGuess []*match.UserLog
  251. objects []*match.Object
  252. start = (p.Pn - 1) * p.Ps
  253. end = start + p.Ps - 1
  254. )
  255. // get from cache.
  256. if rs, count, err = s.dao.ObjectsCache(c, p.Sid, start, end); err != nil || len(rs) == 0 {
  257. if objects, err = s.dao.ObjectsUnStart(c, p.Sid); err != nil {
  258. log.Error("s.dao.ObjectsUnStart id(%d) error(%v)", p.Sid, err)
  259. return
  260. }
  261. count = len(objects)
  262. if count == 0 || count < start {
  263. rs = _emptyObjects
  264. return
  265. }
  266. s.cache.Do(c, func(c context.Context) {
  267. s.dao.SetObjectsCache(c, p.Sid, objects, count)
  268. })
  269. if count > end+1 {
  270. rs = objects[start : end+1]
  271. } else {
  272. rs = objects[start:]
  273. }
  274. }
  275. if mid > 0 {
  276. if userGuess, err = s.ListGuess(c, p.Sid, mid); err != nil {
  277. log.Error("s.ListGuess(%d,%d) error(%v)", p.Sid, mid, err)
  278. err = nil
  279. }
  280. for _, rsObj := range rs {
  281. for _, guess := range userGuess {
  282. if rsObj.ID == guess.MOId {
  283. rsObj.UserResult = guess.Result
  284. break
  285. }
  286. }
  287. }
  288. }
  289. return
  290. }