score.go 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  1. package service
  2. import (
  3. "context"
  4. "fmt"
  5. "sort"
  6. "time"
  7. "go-common/app/admin/main/up-rating/dao/global"
  8. "go-common/app/admin/main/up-rating/model"
  9. "go-common/library/ecode"
  10. "go-common/library/log"
  11. "go-common/library/xstr"
  12. )
  13. // RatingList returns rating info list
  14. func (s *Service) RatingList(c context.Context, arg *model.RatingListArg, date time.Time) (res []*model.RatingInfo, total int64, err error) {
  15. var (
  16. cdate = getStartMonthlyDate(date)
  17. cdateStr = cDateStr(cdate)
  18. mon = int(cdate.Month())
  19. )
  20. res = make([]*model.RatingInfo, 0)
  21. q := scoreListQuery(arg)
  22. total = 10000
  23. // if total, err = s.dao.Total(c, mon, cdateStr, q); err != nil {
  24. // log.Error("s.dao.Total error(%v)", err)
  25. // return
  26. // }
  27. // if total == 0 {
  28. // return
  29. // }
  30. // scores
  31. q += fmt.Sprintf(" ORDER BY id ASC LIMIT %d, %d", arg.From, arg.Limit)
  32. if res, err = s.dao.ScoreList(c, mon, cdateStr, q); err != nil {
  33. log.Error("s.dao.ScoreList error(%v)", err)
  34. return
  35. }
  36. if len(res) == 0 {
  37. return
  38. }
  39. var (
  40. m = make(map[int64]*model.RatingInfo, len(res))
  41. mids = make([]int64, 0, len(res))
  42. )
  43. for _, v := range res {
  44. mids = append(mids, v.Mid)
  45. m[v.Mid] = v
  46. }
  47. // fans and avs
  48. levelInfos, err := s.dao.LevelList(c, mon, cdateStr, mids)
  49. if err != nil {
  50. log.Error("s.dao.LevelList error(%v)", err)
  51. return
  52. }
  53. for _, v := range levelInfos {
  54. score := m[v.Mid]
  55. score.TotalAvs = v.TotalAvs
  56. score.TotalFans = v.TotalFans
  57. }
  58. // nicknames
  59. r, err := global.Names(c, mids)
  60. if err != nil {
  61. log.Error("global.Names error(%v)", err)
  62. return
  63. }
  64. for _, v := range res {
  65. v.NickName = r[v.Mid]
  66. v.Date = v.ScoreDate.Format("2006-01")
  67. }
  68. return
  69. }
  70. func scoreListQuery(arg *model.RatingListArg) (where string) {
  71. if arg.Mid > 0 {
  72. where += fmt.Sprintf(" AND mid=%d", arg.Mid)
  73. }
  74. if arg.ScoreMin > 0 {
  75. where += fmt.Sprintf(" AND %s>=%d", scoreField(arg.ScoreType), arg.ScoreMin)
  76. }
  77. if arg.ScoreMax > 0 {
  78. where += fmt.Sprintf(" AND %s<%d", scoreField(arg.ScoreType), arg.ScoreMax)
  79. }
  80. if len(arg.Tags) > 0 {
  81. // if len(arg.Tags) > 1 {
  82. // s := rand.NewSource(time.Now().Unix())
  83. // r := rand.New(s) // initialize local pseudorandom generator
  84. // i := r.Intn(len(arg.Tags))
  85. // where += fmt.Sprintf(" AND tag_id=%d", arg.Tags[i])
  86. // } else {
  87. // where += fmt.Sprintf(" AND tag_id=%d", arg.Tags[0])
  88. // }
  89. where += fmt.Sprintf(" AND tag_id IN (%s)", xstr.JoinInts(arg.Tags))
  90. }
  91. where += " AND is_deleted=0"
  92. return
  93. }
  94. // ScoreCurrent returns current rating info
  95. func (s *Service) ScoreCurrent(c context.Context, mid int64) (res *model.ScoreCurrentResp, err error) {
  96. current, err := s.lastestScore(c, mid)
  97. if err != nil || current == nil {
  98. return
  99. }
  100. res = &model.ScoreCurrentResp{
  101. Date: current.ScoreDate.Unix(),
  102. Credit: &model.ScoreCurrent{Current: current.CreditScore, Diff: current.CreditScore},
  103. Influence: &model.ScoreCurrent{Current: current.InfluenceScore, Diff: current.InfluenceScore},
  104. Creativity: &model.ScoreCurrent{Current: current.CreativityScore, Diff: current.CreativityScore},
  105. }
  106. prev, err := s.upScore(c, mid, prevComputation(current.ScoreDate))
  107. if err != nil {
  108. return
  109. }
  110. if prev != nil {
  111. res.Credit.Diff = current.CreditScore - prev.CreditScore
  112. res.Influence.Diff = current.InfluenceScore - prev.InfluenceScore
  113. res.Creativity.Diff = current.CreativityScore - prev.CreativityScore
  114. }
  115. return
  116. }
  117. func (s *Service) upScoreHistory(c context.Context, mid int64, queryAll bool, count int) ([]*model.RatingInfo, error) {
  118. if queryAll {
  119. return s.upPastScoresAll(c, mid)
  120. }
  121. return s.upPastScores(c, mid, count)
  122. }
  123. // ScoreHistory returns score history
  124. func (s *Service) ScoreHistory(c context.Context, types []model.ScoreType, mid int64, queryAll bool, limit int) (res []*model.UpScoreHistory, err error) {
  125. res = make([]*model.UpScoreHistory, 0)
  126. history, err := s.upScoreHistory(c, mid, queryAll, limit)
  127. if err != nil || len(history) <= 0 {
  128. return
  129. }
  130. sort.Slice(history, func(i, j int) bool {
  131. return history[i].ScoreDate.Before(history[j].ScoreDate)
  132. })
  133. var (
  134. dates = make([]int64, 0, len(history))
  135. m = map[model.ScoreType][]int64{
  136. model.Credit: make([]int64, 0, len(history)),
  137. model.Creativity: make([]int64, 0, len(history)),
  138. model.Influence: make([]int64, 0, len(history)),
  139. }
  140. )
  141. for _, v := range history {
  142. dates = append(dates, v.ScoreDate.Unix())
  143. m[model.Creativity] = append(m[model.Creativity], v.CreativityScore)
  144. m[model.Credit] = append(m[model.Credit], v.CreditScore)
  145. m[model.Influence] = append(m[model.Influence], v.InfluenceScore)
  146. }
  147. for _, t := range types {
  148. res = append(res, &model.UpScoreHistory{
  149. ScoreType: t,
  150. Date: dates,
  151. Score: m[t],
  152. })
  153. }
  154. return
  155. }
  156. // ExportScores exports scores
  157. func (s *Service) ExportScores(ctx context.Context, arg *model.RatingListArg, date time.Time) (res []byte, err error) {
  158. ratings, _, err := s.RatingList(ctx, arg, date)
  159. if err != nil {
  160. log.Error("s.RatingList error(%v)", err)
  161. return
  162. }
  163. data := formatScores(ratings)
  164. res, err = formatCSV(data)
  165. if err != nil {
  166. log.Error("up-rating FormatCSV error(%v)", err)
  167. }
  168. return
  169. }
  170. func (s *Service) upPastScoresAll(c context.Context, mid int64) (res []*model.RatingInfo, err error) {
  171. res = make([]*model.RatingInfo, 0)
  172. for f := 1; f <= 12; f++ {
  173. var list []*model.RatingInfo
  174. if list, err = s.dao.UpScores(c, f, mid); err != nil {
  175. log.Error("s.dao.UpScores error(%v)", err)
  176. return
  177. }
  178. res = append(res, list...)
  179. }
  180. return
  181. }
  182. func (s *Service) upPastScores(c context.Context, mid int64, count int) (res []*model.RatingInfo, err error) {
  183. res = make([]*model.RatingInfo, 0)
  184. var lastScore *model.RatingInfo
  185. if lastScore, err = s.lastestScore(c, mid); err != nil || lastScore == nil {
  186. return
  187. }
  188. res = append(res, lastScore)
  189. for f := 1; f < count; f++ {
  190. var v *model.RatingInfo
  191. if v, err = s.upScore(c, mid, lastScore.ScoreDate.AddDate(0, -f, 0)); err != nil {
  192. return
  193. }
  194. if v != nil {
  195. res = append(res, v)
  196. }
  197. }
  198. return
  199. }
  200. func (s *Service) lastestScore(c context.Context, mid int64) (score *model.RatingInfo, err error) {
  201. cdate := prevComputation(time.Now())
  202. var b bool
  203. if b, err = s.taskFinished(c, cdate); err != nil {
  204. return
  205. }
  206. if !b {
  207. cdate = prevComputation(cdate)
  208. if b, err = s.taskFinished(c, cdate); err != nil {
  209. return
  210. }
  211. }
  212. if !b {
  213. log.Error("s.latestScore cdate(%s) no data available", cdate)
  214. err = ecode.ServerErr
  215. return
  216. }
  217. return s.upScore(c, mid, cdate)
  218. }
  219. func (s *Service) taskFinished(c context.Context, cdate time.Time) (bool, error) {
  220. str := cDateStr(cdate)
  221. status, err := s.dao.TaskStatus(c, str)
  222. if err != nil {
  223. log.Error("s.dao.TaskStasus date(%s) error(%v)", str, err)
  224. return false, err
  225. }
  226. return status == 1, nil
  227. }
  228. // upScore wraps dao.upScore
  229. func (s *Service) upScore(c context.Context, mid int64, t time.Time) (*model.RatingInfo, error) {
  230. score, err := s.dao.UpScore(c, int(t.Month()), mid, cDateStr(t))
  231. if err != nil {
  232. log.Error("s.dao.UpScore mid(%d) date(%s) error(%v)", mid, t, err)
  233. return nil, err
  234. }
  235. return score, nil
  236. }