From c82fd9ead5761274ddeafc84e2baf93e4205a64a Mon Sep 17 00:00:00 2001 From: Anuken Date: Wed, 3 Oct 2018 20:58:35 -0400 Subject: [PATCH] Added unit tests --- .gitignore | 4 +- build.gradle | 33 +-- .../sprites/blocks/units/revenant-factory.png | Bin 598 -> 607 bytes core/assets/sprites/sprites.png | Bin 104432 -> 104433 bytes core/src/io/anuke/mindustry/maps/Sector.java | 5 +- core/src/io/anuke/mindustry/maps/Sectors.java | 4 +- .../anuke/mindustry/net/Administration.java | 13 -- core/src/io/anuke/mindustry/net/EditLog.java | 21 -- .../mindustry/server/ServerLauncher.java | 28 +-- tests/src/test/java/ApplicationTests.java | 204 ++++++++++++++++++ tests/src/test/java/Tests.java | 9 - 11 files changed, 233 insertions(+), 88 deletions(-) delete mode 100644 core/src/io/anuke/mindustry/net/EditLog.java create mode 100644 tests/src/test/java/ApplicationTests.java delete mode 100644 tests/src/test/java/Tests.java diff --git a/.gitignore b/.gitignore index 12ca21bf90..fdf2b4f464 100644 --- a/.gitignore +++ b/.gitignore @@ -14,8 +14,10 @@ /core/assets-raw/sprites/generated/ /annotations/build/ /kryonet/build/ -/packer/build/ +/tools/build/ +/tests/build/ /server/build/ +/test_files/ /annotations/build/ /android/assets/mindustry-maps/ /android/assets/mindustry-saves/ diff --git a/build.gradle b/build.gradle index df4df532dc..9954ae113d 100644 --- a/build.gradle +++ b/build.gradle @@ -27,7 +27,7 @@ allprojects { appName = 'Mindustry' gdxVersion = '1.9.8' roboVMVersion = '2.3.0' - uCoreVersion = '00d05bd7d3e943c8a454ccf2cb69cdffb23afbb7' + uCoreVersion = '220916714cbe63664c34f95a9dc50a362feca732' getVersionString = { String buildVersion = getBuildVersion() @@ -119,20 +119,6 @@ project(":html") { } } -project(":tests"){ - apply plugin: "java" - - dependencies { - compile project(":core") - testImplementation('org.junit.jupiter:junit-jupiter-api:5.1.0') - testRuntimeOnly('org.junit.jupiter:junit-jupiter-engine:5.1.0') - } - - test { - useJUnitPlatform() - } -} - project(":ios") { apply plugin: "java" apply plugin: "robovm" @@ -218,6 +204,23 @@ project(":server") { } } +project(":tests"){ + apply plugin: "java" + + dependencies { + testImplementation project(":core") + testImplementation('org.junit.jupiter:junit-jupiter-api:5.1.0') + testRuntimeOnly('org.junit.jupiter:junit-jupiter-engine:5.1.0') + testImplementation "com.badlogicgames.gdx:gdx-backend-headless:$gdxVersion" + testImplementation "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-desktop" + } + + test { + useJUnitPlatform() + workingDir = new File("../core/assets") + } +} + project(":tools") { apply plugin: "java" diff --git a/core/assets-raw/sprites/blocks/units/revenant-factory.png b/core/assets-raw/sprites/blocks/units/revenant-factory.png index 6182b7ea09a76ce2999604265617f66431617b71..a236936f62b4cb4836e7ac5378cd41b29bab9244 100644 GIT binary patch delta 529 zcmV+s0`C3R1m6UZK@0={5hl}KIWhnM0sfIq8-JC8GNQ^6==dCgBjnR@1geNK6?Z_| zhLu7=L4lN-iZt=!!)_0GUR)`>{{8>}z_Q-9&s^x* zvVY#bT0`4h41LM-LUbM@TnBA)5fLc1n@Vcl>Gr)yTp@r9jaJh-?{xe2=Q1pP$2FP= zN7uL_Uc7(W=Q1czU7sDJfvwnXZVb?MjspL`3ngy=bkInO_tf9DnT>YJ@p}8<_3aB^ z5UHkqJP>J3YsUsa2ghZSZJdT&wT=lMhkw&EK|7_;Je~f#K!HkV<4N$NAF&Ihn)-TQ zGb3(FpxM3jJ(Ojvo`DBTunV-A->a9#jMJEo&<32+7C8!S$g^@e2xX0Jc&ufYHl)M> zKQ5F*#^=yCtgsD_klC4IV%jeRtq&FTVI*-n>4XcNoUSr>+mHrP1tX$1xO1@tp?VWe zA{)}lsS02;9aq8$B+??1QWrHVBctiq5?$^i<*Z$%EbrD{%1TOv_ zbK~*pAOhTWf>*OLmkw!{y9CQH9At?B0Qh*DCuN<-+@SKjus38|f|wx63ib5|Df&ar Tc;I=A00000NkvXXu0mjf56}N; delta 520 zcmV+j0{8vj1l9zQK@0;97YxbvLeT&K0rinh8-GPX8Byg3bbOA$5%TFc0#%eU6?Z_| zCM$)4f&wWu6=~wZSRSuu7b%vImL1uid4Bf3Nr2e<=k@|6_ITc^>mQA*ECfu(S%S|l zCi%UL=5hc4^X2Mt+#gKN+6gVE=bK38%az~FV9eNSVlB;qzEXXFs;# z2{J!(%w1rCI)sYW1u55bq3?mU?qyuqG`ld;NJxd{Jrog*!F8fq0zP)DC?d;2#BmKw z7qh!)0zMHX6Gf>c&Fa{6G4n!~=SaD9rs5Qlpv2UO%GW5LsNhvgAnEs*8&Ajw5#X^C zyqeXybZ9J>49hSXXNdy3pz^%%H)LOem`&6*n(G(f?l5GK%=nD}0000< KMNUMnLSTX;m;CYo diff --git a/core/assets/sprites/sprites.png b/core/assets/sprites/sprites.png index c81d3af0bd59bc6469785cb4a4b44ce8140740ca..e84fb5e1c2b8328f2bf6dc2900066a74efc8f4c6 100644 GIT binary patch delta 19054 zcmYg%cQ}>*8~^j`-p~EM@7KDQp3^Tsr^m{XL1VP~*<9x+)uYhP)#}3O z;}-3^Co-xO?mazG_|{aMi(iBNMVwyqK2b3qQR9^C8ziZ--2`2J&aW}cPZTm++B zdtLhLhxc4%qW6v^zTNe&kLC-LYx_0!B!q8n|E}%$@o9P}e8KO>{IG3sVJ+&t?l-r! zGgLPAM*vEv3JI72y8NxSfjZl-{^n6dCNC_cT_sn#-;DHZ{a52{sSF>VQ%49z?XYBA zV&J}yA?gt&&t!T3IasDySwat0xv}TwSwS;kt~9X7~e2-#dWHFY0uhyc>T?c+pjFc!6)R$@GPc2nt@)t!hG707Tk z@E*U?@_`}Aia2v3z+o^YuB-A0lBeSHc3*FtP_MB6B)?M~lGKcqvx=xMzOSZZ#ExPd zFc!>6lHXcW&KAButh4y%MHq5r{b1_;bMF#Gi>ftamLe+_b=*|u!ykRK%R^l&fkO~kkk0Xsl|%s4(8knJ3`suk+} zRzdfK4u(8+ta)IJuch*uF#pL@XKxA-xYV3h z6JM*JZU5*_h(;C9&N$s@!QRfb90uq|=lf$2rw#&aRDB(lJW9MGAg%c=E zlH`%*Em$SACY0^^RxWdz7Hql_SiqVCOuLQ8b97vO(ejN?SDG9H@_c$9D_0gIYdstUShi`Z&snVU~rwK z>+?khPXv>u2oj<4YR?4M8=LKwp?tfSNBUFHh^Z`%&)#I+mayBBRyU4_jWt~s_LpG+ zwYm$jd<4VsQCW1hmKW=uat&-xqlD3WEXz%7TNjY@K)0ol7O5hF{9shXTEgrNYPg4x zs|+LI7!YkQ6f*$brEleew6`Hw12FE@HEtT{yf;XIT2^}%0@j4U(mS0s9yAfazSH51 zEF`wlV9(gQPXM?ZU@x1WeKdVOEJOz-0<<)3Zfg5#OL}t{0=b=6Oqf}6!D;^Y{f==X)r_wbz6G`H1qIW(N0$^r zw5+G*Y~9nfYTeUsa*Q&KH_`){RKOb?`EyMT|^Y+VaPz;b#@Wlk%TrAPk=2Lr6H zhyx}{;sK&4>B5U$>r@4VblhsqY$sxn4nL^wWz+&@^;cI2P=2L|AkU}^F|;rs0HQ)r z@jFL_0h6KyJMETI_ptT0>#}LzG6D-5o4SxkBF ztkGftvK^4cI|p}x{|+-NGE>l)<(}`lY__$FYcmWWWqrGQ{trMJ4|K1p0URJ;!h&Vj z8k5ed;qO_bqJMxHcK^z1JMa27_7p#7yNPl~=p7(UBj%j&ZW3Ag@WeS?`T%mlo|7as zYi}fWM3jW;f!N_6(%QI7^VX;4lINLj>n+vFr;$+MnK$}@jbVt z>GE@Sw2+10Od{Vv z0(O`-cSR4X`Xf3ca&)l}CPeb=Hj5BcBd{jK-!2N7B)mnNyO1jwpt($s7EZ@Q75jl= zApud?1K3WZZc zuwQ_&5d8POp@S+htl?tPXZ#mFu=cMfNq~pl2(TdK0O1UVf+qyja}hYq$)aJo+zfA^{t1q|T`i6A`>%gNY!y94W2y@YleAe7&Z?ss`!As~j*@VC1`btJQNswG3g zqzui>3N7PRHakv|G-cUSr!Qx$kZw#2Gu~Vf*zE?!3~-ngufa>}_!q3cJH~4Xu7aIh9-PqRiZDz>1}af zftoMCfCo~aeFT88IrHMttA9hJDo!;Xy8-6=h&d>6CZycq&@_Y3KrkvD`y<@*#{z9IP-su%sT{Onuro$%r+f{oT|EQJ}iqG|0oT9e>ztf6j^mC zQU?6LGc1W41>MZ@|8`)W8S+kP&eoVEH1a@IGZOFv_2_!MAH5!S{*2?(abX(FRqCxZ z(hnf18FJK3YMb=Ce(fbc$P>w)H*~nEuV>W4i#^^CHrX>=+AVlYvd|npf_Z;wU{_P~ey73C`rxhCfJspeZfaSHlg{##(3QGp3-b{~wB8ik6wG~i z=2D63>A~jucHl}9=>MHt-)XQDhux^38y^`mcKZNO3M`)wy7d0`Q7m7f|Kyatqc|4= zB5@R63p&y-!baa4tzDqB3k-=Q77#o28o}xw?AM0G;5^5S#WqAF+G1`hVR*-WUmpY5 zEsVslH=cE>S&L5o(sRna4#$w5D5uH!KyyzZv7ey<%@_l{eO1!i4ZHOE{&+2Y-nFK; zE`eYkiJXV3Fc-rYfAuOt!D z{LqtZc)KiJ5Z8HzQ3L_HbGblbo6cnE?INL^GVj<{@4jrnK_+yZeuzj z`@>!m5}nZ7af|C=wB=mTefy$O<}Cu$WR?pvB?Un41^nWWhq?Stx{zPwUbkNIzBS@0 zChs}F_Wn%rB~+T2@H59v=(2wbFWk6>VH=m$GB~Qu?6dz7g2XFp-(`||R{$GWeY!+j z&~e?(zVs*y~sZiT=6amks zdJ9R~8A}jxYY@tV-0?z!ImSQ|q}}+|$ve zpr?BI%kJ-7g2F`)Q>p}V4;;J{E>7nCgbn!Yv z2O(H?-Jw%_R5>n+cuq@akF-BGji$JOF)vk(cC6ym{v;~*ePFktxxgb5;KN6TwBAwG zHhzNnKgj@EC7)eCtlQL>35vq2Ob|Qlq<5vEgP&x=1gyUlmd?)lIPHd9gy1hEn(48p zQmC#WFeK{VzyGHqhpm;NQ%4RV!NM@s>zpk$^=*IG7X*l_+AtQkmGF0>?*kmbQMx#U z+IMV)6r5&6wPp~Q&vgcJ@Q^h4-wS&qSa-(u*7c19$ZY}aI%K#N=VQGV5gqY;HlJ#$ zZXHNsQP$ja-~s=z-QDb>JR6zD2kGE+{^^PM=Lj^QozJE!&pzN-xzGZc^Et-!1;0U( z8w|-toSPqmOw(><3wHz=IWa@7{NFyhou7Lei$dV-cTxTPqfDerKH@O8a7KEmTK*6- z*!}HycJH@oDcTIHU`nVh$WHxvq7~>~ofs^nzEKTy{Pul@o3| z!;9nV)NzEw(sb6Dm}`r`2a4mPf!h}TJ5_?5DA+syf{87G3EWJH+@&%h-*pB#cNMvEPG1?)j!16d|wj@ z_%?g;L`ZAVV>Nec8F_Ij=FD?+uqU&8KfDVZ%6OGitg+@V4jubd9sMk07Z0CVNb{H) zde!{fXT+IaNXt&*g!3`ZWAE3l8gN}-muHg;{N3D>*FILAJlFm_Ro)J9Ll>R-+ONAU zsf#u;M7CYkvTbh=eAfPUB-~=%%TtoO!E9Yn%_Up&GI@J!i6@Xkc3Ih?S;0SRnte4R z*&swhobY(mwTePldjd{T>ZU=gHgiOTkmK zwwCG3WufWc`GrG;G~%?j(T)lC!BAmkZ;IEmua`C*%GUo>v&oOW@M&wWzr%Y+gfR?0 ze^pHQoiV`>az9HW^ge^?@B774DTSRJ+*Cfs+_3nM(=QgoWV9NWBQ`(xJio8lrRC%h z<{s{{B*eNPSEcf5T9knEPj6x9{y55ukkd{!?z|DEEIHxykcAG=k)F)5QR{STTKL|d zGU7Egv|gE(+%?ZKFMU`1-B*Ki?=8L2?e|ohsmSDzKcfy-{7hwn0as#=+FgBDB`Wcw)BjR%D)qHF>HD;VMk_7L#L{^(I2{N1Ev|ap2b`tZdq>ImH~Oy zRvHqsH8#=^*rVZd#>L9)^2hBC6NdItwt9)ffGZ;ThgpD!vNfxI-AlgfmG5Gdi82Qe zw?AIoNE7_&=%5Bw9`nicFMmC^MsvMjY>9HU2Azv{xFtF*vImYa5^Z-=@z$hLlW(&CeQ#!i{U{ldg^Y*S4Nr^gR3rDbUNJ>9$W#rAj?Ln*($scN#sss>w1 zK$z(TYlSw=N}uy3u~cf+wC^Jmv4hG!*WSlH3(sn0``ObPe`n{qJ;(fdcFxt7I~gJM zPqPgqnf7_ua0Z^Bf3FvsbEz`L@N+{~27E?S+nUzDhUUEXPN6Dvt#$P20E|pTNtJe= zkU?5IHLolMNGY{^_iWcn^-mbAP~I@971A0X;t0)DYV~cRL@GW(v(wAQwU?`mqOGbk zrBA!`O7{i#&c(J#?D|U#j^m;S#tIqxbhS5o62|=rsmg3%w^rTgY|qd%Oq@YC*S@bP zw)*<^Z#Eew4UeSj@#DAadHp75s9&0&;86U*kTbYEG%`RqxIyL*u8^(UM zQC{z-7)Xrg+CVPdwK@yP{k_9ly}9{>NukQ!s%SXVX1l9yr!#}R-B}mSHqQA3$L($7 z!4hWnX^da#LZ2%sdJHE6iiujqIniz3qx$RZTL^z!Ol;A?`+<{9-GUV*(wYFibLrQ zSNqq$32Ara8meS~Y+=R0WzSF?p7oaQl7s)PwG!*0^Aef ztx4i%yiq=xtjH2Z3-ewLD^Ix3*=Sroxv=-%cauZ()n|C*<`vEN3$Tt%Tsc(idvu+9 z|Arz7(B&f+DcfNy&m4CO7yhgdj#7HDZ(gOW()Xv=cL&!$jkk^Zz-Y7Pdb5bTbfez# zUDQ8eW2C4x)vM1?J~N?h^htfE<*LuB1H*=O0FX_key!8SPzM&jmikoMROMN{5;pnK zBHh|y5qOb%RrE#|rlwvh$iI;kwVFsvIYef?M*b4}tBv)Uzs@Ra@CzM~BbfiPnu11bVtoO_repiUmd7~l* z{#%n@O?j)_Y2axrcdB&T7q5%K*-E<|3g5H7Pa*%h#AG-w%p&f{cHVT`Tiba0NX!~u zXrGNL*1mS__+(Z02HWSqR#e_-6m3IktD}B|`tdW8hpm2Boqi#A6P>EMt5IIMg5rM&C7u6 zpNkv*7Q9MCvhwR#DZ7nBPUP_IdZpHmm@AiuD3j=w!p@n1vN^9Vv$Dv9=Q_Dh$+@eZ zPF(8DIH()p!Y$-ocTY3&?HL&yG{f+Yu-JUtwDQ2nI<LP1`NzlNs+i>EOzA zD+APdNPFB> z|C^#JTgsQr=^tF~N9+wB>zwiVSubU2MgvQlCCRgVHi4UzBc4x#MUPYh~qa=I9tj?fGdK_e%j$5>z3d0PZd{=DCkg@6Xx`PqwBS!e{}1T z+)7*F1`Xx`niG8`bE;PCdwt9M?gvHUKj^{#8zf<@0f$@LZUD^RF7p2E$c((>RKJ=K zW+;Ss-L)U!*rrrAs=hifS)A4iAgss=OX?x@mQ*2jKsUyJJeH@EfkaK>i;dLHU1uTp zy~fzD5h?D!h-A=-hl)=V9@tHXsB^<57k#Odbp?va`OqglU3jSraT}H3)RA;Bx+jp}LWy(jlW@PO<1n=|@*+B5&c+XF9dN)$1M=v7 zPnkO#`F#g3+&LGZio@q=Zt7m$-pskLvDB5tvrkI~oTXwh3GAlxgBM#LW<~Zv+L7?5 ze7G#C$5|u`{OH0zJG*~*QQ5lpG66#-O{5sH4b_afj?f{czWZHz zq@`>Aoh(KQx9kVZ{C*fUALOQlsH4Ho(`&8`g zYN`WQel8<4|IfQxy1a)lw&+{7HNB&S(^4MTXl^uqcWY9Kyv46@&Tt-KS}d;C+*iKU z6N4`Beb3e~FcXOTOHVTpP+t;ax(4Dk)W966UGVPkql~;$Nobp-&yH%`;X#9u3#N8j zc`k8*k0)+uQD`P(Y3MSa2}Lo;!dPI|lex{54o0wMbTUx0f7twO-*6(W|N5p-;JG<# z*OmtE?cE^e0EWNsEaIkEPSZor#ghP!sJOth+<3=6)!|v(9q|m!G6T5zFF{v^1@3ivS1SzD3UMhOQ8ee!a2BR;J zVRVKL1}3IzM@pUE2JB?s*PedeUOh25?|&@}=h0I9>)FPvEU350$)^lhmZ|;dd`L*n zrBpgda%y8naG%Y-YnAmK3zVj{w#Ew8?gJ8h=h?CM-)QdUk4bUOQ6q+&2{I5bMb^jAMAcX^FisHze#EtX{fjwbHV93$4+tY1UC9 zQU!2n^|1BK1UpSud?PN6cN7!MaXq4si;IxU*JO2oe^q=-QFOocq)>qmjV2TREK=e1 z9Pm@eU+FM$vUjO0xn^T4@{Z4tO75REuCWK-h7yA6dnWSKd^`8}vg4#4wdT0PDZOCN zO;hSb|IM!>29@4!DmrreF_8JD-})k$@A(jXA^+TK zHrsVa`X~hK{!Dw+!pt3LFX0>2b7Y)p)&;l-tKoCD$-+j5|ba$b&NyMCmYd`LYp}e$- zCulALIVJUhHzI*v8TxBtN&Gdj7OHT(Os`vCFzQ-~qf<5MQ=C*g?fqDSGyxU_8yd#CQnoR(73>L4x&5hFQ|o`t3;Ar za*DSUe`s#~g3lFx!?};GJ>S#7Eg0*ep8crvP4P;PL?zKR)QM zp3XIL{S!z7)(j^SJF`&710WI{Z;vZl9$cqntG~F%y(tcEW`axeulkZSfoJR^N`#Iw zzTOuYuS38puPiNz^H0M>RQ_Kh?APb|y?4-`Poymva)De^<|=ATr_KFxH_;ptZ#>M? zR+m~MgkT(hj+`hW6^$u&W`aN@4DeZI+u5l+fH#I3 z0a=f}c_0hPb+$NO{L`8ZYR#`@6Y7DUA97ziUW4mw|FP%38p;-sc!wEA;tg$p^lh&> zBkc_Sa8vE+HK$K~&Z5?@kE~n@3s4fA*Q)B_hrl0+2vA0c=?e3?ju z`!uzBlNlo~BwnPg00kqfEuuf_A68l-5k_^F9Yky{KGj%&{|e!FpvhcM<- z^+DGQF!#Gh?+cUZfP5EnRZPyy%3(wfu;L^!TextN(`ZZYC&T3v?JZ)ME+@&+t6^Uf zoFIxACDxI(1FbdII-xumuyX6djA8|sK2w*j<=>?DvVjH;ZlH&n z<=;c{7Hex*omlDcsZdS%8+ITi>%pNU^J)D!&DK)q2(RC_S&-6&oh1KCG^3p6m=-dl zQp$^o|G|xs3T5LbV)|$ou1NjfaK?R;jlj9%JtOG=xS5DcGH*4Tuao14x*EORE)M61 z9nLJN^4_cv@7ubbAV5rZjM9a^$f|Jfsh^Kc6Gh@;1FtzUH$HII1`weLhlgJE=v|Cl z*LbyY%k70K@1=mpUz|wW{2i-P8on8GaT>l!2FUb15t&7lbEGO$Q0RNBZchApS9#2U z93T^pJ5i&Pc(SE5Z=wGzjI~+lB|Kw+u?hXQP3Nl#&N1bz_!)r6?{$A5bH9DEs+rW8 z?5&f;%X$;~>;g@Sb@a3huk;0bGTxKRD|`^s6aDBrg3Zw3&~DF;6<{SAz9s-t=SPjWt>IO7`19sk6F8j zJBwf24^fsYN*RC&kw6!bM?efnqSH|>R0Z1f~e6q`hb0iS% zd?hg~vKO%bANHb!ZHol9qi{HnC8g<)ok#-9B?3t{_0`;F$349${`u9n)y8j>aJs;x z;PpG1W!G3r7Xdu?U`n_LZznq;%SetuO(J1d;dz{E{-_x<%Xoacaetr%L5Z0Awb3B? z&1(sYJz!B_=m5P=|Da#5b9<=84aeh_aGOS}1O>(as7>u`)O_H6lkpK=`g0-6&wsAAhUs8|~# za*U<=d0u=uj_ZBrGs5d`zbyH`ROvsa^aKIBV91!)k;0{WkljOS!Q&m5t`dzF@`3cw zskgbbwt-*5^xL{uiw>{)gR3|Q-_#O~zTnj&DokWVV58RgsNe9GeHWK7B(8~vWg2p8 z~iNLVP7QzA0}+22k_Ge4j+ zB`BK_-mbQ@{_^aOwX7{sb<{n|m-_Pr0i8K<%n%QZ6jgawu0k@=M)9-v~ z4zy?w(t0NG!mGzpn{)b9(Y+Zg1Vi7>@-ibmxRUeO^!)Dm@0N(aU^wR|VfC7gqXu0% zFP~GW?YMatOD*=*1}vdcZ0$!-YGN<~yVyewMLrhq$&Bl&X!C25k_*Dx&If=s?{+IW@N14 zRtHP&PEmAv=utepl~@usN|n}bqrFApLOUGVQIf}UtCE_T#*tP{9I=i4* z47r<>k3}^2n11slzNp<6zzI>X|J^PkzK}g z#Zy&1-AtX~x&(=#%eWuHa%C&~KF_akyFS6-t+VSlk#oZw{ds@<`qHJSq-P7l+e1(5 zsvEBWaRq7aH3`6pDxT&lNsc)q3Ln%8^zv|y9Ai;=lUT}Z?& zC015eGhChhs@a%dFlQ1tq!#Md_d9XNi8sh@QRse_X=>N6@TJhHp%?azOp6{Cqn4|| z1}kHplr!W<7v9H2z7dp@9`}kS;q5Zu(VQF3A!{3z=l@eH(f`Snmy48IJA;R2Jatrm zb%hc9osr@ybSW_ZSF)dDX`gVRwbXIRtC2a_1tba8T#dV$b zt;NR04n8*AO;o$OTjd=BEAut7KoSMUaCKeLxB**6cpmgyhZgz;prJWZ6d(Q3BwiGj zqS4InL(8oWsp7*72u@h#6Z>mi%|6jyOm437&UsR_!`kRvzFucEZk#ct;Ws(dVo8MD zYmWOVdYv4ai}PiU0~{2;cbnlcbtAg8u?OOhbVbV3=04HVdEnB%{xw+8vy&V5j6}n6 zH|;$&soaPCn&DV;rNhkP13c=2B0m?8sF${AhEOjqMpjMa9SLcec*}G-bt4r>DRb(- z)h9Z;$~C6aq)Mt@YnBIRJ+0fa%o6hB`A_JI58g?@0VH~-P{3mDPPV6J#tuf& zA{lI;;u|5k_wXK7uM=MDj2HN+Zxz(RS9;o6OsxRCPFqo<0dg=^apgxIv9S2%d3$`pDxx_jd0+$IYMThXTK@dmK0ZX?;`<0cO^sn+JBj zov^9a{}b`)G40h8AQFQbvKkiBeBRq$_MS$WNV1*1fU7T4?|NUDUU$n|EWfy_Khb9H zXl!?Bd^pN<|H(IRJJx;r26!7bzNhF+Q+_>X*M6ogxwCrAUTfr-Lt4=4rb{3iI>6z4M+m3r$qbFHM z1}AzI7nu}YI`2Q(j5TE)d83pjQH=6#hT|Dm5BJs4{K)JR(HxJPBOgqE$>vRs8>kqy z`?GR_?!x3-iH_1O$D)WQA*&gm=vn2^H*p*iD()BL!tE3Ib@tMRJ?8GcOT_+8^8?HO z4Ym$uWGQ$prhvbrg&`16z7ecdBYl-dJ%Y5hZWWtsCclcj>>05d3nHlDjcQ${nMmcV zTAR>z)8?IpRjr2`x599H;!aB{kL8-?F|CuX318`QjSUVilF%^Qbj_ z*M2`Ehi@xCzm_GhYjGVAf4&s9Ihj7S_CD}S-%^!P8|N|_Y0~wed2FZo>0JAKnacg_ zYO^%wPmO*JYCm$?V_)ega|lz@)y>|mNKktO&}}aXNRyAqu6F(QF?ZVQD?n#k%&YtM zuSYYu|NK@|4*BzKXVeHtUCk}QeZgHf-iI7(z+JN;F>Dv1x!31^(Sr{mr=k|~@yuJ| zXEOo{UaxhOVFTAL+~21S9s?(?KhBJ~+*FmR92P;wj?KA4TN88A8?yxCEIKnr(vw}* zOaxLzkd+NtfiLLf$A4A)vfON4Gu-3f5=j}tACF3HRW>fC>u~#QS+&v%Cb;7q%AN&J zmp|=T7x1P7NUjqhlO}Cxz9r<`=YcVFS`x#8&bpNN*nUz<(8pbx18i)6&>l*TH?>bM zC;wW1Xf*1Teon(qPxjAsn*T^>{+<6d=2NjR8Nu@&9B6Cg!b2*1#S}wlMe#L zS)=Eh+HO;r6%^&S)u)#eKgfN5Rn+?EvLCn0^#}J(t%_8vc{WU^Jrfg<;m39SQvf=0 zNAR$JDjVQ|6Z4)C9Z{-WNl!!{8Ws)MmUO*p7C`TCV66;;XU2i-zc3;Be=wo^FytCh za7%rUBfP#Qum|NS|&K*2-rTXG0s z#Yp058l+v$;fA!>C-ZeGr~t>&IxB^fO_-y*KE<{Hxj!3q)$KzFrA(>hXEv*YwXlUeeeRwX?4rt>#Ay*Bmy_ zPd9Ci<~=WMXUSN}!)peY=Ie?`+>vh-sR2zt{nXd)U;bCepYmD>mA{lQ-K112G-Aq# z%gGYjrwWV!er~sMWpMn}IE%Udz7~517@(sq;Ok@qaY9$NmaW9v{~U`+?nHevPlgyu z(}}<7|Gt@MvCB`)a=2&_+?Rb%DG?64Q@w5MsPaXpM|b|Cv7B=d`TNJGVC6@S;q%HgQTdPCZn*#Jelx&kIr;R-vF+o=9r@a;Pn%27jSpW; zXdpFW;m*xFk>`1!{Q5@a+G9CKZ>2vx1>rhIXD#}!wmg?*G*7=}t!jEdS+3603ALFOAN%0?hz_j#xj3+>u5;B75t8E^2_g^{O4BwtY-B?W>-hI7NLJ%yNN$aZakO505}X zWk1ZYL$`i59M}(~ghtb!Ec&TktYC*$*~A*J-J%vfd+q4<1}&+5Y^f3UA+^CJhC(CL zR`{@XzMTO|H&WFLK6)?_3CtA@(d86B#DjZr{DaL=k1wPX`2+T&5se!m=I4zSaSLj zY5l724C4}d{)K1XCu?I+29Ot89>rTBHNYER z?qReG{j%ylGrChR=!~ZTX@Qiy^&LSWsJ8ri#rj4YeG&J#V-2quBvu{=b2Ugj<~v0( zKt@|tiy!W#>sr>*trudxPRw5Xc0$2J_bQ`=(ho*OUY@0eM;h%<^%BxM_$$g@eajha zXsIjnDgHLJ<3-SrWfJKeNI0&6+a}Wo8Ng8aYO?}h5+DDi+LW0|{?{-$Z(XSBX2re8!&1z+$7RN)k<`Ak2d;F#yp6IV z@08pAVJ#?UhJS9N9Rs@7e@Rd69qLOUiT8@c%jmIVMNa_O=zj}Q$W5n{a@thnGW;9{ zE;WtSr~2MN4x!q9{Yr^-3;p$@KLWTd8Kxxce45x8RR?@Bb<4i~Cs% zu)Mnfp{tX*R3F(~z$d_{X3+aZxOt}`D2O`fNkOenb6^oa6h?~%R&ggI^_a?EI=(o|CQo&7W|8#S3345gTqNVxXxVo18+^Ya(}nl4-y1k6_acH{;Z!}axd zUljVMI;%uBbF4#~aPW6uGuW8`Q!>`RPflhf1J)+Hbp_wzVnuRgsSUK)=kK^)if=s`w*&NNfOt@fbutl{!ulT7O8!4PO zOI;^m7L~tCzwdo2aU4JUmCqug5d5&NS0r2Kh28T`hefLS}Vv>}> z)tXote1E45zoGc1i38ZR>&$0H{ez6Lt~nb}RtVU>W|Rj?UC{3|@0FGu0`6uPUI!w( zxdPq`y!oKuuAR$s5f~G!?%J@AA-0FvEncsDbh16Qm4*~-Cw2A9-rYbJ7zq_Inq7Z0 z!O$@m-pj9XsGaG!_a36a_JH-uV#16r}|IMmYR(7G3l^%t&l0ba>p#ZQ;+piH4EAltPj&FS6I^yy2=3c>lS~1jKJ^UVI z;NwT5FwW?^{`P}MF~etHLGF3?^$8un=nY)(b?e6cc@lvaqM8hZnj;&V%9T7+0FxIuvkodwVqtxh(GD-J}85+R5_uG zVY`%?|DZlY&Fag3ISG5fuhIpucF>!*ZTNdl>wMv!Hpa6e|YFp3y=<3xus5=u>U3iZ1|%W z6RCIynS4%e`}EN%HVvowciAAXcON8blts{k)1j}!BY5FIUd!W zxYEWrZ6%{$cAGjI`gAW3xuPdx;>XAEzL!-2ZC<@n=d(-E{Q|sef6vE(8`KMPc%lE# zX>MHfl+?qoNcRgM&3gZH=$jBcyySyG!6d-(u>I%ML&Z@9KIua)Co_&@@}sE*wK@^m z7lo`pw;hszjqAG!q$28)(p)1Q$^h>Y7c%AAneAKTD<@M z`1_?J8A*FV1gEApAQ;5u!L?4~M9M2$(Qpa}D3| zCEJKa{>K2aw7E<;70|Jo*LnP0xMaYfTa&m=#nH3;;v+u5+wlOtb%__w6BbQWu{`Ou4wB`D`R}L@tAiC zPEAtxSm0K~<)@LVcpC0Tc}T-fAS)dN-JqT7@%a{Jv+jZF2yl!B;GiiO$kQ(~=wKrW zQVvq?7!nMVZ-1k8#W(w27~u<`n8IGCQy}tbQ3hpB+bz)OxEtQxzayeXiyc7hmR>z| zpRPbum~!VDUJa5S(^?oo1dwdqj=$stlKUMa(Adx9gm2gWcj}6G<}C1`$m9(z?)40} zUj*>_S_Igjy91DYk_lim<_cqH_0?O?9xlYUyjM>vL1Ib=GgSFZ(Sfd^E;^s45g$$q zCek#92v+fCwhbYkrZ2tlw_D;XljS4IBl^-b)@SKJZ-^o#dUz=&@|VLMwePNYY3SSN7j=nyzA+`uw1kbD4_6`K6S zX{l5$5e|@KCK$?~DaeKA3Ya|&2oOcCVJcjdELl8tKo+IoE57RIi*4vxJQwP{^R%Dc zNAdlli;R;@9JwQV@P!uJw{&4jE=n9Y3tuY5rbcS@XUl5-;B({PEmHOp*6k{UkOBZg zvy~r1gwZoQaY#2U!<(ik1t$d?brqq{xCrEO$Dr)5rC!*ueiOc1s<+L{3?DA=J(!tG zmE4LC!$H*bnT~skq6t{v0ZZu#4aqJeOWd8q3MI>X<<(Cv+Ojeh6m z-t7*Roeu5^L}+mxQdcAa+wFHU6mFx9L(Gee!R$A$Junn!xt*@9an?H5>BA$FKp6NkZLEs4RJ+B|7 z44k_LrR+t;yvH>^CH^1PoZ@}sW)>P zT8UU^sM`uhmPCYAUqeJ=Pw17I{=bztwKi75te)sqL`Eu7k z?V(zyS0w$d7$OB)pe!U76#2W0VaWdYAagnF;m<7=IUhm<;U z`>(AM`cbH{$~_N;evsMS%Q&H@dD=jYu?&v8zS$UM=cuYyiO+86pO%TASvK1N2RoQK zhs2I1N%$BkSE0(g%u}P~9KFSYIpDxm+)Siq9(C`QQgk10&r*yzzOs8w(~Up)oi|b* z7hN4@0u)wbP7z>gJD&G(KP&T`>xcbX7xlsEzBzbGV^=eGU5>y4LVeDH9Co{&_PL*r zX$|W_O?Lo(_kzsRMZ%&HjO6yke7JxG2y|oLA6GH(@IdKsQ+BAqx&93JB&s{rZ2FS$ z&v(I)I%dd!#vS*in<1b(ZkmnNJ~SlS49AEi1&O&%2X)3%ro#tVkyU#-7S!uxu5`@x z*X0R#(-wprRQo}TgqAUa94M@DcFxAf=l=^Gxsx!8t!J_T(D`a}f?k4D8GyP`K4hG@ z0jovJzqQjoUV9uD{{9UeV4Jqo0JDk1_p{Kn%Ny;nplnq~-*}y=4%e^lmZvFT@3jy% zcmurPi^19ODbE*DYQ?Qs_9WaS{%pkuz5Ai~(((`Pr5hA4KJipstX=hXO~|;;3Ak$d zZb1H=-pd*}huA#w7eCY>xRU+sJ{>byH-|`bW*#@X0K#ANLrPaIFlV}CA4Cg2WBcgB zR7#Rrw$=BRmv|px0qjf63E~Vsucp+r#SgE&zq=YzpIvANz-zmf4v9mnvrdM97jAR@ z3K&lwJ%Ow{H;dsw^dL(mIVOw?12}weJrtvRlIdwB#_HJTvf=rAM0g5cNBM80r~!=8 zAnVG7qoN7YF6&|WXRB&JO!^)Jeu+Der>xi!dfGIATk2vCyqf1>tI-4+XOuq_HQ@i! zFUY-DzU9v6JpShxFLxIhS${s*hXyNbt%}#Y1Gs@HqR)iOj>Nd5 zFjf|*@8@_5K0hHX>V`we+tN{BNV|#Gv=`9zOc-zOz~II_8Wh)Y=l4yC>Sm~Ln5w+3 zay$5faaIszgy0AXqPZ9L9*y~T0-C?8U_=ibQ7@AfzoR^&o_F#`Q5*j13fWiTSL8G> zk@zH7^a_nB?7w+eF_zqM-&)z(`%Njiri~Os-NGpa2VpO%4xCGtz{#hvI<3T`g0*?} z&veU{+Cpy_AO@ogk+iPVXhpF$wl2QPo2;}*dBuvQs6Zw+`W zd;|;OFH4K?->8AgY{d5_+jd$aY`71jkhdmXv{edt#~8fSwsqmX=>D&D<%O^RXvB5h z6)xsLJVw8@6KasReG~_t{UnzdLXT8e7IKxF#^h4OQaX0K_t0iqA8SiKci8>+Wu)zP zQOm1b4A8!gVvg=Y47Z`9ZXC8_tjlwx`cpq|H3M38K8G?H1*4d6!i{JnJqQ_=Q}L^s zEr%D~mp<8aGTOL4N!Ye!oSn2=m%N7F@-Vigb zAV#%FEP)tP7NN{25{C$zd!+lIG{D-)G!Y;S43(TF?6u9JVvW+{43l_KE}k^mdNkBR zDS#smWDLUMS!@@WIt}ywcWMjT8aR}9wL{T{a+#<-FjNveAPr31b}_@?>~>r+v|}O6 ze)6KT?RH{x^rSM<6J|#4QeB}Q2u*W?ukWQ7qD+wZ`38$K9o^Ue4r4T7@gIRQvG`jb zdq)%EHP(aMs~ncQO4{zAa)^0n^(WSjB{=$DSI=f8KbW!xYpsPn;wUv`aAKYWbDLK} zUJ1&c@SP}Cv)HisgBoCef1%v6a@$F;a7sGhbKsb1%N-fjksENegdFD;iZJ|BBRmJQ z^DquPerv4(-2S(Pz$W<2zI6k7X}<^=*?bQLqL@{&HGtQhBAYK6R(@fmgi`kJ8~tfr zy2Z-0r+?_nL^AN9dZ zor>w0)tMR|=!pA2DJEM+ZCgBo_p44=^49I%&M5b!%$P%^$#pU%!jtRspYq<;_`gRm bTebVi4a%d8rjmzndjmRh~GqT5hijY#$uve6ZRmkRuP-Y0( zQ7AjR!#UsE`}2D|e*c_5tjGO&-Oq77uj_i6&t;y=Wu_D$eY$Aby~&mphVsRncf0q$ ze!j~#;)b4C+?NY77q4bU-;ERx>#38ne#FCfFG@z&;7F?A9(yE>lQnxbO}60j1nVv7 zHU+8RYLWX?La^#_;%Ioo{^Xt=)sMvQ*L%;b{qBzOXw}T5ExMNUP39c*oZZM?>8{GI zO3@luNp3~JG3P9xZi-s#-76O2m+gwXpDp01oXR|_U0H41&IjB*Ir^TbAze=Y)>=D_bcqNbHJyn zdll?xG0F-ctr2eJ2#gmxe_stq;3x0uu$8wSn6TPFPE;awTS=!lPKF^z$2HZ908t{& zAyCeR5N(Gl>lUu&)5bNm_bXCnwSKvWaBSHZq8f98cd&JNBeUscpsPya+XY1fH&esA zKze43_Tu4ZF?Syy&e-bv8Gx>1^&QUurpC|PfZ_K8{j&7!V80Eh-(T&8;gR*gtKBsR z`#(?%fHFDF(uf1Iiq%VVSA!kmJ=Fo~R0W(j0)MbuoNQ9%NFLB9LSEkuRby3v6_NAZ zH;h{I-+F&_VR?A0%BNcGdT9Q}ID&%LA+K7en>rrz_ZAd zXR+)M5`ISEhNXC_`ujf0_kDIVf0-2tcMjw(?4Z(->z><@L@^^d;#5Vf>k43s4pCR9k%cM?)tFC@xR@L)V~KDX}-2}1NZ@ZmB- zMKqKEyujfFmKIGUdUb~IegJkvEE)S^0RVYB9uG>{BKeITeIEgy6#_L!$Li6dLsg&i z$X7%Km4ISl?OYbn^5TNwx?(|w2+nP!$>oGQ@2851G)^NI^ThB7{#YU0s#!zH6{qsZ zYGx?T2rpJ}OLAL!$pk*yl?O9`d{FzMa#fJ;+1HyPmp8zEqMH>}a=5w0v2&Vs$L@Lw zz5vKV3@#$2kvcJd_lG>)cjmmpcQGflQEQ<^{Ew<-+K9%{C%Zq2@y%IQa2H22f!LM( z$2k${dDj^2r2%%b{lYtS+cOM};QZB?8$t3HQl%hm!~%<8BE;^g(W0I3{K%+Ke)vv^ zfNX+U!3n$*@~FZ#LFV=a8Nk{Q12?rG%_?i{)#iO zo$XZjJ}=b2p=k|&PxhiTt$PXAtI}zw_i2(=& z6Cj7cyV@iDj79<=V(> zMuyoCDi5qkI2-{vfXAY*a;%n=AhjL=yj3RB*$R0&GJ zYA+R+5aA+Ef9I1qxe8!ZRmlT8YjxNmf{&pEWF{?Pz7VvC573N}Dg-DF{SD^Z9=o*S zKuH+f?k;!{z^n|X1HF^3ncsgKuXlLWh6G6f<(H=RO@A!_Ebwk>aslNo44*Mdg#O}S?8A|XtueUI?4cdI+2?6%`Liu|K;~n=-!Q~i2TZEqx-zohI z#5Nvag<`*XRdtXjwEYC4-g2fMP6Q!)Bk&oYI)IQLjilhAC{onQtYV|RVc)9v!E0s& zNMZ+LVf6DaNq^jM6mS27V$T6ArZQzME;`0YokRFhW9vr)46H=SP>Rk;kvEgn?RN5I zEganVbv2PfWMnNeoFrY@y>f-A3&D9+4thA;0!(U2O4B?mIG&I1ZwDIP_T{vlty+Ix+vi!RhZ5+i6Qj_!+{-!Hd$Kr=SW_oF?JokX3U?>4@he7{ZF#vWs zYKhXS3alg+aB8ji$x7W4qeeXfdw@EKoD1d)huIJPZ-IFLE$3 zFf$|s+Pv$dKjkx{&V1z8fz}>4>ID4exm6Mkr6e-ZDe4Ghz3L7HOCqI@rzoe`!%!N@ zfZ>%{MybBqQQ*;)7bn2!@}bkgn^i4G47AvPe||B7J$M%$TG*)(UV8Qvb~vdH(lD%x zlk=q!4uUovJrGQ6VKJ!+lPNr@ZZP@nRyUMGQ8@rNJXTx44WLMh}pu9!y zwcf$bS+O4ds#f85V%w8)e1sdLI|NZ-2RF`umhHE@_Ua!$74wTgnOt{Uk-x*cs$JaD z`Z@D0F8{hs1d1Kca#dS{Knn7OzaA6L1EIv)aY;hybaqVWLhwH4y62%+Z+b=$^Q6{hABqK(yYzVx z$r>Ca@h)!m0FJN>n>i&4ZCN#0k`3M`OA2Ez1$FdMKeaw;M`>*Q!UAmENca`30)1Se z3v)ueTgp=$QpyWW=6UVsmP=UniSQs~U!aKI)ydu>OvA8>5_d?M z0B(3e>>VxC`6TVpain3CH5Gvi4cGmmizQ55F8d6nJ^!v?U~cqcq2|+qBSP7YYEu+X zJ>NYQ!mj3E1f->rv)zHF3{x29W2t?Sq8amGopbE9Uf_!e?4llIi(F;0#6#*_57X1^ zIsDg^-bNRok|CX!eqo)xVsxr7S;m#cTYUJ+O`hq7eVW{J`=!0q2GW|{!7<{v`DpB=7p)otUiR&NwesbgJ@xD zmBh?lNWBZ>+h7W$yL?>mlT&;ip=4=pv&cyNyuh2bk2qI}ghKUS7RN?QzqGauwhmTI$thX45ebDy-0 zmr$7x=x3uz4X_uXurn)-XwSpy;ODr)X%>K|cK`w^%2HDs-yUOy>*M>E2ucs^4rhBO zA3?FQDo4UI!Sx=VZS)dD9!`S&*xEb-3JkVT=nu?6-~|_6qz0_-9`j--@`4JJ?NK1% zVRBoT|E1wF&xEZRkh-%5ZdYtf#MW*Dxq7$d>oGj(E{q%{a1;@6<2=GM*Cj{D>rnsd z+RP+6wWzU|v8pDhTbY(FJ>QBRhDhUa(U5rQOFmk{EHnJE7kb=pN9+0tvw^gT^(ZY+ z0+}X&%5yWm@iYtr$WEWQeN7DHF0Wq&x0Twhk44<%CrCo;y=iKqtQ@9gfqy%t2PN5S zx6|z6!Xy%ZF+m!MMAAyG7}J?KA0zve1*EG2eeY!~X+Wx1;4TdmxxQd&BJ9+LgV&l; z+2c5{NtSH(NDQ_9aWpr_PLvY?egt^et4Ayl*hUDKS*8mU!PL!FkPRsngp+Z(EIZ*< z@o_|sicjUjt-Fm!-nG&D+x@zW4J@U=?xuS4-vhQo-8zwXG-F*$J5xJ+l&|eAt%wpq zHN;YP97ab=J*Ad5y8P_j>K`6^yEveBG?h8g@~dLtN_DX9t%EWCisR9<@yB(D zSkiI`74zaXbPhaIpx+=;ozss?&k800mkHiUh;+kQlnSw3Lu!p%afTNj0c0Ef+53yO zXCU(d55-g;qDAtgw1&nwQ(qE**>{W2o~8Y$5*xGua^N9Pi}L-;+*(8GhiWja)%CWS zJ#{17_rYoM01Fg*#*Rn$t~Pjh0vxU22A@$3?_=nV2;1Nlx>g-rf;Q?fb7*F;XhJHd z3I`O2CSZ`vYS0Zo+u8Mlv^gDMg8_+RYcjbr)$^i7{-|eHfx=AM-Jj?Y&Xr26zM4re z6&wy{(i%T^8cU&9oyDV$K*^ndqkd`kqE)i^Ua+H$ML?}#Y#k8 z{UVU>BFBPJ8%vY!N+P^sXF`H&DLbXD`}iG&T9gcy^sXDvHU}2P7gec!n-Y)BKB#Rx z+&9}_5Hf{>PKP`enD=JOGt>^EetWc{&F@8=%=OOiuWwsKr zEgQgwk$cwp=!ZTwcw(sqZAzSY*!4Gi)vi_xWruU~k_ZMof(2pK+ArAb^zV05gJ_ey z$=BRot(etT)g=D9_=7diE&k0cB-%59T>fBup`-}k0|f4DRz-Qj-1qQDMX|}Ok2#uo zYqkt}@gtOfTAaQQMrfT8=)osf;$(JTYs=xTfrBLS-#(Vx8B0Mo?W2ERR+U{{M|-B| zT@gMHM(p+l>U*?0&ur13J@2x5eAl8fD+B(+Bf*s`81Q_hB0Hb5()0HS#f1RF3Pnz9 z|7tzC!uN{=ggJCQb>YE7t{o*a#^O)&YduCab(ILG3r>AI?q0|n--8VkUS}qmgMTYY zK1*2sZ6NzFd*9R-tD?9!!!gO15iYczy(40<)sFse*Fxdh$)<3}*}X>Q>eUyH?RMbFEC}WQja@BU% zt;Fv1Zc_G`F}41;e^v?qP$Gx_Mca1P=htY|^t;vGv7s^Qek1n#nubdrPd4So>^4Je z&><_)reK@7gHrYQdUwlKp?uf+UHR`;u6zp=6+L}twj+?`L9FaU2_@|V<)0F@^Lp0l z)b-k7T8U1@*w04;pLuSz&-Yj{_B)9xxh0n@;FsR{^*y#7dmn5&k|;j*a%WkSD*tkv zVx*`NdMF^Nowrh3uNuHVS!m3c;eka;Yx^1(zv+7oZA;)Dc?IMI(02XpB1SmH+A zm;Xxmhedtm@ye=Ci2*Ja_E*#754UJ-)BRw&Hflg`-M5nPq>-^)YHASc96oxG`3BRr z$!B}{9~+xkQ~JRcp$IZM zEhXef{kR;K@m{mfgqzyYJ$BbehD0%lQ8}LEs=aJHg$B7@Mt?x6_h<|EvXS5#X*qkf z2>abhV|j>5K2+QSa6jq8&UbHRH67?_cH`1djqKpOIxgDsKy-@z zj`S1T1Un0>It%Z(*K9X)Bg?Ixe3dSLn`j;vJ6YBm8d?7O`|a}fYmTDB!_oJw-?C-L ze;w*qLA!l*&Ch#$f8(IsO#l8^@8Ze#%nO!VcFv3VoM}!f>by_?ll^=g-@~~*GvV{& ze@V=Z#Tv5v<>PFU`}V6E)iKb1kD{+TqMtGgi7PJ2LwidE<{8c3 zjJkpPD`w-)iS>v2wTJV8%ueuq3*_IlE$&N8di>YinsbcH)bm$Ud}&Flx7Lz;`M1`} zoXN)smQR!V$)!rX@7ZUrIM}w7$|9hH=7?6at?p+02tC@ra{sba1RBfINPX`!kh{K- zM}Yn=<WU6OwM=|O8{k}o%OB0cnf|`~)F+bnmys8N%ymST;MoHy zr{C(f1%4vZIe5qc570zyba4HTQPmrN`o?lmm8zwWs64)LOg;H|j@rcv8<8zijX_ya zg*YL!o9%nlS&0KtX_`CSmJCKe2M^ixPC8v2x-{!anT)`Lm+7N=emS~heZEznOTOEw z-0Rx$X~OxP369c2%?2%%gm-G+7xvJ#u(lrz0JtG(9~gbqqp zmX&kX1vy7|cq#>lbNQV;@9(y9%e3FU!FZM_92LS@-pKc*)u^7dR#uC7dTWaxYsuaR zzm<+z&Q=}Vzqi}FwYcVNK@0&h7QDU{Zs!aBy?jUwyN?Oa_=~H;2yU)n*QMBY-ixN@ z8MKJ}6gs+?sp_G(z*!-yDH}9@&mz`)(6@fr`F0OWO^4+cb=w@=d zy&^Z9jJ)QUve7@(73XN)?YT?ieDDyb$sq4f(U*)0XA*c@eD!-_ZGpr0tFxjG;fyIe zZG76pPnA-a61W;|x4ca*8=P2UEg1}GHIToMXPnkiyi`DAWrE&~w!j-pWPd9`ioQTl zd)b+V%Y4o8ejPYU)Pl~#Ft&gp*XH??-H!IS<3pZ%?t1Lxpp*$6nU&O^D4UTi-5_Gq z#0zYweNk9LXHxy!OMnZe1QdE@c9{5U{_uFE-s(B7@mAOAEkaprk2zY&4um5h1gXE2 z55w`f{B5WBb}jxg7+5#2GLL*L*W0)Rb2b4nwN*!+$mo0!Bql3YNKy}lmb{$IaW;M# z9<9Dmh=bMIN&?e+mD=pKu))C3cv4b~h*8~A(@ibefbMA9xHbvYLrLB^uf#fCC*<5K z7K#w8{t4Uac^HqFX*T(Uun!SM=ENC_dKD&*3?`=y==GU@?sp}a8~6vsdumiJQ)~&$ z*(dM`ZD#?*j&i(K)05!bnL^$Pq$3n#=CajRR_Oh=+6Qn!j$n@i`|h9DcBL*3`p^1a zJ>Fq+A+P=ydL&-ur&!L-&H;sM-?JnjKCMpWrG0}tHuP*IAYvm``f?6HIX>r6g`sJ2 zXmA&&`88NJ>{qJyKQXzSvL=pn(}N$1<>@?nx1xywnZF^;A!B0L%W~2&Yd{Q->WCfP zD4VTx3|dGS>ii>F*)f!Np8zi9zSh>glX?fWQS8&trPrZY>(y#~Url2e+nM-=7A6Q7 zuV;abA0qgQn}44DO8#^+dAC=8A=ie1AxqW2?@hH?sYRY4Qj`tn$;h1XH$}D*58oD< zcW^x#T=OZ`l8hP-UGX>!9PCGOw&?wBI;Vp{gK!xfWu@%Yx?L#9tk8|VaIsD>1E6

m?O{)=|;dImt|?PTuIico%kDab4o_VssZm zG4XB^Lck@~P#7)EN}6pvDt65OU8w(}gSjyB)~S8}q0q9q8P>=R?jUXH8sf5xUd|1p zmo5p)_~Rm8nm)Tvmy;_h|0(ij-smjQu=r+YxtVl1M`$vLAp=eihuo%x@@}&WXg{h z12;f*dR{1xj-*`4%-a+FY2ZxB)nub}JEDn4j-4{SwaW2@Unke0k3=7wv51gpS+1D) zQ35F2DPF{bzT3&$-7dPEz=EE~^3?bE@USa^()0@EMpFY&qLlw8;z;z!F~5ax z3D}1(k$8ot#aHUoSe`EJ_a4o=2VQ&}($7?w>PLf|9#&3&GYYx+YJ}#%t#GBTQda%O z?g2(WJuBgmT5A`#2pKqV0RXwd-8DSG@J<-eo}KS0$Jmu&eujdSWON72x;8{f6|zVN z6pj52Z<{%>n_lAh#D7Li^M=YM3UOeD397#|5%*+*-nx;45gGOOuSXw0rI22*hz_aL zIZ68FtKV3PicoEN`hb6Vm8oG13)=xBO%861kDcJ5+y}}X_z>11b6QNHo%0lU=g#gu z@!^5$rK!u+1_*hCiE^}RH3?vSt9-!tZCE_^ycu`BK z_b265_h7MKqY97Zw?C10zyCwCA{I)EgJOnPHa_%KOW+hM+;<_EaMR|WQo6>nB`bJ= zsb`_nn{iwb+PV^E{c3J+sbBJN`IpG9JpRD7sD^b+_0W}Er+$Bhz4GhXx0GH;fY(9K zz@onIfg|QZaPsz^-2@^6UYgy?Bt@WFOLT9^F53p=XQMv=9{d_df$}m_Qc)KHO<_!y zaSR^*5Xp`+EWWcq7&hedA1M1MWfnyl>!T*`lua3Qrm|tQ2(EUY@h6N@{e(c+@OU}G zb_dMapvNjbf&iEDMh7=ag?}ib=aknIZiD>aodisPjLkVEFR<(7aGA5&YN*k|r`fPl zjnZ0e0Uneg2E(FzjVDH#@ktLDIs|AIXG)a=a<1$S0{L5T?wS36beHXp_~kWd8ul^! z@P%N4#j>9y^q|A`)})5)A9k{y^DE-__Vn*hU0voMPW#dS@MgtVzjK`l%ApB(==>zv zRr8#1&%ZkyF;)tmE3*BhEkw7xRC^9ABR#I}Edr{jky;vSUxo%TI_ibtp`S^0+4qKW ziwBR8DAM%lzj=GiTo2qsx71%v!|6|i^~GdgN0iWK4+I!CK;f!X?A(NHf3de;RS+Y$ zR}xN|Yd=2n`1lJYDl52E1Ub&$3gvBZOI*Am;h>#p_wDyd`Y?rA%d4wU8R zon{jc#4pOspRe7f%R`=G!gRp#eG|9YrC6Ulw^!`OgP#GWK$Y*wW+8tC%f6Nh&g7Hw zTM)AK@Zmfk2MfcoAPf1t-CWCS;})-$8m?No_|Gi>lwu?nMv}n5@tUPE-GG;IEIWLm z^J6WMKph!kLNd}2b+8PJ$#6tuQ8U*IogQiYK3mEpj9i8OCtdkWEn`_1CUbfurO_?} zfyZN2<}?@o*>@A(hhg%VC6l((Jv^+^(Kkb)7Z1 zXH)cCR`!Y0;MT0#-FX+4goXsw_%d5>&4MBI`vSs3!yb$xw625}CT;T(NYd|8c37pd zL!t(z%$|DJ+O-jrO!a%TWxQK2K_CmS6V;N0TI>Ll>I013*RM)JyqDE;2&#w5vbzj4fc-wVk9? zAh8}hbw_^YQK2mZ-?BW*bolpQpFk%8C@$}vIAqAzbkko1hW*kjXa(Iv`uQF2R*O39 zD=?t&Y{h3{xwssM$j3%1(5=WoJNNhuqcEZ`JCYHjAWQ!}hxXsQ_u$8* zM-tZ-*Pe0H$gStbxt2tgawzs`&#(QC2%4U|<~c&B6)?gYGoV-m6XBpZoRk15pmN!b z|Ct^KFz4d7>z)Q`m+<(AV#)ed0}!*eimAT>!JJ_DL-8;LlbbPe^o652BM?&W&EQ>i zGUPFyoQ27|wfogvHGr zB}+nT0<$>!2D`akp~|+p5^dX6i1Pw>}H`_p2oep1?C9^ zrA_#lz8V8$;VTS%Vq3^6`c#-KjHiSif8PAp)qhPV^ufnTrF24Pk~gO3jQrbsC+7XY zRr0XtHYEZSk8GG@G6ErQ0ITy>@M89c2=xGmr5Y!G;yTG=?ZAi<#pq(e(xpx%iU_X9 z=Cu#{l?xy40hVdk!)T+?->v4aGbstZm#Tqtib(Ih%h=E5&{A+hLrRq5!MxS_ijBk= zf|@B9xyD<8&cn=(P$Xlh%uj?W!p75R>9O$;oBAm`!r+2*TFa8C@1H!Yz}G9`>`30s zMzmXzqFygNPllUYd)TSb>qHQ3j7Me8^QDj9!GS3%0w*=;{eEW)ymtTv6Bx0$*vman z%F|p~m^F64nHiNi4;UF~DJ z0m2#egXY6=OJzeF`g`bBCR5E!SImCfEB$|9GWtjFuiS7s%9ruW{Nq+`yDu+hN%TbrNfrWxg?v9|o&-ZPJ${rIDYha(Te@Q|al zKYRSq&15s$qjF0*Lh)F<=_V3Xrn)cSzwn>{B(1SD3e#E ztNbK30b!4FRrxK3+doQxG=WN>9GUeKwbJta^YJHtIg)YQ`Ji>E$+xnLp4fLEb zkCB~%Rcj<)>Mdy2lF;K~Pg%u8dr=(87cmaLvSGu0De;Gj*P%*jioz@^_TM-Etsi3i z4T%@rc7L;~^nI#o$EUu{Vm$@Qm(}plAQ0()_Z6*5(W5{BN6A0YH@H3V@Ih{fif;Y- ztH6qolt?hV4JOg>FC-$#wgM@rdU5=y!1S+QF#P9`^zmn8_2b6HNI#LI;+H4%}d?&lF^sO@uIG7<|&_2;cX1-mm~N z38T*$p-dH?v)-Bp0YL7J`FUeoJpi*_?MY1DA6wgb-y(srr_ zN<+fM#VL~;t!&_=8HS-B#Ut3M@Ni0OSmKgH<=Zs1xrra!YT9qtRz+=1J-qH{y>SnR zNNs0Z4Pk2Grfw|XVa7}zA`d3R##LIrN4M}J)Z*m0!xEhFgV(z;WFU8P6pc2=>d{@| zPN3qxMHo(TlKt16`wxml+N@wbO57dD=Tj8sh5ku+$ZYGx!Do*nrmalyMMGkGsSehA z?b*$4>qa_ON;mD52lkR6v!yXU1|Ok~QhyF1W7d|N`K#WMIHlOrSD@|sJt_Eg2kb@f zn*!M)LxCG|iY(B7dsL4XANV4Dx8>0Q^O=ai53Fs{if~=mXt8^VuCq@?m=M*U=y3IM zD69tQMs{MMFU~~0xFY>hyTE%sI5fG+&SHb!#10wv8QBV2nE&iDAMIwTZbK;m8w<77 z&Z+Qso)bkadLe!u*b8@;6)1F1Dn^Q6Dz(x>wjeeXvCpkaGPp%?)Q%r?P@oTWm&vo9 z(WhQVY1U2ZM5?c$Te^(fWOb$hj=I5}AWWuR=2xEmPvA9Qs9cfPs^WvWl0S}`qADu} zM4zJ{8Qj@|yP`Iu`0^%D=7m~miaQ_q&xbGzC$FtySj<8xPzmPvN|}AZt#DodS^*7^Clr!LuG3?)~~~ulIqyiSt$B5q0^YY=JF!3LYOF z#;m1XOxCA#j=ue%cT$KLnpwRs&xr_flYSkYTV*epbrgPX&l?V#-MW%|wZ5!=;ngZP z0yh~2YF*!Svv}Y8Y>_us=hbD(emQ7AK^WJRy2bBO5j9$k8wwhKc}MKwWGN=;npP@N zvS>)cf9lsSN&9ab!6}EHs;$IugS8gLxOC?X<^UlA)>i0Pw>i!~e$4Vym7@q*VN4$f zzRGVd165`%4byTNCRZg&453`xxz6Ly7$$V8#^`$?+fk+&_J)}%=kY7~9<9~2!~XVl z3|l;WR*Lo1Yjh7vC0mnuXet~W90tKQmftn%&v!1pe2vwk@2Z;Dw0oGuA9_D**3WFT zQrdaC${BkJvF1Ze8eg7eO{kd#TJai$5i>?4ySJJvPR?&CUmJEqW=!5aBe~xHdi`gg@YGV+uCCL(r?Jte-FegRLWFn% zH2v<#oOFj_sdREf)ykm%*d~gwjSR)a#Y8gO)}KIG^D-BPR2~S?oKB1Ko8Cj981&L4 zap1&7*;cC^3g^bG*dPEMk+f6yF7KIqpFty$l>wOfE_+Wo#FJg3MZBjwo)o71P`kgJ ztad8kR7b#gWMY{y8xAhaIo6^LYq!QL0+)4Z)w7{l_2+*s32n1fxzXgi94rN@(`&4P zS1X5dCdnQ-uU5N>-w)aD(Hqol|DaCXc8h<=FRfnZQx!9=XB1UGnD5n3nB&oY4}FWgkXa^A9f;O%Jy@|qo#g;WK>{-G>8_{`m+OEb8ne-zft zYvot^!0_85eP+JPHa}J{w6xr#@|#=j$cljvIDKhcXOHPT(n9FFb&2;qV6T;F~2$)&;8CXzia!ye;py%wJD>$QELvO z+V1Ib63SM$dh_vHR^Pw-K12U3JzuSTh$(%dX2#N>d%w_TG&Anj*HOKT1zlS(nJulx za>qD2a>>J{RgFJ*_QRmxn5Nb7Cf|+=DPK1=Qs#w>CG^NcJIv;4dx;VFXZ-b(Rm0O$ z!hTn#eQ$h!P-Al#uj}J!~ znOf?+pJQjy)0?4fQg6U5ZlSpy zh$x>`jv=npLT}WiOFW+mG!rcG!B;8G+&A+)9_Dzgyo| z(So_-tk6{}kI8!NOUkR7>-j0{ZyxT5jq`5(do=3%kHO*c@65k?2eUEmivYGQS4{EH zs?9hu{hecI4^V6-{L;oVF_UxmeI`IHN=M$*POT`K1s${YiQi~3cU_Uc60<3KJ0%SS z*>OUE-C!;AJa>mY_M0Vs9aFL%# ze`bzyQERW0-@Hxz0gl4cZI$`*-KXeIj}*MKpDV}0~* zdk-&t<$$&Yvt#_oSNj}? z!HhJiS>b7#8SM&pU^1KakPQ8WP4u)IQ^`+muK&2wBn8ZFg2AR^d%tXh)O3Q92_0kP zV(1BVvD4dK_b0X$)l3Zgwl{!6{uP2(pHHkr`~}0uKQ1ZXjCLf-$kXwfV9dU!-HUly z;`%NW$eK=qdfWBBh-D`YU9WBor?c%-R$4!37kIKp@mFEi(%Fh4ws+NrUqqHj&z9vX z$73B&9ysV^*6etJE0>oSFhgTSlby^Dp#ox6`+SZFaUGQYpXY20;;&C{Ge zc9-$~LrjNwd^UUU+*3lOSJ0K}%gU?H^cH%x|kO0Ys`%c#j}w4&k9^W%;6V0{4HT z{rUgFmjZSmr{gb(5DnEhpM4W>V`NIfvP^S@lluJq9|#Luab0XD<@QunT3o5jyd)da zwdkzO2NQK8Z|rgo%ap912h6J6u+1ldM9;^;v&BfowDCh6(X&o$Re0w~iIXRWhBw zcm-~a58HnWGA~5m_WJ+MOkx>A9|wKhr)b~ucx>Z20=>Q_w|0ruC^K$UPwf?_=~XmH z9zd-`MbLoy1(p{$@iwI zb1S#OC{RFdJ&Bas2$VPGUmqMP|M|~;7mwlXxHF8ylb`BXX|gH4E$b6y1_>x_P_1d! zVCM8xjH1Npm(?0v0;}acmaCVqgvVz3H{Wq4B{3&ia*e&u`hhMq??LHgxLNO`F<6C_N{n(^X z&;G$~qi4DI{&yFrHt#|lV=Xk0GsnS_DJZE&_`X8Q7AU?_Y;s?BIn1K#;*Z?-R^0>W zxvhtMzr<8pM+Dt^W^?iDfEPBU8?WnfUie)^Kr)znD@TW1?yj19HxJYl6?-}YX`O5QE(d50n z?BWaBC4O9+Eeuz`*~q(|o5?f$?G0LCR%m|lvRR>QyF+ef>hN6w(F3`h7B0+*j&&{U z;w{}p&i^!Cy!%Il&X|QNm8a;&-4;ueF$v6&k@XETGyFN!>~AOGxCb^{ygo11;%{n# z()2Dmw$b5Ji=My=;Yb$_=6H%{-b^;PRnh$WY9tUcD^PZV;F&(6ni8t<;H zx~X^)NUoT1)(!K__BTyG#L*wRnjY(5PaZ`>{4@oar8F2dPp`Fv;CS`z+a+uj4C|34Fy{q~mx;~w& z_e&?q>aN82Au8bu&xd~ZYh4;r-owklzzBiJbC@hZcb56D6=59M zG65_bK4Du0_dnRyPpXcZ?KGcZsIX9Wb5K0KTK5Nz48&{xT{T%~nBV*hY(T=?Cm%3# zgDuAKkEPW=h}R4=kY?U=s6FmV=OH7oOXjjH4zi20F5v#+1?1`ZKFk91+KGMaw?K*^ z^ELq$B8`-~mbmSAI#jR6GZZr)jBG`9xEX10DsGP%=w*KQRdhT8#cdp$N+jlvoGZz^ zD}HJ$hy%3bOg0CSpYb-wIbId8!G$|$bMF!3&GuAwkMSPJG7k=m>4u7di5|w{a7<{H zQ>)KKr!?+YjCZ}#>r*{kmZW7jpP+TpZ7hgo{j*L5^ELjq{+HkBrYlb91o;j`0~c|~8Ot(>#JEzp6P!QD^adZ%LE zc;l~}7)kt8DuTmYb2>O{hpRDIZ?@ht1<=3i@M4Xw7)RxHqejbwL!-ARQ0oDv;8`W- zznynjA-2e}ByOK4Ht{NyO)X&iT}lK>={k)M&c$HvP_)<`*TX~6tT!k;y6%X8;GCm> z(T)^s%-d^bj6b70zDB}!dq}Nrw+2QK!_V9Ic@SqU5eq&bx{tSZ;8SEdq;y+gI`AGE zoSjB^HJ<*mEd&xiHD8=2R;lfY5c;> z1Sn_O%*);n!-tl+hzCw|ePhgY@>_cJ_A!ReCB%g?FJ5v+OUs2JtMo;fc=98^a{`=j zz<`qvXDIu{k!fVDrWV~!pg3pT`51aB3_1rwrgyx@*o~1Y^V~+v<@G{S_dhjol8O3h zy`#>dK@JkDwVYbfD_|J1iWSXED7Ld0$2_?EL0aY?Y&{PDgahu^$1`IA&Hc`Z2j-Uh z?ba2K5yv!gR;v5X?igzvMN;2%pB|pzzzo$~vxlOjmuNrcgU6OMCnKi?$3mW~auB(K zoU_(e>Q`j?C|{8|o?HEahrECMExi)-vZzwOhnAeFVv;KOkGM-EgoS`6rYmNGrO~b# z?iU!$U7uZC8TrDp9p5j;2Cq)s(PY7Jn*;5E7$|_D?BA__^lt;^slO)%&KSpWl6-Rw zJ41sj5X3xMuRRS3gPBj;==S7FU5r)n?a3Nc8L>pT^Dlcg54{Q~^ z`YBWp=Vi`@pd>MH$2}neM@)kv4^9Awo&4eMTmUJ}!I$KimD4XoV%D||%;fuQyB5kT znioC(@9SVu*DtZ76FP7Gnm=czeE6ZRy5cqzc&})_v*lKA18D!7=_pJ?N@!kniFZ6d zij^>oFj_#6kGXAFoX4F76{dYR6r$AdTS%$oJi9d1c@ z9tYG%crp{z{==MVn6iSY4hK)I)39y8uY9`R;fr$g%iP%Nmc0Z}XI|~!@pN)NEOeKb z<2M}TP29jkM!C%9S!31xP53HDzGywTgZv~=YAMYC1qCAT(>+(Q!)9P!GCyLl9MxQz z`moO>{hZ3thTVf6p(?Ksn5if_(m80bOmD|ddJi!3rbVSs!>?m)JmZYQ8~l^CRe@U8 zK+-h$?JiVlTAdP#{6qkaXWRHp1P!tV;o0_ti-p>MlUngQVYgR>J>Urw9B~JZ#1q}> zcqsRrz(CG)ES_{5I~96i6+2ef72Rep725Ea-I{BXJfUz&!tYAN!J=g6OCri2RUCY$ z_aFRZw$yGo%L@W2geV*&zGBnb3sIqO-#6aSG5;Y3oRE4wn}=Zn@H3a%*pXH(viH$_ zF2ns0b^0EVXPTC`0Oj>HZ~s(hPMSE zb||I)1p&2q_?pZHhzMSSl`HHP9S_s$(=bYG<1{O5c1;OyTw zdRe`UH@y}Yr)S?T%U+~i9a7i(q&!k(s(f=8YpC_hg#nzViJ@k2F+ts=%bQK{+VcTusbdcySh6W=-YT^t0Dv z`xMz{Ux)ZZ_(&lWq(j+O-B|(2m+p8Ps!@Nc#)=fu}r1#-Zq$!2Se3-o28^ACfG&{|5$~oTB)(@oBUMN zvou^hn+>)ey8UP07I4E^#dch&^(l9rDL6j?fcqsj(v6h;cK!IHc9+bD>J9sXb%+K`@0bEueiWS zAcD#f(?dg*Vmb&+OWpFldD-Vm*T(nJuzz#k{0Wea2d$WI@<5Ftvv9K<~+Lgg&axvdAC#Xy$A?O`5_y>zSYei@(C$J`^0iF;ixcutvD zr*RW_=skN$dN%^sKEx98l%v5*1HwrpHpYHDi0+kTJEGrn{zk6J4n^$ln>S_mF-)}H zzZ0SeTFj7Rli`sim~IMGbH!tLaQL1Dls?-lKnjsYJOA{b#nMXUh6tv37jRy(;G#rX zL8H)SDv2{kJ@Ae!;tfOOoiSRdpT1ja?_7k}HJ73lY+u?WdYjNwJjq@F4EnSdlqi<8 z7)7Pc168MmdW(>SA9jpEV}_%2;rpE<`6XV9_B`H3um0cJQ${q&#H0pw3$DzTmOtS8Ac$ zu=?!AVTni)%t~(0ry-wOGMkh9FUy6V2IMbNQL-AOf|l(dx4EC4Z!1T(Xy4V%LphUf zg85kfD--Ki`pUksB372B2V0$bRH!cLmSFf9RNa?`%bhfwNsAY%{2=MBky%`%e z89%@1lE2OD5F7bbU*O=NU$+X^aV*%kox!Z)JMQDC2qg*=e7Qjw>|d^8YFAcNm>V>( z!d=AbCMd0PbvV6(qALWr^9yNsB1|Sq%E@?Xy2>WR>;f(G3Mteh`a6(3=d#>`f6Ll9Ma{^WKZ+rPRfKheB8)8>=lK404<6|9&5M?6s|)v^SK0g=`=r-hDAYow%w6qcFe?7gtz2V)izd(V?V^xTG9-a1YTc5_WqB=*-ua8 zT{xu=DhJ6)8*{6NH^&}M9;zQ_@yul`pli|Dd?~!oL2;&3bL=`89_rWz_3qLYNj#k3 zqSQIg7FF$!BVp#4$!N!CGr3Qtz@w|#pcXa4jLEp?bFQD{fNSr#;GIkN-8I`QZR~Tk zuRQ#}CayfHsWXdz4`c^fS_y_yK;(dyO(8NYLdvQ`18q|fkX=YY8!}S_1flP-i;ge_ zs!W0qK|l)uM3j9IBJ>#6T2hcDs7OEt%GM+`A?cT%Gv~}d@6UJMz3+bayZ86Izsng6 z=)a&!f$x{5-s3rJG5m`-v@jUrt zvH*(qd+7XRD)Ii-NTop^btui;35?pyOv4yU&$YKDc+W(ch@MA%v0s}gvQ8+Kw>e!A zZO4ejT*N6-J?AZc=bBT{WWv<~Cxin_!vFMu0gJ)#7Hs?zIKF#p>KEhoiXe%fjkrVy zmN^-}eii|b4#0AhE=TABV&`Xd&cy(Q-0eW86t{saVPIuj<>UB5(K!W7-E47J74>Yl zg+rc1tVmCWJbVLx`M(y0%#^@d(Oo?fR}i7bwEnzAm-l%m!h_nANrT5FP92}U*&9s>SkvWHGW-7okP{L1W z(T{tnj5Yw|+w&H;Q*^uTgavGTTXg+8psF`V<5FyO@n6adKUO)BXtZ^3H@;Ym3)CrOhPz>bSjQwT#rG;quaJr zMp7C|5jY$KWj0cR7PmFGzh>&9;3GFvDbG@}>j?|>e$nQ6Qt=7g$))q$R9?2KZ*`Tu zzCxJGo^q0S`IyZ%?dYS|{bT_0?B;1}E<%P|^WzD!&z@nys?d65^G#`$Bo=L$J5Jeo z?gG<_j&iv_PV&W`uY7lboTyx~A9ukxo4-L#sL#u$%!0AP?vo%Q261&?cwOqR0=`=9?y=7>H8hiIy7733=6 z%VE>43oPFd$MQ*vMlYhQ4MAI%TTCHhejB@m;83f#Wk>R{LNzM1=vHtx98aJ79|%o8 zv_QRpO8IECH2SAA^T8LW-0ZQsuNOa{uqzx%fio6W+$9KeyG0uXpL@Ak(a9NWeY?Ki zy4?P0&f_?)|L?kR6NECrj~?9i%@=UKVc^CbZK*v`Tc;P>pScFCrB!>{|BRaAAM**z zJ*tHuhqW+w{NZ0Z#J_w}`rn`ZY*`3)!=~%LHCr~~E{(hdqV~!k#F$;&X^UGCgfK`G z^A@8mYdptuB=Hw9CR?v|Zo%bK#vCq?1D8 z2Umf~K`{+qYLF4`Yo>f)ZvHUNOZLIKjhwsN?i&-j*76gk;Q)G8hr8Y7c#>o&wVc8i pk6&7a?2J5O<*xd_$J&oOGGsV5Y~ye%V;a`>;H playerInfo = new ObjectMap<>(); /**Maps UUIDs to trace infos. This is wiped when a player logs off.*/ private ObjectMap traceInfo = new ObjectMap<>(); - /** Maps packed coordinates to logs for that coordinate*/ - private IntMap> editLogs = new IntMap<>(); private Array bannedIPs = new Array<>(); public Administration(){ @@ -46,16 +43,6 @@ public class Administration{ Settings.save(); } - public void setAntiGriefParams(int maxBreak, int cooldown){ - Settings.putInt("antigrief-max", maxBreak); - Settings.putInt("antigrief-cooldown", cooldown); - Settings.save(); - } - - public IntMap> getEditLogs(){ - return editLogs; - } - /** * Call when a player joins to update their information here. */ diff --git a/core/src/io/anuke/mindustry/net/EditLog.java b/core/src/io/anuke/mindustry/net/EditLog.java deleted file mode 100644 index ab922ae8e0..0000000000 --- a/core/src/io/anuke/mindustry/net/EditLog.java +++ /dev/null @@ -1,21 +0,0 @@ -package io.anuke.mindustry.net; - -import io.anuke.mindustry.world.Block; - -public class EditLog{ - public String playername; - public Block block; - public int rotation; - public EditAction action; - - EditLog(String playername, Block block, int rotation, EditAction action){ - this.playername = playername; - this.block = block; - this.rotation = rotation; - this.action = action; - } - - public enum EditAction{ - PLACE, BREAK - } -} diff --git a/server/src/io/anuke/mindustry/server/ServerLauncher.java b/server/src/io/anuke/mindustry/server/ServerLauncher.java index 3ed3280250..17ce9d6a8d 100644 --- a/server/src/io/anuke/mindustry/server/ServerLauncher.java +++ b/server/src/io/anuke/mindustry/server/ServerLauncher.java @@ -1,7 +1,6 @@ package io.anuke.mindustry.server; import com.badlogic.gdx.ApplicationListener; -import com.badlogic.gdx.ApplicationLogger; import com.badlogic.gdx.Files.FileType; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.Preferences; @@ -13,6 +12,7 @@ import io.anuke.kryonet.KryoClient; import io.anuke.kryonet.KryoServer; import io.anuke.mindustry.net.Net; import io.anuke.ucore.io.BinaryPreferences; +import io.anuke.ucore.util.EmptyLogger; import io.anuke.ucore.util.OS; import java.io.File; @@ -24,31 +24,7 @@ public class ServerLauncher extends HeadlessApplication{ super(listener, config); //don't do anything at all for GDX logging: don't want controller info and such - Gdx.app.setApplicationLogger(new ApplicationLogger(){ - @Override - public void log(String tag, String message){ - } - - @Override - public void log(String tag, String message, Throwable exception){ - } - - @Override - public void error(String tag, String message){ - } - - @Override - public void error(String tag, String message, Throwable exception){ - } - - @Override - public void debug(String tag, String message){ - } - - @Override - public void debug(String tag, String message, Throwable exception){ - } - }); + Gdx.app.setApplicationLogger(new EmptyLogger()); } public static void main(String[] args){ diff --git a/tests/src/test/java/ApplicationTests.java b/tests/src/test/java/ApplicationTests.java new file mode 100644 index 0000000000..5cee8a0c0a --- /dev/null +++ b/tests/src/test/java/ApplicationTests.java @@ -0,0 +1,204 @@ +import com.badlogic.gdx.Gdx; +import com.badlogic.gdx.backends.headless.HeadlessApplication; +import com.badlogic.gdx.backends.headless.HeadlessApplicationConfiguration; +import io.anuke.mindustry.Vars; +import io.anuke.mindustry.content.Items; +import io.anuke.mindustry.content.blocks.Blocks; +import io.anuke.mindustry.content.blocks.StorageBlocks; +import io.anuke.mindustry.core.GameState.State; +import io.anuke.mindustry.core.Logic; +import io.anuke.mindustry.core.NetServer; +import io.anuke.mindustry.core.World; +import io.anuke.mindustry.game.Content; +import io.anuke.mindustry.game.Team; +import io.anuke.mindustry.io.BundleLoader; +import io.anuke.mindustry.io.SaveIO; +import io.anuke.mindustry.maps.Map; +import io.anuke.mindustry.world.Tile; +import io.anuke.ucore.core.Timers; +import io.anuke.ucore.modules.ModuleCore; +import io.anuke.ucore.util.EmptyLogger; +import io.anuke.ucore.util.Log; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.io.File; + +import static io.anuke.mindustry.Vars.*; +import static org.junit.jupiter.api.Assertions.*; + +public class ApplicationTests{ + + @BeforeAll + static void launchApplication(){ + try{ + boolean[] begins = {false}; + Throwable[] exceptionThrown = {null}; + Log.setUseColors(false); + + ModuleCore core = new ModuleCore(){ + @Override + public void init(){ + Vars.init(); + + headless = true; + + BundleLoader.load(); + content.load(); + content.initialize(Content::init); + + module(logic = new Logic()); + module(world = new World()); + module(netServer = new NetServer()); + } + + @Override + public void postInit(){ + super.postInit(); + begins[0] = true; + } + }; + + HeadlessApplicationConfiguration config = new HeadlessApplicationConfiguration(); + config.preferencesDirectory = "test_files/"; + + new File("tests_files/").delete(); + + new HeadlessApplication(core, config){{ + Gdx.app.setApplicationLogger(new EmptyLogger()); + }}; + + for(Thread thread : Thread.getAllStackTraces().keySet()){ + if(thread.getName().equals("HeadlessApplication")){ + thread.setUncaughtExceptionHandler((t, throwable) -> exceptionThrown[0] = throwable); + break; + } + } + + while(!begins[0]){ + if(exceptionThrown[0] != null){ + fail(exceptionThrown[0]); + } + Thread.sleep(10); + } + }catch(Throwable r){ + fail(r); + } + } + + @BeforeEach + void resetWorld(){ + Timers.setDeltaProvider(() -> 1f); + logic.reset(); + state.set(State.menu); + } + + @Test + void initialization(){ + assertTrue(logic != null); + assertTrue(world != null); + assertTrue(content.getContentMap().length > 0); + } + + @Test + void loadSector(){ + world.sectors().createSector(0, 0); + world.sectors().playSector(world.sectors().get(0, 0)); + } + + @Test + void playMap(){ + assertTrue(world.maps().all().size > 0); + + world.loadMap(world.maps().all().first()); + } + + @Test + void spawnWaves(){ + world.loadMap(world.maps().all().first()); + logic.runWave(); + unitGroups[waveTeam.ordinal()].updateEvents(); + assertFalse(unitGroups[waveTeam.ordinal()].isEmpty()); + } + + @Test + void createMap(){ + assertTrue(world.maps().all().size > 0); + + Tile[][] tiles = world.createTiles(8, 8); + + world.beginMapLoad(); + for(int x = 0; x < tiles.length; x++){ + for(int y = 0; y < tiles[0].length; y++){ + tiles[x][y] = new Tile(x, y, (byte)0, (byte)0); + } + } + world.endMapLoad(); + } + + @Test + void multiblock(){ + createMap(); + int bx = 4; + int by = 4; + world.setBlock(world.tile(bx, by), StorageBlocks.core, Team.blue); + assertTrue(world.tile(bx, by).getTeam() == Team.blue); + for(int x = bx-1; x <= bx + 1; x++){ + for(int y = by-1; y <= by + 1; y++){ + if(x == bx && by == y){ + assertTrue(world.tile(x, y).block() == StorageBlocks.core); + }else{ + assertTrue(world.tile(x, y).block() == Blocks.blockpart && world.tile(x, y).getLinked() == world.tile(bx, by)); + } + } + } + } + + @Test + void blockInventories(){ + multiblock(); + Tile tile = world.tile(4, 4); + tile.entity.items.add(Items.coal, 5); + tile.entity.items.add(Items.titanium, 50); + assertTrue(tile.entity.items.total() == 55); + tile.entity.items.remove(Items.phasematter, 10); + tile.entity.items.remove(Items.titanium, 10); + assertTrue(tile.entity.items.total() == 45); + } + + @Test + void timers(){ + boolean[] ran = {false}; + Timers.run(1.9999f, () -> ran[0] = true); + + Timers.update(); + assertFalse(ran[0]); + Timers.update(); + assertTrue(ran[0]); + } + + @Test + void save(){ + assertTrue(world.maps().all().size > 0); + + world.loadMap(world.maps().all().first()); + SaveIO.saveToSlot(0); + } + + @Test + void load(){ + assertTrue(world.maps().all().size > 0); + + world.loadMap(world.maps().all().first()); + Map map = world.getMap(); + + SaveIO.saveToSlot(0); + resetWorld(); + SaveIO.loadFromSlot(0); + + assertTrue(world.getMap() == map); + assertTrue(world.width() == map.meta.width); + assertTrue(world.height() == map.meta.height); + } +} \ No newline at end of file diff --git a/tests/src/test/java/Tests.java b/tests/src/test/java/Tests.java deleted file mode 100644 index 261bc16c5f..0000000000 --- a/tests/src/test/java/Tests.java +++ /dev/null @@ -1,9 +0,0 @@ -import org.junit.jupiter.api.BeforeEach; - -public class Tests{ - - @BeforeEach - void launchApplication(){ - - } -} \ No newline at end of file