Add report registry and valid periods
This commit is contained in:
@@ -9,6 +9,8 @@ import (
|
||||
"gitea.maximumdirect.net/eric/weatherreporter/internal/adapters/weatherapi"
|
||||
"gitea.maximumdirect.net/eric/weatherreporter/internal/config"
|
||||
"gitea.maximumdirect.net/eric/weatherreporter/internal/forecast"
|
||||
"gitea.maximumdirect.net/eric/weatherreporter/internal/report"
|
||||
"gitea.maximumdirect.net/eric/weatherreporter/internal/timeutil"
|
||||
)
|
||||
|
||||
type ReportKind string
|
||||
@@ -49,16 +51,81 @@ type FetchBundleRequest struct {
|
||||
|
||||
func Generate(ctx context.Context, req GenerateRequest) error {
|
||||
_ = ctx
|
||||
_ = req
|
||||
if _, err := ResolveGenerate(req, time.Now()); err != nil {
|
||||
return err
|
||||
}
|
||||
return fmt.Errorf("generate is not implemented")
|
||||
}
|
||||
|
||||
func RunBatch(ctx context.Context, req BatchRequest) error {
|
||||
_ = ctx
|
||||
_ = req
|
||||
if _, err := ResolveBatch(req, time.Now()); err != nil {
|
||||
return err
|
||||
}
|
||||
return fmt.Errorf("run is not implemented")
|
||||
}
|
||||
|
||||
func ResolveGenerate(req GenerateRequest, now time.Time) (report.Resolved, error) {
|
||||
location, err := timeutil.LoadLocation(req.Config.WeatherAPI.Timezone)
|
||||
if err != nil {
|
||||
return report.Resolved{}, err
|
||||
}
|
||||
id, err := reportIDForCommand(req.Report)
|
||||
if err != nil {
|
||||
return report.Resolved{}, err
|
||||
}
|
||||
return report.DefaultRegistry().Resolve(id, report.ResolveRequest{
|
||||
Now: now,
|
||||
Location: location,
|
||||
Date: req.Date,
|
||||
StormStart: req.StormStart,
|
||||
StormEnd: req.StormEnd,
|
||||
})
|
||||
}
|
||||
|
||||
func ResolveBatch(req BatchRequest, now time.Time) ([]report.Resolved, error) {
|
||||
location, err := timeutil.LoadLocation(req.Config.WeatherAPI.Timezone)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
batch, err := reportBatchForCommand(req.Batch)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return report.DefaultRegistry().BatchReports(batch, report.ResolveRequest{
|
||||
Now: now,
|
||||
Location: location,
|
||||
})
|
||||
}
|
||||
|
||||
func reportIDForCommand(kind ReportKind) (report.ID, error) {
|
||||
switch kind {
|
||||
case ReportDaily:
|
||||
return report.DailyToday, nil
|
||||
case ReportTomorrow:
|
||||
return report.DailyTomorrow, nil
|
||||
case ReportThreeDay:
|
||||
return report.ThreeDay, nil
|
||||
case ReportWeekend:
|
||||
return report.Weekend, nil
|
||||
case ReportStorm:
|
||||
return report.Storm, nil
|
||||
default:
|
||||
return "", fmt.Errorf("unknown report command %q", kind)
|
||||
}
|
||||
}
|
||||
|
||||
func reportBatchForCommand(kind BatchKind) (report.Batch, error) {
|
||||
switch kind {
|
||||
case BatchMorning:
|
||||
return report.Morning, nil
|
||||
case BatchEvening:
|
||||
return report.Evening, nil
|
||||
default:
|
||||
return "", fmt.Errorf("unknown batch command %q", kind)
|
||||
}
|
||||
}
|
||||
|
||||
func FetchBundle(ctx context.Context, req FetchBundleRequest) (*forecast.Bundle, error) {
|
||||
client, err := weatherapi.New(req.Config)
|
||||
if err != nil {
|
||||
|
||||
@@ -8,8 +8,10 @@ import (
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"gitea.maximumdirect.net/eric/weatherreporter/internal/config"
|
||||
"gitea.maximumdirect.net/eric/weatherreporter/internal/report"
|
||||
)
|
||||
|
||||
func TestFetchAndSaveBundle(t *testing.T) {
|
||||
@@ -62,3 +64,77 @@ func TestFetchAndSaveBundleRequiresOutputPath(t *testing.T) {
|
||||
t.Fatalf("error = %q, want output path context", err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func TestResolveGenerateMapsCommandToReportDefinition(t *testing.T) {
|
||||
cfg := config.Defaults()
|
||||
cfg.WeatherAPI.Timezone = "America/Chicago"
|
||||
now := mustParse("2026-05-29T18:00:00-05:00")
|
||||
|
||||
resolved, err := ResolveGenerate(GenerateRequest{
|
||||
Config: cfg,
|
||||
Report: ReportTomorrow,
|
||||
}, now)
|
||||
if err != nil {
|
||||
t.Fatalf("ResolveGenerate() error = %v", err)
|
||||
}
|
||||
if resolved.Definition.ID != report.DailyTomorrow {
|
||||
t.Fatalf("ID = %q, want daily_tomorrow", resolved.Definition.ID)
|
||||
}
|
||||
if resolved.Definition.PromptID != "weather.daily_report" {
|
||||
t.Fatalf("PromptID = %q, want weather.daily_report", resolved.Definition.PromptID)
|
||||
}
|
||||
if got := resolved.ValidPeriod.Start.Format("2006-01-02"); got != "2026-05-30" {
|
||||
t.Fatalf("valid start date = %s, want 2026-05-30", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestResolveGenerateStorm(t *testing.T) {
|
||||
cfg := config.Defaults()
|
||||
cfg.WeatherAPI.Timezone = "America/Chicago"
|
||||
now := mustParse("2026-05-29T12:00:00-05:00")
|
||||
start := mustParse("2026-05-29T18:00:00-05:00")
|
||||
end := mustParse("2026-05-30T06:00:00-05:00")
|
||||
|
||||
resolved, err := ResolveGenerate(GenerateRequest{
|
||||
Config: cfg,
|
||||
Report: ReportStorm,
|
||||
StormStart: start,
|
||||
StormEnd: end,
|
||||
}, now)
|
||||
if err != nil {
|
||||
t.Fatalf("ResolveGenerate() error = %v", err)
|
||||
}
|
||||
if resolved.Definition.ID != report.Storm {
|
||||
t.Fatalf("ID = %q, want storm", resolved.Definition.ID)
|
||||
}
|
||||
if !resolved.ValidPeriod.Start.Equal(start) || !resolved.ValidPeriod.End.Equal(end) {
|
||||
t.Fatalf("period = %#v, want storm window", resolved.ValidPeriod)
|
||||
}
|
||||
}
|
||||
|
||||
func TestResolveBatchMorningSkipsWeekendOnSunday(t *testing.T) {
|
||||
cfg := config.Defaults()
|
||||
cfg.WeatherAPI.Timezone = "America/Chicago"
|
||||
now := mustParse("2026-05-31T06:00:00-05:00")
|
||||
|
||||
resolved, err := ResolveBatch(BatchRequest{Config: cfg, Batch: BatchMorning}, now)
|
||||
if err != nil {
|
||||
t.Fatalf("ResolveBatch() error = %v", err)
|
||||
}
|
||||
if len(resolved) != 2 {
|
||||
t.Fatalf("resolved length = %d, want 2", len(resolved))
|
||||
}
|
||||
for _, item := range resolved {
|
||||
if item.Definition.ID == report.Weekend {
|
||||
t.Fatal("morning batch included weekend on Sunday")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func mustParse(value string) time.Time {
|
||||
parsed, err := time.Parse(time.RFC3339, value)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return parsed
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user