package call import ( "context" "fmt" "gorm.io/gorm/clause" "reflect" "server/common" "server/db" "server/pb" "server/util" "strings" "sync" "time" "github.com/liangdas/mqant/log" "gorm.io/gorm" ) func GetShareInfo(uid int) *common.ShareInfo { shareInfo := &common.ShareInfo{UID: uid} db.Mysql().Get(shareInfo) if shareInfo.ID <= 0 { info, _ := GetUserXInfo(uid, "channel_id") shareInfo.ChannelID = info.ChannelID shareInfo.Share = util.GetShareCode(uid) shareInfo.CreateTime = time.Now().Unix() shareInfo.Level = 0 db.Mysql().Create(shareInfo) } shareInfo.UpList = []int{shareInfo.UP1, shareInfo.UP2, shareInfo.UP3, shareInfo.UP4, shareInfo.UP5} betAmountTeam := shareInfo.BetAmountTeam downCount := shareInfo.Down1 + shareInfo.Down2 + shareInfo.Down3 + shareInfo.Down4 + shareInfo.Down5 shareConfig := GetConfigShareAll() for _, v := range shareConfig { if betAmountTeam >= int64(v.BetExp) && downCount >= int64(v.InviteExp) { shareInfo.Level = v.Level } } return shareInfo } func GetShareInfoByCode(code string) *common.ShareInfo { shareInfo := &common.ShareInfo{Share: code} db.Mysql().Get(shareInfo) return shareInfo } func GetShareLink(cid, uid int) string { shareInfo := GetShareInfo(uid) channel := GetChannelByID(cid) if channel == nil { return "" } u := "" if strings.Contains(channel.ShareURL, "?") { u = channel.ShareURL + fmt.Sprintf("&shareCode=%s", shareInfo.Share) } else { u = channel.ShareURL + fmt.Sprintf("?shareCode=%s", shareInfo.Share) } if !strings.Contains(u, "app") { u += fmt.Sprintf("&app=%d", common.GetShareChannel(cid)) } return u } // 分享查询 func ShareBind(share string, isOld bool, uid, cid int) { // 分享码为空 if share == "" { return } // 获取上一级分享信息 upInfo := &common.ShareInfo{Share: share} db.Mysql().Get(upInfo) if upInfo.ID > 0 { upInfo.UID = upInfo.UID UpdateShare(upInfo.UID, 4, 0, fmt.Sprintf("%d", uid)) shareInfo := GetShareInfo(upInfo.UID) shareCfg := GetConfigShare(shareInfo.Level, 0) if shareCfg.BeInviteRebate > 0 { // 被邀请获得 UpdateCurrencyPro(&common.UpdateCurrency{ CurrencyBalance: &common.CurrencyBalance{ UID: uid, Value: shareCfg.BeInviteRebate, ChannelID: cid, Type: common.CurrencyINR, Event: common.CurrencyEventShareBeInvite, NeedBet: GetConfigCurrencyResourceNeedBet(common.CurrencyResourceBonus, shareCfg.BeInviteRebate), }, }) } PushRed(upInfo.UID, pb.RedPointModule_RedPointShare, 1) } else { // 一级 upInfo = &common.ShareInfo{Share: share} } if upInfo.ID <= 0 { return } if !isOld { // 新账号创建分享信息 shareInfo := &common.ShareInfo{UID: uid, UP1: upInfo.UID, UP2: upInfo.UP1, UP3: upInfo.UP2, UP4: upInfo.UP3, UP5: upInfo.UP4, CreateTime: time.Now().Unix(), ChannelID: cid, Share: util.GetShareCode(uid)} db.Mysql().Create(shareInfo) } else { // 已有账号直接走更新 err := db.Mysql().Update(&common.ShareInfo{UID: uid}, map[string]interface{}{ "up1": upInfo.UID, "up2": upInfo.UP1, "up3": upInfo.UP2, "up4": upInfo.UP3, "up5": upInfo.UP4, }) if err != nil { log.Error("ShareBind err:%v", err) } } // 更新上级的下级数 ref := reflect.ValueOf(upInfo).Elem() // 上级的1-5级 for i := 0; i <= 4; i++ { var upUid int if i == 0 { upUid = upInfo.UID } else { upUid = int(ref.FieldByName(fmt.Sprintf("UP%d", i)).Int()) } if uid == 0 { continue } field := fmt.Sprintf("down%d", i+1) log.Debug("uid:%d, field:%s", upUid, field) updateErr := db.Mysql().C().Model(&common.ShareInfo{}).Where("uid = ?", upUid).Updates(map[string]interface{}{ field: gorm.Expr(fmt.Sprintf("`%s` + 1", field)), }).Error if updateErr != nil { log.Error("update share info err, %s", updateErr.Error()) } //db.Mysql().Update(&common.ShareInfo{UID: upUid}, map[string]interface{}{field:}) } // todo util.Go(func() { if upInfo.UID != 0 { // pdd摇奖次数 err := db.Mysql().C().Model(&common.PddDataNew{}).Where("uid = ?", upInfo.UID). Updates(map[string]interface{}{ "spin": gorm.Expr("spin + ?", 1), }).Error if err != nil { log.Error("update spin err, %s", err.Error()) return } PushRed(upInfo.UID, pb.RedPointModule_RedPointPdd, 1) // 裂变任务邀请人数 err = db.Mysql().C().Model(&common.ShareTaskNewData{}).Where("uid = ? and `type` = 2 and `status` = 0", upInfo.UID). Updates(map[string]interface{}{ "progress": gorm.Expr("progress + ?", 1), }).Error if err != nil { log.Error("update share invite task err, %s", err.Error()) return } // 邀请任务 CheckTask(Task{upInfo.UID, 1, []common.TaskType{common.TaskTypeInviter}}) } }) } //// 判断分享,发放有效用户奖励 //func CheckShare(r *common.RechargeOrder) { // shareInfo := GetShareInfo(r.UID) // // todo // if GetConfigShareSys() == nil { // return // } // reward := GetConfigShareSys().ShareReward // // 付费分享 // // CheckShareTask(shareInfo.UP1, 1, common.TaskTypePayShare) // // 发放奖励 // update := map[string]interface{}{ // "recharge_amount": gorm.Expr("recharge_amount + ?", r.Amount), // } // if shareInfo.BetAmount != -1 { // update["bet_amount"] = gorm.Expr("bet_amount + ?", r.Amount) // } // db.Mysql().Update(&common.ShareInfo{UID: r.UID}, update) // betAmount := shareInfo.BetAmount // if betAmount == -1 { // betAmount = 0 // } // if shareInfo.RechargeAmount+r.Amount < GetConfigShareSys().ShareRecharge { // return // } // if shareInfo.UP1 == 0 { // return // } // if shareInfo.BetAmount >= 0 { // db.Mysql().Update(&common.ShareInfo{UID: r.UID}, map[string]interface{}{ // "bet_amount": -1, // }) // update = map[string]interface{}{ // "invalid_invites": gorm.Expr("invalid_invites + 1"), // "invite_reward": gorm.Expr("invite_reward + ?", reward), // "available_reward": gorm.Expr("available_reward + ?", reward), // } // db.Mysql().Update(&common.ShareInfo{UID: shareInfo.UP1}, update) // ShareRecharge(r.UID, r.Amount+betAmount, 1) // IncreaseInviteCount(fmt.Sprintf("%v", shareInfo.UP1), 1, false) // } else { // ShareRecharge(r.UID, r.Amount+betAmount, 2) // } //} func ShareRecharge(uid int, amount int64, typ int) { shareInfo := &common.ShareInfo{UID: uid} db.Mysql().Get(shareInfo) if shareInfo.UP1 == 0 { return } ref := reflect.ValueOf(shareInfo).Elem() // 循环查询上级 for i := 1; i <= 5; i++ { upUid := int(ref.FieldByName(fmt.Sprintf("UP%d", i)).Int()) if upUid == 0 { break } tmpShareInfo := GetShareInfo(upUid) con := GetConfigShareByLevel(tmpShareInfo.Level) if con == nil { log.Error("unknown config share level:%v", i) continue } var per int64 for _, v := range con.SubRewardTiers { if v.Tier == i { per = v.Per } } // 发奖 reward := amount * per / 1000 if reward <= 0 { continue } db.Mysql().Update(&common.ShareInfo{UID: upUid}, map[string]interface{}{ "withdrawable": gorm.Expr("withdrawable + ?", reward), }) if i == 1 { // 上一级的充值任务 err := db.Mysql().C().Model(&common.ShareTaskNewData{}).Where("uid = ? and `type` = ? and `status` = 0", upUid, common.ShareTaskNewTypeRecharge).Updates(map[string]interface{}{ "progress": gorm.Expr("progress + ?", amount), }).Error if err != nil { log.Error("update share recharge task err, %s", err.Error()) } } db.Mysql().Create(&common.ShareDetail{ UID: uid, Type: typ, Up: upUid, RechargeAmount: amount, Reward: reward, Time: time.Now().Unix(), }) } } // 投注奖励结算 func ShareSettle(d *pb.InnerAfterSettle) { //shareInfo := &common.ShareInfo{UID: int(d.UID)} //db.Mysql().Get(shareInfo) //if shareInfo.UP1 == 0 { // return //} //db.Mysql().Update(&common.ShareInfo{UID: int(d.UID)}, map[string]interface{}{"bet": gorm.Expr("bet + ?", d.TotalBet)}) // //ref := reflect.ValueOf(shareInfo).Elem() //// 循环查询上级 //for i := 1; i <= 3; i++ { // uid := int(ref.FieldByName(fmt.Sprintf("UP%d", i)).Int()) // if uid == 0 { // break // } // con := GetConfigShareByLevel(i) // if con == nil { // log.Error("unknown config share level:%v", i) // continue // } // // 发奖 // reward := d.TotalBet * con.Per / 1000 // if reward <= 0 { // continue // } // db.Mysql().Update(&common.ShareInfo{UID: uid}, map[string]interface{}{ // "bet_reward": gorm.Expr("bet_reward + ?", reward), // "available_reward": gorm.Expr("available_reward + ?", reward), // }) //} } func GetConfigShareByLevel(level int) (result *common.ConfigShare) { for _, v := range configShare { if v.Level == level { return v } } return } func PackLevelSql(uid, level int) (sql string) { if level == 0 { sql = fmt.Sprintf("up1 = %d or up2 = %d or up3 = %d", uid, uid, uid) } else { sql = fmt.Sprintf("up%d = %d", level, uid) } return } // GetUserShares 查询玩家下级数量 func GetUserShares(uid, level int) int64 { return db.Mysql().Count(&common.ShareInfo{}, PackLevelSql(uid, level)) } // GetUserShareRecharges 查询玩家下级充值人数 func GetUserShareRecharges(uid, level int) (count int64) { sql := fmt.Sprintf(`SELECT count(*) as count from (SELECT uid from share_info WHERE %s)a INNER JOIN (SELECT uid from recharge_info WHERE total_recharge > 0)b on a.uid = b.uid`, PackLevelSql(uid, level)) err := db.Mysql().C().Raw(sql).Scan(&count).Error if err != nil { log.Error("err:%v", err) } return } // GetUserShareValidRecharges 查询玩家下级有效充值人数 func GetUserShareValidRecharges(uid, level int) (count int64) { sql := fmt.Sprintf(`SELECT count(*) as count from (SELECT uid from share_info WHERE %s)a INNER JOIN (SELECT uid from recharge_info WHERE total_recharge >= %d)b on a.uid = b.uid`, PackLevelSql(uid, level), GetConfigShareSys().ShareRecharge) err := db.Mysql().C().Raw(sql).Scan(&count).Error if err != nil { log.Error("err:%v", err) } return } // GetUserShareRechargeAmount 查询玩家下级充值总额 func GetUserShareRechargeAmount(uid, level int) (count int64) { sql := fmt.Sprintf(`SELECT sum(b.total_recharge) as count from (SELECT uid from share_info WHERE %s)a INNER JOIN (SELECT uid,total_recharge from recharge_info WHERE total_recharge > 0)b on a.uid = b.uid`, PackLevelSql(uid, level)) err := db.Mysql().C().Raw(sql).Scan(&count).Error if err != nil { log.Error("err:%v", err) } return } // GetActivityShareCode 根据actid获取share code func GetActivityShareCode(uid, actId int) (code string, err error) { now := time.Now() ret := make([]*common.ShareActivityCode, 0, 1) _, err = db.Mysql().QueryList(0, 1, fmt.Sprintf("uid = %d and activity_id = %d ", uid, actId), "id", &common.ShareActivityCode{}, &ret) if err != nil { log.Error("GetActivityShareCode err:%v", err) return } expireTime := util.GetZeroTime(now.AddDate(0, 0, 1)) if len(ret) == 0 { code = util.GetShareCode(-uid - actId) err = db.Mysql().Create(&common.ShareActivityCode{ UID: uid, ShareCode: code, ActivityId: actId, ExpireAt: expireTime.Unix(), CreateAt: now.Unix(), }) if err != nil { log.Error("GetActivityShareCode err:%v", err) return } } else { code = ret[0].ShareCode _, err = db.Mysql().UpdateRes(&common.ShareActivityCode{UID: uid, ActivityId: actId}, map[string]interface{}{ "expire_at": expireTime.Unix(), }) if err != nil { log.Error("GetActivityShareCode err:%v", err) } } return } // SendShareReward 发送分享奖励 func SendShareReward(channel, uid, actId int) { log.Info("SendShareReward channel:%v,uid:%v,actId:%d", channel, uid, actId) if common.ActivityIDFreeSpin == actId { freespin := GetUserFreeSpinData(uid) now := time.Now().Unix() if freespin.LastSpin == 0 && freespin.SpinNum == 0 { // 未参与活动 p, _ := GetUserXInfo(uid, "birth") data := &common.ActivityFreeSpinData{UID: uid, SpinNum: common.DefaultFreeSpinNum} if util.IsSameDayTimeStamp(now, p.Birth) { data.LastSpin = now } err := db.Mysql().Create(data) if err != nil { log.Error("SendShareReward uid:%v,err:%v", uid, err) } } else { _, err := db.Mysql().UpdateRes(&common.ActivityFreeSpinData{UID: uid}, map[string]interface{}{"last_spin": now, "spin_num": gorm.Expr("spin_num + ?", 1)}) if err != nil { log.Error("SendShareReward uid:%v,err:%v", uid, err) } } } else if common.ActivityIDSign == actId { // 判断今日参与签到 // 如果参与就再发送奖励,同时发送邮件 list := GetConfigActivitySign() data := &common.ActivitySignData{UID: uid} db.Mysql().Get(data) first := util.GetZeroTime(time.Unix(data.Time, 0)).Unix() today := util.GetZeroTime(time.Now()).Unix() day := int((today-first)/common.OneDay) + 1 log.Info("SendShareReward day:%v", day) // 给前两天 if day > 2 { return } sign := data.Sign for i := 0; i < day; i++ { if sign&1 == 1 && day == i+1 { // 发放当日奖励 for _, v := range list { if v.Day == day { reward := v.Reward log.Info("SendShareReward reward:%v", reward) UpdateCurrencyPro(&common.UpdateCurrency{ CurrencyBalance: &common.CurrencyBalance{ UID: uid, Type: common.CurrencyINR, ChannelID: channel, Value: reward, Event: common.CurrencyEventActivitySign, NeedBet: GetConfigCurrencyResourceNeedBet(common.CurrencyResourceBonus, reward), }, }) break } } break } sign >>= 1 } } } // WriteShareBalance 写入分享流水 func WriteShareBalance(b *common.ESShareBalance, shouldUpdate bool) { if b.Amount == 0 { return } now := time.Now() if (b.FriendNick == "" || b.Phone == "") && b.FriendUID > 0 { ret, _ := GetUserXInfo(b.FriendUID, "nick", "mobile") b.FriendNick = ret.Nick b.Phone = ret.Mobile } if b.RefererNick == "" { ret, _ := GetUserXInfo(b.RefererUID, "nick") b.RefererNick = ret.Nick } if b.Date == "" { b.Date = now.Format("20060102") } if b.Time == 0 { b.Time = now.Unix() } InsertToESGO(common.ESIndexShareBalance, b) if !shouldUpdate { return } // 先更新总收益 total := &common.ShareRewardData{} // totalSql := fmt.Sprintf("select * from share_reward_data where uid = %d and time = 0", b.RefererUID) db.Mysql().QueryBySql(fmt.Sprintf("select * from share_reward_data where uid = %d and time = 0", b.RefererUID), total) if total.ID == 0 { total = &common.ShareRewardData{} total.UID = b.RefererUID total.Date = "" total.Time = 0 total.SetReward(b.Event, b.Amount) db.Mysql().Create(total) } else { field := total.GetRewardName(b.Event) if field != "" { db.Mysql().UpdateW(&common.ShareRewardData{}, map[string]interface{}{ "total_reward": gorm.Expr("total_reward + ?", b.Amount), field: gorm.Expr(fmt.Sprintf("%s + %d", field, b.Amount))}, fmt.Sprintf("uid = %d and time = 0", b.RefererUID)) } } // 更新当天收益 t := util.GetZeroTime(now).Unix() today := &common.ShareRewardData{UID: b.RefererUID, Time: t} db.Mysql().Get(today) if today.ID == 0 { today = &common.ShareRewardData{UID: b.RefererUID, Time: t} today.Date = b.Date today.SetReward(b.Event, b.Amount) db.Mysql().Create(today) } else { field := today.GetRewardName(b.Event) if field != "" { db.Mysql().Update(&common.ShareRewardData{UID: b.RefererUID, Time: t}, map[string]interface{}{ "total_reward": gorm.Expr("total_reward + ?", b.Amount), field: gorm.Expr(fmt.Sprintf("%s + %d", field, b.Amount))}) } } // 更新分享者总奖励表 // one := &common.ShareTotalReward{RefererUID: b.RefererUID, FriendUID: b.FriendUID, Level: b.Level, Reward: b.Amount} // if !db.Mysql().Exist(one) { // one.Reward = b.Amount // db.Mysql().Create(one) // return // } // db.Mysql().Update(one, map[string]interface{}{"reward": gorm.Expr("reward + ?", b, b.Amount)}) // db.Mysql().UpsertMap(fmt.Sprintf("referer_uid = %v and friend_uid = %v", b.RefererUID, b.FriendUID), // one, map[string]interface{}{"reward": gorm.Expr("reward + ?", b.Amount)}) } // 计算排行榜 func CalShareRank(t int, ti int64) (list []*common.ShareRank) { data := []*OneRank{} switch t { case common.ShareRankTypeDaily: db.Mysql().QueryBySql(fmt.Sprintf("select uid as UID,total_reward as Reward from share_reward_data where time = %d ORDER BY Reward desc LIMIT %d", ti, common.ShareRankMaxNum), &data) case common.ShareRankTypeWeekly: db.Mysql().QueryBySql(fmt.Sprintf("select uid as UID,sum(total_reward) as Reward from share_reward_data where time>=%d and time<%d group by uid ORDER BY Reward desc LIMIT %d", ti, ti+7*common.OneDay, common.ShareRankMaxNum), &data) case common.ShareRankTypeMonthly: db.Mysql().QueryBySql(fmt.Sprintf("select uid as UID,sum(total_reward) as Reward from share_reward_data where time>=%d and time<%d group by uid ORDER BY Reward desc LIMIT %d", ti, util.GetLastDateOfMonth(time.Unix(ti, 0)).Unix()+common.OneDay, common.ShareRankMaxNum), &data) } for _, v := range data { one := &common.ShareRank{ UID: v.UID, Type: t, Time: ti, Level: GetShareInfo(v.UID).Level, Reward: v.Reward, } p, _ := GetUserXInfo(v.UID, "avatar", "nick") one.Avatar = p.Avatar one.Nick = p.Nick list = append(list, one) } return } func GetShareRank(t int, ti int64) (list []*common.ShareRank) { now := time.Now() switch t { case common.ShareRankTypeDaily: if util.GetZeroTime(now).Unix() == ti { // 查询今天 list = CalShareRank(t, ti) return } case common.ShareRankTypeWeekly: if util.GetWeekZeroTime(now).Unix() == ti { // 查询本周 list = CalShareRank(t, ti) return } case common.ShareRankTypeMonthly: if util.GetFirstDateOfMonth(now).Unix() == ti { // 查询本月 list = CalShareRank(t, ti) return } } db.Mysql().QueryList(0, common.ShareRankMaxNum, fmt.Sprintf("type = %d and time = %d", t, ti), "reward desc", &common.ShareRank{}, &list) return } type OneRank struct { UID int Reward int64 } func GetShareRewardData(uid, t int, ti int64) *common.ShareRank { data := &OneRank{} switch t { case common.ShareRankTypeDaily: db.Mysql().QueryBySql(fmt.Sprintf("select uid as UID,total_reward as Reward from share_reward_data where time = %d AND uid = %d", ti, uid), &data) case common.ShareRankTypeWeekly: db.Mysql().QueryBySql(fmt.Sprintf("select uid as UID,sum(total_reward) as Reward from share_reward_data where time>=%d and time<%d AND uid = %d", ti, ti+7*common.OneWeek, uid), data) case common.ShareRankTypeMonthly: db.Mysql().QueryBySql(fmt.Sprintf("select uid as UID,sum(total_reward) as Reward from share_reward_data where time>=%d and time<%d AND uid = %d", ti, util.GetLastDateOfMonth(time.Unix(ti, 0)).Unix()+common.OneDay, uid), &data) } one := &common.ShareRank{ UID: uid, Type: t, Time: ti, Level: GetShareInfo(uid).Level, Reward: data.Reward, } p, _ := GetUserXInfo(uid, "avatar", "nick") one.Avatar = p.Avatar one.Nick = p.Nick return one } func GetShareWithdrawHis(uid, page, num int) (list []*common.RechargeOrder, count int64) { count, _ = db.Mysql().QueryListW(page, num, "created_at desc", &common.RechargeOrder{UID: uid}, &list, "uid = ? and (event = ? or event = ?) and scene = ?", uid, common.CurrencyEventWithDraw, common.CurrencyEventShareWithdraw, common.ActivityIDShare) return } func ShareRankUserGet(page, pageSize int, rankAt time.Time, withCount bool) (rankUsers []common.ShareRankDataWithUser, count int64, err error) { if withCount { countQuery := db.Mysql().C(). Model(&common.ShareRankData{}). Where("rank_cycle = ? and rank_at = ?", 2, rankAt.Unix()) err = countQuery.Count(&count).Error if err != nil { log.Error("get rank user count err, %s", err.Error()) return } } err = db.Mysql().C().Table("share_rank_data as srd"). Select("srd.*, u.*"). Joins("left join users as u on srd.uid = u.id"). Where("srd.rank_cycle = ? and srd.rank_at = ?", 2, rankAt.Unix()). Order("srd.rank_value desc, srd.updated_at").Offset((page - 1) * pageSize).Limit(pageSize). Find(&rankUsers).Error if err != nil { log.Error("get rank user err, %s", err.Error()) return } return } var once sync.Once func ShareRankHandler() { once.Do(func() { util.Go(func() { for { now := time.Now() nextSettleAt := util.GetWeekZeroTime(now).AddDate(0, 0, 7).Add(30 * time.Minute) if now.After(nextSettleAt) { nextSettleAt = nextSettleAt.AddDate(0, 0, 7) } timer := time.NewTimer(nextSettleAt.Sub(now)) <-timer.C shareRankAward() nextSettleAt = util.GetWeekZeroTime(now).AddDate(0, 0, 7).Add(30 * time.Minute) log.Debug("next share rank at: %s", nextSettleAt.Format(time.DateTime)) timer.Reset(nextSettleAt.Sub(time.Now())) } }) }) } func shareRankAward() { now := time.Now() jackpot := ShareRankJackpotPreGet() lessJackpot := jackpot lastRankAt := util.GetWeekZeroTime(now).AddDate(0, 0, -7) shareRankAwards := GetConfigShareRankAwardMap() if shareRankAwards == nil { log.Error("share rank award is nil") return } var rankUsers []*common.ShareRankData err := db.Mysql().C().Model(&common.ShareRankData{}).Where("rank_at = ?", lastRankAt.Unix()).Order("rank_value desc, updated_at").Find(&rankUsers).Error if err != nil { log.Error("get share rank user err, %s", err.Error()) return } for index, rankUser := range rankUsers { var ( rank = index + 1 userAward int userAwardCount int64 ) award, ok := shareRankAwards[rank] if ok { userAward = award.AwardRate userAwardCount = jackpot * int64(userAward) / 10000 lessJackpot -= userAwardCount } if lessJackpot <= 0 { userAwardCount = 0 } updateValues := map[string]interface{}{ "user_award": userAward, "user_award_count": userAwardCount, "rank": rank, "updated_at": now.Unix(), } err = db.Mysql().C().Model(&common.ShareRankData{}).Where("id = ?", rankUser.ID).Updates(updateValues).Error if err != nil { log.Error("update share rank data err, %d:%+v %s", rankUser.ID, updateValues, err.Error()) continue } if userAwardCount == 0 { continue } _, err = UpdateCurrencyPro(&common.UpdateCurrency{ CurrencyBalance: &common.CurrencyBalance{ UID: rankUser.UID, Type: common.CurrencyINR, Value: userAwardCount, Event: common.CurrencyEventShareRankAward, NeedBet: GetConfigCurrencyResourceNeedBet(common.CurrencyResourceBonus, userAwardCount), }, }) if err != nil { log.Error("share rank award err, %s", err.Error()) } mail := common.Mail{ DraftID: "", Sender: "system", Receiver: rankUser.UID, Type: 1, Title: fmt.Sprintf("EARN RANKING(%s)", lastRankAt.Format("20060102")), Content: fmt.Sprintf("Well done! You ranked %dth on the invitation leaderboard and won a reward. Go claim it now!", rank), SendMethod: 1, Status: common.MailStatusNew, Time: now.Unix(), } err = db.Mysql().C().Model(&common.Mail{}).Create(&mail).Error if err != nil { log.Error("create mail err, %s, %+v", err.Error(), mail) } } preJackpotLessKey := getShareRankJackpotPreKey() + "|less" log.Debug("shareRankAward, %s, %d, less jackpot:%d", preJackpotLessKey, jackpot, lessJackpot) err = db.Redis().GetRedis().Set(context.Background(), preJackpotLessKey, lessJackpot, time.Hour*24*7*2).Err() if err != nil { log.Error("share rankAward, %s set less-jackpot err, %s", preJackpotLessKey, err.Error()) } if jackpot > 0 { _, _, _, jackpotKey := getShareRankJackpotKey() _, err = db.Redis().Incr(jackpotKey, lessJackpot) if err != nil { log.Error("incr less jackpot err, %s, %s:%d", err.Error(), jackpotKey, lessJackpot) } } } // updateType(1:下注,2:充值,3:任务,4:邀请人) func updateShareByUp(uid, upUid, uplevel, updateType int, updateValue int64, expand ...string) { shareInfo := GetShareInfo(upUid) shareCfgMap := GetConfigShareMap() shareCfg := shareCfgMap[shareInfo.Level] rewardTier, ok := shareCfg.SubRewardTiersMap[uplevel] now := time.Now() var awardCount int64 if !ok || rewardTier.Per == 0 { return } var shareReward *common.ShareReward updateValues := make(map[string]interface{}) switch updateType { case 1: // 下注返利 var winCount int64 if len(expand) > 0 { winCount = util.ToInt64(expand[0]) } if winCount < 0 { rewardCount := -winCount * rewardTier.Per / 100 shareReward = &common.ShareReward{ UID: upUid, UpLevel: uplevel, RewardType: updateType, RewardCount: rewardCount, RewardDesc: fmt.Sprintf("%d", uid), RewardAt: now.Unix(), } awardCount = rewardCount updateValues["reward"] = gorm.Expr("reward + ?", rewardCount) updateValues["withdrawable"] = gorm.Expr("withdrawable + ?", rewardCount) } betAmount := updateValue * rewardTier.Per / 100 updateValues["bet_amount_team"] = gorm.Expr("bet_amount_team + ?", betAmount) case 2: // 充值返利 rewardCount := updateValue * rewardTier.Per / 100 shareReward = &common.ShareReward{ UID: upUid, UpLevel: uplevel, RewardType: updateType, RewardCount: rewardCount, RewardDesc: fmt.Sprintf("%d", uid), RewardAt: now.Unix(), } awardCount = rewardCount updateValues["reward"] = gorm.Expr("reward + ?", rewardCount) updateValues["withdrawable"] = gorm.Expr("withdrawable + ?", rewardCount) } if shareReward != nil { err := db.Mysql().C().Create(&shareReward).Error if err != nil { log.Error("create up share reward err, %s", err.Error()) } } if len(updateValues) > 0 { err := db.Mysql().C().Model(&common.ShareInfo{}).Where("uid = ?", upUid).Updates(updateValues).Error if err != nil { log.Error("update up share info err, %s", err.Error()) } if _, ok = updateValues["reward"]; ok { // 更新排行榜 shareRankData := common.ShareRankData{ UID: shareInfo.UID, RankCycle: 2, RankAt: util.GetWeekZeroTime(now).Unix(), RankValue: awardCount, UpdatedAt: now.Unix(), } err = db.Mysql().C().Model(&common.ShareRankData{}).Clauses(clause.OnConflict{ Columns: []clause.Column{{Name: "rank_cycle"}, {Name: "rank_at"}, {Name: "uid"}}, DoUpdates: clause.Assignments(map[string]interface{}{ "rank_value": gorm.Expr("rank_value + ?", shareRankData.RankValue), "updated_at": shareRankData.UpdatedAt, }), }).Create(&shareRankData).Error if err != nil { log.Error("update up share rank data err, %s", err.Error()) } } } } // UpdateShare updateType(1:下注,2:充值,3:任务,4:邀请人,5:提现, 6:回滚) func UpdateShare(uid, updateType int, updateValue int64, expand ...string) (err error) { if updateType == 1 { // 直接更新下注奖池 if len(expand) > 0 && expand[0] == "isRobot" { return } _, _, expired, rankKey := getShareRankJackpotKey() _, err = db.Redis().Incr(rankKey, updateValue/100) if err != nil { log.Error("update rank jackpot err, %s:%s", rankKey, err.Error()) } db.Redis().Expire(rankKey, time.Duration(expired)*time.Second) } now := time.Now() shareInfo := GetShareInfo(uid) var shareReward *common.ShareReward updateValues := make(map[string]interface{}) var awardCount int64 var updateUp bool switch updateType { case 1: updateValues["bet_amount"] = gorm.Expr("bet_amount + ?", updateValue) updateValues["bet_amount_team"] = gorm.Expr("bet_amount_team + ?", updateValue) updateUp = true case 2: updateUp = true case 3: desc := expand[0] shareReward = &common.ShareReward{ UID: uid, RewardType: updateType, RewardCount: updateValue, RewardDesc: desc, RewardAt: now.Unix(), } awardCount = updateValue updateValues["reward"] = gorm.Expr("reward + ?", updateValue) updateValues["withdrawable"] = gorm.Expr("withdrawable + ?", updateValue) case 4: configMap := GetConfigShareMap() if config, ok := configMap[shareInfo.Level]; ok { amount := config.InviteRebate var desc string if len(expand) > 0 { desc = expand[0] } shareReward = &common.ShareReward{ UID: uid, RewardType: updateType, RewardCount: amount, RewardDesc: desc, RewardAt: now.Unix(), } awardCount = updateValue if awardCount == 0 { // 绑定的时候不关心奖励数 awardCount = amount updateValue = amount } updateValues["reward"] = gorm.Expr("reward + ?", amount) updateValues["withdrawable"] = gorm.Expr("withdrawable + ?", amount) } case 5: desc := expand[0] shareReward = &common.ShareReward{ UID: uid, RewardType: updateType, RewardCount: -updateValue, RewardDesc: desc, RewardAt: now.Unix(), } updateValues["withdrawable"] = gorm.Expr("withdrawable - ?", updateValue) case 6: desc := expand[0] shareReward = &common.ShareReward{ UID: uid, RewardType: updateType, RewardCount: updateValue, RewardDesc: desc, RewardAt: now.Unix(), } updateValues["withdrawable"] = gorm.Expr("withdrawable + ?", updateValue) } if len(updateValues) > 0 { err = db.Mysql().C().Model(&common.ShareInfo{}). Where("id = ?", shareInfo.ID). Updates(updateValues).Error if err != nil { log.Error("update share err, %s", err.Error()) return } if _, ok := updateValues["reward"]; ok { // 更新排行榜 shareRankData := common.ShareRankData{ UID: shareInfo.UID, RankCycle: 2, RankAt: util.GetWeekZeroTime(now).Unix(), RankValue: awardCount, UpdatedAt: now.Unix(), } err = db.Mysql().C().Model(&common.ShareRankData{}).Clauses(clause.OnConflict{ Columns: []clause.Column{{Name: "rank_cycle"}, {Name: "rank_at"}, {Name: "uid"}}, DoUpdates: clause.Assignments(map[string]interface{}{ "rank_value": gorm.Expr("rank_value + ?", shareRankData.RankValue), "updated_at": shareRankData.UpdatedAt, }), }).Create(&shareRankData).Error if err != nil { log.Error("update share rank data err, %s", err.Error()) return } } } if shareReward != nil { err = db.Mysql().C().Create(&shareReward).Error if err != nil { log.Error("create share reward err, %s", err.Error()) return } } if updateUp { for index, upUid := range shareInfo.UpList { if upUid == 0 { continue } updateShareByUp(uid, upUid, index+1, updateType, updateValue, expand...) } } return } func getShareRankJackpotKey() (rankAt, awardAt time.Time, expired int64, key string) { now := time.Now() rankCycle := 2 key = fmt.Sprintf("share_rank_jackpot|%d", rankCycle) switch rankCycle { case 1: rankAt = util.GetZeroTime(now) awardAt = rankAt.AddDate(0, 0, 1) expired = int64(rankAt.AddDate(0, 0, 2).Sub(now).Seconds()) case 2: rankAt = util.GetWeekZeroTime(now) awardAt = rankAt.AddDate(0, 0, 7) expired = int64(rankAt.AddDate(0, 0, 14).Sub(now).Seconds()) case 3: rankAt = util.GetFirstDateOfMonth(now) awardAt = rankAt.AddDate(0, 1, 0) expired = int64(rankAt.AddDate(0, 2, 0).Sub(now).Seconds()) } key += fmt.Sprintf("|%s", rankAt.Format("20060102")) return } func getShareRankJackpotPreKey() (key string) { now := time.Now() var rankAt time.Time rankCycle := 2 key = fmt.Sprintf("share_rank_jackpot|%d", rankCycle) switch rankCycle { case 1: rankAt = util.GetZeroTime(now).AddDate(0, 0, -1) case 2: rankAt = util.GetWeekZeroTime(now).AddDate(0, 0, -7) case 3: rankAt = util.GetFirstDateOfMonth(now).AddDate(0, -1, 0) } key += fmt.Sprintf("|%s", rankAt.Format("20060102")) return } func ShareRankJackpotGet() (jackpot, rankLess int64) { _, awardAt, _, rankKey := getShareRankJackpotKey() jackpot = db.Redis().GetInt64(rankKey) rankLess = int64(awardAt.Sub(time.Now()).Seconds()) return } func ShareRankJackpotPreGet() (jackpot int64) { jackpot = db.Redis().GetInt64(getShareRankJackpotPreKey()) return } func ShareRankJackpotPreLessGet() (jackpot int64) { jackpot = db.Redis().GetInt64(getShareRankJackpotPreKey() + "|less") return }