// 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 }