package forecasts 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.ForecastRepository registry *units.Registry limit int } func NewService(repo ports.ForecastRepository, registry *units.Registry, limit int) *Service { return &Service{repo: repo, registry: registry, 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"` TemperatureC *float64 `json:"temperatureC,omitempty"` TemperatureF *float64 `json:"temperatureF,omitempty"` TemperatureCMin *float64 `json:"temperatureCMin,omitempty"` TemperatureFMin *float64 `json:"temperatureFMin,omitempty"` TemperatureCMax *float64 `json:"temperatureCMax,omitempty"` TemperatureFMax *float64 `json:"temperatureFMax,omitempty"` DewpointC *float64 `json:"dewpointC,omitempty"` DewpointF *float64 `json:"dewpointF,omitempty"` RelativeHumidityPercent *float64 `json:"relativeHumidityPercent,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"` ApparentTemperatureC *float64 `json:"apparentTemperatureC,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, unitSystem string) (Response, error) { if s == nil { return Response{}, fmt.Errorf("forecasts service is nil") } converter, err := s.registry.Resolve(unitSystem) if err != nil { return Response{}, err } 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 { item := 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, RelativeHumidityPercent: p.RelativeHumidityPercent, WindDirectionDegrees: p.WindDirectionDegrees, BarometricPressurePa: p.BarometricPressurePa, VisibilityMeters: p.VisibilityMeters, CloudCoverPercent: p.CloudCoverPercent, ProbabilityOfPrecipitationPercent: p.ProbabilityOfPrecipitationPercent, PrecipitationAmountMm: p.PrecipitationAmountMm, SnowfallDepthMm: p.SnowfallDepthMm, UVIndex: p.UVIndex, } switch converter.System() { case constants.UnitSystemUS: item.TemperatureF = converter.TemperatureCToOutput(p.TemperatureC) item.TemperatureFMin = converter.TemperatureCToOutput(p.TemperatureCMin) item.TemperatureFMax = converter.TemperatureCToOutput(p.TemperatureCMax) item.DewpointF = converter.TemperatureCToOutput(p.DewpointC) item.WindSpeedMph = converter.SpeedKmhToOutput(p.WindSpeedKmh) item.WindGustMph = converter.SpeedKmhToOutput(p.WindGustKmh) item.ApparentTemperatureF = converter.TemperatureCToOutput(p.ApparentTemperatureC) default: item.TemperatureC = converter.TemperatureCToOutput(p.TemperatureC) item.TemperatureCMin = converter.TemperatureCToOutput(p.TemperatureCMin) item.TemperatureCMax = converter.TemperatureCToOutput(p.TemperatureCMax) item.DewpointC = converter.TemperatureCToOutput(p.DewpointC) item.WindSpeedKmh = converter.SpeedKmhToOutput(p.WindSpeedKmh) item.WindGustKmh = converter.SpeedKmhToOutput(p.WindGustKmh) item.ApparentTemperatureC = converter.TemperatureCToOutput(p.ApparentTemperatureC) } periods = append(periods, item) } return Response{ Timestamp: ts, Periods: periods, }, nil }