package types import ( "fmt" "maps" "sig-pub/pkg/utils/codec" "time" "github.com/spf13/cast" ) const ( inputCacheKey = "__$cache__" ) // TODO 将indicator meta的定义的输入参数传入, 限制只能获取这些输入参数 type Input map[string]any // getCache 避免多线程读写cache map func (in Input) getCache(k string) (r any, ok bool) { if in == nil { return } c, ok := in[inputCacheKey] if !ok { return } r, ok = c.(map[string]any)[k] return } func (in Input) setCache(k string, v any) { if in == nil { return } c, ok := in[inputCacheKey] if !ok { c = make(map[string]any, 4) in[inputCacheKey] = c } c.(map[string]any)[k] = v } func (in Input) get(k string, t string) (r any) { if in == nil { panic(fmt.Errorf("input %s type %s not provide", k, t)) } r, ok := in[k] if !ok { panic(fmt.Errorf("input %s type %s not provide", k, t)) } return } func (in Input) Float(k string) (v float64) { if r, ok := in.getCache(k); ok { if v, ok = r.(float64); ok { return } } v, err := cast.ToFloat64E(in.get(k, "float")) if err != nil { panic(fmt.Errorf("input float parse error: %s", k)) } in.setCache(k, v) return } func (in Input) Int(k string) (v int) { if r, ok := in.getCache(k); ok { if v, ok = r.(int); ok { return } } v, err := cast.ToIntE(in.get(k, "int")) if err != nil { panic(fmt.Errorf("input int parse error: %s", k)) } in.setCache(k, v) return } func (in Input) Int16(k string) (v int16) { if r, ok := in.getCache(k); ok { if v, ok = r.(int16); ok { return } } v, err := cast.ToInt16E(in.get(k, "int16")) if err != nil { panic(fmt.Errorf("input int16 parse error: %s", k)) } in.setCache(k, v) return } func (in Input) String(k string) (v string) { if k == "pt" && in != nil { if _, ok := in[k]; !ok { in[k] = KPriceTypeDefault } } v, err := cast.ToStringE(in.get(k, "string")) if err != nil { panic(fmt.Errorf("input string parse error: %s", k)) } return } func (in Input) Time(k string) (v time.Time) { v, err := cast.ToTimeInDefaultLocationE(in.get(k, "time"), time.Local) if err != nil { panic(fmt.Errorf("input time parse error: %s", k)) } return } func (in Input) PriceType(k ...string) (v KPriceType) { key := "pt" if len(k) > 0 { key = k[0] } v = KPriceType(in.String(key)) return } func (in Input) Decode(k string, point any) { t := fmt.Sprintf("%T", point) v := in.get(k, t) if err := codec.MapDecode(v, point); err != nil { panic(fmt.Errorf("input %s decode error: %s, %v", t, k, err)) } } func (in Input) DecodeInput(point any) { if err := codec.MapDecode(in, point); err != nil { panic(fmt.Errorf("input decode to %T error: %v", point, err)) } } // Assign 将other中的值赋给当前Input func (in Input) Assign(others ...Input) Input { for _, other := range others { maps.Copy(in, other) } return in } // 参数类型 type InputType int8 const ( _ InputType = iota InputTypeBool InputTypeString InputTypeFloat InputTypeUFloat InputTypeInt InputTypeUInt InputTypeTime InputTypeKPriceType InputTypeUFloats // float数组 InputTypeUFloats2D // float二维数组 InputTypeSelect // 单选 InputTypeCheckBox // 多选 ) type InputArg struct { Name string `json:"name"` Desc string `json:"desc"` Type InputType `json:"type"` // 参数类型 Options []InputOption `json:"options"` // 单选/多选选项列表 Default any `json:"default"` // 默认值 TODO 构造context前将默认值置入input } type InputOption struct { Name string `json:"name"` Desc string `json:"desc"` }