Files
weatherapi/internal/application/forecasts/service.go
Eric Rakestraw 27817f9e43
All checks were successful
ci/woodpecker/push/build-image Pipeline was successful
Initial MVP commit
2026-03-17 08:35:16 -05:00

105 lines
4.6 KiB
Go

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"`
IsDay *bool `json:"isDay"`
ConditionCode int `json:"conditionCode"`
ConditionText *string `json:"conditionText"`
ProviderRawDescription *string `json:"providerRawDescription"`
TextDescription *string `json:"textDescription"`
DetailedText *string `json:"detailedText"`
IconURL *string `json:"iconUrl"`
TemperatureF *float64 `json:"temperatureF"`
TemperatureFMin *float64 `json:"temperatureFMin"`
TemperatureFMax *float64 `json:"temperatureFMax"`
DewpointF *float64 `json:"dewpointF"`
RelativeHumidityPercent *float64 `json:"relativeHumidityPercent"`
WindDirectionDegrees *float64 `json:"windDirectionDegrees"`
WindSpeedMph *float64 `json:"windSpeedMph"`
WindGustMph *float64 `json:"windGustMph"`
BarometricPressurePa *float64 `json:"barometricPressurePa"`
VisibilityMeters *float64 `json:"visibilityMeters"`
ApparentTemperatureF *float64 `json:"apparentTemperatureF"`
CloudCoverPercent *float64 `json:"cloudCoverPercent"`
ProbabilityOfPrecipitationPercent *float64 `json:"probabilityOfPrecipitationPercent"`
PrecipitationAmountMm *float64 `json:"precipitationAmountMm"`
SnowfallDepthMm *float64 `json:"snowfallDepthMm"`
UVIndex *float64 `json:"uvIndex"`
}
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
}