diff --git a/dbproxy/svc/l_redpacket.go b/dbproxy/svc/l_redpacket.go index b94c6ef..6ce45a1 100644 --- a/dbproxy/svc/l_redpacket.go +++ b/dbproxy/svc/l_redpacket.go @@ -27,7 +27,7 @@ func (r *RedPacketService) GetAll(plt *string, res *[]*model.RedPacket) error { list, err := d.GetAll() if err != nil { - logger.Logger.Errorf("GetAll error: %v", err) + logger.Logger.Errorf("RedPacketService.GetAll error: %v", err) return err } @@ -36,17 +36,19 @@ func (r *RedPacketService) GetAll(plt *string, res *[]*model.RedPacket) error { return nil } -func (r *RedPacketService) UpdateAll(plt *string, list []*model.RedPacket) error { - d, err := mongox.GetDao(*plt, dao.NewRedPacket) +func (r *RedPacketService) UpdateAll(req *model.UpdateRedPacketAllReq, res *bool) error { + d, err := mongox.GetDao(req.Plt, dao.NewRedPacket) if err != nil { return err } - err = d.UpdateAll(list) + err = d.UpdateAll(req.List) if err != nil { - logger.Logger.Errorf("UpdateAll error: %v", err) + logger.Logger.Errorf("RedPacketService.UpdateAll error: %v", err) return err } + *res = true + return nil } diff --git a/model/player.go b/model/player.go index 231018a..b6d33cf 100644 --- a/model/player.go +++ b/model/player.go @@ -548,6 +548,11 @@ type DiamondBankData struct { TakeRecord map[int32]int64 // 每次领取记录 } +type RedPacketData struct { + N int64 // 领取次数 + RN int64 // 非空奖次数 +} + type WelfareData struct { ReliefFundTimes int32 //救济金领取次数 Sign7 *NewSignData //七日签到 @@ -565,7 +570,7 @@ type WelfareData struct { PermitAward map[int32]int64 // 赛季通行证奖励领取时间 PermitExchange map[int32][]int64 // 赛季通行证兑换次数, 多次的兑换时间 NianData *NianData //年兽活动数据 - RedPacket map[int64]int // 红包活动 活动id:领取次数 + RedPacket map[int64]*RedPacketData // 红包活动 活动id:领取次数 } func NewWelfareData() *WelfareData { @@ -582,10 +587,10 @@ func NewWelfareData() *WelfareData { }, PermitAward: make(map[int32]int64), PermitExchange: make(map[int32][]int64), + RedPacket: make(map[int64]*RedPacketData), NianData: &NianData{ OtherAwardNum: make(map[int32]int32), }, - RedPacket: make(map[int64]int), } } diff --git a/model/redpacket.go b/model/redpacket.go index 9dc3645..6c49c65 100644 --- a/model/redpacket.go +++ b/model/redpacket.go @@ -30,6 +30,8 @@ func GetRedPacketAll(plt string) (res []*RedPacket, err error) { return nil, errors.New("rpc client is nil") } + res = make([]*RedPacket, 0) + err = rpcCli.CallWithTimeout("RedPacketService.GetAll", &plt, &res, time.Second*30) if err != nil { logger.Logger.Errorf("GetRedPacketAll error: %v", err) @@ -39,13 +41,23 @@ func GetRedPacketAll(plt string) (res []*RedPacket, err error) { return res, nil } +type UpdateRedPacketAllReq struct { + Plt string + List []*RedPacket +} + func UpdateRedPacketAll(plt string, list []*RedPacket) error { if rpcCli == nil { logger.Logger.Error("model.UpdateRedPacketAll rpcCli == nil") return errors.New("rpc client is nil") } + req := &UpdateRedPacketAllReq{ + Plt: plt, + List: list, + } + res := false - err := rpcCli.CallWithTimeout("RedPacketService.UpdateAll", &plt, &list, time.Second*30) + err := rpcCli.CallWithTimeout("RedPacketService.UpdateAll", req, &res, time.Second*30) if err != nil { logger.Logger.Errorf("UpdateRedPacketAll error: %v", err) return err diff --git a/statistics/task/excelmgr.go b/statistics/task/excelmgr.go index bc83808..5856f5f 100644 --- a/statistics/task/excelmgr.go +++ b/statistics/task/excelmgr.go @@ -2,7 +2,6 @@ package main import ( "fmt" - "golang.org/x/exp/maps" "strings" "github.com/mozillazg/go-pinyin" @@ -111,7 +110,7 @@ func (e *ExcelMgr) Save(id int, startTime, endTime string) error { filename := fmt.Sprintf("%s_%s_%s.xlsx", d.DataName, startTime, endTime) - if VP.GetBool("IsDatabaseMode") { + if true { rows, err := d.GetRows("Sheet1") if err != nil { return err @@ -127,21 +126,20 @@ func (e *ExcelMgr) Save(id int, startTime, endTime string) error { index := make(map[string]string) for _, v := range d.Head { cl := ChineseToPinYin([]string{v})[0] - d.TableHead = append(d.TableHead, cl) files[cl] = v if strings.Contains(v, "*") { index[cl] = "INDEX" } } - createSQL := buildCreateTableSQLWithIndices(d.TableName, d.DataName, files, index) + createSQL := buildCreateTableSQLWithIndices(d.TableName, d.DataName, d.TableHead, files, index) if err = db.Exec(createSQL).Error; err != nil { logger.Logger.Errorf("createTable error: %v", err) return err } - if err = insertData(db.DB, d.TableName, maps.Keys(files), rows); err != nil { + if err = insertData(db.DB, d.TableName, d.TableHead, rows); err != nil { logger.Logger.Errorf("insertData error: %v", err) return err } @@ -195,12 +193,13 @@ func (e *ExcelMgr) Pull(id int, startTime, endTime string) (*excelize.File, stri } // 构建创建表的 SQL 语句,支持中文描述和索引 -func buildCreateTableSQLWithIndices(tableName string, comment string, fields map[string]string, indices map[string]string) string { +func buildCreateTableSQLWithIndices(tableName string, comment string, head []string, fields map[string]string, indices map[string]string) string { var columns []string var indexDefs []string // 遍历字段定义 - for field, comment := range fields { + for _, field := range head { + comment := fields[field] column := fmt.Sprintf("`%s` VARCHAR(255) COMMENT '%s'", field, comment) columns = append(columns, column) @@ -234,7 +233,7 @@ func insertData(db *gorm.DB, tableName string, header []string, rows [][]string) insertSQL := fmt.Sprintf("INSERT INTO `%s` (%s) VALUES (%s)", tableName, "`"+strings.Join(header, "`,`")+"`", placeholders) - for _, row := range rows { + for _, row := range rows[1:] { // 确保每行数据长度和表头一致 if len(row) < len(header) { for len(row) < len(header) { diff --git a/worldsrv/activity_redpacket.go b/worldsrv/activity_redpacket.go index d697b57..7394d17 100644 --- a/worldsrv/activity_redpacket.go +++ b/worldsrv/activity_redpacket.go @@ -133,36 +133,21 @@ func (m *RedPacketMgr) GetRemainTimesByConfig(p *Player, cfg *webapiproto.RedPac return 0, 0 } - var limit int32 - playerLimit := WelfareMgrSington.GetConfig(p.Platform).RedPacketConfig.GetPlayerLimit() - if playerLimit > 0 && cfg.GetMaxCount() > 0 { - if playerLimit < int32(cfg.GetMaxCount()) { - limit = playerLimit - } else { - limit = int32(cfg.GetMaxCount()) - } - } else { - if playerLimit > 0 { - limit = playerLimit - } - if cfg.GetMaxCount() > 0 { - limit = int32(cfg.GetMaxCount()) - } - } - if limit <= 0 { + if cfg.GetMaxCount() <= 0 { return -1, -1 } + n := 0 if p.WelfData != nil && p.WelfData.RedPacket != nil { if _, exist := p.WelfData.RedPacket[cfg.GetId()]; exist { - n = p.WelfData.RedPacket[cfg.GetId()] + n = int(p.WelfData.RedPacket[cfg.GetId()].N) } } - remainCount := int64(limit) - int64(n) + remainCount := cfg.GetMaxCount() - int64(n) if remainCount < 0 { remainCount = 0 } - return int64(limit), remainCount + return cfg.GetMaxCount(), remainCount } // AddUse 添加使用红包 diff --git a/worldsrv/actmonitormgr.go b/worldsrv/actmonitormgr.go deleted file mode 100644 index 01a8120..0000000 --- a/worldsrv/actmonitormgr.go +++ /dev/null @@ -1,177 +0,0 @@ -package main - -import ( - "math" - "mongo.games.com/game/model" - "mongo.games.com/goserver/core/logger" - "sort" -) - -const ( - ActState_Login int32 = 1 << iota //登录.1 - ActState_Exchange //兑换.2 - ActState_Game //游戏.3 - ActState_Max -) - -var ActMonitorMgrSington = &ActMonitorMgr{ - ActMonitorList: make(map[int64]*ActMonitorInfo), -} - -type ActMonitorInfo struct { - SeqNo int64 - SnId int32 - Platform string //平台 - MonitorType int32 //二进制 1.登录 2.兑换 3.游戏 - CreateTime int64 //创建时间 - Creator string //创建者 - ReMark string //备注 - GameName string //当前所在游戏名字 - State int //玩家状态 0.全部 1.不在线 2.在线 3.游戏中 -} -type ActMonitorMgr struct { - ActMonitorList map[int64]*ActMonitorInfo - NowActSeqNo int64 -} - -// monitorType 自己的类型 flag 当前触发的类型 -func (u *ActMonitorMgr) IsMarkFlag(monitorType, flag int32) bool { - if (monitorType & flag) != 0 { - return true - } - return false -} -func (u *ActMonitorMgr) Init() { - actMonitorData := model.GetAllActMonitorData() - for _, info := range actMonitorData { - ami := &ActMonitorInfo{ - SeqNo: info.SeqNo, - SnId: info.SnId, - Platform: info.Platform, - MonitorType: info.MonitorType, - CreateTime: info.CreateTime, - Creator: info.Creator, - ReMark: info.ReMark, - } - if u.NowActSeqNo < info.SeqNo { - u.NowActSeqNo = info.SeqNo - } - u.ActMonitorList[info.SeqNo] = ami - } -} - -type ActMonitorList struct { - PageNo int - PageSize int - PageSum int - TotalSum int - Data []*ActMonitorInfo -} - -func (u *ActMonitorMgr) QueryAMIList(pageNo, pageSize int, platform string, snid, startTs, endTs, state int) *ActMonitorList { - if len(u.ActMonitorList) == 0 { - return nil - } - var amiList = make([]*ActMonitorInfo, 0) - for _, v := range u.ActMonitorList { - if len(platform) != 0 && v.Platform != platform { - continue - } - if snid != 0 && v.SnId != int32(snid) { - continue - } - if startTs != 0 && endTs != 0 && (v.CreateTime < int64(startTs) || v.CreateTime > int64(endTs)) { - continue - } - if state != 0 && v.State != state { - continue - } - amiList = append(amiList, v) - } - sort.Slice(amiList, func(i, j int) bool { - if amiList[i].SeqNo > amiList[j].SeqNo { - return true - } - return false - }) - totalNum := len(amiList) //总条目 - pageSum := int(math.Ceil(float64(totalNum) / float64(pageSize))) //总页数 - if pageNo <= 0 || pageNo > pageSum { - pageNo = 1 //当前页 - } - start := (pageNo - 1) * pageSize - end := start + pageSize - if totalNum > start { - if totalNum < end { - end = totalNum - } - amiList = amiList[start:end] - } - for k, v := range amiList { - actPlayer := amiList[k] - actPlayer.GameName = "" - p := PlayerMgrSington.GetPlayerBySnId(v.SnId) - if p != nil { - if p.IsOnLine() { - actPlayer.State = 2 - } else { - actPlayer.State = 1 - } - if p.scene != nil { - actPlayer.State = 3 - actPlayer.GameName = p.scene.dbGameFree.GetName() + p.scene.dbGameFree.GetTitle() - } - } else { - actPlayer.State = 1 - } - } - return &ActMonitorList{pageNo, pageSize, pageSum, totalNum, amiList} -} -func (u *ActMonitorMgr) Edit(amt *ActMonitorInfo) { - u.ActMonitorList[amt.SeqNo] = amt -} -func (u *ActMonitorMgr) Del(seqNo int64) { - delete(u.ActMonitorList, seqNo) -} -func (u *ActMonitorMgr) AddSeqNo() int64 { - u.NowActSeqNo++ - return u.NowActSeqNo -} -func (u *ActMonitorMgr) GetSeqNo(snid int32, platform string) int64 { - for _, v := range u.ActMonitorList { - if v.SnId == snid && v.Platform == platform { - return v.SeqNo - } - } - return -1 -} -func (u *ActMonitorMgr) SendActMonitorEvent(eventType, snid int32, name, platform string, billNo, exchangeCoin int64, - gameSceneName string, state int32) { - logger.Logger.Tracef("SendActMonitorEvent eventType:%v snid:%v name:%v platform:%v billNo:%v exchangeCoin:%v "+ - "gameSceneName:%v state:%v", eventType, snid, name, platform, billNo, exchangeCoin, gameSceneName, state) - //seqNo := u.GetSeqNo(snid, platform) - //if data, ok := u.ActMonitorList[seqNo]; ok { - // if u.IsMarkFlag(eventType, data.MonitorType) { - // var flag int32 - // if eventType == ActState_Login { - // flag = 1 - // } else if eventType == ActState_Exchange { - // flag = 2 - // } else if eventType == ActState_Game { - // flag = 3 - // } - // logger.Logger.Tracef("GenerateActMonitorEvent "+ - // "flag:%v eventType:%v snid:%v name:%v platform:%v billNo:%v exchangeCoin:%v "+ - // "gameSceneName:%v state:%v reMark:%v", - // flag, eventType, snid, name, platform, billNo, exchangeCoin, gameSceneName, state, data.ReMark) - // LogChannelSingleton.WriteMQData(model.GenerateActMonitorEvent(flag, snid, name, platform, - // time.Now().Unix(), billNo, exchangeCoin, gameSceneName, state, data.ReMark)) - // } - //} -} -func init() { - //RegisterParallelLoadFunc("用户行为监控列表", func() error { - // ActMonitorMgrSington.Init() - // return nil - //}) -} diff --git a/worldsrv/etcd.go b/worldsrv/etcd.go index a257d4d..b4d1d28 100644 --- a/worldsrv/etcd.go +++ b/worldsrv/etcd.go @@ -114,6 +114,99 @@ func init() { etcd.Register(etcd.ETCDKEY_NianConfig, webapi.ActivityNianConfig{}, platformConfigEvent) // 红包配置 etcd.Register(etcd.ETCDKEY_REDPACKET, webapi.RedPacketConfig{}, platformConfigEvent) + + WelfareMgrSington.UpdateRedPacket(&webapi.RedPacketConfig{ + Platform: "1", + List: []*webapi.RedPacketInfo{ + { + Id: 1, + On: 1, + StartHMS: 90000, + EndHMS: 100000, + StayTs: 0, + MaxCount: 100, + LessCount: 5, + ItemId: 100001, + TotalNum: 100000, + RedList: []*webapi.RedInfo{ + { + Num: 1, + Rate: 50, + }, + { + Num: 10, + Rate: 10, + }, + { + Num: 20, + Rate: 10, + }, + { + Num: 30, + Rate: 10, + }, + }, + }, + { + Id: 2, + On: 1, + StartHMS: 100000, + EndHMS: 120000, + StayTs: 30, + MaxCount: 10000, + LessCount: 5, + ItemId: 100001, + TotalNum: 100000, + RedList: []*webapi.RedInfo{ + { + Num: 1, + Rate: 50, + }, + { + Num: 10, + Rate: 10, + }, + { + Num: 20, + Rate: 10, + }, + { + Num: 30, + Rate: 10, + }, + }, + }, + { + Id: 3, + On: 1, + StartHMS: 120000, + EndHMS: 180000, + StayTs: 0, + MaxCount: 10000, + LessCount: 5, + ItemId: 100001, + TotalNum: 100000, + RedList: []*webapi.RedInfo{ + { + Num: 1, + Rate: 50, + }, + { + Num: 10, + Rate: 10, + }, + { + Num: 20, + Rate: 10, + }, + { + Num: 30, + Rate: 10, + }, + }, + }, + }, + }, false) } func platformConfigEvent(ctx context.Context, completeKey string, isInit bool, event *clientv3.Event, data interface{}) { diff --git a/worldsrv/welfmgr.go b/worldsrv/welfmgr.go index 3a4b8af..14b9226 100644 --- a/worldsrv/welfmgr.go +++ b/worldsrv/welfmgr.go @@ -3,6 +3,7 @@ package main import ( "fmt" "math" + "math/rand" "slices" "time" @@ -2314,7 +2315,15 @@ func (this *WelfareMgr) GetRedPacket(p *Player, id int64) *welfare.SCRedPacketDr p.SendToClient(int(welfare.SPacketID_PACKET_SCRedPacketDraw), pack) } - playerLimit := this.GetConfig(p.Platform).RedPacketConfig.GetPlayerLimit() + if p.WelfData == nil { + return nil + } + + if p.WelfData.RedPacket[id] == nil { + p.WelfData.RedPacket[id] = &model.RedPacketData{} + } + data := p.WelfData.RedPacket[id] + var cfg *webapi_proto.RedPacketInfo for _, v := range this.GetConfig(p.Platform).RedPacketConfig.GetList() { if v.GetId() == id { @@ -2331,17 +2340,8 @@ func (this *WelfareMgr) GetRedPacket(p *Player, id int64) *welfare.SCRedPacketDr } // 次数限制 - n := 0 - if p.WelfData != nil && p.WelfData.RedPacket != nil { - if _, exist := p.WelfData.RedPacket[id]; exist { - n = p.WelfData.RedPacket[id] - } - } + n := int(data.N) - if playerLimit > 0 && n >= int(playerLimit) { - Send(welfare.OpResultCode_OPRC_NoTimes) - return pack - } if cfg.GetMaxCount() > 0 && cfg.GetMaxCount() <= int64(n) { Send(welfare.OpResultCode_OPRC_NoTimes) return pack @@ -2350,28 +2350,70 @@ func (this *WelfareMgr) GetRedPacket(p *Player, id int64) *welfare.SCRedPacketDr // 余额检查 var reward int64 // 红包奖金 remain := RedPacketMgrInst.GetRemainReward(p.Platform, id) - if remain <= 0 { - // 空奖 - } else { - // 保底计算 - - // 概率抽奖 + var playerRN int32 + playerLimit := this.GetConfig(p.Platform).RedPacketConfig.GetPlayerLimit() + if playerLimit > 0 { + for _, v := range p.WelfData.RedPacket { + playerRN += int32(v.RN) + } } - if p.WelfData != nil { - p.WelfData.RedPacket[id]++ - RedPacketMgrInst.AddUse(p.Platform, id, reward) - if reward > 0 { - BagMgrSingleton.AddItems(&model.AddItemParam{ - Platform: p.Platform, - SnId: p.GetSnId(), - Change: []*model.Item{{ItemId: cfg.GetItemId(), ItemNum: reward}}, - GainWay: common.GainWayRedPacket, - Operator: "system", - Remark: "红包奖励", - }) + // 总奖池没有了或非空奖红包数量已经达到上限 + if remain <= 0 || (playerLimit > 0 && playerRN >= playerLimit) { + // 空奖 + } else { + f := func() { + // 概率抽奖 + rate := 0 + n := rand.Int63n(100) + for _, v := range cfg.GetRedList() { + rate += int(v.GetRate()) + if n < int64(rate) { + reward = v.GetNum() + break + } + } } + if cfg.GetMaxCount() > 0 { + // 保底计算 + if data.RN >= cfg.GetLessCount() { + f() + } else { + sub := cfg.GetLessCount() - data.RN + if cfg.GetMaxCount()-data.N <= sub { + // 必中 + for i := 0; i < 1000; i++ { + f() + if reward > 0 { + break + } + } + } else { + f() + } + } + } else { + f() + } + } + + if remain < reward { + reward = 0 + } + + data.N++ + RedPacketMgrInst.AddUse(p.Platform, id, reward) + if reward > 0 { + data.RN++ + BagMgrSingleton.AddItems(&model.AddItemParam{ + Platform: p.Platform, + SnId: p.GetSnId(), + Change: []*model.Item{{ItemId: cfg.GetItemId(), ItemNum: reward}}, + GainWay: common.GainWayRedPacket, + Operator: "system", + Remark: "红包奖励", + }) } //todo 抽奖记录 @@ -2412,7 +2454,7 @@ func init() { OnPlayerDayChangedFunc: func(p *Player, isLogin, isContinue bool) { if p.WelfData != nil && p.WelfData.RedPacket != nil { - p.WelfData.RedPacket = make(map[int64]int) + p.WelfData.RedPacket = make(map[int64]*model.RedPacketData) } WelfareMgrSington.OnDayChanged(p) },