package dispatch import ( "go_dreamfactory/comm" "go_dreamfactory/lego/core" "go_dreamfactory/lego/sys/log" "go_dreamfactory/modules" "go_dreamfactory/pb" "go_dreamfactory/sys/configure" "go_dreamfactory/utils" "go.mongodb.org/mongo-driver/mongo" "go.mongodb.org/mongo-driver/x/bsonx" ) type modelDispatch struct { modules.MCompModel module *Dispatch service core.IService } func (this *modelDispatch) Init(service core.IService, module core.IModule, comp core.IModuleComp, options core.IModuleOptions) (err error) { err = this.MCompModel.Init(service, module, comp, options) this.TableName = comm.TableDispatch this.module = module.(*Dispatch) this.service = service this.DB.CreateIndex(core.SqlTable(this.TableName), mongo.IndexModel{ Keys: bsonx.Doc{{Key: "_id", Value: bsonx.Int32(1)}}, }) return } // 初始玩家公告 // Deprecated func (this *modelDispatch) initDispatch(uid string, dispatch *pb.DBDispatch) *pb.Noticeboard { tasks, err := this.taskRandom(uid, dispatch) if err != nil { return nil } if len(tasks) == 0 { return nil } freeCount := this.module.configure.GetGlobalConf().DispatchFreecheck ticketCount := this.module.configure.GetGlobalConf().DispatchNumoftimes dis := &pb.DBDispatch{ Uid: uid, Ticket: ticketCount, Nb: &pb.Noticeboard{ Lv: 1, //公告初始升级 FreeCount: freeCount, Tasks: tasks, UpdateTime: configure.Now().Unix(), }, } if err := this.Add(uid, dis); err != nil { return nil } return dis.Nb } // 获取派遣数据 func (this *modelDispatch) getDBDispatch(uid string) (dis *pb.DBDispatch) { dis = &pb.DBDispatch{} if err := this.Get(uid, dis); err != nil { if err == mongo.ErrNoDocuments { dis.Uid = uid dis.Nb = &pb.Noticeboard{ Lv: 1, } if err := this.Add(uid, dis); err != nil { return } } return } return } // 获取任务权重数据 func (this *modelDispatch) getTasksWeight(uid string, noticeLv int32) []int32 { dispatch := this.getDBDispatch(uid) if dispatch == nil { return []int32{} } if dispatch.Nb == nil { return []int32{} } conf, err := this.module.configure.getDispatchLvConf(noticeLv) if err != nil || conf == nil { this.module.Error("配置不存在", log.Field{Key: "error", Value: err}) return []int32{} } items := make([]*comm.WeightItem, 0) for i, v := range conf.Probability { items = append(items, &comm.WeightItem{Id: (i + 1), Weight: int(v)}) } wr := comm.NewWeightedRandom(items) //任务类型 var taskType int if c := wr.Pick(); c != nil { taskType = c.Id.(int) } confList := this.module.configure.getDispatchListConf() var tIds []int32 for _, v := range confList { if int(v.Type) == taskType { tIds = append(tIds, v.Id) } } return tIds } // 随机任务 func (this *modelDispatch) taskRandom(uid string, dispatch *pb.DBDispatch) (tasks []*pb.DispatchTask, err error) { if dispatch.Nb.Lv == 0 { dispatch.Nb.Lv = 1 } conf, err := this.module.configure.getDispatchLvConf(dispatch.Nb.Lv) if err != nil || conf == nil { return nil, err } var items []*comm.WeightItem for i, v := range conf.Probability { items = append(items, &comm.WeightItem{Id: (i + 1), Weight: int(v)}) } wr := comm.NewWeightedRandom(items) //任务类型 var taskType int if c := wr.Pick(); c != nil { taskType = c.Id.(int) } confList := this.module.configure.getDispatchListConf() var tIds []int32 for _, v := range confList { if int(v.Type) == taskType { tIds = append(tIds, v.Id) } } //判断随机数量 var n int n = len(dispatch.Nb.Tasks) if n == 0 { //随机6个任务 ids := utils.RandomNumbers(1, len(tIds), 6) for _, id := range ids { taskConf, err := this.module.configure.getDispatchTaskConf(int32(id)) if err != nil { continue } //公告持续截至时间 duration := configure.Now().Unix() + int64(taskConf.Taskcd) tasks = append(tasks, &pb.DispatchTask{ TaskId: int32(id), Duration: duration, }) } } else { tasks = dispatch.Nb.Tasks var randCount int for i := 0; i < len(tasks); i++ { //只随机未接取的任务 if tasks[i].Status == 0 { //删除 tasks = append(tasks[:i], tasks[i+1:]...) i-- randCount++ } } //追加随机 for i := 0; i < randCount; i++ { task := this.addRandomTask(uid, dispatch) if task != nil { tasks = append(tasks, task) } } } return } func (this *modelDispatch) addRandomTask(uid string, dispatch *pb.DBDispatch) *pb.DispatchTask { randomTaskIds := this.getTasksWeight(uid, dispatch.Nb.Lv) if len(randomTaskIds) == 0 { return nil } //追加一条随机任务 ids := utils.RandomNumbers(1, len(randomTaskIds), 1) if len(ids) <= 0 { return nil } taskId := ids[0] taskConf, err := this.module.configure.getDispatchTaskConf(int32(taskId)) if err != nil { return nil } //公告持续截至时间 duration := configure.Now().Unix() + int64(taskConf.Taskcd) return &pb.DispatchTask{ TaskId: int32(taskId), Duration: duration, } } // 替换指定的已完成任务 func (this *modelDispatch) replaceTask(uid string, taskId int32, dispatch *pb.DBDispatch) (tasks []*pb.DispatchTask, oldTask *pb.DispatchTask) { tasks = dispatch.Nb.Tasks var randCount int for i := 0; i < len(tasks); i++ { //替换状态是完成的任务 if tasks[i].Status == 2 { if taskId != tasks[i].TaskId { continue } oldTask = tasks[i] //删除 tasks = append(tasks[:i], tasks[i+1:]...) i-- randCount++ break } } if randCount > 0 { task := this.addRandomTask(uid, dispatch) if task != nil { tasks = append(tasks, task) } } return } // 替换所有完成的任务 func (this *modelDispatch) replaceFinishedTask(uid string, dispatch *pb.DBDispatch) (tasks []*pb.DispatchTask, oldtasks []*pb.DispatchTask) { var randCount int tmp := dispatch.Nb.Tasks for i := 0; i < len(tmp); i++ { //替换状态是完成的任务 if tmp[i].Status == 2 { //删除 oldtasks = append(oldtasks, tmp[i]) dispatch.Nb.Tasks = append(dispatch.Nb.Tasks[:i], dispatch.Nb.Tasks[i+1:]...) i-- randCount++ } else { tasks = append(tasks, tmp[i]) } } for i := 0; i < randCount; i++ { task := this.addRandomTask(uid, dispatch) if task != nil { tasks = append(tasks, task) } } return } // 验证英雄的条件 func (this *modelDispatch) validHeroCond(uid string, taskId int32, heroId string) (ok1, ok2 bool, err error) { //校验英雄是否已被派遣 dispatch := this.getDBDispatch(uid) if dispatch == nil { return } for _, v := range dispatch.Nb.Tasks { for _, h := range v.HeroIds { if h == heroId { err = comm.NewCustomError(pb.ErrorCode_DispatchHeroAssigned) return } } } //taskConf gd, err := this.module.configure.getDispatchTaskConf(taskId) if err != nil { return } //获取英雄信息 hero, code := this.module.ModuleHero.GetHeroByObjID(uid, heroId) if code == pb.ErrorCode_Success && hero != nil { for _, v := range gd.Taskreq { switch v.Key { case 1: //校验英雄的基础条件 if hero.Lv >= v.Param { ok1 = true } } } for _, v := range gd.Taskreqex { switch v.Key { case 2: //校验英雄的额外要求 if hero.Star >= v.Param { ok2 = true } } } } return } // 派遣 func (this *modelDispatch) dispatch(uid string, taskId int32, heroIds []string, disp *pb.DBDispatch) error { var flag bool //额外条件是否满足 for _, heroId := range heroIds { if ok1, ok2, err := this.validHeroCond(uid, taskId, heroId); err == nil { if !ok1 { return comm.NewCustomError(pb.ErrorCode_DispatchHeroNoReached) //基础条件未满足 } if ok2 { flag = true } } else { return err } } for _, v := range disp.Nb.Tasks { if v.TaskId == taskId && v.Status == 0 { v.HeroIds = heroIds if v.Duration <= configure.Now().Unix() { return comm.NewCustomError(pb.ErrorCode_DispatchTaskExpired) } else { if v.LeftTime >= configure.Now().Unix() { v.Status = 2 //任务结束 v.Exaward = flag } else { taskConf, err := this.module.configure.getDispatchTaskConf(v.TaskId) if err != nil { continue } v.Status = 1 //任务进行中 leftTime := configure.Now().Unix() + int64(taskConf.Tasktime) v.LeftTime = leftTime v.Exaward = flag } } } } update := map[string]interface{}{ "nb": disp.Nb, } if err := this.Change(uid, update); err != nil { return err } return nil } // 更新免费刷新次数 func (this *modelDispatch) updateFreeCount(uid string, noticeboard *pb.Noticeboard) error { if noticeboard.FreeCount <= 0 { return comm.NewCustomError(pb.ErrorCode_DispatchNoFree) } noticeboard.FreeCount-- update := map[string]interface{}{ "nb": noticeboard, } return this.Change(uid, update) } // 更新刷新次数 func (this *modelDispatch) updateRefreshCount(uid string, noticeboard *pb.Noticeboard) error { noticeboard.RefreshCount++ update := map[string]interface{}{ "nb": noticeboard, } return this.Change(uid, update) } // 更新公告任务 func (this *modelDispatch) updateTasks(uid string, noticeboard *pb.Noticeboard, tasks []*pb.DispatchTask) error { noticeboard.Tasks = tasks update := map[string]interface{}{ "nb": noticeboard, } return this.Change(uid, update) } // 更新公告栏任务 func (this *modelDispatch) updateNotice(uid string, dispatch *pb.DBDispatch) error { var randCount int for i := 0; i < len(dispatch.Nb.Tasks); i++ { if dispatch.Nb.Tasks[i].Status == 1 { if dispatch.Nb.Tasks[i].LeftTime != 0 && dispatch.Nb.Tasks[i].LeftTime <= configure.Now().Unix() { //更改次任务状态为 dispatch.Nb.Tasks[i].Status = 2 //任务结束 dispatch.Nb.Tasks[i].LeftTime = 0 //升级 conf, err := this.module.configure.getDispatchLvConf(dispatch.Nb.Lv) if err != nil || conf == nil { return err } } } if dispatch.Nb.Tasks[i].Status == 0 { //判断到期时间 if dispatch.Nb.Tasks[i].Duration != 0 && dispatch.Nb.Tasks[i].Duration <= configure.Now().Unix() { //替换到期任务 dispatch.Nb.Tasks = append(dispatch.Nb.Tasks[:i], dispatch.Nb.Tasks[i+1:]...) i-- randCount++ } } } //刷新任务 count := len(dispatch.Nb.Tasks) if count < 6 { randCount = 6 - count } for i := 0; i < randCount; i++ { task := this.addRandomTask(uid, dispatch) if task != nil { dispatch.Nb.Tasks = append(dispatch.Nb.Tasks, task) } } //判断是否有下一等级 nextConf, err := this.module.configure.getDispatchLvConf(dispatch.Nb.Lv + 1) if nextConf != nil { if dispatch.Nb.TaskCount >= nextConf.Upgrade { if err != nil { return err } dispatch.Nb.Lv++ dispatch.Nb.TaskCount = 0 } } return this.updateTasks(uid, dispatch.Nb, dispatch.Nb.Tasks) } // 更新周任务状态 func (this *modelDispatch) updateWeekstatus(uid string, idx int32, noticeboard *pb.Noticeboard) error { noticeboard.WeekReceived = append(noticeboard.WeekReceived, idx) update := map[string]interface{}{ "nb": noticeboard, } return this.Change(uid, update) }