predictor/internal/api/wind.go

92 lines
2.7 KiB
Go

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
}