package call import ( "fmt" "reflect" "server/common" "server/db" "server/pb" "server/util" "strings" "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 = 1 db.Mysql().Create(shareInfo) } 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 // todo ?发送奖励? //util.Go(func() { // SendShareReward(cid, codeInfo.UID, codeInfo.ActivityId) //}) } 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() for i := 1; i <= 4; i++ { upUid := int(ref.FieldByName(fmt.Sprintf("UP%d", i)).Int()) if uid == 0 { break } field := fmt.Sprintf("down%d", i+1) db.Mysql().Update(&common.ShareInfo{UID: upUid}, map[string]interface{}{field: gorm.Expr(fmt.Sprintf("%s + 1", field))}) } // todo 更新上级邀请玩家数量? CheckTask(Task{Uid: upInfo.UID, Value: 1, Types: []common.TaskType{common.TaskTypeInvite}}) // 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 } // 裂变任务邀请人数 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 } } }) } // 判断分享,发放有效用户奖励 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 }