From 7ca44641b3350bf32d62d3251b109f31677d538d Mon Sep 17 00:00:00 2001
From: emtunhei <emtunhei@stud.ntnu.no>
Date: Mon, 4 Apr 2022 14:05:11 +0200
Subject: [PATCH] Combined searching data from multiple sawmills

---
 .../java/com/application/DB/Constants.java    | 140 +++++---
 src/main/java/com/application/DB/DB.java      | 308 ++++++++++--------
 .../GUI/LineChartFunctionality.java           |   1 -
 src/main/java/com/application/Main.java       |   3 +
 target/classes/com/application/DB/DB.class    | Bin 12956 -> 15877 bytes
 .../com/application/Main$1WorkerThread.class  | Bin 2263 -> 2263 bytes
 target/classes/com/application/Main.class     | Bin 8003 -> 8195 bytes
 7 files changed, 266 insertions(+), 186 deletions(-)

diff --git a/src/main/java/com/application/DB/Constants.java b/src/main/java/com/application/DB/Constants.java
index 0f56afc..0493b05 100644
--- a/src/main/java/com/application/DB/Constants.java
+++ b/src/main/java/com/application/DB/Constants.java
@@ -3,22 +3,18 @@ package com.application.DB;
 import java.time.LocalDateTime;
 import java.time.format.DateTimeFormatter;
 import java.util.HashMap;
-import java.util.Map;
 
 /**
  * This class contains constants to be used related to database activities
  */
 public final class Constants {
 
-    // Format for today's date
-    static DateTimeFormatter format = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
-
     private Constants() {
         // Empty constructor
     }
 
     // Today's date
-    public static final String TODAYS_DATE = format.format(LocalDateTime.now());
+    public static final String TODAYS_DATE = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").format(LocalDateTime.now());
 
     // User inputs
     public static String TREE_SPECIES = "";
@@ -27,79 +23,139 @@ public final class Constants {
     public static  String MOISTURE_GOAL = "";
 
     // Number of wanted drying periods
-
     public static int NUMBER_OF_PERIODS = 1;
 
     // Database ID/name
     public static final String PROJECT_ID = "sf-drying-optimization";
 
 
-
     // Location Valasen(124)
     // Project settings
-    public static final int LOCATION_ID = 124;
-    public static final String TABLE_NAME_VALMATICS = "int_dk_valmaticsdryingbatches_v2";
-    public static final String TABLE_NAME_KWH = "int_sd_winccsensordata";
+    public static final int VALASEN_LOCATION_ID = 124;
+    public static final String VALASEN_TABLE_NAME_VALMATICS = "int_dk_valmaticsdryingbatches_v2";
+    public static final String VALASEN_TABLE_NAME_KWH = "int_sd_winccsensordata";
 
     // Parameters settings
     // Valmatics
-    public static final String NAME_PARAMATERS = "Name";
-    public static final String START_DRYING_NAME = "DryingStarted";
-    public static final String STOP_DRYING_NAME = "CalculatedStop";
-    public static final String KILIN_NAME = "KilnName";
-    public static int KILIN_ID = 5;                 // Kammer 5
-    //public static int KILIN_ID = 6;                 // Kammer 6
-    public static final int LIMIT = 1000;
+    public static final String VALASEN_NAME_PARAMATERS = "Name";
+    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 = 6;                 // Kammer 6
+    public static final int VALASEN_LIMIT = 1000;
 
     // Winccsensordata
-    public static final String KWH_NAME = "VariantValue";
-    public static final String TIMESTAMP_NAME = "Timestamp";
-    public static final String VALUE_ID_NAME = "ValueID";
-    public static final int VALUE_ID = 51;          // Kammer 5
-    //public static final int VALUE_ID = 56;          // Kammer 6
-
-
+    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 = 56;          // Kammer 6
 
 
 
 
 
 
-
-/*
     // Location Arjang(174)
     // Project settings
-    public static final int LOCATION_ID = 174;
-    public static final String TABLE_NAME_VALMATICS = "int_dk_valmaticsdryingbatches";
-    public static final String TABLE_NAME_KWH = "int_sd_swappconsensordata";
+    public static final int ARJANG_LOCATION_ID = 174;
+    public static final String ARJANG_TABLE_NAME_VALMATICS = "int_dk_valmaticsdryingbatches";
+    public static final String ARJANG_TABLE_NAME_KWH = "int_sd_swappconsensordata";
 
     // Parameters settings
     // Valmatics
-    public static final String NAME_PARAMATERS = "Name";
-    public static final String START_DRYING_NAME = "DryingStarted";
-    public static final String STOP_DRYING_NAME = "DryingCompleted";
-    public static final String KILIN_NAME = "KilinId";
-    public static int KILIN_ID = 18;
-    //public static int KILIN_ID = 18554;
-    public static final int LIMIT = 1000;
+    public static final String ARJANG_NAME_PARAMATERS = "Name";
+    public static final String ARJANG_START_DRYING_NAME = "DryingStarted";
+    public static final String ARJANG_STOP_DRYING_NAME = "DryingCompleted";
+    public static final String ARJANG_KILIN_NAME = "KilinId";
+    public static int ARJANG_KILIN_ID = 18;
+    //public static int ARJANG_KILIN_ID = 18554;
+    public static final int ARJANG_LIMIT = 1000;
 
     // Swappconsensordata
-    public static final String KWH_NAME = "RealValue";
-    public static final String TIMESTAMP_NAME = "Timestamp";
-    public static final String VALUE_ID_NAME = "ValueID";
-    public static final int VALUE_ID = 19;
-
+    public static final String ARJANG_KWH_NAME = "RealValue";
+    public static final String ARJANG_TIMESTAMP_NAME = "Timestamp";
+    public static final String ARJANG_VALUE_ID_NAME = "ValueID";
+    public static final int ARJANG_VALUE_ID = 19;
 
- */
 
 
 
+    public static HashMap<Integer, HashMap<String, HashMap<String, String>>> getSawmills(){
+        HashMap<Integer, HashMap<String, HashMap<String, String>>> sawmillInfo = new HashMap<>();
+        sawmillInfo.put(VALASEN_LOCATION_ID, getValasenTables());
+        sawmillInfo.put(ARJANG_LOCATION_ID, getArjangTables());
+        return sawmillInfo;
+    }
 
+    // Valasen
+    private static HashMap<String, HashMap<String, String>> getValasenTables(){
+        HashMap<String, HashMap<String, String>> valasenTables = new HashMap<>();
+        valasenTables.put(getValasenTableNames().get("Valmetics"), getValasenValmeticsParameters());
+        valasenTables.put(getValasenTableNames().get("Kwh"), getValasenWinccsensordataParameters());
+        return valasenTables;
+    }
 
+    public static HashMap<String, String> getValasenTableNames(){
+        HashMap<String, String> valasenTables = new HashMap<>();
+        valasenTables.put("Valmetics", VALASEN_TABLE_NAME_VALMATICS);
+        valasenTables.put("Kwh", VALASEN_TABLE_NAME_KWH);
+        return valasenTables;
+    }
 
+    private static HashMap<String, String> getValasenValmeticsParameters(){
+        HashMap<String, String> valasenValmeticsParameters = new HashMap<>();
+        valasenValmeticsParameters.put("Name", VALASEN_NAME_PARAMATERS);
+        valasenValmeticsParameters.put("DryingStarted", VALASEN_START_DRYING_NAME);
+        valasenValmeticsParameters.put("DryingStopped", VALASEN_STOP_DRYING_NAME);
+        valasenValmeticsParameters.put("KilnName", VALASEN_KILIN_NAME);
+        valasenValmeticsParameters.put("KilinID", String.valueOf(VALASEN_KILIN_ID));
+        valasenValmeticsParameters.put("Limit", String.valueOf(VALASEN_LIMIT));
+        return valasenValmeticsParameters;
+    }
 
+    private static HashMap<String, String> getValasenWinccsensordataParameters(){
+        HashMap<String, String> valasenWinccsensordataParameters = new HashMap<>();
+        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));
+        return valasenWinccsensordataParameters;
+    }
 
+    // Arjang
+    private static HashMap<String, HashMap<String, String>> getArjangTables(){
+        HashMap<String, HashMap<String, String>> arjangTables = new HashMap<>();
+        arjangTables.put(getArjangTableNames().get("Valmetics"), getArjangValmeticsParameters());
+        arjangTables.put(getArjangTableNames().get("Kwh"), getArjangWinccsensordataParameters());
+        return arjangTables;
+    }
 
+    public static HashMap<String, String> getArjangTableNames(){
+        HashMap<String, String> valasenTables = new HashMap<>();
+        valasenTables.put("Valmetics", ARJANG_TABLE_NAME_VALMATICS);
+        valasenTables.put("Kwh", ARJANG_TABLE_NAME_KWH);
+        return valasenTables;
+    }
 
+    private static HashMap<String, String> getArjangValmeticsParameters(){
+        HashMap<String, String> arjangValmeticsParameters = new HashMap<>();
+        arjangValmeticsParameters.put("Name", ARJANG_NAME_PARAMATERS);
+        arjangValmeticsParameters.put("DryingStarted", ARJANG_START_DRYING_NAME);
+        arjangValmeticsParameters.put("DryingStopped", ARJANG_STOP_DRYING_NAME);
+        arjangValmeticsParameters.put("KilnName", ARJANG_KILIN_NAME);
+        arjangValmeticsParameters.put("KilinID", String.valueOf(ARJANG_KILIN_ID));
+        arjangValmeticsParameters.put("Limit", String.valueOf(ARJANG_LIMIT));
+        return arjangValmeticsParameters;
+    }
 
+    private static HashMap<String, String> getArjangWinccsensordataParameters(){
+        HashMap<String, String> arjangWinccsensordataParameters = new HashMap<>();
+        arjangWinccsensordataParameters.put("KwhName", ARJANG_KWH_NAME);
+        arjangWinccsensordataParameters.put("Timestamp", ARJANG_TIMESTAMP_NAME);
+        arjangWinccsensordataParameters.put("ValueIDName", ARJANG_VALUE_ID_NAME);
+        arjangWinccsensordataParameters.put("ValueID", String.valueOf(ARJANG_VALUE_ID));
+        return arjangWinccsensordataParameters;
+    }
 }
diff --git a/src/main/java/com/application/DB/DB.java b/src/main/java/com/application/DB/DB.java
index 70adc81..3116ced 100644
--- a/src/main/java/com/application/DB/DB.java
+++ b/src/main/java/com/application/DB/DB.java
@@ -60,6 +60,8 @@ public class DB {
         //getKwh();
         //getName();
         //getZeroPointDate();
+        System.out.println(setInputParameters());
+
     }
 
 
@@ -125,67 +127,142 @@ public class DB {
 
     }
 
-    public static Map<Integer, Map<String, Number>> setInputParameters() throws Exception {
 
-        // If location is Valasen, then the database stores furu as fura, swedish.
-        if(LOCATION_ID == 124 && TREE_SPECIES.equalsIgnoreCase("Furu")) {
-            TREE_SPECIES = "Fura";
-        }
+    public static Map<Integer, Map<String, Number>> setInputParameters() throws Exception {
+    //public static Map<String, String> setInputParameters() throws Exception {
+        Map<Integer, Map<String, Number>> allDryingPeriods = new TreeMap<>();
 
-        System.out.printf("Tree species: \t%s\n",TREE_SPECIES);
-        System.out.printf("Width: \t\t\t%s\n",DIMENSIONS);
-        System.out.printf("Sawset: \t\t%s\n",SAWSET);
-        System.out.printf("Moisture: \t\t%s\n",MOISTURE_GOAL);
 
         String extraInputParameter = "";
-        String treeSpecies = "AND LOWER(" +NAME_PARAMATERS+ ") LIKE LOWER("+'"'+"%"+ TREE_SPECIES +"%"+'"'+") ";
-        String dimensions = "AND LOWER(" +NAME_PARAMATERS+ ") LIKE LOWER("+'"'+"%"+ DIMENSIONS +"%"+'"'+") ";
-        String sawset = "AND LOWER(" +NAME_PARAMATERS+ ") LIKE LOWER("+'"'+"%"+ SAWSET +"%"+'"'+") ";
-        String moistureGoal = "AND LOWER(" +NAME_PARAMATERS+ ") LIKE LOWER("+'"'+"%"+ MOISTURE_GOAL +"%"+'"'+") ";
+        int locationID = 0;
+        int index = 0;
 
+        // Valmetics parameters
+        String nameParameter = "";
+        String kilinName = "";
+        int kilinID = 0;
+        String startDryingTime = "";
+        String stopDryingTime = "";
+        String valmeticsTableName = "";
+        int limit = 0;
+
+        // Kwh parameters
+        String kwhTableName = "";
+        String KwhName = "";
+        String timestamp = "";
+        String valueIDName = "";
+        int valueID = 0;
+
+        for (HashMap.Entry<Integer, HashMap<String, HashMap<String, String>>> location : Constants.getSawmills().entrySet()) {
+            System.out.printf("\n\nLocation ID: \t%s\t\t\tRest of map: \t%s\n", location.getKey(), location.getValue());
+
+            locationID = location.getKey();
+
+            //System.out.println(location.getValue());
+
+            if (location.getKey() == 124) {
+                // Valmetics
+                valmeticsTableName = getValasenTableNames().get("Valmetics");
+                nameParameter = location.getValue().get(getValasenTableNames().get("Valmetics")).get("Name");
+                startDryingTime = location.getValue().get(getValasenTableNames().get("Valmetics")).get("DryingStarted");
+                stopDryingTime = location.getValue().get(getValasenTableNames().get("Valmetics")).get("DryingStopped");
+                kilinName = location.getValue().get(getValasenTableNames().get("Valmetics")).get("KilnName");
+                kilinID = Integer.parseInt(location.getValue().get(getValasenTableNames().get("Valmetics")).get("KilinID"));
+                limit = Integer.parseInt(location.getValue().get(getValasenTableNames().get("Valmetics")).get("Limit"));
+
+                // Kwh
+                kwhTableName = getValasenTableNames().get("Kwh");
+                KwhName = location.getValue().get(getValasenTableNames().get("Kwh")).get("KwhName");
+                timestamp = location.getValue().get(getValasenTableNames().get("Kwh")).get("Timestamp");
+                valueIDName = location.getValue().get(getValasenTableNames().get("Kwh")).get("ValueIDName");
+                valueID = Integer.parseInt(location.getValue().get(getValasenTableNames().get("Kwh")).get("ValueID"));
+            }
+            if (location.getKey() == 174) {
+                // Valmetics
+                valmeticsTableName = getArjangTableNames().get("Valmetics");
+                nameParameter = location.getValue().get(getArjangTableNames().get("Valmetics")).get("Name");
+                startDryingTime = location.getValue().get(getArjangTableNames().get("Valmetics")).get("DryingStarted");
+                stopDryingTime = location.getValue().get(getArjangTableNames().get("Valmetics")).get("DryingStopped");
+                kilinName = location.getValue().get(getArjangTableNames().get("Valmetics")).get("KilnName");
+                kilinID = Integer.parseInt(location.getValue().get(getArjangTableNames().get("Valmetics")).get("KilinID"));
+                limit = Integer.parseInt(location.getValue().get(getArjangTableNames().get("Valmetics")).get("Limit"));
+
+                // Kwh
+                kwhTableName = getArjangTableNames().get("Kwh");
+                KwhName = location.getValue().get(getArjangTableNames().get("Kwh")).get("KwhName");
+                timestamp = location.getValue().get(getArjangTableNames().get("Kwh")).get("Timestamp");
+                valueIDName = location.getValue().get(getArjangTableNames().get("Kwh")).get("ValueIDName");
+                valueID = Integer.parseInt(location.getValue().get(getArjangTableNames().get("Kwh")).get("ValueID"));
+            }
 
+            // If location is Valasen, then the database stores furu as fura, swedish.
+            if (location.getKey() == 124 && TREE_SPECIES.equalsIgnoreCase("Furu")) {
+                TREE_SPECIES = "Fura";
+            }
 
-        // Input parameters
-        if(!TREE_SPECIES.isEmpty()){
-            extraInputParameter += treeSpecies;
-        }
-        if(!DIMENSIONS.isEmpty()){
-            extraInputParameter += dimensions;
-        }
-        if(!SAWSET.isEmpty()){
-            extraInputParameter += sawset;
-        }
-        if(!MOISTURE_GOAL.isEmpty()){
-            extraInputParameter += moistureGoal;
-        }
+            /*
+            System.out.printf("Tree species: \t%s\n", TREE_SPECIES);
+            System.out.printf("Width: \t\t\t%s\n", DIMENSIONS);
+            System.out.printf("Sawset: \t\t%s\n", SAWSET);
+            System.out.printf("Moisture: \t\t%s\n", MOISTURE_GOAL);
+
+             */
+
+            String treeSpecies = "AND LOWER(" + nameParameter + ") LIKE LOWER(" + '"' + "%" + TREE_SPECIES + "%" + '"' + ") ";
+            String dimensions = "AND LOWER(" + nameParameter + ") LIKE LOWER(" + '"' + "%" + DIMENSIONS + "%" + '"' + ") ";
+            String sawset = "AND LOWER(" + nameParameter + ") LIKE LOWER(" + '"' + "%" + SAWSET + "%" + '"' + ") ";
+            String moistureGoal = "AND LOWER(" + nameParameter + ") LIKE LOWER(" + '"' + "%" + MOISTURE_GOAL + "%" + '"' + ") ";
 
 
+            // Input parameters
+            if (!TREE_SPECIES.isEmpty()) {
+                extraInputParameter += treeSpecies;
+            }
+            if (!DIMENSIONS.isEmpty()) {
+                extraInputParameter += dimensions;
+            }
+            if (!SAWSET.isEmpty()) {
+                extraInputParameter += sawset;
+            }
+            if (!MOISTURE_GOAL.isEmpty()) {
+                extraInputParameter += moistureGoal;
+            }
 
-        Map<Integer, Map<String, Number>> results;
-        while(true){
-            System.out.printf("\nExtra parameters:\n %s\n\n",extraInputParameter);
-            // Retrieves the dates
-            results =  getKwh(getZeroPointDate(extraInputParameter));
-
-            // Checks if any dates where found, if not parameters are removed until dates are found
-            if(results.size()<NUMBER_OF_PERIODS){
-                if(extraInputParameter.contains(sawset)) {
-                    extraInputParameter = extraInputParameter.replace(sawset,"");
-                    System.out.println("Sawset is removed");
-                } else if(extraInputParameter.contains(treeSpecies)) {
-                    extraInputParameter = extraInputParameter.replace(treeSpecies,"");
-                    System.out.println("Tree species is removed");
-                } else if(extraInputParameter.contains(dimensions)) {
-                    extraInputParameter = extraInputParameter.replace(dimensions,"");
-                    System.out.println("Dimensions is removed");
-                } else if(extraInputParameter.contains(moistureGoal)) {
-                    extraInputParameter = extraInputParameter.replace(moistureGoal,"");
-                    System.out.println("Moisture goal is removed");
+            Map<Integer, Map<String, Number>> results = new TreeMap<>();
+
+            while (true) {
+                System.out.printf("\nExtra parameters:\n %s\n\n", extraInputParameter);
+                // Retrieves the dates
+                //results = getKwh(getZeroPointDate(locationID, extraInputParameter, nameParameter, kilinName, kilinID, startDryingTime, stopDryingTime, valmeticsTableName, limit));
+                results = getKwh(getZeroPointDate(locationID, extraInputParameter, nameParameter, kilinName, kilinID, startDryingTime, stopDryingTime, valmeticsTableName, limit),
+                        locationID, kwhTableName, KwhName, timestamp,valueIDName, valueID, index);
+
+                // Checks if any dates where found, if not parameters are removed until dates are found
+                if (results.size() < NUMBER_OF_PERIODS) {
+                    if (extraInputParameter.contains(sawset)) {
+                        extraInputParameter = extraInputParameter.replace(sawset, "");
+                        System.out.println("Sawset is removed");
+                    } else if (extraInputParameter.contains(treeSpecies)) {
+                        extraInputParameter = extraInputParameter.replace(treeSpecies, "");
+                        System.out.println("Tree species is removed");
+                    } else if (extraInputParameter.contains(dimensions)) {
+                        extraInputParameter = extraInputParameter.replace(dimensions, "");
+                        System.out.println("Dimensions is removed");
+                    } else if (extraInputParameter.contains(moistureGoal)) {
+                        extraInputParameter = extraInputParameter.replace(moistureGoal, "");
+                        System.out.println("Moisture goal is removed");
+                    } else break;
                 } else break;
             }
-            else break;
+            allDryingPeriods.putAll(results);
+            index = results.size();
+        }
+        System.out.println(allDryingPeriods.size());
+        for (Map.Entry<Integer, Map<String, Number>> entry : allDryingPeriods.entrySet()) {
+            System.out.printf("Timestamp: \t%s\t\t\tkWh: \t%s\n", entry.getKey(), entry.getValue());
         }
-        return results;
+
+        return allDryingPeriods;
     }
 
 
@@ -195,13 +272,15 @@ public class DB {
      * @return the results
      * @throws Exception returns potential error
      */
-    public static Map<Integer, Map<String, Number>> getKwh(Map<String, String> dates) throws Exception {
+
+    public static Map<Integer, Map<String, Number>> getKwh(Map<String, String> dates, int locationID,
+                                                           String kwhTableName, String KwhName,
+                                                           String timestamp, String valueIDName,
+                                                           int valueID, int index) throws Exception {
 
         // Initializing the data map to store the results
         Map<Integer, Map<String, Number>> finalResults = new HashMap<>();
 
-        int index = 0;
-
         for (Map.Entry<String, String> entry : dates.entrySet()) {
             //System.out.printf("Intid: \t%s\t\t\tOuttid: \t%s\n",entry.getKey(),entry.getValue());
 
@@ -210,13 +289,13 @@ public class DB {
 
             // Preparing a query statement
             // Query statement 124 Valåsen
-            final String sqlStatement = "SELECT `" + TIMESTAMP_NAME + "`, `"+KWH_NAME+"` " +
-                    "FROM `" + PROJECT_ID + "." + LOCATION_ID + "." + TABLE_NAME_KWH + "` " +
-                    "WHERE " + TIMESTAMP_NAME + " BETWEEN " + '"'+ entry.getKey() + '"' +
+            final String sqlStatement = "SELECT `" + timestamp + "`, `" + KwhName + "` " +
+                    "FROM `" + PROJECT_ID + "." + locationID + "." + kwhTableName + "` " +
+                    "WHERE " + timestamp + " BETWEEN " + '"' + entry.getKey() + '"' +
                     " AND " + '"' + entry.getValue() + '"' +
-                    " AND " + VALUE_ID_NAME + " = " + VALUE_ID + " " +
-                    " AND " + KWH_NAME + " <> 0 " +
-                    " ORDER BY " + TIMESTAMP_NAME + " ASC";
+                    " AND " + valueIDName + " = " + valueID + " " +
+                    " AND " + KwhName + " <> 0 " +
+                    " ORDER BY " + timestamp + " ASC";
 
 
             System.out.println(sqlStatement);
@@ -229,46 +308,46 @@ public class DB {
             for (FieldValueList row : result.iterateAll()) {
 
                 // Sets the baseline in order to reset the kWh counter
-                if (baseline == 0){
-                    baseline = row.get(""+KWH_NAME+"").getNumericValue().intValue();
+                if (baseline == 0) {
+                    baseline = row.get("" + KwhName + "").getNumericValue().intValue();
                 }
                 //System.out.println("baseline: "+baseline);
 
                 // kWh value
-                int variantValue = row.get(""+KWH_NAME+"").getNumericValue().intValue()-baseline; //-baseline
+                int variantValue = row.get("" + KwhName + "").getNumericValue().intValue() - baseline; //-baseline
 
                 // Retrieving the wanted data
-                long timeStamp = row.get(""+TIMESTAMP_NAME+"").getTimestampValue() / 1000;
+                long timeStamp = row.get("" + timestamp + "").getTimestampValue() / 1000;
                 // Riktig format, men i string
                 String formatedTimeStamp = getDateFormat().format(timeStamp);
 
                 // Checks for negative values
-                if(variantValue > 0) {
+                if (variantValue > 0) {
                     // Adding the data to a list in order to sort through later
                     data.put(formatedTimeStamp, variantValue);
                 }
 
                 //System.out.printf("Timestamp: \t%s\t\t\tkWh: \t%s\t\t\tBaseline: %s\n",formatedTimeStamp,variantValue,baseline);
                 // Checks if the data is empty
-                }
+            }
 
             System.out.println("Data size: " + data.size());
 
             NavigableMap<String, Number> sortedData = new TreeMap<>(data);
-            if(!sortedData.isEmpty() && sortedData.size()>50) {
-                finalResults.put(index,sortedData);
+            if (!sortedData.isEmpty() && sortedData.size() > 50) {
+                finalResults.put(index, sortedData);
                 index += 1;
             }
         }
 
-        System.out.println("\nFinal results size: "+finalResults.size());
+        System.out.println("\nFinal results size: " + finalResults.size());
 
         // Defining a treemap to sort the data incrementally
         NavigableMap<Integer, Map<String, Number>> sortedFinalResults = new TreeMap<>(finalResults);
 
 
         for (Map.Entry<Integer, Map<String, Number>> entry : sortedFinalResults.entrySet()) {
-            System.out.printf("Timestamp: \t%s\t\t\tkWh: \t%s\n",entry.getKey(),entry.getValue());
+            System.out.printf("Timestamp: \t%s\t\t\tkWh: \t%s\n", entry.getKey(), entry.getValue());
         }
 
         return sortedFinalResults;
@@ -287,59 +366,43 @@ public class DB {
      * @return Returns a treemap that sorts the Start- and End time for each drying period incrementally
      * @throws Exception Throws exception if an error occurs
      */
-    private static Map<String, String> getZeroPointDate(String extraUserInput) throws Exception{
+    private static Map<String, String> getZeroPointDate(int locationID, String extraUserInput, String nameParameter,
+                                                        String kilinName, int kilinID, String startDryingTime,
+                                                        String stopDryingTime, String valmeticsTableName, int limit)
+                                                        throws Exception {
 
         // Initializing the dates map to store the results
         Map<String, String> dates = new HashMap<>();
 
-        // Preparing a query statement
-        /*
-        final String sqlStatement =
-                        "SELECT InTidTork, UtTidTork FROM `sf-drying-optimization.124.int_gs_ds_sipalpackages`" +
-                        "WHERE Tork Like \"%5%\" AND InTidTork BETWEEN \"2021-01-30 08:51:03\" " +
-                                "AND \"2022-03-15 11:10:09\" ORDER BY InTidTork ASC";
-         */
-
 
         // Defining extra parameters if required
         String extraInputParameter = "";
         extraInputParameter += extraUserInput;
-        if(LOCATION_ID == 124){
+        if(locationID == 124){
             extraInputParameter += "AND CalculatedStart BETWEEN \"1990-01-01 00:00:00\" AND \"" + TODAYS_DATE + "\" ";
         }
-        if(LOCATION_ID == 174){
+        if(locationID == 174){
             // KILIN_ID starts at 0 not 1 in the database.
-            KILIN_ID -= 1;
+            kilinID -= 1;
         }
 
-        // Sqlstatement for Valåsen(124)
+
+        // Sqlstatement
         final String sqlStatement =
-                        "SELECT MAX("+ NAME_PARAMATERS +") as DryingSchedule, MAX("+KILIN_NAME+") as Kiln_ID, " + START_DRYING_NAME + ", MAX("+STOP_DRYING_NAME+") as DryingCompleted " +
-                        "FROM `" + PROJECT_ID + "." + LOCATION_ID + "." + TABLE_NAME_VALMATICS + "` " +
-                        "WHERE " + KILIN_NAME + " = " + KILIN_ID + " " +
-                        "AND "+START_DRYING_NAME+" BETWEEN \"1990-01-01 00:00:00\" AND \"" + TODAYS_DATE + "\" " +
-                        "AND "+STOP_DRYING_NAME+" BETWEEN \"1990-01-01 00:00:00\" AND \"" + TODAYS_DATE + "\" " +
+                        "SELECT MAX("+ nameParameter +") as DryingSchedule, MAX("+kilinName+") as Kiln_ID, " + startDryingTime + ", MAX("+stopDryingTime+") as DryingCompleted " +
+                        "FROM `" + PROJECT_ID + "." + locationID + "." + valmeticsTableName + "` " +
+                        "WHERE " + kilinName + " = " + kilinID + " " +
+                        "AND "+startDryingTime+" BETWEEN \"1990-01-01 00:00:00\" AND \"" + TODAYS_DATE + "\" " +
+                        "AND "+stopDryingTime+" BETWEEN \"1990-01-01 00:00:00\" AND \"" + TODAYS_DATE + "\" " +
                                 extraInputParameter +
-                        "AND LOWER(" +NAME_PARAMATERS+ ") NOT LIKE LOWER("+'"'+"%"+ "test" +"%"+'"'+") " +
-                        "Group by "+ START_DRYING_NAME + " " +
-                        "Order by "+ START_DRYING_NAME + " ASC " +
-                        "LIMIT " + LIMIT;
+                        "AND LOWER(" +nameParameter+ ") NOT LIKE LOWER("+'"'+"%"+ "test" +"%"+'"'+") " +
+                        "Group by "+ startDryingTime + " " +
+                        "Order by "+ startDryingTime + " ASC " +
+                        "LIMIT " + limit;
 
         System.out.println(sqlStatement);
 
 
-        /*
-        // Sqlstatement for Årjang(174)
-        final String sqlStatement =
-                        "SELECT MAX(Name) as DryingSchedule, MAX(KilinId)+1 as KilnName, DryingStarted, Max(DryingCompleted) as DryingCompleted\n" +
-                        "FROM `" + PROJECT_ID + "." + LOCATION_ID + "." + TABLE_NAME_VALMATICS + "` " +
-                        "WHERE KilinId = 16  \n" +
-                        "AND DATE(DryingStarted) BETWEEN \"1990-08-17\" AND \"2022-08-17\"\n" +
-                        "AND DATE(DryingCompleted) BETWEEN \"1990-08-17\" AND \"2022-08-17\"\n" +
-                        "Group by DryingStarted\n" +
-                        "Order by DryingStarted desc";
-
-         */
 
         // Retrieves the results from the queryjob
         TableResult result = createQueryJob(sqlStatement);
@@ -440,46 +503,5 @@ public class DB {
 
         // Returns a treemap that sorts the dates incrementally
         return new TreeMap<>(sortedFinalResults);
-
-/*
-        // Defining a treemap to sort through the data
-        NavigableMap<String, String> dataSet = new TreeMap<>(dates);
-
-        // Defining a hashmap to store the final sorted data
-        Map<String, String> sortedDates = new HashMap<>();
-
-        // Iterating through the data in order to find and set a zeropoint for the dates.
-        for (Map.Entry<String, String> entry : dataSet.entrySet()) {
-
-            // Retrieving the entry key and value
-            String inTid = entry.getKey();
-            String utTid = entry.getValue();
-
-            // Format the date to LocalDateTime datatype
-            LocalDateTime date = LocalDateTime.parse(inTid, format);
-            // Creates a future date to compare against one day forward in time
-            LocalDateTime dateNowPlus = date.plusDays(1);
-            String formatedDateNowPlus = format.format(dateNowPlus);
-
-            try {
-                // Retrieves the next entry in the list
-                String next = dataSet.higherEntry(entry.getKey()).getKey();
-
-                // Checks if the next date is longer than 1 day,
-                // if so the current date is the last intidtork date and
-                // is the one we will use in order to reset the kWh.
-                if(next.compareTo(formatedDateNowPlus) > 0){
-                    // Storing the dates that will be used for resetting kWh.
-                    sortedDates.put(inTid,utTid);
-                }
-            } catch (NullPointerException e){
-                // Can't find any more iterations, breaks out of the loop.
-                break;
-            }
-        }
-        // Defining a treemap to sort through the data
-        return new TreeMap<>(sortedDates);
-
- */
     }
-}
\ No newline at end of file
+}
diff --git a/src/main/java/com/application/GUI/LineChartFunctionality.java b/src/main/java/com/application/GUI/LineChartFunctionality.java
index 2aa9836..5d80390 100644
--- a/src/main/java/com/application/GUI/LineChartFunctionality.java
+++ b/src/main/java/com/application/GUI/LineChartFunctionality.java
@@ -53,7 +53,6 @@ public class LineChartFunctionality {
         for (Map.Entry<Integer, Map<String, Number>> entryKwh : userInput.entrySet()) {
             Map data = entryKwh.getValue();
             //System.out.println(data.size());
-
             XYChart.Series<String, Number> newSeries = new XYChart.Series<String, Number>();
             int index = 0;
             for (Object entryData : data.entrySet()) {
diff --git a/src/main/java/com/application/Main.java b/src/main/java/com/application/Main.java
index bd571fe..51c2313 100644
--- a/src/main/java/com/application/Main.java
+++ b/src/main/java/com/application/Main.java
@@ -1,5 +1,6 @@
 package com.application;
 
+import com.application.DB.Constants;
 import com.application.GUI.InputPopUpWindow;
 import com.application.GUI.OutputPopUpWindow;
 import com.application.GUI.RingProgressIndicator;
@@ -121,6 +122,8 @@ public class Main extends Application {
 
         // Displays the input parameters popup window
         InputPopUpWindow.display();
+
+        System.out.println(Constants.getSawmills());
     }
 
     /**
diff --git a/target/classes/com/application/DB/DB.class b/target/classes/com/application/DB/DB.class
index 82478f7c1f0a59ad25689f282837d8015f388f7a..ec94bb2562c0057e24be6028107eec5cfcf34df4 100644
GIT binary patch
literal 15877
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
PF&IpzF{Uv3Fh~LbHjXeD

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

diff --git a/target/classes/com/application/Main$1WorkerThread.class b/target/classes/com/application/Main$1WorkerThread.class
index 85f8b6b57414a54f365625d92ec3237bc2e6d237..8b34aeaa44ad3497f9d1132d6e88cf8bf0cb46f2 100644
GIT binary patch
delta 89
zcmcaEcwKOVAv^C?22O^{415gN7=#(FPqt%UX?ll&jp056C&OI^E{1yyd<>5mL>Qhi
vh%-E9kYISiAj9yKL66}%gE_-X21kZh3|<Vc8GISuO_t%vVthWiog)AMbAB1N

delta 89
zcmcaEcwKOVAv^CS22O?x415fi8H5?GOtxcRX?l}^jo}UhC&MiUE{59-d<^#)L>L}3
vh%-E3kYISoAj9y8L66}HgE_-921kbH3|<T`7<?ICPnO}xVtg{Wog)AMY1tWl

diff --git a/target/classes/com/application/Main.class b/target/classes/com/application/Main.class
index b75fd902a89b66c4ea42cc02d24828f3f32a6494..d2bf5a43d4db88a06915f89a71f9d0b69159cbad 100644
GIT binary patch
delta 3654
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

delta 3441
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
Px{P{^`cM|L38Ov$Yv{cu

-- 
GitLab