From 8a74b214f53ba87c734200a4a2bdb2bfa1792e12 Mon Sep 17 00:00:00 2001 From: Eilert Tunheim <emtunhei@stud.ntnu.no> Date: Fri, 25 Mar 2022 13:35:22 +0100 Subject: [PATCH] Fully functional quick switching using constans class --- .../java/com/application/DB/Constants.java | 43 +++++++- src/main/java/com/application/DB/DB.java | 95 ++++++++++-------- .../com/application/DB/Constants.class | Bin 1028 -> 1340 bytes target/classes/com/application/DB/DB.class | Bin 10348 -> 10444 bytes 4 files changed, 94 insertions(+), 44 deletions(-) diff --git a/src/main/java/com/application/DB/Constants.java b/src/main/java/com/application/DB/Constants.java index 65b1741..9326672 100644 --- a/src/main/java/com/application/DB/Constants.java +++ b/src/main/java/com/application/DB/Constants.java @@ -23,16 +23,51 @@ public final class Constants { // Database ID/name public static final String PROJECT_ID = "sf-drying-optimization"; - // Location Valasen + + // 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"; - // Location Arjang - /* + // Parameters settings + // Valmatics + public static final String OTHER_PARAMETERS_NAME = "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 final int KILIN_ID = 5; + + // Winccsensordata + public static final String KWH_NAME = "VariantValue"; + public static final int VALUE_ID = 51; + + + + + + + +/* + // 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"; - */ + + // Parameters settings + // Valmatics + public static final String OTHER_PARAMETERS_NAME = "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 final int KILIN_ID = 16; + + // Winccsensordata + public static final String KWH_NAME = "RealValue"; + public static final int VALUE_ID = 19; + + */ + } diff --git a/src/main/java/com/application/DB/DB.java b/src/main/java/com/application/DB/DB.java index eb340cd..a533625 100644 --- a/src/main/java/com/application/DB/DB.java +++ b/src/main/java/com/application/DB/DB.java @@ -12,6 +12,7 @@ import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.*; + import static com.application.DB.Constants.*; /** @@ -167,14 +168,15 @@ public class DB { // Preparing a query statement // Query statement 124 Valåsen - final String sqlStatement = "SELECT `TimeStamp`, `VariantValue` " + + final String sqlStatement = "SELECT `TimeStamp`, `"+KWH_NAME+"` " + "FROM `" + PROJECT_ID + "." + LOCATION_ID + "." + TABLE_NAME_KWH + "` " + "WHERE TimeStamp BETWEEN " + '"'+ entry.getKey() + '"' + " AND " + '"' + entry.getValue() + '"' + - " AND ValueID = 51" + + " AND ValueID = " + VALUE_ID + " " + " ORDER BY TimeStamp ASC"; + /* // Query statement 174 Årjang final String sqlStatement = @@ -199,12 +201,12 @@ public class DB { // Sets the baseline in order to reset the kWh counter if (baseline == 0){ - baseline = row.get("VariantValue").getNumericValue().intValue(); + baseline = row.get(""+KWH_NAME+"").getNumericValue().intValue(); } //System.out.println("baseline: "+baseline); // kWh value - int variantValue = row.get("VariantValue").getNumericValue().intValue()-baseline; //-baseline + int variantValue = row.get(""+KWH_NAME+"").getNumericValue().intValue()-baseline; //-baseline // Retrieving the wanted data long timeStamp = row.get("TimeStamp").getTimestampValue() / 1000; @@ -258,10 +260,6 @@ public class DB { */ private static Map<String, String> getZeroPointDate() throws Exception{ - // Initializing a date format in the data type DateTimeFormatter - // Required for iterating through the dates. - DateTimeFormatter format = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); - // Initializing the dates map to store the results Map<String, String> dates = new HashMap<>(); @@ -274,19 +272,22 @@ public class DB { */ + // Defining extra parameters if required + String extraInputParameter = ""; + if(LOCATION_ID == 124){ + extraInputParameter = "AND CalculatedStart BETWEEN \"1990-01-01 00:00:00\" AND \"" + TODAYS_DATE + "\" "; + } + // Sqlstatement for Valåsen(124) final String sqlStatement = - "SELECT MAX(Name) as DryingSchedule, MAX(KilnName) as Kiln_name, DryingStarted, Max(CalculatedStop) as CalculatedStop " + + "SELECT MAX("+OTHER_PARAMETERS_NAME+") 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 KilnName = 5 " + - //"AND DATE(DryingStarted) BETWEEN \"1990-08-17\" AND \"2022-08-17\" " + - //"AND DATE(CalculatedStop) BETWEEN \"1990-08-17\" AND \"2022-08-17\" " + - //"AND DATE(CalculatedStart) BETWEEN \"1990-08-17\" AND \"2022-08-17\" " + - "AND DryingStarted BETWEEN \"1990-01-01 00:00:00\" AND \"" + TODAYS_DATE + "\" " + - "AND CalculatedStop BETWEEN \"1990-01-01 00:00:00\" AND \"" + TODAYS_DATE + "\" " + - "AND CalculatedStart BETWEEN \"1990-01-01 00:00:00\" AND \"" + TODAYS_DATE + "\" " + - "Group by DryingStarted " + - "Order by DryingStarted ASC "; + "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 + "\" " + + extraInputParameter + + "Group by "+ START_DRYING_NAME + " " + + "Order by "+ START_DRYING_NAME + " ASC "; System.out.println(sqlStatement); @@ -315,17 +316,26 @@ public class DB { String formatedInTidTork = ""; String formatedUtTidTork = ""; + //System.out.println("Start: "+row.get("DryingStarted").getTimestampValue()); + //System.out.println("Stop: "+row.get("DryingCompleted").getTimestampValue()); + + // Retrieving the data // DryingStarted: if(!row.get("DryingStarted").isNull()){ + // Check if response is given in millis - if(row.get("DryingStarted").getValue() instanceof Integer) { - long InTidTorkLong = row.get("DryingStarted").getTimestampValue()/1000; + try{ + long doubleValue = row.get("DryingStarted").getTimestampValue(); + long InTidTorkLong = doubleValue/1000; // Formating the data from long to a string in the correct date format formatedInTidTork = getDateFormat().format(InTidTorkLong); - } - // Checks if response is given in a string date format - else if(row.get("DryingStarted").getValue() instanceof String) { + //System.out.println("LONG!!@@@@"); + } catch(NumberFormatException e){ + //not long value, must be of type string + + //System.out.println("Must be a string!!@@@@"); + // stores the value String value = (String) row.get("DryingStarted").getValue(); // Splits the string based on 'T' @@ -333,29 +343,34 @@ public class DB { // Combines the values into a new format formatedInTidTork = splitValue[0]+" "+splitValue[1]; } + + // Checks if response is given in a string date format + //if(row.get("DryingStarted").getValue().equals(Long.parseLong(row.get("DryingStarted").getValue().toString()))) { + + } // CalculatedStop: // DryingCompleted: - if(!row.get("CalculatedStop").isNull()){ - // Check if response is given in millis - if(row.get("CalculatedStop").getValue() instanceof Integer) { - 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 if(row.get("CalculatedStop").getValue() instanceof String) { - // stores the value - String value = (String) row.get("CalculatedStop").getValue(); - // Splits the string based on 'T' - String[] splitValue = value.split("T"); - // Combines the values into a new format - formatedUtTidTork = splitValue[0]+" "+splitValue[1]; - } + // Check if response is given in millis + try{ + long doubleValue = row.get("DryingCompleted").getTimestampValue(); + long utTidTorkLong = doubleValue/1000; + // Formating the data from long to a string in the correct date format + formatedUtTidTork = getDateFormat().format(utTidTorkLong); + } catch(NumberFormatException e) { + //not long value, must be of type string + + // stores the value + String value = (String) row.get("DryingCompleted").getValue(); + // Splits the string based on 'T' + String[] splitValue = value.split("T"); + // Combines the values into a new format + formatedUtTidTork = splitValue[0] + " " + splitValue[1]; } - System.out.println(formatedInTidTork); - System.out.println(formatedUtTidTork+"\n"); + System.out.println("Inn formated: "+formatedInTidTork); + System.out.println("Ut formated: "+formatedUtTidTork+"\n"); /* // CalculatedStop: diff --git a/target/classes/com/application/DB/Constants.class b/target/classes/com/application/DB/Constants.class index 36d1dfcf105d9904e54bdde59aeb74409a514b91..c682eb0f42ee8e24b82c8dc46fc7e8e06d2425f1 100644 GIT binary patch delta 561 zcmZqS*u!Ob>ff$?3=9k=3|?FeoD2pW42E0`MhwQB3>*w5TnwfRW+1LPh-<;lV9Cy4 zHPNt$(R$(%gL)fA2EGtSCm+{%KSy8Jc<*oz4hCCB22uYI57(gh0LLIlU)K=VpkS~x z2ZJ3WgJ5uoV^B!EOHibzpF338o{>QyIK)2yRn&ozfy>*|$I}n0%8`+Q1H$)oVP;@p zU}a>G;qVUkfJ!?tGH`@B`h>d1L!^x-zMR0U#-KjAhEYPonTNrJ!Ig)Bi-DV+!HtK( zoxuad@tnMdvCo;sFEKZjk%8Bxs4_DzJ-8&Xs3bLok%7-SF(<h+C$S_oCAcKN0Azb+ zP98)pPgr76W@27RSYl3TDkFo^<VGf?$+1kQ7<ngaFbCF4GDtA+GB7gmGcYhPF-S5< zGDsour5Pj{WRUo>43Z3TNPKw)Nd^T5A-H};21y1bBza{9Nd^@pc~u4`1||kI26YBT z1`P%V24h<WMg~Su2x)C+VB83HgC+w50~Z4m0|SEq0}F!?gBAk=0}n(IgEoT>0|NsG cgD%8`$w!&hBoXTQ7&sV285kM#z~<-!0Jzgvs{jB1 delta 261 zcmdnP)xu$T>ff$?3=9k=4CY)6oD51F49Z*#Dh#Te3>*w<Tny?A8X&GFh^xiUpv}&p zGtsb!QFr1J15rIj2EGtSCm+{%KSy8Jc<*oz4hH?n`HT~cB^V?b8H6h<D=T$<eRWe( z6g)hva&xVUi`f|rco+;BjCdHh7`WLPjCmML7)(JNv&lwGeUq7(-!igI{=gjQ!^FVE zAi*HXz{nuQz`$V4z{tSJz`($&wVi=+BLf2i6N5AZ0|OTW69WT-00Rqy5Q7W@0|O64 l5rZs)90LOb2ZKDsfXRPZ)Fct=`4~7DL>U+v6u{;v0swzRBiH}{ diff --git a/target/classes/com/application/DB/DB.class b/target/classes/com/application/DB/DB.class index 386565ccedb8265adb368a8df6a4c7ae9917907c..d01f067c3c3db55edf5e5ab9b325a53bacff7aaa 100644 GIT binary patch delta 4035 zcmaD8a3-++)W2Q(7#J8#7|*gZ+~Hz~XSmDGaF2uGJ{JQs!vhY6hg=Mg7#@Q-PuLlr zaxgsOV&G(Wz|QcTi-CvX1sB6hhF2igYj%b=TnqvXZ@CyM8QyU*yl40TVtwRd5M%hn z&hVLo;VX#w4McngN&jGH_z6-`|BH*^H^Uz;hQAE|*ctwFGe|QsvNJMqF)}l<urso9 zFtTwmC^I|&@!7c;IT$&)7`Yg^xfppEdAS(*82PyvDj5aX83jQKgxMKIxES;p?t%nG zxf#V6#km<J7$vzGr5L3_gbX{QEIXqd7lRqYT@FThE(SBkdIfF<Q$|I0MkNqWnS)UU z#8>5DR0HwVIT$rSG&d)sCZiS?qc)=s$ZTCMMm<J-Zbkz}Np?m<4n`v`1`kGKE=ChZ zQ!Yj`Msp5E3lPVWl>rQxUw|}OaWPsm+Hf&2Gum=7+A-RL+~>ei&*%tZII%N2b1_6P zx^OePGP;2XCk{q;5G~HZ=)unD39{RZgVCFV(T9_Pk<pif(T{`CpMx=ggE5eUF^GdP zn1eBdgE5qYF$`pNI6Gqmh*srbjO1dlW{l!sjOJjB;b4sAV2tBnj0cIiaWE#ZGchJ^ ze$6<Kk?SctV-h>Vb9RO|n<q27GBPG_zR42LES$p5m<kRxC3eO%c1A;X#`MYF9Fg4I zDfy*IIjLcZIi-^qa%iYArZO@p`eY@RCF<uS=B4ZVmF6a;7P;jY<tCQ6RwSnulw{`T zSx-LBVI{+wl30>j%*Y^|T2WGz=$ThgS`v_0l$e`Zl3FzR9Gm{+8g|af`JAO}RSeaP z3{sQhnWQGOa7l<&F=j9_Fo%XXvomJ$FlI4k^DyQx=1w-^surkX%wuQF=V2^hEaYJ< zVyK?HmrFvbn6ZS1VF|-hcE(a3#xllo9)?ziHXg<b#;VEhxgrIs8EbeLYZ>c!80#4u z7#Wl%E3!yU-XOvu%EK_7VFo*6BS=#dJ7Y6QRm<dlZd>M7#<t1lxfR)xc^KOnJ0^eQ z*4OT2>|$r^=3(q%>}6-{<6-P)oWRaF5u|kzJL6=K)+sy;GZ|(vGMK_Fm^@QLcycR` zIP+A-X_M#kh$)-~xiN)@aXRA+cE*`JjI$VLvooghFwS9|%fmR2asK41JgYnwFfQa_ zT*Nq^kwE|v%E2W?nR)3vj0+eSGcvF$IQqFL@Gvd`DdGonK+%)x>7rn(08+D*kwHRX z@&R5+#brE<%NbX&Gp^)eT*a8d!?1v1Av<Fl594aaHSCOQ85uOdZe1tEHCc{Nw0<4q zdUnPQJd7I|H?cEr=3(5zxRsHCGbA%NHMk@(w}6Ln8{>8!hDL@acE%k%j5`^3@i6XY z+{4be7sT1e!?>UE03!ppOJYf)LUCqQs+9r{<3W%Sf?$u7mSpDWhZLoz`X(0eFjO%f zVrNX}VLZ$@mytn~%Pli6aq<>EC(a{`M;RFy7#YkbdkUEI@-QA_Sj@=4q@=*e@P9H3 zzm=t@i;jXzQDtUcdT>c%QAuiwj)JdagoblsPI75ZVo7RBa7liFrb1#dRF!jnZb43J zNovYuEnc<B^Z3(b85!7=z=6idz=x`hkwIm$f`D2*r+ZO;X@Npgr2-=ZFN$T13|tES zMJcI85J^@A$6#j#9>(J!PsoFPi91s;GBAelFrHvM$;iN{z{tQ4F&OSXMg~65ygY@p z{37vOkUy+ImWP&r1fcxMjDk-XMJHdB5!oy+bdHhn^yYWM*H|Y%k(S?lL~<G<H(MGw z7cw%aX-syIk(_*9nw1@raI7bv7Z97=ES)%+Stfn*Mj21WGm{m?MJDshS_f1z#Dfbj zP6kGXDu!wXMur*&1_pfwMg~R(1_oBG?F>vC85kIt7-|_97}&sq5)5?=3=BMAHY-Ct zLjwZ?0~aV=fHY5@C99?nQp?A{%)r2)z`(_z$RNz11lPmGz|GLi&;r)e%FxEZ#85N& zz3jqzkRCY(b_NCp9R@B2BL-0hV+JV(69#JrBL-&%6NWSfQ?MCY3@i*%42lfx3>^%N z48jb-44n*J3``7M3~>zI3_T1C3~3BZP}yDv28IX*j{gjr3@q#nee4YV><kmw8749? zvNKHN`p>`y7G?km)<Z?z*%>DOXAoduV`u0COE64ifa_rX&%ngM1Tl$$fngE@0|N^K zBZD#nC&OfhDIl*fFfbUy!fpqHP&gv&xEPoi7#JKFSQwna{(yzwREB9FqlDmQae>Mu zkXe%#$m@fHQj7sq!vr!gGXyd4F$6P+FoZD3G6W*o&jl)bz<U14M<pSGGKE2eA(cUv zA%j7YA(KIyA&0?~A(z3OAs_4nF|d<78D=xgVPIeoVK8Nw%P^0DkpUEJoD58V7_`|L z=1Zekvw&eC*qU7ms@@=LAik<);AUt*GE#(L5yN5z1_o{hPN<Q{LA8WoDFZVonKAb> zurcs4Ffg8*tfi>H=sek5F`!<+cpHO*kmEK6%WVu!R;-&CoF!SeF}O&w?qG1WVq-RA zmt@<<;I@;&osq$cLy}`BgE1q+OomJl%Y>2P0E34Wrzra@1|dmKA<u0LUfUSFw=wvb zv7>NB*;CB8BsqnA!3z9D82oe1xpy!GigE9#X9(KH5NyRO$~BKcNRma8SCnf9Ls zP-cek<^LydVsPHgU>3QZ!CWY88-t}J%T9)HMuu$+4%--<wlTQuW{8NCWZBLT32|B! zBf~5Pd63hh85snOmM{owN$+3?0SSQ2Yhh$u{%;qOkulpCWG%HYjnvxC5b3M4lOcBU z8YMY)XQ4ROy$tb_FDi-ECxkEme_Ce)IPrkuqmDtIfq|iqfrDWJ11M2wGt6Z$VOY)J z$gq|nhG88;1H(av4u&HP{S3z$CNZ2~*urp{VJE{Gh7$}I8E!FLVR*%Gjo~}PO@==V zw;8z^9x(DTJYv*kc*1DG@RZSy;TdBz!*j+shL?<q46hmM8Q#@1b})QoT*2^(@g&1% z#xo3G!HJ-cfsf%9gCWB*hUE-g46hgz8CEc?WZ-7_&LG0DieWJWFT)mwaE8?kYZy2g zOc=Eo)-tSPU}0!rxCc%)tPK4O=NZ;BY+ztxn8a{~VI#wG26jdZ1~rCF44WA^7_=FU z8MZKNXJBSr!BDRVX0kAFFdk#r!LSZgsxTg5*vYV*fswI;!Hr=T!)691hTRMd40a4` zP|Nl(ut1I53pZ{b*f@}B`x#)S9bjO9nsJbU37jc{894tjNU$>;Vq|AH{GXwfp`H`U zVP`nP&TxpG;V3)9F_0t!!yg7sc824>7@U4FF#TunXJCe^WMKHk!1R~Fh@IgCJHz2$ z4CYAr>m<0OJ;lJqa2lRR7BH|e@GvkizSzy67rC85-&-ir2bKhr>bEgiZemE@#$YLw z0?9FOxm1Ky8c04JL}VZYLF%<ZVwoT!3q)jt2rw%LVwmqH24|gZ3@$o57+n2y;n|J_ zl<Yy-j<Mbp#DwNMR-r^IHlai-c1c#DEO5@soyCv<=lGd(h;e|k8W$+5aqWQQG`8go zHdY*PRrv=PtgSdDIfV+gF%(*HL47L8#cTv}ToEYGaj}5dpwfY@UXoR)7;F^|)7fFB zLsXGuIy+L%ECE@}1__mI3@$L4dIoc$Qjioo$aQ6Kc~BWuK8rz2l6@OP`78!LElD;> zc4#5;@AxJLXQ2v~y$tb@%#h5!gCQh%8$&`ksQ3Wo^$iS63|kqlG2CRxV-#XEW;A2S zV_*T-z-<hQ3=E7M3>=Ii4BU)j^$co^QVhk6DhySOrVRCrmJACRZ5Wm?+A^$QbY<Ae z=*e)9(Tm|EqYuM1#z=;njD8Ha8ABLeF@`aGW{hAIVoYU}V@zXIW6WSQW-MYfW6Wf< zV9aH7XUt~|U@T<JXDngtWGrP|!PvsMgRzbAFk>g<F~%;&`;5H|peDc?hI&DUgAAe! zXBbv8a4?)?;AJ?=uo9f*H5kq@EN0+j_{<>BaGqfr0~f<>26KiB3>O(V80BC(7}Xef z87_fzFuF59bub3NbTC@LbTBMolxMiiu$Y03VFjZ!!xe_b4D1XG7?l}T*E6hPU}fN7 ze86xOocXyK?=oCtSj@o4P|R2gE=`yi>KQY^r3o{*7~o-GgsQ*JzyQwFZVc@I8M+u) zVfh!7h1nSnGcf#T@MGXW6J=*O4$kC9K~0Do7U{|C3^y!(Fa-Z%V8Y19HyM~1Zh>?3 zZH8?O3=CEb><p%iVhmf^I2ptk-ZOk*;AD_zkY;3H;AGHYkY*HO;AE_1JjL*Zg_Geg Q!*3AH$j8XT@P$DV0OB2lCjbBd delta 3959 zcmX>T_$HwK)W2Q(7#J8#827O=T;^hkW4OZ3aFv7M8W#gI!*vdZ8(a)G8E%0%x7iu) za4_8EV&G)B&dzX;i-CvXJ{Q9ShKC^5BX)+zTnqvXPq-M07@l%5JY#qcV!hyE5My}B z&hUzZ;SGrS7DT)QNxx@j_yAH-|B;K~6T@dNhA#|X*%`iZGe|T1U}yNr#qf*aH#@^0 z4u-#649X1GLHvJQ4F4G!xEL83nYb948Ckd(SsB^57>XF#*%>*w7=AHwu`_aWG3YT| z0SWSOGx9R>aWnEW3UD(DG75nRVRl9lc1BSy1~Y~$9E@UI3}%e=;@k|Tj1ugOk|3TG z2ctBIFT=qo3*s|zGRiT^b1^C~DuT>Z;$l>0RN-b+WfWj%RO4V&=VEYU)Zk*&WYpqf z)MnJ-VAKV1^jI0dfcXVTlRg)t0iz)o12dx$7ef}KG00se9E_$Q+Kj87!Hm(Ioza4e zA)L{Yo6(BV8bp|JFxr4<J`P4(c1Amp1MImN9T*)s7@as77#W>87+p9RT{#%tI2heI z7(GC?dV&ZUc1AA_MsF?#YepXqMqds_KMqEJ5YL)}F@T*hkdcASCNnRy#Ey}HSwl07 zkzq4GQ!gXe9d^bbc7}WG439T2V|Ha^4Bq^PC7xM0gq<-I9AuL0jA87IYV3^RljArd zCm-cdoh-y@VaAr0UzD3z!pNZFla*MOs9%zqo2m~H(|1WMNe#)&O?3k+DM>A|W@KPZ zNi0b%p8Swae{w%N=j3^urEJ9vC5#MGljku>O*ZC|5G!VkWMp6t4RK~?jN)O8W{lxs zjAe|QoXAxzP|O(5&X~Z%n8=vK!<fuaGWiXcgj5P+Di6b4hI#CaX*`VSj2S!(bqw`9 zjG2ttljXQ01#%d3c^LB;^LZEx7z-I0lqM^3D~a+jOkkME&R7J}P|VI)0#Z>rc^|he za~Wg#<bT|XY{5K?6^xaWReAKas~D@<8EbeLYZ>d<8S8l%8yFke8Jj>_o7ov#Kw4XQ z7$z}HW@Ip(e2`mt@?i;~$y<2DncEoKC!gaHQ#b;0TL=$h2V*BYV;2u&H)9VwV<-<} zFJm7MV?X1B$t=99>L)Tz;$fW3IDwHt0341viFxVz!6ikRdFeci6B(y4GO#K*`nf3Z zFir(2(g1V95_3vZJzW%R6-*5k{DWLvgA|-16+l5AT#}eupx_wn%+5HChjBXN40gtu zJdCp#BY7BRGR$IU4C7&(%{YghaV{f+Msj|x{^V2^vB~G8xF(12iAKz0oX^g<fQNA* z<05v(#XO8l7?(0KaKeq{VO++zoQI)`p_-j>1rOs&##KBFrx{m+SZjC~*D|hSWZ-s5 zEJ;)-&a6tcQs7}+&$txihYgeW^NDd6Gj3#O4Ci6o#Mn3a0iPG&X2vb-j1fGHTN$@8 zGBQjq=eM%TOUzBxQE(}$%*;y<E=epZNlnpF@J+1Ha8ArgF3m|SNlghZ$uH1UNGw)B z6`K5tzek3LaXZ5tMg|Kda2TN}aN}2DWn{2aQkZPaZ(h&HV4|epUX)*2ppaCFYNLXG zQA%nNrm$nMvjQUn10w@3iUWBVcQE!bG6*6f&oi$iH9fV6k%2LUhjAz4E=C4M1x5xw zWcM)T7fkjSe4?xb)`d6gY&H~n%E-89v$)7L*3CRp(-<eOme!p7LOOBsTS@uJo-*mY zocU=1i6teeMR|-27L!;-Cohm>mBnl3<h3$BjC&{llJO5HVu%BmSDXxt48;s342%q= z3=9nV42%qn3=9mcTH6_zHZm|UFfo)dFfg!z1;rW485kINz-(5A3WiDs1_mxrssL%8 zJX2OpAEcI#fti7UL7st&L4iS-K@qNpi-DV=hM^X$r;eeXfr+7X@;lju^&mZR4D1XH z4B8A_42BG%3`Pu648{!B42BHO48{y;3?^VRv=~?zq!<(#8W<WG7#V~af*G0^ni-fF zK-E_ZLn{LVLmC4URJM(Qfgyr{<3EEY0}DGtJ3B)MJ3}WsLl*-hJ3|-Oe+D+NFat=i z9xCe2&d~LrL4bjcouM5p!O+D3*TMXsfr)_$ViE%bLpK8h0}BHqgE9jrLk~kQ$SVvC z492jq+rc0djtDz01||ju273k;1}CsTVBy!t&<`?72yPY^sE7iYHF>_gJ~$}F7(kUu z00T2aAOjym5Q7LqFoP^Z0FwP&pkfHD=dXNJ5+W#*8AKRT7-SjJ859{Z7_=F(8B7^+ z7~C21z)lbYJIRw_3d2+e1_luZQ-)~_(-{~UK*7ez!1RYfo1I~XG>SDd8D@d4*{PuF z4YCH}s~QGwhI%9;MHpr?%wb?);AY^28i^cKa~b9_FoTjAb1MTI10Mqe<B`dliVBRD zlf4uJ>bEgCSg~$maFk@-#^5B$x`V;lijCQfU6O4ZgUe0^S4IXa4oQxk491KMGZ`{L zEE7hC0}O6foTBWr7=$D_h1|C>cx+?v+{WN##*V@jWlu5VlH?Tf1}pFpVerj0=ib5K zFUGxtAz&LrpcStu*SvZLAxRcVUQw<c3_&{?f|(h@m;ax<iNSF<gIVNu26Lg1Z48!@ zEIS!O85y=Qgl%JR*v8<rn;|?>l4UzX1jK2Pj103F<Uvl0Vq_37TEZZ#CB1_o2qXY9 zuZ59u`M)DbMn-RAu+)N?2=YJFNUiM*5xzP*8Dbb2b}|?-GWh92y=|nslL72&Q!AED z430vvta};aBAG$XvSMTij${F`>=+q>w=u+rFaLj9X9GBKf#R!<L7stup_hS!p`U?^ zVFrUX!yE<^hE)uX3~Lx-7}heB)idm8sAD+9(8_R>p@ZQV!zzZ84C@(AG3;YF&v1d^ z62k+AD-3TLt}}dMxXH-KaF3CN;Q^yE!y`sLhR2L93{MyX8J;qRFg#}rXL!k2%J7D< zj^RDyJcbX9`x!nm9%A?mP9%K{d<+*D3>oG#EMNe&A{7}HGAv@?W_ZgW!cf1MVGaW? z!zzYwh9wM388{hC7!??nF)U|bVJKs`2ToV446O|38CEc?WME_HU^v6DieUi*JEI<h z8pCRaH4GdK+KieEYZ*2$Ff-0$Pz1AB7&sXBFl=O44k~pRcQI^YSir!@SjXVTu$f^E z0~5m*1_lN@1~!mg^$g1xwlc6ljoSt{Zadt#9Sktzb}}$P4cW!O1kN?V44nTMB-j~t zGqN-6`Oi?zzzJouGwfw&*v-zckDXyZNRENw4}&H<!+~E6PQMtK{xkS9Fhf+<?_ps0 z#lZBJ!HAvVAUngJUkv6*8SoIeC_c=<#c%|ki98wD7`PZ181D(O>|jXn-p!yFxt&4Z z2bN$Hw=r05Vo2J?U@4T0V5T6LsoNMVw=p>QZenoM*~U=sq_cy;*-saq+rWtll-n5N zLCFf7?%b?ch0?6pgwm|oC0T{i!TBj;7DE-BlX;LKYbJv-oDa!t9H7j`0nKb|%Ne}j z@|g!2tY<P<NwNynLrlv&z+er^O+wk*7;>yQp`MZCWHthMBo~wkIaxq#P;tQ~$tskG z><9=4;RpyHizC<}j)2I69Z?T<1yq0(N3es+EVgY7PKcZ>$qsUCJ|uiWr5W2chJslP zVj%H?SqyyIl5CRf&_d?lTu@FfWT^*dWo>YAu!A88oP|N<i}rSg2t+n+V^CxORbp(6 zTnv1SVhr|-$_#FdCJf$;77RIz)(i!VHVh?<4h)TqP7D(nof#G~x-zU|bYs}a=)rK1 z(Tm{%qYuMPMn8rhj3JDyjA4wTjNy!`jFF5+jP+5Bri{^yu8gsaA&l{iv5bj~HH@i@ zEsSZ5^B7AR*D;ne?qsZD+{0MSc$KjZoSj=3co`Nl@G=}_Sj51=aDhRC;TXdl1`dXs z4Dt-e8TuJG8C4m08BTy?8AD*QjIl6Th5|-UhLa3)7}yv}7+vcbPBF}3U}wl-^aU3H ztPE_7HyBPcoMB*K;A6bNaF$^?10#by<9u*Yz{KFqI2l|NFoQEOs8WTfI>!L1#|#<R z|1*R!u(C6phi5=`hCK`n{}`g!84iGR<i6hwZZ^Le+<q|F{EA~>!pLtI7?>C?f^*&_ zhV={#3|0*645o~{4C~l98N?W#F}!BrWRPc&X86v)$)Lj^&B)2X$(Y5so8dJJC&L$p PPav9+m64g@HG?Do^3rXV -- GitLab