# COMP1110 Lab 4
## Before the Lab
* Complete your personal journal for week 5, commit and push at least 5 minutes before your lab.
* Make sure you’ve covered the modules [**S2**](https://cs.anu.edu.au/courses/comp1110/lectures/se/#S2) (Branches and Merging) and [**J4**](https://cs.anu.edu.au/courses/comp1110/lectures/java/#J4) (Random).
## Purpose
In this lab you will complete a git exercise in which you will practice using git in a group setting, and you will develop a more complex Java program.
**It is essential that you complete this lab and have a tutor mark it off during the lab**.
## GitLab Upstream Pulls for Assignment
**One** group member should do the following. Once complete, each of the
other group members can pull the changes.
0. Quit IntelliJ if you have it open.
1. Start a terminal (use the menu at top left)
2. Change directory (`cd`) into the folder that contains your intelliJ
projects (`cd IdeaProjects`)
3. Change directory (`cd`) into your assignment repo (`cd comp1110-ass2-
or `cd comp1140-ass2-
4. Display the currently known remote repos for the project (`git remote -v`).
5. Add the comp1110 assignment2 repo as a remote upstream repo (`git remote
add upstream https://gitlab.cecs.anu.edu.au/comp1110/comp1110-ass2.git` or
`git remote add upstream https://gitlab.cecs.anu.edu.au/comp1110/comp1140-ass2.git`).
6. Now open your comp1110-ass2 (or comp1140-ass2) repo in IntelliJ
7. Prepare to pull changes (VCS -> Git -> Pull…)
8. Use the drop-down menu to change the ‘Remote’ to be
`upstream(https://gitlab.cecs.anu.edu.au/comp1110/comp1110-ass2.git)’
or ‘upstream(https://gitlab.cecs.anu.edu.au/comp1110/comp1140-ass2.git)`.
9. Refresh the list of branches by clicking the refresh button to the right
of the dropdown.
10. Select the `upstream/master` branch.
11. Click `Pull`. This should behave just like a merge from your last lab
exercise, and work without further interaction. If not, you may need to
merge, in which case you should consult your tutor if you’re unsure what to
do.
12. Bring up the `Version Control` panel at the bottom of your IntelliJ
window, and select `Log`, and notice that you now have some new changes in
your history.
13. Commit and push your change.
14. Your group members can now pull your change to their clones of the group
repo.
You can repeat these steps to pull further changes into your forks of class
repos. You only need to perform the steps on one of your clones and then
the changes will be visible (after pulling) at each clone of your repo.
You can do this on the lab computers (as in this exercise) or on your home
computer. If you have Linux or MacOS on your computer, the process is
as described above. If you have Windows on your computer, you will
need to use [git bash](https://git-for-windows.github.io) rather than a
terminal to set your upstream remote (steps 2-6). Once done, close the issue (#14).
## Git groupwork
This is a simple exercise that explores most of the git skills that you are
expected to use in COMP1110. This exercise was demonstrated in a [how-to video](https://cs.anu.edu.au/courses/comp1110/help/mp4/gitexercise.mp4).
If you have not seen the video, I strongly recommend you watch it. If you get
yourself into trouble doing this exercise, you may find it helpful to look at
the video again. In the (https://cs.anu.edu.au/courses/comp1110/help/mp4/gitexercise.mp4) I performed the role of all three characters
(Alice, Bob and Cindy). You should do this exercise in the lab with your group
members. If there are only two people in the group, you should be able to adapt
the exercise by delegating Cindy’s activities to Alice (so you just have Alice
and Bob).
1. Before you start, **everyone** in the group must have a clone of your group
repo and an associated project in IntelliJ. This will work best if you’re
sitting nearby to each other.
2. **Alice** does the following (with the others watching…):
**Create a new package and 2 new classes**
* Create a new package, `gittest`.
* Create two new Java classes, `Main` (which has an empty `main()` method), and `A`, which just has a `toString()`. When IntelliJ prompts you to add the new classes to git, say yes.
* If you neglected to add the new files when they were created, add them now.
You will notice that if a file has not been added to version control, IntelliJ shows the name of the file in red.
You can add a file using `VCS` -> `Git` -> `Add`, or via the keyboard shortcut `Ctrl+Alt+A`.
The file name will appear green once added.
**Commit and push new files classes to group repo**
* Commit (`VCS` -> `Commit Changes…` or `Ctrl+K`), being sure to set the author’s name to `Alice
* Click `Commit`, choosing to `Commit and Push`.
* You should see a little green notification dialogue at the bottom of the screen confirming that the push was successful.
3. **Bob** does the following (*without co-ordinating with Cindy*):
**Pull changes from group repo**
* Pull Alice’s changes `VCS` -> `Git` -> `Pull…`, leave the defaults and click `Pull`.
* In the `Version Control` tool window (activate by clicking the little icon at the very bottom left of the IntelliJ window, and select `Version Control`), you should see Alice’s changes.
**Add a new class to group project**
* Create a new Java class in the `gittest` package, `B` which just has a `toString()` method. When prompted to add the new class to git, choose `Yes`.
**Commit changes but do not push to group repo**
* Commit (`Ctrl+K`), set the author to `Bob
* Do **not** push the change yet (we want to imagine Bob gets interrupted before pushing).
4. **Cindy** does the following (*without co-ordinating with Bob*):
**Pull changes from group repo**
* Pull Alice’s changes `VCS` -> `Git` -> `Pull…`, leave the defaults and click `Pull`.
* In the `Version Control` tool window (activate by clicking the little icon at the very bottom left of the IntelliJ window, and select `Version Control`), you should see Alice’s changes.
**Add a new class to group project**
* Create a new Java class in the `gittest` package, `C` which just has a `toString()` method. When prompted to add the new class to git, choose `Yes`.
**Commit changes and push to group repo**
* Commit (`Ctrl+K`), set the author to `Cindy
* You should see a little green notification dialogue at the bottome of the screen confirming that the push was successful.
5. **Bob** now does the following:
**Try to push your commit to group repo**
* Try to push `Ctrl+Shift+K`, then click `Push`, and see an error message giving you the option to either intentionally push a new head, or merge. We will merge in the following steps.
**Merge your changes with group repo**
* Click `Merge`.
* You should see a green notification saying that the Push was successful and that two commits were pushed. The first of the two commits is the one that Bob did in step 3. The second is an automatically generated one that captures the merge of Cindy and Bob’s work.
* View the log by clicking on the `Log` tab of the Version Control tool window. You can see a graph showing the merge of Cindy’s work with Bob’s.
6. **Alice** and **Cindy** update (`Ctrl+T`, select `Merge` as the update type). Now everyone should be in the same state. View history to ensure that this is so (`Team…`, `Show History`).
7. **Bob** now conducts an experiment, but doesn’t want to mess things up for Alice and Cindy (because his idea may not necessarily work out), so he uses a *branch*:
**Create a new branch of your group repo**
* Add a new branch named `BobsExperiment` (`VCS`, `Git`, `Branches…`, `New Branch…`). Rules for branch names can be found [here](https://www.kernel.org/pub/software/scm/git/docs/git-check-ref-format.html).
**Make changes to the group project, commit and push to your branch of group repo**
* Make a simple change to class `B`, commit that change (`Ctrl+K`), being sure to set the author to Bob.
* Make another simple change to class `B`, commit that change.
* Push your changes.
8. **Everyone** does the following (*at the same time*):
* Update project (`Ctrl+T`).
* Look at the `Log` tab of the Version Control tool window.
* Ensure that you are on the head of the `master` branch (i.e. not on Bob’s experimental branch).
The changeset you are on will be marked with a yellow tag; if you hover the mouse over the tag it should show the word ‘HEAD’.
If you followed all of the steps, Alice and Cindy should have the changeset where Bob did a merge (right before he made the branch).
Bob will be on the wrong changeset, so he should switch to the `master` branch: `VCS`, `Git`, `Branches`, `Local Branches`, select `origin/master`, and `Checkout`.
* Now (ignoring Bob’s experiment), everyone should edit the main method of `Main` and add a line such as `A a = new A();`, changed suitably to reflect the author (eg `B` for Bob and `C` for Cindy).
* Each person should now save their change and commit (**but don’t yet push**) your change. Remember to set your author name and a commit message.
9. **Alice** pushes her changes. There should be no error.
10. **Bob** now tries to push his change, but will find a problem that he must now resolve. [Why can’t you push? What’s causing the problem?]
* Try to push (`Ctrl+Shift+K`).
**Manually merge changes with group repo**
* You should get an error message, which you should read (you will resolve the problem by merging, so click `Merge`).
* You will see a dialogue which presents you with three choices (`Accept Yours`, which would throw away Alice’s work, `Accept Theirs`, which would throw away your work, or `Merge`, which we will do). Click `Merge`.
* You will see a window with three panes, the center shows the result, the left shows yours (Bob’s), and the right shows theirs (Alice’s).
* Click the little `<<` icon next to Alice's change to bring it into the merged result.
* Click the little `>>` icon next to your (Bob’s) change to bring it into the merged result.
* You will be asked whether you want to finish. Click `Save and Finish`.
* Push your result (`Ctrl+Shift+K`).
11. **Cindy** now tries to push her change, but will run into the same problem as Bob.
* Try to push (`Ctrl+Shift+K`).
**Manually merge changes with group repo**
* You should get the same error message as Bob, which you should read (you will resolve the problem by merging, so click `Merge`).
* You will see a dialogue which presents you with three choices (`Accept Yours`, which would throw away Alice and Bob’s work, `Accept Theirs`, which would throw away your work, or `Merge`, which we will do). Click `Merge`.
* You will see a window with three panes, the center shows the result, the left shows yours (Cindy’s), and the right shows theirs (Alice and Bob’s).
* Click the little `<<` icon next to Alice and Bob's change to bring it into the merged result.
* Click the little `>>` icon next to your (Cindy’s) change to bring it into the merged result.
* You will be asked whether you want to finish. Click `Save and Finish`.
* Push your result (`Ctrl+Shift+K`).
12. **Everyone** pulls and updates and should see the `Main` file with all three contributions.
That completes the group exercise. Close the associated issue (#15). The next exercise is an individual exercise.
## Heads or Tails
This exercise requires using object oriented design and imperative
design.
* Hopefully, having completed lab 3, you will have a working
`Dice` class which can, given a lower and upper bound, produce random
values in this range (inclusive).
* If you haven’t got this class working yet, please take this time now
to complete the debugging activity of lab 3.
* Please take some time to revise how `Random` is used to generate
random numbers between two values. If you are having trouble
understanding how `Random` works or are stuck on the debugging task
from lab 3, now is a good time to ask a peer or your tutor for help.
* Copy the working Dice class to your lab 4 package, and create a new
class, `HeadsOrTails`.
* The class `HeadsOrTails` should enable the user to play many games
of heads or tails by accepting the ‘prediction’ from the terminal.
* The user should input `h` for heads and `t` for tails. Any other
inputs should result in `Unexpected input` being printed to the
terminal.
* When a heads or tails guess is received from the user, the program
should use the `Dice` class to create a `coin` which should then be
flipped. If the user’s prediction is correct, print `Good guess!` to
the terminal, otherwise print `Bad luck!`.
* The program should accept guesses and give answers
repeatedly until the user exits with `Ctrl+d`. Please don’t print any
extra content to the terminal besides that precisely described above –
this will impact testing.
* **Consider**: how many `coin`’s do we need? Does `coin` have to be a
local variable or can we declare it once? Can `coin` be an
instance variable? Can `coin` be a class variable
(i.e. static)? Can `coin` be a final variable? If `coin` is
final, will calling `rollDice()` on `coin` still be random?
Once you have completed the `HeadsOrTails` class, test your code using
the provided test class `L4 HeadsOrTailsTest`. Commit, push to git,
close the issue (#16) and show your tutor.
## Extension
**Background**
Professor [Richard P. Brent](https://researchers.anu.edu.au/researchers/brent-rp) (Emeritus professor at ANU!) made significant contributions to the field of random number generators, and created some algorithms to produce pseudo-random numbers.
[Further reading for those interested.](https://arxiv.org/abs/1004.3115)
**Write your own ‘random’ code**
As discussed in lectures, java.util.random gives you *pseudo-random* numbers- it looks random, but is created using a formula.
Without using java.util.random, write a code that will ‘randomly’ return an int in [1,2,3] every time you run it.
**Test your own ‘random’ code using collections**
Write some code to run your program 150 times, and collect the results. Read through the next steps and work out which collection type will be most useful here. (Array,list,set,map?)
To be *pseudo-random*, your code should:
– Print each number roughly the same amount of times. Using your collection, print how often each number came up-the closer to (50,50,50) the better!
– It should look random- if your code runs 1,2,3,1,2,3,1,2,3… that won’t look random. Seperate the results into the first 50 (1-50), second 50 (51-100) and third 50 results (101-150).
How often is the same result in the same place- (e.g. Does the 1st result = 51st result = 101st result? How often does this happen?)
– Should contain all small sequences of numbers. Check that your results contain the following sets: (1,1,1), (1,2,3),(2,3,2),(3,2,1),(3,1,2).
How many different ways can you think of to create a ‘random’ number generator? You don’t have to program more than one, but if you do try testing them against each other.
# COMP1110 Lab 5
## Before the Lab
* Complete week 6 of your personal journal, commit and push at least 5 minutes prior to your lab.
* Make sure you’ve covered the modules [**J9**](https://cs.anu.edu.au/courses/comp1110/lectures/java/#J9) (Lambda expressions) and [**X1**](https://cs.anu.edu.au/courses/comp1110/lectures/javafx/#X1) (JavaFX)
## Purpose
In this lab you will write a simple Java FX program.
**It is essential that you complete this lab and have a tutor mark it off during the lab**.
## A simple JavaFX animation
Your objective here is to familiarize yourself further with JavaFX by creating
a simple window with a moving ‘ant’.
In the Java package comp1110.lab5, within your comp1110-labs
repository, create a new Java class, `Ant`, that draws the path of an
ant that is walking randomly around a JavaFX window. This should look
a little like a scribbling on a page. If the ant walks off the edge of
the screen re-center the ant and continue the random walk. Use the
basic template from the code from lecture X01 (or the
[HelloTutor](../lab1/HelloTutor.java) example from Lab 1). In addition
to that, you may find the following helpful:
““java
…
primaryStage.setScene(scene);
Timeline timeline = new Timeline(new KeyFrame(Duration.millis(100),
ae -> {
/* your code goes here */
}));
timeline.setCycleCount(Animation.INDEFINITE);
timeline.play();
primaryStage.show();
…
““
that little bit of code will be called once every 100 milliseconds (10 times a second).
![alt ant](assets/lab5.png)
## Extension
**Use recursion to reverse an ArrayList**
Create a recursive method reverseArray.
The method should take an ArrayList of characters and return the same ArrayList with the characters reversed.
E.g. if you start with `[‘a’,’b’,’c’,’d’,’e’]` the method should return `[‘e’,’d’,’c’,’b’,’a’].
For the method to be recursive, it needs to call itself at some point.
**Use recursion to print a triangle (harder)**
Create a method `trianglePrinter`.
The method should take an integer as input, and print out a triangle with that many rows.The triangle should look like the triangle from lab 2, except the bottom row should have spaces instead of stars.
For example, if you run trianglePrinter(5):
“`
____*
___*_*
__*___*
_*_____*
*_______*
“`
To be recursive, the method needs to call itself at some point.
# COMP1110 Lab 6
## Before the Lab
* Complete week 7 of your personal journal, commit and push at least 5 minutes prior to the start of your lab.
* Make sure you’ve covered module [**X01**](https://cs.anu.edu.au/courses/comp1110/lectures/javafx/) (JavaFX)
## Purpose
In this lab you will write a more advanced JavaFX program.
**It is essential that you complete this lab and have a tutor mark it off during the lab**.
## JavaFX Shapes
1. **Create a new JavaFX class.**
In the Java package `comp1110.lab6` within your labs repo, create a new Java class, `Board`, which extends `javafx.Application`, that draws a 600×519 pixel window. Set the window title to “Board”.
2. **Draw a triangle**
Create an upright 200x200x200 equilateral triangle within the scene you made in step 1. Use the `Polygon` class. Make the vertices centered around (0,0), and afterward use `setLayoutX()` and `setLayoutY()` to recenter the triangle in the middle of your window. Set the fill color of the triangle to `LIGHTGREY`.
![alt triangle](assets/lab6a.png)
*Hint: Relative to the center of the triangle, the apex of the triangle should be at (0.0, -86.6), and the right and left corners of the base should be (100.0, 86.6) and (-100.0, 86.6), where 100 = 200/2 and 86.6 = sqrt((200*200)-(100*100))/2;*
3. **Create an inner class**
Create an inner class, `Triangle`, which extends `Polygon` and has a constructor with signature `Triangle(double x, double y, double side)`. This should create an upright equilateral triangle, centered at (`x`,` y`), with sides of length `side`.
Comment out the code you wrote in step 2 (that drew the triangle with Polygon), and replace it with the creation of a `Triangle`. Set the fill color of the new triangle to `LIGHTGREY`. Don’t forget to add your triangle to the root group.
4. **Fill the board with triangles**
Fill the board with a grid of triangles, storing each triangle in an ArrayList
5. **Create a white border**
Reduce the size of each triangle to 196 pixels, while maintaining the spacing as if they were size 200. This should create the effect of a white border around each triangle.
![alt board](assets/lab6b.png)
6. **Finish up**
Commit your code, push it, close the relevant issue (#18), and show your work
to your tutor.
## Work on your group assignment
Use any spare time to work on your group assignment.
# COMP1110 Lab 7
## Before the Lab
* Complete week 8 of your personal journal, commit and push at least 5 minutes prior to the start of your lab.
* Make sure you’ve covered module [**X01**](https://cs.anu.edu.au/courses/comp1110/lectures/javafx/) and [**X02**](https://cs.anu.edu.au/courses/comp1110/lectures/javafx/#x2) (JavaFX).
## Purpose
In this lab you will extend the your Board program from Lab 6 to include drag-and-drop.
**It is essential that you complete this lab and have a tutor mark it off during the lab**.
## JavaFX Drag and Drop
1. **Create an inner class**
Create a new inner class `DraggableTriangle`, that extends your inner class `Triangle`.
2. **Add a constructor**
Add a constructor to your new inner class with the following signature: `DraggableTriangle(double x, double y, double size, Board board)`. Ensure that this constructor calls its parent constructor (`super(x, y, size)`), and then sets the fill color to`RED`.
3. **Add a new field**
Add a private instance field `board` to your `DraggableTriangle` inner class and initialize it in the constructor (i.e. `this.board = board;`).
4. **Create a draggable triangle**
Within the `start()` method of your `Board` class, create a new `DraggableTriangle` of size 200, centered at (300, 260), and with the board (i.e. `this`) passed as the fourth argument to the constructor. Remember to add the draggable triangle to your root group.
![alt board](assets/lab7a.png)
5. **Make the inner class draggable**
Make the inner class `DraggableTriangle` draggable. The approach here is to identify how much the mouse has moved (by comparing its current position to its last position), and then move the triangle by that same amount.
* Add two private instances fields to the inner class, both doubles, to track the location of the mouse as the object is dragged. Call them `mousex` and `mousey`.
* Remember where the mouse is when it is first pressed, and ensure your triangle remains visible. Do this within the constructor by establishing a handler for mouse presses. You need to add code to the constructor for `DraggableTriangle` that looks something like this:
““Java
this.setOnMousePressed(event -> {
.. your code here ..
});
““
* Your code should store the current mouse x and y positions in the private fields (e.g. `mousex = event.getSceneX()`, etc), and should ensure the draggable triangle is not covered by other nodes in the scene (call `toFront()` to ensure this).
* Move the triangle as the mouse is dragged using a handler via `setOnMouseDragged()` in much the same way as you did for `setOnMousePressed()` in the previous step. In that code, find out how much the mouse has moved (e.g. use `event.getSceneX() – mousex`), and change the location of the triangle by the same amount (use `setLayoutX()`, etc). Then remember the new mouse location (updating `mousex` and `mousey`), so that it is all ready for the next time the event occurs.
You should now be able to drag the red triagle around.
6. **Add a distance calculator**
Add a method to your inner class `Triangle` with signature `private double distance(double x, double y)` that returns the euclidian distance from the center of the triangle to the point (x,y), (using Pythagoras’ theorem :-).
7. **Find the nearest triangle**
Add an instance method to your `Board` class that allows you to find the nearest triangle to a given point, it should have a signature something like `Triangle findNearestTriangle(double x, double y)`. You can do this by simply iterating over all the triangles in your `ArrayList
8. **Highlight the nearest**
Highlight the triangle nearest the draggable triangle:
* Add a new field to your `Board` class that allows you to remember a ‘highlighted’ triangle, and initialize the field to `null` (e.g. `Triangle highlighted = null;`).
* Add a method `void highlightNearestTriangle(double x, double y)` that highlights the triangle nearest a point (`x`, `y`). This method should first un-highlight the currently highlighted triangle (if there is one), by filling it with `LIGHTGREY`. It should then set the variable `highlighted` to be equal to the nearest triangle to (`x`, `y`), and then it should set the fill color of the highlighted triangle to `GREEN` (or whatever color you prefer).
* Add a line to your `setOnMouseDragged()` event in the constructor of `DraggableTriangle` that calls `board.highlightNearestTriangle()` with the location of your draggable triangle as arguments. You should now find that as you drag your red triangle around, the triangle nearest it is highlighted green.
![alt board](assets/lab7b.png)
9. **Snap to nearest triangle**
Finally, make your draggable triangle snap to the nearest triangle. To do this, add a handler for mouse release (use `setOnMouseReleased()`, just like you did for `setOnMousePressed()` and `setOnMouseDragged()`). In that code, find the nearest triangle to your draggable triangle, and then make the location and orientation of the draggable triangle be the same as that of the nearest triangle (using `setRotate()`, `getRotate()`, `setLayoutX()`, etc.).
10. **Finish off**
Commit and push your work, close the relevant issue (#19), and notify your tutor.
## Extension: Hashing
**Create a hash program**
Using the lecture code from C03 as a template:
* Read the data from `assets\us_postal_codes.txt`. Each line contains a postal code,town name, state name, state code,county name, latitude and longitude.
Then:
Imagine you are in charge of the entire US postal service, and you have only 50 delivery officers to cover the entire country (40933 zip codes).
You want to give each person a roughly equal amount of work (imagine each post code has the same amount of mail).
Create a hash function that will:
1. Split the work as evenly as possible (imagine that each post code has the same amount of mail)
2. Minimise the travel each person does as much as possible. Imagine that each person starts at any one of their zip codes, and avoid them having to travel across the country.
You can test 1. by running the program and checking the histogram of results to see if the hash function is even.
How many ways can you do this?
## Work on your group assignment
Use any spare time to work on your group assignment.