Files
weatherreporter/internal/report/definition.go

122 lines
3.1 KiB
Go

// Package report defines report identities, registry metadata, and valid periods.
package report
import (
"fmt"
"strings"
"time"
"gitea.maximumdirect.net/eric/weatherreporter/internal/module"
"gitea.maximumdirect.net/eric/weatherreporter/internal/timeutil"
)
type ID string
const (
Daily ID = "daily"
Today ID = "today"
Tomorrow ID = "tomorrow"
Hourly ID = "hourly"
)
type Batch string
const (
Morning Batch = "morning"
Evening Batch = "evening"
)
type Definition struct {
ID ID
Name string
PromptID string
PromptVersion string
TemplateID string
GeneratedTextSchemaID string
ArtifactGroup string
OutputName string
DistributorPathTemplates []string
Modules []module.ConfigItem
Morning bool
Evening bool
resolve func(ResolveRequest) (timeutil.Period, error)
runIDDisambiguator func(Resolved) string
}
func (r Resolved) OutputName() (string, error) {
if r.Definition.ID == Daily {
if r.ValidPeriod.Start.IsZero() {
return "", fmt.Errorf("daily report has no valid-period start for output naming")
}
location, err := timeutil.LoadLocation(r.Timezone)
if err != nil {
return "", fmt.Errorf("load report timezone for output naming: %w", err)
}
return "daily-" + r.ValidPeriod.Start.In(location).Format(timeutil.DateLayout) + ".md", nil
}
if r.Definition.OutputName == "" {
return "", fmt.Errorf("report %q has no output name", r.Definition.ID)
}
return r.Definition.OutputName, nil
}
func (d Definition) ResolvePeriod(req ResolveRequest) (timeutil.Period, error) {
if d.resolve == nil {
return timeutil.Period{}, fmt.Errorf("report %q has no valid-period resolver", d.ID)
}
return d.resolve(req)
}
func (d Definition) ModuleIDs() []module.ID {
ids := make([]module.ID, 0, len(d.Modules))
for _, item := range d.Modules {
ids = append(ids, item.ID)
}
return ids
}
type ResolveRequest struct {
Now time.Time
Location *time.Location
Date time.Time
}
type Resolved struct {
Definition Definition
GeneratedAt time.Time
Timezone string
ValidPeriod timeutil.Period
}
type Metadata struct {
RunID string `json:"runId"`
ReportID ID `json:"reportId"`
PromptID string `json:"promptId"`
GeneratedAt time.Time `json:"generatedAt"`
Timezone string `json:"timezone"`
ValidPeriod timeutil.Period `json:"validPeriod"`
}
func (r Resolved) Metadata() Metadata {
return Metadata{
RunID: r.runID(),
ReportID: r.Definition.ID,
PromptID: r.Definition.PromptID,
GeneratedAt: r.GeneratedAt,
Timezone: r.Timezone,
ValidPeriod: r.ValidPeriod,
}
}
func (r Resolved) runID() string {
runID := r.GeneratedAt.UTC().Format("20060102T150405.000000000Z") + "_" + string(r.Definition.ID)
if r.Definition.runIDDisambiguator == nil {
return runID
}
disambiguator := strings.TrimSpace(r.Definition.runIDDisambiguator(r))
if disambiguator == "" {
return runID
}
return runID + "_" + disambiguator
}