123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252 |
- package service
- import (
- "context"
- "fmt"
- "sort"
- "time"
- "go-common/app/admin/main/up-rating/dao/global"
- "go-common/app/admin/main/up-rating/model"
- "go-common/library/ecode"
- "go-common/library/log"
- "go-common/library/xstr"
- )
- // RatingList returns rating info list
- func (s *Service) RatingList(c context.Context, arg *model.RatingListArg, date time.Time) (res []*model.RatingInfo, total int64, err error) {
- var (
- cdate = getStartMonthlyDate(date)
- cdateStr = cDateStr(cdate)
- mon = int(cdate.Month())
- )
- res = make([]*model.RatingInfo, 0)
- q := scoreListQuery(arg)
- total = 10000
- // if total, err = s.dao.Total(c, mon, cdateStr, q); err != nil {
- // log.Error("s.dao.Total error(%v)", err)
- // return
- // }
- // if total == 0 {
- // return
- // }
- // scores
- q += fmt.Sprintf(" ORDER BY id ASC LIMIT %d, %d", arg.From, arg.Limit)
- if res, err = s.dao.ScoreList(c, mon, cdateStr, q); err != nil {
- log.Error("s.dao.ScoreList error(%v)", err)
- return
- }
- if len(res) == 0 {
- return
- }
- var (
- m = make(map[int64]*model.RatingInfo, len(res))
- mids = make([]int64, 0, len(res))
- )
- for _, v := range res {
- mids = append(mids, v.Mid)
- m[v.Mid] = v
- }
- // fans and avs
- levelInfos, err := s.dao.LevelList(c, mon, cdateStr, mids)
- if err != nil {
- log.Error("s.dao.LevelList error(%v)", err)
- return
- }
- for _, v := range levelInfos {
- score := m[v.Mid]
- score.TotalAvs = v.TotalAvs
- score.TotalFans = v.TotalFans
- }
- // nicknames
- r, err := global.Names(c, mids)
- if err != nil {
- log.Error("global.Names error(%v)", err)
- return
- }
- for _, v := range res {
- v.NickName = r[v.Mid]
- v.Date = v.ScoreDate.Format("2006-01")
- }
- return
- }
- func scoreListQuery(arg *model.RatingListArg) (where string) {
- if arg.Mid > 0 {
- where += fmt.Sprintf(" AND mid=%d", arg.Mid)
- }
- if arg.ScoreMin > 0 {
- where += fmt.Sprintf(" AND %s>=%d", scoreField(arg.ScoreType), arg.ScoreMin)
- }
- if arg.ScoreMax > 0 {
- where += fmt.Sprintf(" AND %s<%d", scoreField(arg.ScoreType), arg.ScoreMax)
- }
- if len(arg.Tags) > 0 {
- // if len(arg.Tags) > 1 {
- // s := rand.NewSource(time.Now().Unix())
- // r := rand.New(s) // initialize local pseudorandom generator
- // i := r.Intn(len(arg.Tags))
- // where += fmt.Sprintf(" AND tag_id=%d", arg.Tags[i])
- // } else {
- // where += fmt.Sprintf(" AND tag_id=%d", arg.Tags[0])
- // }
- where += fmt.Sprintf(" AND tag_id IN (%s)", xstr.JoinInts(arg.Tags))
- }
- where += " AND is_deleted=0"
- return
- }
- // ScoreCurrent returns current rating info
- func (s *Service) ScoreCurrent(c context.Context, mid int64) (res *model.ScoreCurrentResp, err error) {
- current, err := s.lastestScore(c, mid)
- if err != nil || current == nil {
- return
- }
- res = &model.ScoreCurrentResp{
- Date: current.ScoreDate.Unix(),
- Credit: &model.ScoreCurrent{Current: current.CreditScore, Diff: current.CreditScore},
- Influence: &model.ScoreCurrent{Current: current.InfluenceScore, Diff: current.InfluenceScore},
- Creativity: &model.ScoreCurrent{Current: current.CreativityScore, Diff: current.CreativityScore},
- }
- prev, err := s.upScore(c, mid, prevComputation(current.ScoreDate))
- if err != nil {
- return
- }
- if prev != nil {
- res.Credit.Diff = current.CreditScore - prev.CreditScore
- res.Influence.Diff = current.InfluenceScore - prev.InfluenceScore
- res.Creativity.Diff = current.CreativityScore - prev.CreativityScore
- }
- return
- }
- func (s *Service) upScoreHistory(c context.Context, mid int64, queryAll bool, count int) ([]*model.RatingInfo, error) {
- if queryAll {
- return s.upPastScoresAll(c, mid)
- }
- return s.upPastScores(c, mid, count)
- }
- // ScoreHistory returns score history
- func (s *Service) ScoreHistory(c context.Context, types []model.ScoreType, mid int64, queryAll bool, limit int) (res []*model.UpScoreHistory, err error) {
- res = make([]*model.UpScoreHistory, 0)
- history, err := s.upScoreHistory(c, mid, queryAll, limit)
- if err != nil || len(history) <= 0 {
- return
- }
- sort.Slice(history, func(i, j int) bool {
- return history[i].ScoreDate.Before(history[j].ScoreDate)
- })
- var (
- dates = make([]int64, 0, len(history))
- m = map[model.ScoreType][]int64{
- model.Credit: make([]int64, 0, len(history)),
- model.Creativity: make([]int64, 0, len(history)),
- model.Influence: make([]int64, 0, len(history)),
- }
- )
- for _, v := range history {
- dates = append(dates, v.ScoreDate.Unix())
- m[model.Creativity] = append(m[model.Creativity], v.CreativityScore)
- m[model.Credit] = append(m[model.Credit], v.CreditScore)
- m[model.Influence] = append(m[model.Influence], v.InfluenceScore)
- }
- for _, t := range types {
- res = append(res, &model.UpScoreHistory{
- ScoreType: t,
- Date: dates,
- Score: m[t],
- })
- }
- return
- }
- // ExportScores exports scores
- func (s *Service) ExportScores(ctx context.Context, arg *model.RatingListArg, date time.Time) (res []byte, err error) {
- ratings, _, err := s.RatingList(ctx, arg, date)
- if err != nil {
- log.Error("s.RatingList error(%v)", err)
- return
- }
- data := formatScores(ratings)
- res, err = formatCSV(data)
- if err != nil {
- log.Error("up-rating FormatCSV error(%v)", err)
- }
- return
- }
- func (s *Service) upPastScoresAll(c context.Context, mid int64) (res []*model.RatingInfo, err error) {
- res = make([]*model.RatingInfo, 0)
- for f := 1; f <= 12; f++ {
- var list []*model.RatingInfo
- if list, err = s.dao.UpScores(c, f, mid); err != nil {
- log.Error("s.dao.UpScores error(%v)", err)
- return
- }
- res = append(res, list...)
- }
- return
- }
- func (s *Service) upPastScores(c context.Context, mid int64, count int) (res []*model.RatingInfo, err error) {
- res = make([]*model.RatingInfo, 0)
- var lastScore *model.RatingInfo
- if lastScore, err = s.lastestScore(c, mid); err != nil || lastScore == nil {
- return
- }
- res = append(res, lastScore)
- for f := 1; f < count; f++ {
- var v *model.RatingInfo
- if v, err = s.upScore(c, mid, lastScore.ScoreDate.AddDate(0, -f, 0)); err != nil {
- return
- }
- if v != nil {
- res = append(res, v)
- }
- }
- return
- }
- func (s *Service) lastestScore(c context.Context, mid int64) (score *model.RatingInfo, err error) {
- cdate := prevComputation(time.Now())
- var b bool
- if b, err = s.taskFinished(c, cdate); err != nil {
- return
- }
- if !b {
- cdate = prevComputation(cdate)
- if b, err = s.taskFinished(c, cdate); err != nil {
- return
- }
- }
- if !b {
- log.Error("s.latestScore cdate(%s) no data available", cdate)
- err = ecode.ServerErr
- return
- }
- return s.upScore(c, mid, cdate)
- }
- func (s *Service) taskFinished(c context.Context, cdate time.Time) (bool, error) {
- str := cDateStr(cdate)
- status, err := s.dao.TaskStatus(c, str)
- if err != nil {
- log.Error("s.dao.TaskStasus date(%s) error(%v)", str, err)
- return false, err
- }
- return status == 1, nil
- }
- // upScore wraps dao.upScore
- func (s *Service) upScore(c context.Context, mid int64, t time.Time) (*model.RatingInfo, error) {
- score, err := s.dao.UpScore(c, int(t.Month()), mid, cDateStr(t))
- if err != nil {
- log.Error("s.dao.UpScore mid(%d) date(%s) error(%v)", mid, t, err)
- return nil, err
- }
- return score, nil
- }
|