Reduce cyclomatic complexity in weather callsign view

Simplify timestamp comparison and weather value formatting:
- Extract compare_timestamps with pattern matching for different types
- Remove duplicate formatter code (was a bug)
- Extract format_string_value and format_numeric_value helpers

Co-Authored-By: Graham <noreply@anthropic.com>
This commit is contained in:
Graham McIntire 2026-02-09 12:10:56 -06:00
parent 12cf324d4c
commit c30a1c55f7
No known key found for this signature in database

View file

@ -92,38 +92,35 @@ defmodule AprsmeWeb.WeatherLive.CallsignView do
defp should_update_weather?(nil, _new_packet), do: true defp should_update_weather?(nil, _new_packet), do: true
defp should_update_weather?(current_packet, new_packet) do defp should_update_weather?(current_packet, new_packet) do
# Only update if the new packet is actually newer
# Handle both atom and string keys
new_received_at = Map.get(new_packet, :received_at) || Map.get(new_packet, "received_at") new_received_at = Map.get(new_packet, :received_at) || Map.get(new_packet, "received_at")
current_received_at = Map.get(current_packet, :received_at) || Map.get(current_packet, "received_at") current_received_at = Map.get(current_packet, :received_at) || Map.get(current_packet, "received_at")
case {new_received_at, current_received_at} do compare_timestamps(new_received_at, current_received_at)
{nil, _} -> end
false
{_, nil} -> defp compare_timestamps(nil, _), do: false
true defp compare_timestamps(_, nil), do: true
{new_time, current_time} when is_binary(new_time) and is_binary(current_time) -> defp compare_timestamps(new_time, current_time) when is_binary(new_time) and is_binary(current_time) do
new_time > current_time new_time > current_time
end
{new_time, current_time} when is_binary(new_time) -> defp compare_timestamps(new_time, current_time) when is_binary(new_time) do
# Parse string timestamp and compare
case DateTime.from_iso8601(new_time <> "Z") do case DateTime.from_iso8601(new_time <> "Z") do
{:ok, new_dt, _} -> DateTime.after?(new_dt, current_time) {:ok, new_dt, _} -> DateTime.after?(new_dt, current_time)
_ -> false _ -> false
end end
end
{new_time, current_time} when is_binary(current_time) -> defp compare_timestamps(new_time, current_time) when is_binary(current_time) do
# Parse string timestamp and compare
case DateTime.from_iso8601(current_time <> "Z") do case DateTime.from_iso8601(current_time <> "Z") do
{:ok, current_dt, _} -> DateTime.after?(new_time, current_dt) {:ok, current_dt, _} -> DateTime.after?(new_time, current_dt)
_ -> true _ -> true
end end
{new_time, current_time} ->
DateTime.after?(new_time, current_time)
end end
defp compare_timestamps(new_time, current_time) do
DateTime.after?(new_time, current_time)
end end
defp update_weather_data(socket) do defp update_weather_data(socket) do
@ -246,22 +243,18 @@ defmodule AprsmeWeb.WeatherLive.CallsignView do
value = PacketUtils.get_weather_field(packet, key) value = PacketUtils.get_weather_field(packet, key)
case value do case value do
"N/A" -> v when v == "N/A" or is_nil(v) ->
nil
nil ->
nil nil
value when is_binary(value) -> value when is_binary(value) ->
case @weather_formatters[key] do format_string_value(value, key, locale)
{formatter, separator} ->
{converted_value, unit} = formatter.(value, locale)
"#{converted_value}#{separator}#{unit}"
nil -> value when is_number(value) ->
"#{value}" format_numeric_value(value, key, locale)
end
end end
defp format_string_value(value, key, locale) do
case @weather_formatters[key] do case @weather_formatters[key] do
{formatter, separator} -> {formatter, separator} ->
case Float.parse(value) do case Float.parse(value) do
@ -276,8 +269,9 @@ defmodule AprsmeWeb.WeatherLive.CallsignView do
nil -> nil ->
"#{value}" "#{value}"
end end
end
value when is_number(value) -> defp format_numeric_value(value, key, locale) do
case @weather_formatters[key] do case @weather_formatters[key] do
{formatter, separator} -> {formatter, separator} ->
{converted_value, unit} = formatter.(value, locale) {converted_value, unit} = formatter.(value, locale)
@ -287,5 +281,4 @@ defmodule AprsmeWeb.WeatherLive.CallsignView do
"#{value}" "#{value}"
end end
end end
end
end end