fix(chat): grouped calculation of priority score for equal raw callsigns with different suffixes (also fixes #73)

This commit is contained in:
Marc Froehlich
2026-08-06 00:18:36 +02:00
parent eb38268be5
commit 084923366f
2 changed files with 28 additions and 29 deletions
@@ -227,12 +227,11 @@ public final class ScoreService {
ChatMember chosen = null; ChatMember chosen = null;
if (preferredCat != null) { if (preferredCat != null) {
for (ChatMember v : variants) { chosen = variants.stream()
if (v != null && v.getChatCategory() == preferredCat) { .filter(Objects::nonNull)
chosen = v; .filter(v -> isSameChatCategory(v.getChatCategory(), preferredCat))
break; .max(Comparator.comparingLong(ChatMember::getActivityTimeLastInEpoch))
} .orElse(null);
}
} }
if (chosen == null) { if (chosen == null) {
@@ -247,6 +246,14 @@ public final class ScoreService {
return representative; return representative;
} }
private static boolean isSameChatCategory(ChatCategory left, ChatCategory right) {
return left != null
&& right != null
&& left.getCategoryNumber() == right.getCategoryNumber();
}
/** /**
* Projects the immutable score snapshot back into ChatMember display fields so * Projects the immutable score snapshot back into ChatMember display fields so
* the normal station table can sort/filter by score without knowing the score * the normal station table can sort/filter by score without knowing the score
@@ -4291,34 +4291,26 @@ public class Kst4ContestApplication extends Application implements StatusUpdateL
} }
private ChatMember resolveChatMemberForTopCandidate(kst4contest.controller.ScoreService.TopCandidate c) { private ChatMember resolveChatMemberForTopCandidate(
kst4contest.controller.ScoreService.TopCandidate c
String callRaw = c.getCallSignRaw(); ) {
ChatCategory preferredCategory = c.getPreferredChatCategory();
// 1) Prefer exact (callRaw + category) match
synchronized (chatcontroller.getLst_chatMemberList()) {
for (ChatMember m : chatcontroller.getLst_chatMemberList()) {
if (m == null) continue;
if (m.getCallSignRaw() == null) continue;
if (!m.getCallSignRaw().equalsIgnoreCase(callRaw)) continue;
if (preferredCategory != null && preferredCategory.equals(m.getChatCategory())) {
return m;
}
}
// 2) Fallback: any variant with the same callsignRaw
for (ChatMember m : chatcontroller.getLst_chatMemberList()) {
if (m == null) continue;
if (m.getCallSignRaw() == null) continue;
if (m.getCallSignRaw().equalsIgnoreCase(callRaw)) return m;
}
}
if (c == null
|| c.getDisplayCallSign() == null
|| c.getPreferredChatCategory() == null) {
return null; return null;
} }
/*
* Resolve the concrete active login by full callsign and category. Falling
* back to callSignRaw could select a different suffix in the same category.
*/
return chatcontroller.findActiveChatMember(
c.getDisplayCallSign(),
c.getPreferredChatCategory()
);
}
private void updateTimelineVisuals() { private void updateTimelineVisuals() {
if (timelineView == null || chatcontroller == null) return; if (timelineView == null || chatcontroller == null) return;