- Replace stub propagation.ex with real implementation (score_grid_point, upsert_scores, latest_scores, latest_valid_time) - Add PropagationGridWorker (hourly Oban cron) for CONUS grid scoring - Add mix propagation_grid task for manual triggering - Fix duplicate extract_grid/2 from parallel merges - Fix extract_grid to skip outside-grid points instead of erroring - Add propagation queue to Oban config
101 lines
3 KiB
Elixir
101 lines
3 KiB
Elixir
defmodule Microwaveprop.PropagationTest do
|
|
use Microwaveprop.DataCase
|
|
|
|
alias Microwaveprop.Propagation
|
|
alias Microwaveprop.Propagation.GridScore
|
|
|
|
describe "score_grid_point/2" do
|
|
test "scores a single point for all 8 bands" do
|
|
hrrr_profile = %{
|
|
surface_temp_c: 25.0,
|
|
surface_dewpoint_c: 18.0,
|
|
surface_pressure_mb: 1013.0,
|
|
hpbl_m: 500.0,
|
|
wind_u: 3.0,
|
|
wind_v: 2.0,
|
|
cloud_cover_pct: 15.0,
|
|
precip_mm: 0.0,
|
|
profile: [
|
|
%{"pres" => 1000.0, "tmpc" => 25.0, "dwpc" => 18.0, "hght" => 100.0},
|
|
%{"pres" => 975.0, "tmpc" => 22.0, "dwpc" => 15.0, "hght" => 350.0},
|
|
%{"pres" => 950.0, "tmpc" => 19.0, "dwpc" => 10.0, "hght" => 600.0}
|
|
]
|
|
}
|
|
|
|
valid_time = ~U[2026-07-15 13:00:00Z]
|
|
results = Propagation.score_grid_point(hrrr_profile, valid_time)
|
|
|
|
assert length(results) == 8
|
|
|
|
Enum.each(results, fn result ->
|
|
assert result.score >= 0 and result.score <= 100
|
|
assert map_size(result.factors) == 9
|
|
assert is_integer(result.band_mhz)
|
|
end)
|
|
end
|
|
end
|
|
|
|
describe "upsert_scores/1" do
|
|
test "inserts scores" do
|
|
valid_time = ~U[2026-07-15 13:00:00Z]
|
|
|
|
scores = [
|
|
%{lat: 35.0, lon: -97.0, valid_time: valid_time, band_mhz: 10_000, score: 75, factors: %{humidity: 90}},
|
|
%{lat: 35.0, lon: -97.0, valid_time: valid_time, band_mhz: 24_000, score: 60, factors: %{humidity: 40}}
|
|
]
|
|
|
|
assert {:ok, 2} = Propagation.upsert_scores(scores)
|
|
assert Repo.aggregate(GridScore, :count) == 2
|
|
end
|
|
|
|
test "upserts on conflict" do
|
|
valid_time = ~U[2026-07-15 13:00:00Z]
|
|
|
|
scores = [
|
|
%{lat: 35.0, lon: -97.0, valid_time: valid_time, band_mhz: 10_000, score: 75, factors: %{}}
|
|
]
|
|
|
|
Propagation.upsert_scores(scores)
|
|
Propagation.upsert_scores([%{hd(scores) | score: 80}])
|
|
|
|
assert Repo.aggregate(GridScore, :count) == 1
|
|
end
|
|
end
|
|
|
|
describe "latest_scores/1" do
|
|
test "returns latest scores for a band" do
|
|
valid_time = ~U[2026-07-15 13:00:00Z]
|
|
|
|
scores = [
|
|
%{lat: 35.0, lon: -97.0, valid_time: valid_time, band_mhz: 10_000, score: 75, factors: %{}},
|
|
%{lat: 36.0, lon: -96.0, valid_time: valid_time, band_mhz: 10_000, score: 80, factors: %{}}
|
|
]
|
|
|
|
Propagation.upsert_scores(scores)
|
|
results = Propagation.latest_scores(10_000)
|
|
assert length(results) == 2
|
|
end
|
|
|
|
test "returns empty list when no data" do
|
|
assert Propagation.latest_scores(10_000) == []
|
|
end
|
|
end
|
|
|
|
describe "latest_valid_time/0" do
|
|
test "returns nil when empty" do
|
|
assert Propagation.latest_valid_time() == nil
|
|
end
|
|
|
|
test "returns most recent time" do
|
|
t1 = ~U[2026-07-15 12:00:00Z]
|
|
t2 = ~U[2026-07-15 13:00:00Z]
|
|
|
|
Propagation.upsert_scores([
|
|
%{lat: 35.0, lon: -97.0, valid_time: t1, band_mhz: 10_000, score: 50, factors: %{}},
|
|
%{lat: 35.0, lon: -97.0, valid_time: t2, band_mhz: 10_000, score: 60, factors: %{}}
|
|
])
|
|
|
|
assert Propagation.latest_valid_time() == t2
|
|
end
|
|
end
|
|
end
|