diff --git a/.gitignore b/.gitignore index 73205eb351ed0c475081a0122d26b7768fc53a1c..e4505922d167594db040bc20237867ba55e3970b 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,4 @@ /doc/ /contacts.log /addressbook.dat +/src/main/resources/com.application/sf-drying-optimization-1e234ad2b0f4.json diff --git a/pom.xml b/pom.xml index 221d396532975bb209aa47db1d85c44ec971bf1f..e6c30632be74fa49f90a30a1c7e6dfa33c7d6844 100644 --- a/pom.xml +++ b/pom.xml @@ -45,6 +45,7 @@ <artifactId>jblas</artifactId> <version>1.2.4</version> </dependency> + </dependencies> <properties> diff --git a/src/main/java/com/application/DB/Constants.java b/src/main/java/com/application/DB/Constants.java index ccb1facb19eda28314facb4e06f8ae58fd4cfe11..a52c3f91c3aa9fd112481a4983ac79e93fbb6a58 100644 --- a/src/main/java/com/application/DB/Constants.java +++ b/src/main/java/com/application/DB/Constants.java @@ -27,10 +27,13 @@ public final class Constants { public static int NUMBER_OF_PERIODS = 2; // Number of seconds to wait before updating live data, in seconds - public static int NUMBER_OF_SECONDS_LIVE_DATA = 10; + public static int NUMBER_OF_SECONDS_LIVE_DATA = 60; + + // Confidence interval + public static final double CONFIDENCE_INTERVAL = 0.80; // Non linear regression - public static final double ADJUST_REGRESSION = 5.5; + public static final double ADJUST_REGRESSION = 5.0; // Current sawmill settings; public static final String PROJECT_ID = "sf-drying-optimization"; diff --git a/src/main/java/com/application/DB/DB.java b/src/main/java/com/application/DB/DB.java index 42574d67d24a06ba2c196f62e5ef95b8feda1521..513b38d1f0e05ad5af601dada2364a473a63f618 100644 --- a/src/main/java/com/application/DB/DB.java +++ b/src/main/java/com/application/DB/DB.java @@ -1,5 +1,6 @@ package com.application.DB; +import com.application.GUI.NotificationPopUp; import com.google.cloud.bigquery.*; import org.joda.time.DateTime; @@ -28,7 +29,7 @@ public class DB { //getName(); //getZeroPointDate(); //System.out.println(setInputParameters()); - getNoOfChambers(); + //getNoOfChambers(); } diff --git a/src/main/java/com/application/GUI/LineChartFunctionality.java b/src/main/java/com/application/GUI/LineChartFunctionality.java index 98836700a206684aaa85ffedcc236c24b080999a..501eb1460a43fc96348c1ab5cd5665ce87270337 100644 --- a/src/main/java/com/application/GUI/LineChartFunctionality.java +++ b/src/main/java/com/application/GUI/LineChartFunctionality.java @@ -1,5 +1,6 @@ package com.application.GUI; +import com.application.DB.Constants; import com.application.Main; import javafx.scene.chart.CategoryAxis; import javafx.scene.chart.LineChart; @@ -10,70 +11,146 @@ import org.apache.commons.math3.distribution.TDistribution; import org.apache.commons.math3.exception.MathIllegalArgumentException; import org.apache.commons.math3.stat.descriptive.SummaryStatistics; import org.apache.commons.math3.stat.regression.SimpleRegression; +import org.checkerframework.checker.units.qual.A; +import org.jblas.DoubleMatrix; +import org.jblas.Solve; import java.util.*; -import static com.application.DB.Constants.ADJUST_REGRESSION; - public class LineChartFunctionality { private static LineChart<String, Number> lineChart; private static XYChart.Series<String, Number> liveDataSeries; + private static XYChart.Series<String, Number> regressionSeries; + private static XYChart.Series<String, Number> regressionSeriesConfidenceInterval; private static CategoryAxis xAxis; private static NumberAxis yAxis; - private static final double CONFIDENCE_INTERVAL = 0.90; - private static int dataPoints = 0; + private static int dataPointsXAxis = 0; + private static int dataPointsYAxis = 0; private static Map<String, Number> liveData; + private static ArrayList<XYChart.Series<String, Number>> previousData; + private static boolean printRegression; + private static boolean printRegressionConfidenceInterval; + private static boolean printLiveData; + private static boolean printPreviousData; public LineChartFunctionality() { xAxis = new CategoryAxis(); yAxis = new NumberAxis(); lineChart = new LineChart<>(xAxis, yAxis); + lineChart.setTitle("Drying Processes"); + lineChart.setAnimated(false); xAxis.setLabel("Data Points"); xAxis.setAnimated(false); yAxis.setLabel("Kwh"); yAxis.setAnimated(false); - lineChart.setTitle("Drying Processes"); - } + regressionSeries = new XYChart.Series<String, Number>(); + regressionSeriesConfidenceInterval = new XYChart.Series<String, Number>(); + liveDataSeries = new XYChart.Series<String, Number>(); + previousData = new ArrayList<>(); - public static LineChart<String, Number> getLineChart() { - return lineChart; + printRegression = true; + printRegressionConfidenceInterval = true; + printLiveData = true; + printPreviousData = true; } - public static void updateLineChart(XYChart.Series<String, Number> series) { - lineChart.getData().add(series); - series.getNode().setId("dataGraphs"); - lineChart.getStylesheets().add(LineChartFunctionality.class.getResource("/com.application/GUI/graphStyles.css").toExternalForm()); - } - public static void clearLineChart() { - lineChart.getData().clear(); + /** + * Prints the graphs to the line chart + * + * Note: Something wrong when exceeding 8 series, think the next series choose a random series color + */ + public static void printGraphs() { + + System.out.println("Graph size: " + getLineChart().getData().size()); + + + //clearLineChart(); + getLineChart().getData().clear(); + //Collections.singleton(getLineChart().getData().setAll()); + //getLineChart().getData().setAll(); + + System.out.println("Graph size after clear: " + getLineChart().getData().size()); + + //getLineChart().getData().remo + if(printLiveData){ + updateLineChart(getLiveDataSeries()); + } else { + updateLineChart(new XYChart.Series<>()); + } + + if(printRegression){ + updateLineChart(getRegressionSeries()); + } else { + updateLineChart(new XYChart.Series<>()); + } + + if(printRegressionConfidenceInterval){ + updateLineChart(getRegressionSeriesConfidenceInterval()); + } else { + updateLineChart(new XYChart.Series<>()); + } + + if(printPreviousData){ + + // If there are more than 5 series, adds 3 new empty series to keep the color scheme + //int index = getLineChart().getData().size(); + for (int i = 0; i < getPreviousData().size(); i++) { + int index = getLineChart().getData().size(); + //System.out.println(getPreviousData().size()); + if (index % 8 == 0 ){ + System.out.println(getLineChart().getData().size()); + for (int j = 0; j < 3; j++) { + updateLineChart(new XYChart.Series<>()); + //index++; + System.out.println("@@@@@@@"); + } + } + System.out.println("Linechart size: "+getLineChart().getData().size()); + updateLineChart(getPreviousData().get(i)); + //index++; + + } + } } - private static Map<Integer, ArrayList<Double>> statistics(Map<Integer, ArrayList<Double>> multiMap){ + + + private static Map<Integer, ArrayList<Double>> statistics(Map<Integer, ArrayList<Double>> multiMap, boolean CIShadow){ //System.out.println("\n\nMultimap: \n"); for (Map.Entry<Integer, ArrayList<Double>> entry : multiMap.entrySet()) { //System.out.printf("\nIndex: \t%s\t\t\tkWh: \t%s\n", entry.getKey(), entry.getValue()); - if(entry.getValue().size()>1){ + //System.out.println("entry: "+entry); + //if(entry.getValue().size()>1){ SummaryStatistics stats = new SummaryStatistics(); for (double val : entry.getValue()) { stats.addValue(val); } + //System.out.println("Stats: "+stats); + // Calculate 95% confidence interval - double ci = calcMeanCI(stats, CONFIDENCE_INTERVAL); + double ci = calcMeanCI(stats, Constants.CONFIDENCE_INTERVAL); //System.out.println(String.format("Mean: %f", stats.getMean())); double lower = stats.getMean() - ci; double upper = stats.getMean() + ci; - //System.out.println(String.format("Confidence Interval 95%%: %f, %f", lower, upper)); + System.out.println(String.format("Confidence Interval "+Constants.CONFIDENCE_INTERVAL*100+"%%: %f, %f", lower, upper)); // Deletes entries if they are out of bounds with the confidence interval entry.getValue().removeIf(value -> Double.compare(value, lower) < 0 || Double.compare(value, upper) > 0); - } + + if(CIShadow){ + ArrayList<Double> lowerUpperBounds = new ArrayList<>(); + lowerUpperBounds.add(lower); + lowerUpperBounds.add(upper); + multiMap.replace(entry.getKey(), lowerUpperBounds); + } + //} } return multiMap; } @@ -127,8 +204,83 @@ public class LineChartFunctionality { //System.out.println("Series size: "+allSeries.size()); + + + // Finds the end datapoint at the end of each graph + int numberOfGraphs = 0; + + ArrayList<Double> dataArraylistXAxis = new ArrayList<>(); + ArrayList<Double> dataArraylistYAxis = new ArrayList<>(); + + Map<Integer, ArrayList<Double>> endOfGraphPointsXAxis = new HashMap<>(); + Map<Integer, ArrayList<Double>> endOfGraphPointsYAxis = new HashMap<>(); + + for (int i = 0; i < multiMap.size(); i++) { + ArrayList<Double> list = multiMap.get(i); + for (int j = 0; j < list.size(); j++) { + if (numberOfGraphs < list.size()) { + numberOfGraphs = list.size(); + } + if (list.size() < numberOfGraphs) { + + dataArraylistXAxis.add((double) i); + dataArraylistYAxis.add(multiMap.get(i).get(j)); + //System.out.println(tempList); + + numberOfGraphs = list.size(); + } + } + } + dataArraylistXAxis.add((double) multiMap.size()); + dataArraylistYAxis.add(multiMap.get(multiMap.size()-1).get(0)); + + //System.out.println(dataArraylistYAxis); + + + endOfGraphPointsXAxis.put(0,dataArraylistXAxis); + endOfGraphPointsYAxis.put(0,dataArraylistYAxis); + + System.out.println(endOfGraphPointsXAxis); + System.out.println(endOfGraphPointsYAxis); + + Map<Integer, ArrayList<Double>> endOfGraphPointsConfidenceXAxis = statistics(endOfGraphPointsXAxis,false); + Map<Integer, ArrayList<Double>> endOfGraphPointsConfidenceYaxis = statistics(endOfGraphPointsYAxis,false); + + System.out.println("X-axis:"+ endOfGraphPointsConfidenceXAxis); + System.out.println("X-axis size: "+ endOfGraphPointsConfidenceXAxis.size()); + System.out.println("------------"); + System.out.println("Y-axis:"+ endOfGraphPointsConfidenceYaxis); + System.out.println("Y-axis size: "+ endOfGraphPointsConfidenceYaxis.size()); + System.out.println("------------"); + + + dataPointsXAxis = 0; + for (Map.Entry<Integer, ArrayList<Double>> entry : endOfGraphPointsConfidenceXAxis.entrySet()) { + System.out.println("Arraylist: "+ entry.getValue()); + for (int i = 0; i < entry.getValue().size(); i++) { + System.out.println("End of graphs: "+ entry.getValue().get(i)); + dataPointsXAxis += entry.getValue().get(i); + } + } + dataPointsXAxis = dataPointsXAxis /endOfGraphPointsConfidenceXAxis.get(0).size(); + + System.out.println("Datapoints: " + dataPointsXAxis); + + dataPointsYAxis = 0; + for (Map.Entry<Integer, ArrayList<Double>> entry : endOfGraphPointsConfidenceYaxis.entrySet()) { + System.out.println("Arraylist: "+ entry.getValue()); + for (int i = 0; i < entry.getValue().size(); i++) { + System.out.println("End of graphs: "+ entry.getValue().get(i)); + dataPointsYAxis += entry.getValue().get(i); + } + } + dataPointsYAxis = dataPointsYAxis /endOfGraphPointsConfidenceYaxis.get(0).size(); + + System.out.println("Datapoints Y-axis: " + dataPointsYAxis); + + // Stores the data from the confidence interval in a new map - Map<Integer, ArrayList<Double>> confidenceIntervalData = statistics(multiMap); + Map<Integer, ArrayList<Double>> confidenceIntervalData = statistics(multiMap,false); //getNonLinearRegression(confidenceIntervalData); @@ -157,6 +309,13 @@ public class LineChartFunctionality { } } + Map<Integer, ArrayList<Double>> confidenceIntervalShadow = statistics(multiMap,true); + for ( Map.Entry<Integer, ArrayList<Double>> entry : confidenceIntervalShadow.entrySet()) { + for (int i = 0; i < entry.getValue().size(); i++) { + Double doubleData = entry.getValue().get(i); + getRegressionSeriesConfidenceInterval().getData().add(new XYChart.Data<String, Number>(String.valueOf(entry.getKey()), doubleData.intValue())); + } + } System.out.println(data.length); //System.out.println(data[12][1]); @@ -174,53 +333,60 @@ public class LineChartFunctionality { } } - // Finds the end datapoint at the end of each graph - int numberOfGraphs = 0; - ArrayList<Integer> endOfGraphPoints = new ArrayList<>(); - for (int i = 0; i < confidenceIntervalData.size(); i++) { - ArrayList<Double> list = confidenceIntervalData.get(i); - for (int j = 0; j < list.size(); j++) { - if (numberOfGraphs < list.size()) { - numberOfGraphs = list.size(); - } - if (list.size() < numberOfGraphs) { - endOfGraphPoints.add(i); - numberOfGraphs = list.size(); - } - } - } - endOfGraphPoints.add(confidenceIntervalData.size()); - dataPoints = 0; - for (int i = 0; i < endOfGraphPoints.size(); i++) { - dataPoints+=endOfGraphPoints.get(i); - } - dataPoints = dataPoints/endOfGraphPoints.size(); + //updateLineChart(liveDataSeries); - liveDataSeries = new XYChart.Series<String, Number>(); - updateLineChart(liveDataSeries); - - - XYChart.Series<String, Number> regressionSeries = new XYChart.Series<String, Number>(); - for (int i = 0; i <= dataPoints; i++) { + //XYChart.Series<String, Number> regressionSeries = new XYChart.Series<String, Number>(); + for (int i = 0; i <= getDataPointsXAxis(); i++) { // Connect the data to a series //System.out.println(simpleRegression.predict(i)); //regressionSeries.getData().add(new XYChart.Data<String, Number>(String.valueOf(i), simpleRegression.predict(i))); + /* regressionSeries.getData().add(new XYChart.Data<String, Number>( String.valueOf(i), - getNonLinearRegression(confidenceIntervalData, - simpleRegression.getIntercept(), + getNonLinearRegression( + confidenceIntervalData, + getDataPointsYAxis(), + //simpleRegression.getIntercept(), + simpleRegression.getSlope(), + //simpleRegression.getIntercept() + getDataPointsYAxis(), + i, + getDataPointsXAxis() + ))); + + */ + + /* + regressionSeries.getData().add(new XYChart.Data<String, Number>( + String.valueOf(i), + getCubicNonLinearRegression(confidenceIntervalData,i) + )); + + */ + + + + getRegressionSeries().getData().add(new XYChart.Data<String, Number>( + String.valueOf(i), + getNonLinearRegression( + confidenceIntervalData, + Math.sqrt(Math.pow(simpleRegression.getIntercept(),2)), simpleRegression.getSlope(), i, - dataPoints))); + getDataPointsXAxis() + ))); + + } - updateLineChart(regressionSeries); + //updateLineChart(getRegressionSeries()); //lineChart.setOpacity(1); + getPreviousData().clear(); for (Map.Entry<Integer, Map<String, Number>> entryKwh : userInput.entrySet()) { //System.out.println(data.size()); XYChart.Series<String, Number> newSeries = new XYChart.Series<String, Number>(); @@ -234,8 +400,9 @@ public class LineChartFunctionality { newSeries.getData().add(new XYChart.Data<String, Number>(String.valueOf(index), kwhValue)); index++; } + addPreviousData(newSeries); //allSeries.add(newSeries); - updateLineChart(newSeries); + //updateLineChart(newSeries); //lineChart.setOpacity(1); } @@ -252,13 +419,15 @@ public class LineChartFunctionality { System.out.println("Predicted Time: " + simpleRegression.predict(35)); // You can also get the slope and intercept from your data - System.out.println("slope = " + simpleRegression.getSlope()); + System.out.println("Alpha! = " + simpleRegression.getSlope()); System.out.println("intercept = " + simpleRegression.getIntercept()); //simpleRegression.add getTimeLeft(0); + printGraphs(); + return getLineChart(); } @@ -272,30 +441,36 @@ public class LineChartFunctionality { Double kwhValue = entryKwh.getValue().doubleValue(); // Connect the data to a series - liveDataSeries.getData().add(new XYChart.Data<String, Number>(String.valueOf(index), kwhValue)); + getLiveDataSeries().getData().add(new XYChart.Data<String, Number>(String.valueOf(index), kwhValue)); index++; } } public static void getTimeLeft(int liveData){ - int time = 0; + int minutes = 0; + int hours = 0; if(liveData == 0) { - time = getDataPoints()*10; + minutes = getDataPointsXAxis()*10; } else { - time = (getDataPoints()/liveData)*10; + minutes = (getDataPointsXAxis()/liveData)*10; } - if(time > 60){ - time = time/60; - Main.setTimeLeftText(time + " h"); + if(minutes > 60){ + hours = minutes/60; + Main.setTimeLeftText(hours + " h"); + if(hours == 3){NotificationPopUp.displayNotificationWindow("3 Hours Left!");} } else { - Main.setTimeLeftText(time + " min"); + if(minutes == 60){NotificationPopUp.displayNotificationWindow("1 Hours Left!");} + Main.setTimeLeftText(minutes + " min"); + } + if(minutes == 0){ + NotificationPopUp.displayNotificationWindow("Drying Process Finished!"); } } - public static double getNonLinearRegression(Map<Integer, ArrayList<Double>> confidenceIntervalData, double y0, double alpha, double j, int n) { + public static double getNonLinearRegression(Map<Integer, ArrayList<Double>> confidenceIntervalData, double y0, double alpha, double j, double n) { //return Math.exp(intercept+slope*i)/(1+Math.exp(intercept+slope*i)); @@ -308,28 +483,128 @@ public class LineChartFunctionality { } } } + + beta = getDataPointsYAxis()+y0; + //System.out.println("Beta: " +beta); + //System.out.println("y0: "+y0); + + //System.out.println("maxYValue: " + maxYValue); //System.out.println("j*n: "+j/n); - //double p_t = ((beta*maxYValue)/(maxYValue+((beta-maxYValue)*Math.exp(-alpha*(yValue-maxYValue))))); - //double p_t = ((beta* y0)/(y0 +((beta- y0)*Math.exp(-alpha*j/n/(2*Math.PI)))))-y0; //Funker sånn halveis - //double p_t = (beta * y0)/(y0 + (beta - y0)*Math.exp(-intercept*(j/n))); - - double p_t = (((beta * y0))/(y0 +((beta- y0)*Math.exp(-alpha*j/n/(ADJUST_REGRESSION)))))-y0; //Beste til nå + //double p_t = (((beta * y0))/(y0 +((beta- y0)*Math.exp(-alpha*j/n/(ADJUST_REGRESSION)))))-y0; //Beste til nå + double p_t = (((beta * y0))/(y0 +((beta- y0)*Math.exp(-alpha*j/n/((alpha/10))))))-y0; //Beste til nå + //double p_t = (((beta * y0))/(y0 +((beta- y0)*Math.exp(-alpha*(j-n)))))-y0; //Beste til nå + /* System.out.println("---------------------------"); System.out.println("y0: " + y0); System.out.println("Alpha: " + alpha); System.out.println("Beta: " + beta); - System.out.println(p_t); + //System.out.println(p_t); + + */ + + return p_t; } - public static int getDataPoints() { - return dataPoints; + + /** + * Third degree cubic non-linear regression + * + * n = + * + * sumT1 = + * sumT2 = + * sumT3 = + * sumT4 = + * + * sumY = + * sumYxT1= + * sumYxT2 = + * @param confidenceIntervalData Data to process + * @return + */ + public static double getCubicNonLinearRegression(Map<Integer, ArrayList<Double>> confidenceIntervalData, int index){ + + double n = confidenceIntervalData.size(); + //double n = getDataPointsYAxis(); + //System.out.println(n); + + double sumT1 = 0; + double sumT2 = 0; + double sumT3 = 0; + double sumT4 = 0; + + double sumY = 0; + double sumYxT1 = 0; + double sumYxT2 = 0; + + + + for (Map.Entry<Integer, ArrayList<Double>> entry : confidenceIntervalData.entrySet()) { + + sumT1 += entry.getKey(); + sumT2 += Math.pow(entry.getKey(),2); + sumT3 += Math.pow(entry.getKey(),3); + sumT4 += Math.pow(entry.getKey(),4); + + for (int j = 0; j < entry.getValue().size(); j++) { + + sumY += entry.getValue().get(j); + sumYxT1 += entry.getValue().get(j) * entry.getKey(); + sumYxT2 += entry.getValue().get(j) * Math.pow(entry.getKey(), 2); + } + } + + + + +/* + for (Map.Entry<Integer, ArrayList<Double>> entry : confidenceIntervalData.entrySet()) { + + + + for (int j = 0; j < entry.getValue().size(); j++) { + + sumT1 += Math.pow(entry.getValue().get(j), 1); + sumT2 += Math.pow(entry.getValue().get(j), 2); + sumT3 += Math.pow(entry.getValue().get(j), 3); + sumT4 += Math.pow(entry.getValue().get(j), 4); + + sumY += entry.getKey(); + sumYxT1 += entry.getKey() * entry.getValue().get(j); + sumYxT2 += entry.getKey() * Math.pow(entry.getValue().get(j), 2); + } + } + + */ + + + + DoubleMatrix firstMatrix = new DoubleMatrix(new double[][]{{n,sumT1,sumT2},{sumT1,sumT2,sumT3},{sumT2,sumT3,sumT4}}); + DoubleMatrix secondMatrix = new DoubleMatrix( new double[]{sumY, sumYxT1, sumYxT2}); + + + DoubleMatrix solvedMatrix = Solve.solve(firstMatrix,secondMatrix); + //System.out.println(solvedMatrix); + + //return ((solvedMatrix.get(0)) + (solvedMatrix.get(1) * index) + (solvedMatrix.get(2) * Math.pow(index, 2))); + //return ((solvedMatrix.get(1) * index) + (solvedMatrix.get(2) * Math.pow(index, 2)))*(-1); + return ((solvedMatrix.get(1) * index) + (solvedMatrix.get(2) * Math.pow(index, 2))); + + } + + public static int getDataPointsXAxis() { + return dataPointsXAxis; + } + + public static int getDataPointsYAxis() { + return dataPointsYAxis; } public static Map<String, Number> getLiveData() { @@ -339,4 +614,79 @@ public class LineChartFunctionality { public static void setLiveData(Map<String, Number> input) { liveData = input; } + + public static XYChart.Series<String, Number> getLiveDataSeries() { + return liveDataSeries; + } + + public static void setRegressionSeries(XYChart.Series<String, Number> regressionSeries) { + LineChartFunctionality.regressionSeries = regressionSeries; + } + + public static XYChart.Series<String, Number> getRegressionSeries() { + return regressionSeries; + } + + public static boolean isPrintRegression() { + return printRegression; + } + + public static void setPrintRegression(boolean printRegression) { + LineChartFunctionality.printRegression = printRegression; + } + + public static boolean isPrintRegressionConfidenceInterval() { + return printRegressionConfidenceInterval; + } + + public static void setPrintRegressionConfidenceInterval(boolean printRegressionConfidenceInterval) { + LineChartFunctionality.printRegressionConfidenceInterval = printRegressionConfidenceInterval; + } + + public static boolean isPrintLiveData() { + return printLiveData; + } + + public static void setPrintLiveData(boolean printLiveData) { + LineChartFunctionality.printLiveData = printLiveData; + } + + public static boolean isPrintPreviousData() { + return printPreviousData; + } + + public static void setPrintPreviousData(boolean printPreviousData) { + LineChartFunctionality.printPreviousData = printPreviousData; + } + + public static ArrayList<XYChart.Series<String, Number>> getPreviousData() { + return previousData; + } + + public static void addPreviousData(XYChart.Series<String, Number> previousData) { + LineChartFunctionality.previousData.add(previousData); + } + + public static XYChart.Series<String, Number> getRegressionSeriesConfidenceInterval() { + return regressionSeriesConfidenceInterval; + } + + public static void setRegressionSeriesConfidenceInterval(XYChart.Series<String, Number> regressionSeriesConfidenceInterval) { + LineChartFunctionality.regressionSeriesConfidenceInterval = regressionSeriesConfidenceInterval; + } + + public static LineChart<String, Number> getLineChart() { + return lineChart; + } + + public static void updateLineChart(XYChart.Series<String, Number> series) { + getLineChart().getData().add(series); + series.getNode().setId("dataGraphs"); + getLineChart().getStylesheets().add(LineChartFunctionality.class.getResource("/com.application/GUI/graphStyles.css").toExternalForm()); + } + + public static void clearLineChart() { + getLineChart().getData().clear(); + //lineChart.getData(). + } } diff --git a/src/main/java/com/application/GUI/NotificationPopUp.java b/src/main/java/com/application/GUI/NotificationPopUp.java new file mode 100644 index 0000000000000000000000000000000000000000..7359602fe9f91010895655f3f9edce2136ddd71f --- /dev/null +++ b/src/main/java/com/application/GUI/NotificationPopUp.java @@ -0,0 +1,37 @@ +package com.application.GUI; + +import javafx.geometry.Pos; +import javafx.scene.Scene; +import javafx.scene.control.Button; +import javafx.scene.control.Label; +import javafx.scene.layout.VBox; +import javafx.stage.Modality; +import javafx.stage.Stage; + +public class NotificationPopUp { + + public static void displayNotificationWindow(String message){ + + Stage window = new Stage(); + window.initModality(Modality.APPLICATION_MODAL); + window.setTitle("Notification window"); + + Label messageLabel = new Label(); + messageLabel.setText(message); + + Button close = new Button("Close"); + close.setOnAction(event -> window.close()); + + VBox layout = new VBox(10); + layout.setAlignment(Pos.CENTER); + layout.getChildren().addAll(messageLabel,close); + + Scene scene = new Scene(layout, 300, 200); + scene.getStylesheets().add(InputPopUpWindow.class.getResource("/com.application/CSS/styleSheet.css").toExternalForm()); + window.setScene(scene); + window.showAndWait(); + } + +} + + diff --git a/src/main/java/com/application/Main.java b/src/main/java/com/application/Main.java index b795ec3dd57730f274660ee66ea94c309ac7b5c7..fedf56036e82856bc5f62a56a680d54e34341c2f 100644 --- a/src/main/java/com/application/Main.java +++ b/src/main/java/com/application/Main.java @@ -8,6 +8,7 @@ import com.application.GUI.LineChartFunctionality; import javafx.application.Application; import javafx.application.Platform; +import javafx.geometry.Pos; import javafx.scene.chart.LineChart; import javafx.scene.control.*; import javafx.scene.image.Image; @@ -16,6 +17,7 @@ import javafx.scene.layout.*; import javafx.scene.Scene; import javafx.stage.Stage; +import javax.naming.LimitExceededException; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; @@ -24,7 +26,7 @@ import java.util.logging.Logger; import static com.application.DB.Constants.*; import static com.application.DB.HelpingFunctions.*; import static com.application.DB.HelpingFunctions.isLoadedData; -import static com.application.GUI.LineChartFunctionality.getDataPoints; +import static com.application.GUI.LineChartFunctionality.getDataPointsXAxis; import static com.application.GUI.LineChartFunctionality.getLiveData; import static java.util.logging.Level.SEVERE; @@ -36,11 +38,13 @@ import static java.util.logging.Level.SEVERE; */ public class Main extends Application { + private LineChartFunctionality lineChartFunctionality; + private BorderPane topBar; private HBox logoBar; private VBox sideBar; private MenuBar menuBar; - private LineChartFunctionality lineChartFunctionality; + private HBox bottomBar; private static TextField treeSpeciesText; private static TextField dimensionsText; @@ -68,11 +72,12 @@ public class Main extends Application { super.init(); // Initializing variables + this.lineChartFunctionality = new LineChartFunctionality(); this.topBar = new BorderPane(); this.logoBar = new HBox(); this.sideBar = new VBox(); this.menuBar = new MenuBar(); - this.lineChartFunctionality = new LineChartFunctionality(); + this.bottomBar = new HBox(); } /** @@ -90,6 +95,7 @@ public class Main extends Application { this.sideBar = createSideBar(); this.logoBar = createLogoBar(); + LineChart<String, Number> lineChart = LineChartFunctionality.getLineChart(); //Set id's to connect to css stylesheet @@ -97,6 +103,8 @@ public class Main extends Application { this.logoBar.setId("logoBar"); this.menuBar.setId("menuBar"); this.sideBar.setId("sideBar"); + this.bottomBar = createBottomBar(); + this.bottomBar.setId("bottomBar"); lineChart.setId("lineChart"); @@ -111,6 +119,7 @@ public class Main extends Application { root.setTop(this.topBar); root.setLeft(this.sideBar); root.setCenter(lineChart); + root.setBottom(this.bottomBar); VBox.setVgrow(this.logoBar, Priority.ALWAYS); @@ -251,7 +260,7 @@ public class Main extends Application { rpi.setProgress(progress); }); - progress = getLiveData().size()/getDataPoints(); + progress = getLiveData().size()/ getDataPointsXAxis()*100; if (progress > 100) { break; @@ -305,6 +314,71 @@ public class Main extends Application { return new HBox(imageViewM, region1, imageViewTitle, region2); } + private HBox createBottomBar(){ + HBox hBox = new HBox(); + + Label liveDataText = new Label("View Live Data"); + CheckBox liveDataBox = new CheckBox(); + liveDataBox.setSelected(true); + liveDataBox.setOnAction(event -> { + if(liveDataBox.isSelected()){ + LineChartFunctionality.setPrintLiveData(true); + LineChartFunctionality.printGraphs(); + + } else { + LineChartFunctionality.setPrintLiveData(false); + LineChartFunctionality.printGraphs(); + } + }); + + Label regressionText = new Label("View Regression"); + CheckBox regressionBox = new CheckBox(); + regressionBox.setSelected(true); + regressionBox.setOnAction(event -> { + if(regressionBox.isSelected()){ + LineChartFunctionality.setPrintRegression(true); + LineChartFunctionality.printGraphs(); + + } else { + LineChartFunctionality.setPrintRegression(false); + LineChartFunctionality.printGraphs(); + } + }); + + Label regressionConfidenceIntervalText = new Label("View Regression Shadow"); + CheckBox regressionConfidenceIntervalBox = new CheckBox(); + regressionConfidenceIntervalBox.setSelected(true); + regressionConfidenceIntervalBox.setOnAction(event -> { + if(regressionConfidenceIntervalBox.isSelected()){ + LineChartFunctionality.setPrintRegressionConfidenceInterval(true); + LineChartFunctionality.printGraphs(); + } else { + LineChartFunctionality.setPrintRegressionConfidenceInterval(false); + LineChartFunctionality.printGraphs(); + } + }); + + Label previousText = new Label("View Previous Data"); + CheckBox previousBox = new CheckBox(); + previousBox.setSelected(true); + previousBox.setOnAction(event -> { + if(previousBox.isSelected()){ + LineChartFunctionality.setPrintPreviousData(true); + LineChartFunctionality.printGraphs(); + } else { + LineChartFunctionality.setPrintPreviousData(false); + LineChartFunctionality.printGraphs(); + } + }); + + + hBox.getChildren().addAll(liveDataText, liveDataBox, regressionText, regressionBox, regressionConfidenceIntervalText, regressionConfidenceIntervalBox, previousText, previousBox); + hBox.setAlignment(Pos.CENTER_RIGHT); + hBox.setSpacing(5); + + return hBox; + } + @@ -327,6 +401,10 @@ public class Main extends Application { public static void setTimeLeftText(String moistureGoalText) { Main.timeLeftText.setText(moistureGoalText); } + + public LineChartFunctionality getLineChartFunctionality() { + return lineChartFunctionality; + } } diff --git a/src/main/resources/com.application/CSS/styleSheet.css b/src/main/resources/com.application/CSS/styleSheet.css index 70d9445d4fce81779c39abcc8e07c3b966ab826c..278e82918bec639cf5a468a90c1da76834953170 100644 --- a/src/main/resources/com.application/CSS/styleSheet.css +++ b/src/main/resources/com.application/CSS/styleSheet.css @@ -23,6 +23,7 @@ */ #sideBar { -fx-pref-width: 250; + -fx-pref-height: infinity; } #sideBarLabel { @@ -74,6 +75,22 @@ -fx-text-fill: white; } +/* + BottomBar styling + */ +#bottomBar { + -fx-pref-width: infinity; + -fx-pref-height: 50; +} + +#bottomBarButtons { + -fx-alignment: center-right; + -fx-tile-alignment: center-right; + -fx-translate-x: -5; + -fx-pref-width: 150; + -fx-pref-height: 25; +} + /* Input popup window */ diff --git a/src/main/resources/com.application/GUI/graphStyles.css b/src/main/resources/com.application/GUI/graphStyles.css index ce64d11a6212e471d83818c65688d7718b717114..455fbb9ab2596ef8f94c786b6088f4cfe4873912 100644 --- a/src/main/resources/com.application/GUI/graphStyles.css +++ b/src/main/resources/com.application/GUI/graphStyles.css @@ -4,20 +4,25 @@ -fx-effect: null; } +.chart-earlier-data-line { + -fx-stroke-width: 1px; + -fx-effect: null; +} + .default-color0.chart-series-line{-fx-stroke: red; -fx-opacity: 1.0} .default-color1.chart-series-line{-fx-stroke: green; -fx-opacity: 1.0} -.default-color2.chart-series-line{-fx-stroke: rgba(0,168,355,0.3); -fx-opacity: 0.1} -.default-color3.chart-series-line{-fx-stroke: rgba(0,168,355,0.3); -fx-opacity: 0.1} -.default-color4.chart-series-line{-fx-stroke: rgba(0,168,355,0.3); -fx-opacity: 0.1} -.default-color5.chart-series-line{-fx-stroke: rgba(0,168,355,0.3); -fx-opacity: 0.1} -.default-color6.chart-series-line{-fx-stroke: rgba(0,168,355,0.3); -fx-opacity: 0.1} -.default-color7.chart-series-line{-fx-stroke: rgba(0,168,355,0.3); -fx-opacity: 0.1} +.default-color2.chart-earlier-data-line{-fx-stroke: black; -fx-opacity: 0.1} +.default-color3.chart-earlier-data-line{-fx-stroke: rgba(0,168,355,0.3); -fx-opacity: 0.1} +.default-color4.chart-earlier-data-line{-fx-stroke: rgba(0,168,355,0.3); -fx-opacity: 0.1} +.default-color5.chart-earlier-data-line{-fx-stroke: rgba(0,168,355,0.3); -fx-opacity: 0.1} +.default-color6.chart-earlier-data-line{-fx-stroke: rgba(0,168,355,0.3); -fx-opacity: 0.1} +.default-color7.chart-earlier-data-line{-fx-stroke: rgba(0,168,355,0.3); -fx-opacity: 0.1} .default-color0.chart-line-symbol{-fx-background-color: red,red;} .default-color1.chart-line-symbol{-fx-background-color: green,green;} -.default-color2.chart-line-symbol{-fx-background-color: rgba(0,168,355,0.3),rgba(0,168,355,0.3);} -.default-color3.chart-line-symbol{-fx-background-color: rgba(0,168,355,0.3),rgba(0,168,355,0.3);} -.default-color4.chart-line-symbol{-fx-background-color: rgba(0,168,355,0.3),rgba(0,168,355,0.3);} -.default-color5.chart-line-symbol{-fx-background-color: rgba(0,168,355,0.3),rgba(0,168,355,0.3);} -.default-color6.chart-line-symbol{-fx-background-color: rgba(0,168,355,0.3),rgba(0,168,355,0.3);} -.default-color7.chart-line-symbol{-fx-background-color: rgba(0,168,355,0.3),rgba(0,168,355,0.3);} +.default-color2.chart-line-symbol{-fx-background-color: black,white;} +.default-color3.chart-line-symbol{-fx-background-color: rgba(0,168,355,0.3),white;} +.default-color4.chart-line-symbol{-fx-background-color: rgba(0,168,355,0.3),white;} +.default-color5.chart-line-symbol{-fx-background-color: rgba(0,168,355,0.3),white;} +.default-color6.chart-line-symbol{-fx-background-color: rgba(0,168,355,0.3),white;} +.default-color7.chart-line-symbol{-fx-background-color: rgba(0,168,355,0.3),white;} diff --git a/target/classes/com.application/CSS/styleSheet.css b/target/classes/com.application/CSS/styleSheet.css index 70d9445d4fce81779c39abcc8e07c3b966ab826c..278e82918bec639cf5a468a90c1da76834953170 100644 --- a/target/classes/com.application/CSS/styleSheet.css +++ b/target/classes/com.application/CSS/styleSheet.css @@ -23,6 +23,7 @@ */ #sideBar { -fx-pref-width: 250; + -fx-pref-height: infinity; } #sideBarLabel { @@ -74,6 +75,22 @@ -fx-text-fill: white; } +/* + BottomBar styling + */ +#bottomBar { + -fx-pref-width: infinity; + -fx-pref-height: 50; +} + +#bottomBarButtons { + -fx-alignment: center-right; + -fx-tile-alignment: center-right; + -fx-translate-x: -5; + -fx-pref-width: 150; + -fx-pref-height: 25; +} + /* Input popup window */ diff --git a/target/classes/com.application/GUI/graphStyles.css b/target/classes/com.application/GUI/graphStyles.css index bbef3d52ce4941ae4c58f31aa59e4f0e8b31486e..455fbb9ab2596ef8f94c786b6088f4cfe4873912 100644 --- a/target/classes/com.application/GUI/graphStyles.css +++ b/target/classes/com.application/GUI/graphStyles.css @@ -4,20 +4,25 @@ -fx-effect: null; } -.default-color0.chart-series-line{-fx-stroke: green; -fx-opacity: 1.0} -.default-color1.chart-series-line{-fx-stroke: rgba(0,168,355,0.3); -fx-opacity: 0.1} -.default-color2.chart-series-line{-fx-stroke: rgba(0,168,355,0.3); -fx-opacity: 0.1} -.default-color3.chart-series-line{-fx-stroke: rgba(0,168,355,0.3); -fx-opacity: 0.1} -.default-color4.chart-series-line{-fx-stroke: rgba(0,168,355,0.3); -fx-opacity: 0.1} -.default-color5.chart-series-line{-fx-stroke: rgba(0,168,355,0.3); -fx-opacity: 0.1} -.default-color6.chart-series-line{-fx-stroke: rgba(0,168,355,0.3); -fx-opacity: 0.1} -.default-color7.chart-series-line{-fx-stroke: rgba(0,168,355,0.3); -fx-opacity: 0.1} +.chart-earlier-data-line { + -fx-stroke-width: 1px; + -fx-effect: null; +} + +.default-color0.chart-series-line{-fx-stroke: red; -fx-opacity: 1.0} +.default-color1.chart-series-line{-fx-stroke: green; -fx-opacity: 1.0} +.default-color2.chart-earlier-data-line{-fx-stroke: black; -fx-opacity: 0.1} +.default-color3.chart-earlier-data-line{-fx-stroke: rgba(0,168,355,0.3); -fx-opacity: 0.1} +.default-color4.chart-earlier-data-line{-fx-stroke: rgba(0,168,355,0.3); -fx-opacity: 0.1} +.default-color5.chart-earlier-data-line{-fx-stroke: rgba(0,168,355,0.3); -fx-opacity: 0.1} +.default-color6.chart-earlier-data-line{-fx-stroke: rgba(0,168,355,0.3); -fx-opacity: 0.1} +.default-color7.chart-earlier-data-line{-fx-stroke: rgba(0,168,355,0.3); -fx-opacity: 0.1} -.default-color0.chart-line-symbol{-fx-background-color: green,green;} -.default-color1.chart-line-symbol{-fx-background-color: rgba(0,168,355,0.3),rgba(0,168,355,0.3);} -.default-color2.chart-line-symbol{-fx-background-color: rgba(0,168,355,0.3),rgba(0,168,355,0.3);} -.default-color3.chart-line-symbol{-fx-background-color: rgba(0,168,355,0.3),rgba(0,168,355,0.3);} -.default-color4.chart-line-symbol{-fx-background-color: rgba(0,168,355,0.3),rgba(0,168,355,0.3);} -.default-color5.chart-line-symbol{-fx-background-color: rgba(0,168,355,0.3),rgba(0,168,355,0.3);} -.default-color6.chart-line-symbol{-fx-background-color: rgba(0,168,355,0.3),rgba(0,168,355,0.3);} -.default-color7.chart-line-symbol{-fx-background-color: rgba(0,168,355,0.3),rgba(0,168,355,0.3);} +.default-color0.chart-line-symbol{-fx-background-color: red,red;} +.default-color1.chart-line-symbol{-fx-background-color: green,green;} +.default-color2.chart-line-symbol{-fx-background-color: black,white;} +.default-color3.chart-line-symbol{-fx-background-color: rgba(0,168,355,0.3),white;} +.default-color4.chart-line-symbol{-fx-background-color: rgba(0,168,355,0.3),white;} +.default-color5.chart-line-symbol{-fx-background-color: rgba(0,168,355,0.3),white;} +.default-color6.chart-line-symbol{-fx-background-color: rgba(0,168,355,0.3),white;} +.default-color7.chart-line-symbol{-fx-background-color: rgba(0,168,355,0.3),white;} diff --git a/target/classes/com/application/DB/Constants.class b/target/classes/com/application/DB/Constants.class index 02c56a821341bc307e15807c05b63c49702bfc51..baab2e803b66b6756e559d63ec15e8f4a94e25b9 100644 Binary files a/target/classes/com/application/DB/Constants.class and b/target/classes/com/application/DB/Constants.class differ diff --git a/target/classes/com/application/DB/DB.class b/target/classes/com/application/DB/DB.class index 26a1f36fce1a238184b8a29e8cb4e0d4a150c8f8..5c58c7b89d7fff8a3e2b14f0002b918b5e5f5fb3 100644 Binary files a/target/classes/com/application/DB/DB.class and b/target/classes/com/application/DB/DB.class differ diff --git a/target/classes/com/application/GUI/InputPopUpWindow.class b/target/classes/com/application/GUI/InputPopUpWindow.class index 037171ffa7925880946ed5def0d7a08388321c3e..9842a47d800e544997e151418ed15de64d8ee3d9 100644 Binary files a/target/classes/com/application/GUI/InputPopUpWindow.class and b/target/classes/com/application/GUI/InputPopUpWindow.class differ diff --git a/target/classes/com/application/GUI/LineChartFunctionality.class b/target/classes/com/application/GUI/LineChartFunctionality.class index 125b40b88613c6967a6c7d4b98232326c6796831..57aee1313539f1ad355d32cb846c027cee1bed12 100644 Binary files a/target/classes/com/application/GUI/LineChartFunctionality.class and b/target/classes/com/application/GUI/LineChartFunctionality.class differ diff --git a/target/classes/com/application/GUI/NotificationPopUp.class b/target/classes/com/application/GUI/NotificationPopUp.class new file mode 100644 index 0000000000000000000000000000000000000000..a641aa4f3a2fbca07b4a00092023747f9151dd14 Binary files /dev/null and b/target/classes/com/application/GUI/NotificationPopUp.class differ diff --git a/target/classes/com/application/Main$1WorkerThread.class b/target/classes/com/application/Main$1WorkerThread.class index 8764a06752f05b58c77755135c22afadf0c8bbf2..2e6f24c9e60fd26fd07531bdb7b2189fc12d020b 100644 Binary files a/target/classes/com/application/Main$1WorkerThread.class and b/target/classes/com/application/Main$1WorkerThread.class differ diff --git a/target/classes/com/application/Main.class b/target/classes/com/application/Main.class index b9e38140f6b49fd482603f5b043ca7205cbe4856..f118b6220aa918d8330fbdac3923da893dda2b49 100644 Binary files a/target/classes/com/application/Main.class and b/target/classes/com/application/Main.class differ