|
|
- package service
-
- import (
- "LAPP_AS/common"
- base_dal "LAPP_AS/dao/base"
- me_dal "LAPP_AS/dao/me"
- om_dal "LAPP_AS/dao/om"
- wm_dal "LAPP_AS/dao/wm"
- "LAPP_AS/db"
- meta "LAPP_AS/meta/om"
- base_model "LAPP_AS/models/base"
- me_model "LAPP_AS/models/me"
- om_model "LAPP_AS/models/om"
- wm_model "LAPP_AS/models/wm"
- "fmt"
- "github.com/pkg/errors"
- "time"
- )
-
- /**调度引擎**/
- type SchedulerSrv struct{
- PlantNr int
- StartDate time.Time
- EndDate time.Time
- WorkPlaceDict map[string]*WorkPlaceSrv // 所有的设备对象
- WorkPlaceGrpDict map[string]*WorkPlaceGrpSrv
- ToolDict map[string]*ToolSrv // 所有的工具对象
- ToolGrpDict map[string]*ToolGrpSrv
- ArticleDict map[string]*ArticleSrv // 所有的物料对象
- SecResourceDict map[string]*SecondaryResourceSrv // 所有的次要资源对象
- PersonDict map[int]*PersonSrv // 所有人员对象
- SkillDict map[string]*SkillSrv // 所有技能对象
- OrderDict map[string]*OrderSrv // 所有工单对象
- OperationDict map[string]*OperationSrv // 所有订单工序对象
- TmSrv TimeModelSrv // 时间模型
- ProjDict map[string]me_model.Project // 激活的项目字典
- 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[string]*WorkPlaceSrv)
- se.WorkPlaceGrpDict = make(map[string]*WorkPlaceGrpSrv)
- se.ToolDict = make(map[string]*ToolSrv)
- se.ToolGrpDict = make(map[string]*ToolGrpSrv)
- se.ArticleDict = make(map[string]*ArticleSrv)
- se.SecResourceDict = make(map[string]*SecondaryResourceSrv)
- se.PersonDict = make(map[int]*PersonSrv)
- se.SkillDict = make(map[string]*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
- projtablst []me_model.Project
- )
- // 初始化
- se.ProjDict = make(map[string]me_model.Project )
- // 读取激活的项目数据
- engine := db.Eloquent.Master()
- session := engine.NewSession()
- defer session.Close()
- me_dao := me_dal.NewProjectDAO(session, se.PlantNr, "scheduler")
- if projtablst, err = me_dao.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 base_model.WorkPlace
- wptablst []base_model.WorkPlace
- wpgtab base_model.WorkPlaceGrp
- wpgtablst []base_model.WorkPlaceGrp
- ok bool
- )
- engine := db.Eloquent.Master()
- session := engine.NewSession()
- defer session.Close()
- WorkPlaceGrp_dao := base_dal.NewWorkPlaceGrpDAO(session, se.PlantNr, "scheduler")
- // 加载并创建工位组对象
- if wpgtablst, err = WorkPlaceGrp_dao.SelectAll(); err != nil{
- err = errors.New(fmt.Sprintf("加载工位组主数据出错:%v",err))
- return
- }
- for _, wpgtab = range wpgtablst {
- wpg = &WorkPlaceGrpSrv{}
- wpg.Create(wpgtab)
- se.WorkPlaceGrpDict[wpg.WorkPlaceGrpId] = wpg
- }
-
- // 加载并创建工位对象
- WorkPlace_dao := base_dal.NewWorkPlaceDAO(session, se.PlantNr, "scheduler")
- if wptablst, err = WorkPlace_dao.SelectAll(); err != nil{
- err = errors.New(fmt.Sprintf("加载工位主数据出错:%v",err))
- return
- }
- for _, wptab = range wptablst {
- wp = &WorkPlaceSrv{}
- wp.Create(wptab)
- // 生成工位的时间曲线 todo
- err := wp.GetWorkDayList(&se.TmSrv)
- if err != nil {
- fmt.Println(err)
- }
- // 基于产线的时间模型和排班获取产线在指定时间区间内的时间线集合
- wp.GenerateTimeCurve(&se.TmSrv)
-
- // 获取工位组对象
- if wpg, ok = se.WorkPlaceGrpDict[wp.WorkPlaceGrpId]; ok {
- se.WorkPlaceDict[wp.WorkPlaceId] = wp
- se.WorkPlaceGrpDict[wp.WorkPlaceGrpId].WorkPlaceDict[wp.WorkPlaceId] = wp
- }
- }
-
- return
- }
-
- // 加载工具主数据
- func(se *SchedulerSrv)LoadToolData()(err error){
- var(
- toolsrv *ToolSrv
- toolgrpsrv *ToolGrpSrv
- tooltab base_model.Tool
- tooltablst []base_model.Tool
- toolgrptab base_model.ToolGrp
- toolgrptablst []base_model.ToolGrp
- tavailtab base_model.ToolUnAvailTimeLst
- tavailtablst []base_model.ToolUnAvailTimeLst
- timelinesrv TimeLineSrv
- ok bool
- )
-
- engine := db.Eloquent.Master()
- session := engine.NewSession()
- defer session.Close()
-
- // 加载并创建工具组对象
- toolGrp_Dao := base_dal.NewToolGrpDAO(session, se.PlantNr, "scheduler")
- if toolgrptablst, err = toolGrp_Dao.SelectAll(); err != nil{
- err = errors.New(fmt.Sprintf("加载工具组主数据出错:%v",err))
- return
- }
- for _, toolgrptab = range toolgrptablst {
- toolgrpsrv = &ToolGrpSrv{}
- toolgrpsrv.Create(toolgrptab)
- se.ToolGrpDict[toolgrpsrv.ToolGrpId] = toolgrpsrv
- }
-
- // 加载并创建工具对象
- tool_Dao := base_dal.NewToolDAO(session, se.PlantNr, "scheduler")
- if tooltablst, err = tool_Dao.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.ToolGrpId]; ok {
- toolgrpsrv.ToolDict[toolsrv.ToolId] = toolsrv
- }
- // 插入工具
- se.ToolDict[toolsrv.ToolId] = toolsrv
- }
-
- // 基于计划的指定计划时段加载工具的不可用时间数据
- toolUnAvailTimeLst_Dao := base_dal.NewToolUnAvailTimeLstDAO(session, se.PlantNr, "scheduler")
- if tavailtablst, err = toolUnAvailTimeLst_Dao.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.ToolId]; ok{
- timelinesrv = TimeLineSrv{}
- timelinesrv.Init(tavailtab.BegTime.Restore(), tavailtab.EndTime.Restore())
- toolsrv.UnAvailTimeLineArray = append(toolsrv.UnAvailTimeLineArray, timelinesrv)
- }
- }
-
- return
- }
-
- // 加载物料主数据,包括库存及在途
- func(se *SchedulerSrv)LoadArticleData()(err error){
- var(
- artsrv *ArticleSrv
- arttab base_model.Article
- arttablst []base_model.Article
- artstocktab wm_model.Stock
- artstocktablst []wm_model.Stock
- arttransittab wm_model.TransitStock
- arttransittablst []wm_model.TransitStock
- ok bool
- )
-
- engine := db.Eloquent.Master()
- session := engine.NewSession()
- defer session.Close()
-
- // 获取物料主数据
- article_Dao := base_dal.NewArticleDAO(session, se.PlantNr, "scheduler")
- if arttablst, err = article_Dao.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
- }
-
- // 加载物料库存数据
- stock_Dao := wm_dal.NewStockDAO(session, se.PlantNr, "scheduler")
- if artstocktablst, err = stock_Dao.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
- }
- }
-
- // 加载物料在途数据
- transitStock_Dao := wm_dal.NewTransitStockDAO(session, se.PlantNr, "scheduler")
- if arttransittablst, err = transitStock_Dao.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 base_model.Person
- pertablst []base_model.Person
- skilltab base_model.Skill
- skilltablst []base_model.Skill
- perskilltab base_model.PersonSkilllst
- perskilltablst []base_model.PersonSkilllst
- ok bool
- )
-
- engine := db.Eloquent.Master()
- session := engine.NewSession()
- defer session.Close()
-
- // 加载人员主数据
- person_Dao := base_dal.NewPersonDAO(session, se.PlantNr, "scheduler")
- if pertablst, err = person_Dao.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
- }
-
- // 加载技能数据
- skill_Dao := base_dal.NewSkillDAO(session, se.PlantNr, "scheduler")
- if skilltablst, err = skill_Dao.SelectAll(); err != nil{
- err = errors.New(fmt.Sprintf("加载技能主数据出错:%v",err))
- return
- }
- for _, skilltab = range skilltablst {
- skillsrv = &SkillSrv{}
- skillsrv.Create(skilltab)
- se.SkillDict[skillsrv.SkillId] = skillsrv
- }
-
- // 加载技能的人员数据
- personSkill_Dao := base_dal.NewPersonSkilllstDAO(session, se.PlantNr, "scheduler")
- if perskilltablst, err = personSkill_Dao.SelectAll(); err != nil{
- err = errors.New(fmt.Sprintf("加载人员技能主数据出错:%v",err))
- return
- }
- for _, perskilltab = range perskilltablst {
- if skillsrv, ok = se.SkillDict[perskilltab.SkillId]; !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 base_model.SecondaryResource
- resourcetablst []base_model.SecondaryResource
- secressrv *SecondaryResourceSrv
- )
-
- engine := db.Eloquent.Master()
- session := engine.NewSession()
- defer session.Close()
-
- // 加载次要资源
- secondaryResouce_Dao := base_dal.NewSecondaryResourceDAO(session, se.PlantNr, "scheduler")
- if resourcetablst, err = secondaryResouce_Dao.SelectAll(); err != nil{
- err = errors.New(fmt.Sprintf("加载次要资源数据出错:%v",err))
- return
- }
- for _, resourcetab = range resourcetablst {
- secressrv = &SecondaryResourceSrv{}
- secressrv.Create(resourcetab)
- se.SecResourceDict[secressrv.ResourceId] = secressrv
- }
-
- // 初始化次要资源的时间模型
-
- return
- }
-
- // 加载订单主数据(未完成订单)
- func(se *SchedulerSrv)LoadWorkOrderData()(err error){
- var(
- ordsrv *OrderSrv
- opsrv *OperationSrv
- vordtablst []om_model.VWorkorder
- i int
- )
-
- engine := db.Eloquent.Master()
- session := engine.NewSession()
- defer session.Close()
-
- // 加载所有未完成的订单
- workOrder_dao := om_dal.NewWorkOrderDAO(session, se.PlantNr, "scheduler")
- if vordtablst, err = workOrder_dao.SelectAllUnfinishedFullData(); err != nil {
- err = errors.New(fmt.Sprintf("加载工单数据出错:%v",err))
- return
- }else{
- WOOperation_dao := om_dal.NewWOOperationDAO(session, se.PlantNr, "scheduler")
- // 获取订单工序数据
- for i = 0; i < len(vordtablst); i++ {
- session_OmWooperation := session.Table(meta.WOOperation.TableName)
- if err = session_OmWooperation.Where("PlantNr = ? and WorkOrderId = ?",se.PlantNr,
- vordtablst[i].WorkOrder.WorkOrderId).Asc("OperationNr", "SplitNr").Find(&vordtablst[i].WorkOrder.Operationlst); err != nil{
- return
- }
-
- for j := 0; j < len(vordtablst[i].WorkOrder.Operationlst); j++ {
- woOperationData, err := WOOperation_dao.SelectOne(vordtablst[i].WorkOrder.Operationlst[j].WorkOrderId,vordtablst[i].WorkOrder.Operationlst[j].OperationNr,vordtablst[i].WorkOrder.Operationlst[j].SplitNr)
- if err != nil{
- return err
- }
- vordtablst[i].WorkOrder.Operationlst[j] = *woOperationData
- }
- }
- }
- for i = 0; i < len(vordtablst); i++ {
- ordsrv = &OrderSrv{}
- ordsrv.Create(vordtablst[i].WorkOrder)
- 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("|| 工位:%s 可使用时间:%s",wpet.WorkPlaceId, 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 工位:%s 不可使用时间:%s",wpet.WorkPlaceId, 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("|| 工具:%s 可使用时间:%s",tet.ToolId, 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 工具:%s 不可使用时间:%s",tet.ToolId, 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.WorkPlaceGrpId)
- if len(optionalwplst) <= 0 {
- //fmt.Println("工位组:",op.WorkPlaceGrpNr," 无可用工位!")
- // 获取工位组对象
- if wpg, ok = se.WorkPlaceGrpDict[op.WorkPlaceGrpId]; !ok{
- //fmt.Println("工位组:",op.WorkPlaceGrpNr," 不存在!")
- return
- }
- // 无可用工位,则将任务放到工位组等待队列
- wpg.WaitTaskArray = append(wpg.WaitTaskArray, *op)
- return
- }
- if se.SchedRule.ToolConstraintToggle && op.ToolGrpId != ""{
- // 获取可用工位
- optoollst = se.GetAvailToolList(op.ToolGrpId)
- if len(optoollst) <= 0 {
- //fmt.Println("工具组:",op.ToolGrpId," 无可用工位!")
- // 获取工具组对象
- if tg, ok = se.ToolGrpDict[op.ToolGrpId]; !ok{
- //fmt.Println("工具组:",op.ToolGrpId," 不存在!")
- return
- }
- // 无可用工位,则将任务放到工位组等待队列
- tg.WaitTaskArray = append(tg.WaitTaskArray, *op)
- return
- }
- }
- // 有可用工位,取第一个工位进行调度
- op.PlanStartTime = opevent.TriggerTime
- op.PlanEndTime = op.PlanStartTime.Add(op.PlanDuration)
- op.PlanWorkPlaceId = optionalwplst[0].WorkPlaceId
- if se.SchedRule.ToolConstraintToggle && op.ToolGrpId !="" {
- op.PlanToolId = optoollst[0].ToolId
- }
-
- // 基于工序开始生成工序结束事件
- 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.PlanWorkPlaceId]; 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.ToolGrpId != ""{
- if t, ok = se.ToolDict[op.PlanToolId]; 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.PlanWorkPlaceId]; 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.PlanWorkPlaceId))
- return
- }
- if se.SchedRule.ToolConstraintToggle && op.ToolGrpId != ""{
- if t, ok = se.ToolDict[op.PlanToolId]; 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.WorkPlaceId]; !ok {
- fmt.Println(fmt.Sprintf("SchedWPAvail: 工位:%s 不存在",wpevent.WorkPlaceId))
- return
- }
- // 获取工位组对象
- if wpg, ok = se.WorkPlaceGrpDict[wp.WorkPlaceGrpId]; !ok {
- fmt.Println(fmt.Sprintf("工位组:%s 不存在",wp.WorkPlaceGrpId))
- 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.WorkPlaceId]; !ok {
- fmt.Println(fmt.Sprintf("SchedWPUnAvail: 工位:%s 不存在",wpevent.WorkPlaceId))
- 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.ToolId]; !ok {
- fmt.Println(fmt.Sprintf("SchedToolAvail: 工具:%s 不存在",tevent.ToolId))
- return
- }
- // 获取工具组对象
- if tg, ok = se.ToolGrpDict[t.ToolGrpId]; !ok {
- fmt.Println(fmt.Sprintf("工具组:%d 不存在",t.ToolGrpId))
- 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.ToolId]; !ok {
- fmt.Println(fmt.Sprintf("SchedToolUnAvail: 工具:%s 不存在",tevent.ToolId))
- 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(wpgid string)(optionalwplst []OptionalWorkPlaceSrv){
- var(
- wpid string
- wp *WorkPlaceSrv
- wpg *WorkPlaceGrpSrv
- ok bool
- )
-
- // 获取工位组对象
- if wpg, ok = se.WorkPlaceGrpDict[wpgid]; !ok {
- fmt.Println(fmt.Sprintf("GetAvailWorkPlaceList: 工位组:%s 不存在",wpgid))
- return
- }
-
- optionalwplst = []OptionalWorkPlaceSrv{}
- for wpid, _ = range wpg.WorkPlaceDict{
- if wp, ok = se.WorkPlaceDict[wpid]; !ok{
- fmt.Println(fmt.Sprintf("GetAvailWorkPlaceList: 工位:%s 不存在",wpid))
- return
- }
-
- if wp.Status == common.RES_STATUS_AVAIL {
- optionalwp := OptionalWorkPlaceSrv{WorkPlaceId: wp.WorkPlaceId, Priority: 0}
- optionalwplst = append(optionalwplst, optionalwp)
- }
- }
-
- return
- }
-
- // 获取当前可用工具
- func(se *SchedulerSrv)GetAvailToolList(tgid string)(opttoollst []OptionalToolSrv){
- var(
- tid string
- t *ToolSrv
- tg *ToolGrpSrv
- ok bool
- )
-
- // 获取工位组对象
- if tg, ok = se.ToolGrpDict[tgid]; !ok {
- fmt.Println(fmt.Sprintf("GetAvailToolList: 工具组:%s 不存在",tgid))
- return
- }
- fmt.Println("获取工具组的工具.......",tg.ToolGrpId)
- opttoollst = []OptionalToolSrv{}
- //todo
- for tid, _ = range tg.ToolDict{
- if t, ok = se.ToolDict[tid]; !ok{
- fmt.Println(fmt.Sprintf("GetAvailToolList: 工位:%s 不存在",tid))
- return
- }
- fmt.Println(" 工具:",t.ToolId," 状态:",t.Status)
- if t.Status == common.RES_STATUS_AVAIL {
- optionalt := OptionalToolSrv{ToolId: t.ToolId, 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.WorkPlaceId] = wp
- wpg.WorkPlaceDict[wp.WorkPlaceId] = 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.WorkPlaceId] = wp
- wpg.WorkPlaceDict[wp.WorkPlaceId] = wp
- se.WorkPlaceGrpDict[wpg.WorkPlaceGrpId] = 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.WorkPlaceId] = wp
- wpg.WorkPlaceDict[wp.WorkPlaceId] = wp
- se.WorkPlaceGrpDict[wpg.WorkPlaceGrpId] = 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.WorkPlaceId] = wp
- wpg.WorkPlaceDict[wp.WorkPlaceId] = 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.WorkPlaceId] = wp
- wpg.WorkPlaceDict[wp.WorkPlaceId] = wp
- se.WorkPlaceGrpDict[wpg.WorkPlaceGrpId] = 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.ToolId] = t
-
- // 创建工具组
- tg = &ToolGrpSrv{}
- tg.Init("10")
- tg.ToolIdxDict[t.ToolId] = t.ToolId
- se.ToolGrpDict[tg.ToolGrpId] = 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.ToolId] = t
-
- // 创建工具组
- tg = &ToolGrpSrv{}
- tg.Init("20")
- tg.ToolIdxDict[t.ToolId] = t.ToolId
- se.ToolGrpDict[tg.ToolGrpId] = 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, WorkPlaceGrpId: "10", ToolGrpId: "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, WorkPlaceGrpId: "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, WorkPlaceGrpId: "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, WorkPlaceGrpId: "10", ToolGrpId: "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, WorkPlaceGrpId: "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, WorkPlaceGrpId: "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
- }
|