Commit graph

692 commits

Author SHA1 Message Date
c6bf333c98 Add dialyxir for static analysis
PLT stored in priv/plts/ (gitignored). Run with `mix dialyzer`.
2026-04-11 17:43:18 -05:00
FluxCD
d137975739 chore: update prop image to git.mcintire.me/graham/prop:main-1775947163-2ecd803 [skip ci] 2026-04-11 22:40:08 +00:00
5bcf579009 Add ADIF file upload for contact submission
Parse ADIF tagged-data format with fuzzy frequency-to-band matching
(nearest microwave band for any freq >= 900 MHz). Supports STATION_CALLSIGN,
OPERATOR, CALL, GRIDSQUARE, MY_GRIDSQUARE, FREQ, BAND, QSO_DATE, TIME_ON.
Same dedup and preview/commit flow as CSV upload.

Also fix select dropdown text alignment in daisyUI.
2026-04-11 17:39:05 -05:00
FluxCD
1111e64bdd chore: update prop image to git.mcintire.me/graham/prop:main-1775946667-67df5fc [skip ci] 2026-04-11 22:32:08 +00:00
25c703401b Link to existing contact on duplicate submission
Return the conflicting contact from create_contact so the UI can redirect
to it with a flash message instead of just showing a form error.
2026-04-11 17:30:46 -05:00
FluxCD
231f1d9a14 chore: update prop image to git.mcintire.me/graham/prop:main-1775946446-9c64d75 [skip ci] 2026-04-11 22:28:06 +00:00
cdb59be6d7 Deduplicate single contact submissions same as CSV import
Check for existing contacts with the same station pair (order-independent),
band, and grids within a 1-hour window before inserting.
2026-04-11 17:27:03 -05:00
FluxCD
3334db5a08 chore: update prop image to git.mcintire.me/graham/prop:main-1775946134-cd14a06 [skip ci] 2026-04-11 22:23:05 +00:00
4ca8c5d3bc Add Q65 contact mode 2026-04-11 17:21:45 -05:00
FluxCD
a37b4cb929 chore: update prop image to git.mcintire.me/graham/prop:main-1775945466-55b12bc [skip ci] 2026-04-11 22:14:01 +00:00
58e4f55ba8 Curved earth surface in elevation profile with ducts following curvature 2026-04-11 17:10:38 -05:00
FluxCD
d99b7a6ea2 chore: update prop image to git.mcintire.me/graham/prop:main-1775944792-4a8d1a1 [skip ci] 2026-04-11 22:02:00 +00:00
1f368f9b61 Convert all JavaScript to TypeScript with type annotations
- Rename all .js files to .ts in assets/js/
- Add interfaces for hook state, data structures, and event payloads
- Add type annotations to function parameters and return types
- Create type declarations for vendor deps (Leaflet, Chart.js, Phoenix, topbar)
- Update tsconfig.json for strict TypeScript checking
- Update esbuild entry point to app.ts
2026-04-11 16:59:28 -05:00
FluxCD
9b4d9d08dd chore: update prop image to git.mcintire.me/graham/prop:main-1775944179-5ad3941 [skip ci] 2026-04-11 21:50:54 +00:00
3d550f24c6 Defer map init and sendBounds to requestAnimationFrame in all map hooks 2026-04-11 16:49:17 -05:00
FluxCD
bfbe077257 chore: update prop image to git.mcintire.me/graham/prop:main-1775944065-d52172c [skip ci] 2026-04-11 21:47:53 +00:00
08ffc7e028 Admin direct edit on contact show page, suggest edit for non-admins 2026-04-11 16:46:46 -05:00
FluxCD
e651c1e481 chore: update prop image to git.mcintire.me/graham/prop:main-1775943275-ae384af [skip ci] 2026-04-11 16:46:46 -05:00
18e920fe54 Fix backfill page missing partitioned table stats, fix contacts map init
Backfill page now sums child partition stats for partitioned tables
like hrrr_profiles (relkind 'p') which were excluded by the relkind
'r' filter. Contacts map defers Leaflet init to requestAnimationFrame
so the flex container has dimensions before map initialization.
2026-04-11 16:34:15 -05:00
FluxCD
4e37b0eeca chore: update prop image to git.mcintire.me/graham/prop:main-1775943041-23a4f34 [skip ci] 2026-04-11 16:34:15 -05:00
e74adf0036 Auto-download missing SRTM tiles, treat water areas as 0m elevation
SRTM profiles no longer abort on missing tiles — water/ocean areas
return 0m elevation instead of failing the entire profile and falling
back to the rate-limited API. Elevation client and viewshed now pass
download: true to auto-fetch missing tiles from S3. NFS mount changed
to writable so downloaded tiles persist across pods.
2026-04-11 16:30:25 -05:00
FluxCD
80d1169f71 chore: update prop image to git.mcintire.me/graham/prop:main-1775942481-e31864b [skip ci] 2026-04-11 16:30:25 -05:00
77656ba023 Move contacts map controls to sidebar matching main map layout
Replace the JS-built Leaflet control panel with a server-side
sidebar (desktop) and mobile floating controls. Band checkboxes,
callsign filter, and nav links now match the main propagation map
layout. Filter state managed by LiveView, pushed to JS via events.
2026-04-11 16:21:04 -05:00
FluxCD
b468232b0e chore: update prop image to git.mcintire.me/graham/prop:main-1775942121-5f93a72 [skip ci] 2026-04-11 16:21:04 -05:00
a66d3094ca Add contact edit approval system with admin review queue
Registered users can suggest edits to any contact's core fields
(callsigns, grids, band, mode, timestamp). Edits enter an admin
approval queue with field-by-field diff view. On approve, changes
are applied and enrichment re-enqueued if grids/band changed.
Users receive email notification on approve or reject.

Also updates dependabot.yml for mix ecosystem.
2026-04-11 16:15:49 -05:00
FluxCD
0fc4f37e86 chore: update prop image to git.mcintire.me/graham/prop:main-1775939246-08d4060 [skip ci] 2026-04-11 16:15:49 -05:00
Graham McIntire
80b2a250f1 Create dependabot.yml 2026-04-11 16:03:23 -05:00
2aa76727f9 Add callsign filter and band counts to contacts map
- Callsign input filters contacts where either station matches
  (case-insensitive substring match, debounced 300ms)
- Band checkboxes now show per-band count of visible contacts
- All/None buttons for quick band selection
- Header count updates dynamically with filters
- Complete rewrite: rebuilds map on any filter change instead of
  toggling individual layers (simpler, handles cross-filter correctly)
2026-04-11 15:26:57 -05:00
FluxCD
6d30714521 chore: update prop image to git.mcintire.me/graham/prop:main-1775939032-1820bc0 [skip ci] 2026-04-11 20:25:38 +00:00
5a1ac63f56 Force dark theme on map sidebar and mobile controls
The sidebar and mobile floating controls overlay the dark map tiles
but inherited light theme colors, making dropdowns, inputs, and
menus invisible (white-on-white). Adding data-theme="dark" forces
all daisyUI components within these containers to use dark variants
regardless of the page's theme setting.
2026-04-11 15:23:26 -05:00
FluxCD
0b1e411110 chore: update prop image to git.mcintire.me/graham/prop:main-1775938787-827019c [skip ci] 2026-04-11 20:20:38 +00:00
e8ae407be9 Add rain scatter prediction to map detail panel
When clicking a grid point, fetches the latest NEXRAD composite
reflectivity and identifies rain cells within 300 km that could
enable rain scatter contacts. Shows:
- Scatter classification (excellent/good/marginal/none)
- Top 3 cells with dBZ, distance, bearing, and relative signal
- Colored circle markers on the map at rain cell locations
- Markers sized by reflectivity, colored by intensity

Uses simplified bistatic radar equation accounting for reflectivity,
frequency-dependent scattering (Rayleigh/Mie), and R^4 path loss.
NEXRAD cells sampled every ~5 km within bounding box for efficiency.
2026-04-11 15:19:19 -05:00
FluxCD
2e9d6a7c7f chore: update prop image to git.mcintire.me/graham/prop:main-1775937341-75cf493 [skip ci] 2026-04-11 19:56:29 +00:00
9fea93f59c Show earth curvature in contact elevation profile
Terrain elevations now include the earth bulge correction, so the
profile visually humps up in the middle relative to the straight
LOS beam — showing how the curved earth rises into the signal path.
Uses actual k-factor from HRRR refractivity when available, otherwise
standard 4/3. For a 300 km path at k=4/3, the midpoint bulge is
~2,650 m (8,700 ft).
2026-04-11 14:55:21 -05:00
ab8773acd0 Add per-band filter checkboxes with All/None to contacts map 2026-04-11 14:55:21 -05:00
ff1b2d0cbe Add Maidenhead grid overlay toggle to contact map 2026-04-11 14:55:21 -05:00
13782ea7d4 Increase max zoom on main map from 10 to 13 2026-04-11 14:55:21 -05:00
8a39ae4411 Improve light mode contrast for score colors and map controls
- Darken tier colors for page elements (path, beacon, contact pages):
  EXCELLENT #00ffa3→#059669, GOOD #7dffd4→#0d9488,
  MARGINAL #ffe566→#ca8a04, POOR #ff9044→#ea580c,
  NEGLIGIBLE #ff4f4f→#dc2626
- Make mobile map controls fully opaque (bg-base-100 not /90)
- Map popups (dark background) keep original vibrant colors
2026-04-11 14:55:21 -05:00
FluxCD
a0c59bd759 chore: update prop image to git.mcintire.me/graham/prop:main-1775934822-6f9477c [skip ci] 2026-04-11 19:14:20 +00:00
bcdbf0b53a Show per-duct layer heights in map detail panel
When clicking a grid point with ducting, the panel now shows each
duct layer with base-top height in feet, thickness in meters, and
minimum trapped frequency. Data flows from Duct.analyze through
the scoring factors as a ducts array.
2026-04-11 14:13:24 -05:00
FluxCD
da0d0fcbdb chore: update prop image to git.mcintire.me/graham/prop:main-1775934001-2db220b [skip ci] 2026-04-11 19:01:18 +00:00
03bd77c6d4 Update CLAUDE.md scoring table: 10 factors with recalibrated weights 2026-04-11 13:59:42 -05:00
FluxCD
bda8928309 chore: update prop image to git.mcintire.me/graham/prop:main-1775933573-516a430 [skip ci] 2026-04-11 18:54:15 +00:00
bac0bc3a98 Update about page: ten factors, mention PWAT and native duct detection 2026-04-11 13:52:26 -05:00
FluxCD
0448ff47cc chore: update prop image to git.mcintire.me/graham/prop:main-1775933390-856c5ff [skip ci] 2026-04-11 18:51:14 +00:00
58a99de3cd Fix map detail panel: update weights, add PWAT, show duct info
- Update all 9 hardcoded weights to match recalibrated values
- Add missing PWAT factor (11.3% weight) to FACTOR_META and FACTOR_ORDER
- Reorder factors by weight (highest first)
- Fix pressure explanation (low pressure is better, not rising)
- Add PWAT factor explanation (beneficial vs harmful by band)
- Show duct info panel when native data detects ducting layers
  (count, thickness, minimum trapped frequency)
2026-04-11 13:49:24 -05:00
FluxCD
a1d787b26f chore: update prop image to git.mcintire.me/graham/prop:main-1775933080-2e4602e [skip ci] 2026-04-11 18:46:13 +00:00
880988b591 Update algo.md weights and data flow for native duct integration
- Replace stale April 2026 manual weights with recalibrated values
- Document native hybrid-sigma data in data flow section
- Note refractivity factor now uses native 10-50m resolution
- Add hourly grid integration section to Part 12
- Expose duct_info (count, freq, thickness) in scoring factors for UI
2026-04-11 13:44:13 -05:00
FluxCD
fe7597fb26 chore: update prop image to git.mcintire.me/graham/prop:main-1775932266-bd4a15e [skip ci] 2026-04-11 18:32:10 +00:00
57578dff4d Add native HRRR duct detection to hourly propagation scoring
The PropagationGridWorker now fetches native hybrid-sigma levels
(TMP, SPFH, HGT, PRES × 50 levels) alongside the standard surface
and pressure products. Native data provides 10-50m vertical spacing
vs 250m from pressure levels, detecting thin surface ducts invisible
to the standard product.

Key design: cell-by-cell reducer in Wgrib2.extract_grid_from_file_mapped
processes each of the 95k CONUS cells through a duct analysis function
inline, keeping only scalar metrics per cell. Peak memory ~86 MB
instead of ~1.8 GB for the full grid map.

Per-cell output: native_min_gradient, best_duct_freq_ghz,
max_duct_thickness_m, duct_count. The scorer prefers the native
gradient over the pressure-level gradient when available.

Native fetch is optional — if it fails, scoring continues with
pressure-level data only.
2026-04-11 13:30:48 -05:00