Assignment 3 (15% of CS321) + lab 2 (20% of CSL321)

Due: Monday, March 8th 2021 at 11:59 PM


Lab 2:

In this lab we will get familiar with some common method overloading (toString(), equals(), and hashCode()) as well as generics and a small introduction to threads.


Lab Q1 overriding toString() – toString() is a method that all classes inherit from the superclass Object. toString() is called automatically on obj by System.out.println(obj), where obj is some instance of a class. Typically, toString() is overridden in order to produce some type of informative output describing the object’s state. If toString() is not overridden, Object’s toString() method is called by default, which returns a string as you see below: 

public String toString() {

      return getClass().getName() + "@" + Integer.toHexString(hashCode());

}

this code is taken directly from the Object class’s definition in the Java Language (can see here). This code concatenates the class name with the @ symbol and the hashCode of the object. hashCode by default returns an int representing the object’s location in memory, so the form of the string returned by Object’s toString is: className@memoryAddress.

For Q1, create a new class called ‘CurrentTime’. The class will have a single, no argument constructor and a single field ‘currentTimeMillis’ of type ‘long’. In the constructor, you will create and run a new anonymous thread (see example here) and within the thread, create an infinite loop using while(true) that updates currentTimeMillis with the current time and then sleeps for 1000ms, and then calls System.out.println(this.toString()) to print out a formatted version of current time. You will need to override toString() in CurrentTime to make it return a formatted version of currentTimMillis. Running your code should provide the below output (date will be different for you):


CurrentTime class + main:

public class Main {

      public static void main(String[] args) {

            new CurrentTime();

      }

}

class CurrentTime{

      private long currentTimeMillis;

      public CurrentTime(){

            new Thread(new Runnable() {

                  @Override

                  public void run() {

                        while(true) {

                              currentTimeMillis = System.currentTimeMillis();

                              try {

                                    Thread.sleep(1000);

                              } catch (Exception e) {

                                    e.printStackTrace();

                              }

                              System.out.println(CurrentTime.this);

                        }

                  }

            }).start();

      }

      @Override

      public String toString(){

            //your code here

      }

}


Lab Q2 overriding equals() and hashCode() – in order to compare two objects in java, we use the equals() method. The call to equals looks like this: 

bool isEqual = obj1.equals(obj2);

Where obj1 and obj2 are the two objects we want to compare for equality.

By default, equals() simply compares the reference value (address) of the two objects. Below is the default behavior of equals (which all classes inherit from Object):

public boolean equals(Object obj) {

      return (this == obj);

}

By default (without overriding equals()) two references are equal in Java if and only if they both refer to the same object (remember – reference types are any non-primitive type, any class you define in Java is a reference type). Therefore, in the above equals method, the code this == obj simply checks to see if both references have the same address, if so it means they both refer to the same object.

We would like to override equals() so when we call obj1.equals(obj2), it will return true if both obj1 and obj2 have the same state, even if they are references to different objects. Consider the following class:

class IntHolder {

      public int x, y;

      public IntHolder(int x, int y) {

            this.x = x;

            this.y = y;

      }

      /*

      @Override

      public boolean equals(Object obj){

      ...your code here...

      }

        */

}

now consider the following code in main:

IntHolder intHolder1 = new IntHolder(2,4);

IntHolder intHolder2 = new IntHolder(2,4);

System.out.println(intHolder1.equals(intHolder2)); // should print 'true' if 'equals()' overridden properly

We want this to print true, because even though intHolder 1 and intHolder2 are different objects, they are equal in the sense that they have the same ‘state’ (their instance variables have the same values) . To get this behavior, we need to override the equals method (which means we also need to override hashCode(), see why here). Here is an example of using casting and instanceof to successfully override equals().

Q2 summary: override equals() and hashCode in the simple IntHolder class, so it prints true in the above example.


Lab Q3 generic class

Read the generics lesson from the java tutorials: https://docs.oracle.com/javase/tutorial/java/generics/index.html in particular, you should read about bounded type parameters.

Once you’ve finished reading, create a generic ‘SimpleStatistics’ class that carries out the following operations on any array which contains subtypes of Number class (such as Short, Integer, Double, etc). The operations are: mean, standard deviation, median, max, and min.

You should be able to compile and run the following:

public class Main {

      public static void main(String[] args) {

            ArrayList<Double> doubles = new ArrayList<>(){

                  {add(10.0); add(1.9); add(1.3); add(2.5);}

            };

            ArrayList<Integer> integers = new ArrayList<>(){

                  {add(10); add(1); add(1); add(2);}

            };

            // more array lists with bytes, floats, longs, etc (some subclasses of Number)

            System.out.println(new SimpleStatistics<Double>().mean(doubles));

            System.out.println(new SimpleStatistics<Integer>().standardDeviation(integers));

            //etc

      }

}

Your class might look something like this (add the requested methods). You might need to modify the class signature also.

class SimpleStatistics<T extends Number>{

      // your methods here

}

this post might be useful for Q3:

https://stackoverflow.com/questions/17393526/how-can-i-initialize-a-generic-variable-in-java


Assignment 3 – live cryptocurrency display

In this assignment, we will return to the financial markets. We will expand on assignment 1 in preparation for the final project. We will get familiar with threads and an external library (JSoup) as well as more UI and the first of the SOLID principles (single responsibility principle).

I have provided you with a small class which performs the task of fetching live bitcoin (BTCUSD) data from robinhood.com and updating a chart in real time with the bitcoin time series as the market evolves. However, the class is poorly organized because it has multiple responsibilities; it should be broken up into multiple classes, with each class responsible for a single task (such as loading data, displaying data, or handling user input).

In its current form, my class scrapes bitcoin data from robinhood using JSoup libraries. JSoup fetches all this data from the url (see code) and stuffs it into a document. My code converts the document to a String object and then searches this string and extracts the current price. This runs in an infinite while loop within a separate thread, which sleeps every 500 ms to conserve CPU cycles.

JSoup installation: download the core library jar file here and add it to your module dependencies in intellij.

As mentioned, the class is poorly organized. Your job is to break this class up into subclasses according to functionality. Each class should have only a single responsibility (fetch data, display data, handle IO, etc.).

You will need to construct a variety of classes. Focus on the ‘single responsibility principle’ from SOLID:

S          Single responsibility principle – a class should only have a single responsibility

O         Open-closed principle – software entities should be open for extension but closed for modification

L          Liskov substitution principle – objects in program should be replaceable with instances of their subtypes

I          Interface segregation principle - many client-specific interfaces better than one general purpose interface

D         Dependency inversion principle - depend on abstractions, not concretions

You will probably want one ‘central’ class which is composed of your other classes (has them as member variables, in a ‘has-a’ relationship) so that it can coordinate the data passing, I/O, and display updating across classes.

In addition to improving my code by breaking it up into multiple classes, add the following features (add more classes where appropriate):

1) In its current state, the graph is updated upon each JSoup URL fetch (every 500 ms). However, we should update the graph only when the price changes. If the new data point bitcoin price fetched by JSoup is identical to the previous data point’s price, it should be discarded. Update the graph only when the price changes.

2) Add an x-axis and a y-axis to graph: bitcoin value on y-axis and date/time on the x-axis. Can use Java’s dateTime libraries and formatting (see Q1 above) for the x-axis.

3) Add a button that resets the chart when clicked (clears the underlying array and starts from zero data points).

4) Add a text field that shows one of the following in the top-left of the chart:

a. If current data value > previous data value, should show: direction: up

b. If current data value < previous data value, should show: direction: down

5) Add two buttons to increase/decrease the update speed in the thread that fetches the data using JSoup. Define the range of allowable update speeds in a final int array as follows: 100 ms, 250 ms, 500 ms, 1000 ms, 5000 ms, 10000 ms. (currently, it is set to 500 ms, see the call to Thread.sleep() in my code).

6) Add three buttons so the user can switch between BTC-USD, DOGE-USD, and ETH-USD (links below). Your application should maintain a separate array for each of these values in the background, so when the user switches to a different cryptocurrency using the button, the data is already fetched and ready to display.

a. https://robinhood.com/crypto/BTC (bitcoin value in USD(

b. https://robinhood.com/crypto/ETH (Ethereum value in USD)

c. https://robinhood.com/crypto/DOGE (dogecoin value in USD)

each of the above features 1-6 is worth 10%. The overall structure of your code (how well you break up the functionality into separate classes, etc.) is worth 40%.

bonus +10%: add the Bollinger Band and weighted moving average indicators to your charts, along with buttons to toggle them on/off. Add ‘persistence’ to your application by saving the currently acquired data to some file every x seconds, and then when the program runs, check that directory to see if it contains any previously saved data, load it, and then continue to accumulate timepoints from robinhood.

Below: result after running moodle code for a few minutes (the pattern will be different for you because the data is real-time). You can stick to the basic line chart (example below) for this assignment, because I couldn’t find a simple way to get OHLC data. if you find a better free API for getting the BTC/ETH/DOGE data, feel free to use that instead.