ut_rank.go 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. package service
  2. import (
  3. "context"
  4. "fmt"
  5. "math"
  6. "sort"
  7. "strconv"
  8. "time"
  9. "go-common/app/admin/main/apm/model/ut"
  10. "go-common/library/log"
  11. xtime "go-common/library/time"
  12. )
  13. // RankTen find data and avg(coverage)
  14. func (s *Service) RankTen(c context.Context, order string) (ranks []*ut.RankResp, err error) {
  15. s.ranksCache.Lock()
  16. allRanks := s.ranksCache.Slice
  17. s.ranksCache.Unlock()
  18. ranksLen := len(allRanks)
  19. if ranksLen == 0 {
  20. log.Info("s.RankTen order(%s) ranks is empty", order)
  21. return
  22. }
  23. if ranksLen > 10 {
  24. ranksLen = 10
  25. }
  26. if order == "desc" {
  27. sort.Slice(allRanks, func(i, j int) bool { return allRanks[i].Score > allRanks[j].Score })
  28. } else {
  29. sort.Slice(allRanks, func(i, j int) bool { return allRanks[i].Score < allRanks[j].Score })
  30. }
  31. ranks = append(ranks, allRanks[0:ranksLen]...)
  32. return
  33. }
  34. // UserRank return one's rank
  35. func (s *Service) UserRank(c context.Context, username string) (rank *ut.RankResp, err error) {
  36. s.ranksCache.Lock()
  37. allRanks := s.ranksCache.Map
  38. s.ranksCache.Unlock()
  39. if len(allRanks) == 0 {
  40. log.Info("s.RankTen(%s) ranks is empty", username)
  41. return
  42. }
  43. rank = allRanks[username]
  44. return
  45. }
  46. // RanksCache flush cache for ranks.
  47. func (s *Service) RanksCache(c context.Context) (err error) {
  48. s.ranksCache.Lock()
  49. defer s.ranksCache.Unlock()
  50. var (
  51. rankSlice []*ut.RankResp
  52. rankMap = make(map[string]*ut.RankResp)
  53. endTime = time.Now().AddDate(0, -3, 0).Format("2006-01-02 15:04:05")
  54. )
  55. if err = s.DB.Table("ut_merge").Raw("select * from (select ut_commit.username,ROUND(avg(coverage)/100,2) AS coverage,ROUND(SUM(passed)/SUM(assertions),2)*100 AS pass_rate, SUM(assertions)AS assertions, SUM(passed) AS passed, MAX(ut_commit.mtime) as mtime from ut_merge,ut_commit,ut_pkganls where ut_merge.merge_id=ut_commit.merge_id and ut_commit.commit_id=ut_pkganls.commit_id and ut_merge.is_merged=1 and ut_merge.mtime >=? and (ut_pkganls.pkg!=substring_index(ut_pkganls.pkg,'/',5) or ut_pkganls.pkg like 'go-common/library/%') GROUP BY ut_commit.username) as t1", endTime).
  56. Find(&rankSlice).Error; err != nil {
  57. log.Error("RankResult error(%v)", err)
  58. return
  59. }
  60. total := len(rankSlice)
  61. for _, rank := range rankSlice {
  62. rank.Total = total
  63. rank.Newton = NewtonScore(rank.Mtime)
  64. Score := rank.Coverage * WilsonScore(rank.Passed, rank.Assertions) * rank.Newton
  65. rank.Score, _ = strconv.ParseFloat(fmt.Sprintf("%.2f", Score), 64)
  66. }
  67. // desc
  68. sort.Slice(rankSlice, func(i, j int) bool { return rankSlice[i].Score > rankSlice[j].Score })
  69. for index, rank := range rankSlice {
  70. rank.Rank = index + 1
  71. rank.AvatarURL, _ = s.dao.GitLabFace(c, rank.UserName)
  72. rankMap[rank.UserName] = rank
  73. if history, ok := s.ranksCache.Map[rank.UserName]; ok {
  74. rank.Change = history.Rank - rank.Rank
  75. }
  76. }
  77. s.ranksCache.Map = rankMap
  78. s.ranksCache.Slice = rankSlice
  79. return
  80. }
  81. //WilsonScore Wilson-score-interval
  82. func WilsonScore(pos int, total int) (score float64) {
  83. z := float64(1.96)
  84. posRat := float64(pos) / float64(total)
  85. score = (posRat + math.Pow(z, 2)/(2*float64(total))) / (1 + math.Pow(z, 2)/float64(total))
  86. return
  87. }
  88. // NewtonScore . Newton's Law of Cooling
  89. // 冷却因子经我们需求计算 a = 0.02
  90. // deltaDays<7 day -a*x^2+b >7 NewTonScore
  91. func NewtonScore(maxMtime xtime.Time) (score float64) {
  92. deltaDays := int(time.Since(maxMtime.Time()).Hours() / 24)
  93. if deltaDays <= int(7) {
  94. score = -(float64(0.0012))*math.Pow(float64(deltaDays), 2) + float64(1)
  95. return
  96. }
  97. score = math.Exp(-(float64(0.02) * float64(deltaDays)))
  98. return
  99. }