Academic Integrity: tutoring, explanations, and feedback — we don’t complete graded work or submit on a student’s behalf.

The goal of this lab is to create a dashboard in JavaFX summarizing a large data

ID: 3791331 • Letter: T

Question

The goal of this lab is to create a dashboard in JavaFX summarizing a large dataset. For the first assignment, use the 2015 CSV file for City of Vancouver property tax assessments:

http://data.vancouver.ca/datacatalogue/propertyTax.htm

Your dashboard should have displays for each of the following information:

Average property value and standard deviation for the entire data set.

Average house age and standard deviation for the entire data set.

Total house value change for the entire data set (current land value – previous land value).

Count the number of Commercial, One Family and Multiple Family Dwelling for the entire data set.

The maximum value, minimum value, and number of homes with house value by increments of $25000. For example, this could be a table, bar chart, or pie chart, which shows the number of homes with value from (thousands) 100 – 125, 125-150, 150-175, 175-200, etc all the way to the maximum first “bin” or interval that has 0 (this should be somewhere in the millions..)

The user should be able to double-click on any of the displays for items 1-5 to drill down to show more detail on the calculation. The next level of detail should be a stage with a ListView by street name, and then double-clicking on a given item should open another stage showing the calculation by postal code. For example, double-clicking on the property value should show a display of property values by postal code. Double-clicking on a given postal code should then show the property values by street name.

Marks:

Property value and standard deviation are shown properly                         +2

House age and standard deviation are shown properly                                +2

House value change is shown properly                                                         +2

Number of property types are shown properly                                             +2

House values histogram is shown properly                                                   +2

Double-clicking on items 1, 2, or 3 shows the calculation by street name, and then by postal code.                                                                                            +4

Create an HTML user guide with screenshots of your interface of where the professor should look to find the information for items 1-6. Also write 1 sentence explaining why you chose your chart type for displaying the information.         +2

Explanation / Answer

Assignment1.java

import java.io.BufferedReader;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;

import javax.swing.JFileChooser;
import javax.swing.filechooser.FileNameExtensionFilter;

import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.ListView;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.TextField;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.layout.ColumnConstraints;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

// Main class
public class Assignment1 extends Application {
  
   // Main method
   public static void main(String[] args) {
       launch(args);
   }
  
   // Starts main window
   @Override
   public void start(Stage primaryStage) throws Exception {
      
       GridPane root = new GridPane();
      
       Label getAddLbl = new Label("Enter the file location: ");
       GridPane.setConstraints(getAddLbl, 0, 0);
       GridPane.setColumnSpan(getAddLbl, 2);
      
       TextField getFileLoc = new TextField();
       getFileLoc.setMinWidth(350);
       GridPane.setConstraints(getFileLoc, 0, 1);
       GridPane.setColumnSpan(getFileLoc, 2);
      
       Button selectButton = new Button("...");
       GridPane.setConstraints(selectButton, 2, 1);
      
       Button loadButton = new Button("Load dataset");
       GridPane.setConstraints(loadButton, 0, 2);
      
       Button openDash = new Button("Open dashboard");
       GridPane.setConstraints(openDash, 1, 2);
      
       Label status = new Label("");
       GridPane.setConstraints(status, 0, 3);
      
       // Table with all Properties on the file
       TableView<Property> table = setTable();
      
       selectButton.setOnMouseClicked(clickEvent -> getFileLoc.setText(getFile()));
       loadButton.setOnMouseClicked(clickEvent -> readCSVFile(getFileLoc.getText(),table,status));
       openDash.setOnMouseClicked(clickEvent -> startMainDashboard(table));
      
       // Set main window
       root.getChildren().addAll(getAddLbl,getFileLoc,loadButton,openDash,selectButton,status);
      
       primaryStage.setScene(new Scene(root, 400, 100));
       primaryStage.setTitle("");
       primaryStage.setResizable(false);
  
       primaryStage.show();
   }
  
   // Opens a pop-up window to select a file. Its path is returned as a string.
   protected String getFile()
   {
       JFileChooser chooser = new JFileChooser();
        FileNameExtensionFilter filter = new FileNameExtensionFilter("CSV",
            "csv");
        chooser.setFileFilter(filter);
        int returnVal = chooser.showOpenDialog(null);
        if(returnVal == JFileChooser.APPROVE_OPTION)
        {
           return chooser.getSelectedFile().getPath();
        }
        return "";
   }
  
   protected void startMainDashboard(TableView<Property> table)
   {
       GridPane root = setGridPane(table);
       root.setPadding(new Insets(10));
      
       Stage newStage = new Stage();
       newStage.setTitle("Dashboard");
       Scene newScene = new Scene(root, 900, 600);
      
       //Tell the stage which scene to display
       newStage.setScene(newScene);
      
       //make the stage visible
       newStage.show();
   }
  
  
   // Creates a GridPane that will show the dashboard
   protected GridPane setGridPane(TableView<Property> table)
   {
       GridPane root = new GridPane();
      
       // Adjusts columns
       ColumnConstraints column1 = new ColumnConstraints();
       column1.setPercentWidth(33);
      
       ColumnConstraints column2 = new ColumnConstraints();
       column2.setPercentWidth(33);
      
       ColumnConstraints column3 = new ColumnConstraints();
       column3.setPercentWidth(33);
       column3.setHgrow(Priority.ALWAYS);
      
       root.getColumnConstraints().addAll(column1,column2,column3);
      
      
       // Sets the 6 displays
       // Average property value and standard deviation
       VBox item1 = PrepareMainDisplays.setItem1(table.getItems());
       GridPane.setConstraints(item1, 0, 0);
      
       // Average house age and standard deviation
       VBox item2 = PrepareMainDisplays.setItem2(table.getItems());
       GridPane.setConstraints(item2, 1, 0);
      
       // Total house value change
       VBox item3 = PrepareMainDisplays.setItem3(table.getItems());
       GridPane.setConstraints(item3, 2, 0);
      
       // Types of properties
       VBox item4 = PrepareMainDisplays.setItem4(table.getItems());
       GridPane.setConstraints(item4, 0, 1);
      
       // Maximum value, minimum value and table with number of
       // properties by increments
       HBox item5 = PrepareMainDisplays.setItem5(table.getItems());
       GridPane.setConstraints(item5, 1, 1);
       GridPane.setColumnSpan(item5, 2);
      
       root.getChildren().addAll(item1,item2,item3,item4,item5);
      
       return root;
   }
  
   // Reads a CSV file into a table
   public void readCSVFile(String filename, TableView<Property> table, Label status)
   {
      
        //Create a list of data:
        final ObservableList<Property> data = FXCollections.observableArrayList();
      
       try(BufferedReader reader = Files.newBufferedReader(Paths.get(filename)))
       {
           String line = "";
           // Ignores first line -> Column names
           reader.readLine();
          
           //get a line of text from the file
           line = reader.readLine();
          
           while(line != null){
              
               Property propTemp;
              
               // In case the last item is not filled
               if (line.charAt(line.length()-1) == ',')
               {
                   line += '0';
               }
              
               //Split the line by commas
               String [] partsOfLine = line.split(",");
              
               try{
              
                   propTemp = new Property(partsOfLine[0],partsOfLine[1],
                       partsOfLine[2],partsOfLine[3],partsOfLine[4],
                       partsOfLine[5],partsOfLine[6]);
                  
                   data.add(propTemp);
               }
               catch (Exception e)
               { }
              
               line = reader.readLine();
              
           }
           table.setItems(data);
           status.setText("File was loaded.");
          
       }catch(IOException ioe)
       {
           System.out.println("Problem reading csv: " + ioe.getMessage());
           status.setText("There was an error.");
       }
   }
  
   // Sets the property table
   @SuppressWarnings("unchecked")
   private TableView<Property> setTable()

   {
       TableView<Property> table = new TableView<Property>();
      
       TableColumn<Property, String> pidCol = new TableColumn<>("PID");  
        TableColumn<Property, String> catCol = new TableColumn<>("Category");
        TableColumn<Property, String> streetCol = new TableColumn<>("Street Name");
        TableColumn<Property, String> postCol = new TableColumn<>("Postal Code");
        TableColumn<Property, String> currValCol = new TableColumn<>("Current Value");
        TableColumn<Property, String> prevValCol = new TableColumn<>("Previous Value");
        TableColumn<Property, String> yearCol = new TableColumn<>("Year Built");
        table.getColumns().addAll(pidCol, catCol, streetCol, postCol, currValCol, prevValCol, yearCol);
      
        //Tell the columns what getter function to call for their data:
        pidCol.setCellValueFactory(
                new PropertyValueFactory<Property,String>("PID")
           );
      
        catCol.setCellValueFactory(
                new PropertyValueFactory<Property,String>("Category")
           );
      
        streetCol.setCellValueFactory(
                new PropertyValueFactory<Property,String>("StreetName")
           );
      
      
        postCol.setCellValueFactory(
                new PropertyValueFactory<Property,String>("PostalCode")
           );
      
        currValCol.setCellValueFactory(
                new PropertyValueFactory<Property,String>("CurrValue")
           );
      
        prevValCol.setCellValueFactory(
                new PropertyValueFactory<Property,String>("PrevValue")
           );
      
        yearCol.setCellValueFactory(
                new PropertyValueFactory<Property,String>("YearBuilt")
           );
      
       return table;
      
   }


}


PrepareMainDisplays.java

import java.util.List;

import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.scene.chart.BarChart;
import javafx.scene.chart.CategoryAxis;
import javafx.scene.chart.NumberAxis;
import javafx.scene.chart.XYChart;
import javafx.scene.control.TableView;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.text.Font;
import javafx.scene.text.FontWeight;
import javafx.scene.text.Text;


public abstract class PrepareMainDisplays
{
   // Sets the first display: Average property values and standard deviation
   public static VBox setItem1(List<Property> table)
   {
      
       VBox aux = new VBox();
       aux.setStyle("-fx-background-color: #FFFFFF; -fx-alignment: center;");
      
      
       // Average property value
       Text propValue = new Text("Average Property Value:");
       propValue.setFont(Font.font("Arial", FontWeight.NORMAL, 14));
      
       String [] data = PrepareData.getItem1(table).split(" ");
      
       Text propValueNo = new Text("CAD$" + data[0]);
       propValueNo.setFont(Font.font("Arial", FontWeight.BOLD, 20));
       propValueNo.setFill(Color.BLUE);
      
       // Standard deviation
       Text sdText = new Text("Standard Deviation:");
       sdText.setFont(Font.font("Arial", FontWeight.NORMAL, 14));
      
       Text sdValue = new Text("CAD$" + data[1]);
       sdValue.setFont(Font.font("Arial", FontWeight.BOLD, 20));
       sdValue.setFill(Color.DODGERBLUE);
      
       aux.setPadding(new Insets(50));
       aux.setSpacing(10);
      
       aux.getChildren().addAll(propValue,propValueNo,sdText,sdValue);
      
       // Opens a new display in case of double click showing info by street
       aux.setOnMouseClicked(new EventHandler<MouseEvent>() {
          
            @Override
            public void handle(MouseEvent click) {

                if (click.getClickCount() == 2) {

                   PrepareSecondaryDisplays.getInfoByStreet(table,"price");
                }
            }
       });
      
       return aux;
   }
  
   // Sets the second display: Average house age and standard deviation
   public static VBox setItem2(List<Property> table)
   {
       VBox aux = new VBox();
       aux.setStyle("-fx-background-color: #FFFFFF; -fx-alignment: center;");
      
       String [] data = PrepareData.getItem2(table).split(" ");
      
      
       // House age
       Text avgHouseAgeText = new Text("Average House Age:");
       avgHouseAgeText.setFont(Font.font("Arial", FontWeight.NORMAL, 14));
      
       Text avgHouseAgeData = new Text(data[0] + " years");
       avgHouseAgeData.setFont(Font.font("Arial", FontWeight.BOLD, 20));
       avgHouseAgeData.setFill(Color.BLUE);
      
       // Standard deviation
       Text sdText = new Text("Standard Deviation:");
       sdText.setFont(Font.font("Arial", FontWeight.NORMAL, 14));
      
       Text sdData = new Text(data[1] + " years");
       sdData.setFont(Font.font("Arial", FontWeight.BOLD, 20));
       sdData.setFill(Color.DODGERBLUE);
      
       aux.setPadding(new Insets(50));
       aux.setSpacing(10);
      
       aux.getChildren().addAll(avgHouseAgeText,avgHouseAgeData,sdText,sdData);
      
       // Opens a new display in case of double click showing info by street
       aux.setOnMouseClicked(new EventHandler<MouseEvent>() {
          
            @Override
            public void handle(MouseEvent click) {

                if (click.getClickCount() == 2) {
                   PrepareSecondaryDisplays.getInfoByStreet(table,"age");
                }
            }
       });
      
       return aux;
   }

   // Sets the third display: Total house value change
   public static VBox setItem3(List<Property> table)
   {
       VBox aux = new VBox();
       aux.setStyle("-fx-background-color: #FFFFFF; -fx-alignment: center;");
      
       Text houseValueChangeText = new Text("Total House Value Change:");
       houseValueChangeText.setFont(Font.font("Arial", FontWeight.NORMAL, 14));
      
       Text houseValueChangeData = new Text("CAD$" + PrepareData.getItem3(table));
       houseValueChangeData.setFont(Font.font("Arial", FontWeight.NORMAL, 20));
       houseValueChangeData.setFill(Color.GREEN);
      
       aux.setPadding(new Insets(50));
       aux.setSpacing(10);
      
       aux.getChildren().addAll(houseValueChangeText,houseValueChangeData);
      
       // Opens a new display in case of double click showing info by street
       aux.setOnMouseClicked(new EventHandler<MouseEvent>() {

            @Override
            public void handle(MouseEvent click) {

                if (click.getClickCount() == 2) {
                   PrepareSecondaryDisplays.getInfoByStreet(table,"totalValueChange");
                }
            }
       });
      
       return aux;
   }

   // Sets the fourth display: A bar chart showing the types of property
   @SuppressWarnings("unchecked")
   public static VBox setItem4(List<Property> table)
   {
       VBox aux = new VBox();
       aux.setStyle("-fx-background-color: #FFFFFF; -fx-alignment: center;");
      
       String [] data = PrepareData.getItem4(table).split(" ");
      
      
       // Create the bar chart
       final CategoryAxis xAxis = new CategoryAxis();
       final NumberAxis yAxis = new NumberAxis();
      
       final BarChart<String,Number> chart = new BarChart<String,Number>(xAxis,yAxis);
       chart.setTitle("Property Types");
      
       xAxis.setLabel("");
       yAxis.setLabel("N");
      
       XYChart.Series<String,Number> commercial = new XYChart.Series<String,Number>();
       commercial.setName("Commercial");
       commercial.getData().add(new XYChart.Data<String,Number>("",Double.parseDouble(data[0])));
      
       XYChart.Series<String, Number> XYChart.Series<String,Number>();
       oneFam.setName("One Family Dwelling");
       oneFam.getData().add(new XYChart.Data<String,Number>("",Double.parseDouble(data[1])));
      
       XYChart.Series<String, Number> multiFam = new XYChart.Series<String, Number>();
       multiFam.setName("Multi Family Dwelling");
       multiFam.getData().add(new XYChart.Data<String,Number>("",Double.parseDouble(data[2])));
      
        chart.getData().addAll(oneFam,multiFam,commercial);
        chart.setCategoryGap(0);
        chart.setBarGap(0);
        chart.setHorizontalGridLinesVisible(false);
      
       aux.setPadding(new Insets(50));
       aux.setSpacing(10);
      
       aux.getChildren().add(chart);
      
       // Opens a new display in case of double click showing info by street
       aux.setOnMouseClicked(new EventHandler<MouseEvent>() {

            @Override
            public void handle(MouseEvent click) {

                if (click.getClickCount() == 2) {
                   PrepareSecondaryDisplays.getInfoByStreet(table,"houseType");
                }
            }
       });
      
       return aux;
   }
  

   public static HBox setItem5(List<Property> table)
   {
       HBox aux = new HBox();
       aux.setStyle("-fx-background-color: #FFFFFF; -fx-alignment: center;");
      
       // Left: max and min values
       VBox left = new VBox();
       left.setStyle("-fx-background-color: #FFFFFF; -fx-alignment: center;");
      
       String [] data = PrepareData.getItem5(table).split(" ");
      
       // Maximum value
       Text maxValueText = new Text("Maximum Property Value:");
       maxValueText.setFont(Font.font("Arial", FontWeight.NORMAL, 14));
      
       Text maxValueData = new Text("CAD$" + data[0]);
       maxValueData.setFont(Font.font("Arial", FontWeight.NORMAL, 20));
       maxValueData.setFill(Color.DARKBLUE);
      
       // Minimum value
       Text minValueText = new Text("Minimum Property Value:");
       minValueText.setFont(Font.font("Arial", FontWeight.NORMAL, 14));
      
       Text minValueData = new Text("CAD$" + data[1]);
       minValueData.setFont(Font.font("Arial", FontWeight.NORMAL, 20));
       minValueData.setFill(Color.DODGERBLUE);
      
       left.setPadding(new Insets(50));
       left.setSpacing(10);
      
       left.getChildren().addAll(maxValueText,maxValueData,minValueText,minValueData);
      
      
       // Right: table with number of properties by increments in house value
       VBox right = new VBox();
       right.setStyle("-fx-background-color: #FFFFFF; -fx-alignment: center;");
      
       Text tableTitle = new Text("Number of Homes by Value");
       tableTitle.setFont(Font.font("Arial", FontWeight.NORMAL, 14));
      
       final TableView<ValueBracket> houseValues = PrepareData.prepareItem5Table();
       houseValues.setItems(PrepareData.getHouseValueItems(table,Double.parseDouble(data[0])));
      
       right.getChildren().addAll(tableTitle,houseValues);
       right.setPadding(new Insets(50));
       right.setSpacing(10);
      
       aux.getChildren().addAll(left,right);
      
       // Opens a new display in case of double click showing info by street
       aux.setOnMouseClicked(new EventHandler<MouseEvent>() {

            @Override
            public void handle(MouseEvent click) {

                if (click.getClickCount() == 2) {
                   PrepareSecondaryDisplays.getInfoByStreet(table,"maxMin");
                }
            }
       });
      
       return aux;
   }

}

Property.java

// Structure describing a real estate property
public class Property {
  
   // Property ID
   private String PID;
  
   // Category (commercial, one family dwelling, etc)
   private String category;
  
   // Street name
   private String streetName;
  
   // Postal code
   private String postalCode;
  
   // Current property value
   private String currValue;
  
   // Previous property value
   private String prevValue;
  
   // Year it was built
   private String yearBuilt;
  
   // Constructor
   public Property(String PID, String category, String streetName,
                   String postalCode, String currValue, String prevValue,
                   String yearBuilt){
      
       this.PID = PID;
       this.category = category;
       this.streetName = streetName;
       this.postalCode = postalCode;
       this.currValue = currValue;
       this.prevValue = prevValue;
       this.yearBuilt = yearBuilt;
      
   }
  
   // Constructor with no parameters -> error
   public Property()
   {
       this.PID = "ERROR";
       this.category = "ERROR";
       this.streetName = "ERROR";
       this.postalCode = "ERROR";
       this.currValue = "ERROR";
       this.prevValue = "ERROR";
       this.yearBuilt = "ERROR";
      
   }

  
   // GETTERS ***************************************************************
  
   public String getPID() {
       return PID;
   }

   public String getCategory() {
       return category;
   }

   public String getStreetName() {
       return streetName;
   }

   public String getPostalCode() {
       return postalCode;
   }

   public String getCurrValue() {
       return currValue;
   }

   public String getPrevValue() {
       return prevValue;
   }

   public String getYearBuilt() {
       return yearBuilt;
   }
}

PrepareData.java


import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;

import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.PropertyValueFactory;

public abstract class PrepareData {
  
   public static String getItem1(List<Property> table)
   {
      
       double mean = 0;
       double sd = 0;
      
       // Holds all the property values of the current dataset
       ArrayList<Double> values = new ArrayList<Double>();
      
       for (Property p : table)
       {
           try
           {
               if (Double.parseDouble(p.getCurrValue()) > 0) {
                   mean += Double.parseDouble(p.getCurrValue());
                   values.add(Double.parseDouble(p.getCurrValue()));
               }
           } catch (Exception e) {}
       }

       mean /= table.size();
      
       sd = Math.sqrt(differenceOfSquares(values,mean)/values.size());
      
       // Formats number to .2
       double meanRounded = Math.round(mean);
      
       if (meanRounded > mean)
           meanRounded--;
      
       mean = Math.round((mean - meanRounded) * 100);
       mean = (mean / 100) + meanRounded;
      
       // Formats sd to .2
       double sdRounded = Math.round(sd);
      
       if (sdRounded > sd)
           sdRounded--;
      
       sd = Math.round((sd - sdRounded) * 100);
       sd = (sd / 100) + sdRounded;
  
       return "" + mean + " " + sd;
   }
  
   public static String getItem2(List<Property> table)
   {
       double sd;
      
       // Average year is an int instead of a double
       int avgYear = 0;
      
       // Average age = current year - average year
       int mean = 0;
      
       // All years
       ArrayList<Double> values = new ArrayList<Double>();
      
       for (Property p : table)
       {
           if (Integer.parseInt(p.getYearBuilt()) > 0) {
               avgYear += Integer.parseInt(p.getYearBuilt());
               values.add(Double.parseDouble(p.getYearBuilt()));
           }
       }
      
       // In many cases, this information is incomplete
       if (values.size() > 0)
       {
           avgYear /= values.size();
           mean = Calendar.getInstance().get(Calendar.YEAR) - avgYear;
           sd = Math.sqrt(differenceOfSquares(values,avgYear)/values.size());
       }
       else
           sd = 0;
      
       // Formats sd to .2
       double sdRounded = Math.round(sd);
      
       if (sdRounded > sd)
           sdRounded--;
      
       sd = Math.round((sd - sdRounded) * 100);
       sd = (sd / 100) + sdRounded;
      
       return "" + mean + " " + sd;
   }

   // Gets total value change for properties in a list  
   public static String getItem3(List<Property> table)
   {
       // Total current value
       int totalCurr = 0;
      
       // Total previous value
       int totalPrev = 0;
      
       for (Property p : table)
       {
           try
           {
               if (Integer.parseInt(p.getCurrValue()) > 0 &&
                   Integer.parseInt(p.getPrevValue()) > 0) {
                  
                   totalCurr += Integer.parseInt(p.getCurrValue());
                   totalPrev += Integer.parseInt(p.getPrevValue());
               }
           } catch (Exception e) {} // In case of incomplete data, that property is ignored
       }
      
       return "" + (totalCurr-totalPrev);
   }
  
   public static String getItem4(List<Property> table)
   {
      
       // Number of commercial buildings
       int nCommercial = 0;
      
       // Number of one family dwellings
       int nOneFam = 0;
      
       // Number of multi family dwellings
       int nMultiFam = 0;
      
       for (Property p : table)
       {
           if (p.getCategory().contains("Commercial"))
               nCommercial++;
          
           else if (p.getCategory().contains("One"))
               nOneFam++;
          
           else if (p.getCategory().contains("Multiple"))
               nMultiFam++;
       }
      
       return "" + nCommercial + " " + nOneFam + " " + nMultiFam;
   }

   /* Gets maximum and minimum value of properties in a list */
   public static String getItem5(List<Property> table)
   {
       long maxValue = 0;
       long minValue = -99;
      
       // Get max and min value
       for (Property p : table)
       {
           try
           {
               long currValue = Long.parseLong(p.getCurrValue());
               if (currValue > maxValue)
               {
                   maxValue = currValue;
                  
                   if (minValue == -99)
                       minValue = maxValue;
               }
              
               if (currValue > 0 && currValue < minValue)
                   minValue = currValue;
              
           } catch (Exception e) {}   // If data is incomplete, it's just ignored
       }
      
       return "" + maxValue + " " + minValue;
   }

   /* Gets number of properties by increments of 25k in a list */
   public static ObservableList<ValueBracket> getHouseValueItems(List<Property> table, double maxValue)
   {
       ArrayList<ValueBracket> houses = new ArrayList<ValueBracket>();
      
       int [] increments = new int[(int)(maxValue / 25000) + 1];
      
       ArrayList<Double> values = new ArrayList<Double>();
      
       for (Property p : table)
       {
           try
           {
               values.add(Double.parseDouble(p.getCurrValue()));
           }
           catch (Exception e) {} // Incomplete data is ignored
       }
      
       for (double x : values)
       {
           int i = (int) x / 25000;
           increments[i]++;
       }
      
       // Ignores first 100k
       for (int i =4; i<increments.length; i++)
       {
           int min = i * 25;
           int max = (i+1) * 25;
           String sections = min + "k - " + max + "k";
          
           if (increments[i] > 0)
               houses.add(new ValueBracket(sections,increments[i]));
          
           // Stops when it reaches the first empty increment
           else if (!houses.isEmpty())
               break;
       }
      
       return FXCollections.observableList(houses);
   }

  
   /* Prepares table showing number of properties by increments of 25k    */
   public static TableView<ValueBracket> prepareItem5Table()
   {
       final TableView<ValueBracket> houseValues = new TableView<ValueBracket>();
      
       // Two columns: price and n
       final TableColumn<ValueBracket,String> bracket = new TableColumn<ValueBracket,String>("Price (in $CAD)");
       bracket.setCellValueFactory(
                new PropertyValueFactory<>("price")
           );
       bracket.setSortable(false);
      
       final TableColumn<ValueBracket,Integer> nBracket = new TableColumn<ValueBracket,Integer>("N");
       nBracket.setCellValueFactory(
                new PropertyValueFactory<>("n")
           );
       nBracket.setSortable(false);
      
       houseValues.getColumns().addAll(bracket,nBracket);
      
       houseValues.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
      
       return houseValues;
   }
  
   // Used to calculate the standard deviation
   protected static double differenceOfSquares(List<Double> list, double mean)
   {
       double sum = 0;
       for (Double curr : list)
       {
           sum += (curr-mean) * (curr-mean);
       }  
       return sum;
   }

}

Note: due to limited character cant able to post all files

Hire Me For All Your Tutoring Needs
Integrity-first tutoring: clear explanations, guidance, and feedback.
Drop an Email at
drjack9650@gmail.com
Chat Now And Get Quote