358 lines
8.4 KiB
Go
358 lines
8.4 KiB
Go
package timer
|
|
|
|
import (
|
|
"context"
|
|
"go_dreamfactory/comm"
|
|
"go_dreamfactory/modules"
|
|
"go_dreamfactory/pb"
|
|
"go_dreamfactory/sys/db"
|
|
"sync"
|
|
"sync/atomic"
|
|
"time"
|
|
|
|
"go_dreamfactory/lego/base"
|
|
"go_dreamfactory/lego/core"
|
|
"go_dreamfactory/lego/sys/cron"
|
|
"go_dreamfactory/lego/sys/log"
|
|
|
|
"go.mongodb.org/mongo-driver/bson"
|
|
"go.mongodb.org/mongo-driver/mongo"
|
|
"go.mongodb.org/mongo-driver/mongo/options"
|
|
)
|
|
|
|
/*
|
|
捕羊大赛 维护服务
|
|
*/
|
|
type ParkourComp struct {
|
|
modules.MCompConfigure
|
|
service base.IRPCXService
|
|
module *Timer
|
|
refresh time.Time //上一次刷新时间
|
|
ulock sync.RWMutex
|
|
users []*pb.DBRaceMember //推荐用户信息
|
|
tlock sync.RWMutex
|
|
teams map[string][]*pb.DBRaceMember
|
|
timerlock int32
|
|
total int32
|
|
}
|
|
|
|
//组件初始化接口
|
|
func (this *ParkourComp) Init(service core.IService, module core.IModule, comp core.IModuleComp, options core.IModuleOptions) (err error) {
|
|
this.MCompConfigure.Init(service, module, comp, options)
|
|
this.service = service.(base.IRPCXService)
|
|
this.module = module.(*Timer)
|
|
this.timerlock = 1
|
|
this.teams = make(map[string][]*pb.DBRaceMember)
|
|
return
|
|
}
|
|
|
|
//自由跨服环境下开启此功能
|
|
func (this *ParkourComp) Start() (err error) {
|
|
err = this.MCompConfigure.Start()
|
|
if db.IsCross() {
|
|
this.refreshlist()
|
|
this.service.RegisterFunctionName(string(comm.RPC_ParkourJoinMatch), this.join)
|
|
this.service.RegisterFunctionName(string(comm.RPC_ParkourCancelMatch), this.cancel)
|
|
if _, err = cron.AddFunc("*/10 * * * * ?", this.match); err != nil {
|
|
this.module.Errorf("cron.AddFunc err:%v", err)
|
|
}
|
|
if _, err = cron.AddFunc("1 1 * * * ?", this.refreshlist); err != nil {
|
|
this.module.Errorf("cron.AddFunc err:%v", err)
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
//刷新推荐列表
|
|
func (this *ParkourComp) refreshlist() {
|
|
var (
|
|
c *mongo.Cursor
|
|
conn *db.DBConn
|
|
err error
|
|
)
|
|
if conn, err = db.Local(); err != nil {
|
|
return
|
|
}
|
|
if c, err = conn.Mgo.Find(core.SqlTable(comm.TableParkour), bson.M{}, options.Find().SetSort(bson.D{{"integral", -1}}).SetSkip(0).SetLimit(100)); err != nil {
|
|
this.module.Errorln(err)
|
|
return
|
|
} else {
|
|
result := make([]*pb.DBParkour, 0, c.RemainingBatchLength())
|
|
for c.Next(context.Background()) {
|
|
tmp := &pb.DBParkour{}
|
|
if err = c.Decode(tmp); err != nil {
|
|
log.Errorln(err)
|
|
} else {
|
|
result = append(result, tmp)
|
|
}
|
|
}
|
|
this.ulock.Lock()
|
|
this.users = this.users[:0]
|
|
for _, v := range result {
|
|
this.users = append(this.users, &pb.DBRaceMember{
|
|
Uid: v.Uid,
|
|
Mount: v.Dfmount,
|
|
Maxhp: 6,
|
|
Currhp: 6,
|
|
Isai: true,
|
|
})
|
|
}
|
|
|
|
this.ulock.Unlock()
|
|
}
|
|
return
|
|
}
|
|
|
|
//加入匹配中
|
|
func (this *ParkourComp) join(ctx context.Context, req *pb.RPCParkourJoinMatchReq, resp *pb.RPCParkourJoinMatchResp) (err error) {
|
|
this.tlock.Lock()
|
|
this.teams[req.Captainid] = req.Member
|
|
this.total += int32(len(req.Member))
|
|
this.tlock.Unlock()
|
|
if this.total >= 6 && atomic.LoadInt32(&this.timerlock) == 1 {
|
|
this.match()
|
|
}
|
|
return
|
|
}
|
|
|
|
//加入匹配中
|
|
func (this *ParkourComp) cancel(ctx context.Context, req *pb.RPCParkourCancelMatchReq, resp *pb.RPCParkourCancelMatchResp) (err error) {
|
|
this.tlock.Lock()
|
|
delete(this.teams, req.Captainid)
|
|
this.tlock.Unlock()
|
|
return
|
|
}
|
|
|
|
//定时匹配处理
|
|
func (this *ParkourComp) match() {
|
|
// this.module.Debug("执行一次匹配!")
|
|
if !atomic.CompareAndSwapInt32(&this.timerlock, 1, 2) { //正在执行,就不要在进来了
|
|
return
|
|
}
|
|
|
|
defer atomic.StoreInt32(&this.timerlock, 1) //执行完毕释放
|
|
|
|
// this.module.Errorf("捕羊大赛 定时匹配,%d", this.total)
|
|
if this.total == 0 {
|
|
return
|
|
}
|
|
|
|
var (
|
|
ok bool
|
|
err error
|
|
users []*pb.DBRaceMember
|
|
teams1 []string = make([]string, 0)
|
|
teams2 []string = make([]string, 0)
|
|
teams3 []string = make([]string, 0)
|
|
left int32 = this.total
|
|
red []string = make([]string, 0)
|
|
rednum int = 0
|
|
reduser []*pb.DBRaceMember = make([]*pb.DBRaceMember, 0)
|
|
bule []string = make([]string, 0)
|
|
bulenum int = 0
|
|
buleuser []*pb.DBRaceMember = make([]*pb.DBRaceMember, 0)
|
|
order bool = false
|
|
)
|
|
this.tlock.Lock()
|
|
for k, v := range this.teams {
|
|
if len(v) == 1 {
|
|
teams1 = append(teams1, k)
|
|
} else if len(v) == 2 {
|
|
teams2 = append(teams2, k)
|
|
} else {
|
|
teams3 = append(teams3, k)
|
|
}
|
|
}
|
|
this.tlock.Unlock()
|
|
|
|
this.ulock.RLock()
|
|
users = make([]*pb.DBRaceMember, 0, len(this.users))
|
|
for _, v1 := range this.users {
|
|
ok = false
|
|
for _, v := range this.teams {
|
|
for _, v2 := range v {
|
|
if v1.Uid == v2.Uid {
|
|
ok = true
|
|
}
|
|
}
|
|
}
|
|
if !ok { //过滤掉已存在的人员
|
|
users = append(users, v1)
|
|
}
|
|
}
|
|
this.ulock.RUnlock()
|
|
|
|
if len(users)+int(this.total) < 6 { //人员不足
|
|
return
|
|
}
|
|
|
|
var fn = func() {
|
|
if order {
|
|
//找红队
|
|
if rednum <= 0 && len(teams3) > 0 {
|
|
red = append(red, teams3[0])
|
|
teams3 = teams3[1:]
|
|
rednum = 3
|
|
left -= 3
|
|
} else if rednum <= 1 && len(teams2) > 0 {
|
|
red = append(red, teams2[0])
|
|
teams2 = teams2[1:]
|
|
rednum = 2
|
|
left -= 2
|
|
} else if rednum <= 2 && len(teams1) > 0 {
|
|
red = append(red, teams1[0])
|
|
teams1 = teams1[1:]
|
|
rednum = 1
|
|
left -= 1
|
|
}
|
|
|
|
//找蓝队
|
|
if bulenum <= 0 && len(teams3) > 0 {
|
|
bule = append(bule, teams3[0])
|
|
teams3 = teams3[1:]
|
|
bulenum = 3
|
|
left -= 3
|
|
} else if bulenum <= 1 && len(teams2) > 0 {
|
|
bule = append(bule, teams2[0])
|
|
teams2 = teams2[1:]
|
|
bulenum = 2
|
|
left -= 2
|
|
} else if bulenum <= 2 && len(teams1) > 0 {
|
|
bule = append(bule, teams1[0])
|
|
teams1 = teams1[1:]
|
|
bulenum = 1
|
|
left -= 1
|
|
}
|
|
} else {
|
|
//找蓝队
|
|
if bulenum <= 0 && len(teams3) > 0 {
|
|
bule = append(bule, teams3[0])
|
|
teams3 = teams3[1:]
|
|
bulenum = 3
|
|
left -= 3
|
|
} else if bulenum <= 1 && len(teams2) > 0 {
|
|
bule = append(bule, teams2[0])
|
|
teams2 = teams2[1:]
|
|
bulenum = 2
|
|
left -= 2
|
|
} else if bulenum <= 2 && len(teams1) > 0 {
|
|
bule = append(bule, teams1[0])
|
|
teams1 = teams1[1:]
|
|
bulenum = 1
|
|
left -= 1
|
|
}
|
|
//找红队
|
|
if rednum <= 0 && len(teams3) > 0 {
|
|
red = append(red, teams3[0])
|
|
teams3 = teams3[1:]
|
|
rednum = 3
|
|
left -= 3
|
|
} else if rednum <= 1 && len(teams2) > 0 {
|
|
red = append(red, teams2[0])
|
|
teams2 = teams2[1:]
|
|
rednum = 2
|
|
left -= 2
|
|
} else if rednum <= 2 && len(teams1) > 0 {
|
|
red = append(red, teams1[0])
|
|
teams1 = teams1[1:]
|
|
rednum = 1
|
|
left -= 1
|
|
}
|
|
|
|
}
|
|
order = !order
|
|
}
|
|
fn()
|
|
if (rednum < 3 || bulenum < 3) && left > 0 {
|
|
_lt := left
|
|
fn()
|
|
if left < _lt {
|
|
fn() //做多执行三次即可
|
|
}
|
|
}
|
|
this.tlock.RLock()
|
|
for _, v := range red {
|
|
reduser = append(reduser, this.teams[v]...)
|
|
}
|
|
for _, v := range bule {
|
|
buleuser = append(buleuser, this.teams[v]...)
|
|
}
|
|
this.tlock.RLock()
|
|
|
|
if len(users)+rednum+bulenum < 6 {
|
|
return
|
|
}
|
|
|
|
//补充人员
|
|
if len(reduser) < 3 {
|
|
n := len(reduser)
|
|
reduser = append(reduser, users[0:(3-len(reduser))]...)
|
|
users = users[(3 - n):]
|
|
for _, v := range reduser[rednum:3] {
|
|
if v.Name == "" { //同步用户数据
|
|
if user, err := this.getuser(v.Uid); err != nil {
|
|
this.module.Errorln(err)
|
|
return
|
|
} else {
|
|
v.Name = user.Name
|
|
v.Avatar = user.Avatar
|
|
v.Lv = user.Lv
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if len(buleuser) < 3 {
|
|
n := len(buleuser)
|
|
buleuser = append(buleuser, users[0:(3-len(buleuser))]...)
|
|
users = users[(3 - n):]
|
|
for _, v := range buleuser[bulenum:3] {
|
|
if v.Name == "" { //同步用户数据
|
|
if user, err := this.getuser(v.Uid); err != nil {
|
|
this.module.Errorln(err)
|
|
return
|
|
} else {
|
|
v.Name = user.Name
|
|
v.Avatar = user.Avatar
|
|
v.Lv = user.Lv
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
ctx, _ := context.WithTimeout(context.Background(), time.Second*2)
|
|
if err = this.service.RpcCall(ctx,
|
|
comm.Service_Worker,
|
|
string(comm.RPC_ParkourMatchSucc),
|
|
&pb.RPCParkourMatchSuccReq{Red: reduser, Bule: buleuser},
|
|
&pb.RPCParkourMatchSuccResp{},
|
|
); err != nil {
|
|
this.module.Errorln(err)
|
|
return
|
|
}
|
|
this.tlock.Lock()
|
|
for _, v := range red {
|
|
delete(this.teams, v)
|
|
}
|
|
for _, v := range bule {
|
|
delete(this.teams, v)
|
|
}
|
|
this.total -= int32(rednum)
|
|
this.total -= int32(bulenum)
|
|
this.tlock.Lock()
|
|
}
|
|
|
|
// 从远程库查询用户
|
|
func (this *ParkourComp) getuser(uid string) (user *pb.DBUser, err error) {
|
|
var (
|
|
model *db.DBModel
|
|
)
|
|
if model, err = this.module.getDBModelByUid(uid, comm.TableUser); err != nil {
|
|
return
|
|
}
|
|
user = &pb.DBUser{}
|
|
if err = model.Get(uid, user); err != nil {
|
|
this.module.Errorln(err)
|
|
}
|
|
return
|
|
}
|