293 lines
8.0 KiB
Go
293 lines
8.0 KiB
Go
package service
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"fmt"
|
|
"strconv"
|
|
"time"
|
|
|
|
"go-common/app/job/main/up-rating/model"
|
|
|
|
"go-common/library/log"
|
|
xtime "go-common/library/time"
|
|
"golang.org/x/sync/errgroup"
|
|
)
|
|
|
|
const (
|
|
// TotalType total type
|
|
TotalType int = iota
|
|
// CreativeType creative type
|
|
CreativeType
|
|
// InfluenceType influence type
|
|
InfluenceType
|
|
// CreditType Credit type
|
|
CreditType
|
|
)
|
|
|
|
var (
|
|
_offset int64 = 10
|
|
_sumTotal int64
|
|
_creativeTotal int64
|
|
_influenceTotal int64
|
|
_creditTotal int64
|
|
)
|
|
|
|
func initSection(min, max, section int64, ctype int, tagID int64, date xtime.Time) *model.RatingStatis {
|
|
return &model.RatingStatis{
|
|
Section: section,
|
|
Tips: fmt.Sprintf("\"%d-%d\"", min, max),
|
|
TagID: tagID,
|
|
CDate: date,
|
|
CType: ctype,
|
|
}
|
|
}
|
|
|
|
func initSections(totalScore, tagID int64, ctype int, date xtime.Time) (statis []*model.RatingStatis) {
|
|
var (
|
|
idx int64
|
|
)
|
|
statis = make([]*model.RatingStatis, totalScore/_offset)
|
|
for idx*_offset < totalScore {
|
|
statis[idx] = initSection(idx*_offset, (idx+1)*_offset, idx, ctype, tagID, date)
|
|
idx++
|
|
}
|
|
return
|
|
}
|
|
|
|
// RunStatistics run up rating statistics
|
|
func (s *Service) RunStatistics(c context.Context, date time.Time) (err error) {
|
|
err = s.initTotalScore(c)
|
|
if err != nil {
|
|
log.Error("s.initTotalScore error(%v)", err)
|
|
return
|
|
}
|
|
err = s.delStatistics(c, date)
|
|
if err != nil {
|
|
log.Error("s.delStatistics error(%v)", err)
|
|
return
|
|
}
|
|
err = s.statistics(c, date)
|
|
if err != nil {
|
|
log.Error("s.scoreStatistics error(%v)", err)
|
|
}
|
|
return
|
|
}
|
|
|
|
func (s *Service) initTotalScore(c context.Context) (err error) {
|
|
params, err := s.getAllParamter(c)
|
|
if err != nil {
|
|
log.Error("s.getAllParamter error(%v)", err)
|
|
return
|
|
}
|
|
_sumTotal = params.WCSR + params.HR + params.WISR
|
|
_creativeTotal = params.WCSR
|
|
_influenceTotal = params.WISR
|
|
_creditTotal = params.HR
|
|
return
|
|
}
|
|
|
|
func (s *Service) delStatistics(c context.Context, date time.Time) (err error) {
|
|
err = s.delRatingCom(c, "up_rating_statistics", date)
|
|
if err != nil {
|
|
return
|
|
}
|
|
err = s.delRatingCom(c, "up_rating_top", date)
|
|
return
|
|
}
|
|
|
|
// delRatingCom del com
|
|
func (s *Service) delRatingCom(c context.Context, table string, date time.Time) (err error) {
|
|
for {
|
|
var rows int64
|
|
rows, err = s.dao.DelRatingCom(c, table, date, _limit)
|
|
if err != nil {
|
|
return
|
|
}
|
|
if rows == 0 {
|
|
break
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
func (s *Service) statistics(c context.Context, date time.Time) (err error) {
|
|
var (
|
|
readGroup errgroup.Group
|
|
sourceCh = make(chan []*model.Rating, _limit)
|
|
statisCh = make(chan []*model.Rating, _limit)
|
|
topCh = make(chan []*model.Rating, _limit)
|
|
|
|
sections map[int]map[int64][]*model.RatingStatis
|
|
topRating map[int]map[int64]*RatingHeap
|
|
)
|
|
baseInfo, err := s.BaseTotal(c, date)
|
|
if err != nil {
|
|
log.Error("s.BaseTotal error(%v)", err)
|
|
return
|
|
}
|
|
// get rating info
|
|
readGroup.Go(func() (err error) {
|
|
err = s.RatingInfos(c, date, sourceCh)
|
|
if err != nil {
|
|
log.Error("s.RatingInfos error(%v)", err)
|
|
}
|
|
return
|
|
})
|
|
|
|
// dispatch
|
|
readGroup.Go(func() (err error) {
|
|
defer func() {
|
|
close(topCh)
|
|
close(statisCh)
|
|
}()
|
|
for rating := range sourceCh {
|
|
statisCh <- rating
|
|
topCh <- rating
|
|
}
|
|
return
|
|
})
|
|
|
|
// top
|
|
readGroup.Go(func() (err error) {
|
|
topRating, err = s.ratingTop(c, date, topCh)
|
|
if err != nil {
|
|
log.Error("s.RatingTop error(%v)", err)
|
|
}
|
|
return
|
|
})
|
|
// statis
|
|
readGroup.Go(func() (err error) {
|
|
sections, err = s.scoreStatistics(c, date, statisCh, baseInfo)
|
|
if err != nil {
|
|
log.Error("s.scoreStatistics error(%v)", err)
|
|
}
|
|
return
|
|
})
|
|
if err = readGroup.Wait(); err != nil {
|
|
log.Error("run readGroup.Wait error(%v)", err)
|
|
return
|
|
}
|
|
|
|
// persistent
|
|
var writeGroup errgroup.Group
|
|
|
|
//up_rating_statistics
|
|
writeGroup.Go(func() (err error) {
|
|
err = s.insertSections(c, sections)
|
|
if err != nil {
|
|
log.Error("s.insertSections error(%v)", err)
|
|
}
|
|
return
|
|
})
|
|
// up_rating_top
|
|
writeGroup.Go(func() (err error) {
|
|
_, err = s.insertTopRating(c, date, topRating, baseInfo)
|
|
if err != nil {
|
|
log.Error("s.insertSections error(%v)", err)
|
|
}
|
|
return
|
|
})
|
|
if err = writeGroup.Wait(); err != nil {
|
|
log.Error("run writeGroup.Wait error(%v)", err)
|
|
}
|
|
return
|
|
}
|
|
|
|
func (s *Service) scoreStatistics(c context.Context, date time.Time, source chan []*model.Rating, baseInfo map[int64]*model.BaseInfo) (sections map[int]map[int64][]*model.RatingStatis, err error) {
|
|
sections = make(map[int]map[int64][]*model.RatingStatis) // map[ctype][tagID][]*model.RatingStatis
|
|
sections[TotalType] = make(map[int64][]*model.RatingStatis)
|
|
sections[CreativeType] = make(map[int64][]*model.RatingStatis)
|
|
sections[InfluenceType] = make(map[int64][]*model.RatingStatis)
|
|
sections[CreditType] = make(map[int64][]*model.RatingStatis)
|
|
for rating := range source {
|
|
for _, r := range rating {
|
|
statisScoreCtype(TotalType, r.CreativityScore+r.InfluenceScore+r.CreditScore, _sumTotal, sections, date, r, baseInfo[r.MID])
|
|
statisScoreCtype(CreativeType, r.CreativityScore, _creativeTotal, sections, date, r, baseInfo[r.MID])
|
|
statisScoreCtype(InfluenceType, r.InfluenceScore, _influenceTotal, sections, date, r, baseInfo[r.MID])
|
|
statisScoreCtype(CreditType, r.CreditScore, _creditTotal, sections, date, r, baseInfo[r.MID])
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
func statisScoreCtype(ctype int, score, totalScore int64, sections map[int]map[int64][]*model.RatingStatis, date time.Time, rate *model.Rating, base *model.BaseInfo) {
|
|
if _, ok := sections[ctype][rate.TagID]; !ok {
|
|
sections[ctype][rate.TagID] = initSections(totalScore, rate.TagID, ctype, xtime.Time(date.Unix()))
|
|
}
|
|
idx := score / _offset
|
|
if idx >= int64(len(sections[ctype][rate.TagID])) {
|
|
idx = int64(len(sections[ctype][rate.TagID]) - 1)
|
|
}
|
|
sections[ctype][rate.TagID][idx].Ups++
|
|
sections[ctype][rate.TagID][idx].TotalScore += rate.CreativityScore + rate.InfluenceScore + rate.CreditScore
|
|
sections[ctype][rate.TagID][idx].CreativityScore += rate.CreativityScore
|
|
sections[ctype][rate.TagID][idx].InfluenceScore += rate.InfluenceScore
|
|
sections[ctype][rate.TagID][idx].CreditScore += rate.CreditScore
|
|
if base != nil {
|
|
sections[ctype][rate.TagID][idx].Fans += base.TotalFans
|
|
sections[ctype][rate.TagID][idx].Avs += base.TotalAvs
|
|
sections[ctype][rate.TagID][idx].Coin += base.TotalCoin
|
|
sections[ctype][rate.TagID][idx].Play += base.TotalPlay
|
|
}
|
|
}
|
|
|
|
func (s *Service) insertSections(c context.Context, sections map[int]map[int64][]*model.RatingStatis) (err error) {
|
|
for ctype, tags := range sections {
|
|
for tagID, statis := range tags {
|
|
_, err = s.insertRatingStatis(c, ctype, tagID, statis)
|
|
if err != nil {
|
|
return
|
|
}
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
func (s *Service) insertRatingStatis(c context.Context, ctype int, tagID int64, statis []*model.RatingStatis) (rows int64, err error) {
|
|
return s.dao.InsertRatingStatis(c, assembleRatingStatis(c, ctype, tagID, statis))
|
|
}
|
|
|
|
func assembleRatingStatis(c context.Context, ctype int, tagID int64, statis []*model.RatingStatis) (vals string) {
|
|
var buf bytes.Buffer
|
|
for _, s := range statis {
|
|
buf.WriteString("(")
|
|
buf.WriteString(strconv.FormatInt(s.Ups, 10))
|
|
buf.WriteByte(',')
|
|
buf.WriteString(strconv.FormatInt(s.Section, 10))
|
|
buf.WriteByte(',')
|
|
buf.WriteString(s.Tips)
|
|
buf.WriteByte(',')
|
|
buf.WriteString(strconv.FormatInt(s.TotalScore, 10))
|
|
buf.WriteByte(',')
|
|
buf.WriteString(strconv.FormatInt(s.CreativityScore, 10))
|
|
buf.WriteByte(',')
|
|
buf.WriteString(strconv.FormatInt(s.InfluenceScore, 10))
|
|
buf.WriteByte(',')
|
|
buf.WriteString(strconv.FormatInt(s.CreditScore, 10))
|
|
buf.WriteByte(',')
|
|
buf.WriteString(strconv.FormatInt(s.Fans, 10))
|
|
buf.WriteByte(',')
|
|
buf.WriteString(strconv.FormatInt(s.Avs, 10))
|
|
buf.WriteByte(',')
|
|
buf.WriteString(strconv.FormatInt(s.Coin, 10))
|
|
buf.WriteByte(',')
|
|
buf.WriteString(strconv.FormatInt(s.Play, 10))
|
|
buf.WriteByte(',')
|
|
buf.WriteString(strconv.FormatInt(s.TagID, 10))
|
|
buf.WriteByte(',')
|
|
buf.WriteString(strconv.Itoa(s.CType))
|
|
buf.WriteByte(',')
|
|
buf.WriteString("'" + s.CDate.Time().Format(_layout) + "'")
|
|
buf.WriteString(")")
|
|
buf.WriteByte(',')
|
|
}
|
|
|
|
if buf.Len() > 0 {
|
|
buf.Truncate(buf.Len() - 1)
|
|
}
|
|
vals = buf.String()
|
|
buf.Reset()
|
|
return
|
|
}
|