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
|
|
}
|