2 Commits

6 changed files with 184 additions and 17630 deletions

View File

@@ -1,2 +0,0 @@
dr2x
oe3cin

File diff suppressed because it is too large Load Diff

View File

@@ -23,6 +23,7 @@ import kst4contest.locatorUtils.DirectionUtils;
import kst4contest.logic.PriorityCalculator; import kst4contest.logic.PriorityCalculator;
import kst4contest.model.*; import kst4contest.model.*;
import kst4contest.test.MockKstServer; import kst4contest.test.MockKstServer;
import kst4contest.utils.BoundedDequeObservableList;
import kst4contest.utils.PlayAudioUtils; import kst4contest.utils.PlayAudioUtils;
import kst4contest.view.Kst4ContestApplication; import kst4contest.view.Kst4ContestApplication;
@@ -1007,7 +1008,8 @@ public class ChatController implements ThreadStatusCallback, PstRotatorEventList
// ******All abstract types below here are used by the messageprocessor! // ******All abstract types below here are used by the messageprocessor!
// *************** // ***************
private ObservableList<ChatMessage> lst_globalChatMessageList = FXCollections.observableArrayList(); //All chatmessages will be put in there, later create filtered message lists private static final int MAX_CHAT_MESSAGES = 10000;
private final BoundedDequeObservableList<ChatMessage> lst_globalChatMessageList = new BoundedDequeObservableList<>(MAX_CHAT_MESSAGES); //All chatmessages will be put in there, later create filtered message lists
// private ObservableList<ChatMessage> lst_toAllMessageList = FXCollections.observableArrayList(); // directed to all // private ObservableList<ChatMessage> lst_toAllMessageList = FXCollections.observableArrayList(); // directed to all
// (beacon) // (beacon)
private FilteredList<ChatMessage> lst_toAllMessageList = new FilteredList<>(lst_globalChatMessageList); // directed to all private FilteredList<ChatMessage> lst_toAllMessageList = new FilteredList<>(lst_globalChatMessageList); // directed to all
@@ -1152,13 +1154,14 @@ public class ChatController implements ThreadStatusCallback, PstRotatorEventList
this.lst_selectedCallSignInfofilteredMessageList = lst_selectedCallSignInfofilteredMessageList; this.lst_selectedCallSignInfofilteredMessageList = lst_selectedCallSignInfofilteredMessageList;
} }
public void addChatMessage(ChatMessage message) {
lst_globalChatMessageList.addFirst(message);
}
public ObservableList<ChatMessage> getLst_globalChatMessageList() { public ObservableList<ChatMessage> getLst_globalChatMessageList() {
return lst_globalChatMessageList; return lst_globalChatMessageList;
} }
public void setLst_globalChatMessageList(ObservableList<ChatMessage> lst_globalChatMessageList) {
this.lst_globalChatMessageList = lst_globalChatMessageList;
}
public String getHostname() { public String getHostname() {
return hostname; return hostname;

View File

@@ -772,7 +772,7 @@ public class MessageBusManagementThread extends Thread {
dummy.setCallSign("ALL"); dummy.setCallSign("ALL");
newMessageArrived.setReceiver(dummy); newMessageArrived.setReceiver(dummy);
this.client.getLst_globalChatMessageList().add(0, newMessageArrived); // sdtout to all message-List this.client.addChatMessage(newMessageArrived); // sdtout to all message-List
} else { } else {
//message is directed to another chatmember, process as such! //message is directed to another chatmember, process as such!
@@ -817,7 +817,7 @@ public class MessageBusManagementThread extends Thread {
if (newMessageArrived.getReceiver().getCallSign() if (newMessageArrived.getReceiver().getCallSign()
.equals(this.client.getChatPreferences().getStn_loginCallSign())) { .equals(this.client.getChatPreferences().getStn_loginCallSign())) {
this.client.getLst_globalChatMessageList().add(0, newMessageArrived); this.client.addChatMessage(newMessageArrived);
if (this.client.getChatPreferences().isNotify_playSimpleSounds()) { if (this.client.getChatPreferences().isNotify_playSimpleSounds()) {
this.client.getPlayAudioUtils().playNoiseLauncher('P'); this.client.getPlayAudioUtils().playNoiseLauncher('P');
@@ -960,7 +960,7 @@ public class MessageBusManagementThread extends Thread {
String originalMessage = newMessageArrived.getMessageText(); String originalMessage = newMessageArrived.getMessageText();
newMessageArrived newMessageArrived
.setMessageText("(>" + newMessageArrived.getReceiver().getCallSign() + ")" + originalMessage); .setMessageText("(>" + newMessageArrived.getReceiver().getCallSign() + ")" + originalMessage);
this.client.getLst_globalChatMessageList().add(0,newMessageArrived); this.client.addChatMessage(newMessageArrived);
// if you sent the message to another station, it will be sorted in to // if you sent the message to another station, it will be sorted in to
// the "to me message list" with modified messagetext, added rxers callsign // the "to me message list" with modified messagetext, added rxers callsign
@@ -1024,7 +1024,7 @@ public class MessageBusManagementThread extends Thread {
newMessageArrived.getSender().setInAngleAndRange(false); newMessageArrived.getSender().setInAngleAndRange(false);
} }
this.client.getLst_globalChatMessageList().add(0, newMessageArrived); this.client.addChatMessage(newMessageArrived);
// System.out.println("MSGBS bgfx: tx call = " + newMessageArrived.getSender().getCallSign() + " / rx call = " + newMessageArrived.getReceiver().getCallSign()); // System.out.println("MSGBS bgfx: tx call = " + newMessageArrived.getSender().getCallSign() + " / rx call = " + newMessageArrived.getReceiver().getCallSign());
} }
} catch (NullPointerException referenceDeletedByUserLeftChatDuringMessageprocessing) { } catch (NullPointerException referenceDeletedByUserLeftChatDuringMessageprocessing) {
@@ -1364,7 +1364,7 @@ public class MessageBusManagementThread extends Thread {
dummy.setCallSign("ALL"); dummy.setCallSign("ALL");
newMessageArrived.setReceiver(dummy); newMessageArrived.setReceiver(dummy);
this.client.getLst_globalChatMessageList().add(0, newMessageArrived); // sdtout to all message-List this.client.addChatMessage(newMessageArrived); // sdtout to all message-List
} else { } else {
//message is directed to another chatmember, process as such! //message is directed to another chatmember, process as such!
@@ -1408,7 +1408,7 @@ public class MessageBusManagementThread extends Thread {
if (newMessageArrived.getReceiver().getCallSign() if (newMessageArrived.getReceiver().getCallSign()
.equals(this.client.getChatPreferences().getStn_loginCallSign())) { .equals(this.client.getChatPreferences().getStn_loginCallSign())) {
this.client.getLst_globalChatMessageList().add(0, newMessageArrived); this.client.addChatMessage(newMessageArrived);
System.out.println("Historic message directed to me: " + newMessageArrived.getReceiver().getCallSign() + "."); System.out.println("Historic message directed to me: " + newMessageArrived.getReceiver().getCallSign() + ".");
@@ -1421,7 +1421,7 @@ public class MessageBusManagementThread extends Thread {
String originalMessage = newMessageArrived.getMessageText(); String originalMessage = newMessageArrived.getMessageText();
newMessageArrived newMessageArrived
.setMessageText("(>" + newMessageArrived.getReceiver().getCallSign() + ")" + originalMessage); .setMessageText("(>" + newMessageArrived.getReceiver().getCallSign() + ")" + originalMessage);
this.client.getLst_globalChatMessageList().add(0,newMessageArrived); this.client.addChatMessage(newMessageArrived);
// if you sent the message to another station, it will be sorted in to // if you sent the message to another station, it will be sorted in to
// the "to me message list" with modified messagetext, added rxers callsign // the "to me message list" with modified messagetext, added rxers callsign
@@ -1441,7 +1441,7 @@ public class MessageBusManagementThread extends Thread {
newMessageArrived.getSender().setInAngleAndRange(false); newMessageArrived.getSender().setInAngleAndRange(false);
} }
this.client.getLst_globalChatMessageList().add(0, newMessageArrived); this.client.addChatMessage(newMessageArrived);
// System.out.println("MSGBS bgfx: tx call = " + newMessageArrived.getSender().getCallSign() + " / rx call = " + newMessageArrived.getReceiver().getCallSign()); // System.out.println("MSGBS bgfx: tx call = " + newMessageArrived.getSender().getCallSign() + " / rx call = " + newMessageArrived.getReceiver().getCallSign());
} }
} catch (NullPointerException referenceDeletedByUserLeftChatDuringMessageprocessing) { } catch (NullPointerException referenceDeletedByUserLeftChatDuringMessageprocessing) {
@@ -1514,7 +1514,7 @@ public class MessageBusManagementThread extends Thread {
for (int i = 0; i < 10; i++) { for (int i = 0; i < 10; i++) {
client.getLst_globalChatMessageList().add(pwErrorMsg); client.addChatMessage(pwErrorMsg);
// client.getLst_toMeMessageList().add(pwErrorMsg); // client.getLst_toMeMessageList().add(pwErrorMsg);
// client.getLst_toAllMessageList().add(pwErrorMsg); // client.getLst_toAllMessageList().add(pwErrorMsg);
} }

View File

@@ -0,0 +1,168 @@
package kst4contest.utils;
import javafx.collections.ObservableListBase;
import java.util.Arrays;
/**
* A bounded ObservableList backed by a circular buffer (ring buffer).
* <p>
* Provides O(1) {@link #addFirst} and {@link #addLast} as well as O(1)
* random access via {@link #get}. When the list reaches {@code maxCapacity},
* adding a new element at the front automatically evicts the oldest element
* at the back — and vice versa.
* <p>
* This is a drop-in replacement for {@code FXCollections.observableArrayList()}
* wherever elements are prepended frequently, e.g. chat message lists.
*/
public class BoundedDequeObservableList<E> extends ObservableListBase<E> {
private final int maxCapacity;
private final Object[] elements;
private int head = 0;
private int size = 0;
public BoundedDequeObservableList(int maxCapacity) {
if (maxCapacity <= 0) throw new IllegalArgumentException("maxCapacity must be > 0");
this.maxCapacity = maxCapacity;
this.elements = new Object[maxCapacity];
}
// ── read access ──────────────────────────────────────────────────────────
@Override
public int size() {
return size;
}
@Override
@SuppressWarnings("unchecked")
public E get(int index) {
checkIndex(index);
return (E) elements[physicalIndex(index)];
}
// ── O(1) deque operations ─────────────────────────────────────────────────
/**
* Inserts {@code element} at index 0 (newest-first order).
* If the list is already at capacity the oldest element (last index) is
* removed first — both changes are reported as a single compound change.
*/
public void addFirst(E element) {
beginChange();
if (size == maxCapacity) {
// evict last element
int lastPhysical = physicalIndex(size - 1);
@SuppressWarnings("unchecked")
E evicted = (E) elements[lastPhysical];
elements[lastPhysical] = null;
size--;
nextRemove(size, evicted); // index after decrement == old last index
}
head = (head - 1 + maxCapacity) % maxCapacity;
elements[head] = element;
size++;
nextAdd(0, 1);
endChange();
}
/**
* Appends {@code element} at the last index (oldest-first order).
* If the list is already at capacity the newest element (index 0) is
* removed first.
*/
public void addLast(E element) {
beginChange();
if (size == maxCapacity) {
// evict first element
@SuppressWarnings("unchecked")
E evicted = (E) elements[head];
elements[head] = null;
head = (head + 1) % maxCapacity;
size--;
nextRemove(0, evicted);
}
elements[physicalIndex(size)] = element;
size++;
nextAdd(size - 1, size);
endChange();
}
// ── standard List mutation (O(n) — use addFirst/addLast for hot path) ─────
@Override
public void add(int index, E element) {
if (index == 0) {
addFirst(element);
return;
}
if (index == size) {
addLast(element);
return;
}
checkIndexForAdd(index);
beginChange();
if (size == maxCapacity) {
int lastPhysical = physicalIndex(size - 1);
@SuppressWarnings("unchecked")
E evicted = (E) elements[lastPhysical];
elements[lastPhysical] = null;
size--;
nextRemove(size, evicted);
}
// shift elements [index .. size-1] one position towards the end
for (int i = size; i > index; i--) {
elements[physicalIndex(i)] = elements[physicalIndex(i - 1)];
}
elements[physicalIndex(index)] = element;
size++;
nextAdd(index, index + 1);
endChange();
}
@Override
public E remove(int index) {
checkIndex(index);
beginChange();
@SuppressWarnings("unchecked")
E removed = (E) elements[physicalIndex(index)];
// shift elements [index+1 .. size-1] one position towards the front
for (int i = index; i < size - 1; i++) {
elements[physicalIndex(i)] = elements[physicalIndex(i + 1)];
}
elements[physicalIndex(size - 1)] = null;
size--;
nextRemove(index, removed);
endChange();
return removed;
}
@Override
public E set(int index, E element) {
checkIndex(index);
beginChange();
@SuppressWarnings("unchecked")
E old = (E) elements[physicalIndex(index)];
elements[physicalIndex(index)] = element;
nextSet(index, old);
endChange();
return old;
}
// ── helpers ───────────────────────────────────────────────────────────────
private int physicalIndex(int virtualIndex) {
return (head + virtualIndex) % maxCapacity;
}
private void checkIndex(int index) {
if (index < 0 || index >= size)
throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + size);
}
private void checkIndexForAdd(int index) {
if (index < 0 || index > size)
throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + size);
}
}

File diff suppressed because it is too large Load Diff