Compare commits
3 commits
ba2fb856fa
...
4631242e19
Author | SHA1 | Date | |
---|---|---|---|
|
4631242e19 | ||
|
5868aa977d | ||
|
2189ba86c4 |
8 changed files with 221 additions and 90 deletions
|
@ -34,7 +34,7 @@ testing {
|
|||
// Apply a specific Java toolchain to ease working on different environments.
|
||||
java {
|
||||
toolchain {
|
||||
languageVersion.set(JavaLanguageVersion.of(17))
|
||||
languageVersion.set(JavaLanguageVersion.of(20))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -42,3 +42,8 @@ application {
|
|||
// Define the main class for the application.
|
||||
mainClass.set("simulation.MainSimulation")
|
||||
}
|
||||
|
||||
// Always execute all tests, even when not all tasks are up-to-date.
|
||||
tasks.withType<Test> {
|
||||
outputs.upToDateWhen { false }
|
||||
}
|
|
@ -1,7 +1,21 @@
|
|||
package simulation;
|
||||
|
||||
class Event{
|
||||
class Event {
|
||||
// Constructor, creates an event of a certain type that should be put in the
|
||||
// event list at a certain time.
|
||||
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");
|
||||
|
||||
eventType = type;
|
||||
eventTime = eventTimeStamp;
|
||||
}
|
||||
|
||||
// Empty constructor (used by the event list constructor)
|
||||
// Event() {
|
||||
// }
|
||||
|
||||
public double eventTime;
|
||||
public int eventType;
|
||||
public Event next;
|
||||
public Event next = null; // Explicitly initialize to null
|
||||
}
|
||||
|
|
|
@ -1,35 +1,72 @@
|
|||
package simulation;
|
||||
|
||||
public class EventList{
|
||||
import java.util.LinkedList;
|
||||
|
||||
private Event list, last;
|
||||
// Essentially a linked list of a non-template node type
|
||||
public class EventList {
|
||||
private Event head = null;
|
||||
private Integer size = 0;
|
||||
|
||||
EventList(){
|
||||
list = new Event();
|
||||
last = new Event();
|
||||
list.next = last;
|
||||
EventList() {
|
||||
}
|
||||
|
||||
public void InsertEvent(int type, double TimeOfEvent){
|
||||
Event dummy, predummy;
|
||||
Event newEvent = new Event();
|
||||
newEvent.eventType = type;
|
||||
newEvent.eventTime = TimeOfEvent;
|
||||
predummy = list;
|
||||
dummy = list.next;
|
||||
while ((dummy.eventTime < newEvent.eventTime) & (dummy != last)){
|
||||
predummy = dummy;
|
||||
dummy = dummy.next;
|
||||
}
|
||||
predummy.next = newEvent;
|
||||
newEvent.next = dummy;
|
||||
}
|
||||
|
||||
public Event FetchEvent(){
|
||||
Event dummy;
|
||||
dummy = list.next;
|
||||
list.next = dummy.next;
|
||||
dummy.next = null;
|
||||
return dummy;
|
||||
// Yes
|
||||
public Event getHead() {
|
||||
return head;
|
||||
}
|
||||
|
||||
public Integer length() {
|
||||
return size;
|
||||
}
|
||||
|
||||
public void insertEvent(Event newEvent) {
|
||||
if (this.head == null) {
|
||||
this.head = newEvent;
|
||||
size += 1;
|
||||
return;
|
||||
}
|
||||
|
||||
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 Event popEvent() {
|
||||
if (head == null)
|
||||
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;
|
||||
// }
|
||||
}
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
package simulation;
|
||||
|
||||
public class GlobalSimulation{
|
||||
import java.util.Random;
|
||||
|
||||
// This class is only created to be able to store the global time.
|
||||
public class GlobalSimulation {
|
||||
public static final int ARRIVAL = 1, READY = 2, MEASURE = 3;
|
||||
public static double time = 0;
|
||||
public static Random rand = new Random();
|
||||
}
|
|
@ -2,20 +2,23 @@ package simulation;
|
|||
|
||||
import java.io.*;
|
||||
|
||||
public class MainSimulation extends GlobalSimulation{
|
||||
public class MainSimulation extends GlobalSimulation {
|
||||
|
||||
public static void main(String[] args) throws IOException {
|
||||
Event actEvent;
|
||||
EventList myEventList = new EventList();
|
||||
State actState = new State(myEventList);
|
||||
myEventList.InsertEvent(ARRIVAL, 0);
|
||||
myEventList.InsertEvent(MEASURE, 5);
|
||||
while (time < 50000){
|
||||
actEvent = myEventList.FetchEvent();
|
||||
time = actEvent.eventTime;
|
||||
actState.TreatEvent(actEvent);
|
||||
}
|
||||
System.out.println("Mean number of customers: " + 1.0*actState.accumulated/actState.noMeasurements);
|
||||
System.out.println("Number of measurements done: " + actState.noMeasurements);
|
||||
}
|
||||
public static void main(String[] args) throws IOException {
|
||||
EventList myEventList = new EventList();
|
||||
Event actEvent;
|
||||
State actState = new State(myEventList);
|
||||
|
||||
myEventList.insertEvent(new Event(ARRIVAL, 0));
|
||||
myEventList.insertEvent(new Event(MEASURE, 5));
|
||||
|
||||
while (MainSimulation.time < 50000) {
|
||||
actEvent = myEventList.popEvent();
|
||||
MainSimulation.time = actEvent.eventTime;
|
||||
actState.TreatEvent(actEvent);
|
||||
}
|
||||
|
||||
System.out.println("Mean number of customers: " + (double) actState.accumulated / actState.noMeasurements);
|
||||
System.out.println("Number of measurements done: " + actState.noMeasurements);
|
||||
}
|
||||
}
|
|
@ -2,57 +2,45 @@ package simulation;
|
|||
|
||||
import java.util.*;
|
||||
|
||||
class State extends GlobalSimulation{
|
||||
|
||||
class State extends GlobalSimulation {
|
||||
public int numberInQueue = 0, accumulated = 0, noMeasurements = 0;
|
||||
private EventList eventList;
|
||||
|
||||
private EventList myEventList;
|
||||
|
||||
Random slump = new Random();
|
||||
|
||||
State(EventList x){
|
||||
myEventList = x;
|
||||
State(EventList eventList) {
|
||||
this.eventList = eventList;
|
||||
}
|
||||
|
||||
private void InsertEvent(int event, double timeOfEvent){
|
||||
myEventList.InsertEvent(event, timeOfEvent);
|
||||
// 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();
|
||||
}
|
||||
|
||||
|
||||
public void TreatEvent(Event x){
|
||||
switch (x.eventType){
|
||||
case ARRIVAL:
|
||||
arrival();
|
||||
break;
|
||||
case READY:
|
||||
ready();
|
||||
break;
|
||||
case MEASURE:
|
||||
measure();
|
||||
break;
|
||||
}
|
||||
// Helper to generate a random number with certain statistical properties
|
||||
private static double generateMean(double mean) {
|
||||
return 2 * mean * rand.nextDouble();
|
||||
}
|
||||
|
||||
private double generateMean(double mean){
|
||||
return 2*mean*slump.nextDouble();
|
||||
}
|
||||
|
||||
private void arrival(){
|
||||
private void arrival() {
|
||||
if (numberInQueue == 0)
|
||||
InsertEvent(READY, time + generateMean(1));
|
||||
eventList.insertEvent(new Event(READY, time + generateMean(1)));
|
||||
numberInQueue++;
|
||||
InsertEvent(ARRIVAL, time + generateMean(2));
|
||||
eventList.insertEvent(new Event(ARRIVAL, time + generateMean(2)));
|
||||
}
|
||||
|
||||
private void ready(){
|
||||
private void ready() {
|
||||
numberInQueue--;
|
||||
if (numberInQueue > 0)
|
||||
InsertEvent(READY, time + generateMean(1));
|
||||
eventList.insertEvent(new Event(READY, time + generateMean(1)));
|
||||
}
|
||||
|
||||
private void measure(){
|
||||
private void measure() {
|
||||
accumulated = accumulated + numberInQueue;
|
||||
noMeasurements++;
|
||||
InsertEvent(MEASURE, time + generateMean(5));
|
||||
eventList.insertEvent(new Event(MEASURE, time + generateMean(5)));
|
||||
}
|
||||
}
|
63
app/src/test/java/simulation/EventListTest.java
Normal file
63
app/src/test/java/simulation/EventListTest.java
Normal file
|
@ -0,0 +1,63 @@
|
|||
package simulation;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
public class EventListTest {
|
||||
@Test
|
||||
void testEventListConstructor() {
|
||||
EventList eventList = new EventList();
|
||||
Event event = new Event(1, 0.0);
|
||||
eventList.insertEvent(event);
|
||||
assert eventList.getHead() == event;
|
||||
assert eventList.getHead().next == null;
|
||||
}
|
||||
|
||||
@Test
|
||||
void testOrdering() {
|
||||
EventList eventList = new EventList();
|
||||
Event event1 = new Event(1, 0.0);
|
||||
Event event2 = new Event(1, 1.0);
|
||||
Event event3 = new Event(1, 2.0);
|
||||
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;
|
||||
}
|
||||
|
||||
@Test
|
||||
void testLength() {
|
||||
Random rand = new Random();
|
||||
EventList eventList = new EventList();
|
||||
for(int i : rand.ints(0, 100).limit(100).toArray()) {
|
||||
eventList.insertEvent(new Event(1, (double) i));
|
||||
}
|
||||
assert eventList.length() == 100;
|
||||
}
|
||||
|
||||
@Test
|
||||
void testPop() {
|
||||
EventList eventList = new EventList();
|
||||
Event event1 = new Event(1, 0.0);
|
||||
eventList.insertEvent(event1);
|
||||
assert eventList.popEvent() == event1;
|
||||
assert eventList.popEvent() == null;
|
||||
}
|
||||
|
||||
@Test
|
||||
void testOrderingRandomAmount() {
|
||||
Random rand = new Random();
|
||||
EventList eventList = new EventList();
|
||||
for(int i : rand.ints(0, 100).limit(100).toArray()) {
|
||||
eventList.insertEvent(new Event(1, (double) i));
|
||||
}
|
||||
for(Event e = eventList.getHead(); e != null; e = eventList.popEvent()) {
|
||||
if(e.next == null) break;
|
||||
assert e.eventTime < e.next.eventTime;
|
||||
}
|
||||
}
|
||||
}
|
17
app/src/test/java/simulation/EventTest.java
Normal file
17
app/src/test/java/simulation/EventTest.java
Normal file
|
@ -0,0 +1,17 @@
|
|||
package simulation;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
public class EventTest {
|
||||
@Test void testConstructor() {
|
||||
Event event = new Event(1, 0.0);
|
||||
assert event.eventType == 1;
|
||||
assert event.eventTime == 0.0;
|
||||
}
|
||||
|
||||
// @Test void testEmptyConstructor() {
|
||||
// Event event = new Event();
|
||||
// assert event.eventType == 0;
|
||||
// assert event.eventTime == 0.0;
|
||||
// }
|
||||
}
|
Loading…
Reference in a new issue