From 8f3af98585eb9fd3143f7206ff8ef19eccdbbbdd Mon Sep 17 00:00:00 2001 From: Edwin Jakobs Date: Sun, 24 May 2020 18:54:14 +0200 Subject: [PATCH] Add skinning support to orx-dnk3a --- build.gradle | 2 +- demo-data/gltf-models/box/Box.glb | Bin 0 -> 1664 bytes demo-data/gltf-models/box/Box.gltf | 142 --------------------- demo-data/gltf-models/box/Box0.bin | Bin 648 -> 0 bytes demo-data/gltf-models/fox/Fox.glb | Bin 0 -> 162872 bytes orx-dnk3/README.md | 4 +- orx-dnk3/build.gradle | 2 + orx-dnk3/src/demo/kotlin/DemoScene02.kt | 6 +- orx-dnk3/src/demo/kotlin/DemoSkinning01.kt | 52 ++++++++ orx-dnk3/src/main/kotlin/Entity.kt | 29 ++++- orx-dnk3/src/main/kotlin/Facet.kt | 7 +- orx-dnk3/src/main/kotlin/Material.kt | 8 +- orx-dnk3/src/main/kotlin/PBRMaterial.kt | 119 +++++++++++------ orx-dnk3/src/main/kotlin/SceneRenderer.kt | 79 ++++++++++-- orx-dnk3/src/main/kotlin/gltf/Glb.kt | 1 + orx-dnk3/src/main/kotlin/gltf/Gltf.kt | 28 +++- orx-dnk3/src/main/kotlin/gltf/GltfScene.kt | 107 +++++++++++----- 17 files changed, 347 insertions(+), 239 deletions(-) create mode 100644 demo-data/gltf-models/box/Box.glb delete mode 100644 demo-data/gltf-models/box/Box.gltf delete mode 100644 demo-data/gltf-models/box/Box0.bin create mode 100644 demo-data/gltf-models/fox/Fox.glb create mode 100644 orx-dnk3/src/demo/kotlin/DemoSkinning01.kt diff --git a/build.gradle b/build.gradle index f98fc092..52d551da 100644 --- a/build.gradle +++ b/build.gradle @@ -14,7 +14,7 @@ buildscript { apply plugin: 'org.jetbrains.dokka' project.ext { - openrndrVersion = "0.3.43-rc.1" + openrndrVersion = "0.3.43-rc.2" kotlinVersion = "1.3.72" spekVersion = "2.0.10" libfreenectVersion = "0.5.7-1.5.3" diff --git a/demo-data/gltf-models/box/Box.glb b/demo-data/gltf-models/box/Box.glb new file mode 100644 index 0000000000000000000000000000000000000000..95ec886b6b92b134291fd41d34ac9d5349306e0a GIT binary patch literal 1664 zcmYe#32|d$U|?uqV_>+$%)sCk?C)2tlvrGxTB2lCt(2acms*rql3%1`rR41IOT_l2x=}td3G{Vo6bE1&E_(pksgq>lz{nBD0Yd8|oRv*6LI%<)#*A zC|MbRYy>gE4yaZtD9X&uEXgc`auZ8RiZYW*OF-OeB|rZlUq>G$D?=Tn0RLdm5Kn(U zB`c#^9i_~?l+0w18Ur1r-29YOB`XuKb5n~l6LX-Jxo(Z?}J3FKvDOAK|C2wGwWx5NnSACM)W zV1;71ZQyW+69}urT%C;xS!`rs0kQ?%f7q-x&@4+>ZJ=ji00xGJmPQ7aMwajt z2TDLXO1V&DU>Xec3~F_hpphJunxX`XV?=;MtcUP1V%XH&3=$hYsd?!o8A?{>MmkC* ziACw4{AFxnX=aRwJq*nTs9ND>1(y_Mf>NR(nps8&hd~`xS&|B~*v!PDHnz5diGjh% z(~kiG8tjQ@H|$4JOMp#^xiC{n(L;(`VCI8pqV<9N2g0E60bv*$MuWuAF-#6bgD^}U z#74(3IT#I+hp|C4j1Qt=7$lC4L2@857!6~C_#h19gJ=*2i6LWbVjy{#IE;pgLHUdf zObpBnObm<+EDWp+Yz*uSYz(Xn91NTcTnyX{TnwBHJPf=Hd<^^ydV~`w33`WD)AU+7g_#hgDL1M@ln;1wQ zCJv)vVo*LK0}}%?0}}%y0}BHy0~-T70~-S?0|x^q0~Z4~0~Z4)0}lf)10MrF10Mq~ dg8+jdgAju-gAjutg9w8tgBXK2gBXJ-0{}-oJwE^d diff --git a/demo-data/gltf-models/fox/Fox.glb b/demo-data/gltf-models/fox/Fox.glb new file mode 100644 index 0000000000000000000000000000000000000000..a541b6f44849159c56020d6fc61bec28ea34393b GIT binary patch literal 162872 zcmYe#32|d$U|_JQVPY__XJGIO_V=q+N-Qo;Em5+nR!YtoV9OHptr$LH%`&b z1zAL<@@)^Hc+qM02ym zG*fdk<20j0V>1ggv!rB*rH;kDOo8Q=@}^1>L?{9C#Mz{=NA<#Sw&YXC6%V7r51%{rj{#N z8R#e_=jRsW=cVSAgj5!!Dp{Et8kvCvOY=&UtPIVKEOeAgz!FMfuFl3vI!Z~EC8_>t zY2es0&{4|G%u}+8)-^QJGqp4_H?%M`GBLKWG&8Z#(KXOBG%_?dF)=qYvoJO^wzM!X z)X}xD&@-?!H83zVGBPkXFg7%b)lte#tWdIw#$trIg`TB>xuJ!HiJ_^fk-4#nj+vRB znURTwnUR^ffrX`oiAij&4yu<7L9Qp>OGfBkBFa2tkR@1y$OO$iLt_gg6Ld3;FoKbk zSTIpSH_wzNpunVFfHo0u6I zTbde~VMd!Nxt4~xI%9eP%``(}P&&pJ#z?*(#y}%8Q*bW9oz6%!(Ad(#1eB(zW}vCD zp%GOLG&3_HP+E}aWphh23#z)%(#Vp!kz#0I2Ffc`OgDyxmZsE=7EscrZoC+pm>Ezv zVhl|!jj0?n=0;}J%`b))rj}HW8B0qe>c)(bp^*u7W5&qH)SS98V`OY;Kw-?7QBV~a zW7LgkRe_PIkuinwj8;Dy6Ee>b(T2iVLmKFr8(0_{8yg!Mo0ypz8d?ynAwg9Tf#ii` zF>#fe1)=0cs)^=?gfc$KCYlf`l1VnvoKQ_ks)-f`22_q23nL2x8J}b~63qA{n`l9( zNG8=pOG84HCCMh55NgDbY$CXegs+J}qKTkx9DyR4WD|`E70D!gE|^ zLqkICOH$ovXhNvfPqK;TCIl)=LMEbBmX?H?z^LXCtS*g>3`nTnu+}nY)ujocv}j~X zxI<~EXJ`tpE)5J#O-u|eEKM=S0nqAwV4GnQ13 z8B2;|2Ccd@G$PdYM=i_<*O!Dl{ir6IDAmU5C_yF^GV}8wL-ffRpm~NI2&Wi4{9gnf ztS?C{N{39711@WGGoF73G&CmVie6Ye9pLl;5!f$|83F2XLvk|aQl5dsMoOPVkwm?#Xfr3%8C152_1 zjV=&yA(nJuL@+Ud+udjh!-!yN0{I+0`Yq7Ih{=BA)oS!5GTK@)-? z0hlMiQIAW%g@HMA^(@R2CI;ZKaAXtkdcx4q!WgvF3#0*NhM_5_X9W_0IRbBF7#doF zS2=++z>F|5GdD8(8SEl4BW2C%uP&Bg(%3)%uR(XyjB8>>KEjt zgH{kDtI!XmeMZT#ei8(o$$wB$0=^1&c#l@f% z^+}1vsm}R1`9&eA6(yxbsUWe;yp+@mB`bqk9i?2T9=F8gl6=T8a}i8CTujf@q899q z)Zz@N(-Dp^1X*5`nVVUXSq7C%EGa3XlXsN%XJJut}?YWFfjz}lCUr`wlFp{*D=tuFfcc;v@`;(Fg7+Y zHV2u8>MBDcJqxfW3@y!!EG!Moj6k7^9*E{TmO9}51kk8ViibGGDBb|HaRJRK26_gD z<|g0;xuDRnFf_0*(lOApw6wGUdEdaq%+%D#%n&1lj12Y6Oij&AO$;n7jbXuW0N#6H zWNK<=Xli6^Vr*`zV}R~F3*HvnxGz;Kqafw8f=pXiGhKUg{g_5siBF5xv_~Q$Vx*qV@m^5BLg!_6LV8jQ;dKxG}bdVH?uS|FgGHT_n3!1_8JU_|8iBW$n1lA0SQ=Sa7#bQHn1M2zp1FacrKP#Ck%@(ck*TEx z7FS#7nVFkg8XB9KnVOq}jMULJ(KE6%H#RXawlp>XB|< zC}p7f%Pqes73?i@G;e|8LeIe1+|bC>!qU>*+}OkdwC)F-*o+MgOfAg}O+XtYutck| zo`H#}p%F+4C~F{s7}aWz#JrSv1JLFlq~xRvO5#Qa#^xrVz%enmG&e8=hns1o;&11E18i5=5G?L<>A{ny@rC zGBdO^GBU6<0p(hdH3kL-78XXJ0?*LQ%*4dV!rT-j3|bCgVQyk+WN8ViaE*09WwMch zrGbHgnW3eDv89nYW=e*p33C$*0~0f_LC_>&Vq{=$Zf0y|Zlt3NP7{_E<_2b`*Q=4OVbCgzr) zrmKOaC1yB6(}SUfxuu1Lk%b|o8Zt4pv;?Joa|07Y14C0YEa?GMBSS-Qk%A~wkZN>8kUqHY zL2211H60u&7!?S}9R>!5=7#2`MnoYMm)-lyHG&L~*wONb|EG^9pEFoFZ z0+gXag*Ir3A~^XYIo}AS)`2-66o2Sd4x~|HY-V9#Vr*_XlP~%N>!FdmKFvU zCZ-lP&2i>> zmL^6PhK81Arj{n4rWR)E0)-3MF`$4!t2`hjl&Oiik%fhkrHQ41rGb$Ns5G@OHUs(E z)ZEb0z|0hz&8B+h=9ZSm7G{>_7KSF4CRh`g5y;8#U;(!aU?~i}1^_u+&(h4&($oUv z6$4WfQ)6&hZ)9R@WNu(!W^Q0=X=s7XEzs0tZfRs}Y60G32T4t!;sES46GLcSZ)R*} zWNBz>U~FlKk(fYv7t^Um@did%igjHBJxFS@0JX*pOpPookWv#Uc8x);70kjDlA0`x zjZHv_9NdJ&EGdmZEgDp}fMXEU+(s+vq50C(*u>Pt)YQV<%)-Ff(99SdnkJ^^mIju_ zp#7L;7LX>Ug@uKsrG&O-y&o%qdANQnIo%H?jn8Lxl@iT7dh}#mT98sgRx^hz03O!g`ek;65g( ziwF_V%mZzuPIb!6OYu!CDauR+^=3_Ul(InGLy!_99b+969a9}M9djKEQ18P)$Iwv6 z&`8J7SjW%=+@~|sF*FDD>fe?? zdgvgtk!Ft#bd-woON)|04zG=^RZviPW5dMYQE==OMy-g-pz67XAg4v zS(57XO?|b4-lsGtiG!I=6Bar+l-T4ru^lgUvMil7$4Df>X{CLu)7w?~4!o;_oa+6` zQPf}Cebj!bc8t>u>sA!=Pgp28dKP3ky?)|@qCR~Ci=%T-pp)7I9j6!P*%y{y(1g*1P76ln~tljmpd-^nc*<&cem5M zLLaBPGzmw8!WJj?_0CSmsy!X6FU)mftMGDa+D@*k#SWQ-B|0RwXgYo86*+_) z7iE3799(R;oeq1q99;5ntwZB)4kwQY`Gbu8K{BsXn4NS&-Gxw9P=6mQx4FuZU~`djZfbI9n~8HfFA`y9`%op=aYJ+hiPu6nXM+a#O>B{~ji zEt=tQ?c09Ga;-UsRJ_$3j1NzC^nJ7rMI6~oWOMF+JmXN5%;{vAEq{|f+?K#s4hxY@IxgbF!HvOaLsJ;WOJO_ z9ys(Yv2d!F6>viKuaY~LLU9|W1-^`gAIp}(=BpZMNX5*`NAgNQdad%ykk|uYMf~sSue7BWP5Shg{&S~ z&D`0{2VnIDa=0Ov56E$ioCfOFKc6jGtLK!XCFq3AMvgmVy=dwD0IaSt>%4XVRtJ4k zUwr^p?;xl12@4$#!0Mp%)%gct_0Fk1NB6_(8f3k=%sgSCa1d4prEg$42&;FH#b2D0 zKM1RX6wWR@0IPS{m?s>7)iou@N)N#5pyfU@4#4W2W7VDqVRcPin#4g^9fX|Uk=_5` z-5hv0Age*nv&ia^>mB6qME1+~(1!Zcolksrv0azV`%r5J@ zbpTdRA?rm>C&+b;_@RRRpgQQhM(aUjHgbAH){87I&p6=#tgb2ig5jZ4VB> z>K!F_u7j|;200v%)g$L+WWOV)Vd$YG9Lk07&=(*Uww32424)=NIIBgsd0YFUWZcS6zmz9=RMwW+U5$Y$kGl0l7Vi z+=fJE>pqotg!v0uFR~ku-HF^TMP?)0h1^d;W+R)4tQWaVL#vnJeM4k5$Yl<)dSo@o zh!Qf@gOq0@sy%tnlQi9ln45b$a-()?v=?DY;rnKn0v5KcfCy5 z(MG3-3rr6>H1Br^Y$Y6R*#KgUEWP*orzTA4zgzekgWmj*hnD z32|2^EgkVgmRt`Vx^kSHrk++lgsgXIvxVc2scuehtdAZZp0^zT?;VVU7%9$Z*}~ozE-;Se5=!6uC0y-ES^hU=InQJpT^*HD$v+* zy;r!?&+zpq>Z8qmI`}iUI(zBgH!ciB`0L@wJ)bSY_gr;be&rjWh@I> zJ@VKTvib{k+_MikOm>>HLB;8e^v~J%%le!y?e#%1AK9JA>XG}`$mS#W-;v#bY%lWo z7_wgE@idodG7kH`RygTyPD2?F^q&+r=dDed)4cR7l(9i%dvWPS&PRKG$vd)H`#O33 z;YA5IWcMJuAKA^wenECKvKr*{hMZ=Q^AvL0LoUNbxJ4b=UNSm8{5IhrvU=ovSK)HO zVa2hPj@mnt4g8!iowJI+0q zIg#859=}D-BglE`&N2?!XD+4SF-Bx@P#L2BF~NzWUKu6dA^Y)jucc#5+!sgQuU8Ku z`xm(``{nb<;bbVIQ~0~~gUI;~IX^x=DCqdY>AqtuKPSpKC$jq8`u81zr#^5@kQX|n z*}&u|mp9At$O4H&yLovW#p504)>4LInKA1Je1`) z-$CPBuj87(?1!{ZO>x+{exl>5CcZ<+ZbPnjkkx1Co^&`kXO5%4k<=kUo(B%pb<5|2$l-~s9$5{t`;qNM_AhdIW&T0Uku~JGW4eBWyW>u*YV_;3`gX4Ca6!e$xO>BY2Q`HA0pxh!=Aozv{qe*!j3F` za6snHJI7}$51{BpX=5Obmm=GX%tm%UvU{dgh{*nA_H#0L?|5id%0`ERi~uK_PpXHO zJ~`!Ju*BTy++H`7Ixhb!r(?F@Nynr!IfpKBe|Gp_sOWTRq3xkPWzP@5>JGV!+Yi9Z zvEx2}0A>y{ThHkG0c?6ziherm%;j>@@@qVVY!~tvGIGAYqQNRV!)T!+Giwscm^QLr zWcA2n+UXtJ9BLMbI{hwfIfQI4@|ZSqe+^kZvKr*Hhn!E5(?4?ki(GCXmnX>Kk6dmb zmy^h42(lVndXeoyE+3HVT;%c%x&B4A7g;Ye(ikstJ&SB6a-HZRrR}(DPN7pWKRZf2 zj;t3sts=J>kkc)we1?q^BDW8b>m%fP2ibh&dKtOQN3IL}Cn4%ht+OcaKLG2aA*(^w z+jvUxAgs^D8Ln^;)-OXI-#}&~k5M4&J+MRmAgs^j(7gWutY3!QUqfc2)eCUFG6E(C z4?YWVdL&Td7@Mqk@E@0$Q$b|`C?6e!wHc7x52pf+55oFK$a<&PiXMdZ^^oi6S{?0! zuznx1n~}wrHd`Eo_4|;;k;4snd=)uNk{v}4!uof};Ug!ico5dtL#`u`>m6jjM4SCQ z0PEi&>z(MNc903$*L(GH>H%2)4p}{NpAoqZLhjcfvq5DPENqeWB9D6@&mZA(19BON zT<;*e4OtvH96)gjtK*Qz-f`KBJhz1$4#?_VrpX+D^%Ifj#gOOkkmnST>n~(CAgf0< z6L~BMIjr{ll0OLRKO(ya+0D4Z5Lpefn~~Ena=u1RlgQ~-gj@6=te=QHwu!8_!sWsN zSU(ZDd_cAr*}ur~3yLpn^%`>j5v^W>=SSpxhg=VW$}U(x5jp=N=fTgtmIq<|L}dRW z`|+30qXV#hBJ%hxa-MyBQ1BqEpNMQe^88nw{`~{6ej>77t_G%qus-8iKCXkXe&SqS zo`b5;{v)y*^c?3Ofb|)X$1SyWPac5v2c-)h9Dwx!1$iDEP>1#nwXXIafb|E>MQ0v> z^+Ww$OgjMU8zRRw=bIk~V0}PjHz0=_vKnN)+NY)*fc0mQ?Lu|~a{0DozQ93PAJF`R z+Cfmi57akA9&cwW+j{`k2eduje*mNg)Hg({_u=BmWht_HWOI<+fLs@=6#YB^>qFTg z^}mq&T=`!)55oF!$aw*|PlsIRBG=={Y~*?$Sue61kmp{J?M2Ra$n`#Qn*>=s@?0>o z-t>-b2Vng;Q{*}nxs8qN2IO)Q*-YfR3AsK(u5*#qAlK1JQrZV${X68eikv=?(=({d zgw=7#^#XF;fn1j%*Oka_KrWM!>n!B*8M*#KR*!5ia=nIZ4zhY=zaZyvo4RrEy(JT>ptW<3%M>pt|O4sJaT!CJXeccN4(!Hd=S=mLrzP`Wf5}Og`6Ic;}N-> zL~germvzWyBAbI;7a-RW$o3+$k<${gUgWYAxtvGVi(GCam-EPeLDq|`9@$>xv03DP zG;;qMnTpd8DutcI3Vjq_6xFqk;4I*jqFEc zy~t~0kjIpe$B~fRqR8bHav6m@zJ%;%Tz)}TADgV`2pXdZt}FnJSHRiG@s4b!jDU$F zY2dvR-6ypcK@KbAxI?!W<}c)O1DTENFJ!&QenD2FvR>r*S(JHOr1@NAHz1E)BkM)(rz5wKklRAYY~=nvvR>qVItv{g=QY}cw`_ah#Yh*U^oDQ;H^9^vF61$7(fnT_-eW+RVR zAnQe*BS2o)ggn=b%toF&K-P;aj=Y`qQO|Wd9=1vm@(89;-n%#{sFVMqY<=|MVA!JhKMJ`L?Vm>x+=r z;k-7U=pekU+hN^0_Cv_#AnWb-7j<0t<)uULDegnem+v~%id?gu*2j4WSv=#esN<7K zz7Ba`m{HagA+JF~){AUD^4u=RjU^6~W?poNe9MZmRtni|$o3+ekG!@DS&iG?O%7of z3+!AN?j1z-?;OW|hoI1(drO!9KZvXbS$rRpsN%e&6OO<~Q5%=-Z_ZN4b6MB|hv%(VN9H*P+m| zbgxZWrz0}k+=|<==e^n9Ps=(Tb@sD4#(fsBKfhuZie6;DBkM&Lx5(mk?6h9uppe<_ zh-~Jncn-%2i}pHHCQL;MlTPl(4mKCk>~^j>i6V|1Cdht4HXqqcWH%$XZ;{)a$n8?( zJdV890y!Tcw{MZ#y~yotxbdIbZxr{>2 zcgX6I%|UhpvU=q50oe`6c^uhZWWC7w5jo!>=XYfF$l}Q6Ba0)K54g-n_6xGxkkuoH z1G3wY%LL@LQpouZxqLttM^2x}`4@RS1i9Qm&a=pQ8CQ9NJhp>eo*?HzWcMSx6WMLZ zZbr^W$axl7J#zj+whNc}$axmItU%81$ZTXa$aW!%BioDYPGt4SenB=LnT=c~BfAs1 ze|P`%mjkeRA9+p|xv%uvc;W$Ay^lN&k8Dn%zvw|&y^m}r^X0n-U~K@eyP^kS^**wC zWHXV~BhN=8o5^uw$pKiskL*t5d2nR&k===GCbAl2y>5Fq9e}j~<~a5rfYtlR;ef1W zK9lG{SiO&|9@#I*YLLSLnLSte-vL;?kL)&NHnJLvf_n#G?Ez#qvfGfu3VHroormEd ztlmeSA5odvdjM9~d!%hW0BZvv>wW9WauC)AC_Z-Y0Ic4R$$5AH)*i^$-FE=i1_*gS ze*o4V2uqm+XCtc-yWMzzzZ23PKz7@zc#eaxy4CPK-$A4{zyVkrAd6@20a(3{ zY$md}&VIIouzKIziu)j}J%CF+ayTHfk@Z?+@g9V=2aw&_$^G~MQoRokE97uH`gSSY z{m5=WHWS&+$mS!D;UJF@A&&*&%Gb#AcgW){$YVsvV=u^g5INr=n~$8=kj0V5k&x3Q za-Kpq6FJQzr)^|6AnQfWYslpZvR-6+kXF&VW+Imr$YvtD0ojkpdXd#5hY51NM$T)`vtTg6wAG{EM8wko6+lg)EM2FLM4x&hN-&4zf71UC3&X z*~o4~b_23rWHXWdh%AomHsmq~x!r}_PC#x~AhVI%Z^(L);~F^)AeUpvY-GP6>qV|F zkkbINn~~YbW}@kZ_eqi6iQMKyW+S&Vk^8gAZBFDq8gf`6vvKJ~ZUZB?>yXVvW+S(y zk@X_imB@3f$oT@9jT|P(dXeJ@Id3AHiOj~O7r9@L99GETiOfcx^F`K+>|bPYWcA2w zERI}WA?Gh-HgcLo){C5XkozFW`3TuB$bA{)ct?&S z$7Kdym zG8=iU16eO}n+LfqgzSD~HgY>3SugUO8gd&3d0q@zFR~hBy~uNX$n#~$VE-e0=o7WwB_s-u3FeL*B-Ls)aod{? zPH_Fb@jq-=Sh~XHor{$0mc6yMKh&vVm%GZz9wz_QE7R`O0YkgHHOY1-C!5%9o*rwL zepTHrzEZ$WYJY)!WVVLg@y2ZX9UCp}8WpSUliCYyANN|o-3N0AOdQ5PJ^#H;cfNyt z?nDv0Pci!TF#BQt{HZ5upZMF>UiPt=efm2~csR%{{bje%L*L#@^^Ki0pSHdI@(*@S z=ak{Jve6g23&|?>FmCGlPSUkhR zb@mAxyDxs4_AnY2PB3*vhJ5yKeq6UZWh!XT<@?HRf-sl;&y1IL=8pyJm45%QQ?rn@ zPn!S3&do*C-f`YvJBOuW_M2MX+EwqBw!d=e3tSz#z6wq@`=smN>@0TuvYRmPksXXL zQ~k|Oe*b&BrJob+&DQ_2>pz}i&(`?W?o@8F{r%s+?Y;!uw#{zJvCoa1XB+ar!u}@f zVq5n!8TJ>r#qE!`Jb>E|b1zIh}~FZ+28r>V9(Z=2p5N`Yx^Hy zKVg4`eP)P(J;%B%`>@@1_8+yf;WW$~nEpMs9(J#)x7t0omFnR|FP^)UOtvpu&92|90Q(fZVm_t*`%dtvghbO>`NEMEWmDckM8 zx(Ob?F#p2*$>+Dnj#GS+U2Kr4ty~Bq{lL-_EIeW6!O{=RTv#~5(g`fR!{R?xJi-24 zFROjp7k&GNt$FZxgvBc?{)7be?2B(C!qWpRzG3pPc>lUb+kQ7+D%_lkWL^8cYjWY~ z2Br_D4i>L4f1msJ!7eOij~$GLg)2-QtUQFZ3j`mx+VR)>+QDd8ISEq-t2bfwC9M4b zqtVsD!Uq;EC9@*!!)CGA!)RFf0aFL7k74$}?1#|_r7m`EY@YCX8R|OHtX&1GH(})}EZxJ(OPDw;f57Bn?HE`+3^NCopJC|`mVaS1tX@G^2TQ-O z`T$15^uf%7wL4(#URb*WM#Jh;m^v6ACJ$@B!f0513sV>U($IdXr>TARXMOvE^ZNEm z53TLPUu)Rs*xA{ynrC1SlZT1J!WkByfA74od!lD#52F{K*kt#@KpWl;%wT`7d_EqcmJoOJxu=1vJkt){ekvDvvlo#Nch;p_*nrec6QO> z@O}tPK5+@VUCA_Gdzid#f|6b8%2@ks*W0#f*^zMlF#BNgu=XQNKdk-v?wpsM_3~8v zm{XZ{rw-@A`!6tcO(h>~`8pC|u5S5lw^lUQ zuH(yZyHuHAJD5ByJ!#1Y*%wCX*u(q-3on>^=Z9^ylWz91-&DWO?$GZj`_2#3?W|Wu z+uP@}*%wL0!P5mS-N?Kav(K3tVGrXso|Ccvb3DjCU0vG#*2+dZn7iDZ*zFaj*}~m- zbJG{Q&MmQa8Lz(DJ=+v$2U71<9}lKM`fk4Bvv=F91n+n4%U)oYKC{$r^NbC4U%wmK zndtM|TNpmEH4x&n_X&7xd+;f*J*Uwj+hn&LcAv`M+wQw{(9XS#)y_C%uichataj2m zPwajdC))K0-?zILQD6s?*KXTvXKch_w?=ZK-6~B^yJq2yb`vt++Eyg)wu`*SYG<)$ zhuw|OtadPSVc`mMckXId``XEDb};|Jj%4RpZ5manasIlTUsFj z??(!KHL~+KXl$3e#>8%3{1;o5>HhW?<@oK5m-*Od-4nGhd+2We?=mZ#KK;ep{=+?1 zdzd;{J$K=fs-4U`XFHgApnNLyH3*(Rk4*h+>s%mX=l#mWp8txceajae`^D=W?3?=)`dz{@4ui-Go%(nj`-88-HQb1dxdR+ZXMxt(R7x3JvaqB-B5i$BZ0>R}$7PV>yL z&+|!#tDC7CXm4L^XAd(6)~|)7N2i%V_B@p;@P0E)9ZVk9Z}u?{v`=MpwuhMq>o>#t zT`+l=I4s_yd7jzLP0xYHKdk(Nm2oJUzq8Ls+_orE_$3Fmqt#BdlD5 zQhbuyP1gK7q<5m^)zgs%!F7yOg!Q@NyC6E?7AXD<`y83E5lL%7V)`P&o%P z7dD;*8()HzZ?N(SR$jr%5m@^cmcL>78diS5!rfG3mhI=~)^@P`01H=GzJY}ktX_cS zKUhA3sfX!@>4S;G$_H3JgUQ44H7viv?17Dcz~o`^22;0mPmz6-Oo~0v%MAOFo^bn| z4JGzvOXBR`w5HjM*u}%eVd_@xoMRW%u*0s++}qBo@*uq53TsEh+Ql$+VLMpuL{EOV z+aTv|7rC6tKJl1~-PGAUaGFcR(9UcUk3CEs%gNPt%v)dB6-KSFtC+RNPE6vI-R0I3 zaM~hupWP~#mv%69r?2+gUKjdgx6s|k*1Ge7-E@mdwhN9vvV)li<6mCLYVhzd6Rr-ng5`{=}?3 zh*T`Mu{n@$50j7kC}8hc%WQ8sgVny{I;TBs{0TO0aM)eM{=qjEdziT}d6+&}KLF;B zUezad$Nt{8gN-M_#+P93fY}cdXAIn6b6BGWUXQ`jBP<<$F|@b;Ueas#|GAI7>c$Ye zo9w>!8&>7n!PH$}8e|`OD+-=|Vg7)*4;Fs^s%O~we*R`Bw{o4`>$SZ0q7gIf?EiAx zTWx%9EAyJm9+tjf>52cNzb&IMi+z3P4;$O~-*zzhx4ZQ1V@jIr_!ckiX_@)eYdvv^iTowLHc3iQrj8|?0tew?DWN|>~*&k z+X-y8wzrFZZrl9F#=a~1sIABa8~fm@XSQlj!tL*i<=A!KO|!4pTv+~DJlWAc^6o3U){74I>#JDoVg2*233>L9 zUf#9K?9R8}wd9u_tp5+=bN()}pKZfvzc$C*{>leN``j>F`^ZDD>|o}8?#l;{vndq@ z+cW;o!D#o0ybQ8mHah`ce!<#JuyPMpUczWtc?wepGZ!{a2Qv?ro?zpExmH2;=YIs* z!{lM(fG~9#k-_#KIt$_Be=u`l<4Le_BA7Z@Ji_8H&otbgC%oJaRzAYgBP<>I3Y*#T zO1*-Yd$4o}OP4Ttm^h4vm4`5MVC5UET!ZBUSa}L7Ct>NK7oZVEWBX(4c1P9f?%ZIT14pRrq z&#?Rsa|cWvOde()te**MFT&c7Fd8F#BLMtQ`(hx3~AKjh9=VonVi%ZRTHJJMYp)+lH%waC*k_&o+}+wc5ed!Q2N+ z53v3RK8fJiFv=ww-9Pf*p*8^@m{UVD4MCHPhD9 z$H5NPZimq@cf-`d`uQ;T!Q2a@YihjglfEjX*XEMLI-4={Vt z-2szln!VYUr=->nM#I7rrcXL~zMWi`6TBS>YgfYPs~48pschA;hpB_{Vd)DN&oCNY z9jqS*6NjmT(Xey?QwJ-zVC{8S{Q#q3^#@EHY@7v_USa72M#I7%rViHcg@p$!oM7g` z@((OM!)Ta$VCrD*fR(#2aoD&3%s;SxD~u15hqdovG%S2z>R|T4?1$wu7!B+1z|_IU z#bD!Pu>LBHhV@rr>R{t#u<`{~-oR*>KA1Y#_#JFK57tkH(Xf6pOdYJf39Dyd^#qKD zwNGK{VC_vz9*t{;R z-2|gy^$<)Qtep$9AEpmRqpO3N1FPR)=E25+VeLg&`w>RN#_?e4VC@4~{RFF*VB>hO zdI;7Yfa!yctHA7m^-Ey=XIQ-s8!v{9i@@d|VC6DQ9HtIN!}2Li9gK#R>#+F;7!4a| zgQ{*mwr4{ReXgOdm`gj7C=nE8k$_7qI>>jE1$3Vd`Mx0Lws9n5_&KCFEXquHV3958h-cf;HV z8}EdvgSF#f>S6g9HeRp6&u)Lb@j86|05)FFz5R%t$n<7gn0lBx1|~N9_me7Y7wWLs zd%Zns1LK$FG1)IKF|dW{hs`VeC^%@xqM&DcgyW=Lk>q!{Jrh41wR<5v6F!dtvj=A0 z#SH@XHsANbomdb6W!)f4h{@*R~E~PIdv^jc~qegR|YSA0Oc2aQmR+o`#NVZEtXk+C8(5 zu)BJS1+K2+qm`YDKbLK)46|L%>vr3<#`kQ!Bin4l+#cI{{NaMDgSiu?zW@GjTbqOX zY~yEMw_TL92d;0zts}PTOApw>++Dk&$JV{5(ss^)5W6DNBDi@lcfj<+^vQKCvVD=$ zXuHZo(Ei!Fr?#+q4^|(t*POG{78QZdU%|$OVf81hK84lKuyh5}2U8DAPq6w6mfm6U z2U7=2N3eK@rE^&P!{lM<8kU}6=>cXx%v@M{gQZ`Xxv+EzGY@8tPrzxr*N+$4z|t=) z-NNKye3*Xp^b1R$u=EIX2h5)1-q-E8RfBC|?uDs?rCZoM20T4M(=Ut0Q6=lWl_XNgEgq%LlOZ597nkgV_hO2j&h~I^Uj{VmHh2j}0un!_qmd{UmeQ z+1`EiEnC>Q9jqNA`8e7B-10tKSbrU+-uQuw{qJXWwlIB*wz}D;Oub~Yx7fpe#c?xR zm^@5h9b>9}u9cH5YyO8rr5_8=3cqqvGyu%{I+@iDfZ#7S>W<8cRFqHvS0e+2i(0dcQ+sQ zx0fuFfZGFe2TZ&v)YD#Eu+`Q?DAAtdL(a!mwr+xj>*LK41Qtf>LZrlA>nPva0 z`k>vjXX*BH4DY~cn7H(fEPI~FyKsA=H@VrLslQ<75a4FNs^PVr>6H|F9;HooS2S|$ zKRIoJn^)iJV83hkKD&f7ZuX@oH`pm>yV_@5H~^Q2sfW3DpO}Mv?20pRbya;X_K5-K z>|pkR=CiNV9ftekDr5l(&SiHmH8R{;^ zmcC)>0cIY|9kBEUGY^)IVd)iS4$NHZzIc22l$$oNbPG$zFm*6}FnL%yhNVwfI)%p4dWX5P_aC;M+P>+EK9x!NBxTx|zS z_b@&z{lmmzG|V2DxiI@+=^W-R_v4B76FN4+(>W~N!|D@QdjnP;!)RFj15*bJM_9PR z@(YZHhgM|w$ox$|MXmoY3_9)DKu=*TE!^Zt!>R|4J z@nP~X8rFV*se_f%uyH(CI)~A)^bb=9eLjeX6FwF}l*}xRz1Rh5chB~ zuz>X=`~?wbVt|AX3j-?yI|CO3OdZ6P^iMa0(g!QlA29d9__*}J{0j>Y5MPjii2>$c z76vW`b_OQ6zhU74QU{4oNch0?!)S!O00YQ8gg8VO%zfzLiHJYa;uE0{Vm_&SCTOXE z>_1RB0dprT9MNf5IKkB63TIl2gW?F}b9M#}a5{$ZX>BiNxPd|qclm)x2dL^m=>;MJ z@&z^wlZBNl5WXlp-XMIKzd69EmWcrt9;BuReg@LgAIx9u(EP`Y<}O6Kg18fwZeZ?( z>7#Xgk!n7AdWX3empO>^Ai^NZfJg@j|3b=HSh<1-7f3k*(+>+zYDo zL+rtfchce&Q$NH;LgFxY!2FFKjxat<9jyGoO+);HE)T0Oxfmer2LugqCrmxe9#}d< z@FD8Z`IzRw?1#{>_=Bl~V98&(l>_^a$d<{t@pmrHVH!Qqx ziNnGXrVhp@m4@ku(WL69wtAR5U^KbrBjN`V?yz)%9xt$d3QQhG!`cV9>_?9m7#|XQ z$RxymboU_mu=D|;A+2eUeh44tUYI*!d>BngT#!Ks++HM}M%W7~Pl(rtZV$v9nEOCx zL3{;ap^M|P2Uh>UXh?2hVnDAKVd9AT24owkeTbiimCNY)5oRBZhM5mbAF%j?@nJM9 z-N5)Tbubzxj!whmVfqm?#Qg|9diw^(htcGzhs6ghU4dv&Od-lYh`9)oP`bt?4>JLh zK4AFOdMt&j882ZmwRCCICL6Ok3m8K z<_}oX zbQ+SrVf_J^dtv<&7$0U2EdRpzFdAJPJ^iE0!}#blET6*6MK^~KA7&m*9XcN-PA?kW zesn&u?tsNBdOC!~8~S(-OdTv=!1%cAgM~Lb4NE;R`!V^j^aGk0 z1~G8E3zLS}0}}_C3mWf$@rkEl=0JQ33s;zbKxTquVB)yUh24~g0Nuya|jP1 z4l7S#`e6AE#z$8Vi%<0UB~~1!4@SfE!DyH`qCAC_qc9p23QPf&xbh>qILushadPT;W5iI4oRYG`fBm zA0ZD38O;1nnmDYT2%}-`M`RjgB1|3@pRo8qr(yCi8rDunR|n&xtAnLiSop%yHB22$ zA36=w2UCYmqpOGUVd`M*7-DId`w-~?6iT4_0iA}V9GH3p4N-@%57G{Ywbv0ex;hvi zq8`?6htUZ0AnIV@2cu!`h0*BlL6`$EALb5B^$>r-SJj3jTl@kaW zGQI)pw<2gre-)t)!UvT*5EIe$LFCcZBh16D9?{-|)N8Q%0YPK02N3e;`q0(GN)k4~efA4phX>&HXV3#NLAILus_Jd6*c5#liQ z5E>NzAUk2|&}npk!1(CuV0@5S5DbZLT;?OhA?jf5KZH3DahN(7jjj&n9#}aAYsaF~ zFm*6-TdEVFneJ7V0;)&NE~8269deC1Rr8QCLiV>?D8=C zVESNu7)?kV(#inMV?fO3fzI#4#L@XMaTtwDo_KLcibI%(>JA=oY%ww5rXf0E_94{K zRvZ@JuzCi;hqxb891@S{;)rww(+5)rp%L{LL>?BeF#BNX2qq3Q55|YdldB$K4#a+# zc?cRNj!r||4@-Z<(g^!d^&`X~_CR76dHftA4oe3xd2~LkeGHRF(5UGUCJt*C!uaUs z!T2y5T^(k6M0F=jAA*L-lS)HuM%V|_Pn8aoLNRZXqV4 zt4Hu5?!eSXtT@bkboKbfA*C;<{Q_Yj%6SMMLL%B<5YrIhif}(f2F8c*5b9ujm^?ZS zlSj7?Q6EC;KlJ(zrXJnhFg{EkorcMy)9C78?t-NQbQ&g)Nkh^ZA@%6?!Tg6#qpO4Q zG1WoB2__G77t9@qbPjPJOdc1F9#1enOg$|8VD=$sRCmC{5%xpUDa;&P;;?dvSQ^%j zq!mr9J8-Lm)fbTR4qY9>-H`DD1Rv7gMCZf$r^M2;W=h(hJ#)s60Sa!}8{5yCDQU-) zE(sRnx}I#m&i$b+RGNW-p}`)(2C+sq|Lhqb`?F_!z+nXnjiDYs=;;BSkDeYhV)*Sh zxIZM@|Dfoc;-gCwlsseMlS}enGv{ZGS(SYKv|@ z>ESW5%OhjsVo-Smk012#BP5Tm9-WV#KSA-2oPQhhMC=(&mf3yVeHiQp^!Pn>1yo+1 zvAxrC1}u*r-{|QBJw2hzqq`5CkM3S{_o2HVT|YV>-M#4Yn0)%?PfYu1n;!_p4|@5F z?mqPNNQjS~p3u!3>3mRnMlO$sTX+ykZ|L%%@IWq~NDUA4@&nyGLg|~3edz8*HxFGN zy*+|1k8U4&dj!3`g07zWeEODup!h*f|LEm4dU&DNC+PBo${Td^sULo{Ex+mQUP9$N zrS3t`uY~G*^!P=OPxST*dU`?Uqo*Hq|Dd}MT^`-Ngv>+NkIqN;54t=ipT7AO(|+2f zcl7uslpfLLsqJ1;;|IMwM=$Tt`J}p+RQC`vpHO{+ZXY@yJ^!Jbht5Y=k8U11AKm@v z=Ap}@^U=c_osS-0==w3;gPQ-)%L{ZqA@k6~16@5KKDvH%|Dp2PcyTQmP)k{y_I1dVNAjJ$m_v&PO+&5FcGXAwD7V z(Bw?;p3q( z{Z97%hf0a&qlX{5d6@oluxDUsfSZpgk6PX^Frca@#7ECR=;ovQADvHX{eqqz(8B|r zPe?r>d35ur%}2K%olkB1hMIZk;epPlw|~&nH##4^yur*rsP*;CnUePBkmegP^`olC zlt<6M^yQ=bAH6(8mq+Jgh7WrAgWvz??IHB=L@%Gv?Q3`)XwMjA0WTlX)uZ##)r0(d z<_u))9yH;E&PUge&X;e^2Gs}Pv43p((fxzoJ|U!^kbBVO(fR1^MRyN6A2UCq#vdW| z==P)Y(cObyf1vZx-Gko$Afz5$KehSj?PWssBf5Lh`IzoQ4S&r1hboU*zTlTfHxHdp zsdc8^3m-lRX@Ge(>i=W^}|`D`WM}Q=<$J`ztPhR zIv-s!Gh2_SGWm;O!}N_Yw*( zba{05px6KC@`UCC(bc23pU}%!Q1~IY@6gjTdi{+qkM4hTdGz)OdiV}KK6?5^Pyguh z=zQv`M^E4A;YmoIkb3m;1(aTp%OgU3bp7aj^z?(C-w5$ZZ6Bc9M=2jYe9`%sPfW^-F!lPbo1%WM|U5({evkA85A$fH7lG@%PWImmPLYpvz;n z7g61VuAWf)6urJf*H6ejnBjw(UWcAMYIqWM|Ikv8o?g-WJLu&JsqIJf@{ZPg^zsZn zy^_i&D2~|CM{zOl2gv%pT^C%5pLi*9e2i?Eu`Z3!h=r|DgA8(al32Z$b}0bUu3c zp}Pm2kKX=3A73J*9=*MTZXPK7klRz}>6cLbjUFE8?E`f4(EUIB`RMgCIv+j#q06K5 zDN~Og-{^ew`WT&0DE*+P2lV`bE>9|-aQTNGUikUw=ArX3(=UGW2HHR9_ES6j(ak5s zM-M;r@_~?kbb0jnA;d@5kIpBgA6*_@KOsK4esuq%^9h+pNFLohbUwO!(9J_vj~;*M zd{Wh;>nCJCx;!EM=;{X>pHTP@Huny+d(h(>olnSpgu^8=X%me9+q? z=zR3{FFGH+J&dlO5FfpLgU&~{kC1uj^62g(#7EbU&L^ZFT^?OOAwIf(bpNCCNi`3> ze}dj0K(`-V9$i1W{pj(B-kwG0qw6QcNB2Lvedv5b=ApZXkpD3IyXgG`{Csr%g!t&; zkIqNek1mhSCsjRq`GMX)N9U8O9=*Lx$UJoO(fR1+q4UwzV~)3=jz^%YCuANdy&;bu zp@%;vAHRK=?jzJ6LQQ|@?m_31YCa+VqlXtdA3c82%|qv->&J92{_w*zkJRu%4{vn) zP|ZV+U(E1EHxEA_eLR*BA3eO#)uYQ3;-l*)l~2fgba_JNqpK&xCuANWc|zu+%cGk| zNS;#l==Bx4eGjWd?CrR&!`J7bt4FUd(c6#c>e0h}MesuSt+lOu*sp`@7qnnTJAN24;mnW5v?tfDC6LK%Qye(I_JJN;hc1t< zA6-2mKB4lFkUXX4qw6QtK0@lz$7|5-L+2AR4_!SWKDv46e02Tj^631bpdNXC1-(B5 z@(;2+x_{8;kI>5tbp7c45p;R<@(SHPbo0^q=qj>q-F|fa=;ouVNB2Lv`_RopS5JsfseVG{qsycF58XfL>e0g&T^^lJXuJ)S zUQzoisO?cg@}!n;q^c(r9)#S7E|1Pf4=-xVqnn4$N4KBWd{XVFwtDpP3B7zk_dmLN z^z?vUUZAT-&tK^F5z6oA`qAw}*N-lbZXddN=KDv5Be02S!@(GzwYk73{60(ol>e0<3#3$rFLh^*n zN0%pL9=bfbenNb7{e<}F`30Sio<9hgN63BX@`TJomq*u6h>xzH5Fg#Yg!qKaLzgEM zzUcO$>nD|uZXO{%warKOFCp{M-G{CpolnR-Lh^*t54t?Md4%NA)syOeTB`@SAGtk? z&PQ)A5#pokN9PmLk1mg{pAa8iKOsIL^9ackG9O)@ka_6sYxMpFx_Rj837L;>9=d*X z^U=*iSC5{)X~b^;oy7*aTnU1~W1uiGkW>TIUXU0FBZ;A?1<5sBomIAt5$PTxMuvv{ zATfy93?Mad{Rb}3o@?5^)E_Xx##akgnkfvQQ}G)nEf$g*X;A2haED5+TU9zY?|DX19N}FrWO45 zo=<}9uS4A50Ag=i!N0!{YJY5l*P*Uc?+?P<-*msj^o2kW-2Qz5>HFA{D&g)2vG)a} z+rjjIWm$7Dd}$lp{mM>i7PGWg?)vn<9u$5J8?M*y|FD#QuV&L;Gf?=wTFSq7(e--! zYP*%YK;gH0jhmBlM$^IhmiG>T!q57C_Kp{#aQzJH&eremuTikIgz9gtQLtTbw%)!H zs(;STQ;tt>PK4{v?x@=>8vVqE>lxU7hSfaW`%7o?af4^D>N_aN?PaJx~z|Knu7y>h!`tU&t3r}FL9yispo zTK^a9{)emGoZ>^84w|dqcL2FxZI;2VE2h78!Sw$-Q@_8lPtjHus^79#(f08fg#Lt` zryK>2O+07@)$iy3*IG$ef3L_Pu=^XHX>jj9wjj*@l(ouUkp1>|!|Z#cx$PCAJNJOX z?~;Mp!3nAb2frzN0NY>Awt36;Kh37F^w;ELv)>_KcmFL&{4;>qO+GgEu=F!)rMaVX zaFde>H2oZ!_iIbn?+Up7=p?26K`&hQ!_qH^9i60P4@1z^)LF%=~x)A;Pex!pLh1M9n(K??1buP2r4hyZ|}Oq?)Eiq3y}RF zc2Iedy?dU_PLTcm`nMc|)_im9+kFol{>yL6?KHPpZ4T4F{KWdb8hrKkccA(~>=h^0 z+j>Ctzs_cMvN-U{z8|W8=NbXi84h{y@H2Q?yZ<96v)xT-{DIg8Pix`fzkg4VlTz_6 z$JbvW`Nu6RZOet24!Hi-4*&gc9*M%^55#Wm@Q3U7i05+L7pCC!7OH=)q=@CUqJB$I z842>=l#ZhPCifTH-TdGP4u24PN=K3X$652i;eYsvpFDTe{Kq6I8!bI(W-Q^0E&N4Yg-rNU&eMD$71Jv=np}vwdi2tNrR#UG@wN6YN7nr`oSxHOroXVS#;U z=u-RDt5(@FFl?|74c%(Ldets_28ILnp`l0ZSFbu{&%kiOJ~Z^I{pwY>>=_sy*oTHb zwO_sJl|2K)2m8>_ulB1~{Q}*4=dgMelS61Is{;cAhr{YsTn?e3ybcTu0uHNJ2|0v@ ziaIbbNI0xsCFKwrD(k?&py052m6AhfsHy`4gNDQERay?Ap}GzX3Q!D2p`pGG3=9Ddt5*d%gocJXFfc?o ztX>u6K)tYJV4yTk?%j>G@94;|H!&`@zjwFR-o>TGe%8!R`}gnq>|I=@*uT7gW-srY z1^e7KUfAcz9cACU;_Ti@3iJ0JkH54p=UJrv8vV0-k6O&xS5SOq-`Tg3_PSN4_g?-o zeV@*wYx^e3MAeZ23)_h|d%#T)jPna1x^X@9nF>Vz2ks0+*Y+PZq| zi@f=AU!zW}y~6*wdsABV_j&WY-M49ftbL2+Ez3sszdvi>_?>l4{Z||gQw^v=}%^sDb zKlVum#M@WuE9_kqYhoR7>*qcl%Xs?(s~Gl9ROYwMPWZJi_E(&}+JpUjrYU#X-i-dW z??PXkeO6V)9@Y0}Y%iYtxo_*&So_KQZtdQCl-*8q)sKBj`my#A*IBI}@7Azm`TA|& zWcwKV`&W!?{%UyIE#LiR-!|1~dwH(KHaqWR*iB*kv@hgIr2Pr|w>FEeG}|3}@NVDl zx(NG+H>7RZ=1sB-34Xn=>R*^W$2$jGkz)(&T1%hrJDVJ8ue>tVR>yjsokHZ}eN9_} z?H|5qv7PsJmtC#k{e82(1=^doPP4tT;h0_5&RhE;%>wK_8s^wK_MEcQTykTd${~OI zo|k>LUosBbWv1QQH*a2`J^z6^+j!4ycC)?i?9(|MY`^npyzLCVRdxaQ?(S>-7i#}? zf}<^8%v?KDq5J!O+CVasHORIKWm|kv-=9_vg{iUxSQ`^(qrlU z=ghv?X<7CgV*89j4u0Ke`svKRNi(wSe+Kp$rLOvclm9EQ&nO*9ez@^ZX-4d>ni04s z`r6rjaS2)W_qb&D^p}b4-Q{?G-}OhC_8~l-d-j+&?){N-VIPBarhPKQi9OuwcJ96A zb#b3eYKDD|7VF-^>d$*mUb(o>KR(^QvQ&NV)cs=n)^T3i_f9L#{=bjc-dJtpeY&qM z?lV50VqbbMXYaI9zkMkk7xy^?C);z`x9=^L%Gh`Q>xF&ZhZ60ZZKm)2Kf8Y4agPi8 z{%a=K^PgF|cQ#YkzS7uu^F7qn$~|77n+$60ow4n_70 z1=wr_x-RX_%$a3(s;S6cXx$eZcZCCcLnhC%d$GUB-pTZ?jo_xWdpB;IWtaE8$UboU zQJd@bv-j3qn`IZRS!{pNWStG?sgAu{KFzXQA6jf5x^9|{-lCknvD~xm(rb$CcY4&> zTwmqBw@6{OUGv;x`)_*wHm}zy?fqgn+m3l>v3;C?f=yQ3?>$fKXWKnJS8Q)~=b^Pl zY{?N`d$Z4)xv?#8=fdpG$fyI#s~ zw!RZQ+s^S_vAt}_^xa*{a&2Dt&$i=vQEdNs&ez>%Zy&IU_n2*Gd8gQ(<%8y)&-tvj zF1EAnj-M*FU(Xx4=R=;B?Nq(lcH1`>+v^Fp>|x0Aw+)t=ZO1je*uHGe>^-gtCAM{J zv+WL+6x*vPZQfI~qQ_S3?JT=HKE?KGFZb=a_k5}?>-|}FN6d=tB`0s&qZ`w2EBtbn zU9VfQy>tJXJ#6*uw%uQ5*-efpw%^gUXwMv{dfTM`v+Sm37TY(p&e$W@mTx+ zVfWFWi*5FL&$erPSZqII&5GUs3R`SW`OUWTepYO+)6%dz^s=XoVc={#fmg-$ncEC@ zUp~lX^D$_)-NiS>_Ibw-?8=UxZp{-i+phOrv3=L^13R1Ir(4y8%(kOt;9RuAGMo9}aHtJUH&eY+(? zX4@@%S8V_H&I;@Q(_8i&_nU3!_N>@mC|1;_Yr?BN{Z6y(L@yWHOSy*GWY}x$?bV-c zXS21~{^i7O8yo%Ty@y3-+wJZtw%7T++Ga0T`(C53v+Slt7TZ6GIb-voe8JvZXJ^@+ zl`ghlv-ORQ+`XN9_s^eYmvXttp1X<7R@>(C-UnH;?BW`V?9&#D*|JW2v)4&~mfb$3 zB74n!YPN^oGVOczW~N=|u0s2T7tL%vdinQVSUl72uzR7s++8=@E;X5b%po)F3QrZ- zzq%i0`*VlJzUIF(>}EI>*!$f~vt@BH-50!IhMoO}eEXLNN^OOHIP6n&o?-VyHs2n- ze5^biwde8XBfF(j7uqGiF0waOi`wJ)`si*3*+q6I&lK5zPmJ2bBYkZ5&ufe9maQ$a z_fL%4BRc)qZoSEi?f&%^+4tl{?fL!n*zS3OOYF|%7TG7hjNG%#!o(`ZbkOq z+>v{(K0Ljf+he8Ovq^>aQBT76EEl-2o3VebUG#+ld*6caJx+d?ck7F9vNQRUZ$FhO zY)_=ojopXYx7$78&9~2H4Bhj5^PSz5`Frfz81n2bBtrLab==vV8MVi5152L$A=%J9 zUpC#|-T!WvU7Syz{k($EJ&k#{cB}X8w9}uMXFroAY|qVGH+Ii5-(lBuInTa@F>DW` z#*N);UT?E=5ze1GkRTUU#Smz`Q< zcVK;yec7kTJ#U1M@1D0{vEBaeB6}mQs6C6@kMFjvTw*7YUSuEhGjdOb{E6L5LYCSc zaV)Z5@-K4F{i!E*|2A4?w@tdpKD{P#kMNn3yJba|+x`4fX#c(`a*tNQsoniQm)qH# zEwmTsi`*lWdwTck+bituE-kdb`7UA)oBNsF>}OZnO{gxkS9=n%r|!X--C}!I*`)^- z+COiI*dz4s?C#QatL-w>3hl3lMC`fy^xW=-C2Q=eeihiKNJZ?qe(3z}p80F-;?5S> zH@pnrvvT8w-4XNF*?G+`u+LZ%zUSV;i@VJiuD8=JD6kha3*Ynq+@;;}D>v9(wlA>1 zXBECDwc_&b?|V1e?dK`5|7#k)CqMi0?(U@`%N4+jDB-<=yGN8|@}37TC}4 z3g4sAd}(*dw+(hv4GZk64u$WT&3|e4f(0Aw;v5U?SGI-kX;izkyU}}t9aCU|eem?~ zJtuEm+@1S52=xTmP@KTi9D*f8=`jo>R*%>~>$b&MtjUf&II8;d|_oFYFeNTW9xSRe}AKf8l#V z6fW$p1?r}4kQUNSafPe$&! z-RX8~?Dp{#+Q%?Q?vXuzdUtK$N;~_Bh4vnABKIg&o!GtiCo;)N9WnSjx4t47LMNYgXi#W!?O8y zJhsL5FFr=?30rY^x4p&!yEF2|_H!ho_dLCPc=xnB3+$MgitW+MN9G&S#@6kIMt>@M z?6`Ex>^-ka8!yh*H&S5kwlhyEv!50sW1PBKD!)2?)Snf<|E(#9>RI!4pkI_%D! zDYHM`CSz<-sAaUVq0P>esob8~PR7{7Ps8Z#+7>%c$8!7T3o^!QX2}^DZmzPMY+7Nz zZnLcMzbX-Zy|=WRzOULo=%t+T z@%&GQ-@EPYEUT;S_d3fPpOF7$xa_Zs-81uQ`>)sJjGg!yjHWt!*z;$mHmO8a>h$)*^K^Wh1iwkRoTyQlQU+kfRPq~TEK9O$TUKeWd0y7o!Ar>y`sq%7QL=l`kHUUsUq zao7PvBY~P8yL~!k_KWvR8>he1H#%~!%Pu^<%sw(l#yFHo&nU#E)9%f}GW#p`GR6~Y zwT<$owA(e^DYN&DlrcV;t!WhYtkq6iyxe~00U2XP2@Rv4hAnoF0?X~+OqMZTdQruQ zue`}_c~7~$?N%A%7b}&Fbhk9vEj(Uszu}0C@u_PHMk^lG+8to5u&?EnH7@XwGg@X+ zW!Gn0VV|iaYn=RC+GufenccjK3j1?1vc?CmNE-PZF0$LOxx&6ES=M-?u(;8aPkDBS z-&NS#T$eR=7Zf#G#FuTyqE%_nFE3}j>yx07x@5YYZEB@`UACNY(@TD%rvk}#l?y8E zlV8dj3*6u_n(#T!?$qr{``k1+<0>&Oqet_i?EXqr+3$&#Gk(X+ZDed2ZPzVOWzWPQ zXWUc8Z4`Yc#;*2frTw22Ib(JqUZaMpIJ=HVmG;)=a>iDgd`6u@33mHVSK5ELDr@|G z4WCiQvP3(Ut(Ercxa5q#xA7ZwnkL(&%&WAI6qhreqA6%};6RGqmG(+|@xQXh9}fu{ zrMjot#T8cC-@hwsthimssP{y=onUmOebx+FW8N*oMqAu6?M}H=+Ar{tHTGI4V&ruo z%Wk1wrTzUjS>yN#qDDccId(H7D(xRUk~Kd4N7U%kvRu1)OqKTUX2=?sWQ!ZE70I{T z{iecxd9E}D*E0KqY0}2>S1gPUS5CD1SX63%dx@0sqe^?DV5RAH2d0M z<@5=5@v}?qIVVUP=c<|-mH+FrGr3S|@3~9b*ge_U=y-pxogHhLJ$m`*xRJ#w_uHYJ zv(LHiU)HE(?{nn0sN1`KVzpX$@choXTOIamw`$n$P5W>8rS8VGZkTh8uO^L5xC_D941${i-FG?^b!r;MpgS0#~H2uZMwMg-9_j97Ee{| zUw!^-`AhWd&Yo(Q{okcj>}^>7Sw81HyE8z^b$@M;vi)I&f0oAFXLqU}bKU=;Tgl$) z@i$8ospC6k(%tq4A6K;RYxr-ORepMBn7#Y{oqH7Q4>mAZr8=G5`B2njf8<7a`#qA3 zR(Iu&@4Rr!V}IgKIeV5aHmiF7GdrhE_1ypbw5 zact)`H;?`Ai{#?$ji&#_o_v7Xu~9qhb6u3FXp#REnwnUzO(>Rxx+ zZ_cY`&v=c|s^Rw0opU0c_RB6%v(GrnXm#rU(Vc3y9QTKrsN08aW3<{Mb8P4P2*>>! zPO95?1u$CeI&yU9<*N?+{Sq|neR%#@zEC~5bA5or{(v7E_TM%zT3Nn0w)53t`~8eF zH0|FAGFoLNAKPin;jn+Tm!^G8%y-M(?fZ7hS2*lXI;~+}af8|F-n!E}U7kDa5A@Nn zFIdiMwP^LZo$aBH`{$fhw?E0qXm#h^@twSf9rsK6tJ`mU$Y3SxbYkZPeW(2wFR0mn zn#yXWCw5`ymDx`F4+g2(`{XlNU0-=(r#!p!{-;+|?boodSOsrBw{vo#^ZvweRr`6- z3|7ZNPVP**?Y#fTO%?m)t_)VC_fGDtb8*>!CPu~HLyW;{`q7g+FRXFd|MI@Fy=@qRA`~JFb3icKL3|6i) zPVMC1;J$yBfr9;cRu-!%eP?%G2=LgSmM(A4kjiMarRUhro6kJ~Pj^z7iy znkvuz4ew;_eeId8!o?5myvO3XU%ExkzHAM%m4C&dorn57_UB8=+pDVowfr@2*Ul^A z9{XRclebS!WVT}2c5vtFx$gU0+!gHC)G%AUj6b;ZsIvS1d-oLVo3=1peVKP~=h+o* z`xlle+W%R`VYONH&7oj?3e?J?A^TzY);nxvR=iw(oSP;p?!^3zK!*sf7UjhYwfPz zDzI;PmuoX&7NgCMiyQ4&*$eFJrsmk({vqNl;-CzDZ`b5X)@C5V6&cBQD>5pG~gK z_k&C}70O%eY-i-#SN7-Hbel2RXuRKK_v2!|eckMQoBjd@n^%W6+HK-2uzzclXY-Aj z(I$A#20JN-0()290-OEU|5-1qS#P(aq`-dJu{@j0Obj;1Qr6k6TwY+$wlCkNqwbHj z@T*mJrtXFIt9BIFOr7(?I+T04UH+Fsd!Y@5HkIf}8;{-Ztyl9cuzRUkY~R39VsljBgY~1k3+y)jFS7q6Rb(Sv@Y(v)x`lQE zcZ=+IzAUsc6#Zg-s%eqk)}2N6>6;2|azA{rmW^C&w|i=l{p>BpHXidoS${NKV#irn zWUsDSXk+v8n{_1bQoDQJMfP)83vHIq_-=jh^-{Zsszvr6{uSB$bN^}`d3Ko{=l?=` z@#+E_jmn?a+cqt?tG-@n-|kvuGr{J&^`$8*>?Af6+IK1x*sNguZJpe<((Ywzq5ZlS z`8E-pf2=o`uChB3U1-mrR%kP6(l6`0jMa8K4GQgR3-fLMpZjY)CvJ`1E0#k0XX^`W zCawBoy*_fS-KFaV_Ny-B*?3+2Z=Dgb&hGij0{e%3c{cyz7;M_3*V|pHDzImY&9^yW z$6#|Kd4pY^SAqSm19>(lJ~G(6tk`ImEnZ+hK_bt_HJ#B$Az`B(n@oZICfz)nJ}X8W zOOB0pwmJp&0wQ@fOqz@~)*Cn2IolN2e{CzUd3NoewN3N}yYJow_DsonHm^4`*s!r} zuv-&dV4qx*XT#CUU^98+dOO+d0{gy6c{T@A7;FUM*4sr_71&Gc$g`Q_!C+&+z22^< zv%tRbXr4`gB7;rt&UJQvGYaf^cnWQVZvL@u&RA#nbXkFY%A$Om%M1QlKNeqS*R!?2 zeou>{AYbaYpq?-g93YA z$9$WWIsdGM?yj+OeOF-rsv+M-@BLqE`3Y<6c>fgGGi@!j;hy%(`nK~LyE&YN_A8GT z+H`pSvOf2HwVl3rq5T7i0vqe4zpUN4R@$wcU1-lCS!i?3^1HR-qNR4#Mn(1kUkhzC zS-x0zL@u(MeW1u*>P3mo-x+VM59`gho9k9=|2VqXX5WLi);s>rwtIN0*#7dKVjI2X zZ>(*2X4@rvEVh3*q1fhN##`&E)3fbfTq?HT5mapR&gz}@?9w@QtG5^1w`-N!oVxnj zdZO%HyGe73?IZsd*?hErZ!LdxuHEFuV*BiGMK%huAFTUo=h@9oF1DY1w8-Y}p%2#T zdh_khxE0&;&MmUJT>jBI?7@7yDVoLh0!2kOt2IAaKbo?@?h1FYJ$m_g^{TY-sYixJ z?S(ydc6w#@so$iHpMBCdn)s{BE+@InK3qb^nDw%*(Vn_ayR|dQ?3bCy7|WXK7@hyy zZpU)2%>HwXj4`)|meIcQHoF|=a{J>wGR8Zvs~as?(qh-)RBqp-C~N$Cxt!6~`Bir3 z%qr{`9FR4BcU;6M__jb zV##cDD#PDy`o=1Ir7k&Rkvujd(XbG^3Hep_p0RSqhbM3vO)-wNJE~J|jAeEBjr=Aj+09;FY5(!LtZ}}VkkKrObUU}yO8exkvc^3|qDC3j z*>*FOEA0=O$Qmz-l{M1It*}#xs<2OAEMu&pre@S0*lc$szuaD#SH{@*ou1KLmM*(r zt!4JI<Ov}EffyEo3I z_Db2(#=ke38yRR%w3}2{YCpYQ+PL?xsnOoK{dRwMl-m0(kTza(+1SXEyU(uVbE*Be zYtqICKNuQ)Ebg&;rdwuT`$yV1WtP6tifdhV)fr{>x8-Gw&!5#bk~ZnI6I@(o&*39u zED*14WZctkxA<*l`D!+h-nhkd_>GqQPO@9S zu+rXEUCubdme;88Zk!$K-AenjesadsTe*y~JEH8&rK;>D{p5`6;<=3Um80zr2v*ro zwUskIf0^6J;aH5_)?bzOA-ZzLevG_EYg6Lv_CKz)XV;Q5=AF!I&tw7<(HXMABkzY(8evR&W&O8eU%WsUu71&l)0q}cuMsI)hKDr+2n zQP3#JIL)rDsM7w-Em`B+2Zf9tZb`Q@jj6Q%a#GfK@?2pf9pg;9cdnK8dOKx}A6JMN z$*j$?JFH)6zj(c@aq2=*qhh5TyKRz{;P5$9E@osnCD(2bbEWj>pqt>QZ_BN+q0&^ z{&uFUv73Oj(fKJQcDmCm>}B4{80S7zG~y4fxBK<7+}x*Cpfjl{`@y7XiItc?5&CfoHGmfD-fN*jM%U}02ubfVq1^ium(4bsLDH_eP* z#ZR#7oKtGgx=7kM?udzz%eOwew2P(opLR6+g>Gm)kg_Cxc)5PvBk}Gf47>lebltX9cJ;%cL*PM*`IPi*?#|>#2vHimhI4V zbJ>3>O2vMbp5=}Ym$vSBf7p5dt*Xi9^TMy9&YQrUtp@L{pQM)9UfPg?8q*2 z+TT>CX1`QAZO6;n#XF4VIPMp&QMbRylD6Yd?7|(bs~z_5oS`z*Y!2w(aqyqR{&YhP`_nzVI}JsAw#RI9+66+3itoc33Aso5XBlDI=Ub@2`ZY3KcZdsXcP{zdNC%(i@o#tG;BH$JG? zzx0sbd8;kK^g*G^{(dzT`(=h{JHFN~+Ob>0b-z%Yvi;8AB0KNwdB1Je9@qVorz_bX z`xCI^*~Ha5md3j6|8z;wey&Z-4o3YIJ06<4?=L%{VBeV-wPQKg${ky|J@(7&lef2A z61k&QV%3hd7d`fWIU;9oli0LFMRL}TvL4U#B=}o0y%s4kDNQ7{@T1faiz!p``_j4=RZ-{ zDYtdiwyCxr`zP1S+fQEQy(2$(!;ak--1pyRSFjIKkJ)iWb>)uvN$&fIlrkEY84ldsj=;^%wLz}Aoo_3|3hq&)< zjX3MH|EPqT{k8eoJ6u>6?%3<^w14SpHTzljC3e1)=iP2{!EygXdv*Ksk&!!2`!C<| z+Rt&n-Boq_B=w{njQbYvIDFb+|IKU-``Opt?)a(9xuea^VgFNRO?!=Hr+1v*ZL?#? zPW%16i#6>n#4~oR>0Y>l^Pl~Gi!e=lg~Ie5QAZZ;_@C>r|I;-M`_Joacesgf+F^Xx zVgG}04g0Ip>~_AY-C*A6?YLj(rn7@Ay8^X@5YRn*Fnwa>m+bKV>$Jb(fvSCsZTt?04NG@iNO#`< zK1tPnPqh8cjg9-v*I#tr-|`%;4v46kQYv+6)Rtx>bF8ixr zE890J*z7!YeYN>hF4z5s@|5kb_XO=&vUT;2Cxx#2T|X(=Ut)^eF*|434%Zv5`=6I8 z+220Ww8Lob^c^2;-S(gOsc0W|-esqt!7KAOi`@1;c)y%|$62GDOG|f}wYGZfmr#|rw~~zB zu`^=Tjv0I&`|Eef+h6+~v%|)4)sDz1?)z1O73@zfiP^Du(~2EAQttapUn$s2-HhF_ zfAWeQ@$=pG+czoN@7of;J*{KosUPd@L+d?_XEjVRU=iMBBmTbL-mKQsIAP0NgPMR7HW_c~?cY^-8VkHyVQ{+l znoaA=di%BtPvbE8Ee7vSJ+aAuR&W2Z)YCX6e80g{_RluzkL&G?i#?5>b)PZ_Tf|_y z_I|y+e}Sj5=i#dc3lFf{{=Z#sZ=36BeD>=DgY)^);;z1HNl?7=l6&kF5Kl{o4LK-{(6X~ z@vhIJhQbwgw$eN6?JL4PjRg~g3`^cv+7|Drx95)XH2!d!&+ue|sqOat_4e&Cp2qAJ z+=jeY4Q!tss<;0Y=V?4=F}tC&r;aVdv3mQ2L{H=I{49n!d(~~(PS)G6O!hQ3t7b6l zFjThve!AZNMXIOq^>aTBCNGtg@yaJdLMl-!_!Y49%pwavRH_4c1CJdM8?ZZgmce`NFfS-pK-m8Y=|=W2rxyPGy&Uew$F zs`fOtzPH#QNA-fujaT*dnYEtAi?+@&DC9YAv;0lH{qZ_aW1gO=1{t6C+9bZKw-;#e zH2#vK0Gq+iQ~yCVcC+dHA*7ermI)@y;`a2AiPrZyP<0%a=48On|0; zz6MWYuVjRMl69WOEebOYKGYwwX@6U9|EJp1IQsr#gIuWlcUF2D=gnDXaQM_+n_tiC z?L*5wjq74}8hn6;$MF(Rfu(VoWpnRpG~OBve+9;~;o3HLOfk|<g~T&c^Y51w8CJ2;WeA?m-Y7O<)ekt&CO-U)VI{Citp!}=V#9w)nM$* zBLe5o`z~%Y!)f#88ddTA{PXYH9X^V|$l58_J&FWR#A5YHBvc}Ko^Z&B;52Fruo zGj00v&3X~aaQkf@W^MT)ZVQ*6>65l8W0o7-zJ71jEe#dHVEaJ&kDE=~qVLNO=Nqj{ z+pNu93RnN~QNk9Ro7>?2VP7Y-rOoRT-25M#Ew?O;(Sz#`)Z*PD^Ysy2K54Pw7DJ)C zaDHxz$(H9uhv4B+eZF+d#bxK<=1*0W+1zp65^mnYBI_*)cJtx-&9;_q$(+sz_pdP9 ztSvLIbHl?&>;&(Yi;TD7@=8aFHh+%Lftx3q9{s(MoG4O}$PgJzn z;<9!k+`pkId$)Y=%z@kI{+ema#hZ`e`k!*AZrOF%1@3?QcJ?h(&R&Mg3$EX{`KwA8 zT>jddh%GCvGvM;cT3lP^Mm&eh`)ToRk^A}xE|1O+uw~qm;dCD^-|64FsUva^T>mdg z;VsE$p1|e*pZUGn&k_+H$J&2wzRPwGtR9qppZlKJ6!dA|<~nHp*(9`lOIaEsy-hp6 zZp)rCg7EmW(dpPyaFG?xFX_qK!gpI7Y#u1Rc3tn@{L$tToUdNQvt@aoF+BW!-I=nb zI+bG!%s!z56E^2@?SZ>@mh${9|LuC==35wfZ8m;+dLt;mfy~#v=xDsSyvhj1|8vn} zOTrahc>EoR|F%iR*c5J`w2;6S&2%w1UvZtymVmR}aP>u3dbiBoI~#7_llIk{fAJoJ zyJz09yiKncJlq5;55CW?+4B5MEIfTAG)~_VueBbof8kcWEpHd7!p%RvVb_*e_F}mF zon|HDrqkQt;q55nYBYxt5gtz^9Jc&E>ke0c+pT_cjG84pJa6yby(Qsi1YF*TY08$a z#cXi<%=39o;*2lA%||aE&lhU!zU`R4*Sz0tudr9W{pn83}toL@UbK83^x88nX$NODs`6_#-?s40DzP8?eZT*>D^OAV>YM*r5tJ+g+9{`N;q3he%or}{@88r%a!%^79#CdttC5cOz*huy|=L5UiQmst0N+B zZ1^v`?JbyIZ~uhhf>psuKHGoC-S%GWs<%(&|7>;qrkbtgZnwSmHTCvIM;3Ony7mFuqT?<8Mc|W3wqu5x_Q*wM`T)9PuH%s{afR< z*W0w--uaTN_1Tl{wy8O8dlQxF?IrYstoON2uoZ}L+k2S5-o7&{)|%<}blX@Tx4n1& z*4c;Ur(1L0o@cw()@`rM+dBK4xB1pj)-AE!V&Jwn_+Fj8F-y6%de2JRHdVL1lP=cT zC(Wy|woO@UTP)+Y*ZO#!ePnQh^#qL#wr51$_Ac39Xa69s(R%&#jkf+mZhKemuCw=Q zZnWOCf1|CxjN4wL-F5bR7dKcx^50;qmf*Jc@4hd-E^X*kG`J=7B z8cwoxTI9Xgh`ruE!QIcgYDR}`nYr&?N9lTdQ(Xt^jKUh*%!ht^gZ1m}-##|5-kFtV z+dVyC?**rN`|}eOtV@&pZQ}xi_8NrN+XuSvTR-nIx9wsH*(;P*Z_l*mmz7MQysi0) z(7g<$_4Z%BU$y%Fi_KQbBz*6I#(Mk8`x~q-&be#DupnZuNl(4~{O{dX_3`U$B=1D- z4VhAJ|6_r_70cEJoAXbj_FB!Vw~u_qY1JI0Wn;HBdavZXdiw=e`Yq)YHd@bgirH(v zpx(Y}uZ2awd$N^cWz60m3+nAJ+FI>2c1qoCmlCsg<$`*92mb3jzfWMTfw}$NHOs}`UHAQy!`5Rt)&oc$@b&06A4~x^;J)u2*uR%rNUTcqfdjWH+ z-H$_y_m;fz-y3dTZ{MQgzFR?}d2d&m-`;zw_4Z)`!MmS+>E1ixjn7^Kk$U^!XR*64 zYfag^rp0^jE~a{W(S-Efkqxu=8d`bnb@)_g?>r}e_oLqn_g>-m-24AgoxNdq*>17+ z<$HH>d+g1>T4$dlTeEvE_nN)zChmJVPSx2TV{F*{-hTaF?-_1;4<4+u&oFM>U1zm% z??W@Uy%YD;*@w++-2LI{#=UAHZhOz}s+F|k=kAt0y=d<@ z6Suv(kL&Ci*iv>ox6IkQ*U4?~lTUT_k7q^hW{R7-_gJ9YUQU*J`-%U3cfU&O-McB# zZLfh?y?uzMTQxZR+jO%g3sgs@*BU>3hF% zb?sfkSZ^OtnY`PWCur{*k*>YGBK7uVzTUfwc3JNYm+RVFqFQhNK*4DD{A!iGEb3i* z>rCtI+k_={JLdB2J*C&R_pWoj{j<LfKyR%xzZg;zL*ItvXdV8M< z)s|Y08P;XaU3&$y>g{L0H?Vpir)=}ev1_kcdcFNOv58hZKU!_x*>&yRlvr=S;l&B7 zcTGEOCR%mvT@+bwUw7cY6_5HGn^z`Xd-eS5?fh1;aXefBb|He>gw#xukN${X1c-l+5XPG zkIU-pUnL!|He9;VcJJQKz0Zp3>~$s{u(mk6(RRxI&b>uNb@mHH_FG5AZm^wsu5)i# zS)G0Vz1`NVE^BQkzU$mOuddF1&c$ukf*C7p@5p!U_3f^+pBT2mI@WNJ?V;GNy?g-p|m~YK(H_5jAd)MCD19kT81yilrmvq=#1$6IKy;^5~ zD80+trM<>hb8YwD+b`?vOB`#hb?Vb>!+3i3GXATxx2jFC4k`7wy^-CsmtU~n{>OSR zYsNX|wzVgF_RdqPxAzJ$u=Y-nxAjr(-D_f0Z+~{1sI?3SyKQHA@7}5Q_4XINzgb<` zbl0ZgNblZxUiJ2SWe-_N6|S>kVei}P5L|CxUfpkHaHzp%x?SJisgd>e{Ni?2Dk)kv zTQmFio{FuvUw7lE*Vb6-ygikI<9Z;r|5cnHO3{o_L@%Kv)#CF zuTFTqJsZpAU0Eyl?rHenyLWm(y?uKm<8G}7FZS#>)Vo*7quyRVNOJc9d#=50b-jB} z+t%9$=@{+~5m4A$Y}~tdkzu`k?k11jFV~vx-Tk;{?{VdNd(O@AyQ5!w?Oi;fXK$uR zz5Uz2rMr7($L}q*?%8{ox!&GwcI$4f?Bcx#pLXwc`&4Itb$S2pQ03;mOcT5Jnm(wr z&*Pi9dp1MQ-f4E-d%vHpvv=RQaQAn!DSIEi@7ntVRG;Ro+sa<=6XV=;1|Ju4+ddl*>TXeeiCim9aE3DqN`?AEEy~ck#_pWQKv*-D< zcektW`n`{Db?()xth2XfKd}3$`^LRlM?3f4F0QlRwEe*DxX&B+p5EKJm#e7GK7sqd z?$;q3_nPkO+y0y}N$|uitBauyb!nWu5)px?Q^&P1o$be6(}#t;Rb0tnXWQ z&u3e)_ulEwz3jbp_7YJWcIRAQv{&nL=ibIyb@o}kD|bsxn6r2N?asYUtLp5xpIf*) zAam;8-%mRC7VNIGKdC!&_kzOSy_es0?p<`Y&c1k8|L&#RTlW6`(YZI{L7n}BwAS5L zv1NP1nY;G(ey+1eFCPVWCfk14t-nX|Ta~@Q8b`Zr$NX$JPL$tc%~5U7x69G)!&wX4 z4|DkT#7b7%dmMMPJNa7CR`bQr-I|)!_7#^M?Luw2Y~`Y_?)EpYwokd|XlK~}*rsOI z`rT8UtL<+;ceKl&u+b)ywR87!-)j5C?;Y)K71r9QPIBHI8Cq>W`KzPdj5aZw3tlgF zwM13hPx$F*mmqCzeJDs^mq2W_ecNwGyGct@cC)q`SiOy@w$J_TX!rH9!k$IWKdj`U zs_h+rI@-xUYTlDS$=iB;NVUDdS4X?{`P=qneeAK`?^A96;hm%1zRDMSJhC=hmpE11 z|9j?Wr!bpm?<%&N*8feb?UU|0+J*b7>}{F(*LtpcwY|qBM>|6S>%C>M0yZ1PtL^_C zb+l`K60ldyOwp!_t=fM34o5rNwW)he91Lv&zf{?8TIFb$?_0UICe^`a+QTY)yE%?_ zTer3DbxQKHd3~Q&E~R~R(+MdXMm&K@4c(` zRv&4$`C3wCpXuRfS6RMx?}2-*HWj&5_KTbx?fyJiw|CFiHk+=@D*IXXj&>Ow>-TDi zwA;vJR@uAQJK9CeTf2APpH>^5+$wv2Cr7)siL3VNENZsNE3L9W?%`;sd2;FA*^laN z+?uNFHwHP{HLjk&SEi`UMr%@){g*gLyZ)#ddxO=pZIYH$*)!)l+C}{6-+Rm~&c*mYa_;OX-uiEWsXLZD6Z*?QLjjv3#ecwq(JC>I+doLS&vJTg&wtsik z(Qd&$e3*4HAd?Kyus+D$57xBK;)Hml^AYI~;Nj&=@D z<9F>5)V1`Ft+wC(+tE(wT%z@NeZ5^DVyf-)e>>VaO=7Z1sXMvLJi6Lm>X)M(TUCIK zwZ7MX8yYP-H(H+?bm*Gv=iUG%O+7`!tQ_G)%H>E9POIip4zm$ z-LTuhx!S(}xuadU42SJ!!ArX(zYoV3RFiB9XDkNH*h?JkaXlCA4(H?D2l)16giALHO? zcSm=_6H$+C7-K&bD`Z+n)5SDtku_X!*7A@qpb2h-4m+pH^e&H-It$b zyYoTr9^M62_A4_T?PiEhwq;^Y-t%)qmHo~#N4qt)-L}u4hwXWMsLH;(#nG;IS(ELw zrJj2du2$KfpX6xwv8~8Y(IWA%3{)OW_yXeX!~=@YfP_f zR@+vi!)*WlTD1M|N+uJ2$CxcYE1B#C9b@eG9b+`Pu_|WE{$q^xw^qg2e-dCcNfwRW z@?L<^K3O!@e%i;^Tix!Yn$<=!*o!vA+81;F*e>2tXu)j%->&d=to=uWep8dRT-%fm z{&;*<+7W9nq{?VApEGugpem#N z0?t_bU%wblBzt1E{QAXcFVz!czv3K|$tAv+Ei2A3*Bg4JGNc9eZCBb&)T`KT>9jBNJ*<)iF3 zXmD+lm=>x4+@2Y@sD}&b+6b)Bf_;aQmOh54Y|Mj5WLb zn!~=uFT%dX#dU|u`~4ON;yCOlERV21wKZTnPw8oM^9$_uY>biiUjvPIDAupDc;mos zUmO)_|Mx-5_Rf6_7A+gt?0L6D+MoTCynSl(J@egiZ1%r-qwMc>vzqW_L~Xg%&1%n| z5oN#iJBvx;p{Olezq8oKABwV9Oky!%myO<{ki=roDjRLTTz|d^hp6CIv(wD>Z_1bO&^%`*lYNd}jQyJIG?SiR=eG3xW3*@Jim|_8 z+OvH@JcmU@BBOoWvl#mgOiA01y4*46J?ABAxla-K0OU_T_6G%^t7Vv#n#zU%Sn5arWj$`a6DStg`T^_-9wC5@+ueG0pT| z9{;xB&HwGbo{Y7ZEM+heDu~@8Rmxy5R1j;Q$;W7NM=W+r79XSiZLwJUXUiB(rtFQ` z@^l%a{p7td_PTaVCdDZ+TeR(%?2A)k>`z@`GST9W*>dU%lf5=~jD2wivx&^+=q<$= z%=R*yqwNKLGn=SIM{g1M&1|m`9c_QRhs8vfIeN>j9u|8&=4g8*Syq!dtE09k$gfMh%L%@+3nx|h_DYy=P=P)6tN{Jox@&xQG|W; zdkzy1pNK8d?>X!}d?M^?%Q#KyzJ+gTDC4xR`xb70Y1c86EJ@R?On*7;mo5mm-@J}< z#|wrwi~1%m`+r{H_F)W>rZvo`w{o*{+t+;!v*(@4ZIUuGYzyyHZu{h!VfN3LcwP+8>)07QElA8OLV-`dOqsdifZ0PQ=J?M!!*i z&+C1=e3I?CLxqh(fAt&fH+i{F^?9=W!|8%Xm)s^81zml%ud6Y|{;`gL(WfI5j6UT) z+4n&@)xPQ^pOL%lL?bTdNBa!6rrN(T;WZLym}n&2dVe2xV48i@d~T!t4<{NqGT+^| z;dPq5H4B$fit{9+$rZQuxwoa;e^2Hxdbnhg(Ss+~_nlP8u)lnS&8U-kvQeem)qSnI zGwdU{SdEG^CmRLKxU{b=Jk!42pUr5h{A8nfv##vB_$b5vw+n}n+L}p5xm&L9-}io_Q2Uqr3Z5j}+ewNV z9c$?~l4gFh@0V_}eacxequ>1fMkn^X+gDVcWG`YRVN}%CXOx}&ai8A7M0-I~DWm^d zeMS>RzwB$~Ote3KP1H?eh9uYl{Um9%c6%6=l8ICnKC} z&mM?mq23Y4)dgav8}9PBOBXaeJSsQ@XuyFsG4h`XnRwgq!<}Po&$Qdd6V6saY&mR3tSXa@cHFwMPxnfOy}>sYqn){vjkXtE+Q*oXX&>9bYP8E` zvXS9~%lq7TGwm6j*o~}TOfm`-zqW5ecZU7ig&amRr%f_ya=)?f3TK9W-G5G_`7V=; z3JPxRGww*Yw}{|2y6|bD(V9tj_DyF?w+~&*V{~W1M5ATv?(O^3l4j4$!e=zuccM|? z*$4aN8Pn|ZeEE$w{+VEucSTMN>7qvOlKYM7PrcbE z`YXv^;JlcTsZhU>_>On`)>S0guV$7oN;uGG^m@UEeJ0-%?QfY%8nx&38L6~>+P9=M z(LO6f%4oTCpV6wUFZ;4TCD`wnAZ>K;RIkw?`)~W=ixTYTZI>~Mtn4+~CiG+9+K=(} zs&{3Lj;Z$=F+Bdcueu=Kp8JEG(dGL+MoQ~{@3VX#XK$*YVC3G?W29C7ci+q0IQxoV zMWZ~O9wX+s|NGh=#oCJrDH>VX_ZZcF`?t@7Aq}is`*Z_sW0lTXZ$vUUG)C(UcRtMpL}M?NiK8us>)iW%S&v z&*-h#mwhUniT3HIC5(Kh^cmf{_HkeCl0^Frrs77@|N4wROn$#_u3eJ7_X|;@TEBiH zG0(UA*ls4-qnD3sLV7nZxPH~7Vp5sC`RdMn$3vU9?iZM`Ep~gE{l$eH`}p|SE%qER zu`Ib$W`A)?`@Xj0)6Ek~&spqeEVmbEY1_BwR{qvs%du0@~_29bjZPz)=?9b-+?hCjzb@P_0t0wdBm)d(w>D%XV ze){HVDOXJvZY{OnwWWU_|Dsu2h5t_5cBs45{>jA&`+jo@SQK)qS?)+IwZHIo;=WYZ zqOGYlvD-v_OYOreChc3VwRW>-`V*5CIi>a*OD68KIy!T+wBJ<|n-Vo+ zb6nh2lgBGd?O(A>*w^xA+U7-hS54NPD7Du%>fbk;ZN2H##qZ3Do|oEt#`W#H^+wF1 z4|O@f@)>_x<#{U zxxGtG>%NEp4)dB7_7;h5<@WE}TlU4RVBBKW?rNNtUT)tpp?P1>b93{3Z0#0V9p(0B z)0_6${17o;xH!sU{>pOu%vp{5+@-&m{;+g4|8uI`K6qBcz9ZdB&F`fCw3z&++uvMa#p;$XewEud_}1-vHN#}4hRLgSv^)FiXaV}}wyiDeriJMfpee(I%eQ%69 zHs9yDX2STp%)V!9+rBINIybZby=rpccA5RhneF@LyLE5YeS6hp?w&IH$JHJC)}HLy z9Ci1q$&$Hc_F~bU`|LgXHn*LS7q$#RyM8~abUILKLMpHk4f&s0UyeD4Q43w6CR zd(EPrefy?xTO5)xuq+HJv)@zHz3&jm@~s;uZ{PN_tjvC4e%C(q^0DZi-Oj09_jfG1 z&uYKVB+C9x{pIZ&)?D0?WXfuPZBCT^tUP-Qp_rXJ#5!5*%UGlB!|G0(?|tX8qvbZU zy+U5Jz3L`Ui?`8TJK}Vh?HR8}+dpaL-C1~L#}2J3Ci~A0G4}4$Z7ufP-L|9Y7^D5a zRWbHIZrE5bUEQ|BP>|8yMl{xbt+CY3NcU|!aw8e+Jc{A95Ymc>G zb6#U-x#0F42C9tqeVnoOExSA|4tj0dq4k^5{$F>DePH3N9l?=zcHBP4WWR|o#{SH{ zDcid*p5Ea%pV{7dQndZ*>1-B?$vbw4=CatQiACGTI#}#n#(i%`tOct*>+C4|1o>Ut zeP*27k-^Aj&!iA#pPlb$Vc@oNhr$Uq`~0Pm_B*fM-EMtj_m0^;?Dihok@n`+0oxBh z-?JmzpTpj4V}yO4o%r@2_hxKM;ODgeZysUaH$`iwtij_t@^#BIM}LYV!moKTCSox66Z zi*nn?z6rB;lH;%_y18qIM-P|%CYNyg#ZeMFB^i(GNM+)(H<}x6FOeg$^P|<_9S!B2 z_P4%<+uK#YH)FYKw(ZVq4*NR42>Wd1dJ8SZ&pY9%0|}?7)t)#d~&mUtqWY z$q;ETejt43yN|3pZ#b~q*GEO#KNj!XQNVp*N6ZE`d(|zG_BsxS%!|3UY(Ff=X8(;h z%6^Fy@6OoIdv{#zX0;d0h_e4UIl!XWa>tIP-&yQ44@KE~=~P&#>+aYglEh-qBO7f$ z>7(?{2WNNf&^*m-|G7NcUVB0R4o|C{J6epH?e|`awqIIgYY|_)eTUynCi^vW3;#Eim}&-Tff7_Vf&7NL`M6hXEFAS-oX}Sy4!XzA7-#W>lADMtS4}1 zTl(J}T*?ggGv>$Io7r_*gg)H4Bb@2K-NQez_7U&Q&5w3$+@8PYuidV=IC}<7Q;R)r zD|g6M{IhFSiL;;WFk?qTyx@-1P5 zGTC!+$JmEe#ajfVZr_oV!ECR#IojS%PGIL+rB6H5e>2-lMMv9Q^#0Br*Lqm& z4Vk0ur+cgHXvn&?!(5itzHfDuy|k*;PUDAHcWA6(wf72%vQNKYYH@kt>K!gtZ1$Xg zBkh$951ZY6zuWA=F*bX%Ws&yFKCnUW!w3fp3-6sf%KmHM6 zpB3wA!7Z_KhjluKz15-!`-7gxcAPgnup{6-hrORqguS+NghfZn&K-qioc8VC!tJ|N zZf^g3YVVHke>m;eEC{#v+TyYOh{L`eElphZzrDikbEZdbzijbo8y`Ejea+V}`|Z2K zcS?U_+sQta+dge(nEmp-Ior%W?AmdsjN6`hZJ2%U{=4QMjvm}mc!|rtN<7@&_twcB zs&hZ=cxlXKUr`%wf7tKhjzzCF?zlOb)BeokaC_(7dv+XqZMO5^Ck}fBuL%3abL=hd z$nV?%>yQ6uwznwO*tsKgHM_mIM5O&R0r8y-j{A44WM#MasE@Q?;I&};o~yfdsKl|^ zzk3#Gk6u3ByewjrKeOMcz3275JwD0yGkyvg$vo>f+GO%_pT_fK`$$$Hqx$d(Mz&X< z?dxw$u|J+GU?g*Ng3;sLC;Prgr`j*<<1<<$G|`Ba`O!Y3t*Q1)EO?FBY9|^ALi^*+ z2e^$a&rdWmW4^m@)9W<*B&Z&v##vB`Y6NRdLf6A z)s{&{>07Sv4Su7k4<;CO&Un0!IWX1!@FYQ_bD0y2z7{;&cL&-Z-}SxU$jkoazM?0| z_77!6jowY|H@{YD4&yxUh&o@8H=EMe5#(`OW!{c)f1!9;sC zAt@tGi9Vw)(J%X2ITP)JuS**V@8~rOT=#7sGqgW`+NIa%nBC8PLG$A67x2p)9lzLP zBz@xdKHV2__Dhy47|o6CG0O4(w@=$3&YpXgq7k!fkJ0?@|NBy}#@c7jQZTZc)nin% z{O>-MggE;Z>hea@F7_B5z3_YAuBUPKr(eh#O;zbNO8@$EUs!g${kEMlM(-*Oz^UzZ2}UwIq!)%KMB0!$0l& z+L&k`a!1_g-l;w#r{oX&=CCK(?>Hc4q#)XF)RXycUrcY3{fc5yqv<*QMv+->_9+P` z+b@(5G5U2H(I0=gUC3y&%><*1Q7`r#kxQ{RNf0zLE0|zZ@AYh7&yo~-E-eA0OGhUd zX`4LR7pj$Nzmu8Y=&`~?qn}cb_W7<)wO==z*Qlv{qS2=>_xIg1O|zd}%VU&qcA}Br z$-DcE_N3V_+{I2!9VZU-do6#M)$wtd=UD;=NCBy#vcNQb5qRB?{i!SYBPsp@i%fV)JKy|W_+Jnpc zJb5$ijY6+I+9%nVYX5GgfRWI$2}bRApX`%hNVWfTOVH?k*aRcFhtKv+s7tXw zDJ^W&@wVSc_x_80EPs>j^J7GeQn&RRrC)!wZ&G!#{p$`B-y|JCvNoOV4u;41t0bqe^0bGEtfR<8q;Sa+xltWveHER=vpbG zx9WXHE1~`IUsI)xoKN=}?X~~5FR>`W-s!50(ay$RqqRam_HFnWZ(sgf)+k=N*XaAB zpZn?x;_YX<$r~x&M)b#RT_mwZ$( zO1A7Vs`&PApC?0{{j>skBlb0j{y1BNoKXowuhHN6zxH)m$J@LAkTHr$={33o?T-h~ zmNuGuy4R@3``bR{`~>?|I#NcBGJQr5#lGy*;7qhXxku+Ai|ea3^PRx&32{=6&8vzHLuG zXSmaCX1Tqjc+)=nDYv!=mEYS6>W>$EY}m)-Gk?4Jxz{^j{qbBIGtRn@w@0Pi+407t%zm{~&psjVv)dmuecu7=k8}3lG-0dvGFx!J)ZTqc-@ZL7 z?{EH>!D%{wYpMP5E&cnJt3TSjI)c;mKzFJAn~M|nMJaijNT2y>3hIxae>-vC8NcT3 zT|QHGi20V<`&LZaSFI?wBl3^Q&Sg2J_NGfF?pv{gcgJY~m7TEucy8&e&9zGmO=11< z8Ljs=rxkFT!usP^Qn|OC5SH9t_Po?yJFaivm(TV)LOL>b*0Yt_bGP^IyZuFeyOgBE z4pFr-`)#Xw_U)CIGGVuWYYOU*N1f~5wkUHfD^Wwx#AwAl{pk2^Fg2b(Q7z+u54;Eyy{#IiHiu^h9L2{kd<=`^qdgZ7pWKxGmSR+`jxp%Rc4R>^ml| zv)BphkEfh(-N)T2x}8DGeFxj`GW+bUZTmWxh;92QWV#*HAAdKqeP7_r-P^CUf7`Ke zPnrGE>W+Ovl8k1DrdygXpIc_n5Z$>?`5xnryd$bRZ`769x0rYB3wok%dV5yCnMOjH z{T9LQeLMB#&G@83%;!3m+2_CP-ls1pu;U1W;Z9xUGJCH5J^P&cgm*Zx8}CeIDYIWQ zwRc}!m+bb5|E+d_`r{jt`}T>4OYZPeH`@v7kFy!}@7vI|d%M{0+dBkSm)bx1)4wl` z>)Q53n%{RM^p@H`J2qk8xpPlUo*8-IMmb9OwRS89LCf5N{1rnk10ZT!4F z?@#r zA1J^0Ad{U8x6yw0gG~D*xsB}ep?qg3KMTsYgYwg$d@CqF6Uw)x5}%Oy=}`NuX=ER| z{pfsj|DwBxkopX$`)#1^M^}$7k8U5e`RMMaw)vErhaNtpnny@Kx;%P#pv$B43AqPd zJ$n42%ah6{WIrK!bpN9B(e)FOM^{fOpH%bF!xNp49-ip#K`$RS&0J_1`E!a@9>=MD z>{i+KU-XQv-u`y6{`Gy&zV&Z%?RP9nv8rD<%R13`&Au4XLVN3%Iaa2Ohpk)R%-t8= zTx`FpIm2qL$OY>SWi$3QC6?G9cx7ZI88FTI6#JZg?=KeHN9HWF%>Mh;>gTfs`zEs& z+h0{@+tG4Ea3{mNMf(gk7TJrI&fgh%>Bz3d&ll`#VlTGecwS(aiHzCq_{+2R9lup< zf6Ccy*Or5gyLFSN?z?ik#Qx*goL&EA7Vi#N*|%@=?Na;v`lemCZtdBfwWniW>!vb$ zq1N_YQcF(l)-Z3~*PvT&|0<|sm+jO2yX7u*?R%YGX8+4SYnP*TQlI?r+Y@MxtKbm6a@vOwY z`OLFD4DWVXhllpsm47U?cVd#*E6l)d^Ubf-Zo;oJ`?oeKd*5uAwt2u@YuA3Q+`ePl z`#smC-&mi2o^Mxlu)^MKf#;roJRa8bKBw3<)>qnZwClIhI_uagB-?V;`&C|_>yY<6!?SlVQ*q?g8-6r_3-EPs4a=VzQ3VXku`)!=e zOm;_4Y_N;mS#Cf1*Jc~eyt?nm-$v>%+< z^?2$eyI{vs`&Y?QHo`XTyY5VxZuhCF#6ECCzV)%Hmpk*1%(C0cT4IkL9%@gY?B`B;{ieOx#($>e{(N@>d*(LFJr8~UThF@3 zxqsi9aQk=N<$JtMQ>|v(rS5xCQE5L{q;bz_U5DMKHWT(<38}X)iml#L67pmBGSknt zQ`GA0jScJfIP8(%v$>MrE;6syex_2x9>3#udvYDs?VOrx?4OD^?y-&w-ZTG{zMY$D zjr}{Onmwlq!uM$EdE0s3uCkw&oVkb5F<=k(moB?^;brz-?_BnLf?#{u-Xx9%^?mrpi8JyR5N^n5xm=4UKlImzCSUo+53W_0HO; zEnU_D??w@zQ{imNo#+MS>jaE&*Xs0zP(_T_e$he}a!)VU3 z8+J=Sr`uaymNZ__6lN4YXN6tljzarMQx%OTaQJWVxYM&I;9I>tdU#y?o3xwtzT}=> zt*HIqUb5OhWJurB&bNNg@+T4dd9SkDXDi>@GkxRBJ>p9v_CIFfuy<$vzbEIL)ZT<| znfo{Sp0f-1&A!(wNOEt9Vb*>=gR^#1R$SV{aO2FL6V~DTb$z((=QwljiEZcI^Y)q1 zejzb)d-hrHtnRJpwPG%2+yCfhr2T_*DI0m+-_~cVg!b=#8)&~RuGMDU^&*>7JB9a~ zG6dS!v#+x`nY+#A{VwVKW*px3YnqPQB*#3rd2m>9|7?9Xdn1GWHt|YqwvvT<``tvX z?UgUhw>j9#Y&*ThdVdhJp8c}ZDKft;qee%h>Jz zO{uq@>weh!z{}wME9dgtqlZU`b&Ad1+t;l{kH_2nJ6>teda}(%{F$Q7wcT!Z3q-5! zgN?gvR-cWsv3c%icWOnIz5mV*o3O49o4tRE?e_Lo*!$+x*~DI*XtTX%3>Jw$N zQ2eF!{PzO(a({yC8!gLht~791Up;7KpJZlkAMajZ6QUfn>riv9UGd)vd*N&9HkG?H z_B_5nao^;aQv2^r`qqb!Htl)xS8%_yLy&!Z>aJZMWqSAAT&TU@_KB^%;e& zJcT9pPkZKTzinQkjlqKByG1J&?UUVGWUu(O*(OzWvDLNqo4caF*W06qhcBy=@rU1A z^)=rMSzr5KZ@;if-k5daRm1;j26py3HTG4nWsMIyS{eP4o@jTeq167?Dly~d?-Pt3 zUteeEKc~PxH&fWy$FA5&aOW1gC9V1Pr!6IoPp%I&3R0P4Cw;Eies7}`aUjO}_14Nh72+x-4oZ=c?$WURJgo#D3Q{C0=SYVAX8RE*PZZC>9LUuv`L zN4@={t?-Vr0&vX>V%pV6Vo@X>1?5+~|oZt9|>NDEmi; zq>YbVbujAVo@Te?P>DTyc$nqC+AVi{-tJQ&fA&q;8)skcH+hdkPw$?+g);lUb$Ho} zcAVYgy^3M)mTu$yrwz>PB`mJ)Q7+Wn+qBtv|ABrLdx@&0d-kfR>m--e^zBcrPDr`zPw!K)SNq*% zy=$kB&1dWI{lWcQ_I1fOtQW3&V6&MiV*f@XPJ08LNShU}KiCu(rR?8X`OJ>*^KzTe zW#4RcT{HH-sJLb~sql(Tz7n4;|B8(L`-`vG1%F_&y|meYln6IbN>A-JA&=e!=w6fm-)NU z+ZKr*@7e5nUT>dWQeeKnS=K7~sgkYAnR@%&x!Kz@rB_&8;qtakSYK~{RV97Lj|K+o zNAuEcnWop<&)vFv$Bdow*53llZLK=$?M?5l+;Qo-q&3&>0^82Mdi(oADcb{YZ?%%0 zZfm<~XTANsCkxDSw?5%A%cZQ`vTzxJmA} z=JvJMbT{0!`*7bb-!;?uu_~d0DSSGvE|4j4FL;4c?ZEyM7 zumA60uKs?B`D6j{{gG?^>~B@_Y$?6>7{0%KjXlqn)}W{G{r7=vJX>515$9Eegz|22 z*n&9!V4gJZmbcFy!u6kez`aHH$Wu5!nwfXY`Gbh_6!Zn#O?97tF)dUU-`_Xi&mKKI zEO+c)IH|pT0Z&x&zJNKE_Ke?_FDSm>q8Pk9XrFgmmAy}$mGURopattmg3DyRyAgeSmqY)n{l+l-ZJs0 z!n^8a3%$8p_w6$&w_heEvrs@tLt#r<@4lNHW%fZ*@(a&@a#75eY}{A2tK9y+BG)2S zuR99@lS210Ew8t~ylvWo&S(6KJReTAbqT1q@2+fL*t^qTsV#Mz?d0Ee_5yD&EZnm0 zyuw+`DX6eXF;ZF_%~~FQwB(*Z#UTgg=yY(Edo6QARnjAOEurHW? z-7d2}ZS#`!6(&t*vg{8rpRwD#zkhQt`*IWQ*Ln8$A8)t2AiZ((G3KQvTda%ii&oFK z+p+iD=8ZQNnYc|avp?R^X=kAHXtSNwLX(A^753W-O6|1f-QFy7YN5&Z=jHZ3CG~d8 z=eBPC+`HUle|@g~4ypZicaOZ;w9#~xiS)!o`z!A1Q8nbZnK0uve7*^*yZi&u;JD zw6bWG$+GBp`x4z>b_=G7ZVtY@(&U0iihb7B=XU7fkv_rBs$k+HD;sf6`v*o5_M0xr zT7T|XYW=B|$^N)SjD3+(r?u``Hk(H#KkXjQjkkXoyx4lvLN%N7R{!nJK99A}`O#y2 zdAqF5sseWVY>PP% zmy=)ZR(2)W`^L%b36v??qa|_NPT_pE{iJ@!J&O)z?2)SLxBIfO)c$JPhur~ACVPHa zAF;E_&9P4iXxSZZ|8w_)z%O=5-xBOAv_9=pS>C(5dONqhY*U#1ZApb)!AaY9eXHTK zH(nQFj~*T?_w6?n-Zk6E;N6UU4gn?hH7gGrW=)xC)UtljzSX;n>^0NA8fN{NY-BFA zW8ansdGocm&yRz@mn+*FSe2PY_zj}f_9?)lvSEWF4^rym$^Ci zuelvzA8^#t=*g@Wqq~8^`#;14+8dX68U69AHIhCrzhCK}yFFJ!nUUN4V5755PW!nE z)a?0~i;b%F^^Ed@efGb!lCqDri!!R%=V`Ryoc;cn-J13(C!>s*w&obcSZVLy?`LOU zx4_y+j;+Timxp^l)2A?du^J7d+FxBp?&{q87d{BH-@|KZBv;yLq!P%!KPn*7KKzBe z(ZR+(qcd4w_9cEwuwP;G+E9G|bfaIZw(V0@&$mYpk6H4(HWu**tR7CSx97J_+q+ut zv`un%mGzNT_4eu~P4~W*RIoL8KHFNNrQUvqpX1((a(1@aCH>ZI9`*KjO7r(V|Dk2O z^qqyZtYp2t)ZHn2Pc}cadEGbLiifq{{@dG?d-TKs?aY?<-WI%Zym{S@`9`|KXg+w=OuIxC;fQu}vZ6ZWZFKHlBFz-E{5 zv08hd32gh&!$bB0xAn8-cGgcWthRGgFSO_Ws$iq^&ca5iu*L40W4XP0*khZg;Y_wK z-Z$Hs$(7sRJ$T>dY%GH<)Bk2W9=US+n#avHvS!n5jPEqt{q`ugZ}$9e?JOW=bNKfp zyI_-2`(5jJt=nFET355|wv+bHvtKN1x05&a-Oic6@7aYHrP+u7Uc5_|U3d2$CKh}1 zuxNYD?037C7B}s-napf|WJa{TMPbnHO$&DHo*eVoE<7&P-s;qX-DfYn+3o4Q-_E@_ z*S^r>#%>Wau04-f=GkqoDYo}Xk=(QSjrX4C3zpk0zFlZ9TQ0XpH!yb3U50ITk8Jbp zc}@Cve?RnP_iObBc6-#)?Av5k?c!CC-u>b#)j% zo;cq~Fd}uIYJH`>)RZ1W?HMzS!WK2``*gD0{-eVo!)Un~M*pVI+1J0j*#1q8l~HeL zyV21dg8Qqhg6y?drx~S0CK!d^Gu(ej*22EoH{R&L&Uho0`=3lOxoG<>|rw0?@se4XI^#bpBa9j9FPcHFSD zRd)&9-#>xJUQ0V^uYIh&?Z&dO{S5tF_G=pK_iFgPwn@s4*#Db_!##f;gm%`y@vwZDj%Y$B3 z`wy-Ov-8ndXEXEFB5SXg_4|Fl7uW;`e6aD@e%AW_o%;QnN5b|@yvt|1QfsUAhl}<5 z53%~~xzQnR`|7)^^|ed&`*-gx*?Bpa-FCKyz@AgRHT#41E89JMb;0IVeDR*k*NgWr z*Pd;+SYo z=e6v;qS)H$mH8{Vc1UfWF!OPhS7`o;a&(&;FO$u4aeveuHMleRCrX z?75~g*_E6(++X>IY2QvaBm106Mmr53gZ*u6Ec-SdHMXA*DbwA*mV<2{f0LQLSMpz5#b%xTH#f5FOU^L2Z`=RJ_N=hZ{=|Q5`|e#Zw_l&| z*S4}zXaBQJZ2P`sn%f&l{;i=X3TheD3S^de|xaYgeK0}LY`+o*A zjNE(5Hzu+9>|?rDWq;_$bfbSP4IAIE2JZ`Otg>IbX1bAjSL?eI9?mdgpBc4LUCU(O z8paxX^zb)qO;b<2y>6*~;K98~x9jXz9Z6H4Q#WHN-;5P|Cn(n2YjUTnJ3cO5n);@F zZ)1MF{lCz3^*t99mNK3;+-rTP-rlo4U0rrd%#u$GC3|-NsJG9oOIJ@;TdDGyaktHz zclGw&yy@y`i;7j7*S6WJ6xG|?Ii{(Hd^@b#y6lFn>x4S{v)QTY_iz7Fy}z2v&TC1n zJ?FF(^~INj)lTOs+kM+!W1oIMS>3NuMJ?#QsU7#bYI~2WWc7FKx@yTj_I3_+)%N=s zQq+5=E2>>zW@PtVsK$OzYO4A#+dr!F^11D%&aJg)YD!aI{A|7I%8Em__pjI4tG`N9 zXPMHe>LWG7mdU%`KDH@MUGwC6Rl$fuwoW(d?C*4?tKVT0Rp~#ZVzc2-z5Q#AboC_p z2-T7gdA4a2>h0y!)70nJo>uk!`M@@*xX#`=J5}BK_b*lRyZ+TD_7pL;~Tfl zt7%8}Wk==MU%2~yw_B5~O?d@K?GC&@+vayp@4lUXOYIplS*@2{y>2sO zL*c&LYbxwLYZqF5ba`aM*J`ov$kuB6BcC?yV)%5)W`E+(y)jI6_HI8bcQZO2v^g5t zus1uW-d@`L{O&~_Yiv|q6>V7G*4tlJ5ZLql`UIQc4~K0#j@8)*O8e}&lIvu1TsqHg z^~VbP-xG`W7)3s@o+e~&XMVlfUO?7&50B@4>!U6rc1zuA?Yng?_Z%%}w~;=$(w0-A z-o9#8*q$f03O0Z17ulukDzaz#ykSolf4fatw1WNIJa_x0@*;bE0x#JtJ}hH@TF}d0 zeY?h|N1w7&-cAAtyTvm?fbI0(*Dd3lRcZJ{<5~t_`NUhPn>-q z$F5!5>|<>#OO5tRHJjVFy7$=leVJ<$c*0}<^0jjIJ0c})s;c{Kbl2GJ|GiJk-r`U5 zZY_yGn`t}b_s`+*u#ZXN+jC4^(Z*@<$9>mVC)%Tj|IS&TjNY%kV3e+=VIR)nX#ZyR zYopuRH;gK>wd|!h?CoEQd^D2Ubj|4h3qAXbZ>{Y4y&f4&bAM+P*{5e;F@zit=%B3?%0CASV5Z4nZ-59tiFcaP^XzP(|A(Uf<8?2b-}vuExRF=kqq zXvC&`&hAKPmi_x5;>JpUWsD{^Pqiz&USco(TiN&=?*#+MUfmJM^K}zM7recuDR&qh*i2+x`9*Z}0J$+qh!m3L~3C z%=Z4Z(e`CL%Er0IXAJkM3)!(H*4hiODHs>Uf7oEh44J=>@=-93R6M#qTMfeJ(Uvrp zoETyxba}a5)a^q1{A^}p-G==}OV!2fFNOKryW4y)I`;Xt(LWwN`#rm??I-sCHnPh- zX2hJNVIOtH!M;oMw~^+914i@o6z!cKyV=hEHv_apXuF>~1eUO9cYuBOVK-;x3QZwrdrUx`_{+qiGZ zp7wbz`+06F+iUcN?UwHSwC7@g*?z}fWBc<;>APAA|L^fUqP{=f*wKFX=1@yUp?7-@ zn~Cq2$@jDWCLn8-vf=ig=`5`KKg^4=4`BAQx)^j~&%!&e_uW-YwojQKYx&cAPNVk{T7`OY4dEcIQoa^`bb`;ph7BKIUY$N9{ku z{?y6X-CroDV?V`kk@aThnmu>LQ}(L|ys*nH5VENVc(O;*ENy>N z@qN3W-^*-X9W>tCZ<)UTQPC~C*oI#gd#B6q`E@jP|B?+4?fP%q@02mq-z8E~yx$^d zp55H$fZgA#`*y9FT)bbPcdp%hGs``vi$iu**{1DJK6Kx1rR>{1?y^eOo;&^b|Hv1$ z58k?I&*{=u%gI+g_peWowZCyga?jP@-n+Yg2JYXHBV<3xX65cBmnQ9A#~ro5N1n|d zJ^WYw+iGjk`pw4GNozm%N?ZHQ;Tvqvc+Rz{&$ros=bX0vW@cww#T#3#%(Gqgm+n%w z*VKu(`K4*Rhx3yAe(P`Y_FQ+vY$SI$?vb7mwEugxpuJdFtPNv}+@2}c2K!wXS=y&% zwAi$`wd^*ZwRhj=L%H^AC$!m=Tb{Mr=x?}p@y>etS)NTcmwESDO>&jC?Kn|yFV&H3 z6W20hH{Y=w+xYH!`;Zc68`nKPdrTMKv=wZwvk$JYv{^K_f6qk+89RwjHTHj{oozO) zpSq{X(#Njhbd`OxO{~rT$Fui{#7wiBzqrKyn0CF*e3zYjc27ELXD66r?;qZ6!}9gh zo{6nD?1V3-+kY{yw7FWyxL0q>Zo8d~dG@^*=G!jIXgnv}nUs<7T`(9SqmQ}A{A4h40ecL5l+pqh1Y<-m% z>=WEtWM6hP)zI1X41x{CGJKG&8OHsOM1xA%>dFjmmaHF|g9g580=nf5#7KNuxePB2=u`>WlAX$kg6WcZA= z9~2wiS;1(Zy(h*#Plngn;PyHr!z*m|-{wZz>t(VUvpCK*>RQ2T&twy7f81Np*z;VS zQTM0Ic2b;~_Ie8J#?IA3Mx1Y3?VQER?b9A`8fQmLGIG0f+-}c?Z2MK2EXMbW_8JA{ zbK3L&4!39QzGl=Ry36Rn9(8-c6i0jX@Ym&BV{7)!Vb8m#wf3!l5AXd|zR>o^0-im) z&Q#dv3nuT|zedtl#ZPzlRn=_!p6ZkP8g^f?O6J_R^P6di{ZW1X{Sp1|trDB;cWqkj zX8)*2asS=3ffg=}>N`9BXxiV%vfrAlPD zesSLZ?m6+6=Kl}x5*A-*xBP$6{u7H{TL#s#?dkb7*N(BFc>n#FPAePP?mh0x^X=F@ ziuWr_}=Go7u&zuJ8R$b zqn5VKXR3Ftt}L}@%j@44Tj*lD{NvJ{@#@v~b_x#r9#2cMHIG)>y)LWHzER=m-sn?3 zwhz~R*q!*c&feCrbT4}N=R9{Z77Fk++Lhd7XWU2urG9RF_w-oH=6b|!>-(`(mu!1)i_H|&8YW(klpgeDtnz0H)EHB zJVwqZjO=m*YwTT@x*K1RxNG<{lgIAMlv;bq3J>FF+m;!=IdIwbz=Aq^(FY#JYKNK) zFGVf4y{uAie~H)ASn*q;;kSl<+t+dR_8Q8b#{Z=K4D+5g*)mqu+ut$vG=3pvYq-m> zz}B+A-d@?=)A)Okx}igRi0#hh_4W?op2n@Kg$!%Gt!(x7)Y~6R^fY$PWHzjSrDi+f zWW7B@ny2x`i9Zdx>*Z`;ovXL!iu5#2F%~d1Hp92heu2G*vGdbyhIxK3Y}q2~?7dt(jL**9YPe$UGuzK`b@nG_ zxf^dNx^L+Ag4b?Yd#(MZYp%vy{zw{~o91kn<5_K=zuehaeS)JA|Lsyc{^kmM^zeT! z$+>0uwl|wEp6B1c=VY)wmp|tgH|sZ>zvv0(qN+gI%7 z+~Q*Qdb9sWf&J_(!S=}?Ik%kL|7x>nkl_BjgF*J}>Rem$9A9lN-6XjGW?hi|lo+lp zFAlxjyhBK6zqn11{ke%;TUNQe+}v0sv_JD_p#6elTw9(Vd$D=xMWOxgwguXo{^r^e z==oxEj)Cz0l9E9Cczy0IPG_EP?&uTVZ)_B3zb=`3OQPTN&HvsA?=N~EU_ZH&d&{d& z&o);XitK-~FTmbmF87x3!_PKzhl=c9ur$D)={WZm#kgmir!NrMe=R@2o>Plw%io-* zn_mZu?r(bUZ$Hz5cT4xhN1L1M#rHFJ``L4=a%^#V`EGNo6yJW?4m$^JQ<>qCYzfGDw^^=+Z~yIeA@)qI99y39zT3R* zDBu3-+7SEuJ26&v_{?RlD!dtSRf9_H7KQw)fxRJ@fj~BQp|S zs_g4oQDYxCDN(ZNC#O_Z*x9{Dw$|A%KF>UJzu-Knid#)KOTO3J{|;=FV)FK%)!im- zx0Sut-g6e8lvM642`RS*yJuI+?JJ@m&yaEDn(Z0ZV#n@VZof>$f7ahc84{gsadvkf zR@!?v@<}yLm^bUmY7M(f4K?=dbN9~NE8RYee-4YC@{L;i`4$r;!xbAP^A@PswXUwQ z4~R0B;t;Zt+IgVG?yz0C{q`OusfHQtl2O(>?ar*ovlq^IH)D1~rPRgUm+YGTGwpx% zrb^nrnJLxHcECayk5B78jmXb_2(UD2An%6u}@sY zj@7@`zR|lw>Yz>U%ovtT+j~>%?NvTEOU2gSnr^H2c+cr)_4YybVv>(d&P(0uIlp)M zx;p!3=hjFH&bu(<**DSsVpab3+b0Ij+EHOUD_|nye!EjK_6s@KXSFSGm+0AfZr^N^ zEPF3bV7(M|qYFVb(!^keJY_e-M8 zeqM3C)Z*~gnaqAI`;`33?a{-(?JV<_#D#NBB)3)DZ(L?&7vgzo^S}N@Cbr+o>}zhc z*=2>!-2Az2nF+6Xfqfd|M!OhE+s(zMD^1?@r`s>{zh$@o=!#AA+E$quRK?lz`TVt0 zVAnC+dSjKzOZiayvzK`7J3WsYF=nhXncDAd&uuGhZ=R%YTvxEtJ*Q5t zai7x)le$$__BRal?fF9{829~OW+Hyh*nY32nf)BM#m4#1mzrqz=-D^9Slgevzs7ii z_fnJV7qso)9kaDRP`Sp~Drl*R{5x&?j5W6QQ5%;VKU%QVzaP{jH62jd$5D zGl`Kku+KPcX@85M*Z8;2a+BFxP3$#8OznSa6&Uv!t}y9xv$B_-t#AMKtM-;3izl1R zU0!eheMN|EZh*m-XOWXkE?ug(R~3}7HG5~WrSJU&6ZMbv_7h{**@T;$ZwWP@V50P^ z-u|#{w9W6ShFfC4Pc%7sr{3PpiOqJ>ZsjfCzD_miF{roaxxC1>;hn&iFFR(Lh!oe_ z7wZeyp@)Ccl!tr#|GwROE<(rN>%5hH$d!kCg1uhteZENBo}<&+e#R8Rz4D6J_G)aE zv}ZcxW&ioR&fX<5EB1;Qe6*W8Il-Riyz$=Bqy2k#+&O1=)GX6}*F&SdmxWsPPW-sf zE^A|s{r6kkdpDd9-^&_w!p?#_+y36avwH%Rl=g1kcg9XRG|N7xe9@jdOUAv+#LnBf zyvwxLu*leRYQw%g49Bk8RWxVVXHERP``qlHJy-udu>1KY)!uAf&92hB&vtDIcyH$r zkYpdmm11q3_ujfnm&yKOc8vX`-ahLIn&viz+XU^S%Yy8q7Uo*te&uF!p<2m)_8C|E zFBkQ!kL!5aJQXsu_r7Ie|L@6NYth{oY@z}*?Awnz*w5it+Eest*PgN)oc3SlhucfP z3*Yn3_0gW3O-%NWen;C2{y4tp=ONR*xiPQpDt;x|vwr8?n{q2*ugc}ib_c66?2W60 z_6j+7>{Yz;#?DMB$zJ~l-`?AT+xPBi60raOAkh9#{`Wl!Umx!M`B>Fn@rZ*xdiZ;{ z7#jWcpKTPnTV=n&S7-Yt@xn%*+slnU1dHykfA4Q!a)H4pQe&f0z|zzE7#?QXcRROj zJS5v~G$Ar=UtmF{{pW>khI0~Hjfy^}?lUc`v=_HhH?UyZXk_8hvG3sFGW&ZcnvF~* zlo*{q@MvFFTdIBbrHMu&vK>anQUd$`ObfQZ7!YiKbzcq72uJMC^5C?u5t(bGuyBK+oN&ti z?v59B7iM-ENpy-B@xIR9?|$VdB0AT zs(rZPBqN9OO-7gYO6`yN;B7CTqHAaStO%UAo}lqK62&0sTHazD%HO#Z)p&(-4W z!#%2vrt0Y#Jvk@7e}|%<{o9xC4bAV^8!hHh-M?#tvpstFui0<5cfIq= z-S;rsdGCQ~Q}%9X&bK!)TfeX8yV>4S|Ng!6Lu>8NpZ>7-{w?*r@7N~peXyy{er{=j z?ei1bdv{;!-OIvMXa8`=LEE<-273=?H1B26sNW1 z?cSp=l=oH~tF!;^(Y)88BX94fPYiq6QtIr#KH0H%Zg1#bxs3<+JPoh4ul>rlFL z-W#k}_q@7NYCkivXWxvlguM|D`SwMbbJ@3WhU`!KaBPpqYVLhc=5X2zzYp2Ze$37~ zrIcmgLn|?R=J`JRe>hFFsd~Y%Po!DRK46Re{#WYjt&4Vk-ns({FT^zbj3+G@*qOU};Dfy;iMbg=!s+0C{y zjb-iH7I4`Id=0W+Xq;nP{8qv4<`ZFig%%(CtT|q`ZZ67pit=*y7x%i@Pl_GlwtPKOcK;&O?Y~U4wcq$j!8U)5q}@d^b^BS@ZSCjPIoW<>5VMQ_ zByHcX?rz`kINkQfM`k;ZAa?tWzG3zYzh&5-+;G7*c;{2QNtcuCUn%<7Zt`DX%Mx(f z&USyM{hvM)TiM(e+aRvJc6@@l_D>co*w&pav^{y{kXY{^*0%qAuG?L? zlWuQxq1mP&_Kl52!V5dQugUhcv79#bGa77)H@vqC)K0QzGt;*AT)oqJ-D3`W&7cVT zkdmJ^U$^<%X|-F}$1K&f-zu75PZ%@GHMmw`3QTDsGKewAO zdC4CB{wBMyvT*yLrq6aIVYxO3A12!w8oAmhe2}oWZP2x433j$y(4k|0F4@e!>U^;+ zdz7Y~>SqyqM^A5i^zav3_sh_9VULlD7|(uF*D(9{TH6d$*UU2tl49O}^kKC9ZXq_K zI^G^5k2B2s-OHoxUz#-=EnF66BwEY5U#u|7e#>HhqZ7C08y$VeyuUXo+WzJ>9;06( zK}M-TO#AC1V(hK2HySQJQg75Y;nTh;MTz#z>y8?@yKgZ1wCM0Yg~>VgHJca=;|?r0 zGMApPZ~n4UdztVG1?wI%_#f%_I)+4^6V8#y^O?CJB_># zKG?_4l4ieeUZ>IZiP1)JDGd9MRmR%$ZC+&PnbKwS+mUxaLqn*2)A?+p50NcK7rzPa zuka7DXTKn56qglb#C}0=e_U3Oy}Ej~QGsic(Y13L`(;ZV?9Zgf7zrd=8r8mX-p_wR z#eQ{Bk5R%bKSSOc@BK@{r0s1M%rIK!q+qo1Y2f}NeM0sh4LFVV8CDzdSqJSm7ZI|b z6f)0f*~fgN-wK}lixTAQzg*Kb3dzkg`dekT|6aGTJ;N~-qX)CQj5x()_m?Pp*`tSl z@GkMa{x@drO^-6%zdX|1{_1Iwz3XKA_6ADY?XU6BviBBH+H3Nua&N7U*Zv3Zr0xAP z_4htr;kUPUci8@?;av9Le2w>p-I3kv@hxe;_19N+8HpBqnJR_$u4~TQFSBU7T`QBr zUd^q_d+SbD>}R>2VRtFdYOhn7%H9?G>h}MBKi^g;Om%PFR<6D6<@Njbr%LP<-7B*< zE|hhzif;Y>9T)2NUQgEA%cQ5U_iT0je(vi2sr6xn<6knY}dyN~TLnp3y`hx(qq+C0vCr8pn%F(|9q@6W5Sk2f%Eul^SH zy|PQI_U|rp+gJHEYH!^NuDyEGYxnP-@?)-ECn1#ZT5wW|P7GlYX-M zWHuStpJ|b{D?V+oe_@OCzT(pc_Ir29+DWf5*gt8P>^|u=2KF3=ns(Am2K(+$xe2s;`R1RCp+ys8Lwym z*w)D|IZ1E-SzD)liAj3)A(tKP&SdKCH@)n*?^LFqJu9=LolS+_{^v}N`>ZPT>^;|5 z*_A%i+poRGYG3g)J$uE6g?5kUY3={`pm5*gd0O`Ov-9jWz0umgK09yUrZ-ylcXnpj zNoQ&AU$Zk~pLCYC{Yl`)Bed?%U3*V=ovRYM1m|XaB93(0xh2b?m>bakEPm z(%Zj(joZFdAwByknHF~Ec=Y$jW?Jk!&!caT9{vFV>rD4$9&u#1QE@u#uoldoHABTo z-*AoTp3EbTx?feC7Avkc-J5yDaettylZ4PJFgs|Ss#7P^O0b%zTxw2VKP@-ioq5Eu zB3;cX>G3i!o9Bp{(~ZkZ!R+}8>P~J)mVnttwdzh`n-+uFQ*Ws|Dc3JC-IaO7@yHZ) zC*cE2!R#1ybteW!h?!q@syTgjTmiPL+egjmNfX3grTeN**AA}&tKV6u>a?F_jp_c( zBaWdgs!p3-*Mil*nx^8ks14%BW=$2RzT@k`;!=B*ofF1fr>mA*z~Vv{N=}u2o56a0I+UEmlQ)6cJvWq`j+8^( zc0@zjDX(V(SpEMBWhbtM>%nZhlgdt8wyp!azf4laDeBZ(u-=WCDo%gytpT&&?o@GF z@_98loHe*qoxC|#gViTTsXBd;Sp{a#U#03a#c(B9&8=UmPS$QKz-$q3HK#{W%fV^_ zXRA4N<}U-YdtR$KX|+J&^tiRU)8!eEIA!WlcS=|ciPLrW)tzRUECH+6U8nApECEs9 zmZ0vW{%0vz{E?8l(}VlV!0vQ7s^+xxFeI*Ll&d+VFNehSS4}l1&F+<8HNkgOo!;j` z+`Ot!)oFbY#4qfQs!mmAka$o2tm0%L1&Q}POI4hH{DrV3B2=9AJX{Ahr% z6rI8=A$rwLD>@y?+yZvbPIVnMo5-YrT_tG%G^d7$JZX$^5_k*%^*kM;&|d@;{b zcKRa?@z;!R%1+4nTDUL8Zhz(x$8Hk^C&i^|_8_+2Q3a>U2`%=Zyzkbc=p=r1E|~o; zOUY^Bu3mdke&5Ee;&f)Ql|85&*tlQasZx8I9XOAlQg>P?uC^B>uIj1kBz|$$J`h`{ zL&YigE&qNHds2$3)3zK>F#G62HK!-@iuQx_Za$&zw0nIMnEf+V!^!O#M7*tB-AP}~ zVL!-TW?faMePLhrf!wyURmsUa$QaCa>r!w+_DlGtL#Cc4I~>=Dusex;+Hb03w$1Tb zBb(EbsQsql^R_w)b+b98@7inH7q!*#w=uhu!~3nKKOS#(e7}mr>C&%7rZMZ+JLbOQ zatc=IG+q5~rQ?OWyiWhtC7C|VSn7D*StNRa8n<;xt8b%{D%|6F0Z^4TWG)SJ>y zeOnfpdN?0-{NkqMbgk)>X^ZVu$M?TfokWAanx5l%=*Y7{#c6xJnAzkhZyl#Tm3LB} zrDt|=&UeSY$5KxG+bqo-w*PkI(2{Vv#HV34S^Kl&p(1Ig5_3s2k7Q=2_0x@#G<&80&2j5F87G0|Y-a1N zZ#$l77IM0(bj@^b_Cd#kFFBo%!>2RA&z+Y`ii?4Pf!EW+C5VB6g#m;)m>3usKGg5I z!oZLb?CIhdQo;Dxe_(+Fx7_RF`573P8rFxg6z|uve$wxH{1cM`gN2>-GT{LIVwGHb z0p`=(4Ga$iN^1@sxHEqeW6e(16;h^`?mG)G#4K#|n)$h5IuBzRd&dwC~UX3Ax%h@{maqxewqt86Ge71Ie zQ{}AKd)tEX!0fLk`__aWa@~3;WOhcpoz#=Bc}xw<4EAj{-S>CBklrfYl}}m26F^1? zd@Rd#Zu=FkIV~i&N!wt3xw17w2G`MZ*M5B4;ALT_yHb=5qVR$Bn=Ai&XDRggd#^IP zxNpjg>$^D_W*z!hzU|od_RvEgGd|pv_WzN{J~B#ZSM9>k}1?`cG}Fr^ol#R0{iyV4mQ;u&hTN3DJy!nU=IfnnYMLZ76A#W#Di*1n#w zcViL<14EzZ^Vd8FzUVV6Fg$o_ufQCU`ynBw--&@?0^=I9yn{afKiYat7Gx+m$!OGY zmF@C=xmJb-Gj=0}gkSCq3=V7?t|a`LzLwQ# z$;*&8X+rA+#x=$Xzph8KG|Zm;>DP1fSBwP)7WQk5r9`ex*tW?x@^4+@fn4^DXO``g zSiolYCwOz)mR`}azsv8gkgt}V!)wIgV)!@u@S^I=BHKz<-*4nenE0G|Sv?EG>`S{6 z-6j1~87|EA`M;}+A)%}EAtT6b+Z$Ba7-kDOuoc9zFRPDrWia^r_*cB`tvVxy3}1-O zFZ|o$!`K)WH@&>SwTU4ixGDJBLTzS?wHK%R{O4dWQ(gCe3^AYo??ga+nJs=Xk_Q@jm(}aKGHlRfyu6?1!GU83 zK%oTTF)aHpxg%JBVNS{}l^<-st(G&-uBnCK=pc@N*RdPxTMmbfL!FVr70IvB8~ zuYD<>ZnmucvDiEYh8h24pC|mfZo;H5!opxJB(vQw=IrH}ytCMt7#d#6OEO&lZ`6>c z#L%(C;;Z4`_ZuslUdl^4Ffc?s?|l94{!Cu0Njwgd-Amg!8?r9hq%y?(&z7Cl$-rPy z$hfD=fz5$og}GA0>w11hgTITbGt}lWEO04&@k?XwJcd~yjV_GrxkhJ$*$RXk*%nQ% zU`i-p6cL>9@2jdL10zGhyIKEiSs122|FHh8ax2q;Hw^CjdG8s{wxr$OsXjxjfv4eh{oxsAN(>HB zsa938Th8TNX!;_|!cfh}P|h-Ab}B=z3j@P}#7)Y#)rR3XNc_h=gu$4z);Zm=#SaoW;rE>3JwOo1c%RsfBBgh z7*zQg4}9sDyEG>;imlJ4L_jv5QiOviT?W_fL%p4329WNf8 zb!GqsbcO;G14F_ub`}O%77;-?riRz`e^p*8HZU-F2{Je^FdSGa`{Rp!o*XN~0mB}i zg2Vm!>-YWtv$cV@nMZ+PMl1uv_5Tkz8@?%aC_6oFcCcbwFqwma;YR?w^bM`myZ0AQ zZD3&7@$dLa-Uo^e3=gI-S){+$IUwUc$xK#orjdv#@8#m(#>R&qy^%2ngU^SLpV?A! zre^z@GdDs)w@v-HTxaU7*yzp1S67vt{`A|`QU+a)+HYB9Aqo5A7%H$#D4$kA07WJ(x*#VufJSbjQs=}I-vN1h=^eqZ8Zuwe*e zw0iSDvi={#EBhI4m#6=D`~3wU+k*WJ2bOFws(cxzc2+*<(vx|&@<8=w0pAa9&;L>1 z#U0%(lSGR=*cTjUIN)4eII$+M%J$r9{!4!hD^ERSVmMG|T(V!|x1G#U)G`wP_~aea9EP}Ng~taNEVl_V ztmv32vQY5v^J<%+_v5MGuio5#VO7+ zVs$qD$GOjM^w9g@u+U`o|C6Uw9MUZq6d3LXtiAGo%Z9mu!j~udhFz)W`PIG8?f)HV zZyts(9SOa^%0<6hryXG3)-nH!>#Ue*3pFcWMyciJI^;6AIX<@OTy}J0^1{Y8MTP?! zul}jT%)0e2Me{GWw73~p?>m0AgR3r1;bZvHBe7-L?|XfcXO;aDb}!rTurTOtN$&(S}(o-sde}L&-0&4G{ng;G|buhF33I0 z&Hw8RmAQ8~BK7P~J2c)oI7N7iTxf~qEu&YGYxmtr2-0}eb9pB7&V{TWI2mMvG`=5B zU%Ec#|9rvF+$Hu)q1W1ix9YHI9*_RlKLEZ?TFIo!UWwuX1| zf?4jtDKV@J3WzlXTX`kk zJjb)a4cg28-(1vN9jYw-?>y z;=lXq@37Q$LJ-#~(aVOqojQ3n3E;@y{4d%V@C)R{if=I|Wm4~Jge5Apfh z`RQ5v;duS){a&8C>i;KfkNe+LU&+nPa9|q$f@`cBNx6)tB|HW%I{5sBXKw+x9!`|>}Z=s&k zP5Zz8e*345zpmvb=eFP*Z~NX}GI`^#_0?W;&APwaTmPs1@Aov|RZ~*^T_5mYf`Q@G z-t^{^D%uPS{@1(>o~&P8GKcp-MdVBVWy_Mju2`gX^+L@Gw~0G*G=4aPW3wSh?`b{5 zmIwa-zG=^{R^;)QaTjD|C}hj_VUBWM@qdofT%+EboUO-O+`dk`WzWXIu(JIi1H+RC zziK&r84fToFnqbo{D9}?A7+LvZ3;ogH_}#|W17kK!-nbVGU$G+M6Z#Aoj@hpZF^*js= z#~B*b7@q!rsCz?8sj740goTaa z7k3knhvh7WIe)Lp{Mz$zN&No_>y+6Kgv7YS%t{nx_`<`+5W+CSq|qni-*0R0|2;Q8 zS2J9BQDqQZSXf#fn0fXS60I;b*Z zR#&FmIiBE&I}b=nuzJr6oNnVKs&%@*e4*0G@RA!Jw4`!al0NgZH83;mQu-Bo+dhb4 z-;ed;9~fdB_Sv5Pwq--$6$z6S8Lcl~UHgA^+kss?3_kA9JSSCux*E9Gsb*=WaA+F0 zID^CtMu*ldheBR&O#0f-B>v@V+L4gd><4cbb27w#`H&GcW7Q7tqRhyZzh0lxC<;#C zjk(u((pFV-^7P6tHrEutw%-!%@HVLYqEPqdSJQpgv;|w=v%yU?oN@pI)NAd zzBavlp@re=k9TqnpX&b`ul@IZ|8L>V{`X>P-Wka1+w9zK+`KZ%dREkJ#veNl{C!rv zewt=xk?+)N*FUAim?%b_S~TU!S^55F-CiFQ1s*Pv*K_&ye~mrsZQGTVCZVg{bKNga z4(z*F|2(C%H-BGBuceb|ov%gRho<-xO=S$Cv)miu#$$gqrV6QGVi{Z_kV+;un*6%%a zn~nvncV2$=|0?zg$&JO{|J}ZLFaF&uR=MSw_4^M~nWP&v{^tk1e7FAZ_4A;ds5 z(z~P?KCSQmx8nPfYnT4#U7R1e^6zy;rTGiRekU1DReG@^>Sby*-@w!GbKwz&4*8t(72+sm5g$NUWbUmEs5tO-`bel=L1!E}J3 zqh#W>Z?~?mzIf3_cha0)uMCJQvJ=1B!%KcA9^X4s=4Pf_QgbOsb5_>; z8C`qI)f%|o-(y+u=l*ZW9qV?U@zTHCc_C(QTJeir`tfb;-xqJ0qxrWuBKYh~kzJXg z(KZfi@2ohU%<$mN)fGD*9hm<=eSb*m$%O~HA6zoAsS;TK_UNC){G7`Z*OvWh_Kbe@ z+xWb1{mE=T)(!G8e|O6ACy9hO#Xk|Z*(4wL;F8(S%aa)+LjOnX?loh062DjKC2Jaw z(wm#>Z=HWtU!F60>5Kld>kqlE?%u799y0PHj34I2e|GUB`eE$DFiNV9}$L{|x{}!3w6#DWxa>KF5j0_CQ zw`$c6wqAQW>8wzKK&HxC#h;(*&tH3W<(klzx`xOE+XsvpOd+efjks8uUZfjMZfRhA zV7uIP!?xuIzC?98t$J_sVjtrYB?c)TW`}2qoMG~eats+v489BsoHw@`epueg$e?r3 z`u~gVr(KyV7_!#Yymj~~uW`ufh}S&(&nF(2PIxb}D)+!IUrUfZ43n9KIXrJTZvGl; zs(5>mL%+ODcfdBrEld$cKO-BeSMD@g%(Rk&L4x6$mJNd#w=>g$Ck?;UIW_+~zo|D` z_>YmFA&14Ol<@(h#vvwIhE0wM z&r1X@ijb`6oQt^)cIYXY;?RS^383Z1I!@289ekHsu|au4lry_V3?;IA6V%`)8fdCBuWSwt^!eR=Zwl&rgxXTO}G%sA!0bp?YN)5hJ?A89jGp4cqC zh4DvfeEjtP{?ZMLD@EG_AM4CKHF3$!Ly^@1|M@p?#O`0cgr$~2PQ&4Q4$G9kccUev&dRP+(mFw@Yxb!eHC~%g4C^fqaX0+6x7GWDrr4E>PvaeWLf5qTZQqIx76UW=rxf^>O7<}|A z0?+;9o44a-F?)W+znc5|{rgz9yt40GJL6V`e$V&+uk?R8+CM%2x0un4$uRwzfi82v zzxxwRJJcMe__BXs$QD?3U0ioIU-ZSl zt(RF6&bd@Du3cshHVa-E)@uud%&svPs5t1REtLN**U8>5&fb4?Z@V^g zz{>xz+RLJRO#0$J_y7M}Z2zX3)q=->V=t=-V?)RpRUWhdJhM-DnKhK}=9f$O^~GGa z?m_+2!h}g7-JW58K0es^=+fhxY9cmFH@U%32jPg?oUSu|_? z&*}eP@09=G%Ot~=aBGPb^M&^zDWCbDuF^1A5);3l{esViiy@CsoQ|Azf7`{r6}--q z;{L9iZ@uf=B!j)1bbk7q=(z58-MGN}qW-E-596SJ$C*p=nHKz8IDf(fng6Mu&rkRh zo$_b_{{_~q3lf(Ut`W1DxZuOfiU127SkJ|iXWEfUle&kri5W14rK_YbVtR3CcD_#Bu z|2xk7<#{F(gIvOjr~kjMk1Sz`IQD{h#VpTU2A!^19o@@q7X1rn1m%wq@u&3*ByMSE zFuA1lRx|N0ki58H;fh0xR(T!^{GaadQ$A#-Wi>BDnaOp{w&hnoGKgm}Fz_$14AEV2 z^cF+MtdJcRujDhB?zCo!Uhi91pH-yL@aoo?PxcJ6>u)d}S<}cK5Gc%@)p{$7eZep8 zujjdX*)sz73iF>|SD#e!Az{86LxOvwn!_C@*CzHCe`aJ^Ca-eT)l=@6)v@T`P7g-@ z3yZ4U7*?(RzF|u7@8=&*{}-5PRKWDSuI$zymWGIAhE@E%j4K@eZg%?om|<0Vo882` zx*OkE7!rCn{A^cqC}(DfV7j{5ieXjPujPNvpJ!g(HCOd-uB2lqs3l+jqV#9|j|YrO z!N)8Q3cZ;d!4S;tn<4j_uOV;quk_Y5<$$&S-s*gnFPhw6WXWz zzsb}hb5Q8c6zi0ipSSJ*ce*a3n9X5(6gb#fPA^>hEC0`d&UgAveMK&^?o%a$H3I&z zpZd?Avvm=t0P6y2`{`$8=3l*lgG=9mzhNhD^7BN1?YZLH;LiUj=i$lJiFaImRHIaX9rr$J zubY!T<@hn?p2b}%j4$ec%4_`J{4>47x8Xz$;}6Cw_Awpo6`#C5-n^YUbC2F1|3zsR z_Zx4!E3^0(gUPFUk+0k9-T%z}pQ`2{%)oGM-M^VWkB+UZKfu4>-)HaZw>768W|-{M z{Ll9`;_J;jGpfcN>DKz%$ z+=5K0Z|aeMx9_?ybvIwgr@8ZKK#TaN*Nuz?U%!=#7n=RgdFr;nV=F@jU(A9#%m18D zY*=5LH7VD@jA84q^>n^PFnpaqQ*4_@+&#{-$x)e1I+OIh=Ih$j zOJx0=|0u+zmEpk3%kzvKGmOkcsk-=p`c5s*m1in zrCn+cci6sy%9#LR@LxTQ zkC}m?MEigGyq!|nckQ)n_sOJpr%u@_KjFz)SBH~NKYAZMU;WZlQfUrb-xUQ$jsM11 zzpZKSX5Uf45b%Hh|D}(OJog^mANv3JX^UCU4WHVd^Ddm8P-Wu3zWQ@-`u?K)387kM zOh*|#1@67w%$Sh0l%Ih?qa}0UN!7|))(QHPw)idh#?bz`qM>)LZTVwHh6T+|7kWZ==(*>gZP5GMFuiWM?uV`Zr~LnYQ=I-ka_XZAToYE* zFZjd1*?(_3w4S=i&cGmY==plJU7z^1UxZCvk->Dt@g@Hidxqj{t;6R;rQa`qEPc58 z_(ukY2B!s_7w$5}*nFU`u%M zO1|My*Q~aQ$0n}&8F0VQhQWb7fMZR73F9J$_hteAvR6Dy^?ju7EpaxW7|)jc_e5S=Fh7a#6_TmcG<1K*~sx|y-6@X1r1v-#16qTD8o?-=tKZ>fFd z|8qsVeRYVd?^T!5&G!mz7#J1^T=97vp<5O8&wmfE5sxrEzw96jaI9~c&_Qp=kC zy>GG&!-3j^UtRgcRHnwA(`J6qy5bVciz!+X4G&k>A7C!n9+k{cau{q_LHveUQD+uc zd@9mgDdI04cUdv?(S}cKU->H-0xrtTUjENhj^V++1W{4$Rj=Mn^77{{6hG-Gyuf+Y z1xANo%yJ6;R-lM2d8=yVVbXrhEa7lmu?+)5LHvd^pOB+>gCi>${9oyK)E{8ZkPw|d?}S`J;p4}NMFQXDt|{iN`NL@c=;`Y3_j7M$ z_pviDyyL#6b?4~hik&jCB@VkAf@VJ3zIRTh%*~8fpPj!4-O)FL8nt4@tqiGU(@p(q z3Pa>#&o364%qY>29{<<$dCh69J_}{=D5UOp` zw|awu=~@0YQ@$ED9MrD6cjw#tB-46^hTl!*3z!wu*q8hAZ|99)_&W;5netzo_iG+>tBy)-BMe`^3&rwM2M^z#Z31 z4{RE`)z{~nPrAk+BE-cTXp^ZGyT^H30z<`WM&9L7@(dGF+XFwZ(Bjp5%fH6sGK<5< z$@ctWVJr&TGX(1H+5g+&(f3~`{o}6d`vT1*_P@>xE{rv0sPyqH(Oaif=YO+_@xfX) zlR2w0jvZ;b#&%%QigoYSe!2R4s&eV()E}#jC`w za&0`tP@z?txUQ7{!29e~M;1=&u2{;*zu@b?`NtSUk_ufP?OuOx{Tn?krLITnt?%S( zuBI@3n5`)L?-+Xm|1Ca;%@_A;UW%L&u;OV%$E>U(!NU57>$~|F)|*VoS+4$0_^ZA; z+k#(fv~<@pW>_(FJvz>uW30oK!lW7a+`<35Q2YsH)?Vy^_am8y1e-)!mHq0uGJzv1czjR~AfT;?+0p7`_i zcJ_Tmn{KKut~$=3<7~2Gn*ICvwQlbuc|gu+um9<8e^ZL#>Qugl^;Hb(oo3k`ND#3v zP-!S-C6tpT9Jny~FCo%piu= z{QeUSHV##<4x}(y{M#Iy;vk`5TbiK8DDyv3&q#r10%K`{2s`5kuLj-6G7b_7%&!tI z{9t?_aN(FBLt+EZie|@P_6BE%)$R-`j7AIi*v?8b@G-tsV4T2mVu6)G8bchX!~v-y zJ_Y^>s;>@Y{C)eEb&tyRO1-N6t5@wZKigv>wOLpFW23?4M3eTJGr!bMpE+~pdtPH> ztDrS9c6^Iv*p5z0>P|D+vU2z8YinQKyS!ib{R=m_{HtHq{rexR_0=cG+t@btug&Y& ztGo)VT~*7SIKQ|vt-5!QXV0Pr_WQrSUElZ4nMu~+#O~rN4E0(IUcEhgAe(bZy{rSf zMAo5T=5qnUAJUmu&AZ35r^VryIr|14o!gmA|5^@kt@srq@M#m{%l|*le~D){;F|Et zgt6Xl!K>$U53FWgQoo($1;eK~Y6`y&YptlNn#*u$Ki>l86UE;;J^ycDTE+0f{O@aq zMe|hB6*ly}low%e_*L%R5ZJ)8oO4a|FLqXj3ID9!7_Azj(aG7OEeE@^Qo%hR`zfAbo%k<{8z{R}zY6>9Jw_VY{{Q1@Ldf5XS z4tBe1XEl7`KdjH7@b3HkdDZ^^w=utDm~`{4ahT9wN5+WSj^AMydYMWXHuhYW=kWM% z@PmorQC4TL*M-SepwC%5e9+pr43I79F{UN zurj37$~v$!Ft9Qlsg*rYroaI5%5}ybCI$yahQj!yYm5vJOhER1`LJ@qHfF{H3|tH+ zeqE~Pmp!1tz#zhKq_%1SGeZN&ny2-$AQ6G@kw5t!Ok-dOU=aB3T0Fm;g@KEKV`GOy8UB|zOf95O~ z7#RW>Cj6fGuasdsEAs*dgkgGAjIc2ID*)XOrk zGF+5D{oksA50p?r4(tE2o|(bf_dm##MfMAr8@{Y(UcgY0wNqYgx_sZVz7UtdCEsl9 zgS_rGdrS;+dF3~8m-10*yQlfARty)ae}T-mXnnz7|HHoa&$Yesp?UE-$E=TLXopI# zlv!SMMb>p{mr>Uy>*Ylkd3PDxNpXNPga$*$zd26t`lG+e|Gk>@xW@2a9=C(xt(dZg zWYY%`!WsNMObz!g@8<(K@VutW|E149xXpWK>RPJ(J$$9aQKetgKYyv;!@Pi*;qUT# z*#}$ZbMG(ZI$-5i|K#7}qTuIumZV8-R$6M*b#$lC$`|Kc1vBUU3l@CAa6og(|9#dC z&lhb^cR#y=Y3KaVzJJG``YoBW*wgovrfa##%NH?69yzcxRC)a0Tf%VOmH+>Xy4ej( z3cr-U-*21qJXFE8t3zbvxrtG+@*S0`4(trS{O9~FXE@*b+=EfzuVmR5dqwxSIl)Wj z>^{C-ixK2o#lmkB^lioGDYH8Ka(`F9PHjWY0ZA!V2BGJZo;$GzFu2sa{J;HuYyO>` z@BiHe+3Y>%Z@c&T*5#gz0)Hp|zR1Xs{eK>}tOKLKU%|f@85v&QFJ8#3!LZ1_$Ucvo ztuuJdlz;61Q#2VC*)OtpV+2KN04qq+ih*OU_C!rvK`V&!7c(<>{D-iAEoNq5TKeU^ zW-xJB@7R)Y*q%luil)c!*Vf$EW;be z;{pv+wLwnYuh!7d#su=r#NVckGIK@T7#Z3aG#Iwa{uTUd+GrfiJS)IymXN#^B`n`H_M+NBw)b}`=&IKa*b_W6Fb3o*xy&Z$awBw zURNfpu{v5dLAiHZ*T=G*rG>BW^%tcZT$p6^&_@hp=zVtfw|gH?UpzIaBxuQ$zWXeD zG}w+Vk`~#yQhoaWANv2K_dht7&|qxN;=nlJpWt6!mRQ9Cjvi1_`DgT9A0U&cXvKr6fY2(x4*qa_7-s8xT}^D?e*`5(&rtL*mz&N+4L8)P{yFfNFi|3d%c>Ay2LC0H4( z8Wb6(zR>@5`tO<>Zx7u)FTn&BOn=BD#&Gd|nEZ=!g$2wKtO~-f88#TPI(!lTdyu{1 z6+;8x1}0~QRbM^+U)m2UL}hO`IKyVo*!{4f6&{~*2Y&-|kkMOIp$moIr9wq%iYm(p4Jj(-hO3_+S| z4C&T?qkq^}Jee+DXy14AuScrZt;JqXHKsle$z5_W&G4S4*}0Q{C72T21zs>{FkJdC zdGGV)?|tzR%l@abd$>xzk7Gb2imH2{tg)EkgQSsF!*YMd3ID>+oNd1^HrK>{>CeR_ zHEI*488?PJSvD``-(!XV=7fTOXTI=XJ#cCN?Ara`daXCl_GeGvSisisg};7UR>I5p zU;Ga20n87!c>LF3xU|3A?gC@P@!!piA`CD8>*)PwmSAmoTEAk+|9^}3f8lRq$YN0V zyZ(qS7d@t5s?_^lYS7}g~GVi#t3Deu6`@bW&$&^Cs9^Q{^b8-6!C z{&HvB@FD-FdflbH#UEj}UHFIBv1d)dG3{(FFGPGH;L@fJ%=gA$H z;OEQg9vuJo5>#_V{bT20yuvWypQ$-(g2z4E@9xH@-v;^@+fM$+C=2qIJZpl1b3^63 z^{*?h%`Z8=#+I+R_J-|>-NzXlq!@Tw^qI{VPwe#mAN#^SBaOYX>Vgmdr<_6=y*~MW z@Bc6M|G)h|_v!x)iVac>)BYPWTHJPSi1D9&GOqf`%Q)k^=P&<_ep$cq&wh(#7v(@9 zyn^wDJ0I79nP$5`KKb%0dGp=nvzxQerfiS?JzrK%^-$4~zd>C~a3Nl9_8garQThUE15{nOy!`_5aqBPlvJRJMZ!rbD zkAJJiu(`SN%l@gqi>pnx_uZMd|L|W^vW5!_t+zrgv#|eYz>D zz}mpKfQ?~Kfk?x%2gf?U)QkMu{h0N3yYc_~`OkLR2bKHn`<89XnAM<`AaD7_i}A;! z{J&50f8N<&qy6RlqLtGx{%`gAufFZqlRwXwy#4*|{?vbr&J4_q46F}I&U{;^mw))I zb|>JOQSf9wIw3~Z4MMeCH0M?I-~DR00M zz|0`haKe(Igy9OqwG?Si4TiV6+pcX3PyZtj%|3*oM&6)-ZvnHxkzAD%e^**B zf4ApPVz~+{0|Tf&U`v?!Dfr^t#V_P^&UeqxbWLG>(8J6i%g~e8HRY7jsiewz_8u#D zl*WB)yb;Q9&WOR8p@bnJJ0z#)(hi@+KLe*`-eeSe{`fKj>jNHUkZT&Q@2S|cIWQ;e z=#E*-|0iGE?@^fZcE9Lb!S|~~8;mPKPHEs{__KZf$4~0(&d-uL-TQB)=-uY0mb;3( zBK~b%&%n^YcOdevd!PEdrQ)k9{I{&W_x9FyCWZ#Z20n%jhd{0dH6H#4GR$KKt=AP{ zC}&_!;9y9AC~2^6ur2)dUxR_ciouHE0Qcfe|JfZt1-?jwF(at`&A`KGz`}5cVF3ff z3x*dA5BL(a%t3Z4xHo}JV6bAi@qaM`!vbc81q?U-GcN#{ZI-7A5-G^)60uZz-f;Ea z|I4~f_sjpUV=DN~z{7ZfvEt&vuX7e8rnbKWxeR+ z+5?~lIs+)`nLqBEer&Va_TyXL^__h4!Xl?X^Rn%`Uky?W_4~5Ee*e#~fcXVO&5PA$ zuhhhx8zQeW?s`#gaQ64)wERnVEHc);zkdDO>)GvRx13{4FaO`q$-rRMz<1#P&tGfj zES@RfEmg3FSw^&Bwe-;)UcU3Tnkt;r3t(ViI5nlH%Sh?@iPSTv9bWx%nEZO#98>q% zP2ZOL&i+^bzw>arob`_0tM}`_x8D=p!RWwfarCb}g9OuuYx65#l&=4O;eqXWQO##T zHql+ecHe5Z|G#_Or7|o5Vm*W9^Z9kB*YACKR$g*V+z(?G2gVJ5_!lr2oO-!GbJnhP z^)J}}|4grW7SGQ%U;6+H1H+R4FH5Q_Dt>&8|1TW>_v(C+hQIcES6>0O0jfIwZNB;D z!GnVG^6$UCzCItbx9sW6)sFw~aNU{Sz59Cc8f{?)h7tzW1?yfnH#fh&o*%RG)0tp@ z+rLkO{q4VgdAk3b`Mw9a|KIFxsuLGm`|q2w=)|HYFP_L~FuZ1EIQ@U}$&~W^_pi2Q z`^WG5lM>EwYyWoRhV1n_zUS}ze6e0if{Ewc3Y}SZy54!bwfugQC2Rp>+1Ic8ewVk$ zGx%LAVc=mDX}FoQZTtTEudlW)pSSDJ5n+GZi%0)!pSLOg`m0xZ_wMSe$Jo#C)tgVy zZcD9>x#DYLsejJb&%Jhm@C;D0;R(BJ@|&GK_gDR=lgs7m|8yRI{;_`MzuW(>KYaMG z%V-Mzwh(MvfKW%e}Dh>?e+!xnSSY;BWwg>Dx-*}aoSPi^eMer=0tSW!oIJ<$|DRfK z`(yL}7qagwz8pI{`|`^#DPP|2XO8%{{nzd0@H?SbEzNz`6`%S3r{sC6@Qf=z3ub*^ ze)eqhvs-n0t8cLUU3KPVoC3ovhW{7qf5jgyzRbwO*!Id)U+$?)WubUYdDqdMCwIO) z7kK{kfrmQVSs#3#Z&CANBlGWiABJ-_489Hf{~VP6EB^mc_ATjp^~s*G`q%zFU;e!8 z{b~M35~u&)*<1bh)w$M0`)2vy`)>b#m)sS$epPV&EXE5gF8^ozK5YNz@!GX(7ilOd z$#Xt9AJb``Z^&qIn8AecWqoFS{eF$EDM4ROeER?S=HAP#e!Clf)v$#xVEgmnwwz_9 zY6yeh^Gr4e;R*ky&srA9@W6Hzj8GC1U$FkY;GX?yoq^2Zx%56nCG)WP9J zI0M54mN5Ij_xa}kfBZOp$^Y9c7;V+-SP%S@XYg$}_x}I2^(C?k*dHxcY}nmW?fr*~ zfnipI(FOYp_xr9lyb~%}Ru>KGn1%VL{*-4(W^`uwUC+Z9HYdA}6QqzY;cvwUo7zkJ znHUamnKw?(zhUJtahLK|_mbz2KW%ikeDqY`mghz57yqRzzjHbmO8lAqYZLPv>Emvq zi$ASk)+w$(_r9)A$MM_#|Hs!J_&fQZF9X8`fwtf4{wM1DONTD$P_utN@pkc<^Og>k zlmAr*&wV$Um*LgH=zV*BE$4q;e)q(6{-k=T_RTY{8D{TVeD3bWITp)=o_v1(*L2&;K_cKML>ekDncTH@{5%XM)tqK0je~*}iYgQ_NrP*S~5o z%ZfqEak@m<;@&gs?CZXtdm;KgXK6{q)XiDz^@8=5S-O_E3m<_m)a#Mv;S%tIK4qX+y?rm?`^Tdzg{M;}1XP^2f&v2z7 z_{87iPi4-o@!1$Uwe&h;S0#IgE4#;Mz7Ho->|faKV82xVet+!uyZfuRaXb9xwkVcm zU@%><{7(HI2A9c;|jqp0_eEoaNi5K$~8*=Tf4s2q0!N9PBaruPb z{iiKmgI#*MZ>$U2Z1}%3#^p$J|6QI7cizSPy3V+Yfx$Fk=5K%BzB@}qQo9NxbNYiO z@8^-z2bv&(hHe}C%>Og}U#&D$aB@!!fp)Z6O7OXh|-i+)a*-ytW#w1(|v zJo}18i<$QXFg*BQ{{QTQvYm_%-rap2UamK%_ly3o-%17y3)+|3fl^}5FLRa`TNxyn z7#hChD^ED5_ILh5z5rKub_Rx*`c}|)drQnuNi8^7-Sh3mel`R&-n7% z{Yi7}tsMTdI*F-wtoS#ot)+KkjZLCur->rTY1qLA*DlM5Py-=v~gJ z3rUSCYdHGzhslETOdq!9Tgh9xr@Y*6Uj9rD;&gL{FJa7apC5fZ=e99Y^l{d_fBmli zm5y%Q`af)o`<~T(`<4{VnQc|HcMaoV@BexVp(P~@3={rUFPdgkSbObBMBW$wwV*cJ z#ks*pKCS=z;;4Duv+P+n9j{EjW7=0W@Bilym-cgeh=Kz1zkh#R)xxNQ)-Lp@8DytQ__A51xSs$&i_WxcKy#6ZdlCC~bl-s|4k$&$}_r)t0&lK67-t2jsW!B5O z;vKh38}@2HJ*(cG{d}3LY3{3a3_O{a>jOm=ul<(Mm1X%z;uGtUWKj%CeZ zkd0u^u9Jkv(D~r$eA@X+zbtpo!CWH~76RS_sj$hGBO@Ny8MS zpq)4V8^31=UGnI~Yk^O1<5fjK`QYV!UWPSlvIUvsxV0(RP0H|>< z9`SO1XbQ&y<|Sb>yIzH{Yba0ETq?7+w_OxZ;G-oyqy2pmISQ!=mGK1wh{ZId%>^(BtRjZxw6 zV&(>>1=0*V{F?X}xEk^pKq3#Wwt&Pqv|lhZFg?%>wvG7u;87>@OLozce}T*nj0`Cjxr{I6O%JT*VP%-`)1>9!N!1^p zpK&pBF>ILi{_?4YFZ^swaTyv64Mq(COj!&X3`@X(iUwgNm1tgo*a9xV)fR)3q z{lT&hk`6Kl=le_-6k&KV`$awGn6eQ7W|F@vN)DQQhb zz&A_91#A_8iy0bT>|ers!{GCspAHrbrU$rXSQ$W*n$8nA9e6)@xif-hgf0lUFhelJlyJUZgfgyx(@1%dci~($*`ORPK_bu2Om>OQ_|CMH1z{#+HVZ*8=^%qze0vKL2 zf(0{}7~+2)n_IE%_q+SN0SpuVwX^8Un=+{Ud;U@W0y{{+kR^aQfkEZp?O*G)nL`*C z+20UnaaQ>#&9{I-;cqfWf&v4x8ie<&S&G5q&nX5jaEbAal~HK_T&MIYObsviB{&+6 z)yHK-BRBE zd|9=CtL45gb%kz;3JgN~A2u*CT(Ym`|9>a&#rdBaugeSfpSx>#`m4$H$u`zG%YL6t z*?zA&?f=F2zuo_j>9b@pc>Iyz1I-aOo1Zwd1vIFx_ftOly?q!%+G(Z@*JbW?blCry zZ)c};E{@lMm!b21fdeDM%lUuZ>nx)z-PQHwo(mf{-nkNM8!_v8gYh-S0A`0r<}v{c z4!_Dp^UA*-d27T45;|Vs!07NL{lygqQwEhf9(ECiCG`Q!ZC{w;TlpA-_NNC6gC<=A znIm=wGIac|xjXy(@z2@ciKTe>T+r?}P z*c5&l|6rPMDo`r7?)d%>&-8!ozb6C=yD$IkR*e!CB=*Vi6)X9Y!T7K5Fx$i?{& zUvM3;=-qzmEcerEu}7b^CheKLsy8HLVi)`UUjZ&fmO%^xe*>8%PH8Z_lna5w9 z?JxJ=*|mE%L&@p?k3C$=T{fvKWcYB%wZ3Qp*o&9fhlJ!l(l{<8k}yQI&5ihkNF z?G)2wn3MNQU4HK8jmPgLT?M3Fw>VFlv~ z#*TkqbV8-Co?BY<+%=c?McM!G$B$>%=Y4lt!l3Z?@|B%4w;q4wSpKf4zIG3r1_Q|K zMfQKSk40Z?ogVr;J|^dk`Tr$GN7a{r^peqKBp9{xOT(yFr_no2vlG#U1UU!4Efy?(3Zo{6tdCOxz-n*7=5 z_53^E=kL9{it)!KP=_UCZvDw0m$GmDwV%kA$AR>9y7Nt8Q4#Usb5J%4Gja zjipLKQ8Jp(_!n943RZc)Da&Dg50k*(#NW05y>2t=xPh|3a#4-loDR_pT_3|%nFU$; zrIub{=`vdSXa#?Xd(@o0`&TipVB9PC_u&@3AM2b#6@Ha3`LBFeY{APotyLD&{_QTd zy2d!|cw}{YD02XFK_k=R2CWJImi|va{ki|I=UJ2U!T(O)nI9Bo^I_g9wgOMRc+N8_g= zZ!M$TWfh8+T$@=X46;bz??Hzk#tHw99(k_nK5xEq>C^{dk|*xjU1iwA`1n@qR1Q{# zi}eLB|L>@IJ!NmwkoN(P{vpL*&8sIc zDg1g|D`*{!RYxFCVVR>hR_GC;Kc0H^xi$JGej-*O#C?z0G$` z!+1f90YGN;FfFOyAhD3)#9xp9ptKHEz5fe;7DE|}=l=&c$v*$y6rdV_-w9 z14yjMegT^VA9&iAN#R%YKX%gtbD7;38?^hG6ux`^U%>XmL~$|0?gj_;00z+9$(4p+ zzO7jYUNO&~zJNJo(SL51m-0T$Z#bB$Kx-U|K#ptROAtvA7kI(I)o@4uZ?hC=3YkIA zV(N?jFZ{2gn0J-DJNKYenpJ|SfiK|XUxwGg%sot37#!GFJgK{u{!{)6gY1Dmg#$~M z3H_b;&yn{6X~k2W>m>ObxOxyfKL11Jb$)3~Mg6n};m22hH3`u-;&0dB-^6-^72352iUY$R@0H zV|-x7AiH4Fzlr}ERkyS7)QK?cSQT=~-oc-TF^7E^^z#)g^Z0LY z0>t0U1)50uz`2m&Z%nAx%lV?7{~P!oa5wAzZ~om-4K_i0(m%!$h6cHHT2sIDf8k$q zLcoE2!yo=H1)(dK)Gw(&px*L|;WcwfgV!(jU+jK-jBQq27Z?xZGFUmN{$0<*P||Qa z{Xc)fF*OFzxXA$l2X=-Rj;ep>w|wEZYKUfPyTz#UpBZfO4ZbDJpy~B~(9|(#q0l?# zFb0qn312}A!oK}yu&v>50J))!!Hw}5Ljxz6^MYaTnulNa|KZnQxMUBS!znm+$$kfK zgV(R)pX?t@V*pLVyZ>UZl4X)$-SJoa#dD@0&;K6(8~8TZy_5$B7~^)<)s>7O?U(Ee zYB&}!NBm>|&Zy0B$^Mc(Lj#k-U+@17iVUlF{mK8&zoRDvBz!^G__?UZe}+(o0|(j| zc6Lrt3YydKw0?oqB_p0`{~2W;9Q<8xThtfUHCgt+C;J`zGr*zKwq&LHN{wKxMb?*g z_cDPN3oNMzP5Az-ZuW)oBK|F#>DXJ zs?5EPMLw>guBETl9u!uKbk97HQGAhQSMuW+$g-BM@1U7w!HqxCOP??5d8$4^FW=fv z)9UU|(Ckm6&j02w`Ai??-v7zJ>~iKrE7!mm4AcHIIycPoUH30DitSzHk2toEi`iW# zUJ7(L?`ymB&+(6O*59Z9|M%lk_NveNn%nioq@V9DyLh)|j|Ow7Na~VLk*T0&Z6L$H z-T&WNmzS4!@4O;c-1vq6i-%~Y+U|?Ho6BuOnp#$+Bzj@H2qf zqwW5W37a#l4_rLnuh$pIaOpn-*8%DKUrf*26q^=pdA9n$You7}#XyE7^$n#HUVGLW zWUK8yEzKXaH8A9^rSAF9zbEPbKfKbtzMSEEEQ8&v#rBVn_0IOa{6uYgP?sy?ic@`x z4PW>rnAUXPd1Cc^ncr6v(e}(;^ZREV*tl4RUE%Nimz)RUf1O@$Z((s_XXGhM_Y&C! zv!a)SG$n*um;b+heoZ01NFndYXm(=?oC*0StIQ%l6vEu6L|JO>a&KBQg zcrc?w<8+aUROsTsK#@j>g?hir7dKp4k|vfpDb00B(Z`z$80VCI+5Ug|ex?tXrvJaX zYn`(E^^#Z1*1dLRU$H7HIXO8bv=KBPpB=$m)HS8(l%}cW^_7~S2(Ewia{qFsf|siD z+dF<7*L}`V8hid(QQz6KXN#?^84pP1AAPBHaMrV1GL;{Tf69@TGngSkp&W z`OB$)J1WZ9E$rB5T-|)Kq^h9e#=Q5nSG7T_2fPXviLN=Xp-^-x({vsOs8+tM!La$J zj%={bx%xH{{^Rz)pWA<5|L668@azZ6CHn)vwl&FEGQ9jRa=Csz>w^y;4CXoK-Mz(X zGSlz-_wVcP?+_HM|JiIG#XjL5s%8OZEP&4<0=DaJQ(wJnmnvVtLZbE7lB`>=%eW*v|bj{@44r zat+UY{{QsQdC34OmR{6%z1;twso?s~<$CdZf2?7eFkkgq3BybI1^jso3?K~;s~MJE ze))0F{kdY#Rb?H1u^;#+KjB}s$N#?~4Uw_>pZ|5f9}81XZ|}M zz!*{1P;R$z>Lr`k+ubLgQVLBq)H?lf#T}V&>u70l{ha-eRK@Kd=PtFVlxb)p_^!R9;`9WiIxz{&Uzb`~5#3 z?KX?Ay8hx)*=Aw$%lEF{e0N!W@mhOBA$taeU#I`3uV5%SH+T26S>pM!-v7VPxm|Iw z^<($>>EClqpLZS3sxp?3JA1j=;-G`W3-$w_>@V%VQ@@SNL0#N`?(M45>HoHy>&=sn zx3b?=vTnzYo6G*6+;Pu)GiWKw>`0xtLA(OH85x$;FWmp1=|bhFW6JBRF0#kok-S^H zZddy99o361!>>vIT(F`%dDr~cnNMWSzx?){_2gfMgrD*k^=|G2#VW&N)y`)#t+Qs*s66FO^B zBs}qPiyRwMkv&7X&BWhY3@-Hx>u<0w*c=(J{YmF(r1;-ryLtbrS2HfMXPEZi@z;CJ z@7fIi5Bb}D+?v1d_qWUc-@fM-`U^^d`-=B7UD)|vH+=uM-sgGNfA1f2aCip_J&*r; z+v`{#%=rCo|IO1!J-)CrO!ybB@LikXGv9{Wr3?%O@*gft`!D#nwGK3Y!!Y6BQwZbq ze~p{cH4}LemwSZI>?Pmh5=PnOj@_)1JFHweYZH5bs z0)L;@u^zYzTI;!_erG%*1H*U5*9>=FezD*A=fjUnzd8TvggD2pV_+y|xUuW|;=F(V z&iCo>RrBY+lo9-HdFaj%#s6 z&RChelzpW}_s>c7d+WE}+dXMH`%anVN=j3U_A?o*dCJ9Lz}_$=C~#?!$j(f)>az!X z({@dFi~gK+VJgE;uo(=p4USL$Yn%$1VrgDkcEP7?_RG3Jf2E~UR(p892xo{{#js#{ zti!#CmyTW&yF#YCwJe(a+SAzj#O1#>)^F;Jo_km-o&3wiz>vUqz@UURp>9bf(tX|H znX;k{H^cJMRz}=mpQAkK4%DWCvWfGqGDhuu*_S7NVaaQTuZiC+u4^vu2znRJ5VM>i zfnj&Up6#<3j(p@ia8Yl8E8`5`B4g`cUJvFdgTnR#BSS*KzdP3qx0J{AE&uNq&X5$z zaI4t%Y^v-^pVVo;ML|;sCM}b{v~QmAZ+djYr#~xp-??Af;JGe+=ghtTCjWO^07@kn z?&~T1b=>_T@xOn19K$TNXRHq<|F8d_w19zy;lPL6uK$0%H+$*Aeq!S8$K3zcvp*7B zQB%Ok(2&;*PE4^54Ir8ULaw>u%lh~HEbz3%2JVi3LjOOM zvS|1xyx;DC05@n-CDy^?&o72%J;ViV z4NtpsGsMLi1b%&G6k(7(aGH}rrLLBNHQ^@XwbgOeqKr3KTaK*f-yp{7z#g%$Yfl}6 z!wdNX`3npdGrVA!#lYb4r;S;I!K#5LMy!ZdT z>89=GL0czwX)RS^cYd-u#24g;CG~Z$cGp*Y`XawI`@f)NuUW8VR|tz;Q8?oTMh1sp z^7Gj1-pHF?Zch5_w6QeYMdb0@kY3S-g@#<+|RjdtIuG) z@|KUQBu}dpI1WAjFZzEwIZy73``!EI=caaZ9ysDSI!V` z{OGr{GTbFA+aa1Q$dXIql!gPy4HN#k{$FbHo?)d#?$fi}cU=;GC+#dP*E-I~yowPt zE7b5s|CjuG2G><)U2}FbZ75!8+jTK*iHIdTPpbO_Pyzt;FuXOVh6>IO+`{_6_3F>n zM}Ne4xt=RMP~ZkPL4T>z)Wu3?xeui5zq8L;bn%@l$mZ)W^;ntB7+vn3w~AX|->hub zO~(Tl%2+hP@v#5P{wce5H(uT;p1Z(xqOct4jxf)#4^3;ryqh2H-Y+@Zm|KHq{W^e-Z!d2+07T!33z_J0!u2@+A#g z7FWwfd>I_xP5-wr-l_pKp04n{`yXhyVirTgo&GQURt}fRFT3Wy0JtxB~20iU<>lDAQw|OZaz+l4YvPkaV@ls}x^#KeQ zSf2FUzJ2@p=lui;}v|NQLX+=!KjFC2I;bZLJ-1CwyW)7eYkSVWv&p8xa4=M%G*+`F33vB?fJ^97nB zT;ugi{+7&vx_w-mfXXBL{LRg8`!j^Gkct zz>t+v;)~BFB|mrnKmC7N$;Vo|hu-$~75_jUU*%SRUMDT_7X6c&*;A{5kp74pO;G zvy{7D9b~UF?pm}r&+9(}!wd!QM5l?$zJF&W(Qd#WM&)ab9iZZ;?$L32>)#iuK@c0K+7(QjvI_)XD<;><0TTmJ07 z;?6q(G(q^Ck=gc%d~`$CCf`4~@AS97)7$ng>dk-4eLt7~mjcK24n~Hm;I((vkBNkq z|9=0hwdnV}GNuc<|EFL5_~m{$#FPfPL;ai%mRe@#wx9n0^xV>IY+LMmLXKTpkln!l zi-lo9)MlBRq76mAlS<#YzGYb;@!loSZArwdg=`-GZNDWjF!(SWyZUo_$n*HHyt`9R zUHtgP{)f~D-}&DezrLHAwkcbTtwEY0A$PL>*0$Ro$EM%QFZp(2gTUH#|cSASPeoE;K!%Yfm4)$w_! zVwW_(XR!Zp|IhEQ_okk(EGo{v9{eqdfx&<=p+WY6`o53RX}Q1hb-5f&`=;zV&cLwd z>8^Cs2T$u|A2iBWZLr%Tsafi-zWid?5~U)!D*_A*cNlrp7_1I7=l@(9oIaJ@snqbkobtG5$q&R~%*7!N_nf<(47i1xCLm|5Mpt^c{^`5EAmZ z`d)h3=abtQOeWur@!zWj3in@;|E@DudHnbO%ongMWXj_1?|EnW7O$NBclG4M(u@ti z8yHy^$Xhw^zxxTbJB#Ib++UF+HZbW0f)Fjv&KWF?&bf62ZLw4^$aVN)+>!(96p5KhUe zx@rGo)0fsWlrYFLRK?ygVchWT{Vui!z65K55L=!9yZ5Z~_;p-QfkF1bB*{&_Tj%k{ z{bC2L%TIV9!eCt=bB^HxV-EWvfdyPuasS>c{$+09OL)s8!jKJF?=8U;;+TK>{| z{z~Ooz_4Q*Q^R-7#S8%qzheKre|YOv5UT_KxlhNNUol89X)s(1-(%*-+#t1p^9J9M zTYd~NjHL_=d-%1O-5A&Wa!MEdG7VIE^stsN7%(o_&iCLGOM_a1wLlv~=!M6h_FFPA z%wo89%YYG7#(ZaF-Vy4+-Y{>GpXd$lC#zT*Ha5I3>%_!*)gnus=R9`EPBzzvE*0 zFLQPVhV5Jt{fAjVt+QY9+%FhFvA}=&|LTj3F@+2lSaR5#v<%o87^GXSrHM2sI)FlS zJ@XEJ35H}wSq5QnoyXvN02J`Q-ZO+rFQ zR~`R>$@zct&(%Me?I!+S*Q_ka&}(JKlyhOAQv5)Kf)CAH zf7xHg`ryIFczw6q(d&PmxM;gxZ~Hqvx9F8Ck|LSIZ2rCml_?IwCoGF5&%XKQ+2qTs z`?n@81FyQ{sHl5c|CZ}O&i79TAMclSy?JHw#k=cQZF{eI%zCBF@uZc|^-L);KK*sc zt$iUmbF@K|%7Hp=jG3yJLD4M1{Y3BY^~-6yuFKrXP^+FeJESit@aY|wbByYj|L+oS zSeD0^zeQGI>f;U(U)ir~a?&oAHk=LVTci>HyN$nJbO|#nEF}0{%iQLtV@gx2O<`D|6gl$UhVUj`U$Ty&3RAw9$Cb&T} z;S7&f*qTqiyN*F5b;+aR|DXSB-|OX@5bc|{?CisLUuL@J|2gN+&QP#?mcu#2`I|Mt+IBWxv1v zyZUmf`#1UDTfb?G>`7pFz?Umaf3@@gu6(s#Xf01Q@HbeJc`}6Y{Kzl%$KKy^VZ~i_(Z>s~$`vtr8 z#b(N0X*Yj;_w?o0?`OqS9{=)b{+5^fE%y|*?~4!k#eRToVf!w&3nty`8BTuqE;s-DRR8Tb1H-!o<~6VGckTr325erj{G!Rk z&nGz>em5MQbX${Q^-abj`{efgrFCzW48IyQfEY&eWa$e`!5K!&VKD#(QgLfAbdF_s#dYviE-mhU_qgX|fJWq7Se4 z+Q81kkRZ!_U=y=P(d)FIdqC2M1HMjSU1|;*)@F!cyqcBfxNvR#J62F%pz3r}(=0xP zzsw9@7QQm(K9$b=f?=L1L&H{WhSNG4AJ?;5?ECvP!22WQ%mvv4FO#uDCtIYra literal 0 HcmV?d00001 diff --git a/orx-dnk3/README.md b/orx-dnk3/README.md index 06e793a5..56f7da49 100644 --- a/orx-dnk3/README.md +++ b/orx-dnk3/README.md @@ -12,10 +12,10 @@ Supported Gltf features - [x] Basic materials - [x] Normal maps - [x] Metallic/roughness maps - - [ ] Skinning + - [x] Skinning - [x] Double-sided materials - [ ] Transparency -- [ ] Animations +- [x] Animations - [ ] Cameras - [ ] Lights diff --git a/orx-dnk3/build.gradle b/orx-dnk3/build.gradle index ba8a852a..82a9d5a5 100644 --- a/orx-dnk3/build.gradle +++ b/orx-dnk3/build.gradle @@ -12,9 +12,11 @@ dependencies { implementation "com.google.code.gson:gson:$gsonVersion" implementation(project(":orx-fx")) implementation(project(":orx-keyframer")) + demoImplementation(project(":orx-camera")) demoImplementation("org.openrndr:openrndr-core:$openrndrVersion") demoImplementation("org.openrndr:openrndr-extensions:$openrndrVersion") + demoImplementation("org.openrndr:openrndr-ffmpeg:$openrndrVersion") demoRuntimeOnly("org.openrndr:openrndr-gl3:$openrndrVersion") demoRuntimeOnly("org.openrndr:openrndr-gl3-natives-$openrndrOS:$openrndrVersion") demoImplementation(sourceSets.getByName("main").output) diff --git a/orx-dnk3/src/demo/kotlin/DemoScene02.kt b/orx-dnk3/src/demo/kotlin/DemoScene02.kt index a589b042..73659c8f 100644 --- a/orx-dnk3/src/demo/kotlin/DemoScene02.kt +++ b/orx-dnk3/src/demo/kotlin/DemoScene02.kt @@ -25,7 +25,7 @@ fun main() = application { } } - val gltf = loadGltfFromFile(File("demo-data/gltf-models/complex02/scene.gltf")) + val gltf = loadGltfFromFile(File("demo-data/gltf-models/duck/Duck.gltf")) // val gltf = loadGltfFromGlbFile(File("demo-data/gltf-models/splash-sss.glb")) val scene = Scene(SceneNode()) @@ -48,8 +48,8 @@ fun main() = application { val renderer = dryRenderer() extend(Orbital()) { far = 500.0 - lookAt = Vector3(0.0, 0.7, 0.0) - eye = Vector3(3.0, 0.7, -2.0) + lookAt = Vector3(0.0, 0.8, 0.0) + eye = Vector3(3.0, 0.8, -2.0) fov = 30.0 } extend { diff --git a/orx-dnk3/src/demo/kotlin/DemoSkinning01.kt b/orx-dnk3/src/demo/kotlin/DemoSkinning01.kt new file mode 100644 index 00000000..d45e9169 --- /dev/null +++ b/orx-dnk3/src/demo/kotlin/DemoSkinning01.kt @@ -0,0 +1,52 @@ +import org.openrndr.application +import org.openrndr.color.ColorRGBa +import org.openrndr.extensions.SingleScreenshot +import org.openrndr.extra.dnk3.* +import org.openrndr.extra.dnk3.gltf.buildSceneNodes +import org.openrndr.extra.dnk3.gltf.loadGltfFromFile +import org.openrndr.extras.camera.Orbital +import org.openrndr.math.Vector3 +import org.openrndr.math.mod_ +import java.io.File + +fun main() = application { + configure { + width = 1280 + height = 720 + //multisample = WindowMultisample.SampleCount(8) + } + + program { + if (System.getProperty("takeScreenshot") == "true") { + extend(SingleScreenshot()) { + this.outputFile = System.getProperty("screenshotPath") + } + } + + val gltf = loadGltfFromFile(File("demo-data/gltf-models/fox/Fox.glb")) + val scene = Scene(SceneNode()) + + scene.root.entities.add(HemisphereLight().apply { + upColor = ColorRGBa.WHITE.shade(0.4) + downColor = ColorRGBa.GRAY.shade(0.1) + }) + val sceneData = gltf.buildSceneNodes() + scene.root.children.addAll(sceneData.scenes.first()) + + + // -- create a renderer + val renderer = dryRenderer() + extend(Orbital()) { + far = 500.0 + lookAt = Vector3(0.0, 40.0, 0.0) + eye = Vector3(150.0, 40.0, 200.0) + fov = 40.0 + } + + extend { + sceneData.animations[2].applyToTargets(seconds.mod_(sceneData.animations[2].duration)) + drawer.clear(ColorRGBa.PINK) + renderer.draw(drawer, scene) + } + } +} \ No newline at end of file diff --git a/orx-dnk3/src/main/kotlin/Entity.kt b/orx-dnk3/src/main/kotlin/Entity.kt index f8a4d1cf..11cdbecd 100644 --- a/orx-dnk3/src/main/kotlin/Entity.kt +++ b/orx-dnk3/src/main/kotlin/Entity.kt @@ -2,24 +2,47 @@ package org.openrndr.extra.dnk3 import org.openrndr.color.ColorRGBa import org.openrndr.draw.* +import org.openrndr.math.Matrix44 class Geometry(val vertexBuffers: List, val indexBuffer: IndexBuffer?, val primitive: DrawPrimitive, val offset: Int, - val vertexCount: Int) + val vertexCount: Int) { + + override fun toString(): String { + return "Geometry(vertexBuffers: $vertexBuffers, indexBuffers: $indexBuffer, primitive: $primitive, offset: $offset, vertexCount: $vertexCount)" + } + +} val DummyGeometry = Geometry(emptyList(), null, DrawPrimitive.TRIANGLES, 0, 0) sealed class Entity -class MeshPrimitive(var geometry: Geometry, var material: Material) +class MeshPrimitive(var geometry: Geometry, var material: Material) { + + override fun toString(): String { + return "MeshPrimitive(geometry: $geometry, material: $material)" + } + +} class MeshPrimitiveInstance(val primitive: MeshPrimitive, val instances: Int, val attributes: List) abstract class MeshBase(var primitives: List) : Entity() -class Mesh(primitives: List) : MeshBase(primitives) +class Mesh(primitives: List) : MeshBase(primitives) { + override fun toString(): String { + return "Mesh(primitives: $primitives)" + } +} + +class SkinnedMesh(primitives: List, + val joints: List, + val skeleton: SceneNode, + val inverseBindMatrices: List +) : MeshBase(primitives) class InstancedMesh(primitives: List, var instances: Int, diff --git a/orx-dnk3/src/main/kotlin/Facet.kt b/orx-dnk3/src/main/kotlin/Facet.kt index f4519eab..197cb717 100644 --- a/orx-dnk3/src/main/kotlin/Facet.kt +++ b/orx-dnk3/src/main/kotlin/Facet.kt @@ -113,10 +113,9 @@ class ClipPositionFacet : ColorBufferFacetCombiner(setOf(FacetType.CLIP_POSITION class LDRColorFacet : ColorBufferFacetCombiner(setOf(FacetType.DIFFUSE, FacetType.SPECULAR), "color", ColorFormat.RGBa, ColorType.UINT8) { override fun generateShader() = """ - vec3 oofinalColor = (f_diffuse.rgb + f_specular.rgb + f_emission.rgb) * (1.0 - f_fog.a) + f_fog.rgb * f_fog.a; - o_$targetOutput = pow(vec4(oofinalColor.rgb, 1.0), vec4(1.0/2.2)); - o_$targetOutput *= m_color.a; - + vec3 finalColor = (max(vec3(0.0), f_diffuse.rgb) + max(vec3(0.0),f_specular.rgb) + max(vec3(0.0), f_emission.rgb)) * (1.0 - f_fog.a) + f_fog.rgb * f_fog.a; + o_$targetOutput = pow(vec4(finalColor.rgb, 1.0), vec4(1.0/2.2)); + o_$targetOutput *= m_color.a; """ } \ No newline at end of file diff --git a/orx-dnk3/src/main/kotlin/Material.kt b/orx-dnk3/src/main/kotlin/Material.kt index 9e488538..a9f79013 100644 --- a/orx-dnk3/src/main/kotlin/Material.kt +++ b/orx-dnk3/src/main/kotlin/Material.kt @@ -8,7 +8,7 @@ import org.openrndr.draw.shadeStyle interface Material { var doubleSided: Boolean var transparent: Boolean - fun generateShadeStyle(context: MaterialContext): ShadeStyle + fun generateShadeStyle(context: MaterialContext, primitiveContext: PrimitiveContext): ShadeStyle fun applyToShadeStyle(context: MaterialContext, shadeStyle: ShadeStyle) } @@ -17,7 +17,7 @@ class DummyMaterial : Material { override var transparent: Boolean = false - override fun generateShadeStyle(context: MaterialContext): ShadeStyle { + override fun generateShadeStyle(context: MaterialContext, primitiveContext: PrimitiveContext): ShadeStyle { return shadeStyle { fragmentTransform = """ x_fill.rgb = vec3(normalize(v_viewNormal).z); @@ -38,3 +38,7 @@ data class MaterialContext(val pass: RenderPass, val meshCubemaps: Map ) +data class PrimitiveContext(val hasNormalAttribute: Boolean, val hasSkinning: Boolean) + + +data class ContextKey(val materialContext: MaterialContext, val primitiveContext: PrimitiveContext) diff --git a/orx-dnk3/src/main/kotlin/PBRMaterial.kt b/orx-dnk3/src/main/kotlin/PBRMaterial.kt index 835d2503..c1d1dd62 100644 --- a/orx-dnk3/src/main/kotlin/PBRMaterial.kt +++ b/orx-dnk3/src/main/kotlin/PBRMaterial.kt @@ -7,6 +7,7 @@ import org.openrndr.math.Vector3 import org.openrndr.math.Vector4 import org.openrndr.math.transforms.normalMatrix import java.nio.ByteBuffer +import javax.naming.Context import kotlin.math.cos @@ -29,7 +30,7 @@ private val noise128 by lazy { cb } -private fun PointLight.fs(index: Int): String = """ +private fun PointLight.fs(index: Int, hasNormalAttribute: Boolean): String = """ |{ | vec3 Lr = p_lightPosition$index - v_worldPosition; | float distance = length(Lr); @@ -37,7 +38,7 @@ private fun PointLight.fs(index: Int): String = """ | p_lightLinearAttenuation$index * distance + p_lightQuadraticAttenuation$index * distance * distance); | vec3 L = normalize(Lr); | -| float side = dot(L, N) ; +| float side = ${if (hasNormalAttribute) "dot(L, N)" else "3.1415"}; | f_diffuse += attenuation * max(0, side / 3.1415) * p_lightColor$index.rgb * m_color.rgb; | f_specular += attenuation * ggx(N, V, L, m_roughness, m_f0) * p_lightColor$index.rgb * m_color.rgb; } @@ -45,14 +46,14 @@ private fun PointLight.fs(index: Int): String = """ private fun AmbientLight.fs(index: Int): String = "f_ambient += p_lightColor$index.rgb * ((1.0 - m_metalness) * m_color.rgb);" -private fun DirectionalLight.fs(index: Int) = """ +private fun DirectionalLight.fs(index: Int, hasNormalAttribute: Boolean) = """ |{ | vec3 L = normalize(-p_lightDirection$index); | float attenuation = 1.0; | vec3 H = normalize(V + L); -| float NoL = clamp(dot(N, L), 0.0, 1.0); +| float NoL = ${if (hasNormalAttribute) "clamp(dot(N, L), 0.0, 1.0)" else "1"}; | float LoH = clamp(dot(L, H), 0.0, 1.0); -| float NoH = clamp(dot(N, H), 0.0, 1.0); +| float NoH = ${if (hasNormalAttribute) "clamp(dot(N, H), 0.0, 1.0)" else "1"}; | vec3 Lr = (p_lightPosition$index - v_worldPosition); //| vec3 L = normalize(Lr); | ${shadows.fs(index)} @@ -66,15 +67,15 @@ private fun DirectionalLight.fs(index: Int) = """ |} """.trimMargin() -private fun HemisphereLight.fs(index: Int): String = """ +private fun HemisphereLight.fs(index: Int, hasNormalAttribute: Boolean): String = """ |{ -| float f = dot(N, p_lightDirection$index) * 0.5 + 0.5; +| float f = ${if (hasNormalAttribute) "dot(N, p_lightDirection$index) * 0.5 + 0.5" else "1"}; | vec3 irr = ${irradianceMap?.let { "texture(p_lightIrradianceMap$index, N).rgb" } ?: "vec3(1.0)"}; | f_diffuse += mix(p_lightDownColor$index.rgb, p_lightUpColor$index.rgb, f) * irr * ((1.0 - m_metalness) * m_color.rgb) * m_ambientOcclusion; |} """.trimMargin() -private fun SpotLight.fs(index: Int): String { +private fun SpotLight.fs(index: Int, hasNormalAttribute: Boolean): String { val shadows = shadows return """ |{ @@ -85,7 +86,7 @@ private fun SpotLight.fs(index: Int): String { | attenuation = 1.0; | vec3 L = normalize(Lr); -| float NoL = clamp(dot(N, L), 0.0, 1.0); +| float NoL = ${if (hasNormalAttribute) "clamp(dot(N, L), 0.0, 1.0)" else "1"}; | float side = dot(L, N); | float hit = max(dot(-L, p_lightDirection$index), 0.0); | float falloff = clamp((hit - p_lightOuterCos$index) / (p_lightInnerCos$index - p_lightOuterCos$index), 0.0, 1.0); @@ -94,7 +95,7 @@ private fun SpotLight.fs(index: Int): String { | { | vec3 H = normalize(V + L); | float LoH = clamp(dot(L, H), 0.0, 1.0); -| float NoH = clamp(dot(N, H), 0.0, 1.0); +| float NoH = ${if (hasNormalAttribute) "clamp(dot(N, H), 0.0, 1.0)" else 1.0}; | f_diffuse += NoL * (0.1+0.9*attenuation) * Fd_Burley(m_roughness * m_roughness, NoV, NoL, LoH) * p_lightColor$index.rgb * m_color.rgb ; | float Dg = D_GGX(m_roughness * m_roughness, NoH, H); | float Vs = V_SmithGGXCorrelated(m_roughness * m_roughness, NoV, NoL); @@ -114,7 +115,12 @@ private fun Fog.fs(index: Int): String = """ """.trimMargin() sealed class TextureSource -object DummySource : TextureSource() +object DummySource : TextureSource() { + override fun toString(): String { + return "DummySource()" + } +} + abstract class TextureFromColorBuffer(var texture: ColorBuffer, var textureFunction: TextureFunction) : TextureSource() class TextureFromCode(val code: String) : TextureSource() @@ -142,10 +148,14 @@ enum class TextureFunction(val function: (String, String) -> String) { */ class ModelCoordinates(texture: ColorBuffer, var input: String = "va_texCoord0.xy", - var tangentInput : String? = null, + var tangentInput: String? = null, textureFunction: TextureFunction = TextureFunction.TILING, var pre: String? = null, - var post: String? = null) : TextureFromColorBuffer(texture, textureFunction) + var post: String? = null) : TextureFromColorBuffer(texture, textureFunction) { + override fun toString(): String { + return "ModelCoordinates(texture: $texture, input: $input, $tangentInput: $tangentInput, textureFunction: $textureFunction, pre: $pre, post: $post)" + } +} class Triplanar(texture: ColorBuffer, var scale: Double = 1.0, @@ -171,7 +181,8 @@ private fun ModelCoordinates.fs(index: Int) = """ | ${if (pre != null) "{ $pre } " else ""} | x_texture = ${textureFunction.function("p_texture$index", "x_texCoord")}; | ${if (post != null) "{ $post } " else ""} -| ${if (tangentInput != null) { """ +| ${if (tangentInput != null) { + """ | vec3 normal = normalize(va_normal.xyz); | vec3 tangent = normalize(${tangentInput}.xyz); | vec3 bitangent = cross(normal, tangent) * ${tangentInput}.w; @@ -179,7 +190,7 @@ private fun ModelCoordinates.fs(index: Int) = """ | x_texture.rgb = tbn * normalize(x_texture.rgb - vec3(0.5, 0.5, 0.)) ; | """.trimMargin() - + } else ""} | tex$index = x_texture; |} @@ -225,16 +236,20 @@ private fun Triplanar.fs(index: Int, target: TextureTarget) = """ """.trimIndent() else ""} """.trimMargin() -sealed class TextureTarget { - object NONE : TextureTarget() - object COLOR : TextureTarget() - object ROUGHNESS : TextureTarget() - object METALNESS : TextureTarget() - object METALNESS_ROUGHNESS : TextureTarget() - object EMISSION : TextureTarget() - object NORMAL : TextureTarget() - object AMBIENT_OCCLUSION : TextureTarget() - class Height(var scale: Double = 1.0) : TextureTarget() +sealed class TextureTarget(val name: String) { + object NONE : TextureTarget("NONE") + object COLOR : TextureTarget("COLOR") + object ROUGHNESS : TextureTarget("ROUGHNESS") + object METALNESS : TextureTarget("METALNESS") + object METALNESS_ROUGHNESS : TextureTarget("METALNESS_ROUGHNESS") + object EMISSION : TextureTarget("EMISSION") + object NORMAL : TextureTarget("NORMAL") + object AMBIENT_OCCLUSION : TextureTarget("AMBIENT_OCCLUSION") + class Height(var scale: Double = 1.0) : TextureTarget("Height") + + override fun toString(): String { + return "TextureTarget(name: $name)" + } } class Texture(var source: TextureSource, @@ -243,9 +258,17 @@ class Texture(var source: TextureSource, val copied = Texture(source, target) return copied } + + override fun toString(): String { + return "Texture(source: $source, target: $target)" + } } class PBRMaterial : Material { + override fun toString(): String { + return "PBRMaterial(textures: $textures, color: $color, metalness: $metalness, roughness: $roughness, emissive: $emission))" + } + override var doubleSided: Boolean = false override var transparent: Boolean = false var environmentMap = false @@ -259,7 +282,7 @@ class PBRMaterial : Material { var parameters = mutableMapOf() var textures = mutableListOf() - val shadeStyles = mutableMapOf() + val shadeStyles = mutableMapOf() // fun copy(): PBRMaterial { // val copied = PBRMaterial() @@ -276,9 +299,9 @@ class PBRMaterial : Material { // return copied // } - override fun generateShadeStyle(context: MaterialContext): ShadeStyle { - val cached = shadeStyles.getOrPut(context) { - val needLight = needLight(context) + override fun generateShadeStyle(materialContext: MaterialContext, primitiveContext: PrimitiveContext): ShadeStyle { + val cached = shadeStyles.getOrPut(ContextKey(materialContext, primitiveContext)) { + val needLight = needLight(materialContext) val preambleFS = """ vec4 m_color = p_color; float m_f0 = 0.5; @@ -317,6 +340,20 @@ class PBRMaterial : Material { val displacers = textures.filter { it.target is TextureTarget.Height } + val skinVS = if (primitiveContext.hasSkinning) """ + uvec4 j = a_joints; + mat4 skinTransform = p_jointTransforms[j.x] * a_weights.x + + p_jointTransforms[j.y] * a_weights.y + + p_jointTransforms[j.z] * a_weights.z + + p_jointTransforms[j.w] * a_weights.w; + + ${if (primitiveContext.hasNormalAttribute) """ + x_normal = normalize(mat3(skinTransform) * x_normal); + """.trimIndent() else ""} + + x_position = (skinTransform * vec4(x_position,1)).xyz; + """.trimIndent() else "" + val textureVS = if (displacers.isNotEmpty()) textures.mapIndexed { index, it -> if (it.target is TextureTarget.Height) { when (val source = it.source) { @@ -331,7 +368,7 @@ class PBRMaterial : Material { } else "" }.joinToString("\n") else "" - val lights = context.lights + val lights = materialContext.lights val lightFS = if (needLight) """ vec3 f_diffuse = vec3(0.0); vec3 f_specular = vec3(0.0); @@ -342,9 +379,9 @@ class PBRMaterial : Material { vec3 ep = (p_viewMatrixInverse * vec4(0.0, 0.0, 0.0, 1.0)).xyz; vec3 Vr = ep - v_worldPosition; vec3 V = normalize(Vr); - float NoV = abs(dot(N, V)) + 1e-5; + float NoV = ${if (primitiveContext.hasNormalAttribute) "abs(dot(N, V)) + 1e-5" else "1"}; - ${if (environmentMap && context.meshCubemaps.isNotEmpty()) """ + ${if (environmentMap && materialContext.meshCubemaps.isNotEmpty() && primitiveContext.hasNormalAttribute) """ { vec2 dfg = PrefilteredDFG_Karis(m_roughness, NoV); vec3 sc = m_metalness * m_color.rgb + (1.0-m_metalness) * vec3(0.04); @@ -356,32 +393,32 @@ class PBRMaterial : Material { ${lights.mapIndexed { index, (node, light) -> when (light) { is AmbientLight -> light.fs(index) - is PointLight -> light.fs(index) - is SpotLight -> light.fs(index) - is DirectionalLight -> light.fs(index) - is HemisphereLight -> light.fs(index) + is PointLight -> light.fs(index, primitiveContext.hasNormalAttribute) + is SpotLight -> light.fs(index, primitiveContext.hasNormalAttribute) + is DirectionalLight -> light.fs(index, primitiveContext.hasNormalAttribute) + is HemisphereLight -> light.fs(index, primitiveContext.hasNormalAttribute) else -> TODO() } }.joinToString("\n")} - ${context.fogs.mapIndexed { index, (node, fog) -> + ${materialContext.fogs.mapIndexed { index, (node, fog) -> fog.fs(index) }.joinToString("\n")} """.trimIndent() else "" val rt = RenderTarget.active - val combinerFS = context.pass.combiners.map { + val combinerFS = materialContext.pass.combiners.map { it.generateShader() }.joinToString("\n") val fs = preambleFS + textureFs + lightFS + combinerFS - val vs = (this@PBRMaterial.vertexTransform ?: "") + textureVS + val vs = (this@PBRMaterial.vertexTransform ?: "") + textureVS + skinVS shadeStyle { vertexPreamble = """ $shaderNoRepetitionVert - ${(this@PBRMaterial.vertexPreamble)?:""} + ${(this@PBRMaterial.vertexPreamble) ?: ""} """.trimIndent() fragmentPreamble = """ |$shaderLinePlaneIntersect @@ -394,7 +431,7 @@ class PBRMaterial : Material { this.suppressDefaultOutput = true this.vertexTransform = vs fragmentTransform = fs - context.pass.combiners.map { + materialContext.pass.combiners.map { if (rt.colorBuffers.size <= 1) { this.output(it.targetOutput, 0) } else diff --git a/orx-dnk3/src/main/kotlin/SceneRenderer.kt b/orx-dnk3/src/main/kotlin/SceneRenderer.kt index 870b401f..e9f2d18b 100644 --- a/orx-dnk3/src/main/kotlin/SceneRenderer.kt +++ b/orx-dnk3/src/main/kotlin/SceneRenderer.kt @@ -5,6 +5,7 @@ import org.openrndr.draw.* import org.openrndr.draw.depthBuffer import org.openrndr.extra.fx.blur.ApproximateGaussianBlur import org.openrndr.math.Matrix44 +import org.openrndr.math.transforms.normalMatrix class SceneRenderer { @@ -48,10 +49,11 @@ class SceneRenderer { val lights = scene.root.findContent { this as? Light } val meshes = scene.root.findContent { this as? Mesh } + val skinnedMeshes = scene.root.findContent { this as? SkinnedMesh } + val fogs = scene.root.findContent { this as? Fog } val instancedMeshes = scene.root.findContent { this as? InstancedMesh } - run { lights.filter { it.content is ShadowLight && (it.content as ShadowLight).shadows is Shadows.MappedShadows }.forEach { val shadowLight = it.content as ShadowLight @@ -80,7 +82,7 @@ class SceneRenderer { drawer.clear(ColorRGBa.BLACK) drawer.cullTestPass = CullTestPass.FRONT - drawPass(drawer, pass, materialContext, meshes, instancedMeshes) + drawPass(drawer, pass, materialContext, meshes, instancedMeshes, skinnedMeshes) } when (shadowLight.shadows) { is Shadows.VSM -> { @@ -99,7 +101,6 @@ class SceneRenderer { for (pass in outputPasses) { val materialContext = MaterialContext(pass, lights, fogs, shadowLightTargets, meshCubemaps) - val defaultPasses = setOf(DefaultTransparentPass, DefaultOpaquePass) if ((pass !in defaultPasses || postSteps.isNotEmpty()) && outputPassTarget == null) { @@ -109,7 +110,7 @@ class SceneRenderer { if (pass == outputPasses[0]) { outputPassTarget?.let { drawer.withTarget(it) { - background(ColorRGBa.PINK) + clear(ColorRGBa.PINK) } } } @@ -122,7 +123,7 @@ class SceneRenderer { } } outputPassTarget?.bind() - drawPass(drawer, pass, materialContext, meshes, instancedMeshes) + drawPass(drawer, pass, materialContext, meshes, instancedMeshes, skinnedMeshes) outputPassTarget?.unbind() outputPassTarget?.let { output -> @@ -167,7 +168,9 @@ class SceneRenderer { private fun drawPass(drawer: Drawer, pass: RenderPass, materialContext: MaterialContext, meshes: List>, - instancedMeshes: List>) { + instancedMeshes: List>, + skinnedMeshes: List> + ) { drawer.depthWrite = pass.depthWrite val primitives = meshes.flatMap { mesh -> @@ -185,8 +188,9 @@ class SceneRenderer { if (primitive.material.doubleSided) { drawer.drawStyle.cullTestPass = CullTestPass.ALWAYS } - - val shadeStyle = primitive.material.generateShadeStyle(materialContext) + val hasNormalAttribute = primitive.geometry.vertexBuffers.any { it.vertexFormat.hasAttribute("normal") } + val primitiveContext = PrimitiveContext(hasNormalAttribute, false) + val shadeStyle = primitive.material.generateShadeStyle(materialContext, primitiveContext) shadeStyle.parameter("viewMatrixInverse", drawer.view.inversed) primitive.material.applyToShadeStyle(materialContext, shadeStyle) drawer.shadeStyle = shadeStyle @@ -207,6 +211,62 @@ class SceneRenderer { } } + + val skinnedPrimitives = skinnedMeshes.flatMap { mesh -> + mesh.content.primitives.map { primitive -> + NodeContent(mesh.node, Pair(primitive, mesh)) + } + } + + skinnedPrimitives + .filter { + (it.content.first.material.transparent && pass.renderTransparent) || + (!it.content.first.material.transparent && pass.renderOpaque) + } + .forEach { + val primitive = it.content.first + val skinnedMesh = it.content.second.content + drawer.isolated { + if (primitive.material.doubleSided) { + drawer.drawStyle.cullTestPass = CullTestPass.ALWAYS + } + val hasNormalAttribute = primitive.geometry.vertexBuffers.any { it.vertexFormat.hasAttribute("normal") } + val primitiveContext = PrimitiveContext(hasNormalAttribute, true) + + val nodeInverse = it.node.worldTransform.inversed + + + + val jointTransforms = (skinnedMesh.joints zip skinnedMesh.inverseBindMatrices) + .map{ (nodeInverse * it.first.worldTransform * it.second) } +// val jointNormalTransforms = jointTransforms.map { Matrix44.IDENTITY } + + val shadeStyle = primitive.material.generateShadeStyle(materialContext, primitiveContext) + + shadeStyle.parameter("jointTransforms", jointTransforms.toTypedArray()) +// shadeStyle.parameter("jointNormalTransforms", jointNormalTransforms.toTypedArray()) + + shadeStyle.parameter("viewMatrixInverse", drawer.view.inversed) + primitive.material.applyToShadeStyle(materialContext, shadeStyle) + drawer.shadeStyle = shadeStyle + drawer.model = it.node.worldTransform + + if (primitive.geometry.indexBuffer == null) { + drawer.vertexBuffer(primitive.geometry.vertexBuffers, + primitive.geometry.primitive, + primitive.geometry.offset, + primitive.geometry.vertexCount) + } else { + drawer.vertexBuffer(primitive.geometry.indexBuffer!!, + primitive.geometry.vertexBuffers, + primitive.geometry.primitive, + primitive.geometry.offset, + primitive.geometry.vertexCount) + } + } + } + + val instancedPrimitives = instancedMeshes.flatMap { mesh -> mesh.content.primitives.map { primitive -> NodeContent(mesh.node, MeshPrimitiveInstance(primitive, mesh.content.instances, mesh.content.attributes)) @@ -219,7 +279,8 @@ class SceneRenderer { .forEach { val primitive = it.content drawer.isolated { - val shadeStyle = primitive.primitive.material.generateShadeStyle(materialContext) + val primitiveContext = PrimitiveContext(true, false) + val shadeStyle = primitive.primitive.material.generateShadeStyle(materialContext, primitiveContext) shadeStyle.parameter("viewMatrixInverse", drawer.view.inversed) primitive.primitive.material.applyToShadeStyle(materialContext, shadeStyle) if (primitive.primitive.material.doubleSided) { diff --git a/orx-dnk3/src/main/kotlin/gltf/Glb.kt b/orx-dnk3/src/main/kotlin/gltf/Glb.kt index bcc1cde3..87301f4c 100644 --- a/orx-dnk3/src/main/kotlin/gltf/Glb.kt +++ b/orx-dnk3/src/main/kotlin/gltf/Glb.kt @@ -28,6 +28,7 @@ fun loadGltfFromGlbFile(file: File): GltfFile { if (chunkType == 0x004E4942) ByteBuffer.allocateDirect(chunkLength) else ByteBuffer.allocate(chunkLength) (chunkBuffer as ByteBuffer) channel.read(chunkBuffer) + chunkBuffer.order(ByteOrder.nativeOrder()) return chunkBuffer } diff --git a/orx-dnk3/src/main/kotlin/gltf/Gltf.kt b/orx-dnk3/src/main/kotlin/gltf/Gltf.kt index 78f6cc21..a1ae60c2 100644 --- a/orx-dnk3/src/main/kotlin/gltf/Gltf.kt +++ b/orx-dnk3/src/main/kotlin/gltf/Gltf.kt @@ -33,7 +33,8 @@ class GltfNode(val children: IntArray?, val scale: DoubleArray?, val rotation: DoubleArray?, val translation: DoubleArray?, - val mesh: Int?) + val mesh: Int?, + val skin: Int?) class GltfPrimitive(val attributes: LinkedHashMap, val indices: Int?, val mode: Int?, val material: Int) { fun createDrawCommand(gltfFile: GltfFile): GltfDrawCommand { @@ -87,6 +88,23 @@ class GltfPrimitive(val attributes: LinkedHashMap, val indices: Int textureCoordinate(dimensions, 0) accessors.add(accessor) } + "JOINTS_0" -> { + val type = when (Pair(accessor.type, accessor.componentType)) { + Pair("VEC4", GLTF_UNSIGNED_BYTE) -> VertexElementType.VECTOR4_UINT8 + Pair("VEC4", GLTF_UNSIGNED_SHORT) -> VertexElementType.VECTOR4_UINT16 + else -> error("not supported ${accessor.type} / ${accessor.componentType}") + } + attribute("joints", type) + accessors.add(accessor) + } + "WEIGHTS_0" -> { + val type = when (Pair(accessor.type, accessor.componentType)) { + Pair("VEC4", GLTF_FLOAT) -> VertexElementType.VECTOR4_FLOAT32 + else -> error("not supported ${accessor.type} / ${accessor.componentType}") + } + attribute("weights", type) + accessors.add(accessor) + } } } } @@ -181,7 +199,6 @@ class GltfBufferView(val buffer: Int, class GltfBuffer(val byteLength: Int, val uri: String?) { fun contents(gltfFile: GltfFile): ByteBuffer = if (uri != null) { - if (uri.startsWith("data:")) { val base64 = uri.substring(uri.indexOf(",") + 1) val decoded = Base64.getDecoder().decode(base64) @@ -223,6 +240,9 @@ class GltfChannelTarget(val node: Int?, val path: String?) class GltfChannel(val sampler: Int, val target: GltfChannelTarget) + +class GltfSkin(val inverseBindMatrices: Int, val joints: IntArray, val skeleton: Int) + class GltfFile( val asset: GltfAsset?, val scene: Int?, @@ -236,7 +256,9 @@ class GltfFile( val images: List?, val textures: List?, val samplers: List?, - val animations: List?) { + val animations: List?, + val skins: List? +) { @Transient lateinit var file: File diff --git a/orx-dnk3/src/main/kotlin/gltf/GltfScene.kt b/orx-dnk3/src/main/kotlin/gltf/GltfScene.kt index 432381f4..cb1807ea 100644 --- a/orx-dnk3/src/main/kotlin/gltf/GltfScene.kt +++ b/orx-dnk3/src/main/kotlin/gltf/GltfScene.kt @@ -10,10 +10,18 @@ import org.openrndr.math.Quaternion import org.openrndr.math.Vector3 import org.openrndr.math.transforms.transform import java.io.File +import java.nio.Buffer import java.nio.ByteOrder import kotlin.reflect.KMutableProperty0 class SceneAnimation(var channels: List) { + + val duration: Double + get() { + return channels.maxBy { it.duration }?.duration ?:0.0 + } + + fun applyToTargets(input: Double) { for (channel in channels) { channel.applyToTarget(input) @@ -22,6 +30,7 @@ class SceneAnimation(var channels: List) { } sealed class AnimationChannel { + abstract val duration: Double abstract fun applyToTarget(input: Double) } @@ -30,6 +39,9 @@ class QuaternionChannel(val target: KMutableProperty0, override fun applyToTarget(input: Double) { target.set(keyframer.value(input) ?: Quaternion.IDENTITY) } + + override val duration: Double + get() = keyframer.duration() } class Vector3Channel(val target: KMutableProperty0, @@ -37,6 +49,8 @@ class Vector3Channel(val target: KMutableProperty0, override fun applyToTarget(input: Double) { target.set(keyframer.value(input) ?: default) } + override val duration: Double + get() = keyframer.duration() } class GltfSceneNode : SceneNode() { @@ -44,6 +58,11 @@ class GltfSceneNode : SceneNode() { var scale = Vector3.ONE var rotation = Quaternion.IDENTITY + override fun toString(): String { + return "translation: $translation, scale: $scale, rotation: $rotation, children: ${children.size}, entities: ${entities} " + } + + override var transform: Matrix44 = Matrix44.IDENTITY get() = transform { translate(translation) @@ -93,6 +112,12 @@ fun GltfFile.buildSceneNodes(): GltfSceneData { pbrMetallicRoughness?.let { pbr -> material.roughness = pbr.roughnessFactor ?: 1.0 material.metalness = pbr.metallicFactor ?: 1.0 + + material.color = ColorRGBa.WHITE + pbr.baseColorFactor?.let { + material.color = ColorRGBa(it[0], it[1], it[2], it[3]) + } + pbr.baseColorTexture?.let { texture -> val cb = images!![textures!![texture.index].source].createSceneImage() cb.filter(MinifyingFilter.LINEAR_MIPMAP_LINEAR, MagnifyingFilter.LINEAR) @@ -181,32 +206,10 @@ fun GltfFile.buildSceneNodes(): GltfSceneData { return MeshPrimitive(geometry, material) } - val sceneMeshes = mutableMapOf() - fun GltfMesh.createSceneMesh(): Mesh = sceneMeshes.getOrPut(this) { - Mesh(primitives.map { - it.createScenePrimitive() - }) - } val sceneNodes = mutableMapOf() fun GltfNode.createSceneNode(): SceneNode = sceneNodes.getOrPut(this) { val node = GltfSceneNode() - mesh?.let { - node.entities.add(meshes[it].createSceneMesh()) - } -// val localTransform = transform { -// translation?.let { -// translate(it[0], it[1], it[2]) -// } -// rotation?.let { -// val q = Quaternion(it[0], it[1], it[2], it[3]) -// multiply(q.matrix.matrix44) -// } -// scale?.let { -// scale(it[0], it[1], it[2]) -// } -// } - node.translation = translation?.let { Vector3(it[0], it[1], it[2]) } ?: Vector3.ZERO node.scale = scale?.let { Vector3(it[0], it[1], it[2]) } ?: Vector3.ONE node.rotation = rotation?.let { Quaternion(it[0], it[1], it[2], it[3]) } ?: Quaternion.IDENTITY @@ -214,20 +217,66 @@ fun GltfFile.buildSceneNodes(): GltfSceneData { matrix?.let { node.transform = Matrix44.fromDoubleArray(it).transposed } - - -// node.transform = this.matrix?.let { -// Matrix44.fromDoubleArray(it).transposed -// } ?: localTransform for (child in children.orEmpty) { node.children.add(nodes[child].createSceneNode()) } node } + val sceneMeshes = mutableMapOf() + fun GltfMesh.createSceneMesh(skin: GltfSkin?): MeshBase = sceneMeshes.getOrPut(this) { + if (skin == null) { + Mesh(primitives.map { + it.createScenePrimitive() + }) + } else { + val joints = skin.joints.map { nodes[it].createSceneNode() } + val skeleton = nodes[skin.skeleton].createSceneNode() + val ibmAccessor = accessors[skin.inverseBindMatrices] + val ibmBufferView = bufferViews[ibmAccessor.bufferView] + val ibmBuffer = buffers[ibmBufferView.buffer] + + val ibmData = ibmBuffer.contents(this@buildSceneNodes) + ibmData.order(ByteOrder.nativeOrder()) + (ibmData as Buffer).position(ibmAccessor.byteOffset + (ibmBufferView.byteOffset ?: 0)) + + require(ibmAccessor.type == "MAT4") + require(ibmAccessor.componentType == GLTF_FLOAT) + require(ibmAccessor.count == joints.size) + val ibms = (0 until ibmAccessor.count).map { + val array = DoubleArray(16) + for (i in 0 until 16) { + array[i] = ibmData.float.toDouble() + } + + val m = Matrix44.fromDoubleArray(array).transposed + println("--") + println(m) + println(array.joinToString(",")) + + m + } + + SkinnedMesh(primitives.map { + it.createScenePrimitive() + }, joints, skeleton, ibms) + } + } + val scenes = scenes.map { scene -> + println(scene.nodes.size) scene.nodes.map { node -> - nodes[node].createSceneNode() + println("node: $node") + val gltfNode = nodes[node] + val sceneNode = gltfNode.createSceneNode() + sceneNode + } + } + for ((gltfNode, sceneNode) in sceneNodes) { + gltfNode.mesh?.let { + val skin = gltfNode.skin?.let { (skins!!)[it] } + println("adding mesh") + sceneNode.entities.add(meshes[it].createSceneMesh(skin)) } } @@ -276,7 +325,7 @@ fun GltfFile.buildSceneNodes(): GltfSceneData { } val keyframer = KeyframerChannelQuaternion() val inputOffset = (inputBufferView.byteOffset ?: 0) + (inputAccessor.byteOffset ?: 0) - val outputOffset = (outputBufferView.byteOffset ?: 0) + (inputAccessor.byteOffset ?: 0) + val outputOffset = (outputBufferView.byteOffset ?: 0) + (outputAccessor.byteOffset ?: 0) val inputStride = (inputBufferView.byteStride ?: 4) val outputStride = (outputBufferView.byteStride ?: 16) for (i in 0 until outputAccessor.count) {