355 lines
9.7 KiB
Go
355 lines
9.7 KiB
Go
package data
|
||
|
||
import (
|
||
"context"
|
||
"sort"
|
||
"time"
|
||
|
||
"go-common/app/interface/main/creative/model/data"
|
||
"go-common/app/interface/main/creative/model/tag"
|
||
|
||
"go-common/library/ecode"
|
||
"go-common/library/log"
|
||
)
|
||
|
||
func beginningOfDay(t time.Time) time.Time {
|
||
d := time.Duration(-t.Hour()) * time.Hour
|
||
return t.Truncate(time.Hour).Add(d)
|
||
}
|
||
|
||
func getTuesday(now time.Time) time.Time {
|
||
t := beginningOfDay(now)
|
||
weekday := int(t.Weekday())
|
||
if weekday == 0 {
|
||
weekday = 7
|
||
}
|
||
d := time.Duration(-weekday+2) * 24 * time.Hour
|
||
return t.Truncate(time.Hour).Add(d)
|
||
}
|
||
|
||
func getSunday(now time.Time) time.Time {
|
||
t := beginningOfDay(now)
|
||
weekday := int(t.Weekday())
|
||
if weekday == 0 {
|
||
return t
|
||
}
|
||
d := time.Duration(7-weekday) * 24 * time.Hour
|
||
return t.Truncate(time.Hour).Add(d)
|
||
}
|
||
|
||
func getDate() (sd string) {
|
||
t := time.Now()
|
||
td := getTuesday(t).Add(12 * time.Hour)
|
||
if t.Before(td) { //当前时间在本周二12点之前,则取上上周日的数据,否则取上周日的数据
|
||
sd = getSunday(t.AddDate(0, 0, -14)).Format("20060102")
|
||
} else {
|
||
sd = getSunday(t.AddDate(0, 0, -7)).Format("20060102")
|
||
}
|
||
log.Info("current time (%s) tuesday (%s) sunday (%s)", t.Format("2006-01-02 15:04:05"), td, sd)
|
||
return
|
||
}
|
||
|
||
// NewStat get stat from hbase.
|
||
func (s *Service) NewStat(c context.Context, mid int64, ip string) (r *data.Stat, err error) {
|
||
hbaseDate1 := time.Now().AddDate(0, 0, -1).Add(-12 * time.Hour).Format("20060102")
|
||
hbaseDate2 := time.Now().AddDate(0, 0, -2).Add(-12 * time.Hour).Format("20060102")
|
||
var r1, r2 *data.UpBaseStat
|
||
if r1, err = s.data.UpStat(c, mid, hbaseDate1); err != nil || r1 == nil {
|
||
log.Error("s.data.NewStat error(%v) mid(%d) r1(%v) ip(%s)", err, mid, r1, ip)
|
||
err = ecode.CreativeDataErr
|
||
return
|
||
}
|
||
if r2, err = s.data.UpStat(c, mid, hbaseDate2); err != nil || r2 == nil {
|
||
log.Error("s.data.NewStat error(%v) mid(%d) r2(%v) ip(%s)", err, mid, r2, ip)
|
||
err = ecode.CreativeDataErr
|
||
return
|
||
}
|
||
r = &data.Stat{}
|
||
if r1 != nil {
|
||
r.Play = r1.View
|
||
r.Dm = r1.Dm
|
||
r.Comment = r1.Reply
|
||
r.Fan = r1.Fans
|
||
r.Fav = r1.Fav
|
||
r.Like = r1.Like
|
||
r.Share = r1.Share
|
||
r.Coin = r1.Coin
|
||
r.Elec = r1.Elec
|
||
}
|
||
log.Info("s.data.UpStat hbaseDate1(%+v) mid(%d)", r1, mid)
|
||
if r2 != nil {
|
||
r.PlayLast = r2.View
|
||
r.DmLast = r2.Dm
|
||
r.CommentLast = r2.Reply
|
||
r.FanLast = r2.Fans
|
||
r.FavLast = r2.Fav
|
||
r.LikeLast = r2.Like
|
||
r.ShareLast = r2.Share
|
||
r.CoinLast = r2.Coin
|
||
r.ElecLast = r2.Elec
|
||
}
|
||
log.Info("s.data.UpStat hbaseDate2 (%+v) mid(%d)", r2, mid)
|
||
pfl, err := s.acc.ProfileWithStat(c, mid)
|
||
if err != nil {
|
||
return
|
||
}
|
||
r.Fan = int64(pfl.Follower)
|
||
return
|
||
}
|
||
|
||
// ViewerBase get up viewer base data.
|
||
func (s *Service) ViewerBase(c context.Context, mid int64) (res map[string]*data.ViewerBase, err error) {
|
||
dt := getDate()
|
||
// try cache
|
||
if res, _ = s.data.ViewerBaseCache(c, mid, dt); res != nil {
|
||
s.pCacheHit.Incr("viewer_base_cache")
|
||
return
|
||
}
|
||
// from data source
|
||
if res, err = s.data.ViewerBase(c, mid, dt); len(res) != 0 {
|
||
s.pCacheMiss.Incr("viewer_base_cache")
|
||
s.data.AddCache(func() {
|
||
s.data.AddViewerBaseCache(context.Background(), mid, dt, res)
|
||
})
|
||
}
|
||
return
|
||
}
|
||
|
||
// ViewerArea get up viewer area data.
|
||
func (s *Service) ViewerArea(c context.Context, mid int64) (res map[string]map[string]int64, err error) {
|
||
dt := getDate()
|
||
// try cache
|
||
if res, _ = s.data.ViewerAreaCache(c, mid, dt); res != nil {
|
||
s.pCacheHit.Incr("viewer_area_cache")
|
||
return
|
||
}
|
||
// from data source
|
||
if res, err = s.data.ViewerArea(c, mid, dt); len(res) != 0 {
|
||
s.pCacheMiss.Incr("viewer_area_cache")
|
||
s.data.AddCache(func() {
|
||
s.data.AddViewerAreaCache(context.Background(), mid, dt, res)
|
||
})
|
||
}
|
||
return
|
||
}
|
||
|
||
// CacheTrend get trend from mc.
|
||
func (s *Service) CacheTrend(c context.Context, mid int64) (res map[string]*data.ViewerTrend, err error) {
|
||
dt := getDate()
|
||
// try cache
|
||
if res, err = s.data.TrendCache(c, mid, dt); err != nil {
|
||
log.Error("trend s.data.TrendCache err(%v)", err)
|
||
return
|
||
}
|
||
if len(res) != 0 {
|
||
s.pCacheHit.Incr("trend_cache")
|
||
return
|
||
}
|
||
// from data source
|
||
if res, err = s.viewerTrend(c, mid, dt); err != nil {
|
||
return
|
||
}
|
||
s.pCacheMiss.Incr("trend_cache")
|
||
if len(res) != 0 {
|
||
s.data.AddCache(func() {
|
||
s.data.AddTrendCache(context.Background(), mid, dt, res)
|
||
})
|
||
}
|
||
return
|
||
}
|
||
|
||
// ViewerTrend get up viewer trend data.
|
||
func (s *Service) viewerTrend(c context.Context, mid int64, dt string) (res map[string]*data.ViewerTrend, err error) {
|
||
ut, err := s.data.ViewerTrend(c, mid, dt)
|
||
if err != nil || ut == nil {
|
||
log.Error("trend s.data.ViewerTrend err(%v)", err)
|
||
return
|
||
}
|
||
f := []string{"fan", "not_fan"}
|
||
skeys := make([]int, 0) //for tag sort.
|
||
tgs := make([]int64, 0) // for request tag name.
|
||
res = make(map[string]*data.ViewerTrend)
|
||
for _, fk := range f {
|
||
td := ut[fk]
|
||
vt := &data.ViewerTrend{}
|
||
if td == nil {
|
||
vt.Ty = nil
|
||
vt.Tag = nil
|
||
res[fk] = vt
|
||
continue
|
||
}
|
||
tg := make(map[int]string) //return tag map to user.
|
||
ty := make(map[string]int64) //return type map to user.
|
||
//deal type for type name.
|
||
if td.Ty != nil {
|
||
for k, v := range td.Ty {
|
||
ke := int16(k)
|
||
if t, ok := s.p.TypeMapCache[ke]; ok {
|
||
ty[t.Name] = v
|
||
}
|
||
}
|
||
} else {
|
||
ty = nil
|
||
}
|
||
// deal tag for tag name.
|
||
if td.Tag != nil {
|
||
for k, v := range td.Tag {
|
||
tgs = append(tgs, v)
|
||
skeys = append(skeys, k)
|
||
}
|
||
var tlist []*tag.Meta
|
||
if tlist, err = s.dtag.TagList(c, tgs); err != nil {
|
||
log.Error("trend s.dtag.TagList err(%v)", err)
|
||
}
|
||
tNameMap := make(map[int64]string)
|
||
for _, v := range tlist {
|
||
tNameMap[v.TagID] = v.TagName
|
||
}
|
||
for _, k := range skeys {
|
||
if _, ok := tNameMap[td.Tag[k]]; ok {
|
||
tg[k] = tNameMap[td.Tag[k]]
|
||
}
|
||
}
|
||
} else {
|
||
tg = nil
|
||
}
|
||
vt.Ty = ty
|
||
vt.Tag = tg
|
||
res[fk] = vt
|
||
}
|
||
return
|
||
}
|
||
|
||
// RelationFansDay get up viewer trend data.
|
||
func (s *Service) RelationFansDay(c context.Context, mid int64) (res map[string]map[string]int, err error) {
|
||
dt := time.Now().AddDate(0, 0, -1).Add(-12 * time.Hour).Format("20060102")
|
||
// try cache
|
||
if res, _ = s.data.RelationFansDayCache(c, mid, dt); res != nil {
|
||
s.pCacheHit.Incr("relation_fans_day_cache")
|
||
return
|
||
}
|
||
// from data source
|
||
if res, err = s.data.RelationFansDay(c, mid); len(res) != 0 {
|
||
s.pCacheMiss.Incr("relation_fans_day_cache")
|
||
s.data.AddCache(func() {
|
||
s.data.AddRelationFansDayCache(context.Background(), mid, dt, res)
|
||
})
|
||
}
|
||
return
|
||
}
|
||
|
||
// RelationFansHistory get relation history data by month.
|
||
func (s *Service) RelationFansHistory(c context.Context, mid int64, month string) (res map[string]map[string]int, err error) {
|
||
if res, err = s.data.RelationFansHistory(c, mid, month); err != nil {
|
||
log.Error("s.data.RelationFansHistory err(%v)", err)
|
||
}
|
||
return
|
||
}
|
||
|
||
// RelationFansMonth get up viewer trend data.
|
||
func (s *Service) RelationFansMonth(c context.Context, mid int64) (res map[string]map[string]int, err error) {
|
||
dt := time.Now().AddDate(0, 0, -1).Add(-12 * time.Hour).Format("20060102")
|
||
// try cache
|
||
if res, _ = s.data.RelationFansMonthCache(c, mid, dt); res != nil {
|
||
s.pCacheHit.Incr("relation_fans_month_cache")
|
||
return
|
||
}
|
||
// from data source
|
||
if res, err = s.data.RelationFansMonth(c, mid); len(res) != 0 {
|
||
s.pCacheMiss.Incr("relation_fans_month_cache")
|
||
s.data.AddCache(func() {
|
||
s.data.AddRelationFansMonthCache(context.Background(), mid, dt, res)
|
||
})
|
||
}
|
||
return
|
||
}
|
||
|
||
// ViewerActionHour get up viewer action hour data.
|
||
func (s *Service) ViewerActionHour(c context.Context, mid int64) (res map[string]*data.ViewerActionHour, err error) {
|
||
dt := getDate()
|
||
// try cache
|
||
if res, _ = s.data.ViewerActionHourCache(c, mid, dt); res != nil {
|
||
s.pCacheHit.Incr("viewer_action_hour_cache")
|
||
return
|
||
}
|
||
// from data source
|
||
if res, err = s.data.ViewerActionHour(c, mid, dt); len(res) != 0 {
|
||
s.data.AddCache(func() {
|
||
s.pCacheMiss.Incr("viewer_action_hour_cache")
|
||
s.data.AddViewerActionHourCache(context.Background(), mid, dt, res)
|
||
})
|
||
}
|
||
return
|
||
}
|
||
|
||
// UpIncr for Play/Dm/Reply/Fav/Share/Elec/Coin incr.
|
||
func (s *Service) UpIncr(c context.Context, mid int64, ty int8, ip string) (res map[string]*data.ViewerIncr, err error) {
|
||
tyStr, _ := data.IncrTy(ty)
|
||
res = make(map[string]*data.ViewerIncr)
|
||
daytime := time.Now().AddDate(0, 0, -1).Add(-12 * time.Hour)
|
||
datekey := daytime.Format("20060102")
|
||
dt := daytime.Format("20060102")
|
||
vic, _ := s.data.ViewerIncrCache(c, mid, tyStr, dt)
|
||
if vic != nil {
|
||
s.pCacheHit.Incr("viewer_incr_cache")
|
||
res[datekey] = vic
|
||
log.Info("s.data.ViewerIncrCache mid(%d) cache(%v) err(%v)", mid, vic, err)
|
||
return
|
||
}
|
||
incr, _ := s.data.UpIncr(c, mid, ty, dt)
|
||
if incr == nil {
|
||
res[datekey] = nil
|
||
log.Info("s.data.UpIncr mid(%d) incr(%v) err(%v)", incr, err)
|
||
return
|
||
}
|
||
tyRank := make(map[string]int) //return type map to user.
|
||
for k, v := range incr.Rank {
|
||
ke := int16(k)
|
||
if t, ok := s.p.TypeMapCache[ke]; ok {
|
||
tyRank[t.Name] = v
|
||
}
|
||
}
|
||
sortK := make([]int, 0, len(incr.TopAIDList))
|
||
aids := make([]int64, 0, len(incr.TopAIDList))
|
||
for k, v := range incr.TopAIDList {
|
||
aids = append(aids, v)
|
||
sortK = append(sortK, k)
|
||
}
|
||
avm, _ := s.p.BatchArchives(c, mid, aids, ip)
|
||
if len(avm) == 0 {
|
||
return
|
||
}
|
||
sort.Ints(sortK)
|
||
arcs := make([]*data.ArcInc, 0, len(avm))
|
||
for _, k := range sortK {
|
||
if aid, ok := incr.TopAIDList[k]; ok {
|
||
if av, ok := avm[aid]; ok {
|
||
al := &data.ArcInc{}
|
||
al.AID = av.Archive.Aid
|
||
al.PTime = av.Archive.PTime
|
||
al.Title = av.Archive.Title
|
||
al.DayTime = daytime.Unix()
|
||
if _, ok := incr.TopIncrList[k]; ok {
|
||
al.Incr = incr.TopIncrList[k]
|
||
}
|
||
arcs = append(arcs, al)
|
||
}
|
||
}
|
||
}
|
||
vi := &data.ViewerIncr{}
|
||
vi.Arcs = arcs
|
||
vi.TotalIncr = incr.Incr
|
||
if len(tyRank) == 0 {
|
||
vi.TyRank = nil
|
||
} else {
|
||
vi.TyRank = tyRank
|
||
}
|
||
res[datekey] = vi
|
||
// insert cache. NOTE: sync reason?
|
||
s.data.AddCache(func() {
|
||
s.pCacheMiss.Incr("viewer_incr_cache")
|
||
s.data.AddViewerIncrCache(context.Background(), mid, tyStr, dt, vi)
|
||
})
|
||
return
|
||
}
|