bilibili-backup/app/job/main/growup/service/income/income_date_statis.go

273 lines
8.6 KiB
Go
Raw Permalink Normal View History

2019-04-22 10:59:20 +08:00
package income
import (
"bytes"
"context"
"fmt"
"math"
"strconv"
"time"
incomeD "go-common/app/job/main/growup/dao/income"
model "go-common/app/job/main/growup/model/income"
"go-common/library/log"
xtime "go-common/library/time"
)
var (
_avIncomeDailyStatis = "av_income_daily_statis"
_avIncomeWeeklyStatis = "av_income_weekly_statis"
_avIncomeMonthlyStatis = "av_income_monthly_statis"
_cmIncomeDailyStatis = "column_income_daily_statis"
_cmIncomeWeeklyStatis = "column_income_weekly_statis"
_cmIncomeMonthlyStatis = "column_income_monthly_statis"
_bgmIncomeDailyStatis = "bgm_income_daily_statis"
_bgmIncomeWeeklyStatis = "bgm_income_weekly_statis"
_bgmIncomeMonthlyStatis = "bgm_income_monthly_statis"
)
// SectionEntries section entries
type SectionEntries struct {
avDaily []*model.DateStatis
avWeekly []*model.DateStatis
avMonthly []*model.DateStatis
}
// DateStatis income date statistics
type DateStatis struct {
dao *incomeD.Dao
}
// NewDateStatis new income date statistics service
func NewDateStatis(dao *incomeD.Dao) *DateStatis {
return &DateStatis{dao: dao}
}
func initIncomeSections(income, tagID int64, date xtime.Time) []*model.DateStatis {
incomeSections := make([]*model.DateStatis, 12)
incomeSections[0] = initIncomeSection(0, 1, 0, income, tagID, date)
incomeSections[1] = initIncomeSection(1, 5, 1, income, tagID, date)
incomeSections[2] = initIncomeSection(5, 10, 2, income, tagID, date)
incomeSections[3] = initIncomeSection(10, 30, 3, income, tagID, date)
incomeSections[4] = initIncomeSection(30, 50, 4, income, tagID, date)
incomeSections[5] = initIncomeSection(50, 100, 5, income, tagID, date)
incomeSections[6] = initIncomeSection(100, 200, 6, income, tagID, date)
incomeSections[7] = initIncomeSection(200, 500, 7, income, tagID, date)
incomeSections[8] = initIncomeSection(500, 1000, 8, income, tagID, date)
incomeSections[9] = initIncomeSection(1000, 3000, 9, income, tagID, date)
incomeSections[10] = initIncomeSection(3000, 5000, 10, income, tagID, date)
incomeSections[11] = initIncomeSection(5000, math.MaxInt32, 11, income, tagID, date)
return incomeSections
}
func initIncomeSection(min, max, section, income, tagID int64, date xtime.Time) *model.DateStatis {
var tips string
if max == math.MaxInt32 {
tips = fmt.Sprintf("\"%d+\"", min)
} else {
tips = fmt.Sprintf("\"%d~%d\"", min, max)
}
return &model.DateStatis{
MinIncome: min,
MaxIncome: max,
MoneySection: section,
MoneyTips: tips,
Income: income,
CategoryID: tagID,
CDate: date,
}
}
func (s *DateStatis) handleDateStatis(c context.Context, archiveCh chan []*model.ArchiveIncome, date time.Time, table string) (incomeSections []*model.DateStatis, err error) {
// delete
if table != "" {
_, err = s.dao.DelIncomeStatisTable(c, table, date.Format(_layout))
if err != nil {
log.Error("s.dao.DelIncomeStatisTable error(%v)", err)
return
}
}
// add
incomeSections = s.handleArchives(c, archiveCh, date)
return
}
// handleArchives handle archive_income_daily_statis, archive_income_weekly_statis, archive_income_monthly_statis
func (s *DateStatis) handleArchives(c context.Context, archiveCh chan []*model.ArchiveIncome, date time.Time) (incomeSections []*model.DateStatis) {
archTagMap := make(map[int64]map[int64]int64) // key TagID, value map[int64]int64 -> key aid, value income
tagIncomeMap := make(map[int64]int64) // key TagID, value TagID total income
for archive := range archiveCh {
handleArchive(archive, archTagMap, tagIncomeMap, date)
}
incomeSections = make([]*model.DateStatis, 0)
for tagID, avMap := range archTagMap {
incomeSection := countIncomeDailyStatis(avMap, tagIncomeMap[tagID], tagID, date)
incomeSections = append(incomeSections, incomeSection...)
}
return
}
func handleArchive(archives []*model.ArchiveIncome, archTagMap map[int64]map[int64]int64, tagIncomeMap map[int64]int64, startDate time.Time) {
if archives == nil {
return
}
if archTagMap == nil {
archTagMap = make(map[int64]map[int64]int64)
}
if tagIncomeMap == nil {
tagIncomeMap = make(map[int64]int64)
}
for _, archive := range archives {
if !startDate.After(archive.Date.Time()) {
tagIncomeMap[archive.TagID] += archive.Income
if _, ok := archTagMap[archive.TagID]; !ok {
archTagMap[archive.TagID] = make(map[int64]int64)
}
archTagMap[archive.TagID][archive.AID] += archive.Income
}
}
}
func (s *DateStatis) handleDateUp(c context.Context, upStatisCh chan []*model.UpIncome, date time.Time) (upSections, upAvSections, upCmSections, upBgmSections []*model.DateStatis, err error) {
_, err = s.dao.DelIncomeStatisTable(c, "up_income_daily_statis", date.Format(_layout))
if err != nil {
log.Error("s.dao.DelIncomeStatisTable error(%v)", err)
return
}
_, err = s.dao.DelIncomeStatisTable(c, "up_av_daily_statis", date.Format(_layout))
if err != nil {
log.Error("s.dao.DelIncomeStatisTable error(%v)", err)
return
}
_, err = s.dao.DelIncomeStatisTable(c, "up_column_daily_statis", date.Format(_layout))
if err != nil {
log.Error("s.dao.DelIncomeStatisTable error(%v)", err)
return
}
_, err = s.dao.DelIncomeStatisTable(c, "up_bgm_daily_statis", date.Format(_layout))
if err != nil {
log.Error("s.dao.DelIncomeStatisTable error(%v)", err)
return
}
upMap := make(map[int64]int64)
upAvMap := make(map[int64]int64)
upCmMap := make(map[int64]int64)
upBgmMap := make(map[int64]int64)
var upTotal, avTotal, cmTotal, bgmTotal int64
for up := range upStatisCh {
up, av, cm, bgm := handleUp(up, upMap, upAvMap, upCmMap, upBgmMap, date)
upTotal += up
avTotal += av
cmTotal += cm
bgmTotal += bgm
}
upSections = countIncomeDailyStatis(upMap, upTotal, 0, date)
upAvSections = countIncomeDailyStatis(upAvMap, avTotal, 0, date)
upCmSections = countIncomeDailyStatis(upCmMap, cmTotal, 0, date)
upBgmSections = countIncomeDailyStatis(upBgmMap, bgmTotal, 0, date)
return
}
func handleUp(upIncomes []*model.UpIncome, upMap, upAvMap, upCmMap, upBgmMap map[int64]int64, startDate time.Time) (income, avIncome, cmIncome, bgmIncome int64) {
if len(upIncomes) == 0 {
return
}
for _, upIncome := range upIncomes {
if startDate.Equal(upIncome.Date.Time()) {
income += upIncome.Income
avIncome += upIncome.AvIncome
cmIncome += upIncome.ColumnIncome
bgmIncome += upIncome.BgmIncome
upMap[upIncome.MID] += upIncome.Income
if upIncome.AvIncome > 0 {
upAvMap[upIncome.MID] += upIncome.AvIncome
}
if upIncome.ColumnIncome > 0 {
upCmMap[upIncome.MID] += upIncome.ColumnIncome
}
if upIncome.BgmIncome > 0 {
upBgmMap[upIncome.MID] += upIncome.BgmIncome
}
}
}
return
}
func (s *DateStatis) incomeDateStatisInsert(c context.Context, incomeSection []*model.DateStatis, table string) (rows int64, err error) {
var buf bytes.Buffer
for _, row := range incomeSection {
buf.WriteString("(")
buf.WriteString(strconv.FormatInt(row.Count, 10))
buf.WriteByte(',')
buf.WriteString(strconv.FormatInt(row.MoneySection, 10))
buf.WriteByte(',')
buf.WriteString(row.MoneyTips)
buf.WriteByte(',')
buf.WriteString(strconv.FormatInt(row.Income, 10))
buf.WriteByte(',')
buf.WriteString(strconv.FormatInt(row.CategoryID, 10))
buf.WriteByte(',')
buf.WriteString("'" + row.CDate.Time().Format(_layout) + "'")
buf.WriteString(")")
buf.WriteByte(',')
}
if buf.Len() > 0 {
buf.Truncate(buf.Len() - 1)
}
vals := buf.String()
buf.Reset()
rows, err = s.dao.InsertIncomeStatisTable(c, table, vals)
return
}
func countIncomeDailyStatis(incomes map[int64]int64, totalIncome, tagID int64, date time.Time) (incomeSections []*model.DateStatis) {
if len(incomes) == 0 {
return
}
incomeSections = initIncomeSections(totalIncome, tagID, xtime.Time(date.Unix()))
for _, income := range incomes {
for _, section := range incomeSections {
min, max := section.MinIncome*100, section.MaxIncome*100
if income >= min && income < max {
section.Count++
}
}
}
return
}
func (s *DateStatis) upIncomeDailyStatisInsert(c context.Context, upIncomeSection []*model.DateStatis, table string) (rows int64, err error) {
var buf bytes.Buffer
for _, row := range upIncomeSection {
buf.WriteString("(")
buf.WriteString(strconv.FormatInt(row.Count, 10))
buf.WriteByte(',')
buf.WriteString(strconv.FormatInt(row.MoneySection, 10))
buf.WriteByte(',')
buf.WriteString(row.MoneyTips)
buf.WriteByte(',')
buf.WriteString(strconv.FormatInt(row.Income, 10))
buf.WriteByte(',')
buf.WriteString("'" + row.CDate.Time().Format(_layout) + "'")
buf.WriteString(")")
buf.WriteByte(',')
}
if buf.Len() > 0 {
buf.Truncate(buf.Len() - 1)
}
vals := buf.String()
buf.Reset()
rows, err = s.dao.InsertUpIncomeDailyStatis(c, table, vals)
return
}