evcc-io/tariff/proxy_average.go

66 lines
1.2 KiB
Go

package tariff
import (
"slices"
"time"
"github.com/evcc-io/evcc/api"
)
// average wraps a tariff with averaging
type average struct {
average time.Duration
api.Tariff
}
// NewAverageProxy creates a proxy that tariff averaging
func NewAverageProxy(t api.Tariff) (api.Tariff, error) {
return &average{
average: time.Hour,
Tariff: t,
}, nil
}
func (t *average) Rates() (api.Rates, error) {
rates, err := t.Tariff.Rates()
if len(rates) == 0 || err != nil {
return rates, err
}
return averageSlots(rates, t.average), nil
}
// averageSlots averages 15-minute slots by period
func averageSlots(rates api.Rates, average time.Duration) api.Rates {
if len(rates) == 0 {
return nil
}
// accumulate sums and counts per period
avgs := make(map[time.Time]*struct {
sum float64
cnt int
})
for _, r := range rates {
ts := r.Start.Truncate(average)
avg, ok := avgs[ts]
if !ok {
avg = new(struct {
sum float64
cnt int
})
avgs[ts] = avg
}
avg.sum += r.Value
avg.cnt++
}
res := slices.Clone(rates)
for i, r := range res {
avg := avgs[r.Start.Truncate(average)]
res[i].Value = avg.sum / float64(avg.cnt)
}
return res
}