go-common/app/interface/main/creative/service/data/overview.go
2019-04-22 18:49:16 +08:00

355 lines
9.7 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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
}