Add current conditions condition code consensus helper
This commit is contained in:
107
internal/adapters/outbound/postgres/conditions_codes.go
Normal file
107
internal/adapters/outbound/postgres/conditions_codes.go
Normal file
@@ -0,0 +1,107 @@
|
||||
// conditions_codes.go selects current-conditions WMO codes from source candidates.
|
||||
// Layer: adapters/outbound/postgres conditions feature.
|
||||
package postgres
|
||||
|
||||
import "gitea.maximumdirect.net/ejr/weatherfeeder/model"
|
||||
|
||||
type currentConditionsConditionCodeCandidate struct {
|
||||
EventSource string
|
||||
ConditionCode model.WMOCode
|
||||
}
|
||||
|
||||
type conditionCodeFamily int
|
||||
|
||||
const (
|
||||
conditionCodeFamilyUnknown conditionCodeFamily = iota
|
||||
conditionCodeFamilyClearOrCloud
|
||||
conditionCodeFamilyFog
|
||||
conditionCodeFamilyDrizzle
|
||||
conditionCodeFamilyRain
|
||||
conditionCodeFamilySnow
|
||||
conditionCodeFamilyThunderstorm
|
||||
)
|
||||
|
||||
var currentConditionsConditionCodeRankings = map[conditionCodeFamily][]model.WMOCode{
|
||||
conditionCodeFamilyClearOrCloud: {0, 1, 2, 3},
|
||||
conditionCodeFamilyFog: {45, 48},
|
||||
conditionCodeFamilyDrizzle: {51, 53, 55, 56, 57},
|
||||
conditionCodeFamilyRain: {61, 63, 65, 80, 81, 82, 66, 67},
|
||||
conditionCodeFamilySnow: {71, 73, 75, 85, 86, 77},
|
||||
conditionCodeFamilyThunderstorm: {95, 96, 99},
|
||||
}
|
||||
|
||||
var currentConditionsConditionCodeFamilies = buildCurrentConditionsConditionCodeFamilies()
|
||||
|
||||
func buildCurrentConditionsConditionCodeFamilies() map[model.WMOCode]conditionCodeFamily {
|
||||
families := make(map[model.WMOCode]conditionCodeFamily)
|
||||
for family, ranking := range currentConditionsConditionCodeRankings {
|
||||
for _, code := range ranking {
|
||||
families[code] = family
|
||||
}
|
||||
}
|
||||
return families
|
||||
}
|
||||
|
||||
func selectCurrentConditionsConditionCode(candidates []currentConditionsConditionCodeCandidate) model.WMOCode {
|
||||
seenSources := make(map[string]struct{})
|
||||
familyCounts := make(map[conditionCodeFamily]int)
|
||||
codeCounts := make(map[model.WMOCode]int)
|
||||
|
||||
for _, candidate := range candidates {
|
||||
if _, seen := seenSources[candidate.EventSource]; seen {
|
||||
continue
|
||||
}
|
||||
seenSources[candidate.EventSource] = struct{}{}
|
||||
|
||||
family, ok := currentConditionsConditionCodeFamilies[candidate.ConditionCode]
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
familyCounts[family]++
|
||||
codeCounts[candidate.ConditionCode]++
|
||||
}
|
||||
|
||||
winningFamily, ok := currentConditionsWinningConditionCodeFamily(familyCounts)
|
||||
if !ok {
|
||||
return model.WMOUnknown
|
||||
}
|
||||
|
||||
return currentConditionsWinningConditionCode(winningFamily, codeCounts)
|
||||
}
|
||||
|
||||
func currentConditionsWinningConditionCodeFamily(counts map[conditionCodeFamily]int) (conditionCodeFamily, bool) {
|
||||
winningFamily := conditionCodeFamilyUnknown
|
||||
winningCount := 0
|
||||
tied := false
|
||||
|
||||
for family, count := range counts {
|
||||
if count > winningCount {
|
||||
winningFamily = family
|
||||
winningCount = count
|
||||
tied = false
|
||||
continue
|
||||
}
|
||||
if count == winningCount {
|
||||
tied = true
|
||||
}
|
||||
}
|
||||
|
||||
if winningCount == 0 || tied {
|
||||
return conditionCodeFamilyUnknown, false
|
||||
}
|
||||
return winningFamily, true
|
||||
}
|
||||
|
||||
func currentConditionsWinningConditionCode(family conditionCodeFamily, counts map[model.WMOCode]int) model.WMOCode {
|
||||
winningCode := model.WMOUnknown
|
||||
winningCount := 0
|
||||
|
||||
for _, code := range currentConditionsConditionCodeRankings[family] {
|
||||
if counts[code] > winningCount {
|
||||
winningCode = code
|
||||
winningCount = counts[code]
|
||||
}
|
||||
}
|
||||
|
||||
return winningCode
|
||||
}
|
||||
Reference in New Issue
Block a user