Define briefing fact requirement vocabulary

This commit is contained in:
2026-08-13 03:59:09 +00:00
parent 965f16d7a4
commit 2c4c0bbd90
5 changed files with 146 additions and 73 deletions

View File

@@ -0,0 +1,54 @@
package briefing
type factRequirementCategory string
const (
collectedFactRequirement factRequirementCategory = "collected"
derivedFactRequirement factRequirementCategory = "derived"
)
type factRequirement struct {
identity string
category factRequirementCategory
}
func (r factRequirement) String() string {
return r.identity
}
var (
currentConditionsRequirement = factRequirement{identity: "collected.current_conditions", category: collectedFactRequirement}
narrativeForecastRequirement = factRequirement{identity: "collected.narrative_forecast", category: collectedFactRequirement}
hourlyForecastRequirement = factRequirement{identity: "collected.hourly_forecast", category: collectedFactRequirement}
alertsRequirement = factRequirement{identity: "collected.alerts", category: collectedFactRequirement}
discussionRequirement = factRequirement{identity: "collected.discussion", category: collectedFactRequirement}
weatherStoryRequirement = factRequirement{identity: "collected.weather_story", category: collectedFactRequirement}
spcOutlooksRequirement = factRequirement{identity: "collected.spc_convective_outlooks", category: collectedFactRequirement}
sourceMetadataRequirement = factRequirement{identity: "collected.source_metadata", category: collectedFactRequirement}
hourlyPeriodsRequirement = factRequirement{identity: "derived.hourly_periods", category: derivedFactRequirement}
narrativePeriodsRequirement = factRequirement{identity: "derived.narrative_periods", category: derivedFactRequirement}
alertOverlapsRequirement = factRequirement{identity: "derived.alert_overlaps", category: derivedFactRequirement}
dailySummariesRequirement = factRequirement{identity: "derived.daily_summaries", category: derivedFactRequirement}
daypartSummariesRequirement = factRequirement{identity: "derived.daypart_summaries", category: derivedFactRequirement}
precipTimingRequirement = factRequirement{identity: "derived.precip_timing", category: derivedFactRequirement}
spcDerivedOutlooksRequirement = factRequirement{identity: "derived.spc_convective_outlooks", category: derivedFactRequirement}
)
var factRequirementVocabulary = []factRequirement{
currentConditionsRequirement,
narrativeForecastRequirement,
hourlyForecastRequirement,
alertsRequirement,
discussionRequirement,
weatherStoryRequirement,
spcOutlooksRequirement,
sourceMetadataRequirement,
hourlyPeriodsRequirement,
narrativePeriodsRequirement,
alertOverlapsRequirement,
dailySummariesRequirement,
daypartSummariesRequirement,
precipTimingRequirement,
spcDerivedOutlooksRequirement,
}

View File

@@ -28,8 +28,8 @@ type ModuleDefinition struct {
ID module.ID ID module.ID
StanzaName string StanzaName string
DefaultOptions any DefaultOptions any
RequiredCollected []module.FactRequirement RequiredCollected []factRequirement
RequiredDerived []module.FactRequirement RequiredDerived []factRequirement
SupportedReports []report.ID SupportedReports []report.ID
MissingData module.MissingDataBehavior MissingData module.MissingDataBehavior
AllowDuplicate bool AllowDuplicate bool
@@ -154,55 +154,55 @@ func missingRequirements(definition ModuleDefinition, ctx ModuleContext) []strin
var missing []string var missing []string
for _, requirement := range definition.RequiredCollected { for _, requirement := range definition.RequiredCollected {
if !collectedFactAvailable(requirement, ctx) { if !collectedFactAvailable(requirement, ctx) {
missing = append(missing, string(requirement)) missing = append(missing, requirement.String())
} }
} }
for _, requirement := range definition.RequiredDerived { for _, requirement := range definition.RequiredDerived {
if !derivedFactAvailable(requirement, ctx) { if !derivedFactAvailable(requirement, ctx) {
missing = append(missing, string(requirement)) missing = append(missing, requirement.String())
} }
} }
return missing return missing
} }
func collectedFactAvailable(requirement module.FactRequirement, ctx ModuleContext) bool { func collectedFactAvailable(requirement factRequirement, ctx ModuleContext) bool {
switch requirement { switch requirement {
case module.CollectedCurrentConditions: case currentConditionsRequirement:
return ctx.Collected.Current != nil return ctx.Collected.Current != nil
case module.CollectedNarrativeForecast: case narrativeForecastRequirement:
return ctx.Collected.Narrative != nil return ctx.Collected.Narrative != nil
case module.CollectedHourlyForecast: case hourlyForecastRequirement:
return ctx.Collected.Hourly != nil return ctx.Collected.Hourly != nil
case module.CollectedAlerts: case alertsRequirement:
return ctx.Collected.Alerts != nil return ctx.Collected.Alerts != nil
case module.CollectedDiscussion: case discussionRequirement:
return ctx.Collected.Discussion != nil return ctx.Collected.Discussion != nil
case module.CollectedWeatherStory: case weatherStoryRequirement:
return ctx.Collected.WeatherStory != nil return ctx.Collected.WeatherStory != nil
case module.CollectedSPCConvectiveOutlooks: case spcOutlooksRequirement:
return ctx.Collected.SPCConvectiveOutlooks != nil return ctx.Collected.SPCConvectiveOutlooks != nil
case module.CollectedSourceMetadata: case sourceMetadataRequirement:
return len(ctx.Collected.SourceProvenance) > 0 || len(ctx.Collected.SourceWarnings) > 0 return len(ctx.Collected.SourceProvenance) > 0 || len(ctx.Collected.SourceWarnings) > 0
default: default:
return false return false
} }
} }
func derivedFactAvailable(requirement module.FactRequirement, ctx ModuleContext) bool { func derivedFactAvailable(requirement factRequirement, ctx ModuleContext) bool {
switch requirement { switch requirement {
case module.RequiresDerivedHourlyPeriods: case hourlyPeriodsRequirement:
return len(ctx.Derived.ValidPeriodHourlyPeriods) > 0 return len(ctx.Derived.ValidPeriodHourlyPeriods) > 0
case module.RequiresDerivedNarrativePeriods: case narrativePeriodsRequirement:
return len(ctx.Derived.ValidPeriodNarrativePeriods) > 0 return len(ctx.Derived.ValidPeriodNarrativePeriods) > 0
case module.RequiresDerivedAlertOverlaps: case alertOverlapsRequirement:
return true return true
case module.RequiresDerivedDailySummaries: case dailySummariesRequirement:
return len(ctx.Derived.DailySummaries) > 0 return len(ctx.Derived.DailySummaries) > 0
case module.RequiresDerivedDaypartSummaries: case daypartSummariesRequirement:
return len(ctx.Derived.DaypartSummaries) > 0 return len(ctx.Derived.DaypartSummaries) > 0
case module.RequiresDerivedPrecipTiming: case precipTimingRequirement:
return true return true
case module.RequiresDerivedSPCConvectiveOutlooks: case spcDerivedOutlooksRequirement:
return ctx.Derived.SPCConvectiveOutlooks != nil return ctx.Derived.SPCConvectiveOutlooks != nil
default: default:
return false return false
@@ -291,7 +291,7 @@ func defaultModuleDefinitions() []ModuleDefinition {
ID: module.Metadata, ID: module.Metadata,
StanzaName: "metadata", StanzaName: "metadata",
DefaultOptions: module.MetadataOptions{}, DefaultOptions: module.MetadataOptions{},
RequiredCollected: []module.FactRequirement{module.CollectedSourceMetadata}, RequiredCollected: []factRequirement{sourceMetadataRequirement},
SupportedReports: allReports, SupportedReports: allReports,
MissingData: module.MissingDataEmpty, MissingData: module.MissingDataEmpty,
Builder: buildMetadataModule, Builder: buildMetadataModule,
@@ -300,7 +300,7 @@ func defaultModuleDefinitions() []ModuleDefinition {
ID: module.CurrentConditions, ID: module.CurrentConditions,
StanzaName: "current_conditions", StanzaName: "current_conditions",
DefaultOptions: module.CurrentConditionsOptions{}, DefaultOptions: module.CurrentConditionsOptions{},
RequiredCollected: []module.FactRequirement{module.CollectedCurrentConditions}, RequiredCollected: []factRequirement{currentConditionsRequirement},
SupportedReports: allReports, SupportedReports: allReports,
MissingData: module.MissingDataOmit, MissingData: module.MissingDataOmit,
Builder: buildCurrentConditionsModule, Builder: buildCurrentConditionsModule,
@@ -310,8 +310,8 @@ func defaultModuleDefinitions() []ModuleDefinition {
ID: module.NarrativeForecast, ID: module.NarrativeForecast,
StanzaName: "narrative_forecast", StanzaName: "narrative_forecast",
DefaultOptions: module.NarrativeForecastOptions{}, DefaultOptions: module.NarrativeForecastOptions{},
RequiredCollected: []module.FactRequirement{module.CollectedNarrativeForecast}, RequiredCollected: []factRequirement{narrativeForecastRequirement},
RequiredDerived: []module.FactRequirement{module.RequiresDerivedNarrativePeriods}, RequiredDerived: []factRequirement{narrativePeriodsRequirement},
SupportedReports: []report.ID{report.Daily, report.Today, report.Tomorrow}, SupportedReports: []report.ID{report.Daily, report.Today, report.Tomorrow},
MissingData: module.MissingDataOmit, MissingData: module.MissingDataOmit,
Builder: buildNarrativeForecastModule, Builder: buildNarrativeForecastModule,
@@ -320,8 +320,8 @@ func defaultModuleDefinitions() []ModuleDefinition {
ID: module.HourlyForecast, ID: module.HourlyForecast,
StanzaName: "hourly_forecast", StanzaName: "hourly_forecast",
DefaultOptions: module.HourlyForecastOptions{}, DefaultOptions: module.HourlyForecastOptions{},
RequiredCollected: []module.FactRequirement{module.CollectedHourlyForecast}, RequiredCollected: []factRequirement{hourlyForecastRequirement},
RequiredDerived: []module.FactRequirement{module.RequiresDerivedHourlyPeriods}, RequiredDerived: []factRequirement{hourlyPeriodsRequirement},
SupportedReports: []report.ID{report.Daily, report.Today, report.Tomorrow, report.Hourly}, SupportedReports: []report.ID{report.Daily, report.Today, report.Tomorrow, report.Hourly},
MissingData: module.MissingDataOmit, MissingData: module.MissingDataOmit,
Builder: buildHourlyForecastModule, Builder: buildHourlyForecastModule,
@@ -331,7 +331,7 @@ func defaultModuleDefinitions() []ModuleDefinition {
ID: module.DerivedDailySummary, ID: module.DerivedDailySummary,
StanzaName: "derived_daily_summary", StanzaName: "derived_daily_summary",
DefaultOptions: module.DerivedDailySummaryOptions{}, DefaultOptions: module.DerivedDailySummaryOptions{},
RequiredDerived: []module.FactRequirement{module.RequiresDerivedDailySummaries, module.RequiresDerivedPrecipTiming}, RequiredDerived: []factRequirement{dailySummariesRequirement, precipTimingRequirement},
SupportedReports: []report.ID{report.Daily, report.Today, report.Tomorrow}, SupportedReports: []report.ID{report.Daily, report.Today, report.Tomorrow},
MissingData: module.MissingDataError, MissingData: module.MissingDataError,
Builder: buildDerivedDailySummaryModule, Builder: buildDerivedDailySummaryModule,
@@ -340,7 +340,7 @@ func defaultModuleDefinitions() []ModuleDefinition {
ID: module.DerivedDaypartSummaries, ID: module.DerivedDaypartSummaries,
StanzaName: "derived_daypart_summaries", StanzaName: "derived_daypart_summaries",
DefaultOptions: module.DerivedDaypartSummariesOptions{}, DefaultOptions: module.DerivedDaypartSummariesOptions{},
RequiredDerived: []module.FactRequirement{module.RequiresDerivedDaypartSummaries}, RequiredDerived: []factRequirement{daypartSummariesRequirement},
SupportedReports: daypartReports, SupportedReports: daypartReports,
MissingData: module.MissingDataError, MissingData: module.MissingDataError,
Builder: buildDerivedDaypartSummariesModule, Builder: buildDerivedDaypartSummariesModule,
@@ -350,7 +350,7 @@ func defaultModuleDefinitions() []ModuleDefinition {
ID: module.PrecipTiming, ID: module.PrecipTiming,
StanzaName: "precip_timing", StanzaName: "precip_timing",
DefaultOptions: module.PrecipTimingOptions{}, DefaultOptions: module.PrecipTimingOptions{},
RequiredDerived: []module.FactRequirement{module.RequiresDerivedPrecipTiming}, RequiredDerived: []factRequirement{precipTimingRequirement},
SupportedReports: allReports, SupportedReports: allReports,
MissingData: module.MissingDataEmpty, MissingData: module.MissingDataEmpty,
Builder: buildPrecipTimingModule, Builder: buildPrecipTimingModule,
@@ -359,8 +359,8 @@ func defaultModuleDefinitions() []ModuleDefinition {
ID: module.AlertDigest, ID: module.AlertDigest,
StanzaName: "alert_digest", StanzaName: "alert_digest",
DefaultOptions: module.AlertDigestOptions{}, DefaultOptions: module.AlertDigestOptions{},
RequiredCollected: []module.FactRequirement{module.CollectedAlerts}, RequiredCollected: []factRequirement{alertsRequirement},
RequiredDerived: []module.FactRequirement{module.RequiresDerivedAlertOverlaps}, RequiredDerived: []factRequirement{alertOverlapsRequirement},
SupportedReports: allReports, SupportedReports: allReports,
MissingData: module.MissingDataEmpty, MissingData: module.MissingDataEmpty,
Builder: buildAlertDigestModule, Builder: buildAlertDigestModule,
@@ -369,8 +369,8 @@ func defaultModuleDefinitions() []ModuleDefinition {
ID: module.SPCConvectiveOutlooks, ID: module.SPCConvectiveOutlooks,
StanzaName: string(module.SPCConvectiveOutlooks), StanzaName: string(module.SPCConvectiveOutlooks),
DefaultOptions: module.SPCConvectiveOutlooksOptions{}, DefaultOptions: module.SPCConvectiveOutlooksOptions{},
RequiredCollected: []module.FactRequirement{module.CollectedSPCConvectiveOutlooks}, RequiredCollected: []factRequirement{spcOutlooksRequirement},
RequiredDerived: []module.FactRequirement{module.RequiresDerivedSPCConvectiveOutlooks}, RequiredDerived: []factRequirement{spcDerivedOutlooksRequirement},
SupportedReports: allReports, SupportedReports: allReports,
MissingData: module.MissingDataEmpty, MissingData: module.MissingDataEmpty,
Builder: buildSPCConvectiveOutlooksModule, Builder: buildSPCConvectiveOutlooksModule,
@@ -379,7 +379,7 @@ func defaultModuleDefinitions() []ModuleDefinition {
ID: module.AreaForecastDiscussion, ID: module.AreaForecastDiscussion,
StanzaName: "area_forecast_discussion", StanzaName: "area_forecast_discussion",
DefaultOptions: module.AreaForecastDiscussionOptions{}, DefaultOptions: module.AreaForecastDiscussionOptions{},
RequiredCollected: []module.FactRequirement{module.CollectedDiscussion}, RequiredCollected: []factRequirement{discussionRequirement},
SupportedReports: allReports, SupportedReports: allReports,
MissingData: module.MissingDataOmit, MissingData: module.MissingDataOmit,
Builder: buildAreaForecastDiscussionModule, Builder: buildAreaForecastDiscussionModule,
@@ -388,8 +388,8 @@ func defaultModuleDefinitions() []ModuleDefinition {
ID: module.SPCConvectiveDiscussion, ID: module.SPCConvectiveDiscussion,
StanzaName: string(module.SPCConvectiveDiscussion), StanzaName: string(module.SPCConvectiveDiscussion),
DefaultOptions: module.SPCConvectiveDiscussionOptions{}, DefaultOptions: module.SPCConvectiveDiscussionOptions{},
RequiredCollected: []module.FactRequirement{module.CollectedSPCConvectiveOutlooks}, RequiredCollected: []factRequirement{spcOutlooksRequirement},
RequiredDerived: []module.FactRequirement{module.RequiresDerivedSPCConvectiveOutlooks}, RequiredDerived: []factRequirement{spcDerivedOutlooksRequirement},
SupportedReports: allReports, SupportedReports: allReports,
MissingData: module.MissingDataOmit, MissingData: module.MissingDataOmit,
Builder: buildSPCConvectiveDiscussionModule, Builder: buildSPCConvectiveDiscussionModule,
@@ -398,7 +398,7 @@ func defaultModuleDefinitions() []ModuleDefinition {
ID: module.WeatherStory, ID: module.WeatherStory,
StanzaName: "weather_story", StanzaName: "weather_story",
DefaultOptions: module.WeatherStoryOptions{}, DefaultOptions: module.WeatherStoryOptions{},
RequiredCollected: []module.FactRequirement{module.CollectedWeatherStory}, RequiredCollected: []factRequirement{weatherStoryRequirement},
SupportedReports: allReports, SupportedReports: allReports,
MissingData: module.MissingDataOmit, MissingData: module.MissingDataOmit,
Builder: buildWeatherStoryModule, Builder: buildWeatherStoryModule,
@@ -407,7 +407,7 @@ func defaultModuleDefinitions() []ModuleDefinition {
ID: module.OutdoorWindows, ID: module.OutdoorWindows,
StanzaName: "outdoor_windows", StanzaName: "outdoor_windows",
DefaultOptions: module.OutdoorWindowsOptions{}, DefaultOptions: module.OutdoorWindowsOptions{},
RequiredDerived: []module.FactRequirement{module.RequiresDerivedDaypartSummaries}, RequiredDerived: []factRequirement{daypartSummariesRequirement},
SupportedReports: daypartReports, SupportedReports: daypartReports,
MissingData: module.MissingDataEmpty, MissingData: module.MissingDataEmpty,
Builder: buildOutdoorWindowsModule, Builder: buildOutdoorWindowsModule,
@@ -416,7 +416,7 @@ func defaultModuleDefinitions() []ModuleDefinition {
ID: module.TodayPlanning, ID: module.TodayPlanning,
StanzaName: "today_planning", StanzaName: "today_planning",
DefaultOptions: module.TodayPlanningOptions{}, DefaultOptions: module.TodayPlanningOptions{},
RequiredDerived: []module.FactRequirement{module.RequiresDerivedDailySummaries}, RequiredDerived: []factRequirement{dailySummariesRequirement},
SupportedReports: []report.ID{report.Today}, SupportedReports: []report.ID{report.Today},
MissingData: module.MissingDataEmpty, MissingData: module.MissingDataEmpty,
Builder: buildTodayPlanningModule, Builder: buildTodayPlanningModule,
@@ -425,7 +425,7 @@ func defaultModuleDefinitions() []ModuleDefinition {
ID: module.TomorrowPlanning, ID: module.TomorrowPlanning,
StanzaName: "tomorrow_planning", StanzaName: "tomorrow_planning",
DefaultOptions: module.TomorrowPlanningOptions{}, DefaultOptions: module.TomorrowPlanningOptions{},
RequiredDerived: []module.FactRequirement{module.RequiresDerivedDailySummaries}, RequiredDerived: []factRequirement{dailySummariesRequirement},
SupportedReports: []report.ID{report.Tomorrow}, SupportedReports: []report.ID{report.Tomorrow},
MissingData: module.MissingDataEmpty, MissingData: module.MissingDataEmpty,
Builder: buildTomorrowPlanningModule, Builder: buildTomorrowPlanningModule,
@@ -434,7 +434,7 @@ func defaultModuleDefinitions() []ModuleDefinition {
ID: module.DailyPlanning, ID: module.DailyPlanning,
StanzaName: "daily_planning", StanzaName: "daily_planning",
DefaultOptions: module.DailyPlanningOptions{}, DefaultOptions: module.DailyPlanningOptions{},
RequiredDerived: []module.FactRequirement{module.RequiresDerivedDailySummaries}, RequiredDerived: []factRequirement{dailySummariesRequirement},
SupportedReports: []report.ID{report.Daily}, SupportedReports: []report.ID{report.Daily},
MissingData: module.MissingDataEmpty, MissingData: module.MissingDataEmpty,
Builder: buildDailyPlanningModule, Builder: buildDailyPlanningModule,

View File

@@ -30,6 +30,52 @@ func TestDefaultModuleRegistryValidatesReportDefaults(t *testing.T) {
} }
} }
func TestFactRequirementVocabularyMatchesModuleDefinitions(t *testing.T) {
vocabulary := make(map[string]factRequirement, len(factRequirementVocabulary))
for _, requirement := range factRequirementVocabulary {
if requirement.identity == "" {
t.Fatal("fact requirement identity is empty")
}
if requirement.category != collectedFactRequirement && requirement.category != derivedFactRequirement {
t.Fatalf("fact requirement %q category = %q, want collected or derived", requirement.identity, requirement.category)
}
if _, exists := vocabulary[requirement.identity]; exists {
t.Fatalf("duplicate fact requirement %q", requirement.identity)
}
vocabulary[requirement.identity] = requirement
}
used := map[factRequirement]struct{}{}
for _, definition := range defaultModuleDefinitions() {
for _, requirement := range definition.RequiredCollected {
assertFactRequirementCategory(t, vocabulary, used, definition.ID, requirement, collectedFactRequirement)
}
for _, requirement := range definition.RequiredDerived {
assertFactRequirementCategory(t, vocabulary, used, definition.ID, requirement, derivedFactRequirement)
}
}
for _, requirement := range factRequirementVocabulary {
if _, ok := used[requirement]; !ok {
t.Fatalf("fact requirement %q is not used by a module definition", requirement.identity)
}
}
}
func assertFactRequirementCategory(t *testing.T, vocabulary map[string]factRequirement, used map[factRequirement]struct{}, moduleID module.ID, requirement factRequirement, want factRequirementCategory) {
t.Helper()
descriptor, ok := vocabulary[requirement.identity]
if !ok {
t.Fatalf("module %q uses unknown fact requirement %q", moduleID, requirement.identity)
}
if descriptor != requirement {
t.Fatalf("module %q requirement %q does not use the vocabulary descriptor", moduleID, requirement.identity)
}
if requirement.category != want {
t.Fatalf("module %q requirement %q category = %q, want %q", moduleID, requirement.identity, requirement.category, want)
}
used[requirement] = struct{}{}
}
func TestDefaultReportModulesBuildSnapshots(t *testing.T) { func TestDefaultReportModulesBuildSnapshots(t *testing.T) {
registry := MustDefaultModuleRegistry() registry := MustDefaultModuleRegistry()
for _, definition := range report.DefaultRegistry().All() { for _, definition := range report.DefaultRegistry().All() {
@@ -467,24 +513,24 @@ func TestModuleRegistryAcceptsTypedOptions(t *testing.T) {
func TestSPCConvectiveOutlookCollectedRequirementAvailability(t *testing.T) { func TestSPCConvectiveOutlookCollectedRequirementAvailability(t *testing.T) {
ctx := ModuleContext{} ctx := ModuleContext{}
if collectedFactAvailable(module.CollectedSPCConvectiveOutlooks, ctx) { if collectedFactAvailable(spcOutlooksRequirement, ctx) {
t.Fatal("collectedFactAvailable() = true, want false without source") t.Fatal("collectedFactAvailable() = true, want false without source")
} }
ctx.Collected = facts.CollectedFacts{SPCConvectiveOutlooks: &weatherdata.ConvectiveOutlookRun{}} ctx.Collected = facts.CollectedFacts{SPCConvectiveOutlooks: &weatherdata.ConvectiveOutlookRun{}}
if !collectedFactAvailable(module.CollectedSPCConvectiveOutlooks, ctx) { if !collectedFactAvailable(spcOutlooksRequirement, ctx) {
t.Fatal("collectedFactAvailable() = false, want true with checked source") t.Fatal("collectedFactAvailable() = false, want true with checked source")
} }
} }
func TestSPCConvectiveOutlookDerivedRequirementAvailability(t *testing.T) { func TestSPCConvectiveOutlookDerivedRequirementAvailability(t *testing.T) {
ctx := ModuleContext{} ctx := ModuleContext{}
if derivedFactAvailable(module.RequiresDerivedSPCConvectiveOutlooks, ctx) { if derivedFactAvailable(spcDerivedOutlooksRequirement, ctx) {
t.Fatal("derivedFactAvailable() = true, want false without derived outlooks") t.Fatal("derivedFactAvailable() = true, want false without derived outlooks")
} }
ctx.Derived = facts.DerivedFacts{SPCConvectiveOutlooks: []weatherdata.ConvectiveOutlook{}} ctx.Derived = facts.DerivedFacts{SPCConvectiveOutlooks: []weatherdata.ConvectiveOutlook{}}
if !derivedFactAvailable(module.RequiresDerivedSPCConvectiveOutlooks, ctx) { if !derivedFactAvailable(spcDerivedOutlooksRequirement, ctx) {
t.Fatal("derivedFactAvailable() = false, want true for checked empty derived outlooks") t.Fatal("derivedFactAvailable() = false, want true for checked empty derived outlooks")
} }
} }

View File

@@ -114,26 +114,6 @@ func StanzaValue[T any](s Snapshot, name string) (T, bool, error) {
return zero, true, nil return zero, true, nil
} }
type FactRequirement string
const (
CollectedCurrentConditions FactRequirement = "collected.current_conditions"
CollectedNarrativeForecast FactRequirement = "collected.narrative_forecast"
CollectedHourlyForecast FactRequirement = "collected.hourly_forecast"
CollectedAlerts FactRequirement = "collected.alerts"
CollectedDiscussion FactRequirement = "collected.discussion"
CollectedWeatherStory FactRequirement = "collected.weather_story"
CollectedSPCConvectiveOutlooks FactRequirement = "collected.spc_convective_outlooks"
CollectedSourceMetadata FactRequirement = "collected.source_metadata"
RequiresDerivedHourlyPeriods FactRequirement = "derived.hourly_periods"
RequiresDerivedNarrativePeriods FactRequirement = "derived.narrative_periods"
RequiresDerivedAlertOverlaps FactRequirement = "derived.alert_overlaps"
RequiresDerivedDailySummaries FactRequirement = "derived.daily_summaries"
RequiresDerivedDaypartSummaries FactRequirement = "derived.daypart_summaries"
RequiresDerivedPrecipTiming FactRequirement = "derived.precip_timing"
RequiresDerivedSPCConvectiveOutlooks FactRequirement = "derived.spc_convective_outlooks"
)
type MissingDataBehavior string type MissingDataBehavior string
const ( const (

View File

@@ -120,13 +120,6 @@ func TestSPCConvectiveModuleContractsAreStable(t *testing.T) {
if SPCConvectiveDiscussion != ID("spc_convective_discussion") { if SPCConvectiveDiscussion != ID("spc_convective_discussion") {
t.Fatalf("SPCConvectiveDiscussion = %q, want stable discussion module ID", SPCConvectiveDiscussion) t.Fatalf("SPCConvectiveDiscussion = %q, want stable discussion module ID", SPCConvectiveDiscussion)
} }
if CollectedSPCConvectiveOutlooks != FactRequirement("collected.spc_convective_outlooks") {
t.Fatalf("CollectedSPCConvectiveOutlooks = %q, want collected requirement", CollectedSPCConvectiveOutlooks)
}
if RequiresDerivedSPCConvectiveOutlooks != FactRequirement("derived.spc_convective_outlooks") {
t.Fatalf("RequiresDerivedSPCConvectiveOutlooks = %q, want derived requirement", RequiresDerivedSPCConvectiveOutlooks)
}
_ = SPCConvectiveOutlooksOptions{} _ = SPCConvectiveOutlooksOptions{}
_ = SPCConvectiveDiscussionOptions{} _ = SPCConvectiveDiscussionOptions{}
} }