Files
weatherfeeder/internal/normalizers/common/wmo_text.go

130 lines
2.6 KiB
Go

// FILE: ./internal/normalizers/common/wmo_text.go
package common
import (
"strings"
"gitea.maximumdirect.net/ejr/weatherfeeder/internal/model"
)
// WMOFromTextDescription is a cross-provider fallback that tries to infer a WMO code
// from a human-readable condition string.
//
// This is intentionally “coarse” and conservative. It is useful when a provider:
//
// - does not provide a condition code, or
// - provides it inconsistently / null, or
// - provides only textual conditions for some endpoints.
//
// Providers may still choose to override this with richer signals
// (METAR phenomena, explicit numeric codes, etc.).
func WMOFromTextDescription(desc string) model.WMOCode {
s := strings.ToLower(strings.TrimSpace(desc))
if s == "" {
return model.WMOUnknown
}
// Thunder / hail
if strings.Contains(s, "thunder") {
if strings.Contains(s, "hail") {
return 99
}
return 95
}
// Freezing hazards
if strings.Contains(s, "freezing rain") {
if strings.Contains(s, "light") {
return 66
}
return 67
}
if strings.Contains(s, "freezing drizzle") {
if strings.Contains(s, "light") {
return 56
}
return 57
}
// Drizzle
if strings.Contains(s, "drizzle") {
if strings.Contains(s, "heavy") || strings.Contains(s, "dense") {
return 55
}
if strings.Contains(s, "light") {
return 51
}
return 53
}
// Showers
if strings.Contains(s, "showers") {
if strings.Contains(s, "heavy") {
return 82
}
if strings.Contains(s, "light") {
return 80
}
return 81
}
// Rain
if strings.Contains(s, "rain") {
if strings.Contains(s, "heavy") {
return 65
}
if strings.Contains(s, "light") {
return 61
}
return 63
}
// Snow (check snow showers first)
if strings.Contains(s, "snow showers") {
if strings.Contains(s, "light") {
return 85
}
return 86
}
if strings.Contains(s, "snow grains") {
return 77
}
if strings.Contains(s, "snow") {
if strings.Contains(s, "heavy") {
return 75
}
if strings.Contains(s, "light") {
return 71
}
return 73
}
// Fog / mist
if strings.Contains(s, "rime fog") {
return 48
}
if strings.Contains(s, "fog") || strings.Contains(s, "mist") {
return 45
}
// Sky-only
if strings.Contains(s, "overcast") {
return 3
}
if strings.Contains(s, "cloudy") {
return 3
}
if strings.Contains(s, "partly cloudy") {
return 2
}
if strings.Contains(s, "mostly sunny") || strings.Contains(s, "mostly clear") ||
strings.Contains(s, "mainly sunny") || strings.Contains(s, "mainly clear") {
return 1
}
if strings.Contains(s, "clear") || strings.Contains(s, "sunny") {
return 0
}
return model.WMOUnknown
}