Assignment #1
Value: 25%
Due Date for Checkpoint #1 (NO LATE SUBMISSIONS POSSIBLE): Friday 28 March 2025 9:00pm
(Extended) Due Date for Checkpoint #1 (NO LATE SUBMISSIONS POSSIBLE): Monday 31 March 2025 9:00pm
Due Date for Checkpoint #2: Monday 28 April 2025 9:00pm
(Up to 2 days LATE) for Checkpoint #2: Wednesday 30 April 2025 9:00pm (See Late Submissions)
Learning Outcomes:
- Gain more confidence programming in Java.
- Design an object-oriented programming (OOP) solution to a problem.
- Apply OOP concepts such as inheritance, polymorphism, and encapsulation (information hiding).
Full Test Cases
You can find the full test cases below.
Table of Contents
- Recommended Approach
- The Operator Management System
- Locations in te reo Māori
- Files Provided
- Checkpoints
- OOP Requirements
- The Commands
- Tasks
- Marking Scheme
- Important Instructions
Warning about static fields
You should not need to use static
fields in this assignment. If you are using static
fields, you will encounter lots of problems.
If you use static
fields, you will notice a weird behaviour that your test cases will pass when executed one at a time, but mostly fail when executed in one go. This is because the static
field values are shared across all test cases, and the test cases are executed with this persistant value. This is not the behaviour you want.
So, be sure to always test your final submission using the command we have provided below, as this is how you will be marked:
./mvnw clean compile test
for Unix/Mac OS or .\mvnw.cmd clean compile test
for Windows
Recommended Approach
To make sure that your machine is properly set for doing the assignment (and all assignments in this course), refer to the FAQ on the course website.
Then it’s a matter of:
- Clone the GitHub repository.
- Use Visual Studio Code for doing the assignment.
- Use the graphical “Testing” view in Visual Studio Code to run the tests (details below).
- As a final check before submitting, use the Maven wrapper to check that everything compiles and the test cases pass (details below).
To help you get started, you might want to watch the following video:
Let’s begin!
Clone the GitHub repository
Clone the assignment repository by accepting the GitHub invitation that was sent to you.
This would be to the same GitHub account that you used in the Hello GitHub assignment.
The Operator Management System
In this assignment, you will develop a centralised system for managing multiple Aotearoa New Zealand activity operators. The system is designed to oversee details of various operators, their offered activities, and the feedback received from customers and experts.
With this system, administrative staff can:
- View a list of all registered operators.
- Register new operators by providing a name and location.
- Create activities and assign them to existing operators.
- Collect and display different types of reviews for each activity.
- Perform various actions on reviews depending on their type.
- Determine the top activity in each location.
Since budget constraints require a simple solution, the interface will be entirely terminal-driven. This means that the administrators will interact with the system through a menu displayed in the terminal; they select commands by entering the corresponding codes, and additional inputs are prompted as necessary. Once a command is selected, the system processes the action accordingly.
The menu of commands will be displayed on the terminal as follows:
SEARCH_OPERATORS [1 argument] Search for operators by keyword <KEYWORD> in their name or location
CREATE_OPERATOR [2 arguments] Create a new operator with <OPERATOR_NAME> and <LOCATION>
VIEW_ACTIVITIES [1 argument] View all activities for <OPERATOR_ID>
CREATE_ACTIVITY [3 arguments] Create activity with <ACTIVITY_NAME> and <ACTIVITY_TYPE> for <OPERATOR_ID>
SEARCH_ACTIVITIES [1 argument] Search activities by <KEYWORD> in activity name or type or operator location
ADD_PUBLIC_REVIEW [1 argument] Add a public review for an activity identified by <ACTIVITY_ID>
ADD_PRIVATE_REVIEW [1 argument] Add a private review for an activity identified by <ACTIVITY_ID>
ADD_EXPERT_REVIEW [1 argument] Add an expert review for an activity identified by <ACTIVITY_ID>
DISPLAY_REVIEWS [1 argument] Display all reviews for an activity identified by <ACTIVITY_ID>
ENDORSE_REVIEW [1 argument] Endorse a public review identified by <REVIEW_ID>
RESOLVE_REVIEW [2 arguments] Resolve a private review identified by <REVIEW_ID> with <RESPONSE>
UPLOAD_REVIEW_IMAGE [2 arguments] Upload an <IMAGE_NAME> for an expert review identified by <REVIEW_ID>
DISPLAY_TOP_ACTIVITIES [no args] Display the top activity in each location based on public and expert reviews
HELP [no args] Print usage
EXIT [no args] Exit the application
You have been given an incomplete implementation of the system, with only the command line interface implemented. You need to implement the commands using object-oriented programming!
Locations in te reo Māori
Given the relevance of this system to Aotearoa New Zealand, the clients have asked us to support both English and te reo Māori in the system for the locations. The official list of locations in te reo Māori are provided on the ReoMāori website. The locations are summarised in the map below:
Want to practice your pronunciation?
If you would like to practice your pronunciation of the te reo Māori alphabet, you can listen to them below:
Short Vowels
a | |
e | |
i | |
o | |
u |
Long Vowels
ā | |
ē | |
ī | |
ō | |
ū |
Consonants
h | |
k | |
m | |
n | |
p | |
r | |
t | |
w |
Digraphs
ng | |
wh |
These have come from the ReoMāori guide to pronunciation website.
Files Provided
Below is a list of the files provided to you for this assignment. You should not modify any of the files provided to you, except for the OperatorManagementSystem.java
file (where you will need to implement the logic for the commands), and the MainTest.java
file (where you can add your own test cases if you wish).
src/main/java/nz/ac/auckland/se281/Main.java
This class implements the command line interface (CLI).
You should not modify this class.
src/main/java/nz/ac/auckland/se281/MessageCli.java
This class declares most of the messages of the system.
You should not modify this class, but you are encouraged to use it.
You are encouraged to refer to these messages in the code you write, as it will be easier for you to avoid spelling and formatting issues that might otherwise cause you to fail test cases.
There are two ways to use these messages in your code:
- Get the message so that you can print it yourself by calling the
getMessage()
method, or - Request for the message to be printed directly by calling the
printMessage()
method.
You will notice that most of the messages have %s
placeholders in their values. For example, have a look at the definition of the PROFILE_CREATED
message:
public enum MessageCli {
// ...
OPERATOR_CREATED("Successfully created operator '%s' ('%s') located in '%s'."),
// ...
}
There are three %s
placeholders, which means this message expects you to pass three arguments when you want to use getMessage()
or printMessage()
on the OPERATOR_CREATED
message.
For example, consider you want to construct the message Successfully created operator 'West Auckland Camel Treks' ('WACT-AKL-001') located in 'Auckland | Tāmaki Makaurau'.
If you want to get the message to print it yourself, you would do:
String message = MessageCli.OPERATOR_CREATED.getMessage("West Auckland Camel Treks", "WACT-AKL-001", "Auckland | Tāmaki Makaurau"); // get the message
System.out.println(message); // print it yourself
But, of course, it will often be easier to just print the message directly:
MessageCli.OPERATOR_CREATED.printMessage("West Auckland Camel Treks", "WACT-AKL-001", "Auckland | Tāmaki Makaurau"); // print the message directly
Be sure to dedicate time to understand how this works, as it will be very useful to use and make your job easier. You should already be familiar with this concept from how printf()
works in C.
src/main/java/nz/ac/auckland/se281/OperatorManagementSystem.java
This class declares the methods that are invoked by the command line interface (Main.java
). This is where you need to start your coding.
You must NOT change the signature of the existing methods of this class (such as changing method names, parameters, and return types).
Of course, you can (and you should) add instance fields and new methods of your own.
If you need to instantiate/initialise fields of the OperatorManagementSystem
instance, you can only use the provided zero-parameter constructor (public OperatorManagementSystem()
). You should not create other constructors in the OperatorManagementSystem
class, as they will not be used by the command line or test cases.
src/main/java/nz/ac/auckland/se281/Types.java
This Java file contains the following enum
types:
Location
ActivityType
ReviewType
These enum
types are used to represent the different locations, activity types, and review types that are supported by the system. You will find these useful when implementing your system.
You should not modify anything in the Types.java
file.
src/test/java/nz/ac/auckland/se281/MainTest.java
This Java file contains the JUnit test cases for this assignment. These test cases make sure that you have implemented most of the assignment correctly.
Making sure that your program passes all of the provided tests will not guarantee that you will get full marks for this assignment, but it will mean that you should get at least half of the marks for the parts that work according to those tests. In fact, we only provided to you half of the test cases that we will use for marking your assignment. You should also note that the test cases we will use for marking your assignment will use slightly different inputs, to ensure you are not hardcoding the expected outputs.
The way that these test cases work is the same as you have seen in the Hello GitHub assignment. You can run them in the same way, either using the Maven wrapper or the Test Runner for Java extension in VS Code.
Writing your own tests or extending the ones you have been given is strongly recommended. Add them inside MainTest.YourTests
, which you can find at the bottom of the MainTest.java
class. You also need to uncomment each Suite Class near the top of this file:
@RunWith(Suite.class)
@SuiteClasses({
MainTest.Task1.class,
// MainTest.Task2.class,
// MainTest.Task3.class,
// MainTest.YourTests.class, // <-- uncomment this line
})
You can easily write a test using the helper methods runCommands()
, assertContains()
and assertDoesNotContain()
.
These are implemented by us—they are not standard JUnit.
First, with runCommands()
you specify the commands to be executed (separated by a comma). With assertContains()
, you specify what is the text that you expect to see on the console after executing all the commands, while with assertDoesNotContain()
, you specify what is the text that you expect not to see on the console after executing all the commands.
For example, this test case checks that an operator is created and saved:
@Test
public void T1_xx_create_operator_saved() throws Exception {
runCommands(
CREATE_OPERATOR, "'West Auckland Camel Treks'", "'AKL'",
SEARCH_OPERATORS, "*",
EXIT);
assertContains("There is 1 matching operator found:");
assertContains("* West Auckland Camel Treks ('WACT-AKL-001' located in 'Auckland | Tāmaki Makaurau')");
assertDoesNotContain("Operator not created", true);
assertDoesNotContain("There are", true);
}
If the CREATE_OPERATOR
command correctly created and saved the operator, then the SEARCH_OPERATORS
command should find it. There are some messages that are expected to be there (checked with assertContains()
), and some that are not expected to be there (checked with assertDoesNotContain()
).
While you can add as many tests as you want, we will not consider them when marking your assignment. Be aware that your code must still work with the original version of the MainTest.java
file, where we will reuse the test cases initially provided to you (with slightly different values), while also adding new test cases not visible to you.
src/test/java/nz/ac/auckland/se281/CliTest.java
You should not modify this file.
This Java file is used by the testing framework.
Various “hidden” files
Note: We also provide additional “hidden” files (those starting with “.
”). You would need to change the folder options to be able to see them. We provide a .gitignore
file that specifies intentionally-untracked files that Git should ignore, and a .mvn
folder containing the Maven wrapper. You should not change these files, and you should not delete them.
Checkpoints
To help you tackle this assignment, we have split it into two checkpoints:
- Checkpoint #1 will cover Task 1.
- Checkpoint #2 will cover Tasks 2 and 3.
You will need to submit your code for each checkpoint to your GitHub repository before each checkpoint’s respective deadline. The due dates for each checkpoint are listed at the top of this page. Make sure that you have pushed your commits and that they appear in the remote GitHub repository before the deadline. Refer to the instructions at the bottom of this page (Final Submission on GitHub) for more information on how to submit your code.
Checkpoint #1
This checkpoint is about applying basic Java OOP concepts, such as:
- Using collections
- Using loops
- Using classes
Inside the MainTest.java
file, you will find the relevant test cases for this checkpoint are contained within:
- The
MainTest.Task1
class
Please note that the marks for Checkpoint #1 (i.e., test cases in Task 1
) will only be based on the code you submit before the end of the Checkpoint #1 deadline. Any changes you make to your code after the Checkpoint #1 deadline (which might pass more test cases in Task 1
), will not be considered for marks towards Checkpoint #1 (regardless of whether you pass more or fewer test cases in Task 1
by the end of Checkpoint #2). This includes the hidden Task 1
test cases that we will use for marking your assignment.
Please also note that there is no “late submission” opportunities for Checkpoint #1. This also means we cannot support individual “extensions” for Checkpoint #1 (even if you were to provide a medical certificate).
This is because:
- We will be releasing the hidden test cases for
Task 1
soon after Checkpoint #1 deadline passes (after we do some final checks on Task 1 submissions), so you can take these into consideration if you wish (they might help for implementation towards Checkpoint #2), and - We will be using the same repository for the entire assignment, meaning it will be impossible to distinguish between the code you intended to target
Task 1
versus code you are writing that targetsTask 2
andTask 3
.
Checkpoint #2
This checkpoint is about applying slightly more advanced OOP concepts:
- Using inheritance
- Using polymorphism
- Using abstract classes
Inside the MainTest.java
file, you will find the relevant test cases for this checkpoint are contained within:
- The
MainTest.Task2
class - The
MainTest.Task3
class
Just like there are hidden test cases for Task 1
, there will also be hidden test cases for Task 2
and Task 3
. They will be released soon after the Checkpoint #2 deadline passes, after preliminary marking has been completed to make sure the test cases were fair and reasonable.
OOP Requirements
For this assignment, you should use the OOP concepts we covered in class. As such, you should not implement all your code inside the OperatorManagementSystem
class. You should create appropriate classes. We are giving you complete freedom on how to do the OOP design. You will decide how many and which Java classes to create.
Inheritance (Checkpoint #2)
You should make sure that you are using inheritance for Checkpoint #2. There, we will check for the following:
- Your code should have at least one abstract class, and
- Your code should have at least three (sub)classes that extend class(es) that you have created.
Note that not all the sub-classes necessarily need to extend the abstract class. It is up to you.
For example, you meet the requirement if you create an abstract class public abstract class A
, a public class B
, and if you have three (sub)classes public class C extends A
, public class D extends B
, and public class E extends B
:
As another example, you meet the requirement if you create an abstract class public abstract class A
, and if you have three (sub)classes public class B extends A
, public class C extends A
, and public class D extends A
. You can of course, create more classes on top of these, depending on your OO design choices:
It goes without saying that just creating the classes is not sufficient. Your code has to make use of the classes.
It goes without saying: just creating the classes is not sufficient
First, your code must use those classes. Obviously, if you create classes and never use them to implement your logic, you will not get any credit for them.
What’s more, you must place your classes in separate files to practice good coding practices. For example, if you have a class Foo
and a class Bar
, you should place Foo
in a file called Foo.java
and Bar
in a file called Bar.java
. This is good practice and it will make it easier for you to manage your code. For marking the OO design, we will only consider classes that are in separate files for the purposes of receiving those marks.
The Commands
Before proceeding with the tasks, read the code provided to you and start to familiarise yourself with the command-line interface.
To run the application in VS Code in an interactive mode, run the Main class using the Maven wrapper through VS Code’s built-in terminal. If the terminal window is not open, you can open it by clicking on the Terminal
menu, then New Terminal
. Then type the following command:
./mvnw compile exec:java@run
for Unix/Mac OS or .\mvnw.cmd compile exec:java@run
for Windows
You should see the following output:
Now you can try some of the commands!
Note: The commands are not case sensitive. Also, you can use underscores or hyphens interchangeably.
For example, the following are all correct and equivalent:
create-operator
create_operator
CREATE_OPERATOR
CREATE-OPERATOR
Create-Operator
CrEaTe_OpErAtOr
CREATE-operator
create-OPERATOR
Try the HELP
command to see the list of available commands:
You can also try the EXIT
command to exit the system:
Only the HELP
and EXIT
commands are implemented for you. You will need to implement the rest of the commands.
Commands with no arguments
The following commands do not require any arguments:
DISPLAY_TOP_ACTIVITIES [no args] Display the top activity in each location based on public and expert reviews
HELP [no args] Print usage
EXIT [no args] Exit the application
This means you can just type them in the command line, press Enter or Return, and they will be executed. For example, if you use the DISPLAY_TOP_ACTIVITIES
command and press Enter or Return, you should see the following:
Obviously, nothing got printed since you need to implement the logic. But notice that no error was reported, since you did not add any arguments (as expected by the command).
If you were to use the DISPLAY_TOP_ACTIVITIES
command followed by some arguments, you would get an error message:
This is because the command expects no arguments, but you provided some (in this case, added
, extra
, things
).
Commands with arguments
The following commands require arguments:
SEARCH_OPERATORS [1 argument] Search for operators by keyword <KEYWORD> in their name or location
CREATE_OPERATOR [2 arguments] Create a new operator with <OPERATOR_NAME> and <LOCATION>
VIEW_ACTIVITIES [1 argument] View all activities for <OPERATOR_ID>
CREATE_ACTIVITY [3 arguments] Create activity with <ACTIVITY_NAME> and <ACTIVITY_TYPE> for <OPERATOR_ID>
SEARCH_ACTIVITIES [1 argument] Search activities by <KEYWORD> in activity name or type or operator location
ADD_PUBLIC_REVIEW [1 argument] Add a public review for an activity identified by <ACTIVITY_ID>
ADD_PRIVATE_REVIEW [1 argument] Add a private review for an activity identified by <ACTIVITY_ID>
ADD_EXPERT_REVIEW [1 argument] Add an expert review for an activity identified by <ACTIVITY_ID>
DISPLAY_REVIEWS [1 argument] Display all reviews for an activity identified by <ACTIVITY_ID>
ENDORSE_REVIEW [1 argument] Endorse a public review identified by <REVIEW_ID>
RESOLVE_REVIEW [2 arguments] Resolve a private review identified by <REVIEW_ID> with <RESPONSE>
UPLOAD_REVIEW_IMAGE [2 arguments] Upload an <IMAGE_NAME> for an expert review identified by <REVIEW_ID>
This means you must provide the required number of arguments before pressing Enter or Return for them to be executed. For example, if you use the CREATE_OPERATOR
command without arguments (or the wrong number of arguments) and press Enter or Return, you should see the following:
To use it correctly, you need to provide the correct number of arguments:
Obviously, nothing got printed since you need to implement the logic. But notice that no error was reported, since you provided two arguments (as the command expects).
Tasks
To guide you through the assignment, we have divided it into three tasks. Task 1 corresponds to Checkpoint #1, while Task 2 and Task 3 together correspond to Checkpoint #2.
For each task, we provide a number of test cases (in MainTest.java
) that you can use to test your code.
Task 1 (Checkpoint #1) [Worth 6%]
Initial test results
As soon as you compile and run the tests, you will notice the following output…
With the Maven wrapper:
./mvnw clean compile test
for Unix/Mac OS or .\mvnw.cmd clean compile test
for Windows:
With the Test Runner for Java extension in VS Code:
From the left side of VS Code, click on the Testing icon:
You will then see all the test cases. You might need to expand to see them all:
Tip: Running a single test case at a time…
Running a single test at a time will help you focus on one test at a time, and will make it easier to understand what is going on.
Option 1: Using the command line
If you wanted to use the command line to run a single test case, you can do so by specifying the test case name. For example, to run the first test case, you would use the following command:
./mvnw compile -Dtest=nz.ac.auckland.se281.MainTest\$Task1#T1_01_name_of_test_case_method test
for Unix/Mac OS or
.\mvnw.cmd compile -Dtest=nz.ac.auckland.se281.MainTest\$Task1#T1_01_name_of_test_case_method test
for Windows
Note that you need to change two things:
- The name of the Task (e.g.,
Task1
), and - The name of the test case’s method (e.g.,
T1_01_name_of_test_case_method
).
However, we recommend you use the Test Runner for Java extension in VS Code, as it is much easier to use and allows you to debug your code more easily. See the next section here.
Option 2: Using VS Code’s Test Runner (recommended)
We recommend you use the Test Runner for Java extension in VS Code. It is a very useful tool that will help you run and debug your tests. It will give you control to run all tests at the same time (as in the example above), or run a single test at a time, for example:
It will also make it easier to debug your code, as you can set breakpoints and step through your code.
When you are trying to pass a particular test case, you will find the Debug Console tab in VS Code very useful. Here, you will see the output of your program after the test you selected has finished running:
For more help on how to debug your code in VS Code, see the VS Code debugging resource. In particular, there is a section called “Debugging for the Test Cases in the Assignments”.
If you are having issues running tests in Test Runner…
If you attempt to run the tests via the Test Runner, and it gives you some problems (e.g., there’s some weird error, or the tests don’t actually appear to run), then try running the tests via the command line first:
./mvnw clean compile test
for Unix/Mac OS or .\mvnw.cmd clean compile test
for Windows
This should then allow you to run the tests via the Test Runner as expected.
In either case, the examples above are telling you that 15 test cases were run, none of them passed, and all of them failed. In the output, you will find more details on why the test cases failed.
Hint: Look at the numbering of the test cases which guide you in a recommended order. In this case, T1_01_zero_operators()
is a good place to start.
For example, let’s consider the first test case as shown in the terminal, for when you use the Maven wrapper:
The same information is present in the Test Runner for Java extension in VS Code. You can click on the red x
() to see the details of the failed test:
The important message to read is:
java.lang.AssertionError: The test is expecting the following output in the console, but it was not there:
"There are no matching operators found."
This means that the test is expecting the output There are no matching operators found.
to be printed in the console, but it was not there. This is because you have not implemented the logic for the SEARCH_OPERATORS
command yet.
Let’s try something. Go to the searchOperators()
method inside OperatorManagementSystem.java
, and add the following code:
public void searchOperators(String keyword) {
// TODO implement
System.out.println("There are no matching operators found.");
}
Run your test again, and you should see the following:
Or, from the terminal, we see that now only 14 of the 15 tests are failing since we are passing the first test case:
Now, of course the edit we did was a hack to demonstrate how the tests work. We will very soon have some operators in the system, and this hard-coded print statement will cause all those other test cases to fail! We therefore need to implement the correct logic as described in the following sections.
Creating operators (CREATE_OPERATOR
and SEARCH_OPERATORS
)
Task 1 will require you to implement (some of) the logic for the CREATE_OPERATOR
and SEARCH_OPERATORS
commands.
The CREATE_OPERATOR
command creates a new operator with the specified operator name and location (passed as arguments to the CREATE_OPERATOR
command). If any invalid input is provided, an error message should be printed (details below).
The SEARCH_OPERATORS
command searches for operators by keyword in their name or location. Notice that the SEARCH_OPERATORS
command requires one argument, which is the keyword to search for.
If there are no operators in the system, it prints just the following header:
There are no matching operators found.
If the keyword specified is *
, it should print all the operators in the system. For example, if there are two operators in the system:
There are 2 matching operators found:
* West Auckland Camel Treks ('WACT-AKL-001' located in 'Auckland | Tāmaki Makaurau')
* Parliament Bungee Jump ('PBJ-WLG-001' located in 'Wellington | Te Whanganui-a-Tara')
If there is only one operator in the system, then the header should be singular:
There is 1 matching operator found:
* West Auckland Camel Treks ('WACT-AKL-001' located in 'Auckland | Tāmaki Makaurau')
You are recommended to attempt the test cases in the order they are numbered. This will help you build up your implementation incrementally. You will therefore notice that the first few test cases that use the SEARCH_OPERATORS
command are using the *
keyword, which means you should print all the operators in the system. So you can momentarily ignore the keyword argument until you reach the test cases that require you to search for specific operators by keyword (more on that later).
Take note of the differences between the different cases above:
- When the quantity is 0, it uses “no” and “operators” (plural), and the sentence ends with a period (“.”).
- When the quantity is 1, it uses “is” and “operator” (singular), and the sentence ends with a colon (“:”).
- When the quantity is 2 or more, it uses “are” and “operators” (plural), and the sentence ends with a colon (“:”).
Hint: Have a look at the MessageCli.OPERATORS_FOUND
message template:
OPERATORS_FOUND("There %s %s matching operator%s found%s")
This message template has four %s
placeholders:
- The first
%s
is for the verb (i.e., “is” or “are”) - The second
%s
is for the number of operators (e.g., “0”, “1”, “2”, etc.) - The third
%s
is for the word “operator”, whether you want it to be singular or plural (i.e., “operator” or “operators”) - The fourth
%s
is for the colon (“:”) or period (“.”)
To get the message "There are 2 matching operators found:"
, you can do one of the following:
MessageCli.OPERATORS_FOUND.getMessage("are", "2", "s", ":"); // Using the getMessage() method
MessageCli.OPERATORS_FOUND.printMessage("are", "2", "s", ":"); // Using the printMessage() method
When a new operator is created, it should be added to the system. The arguments have the following requirements:
<OPERATOR_NAME>
- Must be at least 3 characters long (surrounding spaces are not counted).
- You will notice the use of single quotes in the test cases. This is because the operator name can be a single word (in which case the single quotes are optional), or multiple words (in which case the single quotes are required). You don’t need to worry about this, as the code provided already handles this and gives you the full name regardless.
<LOCATION>
- The list of acceptable locations is provided in the
Location
enum in theTypes.java
file. - The user can type in the location in any combination of upper and lower case letters, using either the te reo Māori or English name, or the location’s abbreviation. For example, the user can type in
Auckland
,auckland
,Tāmaki Makaurau
,tāmaki makaurau
,AKL
, orakl
for the locationAuckland | Tāmaki Makaurau
. - Have a look at the
fromString
method in theLocation
enum to see how you can convert a string to aLocation
enum value. This will be useful. For example,Location.fromString("akl")
will returnLocation.AUCKLAND
.
There are a few other requirements that you need to consider, which are explained below.
✭ You do not need to worry about the user typing in too many or too few arguments. You can assume that the user will always type in a command that has the correct number of arguments (this is already handled for you in the code provided).
✭ You do not need to worry about test cases where there are multiple errors in the same command. You can assume that the user will always type in a command that has only one error at most.
✭ As a general rule, if there is nothing explicitly mentioned in this handout, then you do not have to take it into account. We have purposely limited the number of “corner cases” you need to consider, to make the assignment easier to complete. Otherwise, you will be forever anticipating every single possible input, and you will never finish the assignment. If we don’t mention it, you don’t have to worry about it. There won’t be any “hidden” test cases that will test for something we didn’t explicitly mention in this handout.
When a successful operator is created, a success message should be printed:
Successfully created operator '<OPERATOR_NAME>' ('<OPERATOR_ID>' located in '<LOCATION>').
For example:
281-activity-operator-system> CREATE_OPERATOR 'West Auckland Camel Treks' 'Akl'
Successfully created operator 'West Auckland Camel Treks' ('WACT-AKL-001') located in 'Auckland | Tāmaki Makaurau'.
The success message prints the operator name, operator ID, and location. The format of this message is very strict. Make sure you check for an appropriate message template in MessageCli
to help you.
The operator ID is generated as follows:
<OPERATOR_INITIALS>-<LOCATION_ABBREVIATION>-<THREE_DIGIT_NUMBER>
- The
OPERATOR_INITIALS
are composed from the first letter of each word in the operator name (in uppercase). For example, the operator initials forWest Auckland Camel Treks
would beWACT
, while the operator initials forParliament Bungee Jump
would bePBJ
. - The
LOCATION_ABBREVIATION
is the abbreviation of the location as per theLocation
enum. - The
THREE_DIGIT_NUMBER
is a three-digit number starting from001
and incrementing by1
for each new operator in the same location. If the operator is the first operator in the location, then the number should be001
(even if there are other operators in other locations in the system). If the operator is the second operator in the location, then the number should be002
, and so on.
To extract the operator initials from the operator name, you can use the String.split()
method. For example:
String operatorName = "West Auckland Camel Treks";
String[] words = operatorName.split(" ");
for (String word : words) {
System.out.println(word.charAt(0));
}
If there is already an operator with the same name in the same location, then the (duplicate) operator should not be created, and an error message should be printed. In the following example, the first time the operator is created successfully, while the second time the operator is not created as it’s a duplicate. Therefore, there’s only one operator in the system after the two commands:
281-activity-operator-system> CREATE_OPERATOR 'West Auckland Camel Treks' 'AKL'
Successfully created operator 'West Auckland Camel Treks' ('WACT-AKL-001') located in 'Auckland | Tāmaki Makaurau'.
281-activity-operator-system> CREATE_OPERATOR 'West Auckland Camel Treks' 'AKL'
Operator not created: the operator name 'West Auckland Camel Treks' already exists same location for 'Auckland | Tāmaki Makaurau'.
281-activity-operator-system> SEARCH_OPERATORS *
There is 1 matching operator found:
* West Auckland Camel Treks ('WACT-AKL-001' located in 'Auckland | Tāmaki Makaurau')
Searching for operators using a keyword
Above we discussed using the *
keyword to print all operators in the system. Now, we will discuss searching for operators using a keyword.
The keyword can be any string, and it should be case insensitive. Other than macrons for Māori words, you do not need to worry about any other special characters. The keyword might be a substring of the operator name or location.
The keyword is searched for in:
- The operator name (case insensitive),
- The operator location (case insensitive, te reo Māori, English, or abbreviation).
Here’s an example of searching for operators using the keyword Tāmaki
. Notice how the extra spaces at the ends of the ' '
are ignored:
281-activity-operator-system> SEARCH_OPERATORS 'Tāmaki '
There are 2 matching operators found:
* Volcano Bungee Jump ('VBJ-AKL-002' located in 'Auckland | Tāmaki Makaurau')
* West Auckland Camel Treks ('WACT-AKL-001' located in 'Auckland | Tāmaki Makaurau')
If the keyword is found in either the operator name or location, then the operator should be printed along with the header that summarises how many operators were found (as discussed earlier), not the total number of operators in the system (unless they all match the keyword in some way).
Once you have implemented all the logic for Task 1, you should see all your test cases pass:
Or, from the terminal view:
As explained at the end of this document, we only provide you with half the test cases from each task. So, even though you have passed all 15 test cases, there are 15 more hidden test cases that we will add to these for Task 1. So, make sure you have implemented all the logic, and read the requirements carefully.
Task 2 (Checkpoint #2) [Worth 5%]
Now that the system supports creating operators, it is time to manage those operators. This will include creating activities for an operator, viewing an operator’s activities, and searching for activities in the system.
Go to the top of the MainTest.java
file, and uncomment the following line:
@RunWith(Suite.class)
@SuiteClasses({
MainTest.Task1.class,
// MainTest.Task2.class, // <-- uncomment this line to get started on Task 2
// MainTest.Task3.class,
// MainTest.YourTests.class,
})
You will see 15 new test cases, all of which are failing. Follow the same process as Task 1 to get them all passing, and carefully read the requirements below so you consider scenarios where test cases are not provided.
Creating activities (CREATE_ACTIVITY
)
The CREATE_ACTIVITY
command creates a new activity for the specified operator ID. The operator ID is the unique identifier that was generated when the operator was created. If any invalid input is provided, an error message should be printed (details below).
When a new activity is created, it should be added to the system. The arguments have the following requirements:
<ACTIVITY_NAME>
- Must be at least 3 characters long (surrounding spaces are not counted).
- Similar to operator names, the activity name can be a single word (in which case the single quotes are optional), or multiple words (in which case the single quotes are required). Again, you don’t need to worry about this, as the code provided already handles this and gives you the full name regardless.
- You don’t need to worry about an operator having multiple activities with the same name, we will not test for this.
<ACTIVITY_TYPE>
- The list of acceptable activity types is provided in the
ActivityType
enum in theTypes.java
file. - The user can type in the activity type in any combination of upper and lower case letters. For example, the user can type in
Adventure
,adventure
,ADVENTURE
, oraDvEnTuRe
for the activity typeActivityType.ADVENTURE
. - If the user provides an invalid activity type, then the default value should be
ActivityType.OTHER
. There is no error generated for this. - Have a look at the
fromString
method in theActivityType
enum to see how you can convert a string to anActivityType
enum value. This will be useful. For example,ActivityType.fromString("adventure")
will returnActivityType.ADVENTURE
.
<OPERATOR_ID>
- The operator ID is the unique identifier that was generated when the operator was created.
When a successful activity is created, a success message should be printed:
281-activity-operator-system> CREATE_ACTIVITY 'Bethells Beach Camel Trek' Adventure 'WACT-AKL-001'
Successfully created activity 'Bethells Beach Camel Trek' ('WACT-AKL-001-001': 'Adventure') for 'West Auckland Camel Treks'.
This success message includes the activity name, the activity ID, the created activity type, and the operator name. The format of this message is very strict. Make sure you check for an appropriate message template in MessageCli
to help you.
Notice that the activity ID is generated as follows:
<OPERATOR_ID>-<THREE_DIGIT_NUMBER>
The THREE_DIGIT_NUMBER
is a three-digit number starting from 001
and incrementing by 1
for each new activity for the same operator. If the activity is the first activity for the operator, then the number should be 001
(even if there are other activities for other operators in the system). If the activity is the second activity for the operator, then the number should be 002
, and so on.
If the activity name is less than 3 characters long, then an error message should be printed and the activity should not be created:
281-activity-operator-system> CREATE_ACTIVITY Hi ADVENTURE 'WACT-AKL-001'
Activity not created: 'Hi' is not a valid activity name.
If the operator ID does not exist, then an error message should be printed and the activity should not be created:
281-activity-operator-system> CREATE_ACTIVITY 'Bethells Beach Camel Trek' ADVENTURE 'WACT-AKL-789'
Activity not created: 'WACT-AKL-789' is an invalid operator ID.
Viewing activities (VIEW_ACTIVITIES
)
The VIEW_ACTIVITIES
command views all activities for the specified operator ID. If any invalid input is provided, an error message should be printed (details below).
If the operator ID does not exist, then an error message should be printed:
281-activity-operator-system> VIEW_ACTIVITIES UHOH-AKL-789
Operator not found: 'UHOH-AKL-789' is an invalid operator ID.
If the operator has no activities, then the following message should be printed:
281-activity-operator-system> VIEW_ACTIVITIES 'BSSJ-DUD-002'
There are no matching activities found.
Otherwise, the activities should be printed with a header that summarises how many activities the operator has, followed by the details of each activity.
For example, if the operator has one activity:
There is 1 matching activity found:
* Stars or Spaceships?: [NUW-NSN-001-001/Scenic] offered by Nelson UFO Watching
If the operator has two or more activities:
There are 2 matching activities found:
* Jumping Through Political Loopholes: [PBJ-WLG-001-001/Culture] offered by Parliament Bungee Jump
* Legends of the Lost Snow: [MMSR-TRG-001-001/Culture] offered by Mount Maunganui Ski Resort
In all of the above cases, take note of the verb, the word “activity” (singular or plural), and the colon or period at the end of the sentence. You can use the MessageCli.ACTIVITIES_FOUND
message template to help you with this.
Searching for activities (SEARCH_ACTIVITIES
)
The SEARCH_ACTIVITIES
command searches for activities by keyword in the activity name or type or operator location. If any invalid input is provided, an error message should be printed.
If the keyword specified is *
, it should print all the activities in the system. For example, if there are two activities in the system:
281-activity-operator-system> SEARCH_ACTIVITIES '*'
There are 2 matching activities found:
* Bethells Beach Camel Trek: [WACT-AKL-001-001/Adventure] offered by West Auckland Camel Treks
* Lava Lookout Walk: [VBJ-AKL-002-001/Scenic] offered by Volcano Bungee Jump
If a keyword other than *
is specified, then the keyword should be searched for in:
- The activity name (case insensitive),
- The activity type (case insensitive),
- The operator location (case insensitive, te reo Māori, English, or abbreviation).
Other than macrons for te reo Māori words, you do not need to worry about any other special characters. The keyword might be a substring of the activity name, type, or operator location.
Here is an example of searching for activities using the keyword Whakatu
:
281-activity-operator-system> SEARCH_ACTIVITIES Whakatu
There are 2 matching activities found:
* Stars or Spaceships?: [NUW-NSN-001-001/Scenic] offered by Nelson UFO Watching
* Meteorites & Meat Pies: [NUW-NSN-001-002/Food] offered by Nelson UFO Watching
The wording for the header should be consistent with the previous examples, depending on the number of activities found. This includes the verb, the word “activity” (singular or plural), and the colon or period at the end of the sentence.
Task 3 (Checkpoint #2) [Worth 7%]
Now that the system supports creating activities, it is time to manage those activities. This will include adding reviews for activities, viewing reviews for activities, and performing other actions related to reviews.
Go to the top of the MainTest.java
file, and uncomment the following line:
@RunWith(Suite.class)
@SuiteClasses({
MainTest.Task1.class,
MainTest.Task2.class,
// MainTest.Task3.class, // <-- uncomment this line to get started on Task 3
// MainTest.YourTests.class,
})
You will see 20 new test cases, all of which are failing. Follow the same process as Task 1 and Task 2 to get them all passing, and carefully read the requirements below so you consider scenarios where test cases are not provided.
Reviews for activities
The system supports three types of reviews for activities. Each review type has different requirements and actions associated with it:
-
Public reviews are reviews that are visible to everyone. They are added by customers who have experienced the activity. They include the reviewer’s name, rating, and comments. A reviewer might want to keep it anonymous, in which case the reviewer’s name will remain anonymous when printed. Administrators can endorse public reviews, which means they agree with the review and want to highlight it. If a public review is endorsed, it should be marked as such when printed.
-
Private reviews are reviews that are only visible to the operator. They are added by customers who have experienced the activity and generally use it as a way to provide feedback to the operator. They include the reviewer’s name, email, rating, and comments. The customer can also request a follow-up response from the operator, where a response is actioned to resolve the review. If the customer does not request a follow-up response, then the review is marked as resolved when printed (with the response “-“ used). If the customer requests a follow-up response, then the response should be printed as provided by the operator. If the operator has not yet responded, but the customer has requested a follow-up response, then the review will also say
Need to email 'felicia@email.com' for follow-up.
There will be examples below. -
Expert reviews are reviews that are added by experts in the field. They are visible to everyone. They include the reviewer’s name, rating, comments, and whether they recommend the activity. Experts can also upload images to support their review.
For boolean values, you can assume that the user will always type in y
or n
exactly. You do not need to worry about any other variations (whether different casing or spelling).
When any review is added, it should be added to the system tied to a particular activity. The activity ID is the unique identifier that was generated when the activity was created. If any invalid input is provided, an error message should be printed (details below).
When a review is added, a success message should be printed:
281-activity-operator-system> ADD_PUBLIC_REVIEW WACT-AKL-001-001
Reviewer name: Alice
Anonymous? (y/n): n
Rating (1-5): 5
Review text: Nice
Public review 'WACT-AKL-001-001-R1' added successfully for activity 'Bethells Beach Camel Trek'.
You will notice that adding reviews only requires the activity ID as an argument. The rest of the information is prompted for after the command is executed. This is handled for you, and you will receive expected components in the String[] options
parameter in the OperatorManagementSystem.addPublicReview()
method (or the equivalent method for private and expert reviews).
For the example above, the options
array would contain the following:
options[0] = "Alice"
options[1] = "n"
options[2] = "5"
options[3] = "Nice"
To see this in your code, you can easily print each value out in your addPublicReview()
public void addPublicReview(String activityId, String[] options) {
for (int i = 0; i < options.length; i++) {
String value = options[i];
System.out.println("option " + i + " = " + value);
}
}
When a review is added, it should be added to the system. The review ID is generated as follows:
<ACTIVITY_ID>-R<REVIEW_NUMBER>
The REVIEW_NUMBER
is a number starting from 1
and incrementing by 1
for each new review for the same activity. If the review is the first review for the activity, then the number should be 1
(even if there are other reviews for other activities in the system). If the review is the second review for the activity, then the number should be 2
, and so on. In the example above, the review ID would be WACT-AKL-001-001-R1
.
If an invalid activity ID is provided, then an error message should be printed and the review should not be added:
281-activity-operator-system> ADD_PUBLIC_REVIEW WACT-AKL-001-999
Reviewer name: Alice
Anonymous? (y/n): n
Rating (1-5): 5
Review text: Nice
Review not added: 'WACT-AKL-001-999' is an invalid activity ID.
Notice how it still asks for all the options, even though the activity ID is invalid. This is because determining whether the activity ID is valid or not is done by you after the options are collected and passed to you.
If the rating is not between 1 and 5, it needs to be quietly adjusted to the nearest valid rating. For example, if the rating is 0
, it should be adjusted to 1
, and if the rating is 6
, it should be adjusted to 5
. You can then continue with creating the review as normal.
Displaying reviews
The system supports viewing reviews for activities. This includes viewing public, private, and expert reviews.
The DISPLAY_REVIEWS
command displays all reviews for the specified activity ID. If any invalid input is provided, an error message should be printed:
281-activity-operator-system> DISPLAY_REVIEWS WACT-AKL-001-999
Activity not found: 'WACT-AKL-001-999' is an invalid activity ID.
If the activity has no reviews, then the following message should be printed:
281-activity-operator-system> DISPLAY_REVIEWS ARWR-CHC-002-003
There are no reviews for activity 'River Rush'.
Otherwise, the reviews should be printed with a header that summarises how many reviews the activity has.
For example, if the activity has one review, the header should be:
281-activity-operator-system> DISPLAY_REVIEWS TUW-TUO-002-002
There is 1 review for activity 'Close Encounters of the Lake'.
...
If the activity has two or more reviews, the header should be:
281-activity-operator-system> DISPLAY_REVIEWS TUW-TUO-002-002
There are 2 reviews for activity 'Close Encounters of the Lake'.
...
In all the cases above, take note of the verb, the word “review” (singular or plural).
When displaying reviews, you will need to print the information related to the review. Have a look at the REVIEW_ENTRY_xxx
message templates in the MessageCli
class to help you with this. You should be making use of these message templates to print the reviews in the correct format. It actually doesn’t matter on the order of the reviews, or the order of the lines of bits of information within the review. As long as the correct information is there, and it is in the correct format (based on those templates), then the test cases will pass.
Below is a full example of how a public review should be displayed based on how the review is added. First, the review is added, not anonymously. Then, the review is displayed. It hasn’t been endorsed yet, so it doesn’t say that it has been endorsed when printed:
281-activity-operator-system> ADD_PUBLIC_REVIEW SSB-TRG-002-001
Reviewer name: Alice
Anonymous? (y/n): n
Rating (1-5): 3
Review text: Could be better
Public review 'SSB-TRG-002-001-R1' added successfully for activity 'Nemos Playground'.
281-activity-operator-system> DISPLAY_REVIEWS SSB-TRG-002-001
There is 1 review for activity 'Nemos Playground'.
* [3/5] Public review (SSB-TRG-002-001-R1) by 'Alice'
"Could be better"
If however the review is added anonymously, then the review should be displayed as such when printed:
281-activity-operator-system> ADD_PUBLIC_REVIEW SSB-TRG-002-001
Reviewer name: Alice
Anonymous? (y/n): y
Rating (1-5): 3
Review text: Could be better
Public review 'SSB-TRG-002-001-R1' added successfully for activity 'Nemos Playground'.
281-activity-operator-system> DISPLAY_REVIEWS SSB-TRG-002-001
There is 1 review for activity 'Nemos Playground'.
* [3/5] Public review (SSB-TRG-002-001-R1) by 'Anonymous'
"Could be better"
Below is a full example of how a private review should be displayed based on how the review is added. First, the review is added, and the customer says that a follow-up response is needed. Then, the review is displayed before the operator has responded/resolved it:
281-activity-operator-system> ADD_PRIVATE_REVIEW TUW-TUO-002-002
Reviewer name: Felicia
Email: felicia@email.com
Rating (1-5): 1
Review text: I'm so disappointed!
Follow-up requested? (y/n): y
Private review 'TUW-TUO-002-002-R1' added successfully for activity 'Close Encounters of the Lake'.
281-activity-operator-system> DISPLAY_REVIEWS TUW-TUO-002-002
There is 1 review for activity 'Close Encounters of the Lake'.
* [1/5] Private review (TUW-TUO-002-002-R1) by 'Felicia'
"I'm so disappointed!"
Need to email 'felicia@email.com' for follow-up.
Should a private review be created without requiring a follow-up response, then the review is immediately marked as resolved when printed (with the response “-“ used). Notice that there’s no longer the Need to email ...
line:
281-activity-operator-system> ADD_PRIVATE_REVIEW TUW-TUO-002-002
Reviewer name: Felicia
Email: felicia@email.com
Rating (1-5): 5
Review text: Thank you for the great experience!
Follow-up requested? (y/n): n
Private review 'TUW-TUO-002-002-R1' added successfully for activity 'Close Encounters of the Lake'.
281-activity-operator-system> DISPLAY_REVIEWS TUW-TUO-002-002
There is 1 review for activity 'Close Encounters of the Lake'.
* [5/5] Private review (TUW-TUO-002-002-R1) by 'Felicia'
"Thank you for the great experience!"
Resolved: "-"
Below is a full example of how an expert review should be displayed based on how the review is added. First, the review is added, and the expert recommends the activity. Then, the review is displayed:
281-activity-operator-system> ADD_EXPERT_REVIEW ARWR-CHC-002-003
Reviewer name: Eve
Rating (1-5): 4
Review text: Lots of rapids, very scary, watch out!
Would recommend? (y/n): y
Expert review 'ARWR-CHC-002-003-R1' added successfully for activity 'River Rush'.
281-activity-operator-system> DISPLAY_REVIEWS ARWR-CHC-002-003
There is 1 review for activity 'River Rush'.
* [4/5] Expert review (ARWR-CHC-002-003-R1) by 'Eve'
"Lots of rapids, very scary, watch out!"
Recommended by experts.
If the expert does not recommend the activity, then the Recommended by experts.
line should not be printed.
Endorsing public reviews
The system supports endorsing public reviews. This is done by administrators who agree with the review and want to highlight it.
The ENDORSE_REVIEW
command endorses a public review. The review ID is the unique identifier that was generated when the review was created. If any invalid input is provided, an error message should be printed:
Review not found: 'ARWR-CHC-002-003-R2' is an invalid review ID.
Endorsing is only allowed on public reviews. If a private or expert review is provided, then an error message should be printed:
Review not endorsed: 'ARWR-CHC-002-003-R1' is not a public review.
If the review is successfully endorsed, a success message should be printed:
Review 'SSB-TRG-002-001-R1' endorsed successfully.
Then, when printed, the review should be marked as endorsed:
281-activity-operator-system> DISPLAY_REVIEWS SSB-TRG-002-001
There is 1 review for activity 'Nemos Playground'.
* [3/5] Public review (SSB-TRG-002-001-R1) by 'Alice'
"Could be better"
Endorsed by admin.
Resolving private reviews
The system supports resolving private reviews. This is done by operators who have responded to the review and resolved the issue.
There are the equivalent error checks and messages for resolving private reviews as there are for endorsing public reviews:
- Checking if the review ID is valid.
- Checking that the resolving only happens for private reviews.
- Printing the success message when the review is resolved.
Below is an example of resolving a private review. First, the review is added (with the customer requesting a follow-up response). Then, the review is displayed (before being resolved), then the review is resolved, then the review is displayed (after being resolved):
281-activity-operator-system> ADD_PRIVATE_REVIEW TUW-TUO-002-002
Reviewer name: Felicia
Email: felicia@email.com
Rating (1-5): 1
Review text: I'm so disappointed!
Follow-up requested? (y/n): y
Private review 'TUW-TUO-002-002-R1' added successfully for activity 'Close Encounters of the Lake'.
281-activity-operator-system> DISPLAY_REVIEWS TUW-TUO-002-002
There is 1 review for activity 'Close Encounters of the Lake'.
* [1/5] Private review (TUW-TUO-002-002-R1) by 'Felicia'
"I'm so disappointed!"
Need to email 'felicia@email.com' for follow-up.
281-activity-operator-system> RESOLVE_REVIEW TUW-TUO-002-002-R1 'So sorry to hear that!'
Review 'TUW-TUO-002-002-R1' resolved successfully.
281-activity-operator-system> DISPLAY_REVIEWS TUW-TUO-002-002
There is 1 review for activity 'Close Encounters of the Lake'.
* [1/5] Private review (TUW-TUO-002-002-R1) by 'Felicia'
"I'm so disappointed!"
Resolved: "So sorry to hear that!"
Uploading images for expert reviews
The system supports uploading images for expert reviews. This is done by experts who want to provide visual support for their review.
There are the equivalent error checks and messages for uploading images for expert reviews as there are for endorsing public reviews and resolving private reviews:
- Checking if the review ID is valid.
- Checking that the image is only uploaded for expert reviews.
- Printing the success message when the image is uploaded.
Below is an example of uploading an image for an expert review. First, the review is added, the review is displayed (before the image is uploaded), then the image is uploaded, then the review is displayed (after the image is uploaded), then another image is uploaded, then the review is displayed (after the second image is uploaded):
281-activity-operator-system> ADD_EXPERT_REVIEW ARWR-CHC-002-003
Reviewer name: Eve
Rating (1-5): 4
Review text: Lots of rapids, very scary, watch out!
Would recommend? (y/n): y
Expert review 'ARWR-CHC-002-003-R1' added successfully for activity 'River Rush'.
281-activity-operator-system> DISPLAY_REVIEWS ARWR-CHC-002-003
There is 1 review for activity 'River Rush'.
* [4/5] Expert review (ARWR-CHC-002-003-R1) by 'Eve'
"Lots of rapids, very scary, watch out!"
Recommended by experts.
281-activity-operator-system> UPLOAD_REVIEW_IMAGE ARWR-CHC-002-003-R1 image1.jpg
Image 'image1.jpg' uploaded successfully for review 'ARWR-CHC-002-003-R1'.
281-activity-operator-system> DISPLAY_REVIEWS ARWR-CHC-002-003
There is 1 review for activity 'River Rush'.
* [4/5] Expert review (ARWR-CHC-002-003-R1) by 'Eve'
"Lots of rapids, very scary, watch out!"
Recommended by experts.
Images: [image1.jpg]
281-activity-operator-system> UPLOAD_REVIEW_IMAGE ARWR-CHC-002-003-R1 image2.jpg
Image 'image2.jpg' uploaded successfully for review 'ARWR-CHC-002-003-R1'.
281-activity-operator-system> DISPLAY_REVIEWS ARWR-CHC-002-003
There is 1 review for activity 'River Rush'.
* [4/5] Expert review (ARWR-CHC-002-003-R1) by 'Eve'
"Lots of rapids, very scary, watch out!"
Recommended by experts.
Images: [image1.jpg,image2.jpg]
Displaying top activities
The DISPLAY_TOP_ACTIVITIES
command displays the top activity in each location based on the average rating of the public and expert reviews (private reviews are not included in this calculation).
It prints a header for each location, followed by the top activity in that location (if there is one). You don’t have to worry about handling ties in the average rating for the same location.
Below is the case when there are no reviewed activities in the system, despite there being activities in the system:
281-activity-operator-system> DISPLAY_TOP_ACTIVITIES
No reviewed activities found in Auckland | Tāmaki Makaurau.
No reviewed activities found in Hamilton | Kirikiriroa.
No reviewed activities found in Tauranga.
No reviewed activities found in Taupo | Taupō-nui-a-Tia.
No reviewed activities found in Wellington | Te Whanganui-a-Tara.
No reviewed activities found in Nelson | Whakatu.
No reviewed activities found in Christchurch | Ōtautahi.
No reviewed activities found in Dunedin | Ōtepoti.
If a location doesn’t have any activities, or if it doesn’t have any reviewed activities, then the message is the same: No reviewed activities found in ...
.
Below is the case when there one reviewed activity:
281-activity-operator-system> ADD_PUBLIC_REVIEW SSB-TRG-002-001
Reviewer name: Alice
Anonymous? (y/n): n
Rating (1-5): 3
Review text: Could be better
Public review 'SSB-TRG-002-001-R1' added successfully for activity 'Nemos Playground'.
281-activity-operator-system> DISPLAY_TOP_ACTIVITIES
No reviewed activities found in Auckland | Tāmaki Makaurau.
No reviewed activities found in Hamilton | Kirikiriroa.
Top reviewed activity in Tauranga is 'Nemos Playground', with an average rating of 3
No reviewed activities found in Taupo | Taupō-nui-a-Tia.
No reviewed activities found in Wellington | Te Whanganui-a-Tara.
No reviewed activities found in Nelson | Whakatu.
No reviewed activities found in Christchurch | Ōtautahi.
No reviewed activities found in Dunedin | Ōtepoti.
Your Tests (optional)
You can add your own test cases in the MainTest.YourTests
class, in a similar way to how the test cases are written in the MainTest.Task1
, MainTest.Task2
, and MainTest.Task3
classes.
These won’t be marked (in fact, they will be ignored during marking), but they are useful for you to test your code. Furthermore, knowing how to write test cases (and getting into the good habit of doing so) will help you write better code and gets you into the problem-solving mindset, which is extremely useful for your future career as an engineer.
Marking Scheme
Item | Value | Due | Note |
---|---|---|---|
Task 1 | 6% | Checkpoint #1 | ❶ |
Task 2 | 4% | Checkpoint #2 | ❶ |
Task 3 | 8% | Checkpoint #2 | ❶ |
OO Design | 2% | Checkpoint #2 | ❷ |
Code Style | 2% | Checkpoint #2 | ❸ ❹ |
Git Etiquette | 3% | Checkpoint #2 | ❸ ❺ |
Total | 25% |
Important Notes: In order to get these marks, you need to make a genuine attempt on the assignment:
❶ We have provided you with half of the test cases used for marking each of the tasks. However, you should not hard-code any logic in order to pass these given test cases as we will change them to have slightly different values. Such hard-coded test cases will naturally fail and get you no marks. See the section below “Does passing test cases mean I have completed the assignment?” for more information.
❷ The classes you create must actually be used, and not be “dummy classes”. You need to create and use at least one abstract class, and at least three (sub)classes that extend a class that you have created. You also need to pass at least 20% of test cases (in Task 2 and 3) in order to get the marks for this item (in other words, these classes need to actually contribute to the functionality of the program).
❸ If you did not pass at least 20% of the total test cases, you will get zero marks for this component. You will not get these marks if you only cloned the repo and pretty much only “submit” the code we provided you.
❹ This is checked and marked at the end of Checkpoint #2, but it’s recommended you clean up your code as you go along rather than at the very end. Make use of the Code Style tool frequently, and learn from it. View required Code Style conventions here.
❺ Although this is marked at the end of Checkpoint #2, there is no opportunity to “fix” past mistakes since you can’t tamper/change your Git history. With that said, we will provide some leniency so you can still get full marks if you made the odd mistake and not too often. We will share reports throughout the assignment so you can see how you’re tracking with this, so you can view any mistakes you might have made and not repeat them. View required Git Etiquette conventions here.
Important Instructions
Please read the following information carefully before you begin your assignment.
Does passing test cases mean I have completed the assignment?
You will see that we provide some test cases to help guide you. In most cases, these test cases are not comprehensive. They are not designed to test all possible inputs. They are designed to help you get started.
What’s more, you should make sure you do not hard code your logic to pass the specific test cases we provide. You should write your code in a way that it will work for any input.
For example, if we provide a test case that checks if the method checkIfIsEven
returns true
when the input is 2
:
@Test
public void testIsEven() {
checkIfIsEven(2);
assertContains("true");
}
You should not write your code like this:
public void checkIfIsEven(int number) {
if (number == 2) {
System.out.println("true");
} else {
System.out.println("false");
}
}
This is because in the actual marking, we will use different values for the test cases. For example, we may use the test case:
@Test
public void testIsEven() {
checkIfIsEven(280);
assertContains("true");
}
If you have hard coded your logic to pass the test case checkIfIsEven(2)
, then your code will not pass the test case checkIfIsEven(280)
and you will therefore not get the marks for that test case.
Code Style Tool
Note: You should have received an email (from “GradeStyle”) with your personal access token. If you didn’t, it’s most likely because you have not associated your GitHub username with your identity when you accepted one of the assignments. In that case, please email Nasser and let him know what GitHub username you used for Hello GitHub.
There will be marks allocated to your code style. Please see the Java Conventions and Best Practices page for more information on code style relevant to this course.
To provide you with feedback on your code style, we will be using a tool we have developed. This tool will check your code for common code style issues, and email you a report on your code style. This email report will let you know what you need to fix.
After the assignment deadline has passed, we will use the same tool to mark code style for your submission.
To benefit from this tool, you need to have your commits pushed to the remote GitHub repository. The tool will extract the code from there, analyse your code, and email you the report.
To use the tool, a codestyle.config
file is needed in to the root directory (where the pom.xml
file is). Inside it, you should include two things:
email: "student@aucklanduni.ac.nz"
accessToken: "token-that-was-emailed-to-you"
Note: You will notice that the codestyle.config
file is added to the .gitignore
file. It is good practice to never track credentials in a repository.
The access token will be emailed to you, and is unique for you.
In the assignment repo, you will find a codestyle_SAMPLE.config
for your convenience. You can copy-and-paste it, change the name (to codestyle.config
), and fill the email
and accessToken
values with your credentials.
To invoke the actual tool, you will run:
./mvnw clean compile exec:java@style
for Unix/Mac OS or .\mvnw.cmd clean compile exec:java@style
for Windows
You will receive an email with the feedback.
Some notes about running the tool:
- We limit the number of times you can run the tool (currently once per 30 minutes). With a large number of students, we cannot afford to run the tool on every commit. To make the most of the tool, we therefore recommend you start the assignment early on, and run the tool frequently. If you leave it too late, you will not be able to run the tool as many times as you might like.
- The tool runs on code you have pushed to the remote repository. It does not run on your local repository. Therefore, if you want to generate a new report on your latest code, you will need to do a
git commit
and agit push
to the remote repository. The tool will decline to run if you have not pushed your latest code to the remote repository. - Some of the code style aspects might require your code to compile. So, make sure you have a working code before running the tool. If you have a compilation error, the tool will not run (and it will still count as one of your runs). So, remember to do a
./mvnw clean compile
for Unix/Mac OS or.\mvnw.cmd clean compile
for Windows (or include theclean compile
in yourexec:java@style
command) before running the tool. - The tool will use the GitHub username that was registered in the first Hello GitHub assignment you completed. If you did not associate your name with a GitHub username, you would not have received an email with the access token. If you have associated your GitHub username, but you did not receive an email with the access token, please contact us.
- If you are using a different GitHub username (compared to the one you used in the Hello GitHub assignment), then the tool will not be able to find your repo, and therefore will not be able to run. You need to be using the same GitHub account you registered earlier.
Here’s an example of running the Code Style tool.
Please note: Although the video is from a previous semester, the process is still pretty much the same. Follow the process to use the code style tool, but ignore differences of anything else you notice (like the code style table or weighing of components etc). Instead refer to this year’s handout for that specific information. This video is only to explain running the code style tool.
Academic Honesty
You MUST use the GitHub repository created in the course’s GitHub Organization.
NEVER use your own repository, or copy your code to another repository to work from.
Doing so means your assignment will not be accepted for marking.
- The work done on this assignment must be your own work. Think carefully about any problems you come across, and try to solve them yourself before you ask anyone for help (struggling a little with it will help you learn, especially if you end up solving it). If you still need help, check on Ed Discussion (if it is about interpreting the assignment specifications) or ask in the Drop-In help clinics (if you would like more personal help with Java). Under no circumstances should you take or pay for an electronic copy of someone else’s work.
- All submitted code will be checked using software similarity tools. Submissions with suspicious similarity will result in action taken following the University’s Guidelines for Academic Misconduct, and forwarded to the Disciplinary Committee.
- Penalties for copying will be severe. In most cases, this is ZERO for the assignment in question. To avoid being caught copying, don’t do it. Please note the same penalty applies to both the person who copied and the person who was copied from.
- The University has recently taken a much stricter stance on academic misconduct and streamlined the process for dealing with it. In a nutshell, it takes a non-negotiation approach — no longer requiring a thorough investigation. You will therefore simply be informed, and find the penalty applied to the assignment. This is why it’s important to not only copy from others, but also not to show your work to others.
- You must not attempt to tamper with your GitHub commits. This means all commits must be preserved, including the one that is automatically created for you. Disregarding this will result in major penalties. See the section on Tampering with your Git commit history for more information.
- To ensure you are not identified for potential plagiarism, you should follow these points:
- Always do individual assignments by yourself.
- Never show or give another person your code.
- Make sure you are doing plenty of commits and pushes to GitHub. This will help you to track your progress and also to ensure that you have a backup of your work. It also makes it easier for us to see that you have not been copying from someone else.
- Do not share your GitHub account with anyone.
- Never put your code in a public place (e.g. Reddit, public GitHub repository, forums, your website, etc).
- Never leave your computer unattended. You are responsible for the security of your account.
- Ensure that you always remove your USB flash drive from any public computer before you log off from it.
- Frequently commit your code to GitHub. This provides a track record of your work and will allow the teaching team to follow your footsteps as you complete your assignment. If you do not frequently commit your code, it will look suspicious.
Git Etiquette
All the take-home programming assignments will require you to make good use of Git and GitHub.
There are marks associated with Git usage. But you could stand to lose more marks if there’s evidence of tampering with your Git commit history.
Make sure you are familiar with the expectations outlined in the Git Etiquette page.
Can I use Copilot and ChatGPT for this assignment?
As you progress through the course, mastering the underlying OOP concepts is essential. Throughout this process, Generative AI tools like Copilot and ChatGPT can be beneficial. They help generate code snippets and assist with programming tasks.
We do not frown upon using these tools. In fact, part of this course includes a task specifically designed to enhance your skills in using these tools critically.
You will notice how these tools can help you write code faster and more efficiently. They boost your productivity.
While these AI tools are valuable, relying too heavily on them can impede your learning. If you depend too much on their output, you may miss out on the opportunity to develop your programming skills. Our goal is to not only acquaint you with tools such as Copilot and ChatGPT but more importantly, to solidify your understanding of core programming concepts for effective application.
This course includes invigilated and practical tests that run without the aid of AI tools (or any other resource for that matter), to ensure you can independently apply what you’ve learned. Over-dependence on AI might make these tests more difficult and stressful.
The real benefit of Generative AI tools lies in understanding the logic of the code they produce, not just in using the code. This video below illustrates the importance of comprehending AI-generated code:
As highlighted in this video, Generative AI is great at filling in the small gaps in your knowledge. Just make sure you aren’t relying on them to fill in the big gaps in your knowledge—because they won’t.
Final Submission on GitHub
In this course, all your programming assignments will be automatically extracted from GitHub. There will be no separate submission on Canvas.
The following instructions are very important. Make sure you double check everything, otherwise your assignment will not be marked:
- You must use the GitHub repository created in the course’s GitHub Organization.
- It is not enough that you were doing
git add
andgit commit
commands! This only tracks the changes on your local machine! - Unfortunately, it is not a good look for us to hack into your machine in order to take your local repo (even for the good intentions of marking it). Therefore, it is absolutely important you have (correctly) executed a
git push
so that all your commits and changes are sent to the remote GitHub repository. - To make sure you submitted your code, simply go to https://github.com and check the “commits” tab of your assignment repository. Do you see the latest changes there? If so, you are good. If no, something went wrong and you need to sort it out so that it appears in the remote repository before the deadline.
- As an extra (strongly recommended) precaution, you should clone your GitHub remote repo to your machine (e.g., to a temporary folder), and check it works correctly by compiling it and running it all over again (in a “fresh” directory). This is to protect you if you didn’t correctly include all the changed files (in which case, the assignment runs correctly on your local repo but you didn’t push everything to the remote repo).
- If you want to submit late, review the Late Submissions section to understand how it works with your GitHub repository.
Avoid getting zero marks…
It is your responsibility to make sure all your changes are correctly visible on your remote GitHub repository. Read all the submission instructions carefully. It is not enough that you did commits and they appear in your local repository. Even if you pushed them to the remote repository later on (with timestamps before the deadline), it is not enough! The changes must appear in the remote repository before the deadline to be considered for marking. No exceptions.
You must double check that you have uploaded the correct code for marking! There will be no exceptions if you accidentally submitted the wrong files, regardless of whether you can prove you did not modify them since the deadline. No exceptions. Get into the habit of downloading them again, and double-checking all is there.
Late Submissions
Please also be careful with your final commits. We don’t recommend you risk making any changes in the final minutes (unless your intention is to submit late). For fairness, we have to penalise any late submissions, even if it’s just a minute late. This is why we have a 30-minute late penalty category (so that 1-30 minutes late is only 1% penalty). You get to decide if it’s worth the risk to work on your assignment up until the deadline.
Late submissions are based on the GitHub server timestamp
If you intend to submit before the deadline (and not utilise the late penalty allowance), then make sure you have pushed all your commits to your remote GitHub repository before the deadline.
To determine if you have a late submission, we use the GitHub server timestamp. If the timestamp is after the deadline, then it is late.
Please note: We do NOT use the commit timestamps. This is because the commit timestamps are based on your local machine, and can be easily changed. We will therefore only use the GitHub server timestamp to determine if your submission is late or not. No exceptions. This is why it’s important for you to make sure you push your commits to the remote repository before the deadline.
If you would like more time and submit late (with penalties), then simply keep working on your assignment and make sure you push the latest commits to the remote repository before the following deadlines. By looking at the last push timestamp, we will determine how late your submission is.
After the 48-hour late period passes, your repository will become read-only — and you will not be able to push to it. You will get an error message when you attempt to push, that you do not have access to it. This is to ensure that we can start marking the assignments and provide feedback to you in a timely manner.
Remember: your commits need to be pushed and in the remote repository within the 48 hours, not only timestamped!.
Late submission penalties:
Late by † | Penalty |
---|---|
1 to 30 minutes late | 1% penalty |
Up to 3 hours late | 2% penalty |
Up to 12 hours late | 8% penalty |
Up to 24 hours late | 15% penalty |
Up to 36 hours late | 20% penalty |
Up to 48 hours late | 30% penalty |
More than 48 hours late | 100% penalty ‡ |
† Based on GitHub server timestamp of last push.
‡ At 48 hours late, your GitHub repository becomes read-only, no more pushes possible or accepted.
It is up to you if you want to risk working on your assignment up until the deadline. If you don’t successfully push to the remote repository before the above deadlines, then it will be late. Don’t risk it.
We will stick by these clearly-specified rules. We have to be fair to everyone, and we will not be able to make exceptions to these rules due to mistakes or misunderstandings. If you are unsure about anything, please ask in Ed Discussion well ahead of the deadline.