mirror of
https://github.com/praktimarc/kst4contest.git
synced 2026-08-26 03:57:16 +02:00
chore: add Codex project context and agent guidance
This commit is contained in:
@@ -0,0 +1,102 @@
|
||||
# Architecture context
|
||||
|
||||
## Current package shape
|
||||
|
||||
The repository currently contains major packages under `src/main/java/kst4contest/` including:
|
||||
|
||||
- `controller`
|
||||
- `locatorUtils`
|
||||
- `logic`
|
||||
- `model`
|
||||
- `service`
|
||||
- `test`
|
||||
- `utils`
|
||||
- `view`
|
||||
|
||||
Do not treat package names alone as proof of clean MVC boundaries. Inspect actual dependencies.
|
||||
|
||||
## Preferred message/member data flow
|
||||
|
||||
The established target architecture for active chat members is:
|
||||
|
||||
```text
|
||||
ON4KST / network
|
||||
|
|
||||
v
|
||||
MessageBusManagementThread
|
||||
|
|
||||
v
|
||||
ChatController
|
||||
|
|
||||
v
|
||||
thread-safe active-member domain state
|
||||
(ConcurrentMap; identity includes callsign + category)
|
||||
|
|
||||
v
|
||||
JavaFX ObservableList UI mirror
|
||||
|
|
||||
v
|
||||
FilteredList / SortedList / TableView / selection
|
||||
```
|
||||
|
||||
Key rule:
|
||||
|
||||
`ObservableList` is a JavaFX UI projection, not the canonical store for worker-thread logic.
|
||||
|
||||
`MessageBusManagementThread` must not directly read or modify the UI list.
|
||||
|
||||
## JavaFX boundary
|
||||
|
||||
UI-visible mutations belong on the JavaFX Application Thread.
|
||||
|
||||
Prefer controller-owned helpers such as an existing `runOnFxThread` abstraction when available; otherwise use `Platform.runLater` consistently.
|
||||
|
||||
Do not move business/data access into the FX thread merely to silence a threading problem.
|
||||
|
||||
## Parser/service separation
|
||||
|
||||
For protocol receivers, the preferred direction is:
|
||||
|
||||
```text
|
||||
Receiver (I/O only)
|
||||
-> Parser (wire data -> DTO)
|
||||
-> Service (domain/persistence logic)
|
||||
-> Controller (UI coordination)
|
||||
-> Observable UI model
|
||||
-> View
|
||||
```
|
||||
|
||||
A previous concrete example for UCXLog was:
|
||||
|
||||
```text
|
||||
UcxUdpReceiver
|
||||
-> UcxPacketParser
|
||||
-> DTO
|
||||
-> UcxLogService
|
||||
-> ChatController
|
||||
-> UI projection
|
||||
```
|
||||
|
||||
This is architectural guidance, not permission for a broad refactor. Apply only when it is in scope and approved.
|
||||
|
||||
## DTO preference
|
||||
|
||||
Prefer explicit DTO classes over records when introducing protocol/transport data structures in this project, unless the approved concept intentionally changes that convention.
|
||||
|
||||
## Null safety
|
||||
|
||||
Chat members can be incomplete, especially:
|
||||
|
||||
- fallback members;
|
||||
- historic message senders;
|
||||
- server-derived partial members.
|
||||
|
||||
Values such as QRB and QTF can be absent.
|
||||
|
||||
Rules:
|
||||
|
||||
- absence stays absence;
|
||||
- do not map `null` to numeric zero;
|
||||
- UI must render unavailable state safely;
|
||||
- sorting/filtering/calculation code must tolerate missing values;
|
||||
- unexpected missing values must not terminate worker or UI threads.
|
||||
@@ -0,0 +1,42 @@
|
||||
# Automated messaging, beacons and skeds
|
||||
|
||||
## General
|
||||
|
||||
Automated replies/beacons must be conservative because they interact with the live ON4KST service.
|
||||
|
||||
## Established safety behaviour
|
||||
|
||||
Historical confirmed rules include:
|
||||
|
||||
- beacon/autoanswer scheduling shares controlled timing rather than spawning uncontrolled independent timers;
|
||||
- minimum interval has been tightened to avoid spam;
|
||||
- automated text length is bounded;
|
||||
- invalid or incomplete replies are rejected before transmission;
|
||||
- a cooldown is not consumed unless a complete valid reply enters the TX queue;
|
||||
- QRG/frequency requests take precedence where the current implementation defines that;
|
||||
- automated-message markers are ignored to prevent response loops.
|
||||
|
||||
Recent logic used a two-minute cooldown keyed by complete callsign plus chat category and ignored the project's own automated-message marker.
|
||||
|
||||
Treat exact marker strings and timing constants as current-code facts to verify, not values to recreate from memory.
|
||||
|
||||
## Monitoring
|
||||
|
||||
Station monitoring is intentionally base-call-wide:
|
||||
|
||||
Entering a variant such as:
|
||||
|
||||
```text
|
||||
DN9APW-2
|
||||
DN9APW-70
|
||||
```
|
||||
|
||||
monitors:
|
||||
|
||||
```text
|
||||
DN9APW
|
||||
```
|
||||
|
||||
This reduces manual configuration for sked monitoring.
|
||||
|
||||
Keep this separate from chat-member identity, which may require full suffix + category.
|
||||
@@ -0,0 +1,87 @@
|
||||
# Domain, callsigns and bands
|
||||
|
||||
## Chat-member identity
|
||||
|
||||
Full callsign variants can be distinct chat identities.
|
||||
|
||||
Examples:
|
||||
|
||||
```text
|
||||
DN9APW
|
||||
DN9APW-2
|
||||
DN9APW-70
|
||||
```
|
||||
|
||||
Do not globally strip suffixes when identifying chat members.
|
||||
|
||||
Category is also part of identity. A practical key is conceptually equivalent to:
|
||||
|
||||
```text
|
||||
FULL_CALLSIGN|CATEGORY
|
||||
```
|
||||
|
||||
Do not allow messages from one category to attach to a same-looking member in another category.
|
||||
|
||||
## Base-call operations
|
||||
|
||||
Some features intentionally operate on the base callsign.
|
||||
|
||||
Confirmed examples:
|
||||
|
||||
### Worked state
|
||||
|
||||
Worked status is shared across suffix variants of the same base call.
|
||||
|
||||
If the base station has been worked on the relevant basis, variants such as `CALL-2`, `CALL-70`, `CALL-144`, `CALL-432` should not become independent worked identities merely because of the suffix.
|
||||
|
||||
### Monitoring
|
||||
|
||||
Monitoring a station entered as `DN9APW-2` or `DN9APW-70` should monitor the base call `DN9APW`.
|
||||
|
||||
This is intentional: a user monitoring another station's skeds should not have to create one monitor entry per SSID.
|
||||
|
||||
Do not extend base-call matching to unrelated features without approval.
|
||||
|
||||
## Suffix semantics
|
||||
|
||||
Do not assume a suffix always means a band or category.
|
||||
|
||||
Historical examples have shown the same base calls with different suffix conventions in different chat categories.
|
||||
|
||||
Therefore:
|
||||
|
||||
- preserve exact full-call identity where needed;
|
||||
- normalize only for explicitly approved base-call features;
|
||||
- never infer missing band/category semantics from the suffix alone.
|
||||
|
||||
## Categories
|
||||
|
||||
KST4Contest's central VHF/UHF usage focuses on ON4KST categories 2 and 3.
|
||||
|
||||
However, other categories can occur.
|
||||
|
||||
Rules:
|
||||
|
||||
- unsupported/uninteresting categories must be ignored or handled safely;
|
||||
- they must not produce index, switch or null errors;
|
||||
- do not let their values contaminate category-2/category-3 band logic.
|
||||
|
||||
## Band availability
|
||||
|
||||
Band activity can be derived from several signals including name/text parsing and explicit/manual information.
|
||||
|
||||
Confirmed invariant:
|
||||
|
||||
`NOT-QRV` overrides positive availability indications.
|
||||
|
||||
Known-active-band and `B+` handling should use one consistent interpretation across the program.
|
||||
|
||||
Do not implement separate slightly different parsers in multiple UI/features if a shared existing mechanism is available.
|
||||
|
||||
## Current QRG
|
||||
|
||||
Features that depend on propagation/band/frequency should use the current relevant QRG or the approved band calculation.
|
||||
|
||||
Never silently reintroduce a universal hardcoded 144 MHz fallback.
|
||||
|
||||
When a frequency is ambiguous and no approved fallback exists, ask rather than guessing.
|
||||
@@ -0,0 +1,115 @@
|
||||
# Known edge cases and regression patterns
|
||||
|
||||
This file is a regression-awareness list. Reproduce/inspect current code before deciding a historical bug still exists.
|
||||
|
||||
## Incomplete ChatMember
|
||||
|
||||
Known failure pattern:
|
||||
|
||||
```text
|
||||
Cannot invoke "java.lang.Double.intValue()" because
|
||||
ChatMember.getQrb() is null
|
||||
```
|
||||
|
||||
Lesson:
|
||||
|
||||
- QRB can be absent;
|
||||
- UI/calculation code must not blindly unbox/convert;
|
||||
- unavailable is not zero.
|
||||
|
||||
Apply the same reasoning to QTF and other server/fallback-derived fields.
|
||||
|
||||
## Callsign suffix collisions
|
||||
|
||||
A historical issue caused messages/identity problems between:
|
||||
|
||||
```text
|
||||
DN9APW
|
||||
DN9APW-2
|
||||
```
|
||||
|
||||
The corrective model is not "strip all suffixes".
|
||||
|
||||
Instead:
|
||||
|
||||
- keep full-call chat identities distinct;
|
||||
- include category;
|
||||
- use base call only for explicitly base-call-wide features such as worked state/monitoring.
|
||||
|
||||
## Unsupported chat categories
|
||||
|
||||
The ON4KST ecosystem can expose categories outside the two central ones.
|
||||
|
||||
A parser/switch/filter must not throw because the category is irrelevant to KST4Contest.
|
||||
|
||||
Safe ignore/fallback beats fake band assignment.
|
||||
|
||||
## AirScout higher-band queries
|
||||
|
||||
A historical observation showed aircraft visible in AirScout while API results for a 432 MHz case were empty.
|
||||
|
||||
Potential causes included frequency-string formatting.
|
||||
|
||||
Lesson:
|
||||
|
||||
- verify the exact upstream contract;
|
||||
- compare request produced by KST4Contest with a known-working request;
|
||||
- do not "fix" by guessing a string format or falling back to an unrelated band.
|
||||
|
||||
## Second airplane-scatter result / missing aircraft
|
||||
|
||||
A known UI failure involved missing/partial airplane-scatter data and a `TextInputControl` range error (`start must be <= end`).
|
||||
|
||||
Lesson:
|
||||
|
||||
- empty/partial AP results must be validated before text-range highlighting/selection;
|
||||
- second-result paths need the same null/range checks as primary results.
|
||||
|
||||
## Historic/unknown user message
|
||||
|
||||
A user/message record can refer to a callsign not present in the current member list.
|
||||
|
||||
Do not require current login membership to render or classify historic messages.
|
||||
|
||||
## UM3-style handling
|
||||
|
||||
Historical message handling included cases that should be ignored safely if the user is not in the chat/member state.
|
||||
|
||||
Lesson:
|
||||
|
||||
- external message types must tolerate missing member references.
|
||||
|
||||
## CR/LF and disconnect suspicion
|
||||
|
||||
Do not treat line endings as harmless text formatting in socket code.
|
||||
|
||||
When diagnosing a disconnect:
|
||||
|
||||
- inspect transmitted bytes;
|
||||
- inspect server response/EOF;
|
||||
- compare Windows versions only after proving the application sends different bytes;
|
||||
- avoid duplicated LF/CRLF terminators.
|
||||
|
||||
## Filter reset
|
||||
|
||||
A reset button that clears control values but leaves predicates active is not a valid reset.
|
||||
|
||||
Verify final predicate composition, not only UI state.
|
||||
|
||||
## Map render flicker
|
||||
|
||||
Leaflet/WebView render fragmentation under Java 21 was mitigated by:
|
||||
|
||||
```text
|
||||
window.L_DISABLE_3D = true
|
||||
```
|
||||
|
||||
before Leaflet load.
|
||||
|
||||
Do not remove as "obsolete CSS cleanup" without a visual regression check.
|
||||
|
||||
## Network start/reconnect loop
|
||||
|
||||
Initial connection failure must not spin indefinitely or block controlled recovery.
|
||||
|
||||
Connection state must be based on actual I/O lifecycle rather than only `Socket.isConnected()`-style historical state.
|
||||
@@ -0,0 +1,183 @@
|
||||
# Project behaviour catalog
|
||||
|
||||
This catalog summarizes behaviour established during prior KST4Contest work. It is context for analysis, not permission to overwrite newer code. Always inspect the current implementation before modifying a listed area.
|
||||
|
||||
## Core purpose
|
||||
|
||||
KST4Contest is an ON4KST-oriented desktop client optimized for VHF/UHF/microwave contest workflows.
|
||||
|
||||
Core areas developed over time include:
|
||||
|
||||
- simultaneous ON4KST chat handling;
|
||||
- priority candidates;
|
||||
- sked workflow and timeline;
|
||||
- worked-state synchronization;
|
||||
- logging integrations;
|
||||
- DXCluster;
|
||||
- AirScout / airplane-scatter assistance;
|
||||
- rotor/control integrations;
|
||||
- map/path visualization;
|
||||
- automated replies/beacons;
|
||||
- user filtering and reachability;
|
||||
- documentation and website/update-feed integration.
|
||||
|
||||
## Two chat categories
|
||||
|
||||
The application is designed around two simultaneous relevant chat categories in normal operation.
|
||||
|
||||
Important consequences:
|
||||
|
||||
- same-looking calls in different categories are not automatically the same chat identity;
|
||||
- category is part of message/member identity;
|
||||
- category-specific QRG/band settings must not leak into the other category;
|
||||
- unsupported categories must not crash shared logic.
|
||||
|
||||
## Priority candidates
|
||||
|
||||
Priority scoring has included factors such as:
|
||||
|
||||
- QTF match;
|
||||
- recent activity;
|
||||
- message count;
|
||||
- positive signal indications;
|
||||
- sked rate.
|
||||
|
||||
Do not change weighting/meaning as collateral work. Treat it as user-facing contest logic.
|
||||
|
||||
## Timeline / skeds
|
||||
|
||||
The sked timeline has used 30-minute lanes and visualized airplane-scatter probability windows.
|
||||
|
||||
Known historical AP strength levels:
|
||||
|
||||
- 100%;
|
||||
- 75%;
|
||||
- 50%.
|
||||
|
||||
Sked reminder presets have covered short contest-relevant lead times.
|
||||
|
||||
Do not hardcode historical display constants into new code without verifying the current view/model.
|
||||
|
||||
## Worked state
|
||||
|
||||
Worked state is loaded from persistence and updated live from supported logging inputs.
|
||||
|
||||
The simplified UI meaning has been "worked any" where the locator/worked indicator is concerned.
|
||||
|
||||
Worked state is base-call-wide across suffix variants where established.
|
||||
|
||||
When changing persistence or logging synchronization, verify:
|
||||
|
||||
- startup DB load;
|
||||
- live update;
|
||||
- suffix/base-call mapping;
|
||||
- band mapping;
|
||||
- 50/70 MHz support where applicable;
|
||||
- UI projection.
|
||||
|
||||
## Known active bands / B+
|
||||
|
||||
Known-active-band information is derived consistently across the application from available hints.
|
||||
|
||||
Historical work unified:
|
||||
|
||||
- band mentions in user names;
|
||||
- band mentions in text;
|
||||
- manual/global band information;
|
||||
- `B+`-style availability.
|
||||
|
||||
Explicit `NOT-QRV` overrides positive hints.
|
||||
|
||||
Avoid introducing a second parser with different semantics.
|
||||
|
||||
## Selection and send workflow
|
||||
|
||||
Established fast-workflow behaviour includes:
|
||||
|
||||
- selecting a new station prefills `/cq callsign`;
|
||||
- send text is geared toward minimal contest interaction;
|
||||
- if no target chat category is selected, Main is the established fallback.
|
||||
|
||||
These are intentional workflow decisions, not incidental UI details.
|
||||
|
||||
## DXCluster
|
||||
|
||||
DXCluster support has included:
|
||||
|
||||
- integrated display;
|
||||
- copyable lines;
|
||||
- `/cq` workflow support;
|
||||
- beacon monitoring;
|
||||
- QTF/bearing-related presentation.
|
||||
|
||||
Preserve locator semantics and avoid sender/receiver field confusion.
|
||||
|
||||
## Map / path view
|
||||
|
||||
Map work has included:
|
||||
|
||||
- Leaflet 1.9.4 in JavaFX WebView;
|
||||
- terrain/path information;
|
||||
- airplane-scatter integration;
|
||||
- target-station selection;
|
||||
- path-analysis visibility;
|
||||
- station-count/status information;
|
||||
- target reset that does not reset zoom.
|
||||
|
||||
A persistent right-side station-information panel has been reduced/removed in favour of more compact presentation in later UI work.
|
||||
|
||||
Before changing layout, inspect the current version because this area has been actively iterated.
|
||||
|
||||
## Reachability and filters
|
||||
|
||||
Filter work has separated reachability concerns from generic filters.
|
||||
|
||||
A Reset Filter control must reset the actual filter predicates, not just visual controls.
|
||||
|
||||
UI sorting/filtering must remain stable when backing data changes.
|
||||
|
||||
## Autoanswer and beacons
|
||||
|
||||
Automated messaging exists to reduce repetitive contest chat work without creating spam or feedback loops.
|
||||
|
||||
Important principles:
|
||||
|
||||
- conservative timing;
|
||||
- bounded text;
|
||||
- no loop on own automated markers;
|
||||
- only consume cooldown after a valid queued reply;
|
||||
- category/callsign-safe identity;
|
||||
- QRG requests handled with the intended precedence.
|
||||
|
||||
## Connection handling
|
||||
|
||||
Network reliability is contest-critical.
|
||||
|
||||
Work has explicitly targeted:
|
||||
|
||||
- accurate connected/disconnected state;
|
||||
- server disconnect detection;
|
||||
- reconnect behaviour on unstable links;
|
||||
- no infinite loop on initial connection failure;
|
||||
- visible connection-state indication in the UI.
|
||||
|
||||
Do not regress connection state into "socket object exists therefore connected".
|
||||
|
||||
## Historic messages
|
||||
|
||||
Historic/non-current chat senders may not have a complete live `ChatMember`.
|
||||
|
||||
Highlighting, display and parsing must tolerate users not currently logged in.
|
||||
|
||||
## Website and documentation
|
||||
|
||||
The application repository also contains:
|
||||
|
||||
- bilingual manual content;
|
||||
- documentation images;
|
||||
- automated documentation PDF build;
|
||||
- Eleventy website;
|
||||
- download/update metadata generation;
|
||||
- release-oriented website automation.
|
||||
|
||||
A user-visible feature change may therefore affect more than Java source.
|
||||
@@ -0,0 +1,101 @@
|
||||
# Protocols and external integrations
|
||||
|
||||
This file records stable rules plus historical context. For exact current wire formats, ports and frequency strings, inspect the current code and authoritative upstream documentation.
|
||||
|
||||
## ON4KST
|
||||
|
||||
KST4Contest depends on long-lived server communication where malformed commands or framing can lead to disconnects.
|
||||
|
||||
Rules:
|
||||
|
||||
- preserve exact protocol framing;
|
||||
- treat CR/LF changes as protocol changes, not formatting cleanup;
|
||||
- do not append extra line terminators without verification;
|
||||
- detect actual socket/server disconnects reliably;
|
||||
- initial connection failure must not create an uncontrolled infinite loop;
|
||||
- reconnect logic must tolerate unstable Internet access;
|
||||
- the UI should make disconnected state clearly visible where implemented.
|
||||
|
||||
If Windows-specific behaviour is suspected, do not assume Win10/Win11 line-ending semantics explain it without reproducing or tracing the bytes.
|
||||
|
||||
## UCXLog / DXLog UDP XML
|
||||
|
||||
`contactreplace` must be handled equivalently to `contactinfo` for whole-log broadcasts where applicable.
|
||||
|
||||
Historical raw-packet XML start detection included:
|
||||
|
||||
```text
|
||||
<?xml
|
||||
<contactinfo
|
||||
<contactreplace
|
||||
<RadioInfo
|
||||
```
|
||||
|
||||
DOM handling also included a fallback to `contactreplace`.
|
||||
|
||||
Before changing this path, inspect the current parser because the code may have been refactored since this behaviour was introduced.
|
||||
|
||||
Preferred layering:
|
||||
|
||||
```text
|
||||
UDP receiver -> parser -> DTO -> service/domain/DB -> controller -> UI
|
||||
```
|
||||
|
||||
## Win-Test
|
||||
|
||||
Historical integration uses UDP port 8721 for Win-Test information.
|
||||
|
||||
Do not hardcode this fact into unrelated logic. Verify current configuration before changing listener setup or band mapping.
|
||||
|
||||
Changes involving 50/70 MHz, worked state or frequency mapping must be consistent with other logging inputs.
|
||||
|
||||
## AirScout
|
||||
|
||||
KST4Contest integrates with AirScout path/airplane-scatter information.
|
||||
|
||||
Stable principles:
|
||||
|
||||
- propagation/path queries must reflect the current relevant frequency/band;
|
||||
- do not fall back to 144 MHz merely because older code did;
|
||||
- unsupported chat categories must fail safely;
|
||||
- frequency-string formatting is an external API contract and must be checked, not guessed.
|
||||
|
||||
Historical work included a temporary 430 MHz approximation for ambiguous higher-band handling. Treat that as historical context, not a permanent invariant. Inspect the current implementation before using or changing it.
|
||||
|
||||
## PSTRotator
|
||||
|
||||
The integration has evolved.
|
||||
|
||||
Historical project notes mention more than one control approach, and recent work included UDP control/feedback behaviour around a configurable control port and feedback on the next port, including SPID movement retry logic.
|
||||
|
||||
Therefore:
|
||||
|
||||
- inspect the current implementation before assuming TCP vs UDP;
|
||||
- inspect current settings/defaults;
|
||||
- do not copy an old port/transport assumption into new code;
|
||||
- preserve asynchronous JavaFX-safe handling;
|
||||
- preserve any verified retry sequence only if it still exists in current code/tests.
|
||||
|
||||
If current code and historical notes conflict, ask Marc after showing the conflict.
|
||||
|
||||
## DXCluster
|
||||
|
||||
DXCluster is integrated into the contest workflow.
|
||||
|
||||
Preserve:
|
||||
- copyable/usable cluster lines;
|
||||
- correct sender/receiver locator semantics;
|
||||
- safe handling of missing locator data.
|
||||
|
||||
A historical bug copied sender and receiver locators as equal; do not reintroduce that behaviour.
|
||||
|
||||
## Protocol-wide error handling
|
||||
|
||||
External data is not trusted to be complete.
|
||||
|
||||
Rules:
|
||||
|
||||
- validate before dereferencing;
|
||||
- unknown categories/bands/tags should degrade safely;
|
||||
- malformed packets must not kill long-running receiver/management threads;
|
||||
- logging should make the rejected input diagnosable without flooding normal operation.
|
||||
@@ -0,0 +1,22 @@
|
||||
# Deferred and roadmap context
|
||||
|
||||
This file is background only. Do not implement these items merely because they are mentioned here.
|
||||
|
||||
## Propagation model
|
||||
|
||||
After the manual audit, Marc intends to revisit and improve KST4Contest propagation modelling.
|
||||
|
||||
Exploration areas include:
|
||||
|
||||
- higher-density Copernicus GLO-30 terrain sampling;
|
||||
- Fresnel-zone analysis;
|
||||
- diffraction modelling;
|
||||
- simplified ray tracing / multi-segment paths;
|
||||
- VHF/UHF/microwave contest applicability, including around 1296 MHz and above;
|
||||
- practical contest-oriented prediction rather than academic complexity for its own sake.
|
||||
|
||||
This requires a fresh concept before implementation.
|
||||
|
||||
## Rule
|
||||
|
||||
Roadmap context must never silently enlarge the scope of a current task.
|
||||
@@ -0,0 +1,80 @@
|
||||
# Settings and data context
|
||||
|
||||
Inspect `Config`/settings classes and current UI before using these names; this list records important settings/concepts encountered during prior work.
|
||||
|
||||
## Band / station settings
|
||||
|
||||
Important concepts have included:
|
||||
|
||||
- `MYQRGFirstCat`;
|
||||
- `MYQRGSecondCat`;
|
||||
- manual station band information;
|
||||
- current/actual QTF;
|
||||
- known-active bands;
|
||||
- selected/current QRG.
|
||||
|
||||
Band-dependent features must use the correct category/station context.
|
||||
|
||||
## Antenna / path settings
|
||||
|
||||
Important concepts have included:
|
||||
|
||||
- `actualQTF`;
|
||||
- `antennaBeamWidthDeg`;
|
||||
- maximum QRB;
|
||||
- AirScout/path-analysis settings.
|
||||
|
||||
Missing QRB/QTF must remain unknown, not numeric zero.
|
||||
|
||||
## UI settings
|
||||
|
||||
Persisted UI behaviour has included:
|
||||
|
||||
- dark mode;
|
||||
- map/path-analysis visibility;
|
||||
- filters/reachability controls;
|
||||
- column visibility;
|
||||
- divider/layout state where implemented.
|
||||
|
||||
Do not reset persisted user choices as an incidental effect of a feature change.
|
||||
|
||||
## Logging / worked persistence
|
||||
|
||||
Worked information is persisted and updated through multiple input paths.
|
||||
|
||||
Before changing one path, compare semantics across:
|
||||
|
||||
- DB load on startup;
|
||||
- simple/manual log integration where present;
|
||||
- UCXLog/DXLog;
|
||||
- Win-Test;
|
||||
- other current logging inputs.
|
||||
|
||||
The goal is one worked-state interpretation regardless of source.
|
||||
|
||||
## Chat/message automation
|
||||
|
||||
Configuration has included:
|
||||
|
||||
- beacon/autoanswer enablement;
|
||||
- beacon defaults;
|
||||
- message limits/timers;
|
||||
- category-specific communication.
|
||||
|
||||
Do not duplicate timers or create per-feature scheduling that bypasses the shared safety model.
|
||||
|
||||
## Connection state
|
||||
|
||||
Connection-state UI must reflect actual ON4KST connection lifecycle.
|
||||
|
||||
Any new state enum/property should have a clear owner and thread boundary.
|
||||
|
||||
## Persistence rule
|
||||
|
||||
Do not change persisted keys/schema/semantics simply to make new code easier.
|
||||
|
||||
If a schema/key migration is required:
|
||||
|
||||
1. explain current and new format;
|
||||
2. describe backward compatibility;
|
||||
3. ask for approval before implementing.
|
||||
@@ -0,0 +1,100 @@
|
||||
# Build, tests, static analysis and release safety
|
||||
|
||||
## Maven
|
||||
|
||||
Use the repository Maven wrapper.
|
||||
|
||||
Windows:
|
||||
|
||||
```text
|
||||
.\mvnw.cmd test
|
||||
.\mvnw.cmd package
|
||||
```
|
||||
|
||||
Run narrower tests first when possible.
|
||||
|
||||
## Important Surefire behaviour
|
||||
|
||||
The project has used:
|
||||
|
||||
```xml
|
||||
<testFailureIgnore>true</testFailureIgnore>
|
||||
```
|
||||
|
||||
Therefore an exit code of zero is not sufficient evidence that all tests passed.
|
||||
|
||||
Always inspect:
|
||||
|
||||
- test counts;
|
||||
- failures;
|
||||
- errors;
|
||||
- skipped tests;
|
||||
- Surefire report output when necessary.
|
||||
|
||||
State exact results in the completion report.
|
||||
|
||||
## PMD and SpotBugs
|
||||
|
||||
PMD and SpotBugs are integrated, but their findings have historically not always failed the build.
|
||||
|
||||
Do not say "static analysis clean" unless the relevant reports/output were actually checked.
|
||||
|
||||
## Packaging
|
||||
|
||||
The build contains packaging/module-list consistency logic.
|
||||
|
||||
Changes involving modules, JavaFX modules, jpackage or `module-info.java` must check:
|
||||
|
||||
- `pom.xml`;
|
||||
- `packaging/` helpers;
|
||||
- module requirements;
|
||||
- packaging verification output.
|
||||
|
||||
Do not manually update only one copy of a generated/synchronized module list.
|
||||
|
||||
## Website
|
||||
|
||||
The website is Eleventy-based and has Node tests.
|
||||
|
||||
Inspect `website/package.json`, `website/test/` and current scripts before choosing exact commands.
|
||||
|
||||
Historical website validation included Node tests for generated version/update information.
|
||||
|
||||
## Documentation build
|
||||
|
||||
GitHub Actions generates documentation/PDF and site artefacts.
|
||||
|
||||
A local code build does not prove documentation/site CI will pass.
|
||||
|
||||
## Versioning
|
||||
|
||||
Do not change project version, semantic version, update feed, tag or release metadata unless explicitly requested.
|
||||
|
||||
## Git
|
||||
|
||||
Each of these needs separate authorization:
|
||||
|
||||
- stage;
|
||||
- commit;
|
||||
- push;
|
||||
- PR;
|
||||
- merge;
|
||||
- tag;
|
||||
- release.
|
||||
|
||||
When asked to commit, use a concise English commit message.
|
||||
|
||||
Do not stage unrelated files.
|
||||
|
||||
## Release communication
|
||||
|
||||
When a release is explicitly in scope, check:
|
||||
|
||||
- current changelog;
|
||||
- GitHub release/tag;
|
||||
- website download/update feed;
|
||||
- documentation;
|
||||
- HamRadioOnline download/manual destinations;
|
||||
- any SourceForge publication workflow currently used.
|
||||
|
||||
Do not assume an older deployment pipeline is still active.
|
||||
@@ -0,0 +1,73 @@
|
||||
# Threading and state management
|
||||
|
||||
## Canonical state vs UI state
|
||||
|
||||
Use a thread-safe canonical state for data consumed by worker/network threads.
|
||||
|
||||
The active-member UI list is only a projection.
|
||||
|
||||
Preferred conceptual model:
|
||||
|
||||
```text
|
||||
ConcurrentMap<MemberKey, ChatMember> activeMembers
|
||||
|
|
||||
| FX-thread projection/update
|
||||
v
|
||||
ObservableList<ChatMember> activeMembersUi
|
||||
```
|
||||
|
||||
`MemberKey` semantics must preserve full callsign plus category unless the specific operation is intentionally base-call-wide.
|
||||
|
||||
## MessageBusManagementThread
|
||||
|
||||
Do not:
|
||||
|
||||
- iterate JavaFX `ObservableList` from the worker thread;
|
||||
- add/remove JavaFX-list entries directly from the worker thread;
|
||||
- use the FX thread as a substitute for proper domain state ownership.
|
||||
|
||||
Do:
|
||||
|
||||
- pass domain events/data to the controller/service boundary;
|
||||
- modify canonical thread-safe state outside UI code as appropriate;
|
||||
- project changes to JavaFX state on the FX thread.
|
||||
|
||||
## Controller boundary
|
||||
|
||||
`ChatController` is the preferred coordination boundary for UI-visible state.
|
||||
|
||||
Keep view-specific operations out of protocol receiver code.
|
||||
|
||||
## External receiver design
|
||||
|
||||
For receiver refactors, separate:
|
||||
|
||||
- socket/UDP/TCP I/O;
|
||||
- parsing;
|
||||
- DTO;
|
||||
- domain/persistence;
|
||||
- UI coordination.
|
||||
|
||||
## Error containment
|
||||
|
||||
Long-running threads must survive:
|
||||
|
||||
- malformed server records;
|
||||
- incomplete members;
|
||||
- unknown bands/categories;
|
||||
- missing locators;
|
||||
- null QRB/QTF;
|
||||
- temporary socket failure.
|
||||
|
||||
Catch errors at meaningful boundaries and include enough context in English diagnostic logs/comments to trace the input and stage of failure.
|
||||
|
||||
Do not swallow errors silently.
|
||||
|
||||
## JavaFX selection/sorting
|
||||
|
||||
When updating backing data:
|
||||
|
||||
- preserve current selection where the feature expects it;
|
||||
- avoid invalidating `FilteredList`/`SortedList` assumptions;
|
||||
- do not create recursive UI updates;
|
||||
- avoid accessing control state from worker threads.
|
||||
@@ -0,0 +1,65 @@
|
||||
# UI behaviour and workflow invariants
|
||||
|
||||
These are known user-experience decisions. Verify the current implementation before changing them.
|
||||
|
||||
## Selection and send text
|
||||
|
||||
A new station selection should prefill the established command form:
|
||||
|
||||
```text
|
||||
/cq callsign
|
||||
```
|
||||
|
||||
This behaviour is deliberate even when prior input text existed, according to the established workflow.
|
||||
|
||||
If no category is selected for sending, the established fallback is the Main category.
|
||||
|
||||
Do not change either behaviour as a side effect of unrelated refactoring.
|
||||
|
||||
## Map view
|
||||
|
||||
Known decisions:
|
||||
|
||||
- reset clears the target/station selection;
|
||||
- reset does not change the current zoom level;
|
||||
- selected-station information was moved toward the compact status line rather than requiring a persistent right-side detail panel;
|
||||
- path-analysis visibility is user-controllable and should not become undiscoverable;
|
||||
- map controls must remain usable in dark/light modes.
|
||||
|
||||
## Leaflet / JavaFX WebView
|
||||
|
||||
With Leaflet 1.9.4 under Java 21, fragmented rendering/flicker was fixed by disabling Leaflet CSS 3D transforms before Leaflet loads:
|
||||
|
||||
```text
|
||||
window.L_DISABLE_3D = true
|
||||
```
|
||||
|
||||
Do not remove/reorder this workaround without reproducing the rendering problem and proving the replacement.
|
||||
|
||||
## Filters
|
||||
|
||||
Known UI direction:
|
||||
|
||||
- Reset Filter must actually clear relevant filter predicates;
|
||||
- reachability controls are conceptually separate from generic filter controls;
|
||||
- reset control should remain visually discoverable;
|
||||
- truncated text should remain accessible through tooltips where implemented;
|
||||
- clickable links should remain functional in both themes.
|
||||
|
||||
## Priority / timeline
|
||||
|
||||
The contest workflow includes:
|
||||
- priority candidate presentation;
|
||||
- sked timeline;
|
||||
- activity/AP windows;
|
||||
- sked reminders.
|
||||
|
||||
Avoid UI changes that damage quick contest operation merely to make layout code simpler.
|
||||
|
||||
## Null display
|
||||
|
||||
Missing data is not `0`.
|
||||
|
||||
For QRB/QTF/locator/derived values, follow the current UI convention for unavailable/empty state.
|
||||
|
||||
Do not show a plausible-looking number when the model value is actually unknown.
|
||||
Reference in New Issue
Block a user