package pagoda import ( "context" "fmt" "go_dreamfactory/comm" "go_dreamfactory/lego/core" "go_dreamfactory/lego/sys/log" //"go_dreamfactory/lego/sys/redis" "go_dreamfactory/lego/sys/redis/pipe" "go_dreamfactory/modules" "go_dreamfactory/pb" "go_dreamfactory/sys/configure" "go_dreamfactory/sys/db" "sort" "github.com/go-redis/redis/v8" "go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/bson/primitive" "go.mongodb.org/mongo-driver/mongo/options" ) var floorRankKey = "pagoda:floor" type ModelRank struct { modules.MCompModel modulePagoda *Pagoda } func (this *ModelRank) Init(service core.IService, module core.IModule, comp core.IModuleComp, options core.IModuleOptions) (err error) { this.TableName = comm.TablePagodaRecord err = this.MCompModel.Init(service, module, comp, options) this.modulePagoda = module.(*Pagoda) return } func (this *ModelRank) AddRank(uId string, data *pb.DBPagodaRecord) (err error) { if err = this.Add(uId, data); err != nil { //this.Errorf("err:%v", err) return } return nil } //获取用户通过扩展表 // func (this *ModelRank) GetUserRandData(uid string) (result *pb.DBPagodaRecord, err error) { // result = &pb.DBPagodaRecord{} // if err = this.Get(uid, result); err != nil && redis.RedisNil != err { // return // } // err = nil // return result, err // } func (this *ModelRank) ChangeUserRank(uid string, value map[string]interface{}) (err error) { if len(value) == 0 { return nil } return this.Change(uid, value) } func (this *ModelRank) GetRankData() (data []*pb.DBPagodaRecord, err error) { data = make([]*pb.DBPagodaRecord, 0) if conn, err := db.Cross(); err == nil { err = conn.Redis.LRange(comm.TableSeasonRankList, 0, -1, &data) } //err = this.Redis.LRange(comm.TablePagodaRankList, 0, -1, &data) return } func (this *ModelRank) getPagodaRankList(uid string) []*pb.DBPagodaRecord { pagodaRank := make([]*pb.DBPagodaRecord, 0) err := this.GetList(uid, &pagodaRank) if err != nil { return nil } return pagodaRank } // 插入新的排行数据 func (this *ModelRank) addPagodaRankList(session comm.IUserSession, data *pb.DBPagoda, Leadpos int32, line []*pb.LineUp, costTime int32) { uid := session.GetUserId() var ( dbModel *db.DBModel err error ) userinfo := this.modulePagoda.ModuleUser.GetUser(session.GetUserId()) new := &pb.DBPagodaRecord{ Id: primitive.NewObjectID().Hex(), Uid: session.GetUserId(), PagodaId: data.PagodaId, Type: data.Type, Nickname: userinfo.Name, Icon: "", // 暂时没有数据 Lv: userinfo.Lv, Leadpos: Leadpos, Line: line, CostTime: costTime, } if this.modulePagoda.IsCross() { if dbModel, err = this.modulePagoda.GetDBNoduleByUid(uid, this.TableName, this.Expired); err != nil { this.modulePagoda.Errorln(err) } else { if err = dbModel.AddList(session.GetUserId(), new.Id, new); err != nil { this.modulePagoda.Errorf("err:%v", err) } } } else { if err := this.AddList(session.GetUserId(), new.Id, new); err != nil { this.modulePagoda.Errorf("err:%v", err) } } // 查询本层是否上榜 rankData, ilen, err1 := this.GetFloorLastRankData(data.PagodaId, dbModel) if err1 != nil { if rankData.CostTime < costTime || ilen < comm.MaxRankNum { this.ChangeFloorRankList(session, data.PagodaId, new, dbModel) } } return } // 读取某一层排行数据 func (this *ModelRank) GetFloorRankList(floor int32) (result []*pb.DBPagodaRecord, err error) { key := fmt.Sprintf("%s-%d-rank", floorRankKey, floor) temp := make([]*pb.DBPagodaRecord, 0) if err = this.Redis.LRange(key, 0, -1, &temp); err != nil { this.modulePagoda.Errorf("err:%v", err) return } result = make([]*pb.DBPagodaRecord, len(temp)) for n, v := range temp { result[n] = v //n++ } return } // 获取排行榜最后一个元素 func (this *ModelRank) GetFloorLastRankData(floor int32, dbModel *db.DBModel) (curData *pb.DBPagodaRecord, len int, err error) { key := fmt.Sprintf("%s-%d-rank", floorRankKey, floor) len, err = dbModel.Redis.Llen(key) curData = &pb.DBPagodaRecord{} if dbModel.Redis.Lindex(key, -1, curData); err != nil { this.modulePagoda.Errorf("err:%v", err) return } if curData == nil { data := make([]interface{}, 0) // options.Find().SetLimit(comm.MaxRankList) if _data, err := dbModel.DB.Find(comm.TableSeasonRecord, bson.M{"pagodaId": floor}, options.Find().SetSort(bson.M{"pagodaId": -1}).SetLimit(comm.MaxRankList)); err == nil { for _data.Next(context.TODO()) { temp := &pb.DBPagodaRecord{} if err = _data.Decode(temp); err == nil { data = append(data, temp) curData = temp } } } err := dbModel.Redis.RPush(key, data...) if err == nil { this.modulePagoda.Errorf("rpush failed :%v", err) } } return } // 修改某一层排行数据 func (this *ModelRank) ChangeFloorRankList(session comm.IUserSession, floor int32, curData *pb.DBPagodaRecord, dbModel *db.DBModel) (err error) { key := fmt.Sprintf("%s-%d-rank", floorRankKey, floor) lockkey := fmt.Sprintf("%s-%d-lock", floorRankKey, floor) dbModel.Redis.Lock(lockkey, configure.Now().Second()*5) defer dbModel.Redis.UnLock(lockkey) if dbModel.Redis.RPush(key, curData); err != nil { this.modulePagoda.Errorf("err:%v", err) return } temp := make([]*pb.DBPagodaRecord, 0) if err = dbModel.Redis.LRange(key, 0, -1, &temp); err != nil { this.modulePagoda.Errorf("err:%v", err) return } // 排序 sort.SliceStable(temp, func(i, j int) bool { return temp[i].CostTime < temp[j].CostTime }) iLne := len(temp) if dbModel.Redis.RPush(key, temp); err != nil { this.modulePagoda.Errorf("err:%v", err) return } if iLne > comm.MaxRankNum { iLne = comm.MaxRankNum } err = dbModel.Redis.Ltrim(key, -1*iLne, -1) //对一个列表进行修剪 if err != nil { log.Errorf("delete failed") } return } func (this *ModelRank) getPagodaRankListByFloorid(uid string, floorid int32) *pb.DBPagodaRecord { pagodaRank := make([]*pb.DBPagodaRecord, 0) err := this.GetList(uid, &pagodaRank) if err != nil { return nil } for _, v := range pagodaRank { if v.PagodaId == floorid { return v } } return nil } //设置本服 func (this *ModelRank) SetNormalPagodaRankList(tableName string, score int32, uid string) { var ( pipe *pipe.RedisPipe = this.DBModel.Redis.RedisPipe(context.TODO()) menbers *redis.Z ) menbers = &redis.Z{Score: float64(score), Member: uid} if cmd := pipe.ZAdd(tableName, menbers); cmd != nil { dock, err1 := cmd.Result() if err1 != nil { this.modulePagoda.Errorln(dock, err1) } } if _, err := pipe.Exec(); err != nil { this.modulePagoda.Errorln(err) return } } func (this *ModelRank) seasonSettlement() { list := this.modulePagoda.configure.GetPagodaSeasonReward() if list == nil { return } rankReward := this.modulePagoda.configure.GetPagodaSeasonReward() if rankReward == nil { return } if !db.IsCross() { if conn, err := db.Cross(); err == nil { var ( pipe *pipe.RedisPipe = conn.Redis.RedisPipe(context.TODO()) Items []*pb.UserAssets ) rd := pipe.ZRange("pagodaSeasonRank", 0, 50) if _, err = pipe.Exec(); err != nil { this.modulePagoda.Errorln(err) return } uids := rd.Val() for index, uid := range uids { Items = make([]*pb.UserAssets, 0) //TO 排名配置 for _, v := range rankReward { if len(v.Ranking) != 2 { continue } if index >= int(v.Ranking[0]) && index <= int(v.Ranking[1]) { for _, v1 := range v.Reward { Items = append(Items, &pb.UserAssets{ A: v1.A, T: v1.T, N: v1.N, }) } this.modulePagoda.mail.SendNewMail(&pb.DBMailData{ CreateTime: uint64(configure.Now().Unix()), Items: Items, }, uid) break } } } } } }