extra_func.go 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. package service
  2. import (
  3. "context"
  4. "math/rand"
  5. "sync"
  6. "time"
  7. model "go-common/app/interface/main/credit/model"
  8. acmdl "go-common/app/service/main/account/api"
  9. "go-common/library/ecode"
  10. "go-common/library/log"
  11. "go-common/library/sync/errgroup"
  12. )
  13. func (s *Service) caseVoteID(c context.Context, mid int64, pubCid int64) (cid int64, err error) {
  14. // 获取发放中cids的列表
  15. mcases, err := s.dao.GrantCases(c)
  16. if err != nil {
  17. log.Error("s.dao.GrantCases error(%v)", err)
  18. return
  19. }
  20. if len(mcases) == 0 {
  21. log.Warn("no grant cases(%+v)!", mcases)
  22. return
  23. }
  24. // 7天内已投cids
  25. weekcases, err := s._caseObtainMID(c, mid, 7, model.CaseObtainNoToday)
  26. if err != nil {
  27. log.Error("s._caseObtainMID(%d, 7, %t) error(%v)", mid, model.CaseObtainNoToday, err)
  28. return
  29. }
  30. // 今天内已投cids
  31. todaycases, err := s._caseObtainMID(c, mid, 0, model.CaseObtainToday)
  32. if err != nil {
  33. log.Error("s._caseObtainMID(%d, 0, %t) error(%v)", mid, model.CaseObtainToday, err)
  34. return
  35. }
  36. todayPubVote := 0
  37. tpmcids := make(map[int64]struct{})
  38. // 今天已投cid的map
  39. for _, tcase := range todaycases {
  40. if tcase.CaseType == model.JudeCaseTypePublic {
  41. tpmcids[tcase.ID] = struct{}{}
  42. todayPubVote++
  43. }
  44. }
  45. vcids := []int64{}
  46. for wcid := range weekcases {
  47. vcids = append(vcids, wcid)
  48. }
  49. for cid, m := range mcases {
  50. if _, ok := tpmcids[cid]; !ok && m.CaseType == model.JudeCaseTypePublic {
  51. todayPubVote++
  52. }
  53. // 把被举报人是风纪委用户自己和结案时间后10分钟的稿件 加入用户已投稿列表
  54. if m.Mid == mid || m.Etime.Time().Add(-time.Duration(s.c.Judge.ReservedTime)).Before(time.Now()) {
  55. vcids = append(vcids, cid)
  56. continue
  57. }
  58. }
  59. tLen := len(todaycases)
  60. // 获取案件最大数判断
  61. if int64(tLen-todayPubVote) >= s.c.Judge.CaseObtainMax {
  62. err = ecode.CreditCaseMax
  63. return
  64. }
  65. // 制作非可投cids的map
  66. vmcids := make(map[int64]struct{})
  67. for _, uncid := range vcids {
  68. vmcids[uncid] = struct{}{}
  69. }
  70. // 小众
  71. pteCids := make([]int64, 0)
  72. // 大众
  73. pubCids := make([]int64, 0)
  74. // 大众cid的map
  75. mpCids := make(map[int64]struct{})
  76. // 取出可投cids
  77. for kcid, m := range mcases {
  78. if _, ok := vmcids[kcid]; ok {
  79. continue
  80. }
  81. if m.CaseType == model.JudeCaseTypePublic {
  82. pubCids = append(pubCids, kcid)
  83. mpCids[kcid] = struct{}{}
  84. } else {
  85. pteCids = append(pteCids, kcid)
  86. }
  87. }
  88. pubLen := len(pubCids)
  89. pteLen := len(pteCids)
  90. // 没有可投的案件
  91. if pubLen+pteLen == 0 {
  92. log.Warn("mid(%d) no case can vote!", mid)
  93. return
  94. }
  95. var caseType int8
  96. _, ok := mpCids[pubCid]
  97. if pubCid != 0 && !ok {
  98. return
  99. }
  100. if pubCid != 0 && ok {
  101. cid = pubCid
  102. caseType = model.JudeCaseTypePublic
  103. } else {
  104. radio := rand.New(rand.NewSource(time.Now().UnixNano()))
  105. if pubLen > 0 {
  106. cid = s._randCid(pubCids, radio)
  107. caseType = model.JudeCaseTypePublic
  108. } else if pteLen > 0 {
  109. cid = s._randCid(pteCids, radio)
  110. caseType = model.JudeCaseTypePrivate
  111. }
  112. }
  113. // db插入用户投票数据
  114. if err = s.dao.InsVote(c, mid, cid, s.c.Judge.CaseCheckTime); err != nil {
  115. log.Error("s.dao.InsVote( mid(%d), cid(%d), s.c.Judge.CaseCheckTime(%d)) error(%v)", mid, cid, s.c.Judge.CaseCheckTime, err)
  116. return
  117. }
  118. mcid := &model.SimCase{ID: cid, CaseType: caseType}
  119. // 从redis的set中设置用户已投cids
  120. if err = s.dao.SetVoteCaseMID(c, mid, mcid); err != nil {
  121. log.Error("s.dao.SetVoteCaseMID(%d,%+v) error(%v)", mid, mcid, err)
  122. return
  123. }
  124. log.Info("CaseObtain mid:%d total:%d CaseObtainMax:%d cid:%d", mid, int64(tLen+todayPubVote), s.c.Judge.CaseObtainMax, cid)
  125. // db插入case投放总数
  126. if err = s.dao.AddCaseVoteTotal(c, "put_total", cid, 1); err != nil {
  127. log.Error("s.dao.InsVote( mid(%d), cid(%d), s.c.Judge.CaseCheckTime(%d)) error(%v)", mid, cid, s.c.Judge.CaseCheckTime, err)
  128. }
  129. return
  130. }
  131. // 获取用户N天内已投列表
  132. func (s *Service) _caseObtainMID(c context.Context, mid int64, day int, isToday bool) (cases map[int64]*model.SimCase, err error) {
  133. isExpired, err := s.dao.IsExpiredObtainMID(c, mid, isToday)
  134. if err != nil {
  135. log.Error("s.dao.IsExpiredObtainMID(%d,%t) error(%v)", mid, isToday, err)
  136. return
  137. }
  138. if isExpired {
  139. cases, err = s.dao.CaseObtainMID(c, mid, isToday)
  140. if err != nil {
  141. log.Error("s.dao.CaseObtainByMID(%d,%t) error(%v)", mid, isToday, err)
  142. return
  143. }
  144. } else {
  145. if cases, err = s.dao.LoadVoteIDsMid(c, mid, day); err != nil {
  146. log.Error("s.dao.LoadVoteIDsMid(%d,%d) error(%v)", mid, day, err)
  147. return
  148. }
  149. if len(cases) == 0 {
  150. return
  151. }
  152. s.addCache(func() {
  153. if err = s.dao.LoadVoteCaseMID(context.TODO(), mid, cases, isToday); err != nil {
  154. log.Error("s.dao.LoadVoteCaseMID(%d,%v,%t) error(%v)", mid, cases, isToday, err)
  155. return
  156. }
  157. })
  158. }
  159. return
  160. }
  161. // cid 取值的随机算法
  162. func (s *Service) _randCid(cids []int64, radio *rand.Rand) (cid int64) {
  163. // 随机取出数组的游标
  164. rand := int64(radio.Intn(len(cids)))
  165. cid = cids[rand]
  166. return
  167. }
  168. // 列表批量异步获取用户信息
  169. func (s *Service) infoMap(c context.Context, uids []int64) (infoMap map[int64]*acmdl.Info, err error) {
  170. total := len(uids)
  171. pageNum := total / model.JuryMultiJuryerInfoMax
  172. if total%model.JuryMultiJuryerInfoMax != 0 {
  173. pageNum++
  174. }
  175. var (
  176. g errgroup.Group
  177. lk sync.RWMutex
  178. )
  179. infoMap = make(map[int64]*acmdl.Info, total)
  180. for i := 0; i < pageNum; i++ {
  181. start := i * model.JuryMultiJuryerInfoMax
  182. end := (i + 1) * model.JuryMultiJuryerInfoMax
  183. if end > total {
  184. end = total
  185. }
  186. g.Go(func() (err error) {
  187. var (
  188. arg = &acmdl.MidsReq{Mids: uids[start:end]}
  189. res *acmdl.InfosReply
  190. )
  191. if res, err = s.accountClient.Infos3(c, arg); err != nil {
  192. log.Error("s.accountClient.Infos3(%v) error(%v)", arg, err)
  193. err = nil
  194. } else {
  195. for uid, info := range res.Infos {
  196. lk.Lock()
  197. infoMap[uid] = info
  198. lk.Unlock()
  199. }
  200. }
  201. return
  202. })
  203. }
  204. if err = g.Wait(); err != nil {
  205. log.Error("g.Wait() error(%v)", err)
  206. }
  207. return
  208. }
  209. // userInfo one user card.
  210. func (s *Service) userInfo(c context.Context, mid int64) (card *acmdl.CardReply, err error) {
  211. if mid == 0 {
  212. return
  213. }
  214. arg := &acmdl.MidReq{
  215. Mid: mid,
  216. }
  217. if card, err = s.accountClient.Card3(c, arg); err != nil {
  218. log.Error("s.accountClient.Card3(%+v) error(%+v)", arg, err)
  219. }
  220. return
  221. }