go-common/app/interface/main/activity/service/like/match.go
2019-04-22 18:49:16 +08:00

303 lines
8.5 KiB
Go

package like
import (
"context"
"encoding/json"
"time"
"go-common/app/interface/main/activity/conf"
dao "go-common/app/interface/main/activity/dao/like"
match "go-common/app/interface/main/activity/model/like"
coinmdl "go-common/app/service/main/coin/model"
suitmdl "go-common/app/service/main/usersuit/model"
"go-common/library/ecode"
"go-common/library/log"
"go-common/library/net/metadata"
"go-common/library/sync/errgroup"
)
const (
_matchTable = "act_matchs"
_objectTable = "act_matchs_object"
_userLogTable = "act_match_user_log"
_reason = "参与竞猜"
)
var (
_emptyMatch = make([]*match.Match, 0)
_emptyObjects = make([]*match.Object, 0)
_emptyUserLog = make([]*match.UserLog, 0)
_emptyFollow = make([]string, 0)
)
// Match get match.
func (s *Service) Match(c context.Context, sid int64) (rs []*match.Match, err error) {
// get from cache.
if rs, err = s.dao.ActMatchCache(c, sid); err != nil || len(rs) == 0 {
if rs, err = s.dao.ActMatch(c, sid); err != nil {
log.Error("s.dao.Match sid(%d) error(%v)", sid, err)
return
}
if len(rs) == 0 {
rs = _emptyMatch
return
}
s.cache.Do(c, func(c context.Context) {
s.dao.SetActMatchCache(c, sid, rs)
})
}
return
}
// AddGuess add match guess.
func (s *Service) AddGuess(c context.Context, mid int64, p *match.ParamAddGuess) (rs int64, err error) {
var (
object *match.Object
userGuess []*match.UserLog
group *errgroup.Group
coinErr, suitErr error
count float64
ip = metadata.String(c, metadata.RemoteIP)
)
if p.Stake > conf.Conf.Rule.MaxGuessCoin {
err = ecode.ActivityOverCoin
return
}
//check mid coin count
if count, err = s.coin.UserCoins(c, &coinmdl.ArgCoinInfo{Mid: mid, RealIP: ip}); err != nil {
dao.PromError("UserCoins接口错误", "s.coin.UserCoins(%d,%s) error(%v)", mid, ip, err)
return
}
if count < float64(p.Stake) {
err = ecode.ActivityNotEnoughCoin
return
}
// get from cache.
if object, err = s.dao.ObjectCache(c, p.ObjID); err != nil || object == nil {
if object, err = s.dao.Object(c, p.ObjID); err != nil {
log.Error("s.dao.Match id(%d) error(%v)", p.ObjID, err)
return
}
if object == nil || object.ID == 0 {
err = ecode.ActivityNotExist
return
}
s.cache.Do(c, func(c context.Context) {
s.dao.SetObjectCache(c, p.ObjID, object)
})
}
if time.Now().Unix() < object.Stime.Time().Unix() {
err = ecode.ActivityNotStart
return
} else if object.Result > 0 || time.Now().Unix() > object.Etime.Time().Unix() {
err = ecode.ActivityOverEnd
return
}
sid := object.Sid
if userGuess, err = s.ListGuess(c, sid, mid); err != nil {
log.Error("s.ListGuess(%d,%d) error(%v)", sid, mid, err)
return
}
for _, userLog := range userGuess {
if userLog.MOId == p.ObjID {
err = ecode.ActivityHaveGuess
return
}
}
if rs, err = s.dao.AddGuess(c, mid, object.MatchId, p.ObjID, sid, p.Result, p.Stake); err != nil || rs == 0 {
log.Error("s.dao.AddGuess matchID(%d) objectID(%d) sid(%d) error(%v)", object.MatchId, p.ObjID, sid, err)
return
}
s.dao.DelUserLogCache(context.Background(), sid, mid)
group, errCtx := errgroup.WithContext(c)
if len(s.c.Rule.SuitPids) > 0 && len(userGuess)+1 == s.c.Rule.GuessCount {
for _, v := range s.c.Rule.SuitPids {
pid := v
group.Go(func() error {
mids := []int64{mid}
if suitErr = s.suit.GrantByMids(errCtx, &suitmdl.ArgGrantByMids{Mids: mids, Pid: pid, Expire: s.c.Rule.SuitExpire}); suitErr != nil {
dao.PromError("GrantByMids接口错误", "s.suit.GrantByMids(%d,%d,%s) error(%v)", mid, p.Stake, ip, suitErr)
}
return nil
})
}
}
group.Go(func() error {
loseCoin := float64(-p.Stake)
if _, coinErr = s.coin.ModifyCoin(errCtx, &coinmdl.ArgModifyCoin{Mid: mid, Count: loseCoin, Reason: _reason, IP: ip}); coinErr != nil {
dao.PromError("ModifyCoin接口错误", "s.coin.ModifyCoin(%d,%d,%s) error(%v)", mid, p.Stake, ip, coinErr)
}
return nil
})
if s.c.Rule.MatchLotteryID > 0 {
group.Go(func() error {
if lotteryErr := s.dao.AddLotteryTimes(errCtx, s.c.Rule.MatchLotteryID, mid); lotteryErr != nil {
log.Error("s.dao.AddLotteryTimes(%d,%d) error(%+v)", s.c.Rule.MatchLotteryID, mid, lotteryErr)
}
return nil
})
}
group.Wait()
return
}
// ListGuess get match guess list.
func (s *Service) ListGuess(c context.Context, sid, mid int64) (rs []*match.UserLog, err error) {
// get from cache.
if rs, err = s.dao.UserLogCache(c, sid, mid); err != nil || len(rs) == 0 {
if rs, err = s.dao.ListGuess(c, sid, mid); err != nil {
log.Error("s.dao.ListGuess sid(%d) mid(%d) error(%v)", sid, mid, err)
return
}
if len(rs) == 0 {
rs = _emptyUserLog
return
}
}
var (
moIDs []int64
objects map[int64]*match.Object
)
for _, v := range rs {
moIDs = append(moIDs, v.MOId)
}
if len(moIDs) == 0 {
return
}
if objects, err = s.dao.MatchSubjects(c, moIDs); err == nil {
for _, v := range rs {
if obj, ok := objects[v.MOId]; ok {
v.HomeName = obj.HomeName
v.AwayName = obj.AwayName
v.ObjResult = obj.Result
v.GameStime = obj.GameStime
}
}
}
s.cache.Do(c, func(c context.Context) {
s.dao.SetUserLogCache(c, sid, mid, rs)
})
return
}
// Guess user guess
func (s *Service) Guess(c context.Context, mid int64, p *match.ParamSid) (rs *match.UserGuess, err error) {
var (
userGuess []*match.UserLog
totalCont, winCount int64
)
if userGuess, err = s.ListGuess(c, p.Sid, mid); err != nil {
log.Error("s.ListGuess(%d,%d) error(%v)", p.Sid, mid, err)
return
}
for _, guess := range userGuess {
if guess.ObjResult > 0 {
if guess.Result == guess.ObjResult {
winCount++
}
totalCont++
}
}
rs = new(match.UserGuess)
rs.Total = totalCont
rs.Win = winCount
return
}
// ClearCache del match and object cache
func (s *Service) ClearCache(c context.Context, msg string) (err error) {
var m struct {
Table string `json:"table"`
New struct {
ID int64 `json:"id"`
Sid int64 `json:"sid"`
MatID int64 `json:"match_id"`
Mid int64 `json:"mid"`
MOId int64 `json:"m_o_id"`
} `json:"new,omitempty"`
}
if err = json.Unmarshal([]byte(msg), &m); err != nil {
log.Error("ClearCache json.Unmarshal msg(%s) error(%v)", msg, err)
return
}
log.Info("ClearCache json.Unmarshal msg(%s)", msg)
if m.Table == _matchTable {
if err = s.dao.DelActMatchCache(c, m.New.Sid, m.New.ID); err != nil {
log.Error("s.dao.DelActMatchCache sid(%d) matchID(%d) error(%v)", m.New.Sid, m.New.ID, err)
}
} else if m.Table == _objectTable {
if err = s.dao.DelObjectCache(c, m.New.ID, m.New.Sid); err != nil {
log.Error("s.dao.DelObjectCache objID(%d) Sid(%d) error(%v)", m.New.ID, m.New.Sid, err)
}
} else if m.Table == _userLogTable {
if err = s.dao.DelUserLogCache(c, m.New.Sid, m.New.Mid); err != nil {
log.Error("s.dao.DelUserLogCache mid(%d) error(%v)", m.New.Mid, err)
}
}
return
}
// AddFollow add match follow
func (s *Service) AddFollow(c context.Context, mid int64, teams []string) (err error) {
if err = s.dao.AddFollow(c, mid, teams); err != nil {
log.Error("s.dao.AddFollow mid(%d) teams(%v) error(%v)", mid, teams, err)
}
return
}
// Follow get match follow
func (s *Service) Follow(c context.Context, mid int64) (res []string, err error) {
if res, err = s.dao.Follow(c, mid); err != nil {
log.Error("s.dao.Follow mid(%d) error(%v)", mid, err)
}
if len(res) == 0 {
res = _emptyFollow
}
return
}
// ObjectsUnStart get unstart object list.
func (s *Service) ObjectsUnStart(c context.Context, mid int64, p *match.ParamObject) (rs []*match.Object, count int, err error) {
var (
userGuess []*match.UserLog
objects []*match.Object
start = (p.Pn - 1) * p.Ps
end = start + p.Ps - 1
)
// get from cache.
if rs, count, err = s.dao.ObjectsCache(c, p.Sid, start, end); err != nil || len(rs) == 0 {
if objects, err = s.dao.ObjectsUnStart(c, p.Sid); err != nil {
log.Error("s.dao.ObjectsUnStart id(%d) error(%v)", p.Sid, err)
return
}
count = len(objects)
if count == 0 || count < start {
rs = _emptyObjects
return
}
s.cache.Do(c, func(c context.Context) {
s.dao.SetObjectsCache(c, p.Sid, objects, count)
})
if count > end+1 {
rs = objects[start : end+1]
} else {
rs = objects[start:]
}
}
if mid > 0 {
if userGuess, err = s.ListGuess(c, p.Sid, mid); err != nil {
log.Error("s.ListGuess(%d,%d) error(%v)", p.Sid, mid, err)
err = nil
}
for _, rsObj := range rs {
for _, guess := range userGuess {
if rsObj.ID == guess.MOId {
rsObj.UserResult = guess.Result
break
}
}
}
}
return
}