diff --git a/lib/microwaveprop_web/live/rover_live.ex b/lib/microwaveprop_web/live/rover_live.ex index 75fbabc1..6363c6bd 100644 --- a/lib/microwaveprop_web/live/rover_live.ex +++ b/lib/microwaveprop_web/live/rover_live.ex @@ -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 <% end %> - <%= if @computing do %> -
- -
Computing coverage areas...
-
+ <%= if length(@stations) >= 2 do %> + <% end %> - <%= if @stations != [] and !@computing and @coverage == [] do %> + <%= if length(@stations) == 1 do %>
- Add at least 2 stations to see coverage + Add at least 2 stations to calculate
<% end %>