defmodule MicrowavepropWeb.ContactMapLive do @moduledoc false use MicrowavepropWeb, :live_view import Ecto.Query alias Microwaveprop.Radio.Contact alias Microwaveprop.Repo @impl true def mount(_params, _session, socket) do contacts = load_contacts() {:ok, assign(socket, page_title: "Contact Map", contacts_json: Jason.encode!(contacts), contact_count: length(contacts) )} end defp load_contacts do from(c in Contact, where: not is_nil(c.pos1) and not is_nil(c.pos2), select: %{ id: c.id, pos1: c.pos1, pos2: c.pos2, band: c.band, station1: c.station1, station2: c.station2, mode: c.mode, distance_km: c.distance_km, qso_timestamp: c.qso_timestamp } ) |> Repo.all() |> Enum.map(fn c -> lat1 = c.pos1["lat"] lon1 = c.pos1["lon"] || c.pos1["lng"] lat2 = c.pos2["lat"] lon2 = c.pos2["lon"] || c.pos2["lng"] band = if c.band, do: Decimal.to_integer(c.band), else: 0 dist = if c.distance_km, do: Decimal.to_float(c.distance_km) ts = if c.qso_timestamp, do: Calendar.strftime(c.qso_timestamp, "%Y-%m-%d %H:%M") if lat1 && lon1 && lat2 && lon2 do [lat1, lon1, lat2, lon2, band, c.station1, c.station2, c.mode, dist, ts, c.id] end end) |> Enum.reject(&is_nil/1) |> dedup_reciprocals() end # Deduplicate reciprocal contacts (A↔B same band/hour = same contact logged by both sides) defp dedup_reciprocals(contacts) do Enum.uniq_by(contacts, fn [_lat1, _lon1, _lat2, _lon2, band, s1, s2, _mode, _dist, ts, _id] -> stations = Enum.sort([s1 || "", s2 || ""]) hour = if ts, do: String.slice(ts, 0..12), else: "" {stations, band, hour} end) end @impl true def render(assigns) do ~H"""
Contact Map
{Integer.to_string(@contact_count)} contacts
""" end end