feat(discovery/crawler): PLZ-to-land inference helper
This commit is contained in:
45
backend/internal/domain/discovery/crawler/plz.go
Normal file
45
backend/internal/domain/discovery/crawler/plz.go
Normal file
@@ -0,0 +1,45 @@
|
||||
package crawler
|
||||
|
||||
import "strings"
|
||||
|
||||
// InferLand maps a PLZ to a DACH country. 5-digit -> DE. 4-digit is ambiguous
|
||||
// between AT and CH; we recognize common CH ranges (1000-1299 Geneva/Vaud,
|
||||
// 3000-3999 Bern, 4000-4999 Basel/Aarau, 6000-6999 Luzern/Ticino/Wallis,
|
||||
// 8000-8999 Zurich, 9000-9999 St. Gallen) and fall back to AT for everything
|
||||
// else 4-digit. Unknown -> "". The Land string is the form used throughout
|
||||
// discovery (not ISO-2).
|
||||
func InferLand(plz string) string {
|
||||
plz = strings.TrimSpace(plz)
|
||||
switch len(plz) {
|
||||
case 5:
|
||||
if !isAllDigits(plz) {
|
||||
return ""
|
||||
}
|
||||
return "Deutschland"
|
||||
case 4:
|
||||
if !isAllDigits(plz) {
|
||||
return ""
|
||||
}
|
||||
switch plz[0] {
|
||||
case '1':
|
||||
if plz >= "1200" && plz <= "1299" {
|
||||
return "Schweiz"
|
||||
}
|
||||
return "Oesterreich"
|
||||
case '3', '4', '6', '8', '9':
|
||||
return "Schweiz"
|
||||
default:
|
||||
return "Oesterreich"
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func isAllDigits(s string) bool {
|
||||
for _, r := range s {
|
||||
if r < '0' || r > '9' {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
29
backend/internal/domain/discovery/crawler/plz_test.go
Normal file
29
backend/internal/domain/discovery/crawler/plz_test.go
Normal file
@@ -0,0 +1,29 @@
|
||||
package crawler
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestInferLand(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
plz string
|
||||
want string
|
||||
}{
|
||||
{"empty", "", ""},
|
||||
{"de 5-digit", "49186", "Deutschland"},
|
||||
{"de 5-digit low", "01067", "Deutschland"},
|
||||
{"at 4-digit typical", "1010", "Oesterreich"},
|
||||
{"ch 4-digit typical", "8001", "Schweiz"},
|
||||
{"ch 4-digit zurich range", "8000", "Schweiz"},
|
||||
{"ch 4-digit bern range", "3000", "Schweiz"},
|
||||
{"at 4-digit outside ch ranges", "2500", "Oesterreich"},
|
||||
{"short garbage", "12", ""},
|
||||
{"non-numeric", "abcde", ""},
|
||||
}
|
||||
for _, tc := range tests {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
if got := InferLand(tc.plz); got != tc.want {
|
||||
t.Errorf("InferLand(%q) = %q; want %q", tc.plz, got, tc.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user