108 lines
3.0 KiB
Go
108 lines
3.0 KiB
Go
// 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
|
|
}
|