go_dreamfactory/modules/sociaty/model_sociatyboss.go
2023-01-13 20:33:21 +08:00

402 lines
10 KiB
Go

package sociaty
import (
"context"
"go_dreamfactory/comm"
"go_dreamfactory/lego/core"
"go_dreamfactory/lego/sys/log"
rn "go_dreamfactory/lego/sys/redis"
"go_dreamfactory/lego/sys/redis/pipe"
"go_dreamfactory/modules"
"go_dreamfactory/pb"
"go_dreamfactory/sys/configure"
"go_dreamfactory/utils"
"sort"
"time"
"github.com/go-redis/redis/v8"
"go.mongodb.org/mongo-driver/mongo"
)
var (
BOSS_SPORTS = "sports"
BOSS_PLAYERS = "players"
SPORTS_HOUR = 3 * 24 //赛季周期
)
type ModelSociatyBoss struct {
modules.MCompModel
moduleSociaty *Sociaty
service core.IService
}
func (this *ModelSociatyBoss) Init(service core.IService, module core.IModule, comp core.IModuleComp, options core.IModuleOptions) (err error) {
this.TableName = comm.TableSociatyBoss
err = this.MCompModel.Init(service, module, comp, options)
this.moduleSociaty = module.(*Sociaty)
this.service = service
return
}
// 初始化赛季
func (s *ModelSociatyBoss) initSports() error {
ticker := time.NewTicker(time.Second)
sports := &pb.DBSociatyBossSports{}
if err := s.Get(BOSS_SPORTS, sports); err != nil {
if err == rn.RedisNil || err == mongo.ErrNoDocuments {
sports.EndTime, sports.SettlementTime = s.sportsTime()
if err2 := s.Add(BOSS_SPORTS, sports); err2 != nil {
return err2
}
} else {
s.moduleSociaty.Errorln(err)
return err
}
}
go func() {
for {
select {
case <-ticker.C:
now := configure.Now()
//触发结算
if now.Unix() >= sports.SettlementTime {
_, sports.SettlementTime = s.sportsTime()
s.settlement()
s.moduleSociaty.Debugln("更新赛季结算时间:" + utils.FormatStr(sports.SettlementTime, ""))
}
if now.Unix() >= sports.EndTime {
// 更新下一赛季周期结束时间
sports.EndTime, sports.SettlementTime = s.sportsTime()
update := map[string]interface{}{
"endTime": sports.EndTime,
"settlementTime": sports.SettlementTime,
}
if err := s.Change(BOSS_SPORTS, update); err != nil {
s.moduleSociaty.Errorln("Failed to change")
return
}
//归档前赛季数据、清理前赛季玩家
s.reset()
s.moduleSociaty.Debugln("更新赛季周期时间:" + utils.FormatStr(sports.EndTime, ""))
}
}
}
}()
return nil
}
// 获取赛季数据
func (s *ModelSociatyBoss) getSociatyBossSports() *pb.DBSociatyBossSports {
sports := &pb.DBSociatyBossSports{}
if err := s.Get(BOSS_SPORTS, sports); err != nil {
s.moduleSociaty.Errorln(err)
return nil
}
return sports
}
// 赛季时间
func (s *ModelSociatyBoss) sportsTime() (t1, t2 int64) {
now := configure.Now()
end1 := now.Add(time.Duration(SPORTS_HOUR) * time.Hour) //测试时单位分钟 else Hour
h, _ := time.ParseDuration("-1h") //测试时2m else -1h
end2 := end1.Add(h)
return end1.Unix(), end2.Unix()
}
// 公会BOSS是否开始
func (s *ModelSociatyBoss) sportsIsStarted() bool {
sports := s.getSociatyBossSports()
if sports == nil {
return false
}
if sports.EndTime == 0 {
return false
} else {
now := configure.Now().Unix()
end := sports.SettlementTime
if now < end {
return true
}
}
return false
}
// 公会BOSS是否结束
func (s *ModelSociatyBoss) sportsIsFinished() bool {
sports := s.getSociatyBossSports()
if sports == nil {
return false
}
if sports.EndTime == 0 {
return true
} else {
now := configure.Now().Unix()
end := sports.SettlementTime
if now > end && now < sports.EndTime {
return true
}
}
return false
}
// 设置阵容
func (s *ModelSociatyBoss) setFormation(sociaty *pb.DBSociaty, uid string, teams map[int32]*pb.ChallengeTeam) error {
if !s.moduleSociaty.modelSociaty.isMember(uid, sociaty) {
return comm.NewCustomError(pb.ErrorCode_SociatyBelongTo)
}
for _, m := range sociaty.Members {
if m.Uid == uid {
m.Teams = teams
}
}
update := map[string]interface{}{
"members": sociaty.Members,
}
return s.moduleSociaty.modelSociaty.updateSociaty(sociaty.Id, update)
}
//挑战开始
func (s *ModelSociatyBoss) challengestart(session comm.IUserSession, sociaty *pb.DBSociaty) error {
//组装阵容数据
var formations []*pb.BattleFormation
m := s.moduleSociaty.modelSociaty.getMemberInfo(sociaty, session.GetUserId())
for _, v := range m.Teams {
formations = append(formations, v.Formation)
}
if len(formations) == 0 {
return comm.NewCustomError(pb.ErrorCode_SociatyNoFormation)
}
iBattle, err := s.service.GetModule(comm.ModuleBattle)
if err != nil {
return err
}
if b, y := iBattle.(comm.IBattle); y {
if code, _ := b.CreatePvbBattle(session, &pb.BattlePVBReq{
Ptype: pb.PlayType_sociaty,
Title: "公会BOSS",
Format: formations,
}); code != pb.ErrorCode_Success {
return comm.NewCustomError(code)
}
}
return nil
}
// 挑战结束
func (s *ModelSociatyBoss) challengefinish(sociaty *pb.DBSociaty, uid string, report *pb.BattleReport) error {
// BOSS无伤害
if report.Harm == 0 {
return nil
}
//保存挑战记录
if err := s.addChallengeRecord(uid, sociaty.Id, &pb.DBSociatyBossRecord{
Uid: uid,
SociatyId: sociaty.Id,
Integral: s.transIntegral(report.Harm),
Duration: report.Costtime,
Rtime: configure.Now().Unix(),
}); err != nil {
return err
}
return nil
}
// 挑战记录 作为阵容推荐的依据;
func (s *ModelSociatyBoss) addChallengeRecord(uid, sociatyId string, record *pb.DBSociatyBossRecord) error {
if err := s.AddList(uid, sociatyId, record); err != nil {
return err
}
return s.addUserWithSports(uid, sociatyId)
}
// 记录参赛的玩家
func (s *ModelSociatyBoss) addUserWithSports(uid, sociatyId string) error {
record := &pb.DBSociatyBossUser{
Uid: uid,
SociatyId: sociatyId,
}
return s.moduleSociaty.modelSociatyBoss.AddList(BOSS_PLAYERS, uid, record)
}
// 记入排行
func (s *ModelSociatyBoss) addRank(uid string, integral int64) error {
var (
pipe *pipe.RedisPipe = s.Redis.RedisPipe(context.TODO())
m *redis.Z
)
m = &redis.Z{Score: float64(integral), Member: uid}
if cmd := pipe.ZAdd(s.TableName, m); cmd != nil {
_, err := cmd.Result()
if err != nil {
return err
}
}
if _, err := pipe.Exec(); err != nil {
return err
}
return nil
}
// 伤害转换积分
func (s *ModelSociatyBoss) transIntegral(harm int32) int64 {
return int64(harm)
}
// 查询排行榜
func (this *ModelSociatyBoss) queryRankUid(count int64) (ranks []string, err error) {
var (
result []string
)
if result, err = this.DBModel.Redis.ZRevRange(this.TableName, 0, count).Result(); err != nil {
return
}
ranks = make([]string, 0)
for i := 0; i < len(result); i += 1 {
ranks = append(ranks, result[i])
}
return
}
// 取积分
func (this *ModelSociatyBoss) getScoreByUid(uid string) int64 {
result, err := this.DBModel.Redis.ZScore(this.TableName, uid)
if err != nil {
return 0
}
return int64(result)
}
// 取排名
func (this *ModelSociatyBoss) getRankingByUid(uid string) int64 {
result, err := this.DBModel.Redis.ZRevRank(this.TableName, uid)
if err != nil {
return 0
}
return (result + 1)
}
// 排行榜
func (s *ModelSociatyBoss) rank(sociatyName string, rankType int32) (res []*pb.SociatyRankInfo) {
var rankCount int64
switch rankType {
case 1: //个人
rankCount = 1000
case 2: //成员
rankCount = 50
case 3: //公会
rankCount = 50
}
// 所有排行记录
rankUids, err := s.queryRankUid(rankCount)
if err != nil {
return nil
}
for _, uid := range rankUids {
imodule, err := s.service.GetModule(comm.ModuleUser)
if err != nil {
return nil
}
if iuser, ok := imodule.(comm.IUser); ok {
if user := iuser.GetUser(uid); user != nil && user.Uid != "" {
res = append(res, &pb.SociatyRankInfo{
SociatyName: sociatyName,
Name: user.Name,
Head: user.Avatar,
Lv: user.Lv,
Ranking: s.getRankingByUid(user.Uid),
Integral: s.getScoreByUid(user.Uid),
})
}
}
}
return nil
}
// 公会BOSS重置数据
func (s *ModelSociatyBoss) reset() error {
s.moduleSociaty.Debugln("赛季重置")
// 清理前赛季玩家
var players []*pb.DBSociatyBossUser
if err := s.GetList(BOSS_PLAYERS, &players); err != nil {
return err
}
for _, v := range players {
if err := s.DelListlds(BOSS_PLAYERS, v.Uid); err != nil {
s.moduleSociaty.Error("清理玩家赛事记录", log.Field{Key: "uid", Value: v.Uid}, log.Field{Key: "err", Value: err.Error()})
}
// 归档前赛季数据
update := map[string]interface{}{
"status": 1, //归档
}
if err := s.ChangeList(v.Uid, v.SociatyId, update); err != nil {
s.moduleSociaty.Error("归档玩家赛事记录", log.Field{Key: "uid", Value: v.Uid}, log.Field{Key: "err", Value: err.Error()})
}
}
return nil
}
// 赛季结算
func (s *ModelSociatyBoss) settlement() error {
s.moduleSociaty.Debugln("赛季结算")
start := time.Now()
var players []*pb.DBSociatyBossUser
// 查询所有参赛玩家
if err := s.GetList(BOSS_PLAYERS, &players); err != nil {
return err
}
// 计算玩家的赛季积分
for _, r := range players {
s.moduleSociaty.Debugln(r.Uid)
var record []*pb.DBSociatyBossRecord
if err := s.GetListObj(r.Uid, r.SociatyId, &record); err != nil {
s.moduleSociaty.Error("查询玩家赛事记录", log.Field{Key: "uid", Value: r.Uid}, log.Field{Key: "err", Value: err.Error()})
continue
}
//排序-倒叙
sort.SliceStable(record, func(i, j int) bool {
return record[i].Integral > record[j].Integral
})
var total int64 //当前赛季总积分
var highScore []int64 //暂存玩家积分
for i, v := range record {
highScore = append(highScore, v.Integral)
total += v.Integral
if i > 2 {
break
}
}
// 更新玩家赛季信息
update := map[string]interface{}{
"total": total,
"integrals": highScore,
}
if err := s.ChangeList(BOSS_PLAYERS, r.Uid, update); err != nil {
s.moduleSociaty.Error("更新玩家赛事信息", log.Field{Key: "uid", Value: r.Uid}, log.Field{Key: "err", Value: err.Error()})
continue
}
//将玩家积分加入排行榜
s.addRank(r.Uid, total)
s.moduleSociaty.Debugln("耗时:", time.Since(start))
}
return nil
}