go-common/app/interface/main/esports/service/match_active.go

538 lines
14 KiB
Go
Raw Normal View History

2019-04-22 10:49:16 +00:00
package service
import (
"context"
"time"
"go-common/app/interface/main/esports/model"
arcmdl "go-common/app/service/main/archive/api"
"go-common/library/ecode"
"go-common/library/log"
"go-common/library/sync/errgroup"
"go-common/library/xstr"
)
var (
_emptActDetail = make([]*model.ActiveDetail, 0)
_emptActModule = make([]*model.Module, 0)
_emptActVideos = make([]*arcmdl.Arc, 0)
_emptTreeList = make([][]*model.TreeList, 0)
)
//ArcsInfo archive info
func (s *Service) ArcsInfo(c context.Context, aids []int64) (arc []*arcmdl.Arc, err error) {
var (
arcsReply *arcmdl.ArcsReply
res map[int64]*arcmdl.Arc
)
if arcsReply, err = s.arcClient.Arcs(c, &arcmdl.ArcsRequest{Aids: aids}); err != nil {
log.Error("s.arcClient.Arcs(%v) error(%v)", aids, err)
return
}
if arcsReply == nil {
return
}
res = make(map[int64]*arcmdl.Arc)
for k, v := range arcsReply.Arcs {
if v != nil && v.IsNormal() {
res[k] = v
}
}
for _, aid := range aids {
if v, ok := res[aid]; ok {
arc = append(arc, v)
}
}
return
}
// ActModules matchs active videos
func (s *Service) ActModules(c context.Context, mmid int64) (res []*arcmdl.Arc, err error) {
var (
mModule *model.Module
aids []int64
)
if res, err = s.dao.GetActModuleCache(c, mmid); err != nil || res == nil {
if mModule, err = s.dao.Module(c, mmid); err != nil {
return
}
if mModule == nil {
err = ecode.EsportsActVideoNotExist
return
}
if aids, err = xstr.SplitInts(mModule.Oids); err != nil {
return
}
if res, err = s.ArcsInfo(c, aids); err != nil {
return
}
if res == nil {
res = _emptActVideos
return
}
s.cache.Do(c, func(c context.Context) {
s.dao.AddActModuleCache(c, mmid, res)
})
}
return
}
//MatchAct match act
func (s *Service) MatchAct(c context.Context, aid int64) (act *model.Active, err error) {
if act, err = s.dao.GetMActCache(c, aid); err != nil || act == nil {
if act, err = s.dao.Active(c, aid); err != nil {
log.Error("s.dao.Active error(%v)", err)
return
}
if act != nil {
s.cache.Do(c, func(c context.Context) {
s.dao.AddMActCache(c, aid, act)
})
}
}
return
}
// ActPage matchs active page info
func (s *Service) ActPage(c context.Context, aid int64) (res *model.ActivePage, err error) {
var (
act *model.Active
modules []*model.Module
aids []int64
actDetail []*model.ActiveDetail
videos []*arcmdl.Arc
moduleErr, actDetailError, actError error
mapSeasons map[int64]*model.Season
)
if res, err = s.dao.GetActPageCache(c, aid); err != nil || res == nil {
res = &model.ActivePage{}
group, errCtx := errgroup.WithContext(c)
group.Go(func() error {
if act, actError = s.MatchAct(errCtx, aid); actError != nil {
log.Error("s.dao.Active error(%v)", moduleErr)
}
return actError
})
group.Go(func() error {
if modules, moduleErr = s.dao.Modules(errCtx, aid); moduleErr != nil {
log.Error("s.dao.Modules error(%v)", moduleErr)
return nil
}
if len(modules) > 0 && modules[0].Oids != "" {
if aids, moduleErr = xstr.SplitInts(modules[0].Oids); moduleErr != nil {
log.Error("s.ActPage.SplitInts oids error(%v) error(%v)", modules[0].Oids, moduleErr)
return nil
}
if videos, moduleErr = s.ArcsInfo(c, aids); moduleErr != nil {
log.Error("s.ActPage.ArcsInfo aids(%v) error(%v)", aids, moduleErr)
}
}
return nil
})
group.Go(func() error {
if actDetail, actDetailError = s.dao.ActDetail(errCtx, aid); actDetailError != nil {
log.Error("s.dao.ActDetail error(%v)", actDetailError)
}
return nil
})
err = group.Wait()
if err != nil {
return
}
if act == nil {
err = ecode.EsportsActNotExist
return
}
res.Active = act
if len(actDetail) == 0 {
res.ActiveDetail = _emptActDetail
} else {
res.ActiveDetail = actDetail
}
if len(modules) == 0 {
res.Modules = _emptActModule
} else {
res.Modules = modules
}
if len(videos) == 0 {
res.Videos = _emptActVideos
} else {
res.Videos = videos
}
if mapSeasons, err = s.dao.EpSeasons(c, []int64{act.Sid}); err != nil {
log.Error("s.dao.EpSeasons error(%v)", err)
err = nil
}
if season, ok := mapSeasons[act.Sid]; ok {
res.Season = season
} else {
res.Season = &model.Season{}
}
s.cache.Do(c, func(c context.Context) {
s.dao.AddActPageCache(c, aid, res)
})
}
return
}
//ContestCommon act match same deal logic
func (s *Service) ContestCommon(c context.Context, mid int64, p *model.ParamContest) (rs []*model.Contest, total int, err error) {
var (
cData, tmpRs []*model.Contest
contErr, teamErr, seasonErr error
teams, seasons []*model.Filter
cids []int64
dbContests map[int64]*model.Contest
)
group, errCtx := errgroup.WithContext(c)
group.Go(func() error {
if cData, total, contErr = s.dao.SearchContestQuery(errCtx, p); contErr != nil {
log.Error("s.dao.SearchContest error(%v)", contErr)
}
return contErr
})
group.Go(func() error {
if teams, teamErr = s.dao.Teams(errCtx); teamErr != nil {
log.Error("s.dao.Teams error(%v)", teamErr)
}
return nil
})
group.Go(func() error {
if seasons, seasonErr = s.dao.SeasonAll(errCtx); seasonErr != nil {
log.Error("s.dao.SeasonAll error %v", seasonErr)
}
return nil
})
err = group.Wait()
if err != nil {
return
}
if total == 0 || len(cData) == 0 {
rs = _emptContest
return
}
cids = s.contestIDs(cData)
if len(cids) > 0 {
if dbContests, err = s.dao.EpContests(c, cids); err != nil {
log.Error("s.dao.Contest error(%v)", err)
return
}
}
for _, c := range cData {
if contest, ok := dbContests[c.ID]; ok {
tmpRs = append(tmpRs, contest)
}
}
rs = s.ContestInfo(c, cids, tmpRs, teams, seasons, mid)
return
}
// ActTop act match top data
func (s *Service) ActTop(c context.Context, mid int64, param *model.ParamActTop) (res []*model.Contest, total int, err error) {
var (
act *model.Active
sids []int64
mapSeasons map[int64]*model.Season
sTime, eTime time.Time
season *model.Season
ok bool
)
isFirst := param.Pn == 1 && param.Sort == 0 && param.Stime == ""
if isFirst {
if res, total, err = s.dao.GetActTopCache(c, param.Aid, int64(param.Ps)); err != nil {
err = nil
} else if len(res) > 0 {
s.fmtContest(c, res, mid)
return
}
}
if act, err = s.MatchAct(c, param.Aid); err != nil {
log.Error("s.MatchAct error(%v)", err)
return
}
if act == nil || act.Sid <= 0 {
err = ecode.EsportsActNotExist
return
}
sids = []int64{act.Sid}
if mapSeasons, err = s.dao.EpSeasons(c, sids); err != nil {
log.Error("MatchAct s.dao.EpSeasons error(%v)", err)
return
}
season, ok = mapSeasons[act.Sid]
if !ok {
log.Error("s.ActTop sid(%d) not exists", act.Sid)
return
}
if param.Stime != "" {
sTime, _ = time.ParseInLocation("2006-01-02", param.Stime, time.Local)
if sTime.Unix() <= season.Stime {
param.Stime = time.Unix(season.Stime, 0).Format("2006-01-02 15:04:05")
} else {
sTime, _ = time.ParseInLocation("2006-01-02", param.Stime, time.Local)
param.Stime = time.Unix(sTime.Unix(), 0).Format("2006-01-02") + " 00:00:00"
}
} else {
param.Stime = time.Unix(season.Stime, 0).Format("2006-01-02 15:04:05")
}
if param.Etime != "" {
if season.Etime != 0 {
eTime, _ = time.ParseInLocation("2006-01-02", param.Etime, time.Local)
if eTime.Unix() >= season.Etime {
param.Etime = time.Unix(season.Etime, 0).Format("2006-01-02 15:04:05")
} else {
eTime, _ = time.ParseInLocation("2006-01-02", param.Etime, time.Local)
param.Etime = time.Unix(eTime.Unix(), 0).Format("2006-01-02") + " 23:59:59"
}
} else {
eTime, _ = time.ParseInLocation("2006-01-02", param.Etime, time.Local)
param.Etime = time.Unix(eTime.Unix(), 0).Format("2006-01-02") + " 23:59:59"
}
} else {
if season.Etime != 0 {
param.Etime = time.Unix(season.Etime, 0).Format("2006-01-02 15:04:05")
}
}
p := &model.ParamContest{
Mid: act.Mid,
Sids: []int64{act.Sid},
Sort: param.Sort,
Stime: param.Stime,
Etime: param.Etime,
Pn: param.Pn,
Ps: param.Ps,
}
if res, total, err = s.ContestCommon(c, mid, p); err != nil {
return
}
if len(res) == 0 {
res = _emptContest
return
}
if isFirst {
s.cache.Do(c, func(c context.Context) {
s.dao.AddActTopCache(c, param.Aid, int64(param.Ps), res, total)
})
}
return
}
// ActPoints act match point match
func (s *Service) ActPoints(c context.Context, mid int64, param *model.ParamActPoint) (res []*model.Contest, total int, err error) {
var (
act *model.Active
detail *model.ActiveDetail
)
isFirst := param.Pn == 1 && param.Sort == 0
if isFirst {
if res, total, err = s.dao.GetActPointsCache(c, param.Aid, param.MdID, int64(param.Ps)); err != nil {
err = nil
} else if len(res) > 0 {
s.fmtContest(c, res, mid)
return
}
}
if act, err = s.MatchAct(c, param.Aid); err != nil {
log.Error("s.dao.Active error(%v)", err)
return
}
if act == nil || act.Sid <= 0 {
err = ecode.EsportsActNotExist
return
}
p := &model.ParamContest{
Mid: act.Mid,
Sids: []int64{act.Sid},
Sort: param.Sort,
Pn: param.Pn,
Ps: param.Ps,
}
detail, err = s.dao.PActDetail(c, param.MdID)
if err != nil {
log.Error("s.dao.PActDetail error(%v)", err)
return
}
if detail != nil {
if detail.STime != 0 {
p.Stime = time.Unix(detail.STime, 0).Format("2006-01-02 15:04:05")
}
if detail.ETime != 0 {
p.Etime = time.Unix(detail.ETime, 0).Format("2006-01-02 15:04:05")
}
} else {
err = ecode.EsportsActPointNotExist
return
}
if res, total, err = s.ContestCommon(c, mid, p); err != nil {
return
}
if len(res) == 0 {
res = _emptContest
return
}
if isFirst {
s.cache.Do(c, func(c context.Context) {
s.dao.AddActPointsCache(c, param.Aid, param.MdID, int64(param.Ps), res, total)
})
}
return
}
//contestTeam get contest team
func (s *Service) contestTeam(c context.Context, contests map[int64]*model.Contest, teams map[int64]*model.Filter) (list []*model.ContestInfo, err error) {
for _, v := range contests {
contest := &model.ContestInfo{Contest: v}
if v.HomeID > 0 {
if team, ok := teams[v.HomeID]; ok {
contest.HomeName = team.Title
contest.HomeTeam = team
} else {
contest.HomeName = ""
contest.HomeTeam = struct{}{}
}
} else {
contest.HomeName = ""
contest.HomeTeam = struct{}{}
}
if v.AwayID > 0 {
if team, ok := teams[v.AwayID]; ok {
contest.AwayName = team.Title
contest.AwayTeam = team
} else {
contest.AwayName = ""
contest.AwayTeam = struct{}{}
}
} else {
contest.AwayName = ""
contest.AwayTeam = struct{}{}
}
if v.SuccessTeam > 0 {
if team, ok := teams[v.SuccessTeam]; ok {
contest.SuccessName = team.Title
} else {
contest.SuccessName = ""
}
} else {
contest.SuccessName = ""
}
contest.Season = struct{}{}
contest.SuccessTeaminfo = struct{}{}
list = append(list, contest)
}
return
}
//TeamMap get team and map team id to team
func (s *Service) TeamMap(ctx context.Context) (res map[int64]*model.Filter, err error) {
var (
teams []*model.Filter
)
if teams, err = s.dao.Teams(ctx); err != nil {
log.Error("LoadKnockoutTree s.dao.Teams error(%v)", err)
return
}
res = make(map[int64]*model.Filter)
for _, v := range teams {
res[v.ID] = v
}
return
}
// BuildKnockTree knock tree.
func (s *Service) BuildKnockTree(c context.Context) {
var (
trees []*model.Tree
sTree []*model.TreeList
mids []int64
contests map[int64]*model.Contest
cInfos []*model.ContestInfo
mapContests map[int64]*model.ContestInfo
treeList [][]*model.TreeList
err error
details []*model.ActiveDetail
teamMap map[int64]*model.Filter
)
if teamMap, err = s.TeamMap(c); err != nil {
log.Error("LoadKnockoutTree TeamMap error(%v)", err)
return
}
if details, err = s.dao.KDetails(c); err != nil {
log.Error("LoadKnockoutTree s.dao.KDetails error(%v)", err)
return
}
//build tree
for _, detail := range details {
if detail.Online == _downline {
//edit status; must add cache time
if s.dao.AddActKnockCacheTime(c, detail.ID); err != nil {
log.Error("LoadKnockoutTree s.dao.AddActKnockCacheTime error(%v)", err)
continue
}
} else {
treeList = _emptTreeList
sTree = make([]*model.TreeList, 0)
if trees, err = s.dao.Trees(c, detail.ID); err != nil {
log.Error("s.dao.Trees error(%v)", err)
return
}
for _, tree := range trees {
mids = append(mids, tree.Mid)
}
if len(mids) == 0 {
continue
} else {
count := len(mids)
if contests, err = s.dao.EpContests(c, mids); err != nil {
log.Error("s.dao.RawEpContests error(%v)", err)
continue
}
if cInfos, err = s.contestTeam(c, contests, teamMap); err != nil {
log.Error("s.contestTeam Error (%v)", err)
continue
}
mapContests = make(map[int64]*model.ContestInfo, count)
for _, info := range cInfos {
mapContests[info.ID] = info
}
for _, tree := range trees {
if tree.Pid == 0 {
if len(sTree) > 0 {
treeList = append(treeList, sTree)
}
sTree = nil
if cInfo, ok := mapContests[tree.Mid]; ok {
sTree = append(sTree, &model.TreeList{Tree: tree, ContestInfo: cInfo})
} else {
sTree = append(sTree, &model.TreeList{Tree: tree})
}
} else {
if cInfo, ok := mapContests[tree.Mid]; ok {
sTree = append(sTree, &model.TreeList{Tree: tree, ContestInfo: cInfo})
} else {
sTree = append(sTree, &model.TreeList{Tree: tree})
}
}
}
if len(sTree) > 0 {
treeList = append(treeList, sTree)
}
if len(treeList) > 0 {
go s.dao.AddActKnockoutCache(context.Background(), detail.ID, treeList)
}
}
}
}
}
// ActKnockout knockout tree
func (s *Service) ActKnockout(c context.Context, madID int64) (res [][]*model.TreeList, err error) {
if res, err = s.dao.GetActKnockoutCache(c, madID); err != nil {
return
}
if len(res) == 0 {
res = _emptTreeList
err = ecode.EsportsActKnockNotExist
}
return
}