123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364 |
- package service
- import (
- "bytes"
- "context"
- "fmt"
- "math/rand"
- "sort"
- "strconv"
- "strings"
- "time"
- "go-common/app/job/main/growup/model"
- "go-common/app/job/main/growup/model/income"
- "go-common/library/log"
- )
- var (
- _dbLimit = 2000
- _dbBatchSize = 2000
- )
- // CreativeUpBill creative up bill
- func (s *Service) CreativeUpBill(c context.Context, startDate, endDate time.Time) (err error) {
- // up_info_video
- ups, err := s.signed(c, int64(_dbLimit))
- if err != nil {
- log.Error("s.signed error(%v)", err)
- return
- }
- upBills := handleUps(ups, endDate)
- // up_income
- upIncome, err := s.getUpIncomeByDate(c, "up_income", startDate, endDate)
- if err != nil {
- log.Error("s.getUpIncomeByDate error(%v)", err)
- return
- }
- handleUpIncome(upBills, upIncome)
- // up_signed_avs
- upAvs, err := s.upSignedAvs(c, _dbLimit)
- if err != nil {
- log.Error("s.upSignedAvs error(%v)", err)
- return
- }
- for _, up := range upBills {
- up.AvCount = upAvs[up.MID]
- }
- // av_income_statis
- avs, err := s.getAvIncomeStatis(c, int64(_dbLimit), endDate)
- if err != nil {
- log.Error("s.getAvIncomeStatis error(%v)", err)
- return
- }
- handleAvIncomeStatis(upBills, avs)
- upQuality, err := s.getUpQuality(c, int(endDate.Day()), _dbLimit)
- if err != nil {
- log.Error("s.getUpQualities error(%v)", err)
- return
- }
- if len(upQuality) == 0 {
- err = fmt.Errorf("Error: get 0 ups from up_quality_info_%d", endDate.Day())
- return
- }
- handleUpQuality(upBills, upQuality)
- handleUpBills(upBills)
- // insert
- err = s.upBillDBStore(c, upBills)
- if err != nil {
- log.Error("s.upBillDBStore error(%v)", err)
- }
- return
- }
- func randStr(strs []string) string {
- return strs[rand.Intn(len(strs))%len(strs)]
- }
- func handleUpBills(upBills map[int64]*model.UpBill) {
- for _, up := range upBills {
- titles := []string{}
- shareItem := ""
- switch {
- case up.TotalIncome >= 500000:
- titles = append(titles, "掘金小能手")
- shareItem = randStr([]string{"98亿手办", "圣地巡礼机票"})
- case up.TotalIncome >= 100000:
- shareItem = randStr([]string{"BML现场门票", "老婆的演唱会门票", "购物车里的“老婆”"})
- case up.TotalIncome >= 50000:
- shareItem = randStr([]string{"超大堆小电视抱枕", "肥宅快乐桶吃到吐", "老婆的应援周边"})
- case up.TotalIncome >= 10000:
- shareItem = randStr([]string{"一堆“2233”挂件", "N个月大会员", "一暑假肥宅快乐水"})
- case up.TotalIncome < 10000:
- shareItem = randStr([]string{"创作补给餐", "自我打call棒", "承包几部番剧", "老婆的海报"})
- }
- if up.AvCount >= 30 {
- titles = append(titles, "B站劳模")
- }
- if up.Fans >= 10000 {
- titles = append(titles, "万人迷")
- }
- if up.TotalPlayCount >= 500000 {
- titles = append(titles, "流量王")
- }
- if len(titles) == 0 {
- titles = []string{"社会人", "快乐肥宅", "9percent"}
- }
- up.Title = randStr(titles)
- up.ShareItems = shareItem
- }
- }
- func handleUps(ups map[int64]*model.UpInfoVideo, end time.Time) (upBills map[int64]*model.UpBill) {
- upBills = make(map[int64]*model.UpBill)
- for _, up := range ups {
- upBills[up.MID] = &model.UpBill{
- MID: up.MID,
- SignedAt: up.SignedAt.Time().Format(_layout),
- Fans: up.Fans,
- TotalPlayCount: up.TotalPlayCount,
- EndAt: end.Format(_layout),
- }
- }
- return
- }
- func handleUpIncome(upBills map[int64]*model.UpBill, upIncome []*model.UpIncome) {
- for _, up := range upIncome {
- upB, ok := upBills[up.MID]
- if !ok {
- continue
- }
- if up.Date.Time().Format(_layout) >= upB.SignedAt {
- upB.TotalIncome += up.Income
- if upB.FirstTime == "" {
- upB.FirstIncome = up.Income
- upB.FirstTime = up.Date.Time().Format(_layout)
- }
- if upB.MaxIncome < up.Income {
- upB.MaxIncome = up.Income
- upB.MaxTime = up.Date.Time().Format(_layout)
- }
- }
- }
- }
- func handleAvIncomeStatis(upBills map[int64]*model.UpBill, avs map[int64]*income.AvIncomeStat) {
- for _, av := range avs {
- upB, ok := upBills[av.MID]
- if !ok {
- continue
- }
- if av.CTime.Time().Format(_layout) < upB.SignedAt {
- continue
- }
- income := av.TotalIncome
- if income > upB.AvMaxIncome {
- upB.AvMaxIncome = income
- upB.AvID = av.AvID
- }
- }
- }
- func handleUpQuality(upBills map[int64]*model.UpBill, upQualities []*model.UpQuality) {
- total := len(upQualities)
- sort.Slice(upQualities, func(i, j int) bool {
- return upQualities[i].Quality > upQualities[j].Quality
- })
- for i := 0; i < len(upQualities); i++ {
- mid := upQualities[i].MID
- if _, ok := upBills[mid]; ok {
- upBills[mid].QualityValue = upQualities[i].Quality
- rank := i
- for rank > 0 && upQualities[rank].Quality == upQualities[rank-1].Quality {
- rank--
- }
- upBills[mid].DefeatNum = (10000 * (total - rank)) / total
- }
- }
- }
- func (s *Service) signed(c context.Context, limit int64) (m map[int64]*model.UpInfoVideo, err error) {
- var id int64
- m = make(map[int64]*model.UpInfoVideo)
- for {
- var us map[int64]*model.UpInfoVideo
- id, us, err = s.dao.UpInfoVideo(c, id, limit)
- if err != nil {
- return
- }
- for k, v := range us {
- if v.AccountState == 3 && v.IsDeleted == 0 {
- m[k] = v
- }
- }
- if len(us) < _dbLimit {
- break
- }
- }
- return
- }
- func (s *Service) getUpIncomeByDate(c context.Context, table string, start, end time.Time) (ups []*model.UpIncome, err error) {
- ups = make([]*model.UpIncome, 0)
- end = end.AddDate(0, 0, 1)
- for start.Before(end) {
- var up []*model.UpIncome
- up, err = s.GetUpIncome(c, table, start.Format("2006-01-02"))
- if err != nil {
- return
- }
- ups = append(ups, up...)
- start = start.AddDate(0, 0, 1)
- }
- return
- }
- func (s *Service) getAvIncomeStatis(c context.Context, limit int64, endDate time.Time) (m map[int64]*income.AvIncomeStat, err error) {
- m = make(map[int64]*income.AvIncomeStat)
- var id int64
- for {
- var am map[int64]*income.AvIncomeStat
- am, id, err = s.income.AvIncomeStat(c, id, limit)
- if err != nil {
- return
- }
- for avID, stat := range am {
- if stat.CTime.Time().Before(endDate.AddDate(0, 0, 1)) {
- m[avID] = stat
- }
- }
- if len(am) < int(limit) {
- break
- }
- }
- return
- }
- func (s *Service) upSignedAvs(c context.Context, limit int) (upAvs map[int64]int64, err error) {
- upAvs = make(map[int64]int64)
- var id int64
- for {
- var ups map[int64]int64
- ups, id, err = s.dao.ListUpSignedAvs(c, id, limit)
- if err != nil {
- return
- }
- for mid, avCount := range ups {
- upAvs[mid] = avCount
- }
- if len(ups) < limit {
- break
- }
- }
- return
- }
- func (s *Service) getUpQuality(c context.Context, day, limit int) (ups []*model.UpQuality, err error) {
- ups = make([]*model.UpQuality, 0)
- var (
- id int64
- table string
- up []*model.UpQuality
- )
- if day < 10 {
- table = fmt.Sprintf("up_quality_info_0%d", day)
- } else {
- table = fmt.Sprintf("up_quality_info_%d", day)
- }
- for {
- up, id, err = s.dao.GetUpQuality(c, table, id, limit)
- if err != nil {
- return
- }
- ups = append(ups, up...)
- if len(up) < limit {
- break
- }
- }
- return
- }
- func (s *Service) upBillDBStore(c context.Context, upBill map[int64]*model.UpBill) (err error) {
- var (
- buff = make([]*model.UpBill, _dbBatchSize)
- buffEnd = 0
- )
- for _, u := range upBill {
- buff[buffEnd] = u
- buffEnd++
- if buffEnd >= _dbBatchSize {
- _, err = s.upBillBatchInsert(c, buff[:buffEnd])
- if err != nil {
- return
- }
- buffEnd = 0
- }
- }
- if buffEnd > 0 {
- _, err = s.upBillBatchInsert(c, buff[:buffEnd])
- if err != nil {
- return
- }
- buffEnd = 0
- }
- return
- }
- func assembleUpBill(upBill []*model.UpBill) (vals string) {
- var buf bytes.Buffer
- for _, row := range upBill {
- buf.WriteString("(")
- buf.WriteString(strconv.FormatInt(row.MID, 10))
- buf.WriteByte(',')
- buf.WriteString(strconv.FormatInt(row.FirstIncome, 10))
- buf.WriteByte(',')
- buf.WriteString(strconv.FormatInt(row.MaxIncome, 10))
- buf.WriteByte(',')
- buf.WriteString(strconv.FormatInt(row.TotalIncome, 10))
- buf.WriteByte(',')
- buf.WriteString(strconv.FormatInt(row.AvCount, 10))
- buf.WriteByte(',')
- buf.WriteString(strconv.FormatInt(row.AvMaxIncome, 10))
- buf.WriteByte(',')
- buf.WriteString(strconv.FormatInt(row.AvID, 10))
- buf.WriteByte(',')
- buf.WriteString(strconv.FormatInt(row.QualityValue, 10))
- buf.WriteByte(',')
- buf.WriteString(strconv.Itoa(row.DefeatNum))
- buf.WriteByte(',')
- buf.WriteString("\"" + strings.Replace(row.Title, "\"", "\\\"", -1) + "\"")
- buf.WriteByte(',')
- buf.WriteString("'" + row.ShareItems + "'")
- buf.WriteByte(',')
- buf.WriteString("'" + row.FirstTime + "'")
- buf.WriteByte(',')
- buf.WriteString("'" + row.MaxTime + "'")
- buf.WriteByte(',')
- buf.WriteString("'" + row.SignedAt + "'")
- buf.WriteByte(',')
- buf.WriteString("'" + row.EndAt + "'")
- buf.WriteString(")")
- buf.WriteByte(',')
- }
- if buf.Len() > 0 {
- buf.Truncate(buf.Len() - 1)
- }
- vals = buf.String()
- buf.Reset()
- return
- }
- func (s *Service) upBillBatchInsert(c context.Context, upBill []*model.UpBill) (rows int64, err error) {
- vals := assembleUpBill(upBill)
- rows, err = s.dao.InsertUpBillBatch(c, vals)
- return
- }
|