mirror of
https://github.com/praktimarc/kst4contest.git
synced 2026-08-24 11:06:59 +02:00
fix(wintest): add band-aware sked QRG resolution, preserve portable callsigns, strip KST suffixes and correct ADDSKED timestamps
This commit is contained in:
@@ -318,86 +318,6 @@ public class ChatController implements ThreadStatusCallback, PstRotatorEventList
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Chooses a useful initial band for a new sked.
|
|
||||||
*
|
|
||||||
* <p>Recent frequency evidence has priority over station-name information.
|
|
||||||
* Manual NOT-QRV exclusions are respected. The operator can still select
|
|
||||||
* another locally enabled band from the dropdown.</p>
|
|
||||||
*/
|
|
||||||
private Band resolveDefaultSkedBand(ChatMember selectedMember,
|
|
||||||
EnumSet<Band> enabledBands) {
|
|
||||||
|
|
||||||
if (selectedMember == null || enabledBands == null || enabledBands.isEmpty()) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
List<ChatMember> variants =
|
|
||||||
chatcontroller.findActiveChatMembersByRawCall(
|
|
||||||
selectedMember.getCallSignRaw()
|
|
||||||
);
|
|
||||||
|
|
||||||
if (variants.isEmpty()) {
|
|
||||||
variants = List.of(selectedMember);
|
|
||||||
}
|
|
||||||
|
|
||||||
BandOpportunityResolver.Resolution resolution =
|
|
||||||
BandOpportunityResolver.resolve(
|
|
||||||
variants,
|
|
||||||
System.currentTimeMillis()
|
|
||||||
);
|
|
||||||
|
|
||||||
EnumSet<Band> availableBands = resolution.getAvailableBands();
|
|
||||||
availableBands.retainAll(enabledBands);
|
|
||||||
|
|
||||||
Band newestFrequencyBand = null;
|
|
||||||
long newestTimestamp = Long.MIN_VALUE;
|
|
||||||
long now = System.currentTimeMillis();
|
|
||||||
|
|
||||||
for (ChatMember member : variants) {
|
|
||||||
if (member == null || member.getKnownActiveBands() == null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (Map.Entry<Band, ChatMember.ActiveFrequencyInfo> entry
|
|
||||||
: member.getKnownActiveBands().entrySet()) {
|
|
||||||
|
|
||||||
Band band = entry.getKey();
|
|
||||||
ChatMember.ActiveFrequencyInfo info = entry.getValue();
|
|
||||||
|
|
||||||
if (band == null
|
|
||||||
|| info == null
|
|
||||||
|| !availableBands.contains(band)
|
|
||||||
|| !band.isPlausible(info.frequency)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
long ageMs = now - info.timestampEpoch;
|
|
||||||
if (ageMs < 0L
|
|
||||||
|| ageMs > BandOpportunityResolver.RECENT_DYNAMIC_EVIDENCE_MAX_AGE_MS) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (info.timestampEpoch > newestTimestamp) {
|
|
||||||
newestTimestamp = info.timestampEpoch;
|
|
||||||
newestFrequencyBand = band;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (newestFrequencyBand != null) {
|
|
||||||
return newestFrequencyBand;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!availableBands.isEmpty()) {
|
|
||||||
return availableBands.iterator().next();
|
|
||||||
}
|
|
||||||
|
|
||||||
return enabledBands.iterator().next();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public void stopRotator() {
|
public void stopRotator() {
|
||||||
if (rotatorClient != null) {
|
if (rotatorClient != null) {
|
||||||
rotatorClient.stop();
|
rotatorClient.stop();
|
||||||
|
|||||||
@@ -583,6 +583,84 @@ public class Kst4ContestApplication extends Application implements StatusUpdateL
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Chooses a useful initial band for a new sked.
|
||||||
|
*
|
||||||
|
* <p>Recent frequency evidence has priority over station-name information.
|
||||||
|
* Manual NOT-QRV exclusions are respected. The operator can still select
|
||||||
|
* another locally enabled band from the dropdown.</p>
|
||||||
|
*/
|
||||||
|
private Band resolveDefaultSkedBand(ChatMember selectedMember,
|
||||||
|
EnumSet<Band> enabledBands) {
|
||||||
|
|
||||||
|
if (selectedMember == null || enabledBands == null || enabledBands.isEmpty()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<ChatMember> variants =
|
||||||
|
chatcontroller.findActiveChatMembersByRawCall(
|
||||||
|
selectedMember.getCallSignRaw()
|
||||||
|
);
|
||||||
|
|
||||||
|
if (variants.isEmpty()) {
|
||||||
|
variants = List.of(selectedMember);
|
||||||
|
}
|
||||||
|
|
||||||
|
BandOpportunityResolver.Resolution resolution =
|
||||||
|
BandOpportunityResolver.resolve(
|
||||||
|
variants,
|
||||||
|
System.currentTimeMillis()
|
||||||
|
);
|
||||||
|
|
||||||
|
EnumSet<Band> availableBands = resolution.getAvailableBands();
|
||||||
|
availableBands.retainAll(enabledBands);
|
||||||
|
|
||||||
|
Band newestFrequencyBand = null;
|
||||||
|
long newestTimestamp = Long.MIN_VALUE;
|
||||||
|
long now = System.currentTimeMillis();
|
||||||
|
|
||||||
|
for (ChatMember member : variants) {
|
||||||
|
if (member == null || member.getKnownActiveBands() == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Map.Entry<Band, ChatMember.ActiveFrequencyInfo> entry
|
||||||
|
: member.getKnownActiveBands().entrySet()) {
|
||||||
|
|
||||||
|
Band band = entry.getKey();
|
||||||
|
ChatMember.ActiveFrequencyInfo info = entry.getValue();
|
||||||
|
|
||||||
|
if (band == null
|
||||||
|
|| info == null
|
||||||
|
|| !availableBands.contains(band)
|
||||||
|
|| !band.isPlausible(info.frequency)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
long ageMs = now - info.timestampEpoch;
|
||||||
|
if (ageMs < 0L
|
||||||
|
|| ageMs > BandOpportunityResolver.RECENT_DYNAMIC_EVIDENCE_MAX_AGE_MS) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (info.timestampEpoch > newestTimestamp) {
|
||||||
|
newestTimestamp = info.timestampEpoch;
|
||||||
|
newestFrequencyBand = band;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newestFrequencyBand != null) {
|
||||||
|
return newestFrequencyBand;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!availableBands.isEmpty()) {
|
||||||
|
return availableBands.iterator().next();
|
||||||
|
}
|
||||||
|
|
||||||
|
return enabledBands.iterator().next();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method generates a BoderPane which shows some additional information about a callsign which had been
|
* This method generates a BoderPane which shows some additional information about a callsign which had been
|
||||||
@@ -7350,6 +7428,17 @@ public class Kst4ContestApplication extends Application implements StatusUpdateL
|
|||||||
// chatMemberTableFilterQTFAndQRBHbox.set
|
// chatMemberTableFilterQTFAndQRBHbox.set
|
||||||
|
|
||||||
VBox chatMemberTableFilterVBoxForAllFilters= new VBox();
|
VBox chatMemberTableFilterVBoxForAllFilters= new VBox();
|
||||||
|
|
||||||
|
Button btnResetChatMemberFilters = new Button("Reset filters");
|
||||||
|
btnResetChatMemberFilters.getStyleClass().clear();
|
||||||
|
btnResetChatMemberFilters.getStyleClass().addAll(
|
||||||
|
"button",
|
||||||
|
"buttonMyQrg1"
|
||||||
|
);
|
||||||
|
btnResetChatMemberFilters.setTooltip(
|
||||||
|
new Tooltip("Disable all station-list filters and show every user")
|
||||||
|
);
|
||||||
|
|
||||||
chatMemberTableFilterVBoxForAllFilters.setSpacing(1);
|
chatMemberTableFilterVBoxForAllFilters.setSpacing(1);
|
||||||
|
|
||||||
chatMemberTableFilterVBoxForAllFilters.setMinWidth(0);
|
chatMemberTableFilterVBoxForAllFilters.setMinWidth(0);
|
||||||
@@ -7533,20 +7622,12 @@ public class Kst4ContestApplication extends Application implements StatusUpdateL
|
|||||||
"-fx-border-radius: 1;" +
|
"-fx-border-radius: 1;" +
|
||||||
"-fx-border-color: lightgrey;");
|
"-fx-border-color: lightgrey;");
|
||||||
|
|
||||||
// chatMemberTableFilterQTFAndQRBHbox.setFillHeight(true);
|
chatMemberTableFilterQTFAndQRBHbox.getChildren().addAll(
|
||||||
// chatMemberTableFilterQTFAndQRBHbox.setAlignment(Pos.CENTER_LEFT);
|
btnResetChatMemberFilters,
|
||||||
// chatMemberTableFilterQTFAndQRBHbox.getChildren().add(chatMemberTableFilterQRBHBox);
|
chatMemberTableFilterQRBHBox
|
||||||
chatMemberTableFilterQTFAndQRBHbox
|
);
|
||||||
.getChildren()
|
|
||||||
.add(chatMemberTableFilterQRBHBox);
|
|
||||||
|
|
||||||
|
|
||||||
// HBox chatMemberTableFilterQTFHBox = new HBox();
|
|
||||||
// FlowPane chatMemberTableFilterQTFHBox = new FlowPane();
|
|
||||||
// chatMemberTableFilterQTFHBox.setAlignment(Pos.CENTER_LEFT);
|
|
||||||
// chatMemberTableFilterQTFHBox.setPrefWidth(525);
|
|
||||||
// chatMemberTableFilterQTFHBox.setHgap(2);
|
|
||||||
|
|
||||||
FlowPane chatMemberTableFilterQTFHBox = new FlowPane(
|
FlowPane chatMemberTableFilterQTFHBox = new FlowPane(
|
||||||
Orientation.HORIZONTAL,
|
Orientation.HORIZONTAL,
|
||||||
2,
|
2,
|
||||||
@@ -7874,13 +7955,26 @@ public class Kst4ContestApplication extends Application implements StatusUpdateL
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// HBox chatMemberTableFilterWorkedBandFiltersHbx = new HBox();
|
|
||||||
|
|
||||||
FlowPane chatMemberTableFilterWorkedBandFiltersHbx = new FlowPane(
|
FlowPane chatMemberTableFilterWorkedBandFiltersHbx = new FlowPane(
|
||||||
Orientation.HORIZONTAL,
|
Orientation.HORIZONTAL,
|
||||||
2,
|
2,
|
||||||
3
|
3
|
||||||
);
|
);
|
||||||
|
|
||||||
|
HBox chatMemberTableReachabilityBox = new HBox(4);
|
||||||
|
chatMemberTableReachabilityBox.setAlignment(Pos.CENTER_LEFT);
|
||||||
|
chatMemberTableReachabilityBox.setMinWidth(0);
|
||||||
|
|
||||||
|
chatMemberTableReachabilityBox.setStyle(
|
||||||
|
"-fx-padding: 1;" +
|
||||||
|
"-fx-border-style: solid inside;" +
|
||||||
|
"-fx-border-width: 1;" +
|
||||||
|
"-fx-border-insets: 1;" +
|
||||||
|
"-fx-border-radius: 1;" +
|
||||||
|
"-fx-border-color: lightgrey;"
|
||||||
|
);
|
||||||
|
|
||||||
chatMemberTableFilterWorkedBandFiltersHbx.setAlignment(Pos.CENTER_LEFT);
|
chatMemberTableFilterWorkedBandFiltersHbx.setAlignment(Pos.CENTER_LEFT);
|
||||||
chatMemberTableFilterWorkedBandFiltersHbx.setRowValignment(VPos.CENTER);
|
chatMemberTableFilterWorkedBandFiltersHbx.setRowValignment(VPos.CENTER);
|
||||||
chatMemberTableFilterWorkedBandFiltersHbx.setMinWidth(0);
|
chatMemberTableFilterWorkedBandFiltersHbx.setMinWidth(0);
|
||||||
@@ -7932,9 +8026,11 @@ public class Kst4ContestApplication extends Application implements StatusUpdateL
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
chatMemberTableFilterWorkedBandFiltersHbx.getChildren().add(new Label("Reachability:"));
|
chatMemberTableReachabilityBox.getChildren().addAll(
|
||||||
chatMemberTableFilterWorkedBandFiltersHbx.getChildren().add(cmbReachabilityBand);
|
new Label("Reachability:"),
|
||||||
chatMemberTableFilterWorkedBandFiltersHbx.getChildren().add(btnCalculateSelectedTropo);
|
cmbReachabilityBand,
|
||||||
|
btnCalculateSelectedTropo
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* In order to work the filters needs the proper band settings, which should be worked
|
* In order to work the filters needs the proper band settings, which should be worked
|
||||||
@@ -8276,8 +8372,44 @@ public class Kst4ContestApplication extends Application implements StatusUpdateL
|
|||||||
btnTglAsNext5Min
|
btnTglAsNext5Min
|
||||||
);
|
);
|
||||||
|
|
||||||
// chatMemberTableFilterWorkedBandFilters
|
btnResetChatMemberFilters.setOnAction(event -> {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Reset the visible state of every station-list filter.
|
||||||
|
*
|
||||||
|
* Grid coloring and the selected reachability band are intentionally
|
||||||
|
* preserved because they are display/calculation settings, not filters.
|
||||||
|
*/
|
||||||
|
List.of(
|
||||||
|
btnTglNewLocator,
|
||||||
|
btnTglReachableTropo,
|
||||||
|
btnTglNewBands,
|
||||||
|
btnTglAsNext5Min,
|
||||||
|
tglBtnQRBEnable,
|
||||||
|
btnTglwkd,
|
||||||
|
btnTglwkd50,
|
||||||
|
btnTglwkd70,
|
||||||
|
btnTglwkd144,
|
||||||
|
btnTglwkd432,
|
||||||
|
btnTglwkd23,
|
||||||
|
btnTglwkd13,
|
||||||
|
btnTglwkd9,
|
||||||
|
btnTglwkd6,
|
||||||
|
btnTglwkd3,
|
||||||
|
btnTglInactive
|
||||||
|
).forEach(toggleButton -> toggleButton.setSelected(false));
|
||||||
|
|
||||||
|
tglGrpQTF.selectToggle(null);
|
||||||
|
chatMemberTableFilterQtfEnableChkbx.setSelected(false);
|
||||||
|
chatMemberTableFilterTextField.clear();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Programmatically changing a ToggleButton does not invoke its action
|
||||||
|
* handler. Clear the predicate list explicitly so no stale predicate
|
||||||
|
* can remain active.
|
||||||
|
*/
|
||||||
|
chatcontroller.getLst_chatMemberListFilterPredicates().clear();
|
||||||
|
});
|
||||||
|
|
||||||
chatMemberTableFilterTextFieldBox.getChildren().addAll(chatMemberTableFilterTextField);
|
chatMemberTableFilterTextFieldBox.getChildren().addAll(chatMemberTableFilterTextField);
|
||||||
|
|
||||||
@@ -8293,6 +8425,7 @@ public class Kst4ContestApplication extends Application implements StatusUpdateL
|
|||||||
|
|
||||||
chatMemberTableFilterTextFieldAndWorkedBandsHbx.getChildren().addAll(
|
chatMemberTableFilterTextFieldAndWorkedBandsHbx.getChildren().addAll(
|
||||||
chatMemberTableFilterTextFieldBox,
|
chatMemberTableFilterTextFieldBox,
|
||||||
|
chatMemberTableReachabilityBox,
|
||||||
chatMemberTableFilterWorkedBandFiltersHbx
|
chatMemberTableFilterWorkedBandFiltersHbx
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user