From 02acc3095fe967986c9c54cc7a0bd5087b9e21de Mon Sep 17 00:00:00 2001 From: mofangmin Date: Fri, 20 Sep 2024 17:21:26 +0800 Subject: [PATCH] =?UTF-8?q?=E6=8E=92=E8=A1=8C=E6=A6=9C=E6=B4=BB=E5=8A=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- call/config.go | 53 +++++- call/mail.go | 1 + call/reload.go | 19 ++ call/robot.go | 243 ++++++++++++++++++++++++++ call/share.go | 8 +- common/activity.go | 6 +- common/config.go | 6 + common/currency.go | 1 + common/share.go | 27 +++ db/redis/redis.go | 2 + modules/backend/handler/gm/gm.go | 11 ++ modules/backend/migrate.go | 2 + modules/backend/routers/routers_gm.go | 2 +- modules/backend/values/gm.go | 4 + modules/web/app/activity.go | 1 + modules/web/handler/activity.go | 14 +- modules/web/handler/share.go | 6 +- modules/web/middleware/token.go | 1 + modules/web/timer.go | 118 ++++++++++++- modules/web/values/activity.go | 24 +-- 20 files changed, 521 insertions(+), 28 deletions(-) create mode 100644 call/robot.go diff --git a/call/config.go b/call/config.go index 003076f..aa88194 100644 --- a/call/config.go +++ b/call/config.go @@ -66,6 +66,8 @@ var ( configActivityPopup []*common.ConfigActivityPopup configDiscountTicket []common.ConfigDiscountTicket configRtp []common.ConfigRtp + configRankReward []common.ConfigShareRankReward + configRankRule []common.ConfigShareRankRule // 客服 configCustomerRobot []*common.ConfigCustomerRobot customerOrderLabel []*common.CustomerOrderLabel @@ -247,14 +249,15 @@ func GetConfigActivityAll() []*common.ConfigActivity { func GetConfigActivityActiveAll(uid int) []*common.ConfigActivity { ret := []*common.ConfigActivity{} for _, v := range configActivity { + v.IsOpen = true if !v.IsValid() { - continue + v.IsOpen = false } if v.ActivityID == common.ActivityIDFirstRechargeBack && !ShouldShowActivityFirstRechargeBack(uid) { continue } if v.Push != 1 { - continue + v.IsOpen = false } ret = append(ret, v) } @@ -1625,3 +1628,49 @@ func GetConfigRTPByAmount(amount int64) (ret common.ConfigRtp) { } return } + +func LoadConfigRobotRankReward() (err error) { + var list []common.ConfigShareRankReward + if _, err = db.Mysql().QueryAll("", "", &common.ConfigShareRankReward{}, &list); err != nil { + log.Error("err:%v", err) + return err + } + configRankReward = list + return nil +} + +func GetConfigRobotRankReward() []common.ConfigShareRankReward { + return configRankReward +} + +func GetConfigRobotRankRewardByRank(rank int) (ret common.ConfigShareRankReward) { + for _, conf := range configRankReward { + if conf.StartLevel <= rank && conf.EndLevel >= rank { + return conf + } + } + return +} + +func LoadConfigRobotRankRule() (err error) { + var list []common.ConfigShareRankRule + if _, err = db.Mysql().QueryAll("", "", &common.ConfigShareRankRule{}, &list); err != nil { + log.Error("err:%v", err) + return err + } + configRankRule = list + return nil +} + +func GetConfigRobotRankRule() []common.ConfigShareRankRule { + return configRankRule +} + +func GetConfigRobotRankRuleByDay(day int) (ret common.ConfigShareRankRule) { + for _, rule := range configRankRule { + if rule.Day == day { + return rule + } + } + return +} diff --git a/call/mail.go b/call/mail.go index dad4203..0b04a2f 100644 --- a/call/mail.go +++ b/call/mail.go @@ -17,6 +17,7 @@ var ( EmailWithdrawFail = "Your order %v, Amount: $%v\nYour withdrawal failed due to incorrect information. Please verify or change your withdrawal details and resubmit" EmailShareWithdrawFail = "Your friend's invitation reward withdrawal order: %v, Amount: %v\nYour withdrawal failed due to incorrect information. Please verify or change your withdrawal details and resubmit.\n" EmailDiscount = "Congratulations, you have received a $%v coupon for a top-up of $%v or more." + EmailShareRank = "Congratulations on achieving Rank %v in the million giveaway event. You have received a bonus of ₹%v. Thank you for participating!" ) func checkMail(uid int, red *common.PlayerRed) { diff --git a/call/reload.go b/call/reload.go index 40933cc..5b0ec12 100644 --- a/call/reload.go +++ b/call/reload.go @@ -486,6 +486,25 @@ func CommonReload(c map[int][]func(*pb.ReloadGameConfig) error) { return nil }} } + + if _, ok := c[common.ReloadConfigRankReward]; !ok { + c[common.ReloadConfigRankReward] = []func(*pb.ReloadGameConfig) error{func(rgc *pb.ReloadGameConfig) error { + if err := LoadConfigRobotRankReward(); err != nil { + log.Error("error : [%s]", err.Error()) + return err + } + return nil + }} + } + if _, ok := c[common.ReloadConfigRankRule]; !ok { + c[common.ReloadConfigRankRule] = []func(*pb.ReloadGameConfig) error{func(rgc *pb.ReloadGameConfig) error { + if err := LoadConfigRobotRankRule(); err != nil { + log.Error("error : [%s]", err.Error()) + return err + } + return nil + }} + } // 客服 if _, ok := c[common.ReloadConfigCustomerRobot]; !ok { c[common.ReloadConfigCustomerRobot] = []func(*pb.ReloadGameConfig) error{func(rgc *pb.ReloadGameConfig) error { diff --git a/call/robot.go b/call/robot.go new file mode 100644 index 0000000..1f0a043 --- /dev/null +++ b/call/robot.go @@ -0,0 +1,243 @@ +package call + +import ( + "context" + "fmt" + "math/rand" + "server/common" + "server/db" + "strconv" + "time" + + "github.com/liangdas/mqant/log" +) + +const ( + RankNum = 20 +) + +var ( + Robots = []*common.ConfigShareRobot{{ + RobotID: 21891253, + }, { + RobotID: 23923560, + }, { + RobotID: 25956230, + }} +) + +// RankInfo 机器人结构 +type RankInfo struct { + Rank int + InviteCount int64 + Avtar int + UserName string +} + +func IsRobot(uid int) bool { + for _, robot := range Robots { + if robot.RobotID == uid { + return true + } + } + if db.Mysql().Exist(&common.ConfigShareRobot{RobotID: uid}) { + return true + } + return false +} + +// 获取排行榜key +func GetRedisRankKey() string { + activity := GetConfigActivityByID(common.ActivityIDInviteRank) + if activity == nil { + log.Error("GetRedisRankKey ==nil") + return "" + } + return fmt.Sprintf("robot_ranking:%v", activity.Start) +} + +func GetRedisRankRobotKey(uid int) string { + today := time.Now().Format("20060102") + activity := GetConfigActivityByID(common.ActivityIDInviteRank) + if activity == nil { + log.Error("GetRedisRankKey ==nil") + return "" + } + return fmt.Sprintf("robot_ranking:%v:robot:%v:%v", activity.Start, uid, today) +} + +func GetRedisRankRewardKey() string { + activity := GetConfigActivityByID(common.ActivityIDInviteRank) + if activity == nil { + log.Error("GetRedisRankKey ==nil") + return "" + } + return fmt.Sprintf("robot_ranking:%v:reward", activity.Start) +} + +func TodayLogic(key string, uid int, num, times int64) { + robotKey := GetRedisRankRobotKey(uid) + timesCount := db.Redis().HGetInt(robotKey, "times_count") + // timesUse := db.Redis().HGetInt(robotKey, "times_use") + if timesCount == 0 { + err := db.Redis().HSet(robotKey, map[string]interface{}{ + "times_count": times, + "times_use": 1, + "num": 1, + }) + if err != nil { + log.Error("err:%v", err) + return + } + timesCount = int(times) + } else { + err := db.Redis().HIncrBy(robotKey, "times_use", 1) + if err != nil { + log.Error("err:%v", err) + return + } + if err = db.Redis().HIncrBy(robotKey, "num", num); err != nil { + log.Error("err:%v", err) + return + } + } + // if timesUse < timesCount { + IncreaseInviteCount(fmt.Sprintf("%v", uid), num, true) + // } +} + +// IncreaseInviteCount 增长机器人邀请人数 +func IncreaseInviteCount(robotName string, increment int64, isRobot bool) { + if increment > 0 { + ctx := context.Background() + rdb := db.Redis().GetRedis() + key := GetRedisRankKey() + newScore, err := rdb.ZIncrBy(ctx, key, float64(increment), robotName).Result() + if err != nil { + log.Error("增长失败: %v", err) + } else { + log.Info("机器人 %s 增长 %d 人,新的邀请人数为 %d", robotName, increment, int64(newScore)) + } + } +} + +func GetUserRank(uid int) (ret RankInfo) { + ctx := context.Background() + rdb := db.Redis().GetRedis() + key := GetRedisRankKey() + member := fmt.Sprintf("%v", uid) + score, err := rdb.ZScore(ctx, key, member).Result() + if err != nil { + log.Error("Error:", err) + return + } else { + log.Info("Score of %s: %f", member, score) + } + + // 获取指定成员的排名 (从小到大) + rank, err := rdb.ZRevRank(ctx, key, member).Result() + if err != nil { + log.Error("Error:", err) + return + } else { + log.Info("Rank of %s (ascending): %d", member, rank) + } + user, _ := GetUserXInfo(uid, "avatar") + if user != nil { + ret.Avtar, _ = strconv.Atoi(user.Avatar) + } + ret.Rank = int(rank) + 1 + ret.InviteCount = int64(score) + ret.UserName = fmt.Sprintf("User%v", uid) + return +} + +func GetTopShareRank(rank int64) (ret []RankInfo) { + ctx := context.Background() + rdb := db.Redis().GetRedis() + key := GetRedisRankKey() + rankList, err := rdb.ZRevRangeWithScores(ctx, key, 0, rank-1).Result() + if err != nil { + log.Error("获取排名失败: %v", err) + return nil + } + for idx, robot := range rankList { + username := fmt.Sprintf("%v", robot.Member) + uid, _ := strconv.Atoi(username) + + log.Debug("用户: %s,邀请人数: %d", robot.Member, int(robot.Score)) + info := RankInfo{ + Rank: idx + 1, + UserName: fmt.Sprintf("%v", robot.Member), + InviteCount: int64(robot.Score), + Avtar: rand.Intn(28) + 1, + } + if !IsRobot(uid) { + user, _ := GetUserXInfo(uid, "avatar") + info.Avtar, _ = strconv.Atoi(user.Avatar) + + } + ret = append(ret, info) + } + return +} + +// RiskControl 风控逻辑 +func RiskControl() { + rankList := GetTopShareRank(RankNum) + log.Info("rishControl:%v", rankList) + playerMap := make([]RankInfo, 0, 10) + robotMap := make([]RankInfo, 0, 10) + for _, rankInfo := range rankList { + uid, _ := strconv.Atoi(rankInfo.UserName) + // 判断是否为机器人 + if !IsRobot(uid) { + playerMap = append(playerMap, rankInfo) + } else { + robotMap = append(robotMap, rankInfo) + } + } + log.Debug("playerMap:%+v", playerMap) + log.Debug("robotMap:%+v", robotMap) + for idx, robot := range robotMap { + if idx < 3 { + player := playerMap[0] + log.Debug("player:%v,robot:%v", player, robot) + if robot.InviteCount < player.InviteCount { + IncreaseInviteCount(robot.UserName, player.InviteCount-robot.InviteCount+rand.Int63n(15), true) + } + } + } +} + +func SendReward() { + rankList := GetTopShareRank(RankNum) + log.Info("SendReward:%v", rankList) + for _, rankInfo := range rankList { + if rankInfo.InviteCount > 0 { + uid, err := strconv.Atoi(rankInfo.UserName) + if err != nil { + log.Error("err:%v", err) + continue + } + if rankInfo.Rank <= 3 && !IsRobot(uid) { + // 强制修改成第四名 + rankInfo.Rank = 4 + } + conf := GetConfigRobotRankRewardByRank(rankInfo.Rank) + if conf.Reward > 0 { + UpdateCurrencyPro(&common.UpdateCurrency{ + CurrencyBalance: &common.CurrencyBalance{ + UID: uid, + Event: common.CurrencyEventActivityShareRank, + Type: common.CurrencyINR, + Value: conf.Reward, + // NeedBet: GetConfigCurrencyResourceNeedBet(common.CurrencyResourceBonus, conf.Reward), + }, + }) + SendMailWithContent(uid, SystemTitle, fmt.Sprintf(EmailShareRank, rankInfo.Rank, conf.Reward/common.DecimalDigits)) + } + } + + } +} diff --git a/call/share.go b/call/share.go index d8206e9..3248740 100644 --- a/call/share.go +++ b/call/share.go @@ -114,11 +114,14 @@ func CheckShare(r *common.RechargeOrder) { "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) } - ShareRecharge(r.UID, r.Amount+betAmount) } -func ShareRecharge(uid int, amount int64) { +func ShareRecharge(uid int, amount int64, typ int) { shareInfo := &common.ShareInfo{UID: uid} db.Mysql().Get(shareInfo) if shareInfo.UP1 == 0 { @@ -147,6 +150,7 @@ func ShareRecharge(uid int, amount int64) { }) db.Mysql().Create(&common.ShareDetail{ UID: uid, + Type: typ, Up: upUid, RechargeAmount: amount, Reward: reward, diff --git a/common/activity.go b/common/activity.go index beb117c..8874f00 100644 --- a/common/activity.go +++ b/common/activity.go @@ -23,6 +23,7 @@ const ( ActivityIDSevenDayBox // 7日签到宝箱 ActivityIDSuper // 超级1+2 ActivityIDBetDraw // 下注抽奖活动 + ActivityIDInviteRank // 邀请排行榜 ) @@ -75,6 +76,7 @@ type ConfigActivity struct { Data string `gorm:"column:data;type:varchar(255);comment:跳转数据" json:"Data" web:"data"` Content string `gorm:"column:content;type:varchar(255);comment:文案内容" json:"Content" web:"content"` Text string `gorm:"column:text;type:varchar(255);comment:按钮内容" json:"Text" web:"text"` + IsOpen bool `gorm:"-"` } func (a *ConfigActivity) TableName() string { @@ -307,8 +309,8 @@ func (c *ConfigActivityBreakGift) TableName() string { type ConfigActivityWeekCard struct { ID int `gorm:"primarykey"` - DayOneReward int64 `gorm:"column:day_one_reward;type:bigint(20);default:0;comment:第一天奖励" web:"day_one_reward"` // 下限 - MiniLimit int64 `gorm:"column:mini_limit;type:bigint(20);default:0;comment:下限" web:"mini_limit"` // 下限 + DayOneReward int64 `gorm:"column:day_one_reward;type:bigint(20);default:0;comment:第一天奖励" web:"day_one_reward"` // 下限 + MiniLimit int64 `gorm:"column:mini_limit;type:bigint(20);default:0;comment:下限" web:"mini_limit"` // 下限 RewardAmount int64 `gorm:"column:reward_amount;type:bigint(20);default:0;comment:第二到第6天奖励金额" web:"reward_amount"` // 第二到第6天奖励金额 Discount int64 `gorm:"column:discount;type:bigint(20);default:0;comment:第二到第6天奖励金额" web:"discount"` // 满减券折扣 } diff --git a/common/config.go b/common/config.go index bc32efc..a6d1e18 100644 --- a/common/config.go +++ b/common/config.go @@ -54,6 +54,8 @@ const ( ReloadConfigActivityPopup // 活动弹窗 ReloadConfigDiscountTicket // 折扣券 ReloadConfigRTP // rtp配置 + ReloadConfigRankReward // 排行榜奖励 + ReloadConfigRankRule // 规则 ReloadConfigCustomerRobot // 客服系统机器人配置 ReloadConfigCustomerLabel // 客服系统订单标签 ReloadConfigCustomer // 客服系统订单标签 @@ -152,6 +154,10 @@ func GetConfigStructByType(t int) (interface{}, interface{}) { return &ConfigDiscountTicket{}, &[]ConfigDiscountTicket{} case ReloadConfigRTP: return &ConfigRtp{}, &[]ConfigRtp{} + case ReloadConfigRankReward: + return &ConfigShareRankReward{}, &[]ConfigShareRankReward{} + case ReloadConfigRankRule: + return &ConfigShareRankRule{}, &[]ConfigShareRankRule{} default: return nil, nil } diff --git a/common/currency.go b/common/currency.go index a8a2142..f9022e9 100644 --- a/common/currency.go +++ b/common/currency.go @@ -101,6 +101,7 @@ const ( CurrencyEventActivitySuper // 超级1+2 CurrencyEventActivityBetDraw // 下注抽奖 CurrencyEventActivityShareBind // 分享绑定 + CurrencyEventActivityShareRank // 分享排行榜 CurrencyEventAll CurrencyEventGM = 1000 // 后台修改货币 diff --git a/common/share.go b/common/share.go index 6025cef..8a61873 100644 --- a/common/share.go +++ b/common/share.go @@ -53,6 +53,7 @@ func (a *ShareInfo) TableName() string { type ShareDetail struct { ID int `gorm:"primarykey"` + Type int `gorm:"column:type;not null;default:0;type:int(11);"` UID int `gorm:"column:uid;not null;type:int(11);"` Up int `gorm:"column:up;type:int(11);default:0;comment:上级"` Reward int64 `gorm:"column:reward;type:bigint(20);default:0;comment:获取奖励"` @@ -138,3 +139,29 @@ type ConfigShareRobot struct { func (c *ConfigShareRobot) TableName() string { return "config_share_robot" } + +type ConfigShareRankReward struct { + ID int `gorm:"primarykey"` + StartLevel int `gorm:"column:start_level;type:int(11);default:0;comment:开始等级" web:"start_level"` + EndLevel int `gorm:"column:end_level;type:int(11);default:0;comment:结束等级" web:"end_level"` + Reward int64 `gorm:"column:reward;type:bigint(20);default:0;comment:奖励金额" web:"reward"` + isOpen int `gorm:"column:is_open;type:int(11);default:0;comment:是否外放" web:"is_open"` +} + +func (c *ConfigShareRankReward) TableName() string { + return "config_share_rank_reward" +} + +type ConfigShareRankRule struct { + ID int `gorm:"primarykey"` + Day int `gorm:"column:day;type:int(11);default:0;comment:天数" web:"day"` + StartInterval int64 `gorm:"column:start_interval;type:bigint(20);default:0;comment:开始间隔" web:"start_interval"` + EndInterval int64 `gorm:"column:end_interval;type:bigint(20);default:0;comment:结束间隔" web:"end_interval"` + IncrNum int64 `gorm:"column:incr_num;type:bigint(20);default:0;comment:增长人数" web:"incr_num"` + StartIncrTimes int64 `gorm:"column:start_incr_times;type:bigint(20);default:0;comment:增长次数" web:"start_incr_times"` + EndIncrTimes int64 `gorm:"column:end_incr_times;type:bigint(20);default:0;comment:增长次数" web:"end_incr_times"` +} + +func (c *ConfigShareRankRule) TableName() string { + return "config_share_rank_rule" +} diff --git a/db/redis/redis.go b/db/redis/redis.go index 38fe719..b09c9c6 100644 --- a/db/redis/redis.go +++ b/db/redis/redis.go @@ -130,6 +130,8 @@ func (r *RedisClient) HSet(key string, data ...interface{}) error { return err } return r.GetRedis().HSet(context.Background(), key, out).Err() + } else if tmp.Kind() == reflect.Map { + return r.GetRedis().HSet(context.Background(), key, data[0]).Err() } return r.GetRedis().HSet(context.Background(), key, data).Err() } diff --git a/modules/backend/handler/gm/gm.go b/modules/backend/handler/gm/gm.go index 8ec5cf6..092027f 100644 --- a/modules/backend/handler/gm/gm.go +++ b/modules/backend/handler/gm/gm.go @@ -266,3 +266,14 @@ func OptPlayerDisconnect(c *gin.Context) { } } + +func GMDelShareRank(c *gin.Context) { + a := app.NewApp(c) + defer func() { + a.Response() + }() + // 过期后判断占榜是否有问题 + call.RiskControl() + // 发放奖励 + call.SendReward() +} diff --git a/modules/backend/migrate.go b/modules/backend/migrate.go index e904fd8..9f45cae 100644 --- a/modules/backend/migrate.go +++ b/modules/backend/migrate.go @@ -120,6 +120,8 @@ func MigrateDB() { new(common.ConfigRtp), new(common.PlayerRtpData), new(common.ShareDetail), + new(common.ConfigShareRankRule), + new(common.ConfigShareRankReward), ) if err != nil { panic("Migrate db fail") diff --git a/modules/backend/routers/routers_gm.go b/modules/backend/routers/routers_gm.go index cfafae0..4934b54 100644 --- a/modules/backend/routers/routers_gm.go +++ b/modules/backend/routers/routers_gm.go @@ -23,7 +23,7 @@ func gmHandle(e *gin.Engine) { e.POST("/gm/recharge", handler.GMRecharge) e.POST("/gm/bindPhone", handler.GMBindPhone) e.POST("/gm/unbindPhone", handler.GMUnBindPhone) - + e.POST("/gm/deleteShareRank", handler.GMDelShareRank) // 后台强制玩家掉线 e.POST("/gm/player/OptPlayerDisconnect", handler.OptPlayerDisconnect) } diff --git a/modules/backend/values/gm.go b/modules/backend/values/gm.go index d11f128..7efb3a2 100644 --- a/modules/backend/values/gm.go +++ b/modules/backend/values/gm.go @@ -166,6 +166,10 @@ func GetControlType(path string) int { return common.ReloadConfigDiscountTicket case "configRtp": return common.ReloadConfigRTP + case "configShareRankReward": + return common.ReloadConfigRankReward + case "configShareRankRule": + return common.ReloadConfigRankRule default: return 0 } diff --git a/modules/web/app/activity.go b/modules/web/app/activity.go index e71cc23..ff56ec5 100644 --- a/modules/web/app/activity.go +++ b/modules/web/app/activity.go @@ -16,6 +16,7 @@ func (g *Gin) CheckActivityExpire(id int) (pass bool) { pass = act.IsValid() if !pass { g.Code = values.CodeActivityExpire + g.Msg = "The event has expired." } return } diff --git a/modules/web/handler/activity.go b/modules/web/handler/activity.go index 27d082b..4d50c3b 100644 --- a/modules/web/handler/activity.go +++ b/modules/web/handler/activity.go @@ -2205,9 +2205,21 @@ func InviteRankInfo(c *gin.Context) { defer func() { a.Response() }() - if !a.CheckActivityExpire(common.ActivityIDBetDraw) { + if !a.CheckActivityExpire(common.ActivityIDInviteRank) { return } + a.GetUID() resp := new(values.InviteInfoResp) a.Data = resp + resp.ActivityConf = call.GetConfigActivityByID(common.ActivityIDInviteRank) + resp.RankInfoList = call.GetTopShareRank(call.RankNum) + for _, rankInfo := range resp.RankInfoList { + rankInfo.UserName = rankInfo.UserName[:7] + rankInfo.UserName = rankInfo.UserName[:4] + "***" + rankInfo.UserName = "User" + rankInfo.UserName + } + resp.RewardRankConfig = call.GetConfigRobotRankReward() + if a.UID > 0 { + resp.MyRank = call.GetUserRank(a.UID) + } } diff --git a/modules/web/handler/share.go b/modules/web/handler/share.go index 03a6034..01ba45f 100644 --- a/modules/web/handler/share.go +++ b/modules/web/handler/share.go @@ -132,7 +132,7 @@ func ShareList(c *gin.Context) { if err != nil { log.Error("err:%v", err) } - err = db.Mysql().QueryBySql(fmt.Sprintf("SELECT UID, SUM(reward) AS total_reward, SUM(recharge_amount) AS total_recharge FROM share_detail WHERE up = %d and FROM_UNIXTIME(Time, '%%Y-%%m-%%d') = CURDATE() GROUP BY UID ORDER BY total_reward DESC limit %d,%d", a.UID, req.Page, req.Size), &ret) + err = db.Mysql().QueryBySql(fmt.Sprintf("SELECT UID, SUM(reward) AS total_reward, SUM(recharge_amount) AS total_recharge FROM share_detail WHERE up = %d and FROM_UNIXTIME(Time, '%%Y-%%m-%%d') = CURDATE() GROUP BY UID ORDER BY total_reward DESC limit %d,%d", a.UID, req.Page*req.Size, req.Size), &ret) if err != nil { log.Error("err:%v", err) } @@ -147,7 +147,7 @@ func ShareList(c *gin.Context) { if err != nil { log.Error("err:%v", err) } - err = db.Mysql().QueryBySql(fmt.Sprintf("SELECT UID, SUM(reward) AS total_reward, SUM(recharge_amount) AS total_recharge FROM share_detail where up = %d GROUP BY UID ORDER BY total_reward DESC limit %d,%d", a.UID, req.Page, req.Size), &ret) + err = db.Mysql().QueryBySql(fmt.Sprintf("SELECT UID, SUM(reward) AS total_reward, SUM(recharge_amount) AS total_recharge FROM share_detail where up = %d GROUP BY UID ORDER BY total_reward DESC limit %d,%d", a.UID, req.Page*req.Size, req.Size), &ret) if err != nil { log.Error("err:%v", err) } @@ -162,7 +162,7 @@ func ShareList(c *gin.Context) { if err != nil { log.Error("err:%v", err) } - err = db.Mysql().QueryBySql(fmt.Sprintf("SELECT UID, SUM(reward) AS total_reward, SUM(recharge_amount) AS total_recharge FROM share_detail where up = %d GROUP BY UID ORDER BY total_recharge DESC limit %d,%d", a.UID, req.Page, req.Size), &ret) + err = db.Mysql().QueryBySql(fmt.Sprintf("SELECT UID, SUM(reward) AS total_reward, SUM(recharge_amount) AS total_recharge FROM share_detail where up = %d GROUP BY UID ORDER BY total_recharge DESC limit %d,%d", a.UID, req.Page*req.Size, req.Size), &ret) if err != nil { log.Error("err:%v", err) } diff --git a/modules/web/middleware/token.go b/modules/web/middleware/token.go index 68fe599..89dbfb7 100644 --- a/modules/web/middleware/token.go +++ b/modules/web/middleware/token.go @@ -58,6 +58,7 @@ var ( "/customer/image/download": {}, "/activity/firstRechargeBack/info": {}, "/activity/weekCard/info": {}, + "/activity/inviteRank/info": {}, } ) diff --git a/modules/web/timer.go b/modules/web/timer.go index f487830..c4a1535 100644 --- a/modules/web/timer.go +++ b/modules/web/timer.go @@ -1,13 +1,16 @@ package web import ( + "context" "fmt" + "math/rand" "server/call" "server/common" "server/config" "server/db" "server/modules/web/values" "server/util" + "strconv" "time" "github.com/liangdas/mqant/log" @@ -15,7 +18,8 @@ import ( func FetchDatas() { GetShareData() - GetActivitySlotsRank() + // GetActivitySlotsRank() + RobotRank() } var ( @@ -73,3 +77,115 @@ func GetActivitySlotsRank() { log.Debug("ActivitySlotsRank:%+v", v) } } + +func RobotRank() { + now := time.Now() + activity := call.GetConfigActivityByID(common.ActivityIDInviteRank) + key := call.GetRedisRankKey() + log.Info("key:%v,rank checking", key) + // 活动未开始 + if activity.IsRelease != 2 || activity.Start > now.Unix() { + time.AfterFunc(time.Minute, RobotRank) + return + } else if activity.End < now.Unix() && activity.End > 0 { + rewardKey := call.GetRedisRankRewardKey() + res, _ := db.Redis().GetString(rewardKey) + if res == "1" { + // 一分钟重试 + log.Info("key:%v,checking", key) + time.AfterFunc(time.Minute, RobotRank) + return + } + // 过期后判断占榜是否有问题 + call.RiskControl() + // 发放奖励 + call.SendReward() + // 记录已经发奖 + db.Redis().SetNX(rewardKey, "1") + time.AfterFunc(time.Minute, RobotRank) + log.Info("key:%v,checking", key) + return + } + startTime := time.Unix(activity.Start, 0) + endTime := time.Unix(activity.End, 0) + // 总天数 + totalDay := int(endTime.Sub(startTime).Hours() / 24) + // 今天是第几天一个小时算一天 + day := int(now.Sub(startTime).Hours()/24) + 1 + // 获取占榜规则 + rule := call.GetConfigRobotRankRuleByDay(day) + if rule.ID == 0 { + log.Error("day:%v rule err", day) + } + // 增长人数 + num := rule.IncrNum + rdb := db.Redis().GetRedis() + ctx := context.Background() + robots := call.Robots + log.Info("totalDay:%v,day:%v,rule:%+v", totalDay, day, rule) + if day == totalDay { + log.Debug("最后一天增长逻辑") + robotRank := int64(0) + // 获取机器人排名 + for i := 0; i < len(robots); i++ { + result, err := rdb.ZRevRangeWithScores(ctx, key, robotRank, robotRank).Result() + if err != nil { + log.Error("Error:", err) + continue + } + _, topRankScore := result[0].Member, result[0].Score + lastRankScore, _ := rdb.ZScore(ctx, key, strconv.Itoa(robots[len(robots)-1].RobotID)).Result() + growth := int64(topRankScore-lastRankScore) / 5 + times := rand.Int63n(rule.EndIncrTimes-rule.StartIncrTimes) + rule.StartIncrTimes + call.TodayLogic(key, robots[i].RobotID, growth, times) + } + } else if day >= totalDay*2/3 { + log.Debug("倒数3/2天的增长逻辑") + robotRank := int64(0) + for _, robot := range robots { + rank, err := rdb.ZRevRank(ctx, key, strconv.Itoa(robot.RobotID)).Result() + if err != nil { + fmt.Println("Error:", err) + continue + } + if rank > 2 { + // 如果机器人不在前三名 + result, err := rdb.ZRevRangeWithScores(ctx, key, robotRank, robotRank).Result() + if err != nil { + log.Error("Error:", err) + continue + } + _, inviteCount := result[0].Member, result[0].Score + robotScore, err := rdb.ZScore(ctx, key, strconv.Itoa(robot.RobotID)).Result() + if err != nil { + log.Error("Error:", err) + continue + } + // 计算差值 N + N := rand.Int63n(int64(inviteCount-robotScore)) / 5 + if inviteCount-robotScore <= 5 { + N = int64(inviteCount - robotScore) + } + times := rand.Int63n(rule.EndIncrTimes-rule.StartIncrTimes) + rule.StartIncrTimes + call.TodayLogic(key, robot.RobotID, N, times) + } else { + // 如果机器人在前三名,使用正常增长逻辑 + times := rand.Int63n(rule.EndIncrTimes-rule.StartIncrTimes) + rule.StartIncrTimes + call.TodayLogic(key, robot.RobotID, num, times) + } + } + } else { + for _, robot := range robots { + times := rand.Int63n(rule.EndIncrTimes-rule.StartIncrTimes) + rule.StartIncrTimes + call.TodayLogic(key, robot.RobotID, num, times) + } + } + // 随机出增长间隔 增长人数 增长次数 + interval := rand.Int63n(rule.EndInterval-rule.StartInterval) + rule.StartInterval + interval = int64(time.Duration(interval) * time.Hour / 100) + log.Info("%v小时后执行", time.Duration(interval)/time.Hour) + if now.Unix()+interval > activity.End { + interval = activity.End - now.Unix() + } + time.AfterFunc(time.Duration(interval), RobotRank) +} diff --git a/modules/web/values/activity.go b/modules/web/values/activity.go index 550d93c..7f48787 100644 --- a/modules/web/values/activity.go +++ b/modules/web/values/activity.go @@ -1,6 +1,9 @@ package values -import "server/common" +import ( + "server/call" + "server/common" +) // GetPromotionsResp 促销中心 type GetPromotionsResp struct { @@ -326,20 +329,9 @@ type DiscountTicketResp struct { ChannelList []*common.ConfigPayChannels } -type RewardRankConfig struct { - RankMin int64 - RankMax int64 - Reward int64 -} - -type RankInfo struct { - Rank int `json:"Rank"` - Reward int `json:"Reward"` - UserName string `json:"UserName"` -} - type InviteInfoResp struct { - RewardRankConfig []RewardRankConfig - RankInfoList []RankInfo - MyRank RankInfo + RewardRankConfig []common.ConfigShareRankReward + RankInfoList []call.RankInfo + MyRank call.RankInfo + ActivityConf *common.ConfigActivity }