diff --git a/lib/microwaveprop/pskr.ex b/lib/microwaveprop/pskr.ex index e2238875..7980ff55 100644 --- a/lib/microwaveprop/pskr.ex +++ b/lib/microwaveprop/pskr.ex @@ -152,16 +152,26 @@ defmodule Microwaveprop.Pskr do } end - # Keep locators at the precision the spotter reported. Maidenhead - # validity already enforces minimum 4 chars + even length + the - # right alphabet at each position, so anything that passes is a - # legal 4/6/8/10-char locator we can store as-is. Uppercase for - # consistent indexing — the unique key is case-sensitive. + # Require ≥ 6-char locators on both ends. 4-char grids cover + # ~70 km × 100 km, so the midpoint and path distance error + # dwarfs any HRRR cell match (3 km native) and the resulting + # calibration sample geometry is meaningless. Drop the spot + # entirely rather than store a low-precision row. + # + # Maidenhead validity enforces even length + correct alphabet + # per position, so a passing string is a legal 6/8/10-char + # locator we can store as-is. Uppercase for consistent indexing + # — the unique key is case-sensitive. defp fetch_grid(json, key) do case Map.get(json, key) do grid when is_binary(grid) -> upper = String.upcase(grid) - if Maidenhead.valid?(upper), do: {:ok, upper}, else: {:error, {:bad_grid, key, grid}} + + cond do + not Maidenhead.valid?(upper) -> {:error, {:bad_grid, key, grid}} + String.length(upper) < 6 -> {:error, {:short_grid, key, grid}} + true -> {:ok, upper} + end other -> {:error, {:missing_grid, key, other}} diff --git a/test/microwaveprop/pskr_test.exs b/test/microwaveprop/pskr_test.exs index 1a04a880..4ba9d718 100644 --- a/test/microwaveprop/pskr_test.exs +++ b/test/microwaveprop/pskr_test.exs @@ -36,12 +36,16 @@ defmodule Microwaveprop.PskrTest do assert DateTime.to_unix(spot.transmit_time) == 1_662_407_697 end - test "accepts 4-char grids verbatim" do - json = @sample |> Map.merge(%{"sl" => "EM12", "rl" => "DM43"}) |> Jason.encode!() + test "rejects 4-char grids on either end (insufficient precision)" do + # A 4-char locator is ~70 km × 100 km — the midpoint and + # distance error swamps any HRRR cell match (3 km native). + # Drop the spot rather than store a calibration sample whose + # geometry is meaningless. + sender_short = @sample |> Map.put("sl", "EM12") |> Jason.encode!() + receiver_short = @sample |> Map.put("rl", "DM43") |> Jason.encode!() - assert {:ok, spot} = Pskr.parse_spot(json) - assert spot.sender_grid == "EM12" - assert spot.receiver_grid == "DM43" + assert {:error, _} = Pskr.parse_spot(sender_short) + assert {:error, _} = Pskr.parse_spot(receiver_short) end test "preserves extended-square (8-char) precision" do