c#3=w@-zX-J z6s?|CF>P@)^G;M5z1Tv%o2si;QD>vs#c}ep7G<@ZIh&GDEn(i1uz=qy&!3v8%DQ( j;_sS#g(!a%IAe{ECnnitpT}IHZ#%qkfe2o3uP3M zRs$Ksu1-j?y5gY+UZ4UZRk%6Qfm4h;>s?eZT6eHvKb-umGA^hy26QQYT}nWg;n!vK zxrcOl`xXW@x_w S~UL$sMez441E$o>VE@i~I8T*z`i zP^OZUS(q~xwk$ oJNfPlTMX^$kw1pAmbzkj|lDI5HyCNwbccq6u!A^)@ z_R564sSIDF6bhD;cVig&*`0A^3J>kZc@{no8@X&wgt>9o2wx;_8`~}Cl-&v_M(Ng) zJGLj16B`v#xSoX19Y BZFuknGquN806{`#qNIG(tHLVL|flU&} zcsqd5s2q4`2%kp<^_a+AN!C1%+#MGQZb4rBmTz(_QZv26qdcKG9=?iq;|ZCL;To3H zp3p_)E-p6?9od{BOXBoTFt-jM43&&82dP3P`CwBbEhD VKS#|zYO2_8+8 zWRGMAh=D;!$%2^5x&ugWJ8U?b>ek|rfQH1Q0l`p`M+@?RZ>=ooT69Zwq-!xAEx!)h z^glLMF?(%p+`GaD0w3sFf<4kTkY9j2KoHgZk5w4GSC&e-Gr~2ZC`1Lv7AVMIo~K5- zDG_IR&dswd2pUdB1PxG1Nw^dWN+`!w;MPS#T8eQAit9-2E*%e^fmL|%^n;J4+BLTn z!=U7*T^gwbss#CS#P?lk_saf8tQ1Rv@!L5mKHP1Z`se%2O)BQU+wX1vOuvES{To#Z zW3<=yH)3aZ>%?W9?9mAVu3Jdut;?-=(sBbamb_bcrw#`Fx`?6hOB5{qKdqYclS=vT zj-KP689m8?w7*fMIC_&-4Q%G${KJGV;pQ!Y631_Cru6UJOtWsz335yLH$JqJ2W8J)k_h0Gx9wY!672cG#yWPS~2y!_(c3ctmJEd5_Pu~KlAc?&4gO@Jf zb+=f-r%xRRncwKaLr|nBUKE6vRkdG9@;e2#nK&Bb=&NK`W0L7A1)Y9Q3IZ%Q2l7S1 zb;4ckr;S!cxS}x Q_ zE~?S(=0S4TxdrcMPM3@PX3I<>otwEaB-`ogL`|W5g&4!Xi@B9 2HN>3~I?1W};AXIE_Z56mv=x_73_C_dSb@igU%2mrka^BhMY;-xvwz;#tY*TB8 z%Nf3YLebf=6Z{~54g&alu|g^8FhdG=+fK1JZ(tzP)W-3@$21qwD{(c4=$#?j5t24_ zw6}+(patEDIOl}!?hx+>cvk}UGV;ZQ5s^tACUNspz1xtF+zJfJUDQQg#y(k4qYr3O z{hHLiiXlz*J}LMQdiHzz%J+GOHCdO`apIN0ms);$jc?VO^Xj!hy?IPhMJtU#Q$oO$ z<2U6Dnez56207WjiZRK&=wu;0%Wul+PaBZ_qG>SeWZPS-KeP>1uJ^?$8hRLzK_#b< z-*HXeOQz(2DbsJt3>r)$3F(1^e1AgzI1)@L4BB&VM9IvtJ<>6)AY?1@n~DaqKnP L@R$_>5^n|-+sU*k4kJAdBb3MSaEO`#0X;Ams=h&APC?UCC4 zk{4$@H)F_J((9#zX3Np2BT k4dDKDM4%E(W)a={Zo6ZhOLETaZI!^s5Kl`A5uRO zGq#MT;_cU|SY1|6*_cFU%o?$!9=+qp9Rb@+zisAV?&&?g^_ eu@U8+;qL_?p|!o7=}Ej3pThU2 JkYtI%Ehr)@!zG46W+92;OEh-dxD1oJgB1duF%TJe`p6V-HbT-bnrs2GK!w9S_ zVLFa#9@TseLu1VP`bOM;ui4)Jk%7FH{`Xhfw^qY>YvGq8UR(O#nf(j@`0QVpH2aYW z{Ysequg3Jy!mr2dllSwNBYNx2 YeD= znpEl?ySBD~dZ!3u- E&oSMr`kf_MTA5${ irb$ zN;CETR3oJMK*2zo57d%%UMuy1rf_u*^}+nuRRz?CvD&(s)Q73lmRXtKm>H<^HwiT2 zRspvuYjc_3WEa$$B_Ek+z&|o8Ytz_|k|l_z(uk)qh-WfT{YN=Mnp^=dP}a_3KAK4* zoU2@}Vt*@RR%Uu7zg5!cQGrMD+vsU4WQDUtYT8gRcv zxiW_JM@bNmrV)=}5Z7U4euI$4DBx!0$~4BGN+ZlvuF7ToQ>LuSV9(ic0KMljSO_|o zivx15VA|?TW+;_`@fgaW5ziFx9A#Z8GgMMgmns=fp#dLGRn`@~!_&Z`U8s-)-V#IDguFL+~U2)dw|wpK0=NNI=&uox1M z(HJ6UFhr$XXOssF1?!};phN<(L8)?`P8p1*Av_o(glK6D(Md7HD8)1utUhR^*Ue*s zN!oRV(qMsr7b@4ymIr4@Fnksi0iM|mcxw4$CuQXuX(=+Fq@$uFhW`~{{3QU-(fm20 zuS^9&`t-`u`NbG6NX~{4Ga%T802QKq8v-6cwrmowaSTKCaP))x`b4Egh9*z^ugC|L zX)(V-hM*Vx$Pi?bZz>h@ zB8bJJ(Tr2%Lqs;@=inD4UE_kTn}zvrW2TLeh|F2MiH=8w!^xA2WsUHG^0N| zIQsG i=LO zk!dDpRvF1pSLtM;Q2}@#^ZpW|Lu_j^D3G%?pwVb-2hGLp7$^gr>u3X}6x`-^H=l|n zr6b72IwuAr6T`9*;MxJvq`+Tq1!cF$lICJmJ^&DR3d)c?%#Xvu&x}Dd8h{JsUczvQ zQ;qHJvP>4s-o&+EJ!z<0O3OeVMDc$(>8$USBz}qbc>q`74?e?!Z6e~E&ySL%bs73` zV~X0kZG%bo|J%yJ7s%Rm>vh7?OvRRfu`%?KCTG?qG)#2xmdz2Cy9>kr2dF}1#1&yP z30Fws?%?CFpxYqwJLK+PlG63*^q {F1OR!bF^~RVw;0HqniDFv5*MSQNr6 z{s($LLokNm8iLOeTt{#N!G9uHgy7#1=n(u7!50X2Ai#O&h4Fuzf`uUJJKn`WLErHb zU^gkkgrU2aG&H5wkKa;wH4a%60=&bBmy&3}ghden;^KG(g1gL<7l)v$bBI^qXvs-` z(_IYx28rsioZPW(fR1__OPqyeZy_1YNs%3}q e zLPxR7k) *P4xz8p%mT%V9ce3S
_O@bH?veAQWZ6y|0~qO9 zVIU8* 3p9O$MZkXWEz2Q6#$K5hWDQFNNH8va&c!ES^kR zrik$<9BSy3@Oc#En~tgE8?Tb2=EXvjlQlGmY@ ZuJ zWHsUN_4F>X{5Dg{{b2(sZ7q-*xXGfHHazo!PL6+zNN>-Q-3B!RQ7^uI75y~1|Mv7m zJPx~JHmq2_sxE)^TC{oIWdDk`cS-H}^X%k>+cSZsf-FlA;LZVR2-d^gq;(+dta6MO zmWr^b7NS>J7P}C`l_}6q6r_fi|0xK|R^M_W2uEE=-R|7ub~LuOcI HSWfc zqNA0YxXlY{y%386h+@ ev8J)(#u z&${!ybD@lDSoBw46tK#iF;FMveC4vkh@Ht=sH&dLyg6G9@STLR>?I23z1i#%R{p+% zU80loO^~RG0TB7*fS~{SJJA2b@HC~H*+y}ar|53bK7p~`AZRgIkPt@FQ!NrQyE9V< zf>qF8j2i)W%Sh3~aq%4MVL2HmZ>CQuBAN))7_^Klr*Px7M4_l(H*Sv%Ceomh;8etZ zzqJC?PEn9#Tq!kPF({C3Qf8 aT<>btdgPLz1jn>NU6O#kRKxT5 5kapd{!Ca;KJh=?q+V>_LY?9ywm zUwOFSzNoU!e&z9_qc1!emKO?d34l)$ZT#%z9qn!~iqEgxyVGeOedvIF3+|9celH3X z2cG!!#YgOgg7H0WDG>v?nzOM@@bkMVFpkS+x@2NhmwIxNujoR46q>?sL2wyBNCow^ zI|VT&j~o!#-pj#mj&t&^F7@QLged+hWN1dlqRZ0O+3IfI2~?qQPkvkT9w(R2J9oB% zDO)oo^@d4oetun5b`*}8Fgz3vI)#cQikATpG|6IBz#YNn d@jieX70=|bz%8UL+{XqDmd`1z(ufi>O|)^ulyLZtLw5vBf_N);(0z6-2)Kq! z^ L zV#r+8<7I>KiG7A=6OJWZh%fGU4aXOsvuyUwtn;ng 4nbnF$mWfaKFBx zxK+gRm8+DZrc)0rw3ZtrZ{%ppS;-r-WPrcPD$8~3n=ul^wKU>7262P3+|IsfqXD9& zfT|0I?J!y^)53A4-4i9_>Aj4bA!GGcQnMx+OtB+TF_~;9-dMuhU~ygD3cI)iK0CE< zbnquvj)FZZ8GXK&^esyCegY}8X&x^ub^QNE55xZ)oQX@+_=ygo<0m?%*aM);I+<~~ z$qp25Gtc0Z&xT}oQ6TFCJB%osKg!l89bkM>w&AFfpgzqsqEH`H?N{|oJ)oH+f*mOL zX;OzYGkl5}d_1x~5<3GN!#Y;5+9t2tj0z+(I0(or=%vCbJ4yMjq{z~0QC$yY(gVYo zXwbW3p)JA}p+PixVwR2krc*Tq$RXR35Q(2~zatM$L?TXvSq|hBnt>m09=GMDjz8o` zP1vhcqV~}yM#HnZFw!mekk4is!ID4)yYn9@suYXb%K#xXM+zG!gpWjs-z~A}K>1-{ z%2mjYfJHenA(Ms&lxk7kvO8r5?iSsfRBDrJ5z9&T{+FffWo|7cJ6cfaj6U9P7s#%C z^qEJ&@L9C%zVzDnBFY>4<>#LUTW?VLptbegkJ{m3m;KY%UcLJLgQL$paOt%NfEZui z*E8z4&e|Yq PF0 3%nzTaAzXq=8)Vw*V7Squ0+!0I}^I3}3fG) zs+X@W1M (-tS_|hItz1u* zJ!JN-4XD?hQ?Ek 2hDjVo+|Z-4IZ3^s6^s)EK@V zlhe@FuUz#oeP@iuiUR6PZcc@bdc!y$@Hb6mY^9BQ%ciWzW!}n?K+sz`G~&4o;swe| zD>M78=?Rr4=4}%Tp0{nvs%Ylztb{5B^NxZAoJXFiDNMxxrGRRMdC!YTa}!Tq+>=gA z!E$CEk$2^@79d#`G^8LkUAyG5z_e*O8Tly2q+#bk#sfTD&5lCo6A%_hGLj5nQp3q2 zWRg?kS=J4fNSGx`$l_5!k#_MNPBEaVSh{B1B#KXlFu{5#dOQrcN}*1@Sm&r4IS=7$ z$q?*SqQfs~Bp!A$-HVizFsUT4$I$`L#FaFO!nnzo*wgNz20*x|mx2Zc=f_9LuR6LRe%UzMkOvNzV;XK}=gqt1ki5oB!CtVa<3B&@*nHM(feF$Ta3xuoN z4t!M#T3uxGfW(3>w%z^ROy1q(kS9~-NBZyu`L*X^_BxfM%p_~OTfG|7k*Z*UVEdo$ z*Mb42Uz;1$nt`b@CLYTO#>EHXa{Y0+fw)3{T;YIppm8W}#$b^@ZcYyqEGWV)JdsTw z*P9lIFZKiTrY{zFzZrhhj6uV&X&&%z0dt<;oY!ABY%UI#PDiqn?>DR98G_$DHE6b9 zB4@j^yu;d@kF{pdqD7k`dk=J`YkVu$`ZCt}8gBD#+i_mqI&L4@XSkrwxHcC$^95|h z!fUXr3q>2jGsS6(Qki#C*+u#CCK%uGPX(B8cl#8eaCf7(!80|tkbu0s*lge=JF;LG zfW;d;FJ$2HqO@Bon8JN|XRI1_8k`e&y92hxcV8B{O|Mdf?_vtPi)le ^$`> 1-2+2j`Q$Og|9I(`)rT;}5KFXu!Vz8N>R5d5OwS*_b%Jwpk z9Nsm?gdZ0tL0i#+Z@jH*plrjWc8%Xx;nlGnUL9+?V ^Vil$2*LNktuStyDmF$ferM(h~&yMTFD}X9; zlM^|wE3cBvPu@3r;71YT9C&zlrT>RlkG%{m(0JNA?3rM$ojJ=6QuaK1Cfc5W2QJRw z0YeTn;Rb&Vye``Sftw(7TPG)E0I#REqumKX0?`qKMq)vcaC|!E76tK>BJADcwTDcC zDKW^P!a_6$-0=BkrwgRcB=2sE7p21?dAK2h kRM9J|gB$Q|yQY*@%9gsmV z(Gke^)xW}nLcS5hP-+G`A9Tc=n2BG2UU+v-g`y@kwlf)m@ogiy=kBD<<0k@eg%cv{ zKS7d^I&7KaXa>_8;lZ3p$m_5~7F0OSJ^W5gC~tOg&D+2vM+WR7Jk8)=#EMavOa6Ly zl6U;P$kvMF{$3$dcrZdLcrqd?gj}I0;APRm8fQvSUVK+?_!evc-HbmQ;C6*rcgGHR zNJzV}O>S4QOAEzERtvZ~0T*xo9OUduAwBmbB!{a<+UQciNddP)6&0Hcwl`Th`{W}= z6Zztv6xDUAKxx?rrX~3#_1*%)-D~w;G$p{@J~6pR6--L$i2~lwVD6oMX#SYQU`z~J zQ;#k?vaCOC$XeJ-2NSHlw;!4I%+$W!PtQ4*P#8?j=`ZTP{kdt!=Ji%wv?YUSNqS!Y z$^qST_5Ex59AHOb$>^;N+R~18AL)MF8?>iA8+9z|MEL-Fe95qV`XzWSSK@taZ-3ci zcYbV7AB%$IH`J8X*6V(3W |?m`|%oIT1{^y0DOQq?Xj-@m5+LZv*w?cyqtZy{%rA?_5DlxRPdBbXFeQr zC +hhMo$#wd%r8JDxjoZL7PajYu`4vgN zwULvKd)#GYU1|A{OR*_Dt#IKW!QX#HYR>-wgN|LOa!wD z@*nqF;KwFVf)Q=`%5@t|=c~nwRFX3V$pGKbst_iW6;{obycK0fm}{&mmAy?zBaDfM zkhinaA<;XfEa30VRxXmW?@A>Q@~(_VT+Se_N?laMzB`2mc+-iA9H(43GGiIC@xEsG z6^J=2Y~7(w)6DQ>L1BR7W)w&`oQNDF&|A4jhH^%- zY>iS1dIIz$#Q_ag0A0`bD7=zgG{49r_c9YCUjaeWfHf3|v_;OzPRJwtDvAZd@61`S zqqmXAyA(!zq%HN(6KM|Y@iHi3AQ$gfNxM~EILt-Q6gX2A9?32|u#N(~SK*-z_>Vox zyA__OyJbNCqrzb?{$nl3gc3o+ph5 d3Kmv22oy}!+6+&Ju}W7+E8uY0IJWE+f Qh@s>~Ql8q)+#!Pam?+@Tn8OkTc4eK=ky6eR8l94Co8}`obZ7(dSg0 za)AUcqp`*w=b;=x^l^u$ADZ4 _w+2^%7&rx29TWw4EcUTet*+on$M6wY?vQ3B=p{X zsHSJpBx}W`XDiN@BI^xrZr8#qWOxAU_BD6bfz8 zQtQ8%3xjx#0wD6?2g_nA=P+;2VXI_vafZ8KhHlcPjC15af|$c_!G&M#z$Y;Z1xF(% z4ll}uR~NvHhsh1B5!h6a8b40TvD@HX2(NWZ$?~066>#jJ*Nb?I(L3qkj#SJA`Q+TV zy5)rOcsLwX8#2 lY!?gf;%C|0})&f6n5!U@72fdAANiP`L`!PiiS)Z2-_|VJ}`Rf< P>C9JKKQAA|~l5CiX5MTPtq;1#v^0%!DB^nOFZ zeS)W8E<_QSKpI|xn27C&u&Z&-MU^!UGcq6||M3oqI*{hY)!=#>B7o $#tY}J(bgAtLf^moxOt#t(BL!7`?zTO i?)@;l;d`(&-P&56OF($JZR)d}Q-^ZQhq78uRDWIvT4)VNa@Go!Zwn zP(CniP 07iZpx*3PZx#eZ4iNSvK|}8;D_Urw&XlA9e8ZwFS1@m+Sj!pa zO@;-W|0N{h3+R*cABdx)im~s&P@#>*Z4ahJECPP;U`s<8hUQ}YI7Q`g>_X~Q_~TG* zPSFY{Y$Fve6;dO)71%*w_JD!rzGc2tOll9>B%KWDIQS#cbmgIwQ9aXX`V=WYlnEwU zI}W9;ti+n&C#KrDkj&jtfs}uu89&A k~5?CVzIe56A19~3$Mh(#vWNZx 4t4ED9z5 zK*&tQ;JQumn-ToGAcwvK(Y*j*SUNgd`4i}0ir}{h{0N2-{0afyB>9&S2&+)A*7*{> z3Iw?QMFX5y5PKUzId)7CSnWpd9t46A>u!o#P4P%oco-0hN2)IJ4+1kI@D0LNh{1?c z2&xbuTPXbcm`D+Dcku{tv|LfrlfUnE&|VNnB_#DW_ij1be5BczHFwZ8lvF+xU*VIQ zK90BbDf=YPDvv3BIrC0ShwPO@@l`%)9Oki4M9n{K9I`JOieG$dp4o%-Lv}3euH_#m zr}eGxTlMVvV_>_!^z7=P^p!)&t9(*#(&y52b~XL^3VIjK#*gt#8O^5jG1n<{#}-R6 z*ll#*)aw+wW2 `wCjTZ+HDdw#OlW=E4ZhP@UWRR`ZjG5-L~7WqyL(fy!`0<-YnKl_my9#(7m>X zHj1T!GvFMfz&XubM`x@+#?I_(!gkE;hahmqw5gB^DgkHEa2=g%OXxf{a{#1-;EZji zXS1e$1N>ab)Inxo#&hld?77z|2>aYar?B-jq}CW&2aVm(fI9$PM)z78`RuXj$+*dc z3C+$Ex5hUZAS^9mS(*sE2iPF27Etq1d@6uY6g~zjXliXnzEDt|{|Rz|PQKB#y|sA@ z|9wm;sAb|2i^3w&_9vuuH*>-R>w?H{*hG_SkDF6)(S@{?Kvdm(3)VF9&G=I?E>Vkv z_hVj1a-T?rANE`Rgr!n1B(8@yH?D%3j%~}tUs(`|qp-!Tm_t~pH?Q8W6m#H5YdTw< f^Z4WB`6qIvc|%kl8F^wJ{J y=VcEO}M9b&*P^jlndD z(l?2ibd=cXk#vljraQ5-bc``dq9#Ra8d78LF^PZAH^HU9WOODy=iEmD+THW_O!0Z{ zdFS4H?()t(+kIYol7HzfF7jMNgqDHdkBV+LzOkh{GM-K8&T^!%jL3+rC#pV*mWFx* zEu-sWXld*|lo1d-an14d@y(Wc3vI6SBs3@1CsJJHu{PW4Z4_5~lA4q2lbciOQ<_uj zQz=d3nbe$CpGI-5C%rkNK7-;qPiAvgeHP$)SN29ujM%BDw{uJtBS!9I#Hg1!oGZiB zPu|XwI(C7X4=F0#PG3m9w9V&kZE5g?6t!-zum2Ucn`IM88E<7RWF2qe9#`~l e9l{ zQ-G2Rtgv0-7^|s3og^-y1LV5WTv`ik2lPmDrEgwL_vQ|OwHuY
6!{H7D9_@zy@Dd z72rkNGwjRz7ibo-W+yvgxeCB}_;=&+{v_Rcmh 1dN$on9%Lv_^cDC>fz&Na1eT*lK4(3a`tv(Tl88qy%yya*}c;;NGL;FOi4H z`%wlfuI7%R)j*&_`&IqdqE@r4np8y}vih=sPJaQ-%cE1RVAi)YOox^<{4kE&Y$xR= zqfIMn!lK=w^K1ReEv%RAO84`A-3~3;6Ju4vW3i7Vy_0RMmUPF&8J=TAonQAH^Sr{Z zJ)(G-BPS;(lXo7~#IOu>V;u3}k-N4M-kc@qJJfzXDKOhvIwbL!W5^3R#)PJIurju5 zieKH$bxl(+9TCtlLV83VEJyE;fH63c$1!A Dc3Z->RG{mkYf@ f^8#{hK?3 NaJj6X>s_rx49%8R`RP?&X-Ea+@$#X;_zAUdR(qHsTzAP zLQqLtd0jpUPfJMA btG;uQ91sg4{ #T;==i~fbE%yM~`yHMfPWgS{rkb(XdR9NDyUqv^C3_Xa=EQx0?!b_F z@}PNgU(s>nMe}r^8qGaBer2@xd5^DpX~zk1Xzt3vxhpT`ue@wZ+PAcOX)v>9pkk=D zVX(F#ShFFx!5j2#3wpN)(|3$8%zSPk_ZNnVt>T7F@k6GpK~q+r;*u$ExTtuquHq9@ z;fM}~9x?Qnr5CZBmnH2PwQM|5XLbjkgPFc$t *k51lXA3hHL@A4Nte+}K-xdSmOOwc+++4Pdyp_9ER|bbjcu2rQL>dxe$ )lCJEU6{ZQQLLaT7$_(IASWM{FO|c{Tl-slR1;L6b@T-?YW5uXTXk zj3hNhbJ ViF8Hg@d*5>dZ#%gMm z{D(=l8kRrD3V@%}Xljc2b1{iEQ~7gK1;l4+YP0$Cd}3`He?Cn>JV&T4B7x~ i!qQA_a9<{|Y~< zW2t(*ih?XXMh?w 9(#*H3#i%UW=@uJTW76VxVaB({<6D43= z&qjk{{}j9Z3H*?Unc?VE5 oy5w@aYtVU+Gg5HeluC0-Y|@YVad}eL3FXSBSz9W!Ss%I!SFya+=Do z06$IrJP$4zdqflNz@ld(NDII_iX|hDS~)*>Ek{hGwMxUQ{3_D@lnH091m8im*@m)f z(;m@<=fg7F_1pEnN%G(fvpJo5UVkbv#)}btg`b0_qccMX%&!I~6UF~qg$_BYH|K!& zktk^Vn$3AwQE3Qs?$G)Q!d(3tF 0N8~>*-_)!QHW`{#UEF-?93Y%t{8lEOaO654@~&+|hsvbOrd4 z8`i=G-PJ(BGHc;)yFTnzh0D9z@z}2GyZ@l}j$!7m{o8qr4zrR8GYFS=4fAG41l=#Q z>|Nh29pHa*9T5*jjO~|I*%E~;$g9-}YLFc7KQB31ckJEYY|I@?TKK=&x$Sy+k`rCu z2@~E*-x2v;U5Yjhh5i3LWtq`Gdf965x#f{|*X7pQ PxqD1<0)X+7q+)JF;js40JzIlm8((;z>NFay(yn}?!EH(!7mT*`s~CTDNAd} zx~1{Sb+@>@b~_hRdVM1J(6n?((ihL}$KO?wv8>WW-SRJ{(choSq*XA1g(R>nQ%B9n z)d6_EN?u-OC%;`5pKAf C!|^?*GtF9$>k;;Rh-~%yFDJFSurc10+rg}^GPAW>1p-4?2!{x>d#>a zsRhST` M0C3wq2#>_!u=0#(6r+PTb*r^!dCTVPxo<3+y?-lzh zewKE;u|My$@wDS&`RZWIn$886jkY0U+MqG5cfrrJLsRAtPMLpx=1|T0!J74#jQ4j| z(C&GI#=O490X}HVyJW1rY)BX~1TqH=nL+!KfyROQ;63%htowrNox#m5pBP$)&DLw# zjKMU*siSR| AK!^(d(TSpY*OMJTao6F`Dn9%sRx2`EC zE_%Y61ONC<%3S{0)!rJ>!4S7cj4;*PBkKQgI^T{@C-6@T*8gQXx4g}8yq=k_t<7Oh zrGqbKVBX7`1P`aR Hq=@a=i@1E(bQ(B&QIcy zp3Wkkv4+QoY#ir&4qrEkKVMMJE-6%8n8L!tg+fhTlIp@NLtTXOBOM2nk0La637U`M zSfGDorW6Z{lmrD*k`&OUPWoQ|Z|c{vkPm~HHmm{3oOMNku_s@vufgLOO}Ide=S;c! zX3v*LU%ayCnJ=C^cID9buI%Z#`q-Y7dn(EuD=Nz?);d;IFR5I*dev8Nb;>PMrcK98 z&YvEBWQ?hV1CH948)YxC5-Ra_%w_ t@_f161l~qe>pP9iu@i z(lF+*D<{~5?;-W~2xP+`LePp)h8I0yd7ZMBe~uKdPdCg!)&4A0J Hl`UoxNu|kXK26L|%Ua0Ny;E3k`*+&yTaZWAH2379D-*X9#`=;BUr#hCJj*W~;~n zhYJQ$Jdn(#KM(EN(OzD8b *&y zFnpwOzeEsw9KrVigoKTr)&}2rL}ph_*d4kjtP^s=?j0_PGNRF!3VMzTfxJ7<6P?q_ zt{~aY>+G)nMDZXC4{y3w k2ROTM^sf;73xEj$4w 6CM0;=&2FDP3X%;CEt^~+zPVvrNC~*u+8k10 z>2C2!7%WKX2>t`X_*P`%V>SYm3rK!Y=VT+KOl0R^GFIgRunY30+(H6wij?phgdqT4 zjHu{l$XoF~aWo~dP5low)v!v;l}m5;f9&buQa=QI6a0gpdfpc@Vw$%}_NG24linda zTQiOFGNHC^)o9gA )#g+fFPSp>?GGAM>;W=! zTY;e%J3>&zNIMa%AltXqnnPTRFJxE%=Y3VBqi(6=p6a@arT4hW`K3v5ZU$OQC!jG1 z#xJnX8vqEq%u2r8mdn0HVz)m#uM+812 m+{TeII z0w7D4m#(6IrgR2r1_bDqN*^E?&qUzskzPSC3&Al23lZRPzav{kx37iVvm CEK)d6yRhmG6A_J6$NVV*tQzwDt8*aA9mByvL+x;+-am+w6H zMc?IGoe z-KF!XQ3~l>T-$t(29Kw8t4k#RzFSo+3wIxM2?-ddO~nMQYfDJAp~2Y%`8lr+s;DlM zfvhxAN%7;!%Fj>^3dp+0ow{(^O|3DLk01A$pd4Wk=oypc>j=b5KXQDZCHuRwW|hL@ zHLSh$b*`Y9j5*rLx4a23(7T!QwTp`QGm+)?YL*`;5*E!>eZUIUT9vdKs+~M}_YISF zGK{+q?(;i%QuqX9Ui~a2iTJVHj>4}Xsc)JLBBZdw2`oqyDSj|RPD6DFeqpnYJouC~ zsYB_D0KW9+7etk)9^(SJE>h^V1|Tt{@vH7i6=^Y5v=XihSvhGkCRLEUp*ffBx^Sw* zuCEIj9gVIAkFU|;Y;-}a+`PHXwMlvhMy0ADq*w&L(=E2(>cdDng#g$y(t7{`(rJJT z?HVbFq(KC~LU0kmB?O-!pxO~lv#bUtng!fB*~I-TVwVw6TlZVQ{!ZG}4%-`!eyhpD zd(8noOvk$iT4SOW!ru{2qp@5zn(qi6iw4Xzcw7!~tlqGvc6V)0T(9wxK7&TJ81-H> zW 4$%#*t<-o3c1cGwu#lm2UnqKyzr2lZ<(q7LfQ zzquS04-u2b@~IIcHI3z#Hy$RnvwZG+C3A}B5GpnEWB60iEWkT%Z4}TD;& nNEuPfUd0+R_gM?Kg9FWJ>)-Nh2FtB~f*gD< z53b5CJokiw_iNyab%PI2B>u?9?pRLLlRrFfAuhOcI8dVJyY?u^tEDFW565(q rKQ~k*5!2a#1Wfb)Ya{kbT>7tXPbIs+JVQ#*B}wks6Rj^-v>XROg_~ zNCgO}Zb}8ru9a2L8f-*OQ5#~k4{oP?8-SKKq;72@yADRidA0B~u54so;~~cnW+`pB zfAh(24n8GZXLOnzvZdD}n5>85E|aDgvNJz1Oul9Y^4BU>Q!oNDQgF+w2WIb1O|K~A zPZtUmGgVF&EmP!gffLmp>?XKwCsAO+R=!+m &Tr%3SC zKnp7>Is_8+R1#TtC`P;f5L784ONbUNmNnA6^p6h3kVjrIV#eFh0j9_=G=U!lZ?0H2 zd EyG|CQ*pWAG~ zN0kQh)OwkJoXj6m)_j;77^@da%8yfXBYbHvH2wLxa4mii;b+CjBT-@H2ilTbNm34& zbjq;p^XbW8gOxmQ(2;k49A6+Omj7!^$r kbRakYen8s!;d6$mRs8jl<9{^3H4MD``-hj1`D6S@v`Apfpd z7r|tAq>=CTCDw*FsuX2>70^-5=0KJ)(bg%9-Dt6zlFRXlJrzUNyg_T;khN&gT6EDm z<6?YqXZ6>h4NGn+nYeiJcHboJbtY0{=`0`NBFNRg{D9H4Z$|fwo{a7}z15Ih95z{p z6A}+*?$10pdH>|zwHFf#ew8r&_|(0sPt8eK37-NKcb5$(*bZjz&+aY0n2@t~!LZ4) zueQ6kcR}y;KDICQSmsNa$75g0>q`!%mR>T={AR=gL*7hcG{zxy(x5sim^%OTw3F@c z%{-YK2qrHLF25&u|He<$n}(xIo%*lyV7k}fl$PASnaRW^4w hbGS%oIEFJ zoC{h$!t$vBwR{9 >q7fFS0({R>0`PRHP|2&_SEg0w3h(Ez z0G+Unqd%g3LdV_9k;0eVEKl}sN+M4lqMiWhJ)w^4_?v?d_W%kK&?RZ%o1X1(z` kgF<^(FoJm7;*O@JYkd4CkJeO8lw- z2PNDezhWk3kLk2<-=?4+04d0^SCX@oeifW(m0wM7o>;%?$e3pWhxt1SaAzc|&rDwM zSwWxRwH!UeT5Lv=k6LTGUK=~P38S-NeAY0wkqbL2T_?uQu&z#Oh6b{M!1E`^>OUbZ zM+*dcD?mOzni`<-irp~bB+kUP4 ETDhGXJ}VhRRh3NFSJUT5@h(B==D;`S}-UPKmmR*rC5$eY6n zY6qVM50ly2v-;qD`|s;BU9{yNj~=v59W+ndtGH}V=$YOdv%i!)w3kPJ$31Aws_m;d zp&iTxe()7d-k>S3&w0r-b=Z{H^I&)F-YWPMM gNASJ}g82 YA0by&CTb)^GT=-Z{cEdgIqwxCREm?VBk~Z1RiRpfTsJgO&mN zwx?WGq2o^}6cuLfl%_ltiqkrw!lXKFj;gQ=r?XjrRDH{#9@|Tj9>^i{vbCI_Cx4h5 zzUu|E$fF-l-kh&zS(2Qc3?lAl$+AWhDF{RnZNMmi6y~#}!IjGSG-OI+GKp$YlGTk- z 1K z3((`PFkOQ0hM9j5o1=uv4iU8#G_i13Y<`q@ewH3+L18@utx;IB(CyZ08rjQ+xP6h` zkv-mvhP2M|VSU7&n%y;BOGY>$Vk0|jh~B5{R`z)JDlZw*Cfr7po#aon2eT?qZV9eh z_iMxYZ!Q}xL&oeuV>aGfjCFiUP5amf4fbFlw`zbt*&dv{1SD;pIAm~*2-x&C7#f2G z9dVe9K5j^#F{sZ7X3slmJSm)9Gf+M-Etol~@Q3u9ex=`Z8=dt=_LjE@*0M8WzLoh& zUU@w8Zv5Q&7XDNm3xregEaDa(ajRxQ1b-?cE@^?9e@`vIgR~#_>^}j>As`9-{97H1 zTMS!-iK))l(!=S*pT4#^wiK!Vfq*KTdl7q<6uxdMq&j7c+xTk;2|fwz{of>OS+eEz zWDfkqeXlU{udJ_niRuj-_kFHE^NlE;ol9oCJ%54|uferXM=*mt@peTG z`adBhIAE@pEs_!#g;em#*G9L;H9iaYK8#Wv4oIZByse%sF1UkjkX(>Zr49><8f=sG zmzD>{Rj(R2I@%h1jUmN`2Cqx1#6hXMrl3?F&cojcBIg3H9p;G<(MGTXqpl(0$Wy-@ zSzv)S5NG`n3$9N3rTmB~GoWI4Y-g{6^9@BE5HMtc0z6M_?GCD-oKAx8WCZ>VYGe;^ zElw^8ACnQJAV@_(t k!WSp)+J4j_010ZrYc;;hFbC=XVk1(S^^waG{E zk;Qfqi1i}CEtWuASs4j;QWhH I6&A$`J;N-c>iSxMs}~Y<>I)1I399S`4J$z^7{~*eD^k z&p5(BaWa+`!Sx&DviZRqNWL~nBgFKQ_ue}b$Pj#N?}8f)me-cyK*$w}<1Sj96zO;) z37k;c>jXn3l=cA$ifd|%kaJwP!9X!mVu3N!`@ApN@j3Q-Nt__EBUAN4Bijdy!tz>@ zPN-&k=`yO>6LgenGUfgBbh=NtJN6tZFz^9{dlURO3;EqFz`ctj?eEv#_g6%(0SM_D zeZIDQr^k)QgyvvqgrRC|@HTqf8$#+fPlFFWJ8qV`vCo$XFpQPIGB)_!BK GbOTWdW-%UscvgS;hBO03-m$ZuQ9#?+#(v{`# zvB#DMNa@qBI75cj@co20zqWPL68Sq!`LNUTfM$*g0*c543Av@74WC^CzqwL789tMv X$Qop_i0bUzs0uBcah*X(<>|ix^C-)6 diff --git a/Module/__pycache__/Main.cpython-312.pyc b/Module/__pycache__/Main.cpython-312.pyc index 8def77f4807f4d0c73ab38c95cb3dd87800b8202..24cd69eac3ec15f66b9916510cd494ebbed61053 100644 GIT binary patch delta 20 acmbOwJ4=@PG%qg~0}x0x{ocsk&j$cDDg{{p delta 20 acmbOwJ4=@PG%qg~0}vci`?Zm~pAP^yl?9{# diff --git a/Utils/ThreadManager.py b/Utils/ThreadManager.py index 523fe26..a464052 100644 --- a/Utils/ThreadManager.py +++ b/Utils/ThreadManager.py @@ -1,80 +1,141 @@ import ctypes import threading +import time from typing import Dict, Tuple, List from Utils.LogManager import LogManager -def _async_raise(tid: int, exc_type=KeyboardInterrupt): - """向指定线程抛异常,强制跳出""" - res = ctypes.pythonapi.PyThreadState_SetAsyncExc(ctypes.c_long(tid), ctypes.py_object(exc_type)) - if res == 0: - raise ValueError("线程不存在") - elif res > 1: - ctypes.pythonapi.PyThreadState_SetAsyncExc(ctypes.c_long(tid), 0) +def _async_raise(tid: int, exc_type=KeyboardInterrupt) -> bool: + """向指定线程抛异常(兜底方案)""" + try: + res = ctypes.pythonapi.PyThreadState_SetAsyncExc( + ctypes.c_long(tid), ctypes.py_object(exc_type) + ) + if res == 0: + LogManager.method_info(f"线程 {tid} 不存在", "task") + return False + elif res > 1: + ctypes.pythonapi.PyThreadState_SetAsyncExc(ctypes.c_long(tid), 0) + LogManager.method_info(f"线程 {tid} 命中多个线程,已回滚", "task") + return False + return True + except Exception as e: + LogManager.method_error(f"强杀线程失败: {e}", "task") + return False + class ThreadManager: _tasks: Dict[str, Dict] = {} - _lock = threading.Lock() + _lock = threading.RLock() @classmethod - def add(cls, udid: str, thread: threading.Thread, event: threading.Event) -> Tuple[int, str]: - LogManager.method_info(f"准备创建任务:{udid}", "task") - LogManager.method_info("创建线程成功", "监控消息") + def _cleanup_if_dead(cls, udid: str): + """如果任务线程已结束,清理占位""" + obj = cls._tasks.get(udid) + if obj and not obj["thread"].is_alive(): + cls._tasks.pop(udid, None) + LogManager.method_info(f"检测到 [{udid}] 线程已结束,自动清理。", "task") + + @classmethod + def add(cls, udid: str, thread: threading.Thread, event: threading.Event, force: bool = False) -> Tuple[int, str]: with cls._lock: - # 判断当前设备是否有任务 - if cls._tasks.get(udid, None) is not None: - return 1001, "当前设备已存在任务" - thread.start() - print(thread.ident) + cls._cleanup_if_dead(udid) - cls._tasks[udid] = { - "id": thread.ident, - "thread": thread, - "event": event - } - return 200, "创建成功" + # 已存在任务还在运行 + old = cls._tasks.get(udid) + if old and old["thread"].is_alive(): + if not force: + return 1001, "当前设备已存在任务" + LogManager.method_info(f"[{udid}] 检测到旧任务,尝试强制停止", "task") + cls._force_stop_locked(udid) + + # 启动新任务 + try: + thread.start() + cls._tasks[udid] = { + "id": thread.ident, + "thread": thread, + "event": event, + "start_time": time.time(), + } + LogManager.method_info(f"创建任务成功 [{udid}],线程ID={thread.ident}", "task") + return 200, "创建成功" + except Exception as e: + LogManager.method_error(f"线程启动失败: {e}", "task") + return 1002, f"线程启动失败: {e}" @classmethod - def stop(cls, udid: str) -> Tuple[int, str]: - try: - print(cls._tasks) - obj = cls._tasks.get(udid, None) - obj["event"].set() - r = cls._kill_thread(obj.get("id")) - if r: + def stop(cls, udid: str, stop_timeout: float = 5.0, kill_timeout: float = 2.0) -> Tuple[int, str]: + """安全停止单个任务""" + with cls._lock: + obj = cls._tasks.get(udid) + if not obj: + return 200, "任务不存在" + + thread = obj["thread"] + event = obj["event"] + tid = obj["id"] + + LogManager.method_info(f"请求停止 [{udid}] 线程ID={tid}", "task") + + # 已经结束 + if not thread.is_alive(): cls._tasks.pop(udid, None) - else: - print("好像有问题") + return 200, "已结束" + + # 1. 协作式停止 + try: + event.set() + except Exception as e: + LogManager.method_error(f"[{udid}] 设置停止事件失败: {e}", "task") + + thread.join(timeout=stop_timeout) + if not thread.is_alive(): + cls._tasks.pop(udid, None) + LogManager.method_info(f"[{udid}] 协作式停止成功", "task") + return 200, "已停止" + + # 2. 强杀兜底 + LogManager.method_info(f"[{udid}] 协作式超时,尝试强杀", "task") + if _async_raise(tid): + thread.join(timeout=kill_timeout) + + if not thread.is_alive(): + cls._tasks.pop(udid, None) + LogManager.method_info(f"[{udid}] 强杀成功", "task") + return 200, "已停止" + + # 3. 最终兜底:标记释放占位 + LogManager.method_error(f"[{udid}] 无法停止(线程可能卡死),已释放占位", "task") + cls._tasks.pop(udid, None) + return 206, "停止超时,线程可能仍在后台运行" + + @classmethod + def _force_stop_locked(cls, udid: str): + """内部用,带锁强制停止旧任务""" + obj = cls._tasks.get(udid) + if not obj: + return + try: + event = obj["event"] + event.set() + obj["thread"].join(timeout=2) + if obj["thread"].is_alive(): + _async_raise(obj["id"]) + obj["thread"].join(timeout=1) except Exception as e: - print(e) - return 200, "操作成功" + LogManager.method_error(f"[{udid}] 强制停止失败: {e}", "task") + finally: + cls._tasks.pop(udid, None) @classmethod def batch_stop(cls, ids: List[str]) -> Tuple[int, str]: - try: - for udid in ids: - cls.stop(udid) - except Exception as e: - print(e) - return 200, "停止成功." - - @classmethod - def _kill_thread(cls, tid: int) -> bool: - """向原生线程 ID 抛 KeyboardInterrupt,强制跳出""" - try: - res = ctypes.pythonapi.PyThreadState_SetAsyncExc(ctypes.c_long(tid), - ctypes.py_object(KeyboardInterrupt)) - # LogManager.method_info(f"向原生线程 {tid} 抛 KeyboardInterrupt,强制跳出", "task") - if res == 0: # 线程已不存在 - print("线程不存在") - return False - if res > 1: # 命中多个线程,重置 - print("命中了多个线程") - ctypes.pythonapi.PyThreadState_SetAsyncExc(ctypes.c_long(tid), 0) - LogManager.method_info("杀死线程创建成功", "监控消息") - - print("杀死线程成功") - return True - except Exception as e: - print("杀死线程出现问题 错误的原因:",e) \ No newline at end of file + failed = [] + for udid in ids: + code, msg = cls.stop(udid) + if code != 200: + failed.append(udid) + if failed: + return 207, f"部分任务未成功停止: {failed}" + return 200, "全部停止成功" \ No newline at end of file diff --git a/Utils/__pycache__/LogManager.cpython-312.pyc b/Utils/__pycache__/LogManager.cpython-312.pyc index 4fab7ccb5e6edc76e1ee5f14d65ff69e19d81108..2607057c369146f2ec04baf0459c453df7218785 100644 GIT binary patch delta 23 dcmX?Jbi9b~G%qg~0}v=S{myXG+Q?^V2>@Lc2NM7Q delta 23 dcmX?Jbi9b~G%qg~0}vci`<0=mxslJ(5&&PG2SNY< diff --git a/Utils/__pycache__/ThreadManager.cpython-312.pyc b/Utils/__pycache__/ThreadManager.cpython-312.pyc index 1e67d5d86925a4d0cf34096a413191adba1eb7c1..c2b09b701808562d3919e5a8783da987be6bf0d2 100644 GIT binary patch literal 8165 zcmd5>dvH`$nm@Piz5PgT(l-xCAQ0LlCN!^+;t>{6hzT!&2ouyzgz0Mg-at1Y9q#Q$ z!*(pj0ZkA#of_Rl!LiwKXQGZ8-5JdYj0{*SRa?7zduccAm8!LB=m7hV;ZcQ!|Lpgj z+pn}itf|_nJzagC-}%n#JHPKc-~HEuf;<8tCVjWNqLh%oU?COwWag#>nL#2EiRmD1 zM#{7?v}|fKL2Bw?_i}CAUcQarYi=_$NW*qm_FCJl43TZ^jKs-#5-;bsbCUTG-zJ#I zdLmg45y|?F$rz=rpqp{pu3@3s$?9B_*AvkB?ZK`NS?4x;)qs=H^EUf;ZE<(Hcgc#* z2E3APR^&iX>GULdP)=ruS@_@lF9v6ABLP~CkuRGrS?f!!GEGHD0D2n1hum^Ph`f_* z&!V&D5J54-r07y>>@kH*60>J6AxcFcKh?u0q;i>5GKI)-*u&RZiA(inNH-7t&3l@l zfAjy{sw5^e;*Xl8C3lwH)@l+cOs%GdDAhe|7AG;)l1U|7h&@hTH)XH3l}LF#>~m~4 zZ=}yK&yZ)?R`Lwv%n#0kzKQU__|X>=@4a^AlTWV dj)JoummB7@WsM5%XN9zB+LcPMdUSmy$6b r^A_v<#Gl)D06f2S@a>t#jpD^5 c2sB zkW6re{IpAjrDKJa(Zb5H!WGfN6_ ?Lm2aBI91lbt4~wbgaC|n(TSK z?1Y&J_V9g2fN=VlP!$!bB2Nyt46hxTsa3BUZI20S<0a+s0x`V!$dkZpOqdlFW{nBU zqr&pv@Bg^xgPyZ37wb1(SR50! V2;+}G3%VD zb&giGd}QB ~# z5lu4RZj#tTT)H+NYDKIE#I*SE0CEDLsKqxkrxJ>iSuT_;vRxLDC(fijPqH53)0~Td za}niilZ&N1_)n&`O8HsTCF$7-S+gsJ+5&l+%p?Dt{+v{pMLE6O?kv^|CJC5scHuQs zbuK7*rAeTTAWT6!2AM$;B0flSgAXZkLIz|JT$N1-usFG?U_G@JYW-dK<5kKDAx1J~ z!6DuT8hli3rb K$okFm |Ks-47tqqZA<#tFxXCRhdO80fSWBXuuAo z3~NM}r$csk2D@C|c9#SgcA#?7u`bGOcR(+72SflFW@0by_x1VuJNr6^wqGo)>Se#o zFAS?gD+YST$`(e;7RJhc5*O_KkM=#<-`v+cv@}v06KXSe{i%`C5wo_uRjY2(c0B!s z;F;h_`2)R6ZUTRzR6?Zl@_xA!jD>c;;*k~9#GY)Wj;Bgx>kw#xyUErv!l2aspoCEh z#MPYOn^JC4%D;yX@yeqiJ}H-J3Cb`@$)!>s;?z7F8c*=cmY^) VhbC z3EIP;r7V&d6n-CYCuIP6{|A=jEYNwdYCL 09-A0%HFi2bd7t=CDpZ3V#5nBa&C4hls8VI|WC=MBsoTr{vKQhKqt zwzu(1dvOkgeOWduUh(j4J9M8w9=AkNR52#jM#b9UqT!{(wb}!%S{*`IO!UOX5~C>+ zh=~g(%tFD6xHx@K7!Y1A{CcM2jRmhRh*#FcXIEXSs{O6=r1RJFuiN;V;xIdyH;^~9 zG%7l732FA4^Py2`^og?%Y1^J0+qN^hZKt;NXIh<0bMK0YyW?f^ZqH9m>f2ijNa<`a zkqTB^5@(Kyby2ZSoA>bOzEO`h_mQ*fV&bNFS%o%d$w u)cH{&Zu$ zn^*u{@7!LPVt7Y=2)6K81K+fq{d2{9h|gIXY8&fK=j&}vOZd;ooTf$mXLA_LJ2+_m zY!Q$7B`oHb^G&NQxP|;77Yr3aZciB&I~zf0rgk{Y3TRi{BnY1rT}IMStwYg-?{*-ybslSPDsI~ zS__~#)f(`6<^(WMvgQjQn7aZSz`S`XRgfBu&L$1#8TKL5?}U^RyXTD8{IxT_#}4Mv z9V`HoDr@(qSY_dl;$xr8CxG@14IxWvrAjfJ%~ZR={=eA`aq=qeu^Uq;a8PJys1{A; z^Vgo>6yq0z;!VGOK=Ib~ShLRO?lZ~{S#xg+C|st;`kXb)9Nli@en7!8N&i4e5S4r4 zy}rcZVM8Y-j=cgec|+SZJ59<0Xb+-&WK^X+0a;3A9+Kd@@9O&>kALvI!3T6CUfh)Z z4I0wWwn>g?-GTZxEP4gCb`Vw7P6ufAD`(y_cwGMErOT&2N-4~@7~PUYzaYxvPDkQc z|K&3$5~uqOazo*!=A0bCXbL(ecewh|;qk$bvW)_8P|!61SL&@uYVQ@a-}qo;{GVSj zSb@_dsm}Y~zxs ywS>{065-<#d`=C{4RXLDR_&VqFdpoHo!fDIW{Y#P2 zGK{J*!gl~QbErGSumW(Ws11;@131(*2Z|>f0$A4swCWvd34p#YEHZ2Xr)>ihFP@gG z{7a_C%NE|YVCw{-aUPjIW2k&!XYaarY1xovU~}(U=ogj-oV|^g(~ggyjWmrcAFVjs za(1m&{pf{tF`)$pE1fyGdSG>|qz0@4)bE3Z1BF9@$o7~xFJ4x6dv?|^RcygiOkA8c zXdAG-oIhbD1ttBP`Zh&`-c2!KVZ3C b9S1!YM` z&9+D&(ylGotW|Hhus xLw_I>vXwl}PuV_qc`%kg$y9pKv@7%7-%;1i?5oF-loDD4dhlX;9&y|Vm zMbo*uh8a-!%+~NQB>y7TL;SgD+d%lwXUtmvApiL?GuAxFL(K)kLjD5FZxAe#yc=jF zP}AjW>O2CVg^Jwp!*5UYZm3K*gKsv8x_5fm5c@-34t%{Crpr|CQ;GW>pHg{Qlz3-y zLdr}~sxxmVbVH*lGzEvWL6l)5StgA&_3F{O&k2)Fn{Eb_O8WH+N~N}k3#4DTQ@PqC zD^+v05J#0tUdF7WN`-rlJGvfJ3Z&U8 vraw>OeuuoBhdg(be>S)q>m?M5fl$NCS&IJ-)#y|sbdh`#pz=&jtj*T zraW6+1|o%`{*8Sbk8Xnd9k%vu851g_LS 0?>U2p!_{XcT_x+NQ2{%+2q`8Tcg09tDV(oVb7cRMmsrg z;i2Zdz+&EB*|-oqYF `~B%J{#-ZrcRL%FYXq)ZRA+rXegTIy#=8z!ruK{va*y5vp?JdRaRR94fvcDJ`f zmJH7#hhHIdcCWfiMOma0mVBS*J?##7c2hUNf%3_cmT5Tzoz%x6g4cRcNv|2?=mueJ zHN8#o@`^XCuUaFe#|!&5_BMs9;bTBped+H|Q56gn3`t*z)e{yVy>2B!alB-@HnV=z zJo2nozD6rqqX}!`_PNUaz`5DUtaF-nK@LLcnq-EoahB;;m#fpgS9ZDdJeO;)UkY|$ zUU0eg1>GG+i*XC_Ou&c 4z7cJDhW&B8GVmk j*^KgEz2Gk{{$ImQ!}~`3=kvJ3%lVUS_0cWh2#|cuLy=?hHxWAw{2%Z&0En2c(~9 zW9aPcd|kwIgFupOgxo|GZL;#tq3x0CS7Anw9bPt4GU6F2e{1y(EK=(0Cde7vhMVOq zR8Z9@n=x7p5xC>KyWrpyJYISfbiZ|xen?xC`7mvKyerxycR%fSE7Hc!0DPzmb_JB5 zV#jS5QB0=ivK@;kc=W99SXUW>^|11{P=|n^B9a3vG0az_;4312Me_ff)I>>5g46*_ f-M{=g5t(UW&jco;H8(N2UAvEAoHq!@l==Sxz=WuA6<2WMN^+dvBY- zY%(#`W{FW?v;!tMqOD`B6UEjVOh^;sm&~*u*a2s^PiE>&St4KR26W=YFFohIee8le z(=YAa;okGkJ@4H6?m6do&gE~pxi$iAvF6{0cIOcCFMKc>n i)-a5oMQr}E_17yBBG_85?ImNP7B-%T&s;Hj}yW40ujvb)4Jx? zoL 0wRexIUpdqX_|QDt}eWyMXYwq3!4yS?4sgQBD|ieK=h-qkdipl9H3 zsglASDjE~Jj!dZ(w}V@rUM3WHPj4NlYgG%A_fzv3a+Xy>@EE2HIpfQY(P3JkI`1Jw z%2D84^(N4U+(`=Nna)O--}?XCwLlsBp-3;=%euMH2G~hraA^L_sl*3oZ(h23^ZZNm zr_UuOPbMZNzL`9en7ovTeDd|hKPOIIlJE?_vqPuL%}u j5((E>=CZE#V zBg(3^r&l=??DqEf)zV+|?mZ-lUg2rQtB9VbMP-NF+wI$V)Cba@K(PBDN_&C_Iz+Iw zZJ##~5_d{cP;xVp8Puv4@u<&(YE?!OWf`sOa=Gq2+ECl}j4VoWTi+pX_rXrDzpYV} zJC$HhTfi$T_xcsFtIZ#jf&Yx+56Er$E>fOT)6=W+9xv|1BYFLxXAS5@OUhl)ogi~I zN6c0hwUxzeTcftEAMd-k|D*lawoGq({O?7vrj}?^%T()u=_cQ_O*qjIH`^lKlSgOs zN~TITPUmf!vTTZ5`N-kZ#j}>Yn586YDT!I`k6P~k_<@UcAJttenBKDU+TkxOO-Y8> z@|R#i;=|5phJP%vniq=%W2=>ZhWJS xd zftf70(qT=BWDH@jxuNlSn-!51eg+5PmkZM!hNon_XV?dJoNKT_GS8sXqk%oJtE}^3 zI?M>BQ6~GI! @^W4z hx9SHT`ajgcebAx ldn_4kWiU}A|xSM@k%iCNPciI&M$zUxmlI*1!M_*JH3vKmIs7#N%*xY;}wLy z{1why11y9ac@#Q;8jCY#sfb!Crq*vA-#h-;)VhZz_RUxtXP5cwwv7J@81Y=kK+8)l zU)h}lef@m{$NP_u2xE=YcK4KhTfDgTwwdG=M_Q5=l3OsatAE#-=2<>}@b2NwLz`## zbx9K`UOOBZ3dGA?@zRQ0X4aJ#X&892|H(lm%9r1^!^_DM;;6b^YEXA%w8&&deGT(j z)eahl>or{cgXR?(7jvkVaoe@HvS!2y_)V6qo8fg?=d)$y%vjJfDV});=7&`+?ftNN zwy2`B=}+fjV|T}xFe9za{sq~hE^~*NThsU=FosTwSYf7$DCmM(t0q$6u?*QTo0e^X zXg|gthb*m+N2ntt6-ivP=FyT1l!P!JC*HY|_|3rlX#c|S2MceHxM^uUPT@N9uf9BY zWi;jLX6bHVX>Ki51En%D_%`q9^alc-6oxWA!5-BL`C05y{K0NFCqdCdG$&UXNYg4M zsgx+A-O d8NMR!D2O>+QHN`+;N9Z4iqEh4{n}~APa`}2VRyjPux-dT zoHvv=qKxgGacoT5z=6Ltll-Eoq77d-?g6KFRDJ&~M;xV#gwhvZKk!84iMYM;ha?A_ zJ8}i=?PNV&? ~sW(`w~WIx0^ zI49{?PAxE*YT@NVk0NIZS#$&n9AP;;G)G{R<$^Sv;WU~fFvpo*NC?MZ%y0y{*)TOi zed77i`3rCBrmlhV>3-lzHQ1pM+^lZMEy&Oy>pq}Xp_T1`SMeS4XvQpAY0UJ@Hhk|9 z=+LCBweZW5y9QY_hGobyvgUVrw-{1d4lv}X&VKY?fQNa ka9m6bS_8)| zI>uytkqumTxn=^_%|Vy#&C$mU*X2VGfdCBwl&*=4)^28Q;~^=z`ma>*r$cfuL6s znz|KHl0rR7wws8A@cx*DMhO+7uAwV)6Bp(#L3wd@ZsL!+#t^3P`8Q6?U%0F@GE={_ z4&TLZ$&}CoXm4oKDn8tRZoV?EBdlxTwb#G?@WY#DUx4i=&W(LDdA8YYldv3<5OpPt zM+s{#2@hP&|IrueNQ}NMRbq#6YJ@1}H3_#R{WwIW&A{&~TN#^~0RAw{%a@>o=rq}_ z4b-f&B<8G)IxAz&?NR6U$$eM%f4cw1mg%~uX6qVab-SZ=yJwm`({;}+F;u|;D$; !R5x6D9MU_1e3 pM)6$L2$Li*jB#VW^IOIay=7m- z$CM;c$#PB7#8r>%9jki1B}srhziqr=+&5nG-Xn|nn34u6>CmL}xdv(k_J`w`vZ#%k z&@CES`U&92yLml2>VSs(T5k`WxP*4m&QrnzR2|w)y(aw+9<4H$5GbU2?67LqkFpV| z<>OT?+ja9lEIkern1E%p2KW<2eMxe^B#wWQ>L{sBkPYD7KY8F5F;P!agT5tgyzO|D Nq8g}0q79nb{{W}9VaEUf diff --git a/script/__pycache__/ScriptManager.cpython-312.pyc b/script/__pycache__/ScriptManager.cpython-312.pyc index f355c047eaaf07ce8e8f415ebf26f63e67ea5cfa..cc81b14c3ed40f665b5c293b75f1f4291155509a 100644 GIT binary patch delta 5478 zcmb`LdstIfw!pLV4hbYYQj8Etcp9N9L93vGfbV)0Tdh`68j~YLLZUkd1&gAcw&GY7 zzcsz;RV#k2qmI2w&7C`1ZD;DOQ)^ob!U&$rd}C*-)s7E}oldWediUB Cy!cDGcp2J zOo@fDx|rEf^-+}8M-9-%xW-g3U*-tEXCTGMN40vRhi}BAHxKAB!H2p*FeD;jpzaE$ zJM50gOpjR;U9Y100pnGVWcZ0EW=#yf8SFD+Rnhe^hvo2=CX<+;R%eT;=M9e*Uq>9V zV9;+IGKjTYJNoLiBkx~5w(sihjaQDIy7Joot8cbk-F&1*!#c12>xrxT8gt+m`g!qa z{Q-^6>mJtNu)ueEZwghhvZR0L88f^=QBqTv-xH{o)b7fF*DXN3AyY?FaY`&rhXaOc zyV@NHP*1L;aMvR0awV1MT3%ioe$)kHVSVaTus2l=<02iJQEY1PGdcJoFJ&0aoqF2^ zy{+4tx_8meMepWyW=&|zn$T`7+BoyFb#&v*@71!H!LTsOs_iyJH%;j 5jK-U$t%3_WEu0?-U=HvTw?PS^H+SOl?ma-&$DO9zVNr zYL~&db?U~cP4gQ%3`yN)Yo|G@&7AdaNsF>`#H6+nliIT tr%1^jE8skl~@EWV4*y zg^_kAaYBVXhfIW>_NPfPd}3eh9L?m=F^D_{N#j})T<#JpX+AcMMOd+2TkWb6SoR3g zaWF3>i4?%flp$m;>`k%9jl=<}3L2 E zk(5AoYO}hAH3a`2x{$g-u6cV +1LEMu+N*%|NNboXbjqTIyN@gaH9tvL+CMno6 zG;Q3Uh_>Bc&?_@oMnP7=K?Oc97Nls~t++epVbE8=hO%d3;Sp`SCF`g2ZxucuWEk8k zTCB#+p!49lVn0~{9~H;jxq GJd+ jgzUdkqe$l+}II7X_ELmKu@LTylafMI~ z`gpe`o!jSiR~5V5ReaA6spwuDupNQ=g}q}EBrJG#(0Mc_%KveltlK vI6Z{3 z1^4w=uwxv8hr 8 bJ*)_ zlq3G3Bjb#dh*Jo@u(PbhPGcch;}hwZ5b#Y@U&YSraKe|KvkQxl<2@M9sxQ4{v$6l5 z{!N%b2jS2YV609fzYdM8{vcxPZ&-^%!?TzayENeQ1y&XLJyWP4h;#kkfIpm>o)CES zeaNnTLH@lQR+rdee{G2THuPehJ%)S)FK -zYQv7XGl|4GqB z&tUH-3_%rx&9-jcy0GeKh}Ah@Y_h|HH%x<)*kv$?j{D<3g-^=nsii!8SRefqaSp)) z qDe=I^lBi@1aM9x)WeE%pZ5hvk1D?ji0oI2_@V=KskVQS1YR9>Ffs zGD;9~h6bv@q7v~kc8C2HODb$rBQyvtLWj^J42VcX*sa+NiG5}GMHl-FDR) R^DP8c4iWYIG2N;7#KDPi*X#ndl#li<~Ws@I6 z-@bJ>ab_AW2Se&Qm+3?4)d)W#fZ##Mo&GDV@<>F*YYYrmKK#`;TaI2iweHG+O|%J| zryj6l#rc6krCx`FH^JD`AtTyMQm||*$-RDd8r?g+jC4Wee;rZt3x@>~KVCv^K*Pr^ z`pY;go1rEFww9S;)|m)W1`Ey%Chbsj#u=Z7qKwQZRthxe5?O93_j+i4=)*HBiQbKq zk0C-(_{s1FZY!Qf``vIOcK;l)3Bj$q7E5^9q;DW{5vveR1}So>*Y7D8d;)#}2g6=Z zPz|Nmzce64RSWDp+f%;EMg3lX1)YF%)WJXv)wzZ6jp`Zr;gezHRY*VUZ+Pt4;hP@! z_Qz2nY2B4BaZaGfJK&`IJ!*p2TS-&tVrv#@c#Zq9J%sor;vj<~J-qed;|p8){x@Oi zEd*dHWY@CzPtTJ*aP`vyVuAE?>H2HfJPk1&a_%_g)Ce2TrKnSs%zbZ$-aFSP*Bp-O zm1(U*;m8-yEAXj2zm?ysm6oCK=J|BF(h@p#e!h-u4w<|1NG^JaLlHg_6xD3o(V&l9 zlWXN>Hl!YINT0A&r1P0?#>o`~wqHso`{9F2C!gxVIYd$g+4Xd}LmpmSC2Wy$$x%2h zeQI5T15~_SQUrw+>@F$@e(FTg$Kc?9&rCkXRvav1!&q`R#%!u-RCYy~8Wmm9aqQZt zO9WH5UBRBAk=+dj;)egY=46-0Z?4(Z56_vX>&M7fp^vV|5yK)Tg 2FA#)cN-58^mtJ%v7Vb_iPgdPP+okrHNyn-qdNl_)#(Mr_Q z3%71~hvHK2k_l{)Rjg4``@(A`e9QpB)CcQt=E^l{_|Kc4+x;j2jX(pe d-HZ(ccZWy8rU zdz!8`Z^*X|VMo)E9vAyI{Af$8P=h16llEsao(i79j#|V&g)NWC(bzEtk%w51$VZGt zSP`!vxFQYE_}#SR9IWF8QI>>dbSjp((fHvt5_-O~ghTQ*?4E$YZ15 1x<9P+l3R7NiJv*A(5A IF 3g@u4&@+D@tR%TGyDxs+NPPbo1{S9*^4Sd-8zv(#6H*;w3id0*p|}vc zxQ!OUJAGMX5w!OG>ZQ3jtQqlZ#D|Cz2rCXxM5H6|u#$A_Cjr6bVVP4>O ;M1& delta 4703 zcma)=3v^V)8OL{avzy0mHVF_Q2^;btB%AO`5G3Ih2t=S3ke4rH*<>%-OZJh>-6aGA z1gwH$4e)6Ju^4<*&?Abg)nc`vsJtbhC|4@9f`SzlP@z&y=RXUEdi0#`;ruc)cV_O) zH~;UO@AApAm^Xej+4m+UCK$x;^MCx?TU@Z!KFZ`ARZ%u`x~6b#<^r!fP*dwxXO2;{ z+EB1=rq8W~`l=ztKT{2AZmKrjW&GYir%hjU^29V5T=AF*zea=8Om=f$(==xSO*P*^ zZ 6tA%a@+G*Ll@26KH`zRiG&?chWM62f`w}zE_Jv7JMq;mY>C|LzN_xf^T>~>T zGG`KH+V7=<_8AtBXmxg{;Yn(aZsG2LC+OEL)!v|5t#Gq=rdz9ne!mh3-Kc6I+Le?a z<4oqg=u(oulR4zBbIsS~pGGZNbf)%;UFor8XY6&NqU~pNDEVmD^sGl6>l{xsevm(` zEq~bIwBgI`CsWd>EyY3KrFgoXuyy{x=4i7yS~Cx34S3#oFmvF0w(Cw(eWx_jd$!SZ zTW4qFk {|Ov))?tZ!s#ZmN;# zv^KAV4WPYw#cVYFkk^-$Q&I0(C41+=g9P1X=uS(e7w&5@^vE@iBS`VQaPZy+8I1p P1Ns|L;ddgF0O>Qs%ZRwm#ACO-sq|hh65qpTIH^;4bGY4(v)hx0^_k--Re{4 zDXyw;C=?9naSd)YG)?G-ufww#tcPzz-^WllDZb)tu!OHioz2%-qn;QFhTJ|(8w_|f z-a^Ai-fl4nHER24!^q3V4Lzx~Jkw-IcSd%UA7`c`*&}Gv=uP7EM$*)Z9P<%J@mfYJ zYcpbE4Vfjhp<;{aNLtaAF?}N8G40HP^9g6sfM6GTpmMCG085%mM=JxRI0ikXhAT>F zqS8 B&DTQD-Y|u=yfCi43wv?(9lfmA z%A)@rsg|fUyvpqgz8`b!GkXZeu^2<5F(vo5gwEQvA|t`^sOZ*O$MT#p*5&=ii^V) zs6e%sL3mP~GG_4KqdH1Jj}?JqvWQbU<577_Yf5i{&_w{MQx!{wFo;%3AE`GPH{3!C zYx|oFnY|;*++?9kN7 Ve6lo;1uqN(etI%^ zn^pR7G#F4qU8_azbQnEfm)~!x=;iEoMUxouGVlr@H?UKb#Lc5 ddsbKF{)!s4wVAug~hqHb(Z;zm^ae5iQPGv5uCewDddCU9MP$B6(uv zX!|q0(KN$&LR^RAvT5kT2zxd1)xzvf>@`YRnVa6B6{)G$F+%EWhH!;5L$;%yA+-8S zzQA|j>6-!??#ryK=H_PJ9c?=)xN30c1e17z$*$4(Ypcc;2#xbJbbAYU8xTil;O_vt zfZf0zN?Yyd*@ogFK&tgHO78*h14n53>YU+4DE=Mz7&s0{m4AxTXTWLT4DdPdFW?J- za5}mCjzWGG4POFZ0bc`7;2dxsxBz@Zmse-^aXO RBBn|}FDoDwnfmLB zlyZYCxeeX-qLhe|9Y|v0aCtI{DL`kS3y?~)AM9%FilUV5Xj<}MF6&NDKG@rM-Wb{c z;1@PlOWQW~vC3naig^p@+{Uy0e$@kirsr}Dk#5*qMkH* bBJ@f$Bk%z4tNZBLcp09 zm4H0+3baZc+>g@3Kno%hUr#UWKfu<}k^>`HDs4ZIXFZAL8-Q{2^?`xnJEGUSITm}2 zh*+OQZhZH$(YVD<6Aw)_8JySC6Ng%mmzEvQGm8AuefXAmc5h_cu~If35^ H zV|0Ta8hCslTTeB|cROaGgITugCQYdq$(*7Dct5;p3;p)Q#Pkhf*V-`AO(YjdomPaG z$9!l{UT*p*r3-C4k!><`N{xJcVzG_6Xx7;hHicH5&9+9Pz8Dj(ptjN+I(~MA1-=m8 zBCD&vJX>(9sLFI=8ox~x7bLr@WdiE*i7%vnbwUewU_d5K%1w)G|Eh$gLN;PA%%h3L z8M5SVb&5SV#PTJUIGo0wD@!|PV!7j)yb?rTQ?1g-J=lvv51&&DVGf;@3q#bviWXng zE==~hW?Js0zUK!TFPN$7{J!kDm;i?2wW8#V;XX9@fh%^JbfGfsJGltaOV}wZ_i=M8 zUz@vf%twwaid@JQ=|eUhy^tZi_}dGMEK4!=E^7Sd9;UDUwzyx^?ZjAhXM2158CYB9 zW#J@I`fTZ6PAz-&)E`%V+PbVPtAIPn^{snxIr{u+#FMd!qf69>PznJ*b7<+UgYaN5 za6PaP7y@);WQ$NO1EkMe3^ek)ik|(^fMeltz!>aG8tXEuCA9Iow5ZE2K^?v=ziqBM zn)I>tX#FYH>hXwLE^pAU=m{dH3srkvRiQvf5~qtST$3Mv@pDw4;*y`7EtrFgx9f4i zYVMk=iEk7${v$!tsq~`V>czsEfkv8gu@~D*4HvWGaR@pKh;wMYn8|GPw~G$TM9efv zcyS4Jxzxw931?awsl4=pF{kbJn!|m(f(K{Zy!qDW>t7CU4ZkvL*ObH8Pkz7eO$TqU zX`?QeA1OZS9CX-m)8-znqh3ilIAZdl(#a3IH}z<9+;r4A^sr-kn{%jmQoqY~Xymkq z-3OgR+ae!aPLG+^Uo0jZFW!ENmPh|Z^Oylx^>qRw5Qu;xl2|m124r4|A-n?5W1`M| zGagCH-ulp3R>a0XRL`ECJsI5|0k#6$fR}(Ybngyi1GozHc<~jlxIH2s>*lfZMBLWR zb9_N}D4I;jLzfl}U_>kM_?kNztF+q9S?6;K%{dotV{7&?c3**v*LUMRPoW#MsK?^S zd} 5DI@sHYwj_z8&ei_XXDs;gZv|1`@du< B2hjik