diff --git a/interval_base.go b/interval_base.go new file mode 100644 index 0000000..2d65003 --- /dev/null +++ b/interval_base.go @@ -0,0 +1,194 @@ +package crontab + +import ( + "strconv" + "strings" + + "474420502.top/eson/structure/priority_list" + randomdata "github.com/Pallinder/go-randomdata" +) + +type randLR struct { + left, right int +} + +// NodeCount 用于priority_list +type NodeCount struct { + plist.Node + randLR +} + +type hInterval struct { + PlanFailCount plist.PriorityList + PlanTrueCount plist.PriorityList + + PlanFail []randLR + PlanTrue []randLR + + Count int + ConstCount int +} + +func (interval *hInterval) reset() { + interval.Count = interval.ConstCount +} + +// Compare NodeCount比较函数 +func (rlr *NodeCount) Compare(v plist.INode) bool { + return rlr.GetValue().(int) > v.GetValue().(int) +} + +func parseIntervalString(crontab string) []interface{} { + var result []interface{} + + values := strings.Split(crontab, ",") + for _, value := range values { + interval := &hInterval{} + + // 次数 + valuesCounts := strings.Split(value, "x") + switch len(valuesCounts) { + case 1: + interval.ConstCount = 1 + + case 2: + count, err := strconv.Atoi(valuesCounts[1]) + if err != nil { + panic(err) + } + interval.ConstCount = count + default: + panic("valuesCounts error, the len is not in range") + } + + // 统计失败与普通间隔值的数组 + failAndNormal := valuesCounts[0] + + valuesFN := strings.Split(failAndNormal, "|") + + for _, FN := range valuesFN { + if FN == "" { + continue + } + + switch FN[0] { + case 'f', 'F': + scharIndex := strings.Index(FN, "?") + if scharIndex != -1 { + + fc := FN[0:scharIndex] + flr := FN[scharIndex+1:] + + node := new(NodeCount) + node.SetValue(getInt(fc[1:])) + node.randLR = parseRandLR(flr) + interval.PlanFailCount.Insert(node) + + } else { + fvalue := FN[1:] + interval.PlanFail = append(interval.PlanFail, parseRandLR(fvalue)) + } + + case 't', 'T': + scharIndex := strings.Index(FN, "?") + if scharIndex != -1 { + tc := FN[0:scharIndex] + tlr := FN[scharIndex+1:] + + node := new(NodeCount) + node.SetValue(getInt(tc[1:])) + node.randLR = parseRandLR(tlr) + interval.PlanTrueCount.Insert(node) + + } else { + tvalue := FN[1:] + interval.PlanTrue = append(interval.PlanTrue, parseRandLR(tvalue)) + } + + default: + FN = "t" + FN + scharIndex := strings.Index(FN, "?") + if scharIndex != -1 { + tc := FN[0:scharIndex] + tlr := FN[scharIndex+1:] + + node := new(NodeCount) + node.SetValue(getInt(tc[1:])) + node.randLR = parseRandLR(tlr) + interval.PlanTrueCount.Insert(node) + + } else { + tvalue := FN[1:] + interval.PlanTrue = append(interval.PlanTrue, parseRandLR(tvalue)) + } + } + } + + interval.reset() + result = append(result, interval) + } + + return result +} + +func parseRandLR(lrvalue string) randLR { + vlen := len(lrvalue) + lastchar := lrvalue[vlen-1] + + lr := strings.Split(lrvalue, "-") + switch len(lr) { + case 1: + lr := randLR{parseTimeValue(lr[0], lastchar), parseTimeValue(lr[0], lastchar)} + return lr + case 2: + + lr := randLR{parseTimeValue(lr[0], lastchar), parseTimeValue(lr[1], lastchar)} + return lr + default: + panic("lr is error") + } +} + +// intervalPriorityListISecond 获取优先链表比较的值 +func intervalPriorityListISecond(planlist *plist.PriorityList, count int) int { + + if planlist.Size() > 0 { + node := new(NodeCount) + node.SetValue(count) + + iwantNode := planlist.GetCompare(node) + if iwantNode != nil { + wantNode := iwantNode.(*NodeCount) + lr := wantNode.randLR + return randomdata.Number(lr.left, lr.right+1) + } + } + + return -1 +} + +func getInt(v string) int { + vint, err := strconv.Atoi(v) + if err != nil { + panic(err) + } + return vint +} + +func parseTimeValue(v string, lastchar byte) int { + + vlen := len(v) + + switch lastchar { + case 's': + return getInt(v[:vlen-1]) + case 'm': + return getInt(v[:vlen-1]) * 60 + case 'h': + return getInt(v[:vlen-1]) * 3600 + case 'd': + return getInt(v[:vlen-1]) * 3600 * 24 + default: + return getInt(v) + } +} diff --git a/yearplan_base.go b/yearplan_base.go new file mode 100644 index 0000000..0ce6352 --- /dev/null +++ b/yearplan_base.go @@ -0,0 +1,107 @@ +package crontab + +import ( + "errors" + "fmt" + "strconv" + "strings" +) + +type timePointer struct { + left, right int + leftlimit, rightlimit int + per int + isAll bool +} + +func (tp *timePointer) String() string { + return fmt.Sprintf("left: %d, right: %d, leftlimit: %d, rightlimit: %d, per: %d", tp.left, tp.right, tp.leftlimit, tp.rightlimit, tp.per) +} + +func createTimePointer(min string, llimit, rlimit int, fixedLeftRight bool) []timePointer { + + var result []timePointer + + exelist := strings.Split(min, ",") + for _, exe := range exelist { + tp := timePointer{} + + takeper := strings.Split(exe, "/") // per + var rangevalue, per string + if len(takeper) == 1 { + rangevalue = exe + per = "1" + } else { + rangevalue = takeper[0] + per = takeper[1] + } + // takeRange + be := strings.Split(rangevalue, "-") + var left, rigth string + switch len(be) { + case 1: + left = be[0] + rigth = be[0] + case 2: + left = be[0] + rigth = be[1] + default: + panic(errors.New("range value is > 2")) + } + + if left == "*" { + tp.left = llimit + } else { + ileft, err := strconv.Atoi(strings.Replace(left, "^", "-", -1)) + if err != nil { + panic(err) + } + tp.left = ileft + } + + if rigth == "*" { + tp.right = rlimit + } else { + iright, err := strconv.Atoi(strings.Replace(rigth, "^", "-", -1)) + if err != nil { + panic(err) + } + tp.right = iright + } + + iper, err := strconv.Atoi(per) + if err != nil { + panic(err) + } + + tp.per = iper + tp.leftlimit = llimit + tp.rightlimit = rlimit + + // 修正左值 + leftfixed := tp.left + if leftfixed < 0 { + leftfixed += tp.rightlimit + 1 + if fixedLeftRight { + tp.left = leftfixed + } + } + + rightfixed := tp.right + if rightfixed < 0 { + rightfixed += tp.rightlimit + 1 + if fixedLeftRight { + tp.right = rightfixed + } + } + + // 全部符合 当左等于左 且 右等于右最大 并且 per == 1 + if leftfixed == tp.leftlimit && rightfixed == tp.rightlimit && tp.per == 1 { + tp.isAll = true + } + + result = append(result, tp) + } + + return result +}