fixed prio score penalty on sked fail

This commit is contained in:
Marc Froehlich
2026-08-10 03:06:06 +02:00
parent 00aefdacd5
commit 401f271d56
2 changed files with 42 additions and 32 deletions
@@ -83,12 +83,13 @@ public class PriorityCalculator {
// --------------------------------------------------------------------
double score = 100.0;
// if (!member.isWorked()) {
// score += 200.0;
// }
//"worked" for scoring is derived ONLY from per-band flags (worked144/432/...)
// EnumSet<Band> workedBandsForScoring = getWorkedBands(member);
/*
* A manual Sked-fail mark represents an explicit operator decision. The
* penalty is therefore applied after all positive contributions, including
* an imminent sked. Applying it earlier would allow the later sked boost to
* almost completely cancel the failure mark.
*/
boolean manualSkedFailed = false;
if (workedBandsForScoring.isEmpty()) {
score += 200.0; // never worked on any supported band -> higher priority
@@ -190,9 +191,11 @@ public class PriorityCalculator {
}
// Manual sked fail (path likely bad) => strong, permanent penalty until reset
if (mx.manualSkedFailed) {
score *= 0.15;
}
/*
* Remember the explicit failure state here. The actual penalty is applied
* after the sked contribution has been calculated.
*/
manualSkedFailed = mx.manualSkedFailed;
}
}
@@ -226,10 +229,25 @@ public class PriorityCalculator {
// --------------------------------------------------------------------
// 8) Legacy penalty: failed attempts in ChatMember
// --------------------------------------------------------------------
// --------------------------------------------------------------------
// 8) Legacy penalty: failed attempts in ChatMember
// --------------------------------------------------------------------
if (member.getFailedQSOAttempts() > 0) {
score = score / (member.getFailedQSOAttempts() + 1);
}
// --------------------------------------------------------------------
// 9) Explicit operator override: manual Sked fail
// --------------------------------------------------------------------
if (manualSkedFailed) {
/*
* Apply the penalty to the complete result. This includes an imminent
* sked and prevents its strong time-dependent boost from cancelling the
* operator's explicit failure assessment.
*/
score *= 0.15;
}
return Math.max(0.0, score);
}
@@ -4388,10 +4388,10 @@ public class Kst4ContestApplication extends Application implements StatusUpdateL
/**
* Resolves and selects a priority candidate.
*
* If the station is currently visible in the member table, selecting it there is
* preferred because the existing table-selection listener then keeps the rest of
* the UI in sync. If the station is filtered out, we still show FurtherInfo and
* prepare the /cq text so the priority list remains useful with active filters.
* <p>The common selection helper is used deliberately. It updates Further Info,
* prepares the directed message and selects the corresponding table row when
* the row is currently visible. A candidate hidden by an active table filter
* remains usable without changing or resetting that filter.</p>
*/
private void selectTopCandidate(
kst4contest.controller.ScoreService.TopCandidate candidate,
@@ -4408,25 +4408,17 @@ public class Kst4ContestApplication extends Application implements StatusUpdateL
return;
}
// if (tbl_chatMember.getItems().contains(resolved)) {
// tbl_chatMember.getSelectionModel().select(resolved);
// tbl_chatMember.scrollTo(resolved);
// } else {
// selectedCallSignInfoStageChatMember = resolved;
// chatcontroller.getScoreService().setSelectedChatMember(selectedCallSignInfoStageChatMember);
//
// selectedCallSignFurtherInfoPane.getChildren().setAll(generateFurtherInfoAbtSelectedCallsignBP(resolved));
// txt_chatMessageUserInput.clear();
// txt_chatMessageUserInput.setText("/cq " + resolved.getCallSign() + " ");
// txt_chatMessageUserInput.requestFocus();
// txt_chatMessageUserInput.selectEnd();
// }
tbl_chatMember.getSelectionModel().select(resolved); //new mechanic for selectionchange events due to textfield
//manipulation...
// Keep ScoreService selection in sync even if the visible table selection path was used.
chatcontroller.getScoreService().setSelectedChatMember(resolved);
/*
* This is an explicit operator action and therefore follows the same path
* as a timeline click. The exact callsign and category stored in the
* TopCandidate remain authoritative.
*
* focusChatMemberAndPrepareCq() also handles candidates which are currently
* hidden by a FilteredList. In that case the table row cannot be selected,
* but Further Info, ScoreService selection and the prepared /cq message are
* still updated.
*/
focusChatMemberAndPrepareCq(resolved);
}
/**