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