mirror of
https://github.com/praktimarc/kst4contest.git
synced 2026-08-04 01:15:27 +02:00
Changed sked opportunity highlighting mechanism to more precision, updated the manual
This commit is contained in:
@@ -37,6 +37,8 @@ Die zentrale Tabelle aller aktuell aktiven Chat-Nutzer. Spalten (je nach Konfigu
|
||||
|
||||
**Sortierung**: Klick auf Spaltenköpfe. QRB-Sortierung arbeitet numerisch (ab v1.22 korrigiert).
|
||||
|
||||
|
||||
Ein grün und fett dargestelltes Rufzeichen kennzeichnet eine aus einer gerichteten Nachricht hergeleitete Richtungsgelegenheit. Die Markierung bezieht sich auf den Absender der Nachricht und bleibt höchstens fünf Minuten sichtbar. Herleitung und Grenzen: [Richtungsgelegenheiten aus gerichteten Nachrichten](de-Funktionen#richtungsgelegenheiten-aus-gerichteten-nachrichten).
|
||||
### Sendfeld
|
||||
|
||||
Texteingabe für ausgehende Nachrichten. Nach Klick auf ein Rufzeichen in der Benutzerliste erhält das Sendfeld automatisch den Fokus – sofort tippen ohne Doppelklick (ab v1.22).
|
||||
|
||||
@@ -25,25 +25,29 @@ Im Klartext: Die Information muss nicht erst im Chat gefunden, gelesen, gemerkt
|
||||
|
||||
## Wie wird eine Richtungsgelegenheit hergeleitet?
|
||||
|
||||
Angenommen, Station A schreibt eine gerichtete Nachricht an Station B. KST4Contest geht in diesem Fall davon aus, dass Station A ihre Antenne zumindest ungefähr in Richtung von Station B ausgerichtet hat.
|
||||
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.
|
||||
|
||||
Anschließend werden zwei Richtungen verglichen:
|
||||
Dafür werden zwei Richtungen verglichen:
|
||||
|
||||
- die Richtung von Station A zu Station B,
|
||||
- die Richtung von Station A zur eigenen Station.
|
||||
|
||||
Liegt die eigene Station innerhalb des konfigurierten Antennen-Öffnungswinkels und befindet sich Station A innerhalb des eingestellten maximalen QRB, wird die Situation als Richtungsgelegenheit behandelt.
|
||||
Der in den Station Settings konfigurierte Antennen-Öffnungswinkel ist der vollständige Winkel. Für die Prüfung wird jeweils die Hälfte links und rechts der Richtung A → B angesetzt. Bei `70°` sind das somit `±35°`.
|
||||
|
||||
Da ON4KST keine Antennendaten der fremden Station überträgt, verwendet KST4Contest den Öffnungswinkel der eigenen Antenne zugleich als Näherung für Station A. Das ist keine Messung der tatsächlichen Antennenrichtung, sondern eine bewusst einfache geometrische Annahme.
|
||||
|
||||
Ein DX-Cluster-Spot wird nur erzeugt, wenn alle folgenden Bedingungen erfüllt sind:
|
||||
|
||||
1. Die Nachricht ist an eine konkrete andere Station gerichtet.
|
||||
1. Eine gerichtete Nachricht wurde zwischen zwei anderen Stationen erkannt.
|
||||
2. Für Absender und Empfänger sind gültige Locator bekannt.
|
||||
3. Der Absender liegt innerhalb des konfigurierten maximalen QRB.
|
||||
4. Die eigene Station liegt aus Sicht des Absenders innerhalb des konfigurierten Antennen-Öffnungswinkels.
|
||||
5. Für den Absender ist eine verwertbare Frequenz bekannt.
|
||||
3. Der Absender liegt innerhalb des konfigurierten maximalen QRB zur eigenen Station.
|
||||
4. Die eigene Station liegt aus Sicht des Absenders innerhalb des angenommenen Antennenkorridors.
|
||||
5. Für den Absender ist eine verwertbare Frequenz bekannt oder in der aktuellen Nachricht erkannt worden.
|
||||
6. Der lokale DX-Cluster-Server ist aktiviert.
|
||||
|
||||
Das Verfahren ist bewusst eine geometrische Herleitung. Es beweist weder, dass die Gegenstation tatsächlich mit genau dieser Antennenrichtung arbeitet, noch ersetzt es eine Ausbreitungsberechnung. Es erkennt eine plausible Gelegenheit. Mehr sollte man aus einer Chat-Nachricht auch nicht herauslesen.
|
||||
Treffen die Bedingungen zu, wird der Spot unmittelbar beim Verarbeiten der Nachricht erzeugt. Die parallel angezeigte grüne Richtungsmarkierung bleibt dagegen fünf Minuten sichtbar und kann durch spätere Nachrichten verlängert oder vorzeitig entfernt werden.
|
||||
|
||||
Das Verfahren berücksichtigt weder Gelände noch aktuelle Ausbreitungsbedingungen und beweist keine tatsächliche Antennenstellung. Es erkennt eine plausible Gelegenheit. Die ausführliche Herleitung und ein Zahlenbeispiel stehen unter [Richtungsgelegenheiten aus gerichteten Nachrichten](de-Funktionen#richtungsgelegenheiten-aus-gerichteten-nachrichten).
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -2,45 +2,71 @@
|
||||
|
||||
> 🇬🇧 [English version](en-Features) | 🇩🇪 Du liest gerade die deutsche Version
|
||||
|
||||
Übersicht aller Hauptfunktionen von KST4Contest.
|
||||
Dieses Kapitel beschreibt die wichtigsten Funktionen von KST4Contest, ihre Herleitung und die Grenzen der daraus gewonnenen Informationen.
|
||||
|
||||
---
|
||||
## Richtungsgelegenheiten aus gerichteten Nachrichten
|
||||
|
||||
## Sked-Richtungs-Hervorhebung
|
||||
Im ON4KST-Chat ist sichtbar, welche Station eine Nachricht an welche andere Station richtet. Eine tatsächliche Antennenrichtung wird dabei nicht übertragen. Für den Contestbetrieb lässt sich aus einer solchen Nachricht trotzdem eine brauchbare Annahme ableiten: Wer einen Sked anfragt, beantwortet oder vorbereitet, richtet seine Antenne normalerweise zumindest ungefähr auf die angesprochene Station.
|
||||
|
||||
Eine der Kernfunktionen: Wenn eine Station ein Sked in die **eigene Richtung** sendet, wird sie in der Benutzerliste **grün und fett** hervorgehoben.
|
||||
KST4Contest wertet deshalb gerichtete Nachrichten zwischen zwei anderen Stationen aus. Die Nachricht muss nicht ausdrücklich als Sked gekennzeichnet sein. Entscheidend sind der Absender, der Empfänger und deren Locator.
|
||||
|
||||
### Wie funktioniert das?
|
||||
### Wie wird die Richtung hergeleitet?
|
||||
|
||||
Die Berechnung basiert auf folgender Logik:
|
||||
Angenommen, Station A schreibt eine gerichtete Nachricht an Station B:
|
||||
|
||||
- Wenn Station A eine Sked-Anfrage an Station B sendet, wird angenommen, dass A ihre Antenne auf B ausrichtet.
|
||||
- Wenn die daraus resultierende Richtung von A zur eigenen Station innerhalb des halben Öffnungswinkels der eigenen Antenne liegt, wird A hervorgehoben.
|
||||
1. KST4Contest berechnet die Richtung von Station A zu Station B.
|
||||
2. Diese Richtung wird als wahrscheinliche Antennenrichtung von Station A verwendet.
|
||||
3. Anschließend wird die Richtung von Station A zur eigenen Station berechnet.
|
||||
4. Die Winkeldifferenz wird mit der Hälfte des konfigurierten Antennen-Öffnungswinkels verglichen.
|
||||
5. Zusätzlich muss Station A innerhalb des konfigurierten maximalen QRB liegen.
|
||||
|
||||
**Beispiel** (Öffnungswinkel 69°, Halbwinkel 34,5°):
|
||||
Ein eingetragener Öffnungswinkel von `70°` ergibt damit einen angenommenen Korridor von jeweils `35°` links und rechts der Richtung von Station A zu Station B.
|
||||
|
||||
| Situation | Ergebnis für DO5AMF in JN49 |
|
||||
| Beispiel | Ergebnis |
|
||||
|---|---|
|
||||
| Sked von F5FEN → DM5M | ✅ Hervorhebung (F5FEN zeigt Richtung DM5M, das liegt nahe JN49) |
|
||||
| Sked von DM5M → F5FEN | ✅ Hervorhebung (DM5M antwortet in Richtung F5FEN) |
|
||||
| F1DBN ist unbeteiligt | ❌ Keine Hervorhebung |
|
||||
| DO5AMF/P (anderer Standort) | ❌ Keine Hervorhebung für Sked-Antwort |
|
||||
| Richtung A → B: `120°`, Richtung A → eigene Station: `145°` | Winkeldifferenz `25°`: Richtungsgelegenheit erkannt |
|
||||
| Richtung A → B: `120°`, Richtung A → eigene Station: `165°` | Winkeldifferenz `45°`: außerhalb des angenommenen Korridors |
|
||||
| Locator von A oder B fehlt | Keine Richtungsberechnung möglich |
|
||||
| A liegt außerhalb des maximalen QRB | Keine Richtungsgelegenheit |
|
||||
|
||||
Die Berechnung berücksichtigt keine topografischen Wegberechnungen – das ist eine bewusste Vereinfachung. Möglicherweise wird das in einer späteren Version ergänzt.
|
||||
### Was wird in der Benutzerliste angezeigt?
|
||||
|
||||
> Konfiguration: [Konfiguration – Antennen-Öffnungswinkel](Konfiguration#antennen-öffnungswinkel-antenna-beamwidth)
|
||||
Wird eine Richtungsgelegenheit erkannt, erscheint das Rufzeichen des Absenders in der Benutzerliste grün und fett. Im Evening-Modus wird dafür ein helleres Grün verwendet. Der Empfänger der Nachricht wird nicht allein deshalb markiert; eine Antwort in Gegenrichtung wird als eigene Nachricht und damit als neuer Fall berechnet.
|
||||
|
||||

|
||||
|
||||
Im Bild sendete DF0GEB eine gerichtete Nachricht an DN9APW und bekam eine Antwort. KST4Contest erkannte die Richtungsgelegenheit und markierte DN9APW in der Benutzerliste.
|
||||
Zur Verdeutlichung ist die MAP eingeblendet. Ich stehe als Empfänger zwischen beiden Stationen und bekomme deswegen die Warnung.
|
||||
|
||||
Die Markierung bleibt fünf Minuten ab der letzten passenden Nachricht sichtbar. Eine weitere passende Nachricht derselben Station beginnt diesen Zeitraum erneut. Sendet die Station vorher eine gerichtete Nachricht, deren Richtung die Bedingungen nicht erfüllt, wird die Markierung unmittelbar entfernt.
|
||||
|
||||
Ist die einfache Soundausgabe aktiviert, gibt KST4Contest beim erstmaligen Erkennen der Richtungsgelegenheit zusätzlich einen kurzen Hinweis aus. Solange die Station bereits markiert ist, wird derselbe Hinweis nicht mit jeder weiteren passenden Nachricht wiederholt.
|
||||
|
||||
### Was bedeutet die Markierung – und was nicht?
|
||||
|
||||
Die Berechnung ist eine geometrische Herleitung. Sie beweist nicht, dass Station A ihre Antenne tatsächlich auf Station B ausgerichtet hat. Ebenso wenig berücksichtigt sie Gelände, aktuelle Ausbreitungsbedingungen, die reale Antennencharakteristik der fremden Station oder deren Rotatorposition.
|
||||
|
||||
ON4KST liefert keinen individuellen Öffnungswinkel für die fremde Station. KST4Contest verwendet deshalb den für die eigene Antenne konfigurierten Wert auch als Näherung für Station A. Ein zu großer Wert erzeugt entsprechend mehr mögliche Richtungsgelegenheiten, ein zu kleiner Wert kann brauchbare Situationen übersehen.
|
||||
|
||||
Im Klartext: Die grüne Markierung ist ein begründeter Hinweis auf eine mögliche Gelegenheit. Sie ist weder eine Ausbreitungsvorhersage noch eine Garantie für ein QSO.
|
||||
|
||||
Konfiguration:
|
||||
|
||||
- [Antennen-Öffnungswinkel](de-Konfiguration#antennen-öffnungswinkel-antenna-beamwidth)
|
||||
- [Standard-Maximum-QRB](de-Konfiguration#standard-maximum-qrb)
|
||||
|
||||
---
|
||||
|
||||
## Sked-Richtungs-Spots (Integrierter DX-Cluster)
|
||||
## Weitergabe als DX-Cluster-Spot
|
||||
|
||||
Seit Version 1.23 kann KST4Contest erkannte Richtungsgelegenheiten als DX-Cluster-Spots an ein verbundenes Logprogramm weitergeben.
|
||||
Seit Version 1.23 kann KST4Contest eine erkannte Richtungsgelegenheit an den DX-Cluster-Client eines Logprogramms weitergeben. Dafür muss der lokale DX-Cluster-Server aktiviert und für den Absender eine verwertbare Frequenz bekannt sein.
|
||||
|
||||
Aus einer gerichteten Chat-Nachricht wird zunächst die wahrscheinliche Antennenrichtung des Absenders hergeleitet. Liegt die eigene Station innerhalb des konfigurierten Öffnungswinkels und ist eine Frequenz bekannt, erscheint die Station als Spot in der Bandmap des Logprogramms.
|
||||
Die Frequenz kann bereits aus einer früheren Nachricht stammen oder erstmals in der aktuell auslösenden Nachricht stehen. In beiden Fällen steht sie der Spot-Prüfung zur Verfügung. KST4Contest überträgt damit nicht jede im Chat gefundene QRG, sondern nur Frequenzen, die mit einer geometrisch passenden gerichteten Nachricht zusammenfallen.
|
||||
|
||||
KST4Contest überträgt damit nicht jede gefundene Frequenz, sondern nur Situationen, die für die eigene Station geometrisch plausibel sind.
|
||||
Die Fünf-Minuten-Markierung und der DX-Cluster-Spot beruhen auf derselben Richtungsberechnung, haben aber einen unterschiedlichen Lebenszyklus: Die Markierung bleibt vorübergehend in der Benutzerliste sichtbar. Der Spot wird unmittelbar beim Verarbeiten der passenden Nachricht erzeugt.
|
||||
|
||||
Details: [Integrierter DX-Cluster-Server](de-DX-Cluster-Server).
|
||||
Einrichtung, Frequenzbehandlung und Grenzen: [Integrierter DX-Cluster-Server](de-DX-Cluster-Server).
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -29,13 +29,25 @@ Eigenes Rufzeichen und Maidenhead-Locator (6-stellig, z. B. `JN49IJ`) eintragen.
|
||||
|
||||
### Antennen-Öffnungswinkel (Antenna Beamwidth)
|
||||
|
||||
Einen realistischen Wert für den Öffnungswinkel der eigenen Antenne eintragen (in Grad). Dieser Wert wird für die [Sked-Richtungs-Hervorhebung](Funktionen#sked-richtungs-hervorhebung) verwendet. Ein Testwert von 50° hat sich bewährt; DM5M nutzt Quads mit 69°.
|
||||
Trage den vollständigen horizontalen Öffnungswinkel der eigenen Antenne in Grad ein. KST4Contest verwendet jeweils die Hälfte dieses Werts links und rechts der gewählten beziehungsweise hergeleiteten Antennenrichtung. Ein eingetragener Wert von `70°` entspricht daher einem Korridor von `±35°`.
|
||||
|
||||
> **Keinesfalls** Fantasy-Werte eintragen – die Richtungsberechnungen werden sonst unbrauchbar.
|
||||
Der Wert wird an mehreren Stellen verwendet:
|
||||
|
||||
- für den QTF-Filter der Benutzerliste,
|
||||
- für die Darstellung des eigenen Antennenkorridors,
|
||||
- als angenommener Öffnungswinkel einer fremden Station bei der [Herleitung von Richtungsgelegenheiten](de-Funktionen#richtungsgelegenheiten-aus-gerichteten-nachrichten).
|
||||
|
||||
Der letzte Punkt ist bewusst eine Näherung. ON4KST überträgt weder die verwendete Antenne noch deren Öffnungswinkel. KST4Contest verwendet deshalb den eigenen Wert als praktikable Annahme für die Gegenstation.
|
||||
|
||||
Wähle einen realistischen Wert. Ein zu großer Öffnungswinkel erzeugt viele geometrische Treffer, die praktisch kaum noch eine Aussage haben. Ein zu kleiner Wert kann dagegen brauchbare Richtungsgelegenheiten ausblenden.
|
||||
|
||||
### Standard-Maximum-QRB
|
||||
|
||||
Maximale Entfernung (in km), für die Richtungs-Warnungen ausgelöst werden sollen. Realistischer Wert für DM5M: 900 km. Stationen, die weiter entfernt sind, werden für Highlighting-Zwecke ignoriert.
|
||||
Trage die maximale Entfernung in Kilometern ein, innerhalb der KST4Contest Richtungsgelegenheiten berücksichtigen soll. Maßgeblich ist die Entfernung zwischen der eigenen Station und dem Absender der gerichteten Nachricht – nicht die Entfernung zwischen Absender und Empfänger.
|
||||
|
||||
Liegt der Absender weiter entfernt, wird die Situation auch dann nicht hervorgehoben und nicht als Richtungsgelegenheit an den lokalen DX-Cluster-Server weitergegeben, wenn der berechnete Winkel passen würde.
|
||||
|
||||
Der Wert sollte zum eigenen Stationsaufbau und zum vorgesehenen Contestbetrieb passen. Ein unnötig großer Bereich erzeugt Hinweise für Stationen, die praktisch nicht mehr zum Arbeitsbereich gehören; ein zu kleiner Bereich blendet mögliche Kandidaten bereits vor der Richtungsbewertung aus.
|
||||
|
||||
---
|
||||
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 961 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 391 KiB After Width: | Height: | Size: 389 KiB |
@@ -776,6 +776,19 @@ public class MessageBusManagementThread extends Thread {
|
||||
newMessageArrived));
|
||||
}
|
||||
|
||||
/*
|
||||
* Detect and store the sender's QRG before any directional-opportunity
|
||||
* or DX-Cluster processing. A frequency first mentioned in this directed
|
||||
* message is then immediately available for the resulting spot.
|
||||
*
|
||||
* The parser needs only the message text, sender and preferences. The
|
||||
* receiver does not have to be resolved yet.
|
||||
*/
|
||||
smartFrequencyExtraction(
|
||||
newMessageArrived,
|
||||
this.client.getChatPreferences());
|
||||
|
||||
// TODO: Next: get frequency infos out of name?
|
||||
|
||||
if (splittedMessageLine[7].equals("0")) {
|
||||
// message is not directed to anyone, move it to the cq messages.
|
||||
@@ -1058,9 +1071,6 @@ public class MessageBusManagementThread extends Thread {
|
||||
exceptionOccured.printStackTrace();
|
||||
}
|
||||
|
||||
// --- Band/QRG recognition (fills ChatMember.knownActiveBands) ---
|
||||
smartFrequencyExtraction(newMessageArrived, this.client.getChatPreferences());
|
||||
|
||||
// TODO: Next: get frequency infos out of name?
|
||||
} else
|
||||
|
||||
|
||||
@@ -26,9 +26,16 @@ public class ChatMember {
|
||||
String name;
|
||||
String callSignRaw; //without -2 or -70 etc.
|
||||
|
||||
/**
|
||||
* A directional opportunity inferred from a directed chat message remains
|
||||
* relevant for five minutes. The timestamp is used instead of a permanent
|
||||
* boolean so an old antenna-direction assumption cannot remain visible
|
||||
* indefinitely.
|
||||
*/
|
||||
static final long DIRECTION_OPPORTUNITY_VALIDITY_MILLIS = 5L * 60L * 1000L;
|
||||
|
||||
private volatile long directionOpportunityValidUntilEpochMs;
|
||||
|
||||
boolean isInAngleAndRange; //if he tries a sked in my dir, he is in range, will process that in the messages
|
||||
|
||||
// String frequency; // last known qrg of the station
|
||||
|
||||
@@ -108,12 +115,37 @@ public class ChatMember {
|
||||
this.lastFlagsChangeEpochMs = lastFlagsChangeEpochMs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the most recently inferred directional opportunity is
|
||||
* still valid.
|
||||
*
|
||||
* @return {@code true} until the five-minute validity period has expired
|
||||
*/
|
||||
public boolean isInAngleAndRange() {
|
||||
return isInAngleAndRange;
|
||||
return isInAngleAndRangeAt(System.currentTimeMillis());
|
||||
}
|
||||
|
||||
/**
|
||||
* Time-aware variant used by the public getter and by unit tests.
|
||||
*
|
||||
* @param nowEpochMs time against which the validity is checked
|
||||
* @return {@code true} while the stored validity timestamp is still in the future
|
||||
*/
|
||||
boolean isInAngleAndRangeAt(long nowEpochMs) {
|
||||
return directionOpportunityValidUntilEpochMs > nowEpochMs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts a new five-minute validity period or removes the current
|
||||
* directional opportunity immediately.
|
||||
*
|
||||
* @param inAngleAndRange {@code true} for a newly detected opportunity;
|
||||
* {@code false} to clear it
|
||||
*/
|
||||
public void setInAngleAndRange(boolean inAngleAndRange) {
|
||||
isInAngleAndRange = inAngleAndRange;
|
||||
directionOpportunityValidUntilEpochMs = inAngleAndRange
|
||||
? System.currentTimeMillis() + DIRECTION_OPPORTUNITY_VALIDITY_MILLIS
|
||||
: 0L;
|
||||
}
|
||||
|
||||
public AirPlaneReflectionInfo getAirPlaneReflectInfo() {
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
package kst4contest.model;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
class ChatMemberDirectionOpportunityTest {
|
||||
|
||||
@Test
|
||||
void directionalOpportunityExpiresAfterConfiguredValidityPeriod() {
|
||||
ChatMember member = new ChatMember();
|
||||
|
||||
member.setInAngleAndRange(true);
|
||||
long afterActivationEpochMs = System.currentTimeMillis();
|
||||
|
||||
assertTrue(member.isInAngleAndRangeAt(afterActivationEpochMs));
|
||||
assertFalse(member.isInAngleAndRangeAt(
|
||||
afterActivationEpochMs
|
||||
+ ChatMember.DIRECTION_OPPORTUNITY_VALIDITY_MILLIS
|
||||
+ 1L));
|
||||
}
|
||||
|
||||
@Test
|
||||
void directionalOpportunityCanBeClearedImmediately() {
|
||||
ChatMember member = new ChatMember();
|
||||
|
||||
member.setInAngleAndRange(true);
|
||||
assertTrue(member.isInAngleAndRange());
|
||||
|
||||
member.setInAngleAndRange(false);
|
||||
assertFalse(member.isInAngleAndRange());
|
||||
}
|
||||
}
|
||||
@@ -1277,115 +1277,65 @@ public class Kst4ContestApplication extends Application implements StatusUpdateL
|
||||
tbl_chatMemberTable.setTooltip(new Tooltip(
|
||||
"Stations available \n\nUse right click to a station to select predefined texts\nor hit <strg> + <1> ... <9> to write textsnippet to selected station\n\nHit <enter> to send"));
|
||||
|
||||
TableColumn<ChatMember, String> callSignCol = new TableColumn<ChatMember, String>("Callsign");
|
||||
callSignCol.setCellValueFactory(new Callback<CellDataFeatures<ChatMember, String>, ObservableValue<String>>() {
|
||||
TableColumn<ChatMember, String> callSignCol =
|
||||
new TableColumn<ChatMember, String>("Callsign");
|
||||
|
||||
@Override
|
||||
public ObservableValue<String> call(CellDataFeatures<ChatMember, String> cellDataFeatures) {
|
||||
SimpleStringProperty callsgn = new SimpleStringProperty();
|
||||
callSignCol.setCellValueFactory(cellDataFeatures -> {
|
||||
ChatMember member = cellDataFeatures.getValue();
|
||||
|
||||
ChatMember member = cellDataFeatures.getValue();
|
||||
String baseCallsign;
|
||||
|
||||
if (member.getState() == 1) {
|
||||
baseCallsign = "(" + member.getCallSign() + ")"; //away user
|
||||
} else {
|
||||
baseCallsign = member.getCallSign();
|
||||
}
|
||||
|
||||
callsgn.setValue(baseCallsign);
|
||||
|
||||
// System.out.println(member.getCallSign() + " / " + member.getState()+ " <<<<<<<<<<<<<<<<<< state ");
|
||||
|
||||
return callsgn;
|
||||
if (member == null || member.getCallSign() == null) {
|
||||
return new SimpleStringProperty("");
|
||||
}
|
||||
|
||||
String displayedCallsign = member.getState() == 1
|
||||
? "(" + member.getCallSign() + ")"
|
||||
: member.getCallSign();
|
||||
|
||||
return new SimpleStringProperty(displayedCallsign);
|
||||
});
|
||||
|
||||
callSignCol.setCellFactory(new Callback<TableColumn<ChatMember, String>, TableCell<ChatMember, String>>() {
|
||||
public TableCell call(TableColumn param) {
|
||||
callSignCol.setCellFactory(column -> new TableCell<ChatMember, String>() {
|
||||
|
||||
return new TableCell<ChatMember, String>() {
|
||||
@Override
|
||||
protected void updateItem(String item, boolean empty) {
|
||||
super.updateItem(item, empty);
|
||||
|
||||
/*
|
||||
* JavaFX reuses TableCell instances while the user scrolls, sorts or
|
||||
* filters the table. Every visual state must therefore be reset before
|
||||
* the cell is populated with another ChatMember.
|
||||
*/
|
||||
getStyleClass().remove("table-cell-inAngleAndRange");
|
||||
setGraphic(null);
|
||||
|
||||
@Override
|
||||
public void updateItem(String item, boolean empty) {
|
||||
if (empty || item == null) {
|
||||
setText(null);
|
||||
setStyle("");
|
||||
return;
|
||||
}
|
||||
|
||||
super.updateItem(item, empty);
|
||||
setText(item);
|
||||
|
||||
int currentIndex = indexProperty().getValue() < 0 ? 0 : indexProperty().getValue();
|
||||
// System.out.println(">>>>>>>>>>>>>>>> INDEXPROPERTY = " + indexProperty().getValue() + " " + getIndex() + " / " + item);
|
||||
ChatMember chatMember = getTableRow() == null
|
||||
? null
|
||||
: getTableRow().getItem();
|
||||
|
||||
if (chatMember == null) {
|
||||
setStyle("");
|
||||
return;
|
||||
}
|
||||
|
||||
if (item != null) {
|
||||
boolean useBoldFont = chatMember.getState() == 2
|
||||
|| chatMember.getState() == 3;
|
||||
|
||||
ChatMember chatMember = (ChatMember) param.getTableView().getItems().get(currentIndex);
|
||||
// System.out.println(chatMember.getCallSign() + " / " + chatMember.getState() + " <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<state ");
|
||||
if (chatMember.isInAngleAndRange()) {
|
||||
getStyleClass().add("table-cell-inAngleAndRange");
|
||||
useBoldFont = true;
|
||||
}
|
||||
|
||||
// System.out.println(this.getStyleClass() + "<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<");
|
||||
// this.getStyleClass().clear(); //clear css reference, then recoloring
|
||||
// this.getStyleClass().add("table-cell"); //set old reference
|
||||
|
||||
|
||||
// System.out.println("KST4Contestapp ************************************** members state is: " + chatMember.getState());
|
||||
|
||||
if (chatMember.getState() == 3 ) { //login in last 5 min
|
||||
// System.out.println("####################################### fATfatFett");
|
||||
this.setStyle("-fx-font-weight: bold");
|
||||
// this.getStyleClass().clear();
|
||||
// this.getStyleClass().add("table-cell-bold"); //add new special colored css reference
|
||||
|
||||
} else if (chatMember.getState() == 0 ) { //here
|
||||
// this.getStyleClass().clear();
|
||||
// this.getStyleClass().add("table-cell");
|
||||
this.setStyle("-fx-font-weight: normal");
|
||||
} else if (chatMember.getState() == 2 ) { //here and relogin
|
||||
// this.getStyleClass().clear();
|
||||
// this.getStyleClass().add("table-cell-bold");
|
||||
this.setStyle("-fx-font-weight: bold");
|
||||
} else if (chatMember.getState() == 1 ) { //away
|
||||
// this.getStyleClass().clear();
|
||||
// this.getStyleClass().add("table-cell");
|
||||
this.setStyle("-fx-font-weight: normal");
|
||||
}
|
||||
|
||||
if (chatMember.isInAngleAndRange()) {
|
||||
// this.getStyleClass().add("table-cell-inAngleAndRange");
|
||||
|
||||
//// getStyleClass().add("");
|
||||
this.setTextFill(Color.LIGHTGREEN);
|
||||
this.setStyle("-fx-font-weight: bold");
|
||||
}
|
||||
|
||||
|
||||
// else if (chatMember.getState() != 3){ //TODO: this double handling should be improved as may there can be new markers. Neccessarry to reset the colour to black
|
||||
// this.setTextFill(Color.BLACK);
|
||||
// this.setStyle("-fx-font-weight: normal");
|
||||
// } else {
|
||||
// this.setTextFill(Color.BLACK);
|
||||
// }
|
||||
|
||||
// if ((Utils4KST.time_getSecondsBetweenEpochAndNow(chatMember.getActivityTimeLastInEpoch()+"") /60%60) < 2) {
|
||||
// this.setTextFill(Color.ORANGE);
|
||||
// }
|
||||
}
|
||||
|
||||
|
||||
// if (!isEmpty()) {
|
||||
// this.setTextFill(Color.BLACK);
|
||||
// // Get fancy and change color based on data
|
||||
//
|
||||
// if (item.contains("5")) {
|
||||
// this.setTextFill(Color.BLUEVIOLET);
|
||||
// } else if (item.contains("7") ) {
|
||||
// this.setTextFill(Color.RED);
|
||||
// } else if (item.contains("0") ) {
|
||||
// this.setTextFill(Color.ORANGE);
|
||||
// }
|
||||
////
|
||||
setText(item);
|
||||
// }
|
||||
}
|
||||
};
|
||||
setStyle(useBoldFont
|
||||
? "-fx-font-weight: bold;"
|
||||
: "-fx-font-weight: normal;");
|
||||
}
|
||||
});
|
||||
|
||||
@@ -7470,7 +7420,23 @@ public class Kst4ContestApplication extends Application implements StatusUpdateL
|
||||
|
||||
|
||||
// chatMemberTableFilterQTFHBox.setSpacing(5);
|
||||
chatMemberTableFilterQTFHBox.getChildren().addAll(chatMemberTableFilterQtfTF, new Label("deg +/- " + chatcontroller.getChatPreferences().getStn_antennaBeamWidthDeg() + ""), qtfNorth, qtfNorthEast, qtfEast, qtfSouthEast, qtfSouth, qtfSouthWest, qtfWest, qtfNorthWest);
|
||||
Label lblQtfHalfBeamwidth = new Label("± BW/2");
|
||||
lblQtfHalfBeamwidth.setTooltip(new Tooltip(
|
||||
"The QTF filter uses half of the configured total antenna beamwidth "
|
||||
+ "on each side of the selected direction."));
|
||||
|
||||
chatMemberTableFilterQTFHBox.getChildren().addAll(
|
||||
chatMemberTableFilterQtfTF,
|
||||
lblQtfHalfBeamwidth,
|
||||
qtfNorth,
|
||||
qtfNorthEast,
|
||||
qtfEast,
|
||||
qtfSouthEast,
|
||||
qtfSouth,
|
||||
qtfSouthWest,
|
||||
qtfWest,
|
||||
qtfNorthWest);
|
||||
|
||||
chatMemberTableFilterQTFAndQRBHbox.getChildren().add(chatMemberTableFilterQTFHBox);
|
||||
|
||||
chatMemberTableFilterVBoxForAllFilters.getChildren().add(chatMemberTableFilterQTFAndQRBHbox);
|
||||
@@ -8474,7 +8440,12 @@ public class Kst4ContestApplication extends Application implements StatusUpdateL
|
||||
|
||||
TextField txtFldstn_antennaBeamWidthDeg = new TextField(this.chatcontroller.getChatPreferences().getStn_antennaBeamWidthDeg() + "");
|
||||
txtFldstn_antennaBeamWidthDeg.setFocusTraversable(false);
|
||||
txtFldstn_antennaBeamWidthDeg.setTooltip(new Tooltip("Your antenna beamwidth in DEG\n\nEnter correct values here due it´s used for path suggestions!!!"));
|
||||
txtFldstn_antennaBeamWidthDeg.setTooltip(new Tooltip(
|
||||
"Your antenna beamwidth in degrees.\n\n"
|
||||
+ "KST4Contest also uses this value as an assumed beamwidth "
|
||||
+ "for other stations when it derives directional opportunities "
|
||||
+ "from directed chat messages."));
|
||||
|
||||
txtFldstn_antennaBeamWidthDeg.textProperty().addListener(new ChangeListener<String>() {
|
||||
|
||||
@Override
|
||||
|
||||
Reference in New Issue
Block a user