This commit is contained in:
Imbus 2023-09-29 07:31:06 +02:00
parent 4631242e19
commit a86f928f36
7 changed files with 64 additions and 102 deletions

View file

@ -1,8 +1,12 @@
package simulation; package simulation;
class Event { class Event implements Comparable<Event> {
// Our only data members, we don't want anyone to tamper with these
private double eventTime;
private int eventType;
// Constructor, creates an event of a certain type that should be put in the // Constructor, creates an event of a certain type that should be put in the
// event list at a certain time. // event list at a certain time. Throws if type is out of bounds.
Event(int type, double eventTimeStamp) throws IllegalArgumentException { Event(int type, double eventTimeStamp) throws IllegalArgumentException {
if (type > 3 || type < 1) if (type > 3 || type < 1)
throw new IllegalArgumentException("Event type must be one of ARRIVAL, READY or MEASURE"); throw new IllegalArgumentException("Event type must be one of ARRIVAL, READY or MEASURE");
@ -11,11 +15,17 @@ class Event {
eventTime = eventTimeStamp; eventTime = eventTimeStamp;
} }
// Empty constructor (used by the event list constructor) // Setters and getters for the private variables instead of having them public
// Event() { public double getEventTime() {
// } return eventTime;
}
public int getEventType() {
return eventType;
}
public double eventTime; // This is the custom comparator that PriorityQueue uses to sort the events
public int eventType; @Override
public Event next = null; // Explicitly initialize to null public int compareTo(Event e) {
return Double.compare(eventTime, e.eventTime);
}
} }

View file

@ -1,72 +1,41 @@
package simulation; package simulation;
import java.util.LinkedList; import java.util.PriorityQueue;
// Essentially a linked list of a non-template node type // Wrapper class for a priority queue of events
// Changed from a linked list to a priority queue better suited for this type of application
public class EventList { public class EventList {
private Event head = null;
private Integer size = 0;
EventList() { // A heap backed, event containing priority queue.
private PriorityQueue<Event> pq = new PriorityQueue<>();
// This one contains events that are prioritized over the normal events
private PriorityQueue<Event> high_pq = new PriorityQueue<>();
// This is a helper function to get the correct queue
private PriorityQueue<Event> getQueue() {
return switch(high_pq.size()) {
case 0 -> pq; // If no priority events, return normal queue
default -> high_pq; // If priority events, return priority queue
};
} }
// Yes
public Event getHead() { public Event getHead() {
return head; return getQueue().peek();
} }
public Integer length() { public Integer length() {
return size; return getQueue().size();
} }
public void insertEvent(Event newEvent) { public void insertEvent(Event newEvent) {
if (this.head == null) { pq.add(newEvent);
this.head = newEvent; }
size += 1;
return;
}
Event cursor = this.head; public void insertPriorityEvent(Event newEvent) {
// int tries = 0; high_pq.add(newEvent);
// Find the right place in the list using a sliding window
while ((cursor.next != null) && (cursor.eventTime < newEvent.eventTime)) {
cursor = cursor.next;
// tries++;
}
if (cursor.eventTime > newEvent.eventTime) {
newEvent.next = this.head;
this.head = newEvent;
} else {
newEvent.next = cursor.next;
cursor.next = newEvent;
}
// System.out.println("Tries: " + tries);
size += 1;
} }
public Event popEvent() { public Event popEvent() {
if (head == null) return getQueue().poll();
return null;
Event temp = head;
head = head.next;
temp.next = null;
size -= 1;
return temp;
} }
public Event fetchEvent() {
Event temp = head.next;
head.next = temp.next;
temp.next = null;
size -= 1;
return temp;
}
// public Event popFront() {
// Event front = this.head;
// this.head = this.head.next;
// return front;
// }
} }

View file

@ -12,9 +12,9 @@ public class MainSimulation extends GlobalSimulation {
myEventList.insertEvent(new Event(ARRIVAL, 0)); myEventList.insertEvent(new Event(ARRIVAL, 0));
myEventList.insertEvent(new Event(MEASURE, 5)); myEventList.insertEvent(new Event(MEASURE, 5));
while (MainSimulation.time < 50000) { while (MainSimulation.time < 200000) {
actEvent = myEventList.popEvent(); actEvent = myEventList.popEvent();
MainSimulation.time = actEvent.eventTime; MainSimulation.time = actEvent.getEventTime();
actState.TreatEvent(actEvent); actState.TreatEvent(actEvent);
} }

View file

@ -1,23 +1,22 @@
package simulation; package simulation;
import java.util.*;
class State extends GlobalSimulation { class State extends GlobalSimulation {
public int numberInQueue = 0, accumulated = 0, noMeasurements = 0; public int numberInQueue = 0, accumulated = 0, noMeasurements = 0;
private EventList eventList; private EventList eventList = null;
State(EventList eventList) { State(EventList eventList) {
this.eventList = eventList; this.eventList = eventList;
} }
// Dispatches the events to the right handler // Dispatches the events to the right handler with a java 20 switch statement
public void TreatEvent(Event x) { public void TreatEvent(Event event) {
if (x.eventType == ARRIVAL) switch (event.getEventType()) {
arrival(); case ARRIVAL -> arrival();
else if (x.eventType == READY) case READY -> ready();
ready(); case MEASURE -> measure();
else if (x.eventType == MEASURE) }
measure(); // System.out.println(String.format("Event type: %d, Customers: %d, Time: %.1f",
// event.getEventType(), numberInQueue, event.getEventTime()));
} }
// Helper to generate a random number with certain statistical properties // Helper to generate a random number with certain statistical properties
@ -28,8 +27,8 @@ class State extends GlobalSimulation {
private void arrival() { private void arrival() {
if (numberInQueue == 0) if (numberInQueue == 0)
eventList.insertEvent(new Event(READY, time + generateMean(1))); eventList.insertEvent(new Event(READY, time + generateMean(1)));
numberInQueue++;
eventList.insertEvent(new Event(ARRIVAL, time + generateMean(2))); eventList.insertEvent(new Event(ARRIVAL, time + generateMean(2)));
numberInQueue++;
} }
private void ready() { private void ready() {

View file

@ -1,12 +0,0 @@
package simulation;
// import org.junit.jupiter.api.Test;
// import static org.junit.jupiter.api.Assertions.*;
// No defined tests yet
class AppTest {
// @Test void appHasAGreeting() {
// App classUnderTest = new App();
// assertNotNull(classUnderTest.getGreeting(), "app should have a greeting");
// }
}

View file

@ -11,7 +11,6 @@ public class EventListTest {
Event event = new Event(1, 0.0); Event event = new Event(1, 0.0);
eventList.insertEvent(event); eventList.insertEvent(event);
assert eventList.getHead() == event; assert eventList.getHead() == event;
assert eventList.getHead().next == null;
} }
@Test @Test
@ -23,10 +22,10 @@ public class EventListTest {
eventList.insertEvent(event3); eventList.insertEvent(event3);
eventList.insertEvent(event2); eventList.insertEvent(event2);
eventList.insertEvent(event1); eventList.insertEvent(event1);
assert eventList.getHead() == event1; assert eventList.popEvent() == event1;
assert eventList.getHead().next == event2; assert eventList.popEvent() == event2;
assert eventList.getHead().next.next == event3; assert eventList.popEvent() == event3;
assert eventList.getHead().next.next.next == null; assert eventList.popEvent() == null;
} }
@Test @Test
@ -55,9 +54,11 @@ public class EventListTest {
for(int i : rand.ints(0, 100).limit(100).toArray()) { for(int i : rand.ints(0, 100).limit(100).toArray()) {
eventList.insertEvent(new Event(1, (double) i)); eventList.insertEvent(new Event(1, (double) i));
} }
Event prev = eventList.popEvent();
for(Event e = eventList.getHead(); e != null; e = eventList.popEvent()) { for(Event e = eventList.getHead(); e != null; e = eventList.popEvent()) {
if(e.next == null) break; assert prev.getEventTime() <= e.getEventTime();
assert e.eventTime < e.next.eventTime; prev = e;
} }
} }
} }

View file

@ -3,15 +3,10 @@ package simulation;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
public class EventTest { public class EventTest {
@Test void testConstructor() { @Test
void testConstructor() {
Event event = new Event(1, 0.0); Event event = new Event(1, 0.0);
assert event.eventType == 1; assert event.getEventType() == 1;
assert event.eventTime == 0.0; assert event.getEventTime() == 0.0;
} }
// @Test void testEmptyConstructor() {
// Event event = new Event();
// assert event.eventType == 0;
// assert event.eventTime == 0.0;
// }
} }