Learning Outcomes:

  • Gain more confidence programming in Java.
  • Design an object-oriented programming (OOP) solution to a problem.
  • Apply OO design patterns



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.

Static Methods are fine, Static Fields are not (unless are final)!

If you use non-final static fields, you will be penalised

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




Table of Contents




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 debug your program you should use the debugging mode step by step as we did in class, this will drastically help you to debug and understand your program. Recall that if a test case runs for more than 10 seconds, it will fail. We have to do this check because some students might create infinite loops and the marking of the assignments will run for eternity. This poses a problem for the debugging mode as you will likely spend more than 10 seconds inspectioning the execution. To solve the issue, you have to comment line 53 of SysCliTest.java.
   // @Rule public Timeout timeout = new Timeout(10, TimeUnit.SECONDS);

Remember to uncomment that line when you finish the assignment to make sure that each test does not run for more than 10 seconds


Let’s begin!


Clone the GitHub repository

Edit

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.




Mind Game (Guess Colours)

Edit [Image generated by DALL-E 2025]

You are to implement a Mind Game, where a human player competes against an Artificial Intelligence (AI) called HAL-9000 (I hope you get the cinematic reference) in a color-based guessing game. This is a game of chance, but also a game of psychology! The AI will try to guess the player’s next colour.

Game Rules

Each round, both the human and the AI must:

  • Select a color to play.
  • Make a guess about the opponent’s chosen color.

Scoring System

  • +1 point for each correct guess.
  • +2 bonus points if:
    • The correct guess matches the Power Colour, and
    • The round number is a multiple of 3.

The Power Colour is a randomly selected color that is assigned every third round. Importantly, neither the human player nor the AI knows what the Power Colour will be before choosing their colors for that round.

The game ends after a predefined number of rounds, and the winner is the player with the highest total score.

AI Difficulty Levels

The AI’s behavior adapts based on the selected difficulty:

  • EASY: Chooses and guesses completely at random.
  • MEDIUM: Starts randomly, then switches to a strategy from round 2 onward.
  • HARD: Starts randomly, then adapts based on the win/loss history of previous rounds.





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 Game.java file (where you will need to implement the logic for the commands), the MainTest.java file (where you can add your own test cases if you wish), the Colour.java file with the definition of the colours and utility methods for selecting them randomly, and the Utils.java file for the scanner and random objects.


Edit maven wrapper (mvnw for Unix/Mac OS or mvnw.cmd for Windows)

This file will allow you to build and run this assignment. We will use a Maven wrapper to guarantee that we all have a common configuration to run and test the assignment. This is how your project will be marked. There are three main Maven commands relevant to this assignment:

  • compile (./mvnw compile for Unix/Mac OS or .\mvnw.cmd compile for Windows) Compiles the Java classes (will only compile the Java source files that have changed from the previous build). To make sure your code is compiling correctly, you should see a BUILD SUCCESS output. However, note that at the very beginning you will see a BUILD FAILURE output (more information below).

    Edit

  • test (./mvnw test for Unix/Mac OS or .\mvnw.cmd test for Windows) Compiles the Java classes and runs the test cases (will only compile the files that have changed from the previous build). You should see a BUILD SUCCESS output if the code compiles and all the tests pass. If the code doesn’t compile, or if any of the tests fail, you will see a BUILD FAILURE output.

  • clean (./mvnw clean for Unix/Mac OS or .\mvnw.cmd clean for Windows) Removes the Java binary files (*.class) by clearing the target directory into which Maven normally builds your project. Running clean periodically is useful, for example to remove those .class files referring to deleted or renamed Java source files.


You can append commands together. For example, ./mvnw clean test for Unix/Mac OS or .\mvnw.cmd clean test for Windows will execute the clean command followed by the test command. This is generally a good idea, as a clean will remove any old compiled files that may be causing problems, and you can feel more reassured that the tests are running on a clean slate.

For more information about Maven, visit the related page about development environment.

Note: The first time you run the wrapper, it might take some time (a couple of minutes) to download the required libraries and dependencies. This is normal. Subsequent runs will be much faster.

Edit src/main/java/nz/ac/auckland/se281/Main.java

This class implements the command line interface (CLI).

You should not modify this class.




Edit src/main/java/nz/ac/auckland/se281/MessageCli.java

This class declares all 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. If you are using this class, you will not need to call System.out.println anywhere in your code.

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 WELCOME_PLAYER message:

public enum MessageCli {
  // ...
  WELCOME_PLAYER("Welcome, %s!")
   // ...
}

There are two %s placeholders, which means this message expects you to pass two arguments when you want to getMessage() or printMessage() it.

For example, consider you want to construct the message "Welcome, Alice!"

If you want to get the message to print it yourself, you would do:

String message = MessageCli.WELCOME_PLAYER.getMessage("Alice");  // 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.WELCOME_PLAYER.printMessage("Alice");  // 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.




Edit src/main/java/nz/ac/auckland/se281/engine/Game.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 (just cannot add static fields, here or anywhere else - UNLESS ARE FINAL - for example final static String THIS_IS_A_CONSTANT = "Hello!").

You should not create constructors in the Game class, as they will not be used by the command line or test cases. And you don’t need to for completing the exercise. The only constructor that you can use is the default constructor public Game(){ ... } that takes in input zero arguments. If you do not need it, you can delete it, otherwise an empty constructor will be flagged as useless code by the code style tool.




Edit src/main/java/nz/ac/auckland/se281/Utils.java

This class contains static objects that are essential for completing the assignment. We’ve designed it this way to ensure that test cases can override and utilize the same static objects. However, please note that this is not an example of good design, but it is necessary for testing purposes. You are not permitted to modify this class, except for changing the random seeds to the Random objects, which will make your program pseudo-deterministic and aid in debugging. In fact, the AI may make random decisions, and you might want to reproduce a specific behavior when debugging. To change the random seed, simply insert a number here (for example 2):

public static Random randomAi = new Random(2);

You can choose any number, and you may refer to the test cases to see which numbers are being used. It is crucial that your code works with any random seed, as you will not know which seed will be used by the hidden test cases :P. Occasionally, test your game with the following code:

public static Random randomAi = new Random();

By not specifying a number, the seed will be generated randomly based on your system’s clock time.

To make your life easier and avoid confusion, two separate Random objects are used for different purposes. Additionally, a Scanner object is provided for reading user input from the console. These will be explained in more detail during the task descriptions.

Edit src/main/java/nz/ac/auckland/se281/model/Colour.java

This class defines the colours to be use in the game : Red, Green, Blue, and Yellow.

public enum Colour {
  RED,
  GREEN,
  BLUE,
  YELLOW;
}

The class also includes helper methods for selecting the colours randomly and converting strings to color values. Different Random objects are used internally, depending on whether the method is selecting the Power Colour or determining the AI’s behavior. You should not modify this class. Instead, use the provided methods as intended.




Edit src/test/java/nz/ac/auckland/se281/SysCliTest.java

This is the custom testing framework we created to allow system level testing of your assignment, you cannot change this class.




Edit src/test/java/nz/ac/auckland/se281/MainTest.java

This Java file contains the 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.

Since we want to give you freedom in designing the system following the object-oriented concepts you learned in class, these are not traditional JUnit test cases. Here, the tests do not directly invoke the code (as we don’t know how you are going to implement it, which classes and methods you will create, and so on). Instead, they test the system from the command line interface, simulating a user typing the commands with the keyboard and observing the result shown on the screen.

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.Task4.class,
        MainTest.Task5.class
        // MainTest.YourTests.class, // <-- add this if you want
})

You can easily write a test using the helper methods runCommands(), assertContains() and assertDoesNotContain(). (which are implemented by us—they are not standard JUnit).

First, with runCommands() you specify the commands (or inputs) to be executed (separated by a comma). Then, with assertContains(), you specify what is the text that you expect to see on the console after executing all the commands. For example, this test case checks that two new profiles are correctly created and added into the system:

Note that is a bit different from A1, multiple inputs are separated by a space. Also notice the space before EASY, It is needed as it is part of the same atomic command new-game EASY 4. A simple way to think about it is that every comma in runCommands , is when the user presses enter.

We have also implemented two additional methods: assertDoesNotContainAtRound(String, roundNumber) and assertContainsAtRound(String, roundNumber). These methods check whether a specific string is absent or present, respectively, in the output of a given round.

    @Test
    public void T1_02_play_start_round() throws Exception {
      runCommands(
          NEW_GAME + " EASY 5","Valerio", PLAY, "R B");
      assertContains(START_ROUND.getMessage("1", "5"));
      assertDoesNotContain(START_ROUND.getMessage("0", "5"));
      assertDoesNotContain(START_ROUND.getMessage("2", "5"));
      assertDoesNotContain(START_ROUND.getMessage("1", "0"));
    }

Sometimes it is easier to follow the test case by forcing breaklines with // at the end of each line. For example, the previous test case could be written as:

    @Test
    public void T1_02_play_start_round() throws Exception {
      runCommands(
          NEW_GAME + " EASY 5",
          "Valerio", //
          PLAY,
          "R B");
      assertContains(START_ROUND.getMessage("1", "5"));
      assertDoesNotContain(START_ROUND.getMessage("0", "5"));
      assertDoesNotContain(START_ROUND.getMessage("2", "5"));
      assertDoesNotContain(START_ROUND.getMessage("1", "0"));
    }

This way, even if your IDE attempts to auto-format the code, it will not change the way the test case is layed out. It makes it easier in the second case to see we executed two commands (NEW_GAME and PLAY), and then we checked that the output contains the lines we would expect to see as a result of those commands executing.

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 while also adding new test cases not visible to you.




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.




OOP Requirements

For this assignment, you should use the OOP concepts and the Design Patterns that we covered in class. As such, you should create appropriate classes and objects. We are giving you complete freedom on how to do the OO design. You will decide how many and which Java classes to create. However, to be sure that you are using design patterns, you are requested to do the following.

OOP requiriments

You should use the Strategy design pattern to implement the three different AI strategies (Random, AvoidLast, and LeastUsed) and allow switching among them at runtime.

Additionally, use the Factory design pattern to create AI instances based on the difficulty level selected by the player (EASY, MEDIUM, or HARD).

  • For the Strategy pattern, ensure there is a method named setStrategy, exactly as demonstrated in class.
  • For the Factory pattern, the method responsible for creating the different AI instances must be declared as static, following the approach shown in class.

AND

You should use at least 1 interface and 1 abstract class or at least 2 abstract classes or at least 2 interfaces. This includes those interfaces/abstract classes that you will need to create to implement the design patterns.


Later sections of this page will provide more information. Note that you can choose to use either “interfaces” or “abstract classes”; it is up to you. You can choose the one that you think is more suitable for your implementation! In the lectures, we discussed several times how you should choose between them. Also, you have the freedom to use additional design patterns other than the ones mentioned above. However, when marking the assignment we will only consider the implementation of Strategy and Factory as described above. It is up to you if you want to use other design patterns, it will not affect your marks.

It goes without saying that just implementing the design patterns is not sufficient. Your code has to make use of the classes that implements the design patterns. This is also true for the abstract classes/interface requirement




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 clean compile exec:java@run for Unix/Mac OS or .\mvnw.cmd clean compile exec:java@run for Windows

You should see the following output:

Edit

Now you can try some of the commands!

Note: The commands are not case sensitive. Also, you can use underscores or hypens interchangeably.

For example, the following are all correct and equivalent:

  • new-game
  • NEW_game
  • NEW_GAME
  • NeW-GaME


Try the HELP command to see the list of available commands

You can also try the EXIT command to exit the system:

281-mind-game>exit
You closed the terminal. Goodbye.
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:
[INFO] Finished at:
[INFO] ------------------------------------------------------------------------

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:

PLAY            [no args]       Play a round
SHOW_STATS      [no args]       Show the current statistics
HELP            [no args]       Print usage information
EXIT            [no args]       Exit the application

This means you can just type them in the command line, press Enter/Return, and they will be executed.

Obviously, nothing got printed since you need to implement the logic. But notice that no error was reported, since you did not add arguments (as the command expects).

If you were to use the PLAY command followed by some arguments, you would get an error message:

281-mind-game> play 1 2 hello
Error! Incorrect number of arguments. Expected 0 arguments for the "PLAY" command.
281-mind-game>

This is because the command expects no arguments, but you provided some (in this case, 1, 2, hello).




Commands with arguments

The following command require arguments:

NEW_GAME	[2 arguments]	Start a new game: NEW_GAME <DIFFICULTY_LEVEL> <NUMBER_OF_ROUNDS>
	DIFFICULTY_LEVEL: EASY | MEDIUM | HARD
	NUMBER_OF_ROUNDS: a positive integer (> 0)

This means you must provide the required number of arguments before pressing Enter/Return for them to be executed. For example, if you use the NEW_GAME command without arguments (or the wrong number of arguments) and press Enter/Return, you will get and ERROR.

281-mind-game> new-game
Error! Incorrect number of arguments. Expected 2 arguments for the "NEW_GAME" command.
281-mind-game>

To use it correctly, you need to provide the correct number of arguments:

The DIFFICULTY_LEVEL and what is the NUMBER_OF_ROUNDS to play.

281-mind-game> new-game HELLO 4
Error! Invalid difficulty level. Valid options are EASY, MEDIUM, and HARD.
281-mind-game> new-game EASY HELLO
Error! The number of rounds must be a positive integer greater than 0.

The input check of new-game is already implemented for you (you are welcome! :) ).

Obviously, nothing happens after you execute the NEW_GAME command and enter your name, since the game logic still needs to be implemented. However, notice that no error is reported because you provided the correct number of arguments, as expected by the command.

281-mind-game> new-game EASY 5
	What is your name?: Valerio
281-mind-game>







AI Strategies

Before outlining the assignment tasks, let’s review the AI strategies you will need to implement. These strategies determine how the AI selects which color to guess, based on patterns in the colors chosen by the human player. The primary goal of the AI is to win the game by making accurate predictions of the human’s color choices.

Random Strategy

This strategy selects both the AI’s own color and its guessed color randomly.
The method Colour.getRandomColourForAi() is already implemented and will help you with this.

Avoid Last Colour Strategy

This strategy selects the AI’s own color randomly. However, for the guessed color, it randomly picks a color excluding the one the human chose in the previous round.
The idea is that the human is unlikely to choose the same color two times in a row.

For example, if in the first round the player chose RED and guessed GREEN, then in the second round, the AI will guess randomly among GREEN, BLUE, and YELLOW, but not RED.

You should use the method Colour.getRandomColourExcluding(Colour exclude) (already implemented for you) to help with this.

Least Used Colour Strategy

As the name suggests, this strategy chooses the color that the human has used least often during the current game. The idea behind this strategy is that the player will eventually use underused colors and avoid repeating the same ones too frequently.

If there are multiple colors that have been used the least, the AI will choose the one that comes first in the canonical order defined in the Colour class:
RED, GREEN, BLUE, YELLOW.

For example, if the player has used RED 3 times, GREEN 2 times, and BLUE and YELLOW 0 times, the AI will guess BLUE (since it comes before YELLOW in the order).

Tasks

To guide you through the assignment, we have divided it into five tasks

For each task, we provide a number of test cases (in MainTest.java) that you can use to test your code.



Before you start we encourage you to comment out the tests of all tasks except the first one:

In MainTest.java:

@RunWith(Suite.class)
@SuiteClasses({
  MainTest.Task1.class //,
  //MainTest.Task2.class,
  //MainTest.Task3.class,
  //MainTest.Task4.class,
  //MainTest.Task5.class
})

Task 1

Initial test results

As soon as you compile and run the tests, you will notice that all 18 test cases of Task 1 fail.

With the Maven wrapper:

./mvnw clean compile test for Unix/Mac OS or .\mvnw.cmd clean compile test for Windows:

[INFO]
[ERROR] Tests run: 18, Failures: 18, Errors: 0, Skipped: 0
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------


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:


We recommend you use the Test Runner for Java extension in VS Code. It is a very useful tool that will help you run the 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.


TIP: If you have trouble 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 18 test cases were run, none of them passed, and all of them failed. In the output, you will find more details on which particular tests failed.

Hint: Look at the numbering of the test cases to guide you in the recommended order to tackle them, in this case the first test case is T1_01_welcome_message().


The important message to read is:

[INFO]
[INFO] Results:
[INFO]
[ERROR] Failures:
[ERROR]   MainTest$Task1.T1_01_welcome_message:37->SysCliTest.assertContains:154->SysCliTest.assertContains:159 The test is expecting the following output in the console, but it was not there:
	"Welcome, Valerio!"


This means that the test is expecting the output Welcome, Valerio! to be printed in the console, but it was not there. This is because you have not implemented the logic for the NEW_GAME command yet.


Let’s try something. Go to the public void newGame(Difficulty difficulty, int numRounds, String[] options) { method inside engine.Game.java, and add the following code:

  public void newGame(Difficulty difficulty, int numRounds, String[] options) {
    String namePlayer = options[0];
    MessageCli.WELCOME_PLAYER.printMessage(namePlayer);
  }

and also add import nz.ac.auckland.se281.cli.MessageCli; at the beginning of engine.Game.java.


From the terminal, we see that now only 17 of the 18 tests are failing:

[ERROR] Tests run: 18, Failures: 17, Errors: 0, Skipped: 0


We correctly print the Welcome message! For example,

281-mind-game> NEW_GAME EASY 5
	What is your name?: Valerio
Welcome, Valerio!
281-mind-game>




Task 1 will require you to implement (some of) the logic for the PLAY command and NEW_GAME command:

Welcome Message

When the player starts a new game using the NEW_GAME command, the game prompts for the player’s name. After the name is entered, a welcome message is printed.

281-mind-game> new-game EASY 5
What is your name?: Valerio
Welcome, Valerio!

Round Tracking

After the NEW_GAME command is invoked, each time the PLAY command is used, the game displays the current round number out of the total number of rounds specified when starting the game (new-game method).

281-mind-game> play
Starting round 1 of 5:
....
281-mind-game> play
Starting round 2 of 5:

Example, if the game is started with 5 rounds:

281-mind-game> play
Starting round 1 of 5:

The second time PLAY is used:

Starting round 2 of 5:

Prompting for Colors

After showing the current round, the game asks the player to enter two colors: one as their chosen color and one as their guess.

The valid colors are: RED, GREEN, BLUE, YELLOW, or their initials R, G, B, Y.

The following prompt is displayed (use the corresponding MessageCli enum):

Enter two colors (RED, GREEN, BLUE, YELLOW): your own color followed by your guess, then press Enter.

Reading Input

The player’s input must be read using the following statement:

String input = Utils.scanner.nextLine();

This allows the test framework to intercept console input during testing.

Input Validation

The player must enter exactly two valid colors.

If the input is invalid (e.g., unrecognized colors or incorrect number of inputs), the game displays an error message using MessageCli.INVALID_INPUT and repeats the prompt until valid input is provided.

hello world
Error! Invalid input. Allowed colors are RED, GREEN, BLUE, and YELLOW (you may also use R, G, B, or Y). Please try again.
Enter two colors (RED, GREEN, BLUE, YELLOW): your own color followed by your guess, then press Enter.
Red Pink
Error! Invalid input. Allowed colors are RED, GREEN, BLUE, and YELLOW (you may also use R, G, B, or Y). Please try again.
Enter two colors (RED, GREEN, BLUE, YELLOW): your own color followed by your guess, then press Enter.
RED YELLOW

Power Colour

Every 3 rounds (e.g., rounds 3, 6, 9, …) the game randomly selects a Power Colour. This color is announced using MessageCli.PRINT_POWER_COLOUR. You need to use model.Colour.getRandomColourForPowerColour() to select it.

Starting round 3 of 5:
Enter two colors (RED, GREEN, BLUE, YELLOW): your own color followed by your guess, then press Enter.
B B
The POWER COLOUR is BLUE!

Action Confirmation

When the player enters valid colors, the game prints a confirmation message showing the player’s choices.

281-mind-game> play
Starting round 2 of 5:
Enter two colors (RED, GREEN, BLUE, YELLOW): your own color followed by your guess, then press Enter.
B B
Player Valerio: chose BLUE and guessed BLUE

Once all test cases pass, and you’re confident in your implementation, you may proceed to the next task.

Task 2

In Task 2, you need to implement the EASY level of the AI and the computation of the scores.

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.Task4.class,
        // MainTest.Task5.class,
})


You will see 10 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.




  • The EASY level uses the Random strategy explained above, and it will never change the strategy for the rest of the game.

  • Same as for the player, the game also needs to print Player HAL-9000: chose BLUE and guessed RED for the AI with the played colours. The AI is called HAL-9000, and will always be HAL-9000 even in the hidden test cases.

Starting round 1 of 5:
Enter two colors (RED, GREEN, BLUE, YELLOW): your own color followed by your guess, then press Enter.
 R R
Player HAL-9000: chose BLUE and guessed RED
Player Valerio: chose RED and guessed RED
  • Then, the game has to print the PRINT_OUTCOME_ROUND message after each round, for example:
281-mind-game> play
Starting round 1 of 5:
Enter two colors (RED, GREEN, BLUE, YELLOW): your own color followed by your guess, then press Enter.
 Y R
Player HAL-9000: chose BLUE and guessed RED
Player Valerio: chose RED and guessed YELLOW
Player Valerio earned 0 point(s) this round.
Player HAL-9000 earned 1 point(s) this round.

The AI earned 1 point because it guessed RED while the player chose RED as their color for the round. The Player earned 0 point(s) as they did not correctly guess BLUE.

  • You must implement the logic for the Power Colour. Every third round (i.e., rounds 3, 6, 9, …), a color is randomly selected as the Power Colour and announced with PRINT_POWER_COLOUR. Clearly, the power colour is shown after the player and ai made their choice.

If a player (either human or AI) correctly guesses the opponent’s color and that guessed color matches the current Power Colour, they will receive:

  • 1 point for a correct guess
  • +2 bonus points for guessing the Power Colour
  • Total: 3 points

If the guessed color is correct but not the Power Colour, only 1 point is awarded.

For example, assume it’s round 3, and the randomly selected Power Colour is BLUE.

Player Choices:

  • HAL-9000 (AI): chose GREEN, guessed BLUE
  • Player: chose BLUE, guessed GREEN

Outcome:

  • The AI correctly guessed the player’s color (BLUE).
  • The guessed color (BLUE) is also the Power Colour.
  • The Player correctly guessed the AI’s color (GREEN), but is not the power colour, so only 1 point is earned.
Player Valerio earned 1 point(s) this round.
Player HAL-9000 earned 3 point(s) this round.

This logic ensures +2 bonus points are awarded only when the guessed color is both correct and matches the Power Colour.

Task 3

In Task 3 you need to implement the MEDIUM level of the AI.

  • For the first round the MEDIUM level will use the Random strategy, for the second round onwards the MEDIUM level will switch to the Avoid Last strategy and will keep that strategy until the game ends.

For example:

281-mind-game> new-game EASY 5
	What is your name?: Valerio
Welcome, Valerio!
281-mind-game> play
Starting round 1 of 5:
Enter two colors (RED, GREEN, BLUE, YELLOW): your own color followed by your guess, then press Enter.
 R R
Player HAL-9000: chose BLUE and guessed RED
Player Valerio: chose RED and guessed RED
Player Valerio earned 0 point(s) this round.
Player HAL-9000 earned 1 point(s) this round.
281-mind-game> play
Starting round 2 of 5:
Enter two colors (RED, GREEN, BLUE, YELLOW): your own color followed by your guess, then press Enter.
B B
Player HAL-9000: chose GREEN and guessed GREEN
Player Valerio: chose BLUE and guessed BLUE
Player Valerio earned 0 point(s) this round.
Player HAL-9000 earned 0 point(s) this round.
281-mind-game> new-game MEDIUM 5
	What is your name?: Valerio
Welcome, Valerio!
281-mind-game> play
Starting round 1 of 5:
Enter two colors (RED, GREEN, BLUE, YELLOW): your own color followed by your guess, then press Enter.
B R
Player HAL-9000: chose RED and guessed RED
Player Valerio: chose BLUE and guessed RED
Player Valerio earned 1 point(s) this round.
Player HAL-9000 earned 0 point(s) this round.
281-mind-game> play
Starting round 2 of 5:
Enter two colors (RED, GREEN, BLUE, YELLOW): your own color followed by your guess, then press Enter.
R Y
Player HAL-9000: chose GREEN and guessed GREEN
Player Valerio: chose RED and guessed YELLOW
Player Valerio earned 0 point(s) this round.
Player HAL-9000 earned 0 point(s) this round.
281-mind-game> play
Starting round 3 of 5:
Enter two colors (RED, GREEN, BLUE, YELLOW): your own color followed by your guess, then press Enter.
B R
Player HAL-9000: chose YELLOW and guessed BLUE
Player Valerio: chose BLUE and guessed RED
The POWER COLOUR is BLUE!
Player Valerio earned 0 point(s) this round.
Player HAL-9000 earned 3 point(s) this round.
  • In the first round, the MEDIUM AI uses a fully random strategy throughout all rounds. There is no learning or adaptation in this mode.
  • Starting from round 2, it switches to the AvoidLast strategy. This strategy assumes the human player will not choose the same color in consecutive rounds, so it excludes the previous human color from its guess (BLUE in this case).

  • In round 3, the AI will guess randomly but excluding RED because is the colour that the human played in Round 2. The AI is also lucky and also got the power colour.

Task 4

Task 4 – Implementing the HARD AI Level

In this task, you need to implement the behavior of the AI when the difficulty level is set to HARD.

  • Rounds 1 and 2:
    The AI uses the Random strategy.

  • Round 3:
    The AI switches to the LeastUsed strategy.

  • From Round 4 onwards:
    The AI dynamically switches between LeastUsed and AvoidLast strategies based on performance:

    • If the current strategy lost in the previous round (i.e., the AI earned 0 points), the AI switches to the other strategy.
    • If the current strategy earned 0 points, in the previous round, the AI continues using the same strategy.
  • When using the LeastUsed strategy, the AI must consider the entire history of colors chosen by the human player from round 1 up to the previous round. Naturally, to ensure fairness, the AI has no knowledge of the color selected by the human in the current round. That information only becomes available after the round is completed.

  • Every time the player runs the NEW_GAME command:

    • A new game begins.
    • The AI forgets all previous moves and starts fresh.
    • If the HARD level is selected again, the AI restarts with the Random strategy as in rounds 1 and 2.

In summary, the AI’s color tracking and strategy behavior must be reset with every new game session, and it should only consider the moves made during the current game.

Example of Strategy Switching

Assume a 5-round game with difficulty level HARD.

  1. Round 1:
    AI uses Random.
    AI earns 1 point.

  2. Round 2:
    AI continues with Random.
    AI earns 0 points.

  3. Round 3:
    AI switches to LeastUsed. (this always no matter the outcome of round 2) AI earns 0 points.

  4. Round 4:
    Since LeastUsed earned 0 points in Round 3, AI switches to AvoidLast for round 4.
    AI earns 2 points.

  5. Round 5:
    AvoidLast earned points in Round 4, so AI continues with AvoidLast.

This dynamic switching allows the HARD AI to adapt based on what strategies are working best within a game.

Task 5

In Task 5, you need to implement the logic that terminates the game (when the specified number of rounds is over) and executes the command SHOW_STATS

  • first of all, the user cannot run the command PLAY before the game is started (it shows an error message):
281-mind-game>play
281-mind-game> Error! Game not started yet. Please start a new game first.
  • The player has the freedom to start a new game with NEW_GAME while the current game is not finished yet. In this case, everything must starts from a blank state. If a new game is made whilst another is in progress, end the current game without displaying the stats/winner and just immediately start a new game.
281-mind-game> new-game EASY 3
        What is your name?: Valerio
Welcome, Valerio!
281-mind-game> play
Starting round 1 of 3:
Enter two colors (RED, GREEN, BLUE, YELLOW): your own color followed by your guess, then press Enter.
R G
Player HAL-9000: chose BLUE and guessed RED
Player Valerio: chose RED and guessed GREEN
Player Valerio earned 0 point(s) this round.
Player HAL-9000 earned 1 point(s) this round.
281-mind-game> new-game HARD 6
        What is your name?: Valerio
Welcome, Valerio!
281-mind-game> play
Starting round 1 of 6:
Enter two colors (RED, GREEN, BLUE, YELLOW): your own color followed by your guess, then press Enter.
Y R
Player HAL-9000: chose GREEN and guessed GREEN
Player Valerio: chose YELLOW and guessed RED
Player Valerio earned 0 point(s) this round.
Player HAL-9000 earned 0 point(s) this round.
281-mind-game>
  • You need to implement the SHOW-STATS command, which can only be executed when a game is running (otherwise the game shows an error message).
281-mind-game>show-stats
281-mind-game> Error! Game not started yet. Please start a new game first.

This command displays the cumulative number of points earned by each player since the start of the current game, using the PRINT_PLAYER_POINTS command from MessageCli.

281-mind-game> show-stats
Player Valerio has 7 point(s).
Player HAL-9000 has 8 point(s).

Exmaple of usage

281-mind-game> new-game HARD 6
        What is your name?: Valerio
Welcome, Valerio!
281-mind-game> play
Starting round 1 of 6:
Enter two colors (RED, GREEN, BLUE, YELLOW): your own color followed by your guess, then press Enter.
Y R
Player HAL-9000: chose GREEN and guessed GREEN
Player Valerio: chose YELLOW and guessed RED
Player Valerio earned 0 point(s) this round.
Player HAL-9000 earned 0 point(s) this round.
281-mind-game> show-stats
Player Valerio has 0 point(s).
Player HAL-9000 has 0 point(s).
281-mind-game> play
Starting round 2 of 6:
Enter two colors (RED, GREEN, BLUE, YELLOW): your own color followed by your guess, then press Enter.
B R
Player HAL-9000: chose RED and guessed RED
Player Valerio: chose BLUE and guessed RED
Player Valerio earned 1 point(s) this round.
Player HAL-9000 earned 0 point(s) this round.
281-mind-game> play
Starting round 3 of 6:
Enter two colors (RED, GREEN, BLUE, YELLOW): your own color followed by your guess, then press Enter.
Y R
Player HAL-9000: chose GREEN and guessed RED
Player Valerio: chose YELLOW and guessed RED
The POWER COLOUR is BLUE!
Player Valerio earned 0 point(s) this round.
Player HAL-9000 earned 0 point(s) this round.
281-mind-game> show-stats
Player Valerio has 1 point(s).
Player HAL-9000 has 0 point(s).
  • When the specified number of rounds has been completed, the game ends and displays the summary statistics—equivalent to running the SHOW_STATS command. The end of the game is indicated with the PRINT_END_GAME message. The game also announces the winner using the PRINT_WINNER_GAME message. Note that the game can end in a tie, in which case PRINT_TIE_GAME is used.
Player Valerio has 1 point(s).
Player HAL-9000 has 2 point(s).
The game is over!
Player HAL-9000 wins the game!

or

Player Valerio has 3 point(s).
Player HAL-9000 has 3 point(s).
The game is over!
It's a tie! Both players have the same number of points.

Full exmaple

281-mind-game> new-game HARD 4
        What is your name?: Valerio
Welcome, Valerio!
281-mind-game> play
Starting round 1 of 4:
Enter two colors (RED, GREEN, BLUE, YELLOW): your own color followed by your guess, then press Enter.
B R
Player HAL-9000: chose BLUE and guessed YELLOW
Player Valerio: chose BLUE and guessed RED
Player Valerio earned 0 point(s) this round.
Player HAL-9000 earned 0 point(s) this round.
281-mind-game> play
Starting round 2 of 4:
Enter two colors (RED, GREEN, BLUE, YELLOW): your own color followed by your guess, then press Enter.
Y R
Player HAL-9000: chose BLUE and guessed RED
Player Valerio: chose YELLOW and guessed RED
Player Valerio earned 0 point(s) this round.
Player HAL-9000 earned 0 point(s) this round.
281-mind-game> play
Starting round 3 of 4:
Enter two colors (RED, GREEN, BLUE, YELLOW): your own color followed by your guess, then press Enter.
G G
Player HAL-9000: chose RED and guessed RED
Player Valerio: chose GREEN and guessed GREEN
The POWER COLOUR is RED!
Player Valerio earned 0 point(s) this round.
Player HAL-9000 earned 0 point(s) this round.
281-mind-game> play
Starting round 4 of 4:
Enter two colors (RED, GREEN, BLUE, YELLOW): your own color followed by your guess, then press Enter.
B G
Player HAL-9000: chose YELLOW and guessed RED
Player Valerio: chose BLUE and guessed GREEN
Player Valerio earned 0 point(s) this round.
Player HAL-9000 earned 0 point(s) this round.
Player Valerio has 0 point(s).
Player HAL-9000 has 0 point(s).
The game is over!
It's a tie! Both players have the same number of points.
281-mind-game> new-game EASY 4
        What is your name?: Valerio
Welcome, Valerio!
281-mind-game> B R
Error! Command not found. (Run 'help' to see the list of available commands): "B"
281-mind-game> play
Starting round 1 of 4:
Enter two colors (RED, GREEN, BLUE, YELLOW): your own color followed by your guess, then press Enter.
B R
Player HAL-9000: chose YELLOW and guessed BLUE
Player Valerio: chose BLUE and guessed RED
Player Valerio earned 0 point(s) this round.
Player HAL-9000 earned 1 point(s) this round.
281-mind-game> play
Starting round 2 of 4:
Enter two colors (RED, GREEN, BLUE, YELLOW): your own color followed by your guess, then press Enter.
R G
Player HAL-9000: chose YELLOW and guessed YELLOW
Player Valerio: chose RED and guessed GREEN
Player Valerio earned 0 point(s) this round.
Player HAL-9000 earned 0 point(s) this round.
281-mind-game> play
Starting round 3 of 4:
Enter two colors (RED, GREEN, BLUE, YELLOW): your own color followed by your guess, then press Enter.
B R
Player HAL-9000: chose YELLOW and guessed GREEN
Player Valerio: chose BLUE and guessed RED
The POWER COLOUR is GREEN!
Player Valerio earned 0 point(s) this round.
Player HAL-9000 earned 0 point(s) this round.
281-mind-game> play
Starting round 4 of 4:
Enter two colors (RED, GREEN, BLUE, YELLOW): your own color followed by your guess, then press Enter.
Y G
Player HAL-9000: chose GREEN and guessed YELLOW
Player Valerio: chose YELLOW and guessed GREEN
Player Valerio earned 1 point(s) this round.
Player HAL-9000 earned 1 point(s) this round.
Player Valerio has 1 point(s).
Player HAL-9000 has 2 point(s).
The game is over!
Player HAL-9000 wins the game!

When all the test cases are passing, that’s a great sign! However, keep in mind that only half the test cases are provided (read the instructions below).

If you want you can write your own test cases to gain more confidence that your code is correct.




Marking Scheme

Item Value Note
Task 1 1%
Task 2 1%
Task 3 1%
Task 4 1%
Task 5 1%
OO Design 6%
Code Style 3%
Git Etiquette 1%
Total 15%


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 to fulfil the OOP requirements must actually be used, and not be “dummy classes”. You also need to pass at least 20% of the given test cases 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 on the final submission, 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.

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.





Edit

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 a git 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 the clean compile in your exec: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 and git 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.