SJA APS后端代码
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.

799 lines
20 KiB

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