| @@ -35,6 +35,11 @@ func (e *NodeEnv) ToEnvWorker(worker exec.WorkerInfo) { | |||||
| e.Worker = worker | e.Worker = worker | ||||
| } | } | ||||
| func (e *NodeEnv) CopyFrom(other *NodeEnv) { | |||||
| e.Type = other.Type | |||||
| e.Worker = other.Worker | |||||
| } | |||||
| func (e *NodeEnv) Equals(other *NodeEnv) bool { | func (e *NodeEnv) Equals(other *NodeEnv) bool { | ||||
| if e.Type != other.Type { | if e.Type != other.Type { | ||||
| return false | return false | ||||
| @@ -7,6 +7,7 @@ import ( | |||||
| "github.com/samber/lo" | "github.com/samber/lo" | ||||
| "gitlink.org.cn/cloudream/common/pkgs/types" | "gitlink.org.cn/cloudream/common/pkgs/types" | ||||
| "gitlink.org.cn/cloudream/common/utils/math2" | |||||
| "gitlink.org.cn/cloudream/common/utils/serder" | "gitlink.org.cn/cloudream/common/utils/serder" | ||||
| ) | ) | ||||
| @@ -170,18 +171,9 @@ type SegmentRedundancy struct { | |||||
| } | } | ||||
| func NewSegmentRedundancy(totalSize int64, segmentCount int) *SegmentRedundancy { | func NewSegmentRedundancy(totalSize int64, segmentCount int) *SegmentRedundancy { | ||||
| var segs []int64 | |||||
| segLen := int64(0) | |||||
| // 计算每一段的大小。大小不一定都相同,但总和应该等于总大小。 | |||||
| for i := 0; i < segmentCount; i++ { | |||||
| curLen := totalSize*int64(i+1)/int64(segmentCount) - segLen | |||||
| segs = append(segs, curLen) | |||||
| segLen += curLen | |||||
| } | |||||
| return &SegmentRedundancy{ | return &SegmentRedundancy{ | ||||
| Type: "segment", | Type: "segment", | ||||
| Segments: segs, | |||||
| Segments: math2.SplitN(totalSize, segmentCount), | |||||
| } | } | ||||
| } | } | ||||
| @@ -45,3 +45,30 @@ func Clamp[T constraints.Integer](v, min, max T) T { | |||||
| return v | return v | ||||
| } | } | ||||
| // 将一个整数切分成小于maxValue的整数列表,尽量均匀 | |||||
| func SplitLessThan[T constraints.Integer](v T, maxValue T) []T { | |||||
| cnt := int(CeilDiv(v, maxValue)) | |||||
| result := make([]T, cnt) | |||||
| last := int64(0) | |||||
| for i := 0; i < cnt; i++ { | |||||
| cur := int64(v) * int64(i+1) / int64(cnt) | |||||
| result[i] = T(cur - last) | |||||
| last = cur | |||||
| } | |||||
| return result | |||||
| } | |||||
| // 将一个整数切分成n个整数,尽量均匀 | |||||
| func SplitN[T constraints.Integer](v T, n int) []T { | |||||
| result := make([]T, n) | |||||
| last := int64(0) | |||||
| for i := 0; i < n; i++ { | |||||
| cur := int64(v) * int64(i+1) / int64(n) | |||||
| result[i] = T(cur - last) | |||||
| last = cur | |||||
| } | |||||
| return result | |||||
| } | |||||
| @@ -0,0 +1,57 @@ | |||||
| package math2 | |||||
| import ( | |||||
| "testing" | |||||
| . "github.com/smartystreets/goconvey/convey" | |||||
| ) | |||||
| func Test_SplitLessThan(t *testing.T) { | |||||
| checker := func(t *testing.T, arr []int, total int, maxValue int) { | |||||
| t.Logf("arr: %v, total: %d, maxValue: %d", arr, total, maxValue) | |||||
| sum := 0 | |||||
| for _, v := range arr { | |||||
| sum += v | |||||
| if v > maxValue { | |||||
| t.Errorf("value should be less than %d", maxValue) | |||||
| } | |||||
| } | |||||
| if sum != total { | |||||
| t.Errorf("sum should be %d", total) | |||||
| } | |||||
| } | |||||
| Convey("测试", t, func() { | |||||
| checker(t, SplitLessThan(9, 9), 9, 9) | |||||
| checker(t, SplitLessThan(9, 3), 9, 3) | |||||
| checker(t, SplitLessThan(10, 3), 10, 3) | |||||
| checker(t, SplitLessThan(11, 3), 11, 3) | |||||
| checker(t, SplitLessThan(12, 3), 12, 3) | |||||
| }) | |||||
| } | |||||
| func Test_SplitN(t *testing.T) { | |||||
| checker := func(t *testing.T, arr []int, total int) { | |||||
| t.Logf("arr: %v, total: %d", arr, total) | |||||
| sum := 0 | |||||
| for _, v := range arr { | |||||
| sum += v | |||||
| } | |||||
| if sum != total { | |||||
| t.Errorf("sum should be %d", total) | |||||
| } | |||||
| } | |||||
| Convey("测试", t, func() { | |||||
| checker(t, SplitN(9, 9), 9) | |||||
| checker(t, SplitN(9, 3), 9) | |||||
| checker(t, SplitN(10, 3), 10) | |||||
| checker(t, SplitN(11, 3), 11) | |||||
| checker(t, SplitN(12, 3), 12) | |||||
| }) | |||||
| } | |||||