Add Hunt options: target priority + smart filters (pileup avoidance, min-SNR floor) - #699
Conversation
The HUNT button gets the same notch/long-press affordance as the CQ button, opening a Hunt options sheet: - Hunt priority (single-select): Latest (historical behavior, default), Strongest, Weakest, Farthest, POTA/SOTA activators first (unhunted parks rank highest), New DXCC first, New grid first. - Smart filters: Avoid pileups (prefer CQs no one else is answering this cycle; soft preference) and a Minimum-signal floor (Off/-10/-15/-20 dB; hard filter so Hunt never starts a QSO that's unlikely to complete). Engine: the hunt scan in FT8TransmitSignal previously answered the first qualifying CQ (most recent decode). It now collects all qualifying CQs and ranks them via HuntTargetSelector, a pure Kotlin selector driven by three new persisted settings (huntPriority, huntAvoidPileups, huntMinSnr). LATEST with no filters short-circuits to the old behavior with no extra per-cycle work. All existing eligibility filters (worked-before, POTA-only, directional-CQ respect, exclusions) are unchanged. UI: a non-default priority shows a short tag under the HUNT label (STRONG/WEAK/DX/POTA/DXCC/GRID), mirroring the CQ button's FREE/FD subtitle. Options apply immediately, mid-hunt. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## dev #699 +/- ##
============================================
+ Coverage 29.36% 29.72% +0.35%
- Complexity 197 222 +25
============================================
Files 179 192 +13
Lines 24068 25543 +1475
Branches 3263 3545 +282
============================================
+ Hits 7067 7592 +525
- Misses 16780 17698 +918
- Partials 221 253 +32
Flags with carried forward coverage won't be shown. Click here to find out more.
🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Pull request overview
Adds a new “Hunt options” UX and selection engine so the HUNT feature can rank multiple eligible CQ callers per decode cycle using configurable priority modes plus smart filters (pileup avoidance and a minimum-SNR floor). This extends existing CQ-button affordances (notch/long-press/options sheet) to HUNT and persists the new settings via the existing GeneralVariables + config DB pattern.
Changes:
- Introduces
HuntTargetSelectorranking logic (with a Java-callable bridge) and updates the transmit engine to collect all eligible CQs and delegate selection. - Adds a new Compose
HuntOptionsSheet, a HUNT subtitle tag on the TX strip, and new localized strings for the sheet. - Persists three new hunt settings (
huntPriority,huntAvoidPileups,huntMinSnr) and adds unit tests for both the selector and UI helper logic.
Reviewed changes
Copilot reviewed 10 out of 10 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| ft8af/app/src/test/kotlin/radio/ks3ckc/ft8af/ui/components/HuntOptionsLogicTest.kt | Unit tests for pure helpers used by the Hunt options UI (subtitle tag + min-SNR chip helpers). |
| ft8af/app/src/test/kotlin/radio/ks3ckc/ft8af/hunt/HuntTargetSelectorTest.kt | Unit tests for candidate selection logic: config parsing, SNR floor, pileup preference, and all priority modes. |
| ft8af/app/src/main/res/values/strings_compose.xml | Adds new strings for the Hunt options notch/description and the sheet UI content. |
| ft8af/app/src/main/kotlin/radio/ks3ckc/ft8af/ui/components/TxStrip.kt | Extends the HUNT stacked button with optional notch/long-press + subtitle support to open options. |
| ft8af/app/src/main/kotlin/radio/ks3ckc/ft8af/ui/components/HuntOptionsSheet.kt | New Compose bottom sheet for Hunt options (priority + smart filters) with extracted pure helpers. |
| ft8af/app/src/main/kotlin/radio/ks3ckc/ft8af/hunt/HuntTargetSelector.kt | New ranking engine + config parsing and Java bridge to pick which eligible CQ to answer. |
| ft8af/app/src/main/kotlin/radio/ks3ckc/ft8af/FT8AFApp.kt | Wires the Hunt options sheet into the app UI, updates persisted settings, and shows subtitle tags. |
| ft8af/app/src/main/java/com/k1af/ft8af/GeneralVariables.java | Adds new volatile hunt config statics and a min-SNR sentinel constant. |
| ft8af/app/src/main/java/com/k1af/ft8af/ft8transmit/FT8TransmitSignal.java | Collects all qualifying CQs and calls HuntTargetSelector.pick(...) to choose among them; logs options context. |
| ft8af/app/src/main/java/com/k1af/ft8af/database/DatabaseOpr.java | Loads the three new hunt config keys from persisted config into GeneralVariables. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
…stability Per Copilot review on #699: append an explicit HuntCandidate.index tie-breaker to every priority comparator and pick with minWithOrNull, so the freshest-decode tie-break is a contract of the comparator (index is unique => total order) rather than an artifact of sortedWith stability, and no ranked copy of the pool is allocated per decode cycle. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
What
The HUNT button gets the same notch / long-press affordance as the CQ button, opening a new Hunt options sheet:
Hunt priority (which CQ Hunt answers first when several decode in one cycle)
Smart filters (features other FT8 apps don't have)
A non-default priority shows a short tag under the HUNT label (STRONG/WEAK/DX/POTA/DXCC/GRID), mirroring the CQ button's FREE/FD subtitle. Options apply immediately mid-hunt and persist across launches.
How
HuntTargetSelector.kt(new): pure ranking logic (selectHuntCandidate,passesSnrFloor,countRepliesTo,huntPriorityFromConfig) plus a@JvmStatic pick()bridge for the Java engine. Distance/park/pileup lookups only run when the active options need them;LATESTwith no filters short-circuits to the old behavior with zero extra per-cycle work.FT8TransmitSignal.checkCQMeOrFollowCQMessage: the hunt scan now collects all qualifying CQs (same eligibility filters as before: worked-before skip, exclusions, POTA-only filter, directional-CQ respect) and lets the selector choose, instead of taking the first match. The debug log line now includes the active priority and candidate count.huntPriority,huntAvoidPileups,huntMinSnr) following theGeneralVariablesstatic +DatabaseOpr.writeConfig/parse pattern; statics arevolatile(UI thread writes, transmit thread reads), matchinghuntPotaOnly.TxStrip.StackedActionButton: gains an optional options notch + long-press + subtitle, mirroringPrimaryActionButton; the TX-slot button is unchanged.HuntOptionsSheet.kt(new): follows theCqOptionsSheetlayout/chip conventions.Tests
HuntTargetSelectorTest— 24 cases: config parsing fallback, SNR-floor semantics (incl. unknown SNR), every priority mode incl. unknown-SNR/-distance handling, freshest-decode tie-breaks, pileup soft-fallback, reply counting.HuntOptionsLogicTest— subtitle tags (exhaustive over the enum, length-bounded), min-SNR chip data/labels.testDebugUnitTestsuite green;assembleDebugbuilds.🤖 Generated with Claude Code