package config import ( _ "embed" "slices" "time" "code.humancabbage.net/sam/moonmath/coindesk" "code.humancabbage.net/sam/moonmath/moon" "github.com/knadh/koanf/parsers/yaml" "github.com/knadh/koanf/providers/file" "github.com/knadh/koanf/providers/rawbytes" "github.com/knadh/koanf/providers/structs" "github.com/knadh/koanf/v2" ) var k = koanf.New(".") func Load(filePath string) (r Root, err error) { err = k.Load(structs.Provider(Default, "koanf"), nil) if err != nil { return } if filePath != "" { err = k.Load(file.Provider(filePath), yaml.Parser()) if err != nil { return } } err = k.Unmarshal("", &r) return } var Default Root type Root struct { Defaults Asset `koanf:"defaults"` Assets map[coindesk.Asset]Asset `koanf:"assets"` } type Asset struct { Asset coindesk.Asset `koanf:"asset"` Goals []moon.Goal `koanf:"goals"` ConstantBases []moon.ConstantBase `koanf:"constantBases"` RelativeBases []moon.RelativeBase `koanf:"relativeBases"` } func (r Root) ForAsset(a coindesk.Asset) (cfg Asset) { cfg = merge(r.Assets[a], r.Defaults) cfg.Asset = a return } func merge(dst, src Asset) Asset { if len(dst.Goals) == 0 { dst.Goals = src.Goals } if len(dst.ConstantBases) == 0 { dst.ConstantBases = src.ConstantBases } if len(dst.RelativeBases) == 0 { dst.RelativeBases = src.RelativeBases } return dst } // GetBases returns the concatenation of the constant and relative bases, sorted // from most recent to least recent in time. func GetBases(d *Asset) (bases []moon.Base) { for _, b := range d.ConstantBases { bases = append(bases, b) } for _, b := range d.RelativeBases { bases = append(bases, b) } now := time.Now() slices.SortFunc(bases, func(a, b moon.Base) int { aTime := a.From(now) bTime := b.From(now) aFirst := aTime.Before(bTime) bFirst := bTime.Before(aTime) switch { case aFirst: return 1 case bFirst: return -1 } return 0 }) return } //go:embed default.yaml var defaultYamlBytes []byte func init() { var k = koanf.New(".") err := k.Load(rawbytes.Provider(defaultYamlBytes), yaml.Parser()) if err != nil { panic(err) } err = k.Unmarshal("", &Default) if err != nil { panic(err) } }