Initial import

This commit is contained in:
2026-02-14 15:59:31 +01:00
parent 05dcea3c2b
commit f1ecbfaf8d
19 changed files with 2675 additions and 0 deletions

View File

@@ -0,0 +1,142 @@
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)
}
})
}
}