From 79653c5110dfbf2f82032523caf6cf7da3701e34 Mon Sep 17 00:00:00 2001
From: Eilert Tunheim <emtunhei@stud.ntnu.no>
Date: Fri, 4 Mar 2022 13:57:55 +0100
Subject: [PATCH] Updated DB

---
 src/main/java/com/application/DB/DB.java   | 102 +++++++++++++--------
 src/main/java/com/application/Main.java    |  34 +++----
 target/classes/com/application/DB/DB.class | Bin 5822 -> 7024 bytes
 target/classes/com/application/Main.class  | Bin 7336 -> 7537 bytes
 4 files changed, 77 insertions(+), 59 deletions(-)

diff --git a/src/main/java/com/application/DB/DB.java b/src/main/java/com/application/DB/DB.java
index b46727f..0413224 100644
--- a/src/main/java/com/application/DB/DB.java
+++ b/src/main/java/com/application/DB/DB.java
@@ -2,28 +2,30 @@ package com.application.DB;
 
 import com.google.auth.oauth2.GoogleCredentials;
 import com.google.auth.oauth2.ServiceAccountCredentials;
-import com.google.cloud.bigquery.BigQuery;
-import com.google.cloud.bigquery.BigQueryOptions;
-import com.google.cloud.bigquery.FieldValueList;
-import com.google.cloud.bigquery.Job;
-import com.google.cloud.bigquery.JobInfo;
-import com.google.cloud.bigquery.QueryJobConfiguration;
-import com.google.cloud.bigquery.TableResult;
-import com.sun.media.jfxmedia.AudioClip;
-import org.apache.commons.codec.binary.Hex;
+import com.google.cloud.bigquery.*;
 
 import java.io.File;
 import java.io.FileInputStream;
-import java.math.BigDecimal;
-import java.nio.charset.StandardCharsets;
 import java.text.SimpleDateFormat;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Date;
-import java.util.TimeZone;
+import java.util.*;
 
+/**
+ * This class is responsible for handling database related activities
+ *
+ * @author Eilert Tunheim, Karin Pettersen, Mads Arnesen
+ * @version 1.0
+ */
 public class DB {
 
+    private static Map<String, Number> data;
+    private static QueryJobConfiguration queryConfig;
+    private static Job queryJob;
+
+    /**
+     * Retrieves the credentials file
+     * @return
+     * @throws Exception
+     */
     private static GoogleCredentials getCredentials() throws Exception {
         File credentialsPath = new File("./src/main/resources/com.application/sf-drying-optimization-1e234ad2b0f4.json");
 
@@ -37,31 +39,31 @@ public class DB {
         return credentials;
     }
 
-    // Step 1: Initialize BigQuery service
-    // Here we set our project ID and get the `BigQuery` service object
-    // this is the interface to our BigQuery instance that
-    // we use to execute jobs on
+
+    /**
+     * Creates a builder
+     * @return a builder
+     * @throws Exception returns potential error
+     */
     private static BigQuery getBuilder() throws Exception {
+        // Step 1: Initialize BigQuery service
+        // Here we set our project ID and get the `BigQuery` service object
+        // this is the interface to our BigQuery instance that
+        // we use to execute jobs on
         return BigQueryOptions.newBuilder().
                 setCredentials(getCredentials()).
                 setProjectId("sf-drying-optimization")
                 .build().getService();
     }
 
-    public static void getFromExistingTable() throws Exception {
-
-        //ArrayList<String, Integer> results = new ArrayList<>();
-
-        // Step 2: Prepare query job
-        // A "QueryJob" is a type of job that executes SQL queries
-        // we create a new job configuration from our SQL query and
-        final String GET_WORD_COUNT = "SELECT InTidTork, UtTidTork " +
-                "FROM sf-drying-optimization.124.int_gs_ds_sipalpackages " +
-                "WHERE Tork LIKE \"%5%\" AND InTidTork BETWEEN \"2020-05-14 12:51:03\" " +
-                "AND \"2022-03-03 16:10:09\" ORDER BY InTidTork";
-                        QueryJobConfiguration queryConfig =
-                QueryJobConfiguration.newBuilder(GET_WORD_COUNT).build();
 
+    /**
+     * Creates a job
+     * @param queryConfig query configuration information
+     * @return a job
+     * @throws Exception returns potential error
+     */
+    private static Job getJob(JobConfiguration queryConfig) throws Exception {
         // Step 3: Run the job on BigQuery
         // create a `Job` instance from the job configuration using the BigQuery service
         // the job starts executing once the `create` method executes
@@ -77,6 +79,31 @@ public class DB {
         if (queryJob.getStatus().getError() != null) {
             throw new Exception(queryJob.getStatus().getError().toString());
         }
+        return queryJob;
+    }
+
+
+    /**
+     * Retrieves information about kwh and the corresponding date
+     *
+     * @return the results
+     * @throws Exception returns potential error
+     */
+    public static Map<String, Number> getKwh() throws Exception {
+
+        // Initializing a data
+        data = new HashMap<>();
+
+        // Preparing a query job
+        final String sqlStatement = "SELECT TimeStamp, VariantValue " +
+                "FROM sf-drying-optimization.124.int_sd_winccsensordata " +
+                "WHERE TimeStamp BETWEEN \"2021-01-25 08:51:03\" " +
+                "AND \"2021-03-04 11:10:09\" ORDER BY TimeStamp";
+
+        // Creates a job configuration
+        queryConfig = QueryJobConfiguration.newBuilder(sqlStatement).build();
+
+        queryJob = getJob(queryConfig);
 
         // Step 4: Display results
         // Print out a header line, and iterate through the
@@ -89,13 +116,14 @@ public class DB {
 
             SimpleDateFormat newFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
             newFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
-            long inTidTork = row.get("InTidTork").getTimestampValue()/1000;
-            long utTidTork = row.get("UtTidTork").getTimestampValue()/1000;
+            long timeStamp = row.get("TimeStamp").getTimestampValue()/1000;
+            String formatedTimeStamp = newFormat.format(timeStamp);
+
+            int variantValue = row.get("VariantValue").getNumericValue().intValue();
 
-            String formatedInTidTork = newFormat.format(inTidTork);
-            String formatedUtTidTork = newFormat.format(utTidTork);
-            System.out.printf("%s\t\t\t\t\t%s\n", formatedInTidTork, formatedUtTidTork);
+            data.put(formatedTimeStamp, variantValue);
 
         }
+        return data;
     }
 }
\ No newline at end of file
diff --git a/src/main/java/com/application/Main.java b/src/main/java/com/application/Main.java
index cceaf4d..eb012b3 100644
--- a/src/main/java/com/application/Main.java
+++ b/src/main/java/com/application/Main.java
@@ -24,7 +24,7 @@ import javafx.scene.chart.XYChart;
 import java.io.FileInputStream;
 import java.io.FileNotFoundException;
 import java.io.IOException;
-import java.util.Objects;
+import java.util.*;
 
 /**
  * This class launches the application
@@ -38,7 +38,7 @@ public class Main extends Application {
     private HBox menuBar;
     private HBox logoBar;
     private VBox sideBar;
-    private LineChart lineChart;
+    private LineChart<String, Number> lineChart;
     private MenuBar menubar2;
 
     /**
@@ -99,8 +99,6 @@ public class Main extends Application {
 
         VBox.setVgrow(this.logoBar, Priority.ALWAYS);
 
-        DB.getFromExistingTable();
-
         // Sets the scene and defines boundaries
         //Scene scene = new Scene(root, 1200, 600);
         Scene scene = new Scene(root, 1200, 600);
@@ -187,31 +185,23 @@ public class Main extends Application {
     }
 
 
-    private LineChart<String,Number> createLineChart() {
+    private LineChart<String,Number> createLineChart() throws Exception {
 
         final CategoryAxis xAxis = new CategoryAxis();
         final NumberAxis yAxis = new NumberAxis();
-        xAxis.setLabel("Month");
+        xAxis.setLabel("Date");
+
         final LineChart<String, Number> lineChart =
-                new LineChart<String, Number>(xAxis, yAxis);
+                new LineChart<>(xAxis, yAxis);
+
+        lineChart.setTitle("Drying Process");
 
-        lineChart.setTitle("Stock Monitoring, 2010");
+        Map<String, Number> map = DB.getKwh();
+        Map<String, Number> treeMap = new TreeMap<>(map);
 
         XYChart.Series series1 = new XYChart.Series();
-        series1.setName("Portfolio 1");
-
-        series1.getData().add(new XYChart.Data("Jan", 23));
-        series1.getData().add(new XYChart.Data("Feb", 14));
-        series1.getData().add(new XYChart.Data("Mar", 15));
-        series1.getData().add(new XYChart.Data("Apr", 24));
-        series1.getData().add(new XYChart.Data("May", 34));
-        series1.getData().add(new XYChart.Data("Jun", 36));
-        series1.getData().add(new XYChart.Data("Jul", 22));
-        series1.getData().add(new XYChart.Data("Aug", 45));
-        series1.getData().add(new XYChart.Data("Sep", 43));
-        series1.getData().add(new XYChart.Data("Oct", 17));
-        series1.getData().add(new XYChart.Data("Nov", 29));
-        series1.getData().add(new XYChart.Data("Dec", 25));
+        series1.setName("Drying 1");
+        treeMap.forEach((key, value) -> series1.getData().add(new XYChart.Data(key,value)));
 
         lineChart.getData().add(series1);
         return lineChart;
diff --git a/target/classes/com/application/DB/DB.class b/target/classes/com/application/DB/DB.class
index 54d5fed9c7c08e1745ce5b53aa191eb9caf3b723..556fc2cc052661cde9e807016e45a7abe5275738 100644
GIT binary patch
delta 3053
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

delta 1898
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
axWvfE(7?jU(8bWf(7+(c(9h5d;sXFrL6*q?

diff --git a/target/classes/com/application/Main.class b/target/classes/com/application/Main.class
index 7f5dd8be87f89da0ee1c433c2fab6350574ae043..a7169948028a77353b46f51b3ae3f03584f5233d 100644
GIT binary patch
delta 3217
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
JMrK7uB>>qvpy&Vq

delta 3138
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
U4RQkmBf}pCW`@5E{}}!Q0PP!^I{*Lx

-- 
GitLab