Fix rover planner: manual Calculate button, non-blocking computation
- Add explicit "Calculate Coverage" button instead of auto-triggering - Move coverage computation to background Task so LV stays responsive (users can keep adding/removing stations while it computes) - Remove all auto-compute triggers from station add/remove/band change - URL loading resolves stations but doesn't auto-calculate - Button shows "Finding best roving locations..." spinner while computing
This commit is contained in:
parent
961ae0782a
commit
a13d5a47f2
1 changed files with 69 additions and 35 deletions
|
|
@ -80,17 +80,24 @@ defmodule MicrowavepropWeb.RoverLive do
|
|||
idx = String.to_integer(idx_str)
|
||||
stations = List.delete_at(socket.assigns.stations, idx)
|
||||
socket = assign(socket, stations: stations, coverage: [], selected_grid: nil)
|
||||
if length(stations) >= 2, do: send(self(), :compute_coverage)
|
||||
socket = push_event(socket, "stations_updated", %{stations: station_data(stations)})
|
||||
{:noreply, push_url(socket)}
|
||||
end
|
||||
|
||||
def handle_event("select_band", %{"band" => band_str}, socket) do
|
||||
socket = assign(socket, band: String.to_integer(band_str), coverage: [], selected_grid: nil)
|
||||
if length(socket.assigns.stations) >= 2, do: send(self(), :compute_coverage)
|
||||
{:noreply, push_url(socket)}
|
||||
end
|
||||
|
||||
def handle_event("calculate", _params, socket) do
|
||||
if length(socket.assigns.stations) >= 2 and not socket.assigns.computing do
|
||||
send(self(), :compute_coverage)
|
||||
{:noreply, assign(socket, computing: true)}
|
||||
else
|
||||
{:noreply, socket}
|
||||
end
|
||||
end
|
||||
|
||||
def handle_event("select_grid", %{"grid" => grid}, socket) do
|
||||
detail = Enum.find(socket.assigns.coverage, &(&1.grid == grid))
|
||||
{:noreply, assign(socket, selected_grid: detail)}
|
||||
|
|
@ -112,7 +119,6 @@ defmodule MicrowavepropWeb.RoverLive do
|
|||
|> assign(stations: stations, resolving: false)
|
||||
|> push_event("stations_updated", %{stations: station_data(stations)})
|
||||
|
||||
if length(stations) >= 2, do: send(self(), :compute_coverage)
|
||||
{:noreply, socket}
|
||||
end
|
||||
|
||||
|
|
@ -123,7 +129,6 @@ defmodule MicrowavepropWeb.RoverLive do
|
|||
stations = socket.assigns.stations ++ [station]
|
||||
socket = assign(socket, stations: stations, resolving: false)
|
||||
socket = push_event(socket, "stations_updated", %{stations: station_data(stations)})
|
||||
if length(stations) >= 2, do: send(self(), :compute_coverage)
|
||||
{:noreply, push_url(socket)}
|
||||
|
||||
{:error, _reason} ->
|
||||
|
|
@ -134,11 +139,52 @@ defmodule MicrowavepropWeb.RoverLive do
|
|||
def handle_info(:compute_coverage, socket) do
|
||||
stations = socket.assigns.stations
|
||||
band_mhz = socket.assigns.band
|
||||
|
||||
if length(stations) < 2 do
|
||||
{:noreply, socket}
|
||||
else
|
||||
# Run in a background task so the LV stays responsive
|
||||
pid = self()
|
||||
|
||||
Task.start(fn ->
|
||||
result = do_compute_coverage(stations, band_mhz)
|
||||
send(pid, {:coverage_result, result})
|
||||
end)
|
||||
|
||||
{:noreply, assign(socket, computing: true)}
|
||||
end
|
||||
end
|
||||
|
||||
def handle_info({:coverage_result, coverage}, socket) do
|
||||
stations = socket.assigns.stations
|
||||
|
||||
grid_data =
|
||||
Enum.map(coverage, fn c ->
|
||||
%{
|
||||
grid: c.grid,
|
||||
lat: c.lat,
|
||||
lon: c.lon,
|
||||
coverage_score: c.coverage_score,
|
||||
stations_in_range: c.stations_in_range,
|
||||
workable_count: c.workable_count,
|
||||
total_stations: length(stations),
|
||||
prop_score: c.prop_score,
|
||||
best_hour: c.best_hour
|
||||
}
|
||||
end)
|
||||
|
||||
socket =
|
||||
socket
|
||||
|> assign(coverage: coverage, computing: false, selected_grid: nil)
|
||||
|> push_event("coverage_updated", %{grids: grid_data})
|
||||
|
||||
{:noreply, socket}
|
||||
end
|
||||
|
||||
defp do_compute_coverage(stations, band_mhz) do
|
||||
band_config = BandConfig.get(band_mhz) || BandConfig.get(10_000)
|
||||
max_range = band_config.extended_range_km || 500
|
||||
|
||||
socket = assign(socket, computing: true)
|
||||
|
||||
# Find the bounding box around all stations, expanded by max range
|
||||
lats = Enum.map(stations, & &1.lat)
|
||||
lons = Enum.map(stations, & &1.lon)
|
||||
|
|
@ -180,28 +226,7 @@ defmodule MicrowavepropWeb.RoverLive do
|
|||
end)
|
||||
|> Enum.sort_by(& &1.coverage_score, :desc)
|
||||
|
||||
# Push to JS for rendering
|
||||
grid_data =
|
||||
Enum.map(coverage, fn c ->
|
||||
%{
|
||||
grid: c.grid,
|
||||
lat: c.lat,
|
||||
lon: c.lon,
|
||||
coverage_score: c.coverage_score,
|
||||
stations_in_range: c.stations_in_range,
|
||||
workable_count: c.workable_count,
|
||||
total_stations: length(stations),
|
||||
prop_score: c.prop_score,
|
||||
best_hour: c.best_hour
|
||||
}
|
||||
end)
|
||||
|
||||
socket =
|
||||
socket
|
||||
|> assign(coverage: coverage, computing: false, selected_grid: nil)
|
||||
|> push_event("coverage_updated", %{grids: grid_data})
|
||||
|
||||
{:noreply, socket}
|
||||
coverage
|
||||
end
|
||||
|
||||
# ── Coverage Scoring ──
|
||||
|
|
@ -433,16 +458,25 @@ defmodule MicrowavepropWeb.RoverLive do
|
|||
</div>
|
||||
<% end %>
|
||||
|
||||
<%= if @computing do %>
|
||||
<div class="text-xs text-center py-3">
|
||||
<span class="loading loading-spinner loading-sm"></span>
|
||||
<div class="mt-1">Computing coverage areas...</div>
|
||||
</div>
|
||||
<%= if length(@stations) >= 2 do %>
|
||||
<button
|
||||
type="button"
|
||||
phx-click="calculate"
|
||||
class="btn btn-primary btn-sm w-full"
|
||||
disabled={@computing}
|
||||
>
|
||||
<%= if @computing do %>
|
||||
<span class="loading loading-spinner loading-sm"></span>
|
||||
Finding best roving locations...
|
||||
<% else %>
|
||||
Calculate Coverage
|
||||
<% end %>
|
||||
</button>
|
||||
<% end %>
|
||||
|
||||
<%= if @stations != [] and !@computing and @coverage == [] do %>
|
||||
<%= if length(@stations) == 1 do %>
|
||||
<div class="text-xs opacity-50 text-center py-2">
|
||||
Add at least 2 stations to see coverage
|
||||
Add at least 2 stations to calculate
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue