Skip to content

Add a "Best DX" card to the logbook Stats tab (furthest station worked)#673

Merged
patrickrb merged 1 commit into
devfrom
optio/task-8b416c64-a419-42e4-aecf-c25bc19bdd24
Jul 24, 2026
Merged

Add a "Best DX" card to the logbook Stats tab (furthest station worked)#673
patrickrb merged 1 commit into
devfrom
optio/task-8b416c64-a419-42e4-aecf-c25bc19bdd24

Conversation

@patrickrb

Copy link
Copy Markdown
Owner

What & why

Adds a Best DX highlight card to Logbook → Stats, showing the furthest station the operator has worked — callsign, distance (in their preferred mi/km), and grid — measured great-circle from their configured Maidenhead grid.

Seeing "what's the furthest I've ever worked?" is one of the first things an FT8/DX operator wants from a logbook, and it's a natural brag stat next to Total QSOs / DXCC / Zones. Every logged QSO already stores a grid, so this surfaces information the app already has — no new data, no schema change, no extra DB query (it reduces over the records already loaded for the Stats tab).

How it looks

The card sits right below the four big stat cards (Total QSOs / DXCC / CQ / ITU), before the band distribution donut:

BEST DX
┌───────────────────────────────────────┐
│  VK3ABC                     16,842 km  │
│  QF22                                  │
└───────────────────────────────────────┘

It only appears once there's something measurable — i.e. the operator's own grid is configured and at least one logged QSO has a parseable grid. No grid set → the section is hidden (no empty header).

Implementation

  • computeBestDx(records, distanceKm) — a pure, top-level internal reducer that takes an injected grid→distance function and returns the furthest BestDx(callsign, grid, distanceKm). It skips records with a blank callsign/grid, an unparseable grid, or a non-positive/NaN distance (the last mirrors MaidenheadGrid's 0-km result for two stations sharing a grid — a distance floor, never a "best DX").
  • The Composable BestDxCard is a thin wrapper; the screen passes a MaidenheadGrid.getDist(myGrid, …)-backed lambda and renders the distance with MaidenheadGrid.formatDist (unit-aware).
  • Follows the existing extract-pure-helper pattern already used for gridSquaresWorked / workedGridFields, so the decision logic is unit-testable without Robolectric.

Tests

New BestDxTest (7 plain-JVM cases): furthest wins, empty log → null, unparseable/blank grids skipped, blank callsign skipped, nothing-measurable → null, 0 km and NaN distances skipped, callsign/grid trimmed.

Verification

  • ./gradlew :app:testDebugUnitTest --tests 'radio.ks3ckc.ft8af.ui.logbook.*' — green (BestDxTest 7/7, no regressions in the logbook suite).
  • ./gradlew :app:assembleDebugBUILD SUCCESSFUL (full native + APK).

Scope / compatibility

Display-only addition to the Stats tab. No change to decoding, transmit, CAT, or the FT8 protocol path. One new string (log_section_best_dx); other locales fall back to the default, consistent with recent stats additions.

🤖 Generated with Claude Code

Show operators the furthest station they've worked, measured
great-circle from their configured Maidenhead grid, as a highlight card
on the Logbook > Stats tab (callsign + distance in the user's preferred
unit + grid). Every logged QSO already carries a grid, so this needs no
new data — just a reduction over the log.

The selection logic is a pure, JVM-only helper (computeBestDx) that takes
an injected grid->distance function, so it's unit-tested without
Robolectric. It skips records with a blank callsign/grid, an unparseable
grid, or a non-positive/NaN distance (the last mirrors MaidenheadGrid's
0-km result for two stations sharing a grid — a floor, never a best DX),
and the card only renders once there's a measurable contact (operator
grid set + at least one parseable logged grid).

Follows the existing extract-pure-helper pattern (gridSquaresWorked /
workedGridFields) and reuses MaidenheadGrid.getDist/formatDist for
unit-aware display.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@codecov

codecov Bot commented Jul 24, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 16.66667% with 40 lines in your changes missing coverage. Please review.
✅ Project coverage is 36.76%. Comparing base (e662cd7) to head (fd0b64d).

Files with missing lines Patch % Lines
...lin/radio/ks3ckc/ft8af/ui/logbook/LogbookScreen.kt 16.66% 38 Missing and 2 partials ⚠️
Additional details and impacted files

Impacted file tree graph

@@             Coverage Diff              @@
##                dev     #673      +/-   ##
============================================
+ Coverage     36.73%   36.76%   +0.03%     
- Complexity      197      211      +14     
============================================
  Files           216      219       +3     
  Lines         26882    27102     +220     
  Branches       3284     3332      +48     
============================================
+ Hits           9876     9965      +89     
- Misses        16781    16901     +120     
- Partials        225      236      +11     
Flag Coverage Δ
android 15.39% <16.66%> (+0.35%) ⬆️
native 9.93% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
...lin/radio/ks3ckc/ft8af/ui/logbook/LogbookScreen.kt 7.03% <16.66%> (+0.43%) ⬆️

... and 13 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@patrickrb
patrickrb merged commit d5686e7 into dev Jul 24, 2026
17 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant