From a86f928f3600c15c79a9279f46d3143fd05bb5ed Mon Sep 17 00:00:00 2001 From: Imbus Date: Fri, 29 Sep 2023 07:31:06 +0200 Subject: [PATCH] Polish --- app/src/main/java/simulation/Event.java | 26 +++++-- app/src/main/java/simulation/EventList.java | 73 ++++++------------- .../main/java/simulation/MainSimulation.java | 4 +- app/src/main/java/simulation/State.java | 23 +++--- app/src/test/java/simulation/AppTest.java | 12 --- .../test/java/simulation/EventListTest.java | 15 ++-- app/src/test/java/simulation/EventTest.java | 13 +--- 7 files changed, 64 insertions(+), 102 deletions(-) delete mode 100644 app/src/test/java/simulation/AppTest.java diff --git a/app/src/main/java/simulation/Event.java b/app/src/main/java/simulation/Event.java index 227e6bd..e5ed402 100644 --- a/app/src/main/java/simulation/Event.java +++ b/app/src/main/java/simulation/Event.java @@ -1,8 +1,12 @@ package simulation; -class Event { +class Event implements Comparable { + // 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 - // 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 { if (type > 3 || type < 1) throw new IllegalArgumentException("Event type must be one of ARRIVAL, READY or MEASURE"); @@ -11,11 +15,17 @@ class Event { eventTime = eventTimeStamp; } - // Empty constructor (used by the event list constructor) - // Event() { - // } + // Setters and getters for the private variables instead of having them public + public double getEventTime() { + return eventTime; + } + public int getEventType() { + return eventType; + } - public double eventTime; - public int eventType; - public Event next = null; // Explicitly initialize to null + // This is the custom comparator that PriorityQueue uses to sort the events + @Override + public int compareTo(Event e) { + return Double.compare(eventTime, e.eventTime); + } } diff --git a/app/src/main/java/simulation/EventList.java b/app/src/main/java/simulation/EventList.java index 15fd209..1836cc4 100644 --- a/app/src/main/java/simulation/EventList.java +++ b/app/src/main/java/simulation/EventList.java @@ -1,72 +1,41 @@ 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 { - private Event head = null; - private Integer size = 0; - EventList() { + // A heap backed, event containing priority queue. + private PriorityQueue pq = new PriorityQueue<>(); + // This one contains events that are prioritized over the normal events + private PriorityQueue high_pq = new PriorityQueue<>(); + + // This is a helper function to get the correct queue + private PriorityQueue 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() { - return head; + return getQueue().peek(); } public Integer length() { - return size; + return getQueue().size(); } public void insertEvent(Event newEvent) { - if (this.head == null) { - this.head = newEvent; - size += 1; - return; - } + pq.add(newEvent); + } - Event cursor = this.head; - // int tries = 0; - // 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 void insertPriorityEvent(Event newEvent) { + high_pq.add(newEvent); } public Event popEvent() { - if (head == null) - return null; - Event temp = head; - head = head.next; - temp.next = null; - size -= 1; - return temp; + return getQueue().poll(); } - - 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; - // } } diff --git a/app/src/main/java/simulation/MainSimulation.java b/app/src/main/java/simulation/MainSimulation.java index 82a350b..717d604 100644 --- a/app/src/main/java/simulation/MainSimulation.java +++ b/app/src/main/java/simulation/MainSimulation.java @@ -12,9 +12,9 @@ public class MainSimulation extends GlobalSimulation { myEventList.insertEvent(new Event(ARRIVAL, 0)); myEventList.insertEvent(new Event(MEASURE, 5)); - while (MainSimulation.time < 50000) { + while (MainSimulation.time < 200000) { actEvent = myEventList.popEvent(); - MainSimulation.time = actEvent.eventTime; + MainSimulation.time = actEvent.getEventTime(); actState.TreatEvent(actEvent); } diff --git a/app/src/main/java/simulation/State.java b/app/src/main/java/simulation/State.java index 1030ca8..08f2488 100644 --- a/app/src/main/java/simulation/State.java +++ b/app/src/main/java/simulation/State.java @@ -1,23 +1,22 @@ package simulation; -import java.util.*; - class State extends GlobalSimulation { public int numberInQueue = 0, accumulated = 0, noMeasurements = 0; - private EventList eventList; + private EventList eventList = null; State(EventList eventList) { this.eventList = eventList; } - // Dispatches the events to the right handler - public void TreatEvent(Event x) { - if (x.eventType == ARRIVAL) - arrival(); - else if (x.eventType == READY) - ready(); - else if (x.eventType == MEASURE) - measure(); + // Dispatches the events to the right handler with a java 20 switch statement + public void TreatEvent(Event event) { + switch (event.getEventType()) { + case ARRIVAL -> arrival(); + case READY -> ready(); + case 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 @@ -28,8 +27,8 @@ class State extends GlobalSimulation { private void arrival() { if (numberInQueue == 0) eventList.insertEvent(new Event(READY, time + generateMean(1))); - numberInQueue++; eventList.insertEvent(new Event(ARRIVAL, time + generateMean(2))); + numberInQueue++; } private void ready() { diff --git a/app/src/test/java/simulation/AppTest.java b/app/src/test/java/simulation/AppTest.java deleted file mode 100644 index 4b9352a..0000000 --- a/app/src/test/java/simulation/AppTest.java +++ /dev/null @@ -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"); - // } -} diff --git a/app/src/test/java/simulation/EventListTest.java b/app/src/test/java/simulation/EventListTest.java index db0f07e..ba6ef1e 100644 --- a/app/src/test/java/simulation/EventListTest.java +++ b/app/src/test/java/simulation/EventListTest.java @@ -11,7 +11,6 @@ public class EventListTest { Event event = new Event(1, 0.0); eventList.insertEvent(event); assert eventList.getHead() == event; - assert eventList.getHead().next == null; } @Test @@ -23,10 +22,10 @@ public class EventListTest { eventList.insertEvent(event3); eventList.insertEvent(event2); eventList.insertEvent(event1); - assert eventList.getHead() == event1; - assert eventList.getHead().next == event2; - assert eventList.getHead().next.next == event3; - assert eventList.getHead().next.next.next == null; + assert eventList.popEvent() == event1; + assert eventList.popEvent() == event2; + assert eventList.popEvent() == event3; + assert eventList.popEvent() == null; } @Test @@ -55,9 +54,11 @@ public class EventListTest { for(int i : rand.ints(0, 100).limit(100).toArray()) { eventList.insertEvent(new Event(1, (double) i)); } + + Event prev = eventList.popEvent(); for(Event e = eventList.getHead(); e != null; e = eventList.popEvent()) { - if(e.next == null) break; - assert e.eventTime < e.next.eventTime; + assert prev.getEventTime() <= e.getEventTime(); + prev = e; } } } diff --git a/app/src/test/java/simulation/EventTest.java b/app/src/test/java/simulation/EventTest.java index 48122f2..3ce3790 100644 --- a/app/src/test/java/simulation/EventTest.java +++ b/app/src/test/java/simulation/EventTest.java @@ -3,15 +3,10 @@ package simulation; import org.junit.jupiter.api.Test; public class EventTest { - @Test void testConstructor() { + @Test + void testConstructor() { Event event = new Event(1, 0.0); - assert event.eventType == 1; - assert event.eventTime == 0.0; + assert event.getEventType() == 1; + assert event.getEventTime() == 0.0; } - - // @Test void testEmptyConstructor() { - // Event event = new Event(); - // assert event.eventType == 0; - // assert event.eventTime == 0.0; - // } }