package dispatch import ( "go_dreamfactory/comm" "go_dreamfactory/lego/core" "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 } // 初始玩家公告 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 refreshCount := this.module.configure.GetGlobalConf().DispatchRefreshtimes dis := &pb.DBDispatch{ Uid: uid, Ticket: ticketCount, Nb: &pb.Noticeboard{ Lv: 1, //公告初始升级 FreeCount: freeCount, Tasks: tasks, RefreshCount: refreshCount, }, } 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 { return []int32{} } 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) } } return tIds } // 随机任务 func (this *modelDispatch) taskRandom(uid string, dispatch *pb.DBDispatch) (tasks []*pb.DispatchTask, err error) { // dispatch := this.getDBDispatch(uid) // if dispatch == nil { // return nil, errors.New("no data") // } // if dispatch.Nb == nil { // return nil, errors.New("notice is nil") // } if dispatch.Nb.Lv == 0 { dispatch.Nb.Lv = 1 } conf, err := this.module.configure.getDispatchLvConf(dispatch.Nb.Lv) if err != 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 for i, v := range tasks { //只随机未接取的任务 if v.Status == 0 { //删除 tasks = append(tasks[:i], tasks[i+1:]...) //追加一条随机任务 ids := utils.RandomNumbers(1, len(tIds), 1) if len(ids) <= 0 { continue } taskId := ids[0] taskConf, err := this.module.configure.getDispatchTaskConf(v.TaskId) if err != nil { continue } //公告持续截至时间 duration := configure.Now().Unix() + int64(taskConf.Taskcd) tasks = append(tasks, &pb.DispatchTask{ TaskId: int32(taskId), Duration: duration, }) } else { tasks = append(tasks, v) } i-- } } return } func (this *modelDispatch) addRandomTask(uid string, dispatch *pb.DBDispatch) *pb.DispatchTask { randomTaskIds := this.getTasksWeight(uid, dispatch.Nb.Lv) //追加一条随机任务 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) // 任务截至时间 leftTime := configure.Now().Unix() + int64(taskConf.Tasktime) return &pb.DispatchTask{ TaskId: int32(taskId), Duration: duration, LeftTime: leftTime, } } // 替换指定的已完成任务 func (this *modelDispatch) replaceTask(uid string, taskId int32, dispatch *pb.DBDispatch) (tasks []*pb.DispatchTask) { tasks = dispatch.Nb.Tasks for i, v := range tasks { //替换状态是完成的任务 if v.Status == 2 { if taskId != v.TaskId { continue } //删除 tasks = append(tasks[:i], tasks[i+1:]...) i-- tasks = append(tasks, this.addRandomTask(uid, dispatch)) } else { tasks = append(tasks, v) } } return } // 替换所有完成的任务 func (this *modelDispatch) replaceFinishedTask(uid string, dispatch *pb.DBDispatch) (tasks []*pb.DispatchTask) { randomTaskIds := this.getTasksWeight(uid, dispatch.Nb.Lv) for i, v := range dispatch.Nb.Tasks { //替换状态是完成的任务 if v.Status == 2 { //删除 dispatch.Nb.Tasks = append(dispatch.Nb.Tasks[:i], dispatch.Nb.Tasks[i+1:]...) i-- //追加一条随机任务 ids := utils.RandomNumbers(1, len(randomTaskIds), 1) if len(ids) <= 0 { continue } taskId := ids[0] taskConf, err := this.module.configure.getDispatchTaskConf(v.TaskId) if err != nil { continue } //公告持续截至时间 duration := configure.Now().Unix() + int64(taskConf.Taskcd) // 任务截至时间 leftTime := configure.Now().Unix() + int64(taskConf.Tasktime) tasks = append(tasks, &pb.DispatchTask{ TaskId: int32(taskId), Duration: duration, LeftTime: leftTime, }) } else { tasks = append(tasks, v) } } 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 return } case 2: //校验英雄的额外要求 if hero.Star >= v.Param { ok2 = true return } } } } 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 } } } } //周任务数累加 disp.Nb.WeekCount++ update := map[string]interface{}{ "nb": disp.Nb, "ticket": disp.Ticket - 1, } 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 { for i, v := range dispatch.Nb.Tasks { if v.Status == 0 { //判断到期时间 if v.Duration != 0 && v.Duration <= configure.Now().Unix() { //替换到期任务 // dispatch.Nb.Tasks = this.replaceTask(uid, v.TaskId, dispatch) dispatch.Nb.Tasks = append(dispatch.Nb.Tasks[:i], dispatch.Nb.Tasks[i+1:]...) i-- //补一条 dispatch.Nb.Tasks = append(dispatch.Nb.Tasks, this.addRandomTask(uid, dispatch)) } } if v.Status == 1 { if v.LeftTime != 0 && v.LeftTime <= configure.Now().Unix() { //更改次任务状态为 v.Status = 2 //任务结束 v.LeftTime = 0 //升级 conf, err := this.module.configure.getDispatchLvConf(dispatch.Nb.Lv) if err != nil { return err } if dispatch.Nb.WeekCount >= conf.Upgrade { dispatch.Nb.Lv++ } //累计任务数 dispatch.Nb.TaskCount++ dispatch.Nb.WeekCount++ } } } return this.updateTasks(uid, dispatch.Nb, dispatch.Nb.Tasks) }