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.
		
		
		
		
		
			
		
			
				
					
					
						
							94 lines
						
					
					
						
							2.0 KiB
						
					
					
				
			
		
		
		
			
			
			
		
		
	
	
							94 lines
						
					
					
						
							2.0 KiB
						
					
					
				| package stats | |
| 
 | |
| import ( | |
| 	"time" | |
| ) | |
| 
 | |
| type TimedValue struct { | |
| 	t   time.Time | |
| 	val int64 | |
| } | |
| 
 | |
| func NewTimedValue(t time.Time, val int64) *TimedValue { | |
| 	return &TimedValue{t: t, val: val} | |
| } | |
| 
 | |
| type RoundRobinCounter struct { | |
| 	LastIndex int | |
| 	Values    []int64 | |
| 	Counts    []int64 | |
| } | |
| 
 | |
| func NewRoundRobinCounter(slots int) *RoundRobinCounter { | |
| 	return &RoundRobinCounter{LastIndex: -1, Values: make([]int64, slots), Counts: make([]int64, slots)} | |
| } | |
| func (rrc *RoundRobinCounter) Add(index int, val int64) { | |
| 	if index >= len(rrc.Values) { | |
| 		return | |
| 	} | |
| 	for rrc.LastIndex != index { | |
| 		rrc.LastIndex = (rrc.LastIndex + 1) % len(rrc.Values) | |
| 		rrc.Values[rrc.LastIndex] = 0 | |
| 		rrc.Counts[rrc.LastIndex] = 0 | |
| 	} | |
| 	rrc.Values[index] += val | |
| 	rrc.Counts[index]++ | |
| } | |
| func (rrc *RoundRobinCounter) Max() (max int64) { | |
| 	for _, val := range rrc.Values { | |
| 		if max < val { | |
| 			max = val | |
| 		} | |
| 	} | |
| 	return | |
| } | |
| func (rrc *RoundRobinCounter) Count() (cnt int64) { | |
| 	for _, c := range rrc.Counts { | |
| 		cnt += c | |
| 	} | |
| 	return | |
| } | |
| func (rrc *RoundRobinCounter) Sum() (sum int64) { | |
| 	for _, val := range rrc.Values { | |
| 		sum += val | |
| 	} | |
| 	return | |
| } | |
| 
 | |
| func (rrc *RoundRobinCounter) ToList() (ret []int64) { | |
| 	index := rrc.LastIndex | |
| 	step := len(rrc.Values) | |
| 	for step > 0 { | |
| 		step-- | |
| 		index++ | |
| 		if index >= len(rrc.Values) { | |
| 			index = 0 | |
| 		} | |
| 		ret = append(ret, rrc.Values[index]) | |
| 	} | |
| 	return | |
| } | |
| 
 | |
| type DurationCounter struct { | |
| 	MinuteCounter *RoundRobinCounter | |
| 	HourCounter   *RoundRobinCounter | |
| 	DayCounter    *RoundRobinCounter | |
| 	WeekCounter   *RoundRobinCounter | |
| } | |
| 
 | |
| func NewDurationCounter() *DurationCounter { | |
| 	return &DurationCounter{ | |
| 		MinuteCounter: NewRoundRobinCounter(60), | |
| 		HourCounter:   NewRoundRobinCounter(60), | |
| 		DayCounter:    NewRoundRobinCounter(24), | |
| 		WeekCounter:   NewRoundRobinCounter(7), | |
| 	} | |
| } | |
| 
 | |
| // Add is for cumulative counts | |
| func (sc *DurationCounter) Add(tv *TimedValue) { | |
| 	sc.MinuteCounter.Add(tv.t.Second(), tv.val) | |
| 	sc.HourCounter.Add(tv.t.Minute(), tv.val) | |
| 	sc.DayCounter.Add(tv.t.Hour(), tv.val) | |
| 	sc.WeekCounter.Add(int(tv.t.Weekday()), tv.val) | |
| }
 |