Lab 4a: Simulator 2.0
Submission deadline: 2359, Friday, March 30, 2018.
Prerequisites
This lab assumes that students:
- have an understanding of the customer/server system being simulated in Lab 1b
Learning Objectives
After completing this lab, students should be able to write classes that are immutable and free from side effects.
Setup
A skeleton code for Lab 4a is provided. To setup Lab 4a, do the following.
- Login to
cs2030-i
- Copy
~cs2030/lab4a
to~/lab4a
If you are still not familiar with how to do the above, please revisit the UNIX guide.
Goals
The skeleton code provided solves Lab 1b in OO style. The design of the class, however, have been adapted for Lab 4a and 4b, where the goal is to re-implement the solution in a functional style.
In Lab 4a, your task is to change the classes provided so that they become (i) immutable, and (ii) no side effects.
You should use the provided skeleton code as the base for modification. If you wish to modify your own solution to Lab 1b, please feel free to do so as an additional exercise, but do not submit that for Lab 4a/4b.
Immutable
Recall that immutable does not mean an object cannot be modified, but rather, modifying the state of the object always cause a new version of the object with the updated state to be returned. As such you will see that the return type of all methods that changes the state of a class is an object of the class itself. For instance,
1 2 3 | public Statistics serveOneCustomer() { : } |
When we update the state inside Statistics
by incrementing totalNumOfServedCustomers
by 1, we should return a new object with this value incremented, instead of changing the object calling serveOneCustomer
.
The classes you need to make into immutable classes are:
PriorityQueue
, from the packagecs2030.util
.Server
,Shop,
SimState,
Statistics, from the package
cs2030.simulator`.
You should be familiar with the classes, except for
- PriorityQueue
, which is our own version of immutable priority queue built on top of java.util.PriorityQueue
;
- SimState
, the simulation state, which encapsulates three things: the event queue, the statistics, and the shop (states of the servers).
import java.util.*;
While it is convenient to do a mass import with import java.util.*
or similar expression, it increases the chances of name clashes. In this case, we use the same name PriorityQueue
as java.util
. So you should always import only specific classes that you want to use. The checkstyle
configuration on cs2030-i
has been updated to check for this.
No Side Effects
By making the classes immutable, updating the state of one object does not lead to side effects, as a new object is created with the updated state, the existing object remains unchanged.
The remaining side effects in the code after you make the classes immutable, are reading of arrival time from either a file or standard input, and printing of debugging statements to the standard output. In functional-style programming, to keep our functions pure without side effects, we can quarantine these input/output statements to the main function.
For Lab 4a, one way to do this, is to include all the string printed as part of the simulation state. Instead of printing a string to standard output immediately, we append this string to the simulation state. At the end of the simulation, we print out all strings (along with the average waiting time, number of customers served, and number of customers lost).
By doing so, we achieve pure functional code in all parts of our program except the input and output operations in the main
method.
Referential Transparency
By making your classes immutable and your code free from side effects (except in main
), you achieve the property of referential transparency: Any expression can be replaced by the resulting value of that expression, without changing the property of the program.
Simulation Scenario
The scenario is the same as what you solved for Lab 1b (multiple servers, each server has at most one waiting customer).
- The shop has k (k \ge 1) servers.
- Each server has enough space for only one waiting customer.
- The servers are arranged in fixed order, from 1 to k.
- Once a customer arrives at the shop:
- The customer scans the servers, from 1 to k, and approaches the first idle server he/she found to be served immediately.
- If there is no idle server, the customer scans the server, from 1 to k, and waits at the first busy server without a waiting customer that he/she found.
- If every server is busy and already has a customer waiting, the customer leaves the shop.
Grading
This is an ungraded lab. But, submit it anyway as a record that you have attempted the lab.
Input and Output
The input file format is exactly the same as that from Lab 1b. The first line of the input file now is an integer, specifying the number of servers in the shop. The remaining lines contain a sequence of double values, each is the arrival time of a customer (in any order).
Remember: you must not change the formatting of the last line of output.
The test cases and outputs1 should be:
Test Case | Output |
---|---|
1 | 0.000 1 0 |
2 | 0.000 4 0 |
3 | 0.350 6 4 |
4 | 0.000 7 0 |
5 | 0.210 99 1 |
6 | 0.664 39 41 or 0.665 39 41 or 0.667 39 41 |
We removed Test Case 7 (which tested for the limit of 100 in event queue, which no longer applies as we are using PriorityQueue.)
The code given already provides the correct answer. Checking against this answer just makes sure that you did not introduce new bugs while making your code immutable and side effects free.
Submission
When you are ready to submit your lab, on cs2030-i
, run the script
1 | ~cs2030/submit4a |
which will copy all files matching *.java
(and nothing else) from your ~/lab4a
directory and its subdirectory on cs2030-i
to an internal grading directory. We will test compile and test run with a tiny sample input to make sure that your submission is OK.
-
After piping through
tail
(e.g.,java LabFourA < TESTDATA1.txt | tail -1
) ↩