You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
302 lines
8.5 KiB
302 lines
8.5 KiB
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 |
|
}
|
|
|