package forecasts import ( "context" "fmt" "time" "gitea.maximumdirect.net/ejr/weatherapi/internal/application/units" "gitea.maximumdirect.net/ejr/weatherapi/internal/core/ports" ) type Service struct { repo ports.ForecastRepository converter units.Converter limit int } func NewService(repo ports.ForecastRepository, converter units.Converter, limit int) *Service { return &Service{repo: repo, converter: converter, limit: limit} } type Response struct { Timestamp time.Time `json:"timestamp"` Periods []PeriodResponse `json:"periods"` } type PeriodResponse struct { PeriodIndex int `json:"periodIndex"` StartTime time.Time `json:"startTime"` EndTime time.Time `json:"endTime"` Name *string `json:"name,omitempty"` IsDay *bool `json:"isDay,omitempty"` ConditionCode int `json:"conditionCode"` ConditionText *string `json:"conditionText,omitempty"` ProviderRawDescription *string `json:"providerRawDescription,omitempty"` TextDescription *string `json:"textDescription,omitempty"` DetailedText *string `json:"detailedText,omitempty"` IconURL *string `json:"iconUrl,omitempty"` TemperatureF *float64 `json:"temperatureF,omitempty"` TemperatureFMin *float64 `json:"temperatureFMin,omitempty"` TemperatureFMax *float64 `json:"temperatureFMax,omitempty"` DewpointF *float64 `json:"dewpointF,omitempty"` RelativeHumidityPercent *float64 `json:"relativeHumidityPercent,omitempty"` WindDirectionDegrees *float64 `json:"windDirectionDegrees,omitempty"` WindSpeedMph *float64 `json:"windSpeedMph,omitempty"` WindGustMph *float64 `json:"windGustMph,omitempty"` BarometricPressurePa *float64 `json:"barometricPressurePa,omitempty"` VisibilityMeters *float64 `json:"visibilityMeters,omitempty"` ApparentTemperatureF *float64 `json:"apparentTemperatureF,omitempty"` CloudCoverPercent *float64 `json:"cloudCoverPercent,omitempty"` ProbabilityOfPrecipitationPercent *float64 `json:"probabilityOfPrecipitationPercent,omitempty"` PrecipitationAmountMm *float64 `json:"precipitationAmountMm,omitempty"` SnowfallDepthMm *float64 `json:"snowfallDepthMm,omitempty"` UVIndex *float64 `json:"uvIndex,omitempty"` } func (s *Service) GetByTimestamp(ctx context.Context, ts time.Time) (Response, error) { if s == nil { return Response{}, fmt.Errorf("forecasts service is nil") } periodsMetric, err := s.repo.ListForecastPeriodsAt(ctx, ts, s.limit) if err != nil { return Response{}, err } periods := make([]PeriodResponse, 0, len(periodsMetric)) for _, p := range periodsMetric { periods = append(periods, PeriodResponse{ PeriodIndex: p.PeriodIndex, StartTime: p.StartTime, EndTime: p.EndTime, Name: p.Name, IsDay: p.IsDay, ConditionCode: p.ConditionCode, ConditionText: p.ConditionText, ProviderRawDescription: p.ProviderRawDescription, TextDescription: p.TextDescription, DetailedText: p.DetailedText, IconURL: p.IconURL, TemperatureF: s.converter.TemperatureCToOutput(p.TemperatureC), TemperatureFMin: s.converter.TemperatureCToOutput(p.TemperatureCMin), TemperatureFMax: s.converter.TemperatureCToOutput(p.TemperatureCMax), DewpointF: s.converter.TemperatureCToOutput(p.DewpointC), RelativeHumidityPercent: p.RelativeHumidityPercent, WindDirectionDegrees: p.WindDirectionDegrees, WindSpeedMph: s.converter.SpeedKmhToOutput(p.WindSpeedKmh), WindGustMph: s.converter.SpeedKmhToOutput(p.WindGustKmh), BarometricPressurePa: p.BarometricPressurePa, VisibilityMeters: p.VisibilityMeters, ApparentTemperatureF: s.converter.TemperatureCToOutput(p.ApparentTemperatureC), CloudCoverPercent: p.CloudCoverPercent, ProbabilityOfPrecipitationPercent: p.ProbabilityOfPrecipitationPercent, PrecipitationAmountMm: p.PrecipitationAmountMm, SnowfallDepthMm: p.SnowfallDepthMm, UVIndex: p.UVIndex, }) } return Response{ Timestamp: ts, Periods: periods, }, nil }