package maidenhead import ( "math" "strings" "testing" ) var tests = []struct { point Point loc string loc4 string }{ {Point{48.14666, 11.60833}, "JN58TD", "JN58TD25"}, {Point{-34.91, -56.21166}, "GF15VC", "GF15VC41"}, {Point{38.92, -77.065}, "FM18LW", "FM18LW20"}, {Point{-41.28333, 174.745}, "RE78IR", "RE78IR92"}, {Point{41.714775, -72.727260}, "FN31PR", "FN31PR21"}, {Point{37.413708, -122.1073236}, "CM87WJ", "CM87WJ79"}, {Point{35.0542, -85.1142}, "EM75KB", "EM75KB63"}, } func TestGridSquare(t *testing.T) { for _, test := range tests { t.Run(test.loc, func(t *testing.T) { enc, err := test.point.GridSquare() if err != nil { t.Fatal(err) } if enc != test.loc { t.Fatalf("%s want %q, got %q\n", test.point, test.loc, enc) } //t.Logf("%s encoded to %q\n", test.point, enc) }) } } func TestExtendedSquarePrecision(t *testing.T) { for _, test := range tests { t.Run(test.loc4, func(t *testing.T) { got, err := test.point.Locator(ExtendedSquarePrecision) if err != nil { t.Fatal(err) } if got != test.loc4 { t.Fatalf("%s want %q, got %q\n", test.point, test.loc4, got) } //t.Logf("%s encoded to %q\n", test.point, got) }) } } // parsed locator must be translated to the same locator // using GridSquare() func TestParseLocator(t *testing.T) { var locTests = map[string]Point{ "JN88RT": Point{48.791667, 17.416667}, "JN89HF": Point{49.208333, 16.583333}, "JN58TD": Point{48.125000, 11.583333}, "GF15VC": Point{-34.916667, -56.250000}, "FM18LW": Point{38.916667, -77.083333}, "RE78IR": Point{-41.291667, 174.666667}, "PM45lm": Point{35.5, 128.916667}, } for loc, p := range locTests { t.Run(loc, func(t *testing.T) { point, err := ParseLocator(loc) if err != nil { t.Fatalf("%s parsing error: %s", loc, err) } l, err := point.GridSquare() if err != nil { t.Fatalf("%s: %v to GridSquare(): %s", loc, point, err) } if !strings.EqualFold(l, loc) { t.Errorf("%s: parsed to %v produces %s\n", loc, point, l) } if !(almostEqual(p.Latitude, point.Latitude) && almostEqual(p.Longitude, point.Longitude)) { t.Errorf("%s: at %s, expeted %s", loc, point, p) } }) } } func almostEqual(a, b float64) bool { return math.Abs(a-b) < 1e-06 } // invalid Maiden Head locators must return error func TestParseInvalidLocatorStrict(t *testing.T) { locs := []string{ "JN58td", "JN58TDAA", "JNH", "QN58jh", "JN77ya", " ", "JN55J", "JN89HA11aa2", "JN89HA11aa22", } for _, l := range locs { t.Run(l, func(t *testing.T) { _, err := ParseLocatorStrict(l) if err == nil { t.Errorf("Parsing invalid locator '%s' with ParseLocatorStrict() doesn't return any error", l) } }) } } // Distance between corner point and center of the locator square func TestParseLocatorCentered(t *testing.T) { tests := []struct { loc string distExpected float64 }{ {"JN89", 91.42870273454076}, {"JN89HF", 3.8111046375990782}, {"JN89HF23", 0.38109528459829756}, {"JN89HF23ag", 0.015878904160500258}, } for _, test := range tests { t.Run(test.loc, func(t *testing.T) { p, _ := ParseLocator(test.loc) pc, _ := ParseLocatorCentered(test.loc) dist := pc.Distance(p) if !almostEqual(dist, test.distExpected) { t.Errorf("Distance between the center and corner of square locator '%s' is %g, expected %g", test.loc, dist, test.distExpected) } }) } }