feat(rover): replace max-drive-time slider with max-distance in miles
This commit is contained in:
parent
9b81e776ca
commit
915cd1f5a0
5 changed files with 34 additions and 37 deletions
|
|
@ -7,14 +7,11 @@ interface RoverSliderHook extends ViewHook {
|
|||
inputHandler: () => void
|
||||
}
|
||||
|
||||
const AVG_SPEED_KMH = 65.0
|
||||
const KM_PER_MI = 1.609344
|
||||
|
||||
const formatters: Record<string, (v: number) => string> = {
|
||||
forecast: (v) => `+${v}h`,
|
||||
drive: (v) => {
|
||||
const hours = Math.round((v / 60) * 10) / 10
|
||||
return `${hours}h`
|
||||
}
|
||||
distance: (v) => `${v} mi`
|
||||
}
|
||||
|
||||
export const RoverSlider: Partial<RoverSliderHook> = {
|
||||
|
|
@ -29,8 +26,8 @@ export const RoverSlider: Partial<RoverSliderHook> = {
|
|||
const value = Number((this.el as HTMLInputElement).value)
|
||||
if (this.labelEl) this.labelEl.textContent = this.formatter(value)
|
||||
|
||||
if (this.format === "drive") {
|
||||
const km = (value * AVG_SPEED_KMH) / 60.0
|
||||
if (this.format === "distance") {
|
||||
const km = value * KM_PER_MI
|
||||
window.dispatchEvent(new CustomEvent("rover:drive-radius", { detail: { km } }))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ defmodule Microwaveprop.Rover.Compute do
|
|||
band_mhz: non_neg_integer(),
|
||||
valid_time: DateTime.t(),
|
||||
mode: atom(),
|
||||
max_drive_min: integer(),
|
||||
max_distance_km: float(),
|
||||
min_elev_gain: integer()
|
||||
}
|
||||
|
||||
|
|
@ -53,12 +53,12 @@ defmodule Microwaveprop.Rover.Compute do
|
|||
band_mhz: band_mhz,
|
||||
valid_time: valid_time,
|
||||
mode: mode,
|
||||
max_drive_min: max_drive_min,
|
||||
max_distance_km: max_distance_km,
|
||||
min_elev_gain: min_elev_gain
|
||||
} = args
|
||||
|
||||
selected_stations = Enum.filter(stations, & &1.selected)
|
||||
radius_km = max_drive_min * @avg_speed_kmh / 60.0
|
||||
radius_km = max_distance_km * 1.0
|
||||
bbox = bbox_around(home, radius_km)
|
||||
|
||||
raw_cells = scores_at.(band_mhz, valid_time, bbox)
|
||||
|
|
|
|||
|
|
@ -31,7 +31,8 @@ defmodule MicrowavepropWeb.RoverLive do
|
|||
@default_band 10_000
|
||||
@default_mode :ssb
|
||||
@default_forecast_hour 0
|
||||
@default_max_drive_min 120
|
||||
@default_max_distance_mi 80
|
||||
@km_per_mi 1.609344
|
||||
@avg_speed_kmh 65.0
|
||||
|
||||
# NTMS-area anonymous home: EM13 centroid.
|
||||
|
|
@ -51,8 +52,8 @@ defmodule MicrowavepropWeb.RoverLive do
|
|||
band: @default_band,
|
||||
mode: @default_mode,
|
||||
forecast_hour: @default_forecast_hour,
|
||||
max_drive_min: @default_max_drive_min,
|
||||
drive_radius_km: drive_radius_km(@default_max_drive_min),
|
||||
max_distance_mi: @default_max_distance_mi,
|
||||
drive_radius_km: drive_radius_km(@default_max_distance_mi),
|
||||
fixed_stations: fixed_stations,
|
||||
persisted?: persisted?,
|
||||
home: home,
|
||||
|
|
@ -163,7 +164,7 @@ defmodule MicrowavepropWeb.RoverLive do
|
|||
|
||||
defp home_label(lat, lon), do: Maidenhead.from_latlon(lat, lon, 10)
|
||||
|
||||
defp drive_radius_km(max_drive_min), do: max_drive_min * @avg_speed_kmh / 60.0
|
||||
defp drive_radius_km(max_distance_mi), do: max_distance_mi * @km_per_mi
|
||||
|
||||
# ── Events ────────────────────────────────────────────────────────────
|
||||
|
||||
|
|
@ -178,13 +179,13 @@ defmodule MicrowavepropWeb.RoverLive do
|
|||
{:noreply, assign(socket, forecast_hour: hour)}
|
||||
end
|
||||
|
||||
def handle_event("set_max_drive_time", %{"value" => v}, socket) do
|
||||
minutes = v |> parse_int(@default_max_drive_min) |> clamp(30, 240)
|
||||
radius_km = drive_radius_km(minutes)
|
||||
def handle_event("set_max_distance", %{"value" => v}, socket) do
|
||||
miles = v |> parse_int(@default_max_distance_mi) |> clamp(25, 250)
|
||||
radius_km = drive_radius_km(miles)
|
||||
|
||||
{:noreply,
|
||||
socket
|
||||
|> assign(max_drive_min: minutes, drive_radius_km: radius_km)
|
||||
|> assign(max_distance_mi: miles, drive_radius_km: radius_km)
|
||||
|> push_event("update_drive_radius", %{km: radius_km})}
|
||||
end
|
||||
|
||||
|
|
@ -666,7 +667,7 @@ defmodule MicrowavepropWeb.RoverLive do
|
|||
band_mhz: socket.assigns.band,
|
||||
valid_time: socket.assigns.current_valid_time || DateTime.utc_now(),
|
||||
mode: socket.assigns.mode,
|
||||
max_drive_min: socket.assigns.max_drive_min,
|
||||
max_distance_km: socket.assigns.drive_radius_km,
|
||||
min_elev_gain: 0
|
||||
}
|
||||
end
|
||||
|
|
@ -916,26 +917,25 @@ defmodule MicrowavepropWeb.RoverLive do
|
|||
</div>
|
||||
</.sidebar_section>
|
||||
|
||||
<.sidebar_section title="MAX DRIVE TIME">
|
||||
<.sidebar_section title="MAX DISTANCE">
|
||||
<input
|
||||
type="range"
|
||||
min="30"
|
||||
max="240"
|
||||
step="15"
|
||||
value={@max_drive_min}
|
||||
phx-change="set_max_drive_time"
|
||||
min="25"
|
||||
max="250"
|
||||
step="25"
|
||||
value={@max_distance_mi}
|
||||
phx-change="set_max_distance"
|
||||
phx-debounce="200"
|
||||
phx-hook="RoverSlider"
|
||||
phx-update="ignore"
|
||||
id="rover-drive-slider"
|
||||
data-label-id="rover-drive-label"
|
||||
data-format="drive"
|
||||
id="rover-distance-slider"
|
||||
data-label-id="rover-distance-label"
|
||||
data-format="distance"
|
||||
name="value"
|
||||
class="range range-xs range-primary"
|
||||
/>
|
||||
<div class="text-xs opacity-70 mt-1">
|
||||
<span id="rover-drive-label">{Float.round(@max_drive_min / 60, 1)}h</span>
|
||||
from {@home.label}
|
||||
<span id="rover-distance-label">{@max_distance_mi} mi</span> from {@home.label}
|
||||
</div>
|
||||
</.sidebar_section>
|
||||
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ defmodule Microwaveprop.Rover.ComputeTest do
|
|||
band_mhz: 10_000,
|
||||
valid_time: ~U[2026-04-25 12:00:00Z],
|
||||
mode: :ssb,
|
||||
max_drive_min: 60,
|
||||
max_distance_km: 65.0,
|
||||
min_elev_gain: 0
|
||||
}
|
||||
|
||||
|
|
@ -87,7 +87,7 @@ defmodule Microwaveprop.Rover.ComputeTest do
|
|||
band_mhz: 10_000,
|
||||
valid_time: ~U[2026-04-25 12:00:00Z],
|
||||
mode: :ssb,
|
||||
max_drive_min: 60,
|
||||
max_distance_km: 65.0,
|
||||
min_elev_gain: 200
|
||||
},
|
||||
scores_at: scores_at,
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ defmodule MicrowavepropWeb.RoverLiveTest do
|
|||
assert html =~ "FIXED STATIONS"
|
||||
assert html =~ "FORECAST HOUR"
|
||||
assert html =~ "BAND"
|
||||
assert html =~ "MAX DRIVE TIME"
|
||||
assert html =~ "MAX DISTANCE"
|
||||
refute html =~ ">MODE<"
|
||||
refute html =~ "MIN ELEV GAIN"
|
||||
end
|
||||
|
|
@ -63,14 +63,14 @@ defmodule MicrowavepropWeb.RoverLiveTest do
|
|||
refute_push_event(view, "rover_results", %{})
|
||||
end
|
||||
|
||||
test "set_max_drive_time updates the dashed circle radius", %{conn: conn} do
|
||||
test "set_max_distance updates the dashed circle radius", %{conn: conn} do
|
||||
{:ok, view, _html} = live(conn, ~p"/rover")
|
||||
|
||||
render_hook(view, "set_max_drive_time", %{"value" => "120"})
|
||||
render_hook(view, "set_max_distance", %{"value" => "100"})
|
||||
|
||||
# 120 min @ 65 km/h = 130 km
|
||||
# 100 mi = 160.93 km
|
||||
assert_push_event(view, "update_drive_radius", %{km: km})
|
||||
assert_in_delta km, 130.0, 0.1
|
||||
assert_in_delta km, 160.93, 0.1
|
||||
end
|
||||
|
||||
test "calculate triggers a rover_results push_event with cells + drive_radius_km", %{conn: conn} do
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue