From 2f57272b9483bb90c4d539705e8f86da7f664b9c Mon Sep 17 00:00:00 2001 From: emtunhei <emtunhei@stud.ntnu.no> Date: Fri, 25 Mar 2022 09:02:26 +0100 Subject: [PATCH] Updated DB functions withb new sql statements --- .idea/misc.xml | 2 +- src/main/java/com/application/DB/DB.java | 176 +++++++++++------- src/main/java/com/application/Main.java | 6 +- target/classes/com/application/DB/DB.class | Bin 11473 -> 9884 bytes .../com/application/Main$1WorkerThread.class | Bin 2263 -> 2263 bytes target/classes/com/application/Main.class | Bin 8444 -> 8168 bytes 6 files changed, 114 insertions(+), 70 deletions(-) diff --git a/.idea/misc.xml b/.idea/misc.xml index d2b574f..e582eaa 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -10,7 +10,7 @@ <component name="ProjectKey"> <option name="state" value="project://e2804f05-5315-4fc6-a121-c522a6c26470" /> </component> - <component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="true" project-jdk-name="1.8" project-jdk-type="JavaSDK"> + <component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="true" project-jdk-name="corretto-1.8" project-jdk-type="JavaSDK"> <output url="file://$PROJECT_DIR$/out" /> </component> </project> \ No newline at end of file diff --git a/src/main/java/com/application/DB/DB.java b/src/main/java/com/application/DB/DB.java index f65225d..3cb57f0 100644 --- a/src/main/java/com/application/DB/DB.java +++ b/src/main/java/com/application/DB/DB.java @@ -16,12 +16,15 @@ import java.util.*; * This class is responsible for handling database related activities * * @author Eilert Tunheim, Karin Pettersen, Mads Arnesen - * @version 1.0 + * @version 1.1 */ public class DB { - private static Job queryJob; - + /** + * Creates a simple date format to use for converting millis in numbers to a usefull date format + * + * @return returns the date format + */ private static SimpleDateFormat getDateFormat() { SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); dateFormat.setTimeZone(TimeZone.getTimeZone("UTC")); @@ -47,6 +50,13 @@ public class DB { return credentials; } + + /** + * Launching the functions + * + * @param args default param + * @throws Exception throws exception in case of error + */ public static void main(String[] args) throws Exception { getKwh(); //getName(); @@ -55,7 +65,7 @@ public class DB { /** - * Creates a builder + * Creates a bigquery builder * * @return a builder * @throws Exception returns potential error @@ -98,6 +108,24 @@ public class DB { return queryJob; } + /** + * This function creates a query job that uses the query statement + * in order to retrieve information from the database + * + * @param sqlStatement input for the query statement + * @return returns the queryjob with the results + * @throws Exception Throws exception in case of error + */ + private static TableResult createQueryJob(String sqlStatement) throws Exception { + + // Creates a job configuration + Job queryJob = getJob(QueryJobConfiguration.newBuilder(sqlStatement).build()); + + // Retrieves the results from the queryjob + return queryJob.getQueryResults(); + + } + /** * Retrieves information about kWh and the corresponding date @@ -126,21 +154,43 @@ public class DB { Map<String, Number> data = new HashMap<>(); // Preparing a query statement + /* final String sqlStatement = "SELECT DISTINCT TimeStamp, VariantValue " + "FROM sf-drying-optimization.124.int_sd_winccsensordata " + "WHERE TimeStamp BETWEEN " + '"'+ entry.getKey() + '"' + " AND " + '"' + entry.getValue() + '"' + - " ORDER BY TimeStamp ASC";// Preparing a query statement + " ORDER BY TimeStamp ASC"; - //System.out.println(sqlStatement); + */ - // Creates a job configuration - queryJob = getJob(QueryJobConfiguration.newBuilder(sqlStatement).build()); + // Preparing a query statement + // Query statement 124 Valåsen + final String sqlStatement = "SELECT `TimeStamp`, `VariantValue` " + + "FROM `sf-drying-optimization.124.int_sd_winccsensordata` " + + "WHERE TimeStamp BETWEEN " + '"'+ entry.getKey() + '"' + + " AND " + '"' + entry.getValue() + '"' + + " AND ValueID = 51" + + " ORDER BY TimeStamp ASC"; + + + /* + // Query statement 174 Årjang + final String sqlStatement = + "SELECT Timestamp, RealValue FROM `sf-drying-optimization.174.int_sd_swappconsensordata` " + + "WHERE TimeStamp BETWEEN " + '"'+ entry.getKey() + '"' + + " AND " + '"' + entry.getValue() + '"' + + "AND ValueID = 14 " + + "AND RealValue <> 0 " + + "ORDER BY TimeStamp ASC"; + + */ + + System.out.println(sqlStatement); // Iterating through the results - TableResult result = queryJob.getQueryResults(); - //System.out.println("Timestamp \t kWh"); + TableResult result = createQueryJob(sqlStatement); + //System.out.println("Timestamp \t kWh"); int baseline = 0; for (FieldValueList row : result.iterateAll()) { @@ -151,7 +201,7 @@ public class DB { //System.out.println("baseline: "+baseline); // kWh value - int variantValue = row.get("VariantValue").getNumericValue().intValue()-baseline; + int variantValue = row.get("VariantValue").getNumericValue().intValue(); //-baseline // Retrieving the wanted data long timeStamp = row.get("TimeStamp").getTimestampValue() / 1000; @@ -159,19 +209,25 @@ public class DB { String formatedTimeStamp = getDateFormat().format(timeStamp); // Checks for negative values and unresonable large values - if(variantValue > 0 && variantValue < 5000000){ + if(variantValue > 0){ //&& variantValue < 5000000){ // 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()) { + if(!sortedData.isEmpty() && sortedData.size()>50) { finalResults.put(index,sortedData); index += 1; } } + + System.out.println("\nFinal results size: "+finalResults.size()); + // Defining a treemap to sort through the data NavigableMap<Integer, Map> sortedFinalResults = new TreeMap<>(finalResults); @@ -180,53 +236,11 @@ public class DB { System.out.printf("Timestamp: \t%s\t\t\tkWh: \t%s\n",entry.getKey(),entry.getValue()); } + return sortedFinalResults; } - /** - * Retrieves information about kWh and the corresponding date - * - * @throws Exception returns potential error - */ - public static void getName() throws Exception { - - // Initializing the data map to store the results - Map<Object,ArrayList<Object>> data = new HashMap<>(); - - - // Preparing a query statement - final String sqlStatement = - "SELECT Name, CalculatedStart, CalculatedStop FROM `sf-drying-optimization.124.int_dk_valmaticsdryingbatches`" + - "WHERE Name Like \"%Gran%\" AND Name Like \"%3ex%\" AND NAME Like \"%47x150%\" AND DATE(CalculatedStart) " + - "BETWEEN \"2018-08-17\" AND \"2022-08-30\" ORDER BY DATE(CalculatedStart)"; - - // Creates a job configuration - queryJob = getJob(QueryJobConfiguration.newBuilder(sqlStatement).build()); - - // Iterating through the results - TableResult result = queryJob.getQueryResults(); - System.out.println("Name\tCalculatedStarted\tCalculatedStop"); - for (FieldValueList row : result.iterateAll()) { - - // Retrieving the wanted data - String name = row.get("Name").getStringValue(); - // The dates are returned as a 16-digit number that needs to be formatted - long calculatedStart = row.get("CalculatedStart").getTimestampValue()/1000; - long calculatedStop = row.get("CalculatedStop").getTimestampValue()/1000; - // Formatting the dates - String formattedCalculatedStart = getDateFormat().format(calculatedStart); - String formattedCalculatedStop = getDateFormat().format(calculatedStop); - - java.sql.Timestamp timestamp = new Timestamp(calculatedStart); - //System.out.println(timestamp); - - System.out.printf("%s\t\t\t%s\t\t\t%s\n",name, formattedCalculatedStart, formattedCalculatedStop); - - } - //return data; - } - /** * This function retrieves the intidtork and uttidtork dates from the database. * This variables are not sorted and thus this function iterates through the data in order to @@ -249,19 +263,43 @@ public class DB { 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"; + */ + + + // Sqlstatement for Valåsen(124) + final String sqlStatement = + "SELECT MAX(Name) as DryingSchedule, MAX(KilnName) as Kiln_name, DryingStarted, Max(CalculatedStop) as CalculatedStop\n" + + "FROM `sf-drying-optimization.124.int_dk_valmaticsdryingbatches` \n" + + "WHERE KilnName = 5 \n" + + "AND DATE(DryingStarted) BETWEEN \"1990-08-17\" AND \"2022-08-17\"\n" + + "AND DATE(CalculatedStop) BETWEEN \"1990-08-17\" AND \"2022-08-17\"\n" + + "AND DATE(CalculatedStart) BETWEEN \"1990-08-17\" AND \"2022-08-17\"\n" + + "Group by DryingStarted\n" + + "Order by DryingStarted ASC"; - // Creates a job configuration - queryJob = getJob(QueryJobConfiguration.newBuilder(sqlStatement).build()); + + /* + // Sqlstatement for Årjang(174) + final String sqlStatement = + "SELECT MAX(Name) as DryingSchedule, MAX(KilinId)+1 as KilnName, DryingStarted, Max(DryingCompleted) as DryingCompleted\n" + + "FROM `sf-drying-optimization.174.int_dk_valmaticsdryingbatches` \n" + + "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 = queryJob.getQueryResults(); + TableResult result = createQueryJob(sqlStatement); //System.out.println("InTidTork\t\t\tUtTidTork"); - // Iterating through the results for (FieldValueList row : result.iterateAll()) { @@ -270,18 +308,19 @@ public class DB { String formatedUtTidTork; // Retrieving the data - // InTidTork: - if(!row.get("InTidTork").isNull()){ - long InTidTorkLong = row.get("InTidTork").getTimestampValue()/1000; + // DryingStarted: + if(!row.get("DryingStarted").isNull()){ + long InTidTorkLong = row.get("DryingStarted").getTimestampValue()/1000; // Formating the data from long to a string in the correct date format formatedInTidTork = getDateFormat().format(InTidTorkLong); } else { formatedInTidTork = ""; } - // UtTidTork: - if(!row.get("UtTidTork").isNull()){ - long utTidTorkLong = row.get("UtTidTork").getTimestampValue()/1000; + // CalculatedStop: + // DryingCompleted: + if(!row.get("CalculatedStop").isNull()){ + long utTidTorkLong = row.get("CalculatedStop").getTimestampValue()/1000; // Formating the data from long to a string in the correct date format formatedUtTidTork = getDateFormat().format(utTidTorkLong); } else { @@ -295,7 +334,10 @@ public class DB { } //System.out.printf("%s\t\t\t%s\n",formatedInTidTork,formatedUtTidTork); } + System.out.printf("Size of dates: %s\n", dates.size()); + return dates; +/* // Defining a treemap to sort through the data NavigableMap<String, String> dataSet = new TreeMap<>(dates); @@ -333,5 +375,7 @@ public class DB { } // 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/Main.java b/src/main/java/com/application/Main.java index 6da5ee7..38ca17b 100644 --- a/src/main/java/com/application/Main.java +++ b/src/main/java/com/application/Main.java @@ -193,7 +193,7 @@ public class Main extends Application { @Override public void run(){ try { - Thread.sleep(10000); + Thread.sleep(100000); } catch (InterruptedException e) { e.printStackTrace(); } @@ -285,13 +285,13 @@ public class Main extends Application { String date = arr[0]; int kwhValue = Integer.parseInt(arr[1]); - System.out.printf("Date: \t%s\t\t\tkWh: \t%s\n",date,kwhValue); + //System.out.printf("Date: \t%s\t\t\tkWh: \t%s\n",date,kwhValue); // Connect the data to a series series.getData().add(new XYChart.Data(date,kwhValue)); } lineChart.getData().add(series); - System.out.println("\n\nNew line\n\n"); + //System.out.println("\n\nNew line\n\n"); } /* for (Map.Entry<Integer, Map> entryKwh : kWh.entrySet()) { diff --git a/target/classes/com/application/DB/DB.class b/target/classes/com/application/DB/DB.class index b043ea6f9c7d141f62c4802fae9187a01698bd52..1da6ea92dcd6fd9b64697518553dd3ad7c737946 100644 GIT binary patch delta 3989 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 E02=3I%>V!Z delta 5515 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 diff --git a/target/classes/com/application/Main$1WorkerThread.class b/target/classes/com/application/Main$1WorkerThread.class index d4793f5681bdd83671fe08bf926fc358debbea06..fc1cb79295b938a5ba6bc65d216611f6e1d0be64 100644 GIT binary patch delta 14 VcmcaEcwKOU3NvHdf{p4MH~=YR1wQ}) delta 14 VcmcaEcwKOU3NwScz((~A8~`L!1Wy0} diff --git a/target/classes/com/application/Main.class b/target/classes/com/application/Main.class index b9a0b1c909958ed7e95a60800e7fa3918561a1d6..23a916a35e825fce2f8a9fed85331c992bbed12d 100644 GIT binary patch delta 2422 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 N$<WFe&zQ*|2>`mO>$d;^ delta 2690 zcmaE1|HrZZ)W2Q(7#J8#7_V?KOknuW#n8{lz{N0uk&&H|iHm`S;XfxsKO-|cBMTP; zJA}i^&dA2azy;y3vomsVG4Mh-oFLs?Ac7l2@PG(j4u*AH3@nU%91K&r7}!DdOfCjq z5IvoXfvX<GSkJ{!#K_0a$j`;V#V7z$EeIlnK!h+SqX?rYNJ5OAQJl?T(g6k#U~_1K zFt`|086`l3Bo{*)qZ9|DG#8@`qbwJr9HTrpqXMHM2cr@fqcWokh)@L)Y9K-#L}+j^ z)+;k=vNLLNFluu#STO2vFzRwJ>Ve#+&(3JT!Dz_EU<VR40?~ZzjK*9H&Y(bYX5`~w zG~r@!W;EqsG~-}2=U}wpV6^05wBlg2W@ohFV6^38@B`_z1JQi!jP_g%!62Q%j1F83 z!HkaVj80q(;f(dpAkqcoKUa`*-Pjr3*%>`J7(KZdVi|R~7-AT`I2gUz8GX1Ik{Es2 z93nx!XJ7#F{6K_1J7WMBLk7rbcE&(Z2n(<?25~XuF#Km{4CZ3UWBAX(7{bMn!x+lW z7zPUHa1O=@5Us++7|B>4#m!L57|qQX!x+oW7{?e7A`;jc6S*0x8I#x<li3+lxftp| z#<wx1aWJNHF=jAkaxrExW^*#;Fy?YF=CL#8gZKqpjD?IvTnu%L#q5kFTnt@|WguIM zIT*`9G8OEMmF$dFj0`;C`9;~OMIjkQsfj6!o0FMh7`dw%8CWv&GE3MQYc`)^KF7>h zyLl%2M@F$qcE%uf#$a~FFtAJN*clVq8B-@O;4BcB%`k_Dv7TWu55o$EIgAW)lMC5J zgq-q=Qc{Zo67y1d7$!4JVPud12~U2&#=^nFFqL5%RDdVUDZhe;VLHPMMh2P5e5{g_ z=X0^j%w(9w!?2BEI}gJihP^xtXBp1%Fx+Ig#lzUZ*f{wBmzeWx#wH%dX2upC##Ru~ z#@NEn*v`Y)!Pv>e*u~h*$RL!JSeBSpp<kSwnwP2{3?g|LW;6EiF!nO`@i6u?PM9pi ztsyp%hj9|)WOl|WJd9Hrr?E3m=V6?|ICF9ox4hCU9>&>>jXaEV80YdZ&SRX<!?*xM zEM#27!?+maPf3t-<rx`R+%j`gL54RnGO)O&WR@^8uy~~A6!0)EVeFfHnLC?#DP!Yg zN1oN(%NUpQFoMHKX>tR<$YgF_0ioH9D|r}JfkJQ<$YHA)*G$&sEoPq0xOVbl-bCKn zjO%z9*MltHz&LlZAfG(jMv(X9CvRjIp6tnI%DjoOadIP{V&-hd&5R5JE=84@dFcuP zMfu68#l@+`?2KD@7`HNR<6+#+xPzT>ClBK;#@+0Ubv%rF829op?ql4~$RG>~D*e)u z%p85+!~zx9ypp0y9>xP8DP9yQcE*E@42ocz3pn@^c^D5dPGe+Xv}I>J%)@wu@hCgv zF&@U_j3?L`Px3IHVm!^rAnKA>l4_;Esanj*$(bFV0cLVBG6;ap%}LBl*Y{7#N=+`| zVLZclmYwk&594{p3p|V$8T%L+Abw2X7m;9?&3K8CfrpFBFST4DCo?aVi;IWxGGpWB zTK?~ho7)8qS@e-i46ZCLNzG+sV9qZsVPp{X0o#?CuOCp9nO72AQk0sQYd!gZsHy_Q z<ES!>3~U7;b!m(YHj@{M3QwLWEFzE92u23>^wbiU#FE6xk43fW85!8Y8gud(6dC#% zCNMBCurM%zl0E|i0~094gX!rEGr;srhFJ^@3>*xM46_;LFfcOAWnf^?XJBMtWME)m z)!NR$xDl*u9s>gd8(2_@VLk%`0}q(Z%CLZ8Ap-*gC&MC!#SBa!&6AtNL`*@dxfqxj z7#Iu~SQrdZbSz<5%D}*|4D2jMhUE;5pv(%=JNdMj6XU$eeB$z|2pbHcHo(-cWME`i z#jqNzK1lpM<GjgE68ZHY^>z$w3=9nSpz1-aH4JMR7#TPit}(1*n8Luspvth5VLihJ z24;o?hB}6g3^N#57#1^FGi+km%)rX91?nq^s;vyna5t`GU;>o^(7@Trz|6qPz`)?W zn}IiSI|HB3ZidMQl5ULiCYMX9JA+(e0+ENhgoDAE0TjrL3_=W+3_BQhGB7d7Fz7Sv zVgQ+>&Y;4un_(w7iuN$<1=+Frp`-;P<GjgI()D1ERWa}|FfgjajAN8%*vBw~fssLo zQIugn!vO{+1_efThJy@;7?>H%89p!^W;npW!r;#EfZ+(kAqG~41cu`bM;Q(<urU-c zY-c#eaEO7Op_5@A!*PZK3>*wI8TuGbFdSmwWZ1+|%5ak56ayE-A%;|j(+p=AxIuAv zmf;*Yw3TEQGR~WPM8+EIC=Uj91_p)+P)7+e)H9rCxWK^3pu~{JaFO8x0~3QbLn^~1 zhRY1h45kdx3|AN~Gq5m3Fjz2LWw^$`%8<#R&TyUK8Uq_Vly5LFfr?fJW>6|(%3@$+ z;Adc9_`I7TCvrPOuFr0UyvXeg`M%mhlj~#+7&lH{FKfY=IQfOFM)W3z7NJ(wy$o%U z%#yspku0KoI~dx7w=r~tOLA;u=-kcF6)DLJ7TnIzy_3O!i6MOX|Jl0R7<wc*AY70M zz1tZ2mjCzG-2hIRpcEX&AUfGo&bnTKVIQM1!*xa#hFgrP49^(V7~V0eGkj#!1*hv4 z2403925*Mj40jl~8KyEgG2CTX%D}@go56<R9>X05UWO$M#tiov9x(7Rv@!%SJY;yp zz{L>FFqz>o!xIK}h7^V_hNleA88{gH8Rj#*V0Z;i$Dg4g%faxvp5Zma8wN%O0fxs6 zZyDZ!;+x?zG$Cs<oM3p*@PvT{oO~4+n4yMzU|?fV0ILEeWQeMd3@i+v7#J8L8Cd=^ zSTeA&Gkj)e_`=Tcm7U=mJHvN&h93+J{~0V8xX>i>*cpDXGyDWA`2|+>iy{3#gBSxV znnI*(y^`TKxY+o^z{Kzu%=*VLiGhJZiGhV7oPmL1A_D_M9b*c^GX_b9YKB^dmu#F2 LU5qJ=r3{h)C!<eI -- GitLab