From 11e9abc5ccde4e85068bc7e5c08a9a5c4eb774e5 Mon Sep 17 00:00:00 2001 From: Eilert Tunheim <emtunhei@stud.ntnu.no> Date: Tue, 29 Mar 2022 14:58:01 +0200 Subject: [PATCH] Updated input popup window and connected the parameters --- .../java/com/application/DB/Constants.java | 31 +++++---- src/main/java/com/application/DB/DB.java | 64 ++++++++---------- src/main/java/com/application/GUI/Input.java | 45 +++++++++--- src/main/java/com/application/Main.java | 4 +- .../com.application/CSS/styleSheet.css | 4 +- .../com/application/Main$1WorkerThread.class | Bin 2263 -> 2263 bytes target/classes/com/application/Main.class | Bin 8974 -> 8949 bytes 7 files changed, 88 insertions(+), 60 deletions(-) diff --git a/src/main/java/com/application/DB/Constants.java b/src/main/java/com/application/DB/Constants.java index 4c7abb9..da40820 100644 --- a/src/main/java/com/application/DB/Constants.java +++ b/src/main/java/com/application/DB/Constants.java @@ -19,17 +19,17 @@ public final class Constants { public static final String TODAYS_DATE = format.format(LocalDateTime.now()); // User inputs - public static final String TREE_SPECIES = ""; - public static final String WIDTH_DIMENTION = ""; - public static final String HEIGHT_DIMENTION = ""; - public static final String SAWSET = ""; - public static final int MOISTURE_GOAL = 0; + public static String TREE_SPECIES = ""; + public static String WIDTH_DIMENTION = ""; + public static String HEIGHT_DIMENTION = ""; + public static String SAWSET = ""; + public static String MOISTURE_GOAL = ""; // Database ID/name public static final String PROJECT_ID = "sf-drying-optimization"; - /* +/* // Location Valasen(124) // Project settings public static final int LOCATION_ID = 124; @@ -38,20 +38,22 @@ public final class Constants { // Parameters settings // Valmatics - public static final String OTHER_PARAMETERS_NAME = "Name"; + 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; + public static int KILIN_ID = 5; // Kammer 5 + //public static int KILIN_ID = 6; // Kammer 6 // 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; + public static final int VALUE_ID = 51; // Kammer 5 + //public static final int VALUE_ID = 56; // Kammer 6 public static final int LIMIT = 1000; - */ + */ @@ -65,12 +67,12 @@ public final class Constants { // Parameters settings // Valmatics - public static final String OTHER_PARAMETERS_NAME = "Name"; + 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 = 18133; + public static int KILIN_ID = 18; + //public static int KILIN_ID = 18554; // Swappconsensordata public static final String KWH_NAME = "RealValue"; @@ -84,4 +86,7 @@ public final class Constants { + + + } diff --git a/src/main/java/com/application/DB/DB.java b/src/main/java/com/application/DB/DB.java index 0392a00..b9539a5 100644 --- a/src/main/java/com/application/DB/DB.java +++ b/src/main/java/com/application/DB/DB.java @@ -9,7 +9,6 @@ import java.io.FileInputStream; import java.text.SimpleDateFormat; import java.util.*; - import static com.application.DB.Constants.*; /** @@ -140,29 +139,12 @@ public class DB { int index = 0; - /* - final String sqlStatement = "SELECT TimeStamp, VariantValue " + - "FROM sf-drying-optimization.124.int_sd_winccsensordata " + - "WHERE TimeStamp BETWEEN \"2021-01-30 08:51:03\" " + - "AND \"2021-02-15 11:10:09\" ORDER BY TimeStamp ASC"; - */ - for (Map.Entry<String, String> entry : getZeroPointDate().entrySet()) { //System.out.printf("Intid: \t%s\t\t\tOuttid: \t%s\n",entry.getKey(),entry.getValue()); // Initializing the data map to store the results Map<String, Number> data = new HashMap<>(); - // Preparing a query statement - /* - final String sqlStatement = "SELECT DISTINCT TimeStamp, VariantValue " + - "FROM `" + PROJECT_ID + "." + LOCATION_ID + "." + TABLE_NAME_KWH + "` " + - "WHERE TimeStamp BETWEEN " + '"'+ entry.getKey() + '"' + - " AND " + '"' + entry.getValue() + '"' + - " ORDER BY TimeStamp ASC"; - - */ - // Preparing a query statement // Query statement 124 Valåsen final String sqlStatement = "SELECT `" + TIMESTAMP_NAME + "`, `"+KWH_NAME+"` " + @@ -174,20 +156,6 @@ public class DB { " ORDER BY " + TIMESTAMP_NAME + " ASC"; - - /* - // Query statement 174 Årjang - final String sqlStatement = - "SELECT Timestamp, RealValue - "FROM `" + PROJECT_ID + "." + LOCATION_ID + "." + TABLE_NAME_KWH + "` " + - "WHERE TimeStamp BETWEEN " + '"'+ entry.getKey() + '"' + - " AND " + '"' + entry.getValue() + '"' + - "AND ValueID = 19 " + - "AND RealValue <> 0 " + - "ORDER BY TimeStamp ASC"; - - */ - System.out.println(sqlStatement); // Iterating through the results @@ -279,10 +247,28 @@ public class DB { // KILIN_ID starts at 0 not 1 in the database. KILIN_ID -= 1; } + // Input parameters + if(!TREE_SPECIES.isEmpty()){ + extraInputParameter += "AND " +NAME_PARAMATERS+ " LIKE "+'"'+"%"+ TREE_SPECIES +"%"+'"'+" "; + } + if(!WIDTH_DIMENTION.isEmpty()){ + extraInputParameter += "AND " +NAME_PARAMATERS+ " LIKE "+'"'+"%"+ WIDTH_DIMENTION +"%"+'"'+" "; + } + if(!HEIGHT_DIMENTION.isEmpty()){ + extraInputParameter += "AND " +NAME_PARAMATERS+ " LIKE "+'"'+"%"+ HEIGHT_DIMENTION +"%"+'"'+" "; + } + if(!SAWSET.isEmpty()){ + extraInputParameter += "AND " +NAME_PARAMATERS+ " LIKE "+'"'+"%"+ SAWSET +"%"+'"'+" "; + } + if(!MOISTURE_GOAL.isEmpty()){ + extraInputParameter += "AND " +NAME_PARAMATERS+ " LIKE "+'"'+"%"+ MOISTURE_GOAL +"%"+'"'+" "; + } + + // Sqlstatement for Valåsen(124) final String sqlStatement = - "SELECT MAX("+OTHER_PARAMETERS_NAME+") as DryingSchedule, MAX("+KILIN_NAME+") as Kiln_ID, " + START_DRYING_NAME + ", MAX("+STOP_DRYING_NAME+") as DryingCompleted " + + "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 + "\" " + @@ -382,10 +368,20 @@ public class DB { } //System.out.printf("%s\t\t\t%s\n",formatedInTidTork,formatedUtTidTork); } + + // Defining a treemap to sort the data incrementally + NavigableMap<String, String> sortedFinalResults = new TreeMap<>(dates); + + for (Map.Entry<String, String> entry : sortedFinalResults.entrySet()) { + System.out.printf("Timestamp: \t%s\t\t\tkWh: \t%s\n",entry.getKey(),entry.getValue()); + } + System.out.printf("Size of dates: %s\n\n", dates.size()); + + // Returns a treemap that sorts the dates incrementally - return new TreeMap<>(dates); + return new TreeMap<>(sortedFinalResults); /* // Defining a treemap to sort through the data diff --git a/src/main/java/com/application/GUI/Input.java b/src/main/java/com/application/GUI/Input.java index 92a1612..d94d71d 100644 --- a/src/main/java/com/application/GUI/Input.java +++ b/src/main/java/com/application/GUI/Input.java @@ -6,9 +6,14 @@ import javafx.scene.control.*; import javafx.scene.layout.*; import javafx.stage.*; +import static com.application.DB.Constants.*; +import com.application.Main; /** * This class handles the popup input window + * + * @author Eilert Tunheim, Karin Pettersen, Mads Arnesen + * @version 1.0 */ public class Input { @@ -24,6 +29,7 @@ public class Input { inputLabel.setId("inputTop"); // Center - Input fields + // Tree species Label treeSpeciesInputLabel = new Label("Tree Species"); treeSpeciesInputLabel.setId("inputLabel"); TextField treeSpeciesInputText = new TextField(); @@ -31,18 +37,28 @@ public class Input { treeSpeciesInputText.setPromptText("Bjørk"); treeSpeciesInputText.getText(); - Label dimensionsInputLabel = new Label("Width x Height"); - dimensionsInputLabel.setId("inputLabel"); - TextField dimensionsInputText = new TextField(); - dimensionsInputText.setId("inputLabelText"); - dimensionsInputText.setPromptText("47 x 150"); - + // Width + Label widthInputLabel = new Label("Width"); + widthInputLabel.setId("inputLabel"); + TextField widthInputText = new TextField(); + widthInputText.setId("inputLabelText"); + widthInputText.setPromptText("47"); + + // Height + Label heightInputLabel = new Label("Height"); + heightInputLabel.setId("inputLabel"); + TextField heightInputText = new TextField(); + heightInputText.setId("inputLabelText"); + heightInputText.setPromptText("200"); + + // Sawset Label sawsetInputLabel = new Label("Sawset"); sawsetInputLabel.setId("inputLabel"); TextField sawsetInputText = new TextField(); sawsetInputText.setId("inputLabelText"); sawsetInputText.setPromptText("4x"); + // Moisture Label moistureGoalInputLabel = new Label("Moisture Goal"); moistureGoalInputLabel.setId("inputLabel"); TextField moistureGoalInputText = new TextField(); @@ -55,13 +71,23 @@ public class Input { startButton.setId("inputButtonStart"); startButton.setOnAction(e -> { - + TREE_SPECIES = treeSpeciesInputText.getText(); + WIDTH_DIMENTION = treeSpeciesInputText.getText(); + HEIGHT_DIMENTION = heightInputText.getText(); + SAWSET = sawsetInputText.getText(); + MOISTURE_GOAL = moistureGoalInputText.getText(); + + // Call på getKwh() + try { + Main.createLineChart(); + } catch (Exception ex) { + ex.printStackTrace(); + } window.close(); }); - VBox layout = new VBox(10); - layout.getChildren().addAll(inputLabel, treeSpeciesInputLabel, treeSpeciesInputText, dimensionsInputLabel, dimensionsInputText, + layout.getChildren().addAll(inputLabel, treeSpeciesInputLabel, treeSpeciesInputText, widthInputLabel, widthInputText, heightInputLabel, heightInputText, sawsetInputLabel, sawsetInputText, moistureGoalInputLabel, moistureGoalInputText, startButton); layout.setAlignment(Pos.CENTER); @@ -69,7 +95,6 @@ public class Input { scene.getStylesheets().add(Input.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 24c69f3..2f19a21 100644 --- a/src/main/java/com/application/Main.java +++ b/src/main/java/com/application/Main.java @@ -87,6 +87,7 @@ public class Main extends Application { this.sideBar.setId("sideBar"); lineChart.setId("lineChart"); + // Sett the menubar in a vbox inorder to stretch over the whole screen VBox vBox = new VBox(this.menuBar); @@ -175,6 +176,7 @@ public class Main extends Application { finish.setId("sideBarButtonFinish"); finish.setOnAction(e -> Input.display()); + // Creating the circular progressbar RingProgressIndicator ringProgressIndicator = new RingProgressIndicator(); ringProgressIndicator.setRingWidth(100); @@ -259,7 +261,7 @@ public class Main extends Application { } - private LineChart<String,Number> createLineChart() throws Exception { + public static LineChart<String,Number> createLineChart() throws Exception { final CategoryAxis xAxis = new CategoryAxis(); final NumberAxis yAxis = new NumberAxis(); diff --git a/src/main/resources/com.application/CSS/styleSheet.css b/src/main/resources/com.application/CSS/styleSheet.css index c6d1365..54b83c3 100644 --- a/src/main/resources/com.application/CSS/styleSheet.css +++ b/src/main/resources/com.application/CSS/styleSheet.css @@ -55,9 +55,9 @@ #inputTop { -fx-alignment: top-center; -fx-font-size: 24; + -fx-font-weight: 700; -fx-font-family: Arial; - -fx-background-color: rgba(12, 76, 81, 1); - -fx-text-fill: white; + -fx-text-fill: rgba(12, 76, 81, 1); -fx-pref-width: 200; } diff --git a/target/classes/com/application/Main$1WorkerThread.class b/target/classes/com/application/Main$1WorkerThread.class index 6d7959dd02c2288d7396e77e03326f2aa0fbfcca..fc1cb79295b938a5ba6bc65d216611f6e1d0be64 100644 GIT binary patch delta 89 zcmcaEcwKOVAv^D022O_E415gx7=#)2Pqt%UX?lc#jo~;0C&N(&E{0<ad<>@;L>SI7 vh%=mKkYG5&Aj5E$L66})gE_-R21kZV3|<VE8GIS8O_t%vVmv>&og)AMCRP{j delta 89 zcmcaEcwKOVAv^DG22O^Z415fG7=#)2PPSuTX?lo(jo~N*C&OU|E`}ovd<-WTL>SI6 vh%=mIkYG5)Aj5E)L66}qgE_-_21kYq3|<Tu8GIS8OqSuuVmv#!og)AMALtjz diff --git a/target/classes/com/application/Main.class b/target/classes/com/application/Main.class index 298f3b433ab54354bbd403aa498e2291efa2336a..80979f33ddbb4b67750a37f6c45e96cd1f729d8e 100644 GIT binary patch delta 2352 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 delta 2386 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 -- GitLab