From 2d513be0c6196f6cb56aeef3430dc020be5464d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Max=20Beb=C3=B6k?= Date: Wed, 30 Sep 2026 18:54:04 +0200 Subject: [PATCH 1/4] chg: optimize animation and bone perf, make anim return pointer --- examples/96_animtest/Makefile | 59 ++++++ examples/96_animtest/assets/BootTex.ci4.png | Bin 0 -> 737 bytes examples/96_animtest/assets/ChestTex_ci4.png | Bin 0 -> 1244 bytes examples/96_animtest/assets/FaceTex.ci4.png | Bin 0 -> 384 bytes examples/96_animtest/assets/cath.glb | Bin 0 -> 274032 bytes .../96_animtest/assets/catherine_CREDITS.txt | 2 + examples/96_animtest/main.c | 169 ++++++++++++++++ src/t3d/t3danim.c | 183 +++++++++++++++--- src/t3d/t3danim.h | 31 ++- src/t3d/t3dmath.c | 18 +- src/t3d/t3dskeleton.c | 19 +- 11 files changed, 430 insertions(+), 51 deletions(-) create mode 100644 examples/96_animtest/Makefile create mode 100644 examples/96_animtest/assets/BootTex.ci4.png create mode 100644 examples/96_animtest/assets/ChestTex_ci4.png create mode 100644 examples/96_animtest/assets/FaceTex.ci4.png create mode 100644 examples/96_animtest/assets/cath.glb create mode 100644 examples/96_animtest/assets/catherine_CREDITS.txt create mode 100644 examples/96_animtest/main.c diff --git a/examples/96_animtest/Makefile b/examples/96_animtest/Makefile new file mode 100644 index 00000000..de5bd322 --- /dev/null +++ b/examples/96_animtest/Makefile @@ -0,0 +1,59 @@ +BUILD_DIR=build +T3D_INST=$(shell realpath ../..) + +include $(N64_INST)/include/n64.mk +include $(T3D_INST)/t3d.mk + +N64_CFLAGS += -std=gnu2x -O2 + +PROJECT_NAME=t3d_96_animtest + +src = main.c +assets_png = $(wildcard assets/*.png) +assets_gltf = $(wildcard assets/*.glb) +assets_ttf = $(wildcard assets/*.ttf) + +assets_conv = $(addprefix filesystem/,$(notdir $(assets_png:%.png=%.sprite))) \ + $(addprefix filesystem/,$(notdir $(assets_ttf:%.ttf=%.font64))) \ + $(addprefix filesystem/,$(notdir $(assets_gltf:%.glb=%.t3dm))) + +all: $(PROJECT_NAME).z64 + +filesystem/%.sprite: assets/%.png + @mkdir -p $(dir $@) + @echo " [SPRITE] $@" + $(N64_MKSPRITE) $(MKSPRITE_FLAGS) -o filesystem "$<" + +filesystem/%.font64: assets/%.ttf + @mkdir -p $(dir $@) + @echo " [FONT] $@" + $(N64_MKFONT) $(MKFONT_FLAGS) -s 9 -o filesystem "$<" + +filesystem/%.t3dm: assets/%.glb + @mkdir -p $(dir $@) + @echo " [T3D-MODEL] $@" + $(T3D_GLTF_TO_3D) "$<" $@ + $(N64_BINDIR)/mkasset -c 2 -w 256 -o filesystem $@ + +$(BUILD_DIR)/$(PROJECT_NAME).dfs: $(assets_conv) +$(BUILD_DIR)/$(PROJECT_NAME).elf: $(src:%.c=$(BUILD_DIR)/%.o) + +$(PROJECT_NAME).z64: N64_ROM_TITLE="Tiny3D - AnimTest" +$(PROJECT_NAME).z64: $(BUILD_DIR)/$(PROJECT_NAME).dfs + +clean: + rm -rf $(BUILD_DIR) *.z64 + rm -rf filesystem + +sc64: + make build_lib + sc64deployer upload *.z64 && curl 192.168.0.6:9065/off && sleep 1 && curl 192.168.0.6:9065/on + +build_lib: + rm -rf $(BUILD_DIR) *.z64 + make -C $(T3D_INST) + make all + +-include $(wildcard $(BUILD_DIR)/*.d) + +.PHONY: all clean diff --git a/examples/96_animtest/assets/BootTex.ci4.png b/examples/96_animtest/assets/BootTex.ci4.png new file mode 100644 index 0000000000000000000000000000000000000000..48ff66a11db0755c21607642bb576b1e85465f45 GIT binary patch literal 737 zcmV<70v`Q|P)f#&jiJ zG5S57xXBlnzg}#tYG|Qbt%C84Z(HfOl@4^G{vIQ4dlWw0k+ zqCRx39*Y(U(0Z03Ghi{A_9#Y5fG`v4GK0K;!>{Lq2s=BUyErKUykU4XGBUPaPTj^s zIU@l$g=!Bm%fLe%JO*~x3U&K9#*%6{kpLjZCS((uwT<_HMO@SqFc9iUaC6ijC`3+U3oS}F zpATBho9zMwp(2?R?tKNgnc9|6G3Me{G-x>+k08LZXF@f*rs1Il{2O~wIMItf#Yh%{onZADo|xz!9Q0v~Zc(7! zJ$E7Y&w{h_X!n18-|z1!g~%>pT5^o`=&7OTP}L}BK$U2z11&ccYOCH-a>Y~}j6*ca zMNa7Ic*UNyXh$44UzkhtYdy{ zuduCNLoAZlHj_hLLeevdLAi^RX0`0SR@|-Mx5YY;O%?uh(;k zHLx=kicE``02|ogx8=yc4fdLE#{%Z zZzY*XUlv+BiCV!n8d%srI%6>h&jI<$8aE=5VlkIM{K+S52fEy_8I;?UzAJ+(w`zhD zdR0bD-S3xNdYhqGSM51bN6H6(;g$DBwK0B#+)cyf)ZA3@F9bef10000Nn{1`bpw1tT-R&qT&XMib!o@7#?tF8$HOw7xmEZ>B5M+(Sdbfofyk0fd8S^IuL>_>N)&dz7TcuqRy=maoaRe&1=g5F ztrj>H^;+rs2CF$|rV4yBu5x~|z$x~|E`5#u+fwUWb-g$2zS^-ai(#LJ?LqF>L5lNk z%E+8q(s5$n(k_OYfA_51xL@VIQNH7Aka64naO3j{E|w~1zvupE^X5DC-}iB8ru&MI c#tb%$o}%j?$fww=1O3V1>FVdQ&MBb@06;yKUjP6A literal 0 HcmV?d00001 diff --git a/examples/96_animtest/assets/cath.glb b/examples/96_animtest/assets/cath.glb new file mode 100644 index 0000000000000000000000000000000000000000..c94bae87268d3df17eafd07cb6d80a137a807c75 GIT binary patch literal 274032 zcmeEv349bq`gRYXBA@~y!s3BZL@~taYq|%?bS8r+$|c~jqQnpqh=c@_0HPv@;;rk2 z2fB*)eXREZ)9L7{c&+D(x2x-}tGnxcU*A(bnN0O`O;?xW?tgc`Nq*f^-Cfo7yhpuV zRqxx?bDL(2?;%Oj!irwf_gnOk_M1Ls^08&LZEf}KWn+#ln_J&p-&)(=(pomAZ2x(! zEzK=$!{?&N@am@e<~jAP!zb)HW%y#PB3hwoW#wgy>s#9zTbhwssfd;>D=%xS!wt&D zM7vULWn*R@TULK`duuI{$CfR2_w`3FY-w$;X=-dkow(jyy8va%QY}qQ^>yvI-*CBN z&Vr+H|Hk(E1vQMzxYRPcrhVx`x7?J86ZcNdm@s8BDN*Ob*=O361E&H|_stKkZJOV8 z(_G19Ua8zMRd2F&L2dh@*7~w#hl9X{t&Pp?HR>EtgQJGpw)U7tC~I4g`OVNa!$k%z zbTddM%&Bj0Z)~1Rcz~l;m!Z?Cb2!=3(mu7desN>{lI(@4tt|`dTichCN^mtbz3X~v z`jpv6k~@)73n$jL&aIyTMgu5a0?@ni%mtJ8p3?}?PHLG0w#h)R>TzmN{r@oLw`g zk;s0}c`Xa-_gpZ$es)X!{5>nc)P}~nd(O@%!Jd%+o^5rljSJh`_N<*Vr=_`V&kQF< zFQ{#7?n>8yQT46OwM~1X9k|ERSF3P{oJ6IR=;6x_&mDFPd18G-`@Xf!b8x5DmiAhrO2|DrS`k&EaaD<_ zhOFyRJyuRmsc};^6it>5#fV3BwVY&A;+h;YRN2tH8pkab1Z4b@Ol#x(T$(NUvZQ7cqa)1su9p~sCFs+B8rBd#lI)QstxVd`=W zS!2+vW6SF1H8#zGP5^L}(3WWvgre~+t@X973%o=Dtf3i(ti%)p;FVa^bg9y!xN}^K zo0@8xsxE6?v_@q$9*f0gBOaGynoE`*iyAsI%ZeT|WYpPKS4$W_lhEw`0eoCnbzO1u zlT)S{1+xq}s+E%xd5n+&Nl9&tER|63~9&pXxvbBa!%J(GiGYC z5;tTGYydgBqG-UXo0?+Abv-QkiY%Kku-NG4NW7a#K7J?~C^h0SP%XzbQ_+-iO|Fn- zT~z@QvNPl04wNEpMrERmQQagsT~>6_KCN-?yaGB6QglO8R26rRDuyd1A~4M~Wlf34 z43H>ilmaxHF(^D#J{pxX;0+TJg5H2(hOYX+kJc)T7(mIosSrtaD>YgM+J|Z?CQiEO zH7FPOVnF3UEK8W=_B26-R5}&|>X;7M#Z5(x$>4Gn8ZE0@RL8Go=xA6t7uV4y!7Mb# zm;o|eX(+0KW-FsPkhYE*1N2#DtFNX;by?O7Ee3nxw&RTUn&1*F1%BjsTp>h*U^S}9 zCd`S6`b<_k*7B%k>9CGl%4mnGuEroQ(lRwz2dJ1HCyI@eggRV>TBD&V@u;Tirh5vl z5r&7T0Q8teFx6VKZJKc^K!Zm^g;fv=Rf=jl)CT|yt8g6p0-P{MnnCMub#3!pZ{r0T z0FOdcATJ6#1$rP}@Dhp|hXi0fGFBQgk3(ZMH3m+puH{0riNgRPGf0Oq^{K92fwrY- z<0b;IzShN7Zj=y8RZQBzmUXq2cq)JBdgKJcg{szHGbSOPE< zm{mMW;uX4#wk<2r6PE($pjtuH130vp5z}Qg!*l965-T@y8n|zLZQgS+O7s{IqH!1x zRfS^5bQOAx7RG2D(Q+NCDMw+p(fW~{=mMU@xh~e!{0a!a02x+JQ#ITi5WxWz4_nX= z(Zn>Bm>8nVU=M#(@A4Kfux2Gyvn7z82VFP>&f zOp9p*;b^5I79)m%Cbhky;Dy=0{p_09)?H(A_GseXcW&k z8DL#@WvvY{TA9aZu3<6xNjeAyEC|t4@)U$M_3$(E>~G0K0jAXRSyn?lI?E^Y1 zP?V^FXGk1RS5qg31U!++qsBnKC>n2^u-YKT(L|>N`C?!)NESpMuQ1WT!BrFYBFJ5x zfr`Q&LtUX9I-X?ckLYOAc&CyMY0bSJMaf9}W zI?xYhFre!cIs;w(Tp#_gMlh^svN{A}qN9nX2LlyT(O>`*H#X2;C`SV_;|BiY=>6gW z+T9kty#uDw6{32@^1-Npi6Q0(O0(iJi?dXJ8b5$ozsxuzIBR+t?P<}v1Wh?#64 zBP?1S*zLj91ES|Kn8FOXrb5&V{V^HV2JFZ@g`qD%0nwww50q{fi*#tg0QCD~Xce%U zJ~o&J^c9T>^3Ul)Zt#<_8&Gy=wu&L6Ok|fo8d54?gwPl%onyil9tx|P6UQ_q;;cXfKeyL9h%z)(T9h!<9Q1UgeNbt!ZOS>p7^pU zlc8Uf=&gZjU{GK#@hDRjk6kLvb$S%a;JOLLH}HUS2QB4bX$7o5^dDx(Z4c-YsOS@b zNDTA=1Wz%S#=KdoWvtnqx%DkIwQUQ?Tuj5F<~mH2KmZGCTWfKu%$)!u(=0VDvya3? z7Rfc+y@)xBvgpy7$4b=A);%wzE?b707Sy-Rb7#%Egqx~upNFXuOr@cD&Tqt|Ks0ZT zK#rHAJd;+?g${iX9}jW@ zqAj>rAz*z2$`yjgP={P)On3}kz$rfW7#fi)R|pNi+Lhu+Gkt@W4r!v$b%o9UpC`GPZ0eC7yBXWh9@EGa<8oAt48A_2WR|pif-1#C$j}I4t+@y_hGI|!3n0YQxUbDqrC10tfA24X+wc)G zbb~y)x(XIT$j}U`6cZssFXUXaD*SjuuiZ~tu3#aAEZxYJVj^TIM(&{#fRLpgxq<}{ z>MY&Jm0}^p?24Zix#vz{gmAzF6)c31r5m~Gm9%M3{*BEG7ooeaK#;C$cwtM{g<3Xo!sNY^(@>ygQM;Q-b;mnG zCE#H{7B|imhbZ#vm_B3gsdNo0C%+$)MwJLhg-(?qj}#uJ7$?6UlR=dThsmT$urT@S zh>Mocgr%qPq~}AWDZ;2|iHG8qMoXNXIqkVaosRKWt`RT(-#m0}`fXaqH1T^M0$db~S$ zKx61dX?i?A3?uhoWa(jPdc4dV8GzS`{1(9fD9KHaPnd(ZY}j+-CdzT-zW3n*$=@D5tMD&O(ObzsSEKGiSG!_mKJpvC?13mr@lb@Dai2R6D zrlz+;6%dp%0`{mHLNN(%AW%g@ff5unf`zFXLV}`&9SW47tPxF0feKZFsI+BKY0I>< z!|_R`Zppk$%ZNv3MeF26VB!^aY6dV=0eYYrssKIA3{!v`ahp#AH{jM+ zfSy(e1&JPHhAKc0F+&xg2biG>&{GPb3W!SD6Kfl)22n|KV{P*V=Lxk914%T}R*s2E z+7oFT3X-U#W1^Dw1lopzB-*B9qLTJR*@l6{4YJKw4Q`CBuYjne4be7jh)UWJm9!z+ zrVUX^dxC4j2#y1Uh(hPofMQLs@Y-t9+G=uM*eJRc0muB!wGx%ML)q9&pDU6*`jM5B#X$HSEgP)5l z511eSSI*$)rqrk5b1enJ*h9TCiv>oh!AZy>f}=jg6S~V9O#7ncvF5WdEKm4uxLP~` zydjIwqrY(c@`Uh)tc5oM^m9z6NBbdx(XtN-j3;{rFnY`%5*RK0aKJp_ydjIwBmZ!~ zJR!XyYvGOl{T%az^@apSOFtwqap`+PdqV=Fr5_TQxb!{Yz2Sg)0(@D(^5$~!VH3(E zu?qMFsfx?q6XMIN#Rp4V@+vL)klf<6dmk)uxvS!G_k{VfxaF6L_##(W4xEyFIDTp3 zlIN~-#h`_jeMn%m>_c*lCwm4kTKXY@iA$gBefIrxo0n4{y@W~%e+J0&IbXH`KCy>Y=4n!>~ z!wNqyg~n$V;V&(p-Zl4HS|5hEB}&Vu=c1<-hKU+_s9b-f9WKIdj>7Q z!dM15w`5D<$*$7!>0KsFWxZ3Cdkd>D2TK#{rHS>@#Cp!Q7j7y4($IKnVtr9_p?P(D z;+VhQ3%-3xPa1?QLyzbbd?MLbk8glNkIloCpa*C88n?d=|ESp$LmR3VPY`Xm67<+C zBrZ=NZMa(Kk$JchKSPe5XxebK&;#>uCA^XkB}Y$4ZMa%IX=?SV0DMwFSZ75vc zC2K?B@=87wzdXUU;cyAJU{82$SblkBAHq&}LTtlP;+1?TetE)dL)GG07Asr{&tz;k z`{jwX4Ofe|)ra7)C)zfo96bTI;cy8{-V<^g7MEA{eCqK5T+h=kObKy&k5APK*WzvU zVQ_gRA4c!-y?S9>qV^u2mG;yT4wv^?ABK8i$$Q-H;q(h1TJ_Kp0+(mqtS~J_^?2RG z;_}Kq3@%~G%U;QclA~w&tZ>wOB_FO9uk1sW@wnYXA;U6Sr73mtp;hL~vZX2YyoEhW zvFfE*b#Fj!DOSA{t4@U^msXphX8ajJr@8rimcK+rA1B{OK&^pZcp9#>FpIG-!UYAK~9*YkR2Ay=Ep zO{q_BuCJY6U{YNrU;pMVqON*Y$W;}5o+ZCb-UPX-&;zt^CFlWKxDxcxJS-*j04-cC z^zbZH2~SjPNL+bgu^~8|7Z)3*1U)Ge78gA<4@bSQ#;ehH5E! zk+C6g5^nW*%Ta})L|F2kZ@`Aq`n;If5U4yM zu_2|H7ZV$%7H^vmQ^G6vP*U`K2R0nPgyrrDhz-jxVae;l*4`5j8xmLEB2^)zlDA4# zm=a#ehmxbmc^*oRF=1<;w^mg+T*B5qCMDdClTC^_b>UKOSmujIqk;+1{4GQ#a14)@Z8dTB!4UH>M;fVniGUYbxZO{g>1 zr!IZNlr)XfgnDU0o!LA}G3vP~e}cxPp6J_f{e=WZOFv{S z;?no5dK(Iu<_W+J1x(|veCuPf<_*9NqhlI(^;RAQ+-12<7HXOG+t6qhyg(r6g zFuK);1V&3fBru-j{lL88x1j{-`HXEiVB)J@X&y&?IF5N%y$T78ZuKFH(9#bHjFx`L zTEwOA`KWC;V0r%i5S;`q&%Gb22<_z!2~520d)B=QSqm-wkVR z16Fb>MXTrOp>VYNjKXWDIWFH2XCk{6hzdTX6A#r))aKqIiEO}29ZdhC% z*@xnnu;e`-jSY)SxYc{&a6@s}6NMWRmnRN4TrHkfABMw*u;e}8j}3=PSni$}+_2md zZu6ccufkE{Y4PE#muJzdP_=lR?%_&!4)N2tTd%wno=)Kspk#oOH=Ay zul-}fD0o_~v;a(L0hrPPFr|-`*0#?p8&g);omh%jFU6~u)>O~AOAEJ@e^b2r!L?0= z)_>9Ba7^aUbo=AoJd4?CaYn#f-t4&UiHi+af?k|7TnW#}JQOO==qywT&-{C+5}uJ+ zDE{i6ufc|+-7_N-3YTYG9uk*lTpp$tPgHCuN<2Za;q+1WM8$@yMOgBlsMxT$ys{6` zPCU!fhNHwQ`7rHQm%XwNgG*TQo|xE>{PG0FhN9jR6C19Cu;e`vvEk|vmb>Dai3`^n zJ)eOMhf7%Qo^aTZQuM^bhQj3uhYeT4YwJU4z2`Hq;c5}K_NrI%;c$6nAEGrP92NmG zjm--ewU>(QAL zOUV!NwbvgVC8ygPo9b)Y>RMZxn!2vEw6v#i)Y#V8(mb`bWnq15yIZKdtU;Yq10+nT4(OKrlIToLbb@-m(B^X&6-IWZ4*uSE}883Tvbz{Bs-(O?g?ernYI} zyxOucFd)@bIz^?&Wz%R5-4!TaG{0O0-3+Qfny?sPGh8E#CEUxM#MPRGt%S>n<{<}7 zjdSOH`ex`I?oAaW zH$h=?ITPIHsk!UQlEyh?@`lDlu0Z3W6)`iW7@Dq_dQ{b9sKb1)bab>r?z*6x_}+%0 zMWGe*AzfTiwRlvH$B;o&lo)9@^Hp*u(}?P(sc85*i4oJ?^BOs?X_*T#6o{iwiu_oYv8MN0^Vhmz5ynpxgPeV>$tYPy|tyGp{=G3%_{%gG482`mbo-T z2&wMYMIEj#Y-ww3hlzrg#ZA3jjz)=ElA2N0y$5MGbDLUb*EVHNp`qp3OUg3MtvP1) zqJ{={?V$3qxixL`YP(iknp*=owba!$Eg}}ty)#aAk$~!ssi|+SMN{-&X>0dhs)Hb) zXf4edvOys^F}t>IzT2EZ6O#3FYMNVG7r3?_yqTL3V|z=NeaxML6{u-jSdV+uqKUfa zyBMA2oaY=}KFgu5o4fYJ%}ngt-1;n$T}MEGm3^~ypkZ{?=CY`!Z2=w_XzSoE2x@9v zxG;CS1#{XOpb5mX*UV{bpXa{*K=NfSw9cK~ecG))bD9`G*D_M)0HwXIg&0!Ayl2ak zlQj*EO<-r<*(TC|%`2V*o~eeEo>Sjm+n7;I`lfj1wJq!-sSDH6x~BT}r3M(b30CrZ8b2iZUOX#Y8I25AXb|g zT(AkHY8skqGhAtaC}+2{%-^TAWf53;Y+3dMo`a;XmOTVU_tp#Qn-|rz*UpAI<7!tI zYv0<&R<}kxm}a+5g2JM2RyVC>(cF2>^=)pikBr&=1NwxbJweF7yC;Z;{W!PtC)5$d zC?}vJ2*v5XKi&oT8TZFW&$>IxxgIYui)c5l3Ls4c+jVh#ZC(A0`lBoA8nudr=%k^v zYck3vEU2AZUxvF85xWJalVS^M+hF>kJ#F(E8!{HFsbvY2kaR=lp%;nOy70t9xf!|a z=(QBi9#h@y1R~m&+gT^QWgHVF%i<)!d_)k%C+2|Jl?5Jh?Z2Tbo9!x)-%NMG)0K@@ zkd9Mk%U%Bey((sS4+m6*{PYsafAP)ZfgU&LjQ%` z)+sIR!>5y>|D56I$h9xRKrPqB%13rogq*{RB!(#-0=X=c^!T)A`YSx?Q}8e+~$Gpp@^GpjD& zN?q80<;-fS3(J{#B^~jut~aJ`+Z$>y*Zbc!^ZNgN7dADozK!%@Yf96w|A!F;rD@oo z5m8X;!&3d#Qgp!oVRS&L5Bu|?14?~ZaNu7X9Z>4ShVR4Hk-iXb9v0rd1@&#niRolI zl3;OHbV0U5JhiE|xgL>dI_VK3NDlE=i@OSuNruMRi`vQIv1O?#6Q@k8L6igLxTj8; zK4Hd$DU;pF(#cb%O-fF5XT@jieMoA`lxgEgHb`{8DHA5om`)Bbk9zRl6ZY9Rb40w? zjm>i!>&Trk%?Ova8wrbhldy*Z^&*NiS1-H^*?JK=NY_igm6xknhUQW=lXrh|Rg-lg zb9G~sP_S+p1mr3w>-c4BC*iK1>H(9g9ysah5h|Ulp1c#EtKNM_p#bR$sK`}MKD(Z+ zUI7Vo_2l#Fx$4Qs(WvUldm~i!K$@#w%>*U4&2MbZs7zxs!eH9!t0AaKwNM0CSPJMl zvIXz_kvy`22)%NpTrQ86>*ZRxT5gud%8hcwE2`x(&dcQ_ED~{iTDfc<-aQ6Ok{AXu z3s0h;YwK|1wwBgRrI~QOgBt5ez=S(Vzp$kl;gmDnkPE!J1#Z{1EF!^nst(e-LNN~7 zJEb8KwOR)-S73C}S4`rl*n z^_S1-50Ck1a*Xmh{o$5p>VHmubm(`m_7J1*ryz$Qmb(K}eF#Ec`HcQ3dPU4I5KS&a zt5w4_oMr_+_M;+T+*KX5LNN_9ZXiepkjg$g-p=z5&In-In83piB~i{qsNyu=`z zM26{mP)HUFZ}^E8hpo`JqN#Y0!RIP^TtxCP;uMd3Js^;GJoG%xs;r+6In22b-i=!;W4ye}Rsc^-P6 z=5f#$r+5ZW@p$NYn#Vz3oZ^{0#p9qid72lD9uqIYqURLnDIO0!PxCm{^Ayihy}y@7 z# zah{@bxWds>K75|0a_Z+PDyKL{Pxi^s4Vt1jSe*XJQH}zJpn#);U~!NN$;59~6bD3fkfB37&k_$m+q2}d z)%6T=%X4&)F98xbPz(ooo+T~?932cn0Y?kD2#VA}vVc=)4zhGeL--ky@y7v@iq(96jV|5&6hdkREf(bF`38L6N=@nd=b`zWZ~!NArC*-QNqz8 zAx8-Vf03RNnFJ#SX#kgg5lhIz&(T0`{YC1ZE~0-d{380tXn|aJ2}gf~+$9YBMfyu* zuET_fUqt^{_(k-O!GEsHgoj^5|5*4%^pAzVNc}_1aQODmz+a@-MCQ6pIQ$oKo3QYU z=pTdsT*nCyzli-~;TO?A7XBjj&k)f+7Jd=^W8mjHPdNM+a-J~o7wJ7g^u9p*W6>{S z|5*4%^p914k@_d(KVjh)(LWacBK42wEb;VT82EW!5l?vr{vw?sh=&!>KNfxw{bS)T zQvc#2`p3dwr2UH*seeL#5kG!K$S>mOzfz=ML=p0fu<(oM9}9nR`lm!i^pAy~r+>H} zG#RBtc?#&c0SiHK8mL5zvw(QBhhsr_1Qh8OQFt%ha7?Jeb&7BaC{hP`@7r(*0KmX8 zJeL5T4svu@$SJ~T#N>5=q6jF`D}t9$H~=^d;Ce-P65zda!czeuw+KT5>~~IFy~?;I zxdga*e|DHY-d8PB0z50oC4i@c92MZXMR*eAIz@N{6zLUFcwP}M0U}nA@f<7CCxREq ziqjyKr-57n@KlheK}BkykVAwafFd0t3eO?JQy}i^B0K@`{2^QbB7H%I5#{JPqU#P^33R5%PvG2;h1{xC9hA93d}f2liw*5+onT4lK_l02u;rzynaE z3X+#g1MBA!z|%nv0bGZO2LMBdxE>MD4H$N`NSBBbnVBJ~6gU3tC}?+sX-;wx+RE#IODEmEhsFQ)ML#8GK3pNe#{C`CG16rPiX zPXI@yc~9mdy(|hAF%eL8hNhCwGX}L4E&)ZVAkWRhmjFixc?1;cXThQ|!3^XQP^6;; zpQ;Q7z-54twPdIez6)8D3US|5;aDM_r-d&8-lLrdphy+uxmvgc6zOZh=T(c7AkWvr zCxD}aJROb~se(Lb3!i`@&0vw<7KP_+;Sqq3`xd1FYLV_1d|fxVem()knL#WO77T!+ zf>=f_xICYL;-17R*WVIs#oWc)f_egc0*W((D%an_A%N#@;Sx}!zXczR4psr43h`b- z;S<2oK`wwIRgeHIN`;E_w_p`45di)%vdZ(fa79q0!$sveTu4}JX6T6Zz`SE*kvC~o zo?phhmM4o-e0%we;1p45f9F&s>lg*8B(F&n>AoRLzXjIse2ad{f z;P46H=pau5yw_Q{;xd4h(K}|#j8CJAN|BYIt|3>BcZ@2;=8H#z173sfG zdHx$d0UQAt}_w#BI+&n?3zpvVVt ztVk7%af~3JfFiA+&^s**738^FxC9jGZ&7*v7M>9>I4Z~|pvVU?&)>o&fTMzZ0ysLz z1;9~3F94Pfam=9i28>5>kq#G?=Wy|^T+5(<>u`aLa_(Uk1spBp$-pd93AqjzE&&`Z z&XmS=k$7(49}wWHNX6Mv-l|_j#9i)8 zfkh7NgE1joCqIL(A{{Ck&!NI=F}xRI_-rZCXma0(;mMVw zuY3ZEG@3#V6^3H+94cG_iu9=9OQ69`i>E?lo+_y4#V4RhqsjBAa0!4-ERFz<4srn$ zse-%}!nhJB(xamBJSsc}@Ej_90ysLz1yH04^4@dd6Ts0yE&)ZVAnyehJ^`EuG>-tD zM}=FSGl|0`ph%C3#`CCf2@p|1M*pNphl*C@`zspn3oCp96ln#GA~lfbPT>;3^`~&U zGF*2GuRO;H@(B=8K}J`G>rUYjz%hb+0*bVPTz3kO0FDZB2`JK?q80i6ipKM%@Co4P zAkPZMIV$J{z|cXSJH>kgh8-=^pQ6QiI*99;fg(Ok8}s~;FIR_sH&^4n=z@9zN5mog zF24Xyo$H>VVfy8v7wMhRi}cRuyw9?DG@6Bzv^cP^5E4FVZ=qbDc9>0*W)LdXdf^vz&(4^I7D0z_1h@f_p&W;hb$x@NcpAVX0SC{hJ^J{WFKg6D(b zsZa zw(tlj(%Yi*ye-~F$Y=yY@2@bP#G>97jA>^tYG|l$J*csMNn6>Nna6e=myN+n3A2~B z*H5f(p4&dJY>XZw>Osy-X=rGxZ+A1a*S5|jNmYx-lx5`w3v2G`j&$M7?S6jwxJkl` z!#5&RMDP==-r}lA^?vplZg6X8_~h%S z-uh$t^#_R$U$D(nVZ|^=lMD;MAYLR70Mj6Dm7iZeuICdFWCPrhHeJ6Obr<6ZTfahD zi?_TfB7Z*vu@ndKtAqwXsPzEA+Ua=;93;Uwc}d<|UPuFDWb)Hf9>%moI==OpgVaT=$#L zo*E6)2x=p0{!>OZ;zm#nnh%nxm}UT^d=)fdgafkY+Z@$27~qu|NsuSAaJtghY(|N{|Nm0HJ^`q7!(d zAr@4Dp8!1`bbkgQ^pyf+?5hA@cMqz7kw386`vKw8=OQ|x$>>iD5uhtU_h$gYXjiC$ zxKOLq_m`=Nf)2) zgKHSK2Pri^sh8Ky*9=pv*~HNa4}jz&A#MhmY6haXDa0gQHUpnF`G}A|P_6xlP$E#V zeKlZY6Vx*O`7ziJ;A#HYQioOqsRiTyVjNZDf$faJAvGS@(0qt=L5}K}5)I%G1CbsN zYzaO@h9FN3Gw}K3lbK*U)A2M5qS%i=9@q(Fa0tV1kxrBz7vyL>9{9jyAd1I@o|t%i z2-&Wf91rZJ<;x8D1AA%tGC+PIjv{}co$%qo7cGPAgbxqCASohYOqmDT2|pgp5eBqM zKOQ+yBN+Ju^}(+}F$FX6B8c$*yNIQZVe}ewe+DA-F+|#NEGEd)80HxRC}tpv$$^%_ zCj~PaXnXznF(V*`$Q08HBN`2~z4?fcKhRG2d1OSz^a34gp_YdHfh~=Jh|I?aaMee% z77gy@xNqOleMfX11A93POgbjHMKECq7^E3K8jRq1ihO$npHZMa_1|9?>dP929w=o$ z9z9UXemt?jmcz&&Xixokf~WKu_ZOP?F^u2|bUz*=P)GfEg69Mn`2*X%ACK59j)6X- zm_BnnBzZn0++R?i;YJc_k8weL4tCi1_-~3$d>Ur(T(wVLCT813=*5#vh(D$rXy5#J z#3oD(sGA@jF?}}S)f3{6BBswKzP=T3e?NZ|F?}}0<`@k`orvKPn~p(q7qibMCP{_( zqY3J>CaBNB&uhQDbTRvEiaEawGuZj%$0O$Z!Vq0hpMz&$8F&Qs*$}hOrXi@$hFE{Y zgh33@Prp4!gAB;;=MNMjAV1^&g8CfnXY%6_o82XkUorl~#q4uD8fc$=^Vvo`8mQ2| z`D_CO3ym7$f*KUZBR)XF3_yrh3@DJV5+)+Uf+}F-4;*g$0HFdQoin3iK_$o^*yb64 zf*ZY$VvJNploWlMKqd79BC$atB9mi*R>Ds}@Ti0VC?+(?gUNLvGmTzT;53^bkRl7s z$D42r3MsXs2hPAS0ErDGO?A}-weu~AqTNphEKFMOi{VgA$ zSn&9bkw37J`8kB~iI7gjf+vK09Y!;Tkk9}b`w!?hp$ARupj z(6iEr;}32&B+TDi0Pn5@P>>grVG7QXAivn768+u4Cx;I|XHvx{0aGm8(c}%%{eXg> zWqv?np=yXN4DNyZ0R<2He1PI&VMcH&2M>#VfZ~FUCN5}sF-q2QVC{0cBI4s67X{K5URd_brm@Y&(70B?u{SQSQoF{O@2gL|<43NRZf1c)=& zbk22R7~^?A|#2%P=M zp9~<~l|TaW`s~Orh)oExynaA%b_Y@51B4X{gGR25{DF@SKOnpv8bpDw0`#ea zX3!Y<1IPA$KzI#JL69W0RNRG<*@R(Q) zco#~rKpfGIdQpM^;*IA2DLuAn`O1;1Lv zz!VF9xyaw{48#HpDIk^+2{OtIOl0K}p(-$sEoRV61nLLWz`%qVxgaY1e2Qa1=71`E zJy1D{K3NbIeo(OFfo9eR3KI;0!t>33%P0{jJ>T>YS1cz9#Fa-x$ z_%SJB9(xSZgQF}Mm=r~*zlbWtoc1UXJoIK^;tam?ExD|U%`!qcf@3Whm{hTOMpPl@ zx+et!JvJ;%!2uV3ebU6d_cETrfhLWCi7Z(r)b2Df4?Zvj2VJl*1&3Yu`Gn507!g<_ zJjgCHFkvVz^mLJRv59L;vId7|TOndPPF}#y5no;P%i^UX>0)f+F3|T8; zQ3bNXb3XZm&2c_4FsZ>kO}{8qv1k?$5geJx!W3*i{FpewkgNiM3dq0&my*yUQqcs* zYl_AhulaQx?sK8%JTx}2yX@za9vpnd;1j;L5H#_@sDk69_vtuU*+b06>SC{@VyKNL zR6rGeB4WX_9t=KV21v{ViuPqOUl7=r^*IKVm|#~H1;plhP#}_^vDA?|^Fa;ZazwAgzlMoScP7u7` zWWuW}rXF#@xgHED0u_+Kr+Bd8_wflKEP*|Ef4>wZ0yWSNN`-?XsPF3sg&FK1;bBda zysoc`sobC{;NkO?2qwc{1Lk4^6v}4;RawkOjrmM0tQAlLg9NNM6HtHw2~UcE0<0Ru zM*oX6s+(qSRi;3&Ce$#78oz!=Mz?) z7sI3mul&Q{6I51=PpYVjqr)Gh;w(&}I*z4w#Q1~>bwNy`o^w?THa31?YkHuL`_)Mk zwaJ>Oifb`Z71u;n9I_iX_A*GdN6# z!6z&~B!&qujS6B44y#~c3J$CA>$n-b4k)8nY6b_#`ehdv^gF1CH8PiVe~zo`Q(V;d zw-C}tR_-}`*&)MwNYxW2OWQuuZe9D`F4j-8zeq^Z3ai-TGf#dk@y(6v$Nq4@GhE{cwLGyOH*gO_SfBbKLX1iPq?ox3SE=4_1=$|Leym zowuJg{q?P_{^#Dqq?dPHls}7CJ(L(aqbl*^U+UfZ{?m?cd$8TQ>ib=+#f=$zT{`~P z@}pv#cx6N16Dl|T>sYtF{XI5*Yoj}j=kf_5n)~Q0#HB z-v3sAPgI^g8?H>=@b0M8RTCvU{nCxeJKh?dy7So6IxgFATT;4YWa?z;<&L3)*CdZS zepG5;^q(D*-#ROK?eBL^4Lg2a$9bFYnOxjUPp#PNyyQFfImtD%%2Mm^f3)hlN6t-d za)g?Cx!=}FIxXSvjRyv&);)Q0lBECMM^8m(TuaJ2*|OtzJ2x3^s7h`5l76sT-d^H;Ft>HV?VaIk)Ydx?t{+4)QzM{N(&IyC|t;=e*&N zbnj97rtW@aYzIj{J9B(0*>9gD?%9#Or**@M(49tp zC!3$(U-H7hRR62mI_Na+<7Dqc&JVhANNVJeQ(fA#>2W7aOI|%bmKsvIB1xxT+~v`# z*pM-)5407@#D|p~AMUTE{(0Bc$+}^GuDWMxMatQ=GkMJXUso-%5~;`feOpDRN4$SW z)tck2)NX&eB}u1mFCUiNdBt|A{mxyNJbLV$ zcUZAkcTYX>{7cD!m!9Rk)HX2n=RNOp9=;>xB;MF2b#KFc&KPyKa%<-pXSFCKR; zdwwrxaP{ES30Ge0nAe)luk^vGEyr$fK3{p4^YTgCq)xu-I_JuzzjK~mu}$jA$|szq zKTdSwzaEyl^2#TiUky0G8Grb&)Ulgh@0`5y9p|!jyQaq8`nYrN>SvsehTT$C+urH? zdHyHP%x6cYQWI}>4qfuG^X%OtQwxuJ*16%nXPiq98kIWw$Y-6(TmImTZXJ~}_rBSw z+4>9T!9Dg!wKv}D?0enk&QUw=ky`QHqn`8*7r*ChIdRQl6UH zaIZ6T+jpH`KfP<}lwo%|+eMynA_wi3`u>K;op}e3Np3v9vwF+-u5tD__d@57FAPZC z_4&=tobwaOkI(L`KJ_2>Ida^~rM%yQg}~ zF;_b)Z{Mr>^h>u&-SzjoD>rsjR?j%BSE^r=V>i5$tiB`BBlW?cvCd7is;fut*)R3w zpHFoDaayAK@S_H$*4{GE+49=q)w6%oC-urFy`8;pTvdJWqg$i~K6aXQ=OrgscQp1) z4On(Whx+`<)z9ABE0ySVxKrNuLc&#k(xhosB_abr&sUwW1rL~Ehjm<_C2F|=HA<+J~&lz<_&x*dHu|7 zQs0erIyS%LiDX^bR;ihTmpICT4apfd^-Nv7|8!^k=qHkqr+cKPzwoP$=l<|ya-Vfu zq?&G)s@|S>b@DgU`lfa~@U4!WcG|!CZ?)T|POskC=`%iAed?QiQV%_JmGkx4TJ`C_ z`L=r9$o-td&W=@=*GE#<^&3!i+zI2Vzd9N6)sCuqZAw}7v#a`~ZoTs54#=pJl2Iom zqfSajos^6^DH(NAGU}vc)Je&xlaf&Mbp#C_L`N}HyfrU>GU3FPfKp{!&%Ae z?lU{Ci}p>zr}3R$84`@9xlP;B>M$fx)5hbfPKUv!^v64e(?@@ip=Q~#I{MoBjJN4V6y6WJY?ROsNmF&G{kLsQ7+0pqx zX-U4be|hy!caC)Sx_E7JXGK1}u)6c1o*la`f4^$T$rn{0x9btkJ-aSRj{N4L>I+6L zbspMqeRBIA7gtO7T;DPBGBf$&mbX=ZFte^>$=eqtHygF4dfcC$s-n}6KXO&_tdlOS zUZh$Moi=47`S%BItge!-b57iAZt_m^vFg!_�o)*HlhPb{_g@^|sqz;?QaE#G!cN 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 z zH$Ena2)c^=c7k1=we+TCjcDZgc!gv8IHEVTRM>l-GY%eUMc;Z5O)~Shq2>uo@yVO3 z=xaI=L~G!8bQ*8OiobTy;fheQ?TbFXu{jI-&-bM-zgbKimRn<=c6oSC<6YsrXA8;N z3xjdHn-{RzbC!D7eIA)N!wC-;-NY_FF38qkHo1meaQ9vJvDxG>bbahha!cld7bHBu zgYT?DPw7B%CEE#)_r8z2#H>WyeP$A~_Cv5%{tY~MRy=xSKbr_c`{3iU3z+*Df|_jS zk-k3-@vgJE*f>y%OjLr1;w?AZ{SXu~zIfvTplHoLJ{t1{LO=?=sm^p z+h?Qo=Zi7*#G5!?zK8{<&r#m|Cmp&FEREuRsINlC)meRH8(UB8OXA05aU?nTJ{cpcl2 zVox7R4B&nyj)HI0$CDq>p1&aR@;6w2hxBmIjB`ITj)=>eO3rl|pY7No^N4uTPLad& zC`U%`3Pqo}rOF;pjwM$n5jJRr0sS_x8yBTHmON@`&q|jMpjqo0Hs_3#C{}J|k~&~o z=26U+j|(EDSrPK}@@e$=eJ+YRcpv^{W=Fxa`g!!G=k|);kXL(YC>%OJnzo%jQqcsz zy>v8nukg{*WZJ94Y(-cDaCUr!&}GwBdUCyo;u?HkaP}ch(d$?HXq+=v!G4vI<0nl- z2Zx@f9iEC5fi-|zGp$9Dgrkic`zZ1O*WNR>qLszh>B0AVC=~D;UEPog9%A!|_BZ;* zZ2uWW3JTWaxV6vef%5Te_1q=!yNEmR+TWjOPx}e%!Xv@NtldhydEIYXC#f&{U}q?~ z@_iz98>hjDzWieLg+!2_0Ty^}oh~C;#V{9RqRHS*n^A;kPsT6Aika0EM_yc*BAORr z!bn$sF3hk2%tK-<+r;@h)>vTgZx-IrqP zG)`Y3?owCaw6m%*&mH7|h?zNVpUOeE*kM1kh^zf4X0zI8 zvS4T`yJx-%DRTPAY`Zz0l=-Exz6q81-k6WfsZO3`>ZqM;f&U|Xq~8YyuboQzOxVKe zMU-LU^_Y3H){oeqKEQ@dJcEnJL@?L8%pm4=dsqYWZCG(9Orf`HE^*+Nu+#4aVy)K` z(2~zf$@m^U*iBC~a7M@#ly^9ir2oifHik|{0|shf0=#}{s6G>4Qc9P+HNiHD7$WMq zlX}qQ5i>Vh1Jm{~q~GV!=yT){HozetSzm}EPCngHw*_8oFZXe%^NUDg-(@0o<+KmG zY(aY}w0#uu-ZGtbi=4oYXt+dcrA3h|qdPJ`qFvbwdV`o+-DtA4#Ef}wBV^|u7{S~W zM*j=W^6kiD?{7#05=x3q0At67|Kj?AYy`3v$hm%fxDvZsd?jrfBOBC%m`56N3+#Sj zyO~uqQ)5m7E@*OJVzkNW<;eRh>kobi)&Wsgn08580rRFYwcs6!~x_ z6;}nW#q0FDast&6oQ-o0D<*vc6|a=v~^*kpqp>A2FAHQesV_06k7 zIrgU9p*zR$twuAVDLR9F)p~HZ?p?xk`WsxC(}`4fH|2Z=T)>U53UJl|7=OAyfV+6? zBo4OOiYeP3$2I6yH#KtSttWS4(LrqP(4F}b z^%i$@^yXeLWjMC5l(Bm$$APXBxslRl9Fw5Su619Hjg!Z7_u)4nYq}e=N9Tz#Nv&m< z_6R^-HV2TT8#?ft6@Oxsk54{U`L^WKyz$C+N52EloUI@`sM-i#%Ze6)#WGao9g_g}!JUmH)hu;1v$7F=4<1*sU{!4n7j5uMEsuu=P$)VEw?@}RswA!Fa- zGSBN&W~w!@U296NIzPZDk~KRJN-%`KjHD9G_E#Pdq86?#}H`N>sZM;#!Bl=oC;z?Y!k%2t=}0QqsgO+z_E0Atx{!NIYq5AqM`D@3o~mAg$=>-7u<>Mlkr?cG z_~4Iyf8Pu7ZP);bkI^Pr|Gb=)htm~e;|O(!lDiR(<3K*P#n(xK)JXM~NbKDxK*=c+ z$?5MmaDj#fR0~ zZX06Rt;t$!r=%`yb7cte@3)y9^IHrJFb+cA$EUY^B9*`8yU2`yOf>3-x~;2CyT z=}lI@*@%t5;7NS?Ut~l2KW4*cd}o%_jwjCTdUKpKo$Wf=oV}xJPcFG4u3hH=g%kVl zV0ujHPj)1{W=C(S$2u3r;6b%QGRGmGG45+bF5F?T&3b!sqkB7CaiTMs)N~8iesd%h zySCtz5nphWXCY4P?@Ao6+{7P$pU3(i=HaJ$?xgwQORN)+fuBu1fa*F;ArTu&@rUdf zynOLX(Wg^^F3A5bn@(1 ze^QGBg2+>CZFcIX%WTco&s4yVd1SVJ5B8MaEw=t>1@&|N95Q902}?h}$8NpMQZ){< ziHn^Xd-+ratJdK#)%WBqa_^=Y%c?zKN!oTQdD|>f<^4hAq^=uD&NW3d&hGtKp>&Ptbxkzc zf5o0z*|C<%orpvRUt;08_5=O;SSDk!uTofOAtSG{SI`FaLzoeE3BpXdjL5ovP=qCA z(pp`f30&ZQ@96ipg%Z;Yg?R3Lmp%}8{8I}2hDQ#+Zu^Y#cb;GSUOVU7si})3_Q^r9 z7sy>fjsdx=TQHgFP0;kRZH(Yk9*(&lOs3lpL;k^AnQ`hlIBV7ta<{<)srT5#RJ$L= z$2Nu#v(lL;%_fC$PRhg!w=N@^zm}q%{S%mdJ2&AZwJ`EY5ssFHg)(YW2cfJs2@#JavuuT*(JP?I^?haD-uOxJ4@@Jb~I~s z)h-~X3wEFcll{z-*z?$)SwupaEvVWnM?hBI`zw+%k<4q_TGGqlhcX}mbxtJf@{@4D5zwuX1XAC3m zUMY6c^($@%@(7S!K;9^Q&Bg=|q+jNaq7uAjlVcUNY-s8S1uN8{j&z?v%1(6Qyqiae zPA6z7%7;uQp|AUM&1Ea8!xt0j!Fv$7vj=loCikf>(g!rj=tt7BhjIO%e4$>Y*VCug zSrX?F!?^7}@2JY1W%Tl{R^&;IgnM=Q3ibJt1%0l}ngq>s<;+VnsH7PbCA`{~q#dBR zRbexz@>^=?)U5%8>*>N7S6fovm2T)}=n$e}Z_nwB?@T3#r=iv3oXES21Gs%I9jLIz zv8W=9B96(HT)FcVk@&48`f_R*X*yuQ>3sGRNeu2#H|CBb>AN~}U77|7Gpj|^nysE> zbfr4C@KOQa!X57V9sju-kXB)CB{Rta(`8J+?`xf>p8%&l?s9+D(zQ;b} zzTnPh&B>C7m)JWA>cq36C-F+J!hNEBIcA zXK!{S^O{fMAGPP%{_0<`<{Kxn%j^t}uPk9dcKD1FwVg=19gXE3FS2i*yux7*29pBv z0N4?+0K02! z|B<-X&vwwbI>6eA4Cow8r-kgRL?V?hUUvx7eInXk^Rn0W&)=+};zY||kR zi*&gScdlVYyLRNkU{zA!-;?uix{S^CcO~DdZ~qgYZR4~|Hc4!O!iyH_pLMzda(|GY zEUIxb>lZ_2MhMVn)tBf-bu*ebIfi`C{YibA@)WiIse;4fW5}JMD=2Tx2gq!l3Z8v5 zh9oy6QoD@qBl)l<^x{PfS@|%5nlkVnYIyb$-TM+lmd;9~_MN?h%yzv)svlyA)ukkA zROefWbF4&4`Q?aSQiBFPi6MHG=~N|Kiafg1Bk?Ubf7T&tzRyKOo_o%T4nPuAe^oSTTpz;dU zPksVWJ#6x!|K8qRFr2cc>LVbx_iS!T9vf7=puI zQ%{~>qpF|w#;2CVlBr2Qsf+ECscoONam2Vd@-AEh`R_NO9>l&t#@aH{_(l&s?3*ll z_;D`^*d!yMngwrgtX7JmV3I%TetH(+e!j;+9a0pl$K9d4p3Eer zsWrH{%Q}T1I$RO=Z3amzsmBjbZBmTunxL4T8bDseG~$J;wkqz7NK|l!0VFN?8$Rxp zrr2yAukcHjlJ{$V;+yU}6}FY3igTy@2{CHMJ1Wx^9y5FuOr0OubybDT^vqB^ig!`C zAV2cXxjk9AHB(_>uC6eh>r2qj4&;Dhx56uYePQA>AM(LajqG^2N3r`vKY>P<=_JQQ zgPfkYPtot`Q=#U~sRV^;l9#jgE56K~BQk58LRMYWBrj%WD>gsR7ric?LLTnbAU^w! zDvB?)qk^KQl1Zyo$^OvOisVVQROamIq)}Ccd@wIiT)RDiGCkr)wrs7&CuGHnx6yN{ zBF8{7c*8@Sn}1D_6dg^)=FBCuEsI}gKT>Eq?w~xg7Ljnf-MHO}Pl}<*7pTx#p`?5I zaxAcFR!FiwQl9f8NGIL?xX->$w9j=7w4TI}vByi1pwg7SAJRZ&?2RL{RpZg)I4gR? z^|RE=An0F$d!!&pU7-#6ej+tk^Y^!3*UfOK>RK(1J$=_P)`QFA<+G{N^F|Gw&LNeJ z!k%VR6o0*f_iOEZxx0)Z9fcl>er#z^)Sd@$zgHfmJw?&fXzx0FvC|yx^^_cX!Qv5A zrRW8opE{rGGm55rt?5RM9&ihvQC-ND9WA6Ai!>?Y^s6{JdLb8Ce2R{KX+kZFx`Ksw z7jiSvK3d<`nKF5H2@lc@;>7M7>0Fz;X)&^sGbKP#r@9+iuylEk)Kj?`ip>v##~AxixG3wG+@ z%Z(T`L}W2ElQO*8p7iYJ#nnkBi4H}jQhBF35!sM&+{_6xMLO?OsM7X^WZd*&+@4kI zMRz=wQK3#&WXTU9_qmuAIjD`Ij@%kZs+JAmPA+>VN*AS671nZT+1sM(KHEtdCMRYVLpQ_ z4`Y}cZ*>{X;3}-zelpp&=qa;ZpvO#Z?nF#WN0T-EelqVasWR)$jYx^>2;!fm%ErmR z)5fEFk*H0>$tXsOnRAs>d3H6yjzgWNm%{0TF1 zzvpnWKu3qY9{+~kv;guuhZCbII&9E^SM-yMy-0hX5yWn|4!gVhC7pE7l+4~ToK)oL zussS@7%R3H@sdi2MXnC}<={YOM3e>DQbNeG{pzgGlVIjcyfr!b!)I5hO|V38Q;-3-eXfi@fbPp7a`bh4I&3#YEP3BO7zQ$?WN2sr zDb`D1eDnet+sLo@yTJl7=9VS1dfPZAJnb4zJrP1a+LqH7#tmXT)%M|E!I9*$!AZLG zq$VT08HfdsW6AK~M*5)KlQz82jP`B=eBJ$v-V^67Yc3t1oH(`3ffj%lI z?w5?v(3Ux{-T{g4OXv*il(ZFjlRnpq->;8%azD}eoEOOVLf7Vf7&eoX7duiNZ!e~g zM}5M>_6;J|#SArD7*DS<6%yH~CD^Ob3yrcdq~}LRkPV%005$&-J=-&&)y_CN0ST;DnVCYjb&_gy~#EhL+*9E1SK(3 zndQs9h`3mbY>PaPCcX(|vW9z+X+yP$de{Y|-!z};ndU`0zSkgYxr?ZEcO;%@LK(ni&n9aeSBx0-yx%p0xY`xbrq5DUXzx)Ri`uP!* zJY+BP5;>DjWrV1`PDlIJpJc9T^dXM-tZnHBvWH zfOLmR=)ld>$R5XQxWGaOxw2~X{A~-!6T>L{`9~3Dv#W%jZx})BgRi0Bg;J`z?hd^o zBaUcPB%r)v8!E5eX*zwrjF>_!&V%FzW2Tz0=KK8kF&2lw?s4?OyJQ@hc%}#E+B23~rg@uQb$vW}<=&HfOyGXa;U>MtcRca_ zY{I<_OQ#0vJfK5*jv>NR*4(q#`P34N*Yx}v2|3+i5Vt}5G!+v3jBea5B-#C)xQ;FZ zDa(m0{eiJ3yLANIshGbME_D|46+d@cd~zhos5IvGp3GAmy68rCZa)@oH)Lctq&P_J zAPFGxeY%>V?~30oH+3t2U+p?|re4X--qvngo*IbHN}NkBc?@uKuzexk^uBY6-F{QI zwF6d4rqrnv=XH7{={f0|L`_9Yyk_za$?-+kCF3?N6hHcwAgQaOCA0QtihoU;E78z6 zD!G~~7l$?bNEG6ol24~Ei(`a-k|t`sq_cjh*rI%<*RlEE%Bn-t~;=gk*-p0ZFfzV?_f_-;peyaYnLZVOBBy z_PZoC@|dJ#UAvN(Q?%WDgc~K%KTJ#J)akp;jT|TWebc(+d4{3eyx@=GfZK*8CpVe6 zP55Cd&I;^U;{VXpEirRLQOunu#Y?`Kx|Q9WRy<(Q$>KW}CT^xTGK*)v-c+nZ8@N@Q zqi||R7h>(BMz-%PU^`|NpfastL^F6a;qLbl zt{J|G(QGgw`#*(}J^J?0x8IK4A2A&t=`oYr?;FTYaQ=wy>s`i<^F`dpPsVKYmwL3z zt`F(|$daQk6*8-;2Vm#rnB1MB&Yg@O!Yusci~XN@kgjL$uv^1C6+04EV28a@Qt@OT ztA4+csyVa`8-Jcdp8t+#HOjrwqdNz2mfn0~5IBns%UX(7d*&3qdv1OQlA2tL z>#w_WtTc@+Ti1?U^yq+dI!`0F_fN(r(%!MO1BI8Hd6Qlb2BUYGN7xbJ&v5idOzhK4 z**@BJOp&oA;n?nk^*qFWeQ*QqA`}Tc^b{W`e8mO`!*Q$|Axn=O#qA?ix$aB1;~1Hc zbaGvdvo`hMZX621+1f&4FvlAoI%3O7IRU<6G?cu&H4(?^_TgUEx#3=;99r)8`LPP# z$N6WvzsHJ|{cEoL`tLb8ZRP(b=1)C)>PP0xnL}Vs76}jkGxu!Ru$3_XDjDWjt%EsO zn_-^SHkgOClRSHx33IWs;P`Bqk98DuPQsk59MH>$d07guuL$O5T>#xHpnDB;Z-MST z(0vHHPeJz;=)MKrkDyxxy0xI&2)aM`en(dei}tR=hIMqEGe^x8Y9 zyPV+i202Pp_OOm3j+SLOy=R4v~33O_!?A z34$?@&m(yvqt2Etqt>Pint`9!C*BpU?@3(R+2;v%Lq5)=K{Qh6=d$+UErB)UPyE(_ zaimxm^QAR{&2UdPPScz!y}Z%o+cFK|v!61OWa&VOZtQdUw!=`U4tam^XlgZ=>*AH( zU#R^KVD-v!;o8?QXRF~i)v;`rz;w<-q3sJ9X&dVFoVtaiN-g^LJg`>Nnew|kdvR?cYe!MFq!6wG2X24p(GjT`JlbbRUUeOy3 zciJrI)T}8w4)3(RUDg+ASf>fTW$B7$!PuZj^+2?sE<>Pg+g+pq{SceQj;Lf$mf-O^ zBhhY7MhfPL&>@S%V4s=DP675!7o(<#69T8FRwBhYn6uV%B&yhbR$x(LE1Gy#Ms#+$ zqx?NZ;RZHtVE%@?DHr2B%>H)BO_H-bH;A?TsQL&21#<3-)p%gEQO%g~x# zj|H@RqG;6`IDemT)S>XHAcC1BLdi06%03c3-1uBz7vm`+Nis6ODhgGbyc8U+_Y$pJ z3HnoFknN0Dg0HqyM15Ak+>j-)i1B?bFg2Vi(o2+)p)PUgsqPy=(D|vNF$pkMaw-m~ zM!yk^ww)%r4TFcC6>(_C?l%IHvC~9HA>VdCum2MCgO&Q>%JZ8k&)@d?3!r?TpnOM^ zmm4;jncpD!2f=M{|UhVXz;&t;GfyxpF*X7w)Nl1ZTy?}f9+QO-!?v$K>U1x_<5m> zpGb(W{t#b#mGQ;LUmu9SXl4BI@oCX2KHJ7GAK&L8zE>&Zdn?4hBgDUnGX7@+KDYor z3{~QT9pFcFEBxT`WmYSEIRf}&&xes5Ib_jbVd z6u|f9p?~mQ4)|{h`0u5}{|&$oR=^MSN`5#1{E-O!5vb&kaNw74;Fr}(ez^twQw;nw zU&%j#z)$Ugp9D&N$^rhuHdfA_O8)u?{N@P!mZ;>nGT^^l;6Fnp|H&@p2tq}+PE$tz z;m4tK%mj8#yB&Lc{KKC*O}$*ScU*U9T>Xb%+ww2ZvHw2(*Zf*u=kK|;O8tN4b`D9l zESP(AORmWh?Q{HjDjO~3>77&a0&Zx-I|T9M;D-XaXNC2--p4ZYdH$X&w<CKdF9QB9%e12X_oo)z^wlXm1$;eatbnc=m|YP3+qCc+@b#|_6X+gCm1hxL6%jxUNA) z($doCPW9^YN8*ISBABZ-YBzMP?*(#+(~D)jyYb8VJCrZ3(eCO>PYC|vL!`1arjdht3B`5l+b zg>HYz$jYildW^5Xyz|^Ug@3)2kV6|Q~+ z_fJdonC(jv<-b&$3OC%B5#MA3ruka3+(x&(V*YL54_*;05vWuzVBKW~@3l+#z(LO<55FZRrszEU@u&+dIlrSx+-s< z?W(BWB_mzd&S7fLUzaaS9j3UECLhoMaYnrEGF7WY*vS?<} zotN^+v)+ocz`s`nam=)KZ{%+;OjV2mz8%{yp4t88FZt9>(-n3y==bTAz%<9alke>2 ztC$fhBX2GzFfmu(%MWR3@-m5KQhu^Q4|ID6Kom1_6^zK>lYDBTR51ebZm@qZ>|d+g{|xkFTIuuWC#}xUUq246 ze^_~azI?x-e7lt8bBFTpf%5w*%YOmvn-2E92m3~YeP_V_#bAH5(*7c-ABR@;vkU4^ z(yIRKpnhjU{gx=}m#_c*Q2#Z``uBkL84vB#UfDjn(0*T_{X&)P_ZPJ9Y-nFqW&5^m zf8IZ0!9N}<{X+!)GpUvTgev{ZM(JOg;D1Hne+!lVr_shg{{sKDXyw1We~)hE-@O0( zw(|dMh!3k)@iDng{7i@V`T_A}t&Fc6W&AZOK0xB`EyQu0SU z@QWAlOO%pdynufg;2#4e{|p3vx&-`WX!3`j_5*({0RGyn5j7c*0XDRdeb4(1Grr8acGmUo*moUhfenl;3jH~M=QtGv%8`K=(*zqxVkIjQRIwz z_K5i$`q{_;uJe`&$UCf_U9KBMw-*O+st2{duQ3YXvQ)hg z>d?Sml&+x%bPeEA)V)!LNdx=MU;}+X6Uy6p3L56r!2W!-nf|U4z&RRCMOG6V*mZ^5 zXs0GAXJk7K^#VOZU+mo=UmA z8NTReego^^e~>LN-xwO^(=+?&u)}r4Dy3=_n_bp9|PIqWz zceFo4&n%R3{SLw$WRphruku{_(HSYX`Q!}r!oHDxoLoRhACYpNIf1D2*haShV45Dc zPs+*8&O{q#G_tpgINEckl+!&n3ylkJWaqk^r+03aatAYJBebrOHQaiMHeVyt&VR!Kl;6WGkFn`**CF0 z%wEyHAh>8`@%|lsjJ%jBLg>u^Y_a(z}L9 zxy-JM(YuLFtg7)lIzj@+doM<5UQO)cckgJ0tCX9*elZ$4tqJDUzNcprDQ8o#7+v*g zVk;Zo(?M9u9lpO9dHXf7F~Se@LnP%&-!DcFA#djKfj$g*t?I?d3-Y^_`)|YkGSKha z_(%UZ=-b2jZItJCf%ETx>#tH?e-T{&EtIdLvV3Eqe6~>jpvUn|2MSHDrNipg!bXv z@1wH)E<^kA?K`Da`}TtNe*x`p3+>+(+MoB2aZ3NN2mfg6KVINpUf^G!!M_^j&Ta8O z9i{&*0srIuGg9fFIpCkX|6T?E^-}sT@83>J|BeR#=KViM>Hj0a|M~d%sEm&d5Fc&h z=N`nD0mPRM#MgU>ueR~mHa=}2ezPHdH$nVvf%t73-+dtd6CwV6mGR#eAKKzaTYRAa ze@d13vkLHs$EWd1eA)~6bRF<(gA%_A0l#>BlPK|RJ>VOUf9I6=rvdoa4e;@|+aG+~ z0{F<|=TgAWc7UI1fS+ygbv5AcdnNw1D;?j0&u&V5_5yt7@jI#&e%}Io4_4y4C*Zp= z;J9;izc>T`{8aMK58xl3pB5|msTBB$ z=db3M0$L3G6$Sh?6!@)MD}HOse{K1(82D2M{ozk_;LiuZudkK-ItBQ(E&uX!7x{i` zeypUm-1_~w)^gi-x7y}gzrWR5ZvFmNYq{;aLl5_uF?yClcJI;=3?+&txlU$GR8Jur z^I$lWKt&U3buY%MqmW(xU>K8$qsg^RrcBLy0js&xjY$ey?BRW4CSZ6p zIbLqWRHO@7j|GHL852z|s2DQO=L%SrGKyI;A)4&1?7`Fw5U|=81k6#dXcE7<8>9Wv zh1KzPVvhPolXca4%+Nh9Y<|K}X4b4|@=jfsiF9{i7mpgq+zN^&`j54l*I%4j*)dz@ z-Ez=hpuue3=*+%3ZpEa_qRE8(j?5NoXSQs-8S^Y9npmD!VY=lyvBjx|%)zbEWR&?g zS|oB}-^S@PFZM(eb#V<%DID1x{Z5SR7}!(!miBRQWNW z`pEfcGP?OTUEkG#9rvM{*1Z``dWKw~yGGixAM;+&+n+=eyR{6R{%|Pkt9py>2lMb; zCY`0fIt*nKUKh~?^)Q$HMmC+ab_iSTdzv27K8DD3cF}L14rYhR_Rxu)V@OTcjdbFG z!R+X%8|Vxpex6_=-4H&A4f-5OFSdyxJw_~|%ZdiFmu`F0pNGW2x6VB21L_0Wfiinq z1Hre44~b~=advE)UKcuVWDE&{ImXX74`6dW9x5t5Vn}g=CcXB4e>U~X7R5fF7?P9m zN^!}!KRacOq2k7@7&80f8O4yme(ac#CGwC(F=XAQ1Vz$OTUJfIR=9e33>oQZrI=LT zmsQ&*6KTiBkZ+GR6pnH0%dQG77X4ZgLo}V!1+`oIux1JsDqu|vIjB-0todleX5KNQ zoHxagTi;woMZ;}a*GfbsZHpmB@)S}1L2GtS^>k`ddJHl1IU`cnv1X00hEaQW#}M1$ z6`~~(R_v|ZWGW&H=21$2h&F$+WWV@tqh7*1%b%s4se7|6*^$2csF#Oh$i{cQsP*qG z*s0masTId!NVUp9N@uABd&oJTx^^OljO#>ETiaW(Si6|Icq)e2tBt1SWb|fxnqH;C z&cu*~?>(tp+?yS>;5PN{Yz(<}TuL4MV9q92Kcsr)Livw_E6P`&eFh|T?_ z)VFEoY@dv`R3qdyog=BWX69_a;!o7Ub1`I7h>S9*GGi5nHPn!Nm}fdXkt(=o#!9nm zsoju2idRyzv&~q|xeZhm4XMnK;5ViM&N zXU0yg{6={|{)Te@RptJ@px*)XX{EkUdHyeR{+z!zTt6SKKVEtLEz0u2hxb~_X9ne8 z1Lb#AmVYqV_XX^;1^b%7KDEj7DIc(ZuF`(96H;m))Xzp`{dgY z$3E~MP4FL)(tl#XznZ|ml9m2drS!j1O8?v1d|&t({BsNVrwjP!L{Yk+4*a*L(tk6a zY$zNF{vD+BZ-4NAFYy0{y)uy&`2R6wd<;>>$9;&Op%6bz=n{D-#E&_|*LjGq`ze3o zD@_@H^OW&7AL8>7#OGsWe2#$l?G5o8qm19q5a0VCz6U7dyQeb#Zz$v64)Ea{;KNKM zK3q}ahggXp#egrb0AEG`zN`Rzc@Frq8t|uCi9cR|Pc?u~tCjd<-3Grb0pGd+zI{;Q zn+M=uE#RNK690I7ya)LBJM}kx81V5q;OF#K_}La;9RPn_0DoU7@wZzWd>*I7@5@U3 z_EO^eeI>pd0sg;fh5zr{@WXcC4@cmSLg0^?z#l7sUo=|rOQw>4G?e`F8u;lk@RKI+ z(^B9kTFGCNmHbr+{PqO+ElbI7H-Z1Efd4uu`A^h_A5Q>(#shzb0e{8=f0hEjb_IUj z0{kiher?OY{5=5wJkP%y*jjG=zHV!|?YpAX)>^i`b^t2d6hOYb)?{!A@ z`L%3Dm_O>aI)G>t>LRBLwd}p;ekgQB0O?!W1v%fTWebM*A+aogG_>oA9NyHjaY4Q) zE-HY~v-FWgV=X&%lMfoO9OgvUbVCi=b?oNM>BxO?0I50H1D&?0W7ln+hMvv~AQ>wR zkh7?c-L`xxdNTv|CmW$vUUe)bo`M3W2aryACTQ)_I@Z0(3r(98K>XCr(9n%_?C4#d zsC;w)Ssd3JErk28$NeUw^R6%t+`tMM-Kb+n9ri%jIe>J&XM=3N)UlS`CL%Yx0CMPz zEsF0}&ngy=M-MFm$iCwP&@UJG{wwW{)C~g2!}Ehsl7BtB{rebnM<;-w`l0B@O1M8B zFd7YS7eL~%6QYjSvkNDWM6>IqL_1S}tnSvcWlM%5^g&7{cSdOY&w93Ml^eSIL`uvz zx}sUu4ea5qV&r^NN^Y18L(9fDu=3pmEj}+LiMb%tk5kaP~(2MvZLE1xK_pQA)gS zO+z2WjqLdQ_GtfdDVY-JhuC?IY-ZIE^lqM%40{)ViZ(Q|X}W{aG+!y{;5Q3hgXix$ z;XtH1QA%uz=c4QIyj8w*0IGA7l9VnB(b4aX?Df2UXsC;nl#L2T!%Ujkuj;nw>HsMj zGIuH32G575=J!EdZz*{@e;JB{=h3^5t&v$zDG`kiM_(eE*et0Ps?m|cT#P96c54&+ zs@?)QcaV~xyci@o)x=KR)BArg_uf%aY+tu12$BR7N>))3%!(pNckR7_ZUY%b#fT!J zm?I(}AVI_oD4?jAP!I!1rn>^IA|jY`!kiO^qhP$N4%OeUZ-4i`G2R>BAMcF8aL-d+ zyY^mdt~tA^t9GHk&4FZzLoCue2j}Zkt&!)aK(eA{4eI}}iTysX8?t^KNKzlip@UzW z*r6s}QNrUuV*M%}1?x4l?Tx#j$h(0g=WYU8Zqdv(^s+*&uLr_94T-3_Z!`PK#}f6s z7)YAq)}lb?W_H6C3-sn(AQ|VFgocl7X6a|Sm`Zi#jF6_S> z_UHRwAoQ;f{i`2eeS8yP{FN|%7a0E{7(YKhMrD4}VE!v${%>LaJ~02Y5TEBle11cG z)Z@p;x3v)8T@YXO`1ASsBIG9x@}mp+yCCE*6!Is9{EiXw8wUAR&;MuO$8mulHNX#b z{%iw&9TNEU9{4p9_}3)xZz%9jouBIby#V~y5V!Dq2=JTd|3QKO7QlZF>SI6D#|xo8 z`1-+6KL?d#21KYyq{_4+J_`n414w=>kQdVMd4`acBq zzXa-k3DiHY4`&2@_--ZrZ~D;-^rc47m+_!4>iY8w^eJ1=r){85ynY=N^lJ?07q4#} z1$}!6`lhab{XrkC1bsXS`lzm->iVj#zq~&C3i>=1^f?Li+f_xsMWF8o1%20EZ}H#s zU)>*6{o@q)$58N>Sn!uv@E1Aw3-3QC1pj#r{=@szZNZ=Hz@OCpi}yE6@HZRqH+}H8 z!Qg)b!2b?`|23MoMfTv2?ZF?@!5@EuKRSYc?g#(;4*to2fAapS3I2K>{PivPtGfU4 z_iFRr&Ht&kRo7=wZL6;hppI472T*ORt`DHvR)02q({O91*ESzKc)BlTkQhlOH+5sq zZScWCAAG1hz$Z3!W7yR`IM?2XDp(syM*P#2={VO1&+6?>S+9#E3x{-NPWk#^gKM7D zkK{;FBI&}^4)(#$_8t`87)fmUSTTbPeXvL}ntHuCl9WENU|K!##^?1$Qa@87iP2JX zh7@_@V+j&!+4e|s_?jtW5bceZ6}wO#J0gjep$QY`=8b)`5EZ{WlDsqT#1yph#<{~q zlRI5>nFaWs;I`4}-Cy}a<26$7c8g^?tL zHejr-dg9)#`%;Bvk)(ZVxE>JciDypiMO~pI$=<%LnWnCuc+XO6${yB0pE$4;vxW1( z`r|CA+S*96z~&E~HPr)uZ)HMly9{fuocvCQe{;tk3GJ!%w;(>cpXjj7?%4CT0hQAb zNecVDp+9za$6s|?Q+J<7l9fH5(jFzFamU_&#J2AvNz&JQ^d0GF{9Ny|c+J;HVwH29 z*10|kuarF(KmHj>z7D@YqnV@dy-|0>E?QCKT17Q|`Qu1DTV5~TVGu>$_hsqf(Ic_5 zb(Q#0hbVGudl`MlU?d(IS1j&i9z~x1K0&wLIRcM|A4h)7Cu@} zla&&DG0$H-6t3sE)Wy>!?Id{SI!ZirR1~b~7EYTVbHintw&L$zQDmd4uszQ@H-~=Z`M!x{KhWBZDf3u8JbjoiymyAp|?;-l)`% ziXxIDpX6af37(*BF54Xq*OTI($qRG{?(^79_71KWePeFR^BOQ7?iDI)jsra5qI`)Q zW1FLivg(8=(lDV~{(U#b-M^&C#;%3yMRGe;82^Ybl*J}TkqXxWdGuHe>phjqI>Ys-$qvWmnVuL|53Q6f1Z=qWnB3DH zV{Z?cYy;p3VLK;mA1x`6$HV^pK9|Zm!S*wSMRHT<|6M{$|9{~4esKKb4K2s-4C9l) z`1%RsI}PLi2IKD}j6WjaqI?m|FDpM$b{6JG!~9Rc{I$GW=3fc%ISTQaC&Z@`;eT)(6BMIuK7u3%np?(6OzOF%i z8T@RiFTVcVq5cjC^`~B+jZnY$p?=+k`aLPs_s4Ek;>S?m_k{Y75bA%dbBjKNj&9M1 z`v+U}qpzSJvp`=SfWFiT`m#*WpKgNwq=G(u0)2Wd=+hF=uN9zQ(*^ySDCpZnLEq*J z`lqSYqJJ@hK6V%M@gV5uchJuaK|j^?bpq&bSI}Q0L4RWeecmbPb2rfM51`*C1pS@_ z`hE`deVL%|9|Zl+67*je{9z6FgNNV`Ip80<;2+Zk|9G;b#b3e&e>o2RqXGVNQ}Caz z;7|R)pR5IcQu>#@;9rZu-&pXsA6Hxa&0Fxl6@vdA68y1D@W&YN&$Hm4YX$$5fxq?y zf0YXUs_wta-{tw|D^=U7>%pkD`QP_d*CI*zB`TNS@h>S^+^v+~zxQf!#fx6AO4i)( z_V4|68y8)x(B3z#^zf*Xe{sn~sbe%QU~NEi*9vUe14K>9GjOlAj$fvs~M~g8%-~{A{u8qwT%2HJiLD z_}?kwyKa}|+|ntZkh!{oe-^lSNU_YNyhr)&x*Zjt0Q=b7knQd5TK<|Yt#||Y`}1a5 zZMT`_13KNP;P1b`SlnLTyC%N;*y(Q-w*Ysm>m|=RnO>eVt>u2cUjr!ltm-4>)+?+l z<*@zJC4c$U?`(NNmP2J8;D-km$QwjA%6+TdE4KmO=b0e?8uzZe;>GmJ2*A%Sq{z1f zwyNmcxUzBz|M`pA^1AnJD;|cfs}upACp|7td2U&u&upvg4ES(QT5e7CsTebVU*%i4 z-_IzhPTupSW5v_C$17>Ta~ki;^X^G2CZ3R0t_S?<%p1A1t$)SM0p}|H04HDhAvanc zRH6UiMx`-e$Hdn3mEVgi#uYxTyz(2?JUwniw>uD1ac|eB%8h`t8#>b)jwDqiZ2Md3 z0(eHduC!sREfqVeb!4C5e!?HaZRzgg(kp!BMzUkNQy2_3c?4w%Z?6l+7P2+X#4A;c9yFqbC)E!UAN2 z00-N|(fyyltT-;3D!T#CCpgz6&`0*Zt5{PxLlz5|kR;m2=u?IJ$62xgfF&D~X`}xC zROsCel|6*}AxGtJpiO=>RdialK$ZbGV%H}6RoJhJFExv0V*&RG+(J*t{#%iFZkfy& z@U>4{=>g7~l@C^h$?n4Q4{au-(nnXdstmXtF3SVFcS9OIf3sF)=8Fi~YQXciZlnFe zwJZG(M#&}so-u1XJ=U>x<(jt9vf+UD=%>@M=UZ2L^p25P1NMkbr`tH_RDNoVk+lW9 zzdD`nv0SI}MQE%{8?eTMblNOgr?NUFR;H=4{iU#--(O#4f4=`U(EmuGf93IGgyXA^ zZ@)19bYc94Fux-(ze&RU`1ucl`9Bus-w)z5P9;98)Z(WeUuFCag!m)Kj~C=;l#m}j zf4Pvq7$JXre)~awk1F#E`JVy#w-@ry^TSYu9|3Co2?c%?0>7FBek}q18LIHl0{EE* z{EQL!84mnC5ByCM_{;NqH}E@5;J1?h?gIZWLVXxQeb@^1u|uez2%&!X`dS0^^;xK| zUuyL?6Y8@a)Mu7ZpSy+njT7ouS>Jbr`W`OS{{*4_<3S(vK_9dQeNfkrxu7qHL0+GwAC?(AOeCU;l#s&IA4JA?U9i=<^QH=R855>p{P}gMJ?t^!qXBd$o$b&j9^D z3i|&+(EkhI4_@F8Cj@_30sfH({^2M1$6xT5tKcsi1b-O<{<8u62MPXj3H-?r{As1& zPnFXLc2)2o&h`9NS#>aBzr3TODzIiJ)@EOV(%=wovnc$oQfr#4I3%PIbvDm zb4}C-aP`5D)CNl|vkcQhV->OFt=&gzrkATs?A;nofP2O-WPG63|CGu`%-2OjICw_s z>w9XewY!X5*GI1y(0J-Sm0sm7D~K~h;WRw6wD27jaCfXMVM#l5TLv1w`7NazG*Q+& zwxr_uMadMIBu`UpDx37qkoR zL7(jOlInAOne5y9?#Q$-mejs`PAwiBDeL89i-O>u^c|a@QH!+VWUC+dMG^V1p0N2- z>bmh-S&y7SXa=mSz9Q{0HGIT+SwxxxvV?oowZA;1n$kDRUha2B2jCv{$C3uB&F@qh zEPIK5?S^L(*W9NvS7pfN^p&E4JK>pu+`AN`wM!=7>W+q|!!u;`ZK~JKy|NWLzQ`gK z=C8O()!XOD9&8+k8sHxF%Hr!(YHgk@q0?lPkPM!cd6k+q`M7Lj_H@)C5j=4IWePny zDZAGr1Z|Cld)5bEq-KmOlbzl<4{1illAf>XsBy(IS=#T#XyM9O(k{K0QhZ}&!#u;# z-KFrI$Ek*@usAKVUmc0O7sB?dXQ;atH8RtUv8X;2;y?Qo75e48Y?UY;h0KCAFh6tD zhJ6=hn==!U`3!ibF^ZuMcDpJoxSxdHPl+V~T5{_8!W*(fdh5}rfLLOlR6#Mxw`H3< zZ$#GP;F$=+GAd#5Jz1R2X0*mHmMqRJrk+|i$YSnnLDt^j`8`ikKeHam?yXNjpWNX) z7;}P3dGti~txFox9|hm(rXHi}K0K5C-n6){LTKDz6%+WLpwFUg*>n`d{<_B4iv@A4vI6MlrKgt~b$wC*MV#(dAti%1D0E-Q_XW4W##W%@I;MtDsq0K zjQO|=)x!2;UDGL3*zWbNW&dxmzX9y;4g2%`AA|mnK>w|vfByIv;rP?x_^sji{P<46 z`1E0XA7Om__~kHuI~e~w82<#A-_`|LREX6_S>(6>KL4)}kH-+7REW;gCN* zzx9w`8_4f?$SD*PfuSO8xB*`ui31SEA9wH{-k-9- zpPqm}UGQrCuYc8mf2{@o>H_}7`lcwz#or?iH3N=c9gT_sA8dV+Vitpz9$k$_$Jx;A@JWIzS~;v! z8gE07H7}sfF9R>z6oKLrZ0Ot(Cn(bu;N2rvq2NRty2s4pR8&|jnRI6*nzPo1)(<{L z>4nFVAfGUJ9@vI<_B~1!t%B#r_AN*I*V)j=dgN1ak>HgVmZC?=HgxIzJZjl$csIcH z#mH#`^tU>fN{)#o6U!H(+>JK0N2|jWw+7Ci!{(#jn{85oiz+t7U) zw^5_AARa^fkXyD5{c%<*b#MpN-VE9H`|$ zDbhJ)L;LkuPxZ`;B{{Y(Xnd{>Eg76d$&bSGahJp>|A-CUzIOsOxd60ok`vNAWdj_hamqGHuQU01hu0qme_O~h>jN8&_+X+Q%>+*iks30eJ_IXY*;{DgxYzU zY=fv$i2ub9DgbK3ac4IaS8hX#UI$WlfXkr=El_Et4PE#%fRdhzC4PCG(OtO>U9B^Q z%B+L$9(&rOPmB$1^UIyOeKD2{J=6w$t>OHgxn}JF4pg`0iEnf;xWAhBoip zom%rSmdrf;fU-JoLrWVhDCRMIcQCp^Ew8hoEowVam!ATE@7GiL^{_Tx`*zexcz$yA zkZOv%U_;L@)2D)7#*%|QSgP!z4gIP{n|k~zmVCWfPHntoL!Y0jK@E5lODx@rD3{A{ zyyhnHNO(ST_1fdqUBI)Zd=?LW2hW#YI6`?`v7sINz860Q{L>n@$ZIkGj-8IH z4^fu^Kkoigd;)Nr$2rs^z&`FT#ODF8Uvh}L1o&Ksm*PUe(=BtUy@2lv`>%xlM+27k zY3cs}9RD^Pe}{1VW3DaZi*9NeUk!|Z6O8|;F#aF?S*ir)XMIVVYJmBv&;QAzdMXd% zlWp9NDunnLb-Y0>f%pxo??hdK_)UcPc7ga}A-;V4k3#%A3-Nzo&`9-!{Pa6uM|FYx ztcUzXK>mD%{MiWk)fDnO1M>d}@-GwefAU}pKThjOsL#L;C4YJe{7F368QlYZ8EcH8 zvVdO`1^(?2_=ka?Yk;2;fuHL9<@wzV{B9KZt>k}Of&Vvz`gkbR$JnV(NCWCeVYr5B zhWb&~S39A;)a#G0&(*3I4M;DjJ;xf6@hiV!@xB!M}#7_}6PSf3pz$PcHbM zx<6Whe`7@AQy)o1~D^C)1+LDtkJ1O?`*OaxsAxQ8HP(}ahgovk3yz38t(ZUsO!XvhW?OPj zFLT8+Mg>p{=6Dk4088$!>tV6xfQeM#a!)dOq$TGanIoQPJBe~w1K7cmJD7Gr>@s9B z^>ni*5p}oZ%s1>48;qGk&D#y}Ftp@)1!aqK`C-9EV$^fRPj$H zn5u5=MZQH^aIYe^h+ixWp$1uakrROyoOQrP@sDA1sMUkK$Rbx*ORrP1II+WADrSTi zvF~ZYbty^|=V;EShE4S%Z?r79p8ey**K`+B$Ci7MBTvn_Wc?`dw4RHpn;X5zo>S)B zo`mJ%V!x$SN{$z)-)GKIHS@(!w=SoyGG0Uy1E0ScEEYcsqqg7jB15N`a|f6yVrRUH zD*WU{LY&OG{qz0BZUvE)pP@JDZfwpy`063H84yj0?Yzm34`$q*U^nsZl32>u&6}*K zHRF2jcNS;a#!=^|c@v);Gw%KM!D18^Pl+SE$$(fhE>EMk_;+;zwP(9Gxi-m+YumA# zSZ2AFvMTf@-G-TQnG>I~&Z=jZ0_>hl>OgRm+m!io>Hd3#L`jF&AQ*LV2P0@@Oo8Y~4KBU_$ zQ_kl4Sy4NyE!2ZxAM!}a@ z&6<}=B^~r3Azw_mEt*?JzJX~}eyI=9d|<+Tzm*{BjurCgMEcM_1qn z&mUdj48{#$xiHBlR%XKzr2BeH-LXGz&{H3$Mdr<@H0c;r#gRmem_y+x03%7 zf&YAcY=ip1LVb*b`ssQvSbU}-j9Lfv!`GLiN`3M5mj(4#D%78PeX7?lU*BC->YK0s z=TQG^h59c5edrGQ&?M-CQa_#x`oZf8>+f&Q!+vt4Z8eJ0fz^haHvc>U_AqF=ne zodSL91Nznv^o`d)YtX+uLH~GtGy{D!67-SR&wZeuu7Z9l^)*1ySEc^867*N8&%uH| z&jtOK%sV3PA2xxS0s8$!(Dy; z=?VU`Qt%%H{&ehWp?DAY(-!b2-oHw~zx)ONQuntK@V}3O|H;7rczftGfTX!TGmxJ!RFl>UzqmZS}Q$W2<4!FUwc7b|rSMo~VHa10FH#6+Ju0 z&H3Xi4Rj37nTlt;qJQ>tcdoyyi9W;if;+ok(Hm!ub?!Sr3;luX3-xbb(T-H0v;R|V zbP3M6W_!M-=hZB5p8Z1yg;c>gocuNYO*_Upb(ubrv+x}my`j<1WanTnLv#tQkAJ%K zhJNI;-FZ|}JCqIQbRCwzrThHY=WJ?ijBG1n$#R=_w3}9e^YYGcUvnv}WBTG9y?6%e zY#VBc#=v*njV14CvB@Q8i;mXl;|chUHuVFYZ1&jsfN?K0{3u+Xjr>R-p7YhYCbTc= zlN(FomNwEaqO?UO9R?%C0XU~w_KE%()J|ls?TCKCIjvL7XZqa(3(;UV3f$TiLnIjw{1_rJfY@OY0q5}L{hH_}K2t^Kji;lm2)KSet(l&xm?tXSGaHS7YYf3DKWL4#2+>TqzddbU zEV)_plfD{|D4N}ACE7j{&dGoNqVx4PiEcGUBgte~vu^Mo+U({w(dv)!=-3#DSMXo@ zTInv)W_X9nwb8KVkh=zxeej@Yz>5v&3|ya#ZqQ)nXB-t#4O>v6V=U>lRFiR8Uo3im zDGhZQ5KBxoTQQ1da?!Mk43yb3mNaf|#XR*qEt<4F3$?O zF5_}WU%a7}0yPxIkbov#=KXL(@mt^1sB3-^|`KRbr_73(qWwsaJSifYlR9Wf;AxgJyD(@8w)-g(rtErvuG>od0>br!pftw&W` zW5^DXK2t0)6>IIffQ&Z9kf>?;OkTK|czESS^gcO;xJ2qRgQCpE2KkpzU{Va(kgCt5 z`dWxrExHWXl43}ogZj)rUo6B}=L-57A4A3!>N6+iT8jHFzkf^XjAAJ3MfckkX)DK@@W>8QlXbmGyl^sBiW9=k?(j z=)+;qhZ~>|ynb8<{kSaXhq}J-`m+P{XR@F_N_~1I=#x^vG6nro>f3xl-+2A|tfGHP zef%WoBd?#%pr4JPpMyX@mHPS%^wkXXRjI#EKz~g^e|ddg2>QGi^tl%FS*hP!1pQX( zJ0<8lum5_W|4Rk^=lx+R_yZRFf%lL0D*nOy%V+SHCxXB5{&N!iXA=0&Lhv7@Ke@Dy zao!I8#QWDA@ULL-uQ}jfN`LDC{x$*pP3eE@1^?syu}JX8i{Ov;;Gf?eUeN)E-JGMr zKb8Larvf{l27gue-yOgIvwps6TXp?>)wcTD?d==lP(G~XE^1RqZ*3BzDDqyCty?0Lb@B^6T{+>9pF~+h4krAIQIN_bf?Oe+EZ6ZkK*yMcoYG+tmjF( zcn)ZNQ#{fIoW0>Btpj+SUjj6$94ezd0%J+;q;+UUr7iU`qMW`nHI~>muS4_TZX5Hl z74-Be@Y`;7G72rXr5+Edq_0nc{zt7xGsLctjmAW7S7#R zx{DuN|99VvS{K?#uU^Ra9qS0 zI%ovkAGRtL4LkyO7Y(VVb)|5>+Rs$vpJz*Bs@_j!Wn1NzRb}o9XDvep~8!mpb~?a9BUqAOl4J#I^g- z@b#d2+86Nm`x&SmVE4Fsx+7qdf1tm;w$!iv_4L(YfORraEnvgSdipTn64Oj{6!7cI z^>jGkXq!y54Y13TdU`zIuz{H<9`Nap^|TmpvqL6|1f1SfPxl2pTAYa%0JhP*K$`u)V9W-Cfwh-6r&v>Ce)$3QizTJiT=Y;yV5cJ`bpbtv@m?P+iy1w{< z{KFg1%Y``l_zK4T3%g z3i`ZO(C-m~e)IZnq@wTVLH}>5=s)idJHa1j3;tjx_(#3qAL{4&N@#}{;l&Y|$dV+t>0>9+_^%!91HZA_D z?!T(37SIDn>xY6a!9wgw0C3mN?LLTtSmEQKHtaa=!{T+!Ngbsb5opy zcNdE3Hn*XFJ1cI-*VFPsT`}G5h6fqi&x+e%P%V#~CZb)gdXNhPt+?cFXXRIlo#{1~ zVEYg&F513EZf)pHzpVFwYaLeH8Sy!}=iK4+*7F`@>ToMA*1c9v&N$IS&UuhVkrh`l z>b(4XZzo!O)`J8iD=tw|C%?4Ck)C$OgQO5E?z>~X{8IBUy7ZI>S>X!v>wZDLVcsxW zs_-Dc-K@Cde=o?lJ#nDTsyqmhTEV-(FUmzh4zvyDL0m^zah?D*7kHi7>}<6 z@>zLZ9#}h=ZsNxW<3HQ^hMYXBz z1Z>4U`gB8XX9(L*dk`mxSKIzK)%h;O{J6*sf=raUQQ5WT6!gSbFG!mizvrzZ}glOP{nPF9@n*PC+Ll0mdvEyUB& zihHYnOMWkS5Zw{-7XkUq?S4yMF@6wz6mYqN6?e}5mi(9JAljwQgBSx|j&I2~N(a## z;KZR;oYlx%@^54iJplMH6!1EqTk_80LG*mUZ2&JAcS|1RG>F~^_y_Q(!-QM%#g2pM z9m4jduzi}a-2pzI1pBua_UHSzg#Nz^{qx6Ps&agOe5YZ2nqDpAst{CjsIU2k~15@mmA&+XC^cg!r04e48M?dmz4i{D(sP z_X_bJ4*Ai5{PYy^!{_fI`)3 z2Kd4Arx)-i6!`NU_%jmtmFa(7uB&TL4+qTi?+x%TTi~CPpTz<{)%m*%_`Fbs-#q_s zsPKOo;4M%ekD)%If$zG2he7@1K>gGM=Ig5~)K|7pU+VRztk3O2eX7?lU*F%LzAp>) z&DVdNO8qPKp+?XLrGB^w`oZhVY0wuhL0@?NS)-yqygsc5eY&R9C(y5rD*C0=x08at z@%pz7^eYV>T9u}ue|=w1^u-a^q1G?4WQ3i(qeU%bCP zRq;38|E`1o9TogF6b8@^ET9!7(iFv=YBNbj6s@>EDn+pu+HYKFg{NnVVluR6 z|CKAc`=%(2pxwP(t{CT^q9{6JCK(bcS3C$vQFuVRyrW!EJ~c&gEiT7_cH zniRze&P?*OQ-#87U5cWDHIp1nD_6|hlA<`ym`VB?mMhBAQxu!v{aE+o$`nKPq$vF5 zW)hpPrHUIlDGD8#nItN>RI%e&iei6-nZ)mMi6X2dMPXNNCg~|IQOu%K6q%)FlI1zY zijXrYiZ8`xl2eAoiqQHLg}4afu%bv2dObz4tk6ud8Oi^W% zs>sMPlXQM^R8ieGRgu5LOfqcoQAPCNR7G8endG_VQN^=isfu6Q%_Kot`HDZHRE6s{ zh{^DL#c7hN*qv%7+4kUw!bzH{FibI%97#T+@Ex71*trE_E;^zx@=8^Z&1RD5&v}Za zzNreWO=gl6C-W51V^bB+H<(F8;dzRFB1m)){%AtK6+9vyQ70;l(3)+>t z|M&l|{5%DpSN1am`cds)d0aUhS9Ltfao&P)D#tH|@h^dSwSsxAgn6mX*GGth8^l2w zpL~dqGHz)QH`REm##tHvXApm7UK}AWs`*mp(Gl{f%&#BhS2gddd{E_yDt}aYrQ}-> z@J*G6s{B;ttty{Yd9KQTWnI`nU8vTJY8@%-s~6OlYTc>UqiUV1)~~Xz*F#;a*1M_> zsOp1KH#pD@rJmdYJyGgR8R(3v{;2Abs$Qw;m{Q-;LEn_RHx+bGsfSLWhf1C70y?SG zPh-%}L!he(XMwk%tEzgds>7=Kto}Z@vR4dA7K(*X|v{Ogh* z4gwthO@dtjues=lJpq?}m*6RYx7GXM{(!xkB{&8!b>0sf0CxKc>sA0>UgL)!wzcC@ ze@pN^z~VE0_yl02A;q2D9muXKKfDU?NG&Oz0C)rKhn)fE=}7T@!0jsh@HZnnZl-}0 ze*)aU*bg5A9M)EfJvah(FC*l>&knd#w&R{$;wk>Znp&0YQQ3mrRd z-a;v!G}eL8PJTE5uv3^6xAJ!&o&)`GO>3A>v=ko)e8a{MI|2ThD8&Ke9LN+)Kb)&= z$6eb5pC9i)-gofBrhp5!!{-5S*7L*3T6Wy(-4Oo?4rJtCU;ML`9XBLLihl#P{^pC9 z0KRxsiVp-hke=^-@k>oR&Z}68r4t><_-DR22=IQH6h8yZ-1Ef^8g^W@LW*N1Igp@h zzIZy|vU8B{$uQnJU;ON^Ew|#56z2ktKJAO=1O9SDiXEmnkl%7&{Ns-;H}Jj`%K+af z@x_|~_jn@3;;9aB51TKx0et196qf_unCpvA{kG-o-%D}7X%1xNeqTHru;er31Mrz$ zzPK%5jqg(Y7jRgHFJ^w(a-lz^I4}_So9c^~177`Cipv0-ZuZ5401wj|fpw=l5WV%j z_|s2YE>mX&_5(a~tuL+wyjy<+P6Iq3-WRV2>}5Ct*8vWW^~HgJceEXW{{U_i?TbZ# zQ`(P!byFNj*C=0X1=zOZ2ZUUVAf7q_R|9+wWV4;8I@$H1;E62A*7@zw12dd3aIsd)F{B?!+>=fdo z9={Zb?=pyIG{mikpZr;@*C z1^%k@Tb=*v^)Xtle$?wrz5dkeQ@wuG>s!74)%8JLKa$k+MO}Z?^+{d7)b&kW|J3zS zsh`DyeyZ!My8bHl`Iw;3>iVtJ_XmQ$4;1u&g`odRe+Ux%LES&p{YBk>R;c-tx_@m4 ze;Xk9TQvBW(*H^X|5Nuzb^lcNS9Sm8p9}s8=TiLpw*L3_|NT9z@Er7iy`z(VCK~=z z!T(vygzxV^fB*Y?!v1gX3~T95=>e@bl%@FHvppyX;-2vFC_upN@ANRon5u_M%(iwoKqxTZTO!L)39A=uf#myK4LB zsB^ED?Czg+YBe>%VVf1~$;_O22B<^NG@^Y!#!|G~Bv>~VLq+XI7;DoKY*CS>L& zx3O81tGWa?va+E`ZfRWxR;8bL$L+g1&5iBliL0kJvp?SYyR|iY<8mo#g3GCkzHXZx z@?A?Jv|XFm`nWZmG;!Pf)YUc8+0$**qfu_oCj(r+mAbh_Xiaikp6Tw|G;5gKU(*q8 zM=H9zmiXJa<p}_t9nO|bJ;Gx=~@|-rkKU} zxZK}R=(;=kieh59w@d$PYhBM-HYt2gdbt#K@Nyl2wN9md8tHQRo};VQDD6}CBAs0N zUkr9#_2nPMjub1GuAwJgtDl@zv^%2dQa|gv>(MuR6jAT%NH@bCZhyn06;G_!lU?)u z-EN5~#qlU(Vr>-f7TsT4kysyzCzhwV<$9c|N_yA^`{EsLdXtY;-Ctpelj0vz8j|($ zZXZ{Z({=thd(lnm@1+T{SJNX&@Vn!! z$G`Z!Xf+e{CYIhheHwAA#*;+_dc?yyhJD!Do?U9~L9ThWB?I^8 zu+6FAY^6vjktJkq> z7wy6urbKX$m(`=jW?zi;jl}fo6`bd&3VLa&E>0Y?4mZSvaGlz$V92`?WbSky)?^&d z%^b6YS=ziA1wA$(W!&tumEM%s8MZ&#MyP5BHGHUS6e);h2Q`2kbm($O^4KGnX5+CHdu4*^3Zg? zy=KU;3Nt-C^s=6O@73brVX|m)1=giJz8~(bJ$+a<)hCLadwLKT{HbNGJb5WU?y!_R zcDRNAX`{BKs zz<$+8V%`seXK&6}k&cnZ>|N7Brftm#vSfWv@~f^BJ3ja>vp0ee^J%?_$*In)`6UfD zd7g;0D(**mB%82BB{?*Sx@GG#l>=*C`78%m^ZgUI|sQ+9Hn-YmXoPvRF0 zBBK~ncG9~(tkHUV!Zr3Mu{%uIoSk-TjjaPYytfw_-OHFg$62$Rmx)RJdUK-ZXvDsn z+nF8iIg&KL(IdAGYP0d@TeAzg`jgWBuW>i=7v{@|=gbUPFTIC1jVH_RFkvrbjBUVt z@@C~$Y+}zbVG$|J`q#^ePKGx&@HotLy6w+2q(u;?!v=T{PGzoocVd=aT}@;iicv&t z91|(2quVWn`-;ymLZ|jDX8aS==*-TsM5|yVy54RsWAHeJ&VqZX`0p0{AHR;B@{iBw z!t~RwrYmjSUab7hErNDuXdi&~9h+vnE`Jn`8{k2vm>`{2|Cn@>ka~v<( ztwGin&cTb`iHP;%i+JikSFn{sG3K_LlWc!evbFXC_FYhlO@b^*Z#NTiAoK&k>eorQ|7{1dEV@0Jz49K$`5STPlf6ifs19V)z2ErqlvDWYiZ-OTXFIZMq5)|o z(;yx6pW?T+tw_V>wq$px39+_fapL_~5PLl`xnDD$Z~PlyU-})hsk$WT#C}|htw_NB zKiKAtArWU8VXC4ZIl1&JUeUWVX%+g4>Xtf)^tjxBZTpy$eB7h^)n`M zZL^rmS4Wbi!&c+m&`zXx@(t$rA$MZ_ayTB|rz@G2bce}pl#n3P&batjcM|$3hmkFl zkXn2RU39f1`rEXbA#XiMmo1Z#;iY!OYtjtV&E21zADlp~pKU;n{Mv+u?4LlYmKjof z?wTQ&%I~y%oBy6WCwX`2pWR1XXRpvJuNoR%+zjnluf#G@;yCfoE_TfE>Ibqv=U^R@ zvE#(w0e4Mn!5TOG#a{s1w|gM_3)?00Cy1K>TPPmNegU3jJ>lQ&8Y>>keghuqIR4-M zhQu`di!&Ae;;-=eRX^|lyZW}>B^07 zQO_GQLolD(({ z>Flk+IGxF4A5NE&GD|aZp?wq0$g|mmTZqgyF(nT3n(1~&_psL=V$x=1d-C|122)#= z!3K>UL2fx~5j0tkG5VCumK6Dsp4tt#}LCFj?)w5;th;9eGf?FxLk?jopgSw_LW%)g>hJQ49f8rr+qACi57=p9}N3QNBGe?v%nDG&VQ*Z1Oy-#f$0Bs+1wJwM|Y z4w=|6(wtkm!-RA1`WoAl4!1 z@A~%SY!`S>)3&R);p}iS=9V5Az4Q@#q1_j}V3`AHbu}G_2kUV<0oueRyC=E))Ej$0 z?9YAk--d_&u_NzwhT_8k9k|&M1E_bko}|Ny33!X+PWHzAP-fNMCFFix7yQ?IHrwk* z4()Ye6^ScJMpVdp)+Vl&UfyvfaUZb+1(cp<4{)8BBKrj-tfmthwC*i?@8B>d_uEWz zcSsIZu>K?K{?Blx|LY(knw&x9&;7u5)E&-*44X-`NEVf{@)P@RvxvzK2_lupw^G${ zP3)bSE{x-<>158pMHJib7uz^b!n|4>NX%x9qxjn7&-wY<e^IOyel_}z$N>}icbKp%;+HY1spedjJOc+ z`zyv`cfjRa$BB;tF1lbWmH?J)Xu&xrjsM-hdPWP5n`kT^4cl8kYUzJ%UQ7SAPh0x; z&g>xegzZg2|0}a$9qx%;k)_dk{Qcrm;xT0-PDRFOXYe^3d1nUcI&=*-NH#&K6D#n* zMTe9kQVXOIQD;FN=d!{!rxjkb7aR1d@r_QJu|tB4)oLxA4_o(}lS zU!#AwX9Era+zPhuhVA9T=hgQ&6#A9Wc`s$7!^#L;$GP1)-cc0wrc?s$S5-cx<6ec(BYx`ReewhP4UW;NtV{L_U5JTT{@E%+G3vvyYA=T3lx~Q>IO# zw;JO2^L&kYZb>TM|L&ZumP8NcXRKfk{BkP%0!0(AoUU*Y{656C+$XL2ZkmEybvEzYY zlv$C$9L$d*$2+`7or(sdtaJ;e`EE4Hc)JNDE&4%e40NFRb>@QYzf)Cf4^dhhhEg{# z!*iz|GO?rcbjo>q9kurvto?Gmr@XYcm>Qe@iPC!bpYu;XkE$LTSYPJSzNx)i!u><8 z6QSKnXsceg?6G(|=J62w1XNa-$ncow1z+R*zsmCX$zcWzLyM%C6{h|r-+LOsT2Cfi=gS@OwZ3|!t*IFqJ;jtmA%7n9cdoMh5&w89CA%}*b1|ETp&;}A*f-IK^qXPG zJvk ze|etp9O2vidak`tcvX=7A;(&159HfjJ2(|Tn@{c@x=67ru2GH#XK@^8_>DefQ$h zxNJ7COrPwpwIH3Q9m1Nao7sW|{mD=H6}+zhJEo+&8QESskT`t`COX}m;a!Wz*{IQx zxXq0P6w%<6Pqz{|NT-{GI(dAY6=+sc+<-dsO;Pt&0mS}C1 z98{7>78OMVR6sGZr+dN1jFv~98o zNnvlCA0jB!(1G}d*|!T9IELL??TMrRo-4!qo2HB&0GNt@E;7mhpX8zlXq5=^5=l-JX2WRTEfo1 zE-i3Y1vr~I8N?s**`XTBf&jnqpl)mfa=$mRFVZyxHt$Bk&v{NTtT>FFs6SG$El~+} zIQoG_IBD?eGdc}<6Z(xAypc!}_+$_scH z7tG%pB|tCY3y5aO1U%xGE#F=6k{N6IfEzz_I4o!w$RA(#fC;~|SUl(8Lg+WTi=-{l zKrSnfA!9plnEJ4R%yc`3^bPFst-=6!mJv%1x{SiVpQPfKF{>bA^I|fh-4<{0O2STW zSHrseEdu%IIlrW|-lnr59vQ9B=@v07fxC~Lr%Y7R$=>kV;dgb?m~PUA<# ztv;?OV~WR?4}p{n2R>TKmh0KuMQgGRfafFU@i#w>=DZWuqNGilkadmW(*&ukf!!!H zF>VYzFEQhX_;KQGt2L4D8!K?3vg^%3Qlo7KZ5p&`(H7VsZ2rzfH?6z;#d0;pKPb-o zbYNmN%~f7BQ~o&WQDux?8>6W;2~gURdHllxCno8k0v?(Z0WU4bTFsUdF*4oTabRpb z|8rylwTbGHK|N*6R_Pf2n$t~Gxpx5>97<4!t}iceL-?`6VWRHsfK919cbARDqaXuZaaSH7Rg^;J_{ROG$1b(`{56cQE+VpL#$={VJ1ZzAF^2p zv11Cjo`o5BzNaKy%u#>_pH6O~mp2Ymn-8m3xxinO-V*%0i;E8P#dnvjh8Hsqk)t(N znDN{wTx1ymS1LV-$K0dHV6qK%EeZye>r=SGXh(dC--H>xnQ-Mn5~u!62L?u)V};j~ zplyCQ`gGJBLUw;aj{{6;e(+>$bHyCQWEGB3G=h`?XHi!DNtCT|7GFIT3197BGA64tP=iYre%lrg z?nP_amlf+#xSSe3Olu?j`1P5c|8O&E>&!rTG&lSf9hX{kTR__biuLH$c+UQYg|FY+ zFyDh4&$1GeoGC6&+A(oQ_iUVS`n1*I+fhvL+gMQXE5wP=VpYMj%mt|kn4cmEMkTdY zvmAz?odq6H`0E3Hb*0{_gV#Wo`Cf4N*9CliU4Oy;wJA(=_DYy(=YW+SZ4!KNb7Xy@ z>Dp{t1p*nvZo!M0>Y`utId;xlB={>+mzk52AUgVk=9XKeV6P{`m_^qPag8BS&=H~m zvmSpCyfU0Xe4f)>0ew%XaP$^TFCI%`zr4e#c8M_XXXjLL{#x$Rl2hpLvrrh?Hr;B9 zsUGrNRgR^PE`ru8zE+3NCm}(+DqNpE3zn>iw>osgxdGZ z!IrOhe407;VhgL`GZI+$vHT>>g@UuGuh<7u7%6i@V+H=|t^%^qXd{`EieRk7b#gA)nq1hJLgco&!kVCcB8Alw zo^1t0+)}=Z8$XQZ^R~m!EcMSv|gO&XCE(Mh3f&q}c^;v-CvSc8)^F;zl8a+)Y?6|jmwZ&VH4wb8 zSrVJttXKb9*z?I(sHtAkyjh}Dc)e(=u-N}dbMmt!VOmV7&}?xFEflasD0^Bgyy4o` zobhPBaJbPGVL1D;`3-L+Y{`Epv^b~SGOe+{ki5PjJW_4aGO*Iy=9fW@P$AQ##j8uF z`PNJ=;qC0#&5`f)numXX-0VDYeY3$xPn%=jn_EsTv1t}+_Y<1+)V1XMjA=d)Y9;*c zE^4_qV{G$1RVSfks<`D%sCo0v>R{oNmLo0GUJq&(J7x(3Ju6xwJcl>gv{nk2tEaYn zi&nMSGU0--NmsQ+<@`LGNBiyzRs0&8-8B2ztjl{ZtSzf+&aVxJEj_Zf6FyZmcV~QP zy6{=m*43-H`E1yd=KYtnY$KzJo4wa1HHSUXvAy=Wr1^BjSv*$Rls^(rbGHr-hbfz% zV%ruoKC$i~_k>jg**s;K(QeKMKguL;Tu$Jxc7x%|HAB8&Q5zBYx#1yo`f$H`2yb=n z18HeLf_lac;s>Z1K!~IaEV=B9`Y(~?XKow;5kusmF@7OFyx(*sDiWUb9~+V0x{NU!520U1=%smpsKTv)Gla6*LPXM>^uX|nrcA~pH3p{ z_D_N_$p-MIL6@`0mgdKNGk~=})xqS8IU06@KA)RBs2D1N?I96Tww}P}t$c(p*be~D zO;VV&33w;d6S&J}0Gzop6vIYqKGAJIeztD_Y}XryXBbcCXXk9d&DRFN`w{^rJMH+9 zi6gMGu`;a{Jsn4$nM>yYL&e9#)j;!?4K1TEgCD#)!q+LhZH^f#TWmtt|8>QaevRja{-;pbr!i1b?~7&Ln(<9iO1RX~4A#O5+>}0+ zFS8zu?Mlr4{(kHAq4fS{^?t|w7nYF7%uqm?85!u}g$s16fU7D^@x=>saZh&;rvJx< z1qJkfm6#Qa>Hja_dw1{BecjZCAOZAv&{xhUuSahZo*P<;nBodzDiztCXL`e=_v6y7b(1avKc%>kC2rriNbJI0CRxjD(9R8*zAaxmYRrut-iW3T95u#G1Ft#dqtfMYa2)z@#Px ze|4x3@3AZwrFln#)zL&eqP9YO(`~QF;(hf0xZj`m|Npz+8{N|@1zN!d8471pAdzjkibiaHQOc=R=Y~|OBpSeXrwSGwbNp1sqHEj2|)|pW-b>bc7wc`w;rAh?N zN^!vLuSWHf>|M%K@-eXg##UrJ zJRSSD88F=*QLtl~7LwVu4WDc+7c{($fb%g!nQ?jf*g{-ub<-^Z{-poE^X$KTV7>7M zz5cI88e`BGPpzJgHM+$3p;Z9?G;k|YvnWOPr#Ior`&RHlo4dg`@ z-;n->dSV%)k2fW+=3l>3MoTxI#I?J>aKvFH{IIKBB; zNb5#~GiQ;zODC`qUt)Qul1gUYG<&X5AqM@3PT(~@yhg=E_UPtKM|?Lwg12&H^a3#Px)zN(d__;Qk8}8%j7weJ6Yu3 zr1>yzpgx?ieaoi5C?QizrogznBOqG%jGZY_Mc#k202MbwxV-KuTaa8uO8qThO6Cx# zAKSw|4=E!q{U(FMXGIuaFT)-9x{0Xi+CfOC4D^eY=SEd$ksSB=;Mu7GCEvcWg)4WF z#RIM3)pbo!W52T3Ruqw(ApjF*yvE8g%G}MJ(PW;A8ytDb-~*8(I7_3yxL4+})X(wX z>F>4S_4)yN*L&!TYsY?_WJ`VMe)iKE`{J)%?{Q4H3Lk8@joeevhlceWp0MFNfj6s( z@SQb08KaCX?&XpA4FgEpzF;sNBZ)-M-~7Ur%s@m*2#=q(!^=Z zAH<(9nh$Svk0YV!CoWZAiO$ zc^^5qD3t#l*u@OVdCt{utt3Z-gZaU^^c(KWMttvaGOm5F8Z7Z}RQ5d&mv|~+EvHqW zFv=Huc!l5s6B}-Ce;P}XoQFNWI5A^yB#~eCtAH*zgX4SVkqyncB>27`G@VYs{nfIG zXF?7cKF1e4SG(a?6-^{$=|*y+d=8xII*T_L4&<*73?=;Q%hX4Vlr)H@g!KFJarXUK4)Uk?Gtv{`WQ#a!0l z*B7>D@&p*aXCl;hrFFa5IZRdShdoXjvoEiigZHILz>siU>NcDa5fw1G zI|r_0uE+UWubCYSZsDl8p71CA|N3bDwZ->td)xhsqbJ)?pX{<{BaimQXNEjPv7vsr z=vF<}9O(}~23g~Av-9wkR}J{w)Fr@HSKu0z&sg$oEB<`j60TNX!0o?>!Z5`>SZ|0n zTrm8CNB`1<<#C4imB}z#D@+ou2foB53$3uwY9fTjox^(JnK*Icaa{C#E{vR+kFTy& z$K~~EV9;a@V~=gb3l=;>^${b%P;3dz1RdN{rpLYtRfM=qN6;Hr!bLoO!zsBn;Ep}3 zVUUdyksbY+bBOl9$2LZS*NAd%sE#!!=+?s@scn1noxNhm&D+rX1U>x3Egp&!{gIo= zI9y5Ry=Iz`5bu2g)$j7e_vY-ydDOo5C;k8WMS9;Ieev(#(v#Gv4^%;7*2KQpdFqLJ zAD@9_;z7;&YfBQKYo;al!e#^aX~}DG*{HQ}TQq=N`g#%#bri9d^Wve&ZZg^a)C^y! zeaD`96%B`V#*>s6X4og@E^BHQ11Ez<5Z|k2__1>lyZ%lLY{^t59${v9PvlRrV)+_~ zJ1a?I4vfWf?AHm-jf;hqx?j1=+s9xhm&J_K@>n>%P=m;HokA0B>zVX#aWMbIOmfdE zgqwQ%9h06M3roU1$%!Nd;&oUWJ&lTnI@LL3$W$fr(fJMI;~oPNit0r1t}5BwS;J)4 z#)6{U4vxzjNYslhnbBqOkaV($9auP!I8+D(&I=OYPx}A2`Ae_=QHA;(GpYZvFFvH` z1r@O>%tFT_oL|m+e8|BMuFNJ(7COK^9ef*4TM-JI3O!Le-3w^ z@dMXgub8$_F(;vV1A9DL2HDoW%=N%VZd%MM{3rdr<8FX^xB*HJ@ZzyfyE%8w=LHsbL?~7=!G`3B2sMMnTBvO@d7W zCxW);XkJn0tALL?&72&F!RY2FUVoMXQ<^V<#QHW6tzyZqy4{bFxO9)Xet8mF z`xINr%Ys0r3qK223S+hR*zTYl?332wTNaKUe<7N|KuVhiPZAsi`bn zS@H?z4OQn;;ybXSsv^|>e2I&QD&J#!8`oUw5AP>D#(&b^%fDXz`*$4wi_cLXt{(N_ z-ejdG_r(Wh=)x%9PmJ<1InLy(9S9HDfWpjWY+L0z&bZJBs@*1n>p@>;o9ah)S^NYr zz7hZ)CLB|r^qYP3ssr11;p8O#$k zJM1I3mX|6E-~=C1Q2F2}X5#b&82aG|x_@dPXX9RtWVFLU`t&AL8{)#*X%yncHnuQ& z>H@T_u7Z8}*$@UqYQdAe258dR2-Z_?9!S}1LiQv%=ymlog5xoaGXgUqA!*| zngB1X3}Al17G{Gp!v>w20mqijg~k=j7@6iEcJM%5NVM|>13y}OuRDz$71N282L!=^ zLPh37{|#)U9*cFqx`Rv@Fc6=_mfn&ADMtZZH(txcUU6gR`kTR@^!M7%d+YUh&~0Bl z=s{XTua8pgvuI*p+$288Dd*2bLz7=x!I?yeek{Sy&zy>k&v`I8w>&^e-HzXRbQ=?n z^Oz7;54@Ln@fv>jnD&QH82;EtymHYrUd643NuK?cIVNietA1(nW1Qaz7LR($_~y@p zyZP_Q=yiXIBjTfzuw8WpR_SnnjRm!0LNWUSE{cbb^);A31XL%k)>t7yV zbya3VTHqt%tCWh2zEz1@rF=oY&6W71EI^)v9tf(>uK{iGb8eZ%baW}=Jv}I6Rbzj`OK7ckIzq@W;nAjHw%unF+EZ+zML9{WcBc{H|bdO*V({qCifryhVMWwzm|?@*8E_fwF51;~ zlRG`#6*j*s!IAgn1?Ap*xcP@e;d#nD!J^T1f`O_5q9as?JPRBIXKqU|0}N6{nUps# zt~d#%%MW3espN>ZP#*nBzXIi5ul?X1ZGG{jo?jCQ^?Bjjt0wiuZEJim4Rn9+Hxc!ADRXlR|sk8WPWEq7KxPuevg zyU~XqTP)(t3=9zG@Br6@&gE63%D6+CJo9XmHr)KC!W(Wi=T60&vxAm8z_ddr2p@Hx zwc45?u3EDiMy`t?!=v@tIYwz#oKp<^Nxwej+X2egsgg<17f(02(j26$WE(T&z0C~! zrsi0Xv0cCJg^kRDlxD{%^0r~=&ut7RnKehOQLq)OezMsk=-2GCslV;+dyj2)re1Bz zkyo>Iz0+c|PWeF7Gg&R$$}Rae-xh9fnt=6ejU!gs_&F6ejVT>$d$xRz4bn7hzVJ@b z*86p|jbM9Gv;0q4+b+55HuruWZ{9Rm+IE9`e_@J7OEYPdwhjBNCQNcZ(>!XroNcv> zitw=KrRG8V6m4_n$q93hwl^1#8DP88`B+;w+l`X$U_d9nFd_{f zvvucZ8vJ7Pj(6fKun#-jo6j$GOk&((zhlRlcW_&OGyap7n3aC11tneI@ke(xzTlE6 zx2@0^LVintU7i$=i4NyxF&>hS{laD99-?DNSgD&<5V-dvuFLBr5?-ld*lzgn(&{k?P4URy`+T&pks$EN=O$>*Y`rUr!tIxu|raG?GgTKm!xSg`=6 zO`AsRlFtPvCnvaf*Ax8w{DAs#AUZnw@44T!X{pp_lR=Nk1~s)U^te2FodSAn5xrJ1 zJ-(b?uacfqL$7(5o_Ca9S4_`sqSro2&pkuWy+F@xqvu|w=ia2}-lh8`BnFse|DE@1 z5u7Tjqc}NnS(AHDiukc*w$Sj|;wIY`6?V+DY~fz38BNR6g4kL9*}|t?tfoNX-0 z7LMJi-?TCFB0Km;ws3#=aeRS{qZdGSDrBYE^aDQ7{p5d%oQpxnBL@h@wNDL_cmc+j$Ko^ z-cj-Bs;$DYs}?o|x1@=q=WG#bG%Rk)+&@Wt;>9MRg^hdDnC+dSQRO+pdvBLCSy@Jl zx^`?7>WY^&-M-s?y#8{waQ43CP4CyAJvL);wlL<1Pg7sMS@z-El0JN!@&A%7L~ zjNpZg`d($``oRPc{*uH_o^u)1cM8nnrwI_A_7M&LFoTKjlw!PxCBmTo&(NX_8^)#l zt6;EmA{2+*L>j>iQ()aKh^0AJUI`ab^!v%o3+Az4eQhG#J97fD^CmEBb?*qgE+s+uCoyg>?hA%CC4xP=iZ0!@V$#K3g4Vo5 z`c8a|ZkAg!qiQ}2YL?QqcmAO#;U9Xon@Z#R$evmMT9Mg#CjqwJ>xY;BUc@AOsWR&d z6Tr<*4UawV%uH$4U_!hS;Lrd~Y~k$Ad==|3oMi$m>DI=>5cBaoL@zu+d`-ha|vc2TdG$#f8Z*(qU$eOMu_I)Uhk)$UGKm zGQ+97T&AnyGxhVCnTH254l5JDFlqq)@P0Nkzf_s|ot*&0PXRBwV#|D6(2sdmmjHVg z%ixN`h7*D-wCoT6QMh;8x8($!er>b5!5h=Fi!j$S$mr>Tc-C2Y9SHQ zE_b7X@utj+Rc{141c{KN_71J77{jfEA&@0nP zOiHB$GwNpo@YT}z>k)>LnJvpKx|skRrDx$k^gO5ZoE)Nrr@foQd~#M{2Ck?43sa-E z)P>B|_v%dO(gawjtbvzwEoM9~XfYuu0oIGOu-`j3#6?g_)+ehjaVUTEfCX+$+)R|cFI$ynhVr}5kHe47Z6V#t1y<{)hw`VKEOCbO zHWGGwq*czl5MGs;h!xcH$U7;iVdSQzn4X-1u zDk0*vE~|LyB3pd8^aw#q7mF*>SMo!;h1e1uCq3IHi}h<(@C|gzopp&Lq9!dd>ImSE zAE*9}$t~oz>nG9K@BaL0AHb&^PLb{V&Wj4o{Q0r{F`g-Tj*QvcD6$Us|8lN-Y*^Sy{^;b(VAUs z(k?&VEz}0*Yo8>4WpeC8JAXcPy)FJkcoLQQh`pm6z`Goqj*H~Pq?p!ND7zEDYrmX{ z;UAd@am@G4 zb`GKZS$;BJJ8u(NF#D${vN)7~oMwqT9^{biGd5d2?+E4BHd^36$4~EEwAY9JiMGD@ znyU09N$Nu%RT6%*FHTLqj$-VRxcr|7h)r-XtUhxU-LX#M{M9OnY*;X4 z>`GD)8w>@%PorJe*K*5uSCYAz!Ekjji_~n_a)+o-{ORss=rO8BC@qnj?^#7`*kEw* z--$~1CU8@CRFT-uV0f@_J<7?A=OT-%2vQG$jbd-a`NVOeB~?UWUI?tQnt%e;W4ZXF zm1JFR2t>HZpv@&QTtMLg68+qI%O;qMBPHzO2A#%VCRVUe8L<1#Y)P$(o1 zcq97O5Y9!;Dii+&p4Vgt%55K zapF=guOly)M?stFLGDzjBPYC>LTqSWanJcW&S0kl=RGT(z@bR^?B2jxbT8s=D`XOL z+epyZcbvPtdJ&f;k`H0`TE<$>87Ea{@WU&I3xsyJlw>HA(({wn)S>w)0S=kyhU8`P)^3t29uDl8+?qiA=jEyW@B`Owiehp4SwT`I-yZEtuwO z9wLwn92CbIqA#dpR9!7lH6D3Uow4z(DFwps;3 z>tByigfmNqzc&@kbXW~bX>N{Z|0XgQwb2}|Rp9E|g>Ec8K~mqCGe>9~*|$f}k;}4E zWQ-t*$uV6Ckpmthhe2n_xBP?5_u>_B<;ZPxA@MwkyL_8bvs?kSUoNA`0MFmx50brq-hK8nJAs1ww(ax7NKkQsA@{qntChm7fwYUA@&+*eYAG$9d{Z9;! zDvjaki(zI5QI@Ra_AXckF=xE6gJTD|zTyDa>bMLFLcH+hH63K#?h5Y9vSpC(yA-?D zc93hirJR23GGI$QaZ+ao84r88vHO;Rp0PWQ{oO&*Hx_bwcb0+M8)v-WO$Sj4-^T4U z^MK?_+xMgddQFI@r~=jr1dd?17tpFx5r{=Tx>4tNHiDA*TMcK9meT zgxZPcvKdxozW%Ud#YbfIrJal_lVapI_`|rV4^dNV2gwfzWsG-GS=_#e&K$c!J}s(Z zqG-S4v>4GqT~a#v26LDC;*(;k(9@u6g zyYM<;@9CgYcYiR*%S7_eu9IWOhoK=0{o!XsDzcZjK`Nw2pcH$5$RWunaKH`nbH^}L zH_IQUd8VRe<~PVdR~=+%MdM#4W+JU+v>&B}Du?@nvFR3+v-t+G*!GRdmGOrf*VF3Frn{)eva~8LG3g%4`g)CYyVM`IbN2(Cz<21Q?llte{I|GhoFA||rE!GeRpM$N&)%2tgEBQ` zJZ9__LS3HhrN4Z^-%A_cnb$#HRDEUVC-{P&<8U0Zvz_cN)a9~_e8Hk+G`3f3CvGy6 zIitUP;Mj%k~hP4rwNh>*Zn%gRM%NFbVwvpvlNnC33atIdA z!Ml>%NEDq@#0^>wx|iqU+bwP6MAcRafELG%qz{9L(%F!2@Ki#5yOS;A60aB2tfSayJW<+coJ zqrC8+kDn)XzPo~gIrowyV9oh^YK!=ULPF*-It##-&?LQI6FGGP z@1qRO3y1?L!_!PsKJ9N3;G*quu$S(?M)x15`_t(DFxd;tN_xJru{GAG=O3ll2kSb) z{(r7tOz&?-@6Xfwd(r!kx9ntol-CMw(C2fY&-aWzKP#*iRMO|aPoF=9(q~KQbD;FK zQ~Fc_rO+Bm|7lA9PD=kt%AW_6KT|1xd?RtrY|!#{V*-))q?&nSPVQT}eB z{69zeFQWW!r~J31^0`3eGndLIhRUak$}f}3ubs-Tk;+e%%6C;C`DRl2k9kxnI6&op zpUOX(>c!|)&Q~h+%suaAY`nj0uXFsaHwp4$uss2V#{dJ}K9Z2=Nfa>>ls^7U({~uBPKTY*t zgX(`f9UlTZKD_Aoh@<1<&+*ec?s{Veds|;TW_IxeL}Li6EeACA#mj@%qN#?*@Z`~} zx$XynaCqxlv`gj~c1l^rZFm+4UnP=|YQ<6fdhH6%;Cmq4U7mzis2|1a={JwAZVA**Kab<4}Q{yY-ksj-l{1 zFdem;mf_D~8<~>2P}n;(70LZ5#&I6!nFz%&aB5hG9LdvU?a9A4)_QAMM75 z*Ywe4`n`E_c`ULvF2cDpCZeAEVesQ@6pC-!iD$>oLgC8cP@oloB90egcWyEIZWa!c zg2ParZXq^XyA*x42?y_oq3Gt50_+*&jYiI*zc(Yokj94syk`AUw21Z}KMzB5h85z` z_ZK4%+V?PzK=(rnvChd^X#5P?{}G8sd@00!>_qe%g~Mi#7&PnjPJB3G2s&*_&tDXW zX1&>k*K^Y7m3%myyPSx|uGx*BJ-fh^wuix{#p{s3V=s<*nZr0{(cees6tp&j>hiiF zOtnQA6wOORQ(l$g3C*9a@aIk8SRLtvXI z6Fm(%h@ajsX3s1Q0k?TssJNyEYZP5$_q+;*H@;b@`$!#@I3~rltqTS-l`M29xgMWO z)#56L1;gh>ndq+45xk_uQz#p8avax41r`P7vYy0e-d-lb$ z650*Db$EWSEt}XEOAJe@@2zd!@|!pR+fVUl{|`Irzcy8me_}GTXiR2b{BKQ|23iAV z1g!xhpmlJnY?D!Rcq*ssn2R6%3WwGoiD)sG!g)&P;&u8FFi9ANX75er2B&Vr(}WR_ zQM3wK&sxXbdcGA0`q3Qi4_;{6%e9<~{Z_muB?6?(T~K&y0+)Mn3%->X0cyF6&^l_< z$&BBE`JEBqRki?)agOI2mTke2^qVN4*$K_?Pvi!-ZpAnDhr_N@K4|;fbzJJ_?bxU= z4D7sPk?;95&b4b79-0&i@!!{@Wjivt#;e76aYG1=1K5OGCuDO!y36tEpb&W2e=ADY z*~n!r-j6TFg+S1^E$A=ljhyy?{di(2)v=~6Xn#{Scixo7KR*qDD5ou`d|oyu*I0(- ztV3a3-DY&PW&>Bqmf(oWP>4Lc38_BK;#%DI;V%6!h%U-O2|qJAJ$^SHzaGc9tNIkH=uOM3@)>x0DpI)W2z_Zk~!d!%vk&;O%F&p2A6=U@4hyrbvS-&B>Z6wYFLE}ktJ0iSi&Ajhl8T%>U> z-ljtNc`X>-%3jB%=;Y#wgCk((XJ0gn+UQ=^Edu9zlqH=^^f z^P+IbU$h+cf1Au599)2JEeV7BZfnqy>~t>1VK)x+4uy@!)}!Y?GPxZoB{-)#1RnTr zLX#I{bIy7d|3f}^={NkVwk_!Smu&8W!hXDPe+b+jz6CAWp3S}2ufP#KA#h)EGurZg z1Lss&hGXZ2f@xe1nxeIVTa{CSIT8v>%Ck|lau)YNXCIz0ISl5MXQ2zPGPs&myK!}O z7z`@QKyv5Sa|Y~Ayqmt0Z7!yxX(XMSIIRHh38C}})6nm`Y1~Q69a!~HI9$?CMS+vk zxVEZ1+;Ke|2CYs((4NY@=l-XBddFn%yY%02_b>LPb(5@VOs@rv>FtYqYbJ&Cso7)m zPL`jXEFrFL+aelb;sz=Wa(r^Drg%l_MysE7u8{Xso;UBFD$a<@6?DCIfr~DR{Hnt~ z;(^0en0K-+(0ZmHpCDQ>|D57W~b_xX!q!r=kDML?ar6wyc@vljo2@KCfLo?l{$fF`T$-rWS{s_+BRl|_F_0<*N<0xwNY%dKY-cm>kQ`t z<$3?g<>Glyl^I=uD;&s>;mt!vi*E)y3Y2Bt!C;*fFIpfYCP5ma1B?f}x+uxV@vlX{ z7k(0Xm3x5fHA%kV=xfnHw@;#7`#iv|N0OgV@>-M_{7EF<>H!jZQhZ>>YtiKmpF|&H zJYb8f6n`+}wdi8mC(%y_4;WV|#h><)=Mz(De&e(rk;07+qP^GMAv;EzSK8SlT9fiYH06LhgkP2BeWl)r zWQKeYrG!#`TgmW`!`_I-)V>$(ncxnkdt~@=oo_@I*6&5xpWOiekl|(LycLbU^-ko@ zyFv17S^o5%x1!e6ccS^5-QZ}lEI;S|TT$}#cOvgVH}Ec#<*Q`hiHwK76ODEGpYr+p zok+*vzp>!G{a)N#^J)RDbM^b9`lP=2&ze_HPss7vyZ2(UUk{=uO2UM1a(tfNKKv+4 z5B~Zp0UsRY`O~lV;Sv`;$jy_0%N_FkLA4TGrKSfJ3KGy7slexCl;Xb{biuy-7j~Pf z$WNPBj^9nwh0QO2V1>c`_#dA8aXhaBcRIh}8eJMQdZ-es8R@{zZC~)haRYc&sK&R~ zXoI%oC%WF062J3jEzV`Npm4%_{9~&!-~6B+=f2T|@F{Qbjdm4&=IsW2L0c1UYQM(Z zAT@sY{bTsADH@R3`2z1>G?4FiPmE(72Z3+JQ~WSpoga9P;7K9sa3;JHk2^SspS-;p z`)wWw_njYLO`^d+m~;{^J5FZFr1Om-mXhj2Asu0vV&RtXl%UJEtF_{edL>X@ zfBApx|MUDmuitzBA${)O`+V|!p6@4p{-6Im|2+Eqz4SfoL*JkDYf%2&`-eZnDSvwT zH>D5%{^W08{`*t@|0$n8<@ddhd?ToQd*#3D|FHL-QBf@2-zdR^S;?q?C`p3I5U0Cp z3nL?>+3ItU4J*(^_kl0`uz9x`<-3i z<*lyoe_#Kt_eT`lAOGGz%Ki5DZ(nQrBJ(Ne#B7plk3Ml~O`o%r!rfXq=NdN$X}N|V zJ4Y#8zjKcJA)Sl*uy-20u~Hc2b&DGlx&YOCIiWL=QW)6j9XF#g1ogN6z?UUS;Yyqu z|L$5iGB7gWH>{A-dHs42$?Rz1Q=ADuI9N*cUm21+cb5v+rrqNG#!Km(uLH>Dd&`8& z?^!I?QBwM%gClu2HBRu}-wRC-l+wp3LrHV?GGXbm%lzRbQrIuiMX%kb^XgUc zkUA)t?>c5N3NYJ@@ULai+_;n16fZ)f!n)y3R!bq~!*M=!!U80-@x>>sqv33oj9E-DxRHz7w=mH;ny$n%ZB@)quz({T=x(N-+!JDe(sEHSITkv z(m*I4UcxVa)CYNquHc3{^Px>uE^n3ko3CxC#50(VT>fS`Z*}uD|7_iDJZ0?yi0Ed` zmtFPe^Vi+P7bXY6J@qth!RbSs{`^ZgWMv3c-l{3FKU7oV-k##x#8B{!`XO7W_ez$N zTY%#m7lD`GXma^cUlPCXFfP~_1{r=ENx$}%$J*{`vTdVK~IzPa>h43T2zS?!(`gg~Qh98KlQ~Etz>!E`Hf20<8AB5*CU^ zOxSyHL`ei3IoO-Tz2C>3N!*5KW<^5v(k{fIqCNkCJ@0E~MuAViE~L~%#Ji79!+lwN z1^a6~i9yq39=oo_ZJEyJQg>}K39aA<>jmQ*6JvpQ)+C9iGWbT38}|2$gJ)q~iFNOz z{Or{|@Z-JlkafHxd3o$Szio2`dhR6!{!|yz20iAv-|LZij1-n@7?Q>5_59oT*=Rh= zN7SgwlT|z0p$Khu&0#6LSTLQ)UUWwnKC!q@8Z1vlpp?k^7@*7z+fXI*JB@m}mYmsb zf;2}RL^)UE;f7Z-DbTS(#~O~Jj<@4su~96s8t;H0_8`jo6c3hC3F)a1$k1dby2r-5 zarUX~$UJY9k(q{^3|U;{Eh|clK2AVu`>aG|%+K)GA}M!3HUkBuM4*4~pF?c_4PYgS zmDcp+j&qB;F`tzFmY)k-)6EY};m2@Sa(7q+%9!O2qT!}6WVI`Kdp;cDr|xi$#aGcD zASOf`$4;z-5 zle1Zi(F89aFi$su-TJ*q=XtBp&5j;WZ)Xde7Ir3Ex2K{*#bW4J;{taJf64CYWFt~H z5R8uxhJoqNWldjqBN>a^IdO~!QFDd~H1+_P+dom3b|n?r23x`_ zS4Q4#3t`c}1e|tN$Mth?BN;_QAnm4roBRgKitl_SC-#IuSpmiKZhw~j>{d-idxSvj zqO+LjOdtcdUnWb7f}t_wJdX6(PF#~HanK9~Nz+9sGLAqX90uSBBV}0}c zB>jQ~@enVCFRlUj!uqS^=?+s;cbw^Wb64Y0X_P!z>PXJKUJMc3KD@Ngabj^-LP|P^ z!+P&>{Md09VMo&>cXbf+33`hM-cBRMw++bCkF#LiJvGp%T0yS6Y?Uo&X72~IEA-zQ zLfU8taHp4ygCE~?!Ny=RIc^!o>okmju1SVqHqD#Z^!mUH_gQ?hYbFpoz>T;j4npT$ zJ;1@(6!!5Pd8IM~b<~%@zxPiSd-r2X8*pX&uQi=hmL^jAG^qq+7Ph8i9(dB)m3L+R z@79pWD@Ks|(vx1c&6WASXdp7d2u^g-s>S4Z0mj+2c+(S0aATzHkAZa7@9+SC`0vY3PcJKCVe>S@BA@P1G!cBix4 zbdlrtKtXcf6z*IB+P`BT^m6PX!I9a!$86xJj*AwGI6q%FHPZ%Wt`kwyN45NHZj?|_ z?FfZs=G3WiJFh0P5Z?`*bgoCw=_D=vG_0 zec=Y;-%v=h4JX6(AXPelY883eA|oeHP6herCi&@K9ffd@a&mr*KO`FelAjWp3#-&0 zkuicl>^|Hqe^$x~QvN5Qd#1ss=jzlo*+ckAx(L^vPlh>B9jWasiO}suFTwomcnD5m zG4tb{h0QNagnb>xz`BFFwEVJ}AY3&TtV>3~nWw$z!@W8}*D<=nkKM!Jm5w1jsMAUC zc&;JD{u&0SuN%^D7upHS%D$5!i-*Df5<`0AY$qY;Y$f3~41@eaL)zrjN!WM(7;(=Y z1~cXuQ7-Ev>HKs(G3Yl8f+~z@pZWVq+#yG@s<$V+tumqS8U~WdD@MpFR(Zg{$)PE9d5{8Ny$0>jqCh4WRGzP59!-RebJB49=N0bhEDke{9Tp z{-ib!y~+pDmRHqW)yI|mgsx(6*B?ZC$0TukYy)}Un=VivG>Cpj&%|Ha1AipZ1vu3~ zv?@ibWTmbKZ_DnLZ%)}!LpKkZ5WbzeB6fwJ@{EBeU%%KL$A+E98&;~1flGh`_xeL-`CC*9sFj||;OWeuB+!GwBJ?d7Rt zV|YK3)WH}|zwxA1-{+AT%M-|%N+bC8!IP@DSQFnJ1tk805lnsRN%J25lG%!%kfE22 z;NSblp6xp^D@uRD*0j9J)$&SExUo+U@fLZ>-o zrTcztUmXTFrDw?aed|cDZ9YCWARI)dmk5hvMMhii#fNu?L(BDQ^1kXBxvIMd-;uC5 zF^M&#X;XV4^wD;_kLlxHZTd}aRp<%*k}`3LS`^p@s0p{u^=109O?ZL!VmRcXCTN%U z6_SgRaZzD3yi-vTg6gz|{X!h>!s50}s{TPH10 zUdZqHoWw^gCUv5{sOF6nj;yaBw$t^=^Yjy3^2d1EEY9WIgq-0b&J>|1v*M}EkKO#( zr+M7IrO#0InK(NB?JnN=Od9v(Y&%@|W*Pn5eHVXg;1VurVIQo|#nX_gv;5rU2e_EN z9}tUaNw4PK<8Q1iHX`raBTKvG5$!OtNDb2Utwi=EkDy8>Mt{s17={TEZK28-z|Ck z2UTB<1&!tV$RbO1+@QmJ0>b(TO}>YS^9W6RX4*37d`4eLHaJdPjm)rQOe_RP>IfFQ z3Q1x$!l8F!;KzMUp?n4*_kK;r-L6H0_vG%v-t4o)epDPrwoza(rlVltd4aT)Y{Uiq z!r^nZst~|kB>mYrN{}J5DVtG4u;zKv>1HABagxO(uy{bUhfs3O;Vg?w5(LdZE|5v% z3kjc9j>*Izh|xJivQzR&)RS_&eoin{NRN_eyA0B?;T(3?TnN(V2T02N)x@kshE4B; z!sXZd$-8x-#B%dV7QZeGxOj=Z8I?s$${ay&KPMpCFc0I(nC5gz27s7_gCAf?5Rcte+ zfD}$&2>a9sPX6S?b+WxlCbU}!`Mv^v`Dqd-Gki$O6d~YVUxIVOL%D6^?~*Lng;3pe z3@`1vlIwBw60se<2v*Q6tTHH-Yd`cDX=4-#CGQvFEw^*Hq|hYd`DzI?hHK$>ru#V< zV@{@e#=%R;0B)k$DQ;{LF22$%g`>d(IO#nZ7qS%Pwq;y~8(*Bm>LslH zV1EUtQ6w&2$?A`F)$!Jr8{B@}mArWx2X21ju;0a?XwePdUO~h-93wY$nJ7!vn~8hj?L9&3f*E8wD>$EVZG?!9?(o9U8r04ZZr>#}Va;d+*KgUu+@LdD zjj@VQ_r(RAa~#05pnw|}+DPKv9pSOJGkkn{g0t!QnWSy72kPSr(R+?@*WNxOhH-XK zXT?EH*by#zjQrutxyG9i>2e$J z!z{nLyCzq8rC6qR$q||!TR?I0Ch?W7)g@(f2g4ev0qEECE_PDf7DpQSK>scsVUCBq zRp|V5WW_YAEeP zmd@%W41VSX!=w99E&tABYC&gVTdo)Io`&?a?lW1pckjr9?p|=^xDibc&ykhyK0;E} zhQZRZzBF5IF5A^%3fVSeD13?N&thQPlyrY`RTemK2&_sor$<)!i7QOzmV_s}LFab^ zXwtxDF?){WW@IoQ@o-yu?e-k5BqEo4J(+`FR|Zk*jrX~7zjl12r3-j8iRj85m|y5` z&o5MQg6+RWbpM(({)1!~zv;Up*tra%#lD2E&m78k*y#c%x?0c?Rn`2a?N)qV<6yWD zZ$-V9KIZ#0nD90q5wv@3Lq*FU@t2+S`J)P!1IuC{^|^JQ?^n^4cTN>U$rCZP3RLj# z*Xr^v_ie#T&y6U+e;Y)-_AM;!Ph2_~AuQbsoXT4Ijj>LVaMy2`@T(i8J4&)P?_^-3L0+VYJZ7 zk{8Va{@8Uxh;{L#OU+IA!gWLV9cPT;Vt)^M{fQ}`wZ?ZQ_ikO{Ud+H?GufP8=Xda13U6^6 z^4;KzaX+dyc_aVwU^6$1^8iE)sbk+5e)R(*zUJ~UxR`A~x7>H*vw!e>VT(7j|Iwux z@6`APVHkh)@JPu1tVzvRByy?E96#l)FYE~KK@01gT!Y5w^YQs(V9~>F)M{I#tgiQY zu9}WzG4;FARTZ_enh8h6wFcv0TfgpfuD30Tip-ELST`0%1oot7_p$ia>=t8DI~oR_ z*QWfJ`2;I6NNv(6$ef^0&9#Eaq!Cw1uWBDK>ff8*vYbvl6+cMO@!?RA*@vc=c$1Hd zx(Hc`Ua+XF4;`|}nOqOh6SAjzLBsGq)H1_@{O~sv=xHzb_x^dx?%COF@0GC9nojPM zqj+4QCF$JhLFrfB9K|F?m!5r4daqrMf@AdK=IT=NE?ePqO-o{9`KTLszlX zFH7MhXiK`k?WaiZn5FPprX!IW+9^g~&Q$nB=t?dP=M=e_nF_JLo@7qq5JlpWOhtK< zo}}&1;fmownF@P*eaSeNkqYyOOvNe_eaUX~k&1v#nTjXh^dvP!!xe4HGZntMdJ>m< ziNdi*mZHW{PvY$)Rw(9YDLx<5m7F%PRjj<2rRZazEAh)VR`{4^D<&uCNa|knR7_i% zt+-aBEvd6=r`T4St=JH$EeWluFBR2gD`dLbl9peuOFcDn6qS#)B<>!MN?YURq@Sa> z!m!dhaliC;ryPaVRV_)wiF>6pzGo|RDzzm2q<2eqS23)fX-R$>-!0WWkgeGFQ%lmn z{rytwh-}3!V{M5%@NwxohipaE7;T9sc~e^bHA@knqAl6Cv97e;u`IMAPy01j1+yoWGZ%~=}WFWGE%(hkfqo*QD3q;-B8idfnoJaPx3UNm%=@ijUTTk*&n8( zm|c{m*!x;n;%eMoaauiFF?g`9B_9d;CIPZTy9`V-*|jLV<*_c zEoNuX?WYAb$ge}UZ`s0&y&JLLeG8fv{u`YcG7z>cO~ooQ3p#bP8rH}k2n|eUC7tyj(;llE+Cg-33JyPFLG5rGta5W8Tz{U1?_9H> zky7ecT=Np0fd)dpq#aa7#M!+f}sbqBUGuzYDKiVM()O7t!EF)}XUxH_lsUNjKG> zLzQA{__utLFYd;^OkPFebLiMW7RPzQZoF^<8}CvXDv($M*}e-`vHlvts!p5 zPCRX`C6&CtjJ|HPhHbNU;8#qZp`O>7FR3-mY1)RTEVrcNpbAZBZv%R9Irwg@C7rhR zKB^tY>c5%YLzE>gy!9B}U26kh(=&0uP)oX_`~@<+U;|UfXW*Lomb7EPwYFXZjz0)`+)bJBGJ(RwdfmWDNngc3`U{ zOIj?yipmPDVT9Q(d^*{Zo@##y{fx1Ovc9|VFSZ{X)}BXWM_5CzlHJ&m;lDMI?GO9^ zyL^;39m;1brLRtFdd?C}JY7B6eJ%MsSiM#U%TtoweYf^>%k6B8NBmmn{;YhGo5ai# zSI^tvUKE$+_H36m7T0cYC;B`7kM!s@miUQvihFQrwp)sk39c+kaW5j9+%B8w;fsq> z-L-0x+>Wxma$dvI+;3JccC*n?!O}q+-QSf=apToqBjf&?+=aE^R-IXaR1MPI)f-LR z+D$!yBwaVVFW%bD&8{Q^J#X6VZd!bM@VEZ)Xu?r}4B4X%wCg{W++d#AHg2ES_V zhuW{saNoM@7ucU^d^H_s*8{fLpIRBzpKaq_}!_fNy7mMY!qXD-kFD>g*b>|&&{k#J`PXL5?2 zhupor6Rp^^hg-0~khnTXVbE4rw6%=qy40MO&6cq|74{?etHf7)(!ZkQ>`$fr++TnH z4?h0?e>+3q{{=q(rx*!?MSsObNLa%1oU5p8{u3`DFDf3-@BbOM3(F=hQIp_}(-OQ% z{|+8BK7_2&3V@r90XS2dim#utl8t6Iy2S@M9QwWnxohh4ZK`A7p1lD!R&3=1J_qoe zdK`3~_#H)F+fD{f)#24y-q;TN&Z4I#m&voFRh;~6JnWX`p%*C^$g!IvIaNJ&o-AIE z)ZPeW^H~#a{5Tc|t#c?E=5&%I_^NQZ2~1x$+Z(OU&m+ENm&CVrOF?adHOl?Dh2-wp zF8)*^1p|W~Xiwp4;`2R1+;~+AE73Pzv1B1}o*)*_td>Gv{YCyo$tW_Up_AC2>DyfB z9u^;95IbYO>grG zH%0D4Tb_=k4_KbHP8~Aj?#IU9r|W%KKDv5*N$as(Hz5_@Zg8iy5#@N&+D>$|x)cZZ zLNw&pc0Bd24!vzZ4G-AkN?naM;;bD8^s=7=W=Gug%9d!X8f`$k7MbCC?a*J-k8PonFx%hvU}i(e5m#(3P?w^s=)%9@<`)`lvOaS!+FMmg*q9!Bv~a+CD%L z9>Zz7)y6o`Mw1@6E1;+vADUX*9hZFSPJa&GgMt%A(X)%xuyl1-T5GokP5d&NzL@zQ zeQ48}hQIPhW@sE$8FveHjn<&k6YS9Pnd52PMS?bdXh#orXp8KpO{9AZ51?KVZKyn% z@R!XeQ{FlYz3i<<6V`c}VrWM1GQie(&8f8)1Iw`LKr7i#5seAtN;nr}u;n;oTK1X%t&pjrKa}cf0 z6T6N$D>KS|FK?eb3(~`nh;`>vS+sA1yq#G9_&e$)#lHXIacq3t4AYkJ`4__07<3xNtS$b9yoA++AQ}3j(Z>@+6r%8YRT5H{r+a%5U%2V7h!U!hRpe%6ug7|xty-r zg7Jy2vTjxEe(`-Qx4^EKpws7fNi56T*};D%*LM)prwnZ=nZ)iNg^NdWYrpgpA|0QU z^r(=6_V2OW8*ek=HF{E#bcyZ3r+$CMrQcxppSBGp7ZDx zUkb85e=PK2{=orDW}UJQ))Uf$qvS)5h;SOS$98K|PITAIk=x{t!tcLEz{f{Via-7k z%ZGNJj=P3M!KD={WcG-9A+x$W9-SNuvrqgc>TjKeEe&Sq6(eLqQajIgV-L>TU?PeP_jVQgn# z;pn|}LUCLS+0NFpb(Oa;=3{{{qwz4gwUgOfRCx#kY99)b10IkaOn*P%85XL#sK^~B zs0lusnU1!di%{#=T`q0b64cr6P2xN|!Ed3Vy!NZ9aCI@$-}fINv}rp)?lxW|IR1!* z?_>K5T}$lcBfDdvXmc#6*Bc9%bCFww3=u+^et+{>BjK%?SUxXrsBl9Z`#<+trCgOV zRo-`%&yAMM$JCJBZ^Qn?i8o+$M@BndIF7yEWeDS9r_sETMOf$g7Q7@RU3hG@rrW3U>ncrzWUW_CwAn``Bv2Le&T`~bLrp$mfaT6vgG0P4Om09Ie` zjFf&F%6J({St@CzER{vtJpA-<=Cio^Y!~OY4f%iNIp1aH<6IS2jB*1^k>9koSY`b( zka8pN)jPe>os@K}u_6@ePcu7n>u$(%zyoZVI~f91*J1xjnkeA;MclQ`449ZO6bG;G zgFc*2!SgZ}flgc@QfbSf=G`F}PDO)gwF7E1cnk`&Ux#C96y!LDq1%Pt=x5qV+}xY_ zc<;|alRrsN+YYyIir;+DIC2(2Hy(9-_zq_o&jg41cWC|$M>Lab#11E>!J(e*aA>0) z8aC<|J|~_Ec87c5vmOIcXUA_i($^onhic>f)dSJh#7Fp7{45w8(hYAtJP17=OYz(2 zK!6o3XlA+yZ3TNe-oYj5{q<&)(_mb5$7He|fD$G&Fd_OLR<&Ez(R+DpM zdEf8f`%hkYphGja3SW+E;$hWeAwJPr?j#(_o8PQQa7F+me=%J=bR-1o zSmJeuOkno8^}=iK!O(g6XH>Ch04%(Ch+mz_v)FkBXwo(t(5W1VG$X`7V@{xbzinZ3 zhBtRQ$rWb4%|i{Pwvc-I3&}5cg~E;Nkr&hJluYaI0|ekQ->< zUCE!lZ2&z}j|xZfhr`{#QsOhc6Qs;66edOZL1+)DF#TIC{<$(=xREp+4nz}STv{d8 zwNDg^#?1q}$frWupb~s}mML*cIcwQ#j;2hKTehVCs2 zgY8eQ2(qo4@B|jyMe|oU$aT&irJkFR+LcIn%Iy?VYZLGu$3Wz`axsiPmngjN z9>#K^4@4bQmVg8AFMJ7}iM^}qd9g(dB=q8irfC!KE&F|Z*4G%Qwl){qo%Y4mk3;wc zGnPW{k;cO3EhF*cRipSjE0_M|OQpQm{_W5IH{Di6#i^Ilr>bRVk=}v3`8tf&IdFH| zt)5fllM*WBr(S!b--Bne7&fEi_a2qV#a1HJY4Ut%A7v@;y&_P4;N(MIHzo@DR=pNl zQu2kj%e(W1@$CGUt`~|=&Lis6Q^jHaQn*RW$f(nAO01`Mb8Y^pe8!dzYHnybRo2pS z^snE5(w0Fjs;UJlrEzA;I?Drjr1{ zpsF(X*kA3X(m^dMs;qtIU*oBiwj5_SqyPE7YJkd#_~w>VCMu=>X;(=&j$4{fC8($z zQTA7T+HyQJL8V|t3$^*rdr6-R+p-%99GuV8l`MqDg`RbRQ}UnHQ^ZRb4pE3<&d&n1*_yM>x}+ST_xdY zb4|;sHf>4|DBGD_j{Mc$W-xn4`Oo{xf4;ALV^P-s_eGgoK$GPeSjBwW{21Mn(aRY9 zcV2U)&y+H+`3c={m~(O+8a5zJxLC9UyI&55*GG4w)S4rLw{I~HJTw>P_CAeNdQ}J? zJt}dL@oZ?@n<7h%J3_}F)j09mY}lW22AR0r6y{uhfXS)3keq%PIrY0J?E6rOvvn3g z@!UPg`aKaoPrQt~s|CZG=xqPkK&W7nIGun#puTN zjl!AAZCJ4)3f2TpM#htt3&UwLhVRi}Tt65+S~FYt5EOwIoQ;9B-&W}3WN#s1_jug< z3(J*tsW&ou?;;GE?1p=9i3PJ;n&{v+8-wPO4Gw}^6~epmQh1SNgJ$n{6N+Apz;m^jDsFr4O4j&%DydP$^I4{q}FU{!L%#G+Y?Pe53|4A1PJlFEy0WE{sFliQqB52W{T#Bu>lCD4lUi^%ARwD%5!X4_tLT16)3(Dgm9i1r3`1FTgU%Sq;QGnM(=>|2$7T43}PMjsktR^(Bu zNjr6@#!<`lVMP8({8>+%_78rJ!#8Tdpk=4={QbJLBJmqOXWAYzcAUco%!gyZMHMJ# zXX8aLuVH&V1G+m-9ftY7!QyYX{+Bxcr@pIIyOxdtz5ZPdf|tF;K`NDaNjC#(e@qoR zd40e>#+BGe-GF|6-GV!Gs=<4PR^o>>`n3GsFMM};EuIowiB)gw(_VoM_*VNythS*N z2cOiZ#}wai-km0vzort$tkI{de}BRkZ>xZ;uo8b{XN*IgnD32~I{cJX;+K8(X}{$! z@$;2!;m4UuT=7PaYJGiz%?jH?=8;M~?2sN!$#{t8oznpGoJwr7P>-r7-o?@TJHhCc zl{nH~kJ(gJ;xhj(&@!(Q5B#Z1dq&>C8qd1IVDC!2{Gu)`+k6$94CoHxft7gOHeD*_ zD)1GD9-yaFi9=#_DUH5_!+-UFZ>p8pZmuq!KcyVMitY)=>u%vQ{<_q^@gg?L?Fm0> zZvC}CmGV>W%fE|qua+|(j=s!?BR1-(lajV#baluVr^sQm!6d&Ox~x5$H2i*zKk3Ya zRkSVo-8F$Yt$v72CN2ck>1ybC{$BF=UNN>&iGq^KpS)Vx71E-Wj_HtSa5t~#hl;9+ zQ~iqnT0i@6G1zF;@f#LCC$u>c-#QQlzOz5`lfu7~Bf%;7*O>@dd;SG~e}#rn*EI(> znTNr%f}8xPPQ8Re$Aj3^Wg#4_EaES=SP4?xZMReb{Z zvYNp{VMQh8-mq9WHGTM(dG5lOV-ImB7Aq%r>O<~Pe-IXIe1emD%mwIin7g0nEL2W> zg4ac}*f*Oy@dZBz2oHDO$L;0>!p#Rc{Lm6zL3H*C{u;Lsx_{`5Dqb{^tDDc@!$uL% z#bN}ycdC@sUEhuqQdzE^$I)ni$Z}$IVHqxSiiNnbap?7j9z-@zj1?7e5M4ACnW-ko zdJnBb{f9|mXJ9{+F?C-FKDHbMv1jDF^b@-wG1UF}&7vC`F_yH_d^z0EYaP^rovHDTW=lIWo zowwg&=cIGuccUe|>Cag(`xMKO(tJ+*B*~3`vuZXxzy1Q-ZZ8uj_5v1BbIyOQe++z$ zbzk2RcbsC!cgUO#?+4c4(#UpPRHZ7vW&BJqsrrq*UfOXwZAILDW+VJgzXRMoG>2;< z2V`TIPvyb=Jz&@C6s~)Ylvu@%0W(_z(CL4GlNCKBJ&_M+l^C;U49ewAFcLgy7~h|yTsz4>WA=(l`E6nHROW*J&OY0*PvyN=<8*3a4YM&X46Q4S z8%+y8Gx}uu_+;5&c=K)$HGX%957)}& z!#+C0tz=hPIlq*DOiu9B&JI@Aa~ar}&ax@hfHedtG7tUOU=5 zz>&!7ok%Tqg{6xJ(E-EDWN!oZ6O9lTFgZPlzR_&Y&FuM(tT%Llc~U#78Dh(;?f6M9 zv+t8pHgs1neVkU2p=|!g^kr?W#WgI_~B=U;BECRE_1RuxjOqYAAR{4+F2;2V%4qu3T>dwH)QkwSICCp6z9*$Ek!?{( zqbG@7|46))=|~MP_Yk^$Gv>Y4Oy-{zNkQV@M|f@C%pJVNa<6Agp>%|~@I?DOXR5D< zmPn;gdDT`};JlS{%o8JF0n5E^D-u=@n87{kJQk%gonU`M2Vw0zQ!eAx3bq#sd31u-IgiX)4p^u2KM2@q(Yw~U5oq}eLG@Z;k+B4vDQgdex$D&3L8EX zMrgmnt4-ATHflflLsw@*&kN^p%Zm2=&-~l`$gp52-JXU`i#qcgE4TA#RTKm!&BMoD zb>&|jS;h|^7xQ21m%9Yx;|AS$3%&XLwjMD+^P+IUu5SFygM;`7(k0NYT>^eNr#pXc zgTMtph=wzBS7Fy#J$RpiP9^<^MT2Z|5)Mi4$+!90mV`c84E8J5;0zWIddt#PMCJ_qqe}8v5DpZ*9g{sF%HoLZz&pz{5*~H|i^ea&6 z{FG-b$MuhkD6^>?lCjNxgKuD=z-a#W!opwaW9YI=k7W@}EF6Vq4+t7MmLB>1MHX5O zLV1_&kX|sB&Wh9`BdXnm>GQgQqswSIIoO#LeRUV^{_Y8(S4YyRV?9Ymw!3iBU+2Hp zo3lq!ivTZjI}{7X2bf=Yhmkb&`zZ3j-a&AW(*@5iBk0?^Q^>csrb59JJ$SR*o9@dB zCZFzU3HX))1YPu^k$wq8+DT2AhVoak4On$-$U*ez==#dhSo0e-B_vWHGf~luJqkQ*yP|7EHf8(Rr_T zk<3?LWs0BnVEEIXPIb;E2QQqGjcs&-Id5z!9+65apQg(WKNUmd%>ndEQUZxuyGiD{ z8$+M#W^`uHY2?SyqcTSecX-!gLc`BHkUdq;Wx>-uAV0&1wtLcvc<#|8UziV$LsM^R zsb48e%X1(KyWz0yV=ubvXrV0syo7XB^9C6^gF4FOcas%m{wY^hlsdpQdyExtR%u9v z9^>8T#|~3Wy4Fcj<}7mGV4bSysog`;va^SK%9~upkRw`>g0<(}>d_9xtaxonPF12? zhozeo=4-SiL8q}>AX=|*_tBQ@lyrAn@4ZeT?V~M8_Io;b^o?Z2WoE0j_ISqN`n+UC zyo0vH_Jj6d@yTSxsu|jnT=^X#i99z&k+pw=Vy3^YWaY;g zMYd&%;`BaU$+gSLirKj-iXQKEnUzk4Le?`?(aBs-5@o+fu_-cD;W<@L;4}(%Xb6+PS7FwlO=nn-c_u)1+n`e0Ggo z+@L8>>+1_Ky7eqC^d9-VhDL#_9tlf^SL5?0Z{;;NyoJEk z(xl}b1A_h=t zwiAx4uw$3^G_3N;k_tAiSk-?JOxQaaH!QTI_47Gw`f?EL3Z94&vv+$s4&e{e>>+f` zczisS*_Sn9>{wwB8sC@=znul0FljJ8ZzX~kxnuFxYI7=D=7!y*A_&SFgR8cf)AHHw z*nvIo+`Bd!S5Gyk<~kCr@mmCK+(zTm_U825CJF9p<^VH4`Qk)9bGoKlf){`TJiFBIpu-8B}^Qz+?6w*Sx$ z{6F-XG5^pb!~UVyXZ%B-Irk4;T>B5*)pXYXjNjGoA6mTpA37%g9~xiyhu&2E58eFk zA9~^Ef9Tf#Z~gt&X^}Mau(|Vn)*Wa42*8H}{p*23Oachm|-#9-%8i9xHZ4^B{ zT5IpMcM04`iNxzN8bvoMzuB+PSORNA(YPR_Q8Wa7u|FBI1YTsu;x6WmqSc>1*mpKx z0#=m?IO|-4=*o{*_BrRGfo@)f4-RP%@oA6k53+aoaqrgP$RqWl!@q9ZM;%!Vo;e%v zR`q(3B=?GahWcVK4cdgej`}W2RX=CnWmFW5(8<8tvg$;IyNm5}nBV_t{~WykQ?1CO z>A3xYPZ40(V<&DHS1VG)9k6d07Xd{b_TbdJ-$Zqhx%Me{!y(T$5BHD#CR(n!)7~_e z)tBtW9VOpH6T-IHcanrd$*aA1mfbhenOCNwSuFP4Ue>O`+6~8>i8`|OT-M)|^)EeO zE>iaYd;D3CEk(-l2eJ9<+5F*etVPQCi`n`Pu=R~UWG7Ot@9*`WS9KIA*Z((v_6t+YS!Rj#$ zoaiKb{Be$jpA!+&J^kc9-x$n~OpS%zaSk|T>u+viA@H*sVxc!0fTs}^zGgn=BNr@# znx01ZX_Xp(kNF5ZeY6Z5Hfv(_#y0$dr5rzEL>!C?=zy&{wC96bT>0ZC;-Ip36B_Zp z1HW&(3*WIl%aI~}kG8Do$ZweE%*S}M=es)(QE6o-J|)PBe;6MRF0*f<>t{Rj<4-yA zT6^Nbq)!Fr<}Zy4Cuf8GmgVe<6SPQ}X|u@n8Li|G)A1 z^ar1RW6zKwD6{@a7;rm8&Dr6L6z+>et_$q%Myop&RXCn zh0H#@&MZMb>S-`-bBdjFpGw85GndOdUJj<)t8CGx@2U8e245quH)Gxlg~6JpNC97ubKRUnfy$c{AMxv{ae1uYeK1KQohHw zrhi|0r7FXc9WES`4-Zp}5Ss zuOM3WLr7IDhI!=+@Z8wGf?h+d(9JR$RCQ+JDG&Mz&pv+;=9ff6(!B{daIA^o3eSYI z5lg^G-5XauHxY^-R0=MmSf12$4r{IKCv29V6P6EI3Xcw1;`!G7h2m}}g#Dhe(08LY z-hI2ja6@aGaB%oCXc^Oj%%V(%uP%wgMH~mY&u$A)6S4G?g2KBCy8GKq5Hla)d(7T#gv(j}LsxU*!I9xa{UpQ5 zqYJvv+O0y;Ni}PKI$#zGV*M++eImB3zaty}5F7tvHw$4R8^4;(KY-2up3Q%l&EI}( z3o>WxtNpV+Teki@w*Dt<{Ri0kiy41mjK2)V-$BM-PsV?5#((l3{?!;hcNjj~89ri$ z&t`^SFvHK2;iq8uwPpBDVEDfLgYN={|1^fb$shdPnS8D>`FJw;RJoOw>J3S2+`dkyD;=jw=o;r)>-Bf)Th}W+J0Its5sThw_HDhvZqdm zZl2?XrETiuog{f^!s+QyTW2P?ysecRhGwG69Rk?-UJWsLQ7b<=JsG|834pQ8)-bfT zR&KB+5@jt9fYTK}Wqw+9^0O_zC~02+i>Yv1`~cU-XEEgRK3=i`(LRtbb~<6)I=_>o5P5O=jco zW#g}AJ3%QHivw#RkU_Ki2T@4gOSIvEPmO%-Ur$OlU&CgXvRLSfm?^Qd8$4_-cJE#9oX z2-Y!Z&JP@c-MrS|z7rS0c9WCn=aUimQLiMNyK@nYKbVISj*rCaef_hEJKQ##0*t#1okpBh`AQ)pMtARXtDJ-P3cs9>g~h@!g5|$Exr@iTMA1Hk|fBe$FF5#mLVO zd_I^}Um^1^8WUT)_H@#|Sg`isNy(_5 zb|YC=*@-y|H$c?~zG1;rNb0m&pwr*GB&z=)VsA_0hi{&L4~OhvNJuIR8P6 zUySj)_-fIf7=Hlfw+QpIROQzR^H0V6-7){qnExTH&lu}#h4rn&`f9QMuc)c91?$hl z`XdmZ?T8PH_~;=%>kz*?h@Uy)7lrucAinny-+vI_AjEe);_r|6yCD8Ci2q*X=PmN% ziu|M?KQEELP~hoK7%#hD9>bA+9qlGN4$y<|n(pugA$z-v8_SwP4pS8lt zsb=ut@EZ2#UOUKNR4ee)&A{DwJ9`YH#X5T94ezRAWN zv;)gkpM?I=W?;JPCmUaE2eqc}1+PRiDC^da*p=b$Lakp4x3H(cz0Q3|$zwZc-TR@C zvd|1R-JqnVsXaVTs1S@|%^c_^8) z+a7k59S}Ug3}(8=krDUo;g@BuVBFgbu16)2N6i%Y8}?e^kS;!7H)tUl*GmD>`I*8c zEi?FiVIj#HsDPo?D}-^HW-u1V$Kv?F1DV1F96yWxkI}yr{STmj51fA_&M)BnMmYZn zj6WOWzsL9!F#dE^exLjQ%`X!3?|}I)#{AD={$o}3t;YI#VttiZzY^;ofb}oJ`j4yd z>94{kQH7s%-}k~~#IFePjYoWK5Z``??=!^z7~lM|PS1N6Aef!D}DMG7bhZJ8D@|2T;7QpFtYlS_t zPATpU;*=vtEC4IIT}ZIHp=dp!TsdaI0vLoEZSD3yz~8belm__xQ;JuC02$8|RX6S^ zvzsjdU4tXSn93K5OB(l;2OHsiZX9QD{HAK$3H^1@|EkJgo<9!f*Hz6g$KQ$ZAF1NY z`L)LUYE}8w<^M&Mzg(Yy^?g#+mx1+<$NGa*^^Zb)$`GG)6+TT6zf*`Gqrxvzg>SR4 zzxWkQ?|aap!MRQ%QFSKcq=_1W^Zsk$xq!Edcv zKd5du7&sR?EgDa(2W=5zUsO?U++4U^GoIMB+#-~@S5b3*E_8NwCwZZpg_6y;D0t6< zPvH|u+u%(?zEDBWj`4<-5uW5$(~ZK96IW^HKp(i;cN%%)yj~bnet}vY@CD7lS)_;U zTA@<&EWPmC4-}2PNp8(*A?C<&I%8A-_ObCNm)5NmuJ=>Yl4XIQgZ&qMhhz%7%8$_B zxj}GoLNvn(@_6ILMm>+`DrcOgiL?Es{iqSW z(>j4`HuDq>&d2*A$ELC$wkB|T4NlVOS^?6T2GiNKJr{5luBFsDFhFXXFoWGKEa0|| zkm%#Ps4d!Q7F%JS$axtH)L}%RlyrPH>$@nCD|)4*<4|kXa`IfZaYZ6GS1P7EItNLe zuFYe&bWP&2r6T$)C`eMa_hIi%N#f3H7E=8qLDI0!zN}wn66dky2wn0xNYcLL%YHbT z#PJ&r(*+vA(im4i_Ck3Qx8qj<)oC6qoeA_~8(vG|zLgjJ86S<~WvX%6zXkeNqrZs$ z^8CYb{!rEYa(o`+-^ci67+=n>Gv>Edm0w-{TB`i(*Y^bLx5fHzVEvP@ei@(kh|d8P zJ~Dpgh+i7wcOCJo!?#+6uZ;gbS)*HpzmtleFy!Y3@?)st&lCBJK>q6UTen}-|67D> z8YkeI#?SD=M%})mS1a1J)PVg>dcZF1$5em&e|9XA=a$#hb;b1_$LC!Bv%ap*?$^Z% z`gIyXn(d3?`bArV?q^GA+F}IJ%AC*r+H4IMk}aX}JvRb*NnFR)HjsG20_J77kvVUd za{VvbKxXkkSY+r%!r!jsx?Zt`&Hm=_Y3*?0KQ@OOq+<^gUgI@N%`jq-ozJz8!|Mu{ z{%~r-F!J~b&t21G;qhYs3(;q3LI?)2hL+^;=K4^xlPhDfrFpSl|GQ2lj+}D_lq)4^6(Nk0ThB z7(?PX7cwoVF)w8}!jLRu5W$7SbZ^3Y6#N~J!SN8)_)_%0js6Ps|A79vIR81Ezs2F- z+;*J*5yt<5@h@Y1eT?4{^V@{^#bbU0Fu&87|7^_P6Z0pSzg%B;tj|(apIrY*tbf4M zzxCJQ|7j}xFCsr*@468$-Ve1<%+~T&!;#yKtHX6wk4RIY&ovk9)_l^D`|V)5sQvYmVkxUy5bD zZdgG06&vV1cQlvp8Ou)YV+l0K2FBeU&E2h-&(2J@gkFtoV6Vp*?gk1B)_%2w)YaCo zxoQmOx+jL+_DS z>$%PvYH|NASuu_?*crtN53S+Ib4%!VVH{WD8O6@mvw?+Yar?tKZr6Y)*2UTes(4HA zt{ul+?HmdE+uV0RIY|SyY-8RY)gjk(jKR>=NxD608`CsjhYaXo3|nlR zq)%yEnJ#N|h+ltWINiZXdS#Wv3=hyD-eZly;;o}(Hf1w2+(w7YTx<-M#g0;JyN%4v z53R_7Q^xRUzN54#cpa0O+lmyo>XAHWCF8l221RN6sB^wHu+j*0(%|~mS%TIVbU|S$+h<;5Lq=?GObv`EKkuU z+Fwl|562yFJR8TasM`@gHM;*D=30m|vls zALhRw^Oscl%k^oi>Klsn$@Ndd`WaRIGCsRh_#8ugED*nGh+ie*cM$QjM0`JZZDz(I zzS9xkGl>63#NQ3^pNII%{8S=8osb`2??6Kw;X$f)nF7u5{LhN%w zZNRV40y^!u%y&CbV83>NE%t912&czh=Cj*sC}vvN!By-NoAv4ve{iR{!ac+u{O_2- zrN)=|c0Rs}cJ~!9!y0?Y#9ZWuk6oqMGlzx9q`uJN@dbWyo5PAP{}LE-6W4qUzrb%l zcUiGC7$9y$Zae@{&PH}t= zj_c$2N%YS}|L5pG1O4Us<8gj#)%>$Dem9J-!1xa^egft<1M|yx|4Lzn`N{bwWBzuk z{KK)nE?D14tnVwy6-UWRx0lEQ)DuVn{U8U!*MHSX|+*9XG4 zo3`NR7|1BjRq@cs0yML2;og=&W^+sx?={o{Odauj)jEjz*uIM2zS#mC|FMBHYl4`A z+i&wfG%O)G$_CE%3T6%%-{$`fumoso14dFX|K+|V%->)QC&z^_8w_soA4XU~ ze=BR)axa7_+kTUOdejR0Ra!yTgivOt{Y`!+t`B~eWd-kwLYXuFRPxRqc)a(*^HFUm z6SlpQ@0)H7M_DVF*gK4w5MRmb?8oaX3o8h*31jvKSMr;Stf3Ic*WtJWj<>>b+5a^9 zhpPOa{sE_7xBA~_%-NI#cxCWnjpRp5Z_$HcQWGp1@R9@`~mSF zjQ9s4Kj)C2&B#wTj&%oy6{_zp-b*S47dJZd;*E`idR>nI7~c&)W%nWF!xo^ZX= zLE_yKxr1iQ6xXy(VE8r%X~~8JuC^>yk%?>nZ6h5dx8HG`S4gVjeY^>Lad(g+D`L5v z{;3N8ToV}JdhU4)#J_^TW|0U>e zVD{JF4(A_)^WP0lRaE2ra{M5Se?b-hMkV$&!Th2JEK^*?{I+BMdocf%o0lp2Vg7P` z#aQ2SRef^(O|X7jRsCBKpDl<_JH$s9@i9dF&Le)q+y2E*#@7PzRjBaQMEqwX{A|hv9Ue}S246+H z+cShX{Z0ZzwpjCha>aO4!(r%Z`=CK!D2|+pZR@eeRJ5MbNw81 z{h#>0oTvQxMfiESmPV?1 zc^(_Y;R)g(+cG`_5g*x>akE0)Nu0FwRBOiskHz4Il&`G8?3WysZWTh z^gH*Q@L;<(T#TxvUBgYK13Kq~%mQsNb*`lwqD>`_PG<$rbJ}3{`zJk_U@9Fwds--a zt__{?e$uH+OeJ%}Q$kg%mSE}llXl23mC_X_gfC1>7+vv$&R=ILHSc{~_~eh{vwzSg zxu(*lCZfRPw1mc=zfU7J%Z zEH`Qe{r~+&{f?VT$J!nf);qL_3tv#P!^Sbr?muZ{KB$n~r6Nkx1cS63-Pbx zXCLyDh5Xd<_eI5DeSYQp1oAb1-M!5JZvVeq%PFra(>6>0)4R>HdLj43GTp)Wx%=^1 ziv#(g^U@ujy&8CYdFn;J%g=O&ym#98{yYBlm*ox**VIZQ8r_5I*1{OSfdW}Q+J$ih~#kbtqcdHyWtQdYg=)__!YFL(oUZMN( ze%X(ey>_i|xc_15@jLgfl^njD?%=v@)^YXRrv6{%=BAe0ssBZ8jn#7V{9oi|`G1g` zoag;}Q}90HpMU?G-faK%V$^sfN|I|E|%fo2za=3c
vCoJ` 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 literal 0 HcmV?d00001 diff --git a/examples/96_animtest/assets/catherine_CREDITS.txt b/examples/96_animtest/assets/catherine_CREDITS.txt new file mode 100644 index 00000000..f2cd2512 --- /dev/null +++ b/examples/96_animtest/assets/catherine_CREDITS.txt @@ -0,0 +1,2 @@ +"catherine.blend" Model from: https://github.com/buu342/N64-Sausage64 +License: WTFPL license \ No newline at end of file diff --git a/examples/96_animtest/main.c b/examples/96_animtest/main.c new file mode 100644 index 00000000..8bcd6f8d --- /dev/null +++ b/examples/96_animtest/main.c @@ -0,0 +1,169 @@ +#include +#include +#include +#include +#include + +/** + * Animation benchmark (96_animtest). + * + * Draws 4 instances of the same model, each with its own skeleton playing a different animation. + * The CPU time of 't3d_anim_update' and 't3d_skeleton_update' (summed over all instances) + * is measured every frame and shown as average and peak over the last 'AVG_FRAMES' frames. + * A fixed delta-time is used so that runs are reproducible. + */ + +#define FB_COUNT 3 +#define INST_COUNT 4 +#define AVG_FRAMES 64 +#define DELTA_TIME (1.0f / 60.0f) + +typedef struct { + T3DSkeleton skel; + T3DAnim *anim; + float posX; +} Instance; + +typedef struct { + uint32_t sum; + uint32_t peak; + uint32_t curSum; + uint32_t curPeak; +} TimeStat; + +static void stat_add(TimeStat *s, uint32_t ticks) { + s->curSum += ticks; + if(ticks > s->curPeak)s->curPeak = ticks; +} + +static void stat_flush(TimeStat *s) { + s->sum = s->curSum; + s->peak = s->curPeak; + s->curSum = 0; + s->curPeak = 0; +} + +int main() +{ + debug_init_isviewer(); + debug_init_usblog(); + asset_init_compression(2); + + dfs_init(DFS_DEFAULT_LOCATION); + + display_init(RESOLUTION_320x240, DEPTH_16_BPP, FB_COUNT, GAMMA_NONE, FILTERS_RESAMPLE_ANTIALIAS); + rdpq_init(); + t3d_init((T3DInitParams){}); + rdpq_text_register_font(FONT_BUILTIN_DEBUG_MONO, rdpq_font_load_builtin(FONT_BUILTIN_DEBUG_MONO)); + + T3DViewport viewport = t3d_viewport_create_buffered(FB_COUNT); + T3DMat4FP* modelMatFP = malloc_uncached(sizeof(T3DMat4FP) * FB_COUNT * INST_COUNT); + + const T3DVec3 camPos = {{0, 22.0f, 66.0f}}; + const T3DVec3 camTarget = {{0, 16.0f, 0}}; + + uint8_t colorAmbient[4] = {0xBB, 0xBB, 0xBB, 0xFF}; + uint8_t colorDir[4] = {0xEE, 0xAA, 0xAA, 0xFF}; + T3DVec3 lightDirVec = {{1.0f, 1.0f, 1.0f}}; + t3d_vec3_norm(&lightDirVec); + + // "catherine.blend" Model from: https://github.com/buu342/N64-Sausage64 + T3DModel *model = t3d_model_load("rom:/cath.t3dm"); + const float modelScale = 0.0035f; + const char* animNames[INST_COUNT] = {"Run", "Walk", "Attack1", "Roll"}; + + Instance inst[INST_COUNT]; + for(int i=0; i + #define SQRT_2_INV 0.70710678118f #define KF_TIME_TICK (1.0f / 60.0f) +#define BUFF_HALF_SIZE (T3D_ANIM_BUFFER_SIZE / 2) + +_Static_assert(T3D_ANIM_BUFFER_SIZE % 32 == 0 && T3D_ANIM_BUFFER_SIZE <= 0x8000, "invalid T3D_ANIM_BUFFER_SIZE"); +_Static_assert(offsetof(T3DAnim, buffer) == 0 && _Alignof(T3DAnim) >= 16, "T3DAnim buffer must be first and 16-byte aligned"); +_Static_assert(_Alignof(T3DAnimTargetQuat) >= 8, "T3DAnimTargetQuat must be 8-byte aligned"); +_Static_assert(offsetof(T3DAnimTargetQuat, kfCurr) % 8 == 0, "kfCurr must be 8-byte aligned"); +_Static_assert(offsetof(T3DAnimTargetQuat, kfNext) % 8 == 0, "kfNext must be 8-byte aligned"); + +typedef uint64_t __attribute__((may_alias)) u64_alias_t; +typedef uint64_t __attribute__((aligned(2), may_alias)) u64_unaligned_t; // Maps the input data streamed from the animation data file typedef struct { @@ -16,21 +27,118 @@ typedef struct { uint16_t data[2]; // can be either 1 or 2 16-bit values (scalar / quat) } T3DAnimKF; -T3DAnim t3d_anim_create(const T3DModel *model, const char *name) { +// Starts loading the next part of the file into the given half (async) +static void stream_load(T3DAnim *anim, uint32_t half) { + if(anim->loadOffset >= anim->streamSize)anim->loadOffset = 0; // prefetch the start again for looping + uint32_t size = anim->streamSize - anim->loadOffset; + if(size > BUFF_HALF_SIZE)size = BUFF_HALF_SIZE; + + uint8_t *dst = anim->buffer + half * BUFF_HALF_SIZE; + data_cache_hit_invalidate(dst, BUFF_HALF_SIZE); + anim->dmaTicket = dma_read_raw_async(dst, anim->romAddr + anim->loadOffset, size); + anim->loadOffset += size; +} + +// Waits for the pending DMA, since the PI queue is ordered this also covers any earlier one +static inline void stream_wait(T3DAnim *anim) { + if(anim->dmaTicket) { + dma_wait_finished(anim->dmaTicket); + anim->dmaTicket = 0; + } +} + +// (Re-)loads the stream from the start, blocks until the first half is loaded +static void stream_reset(T3DAnim *anim) { + stream_wait(anim); + anim->loadOffset = 0; + stream_load(anim, 0); + stream_wait(anim); + stream_load(anim, 1); + anim->readPos = 0; + anim->streamPos = 0; +} + +static void stream_rewind(T3DAnim *anim) { + const uint32_t halfSize = BUFF_HALF_SIZE; + uint32_t halfStart = anim->readPos >= halfSize ? halfSize : 0; + uint32_t halfOffset = anim->streamPos - (anim->readPos - halfStart); // file offset of the current half + anim->streamPos = 0; + + // start of the file is in the current half (file smaller than a half, or it was just switched to) + if(halfOffset == 0 || halfOffset >= anim->streamSize) { + anim->readPos = halfStart; + return; + } + // current half contains the end of the file, so the other one was loaded from the start (looping) + if(halfOffset + halfSize >= anim->streamSize) { + stream_wait(anim); + anim->readPos = halfSize - halfStart; + stream_load(anim, halfStart ? 1 : 0); + return; + } + stream_reset(anim); +} + +// Copies the next keyframe out of the stream, returns false at the end of the stream +static inline bool stream_read_kf(T3DAnim *anim, T3DAnimKF *kf) { + uint32_t size = anim->nextKfSize; + if(anim->streamPos + size > anim->streamSize)return false; + + const uint32_t halfSize = BUFF_HALF_SIZE; + uint32_t pos = anim->readPos; + uint32_t halfEnd = pos >= halfSize ? (halfSize * 2) : halfSize; + const uint16_t *src = (const uint16_t*)(anim->buffer + pos); + uint16_t *dst = (uint16_t*)kf; + + if(pos + 8 <= halfEnd) { // always copy 8 bytes, the check makes sure it never touches the other half + *(u64_alias_t*)kf = *(const u64_unaligned_t*)src; + } else { // crosses into the other half, which may wrap around to the start of the buffer + uint32_t sizeA = (halfEnd - pos) / 2; + for(uint32_t i=0; ibuffer + (halfEnd == halfSize ? halfSize : 0)); + for(uint32_t i=sizeA; istreamPos += size; + if(pos >= halfEnd) { // current half fully read, switch and refill it + stream_wait(anim); + if(pos >= halfSize * 2)pos -= halfSize * 2; + stream_load(anim, halfEnd == halfSize ? 0 : 1); + } + anim->readPos = pos; + return true; +} + +T3DAnim* t3d_anim_create(const T3DModel *model, const char *name) { T3DChunkAnim* animDef = t3d_model_get_animation(model, name); assertf(animDef, "Animation '%s' not found in model", name); - return (T3DAnim){ - .animRef = animDef, - .targetsScalar = NULL, - .targetsQuat = NULL, - .time = 0.0f, - .speed = 1.0f, - .nextKfSize = sizeof(T3DAnimKF), - .file = asset_fopen(animDef->filePath, NULL), - .isPlaying = 1, - .isLooping = 1 - }; + const char *path = animDef->filePath; + path += 5; + pi_addr_t romAddr = dfs_rom_addr(path); + int streamSize = dfs_rom_size(path); + assertf(romAddr != 0 && streamSize >= 0, "Animation data not found: %s", animDef->filePath); + assertf((romAddr & 1) == 0 && (streamSize & 1) == 0, "Animation data not 2-byte aligned: %s", animDef->filePath); + + // own allocation, so the buffer (first member) is cache-line aligned and never moves while DMAs are pending + T3DAnim *anim = memalign(16, sizeof(T3DAnim)); + + // no struct-literal here, that would also clear and copy the buffer + anim->animRef = animDef; + anim->targetsQuat = NULL; + anim->targetsScalar = NULL; + anim->speed = 1.0f; + anim->time = 0.0f; + anim->dmaTicket = 0; + anim->romAddr = romAddr; + anim->streamSize = streamSize; + anim->nextKfSize = sizeof(T3DAnimKF); + anim->isPlaying = 1; + anim->isLooping = 1; + stream_reset(anim); + return anim; } static void rewind_anim(T3DAnim *anim) @@ -42,7 +150,7 @@ static void rewind_anim(T3DAnim *anim) anim->targetsQuat[c].base.timeEnd = 0; } anim->nextKfSize = sizeof(T3DAnimKF); - rewind(anim->file); + stream_rewind(anim); } void t3d_anim_attach(T3DAnim *anim, const T3DSkeleton *skeleton) { @@ -137,9 +245,8 @@ static inline T3DAnimTargetBase* get_base_target(T3DAnim *anim, uint64_t channel } static inline bool load_keyframe(T3DAnim *anim) { - T3DAnimKF kf; - size_t readBytes = fread(&kf, anim->nextKfSize, 1, anim->file); - if(readBytes == 0)return false; + T3DAnimKF kf __attribute__((aligned(8), uninitialized)); // 8-byte aligned for the 64-bit copy + if(!stream_read_kf(anim, &kf))return false; bool isLarge = kf.nextTime & 0x8000; anim->nextKfSize = isLarge ? sizeof(T3DAnimKF) : (sizeof(T3DAnimKF)-2); @@ -156,7 +263,9 @@ static inline bool load_keyframe(T3DAnim *anim) { if(channelMap->targetType == T3D_ANIM_TARGET_ROTATION) { T3DAnimTargetQuat *target = (T3DAnimTargetQuat*)targetBase; - target->kfCurr = target->kfNext; + // 64-bit copy, otherwise we get a memcpy + ((u64_alias_t*)&target->kfCurr)[0] = ((u64_alias_t*)&target->kfNext)[0]; + ((u64_alias_t*)&target->kfCurr)[1] = ((u64_alias_t*)&target->kfNext)[1]; unpack_quat(kf.data[0], kf.data[1], &target->kfNext); } else { T3DAnimTargetScalar *target = (T3DAnimTargetScalar*)targetBase; @@ -167,6 +276,19 @@ static inline bool load_keyframe(T3DAnim *anim) { return true; } +// Local copy for better cache usage +static inline void local_quat_nlerp(T3DQuat *res, const T3DQuat *a, const T3DQuat *b, float t) { + float blend = 1.0f - t; + if(t3d_quat_dot(a, b) < 0.0f) { + blend = -blend; + } + res->v[0] = blend * a->v[0] + t * b->v[0]; + res->v[1] = blend * a->v[1] + t * b->v[1]; + res->v[2] = blend * a->v[2] + t * b->v[2]; + res->v[3] = blend * a->v[3] + t * b->v[3]; + t3d_quat_normalize(res); +} + void t3d_anim_update(T3DAnim *anim, float deltaTime) { if(!anim->isPlaying)return; int32_t updateFlag = 1; @@ -183,24 +305,31 @@ void t3d_anim_update(T3DAnim *anim, float deltaTime) { } } - uint32_t channelCount = anim->animRef->channelsScalar + anim->animRef->channelsQuat; + // local copies, stores through the target pointers below could alias 'anim' and force reloads otherwise + const float time = anim->time; + const uint32_t channelsQuat = anim->animRef->channelsQuat; + const uint32_t channelCount = anim->animRef->channelsScalar + channelsQuat; + T3DAnimTargetQuat *targetsQuat = anim->targetsQuat; + T3DAnimTargetScalar *targetsScalar = anim->targetsScalar; + for(uint32_t c=0; canimRef->channelsQuat; - T3DAnimTargetBase *target = get_base_target(anim, c, isRot); + bool isRot = c < channelsQuat; + T3DAnimTargetBase *target = isRot ? + (T3DAnimTargetBase*)&targetsQuat[c] : + (T3DAnimTargetBase*)&targetsScalar[c - channelsQuat]; - while(anim->time >= target->timeEnd) { + while(time >= target->timeEnd) { if(!load_keyframe(anim))break; } float timeDiff = target->timeEnd - target->timeStart; - float interp = (anim->time - target->timeStart) / timeDiff; + float interp = (time - target->timeStart) / timeDiff; *target->changedFlag = updateFlag; if(isRot) { T3DAnimTargetQuat *t = (T3DAnimTargetQuat*)target; - t3d_quat_nlerp(t->targetQuat, &t->kfCurr, &t->kfNext, interp); - //t3d_quat_slerp(t->targetQuat, &t->kfCurr, &t->kfNext, interp); + local_quat_nlerp(t->targetQuat, &t->kfCurr, &t->kfNext, interp); } else { T3DAnimTargetScalar *t = (T3DAnimTargetScalar*)target; *t->targetScalar = t3d_lerp(t->kfCurr, t->kfNext, interp); @@ -210,10 +339,8 @@ void t3d_anim_update(T3DAnim *anim, float deltaTime) { void t3d_anim_destroy(T3DAnim *anim) { if(anim->targetsQuat)free(anim->targetsQuat); // 'targetsScalar' is part of this memory-block - if(anim->file)fclose(anim->file); - anim->targetsQuat = NULL; - anim->targetsScalar = NULL; - anim->file = NULL; + stream_wait(anim); // DMAs could still be writing into the buffer + free(anim); } void t3d_anim_set_time(T3DAnim *anim, float time) { diff --git a/src/t3d/t3danim.h b/src/t3d/t3danim.h index ffa42cac..80bf88c0 100644 --- a/src/t3d/t3danim.h +++ b/src/t3d/t3danim.h @@ -28,8 +28,8 @@ typedef struct { typedef struct { T3DAnimTargetBase base; T3DQuat* targetQuat; // target to modify - T3DQuat kfCurr; // current keyframe value - T3DQuat kfNext; // next keyframe value + T3DQuat kfCurr __attribute__((aligned(8))); // current keyframe value (aligned for 64-bit copies) + T3DQuat kfNext __attribute__((aligned(8))); // next keyframe value } T3DAnimTargetQuat; typedef struct { @@ -39,7 +39,12 @@ typedef struct { float kfNext; } T3DAnimTargetScalar; +#define T3D_ANIM_BUFFER_SIZE 512 // keyframe stream buffer, split into two halves + typedef struct { + // keyframe stream, DMA'd from ROM into two halves ([A|B]), kept first for alignment + uint8_t buffer[T3D_ANIM_BUFFER_SIZE] __attribute__((aligned(16))); + T3DChunkAnim *animRef; T3DAnimTargetQuat *targetsQuat; T3DAnimTargetScalar *targetsScalar; @@ -47,19 +52,27 @@ typedef struct { float speed; float time; - FILE *file; - int nextKfSize; + uint64_t dmaTicket; // last queued DMA, always targets the half not being read, 0 if none + pi_addr_t romAddr; + uint32_t streamSize; + uint32_t loadOffset; // file offset of the next DMA + uint32_t streamPos; // bytes read since the last rewind + uint16_t readPos; // read position in 'buffer' (both halves) + + uint8_t nextKfSize; uint8_t isPlaying; uint8_t isLooping; } T3DAnim; /** - * Creates an animation instance from a model's animation definition + * Creates an animation instance from a model's animation definition. + * Free it with 't3d_anim_destroy'. + * * @param model The model to create the animation from * @param name The name of the animation to create - * @return The created animation + * @return The created animation, free with t3d_anim_destroy */ -T3DAnim t3d_anim_create(const T3DModel *model, const char* name); +T3DAnim* t3d_anim_create(const T3DModel *model, const char* name); /** * Attaches an animation to a skeleton. @@ -110,7 +123,7 @@ void t3d_anim_update(T3DAnim* anim, float deltaTime); /** * Sets the animation to a specific time. - * Note: this may cause some work internally due to potential DMAs. + * Note: going back in time needs a rewind, which may cause a blocking DMA. * @param anim animation to set time for * @param time time in seconds */ @@ -179,7 +192,7 @@ inline static void t3d_anim_set_looping(T3DAnim* anim, bool loop) { } /** - * Frees data allocated in the animation struct. + * Frees the animation, including the instance itself. * @param anim */ void t3d_anim_destroy(T3DAnim *anim); diff --git a/src/t3d/t3dmath.c b/src/t3d/t3dmath.c index 9817fe1c..88eee964 100644 --- a/src/t3d/t3dmath.c +++ b/src/t3d/t3dmath.c @@ -219,6 +219,15 @@ void t3d_mat4_ortho(T3DMat4 *mat, float left, float right, float bottom, float t void t3d_mat4_from_srt(T3DMat4 *mat, const float scale[3], const float quat[4], const float translate[3]) { + // read all inputs first, since 'mat' could alias them the compiler would otherwise + // write the matrix unscaled first and then again after loading the scale + float scaleX = scale[0]; + float scaleY = scale[1]; + float scaleZ = scale[2]; + float posX = translate[0]; + float posY = translate[1]; + float posZ = translate[2]; + float qxx = quat[0] * quat[0]; float qyy = quat[1] * quat[1]; float qzz = quat[2] * quat[2]; @@ -230,12 +239,11 @@ void t3d_mat4_from_srt(T3DMat4 *mat, const float scale[3], const float quat[4], float qwz = quat[3] * quat[2]; *mat = (T3DMat4){{ - {1.0f - 2.0f * (qyy + qzz), 2.0f * (qxy + qwz), 2.0f * (qxz - qwy), 0.0f}, - { 2.0f * (qxy - qwz), 1.0f - 2.0f * (qxx + qzz), 2.0f * (qyz + qwx), 0.0f}, - { 2.0f * (qxz + qwy), 2.0f * (qyz - qwx), 1.0f - 2.0f * (qxx + qyy), 0.0f}, - { translate[0], translate[1], translate[2], 1.0f} + {(1.0f - 2.0f * (qyy + qzz)) * scaleX, (2.0f * (qxy + qwz)) * scaleX, (2.0f * (qxz - qwy)) * scaleX, 0.0f}, + {(2.0f * (qxy - qwz)) * scaleY, (1.0f - 2.0f * (qxx + qzz)) * scaleY, (2.0f * (qyz + qwx)) * scaleY, 0.0f}, + {(2.0f * (qxz + qwy)) * scaleZ, (2.0f * (qyz - qwx)) * scaleZ, (1.0f - 2.0f * (qxx + qyy)) * scaleZ, 0.0f}, + {posX, posY, posZ, 1.0f} }}; - t3d_mat4_scale(mat, scale[0], scale[1], scale[2]); } void t3d_mat4_from_srt_euler(T3DMat4 *mat, const float scale[3], const float rot[3], const float translate[3]) diff --git a/src/t3d/t3dskeleton.c b/src/t3d/t3dskeleton.c index 476b9ada..e94e97c5 100644 --- a/src/t3d/t3dskeleton.c +++ b/src/t3d/t3dskeleton.c @@ -62,9 +62,10 @@ void t3d_skeleton_blend(const T3DSkeleton *skelRes, const T3DSkeleton *skelA, co void t3d_skeleton_update(T3DSkeleton *skeleton) { int updateLevel = -1; - bool forceUpdate = false; + uint32_t forceUpdate = 0; T3DMat4FP* matStackFP = nullptr; + T3DMat4 tmp __attribute__((uninitialized)); for(int i = 0; i < skeleton->skeletonRef->boneCount; i++) { @@ -76,8 +77,14 @@ void t3d_skeleton_update(T3DSkeleton *skeleton) updateLevel = -1; } - if(bone->hasChanged || forceUpdate) + const bool hasChanged = bone->hasChanged | forceUpdate; + if(hasChanged) { + // if a bone changed we need to also update any children. + // To do so, update all following bones until we hit one that has the same depth as the changed bone. + if(!forceUpdate)updateLevel = boneDef->depth; + forceUpdate = 1; + // only cycle through matrices if at least one bone changes. // this avoids flickering at the end of an animation, since it would cycle through the last X frames otherwise. if(matStackFP == nullptr) @@ -86,20 +93,14 @@ void t3d_skeleton_update(T3DSkeleton *skeleton) matStackFP = &skeleton->boneMatricesFP[skeleton->skeletonRef->boneCount * skeleton->currentBufferIdx]; } - // if a bone changed we need to also update any children. - // To do so, update all following bones until we hit one that has the same depth as the changed bone. - if(!forceUpdate)updateLevel = boneDef->depth; - forceUpdate = true; - if(boneDef->parentIdx != 0xFFFF) { - T3DMat4 tmp; t3d_mat4_from_srt(&tmp, bone->scale.v, bone->rotation.v, bone->position.v); t3d_mat4_mul(&bone->matrix, &skeleton->bones[boneDef->parentIdx].matrix, &tmp); } else { t3d_mat4_from_srt(&bone->matrix, bone->scale.v, bone->rotation.v, bone->position.v); } - t3d_mat4_to_fixed(&matStackFP[i], &bone->matrix); + t3d_mat4_to_fixed_3x4(&matStackFP[i], &bone->matrix); // if a bone has changed, we need to force updating it until it reached all buffers. // otherwise once the updating stops, and we cycle through buffers still, it would flicker. From 4ecb4490aa341abee42f071c0640283c500d6659 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Max=20Beb=C3=B6k?= Date: Wed, 30 Sep 2026 18:59:25 +0200 Subject: [PATCH 2/4] chg: go back to non-pointer return --- examples/96_animtest/main.c | 6 ++-- src/t3d/t3danim.c | 58 ++++++++++++++++++++----------------- src/t3d/t3danim.h | 30 ++++++++++++++----- 3 files changed, 57 insertions(+), 37 deletions(-) diff --git a/examples/96_animtest/main.c b/examples/96_animtest/main.c index 8bcd6f8d..0317f3fd 100644 --- a/examples/96_animtest/main.c +++ b/examples/96_animtest/main.c @@ -20,7 +20,7 @@ typedef struct { T3DSkeleton skel; - T3DAnim *anim; + T3DAnim anim; float posX; } Instance; @@ -76,7 +76,7 @@ int main() for(int i=0; i= 16, "T3DAnim buffer must be first and 16-byte aligned"); _Static_assert(_Alignof(T3DAnimTargetQuat) >= 8, "T3DAnimTargetQuat must be 8-byte aligned"); _Static_assert(offsetof(T3DAnimTargetQuat, kfCurr) % 8 == 0, "kfCurr must be 8-byte aligned"); _Static_assert(offsetof(T3DAnimTargetQuat, kfNext) % 8 == 0, "kfNext must be 8-byte aligned"); @@ -31,10 +28,10 @@ typedef struct { static void stream_load(T3DAnim *anim, uint32_t half) { if(anim->loadOffset >= anim->streamSize)anim->loadOffset = 0; // prefetch the start again for looping uint32_t size = anim->streamSize - anim->loadOffset; - if(size > BUFF_HALF_SIZE)size = BUFF_HALF_SIZE; + if(size > anim->bufferHalfSize)size = anim->bufferHalfSize; - uint8_t *dst = anim->buffer + half * BUFF_HALF_SIZE; - data_cache_hit_invalidate(dst, BUFF_HALF_SIZE); + uint8_t *dst = anim->buffer + half * anim->bufferHalfSize; + data_cache_hit_invalidate(dst, anim->bufferHalfSize); anim->dmaTicket = dma_read_raw_async(dst, anim->romAddr + anim->loadOffset, size); anim->loadOffset += size; } @@ -59,7 +56,7 @@ static void stream_reset(T3DAnim *anim) { } static void stream_rewind(T3DAnim *anim) { - const uint32_t halfSize = BUFF_HALF_SIZE; + const uint32_t halfSize = anim->bufferHalfSize; uint32_t halfStart = anim->readPos >= halfSize ? halfSize : 0; uint32_t halfOffset = anim->streamPos - (anim->readPos - halfStart); // file offset of the current half anim->streamPos = 0; @@ -84,7 +81,7 @@ static inline bool stream_read_kf(T3DAnim *anim, T3DAnimKF *kf) { uint32_t size = anim->nextKfSize; if(anim->streamPos + size > anim->streamSize)return false; - const uint32_t halfSize = BUFF_HALF_SIZE; + const uint32_t halfSize = anim->bufferHalfSize; uint32_t pos = anim->readPos; uint32_t halfEnd = pos >= halfSize ? (halfSize * 2) : halfSize; const uint16_t *src = (const uint16_t*)(anim->buffer + pos); @@ -111,9 +108,10 @@ static inline bool stream_read_kf(T3DAnim *anim, T3DAnimKF *kf) { return true; } -T3DAnim* t3d_anim_create(const T3DModel *model, const char *name) { +T3DAnim t3d_anim_create_buffered(const T3DModel *model, const char *name, uint32_t bufferSize) { T3DChunkAnim* animDef = t3d_model_get_animation(model, name); assertf(animDef, "Animation '%s' not found in model", name); + assertf(bufferSize >= 32 && (bufferSize % 32) == 0 && bufferSize <= 0x8000, "Invalid animation buffer size: %lu", bufferSize); const char *path = animDef->filePath; path += 5; @@ -122,22 +120,23 @@ T3DAnim* t3d_anim_create(const T3DModel *model, const char *name) { assertf(romAddr != 0 && streamSize >= 0, "Animation data not found: %s", animDef->filePath); assertf((romAddr & 1) == 0 && (streamSize & 1) == 0, "Animation data not 2-byte aligned: %s", animDef->filePath); - // own allocation, so the buffer (first member) is cache-line aligned and never moves while DMAs are pending - T3DAnim *anim = memalign(16, sizeof(T3DAnim)); - - // no struct-literal here, that would also clear and copy the buffer - anim->animRef = animDef; - anim->targetsQuat = NULL; - anim->targetsScalar = NULL; - anim->speed = 1.0f; - anim->time = 0.0f; - anim->dmaTicket = 0; - anim->romAddr = romAddr; - anim->streamSize = streamSize; - anim->nextKfSize = sizeof(T3DAnimKF); - anim->isPlaying = 1; - anim->isLooping = 1; - stream_reset(anim); + T3DAnim anim = { + .animRef = animDef, + .targetsQuat = NULL, + .targetsScalar = NULL, + .speed = 1.0f, + .time = 0.0f, + .buffer = memalign(16, bufferSize), // own cache-lines, needed for the invalidate before each DMA + .dmaTicket = 0, + .romAddr = romAddr, + .streamSize = streamSize, + .bufferHalfSize = bufferSize / 2, + .nextKfSize = sizeof(T3DAnimKF), + .isPlaying = 1, + .isLooping = 1 + }; + // DMAs target the heap buffer, so returning the struct by value is fine + stream_reset(&anim); return anim; } @@ -339,8 +338,13 @@ void t3d_anim_update(T3DAnim *anim, float deltaTime) { void t3d_anim_destroy(T3DAnim *anim) { if(anim->targetsQuat)free(anim->targetsQuat); // 'targetsScalar' is part of this memory-block - stream_wait(anim); // DMAs could still be writing into the buffer - free(anim); + if(anim->buffer) { + stream_wait(anim); // DMAs could still be writing into the buffer + free(anim->buffer); + } + anim->targetsQuat = NULL; + anim->targetsScalar = NULL; + anim->buffer = NULL; } void t3d_anim_set_time(T3DAnim *anim, float time) { diff --git a/src/t3d/t3danim.h b/src/t3d/t3danim.h index 80bf88c0..e9639034 100644 --- a/src/t3d/t3danim.h +++ b/src/t3d/t3danim.h @@ -39,12 +39,9 @@ typedef struct { float kfNext; } T3DAnimTargetScalar; -#define T3D_ANIM_BUFFER_SIZE 512 // keyframe stream buffer, split into two halves +#define T3D_ANIM_DEFAULT_BUFFER_SIZE 512 // default keyframe stream buffer size, split into two halves typedef struct { - // keyframe stream, DMA'd from ROM into two halves ([A|B]), kept first for alignment - uint8_t buffer[T3D_ANIM_BUFFER_SIZE] __attribute__((aligned(16))); - T3DChunkAnim *animRef; T3DAnimTargetQuat *targetsQuat; T3DAnimTargetScalar *targetsScalar; @@ -52,12 +49,15 @@ typedef struct { float speed; float time; + // keyframe stream, DMA'd from ROM into two halves ('buffer' = [A|B]) + uint8_t *buffer; uint64_t dmaTicket; // last queued DMA, always targets the half not being read, 0 if none pi_addr_t romAddr; uint32_t streamSize; uint32_t loadOffset; // file offset of the next DMA uint32_t streamPos; // bytes read since the last rewind uint16_t readPos; // read position in 'buffer' (both halves) + uint16_t bufferHalfSize; uint8_t nextKfSize; uint8_t isPlaying; @@ -66,13 +66,29 @@ typedef struct { /** * Creates an animation instance from a model's animation definition. + * Keyframes are streamed from ROM via DMA into a buffer of the given size. + * The buffer is split in two halves, while one is read the other one gets loaded in the background. * Free it with 't3d_anim_destroy'. * * @param model The model to create the animation from * @param name The name of the animation to create - * @return The created animation, free with t3d_anim_destroy + * @param bufferSize size of the stream buffer in bytes, must be a multiple of 32 + * @return The created animation */ -T3DAnim* t3d_anim_create(const T3DModel *model, const char* name); +T3DAnim t3d_anim_create_buffered(const T3DModel *model, const char* name, uint32_t bufferSize); + +/** + * Creates an animation instance from a model's animation definition, + * using the default stream buffer size ('T3D_ANIM_DEFAULT_BUFFER_SIZE'). + * Free it with 't3d_anim_destroy'. + * + * @param model The model to create the animation from + * @param name The name of the animation to create + * @return The created animation + */ +static inline T3DAnim t3d_anim_create(const T3DModel *model, const char* name) { + return t3d_anim_create_buffered(model, name, T3D_ANIM_DEFAULT_BUFFER_SIZE); +} /** * Attaches an animation to a skeleton. @@ -192,7 +208,7 @@ inline static void t3d_anim_set_looping(T3DAnim* anim, bool loop) { } /** - * Frees the animation, including the instance itself. + * Frees data allocated in the animation struct. * @param anim */ void t3d_anim_destroy(T3DAnim *anim); From d8a433d9203cac37543983f1b5a5170359bf510a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Max=20Beb=C3=B6k?= Date: Tue, 6 Oct 2026 19:38:12 +0200 Subject: [PATCH 3/4] chg: optimize bone arg access --- src/t3d/t3danim.c | 1 - src/t3d/t3danim.h | 2 +- src/t3d/t3dmath.h | 5 +++ src/t3d/t3dskeleton.c | 98 ++++++++++++++++++++++++++++++++++++++----- src/t3d/t3dskeleton.h | 6 ++- 5 files changed, 97 insertions(+), 15 deletions(-) diff --git a/src/t3d/t3danim.c b/src/t3d/t3danim.c index 802f8066..bbd51c31 100644 --- a/src/t3d/t3danim.c +++ b/src/t3d/t3danim.c @@ -36,7 +36,6 @@ static void stream_load(T3DAnim *anim, uint32_t half) { anim->loadOffset += size; } -// Waits for the pending DMA, since the PI queue is ordered this also covers any earlier one static inline void stream_wait(T3DAnim *anim) { if(anim->dmaTicket) { dma_wait_finished(anim->dmaTicket); diff --git a/src/t3d/t3danim.h b/src/t3d/t3danim.h index e9639034..0b471fab 100644 --- a/src/t3d/t3danim.h +++ b/src/t3d/t3danim.h @@ -49,7 +49,7 @@ typedef struct { float speed; float time; - // keyframe stream, DMA'd from ROM into two halves ('buffer' = [A|B]) + // keyframe stream, DMA'd from ROM uint8_t *buffer; uint64_t dmaTicket; // last queued DMA, always targets the half not being read, 0 if none pi_addr_t romAddr; diff --git a/src/t3d/t3dmath.h b/src/t3d/t3dmath.h index 32a8a3f5..4b948786 100644 --- a/src/t3d/t3dmath.h +++ b/src/t3d/t3dmath.h @@ -23,6 +23,11 @@ typedef fm_vec4_t T3DVec4; typedef fm_quat_t T3DQuat; typedef fm_mat4_t T3DMat4; +// 4x3 float matrix, missing values are implicitly (0,0,0,1) +typedef struct { + float m[4][3]; +} T3DMat4x3; + // 3D s16.16 fixed-point vector, used as-is by the RSP. typedef struct { int16_t i[4]; diff --git a/src/t3d/t3dskeleton.c b/src/t3d/t3dskeleton.c index e94e97c5..cddebcee 100644 --- a/src/t3d/t3dskeleton.c +++ b/src/t3d/t3dskeleton.c @@ -3,13 +3,88 @@ * @license MIT */ #include "t3dskeleton.h" +#include + +static_assert(sizeof(T3DBone) == 96, "T3DBone should be exactly 6 cache-lines"); + +// Same as 't3d_mat4_from_srt', but for a 4x3 matrix +static void mat4x3_from_srt(T3DMat4x3 *mat, const float scale[3], const float quat[4], const float translate[3]) +{ + // read all inputs first, since 'mat' could alias them + float scaleX = scale[0]; + float scaleY = scale[1]; + float scaleZ = scale[2]; + float posX = translate[0]; + float posY = translate[1]; + float posZ = translate[2]; + + float qxx = quat[0] * quat[0]; + float qyy = quat[1] * quat[1]; + float qzz = quat[2] * quat[2]; + float qxz = quat[0] * quat[2]; + float qxy = quat[0] * quat[1]; + float qyz = quat[1] * quat[2]; + float qwx = quat[3] * quat[0]; + float qwy = quat[3] * quat[1]; + float qwz = quat[3] * quat[2]; + + *mat = (T3DMat4x3){{ + {(1.0f - 2.0f * (qyy + qzz)) * scaleX, (2.0f * (qxy + qwz)) * scaleX, (2.0f * (qxz - qwy)) * scaleX}, + {(2.0f * (qxy - qwz)) * scaleY, (1.0f - 2.0f * (qxx + qzz)) * scaleY, (2.0f * (qyz + qwx)) * scaleY}, + {(2.0f * (qxz + qwy)) * scaleZ, (2.0f * (qyz - qwx)) * scaleZ, (1.0f - 2.0f * (qxx + qyy)) * scaleZ}, + {posX, posY, posZ} + }}; +} + +// Same as 't3d_mat4_mul', but for affine 4x3 matrices +static void mat4x3_mul(T3DMat4x3 *matRes, const T3DMat4x3 *matA, const T3DMat4x3 *matB) +{ + for(uint32_t i=0; i<3; i++) { + for(uint32_t j=0; j<3; j++) { + matRes->m[j][i] = matA->m[0][i] * matB->m[j][0] + + matA->m[1][i] * matB->m[j][1] + + matA->m[2][i] * matB->m[j][2]; + } + matRes->m[3][i] = matA->m[0][i] * matB->m[3][0] + + matA->m[1][i] * matB->m[3][1] + + matA->m[2][i] * matB->m[3][2] + + matA->m[3][i]; + } +} + +// Same as 't3d_mat4_to_fixed_3x4', but from a 4x3 matrix +static void mat4x3_to_fixed(T3DMat4FP *matOut, const T3DMat4x3 *matIn) { + for(uint32_t y=0; y<4; ++y) { + uint32_t fixed0 = T3D_F32_TO_FIXED(matIn->m[y][0]); + uint32_t fixed1 = T3D_F32_TO_FIXED(matIn->m[y][1]); + uint32_t fixed2 = T3D_F32_TO_FIXED(matIn->m[y][2]); + + // prepare 64bit values, this creates less writes to memory later + uint64_t I = (fixed0 & 0xFFFF0000) | (fixed1 >> 16); + I <<= 32; // needs to be separate, otherwise -Os generates wrong code + I |= (fixed2 & 0xFFFF0000); + + // puts a '1' into the last value of the matrix + I |= (y+1) >> 2; + + uint64_t F = (fixed0 << 16) | (fixed1 & 0xFFFF); + F <<= 32; // needs to be separate, otherwise -Os generates wrong code + F |= (fixed2 << 16); + + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wstrict-aliasing" + *(uint64_t*)matOut->m[y].i = I; // guaranteed to be 64-bit aligned + *(uint64_t*)matOut->m[y].f = F; + #pragma GCC diagnostic pop + } +} T3DSkeleton t3d_skeleton_create_buffered(const T3DModel *model, int bufferCount) { const T3DChunkSkeleton *skelRef = t3d_model_get_skeleton(model); assert(skelRef != NULL); T3DSkeleton skel = (T3DSkeleton){ - .bones = malloc(sizeof(T3DBone) * skelRef->boneCount), + .bones = memalign(16, sizeof(T3DBone) * skelRef->boneCount), .boneMatricesFP = malloc_uncached(sizeof(T3DMat4FP) * skelRef->boneCount * bufferCount), .skeletonRef = skelRef, .bufferCount = bufferCount, @@ -22,7 +97,7 @@ T3DSkeleton t3d_skeleton_create_buffered(const T3DModel *model, int bufferCount) T3DSkeleton t3d_skeleton_clone(const T3DSkeleton *skel, bool useMatrices) { T3DSkeleton result = { - .bones = malloc(sizeof(T3DBone) * skel->skeletonRef->boneCount), + .bones = memalign(16, sizeof(T3DBone) * skel->skeletonRef->boneCount), .boneMatricesFP = NULL, .skeletonRef = skel->skeletonRef, }; @@ -43,6 +118,8 @@ void t3d_skeleton_reset(T3DSkeleton *skeleton) { sizeof(T3DVec3) + sizeof(T3DQuat) + sizeof(T3DVec3) // copy all 3 vectors (SRT) at once ); skeleton->bones[i].hasChanged = true; + skeleton->bones[i].parentIdx = boneDef->parentIdx; + skeleton->bones[i].depth = boneDef->depth; } } @@ -65,14 +142,13 @@ void t3d_skeleton_update(T3DSkeleton *skeleton) uint32_t forceUpdate = 0; T3DMat4FP* matStackFP = nullptr; - T3DMat4 tmp __attribute__((uninitialized)); + T3DMat4x3 tmp __attribute__((uninitialized)); for(int i = 0; i < skeleton->skeletonRef->boneCount; i++) { T3DBone *bone = &skeleton->bones[i]; - const T3DChunkBone *boneDef = &skeleton->skeletonRef->bones[i]; - if(forceUpdate && boneDef->depth <= updateLevel) { + if(forceUpdate && bone->depth <= updateLevel) { forceUpdate = false; updateLevel = -1; } @@ -82,7 +158,7 @@ void t3d_skeleton_update(T3DSkeleton *skeleton) { // if a bone changed we need to also update any children. // To do so, update all following bones until we hit one that has the same depth as the changed bone. - if(!forceUpdate)updateLevel = boneDef->depth; + if(!forceUpdate)updateLevel = bone->depth; forceUpdate = 1; // only cycle through matrices if at least one bone changes. @@ -93,14 +169,14 @@ void t3d_skeleton_update(T3DSkeleton *skeleton) matStackFP = &skeleton->boneMatricesFP[skeleton->skeletonRef->boneCount * skeleton->currentBufferIdx]; } - if(boneDef->parentIdx != 0xFFFF) { - t3d_mat4_from_srt(&tmp, bone->scale.v, bone->rotation.v, bone->position.v); - t3d_mat4_mul(&bone->matrix, &skeleton->bones[boneDef->parentIdx].matrix, &tmp); + if(bone->parentIdx != 0xFFFF) { + mat4x3_from_srt(&tmp, bone->scale.v, bone->rotation.v, bone->position.v); + mat4x3_mul(&bone->matrix, &skeleton->bones[bone->parentIdx].matrix, &tmp); } else { - t3d_mat4_from_srt(&bone->matrix, bone->scale.v, bone->rotation.v, bone->position.v); + mat4x3_from_srt(&bone->matrix, bone->scale.v, bone->rotation.v, bone->position.v); } - t3d_mat4_to_fixed_3x4(&matStackFP[i], &bone->matrix); + mat4x3_to_fixed(&matStackFP[i], &bone->matrix); // if a bone has changed, we need to force updating it until it reached all buffers. // otherwise once the updating stops, and we cycle through buffers still, it would flicker. diff --git a/src/t3d/t3dskeleton.h b/src/t3d/t3dskeleton.h index e004fb40..6b848675 100644 --- a/src/t3d/t3dskeleton.h +++ b/src/t3d/t3dskeleton.h @@ -19,12 +19,14 @@ extern "C" * if 'hasChanged' is set to true. */ typedef struct { - T3DMat4 matrix; + T3DMat4x3 matrix; T3DVec3 scale; T3DQuat rotation; T3DVec3 position; int32_t hasChanged; -} T3DBone; + uint16_t parentIdx; // copy of the model's bone definition, avoids touching it in 't3d_skeleton_update' + uint16_t depth; +} __attribute__((aligned(16))) T3DBone; /** * Skeleton instance, can be constructed from a model's skeleton definition. From 1bdebea780ee58f2503c3c94d87213ce75ed9bca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Max=20Beb=C3=B6k?= Date: Tue, 6 Oct 2026 21:02:04 +0200 Subject: [PATCH 4/4] docs: add breaking changes --- breakingChanges.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/breakingChanges.md b/breakingChanges.md index 7b89ea73..ac6e5112 100644 --- a/breakingChanges.md +++ b/breakingChanges.md @@ -1,5 +1,11 @@ # Breaking changes +## Animation performance improvements (2026-10-06) + +The `matrix` member of `T3DBone` is now a new `T3DMat4x3`. +Any kind of matrix math needs adjustments. +Note that a pointer to that struct cannot simply be cast to a `T3DMat4`. + ## Precision fix (2026-09-28, [e14ff480e6ab15b723373754d1edd95af22cc9f5](https://github.com/HailToDodongo/tiny3d/commit/e14ff480e6ab15b723373754d1edd95af22cc9f5)) This change increased depth precision, and by extension UV and position too by a bit.