revert(map): remove antenna-height control
The antenna-height input only scaled the displayed range labels and the viewshed max-range — it never fed into the propagation score itself. Showing the control implied the colored overlay responded to it, which was misleading. Viewshed now uses a fixed 10 m baseline, matching the previous 33 ft default.
This commit is contained in:
parent
72d4ad4815
commit
e3248e335b
2 changed files with 17 additions and 115 deletions
|
|
@ -87,7 +87,6 @@ defmodule MicrowavepropWeb.MapLive do
|
||||||
outside_conus: outside_conus?(visitor),
|
outside_conus: outside_conus?(visitor),
|
||||||
grid_visible: false,
|
grid_visible: false,
|
||||||
radar_visible: false,
|
radar_visible: false,
|
||||||
antenna_height_ft: 33,
|
|
||||||
deploy_iso: Calendar.strftime(build_ts, "%Y-%m-%d %H:%M UTC"),
|
deploy_iso: Calendar.strftime(build_ts, "%Y-%m-%d %H:%M UTC"),
|
||||||
deploy_ago: format_deploy_ago(build_ts)
|
deploy_ago: format_deploy_ago(build_ts)
|
||||||
)}
|
)}
|
||||||
|
|
@ -159,9 +158,7 @@ defmodule MicrowavepropWeb.MapLive do
|
||||||
|> assign(selected_band: band, valid_times: valid_times, selected_time: selected_time)
|
|> assign(selected_band: band, valid_times: valid_times, selected_time: selected_time)
|
||||||
|> LiveStash.stash_assigns([:selected_band, :selected_time])
|
|> LiveStash.stash_assigns([:selected_band, :selected_time])
|
||||||
|> push_event("update_scores", %{scores: scores})
|
|> push_event("update_scores", %{scores: scores})
|
||||||
|> push_event("update_band_info", %{
|
|> push_event("update_band_info", %{band_info: band_info(band)})
|
||||||
band_info: band_info(band, socket.assigns.antenna_height_ft)
|
|
||||||
})
|
|
||||||
|> push_timeline()
|
|> push_timeline()
|
||||||
|
|
||||||
{:noreply, socket}
|
{:noreply, socket}
|
||||||
|
|
@ -194,23 +191,6 @@ defmodule MicrowavepropWeb.MapLive do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def handle_event("set_antenna_height", %{"height_ft" => value}, socket) do
|
|
||||||
height =
|
|
||||||
case Integer.parse(value) do
|
|
||||||
{h, _} when h >= 0 and h <= 200 -> h
|
|
||||||
_ -> 8
|
|
||||||
end
|
|
||||||
|
|
||||||
socket =
|
|
||||||
socket
|
|
||||||
|> assign(:antenna_height_ft, height)
|
|
||||||
|> push_event("update_band_info", %{
|
|
||||||
band_info: band_info(socket.assigns.selected_band, height)
|
|
||||||
})
|
|
||||||
|
|
||||||
{:noreply, socket}
|
|
||||||
end
|
|
||||||
|
|
||||||
def handle_event("toggle_grid", _params, socket) do
|
def handle_event("toggle_grid", _params, socket) do
|
||||||
visible = !socket.assigns.grid_visible
|
visible = !socket.assigns.grid_visible
|
||||||
|
|
||||||
|
|
@ -275,7 +255,6 @@ defmodule MicrowavepropWeb.MapLive do
|
||||||
band_mhz = socket.assigns.selected_band
|
band_mhz = socket.assigns.selected_band
|
||||||
band_config = BandConfig.get(band_mhz)
|
band_config = BandConfig.get(band_mhz)
|
||||||
freq_ghz = band_mhz / 1_000
|
freq_ghz = band_mhz / 1_000
|
||||||
ant_height_m = socket.assigns.antenna_height_ft * 0.3048
|
|
||||||
|
|
||||||
score =
|
score =
|
||||||
case Propagation.point_detail(band_mhz, lat, lon) do
|
case Propagation.point_detail(band_mhz, lat, lon) do
|
||||||
|
|
@ -283,13 +262,13 @@ defmodule MicrowavepropWeb.MapLive do
|
||||||
_ -> 50
|
_ -> 50
|
||||||
end
|
end
|
||||||
|
|
||||||
max_range_km = score_range_km(score, band_config, socket.assigns.antenna_height_ft)
|
max_range_km = score_range_km(score, band_config)
|
||||||
|
|
||||||
socket =
|
socket =
|
||||||
start_async(socket, :viewshed, fn ->
|
start_async(socket, :viewshed, fn ->
|
||||||
Viewshed.compute(lat, lon,
|
Viewshed.compute(lat, lon,
|
||||||
freq_ghz: freq_ghz,
|
freq_ghz: freq_ghz,
|
||||||
ant_height_m: ant_height_m,
|
ant_height_m: 10.0,
|
||||||
max_range_km: max_range_km,
|
max_range_km: max_range_km,
|
||||||
score: score
|
score: score
|
||||||
)
|
)
|
||||||
|
|
@ -442,47 +421,29 @@ defmodule MicrowavepropWeb.MapLive do
|
||||||
Enum.min_by(times, fn t -> abs(DateTime.diff(t, now)) end)
|
Enum.min_by(times, fn t -> abs(DateTime.diff(t, now)) end)
|
||||||
end
|
end
|
||||||
|
|
||||||
defp score_range_km(score, config, ant_height_ft) do
|
defp score_range_km(score, config) do
|
||||||
factor = height_factor(ant_height_ft)
|
cond do
|
||||||
|
score >= 80 -> config.exceptional_range_km
|
||||||
base =
|
score >= 65 -> config.extended_range_km
|
||||||
cond do
|
score >= 50 -> config.typical_range_km
|
||||||
score >= 80 -> config.exceptional_range_km
|
score >= 33 -> round(config.typical_range_km * 0.6)
|
||||||
score >= 65 -> config.extended_range_km
|
true -> round(config.typical_range_km * 0.3)
|
||||||
score >= 50 -> config.typical_range_km
|
end
|
||||||
score >= 33 -> round(config.typical_range_km * 0.6)
|
|
||||||
true -> round(config.typical_range_km * 0.3)
|
|
||||||
end
|
|
||||||
|
|
||||||
round(base * factor)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
defp band_info(band_mhz, ant_height_ft) do
|
defp band_info(band_mhz) do
|
||||||
config = BandConfig.get(band_mhz)
|
config = BandConfig.get(band_mhz)
|
||||||
factor = height_factor(ant_height_ft)
|
|
||||||
|
|
||||||
%{
|
%{
|
||||||
band_label: config.label,
|
band_label: config.label,
|
||||||
typical_range_km: round(config.typical_range_km * factor),
|
typical_range_km: config.typical_range_km,
|
||||||
extended_range_km: round(config.extended_range_km * factor),
|
extended_range_km: config.extended_range_km,
|
||||||
exceptional_range_km: round(config.exceptional_range_km * factor),
|
exceptional_range_km: config.exceptional_range_km,
|
||||||
humidity_effect: to_string(config.humidity_effect),
|
humidity_effect: to_string(config.humidity_effect),
|
||||||
freq_mhz: config.freq_mhz,
|
freq_mhz: config.freq_mhz
|
||||||
antenna_height_ft: ant_height_ft
|
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
# Scales effective range with antenna height. Baseline 33 ft (~10 m) = 1.0;
|
|
||||||
# scales as sqrt(h_m / 10) because radio horizon scales as sqrt(height).
|
|
||||||
# Clamped to [0.6, 2.0] to avoid silly extremes at 0 ft and very tall towers.
|
|
||||||
defp height_factor(ant_height_ft) when is_number(ant_height_ft) do
|
|
||||||
h_m = max(ant_height_ft, 3) * 0.3048
|
|
||||||
factor = :math.sqrt(h_m / 10.0)
|
|
||||||
factor |> max(0.6) |> min(2.0)
|
|
||||||
end
|
|
||||||
|
|
||||||
defp height_factor(_), do: 1.0
|
|
||||||
|
|
||||||
defp selected_label(bands, selected_band) do
|
defp selected_label(bands, selected_band) do
|
||||||
case Enum.find(bands, &(&1.freq_mhz == selected_band)) do
|
case Enum.find(bands, &(&1.freq_mhz == selected_band)) do
|
||||||
nil -> "Select Band"
|
nil -> "Select Band"
|
||||||
|
|
@ -582,7 +543,7 @@ defmodule MicrowavepropWeb.MapLive do
|
||||||
phx-hook="PropagationMap"
|
phx-hook="PropagationMap"
|
||||||
phx-update="ignore"
|
phx-update="ignore"
|
||||||
data-scores={@initial_scores_json}
|
data-scores={@initial_scores_json}
|
||||||
data-band-info={Jason.encode!(band_info(@selected_band, @antenna_height_ft))}
|
data-band-info={Jason.encode!(band_info(@selected_band))}
|
||||||
data-valid-times={
|
data-valid-times={
|
||||||
Jason.encode!(
|
Jason.encode!(
|
||||||
Enum.map(@valid_times, fn t ->
|
Enum.map(@valid_times, fn t ->
|
||||||
|
|
@ -689,20 +650,6 @@ defmodule MicrowavepropWeb.MapLive do
|
||||||
<span class="text-sm">Weather radar</span>
|
<span class="text-sm">Weather radar</span>
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<form phx-change="set_antenna_height" class="flex items-center gap-2 px-1">
|
|
||||||
<label class="text-sm whitespace-nowrap">Antenna height</label>
|
|
||||||
<input
|
|
||||||
type="number"
|
|
||||||
name="height_ft"
|
|
||||||
min="0"
|
|
||||||
max="200"
|
|
||||||
step="1"
|
|
||||||
value={@antenna_height_ft}
|
|
||||||
class="input input-xs w-16 text-right"
|
|
||||||
/>
|
|
||||||
<span class="text-xs opacity-70">ft</span>
|
|
||||||
</form>
|
|
||||||
|
|
||||||
<div class="flex flex-col gap-1 border-t border-base-300 pt-2">
|
<div class="flex flex-col gap-1 border-t border-base-300 pt-2">
|
||||||
<.link navigate="/path" class="btn btn-xs btn-ghost justify-start">
|
<.link navigate="/path" class="btn btn-xs btn-ghost justify-start">
|
||||||
Path Calculator
|
Path Calculator
|
||||||
|
|
@ -844,21 +791,6 @@ defmodule MicrowavepropWeb.MapLive do
|
||||||
<span class="text-sm">Weather radar</span>
|
<span class="text-sm">Weather radar</span>
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<%!-- Antenna height --%>
|
|
||||||
<form phx-change="set_antenna_height" class="flex items-center gap-2 px-1">
|
|
||||||
<label class="text-sm whitespace-nowrap">Antenna height</label>
|
|
||||||
<input
|
|
||||||
type="number"
|
|
||||||
name="height_ft"
|
|
||||||
min="0"
|
|
||||||
max="200"
|
|
||||||
step="1"
|
|
||||||
value={@antenna_height_ft}
|
|
||||||
class="input input-xs w-16 text-right"
|
|
||||||
/>
|
|
||||||
<span class="text-xs opacity-70">ft</span>
|
|
||||||
</form>
|
|
||||||
|
|
||||||
<%!-- Navigation --%>
|
<%!-- Navigation --%>
|
||||||
<ul class="menu menu-xs border-t border-base-300 pt-2 px-0">
|
<ul class="menu menu-xs border-t border-base-300 pt-2 px-0">
|
||||||
<li>
|
<li>
|
||||||
|
|
|
||||||
|
|
@ -85,36 +85,6 @@ defmodule MicrowavepropWeb.MapLiveTest do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "antenna height" do
|
|
||||||
test "renders antenna height input with default 33 ft", %{conn: conn} do
|
|
||||||
{:ok, _lv, html} = live(conn, ~p"/map")
|
|
||||||
assert html =~ ~s(name="height_ft")
|
|
||||||
assert html =~ ~s(value="33")
|
|
||||||
assert html =~ "ft"
|
|
||||||
end
|
|
||||||
|
|
||||||
test "updates antenna height on change", %{conn: conn} do
|
|
||||||
{:ok, lv, _html} = live(conn, ~p"/map")
|
|
||||||
|
|
||||||
html = render_change(lv, "set_antenna_height", %{"height_ft" => "20"})
|
|
||||||
assert html =~ ~s(value="20")
|
|
||||||
end
|
|
||||||
|
|
||||||
test "pushes update_band_info with height-scaled ranges", %{conn: conn} do
|
|
||||||
{:ok, lv, _html} = live(conn, ~p"/map")
|
|
||||||
|
|
||||||
baseline = render_change(lv, "set_antenna_height", %{"height_ft" => "33"})
|
|
||||||
assert_push_event(lv, "update_band_info", %{band_info: %{typical_range_km: baseline_range}})
|
|
||||||
assert baseline =~ ~s(value="33")
|
|
||||||
|
|
||||||
tall = render_change(lv, "set_antenna_height", %{"height_ft" => "100"})
|
|
||||||
assert_push_event(lv, "update_band_info", %{band_info: %{typical_range_km: tall_range}})
|
|
||||||
assert tall =~ ~s(value="100")
|
|
||||||
|
|
||||||
assert tall_range > baseline_range
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
describe "compute_viewshed" do
|
describe "compute_viewshed" do
|
||||||
test "accepts compute_viewshed event without crashing", %{conn: conn} do
|
test "accepts compute_viewshed event without crashing", %{conn: conn} do
|
||||||
{:ok, lv, _html} = live(conn, ~p"/map")
|
{:ok, lv, _html} = live(conn, ~p"/map")
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue