package api import ( "context" "fmt" "net/http" "predictor-refactored/internal/windviz" apirest "predictor-refactored/pkg/rest" ) // GetWindMeta implements GET /api/v1/wind/meta. func (h *Handler) GetWindMeta(_ context.Context) (*apirest.WindMeta, error) { field := h.mgr.Active() if field == nil { return nil, apiError(http.StatusServiceUnavailable, "no dataset loaded") } return &apirest.WindMeta{ Source: field.Source(), Epoch: field.Epoch().UTC(), DefaultStep: 1.0, MinStep: 0.25, SuggestedAltitudes: []int{0, 1000, 5000, 10000, 15000, 20000, 30000}, Bbox: apirest.Region{MinLat: -90, MaxLat: 90, MinLng: 0, MaxLng: 360}, }, nil } // GetWindField implements GET /api/v1/wind/field. func (h *Handler) GetWindField(_ context.Context, params apirest.GetWindFieldParams) ([]apirest.WindComponent, error) { field := h.mgr.Active() if field == nil { return nil, apiError(http.StatusServiceUnavailable, "no dataset loaded") } when := field.Epoch() if t, ok := params.Time.Get(); ok { when = t } req := windviz.Request{ Time: float64(when.Unix()), Altitude: params.Altitude.Or(0), MinLat: params.MinLat.Or(0), MaxLat: params.MaxLat.Or(0), MinLng: params.MinLng.Or(0), MaxLng: params.MaxLng.Or(0), Step: params.Step.Or(0), } key := fmt.Sprintf("%s|%v|%.3f|%.3f|%.3f|%.3f|%.3f|%.3f", field.Source(), req.Time, req.Altitude, req.MinLat, req.MaxLat, req.MinLng, req.MaxLng, req.Step) if h.cache != nil { if cached, ok := h.cache.Get(key); ok { return windFieldToAPI(cached), nil } } out, err := windviz.Rasterize(field, req) if err != nil { return nil, apiError(http.StatusBadRequest, err.Error()) } if h.cache != nil { h.cache.Put(key, out) } return windFieldToAPI(out), nil } // windFieldToAPI maps a rasterized field to the generated component slice. func windFieldToAPI(f windviz.Field) []apirest.WindComponent { out := make([]apirest.WindComponent, 0, len(f)) for _, c := range f { out = append(out, apirest.WindComponent{ Header: apirest.WindHeader{ ParameterCategory: c.Header.ParameterCategory, ParameterNumber: c.Header.ParameterNumber, ParameterNumberName: apirest.NewOptString(c.Header.ParameterNumberName), ParameterUnit: apirest.NewOptString(c.Header.ParameterUnit), Nx: c.Header.Nx, Ny: c.Header.Ny, Lo1: c.Header.Lo1, La1: c.Header.La1, Lo2: c.Header.Lo2, La2: c.Header.La2, Dx: c.Header.Dx, Dy: c.Header.Dy, RefTime: c.Header.RefTime, ForecastTime: c.Header.ForecastTime, }, Data: c.Data, }) } return out }