18 Commits
Author SHA1 Message Date
Marc Froehlich 7ff7248e7d Fixed KST4Contest caused disconnect on getting no activities of ON4KST chatservers if no new lines arriving 2026-08-27 01:26:50 +02:00
Marc Froehlich 3193e4ac73 manual and code: configfile path corrected 2026-08-27 00:23:09 +02:00
Marc Froehlich 3ec6cab46a manual and code: fixed colour handling of the messages and better descripted it in the manual 2026-08-27 00:02:02 +02:00
Marc Froehlich b280f1b0db manual: overhaul features, config, dxcluster server 2026-08-26 22:57:49 +02:00
Marc Froehlich 7fe33613e9 manual: overhaul cluster-server and feature list 2026-08-26 22:43:16 +02:00
Marc Froehlich 9378bf2afd manual: overhaul en-home and changelog de and en 2026-08-26 22:19:27 +02:00
Marc Froehlich 047891e109 manual: overhaul user interface de and en 2026-08-26 01:05:13 +02:00
Marc Froehlich 4f88101ab7 manual: overhaul en-variables and macros 2026-08-26 00:56:33 +02:00
Marc Froehlich 5955ba4ecf manual: added contest workflow and variables 2026-08-26 00:39:24 +02:00
Marc Froehlich a9eba266ee chore: add Codex project context and agent guidance 2026-08-25 01:18:49 +02:00
Marc Froehlich 4601199587 chore: add Codex project context and agent guidance 2026-08-25 01:00:26 +02:00
Marc Froehlich 8c6ce6b402 manual: updated user interface documentation 2026-08-25 00:52:47 +02:00
github-actions[bot] 75ab24da25 chore: update AUR packages to v1.42.0 [skip ci] 2026-08-22 16:56:23 +00:00
Rsclub2_2 8aadbb9ee0 AUR: fix PKGBUILD in Repo 2026-08-22 18:53:44 +02:00
Rsclub2_2 3b344482ba AUR: fix Packages not updating 2026-08-22 18:36:13 +02:00
Rsclub2_2 86ad2f7a43 Website: Version 1.42 released news 2026-08-22 18:29:52 +02:00
Rsclub2_2 29ce6b0a4d AUR: mark Workspace as safe for git. 2026-08-22 18:27:22 +02:00
Rsclub2_2 4d8b8aa12e v1.42 Docs updated 2026-08-22 18:24:55 +02:00
67 changed files with 3920 additions and 424 deletions
@@ -0,0 +1,90 @@
---
name: kst4contest-change
description: Analyze or implement KST4Contest Java/JavaFX changes, bug fixes, refactorings, protocol handling, contest workflow behaviour, callsign/band logic, AirScout/logging/rotor/DXCluster integrations, threading and state management. Use current code as source of truth and follow the mandatory concept-and-question gate before edits.
---
# KST4Contest change workflow
Read the relevant reference files before proposing a concept.
## Phase 1: read-only analysis
- Inspect the current code and tests.
- Identify the current data flow and thread ownership.
- Identify user-visible and protocol-visible behaviour.
- Check relevant `docs/PROJECT_CONTEXT.md` sections when they exist.
- Check whether the task overlaps a known invariant in the references.
- Do not modify files.
## Phase 2: report understanding in German
Explain:
- what Marc wants changed;
- what must remain unchanged;
- which components appear affected;
- what evidence in the current code supports that understanding;
- any conflict between current code and historical project context.
Never resolve a conflict by guessing.
## Phase 3: questions and final concept in German
Before finalizing the concept:
- identify all material implementation choices;
- ask Marc questions that are not already answered by code, project instructions or prior confirmed decisions;
- wait for answers when needed.
Then present:
- intended data/control flow;
- exact behavioural changes;
- compatibility impact;
- thread/UI impact;
- persistence impact;
- test strategy;
- likely documentation impact;
- likely durable project-context impact;
- related-project impact when relevant.
Ask for explicit concept approval and wait before editing.
## Phase 4: implementation
After approval:
- implement the smallest coherent change;
- preserve unrelated behaviour;
- keep comments/Javadoc in English;
- add/update focused tests;
- keep external protocol parsing defensive;
- avoid hidden defaulting for unknown values.
## Phase 5: verification and documentation impact
Run focused checks, then appropriate broader checks.
Because KST4Contest build configuration may ignore failures/findings, inspect summaries and reports rather than only command exit status.
Then use `$software-project-context`:
- do a low-cost documentation-impact classification;
- inspect only likely affected manual/README/website sections;
- update targeted documentation when clearly required by the approved implementation;
- update `docs/PROJECT_CONTEXT.md` for significant durable technical decisions/state changes;
- do not perform a full manual audit unless there is a specific trigger.
## Phase 6: report
Report in German:
- files changed;
- implementation summary;
- tests/checks;
- warnings/findings;
- documentation-impact result;
- documentation/context updates or why none were required;
- related-project impact when relevant;
- unresolved issues;
- no Git publication action unless explicitly requested.
@@ -0,0 +1,7 @@
interface:
display_name: "KST4Contest Change"
short_description: "Plan and implement KST4Contest changes safely"
default_prompt: "Analyze the requested KST4Contest change, explain your understanding and concept in German, ask implementation questions, and wait for approval before editing."
policy:
allow_implicit_invocation: true
@@ -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.
@@ -0,0 +1,74 @@
---
name: kst4contest-documentation
description: Perform targeted KST4Contest documentation-impact checks and update affected German/English manuals, README, website feature text, changelog, release notes and durable project context. Avoid full audits by default; keep documentation aligned with implemented behaviour and use the praktimarc-writing-style skill.
---
# KST4Contest documentation workflow
Use `$software-project-context` and `$praktimarc-writing-style`.
## Default behaviour
Do not read the complete manual or website after every code change.
Start with a documentation-impact classification and search for the affected feature, setting, UI label, protocol/integration or operational concept.
Escalate to a broader audit only when:
- Marc explicitly requests it;
- a major release is being prepared;
- the change is broad across UI/workflows;
- multiple targeted checks reveal wider drift.
## Before editing documentation
1. Inspect the actual implementation or approved specification.
2. Explain in German what documentation is probably affected.
3. Ask only unresolved behaviour/scope questions.
4. If documentation updates are already part of an approved implementation concept, no second approval is required for obvious synchronisation.
5. If documentation reveals a new material product decision, stop and ask Marc.
## Manuals
When user-facing behaviour is affected:
- search English and German manual content under `github_docs/` for the relevant feature/labels first;
- inspect surrounding sections only;
- keep both language versions semantically equivalent;
- do not translate mechanically; English must be idiomatic;
- preserve exact UI labels, values, callsigns, ports and protocol terminology;
- document current behaviour only;
- if code and manual disagree and it is unclear which behaviour is intended, report the conflict;
- identify outdated/missing screenshots explicitly.
## README / website
Check only when the changed feature, installation, configuration, capability or compatibility is represented there or should reasonably be represented there.
- Keep feature descriptions concise.
- Explain real contest/operating benefit, not marketing slogans.
- Avoid duplicating large manual sections on the website.
- Keep the main manual/download destinations consistent with the current site strategy.
## Durable project context
Update `docs/PROJECT_CONTEXT.md` for significant:
- architectural decisions;
- threading/state ownership;
- callsign/category semantics;
- protocol/integration contracts;
- persistence/configuration changes;
- durable workarounds;
- deployment/website relationships;
- cross-project dependencies;
- planned propagation/API architecture when it becomes concrete.
Keep current-state sections current rather than using the file as a raw changelog.
## Changelog / release notes
- Compact factual bullets.
- Include user-visible changes and important reliability/compatibility fixes.
- Do not invent version scope; derive it from actual commits/changelog/release context.
- Keep release posts short and operationally relevant.
@@ -0,0 +1,7 @@
interface:
display_name: "KST4Contest Documentation"
short_description: "Keep KST4Contest manuals, website and release text aligned"
default_prompt: "Review the implemented KST4Contest behaviour, explain the documentation impact in German, propose a concept, ask questions, and wait for approval before editing."
policy:
allow_implicit_invocation: true
@@ -0,0 +1,26 @@
# User-facing feature context
This is a documentation coverage reminder, not a canonical feature list. Verify each item in current code before documenting it.
Areas repeatedly documented or changed include:
- simultaneous ON4KST chat categories;
- priority candidates;
- sked timeline/reminders;
- known active bands / B+ / NOT-QRV;
- worked indicators;
- DXCluster;
- AirScout integration;
- map/path analysis;
- filtering and reachability;
- PSTRotator/rotor integration;
- UCXLog/DXLog and Win-Test log synchronization;
- beacon/autoanswer behaviour;
- connection status/reconnect behaviour;
- dark/light UI behaviour;
- QTF/bearing workflow;
- download/update behaviour.
When one of these changes, search both language manuals and website copy for affected references.
Do not specialize documentation beyond actual behaviour. A useful example from prior work is callsign monitoring: entering an SSID-style variant can intentionally monitor the base call rather than requiring every suffix to be configured individually.
@@ -0,0 +1,47 @@
# Manual and website context
## Manual location
KST4Contest documentation is maintained in `github_docs/` with English and German Markdown pages plus screenshots.
The documentation build is automated through repository workflows.
## Audit workflow established with Marc
The normal review method is:
1. compare documentation with actual code/behaviour;
2. propose exact changes;
3. note missing/outdated screenshots and their intended repo location;
4. if code must change to match the manual, stop and confirm that code change first;
5. keep German and English content aligned;
6. prefer one thorough update over many cosmetic iterations.
With Codex editing locally, the old copy/paste insertion-guide step is replaced by direct edits, but the approval logic remains.
## Examples and easter eggs
Deliberate examples/test strings must not be "cleaned up" merely because they are informal.
A known example uses:
```text
DO5AMF
Testing DXC-Spot: Congrats, you donated $100!
```
Preserve such deliberate easter eggs unless Marc explicitly asks to remove or replace them.
## Website
The website under `website/` uses Eleventy/Nunjucks.
Style direction:
- modern and concise;
- technically focused;
- no promotional tone;
- English primary where appropriate;
- documentation remains the detailed source; website text should not duplicate entire manual sections.
Current website architecture/scripts must be inspected before changes.
@@ -0,0 +1,35 @@
# Release communications
## Changelog
Write concise English change descriptions.
Prioritize:
- behaviour users notice;
- contest workflow impact;
- protocol/integration compatibility;
- bug/reliability fixes;
- documentation improvements.
Avoid internal refactor trivia unless it materially changes reliability or maintainability relevant to the release.
## Social release post
Use `$praktimarc-writing-style`.
Typical structure:
- version;
- short statement of what the release contains;
- compact highlights;
- operational context where relevant, e.g. preparation for a VUSHF contest or planned use at DM5M;
- one clear download/manual destination.
Do not oversell.
## Download/manual direction
Marc has preferred routing users to the HamRadioOnline/KST4Contest download/manual pages rather than scattering multiple download links.
Before publishing new text, inspect the current website URLs and release setup instead of copying an old link.
@@ -0,0 +1,52 @@
---
name: kst4contest-review
description: Review current KST4Contest local changes or a proposed diff before commit. Check regressions, null safety, JavaFX threading, callsign/category semantics, band handling, protocol compatibility, tests, targeted documentation impact, durable project context and unintended scope. Report findings in German and do not modify files unless explicitly asked after the review.
---
# KST4Contest review
Review first; do not edit during the review.
Read the relevant KST4Contest change references.
## Review priorities
1. Behaviour matches the approved concept.
2. No unrelated changes.
3. Full callsign/category identity remains correct.
4. Base-call normalization is used only where intended.
5. Null/unknown values are not converted to fake defaults.
6. Worker threads do not manipulate JavaFX UI collections.
7. FX-thread boundaries are correct.
8. Protocol framing, CR/LF, XML and frequency formatting are unchanged unless explicitly intended.
9. External malformed input cannot kill long-running threads.
10. Tests cover the changed behaviour.
11. Maven test output was interpreted correctly despite ignored-failure settings.
12. A documentation-impact assessment was performed.
13. Any likely affected manual/README/website sections match the implementation.
14. `docs/PROJECT_CONTEXT.md` is updated when the change introduces a durable architectural/protocol/state/operational/integration decision.
15. Comments/Javadoc are English.
16. No unintended dependency/version/release changes.
Do not demand a full manual audit for an internal-only change when the impact assessment reasonably concludes there is no documentation effect.
## Report format
Report in German, ordered by severity.
For each finding include:
- affected file/location;
- concrete problem;
- consequence;
- recommended correction.
Then include:
- verification gaps;
- documentation-impact result;
- durable-context gaps;
- related-project gaps when relevant;
- overall assessment.
Do not fix findings until Marc explicitly asks for implementation and the normal concept gate has been satisfied for the fixes.
@@ -0,0 +1,7 @@
interface:
display_name: "KST4Contest Review"
short_description: "Review KST4Contest diffs before commit"
default_prompt: "Review the current KST4Contest changes only. Report findings in German and do not edit files."
policy:
allow_implicit_invocation: true
@@ -0,0 +1,61 @@
# Review checklist
## Scope
- Is every changed file necessary?
- Did unrelated formatting or refactoring slip in?
- Were user-authored local changes preserved?
## Architecture/threading
- Is canonical state owned outside JavaFX controls/lists?
- Does worker code avoid `ObservableList` access?
- Are UI mutations routed to the FX thread?
- Are parser/I/O/domain/UI responsibilities clearer or at least not more coupled?
## Domain
- Full callsign + category identity preserved?
- Base-call matching restricted to worked/monitoring or another explicitly approved feature?
- Unknown category/band values safe?
- NOT-QRV precedence preserved?
- Missing QRB/QTF remains unavailable rather than zero?
## Protocols
- ON4KST framing unchanged unless approved?
- CR/LF exact?
- UCX `contactreplace` compatibility preserved?
- Frequency strings verified rather than guessed?
- PSTRotator/AirScout transport/API assumptions checked against current code?
- Malformed input contained?
## UI
- Selection/focus/zoom/sorting preserved?
- `/cq callsign` prefill behaviour preserved where relevant?
- Main send-category fallback preserved where relevant?
- map WebView workaround preserved?
- null values displayed safely?
## Tests/build
- Focused regression test added or updated?
- Test summary checked?
- Ignored failures explicitly reported?
- PMD/SpotBugs output considered?
- packaging/module-list checks considered if modules changed?
## Documentation
- DE and EN manual both checked?
- website/README/changelog checked if user-visible?
- screenshot impact reported?
- writing style applied?
- no undocumented implementation or documented-but-unimplemented behaviour?
## Git/release
- No version bump unless requested?
- No generated release/update-feed changes by accident?
- No staging/commit/push without explicit authorization?
+4
View File
@@ -0,0 +1,4 @@
model_reasoning_effort = "high"
approval_policy = "on-request"
sandbox_mode = "workspace-write"
web_search = "live"
+74 -27
View File
@@ -16,8 +16,12 @@ on:
options: ["false", "true"]
default: "false"
permissions:
contents: read
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
AUR_SSH_DIR: /tmp/aur-ssh
jobs:
publish-aur:
@@ -38,6 +42,11 @@ jobs:
uses: actions/checkout@v4.1.7
with:
fetch-depth: 0
ssh-key: ${{ secrets.WEBSITE_DEPLOY_KEY }}
- name: Mark workspace as safe Git directory
run: |
git config --global --add safe.directory "$GITHUB_WORKSPACE"
- name: Resolve release version
id: ver
@@ -118,52 +127,74 @@ jobs:
cat "packaging/aur/${pkg}/.SRCINFO"
done
- name: Commit updated PKGBUILDs to repo
if: inputs.dry_run != 'true'
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
git config user.name "github-actions[bot]"
git remote set-url origin "https://x-access-token:${GITHUB_TOKEN}@github.com/${{ github.repository }}.git"
git add packaging/aur/
git diff --cached --quiet && echo "No PKGBUILD changes to commit." && exit 0
git commit -m "chore: update AUR packages to ${{ steps.ver.outputs.tag }} [skip ci]"
git push
- name: Set up AUR SSH
if: inputs.dry_run != 'true'
env:
AUR_SSH_PRIVATE_KEY: ${{ secrets.AUR_SSH_PRIVATE_KEY }}
run: |
mkdir -p ~/.ssh
printf '%s\n' "${AUR_SSH_PRIVATE_KEY}" > ~/.ssh/aur_ed25519
chmod 600 ~/.ssh/aur_ed25519
ssh-keyscan -t ed25519 aur.archlinux.org >> ~/.ssh/known_hosts
cat >> ~/.ssh/config << 'EOF'
Host aur.archlinux.org
IdentityFile ~/.ssh/aur_ed25519
User aur
EOF
mkdir -p "${AUR_SSH_DIR}"
printf '%s\n' "${AUR_SSH_PRIVATE_KEY}" \
> "${AUR_SSH_DIR}/aur_ed25519"
sed -i 's/\r$//' "${AUR_SSH_DIR}/aur_ed25519"
chmod 600 "${AUR_SSH_DIR}/aur_ed25519"
ssh-keygen -y \
-f "${AUR_SSH_DIR}/aur_ed25519" \
> /dev/null
ssh-keyscan \
-T 10 \
-t ed25519 \
aur.archlinux.org \
> "${AUR_SSH_DIR}/known_hosts"
if [ ! -s "${AUR_SSH_DIR}/known_hosts" ]; then
echo "::error::No SSH host key was received from aur.archlinux.org."
exit 1
fi
echo "Received AUR host-key fingerprint:"
ssh-keygen -lf "${AUR_SSH_DIR}/known_hosts"
if ! ssh-keygen -lf "${AUR_SSH_DIR}/known_hosts" \
| grep -Fq "SHA256:RFzBCUItH9LZS0cKB5UE6ceAYhBD5C8GeOBip8Z11+4"; then
echo "::error::The AUR SSH host-key fingerprint does not match the official fingerprint."
exit 1
fi
printf '%s\n' \
"Host aur.archlinux.org" \
" HostName aur.archlinux.org" \
" User aur" \
" IdentityFile ${AUR_SSH_DIR}/aur_ed25519" \
" IdentitiesOnly yes" \
" StrictHostKeyChecking yes" \
" UserKnownHostsFile ${AUR_SSH_DIR}/known_hosts" \
> "${AUR_SSH_DIR}/config"
chmod 600 "${AUR_SSH_DIR}/config"
chmod 600 "${AUR_SSH_DIR}/known_hosts"
- name: Push to AUR
if: inputs.dry_run != 'true'
env:
TAG: ${{ steps.ver.outputs.tag }}
GIT_SSH_COMMAND: ssh -F /tmp/aur-ssh/config
run: |
git config --global user.email "philipp@wagnersnetz.de"
git config --global user.name "Philipp Wagner"
mkdir -p /tmp/aur
push_to_aur() {
local pkg="$1"
local msg="$2"
local aur_dir="/tmp/aur/${pkg}"
git clone "ssh://aur@aur.archlinux.org/${pkg}.git" "${aur_dir}" 2>/dev/null || {
mkdir -p "${aur_dir}"
git -C "${aur_dir}" init
git -C "${aur_dir}" remote add origin "ssh://aur@aur.archlinux.org/${pkg}.git"
}
git -c init.defaultBranch=master clone \
"ssh://aur@aur.archlinux.org/${pkg}.git" "${aur_dir}"
cp "packaging/aur/${pkg}/PKGBUILD" "${aur_dir}/"
cp "packaging/aur/${pkg}/.SRCINFO" "${aur_dir}/"
@@ -179,3 +210,19 @@ jobs:
push_to_aur kst4contest "Update to ${TAG}"
push_to_aur kst4contest-git \
"Update pkgver to $(grep '^pkgver=' packaging/aur/kst4contest-git/PKGBUILD | cut -d= -f2)"
- name: Commit updated PKGBUILDs to repo
if: inputs.dry_run != 'true'
run: |
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
git config user.name "github-actions[bot]"
git add packaging/aur/
git diff --cached --quiet && echo "No PKGBUILD changes to commit." && exit 0
git commit -m "chore: update AUR packages to ${{ steps.ver.outputs.tag }} [skip ci]"
if ! git push; then
echo "::warning::PKGBUILD bookkeeping commit could not be pushed to main."
echo "The AUR packages were published; only the in-repo copy stays behind."
echo "Check that WEBSITE_DEPLOY_KEY still has write access and may bypass"
echo "the branch ruleset, or commit packaging/aur/ by hand."
fi
+2
View File
@@ -65,6 +65,7 @@ jobs:
github_docs/en-Home.md \
github_docs/en-Installation.md \
github_docs/en-Configuration.md \
github_docs/en-Contest-Workflow.md \
github_docs/en-Features.md \
github_docs/en-User-Interface.md \
github_docs/en-Macros-and-Variables.md \
@@ -91,6 +92,7 @@ jobs:
github_docs/de-Home.md \
github_docs/de-Installation.md \
github_docs/de-Konfiguration.md \
github_docs/de-Contest-Workflow.md \
github_docs/de-Funktionen.md \
github_docs/de-Benutzeroberflaeche.md \
github_docs/de-Makros-und-Variablen.md \
+180
View File
@@ -0,0 +1,180 @@
# KST4Contest agent instructions
These project instructions extend Marc's global Codex working agreements.
## Project identity
KST4Contest is a Java/JavaFX desktop client for ON4KST chat with contest-oriented workflows and integrations including logging software, AirScout, rotor control, DXCluster and local persistence.
Primary repository areas:
- `src/main/java/kst4contest/`
- `src/test/` where present;
- `github_docs/`
- `website/`
- `docs/`
- `packaging/`
- `.github/`
- `pom.xml`
Inspect the current tree before assuming an exact class/path still exists.
## Mandatory interaction rule
For every planned code or documentation implementation:
1. inspect first;
2. explain the task understanding in German;
3. identify and ask all relevant implementation questions;
4. wait for answers when needed;
5. present the final concept in German;
6. state what must remain unchanged;
7. request explicit concept approval;
8. wait;
9. implement only after approval.
If an answer is uncertain, do not interpolate it. Check current code/tests/docs/project context first and ask Marc when the uncertainty can affect behaviour.
## Language
- Communicate with Marc in German.
- Write source-code comments and Javadoc exclusively in English.
- Keep log/protocol/API literals in their canonical form.
- Commit messages are concise English when a commit is explicitly requested.
- User-facing DE/EN documentation follows `$praktimarc-writing-style`.
## Java and JavaFX architecture
- Preserve or improve separation between network/parsing/service/controller/UI responsibilities.
- Do not solve architecture problems by letting worker/model code directly manipulate JavaFX UI collections.
- Active chat-member domain state is conceptually thread-safe state; JavaFX `ObservableList` data is a UI projection, not the canonical worker-thread store.
- `MessageBusManagementThread` must not directly read or mutate the JavaFX `ObservableList` used by the UI.
- Route UI-visible mutations through the controller and the JavaFX Application Thread (`Platform.runLater` or the project's equivalent helper).
- Prefer explicit DTOs over records when introducing transport/parser DTOs in this codebase unless the approved concept says otherwise.
- Handle incomplete external/historical data defensively.
- `qrb`, QTF and related external values can be absent. `null` means unavailable, not zero.
- Unexpected input must not terminate message-processing or UI threads.
## Callsign and category identity
- Preserve full callsign variants as distinct chat-member identities where the server exposes them separately.
- Category is part of chat identity. Do not merge messages across categories.
- Base-call normalization may be used only for explicitly base-call-wide features such as worked status or monitoring rules.
- Worked status is shared across suffix variants of the same base call.
- Monitoring a callsign variant such as `DN9APW-2` or `DN9APW-70` is intended to monitor the base call `DN9APW`, so users do not need to enter every SSID.
- Do not generalize suffix semantics beyond behaviour explicitly established by the current code/specification.
## Bands and availability
- ON4KST categories 2 and 3 are central to the normal VHF/UHF workflow, but other category values can occur and must fail safely.
- Do not let unsupported categories produce exceptions.
- Known-active-band logic and `B+` interpretation must remain consistent across the application.
- Band information parsed from names/text must respect explicit `NOT-QRV` information; NOT-QRV overrides positive availability hints.
- Do not silently fall back to a fixed band/frequency when a required decision is ambiguous unless an approved fallback exists.
- Manual band settings and actual current QRG must remain consistent with features that depend on frequency.
## External protocols and integrations
Before changing ON4KST, AirScout, UCXLog/DXLog, Win-Test, PSTRotator or DXCluster handling:
- inspect the current implementation;
- preserve exact framing and compatibility;
- inspect current tests;
- check authoritative upstream documentation when the protocol detail is uncertain;
- ask Marc if more than one behaviour is plausible.
Specific invariants and historical context are in `$kst4contest-change` references.
Never change CR/LF, XML framing, callsign normalization, frequency formatting or port/transport assumptions casually.
## UI behaviour
- Preserve contest workflow speed and discoverability.
- Do not change zoom, selection, focus, sorting, tab choice or prefilled text as an incidental side effect.
- Map reset behaviour should clear the selected target without changing the zoom unless a new task explicitly changes this.
- New station selection should preserve the established `/cq callsign` prefill behaviour.
- If no send category is selected, preserve the established Main-category fallback unless explicitly changed.
- Null/unknown data must render as unavailable/empty according to current UI conventions, not as fake zero values.
## WebView / map compatibility
- The Leaflet WebView workaround that disables problematic CSS 3D transforms before Leaflet loads is a known Java 21 stability measure. Do not remove or reorder it without reproducing and understanding the original rendering/flicker problem.
## Autoanswer / beacon safety
- Prevent automated-message loops.
- Respect the established minimum interval/cooldown logic.
- Do not consume a cooldown for a reply that is rejected before a complete valid TX item is queued.
- Preserve priority of frequency/QRG requests where established.
- Cooldown identity must not accidentally collapse unrelated callsign/category identities.
- Treat the current implementation/tests as the source of truth for exact message markers and timer details.
## Build and verification
Use the Maven wrapper.
Windows:
```text
.\mvnw.cmd ...
```
Read the current `pom.xml` before relying on version numbers.
At the package creation snapshot the project uses Java 21 / JavaFX 21.x and JUnit 5/Mockito, with PMD and SpotBugs integrated.
Important: Maven/Surefire configuration has historically allowed test failures to be ignored, and static-analysis findings may not fail the build. Therefore:
- inspect the Maven test summary;
- inspect Surefire results when needed;
- do not infer "all tests passed" from exit code 0;
- report PMD/SpotBugs findings that are visible in the relevant build.
Run focused tests first, then normally the relevant broader test/build command for the scope.
## Documentation and durable project context
Use `$software-project-context`, `$kst4contest-documentation`, and `$praktimarc-writing-style` as relevant.
Do not perform a full manual or website audit after every implementation.
After a completed change:
1. perform a short documentation-impact classification;
2. if user-visible behaviour is plausibly affected, search only the relevant German and English manual sections under `github_docs/`;
3. keep both language versions semantically aligned when an update is required;
4. check README and website feature text only when the changed feature/configuration is represented there or is likely to need representation;
5. identify screenshots that are likely stale instead of fabricating replacements;
6. update `docs/PROJECT_CONTEXT.md` for significant architectural, protocol, state/persistence, operational, integration, deployment, workaround, or long-lived behavioural decisions;
7. keep `Related Projects / Integration Points` current when KST4Contest, its website, hamradioonline infrastructure or planned propagation services affect one another.
A full documentation audit is reserved for explicit audit requests, major release preparation, broad UI/workflow changes, or evidence that documentation is broadly stale.
## Website
The repository contains an Eleventy-based website under `website/` with its own tests/build logic.
Do not assume website deployment/update-feed details; inspect current scripts/workflows before changing them.
## Change scope and Git
- No unrelated refactoring.
- No production dependency without prior approval.
- No automatic version bump.
- No commit/push/merge/tag/release/deploy without separate explicit authorization.
- Preserve deliberate test data and easter eggs unless explicitly changed.
- Never overwrite unrelated working-tree changes.
## Completion
After implementation, report in German:
- understanding fulfilled;
- changed files;
- important design decisions;
- tests/builds and exact results;
- documentation-impact classification;
- manual/website/README/context updates made or why none were necessary;
- related-project impact when relevant;
- remaining uncertainty;
- suggested next action, without performing it automatically.
+167
View File
@@ -0,0 +1,167 @@
# KST4Contest Project Context
Last reviewed: 2026-08-27
This file is the durable technical project context for KST4Contest. It is not a user manual and not a replacement for the changelog. Current code, tests and authoritative external specifications remain the source of truth when this document is stale or ambiguous.
## Purpose
KST4Contest is a Java/JavaFX desktop client for ON4KST chat focused on VHF/UHF/microwave contest workflows. It combines chat handling with contest-oriented station prioritisation, sked/timeline workflows and integrations with logging, aircraft-scatter, rotor and DX-cluster tooling.
## Current Architecture
- Java 21 / JavaFX desktop application built with Maven.
- Main code is under `src/main/java/kst4contest/`.
- Responsibilities are separated across controller, service, logic, model, utility and view areas.
- Network/parser/service/controller/UI boundaries should remain explicit.
- Long-running network/message processing must tolerate malformed or incomplete external input without terminating processing threads.
- JavaFX `ObservableList` state is a UI projection, not the canonical worker-thread domain store.
## Important Invariants
### Chat identity
- Full callsign variants can be distinct chat-member identities.
- Category is part of chat identity.
- Base-call normalization is permitted only for explicitly base-call-wide functions.
- Worked status is shared across suffix variants of the same base call.
- Monitoring a variant such as `DN9APW-2` or `DN9APW-70` intentionally monitors the base call `DN9APW`.
- Suffixes must not be globally interpreted as a band/category/frequency.
### Band and availability semantics
- ON4KST categories 2 and 3 are the main operational categories, but unexpected category values must fail safely.
- `NOT-QRV` overrides positive inferred band-availability hints.
- Unknown/missing frequency, QRB, QTF or similar external data must remain unavailable rather than becoming a fabricated zero/default.
- Features that depend on frequency should use the current/actual QRG according to current implemented rules; do not silently revert to a fixed 144 MHz default.
### JavaFX/threading
Conceptually:
```text
thread-safe canonical domain state
|
| projection on JavaFX Application Thread
v
JavaFX ObservableList / UI state
```
`MessageBusManagementThread` must not directly iterate or mutate UI-bound JavaFX collections. UI-visible changes should cross the controller/UI boundary and run on the JavaFX Application Thread.
## External Interfaces
Treat current implementation/tests and authoritative upstream documentation as source of truth before modifying any interface.
Known integration areas include:
- ON4KST chat;
- AirScout;
- UCXLog / DXLog UDP XML (`contactinfo`, `contactreplace`);
- Win-Test UDP;
- PSTRotator TCP;
- DXCluster;
- local SQLite persistence.
CR/LF framing, XML framing, ports/transports, callsign normalization and frequency formatting are protocol behaviour and must not be changed as incidental cleanup.
### ON4KST session liveness
- After 90 seconds without inbound data, the application keeps the established empty CRLF heartbeat.
- At about 180 seconds of inbound idle time, the TCP session sends one `RDXQ|<main chat id>|` probe. The probe state belongs to the session, so a two-category login still sends only one probe per idle phase.
- Any subsequent inbound server frame confirms the probe. `DXQ` is accepted as the expected internal response and is not published as chat content.
- If no inbound frame arrives by about 210 seconds, the existing reconnect flow remains responsible for replacing the session.
- Probe diagnostics contain the session id, main category, opcode and timing only. They must not include credentials, complete server frames or normal chat messages.
## User Workflow / UI Invariants
- Contest operating speed and low-friction interaction are primary goals.
- Incidental code changes must not unexpectedly change selection, focus, sorting, tab state, map zoom or prefilled text.
- Map reset clears the selected target without changing zoom unless explicitly redesigned.
- Station selection preserves the established `/cq callsign` prefill behaviour.
- Sending without an explicitly selected send category preserves the established Main-category fallback unless explicitly changed.
## Autoanswer / Beacon
- Automated-message loops must be prevented.
- Cooldown/minimum-interval rules must be preserved.
- A reply rejected before a complete valid TX item is queued must not consume cooldown.
- Current implementation/tests define the exact message markers and timer details.
## Build / Verification
- Use the repository Maven wrapper (`.\mvnw.cmd` on Windows).
- The project uses Java 21 / JavaFX 21.x at this context snapshot.
- JUnit 5/Mockito, PMD and SpotBugs are part of the verification environment.
- Build/test configuration has historically allowed some test/static-analysis failures not to fail the process exit code. Always read actual summaries/reports.
## Documentation Surfaces
- German and English manuals under `github_docs/`.
- Repository README.
- Eleventy-based project website under `website/`.
- Changelog/release communication.
- This technical project context under `docs/PROJECT_CONTEXT.md`.
After implementation use targeted documentation-impact checks. Do not run a complete manual audit unless explicitly requested, release preparation is broad, or targeted checks indicate systematic drift.
## Website / Deployment Relationship
The repository contains the KST4Contest website under `website/`, published separately from the desktop application build.
Current website/deployment scripts and update-feed behaviour must be inspected before changes; do not rely on historical assumptions.
## Important Decisions and Workarounds
- Preserve full callsign/category identity while applying base-call normalisation only to specifically defined features.
- Keep canonical worker-thread domain state separate from JavaFX UI projections.
- Preserve the established JavaFX WebView/Leaflet workaround that avoids problematic CSS 3D transforms unless the original rendering/flicker issue has been reproduced and the replacement is validated.
- Deliberate test data, comments and Easter eggs are preserved unless explicitly changed.
## Planned Technical Direction
These are planned directions, not necessarily implemented behaviour:
- improve propagation/path modelling using higher-resolution terrain data, including Copernicus GLO-30;
- increase terrain/path sampling through a dedicated service/API;
- support high-precision station locations (e.g. extended Maidenhead locators or direct GPS coordinates) while preserving compatible standard display;
- improve terrain/Fresnel/diffraction/refraction modelling for VHF/UHF/microwave use;
- evaluate/implement richer tropospheric/scatter models;
- continue integration of aircraft-scatter and propagation data into reachability/contest workflows.
Before implementing planned items, re-check current decisions and obtain a fresh concept approval.
## Known Limitations / Maintenance Notes
- Historical project context is useful but may be stale; current code/tests win.
- External service/API behaviour must be verified against current upstream documentation when uncertain.
- Screenshots in manuals/website may need targeted replacement after visible UI changes; never fabricate them.
## Recent Significant Changes
### 2026-08-25 Durable project context introduced
- Added a persistent technical context layer so future agents/developers can understand architecture, invariants and cross-project dependencies without replaying chat history.
- Documentation maintenance uses targeted impact assessment rather than a full audit after every implementation.
## Related Projects / Integration Points
### KST4Contest website
- Source is maintained inside this repository under `website/`.
- User-facing feature/configuration changes may require a targeted website check.
### hamradioonline.de
- Serves as the broader amateur-radio umbrella site/infrastructure context.
- KST4Contest content/download/manual links and related knowledge content may intersect with the broader site strategy.
### Webserver / hosting infrastructure
- KST4Contest website and other hamradioonline services depend on the hosting environment.
- Operational details should be maintained in a private infrastructure context rather than duplicated into this public project context when sensitive.
### Planned propagation / terrain service
- Intended to provide richer terrain/propagation data (including higher-resolution Copernicus GLO-30-based processing) to KST4Contest and potentially related hamradioonline tooling.
- Interface contracts must be documented on both provider and consumer sides when they become concrete.
-2
View File
@@ -21,8 +21,6 @@ Ob die Verbindung lediglich als TCP-Verbindung besteht oder bereits vollständig
---
---
## Hauptfenster-Überblick
Das Hauptfenster besteht aus mehreren Bereichen:
+5 -4
View File
@@ -8,10 +8,9 @@ Die veröffentlichten Stable-Versionen und ihre Programmpakete stehen unter [Git
---
## v1.42 Nightly / in Entwicklung
## v1.42.0 (2026-08-22)
> Stand dieses Abschnitts: 14. August 2026.
> v1.42 ist noch kein veröffentlichtes Stable-Release. Bis zur Freigabe können weitere Änderungen hinzukommen.
**Gemeinsamer Bandkontext, sitzungsbasierte ON4KST-Verbindung und signierte macOS-Pakete**
v1.42 führt mehrere bisher getrennte Auswertungen zusammen. Bandinformationen, Worked-Status, NOT-QRV-Markierungen, Rufzeichensuffixe und Frequenzen werden dadurch konsistenter in der Benutzerliste, der Stationskarte, der Prioritätsberechnung und den externen Schnittstellen verwendet.
@@ -71,7 +70,7 @@ v1.42 führt mehrere bisher getrennte Auswertungen zusammen. Bandinformationen,
- **Exakte Sked-Ziele:** Timeline und automatische Erinnerungen verwenden das vollständige sichtbare KST-Rufzeichen. Ein Sked für `DN9APW-2` wird nicht versehentlich an eine andere Variante desselben Basisrufzeichens gesendet.
- **Beacon und Autoantwort überarbeitet:** Beide Chat-Kategorien verwenden einen gemeinsamen Timer, behalten aber getrennte Aktivierungsschalter und Texte. Das zulässige Mindestintervall beträgt zwei Minuten; Nachrichtentexte sind auf 120 Zeichen begrenzt. Die gespeicherte Beacon-Aktivierung wird beim Start aus der Konfiguration übernommen.
- **Beacon und Autoantwort überarbeitet:** Beide Chat-Kategorien verwenden einen gemeinsamen Timer, behalten aber getrennte Aktivierungsschalter und Texte. Das zulässige Mindestintervall beträgt eine Minute; Nachrichtentexte sind auf 120 Zeichen begrenzt. Die gespeicherte Beacon-Aktivierung wird beim Start aus der Konfiguration übernommen.
- **Variablen zentral aufgelöst:** Nachrichtenvariablen für Beacons, Shortcuts, Snippets und andere automatisch erzeugte Texte werden über einen gemeinsamen Resolver verarbeitet.
@@ -139,6 +138,8 @@ v1.42 führt mehrere bisher getrennte Auswertungen zusammen. Bandinformationen,
- Eine genauere Konfiguration von Stationshöhe, Frequenz und K-Faktor wird in [Issue #74](https://github.com/praktimarc/kst4contest/issues/74) weiterverfolgt.
Die veröffentlichte Version ist als [Release v1.42.0](https://github.com/praktimarc/kst4contest/releases/tag/v1.42.0) verfügbar.
---
## v1.41.1 (2026-07-08)
+277
View File
@@ -0,0 +1,277 @@
# Contest-Workflow mit KST4Contest
> [English version](en-Contest-Workflow) | Du liest gerade die deutsche Version
KST4Contest fasst Chat, Stationsauswahl, bekannte QRGs, Worked-Status, Skeds, Aircraft-Scatter-Zeiten und weitere Stationsdaten in einer gemeinsamen Oberfläche zusammen. Der Nutzen entsteht nicht aus einer einzelnen Anzeige, sondern aus dem Zusammenspiel dieser Informationen während des laufenden Contests.
Diese Seite beschreibt einen vollständigen Arbeitsablauf. Die einzelnen Funktionen und ihre technischen Grenzen werden weiterhin in den Kapiteln [Funktionen](de-Funktionen), [Benutzeroberfläche](de-Benutzeroberflaeche), [Log-Synchronisation](de-Log-Synchronisation) und [AirScout-Integration](de-AirScout-Integration) erläutert.
---
## Zweck und Grenzen
KST4Contest soll die Zeit zwischen einer erkannten Möglichkeit und dem tatsächlichen QSO verkürzen.
Das Programm kann unter anderem anzeigen:
- welche Stationen aktiv sind,
- auf welchen Bändern und QRGs sie zuletzt erkannt wurden,
- welche Stationen bereits gearbeitet wurden,
- welche zusätzlichen Bänder noch infrage kommen,
- welche Kandidaten zur aktuellen Antennenrichtung passen,
- wann ein Aircraft-Scatter-Fenster erwartet wird und
- welche Station gerade in eine für die eigene Station brauchbare Richtung arbeitet.
Diese Angaben bleiben Entscheidungshilfen. Ein hoher Prioritätsscore ist keine QSO-Wahrscheinlichkeit. Auch eine von AirScout mit 100% bewertete Reflexionsgeometrie garantiert kein QSO. Ob eine QRG tatsächlich frei ist, die Gegenstation zuhört und der Funkweg unter den aktuellen Bedingungen funktioniert, muss der Operator weiterhin selbst beurteilen.
---
## Vor dem Contest
Die wesentlichen Einstellungen sollten nicht erst unmittelbar vor dem ersten interessanten Sked geprüft werden.
### Grundkonfiguration
Prüfe mindestens:
- eigenes Rufzeichen, Passwort und Locator,
- primäre Chat-Kategorie,
- Login und Einstellungen der zweiten Kategorie, falls sie verwendet wird,
- lokal aktive Bänder,
- Antennenöffnungswinkel,
- maximale sinnvolle Entfernung,
- `MYQRG` und gegebenenfalls `SECONDQRG`,
- Log-Synchronisation und
- benötigte Shortcuts, Snippets und Nachrichtenvariablen.
Antennenöffnungswinkel und maximale Entfernung sind stationsabhängig. Bei DM5M wird die reale Antennenanlage beispielsweise mit einem Öffnungswinkel von 69° und einer maximalen Entfernung von 900km abgebildet. Das sind keine allgemeinen Vorgabewerte.
Speichere dauerhafte Änderungen mit **Save Settings**. Nach dem Verbindungsaufbau sollte der `LINK`-Indikator grün sein. Erst dann sind Anmeldung und Benutzerlistensynchronisation vollständig abgeschlossen.
### Automatische Antworten
Die automatische QRG-Antwort gehört zum aktiven Contest-Workflow. Sie beantwortet wiederkehrende QRG-Anfragen und nimmt dem Chatter damit einen Teil der Routinearbeit ab.
Davon zu unterscheiden ist die allgemeine automatische Antwort. Sie kann auf sämtliche eingehenden Anfragen reagieren und ist vor allem dann sinnvoll, wenn die Station vorübergehend nicht QRV ist oder nicht am Sked-Betrieb teilnehmen möchte. Sie erspart sowohl der eigenen Station als auch den anfragenden Stationen unnötige Folgefragen.
### Optionale Anbindungen
Aktiviere nur die Schnittstellen, die tatsächlich verwendet und vorher getestet wurden:
- Logprogramm beziehungsweise Simplelogfile,
- TRX-Synchronisation,
- AirScout,
- PSTRotator,
- Win-Test-Skedübergabe und
- lokaler DX-Cluster-Server.
Ein Contest ist ein ungünstiger Zeitpunkt, um gleichzeitig die Funkbedingungen und eine erstmals aktivierte Netzwerkschnittstelle zu untersuchen.
---
## Grundablauf während des Contests
Der typische Ablauf wiederholt sich:
1. CQ rufen oder einen vereinbarten Sked durchführen.
2. Chat, Prioritätsliste, Karte und AP-Timeline beobachten.
3. Einen geeigneten Kandidaten auswählen.
4. Eigene oder fremde QRG festlegen.
5. QSO versuchen.
6. Erfolgreiches QSO sofort loggen.
7. Eine weitere Bandmöglichkeit prüfen.
8. Einen erfolglosen, aussagekräftigen Versuch mit **Sked fail** kennzeichnen.
9. Zum CQ-Betrieb oder zum nächsten Kandidaten zurückkehren.
KST4Contest hält die benötigten Informationen zwischen diesen Schritten zusammen. Das eigentliche Umschalten, Rufen, Hören und Entscheiden bleibt bewusst beim Operator.
---
## CQ-Betrieb
Bei einer weitgehend festen CQ-QRG sollten `MYQRG` beziehungsweise `SECONDQRG` den tatsächlich verwendeten Frequenzen entsprechen. Eine aktivierte TRX-Synchronisation kann `MYQRG` automatisch aktualisieren. Ohne automatische Quelle muss der Wert von Hand gepflegt werden.
Der Beacon kann die aktuelle QRG, den Locator und die Antennenrichtung regelmäßig im Chat veröffentlichen. Seine Variablen werden bei jedem Sendedurchlauf erneut ausgewertet.
Wird während des CQ-Betriebs über mehrere Frequenzen gescannt, sollte der Beacon deaktiviert werden. Eine automatisch veröffentlichte QRG ist nur hilfreich, solange sie noch stimmt.
Shortcuts und Snippets sollten die regelmäßig benötigten Nachrichten abdecken, beispielsweise:
- Bitte auf der eigenen QRG hören,
- QRG der Gegenstation erfragen,
- Wechsel zur QRG der Gegenstation ankündigen,
- Antennenrichtung bestätigen und
- einen Sked vorschlagen.
Einzelheiten stehen unter [Makros und Variablen](de-Makros-und-Variablen).
---
## Kandidaten auswählen
Die Benutzerliste kann mit QTF-, QRB-, Worked-, Band-, Aktivitäts-, New-Bands-, Tropo- und AirScout-Filtern auf den aktuellen Betriebszustand begrenzt werden.
Die Prioritätsliste und die AP-Timeline ergänzen diese Auswahl:
- Der Prioritätsscore fasst mehrere bekannte Kriterien zusammen.
- Die AP-Timeline ordnet Skeds und erwartete Aircraft-Scatter-Möglichkeiten zeitlich ein.
- Die Stationskarte zeigt die geografische Lage, Antennenrichtung und den Funkweg.
- Der Worked- und Bandstatus verhindert unnötige Doppelarbeit.
![Prioritätsliste und Bewertungsinformationen](priority_score_overview.png)
Der Score ist eine Sortierhilfe. Prüfe vor einem Versuch weiterhin Rufzeichen, Kategorie, Band, QRG, Richtung, Entfernung und die Aktualität der zugrunde liegenden Informationen.
Eine bewusste Auswahl in Benutzerliste, Prioritätsliste, Timeline oder Karte übernimmt den konkreten Chatmember. Dabei bleiben das vollständige sichtbare Rufzeichen und die zugehörige Chat-Kategorie erhalten. KST4Contest bereitet anschließend `/cq RUFZEICHEN` im Sendfeld vor.
---
## Eigene oder fremde QRG verwenden
Wenn eine gute Ausbreitungsrichtung erkannt wird und ein passendes Flugzeug für einen Kandidaten vorhanden ist, wird die Gegenstation zunächst häufig auf die eigene QRG gebeten. Das ist besonders sinnvoll, wenn dort bereits CQ gerufen wird und die Station ohne weiteren Umbau sofort empfangen kann.
Reagiert die Gegenstation nicht, ist ihre eigene QRG geeigneter oder kann sie die angefragte QRG nicht verwenden, wird gewechselt. KST4Contest hält die zuletzt erkannten QRGs bereit, damit der Operator nicht erneut den gesamten Chatverlauf durchsuchen muss.
Auch ein gezielter Versuch auf der QRG eines Sked-Partners ist Teil des normalen Workflows. Entscheidend ist nicht, grundsätzlich auf der eigenen QRG zu bleiben, sondern die vorhandene Möglichkeit mit möglichst wenig Verzögerung zu nutzen.
Vor dem Wechsel sollten mindestens geprüft werden:
- korrektes Band,
- vollständiges Zielrufzeichen,
- QRG der Gegenstation,
- Antennenrichtung,
- erwartetes Aircraft-Scatter-Fenster und
- Belegung der QRG.
---
## Richtungsgelegenheiten nutzen
Eine gerichtete Nachricht zwischen zwei anderen Stationen kann zeigen, dass der Absender seine Antenne ungefähr in Richtung des Empfängers ausgerichtet hat. Passt diese Richtung auch zur eigenen Station, markiert KST4Contest den Absender vorübergehend grün und fett.
![Grün und fett markierte Richtungsgelegenheit](direction_opportunity_highlight.png)
Die Markierung erscheint in der Benutzerliste und den zugehörigen Ansichten. Bei geeigneter Cluster-Konfiguration und bekannter QRG kann die Gelegenheit zusätzlich über den lokalen DX-Cluster ausgegeben werden.
Damit stehen im entscheidenden Moment bereits mehrere Informationen zur Verfügung:
- vollständiges Rufzeichen,
- Locator und Richtung,
- zuletzt erkannte QRG,
- Bandinformationen,
- AirScout-Daten und
- die aktuelle Reachability- beziehungsweise Tropo-Auswertung.
Der Operator muss diese Daten nicht erst zusammensuchen. Er muss lediglich entscheiden, ob die Gelegenheit den laufenden CQ-Betrieb kurz unterbrechen darf.
Bei DM5M lag die Erfolgsquote solcher opportunistischen Versuche nach der bisherigen praktischen Auswertung ungefähr bei 3540%. Dieser Wert beschreibt die Erfahrung einer konkreten Station. Er ist keine allgemeine Erfolgsprognose und hängt unter anderem von Band, Entfernung, Stationsausrüstung, Reaktionszeit und Ausbreitungsbedingungen ab.
Nach dem Versuch kann unmittelbar weiter CQ gerufen oder mit dem nächsten Sked fortgefahren werden.
---
## Skeds planen und auswerten
Ein Sked sollte mit dem tatsächlich vorgesehenen Band und einer realistischen Uhrzeit eingetragen werden. KST4Contest übernimmt ihn in die eigene Sked-Verwaltung und berücksichtigt ihn bei Erinnerungen, Timeline und Prioritätsberechnung.
Die Skeds werden nur für die laufende Programmsitzung verwaltet. Sie sind kein dauerhafter Ersatz für Contestlog oder Notizen.
Ist die Win-Test-Anbindung aktiviert, versucht KST4Contest den Sked zusätzlich an Win-Test zu übergeben. Fehlt eine verwendbare QRG oder passt das Band nicht, bleibt der interne Sked trotzdem erhalten. Lediglich die zusätzliche Übergabe kann dann entfallen.
### Fehlgeschlagene 100-%-Airplane-Skeds
Scheitert ein sorgfältig vorbereiteter Versuch trotz einer von AirScout mit 100% bewerteten Reflexionsgeometrie, sollte die Station mit **Sked fail** gekennzeichnet werden.
Die 100-%-Anzeige ist keine Erfolgswahrscheinlichkeit. Ein Fehlschlag unter diesen Bedingungen ist aber ein brauchbarer betrieblicher Hinweis darauf, dass der Funkweg mit der aktuellen Stationskonfiguration und den aktuellen Bedingungen nicht funktioniert hat.
Die Kennzeichnung reduziert die Priorität der Station für den Rest der laufenden Sitzung. Dadurch können zunächst Kandidaten bearbeitet werden, für die noch keine vergleichbar deutliche negative Betriebserfahrung vorliegt.
**Sked fail** darf nicht als dauerhafte Aussage verstanden werden, dass die Station grundsätzlich nicht erreichbar ist. Andere Bedingungen, ein anderes Band oder eine geänderte Stationskonfiguration können zu einem anderen Ergebnis führen. Die Kennzeichnung kann zurückgesetzt werden und bleibt nicht über einen Programmneustart erhalten.
---
## Nach jedem QSO: Log und weiteres Band
Ein erfolgreiches QSO sollte sofort im angebundenen Logprogramm eingetragen werden. Nur dann können Worked-Status, Bandstatus, Filter und Prioritätsbewertung zeitnah aktualisiert werden.
Welche Details übernommen werden können, hängt von der Logquelle ab. Einige Schnittstellen liefern Band, QRG und Locator, während einfachere Quellen nur einen globalen Worked-Status melden.
Unmittelbar nach jedem Logeintrag sollte geprüft werden, ob für dieselbe Station ein weiteres gemeinsames, lokal aktiviertes und noch nicht gearbeitetes Band vorhanden ist. KST4Contest weist darauf mit `BAND+` und den Bandinformationen der Station hin, soweit die vorhandenen Daten eine solche Bewertung erlauben.
Diese Prüfung ist in allen Multiband-Betriebsarten sinnvoll. Die Gegenstation kann direkt mit einer konkreten Band- und Frequenzangabe weiterkoordiniert werden, bevor sie ihre Antenne wieder wegdreht oder einen anderen Sked beginnt.
Im Klartext: Das nächste mögliche QSO sollte geprüft werden, solange die Gegenstation noch erreichbar und der gemeinsame Kontext noch vorhanden ist.
Ist die Station auf einem angezeigten Band tatsächlich nicht QRV, sollte das Band als NOT QRV markiert werden. Dadurch verschwindet die unbrauchbare Möglichkeit aus Filtern und Bewertung, statt bei jeder Aktualisierung erneut aufzutauchen.
---
## Mehrkategorien- und Multibandbetrieb
Der Mehrkategorienbetrieb ist bei Multibandstationen keine Nebenfunktion. Sein wesentlicher Vorteil besteht darin, dass Informationen aus zwei Chat-Kategorien in einem gemeinsamen Arbeitsablauf ausgewertet werden.
Besonders groß ist der Vorteil bei:
- Einmann-Multibandstationen,
- Multi-Operator-Multibandstationen mit einem zentralen Chat-Koordinator und
- Stationen, die nach einem QSO regelmäßig direkt ein weiteres Band versuchen.
Worked-Status, bekannte Bandaktivitäten und Band Opportunities können gemeinsam bewertet werden. Das konkrete Nachrichtenziel behält trotzdem sein vollständiges Rufzeichen und seine Chat-Kategorie.
Dadurch kann der Chatter eine Station unmittelbar vom ersten QSO auf das nächste Band koordinieren, ohne Rufzeichen, QRG und Bandstatus erneut zusammensuchen zu müssen. Im praktischen Betrieb kann daraus eine sehr schnelle Folge nutzbarer QSO-Möglichkeiten entstehen. Genau an dieser Stelle entfaltet der Mehrkategorienbetrieb seinen größten Workflow-Vorteil.
Auch im Einmannbetrieb bleibt diese Arbeitsweise wirksam. Der Operator muss den Bandwechsel zwar selbst durchführen, erhält aber die nächste sinnvolle Möglichkeit bereits vorbereitet.
Multi-Multi-Stationen mit mehreren gleichzeitig arbeitenden Chattern profitieren ebenfalls. Dort müssen Zuständigkeiten, Bandwechsel und bereits laufende Anfragen allerdings klar koordiniert werden. Mehrere Chatter mit denselben Informationen sind hilfreich; mehrere widersprüchliche Sked-Anfragen an dieselbe Station eher nicht.
---
## Praxisbeispiele
### DM5M: Erst CQ, später mehr Skeds
Bei DM5M wird während der ersten vier bis fünf Stunden eines VHF-/UHF-Contests überwiegend CQ gerufen. Der Chat wird beobachtet, aber nur für wenige gezielte Eingriffe verwendet.
Später nimmt der Sked-Betrieb deutlich zu. Gute Ausbreitungsrichtungen, passende Aircraft-Scatter-Fenster, noch nicht gearbeitete Stationen und zusätzliche Bandmöglichkeiten werden dann gezielt miteinander kombiniert.
Eine geeignete Station wird zunächst auf die eigene QRG gebeten. Reagiert sie nicht oder ist die QRG bei der Gegenstation nicht verwendbar, wechselt DM5M auf deren QRG. Auch geplante Versuche direkt auf der QRG eines Sked-Partners gehören dazu.
Eine grün und fett markierte Richtungsgelegenheit kann den CQ-Betrieb kurzfristig unterbrechen. Nach dem Versuch wird unmittelbar weitergerufen oder der nächste Sked bearbeitet.
Dieser Ablauf ist ein Praxisbeispiel und keine verpflichtende Betriebsart. Andere Stationen können wesentlich früher skedden, dauerhaft zwischen QRGs wechseln oder den Chat von Beginn an intensiver nutzen.
### G1YBB: Richtungsgelegenheiten systematisch abarbeiten
G1YBB verwendet die Richtungsanzeige besonders konsequent. Grün markierte Stationen werden systematisch geprüft und nach Möglichkeit gearbeitet, während parallel der normale CQ-Betrieb weiterläuft.
KST4Contest automatisiert dabei nicht das QSO. Der Vorteil besteht darin, dass QRG, Richtung, Aircraft-Scatter-Informationen und weitere Bewertungsdaten bereits vorliegen, wenn die Gelegenheit entsteht. Die verbleibende Aufgabe ist eine schnelle betriebliche Entscheidung.
---
## Optionale Schnittstellen im Workflow
| Schnittstelle | Aufgabe im Contest |
|---|---|
| [Log-Synchronisation](de-Log-Synchronisation) | Aktualisiert Worked- und Bandstatus nach dem QSO |
| [AirScout](de-AirScout-Integration) | Liefert Aircraft-Scatter-Kandidaten und erwartete Zeitfenster |
| [PSTRotator](de-Konfiguration) | Übernimmt oder setzt die Antennenrichtung |
| [Win-Test](de-Log-Synchronisation) | Kann angelegte Skeds zusätzlich an Win-Test übergeben |
| [DX-Cluster-Server](de-DX-Cluster-Server) | Übergibt erkannte Möglichkeiten an verbundene Logprogramme |
| [Stationskarte](de-Benutzeroberflaeche) | Zeigt Stationen, Richtungen, Auswahl und Funkweg |
Keine dieser Schnittstellen ist für den grundlegenden Chatbetrieb zwingend erforderlich. Ihr Wert entsteht dann, wenn sie zuverlässig eingerichtet ist und eine konkrete manuelle Aufgabe verkürzt.
---
## Was KST4Contest nicht entscheidet
KST4Contest entscheidet nicht:
- ob eine QRG tatsächlich frei ist,
- ob die Gegenstation gerade hören kann,
- ob ein Flugzeug ein QSO ermöglicht,
- ob eine berechnete Funkstrecke unter den aktuellen Bedingungen funktioniert,
- ob ein laufender CQ-Ruf für eine Gelegenheit unterbrochen werden sollte oder
- welcher Kandidat für die aktuelle Conteststrategie den größten Wert besitzt.
Das Programm stellt die vorhandenen Informationen zusammen und hält sie aktuell. Die letzte Entscheidung bleibt beim Operator. Das ist keine Einschränkung des Workflows, sondern der Teil, für den weiterhin Funkbetrieb statt Tabellenkalkulation betrieben wird.
+24 -5
View File
@@ -23,7 +23,7 @@ Im Klartext: Die Information muss nicht erst im Chat gefunden, gelesen, gemerkt
---
## Wie wird eine Richtungsgelegenheit hergeleitet?
## Automatische Spots aus Richtungsgelegenheiten
Angenommen, Station A schreibt eine gerichtete Nachricht an Station B. KST4Contest verwendet die Richtung von A zu B als Näherung für die aktuelle Antennenrichtung von Station A. Anschließend wird geprüft, ob die eigene Station aus Sicht von A innerhalb des angenommenen Antennenkorridors liegt.
@@ -51,6 +51,22 @@ Das Verfahren berücksichtigt weder Gelände noch aktuelle Ausbreitungsbedingung
---
## Manueller Spot für die ausgewählte Kartenstation
Ein Spot kann auch bewusst ausgelöst werden. Wähle dazu eine Station auf der Stationskarte und verwende **Trigger cluster spot** im Detailbereich.
Diese manuelle Auslösung benötigt keine zuvor erkannte gerichtete Nachricht. Auch maximaler QRB und Antennen-Öffnungswinkel entscheiden in diesem Fall nicht darüber, ob der Spot gesendet wird. Erforderlich sind:
- ein aktivierter lokaler DX-Cluster-Server,
- mindestens ein verbundener DX-Cluster-Client und
- eine für die ausgewählte Kartenstation verwendbare QRG.
Damit kann der Operator eine bereits ausgewählte Station gezielt in die Bandmap übernehmen, auch wenn die Bedingungen für einen automatischen Richtungs-Spot nicht vorliegen. Die Bedienung der Karte ist unter [Stationskarte](de-Benutzeroberflaeche#stationskarte) beschrieben.
Automatische und manuelle Spots werden ausschließlich an die mit KST4Contest verbundenen Clients gesendet. Es erfolgt keine Weiterleitung an einen öffentlichen Internet-Cluster.
---
## Welche Frequenz wird verwendet?
Ein DX-Cluster-Spot benötigt eine eindeutige Frequenz. KST4Contest verwendet dafür dieselbe QRG-Erkennung wie die Benutzerliste und die übrigen bandbezogenen Funktionen.
@@ -171,12 +187,11 @@ Ein Spot enthält:
- das konfigurierte Spotter-Rufzeichen,
- die normalisierte Frequenz,
- das Rufzeichen der erkannten Station,
- das vollständige sichtbare Rufzeichen der erkannten oder ausgewählten Station,
- den Locator,
- Flugzeug-Scatter-Informationen, falls vorhanden,
- die aktuelle UTC-Zeit.
Wenn für die Station aktuelle Aircraft-Scatter-Informationen vorliegen, kann KST4Contest diese als zusätzliche AP-Information in den Kommentar des Spots aufnehmen.
Bei automatisch erzeugten Richtungs-Spots kann KST4Contest bis zu zwei aktuelle AirScout-Einträge als zusätzliche AP-Information in den Kommentar aufnehmen. Fehlende AirScout-Daten verhindern den Spot nicht. Ein manuell über die Stationskarte ausgelöster Spot verwendet den Locator der ausgewählten Station ohne diese optionale Ergänzung.
---
@@ -193,7 +208,7 @@ Prüfe:
- Blockiert eine Firewall die Verbindung?
- Ist im Logger das DX-Cluster-Fenster beziehungsweise die Bandmap aktiviert?
### Testspot funktioniert, aber reale Spots fehlen
### Testspot funktioniert, aber automatische Spots fehlen
Dann funktioniert die Verbindung grundsätzlich. Für die betreffende Chat-Situation war wahrscheinlich mindestens eine fachliche Bedingung nicht erfüllt:
@@ -205,6 +220,10 @@ Dann funktioniert die Verbindung grundsätzlich. Für die betreffende Chat-Situa
KST4Contest sendet absichtlich nicht jede gefundene Frequenz an den Logger. Andernfalls würde aus einer Arbeitserleichterung sehr schnell eine lokale Spot-Schleuder.
### Manuell ausgelöster Spot fehlt
Prüfe, ob auf der Karte eine Station ausgewählt ist und für sie eine verwendbare QRG vorliegt. Der lokale Server muss aktiviert und mindestens ein Client verbunden sein. Die Geometrie einer gerichteten Nachricht, maximaler QRB und Antennen-Öffnungswinkel sind für die manuelle Auslösung keine Voraussetzungen.
### Der Spot erscheint auf dem falschen Band
Prüfe zuerst, welche Frequenzen für die betreffende Station innerhalb der letzten 30 Minuten erkannt wurden. Bei einer relativen Angabe hat dieser Stationskontext Vorrang vor dem globalen Fallback.
+19 -19
View File
@@ -205,20 +205,6 @@ Worked-, NOT-QRV- und Großfeldinformationen werden in der internen SQLite-Daten
Ein manueller Reset unter **Workedstn database** entfernt sämtliche Worked-Markierungen, NOT-QRV-Tags und gespeicherten Worked-Großfelder. Die bekannten Rufzeichenzeilen bleiben dabei in der Datenbank erhalten. Einzelheiten: [Worked Station Database Settings](de-Konfiguration#worked-station-database-settings-gearbeitete-stationen-datenbank).
---
## NOT-QRV-Tags (ab v1.2)
Wenn eine Station mitteilt, dass sie auf einem bestimmten Band nicht QRV ist, kann dies manuell markiert werden:
1. Station in der Benutzerliste auswählen.
2. Rechtsklick → NOT-QRV für das entsprechende Band setzen.
Diese Tags werden in der internen Datenbank gespeichert und bleiben nach einem Neustart von KST4Contest erhalten. Zurücksetzen über die Einstellungen möglich.
**Nutzen**: Verhindert wiederholte Sked-Anfragen auf Bändern, auf denen die Station nicht QRV ist schont sowohl die eigenen Nerven als auch die der Gegenstation.
---
## Richtungsfilter (Direction Filter)
@@ -253,7 +239,21 @@ Bedienung und Aufbau der Filterleiste: [Benutzeroberfläche Filter](de-Benut
## Farbige PM-Zeilen (ab v1.25)
Neue Privatnachrichten erscheinen in **Rot**. Die Farbe wechselt alle 30 Sekunden über Gelb bis Weiß wie ein Regenbogen-Fade. So ist auf einen Blick erkennbar, wie aktuell eine Nachricht ist.
Neue eingehende Privatnachrichten werden in mehreren grünen Altersstufen hervorgehoben. Mit zunehmendem Alter wird das Grün schrittweise gedämpfter:
| Alter der Nachricht | Darstellung |
|---|---|
| bis einschließlich 30 Sekunden | erste grüne Stufe |
| 31 bis 60 Sekunden | zweite grüne Stufe |
| 61 bis 90 Sekunden | dritte grüne Stufe |
| 91 bis 120 Sekunden | vierte grüne Stufe |
| 121 bis 180 Sekunden | fünfte grüne Stufe |
| 181 bis 300 Sekunden | sechste grüne Stufe |
| ab 301 Sekunden | normale Tabellenfarbe |
Die Tabelle aktualisiert die Altersdarstellung alle fünf Sekunden. Ein Grenzübergang kann deshalb erst beim nächsten Aktualisierungslauf sichtbar werden. Nach fünf Minuten bleibt keine Altersklasse an der Zeile haften; auch wiederverwendete oder leere Tabellenzeilen kehren zu ihrem normalen Stil zurück.
Eigene Nachrichten erhalten weiterhin eine separate Hervorhebung und verwenden nicht die grüne Altersskala.
*(Idee von IU3OAR, Gianluca Costantino danke!)*
@@ -300,9 +300,9 @@ Gleichzeitiger Login in **zwei Chat-Kategorien** (z. B. 144 MHz und 432 MHz). Be
## Dark Mode (ab v1.26)
Aktivierbar über: **Window → Use Dark Mode**
Aktivierbar über **Windows → Use dark mode design**. Mit **Windows → Use default mode design** wird wieder auf das normale helle Farbschema umgeschaltet.
Für individuelle Farbanpassungen: CSS-Datei bearbeiten (Pfad in den Programmunterlagen).
Die grüne Altersskala der Privatnachrichten bleibt in beiden Darstellungen erhalten. Textfarbe, normale Tabellenfarbe und die separate Hervorhebung eigener Nachrichten folgen dem jeweils geladenen Standarddesign.
---
@@ -320,7 +320,7 @@ Für ausgewählte Stationen in der Benutzerliste gibt es direkte Buttons, um das
## Skeds und Sked-Erinnerungen
> Verfügbar ab v1.40; Band-, Rufzeichen- und Win-Test-Behandlung erweitert in Nightly / v1.42.
> Verfügbar ab v1.40; Band-, Rufzeichen- und Win-Test-Behandlung erweitert in v1.42.
Ein Sked ist mehr als eine Erinnerung an eine Uhrzeit. Er muss während des laufenden Contestbetriebs rechtzeitig sichtbar werden, die vereinbarte Station priorisieren und sofern gewünscht die Gegenstation noch einmal an den Termin erinnern.
@@ -994,4 +994,4 @@ Die Prüfung verwendet immer den **primären Bildschirm**. Sie stellt nicht die
Die automatische Größenbegrenzung gilt derzeit außerdem nur für das Hauptfenster. Das Einstellungsfenster, das separate Cluster- und QSO-Monitorfenster sowie weitere Zusatzfenster verwenden weiterhin ihre jeweils gespeicherten Größen, ohne dieselbe zusätzliche Prüfung gegen den primären Bildschirm.
Im Klartext: Die Schutzfunktion verhindert vor allem, dass das zentrale Hauptfenster nach einem Wechsel auf einen kleineren Bildschirm unbenutzbar startet. Sie ist keine vollständige Verwaltung aller Fensterpositionen in einem wechselnden Mehrmonitor-Setup.
Im Klartext: Die Schutzfunktion verhindert vor allem, dass das zentrale Hauptfenster nach einem Wechsel auf einen kleineren Bildschirm unbenutzbar startet. Sie ist keine vollständige Verwaltung aller Fensterpositionen in einem wechselnden Mehrmonitor-Setup.
+2 -1
View File
@@ -52,7 +52,7 @@ Download, unterstützte Betriebssysteme und Installationswege sind im Kapitel [I
Dieses Handbuch unterscheidet zwischen der veröffentlichten Stable-Version und dem aktuellen Entwicklungsstand.
Die derzeit veröffentlichte Stable-Version ist **v1.41.1**. Funktionen oder Änderungen, die erst im Entwicklungsstand für v1.42 enthalten sind, werden ausdrücklich als **Nightly / v1.42** gekennzeichnet. Fehlt eine solche Kennzeichnung, bezieht sich die Beschreibung auf die Stable-Version.
Die derzeit veröffentlichte Stable-Version ist **v1.42.0**. Funktionen oder Änderungen, die erst mit einer bestimmten Version hinzugekommen sind, werden ausdrücklich als **ab v1.42** gekennzeichnet. Funktionen, die es nur im aktuellen Entwicklungsstand gibt, sind als **Nightly** gekennzeichnet. Fehlt eine solche Kennzeichnung, bezieht sich die Beschreibung auf die Stable-Version.
- [Stable, Beta und Nightly herunterladen](https://kst4contest.hamradioonline.de/download/)
- [Veröffentlichte GitHub Releases](https://github.com/praktimarc/kst4contest/releases)
@@ -68,6 +68,7 @@ Für einen Contest ist grundsätzlich die Stable-Version zu empfehlen. Nightly-B
|---|---|
| [Installation](de-Installation) | ON4KST-Account, Download, Installation und Updates |
| [Konfiguration](de-Konfiguration) | Login, Station, Bänder, Benutzeroberfläche und externe Schnittstellen |
| [Contest-Workflow](de-Contest-Workflow) | Vorstartprüfung, CQ-Betrieb, Kandidatenauswahl, Skeds, Logeintrag und Bandwechsel |
| [Log-Synchronisation](de-Log-Synchronisation) | Simplelogfile, UCXLog, N1MM+, QARTest, DXLog.net und Win-Test |
| [AirScout-Integration](de-AirScout-Integration) | Verbindung zu AirScout und Auswertung von Aircraft-Scatter-Zeiten |
| [DX-Cluster-Server](de-DX-Cluster-Server) | Übergabe erkannter Möglichkeiten an das Logprogramm |
+4 -4
View File
@@ -4,7 +4,7 @@
Nach dem ersten Start öffnet sich das **Einstellungsfenster** dieses ist der zentrale Ausgangspunkt für alle Konfigurationen. Es empfiehlt sich, das Einstellungsfenster während des Betriebs geöffnet zu lassen (z. B. um den Beacon schnell ein- und auszuschalten).
> **Wichtig**: Nach jeder Änderung unbedingt **„Save Settings"** klicken! Die Einstellungen werden unter Linux in `~/.praktikst/preferences.xml` und unter Windows in `%USERPROFILE%\.praktikst\preferences.xml` (bzw. `C:\Users\<Benutzername>\.praktikst\preferences.xml`) gespeichert. Ab v1.21 werden auch Fenstergrößen und Divider-Positionen beim Speichern gesichert.
> **Wichtig**: Nach jeder Änderung unbedingt **„Save Settings"** klicken! Die Einstellungen werden unter Linux und macOS in `~/.praktiKST/preferences.xml` und unter Windows in `%USERPROFILE%\.praktiKST\preferences.xml` (bzw. `C:\Users\<Benutzername>\.praktiKST\preferences.xml`) gespeichert. Ab v1.21 werden auch Fenstergrößen und Divider-Positionen beim Speichern gesichert.
---
@@ -472,7 +472,7 @@ Die Eingabe darf ein sichtbares KST-Suffix oder portable Bestandteile enthalten.
Die Änderung der Liste wirkt sofort. Zum dauerhaften Speichern anschließend **Save Settings** verwenden. Die Basisrufzeichen werden in der `preferences.xml` gespeichert und beim nächsten Programmstart wiederhergestellt.
> Die Zusammenführung der KST-Suffixe über das Basisrufzeichen ist im Nightly beziehungsweise ab v1.42 enthalten.
> Die Zusammenführung der KST-Suffixe über das Basisrufzeichen ist ab v1.42 enthalten.
Weitere Hintergründe und die Abgrenzung zum Nachrichtenrouting: [QSO-Monitoring](de-Funktionen#qso-monitoring-ab-v131).
---
@@ -871,7 +871,7 @@ Anzeige und Herleitung: [Gearbeitete Rufzeichen, neue Bänder und neue Großfeld
## Dark Mode (ab v1.26)
Umschaltbar über das Menü: **Window → Use Dark Mode**. Die Farben können über CSS individuell angepasst werden.
Der Dark Mode wird über **Windows → Use dark mode design** aktiviert. Mit **Windows → Use default mode design** wird wieder das normale helle Farbschema geladen.
---
@@ -879,6 +879,6 @@ Umschaltbar über das Menü: **Window → Use Dark Mode**. Die Farben können ü
Nach **jeder** Änderung **„Save Settings"** klicken! Ohne Speichern gehen alle Änderungen beim nächsten Start verloren.
- Speicherort: unter Linux `~/.praktikst/preferences.xml` und unter Windows `%USERPROFILE%\.praktikst\preferences.xml` (bzw. `C:\Users\<Benutzername>\.praktikst\preferences.xml`)
- Speicherort: unter Linux und macOS `~/.praktiKST/preferences.xml` und unter Windows `%USERPROFILE%\.praktiKST\preferences.xml` (bzw. `C:\Users\<Benutzername>\.praktiKST\preferences.xml`)
- Ab v1.21: Fenstergrößen und Divider-Positionen werden ebenfalls gespeichert.
- Bei Problemen: Konfigurationsdatei löschen → KST4Contest erstellt eine neue mit Standardwerten.
+7 -1
View File
@@ -361,4 +361,10 @@ Dabei ist insbesondere zu beachten:
- Stationsbezogene Variablen bleiben sichtbar, wenn keine Station ausgewählt ist.
- Der eingefügte Text wird nicht automatisch auf seine betriebliche Richtigkeit geprüft.
Das Sendfeld bleibt deshalb nach dem Einfügen eines Shortcuts oder Snippets bearbeitbar. Die Variablen vermeiden wiederholte Eingaben; die abschließende Prüfung bleibt beim Operator.
Das Sendfeld bleibt deshalb nach dem Einfügen eines Shortcuts oder Snippets bearbeitbar. Die Variablen vermeiden wiederholte Eingaben; die abschließende Prüfung bleibt beim Operator.
---
## Verwendung im Contest
Shortcuts, Snippets und Variablen sind einzelne Werkzeuge innerhalb des laufenden Betriebs. Ihr Zusammenspiel mit CQ-Betrieb, Stationsauswahl, Skeds, QRG-Wechseln und Log-Synchronisation ist unter [Contest-Workflow mit KST4Contest](de-Contest-Workflow) beschrieben.
+7 -4
View File
@@ -8,10 +8,9 @@ Published Stable versions and their application packages are available under [Gi
---
## v1.42 Nightly / in development
## v1.42.0 (2026-08-22)
> Status of this section: 14 August 2026.
> v1.42 is not a published Stable release yet. Further changes may be added before release.
**Shared band context, session-based ON4KST connection and signed macOS packages**
v1.42 brings several previously separate calculations together. Band information, Worked status, NOT-QRV marks, callsign suffixes and frequencies are now used more consistently by the user list, station map, priority calculation and external interfaces.
@@ -71,7 +70,7 @@ v1.42 brings several previously separate calculations together. Band information
- **Exact sked targets:** The timeline and automatic reminders use the complete visible KST callsign. A sked for `DN9APW-2` is not accidentally sent to another variant of the same base callsign.
- **Reworked beacon and automatic replies:** Both chat categories use one shared timer while retaining separate enable switches and message texts. The minimum permitted interval is two minutes and message texts are limited to 120 characters. The stored beacon state is restored from the configuration at startup.
- **Reworked beacon and automatic replies:** Both chat categories use one shared timer while retaining separate enable switches and message texts. The minimum permitted interval is one minute and message texts are limited to 120 characters. The stored beacon state is restored from the configuration at startup.
- **Central variable resolution:** Message variables used by beacons, shortcuts, snippets and other generated text are processed by one shared resolver.
@@ -93,6 +92,8 @@ v1.42 brings several previously separate calculations together. Band information
- **Message-bus diagnostics:** Correctly processed ON4KST frames are no longer reported additionally as `Critical, detected unhandled Chatmessage`. Only genuinely unknown frames reach the fallback diagnostic branch.
- **Password in diagnostic output:** The ON4KST password is no longer written in plain text to the console or error log during connection setup.
- **Long-running station-selection failure:** Chat members managed by the message thread have been decoupled from the JavaFX view. Simultaneous data and table updates therefore no longer cause broken selection models or concurrent-modification problems after longer runtimes.
- **No phantom chat members from UM3:** Historical or additional server messages no longer create user-list entries for stations which are not actually logged into the chat.
@@ -137,6 +138,8 @@ v1.42 brings several previously separate calculations together. Band information
- More detailed configuration of station height, frequency and K factor is being tracked in [Issue #74](https://github.com/praktimarc/kst4contest/issues/74).
The published version is available as [Release v1.42.0](https://github.com/praktimarc/kst4contest/releases/tag/v1.42.0).
---
## v1.41.1 (2026-07-08)
+18 -8
View File
@@ -4,7 +4,7 @@
After the first start, the **settings window** opens this is the central starting point for all configuration. It is recommended to keep the settings window open during operation (e.g. to quickly toggle the beacon on and off).
> **Important**: Always click **"Save Settings"** after any change! Settings are stored in `~/.praktikst/preferences.xml` on Linux and in `%USERPROFILE%\.praktikst\preferences.xml` (or `C:\Users\<Username>\.praktikst\preferences.xml`) on Windows. From v1.21 onwards, window sizes and divider positions are also saved when you click Save.
> **Important**: Always click **"Save Settings"** after any change! Settings are stored in `~/.praktiKST/preferences.xml` on Linux and macOS and in `%USERPROFILE%\.praktiKST\preferences.xml` (or `C:\Users\<Username>\.praktiKST\preferences.xml`) on Windows. From v1.21 onwards, window sizes and divider positions are also saved when you click Save.
---
@@ -40,13 +40,23 @@ After a change, click **Save Settings** and restart KST4Contest. Band columns an
### Antenna Beamwidth
Enter a realistic value for your antenna's beamwidth (in degrees). This value is used for the [Sked Direction Highlighting](en-Features#sked-direction-highlighting). A test value of 50° has proven effective; DM5M uses quads with 69°.
Enter the complete horizontal beamwidth of the local antenna in degrees. KST4Contest applies half of this value to either side of the selected or derived antenna direction. A configured value of `70°` therefore produces a corridor of `±35°`.
> **Do not** enter fantasy values the direction calculations will become useless.
The value is used for:
- the QTF filter in the user list;
- the display of the local antenna corridor; and
- the assumed beamwidth of a remote station when [deriving directional opportunities](en-Features#directional-opportunities-from-directed-messages).
The final use is deliberately an approximation. ON4KST transmits neither the antenna being used nor its beamwidth. KST4Contest therefore uses the local value as a practical assumption for the remote station.
Choose a realistic value for the actual station setup. A value which is too large produces many geometrical matches with little practical meaning. A value which is too small may hide useful directional opportunities.
### Default Maximum QRB
Maximum distance (in km) for which direction warnings should be triggered. A realistic value for DM5M is 900 km. Stations farther away are ignored for highlighting purposes.
Enter the maximum distance in kilometres within which KST4Contest should consider directional opportunities. The relevant distance is between the local station and the sender of the directed message, not between sender and receiver.
If the sender is farther away, the situation is neither highlighted nor forwarded as an automatic directional opportunity to the local DX Cluster server, even if the calculated angle would match.
### Path Analysis and Link Budget
@@ -765,7 +775,7 @@ Data handling and QRG selection: [Log Synchronisation Win-Test](en-Log-Sync#
---
## PSTRotator Settings (from v1.31)## PSTRotator Settings (from v1.31, fully configurable from v1.40)
## PSTRotator Settings (from v1.31, fully configurable from v1.40)
KST4Contest can set an antenna direction through the PSTRotator UDP interface and use the current position reported by PSTRotator as the local QTF.
@@ -874,7 +884,7 @@ The entered value may contain a visible KST suffix or portable components. KST4C
Changes to the list take effect immediately. Press **Save Settings** afterwards to retain them. The base callsigns are stored in `preferences.xml` and restored at the next program start.
> Base-callsign monitoring across KST suffixes is included in Nightly / v1.42.
> Base-callsign monitoring across KST suffixes is included from v1.42 onwards.
Further background and the distinction from message routing: [QSO Sniffer](en-Features#qso-sniffer-from-v131).
@@ -916,7 +926,7 @@ Display and derivation: [Worked Callsigns, New Bands and New Grid Squares](en-Fe
## Dark Mode (from v1.26)
Toggle via the menu: **Window → Use Dark Mode**. The colors can be individually customized via CSS.
Enable Dark Mode through **Windows → Use dark mode design**. Use **Windows → Use default mode design** to restore the normal light colour scheme.
---
@@ -924,6 +934,6 @@ Toggle via the menu: **Window → Use Dark Mode**. The colors can be individuall
Click **"Save Settings"** after **every** change! Without saving, all changes will be lost on the next start.
- Storage location: `~/.praktikst/preferences.xml` on Linux and `%USERPROFILE%\.praktikst\preferences.xml` (or `C:\Users\<Username>\.praktikst\preferences.xml`) on Windows
- Storage location: `~/.praktiKST/preferences.xml` on Linux and macOS and `%USERPROFILE%\.praktiKST\preferences.xml` (or `C:\Users\<Username>\.praktiKST\preferences.xml`) on Windows
- From v1.21: Window sizes and divider positions are also saved.
- If you encounter problems: delete the configuration file → KST4Contest will create a new one with default values.
+277
View File
@@ -0,0 +1,277 @@
# Contest Workflow with KST4Contest
> You are reading the English version | [Deutsche Version](de-Contest-Workflow)
KST4Contest brings chat activity, station selection, known QRGs, worked status, skeds, aircraft scatter timing and other station data together in one interface. Its value does not come from one individual indicator, but from the way this information works together during an active contest.
This page describes a complete operating workflow. Individual functions and their technical limitations remain documented under [Features](en-Features), [User Interface](en-User-Interface), [Log Synchronisation](en-Log-Sync) and [AirScout Integration](en-AirScout-Integration).
---
## Purpose and Limitations
KST4Contest is intended to reduce the time between recognising an opportunity and attempting the actual QSO.
The programme can show, among other things:
- which stations are active,
- on which bands and QRGs they were most recently detected,
- which stations have already been worked,
- which additional bands may still be available,
- which candidates match the current antenna direction,
- when an aircraft scatter window is expected, and
- which station is currently working in a direction useful to the local station.
These remain decision aids. A high priority score is not a QSO probability. An aircraft geometry rated at 100% by AirScout does not guarantee a contact either. The operator must still decide whether a QRG is actually clear, whether the remote station is listening and whether the path works under the current conditions.
---
## Before the Contest
The important settings should be checked before the first interesting sked appears.
### Basic Configuration
Check at least:
- the local callsign, password and locator,
- the primary chat category,
- login and settings for the second category if it is used,
- locally enabled bands,
- antenna beamwidth,
- maximum useful distance,
- `MYQRG` and, where applicable, `SECONDQRG`,
- log synchronisation, and
- the required shortcuts, snippets and message variables.
Antenna beamwidth and maximum distance depend on the station. At DM5M, for example, the actual antenna system is represented by a beamwidth of 69° and a maximum distance of 900 km. These are not general recommended values.
Use **Save Settings** for permanent changes. After connecting, the `LINK` indicator should be green. Only then have login and user-list synchronisation been completed.
### Automatic Replies
The automatic QRG reply is part of the active contest workflow. It answers repeated QRG requests and removes some routine work from the chat operator.
This is different from the general automatic reply. The general reply can react to all incoming requests and is mainly useful while the station is temporarily not QRV or does not want to take part in sked operation. It avoids unnecessary follow-up work for both the local and requesting stations.
### Optional Connections
Enable only interfaces which are actually required and have already been tested:
- logging software or Simplelogfile,
- TRX synchronisation,
- AirScout,
- PSTRotator,
- Win-Test sked handover, and
- the local DX Cluster server.
A contest is not an ideal time to investigate radio conditions and a newly enabled network interface at the same time.
---
## Basic Contest Cycle
The normal operating cycle repeats:
1. Call CQ or run an agreed sked.
2. Monitor chat activity, the priority list, map and AP timeline.
3. Select a suitable candidate.
4. Decide between the local and remote QRG.
5. Attempt the QSO.
6. Log a successful contact immediately.
7. Check for another band opportunity.
8. Mark a meaningful failed attempt with **Sked fail**.
9. Return to CQ operation or continue with the next candidate.
KST4Contest keeps the required information together between these steps. Changing frequency, calling, listening and making the actual decision deliberately remain operator tasks.
---
## CQ Operation
During operation on a mainly fixed CQ frequency, `MYQRG` and `SECONDQRG` should match the frequencies actually in use. Enabled TRX synchronisation can update `MYQRG` automatically. Without an automatic source, the value must be maintained manually.
The beacon can publish the current QRG, locator and antenna direction in the chat at regular intervals. Its variables are evaluated again for every transmission.
Disable the beacon while scanning across several frequencies. An automatically published QRG is useful only while it is still correct.
Shortcuts and snippets should cover the messages required regularly, for example:
- asking a station to listen on the local QRG,
- asking for the remote QRG,
- announcing a move to the remote QRG,
- confirming antenna direction, and
- proposing a sked.
Further details are available under [Macros and Variables](en-Macros-and-Variables).
---
## Selecting Candidates
The user list can be reduced to the current operating situation by combining QTF, QRB, Worked, band, activity, New Bands, Tropo and AirScout filters.
The priority list and AP timeline add further context:
- The priority score combines several known criteria.
- The AP timeline arranges skeds and expected aircraft scatter opportunities by time.
- The station map shows geographical position, antenna direction and radio path.
- Worked and band status help prevent unnecessary duplicate work.
![Priority list and evaluation information](priority_score_overview.png)
The score is a sorting aid. Before attempting a contact, continue to check the callsign, category, band, QRG, direction, distance and age of the underlying information.
A deliberate selection in the user list, priority list, timeline or map selects the concrete chat member. The complete visible callsign and its chat category are retained. KST4Contest then prepares `/cq CALLSIGN` in the send field.
---
## Using the Local or Remote QRG
When a useful propagation direction is detected and a suitable aircraft is available for a candidate, the remote station is often first asked to listen on the local QRG. This is particularly useful while CQ operation is already running there and the station can receive immediately without another change.
If the remote station does not respond, its own QRG is more suitable or it cannot use the requested frequency, the local station changes frequency. KST4Contest keeps the most recently detected QRGs available, so the operator does not have to search the complete chat history again.
A deliberate attempt on the QRG of a sked partner is also part of the normal workflow. The objective is not to remain on the local QRG at all costs, but to use the available opportunity with as little delay as possible.
Before changing frequency, check at least:
- the correct band,
- the complete target callsign,
- the remote stations QRG,
- antenna direction,
- the expected aircraft scatter window, and
- whether the QRG is clear.
---
## Using Directional Opportunities
A directed message between two other stations may indicate that the senders antenna is pointing approximately towards the receiver. If this direction is also useful for the local station, KST4Contest temporarily displays the sender in green and bold.
![Directional opportunity displayed in green and bold](direction_opportunity_highlight.png)
The indication appears in the user list and associated views. With an appropriate cluster configuration and a known QRG, the opportunity may additionally be made available through the local DX Cluster.
Several relevant details are therefore already available when the opportunity appears:
- complete callsign,
- locator and direction,
- most recently detected QRG,
- band information,
- AirScout data, and
- the current Reachability or Tropo assessment.
The operator does not have to collect this information first. The remaining decision is whether the opportunity justifies briefly interrupting ongoing CQ operation.
At DM5M, practical evaluation of these opportunistic attempts has so far produced a success rate of approximately 3540%. This value describes the experience of one particular station. It is not a general prediction and depends on factors such as band, distance, station equipment, response time and propagation conditions.
CQ operation or the next sked can continue immediately after the attempt.
---
## Planning and Evaluating Skeds
Enter a sked with the band actually intended for the contact and a realistic time. KST4Contest adds it to its internal sked management and takes it into account for reminders, the timeline and priority calculation.
Skeds are maintained only for the current programme session. They are not a persistent replacement for the contest log or operating notes.
If the Win-Test connection is enabled, KST4Contest additionally attempts to pass the sked to Win-Test. If no usable QRG exists or the band does not match, the internal sked remains available. Only the additional handover may be skipped.
### Failed 100% Aircraft Skeds
If a carefully prepared attempt fails despite an aircraft geometry rated at 100% by AirScout, mark the station with **Sked fail**.
The 100% indication is not a probability of completing the QSO. A failure under these conditions is nevertheless useful operating evidence that the path did not work with the current station configuration and current conditions.
The mark reduces that stations priority for the remainder of the current session. This allows candidates without comparable negative operating evidence to be handled first.
**Sked fail** must not be treated as a permanent statement that the station cannot be worked. Different conditions, another band or a changed station configuration may produce a different result. The mark can be reset and is not retained after restarting the programme.
---
## After Every QSO: Logging and the Next Band
Enter a successful QSO in the connected logging programme immediately. Only then can worked status, band status, filters and priority evaluation be updated in time.
The available detail depends on the log source. Some interfaces provide band, QRG and locator, while simpler sources report only a global worked state.
Immediately after every log entry, check whether another common, locally enabled and unworked band is available for the same station. KST4Contest indicates this through `BAND+` and the stations band information where the available data permits such an evaluation.
This check is useful in every form of multiband operation. The remote station can be coordinated directly to another band with a specific band and frequency before it turns its antenna away or starts another sked.
In plain terms: check the next possible QSO while the remote station is still available and the common context still exists.
If the station is not actually QRV on an indicated band, mark that band as NOT QRV. This removes the unusable opportunity from filters and evaluation instead of allowing it to reappear after every update.
---
## Multi-Category and Multiband Operation
Multi-category operation is not a secondary feature for multiband stations. Its main advantage is that information from two chat categories can be evaluated within one operating workflow.
The benefit is particularly large for:
- single-operator multiband stations,
- multi-operator multiband stations using one central chat coordinator, and
- stations which regularly attempt another band immediately after a QSO.
Worked state, known band activity and band opportunities can be evaluated together. The concrete message target still retains its complete callsign and chat category.
This allows the chat operator to coordinate a station directly from the first QSO to another band without searching again for callsign, QRG and band status. In practical operation, this can produce a very rapid sequence of usable QSO opportunities. This is where multi-category operation provides its greatest workflow advantage.
The same approach remains effective in single-operator operation. The operator still has to change bands personally, but the next useful opportunity is already prepared.
Multi-multi stations with several active chat operators benefit as well. Responsibilities, band changes and requests already in progress must then be coordinated clearly. Several operators having the same information is useful; several contradictory sked requests sent to the same station are not.
---
## Practical Examples
### DM5M: CQ First, More Skeds Later
During the first four to five hours of a VHF/UHF contest, DM5M operates mainly by calling CQ. The chat is monitored, but used only for a small number of deliberate interventions.
Sked activity increases later. Useful propagation directions, suitable aircraft scatter windows, unworked stations and additional band opportunities are then combined deliberately.
A suitable station is first asked to listen on the local QRG. If it does not respond or cannot use that QRG, DM5M moves to the remote stations frequency. Planned attempts directly on a sked partners QRG are also part of the process.
A green and bold directional opportunity may briefly interrupt CQ operation. Calling or sked operation continues immediately after the attempt.
This is a practical example, not a required operating method. Other stations may start arranging skeds considerably earlier, change QRG continuously or make more intensive use of the chat from the beginning.
### G1YBB: Working Directional Opportunities Systematically
G1YBB uses the directional indication particularly consistently. Stations highlighted in green are checked systematically and worked where possible while normal CQ operation continues in parallel.
KST4Contest does not automate the QSO. Its advantage is that QRG, direction, aircraft scatter information and other evaluation data are already available when the opportunity appears. The remaining task is a quick operating decision.
---
## Optional Interfaces in the Workflow
| Interface | Contest task |
|---|---|
| [Log Synchronisation](en-Log-Sync) | Updates worked and band status after a QSO |
| [AirScout](en-AirScout-Integration) | Supplies aircraft scatter candidates and expected time windows |
| [PSTRotator](en-Configuration) | Receives or sets the antenna direction |
| [Win-Test](en-Log-Sync) | Can additionally pass entered skeds to Win-Test |
| [DX Cluster Server](en-DX-Cluster-Server) | Passes detected opportunities to connected logging programmes |
| [Station Map](en-User-Interface) | Shows stations, directions, selection and radio path |
None of these interfaces is mandatory for basic chat operation. Their value appears when they are configured reliably and shorten a specific manual task.
---
## What KST4Contest Does Not Decide
KST4Contest does not decide:
- whether a QRG is actually clear,
- whether the remote station can currently listen,
- whether an aircraft will enable a QSO,
- whether a calculated radio path works under the current conditions,
- whether ongoing CQ operation should be interrupted for an opportunity, or
- which candidate has the greatest value for the current contest strategy.
The programme assembles the available information and keeps it current. The final decision remains with the operator. This is not a limitation of the workflow; it is the part for which we are still operating radios rather than spreadsheets.
+202 -44
View File
@@ -2,50 +2,164 @@
> 🇬🇧 You are reading the English version | 🇩🇪 [Deutsche Version](de-DX-Cluster-Server)
From **version 1.23**, KST4Contest includes a built-in DX cluster server. It sends spots directly to the logging software whenever a direction warning is triggered.
Since version 1.23, KST4Contest has included a local DX Cluster server. It forwards detected directional opportunities and their frequencies to the DX Cluster client of a logging programme.
*(Idea by OM0AAO, Viliam Petrik thank you!)*
The idea came from OM0AAO, Viliam Petrik. Thank you!
---
## What is the Built-in DX Cluster Server For?
## Why Use a Local DX Cluster Server?
When KST4Contest detects that a station is requesting a sked from your direction and a QRG is known, it **automatically generates a DX cluster spot** and feeds it directly to the logging software's cluster client / band map.
Finding an interesting frequency in the chat is only the first step. During a contest, that information needs to reach the place where it can be used immediately: the logging programme and its bandmap.
The logging software then displays the spot in the band map. Clicking the spot sets the transceiver's frequency and mode directly without any manual typing.
KST4Contest therefore combines two pieces of information it already has:
1. A directed chat message can indicate the approximate direction in which the sending station may be pointing its antenna.
2. A frequency for that station may be known from the same message or an earlier one.
When both pieces fit, KST4Contest creates a local DX Cluster spot. The logger can display it in its bandmap and, depending on its own configuration, tune the transceiver to the frequency when the spot is clicked.
In practical terms, the operator does not have to find the information in the chat, read it, remember it and enter it again in the logger. These small interruptions consume a surprising amount of attention during a contest.
---
## Setup
## Automatic Spots from Directional Opportunities
### In KST4Contest
Assume that station A sends a directed message to station B. KST4Contest uses the direction from A to B as an approximation of the current antenna direction of station A. It then checks whether the local station lies inside the assumed antenna corridor as seen from A.
In Preferences → **DX Cluster Server Settings**:
Two directions are compared:
1. Enter the **port** of the internal server (e.g. 7300 or 8000 must match the logging software).
2. Enter a **spotter callsign** **this must be a different callsign than your contest callsign!**
- Reason: Logging programs filter spots from your own callsign as "already worked". If the spotter uses the same callsign, the spots will not be displayed.
3. Enter the **assumed MHz**: For frequency references like ".205" in the chat, KST4Contest needs to decide whether 144.205, 432.205 or 1296.205 is meant. For single-band contests, simply enter the corresponding band centre. Full frequency references like "144.205" or "1296.338" in the chat are always correctly identified.
- the direction from station A to station B;
- the direction from station A to the local station.
### In UCXLog
The **Antenna Beamwidth** configured under the Station settings is the complete angle. Half of that value is applied on either side of the direction A → B. A setting of `70°` therefore produces a corridor of `±35°`.
- Configure a DX cluster server connection:
- Host: `127.0.0.1` (or IP of the KST4Contest computer)
- Port: As configured in KST4Contest
- Password: can be left empty
- Use the **"Send a test message to your log"** button to test the connection.
ON4KST does not supply antenna data for the remote station. KST4Contest therefore also uses the locally configured beamwidth as an approximation for station A. This is not a measurement of the station's actual antenna direction. It is a deliberately simple geometrical assumption.
### In N1MM+
An automatic DX Cluster spot is created only when all of the following conditions are met:
Similar settings:
- Host: `127.0.0.1` (or IP of the KST4Contest computer)
- Port: As configured in KST4Contest
1. A directed message between two other stations has been detected.
2. Valid locators are known for the sender and receiver.
3. The sender is within the configured **Default Maximum QRB** from the local station.
4. The local station lies inside the assumed antenna corridor as seen from the sender.
5. A usable frequency is known for the sender or detected in the current message.
6. The local DX Cluster server is enabled.
When these conditions are met, the spot is created while the message is processed. The green directional highlight shown in parallel remains visible for five minutes and may be extended or removed by later messages.
The calculation does not consider terrain, current propagation or the station's actual operating intention. It identifies a plausible opportunity. The full derivation and a numerical example are available under [Directional Opportunities from Directed Messages](en-Features#directional-opportunities-from-directed-messages).
---
## Manual Spot for the Selected Map Station
A spot can also be triggered deliberately. Select a station on the station map and use **Trigger cluster spot** in the detail panel.
This manual action does not require a previously detected directed message. The maximum QRB and antenna beamwidth also do not decide whether the spot is sent. It requires:
- the local DX Cluster server to be enabled;
- at least one connected DX Cluster client; and
- a usable QRG for the selected map station.
This lets the operator send an already selected station to the bandmap even when the conditions for an automatic directional spot are not present. Map operation is described under [Station Map](en-User-Interface#station-map).
Both automatic and manual spots are sent only to clients connected to KST4Contest. They are not forwarded to a public Internet cluster.
---
## Which Frequency Is Used?
A DX Cluster spot needs an unambiguous frequency. KST4Contest uses the same QRG detection as the user list and the other band-related functions.
Complete frequencies determine their band directly:
```text
144.205
432,088
1296.338
10368.100
```
Relative values contain only the frequency part within a band:
```text
.205
,205
qrg 205
freq is 205
on 205
205 MHz
```
A bare three-digit number such as `205` is not evaluated without frequency-related context. The same applies to `599`, `144` or text such as `worked 210 stations`. This prevents signal reports, band names or QSO totals from being stored as plausible-looking frequencies and later sent to the logger.
For a relative QRG, KST4Contest determines the band in this order:
1. It checks whether a suitable band context has been detected for the same sender during the previous 30 minutes.
2. If several current bands are known, it uses the most recently updated plausible context.
3. Only when no suitable station context exists does it use the band selected under **Fallback band for relative QRG detection**.
Example:
```text
Global fallback: 144 MHz
Most recent complete QRG for the station: 432.088 MHz
New chat value from the same station: .100
Detected QRG: 432.100 MHz
DX Cluster frequency: 432100.0 kHz
```
Without the current 432 MHz context, the same value would use the global fallback and become `144.100 MHz`.
QRG detection runs before the direction and spot checks. If a station mentions its frequency for the first time in the directed message which also triggers a directional opportunity, the resulting spot can already contain that frequency. A newly detected QRG replaces an older value for the station.
The fallback band is a global QRG-detection setting. Its effect is not limited to the DX Cluster server. Configuration, supported bands and related behaviour are described under [Fallback Band for Relative QRG Detection](en-Configuration#fallback-band-for-relative-qrg-detection).
---
## Setting Up KST4Contest
Open the **Notification** tab in Preferences.
![Notification settings and local DX Cluster server](client_settings_window_notification.png)
Configure the following:
1. Enable **Enable the local DX Cluster server …**.
2. Enter a free **TCP port**. The default is `8000`.
3. Select the appropriate band under **Fallback band for relative QRG detection**.
4. Enter a **Spotter callsign**.
The spotter callsign should preferably differ from the contest callsign. Some loggers filter spots which appear to originate from the local station or handle them differently. Using the same callsign is not prohibited by KST4Contest, but it may make a correctly generated spot invisible in the bandmap.
Changes to the enabled state and TCP port take effect immediately while KST4Contest is connected to the chat. Changing the port disconnects existing DX Cluster clients; the logger must reconnect to the new port.
Use **Save Settings** to store the settings permanently in `preferences.xml`.
---
## Setting Up the Logging Programme
Configure the logging programme as a DX Cluster client connected to KST4Contest.
| Setting | KST4Contest and logger on the same computer | Logger on another computer |
|---|---|---|
| Host | `127.0.0.1` | IP address of the KST4Contest computer |
| Port | TCP port configured in KST4Contest | TCP port configured in KST4Contest |
| Login | Any callsign, if the logger requires one | Any callsign, if the logger requires one |
| Password | Not required | Not required |
KST4Contest does not use the login sent by the logger for authentication. The connection is intended for the local computer or a trusted station network.
If the logger runs on another computer, its TCP connection must be allowed through the local firewall on the KST4Contest computer. Do not expose the port directly to the Internet without additional protection.
Several DX Cluster clients can be connected at the same time. Every generated spot is sent to all clients which are currently connected.
---
## Testing the Connection
After the logger's DX cluster client has connected, use **Send test spot** to generate the following entry:
The **Send test spot** button creates the following test entry:
```text
Spotted callsign: DO5AMF
@@ -53,48 +167,92 @@ Comment: Testing DXC-Spot: Congrats, you donated $100!
Frequency: .300 on the configured fallback band
```
With `144 MHz` selected as the fallback band, the spot appears at approximately `144.300 MHz`.
With `144 MHz` selected as the fallback band, the spot therefore appears at approximately `144.300 MHz`.
The comment is a deliberately retained Easter egg. It makes the test entry easy to identify but has no other function. In particular, no donation or other external action is triggered.
The comment is a deliberately retained Easter egg. It only makes the test spot easy to recognise in the logger. No donation or other external action is triggered.
Three conditions must be met before running the test:
1. KST4Contest is connected to the ON4KST chat.
2. The local DX cluster server is enabled.
3. The logging software's DX cluster client is connected to KST4Contest.
2. The local DX Cluster server is enabled.
3. The logging programme's DX Cluster client is connected to KST4Contest.
If no client is connected, KST4Contest displays a corresponding message. A successful test therefore confirms that at least one connected client received the generated spot.
---
## How It Works
## Content of a Generated Spot
A spot is generated when **both** conditions are met:
A spot contains:
1. A **direction warning** has been triggered (station is making a sked in your direction).
2. The **station's QRG is known** (read from the chat or manually entered).
- the configured spotter callsign;
- the normalised frequency;
- the complete visible callsign of the detected or selected station;
- the locator; and
- the current UTC time.
The generated spot contains:
- Station's callsign
- Frequency
- Spot time
For automatically generated directional spots, KST4Contest can add up to two current AirScout entries to the comment. Missing AirScout data does not prevent the spot from being sent. A spot triggered manually from the station map uses the selected station's locator without this optional addition.
The logging software can then display the spot in the band map and tune the TRX to that frequency with a mouse click.
An automatic comment with AirScout information may look like this:
```text
JN49GL , AP: 1min, 100%; 4min, 75%
```
---
## Multi-Computer Setup
## If No Spot Appears
If KST4Contest runs on a separate computer (not the logging computer):
### The Test Spot Does Not Reach the Logger
- Host in the logging software: IP of the KST4Contest computer (not `127.0.0.1`)
- Same configuration as for the QSO UDP broadcast packets (see [Log Synchronisation](en-Log-Sync))
Check:
- Is KST4Contest connected to the chat?
- Is the local DX Cluster server enabled?
- Does the logger use the same TCP port?
- Does the logger use `127.0.0.1` when both programmes run locally?
- Is a firewall blocking the connection?
- Is the DX Cluster window or bandmap enabled in the logger?
### The Test Works, but Automatic Spots Are Missing
The TCP connection is then working in principle. At least one condition for the relevant chat situation was probably not met:
- no directed message between two other stations;
- missing locator;
- sender outside the maximum QRB;
- direction outside the configured beamwidth;
- no detected frequency.
KST4Contest deliberately does not send every frequency it finds to the logger. Otherwise, a feature intended to reduce distraction would quickly become a local spot generator with rather too much enthusiasm.
### A Manually Triggered Spot Is Missing
Check that a station is selected on the map and that it has a usable QRG. The local server must be enabled and at least one client must be connected. Directional-message geometry, maximum QRB and beamwidth are not prerequisites for the manual action.
### The Spot Appears on the Wrong Band
First check which frequencies were detected for the station during the previous 30 minutes. For a relative value, this station context takes priority over the global fallback.
If no current station context exists, check **Fallback band for relative QRG detection**. The fallback is used only when the band cannot be determined from a complete frequency or the sender's current context.
### The Logger Hides the Spot
Try a spotter callsign which differs from the contest callsign. Depending on the logger, spots from the local callsign may be filtered or handled specially. KST4Contest itself does not require the two callsigns to differ.
---
## Tested Logging Software
## Tested Logging Programmes
- **UCXLog**
- **N1MM+**
The interface has been used with:
Further test reports are welcome please send by email to DO5AMF.
- UCXLog
- N1MM+
Other loggers may work if they support a normal TCP connection to a DX Cluster server and accept conventional `DX de ...` spot lines.
Related reference pages:
- [User Interface](en-User-Interface)
- [Features](en-Features)
- [Configuration](en-Configuration)
+110 -25
View File
@@ -6,45 +6,116 @@ Overview of all main features of KST4Contest.
---
## Sked Direction Highlighting
## Directional Opportunities from Directed Messages
One of the core features: when a station makes a sked request **towards your direction**, it is highlighted **green and bold** in the user list.
The ON4KST chat shows which station directs a message to which other station. It does not transmit the actual antenna direction. A directed message can nevertheless provide a useful indication during a contest: a station requesting, answering or preparing a sked will normally point its antenna at least approximately towards the station being addressed.
### How does it work?
KST4Contest therefore evaluates directed messages between two other stations. The message does not have to be explicitly identified as a sked request. The relevant information is the sender, receiver and their locators.
The calculation is based on the following logic:
### How Is the Direction Derived?
- When station A sends a sked request to station B, it is assumed that A is pointing its antenna towards B.
- If the resulting direction from A to your own station is within half the beamwidth of your own antenna, A is highlighted.
Assume that station A sends a directed message to station B:
**Example** (beamwidth 69°, half-angle 34.5°):
1. KST4Contest calculates the direction from station A to station B.
2. This direction is used as the likely antenna direction of station A.
3. KST4Contest then calculates the direction from station A to the local station.
4. The angular difference is compared with half of the configured antenna beamwidth.
5. Station A must also be within the configured maximum QRB.
| Situation | Result for DO5AMF in JN49 |
A configured beamwidth of `70°` therefore produces an assumed corridor of `35°` on either side of the direction from station A to station B.
| Example | Result |
|---|---|
| Sked from F5FEN → DM5M | ✅ Highlighted (F5FEN points towards DM5M, close to JN49) |
| Sked from DM5M → F5FEN | ✅ Highlighted (DM5M replies towards F5FEN) |
| F1DBN is uninvolved | ❌ No highlighting |
| DO5AMF/P (different location) | No highlighting for sked reply |
| Direction A → B: `120°`, direction A → local station: `145°` | Angular difference `25°`: directional opportunity detected |
| Direction A → B: `120°`, direction A → local station: `165°` | Angular difference `45°`: outside the assumed corridor |
| Locator of A or B is missing | Direction cannot be calculated |
| A is outside the maximum QRB | No directional opportunity |
The calculation does not include topographic path calculations this is a deliberate simplification. It may be added in a future version.
### What Is Shown in the User List?
> Configuration: [Configuration Antenna Beamwidth](en-Configuration#antenna-beamwidth)
When a directional opportunity is detected, the sender's callsign appears in green and bold in the user list. Evening mode uses a lighter green. The receiver is not marked merely because it received the message; a reply in the opposite direction is evaluated as a separate message and therefore as a new case.
![Detected directional opportunity in the user list](direction_opportunity_highlight.png)
In the screenshot, DF0GEB sent a directed message to DN9APW and received a reply. KST4Contest detected the directional opportunity and highlighted DN9APW in the user list. The map is shown for context: the local station lies between the two stations and therefore receives the indication.
The mark remains visible for five minutes after the most recent matching message. Another matching message from the same station restarts that period. If the station sends another directed message which no longer satisfies the direction conditions, the mark is removed immediately.
If simple sound notifications are enabled, KST4Contest also plays a short indication when the directional opportunity is first detected. Further matching messages do not repeat the same sound while the station is already marked.
### What Does the Mark Mean and What Does It Not Mean?
The calculation is a geometric derivation. It does not prove that station A is actually pointing its antenna towards station B. It also does not include terrain, current propagation, the real antenna pattern of the remote station or its rotator position.
ON4KST does not provide the beamwidth of the remote station. KST4Contest therefore uses the value configured for the local antenna as an approximation for station A. A value which is too large produces more possible directional opportunities with less practical meaning. A value which is too small may hide useful situations.
In plain terms: the green mark is a reasoned indication of a possible opportunity. It is neither a propagation forecast nor a guarantee of completing a QSO.
Configuration:
- [Antenna Beamwidth](en-Configuration#antenna-beamwidth)
- [Default Maximum QRB](en-Configuration#default-maximum-qrb)
---
## Sked Direction Spots (Built-in DX Cluster)
## Forwarding as a DX Cluster Spot
From **v1.23**: Direction warnings are forwarded as DX cluster spots to the logging software when a QRG is known. Details: [DX Cluster Server](en-DX-Cluster-Server).
Since version 1.23, KST4Contest can forward a detected directional opportunity to the DX Cluster client of a logging programme. The local DX Cluster server must be enabled and a usable frequency must be known for the sender.
The frequency may come from an earlier message or may be detected for the first time in the message which triggers the opportunity. In both cases it is available when KST4Contest checks whether it can create a spot. The programme therefore does not forward every QRG found in the chat. Automatic spots require a geometrically matching directed message.
The five-minute user-list mark and the DX Cluster spot use the same direction calculation but have different lifetimes. The mark remains visible temporarily. The spot is generated immediately while the matching message is processed.
Setup, frequency handling and limitations: [Built-in DX Cluster Server](en-DX-Cluster-Server).
---
## QRG Detection (QRG Reading)
## QRG Detection
KST4Contest processes every line of text flowing through the channel and automatically extracts **frequency references**. These are displayed in the user list in the **QRG column**.
Frequencies are rarely written in a consistent form in the ON4KST chat. A station may first mention `432.088`, later write only `.100`, and use `qrg 120` in another message. The context is usually obvious to a human reader. Software still has to distinguish whether `120` is a frequency, a time, a distance or something else entirely.
Recognised formats: `144.205`, `432.088`, `.205` (with configured band assumption), etc.
KST4Contest therefore evaluates the text of every public and directed chat message. A detected QRG is assigned to the sender and displayed in the user list's **QRG column**. The column shows the most recently detected frequency with at least three decimal places. A value stored internally as `144.21` is therefore displayed as `144.210`.
**Benefit**: Without asking, you can directly look up a station's calling frequency and decide whether a contact is possible.
### Which Formats Are Recognised?
| Notation | Example | Processing |
|---|---|---|
| Complete frequency | `144.210`, `432,088`, `10368.100` | The frequency determines the band directly. |
| Relative frequency with a dot or comma | `.210`, `,088` | The band is added from the station context or configured fallback. |
| Three-digit frequency with text context | `qrg 210`, `freq is 210`, `on 210`, `210 MHz` | The number is treated as a relative frequency. |
| Three-digit number without frequency context | `210`, `599`, `144` | The number is deliberately not accepted as a QRG. |
The final restriction prevents plausible-looking but incorrect results. With a fallback of `144 MHz`, a signal report of `599` could easily be turned into `144.599 MHz`. The result would be formally valid and operationally useless.
### How Is the Band of a Relative QRG Determined?
KST4Contest uses the following order:
1. If a suitable complete frequency has been detected for the same sender during the previous 30 minutes, KST4Contest uses its band.
2. If several current bands are known, the most recently updated plausible band context is used.
3. If no suitable station context exists, KST4Contest uses the band selected under **Fallback band for relative QRG detection**.
Example: the global fallback is `144 MHz`. A station first mentions `432.088` and writes `.100` a few minutes later. KST4Contest does not add the global fallback. It uses the more recent station context, producing `432.100 MHz`. If another station without previous band information writes `.100`, the result is `144.100 MHz`.
The fallback band really is the last resort. It is selected from the bands supported by KST4Contest and affects all QRG detection, not only the built-in DX Cluster server.
### Where Is a Detected QRG Used?
The most recently detected frequency appears in the user list. Its band context can also affect other functions, including:
- detection of the station's active bands;
- the chat-member score and priority lists;
- band-upgrade hints after a log entry;
- frequency selection for skeds; and
- a DX Cluster spot generated from a directional opportunity.
If the QRG first appears in the same message which triggers a directional opportunity, it is processed before the direction and spot checks. The resulting spot can therefore already use the frequency from that message.
Detection remains a text-based process. KST4Contest cannot prove that the station is still using the stated frequency or that an ambiguous value belongs to a different context. This is precisely why bare three-digit numbers without frequency-related text are no longer accepted.
Configuration and supported fallback bands: [Fallback Band for Relative QRG Detection](en-Configuration#fallback-band-for-relative-qrg-detection).
Use in a logger bandmap: [Built-in DX Cluster Server](en-DX-Cluster-Server).
---
@@ -167,7 +238,21 @@ Operation and layout of the filter bar: [User Interface Filters](en-User-Int
## Coloured PM Rows (from v1.25)
New private messages appear in **red**. The colour fades every 30 seconds from yellow to white like a rainbow fade. This makes it immediately clear how recent a message is.
New incoming private messages use a series of green age highlights. The green becomes progressively more muted as the message gets older:
| Message age | Display |
|---|---|
| up to and including 30 seconds | first green level |
| 31 to 60 seconds | second green level |
| 61 to 90 seconds | third green level |
| 91 to 120 seconds | fourth green level |
| 121 to 180 seconds | fifth green level |
| 181 to 300 seconds | sixth green level |
| from 301 seconds | normal table colour |
The table refreshes the age display every five seconds, so a boundary may become visible only during the next refresh. No age class remains attached after five minutes; reused and empty table rows also return to their normal style.
Messages sent by the local station retain their separate highlight and do not use the green age scale.
*(Idea by IU3OAR, Gianluca Costantino thank you!)*
@@ -214,9 +299,9 @@ Simultaneous login to **two chat categories** (e.g. 144 MHz and 432 MHz). Both c
## Dark Mode (from v1.26)
Toggle via: **Window → Use Dark Mode**
Enable it through **Windows → Use dark mode design**. Use **Windows → Use default mode design** to return to the normal light colour scheme.
For individual colour adjustments: edit the CSS file (path in the program settings).
The green private-message age scale remains available in both designs. Text colour, normal table colour and the separate highlight for locally sent messages follow the selected built-in design.
---
@@ -234,7 +319,7 @@ For selected stations in the user list, there are direct buttons to open the **Q
## Skeds and Sked Reminders
> Available from v1.40; band, callsign and Win-Test handling extended in Nightly / v1.42.
> Available from v1.40; band, callsign and Win-Test handling extended in v1.42.
A sked is more than a reminder tied to a particular time. During a contest, it must become visible early enough, move the agreed station up the priority list and if required remind the remote station as well.
@@ -890,4 +975,4 @@ The check always uses the **primary screen**. It does not restore the previous p
The automatic size restriction currently applies to the main window only. The settings window, the separate cluster and QSO monitor window and other auxiliary windows continue to use their stored sizes without the same additional check against the primary screen.
In plain terms: the protection mainly prevents the central main window from becoming unusable after moving to a smaller display. It is not a complete window-position manager for a changing multi-monitor setup.
In plain terms: the protection mainly prevents the central main window from becoming unusable after moving to a smaller display. It is not a complete window-position manager for a changing multi-monitor setup.
+4 -1
View File
@@ -52,6 +52,8 @@ Downloads, supported operating systems and installation methods are described in
This manual describes the current stable release of KST4Contest.
The currently published Stable version is **v1.42.0**.
Functions that are only available in a Beta or Nightly build are marked accordingly. If no such note is present, the description applies to the stable release.
- [Download Stable, Beta and Nightly builds](https://kst4contest.hamradioonline.de/download/)
@@ -68,6 +70,7 @@ The stable release is normally the appropriate choice for contest operation. Bet
|---|---|
| [Installation](en-Installation) | ON4KST account, downloads, installation and updates |
| [Configuration](en-Configuration) | Login, station, bands, user interface and external connections |
| [Contest Workflow](en-Contest-Workflow) | Pre-start checks, CQ operation, candidate selection, skeds, logging and band changes |
| [Log Synchronisation](en-Log-Sync) | Simplelogfile, UCXLog, N1MM+, QARTest, DXLog.net and Win-Test |
| [AirScout Integration](en-AirScout-Integration) | Connecting AirScout and evaluating aircraft scatter timing |
| [DX Cluster Server](en-DX-Cluster-Server) | Passing detected opportunities to logging software |
@@ -126,4 +129,4 @@ Special thanks go to:
- Philipp (DN9APW) for further development of KST4Contest and the CI/CD infrastructure
- all other testers and contributors who supplied reproducible reports, ideas and corrections
Not every suggestion can be implemented unchanged. Nevertheless, reports from real operation remain an important basis for deciding which problems should be solved first.
Not every suggestion can be implemented unchanged. Nevertheless, reports from real operation remain an important basis for deciding which problems should be solved first.
+275 -90
View File
@@ -2,186 +2,371 @@
> 🇬🇧 You are reading the English version | 🇩🇪 [Deutsche Version](de-Makros-und-Variablen)
KST4Contest offers a flexible system of text snippets, shortcuts and built-in variables that significantly speed up the chat workflow during contests.
KST4Contest distinguishes between shortcut buttons, text snippets and variables. Shortcuts and snippets contain prepared text. Variables add information which may change during operation.
Inserted text remains visible in the send field and can be checked or edited before transmission.
---
## Overview
| Type | Access | Purpose |
| Mechanism | Access | Use |
|---|---|---|
| **Shortcuts** | Button in the toolbar | Quick text insert into the send field |
| **Snippets** | Right-click / Ctrl+1..0 | Text building blocks, optional PM sending |
| **Variables** | Usable in all text fields | Dynamic values (QRG, locator, AP data) |
| **Shortcut** | Button above the send field | Inserts configured text into the send field |
| **Snippet** | Context menu or `Ctrl+1` through `Ctrl+0` | Prepares text for the selected station |
| **Variable** | Placeholder within message text | Inserts current QRG, locator, direction, station or AirScout information |
Shortcuts and snippets store text. Variables supply the corresponding current values.
A shortcut such as
```text
pse sked?
```
always inserts the same text. A shortcut containing
```text
pse call me at MYQRGSHORT
```
instead uses the QRG stored in KST4Contest when the button is pressed.
---
## Shortcuts (Quick-Access Buttons)
## Shortcut Buttons
Configurable in Preferences → **Shortcut Settings**.
Shortcuts are configured under **Preferences → Shortcut Settings**.
- Each configured text creates **one button** in the user interface.
- Clicking a button inserts the text into the **send field**.
- **All variables** can be used in shortcuts and are resolved immediately when inserted.
- Longer texts are also possible.
![Configuration of shortcut buttons and text snippets](client_settings_window_shortcuts.png)
**Tip**: Set up frequently used abbreviations like "pse", "rrr", "tnx", "73" as shortcuts.
Each entry creates one button in the main window. Pressing it appends the configured text to the existing contents of the send field. Text which has already been prepared is not removed.
If a shortcut contains a variable, the variable is resolved when the text is inserted. For example,
```text
pse call me at MYQRGSHORT
```
may become:
```text
pse call me at 144.388
```
The exact entries `MYQRG` and `SECONDQRG` are highlighted as QRG buttons. They insert the current QRG of the first or second chat category respectively.
The shortcut
```text
/SETNAME MYQRG
```
is highlighted as well. Pressing it resolves `MYQRG` and inserts the resulting server command into the send field. The command is not transmitted automatically.
The order of the entries in the settings determines the button order in the main window. Editing, sorting and saving are described under [Configuration Shortcut Settings](en-Configuration#shortcut-settings).
---
## Snippets (Text Building Blocks)
## Text Snippets
Configurable in Preferences → **Snippet Settings**.
Snippets are configured under **Preferences → Snippet Settings**. They are intended primarily for recurring messages to a particular station.
### Access
Snippets can be opened:
- **Right-click** on a callsign in the user list
- **Right-click** in the CQ message table
- **Right-click** in the PM message table
- **Keyboard shortcuts**: `Ctrl+1` to `Ctrl+0` for the first 10 snippets
- by right-clicking a station in the user list,
- by right-clicking a public message,
- by right-clicking a private message, or
- with `Ctrl+1` through `Ctrl+0` for the first ten entries in the snippet list.
### Behaviour with a Selected Callsign
### Using the Context Menu
When a callsign is selected in the user list, the snippet is addressed as a **private message**:
Selecting a station or message will normally have prepared the corresponding `/cq` destination in the send field. A snippet subsequently chosen from the context menu is appended to this text.
```
/CQ CALLSIGN <snippet text>
Existing message text can therefore be extended deliberately.
### Using the Keyboard
A snippet invoked with `Ctrl+1` through `Ctrl+0` replaces the previous contents of the send field with a complete directed message:
```text
/cq CALLSIGN snippet text
```
Then **Enter** can be pressed to send directly even if the send field does not have focus.
The complete visible callsign, including any suffix, is retained. Selecting `9A0BB-70` may therefore produce:
### Hardware Macro Keyboard
```text
/cq 9A0BB-70 pse ur qrg?
```
*(Idea by IU3OAR, Gianluca Costantino)*
KST4Contest also retains the selected station's chat category internally. A snippet for `9A0BB-70` is therefore not accidentally transmitted through the other active chat category.
The key combinations `Ctrl+1` to `Ctrl+0` can be assigned to a programmable macro keyboard. One key press triggers the snippet, another press (mapped to Enter) sends it immediately. In contest operation this saves considerable time.
If no station is selected, or no snippet exists for the selected key combination, nothing is inserted.
### Predefined Default Snippets
The prepared text is not sent automatically:
On first start, some snippets are pre-configured, e.g.:
- `Enter` or **TX** sends the message.
- `Esc` clears the send field.
- `Hi OM, try sked?`
- `I am calling cq ur dir, pse lsn to me at MYQRG`
- `pse ur qrg?`
- `rrr, I move to your qrg nw, pse ant dir me`
### Keyboard Mapping
These can be customised or deleted in the Preferences.
The mapping follows the order of the snippet list:
| Key combination | Entry used |
|---|---:|
| `Ctrl+1` | first entry |
| `Ctrl+2` | second entry |
| … | … |
| `Ctrl+9` | ninth entry |
| `Ctrl+0` | tenth entry |
The key combinations can also be assigned to a programmable macro keyboard. The idea for this method came from IU3OAR, Gianluca Costantino.
KST4Contest does not define a mandatory set of default snippets. The useful texts depend on the station's own contest operation and operating method.
Editing, sorting and saving are described under [Configuration Snippet Settings](en-Configuration#snippet-settings).
---
## Variables
Variables in written texts (snippets, shortcuts, beacon, send field) are replaced by their current values at runtime. Simply type the variable name in **uppercase** in the text.
Variables are reserved placeholders within message text. They must be written in uppercase and are case-sensitive.
### MYQRG
Variables can be used in:
Replaced by the current transceiver frequency.
- shortcuts,
- snippets,
- beacon texts, and
- message text entered or pasted directly into the send field.
- Source: TRX sync via UDP from the logging software (if enabled)
- Fallback: Manually entered value in the MYQRG text field to the right of the send button
- Format: `144.388.03`
Variables in a shortcut or snippet are resolved when the text is inserted into the send field. Variables entered or pasted directly into the send field are resolved immediately before the message is placed in the transmission queue.
**Example**: `calling cq at MYQRG``calling cq at 144.388.03`
Station-specific variables always use the currently selected station. KST4Contest does not derive this station from a `/cq` destination entered manually in the message text.
### MYQRGSHORT
---
Like MYQRG, but only the first 7 characters.
## Global Variables
- Format: `144.388`
Global variables do not require a selected remote station.
**Example**: `qrg: MYQRGSHORT``qrg: 144.388`
| Variable | Replacement value |
|---|---|
| `MYQRG` | current QRG of the first or primary chat category |
| `MYQRGSHORT` | first seven characters of `MYQRG` |
| `SECONDQRG` | current QRG of the second chat category |
| `MYLOCATOR` | complete locator configured for the local station |
| `MYLOCATORSHORT` | first four characters of the local locator |
| `MYCALL` | configured local callsign |
| `MYQTF` | current antenna direction as a numeric value in degrees |
### MYLOCATOR
For example,
Replaced by your own Maidenhead locator (6 characters).
```text
cq at MYQRGSHORT, qtf MYQTF, loc MYLOCATOR
```
- Format: `JO51IJ`
may be resolved to:
**Example**: `my loc: MYLOCATOR``my loc: JO51IJ`
```text
cq at 144.388, qtf 135, loc JO51IJ
```
### MYLOCATORSHORT
### QRG Variables
Like MYLOCATOR, but only the first 4 characters.
`MYQRG` contains the QRG of the first chat category. The value may come from TRX synchronisation with the logging software or from the manually edited QRG field.
- Format: `JO51`
`MYQRGSHORT` uses the same value, but limits it to the first seven characters:
**Example**: `loc: MYLOCATORSHORT``loc: JO51`
```text
144.388.03 → 144.388
```
`SECONDQRG` contains the QRG of the second chat category. Selecting a station from the second chat does not change the meaning of `MYQRG`. Use `SECONDQRG` explicitly when the QRG of the second category is required.
### Locator Variables
`MYLOCATOR` inserts the complete configured locator of the local station:
```text
JO51IJ
```
`MYLOCATORSHORT` uses only the first four characters:
```text
JO51
```
### MYQTF
`MYQTF` inserts the current antenna direction stored in KST4Contest as a numeric angle in degrees.
For example,
```text
ant MYQTF deg
```
may become:
```text
ant 135 deg
```
The direction is not converted into compass terms such as `north`, `north-east` or `south-west`.
---
## Variables for the Selected Station
These variables require a selected remote station:
| Variable | Replacement value |
|---|---|
| `QRZNAME` | name of the selected station, or its complete callsign if no name is available |
| `FIRSTAP` | description and arrival time of the first aircraft reported by AirScout |
| `SECONDAP` | description and arrival time of the second aircraft reported by AirScout |
For example,
```text
Hi QRZNAME, FIRSTAP, pse lsn at MYQRGSHORT
```
may become:
```text
Hi David, a very big AP in 2 min, pse lsn at 144.388
```
### QRZNAME
Replaced by the **name** of the currently selected station from the chat name field.
**Example**: `Hi QRZNAME, sked?``Hi Gianluca, sked?`
KST4Contest uses the name from the selected station's name field. If that field does not contain a usable name, the complete visible callsign is inserted instead.
### FIRSTAP
Replaced by data of the first reflectable aircraft to the selected station (if available).
If an AirScout candidate is available, `FIRSTAP` contains its description and the expected time until the reflection window.
- Condition: AirScout is active and an aircraft is available.
- Example format: `a very big AP in 1 min`
For example:
**Example**: `AP info: FIRSTAP``AP info: a very big AP in 1 min`
```text
a very big AP in 2 min
```
If no aircraft is available for the selected station, KST4Contest inserts:
```text
no ap available
```
### SECONDAP
Like FIRSTAP, but for the second available aircraft.
`SECONDAP` uses the second available AirScout candidate.
- Example format: `Next big AP in 9 min`
For example:
**Example**: `also: SECONDAP``also: Next big AP in 9 min`
```text
Next big AP in 9 min
```
### MYQTF *(planned for v1.3)*
If there is no second candidate, `SECONDAP` is replaced with an empty string.
Replaced by the current antenna direction in words (e.g. `north`, `north east`, `east`, …).
Further information about the aircraft data is available under [AirScout Integration](en-AirScout-Integration#ap-variables-in-messages).
- Source: Degree value in the MYQTF input field (to the right of the MYQRG field)
### Behaviour Without a Selected Station
If no station is selected, `QRZNAME`, `FIRSTAP` and `SECONDAP` remain visible in the text. KST4Contest does not remove these placeholders automatically.
A visible unresolved placeholder is clearer than a formally complete message which silently lacks important information. Before transmission, check that the intended station is selected and that all required variables have been resolved.
---
## Variables in the Beacon
A public beacon has no selected remote station. It can therefore make meaningful use only of variables which depend on the local station and its current configuration:
A public beacon has no selected remote station. It can therefore use only global variables:
| Variable | Value used in the beacon |
|---|---|
| `MYQRG` | current QRG of the primary chat category |
| `MYQRGSHORT` | first seven characters of the primary QRG |
| `SECONDQRG` | current QRG of the second chat category |
| `MYLOCATOR` | complete configured locator of the local station |
| `MYLOCATORSHORT` | four-character locator of the local station |
| `MYCALL` | configured local callsign |
| `MYQTF` | current antenna heading |
- `MYQRG`
- `MYQRGSHORT`
- `SECONDQRG`
- `MYLOCATOR`
- `MYLOCATORSHORT`
- `MYCALL`
- `MYQTF`
`QRZNAME`, `FIRSTAP` and `SECONDAP` require a selected remote station. They are therefore not resolved in a public beacon.
`QRZNAME`, `FIRSTAP` and `SECONDAP` are not resolved in a beacon and should not be used there.
A suitable configuration for the primary category is:
A possible template for the first chat category is:
```text
calling cq at MYQRGSHORT, ant MYQTF deg, loc MYLOCATOR
```
For the second category, use `SECONDQRG` if that category should publish a different frequency:
If the second chat category uses a different QRG, its template must contain `SECONDQRG`:
```text
calling cq at SECONDQRG, ant MYQTF deg, loc MYLOCATOR
```
Global variables are evaluated again on every timer run. A QRG updated by the logging software can therefore appear in the next beacon message.
Global variables are evaluated again on every timer run. A QRG updated by the logging software can therefore already appear in the next beacon message.
The completely resolved text must contain at least one valid character and must not exceed 120 characters. The protocol separator `|` and line breaks are not permitted. If the text is still empty or invalid when transmission is due, that beacon run is skipped.
The fully resolved beacon text:
The common interval and the behaviour of both chat categories are described under [Configuration Beacon Settings](en-Configuration#beacon-settings).
- must contain at least one valid character,
- must not exceed 120 characters,
- must not contain the protocol separator `|`, and
- must not contain line breaks.
If the text is empty or invalid when transmission is due, that beacon run is skipped.
The interval, activation and behaviour of both categories are described under [Configuration Beacon Settings](en-Configuration#beacon-settings).
---
## Example Snippet Workflow
## Example Contest Workflow with Macros
For example, the first configured snippet may contain:
1. Select a station in the user list → callsign is now pre-selected.
2. Press `Ctrl+1` → Snippet "Hi OM, try sked?" is addressed as a PM.
3. Press Enter → Message sent.
4. Station replies with frequency → QRG column is automatically filled.
5. Press `Ctrl+2` → Snippet "I am calling cq ur dir, pse lsn to me at 144.388" (MYQRG resolved).
6. Press Enter → Sent.
```text
Hi QRZNAME, pse sked? I call at MYQRGSHORT
```
No manual typing, no errors, no interruption to CQ calling.
The workflow can then look like this:
1. Select `DL1ABC-432` in the user list.
2. Press `Ctrl+1`.
3. KST4Contest prepares the directed message and resolves its variables.
4. Check the complete text in the send field.
5. If the remote station has proposed another QRG, edit the text accordingly.
6. Press `Enter` or **TX** to send the message.
The result may be:
```text
/cq DL1ABC-432 Hi Peter, pse sked? I call at 432.088
```
The complete callsign determines the recipient. The selected chat category determines the transmission path. Variables reduce repeated typing, but they do not decide whether the inserted information still matches the current operating situation.
---
## Limits of Variable Resolution
Variables reflect the information available to KST4Contest at the time they are resolved.
In particular:
- A QRG supplied by the logging software may have changed in the meantime.
- A manually entered QRG remains active until it is changed again.
- `MYQRG` remains the QRG of the primary category even if a station from the second category is selected.
- The selected station may differ from a `/cq` destination entered manually.
- AirScout may not provide current aircraft data for the path in question.
- Station-specific variables remain visible when no station is selected.
- Inserted text is not checked automatically for operational correctness.
The send field therefore remains editable after a shortcut or snippet has been inserted. Variables avoid repeated input; the final check remains the operator's responsibility.
---
## Use During a Contest
Shortcuts, snippets and variables are individual tools within the operating workflow. Their interaction with CQ operation, station selection, skeds, QRG changes and log synchronisation is described under [Contest Workflow with KST4Contest](en-Contest-Workflow).
+289 -73
View File
@@ -4,21 +4,61 @@
## Connecting to the Chat
1. Select a **chat category** in the settings window (e.g. 144 MHz VHF, 432 MHz UHF, …).
2. Click the **Connect** button.
3. Wait for the connection to be established.
Before connecting for the first time, configure at least the callsign, password, locator and primary chat category in the settings window. If a second category is required, its login must also be enabled and configured completely.
> Disconnecting and reconnecting is only possible via the settings window. It is therefore recommended to keep the settings window open.
The connection can be started in two ways:
- **Connect to …** in the settings window applies the values currently entered there and starts the connection.
- **File → Connect to …** uses the settings already applied in KST4Contest.
Use **Save Settings** if changed values should also be available after the next programme start.
An active connection can be terminated using **File → Disconnect** or **Disconnect** in the settings window. **Exit + disconnect** terminates the connection and then closes the programme.
If an established connection is lost unexpectedly, KST4Contest waits for a limited period and then attempts a controlled reconnect to ON4KST. A failed initial connection attempt no longer blocks the user interface.
The [`LINK` indicator](#status-bar-and-indicators) in the main window shows whether only the TCP connection exists or whether login and synchronisation have actually been completed.
---
## Main Window Overview
The main window consists of several areas:
### Status Bar and Indicators
The status bar is located at the top of the main window next to the menu.
![Status bar with ON4KST connection indicator](connection_status_indicator.png)
The permanently visible `LINK` indicator shows the actual state of the ON4KST connection:
| Indicator | Meaning |
|---|---|
| green `LINK` | Login and synchronisation of all configured chat categories have been completed |
| yellow `LINK…` | Connection, login, user-list synchronisation or controlled shutdown is in progress |
| red `LINK!` | No connection exists, or KST4Contest is waiting before an automatic reconnect |
The tooltip contains the internal connection state and a more detailed description of the current step. The indicator is not a button.
KST4Contest reports `ONLINE` only after login has been confirmed and the user lists of all configured categories have been received. The send field and **TX** remain disabled while the connection is still being established or resynchronised.
Additional indicators appear temporarily after certain events:
- `SKED` indicates that a sked reminder is due. The text contains the complete target callsign and the remaining time.
- `BAND+` appears after a log entry if at least one common, locally enabled and unworked band has been detected for the worked station.
Both indicators flash for approximately twelve seconds and then disappear. Their tooltip contains the complete message or derivation. Neither indicator is clickable.
### PM Window (top left)
Shows all received **private messages** as well as intercepted public messages containing your own callsign. New messages appear in **red** and fade every 30 seconds from yellow to white.
The PM window shows private messages addressed to the local chat logins and the corresponding outgoing replies.
If [QSO Monitoring](en-Features#qso-sniffer-from-v131) is enabled, it additionally shows captured messages involving the monitored base callsigns. These entries receive a `Sniffed:` prefix containing the complete visible sender and receiver callsigns.
New messages are initially highlighted and then gradually return to the normal table colour. This highlighting only indicates the age of the message; it does not change its content or routing.
### User List (Chat Members)
@@ -40,6 +80,11 @@ The central table of all currently active chat users. Columns (depending on conf
| NOT QRV @ | Bands on which the station has manually been marked not QRV |
| Category | Chat category of this entry |
The QRG column shows the frequency most recently detected for a station. Missing trailing zeros are added for display purposes, so `144.21`, for example, is shown as `144.210`. If KST4Contest detects frequencies on several bands in succession, the column shows the latest match. The internal band information may still contain several current bands for that station.
Relative frequency information is first combined with a band context from the same sender which is no more than 30 minutes old. Only if no such context exists does KST4Contest use the global fallback band. Detection rules, examples and limitations: [QRG Detection](en-Features#qrg-detection).
### Worked, band and grid-square status
The subcolumns under **worked** use compact codes because several enabled bands leave little room for full descriptions. `X` marks a callsign worked on that band. `a` and `B+` identify an offered band which has not yet been worked. An appended `o` means that the four-character grid square has already been worked on this band.
@@ -52,39 +97,139 @@ Each status cell has a tooltip containing the legend and the state derived for t
**Sorting**: Click column headers. QRB sorting is numerical (corrected in v1.22).
A callsign displayed in green and bold indicates a directional opportunity derived from a directed message. The marker applies to the sender of that message and remains visible for no more than five minutes. Derivation and limitations: [Directional Opportunities from Directed Messages](en-Features#directional-opportunities-from-directed-messages).
### Send Field
Text input for outgoing messages. After clicking a callsign in the user list, the send field automatically receives focus start typing immediately without double-clicking (from v1.22).
The send field contains the prepared text for the next outgoing message.
### MYQRG Field
When an operator deliberately selects a station in the user list using the mouse or keyboard, KST4Contest prepares a directed message:
To the right of the send button. Shows the current own QRG, can also be entered manually.
```text
/cq CALLSIGN
```
### MYQTF Field *(for v1.3)*
The complete visible callsign, including any suffix, and the chat category of the selected station are retained. A target such as `9A0BB-70` is not shortened to `9A0BB`.
Input field for the current antenna direction. Used for the planned `MYQTF` variable.
A background refresh, changed sorting order or filter update must not overwrite message text which has already been edited. Only an actual station selection by the operator prepares the `/cq` recipient again.
- **TX** or `Enter` sends the prepared text.
- `Esc` clears the send field.
- The send field and **TX** remain disabled until KST4Contest is fully connected to ON4KST.
Shortcuts, snippets and variables are described under [Macros and Variables](en-Macros-and-Variables).
### MYQRG and SECONDQRG Fields
The two QRG fields contain the local frequencies for the primary and secondary chat categories.
`MYQRG` can be updated by an enabled TRX synchronisation interface or entered manually when no automatic QRG source is active. `SECONDQRG` remains independent and contains the frequency used for the second category.
Selecting a station from the second chat does not change the meaning of these values: `MYQRG` continues to belong to the primary category and `SECONDQRG` to the secondary category.
Further details: [TRX Sync Settings](en-Configuration#trx-sync-settings).
### MYQTF Field
The MYQTF field shows the current antenna direction as a numerical angle in degrees.
If PSTRotator is enabled, the value is received automatically and the field cannot be edited manually. Without active rotator synchronisation, the antenna direction can be entered directly. The changed value is applied when the field loses focus.
The value affects, among other things:
- QTF filtering,
- the antenna-sector display on the station map,
- priority-score calculation,
- the AP timeline, and
- the `MYQTF` variable.
---
## Filters
## Message Tables
The filter bar is located above the chat-member table and groups related controls:
KST4Contest deliberately displays message text on a single line. This keeps a larger number of entries visible when chat activity is high. The disadvantage is obvious: if the **Message** column is narrow, not every message fits completely into its cell.
- **Show only QTF** limits the list to a selected antenna direction.
- **Show only QRB [km] <=** sets a maximum distance.
- **Find** searches for a callsign.
- **wkd** hides callsigns which have already been worked on at least one band.
- The individual band buttons hide a station if it has already been worked on that band or has been marked NOT QRV there. Only bands enabled for the local station are shown.
- **Only new grids** shows only stations in four-character grid squares which have not been worked on any band.
- **Grid color** is not a filter. It marks the QRA cell of an already worked grid square without hiding stations.
- **New bands** shows stations with at least one detected, locally enabled and unworked band opportunity. NOT-QRV marks take precedence.
- **Reachability**, **Tropo >=0dB** and **AS next 5m** limit the list according to the selected path or AirScout criteria.
If the message text is wider than the visible cell, moving the mouse over that **Message** cell displays the complete content in a tooltip. No additional full-text tooltip is shown if the message already fits into the column.
The filter bar has no fixed width. QTF, Worked and Reachability controls initially use the available space in their respective rows. When the horizontal divider is moved to the right and the chat-member area becomes narrower, controls wrap only when their actual required width no longer fits.
Web addresses beginning with `http://`, `https://` or `www.` are displayed as links inside the message text. Clicking a link opens it in the operating systems default browser. Other protocols are not treated as links.
![Truncated message text with full-text tooltip and clickable link](message_tooltip_and_link.png)
This avoids having to move the divider merely to read an individual long message. The divider can, of course, still be adjusted if a permanently wider message area is required.
---
## Filters and Reachability Controls
The filter bar is located above the chat-member table. Filters can be combined; a station remains visible only if it satisfies every active condition.
![Wrapped filter bar in a narrow chat-member view](filter_bar_wrapped.png)
In plain terms: the filters determine the table contents, but no longer enforce the minimum width of the entire right-hand side. The bar remains compact in the normal layout and uses additional height only when the view becomes genuinely narrow. Moving the divider back to the left immediately returns the controls to the available rows.
### Station Filters
| Control | Effect |
|---|---|
| **Show only QTF** | Shows only stations inside the selected antenna direction and configured beamwidth |
| **Show only QRB [km] <=** | Limits the list to the entered maximum distance |
| **Find** | Filters by a complete or partial callsign |
| **wkd** | Hides base callsigns already worked on at least one supported band |
| individual band buttons | Hide stations already worked on that band or marked NOT QRV there |
| **Inactive stations** | Hides stations whose latest chat activity was more than 20 minutes ago |
| **Only new grids** | Shows only stations in four-character grid squares not yet worked on any band |
| **New bands** | Shows stations with at least one detected, locally enabled and unworked band opportunity |
| **Tropo >=0dB** | Shows stations with a calculated non-negative SSB margin |
| **AS next 5m** | Shows stations with a current AirScout window or one expected within the next five minutes |
For **New bands**, KST4Contest evaluates current QRGs, band information in the name field and active callsign variants together. Manual NOT-QRV marks take precedence.
The **Tropo >=0dB** filter removes only stations for which a completed calculation returned a negative margin. Stations with pending or failed calculations remain visible. Otherwise, a missing API result would incorrectly be treated as proof that the path is unsuitable.
### Grid Color
**Grid color** is not a filter. It only changes the presentation of the QRA cell and marks four-character grid squares which have already been worked.
The station remains visible regardless of this colour marker. **Reset filters** therefore does not disable **Grid color**.
### Reachability and Calc Selected
The **Reachability** dropdown selects the band used by the Tropo column, the Tropo filter and an explicitly requested path calculation.
- **Auto** derives the band from the stations current QRG, band information in its name field and the supported chat category.
- An explicitly selected band overrides this automatic choice for the Reachability calculation.
Changing the dropdown does not start a calculation for the entire user list. With an online elevation-data source, that would be unnecessarily slow and multiply the number of external API requests.
**Calc selected** calculates only the currently selected station, using either the explicitly selected or automatically derived band. The result is then used by the Tropo column and the associated views.
### Resetting the Filters
**Reset filters** clears:
- the QTF filter,
- the QRB filter,
- the callsign search field,
- all Worked and band filters,
- **Inactive stations**,
- **Only new grids**,
- **New bands**,
- **Tropo >=0dB**, and
- **AS next 5m**.
The internal filter predicates are explicitly cleared as well. Resetting only the visible toggle buttons would not be sufficient.
The following settings are retained:
- **Grid color**, because it is a display option, and
- the **Reachability** selection, because it selects the calculation band rather than directly filtering the table.
### Behaviour in a Narrow View
The filter bar has no fixed width. QTF, Worked and Reachability controls initially use the available space in their respective rows.
When the middle divider is moved to the right and the chat-member area becomes narrower, controls wrap only when their actual required width no longer fits. Widening the area causes them to rearrange immediately.
In plain terms: the filters determine the table contents, but no longer enforce the minimum width of the entire right-hand side.
---
@@ -158,99 +303,171 @@ Calculation and limitations: [Priority Score and Priority List](en-Features#prio
## Station Map
The station map is opened or closed through:
The station map can be opened in two ways:
**Windows → Show / hide station map**
- **Windows → Show / hide station map** opens or closes the map window.
- **Show on map** in the **Further Info** panel opens the map and focuses the selected station.
The window uses the chat members currently visible in the filtered user list. Changing the QRB, QTF, Worked, band or Reachability filters can therefore also change the stations shown on the map.
The map uses the stations which remain visible after applying the current user-list filters. Its header shows the number of displayed stations and indicates a filtered view with `filtered view active`.
A station can additionally be opened directly from the **Further Info** panel using **Show on map**. This selects the station on the map and requests the associated path analysis.
![Station map with a selected station and visible path analysis](station_map_path_analysis.png)
Stations with the same normalised base callsign and position are combined into one marker. At lower zoom levels, nearby markers may additionally be displayed as clusters. These are display groups only; the individual chat logins remain separate message targets inside KST4Contest.
### Selecting a Station
Clicking a station marker:
A single station marker can be selected directly. KST4Contest then:
1. selects the corresponding chat member,
2. scrolls the main user list to that entry,
3. updates the **Further Info** panel, and
4. prepares the complete visible callsign as the message target.
4. prepares the complete visible callsign as the `/cq` recipient.
The map details for the selected station include its locator, QRB, QTF, detected bands and available band opportunities. **Trigger cluster spot** sends a spot through the built-in local DX Cluster server so that connected logging software can receive the selected station and QRG.
Chat logins with the same normalised base callsign and position may share one marker. They nevertheless remain separate message targets inside KST4Contest.
The path-analysis section shows the terrain profile and the calculated route between both stations. Depending on the available data, it includes:
Markers which are too close together at the current zoom level are displayed as a cluster containing the number of stations. Clicking the cluster zooms into that area. A concrete station is selected only after an individual marker becomes visible and is clicked.
For a selected station, the header additionally shows:
- the complete callsign,
- locator,
- QRB and QTF,
- detected active bands,
- any available `B+` band opportunity, and
- the most recently known QRGs.
Long header content is shortened. The complete text remains available in its tooltip.
### Clearing the Selection with Reset View
**Reset view** clears the selected station without changing the map position or zoom level.
It:
- clears the selected station,
- clears the selection in the main user list,
- removes the connection line to the remote station,
- discards a pending analysis for the previous station, and
- removes the right-hand analysis panel.
The map itself remains at the previously selected position and zoom level. This function is therefore not a geographical reset to the local station.
![Station map after Reset view without a selected station](station_map_reset.png)
Selecting another individual marker restores the station selection and analysis panel.
### Triggering a DX Cluster Spot
**Trigger cluster spot** is visible only while a station is selected. It sends one spot to logging programmes connected to the built-in local DX Cluster server.
This requires:
- the local DX Cluster server to be enabled,
- at least one connected cluster client, and
- a usable QRG for the selected station.
The spot is not sent to a public Internet cluster.
### Path Analysis
The terrain profile is displayed below the map. The right-hand analysis panel includes, among other things:
- the data source and number of elevation samples,
- the analysis frequency,
- line-of-sight and horizon information,
- the Earth-curvature or refraction model,
- radio and terrain horizons,
- Fresnel-zone clearance,
- detected obstructions,
- an estimated link budget,
- received power and SSB margin, and
- a short assessment of the path.
- the link budget,
- estimated received power, and
- a summarised path assessment.
Moving the mouse over the terrain profile highlights the corresponding geographical position on the map.
The analysis uses the same centrally derived band as the Reachability functions. A band explicitly selected in the **Reachability** dropdown is taken into account.
The analysis can be hidden using **Hide path analysis** when more space is required for the map. The compact state displays **Path analysis is hidden.** together with the **Show path analysis** button.
These values remain technical estimates. Buildings, vegetation, local obstructions, current propagation conditions and unknown station parameters may substantially change the real result.
### Hiding the Path Analysis
**Hide path analysis** hides both the terrain profile and the right-hand analysis panel, leaving more space for the map.
![Station map with hidden path analysis](station_map_compact.png)
The selected station and map contents remain available while the analysis panel is hidden. The setting is stored and restored at the next start.
The **Path analysis is hidden** message and **Show path analysis** button remain visible, so the function can be restored directly.
Calculation method and limitations: [Station Map and Path Analysis](en-Features#station-map-and-path-analysis-from-v141).
If no station is selected when the analysis is shown again, no empty right-hand panel is displayed. It is recreated only after a specific station has been selected.
The setting is stored and restored at the next programme start.
The divider between the map and detail panel can be moved horizontally. Longer values wrap in a narrow detail panel; a vertical scrollbar appears if the available height is insufficient.
Detailed derivation and limitations: [Station Map and Path Analysis](en-Features#station-map-and-path-analysis-from-v141).
---
## Global Message Tabs and Monitor Window
Three global message tabs are located below the main user list. Unlike the **Further Info** panel, their contents do not depend on the station currently selected.
The lower part of the main window contains three global message tabs. Their contents do not depend on the station currently selected in the user list.
| Tab | Displayed messages |
| Tab | Content |
|---|---|
| **Public messages** | All public chat messages, including CQ calls and beacons |
| **DXCluster messages** | DX cluster messages received from the ON4KST server |
| **QSO of the other** | Directed messages between chat logins other than the local station |
| **Public messages** | Public chat messages, CQ calls and beacons |
| **DXCluster messages** | DX cluster messages received through ON4KST |
| **QSO of the other** | Directed messages between two other stations |
The **Public messages** tab is selected by default.
![Global message tabs in the main window](global_message_tabs.png)
![Global message tabs below the main user list](global_message_tabs.png)
In **QSO of the other**, sender and receiver are displayed separately. **Last QRG TX** and **Last QRG RX** contain the frequencies most recently known for the two stations. They do not necessarily represent the frequency discussed in the displayed conversation.
The **DXCluster messages** table contains the time, reporting and reported stations, locators, QRG, message text and global Worked state where these values are available in the received message.
**wkd TX?** and **wkd RX?** show the global Worked state of the two base callsigns. These values are not band-specific.
The **QSO of the other** table contains:
The **DXCluster messages** tab shows the reporting and reported stations, their locators, QRG, message text and the global Worked state of the reported station. Which fields are actually available depends on the message received from the ON4KST server.
- the complete sender and receiver callsigns,
- the latest QRG currently known for each station,
- the global Worked state of each station,
- the message text, and
- the chat category.
Message text remains on one line. If a cell is too narrow, its complete content is available in a tooltip. Web addresses in the message text are clickable.
The displayed QRG is not necessarily the frequency on which the stations intend to make a contact. It is the latest QRG currently associated with the respective chat member. The Worked state is global and not specific to the displayed QRG or band.
### Separate Monitor Window
A directed chat message in this table does not prove that a radio QSO has taken place. The table also contains sked requests, frequency exchanges and other directed messages between third-party chat logins.
### Separate monitor window
The DX cluster and QSO-of-the-other tables can also be displayed together in a separate window.
KST4Contest additionally opens the **Cluster & QSO of the other** window. It shows DX cluster messages in the upper table and directed messages between other stations in the lower table.
![Separate monitor window for DX cluster traffic and directed messages between other stations](cluster_qso_monitor.png)
The separate window and the tabs use the same underlying messages. Hiding the window does not stop message processing or remove messages from the tabs.
The vertical divider position and window size are stored together with the other UI settings. Use **Save Settings** after changing them.
Use **Windows → Hide cluster / stranger QSOs** to hide the window and **Windows → Show cluster / stranger QSOs** to restore it.
The window can be hidden and restored through:
If a message is too long for its table cell, moving the mouse over the cell displays the complete text in a tooltip. Links beginning with `http://`, `https://` or `www.` can be opened in the system browser.
```text
Windows → Hide cluster / stranger QSOs
Windows → Show cluster / stranger QSOs
```
The main-window tabs and separate monitor window use the same underlying data. Hiding the monitor window therefore neither stops message processing nor removes messages from the tabs.
Derivation and limitations: [Global Message Views](en-Features#global-message-views).
---
## Menu
### File
- **Connect to …** starts the connection using the settings already applied in KST4Contest.
- **Disconnect** terminates the current ON4KST connection without closing KST4Contest.
- **Exit + disconnect** terminates the connection and then closes the programme.
The Connect and Disconnect entries are enabled or disabled according to the current connection state.
### Options
- **Set QRG as name in Chat (main category)** sends `/SETNAME` containing the current `MYQRG` to the primary chat category.
- **Show me as away in chat** sends `/AWAY`.
- **Show me as active in chat** sends `/BACK`.
- **Show options** shows or hides the settings window.
Functions which communicate with the server are available only after the ON4KST connection has been established completely.
### Windows
- **Hide cluster / stranger QSOs** hides the separate monitor window for DX cluster messages and directed messages between other stations.
- **Show cluster / stranger QSOs** restores the monitor window.
- **hide options** hides the settings window.
- **show options** restores the settings window.
- **Hide cluster / stranger QSOs** and **Show cluster / stranger QSOs** hide or restore the separate cluster and QSO monitor window.
- **hide options** and **show options** hide or restore the settings window.
- **Use dark mode design** activates the dark colour scheme.
- **Use default mode design** restores the default colour scheme.
- **Use default mode design** restores the standard light colour scheme.
- **Show / hide station map** opens or closes the separate station-map and path-analysis window.
---
@@ -270,8 +487,7 @@ If the layout has become inconvenient, first move the dividers back to usable po
## Operating Tips
- **Keep the settings window open**: Quick access to enable/disable the beacon.
- **Right-click in the user list**: Opens the snippet menu and other context actions.
- **Mark a station NOT QRV**: Select the station and use the per-band controls in the **Further Info** panel.
- **Enter from anywhere**: When text is in the send field, Enter sends directly even if the focus is elsewhere.
- **Stop the beacon**: Switch off the beacon while scanning frequencies to avoid flooding the chat with messages.
- **Keep the settings window open**: This provides quick access to the beacon controls.
- **Right-click in the user list**: Opens the snippet menu and additional actions, including QRZ.com profiles and NOT-QRV marks.
- **Press Enter while working in the chat**: If the send field contains text, Enter sends it directly even when another control has focus.
- **Stop the beacon while scanning**: Disable the beacon while moving through frequencies to avoid flooding the chat with unnecessary messages.
+3 -3
View File
@@ -1,6 +1,6 @@
pkgbase = kst4contest-bin
pkgdesc = ON4KST Chat Client for VHF/UHF contest operation (pre-built)
pkgver = 1.41.1
pkgver = 1.42.0
pkgrel = 1
url = https://github.com/praktimarc/kst4contest
arch = x86_64
@@ -10,7 +10,7 @@ pkgbase = kst4contest-bin
provides = kst4contest
conflicts = kst4contest
conflicts = kst4contest-git
source = KST4Contest-v1.41.1-archlinux-x86_64.pkg.tar.zst::https://github.com/praktimarc/kst4contest/releases/download/v1.41.1/KST4Contest-v1.41.1-archlinux-x86_64.pkg.tar.zst
sha256sums = 8e9a53ff832920c9ef2733635b90c5a4ffcd57a2958aaa251e92bd031142c614
source = KST4Contest-v1.42.0-archlinux-x86_64.pkg.tar.zst::https://github.com/praktimarc/kst4contest/releases/download/v1.42.0/KST4Contest-v1.42.0-archlinux-x86_64.pkg.tar.zst
sha256sums = 3d8ac19c9f9d3ab0bdaf0ea621de0aa18c64f442c8776d28bfad607522aaf02b
pkgname = kst4contest-bin
+2 -2
View File
@@ -1,6 +1,6 @@
# Maintainer: Philipp Wagner <philipp@wagnersnetz.de>
pkgname=kst4contest-bin
pkgver=1.41.1
pkgver=1.42.0
pkgrel=1
pkgdesc="ON4KST Chat Client for VHF/UHF contest operation (pre-built)"
arch=('x86_64')
@@ -10,7 +10,7 @@ depends=('gst-plugins-base' 'gst-plugins-good')
provides=('kst4contest')
conflicts=('kst4contest' 'kst4contest-git')
source=("KST4Contest-v${pkgver}-archlinux-${CARCH}.pkg.tar.zst::https://github.com/praktimarc/kst4contest/releases/download/v${pkgver}/KST4Contest-v${pkgver}-archlinux-${CARCH}.pkg.tar.zst")
sha256sums=('8e9a53ff832920c9ef2733635b90c5a4ffcd57a2958aaa251e92bd031142c614')
sha256sums=('3d8ac19c9f9d3ab0bdaf0ea621de0aa18c64f442c8776d28bfad607522aaf02b')
package() {
cp -a "${srcdir}/usr" "${pkgdir}/"
+1 -1
View File
@@ -1,6 +1,6 @@
pkgbase = kst4contest-git
pkgdesc = ON4KST Chat Client for VHF/UHF contest operation (git)
pkgver = 1.42.0.r145.gd885924
pkgver = 1.42.0.r256.g8aadbb9
pkgrel = 1
url = https://github.com/praktimarc/kst4contest
arch = x86_64
+1 -1
View File
@@ -1,6 +1,6 @@
# Maintainer: Philipp Wagner <philipp@wagnersnetz.de>
pkgname=kst4contest-git
pkgver=1.42.0.r145.gd885924
pkgver=1.42.0.r256.g8aadbb9
pkgrel=1
pkgdesc="ON4KST Chat Client for VHF/UHF contest operation (git)"
arch=('x86_64')
+4 -4
View File
@@ -1,7 +1,7 @@
pkgbase = kst4contest
pkgdesc = ON4KST Chat Client for VHF/UHF contest operation
pkgver = 1.41.1
pkgrel = 2
pkgver = 1.42.0
pkgrel = 1
url = https://github.com/praktimarc/kst4contest
arch = x86_64
license = GPL-3.0-only
@@ -12,7 +12,7 @@ pkgbase = kst4contest
provides = kst4contest
conflicts = kst4contest-bin
conflicts = kst4contest-git
source = kst4contest-1.41.1.tar.gz::https://github.com/praktimarc/kst4contest/archive/refs/tags/v1.41.1.tar.gz
sha256sums = e96207a2d3fee19d35e34717f5312beb28bb087c040164e352337e749ce53b8d
source = kst4contest-1.42.0.tar.gz::https://github.com/praktimarc/kst4contest/archive/refs/tags/v1.42.0.tar.gz
sha256sums = bd396387b8de41aac706458d5ebf64140ab3e83b8a7c710b66aa802bd48e804e
pkgname = kst4contest
+3 -3
View File
@@ -1,7 +1,7 @@
# Maintainer: Philipp Wagner <philipp@wagnersnetz.de>
pkgname=kst4contest
pkgver=1.41.1
pkgrel=2
pkgver=1.42.0
pkgrel=1
pkgdesc="ON4KST Chat Client for VHF/UHF contest operation"
arch=('x86_64')
url="https://github.com/praktimarc/kst4contest"
@@ -11,7 +11,7 @@ makedepends=('java-environment=21' 'maven')
provides=('kst4contest')
conflicts=('kst4contest-bin' 'kst4contest-git')
source=("${pkgname}-${pkgver}.tar.gz::https://github.com/praktimarc/kst4contest/archive/refs/tags/v${pkgver}.tar.gz")
sha256sums=('e96207a2d3fee19d35e34717f5312beb28bb087c040164e352337e749ce53b8d')
sha256sums=('bd396387b8de41aac706458d5ebf64140ab3e83b8a7c710b66aa802bd48e804e')
build() {
cd "${srcdir}/kst4contest-${pkgver}"
@@ -877,6 +877,12 @@ public class MessageBusManagementThread extends Thread {
|| messageToProcess.getMessageText().isEmpty()) {
// No processable data.
} else {
if (On4KstProtocol.isConnectionProbeResponse(
messageToProcess.getMessageText())) {
// DXQ is the internal response to the active connection probe.
// Liveness was already recorded by the session manager.
return;
}
if (messageToProcess.getMessageText().startsWith(SRVR_LOGSTAT + "|")) {
String[] logstatMessage =
@@ -2177,8 +2183,11 @@ public class MessageBusManagementThread extends Thread {
// e.printStackTrace();
// }
System.out.println(messageTextRaw.getMessageText() + " <- RXed"); // Stdout at
// Console#######################################################TODO:Wichtig
if (!On4KstProtocol.isConnectionProbeResponse(
messageTextRaw.getMessageText())) {
System.out.println(messageTextRaw.getMessageText() + " <- RXed"); // Stdout at
// Console#######################################################TODO:Wichtig
}
try {
processRXMessage23001(messageTextRaw);
@@ -2207,4 +2216,4 @@ public class MessageBusManagementThread extends Thread {
System.out.println("Msgbusmgt: interrupt");
this.interrupt();
}
}
}
@@ -48,6 +48,8 @@ final class On4KstConnectionManager {
static final long LOGIN_FALLBACK_MILLIS = 2_000L; //Login-Fallback
static final long HANDSHAKE_TIMEOUT_MILLIS = 45_000L; //Handshake-Timeout
static final long APPLICATION_HEARTBEAT_AFTER_MILLIS = 90_000L; //Application-Heartbeat
/** Idle duration after which the server is asked for current DX data. */
static final long CONNECTION_PROBE_AFTER_MILLIS = 180_000L; //Active connection probe
static final long INBOUND_STALE_AFTER_MILLIS = 210_000L; //Stale-Timeout - time without rxed data
static final List<Long> RECONNECT_DELAYS_MILLIS =
List.of(2_000L, 5_000L, 10_000L, 20_000L, 30_000L); //Reconnect-Backoff if no connection possible
@@ -178,7 +180,19 @@ final class On4KstConnectionManager {
session.lastInboundMillis.set(now);
session.lastProgressMillis.set(now);
String opcode = opcode(line);
String opcode = On4KstProtocol.opcode(line);
long probeResponseMillis = session.connectionProbe.acknowledge(now);
if (probeResponseMillis >= 0L) {
LOGGER.log(Level.INFO,
"ON4KST connection probe confirmed: session {0}, "
+ "received opcode {1}, response time {2} ms",
new Object[] {
sessionId,
opcode,
probeResponseMillis
});
}
if ("CK".equals(opcode)) {
sendHeartbeat(session);
}
@@ -244,7 +258,15 @@ final class On4KstConnectionManager {
new LinkedBlockingQueue<>();
LinkedBlockingQueue<ChatMessage> transmitQueue =
new LinkedBlockingQueue<>();
Session session = new Session(token, socket, receiveQueue, transmitQueue);
int mainCategory = controller.getChatPreferences()
.getLoginChatCategoryMain()
.getCategoryNumber();
Session session = new Session(
token,
socket,
receiveQueue,
transmitQueue,
mainCategory);
ReadThread readThread = new ReadThread(
token, socket, receiveQueue, this::isActiveSession,
@@ -252,8 +274,7 @@ final class On4KstConnectionManager {
failure -> onConnectionFailure(token, failure));
WriteThread writeThread = new WriteThread(
token, socket, transmitQueue,
controller.getChatPreferences().getLoginChatCategoryMain()
.getCategoryNumber(),
mainCategory,
this::isActiveSession,
failure -> onConnectionFailure(token, failure),
controller::onOn4KstOutboundFrameRejected);
@@ -535,6 +556,29 @@ final class On4KstConnectionManager {
session.transmitQueue.offer(heartbeat);
}
private void sendConnectionProbe(
Session session,
long now,
long inboundIdle
) {
if (session == null || !isActiveSession(session.id)
|| !session.connectionProbe.tryStart(now)) {
return;
}
LOGGER.log(Level.INFO,
"Sending ON4KST connection probe: session {0}, main category "
+ "{1}, inbound idle {2} seconds",
new Object[] {
session.id,
session.mainCategory,
inboundIdle / 1_000L
});
sendControl(
session,
On4KstProtocol.connectionProbe(session.mainCategory));
}
private void onConnectionFailure(long sessionId, Throwable failure) {
scheduler.execute(() -> failSession(sessionId, failure));
}
@@ -634,18 +678,47 @@ final class On4KstConnectionManager {
return;
}
long inboundIdle = now - session.lastInboundMillis.get();
if (inboundIdle > INBOUND_STALE_AFTER_MILLIS) {
failSession(session.id,
new SocketException("No ON4KST data received for "
+ inboundIdle / 1_000L + " seconds"));
long lastInboundMillis = session.lastInboundMillis.get();
long inboundIdle = now - lastInboundMillis;
IdleAction idleAction = determineIdleAction(
inboundIdle,
session.lastHeartbeatMillis.get() >= lastInboundMillis,
session.connectionProbe.isOutstanding());
if (session.lastInboundMillis.get() != lastInboundMillis) {
return;
}
if (inboundIdle > APPLICATION_HEARTBEAT_AFTER_MILLIS
&& session.lastHeartbeatMillis.get()
< session.lastInboundMillis.get()) {
sendHeartbeat(session);
switch (idleAction) {
case TIMEOUT -> {
if (session.lastInboundMillis.get() != lastInboundMillis) {
return;
}
long probeWaitMillis =
session.connectionProbe.responseWaitMillis(now);
if (probeWaitMillis >= 0L) {
LOGGER.log(Level.WARNING,
"ON4KST connection probe timed out: session "
+ "{0}, main category {1}, no response "
+ "for {2} ms, inbound idle {3} seconds; "
+ "reconnecting",
new Object[] {
session.id,
session.mainCategory,
probeWaitMillis,
inboundIdle / 1_000L
});
}
failSession(session.id,
new SocketException("No ON4KST data received for "
+ inboundIdle / 1_000L + " seconds"));
}
case CONNECTION_PROBE ->
sendConnectionProbe(session, now, inboundIdle);
case HEARTBEAT -> sendHeartbeat(session);
case NONE -> {
// The session is active or already has the required idle action.
}
}
} catch (RuntimeException exception) {
LOGGER.log(Level.WARNING,
@@ -653,6 +726,28 @@ final class On4KstConnectionManager {
}
}
/**
* Selects at most one maintenance action for the current inbound idle phase.
*/
static IdleAction determineIdleAction(
long inboundIdleMillis,
boolean heartbeatSentForIdlePhase,
boolean probeOutstanding
) {
if (inboundIdleMillis > INBOUND_STALE_AFTER_MILLIS) {
return IdleAction.TIMEOUT;
}
if (inboundIdleMillis >= CONNECTION_PROBE_AFTER_MILLIS
&& !probeOutstanding) {
return IdleAction.CONNECTION_PROBE;
}
if (inboundIdleMillis > APPLICATION_HEARTBEAT_AFTER_MILLIS
&& !heartbeatSentForIdlePhase) {
return IdleAction.HEARTBEAT;
}
return IdleAction.NONE;
}
private void validateConfiguration() {
ChatPreferences preferences = controller.getChatPreferences();
On4KstProtocol.login(
@@ -782,15 +877,6 @@ final class On4KstConnectionManager {
}
}
private String opcode(String line) {
if (line == null) {
return "";
}
int separator = line.indexOf('|');
return (separator < 0 ? line : line.substring(0, separator))
.trim().toUpperCase(Locale.ROOT);
}
private String describeFailure(Throwable failure) {
if (failure == null) {
return "unknown error";
@@ -808,12 +894,15 @@ final class On4KstConnectionManager {
private final Socket socket;
private final LinkedBlockingQueue<ChatMessage> receiveQueue;
private final LinkedBlockingQueue<ChatMessage> transmitQueue;
private final int mainCategory;
private final long connectedMillis = System.currentTimeMillis();
private final AtomicLong lastInboundMillis =
new AtomicLong(connectedMillis);
private final AtomicLong lastProgressMillis =
new AtomicLong(connectedMillis);
private final AtomicLong lastHeartbeatMillis = new AtomicLong();
private final ConnectionProbeState connectionProbe =
new ConnectionProbeState();
private final Map<Integer, Map<String, ChatMember>> initialMembers =
new ConcurrentHashMap<>();
@@ -831,12 +920,45 @@ final class On4KstConnectionManager {
long id,
Socket socket,
LinkedBlockingQueue<ChatMessage> receiveQueue,
LinkedBlockingQueue<ChatMessage> transmitQueue
LinkedBlockingQueue<ChatMessage> transmitQueue,
int mainCategory
) {
this.id = id;
this.socket = socket;
this.receiveQueue = receiveQueue;
this.transmitQueue = transmitQueue;
this.mainCategory = mainCategory;
}
}
}
/** Maintenance action selected by the session monitor. */
enum IdleAction {
NONE,
HEARTBEAT,
CONNECTION_PROBE,
TIMEOUT
}
/** Tracks one outstanding liveness probe for the complete TCP session. */
static final class ConnectionProbeState {
private final AtomicLong sentMillis = new AtomicLong();
boolean tryStart(long now) {
return now > 0L && sentMillis.compareAndSet(0L, now);
}
long acknowledge(long now) {
long sent = sentMillis.getAndSet(0L);
return sent == 0L ? -1L : Math.max(0L, now - sent);
}
boolean isOutstanding() {
return sentMillis.get() > 0L;
}
long responseWaitMillis(long now) {
long sent = sentMillis.get();
return sent == 0L ? -1L : Math.max(0L, now - sent);
}
}
}
@@ -54,6 +54,27 @@ final class On4KstProtocol {
+ "|0|";
}
/** Builds the active liveness probe for the session's main chat. */
static String connectionProbe(int category) {
return "RDXQ|" + category(category) + "|";
}
/** Returns whether a server frame is the expected liveness-probe response. */
static boolean isConnectionProbeResponse(String frame) {
return "DXQ".equals(opcode(frame));
}
/** Extracts and normalizes the opcode without exposing the remaining frame. */
static String opcode(String frame) {
if (frame == null) {
return "";
}
int separator = frame.indexOf('|');
return (separator < 0 ? frame : frame.substring(0, separator))
.trim()
.toUpperCase(Locale.ROOT);
}
/** Builds a category-qualified locator command after validating Maidenhead syntax. */
static String setLocator(int category, String locator) {
return command(category, "/SETLOC " + locator(locator));
@@ -189,4 +210,4 @@ final class On4KstProtocol {
}
return category;
}
}
}
@@ -25,7 +25,6 @@ import javafx.scene.control.TableRow; // For the priority coloring
import javafx.animation.PauseTransition;
import javafx.beans.binding.Bindings;
import javafx.css.PseudoClass;
import javafx.geometry.*;
import javafx.scene.control.*;
import javafx.scene.input.*;
@@ -3754,67 +3753,54 @@ public class Kst4ContestApplication extends Application implements StatusUpdateL
}
});
//experimental row coloring on new private messages (and recolouring if they get older)
// Color new private messages and restore the normal row style after five minutes.
tbl_privateMSGTable.setRowFactory(tv -> new TableRow<ChatMessage>() {
@Override
protected void updateItem(ChatMessage item, boolean empty) {
protected void updateItem(
final ChatMessage item,
final boolean empty
) {
super.updateItem(item, empty);
try {
if (item != null) {
if (item.getSender().getCallSign().equals(chatcontroller.getChatPreferences().getStn_loginCallSign())) {
PseudoClass foo = PseudoClass.getPseudoClass("messageHighlightOwn-column");
getStyleClass().removeAll(
PrivateMessageRowStyleResolver.knownStyleClasses()
);
// System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> pm row style " + this.getStyleClass());
tv.setStyle(null);
if (empty || item == null || item.getSender() == null) {
return;
}
// this.getStyleClass().clear();
this.getStyleClass().add("messageHighlightOwn-column"); //add new special colored css reference
// setStyle("-fx-background-color: #ADD8E6;");
} else {
final String ownCallsign = chatcontroller
.getChatPreferences()
.getStn_loginCallSign();
// System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> pm row style " + this.getStyleClass());
final boolean ownMessage = Objects.equals(
item.getSender().getCallSign(),
ownCallsign
);
if (( (new Utils4KST().time_generateCurrentEpochTime())) - (Long.parseLong(item.getMessageGeneratedTime())) <= 30 ) { //after 30 seconds change color
// setStyle("-fx-background-color: #FF6F00;");
this.getStyleClass().clear();
this.getStyleClass().add("messageHighlight30-column"); //add new special colored css reference
final String styleClass;
} else if (( (new Utils4KST().time_generateCurrentEpochTime())) - (Long.parseLong(item.getMessageGeneratedTime())) <= 60 ) { //after 60 seconds change color
this.getStyleClass().clear();
this.getStyleClass().add("messageHighlight60-column"); //add new special colored css reference
// setStyle("-fx-background-color: #FFB300;");
} else if (( (new Utils4KST().time_generateCurrentEpochTime())) - (Long.parseLong(item.getMessageGeneratedTime())) <= 90 ) { //after 90 seconds change color
this.getStyleClass().clear();
this.getStyleClass().add("messageHighlight90-column"); //add new special colored css reference
// setStyle("-fx-background-color: #FFB300;");
} else if (( (new Utils4KST().time_generateCurrentEpochTime())) - (Long.parseLong(item.getMessageGeneratedTime())) <= 120 ) { //after 120 seconds change color
this.getStyleClass().clear();
this.getStyleClass().add("messageHighlight120-column"); //add new special colored css reference
// setStyle("-fx-background-color: #FFD54F;");
} else if (( (new Utils4KST().time_generateCurrentEpochTime())) - (Long.parseLong(item.getMessageGeneratedTime())) <= 180 ) { //after 180 seconds change color
this.getStyleClass().clear();
this.getStyleClass().add("messageHighlight180-column"); //add new special colored css reference
// setStyle("-fx-background-color: #FFD54F;");
} else if (( (new Utils4KST().time_generateCurrentEpochTime())) - (Long.parseLong(item.getMessageGeneratedTime())) <= 300 ) { //after 300 seconds change color
this.getStyleClass().clear();
this.getStyleClass().add("messageHighlight300-column"); //add new special colored css reference
// setStyle("-fx-background-color: #FFF176;");
} else
{
if (ownMessage) {
styleClass = PrivateMessageRowStyleResolver
.resolveStyleClass(true, 0);
} else {
try {
final long ageSeconds = new Utils4KST()
.time_generateCurrentEpochTime()
- Long.parseLong(
item.getMessageGeneratedTime()
);
// setStyle("");
}
}
// switch (Integer.parseInt("" + (((new Utils4KST().time_generateCurrentEpochTime())) - (Long.parseLong(item.getMessageGeneratedTime()))))) {
// case int i
// } //TODO: update to JDK21 or bigger, then a range case is possible, improves speed maybe
styleClass = PrivateMessageRowStyleResolver
.resolveStyleClass(false, ageSeconds);
} catch (NumberFormatException exception) {
return;
}
}
// System.out.println("---> messagealter ---> " + (((new Utils4KST().time_generateCurrentEpochTime())) - (Long.parseLong(item.getMessageGeneratedTime()))));
} catch (Exception e) {
;
if (styleClass != null) {
getStyleClass().add(styleClass);
}
}
@@ -12952,4 +12938,4 @@ class CheckBoxTableCell<S, T> extends TableCell<S, T> {
}
}
@@ -0,0 +1,83 @@
package kst4contest.view;
import java.util.List;
/**
* Selects the CSS style class used for a private-message table row.
*/
public final class PrivateMessageRowStyleResolver {
/** Style used for messages sent by the local station. */
public static final String OWN_STYLE_CLASS =
"messageHighlightOwn-column";
/** Upper inclusive age bounds for the private-message color levels. */
private static final List<Long> AGE_LIMITS = List.of(
30L,
60L,
90L,
120L,
180L,
300L
);
/** Style classes corresponding to the configured age bounds. */
private static final List<String> AGE_STYLES = List.of(
"messageHighlight30-column",
"messageHighlight60-column",
"messageHighlight90-column",
"messageHighlight120-column",
"messageHighlight180-column",
"messageHighlight300-column"
);
/** All private-message row classes managed by the row factory. */
private static final List<String> MANAGED_STYLES = List.of(
OWN_STYLE_CLASS,
AGE_STYLES.get(0),
AGE_STYLES.get(1),
AGE_STYLES.get(2),
AGE_STYLES.get(3),
AGE_STYLES.get(4),
AGE_STYLES.get(5)
);
private PrivateMessageRowStyleResolver() {
}
/**
* Returns the complete set of private-message row classes managed by the
* row factory.
*
* @return immutable list of managed style classes
*/
public static List<String> knownStyleClasses() {
return MANAGED_STYLES;
}
/**
* Selects the private-message row class for the supplied message age.
*
* @param ownMessage whether the message was sent by the local station
* @param ageSeconds message age in seconds
* @return managed CSS class, or {@code null} after the five-minute window
*/
public static String resolveStyleClass(
final boolean ownMessage,
final long ageSeconds
) {
String styleClass = null;
if (ownMessage) {
styleClass = OWN_STYLE_CLASS;
} else {
for (int index = 0; index < AGE_LIMITS.size(); index++) {
if (ageSeconds <= AGE_LIMITS.get(index)) {
styleClass = AGE_STYLES.get(index);
break;
}
}
}
return styleClass;
}
}
@@ -0,0 +1,132 @@
package kst4contest.controller;
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
import java.time.Duration;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.Timeout;
import kst4contest.model.ChatMessage;
class On4KstConnectionProbeTest {
@Test
void buildsMainChatProbeAndAcceptsExpectedResponse() {
assertEquals("RDXQ|2|", On4KstProtocol.connectionProbe(2));
assertTrue(On4KstProtocol.isConnectionProbeResponse("DXQ|2|data|"));
assertFalse(On4KstProtocol.isConnectionProbeResponse(
"CH|2|123|DL1ABC|Name|0|text|0|"));
}
@Test
void selectsHeartbeatProbeAndTimeoutAtIdleBoundaries() {
assertEquals(
On4KstConnectionManager.IdleAction.NONE,
idleAction(90_000L, false, false));
assertEquals(
On4KstConnectionManager.IdleAction.HEARTBEAT,
idleAction(90_001L, false, false));
assertEquals(
On4KstConnectionManager.IdleAction.NONE,
idleAction(179_999L, true, false));
assertEquals(
On4KstConnectionManager.IdleAction.CONNECTION_PROBE,
idleAction(180_000L, true, false));
assertEquals(
On4KstConnectionManager.IdleAction.NONE,
idleAction(210_000L, true, true));
assertEquals(
On4KstConnectionManager.IdleAction.TIMEOUT,
idleAction(210_001L, true, true));
}
@Test
void oneSessionProbeIsAcknowledgedByAnyInboundTraffic() {
On4KstConnectionManager.ConnectionProbeState probe =
new On4KstConnectionManager.ConnectionProbeState();
assertTrue(probe.tryStart(1_000L));
assertFalse(probe.tryStart(1_001L),
"A second category must not start another session probe");
assertTrue(probe.isOutstanding());
assertEquals(250L, probe.acknowledge(1_250L));
assertFalse(probe.isOutstanding());
assertEquals(-1L, probe.acknowledge(1_500L));
assertTrue(probe.tryStart(2_000L),
"New inbound activity starts a new idle phase");
}
@Test
@Timeout(5)
void writerUsesExactCrLfForHeartbeatAndConnectionProbe() throws Exception {
byte[] expected = "\r\nRDXQ|2|\r\n".getBytes(StandardCharsets.UTF_8);
try (ServerSocket server = new ServerSocket(0)) {
CompletableFuture<byte[]> received = CompletableFuture.supplyAsync(() -> {
try (Socket accepted = server.accept()) {
accepted.setSoTimeout(2_000);
return accepted.getInputStream().readNBytes(expected.length);
} catch (Exception exception) {
throw new RuntimeException(exception);
}
});
try (Socket client = new Socket("127.0.0.1", server.getLocalPort())) {
LinkedBlockingQueue<ChatMessage> queue =
new LinkedBlockingQueue<>();
AtomicBoolean active = new AtomicBoolean(true);
WriteThread writer = new WriteThread(
11L,
client,
queue,
2,
ignored -> active.get(),
ignored -> { },
ignored -> { });
writer.start();
queue.add(serverFrame(""));
queue.add(serverFrame(On4KstProtocol.connectionProbe(2)));
assertArrayEquals(
expected,
received.get(2, TimeUnit.SECONDS));
active.set(false);
writer.interrupt();
writer.join(Duration.ofSeconds(2).toMillis());
}
}
}
private On4KstConnectionManager.IdleAction idleAction(
long inboundIdleMillis,
boolean heartbeatSent,
boolean probeOutstanding
) {
return On4KstConnectionManager.determineIdleAction(
inboundIdleMillis,
heartbeatSent,
probeOutstanding);
}
private ChatMessage serverFrame(String text) {
ChatMessage message = new ChatMessage();
message.setMessageDirectedToServer(true);
message.setMessageText(text);
return message;
}
}
@@ -0,0 +1,61 @@
package kst4contest.test;
import kst4contest.view.PrivateMessageRowStyleResolver;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNull;
class PrivateMessageRowStyleResolverTest {
@ParameterizedTest
@CsvSource({
"0, messageHighlight30-column",
"30, messageHighlight30-column",
"31, messageHighlight60-column",
"60, messageHighlight60-column",
"61, messageHighlight90-column",
"90, messageHighlight90-column",
"91, messageHighlight120-column",
"120, messageHighlight120-column",
"121, messageHighlight180-column",
"180, messageHighlight180-column",
"181, messageHighlight300-column",
"300, messageHighlight300-column"
})
void selectsAgeStyleClassAtEveryBoundary(
long ageSeconds,
String expectedStyleClass
) {
assertEquals(
expectedStyleClass,
PrivateMessageRowStyleResolver.resolveStyleClass(
false,
ageSeconds
)
);
}
@Test
void returnsNoAgeStyleClassAfterFiveMinutes() {
assertNull(
PrivateMessageRowStyleResolver.resolveStyleClass(
false,
301
)
);
}
@Test
void keepsOwnMessageStyleAfterFiveMinutes() {
assertEquals(
PrivateMessageRowStyleResolver.OWN_STYLE_CLASS,
PrivateMessageRowStyleResolver.resolveStyleClass(
true,
301
)
);
}
}
+2
View File
@@ -8,6 +8,7 @@ const MANUAL_PAGE_ORDER = {
"home",
"installation",
"konfiguration",
"contest-workflow",
"log-synchronisation",
"airscout-integration",
"dx-cluster-server",
@@ -20,6 +21,7 @@ const MANUAL_PAGE_ORDER = {
"home",
"installation",
"configuration",
"contest-workflow",
"log-sync",
"airscout-integration",
"dx-cluster-server",
+2 -2
View File
@@ -50,7 +50,7 @@ KST4Contest also updates the AirScout watchlist. Stations which are no longer ac
## How is the AirScout band selected?
> Automatic station-specific band selection is included in Nightly / v1.42. A fixed configured AirScout band remains available as a manual fallback.
> Automatic station-specific band selection is included from v1.42 onwards. A fixed configured AirScout band remains available as a manual fallback.
In **Auto per station** mode, KST4Contest uses the same propagation-frequency resolver as the internal path analysis. The sources are evaluated in the following order:
@@ -138,7 +138,7 @@ Each KST4Contest instance should use a distinct client identifier. Incoming AirS
This keeps a reply for one operating position from being assigned to another client merely because both listen on the same UDP network.
> Strict reply filtering by the configured client/server pair is included in Nightly / v1.42.
> Strict reply filtering by the configured client/server pair is included from v1.42 onwards.
## AP variables in messages
+1 -1
View File
@@ -66,7 +66,7 @@ All four entries belong to the same base callsign, but they are four different c
This is particularly important for `9A0BB-2` and `9A0BB-70`: because both use the same category, the category alone cannot distinguish them.
> Correct separation of several suffix variants within the same category is included in Nightly / v1.42 and fixes [Issue #73](https://github.com/praktimarc/kst4contest/issues/73).
> Correct separation of several suffix variants within the same category is included from v1.42 onwards and fixes [Issue #73](https://github.com/praktimarc/kst4contest/issues/73).
## How are messages routed?
+18 -13
View File
@@ -4,7 +4,7 @@ icon: 📡
category: Logger Integration
since: "1.23"
summary: Forward detected directional opportunities and their known frequencies as local DX Cluster spots to compatible contest loggers.
description: KST4Contest provides a local TCP DX Cluster server which turns selected ON4KST direction and frequency information into spots for a logger bandmap.
description: KST4Contest provides a local TCP DX Cluster server which forwards automatic directional opportunities or a manually selected map station to a logger bandmap.
tagsList:
- DX Cluster
- bandmap
@@ -29,9 +29,9 @@ The purpose is practical: when a station appears to be pointing in the local dir
That is the entire idea. The function is a bridge between the KST4Contest analysis and the logger, not another source of general DX traffic.
## When is a spot generated?
## Automatic and manual spots
A real spot is generated only when all of the following conditions are met:
An automatic spot is generated only when all of the following conditions are met:
1. A directed message between two other stations has been detected.
2. Valid locators are available for the sender and receiver.
@@ -39,10 +39,12 @@ A real spot is generated only when all of the following conditions are met:
4. The local station lies inside the assumed antenna corridor of the sender.
5. A usable frequency is known for the sender.
6. The local DX Cluster server is enabled.
7. At least one DX-Cluster client is connected to the server.
KST4Contest deliberately does not forward every frequency mentioned in the chat. Otherwise, a function intended to reduce distraction would produce its own local spot flood.
A spot can also be triggered deliberately. Select a station on the station map and use **Trigger cluster spot** in the detail panel. This manual action does not require a directed message, a match with the maximum QRB or a match with the configured antenna beamwidth. It uses the selected station and its known QRG directly.
For either route, at least one DX-Cluster client must be connected to receive the spot. Both automatic and manual spots remain inside the local or trusted station network; KST4Contest does not forward them to a public DX Cluster.
## How is the directional opportunity derived?
Assume that station A sends a directed message to station B. KST4Contest uses the direction from A to B as an approximation of the current antenna direction of station A.
@@ -124,24 +126,25 @@ A bare three-digit value is accepted only when the surrounding text identifies i
## What does the spot contain?
The generated spot contains:
Every generated spot contains:
- the configured spotter callsign;
- the normalised frequency;
- the complete callsign of the detected station;
- the sender's locator;
- up to two optional AirScout entries; and
- the complete visible callsign of the detected or selected station;
- the locator of that station;
- the current UTC time.
Automatically generated directional spots can additionally include up to two current AirScout entries. A manually triggered map spot uses the selected station's locator without this optional addition.
An example comment with AirScout information may look like this:
```text
JN49GL , AP: 1min, 100%; 4min, 75%
```
AirScout information is optional. A missing AirScout response does not prevent the spot from being sent.
AirScout information is optional. A missing AirScout response does not prevent an automatic directional spot from being sent.
> AP-independent spot creation, corrected sender-locator handling and band-generic frequency conversion are included in Nightly / v1.42.
> AP-independent spot creation, corrected sender-locator handling and band-generic frequency conversion are included from v1.42 onwards.
## Connecting a logger
@@ -199,6 +202,8 @@ A successful test confirms that at least one client received the generated spot.
- Was a valid frequency known?
- Did a station-specific band context change the relative QRG?
For a manual spot, check that the station remains selected on the map and has a usable QRG. Maximum QRB, beamwidth and directed-message geometry are not prerequisites for **Trigger cluster spot**.
## What the spot means — and what it does not
The spot means that KST4Contest detected a plausible directional opportunity and knew a frequency for the sender.
@@ -226,6 +231,6 @@ Other loggers may work if they can open a normal TCP connection to a DX Cluster
[Read the complete setup and troubleshooting section in the manual.](/manual/en/dx-cluster-server/)
[Read how directional opportunities are derived.](/manual/en/features/#sked-direction-highlighting)
[Read how directional opportunities are derived.](/manual/en/features/#directional-opportunities-from-directed-messages)
[Read how relative QRG information is configured.](/manual/en/configuration/#fallback-band-for-relative-qrg-detection)
[Read how relative QRG information is configured.](/manual/en/configuration/#fallback-band-for-relative-qrg-detection)
+1 -1
View File
@@ -48,7 +48,7 @@ STATUS packets can also update the local QRG. In multi-operator networks, a stat
Win-Test can additionally receive skeds created in KST4Contest. The handover only takes place when a QRG matching the selected band can be determined. No fixed fallback frequency is inserted merely to make the packet technically valid.
> The band-aware sked handover and explicit `SSB`/`CW` selection are included in Nightly / v1.42.
> The band-aware sked handover and explicit `SSB`/`CW` selection are included from v1.42 onwards.
## Stored state and limitations
+1 -1
View File
@@ -299,7 +299,7 @@ The priority list is calculated from the active station model and is independent
Selecting such a candidate still updates Further Info and prepares the directed message. The active filter remains unchanged.
> Correct band eligibility, base-callsign grouping, separate suffix routing, the final Sked-fail override and selection of filtered candidates are included in Nightly / v1.42.
> Correct band eligibility, base-callsign grouping, separate suffix routing, the final Sked-fail override and selection of filtered candidates are included from v1.42 onwards.
## When is the score updated?
+1 -1
View File
@@ -57,7 +57,7 @@ The frequency is not guessed. KST4Contest first looks for a recent QRG of the re
KST-specific suffixes such as `-2`, `-70` or `-144` are removed from the callsign passed to the log. Portable components such as `/P` and `/M` are preserved.
> Band-aware QRG validation, explicit `SSB`/`CW` selection and the corrected handling of KST suffixes are included in Nightly / v1.42.
> Band-aware QRG validation, explicit `SSB`/`CW` selection and the corrected handling of KST suffixes are included from v1.42 onwards.
![Sked handed over from KST4Contest to Win-Test](/manual/assets/wintest_sked_handover.png)
+1 -1
View File
@@ -37,7 +37,7 @@ AP candidates appear in the upper lanes. Up to four selected candidates can be s
Skeds appear as diamonds in the lower lane. Their labels use the complete selected KST callsign so that band-specific or otherwise suffixed logins remain identifiable.
> Complete KST callsigns in sked labels are included in Nightly / v1.42.
> Complete KST callsigns in sked labels are included from v1.42 onwards.
## Antenna direction remains visible
+13 -1
View File
@@ -72,6 +72,18 @@ description: Technisches Benutzerhandbuch für Installation, Konfiguration, ON4K
<a class="button ghost" href="/manual/de/benutzeroberflaeche/">Benutzeroberfläche</a>
</div>
</article>
<article class="card">
<h3>Contestbetrieb vorbereiten und durchführen</h3>
<p>
Der vollständige Arbeitsablauf von der Vorstartprüfung über CQ-Betrieb,
Kandidatenauswahl und Skeds bis zum Logeintrag und direkten Wechsel auf
ein weiteres Band.
</p>
<div class="actions">
<a class="button secondary" href="/manual/de/contest-workflow/">Contest-Workflow öffnen</a>
</div>
</article>
</div>
</section>
@@ -105,4 +117,4 @@ description: Technisches Benutzerhandbuch für Installation, Konfiguration, ON4K
{% endif %}
{% endfor %}
</div>
</section>
</section>
+13 -1
View File
@@ -72,6 +72,18 @@ description: Technical user manual covering installation, configuration, ON4KST
<a class="button ghost" href="/manual/en/user-interface/">User interface</a>
</div>
</article>
<article class="card">
<h3>Prepare and run contest operation</h3>
<p>
Follow the complete workflow from pre-start checks and CQ operation
through candidate selection and skeds to logging and an immediate move
to another band.
</p>
<div class="actions">
<a class="button secondary" href="/manual/en/contest-workflow/">Open the contest workflow</a>
</div>
</article>
</div>
</section>
@@ -105,4 +117,4 @@ description: Technical user manual covering installation, configuration, ON4KST
{% endif %}
{% endfor %}
</div>
</section>
</section>
+14 -1
View File
@@ -66,6 +66,19 @@ description: Technical user manual for KST4Contest, covering installation, stati
<a class="button ghost" href="/manual/de/funktionen/">Deutsche Funktionen</a>
</div>
</article>
<article class="card">
<h3>Prepare and run contest operation</h3>
<p>
Follow the complete workflow from pre-start checks and CQ operation
through candidate selection and skeds to logging and an immediate move
to another band.
</p>
<div class="actions">
<a class="button secondary" href="/manual/en/contest-workflow/">English workflow</a>
<a class="button ghost" href="/manual/de/contest-workflow/">German workflow</a>
</div>
</article>
</div>
</section>
@@ -87,4 +100,4 @@ description: Technical user manual for KST4Contest, covering installation, stati
<a class="button secondary" href="/roadmap/">View roadmap</a>
</div>
</div>
</section>
</section>
@@ -0,0 +1,23 @@
---
title: Version 1.42 released
summary: Shared band context, a session-based ON4KST connection and signed macOS packages
date: 2026-08-22
---
## Version 1.42 is out
v1.42 is available as a Stable release. It brings several previously separate calculations together: band information, Worked status, NOT-QRV marks, callsign suffixes and frequencies are now used consistently by the user list, the station map, the priority calculation and the external interfaces.
### The highlights
- **Shared band context:** One central band-opportunity calculation feeds the user list, *New bands*, the band-upgrade hint, the Priority Score, the station map and the automatic band selection. The band columns now distinguish `X`, `a`, `B+` and `o`, and 50 and 70 MHz are supported everywhere — from the station settings through to the Win-Test listener.
- **A connection you can trust:** The ON4KST link has been rebuilt around session-scoped connection handling with bounded timeouts, heartbeat detection and controlled reconnect backoff. A compact `LINK` indicator in the main window shows what the connection is actually doing, and the user list no longer disappears after login.
- **Signed and notarized macOS packages:** The DMG files for Apple Silicon and Intel are signed with an Apple Developer ID and notarized by Apple. The first launch now works by double-clicking, without the detour through **Open** in the context menu, and it works offline too.
- **More precise frequencies:** QRG recognition uses a station-specific band context, AirScout and the map path analysis derive realistic per-station frequencies, and the obsolete 430 MHz fallback is now 432 MHz.
The complete list of new functions, changes and fixed bugs is in the [changelog](/manual/en/changelog/) and in the [release notes](https://github.com/praktimarc/kst4contest/releases/tag/v1.42.0).
### Getting it
Packages for Windows, Linux and macOS are on the [download page](/download/) and in the [GitHub release](https://github.com/praktimarc/kst4contest/releases/tag/v1.42.0). Arch Linux users get it via the AUR as usual.
The German and English manuals have been checked against the source code, extended and re-screenshotted for this release. 73