From 1024b9a9c9d995e978ffc8d89228eaa8e4350d58 Mon Sep 17 00:00:00 2001 From: itsumura-h Date: Wed, 1 Apr 2026 19:30:15 +0000 Subject: [PATCH 1/5] fix readme benchmark --- README.md | 3 --- .../images/benchmark-2023-12-23-14-25-04.jpg | Bin 106006 -> 0 bytes 2 files changed, 3 deletions(-) delete mode 100644 documents/images/benchmark-2023-12-23-14-25-04.jpg diff --git a/README.md b/README.md index 74e5f0ba..5a9342b6 100644 --- a/README.md +++ b/README.md @@ -236,9 +236,6 @@ ducere build ## Benchmark -- https://github.com/the-benchmarker/web-frameworks - -![benchmark](./documents/images/benchmark-2023-12-23-14-25-04.jpg) TechEmpower Benchmark results: [FrameworkBenchmarks](https://itsumura-h.github.io/FrameworkBenchmarks/) diff --git a/documents/images/benchmark-2023-12-23-14-25-04.jpg b/documents/images/benchmark-2023-12-23-14-25-04.jpg deleted file mode 100644 index d8b925307e7d13237c73dfe0067a88ddb236af04..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 106006 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 h{Aa6n2 zY6Wf}Y}2*;{Xb$q1%WajydW|Jsf;<*ZY(`1FRhAKXCo+(!bu{&IBeTWPQSMleRK27 zjA0*BMP`n^3v&a%N6jok2s={#n8F8XerB%-d3Th@1Ge zaxX!cuE0rPs#htc+(v>PJs=U&g3<|Lt=g_leq?*QFJ){Rz2I0ZbD8N1t3qV}R*<_( zZ*9Vm)h_h_kRV}kcrlxNqX z9B&N2n>ol1e=7cRSBk!o?>@;Mjf`S7^mZ11W|Z+fx0b4~Uxzi6jAfx_tHvk$Cb?0J za;fAz-bL~P5C*p@djKLWT{tlNT5#E||FvCtfR*9c9jc7!fa!x3l>yW$lKpuJ#yF%S z7v^z$8~V$}J`*r!sDkGGJ3^OPUvoq>=hu7f^Hfgq_m}7rE@ufn^gk=oOXq3&qL=?A z5KsorP4T0dkbn;?&;9kKDo?4q?e~1*?)PsfELsSg z|8mb-)D!>3eF7&cSNVb2IY12;bsQ*lpK%Oxx#`GCe*1!1{FT1!O%_F&C{cBT*H84z zSwAz-BY{n>+} zlmZ@}Ml4`UR&r-nt4RtcV59XGws)x7;nY>`wi;W20>uMNA{~mp3{IIwXjKPM(t3vp zA3U-=d+=%F%<802QObR4-gc0N%XnbZP5W-*E}qX^`NP$5(wpp`g+HD#vS!$Q}KqU6ggE8AxvBj&&frzoK;uazx{RpNFqUtk--JEsW0@og$MTk=k0qGCx^9gtcfrRh5*Y)}#NFHN+mYTgrgd}8mChRL zxL6unDO5RiAl^)9dHL4GolEk3LN9tux5*SN1RD;cNC#7_CQngJ6#2Jbs4^8XTg&#u zE^PshwhgD0akjF9+*u|pn{@qi)m09mpF_nREp$|E_}00CWK2ho$Qo2MUQdm!m_%Ks z`Umz9C31^w?Nw|95NrZH!lQ(3bA5Tf>^K@5tzGfXZm{DMWSLHICqEE#J69?=qptA7?5W-oM#!&l3RTosijp1gYIOH?C z+)SbiN0y_V8@()$$k7ch;sW>N=T(uE=^Sowr|xzWJ_fd&)nhr{or*d#j9v`cjm=)HJRjYdC5_NF{CSpti}po+B&O^ z=+2dEeQX=K&0hq7tcMo*DJ!2u^&w$g<|1yh4U6=1^g|?-B{^uhY>ky~AU(fhpZtrD zNmNFOUP!i}ALJx5X7qybG`g-L-&>-LV4q$;DG%eNWoP8mQQGeAD{k2{c{w!WjhY=4 zd{K1k3K>0gYYuQ1<+Yj3F@A(!C}Af{|6x zOCCw{qs0VOPIYZGwnJ1ds*J#mV@_#YccTy~>tGAi{WY1XX8WBz%&*EhL$$eYwM!>qX`^TwU5o;~E$(P(v` z6R@cYG&H1tcvj9w<+o^2;yMO-vPyc0E11gM_?c=cj~Ys#((w%xV7UOhg<=R3OwV~n zMzEba)Mo56ub-x;__bI1WCV~0!JHPzwKVii1)>bNf79M%%Z(=~iP6+_RL{@Sf*Cu`>W5FT+IN~d1`oyyd@zty= zv%nXpSY=@Ux;pDBuaai^gqY_Z^_BhXYJxD1+T3p#nYvF$LK`F0BU#%?a?kT_jN;k^)iX(P^MP+uIAqO|w?r2lp z!r}c`$t&W0tb!1T*QYtxk~0&0xwZDy;WglZ<^3n27-ClS2bFf*Vi9 z<>(~bi(46^hu;YwaD+Bf5%!}1u^af;A^_J8@*S(Md={*aQ#AQ*lV*nQfuh-mVNbbR z%NHMGNcs|c!eIV`K`SWXUaAgqS?9||g00OqjkayGGRj7!AGBXe8-*qdYoJqFS;k_Q zY8cV<8fgbk1-y@PK97#C zJ#Y`St;(E4ORWEK1yB&P-3|be$1tJ>*HK{N=-q-*)4UcK>=mWyWa+w~`c> zW-S49TXkh>zx!PAQGptOM4UCnIa5z$$7^jEqG-NF#D!ogL~!hZET>q!`{rF%Ne*1#`gn zrRpFy&7c#zObU-Y*A!{`NX27|JL_(l`FhKba1>q?3}`tSOBVQTxV~eH<|7^V35>G6 zg$Gd`%++*)$@cJkFsg`O)iUF#GcQ1q^Qm0ifoyyEHI{6rtP9w0hdF~4;*xh3Iq2>w zb!iyRHwnDG_fpF+)$bM@3i{ynys(VPRZiKckgvO1 z+_ui4Z^uj-eV|-+OT>lC6v9cih%wDi2aD3+;-{zKiz4Llh|Qbh+kT6Ejg_Of#cGeG z1#NGDkzo^+RC_B5&9fFd_bl#6_hy-5(k@l#TxzljW0%A8lQOkh%a9QqU!L7+dUtpE zt*)eoBzChIs~#uW#Otai)ihdFI%l$xJY!EpS`;1Y2uJygJ-$s<#YTZjZJw{=O?M5i zNR|bYZpStH9X;)~BOY!~O_T;C{9)p3G}l|&vtmtKNh zrrj0g)az-Pwi${?rr0V1A4BE4LSr?P2Ew8qC|vzchrRt&nY>lUs}8;6^ONSgosE>G zXOrFm`la`3kwZ3s-cHwMc=E_fqI_Uq{kpO5WJlOTABG@yZDge`h`>Q8TzS3vZpx&T zN5Q0)WF(i7)Sc0KwbDo|cHwUz@=dMdZIALHT!$Kh_16#EB}K9N=*WTS1<~{K=_7?; zy$=IdU^;?T{IZa3Gr7?7Wm2QkBCAhgGZqZ9gOhgU3GKH>-Y;GCt_pH5@LP0Lt|*y! zJSY3`MkmFPb9mcM|BLYO*SI2GdX2^#i1c;o%D@5ARbF}0yAvvFPfIm3QhR@O(uG$F7kP4LF}hFIhUS&`dC0fg}- ziNf?p-im#ryH9#i8#nL;9jj=bg>frNei0_oWX>c;BjP1^M#heerTT{CU`%(VxLZC2 zwb|u9(Q9relqWrlu@(znJCux!5ohKCLX8B`~WY$Hd1^%`Soay-; zsn)|x)2+k$0*#bPQ$u|zoDBbuuL7{Z_a{QwBp-lCJE zInvi#i?m&J$Cq`k_onrZymT!M8JE3wLyhWUE0xV?`TAgd+$@W#lviS56~~umo5z_A z!insB(5LQ~p7*c##?j=ZEKA!mWpj*bjX%}LcD?8p!qsH}ZI%JqCIF*Tl?WWn57=evWVK!kG&2=Y6{v|5!@aCtwM^gL2r7>Nl;T*wV7kS2t zPOEInz&=;ux=zPY`#Ze!TZ11B38KoLPm~m^9Be%2tZHlB5C@SY%sq$Bu+}y|OVd5P zs01ic#2UH|dJXKZ1KJ{A`B$8mns2QQrt3^;nekfLJFV-N@N9+KAj?uSMbjE;Pt^r57kk;U{?11guPqh+82 z=HP3aAzWpOQe|pBi;c*d6-@q6W`M{4u0F8RgF%OQ7iv;k&&=r$EO( zf~T^(7+3fl0)6l2@h;54f9m%hV7Bzw#JD{A266{)rTqaV@E_xeXj%Q-FZgHZZT`aA z7>S()+MXRDxiG|VeZW@d!PX8eLi%7V;TZT#3Gx&Ey?FufA{rWej0YiX_dlgrI^Fg# z2G-bAfkEp6wwfzZs50no9{?(1_tGVd3w$m)SRZ)K4F~TKx=?>4JK*U$oJDs5`}Jc$ z61E>Rx_4^Pg$7t=vlvY?7sdnwou}FpKzDcuI_19$1-9zPSV~BX3Sci2j+PO>&(4*q>lkqaL{{2%ueba=0K4}ayl9t_ zMnZprlJY4ra#F4xP~`kJFD1dT!CY=z*23U9j06K)w8{a6V}<7W^KT$$D3`==3TDT{ zD0|aNgSRY4wXhv}4o)h!54Av?ElF)7+hO=Fx4WP2CgY-6=fOV0)um^>h-eY$>QSrz z1~M=7Uw1^)#{MhJ{(tL7nRPv7*jcxIF!f+ReV(A>Yu8NXPz;)?*kTd*! z&?TR#vn?cA8N3y{lCWF9i8<26Jg9DsUJ{ZDKDv~;aZYr|@3gsBGZ#K$1n&Shql4uD zN?AJBl#;;@0q>}7C3wAUD!dCHc{&3>%G|v=1m6V=X8?JMuOW}uzVi*lB$43{#DhRF zH{-Z4PTJo(>0`|z+tae`DU6<}ThoS@w|4Vt_nUE7C@>jG1 zu<}UOuIqRPU{>dLM-sr5M!*=o1x&V<3`h={$3Ah+#^C47$MTOAK&B7Wf6y2}5&!qq zH`q_1_kZPLl>j>ca=`#>*95|Ebd+5<0;IsjW_5*<0#Vg<@Cd|fcXd7%`80S zJ!nOWKDFCkMehJOE5=sL2INn}UxrDnKb+d_I?rV~Coyb+TuQ(Q!J8`2Qt^)skKi9Y zx+u{-m|AhiQL^ry1D`z}!~vz%F(BXugSQbswJffKGb4$1iHrj=fOncMogmP)$?4-0 zik{P}WoY1_ZVo=``KjsX3uL73o8vb{z>&ZW&kKzM`sQ{|a=&VF<~xRQ20-16Hus##6U;!WufO>NnZudW$9(-V1h?>FZt#2bcz-#ly z=UszMbVW6wdZhrm!jAw3OCkJITi0h~J8eKDF8hJg)MD`d4p%MEdoTc`9B}>^ybFp3 zY}SF`pBh7ch0q6AA*)@9lVhr(gR?yJZp;oC2X>4Z!6W$EQHD zTwV0rsX1+$F=mXq2YAtCyqg1AhJr7}PKBHYqW)1F`BMYn7^_r8p8&~%fw*%DNU1uy z5DjhTPt=E70g`POKk_z)`;Q_|5pV=<01822pGN^$G5!@ui(Y|eNEiV4Mf97ao4JG@6dsKT!AThf6|dFnBQaqc)K+D80d%1QWnitu{D6nIx2=84rd zV$3k%`_@O}^8OCke+$GCrESpfNXAWIg*w$eUgDjHHWhn}fDsS8GwoBQ63bH&VDsP}@$#<;cB0E(f+Gzcb z7C#C(y6f6dj5|QyfHX+~EwK9rIz9xL$ru{eypT6R;jaGxBZUDk8p6%$&PJf;B=Doa zlXd0~c<*%~e+{!|O#ny%I4yuo08}NXi6>3U=x~61zG4QvPYb`J|BnJp^^^=a)e_*p z2KoOqIzR02(SAVIF(ZH*5ocL=hX&tq|3_gk@8G8~z{8br^eMo_fUx{mLmS>}w^VoJ z0Pe!Y^q*Lw39v%ELC(DSgc*#H>OnSmBK$jd`BBh7{xk^uB_I#(Zhp^4(9@<{NtA7< z+X`(!x96eMpjC_j;s^g$D1rY3MiWdUa0D&^DbIk!2#83e9a!xvG7SFa_@nM`Bu5tOUP`hjZLHx{t7Z7Ly*NAx zZ<)%n8t0^misUB`UN!o1e%=#~@LLO2FQZVp`P9ImjV6tuC_QzkqGHH9p5~_2wV1$4 zN5QTmO${>iiJ9&p3VKutov|>{-CfCmPXQDV9^ z=FuJC5kP?h$g?VLBhZ=?g~ish&EC?*q>*^zf(~drIQWbcMW(k`o zOrG7_HNYIMNbnH0LxN1vTY$)(bC&R3Cs1@GKRj`UlE6quwWdtC;;L_zPL_lW!#7QCd271I-O zQN$L+tM{;~fCP8~ejrOApPp>8Cnb=e@1I{jyKR!M&qhsRw*KbfU` z90FsSlI9`DnX%G7G`_u)H_OFgYl!o+;5Kf%7iALo^cKW{lo_heMX~!S666YEo+Eub zu|D2?ff(xtl=(+pGJb~Mx&@1)>qK1O`blK)E-~uLU4XB>vE&(PK6y6XXp)u(0l2Q- z=3{qV5t!y3qFc)j6c1Kb3~wpk;r+1CIw{USzumu=`@G7ECO~5u(Tk0aOdmIWcz>G7 zLgq!|TwBSf$??E;0b}YnW||CBHZ>Y$`caAYIV`w?loJk}qcgk>^j_Mp#3lNbYUvBh z`p{zbFc>(Bz`P1DmL5M^bxs?&)V&=UuAd_FvQ*yrv6>^avm-p=6^!v&kLA8Wh3ktL zmOi%tQ~)9TGY~n4j}hjcIyr=Pmbl%vK?p}Uv6wFg&XwtwM80(EB(&M3a@<>!MtC4r zqmmX&x+fcE7Pe}NBMS=#2!-k**QV$aX+EUyXXO#enfZS*-5q-dX71&u%_Ram9X4tr zd(B^LL3|NZl$Hxou-2L&iHeVya(r)eSvul4GzSdxezQ3Q(l4}#uw<;hOKy#_DggkM~kvm35X8o10>>w?EUVwLn?j-}qRk2to2to_ zGI2{k3{rIDx3q%Y{glbEL5D_Qq2E{CEk+V|#b9#}oMTqf?3EPNa(Z?CGnMm9ClPWI z{PhEi>_fj5H@#$alOc!t=JxAdw_fFrG($2@Cd2iOXS5j(Eq_BXgJYf1}Kh=Qi8C00Ayl;K3`9xamhC!^`Fjchs z^9|N0u6wzYOR`&eZ=Q~>O4+zO7vI8pCZctA31gH6qacm2NsNPunvxP*6gJ#$)tNZ% zqN_-GmHmoaRdWVOG;DTqb^TCgL5di0cpBW|d12g`noHR}!;Kw~IM^fsLlqvV?Y54{Y)xnZRY1XL8NoWPyT>+0 z*+0kRhN;WWO3Ufs^IF9+>t<|dAXe|pJXa+Lc^CT9mBo?* zM9kY5@!emZeYB4{l64{a22xM4E{FiQ?U%a%8@Zq$Ee85uRv0o&1p-F6`hna*$o;2t zSy_D>sPLH$g!$05oQ95wx8(#4_q*+Z;~gJU`HKg=)C~S|o`t2GpvzQ6#dAHzBh79& zv_9RbOj#NwX2BA~ygu~xE#WUgm(MtkR6utnX+tC)-@oUQFZ;FGbZ+zLpa;434kImP z{|!W6*@Xer4eK2WPNO@68&guGL+tJPZ{J*Rp){@EZ+;r}sJ4#>Owg8OrYdb#=PyAQ zOIWe$G`+N&v>Ls8CgHA{wyXz48Hu|?F;!P$n!q~`b-sbBktdgOV)*vhu5^~^E66JMdo%RATTbdp^DnhQQGTeyb zuzmd1grwFX<4kxfPcHz{GC;mjcWHW;vQla!?QTig+U8l%gg3Dnb~$S_Vj>GI+?Nx! zNLnuSst51ld$$P*ojvHAMK4npS57!?m=H8C#M&+4EF#N4cj@yx;%M38@Y)u2kR!Oh zN|Pb+O@jw@$pGHVFA(5|c!h<@{ zT6HhFKC^G2$1p!?F?*WpgDB>Ug9+)e>JtQ{O^;(=EDZ-QsK~uR^BY1(7lx9{OGV2y zn}JJ!@$gQF>a$R~-J}JDWV1vkXIz+?u3ciMaLkiH{AK7K1^ml%noYSE>;&{)M}5Vo zIZQfRp9Eyi_8c4^cI*iKf;EK~i(S{mrC6<-x2n>6?BT2Gg`777G$sI2@7+}8?oON4 z-&i@wkUW_wP~|S`u4Z#3i}Hv%v@H)z(Zcb$JikQmfsC*%JDk$rwrJeXe#g)jeuuME z+1Iw;Ar0<)vsgob+Tk0hL1E3&)EzM{^9oEv`_WTBsC+_cX`3~W#@i9d0&I6MI}N|N zaceGK3X*w%u$tKMQ_Wf2&atwQ?Ids`81asB5@TKmI)^tmmAUL zDja~$N3X#5$G(C5v*IaSCEYH%-|fFDL}Rn7FJ7m&bBLp2nc@iS22t^vL4{B54Xxrw zb%tPGg`pbJ8JSmub*y$MNu#D^y&$gQIjYm^=yaEg+i8{xbBbG@w1HQa=rAz=sgNiO zNzLL6@<_Y3sl|iuUI;wue8k9uVD#A|V*eV?P^RfoML6i@;=Z|}rpj(As;QQ0xF$-e*3WN{lY5DRfRg80(Y`!?d|!gM1!@BwgcJ-*?m1>~go{un!JD`%mk z_DxPRq@6=3WQJt?zJ5t1_F#noP=)3Ye?{+~+bIkN0L@p?HqI7~592LzZ-1c2;f*P^6!qA0!cO1*C>XHe-OxL`aBTMKFLyBn=*nzM%2o!My{o zGvqgrETAJf0`4ABQb1v!!ZC3e=+!uotS zIXOAl1pN2Ne?$9k4EtX|RVerjV8%2CY-!x^dNNEGMhI4&oEHIpw9m|oJ`ElZBEnol z9>BNfB+$3v>wtE+sp{*!g}>ka4UNBX<8NB{n=|~)3IFDVe{;hB0!}FA_+H_w_o|xJ z@gcb4qN3(UH9NVMfv-v6r-)Cs6HgI*z+a>)OveQm`MAx8^^OM`3Tk)`S$T+L)C|9?icWqTCWUg*l$NK&_)@e&0Z2v z;t<3&FYqa}*6k%;U40PXG8n{qFLwj5h+t>v#pcaDS2J^<$i{USI2ql! zHufxXC)}e-`5pfCU-Urc)MbFya4w< zh6I`-)&v_{7~aOLlR=n0jdQr;6(ZeA0b~A*>A~BM{T+2dqm-A?X^~Q(=MU*N=;y$2 zun+A+;eVP|#^}VDuIAmwlrO5+pc9c~ggJY3-inGBtbQAh+r1LL(R>WvPB;0_z}pWL zg92P89H1@d4q=uFrv(@Zv>C;{f7P*B;2`3_LZiO<>%>99?WrothaeaI*hNpCf1Ykp z+JM~}tR;Jc4fV1z>P+j#v&_xC=daA-68!80*I-$1?WLg%y^q7IWD~_7(a|q?O7b!0 z(Ef|{)sqcHG{EPi~DmW$;iR-sWcJs9!6Rq$IY(}d*ng|F;=3mskN{q$(J5K(#x_)kX zoT(oWGWi_|<$FYK{swx)AE2}?jV{e_&zxw$jWc4-vGnMo-*l=M^--Z0ze9IaX_+N6 zOMRWzIYF&&kp4x`;=+Zj>mirB@ThuMtk?AQ|LEqo9f7gB8%vj7|G3Y@S3PhQ{81ox z%jJ4_3nW8PweN0O{47MgXWIMSC-wep_$Jk~2lwZ`-zWG7adiT*UAYK#mQ9qAc)(W* z{s=D-Yfaicynr6ow6q4IIF|il8)pxP!-&W0bBmoGn{@H9-MGR31cyP*H4P<)Q0>|@ zgVH{D)`!j{@bXAq`rgD#$~{4Jxgqb(1}bq8b#&STNh;%1_aYI>-&XMl)YNy)T-UZ^c{nz5_$3VWr(aN`0!?TyDLvDkgx-4{3i3C*)V?04MJ zG_}+pFxR;hV-S{8Pa?j@$cLM$>4bQepcvh{$wGGeRf45o}6+Xq4Kjwv*P zWZz?X{OL|5qf_5vCSkn@9#MPeKr4 z^l^tR8<2Wyk<_sUnFDRvDX+eq4X@Ygn;6w_`! zvpxjWLlTKNl8@Eq?bp0I94P;Q9h<4_;G(9QgJVtQ_;wtlR6iRx(Pb@-WscP)@l*R0 zRBTvNj3J|yV5dO9$*#hx2ky4#R!OQCVS<$nv4)cZGYiNts-0CK`cah$&c%@+mr$J! zVu$Wq1X9FC;*$#?%9#F>csw44Jz|ZpgSXOeIc}vox4V8qd!)+CSXXXl=X#W0vOLi** z+Ibta&s`12flI(WU@u5ICg5hnN6`lxeG<{ztQNQZ_(@GdNqRmpdMpy)b@E?t1-UDq_0nhA5)%t!_Guj z(ZFmqY3%I9=od>$_qCkl59B&z1=R)lRhk14hS3{RUJ(dZ<@`rhZ1@RUj_5TCe5-49 zNh{HA4rJ_rZJh-ngd$yA-o+9Gr`8f&7iJG=u z8B>r00?2bV*w*$qg#=#?s&H|?a|#=m?UQ6}7dyO$3%B1P{5V^({3A#HZ@Kc%f7cD& zIDqI&Axrvl*}|qeZ_pD_QA^F}DX9N10hsD0S4lWSQm*oDi;e zvg&0v5yLipj5!jHh}BJe3F?$yN^R{;g_$sd&R`@ZZx}Y~wDmM0A7rf}IconH9s<`* zTYVL+Xas%+}2A zu_TtLXgbmPXt(7DUU>awK0IjtFvDay#NPb3i{j3IFWKdQ8nVq?eCnzK=W9&$l&fqg zQ@?;d43x${TIFi)O>fl8HN{Z(WTPw=M9KB+SOOT7=&39?-9EI=@3=GNCr1?L+gH@p z&BTe>Nud^sR6Z<&U&?C}8n&S;x+-@+XY2PQ?APx|nRhTN1gV#?u z`uNi5$?QTB>o1>aXubL94ML>G5^4qmvBmp~Yg}emorH!h7b@zEwZ^cyD(B*r8!otn zh;&g4tlnEEQnvcoY*s0b;F-*^AWc|eK-l2)Odh|*!MbpP{ALwx5}k=qnVC6;xF&i| z-G^SO*n|<&d0aam9z1E>hePGcpWErD(%Vo`UpI3)k|bqVj3mS7i5AeVDV<`y??_#% zf(0_(v_+|wK(1^oVQw(`^=N2Tu(V&Tcx3Ix)#+4+mt+54u{_&GMFTepw}3G=DwnP% zerHl1Fb^6t&y;S=b#_vkQuD0^JqYctev~d@&$3Y6WLywLN40q&OW-RtLIM1Qj+T^u zx09(m{Znz-e(z@>i`s_Xa=s26wpv#9kjRYwSv`c!l9_}1RmJ0uez4wfY zYH1oqM^O+&5hdr0N>U`J5s{n(gdrmW!Y~BMNf?5FA{hb6l5@^+BR<4oOAoUxi8IKvr!hJPw~-nyUM0iFiONnd^mSm;BmCh$;q z?og&lE>Uk&_XOSl0dhp!G3|bbKjaM(J5}oT-9ud+q~8lV4qB1?46lI;ggG97!^v9{ zQ5nmPr*2oEA^#QBmp1w+1gNA9m3*;q+W!-D%Cs=vlEfuo{sOd~yQZO=5_%W){U>B) zODf;JYG2`^KcwXF8${1OBYjkSKZE1 zq`v*-dx>WBcho=B1eq(IMov={ZLnXy&lp2YQHTG-_|428AkOo~2p#XAAIOQ%llT5% zp>Qd9S8Q@_+y6uEPci-fYwtE@q;3DLR=;J~j$rCP zME7>mPdjmG4gQhXAr*&9{l8SZ-+~IvxPBXk-}31TO#c7Y?B8O!_MrMdgppF5_qXZz z-6#Kpq|*Oz^1mgMQOq)MO~W`AW!WJmaS)+|NVqeQ0oa`oJ(o5J#2_(ubZXf-Mf<8z zzadZ(cTAW1?+oH(C%JNzFSbZU|MbvHc)k6NtMH)@Lrg|MUZP!O+uqC`>t+rhPc&o>!RE!3+ufP zcUjC6%U=2JOJBQ%^nK=5Dg!2W^t{C+#a@~wuPeANm2T`gl^Do>^J-gr;{&P+dP2BL z+@_r?m{?!nBW(SIs#DyFEB?tSjo)595MwC7F2n4erinq5Rh7l-rww;g41|HW!_Dz@ zRh19F3QfFh78IA-tXQhH@2Lb#7n2ZYdT9g&tIF?b^E%;cwvt?eKK-CpSp6_ z!H>4TW@T71Tt7nxsXHk~aCKg4fgZ+c=}luCTyv0_kAlw2<~pxYQrSP&Y&GqB-j7V0 z{7CQ^iW^92eH*j>S$+56(>2D*^_P$YlX$w}peFJF7RV5`bjp`;QH$UjHZps5L=A*u zk^AMY!^ct>9zHB$0OC<1Gr=Gm=9;spHyGs4g+n{eNX^*FgsI)tHr?m5o@GVaT!v_(bD{c4T9OMlVPRQ1*CJmM?QE9naoB&u>I`)z%Bq6<)ktSg zn^c);Hd&Ew=jSri`HhokGsxhyef7r}vT7|%UMt>0P$kg1h#LZNkJiP8qdYU;(119l zH@3n5wmiTtSPe)O>~{0Qt#X zwg=rmWEk~X*JT{#X2a7d4b!UJVJv-=&7LZ-|0i==OI$4?%bg-fc@+^RUUQi0rFZ3gl-e?%veW(v}Er)8#_66MK&5R8%WYU*5%8 z$Ty8>RU6sjf?r>Aj!355sESV}Qr(!p$~bn4W50OM-2s(Hz;41OEbBu)5<5-t#N2F51Zz&8xa6-1#6}(obfe12 z!i!o4Bn*5zpN`iD%+GyZK+qGU`+UA% z>FcD#hDSAx!)hyk%7Bo;e6He4=!oJ0yhOX1Et{<><%UODxFBj^HiLn%Rd)!TDX9CM ze|Yl(INMG?l931bMyy$uIwva+Q5))B91UUhOSF=W(?e3_brCG@b{aVK@#sT>Sxe%=&5uJ^%yk9yJF){7; zyUnTZI{JW#G&I+$g2r<5)kqQp+i9ZI?1NZ~3?o%47V*Pd9@J0_7Q^yqIZSim>t{m; zYcQz~F9owA1R>0%BAzw-b9N_QjTRG;AMQFa)PxfF%q^$|pjtu3nQZ>EXI5$`G1f?G zd^7X*Q&z5+PbUQaULwyhTdgsz4s(_yBa*#b^mZT*WY*8N4XToALa8a&23M=-#j{$D z@0max97L5l-z~}|;|E1vqvFG&eCPtkcg&=k<{941V;m9^nRqYq?r}54y;~KF_A4h9 zylVY1!Fu`NV=B2};r&^X>@8G$yv^3`e)8O^;3At^%LLQpe1pt;dkG z-r0EZSkCswA&JmAc?El7k5C)K?aG6;`5cIU{)bWo-uN^$;#fxO++~Ali(Jq#N~QBw zFoMA)@NonX#Ahg|sgCK3Nwm&#I#Cqk#<6HAQ6TY~KpGs}tNlO#evefdb!m&}a@0*= z$-$Fq5OJ8Tm$({H9x*yHKi@M?{y{yM!Mib&W_FKn*7Ls4-pH~>lIJq1p+}kAhdF<9 z|2g;XR_of3hU`wm9iAA|y}!eVPrzU8_-g3E=FaLL&%Ij?P+Y=Biru}U!ap~hkbQD0j}$34@)$KgHv z$Gt+sQ5Tcx3ta$WGi3$3|tK=9T$5X?0*%Kw0MSNiOuqTbYW#_u_=rB z!WkYd?B}<8A=^TAA0`ibQ8sK)E-x~p7-!y`#aS6e>>Mg#6{?tDE1z|OXo{wX3D~Sr z!y<03^U>Gv?6N!$qkVI#Ff{9btCeEU`o!#PhQa2AvixrTsHPT*k@+K|rxqa4Hi*`$7=pWb9(yqA$+`2Kc zAw777hvhW_MAm9LQyod()lyJDKA;8bc4z^(hVzf48Vwhhik#+414(5PIDtqwjp&a*Kw9a7GBYEcsQ!(k z|60Z#4EEkCkep0_-zs4*df0XH1}X(I z7Gjs~B{WbUIlKi?E@*bKvM2)LCX`kp8M%`dE~rviokN14PjG(X@qjC8Ft*j z9LaMmohItY#C5rXU80X!ljN>~8iU(RH!E5#Z9{p4-=@Uc=)&i|mwc=-_}ZGxn2qH1 z9k-0QlPVJ$^W5E`$9aDwAzdLtz~R$7%e1j?Ss#whY^_=d<&+GGzqR6?GLMV%>o1UR zUkJkM4+!2Y!JOP4t|Zr9#5!=8Gfv(V5MSYvr@<{;A#dw>wt|rHVY8Hp@3)v6+DIvL zx+cr1{XoL{Ex{wc9v8cOg5e4Dmbryf&2x?|hMj__Wj~Ukhf!A^>q|Ux0>XV-tWR+J z#LU65C$*(P}THY*-v)n(FmuVoRvcZ45aIU|0H}uK2PO5beMW)F5A?$!# zVKaaIb?Q-O`f3QN-OY6^sTNM))X*#AbOt}J3y8vSBD4f~uGJP^R*aM@x-arRQ)q-K z&gE9IW28onnG-P^In_FWRP{?Y#-QP>Ef0MwOz)UTll<+Q+S&rMMN+6)L;OAe`)%|~ z1e13IW+E3d@^fq97;pUcb$EV&AjOxr*>hC%*o&i)L5+&| z_cORtk59=5qCFj+nB?je*8dE`q#`*sdl_9RGmm;BdTMk5Em1ekq)M25#0OqUSTi}N zpx*C2NGld<|3aR6 zoVz-|73GC&>PRYe`|F*77upG(7WAtz(am`yB~8R%?|!3nByX_}-20(9+U3mnPfU}~ znab@ho#m{t`K3q!a@E{g^7*So)nLAU2lxq%m{{y#%t z(gf4zqg>MoqcAO@I-6(aLy2Mh(-M!Xg;sKH;s3@|c_X`#fu9`}WDui+CoS7a=C2Vv_?sEXKX@W0m1Sy)PDf_lCnfgmkvAztr>EngdC)7O-#{q+yd1_Wvn+;NReC0dSjjL1~)0?Jnl&nqm&@@7fnU zRA+>(zZs6m#osQd+I4L~xKftRL|IZit`{ysd~TDTCRqtf5IxLW_)~&3EEokdIa*O3 zBVGfof_BMJhf$>|9U!3*F+MyyLY;6*0`#T^ z1*KvpH_DMXK@9j_#X*tuc`RT5Ygo^Y`ZjDhzM2e(Qrv|S;o&M62J)0W%UE12AejxD z&Pnx-wU=mTqtSYn`p(<`TKyW&L4AAf%x@k3i`c{^N8fbL^O;jTWTOj3lN(h(ou?Fi z|G|OJbNm{ZnTO7mHs!~joYJke3KP2VXAVa;>PYUuDa4ycnV&4vCJhMt{<1TF*%Un1 zCgH`uDb2B^B$v~OXp}A}(eN1;uPu^bpbGG4TRc3>%&|q@;w17_EGjGc7-J>t81YCk z4@5EY1N3Jn^zC(tP0Mb>7db3%x8lvivD6&{$L0lLut8P@OOdX8rlGe;oBH||fsvT+ zn$OEE9hkyjAG52*zbSvV@zN99%y8CSa-ixzjA<6SyJ=i93cCCQ)Y&FnLS7qad45lt zxYzX}(&(uD3ZB)G?LG;FE`bt4RCO!Gr733t^Eh#9K@0m-Q%b9$~V^}ngG z%0=V{V2cQ`M_umww+<8kn+^{}kg3I`CZ{Fn!`>88_OQ*VH&Uy(KheSZlkR>16f(+n z8!*m|g^edJ^&@12-J3{Ba~l^MC+?0Zaw83T2>%#)m`AVGXsRjvHI(jj8&R}TH%>#l zCDIdbaP^V(So?gH;=lKIR)p5auNd?f%q!+&*kfGRYqTGl)NkMaD2gh>^|13 zz>@qYIKA;NLCbnBm!s9rhBdJ+K|lLA$?C{1zHOw1{>K-cbcUI)F%_A?7q6jbfnJnH z)v0T%f}%FBbrcBjSuGy5!SCDT{^Xa8*#TrR9CzpNeQG(>b#vAV=A=vzM?iEPv(JJ%3?vJ51^5_jcusa9@5_FrU z48&94k%-Jhu0|ASX-sI0&#)npj7eXXztLnWdGt8X9;|9{nncT0Swr`r5sI&4bBnbS z1Kd9OLnQyO{9MyoA5D9H>W%r$=~iwYujEOsdP|Wo16HCRpfv**Tce?Rhpk@Cfkd3s%OWY<|( z;7&dw2HzG3sYUyj3Iki@nVL80%=^EMd^ZqVBPPN8PZdnPi26ra!u4)LmDb9l{nbL6 z*^;CRa-=e{mnka0Q7Rq^cdLg<4Km5Tk5nkJtF&U6`>M>S@BhSVAK$~%_1_06_^-}B z+~6?3-70h@5yg~L^=Wk^;9U({=hHON1G6_#w|!HP-9mj(dnMVoI9;n2eghaok1>K> z*Z<9A>y0}GRQ~Q3i&3!wvuK`@fsL<^Syx}f3Oj!qoG&6oal%rSo7QM=WiwOMbEDI75>Nk zO?pXnI``+queH!;#6I7?+|vA}b{5Hq0SP<7;ftxat`AG1i9*=?)i|MQ9LD%S1~Nd( z@U*>KuvBz7{#_GvX04vEejbzO6+YPO(k`#BH_|_F-o(-_S zF86bN*rLAaeuo~Je8YXU1b+`rIPj;O{W&eD1(E@>DJ*P~`Fu*(=`G=ivN8?j!4eI{ zZq^EH=ppyAB22;N_kV7v{_V9_(n=myy3EvnDE}v|OEc;V47@A3TyeaL_inO@42;Ry zaD?Hce}PYYTiMP0T3lLMq9yBM^14iQqM*g&1>VzSf3<&`4)pC+Z9Dy(4Y)WS@jKS= zC)N{$G$up)Tj{tgGELn%%dnL}ixjv)rdl(2CRLH)M;FwJReKOaUDqO!<^%0Otb)9R zKV~aXV2SlLhuh_VL0sl*5L~`9Rf_l!sit=2RWXr$L_3N4<{-cMSLZp&0>aY&=tLQf zH*{LhFI)Nkc069_PvU$)*+q*nq&xD#|PKWp3 z`X1fY1izd++yn-x?nx78`N=_fo78c6*6(*Ap;M$OO8%G()_fGyG9PVO)bm*lJ^8+t z7D66PG~Rg*(GQq(zS>BFrq@yY6KY>k*R%6W(?vB+>HqIOf+_r$JA?N>KFhyNJ|zE- zcghUQ3UU%R!nui>)_loRN-^x@pXncmhT2deB;i3_p|Q&KH~&A z_emMH!{*v#pHNTn;oOrX4K-rTz*Bxoe>!A&d`qjU6qc>^G>fEZ^?p|jzivVUj2NYQ zVJFVv{W<4wm7%npbD~|S9FMNSeCT0EHtLli?p1z@gr(KBTnbdee88 zj*VkMi4yQUae*0`=n2P^K$3=rJt3=@uu|SbjAK_p52Q$}sv}CMUmEu#Sx!L?jKXte z`9*3FYJa=JYs_!xxh}ZEMGw23uG{VguUgxt$pC9LnJq3s>;9srWM?n88l~opR6z+D zV|=>p@o2-a3M77uE_bQeqPwBk`xO4(AYb{h4pnw)eU8RWE#HtA@&x1l?hX=b3mHO2 z60Vt+2Nm3;IYv<_YDE>q_!~4=ks5EU1@wc`O=S;JT$uVZjsgAa2ejb=O6`)`voH{tVQ?2)E+aJ-@*vY3%Z&1%XkzekW zdpqg)+1aUq%P@kcqkZYLk($Tef@UGn%=t>Qx>qC53%1ad@@pE?-L6#X)_YDd9t&IO z!@?Pl-i)%*GbH*3m;=bxh{@R7bYnBuY(&=OK1UvNg?H#4O6=MjtcjKG`_k<#BHFP> z^%)B%Arw_+qYqN6d(7vf2d0>DEj|fKs7jHX>L}9llL)Wt*U+0@70x|8OdWE#H_6z= z>OItjjC}29CrSd^1bOo8cFV%%WCfw- z>9Cm0E&XcPXuO)vpiKXl_ILM5Cf;6k$GlEG3WO!b+QD1j{{iwii6X=MkRH}lmF9n? zx{A!JCTlRREcnJk{i4I`XL*=TLa#=l>augP*MNC-Npi%zAfmK%G&-m9G+Z@#wc}29 zuv1$bz28*gJC=So(P3`_rKi{b<&PpEh+VuiKA0i?jK#_B{zAeA2WQ83rJnw!cPqhs zRN)rmCo>Y?7|B>_H8Sfpzd&hv>I8JW*+rg#1%@|#^Su_6{NRboy82+Mo-eNlDd9JxA}^k2!Ca}OWU8x-;PjcQa8F+DO~Wcx zvb-_DmYSk=99cFvp~%{&^SphTHasf!UB}DJNeP^IuZnK)&jl(p5J3F_@}zFP z5AX|T!!|WXsE7*(^H}p}L+4UUHCk3F?y<;q^lZ1X$^f_foNa;QtugnB+Lg6DS-0QR z1+nrw33Y$lJ%&4vZGT%C+MuL9oIziS1p6<2daku^nWoiI+-u3@P?ZquF>jqh|D^{N zZ1wH9nHj|dZ03>6^$*wyywr>#%|qp|Y@K4_7tL@CPCArK;}j9oE#F)}cPgJGa*P%# z>N=kiG2|otE^ROtk;Rg zxnNf<+Z7(kb|DZDi6Pj%X~J&7SW)@t6n39c^{K?<*tOVAO8zV|%O)0cS)KC2K*1;1 zySvKz3F;sfxE^)J@7YyvH+ogXOFZp{HqMc-Zm}&F43*yG@ta`L5K8m^^xj{e*GH_E zIefw?Tfo70RHoXvbSOWftGbPqq(xuNTDpE5LCUaTkCm!Y4s3_X)Yf!pZXR~R9;73C zc3N+}KQ1QVW0!3Elpq&jndR3!fKtrJ_t}^o&LI`)PZFNw#h)RH&|~MGs@Wtb*}8T| zYd`Ok%D|h1CZh7byzfS(5iJ{-SHj70^PY@e!w)*T$OvnQ;M5$~in6fRRF~E##jSi? zl@;oEJ|?<3>KEsvcZizV!5NIQ{{iv=me-B69jn$x6~jw5*(?SX2a{{6VKD>Vs=)=S zf+W>*(hLA+mNUEOT~!o@Ys6hCgC-8v)pPS0?&=aeN(^G9*U7?AZNf}rE~8@tp~=YJgotQH2xS@CHhv$eS(n3 zh;JcCdsvWX0u6*xa+eus2Uex=PMAbecW;k0YR0!46g%do`(f8~E(Oj-9mTfZ9?%9Y zFw@sP@tf=~jj7c-0&y0Q1qa3UCBLx zb}LJK|K=z6aj+-7J!qc_%B&DNC=AjJUhnfxu`HRa?cAoBi^(9t2ztI?Ne-q~bo^+MpH;eA*)Y+L7caWzY(ikGh()$HQ_HfW!ZGf)_@3(L|_Pm4;2?&`=c>O83m zWneaWoMHC4mGLb|c!$<^p0hSSk$G$*J$i&B{bk{h+8n9Qk-0GrPld3=jRWpd@cYfJ zytL?L^pU=e2^;%@0g2YQ>kUKNqD$LZaXa9z~%+~My>f6;q z{{vFCux)7|$AcCSBa3_wT?UA=xUp-d*nCs*&^43t5qW_|inNyiS5-X=RT(&|sABK9 z!jg0B2Dg}ZZA?{YWL;olmX>Xdodr=yYwPfe!bun%%06l*rTtQt;((FuVGok36AbFLyerZ(X$ymy&ydX%xx;~5lKKMKd32@{$!QU8Y2CM&7Xq$ABky zFSq^xU3qt_apr1<89(xYtfhrO57F z@R4UB;mhl)hxK8N)X>V}&`X_~FAe37z~`*HFS125UyJhPkra) z&Hc0x`sh8?aKaC_uid>v;y?=8pHw*%wm3s-`$`WUjOC?;4sU(xw$)d~skdr)+&(Gz z@@)EjRp+=&mG@FW^XD}6H>G=>S6?Jvlk!i|4>C26aA&i-vAxC3f?QAW*ldct%GmLQ z#hPB6^tuEeY83{YRESbMI|mlxnnn03stbrU)k4EgovlrI>6X{q@slxWuiQY!ELwcC z8jW7t$P?f6uI*D!GKqMavO)@4ILsr~+3_!Pep}R+IHD`fwOznfc1*NN;m2!s&*_WB zP3q{!v3FT226Ll(jA76jj#>kWH=f3LJ-A_;Qu+>(#dO3U*v4V~UAGmQ$p61~t?^+ZyL!T`3JN zkWMxk%YSjBzI8>_C&Y~FO7i27T({06W$9BtbL5aivzWpFFchB?QWCgYnIZXfQV~ zrD$|MT9$8oWyp@HBJlN7hNP&3Yw>PtJ8+zhY;v(a<9>s{dwHgik^bkjfj3j#A6{|4 z@wh2R0h6Dp3?|Jr?PDd+rT}k=ZZJWUM|E$gDNj~SG+VKH5HSUB&Q$F1_?M$Fi%Q@m z(spxGw5&~JY3Vks5iZ_s>T&Z}?|hz;FVQ;SV#GC6#l-QD=gM@PLBd?)_bFZl#C$QI zlz0-%i3M(gac(!LMe^?Ji90w!?e}v#WHFdt2TLx6CVuv+e0$@S=(km6Acn5qs4{RX zYlm}7$c~lgsB$oOHg3zPw1PL%=RQp+r-&XGy5}+k_)3krN**ZuJO?Xisl&k=;6VrsLvS>4@M@!N^6^IrzRsQPUUGr zG@o^)5Y&SfZVglgKomYf1}wS8$4AIBbcs#ca0xxG`FlR;O*Mw1N&R}xSdh6A=gO6y zPbl#04XzRjQD&3TExKb$F;lKOpsT&cfn9Ym@12N@LA?``<_s7ZTD9*sZHLV+(#wZ4 zrjDBVTsNEI^zIc8Y&bh=P>9$(o!hT2J!4vHj6ZZ>VlD~$-Yb99htvLdmDz@>BO7V+`_kn#@x-ZF6McW51^_s&`9{oZkiUMBzf->bd$Y%G;|=V-!2u zf1#zl!Q%PC`WppA70RNm(fH&;qm;)7Kl$~xjWJTH6Ve<<)FYb0h@0jHN}f(DPbPKp zLkD`AuAh2IsE~kO-EYBUQIs9bJqTbQRVc-!Df5@4S_pF&j23X6i9md?<6r**oGvzU zP3v`au{6?$-po;pc?`Mi_N}>5`27GW$xBS5j}_|ho!Eq9m<)sXaq5RZ&xU#V`^S>Wa@<@! z!b=yf{6db$muNg`2z5K>r)T`QB4ll%H#&0xm!dvAhDQZYa}LS%1Iq}CxK*F4%q&K$ z)!V#%=7oyi3*uQzCgyJ5RCCqsfijkBIn7ptPN*O(_o}G!rEl@sNUZEQ}X|-Hw-=lrhTxzXA=ukcw3MXujYQxPF@r z&8a-btb!tjq|vKrRb@7I61(gGW!_+UD;zO8Lo;)4zp}@1Gmj~qU*~qClN65?_cF7# zF;SimyV`yp{E$g_t1LZ`CrHcrABR5_%AY(0QM*6lBgD99RG_>Lobdio3vSCVl0V8s zAkJ_^hIx;FfJ9%6m`$6)ju438W(H-qbv~tln)7%?&7m-ZO%*u&fWS4&avSYgG4lbu z2UzpENT7=IB8nV1cdHY5QSt-SM^=?N=d>yiIk6I>_4r6VTrA?atbBV<7|PAT38j_& zFri+!Ocx9!jWM)u%lxZRU8`()SN*J$;+Mt4WJBYvmUQ(?^sF27b6RhivA#}-wy&9v zWX_Yf9e#-KSVlEP9vwyElgtvW^+2o_(FbMZ{JKw0M(Kvf4&wb*Tz-)g=qkI>S29YB z-+cFCCD>c(kg0+^z(u`(e&p6+SMR%seQnJ|spz4WJdoW(3{+y|Tbp%1uO?zhfjW## z`z*%v#f2wJBG*T<62ngackZ`RaQ*#voVeJ`FW_3YRxjW>z0&6|XJ#(0Q=7&BBlp+5 zdwQc=o26<3uEV>suud3sVQ&-NgX+@H$%C%vZ=_u+w%2HVb3U8mgB`a-d z(|b~4jzI7^sl&tg_kmwshRwlEXZHCFA*)r*0qZTC>*fMdkoA&S2=N?CXSK<}2j+wv3M#OGZXX)M zJCbgg4<>qg&n6)QD_TUUE8BY(^kJRWK?Po=zAvo$&R;^#2A~lLXidf5-2Po*fla!p~CcAe#mmIzm z0;H6iL5l&oFi{K1dN4wD|>V)G~Pzm!P&rv&tt$a7{jN#M9VwtNB#4PT@OvXVBa z7y|zx*$+!_ap-ssAcZ_>D{qD5Iwl^__YrLLJ__jecgi zlZ?KL#QVF%%8*Y&;fMH#Zjy=c1}%L6IB=*4(EvaJ$^a7ICJ!tQjK&YB9N{ys+iV1h z0j#K21oAd*qu$S;w09G}%e{Q?8J&C84WUwmt~0(YX^;lU#$QE) zPUK2vfbIpzVY?(JT3O|+0fH%NW0owrZ z@E2|RQqF^CDMHN`sgNQRyz3C}MBWxiT>)Pt0#bOH01O)i=Gb3-f0A2M6&jQ|xYdpx z%pG?FFFOaJm?j_>*T9$5bHN+TQ{n%>)r3B{P)M-n*p!)yTtFLV0_?E-m+z7&rZb=_ zd=CRi0l~dw>yt2)dHfnZ{0ne8ikVFD@2>!4D}bAQk^ss8nfG*6r4`p+o)^JOvyXs7 zZSlDP3tGZ}L5dpX{sVL=53#G@13*jK@GcqsnM?+*ls*N_TxsF3(G3LkzOWvU$dn%K z2|m3797YB@TVMeEogNS$>PzuqPT@i)D^{cHp8o)uL4KAuM&HW?%Ip1IUJ&5=cgDXf zFs5+1K8tj?c;|gltoM_L`6mho@H1@qBGz9#+y`*~8i{@iM>Ey<52&DfQ!nwMgO?Rj zUNQ&R18s0h21o>0{gXsU$qYWy6m2;yQoz-^^p&Pe+>GTX-@ntWY&%YNLl}uHTNch(B|$6{`SQ}p~XFU0~lJmpDV4u zY~>ttMMP4MzEe^0sLExzW*SISB#D-+izAO^6zRcF2;h|TH$hTT$}la{bP{9vrU^m6-`gsan@u+Ijo{(#Y0EV zPgv%VQgTHlbt9C0FplmOMZ}t8fLzR9Fu|9sU{#ORu z|K}0=uJA#Ke@#d7(5y<`=wnj6Gn|yM^VeG~LdE_UPN~2+9AtQ~LM^u|bsarag$AN@ z&2Z~d-Tf~8oEpnZFXu^cqM@%_V!7hWy`aR8a7+5Mr-y?i8~W3T^L>33ls;vbJ|A3=^tpS z<4NG9OMw$QqUNbK^mT(4X+mI?{ZN9lorhE52V*M``=P_$P4a|oyz}L7jxEw}tYBJQ zNn@jV7IPWwy8gVjOuJVyoeVkNhKe(bR5!5ljgInFK3%-ZveNu0Jw@a;V|6iiiX-yt zU-ytK5m*MVi88LEpG zaq_|*t6)CRC}$XN;bwwm1$qbN&2O1U>dp=z0vJ44c@VfbrK;*2S1CZce@nKA_^Br* z|96rnR|aaYg6kfvfBlFkVF%ZMx1)iOQa}GMq26#H8%D+Cc%N;Q=-Ms2zHlZSUplSX$+}RuSZcp;udi|6bvek&&Dl7gu(;fS(P8LtX7gsyB~M}_ zk8x*-se|*GJn;x(zHen$kkVd;Y4Yc;j~s}ZYhq)G$TB;Zkw1yojaaUqWaZ=u1t^7?rvkPdqIevJl9_Xt=lVu;n~!`tG7ON|X@UHdSBShI+2HIlKYVK`r9raZBt49iwB-`8C$1{DS;m|ebQnbeTZ6u;7TlYyBqmkvK2Ntm&;gl?eUKiE?BAMBO_Y4W0Vam_ffTb2s*7m|KTcqD75 zD=*Rk3$F|vnA##HH!`W$5B$Q{E%_p*+NgqP)9OxKC4MA%(A-EVL$wvm(t#v!`9|7P zhwC92AlJ91B(}986RHt6Z>p#01_oz^ATtQXUJh^AYN=KZG4JUcv`fb#1Rjp@BX}+%+Yihif z)Ixda!i9~vISwg!nwB30rP-NIfI+!aYaWZ4i@X~%DDzg9JDf~>1ScyOzj{CDCKSeM zom+BMYFLRvQ#4$u52M&!5GMpBY`}1Qug0om^g)pm+4S9k{A9|6N3(CC)JmV);$>|^ zSHFgJIL?9!EI9dT-rf*4oqBXjP_Aqs7u{>}kpLrvz>2{%edwAJGn?Av+S= zPTOcBdq_0j)2G;zTX*b)IVDV|K-x(K2i>aNlGXS~#k*PxeNLepNcsn~Wpf|D(N_=z z!|*42SzjQvD}6R5+Ug-Up7~5Vo!5A*hYh&%nq=9&xZc4+xBkL!V6S6B-1<0_%PJfL z^q$?OHz_(ub{O*VT%BkTDGlTIlv){&s~0mge?!uE``}8dYx=mUeGBqMad~w)!#%<# zS-MaGiaX*jKQ%_nmy{{O^es)x6!yd@Yh=l?1vZ&M&i5{yamBMtBdUZyO-)tb7j61l49+^6wdLJK^EO27kC2WyOVw0g zRW=XT1#10%cBi6Ic6~n5yQ>IO~eqFrAB z$$ei}Zl6dYR!4yx<3JWT@EkDfPFF;I`~e#I%4!SN2NstS)WO?hK(2cD&zgiiz|>e8 z$mWx9dJl*{C-n}PA^-JTq03$XT%ZAXO)1pJ8%jqv!KVja=nKCU@Ep@`s3{`Mz;7_> z6VO6Z7r(}Ut7k9TmF5zYpx<@j-ZpwWpW%ZEXmKD>o-*Jh1C78>iGcb9=epGh`QJ{FyUOJ6a8-U z2WYzwaM{7d8;BLarN7`ffdCVDY~#PmGNTv~2Ma*XdH6ZmyHGsCbIPA>oFaiX08b65 zmjnO19^g4*J6!MqS>^T6Er5Rvq%N`o{2atZ0ND7^kz(O6+*lo8NF3tgOm8RoT%h$= z^S}i^Z|j7eFYrNMv;?pf0|n0k7^LH&0)RUa{Ts{R*XNYRM|MG|(@VlG8&%vuQlIVt z&M!h1P1p|ffe}C_^(o+r6egqZfzNya6fDs#2}K!H4LX6v=R815xrpt{hN#EOsP~u5 ze}LQ~Q7oZ=138FJ1f0{$s(=^we)RWK`bL&LUUp~UDE!SByf?i37tWlG=y&G7AX!uI z#K4CDmyaHP#FelU^8+*_`0K%itk(C?$zBj|qZ99R7ub;o&?JDr0ah0ReuBvpMBfWK z^Mx^v=A0anr9pQ95KP61E!lF>l_{;Hoa zyncidTeG>W4=*a&{;#Wl0NC#Z1pGswz5u-pIPd@ZbXMv%^TAaC-g!!iI8p=FIz)&N z$4l^ruyYm#z&myQg+D!-i24G^iM?m=tG~Pf-TVt4^g<0`*#uWk*h5QNU4*5>`$Ya? zKp3!g(I+x^$qmRYAgMMnI#KTwkgzdewW0Y3C&&fnG{{o?S3Z}0{xBV-K%LmF|@K^vQ zc!vQX5>UX>$fdX&{Q?1~82n|^5ejk|bS{#<=O*cL5t0V)697=>I8lZh0t+R#0ULz4 zi6*RvHvsd}3`sO_5v(D53?EgII zIsn1}L4QS@as$Ev7}^nl!yIUN_z?j*(f=1msu25|ZdgfxJGQEKfLrvlGYH`S@<6x( zzSNzyn?P^qU3i#g7qA5xt-iwq||)5Z+O@00C}$ z0sWv8iN;7jQT+rXmld8dD)qc|GPNW@%(oirD*pyXR-5LXs+cidsZOgMoXpxz)_lEbrrmTcVu`CfM}tVQ)N#q{^zqL_kq8f)WHJDN*96ND>eM$w?&%BRR(b z5s;h&l&s`9qU1CpIp-XPoO6Z=o(BCMdEULwp55#02|xCSW@<@q5Q>zQ}Ovi z65$6Gq0>Kd2r+pPXVr8D_LQmMhu+3BdFAvYoelq4&F3Uy3hY&R81`KdU}*-}W*KCX z7jWHzbT48Hhyt3tSdG5P&K;NBr?ZBR91$)#56Bq@N$-Sh+DBtPrwla+x7^CSDvx)I zKkM9BX|N+cKHbCsM=BZ_wt#UU0g{gb$+dkC@o$*99Qd_IRmr(p!()z`NA(nAWm7sR z<%`no&xoZPba#{K-xrvGKp~^*TKH^3(IW9)BPH#Y^$-0~=l&Q{b!(HlC(GmL_X*tZ zzD#ALAmb3N^N2~NKE#50TccheK~7j+X0($N9y#zDJ)Q@3|9Eogsm;9!c}Vb=xMkpW+)gid#1<)dvSAA%jW zZ1oX)Bey~AGcFlB0AIdbv_Su|m5IakT9SPOp9f3s@2pf`+H-rThwY}`{@F2#R-g9H zi80THcEQ5LQ5Met&yo#bfvBkM!W3t~IxjARo6&&((sXSfyX|iGkPpKtoyRP%+m;OW zTis>r6bbBRN6W!Lz^*eA;MN6p=DrF@^rnH8sleq9-c3hS^|?4N_V@32-(4bVFuqS~ zqqc)l-I_bPpW1EgNh27x?LCpW=HLE(Q!*mMG~A>pChqDO6O^-YmZ((gGo{F8Q-fTH z=AhrlX53d&{dw2eZr@rG*wUMkOFbW-eDIwfOL|=y>)q0Ub^)iH;5^~fQ?AZBW)8jd z7J8%|ru`(QGFHkATiHJ=9e|lmjNXJRjMN-L$emz{aNsvj9HZa53ASC|=f7}1TW|j! z^PTZeImof4dk^^oY|LnkxvN$-0Q*JEJ`j~pm`0lfmN%!l7HPcuZKPveT zY$I~d=e8UM-xumKDa##cf`tJQ_0t4&*BO=xn^C|D0QYwcxQ3E|IvNYy%+q!Q7O?f= zdG#>IqGs7-JgP6X+dsOWG-svVAiNsYK1x?|G*xoQ4ET2)W8{lI)N@6&wjOI%dH`oe zC7=N&qRk5m=&vpv1s7UC?IxkilzR5deh#a0w;2T=2r^!G>5osyG|3zHceAf1r7Jd9akiunJCG&Z~emI2>{?nYUy_vO<~8HcTl%L;O_jR zkO_I2NS_M~k1hbYtTK2Qg4sha#|6~yS)0x)yylvsH+7LH3&RiZ&S-ijPI~|P54he) z*T~RuYSX8tj_Zdoo?8vIF;Slgd}=1!#!?=y-99T%9kJ|5X6^{9qpnZR9U0bfR643B z5HK%^cJKWe&hr5;9A|mFV5QJSR9gCt9VO>GW0Dy;dXt^|A}R|yfmwv4Vud`pGIgo) zTtGkM)}A(FJdAVrH+5}c|DwH){XQ1uZs$i4@Fu0~?!6dx1rZ{qoUE)@IQfEaR;!mo z^4OYYqPN|pVEwOwUb^3cZtXab2RqggDIeFdtx~@%`*2eXp0TXDSFB53mG8ZO3fp@F zl_o<=Q86B&LweQLjKbPAciqxECpOh?{$6`&pP6=}XXG}o8J>@1s#xdRzQ6u&;0ymb zv1P04$7IHr-AstiHWi3c-B*WdTrwPgPRNKO`-Z0YGLA^7kkT>65^n#+9YAgPpW%+a zN{CKT9~Y>=&1@pp%BX+mE9>Ndb>xk>K-Cn^`e%U11-(oO-_U*u41r1ADbew>SmW!! z7D+>ZTdyTkf$;)47^B~afr49GnN0OgIA%bzJ5s6b=Ed_eEFNqSEU73f>0|q^h+liA=dHsA@4ukKb6-T#=x9YR2(=f`i z+E;+a|Naaaj=>9@bC1jHx(}S8Y}a`?J_uM+8B#wFEgXGtecXUbHPow^N#8-l9xjb- z0sDO-D`b5b6b=Apz1TAtvhWLXAZg8VkDMd@I>X%kHKqdUxNyqJo?D(~eV+|*UkZOx zb`V?;pnF?J0@STW@ml&l(qA~k_f#AH(kQuS$C0=0lbL>~)7B>glUpWKaUMKTOglLG z!!gKNtlkV~;y~hIWFgACxD!s#v6?vSbEd4@^%?9X|tPLzcWt79I+Y|^o@_*viM%Or7#YG*pC76zfwR>ieirqez+Tp z#l(mk0<%f%I}G_9OE!F{fI;?$+y=Ld9d!!FNe!9RTX)5=JpL^LO;8SlqTg4X68DUNCrV7< z1YGE%voHE!6zJel0H+<~2}!$75QnJ)=t%um$hTdR!wtYO2o5kn*B-Z1QZ~IqqdNf(zdx$SXWNOdJD|kIq^gezdji$Bv-5kG;mVv zwxd77AA_BAE}pWaw?k5X(hu3v_$e}Di#cnKdRCkSyY0BZ>wl0HPchZoA^!9Jve@bO zOF64|(+9WoR)Q3;o&&J`NyN_>+rQr{ZBEf}z;F=sB?}s1u z0JXi}6#p|x!`xU!jI&M%xzMd#;BF{KqVZuHY4KN8kB#qjEFR)Ot?<-p>A`kIZ}|?) z4sLR-h-zUy9S{e^z_%i83!*_h)sQC-x?`sp7xe_z3|S?B-JYT!)I?y;z=4YZXz?+& z9H$ygpKkCJ*6fQ(=9(4ZUC?Ye)!@25)>Gh54~wT8C>=LQ1r1migz8~4R{=A7bbwJO zK_NQ?K(+b-JU ze@&X&s&Yvc^5$wUbV}Zw(Tn@4!`w2}Q|Xm~vQsV4AnxljT(#L`GaT1w4Nup{O{5V!0Vkx(_>Q2 z=bER4Ba4GcwH3}+(~fjp7^Hi_7(Qg~)NwzrDDf{Ya_1ElP7OWj|Fy@9>mNRf5ztuu zXcHo1yL|S=Zk_yJtRB#UaHyTqT{scaq`!??UdT)}G&E_3&XQnNyKuioy<%4A%@lL! zsFRN*Q~kHcjhU2qYd-e(r!(`iQIJ~5HpcAeI4sQgz!wY4MJRyKr;eN!3q!6_*eCz2 zfgz(?k(2R{IHV*?5nfM%Y!{f{r{+x&yrfjc$(WxN+?md`m)Wl~IMqByLjx*fA7p2D zHWXwM)hpoB{}k>It8G`3=?OpN1m&NX%~fT!tKgHqy@h5^S0@V-*y2Sw^n=w5Z+hJm zykRIwX)QRNDu5yZ-k2Sl9vHCt>ld&!o4^h~zk_T9UZ#CIIufj|)Vh0oh{9k4)?Erz ziZFGwP^jwRl{Vv}>UMc&Bpf<(j$NAS$LND~&zNCfjP(E`#uvC^j))c!p~sdyOrqQM z<@wyRWeJ&vqA_dRjPHrsw&L_>u5XTiSg4agm{4rPX2g>z>xQAAXGSy6JCEXME#27K zlz&i9JAEJ39+b6vPw5oixX9CR8y0tED--`q;3ZqWE||XKI@T-3Vg`XW4_UDQvZ&KW z9u4-qpn(rrGQwMs3(tu>=L zer&^WQAZB4tXj(TFF1XxG_sp-gbGMaHB&$Ac{zNdRUbv(t`~cVyuO$fZpNvGacxSV zz7k-XqSv;!!~c;q<#u%ges{%?2yUK0yl7q9yW+Q2HrcKbSw}TL0y=DX~fZ`MG!xCOt3pC5eP;!q&3~gOLZ^*xLR2Ej*etcZTFIm zM0$z(5}HeF71V+Iu;SBQt@#- zZFhNC-Wq&Yfd0cY{f+hD-6turvXMaT<7V-F_i8wsV%x2f$bVwZl_p!k#r~%j*Uh=g zD8|ZtcPvNJ-4Rc(1!tA@707$Y4qXp~86fx^_7eRN2(Z0Rhd|U)r_3RTjDF!f_ercg zA#~~FI*EL;-l*K%s02rR0q&~~WRUtjMm(=D|3x73vPWG4E3YH zedkJqaX#a=1Y6;HpSVNc{R`(0uCBnJl!T2w!4c6lA3PimlCF|2FSv?$Zz(1PJ<3bTmv0(6b5KXXyzSj%RQb8QMu}*e6 zx<99y9Gt=)pPxH?dJmP4#LvB2bHdI0!1$+Yl5mw?VDl>7FwYfT9U*vA;TyB39=tz> zIw1UpRT1)3ATRQuXmmIcO$&MZhPoS$_)4E#d=F zQ%v%Q!T_EG(#u|^IXck}Sjk<>Ek|)>A6UUqrEeV9TKWj%T|G{NVL`(9nmi$wKKOrU z>NDpoR=#1gLEJJ4&`$vKUO2E(+(38dwnlw>$edf@6clUe*z^2)0DCEs+$4HR)ptCRy>y{bqw;U>3s0~pk$9})MxS}6kB9i!14 z4_{8#ZQOV&NoNE9iTRClH5#w;DOb`_%zg!>-g(U4l<}pO`Z&c;AL8+)pQdQYzk0os z{1gp8LL5eISi-jUATFTd4udG$&$86?fM}JnlH%|StxMj9q4`oHU*9mAuHwzwPtAPG>OQoAtnv}3&C5>)?#LZ z^={d^DUs-hxv-b&%mYJc%+~w8^^w50HgO;@rVDL?$<3(_^85wOc6;ip#oYCa9#+(X0BmGQhQI}gho3dsbWR2iroDsDe&Rf`v2^=2FT}umn+#h8IB^}90 zktxYEezow~ed6bK@3!h{D_Dv^^%UD8J5<{p!4iObQ?B`d%TaLt^Pe%)q1f3yLbNUD z%V@j5w3?-V(iz!%%bvkrOxQ1G+>7hB0m7wZk0XABe}l_?dux@LE0rtZA{J(IK9Q`V znDlcXpZAd^9(UawJML5H zMT3(I9D0RM=ZgKfDnc$RxTWW?$muLv(5%_(ak*0l3(%Y6XD&-d{-l9I*=&@&Cp5@C>P97zE5nZWSOepVbRK=@xy)^OAIEu?4NISXI7lc)w@F*JmYG@q z^}Pp|G0!&-Z*Fympaj5HNEDnUnz!tN-<&w027kI}B`H zpw!UnZKMc|Cj);H{lOG)0f5+&clO&@XRsZ*(Ssb0D=i&|AS`AF1QC>S&RVQiO8xDt z?Vs=80r;``Q+@T#qjyg_R_gUD@JEisM595D%X9$tTH;9Ae|;x2#$L(pI0WHC$KbJ7 zVv&c-7AO5?ni}wN=MNNe9UcN913hjvoOldj2KeYN7P#I60!|b-s@8#9B5@-CXhR)Z zFck10r1daoc`L)0VB6b3d=H>+LyC7Hheszs$e`FOE`Pc>wrYQJxcz~W27tys-)7FL zGSoYe=2Q670Dul%O56q(GJtev0L=j07X3&paB3V!xhSEq&LhC0mdBEDsBAOW7k^Sa zIiYe#Y*7P3-rOY522|BMB!c|}#_P}9C!HbIkNXmz6b9iTt6%_b0te4a`nPY^BR)Ml z2v7mu1vuIVgsT9@I~`~R(u)2xX9k9&C$PUM zN@btq9x0rl7XggqL~E4rJ_LhbTZc6D*kx_A*8s>!Jli%7c?b5br^s0qcP30dgP2Bxp;4=82GsG*@{r z+~X`M(7o8Le#ktSfSW7_Djf&nh4hE3;Ml-T0AzL?Gom?QH_=?!$yiLCtmq83UR7YX z646XY4aZ4LOurG>4LM1Ak~u*Du$qhJF|mJRK#>9Z`h&vLwP+`jT@aNS`Sci)OY88xI;oy-S*WtPe7!|OQuPRLjY@?bi>p=;J z_1hp~EcYY_>i0yz0p5woV~o^blNWk{Gp{lovj=jMSkO0)64CnwAWj?bkzb}|-63YC z%yE6)ZI*GW(gF*EZIQyfLF`xz5{(5Db4-_VKtBF-K)zMTdeNWE6B;n?zk}&mcbgG9 z2D0+SRU_{=9>-Zsq+>Q%7y>}tpDaro>8UsZa9wQs9Zz8YxWZjGO7;pM}j7E*xVEJrY=<6bhYmFSzB9dJl%l_hL* z!IB#Hn6L9LXD}3Pr@dxRAPsD|P|95*SaY@E<+8HLkxy0?L&TF_&Gt9L0g>VTw?bMD z_f}uD4s|fm3DMnY4@=ipZ*a4+d=-AQHaTaVV?VuCUs`W@jdgK=?^CjdV{qq^07X=c zvfkL4Dcj1hn!A&X!>?$bkvvjR4vf%U0?Da*8zf)cVDM$^1*lMavi?*Mk9={jZHm@F z$Iu$bNb42&_)T;t0gE?{3yRujz3$uKfxnhkR8esE?LZ6i`t5hGu4C>T~*WcMcuE_zaCLwzJJTer(rRvhavQ>Gv6ml+>dUIzn2QjLw6Om! zWp<_w^67eEHhD1FV7522TBcHiXA6C^x6> z6!@8~?iQ-h#wi=ZHOV+`;0ycV&<(cP zkyVG_DhT)+m6Sw6@-_09P+SSx-{oTU2*18*mqE3y`X_ENYh`vV=rV!YZ;n$%<%Kcl zq+XjRUmT$&4ZJH|UA>+lnA-^QL~1%K_@GI=TM{-7cD&8+dvv6!if-Jz_5#;4Vnk$H zD-4!Hrm6Rkqt(n<)l0lPt=C*h&4=N06!WD9n{$+BgXi+;8_Jv|rS{xY24vauMZeUh zJ>Tl($v-TbIIlcVX>NM-oVx!Lhj&Y3nDp}qD%>j7OF~|ws-p9rJE(HMymMoi%G#bL z9@(@0IU=>sZK;&ELX(l>Wr+gfDlapqD>=0ma;J(b!*A1_MLnsndd9>0ddtB$ZaV#Z z*$8ZR`2e^b=NLD1qlq8OTTwd|b-z=iRK~%@X>7lH-UY*!4n(ppB4jIV@0HF)&3?GW zXA>S%0U5TME6-X;ee_G;2A+|!QMZ`Jh%zvugq5MGQR)e8FO}~&nNkg+N9;YCo%a{D z%IYJ|7pJzQk5>3y^Om_6N;CVSCPVZ`4itH2aUlBYXg~|f#VMUHClw{7rOw|XP&l?iaJzd$3vz-{wpg5}5u64iA{khS5 zO2$TCLq86(55FrX0CL1pl4IK+!=drm9Vy` zY$u|DsBo+zG{u^%^g(L)gC}3BMQG_t#QMsCM*t0r)L)Dt%8PX1XeE{FV6Nbw5j<=5 z{&Kp9;LQAyYAyY8^d?rte4sPl$&LXo1e6cjq(N%wHgV4 z`YE_Ojf^`vpDJix@)wnTF0GI``?d9z21Sc;pqbJ`?Vag72=&BR?Y_>5rj#sZWI_{D0697X)+gnOVSB4SH6qT4*~PKhFe&L~fK zLWJ>YoLzcD_K8$2D%=Yruy=Mq6k=5qS0c7!S?c)XSwHhyQ5bMjgpF2Hvwt=opJs|= z!XcTASi{eS&d78E!(;_p;B@?1*x>r0-(pAfJYl>L?3PiPddnNt=1Bd(yP`kx6spJX z4HW8;4Qc2i4~w=e#uMbAag0|QpE-N#6nrJSqiENos3Lk-oy^&gq%S>6{#*3i%#8S#a-5VGpkbh(kz| zUNcj()F>Gp#d#C$ufq@8Z4Rc9n|Xw&{<}rK(0Nes=cw!Cv!5JhiYo{b<0m>+pTDneclg^DWht}$i;wSEZm z`s5Sp*HtKJT+x*pIOasUu+{#;X;{^WgpONb++4b8H@i$Bz$|Ykz1L2#U`!0B8Ns)4 zi=S~#rc_NoWNlmF2>phBVAAGa@FFWWA8#tSzsb2-UYK7Lyd>k@KekXE(s(Ac;i3W) zUIXt)2f57U%94T}?>g_djAL>=E0$E^@qPtsKfkgtyM2Ff-T0sR(@u7bS~63@{v7UZ z(;cEprl2qqWIn{hCzy>(dn$0oJ(4(fN>tO0MN)$orBNvVh(z$Y4p~6U#guY^=t#jA z{NCo3CLBQf`g%R&FU`9-Uy)i|R7&ymx7(>Q!kq!rH~Tx|jccg#m^XpM|h z9FD|)BMq1h#cix!9RD1vRasv0-RHG;+}=^MW_zeM73qVQTmz=zVlS(&ONbR=%V06Y z(bzKJp&dTq#XlSgs(=XmgZ8tYTQS0pObN!%{rNc88gL&_F?9ov1q=nrr91v`TJxOB z*iEEpg%z#_3h+A>e3SKNwrrpRM}|2!$Qd&zuLnsPy7Bu?#!DE=-s3L`}51J^SR_8GZ4DL@p8R)Z~gCIII<{m$#r0b z2e9hfFI_vFPa{1)m!Vmpp@T(Eg3^_RUWj2d$!B2o?12EVlh4DZW3URa;^W3IV3puM zu@9#K%&Eeq4y3vH!g??Y3MdneDQm<_iN5*DiVBQOw%4Ae&D==iF619%N;!mj;eHk? zx$9hM`LYk9#q36dAFo*R=L?E|55E>@=&U%2Vph0pYNMr%EQ~B6&x)q#c?xGej7K=G z_S~s(=5t~@!Xk3p$?dBCnNllND?Z;~17O1zzI^LA#9lklEq`e}sNK@QEQR>YgeAd| z;jPcvulLXV+?rYvj?GYH3Y!sN5}QM^zfOIB_QjnEYl0DPUiep3LgXpQ(Z?n@S^DiQ z)X8;02aoAf`(!YYg8ci~4iJ^Un|$(_@j8j1;uNiX{Bi#GpN)6_|3sFIL#MX}p2Z@x z%Aa3#oq4Jt*LfZvgbcuP2QX+o?5&UkDXj>CRJ(vLvY3vfqHnfAx03=JV0 ztSAz6c!Jh0%v`}Bou@_cGDY`NGi03Zx-7@aviUZ9bD?s0UR<&h&F;K;e4LhIN$DuV zch2_7=O?4hETX{W;S-5LAyG#Nv;_UedlNlmC5RmX?xx!3bPyokwRFDwP8Jc{3FT zj?S>~UpQCPc;Up0NA~GNqeQj_A@+EUDb^QOlKV^Id2}`(4`}igwzdIRkBSVb-uJ9S z6B>co`upRaB%%VeuPQm|cU#nGiRr|4US?tNY0r~$Jh`i;8Ap%4(?JZJ9&XCOf75V$ z77cV~jY;I;dKL@`jF^KldtVP|vqgnQ-ms%-{WeOYZMIce`^-jde&{T zNw$8cU}m=>vz42J3y4WoM+dCSQsO=qf)&tor`wUe0!ceyXo0N+B_5tQjy_K6iT(cQ zdFJ>cC2Ygr1cn4F_=LP&fb?n67*xkG>E)F+)8PDJ#8FL|L_$>SXO&0as1C={{=&J; zm_gS3a9ZAkw>mW~Olg~!BlbshM$(AAC6vpGRb({9BFzYT{FtOI1Y0IcY-XzqCVmr$%hJm6n z+B9%=K?)xovnwj3nn36jOOq0KuOX8vbv2!J9RtNmNa6aX^Y)VUpmVH%Zke+~a=4xe zLjs~7fXL;4J=*ilY?;a%XOFwZJk~0A8GEYxj9h$XO}udr4Q=0h-nX-8vj{1$a(3Tb zTCx34SSGKVpuNYR32N&K7-kHvc(1Jeo`y zdGQlj09P|U6|Hg1GT2hI3*GClMAcijTJhZgbeAFlZaqW|h-*VC1F~-dl7LhgwF4NK zWZ20h>%=?p3K^x@$wPH|a?QHsAbo)m~E*-_zEOM60;h%&^L2a;!l14%zIJI1i594Yk0&e;rrtT|8d?lAv*=ONf zFZKucqtr+uFY4{98~vbMa#2eX$CkcM5GL(;m$uTl_w9qjefWW@Gd_C17qPwr1MwgK zdMYa~ew{NPMogt|gx~3@YYcf`Axrn^v%p?o1qbZ4c~DV_jPtK2(h3-C^ zll{zfx3=wmY5AMB$EO1Dzx;Ot@E@o&jL}CL{KD}+sbHv*G23!)?!{O;t79^vU+ zhHLVUG9YiuUY@E<eTm( zb7JW)@p<G#hTC)`7XK!pgK6 zduU-$xz;=MYA{F)n5viFZv%`lAN(@7S%CqJZ3AnHDQ|(-iSu6QBydP5?-UeYT zPHQYNTN?V&t3j3l47^T*&)FY3HZ7$K&hrr!`*88NhmUGgV0*M0Ifo5M?_FV7`yr`Y zUe6!$vb#Jt0Mm7-m=7z1+#wGJUKE8blI0^*b9_ej>27e9{EJWC;pf_ynteb;lvX>O zYg;{Jh0AqiYw~N@X0W1u`E!4M`Kh%M75jOx!<4+kbGeyg#G*Ai-^JlCFMub~(o7QKiiDwUD!Y5PI(Sxb226!K5 zH1MA}HV2}N(z@+(AzJTSUPa#$&8nXJ7In_jnT-3654~J(Oi{8~vbx*1DVEph!Oyj( z1g+uh(B5F~8nL0Y^#F}ecC76?pVfO+3NFa<#cEgIl(=QEbfc6pBxtKI@?1Hlh^ z6yCp)LVu0L9_Rr*qf;=Ut6mz(p+o60LO_~jE5W;`j%L(`c@#Vfz*#33MdJSO zF&Z@+C>hAsrVAJb*!iw%8rKV{gL3iEMARhgAWM8&o*mXwIDpwepjDI-Sdw32KA+ob z{l2j*4cXdu`_o7sLbLg~RhXLBX&()u3RGTm6Ya&_rSH&hm0>xr^5O)Tp+%?N`I71Sb+cO<>qQwzdU4R_X0Nn!|2wNe57p zT6^9cs~*0h#zJfO%}TLjvc;rWnv+w%OaNj+@#J}9?%SkGnL3}lFvu zh~Sx{zL?W;fsFOPCpG@}U;n?MmBjR=hojGfr{c1%JPLlB)7T{y^uwm}TodMY^OXAaaF4T#wRnxs7LmlgiKobHd&Ry8Qf#zN(Y|u3No-;D2Rqgn# zrQ9U!8tc!9cFH3)#q+7>TEEp@+N=m&-M)tVVU(L^F|19~yX8sN;0@G8)1b#|vjLxyH;A#2W! zRptaf9-yiC%D{9znT6>RNdws;>J0>qf*nwx!M@ammD&f{10oX#+ci?psl&eZ5)B44 zk&-DF@`U4ni@q#*w45n|3)+k|ioX`W-8780?_pq7^k#{>x0BanwTJc=;wk-cLx16p zp{iHFlX%4H`T?lcW7;fqbPTl|OI{D8v{(!{>h2}{lmkHw#GId4;nh3H>XmNe*ghm=Opz8*>&!#Pw}#IX=f#RN02UcrZvpdCpVV@?Kbn_z2&e zb;lus^`4QkaFt7HCXAibyO=y03u90T1olHvFsTrn zR!-3JM^9T^eEsvKe)^KM(Ti^3Fh)T=@xm>+Y|Wn5$Q%M#VR1Qr4od+G3EV-1W?!Yix> ztNdTY(Dj-VIL20pD+5`68Vm`08@nge~hZa zfU5CdfLjS1)%{rr8pB-ZBP7sP3c!xM+$l1!2N+C(4vK;y8L|iauogdH8b3jcXmF1l zY%e|We|(k^|0Y^YvZ8RQ`&or6K2|_{z^49(X~w!uGlD%NO9Wv(vBxU`y887Wrkh9p zTj2CZc~0l@X!NhSO>gF|E`uVYU6rs3h){3DhXXHA#P+3C4%uVwFzIa>bBUYk-)2QD9O#s8*Dd~`&oREncdz~SixQu8)h?s5UQXtIHT4hLnuRTqo;Z5}(}MwJO8jyq9JEf`Vt+SMz_M ziAnOabV*}aXFEUl6bk#TU+UpZHra~`yBR<%xv*WtO=EQb?0ls&#SjMww#z{tkb*KQ zDtAU61XIdzKI{-6mYR`gE)kXGRkF}qCut8lp4uMV*D2$Oar$_g0aVR)(z!1Y&cARR z-EB|a@E`}bar`s?IGVvWtZ&87B+C~ZzLLBts~;FjfG5_A`TNELC#=`YEOp0j^<80k z(eY^oZr%3cH&`R>*`kjg4Y-fyaUaa|Aqh=muJ=|k6@Tx|p}u0VM;Oc+Zp2)UqbR+cCa>cABixM(>>jjvyc4{E%(9(c}`Rk?>z zB;f3g_AxtTRHY%^atk^ zm=Nd+&^j*9FI!{59miJ@@#$5uw*hCRj zeu|2r(|33iW4Bw;Kk(4@W18$kn~eA_BQpDkTdU2Ch7Vbo+hv3$-AJS>A{4t;;70GN zIcf>mYGEFs1Z2?PL@htY_46ANmjH=de<9;=T#NlX2wR+jQ{3Bmrc37UoIW7@-|c>{ z>izRjw++0-e74uTcC98wplX?2h=C-);y2cb97Bd^ULuFA@@-nZ= zWrbP7?_HBrHGins^fIL4DbFw{&bP^k^`JJ!VDzxUQX^OtGNxIXvkh<(eZf2tx+{j2N#Zv{E3mm2YbCA z{SHpg@AH)5?oKWdvs;DcG4)~k7B3u}zSS{A>47}C3egQAMG+oFiv%H<)76zy)#Y{0 zgBJPHJ~W4&zVVePCu)%!mZfJTSi&XmpD#g$oL|aUup^2}AZ?X(H|sKdko9dOEA6~v z%i59M{k-H=_q)eQ*wM#lhJsSV=$FU&*<8nmhSpylU6A9Nhsn+AEn1^diDSlW#uLzG zjwgf}yj?VPb}#Rge6miu#Yr;02Ke1&yz(iCcPq6hJgC8X+UxCa!VYG&yYpP7k3Ps| zsB6}k+EjK`GkS$gi*63bW%9*3DfQ(sMpT0e*BHBbFgsNHpDqVDLZ?bw1eWy7u5e z89%OWh@wa9IA&jq9*oAG>Chkih2!M5Ft=lN6ZrgJwq3sG7TiXD^!inkI-Du+refmW zLyH44XI|LyIUB@jczwA-)7sF3y4Cm!RrI=@rS!z~L5Qn;b}(CvjI}JtriKlm&*;$H zI*cCouj1)3w}TPts1MZ|CP;={pyhlJCNmQjj0*~dZ|J7ebX=ppTi)HjH9PTD>qF23 z$4)8MmKSC(&~{XfWP=!Z9c+i_J76K8kOY7^VFPmlssp0IFr4#z_oK%{uIuOSfi2eK z`v--|2x-=s`FClm?st+wju(C!4AB zy$o6?w%57A4rTY5EUnPSRl?5}heXxJFW23c;gqq}Bjkm)aiV$h+T5J8)9G19O-UQL z;^}DRiF>E*r5I`Zi$|~wfVlYbe;EBW3RbIkgtLg)--R8lI<0+i=vp-kNjr+@*$?f} z^CK6zIf)9oh~2i!C@zZW9`Km(`K0pB7bn3cFaf(eSbb8KUR&TlfI_7nRcyw^w3RI# z$p=;Xjm@>t`fIo=2fAjAkSCS@v8KdMuUy^iYQ0rpD4o$85RW}xtjQY{)y(zz9Pu$D znvq3vOaTl9{=QC^Qr^nUY$rIup8(7MI2<*PWc3#gDP#dR4TkIk$uNbfNxF{1@}^^a zK@9cdKi0Ml{Uz8Dx9cH}E)%w29F4vpMPM6DQr~8^;1!G6|2K&2_=m{iO9~3(;_~iH z>KnekYrJfzw*D{U!%$gWytmYbs-(1MoZ7ivPy_nELqaW)76$=fRfF44j*rK$=U%_K zU2hHLU(R0S=ig&-h-J6FZFrn1T7$$()hnEf>R986A`BkjpLLGu1q>2$ zgkzF;!XWe(2VnpSBA(w!z*Q#J*5>Ka1hjdHF{oBInrdfERdPDtHhv*#j@liAvlq-7 z`RA$TnMmCPY;-e!A8~8b|A(xVeNeGk5Ytx%rIrY)^aR{;?Ju`HQ8%W9xN~90)tI{r z#|Fl2DPDIEDNtYfF4>Hq$xu-R!_|Wsz2=|$Ia5dWNvp(+#aoB->1dC5bo|cv;nc;RFwaXK9RgtnGsGYn2nRs(YcwDsS{58LtA# zGXJ=!o9bLklLzLD;4P_uH(5^(4Lr9aJgl`456(F=L6)Va(b+!#T0XBA)Dn0jG(7p- zZq<+1u5BCq=Ae5w*FC$_?6?RuRtKZKW}a$qu5WVvSn2t{%GEq6ou1A0A3>3gk=kRK zm8d(CYd_4xeE5?@dDh&{spmk07&Q29vpn|N4{zW~kRg>S#>on_z3C>U++VmPUB$G? zoanu?ux_EBAf58z(bZP9|x96MmtJ6V55fwYQFx?Wf5 z&fV*=3hmIyPnM^#Kr7i?5j8!Cu-IN7_efT%EHk&tjo@X$ z)V;qxk&h9t=u!SGoIXix?HWA8c~Jy^%Ld|EZ_vzYlR{eVVz7|WIy;&32cD&_2dr(c z!{^g&tC%jDKnmntSY3!FJ7Lzo#E~o(1{nOEEXT#* zIm`T$v{4b(BEK=M!0z-Lcll9l-2=;`mNkl$8G0uLD5tT* zjvqWLpDNm}bTO&p2K#Y?^BzXk5uC^}pEg?l*o#Qm0g8z+S{CULDNN0$*O5s&7eS19 zz=BUTh1{>8X(p7FfM`pjWg-|LUb-fuCY4`a<-A|HQ587-F-IQ#PW1w*CVVAvYWE-p z)SmuJ*{Qtp8D`3$hH5;MF&k}DZODt{^qWWtN~O)h@2C51%Z-_rHPTF4Tg)T2!EK9-3=?VH!rVIxMD+jiP%-r#QL82)EaFO%})Wh zBVTiPwzalr^<;ui`slqq%kQI#HqB9X&(X?@{jp^G%M#W`6w5FxI_MbZkWd)r>ZXa5 zd}A1^MG`$aNMcj&-Ks@#|D=8+sgE0nfdSd8l9;b^E~81>xN~X;S@jF*y&p?bUYJc; zmxS3(OKQXmn}&L^haEgV`#PSrN;%{kh)5-DX7#z3o_I>zf(NkoP$_b~%P3QXV}0Pw zSqkV0%}PB`O$N*o-DLDTb;Ej>27QCymWN!}sQyBcGQe^#TzcV;s zv}WQ2m5qp2y86Jz$HE5wWLP}=ZpBpShXPxpk1<3a+%~7k!C6XESMs)vRUb+PZ1>DvncN>KJUj z;Pk@wcK2{sg-Cxz+u@nT<*NZhLeDX-s#H$O?hGq!^9OD-Y25-q*2fx+u$rFfukYFy zbK{TdO^meKGwUkqH!te?heYAI*|y=kFl&i^<_SrRBZV0y4-J`rhdJ$ksB}fZvK9$( zlT9oY+&4(Q{P%p-+T*&jhL2M=$ahmW_Ojh_mb%=caq-t@HO#h46qc5i+-+cqwZ?fqwfZ&vHBI8Awsi7^okE96Ur^UQUw#&kuZj95 zx>v&+r0G^(yp?R}z2Zn8Z`v;WnMC`XO;{jVe6_pa&CCHPTBxerhi*$u)HbBu{Dp5hay8?h`r^~l_Iw5b6n>SyWKm^Qj7aFs;>$U ztlqG2S4&ahZ1-!6#Yi-J^{+r51nn_g9g>jwV94%$9K}n&LChdegTF7Bq_oERuZ7?L z$!Fg2wDY(F<|zkKK8#uOTB0*F)f|C7SagoA zzqx?ZEwDnJKMZJs>~-vf6+5Uhx&!YcT9Sbq^V#| z7oXytAgSKsrymp-87zZ|GoJ-GlGI* zJEFjNn-}D}9S0y*x;-KMje64>LDe*E$VXV@a`t-Vd{Q7Dto-w}cP#WrsH9(ApZ3g> z`5Q-fUeNVg49vY;*lN#e^u=~6MK1a*1k#Fb6)nifuUV}7tvRXT%`HSfLeSbJjRacp=UQGqz!;_UHE`M?I( zfDG|D$CFoc*!%)nE2czekZ6Uj{RtY}-{-Fve zg}aJ+z?!YLoCg%V=pK0V!THK3VtfJ+~tG;}ckxJu^m?w@97ml!so{APY4!iTg%E8o(nWsG=ip&o} z(PRTs&TNR}dZC5(X%)vRF+cRi#xS5|eLKE|s06IPtlA#DU_F6If^03zyVK^8d8-yk z($OUhk73}}$GnBx9z;+tSIM>_oU`8HDqR7~JzRL5q<}BK2Gt@hpwZn2h7uhRX&M_qS+CFXd;L)DbMO zl)@oPD?tf$eM%lKcLt>bthiF-aXsy{v%?+}-H;u|aJ`kKgE*gR_&NAPRB@Mm7oAVr z=ceLv-oi^X<|>_p_ZZI4lz`xrLCLG+MWzwqeuIwX}j;y?gaKeW@KgO2hAJy;8 zEb^9(pY25I@**=B$d}YkZH!v>*MqkgoYuC)G`gyYNn36Xx^bNxA!>mft8N99B`3H*1?=EKp#8~Y#$EojM|!osT5xg zw9C6_}YK8E`yy21Ng>rKL^J0n%tXw>VJOr*+f4&r*(D1?+F);9# z$jtx0EQ^Kova*~Y$M4R@Kl1|b%?W2Dx7w>c9ua<#9FJaZZ(41#UkI(1MMJT4e_8$zu++HZ4$9}EgCiGSv!ph8a zFtD$oROH#Vg#~!ajZ1}${S1N>KZY7gBO&Wxj*QZt0qL153h4%8qb*i2FE*ne$wGw^Dw@J6|>)YW4Vk%^cwYSN?iG&<%j}-F z&yxR|b9?~atABqvPitFqp!kBc+O{CkKvG%XTy^-(0D&z7rjUCw^gQI>+73MjhEPXu zKW6JmXD`=Umm&)zX5>Nz0;M)rIm;}WZqc8th6ELd)$Xp~q>kZ+(9We_-{v^ipx2$8 zwF1en3T`Xa@Kcnhbyy6pjaaWJeHAp)lB+bU=#TLhGB1mkH#;_uUjG;nE7+z~yqhy#oTU!i2{r?i<( ztH>lj_6oz=WYLPx?|ovD0o1z<2&&!lgmIIr8u~%N-F#^G&W+F`d}psR_I5KoKmJyP zEy~_SU&%;L--9`**{kHOTA6d`0bIsGKuRoizy?DAfQt(TubY9$w zRLj>v?M!7Y(wCS{D*wG|J_#vCRT)CIn`du+!G{|uVUHnGaRElP1^dzH z;GRpu5&bUt@jM9q&Rbf7*xk;F327$i*6elJuJiKS(L;dK9RH<9c~GTpbYiH?D`VWS zD>8Jl+x(5rYG9SFZGb{uTi(pCLv5`oO$UyYKf?G)s!)uUO)&6IjM(KwKkamT zx@L-BpAnm)`0&M|EPw_RA!4Sfehou&OLK0A2=9eBN*DC2__O?GwC{sbHuNS=D)XK- ztac;V2;S?tvSojo-z0~qU6gP+1UGSNwS&nYv&y|QgSI~+c#U1IY~Qt$`*L*^66-?4 zI(?*l!8Gq6yN4%?wJaj@R>qA`^~>_}8e6k=viBpsx#VsWxN{KPo00?gDZ9rnr*Crw zufrFX_T$#EEU2j+#!4)3PkzYuwEN&@55H1q-QS%Z+dPdfXE|;z_m{k3tzuWGR~lV^ z-XwIk`|SfO-5kt(QlE!Z^)j33-Wvrd9rXKo^6q0#ifY2SF*}Ee zZmlj zdex~ds|%6`yLRr?H>OF!7M+6xqXEzm=vi&)+fj~>_s?9@?<9%}rVrE%XMH|vc|6>+ zFU!#fGFf!)R2GdK!HwL}z76%(YRbp!T(}y!1b96ua5VHTfPB|euHXJQ#n5(qVm5ib zrf9&9fh+#m+x^EkL~lAJ%3U&3PkPr8|Elb{HdEo-n#hR+wUcE3e$DC{8gPKf{x@yP zy+B^C7oU)G&jsp_;5Jbj@lzc;6((4}=+Y?g!|bJI8BXY1D_Am$d3i;Rj_AscXvC#E zg3cfAN7~vyefCBLfxvY`@TG?bp?*Oq2W1Jq^x@>C7wDY*1vG;KL7fa-T{YlI=V?CG zre@`fr6cVC@=NYH?sxTzQTpCZm2?SFZZwaO-nkQQ_OpnIJVD>Yi5wiL@0&fQ0e+)w z39;j|`?y#9IHgl>&j$v&<;g8kqsI~E20w&|h+eJPFx}te%FJ|+UXZCME0fFLelfHd z$VW=foToGE6sipCFL9*+U?*f$H051vQ*OAYnKFv~1KU&oY!#R`{8pelqRUMC9pDJr zzQ)lR(8R8f7$MJoSE zGYMjRXo4a5B5VM<9tq-6pZ`VDIf^R6lZvA?@d{aZdLF%e;_huT<66`w{(%8vgFNQ< zdAY@`5=k5x?lCtvHyiwUH&f&3MD9WDN>XyCBWc!8+XzzqI-}7i8-8wzxpnhL<)4#9N6=O2v5R_RmIKxiE6uUMT z5|<@1D>yEVD}DiOPjmj7ogby}K~hNIy2g7ATX(3&@#Igq5Q8Qgk{5qva_PZ)S0(h+C|_u9#`ub(1;qUkmn(hw&l zdkIDBC#VruyYawkw^*Om9n6!D?{=BOY2a#y+J@pSl*(brR}Kw#_C4Q3I;EwiNoU?G z*eJwvt>F*c#djkrPw97VbsiSFMR%WY0U%EMUaWJag8iOSo{AOsJpA3^n@AY7c0b}K zs4`-Zl&0#W5NEC8VCNH6zjv+IkHqgH9J25SUOty;q;j8$@R;pRM|lcTr=E(hlAyuD zZjEM|aiWl;@{|;T&KBa*~O617tR0$#-2Oc~8jZK*PCUg>0JJ=p-O3UDCIwqR?j{$$L z0Tv%tj|6bQ`%HVlZXz^OHk1L-;CoXXNM+d59Q@55O-F>fn9QFv>*i8?l_X@kfO^TYSkX7m@uVkgVL+m^6>1~@KyfsD^q+!so; zwq$$Hw{J4RJbR$h-1~Sj{jl-jP8HLy8rRXmtmx*iN`#rAOKdcBO!0uEv zPMIKA9Jy87fUWN+U%pfRn_B;nw%Lp{^lwe_Qh;*+=Up; zkrI+0iG_%0oud!*yYoFUh{tzEQGp+58UVbSUuyKO;zaBWZ}P1@|-~ zk0q~1L{>g4*dVQ`rug$kG2NvRqr~0?R}XUH^q($P5chg&HHXYzAkrATURZeAW__YS zJkkKIARc}$Q84x2hK(4z-?zGUbq1xF?`PIMa-&qnIOLTdp(mZSCL#yUy?qPzO{9d1 z;|Q@O%6*_K36_vphEr4o#c=~_-clO|gpUc6=#}^*Kebrhh&16X$HvAJvGr9V4jxoV zoTj9JC@5Ysm_9&b-Pk|D6G*_G4aRbyj+!ZPK0WLH3uB!#JHd4B+_Hs2y*7Mpm9h~E z&-~Q4#ONbTE|KA=YQMTqHB>eu2;RI+UNGoDnt1SWIi$oteA!C}vV&eLHcai{^}#nt zpc|RF-eSqacsbdg zI!9rjxKWaIbc&Fc_M~lNOetIFO6(oB&_rj#VmO)xT%Z?8)8NyraJ2fErJiA2{kYze z>!n9u##pslbNF~1q*?XW#RSBxAKZ}`dzl*deBli<_sPzi#d7@-9Y%^+$Sp|0iv3YNd zVIaS+iX%n~+#-uXPCC)Z&rZPJ5c9aIuR6~$rXik?`-#Dgj~{0bK_d^tNp$ke=5LRI z`@t8mr_|SNw4C6Be#`g(L_^K~@&R#rsOvFBG{A;``>jk;_M&pPlZfQt5O|XpxK?^8 zAAz&82zUzqtJ-M5v~fl&>yocVpNc828_mIZ4tl-~^$C13l%_0Xzp5ywuK8lIRrwX$ zxe{wDMxI_5CG~3@9P2_eN@J95F5Oqc+EgLu^o%wFE#W)({m_kzK(1_yIk~#gcAU=0 z^S2&hLOIN|Xn|N+B&DV59kl?Jn)++89_f5_<^RCWiw_0?r=0)tYtO@RkR= zo00!ZV_4GCe%Zdik3bo9AyN3ex;&n-s-Ee~l?HYT_ zU&r#+^C{*dzEM*4u|-zimt`~S9qLLXpB6~Iz`RWoTSm<|!8h{7!6on>6nk3AK&heM zSaa5DF0Q8WS)|*S>-n}lA+N%UVuQ#_Tx$PH5rB97ksRk6ZGk(}0yI<*K98%}M(ssi z>^nvs(sxSoZ@3hHWTjSZTn%^=`h6hWsFIH|v8@iH7cCbk!0=e(ZF~E1S9zFgEi!UFVaBk{CO22(~qDSJ}H>o4zoK1O=#`tY!gryTX`xL{A(UOawppwX`8~nYs_VSrWUM12U{#& zgdA6)l_bV+l9gXJf*9BcdN^9{uY|kvQ~Ei63BOZ_dv;y#6Tvw?y%y)Wh`753qHLLW zDFusC4jS$a3W_|>K~#zpn2CVmX;4(5N^9Vj0v z7ij^uZ$5PA(r!h!nOXd~~?`e`cFuRVYQ#EGax Q(*I=E+5h!#!T%WfFXGr(r~m)} From 422471953d7f58ebc18ec5f7d26f6e9c6d3fc670 Mon Sep 17 00:00:00 2001 From: itsumura-h Date: Wed, 1 Apr 2026 19:31:41 +0000 Subject: [PATCH 2/5] . --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 5a9342b6..9c485814 100644 --- a/README.md +++ b/README.md @@ -238,7 +238,8 @@ ducere build ## Benchmark TechEmpower Benchmark results: -[FrameworkBenchmarks](https://itsumura-h.github.io/FrameworkBenchmarks/) + +FrameworkBenchmarks ## Roadmap From bda57b39cea5761fe5f4743c52562dae247d119b Mon Sep 17 00:00:00 2001 From: itsumura-h Date: Wed, 1 Apr 2026 23:35:12 +0000 Subject: [PATCH 3/5] Improve basolato benchmark: add prepared statements, bulk updates, and build/dependency tweaks - Add prepared_benchmark_controller implementing prepared statements and a bulk-update path for the TFB "updates" scenario to reduce DB fan-out and verify failures. - Register prepared_* routes in examples/benchmark/FrameworkBenchmarks/basolato/main.nim. - Switch nimble dependency to use allographer#fix to pick up DB-related fixes. - Simplify Dockerfile build step (adjust ducere build flags) and add a Makefile `clean` target. - Update branch rule (.cursor/rules/branch/fix.mdc) with investigation findings and prioritized remediation: prepared statements, bulk updates, conservative maxConnections, and allographer reliability improvements. --- .cursor/rules/branch/fix.mdc | 116 +++++++++------ basolato.nimble | 4 +- .../prepared_benchmark_controller.nim | 140 ++++++++++++++++++ .../basolato/basolato.dockerfile | 2 +- .../FrameworkBenchmarks/basolato/main.nim | 9 ++ makefile | 6 + 6 files changed, 232 insertions(+), 45 deletions(-) create mode 100644 examples/benchmark/FrameworkBenchmarks/basolato/app/http/controllers/prepared_benchmark_controller.nim diff --git a/.cursor/rules/branch/fix.mdc b/.cursor/rules/branch/fix.mdc index f927af0f..a5e2b674 100644 --- a/.cursor/rules/branch/fix.mdc +++ b/.cursor/rules/branch/fix.mdc @@ -5,52 +5,84 @@ alwaysApply: false fixブランチルール === -このブランチで実装することは以下の通りです。 -- `ducere build` が生成する Nim ビルドコマンドの最適化方針を見直す。 -- 候補となる Nim ビルドオプションを実際にコンパイルし、サンプルコードを使ってビルド時間・実行速度・生成物サイズを計測する。 -- 計測結果を根拠に、`/application/src/basolato/cli/functions/buildImpl.nim` の本番ビルドオプションを更新する。 -- 調査で得た知見が既存ドキュメントとずれる場合は、関連ドキュメントの補足や更新要否も整理する。 +このブランチで整理・実装することは以下の通りです。 +- FrameworkBenchmarks の PostgreSQL シナリオで、DB 接続時に `basolato` の性能が大きく低下する要因を切り分ける。 +- `updates` シナリオの verify fail / 実行失敗要因を、`basolato` 本体・`allographer`・ベンチマーク実装の3層に分けて整理する。 +- 改善案を「即効性が高いもの」と「中長期で効くもの」に分けて記録し、実装順序を判断できる状態にする。 ## 進捗 -- [x] 現在の `fix` ブランチ名とブランチルールファイルの対応を確認した。 -- [x] 現行の `/application/src/basolato/cli/functions/buildImpl.nim` における本番ビルドオプションを確認した。 -- [x] 計測対象とする Nim ビルドオプションの比較軸を確定する。 -- [x] ベンチマークに使うサンプルコードと計測手順を用意する(`examples/example`、`scripts/bench_ducere_build_opts.sh`)。 -- [x] 各ビルドオプションで複数回計測し、実行速度・ビルド時間・生成物サイズを比較する。 -- [x] 採用方針を決め、`/application/src/basolato/cli/functions/buildImpl.nim` に反映する。 -- [x] `ducere` ドキュメント(ja/en)に本番フラグの補足を追記した。 +- [x] `basolato` ベンチマーク実装(`examples/benchmark/FrameworkBenchmarks/basolato`)の DB / query / update / fortune 経路を確認した。 +- [x] `allographer` の PostgreSQL 実装(接続プール、`findPlain`、`update`、prepared statement、non-blocking wait)を確認した。 +- [x] TechEmpower FrameworkBenchmarks の `update` verify 条件を確認し、`rows updated` / `executed queries` / 実更新確認が失敗要因になりうることを整理した。 +- [x] 改善案を `basolato` 本体改善、`allographer` 改善、ベンチマーク測定コード改善の3分類で整理した。 +- [ ] `basolato` 側の `updates` を bulk update 化し、verify fail が解消するか確認する。 +- [ ] `allographer` 側の silent failure と prepared statement 再利用性を改善する。 +- [ ] ベンチマークコードを steady-state を測れる形へ寄せ、変更前後の比較を取る。 ## 参考資料 -- `/application/src/basolato/cli/functions/buildImpl.nim` -- `/application/src/basolato/cli/functions/serveImpl.nim` -- `/application/documents/ja/ducere.md` -- `/application/documents/en/ducere.md` -- `/application/runTest.sh` +- `/application/examples/benchmark/FrameworkBenchmarks/basolato/app/http/controllers/benchmark_controller.nim` - `/application/examples/benchmark/FrameworkBenchmarks/basolato/config/database.nim` -- `/application/examples/benchmark/web-frameworks/basolato/config.yaml` -- `/application/scripts/bench_ducere_build_opts.sh` +- `/allographer/src/allographer/query_builder/models/postgres/postgres_exec.nim` +- `/allographer/src/allographer/query_builder/models/postgres/postgres_open.nim` +- `/allographer/src/allographer/query_builder/models/postgres/postgres_query.nim` +- `/allographer/src/allographer/query_builder/libs/postgres/postgres_impl.nim` +- `/allographer/documents/rdb/postgres_efficiency_report.md` +- `/allographer/.cursor/rules/branch/333-prepared-statement.mdc` +- `https://itsumura-h.github.io/FrameworkBenchmarks/` +- `https://raw.githubusercontent.com/TechEmpower/FrameworkBenchmarks/master/toolset/test_types/update/update.py` +- `https://raw.githubusercontent.com/TechEmpower/FrameworkBenchmarks/master/toolset/test_types/verifications.py` ## 調査結果・設計まとめ -- 現状の本番ビルドでは `--threads:off`、`-d:ssl`、`-d:danger`、`-d:release`、`--parallelBuild:0`、`--passC:\"-flto\"`、`--passL:\"-flto\"`、`--panics:on` を付与している(2026-03 更新: `--stackTrace` / `--lineTrace` は計測の結果、本番から外す)。 -- `optimize=speed` は `--mm:markAndSweep -d:useRealtimeGC`、`optimize=memory` は `--mm:orc -d:useMalloc` を選ぶ実装のまま(CLI 互換維持)。 -- **コンパイル+バイナリ(`examples/example`、`nim c -f` を3回の wall 時間平均、Nim 2.2.8 / Linux amd64)** - -| variant | avg compile (s) | bytes | -|---------|-----------------|-------| -| mem_danger_lto | 49.19 | 2380200 | -| speed_danger_lto | 48.43 | 2080824 | -| mem_danger_no_lto | 23.48 | 4848968 | -| speed_danger_no_lto | 17.03 | 2492344 | -| mem_nodanger_lto | 54.62 | 2654936 | -| speed_nodanger_lto | 51.74 | 2245248 | - -- **`-flto`**: リンクは遅延するが、特に ORC ではバイナリが極端に肥大化しやすいため本番では継続採用。 -- **`-d:danger`**: 同一 GC 設定内でコンパイル時間・サイズが有利な傾向。本番では継続採用。 -- **`--threads:on`**: 標準サーバ(`server.nim`)は `Async` の GC-safety エラーでビルド不能。`--threads:off` を維持。 -- **実行速度(`wrk -t2 -c20`、`/sample/fib/12`、markAndSweep 本番相当ビルド)**: `--stackTrace`/`--lineTrace` ありで約 1500 req/s、なしで約 2280 req/s(同一マシン・短時間計測)。本番からトレース用スイッチを外す判断とした。 -- **memory vs speed GC**: 同一エンドポイントでは markAndSweep+useRealtimeGC が orc+useMalloc より桁違いに高スループット(計測時は数百 vs 千台 req/s オーダー)。CPU 負荷が高い処理では `optimize=speed` を推奨。メモリ制約環境では `memory` の意味は維持。 -- 採用判断は「ビルドが通ること」を前提に、次の優先順位で行う。 -- 実行速度 -- 安定性と互換性 -- 生成バイナリサイズ -- 実装更新時は、CLI 引数 `optimize=speed|memory` の既存インターフェースを壊さない方針を第一候補とする。互換性を壊す場合は、理由をブランチルールに追記してから着手する。 + +### 1. basolato自体の改善 + +- `updates` だけが 1 リクエスト内で `countNum` 本の `Future` を生成して `all(futures).await` している。`queries` は直列なのに、`updates` だけ内部 fan-out しているため、HTTP の同時接続数に加えて DB アクセスの同時実行数まで増幅している。 +- 現状の `updates` は 1 件ごとに `SELECT + UPDATE` を個別実行している。TechEmpower の verify では「実際に更新された件数」と「クエリ数・更新行数」が見られるため、素直に 500 件分の個別更新を投げると接続待ちと DB 負荷が重くなりやすい。 +- `db` / `queries` は毎回 `rdb.table("World").findPlain(...)` を通っており、同一 SQL を高頻度で繰り返すのに prepared statement を使っていない。 +- `maxConnections` の決め方が強すぎる。`(2000 div countProcessors()) - 2` は CPU 数が少ない環境で数百接続になりうるが、単一プロセスの async サーバでその数を使うと PostgreSQL 側の context switch と待機列が増えやすい。 + +改善方針: +- `updates` は「個別 SELECT を維持しつつ、UPDATE は 1 文の bulk update」に変える。候補は `UPDATE ... FROM (VALUES ...)` か `CASE WHEN id = ... THEN ... END`。 +- `db` / `queries` / `fortune` はモジュールスコープで prepared statement を初期化し、リクエストごとに SQL 文字列組み立てと prepare をしない。 +- `updates` のレスポンス生成用データは先に集め、DB 更新は `id` でソートした配列から bulk update を組み立てる。verify 上は JSON 順序は必須ではないが、更新 SQL は安定した順序にした方が観測しやすい。 +- `maxConnections` はまず `32` または `64` に固定して計測し、そこから上げ下げする。接続数を増やすより、1 接続あたりの仕事量を増やす方が今回の構成には合う可能性が高い。 + +### 2. allographer自体の改善 + +- `getFreeConn` がタイムアウトすると `errorConnectionNum` を返すが、その後の `getRowPlain` / `exec` / `getAllRows` は例外ではなくそのまま `return` している。結果として、更新できていなくてもアプリ側では成功レスポンスを返せてしまう。 +- prepared statement は接続ごとに lazy prepare されるが、プール単位の cache がない。高頻度 SQL が複数接続に散ると、prepare の局所性が弱い。 +- `close()` は使った接続全てに `DEALLOCATE` を送る実装なので、短寿命の prepared statement を多用すると warm 状態を毎回捨てる。 +- DML 実行時の列型取得は現在は table 単位 cache になっているが、bulk update 用の raw SQL / prepared SQL を多用する場合は、そもそも query builder を通さない高速経路の価値が高い。 + +改善方針: +- `errorConnectionNum` に到達したときは no-op ではなく `DbError` を投げる。silent failure は benchmark だけでなく通常アプリでも危険。 +- `Connections` に SQL 単位の prepared cache を持たせ、同一 SQL の physical prepare を接続ごとに 1 回へ寄せる。 +- `close()` は論理 close に寄せ、物理 `DEALLOCATE` は明示 API に分離する。steady-state の benchmark では prepared state を維持できるようにする。 +- 接続固定 API、あるいは transaction / prepared context を足し、同一 logical operation の複数クエリを同じ接続に寄せられるようにする。 +- bulk update 用に `raw(...).exec()` だけでなく、prepared raw SQL を再利用できる経路を整える。今回のベンチマーク用途では query builder の汎用性よりも固定 SQL の再利用性が効く。 + +### 3. benchmark_controller.nim のベンチマーク測定コード自体の改善 + +- 現状のコントローラ実装は「フレームワークの素の書き方」に近いが、TechEmpower のような固定シナリオでは、一般用途向けの書き方をそのまま当てると不利になる。 +- `updates` の内部並列は steady-state の測定というより、アプリ側で追加のキューイングとプール競合を作る測定になっている。 +- `db` / `queries` / `fortune` / `updates` の全てで、レスポンス形成に不要なオブジェクト生成や JSON 変換の回数をまだ削れる。 + +改善方針: +- `benchmark_controller.nim` は「ベンチマーク専用実装」と割り切り、固定 SQL + prepared statement + 最小変換で書く。 +- `db` は prepared `SELECT id, randomnumber FROM World WHERE id = ?` を 1 回作って再利用する。 +- `queries` は `countNum` 回のランダム ID を集め、prepared `SELECT` を直列で回す。リクエスト内で DB fan-out はしない。 +- `fortune` も prepared `SELECT id, message FROM Fortune ORDER BY message ASC` を使う。 +- `updates` は次の順で行う。 +- ランダム `(id, randomNumber)` を `countNum` 件作る。 +- verify 用の query count を満たすために、各 id について個別 `SELECT` を行う。 +- 取得後の更新値配列から 1 文の bulk update SQL を組み立てて実行する。 +- JSON レスポンスは事前に確保した配列へ埋める。 +- ベンチマーク用コードは `basolato` の一般的な DX を示す場所ではなく、TFB の測定コードとして最短経路を優先する。汎用 API の使い勝手改善と benchmark 用特殊化は分けて評価する。 + +### 実装優先順位 + +1. `benchmark_controller.nim` の `updates` を bulk update 化して verify fail を解消する。 +2. `db` / `queries` / `fortune` を prepared statement 化し、HTTP あたりの SQL 構築コストを下げる。 +3. `config/database.nim` の `maxConnections` を保守的な値へ調整し、再計測する。 +4. `allographer` の silent failure を例外化する。 +5. `allographer` の prepared cache / logical close / 接続固定 API を設計どおり進める。 diff --git a/basolato.nimble b/basolato.nimble index 61696ab5..be807049 100644 --- a/basolato.nimble +++ b/basolato.nimble @@ -14,8 +14,8 @@ skipDirs = @["basolato/cli"] # Dependencies requires "nim >= 2.0.0" -requires "allographer >= 0.32.0" -# requires "allographer#head" +# requires "allographer >= 0.32.0" +requires "allographer#fix" requires "interface_implements >= 0.2.2" requires "httpbeast >= 0.4.1" requires "httpx >= 0.3.0" diff --git a/examples/benchmark/FrameworkBenchmarks/basolato/app/http/controllers/prepared_benchmark_controller.nim b/examples/benchmark/FrameworkBenchmarks/basolato/app/http/controllers/prepared_benchmark_controller.nim new file mode 100644 index 00000000..9c203489 --- /dev/null +++ b/examples/benchmark/FrameworkBenchmarks/basolato/app/http/controllers/prepared_benchmark_controller.nim @@ -0,0 +1,140 @@ +import std/asyncdispatch +import std/algorithm +import std/json +import std/random +import std/strutils +import std/tables +# framework +import basolato/controller +# databse +import allographer/query_builder +import ../../../config/database +# model +import ../../models/fortune +# view +import ../views/pages/fortune_scf_view + + +const range1_10000 = 1..10000 +const worldByIdSql = """SELECT id, randomnumber FROM "World" WHERE id = ?""" +const orderedFortuneSql = """SELECT id, message FROM "Fortune" ORDER BY message ASC""" +const worldUpdateSql = """UPDATE "World" SET randomnumber = ? WHERE id = ?""" +let emptyArgs: seq[string] = @[] + +let worldByIdStmt = rdb.prepare(worldByIdSql) +let orderedFortuneStmt = rdb.prepare(orderedFortuneSql) +let worldUpdateStmt = rdb.prepare(worldUpdateSql) + +randomize() + + +proc readCount(context: Context, key: string, defaultVal: int = 1): int = + var countNum = + try: + context.params.getInt(key) + except: + defaultVal + if countNum < 1: + countNum = 1 + if countNum > 500: + countNum = 500 + return countNum + + +proc fetchWorldRow(id: int): Future[seq[string]] {.async.} = + return await worldByIdStmt.firstPlain(@[$id]) + + +proc fetchFortuneRows(): Future[seq[seq[string]]] {.async.} = + return await orderedFortuneStmt.getPlain(emptyArgs) + + +proc plaintext*(context:Context):Future[Response] {.async.} = + return render("Hello, World!") + + +proc json*(context:Context):Future[Response] {.async.} = + return render(%*{"message":"Hello, World!"}) + + +proc db*(context:Context):Future[Response] {.async.} = + let i = rand(range1_10000) + let res = fetchWorldRow(i).await + return render(%*{"id": res[0].parseInt, "randomNumber": res[1].parseInt}) + + +proc query*(context:Context):Future[Response] {.async.} = + let countNum = readCount(context, "queries") + + var response = newSeq[JsonNode](countNum) + var futures = newSeq[Future[void]](countNum) + for i in 0.. Date: Thu, 2 Apr 2026 00:04:30 +0000 Subject: [PATCH 4/5] fix query --- .cursor/rules/branch/fix.mdc | 1 + .../app/http/controllers/prepared_benchmark_controller.nim | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.cursor/rules/branch/fix.mdc b/.cursor/rules/branch/fix.mdc index a5e2b674..bb1d92fb 100644 --- a/.cursor/rules/branch/fix.mdc +++ b/.cursor/rules/branch/fix.mdc @@ -15,6 +15,7 @@ fixブランチルール - [x] `allographer` の PostgreSQL 実装(接続プール、`findPlain`、`update`、prepared statement、non-blocking wait)を確認した。 - [x] TechEmpower FrameworkBenchmarks の `update` verify 条件を確認し、`rows updated` / `executed queries` / 実更新確認が失敗要因になりうることを整理した。 - [x] 改善案を `basolato` 本体改善、`allographer` 改善、ベンチマーク測定コード改善の3分類で整理した。 +- [x] `prepared_benchmark_controller.nim` の `query` で、非同期クロージャがループ変数を参照して範囲外アクセスしうる問題(SIGSEGV)を修正した。 - [ ] `basolato` 側の `updates` を bulk update 化し、verify fail が解消するか確認する。 - [ ] `allographer` 側の silent failure と prepared statement 再利用性を改善する。 - [ ] ベンチマークコードを steady-state を測れる形へ寄せ、変更前後の比較を取る。 diff --git a/examples/benchmark/FrameworkBenchmarks/basolato/app/http/controllers/prepared_benchmark_controller.nim b/examples/benchmark/FrameworkBenchmarks/basolato/app/http/controllers/prepared_benchmark_controller.nim index 9c203489..51966c88 100644 --- a/examples/benchmark/FrameworkBenchmarks/basolato/app/http/controllers/prepared_benchmark_controller.nim +++ b/examples/benchmark/FrameworkBenchmarks/basolato/app/http/controllers/prepared_benchmark_controller.nim @@ -71,10 +71,10 @@ proc query*(context:Context):Future[Response] {.async.} = for i in 0.. Date: Thu, 2 Apr 2026 04:09:07 +0000 Subject: [PATCH 5/5] . --- basolato.nimble | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/basolato.nimble b/basolato.nimble index be807049..a1c30362 100644 --- a/basolato.nimble +++ b/basolato.nimble @@ -15,7 +15,7 @@ skipDirs = @["basolato/cli"] requires "nim >= 2.0.0" # requires "allographer >= 0.32.0" -requires "allographer#fix" +requires "allographer#main" requires "interface_implements >= 0.2.2" requires "httpbeast >= 0.4.1" requires "httpx >= 0.3.0"