package observations import ( "context" "fmt" "time" "gitea.maximumdirect.net/ejr/weatherapi/internal/application/units" "gitea.maximumdirect.net/ejr/weatherapi/internal/core/ports" "gitea.maximumdirect.net/ejr/weatherapi/internal/platform/constants" ) type Service struct { repo ports.ObservationRepository registry *units.Registry } func NewService(repo ports.ObservationRepository, registry *units.Registry) *Service { return &Service{repo: repo, registry: registry} } type Response struct { Observations []ObservationResponse `json:"observations"` } type ObservationResponse struct { StationID *string `json:"stationId,omitempty"` StationName *string `json:"stationName,omitempty"` Timestamp time.Time `json:"timestamp"` ConditionCode int `json:"conditionCode"` IsDay *bool `json:"isDay,omitempty"` TextDescription *string `json:"textDescription,omitempty"` TemperatureC *float64 `json:"temperatureC,omitempty"` TemperatureF *float64 `json:"temperatureF,omitempty"` DewpointC *float64 `json:"dewpointC,omitempty"` DewpointF *float64 `json:"dewpointF,omitempty"` WindDirectionDegrees *float64 `json:"windDirectionDegrees,omitempty"` WindSpeedKmh *float64 `json:"windSpeedKmh,omitempty"` WindSpeedMph *float64 `json:"windSpeedMph,omitempty"` WindGustKmh *float64 `json:"windGustKmh,omitempty"` WindGustMph *float64 `json:"windGustMph,omitempty"` BarometricPressurePa *float64 `json:"barometricPressurePa,omitempty"` VisibilityMeters *float64 `json:"visibilityMeters,omitempty"` RelativeHumidityPercent *float64 `json:"relativeHumidityPercent,omitempty"` ApparentTemperatureC *float64 `json:"apparentTemperatureC,omitempty"` ApparentTemperatureF *float64 `json:"apparentTemperatureF,omitempty"` PresentWeather []PresentWeatherResponse `json:"presentWeather,omitempty"` } type PresentWeatherResponse struct { Raw map[string]any `json:"raw,omitempty"` } func (s *Service) GetRecent(ctx context.Context, count int, unitSystem string) (Response, error) { if s == nil { return Response{}, fmt.Errorf("observations service is nil") } converter, err := s.registry.Resolve(unitSystem) if err != nil { return Response{}, err } records, err := s.repo.ListRecentObservations(ctx, count) if err != nil { return Response{}, err } out := make([]ObservationResponse, 0, len(records)) for _, r := range records { item := ObservationResponse{ StationID: r.StationID, StationName: r.StationName, Timestamp: r.Timestamp, ConditionCode: r.ConditionCode, IsDay: r.IsDay, TextDescription: r.TextDescription, WindDirectionDegrees: r.WindDirectionDegrees, BarometricPressurePa: r.BarometricPressurePa, VisibilityMeters: r.VisibilityMeters, RelativeHumidityPercent: r.RelativeHumidityPercent, } presentWeather := make([]PresentWeatherResponse, 0, len(r.PresentWeather)) for _, pw := range r.PresentWeather { presentWeather = append(presentWeather, PresentWeatherResponse{Raw: pw.Raw}) } item.PresentWeather = presentWeather switch converter.System() { case constants.UnitSystemUS: item.TemperatureF = converter.TemperatureCToOutput(r.TemperatureC) item.DewpointF = converter.TemperatureCToOutput(r.DewpointC) item.WindSpeedMph = converter.SpeedKmhToOutput(r.WindSpeedKmh) item.WindGustMph = converter.SpeedKmhToOutput(r.WindGustKmh) item.ApparentTemperatureF = converter.TemperatureCToOutput(r.ApparentTemperatureC) default: item.TemperatureC = converter.TemperatureCToOutput(r.TemperatureC) item.DewpointC = converter.TemperatureCToOutput(r.DewpointC) item.WindSpeedKmh = converter.SpeedKmhToOutput(r.WindSpeedKmh) item.WindGustKmh = converter.SpeedKmhToOutput(r.WindGustKmh) item.ApparentTemperatureC = converter.TemperatureCToOutput(r.ApparentTemperatureC) } out = append(out, item) } return Response{Observations: out}, nil }