go-common/app/interface/main/creative/service/newcomer/task.go
2019-04-22 18:49:16 +08:00

1036 lines
29 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package newcomer
import (
"context"
"reflect"
"sort"
"strings"
"time"
"fmt"
"go-common/app/interface/main/creative/model/newcomer"
accapi "go-common/app/service/main/account/api"
"go-common/library/ecode"
"go-common/library/log"
xtime "go-common/library/time"
)
const (
creatorMID int64 = 37090048 //创作中心哔哩哔哩号
msgPendantCode = "1_17_4"
msgPendantTitle = "恭喜你通关UP主任务-新手任务!"
msgPendantContent = "新手任务通关奖励“小试身手”头像挂件已发送至你的“个人中心-我的头像-我的挂件”中,快来查看和佩戴吧!更多任务奖励正在准备中,敬请期待哦~"
)
// UserTaskInfo def user task info
type UserTaskInfo struct {
Mid int64
UserTaskLevel int8
Follower int64
IsChange bool
}
// AppIndexNewcomer index newcomer
func (s *Service) AppIndexNewcomer(c context.Context, mid int64, plat string) (res *newcomer.AppIndexNewcomer, err error) {
if !s.c.TaskCondition.AppIndexSwitch {
return
}
var (
count int64
todoTasks []*newcomer.UserTask
)
res = &newcomer.AppIndexNewcomer{
H5URL: s.c.H5Page.Mission,
}
// check task bind
count, err = s.CheckUserTaskBind(c, mid)
if err != nil {
return
}
showTaskIDs := make([]int64, 0)
if count > 0 {
// already get tasks
res.TaskReceived = newcomer.BindTask
todoTasks, err = s.newc.UserTasksByMID(c, mid)
if err != nil {
log.Error("AppIndexNewcomer s.newc.UserTasks mid(%d)|error(%v)", mid, err)
return
}
// get at most 2 tasks
maxCnt := 0
for _, v := range todoTasks {
if maxCnt >= 2 {
break
}
showTaskIDs = append(showTaskIDs, v.TaskID)
maxCnt++
}
} else {
// not bind
res.TaskReceived = newcomer.NoBindTask
if len(s.TaskCache) < 2 {
return
}
for i := 0; i < 2; i++ {
t := s.TaskCache[i]
showTaskIDs = append(showTaskIDs, t.ID)
}
}
// fill app tasks struct
for _, v := range showTaskIDs {
if t, ok := s.TaskMapCache[v]; ok {
appt := &newcomer.AppTasks{
ID: t.ID,
Title: t.Title,
Type: t.Type,
}
// get redirect url
if _, ok := newcomer.TaskRedirectMap[plat]; ok {
if r, ook := newcomer.TaskRedirectMap[plat][t.TargetType]; ook {
appt.Label = r[0]
appt.Redirect = r[1]
}
}
res.AppTasks = append(res.AppTasks, appt)
}
}
if len(res.AppTasks) == 0 {
res = nil
}
return
}
// IndexNewcomer index newcomer
func (s *Service) IndexNewcomer(c context.Context, mid int64) (res *newcomer.IndexNewcomer, err error) {
res = &newcomer.IndexNewcomer{}
// check task bind
count, err := s.CheckUserTaskBind(c, mid)
if err != nil {
return
}
if count > 0 {
res.TaskReceived = newcomer.BindTask
} else {
res.TaskReceived = newcomer.NoBindTask
}
var (
upCount int // Number of submissions
viewCount int64 // Number of plays
)
// if archives == 0 && plays == 0 , means zero data
dt := time.Now().AddDate(0, 0, -1).Add(-12 * time.Hour).Format("20060102")
stat, err := s.data.UpStat(c, mid, dt)
if err != nil {
log.Error("IndexNewcomer s.data.UpStat mid(%d)|error(%v)", mid, err)
} else {
viewCount = stat.View
}
up, err := s.arc.UpCount(c, mid)
if err != nil {
log.Error("IndexNewcomer s.arc.UpCount mid(%d)|error(%v)", mid, err)
} else {
upCount = up
}
log.Info("IndexNewcomer mid(%d)|stat.view(%d)|upcount(%d)", mid, viewCount, upCount)
if upCount > 0 || viewCount > 0 {
log.Info("IndexNewcomer upCount>0||viewCount>0 mid(%d)|stat.view(%d)|upcount(%d)", mid, viewCount, upCount)
// check no receive reward
noReceiveCount := 0
noReceiveCount, CountErr := s.getNoReceiveRewardCount(c, mid)
if CountErr != nil {
log.Error("IndexNewcomer s.newc.noReceiveRewardCount mid(%d)|error(%v)", mid, err)
}
res.NoReceive = noReceiveCount
res.SubZero = false
} else {
res.SubZero = true
}
// add three task
tasks := make([]*newcomer.Task, 0)
if len(s.TaskCache) > 3 {
for i := 0; i < 3; i++ {
tasks = append(tasks, s.TaskCache[i])
}
res.Tasks = tasks
} else {
log.Error("IndexNewcomer s.newc len(s.TaskCache)<3 mid(%d)|error(%v)", mid, err)
}
return
}
// getNoReceiveRewardCount get no receive reward count
func (s *Service) getNoReceiveRewardCount(c context.Context, mid int64) (count int, err error) {
userTasks, err := s.newc.UserTasks(c, mid)
if err != nil {
log.Error("getNoReceiveRewardCount s.newc.UserTasks mid(%d)|error(%v)", mid, err)
return
}
tasks := s.getTasksInfoByType(userTasks, newcomer.DefualtTaskType)
if len(tasks) == 0 {
return
}
var (
taskGroupMap map[int64][]*newcomer.Task
taskTypeMap map[int8][]*newcomer.Task
availableCount int
receivedCount int
groupIDs []int64
giftIDs []int64
)
// group by groupID & taskType
taskGroupMap, taskTypeMap = s.groupByTasks(tasks)
groupIDs = make([]int64, 0, len(taskGroupMap))
for k, v := range taskGroupMap {
if _, ok := s.TaskGroupRewardMapCache[k]; ok {
if s.getTaskCompleteCount(v) == len(v) {
availableCount++
}
groupIDs = append(groupIDs, k)
}
}
giftIDs = make([]int64, 0, len(taskTypeMap))
for k, v := range taskTypeMap {
if _, ok := s.GiftRewardMapCache[k]; ok {
if s.getTaskCompleteCount(v) == len(v) {
availableCount++
}
giftIDs = append(giftIDs, int64(k))
}
}
r1, err := s.newc.BaseRewardCount(c, mid, groupIDs) // 基础奖励 已领取个数
if err != nil {
log.Error("getNoReceiveRewardCount s.newc.BaseRewardCount mid(%v)|error(%v)", mid, err)
return
}
r2, err := s.newc.GiftRewardCount(c, mid, giftIDs) // 礼包奖励 已领取个数
if err != nil {
log.Error("getNoReceiveRewardCount s.newc.GiftRewardCount mid(%v)|error(%v)", mid, err)
return
}
receivedCount = int(r1 + r2)
// 可领取未领取的奖励 = 可领取 - 已领取
count = availableCount - receivedCount
if count < 0 {
count = 0
}
log.Info("getNoReceiveRewardCount mid(%d)|availableCount(%d)|receivedCount(%d)|count(%d)", mid, availableCount, receivedCount, count)
return
}
// getUserTaskInfo determine the userTaskLevel
func (s *Service) getUserTaskInfo(c context.Context, mid int64, tasks []*newcomer.Task) (u *UserTaskInfo, err error) {
u = &UserTaskInfo{
Mid: mid,
UserTaskLevel: newcomer.UserTaskLevel01,
IsChange: false,
}
var (
count int // Number of unfinished novice tasks
follower int64
profileStat *accapi.ProfileStatReply
taskTypeMap map[int8][]*newcomer.Task
taskMap map[int64]*newcomer.Task
)
// whether the advanced task is hidden
if s.isHiddenTaskType(newcomer.AdvancedTaskType) {
u.UserTaskLevel = newcomer.UserTaskLevel01
return
}
taskMap = make(map[int64]*newcomer.Task)
taskTypeMap = make(map[int8][]*newcomer.Task)
for _, task := range tasks {
if task == nil {
continue
}
t, ok := s.TaskMapCache[task.ID]
if !ok {
continue
}
tp := *t
tp.CompleteSate = task.CompleteSate
taskTypeMap[tp.Type] = append(taskTypeMap[tp.Type], &tp)
taskMap[tp.ID] = &tp
}
// If the user already has an advanced task, return UserTaskLevel02
if _, ok := taskTypeMap[newcomer.AdvancedTaskType]; ok {
u.UserTaskLevel = newcomer.UserTaskLevel02
return
}
// Calculate whether the novice task is not fully completed (compare with cache)
newcomerTasks := s.getTasksByType(newcomer.NewcomerTaskType)
if len(newcomerTasks) == 0 {
return
}
count = len(newcomerTasks)
for _, t := range newcomerTasks {
if task, ok := taskMap[t.ID]; ok {
if task.CompleteSate == newcomer.TaskCompleted {
count--
}
}
}
// judge fans count
profileStat, profileErr := s.acc.ProfileWithStat(c, mid)
if profileStat == nil || profileErr != nil {
log.Error("genUserTaskInfo s.acc.ProfileWithStat mid(%d)|error(%v)", mid, err)
follower = 0
} else {
follower = profileStat.Follower
}
//Number of unfinished tasks || fans >=100
if count == 0 || follower >= s.c.TaskCondition.Fans {
// insert advancedTask
tasks = s.TaskTypeMapCache[newcomer.AdvancedTaskType]
if len(tasks) == 0 {
log.Warn("genUserTaskInfo no taskType==newcomer.AdvancedTaskType mid(%d)", mid)
return
}
args, placeStr := genBatchParamsBindTasks(tasks, mid)
_, err = s.newc.BindTasks(c, mid, placeStr, args)
if err != nil {
log.Error("genUserTaskInfo s.newc.BindTasks mid(%d)|error(%v)", mid, err)
return
}
u.UserTaskLevel = newcomer.UserTaskLevel02
u.IsChange = true // user level changed
s.putCheckTaskState(mid) // add to checkTaskQueue
}
return
}
//RewardReceive insert reward receive records.
func (s *Service) RewardReceive(c context.Context, mid int64, rid int64, ty int8, ip string) (res string, err error) {
var (
rewardIDs []int64
rewards []*newcomer.Reward
lockSuccess bool
)
// check completed
err = s.isRewardComplete(c, mid, rid, ty)
if err != nil {
return
}
// prevent concurrent collection
key := s.getReceiveKey(rid, ty, mid)
if lockSuccess, err = s.newc.Lock(c, key, 1000); !lockSuccess || err != nil {
if err == nil {
log.Info("RewardReceive s.newc.Lock mid(%d)|rid(%d)|ty(%d)", mid, rid, ty)
res = s.c.TaskCondition.ReceiveMsg
return
}
log.Error("RewardReceive s.newc.Lock mid(%d)|rid(%d)|ty(%d)|error(%v)", mid, rid, ty, err)
}
// check received
err = s.isRewardReceived(c, mid, rid, ty)
if err != nil {
return
}
// get rewards
if ty == newcomer.RewardGiftType {
rewardIDs, err = s.newc.GiftRewards(c, int8(rid))
if err != nil {
log.Error("RewardReceive s.newc.GiftRewards mid(%d)|rewardID(%d)|ty(%d)|err(%v)", mid, rid, ty, err)
return
}
} else {
rewardIDs, err = s.newc.TaskGroupRewards(c, rid)
if err != nil {
log.Error("RewardReceive s.newc.TaskGroupRewards mid(%d)|rewardID(%d)|ty(%d)|err(%v)", mid, rid, ty, err)
return
}
}
if len(rewardIDs) == 0 {
err = ecode.RequestErr
return
}
rewards = make([]*newcomer.Reward, 0)
for _, v := range rewardIDs {
if r, ok := s.RewardMapCache[v]; ok {
rewards = append(rewards, r)
}
}
// get user info
profile, err := s.acc.Profile(c, mid, ip)
if err != nil || profile == nil {
log.Error("RewardReceive s.acc.Profile mid(%d)|rewardID(%d)|ty(%d)|err(%v)", mid, rid, ty, err)
return
}
// receive rewards
rrs := make([]*newcomer.RewardReceive2, 0)
for _, v := range rewards {
r := &newcomer.RewardReceive2{}
r.MID = mid
r.OID = rid
r.Type = ty
r.RewardID = v.ID
r.RewardType = v.Type
if v.IsActive == newcomer.RewardNeedActivate {
r.State = newcomer.RewardCanActivate
} else {
err = s.callBusiness(c, profile, v)
if err != nil {
log.Error("RewardReceive s.callBusiness mid(%d)|reward(%+v)|error(%v)", mid, v, err)
r.State = newcomer.RewardCanActivate
} else {
r.State = newcomer.RewardActivatedNotClick
}
}
rrs = append(rrs, r)
}
_, err = s.newc.RewardReceive2(c, mid, rrs)
if err != nil {
log.Error("RewardReceive s.newc.RewardReceive mid(%d)|rewardID(%d)|ty(%d)|err(%v)", mid, rid, ty, err)
s.newc.UnLock(c, key)
return
}
res = s.c.TaskCondition.ReceiveMsg
log.Info("RewardReceive success mid(%d)|rewardID(%d)|ty(%d)", mid, rid, ty)
return
}
// Determine if the reward can be collected
func (s *Service) isRewardComplete(c context.Context, mid int64, rid int64, ty int8) error {
tids := make([]int64, 0)
tasks := make([]*newcomer.Task, 0)
if ty == newcomer.RewardBaseType {
tasks = s.getTasksByGroupID(rid)
} else if ty == newcomer.RewardGiftType {
tasks = s.getTasksByType(int8(rid))
}
for _, t := range tasks {
if t == nil {
continue
}
tids = append(tids, t.ID)
}
if len(tids) == 0 {
log.Error("isRewardComplete len(tids) == 0 | mid(%d)", mid)
return ecode.CreativeNewcomerNotCompleteErr
}
count, err := s.newc.RewardCompleteState(c, mid, tids)
if err != nil {
log.Error("isRewardComplete s.newc.RewardCompleteState mid(%d)|rewardID(%d)|ty(%d)|err(%v)", mid, rid, ty, err)
return err
}
if count != 0 {
err = ecode.CreativeNewcomerNotCompleteErr
log.Error("isRewardComplete mission not completed mid(%d)|rewardID(%d)|ty(%d)|err(%v)", mid, rid, ty, err)
return err
}
return nil
}
// Determine whether to receive it repeatedly
func (s *Service) isRewardReceived(c context.Context, mid int64, rid int64, ty int8) error {
isReceived, err := s.newc.IsRewardReceived(c, mid, rid, ty)
if err != nil {
log.Error("isRewardReceived s.newc.IsGiftReceived mid(%d)|rewardID(%d)|ty(%d)|err(%v)", mid, rid, ty, err)
return err
}
if isReceived {
err = ecode.CreativeNewcomerRepeatRewardErr
log.Error("isRewardReceived receive multiple times mid(%d)|rewardID(%d)|ty(%d)|err(%v)", mid, rid, ty, err)
return err
}
return nil
}
// Calling the business side interface
func (s *Service) callBusiness(c context.Context, profile *accapi.Profile, v *newcomer.Reward) (err error) {
switch v.Type {
case newcomer.Bcoin: //B币券
err = s.newc.BCoin(c, profile.Mid, v.PriceID, int64(v.PrizeUnit))
case newcomer.MemberBuy: //会员购
err = s.newc.Mall(c, profile.Mid, v.PriceID, profile.Name)
case newcomer.IncentivePlan: //激励计划
err = s.SendRewardReceiveLog(c, profile.Mid)
case newcomer.BigMember: //大会员服务
err = s.newc.BigMemberCoupon(c, profile.Mid, v.PriceID)
case newcomer.PersonalCenter: //个人中心
err = s.newc.Pendant(c, profile.Mid, v.PriceID, int64(v.Expire))
if err != nil {
return
}
//发送消息通知
if e := s.newc.SendNotify(c, []int64{profile.Mid}, msgPendantCode, msgPendantTitle, msgPendantContent); e != nil {
log.Error("callBusiness s.newc.SendNotify mid(%d)|err(%v)", profile.Mid, err)
}
}
return
}
//RewardActivate insert reward receive records.
func (s *Service) RewardActivate(c context.Context, mid, id int64, ip string) (res int64, err error) {
r, err := s.newc.RewardReceiveByID(c, mid, id)
if err != nil {
log.Error("RewardActivate s.newc.RewardIDByReceiveID mid(%d)|receiveID(%d)|err(%v)", mid, id, err)
return
}
// check repeat collection
if r.State != newcomer.RewardCanActivate {
err = ecode.CreativeNewcomerRepeatRewardErr
log.Error("RewardActivate check repeat collection mid(%d)|receiveID(%d)|state(%d)|err(%v)", mid, id, r.State, err)
return
}
// check expire
reward, ok := s.RewardMapCache[r.RewardID]
if !ok || reward == nil {
err = ecode.RequestErr
log.Error("RewardActivate check expire mid(%d)|receiveID(%d)|rewardID(%d)|err(%v)", mid, id, r.RewardID, err)
return
}
var expireTime int64
if r.RewardType == newcomer.Bcoin { //奖品到期时间
expireTime = reward.CTime.Time().Unix() + int64(reward.Expire*24*3600) //B币券显示截止时间
} else {
expireTime = r.ReceiveTime.Time().Unix() + int64(reward.Expire*24*3600)
}
if (time.Now().Unix() - expireTime) > 0 {
err = ecode.CreativeNewcomerReceiveExpireErr
log.Error("RewardActivate check expire mid(%d)|receiveID(%d)|rewardID(%d)|err(%v)", mid, id, r.RewardID, err)
return
}
// get new receive record
nr, err := s.newc.RewardReceiveByOldInfo(c, r)
if err != nil || nr == nil {
log.Error("RewardActivate s.newc.RewardReceiveByOldInfo mid(%d)|receive(%+v)|error(%v)", mid, r, err)
return
}
// prevent concurrent collection
var lockSuccess bool
key := s.getActivateKey(mid, id)
if lockSuccess, err = s.newc.Lock(c, key, 1000); !lockSuccess || err != nil {
if err == nil {
log.Info("RewardActivate s.newc.Lock mid(%d)|id(%d)", mid, id)
res = 0
return
}
log.Error("RewardActivate s.newc.Lock mid(%d)|id(%d)|error(%v)", mid, id, err)
}
profile, err := s.acc.Profile(c, mid, ip)
if err != nil || profile == nil {
log.Error("RewardActivate s.acc.Profile mid(%d)|receiveID(%d)|rewardID(%d)|err(%v)", mid, id, r.RewardID, err)
return
}
if err = s.callBusiness(c, profile, reward); err != nil {
log.Error("RewardActivate callBusiness mid(%d)|receiveID(%d)|rewardID(%d)|err(%v)", mid, id, r.RewardID, err)
return
}
res, err = s.newc.RewardActivate2(c, mid, id, nr.ID)
if err != nil {
log.Error("s.newc.RewardActivate mid(%d)|id(%d)|err(%v)", mid, id, err)
s.newc.UnLock(c, key)
return
}
log.Info("RewardActivate success mid(%d)|receiveID(%d)", mid, id)
return
}
//RewardReceives get reward receive records.
func (s *Service) RewardReceives(c context.Context, mid int64) (res []*newcomer.RewardReceiveGroup, err error) {
var items map[int8][]*newcomer.RewardReceive
items, err = s.newc.RewardReceives(c, mid)
if err != nil {
log.Error("s.newc.RewardReceives mid(%d)|err(%v)", mid, err)
return
}
if len(items) == 0 {
log.Error("s.newc.RewardReceives len(items) == 0")
return
}
keys := reflect.ValueOf(items).MapKeys()
pids := make([]int64, 0, len(keys)) //存储当前奖励 类型对应的 分类id
for _, v := range keys {
if k, ok := v.Interface().(int8); ok {
if pid, ook := s.RewardTyPIDMapCache[k]; ook {
pids = append(pids, pid)
}
}
}
sort.Slice(pids, func(i, j int) bool { //按奖励 类型对应id升序
return pids[i] < pids[j]
})
rkTypes := make([]int8, 0, len(keys)) //存储按照 奖励分类添加顺序排列的 奖励类型
for _, pid := range pids {
if ty, ok := s.RewardPIDTyMapCache[pid]; ok {
rkTypes = append(rkTypes, ty)
}
}
log.Info("RewardReceives mid(%d)|pids(%+v)|rkTypes(%+v)", mid, pids, rkTypes)
res = make([]*newcomer.RewardReceiveGroup, 0)
for _, k := range rkTypes {
item, ok := items[k]
if !ok || len(item) == 0 {
log.Error("RewardReceives items[k] k(%v) item(%+v) ok(%v)", k, item, ok)
return
}
pid, ok := s.RewardTyPIDMapCache[k]
if !ok || pid == 0 {
log.Error("RewardReceives s.RewardTyPIDMapCache[k] pid(%v) ok(%v)", pid, ok)
return
}
pr, ok := s.RewardMapCache[pid]
if !ok || pr == nil { //获取奖励类别名称和logo
log.Error("RewardReceives s.RewardMapCache[pid] pid(%d) pr(%+v) ok3(%v)", pid, pr, ok)
return
}
s0 := make([]*newcomer.RewardReceive, 0, len(item))
s1 := make([]*newcomer.RewardReceive, 0, len(item))
s2 := make([]*newcomer.RewardReceive, 0, len(item))
for _, v := range item {
r, ok := s.RewardMapCache[v.RewardID]
if !ok || r == nil {
log.Error("RewardReceives s.RewardMapCache[v.RewardID] v.RewardID(%v) r(%+v) ok(%v)", v.RewardID, r, ok)
return
}
v.RewardName = r.Name //获取奖品名称
var expireTime int64
if v.RewardType == newcomer.Bcoin { //奖品到期时间
expireTime = r.CTime.Time().Unix() + int64(r.Expire*24*3600)
v.ExpireTime = xtime.Time(expireTime) //B币券显示截止时间
} else {
expireTime = v.ReceiveTime.Time().Unix() + int64(r.Expire*24*3600)
v.ExpireTime = xtime.Time(expireTime)
}
// set RewardExpireNotClick state
if (time.Now().Unix() - expireTime) > 0 {
v.State = newcomer.RewardExpireNotClick
}
switch v.State { //按照0-可激活 >1-已激活不可点击>2-已过期不可点击 优先级展示
case newcomer.RewardCanActivate:
s0 = append(s0, v)
case newcomer.RewardActivatedNotClick:
s1 = append(s1, v)
case newcomer.RewardExpireNotClick:
s2 = append(s2, v)
}
}
r := &newcomer.RewardReceiveGroup{
Count: len(item),
RewardType: pr.Type,
RewardTypeName: pr.Name,
RewardTypeLogo: pr.Logo,
Comment: pr.Comment,
Items: append(append(s0, s1...), s2...),
}
res = append(res, r)
}
return
}
// TaskBind user bind tasks
func (s *Service) TaskBind(c context.Context, mid int64) (res int64, err error) {
count, err := s.CheckUserTaskBind(c, mid)
if err != nil {
return
}
if count > 0 {
err = ecode.CreativeNewcomerReBindTaskErr
return
}
// Determining the number of fans owned by users
profileStat, err := s.acc.ProfileWithStat(c, mid)
if err != nil {
log.Error("TaskBind s.acc.ProfileWithStat mid(%d)|error(%v)", mid, err)
return
}
log.Info("TaskBind s.acc.ProfileWithStat mid(%d)|follower(%d)", mid, profileStat.Follower)
var tasks []*newcomer.Task
if profileStat.Follower >= s.c.TaskCondition.Fans {
tasks = s.TaskTypeMapCache[newcomer.DefualtTaskType]
} else {
tasks = s.TaskTypeMapCache[newcomer.NewcomerTaskType]
}
args, placeStr := genBatchParamsBindTasks(tasks, mid)
res, err = s.newc.BindTasks(c, mid, placeStr, args)
if err != nil {
log.Error("TaskBind s.newc.BindTasks mid(%v)|error(%v)", mid, err)
return
}
// sync check task status
s.syncCheckTaskStatus(c, mid, tasks)
return
}
// genBatchParamsBindTasks generate batch insert parameters
func genBatchParamsBindTasks(tasks []*newcomer.Task, mid int64) ([]interface{}, string) {
place := make([]string, 0)
args := make([]interface{}, 0)
for _, v := range tasks {
place = append(place, "(?, ?, ?, ?, ?)")
args = append(args, mid, v.ID, v.GroupID, v.Type, -1)
}
placeStr := strings.Join(place, ",")
return args, placeStr
}
//CheckUserTaskBind determine if the user has bound the task
func (s *Service) CheckUserTaskBind(c context.Context, mid int64) (count int64, err error) {
count, err = s.newc.UserTaskBind(c, mid)
if err != nil {
log.Error("CheckUserTaskBind s.newc.UserTaskBind mid(%v)|error(%v)", mid, err)
return
}
return
}
//TaskMakeup fix unfinish task state
func (s *Service) TaskMakeup(c context.Context, mid int64) (err error) {
tasks, err := s.newc.UserTasks(c, mid)
if err != nil {
log.Error("TaskMakeup s.newc.UserTasks mid(%d)|error(%v)", mid, err)
err = ecode.RequestErr
return
}
infoTasks := s.getTasksInfoByType(tasks, newcomer.DefualtTaskType)
ts := make([]*newcomer.Task, 0)
for _, v := range infoTasks {
if v == nil {
continue
}
if v.CompleteSate == newcomer.TaskIncomplete {
ts = append(ts, v)
}
}
s.syncCheckTaskStatus(c, mid, ts)
return
}
//TaskPubList to apply task list
func (s *Service) TaskPubList(c context.Context, mid int64) (res *newcomer.PubTaskList, err error) {
res = &newcomer.PubTaskList{}
tasks, err := s.newc.UserTasks(c, mid)
if err != nil {
log.Error("PubTaskList s.newc.UserTasks mid(%d)|error(%v)", mid, err)
return
}
if len(tasks) == 0 {
log.Warn("PubTaskList No binding task | mid(%d)", mid)
res.TaskReceived = newcomer.NoBindTask
return
}
res.TaskReceived = newcomer.BindTask
ts := s.getTasksInfoByType(tasks, newcomer.DefualtTaskType)
if len(ts) == 0 {
log.Error("PubTaskList no task | mid(%d)", mid)
return
}
for _, task := range ts {
if task == nil {
continue
}
tt := &newcomer.PubTask{
ID: task.ID,
Title: task.Title,
Desc: task.Desc,
Type: task.Type,
State: task.CompleteSate,
}
res.Tasks = append(res.Tasks, tt)
}
return
}
// TaskList for task detail
func (s *Service) TaskList(c context.Context, mid int64, ty int8) (res *newcomer.TaskRewardList, err error) {
var (
u *UserTaskInfo
tasks []*newcomer.Task
taskTypeMap = make(map[int8][]*newcomer.Task)
taskGroupMap = make(map[int64][]*newcomer.Task)
)
// get user tasks
userTasks, err := s.newc.UserTasks(c, mid)
if err != nil {
log.Error("TaskList s.newc.UserTasks mid(%d)|error(%v)", mid, err)
return
}
if len(userTasks) == 0 {
// return User did not receive the task
res = &newcomer.TaskRewardList{
TaskReceived: newcomer.NoBindTask,
TaskType: ty,
}
log.Warn("TaskList user did not receive the task mid(%d)", mid)
return
}
// get user info
u, err = s.getUserTaskInfo(c, mid, userTasks)
if err != nil {
return
}
// Judging according to the "user logic level", showing the task type
if ty == newcomer.DefualtTaskType {
ty = u.UserTaskLevel
} else if ty == newcomer.AdvancedTaskType {
if ty > u.UserTaskLevel {
log.Warn("TaskList user unlocked this task mid(%d)", mid)
// return User has not unlocked this type of task
res = &newcomer.TaskRewardList{
TaskReceived: newcomer.BindTask,
TaskType: ty,
}
return
}
}
// get tasks
tasks = s.getTasksInfoByType(userTasks, newcomer.DefualtTaskType)
if len(tasks) == 0 {
err = ecode.CreativeNewcomerNoTask
log.Error("TaskList s.GetTaskByType len(tasks) == 0")
return
}
// group by groupID & taskType
for _, t := range tasks {
if t == nil {
continue
}
if t.Type == ty {
taskGroupMap[t.GroupID] = append(taskGroupMap[t.GroupID], t)
}
taskTypeMap[t.Type] = append(taskTypeMap[t.Type], t)
}
// task_kind
taskKinds := s.getTaskKindsData(u, taskTypeMap)
// task_gift
taskGift, err := s.getTaskGiftData(c, mid, taskTypeMap, newcomer.FromWeb)
if err != nil {
return
}
// task_groups
tgs, err := s.getTaskGroupData(c, mid, taskGroupMap)
if err != nil {
return
}
res = &newcomer.TaskRewardList{
TaskReceived: newcomer.BindTask,
TaskType: ty,
TaskKinds: taskKinds,
TaskGroups: tgs,
TaskGift: taskGift,
}
return
}
// getTaskGroupData for get task_group data
func (s *Service) getTaskGroupData(c context.Context, mid int64, taskMap map[int64][]*newcomer.Task) (tgs []*newcomer.TaskRewardGroup, err error) {
if len(taskMap) == 0 {
return
}
tgs = make([]*newcomer.TaskRewardGroup, 0, len(taskMap))
ranks := make([]int64, 0, len(taskMap))
groups := make([]int64, 0, len(taskMap))
rankGroupMap := make(map[int64]int64)
// sort by groupID
for key := range taskMap {
taskGroup, ok := s.TaskGroupMapCache[key]
if !ok {
continue
}
ranks = append(ranks, taskGroup.Rank)
groups = append(groups, key)
rankGroupMap[taskGroup.Rank] = key
}
sort.Slice(ranks, func(i, j int) bool {
return ranks[i] < ranks[j]
})
// get TaskRewardGroup
for _, k := range ranks {
taskGroup, ok := taskMap[rankGroupMap[k]]
if !ok || len(taskGroup) == 0 {
log.Error("genTaskGroupData taskGroup not exist ID(%d)", rankGroupMap[k])
continue
}
rewardState := newcomer.RewardNotAvailable //奖励领取状态
total := len(taskGroup) // 任务组总数
complete := s.getTaskCompleteCount(taskGroup) // 完成的任务数量
if complete == total {
rewardState = newcomer.RewardAvailable
}
rewards := s.getRewardsByGroupID(rankGroupMap[k]) // 任务组对应的奖励
tg := &newcomer.TaskRewardGroup{
TaskType: taskGroup[0].Type,
Tasks: taskGroup,
Rewards: rewards,
GroupID: rankGroupMap[k],
RewardState: int8(rewardState),
Completed: int64(complete),
Total: int64(total),
}
tgs = append(tgs, tg)
}
// determine if the reward is received
rewardRecvGroup, err := s.newc.RewardReceivedGroup(c, mid, groups)
if err != nil {
log.Error("genTaskGroupData s.newc.RewardReceivedGroup mid(%d)|error(%v)", mid, err)
return
}
for _, v := range tgs {
for _, j := range rewardRecvGroup {
if v.GroupID == int64(j) {
v.RewardState = newcomer.RewardReceived
}
}
}
return
}
// getTaskGiftData for get task_gift data
func (s *Service) getTaskGiftData(c context.Context, mid int64, taskTypeMap map[int8][]*newcomer.Task, from int8) (taskGift []*newcomer.TaskGift, err error) {
if len(taskTypeMap) == 0 {
return
}
taskGift = make([]*newcomer.TaskGift, 0, len(taskTypeMap))
// get gifts by taskType
gifts := make(map[int8][]*newcomer.Reward)
for k := range taskTypeMap {
gifts[k] = s.getRewardsByTaskType(k)
}
for tType, giftRewards := range gifts {
giftState := newcomer.RewardAvailable
complete := s.getTaskCompleteCount(taskTypeMap[tType])
total := len(taskTypeMap[tType])
if complete != total {
if from == newcomer.FromWeb {
giftState = newcomer.RewardNotAvailable
} else if from == newcomer.FromH5 {
giftState = newcomer.RewardUnlock
}
}
// judge the gift is received
isGiftReceived, err := s.newc.IsRewardReceived(c, mid, int64(tType), newcomer.RewardGiftType)
if err != nil {
log.Error("genTaskGiftData s.newc.IsGiftReceived mid(%d)|error(%v)", mid, err)
continue
}
if isGiftReceived {
giftState = newcomer.RewardReceived
}
tg := &newcomer.TaskGift{
State: int8(giftState),
Type: tType,
Rewards: giftRewards,
}
taskGift = append(taskGift, tg)
}
return
}
// getTaskKindsData for get task_kinds data
func (s *Service) getTaskKindsData(u *UserTaskInfo, taskTypeMap map[int8][]*newcomer.Task) (taskKinds []*newcomer.TaskKind) {
taskKinds = make([]*newcomer.TaskKind, 0, len(taskTypeMap))
for tType, tasks := range taskTypeMap {
complete := s.getTaskCompleteCount(tasks) // 完成数量
total := len(tasks) // 总数
state := newcomer.RewardNotAvailable // 完成状态
if complete == len(tasks) {
state = newcomer.RewardAvailable
}
kind := &newcomer.TaskKind{
Type: tType,
Completed: int64(complete),
Total: int64(total),
State: int8(state),
}
// determine the unlock type by user_task level
switch tType {
case newcomer.NewcomerTaskType:
taskKinds = append(taskKinds, kind)
case newcomer.AdvancedTaskType:
if u.UserTaskLevel == newcomer.UserTaskLevel01 {
kind.State = newcomer.RewardUnlock
}
taskKinds = append(taskKinds, kind)
}
}
return
}
// getTaskCompleteCount get tasks complete count
func (s *Service) getTaskCompleteCount(task []*newcomer.Task) int {
complete := 0
for _, t := range task {
if t == nil {
continue
}
if t.CompleteSate == newcomer.TaskCompleted {
complete++
}
}
return complete
}
// groupByTasks group by groupID & taskType
func (s *Service) groupByTasks(tasks []*newcomer.Task) (taskGroupMap map[int64][]*newcomer.Task, taskTypeMap map[int8][]*newcomer.Task) {
taskGroupMap = make(map[int64][]*newcomer.Task)
taskTypeMap = make(map[int8][]*newcomer.Task)
for _, t := range tasks {
if t == nil {
continue
}
taskGroupMap[t.GroupID] = append(taskGroupMap[t.GroupID], t)
taskTypeMap[t.Type] = append(taskTypeMap[t.Type], t)
}
return
}
// getReceiveKey get receive redis key
func (s *Service) getReceiveKey(oid int64, ty int8, mid int64) string {
return fmt.Sprintf("%d_%d_%d", oid, ty, mid)
}
// getActivateKey get active key
func (s *Service) getActivateKey(mid int64, id int64) string {
return fmt.Sprintf("%d_%d", mid, id)
}