package energy import ( "context" "fmt" "log" "math" "strings" "time" "github.com/amigan/energyd/pkg/isoclient" "github.com/lucasb-eyer/go-colorful" "github.com/mazznoer/colorgrad" ) type Energy struct { iso isoclient.Client } type LoadProfile struct { Time time.Time Current int Peak int Lowest int PeakHr int LowestHr int PctPeak int HoursAway int HighFuel string MarginalFuels MarginalFuels } type MarginalFuels []string func (mf MarginalFuels) String() string { return strings.Join(mf, ", ") } func (e *Energy) Compute() error { ic := e.iso load, err := ic.GetCurrentLoad() if err != nil { return err } gphd, err := ic.GetHourlyLoadForecast() if err != nil { return err } fm, err := ic.GetGenFuelMixes() if err != nil { return err } lp := LoadProfile{ Time: load.BeginDate, Current: int(load.LoadMW), LowestHr: -1, } if len(fm) > 0 { highGen := int(fm[0].GenMW) highFuel := fm[0] for _, mix := range fm { if int(mix.GenMW) > highGen { highGen = int(mix.GenMW) highFuel = mix } if mix.Marginal { lp.MarginalFuels = append(lp.MarginalFuels, mix.FuelCategory) } } lp.HighFuel = highFuel.FuelCategory } for h, hf := range gphd.HourlyLoadForecast { if int(hf.LoadMW) > lp.Peak { lp.Peak = int(hf.LoadMW) lp.PeakHr = h } if int(hf.LoadMW) < lp.Lowest || lp.LowestHr == -1 { lp.LowestHr = h lp.Lowest = int(hf.LoadMW) } } hour := time.Now().Hour() lp.PctPeak = int(float32(load.LoadMW/float32(lp.Peak)) * 100) lp.HoursAway = int(math.Abs(float64(hour) - float64(lp.PeakHr))) fmt.Println(lp.String()) return nil } type Colors struct { Mix [2]colorful.Color Peak [2]colorful.Color } func vaporwavePalette() []string { return []string{ "#01cdfe", // blue "#05ffa1", // green "#fffb96", // gold "#ff71ce", // pinkred "#b967ff", // purple } } func outrunPalette() []string { return []string{ "#2de2e6", // blue "#00ff1b", // green "#ff6c11", // gold "#ff3864", // pinkred "#7930ff", // purple } } func (lp *LoadProfile) PeakScaleColors() []string { var scale []string palette := outrunPalette() nowHr := time.Now().Hour() // XXX: get this from lp //if lp.HoursAway > _, _ = palette, nowHr return scale } func (lp *LoadProfile) String() string { return fmt.Sprintf("%s\tC: %d\tP: %d\tL: %d\tPeakHr: %d\tLowestHr: %d\t%%Pk: %d\tHrAway: %d\tPkFuel: %s\tMarginal: %s", lp.Time.String(), lp.Current, lp.Peak, lp.Lowest, lp.PeakHr, lp.LowestHr, lp.PctPeak, lp.HoursAway, lp.HighFuel, lp.MarginalFuels) } func (lp *LoadProfile) Colors() Colors { c := Colors{} peak, err := colorgrad.NewGradient().Domain(float64(lp.Lowest), float64(lp.Peak)).HtmlColors(lp.PeakScaleColors()...).Build() if err != nil { panic(err) } c.Peak[0] = peak.At(float64(time.Now().Hour())) return c } func (e *Energy) Go(ctx context.Context) { tick := time.NewTicker(time.Minute * 15) err := e.Compute() if err != nil { log.Println(err) } for { select { case <-tick.C: err := e.Compute() if err != nil { log.Println(err) } case <-ctx.Done(): return } } } func New(ic isoclient.Client) *Energy { return &Energy{ iso: ic, } }