feat: finish Lab3

This commit is contained in:
Yadunand Prem 2022-09-08 16:04:23 +08:00
parent 383d5c3434
commit 8d5961fdd3
8 changed files with 113 additions and 30 deletions

View File

@ -1,18 +1,18 @@
/**
* The Array<T> for CS2030S
* The Array<T> for CS2030S
*
* @author Yadunand Prem
* @version CS2030S AY21/22 Semester 2
*/
class Array<T extends Comparable<T>> {
class Array<T extends Comparable<T>> {
private T[] array;
public Array(int size) {
// The only way to add values to `array` is via set(), and we can only put
// objects of type T via that method. Thus, it is safe to cast Comparable[]
// The only way to add values to `array` is via set(), and we can only put
// objects of type T via that method. Thus, it is safe to cast Comparable[]
// to T[].
@SuppressWarnings({"unchecked", "rawtypes"})
@SuppressWarnings("unchecked")
T[] temp = (T[]) new Comparable[size];
this.array = temp;
}
@ -27,7 +27,7 @@ class Array<T extends Comparable<T>> {
public T min() {
T result = this.array[0];
for (T i: this.array) {
for (T i : this.array) {
if (i.compareTo(result) < 0) {
result = i;
}
@ -35,6 +35,10 @@ class Array<T extends Comparable<T>> {
return result;
}
public int length() {
return this.array.length;
}
@Override
public String toString() {
StringBuilder s = new StringBuilder("[ ");

View File

@ -22,16 +22,22 @@ class ArrivalEvent extends Event {
@Override
public Event[] simulate() {
ServiceCounter availableCounter = this.shop.getAvailableCounter();
// check if counters are available. If none, push customer to queue if not full.
// If full, customer departs
if (availableCounter == null) {
if (this.shop.isQueueFull()) {
return new Event[] { new DepartureEvent(this.getTime(), customer, shop) };
}
return new Event[] { new JoinQueueEvent(customer, shop) };
// check if counters are available. If available, start service for that
// customer
if (availableCounter != null) {
return new Event[] {
new ServiceBeginEvent(this.getTime(), customer, shop, availableCounter) };
}
return new Event[] {
new ServiceBeginEvent(this.getTime(), customer, shop, availableCounter) };
// if no counters available, check if queue slots avialable in counters
availableCounter = this.shop.findCounterWithQueue();
if (availableCounter != null) {
return new Event[] { new JoinCounterQueueEvent(this.getTime(), this.customer, this.shop, availableCounter) };
}
// if shop queue isn't empty, join shop queue
if (!this.shop.isQueueFull()) {
return new Event[] { new JoinShopQueueEvent(customer, shop) };
}
return new Event[] { new DepartureEvent(this.getTime(), customer, shop) };
}

View File

@ -0,0 +1,24 @@
public class JoinCounterQueueEvent extends Event {
private Customer customer;
private Shop shop;
private ServiceCounter counter;
public JoinCounterQueueEvent(double time, Customer customer, Shop shop, ServiceCounter counter) {
super(time);
this.customer = customer;
this.shop = shop;
}
@Override
public Event[] simulate() {
this.counter.joinQueue(customer);
return new Event[] {};
}
@Override
public String toString() {
return String.format("%s: %s joined counter queue (at %s)",
super.toString(),
this.customer, this.counter);
}
}

View File

@ -1,9 +1,9 @@
class JoinQueueEvent extends Event {
class JoinShopQueueEvent extends Event {
private Customer customer;
private Shop shop;
public JoinQueueEvent(Customer customer, Shop shop) {
public JoinShopQueueEvent(Customer customer, Shop shop) {
super(customer.getArrivalTIme());
this.customer = customer;
this.shop = shop;
@ -12,12 +12,12 @@ class JoinQueueEvent extends Event {
@Override
public Event[] simulate() {
this.shop.joinQueue(customer);
return new Event[] {};
return new Event[] {};
}
@Override
public String toString() {
return String.format("%s: %s joined queue %s",
return String.format("%s: %s joined shop queue %s",
super.toString(),
this.customer, this.shop.queueString());
}

View File

@ -29,10 +29,10 @@ class Queue<T> {
*/
public Queue(int size) {
this.maxSize = size;
// The only way to add values to `items` is via enq(), and we can only put
// objects of type T via that method. Thus, it is safe to cast Comparable[]
// The only way to add values to `items` is via enq(), and we can only put
// objects of type T via that method. Thus, it is safe to cast Comparable[]
// to T[].
@SuppressWarnings({"unchecked", "rawtypes"})
@SuppressWarnings("unchecked")
T[] temp = (T[]) new Object[size];
this.items = temp;
this.first = -1;

View File

@ -24,6 +24,22 @@ public class ServiceCounter implements Comparable<ServiceCounter> {
this.available = true;
}
public boolean isQueueFull() {
return this.queue.isFull();
}
public boolean isQueueEmpty() {
return this.queue.isEmpty();
}
public void joinQueue(Customer customer) {
this.queue.enq(customer);
}
public Customer leaveQueue() {
return this.queue.deq();
}
public ServiceCounter(int queueSize) {
this.id = lastId++;
this.available = true;
@ -32,7 +48,7 @@ public class ServiceCounter implements Comparable<ServiceCounter> {
@Override
public String toString() {
return "S" + id;
return String.format("S%s %s", id, this.queue);
}
@Override

View File

@ -26,7 +26,33 @@ class ServiceEndEvent extends Event {
@Override
public Event[] simulate() {
// if there are customers in the counter queue, they will be serviced next.
// Customers in the shop queue will then be added to the counter queue
if (!this.counter.isQueueEmpty()) {
Customer serviceCustomer = this.counter.leaveQueue();
if (!this.shop.isQueueEmpty()) {
return new Event[] {
new DepartureEvent(this.getTime(), this.customer, this.shop, this.counter),
new ServiceBeginEvent(this.getTime(), serviceCustomer, this.shop, this.counter),
new JoinCounterQueueEvent(this.getTime(), this.shop.leaveQueue(), this.shop, counter)
};
}
return new Event[] {
new DepartureEvent(this.getTime(), this.customer, this.shop, this.counter),
new ServiceBeginEvent(this.getTime(), serviceCustomer, this.shop, this.counter),
};
}
// There can also be the case where the counter queue may be empty but there are
// customers in the shop queue.
if (!this.shop.isQueueEmpty()) {
return new Event[] {
new DepartureEvent(this.getTime(), this.customer, this.shop, this.counter),
new ServiceBeginEvent(this.getTime(), this.shop.leaveQueue(), this.shop, this.counter),
};
}
// else there are no more customers in the queue, and the counter can be freed
this.counter.free();
return new Event[] { new DepartureEvent(this.getTime(), customer, shop, counter) };
return new Event[] { new DepartureEvent(this.getTime(), this.customer, this.shop, this.counter) };
}
}

View File

@ -26,20 +26,19 @@ public class Shop {
*/
public ServiceCounter getAvailableCounter() {
// Check if this logic can be moved elsewhere
/*
for (int i = 0; i < this.counters.length; i++) {
if (this.counters[i].isAvailable()) {
return counters[i];
for (int i = 0; i < this.counters.length(); i++) {
ServiceCounter counter = this.counters.get(i);
if (counter.isAvailable()) {
return counter;
}
}
*/
return null;
}
public boolean isQueueFull() {
return this.queue.isFull();
}
public boolean isQueueEmpty() {
return this.queue.isEmpty();
}
@ -52,6 +51,14 @@ public class Shop {
return this.queue.deq();
}
public ServiceCounter findCounterWithQueue() {
ServiceCounter minCounter = this.counters.min();
if (!minCounter.isQueueFull()) {
return minCounter;
}
return null;
}
public String queueString() {
return this.queue.toString();
}