package common import ( "fmt" "math/rand" "reflect" "server/call" "server/common" "server/config" "server/db" "server/util" "time" "github.com/liangdas/mqant/log" "gorm.io/gorm" ) // 老的分享结算方案暂不使用 func initTimer() { // 结算分享 // ShareSettle() // 结算重置每日数据 // ShareReset() // 分享机器人 ShareRobotTimer() // slots奖池活动机器人 ActivitySlotsRobotTimer() // slots奖池活动结算 ActivitySlotsSettleTimer() } var ( ShareSettleTime = 3 * time.Minute Day5Minute int64 = 288 // 一天有288个5分钟 ) type updateShare struct { Level int MyBets int64 // 自己本次结算下注额 Bets int64 // 记录需要更新的总下注 Reals int // 记录需要更新的有效下线个数 Rewards int64 // 自己的佣金 UpRewards int64 // 对上级的贡献佣金 } func ShareRobotTimer() { robots := call.GetConfigShareRobot() // 每5分钟刷新一次数据 for _, v := range robots { if v.RobotID == 0 { continue } if db.Mysql().Exist(&common.PlayerDBInfo{Id: v.RobotID}) { log.Error("invalid robotid:%v", v.RobotID) continue } one := &common.ShareInfo{UID: v.RobotID} diff := v.DayCashUp - v.DayCashDown if diff <= 0 { continue } add := rand.Int63n(diff) + v.DayCashDown add /= Day5Minute db.Mysql().Get(one) if one.ID == 0 { one.Share = util.GetShareCode(one.UID) one.BetReward = v.InitCash + add db.Mysql().Create(one) } else { db.Mysql().Update(&common.ShareInfo{UID: v.RobotID}, map[string]interface{}{"bet_reward": gorm.Expr("bet_reward + ?", add)}) } } minute := time.Now().Minute() next := minute % 5 if next == 0 { next = 5 } log.Debug("next robot timer:%v", next) time.AfterFunc(time.Duration(5)*time.Minute, ShareRobotTimer) } /* 每日使用10个AI在数字900-990之间随机分别选取一个数字(若选取数字大于910的AI玩家小于3,则重新选取直到选取数字大于910的玩家大于3) 每日使用5个AI在数字850-900之间随机分别选取一个数字 每日中午12点至下午6点每隔一小时随机上场一个ai,6点后每隔15~25分钟上场一个 */ func ActivitySlotsRobotTimer() { now := time.Now() hour := now.Hour() var next int64 defer func() { log.Debug("next ActivitySlotsRobotTimer:%v", next) time.AfterFunc(time.Duration(next)*time.Second, ActivitySlotsRobotTimer) }() if !config.GetBase().Release { next = 5 * 60 ActivitySlotsRobotJoin() return } if hour < 12 { next = util.GetZeroTime(now).Unix() + 12*60*60 + 1 - now.Unix() return } else if hour < 18 { // 一小时内随机生成一个机器人 diff := util.GetZeroTime(now).Unix() + int64(hour+1)*60*60 - time.Now().Unix() next = diff ran := rand.Intn(int(diff)) + 1 log.Debug("next ActivitySlotsRobotJoin:%v", ran) time.AfterFunc(time.Duration(ran)*time.Second, func() { ActivitySlotsRobotJoin() }) return } else if hour < 23 { ran := rand.Int63n(10) + 15 next = ran * 60 log.Debug("next ActivitySlotsRobotJoin:%v", ran) ActivitySlotsRobotJoin() } else { next = util.GetZeroTime(now.AddDate(0, 0, 1)).Unix() + 12*60*60 + 1 - now.Unix() } } const ( Max910Robot = 3 // 数字大于910的机器人 Max900Robot = 7 // 900-990的机器人数 Max850Robot = 5 // 850-900的机器人数 MaxRobotCount = 15 ) // 每日结算后初始10个随机低分机器人 func ActivitySlotsFirstRobotJoin() { list := []*common.ActivitySlotsData{} _, err := db.Mysql().QueryAll("role = 2", "uid asc", &common.ActivitySlotsData{}, &list) if err != nil { log.Error("err:%v", err) return } log.Debug("ActivitySlotsFirstRobotJoin,list:%v", len(list)) isSingle := call.IsActivitySingleDay(common.ActivityIDSlots) for i := 0; i < 10; i++ { phone := util.CheckPhone("") avatar := call.RandomUserAvatar() robotUID := 100 + i number := rand.Intn(400) + 1 if i < len(list) { u := map[string]interface{}{"best_number2": number, "time2": time.Now().Unix(), "nick": phone, "avatar": avatar} if isSingle { u = map[string]interface{}{"best_number1": number, "time1": time.Now().Unix(), "nick": phone, "avatar": avatar} } db.Mysql().Update(&common.ActivitySlotsData{ID: list[i].ID}, u) continue } data := &common.ActivitySlotsData{UID: robotUID, Role: 2, Nick: phone, Avatar: avatar} if isSingle { data.BestNumber1 = number data.Time1 = time.Now().Unix() } else { data.BestNumber2 = number data.Time2 = time.Now().Unix() } db.Mysql().Create(data) } } // 生成一个机器人 func ActivitySlotsRobotJoin() { isSingle := call.IsActivitySingleDay(common.ActivityIDSlots) zero := util.GetZeroTime(time.Now()).Unix() list := []*common.ActivitySlotsData{} _, err := db.Mysql().QueryAll("role = 1", "uid asc", &common.ActivitySlotsData{}, &list) if err != nil { return } var count850, count900, count910 int var canUpdate *common.ActivitySlotsData for i, v := range list { ref := reflect.ValueOf(v).Elem() index := 2 if isSingle { index = 1 } t := ref.FieldByName(fmt.Sprintf("Time%d", index)).Int() if t < zero { if canUpdate == nil { canUpdate = list[i] } continue } number := ref.FieldByName(fmt.Sprintf("BestNumber%d", index)).Int() if number < 900 { count850++ } else if number <= 910 { count900++ } else { count910++ } } total := count850 + count900 + count910 if total >= MaxRobotCount { return } all := make([]int, 3) all[0] = Max850Robot - count850 all[1] = Max900Robot - count900 all[2] = Max910Robot - count910 ran := rand.Intn(all[0] + all[1] + all[2]) this := 0 index := 0 for i := 0; i < 3; i++ { this += all[i] if ran < this { index = i break } } number := 0 switch index { case 0: number = rand.Intn(50) + 850 case 1: number = rand.Intn(11) + 900 case 2: number = rand.Intn(89) + 911 } if number == 0 { return } phone := util.CheckPhone("") avatar := call.RandomUserAvatar() if canUpdate != nil { u := map[string]interface{}{"best_number2": number, "time2": time.Now().Unix(), "nick": phone, "avatar": avatar} if isSingle { u = map[string]interface{}{"best_number1": number, "time1": time.Now().Unix(), "nick": phone, "avatar": avatar} } db.Mysql().Update(&common.ActivitySlotsData{ID: canUpdate.ID}, u) } else { robotUID := 2 if len(list) > 0 { robotUID = list[len(list)-1].UID + 1 } data := &common.ActivitySlotsData{UID: robotUID, Role: 1, Nick: phone, Avatar: avatar} if isSingle { data.BestNumber1 = number data.Time1 = time.Now().Unix() } else { data.BestNumber2 = number data.Time2 = time.Now().Unix() } db.Mysql().Create(data) } } func ActivitySlotsSettleTimer() { now := time.Now() next := util.GetZeroTime(now.AddDate(0, 0, 1)).Unix() + 5 - now.Unix() // 零点过5秒结算 if !config.GetBase().Release { next = util.GetNext5MinUnix() - now.Unix() } defer func() { log.Debug("next ActivitySlotsSettleTimer:%v", next) time.AfterFunc(time.Duration(next)*time.Second, ActivitySlotsSettleTimer) }() // if !call.IsActivityValid(common.ActivityIDSlots) { // return // } date := now.AddDate(0, 0, -1).Format("20060102") record := &common.ActivitySlotsRecord{ UID: -1, // 代表系统结算标志 Date: date, } db.Mysql().Get(record) if record.Settle == 1 { return } con := call.GetConfigActivitySlots() if len(con) == 0 { return } list := []*common.ActivitySlotsData{} order := "best_number1 desc,time1 asc" str := "time1" isSingle := call.IsActivitySingleDay(common.ActivityIDSlots) if !config.GetBase().Release { if !isSingle { // 测试服结算当天的 order = "best_number2 desc,time2 asc" str = "time2" } } else { if isSingle { // 由于是结算前一天,所以查询逻辑是相反的 order = "best_number2 desc,time2 asc" str = "time2" } } db.Mysql().QueryList(0, con[len(con)-1].RankUp, fmt.Sprintf("%s >= %d", str, util.GetZeroTime(time.Now().AddDate(0, 0, -1)).Unix()), order, &common.ActivitySlotsData{}, &list) for i, v := range list { if i == 0 { if config.GetBase().Release { if isSingle { record.BestNumber = v.BestNumber2 } else { record.BestNumber = v.BestNumber1 } } else { if isSingle { record.BestNumber = v.BestNumber1 } else { record.BestNumber = v.BestNumber2 } } } if v.Role > 0 { continue } reward := call.GetConfigActivitySlotsRewardByRank(i + 1) if reward == 0 { continue } // call.UpdateCurrencyPro(&common.UpdateCurrency{ // CurrencyBalance: &common.CurrencyBalance{ // UID: v.UID, // Time: now.Unix(), // Value: reward, // Type: common.CurrencyBrazil, // Event: common.CurrencyEventActivitySlots, // NeedBet: call.GetConfigCurrencyResourceNeedBet(common.CurrencyResourceBonus, reward), // }, // }) one := &common.ActivitySlotsRecord{Date: date, UID: v.UID, Reward: reward, BestNumber: record.BestNumber, Settle: 0, Rank: i + 1} if config.GetBase().Release { if isSingle { one.MyNumber = v.BestNumber2 } else { one.MyNumber = v.BestNumber1 } } else { if isSingle { one.MyNumber = v.BestNumber1 } else { one.MyNumber = v.BestNumber2 } } db.Mysql().Create(one) } record.Settle = 1 db.Mysql().Create(record) ActivitySlotsFirstRobotJoin() } // func ShareSettle() { // if !config.GetBase().Release { // ShareSettleTime = 30 * time.Second // } // log.Debug("next ShareSettle:%v", ShareSettleTime) // time.AfterFunc(ShareSettleTime, func() { // defer ShareSettle() // all := map[int]*updateShare{} // ret := []*common.ShareInfo{} // db.Mysql().QueryAll("bet>0 and up>0", "", &common.ShareInfo{}, &ret) // log.Debug("settle:%v", ret) // if len(ret) == 0 { // return // } // for _, v := range ret { // bet := v.Bet // reals := 0 // if v.TotalBet == 0 { // 产生有效投注,需要更新上级有效下线个数 // reals = 1 // PddUpdate(v.UID, v.UP) // 产生有效投注,更新pdd数据 // } // // 循环查询结算上级 // this := v // lastLevel := 0 // 上一次结算时的上级等级,需要比较该值确定上级是否还能分得佣金 // for { // log.Debug("this:%+v", this) // if this.UP == 0 { // break // } // upInfo := &common.ShareInfo{UID: this.UP} // db.Mysql().Get(upInfo) // if upInfo.ID <= 0 { // break // } // u, ok := all[upInfo.UID] // if !ok { // u = &updateShare{ // Bets: bet, // Reals: reals, // } // all[upInfo.UID] = u // } else { // u.Bets += bet // u.Reals += reals // } // // 首先计算是否升级 // con := call.GetConfigShareLevelByBet(upInfo.TotalAgentsBet + u.Bets) // if con != nil { // // 升级了标记 // if con.Level > upInfo.Level { // u.Level = con.Level // } // // 计算等级差 // var per int64 // if con.Level > lastLevel { // if lastLevel == 0 { // per = con.Per // } else { // lastCon := call.GetConfigShareByLevel(lastLevel) // if lastCon != nil { // per = con.Per - lastCon.Per // } // } // lastLevel = con.Level // } // if per > 0 { // reward := per * bet / 10000 // if reward > 0 { // u.Rewards += reward // thisU, ok := all[this.UID] // if !ok { // all[this.UID] = &updateShare{ // UpRewards: reward, // } // } else { // thisU.UpRewards += reward // } // } // } // } // this = upInfo // } // // 结算完后,更新自己的下注 // my, ok := all[v.UID] // if !ok { // all[v.UID] = &updateShare{ // MyBets: bet, // } // } else { // my.MyBets = bet // } // } // // 计算完成后统一更新玩家数据 // log.Debug("start share update:%d", len(all)) // success := 0 // fail := 0 // for uid, v := range all { // update := map[string]interface{}{} // if v.MyBets > 0 { // update["bet"] = gorm.Expr("bet - ?", v.MyBets) // update["today_bet"] = gorm.Expr("today_bet + ?", v.MyBets) // update["total_bet"] = gorm.Expr("total_bet + ?", v.MyBets) // } // if v.Bets > 0 { // update["today_agents_bet"] = gorm.Expr("today_agents_bet + ?", v.Bets) // update["total_agents_bet"] = gorm.Expr("total_agents_bet + ?", v.Bets) // } // if v.Reals > 0 { // update["today_real_agents"] = gorm.Expr("today_real_agents + ?", v.Reals) // update["total_real_agents"] = gorm.Expr("total_real_agents + ?", v.Reals) // } // if v.Rewards > 0 { // update["today_reward"] = gorm.Expr("today_reward + ?", v.Rewards) // update["total_reward"] = gorm.Expr("total_reward + ?", v.Rewards) // update["available_reward"] = gorm.Expr("available_reward + ?", v.Rewards) // } // if v.UpRewards > 0 { // update["today_up_reward"] = gorm.Expr("today_up_reward + ?", v.UpRewards) // } // err := db.Mysql().Update(&common.ShareInfo{UID: uid}, update) // if err != nil { // fail++ // } else { // success++ // } // } // log.Debug("finish share update:%d,success:%d,fail:%d", len(all), success, fail) // }) // } var ( ShareQueryNum = 5000 ) // func ShareReset() { // next := time.Until(util.GetZeroTime(time.Now().AddDate(0, 0, 1)).Add(5 * time.Second)) // log.Debug("next ShareReset:%v", next) // time.AfterFunc(next, func() { // defer ShareReset() // recordTime := time.Now().AddDate(0, 0, -1) // recordTimeUnix := recordTime.Unix() // recordTimeDate := recordTime.Format("20060102") // start := 0 // for { // ret := []common.ShareInfo{} // db.Mysql().QueryListW(start, ShareQueryNum, "", &common.ShareInfo{}, &ret, "today_agents_bet+today_agents>0") // for _, v := range ret { // uid := v.UID // db.ES().InsertToESGO(common.ESIndexShareProfitReport, &common.ESShareProfitReport{ // UID: uid, // Date: recordTimeDate, // Regist: v.TodayAgents, // Bet: v.TodayAgentsBet, // Level: v.Level, // Time: recordTimeUnix, // Reward: v.TodayReward, // }) // thisStart := 0 // for { // agents := []common.ShareInfo{} // db.Mysql().QueryListW(thisStart, ShareQueryNum, "", &common.ShareInfo{}, &agents, fmt.Sprintf("up = %d", uid)) // for _, v := range agents { // one := &common.ESShareProfitRecord{ // UID: v.UID, // Bet: v.TodayBet, // DownBet: v.TodayAgentsBet, // Up: uid, // Reward: v.TodayUpReward, // Date: recordTimeDate, // Time: recordTimeUnix, // } // db.ES().InsertToESGO(common.ESIndexShareProfitRecord, one) // } // if len(agents) < ShareQueryNum { // break // } // thisStart++ // } // } // if len(ret) < ShareQueryNum { // break // } // start++ // } // db.Mysql().UpdateW(&common.ShareInfo{}, map[string]interface{}{"today_agents_bet": 0, "today_agents": 0, "today_real_agents": 0, "today_reward": 0, "today_bet": 0}, // "today_agents_bet+today_agents>0") // }) // } // 更新玩家pdd邀请数据 func PddUpdate(uid, referer int) { if referer == 0 { return } con := call.GetConfigActivityPdd() if con == nil { return } now := time.Now().Unix() pddData := &common.PddData{UID: referer} db.Mysql().Get(pddData) if now-pddData.Time >= con.Expire*60 { return } db.Mysql().Update(&common.PddData{UID: referer, Time: pddData.Time}, map[string]interface{}{"spin": gorm.Expr("spin + 1")}) user, _ := call.GetUserXInfo(uid, "nick", "avatar") db.ES().InsertToESGO(common.ESIndexBackPddRecord, common.ESPddRecord{ UID: uid, Referer: referer, Time: now, Nick: user.Nick, Avatar: user.Avatar, }) } // initRecordCurrency 记录玩家身上货币,可退出货币 func initRecordCurrency() { next := time.Until(util.GetZeroTime(time.Now().AddDate(0, 0, 1)).Add(time.Second)) // next := time.Until(time.Now().Add(time.Minute)) time.AfterFunc(next, recordCurrency) log.Debug("next initRecordCurrency:%v", next) } func recordCurrency() { initRecordCurrency() // var total, totalCash int64 // channel := call.GetChannelListReal() // con := call.GetConfigWithdrawProduct(common.WithdrawSorceBank) // var least int64 // 最低退出所需金币 // for _, v := range con { // if least == 0 || v.PayGold < least { // least = v.PayGold // } // } // for _, v := range channel { // sql := fmt.Sprintf("channel_id = %v and role <> %v and status = %v", v.ChannelID, common.PlayerRoleRobot, common.AccountStatusNormal) // err := db.Mysql().C().Table("users").Where(sql).Select("sum(bind_cash+cash)").Scan(&total).Error // if err != nil { // log.Error("err:%v", err) // } // tsql := sql + fmt.Sprintf(" and cash > %v", least) // err = db.Mysql().C().Table("users").Where(tsql).Select("sum(cash)").Scan(&totalCash).Error // if err != nil { // log.Error("err:%v", err) // } // if total == 0 && totalCash == 0 { // continue // } // brl := db.Mysql().Sum(&common.PlayerCurrency{}, "", "brl") // usdt := db.Mysql().Sum(&common.PlayerCurrency{}, "", "usdt") // recordDate := time.Now().AddDate(0, 0, -1) // date := recordDate.Format("2006-01-02") // log.Debug("record date:%v,total:%v,totalCash:%v", date, total, totalCash) // db.ES().InsertToESGO(common.ESIndexBackDailyData, &common.ESDailySysData{ // Date: date, // Channel: v.ChannelID, // BRL: brl, // USDT: usdt, // }) // } }