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 ) )
} 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
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
}
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 ( )
}
} )
} )
}
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
}
// todo 给玩家邮件发奖
}
jackpotKey := getShareRankJackpotPreKey ( )
log . Debug ( "shareRankAward, %s, %d, less jackpot:%d" , jackpotKey , jackpot , lessJackpot )
err = db . Redis ( ) . GetRedis ( ) . Set ( context . Background ( ) , jackpotKey , lessJackpot , 0 ) . Err ( )
if err != nil {
log . Error ( "share rankAward, %s set less-jackpot err, %s" , jackpotKey , err . Error ( ) )
}
}
// 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 ( ) )
}
}
}
}
// updateType(1:下注,2:充值,3:任务,4:邀请人,5:提现, 6:回滚)
func UpdateShare ( uid , updateType int , updateValue int64 , expand ... string ) ( err error ) {
if updateType == 1 { // 直接更新下注奖池
_ , _ , 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
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 ... )
}
}
}
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
}