This commit is contained in:
Yadunand Prem 2022-08-25 17:25:02 +08:00
commit 08f94aa5d3
22 changed files with 516 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
Lab1.pdf

34
ArrivalEvent.java Normal file
View File

@ -0,0 +1,34 @@
class ArrivalEvent extends BaseShopEvent {
double serviceTime;
public ArrivalEvent(double time, int customerId, boolean[] available, double serviceTime) {
super(time, customerId, available);
this.availableCounters = available;
this.serviceTime = serviceTime;
}
@Override
public Event[] simulate() {
int counter = -1;
for (int i = 0; i < this.availableCounters.length; i++) {
if (this.availableCounters[i]) {
counter = i;
break;
}
}
if (counter == -1) {
return new Event[] { new DepartureEvent(this.getTime(), customerId, availableCounters) };
}
return new Event[] {
new ServiceBeginEvent(this.getTime(), this.customerId, this.availableCounters, this.serviceTime,
counter) };
}
@Override
public String toString() {
return super.toString() + String.format(": Customer %d arrives", this.customerId);
}
}

22
BaseShopEvent.java Normal file
View File

@ -0,0 +1,22 @@
/**
* This class encapsulates an event in the shop
* simulation. Your task is to replace this
* class with new classes, following proper OOP principles.
*
* @author Wei Tsang
* @version CS2030S AY21/22 Semester 2
*/
abstract class BaseShopEvent extends Event {
final int customerId;
boolean[] availableCounters;
public BaseShopEvent(double time, int customerId, boolean[] availableCounters) {
super(time);
this.customerId = customerId;
this.availableCounters = availableCounters;
}
}

19
DepartureEvent.java Normal file
View File

@ -0,0 +1,19 @@
class DepartureEvent extends BaseShopEvent {
public DepartureEvent(double time, int customerId, boolean[] available) {
super(time, customerId, available);
}
@Override
public String toString() {
return super.toString()
+ String.format(": Customer %d departed", this.customerId);
}
@Override
public Event[] simulate() {
return new Event[] {};
}
}

72
Event.java Normal file
View File

@ -0,0 +1,72 @@
/**
* The Event class is an abstract class that encapsulates a
* discrete event to be simulated. An event encapsulates the
* time the event occurs. A subclass of event _must_ override
* the simulate() method to implement the logic of the
* simulation when this event is simulated. The simulate method
* returns an array of events, which the simulator will then
* add to the event queue. Note that an event also implements
* the Comparable interface so that a PriorityQueue can
* arrange the events in the order of event time.
*
* @author Wei Tsang
* @version CS2030S AY21/22 Semester 2
*/
abstract class Event implements Comparable<Event> {
/** The time this event occurs in the simulation. */
private final double time;
/**
* Creates an event that occurs at the given time.
*
* @param time The time the event occurs.
*/
public Event(double time) {
this.time = time;
}
/**
* Getter to return the time of this event.
*
* @return The time this event occurs.
*/
public double getTime() {
return this.time;
}
/**
* Compare this event with a given event e.
*
* @param e The other event to compare to.
* @return 1 if this event occurs later than e;
* 0 if they occur the same time;
* -1 if this event occurs earlier.
*/
@Override
public int compareTo(Event e) {
if (this.time > e.time) {
return 1;
} else if (this.time == e.time) {
return 0;
} else {
return -1;
}
}
/**
* Return the string representation this event.
*
* @return A string consists of the time this event occurs.
*/
@Override
public String toString() {
return String.format("%.3f", this.time);
}
/**
* Simulate this event.
*
* @return An array of new events to be scheduled by the simulator.
*/
public abstract Event[] simulate();
}

26
Lab1.java Normal file
View File

@ -0,0 +1,26 @@
import java.util.Scanner;
/**
* The main class for CS2030S Lab 1.
*
* @author Wei Tsang
* @version CS2030S AY21/22 Semester 2
*/
class Lab1 {
public static void main(String[] args) {
// Create a scanner to read from standard input.
Scanner sc = new Scanner(System.in);
// Create a simulation. The ShopSimulation
// constructor will read the simulation parameters
// and initial events using the scanner.
Simulation simulation = new ShopSimulation(sc);
// Create a new simulator and run the simulation
new Simulator(simulation).run();
// Clean up the scanner.
sc.close();
}
}

27
ServiceBeginEvent.java Normal file
View File

@ -0,0 +1,27 @@
class ServiceBeginEvent extends BaseShopEvent {
double serviceTime;
int counterId;
public ServiceBeginEvent(double time, int customerId, boolean[] available, double serviceTime, int counterId) {
super(time, customerId, available);
this.serviceTime = serviceTime;
this.counterId = counterId;
// TODO Auto-generated constructor stub
}
@Override
public String toString() {
return super.toString()
+ String.format(": Customer %d service begin (by Counter %d)", this.customerId, this.counterId);
}
@Override
public Event[] simulate() {
this.availableCounters[this.counterId] = false;
double endTime = this.getTime() + this.serviceTime;
return new Event[] {
new ServiceEndEvent(endTime, this.customerId, this.availableCounters, this.counterId) };
}
}

23
ServiceEndEvent.java Normal file
View File

@ -0,0 +1,23 @@
class ServiceEndEvent extends BaseShopEvent {
int counterId;
public ServiceEndEvent(double time, int customerId, boolean[] available, int counterId) {
super(time, customerId, available);
this.counterId = counterId;
// TODO Auto-generated constructor stub
}
@Override
public String toString() {
return super.toString()
+ String.format(": Customer %d service done (by Counter %d)", this.customerId, this.counterId);
}
@Override
public Event[] simulate() {
this.availableCounters[counterId] = true;
return new Event[] { new DepartureEvent(this.getTime(), customerId, availableCounters) };
}
}

58
ShopSimulation.java Normal file
View File

@ -0,0 +1,58 @@
import java.util.Scanner;
/**
* This class implements a shop simulation.
*
* @author Wei Tsang
* @version CS2030S AY21/22 Semester 2
*/
class ShopSimulation extends Simulation {
/**
* The availability of counters in the shop.
*/
public boolean[] availableCounters;
/**
* The list of customer arrival events to populate
* the simulation with.
*/
public Event[] initEvents;
/**
* Constructor for a shop simulation.
*
* @param sc A scanner to read the parameters from. The first
* integer scanned is the number of customers; followed
* by the number of service counters. Next is a
* sequence of (arrival time, service time) pair, each
* pair represents a customer.
*/
public ShopSimulation(Scanner sc) {
initEvents = new Event[sc.nextInt()];
int numOfCounters = sc.nextInt();
availableCounters = new boolean[numOfCounters];
for (int i = 0; i < numOfCounters; i++) {
availableCounters[i] = true;
}
int id = 0;
while (sc.hasNextDouble()) {
double arrivalTime = sc.nextDouble();
double serviceTime = sc.nextDouble();
initEvents[id] = new ArrivalEvent(arrivalTime, id, availableCounters, serviceTime);
id += 1;
}
}
/**
* Retrieve an array of events to populate the
* simulator with.
*
* @return An array of events for the simulator.
*/
@Override
public Event[] getInitialEvents() {
return initEvents;
}
}

20
Simulation.java Normal file
View File

@ -0,0 +1,20 @@
/**
* This class is a general abstract class that
* encapsulates a simulation. To implement a
* simulation, inherit from this class and implement
* the `getInitialEvents` method.
*
* @author Wei Tsang
* @version CS2030S AY21/22 Semester 2
*/
abstract class Simulation {
/**
* An abstract method to return an array of events
* used to initialize the simulation.
*
* @return An array of initial events that the
* simulator can use to kick-start the
* simulation.
*/
public abstract Event[] getInitialEvents();
}

51
Simulator.java Normal file
View File

@ -0,0 +1,51 @@
import java.util.PriorityQueue;
/**
* This class implements a discrete event simulator.
* The simulator maintains a priority queue of events.
* It runs through the events and simulates each one until
* the queue is empty.
*
* @author Wei Tsang
* @version CS2030S AY21/22 Semester 2
*/
public class Simulator {
/** The event queue. */
private final PriorityQueue<Event> events;
/**
* The constructor for a simulator. It takes in
* a simulation as an argument, and calls the
* getInitialEvents method of that simulation to
* initialize the event queue.
*
* @param simulation The simulation to simulate.
*/
public Simulator(Simulation simulation) {
this.events = new PriorityQueue<Event>();
for (Event e : simulation.getInitialEvents()) {
this.events.add(e);
}
}
/**
* Run the simulation until no more events is in
* the queue. For each event in the queue (in
* increasing order of time), print out its string
* representation, then simulate it. If the
* simulation returns one or more events, add them
* to the queue, and repeat.
*/
public void run() {
Event event = this.events.poll();
while (event != null) {
System.out.println(event);
Event[] newEvents = event.simulate();
for (Event e : newEvents) {
this.events.add(e);
}
event = this.events.poll();
}
return;
}
}

4
inputs/Lab1.1.in Normal file
View File

@ -0,0 +1,4 @@
3 1
1.0 1.0
3.0 1.0
5.0 1.0

4
inputs/Lab1.2.in Normal file
View File

@ -0,0 +1,4 @@
3 1
1.1 2.0
2.2 2.0
3.3 2.0

6
inputs/Lab1.3.in Normal file
View File

@ -0,0 +1,6 @@
5 2
1.0 1.0
1.2 1.0
1.4 1.0
1.6 1.0
2.1 1.0

5
inputs/Lab1.4.in Normal file
View File

@ -0,0 +1,5 @@
4 2
1.0 1.0
1.1 1.0
2.2 1.0
2.3 1.0

4
inputs/Lab1.5.in Normal file
View File

@ -0,0 +1,4 @@
3 2
1.0 4
2.1 1
4.2 1

12
outputs/Lab1.1.out Normal file
View File

@ -0,0 +1,12 @@
1.000: Customer 0 arrives
1.000: Customer 0 service begin (by Counter 0)
2.000: Customer 0 service done (by Counter 0)
2.000: Customer 0 departed
3.000: Customer 1 arrives
3.000: Customer 1 service begin (by Counter 0)
4.000: Customer 1 service done (by Counter 0)
4.000: Customer 1 departed
5.000: Customer 2 arrives
5.000: Customer 2 service begin (by Counter 0)
6.000: Customer 2 service done (by Counter 0)
6.000: Customer 2 departed

10
outputs/Lab1.2.out Normal file
View File

@ -0,0 +1,10 @@
1.100: Customer 0 arrives
1.100: Customer 0 service begin (by Counter 0)
2.200: Customer 1 arrives
2.200: Customer 1 departed
3.100: Customer 0 service done (by Counter 0)
3.100: Customer 0 departed
3.300: Customer 2 arrives
3.300: Customer 2 service begin (by Counter 0)
5.300: Customer 2 service done (by Counter 0)
5.300: Customer 2 departed

16
outputs/Lab1.3.out Normal file
View File

@ -0,0 +1,16 @@
1.000: Customer 0 arrives
1.000: Customer 0 service begin (by Counter 0)
1.200: Customer 1 arrives
1.200: Customer 1 service begin (by Counter 1)
1.400: Customer 2 arrives
1.400: Customer 2 departed
1.600: Customer 3 arrives
1.600: Customer 3 departed
2.000: Customer 0 service done (by Counter 0)
2.000: Customer 0 departed
2.100: Customer 4 arrives
2.100: Customer 4 service begin (by Counter 0)
2.200: Customer 1 service done (by Counter 1)
2.200: Customer 1 departed
3.100: Customer 4 service done (by Counter 0)
3.100: Customer 4 departed

16
outputs/Lab1.4.out Normal file
View File

@ -0,0 +1,16 @@
1.000: Customer 0 arrives
1.000: Customer 0 service begin (by Counter 0)
1.100: Customer 1 arrives
1.100: Customer 1 service begin (by Counter 1)
2.000: Customer 0 service done (by Counter 0)
2.000: Customer 0 departed
2.100: Customer 1 service done (by Counter 1)
2.100: Customer 1 departed
2.200: Customer 2 arrives
2.200: Customer 2 service begin (by Counter 0)
2.300: Customer 3 arrives
2.300: Customer 3 service begin (by Counter 1)
3.200: Customer 2 service done (by Counter 0)
3.200: Customer 2 departed
3.300: Customer 3 service done (by Counter 1)
3.300: Customer 3 departed

12
outputs/Lab1.5.out Normal file
View File

@ -0,0 +1,12 @@
1.000: Customer 0 arrives
1.000: Customer 0 service begin (by Counter 0)
2.100: Customer 1 arrives
2.100: Customer 1 service begin (by Counter 1)
3.100: Customer 1 service done (by Counter 1)
3.100: Customer 1 departed
4.200: Customer 2 arrives
4.200: Customer 2 service begin (by Counter 1)
5.000: Customer 0 service done (by Counter 0)
5.000: Customer 0 departed
5.200: Customer 2 service done (by Counter 1)
5.200: Customer 2 departed

73
test.sh Normal file
View File

@ -0,0 +1,73 @@
#!/bin/bash
function control_c() {
if [ -e $out ]
then
rm -f $out
fi
}
trap control_c INT
if [ $# -ne 1 ]
then
echo "usage: $0 <main class>"
exit 1
fi
PROG=$1
if [ ! -e $PROG.class ]
then
echo "$PROG.class does not exist. Have you compiled it with make or javac?"
exit 1
fi
num_failed=0
i=1
while true
do
if [ -e inputs/$PROG.$i.in ]
then
if [ $(uname) == "Darwin" ]
then
out=$(mktemp -t $PROG)
else
out=$(mktemp --suffix=$PROG)
fi
java $PROG < inputs/$PROG.$i.in > $out
status="$?"
if [ "$status" -ne "0" ]
then
echo "$PROG: return non-zero status $status for test case $i"
# cat inputs/$PROG.$i.in
num_failed=$((num_failed + 1))
else
if [ -e $out ]
then
if [ `diff -bB $out outputs/$PROG.$i.out | wc -l` -ne 0 ]
then
echo "test $i: failed"
#cat inputs/$PROG.$i.in
num_failed=$((num_failed + 1))
else
echo "test $i: passed"
fi
rm -f $out
else
echo "$PROG: cannot find output file. Execution interrupted?"
num_failed=$((num_failed + 1))
fi
fi
i=$((i + 1))
else
break
fi
done
if [ $i -eq 1 ]
then
echo "$PROG: no test cases found 🤷"
elif [ $num_failed -eq 0 ]
then
echo "$PROG: passed everything 🎉"
fi
# vim:noexpandtab:sw=4:ts=4