package timemodel import ( "container/list" "leit.com/leit_seat_aps/common" "leit.com/leit_seat_aps/db" "time" ) // 时间线段,包括起始时间点和持续时长(秒) type TimeLine struct { StartTime time.Time // 时间曲线的起始时间点 EndTime time.Time // 时间曲线的结束时间点 EffFactor float64 // 效率因子 } // 到小时的可供与实际占用的能力比 type HourlyWorkLoad struct { SpecDate int SpecHour int Capacity int // 可供能力,以秒计算 Workload int // 负载 Percentage float32 // 百分比 } // 到天的可供与实际占用的能力比 type DailyWorkLoad struct { SpecDate int Capacity int // 可供能力,以秒计算int Workload int // 负载 Percentage float32 // 百分比 } // 到周的可供与实际占用的能力比 type WeeklyWorkLoad struct { SpecYear int SpecWeek int Capacity int // 可供能力,以秒计算 Workload int // 负载 Percentage float32 // 百分比 } // 时间曲线 type TimeCurve struct { StartTime time.Time // 时间曲线的起始时间点 EndTime time.Time // 时间曲线的结束时间点 TimeLineList list.List // 时间线集合 EffFactor float64 // 效率因子 } // 日模型 type DayModel struct { DayModelId int ShiftCount int // 班次数 Duration int // 总计可用时间长度(秒) Daymodeltab db.Daymodel } // 周模型内的工作日 type WorkDay struct { WorkDate time.Time DayModelId int } // 周模型 type WeekModel struct { WeekModelId int StartDate time.Time LoopDays int WorkDayList []WorkDay } // 工作日历指定特殊日期的日模型 type WorkCalendar struct { WorkCalendarid int CalDayDict map[time.Time]WorkDay } // 特殊时段 type TimePeriod struct { StartTime int // 时间曲线的起始时间点 EndTime int // 时间曲线的结束时间点 Type int // 增加减少 1=增加;-1=减少 } // 全局时间模型 type TimeModel struct { StartDate time.Time EndDate time.Time DayModelDict map[int]DayModel WeekModelDict map[int]WeekModel WorkCalendarDict map[int]WorkCalendar } // 调度任务 type SchedTask struct { Task string Resource string StartTime time.Time EndTime time.Time } // 时间模型使用对象 type SchedResource struct { Resource string WeekModelId int WorkCalendarid int SchedTaskList []SchedTask PlanTimeCurve TimeCurve // 初始时间曲线 SchedTimeCurve TimeCurve // 调度时间曲线 WeeklyWorkLoadList []WeeklyWorkLoad DailyWorkLoadList []DailyWorkLoad HourlyWorkLoadList []HourlyWorkLoad SpecialTimePeriods []TimePeriod } // 加载时间模型主数据 func TM_LoadTimeModelMasterData(tm *TimeModel) (err error) { // 加载日模型主数据 // 加载周模型主数据 // 加载工作日历主数据 return } // 对于给定的时间曲线,基于起始时间点和指定时间长度,计算结束时间点 func TM_GetEndTimeByStartTimeAndDuration(tc *TimeCurve, st time.Time, dura int) (et time.Time, err error) { var ( calDura, totalDura float64 e *list.Element tl *TimeLine loc *time.Location ) // utc life loc, _ = time.LoadLocation("UTC") if dura <= 0 { et = st return } // 如果计算起始时间点小于计划曲线的起始时间点 if st.Unix() < tc.StartTime.Unix() { if st.In(loc).Add(time.Duration(dura)*time.Second).Unix() < tc.StartTime.Unix() { et = st.In(loc).Add(time.Duration(dura) * time.Second) return } else { calDura = float64(dura) - tc.StartTime.Sub(st).Seconds() } } // 如果计算起始时间点大于等于计划曲线的起始时间点 if st.Unix() >= tc.EndTime.Unix() { et = st.In(loc).Add(time.Duration(dura) * time.Second) return } // 遍历时间曲线 totalDura = 0 for e = tc.TimeLineList.Front(); e != nil; e = e.Next() { tl = e.Value.(*TimeLine) if tl.EndTime.Unix() <= tl.StartTime.Unix() { continue } if tl.EffFactor <= 0 { tl.EffFactor = 1.0 } if st.Unix() <= tl.StartTime.Unix() { totalDura = totalDura + tl.EndTime.Sub(tl.StartTime).Seconds()*tl.EffFactor } else { totalDura = totalDura + tl.EndTime.Sub(st).Seconds()*tl.EffFactor } if totalDura >= calDura { et = tl.EndTime.In(loc).Add(time.Duration(-1 * (totalDura - calDura) / tl.EffFactor)) return } } et = tc.EndTime.In(loc).Add(time.Duration(calDura - totalDura)) return } // 基于给定时间曲线上的起始时间点,计算可用时长 func TM_GetDurationSecondByTimeSpan(tc *TimeCurve, st time.Time, et time.Time) (totalDura float64, err error) { var ( actStartTime time.Time actEndTime time.Time e *list.Element tl *TimeLine ) if et.Unix() <= st.Unix() { totalDura = 0 return } /** 如果计算结束时间点小于计划曲线的起始时间点 |-------------------| <----> **/ if et.Unix() <= tc.StartTime.Unix() { totalDura = et.Sub(st).Seconds() return } /** 如果计算起始时间点大于等于计划曲线的起始时间点 |--------------------| <-----------> **/ if st.Unix() >= tc.EndTime.Unix() { totalDura = et.Sub(st).Seconds() return } /** |-------------------| <------> **/ if st.Unix() <= tc.StartTime.Unix() && et.Unix() > tc.StartTime.Unix() && et.Unix() <= tc.EndTime.Unix() { actStartTime = tc.StartTime actEndTime = et totalDura = tc.StartTime.Sub(st).Seconds() } /** |-------------------| <---------------------------> **/ if st.Unix() < tc.StartTime.Unix() && et.Unix() > tc.EndTime.Unix() { actStartTime = tc.StartTime actEndTime = tc.EndTime totalDura = tc.StartTime.Sub(st).Seconds() + et.Sub(tc.EndTime).Seconds() } /** |-------------------| <------> */ if st.Unix() >= tc.StartTime.Unix() && et.Unix() <= tc.EndTime.Unix() { actStartTime = tc.StartTime actEndTime = tc.EndTime totalDura = 0 } /** |-------------------| <------> */ if st.Unix() >= tc.StartTime.Unix() && et.Unix() > tc.EndTime.Unix() { actStartTime = st actEndTime = tc.EndTime totalDura = et.Sub(tc.EndTime).Seconds() } /** 计算落在计划时间区间内的有效时间 遍历时间曲线的每一条时间线 =================== NO |-------| NO |-----| 条件1.YES |--------| 条件2.YES |---------------------------| 条件3.YES |------------| 条件4.YES |---------------------| */ for e = tc.TimeLineList.Front(); e != nil; e = e.Next() { tl = e.Value.(*TimeLine) if actEndTime.Unix() <= tl.StartTime.Unix() { continue } if actStartTime.Unix() >= tl.EndTime.Unix() { continue } if tl.EffFactor <= 0 { tl.EffFactor = 1 } if actStartTime.Unix() < tl.StartTime.Unix() && actEndTime.Unix() > tl.StartTime.Unix() { // 条件1 if actEndTime.Unix() <= tl.EndTime.Unix() { totalDura = totalDura + actEndTime.Sub(tl.StartTime).Seconds()/tl.EffFactor break } else { // 条件2 totalDura = totalDura + tl.EndTime.Sub(tl.StartTime).Seconds()/tl.EffFactor actStartTime = tl.EndTime } // 条件3 if actStartTime.Unix() >= tl.StartTime.Unix() && actStartTime.Unix() < tl.EndTime.Unix() { if actEndTime.Unix() <= tl.EndTime.Unix() { totalDura = totalDura + actEndTime.Sub(actStartTime).Seconds()/tl.EffFactor break } else { // 条件4 totalDura = totalDura + tl.EndTime.Sub(actStartTime).Seconds()/tl.EffFactor actStartTime = tl.EndTime } } } } return } // 给时间曲线增加时长 func TM_AddTimeSpanToTimeCurve(tc *TimeCurve, st time.Time, et time.Time) (err error) { var ( t TimeLine tl, tlb, tle *TimeLine e, next, nodeBeg, nodeEnd *list.Element ) if et.Unix() <= st.Unix() { return } /** 如果结束时间点小于计划曲线的起始时间点 |-------------------| <----> */ if et.Unix() <= tc.StartTime.Unix() { return } /** 如果计算起始时间点大于等于计划曲线的起始时间点 |--------------------| <-----------> */ if st.Unix() >= tc.EndTime.Unix() { return } /** |-------------------| <---------------------------> */ if st.Unix() < tc.StartTime.Unix() && et.Unix() > tc.EndTime.Unix() { t = TimeLine{} t.StartTime = st t.EndTime = et t.EffFactor = tc.EffFactor tc.TimeLineList.Init() tc.StartTime = st tc.EndTime = et tc.EffFactor = t.EffFactor tc.TimeLineList.PushBack(&t) return } /** |-------------------| <------> */ if st.Unix() < tc.StartTime.Unix() && et.Unix() > tc.StartTime.Unix() && et.Unix() <= tc.EndTime.Unix() { if nodeEnd, err = TM_GetTimeLineInTimeCurve(tc, et); err != nil { return } if nodeEnd != nil { tl = nodeEnd.Value.(*TimeLine) tl.StartTime = st common.RemoveListAllBeforeItem(&tc.TimeLineList, nodeEnd, false) tc.StartTime = st } else { // 删除时段内的节点 for e = tc.TimeLineList.Front(); e != nil; e = next { next = e.Next() tl = e.Value.(*TimeLine) if tl.StartTime.Unix() > st.Unix() && tl.EndTime.Unix() < et.Unix() { tc.TimeLineList.Remove(e) } } t = TimeLine{} t.StartTime = st t.EndTime = et t.EffFactor = tc.EffFactor tc.TimeLineList.PushFront(t) tc.StartTime = st } } /** |-------------------| <------> */ if st.Unix() >= tc.StartTime.Unix() && et.Unix() <= tc.EndTime.Unix() { if nodeBeg, err = TM_GetTimeLineInTimeCurve(tc, st); err != nil { return } if nodeEnd, err = TM_GetTimeLineInTimeCurve(tc, et); err != nil { return } /** 落在可用时段内 情况一: |-------| |****| **/ if nodeBeg != nil && nodeEnd == nil { tlb = nodeBeg.Value.(*TimeLine) // 删除开始节点之后到结束时间点之间的Node for e = nodeBeg.Next(); e != nil; e = next { next = e.Next() tl = e.Value.(*TimeLine) if tl.EndTime.Unix() <= et.Unix() { tc.TimeLineList.Remove(e) } else { break } } // 更新开始节点的结束时间 tlb.EndTime = et } /** 情况二: |-------| |-------| |***| **/ if nodeBeg == nil && nodeEnd == nil { t = TimeLine{} t.StartTime = st t.EndTime = et t.EffFactor = tc.EffFactor // 删除开始节点之后到结束时间点之间的Node for e = tc.TimeLineList.Front(); e != nil; e = next { next = e.Next() tl = e.Value.(*TimeLine) if tl.StartTime.Unix() > st.Unix() && tl.EndTime.Unix() < et.Unix() { tc.TimeLineList.Remove(e) } } // 添加节点到时间曲线中 for e = tc.TimeLineList.Front(); e != nil; e = next { tl = e.Value.(*TimeLine) if tl.EndTime.Unix() >= t.StartTime.Unix() { tc.TimeLineList.InsertAfter(t, e) break } } } /** 情况三: |-------| |-------| |**| **/ if nodeBeg == nil && nodeEnd != nil { tle = nodeEnd.Value.(*TimeLine) // 删除开始节点到结束时间点之间的Node for e = tc.TimeLineList.Front(); e != nil; e = next { next = e.Next() tl = e.Value.(*TimeLine) if tl.StartTime.Unix() > st.Unix() && tl.EndTime.Unix() < et.Unix() { tc.TimeLineList.Remove(e) } } // 更新结束节点的开始时间 tle.StartTime = st } /** 情况四: |-------| |-------| |****| */ if nodeBeg != nil && nodeEnd != nil { if nodeBeg != nodeEnd { tlb = nodeBeg.Value.(*TimeLine) tle = nodeEnd.Value.(*TimeLine) if tlb != tle { // 删除两节点之间的所有节点 for e = nodeBeg.Next(); e != nil && e != nodeEnd; e = next { next = e.Next() tc.TimeLineList.Remove(e) } // 更新起始时间点 tlb.EndTime = tle.EndTime tc.TimeLineList.Remove(nodeEnd) } } } } /** |-------------------| <------> */ if st.Unix() >= tc.StartTime.Unix() && st.Unix() < tc.EndTime.Unix() && et.Unix() > tc.EndTime.Unix() { if nodeBeg, err = TM_GetTimeLineInTimeCurve(tc, st); err != nil { return } if nodeBeg != nil { tl = nodeBeg.Value.(*TimeLine) tl.EndTime = et common.RemoveListAllAfterItem(&tc.TimeLineList, nodeBeg, false) tc.EndTime = et } else { // 删除时段内的节点 for e = tc.TimeLineList.Front(); e != nil; e = next { next = e.Next() tl = e.Value.(*TimeLine) if tl.StartTime.Unix() > st.Unix() && tl.EndTime.Unix() < et.Unix() { tc.TimeLineList.Remove(e) } } t = TimeLine{} t.StartTime = st t.EndTime = et t.EffFactor = tc.EffFactor tc.TimeLineList.PushBack(t) tc.EndTime = et } } return } // 给时间曲线减少时长 func TM_SubtractTimeSpanFromTimeCurve(tc *TimeCurve, st time.Time, et time.Time) (err error) { var ( t TimeLine tl, tlb, tle *TimeLine e, next, nodeBeg, nodeEnd *list.Element ) if et.Unix() <= st.Unix() { return } /** 如果结束时间点小于计划曲线的起始时间点 |-------------------| <----> */ if et.Unix() <= tc.StartTime.Unix() { return } /** 如果计算起始时间点大于等于计划曲线的起始时间点 |--------------------| <-----------> */ if st.Unix() >= tc.EndTime.Unix() { return } /** |-------------------| <---------------------------> */ if st.Unix() < tc.StartTime.Unix() && et.Unix() > tc.EndTime.Unix() { tc.TimeLineList.Init() return } /** |-------------------| <------> */ if st.Unix() < tc.StartTime.Unix() && et.Unix() > tc.StartTime.Unix() && et.Unix() <= tc.EndTime.Unix() { if nodeEnd, err = TM_GetTimeLineInTimeCurve(tc, et); err != nil { return } if nodeEnd != nil { tl = nodeEnd.Value.(*TimeLine) tl.StartTime = et common.RemoveListAllBeforeItem(&tc.TimeLineList, nodeEnd, false) tc.StartTime = et } else { // 删除时段内的节点 for e = tc.TimeLineList.Front(); e != nil; e = next { next = e.Next() tl = e.Value.(*TimeLine) if tl.StartTime.Unix() > st.Unix() && tl.EndTime.Unix() < et.Unix() { tc.TimeLineList.Remove(e) } } tl = tc.TimeLineList.Front().Value.(*TimeLine) tc.StartTime = tl.StartTime } } /** |-------------------| <------> */ if st.Unix() >= tc.StartTime.Unix() && et.Unix() <= tc.EndTime.Unix() { if nodeBeg, err = TM_GetTimeLineInTimeCurve(tc, st); err != nil || nodeBeg == nil { return } if nodeEnd, err = TM_GetTimeLineInTimeCurve(tc, et); err != nil || nodeEnd == nil { return } /** 落在可用时段内 情况一: |-------| |****| **/ if nodeBeg != nil && nodeEnd == nil { tlb = nodeBeg.Value.(*TimeLine) // 删除开始节点之后到结束时间点之间的Node for e = nodeBeg.Next(); e != nil; e = next { next = e.Next() tl = e.Value.(*TimeLine) if tl.EndTime.Unix() <= et.Unix() { tc.TimeLineList.Remove(e) } else { break } } // 更新开始节点的结束时间 tlb.EndTime = st } /** 情况二: |-------| |-------| |***| **/ if nodeBeg == nil && nodeEnd == nil { t = TimeLine{} t.StartTime = st t.EndTime = et t.EffFactor = tc.EffFactor // 删除开始节点之后到结束时间点之间的Node for e = tc.TimeLineList.Front(); e != nil; e = next { next = e.Next() tl = e.Value.(*TimeLine) if tl.StartTime.Unix() > st.Unix() && tl.EndTime.Unix() < et.Unix() { tc.TimeLineList.Remove(e) } } } /** 情况三: |-------| |-------| |**| **/ if nodeBeg == nil && nodeEnd != nil { tle = nodeEnd.Value.(*TimeLine) // 删除开始节点到结束时间点之间的Node for e = tc.TimeLineList.Front(); e != nil; e = next { next = e.Next() tl = e.Value.(*TimeLine) if tl.StartTime.Unix() > st.Unix() && tl.EndTime.Unix() < et.Unix() { tc.TimeLineList.Remove(e) } } // 更新结束节点的开始时间 tle.StartTime = et } /** 情况四: |-------| |-------| |****| */ if nodeBeg != nil && nodeEnd != nil { if nodeBeg != nodeEnd { tlb = nodeBeg.Value.(*TimeLine) tle = nodeEnd.Value.(*TimeLine) if tlb != tle { // 删除两节点之间的所有节点 for e = nodeBeg.Next(); e != nil && e != nodeEnd; e = next { next = e.Next() tc.TimeLineList.Remove(e) } // 更新起始时间点 tlb.EndTime = st tle.StartTime = et } } else { tlb.EndTime = st t = TimeLine{} t.StartTime = et t.EndTime = tle.EndTime t.EffFactor = tc.EffFactor tc.TimeLineList.InsertAfter(t, nodeBeg) } } } /** |-------------------| <------> */ if st.Unix() >= tc.StartTime.Unix() && st.Unix() < tc.EndTime.Unix() && et.Unix() > tc.EndTime.Unix() { if nodeBeg, err = TM_GetTimeLineInTimeCurve(tc, st); err != nil { return } if nodeBeg != nil { tl = nodeBeg.Value.(*TimeLine) tl.EndTime = st common.RemoveListAllAfterItem(&tc.TimeLineList, nodeBeg, false) tc.EndTime = st } else { // 删除时段内的节点 for e = tc.TimeLineList.Front(); e != nil; e = next { next = e.Next() tl = e.Value.(*TimeLine) if tl.StartTime.Unix() > st.Unix() && tl.EndTime.Unix() < et.Unix() { tc.TimeLineList.Remove(e) } } // 获取最后一个节点 tl = tc.TimeLineList.Back().Value.(*TimeLine) tc.EndTime = tl.EndTime } } return } // 获取某时间点在时间曲线上的位置(哪条时间线上) func TM_GetTimeLineInTimeCurve(tc *TimeCurve, tp time.Time) (node *list.Element, err error) { var ( e *list.Element tl, prevtl *TimeLine ) /** 如果结束时间点小于计划曲线的起始时间点 |-------------------| * * */ if tp.Unix() < tc.StartTime.Unix() || tp.Unix() > tc.EndTime.Unix() { node = nil return } for e = tc.TimeLineList.Front(); e != nil; e = e.Next() { tl = e.Value.(*TimeLine) if tp.Unix() >= tl.StartTime.Unix() && tp.Unix() <= tl.EndTime.Unix() { node = e return } // 如果正好落在两段时间之内不可用时段,则返回后面时段的位置 if e.Prev() != nil { prevtl = e.Prev().Value.(*TimeLine) if tp.Unix() >= prevtl.EndTime.Unix() && tp.Unix() <= tl.StartTime.Unix() { node = e return } } } node = nil return } // 基于指定周模型,工作日历,生成基本时间曲线 func TM_CreateTimeCurveByWeekModelAndWorkCalendar(wmid int, wcid int, tm *TimeModel) (tc TimeCurve, err error) { var ( d time.Time dmodel DayModel tl TimeLine ) // 初始化时间曲线 tc = TimeCurve{} tc.StartTime = tm.StartDate tc.EndTime = tm.EndDate // 基于起始日期遍历每一天 for d = tm.StartDate; d.Unix() <= tm.EndDate.Unix(); d = d.Add(1 * time.Hour * 24) { // 基于周模型ID和工作日历ID获取这一天的日模型 // 基于日模型生成时间线加入时间曲线对象 tl = TimeLine{} tl = tl if dmodel.Daymodeltab.S1_activ == 1 { } if dmodel.Daymodeltab.S2_activ == 1 { } if dmodel.Daymodeltab.S3_activ == 1 { } if dmodel.Daymodeltab.S4_activ == 1 { } } return } // 基于指定的时间点和时间线返回可用时间点 func TM_GetAvailStartTimeBySpecifiedTime(tc *TimeCurve, tp time.Time) (atp time.Time, err error) { var ( e *list.Element tl, tlnext *TimeLine ) if tp.Unix() <= tc.StartTime.Unix() { atp = tc.StartTime return } if tp.Unix() >= tc.EndTime.Unix() { atp = tc.EndTime return } for e = tc.TimeLineList.Front(); e != nil; e = e.Next() { tl = e.Value.(*TimeLine) if tp.Unix() >= tl.StartTime.Unix() && tp.Unix() <= tl.EndTime.Unix() { atp = tp return } if e.Next() != nil { tlnext = e.Next().Value.(*TimeLine) if tp.Unix() > tl.EndTime.Unix() && tp.Unix() < tlnext.StartTime.Unix() { atp = tlnext.StartTime return } } } // 默认返回 atp = tc.StartTime return } // 打印时间曲线 func TM_PrintTimeCurve(tc *TimeCurve) { }