fix(pskr): drop spots with <6-char grids on either end
A 4-char locator covers ~70 km × 100 km, which dwarfs HRRR's 3 km
native cell and any midpoint we'd derive for the calibration corpus.
Storing those samples gives the recalibrator geometry that's
indistinguishable from noise.
fetch_grid/2 now returns {:error, {:short_grid, key, grid}} for any
locator under 6 chars after Maidenhead validation. The spot is
dropped before it reaches the aggregator, so neither pskr_spots_hourly
nor pskr_calibration_samples ever see it.
This commit is contained in:
parent
b08fc5e449
commit
1a3dc4fa0a
2 changed files with 25 additions and 11 deletions
|
|
@ -152,16 +152,26 @@ defmodule Microwaveprop.Pskr do
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
# Keep locators at the precision the spotter reported. Maidenhead
|
# Require ≥ 6-char locators on both ends. 4-char grids cover
|
||||||
# validity already enforces minimum 4 chars + even length + the
|
# ~70 km × 100 km, so the midpoint and path distance error
|
||||||
# right alphabet at each position, so anything that passes is a
|
# dwarfs any HRRR cell match (3 km native) and the resulting
|
||||||
# legal 4/6/8/10-char locator we can store as-is. Uppercase for
|
# calibration sample geometry is meaningless. Drop the spot
|
||||||
# consistent indexing — the unique key is case-sensitive.
|
# 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
|
defp fetch_grid(json, key) do
|
||||||
case Map.get(json, key) do
|
case Map.get(json, key) do
|
||||||
grid when is_binary(grid) ->
|
grid when is_binary(grid) ->
|
||||||
upper = String.upcase(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 ->
|
other ->
|
||||||
{:error, {:missing_grid, key, other}}
|
{:error, {:missing_grid, key, other}}
|
||||||
|
|
|
||||||
|
|
@ -36,12 +36,16 @@ defmodule Microwaveprop.PskrTest do
|
||||||
assert DateTime.to_unix(spot.transmit_time) == 1_662_407_697
|
assert DateTime.to_unix(spot.transmit_time) == 1_662_407_697
|
||||||
end
|
end
|
||||||
|
|
||||||
test "accepts 4-char grids verbatim" do
|
test "rejects 4-char grids on either end (insufficient precision)" do
|
||||||
json = @sample |> Map.merge(%{"sl" => "EM12", "rl" => "DM43"}) |> Jason.encode!()
|
# 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 {:error, _} = Pskr.parse_spot(sender_short)
|
||||||
assert spot.sender_grid == "EM12"
|
assert {:error, _} = Pskr.parse_spot(receiver_short)
|
||||||
assert spot.receiver_grid == "DM43"
|
|
||||||
end
|
end
|
||||||
|
|
||||||
test "preserves extended-square (8-char) precision" do
|
test "preserves extended-square (8-char) precision" do
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue