123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351 |
- package service
- import (
- "context"
- "math"
- "time"
- "go-common/app/job/main/figure-timer/conf"
- "go-common/app/job/main/figure-timer/model"
- "go-common/library/log"
- )
- const (
- bizTypePosLawful = iota
- bizTypeNegLawful
- // bizTypePosWide
- // bizTypeNegWide
- bizTypePosFriendly
- bizTypeNegFriendly
- bizTypePosCreativity
- // bizTypeNegCreativity
- bizTypePosBounty
- // bizTypeNegBounty
- )
- // HandleFigure handle all figure score for a mid
- func (s *Service) HandleFigure(c context.Context, mid int64, weekVer int64) (err error) {
- var (
- figure = &model.Figure{}
- userInfo *model.UserInfo
- actionCounter *model.ActionCounter
- records []*model.FigureRecord
- newRecord *model.FigureRecord
- weekVerRecordsFrom = time.Unix(weekVer, 0).AddDate(0, 0, -7*52).Unix()
- weekVerRecordsTo = time.Unix(weekVer, 0).AddDate(0, 0, -7).Unix() + 1
- )
- //1. get user_info from hbase
- if userInfo, err = s.dao.UserInfo(c, mid, weekVer); err != nil {
- return
- }
- //2. get action_counter from hbase
- if actionCounter, err = s.dao.ActionCounter(c, mid, weekVer); err != nil {
- return
- }
- //3. get figure_records from hbase
- if records, err = s.dao.CalcRecords(c, mid, weekVerRecordsFrom, weekVerRecordsTo); err != nil {
- return
- }
- //4. calc figure
- figure, newRecord = s.CalcFigure(c, userInfo, []*model.ActionCounter{actionCounter}, records, weekVer)
- log.Info("User figure [%+v]", figure)
- log.Info("User newRecord [%+v]", newRecord)
- //5. save to db
- time.Sleep(time.Millisecond)
- if figure.ID, err = s.dao.UpsertFigure(c, figure); err != nil {
- log.Error("%+v", err)
- }
- //6. save new record
- if err = s.dao.PutCalcRecord(c, newRecord, weekVer); err != nil {
- log.Error("%+v", err)
- }
- //7. remove existed redis
- if err = s.dao.RemoveCache(c, mid); err != nil {
- log.Error("%+v", err)
- }
- rank.AddScore(figure.Score)
- return
- }
- // CalcFigure calc figure.
- func (s *Service) CalcFigure(c context.Context, userInfo *model.UserInfo, actionCounters []*model.ActionCounter, records []*model.FigureRecord, weekVer int64) (figure *model.Figure, newRecord *model.FigureRecord) {
- figure = &model.Figure{Mid: userInfo.Mid, Ver: weekVer}
- newRecord = &model.FigureRecord{Mid: userInfo.Mid, Version: time.Unix(weekVer, 0)}
- var (
- posx float64
- negx float64
- newPosx, newNegx float64
- k1, k2, k3, k4, k5 float64 = s.c.Property.Calc.K1, s.c.Property.Calc.K2, s.c.Property.Calc.K3, s.c.Property.Calc.K4, s.c.Property.Calc.K5
- posOffset, negOffset int64
- lawfulBase = s.c.Property.Calc.InitLawfulScore
- lawfulPosMax = s.c.Property.Calc.LawfulPosMax
- lawfulNegMax = s.c.Property.Calc.LawfulNegMax
- lawfulPosK = s.c.Property.Calc.LawfulPosK
- lawfulNegK1 = s.c.Property.Calc.LawfulNegK1
- lawfulNegK2 = s.c.Property.Calc.LawfulNegK2
- lawfulPosL = s.c.Property.Calc.LawfulPosL
- lawfulNegL = s.c.Property.Calc.LawfulNegL
- lawfulPosC3 = s.c.Property.Calc.LawfulPosC3
- lawfulNegC1 = s.c.Property.Calc.LawfulNegC1
- lawfulPosQ3 = s.c.Property.Calc.LawfulPosQ3
- lawfulNegQ1 = s.c.Property.Calc.LawfulNegQ1
- wideBase = s.c.Property.Calc.InitWideScore
- widePosMax = s.c.Property.Calc.WidePosMax
- widePosK = s.c.Property.Calc.WidePosK
- wideC1 = s.c.Property.Calc.WideC1 //有播放的活跃天数
- wideQ1 = s.c.Property.Calc.WideQ1
- wideC2 = s.c.Property.Calc.WideC2 // 账号累计经验值
- wideQ2 = s.c.Property.Calc.WideQ2
- friendlyBase = s.c.Property.Calc.InitFriendlyScore
- friendlyPosMax = s.c.Property.Calc.FriendlyPosMax
- friendlyNegMax = s.c.Property.Calc.FriendlyNegMax
- friendlyPosK = s.c.Property.Calc.FriendlyPosK
- friendlyNegK = s.c.Property.Calc.FriendlyNegK
- friendlyPosL = s.c.Property.Calc.FriendlyPosL
- friendlyNegL = s.c.Property.Calc.FriendlyNegL
- bountyBase = s.c.Property.Calc.InitBountyScore
- bountyMax = s.c.Property.Calc.BountyMax
- bountyPosL = s.c.Property.Calc.BountyPosL
- bountyK = s.c.Property.Calc.BountyK
- bountyQ1 = s.c.Property.Calc.BountyQ1
- bountyC1 = s.c.Property.Calc.BountyC1
- creativityBase = s.c.Property.Calc.InitCreativityScore
- creativityPosMax = s.c.Property.Calc.CreativityPosMax
- creativityPosK = s.c.Property.Calc.CreativityPosK
- creativityPosL1 = s.c.Property.Calc.CreativityPosL1
- )
- //1. lawful
- newPosx, posx = s.calcActionX(lawfulPosL, bizTypePosLawful, actionCounters, records, weekVer)
- posx += lawfulPosQ3 * lawfulPosC3 * float64(userInfo.DisciplineCommittee)
- posOffset = calcOffset(lawfulPosMax, lawfulPosK, posx)
- spyScore := userInfo.SpyScore
- negx = lawfulNegQ1 * lawfulNegC1 * float64(80-float64(spyScore))
- if negx < 0 {
- negx = 0.0
- }
- negOffset = calcOffset(lawfulNegMax, lawfulNegK1, negx)
- newNegx, negx = s.calcActionX(lawfulNegL, bizTypeNegLawful, actionCounters, records, weekVer)
- negOffset += calcOffset(lawfulNegMax, lawfulNegK2, negx)
- figure.LawfulScore = int32(lawfulBase + posOffset - negOffset)
- if figure.LawfulScore < 0 {
- figure.LawfulScore = 0
- }
- newRecord.XPosLawful, newRecord.XNegLawful = int64(newPosx), int64(newNegx)
- //2. wide
- newPosx, newNegx = 0, 0
- posx = wideQ1*wideC1*float64(userInfo.ArchiveViews) + wideQ2*wideC2*float64(userInfo.Exp)
- posOffset = calcOffset(widePosMax, widePosK, posx)
- negx = 0
- negOffset = 0
- figure.WideScore = int32(wideBase + posOffset - negOffset)
- if figure.WideScore < 0 {
- figure.WideScore = 0
- }
- newRecord.XPosWide, newRecord.XNegWide = int64(newPosx), int64(newNegx)
- //3. friendly
- newPosx, newNegx = 0, 0
- newPosx, posx = s.calcActionX(friendlyPosL, bizTypePosFriendly, actionCounters, records, weekVer)
- posOffset = calcOffset(friendlyPosMax, friendlyPosK, posx)
- newNegx, negx = s.calcActionX(friendlyNegL, bizTypeNegFriendly, actionCounters, records, weekVer)
- negOffset = calcOffset(friendlyNegMax, friendlyNegK, negx)
- figure.FriendlyScore = int32(friendlyBase + posOffset - negOffset)
- if figure.FriendlyScore < 0 {
- figure.FriendlyScore = 0
- }
- newRecord.XPosFriendly, newRecord.XNegFriendly = int64(newPosx), int64(newNegx)
- //4. bounty
- newPosx, newNegx = 0, 0
- var bountyVIP float64
- if userInfo.VIPStatus > 0 {
- bountyVIP = 1
- }
- newPosx, posx = s.calcActionX(bountyPosL, bizTypePosBounty, actionCounters, records, weekVer)
- posx += bountyQ1 * bountyC1 * bountyVIP
- posOffset = calcOffset(bountyMax, bountyK, posx)
- negx = 0
- negOffset = 0
- figure.BountyScore = int32(bountyBase + posOffset - negOffset)
- if figure.BountyScore < 0 {
- figure.BountyScore = 0
- }
- newRecord.XPosBounty, newRecord.XNegBounty = int64(newPosx), int64(newNegx)
- //5. creativity
- newPosx, newNegx = 0, 0
- newPosx, posx = s.calcActionX(creativityPosL1, bizTypePosCreativity, actionCounters, records, weekVer)
- posOffset = calcOffset(creativityPosMax, creativityPosK, posx)
- negx = 0
- negOffset = 0
- figure.CreativityScore = int32(creativityBase + posOffset - negOffset)
- if figure.CreativityScore < 0 {
- figure.CreativityScore = 0
- }
- newRecord.XPosCreativity, newRecord.XNegCreativity = int64(newPosx), int64(newNegx)
- //6. calc score
- figure.Score = int32(math.Floor(k1*float64(figure.LawfulScore) + k2*float64(figure.WideScore) + k3*float64(figure.FriendlyScore) + k4*float64(figure.CreativityScore) + k5*float64(figure.BountyScore)))
- return
- }
- // x must >= 0
- func calcOffset(max, k, x float64) (score int64) {
- return int64(math.Floor(max * (1 - math.Pow(math.E, -(k*x)))))
- }
- func (s *Service) calcActionX(L float64, bizType int8, actionCounters []*model.ActionCounter, records []*model.FigureRecord, weekVer int64) (newx, totalx float64) {
- var (
- day int64 = 24 * 3600
- t float64
- lawfulPosC1 = s.c.Property.Calc.LawfulPosC1
- lawfulPosC2 = s.c.Property.Calc.LawfulPosC2
- lawfulPosQ1 = s.c.Property.Calc.LawfulPosQ1
- lawfulPosQ2 = s.c.Property.Calc.LawfulPosQ2
- lawfulNegC2 = s.c.Property.Calc.LawfulNegC2
- lawfulNegC3 = s.c.Property.Calc.LawfulNegC3
- lawfulNegQ2 = s.c.Property.Calc.LawfulNegQ2
- lawfulNegQ3 = s.c.Property.Calc.LawfulNegQ3
- friendlyPosQ1 = s.c.Property.Calc.FriendlyPosQ1
- friendlyPosC1 = s.c.Property.Calc.FriendlyPosC1
- friendlyPosQ2 = s.c.Property.Calc.FriendlyPosQ2
- friendlyPosC2 = s.c.Property.Calc.FriendlyPosC2
- friendlyPosQ3 = s.c.Property.Calc.FriendlyPosQ3
- friendlyPosC3 = s.c.Property.Calc.FriendlyPosC3
- friendlyNegQ1 = s.c.Property.Calc.FriendlyNegQ1
- friendlyNegC1 = s.c.Property.Calc.FriendlyNegC1
- friendlyNegQ2 = s.c.Property.Calc.FriendlyNegQ2
- friendlyNegC2 = s.c.Property.Calc.FriendlyNegC2
- friendlyNegQ3 = s.c.Property.Calc.FriendlyNegQ3
- friendlyNegC3 = s.c.Property.Calc.FriendlyNegC3
- friendlyNegQ4 = s.c.Property.Calc.FriendlyNegQ4
- friendlyNegC4 = s.c.Property.Calc.FriendlyNegC4
- creativityQ1 = s.c.Property.Calc.CreativityQ1
- creativityC1 = s.c.Property.Calc.CreativityC1
- bountyQ2 = s.c.Property.Calc.BountyQ2
- bountyC2 = s.c.Property.Calc.BountyC2
- bountyQ3 = s.c.Property.Calc.BountyQ3
- bountyC3 = s.c.Property.Calc.BountyC3
- )
- if L == 0.0 {
- return 0, 0
- }
- for _, ac := range actionCounters {
- t = float64(7 - (ac.Version.Unix()-weekVer)/day)
- if t <= 0 {
- continue
- }
- switch bizType {
- case bizTypePosLawful:
- if ac.ReportReplyPassed < 0 {
- ac.ReportReplyPassed = 0
- }
- newx += actionX(lawfulPosQ1, lawfulPosC1, float64(ac.ReportReplyPassed), t, L)
- if ac.ReportDanmakuPassed < 0 {
- ac.ReportDanmakuPassed = 0
- }
- newx += actionX(lawfulPosQ2, lawfulPosC2, float64(ac.ReportDanmakuPassed), t, L)
- case bizTypeNegLawful:
- if ac.PublishReplyDeleted < 0 {
- ac.PublishReplyDeleted = 0
- }
- newx += actionX(lawfulNegQ2, lawfulNegC2, float64(ac.PublishReplyDeleted), t, L)
- if ac.PublishDanmakuDeleted < 0 {
- ac.PublishDanmakuDeleted = 0
- }
- newx += actionX(lawfulNegQ3, lawfulNegC3, float64(ac.PublishDanmakuDeleted), t, L)
- case bizTypePosFriendly:
- newx += actionX(friendlyPosQ1, friendlyPosC1, float64(ac.CoinCount), t, L)
- newx += actionX(friendlyPosQ2, friendlyPosC2, float64(ac.ReplyCount), t, L)
- newx += actionX(friendlyPosQ3, friendlyPosC3, float64(ac.DanmakuCount), t, L)
- case bizTypeNegFriendly:
- newx += actionX(friendlyNegQ1, friendlyNegC1, float64(ac.CoinHighRisk), t, L)
- newx += actionX(friendlyNegQ2, friendlyNegC2, float64(ac.CoinLowRisk), t, L)
- if ac.PublishReplyDeleted < 0 {
- ac.PublishReplyDeleted = 0
- }
- newx += actionX(friendlyNegQ3, friendlyNegC3, float64(ac.PublishReplyDeleted), t, L)
- if ac.PublishDanmakuDeleted < 0 {
- ac.PublishDanmakuDeleted = 0
- }
- newx += actionX(friendlyNegQ4, friendlyNegC4, float64(ac.PublishDanmakuDeleted), t, L)
- case bizTypePosCreativity:
- replyLikeCount := float64(ac.ReplyLiked) - float64(ac.ReplyUnliked)
- if replyLikeCount < 0 {
- replyLikeCount = 0.0
- }
- newx += actionX(creativityQ1, creativityC1, replyLikeCount, t, L)
- case bizTypePosBounty:
- newx += actionX(bountyQ2, bountyC2, float64(ac.PayMoney), t, L)
- newx += actionX(bountyQ3, bountyC3, float64(ac.PayLiveMoney), t, L)
- }
- }
- totalx = newx
- for _, r := range records {
- t = float64((weekVer - r.Version.Unix()) / day)
- if t <= 0 {
- continue
- }
- switch bizType {
- case bizTypePosLawful:
- totalx += actionX(1, 1, float64(r.XPosLawful), t, L)
- case bizTypeNegLawful:
- totalx += actionX(1, 1, float64(r.XNegLawful), t, L)
- case bizTypePosFriendly:
- totalx += actionX(1, 1, float64(r.XPosFriendly), t, L)
- case bizTypeNegFriendly:
- totalx += actionX(1, 1, float64(r.XNegFriendly), t, L)
- case bizTypePosCreativity:
- totalx += actionX(1, 1, float64(r.XPosCreativity), t, L)
- case bizTypePosBounty:
- totalx += actionX(1, 1, float64(r.XPosBounty), t, L)
- }
- }
- return
- }
- func actionX(q, c, x, t, L float64) float64 {
- return q * c * x * math.Pow(math.E, -math.Pow((t/L), 2))
- }
- // InitFigure initialize user figure
- func (s *Service) InitFigure(c context.Context, mid int64, ver string) (figure *model.Figure, err error) {
- figure = &model.Figure{}
- figure.Mid = mid
- figure.LawfulScore = int32(conf.Conf.Property.Calc.InitLawfulScore)
- figure.WideScore = int32(conf.Conf.Property.Calc.InitWideScore)
- figure.FriendlyScore = int32(conf.Conf.Property.Calc.InitFriendlyScore)
- figure.BountyScore = int32(conf.Conf.Property.Calc.InitBountyScore)
- figure.CreativityScore = int32(conf.Conf.Property.Calc.InitCreativityScore)
- figure.Ver = s.curVer
- if figure.ID, err = s.dao.UpsertFigure(c, figure); err != nil {
- return
- }
- if err = s.dao.SetFigureCache(c, figure); err != nil {
- log.Error("%+v", err)
- }
- return
- }
- // get ever monday start time ts.
- func weekVersion(now time.Time) (ts int64) {
- var (
- wd int
- w time.Weekday
- )
- w = now.Weekday()
- switch w {
- case time.Sunday:
- wd = 6
- default:
- wd = int(w) - 1
- }
- return time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, time.Local).AddDate(0, 0, -wd).Unix()
- }
|