evcc-io/tariff/fixed/zone.go

82 lines
1.6 KiB
Go

package fixed
import (
"slices"
)
type Zone struct {
Price float64
Days []Day
Hours TimeRange
Months []Month
}
type Zones []Zone
// implement sort.Interface
func (r Zones) Len() int {
return len(r)
}
func (r Zones) Less(i, j int) bool {
if r[i].Hours.From.Minutes() == r[j].Hours.From.Minutes() {
return r[i].Hours.To.Minutes() > r[j].Hours.To.Minutes()
}
return r[i].Hours.From.Minutes() < r[j].Hours.From.Minutes()
}
func (r Zones) Swap(i, j int) {
r[i], r[j] = r[j], r[i]
}
// ForDay returns the zones for given day in ascending order
func (r Zones) ForDayAndMonth(day Day, month Month) Zones {
var zones Zones
for _, z := range r {
if (slices.Contains(z.Days, day) || len(z.Days) == 0) && (slices.Contains(z.Months, month) || len(z.Months) == 0) {
zones = append(zones, z)
}
}
return zones
}
// TimeTableMarkers returns list of zone start/end markers
func (r Zones) TimeTableMarkers() []HourMin {
res := []HourMin{{Hour: 0, Min: 0}}
for _, z := range r {
if !z.Hours.From.IsNil() {
if !slices.Contains(res, z.Hours.From) {
res = append(res, z.Hours.From)
}
}
if !z.Hours.To.IsNil() {
if !slices.Contains(res, z.Hours.To) {
res = append(res, z.Hours.To)
}
}
}
HOURS:
// 1hr intervals
for hour := 0; hour < 24; hour++ {
for _, m := range res {
if m.Hour == hour && m.Min == 0 {
continue HOURS
}
}
// hour is missing
for i, m := range res {
if m.Hour >= hour {
res = slices.Insert(res, i, HourMin{Hour: hour, Min: 0})
continue HOURS
}
}
res = append(res, HourMin{Hour: hour, Min: 0})
}
return res
}