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 zcmexhwokYI)W2Q(7#J8#7zMc)Y#9pJ845WVinth<7>d~$O1KzU8A`br${5N)tO|C9 zN-hRYhAJ+GYK9sv2788DE(Sh^I(CM74u&QWvl&FRfTUa58QM4)+PN4y7&^Hax){1a z%6qsNdKvn-82T9|uro~LW)NnWT+hxhg^OV-!!&k==^P9*xESOZib4FDTnw`qW^*yj zVVKLwFpptA2g3p`hJ_4^*cldsq?d9rEMr*C&9H)DB{#z=hSeZq4LieHc7}Bv4C}cV z^cadc7&dS*Y-HF3;%w$%*uur2%dnM;VH?ACRt7L&e!;=8LxPK8C&Mm~n%x`>d)OKF zf^6Bx&ai(oFOwr9S0OvY0d|HGc81Ey5zMZlBI&6mZbkXIt`(WZC7F5YA&E&jsgs>q z^ujXpLNZfA@{6(=85q4788}Nz;C#Wf{G!~%lGGGWgc>2Ati-ZJ{hY+Sbp7CxqRhN> zYeojR!cdsz$-7ug`T5*kL*m2zgIwaB{X_jiCeLFmn*5)|i1#2n!y$Ht!|V)4*cpya z?q!u^c3^OvyplDM&4J+<BZK&4MrLs*9tH=7<LnG4co<GHoZ?|P&EUw$AdIj(B%>(5 z9OMZehBFLj*%{99Fq~(&z{B9q;K9Rik>N5UgW+UFZmG!!c=;z!VzUvr!f=&`;Tpqr z9)=qXHyIg}ppqPunYoT?urnM2X}`tJa2urP4i7^pLl`^5U69~Cc82>P!3T^CI&e)^ z>=JAb86Gh*$V`ssm*HS%ILyQFnBmFf8g_l@rwq^78J_bnykL0A&hUzd;Wfh>c80e+ z4DT4;Pu|EO$<FYBhv6f`vB?)X{1h2JF??ocIKsp5h2bkZ!#5s=?+icK8IJNW{ABpW z!|<Eo&twPA)Ov=$JPiLB{_`+0FfuYSaKdAQhmnbqnVpe^hmn<$jgf&99{TKz>^zJd zjGR1-T#Vd|3|y+koFJfD%*DtcfCxkXq^#8B5*|h#MqWk+(d7JG{ltQToXq6JlFa-( zeHSNv7bivrjpWJunAF8kG(sYtkwG6EATolYljXRTHV1RBVr1lB{Evrm@<xFJjEa*L zxn(!Y@Fg>CE)?9z#Kl%nl$lqO#>ikZc_OzkWAx;6B9cOx`T7AM;oy>@)WlqCc1D58 zh5{m!xkRl4>=|sqshx#^k->q%k%5uHiGhJZpMjBqk%57MRcku~<3<Js1||k)1_lN; zu%IM^3j+fK517r$;L6~}z`(!-N)ilA3{I1`iY}}Nsg+}3XJBBEVc=p=Vi09eW{_e~ zVX$UUVsK_qVMt?8WdNC>#lXTK#h}RG$>7Dn$RNxR%;3%7!@$JA#Sq8f%izbrz>vnk z1eNt?U|@(~;P}s=$-u(S5Wvn5$j%VN&JfJN$j%VV^`C(aEX)8Bbc2ezvoi$$XAodu zV`m5eOE3g8z;!VHXJBGrf|$g>z!1W~zyJyZIR-9JvIKiYT3jFO6)^@-k)X@K%%I1> z$Dq$3!eGE4%b<&-hm#?k!4af~fr0T60~-S`0|UcbArWsOksS=8+Ze=rb})!*?_iMF z#vsYOmqBVLgETXPuMYEG2AORPvc5XU8F+Uy$VCdtZ)Z^0ud|IoaT|luF$U4y40836 zQ0_JcWsu}11{ERIZ47E4z3ST-H2ie8F=*~&&|+k;Vv%Io$)L^1Fq5GS#L{78IKZH5 z#k!k8FH%T<JA;80n<Sf%;SL6)Z4AbetU@N+7)-Y@n29i$=bE!ivI<!u@i`^g#MpN* zSZ!mdx3=PzWE0~AbF8g+K=#|P?q#rzWR~O(j%1PK3EswF7ry*|8z_}9gHuTugD3+7 zgB1fagB=4agFOQegDZmqgByb;gC~P7gBOE2gD-<4gC9dMLkL4OLnuQELl{FVLlnaV zhG>Ra3^5F=7-AWAF~l<*V@P1Azr>Kp@RA{!;SECyILV|ja4}3^h-8Rhh-6@6SjAw^ z5XBJ9z|OFXL7yRpA)0}c;TVH5Lo7oa12@AZ262XXhByWuhE|3Yh6IL0237`UhF1(p z3~}HD{E#7;A%%gFL4n~cLn=6_r7(0dq%&kNFf)LXn=}JU>OTf^c7{xLhAei5Z0WxY z((DX5><qcT7;2DWpNSz4oJH~(8W|WEj2PG$_!z1g8W=bkq!@%5CNXd_s51yNEMeee 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