- Delete dead config keys and test file (typo'd aprsme_is_*, vacuous disable test) - Remove duplicate function clauses and identical function pairs - Rename misleading one_hour_ago variable to one_day_ago - Strip stale Oban comment - Remove TestHelpers time function duplicates - Inline Aprsme.Schema module (only 1 caller) - Deduplicate prod esbuild config - Thin SymbolRenderer delegations, inline TimeUtils wrappers - Remove redundant DeploymentNotifier GenServer polling - Replace random fallback in get_callsign_key with sentinel
93 lines
2.9 KiB
Elixir
93 lines
2.9 KiB
Elixir
defmodule AprsmeWeb.WeatherUnits do
|
|
@moduledoc """
|
|
Handles weather unit conversions and formatting based on locale.
|
|
Supports imperial (US) and metric (international) units.
|
|
"""
|
|
|
|
alias Aprsme.Convert
|
|
|
|
@doc """
|
|
Determines the unit system based on locale.
|
|
Returns :imperial for US, :metric for most other countries.
|
|
"""
|
|
@spec unit_system(String.t() | nil | any()) :: :imperial | :metric
|
|
def unit_system("en"), do: :imperial
|
|
def unit_system("es"), do: :metric
|
|
def unit_system("de"), do: :metric
|
|
def unit_system("fr"), do: :metric
|
|
def unit_system(locale) when is_binary(locale), do: :metric
|
|
def unit_system(nil), do: :imperial
|
|
def unit_system(_), do: :imperial
|
|
|
|
@doc """
|
|
Converts temperature from Fahrenheit to Celsius if needed.
|
|
Returns the temperature in the appropriate unit for the locale.
|
|
"""
|
|
@spec format_temperature(number() | any(), String.t()) :: {number() | any(), String.t()}
|
|
def format_temperature(temp, locale) when is_number(temp),
|
|
do: format_by_unit(temp, locale, &Convert.f_to_c/1, "°F", "°C")
|
|
|
|
def format_temperature(temp, _locale), do: {temp, "°F"}
|
|
|
|
@doc """
|
|
Converts wind speed from mph to km/h if needed.
|
|
Returns the wind speed in the appropriate unit for the locale.
|
|
"""
|
|
@spec format_wind_speed(number() | any(), String.t()) :: {number() | any(), String.t()}
|
|
def format_wind_speed(speed, locale) when is_number(speed),
|
|
do: format_by_unit(speed, locale, &Convert.mph_to_kph/1, "mph", "km/h")
|
|
|
|
def format_wind_speed(speed, _locale), do: {speed, "mph"}
|
|
|
|
@doc """
|
|
Converts rain from inches to mm if needed.
|
|
Returns the rain amount in the appropriate unit for the locale.
|
|
"""
|
|
@spec format_rain(number() | any(), String.t()) :: {number() | any(), String.t()}
|
|
def format_rain(rain, locale) when is_number(rain),
|
|
do: format_by_unit(rain, locale, &Convert.inches_to_mm/1, "in", "mm")
|
|
|
|
def format_rain(rain, _locale), do: {rain, "in"}
|
|
|
|
@doc """
|
|
Formats pressure (keeps hPa for all locales as it's standard).
|
|
"""
|
|
@spec format_pressure(number() | any(), any()) :: {number() | any(), String.t()}
|
|
def format_pressure(pressure, _locale), do: {pressure, "hPa"}
|
|
|
|
@doc """
|
|
Gets the appropriate unit labels for the locale.
|
|
"""
|
|
@spec unit_labels(String.t()) :: %{
|
|
temperature: String.t(),
|
|
wind_speed: String.t(),
|
|
rain: String.t(),
|
|
pressure: String.t()
|
|
}
|
|
def unit_labels(locale), do: do_unit_labels(unit_system(locale))
|
|
|
|
defp do_unit_labels(:imperial) do
|
|
%{
|
|
temperature: "°F",
|
|
wind_speed: "mph",
|
|
rain: "in",
|
|
pressure: "hPa"
|
|
}
|
|
end
|
|
|
|
defp do_unit_labels(:metric) do
|
|
%{
|
|
temperature: "°C",
|
|
wind_speed: "km/h",
|
|
rain: "mm",
|
|
pressure: "hPa"
|
|
}
|
|
end
|
|
|
|
defp format_by_unit(value, locale, converter, imperial_unit, metric_unit) do
|
|
case unit_system(locale) do
|
|
:imperial -> {value, imperial_unit}
|
|
:metric -> {converter.(value), metric_unit}
|
|
end
|
|
end
|
|
end
|