第二代基于事件的高级计划排程引擎
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 

1115 lines
32 KiB

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
}