140 lines
4.6 KiB
Go
140 lines
4.6 KiB
Go
// Package promptinput builds prompt data packages from briefing packages.
|
|
package promptinput
|
|
|
|
import (
|
|
"fmt"
|
|
"time"
|
|
|
|
"gitea.maximumdirect.net/eric/weatherreporter/internal/briefing"
|
|
"gitea.maximumdirect.net/eric/weatherreporter/internal/changes"
|
|
"gitea.maximumdirect.net/eric/weatherreporter/internal/fileutil"
|
|
"gitea.maximumdirect.net/eric/weatherreporter/internal/forecast"
|
|
"gitea.maximumdirect.net/eric/weatherreporter/internal/report"
|
|
"gitea.maximumdirect.net/eric/weatherreporter/internal/timeutil"
|
|
)
|
|
|
|
const SchemaVersion = "weatherreporter.data_package.v1"
|
|
|
|
type Package struct {
|
|
SchemaVersion string `json:"schemaVersion"`
|
|
RunID string `json:"runId"`
|
|
Report Report `json:"report"`
|
|
Briefing briefing.Package `json:"briefing"`
|
|
RecentChanges RecentChanges `json:"recentChanges"`
|
|
SourceWarnings []forecast.SourceWarning `json:"sourceWarnings,omitempty"`
|
|
}
|
|
|
|
type Report struct {
|
|
ID report.ID `json:"id"`
|
|
Variant string `json:"variant,omitempty"`
|
|
PromptID string `json:"promptId"`
|
|
GeneratedAt time.Time `json:"generatedAt"`
|
|
Timezone string `json:"timezone"`
|
|
CurrentLocalDate string `json:"currentLocalDate"`
|
|
ValidPeriod timeutil.Period `json:"validPeriod"`
|
|
}
|
|
|
|
type RecentChanges struct {
|
|
Items []changes.Change `json:"items"`
|
|
}
|
|
|
|
func Build(briefingPackage briefing.Package) (Package, error) {
|
|
return BuildWithRecentChanges(briefingPackage, nil)
|
|
}
|
|
|
|
func BuildWithRecentChanges(briefingPackage briefing.Package, recentChanges []changes.Change) (Package, error) {
|
|
localDate, err := currentLocalDate(briefingPackage.Metadata.GeneratedAt, briefingPackage.Metadata.Timezone)
|
|
if err != nil {
|
|
return Package{}, err
|
|
}
|
|
items := make([]changes.Change, len(recentChanges))
|
|
copy(items, recentChanges)
|
|
if items == nil {
|
|
items = []changes.Change{}
|
|
}
|
|
pkg := Package{
|
|
SchemaVersion: SchemaVersion,
|
|
RunID: briefingPackage.Metadata.RunID,
|
|
Report: Report{
|
|
ID: briefingPackage.Metadata.ReportID,
|
|
Variant: briefingPackage.Metadata.Variant,
|
|
PromptID: briefingPackage.Metadata.PromptID,
|
|
GeneratedAt: briefingPackage.Metadata.GeneratedAt,
|
|
Timezone: briefingPackage.Metadata.Timezone,
|
|
CurrentLocalDate: localDate,
|
|
ValidPeriod: briefingPackage.Metadata.ValidPeriod,
|
|
},
|
|
Briefing: briefingPackage,
|
|
RecentChanges: RecentChanges{Items: items},
|
|
SourceWarnings: briefingPackage.Metadata.SourceWarnings,
|
|
}
|
|
if err := Validate(pkg); err != nil {
|
|
return Package{}, err
|
|
}
|
|
return pkg, nil
|
|
}
|
|
|
|
func currentLocalDate(generatedAt time.Time, timezone string) (string, error) {
|
|
location, err := timeutil.LoadLocation(timezone)
|
|
if err != nil {
|
|
return "", fmt.Errorf("load report timezone %q: %w", timezone, err)
|
|
}
|
|
return generatedAt.In(location).Format(timeutil.DateLayout), nil
|
|
}
|
|
|
|
func Validate(pkg Package) error {
|
|
if pkg.SchemaVersion == "" {
|
|
return fmt.Errorf("schemaVersion is required")
|
|
}
|
|
if pkg.RunID == "" {
|
|
return fmt.Errorf("runId is required")
|
|
}
|
|
if pkg.Report.ID == "" {
|
|
return fmt.Errorf("report.id is required")
|
|
}
|
|
if pkg.Report.PromptID == "" {
|
|
return fmt.Errorf("report.promptId is required")
|
|
}
|
|
if pkg.Report.GeneratedAt.IsZero() {
|
|
return fmt.Errorf("report.generatedAt is required")
|
|
}
|
|
if pkg.Report.Timezone == "" {
|
|
return fmt.Errorf("report.timezone is required")
|
|
}
|
|
if pkg.Report.CurrentLocalDate == "" {
|
|
return fmt.Errorf("report.currentLocalDate is required")
|
|
}
|
|
if !pkg.Report.ValidPeriod.IsValid() {
|
|
return fmt.Errorf("report.validPeriod must be valid")
|
|
}
|
|
if pkg.Briefing.Metadata.RunID == "" {
|
|
return fmt.Errorf("briefing.metadata.runId is required")
|
|
}
|
|
if pkg.Briefing.Metadata.RunID != pkg.RunID {
|
|
return fmt.Errorf("briefing.metadata.runId must match runId")
|
|
}
|
|
if pkg.Briefing.Metadata.SchemaVersion == "" {
|
|
return fmt.Errorf("briefing.metadata.schemaVersion is required")
|
|
}
|
|
if pkg.Briefing.Metadata.PromptID != pkg.Report.PromptID {
|
|
return fmt.Errorf("briefing.metadata.promptId must match report.promptId")
|
|
}
|
|
if pkg.Briefing.Metadata.ReportID != pkg.Report.ID {
|
|
return fmt.Errorf("briefing.metadata.reportId must match report.id")
|
|
}
|
|
if pkg.Briefing.Daily == nil && pkg.Briefing.ThreeDay == nil && pkg.Briefing.Weekend == nil && pkg.Briefing.Storm == nil {
|
|
return fmt.Errorf("briefing report content is required")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func Save(path string, pkg Package) error {
|
|
if err := Validate(pkg); err != nil {
|
|
return err
|
|
}
|
|
if err := fileutil.WriteJSONAtomic(path, pkg); err != nil {
|
|
return fmt.Errorf("save data package: %w", err)
|
|
}
|
|
return nil
|
|
}
|