package service import ( "container/list" "fmt" "leit.com/aps_engine/utils" "time" ) type TimeCurveSrv struct { StartTime time.Time // 时间曲线的起始时间点 EndTime time.Time // 时间曲线的结束时间点 EffFactor float64 // 效率因子 TimeLineArray []TimeLineSrv TimeLineList *list.List } // 初始化 func(tcs *TimeCurveSrv)Init(starttime, endtime time.Time){ tcs.StartTime = starttime tcs.EndTime = endtime tcs.TimeLineArray = []TimeLineSrv{} } // 将时间数组转化成列表 func (tcs *TimeCurveSrv) GetLineList() { // 初始化 tcs.TimeLineList = list.New() for _, tlsrv := range tcs.TimeLineArray { tcs.TimeLineList.PushBack(tlsrv) } } // 将时间列表转化成数组 func (tcs *TimeCurveSrv) GetLineArray() { // 初始化数组 tcs.TimeLineArray = []TimeLineSrv{} for e := tcs.TimeLineList.Front(); e != nil; e = e.Next() { tlsrv := e.Value.(TimeLineSrv) tcs.TimeLineArray = append(tcs.TimeLineArray, tlsrv) } } // 获取某时间点在时间曲线上的位置(哪条时间线上) func (tcs *TimeCurveSrv) GetTimeLine(tp time.Time) (node *list.Element, err error) { var ( e *list.Element tl, prevtl TimeLineSrv ) /** 如果结束时间点小于计划曲线的起始时间点 |-------------------| * * */ if tp.Unix() < tcs.StartTime.Unix() || tp.Unix() > tcs.EndTime.Unix() { node = nil fmt.Println(11) return } for e = tcs.TimeLineList.Front(); e != nil; e = e.Next() { tl = e.Value.(TimeLineSrv) if tp.Unix() >= tl.StartTime.Unix() && tp.Unix() <= tl.EndTime.Unix() { node = e return } // 如果正好落在两段时间之内不可用时段,则返回后面时段的位置 if e.Prev() != nil { prevtl = e.Prev().Value.(TimeLineSrv) if tp.Unix() >= prevtl.EndTime.Unix() && tp.Unix() <= tl.StartTime.Unix() { node = e return } } } node = nil return } // 删除指定时间线节点之后的所有节点 func (tcs *TimeCurveSrv) RemoveListAllAfterItem(delNode *list.Element, delItem bool) (err error) { var ( e, el, next, n *list.Element ) // 删除litem之后所有的节点 for e = tcs.TimeLineList.Front(); e != nil; e = e.Next() { if delNode == e { next = e.Next() if delItem { tcs.TimeLineList.Remove(e) } for el = next; el != nil; el = n { n = el.Next() tcs.TimeLineList.Remove(el) } break } } return } // 删除指定时间线节点之前的所有节点 func (tcs *TimeCurveSrv) RemoveListAllBeforeItem(delNode *list.Element, delItem bool) (err error) { var ( e, el, prev, p *list.Element ) // 删除litem之前所有的节点 for e = tcs.TimeLineList.Front(); e != nil; e = e.Next() { if delNode == e { prev = e.Prev() if delItem { tcs.TimeLineList.Remove(e) } for el = prev; el != nil; el = p { p = el.Prev() tcs.TimeLineList.Remove(el) } break } } return } // 增加工作时段 func (tcs *TimeCurveSrv) AddTimeLine(addtlsrv TimeLineSrv) (err error) { var ( tlsrv TimeLineSrv tl, tlb, tle *TimeLineSrv e, next, nodeBeg, nodeEnd *list.Element ) if addtlsrv.EndTime.Unix() <= addtlsrv.StartTime.Unix() { return } /** 如果结束时间点小于计划曲线的起始时间点 |-------------------| <----> */ if addtlsrv.EndTime.Unix() <= tcs.StartTime.Unix() { return } /** 如果计算起始时间点大于等于计划曲线的起始时间点 |--------------------| <-----------> */ if addtlsrv.StartTime.Unix() >= tcs.EndTime.Unix() { return } /** |-------------------| <---------------------------> */ if addtlsrv.StartTime.Unix() < tcs.StartTime.Unix() && addtlsrv.EndTime.Unix() > tcs.EndTime.Unix() { tlsrv = TimeLineSrv{} tlsrv.StartTime = addtlsrv.StartTime tlsrv.EndTime = addtlsrv.EndTime tlsrv.EffFactor = addtlsrv.EffFactor tcs.TimeLineList.Init() tcs.StartTime = addtlsrv.StartTime tcs.EndTime = addtlsrv.EndTime tcs.EffFactor = addtlsrv.EffFactor tcs.TimeLineList.PushBack(tlsrv) return } /** |-------------------| <------> */ if addtlsrv.StartTime.Unix() < tcs.StartTime.Unix() && addtlsrv.EndTime.Unix() > tcs.StartTime.Unix() && addtlsrv.EndTime.Unix() <= tcs.EndTime.Unix() { if nodeEnd, err = tcs.GetTimeLine(addtlsrv.EndTime); err != nil { return } if nodeEnd != nil { tl = nodeEnd.Value.(*TimeLineSrv) tl.StartTime = addtlsrv.StartTime tcs.RemoveListAllBeforeItem(nodeEnd, false) tcs.StartTime = addtlsrv.StartTime } else { // 删除时段内的节点 for e = tcs.TimeLineList.Front(); e != nil; e = next { next = e.Next() tl = e.Value.(*TimeLineSrv) if tl.StartTime.Unix() > addtlsrv.StartTime.Unix() && tl.EndTime.Unix() < addtlsrv.EndTime.Unix() { tcs.TimeLineList.Remove(e) } } tlsrv = TimeLineSrv{} tlsrv.StartTime = addtlsrv.StartTime tlsrv.EndTime = addtlsrv.EndTime tlsrv.EffFactor = tcs.EffFactor tcs.TimeLineList.PushFront(tlsrv) tcs.StartTime = addtlsrv.StartTime } } /** |-------------------| <------> */ if addtlsrv.StartTime.Unix() >= tcs.StartTime.Unix() && addtlsrv.EndTime.Unix() <= tcs.EndTime.Unix() { if nodeBeg, err = tcs.GetTimeLine(addtlsrv.StartTime); err != nil { return } if nodeEnd, err = tcs.GetTimeLine(addtlsrv.EndTime); err != nil { return } /** 落在可用时段内 情况一: |-------| |****| **/ if nodeBeg != nil && nodeEnd == nil { tlb = nodeBeg.Value.(*TimeLineSrv) // 删除开始节点之后到结束时间点之间的Node for e = nodeBeg.Next(); e != nil; e = next { next = e.Next() tl = e.Value.(*TimeLineSrv) if tl.EndTime.Unix() <= addtlsrv.EndTime.Unix() { tcs.TimeLineList.Remove(e) } else { break } } // 更新开始节点的结束时间 tlb.EndTime = addtlsrv.EndTime } /** 情况二: |-------| |-------| |***| **/ if nodeBeg == nil && nodeEnd == nil { tlsrv = TimeLineSrv{} tlsrv.StartTime = addtlsrv.StartTime tlsrv.EndTime = addtlsrv.EndTime tlsrv.EffFactor = addtlsrv.EffFactor // 删除开始节点之后到结束时间点之间的Node for e = tcs.TimeLineList.Front(); e != nil; e = next { next = e.Next() tl = e.Value.(*TimeLineSrv) if tl.StartTime.Unix() > addtlsrv.StartTime.Unix() && tl.EndTime.Unix() < addtlsrv.EndTime.Unix() { tcs.TimeLineList.Remove(e) } } // 添加节点到时间曲线中 for e = tcs.TimeLineList.Front(); e != nil; e = next { tl = e.Value.(*TimeLineSrv) if tl.EndTime.Unix() >= tlsrv.StartTime.Unix() { tcs.TimeLineList.InsertAfter(tlsrv, e) break } } } /** 情况三: |-------| |-------| |**| **/ if nodeBeg == nil && nodeEnd != nil { tle = nodeEnd.Value.(*TimeLineSrv) // 删除开始节点到结束时间点之间的Node for e = tcs.TimeLineList.Front(); e != nil; e = next { next = e.Next() tl = e.Value.(*TimeLineSrv) if tl.StartTime.Unix() > addtlsrv.StartTime.Unix() && tl.EndTime.Unix() < addtlsrv.EndTime.Unix() { tcs.TimeLineList.Remove(e) } } // 更新结束节点的开始时间 tle.StartTime = addtlsrv.StartTime } /** 情况四: |-------| |-------| |****| */ if nodeBeg != nil && nodeEnd != nil { if nodeBeg != nodeEnd { tlb = nodeBeg.Value.(*TimeLineSrv) tle = nodeEnd.Value.(*TimeLineSrv) if tlb != tle { // 删除两节点之间的所有节点 for e = nodeBeg.Next(); e != nil && e != nodeEnd; e = next { next = e.Next() tcs.TimeLineList.Remove(e) } // 更新起始时间点 tlb.EndTime = tle.EndTime tcs.TimeLineList.Remove(nodeEnd) } } } } /** |-------------------| <------> */ if addtlsrv.StartTime.Unix() >= tcs.StartTime.Unix() && addtlsrv.StartTime.Unix() < tcs.EndTime.Unix() && addtlsrv.EndTime.Unix() > tcs.EndTime.Unix() { if nodeBeg, err = tcs.GetTimeLine(addtlsrv.StartTime); err != nil { return } if nodeBeg != nil { tl = nodeBeg.Value.(*TimeLineSrv) tl.EndTime = addtlsrv.EndTime tcs.RemoveListAllAfterItem(nodeBeg, false) tcs.EndTime = addtlsrv.EndTime } else { // 删除时段内的节点 for e = tcs.TimeLineList.Front(); e != nil; e = next { next = e.Next() tl = e.Value.(*TimeLineSrv) if tl.StartTime.Unix() > addtlsrv.StartTime.Unix() && tl.EndTime.Unix() < addtlsrv.EndTime.Unix() { tcs.TimeLineList.Remove(e) } } tlsrv = TimeLineSrv{} tlsrv.StartTime = addtlsrv.StartTime tlsrv.EndTime = addtlsrv.EndTime tlsrv.EffFactor = addtlsrv.EffFactor tcs.TimeLineList.PushBack(tlsrv) tcs.EndTime = addtlsrv.EndTime } } return } // 减少工作时段 func (tcs *TimeCurveSrv) SubTimeLine(subtlsrv TimeLineSrv) (err error) { var ( tlsrv TimeLineSrv tl, tlb, tle TimeLineSrv e, next, nodeBeg, nodeEnd *list.Element ) if subtlsrv.EndTime.Unix() <= subtlsrv.StartTime.Unix() { return } /** 如果结束时间点小于计划曲线的起始时间点 |-------------------| <----> */ if subtlsrv.EndTime.Unix() <= tcs.StartTime.Unix() { return } /** 如果计算起始时间点大于等于计划曲线的起始时间点 |--------------------| <-----------> */ if subtlsrv.StartTime.Unix() >= tcs.EndTime.Unix() { return } /** |-------------------| <---------------------------> */ if subtlsrv.StartTime.Unix() < tcs.StartTime.Unix() && subtlsrv.EndTime.Unix() > tcs.EndTime.Unix() { tcs.TimeLineList.Init() return } /** |-------------------| <------> */ if subtlsrv.StartTime.Unix() < tcs.StartTime.Unix() && subtlsrv.EndTime.Unix() > tcs.StartTime.Unix() && subtlsrv.EndTime.Unix() <= tcs.EndTime.Unix() { if nodeEnd, err = tcs.GetTimeLine(subtlsrv.EndTime); err != nil { return } if nodeEnd != nil { tl = nodeEnd.Value.(TimeLineSrv) tl.StartTime = subtlsrv.EndTime tcs.RemoveListAllBeforeItem(nodeEnd, false) tcs.StartTime = subtlsrv.EndTime } else { // 删除时段内的节点 for e = tcs.TimeLineList.Front(); e != nil; e = next { next = e.Next() tl = e.Value.(TimeLineSrv) if tl.StartTime.Unix() > subtlsrv.StartTime.Unix() && tl.EndTime.Unix() < subtlsrv.EndTime.Unix() { tcs.TimeLineList.Remove(e) } } tl = tcs.TimeLineList.Front().Value.(TimeLineSrv) tcs.StartTime = tl.StartTime } } /** |-------------------| <------> */ if subtlsrv.StartTime.Unix() >= tcs.StartTime.Unix() && subtlsrv.EndTime.Unix() <= tcs.EndTime.Unix() { if nodeBeg, err = tcs.GetTimeLine(subtlsrv.StartTime); err != nil || nodeBeg == nil { return } if nodeEnd, err = tcs.GetTimeLine(subtlsrv.EndTime); err != nil || nodeEnd == nil { return } /** 落在可用时段内 情况一: |-------| |****| **/ if nodeBeg != nil && nodeEnd == nil { tlb = nodeBeg.Value.(TimeLineSrv) // 删除开始节点之后到结束时间点之间的Node for e = nodeBeg.Next(); e != nil; e = next { next = e.Next() tl = e.Value.(TimeLineSrv) if tl.EndTime.Unix() <= subtlsrv.EndTime.Unix() { tcs.TimeLineList.Remove(e) } else { break } } // 更新开始节点的结束时间 tlb.EndTime = subtlsrv.StartTime } /** 情况二: |-------| |-------| |***| **/ if nodeBeg == nil && nodeEnd == nil { tlsrv = TimeLineSrv{} tlsrv.StartTime = subtlsrv.StartTime tlsrv.EndTime = subtlsrv.EndTime tlsrv.EffFactor = subtlsrv.EffFactor // 删除开始节点之后到结束时间点之间的Node for e = tcs.TimeLineList.Front(); e != nil; e = next { next = e.Next() tl = e.Value.(TimeLineSrv) if tl.StartTime.Unix() > subtlsrv.StartTime.Unix() && tl.EndTime.Unix() < subtlsrv.EndTime.Unix() { tcs.TimeLineList.Remove(e) } } } /** 情况三: |-------| |-------| |**| **/ if nodeBeg == nil && nodeEnd != nil { tle = nodeEnd.Value.(TimeLineSrv) // 删除开始节点到结束时间点之间的Node for e = tcs.TimeLineList.Front(); e != nil; e = next { next = e.Next() tl = e.Value.(TimeLineSrv) if tl.StartTime.Unix() > subtlsrv.StartTime.Unix() && tl.EndTime.Unix() < subtlsrv.EndTime.Unix() { tcs.TimeLineList.Remove(e) } } // 更新结束节点的开始时间 tle.StartTime = subtlsrv.EndTime } /** 情况四: |-------| |-------| |****| */ if nodeBeg != nil && nodeEnd != nil { if nodeBeg != nodeEnd { tlb = nodeBeg.Value.(TimeLineSrv) tle = nodeEnd.Value.(TimeLineSrv) if tlb != tle { // 删除两节点之间的所有节点 for e = nodeBeg.Next(); e != nil && e != nodeEnd; e = next { next = e.Next() tcs.TimeLineList.Remove(e) } // 更新起始时间点 tlb.EndTime = subtlsrv.StartTime tle.StartTime = subtlsrv.EndTime } } else { tlb.EndTime = subtlsrv.StartTime tlsrv = TimeLineSrv{} tlsrv.StartTime = subtlsrv.StartTime tlsrv.EndTime = subtlsrv.EndTime tlsrv.EffFactor = subtlsrv.EffFactor tcs.TimeLineList.InsertAfter(tlsrv, nodeBeg) } } } /** |-------------------| <------> */ if subtlsrv.StartTime.Unix() >= tcs.StartTime.Unix() && subtlsrv.StartTime.Unix() < tcs.EndTime.Unix() && subtlsrv.EndTime.Unix() > tcs.EndTime.Unix() { fmt.Println(777) if nodeBeg, err = tcs.GetTimeLine(subtlsrv.StartTime); err != nil { return } if nodeBeg != nil { tl = nodeBeg.Value.(TimeLineSrv) tl.EndTime = subtlsrv.StartTime tcs.RemoveListAllAfterItem(nodeBeg, false) tcs.EndTime = subtlsrv.StartTime } else { // 删除时段内的节点 for e = tcs.TimeLineList.Front(); e != nil; e = next { next = e.Next() tl = e.Value.(TimeLineSrv) if tl.StartTime.Unix() > subtlsrv.StartTime.Unix() && tl.EndTime.Unix() < subtlsrv.EndTime.Unix() { tcs.TimeLineList.Remove(e) } } // 获取最后一个节点 tl = tcs.TimeLineList.Back().Value.(TimeLineSrv) tcs.EndTime = tl.EndTime } } return } // 基于起始时间点和Duration计算在当前时间曲线上的结束时间点 func (tcs *TimeCurveSrv) CalEndTime(startTime time.Time, duration time.Duration) (sTime time.Time ,endTime time.Time) { var ( i int zeroDuration, calDuration, totalDuration time.Duration ) // 处理临界条件 if duration <= 0 { endTime = startTime return } // 如果计算起始时间点大于等于计划曲线的结束时间点 if startTime.Unix() >= tcs.EndTime.Unix() { endTime = startTime.Add(duration) return } // 初始化 calDuration = duration endTime = startTime // 如果计算起始时间点小于计划曲线的起始时间点 if startTime.Unix() < tcs.StartTime.Unix() { if startTime.Add(duration).Unix() <= tcs.StartTime.Unix() { endTime = startTime.Add(duration) return } else { calDuration = duration - tcs.StartTime.Sub(startTime) } } if len(tcs.TimeLineArray) <= 0 { return } totalDuration = 0 zeroDuration = 0 /************ * / ------ / *** ------***----- / * / -----*** ------***--- / * 0 1 2 3 * 横线代表可用时间,*代表不可用时间 *问题: 求出时间2 的时间节点? 已知 时间1和时间3的节点,0-3的可用时间间隔,1-2的可用时间间隔 *逻辑: 求出 0-1的时间间隔, 用0-3的时间间隔 减去(0-1)减去(1-2) 计算出(2-3)间隔 ,用3点时间点减去(2-3)时间间隔得出时间2的时间点 **********************/ startbool := true sTime = startTime for i = 0; i < len(tcs.TimeLineArray); i++ { if startTime.Unix() >= tcs.TimeLineArray[i].EndTime.Unix() { continue } if startbool { //记录时间0的节点 zeroStartTime := tcs.TimeLineArray[i].StartTime //计算0-1时间间隔 zeroDuration = utils.GetDuration(zeroStartTime, startTime, tcs.TimeLineArray[i].EffFactor) //如果开始时间落到中断时间区间内,则开始时间变成可用时间的开始时间 if startTime.Unix() < tcs.TimeLineArray[i].StartTime.Unix(){ sTime = tcs.TimeLineArray[i].StartTime } startbool = false } totalDuration = totalDuration + tcs.TimeLineArray[i].Duration if (totalDuration - zeroDuration) >= calDuration { endTime = tcs.TimeLineArray[i].GetEndTimeByDuration(totalDuration - calDuration - zeroDuration) return } //endTime = tcs.TimeLineArray[i].EndTime.Add(calDuration - totalDuration) } return } // 基于给定的两个时间点获取时间曲线上的Duration func (tcs *TimeCurveSrv) CalDuration(startTime, endTime time.Time) (totalDuration time.Duration) { var ( i int actStartTime, actEndTime time.Time ) // 初始化 totalDuration = 0 // 临界条件处理 if startTime.Unix() >= endTime.Unix() { return } if endTime.Unix() <= tcs.StartTime.Unix() || startTime.Unix() >= tcs.EndTime.Unix() { //totalDuration = endTime.Sub(startTime) return } // |-------------------| // <------> if startTime.Unix() < tcs.StartTime.Unix() && endTime.Unix() > tcs.StartTime.Unix() && endTime.Unix() <= tcs.EndTime.Unix() { actStartTime = tcs.StartTime actEndTime = endTime totalDuration = tcs.StartTime.Sub(startTime) } // |-------------------| // <---------------------------> if startTime.Unix() < tcs.StartTime.Unix() && endTime.Unix() > tcs.EndTime.Unix() { actStartTime = tcs.StartTime actEndTime = tcs.EndTime totalDuration = tcs.StartTime.Sub(startTime) + endTime.Sub(tcs.EndTime) } // |-------------------| // <------> if startTime.Unix() >= tcs.StartTime.Unix() && endTime.Unix() <= tcs.EndTime.Unix() { actStartTime = startTime actEndTime = endTime totalDuration = 0 } // |-------------------| // <------> if startTime.Unix() >= tcs.StartTime.Unix() && endTime.Unix() > tcs.EndTime.Unix() { actStartTime = startTime actEndTime = tcs.EndTime totalDuration = endTime.Sub(tcs.EndTime) } /**# 计算落在计划时间区间内的有效时间 # =================== #NO |-------| #NO |-----| #1.YES |--------| #2.YES |---------------------------| #3.YES |------------| #4.YES |---------------------| **/ for i = 0; i < len(tcs.TimeLineArray); i++ { if actEndTime.Unix() <= tcs.TimeLineArray[i].StartTime.Unix() || actStartTime.Unix() >= tcs.TimeLineArray[i].EndTime.Unix() { continue } if tcs.TimeLineArray[i].EffFactor <= 0 { tcs.TimeLineArray[i].EffFactor = 1.0 } if actStartTime.Unix() < tcs.TimeLineArray[i].StartTime.Unix() && actEndTime.Unix() > tcs.TimeLineArray[i].StartTime.Unix() { if actEndTime.Unix() <= tcs.TimeLineArray[i].EndTime.Unix() { // 条件1 totalDuration = totalDuration + tcs.TimeLineArray[i].GetDurationByEndTime(actEndTime) break } else { // 条件2 totalDuration = totalDuration + tcs.TimeLineArray[i].Duration actStartTime = tcs.TimeLineArray[i].EndTime } } if actStartTime.Unix() >= tcs.TimeLineArray[i].StartTime.Unix() && actStartTime.Unix() < tcs.TimeLineArray[i].EndTime.Unix() { if actEndTime.Unix() <= tcs.TimeLineArray[i].EndTime.Unix() { // 条件3 totalDuration = totalDuration + tcs.TimeLineArray[i].GetDurationByStartEndTime(actStartTime, actEndTime) break } else { // 条件4 totalDuration = totalDuration + tcs.TimeLineArray[i].GetDurationByStartTime(actStartTime) actStartTime = tcs.TimeLineArray[i].EndTime } } } return }