From ccef8838debb696bb4e68b8f9fae65d03679ced4 Mon Sep 17 00:00:00 2001 From: kopardev Date: Wed, 7 Feb 2024 13:28:52 -0500 Subject: [PATCH] updates --- CHANGELOG.md | 4 +- README.md | 8 +- docs/assets/images/spacesavers2.png | Bin 41865 -> 79102 bytes docs/blamematrix.md | 49 ------- mkdocs.yml | 1 - spacesavers2_blamematrix | 144 -------------------- spacesavers2_catalog | 39 ++++-- spacesavers2_e2e | 21 ++- spacesavers2_grubbers | 6 +- spacesavers2_mimeo | 203 ++++++++++++++-------------- spacesavers2_usurp | 6 +- src/FileDetails.py | 126 +++++++++++------ src/Summary.py | 3 +- src/dfUnit.py | 105 ++------------ src/utils.py | 12 -- 15 files changed, 241 insertions(+), 486 deletions(-) delete mode 100644 docs/blamematrix.md delete mode 100755 spacesavers2_blamematrix diff --git a/CHANGELOG.md b/CHANGELOG.md index 359a6c0..c7f264d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,7 +10,7 @@ - adding `requirements.txt` for easy creation of environment in "spacesavers2" docker (#68, @kopardev) - `grubbers` has new `--outfile` argument. -- `blamematrix` has 3 new arguments `--humanreable`, `--includezeros` and `--outfile`. +- `blamematrix` has now been moved into `mimeo`. - `mimeo` files.gz always includes the original file as the first one in the filelist. - `mimeo` now has kronatools compatible output. ktImportText is also run if in PATH to generate HTML report for duplicates only. (#46, @kopardev) - documentation updated. @@ -23,6 +23,8 @@ - `blamematrix` fixed to account for changes due to #71 - `usurp` fixed to account for changes due to #71. Now using the new "original file" column while creating hard-links. - `e2e` overhauled, improved and well commented. +- total size now closely resemble `df` results (fix #75 @kopardev) +- files with future timestamps are handles correctly (fix #76, @kopardev) ## spacesavers2 0.10.2 diff --git a/README.md b/README.md index 90e8518..c31b6a2 100644 --- a/README.md +++ b/README.md @@ -20,19 +20,13 @@ Welcome! `spacesavers2`: > New improved parallel implementation of [`spacesavers`](https://github.com/CCBR/spacesavers). `spacesavers` is soon to be decommissioned! -> Note: `spacesavers2` requires [python version 3.11](https://www.python.org/downloads/release/python-3110/) or later and the [xxhash](https://pypi.org/project/xxhash/) library. These dependencies are already installed on biowulf (as a conda env). The environment for running `spacesavers2` can get set up using: -> -> ```bash -> . "/data/CCBR_Pipeliner/db/PipeDB/Conda/etc/profile.d/conda.sh" && \ -> conda activate py311 -> ``` +> Note: `spacesavers2` requires [python version 3.11](https://www.python.org/downloads/release/python-3110/) or later and the [xxhash](https://pypi.org/project/xxhash/) library. These dependencies are already installed on biowulf (as a conda env). ## `spacesavers2` has the following Basic commands: - spacesavers2_catalog - spacesavers2_mimeo - spacesavers2_grubbers -- spacesavers2_blamematrix - spacesavers2_e2e - spacesavers2_usurp diff --git a/docs/assets/images/spacesavers2.png b/docs/assets/images/spacesavers2.png index a1e9a16ea4ffa5c4ac4c38b0b3bc6c514e1b8a9c..7b1d669cc645dea55ecf21cf0d16cf3697a789ab 100644 GIT binary patch literal 79102 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

eZ9ABJN0;i|7>h!4e1QWP#vbQu<)4 zb&mbW!{O6;uCs%e-=_K4ZD@K)By9zkd|SsnM|0!5Eug(+cJSV>O9|+x0n7s|yJe5m zt>FpnIX?ILGw}U{}QvgL4u%+F{#UFgk+G zmCt=k6D|C*3w|mA+tE$;D~e@9K1kWi>*2d)$LjtXJ)>~s5WF%%xbN9nXAWN6M$gd_ z8Y%~nEAX%Cx@mo#rXqI5&~n|z1;Sz?A)eaw@#>R@_3MgErsM<;Y`VPTrSti0kXxYc z{#Lzy$%+$ane3BBF0&4cYY8bxG7%61%ahtEHKYgLwc*+iB^&EzD zUJ_*&uAiJwW3Es*AE}e&Eh#!1F$TGrB{~e1`JQY3R5qRiYsjRhyv}Xey$q|}5}Y~F zF(h@%czasPo_XYNl)PSHz1^z{Uu_KwCgQ8G#O=Oof-Bo)R$vsz0r@Sp&2P#+5f(70 z-kf=d3??REjx_xU+O6-_PT%ckVdMF*S#Z@`-N?x`>&^rnyHz)E z=XiKm0gBF!*V%!&r@mt5jf-DT2MwBj7yDd}GBhhUt(?gK_CmvRPKG?aK zZUwjguG#pdWY;7go<#?FC(*9l8_ufmmv9-n1j!k(4UUcUhQp4-tIe6OUFQ;H(-jSs2=hD?Ot*UwYUQ4!ovC*n7S^%p;rBt_ zgV`--8Jf!~_;MT{5uoA!S}cQp*NEv^-{VBG4?DwweOvy6H3DzaazSIm{`F%_P;Up% zB}w%t+_6h)V$Pw)?S6yx^y8$MCcr(+egr?woC%*Tlw-TeF82)3nO2q zP`xgnefC43jc}?{^@i_8=688^>@XN=g`0&6^V_qG7n8yTII-B$j&sG&?WCcLch04W zfd?v%UN(f=y`=&1=#b({jd)VJ-L0jFsR0-s9!p%ekHyV@z~&LD?t)B6BS^&&er)s5#jUoa|O|;`1!~|I;%d@ zz&eIvo$XIOVZt$)Fk*?W*51*AUD3C%PiMk+I{WX08C z`SI}TkgQ8s4-Q#&({ovyj=4z4r`jatr=NRa8VoR6q<> zsnR7Ny;vYfmnPB`LYLl4Kt-B_-us5or1xGFq&GvaK|ml#htNXFeNo)H_kTb4KIcB? z+c_Uo-nC}U%$k{Zt(o6QtHPR^)90KjYLJ~NwUkPP>;pOBNR^B#b#~)wc)gIw6@NWJ zkf?iP1a?)2d)y5c6O+J@ge-OPm(*iaM|&PnfF>CP&$`@03!`|cC%xn~l20JyJIvEgk3aYTbvtWw_EZH+b*-lJRVz@cNaVVJ(VO$;8nc&B z*9NIOiv>$*XYPin1(Z+kC{j__)rX%iqov_GllyZiN~5cmjCa%c6+xPrieX5u^ffC6 zjXdG1eTHZ9hki%oNCHJGeO|}laDMpSxZDyQ;-IxlUuseK0~kB~fv0VOR@o3^h^|)J z&x}@_3MgJn_8!<8e513_k0-vJs5YNoDTvuuc~e1-iS6I%kG`G^+r@aB))#ix77^CM zJJ3Mcm7ZUiRU=Wu^$U65g4^F7LZ|{zN?A~voyCozI2Z{ug8Zr*T-_RFu zc85UiN1W`cNrI7Vp``=I-I+z5u{Tk@^fmafijplGj1Obgs~vD1dP>0Ytm^tT(fLr6 z_t<*IlSy+(D;}-^@5~DT;!>>;=$X8B!C`o@$$WEo1{4nE<>g=GDD}Ovo%00Zbj)i? z#ZSNK!ok=3-G)nys|F|u_cdsy=9dOa^)3zW6i2{4u0(FD?F1%ZnF>2IA8M7u>xsxb zfs*gX9O7HNd#0}5jj&`{Juv_nOhVzo(2-zMD6_FCcq}%siBIi0M09Ie@vVD!N_crp z8#vo-_oHm<*MN2tuLlbm|^GKxR)3IswQl`EGE`{ zOSf2QiWA8EGbDE3SpNF8iaxaOiZL`+j0q7GplO)MlqBneof&QQG7j2-Kn}WAXG?;u zL4RtVsCc(` zz*!6HaXRo4g)cp}EZrB(2vr@KEE(=QS5?Pk)gahD>gj6ID_I{7#pER(Z|(~()XAV& z>+3vlVgo!bo+hdgz402!#37Wk=3=FdtGDkPP{S1{FKZ5RQ5DJ?eDMM_@6HjN+rq5% ztYgf@=K6~zWFUtH)~0xYf>t}A7jns0S`Cqgn>`>ZlwxxtqAqekBY31LE7H*3&FTf~ zlecg&!g(_4KzGeY5C9hOL;lxMrrl@xn;+EE=@G@>>$WDJuA@qZ0DoWxTPi#3>hDoc zxtMg(h@x~|$xN6P(a!lEK9BtC^@J)Y(L0Fe>;n#yr_1K|;zN;s9J-2eZ-Ca;p(;-l z!>(*dKZk7T4CH)diLrKPDf^HZige%fctNfvYIpT!FyI00d&v~G$ah*mjz1Bg}3{yQk|95u#Yvkr&`*Rkt!TVY_z81R!`ry!7?FMl;~3Co;9vt-5k4+D`#hna!!E0!$YERtZ*V&hEPv9Q5oJkbz*hsDHFXQfZqT_ji4rE&< zPajyO!mBIJXRTg5BVl^N-|-0K=g&)~`(P+W!6;Q_eJuP+eH3BFm66e>am79jcwkn& z9Svnjo!0}t-m5Sh_~sDslHZ-&H>kjMwOIEE6pGv>usGiz&q7vzsngmy;8UmSubHyp zoYqROvB^BAO>7&G8l{^CQH- zUO-!-3yR8x@(w0XgN+nE-x#T4G{iJ>w3O!cC5b!sE$KuT0dHOr0Irb1XxqtjW<} ziW74dNbn$u5uupaJ_L0Vah_GbyN3^_DsWi7%b!G7-X` zU#+eHi;UQC{X{V2(~$)WY1Kn20ENXVk}KpXF3MWc;$yN4zWI|KdN2WZpjoXYvzWjx zk~|WL$K!tUdy{Y5O{BW-4$V`S;H*h5)7355J-SxOeg)+_2*F?1b1(3rn4Bxkhll1{ zJK?|rEHZLMEgOEU^{gf{34ZYrGbq*KjYl@ed*Iz+ zddR!%V$O=yk+N?UP##`ad(n!2uWRMg_?HhJnXIim%{1pdbKY#x^*?U#T|5!xubcpY zrAk(bVlQv=Ck(Uht1o(n&gbd292z_&ic+$wUmq;72bC3&I>5UHi&tTroXNx}MplM? z;Xur^cQhj>qMX`Qy0=z{cq)EPZ@w+d&h*3X4HdW6@8-klN1sNx>dA>3+^p&g*+|)T zSC^y`!R7Gzs=MGg{9l*yjt?PLLXxxOeyG};k&3&6DSA?N9@I$>Cq+SJi7VaHHR`^! zQzIqbYkJH;8ARmX%-8iv+1*-fdQU3j@BVnbYWG>1|bq8i|)$*;nny?sz%H4yNp$LD8I- z;Odt8earj_K*Qj_PmwrWyP)7CGcG;(L1}C0%LJNeSQ5cSKMB-3Q`ayp%BRAG`k3y> zhhZ!GQwkpMzOF6_A^>AKC(2<7lS!Oq>3k{>y*eT?hv?-gZ?4-8nmc9vu^Ewqa<|l% zum7oQ%uq~*aiU_{mK6W0^9Q}wj=1^gzWBdZtG3cFIKug!K@vy1W8lre{XyfFWXRod z6YGKnHkMJHaYYe%oWiq?-A|=v$6Z;w<&2q7>-VfFjm8z|I zWc7Y4S*O)ralq(*pp=<0r#*zG|-9eJc&aupW%-dG3r3S9m4UTdV&ysSin#fqU^bG5imE=!Q%ppz`q^>W;9lz& zG5Ix#ftTxVT?%p&<{cLtY`qKg$=-i>DhpHy3pnrhjN%=jC{6uLyn#!Nzxi<;v|SO{ zQt8O0Ju<~df%xcyH0m@FzNVgjkt>s&B(;|?^6?)!kq@+bu29zI^*BJQSA>I63iZ6S zAPXu~VCK04_I}?-%|Oup>kzq+2OK9d3#wU>{!05iY;O~_(EI?h)Puiq;C`^N-GDn9 z6FX9UrB4d#_WG4AP(zPMo;nmVi&0d*velCKq-EU6(p?v*2HmN|U!M{pe^BSFmP-nb z!~1*tJb~n49|>V^8x(KN)P1NuPZfgz5gUAAC9W!^fQ?v65ept zp9w5=-zeZ%9rfoYWT?LHv9TS_CBHQmu2rS=prLyEn`Ti$n@RuP*QxhMZ-F|hxrf;&p5aXt_E({{+2e7A*9R( zlHX8*+F$sCF+lo4nk8^ciuifZ_G_iUwZ1fwA@BTud@X7?FcYq_pje|vk6?TK+d-Y= zPLxF|ee$O-52pK{zeFhwONAoI9{kp*lU$Z_;OsaOoFcSTX=!R*uo!R9{E3-YGlWjx~ zl%;FA3pSb zin`W80yE*Qj5j$Y>@YO>6uUh4{Sgqx{h0$MAF8yZZq70m5S&d`a=Spho?OUf2mPMd z3MinS%@6T--u>}k%Mt{SEm8^g!}AaYx?^^!#+~y1EtNp>EqxkL@^J6rzsCr;#G}$pY#NVDarOI#FmM*W3Ug{dy@rSZI4ne z;^b&WYu*CZ@o$fE!l5SU0G22KZ=v`52Lx>rp}B~S$E+8S_Pl}gnwf?CL!ZN1+D$AR zFp)5$#XS@xYGJlg47+3aX-n>(*0b*cP=FXjRgf4|?^d2Jt>jO*@VQb?gss%{=0Ej- zf(235kBpwNJ>VISBaIYrQB5#*#c_MO0-pI#A4b87aOgv-@1&#~NM%!0Rvu5eM>)k2 z{OeC_h@_zGdUU%+vUpkh?3RmmVWw1ay#!?VA49Pt@`J?GT!`xH#5~=(cAK{-Y4?k2 z2Z3bSKV6tyb>CIPkhh{2>T}jQzoC>>%rA zQcInYV7DnSht>ulximC$%E5~Hmi12WW$MWM%16KTs*zypQyg}X6L^Gt-e$0&FHBp& zX=nr4O;aFVYGo_r#^Bxn3w);|x|I(qHj8Y%~XEzKOXgU@WyOQ z6#?xqpSbob*S%ZApqPjJh(nQdzrvE~2%u}05Oxq;oZJ#Ya@MTcY6I02S#-)yW z^u5bJ&bU|S$*WY$Mkj1m<-+29aNH@7b^(RLNu#XiIt^ox`Tjy}j2sU$M3j?CaPHEF zeT=**J?y9t#T;jrnuu-By033jc-+kf= zth3*^wHWh7r9Zo$J8P=g(&U+c`efl@4&z&!E@yiZo&ztgFt zwwwAZ@s<^edq-ey3!tRk4?8-lt5azWN|XleZ5U+stdI|^k6ljQBL)w`viMKm65fxB zH>exSsW=c93+N5BQ1rCJ{I_Os9f371jZWX--)RPbcJU`TuC#6UY|04NWnZ!Xd=lt1 zVc>YyBOuWGXM~RrHtFL0XjN2nx{L=G14l3Haq!*z_4r@hHD?-{TTYYG@j$#rfp=MHaD68;STiJ@O&bY4&C8=PhhzqvwDLb$H=-;<}kT8_U3u`;@4$6}hX zRMI#{1ax*0Mxv}AoZ5jqT zTdAYBhMq6Hd_{0d+Yb=nIsGa7dnPsT9X^3re|Y1w6QY0okglJcsIdg<{IY2q2mrY~ zhx4%_;tvDPfxPoh_yE)jeSyd{*Dt=fr_)e(+0cH4$pC;N8lVAq22=|Gy}Vd=Gz5K@ zDuzu!D|Zl2-A*C6{8#LX^z@xnv$x*DSa5tU_ zp<6Q>5(u>Zec|jey6=3A8d40udX)BpxGC$)2>tyK}lFu6`izb5}F&T`>!|x{zm# zByh9Z=_JYJRgHn?0Ocr8LeR1NvZI3zgUg@>@x!iKA;ph&5G_mcPShi?qRT5#^in_% zJ}jwHbg{G7wzON%x7^gOvzO_+&q%ZPks6jH%G)erX*@sVbY zr$cysnqa%bWy!n(BHGos(p6NSB;FvnE>A`o7*zI^#(jeuinG4bpWho=QkU9*Buwe#m(0W+7P0} zr_u8jOH`q23viCAULGqt$CQ~hhClbIT3Z&oTiDC0VdtyZI=G-jRku2D;*ueGNzh5-pBYS&leopi_?J_8lu?McnUY7&u zuYmM~N$^QRj^1|ydBJg?Vkf8;MVr2CK~=-orIcU1Vu8^JY38YW7O3C{juQRa!+zC< zuJP@*Bed@(x$C-FqZgZLdX6VNC8V1=U75UFqWX-TWbEVAY|a0)N*^>K2OBLA4dY&t zPML6@fb$@oxikF?DU*ileqlbwJhaey2Gbaqe6c=bDvs8B90e^TsEerAUtrJaYk zhMtQriFN<=3T>9@QJPDWAj;)d7JhhD;W6b{Yf#$vQg+Y^l3ij0{Vx7B{ z!yka1eDTBppK@U3{Mxnne<%6FIAIH@O)P=%(q=UqT3U2&LEQG^#7pn@F*_;X8UGXvRie+(g zu}2|rA+nxfXX>nJj+_JeTRV80b=KGG4*R)Y1~+{$RJDGEc$)0x|J0_*q{w`W|LUI` z#sONIGw$caDVQvw4BSYc1nP#cXCEP}Aaz+w9KVPW<-o`?vZ-#Rhl_ zdQ+EEjk_Q!dJpT0K!OJS-^4nFC7RRsFRwa$2bOsjaBDx@iiQ*jgr_M%-FI>IiB87j z{Zmg1KymyPsCx6Dy3_FRLC{O3uQ5SteC0->+>M=6sGg?=NqTxRY{+_hqJ}|BBZx4| zSkqer+2t*{?m7i(UL*d$-J&qb0VeU5w-?a)bw)Q6kQe2N-xekTdUnVZ@)TJ`LsixJ zxZk%dp9i$9vj>PKUf)=jTOPjyS_vEsyztYRMI{md%_bQ~Vn-_2z}coVwZ|q$@1NoQ z$B$+>v52a>6eT48oJAd~+W$FFt>eMZAjQxa2tytaob-wO{~u?Zw46NMZT}VIgaV-U zDH%i+lRnSnDVOSAcvMq{CSA!}%OU`}k&`78~rv3@_?xAXv0(yy>{(wQ*>Dz!f zjeOc=lCh9=s14ZuK>OJ0V!AIZg5^>ATHnb3o1^-VQ^KFEg%2a^INZ-e9f~e0P zVQ|SaVT@&m{lm+2MSRhw4%6OM)0tKeE3q~Ia|)yRq5-A?;CYTg%10k_l~v?vU0QpL ztG#cMNp^n5mdrgeS^HdI#U5AK&>4cPpR^pl2HQA)FNH|Bo$1yZ^p)Z_h2@Q?x{Dp= z^z4Y#0w9e8{Sd;pXIE+Q+i_q~x){k*&Z<(=SnloZUG*ed%qvhEtrim`qYPT|FZ&IpO%dRbk>Z zp_IUPZvv^TAE)yY~ zVr6IqpKazw!rQ0?q9|(5t&I7@ySH5Xfp*%I`_lF2$Jh?HK63)VSnGsnUEG9d)ToNL zkNDJx1_i{GQrW}voCB2znJJo))tdEhskQp0)w{<6fXo8Q5ssE!}vomZlKGU8Thx9QV*qRAF zXlCz&@NXs@yn*MBM>qay%%$JM>fVi3Jk@-WGO54~psmtMDime9K;QxD&Ho1zTPHm2p;UFD|^hQs+@K~ku5mCo`CrME{SU%rKZCm=S#``2is zK=aIRgnbh{3*LsR+KaqpQw;-zHP8B@khWlX6T&3~uzri1n!PW2NRWnAPA1TmU@yXEDca`1#lWA?B0$Q1Q zZNY)~a%7m&+Rbc3>$9)*p#LVQ6i*H*A7!h_Z&PBT4XJbQ{CM6sJ_P9xjq2C0__!4M z5Msz%Nuoxvh7IP^g3R&N_S%jK+?gu>7cES9`;tj8iyP8QjG8955lLmP!(@xcuaYY@ z>|h|WsCixdYAVuj-@E?O9n8P%#|1pXqJxT)mbV@X*;CCJ7>|SRE%DV@C8D+7Ij+ zKb4w}?X{*1|MJkaL5EAqs_>F_;hr8@6_`Rh!AyJsePI{zCW5PoOY6*^uXy^)Bq}!a zZesT6hVZ-2+~~HNXi+tYmy<(JZE9-Rs`b6dX9wy)RhXDPDwh3VbS*>AxzEh$Wz?7t zE{?_jMXhXA?vtQ7c~~isvb-xZvOY4Uwj>gzu^u43*va<~%R&Vdg9hE#2`|vUadnLL zJ3TjOQ4XBZZlV`aMkw4LsDIu4-r&I_qRgEtY*0K8JHoEph;^*o#;zGUuo}>Pcgu|V zj*UtV+hdF6ZNraPwqyH3{xHqzinB2LtA5K_d#8_%BlN6c1pJ3>jd(N=Y}9V0`g6) z8?C0~Is)eqr<|YQ5!&*dmJfxjEf3rn+fI6ue7lZF%(>Ye#Y0pP%8n@C77lJ{m@`}4 z9u3)K+%cs5#|{mE+39pGZ<7~uQt12GWG|w`ecWjG!@G(x@<=s+iJa_Y!(^g=8!;=?$Y#KhD!_ zZD){oOZ-(uMAYiw-PLU|wTVy4(fH0!hw%LFUcPL3=KA*X5w&RVK|K!F-|iSD7bhL> z7`9VAg!QnJW9A8uaJS_ie^X159dtFj!%y3HYOuacxkSr~@e>(;PJL}3LAuJIA;n+Z zTW6;9O@X-X#r1a4ok1f?>6#Lbd<61d9G*p;(g&3@fwA~|H)T&E{(vXahNV+B_IWyr zBQ2&fxpH;M6M*Rz`B?EBKutOGTtWtDeO&xkovX8Px@n2XWa4zUS4$V3dqDch9+ymu z0GsvtnW?fRj$w>3?@Y`&i}ZBA#JIe+Dk=qDXF zu2Aq0uX9A599yx|o%B;Rm_J+J+;?(pCHXS|{J|99*s9R)|6_9H9zbKu7SIfoVLfI% z{f%#bax6Uop!5Z}19U)v$kvYk>dGYO#QEUoG|D{yS@%G5a9A6<^nc%X7yMyI3RWNb zgQ+cdT@%;e^gOFcWkw95o-xwiowAVS3DANzhQ-?t zrggvO=5~HVZr?gk1M>VPzLu;)1E+>}gA}7Q{MBS;us=RkQnhn;n~F z^~-kpoVEek)P8XD_OdHsAVJAha^mU(Q6kY2hLF(6?S_rD=WNjgDH%BL!Lb z+qso}ov4RdX7Yq|WL;Ud9Z!7eqwAP$$JQuZBfD}O22FZzw{Y%M8!i9>Jj0WDrpPLt z6Z_3qwWgSKD0;<9t0_4l2%AD!{wnwt*RTpyRmiE6t7%oCK!#>1Qfsk7GhGSifc51K*?VYiXwjJ8S+UC|&-(r>8xHBEj+##Tk~@swqnP;D zid{}WlBEJ%`ZZ%_qEAuZ)p@*W6G*bGRt^b`cMq7$JaeKT^Q5dh_n{!2{5^4@bGMxJ z8S~;%!cKRC+58Rtrq6bNvol|%P+%R#wkLOh?er1O@?hDVOEx>29U&?W!PhWU zRr6uU>Q>mSB1(q?bMkC>xVkQOO4TMO>0*nOUY~3QyUW)O;&wWu^{vu;^5I67AhP+9 z74Ob#s?plAIx-?odsELIr_u^LT}4s-e7Y46*sUr*pY3WDbK`tEp3`Mty?F3RI~`&l ziFNGN{c10pIdM0|PPV(uuUVT%=guuJ6LC=k4jJG5lPTT0TI+QSuK*D&r0#6oBpf_O zX!MzwREx=9dXr6Pj`dOx$NgP;3cD$L?-y56k1+7EyVUb1uXoGbv>(`iDSj_GPV|A?q9hDHA9^EdPT3<1fC~17E^Az&BPhGo$P6V~7C}m9)Aqo9}T1 z??l{Q_)F$;jRy(T;0nm0v#?^{UhEa;!BSMdbKPFHZG3(EGuQ1g<(aCvdEGYs)!6*2 zaLLLOer>)KI}s1fR#ETxT1mC?T1U^V@J7Z0|6=uCRzwFl?wC_X>Y-_QZ>)=B-u? zYKdBwjYk+vUv#*&xM&?_uF3smvy09fB%=iioG3e+aOO@cF58js=3*rpH4#cV6&DdL zrmQ_>iaIw9*#l^6M3sDE1_!9;hqKDu%T)7~SozA=_$a$A?-6BZ3sg+JJ6K#y=VG4z zA=6XN0>UhxxFD3IwPe}EW!nKQl!SCWb~ZlSu|*~&f8kQIv23rB z;yR*Qr=8NTVgW9L&%_8y`oWGKR-i1#+(6qGC*#nU^gayMNc-;bXi?rhR8>VgbZ1~Pu8+s?UxnDpP12N=RX19Ia8AHs;EHc zzK)m6Tt*rxUbZW{g?&^>{y-zql$qTFYq z7R`uTr><(<#*xqSMK#5}>*@eK+^2(HvyKLo!ww+)#xKIpR-n_9@hky)bWiEI{q^h# zJ?P8^i|QNqP7*eMxXO*>?c_z)k7*Mxb0uAVk>pP~MAWbL+P~`4^MJqI;tlm&wv3!J zBzE3KH`9N)R)*E*PIBsJndYwo%sBnBSAh5#;b&Z&g-r!vJ=J{EK}JJJ(H?C-*}dk- zaYLNJ``6l6Whg+GA0z3-yJ+;2l~%Q@UUKj`snfYXh_QuE0 z2-oP&L&(qBPJ^gHm+-*^PP5(fIWrKCd*_RKZx8!0Rd3BT(Uss13S*X*#Vdu~r$jt< zc&R)4o}4E^I3*9Go)1ml7{7bA3Y{i#vGI-E=A`rHo*Fm3c+A@o;~=f5ZOf@rqPT^R z#rd(vtojqR=6MZCyr@S>Xw*V2VLgsF#$OW9eh* z#hdS(hCDCCpNDm74lkw*`&ERHV|Vw{4fEoTi70@T7D)$Qd50GpQL`~rtyS1YJb!y9 zR)0{4m*b7(OV5HA<||WG=Ayl9s7DIW%3jJLhyI2~vyUEd@-BwHvA!K{%b%1>&c5mO z&<~bTX@11V@y7dQ=8KvTRK<{8Kt%`%XmyLHlXZ!T>6~qfbnwYUr8OHFFG6XrJX+@Y zEZ?cW8P-bP2|j|ot9)74#)Wz$2CeE1mKj%6{Cf&Ve%;dOSihT`bn?{36>s zZVWm3v#hYU|7&fNK6`%>GubG^yt!LecgTw;7Rvhg zDzAkQ%DX~uQ?;d`0=xAAZe1$sy_Pc+WQxar4Zr!abX2-%bW%lcZkug#@@>RDqF+PT z-hK8B-|O1Jl_Im1IKGePinMY=A{M6w!&_ zdN*Qx395P#zz3kz zauh(Gqts8n69&c1u1&5q&w6U%7RJiVb9Sx7d5`KwZX+%L?RNk8V+0txvCC}!sY>l# zo?Qs?8~|--6M}pNKm!s1i(>^%lJPk@7uIAgzoNZNU1xx;c?b!(1QrsjDA0{(d$vZ2 zjVA+j1HDqlZX0ODgMXDuUz*sH0obz4T;Y3y@%ht2DO*7oT@gjZZNp4U86s< z^bk_=2L2Xk;dW;REM%`V&kNgIM}Zq6>A{*0LXbt3c4}GU4YLiIc1`;m$puld;+mm9 zNdlYs#Q+7XLvHAPF8tscwU_zOsJE$k!cFp_Wyy=bSKWc8NyLcZ4-u80&ah4NCi-8J!o zQ_wLXFn##Tpw&z%2qD1l9zWF?%)v1`F1J|yDCQr4Mk1FMd^o-`q4P$qj zKiG0_aRRtizlX!mAS!%7bsKRFfIjNNTgoxjOW>R`n)H7AQ;$NF9)E^LTv)?%3{?V3 ze2k17>V1LvT);~Y-u(TK+X(sxkUJN_aj|Mk(WW{HoULspMF5x}B|r)QZ4jd52mIG) zP>3%t0H_iM&}dIY9D=+K%!&u$?Io&6~`qDbk$4Q134O9H0?)~h^PCk4>OGlZZ$Vb3(0dZ3P=9WBUS6subLB8h2 z*}Y<8o#g$WTE@%MW`g?7d{c0>#R`m%g;Wc7Gwv7OUe+AS z75*N2vcdi}nIyz1*P{Q%^IKQ*4tS1je@gM6^hiQXZxIO;u6FPJ7mxgqU{|O{23eti zdwDL1Ywg{C5P~qo1Z=khs^|CEyhV13{=^LYQy`yBK$C`TS)Uy@bOkkLIKBZ1Q~!{J zA1_Gsp2h16`W4Ov3G9F$Is2~xB;w$!Mq6c77eN=G_E$oXwZC_Hh!QMB=>en_$VUFn z<#V7x0O9rj{`G&21FB#%4YS8}hptKNu*{|s1-qN=;V+Zg&FnI%)a-0S@fWjpbo1^Sg5eg3L*SpY+K%!zL!OY$ESiZw$x=pKLC(lD0g|d3;gNw@@ zXqznLeM~`sXO9N+R46hG@M=Fy(J$smLmISb^tfihShhV(0RzGlx8I6mhF3_@-rjEgCc{o2rT>ia6vkhu~CRU>B> zF@jvBw)v@;fQvmq_C_@Bn_azbmW%`>003$|age`Q=XD1SJWWbY8V}1_7QoSau0OW#zz=hEv~|Zeu^`EYNI?!`#<)bBgX>-c9l{Xs z^@zaimlh9}83`G4_zproPyug*z_)`H?)7-4%B*IyoNW)W7(L&hmgPd$73 zy**c-fa(sJh#wp!r8WEqgBTFFL(jy$4)l{$Xl9ZZ7W|!X&af{Fxi&2*nzjX3=-p>pl0q;j=W-hei>KEJ5MP#$dsSlu~ zUrz!Wz_UvmVveToiH*}#8dD2oJ|80WwkDMtZz|3li3s>HI#7(nu{Zo->Kporz64J& zBj|`sELWQw7n~U<-q?I7g1Z^7Ag&BioB@gu8UafSv~ws0VhrvSIL*k0#vy~mI?xzf zw0P+)yixTbga>H8qf9xQzUI?I%zWK90*VoFe_qAi=e_V(ivPB_Vw2^EI|u;iMy;%w z4sii6hbQus1Im7Jqu^?s=~^d#IKT}*cq0ZF3sJ;>WCA*}Y!|-gJ*F~PWAEWmz0c*f zC@bEy1UGZ+_aq5;DEYMXpCdKm#Ey=a+rBOk1I;jb`)Fv~N2MSyfn4s`c20!nBYK&m z?buR7%tY)sgQA}8l|i9>H`nW|Um}s#x~Ql9o-bJx&i$<)`T&@O&vIQ%5hzTFTj6V` zsw{wp1fup@22;d-#Bk)mt5ss^I|!ENq&z=gwl~Dksot@&$ueN8?LFF^wNrcZTTMvX z(V?kY6KQZ7g^Ke(EK(aMBE?}T@pxMfY{s8=Tz#pVA4@`EO%aLw0?%$h(Pf1$9_$Dm z*!M>RNZvmK0W-Ef}$NL*?fV)q$+=$y=cg=PH)LtQp8; z?`b`r>1lJL29kKiHP7~f*+I>ah1d?En zwO6u>AxdrMfl!GXI-rX>4qgc&H-6>_+P-NR#wRBfTDyrcmxFj+*yc*KQ-t9}ig@-n zj=J>mGi*<76;r5^r&+d0j&2lk%HzG$r`ptD;i&J0t;aQAn=C4dc*?8a%aH0MTwXiy zUfv&KvEOcru6rs3wPzKXx|X}hP^Mxj!lPpV3qf|lfz6&-y}i=AUsOS*0s%Q>_TcwN zCtO%o4C=)R$)dD|h6yzw)UYGKLbvJ!V0ZJ-h^#gope4!Y+&8qkHa(c+03SUVyVa_`=2d`8OTb;sJlap;1d4@DJq}$3f!qo1 z<2b9+XA@*_ja$;QF{z5gJ81`w@7G7t72 z#1bp@%ZCt1CO-H(GvCqcVE>n(vS?Ky2ca&-V=NoHVW<+fw=^nWy0jcy^TtDzJV#0r zYX3ZUlImbZ-I?I9Q?F;*lU&;H&Tnm$hlqD(m^#glvv^Zs?cSsCyQ8k^NqA)(Y#e6- z?W{PnliWxdZjNG`&Y=#v3(DcE@`cN!;B3NE0@?=*?Rh;pjKN3gb&u*q6U7X!`UknX zx_&RW(#;wZy(;L!dWxKq)#WT7<% z?m;!38U|nW?zl!KxNc}4#`rW;Nhd@}yl4^MUG55i{kQ>QN4rq1SaVVQ-sCFbN-y8l zoOQDd$eJ{ZtyEGT5p$vge=m)!R}|hgsH}6C(t2$#oYwlM+&B>WU*^?^AuIkHo+b0I z;ctN+=_j5uCJOFRI^&n7FguUxS&c@(3_Ti}a1l`Z(twL#EF(A@lc-g)LO=;1djo6v zNtYae1MuZ&c&oFsp;0!^GXq8f;^6riUFd6qvATB<<;ESf%M#D(aMVN1!FPcE$C%qi z;1oe+TC%Fkph?`lvu#;GRcrDH22YGB!*D>u0=2LVw!7GNckk4ln6{(yA3>-?MX(G@ zXpc&P&MgjgbW%_v=ocyThM0x)iiyL~UG5$T zL|*)^B+xYJhX`dMy9k}{QlXst!BRCvRU64o%yrRFd**IQJWwE9giHmqE0QP)0TP#f zs;Tr@s4Dxi{o&g1e)IDMIz$F-1l{SIc?Mtn@x2lI_Hb$8f+Ko8@fEVg$1P^w^KvJ;q*cK`7$v4&rv%(; zJnK0go*y4JUCUUoqV2NRIpD!|6V*mM~WE+8OE4i_* zeDtYg!RkRyBL*9ktR+(r@0X&e78$&_nx}(Ks|K7QdyauIO z+pGI&@j|?RPkoj^Rg#Zn~5JOD3EmK zs2?NivjN(Lzt~nS!nZEc&O{KNp*pw zT#T+q9q&^%iXTIGyx{YJK;3x4P8&1|+1epMBH>+uoZ)LRqn7-6=AaURB-Yzu_<#`} zeVmG>D!1s5J=4GiTkg*27hgz*um0-fTNM zTxx?ZueF0jFTYhKpG|man3N@tJX?;xc1a2Nu_EgI_CSjglo!alp!W<7MdnV_ZNK=o z0D-E`h9bMV0))5>Y$>CZ)Ks0*`(dH`mO!VGH*gC5I576*l$HV}e4^-hE|FZlysinq zXT2{Nf81?N)O%8R^O-BfV~Du>&U>+Sj>^|y*Y09SU5i~Ll0WLL6qhPE+Zi8DkKj_} zG}EvmWfs#_XM$02p{vpp7a@mXFo1(HiHg;MbO;+utr_xt$3EZ;=9$m#Rs*H_Dtynq z&-xnd*$l0OA*S6GOOJ?+WkZ-t+ZaJrpWxhV;5ESJ#s|V+f2chU-8S{|7$F?7g|L_N z`?gv$$wiA;fQ?eqF^^Y-`|ZoF`QThU3%3qR`fK-598B;&cyN%I)Mb}lEwN3(X^9fB zSwjm++{4WXrSt#@wFNzQvj8~mGlIE@B;1*VW5Gtbqe3&*l^pv`Nk42mqFtrUBw@TK zPu8sWF{EVXn3D;c1;mcqZM9u7u_VT-*`P2a!;IHw=6c}B%K60NKY`du!EbFJ+34|x zDr5xjgE>I*?tu$;5pRt08(_6Ndlq|=_Y6Uk6V6APmQ0iI#9OMC1}poN9|plfo{hM# zgX4k2=D}0vtLmS0soJE}$BDacJ?|Qi z>%@&`nQDUL(1?prUT3IoWw6|OOul$$l!j)4zu3q4rmWi+LY6InRw5^-bg9q5tYeRk z7!y9Dk&jETAfxx-Y>&VNW`y~1{O5pKF17G3e!7C!!@WsjT5iXVbReDGaqhR$N>-`N z)sb60o;Oq(1}@J8(>~u_;6C3UqMO50raPL$mzP)PJg0{yS)*s!eW9!B+yR^4)fD*Q zYk^oxcCaCr5s}%X(rWTR6qGbyiB@0grRvBUlQQN)^wvs2bZ?B%N?@6^j8X(jR$F3Q zA0`lpeq8cUU9XX(F-&ZJ_w!x&JtJc0^0qI2stpDqT2TLl2%!?C)NIZy4%&vV1d=wV z2f0PU#V*IuCW&|o1MTa>n8w96g2jUpZslly?XYF@a{{G^xvY_u9m_?2I5cwKpOHrk z(GM*a@ZBq(z5og&2}AC2ZOTD0&U;P!+8tSqC**Mr1jBbF#5yAYc81b^m0#4@#gDCb z`Ej}pyhSOogO1imW9u-BlPO12UhQ^Wp^Kd+-^#+{;jW*=MMhX}d432%l4rXY11K@p zls^27FOQ`6J{SHq#+5-HS}i>oQ2Rcq^(uaB_5#Y%CueC(MlJlxu14q&2TszFwI^AR z`*PsS1cZUXRiPhLqLEp_J-QHnl4Auzaqy_2YMrrl-@5NVvP1W zYUk++jcr4Rn4`=^fX46hpCEV*I0XRJT4=-=NN9aWb#7SRgRS|>SPlGniJvjTrU{m_ z+H3cH7j60oV%1vPoBbm)jn#(uPS|;d8q*`hOM(SN1qJujZh|6LGX+6`;-G0MrV==l z{UZh`Zz+N|hK;}WYic{%Hy9NsH}oP-qgRR*(EpkZ_lc(qpN|p z42MklxzD7#ll9v1Y_>yES?m1=#yagqU%nbOQeKe|?wt<^-C7Jq3J?HI9_gkMV&O){ z&a2Y?P~LSV6>xRZW*amT`R>Hfj^G{kUG}Az43LusqOcR2(Fo8$yhiLJRt;OPf8L!+ zo2n%<_o?i9@}yQ>Y&5)H{{570xV|ccmJu4E22oq1s4$(CL`%$dHrpBY66rBs&WN`? zGG*vz$g#J2;{I(^6MJRL zm+vCH4a>no?*0o5h}8)jwceqebt#lAo#{nI2nd#L7UMqeH=Fat|9jHLa0>Zf<4l_- zk3S)->!b`>*BL}++e#u15}dVe#?N%1od`jL+fr7qUB;@7HDlA8L2Fe?-t0~_@74dF z4mhv`igVp|!wm;eF)Yj=heU-zxm&T%>O&8&7Pj9-d{?L>Pa#LPIVFtq-^!l2OCvtm zhA}NH4KLdlf$_Mm93)t4$%)SxaOYTJX{T_B8ph16PzCN_b`KhZ zo!SVFfhUbPFX#a87G^{xMBVwg4XLy;1&=D@WOovr2+4xWB4+~*L?a@2OqoBs(eTnz z?}%g&9JjPWYnnirJuM&^XH9=! zJxI7IUWFm7jEED(=`iTDOenqxqm7la3a5#E1&+J*|Frj>VNG>Uzc7l3iinDo&=Kj? z(4;pB9qGLZ1VUG;fPjjCV(0`!niAE{;01fHwf4-cSu?YKGvioKYO-fg5;mivO~DVo#PnyGY{({hPDhYo5MGlT`I7Px z7*J^I8P6y0_R5VQxMe(sfjy?MJA)(vrS2_96qF$)OACWeW=j?!nWmE)U6m|&ta_2 zNR@Gm8r(D?4{0I>iJk)&^j)^cw;>`1zDji998`zC6cyTwl%)tE;T*Fw^}~~$oE(=g zKbVq=$u5ZIFi6$qwJY?)1aIFAa-jiig-5R@>oWX2m(72|K;+p+Z@7@!1EnEH>1tw& zpK#S7S(({Z2$*Fm0Uf)~m@S8SuEh$liT=5LKE2GQ~lN z^)ze++yrJib-`S*C<`dQ=SAO5@Ea3|7{JPaeaMl>#x`_Ib>HB$eM9Yvy%KlzQhq}S zaNKTG5zB1Itj`N-fe4iEWv_JPVdDgEj2h`;LHAGr`;YEtF29)df18&i@^qn;KYiv` zjP=wZMGM+vUR!v%Y<+C4fY>d6ka_}| z^Zxv06JTL_ej&IhXw>G2PL+0!S%Vkg3gQ>K<^{!mtRU%~{FjD4-*eqR!<)$CaDf=J03dA&Qev z54LeAet#IN#>@-Fmr|J-54oo>@FN|YZtP}GNs~r(;!67$c(jl6>6uy|AXcIc^b5`Zj_nbrRfZHEy3=7||nPAtaN{~S` zfSnbHUn|ptgo$>RKRp7j;83wgH3U2mBYl`ELX~zbA+fopx}D0 z7bqB|f}nWaFXs08+{jMG*Egl|K9#0d7Yta1%X%GeTOc+Uer)&9#EfP<2lw1U`Z5_| zw&j!|U*)-x)^n@g#vCeLd1)Qi#?*FTXLh#&?^QwBf_Suk7#uTasY-fut2iLD4xST- zgg2`GO221GW&m97I^^&oJq$Bz>drbox)i6|P6T$oU@y|;b7K{Or17w3uVlZqtd(ie zPVcicYxbVqZfFv}TJa7yiH{Tr^56&ElS|mm*{v=M;c%4Pm)YO+=RJ~)87tPQ0OY!Z8eRsLOZ3d44sV3@#BEDbmCKkG2KB(r6^BL@za0>xMEdq}Un zjAzbD-jF-j063xT-5C(@AVPOI0oRtNxs?nMj`T#y0ff7>+lhWv?H;IHzuUd!Fqnj% zUleb`w%0XhdLMwfBXDAy1x5zdm|*&LdfpAj9Wjg28-Vi>pw#{41YA@@)%e@4mB7ck0Zhj<8xVN$*&)8_i0~V}= z*Ah6;9g34)wb!J1`wLQgw4uJ9ya^Oz6Ci+W* zCw`{5y42g?R``NI8`=^0XlT>%3H~QNa~Ppb8NrXDg`GcqiP<>c@IwwkWx3XdtTZF(*ZiFM% zw8S!`Rj`iIG(p#TMaH?A*(*xw`(ZvO(f&mA+n|Bt+=TA<^9fb~<(QT1^k?I5&+wJTRu(M3OwFW)9 zS`Ws3P#yni--B_l@<)^%S@z@Fp9p6BLUu=<-$GoDZC{AW>cvPvAR2IlY8|N`#@3K9 ztBivr&MuhHwA%Z<>_i|SqZeX7ABIcv(~q)pG{8CclOB(H@@{Apz|(hKsT=OG-2-iB z6!Z-fP+A>o|4Lk{r zL?UArLxQ9+6aLk8^pu&^YObH+W3wsyqWb-xz zfA5!QTrryKmm*9gD<`9Ko0jH=Q|Dd!rk*Di_1;7ZszBez>&6kYMrA0rmw3AEb78<2EI=>Y+!s znB@d}`-oktD%?Z#R?5Q@yP9aBjg5 z8;IJUPb0|45T?ZfF?-fy=7V)f&dh|Ju9ElZ6NgctZO4{ZU)MG;OEmG3>J+-`DwzlE z(n%SF(Q$CsEu@w90P<+l3GxS01DF<8(X5%W+P9FX-P!uXpS`;S(^K*A;GGFTr4ig} zc%)tlAp2$le|1#R2B^UWeC+PZUIf!kBcusV_UbOem~)#Pw->fda)4HM9mrX*K6TXZ zdpo&%S=C2(U|>Y7y~y{`zFVM%I|+k92k$xuWR4>&R(Jd7tzIpZt~+gsryeo3}tb?fe}z|rSaF-<79U4&ZTPajrbR-!rU4S>?J+JavU!fS9=VGBUzCtYKiDf zn#r>n#{vZCa(1(0$Qx)ap^o~u&%aoqqygA*D}3gdFd# z{gNJv_J8>JaDH}bqYSnseN3epm)zALEpxQH6zEOA-?i4PA9HMVsF{TaEZFVB_JsAe zkQe$)DaJ12!oZQQZ15<~XElEEk7IMU1iXKwF9aWS$E3+a_;?g5BEsqapwHz?V zv)N@(ks-c_LFI{tsKR zlA)B%r5{w-jIKXsQr}zLp!CUc3LKOhe^D~coeKWejAV%5COL4jP zSdq0cnr47`Oc!;@loZ2fEK`s|)L=OyaD%D<*>d0kJC}=9t93HZ2J{H+viCTc2pr{};0cOQw#DX+J1hWz-EXv-OYmQ_;zZ#UrvzfL*tILd?Ko{N zG7r)mOD96V(tRXKd0;}wstZ;RUb`iHM7Zy%&WltVSSYs6wC=Yi03ECwoH!7jq(9{)Oo?oMRLRe0YA zdRL?hi-<0~td=4;n2oRi7UX|hVj<9+F7cV#3I;5x`G|IN9QKa6Rq@@9Br<8a*w*0l z&T6tQc=0_(f3`*kyy&4N$baQ{z*@MqUHa_+0O8{x1(BEDG!uzMrvc5cX#uu-BG41D zc&9Gh)1k?lwUd;f=+I$F8OL_lf8UzlexN>R0E7{g^p&TEP1Q%%$r; zw}o2dOtE8l;-UtgRh+nK7)(dn^zYJU$)pX*biz1mTM?q92kAB^5{~}YP9zWSZ8)#uUv z2SaNbT{3%wUy&CzGnIHVR_Dr?VKq>LH)XTsCFLNg=f8!U9Q;P~KVt2V4jhNbF*;=TKLtZyPm{6y6Ls3r7GR<*j?3x;px3`) zkVSjhw|<9+?oMK#t{zWTsXTFCV<7ig?@vPS0-~PTzCi(l^d z9qCi}qA)Y~Qo?V+PxVheL1X@g>Ha~m0qPB)(Fv*?h`R%ihn}LJ{tLdf{r|m3%bbJu zX*c=pMXvpKc;X`)0E!EpQiM?cMk)Rqb{L5r}Hnfc5+LkUcY^|MM%fbr134 zV987WZTW5f4<NR8XxQyv z$FXSp|AwWd4mJFr#&0D8F#<}o9S7iW{=q?`Z2_p@|1h#VMCHlpI$9IZgM&YQ{ILGY zl$)E|j*~tG=fD8W=${7)N5*TM2>6=Az{j@vcO)caQSy*^pmjJPNw1m;e11v1w{C|K zoz5#=?`VqB)X1~Tnm=aPs`p#L6m&(ojFwDnBk)V5C;&3#f0D!yi?(Ii$(urKlYz)j z*+E)1zK+ru$%qKQt( zyYb1{)cWf(ao?-0(l2*CWN1zMu)7`>G_nCZYto_8f5BepFCUx%p$Z}>LWoa^IolZm zA&s_T$|R@S!Vsqy$kvB6@1W%{E6BfamWn&y>fKGT%$EPWGndo!6j>E{TTCON%{cTes zljIM12)?UD$s&}dc9GgRZ#RP=Jo`#T4>F;c_%~98e)`@w z{(`2cV8HVr7w+7#OvDVSj;_W~xV|e@3J&Gx<7>r&l=+ zE-zX#TZ(ixG{aK{X}k#n@biBN(ZTb3nQw?~%c8l(qmS-f3sv4Ks(65VZ}txh0n~oy z3GDUf(}_C)(lS&Hhlnm4^aYC6HqFj=|6v<|)CHex<2@ES6;y_HhjL#Z-_qm?_wasd z*2q89`TLZ_{ZjiwM>>~is~1fB2S8sR!ZF{Hbe4 z`QVwKl}?)Wo&h*cGgI$dS*5a7Q8)e~TKR7kj!e=FKFjYwuchBhieFhtf0we#hKwa` zhq+tSNZE$(Khi9Ykp15DVT5xU&^v#?s%EP0SAMM4F^IThZq_aZ;wD_Kk2dQCtRGwe zgZ2MF1|;>?_@WIC%To!`%nquv9VNEO#BP_uY;xP@es{f-Ni* zFY$-$FMKDc*xzUa5FZH<)tiH8=8$lI%XBM>peHZ}gbJYHeq$ohS)OxpU6Nd`KX7q& zS);2{nsw1q)oW9=^A{GTdk@M4fM%9}-gLL_Qc+1KPuBY(FZ)7nAlnHDiv9*nSA2M( zrSNL}4uGW8`7~F|yC20WUi!^*e^qY9Art!?ki<7~(b3v>eDMdS8T10#Y)7iQ#_Ips zK|h08=~ZGTFXq?BHQlvjs#Oel6pL1g1LQsTX)$uDF$UE?xK~{-ZlOLm-C)B6Bz^n_ z5%YsvT^J@p1nHDZrDjo@!A#UuccGMYo;EBu+_kj z#Ru4>0w6`_&z4sy+OFTlR)k6N)UqW#sD0CnosS-r-PiWwH$0i0+q2aQKQk+>&&YDGs+$YmO5erqW6J5$Ub z1r&{1hirTW=Vd)BOxj)n;JK2gXawp^spiiv0XGNHRXS+i8mm!av?Z!Kq45y76#)|e z9|qw8RA=H`hCuL32zsfUnU`*+Gh}33;vb?Bi?5}u6jmGJ&5lwDG8RX}v=_mW!tT~J0V^fhv#U|Iuk(6DB^;U%GBCgxOz-9^dW$Z+Vbh(Irr!j?(8G~C6 zw^DF8O+y2g9ofpsd2F36KeM zl1_2;pfduAB-Kwd^*C8WNg?pbz!JjF0w(tF>^|shbc4xZZ{i4}XinBM-bfO|6Y+mX z^f%SdTJ0hAs}Q*icWNVL-qmLXYl=bJ=k4)o(Lja{YgbTkIQ)x<>S+SyP~8S_ve4LC zJNdIfOjcKZV$F|RKSW+?(ah1YZa4$7?7BUvC;((ey0mj?hT>0ns@6cC+RpU}AVPPK z`SBc9djF`u9(bc4eJ>Me7$~#!@b5J4mcj%nX^wNViU~|7oXq$8fq)+Q5Vrz_7My|O zt6@7(%Gy)t1XkNz?>-?Cq_yK?iI^Ymvw#>Et4Oq&w}GuVWCwRJjL&VoiN2cRgK@Co(eV#zlD23_jR;|wzUhuz; z@O8v;(3<-OiR~1_gSqgzU${@NVpdVdBHiEj7a0eQZ+acel|J zo1Y(gPcAG+dRZwmyTuO9q-CKVlHhOM*X+r=x3M4F8{)OUGF+TKi< zxFZ<|vaBph_HQ+BCnX#lx=z$W_mllBF0{9Dh=Q*Ishz8BWL-R()(o%1$HWD{)p#zg z(kkvlRp2)o0xM&0H@PvSH^7ZnO=G-`{bp8#=_}T@5>$YN97!(8%M09bI!T-r-glR- zE-K7H-Q&94(&#_4vnYyHDQ@z(eXIcA z7cu&>4Xs2>{K|c@vPj&lFluurh1_g+Z~TW!l27%A5Q}Ujc>zi8)3n~l;#MfrYV|rI zdQD>6DQVBG&c(_)qtDYjv3_+|)~c%IY5?UKpaY|%deNp!iTvgfsa#&v(-S4a$18eq z_DNe%@Im|0R>3-Ikd1|fCIfvs=mT*p*Anx&BjmM{byk0?34(67RR$)#SsFEBPPDg~ zD7Xglss8lL^C7|6zYa(8Cx`o)Uq@3n>rRiHxW`muP>A77(+V~_5>Rp=vty-S(upq) z*!K>2KxaLA}Tx<1icmj6QrZHE*ar9ON~xF1I_ zrApjLM7#+tlkB7UOOkO~Ss`J8GGV@t!iCSk8G40Mw1r!bPr56e&^9(og3bQ@>o@qo9hUYF{yqUR{xJL8a)VMqKL(zT1x$MM#LI~_k)*We!`iu) zPJ-hqSPgRp$q3)&A#Eh(0%=U*^ek$43Fe(FHTu&WYF^M_{K?!su<#oHt((Y5$-pp? zFXGVG-i7ETgW+941Gl-#?TV6O&A;4-mD$SiR7Ue52_?dTj^oBzwVLb_mMANamroH2 zU#5{`PLU!jJ2t;ElM*U^%u&5IQ4wL>A?259UVH&=v0#}u@pGEZuAFdL+HFwp3Rs|$ zm9DZ_;K!k0~_(R?&>MBddeZZ`$UyOM9W=Af`=oXbmEIPQWP&@E0sNwsV5j&{0lD!=^ zA?RmXrOODijMT`nF7XDbgUCyYhxKR07crgZ|LlY(=M}FSS7Fi-0bSyP*zGszzPZ%2 zy2#rio$k%=;?uPGURJP!i;G3hSNXhDDH{eIg;Y0wyOuc?Y*Z;6*@+X(XjRrjHz?39h;n9CvF!5_Qh^)T)$a%0{r88--bmL4`)$iR zw=K1BeCHY@PcNj_s|_E_;qESSPUg(F(1a|JOEp95%H{Im;m3oWd1?w-MTquFb^u1R zh{1P7WgCr}4)wWd7LU_#b#5bkm1V8{kKeGBy2TDwTM%7n7h)|_5Fmm+0mNEcus<8R z_SLGNqnbV7!$hAQ7+AHOzvq^1b4N8d!~xSOrVep==XJf4_SZdMDG@cUV7ClY-$8rt z@t%83m*27h5Y6mSHCKxJ#bPd%1(}vAovyP4FYWvVOY;R5mgeU#9MDkv8=dFNC|J@V z{fAYvDaQKF@h&73x|%sd3v^F0d!%N)KsF4tM^r50HQb#<4l`4e#bc+eH+xNWzT|yJ zo^kG+PQPk0`l$gb*n&x=6Q&>UdyIJ#Flr=up*@zE@$cwns$xrMyN^Pxlf-e}#Phij ze2te>27T`|1UL8^?t7D&tLth{+(fnkRNvA(9v(0ke$X}utw^G^FR;CqJHiDroOGPW z{LE7u0;+dN0JhQs3&0ZObukZ~$M$feWtk5}n$Up*iiSU4{;)aXBqI7=Hs zkvG_SPQdjY2rBYUAY<8wo(*%=yy?cV0SLj9ss=&+bQ?@4Oyff?y10;zim4jS!3R#)BV zx8W*ot3+Hm3myx}AZR5Oeg?#vg}`VtC7-H#cEvEct}H@R2}sK zaYl&kMG(=#`zR2CR^sQwyB}ZLSBTB9t_r>s*A*YERD&99;d0h^7R4`!d@PZ25D9k6 zstc|Gi(idxn#k#=26-R)m>7{iQwD&E1074649P@q4;JIVhs; z3%1PilAH2U&i&?!TE~ z@+L?c147$!c5Za-^+$JwU(jew3S1q? zjM$`oqiz6^iu%c-`g4As@N#skQ|}L_=_Z&|NK;P>9_J3ucLB&(?;jByYE!j~WwH4~uv`NO{7`$jyS2-|06%51x?_o=Zw? zo4ZSHO&uKZ7h_cdY^foGuN3*y4`^zuvOB-YpDyq|O(Mmk!83EJIh8WR zJx6a%)YI1EJyNsju&>5v=;(lmJ1?N^Jw@SET-=jGW~(3>u**~H9Tk)c*ovo~0br*K%H2%-Cw`Ks}t`2BBk5_!u*9D#auJUk!-{G+vpXyN4T zQKsZCg)8Cq6>Cy1Y$mZ;G-3uJ*9g(pZA8prra(o;e@zhvmVC7w>Bg4!arj zDk}Rn(#NqI=952pDd3>aJ=m?ReT}8;@)OYM;%3>iZPbBJ%}PW!Hn_EP%Jac~3gB)f z`I?pZk@DKMP9{y6&?z!h82dU4kPY6D6LVvnxW4DJqQ!RTHk}53kIdxCKDd0sm_K-jEiqwD7)ViN4Z+^Ft10CY>i!QZV&Z9Vz-4*?u8@EaGu{hI`uy)beH8R zbc}!#;ndv#0I)(Tz%Kp$HwDQ3XyAN3b!32yl`jmy2e*>~X^Ypm@tXx|UiV*VeTrY$ zWihYaoJ_vW$`UHp&eeUQb|1?_;?OVu{fif5BYLxz?*x&&wuaPf1C@yzgrsD+fRklW z%>kJ0Li<~-N;FO@gG`px9dR)imftv22?)iI^!ds_R+$6K`)ZO2D5C*65Jv=n6W3Qp_wS8*+)LC;LdFb?d)g8`xfB*`+g z?8pZBRF@Q>(DS6xtrcmM=f(C{ZM0wv?LfC7#O1K_sS_ZSpasmG$0c< z2xF@4chpLgj7%V;?lWc=L^ zruDjaZ`f&gNK_~uw!ur90}#jlt%IL5wmi0K`Ku%QFHH?d;l-C!E$<64io+|S_dz+&4@7W+9vdx}XGtaaPfQ=(QLeFN&< zivBofrnQ(8BbD|ocLj0HS2si;_^Uarf|_qOe>>XzO7gY*ay;@`G1?>IfL zJQjIjH+i12i@Qgj9L-*&t8qr(bAwQ&w%KQ6 zg#l{wy?8WLieU63H<+|h`pDNd-s#&iU&-4kw`mY+?$W>n|(Y@+2w|Qf8U(#;k z*-L;qO4h7n;q-DND>Q(AQ}J~Hyy_6NF&qaJBx#ytX!vp@Pxq*R9jO=WRKC!_dPc(( zTCtRjhCuF5(#rOBWt9hV3w=HZLR{}$i7Ox#-Ml(pfGue^cYWcQKT>+vZvxg5Jl9gA zb?wHRrUaf5uBsn*1%*tX)B`%*{=Q8$)OFk=!s-`V_kz)*rMGJKA~+3ZRdULPF>TSKrI?EPrD`N=SJLJYyAh z#k-+Wvw9IY-at>MUy=p_y#hlLl#MvFlhFzv=pN)YT9jv&I6FG2#ffnsLmx~LNCX0sp=KfIjpEtH>{{vJ-nu(1tG=OHCt0T-F5wn^GyV;nbFPtJsAr7P-p}@zfuL>_`aHj2a zU3L8ZSB7|l3*T0-INU=$_f0aqCd%_#z>pQBq=e`FGR=Jpv zX@#12=I9L79+4=QKwHLibHOtPA$)n8On@fwF3pP{Y$$MUC`53AJa2 zD{Ukiog4}9fF*cUz-p0^;MXzUe3`46g5sDmtz|dV7WQ^v@R4Oc3A>r2=wyu+>hiYC zi&5oWE45McjS?DA*d9>CYCoMC1T~mk<$pT?E;Bjh;3@v6S=U$l`%E_Zsan`?<9ona}?na(OWPm}* zrAzzK$SS$>jEQ|p(t~tLoVYW;RCR`VLrY+P)so(}RTSGQ!m{bRJZgHh`iDj7eq%S) zxmo46nF^4gIRMydM^a}=)g@Y&d`lN11(Yvni#dDl9YH?Y|l*X-po3Y!w#F5PO{s6qzT zI7WH6R72Rr^9Dp--s*y$eT8x6z-#ndgx7m`bcU6aN5XBPAhP?D01djSY-?jCHki7l zxgeHfiaNw6OzZL9J+@Dj1k-(lSA}}LKO<^ZzCb{{{wDL}z(+2|N(L%Mcwv}!*D<8< zY%DLpw>?GI_ca3xFBR^$?W&b6eXKNmQJZ)c7)gh0MUYz4!&?fK3v(b=MYnl{p7P(fRAZ}9c)3(8#=tY3I%+A_;3SZ z`7oP~si*nVU9hPT)vCph@LHEL@-M`ecwZY&=Gqc$Ja?qYrYBh!?3YKY^8@!j^QTI5 zPJ{j9x#TRAz#1ixYXX@Dyq{gSj^5t!;U)&gldp(~DUjtCCpb;$L_#7?6Ub8bRX4I?28)Q zqAtJMtk~MPGt6$S5%yMW1zv52PBM7%63{)}jKjSnM!Gq5k+t2^&)(`kds0t3R*3U$ z9qVF8A<(Av)$BP1T^ds4Y0s@FoxI1{rQUgxOg083l?SiAotc|wFm-=L=WWS|kQDl6 zE#pX@HDAN%FqYbdGg`bQ0x!?gsDQ(u zKnBO%2c>@U?GCMprXC5T4dX^A5bB%0SBJIjgkXGXJ+GUId-&(4%%dRR6B{62+32x& zJ)`PyQP=0b=FSxQFUfDydJ*pdGJSfj5euWW=Ak`}0-X96w_>kh$&>T^+Ul~jUA z-eL!=F7(4sAeQ|1J(91cb+zMp!(h~FI?9GF0JGX8JG=)N=r5fevrrsoI*H3D-j2O! z*f(mk821p0gD*yb7y-D)UlU%(wMAIceM{Bve8Xc)dl9+65%5T@=Bau~;T6zj3744L ziB$1_uWz^nY+X=u0YT#vbA8O8YldmP>nb7lwCSZrU?LGryl!+R4|kcCi}*%env9;T zhCfetD4yI7&o)BRlVKvl{dbek7n_w+@*tUbh&fIwhM(O2y!|xP{E5Oj@H=DPo{}Wh zSH)b(h?d0nk;xx95i?Q z1$IDZ<*OHyq4bOy*o79#HmE_Gd1>W)plCYa+S8;tbGl`V5I{SO5sfz^DwM&m+bGJz z$4GTtozbKf3;yp-o>Zhf?sn@=EMqL^eWP7iY{ON+b)V}!ulcb0FMg^7bbw2?nbYoj zuk<#f_KRmXpAD)8rQt`JwrkZtCO4hU74ia@-O9m(9Db{%U$k$aC26GFp7+{q$n%Z# ze$y?&{Tnc~hMhCFL2eRCL~jPLmq9(0z$lb7t--l;S^&on0soUrOc!Jcl6<%8)kVn5rBM)&Ug|Z-P6y&WQ%w(CoI+Vl(X5o<5ija2< zz?O;BGJv==;aSmlO*JHq)MC+AvF_gwZ)M4sXR*{1>#vs<;Lm{HaGskb;groNm#uXsOWt=eT#XhlNBSA9(g6*B;9)f@{H%9*R$zw!EUW<% zFs2|62xX9;@jsI{?EFqbEy_&mkbAta=3FM;rPAHfRhjhx>C9N4Tjl8TNHXa{m!Ptu zyqp!}UgG5BrFoijqz}V)55}wt_$lOQ@p`XF+5zkD?buytg<+|nzuYTPrPh$T$dkEN zNEe*dI-U)+<1|@W1c{3K?Vxhg<_H_?#f68P$p;9B)>rdY6Orx~ad&6OS6jMhe^w7z z`BDgykfsl|aCWWQxAK=7$bBZ71uhWYj%kK;1NHc5FSL`%YwZu}em@F>Rl@}$m~x*d zq37-wlr(_M3e)wH3ZUK+JV@=}DrX}?=#JCJSCQ=SrAh>X4)somVVj;AY^ z0z695V($Jtnt&DqO9laBe~zr!QEoL&{c^0b{Lq=J4SpqaGy^A68X>IrE}%+E7sPle zx4o36s9?GS_YoyfX6eSsTXz5afv`gFAD(0@%MvPA4ZrdfG`$^=L@G$ifL2(LgAq^a ziSV|T^Ie;ABKAWv4XLs{T$YePh2XAtWkgg5F&0zGt-0o_+?VOYz5&|(M(UXFTT6e+ ze)rAW^Tp*i55cv*;;jRVul(sEMNEWazKKsYFuyK9!UK@AFG%{ zk`)Db7CSQ2g+xz@%YmeFTzp2rmB1w(#C@LU&P49Mlw&u-pv$Rwh3_`Yj2>7dp-p~| z`_@HHme}u0zo*`DXp}l6IpO+ObUfO9nV1#Xuzsj)Zn#w3q*r-1R_Kz&#*~wgMi&9Ym9^0|^Bunnx;9Uub{zq#;Q^@RtmBa4}S3nMw;(%+4N-1QLP| z>3XfJiuz-%_52TSyOXkUS?;#B1>((kUfrQm1>0U@cgPvO+`fZZdMSQ9O?Tx;$jrg(6h zN(ExK1V1kl3Y{kM1g?5M$g?0@!vRCxduf|0@I5ZFp*UCMn;APY6!$a*IKg;V&SP92 zxlkL&>9#ZeYfv3}$qX3=uR^P}a3(bbe55drSU5rVcCIY1nMO1kg+2t{25PQ3 z1^bP`?n%al>$cO|GM|DO1kZihKfiNN=6Fdv9$ipPtSqkI1+xNU-1nLxQW-RU^l;j+ zdO+S!O%B`dZns#)(jJ6FE(^1+@SxZDwx5L40`BZ7aFfU`q<3 zC#^Zgjz`yt_&ACs8MlduavtUkjGAAbCVdjtZ2B$Vs`Pd!CDG^0>4*~g$W)+x1khT< z*(V0`_RJQ9oaoZME{bMLI-ohznf&wjuM!bm9USe5H~mk5`qQ^Bn+A$5gPU-5Gpv4<0-T?hH;KkO096 z!5#MIy}a++-P)?H+O6H%KbEQ~X3jm*=huC@`*imWQ&yBFzy;%iKp+BH8K^1#GeWRJ$jSTtRe^k z-H}yRP?x;Dy*)a+ZkjqR9Xg);d2xAlvwe7_l)O#k^wSLWt9S8?39&8^zM1yr@bcKQsWK2?H zQ=4C4sJ5wv>sxuI_5k3+vD~wT_BU4vdYAj!*Fm3>jV?wRiEf zL~YoVp9;(CNod$8JEf|56&S`2M8qV9M8*k0VV-_L7B)@-;_{Ur>J#$Pjcx4Y)pfl6 z-&xo?6_-^hDCr{H-aEiO5N|^roV^!Xrf;W@FDDMrwZjh99>4n6qT^D^Dyqwp%bRjP zu5~V*jP7=qb{goxqu(ZEM&=mk!wpPqGII(PRCFDjybMfj9GtzHTH5uD;fTP{`j0Kq zu}KPYstA2k2Mv9M|9b}~4+UA3g|~sXF)^1>QD|R(2W_KYp<&U{31#+92t-hmi@OIR z)Y&TtnOz{MX=Cl=ZRO~__CEL|A~M?4%0Njo6Kfq?Epsbylm1m%=ZD4GbnUmkt+~(@#@B21HMp;kG$VM8bX=U%Kp=Tze zs8v$-A<{q2(#AP0BUew?3h_3ib)IAekTwicd1)vp^e(jw@B`*`2Se5^ zC=qDHc9n%mVz1*6f_U!N1-C8&5(<)qim7{k-MxSANmA8pd%sk7k269-MDn#-pExqfC283}xLJoFS~LJRTm)cHA(&X$wgBNk*-- zjR8}O6I1oG+7uVdk*wOol-V<=M=oMm@!Ys zE21v@L7#}6peP5F!efv<8}rlW+biw3px_YJcvp*sM;IWP@rNeX(U(s_kHH%GaF8oz z$E|47hsTFKegvQZ2%*`qlMyCJLL#(>;*<*n8ix?4RT*=00iADu@ce1d!iylDLLwNVwgF!q4LTvV{5bWK$T)epue|B|0DqLm-M^bv;C#uhM>k?5k54^^Gzdc&~O8 z?|+={w9IvGysgxe(>4wA4BjQLt{SF5)pV6A5rId68$suQI^|5DC2 z7t7WTZqHp9p6O%Y?2oTb6P0{Ma>8DSVAk>AwEGv)pnfTHt#%ITeM+&nv;AplY4C)q zd*@Wv+3*RoyrJ>G_>&IfEOzfl!_3Vvy!X=$(h>IRDewQ%59w`|Jk&Kkp6st02)68y zb!;DR+bw>D_b*dZ;g-!miIYMyJz00S@?JVM^HA%waQ?*&mAiFoHt|9|JFO(`IVLIL zBCSpM-aZ^&^HHlP;WF()5&h z*VDz7xPPg&GpCrdeW~PfV4Eu#ZFSOn}G+N9w@acHX*CMuk#S z`Mx6xBuQ~`6=Ut*J6-!rau6xXyP@*2{X0XR=SEkrZ|B~w^*+zYv5JW~AMs(^N-Ghy z=FMXFK6Es1G!x#hU#&rV-9usMWL&LZ9jlqG`X6_!-KO7$-yUKr#Hz4~DP42lUg+az zQ@-9mU+25+DMn@m#7=&M;hI3$VfMv0 zjMweTfmv&K{1IzAGcmMh)1b%CfSJBO_V*~y;>#4gZ3!aJB9j~AJiMkoS|J}^@CZ3! z6^LYKUQhOl*{q!w-agDE#!o@+U0UYSr`|mcfr~y%P$hZxfJYTw8Ga3hyan^XTCp3WF2BD6UzyFNZTGD|m@_~5p9*6Qw8wkvbL*Tl znEeKws##Dd91?88%@ToF`l?YTeydsWea1mj*loGD-BG7KQ#jg@eY9qEMKZLf5)ydK z<)mM~71_2blEa_uhDL@)JQR*0t1pCdncOM46Z(m8>V$tD^3f3a+O%UP2auyh@ z-X_S~(pWv8cMv$cDP?Wc;k>v55Z-Z%{=<7|gZ0~uQ|zXjF!HE%-3HIZ35m~UhTl$K zkgYWs1RgvbJZwb{kHyq+mHI@#6tckbINbtbol!jA~Pe72o_OquLci_?)zG} z`61dWn(R>~`yfP!iIZp9de-G!Lc`457>bqKC5^e=SnrB{ zG0ueqrLrx6%Ubr7ziaPKd^|mZeNs=zg@4Gba{ge$mJC%=w#%~ST|TUT@wHn-Jj{*1 zL&nyAIw@dW6hhbkkajy3Ia9XucBCZB_rSB9=@&}IDo zF_EVtDh|;YAfM`7!G6#o1ECR$D18g>8mznscn8;)FbGE{a@+Jv(}Wh^)#)WfkF6~1 z#@1}7NmVE=$xOLzXhAs_VaDE-O3iGMtIG`o+PGG8iNbb`jc{#P#!PYT>do?c@JDeq zL=cDB*ZiLZ7iQkqWe0TN*wwSs-mNqqk*ge^IniMZCLIWwW|-kKMA=31iszB0FUPX9 zgZ4XeVc)Ka!Yq~FaYO_Z5mcyX$8n@Kq+wx96J0w5CaE#pc&}DKz(}DC`si;4Z_(>g2PrKbUw2q;#S7gZOj3w|=DF$f@4tJ$Oy_11fn-C!Q2QL5&J?j$t2$T8@R6 ztt~(3`05-~TJ7lsOX^VhQOJm=UDhVK(wAB8fG#E*&e?+b?p7+$Mcs&i0fmR{$LRlyX%|07~C}(onTEvD}SNg(T9KJS2h*#*0FX-$d_Md#?>oq^;BDf16{7 z=t&%nyBCrEp5iF-cNc96x$aO2C2Z6!kZh~}`-GBSOD*oF&@E3>^t)cicQIt=K~0Jy z@KRJQ4a%A_jB}s^XlYh??=a2)mB_B2QiGVFb)wn>aNCq3dQhkCA@D#HC(nh-nD7U< zuf{X;$4+RSC3h<#0-4{KyI(W<3q<<-u@hLp`+ZKO1WHoA8F?n<-^^?LRFlGrg09TY z+KqCvTe$|-)fH+li|jL}$~2~0(-sGw8E4kpB+C~FFqQF?M%y762p97U6@(!=oZTJa6^?E0T zBji##p(>Ikm@M|H)zi52IsSes*(P9?Km=>`SB1DDv>M{@kUWD_imavPTObq$`?H<} zy~Ev|!w!K@<`|@`U@uG-VGdW~IvSuV;|Z zH(y$rCsm+zBnF|A>g^fs0uf|9Gk}CB<^7r!%f#d5@1w;jg*m%rk0fJ`ZB6x209(2s zz$0QA72yRzU1pVgkN72+Yv_YJx9WpSwXJJ%f3kiv{EUqbNZs?}HAMT4tz6NrRpq~h z6K3kx{(^i@qrVpg?wTyNIL@_z+X#ht2f#(USp0neYuq?+aeu-{d&kw5SMPWbV{qp#x%HAP@k_9jE7` z>oi)VsLcq<(R}M3YUWIF6g&IutqesJ92#9Xo7WNN$2z>T0BlOU@chz@Z1{X}-9KAt zy%i_4kf+edL{ZsPyz`DZVB*bPOV}t0rV2X9sia_Z`YHlbEMN%hb2gllM!yy&ZmFeP z6E+2Oey}3z$%Z4LD=QJfeYBfC=;`S!hzPbc%0%^j=zcJ*+B;MnW-MQ3Q@S_XUMRI- z;p#M*?sKak*GaMKH@C@Djn&J|UqoM7jtvDZl@>p-^ewW{S~X_3Nquy#724y_xZ3y> zy3!bkHtY)i%v|kPU$Hf3laxGBG{r%nK3%hOmf2NDRrFNa*nLM6mNEGt+A-|_Y?D-I z(r95*!kwAC!>Qo{pM~(16J&Pejx2?4U4A{FD*s+=~>v=X%k)-Io2IX4}g1{ zl@g~1QNarIAa0g(QQp#gx)Lnq-ZoT{d_75t(c6;>(u$I5w$gmy(TZ6DrIFyZ@Yg5@ zH$~S69BkVVE(5j?&J!vfSgMEUI_r(Q7tg7uEkDN&C5{nIrrOtY%Qy7_%?7un=$zKt^&bn(k?Ee#R@w%-ktuiv)mLVkR# zRLo4HN5`^J7Rq4UoiGi!8>0q$PpI)i?>@s>WNfG2Bp%QROM(>Ef@hjub__P?5@$mV%~-(C&Ldzpz(ueD1t`eRRH^0<|ff z#Sd=DLzC32k(Ze_wR?UoF(u)IV-;9N5y~xVP)F@bKrnN|M-~*(W9#}VC>8GNFAp+m zM5jJpJ(~N7g*>adD{}?9y_=#RF*JLzg*G0o`2nMz`{94qbUBGlX z?OAD|2ho5)IY9@t<@sew#V=BbhpNj<`Kd0xTRcg6k)AgAK1y>+MtFl&=L>}&s{uWC zpQNR<83_5kWo!J)JGhJ{Z=VmZao*Bxkxqh(m|*F*^VF~~J{FBS=1G~s%J zL_kp{DsGXq?KOc2w#<$Y+sYjdGi+MN-?8zTwt+omhT0BQCyw;eoJ0V6qt+gwJtnM! zc+eGZG9|?CWuG_5n%ru%sbTF%Ad3Y9c-jV{I{;Eyslgf|yByprHPInY3es_9XoSI1 z)7`}(%U6a4ihQYE9@dlqe1<99dU!$)SX?eemCFF zhR>f4;|Op0-0(P$tO55=l6g1wq_y8FnFh7VmaSn%7SreRKQ0W7k}_>os=BeM)$gM) zF#KclD2Fc{+a}`nc)Lkk_Mc7(7F}fBR%8fqKS83!MEuy5569SFV2{Zhc~RkVwFUFP zhl`44-5`tjXwv}Q@f!JWPm`upBIAdlkZsky+gw!>-Je2Fz(lb{l*7_jog=<|W6+7) zD=!~Aame?+A9}krF~Yd$fB-6#mk3AyrOB`Y1JWY_<>j#?AqF8LNTmXfVXOosqYPDh zx^xlHvG1-5Sr=KZ@_+2TaU^h+IWa(3v?%BoeyAT*{Aa*(W+DRRjPI9L5_iz8-Hb(x z4)qN(is z*}_C2qH$JO$is1lJ?EPquYt)7LdnB>7FHt><#;Lbikbe0yD?`1&OULCe78S%Tte5b zgx5#;?nU*W(pG#OJ{j~dAluah@X#MG6|VK|Y~XBi9PO0PkXWM+iat>C12nEa8rIW4 z@jPep7b1#ciy4Y)l_*x5@jKs_fPC(CyKH}m7HJevFtvJzdpeZkryB) zp;$7Yr+SvqeBwhy@R;#j^3Yp3{pl?uy0vIXA}afZ2k8O1efBd>Ofwv=zPlkvu~RF8+^{k5IO{?Bt)b4f{1g$C`uxBf3}9*_|p&7 zrPmD2*xJ!3?T{-_a z9j=+2lA`5G6y*tr=pVmGT|O>KA|OJ>&l zX^@+8Ogr=udncf(wIi6O5^K4=r)&(OXPKP=lk^kd?ux5FJA+tAy3h=y9b#*gtl zv8?MDUGSF3;4+AwHh1WD7Q$RD7}i%JFxGWR-LB!jHiS2uT5~?e8@_+jv+Xx+7m-p) zoGSA87*ZJ&*9Ps(zWL;lnu&Kvm7jO4`o7(j}^AlB0}Fjmk~TLDO`it-VNH9I-Kdt z-D>IO4?D4PzIFZ8U1M{!!{YOx`^S?Gse(087S@v6QuG@EC~4KBY`=+ypw}-cNIrX* zjoT3+KBDv>&P-HJ$tH6cD2(tc6tSV#_0f5ZXU!Ca|H^Kop;pC+@G@=d@yVvzYPu}R zaLp?eJIY;xVEV|fqtr4eW=n+xRnn7298=<){9WQG=sg#bX)rOII0Uz_HGE+Ir=b4v zFC1!mbls{fzvQYGi*!}o$GSqP+E33X`_ds!X=FoWvE;DU#T288ami%(q_6uAj~Q0* ze8F|P1m!&8KQwtArq|G{1)VP9OCDC*V7!s5L|i6rsk__^*MzPu94tt-^EamI*Luo& z28~wS6*5~}+ss;DUt3GA;n^S>9{4F==8Ld*dg9jnzPsM5-Fx%k%N(Oy4rVx$Cz|k{ zy+=al=rhTcUYF4`b(itV_p~VQ#~NK#i=_)p?AB4l5j~I63Uqtmv2k$JW+ybv^&-|CVsASnJ+eS{^7sq5#(i5+AiC~BwDFYbCI&++|zs@nS);LPGT*>c52en`P zK43-MgAg)N9lY_ z)NY~5+;KKdnKB9OQKv}uB@7UNltYsK z%wz|Nk1p?P?Y$Zw_q9X1$lXgx4tkF#{e1G#7 zeffB4)v1p9Zr%15Xsi16ko2il&@ z_}H|G$v%Ba7B%m1wl8i=Mc1lBQ9nQ$it@EzG>} z{TTu#O_3}mVCEO(c2f!~=Lu2_q)y_Ea_>~2dAt*(jGaeSkjunp!8*s5!+M2+KAje5 zA1HxttD)lBoW4!Qfb{G(bcNGi>TkGSg~C4+t3O0xbS~GkN36A7Lpxny58tq%?<2nW z3m!f*K&2_ki1k55e|>BvZxl@*CHjZtWHmC*l)!_JcL(?wPx(H=2}vD23(j(QECu6Z zDUNd>yU!a_m7CJ$I%}rCnMx46m@Hc9;2QF3c>>Piy@R57F^7^h=WN#b_~yp}W7ZSo z5P>*aUk)sZYx!dKTA}V}D2^yZs-lu%RAt{>UEK6=&-^y4v$ocY`|Oq9N3(BOm}@2qpc6K z4Ca6)REy;#CKWS^(mmL3XU=wMkU6wuW1q}WnR1gt{u}xxh$oGV3mKW%9Aa~ORuo>tt*sITlW4P`}ONQQ=F#&Gw zBsEX3t9^fb5!XLTA^~9g5ivFXFcTy8QRuzr!B3DAj{PbbK#1n|kf&trEfGY}{{6=~ z+Y*U~FVN-=v3B@G%odF3$8-)Q?w@)z(7F{oMf*{|!a1QFZmE_hpK ztS=#M0Y}W{)9}P+ za>t0%J%neozZWtK^~7(es+b4Q<)wcu$Bwd=;NgPDRf#r+9qnzuZQBF-q4ynY$hJ~Wp_;fkqUIG)LjTv8Oy zg}bF=?9gSgU=-MZlO1cAiW>1`h6utPWi#c6hyK=b>5K263hBq3`Z6u$R7TIa^$Omb ziIuQjOC!~ARb_TNSu)h6!a4FFe2fun`-%1;JK$5&T!u?|u4H<=GsxHP>X-~t^<1^j zP2gGd%zjkoz&KL2v8h##%^rOmb`KS;8rh$^(!<}a|+y7vtni!xjm)Yc|(boc;a)h zINAHK(j(QLz0rO!rSNA-!O<6$TH^*m^42=m8QZhWZAzNjoui_x)^<<->Y`1ys;8rS zT0+yRnG^Go^#!iF<>XnktDO$TZ{I8Mttx$o*P6PA_tb5%RDLeA)cE>7$+2B~Q!9|* zDjWzXJ#pT-yq0u9c1WnDwb8Fn`DS(;-=yy$pgJiYXVQt^yh8kCr1+|w+14dbg1JSm z`ELs!4*TqdQxWgYfOi3}SMu=MtjWP_gEYH>f#2|6ZEr?P-vmp@UCXz$njAc#>v=kI z<>Bf4uY2*dv`$H*n6qXbBGxea9!5E$UFkn-n`wG@`I)xyDz~UUSVP;?HcR+%+T~`I z()X^Evmp_NCnO#^ZK!+B3gwQRGtPf*`^R1f7t7avnki<&NLQxOvbvy>9HFx160sK4 zVUYf;eM&G3XF*qmv4UMXQ)}(k=H9}CUQW(cP{|LakjMM>9N=X=LZJy5Vz&82G7@{))Nw=x9oaTV><;Jo#IyN*rSF0FM!6?MM zCXQ_Q3f@T=CG;(6?vzpm^bli{QD}zV!;kWV9=g*-@Q4u2#m79qBsp+k!_|?4Ea9sk z-C$oC>>DPfwSB&<^O@FySdFq)Rv2dJ$u|hMeBkEsh#MVdt;jIYMm~`5(0uj!_3M)b zV|HDylbtVV1$@GdzE5nd8f2#U@vM@&#|t=X2);TSq3gOOdU#rMLwoQ~t7_hCEppqQ zwJ&KFXuJO&z^$RyboPVM^zA)_z42pd>Uh1o+#3>K>(ZRX8~>U%PQ(4X_q+c5R~@fY zWYLckeahd}bGAw5sY(b4QI)KYMroCnrlJ1$6dg1~0nL+cNOXGn9CB7%M7vNQ^vcg?W zNh<^-SAqpxzZmZ|4)=RszrpB-p{X3Xg}o$A09e-*EdR!A_?H^C7gRb3^54OBBysf+*xe|!V6Evi)tCe)+7*esoxEBHeW-;{gtx$-Gn{QZ(cAW9fMI`G5$yG z3s9y10#N-<9wHl38A%ZBfKSncA~MyL6vlSd7-5^?eA_%Z7& zS}@L}D@+}plE6%F70~ys3fwWzt59>&K+FRWNny8l#B(VR7E=bkS9KgW0|kS@p2ttxZZ=>hKr3$7LFKHf!wnNO;lb3J zvD@ajjo^0|8Z@MvG-yp;-InCN(Y`vn4k~QgD!iwN4?&q_J3cg8uWNuP6)u~JET!b7 z*M6M^C+I9cB_=q`yRL;!n8W59mNn=^4y1!&oY_FmqBfcdex)BLLZZvUh23bA?Z7=W z=|R5@AKSvmPXH)fYbl*5c=?_Gy4jb0uui)IFsJ_O~ya8O(n5M{*6XR&@4elUc*vEG9 zD&)T7_T(}9#oOIxn_D~dD9K;pVkF7t>M!Cyj-Io)DPRDw3# zFYxlJN(^ev^VYgNR>r8%uK-2XM|0>!wo3yv^enIj1@NFSTxy`m2!CQLL*IQuo z7~NWnfn0VVFko&IasoRRXcy+K=b|0rF7)GG#`R>d*W7BK_UEq6JH`vh6(=0G>n zVV2}w^U%lP=vV2M3DXm=Lsnxz)dgxUA#77jP|Q0w#vf#@f=5bjQ0GCu9!`mpF777h z<1dZc>RQKFu2PvmuFF~l>~=a6s2kkd+2GCj%=BsS4-U>+B|C`{*$IYSd%OwL* z2#E;S4;kLhLfTQ8cv?=HhBeXcs2vL7&ro2=SitcfzCrbSkrKgvvooaU2OpxfcR<;S zYhBitRXn7m7KBbW-ftjp;i7%C(M|NQ4w`hYOIvZskKS0{x@XQ0u`gUtNF}E)G?$@$ zXazxl(DR_v19_8&8Cxzlr_Luc@8Dlzazns`FbGW+GaXR&^rR}P$?wp|Z^VDAK7)t- zGs-$7#%G2eedfkBB-0FMzHkK-+Isxtw6UMD9kefFO{xEKks-r?zUX3O3_G@L8QDrk z?lNS&V{$@d>$r3BmfAPj&x^->%?HqnU0I^7f(u{eoHp;#j(U-jvVggMw}3-uOrz(^ z2m3!L3_3SM&02=41-Yzr6w<332KDtSPrC+lvKSXc46|90rXT?_{ZU`fN zbv-JH9ixPG>2E+n6`0@p=0;o6rTz4LX>`8XD_&B9{v{H@`j|iM-nyI4S*~li6p&o9 zs-Gl=drH+R(lc{sG*AykS#&*h$~#U&vH$#t9+J;`?uCeJEGe-jh{UyUFU3ctJp^K_ zD5uM{g^F~bP$DtGI=t6cQm}uD%A%sUUZ)5?8M&Wy^xF{Bj&XSy4D59+&jL}&O|nD$8Uc60A%TL=z$)DQmPb@l|BZEIrJh#m_k zMmZ=al3Oh`XJoly?5zyRcCDnu%4i4~M;a=wz{ZALMt3am-?=vCcUU~~YJswyPMh-2 zF9|tM$f9~Vm`bc`ig~Ppnlw7T0(q1+ep5~$@?$Z4!-wo*iEVg$!$pb(WOk3JH93L& zK>{n1sf?}Dn(z2pa$?B4tBfk-TQQKYjZ#E2OqT^?8|p&Hxn6x}6GT~CD)HbC;Qnuh z;*u(PpIaHB)pZ8BeT%XjzVCRq=aza1>WtD;rc#9UfY28&`FgFa(GZ<)Cqjh>LJk?% z{Y0>!dW9AOv;sbm5>EZ;7^4B%JK?{b_vPLb0*ZHhy?fGYmKn)m!%kE&Q`AK!kZ$=k z{u+Dj%qG_9xz?r^!ma#=cITyvRn!S59#c05of_McmifOtE54t7zCdaZFL1kTE_``P zNVd#4l1&sPTZ^Ly3$;`Q4&%_NFjX0R@hYeHTx94QxiL!8Od$G===^?(7YCPqVaHKU z%5$^~+@NB&zIu_y=BAR>NiId#QNxi zLf1l#Tgo+TRcDm`9f$=~*`d4yF0b|uNShonP<&wZl1>;NqgBEkpcZ3e&Vtk50~Wfr z@m*_Y85=_y3#j2adz+jDp}nTNrT&|+C!wNrQ9=S`F6+GqOBjHTLI5Ovet5g4EqRET zKJQ5Lfx<9Rd~}75k8~f18vUtF@>qHdVB-61<;wBu7l;RhrV70-r0aZWkwXMjtf0&= z*D=6AVhdt; z<3g~#T6?)$c_VYyBm7i~3hbQMKxZerAwO;U3SQ1_Q?L8)84{KeI#x^-j!$_o4*>lEQCp&POkTVGGi1*v2y*v%6FgaJ;j!pVMZFL>Bob=Y z969wofx{#am4UO!kIRfZch08Bwc<9EIppn${MO>n=$(WAsZ;Kt0>(5 zT5_zB!bfN}nZRWD@9u^>zB@*`1q4hSTrK$q-A259-KHIwbusNh{s=-goaX3n`@x+! zXzY#652KE5sAAzJcZqdv=hm)`cbf^%mV-QbO838;;NU$UJ>TAI;}X7UycM|VxUD)9 z5#c*adZaL>w)EW>Va@mMbxg{}mAs45dIu-}D2PoLkk9@dTYomqn+LbOw-Y;Jl`Wou zS%}@!;JfP*0+Svwv>PiRQ9L@Z^2<88F<;mEQxFwnUAR0b9HkX_6Xj$C0_o;x>EBT% zY9oO_F+sWi|M&k-;BchXNegGB$YeNVyi ziIk<+&gMtIOarnuHKUQG{ROi9;@37(5$&UFy^j?eU@nZxz0`8yh5zeLN`W`I2SX2f{is2aw0^+2Cpk)i!YA|xLov$E_X4Dxa6S=@ zJrh&PUBwRo{rg-c@W$+5h&JZ(C1?y31q@k+C+5W5h91&V)1GR8axlQ%jG%7xbFop? zXiN76EsTJB@P_~d(nVO;W+VQBzidIG*sg#yl;NJT?i;nxks6s&w$>`1OD&fEduVs_b%TyGTRGj0nvs_We)y0RvsayNsFx`u{T~ z01o;S#7xBf>q?jWKhiL!3ejuvDq4F77k%-EQs8%s;9ez=A7=zUWZ=-XuMX=989;*l z&7ZwNh=%Viy@!Kj0L7~6)Q6h;+D_co`t-WS%_VaQf6Lsxv2h&Lli7JoCt`GQxw_N~)6FE)^P7xwI>`03nX2 z|3IjKw);IlQyH!w_NL#y{RO$c-a1bwKhnM=wai0?MHM2D*fK}rl|w1cpRs3W@Xas; z{>l6gJDfsMO+7OjFJ^y5m9_9R7Pk!9x08mi^_-A>wG5%6mvoVr{mI|qa=Zn*kl+Y} ze}euusI%&s?p^&9Mw4pzJ1OqYEilP28A5()`}Z;HlT2pkXQB5L?)||sChmq{<-ardePf|L9heR0k7!a^ngzI7BxX_%pk!RI+#p)!2KZi5=H_4c!5ZTY zjE7<^SJTN0R45Emz#)?B24Ll1r<|v(`Fud#?&acf+2HG!S+!@U=3rrU8a}%^t(jW! zqp@MHyo?;Hk+-AP1#dY0^Sgicnu^M87|>6O{r3II)^YHTblxlhzn#P2+8vL4-9A}U z=Krx#0j%Nalb&PdQm#)YnNb4sJeA5GLlx;yrCr>%2S$2&Mt(&J%v3JUstn(AcU;1u z#IRfX=;CtIRg{0WAAR z2%*s0GVi&C9etoW>c19%OZD3x?ky?ef6p%!1=<|*?{kcQ>o}j25fOkcfIFt@|H}<| z4~H)tFy8CWH?>tOPS_kAM@403(u4&5J%N98#dWID5`U^i<-+-k+oRevvx%%LY22ep(QXGOh*-n0%|v!iEg z-2aK<2I8+@#z-$~p`X=Spt@=mJVgf%A} zUi~noChd=?{-XtcFm7y)@-BT$OR8#ex4J$YHJ7NpLa|3CWLGW$I*ad*u<%Y|`5n}b zo+~--?J(KXUs}>U03!*Wg3Y#GpY_-SDwG)bgm)^AP4xQzezATv9c-FebYV%z0Pf`7 z=LE!t#$6VRb>J*3KkJysi zh7lg~K5ax%gI92Y>AmOmtv4V3cRlM|1nVEX0>4er!b@tU6o=4}wgI*^5TFk)wCBVx z?gvrmO#OGGPBy>!-;@nsyX>G(OEgL?XP$gHZg2#DHmdjkDE1tAc2<`{)?ThLnP%6~ z{Sr-HA5Kl(F`kBgf-YVONxyt9kJ$`Z=euZTu}4Hvqj&I0?%;(tuxQ#x%#iKZFd2Hb zx9Uw45R@NbEFZV)Gv0<@>zO)f*pq}a3Adw*BT`;fH0A|e>?ai;+jD*`b0|`@sg`q{AwM>Bani-YSfI~oY~5v+j|O>*q@wFHNEqn|bF8|{)1>@Gz*b7V$gycE|7{$@8* z+@H?s^1OtA`Jip60%Fl#nkUC3h+tHXEOEtTqW%wQX*#g?Si*DlTpid=1zVND?kr!m zFe6x=rr>GgCJ>KUE~TkOy9;X2J+j~UP-vmUs%yhBT{=r`MG)f{xAN7sfB+LT{FiIM zTq0-NgRK%DqJFZk6>h^5;gP@ik-rP#7?Dus_24sx7AUDE6?*)o#&{k7Hhg)-r;_zR zcjX56f4Yo9s^~FYk%dA{C!Nx7IxnRq$X-O5M@#+WyjX*`dR}^VYHl%D<}ISJp2X$l znl{*2;oW7+{m;h~5=YNEQAgRd>&rIo$(3u7G47gE!`K!?-KnEY_%uwODS4LCgfl%) zQ*(pV>z?%{?~=sR`l|yMJO`m&Mz*H^F%K0wRk$9P)PLt4Jd)owEty$z*&C?W=GV>a z-tHc}*QQ=E!lKr|U)#NJZpOjswIi+9@W`d@Mq(uR3CBA6fW51G@Xl0Q{ zy-G(D)$u^2LUA@G_+tAb*Rd1whfTeqrLFopHBY7majypo!Ozsmiy`{og$Ou+?=rVu z^ggM!7)8*Z*`ASY-I1uWTPpqf?Xq{9GM}8Y_*+S-!JVPi{mt*1p1RseV~#!?4f99uK$Te#Wx5>2tTkMv!#>sgMm>@~G{)on>i^ zpQ8V1l3gg~C+#t2z>y6#!~vr)0{)M_dsCsTd9mT!8ZOA7J#)xu_K$PX-n#|=_{M;0 z+HeZ(;qN;$y?HBKPo*ZdePkc7|KCoJc%fz&*pH2dgvTNWx%`*hE%^N?jeY;)p&t=? zw)(lv*5+&ScckfQ&aMIQ!B2#f*GtJ}aTKLh9Sid1_C|e%=@!f%&D2+Zun1Efg$g2KZafBAZet_jJx9#K> zM7*H8beT|(0hBI9eQ3_E6EXGmGXwh%bM~W99&2sRuaggLSvzWFDyRu!rKFv|#3%t7 z+^~YFEG?V&o!RIkPK}tR8t%fEBb(e)vIb7MHpO*?gA3gEoU@Go$I99eCbQjO=HC0Y zsWb3CS(7f-srRZI`;P20xmHch6LOL;7E5-%Lq?%vzYdb{o@18k7X-7fv(6Cn7MYxR z_1EFdGZ9p<-zEKaa(eEYj<|!6j72hGCi};sJ#OITQhVfWPkm{$U~1>qRKo?gV53g0 zz5)f?=l|do`T$?`WwVUnAaUc9!2d>I<}P_9pAfHe@aroiJ5n;psI(-WHTkgy%TQCF zh4XSPlB%L(>PIAZ=F69U^1e30!z6SgN`#y`9WOX4lp(Gq2da}KA#eTYs;Qz?#cxU+mmy-S&sbANU{{CgLZs7%cmaSml56mdaAUL+!8T z_F+VI)ur_B>N7h)$o*}&W|Hc~$`zX^V~$Jo!=MxKk4#DiHAwlNS%NA)6!NM{6uq_- zDMY0E`&B;jb*R~J>p0BtH+#8`UHaF89eqOKFf~KIoTm^VM-&#~UKd5}V|Mphc_(ej zn4@)n=f}9Ki#ut1ipr0~%xOrQd6`hh0EH~Ol5>ghc;q5&18ug-jYd!2xPaTWYD&d- z8ELD?;Sxu`%b~ff-?a&nqn8HSS0jziNU6UEW#g@+S_}tKDcB%cya0H~fJY~nN}hA5 zFrR9i6)9&K9n4+7@L`DcVsh&#9Khp)<>vwXZ@adly zh!gfmr~V!}Z)0?^w8wkz1s@I<(Yb&`crhwZb|OWEI@Dm49&Ge$Qm4vMtzVZlBc0`H z@~a9goZo+JYp$k-gZmrGTFMRbV?TQeySvEzO}!Wew~e|2PAb358Ll|a$NiAHL%zSS`WYvmBkB9=`2TOY#P)sHu09N-3Wm3NR5N@!*+lrG@ z4?^|(cL3K~C=h=^hW5aHhHPnCr&5ggepgD9gfiV;M~g$6qX*bN$=uIb1!9|PV$xzg z-}^B^=+%y;9}$*YRcDWU_?=S@v)8F{FcPT@pf3N$UIH-Q{#kWQlJj_`5{=*$ zk3Yc#Nc<7{aWxzWsu(NNA+JsaT+vroOM>7=W$(j{N4M?^VWjZ4+^F-sF;0KTFJ_FO zJAYQnjR+Q@YJ^=lyrO=$Oxb7a6$cCI5H zR(}pAz;(0TWWu6I;HL~Ke=S4=ySb!pfLs2G)?>V$yEI=YA>9bzMzJG`1rIy_7vA18 zDyn7)8wCT1I)s@_&7|eV&({N3NHJ#dNs-W zyKk4_-C!sOd`^D$L?v)kIkQWDD&{);uwX%wD5FzKJ>ETH(Iup9E2$>Q1?`$J zp&f%9D;g~ld7@gJ{mpJjO>FD$1WW-Bh>b4TD$WTMIJ!KYo||m=h@#+8hG@6E`eB0- zsE2q&Tz`rpL|aF8&?AcWQBi!py$13bdC^~KT}~qk8paGen^S7^>eeik!4K4b!QAz( zDjCS4tJ-d}+udzneO8R2f(~@Q@%nwCb0NUcNRz>^6K;9QmT6`Am=D%15@0x(Zvyuh|?H+%yyD$mBC3^_wM)fdRbtZIp4$*rX z26MrmC0K@XJ)3!6F#FUmvS3_WN1A)YgFi`G#3)jVE{F?I!9}MQCkG^|y=s_|_xFoF z+|fnRuJF)BV%&<_m<{|*xJD|aTeMM2gN%&-=qMIyWks}MBnNY-Me0j)hQyI+XrQVJ z%yf+~X!F51eW+Vd)}u_QRlX(HXgt%!f&d~cWRhvn$8~!i56_Al#VO8!NSH+XL*qUl z7=NuyZ{`S6fUD#Vp4P2)i3r0D9y&8Fm33=vtJabitcK?G_R|G&1OJj#)b(JiWy6z3 z<7bb*$M3Sa%f?HbHzs#f1>1%W^C?d_bQ2{iZ;slRR!qItzWE%;tWNBXyAJQzmKgg^ zihP^%DOa6!2Kn-dJ*7U z-n|+l;DK)`S8Yl3%{e)}CD{jwvK7o)OC2s^HWMLLpSMNF_sjvdVRlapSE zjTi#*kYV-B_H<52X+L2CUk8v01Wt?ea}^JWT!|W^FIA!P3}l>;q2fWjhX%4?H!fbI z1aj8_7r(MtX!6H5nBWgu;G26ab{w-p*3AdM&T#wxXqB+j)8eGaZ_4CWf{uqYe74|I z2g5cL$BBrUc#mZ~j#kg=t?&6n51~p~BDeqi@Cz(kEDh|N4GWz-I~x=_oXXZ!W^YdoK5y^IV+q0`AwjaZ5uxVQN$VTJ*#+Ptvur}EjR{1E>iv1iMIokEg!`MP zMkn1u{`XThYt5%(aEV*r*DHt;rv?`9A22QUZA|(6u%YM4p%!XgS=4|sZvDZV@!)zo zlkFC1vfVyU`xYSOU{V12O-h1e#36r<#3IU|RG7nO5lEoe#!{acbas{ii$tCfQ#h-23|`A*aj(ypBPu z+M@qE2|^^Kw4|=CZop&rev#_XeGr?^_Nwq=-!;_af~j_eUki)O*6a_F^z_<3rn-;3 zWbO=6`_=o=@(5#7If`0MR}32VY%>Ue-Vk?6@xnNWHn)Xi6K`5Nn{LO?DhQ$q1S$IjS>@&Bgb>6+EvXmW#`%96VWDYx@ z8*6;d(e;5PaRG5)gnMiO0a;GdOL73Ozoy@#_YWMK(M13#R0lXqQ=BDic zDAb21+Rtv8 z|Kd$GH8jGbPD)Hnly-BEsQ9wO&tHVx87^P?94!*xqIfttF1hRaG9@K<$6UoxDRg@S zjUPX{bSmjix!p>;wXf|=^K9Jg0V9|_e+yz_DfHE^P3wD7-Av^MBHDoz!ldS5K&2!@)y?j1u7T_5#3pATKEQ~8bL%Sg{sHR+Qp7Q68>RFUMenW&q@JRz{#`}@3#;IECzDB!=#}mBlFHy{4Ja) z8!AE03jL5snpf2n(wrb9n}&mB5g_YrRegk=E`oWV{G|D$ z8w~*Yg*YinorTl0W1pXHN8cL_kqG0L#t-R@%ZM@7^)`sM%l#f9_0lOJ{Grv$ZHST? zYLhwBXfQtlBWXMrYMm~a65s{{U<@UVT-mNjT11qwIH$(YN;V^+T9ua7mK9(_QqcI1 zB6AjdBM+EyiR<1$U|J)^{5>}fK9qigJ|S}_i|&NH6{cRc&`Ov`kc9P&-8f|B4XM48 z|EgC268H&`u3Z>geW$NPA%AiBv8rQwd`~=optSJ=6P`xTh-EjyWYt3B+fK@VHkR)< z9imeBIlOu}PMauuW6 zPWw6UXcM@`d3fN5y1S}nPvSNTIi18#b!M=&&3#ZEk!LgY%0)j~tbg9Q{O+jS2PH*H zp*U8=yxF{s&O3b(!G?*(w@W#J`juY(c7d8+4lp^z8)SAV$9C(pq{@f(o~+Z`PMRPt z3F_F9WJ9A+H~0oCybLm1evjB$vg_7b%#k*a@XTmwG4zw&*&cvbinw;M2YQ3Su+P9z zWoK)`f0*U^;BX{Rk}9HVmgP73jbtM=XCx}pE4t69#q(>czrH-)V$zyZGw`X47uvE% zIqP$L6SJ3ycUe3Rw$fJsYHF{>K2Dv?$vk7HD5|Cnq82m`OU+7$k{#pHB9^|*oZd>2 zPF$Z)z1t+CK@jE+a64&aL#2*hauMg!2^g*BrAdY&M1pVtbl~M`l%qV9lhkM7(>YapA+OS4p zUu6Z5FHH>e2^G$i1q%y2ijCP7_to?y4?MOM4^_aCa!Oqb8BCA-8fNb;sJ<6xt<(PO zQ7Vrrh*2C72z3Iz8o32*>T{&X>d+l_Q9`hY_HEa(RYPa49TAwd;0JUP0OF71p11~H z<%ZuJ7;9a?r=}uP-3hg_hgiEy+1mn=4*C`pV16?2yp{mx;&CFyQuqVBe8zC>J2pl} zcq14Jq-V`zZySfhCiE#pY4}hTpHUSSiuoCiO=NM4E*wbG3a2n2*-}kuU&p`mg%ZUo z9-~?gBa1M|(9U5=NNHP4^LKu$QIvDAm1qJptuAQj5nPBV$9>0)ATO7cgpj38R|SUS z0wU*!Ln$70QTJp^*%xhr7h@MZ5$QyUDAv9Ydfdms0o>yTLLXc}i{^d1?FwnBRITPaF@kD4X=x;A1l!ww1 zcD!AHBD}?5GC*}(%|HZwFi|y?(So)WAUz;E1RQ@aHuug%wzppNWXE^-VL+{$o4MC@jUW{V#T^;_$pIlwQ#i*UENbpb@Zu05fs?vi+EVZ*Dxlku24fA{&sAG4?YCKR`hE# zD(sE!@J_-94l|$WS%fXVd!z2^KLRp8xirB5?l34HR3aT4mzqKPOUUH*oTJvBv%ann zRouK4MFsvJz9;r^WE~+4g5E_IQmv&RWAm@{VAv3tT!WiR94}bfUa<9A)f=8{DER%Y z{b$Cjjh3DTuue1VC(QzaM&lYF{ABXfEv2M`g5y#kOHBHl1M#pY=#KYca_#4nPMWwB zeq429KNr=lu&14ZVkq|DV$L{0FnLUm^`a}09%xjo$h5wu{+sa-$!Jlil2Ieq*-X`w zXDB0m6O%0W_)(0I$+O2NZ}myL{VMU}7h7OHE)m|!N!8$bd#d<&YVrwx*ATaK%1~9< zEN-XyauBT{SA@%6(gDOdD%2FhXH6Z4z)N^42!Mv4!tXO~Cmqx>WGatW&FusEV?cAt zobb;rVL^6Nh+zFNRr%RAg-)kW2csJa;Pm#^9yMfoh*kWne$6=Po3gOvP^AtFhs~*h z5G%4v6Z&xrBGSm_WHg zYAZf1%98>D3)Ojv>7oKe{O-aIe=LEO(D5wdN+J5yEpt(X4OtN@9;A;tjXK}H%U;H3y0MuPfoWrW=A?Qwmo*NO zIu4gEdp=h&CJD#bUq_$-lq>?9F-#5QWd&9X;Svtkd!wJSq!mSTC_84(njHABM`J)} zC{O@i=+fW_+m~7t_Xxsp&D2%%-B9wF#H_eg_=^|e%Au=Zs!RUGrZe^Ki92?k49MgM zpvsmbhi`DT(#{Q|^y@}=y@FIT=mt)KOeav{_D_;Ok8JjeB!>i?L8{uiLx(#)m4Dw&Z+})`$Ab%SiE6U|6{bcQ>I^l2acpyqzYJm zQ6Z+Jl=CPhXBaKmSk9@Tu&7nM(J{)w8LL&pWEoiDZuH|iDva^(Tnm`hH}BO>81ciO z58uBJ%2%W{sI<04_4;LZ@WHi^4d zlDQn%peBi2XHRg}oL9QS=d;{Cy}E|F)o1@w5j2j40vv2Vt>7#ljdelPi`}U#DoaLk z?iAJGKMw@C_?+Gb0Lm+^CDjXm5rTmiJTaIdy`~>23G@*;Aj@~8!i@07|Y1%g^=AN}m?ROpWr2z8w4f197oQz+iZmvbyV3-P} zU*~pNzM-^Rj_h}b-+soeqU8?yC$3(849@H#Dy6-Z8ObfP$%J{)c*{_+_eLmz>QK#R z10p2IvCB2|t_@-Eh&o!JSD@3ZU)upSFI*FtPV2=O&U7w2lG-mR?1iM;zS?IWwrSrxSGKu>? z@qcBmB=x?(g_4(Ig(O^NL|N0wHE~CsSDO6HfLqv@dPPi+JBg90j80+4%HeVYd)JGI zit*|xOd{ldOc3Cb#U?5m*=Y_+o(1-aKW$jj925=JJca;3zTZBy{anDn5w+||+7ePr!^Sg9dy9>J4zZA~n?UI6CH8}d?e6MqzTc#Qwof#vnX>-xzWyTJ zFqo?KlU^$wCzMg9V*ksv7jJP8w9+KNu|Nv=^tL@lLzG-Z>H$uuxxX*FIG`3qLf-=F zroSAl0?6wCX`%D`(lfr5tka%zY0=o=LEPR$;+Ud$P^aww{n>VOkNwO?UXFhHGIp_) zB&B?H3X!|vki$Nz0IJsc(3@*9bh%YwA$}`O3jI+zX>SrGQD3J>hb_~HUJmdx1!|LZ z)9{=)i0f5IzobhT@HGK;Rka8x(dI7>jve;14HM~i3|G$t^1*8ZXG61#Q)Jvvz+0QY z2XO&#chEyp^>jpOYR7w#Ar!$!Hs{BT85jV`7QM0Hv&^h{FA^Ypaq}VHQVj{N7fPKU z0ET)iD2w>_1=1Re=ljsTTzT?VKw=f_Y4@aQ(qMyhCc;JP({Jt$!>dyCa_DbGQr?-|Srn z=3Z0F1r|}boF80?D%_0WcwtKGg>6dx!7Q_U!kW)=ZcO75=Zwdgp)+u<{O2ThIgfsb zMbDY%K>}Pw=wQZ;;Kz_(OyjI+-5Y>$PVS%J(S-t#ze3yYMx1XSYKn+z>>tc9bbIaP zTAZ_#0Fu7)XWjoQB}@s_j2x0Vjy^~Jd2aLk=;_I*0RRR9=6B&70LRfw1zC_@jI`ZU zhC!bv0q*|eyxAAdYIPobe)KSYg@q0XnEoepb=mu8u!Wje(>@bp3qKFjE#$lqNLBcl z*$2G<`1t<~rAcK+Xo(1-XaHgV5=x;Q?1>RNTL)g7brvk&hznrA|7Y@6o&dJT!pAfx z57Q~+Eg6%aX`o@{6WjYl5#;L&#i@o}Sqeep_D?AD(o&XK=+J)Kq15}^`j{Uv zro;v!Ek3#lfW7~(bTR^=(C42Udw&56Z#Y=+R!zKRwc&^nDZh3DP?|d7;W!<_8c3rMr)B_L>;ruzCy4K!oXFbuBOzr-G*Gcp7=;7E=A*R+>7>CA24VrI^+tIzGXnzT?Soj2QMl!eJ`^+^Khq#&!W z((*E>)%Ept67km1DS8s5)_r-@ovf_vNaP*4gak=%Uq=z*XtA?x&Bxb4xCmO`xsyGG zzLV=xR@N5D-d<+1nX+!AnhR=_1e`ih?)YE-INC#attT623;V#DRm(5a3M-(Z9Y zR6@gkEwE1TfGESqTmUH7P#tppYkB<-0A6?Ah0cvh_3H9@yLcO%A>aj6xzz%x*h?6% z)pM)!=vM@WqND2tJAIEa4e#fecXmyRX#JoOKBqs4r^yC3ys6(bNWHmij=@s%kue$$ z>gmb8z6Vc~Jrg+_Trp55Z)1TQcw^Ftr|(@fcW;OU7%DQaAtXtZbdlkVQ3;X{bOzB0 z8i&em{wNwCFSJ+L#|Y%1m5(Mjsy95@XSjhfR{-+J@R2pwYMR!=8Vzed$1Lw^~>K!{^EK0M{R@rk)Mn z+*kTLjEHIrFgyff2jsPMNdisySG4c@2UjU_5wy}Qm+&x@O=gZ#?ZUbMJSvj?aclH`nTmT{^}8wsHgmRy@`=`ImplGc{A%@2 zH`<6a?hrH#cmLd$5Pkg{(8mQ(d{*Itw!Fc!XvWWL^-GcUukF!BVMM2`bb_pMhDp&Y zqnYXf$>5%HK55Y1ovjGA(sU3`(C4GDSCawIN0;5cBl|PtvvdAyCPnr8;vY5_*(9HR zP5FV}79z|(483gR3gkVWClA}c_cT+6nQz&Aj3jj!DK9o8=0H69C2f*Z+M{lk$oqypIPT2|3;z&~a#+ zi(SGo;T^h(7!QyEY_f7P{2#d0{#bIIbi_BW2{FRvGC#L>vR|O~rUuP_r1$Tg;=nxR z$E3c=0d;m^VDh3$FUPFc*(9m%+mXo)ydp<@M3g70LVn414RtbuG@Mt%)7S>4xoMEO zK0?=17{cwAER1<5`2baBV0cnk0X6Ho{>hy4lfBosX$PFh6HQP<^Jl$SMDRZKtWA}% zO+8OVo=D?dUcu6<;mrK#S(_ky-Ca2%k=)gnWeW~hT_}NKKJ@9wRGY+Z(Mi_C>AZybNOs;?vWt>vC9zmIs3j<5zu;+4cn zkQ~48IrW=}ToSH%bw|6BL_lxYl(gottqiR4XNG_?C@gOFohpFhjQGyE_O1E(@b9CU z*;kenBLd3l2b9F}L)i~qq|D0MLq*B1j3-3~#V`&MrMpiIBMYDFA50V;#RoUP&-T%z zAJhTm1(z~Ycta5BK6GX3PCjwyxWZPW1ioddx0_E*RMjz_6yBfvXoault&sxd+K8|K zYSKEWp0L0xnt1~}E%(PY*t$zwOq}NQL6qzgx=uiOzHWlWz0qEYx9s-iPaN+k^ngFj z+ejMITrGvhd+YcT&Mb61bm;!EB3y*9TD+E_xgM?soc8#kE+#W0LK&TxxeT2JD(Ni- zZ3-d?9;xGi4VfTf(4xWep@sGGq2DUOS7K`vUdP7@d~hGYsu9|%s+BVjEf?^vECD1^ z6Kwt?HT(D`{cpu{?%{#iOYRVU`&jXCJ(ZKrhW*z^=U=ogbM_sliT7ahsI9~TOL!hO z9RMIqyI8sKhinGU%2QCIR4qFZbfj{HyBL3D^^`;1EO$NR)F{aoK?GS=FH!glg8 zD2Zc*=h@O2uiTM|ITpW$`>jT*Q6R8Bik%E7tt1G!z#=AasC5HC9uVChj^by8I^l97 zANw4;qd85S9NWBE3Cj~~ZuZj|GH^~RuNH4B(O!p(0=ET(&p4jger;ScL>;b$=#@)r z$lv>yX4S%vuldIPgO+ngB+R#ArHNmuO9_Pa&&~j-4y)t;3vdm9vcWe5;&=L|T&q#F z#j2@uVg)Um=hu^b4*u1Nq6OCS=jiG&v+Cn~aJ}%Uav7{I{Fq_%VZ_hszC%9tHT5fC zHb7k(3@XXg+*zwr*=!DMAm_sP1#=Cr`K0bdx_V+=nFFvJk_QN+OqspY74VD@*U|oZ zI{v&}ZI%mSVHMQ$WzZ#*OUiQZ;NDi$>a&r6n?+T)|DB;_oAvP9sXgP!lx~6eZ*PZ# z0(fF_KT5jtCH?WgsS_)@;4Cuyx(W01!H<(}4np1y?YxrN-_{IP;t3P$IhI?Dm;)5&U(+|S7WfC$alqd8lGhgW+zs^-|wdje-c18TQX*rUD6;4(c{{!R*yIIrJS(5^?xt`dGv}@0O!&B8u z6r_JybcNi524(deu;mULKpwMMX;C2xQ`Q~5LSh*5(6^cXh>n&g_okm14-fHwW@E7> z_&$p$y&c}2lwz9&QK`HrH9zSwd)&4x(WvguW7w-PR|%v|q|4KdUV(-N(*FUu&IemX z(_Qaphj-P;B+ROr&P&WUOYy*4=A zD8lVpbfB)GS@68_t$g)z%QCara<7?UBFV5Ts||p5sX3h`>U|CY8pr&oFL8WESx;Pol=X735F3A@pL+xvv9`41QlhH35U? z0MLKB5cNQ4!3)2yOX`Il+od==^{%zkw>UoPfJ|PY#$;ij*eXPJlaa{ez45P2@P-#T zsj*jk2Z?&Z!=Nl>9nlE@AZivJ++m{xbL@+TktU&a!lJ}VU^<7pJ>TosAxSZO27hM&nk@NjrStQNxqujtS|KyhLB zxIm_x@WEtwt%RvZ2?(2#I0r**knRKPifbtS3iR!5wJC(KOr>I`8zmfFEs*WZRXhBd zo+1}@1RpdA)g`%FDy;B(G5k_HpS$(_9}3-CsmfD*#6c%taPT!OKrQWwO2dzgeF57| zOaH`yB6asWfY+kt_+->(Fix*cW;9O~RmL!CIg}+O6CEQX?~<}*q>P;4b^cS)EHj*? zP?xTnv0I??0rKxdf;6yEga5N{4Rut_g6seajvdnBEQ?O2NNAHq9?|5*l_j zEU@eLPAd-?BvSrKu|luJhzE{m&O za;ei}^)c{sq6sqQly%=;(&(yvn*}w&BOw$NEz9+<&GxzG+aTpW@6Xj&0tE2qer#dp z6*S?ub?_!{@!#iu|%;vg1Lm8&31=^3|Geo#UdZ9tq@D%>f z&)Ui&?kB)6&D{B6Keu~Jr=w|i`pniA@Q+qo{2`6x$FPS!_L2x6et2FIt4^U4`m2fo z6J<>cCzg_8;tfW5*LE+?z*ZmTsVxp9X{x|ALAnZ0EY+J~4&@Rg;jQq757T4eRLf8-31^^; zw!Nu+{hOm{r`gPwhNjb#4`39ndcG093|Vm22rJcurApd?T4L3W=QPlmwCwvRwVowY zoja2BI3>cqQ@SQLcZK?cHZ|_@maZfOOu6#0eXIRcXrp*BmLrZO=Dh6ni&EP_6;0Q@ zIY-lWl=8f#OuG&;o~M?K%R0U~LS>KiVV&UgSlNh!C?i0e_j+t8CN1(bD5XXo{yDnz z>*}h?9Z5bg(q`;QJ!zeeKoVZ#nuLR%u+A0(I-_kf@o~K#@D;=&qV)p2iVv|#5I0Zr z$x$sfwc(1xr3?+ARQLwyQNNFx#uQMUs>i@pQnoo0e$3nDXOOEx3uli2>U|X)ffnsP zAe)5;C9A9Dj;0Xz*JDvRKAnD7e=H>*y=Hft(^@GL6K_QX3I}|O*`-fuJ~EC1U%fjH zedvI@*BJkn@IJ;nI?&)M+?W;a1(2|#SkB<=|J3=S@%SWTEUkh1UfQLL>R{#k8>e%? zZz5sLXN!)e*!^Uez6vxp&DyHX>t-PGTXDqkZQnTP#U7ja`hAM5oCxS_UW2G%G84ONzRR7#n5M1-^f5Zr z6#Jy?yi)7;B~ZB*q&z_BR|7HKeoLa_btf(@`^@>YOHX!e{OqZZ)X*z;zJ zgT^?X;)l*0Qn7*gSm+SaI4+?LL%S>yZ*} z(5zfqsbgxz&cz39Pq*k%atmC=1Leb9K<-c3|uPpDeza2m0hVbqd0&DRt||6 z+j@EuTHib`xG2y3))W$yB}1SBqEF2H`QTaE=j zp!o>(-@i@LM?#s-k+0=%Tnxw|dc5#^E|VXi-)Y`K34*fJ z2=qXf%a?szL(u?71DYZzXhlQk%jIAJXHfxUi5Nog3|vm_20|DJmjJ=%8gXC*#Frzu z0UlhL1}aSD{`N!!^ge^-_5X}6QY#39 z+EK9)QUEnaask$RH8L81XiXh}WRZshws$o^i_Zx6P5w2%&3X!C#+jZFaZ_FbKgxL> z9|bJHs|iQ`3dW%Edrdz++pFsNA>*;7T{lBMO@eT*X*ZR7xHN096eDzqzqKDb7Pv8m z4{5G8s?2t}?=%BkWHft+_@DmaP!p%l7)_8yOJe*V=3wPQ&xDTrx}T;vP43`AT!}`$ zv&MKMR276Yr^kJ*E zG!L|P8m!&lkblD?if~=02p^lBKE*8_!T_B^nOWc_`#}Bkmaq(}PV;3|HhAYzy$?eW zCby@)PHp~CO1IOu_#v{RANfy9xRj4FbwGWG`PuJf&u#-!U+W8klzLd7E)TEm+C6o1 z*TQp{0czltN$G9@_im*?nR4HrQ$GUrSxSD+3w3Ww?G9hhvkZA!w#n+l!}l_!ek=n~ zN`R7?XLVzxYeAibJpmcAv6|Gs^`b#ka}nPJGyx)Ep}PmH_i)41D5%6!z4N>XWzkpO zN%oi%-@F%ly2Gk3VqT(TFn#;ifRuAkh8Jxi^yT)%Xp6jf5fwGkr2%#wK?{MhD1csc zoI=@9tGOublU){j9Jap&`2I)He~thE$4eJuIn&e(-D1^|-n4@&e2lN1NDUt{Nk!>9$5y7d8WTmRT*0>T?X0b!3o#3tK|#LRMw^$=L9 zt>qVROGR;tT#egP%qwW1%1|!G-@(_l|KLrQ*Z0w2yV|K{Ley<5ms)=P0p zc0Y$^4IL9N#3cJU912B^pmGAt>472T@^?8jsHddacMeZfx-}Do z_e@OQo`^FxTwF0s4jg}S^YzmM0DB<)^!Nf??tLTZNto?yDK~HEjs*H440>T@CJb3n z*9^9Age8PClj!iSwu-8})kdbE02x@}iYC3$f@z2TebBL}k{@*2RQ?*655Ujh3LT~t zWVnNT6##5J>VrfV<}L)rO-9JWre#XLsP{m5K)O;&hMm}jy=OgW_2YpLjJZz%blvFk zak1DPC4=&9Cttj4Kw1ZZ=lBT;a4$R>YcW``C^AN)Ne-#Xmy|zdRP(r@$5;P^Nex+j z%BW@om%j3|0pRw#>;GrO3HWODC~=^&M^mp{TBB!5688j7=nJCB(Vi$j|vh7O3Ndf}g6I z|A;_WMux8wSNdBci|?-DN9VxC%^Ml(c$s5b;F34k=)QNMMlq7jm*tfC0`cw%j70RDM0 zKHG%$Rscy#>Z0r&a_HdFU9`Y7N_v$G4L4AcToOYS<8~HyO8_p|{Z%yt_EN5DJajRx zb*7&ZKmL6y%v$=M(61+DuURJ(RM-&7eZ~Zl?vgfT<*(-s?|zzpN8Ma#sUW}~`0B8A zfnhWf3-wWPcDu#C{XM{yw|?Bg1HYSwIM6aT2yXH(PU)O}Eot<|OqBHgpFaOP*MySR zu7hJ@lqivUXh%#0FXcqN;EXw62(N2uVJYi8eyp>f)*V8@s-m*4gPfGLUL$P-i#=a`wD zC=)DLm;X+BJ4AUi^?Y$m)Exp-L_c>Ipiuqz;X3mwJ6&e>^Tkj;YjSDRI)K+cpv&_) zoRU%^eq^Z8x|b`0RjiQ)983^3oVlP1qZR?mU?gu7aM7J*42ejof{0UP)*NnCZ~w?Y zzRAN6?>)Z5L3dbc@9pmXQZOVw1reOFd!ON5zS)gEVW6;v+<{AOB1`Lfh4?@{2>)IV z^v3z=xu?^kDZ|I80_B8=g~zBK9lfru0c{_YQM7a_UM$6W0oncnSSlO&)G}&|wyU{7 zu%*4~fr})5XnZdZKq#Ma^C;QXG5vCFyih>BJ`792>+&fDm$o05LF4#LHxc2ekkG6- zxsad$s-nUUPCg3Go#P;@g!h=9@#;I*^uCq$th^w6cni2FKn#&ih4p?n`C1^&duWin zlvu1Gs5^Kzx3vr!-RSo=lxx!9$q2uSbl~nmNeM=6DXD`F)wWHu!?%^t3rsg^7N ztm};LKM_%VOFsK_vKho&aNK(FH+vlMegSOoc`ph;-|V4HFEUf1f?USYcZ4;yWQkD} z5N1@reNyF1B4K&hbAU_!&1&ibxjJv(-FOOh+w&BJLAYxir^S@C>8-&-+wJ(+$v2!5 zZLJ@y=l8V8ef_I5Tj#sH5x+bqZAe=f9)Ol**93CtKIOfn z7qTN3nIhvk!UO*`twM_G7b+T#SjU!y#Jm(~c4rgeV9&D_0Bk4*k3?OLEcjvp1=m5W zbv0w(BM$kdNFk`iszy*emTOk7;wi)9>$waU9+ zl*zIl+tC3@)qF-|y|@Y@33!#BJg#UDx{!eGU@Rt?bekI~-FSWLU49K|!$yT(d-oYu zs_9A$UUqD7wW|&0E!mstG1+;)beDwBnj;NaOr-u?zWM`={7C0>2O;$8kK(>xv?D&QvWV84&hHXNMd#r9BI%ccO}vRHQN%r z-kY>#xMjC^6lw*W>pC}$mqUbute&&Lv7$Z$*AjTjELR%nf_@i8*Mni-ltA%EAy$Iw zPhl0l-NCmKH7-SF1M&04%Y3qaPKvkn^;Kv4$IK=ILX`XP{*6Q0;RQmR=iEU%?{DWa1L zO{-tK+pL>2JO?uU7Qj71{**6dyPAO$VtnyN^j+Zm#|f8^_i#S{G3XI#feNya^=3PW z4jE*E<$ku-2u#S3d>)AG?!31oBBNFAvwkhSje-)C{eB4m4RG|yL?TLO85*GPwfX|k zVeT{t$!Xy;h#V?uuCwON+js%Eu6fGhu^7&SJDgC0uOHf=V0*zrbA`olq<+=7Wb|MP0)nF7692f^V!&G8sfo z{FE2cd&US!z+~5-l#VbulOUs>>-*Wt;bjkSpz5?= zG2INu2I{QTgSkd<^x9U}>VqIVAv0cNEKUz2O*-1Hc{G!&?|aQtAn&u`myoz_$d@M3 zD8N$ODhCYK_~2C>&m%J2VU8E>L|h|q9fAKCmn>MRG333V2tMo~3M^gR1IRZAVfvOm zjNURyQ}s`&x@+ohGNjYJIAHJV`U;NWmBN?V<}h%s7|mZ=P3ZV4bE`yN5oPdk#(i_a z!cmP^#N*F>F=hHn=ogXq&Vua&X`}IEig!GeguZ05imwX5m)w5cQwc<}zJ7y1Pc=jd z!0Bs$+}3j_EvMIjl)7*(edifn!?7z`D4dbJf$C8H#Ebu}#UoT%Zu@DUzm1&ajc_`l zEW2Cqmak&(obNaZYJcMAH@WTi#Sl~?6uGRDf#ac!LTkN%4&JEy>Ctq%?}df$@lf00 zS?Qvpg)cYpo%jJ1jqf<0{HfE%%|h0~NgagynF7;F>ve-dSUfyiR*Q+=#KIRi74X4D zqG*Snf4=zQX}CN!!3*uxwP`Y+PXP8}I|@l#0#^b>ozH+H8$JPQkVi@n3cxqZ8B!0s z7{C2Ga>z|7Om<-+816Y7=@oeFVNxr2wm|>12=ntUCPVAg5EGA3Zbc)sEO^@!TM?w! zp6OWZXW|ZriKS>Tn(u1g)h}JP7%>KjslCN2#Zt!r@=MQ&iWF%e<6fpOZCz82Hx93FSLNL^MTzvNu7liKHSoAZZ>>7Hk)(8(&{n!M;e>b zx%)Av(2{$nzzTo3=6? z4`}DbELv3WxtEB3KLE!piIB&NW;b!3{3wrpHf9L23%*t7Ss_lM{+LJw^mJ&b$L(Ov z3k>te^nO8$6@S#eBMyrx=0i=Q>))#LFC;qQB%X3-NK&8*0Q`L|N!HY1?B=)BUA{Yy z_U%*w1n+Eh4}x*Yg@TwmX85C%gw?JgUx9n4txE-khG(2`I~N#6L4zSkBnBXYB_GDnT>Ha~tjk|kwt;Si?>;Qv$ zGf>H?ua19FL|{{6@NMUr`KoGpsRWlpU9?Md_p~J#AcK0Zvo|h@ia;`u??XgKut9 zV3V0B&e$|TcLVU5Nvx{m z_a+OSg#zHufNLgfF%cKBoWQ3l>^Hull>jvPePDr3A^Qa?b1Rfd)#v%gqLH@`1k{(I zBV;e5WX+DO%3QF3!TyaM0(!4CdQ!M*6@sB_gq%+jSUNczi!F+SG0KcOl@QzPPwV_OG=e5gYKWWWm42_`p_B3*vd{)*;D8P&JCK^|NB zy(nR&zaGSCzFWgDI5DmZvHnpZ9_zh+M>5maDE;SM?}Gc@P8oWm7zBVRVu3BfG(eCG zFP8BCK18U+ulVXdNQDSE_+VYeBkz1l)7VA=U_4TQh50{Pyv+%nYv~)gXo&ychFo;b z2lx$+K(j{*AQkM(;3QZJMZ4l4s1OoS0KboO5voPnlCZ?9XHVljf)<% znXt<)n#t7j=CXhymcQ{Y|2Zdsuq4LM4)d$n=a4!3h|&83o=Yq(qW*V8*kv2#70+&IqvZ|!Rh2o6` zAyEK)9Ph9<(VUQK_Pb>-?nD;`eeV8UWj!KRd9p$Tpq6;21c) zMN&v(W%T%5Cf=6m>?mFYSNg}6>9p4kAoy|wjP?f5Z^ycWS%Qhfb1Mz+Z64D`*i8fv z*=4BprBSr)9_?8e97L=w8DqXzys%{ZS9Mh3t5uTx-S!SMv&~y!Qg4sGSiGPJ zxwJ>K_Ju#i2SQByOg@Lx(?4THc;tQwU4~LqfF#4GT=Zn|Hb<(J>&T(CyY~6&mi%1e zgdqv?$NlTr2-fDvZop9H`k1Xn3Eu3@kDfF#q&ac5{*j;d!nueU2?LpfQsy0LL%+~W zRgu(l$a>vLaG#v%%x~V(e?nuV@om8x^FO=yqbbESnAf)&kH2WXR2DuSZ9E{mOl)xA zjZ5s={MZ&5=;={_wCRYXZc8%)Sn&UZ*2v>Q2ix2}&64Nl8e4W-M^CGdt=C~oKC>4B zz-52buj8`?;BSewM4~NxrqcnMlfUsWT||_cI&&hc$?^QbACm2Rr0wTURik)7!YGP! z3Eg*4=$DHDVBZm5aNe?i2FnYN5>~ULy-0_cy_frJdm9??fN~t5o4AY&tLT7~a1cDi z?CSmZMdj-yHA{Wp!-aLzrznH0eET)|SrweGA%r8c0E0k>NhtPtZ@U*i7Nni5GSL;; zPD=GpR%Qj%B7Z(b%60wj9g=WI5X4WS%W59)?eamk=Z;kh>RQp%uT&e1T=bsfo%2ou+R9?xWKnVJW83#alDYsa;4@2&8ouj{{CvOWK zV9L!A2@BRZ?wZVuCB;5bky4btioVdW9-1M6BdKCs$00wZNB!LXc4Eb*zx7OE3%ye3 z_Brx5t>iJ%{(n)xgqvw{QZG!-0Tl2Yi8gizAy~<|{UXKZ2&DK-7);)$q#S~hSS1ypR+U|X@Fw9$cP>R z$v;`i$s4j>C#8|{i%sJ6q)9$!#gT;7r}gH08t$Z57~yL22G6qJHD{L?VMWiSn_%|e zAwc?2=wcY&VeE<;8qBG9Z@Kz4W0cr_aLJjlPhMMiE)W8q#y;7Lje2T3en zCj(&}y{o#Bc@2*a>r}z$z4p5sgudP^f{M8c?{O65N#fIVSro6QF$bw?@_tOi?k8^H zyhHh*A8QGBmh97Q4k*^2>yCJjZvMZ$MnwflI@IPxNsjZk1q0)Kkl;@Hzkc8$0>e7~ zcG2x;ahzrLq#(f4;>jm%wHdJ!<*J7qbhWm6&Hkc%B^nt~8@en)e>>m)dC)_~oO*I{ zLRHUVr(eKo;_*)5J_^)gi|HB-m#XJl8B>31Z-bs|h`gE-aYUcYNC~g*)J8SsL~)E< z3+{MPu)J-I0;r;!q4dYI*-V}xwhCv5@iGUvzzEa67cjr2BnsZ)^3N`5rzg|L{*CC{ zjLb{7XSaWj@qhZjW2)Q95jXTuBxqI>^8WB*@02*2X zNR!YZgwR5lUP5nDq(dMC=?Y2|5Tu1JC5Rv#Lx9jBVC5jaDZxZ3dJqf|P(e@>0X=s- ze&1c|{`l6qYu!J0{>-dd^UmJ0XV3G#`<=a?Cn9?#-n;@*M%Xt18Ya%}zUf=u0zQ$a z{o_~mGlzR9yOj&?c5zpREI@<7hdhLv1Xv!W-26LUlK}$vq_RW$W}MK|q8)@m!90UWs^E(;VBC zKMP~4g-BUW>wNOUmm{$ssRt{8*}i(qq4v`qL*cGzLXTf#bkJM(_PVJ!I;p;M)v<9cO`p&Rd^B^&2HnOHNKKK2^8hRmH7MKgNH z`KlqwJA8)2daYLb=MZvCUluno^`p&tcWP)v=;b>=O@a9}z=kxx&=!@myC**^3Y%z7 z$@tYiS;H*BjR?&!AQcJpp5AJRAW7L-uoYU-qh zaXJppcf*?7fq8K`@Ev)6pS~gQm;!nHU>P%22F(!4vC-rX3Ub6~q+U6zbDNP2N|6&&8 zIx6H7_VCVq{M_x~K%ew@BXPbm&P+3BY|e?t5lN&ynl`?cXBZJtxE9)+F}a~-%2l1% zA&yQLd?4p`8fH1Ye=2E6=zLU|o`Hsg(-~-C8sDYubI+a>otFeB?RkaK=qm<|ku!CV zn9oSmQL+mPvF_%u4yejK&&(-)VCrncpI%Y=7EvmQ-rh6oO~mCYkrjcCvYU0~{%f*z zpu@qgaU}~-T2SD;4N%?r)LkNL@<9hUk0tqfoPql4lNr;kg&1#=pl0si1^KOpkj!C# zSTQKRTS&QP(Nhd^g7K#BR1OKEMTkyKWvS41v+P1ncYpXWO8cW_v0nW0?uG_uv`&x` zu>4XHcowHJ$k7T=6nKSNh?!UVxl`=;&xQMzND@siS8z2g z&`N0;Vk=L(QMLBYd}V-#g8<;OKT|uIA>U--$rSBWuCzoM+gLF&W~f14E3axD?a0)j z^~Q+JTlAa8iIDMI^x!46AMF*V&}rwtMx3Z=$-iaRt(#zzHRg9-`JsSrFW#9t8R>Tm zgf{l(fn;Q;PJOBE}gtEsu$sk}ygW;S;CFt!NJJYK?eG zk<7Yl-^`ZAEK;yWRuNCu&t2itf%fQoP`;{2NqfRwyX87=yD~<@O_3@a z(G(TbWBfv_BEIhFbcVD2Z-C#lPrHAc>}%SsssDb($&2cAhr%BJmrIp1!far9W9%4h z)J-M6LcWOLjjBKRyfBF)-^$j07??pgG~YOq2Np+OSs_0vxA-_mPET>)as{U=fNZ^Z z^Pt{W(JD>CMmE1oc_%4(XkpUxN=?K)2xEK}zsNAZWVbzTkXW#~7m*m>uV&kcebkFV zzM%{L_A(a7GEN4|atyB2XiuHThWne?bc-3hj0P5_lw1S!i-7ZAem)HMf2q~&vnbrS z2N-VQ2rST@I^}ddKbFXr! z-ru&`O2v*i=O#x_B@4Y+#_g^04~$ZeX4p2y;&{LDzb(Un3CS@JOy8oIr@F1AEWk<# z2-e+4$Fp;`Yo^HEw{%JhXuhWE4fmKQOQ zk)A#Cbnuk#;W*Cd3UQq^=Q4Nl>y`;1|CBHzS5`qA!2g{FiYnY-APq zp-X~-5VP{X_?8u1X_v%mvt*kcO)mBd3$*cBPTwPY_HR~aL%k=R)~I*5)YM&5`X`gwrh2fohC8^|^KLgVqNNd`Zk>7=OT_GJ9921( z5AJ(i9xfv%bG2dbPGU6&4h=b7w|XemQ=;I1-s7S(AQbPmLQ!L&Vk_JoWx=W|2gt20 z@GSi(>2(Ock;hVWC|;re1NQaHGCf1nI>XF~SLGeUj~ii4t^(>#$P&)51R?m5TE~+< z(U?;C_C6n8Gw`n2izV`%N~WJ(chq^WD2ala*pngs*l=b@U(=wi-gYHvt*r$*Ad$78 zf?aUEIo7J)x-n7uUAf(XQs}Jsz;&R+nRm7&aJH1PG>JT$&PeVQL(puXD$iU%6N<-g>(efcYF{8W!;(i!NzMQEz*3w^X%pRXR!Q) zMyDC~H4h@06e4OV-uFIJthRyE@J&+ou)8y~>l&4I~ zcX;pD0qLsAI!Z8kk4t9Ap2m0YUh;=(*x+8bDc}Rzz1_Mg z3K?8-9H-(8)?22C02icL@44Fc+{d+B*R6;O7GT$1a=7ie&F3NU76H={RbRl(;X&f? z(fx~=u-Bt76J*>^Dv&2R3AoYzTw+oRM^(Nc7XBQo+h`sYMRN(muhgJzL=PhlOUFOA z+zj(<9MyiXnu`xj{8jHSDyYvD*x`iKUw!u+U#7WgLCt4>wfab;zI(EVm`up<&)Q?2 zPb@74)g)~Ci80zn4D-&jjJ%j@cS~Q%q44ice#}Eb=l+64po*iDag6KWS{*4M&|#;o z0)eJMqpcpGI0qpx*WEpIMS;n!jl24$fjQ{+l;wSx#?dBvMK}~ZVpM!@>b|tliwbAl z`1ptd_B(ZRTofI5zyX31$LiJvQFt%0#i)vxalsa>PkRTMF`Nef26~-B$aQG9#n#~`@=8G>HwSHn)e?H;mG2%y zEH@xdl{;>EDFdrkwawix3q1&*Nc$ttezcHnARV9d_v*pg`y-yI|BPUgZXwt6#B#x2 zB~--@^jfs~pESDWbSbDA$qv(L9*&BUBv79Z`>}!#{kpP&SoP`f zq#(M{y!(ZZ0pZzIAYl77Qkr1>GT&;RSL4`-K-m_f=i zf;j;}1j!SwuQ!hZOxhdYgU-^*k;NerQ2P(e@kqvUTS}-cuwu<$O&oo)poaHwCoSd{ zyI~fThxn(hAOKv`rfPJ$Eoh!!i_0&Xb}k+DBwnM$ioeP%ZKWuX-kTEe&2RWK42?D^ z2BoF}j!4+yn`QmQoVIa1PY1%f7|Y{?PXtiMoEg-Z``!OymlCbqJbZ(7O^HUYTbT?y z;yk@O*(~t_c;MutF5fDUV>+Ym4*h<1GF$*$!#-EuUO3SW(DKu_GnHuCwCzDU6Ig3ewVjDm$FFm7T&TS%ooJ0d)CK*Fp_!Z$eFrD^T^_&R{OdFMsQ_m zZ*uM~$TifKnjhBbsqYC*P!7!7gtHjS{=hIb)(- zbTxY8Ct;j_%a0?}*G(Pu*n!h^?9vliP=2a(VO@iI*}S`xf9KFTrGdo$2d#7<;83f- zX4q9-?bY53Jh@zh!T7-oT0~N5`ey1-q=#R!AB`h+=|z}=EO^lZKww^gZ7t`%^>(~< z4?m|XBLuOvkkg?ZlfjlFv%T(bIePFw9;?)8KE-zT5CFCL0S#u=WdfzA9WcoBYk&A4 z%)t5nw}lTsaz;{b?Y|0bc?-Yp_0L_WkM*}oLH9bO1OkU+b&iO&=RodFWY;_O=|#y@_-c_}+RU6n&8(4Ub_V^=+pTXsN#$oQWmLh{i#CT2ZLl+a~m zk@L5NMe!~t7tI#>JB`4blKdXCp3p0)K`V(z>X@dr6DN-U#upQbQ)uUIlr;7dB}_}N zBJE`BdktU0I8!6lEwmj2$Q`^WRh}%WZ7=tlDo+NNu>Z!78%AfK3o($-lsH4^I#WC@ zE4n-i_;m@+fkp5S%+vy^y_*O*$iE9`c3Bh1e@^6zbd(daTf;-I$I~U)sNy`>jT_`8 z_T`4E#?pKeT!!GLrs)3f$;bWe4<^`TMFK!Vns4 zt0^C!Utgr?Z@g#oE7v~3Rs)d>VOvS2#`|lFs!f?T{asIfd|7?R=^Kbao OZdPV?rY&dvQvVB_O#lf1 diff --git a/docs/blamematrix.md b/docs/blamematrix.md deleted file mode 100644 index 7868c96..0000000 --- a/docs/blamematrix.md +++ /dev/null @@ -1,49 +0,0 @@ -## spacesavers2_blamematrix - -This takes in the `allusers.mimeo.files.gz` generated by `spacesavers2_mimeo` and processes it to create a matrix with: - -- folder paths as row-names -- usernames as column-names -- duplicate bytes as values in the matrix - -Deleting these high-value duplicates first will have the biggest impact on the users overall digital footprint. - -### Inputs - -- `--filesgz` output file from `spacesavers2_mimeo`. -- `--level` depth at with to cutoff the output. -- `--humanreable` make the output human readable, that is, output in MiB, GiB, TiB, etc. instead of bytes. -- `--includezeros` include empty folders. -- `--outfile` path to the output file. - -```bash -% spacesavers2_blamematrix --help -usage: spacesavers2_blamematrix [-h] -f FILESGZ [-l LEVEL] [-r | --humanreable | --no-humanreable] [-z | --includezeros | --no-includezeros] [-o OUTFILE] [-v] - -spacesavers2_blamematrix: get per user duplicate sizes at a given folder level (default 3) - -options: - -h, --help show this help message and exit - -f FILESGZ, --filesgz FILESGZ - spacesavers2_mimeo prefix.allusers.mimeo.files.gz file - -l LEVEL, --level LEVEL - folder level to use for creating matrix - -r, --humanreable, --no-humanreable - sizes are printed in human readable format ... (default: Bytes) - -z, --includezeros, --no-includezeros - include folders where totalbytes is zero. - -o OUTFILE, --outfile OUTFILE - output tab-delimited file (default STDOUT) - -v, --version show program's version number and exit - -Version: - v0.10.2-dev -Example: - > spacesavers2_blamematrix -f /output/from/spacesavers2_mimeo/prefix.allusers.mimeo.files.gz -d 3 -o prefix.blamematrix.tsv -``` - -### Outputs - -Counts matrix with duplicate bytes per user per folder. - -> Note this can be used to generate a heatmap for quickly find folders with high duplicates and the user they belong to. diff --git a/mkdocs.yml b/mkdocs.yml index 3f8197e..3929983 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -102,6 +102,5 @@ nav: - catalog: catalog.md - mimeo: mimeo.md - grubbers: grubbers.md - - blamematrix: blamematrix.md - usurp: usurp.md - e2e: e2e.md diff --git a/spacesavers2_blamematrix b/spacesavers2_blamematrix deleted file mode 100755 index 9885c7c..0000000 --- a/spacesavers2_blamematrix +++ /dev/null @@ -1,144 +0,0 @@ -#!/usr/bin/env python3 -import sys -import os -import gzip -import textwrap -import time - -from src.VersionCheck import version_check -from src.VersionCheck import __version__ - -version_check() - -# from src.FileDetails import FileDetails -from src.dfUnit import fgzblamer - -# from src.Summary import Summary -from src.utils import * -from datetime import date - -import argparse - - -def main(): - start = time.time() - scriptname = os.path.basename(__file__) - elog = textwrap.dedent( - """\ - Version: - {} - Example: - > spacesavers2_blamematrix -f /output/from/spacesavers2_mimeo/prefix.allusers.mimeo.files.gz -d 3 -o prefix.blamematrix.tsv - """.format( - __version__ - ) - ) - parser = argparse.ArgumentParser( - description="spacesavers2_blamematrix: get per user duplicate sizes at a given folder level (default 3)", - epilog=elog, - formatter_class=argparse.RawDescriptionHelpFormatter, - ) - - parser.add_argument( - "-f", - "--filesgz", - dest="filesgz", - required=True, - type=str, - default=sys.stdin, - help="spacesavers2_mimeo prefix.allusers.mimeo.files.gz file", - ) - parser.add_argument( - "-l", - "--level", - dest="level", - required=False, - type=int, - default=3, - help="folder level to use for creating matrix", - ) - parser.add_argument( - "-r", - "--humanreable", - dest="humanreable", - required=False, - action=argparse.BooleanOptionalAction, - help="sizes are printed in human readable format ... (default: Bytes)", - ) - parser.add_argument( - "-z", - "--includezeros", - dest="includezeros", - required=False, - action=argparse.BooleanOptionalAction, - help="include folders where totalbytes is zero.", - ) - parser.add_argument( - "-o", - "--outfile", - dest="outfile", - required=False, - type=str, - help="output tab-delimited file (default STDOUT)", - ) - parser.add_argument("-v", "--version", action="version", version=__version__) - - print_with_timestamp( - start=start, scriptname=scriptname, string="version: {}".format(__version__) - ) - - global args - args = parser.parse_args() - - blamematrix = dict() - blamematrix["allusers"] = dict() - with gzip.open(os.path.join(args.filesgz), "rt") as filesgz: - for l in filesgz: - dfu = fgzblamer() - properly_set = dfu.set(l, args.level) - if not properly_set: - continue - for user in dfu.users: - if not user in blamematrix: - blamematrix[user] = dict() - for folder in dfu.bm[user]: - if not folder in blamematrix[user]: - blamematrix[user][folder] = 0 - if not folder in blamematrix["allusers"]: - blamematrix["allusers"][folder] = 0 - blamematrix[user][folder] += dfu.bm[user][folder] - blamematrix["allusers"][folder] += dfu.bm[user][folder] - - if args.outfile: - of = open(args.outfile, "w") - else: - of = sys.stdout - - users = list(blamematrix.keys()) - folders = list(blamematrix["allusers"].keys()) - users2 = ["folder"] - users2.extend(users) - outstr = "\t".join(users2) - of.write("%s\n"%(outstr)) - for folder in folders: - outlist = [] - outlist.append(str(folder)) - for user in users: - try: - hrsize = blamematrix[user][folder] - if args.humanreable: - hrsize = get_human_readable_size(hrsize) - except KeyError: - hrsize = "0" - outlist.append(str(hrsize)) - if blamematrix["allusers"][folder] == 0 : - if args.includezeros: - of.write("%s\n"%("\t".join(outlist))) - else: - of.write("%s\n"%("\t".join(outlist))) - if args.outfile: of.close() - print_with_timestamp(start=start, scriptname=scriptname, string="Done!") - - -if __name__ == "__main__": - main() diff --git a/spacesavers2_catalog b/spacesavers2_catalog index 0ba81ca..30b0d35 100755 --- a/spacesavers2_catalog +++ b/spacesavers2_catalog @@ -17,19 +17,17 @@ from pathlib import Path def task(f): - if not os.path.isfile(f): - return "" - else: - fd = FileDetails() - fd.initialize( - f, - buffersize=args.buffersize, - thresholdsize=args.ignoreheadersize, - tb=args.buffersize, - sed=sed, - bottomhash=args.bottomhash, - ) - return "%s" % (fd) + fd = FileDetails() + fd.initialize( + f, + buffersize=args.buffersize, + thresholdsize=args.ignoreheadersize, + tb=args.buffersize, + sed=sed, + bottomhash=args.bottomhash, + st_block_byte_size=args.st_block_byte_size, + ) + return "%s" % (fd) def main(): @@ -84,7 +82,7 @@ def main(): help="this sized header of the file is ignored before extracting buffer of buffersize for xhash creation (only for special extensions files) default = 1024 * 1024 * 1024 bytes", ) parser.add_argument( - "-s", + "-x", "--se", dest="se", required=False, @@ -92,6 +90,15 @@ def main(): default="bam,bai,bigwig,bw,csi", help="comma separated list of special extensions (default=bam,bai,bigwig,bw,csi)", ) + parser.add_argument( + "-s", + "--st_block_byte_size", + dest="st_block_byte_size", + required=False, + default=512, + type=int, + help="st_block_byte_size on current filesystem (default 512)", + ) parser.add_argument( "-o", "--outfile", @@ -120,7 +127,9 @@ def main(): folder = args.folder p = Path(folder) - files = p.glob("**/*") + files = [p] + files2 = p.glob("**/*") + files.extend(files2) if args.outfile: outfh = open(args.outfile, "w") diff --git a/spacesavers2_e2e b/spacesavers2_e2e index 26a3744..57d2bd2 100755 --- a/spacesavers2_e2e +++ b/spacesavers2_e2e @@ -13,8 +13,8 @@ source ${SCRIPT_DIR}/resources/argparse.bash || exit 1 argparse "$@" < ${outfile_catalog_log} 2> ${outfile_catalog_err} fi +sleep 60 + # spacesavers2_mimeo if [ "$?" == "0" ];then echo "Running spacesavers2_mimeo" -command -V ktImportText 2>/dev/null || module load kronatools || (>&2 echo "module kronatools could not be loaded"; exit 1) +command -V ktImportText 2>/dev/null || module load kronatools || (>&2 echo "module kronatools could not be loaded") spacesavers2_mimeo \ --catalog ${outfile_catalog} \ --outdir ${OUTFOLDER} \ --quota $QUOTA \ --duplicatesonly \ - --maxdepth 3 \ + --maxdepth $MAXDEPTH \ --p $prefix \ --kronaplot \ > ${outfile_mimeo_log} 2> ${outfile_mimeo_err} fi +sleep 60 + # spacesavers2_grubbers if [ "$?" == "0" ];then echo "Running spacesavers2_grubbers" && \ @@ -84,13 +88,4 @@ for filegz in `ls ${OUTFOLDER}/${prefix}*files.gz`;do done fi -# spacesavers2_blamematrix -if [ "$?" == "0" ];then -echo "Running spacesavers2_blamematrix" && \ -spacesavers2_blamematrix \ - --filesgz ${OUTFOLDER}/${prefix}.allusers.mimeo.files.gz \ - --level $LEVEL \ - --outfile ${outfile_blamematrix} \ - > ${outfile_blamematrix_log} 2> ${outfile_blamematrix_err} -fi -echo "Done!" +echo "Done!" \ No newline at end of file diff --git a/spacesavers2_grubbers b/spacesavers2_grubbers index 5bbd2a5..adc2c59 100755 --- a/spacesavers2_grubbers +++ b/spacesavers2_grubbers @@ -92,7 +92,7 @@ def main(): of = sys.stdout for fgitem in dups: - if fgitem.totalsize < top_limit: + if fgitem.totalsize <= top_limit: break saved += fgitem.totalsize of.write("%s\n"%(fgitem)) @@ -100,11 +100,11 @@ def main(): if args.outfile: of.close() - saved = get_human_readable_size(saved) + hrsaved = get_human_readable_size(saved) print_with_timestamp( start=start, scriptname=scriptname, - string="Deleting top grubbers will save {}!".format(saved), + string="Deleting top grubbers will save {} [ {} Bytes ] !".format(hrsaved,saved), ) print_with_timestamp(start=start, scriptname=scriptname, string="Done!") diff --git a/spacesavers2_mimeo b/spacesavers2_mimeo index 04a61e3..822c4ee 100755 --- a/spacesavers2_mimeo +++ b/spacesavers2_mimeo @@ -24,19 +24,6 @@ from datetime import date import argparse -def check_terminal_list(p,tlist): - outcome = -1 # append path to tlist - for i,p2 in enumerate(tlist): - if p.len < p2.len: - if p.path in p2.path: - outcome = -2 # path already in tlist - return outcome - else: - if p2.path in p.path: - outcome = i - return outcome - return outcome - def process_hh( uid, hashhash, @@ -45,7 +32,8 @@ def process_hh( maxdepth, uid2uname, gid2gname, - peruser_perfolder_summaries, + perfolder_summaries, + perfolder_dups, user_output, ): for h in hashhash.keys(): @@ -66,63 +54,42 @@ def process_hh( foldest = hashhash[h].flist[oldest_index] user_owns_original = False if foldest.uid == uid or 0 == uid : user_owns_original = True - uid_dup_file_index = [] - if hashhash[h].ndup_inode > 1: # there are duplicate inodes and hence there are duplicate files - inodes_already_summerized = list() + uid_file_index = list(filter(lambda x:x!=oldest_index,uid_file_index)) # remove oldest if present in list + inodes_already_summerized = list() + if hashhash[h].ndup_files > 0: # we have duplicates for i in uid_file_index: f = hashhash[h].flist[i] + fpath = f.apath + parent = fpath.parent fpaths = f.get_paths(mindepth, maxdepth) - if ( - i == oldest_index - ): # its the original file ... not a duplicate + if f.inode in inodes_already_summerized: # it is a hardlink for p in fpaths: - peruser_perfolder_summaries[p].nnondup_files += 1 - peruser_perfolder_summaries[p].non_dup_Bytes.append(f.size) - peruser_perfolder_summaries[p].non_dup_ages.append(f.mtime) - inodes_already_summerized.append(f.inode) # scenario where original already has a hard-link + perfolder_summaries[p].ndup_files += 1 else: - uid_dup_file_index.append(i) - # has the inode already been summarized - if f.inode in inodes_already_summerized: - for p in fpaths: - peruser_perfolder_summaries[p].ndup_files += 1 - else: - inodes_already_summerized.append(f.inode) - for p in fpaths: - peruser_perfolder_summaries[p].ndup_files+=1 - peruser_perfolder_summaries[p].dup_Bytes.append(f.size) - peruser_perfolder_summaries[p].dup_ages.append(f.mtime) - else: - # ndup_inode == 1 .. meaning there are no duplicate inodes .. can still have multiple hard linked files - # only count 1 file/hardlink for summary - i = uid_file_index[0] - f = hashhash[h].flist[i] - fpaths = f.get_paths(mindepth, maxdepth) - for p in fpaths: - peruser_perfolder_summaries[p].nnondup_files += 1 - peruser_perfolder_summaries[p].non_dup_Bytes.append(f.size) - peruser_perfolder_summaries[p].non_dup_ages.append(f.mtime) - if args.duplicatesonly: - if len(uid_dup_file_index) > 0: # this user has some duplicates - out_index = [oldest_index] - out_index.extend(uid_dup_file_index) - user_output.write( - "{}\n".format( - hashhash[h].str_with_name( - uid2uname, gid2gname, out_index - ) - ) - ) - else: - out_index = [] - if user_owns_original == False: - out_index.append(oldest_index) - out_index.extend(uid_file_index) - user_output.write( - "{}\n".format( - hashhash[h].str_with_name(uid2uname, gid2gname, out_index) - ) + inodes_already_summerized.append(f.inode) + if not parent in perfolder_dups: + perfolder_dups[fpath.parent] = 0 + perfolder_dups[fpath.parent] += f.calculated_size + for p in fpaths: + perfolder_summaries[p].ndup_files+=1 + perfolder_summaries[p].dup_Bytes.append(f.calculated_size) + perfolder_summaries[p].dup_ages.append(f.mtime) + else: # we only have 1 original file + if user_owns_original: + fpaths = foldest.get_paths(mindepth, maxdepth) + for p in fpaths: + perfolder_summaries[p].nnondup_files += 1 + perfolder_summaries[p].non_dup_Bytes.append(foldest.calculated_size) + perfolder_summaries[p].non_dup_ages.append(foldest.mtime) + out_index = [] + out_index.append(oldest_index) + out_index.extend(uid_file_index) + if args.duplicatesonly and len(out_index)==1: continue + user_output.write( + "{}\n".format( + hashhash[h].str_with_name(uid2uname, gid2gname, out_index) ) + ) def main(): @@ -241,19 +208,24 @@ def main(): start=start, scriptname=scriptname, string="Reading in catalog file..." ) set_complete = True + folder_info = dict() with open(args.catalog) as catalog: for l in catalog: fd = FileDetails() set_complete = fd.set(l) if not set_complete: continue - if fd.issyml: + if fd.fld != "d" and fd.fld !="f": # not a file or folder continue # ignore all symlinks users.add(fd.uid) groups.add(fd.gid) - path_lens.add(get_file_depth(fd.apath)) + path_lens.add(fd.get_depth()) for p in fd.get_paths_at_all_depths(): paths.add(p) + if fd.fld == "d": + if not fd.apath in folder_info: + folder_info[fd.apath] = fd + continue hash = fd.xhash_top + "#" + fd.xhash_bottom if hash == "#": # happens when file cannot be read sys.stderr.write( @@ -304,8 +276,13 @@ def main(): scriptname=scriptname, string="Total Number of users: %d" % len(users), ) - + blamematrixtsv = os.path.join( + os.path.abspath(args.outdir), "blamematrix.tsv" + ) + blamematrix = dict() + all_blamematrix_paths = set() for uid in users: + blamematrix[uid] = dict() print_with_timestamp( start=start, scriptname=scriptname, @@ -337,9 +314,22 @@ def main(): with gzip.open(useroutputpath, "wt") as user_output, open( summaryfilepath, "a" ) as user_summary: - peruser_perfolder_summaries = dict() + perfolder_summaries = dict() + perfolder_dups = dict() for p in paths: - peruser_perfolder_summaries[p] = Summary(p) + perfolder_summaries[p] = Summary(p) + if not p in folder_info: + folder_info[p] = FileDetails() + folder_info[p].initialize(p) + fd = folder_info[p] + for p2 in fd.get_paths(mindepth,maxdepth): + if not p2 in folder_info: + folder_info[p2] = FileDetails() + folder_info[p2].initialize(p2) + fd2 = folder_info[p2] + if fd2.uid == uid or uid == 0: + perfolder_summaries[p2].folder_Bytes += fd.calculated_size + hashhashsplits = dict() # dict to collect instances where the files are NOT duplicates has same hashes but different sizes (and different inodes) ... new suffix is added to bottomhash .."_iterator" process_hh( uid, @@ -349,7 +339,8 @@ def main(): maxdepth, uid2uname, gid2gname, - peruser_perfolder_summaries, + perfolder_summaries, + perfolder_dups, user_output, ) if len(hashhashsplits) != 0: @@ -362,42 +353,35 @@ def main(): maxdepth, uid2uname, gid2gname, - peruser_perfolder_summaries, + perfolder_summaries, + perfolder_dups, user_output, ) del hashhashsplitsdummy del hashhashsplits for p in paths: - peruser_perfolder_summaries[p].update_scores(quota) - user_summary.write(f"{peruser_perfolder_summaries[p]}\n") + perfolder_summaries[p].update_scores(quota) + user_summary.write(f"{perfolder_summaries[p]}\n") + for p in perfolder_summaries: + dummy = FileDetails() + dummy.initialize(p) + if dummy.get_depth() == mindepth + 1: + all_blamematrix_paths.add(p) + blamematrix[uid][p] = sum(perfolder_summaries[p].dup_Bytes) if args.kronaplot: - terminal_paths = [] - with open(summaryfilepath,'r') as infile: - count = 0 - for l in infile: - l = l.strip().split("\t") - count += 1 - if count==1: - continue #header - if count==2: - terminal_paths.append(pathlen(l[0],int(l[2]))) - continue - p = pathlen(l[0],int(l[2])) - outcome = check_terminal_list(p,terminal_paths) - if outcome == -1: # new ... append - terminal_paths.append(p) - elif outcome == -2: # already in list .. move on - continue - elif outcome > -1: # better than current one in list ... swap - terminal_paths[outcome] = p + print_with_timestamp( + start=start, + scriptname=scriptname, + string="Creating Kronachart for user: %s" % (uid2uname[uid]), + ) with open(kronatsv,'w') as ktsv: - for p in terminal_paths: - path = p.path + for p in perfolder_dups: + path = str(p) path = path.replace('/','\t') path = path.replace('\t\t','\t') - if p.dupbytes != 0 : - ktsv.write("%d\t%s\n"%(p.dupbytes,path)) + if perfolder_dups[p] != 0: + ktsv.write("%d\t%s\n"%(perfolder_dups[p],path)) if ktImportText_in_path: cmd = "ktImportText %s -o %s"%(kronatsv,kronahtml) srun = subprocess.run(cmd,shell=True, capture_output=True, text=True) @@ -405,8 +389,31 @@ def main(): sys.stderr.write("%s\n"%(srun.stderr)) del hashhash - print_with_timestamp(start=start, scriptname=scriptname, string="Finished!") + print_with_timestamp( + start=start, + scriptname=scriptname, + string="Creating Blamematrix", + ) + with open(blamematrixtsv,'w') as btsv: + outlist = ["path"] + uids = list(blamematrix.keys()) + uids.sort() + for uid in uids: + outlist.append(uid2uname[uid]) + btsv.write("\t".join(outlist)+"\n") + for p in all_blamematrix_paths: + outlist = [str(p)] + s = 0 + for uid in uids: + if p in blamematrix[uid]: + s += blamematrix[uid][p] + outlist.append(str(blamematrix[uid][p])) + else: + outlist.append(str(0)) + if s != 0 : btsv.write("\t".join(outlist)+"\n") + + print_with_timestamp(start=start, scriptname=scriptname, string="Finished!") if __name__ == "__main__": main() diff --git a/spacesavers2_usurp b/spacesavers2_usurp index 1ed5cac..2c79c9a 100755 --- a/spacesavers2_usurp +++ b/spacesavers2_usurp @@ -11,10 +11,6 @@ from src.VersionCheck import __version__ version_check() -# from src.FileDetails import FileDetails -from src.dfUnit import fgzblamer - -# from src.Summary import Summary from src.utils import * from datetime import date @@ -81,7 +77,7 @@ def main(): lhash = l[0] if args.hash in lhash: original_copy = Path(l[4].strip('"')) - dupfiles = l[5].split(";") + dupfiles = l[5].split("##") print_with_timestamp( start=start, scriptname=scriptname, diff --git a/src/FileDetails.py b/src/FileDetails.py index 1204257..ce7a4db 100644 --- a/src/FileDetails.py +++ b/src/FileDetails.py @@ -9,8 +9,8 @@ except ImportError: exit(f"{sys.argv[0]} requires xxhash module") -THRESHOLDSIZE = 1024 * 1024 * 1024 -BUFFERSIZE = 128 * 1024 +THRESHOLDSIZE = 1024 * 1024 * 1024 # 1 MiB +BUFFERSIZE = 128 * 1024 # 128 KiB TB = THRESHOLDSIZE+BUFFERSIZE SEED = 20230502 MINDEPTH = 3 @@ -21,14 +21,33 @@ SED[se]=1 def convert_time_to_age(t): - currenttime=int(time.time()) - return int((currenttime - t)/86400)+1 + currenttime = int(time.time()) + age = int((currenttime - t)/86400)+1 + if age < 0: age = 0 + return age + +def get_type(p): + x = "u" # unknown + if not p.exists(): + x = "a" # absent + return x + if p.is_symlink(): + x = "l" # link or symlink + return x + if p.is_dir(): + x = "d" # directory + return x + if p.is_file(): + x = "f" # file + return x + return x class FileDetails: def __init__(self): self.apath = "" # absolute path of file - self.issyml = False + self.fdl = "u" # is it file or directory or link or unknown or absent ... values are f d l u a self.size = -1 + self.calculated_size = -1 self.dev = -1 self.inode = -1 self.nlink = -1 @@ -40,12 +59,13 @@ def __init__(self): self.xhash_top = "" self.xhash_bottom = "" - def initialize(self,f,thresholdsize=THRESHOLDSIZE, buffersize=BUFFERSIZE, tb=TB, sed=SED, bottomhash=False): + def initialize(self,f,thresholdsize=THRESHOLDSIZE, buffersize=BUFFERSIZE, tb=TB, sed=SED, bottomhash=False,st_block_byte_size=512): self.apath = Path(f).absolute() # path is of type PosixPath ext = self.apath.suffix - self.issyml = self.apath.is_symlink() # is a symbolic link - st = os.stat(self.apath) # gather all stats + self.fld = get_type(self.apath) # get if it is a file or directory or link or unknown or absent + st = self.apath.stat(follow_symlinks=False) # gather stat results self.size = st.st_size # size in bytes + self.calculated_size = st.st_blocks * st_block_byte_size # st_blocks gives number of 512 bytes blocks used self.dev = st.st_dev # Device id self.inode = st.st_ino # Inode self.nlink = st.st_nlink # number of hardlinks @@ -54,39 +74,40 @@ def initialize(self,f,thresholdsize=THRESHOLDSIZE, buffersize=BUFFERSIZE, tb=TB, self.ctime = convert_time_to_age(st.st_ctime) # creation time self.uid = st.st_uid # user id self.gid = st.st_gid # group id - try: - with open(self.apath,'rb') as fh: - if ext in sed: - if self.size > tb: - data = fh.read(thresholdsize) - data = fh.read(buffersize) - self.xhash_top = xxhash.xxh128(data,seed=SEED).hexdigest() - if bottomhash: - fh.seek(-1 * buffersize,2) + if self.fld == "f": + try: + with open(self.apath,'rb') as fh: + if ext in sed: + if self.size > tb: + data = fh.read(thresholdsize) data = fh.read(buffersize) - self.xhash_bottom = xxhash.xxh128(data,seed=SEED).hexdigest() + self.xhash_top = xxhash.xxh128(data,seed=SEED).hexdigest() + if bottomhash: + fh.seek(-1 * buffersize,2) + data = fh.read(buffersize) + self.xhash_bottom = xxhash.xxh128(data,seed=SEED).hexdigest() + else: + self.xhash_bottom = self.xhash_top else: + data = fh.read() + self.xhash_top = xxhash.xxh128(data,seed=SEED).hexdigest() self.xhash_bottom = self.xhash_top else: - data = fh.read() - self.xhash_top = xxhash.xxh128(data,seed=SEED).hexdigest() - self.xhash_bottom = self.xhash_top - else: - if self.size > buffersize: - data = fh.read(buffersize) - self.xhash_top = xxhash.xxh128(data,seed=SEED).hexdigest() - if bottomhash: - fh.seek(-1 * buffersize,2) + if self.size > buffersize: data = fh.read(buffersize) - self.xhash_bottom = xxhash.xxh128(data,seed=SEED).hexdigest() + self.xhash_top = xxhash.xxh128(data,seed=SEED).hexdigest() + if bottomhash: + fh.seek(-1 * buffersize,2) + data = fh.read(buffersize) + self.xhash_bottom = xxhash.xxh128(data,seed=SEED).hexdigest() + else: + self.xhash_bottom = self.xhash_top else: + data = fh.read() + self.xhash_top = xxhash.xxh128(data,seed=SEED).hexdigest() self.xhash_bottom = self.xhash_top - else: - data = fh.read() - self.xhash_top = xxhash.xxh128(data,seed=SEED).hexdigest() - self.xhash_bottom = self.xhash_top - except: - sys.stderr.write("spacesavers2:{}:File cannot be read:{}\n".format(self.__class__.__name__,str(self.apath))) + except: + sys.stderr.write("spacesavers2:{}:File cannot be read:{}\n".format(self.__class__.__name__,str(self.apath))) def set(self,ls_line): original_ls_line=ls_line @@ -105,9 +126,9 @@ def set(self,ls_line): self.nlink = int(ls_line.pop(-1)) self.inode = int(ls_line.pop(-1)) self.dev = int(ls_line.pop(-1)) + self.calculated_size = int(ls_line.pop(-1)) self.size = int(ls_line.pop(-1)) - issyml = ls_line.pop(-1) - self.issyml = issyml == 'True' + self.fld = ls_line.pop(-1) self.apath = Path(";".join(ls_line)) # sometimes filename have ";" in them ... hence this! return True except: @@ -119,8 +140,9 @@ def str_with_name(self,uid2uname,gid2gname):# method for printing output in mime # return_str = "\"%s\";"%(self.apath) # path may have newline char which should not be interpretted as new line char return_str = "\"%s\";"%(str(self.apath).encode('unicode_escape').decode('utf-8')) - # return_str += "%s;"%(self.issyml) + return_str += "%s;"%(self.fld) return_str += "%d;"%(self.size) + return_str += "%d;"%(self.calculated_size) return_str += "%d;"%(self.dev) return_str += "%d;"%(self.inode) return_str += "%d;"%(self.nlink) @@ -137,8 +159,9 @@ def __str__(self): # return_str = "\"%s\";"%(self.apath) # path may have newline char which should not be interpretted as new line char return_str = "\"%s\";"%(str(self.apath).encode('unicode_escape').decode('utf-8')) - return_str += "%s;"%(self.issyml) + return_str += "%s;"%(self.fld) return_str += "%d;"%(self.size) + return_str += "%d;"%(self.calculated_size) return_str += "%d;"%(self.dev) # device id return_str += "%d;"%(self.inode) return_str += "%d;"%(self.nlink) @@ -151,12 +174,27 @@ def __str__(self): return_str += "%s;"%(self.xhash_bottom) return return_str - def get_paths_at_all_depths(self): # for files - return self.apath.parents[:-1] # remove the last one ... which will be '/' + def get_paths_at_all_depths(self): # for files and folders + p = self.apath + paths = [] + if self.fld == "d": + paths.append(p) + paths.extend(p.parents[:-1]) # remove the last one ... which will be '/' + return paths def get_paths(self,mindepth,maxdepth): - parents = list(self.apath.parents[0:-1]) - parents = list(filter(lambda x:get_folder_depth(x) <= maxdepth,parents)) - parents = list(filter(lambda x:get_folder_depth(x) >= mindepth,parents)) - return parents + paths = self.get_paths_at_all_depths() + paths = list(filter(lambda x:get_folder_depth(x) <= maxdepth,paths)) + paths = list(filter(lambda x:get_folder_depth(x) >= mindepth,paths)) + return paths + def get_depth(self): + p = self.apath + try: + if p.is_dir(): # folder + return len(list(p.parents)) + else: # file + return len(list(p.parents)) - 1 + except: + print('get_file_depth error for file:"{}", type:{}'.format(path, type(path))) + exit() \ No newline at end of file diff --git a/src/Summary.py b/src/Summary.py index fe5ab54..28435fa 100644 --- a/src/Summary.py +++ b/src/Summary.py @@ -33,6 +33,7 @@ def __init__(self,path): self.ndup_files = 0 self.non_dup_Bytes = [] self.dup_Bytes = [] + self.folder_Bytes = 0 self.non_dup_ages = [] self.dup_ages = [] self.non_dup_age_scores = [] @@ -71,7 +72,7 @@ def print_header(self): def __str__(self): dup_Bytes = sum(self.dup_Bytes) - tot_Bytes = sum(self.non_dup_Bytes) + dup_Bytes + tot_Bytes = sum(self.non_dup_Bytes) + dup_Bytes + self.folder_Bytes try: dup_mean_age = sum(self.dup_ages)/len(self.dup_ages) except ZeroDivisionError: diff --git a/src/dfUnit.py b/src/dfUnit.py index 6be1a68..73c9e1b 100644 --- a/src/dfUnit.py +++ b/src/dfUnit.py @@ -3,7 +3,7 @@ def get_filename_from_fgzlistitem(string): string = string.strip().split(";")[:-1] - for i in range(9): + for i in range(11): dummy = string.pop(-1) filename = ";".join(string) return filename @@ -12,12 +12,13 @@ def get_filename_from_fgzlistitem(string): class dfUnit: def __init__(self,hash): self.hash = hash # typically hash_top + "#" + hash_bottom - self.flist = [] # list of _ls files with the same hash - self.fsize = -1 # size of each file + self.flist = [] # list of catalog files with the same hash + self.fsize = -1 # calculated size of each file self.ndup = -1 # files in flist with same size, but different inode (they already have the same hash) self.ndup_files = -1 # number of duplicate files ... used for counting duplicate files self.ndup_inode = -1 # number of duplicate inodes ... used for counting duplicate bytes self.size_set = set() # set of unique sizes ... if len(size_set) then split is required + self.calculated_size_list = [] self.uid_list = [] # list of uids of files added self.inode_list = [] # list of inodes of files added self.oldest_inode = -1 # oldest_ ... is for the file which is NOT the duplicate or is the original @@ -33,6 +34,7 @@ def add_fd(self,fd): self.flist.append(fd) # add size if not already present self.size_set.add(fd.size) + self.calculated_size_list.append(fd.calculated_size) # add uid self.uid_list.append(fd.uid) # add inode @@ -71,7 +73,7 @@ def compute(self,hashhashsplits): self.ndup = len(self.inode_list) - 1 #ndup is zero if same len(size_set)==1 and len(inode_list)==1 self.ndup_inode = len(set(self.inode_list)) - 1 self.ndup_files = len(self.inode_list) - 1 - self.fsize = self.flist[0].size + self.fsize = self.flist[0].calculated_size return split_required def get_user_file_index(self,uid): @@ -87,10 +89,10 @@ def get_user_file_index(self,uid): def __str__(self): - return "{0} : {1} {2} {3}".format(self.hash, self.ndup, self.fsize,"##".join(map(lambda x:str(x),self.flist))) + return "{0} : {1} {2} {3}".format(self.hash, self.ndup_inode, self.fsize,"##".join(map(lambda x:str(x),self.flist))) def str_with_name(self,uid2uname, gid2gname,findex): - return "{0} : {1} {2} {3}".format(self.hash, self.ndup, self.fsize,"##".join(map(lambda x:x.str_with_name(uid2uname,gid2gname),[self.flist[i] for i in findex]))) + return "{0} : {1} {2} {3}".format(self.hash, self.ndup_inode, self.fsize,"##".join(map(lambda x:x.str_with_name(uid2uname,gid2gname),[self.flist[i] for i in findex]))) class fgz: # used by grubber @@ -109,10 +111,10 @@ def __str__(self): outstring=[] outstring.append(str(self.hash)) outstring.append(str(self.ndup)) - outstring.append(get_human_readable_size(self.totalsize)) - outstring.append(get_human_readable_size(self.filesize)) + outstring.append(str(self.totalsize)) + outstring.append(str(self.filesize)) outstring.append(get_filename_from_fgzlistitem(self.of)) - outstring.append(";".join(map(lambda x:get_filename_from_fgzlistitem(x),self.fds))) + outstring.append("##".join(map(lambda x:get_filename_from_fgzlistitem(x),self.fds))) return "\t".join(outstring) # return "{0} {1} {2} {3} {4}".format(self.hash,self.ndup,get_human_readable_size(self.totalsize), get_human_readable_size(self.filesize), ";".join(map(lambda x:get_filename_from_fgzlistitem(x),self.fds))) # return "{0} {1} {2} {3} {4}".format(self.hash,self.ndup,self.totalsize, self.filesize, ";".join(map(lambda x:get_filename_from_fgzlistitem(x),self.fds))) @@ -135,90 +137,7 @@ def set(self,inputline): self.ndup = total_ndup # these are user number of duplicates/files self.of = fds.pop(0) # one file is the original self.fds = fds # others are dupicates - inodes_set = set() - for f in fds: - l = f.split(";") - inodes_set.add(l[-7]) - self.totalsize = self.ndup * self.filesize - return True - except: - sys.stderr.write("spacesavers2:{0}:files.gz Do not understand line:{1} with {2} elements.\n".format(self.__class__.__name__,original_line,len(inputline))) - # exit() - return False - - -class FileDetails2: - def __init__(self): - self.apath = "" - self.size = -1 - self.dev = -1 - self.inode = -1 - self.nlink = -1 - self.mtime = -1 - self.uid = -1 - self.gid = -1 - self.uname = "" - self.gname = "" - - def set(self,fgzline): - original_fgzline=fgzline - # print(ls_line) - try: - fgzline = fgzline.strip().replace("\"","").split(";")[:-1] - if len(fgzline) < 10: - raise Exception("Less than 10 items in the line.") - self.gname = fgzline.pop(-1) - self.uname = fgzline.pop(-1) - self.gid = int(fgzline.pop(-1)) - self.uid = int(fgzline.pop(-1)) - self.mtime = int(fgzline.pop(-1)) - self.nlink = int(fgzline.pop(-1)) - self.inode = int(fgzline.pop(-1)) - self.dev = int(fgzline.pop(-1)) - self.size = int(fgzline.pop(-1)) - apath = ";".join(fgzline) - apath = apath.strip("\"") - self.apath = Path(apath) # sometimes filename have ";" in them ... hence this! - return True - except: - sys.stderr.write("spacesavers2:{0}:catalog Do not understand line:\"{1}\" with {2} elements.\n".format(self.__class__.__name__,original_fgzline,len(fgzline))) - # exit() - return False - -class fgzblamer: # used by blamematrix - def __init__(self): - self.hash = "" - self.ndup = -1 - self.users = set() - self.folders = set() - self.bm = dict() - self.fds = [] - - def set(self,inputline,depth): - original_line = inputline - try: - inputline = inputline.strip().split(" ") - if len(inputline) < 5: - raise Exception("Less than 5 items in the line.") - self.hash = inputline.pop(0) - dummy = inputline.pop(0) - self.ndup = int(inputline.pop(0)) - if self.ndup == 0 or self.ndup == 1: return False - self.filesize = int(inputline.pop(0)) - full_fds = " ".join(inputline) - fds = full_fds.split("##") - for f in fds: - fd = FileDetails2() - fd.set(f) - self.users.add(fd.uname) - fad=get_folder_at_depth(fd.apath,depth) - self.folders.add(fad) - if not fd.uname in self.bm: - self.bm[fd.uname] = dict() - if not fad in self.bm[fd.uname]: - self.bm[fd.uname][fad] = 0 - self.bm[fd.uname][fad] += self.filesize - self.fds = [] + self.totalsize = total_ndup * self.filesize return True except: sys.stderr.write("spacesavers2:{0}:files.gz Do not understand line:{1} with {2} elements.\n".format(self.__class__.__name__,original_line,len(inputline))) diff --git a/src/utils.py b/src/utils.py index 279046d..68c4b51 100644 --- a/src/utils.py +++ b/src/utils.py @@ -72,18 +72,6 @@ def get_folder_depth(path): return len(list(path.parents)) -def get_file_depth(path): -# example -# >>> len(list(Path("/f1/f2/f3/f4/a.xyz").absolute().parents))-1 -# 4 -# a.k.a. file a.xyz is 4 folders deep - try: - return len(list(path.parents)) - 1 - except: - print('get_file_depth error for file:"{}", type:{}'.format(path, type(path))) - exit() - - def get_timestamp(start): e = time.time() return "%08.2fs" % (e - start)