1package mathexp
2
3import (
4	"fmt"
5	"time"
6
7	"github.com/grafana/grafana-plugin-sdk-go/data"
8)
9
10// Resample turns the Series into a Number based on the given reduction function
11func (s Series) Resample(refID string, interval time.Duration, downsampler string, upsampler string, from, to time.Time) (Series, error) {
12	newSeriesLength := int(float64(to.Sub(from).Nanoseconds()) / float64(interval.Nanoseconds()))
13	if newSeriesLength <= 0 {
14		return s, fmt.Errorf("the series cannot be sampled further; the time range is shorter than the interval")
15	}
16	resampled := NewSeries(refID, s.GetLabels(), newSeriesLength+1)
17	bookmark := 0
18	var lastSeen *float64
19	idx := 0
20	t := from
21	for !t.After(to) && idx <= newSeriesLength {
22		vals := make([]*float64, 0)
23		sIdx := bookmark
24		for {
25			if sIdx == s.Len() {
26				break
27			}
28			st, v := s.GetPoint(sIdx)
29			if st.After(t) {
30				break
31			}
32			bookmark++
33			sIdx++
34			lastSeen = v
35			vals = append(vals, v)
36		}
37		var value *float64
38		if len(vals) == 0 { // upsampling
39			switch upsampler {
40			case "pad":
41				if lastSeen != nil {
42					value = lastSeen
43				} else {
44					value = nil
45				}
46			case "backfilling":
47				if sIdx == s.Len() { // no vals left
48					value = nil
49				} else {
50					_, value = s.GetPoint(sIdx)
51				}
52			case "fillna":
53				value = nil
54			default:
55				return s, fmt.Errorf("upsampling %v not implemented", upsampler)
56			}
57		} else { // downsampling
58			fVec := data.NewField("", s.GetLabels(), vals)
59			ff := Float64Field(*fVec)
60			var tmp *float64
61			switch downsampler {
62			case "sum":
63				tmp = Sum(&ff)
64			case "mean":
65				tmp = Avg(&ff)
66			case "min":
67				tmp = Min(&ff)
68			case "max":
69				tmp = Max(&ff)
70			default:
71				return s, fmt.Errorf("downsampling %v not implemented", downsampler)
72			}
73			value = tmp
74		}
75		if err := resampled.SetPoint(idx, t, value); err != nil {
76			return resampled, err
77		}
78		t = t.Add(interval)
79		idx++
80	}
81	return resampled, nil
82}
83