From db3057c1de1ca173a231eb1d7534fd684ea18338 Mon Sep 17 00:00:00 2001
From: Eilert Tunheim <emtunhei@stud.ntnu.no>
Date: Fri, 22 Apr 2022 11:02:07 +0200
Subject: [PATCH] Implemented linear regression and fixed splitting process
 into two threads

---
 .../java/com/application/DB/Constants.java    |   6 +--
 src/main/java/com/application/DB/DB.java      |  45 ++++++++++++++++++
 .../com/application/GUI/InputPopUpWindow.java |  38 ++++++++++++++-
 .../GUI/LineChartFunctionality.java           |  37 +++++++++-----
 .../com/application/DB/Constants.class        | Bin 6026 -> 5925 bytes
 .../GUI/LineChartFunctionality.class          | Bin 10227 -> 9859 bytes
 6 files changed, 109 insertions(+), 17 deletions(-)

diff --git a/src/main/java/com/application/DB/Constants.java b/src/main/java/com/application/DB/Constants.java
index 7455cef..8ca102c 100644
--- a/src/main/java/com/application/DB/Constants.java
+++ b/src/main/java/com/application/DB/Constants.java
@@ -43,7 +43,7 @@ public final class Constants {
     public static final String VALASEN_START_DRYING_NAME = "DryingStarted";
     public static final String VALASEN_STOP_DRYING_NAME = "CalculatedStop";
     public static final String VALASEN_KILIN_NAME = "KilnName";
-    public static int VALASEN_KILIN_ID = 5;                 // Kammer 5
+    //public static int VALASEN_KILIN_ID = 5;                 // Kammer 5
     //public static int VALASEN_KILIN_ID = 6;                 // Kammer 6
     public static final int VALASEN_LIMIT = 1000;
     public static final ArrayList<Integer> VALASEN_VALMETICS_CHAMBER_IDS = new ArrayList<>(Arrays.asList(5,6));
@@ -52,7 +52,7 @@ public final class Constants {
     public static final String VALASEN_KWH_NAME = "VariantValue";
     public static final String VALASEN_TIMESTAMP_NAME = "Timestamp";
     public static final String VALASEN_VALUE_ID_NAME = "ValueID";
-    public static final int VALASEN_VALUE_ID = 51;          // Kammer 5
+    //public static final int VALASEN_VALUE_ID = 51;          // Kammer 5
     //public static final int VALASEN_VALUE_ID = 56;          // Kammer 6
     public static final ArrayList<Integer> VALASEN_KWH_CHAMBER_IDS = new ArrayList<>(Arrays.asList(51,56));
 
@@ -131,7 +131,7 @@ public final class Constants {
         valasenWinccsensordataParameters.put("KwhName", VALASEN_KWH_NAME);
         valasenWinccsensordataParameters.put("Timestamp", VALASEN_TIMESTAMP_NAME);
         valasenWinccsensordataParameters.put("ValueIDName", VALASEN_VALUE_ID_NAME);
-        valasenWinccsensordataParameters.put("ValueID", String.valueOf(VALASEN_VALUE_ID));
+        //valasenWinccsensordataParameters.put("ValueID", String.valueOf(VALASEN_VALUE_ID));
         //valasenWinccsensordataParameters.put("ValueID", String.valueOf(VALASEN_VALUE_ID));
         return valasenWinccsensordataParameters;
     }
diff --git a/src/main/java/com/application/DB/DB.java b/src/main/java/com/application/DB/DB.java
index c588236..5bd3abf 100644
--- a/src/main/java/com/application/DB/DB.java
+++ b/src/main/java/com/application/DB/DB.java
@@ -319,6 +319,51 @@ public class DB {
     }
 
 
+
+    /**
+     *
+     *
+     * @throws Exception
+     */
+    /*
+    public static void getManualMeasurements() throws Exception {
+
+        // Sqlstatement
+        final String sqlStatement = "";
+
+        System.out.println(sqlStatement);
+
+        // Retrieves the results from the queryjob
+        TableResult result = createQueryJob(sqlStatement);
+
+        //System.out.println("InTidTork\t\t\tUtTidTork");
+        // Iterating through the results
+        for (FieldValueList row : result.iterateAll()) {
+
+            row.get("DryingStarted").getTimestampValue();
+        }
+
+        // Defining a treemap to sort the data incrementally
+        //NavigableMap<String, String> sortedFinalResults = new TreeMap<>(dates);
+
+        System.out.println("\n");
+
+        for (Map.Entry<String, String> entry : sortedFinalResults.entrySet()) {
+            System.out.printf("Intid: \t%s\t\t\tUttid: \t%s\n",entry.getKey(),entry.getValue());
+        }
+
+
+
+        //System.out.printf("Size of dates: %s\n\n", sortedFinalResults.size());
+
+
+        // Returns a treemap that sorts the dates incrementally
+        //return new TreeMap<>(sortedFinalResults);
+    }
+    */
+
+
+
     /**
      * Retrieves information about kWh and the corresponding date
      *
diff --git a/src/main/java/com/application/GUI/InputPopUpWindow.java b/src/main/java/com/application/GUI/InputPopUpWindow.java
index a0ac17b..a6f477a 100644
--- a/src/main/java/com/application/GUI/InputPopUpWindow.java
+++ b/src/main/java/com/application/GUI/InputPopUpWindow.java
@@ -1,5 +1,6 @@
 package com.application.GUI;
 
+import javafx.application.Platform;
 import javafx.collections.FXCollections;
 import javafx.collections.ObservableList;
 import javafx.geometry.Pos;
@@ -9,6 +10,7 @@ import javafx.scene.control.*;
 import javafx.scene.layout.*;
 import javafx.stage.*;
 
+import java.util.Map;
 import java.util.concurrent.*;
 
 import static com.application.DB.Constants.*;
@@ -171,7 +173,7 @@ public class InputPopUpWindow {
 
  */
 
-
+/*
 
                     try {
                         //getData();
@@ -186,6 +188,10 @@ public class InputPopUpWindow {
 
                 );
 
+ */
+
+
+
 
 
 
@@ -215,6 +221,31 @@ public class InputPopUpWindow {
 
  */
 
+                    // Fungerende ny thread!!@@@@@
+                    try{
+                        Thread thread = new Thread(() -> {
+                            try {
+                                // Henter her data fra databasen
+                                Map<Integer, Map<String, Number>> data = setInputParameters();
+                                Platform.runLater(() -> {
+                                    try {
+                                        loadSingleSeries(data);
+                                    } catch (Exception ex) {
+                                        ex.printStackTrace();
+                                    }
+                                });
+                            } catch (Exception ex) {
+                                ex.printStackTrace();
+                            }
+                        });
+                        thread.start();
+
+                    } catch (Exception ex) {
+                        ex.printStackTrace();
+                    }
+                }
+
+        );
 /*
                     // Fungerende ny thread!!@@@@@
                     try{
@@ -239,8 +270,11 @@ public class InputPopUpWindow {
                 }
 
                 );
+        */
+
+
+
 
- */
 
 /*
             class KwhThread implements Runnable  {
diff --git a/src/main/java/com/application/GUI/LineChartFunctionality.java b/src/main/java/com/application/GUI/LineChartFunctionality.java
index d5d3eb9..52057b8 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 javafx.collections.ObservableList;
 import javafx.scene.chart.CategoryAxis;
 import javafx.scene.chart.LineChart;
 import javafx.scene.chart.NumberAxis;
@@ -9,6 +10,7 @@ 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.apache.commons.math3.*;
 
 import java.util.*;
 
@@ -17,7 +19,6 @@ public class LineChartFunctionality {
     private static LineChart<String, Number> lineChart;
     private static CategoryAxis xAxis;
     private static NumberAxis yAxis;
-
     private static final double CONFIDENCE_INTERVAL = 0.90;
 
 
@@ -89,7 +90,9 @@ public class LineChartFunctionality {
 
 
     public static LineChart<String, Number> loadSingleSeries(Map<Integer, Map<String, Number>> userInput) throws Exception {
-        clearLineChart();
+        //clearLineChart();
+        //newSeries.setData(null);
+
 
         Map<Integer, ArrayList<Double>> multiMap = new HashMap<>();
 
@@ -113,12 +116,15 @@ public class LineChartFunctionality {
 
                 // Connect the data to a series
                 newSeries.getData().add(new XYChart.Data<String, Number>(String.valueOf(index), kwhValue));
-                index += 1;
+                index++;
             }
+            //allSeries.add(newSeries);
             updateLineChart(newSeries);
-            lineChart.setOpacity(0.5);
+            //lineChart.setOpacity(1);
         }
 
+        //System.out.println("Series size: "+allSeries.size());
+
         // Stores the data from the confidence interval in a new map
         Map<Integer, ArrayList<Double>> confidenceIntervalData = statistics(multiMap);
 
@@ -132,18 +138,21 @@ public class LineChartFunctionality {
 
 
         // Defines an array to be used for the regression
-        double[][] data = new double[confidenceIntervalData.size()][jMaxSize];
+        double[][] data = new double[confidenceIntervalData.size()*jMaxSize][2];
 
+        int index = 0;
         System.out.println(confidenceIntervalData);
         for (int i = 0; i < confidenceIntervalData.size(); i++) {
 
             ArrayList<Double> list = confidenceIntervalData.get(i);
 
-            System.out.println(list.size());
             for (int j = 0; j < list.size(); j++) {
-                data[i][j] = list.get(j);
+                data[index][0] = i;
+                data[index][1] = list.get(j);
+                index++;
             }
 
+            /*
             for (int j = 0; j < data[i].length; j++) {
                 System.out.println("data[i][j]: "+data[i][j]);
                 if(data[i][j] == 0.0){
@@ -159,11 +168,13 @@ public class LineChartFunctionality {
                     data[i][j] = sum/index;
                 }
             }
+
+             */
         }
 
 
         System.out.println(data.length);
-        System.out.println(data[12][1]);
+        //System.out.println(data[12][1]);
 
         SimpleRegression simpleRegression = new SimpleRegression();
 
@@ -172,23 +183,25 @@ public class LineChartFunctionality {
 
 
         for (double[] datum : data) {
-            System.out.println("");
             for (double v : datum) {
-                System.out.println(v);
+                System.out.println("Data: "+v);
             }
         }
 
 
 
         XYChart.Series<String, Number> regressionSeries = new XYChart.Series<String, Number>();
-        for (int i = 0; i < simpleRegression.getN(); i++) {
+        for (int i = 0; i < confidenceIntervalData.size(); 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)));
         }
         updateLineChart(regressionSeries);
-        lineChart.setOpacity(1);
+        //lineChart.setOpacity(1);
+
+
+
 
         System.out.println("Get R: " + simpleRegression.getR());
         System.out.println("Get getRSquare: " + simpleRegression.getRSquare());
diff --git a/target/classes/com/application/DB/Constants.class b/target/classes/com/application/DB/Constants.class
index 935d57ead8c7405cef6220d66de39651a4d10b64..8bcc60db79a0dd82c0be6154885ac50fd17b0884 100644
GIT binary patch
delta 2167
zcmeCuU#eGs>ff$?3=9k=40pL0EEsy(8Tz;wm_T$t7lSFo1TF>^hKV4NNg&o_5HW>=
zVJb*u8i+HUgJA}Up2@*5i-Tb{2g4i=hPfOJ^Eephb1*F6U|7h-u!vzXCj$$^5)Ou?
z91P1i7?yJ|tl(f+2@+eymCL}wuo`5*8W6FTgJB&9!+H*e4IB&`K?*i;Fl+|VTR0fD
zaxrXU*v`eUgJCC#wF@M?n}cBwh~5h#_JN4~AmRXsILOX$h@Igu7sC;Tqg)Io49D0R
zj!*p9&v;^TBjfJL{!FJf8!}&JV@_d6oy^W<YJHO76c0lYLk<taX@)aA42>XG8AA>u
z17}!bPHt*RW^yqP!&!!NJPef}QD*P*3?7C$5L01t47cp$DO{P{=Xn@TGF;$c@MG|w
z%)xCh6w2Vw!_W*esRcx|GvrK;<c>;+XYgla;0#Jl%n3`(DNW^JNCpWAS5{V5>iYWX
zrlcr%cv$7;S``<wGhF0hxWsUoo#6@(!&QcBJPg+vZtyTzGFUM(Fz_%~Gg$F3*nkLI
z5Mc)*>=_&;OYrD$-{fJq#c-R4A%)@2W`7<#rg{qo1_nh2Nswj+1_n-$W-x8TU<Iaa
zp|l;8wr6l)U|^7BaAdGzU}SJ&U|?WkaAuHXaA9zO^IaJv8QhTM`57b`+>!VK43Z2U
z5Pm(_06_*x22Y3pm@mX2$>4>=7h#ZO@J8Z`GDtG`AX(_kAPEXx21bSeu>L>>NroUK
z^->Iy48cfzX$DD#5HP<U;saR*Nrq4ce-s14kSqvikYtDeYk;U%VvuBrMB*zmNHRnr
z@j)JnM&g4!6obT9VUT2q1@Y^lL8!_g$q<KRA;?GZXbwsMX@II%XOLt_MB;;dl!U|w
zc_<l0KR*K#LkdGG10zEk0|SFG10w??0|SE@tJZb~#*N@mOJ`tU0Oeo?20jKB1_6c)
z22g4OsbXcwWXJ+1hirx%1}28I$=3zU7}F>735uJ-RB<rKGUPJkF)%RXL-j#K3K$rm
zu~Nvu1<Fcb{ZWF}z99RA7+4q>7*ZKH7}6Ld7}6Ou7&74Yaxf?{6r-645-EY3Sjxc3
zPzH6;BSBrp^vME3$SxAW&<_$RhwHCk-~#1au#5hQXiaVtQesS>yi!OR$yde<RcLMi
zi6EQ7$xzKu12%(ESX2|_D>iW0)<OMU%fJOH5<n^#7#Io}n8C8DlkJ67>NhYjFfcQK
z^oTLAGB7YSF>o+6GYB%YFi0`9GAJ{2Accl3Lp_>HKq9CvX@Izdfq_8=YzqSe%O(an
zkS&a0TOcm$fw_!}feTcoft)t^k1%qSOk&_*n9Lx-Foi*bVJea%lo*=O903wRjgn?)
zl(dNGB1Q5{1`dW<41x@^8KfBIAejh?64Yb^5<&JB7efow#D5|_jOmlTMV0Fj$<COe
z70pE;5oG<G3~ktgMGZYzR>OjYfs3IXVk2^d?Pg$#+|I!4ttBKWH2JNl9Ao-q9x-Vo
zm&h`7pt%Gjg6fh^Y%bA2cgYU8OE?(1;F<Or0~-SftP;}P!JxH+L3<m6&gRL>#H8wX
zGnhoO?qx8IWaikxz#1IMBESZscQBZ3XE5K)Ac2q<Fa}9PvItm!XqW;yBn5&XiAWX!
zArK8ypoXMC7$gzNA^@hr3Y^V1GiZPc5lAA_V&Gz6U=U{DV-RByW)NqPV31${6-Y`9
dG7M@Ah74{DmJI0({tO)qVGN86-QdEf2LO>BHUt0w

delta 2329
zcmZ3g*QH;7>ff$?3=9k=43D@NEEy)UGfd)QU;@#TxfskCrf@N^FiZuBOarl|gNPX%
z3^PF@vp}5L91L?n^jr>xc^nM$IT#jjFf8O?Sj54wn1f*n2g6b>hGh)PIT=_OR&X$^
z<X~9E!LXWxVGRevT9DW}u6hO*hV>u=Hh_qY91NQ{7&db-Y~f(o3R19*gJC;}-oe4J
zlZ#;&!)`8yJq&w6tbHKi{TvJjK=eTnaR@{l1`$U<#8D7&jGf^)JHrVshLa4ZxEM?s
zPO~$dVPxPA@po~I432kk44L?|iSg{@8php%0%49mj=`>e@!p<3o__J3E|X1}&WOQ9
z!yJ7=UE@7nm>C!tj5q&hy2{3!!H_xmI;W}iIfnB*3}p-jJPa2YF7hz6f>>1y1&j=w
zVTn1psU?}o#XJm`7%uZL)Ph8ry~{Ir7@9y#g~>YHvXfJ|GP$qtFq~t!%EJ)A5IFe;
zm%UIVLm&@BJIJIC5Yf$0Fj<p3sy>+^kdc8iC^a!BEHS4vm4_i6Bp_T_Sy`#;>#LiR
zqTu0Sm78l-T+GgJjfden!wq(Zn>-A+7;f`0++n!O!(hc=&B(yO!(hW;&BI^|BJ4nf
zJ&15%aO7d|WpHF<5Y9?0OVlqd$;{DrEGkN@^vNtPVPp`@n*5hri2EK7!+nMaJPa8O
z4>wEk*fG^xGB7YGGf0BWW?*381epz{Z5gb=v>lYThtduVjtmS8k_=7^)(ngc&I}9;
zObjjzk_@g4j&QykgCv7Hk~}|yB!dSMUw}c9!4tx-2OA*BAj#kb5diar7$h0Ik@zAE
zk_<jbd{G8YkYB+L@k6rMpFt872@H%3L11%&86+7(kn~A0NHT;X@ueB+B^kny1Y{W`
z8N!haj9`#th-3&vF)#{AKAJ(2AqGjm5`!c|ED|3SvT;a!kVoT@_(Jszk_-t*0xArW
z42ej5RR&3hBqR$#K1@b)PzsWIbp}a>R3yGMgCs*55?_`<5|r%V9`Xxj;AdcB$Y981
zU}VSwWe)~M21W)323D=@42&DWp_t9UzyK;U7#R2%SQrEtau`5~5UhwHmmv?FO!65D
z7?>EcCU*&#F=kIbC?IYMQ^mm`%TUNr#K6E%4Aln_DPdrM#!@K*7bpjU_0Ja;pR6LN
z;tR4<h=GNHfgzQFgCUJUf+3wjgCPTMHwS|fLphqMAdw2Vsg(?z3{_B9O%>EdGBJmN
zgCUnekRgvjiXk7#L=g-VK_b;~6Kfc_K!pI<oeM>@CR++AF=kJW5mK&4_|=%94$V~{
z5o9ws8R{7tKxQy7Fvx&|nt_336NAJC1_lO329Uqmz@l}~&}n4g0+lyV9gPgkU|GZ6
z3`~*R8JNAbgd~L+r6x}l6|WbP6)@hxAij-(JzNW98Z+25DF!wM28JdE4u)n1L53Cv
zDTY=CWrj8eeTEJsziToyqq!R-g6i%TZ0?o=*#ves$Rbdp=s|LLD>MS;3tJ;az$69^
zhRF;P3{x017^WgQLW!Xb%@H6G)F^F-ny4;<9HlcEI2dLz2r|rOkYbpFWFja6QIj4>
z1le0$3>{Dt7mD~WW>0=6f*PHjXf85l=wv|F&&kk*Em+jx!NLHE&ecev(haeZfq|hA
z8l9@h(K&g7s2pSV<n^M`D4D1S%_Xu7J!mfJg}7w$e^F6QL_*pDx0!>Xj{%m?-+_|_
z1H-z>wqk1a9Ge+Tb~BhpvhHOti)7~5!N3|E$s)i8qIWQuZ)dRB%pie~2PHGG0t;jX
za!3jUK@yQH0zx1fW`Y`$0%4FuB#Qu;-r)_kLjzRcfD;pg9s@T61A{OFAA=Z!FoQUQ
p1cL+vsPIx^kYP|`&|}bIFl6vzuw=+)@Mq{@2xDMm=m!^8699jjTjBr!

diff --git a/target/classes/com/application/GUI/LineChartFunctionality.class b/target/classes/com/application/GUI/LineChartFunctionality.class
index 30aa13c4fd74adfb7823e3ea88c92328da5dd2da..07809ca136bbd886e5a43251d3b4cf697a129c50 100644
GIT binary patch
delta 3825
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
E08on?zW@LL

delta 4261
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

-- 
GitLab