You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

423 lines
8.5 KiB
Go

package campaignstat
import (
"joybuywork/internal/consts"
"joybuywork/internal/repository/dbcheck"
"joybuywork/internal/repository/finder"
"joybuywork/internal/repository/model"
"joybuywork/internal/repository/mtype"
"joybuywork/internal/utils/logic"
"joybuywork/internal/utils/verify"
pb "joybuywork/proto/go_proto/w_campaign_stat"
"joybuywork/proto/go_proto/workerr"
)
type TopTen struct {
logic.Logic
Req *pb.TopTenReq
Res *pb.TopTenRes
}
func (s *TopTen) Run() error {
return logic.Run(s)
}
func (s *TopTen) Exec() (err error) {
cpn, err := s.campaign()
if err != nil {
return
}
return s.rank(cpn)
}
// 活动数据
func (s *TopTen) campaign() (cpn *model.FissionCampaign, err error) {
cpn, err = finder.Campaign(s.Ctx, s.Req.GetCampaignHashId())
if err != nil {
err = s.BE().CacheError(err)
return
}
if cpn == nil || cpn.IsDel == mtype.Yes {
return nil, workerr.NotFound("campaign not found")
}
return
}
func (s *TopTen) rank(cpn *model.FissionCampaign) (err error) {
m := s.GetDao().FissionCampaignTicket
tickets, err := m.WithContext(s.Ctx).Where(m.CampaignID.Eq(cpn.ID), m.Open.Eq(mtype.Yes)).Find()
if err != nil {
err = s.BE().MysqlError(err)
return
}
for _, ticket := range tickets {
switch ticket.Mark {
case mtype.FissionCampaignTicketFixed:
err = s._invite(cpn)
if err != nil {
return
}
case mtype.FissionCampaignTicketCustom:
err = s._event(cpn)
if err != nil {
return
}
if s.Res.Invite == nil && verify.InArray[int64](cpn.FissionID, consts.IdReferral, consts.IdWinTogether) {
err = s._invite(cpn)
if err != nil {
return
}
}
}
}
switch cpn.FissionID {
case consts.IdGrow, consts.IdKeep:
err = s._grow(cpn)
if err != nil {
return
}
case consts.IdChop:
err = s._chop(cpn)
if err != nil {
return
}
case consts.IdSignIn:
err = s._sign(cpn)
if err != nil {
return
}
}
return
}
func (s *TopTen) _invite(cpn *model.FissionCampaign) (err error) {
m := s.GetDao().FissionUserStat
list, err := m.WithContext(s.Ctx).
Where(m.CampaignID.Eq(cpn.ID), m.EffectiveNum.Gt(0)).
Order(m.EffectiveNum.Desc(), m.DirectNum.Desc(), m.ID).
Limit(10).Find()
if err != nil {
err = s.BE().MysqlError(err)
return
}
if len(list) == 0 {
return
}
var ids = make([]int64, 0, len(list))
for _, v := range list {
ids = append(ids, v.UserID)
}
userIdMap, err := s._getUserId(cpn.ID, ids)
if err != nil {
return
}
var rank int32 = 1
s.Res.Invite = make([]*pb.TopTenRes_Invite, 0, len(list))
for _, v := range list {
s.Res.Invite = append(s.Res.Invite, &pb.TopTenRes_Invite{
Rank: rank,
UserId: userIdMap[v.UserID],
EffectNum: v.EffectiveNum,
InviteNum: v.DirectNum,
})
rank++
}
//裂变最深层级
furM := s.GetDao().FissionUser.SubTable(cpn.ID)
var maxDeep struct {
Deep int64 `json:"deep"`
}
err = furM.WithContext(s.Ctx).Select(furM.Deep.Max().As("deep")).Where(furM.CampaignID.Eq(cpn.ID)).Scan(&maxDeep)
if err = dbcheck.DbError(err); err != nil {
return s.BE().MysqlError(err)
}
s.Res.MaxLv = maxDeep.Deep
return
}
func (s *TopTen) _event(cpn *model.FissionCampaign) (err error) {
m := s.GetDao().FissionUserStat
list, err := m.WithContext(s.Ctx).
Where(m.CampaignID.Eq(cpn.ID), m.TargetNum.Gt(0)).
Order(m.TargetNum.Desc(), m.ID).
Limit(10).Find()
if err != nil {
err = s.BE().MysqlError(err)
return
}
if len(list) == 0 {
return
}
var ids = make([]int64, 0, len(list))
for _, v := range list {
ids = append(ids, v.UserID)
}
userIdMap, err := s._getUserId(cpn.ID, ids)
if err != nil {
return
}
userCondMap, err := s._getUserConds(cpn.ID, ids)
if err != nil {
return
}
var rank int32 = 1
s.Res.Event = make([]*pb.TopTenRes_Event, 0, len(list))
for _, v := range list {
s.Res.Event = append(s.Res.Event, &pb.TopTenRes_Event{
Rank: rank,
UserId: userIdMap[v.UserID],
Num: v.TargetNum,
Conds: userCondMap[v.UserID],
})
rank++
}
return
}
func (s *TopTen) _getUserId(campaignId int64, ids []int64) (data map[int64]string, err error) {
m := s.GetDao().FissionUser.SubTable(campaignId)
userList, err := m.WithContext(s.Ctx).Where(m.ID.In(ids...)).Find()
if err != nil {
err = s.BE().MysqlError(err)
return
}
data = make(map[int64]string, len(userList))
for _, v := range userList {
data[v.ID] = v.UserMark
}
return
}
func (s *TopTen) _getUserConds(cpnId int64, ids []int64) (data map[int64][]*pb.TopTenRes_Cond, err error) {
condM := s.GetDao().FissionCampaignCond
conds, err := condM.WithContext(s.Ctx).Where(condM.CampaignID.Eq(cpnId)).
Where(
condM.WithContext(s.Ctx).
Or(condM.IsDel.Eq(mtype.No)).
Or(condM.IsDel.Eq(mtype.Yes), condM.DelUse.Eq(mtype.Yes)),
).Find()
if err != nil {
err = s.BE().MysqlError(err)
return
}
m := s.GetDao().FissionUserCond
list, err := m.WithContext(s.Ctx).Where(m.UserID.In(ids...)).Find()
if err != nil {
err = s.BE().MysqlError(err)
return
}
var userCondMap = make(map[int64]map[int64]int64)
for _, v := range list {
if _, ok := userCondMap[v.UserID]; !ok {
userCondMap[v.UserID] = map[int64]int64{
v.CondID: v.Num,
}
} else {
userCondMap[v.UserID][v.CondID] = v.Num
}
}
data = make(map[int64][]*pb.TopTenRes_Cond, len(ids))
for _, userId := range ids {
for _, cond := range conds {
one := &pb.TopTenRes_Cond{
Desc: cond.Desc,
Num: 0,
}
if uc, ok := userCondMap[userId]; ok {
one.Num = uc[cond.ID]
}
data[userId] = append(data[userId], one)
}
}
return
}
func (s *TopTen) _grow(cpn *model.FissionCampaign) (err error) {
m := s.GetDao().FissionUserStat
list, err := m.WithContext(s.Ctx).
Where(m.CampaignID.Eq(cpn.ID), m.GrowRewardNum.Gt(0)).
Order(m.GrowRewardNum.Desc(), m.GrowNum.Desc(), m.ID).
Limit(10).Find()
if err != nil {
err = s.BE().MysqlError(err)
return
}
if len(list) == 0 {
return
}
var ids = make([]int64, 0, len(list))
for _, v := range list {
ids = append(ids, v.UserID)
}
userIdMap, err := s._getUserId(cpn.ID, ids)
if err != nil {
return
}
var rank int32 = 1
for _, v := range list {
s.Res.Grow = append(s.Res.Grow, &pb.TopTenRes_Grow{
Rank: rank,
UserId: userIdMap[v.UserID],
GrowNum: v.GrowNum,
GrowRewardNum: v.GrowRewardNum,
})
rank++
}
return
}
type chopHelp struct {
UserId int64 `json:"user_id"`
Mark string `json:"mark"`
Num int64 `json:"num"`
}
func (s *TopTen) _chop(cpn *model.FissionCampaign) (err error) {
m := s.GetDao().FissionUserStat
list, err := m.WithContext(s.Ctx).
Where(m.CampaignID.Eq(cpn.ID), m.HelpNum.Gt(0)).
Order(m.HelpNum.Desc(), m.ID).
Limit(10).Find()
if err != nil {
err = s.BE().MysqlError(err)
return
}
if len(list) == 0 {
return
}
var ids = make([]int64, 0, len(list))
for _, v := range list {
ids = append(ids, v.UserID)
}
var helps []*chopHelp
helpM := s.GetDao().FissionChopHelp
err = helpM.WithContext(s.Ctx).
Select(helpM.ID.Count().As("num"), helpM.UserID, helpM.Mark).
Where(helpM.CampaignID.Eq(cpn.ID), helpM.UserID.In(ids...)).
Group(helpM.UserID, helpM.Mark).
Scan(&helps)
if err != nil {
err = s.BE().MysqlError(err)
return
}
var helpMap = make(map[int64][]*chopHelp, len(list))
for _, v := range helps {
helpMap[v.UserId] = append(helpMap[v.UserId], v)
}
userIdMap, err := s._getUserId(cpn.ID, ids)
if err != nil {
return
}
var rank int32 = 1
for _, v := range list {
one := &pb.TopTenRes_Help{
Rank: rank,
UserId: userIdMap[v.UserID],
Num: v.HelpNum,
Detail: make([]*pb.TopTenRes_Detail, 0, len(helpMap[v.UserID])),
}
for _, help := range helpMap[v.UserID] {
one.Detail = append(one.Detail, &pb.TopTenRes_Detail{
Title: help.Mark,
Num: help.Num,
})
}
s.Res.Help = append(s.Res.Help, one)
rank++
}
return
}
func (s *TopTen) _sign(cpn *model.FissionCampaign) (err error) {
m := s.GetDao().FissionUserStat
list, err := m.WithContext(s.Ctx).
Where(m.CampaignID.Eq(cpn.ID), m.SignNum.Gt(0)).
Order(m.SignNum.Desc(), m.SignRewardNum.Desc(), m.ID).
Limit(10).Find()
if err != nil {
err = s.BE().MysqlError(err)
return
}
if len(list) == 0 {
return
}
var ids = make([]int64, 0, len(list))
for _, v := range list {
ids = append(ids, v.UserID)
}
userIdMap, err := s._getUserId(cpn.ID, ids)
if err != nil {
return
}
var rank int32 = 1
for _, v := range list {
s.Res.Sign = append(s.Res.Sign, &pb.TopTenRes_Sign{
Rank: rank,
UserId: userIdMap[v.UserID],
SignDay: v.SignNum,
SignRewardNum: v.SignRewardNum,
})
rank++
}
return
}