defmodule Microwaveprop.GeoTest do use ExUnit.Case, async: true alias Microwaveprop.Geo alias Microwaveprop.Radio.Maidenhead describe "haversine_km/4" do test "returns 0.0 for identical points" do assert Geo.haversine_km(32.9, -96.8, 32.9, -96.8) == 0.0 end test "matches a known long-distance pair (DFW to Newington, CT)" do assert_in_delta Geo.haversine_km(32.9, -96.8, 41.714, -72.727), 2333.3, 1.0 end test "computes a half-circumference for antipodal equator points" do # Half the Earth's circumference at R = 6371 km is ~20015 km. assert_in_delta Geo.haversine_km(0.0, 0.0, 0.0, 180.0), 20_015.0, 1.0 end test "is symmetric in its arguments" do forward = Geo.haversine_km(32.9, -96.8, 41.714, -72.727) reverse = Geo.haversine_km(41.714, -72.727, 32.9, -96.8) assert_in_delta forward, reverse, 0.0001 end test "one degree of latitude is roughly 111 km" do assert_in_delta Geo.haversine_km(32.0, -96.0, 33.0, -96.0), 111.195, 0.1 end end describe "bearing_deg/4" do test "returns 0.0 for due north" do assert Geo.bearing_deg(32.0, -96.0, 33.0, -96.0) == 0.0 end test "returns ~90 for due east at the equator" do assert_in_delta Geo.bearing_deg(0.0, 0.0, 0.0, 1.0), 90.0, 0.1 end test "returns 180.0 for due south" do assert Geo.bearing_deg(32.0, -96.0, 31.0, -96.0) == 180.0 end test "returns a bearing in the range [0, 360)" do bearing = Geo.bearing_deg(32.0, -96.0, 32.0, -97.0) assert bearing >= 0.0 and bearing < 360.0 assert_in_delta bearing, 270.0, 1.0 end test "rounds to one decimal place" do # DFW to Newington - pick any pair, the result must have at most 1 decimal. bearing = Geo.bearing_deg(32.9, -96.8, 41.714, -72.727) assert Float.round(bearing, 1) == bearing end end describe "maidenhead_center/1" do test "returns the center of a 4-character grid" do # EM12 is lat 32-33, lon -98 to -96, center (32.5, -97.0). assert Geo.maidenhead_center("EM12") == {32.5, -97.0} end test "returns the center of a 6-character grid at higher precision" do {lat, lon} = Geo.maidenhead_center("EM12kp") assert_in_delta lat, 32.6458, 0.001 assert_in_delta lon, -97.125, 0.001 end test "accepts lowercase grids" do assert Geo.maidenhead_center("em12") == {32.5, -97.0} end test "returns nil for invalid grid characters" do assert Geo.maidenhead_center("ZZZZ") == nil end end describe "latlon_to_grid4/2" do test "encodes the DFW area as EM12" do assert Geo.latlon_to_grid4(32.9, -96.8) == "EM12" end test "encodes Newington, CT as FN31" do assert Geo.latlon_to_grid4(41.714, -72.727) == "FN31" end test "encodes the prime-meridian/equator origin as JJ00" do assert Geo.latlon_to_grid4(0.0, 0.0) == "JJ00" end test "agrees with Maidenhead.from_latlon/3 at precision 4 for typical US coords" do for {lat, lon} <- [{32.9, -96.8}, {41.714, -72.727}, {40.0, -105.0}, {47.6, -122.3}] do assert Geo.latlon_to_grid4(lat, lon) == Maidenhead.from_latlon(lat, lon, 4) end end end end