package service import ( "fmt" "github.com/pkg/errors" "leit.com/aps_engine/common" "leit.com/aps_engine/db" "leit.com/aps_engine/models" "time" ) /**调度引擎**/ type SchedulerSrv struct{ PlantNr int StartDate time.Time EndDate time.Time WorkPlaceDict map[int]*WorkPlaceSrv // 所有的设备对象 WorkPlaceGrpDict map[int]*WorkPlaceGrpSrv ToolDict map[int]*ToolSrv // 所有的工具对象 ToolGrpDict map[int]*ToolGrpSrv ArticleDict map[string]*ArticleSrv // 所有的物料对象 SecResourceDict map[int]*SecondaryResourceSrv // 所有的次要资源对象 PersonDict map[int]*PersonSrv // 所有人员对象 SkillDict map[int]*SkillSrv // 所有技能对象 OrderDict map[string]*OrderSrv // 所有工单对象 OperationDict map[string]*OperationSrv // 所有订单工序对象 TmSrv TimeModelSrv // 时间模型 ProjDict map[string]models.MeProject // 激活的项目字典 SchedRule ScheduleRuleSrv // 调度规则 SchedEventQueue *SchedQueue // 调度事件队列 } // 调度引擎初始化 func(se *SchedulerSrv)Init(plantnr int, stdate, eddate time.Time){ se.PlantNr = plantnr se.StartDate = stdate se.EndDate = eddate se.WorkPlaceDict = make(map[int]*WorkPlaceSrv) se.WorkPlaceGrpDict = make(map[int]*WorkPlaceGrpSrv) se.ToolDict = make(map[int]*ToolSrv) se.ToolGrpDict = make(map[int]*ToolGrpSrv) se.ArticleDict = make(map[string]*ArticleSrv) se.SecResourceDict = make(map[int]*SecondaryResourceSrv) se.PersonDict = make(map[int]*PersonSrv) se.SkillDict = make(map[int]*SkillSrv) se.OrderDict = make(map[string]*OrderSrv) se.OperationDict = make(map[string]*OperationSrv) se.TmSrv = TimeModelSrv{PlantNr: plantnr} se.SchedEventQueue = NewSchedQueue() } // 加载时间模型主数据 func(se *SchedulerSrv)LoadTimeModelData(){ // 加载指定日期范畴内的时间模型相关主数据 se.TmSrv.LoadBasicData(se.StartDate, se.EndDate) // 生成日模型的时间线列表 se.TmSrv.GenDayModelLineArray() } // 加载激活的项目 func(se *SchedulerSrv)LoadProjectData()(err error){ var( i int projtab models.MeProject projtablst []models.MeProject ) // 初始化 se.ProjDict = make(map[string]models.MeProject) // 读取激活的项目数据 projtab = models.MeProject{Plantnr: se.PlantNr} if projtablst, err = projtab.SelectActiveProjects(); err != nil{ err = errors.New(fmt.Sprintf("获取工厂%d的激活的项目失败%v !", se.PlantNr, err)) return } // 加载项目 for i = 0; i < len(projtablst); i++ { se.ProjDict[projtablst[i].Projectid] = projtablst[i] } return } // 加载工位主数据 func(se *SchedulerSrv)LoadWorkPlaceData()(err error){ var( wp *WorkPlaceSrv wpg *WorkPlaceGrpSrv wptab models.Workplace wptablst []models.Workplace wpgtab models.Workplacegrp wpgtablst []models.Workplacegrp ok bool ) // 加载并创建工位组对象 wpgtab = models.Workplacegrp{Plantnr: db.PlantNr} if wpgtablst, err = wpgtab.SelectAll(); err != nil{ err = errors.New(fmt.Sprintf("加载工位组主数据出错:%v",err)) return } for _, wpgtab = range wpgtablst { wpg = &WorkPlaceGrpSrv{} wpg.Create(wpgtab) se.WorkPlaceGrpDict[wpg.WorkPlaceGrpNr] = wpg } // 加载并创建工位对象 wptab = models.Workplace{Plantnr: db.PlantNr} if wptablst, err = wptab.SelectAll(); err != nil{ err = errors.New(fmt.Sprintf("加载工位主数据出错:%v",err)) return } for _, wptab = range wptablst { wp = &WorkPlaceSrv{} wp.Create(wptab) // 生成工位的时间曲线 se.WorkPlaceDict[wp.WorkPlaceNr] = wp // 获取工位组对象 if wpg, ok = se.WorkPlaceGrpDict[wp.WorkPlaceGrpNr]; ok { wpg.WorkPlaceDict[wp.WorkPlaceNr] = wp } } return } // 加载工具主数据 func(se *SchedulerSrv)LoadToolData()(err error){ var( toolsrv *ToolSrv toolgrpsrv *ToolGrpSrv tooltab models.Tool tooltablst []models.Tool toolgrptab models.Toolgrp toolgrptablst []models.Toolgrp tavailtab models.Toolunavailtimelst tavailtablst []models.Toolunavailtimelst timelinesrv TimeLineSrv ok bool ) // 加载并创建工具组对象 toolgrptab = models.Toolgrp{Plantnr: db.PlantNr} if toolgrptablst, err = toolgrptab.SelectAll(); err != nil{ err = errors.New(fmt.Sprintf("加载工具组主数据出错:%v",err)) return } for _, toolgrptab = range toolgrptablst { toolgrpsrv = &ToolGrpSrv{} toolgrpsrv.Create(toolgrptab) se.ToolGrpDict[toolgrpsrv.ToolGrpNr] = toolgrpsrv } // 加载并创建工具对象 tooltab = models.Tool{Plantnr: db.PlantNr} if tooltablst, err = tooltab.SelectAll(); err != nil{ err = errors.New(fmt.Sprintf("加载工具组主数据出错:%v",err)) return } for _, tooltab = range tooltablst { toolsrv = &ToolSrv{} toolsrv.Create(tooltab) // 更新工具组和工具的关联关系 if toolgrpsrv, ok = se.ToolGrpDict[toolsrv.ToolGrpNr]; ok { toolgrpsrv.ToolDict[toolsrv.ToolNr] = toolsrv } // 插入工具 se.ToolDict[toolsrv.ToolNr] = toolsrv } // 基于计划的指定计划时段加载工具的不可用时间数据 tavailtab = models.Toolunavailtimelst{Plantnr: db.PlantNr} if tavailtablst, err = tavailtab.GetUnAvailTime(se.StartDate, se.EndDate); err != nil{ err = errors.New(fmt.Sprintf("加载工具不可用时间数据出错:%v",err)) return } for _, tavailtab = range tavailtablst { if toolsrv, ok = se.ToolDict[tavailtab.Toolnr]; ok{ timelinesrv = TimeLineSrv{} timelinesrv.Init(tavailtab.Begtime, tavailtab.Endtime) toolsrv.UnAvailTimeLineArray = append(toolsrv.UnAvailTimeLineArray, timelinesrv) } } return } // 加载物料主数据,包括库存及在途 func(se *SchedulerSrv)LoadArticleData()(err error){ var( artsrv *ArticleSrv arttab models.Article arttablst []models.Article artstocktab models.WmsArtstock artstocktablst []models.WmsArtstock arttransittab models.WmsArttransitstock arttransittablst []models.WmsArttransitstock ok bool ) // 获取物料主数据 arttab = models.Article{Plantnr: db.PlantNr} if arttablst, err = arttab.SelectAll(); err != nil{ err = errors.New(fmt.Sprintf("加载物料主数据出错:%v",err)) return } // 创建物料对象 for _, arttab = range arttablst { artsrv = &ArticleSrv{} artsrv.Create(arttab) se.ArticleDict[artsrv.ArtId] = artsrv } // 加载物料库存数据 artstocktab = models.WmsArtstock{Plantnr: db.PlantNr} if artstocktablst, err = artstocktab.SelectAll(); err != nil{ err = errors.New(fmt.Sprintf("加载物料库存数据出错:%v",err)) return } for _, artstocktab = range artstocktablst { if artsrv, ok = se.ArticleDict[artstocktab.Artid]; ok { artsrv.AvailQty = artstocktab.Availablestock } } // 加载物料在途数据 arttransittab = models.WmsArttransitstock{Plantnr: db.PlantNr} if arttransittablst, err = arttransittab.SelectAll(); err != nil{ err = errors.New(fmt.Sprintf("加载物料在途库存数据出错:%v",err)) return } for _, arttransittab = range arttransittablst { if artsrv, ok = se.ArticleDict[artstocktab.Artid]; ok { artsrv.TransitStockLst = append(artsrv.TransitStockLst, arttransittab) } } return } // 加载人员主数据,包括技能 func(se *SchedulerSrv)LoadPersonData()(err error){ var( persrv *PersonSrv skillsrv *SkillSrv pertab models.Person pertablst []models.Person skilltab models.Skill skilltablst []models.Skill perskilltab models.Personskilllst perskilltablst []models.Personskilllst ok bool ) // 加载人员主数据 pertab = models.Person{Plantnr: db.PlantNr} if pertablst, err = pertab.SelectAll(); err != nil{ err = errors.New(fmt.Sprintf("加载人员主数据出错:%v",err)) return } for _, pertab = range pertablst { persrv = &PersonSrv{} persrv.Create(pertab) se.PersonDict[persrv.PersonNr] = persrv } // 加载技能数据 skilltab = models.Skill{Plantnr: db.PlantNr} if skilltablst, err = skilltab.SelectAll(); err != nil{ err = errors.New(fmt.Sprintf("加载技能主数据出错:%v",err)) return } for _, skilltab = range skilltablst { skillsrv = &SkillSrv{} skillsrv.Create(skilltab) se.SkillDict[skillsrv.SkillNr] = skillsrv } // 加载技能的人员数据 perskilltab = models.Personskilllst{Plantnr: db.PlantNr} if perskilltablst, err = perskilltab.SelectAll(); err != nil{ err = errors.New(fmt.Sprintf("加载人员技能主数据出错:%v",err)) return } for _, perskilltab = range perskilltablst { if skillsrv, ok = se.SkillDict[perskilltab.Skillnr]; !ok { continue } if persrv, ok = se.PersonDict[perskilltab.Personnr]; !ok { continue } skillsrv.PersonDict[persrv.PersonNr] = persrv } return } // 加载辅助资源主数据 func(se *SchedulerSrv)LoadResourceData()(err error){ var( resourcetab models.Secondaryresource resourcetablst []models.Secondaryresource secressrv *SecondaryResourceSrv ) // 加载次要资源 resourcetab = models.Secondaryresource{Plantnr: db.PlantNr} if resourcetablst, err = resourcetab.SelectAll(); err != nil{ err = errors.New(fmt.Sprintf("加载次要资源数据出错:%v",err)) return } for _, resourcetab = range resourcetablst { secressrv = &SecondaryResourceSrv{} secressrv.Create(resourcetab) se.SecResourceDict[secressrv.ResourceNr] = secressrv } // 初始化次要资源的时间模型 return } // 加载订单主数据(未完成订单) func(se *SchedulerSrv)LoadWorkOrderData()(err error){ var( ordsrv *OrderSrv opsrv *OperationSrv ordtab models.OmWorkorder vordtablst []models.VWorkorder i int ) // 加载所有未完成的订单 ordtab = models.OmWorkorder{Plantnr: db.PlantNr} if vordtablst, err = ordtab.SelectAllUnfinishedFullData(); err != nil { err = errors.New(fmt.Sprintf("加载工单数据出错:%v",err)) return } for i = 0; i < len(vordtablst); i++ { ordsrv = &OrderSrv{} ordsrv.Create(vordtablst[i].OmWorkorder) se.OrderDict[ordsrv.OrderId] = ordsrv // 加载订单所有的工序对象 for _, opsrv = range ordsrv.OperationDict { se.OperationDict[opsrv.GetOrdOpKey()] = opsrv } } return } // 加载订单网络数据 func(se *SchedulerSrv)LoadOrderNetworkData()(err error){ // 加载订单网络 return } // 加载排程规则数据 func(se *SchedulerSrv)LoadScheduleRuleData()(err error){ return } // 启动调度引擎 func(se *SchedulerSrv)Run()(err error){ var( set SchedEvent ) // 从队列循环获取任务执行,直至队列为空 for se.SchedEventQueue.Length() > 0 { set = se.SchedEventQueue.Pop() switch set.GetEvent() { case EVENT_TASK_SETUPBEG: oppbet := set.(OperationEvent) fmt.Println(fmt.Sprintf("订单:%s 工序:%d 换型开始:%s",oppbet.OrderId,oppbet.OperationNr,oppbet.TriggerTime.Format("2006-01-02 15:04:05"))) se.SchedTaskSetupBeg(oppbet) continue case EVENT_TASK_SETUPEND: oppbet := set.(OperationEvent) fmt.Println(fmt.Sprintf("订单:%s 工序:%d 换型结束:%s",oppbet.OrderId,oppbet.OperationNr,oppbet.TriggerTime.Format("2006-01-02 15:04:05"))) se.SchedTaskSetupEnd(oppbet) continue case EVENT_TASK_PLANBEG: oppbet := set.(OperationEvent) fmt.Println(fmt.Sprintf("订单:%s 工序:%d 计划开始:%s",oppbet.OrderId,oppbet.OperationNr,oppbet.TriggerTime.Format("2006-01-02 15:04:05"))) se.SchedTaskPlanBeg(oppbet) continue case EVENT_TASK_PLANEND: oppeet := set.(OperationEvent) fmt.Println(fmt.Sprintf("订单:%s 工序:%d 计划结束:%s",oppeet.OrderId,oppeet.OperationNr,oppeet.TriggerTime.Format("2006-01-02 15:04:05"))) se.SchedTaskPlanEnd(oppeet) continue case EVENT_TASK_POSTBEG: oppbet := set.(OperationEvent) fmt.Println(fmt.Sprintf("订单:%s 工序:%d 后处理开始:%s",oppbet.OrderId,oppbet.OperationNr,oppbet.TriggerTime.Format("2006-01-02 15:04:05"))) se.SchedTaskPostBeg(oppbet) continue case EVENT_TASK_POSTEND: oppbet := set.(OperationEvent) fmt.Println(fmt.Sprintf("订单:%s 工序:%d 后处理结束:%s",oppbet.OrderId,oppbet.OperationNr,oppbet.TriggerTime.Format("2006-01-02 15:04:05"))) se.SchedTaskPostEnd(oppbet) continue case EVENT_WP_STATUS_AVAIL: wpet := set.(WorkPlaceEvent) fmt.Println(fmt.Sprintf("|| 工位:%d 可使用时间:%s",wpet.WorkPlaceNr, wpet.TriggerTime.Format("2006-01-02 15:04:05"))) se.SchedWPAvail(wpet) continue case EVENT_WP_STATUS_UNAVAIL: wpet := set.(WorkPlaceEvent) fmt.Println(fmt.Sprintf("XX 工位:%d 不可使用时间:%s",wpet.WorkPlaceNr, wpet.TriggerTime.Format("2006-01-02 15:04:05"))) se.SchedWPUnAvail(wpet) continue case EVENT_TOOL_STATUS_AVAIL: tet := set.(ToolEvent) fmt.Println(fmt.Sprintf("|| 工具:%d 可使用时间:%s",tet.ToolNr, tet.TriggerTime.Format("2006-01-02 15:04:05"))) se.SchedToolAvail(tet) continue case EVENT_TOOL_STATUS_UNAVAIL: tet := set.(ToolEvent) fmt.Println(fmt.Sprintf("XX 工具:%d 不可使用时间:%s",tet.ToolNr, tet.TriggerTime.Format("2006-01-02 15:04:05"))) se.SchedToolUnAvail(tet) continue case EVENT_PERSON_STATUS_AVAIL: pet := set.(PersonEvent) fmt.Println(fmt.Sprintf("|| 人员:%d 可使用时间:%s",pet.PersonNr, pet.TriggerTime.Format("2006-01-02 15:04:05"))) se.SchedPersonAvail(pet) continue case EVENT_PERSON_STATUS_UNAVAIL: pet := set.(PersonEvent) fmt.Println(fmt.Sprintf("|| 人员:%d 不可使用时间:%s",pet.PersonNr, pet.TriggerTime.Format("2006-01-02 15:04:05"))) se.SchedPersonUnAvail(pet) continue case EVENT_ART_CONSUME: aet := set.(ArticleEvent) fmt.Println(fmt.Sprintf("|| 物料:%s 耗用时间:%s",aet.ArtId, aet.TriggerTime.Format("2006-01-02 15:04:05"))) se.SchedArticleConsume(aet) continue case EVENT_ART_YIELD: aet := set.(ArticleEvent) fmt.Println(fmt.Sprintf("|| 物料:%s 产出时间:%s",aet.ArtId, aet.TriggerTime.Format("2006-01-02 15:04:05"))) se.SchedArticleYield(aet) continue case EVENT_SECRES_CONSUME: sret := set.(SecondaryResourceEvent) fmt.Println(fmt.Sprintf("|| 次要资源:%d 耗用时间:%s",sret.ResourceNr, sret.TriggerTime.Format("2006-01-02 15:04:05"))) se.SchedSecondaryResourceConsume(sret) continue case EVENT_SECRES_YIELD: sret := set.(SecondaryResourceEvent) fmt.Println(fmt.Sprintf("|| 次要资源:%d 耗用时间:%s",sret.ResourceNr, sret.TriggerTime.Format("2006-01-02 15:04:05"))) se.SchedSecondaryResourceYield(sret) continue } } return } // 对换型开始工序进行调度 func(se *SchedulerSrv)SchedTaskSetupBeg(opevent OperationEvent){ } // 对换型结束工序进行调度 func(se *SchedulerSrv)SchedTaskSetupEnd(opevent OperationEvent){ } // 对计划开始工序进行调度 func(se *SchedulerSrv)SchedTaskPlanBeg(opevent OperationEvent){ var( order *OrderSrv op *OperationSrv wp *WorkPlaceSrv wpg *WorkPlaceGrpSrv t *ToolSrv tg *ToolGrpSrv newevent SchedEvent optionalwplst []OptionalWorkPlaceSrv optoollst []OptionalToolSrv ok bool ) // 获取工序订单对象 if order, ok = se.OrderDict[opevent.OrderId]; !ok { fmt.Println(fmt.Sprintf("工序事件的订单: %s 不存在", opevent.OrderId)) return } // 获取工序对象 if op, ok = order.OperationDict[opevent.GetOpKey()]; !ok { fmt.Println(fmt.Sprintf("工序事件的工序: %d 不存在于订单: %s 中", opevent.GetOpKey(), opevent.OrderId)) return } // 获取可用工位 optionalwplst = se.GetAvailWorkPlaceList(op.WorkPlaceGrpNr) if len(optionalwplst) <= 0 { //fmt.Println("工位组:",op.WorkPlaceGrpNr," 无可用工位!") // 获取工位组对象 if wpg, ok = se.WorkPlaceGrpDict[op.WorkPlaceGrpNr]; !ok{ //fmt.Println("工位组:",op.WorkPlaceGrpNr," 不存在!") return } // 无可用工位,则将任务放到工位组等待队列 wpg.WaitTaskArray = append(wpg.WaitTaskArray, *op) return } if se.SchedRule.ToolConstraintToggle && op.ToolGrpNr > 0{ // 获取可用工位 optoollst = se.GetAvailToolList(op.ToolGrpNr) if len(optoollst) <= 0 { //fmt.Println("工具组:",op.ToolGrpNr," 无可用工位!") // 获取工具组对象 if tg, ok = se.ToolGrpDict[op.ToolGrpNr]; !ok{ //fmt.Println("工具组:",op.ToolGrpNr," 不存在!") return } // 无可用工位,则将任务放到工位组等待队列 tg.WaitTaskArray = append(tg.WaitTaskArray, *op) return } } // 有可用工位,取第一个工位进行调度 op.PlanStartTime = opevent.TriggerTime op.PlanEndTime = op.PlanStartTime.Add(op.PlanDuration) op.PlanWorkPlaceNr = optionalwplst[0].WorkPlaceNr if se.SchedRule.ToolConstraintToggle && op.ToolGrpNr > 0 { op.PlanToolNr = optoollst[0].ToolNr } // 基于工序开始生成工序结束事件 fmt.Println(" 创建工序结束事件:",op.OrderId,op.OperationNr,op.PlanEndTime.Format("2006-01-02 15:04:05")) newevent = op.GetPlanEndEvent(op.PlanEndTime) se.SchedEventQueue.Insert(newevent) // 基于工序开始生成设备事件,占用工位资源 if wp, ok = se.WorkPlaceDict[op.PlanWorkPlaceNr]; ok { newevent = wp.GetUnAvailEvent(opevent.TriggerTime) se.SchedEventQueue.Insert(newevent) wp.Status = common.RES_STATUS_UNAVAIL wp.SchedTaskArray = append(wp.SchedTaskArray, *op) } // 考虑有限工具能力 if se.SchedRule.ToolConstraintToggle && op.ToolGrpNr > 0{ if t, ok = se.ToolDict[op.PlanToolNr]; ok { newevent = t.GetUnAvailEvent(opevent.TriggerTime) se.SchedEventQueue.Insert(newevent) t.Status = common.RES_STATUS_UNAVAIL t.SchedTaskArray = append(t.SchedTaskArray, *op) } } } // 对计划结束工序进行调度 func(se *SchedulerSrv)SchedTaskPlanEnd(opevent OperationEvent){ var( order,nextorder *OrderSrv op,nextop *OperationSrv wp *WorkPlaceSrv t *ToolSrv newevent SchedEvent nextoprel OperationRelSrv ok bool ) // 获取工序订单对象 if order, ok = se.OrderDict[opevent.OrderId]; !ok { fmt.Println(fmt.Sprintf("工序事件的订单: %s 不存在", opevent.OrderId)) return } // 获取工序对象 if op, ok = order.OperationDict[opevent.GetOpKey()]; !ok { fmt.Println(fmt.Sprintf("工序事件的工序: %d 不存在于订单: %s 中", opevent.GetOpKey(), opevent.OrderId)) return } // 获取占用工位并释放资源 if wp, ok = se.WorkPlaceDict[op.PlanWorkPlaceNr]; ok { newevent = wp.GetAvailEvent(opevent.TriggerTime) se.SchedEventQueue.Insert(newevent) wp.Status = common.RES_STATUS_AVAIL }else{ fmt.Println(fmt.Sprintf("订单:%s 工序:%d 计划工位:%d 不存在!",op.OrderId,op.OperationNr,op.PlanWorkPlaceNr)) return } if se.SchedRule.ToolConstraintToggle && op.ToolGrpNr > 0{ if t, ok = se.ToolDict[op.PlanToolNr]; ok{ newevent = t.GetAvailEvent(opevent.TriggerTime) se.SchedEventQueue.Insert(newevent) t.Status = common.RES_STATUS_AVAIL } } // 激活后道工序 for _, nextoprel = range op.NextOpDict{ if nextorder, ok = se.OrderDict[nextoprel.OrderId]; ok{ if nextop, ok = nextorder.OperationDict[nextoprel.GetOpKey()]; ok{ newevent = nextop.GetPlanStartEvent(opevent.TriggerTime) se.SchedEventQueue.Insert(newevent) } }else{ fmt.Println(fmt.Sprintf("订单:%s 不存在",nextoprel.OrderId)) continue } } } // 对工序后处理开始进行调度 func(se *SchedulerSrv)SchedTaskPostBeg(opevent OperationEvent){ } // 对工序后处理结束进行调度 func(se *SchedulerSrv)SchedTaskPostEnd(opevent OperationEvent){ } // 对工位可用进行调度 func(se *SchedulerSrv)SchedWPAvail(wpevent WorkPlaceEvent){ var ( wp *WorkPlaceSrv wpg *WorkPlaceGrpSrv op OperationSrv newevent SchedEvent ok bool ) // 获取工位对象 if wp, ok = se.WorkPlaceDict[wpevent.WorkPlaceNr]; !ok { fmt.Println(fmt.Sprintf("SchedWPAvail: 工位:%d 不存在",wpevent.WorkPlaceNr)) return } // 获取工位组对象 if wpg, ok = se.WorkPlaceGrpDict[wp.WorkPlaceGrpNr]; !ok { fmt.Println(fmt.Sprintf("工位组:%d 不存在",wp.WorkPlaceGrpNr)) return } // 更新工位状态 wp.Status = common.RES_STATUS_AVAIL //se.WorkPlaceDict[wp.WorkPlaceNr] = wp // 将等待队列中的工序任务全部推入调度队列 for _, op = range wpg.WaitTaskArray { fmt.Println("************ 获取等待队列中的等待任务:",op.OrderId,op.OperationNr) newevent = op.GetPlanStartEvent(wpevent.TriggerTime) se.SchedEventQueue.Insert(newevent) } wpg.WaitTaskArray = []OperationSrv{} //se.WorkPlaceGrpDict[wpg.WorkPlaceGrpNr] = wpg return } // 对工位不可用进行调度 func(se *SchedulerSrv)SchedWPUnAvail(wpevent WorkPlaceEvent){ var ( wp *WorkPlaceSrv ok bool ) // 获取工位对象 if wp, ok = se.WorkPlaceDict[wpevent.WorkPlaceNr]; !ok { fmt.Println(fmt.Sprintf("SchedWPUnAvail: 工位:%d 不存在",wpevent.WorkPlaceNr)) return } // 更新工位状态 wp.Status = common.RES_STATUS_UNAVAIL //se.WorkPlaceDict[wp.WorkPlaceNr] = wp return } // 对工具可用进行调度 func(se *SchedulerSrv)SchedToolAvail(tevent ToolEvent){ var ( t *ToolSrv tg *ToolGrpSrv op OperationSrv newevent SchedEvent ok bool ) // 获取工具对象 if t, ok = se.ToolDict[tevent.ToolNr]; !ok { fmt.Println(fmt.Sprintf("SchedToolAvail: 工具:%d 不存在",tevent.ToolNr)) return } // 获取工具组对象 if tg, ok = se.ToolGrpDict[t.ToolGrpNr]; !ok { fmt.Println(fmt.Sprintf("工具组:%d 不存在",t.ToolGrpNr)) return } // 更新工具状态 t.Status = common.RES_STATUS_AVAIL // 将等待队列中的工序任务全部推入调度队列 for _, op = range tg.WaitTaskArray { fmt.Println("************ 获取等待队列中的等待任务:",op.OrderId,op.OperationNr) newevent = op.GetPlanStartEvent(tevent.TriggerTime) se.SchedEventQueue.Insert(newevent) } tg.WaitTaskArray = []OperationSrv{} return } // 对工具不可用进行调度 func(se *SchedulerSrv)SchedToolUnAvail(tevent ToolEvent){ var ( t *ToolSrv ok bool ) // 获取工位对象 if t, ok = se.ToolDict[tevent.ToolNr]; !ok { fmt.Println(fmt.Sprintf("SchedToolUnAvail: 工具:%d 不存在",tevent.ToolNr)) return } // 更新工位状态 t.Status = common.RES_STATUS_UNAVAIL return } // 对人员可用进行调度 func(se *SchedulerSrv)SchedPersonAvail(pevent PersonEvent){ } // 对人员不可用进行调度 func(se *SchedulerSrv)SchedPersonUnAvail(pevent PersonEvent){ } // 对物料耗用进行调度 func(se *SchedulerSrv)SchedArticleConsume(artevent ArticleEvent){ } // 对物料产出进行调度 func(se *SchedulerSrv)SchedArticleYield(artevent ArticleEvent){ } // 对次要资源耗用进行调度 func(se *SchedulerSrv)SchedSecondaryResourceConsume(srevent SecondaryResourceEvent){ } // 对次要资源产出进行调度 func(se *SchedulerSrv)SchedSecondaryResourceYield(srevent SecondaryResourceEvent){ } // 获取当前可用工位 func(se *SchedulerSrv)GetAvailWorkPlaceList(wpgnr int)(optionalwplst []OptionalWorkPlaceSrv){ var( wpnr int wp *WorkPlaceSrv wpg *WorkPlaceGrpSrv ok bool ) // 获取工位组对象 if wpg, ok = se.WorkPlaceGrpDict[wpgnr]; !ok { fmt.Println(fmt.Sprintf("GetAvailWorkPlaceList: 工位组:%d 不存在",wpgnr)) return } optionalwplst = []OptionalWorkPlaceSrv{} for wpnr, _ = range wpg.WorkPlaceDict{ if wp, ok = se.WorkPlaceDict[wpnr]; !ok{ fmt.Println(fmt.Sprintf("GetAvailWorkPlaceList: 工位:%d 不存在",wpnr)) return } if wp.Status == common.RES_STATUS_AVAIL { optionalwp := OptionalWorkPlaceSrv{WorkPlaceNr: wp.WorkPlaceNr, Priority: 0} optionalwplst = append(optionalwplst, optionalwp) } } return } // 获取当前可用工具 func(se *SchedulerSrv)GetAvailToolList(tgnr int)(opttoollst []OptionalToolSrv){ var( tnr int t *ToolSrv tg *ToolGrpSrv ok bool ) // 获取工位组对象 if tg, ok = se.ToolGrpDict[tgnr]; !ok { fmt.Println(fmt.Sprintf("GetAvailToolList: 工具组:%d 不存在",tgnr)) return } fmt.Println("获取工具组的工具.......",tg.ToolGrpNr) opttoollst = []OptionalToolSrv{} for tnr, _ = range tg.ToolIdxDict{ if t, ok = se.ToolDict[tnr]; !ok{ fmt.Println(fmt.Sprintf("GetAvailToolList: 工位:%d 不存在",tnr)) return } fmt.Println(" 工具:",t.ToolNr," 状态:",t.Status) if t.Status == common.RES_STATUS_AVAIL { optionalt := OptionalToolSrv{ToolNr: t.ToolNr, Priority: 0} opttoollst = append(opttoollst, optionalt) } } return } // 初始化测试环境,创建一些测试数据 func LoadTestEnvData(se *SchedulerSrv)(err error){ var( wp *WorkPlaceSrv wpg *WorkPlaceGrpSrv t *ToolSrv tg *ToolGrpSrv art *ArticleSrv order *OrderSrv prevop *OperationSrv op *OperationSrv opr OperationRelSrv st,et time.Time tls TimeLineSrv ) // 初始化工厂号及计划区间 st = time.Now() et = time.Now().Add(time.Hour*24*10) se.Init(100, st, et) // 创建工位组 wpg = &WorkPlaceGrpSrv{} wpg.Init(10) // 创建工位 wp = &WorkPlaceSrv{} wp.Init(1,10) st = time.Now() et = time.Now().Add(time.Hour*24*10) wp.TimeCurve.Init(st,et) tls = TimeLineSrv{} st = time.Now() et = time.Now().Add(time.Hour*24) tls.Init(st, et) wp.TimeCurve.TimeLineArray = append(wp.TimeCurve.TimeLineArray, tls) tls = TimeLineSrv{} st = time.Now().Add(time.Hour*28) et = time.Now().Add(time.Hour*48) tls.Init(st, et) wp.TimeCurve.TimeLineArray = append(wp.TimeCurve.TimeLineArray, tls) se.WorkPlaceDict[wp.WorkPlaceNr] = wp wpg.WorkPlaceDict[wp.WorkPlaceNr] = wp wp = &WorkPlaceSrv{} wp.Init(2,10) st = time.Now() et = time.Now().Add(time.Hour*24*10) wp.TimeCurve.Init(st,et) tls = TimeLineSrv{} st = time.Now() et = time.Now().Add(time.Hour*16) tls.Init(st, et) wp.TimeCurve.TimeLineArray = append(wp.TimeCurve.TimeLineArray, tls) tls = TimeLineSrv{} st = time.Now().Add(time.Hour*24) et = time.Now().Add(time.Hour*46) tls.Init(st, et) wp.TimeCurve.TimeLineArray = append(wp.TimeCurve.TimeLineArray, tls) se.WorkPlaceDict[wp.WorkPlaceNr] = wp wpg.WorkPlaceDict[wp.WorkPlaceNr] = wp se.WorkPlaceGrpDict[wpg.WorkPlaceGrpNr] = wpg wpg = &WorkPlaceGrpSrv{} wpg.Init(20) wp = &WorkPlaceSrv{} wp.Init(3,20) st = time.Now() et = time.Now().Add(time.Hour*24*10) wp.TimeCurve.Init(st,et) tls = TimeLineSrv{} st = time.Now() et = time.Now().Add(time.Hour*20) tls.Init(st, et) wp.TimeCurve.TimeLineArray = append(wp.TimeCurve.TimeLineArray, tls) tls = TimeLineSrv{} st = time.Now().Add(time.Hour*22) et = time.Now().Add(time.Hour*44) tls.Init(st, et) wp.TimeCurve.TimeLineArray = append(wp.TimeCurve.TimeLineArray, tls) se.WorkPlaceDict[wp.WorkPlaceNr] = wp wpg.WorkPlaceDict[wp.WorkPlaceNr] = wp se.WorkPlaceGrpDict[wpg.WorkPlaceGrpNr] = wpg wpg = &WorkPlaceGrpSrv{} wpg.Init(30) wp = &WorkPlaceSrv{} wp.Init(4,30) st = time.Now() et = time.Now().Add(time.Hour*24*15) wp.TimeCurve.Init(st,et) tls = TimeLineSrv{} st = time.Now() et = time.Now().Add(time.Hour*21) tls.Init(st, et) wp.TimeCurve.TimeLineArray = append(wp.TimeCurve.TimeLineArray, tls) tls = TimeLineSrv{} st = time.Now().Add(time.Hour*23) et = time.Now().Add(time.Hour*50) tls.Init(st, et) wp.TimeCurve.TimeLineArray = append(wp.TimeCurve.TimeLineArray, tls) se.WorkPlaceDict[wp.WorkPlaceNr] = wp wpg.WorkPlaceDict[wp.WorkPlaceNr] = wp wp = &WorkPlaceSrv{} wp.Init(5,30) st = time.Now() et = time.Now().Add(time.Hour*24*10) wp.TimeCurve.Init(st,et) tls = TimeLineSrv{} st = time.Now() et = time.Now().Add(time.Hour*17) tls.Init(st, et) wp.TimeCurve.TimeLineArray = append(wp.TimeCurve.TimeLineArray, tls) tls = TimeLineSrv{} st = time.Now().Add(time.Hour*25) et = time.Now().Add(time.Hour*52) tls.Init(st, et) wp.TimeCurve.TimeLineArray = append(wp.TimeCurve.TimeLineArray, tls) se.WorkPlaceDict[wp.WorkPlaceNr] = wp wpg.WorkPlaceDict[wp.WorkPlaceNr] = wp se.WorkPlaceGrpDict[wpg.WorkPlaceGrpNr] = wpg // 创建工具 t = &ToolSrv{} t.Init(1, 10) tls = TimeLineSrv{} st = time.Now().Add(time.Hour*5) et = time.Now().Add(time.Hour*10) t.UnAvailTimeLineArray = append(t.UnAvailTimeLineArray, tls) se.ToolDict[t.ToolNr] = t // 创建工具组 tg = &ToolGrpSrv{} tg.Init(10) tg.ToolIdxDict[t.ToolNr] = t.ToolNr se.ToolGrpDict[tg.ToolGrpNr] = tg // 创建工具 t = &ToolSrv{} t.Init(2, 20) tls = TimeLineSrv{} st = time.Now().Add(time.Hour*6) et = time.Now().Add(time.Hour*12) t.UnAvailTimeLineArray = append(t.UnAvailTimeLineArray, tls) se.ToolDict[t.ToolNr] = t // 创建工具组 tg = &ToolGrpSrv{} tg.Init(20) tg.ToolIdxDict[t.ToolNr] = t.ToolNr se.ToolGrpDict[tg.ToolGrpNr] = tg // 创建物料 art = &ArticleSrv{} art.Init("art001",100) se.ArticleDict[art.ArtId] = art // 创建工单及工序 order = &OrderSrv{OrderId: "100001", ProjectId: "G18"} order.OperationArray = []OperationSrv{} order.OperationDict = make(map[string]*OperationSrv) op = &OperationSrv{OrderId: "100001",OperationNr: 10, SplitNr: 0,PlanQty: 10, WorkPlaceGrpNr: 10, ToolGrpNr: 10, PlanDuration: time.Hour * 4} op.PrevOpDict = make(map[string]OperationRelSrv) op.NextOpDict = make(map[string]OperationRelSrv) order.OperationArray = append(order.OperationArray, *op) order.OperationDict[op.GetOpKey()] = op prevop = op opr = OperationRelSrv{OrderId: "100001", OperationNr: 20, SplitNr: 0, Relation: OP_LINK_END_START} prevop.NextOpDict[opr.GetFullKey()] = opr op = &OperationSrv{OrderId: "100001",OperationNr: 20, SplitNr: 0,PlanQty: 10, WorkPlaceGrpNr: 20, PlanDuration: time.Hour * 6} op.PrevOpDict = make(map[string]OperationRelSrv) opr = OperationRelSrv{OrderId: "100001", OperationNr: 10, SplitNr: 0, Relation: OP_LINK_END_START} op.PrevOpDict[opr.GetFullKey()] = opr op.NextOpDict = make(map[string]OperationRelSrv) order.OperationArray = append(order.OperationArray, *op) order.OperationDict[op.GetOpKey()] = op prevop = op opr = OperationRelSrv{OrderId: "100001", OperationNr: 30, SplitNr: 0, Relation: OP_LINK_END_START} prevop.NextOpDict[opr.GetFullKey()] = opr op = &OperationSrv{OrderId: "100001",OperationNr: 30, SplitNr: 0,PlanQty: 10, WorkPlaceGrpNr: 30, PlanDuration: time.Hour * 8} op.PrevOpDict = make(map[string]OperationRelSrv) opr = OperationRelSrv{OrderId: "100001", OperationNr: 20, SplitNr: 0, Relation: OP_LINK_END_START} op.PrevOpDict[opr.GetFullKey()] = opr op.NextOpDict = make(map[string]OperationRelSrv) order.OperationArray = append(order.OperationArray, *op) order.OperationDict[op.GetOpKey()] = op se.OrderDict[order.OrderId] = order order = &OrderSrv{OrderId: "100002", ProjectId: "G18"} order.OperationArray = []OperationSrv{} order.OperationDict = make(map[string]*OperationSrv) op = &OperationSrv{OrderId: "100002",OperationNr: 10, SplitNr: 0,PlanQty: 10, WorkPlaceGrpNr: 10, ToolGrpNr: 10, PlanDuration: time.Hour * 5} op.PrevOpDict = make(map[string]OperationRelSrv) op.NextOpDict = make(map[string]OperationRelSrv) order.OperationArray = append(order.OperationArray, *op) order.OperationDict[op.GetOpKey()] = op prevop = op opr = OperationRelSrv{OrderId: "100002", OperationNr: 20, SplitNr: 0, Relation: OP_LINK_END_START} prevop.NextOpDict[opr.GetFullKey()] = opr op = &OperationSrv{OrderId: "100002",OperationNr: 20, SplitNr: 0,PlanQty: 10, WorkPlaceGrpNr: 20, PlanDuration: time.Hour * 7} op.PrevOpDict = make(map[string]OperationRelSrv) opr = OperationRelSrv{OrderId: "100002", OperationNr: 10, SplitNr: 0, Relation: OP_LINK_END_START} op.PrevOpDict[opr.GetFullKey()] = opr op.NextOpDict = make(map[string]OperationRelSrv) order.OperationArray = append(order.OperationArray, *op) order.OperationDict[op.GetOpKey()] = op prevop = op opr = OperationRelSrv{OrderId: "100002", OperationNr: 30, SplitNr: 0, Relation: OP_LINK_END_START} prevop.NextOpDict[opr.GetFullKey()] = opr op = &OperationSrv{OrderId: "100002",OperationNr: 30, SplitNr: 0,PlanQty: 10, WorkPlaceGrpNr: 30, PlanDuration: time.Hour * 9} op.PrevOpDict = make(map[string]OperationRelSrv) opr = OperationRelSrv{OrderId: "100002", OperationNr: 20, SplitNr: 0, Relation: OP_LINK_END_START} op.PrevOpDict[opr.GetFullKey()] = opr op.NextOpDict = make(map[string]OperationRelSrv) order.OperationArray = append(order.OperationArray, *op) order.OperationDict[op.GetOpKey()] = op se.OrderDict[order.OrderId] = order // 初始化调度队列 se.SchedEventQueue = NewSchedQueue() // 遍历设备时间曲线,生成设备状态事件,推入队列 for _, wp_p := range se.WorkPlaceDict{ for _, tls := range wp_p.TimeCurve.TimeLineArray{ evt1 := wp_p.GetAvailEvent(tls.StartTime) se.SchedEventQueue.Insert(evt1) evt2 := wp_p.GetUnAvailEvent(tls.EndTime) se.SchedEventQueue.Insert(evt2) } } // 载入订单首工序事件 for _, ord_p := range se.OrderDict{ for _, op_p := range ord_p.OperationDict { if len(op_p.PrevOpDict) <= 0 { evt := op_p.GetPlanStartEvent(time.Now()) opet := evt.(OperationEvent) fmt.Println("压入订单工序事件:",opet.OrderId,opet.OperationNr, opet.TriggerTime) se.SchedEventQueue.Insert(evt) } } } return }