From 258e17678077acf467431ce5d1427d8c17f41c2c Mon Sep 17 00:00:00 2001 From: Gregor Maclaine Date: Wed, 2 Aug 2023 05:06:46 +0100 Subject: [PATCH 1/4] Added concurrent information to single bars --- lib/generic-bar.js | 48 +++++++++++++++++++++++++++++++++++++++++++++- lib/single-bar.js | 9 +++++++-- 2 files changed, 54 insertions(+), 3 deletions(-) diff --git a/lib/generic-bar.js b/lib/generic-bar.js index 2e5d11e..1c508c3 100755 --- a/lib/generic-bar.js +++ b/lib/generic-bar.js @@ -48,6 +48,18 @@ module.exports = class GenericBar extends _EventEmitter{ // use default formatter or custom one ? this.formatter = (typeof this.options.format === 'function') ? this.options.format : _formatter; + + /** + * The information to show below progress bar + * @type {string | null} + */ + this.concurrentInfo = null; + + /** + * The concurrent information has changed and should be rerendered next render + * @type {boolean} + */ + this.concurrentInfoUpdated = false; } // internal render function @@ -77,7 +89,7 @@ module.exports = class GenericBar extends _EventEmitter{ || (this.options.noTTYOutput && !this.terminal.isTTY()); // string changed ? only trigger redraw on change! - if (forceRedraw || this.lastDrawnString != s){ + if (forceRedraw || this.lastDrawnString != s || this.concurrentInfoUpdated) { // trigger event this.emit('redraw-pre'); @@ -93,6 +105,22 @@ module.exports = class GenericBar extends _EventEmitter{ // store string this.lastDrawnString = s; + // check if concurrent text needs to be rendered + if (this.concurrentInfo !== null) { + // reset cursor to start of next line + this.terminal.cursorRelative(-s.length, 1); + + // write concurrent info text + this.terminal.write(this.concurrentInfo); + this.terminal.clearRight(); + + // reset cursor to previous line + this.terminal.cursorRelative(0, -1); + + // concurrent info is now up to date + this.concurrentInfoUpdated = false; + } + // set last redraw time this.lastRedraw = Date.now(); @@ -231,4 +259,22 @@ module.exports = class GenericBar extends _EventEmitter{ // add new value; recalculate eta this.eta.update(Date.now(), this.value, this.total); } + + /** + * Sets the information that is given as additional concurrent information + * below the progress bar. It is cleared once the bar completes. + * @param {string} text The info shown below the progress bar + */ + setConcurrentInfo(text) { + this.concurrentInfoUpdated = this.concurrentInfo !== text; + this.concurrentInfo = text; + } + + /** + * Clears the additional concurrent information. + */ + clearConcurrentInfo() { + this.concurrentInfoUpdated = this.concurrentInfo !== ''; + this.concurrentInfo = ''; + } } diff --git a/lib/single-bar.js b/lib/single-bar.js index e8235e4..85cc729 100644 --- a/lib/single-bar.js +++ b/lib/single-bar.js @@ -131,10 +131,15 @@ module.exports = class SingleBar extends _GenericBar{ // clear line on complete ? if (this.options.clearOnComplete){ + // clear progress bar (And any information below) and remain on same line this.terminal.cursorTo(0, null); + this.terminal.clearBottom(); + } else if (this.concurrentInfo) { + // clear the concurrent information and begin on new line + this.terminal.cursorRelative(0, 1); this.terminal.clearLine(); - }else{ - // new line on complete + } else { + // start on next line this.terminal.newline(); } } From 02f47dc2258e9484a732bcc9c993052f7b34c723 Mon Sep 17 00:00:00 2001 From: Gregor Maclaine Date: Wed, 2 Aug 2023 05:07:06 +0100 Subject: [PATCH 2/4] Added example for single bar with concurrent info --- .gitignore | 3 ++- examples/example-concurrent-info.js | 36 +++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 1 deletion(-) create mode 100644 examples/example-concurrent-info.js diff --git a/.gitignore b/.gitignore index a8ac8ca..576d32d 100755 --- a/.gitignore +++ b/.gitignore @@ -8,4 +8,5 @@ node_modules* .tmp* intern_* dev.js -yarn-error.log \ No newline at end of file +yarn-error.log +.DS_Store \ No newline at end of file diff --git a/examples/example-concurrent-info.js b/examples/example-concurrent-info.js new file mode 100644 index 0000000..8c6b0df --- /dev/null +++ b/examples/example-concurrent-info.js @@ -0,0 +1,36 @@ +const cli_progress = require('../cli-progress'); + +// Generate random file names using random hexadecimal names +const random_file_names = Array(10).fill(0).map(() => + Math.floor(Math.random() * Math.pow(16, 6)).toString(16) + '.txt' +); + +const bar = new cli_progress.Bar({ + format: 'Files [{bar}] | {percentage}% | {value}/{total}', + hideCursor: true, + barCompleteChar: '\u2588', + barIncompleteChar: '\u2591', + stopOnComplete: true, + + // If clear on complete then both bar and info are cleared + // clearOnComplete: true, + + // forceRedraw: true +}); + +console.log('Downloading files..'); +bar.start(200, 0); + +const timer = setInterval(() => { + if (bar.value < bar.total) { + bar.increment(); + + const current_file = random_file_names[Math.floor(bar.value / 20)]; + bar.setConcurrentInfo(` --> Downloading ${current_file}...`); + } + + if (!bar.isActive) { + clearInterval(timer); + console.log('Download complete!\n'); + } +}, 15); From 9b7d4cb76c410b8738d763f4cd15c8cfe3de72e4 Mon Sep 17 00:00:00 2001 From: Gregor Maclaine Date: Wed, 2 Aug 2023 05:28:46 +0100 Subject: [PATCH 3/4] Prevent user from using concurrent info in multibars --- lib/generic-bar.js | 15 +++++++++++++++ lib/multi-bar.js | 7 +++++-- lib/options.js | 2 ++ 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/lib/generic-bar.js b/lib/generic-bar.js index 1c508c3..a5d412e 100755 --- a/lib/generic-bar.js +++ b/lib/generic-bar.js @@ -49,6 +49,13 @@ module.exports = class GenericBar extends _EventEmitter{ // use default formatter or custom one ? this.formatter = (typeof this.options.format === 'function') ? this.options.format : _formatter; + /** + * Whether the progress bar should be able to show concurrent info or not. + * E.g. In multibars, each bar should not be able to have concurrent text + * @type {boolean} + */ + this.allowConcurrentInfo = this.options.allowConcurrentInfo; + /** * The information to show below progress bar * @type {string | null} @@ -266,6 +273,10 @@ module.exports = class GenericBar extends _EventEmitter{ * @param {string} text The info shown below the progress bar */ setConcurrentInfo(text) { + if (!this.allowConcurrentInfo) { + return; + } + this.concurrentInfoUpdated = this.concurrentInfo !== text; this.concurrentInfo = text; } @@ -274,6 +285,10 @@ module.exports = class GenericBar extends _EventEmitter{ * Clears the additional concurrent information. */ clearConcurrentInfo() { + if (!this.allowConcurrentInfo) { + return; + } + this.concurrentInfoUpdated = this.concurrentInfo !== ''; this.concurrentInfo = ''; } diff --git a/lib/multi-bar.js b/lib/multi-bar.js index d40ccfc..248bce8 100644 --- a/lib/multi-bar.js +++ b/lib/multi-bar.js @@ -47,9 +47,12 @@ module.exports = class MultiBar extends _EventEmitter{ // global options this.options, - // terminal instance { - terminal: this.terminal + // terminal instance + terminal: this.terminal, + + // concurrent text in multibars is not defined behaviour + allowConcurrentInfo: false }, // overrides diff --git a/lib/options.js b/lib/options.js index 4671d4a..4038a42 100644 --- a/lib/options.js +++ b/lib/options.js @@ -105,6 +105,8 @@ module.exports = { // autopadding character - empty in case autopadding is disabled options.autopaddingChar = options.autopadding ? mergeOption(options.autopaddingChar, ' ') : ''; + options.allowConcurrentInfo = 'allowConcurrentInfo' in options ? options.allowConcurrentInfo : true; + return options; } }; \ No newline at end of file From 95b6759fc2c535a2de2ead5406ca0023fb449a24 Mon Sep 17 00:00:00 2001 From: Gregor Maclaine Date: Wed, 2 Aug 2023 05:40:55 +0100 Subject: [PATCH 4/4] Update README.md to include concurrent info Added concurrent info example pic to README Reset readme to prev style --- README.md | 23 +++++++++++++++++++++++ assets/concurrent-info.png | Bin 0 -> 26291 bytes 2 files changed, 23 insertions(+) create mode 100644 assets/concurrent-info.png diff --git a/README.md b/README.md index e78147a..a3aedc3 100755 --- a/README.md +++ b/README.md @@ -35,6 +35,7 @@ Features * Preset/Theme support * Custom bar formatters (via callback) * Logging during multibar operation +* Concurrent updatable progress information below progressbar Usage ------------ @@ -160,6 +161,28 @@ Note: you may want to increase `etaBuffer` size - otherwise it can cause `INF` e .updateETA(); ``` +### ::setConcurrentInfo() + +Sets the text that is written below the progress bar that can be updated while the process is continuing. + +For example, the text could track which file is currently being downloaded during a multi-file synchronous download process. + +```js +const currentFile = filenames[i]; +.setConcurrentInfo(` --> Downloading ${currentFile}...`); +``` + +Concurrent Info example: + +![](assets/concurrent-info.png) + +### ::clearCurrentInfo() + +Clears any concurrent text written below the progress bar. + +```js +.clearConcurrentInfo(); +``` Multi Bar Mode ----------------------------------- diff --git a/assets/concurrent-info.png b/assets/concurrent-info.png new file mode 100644 index 0000000000000000000000000000000000000000..7fdb90a47137c9b3e8e0e55560fbf6791501bac5 GIT binary patch literal 26291 zcmeFYWk6iX)&+_N3m)7WcL)$5xVyVUaCdh|aCZsr?(XjH4#C~sUuW*jeD}`1@7MeL zy3grTU8m|)*RHBvd#|-SSXNpD9u^xG1Ox0MQ9(%CYhf^@~Iu(Oj`qUVzLevFb_V$eH>6#YNzlh0#k#?#cJxNtotxetw%&sX z$+n)Wm|wT?ClTQg{nELz63Rj}ycMpFY1 z8Qx6-Gl(4VD(G!9vgE3$Fn6?WzHa2U#;#oUbDpg2#Ud)HLS8nmF5wTz4Fs?cBBS*hgykdy0xfsVtJ@pKrUdUlZg zpDuQ$(ei=RbPx~pSuip`kw1egcjE7De`xg~fCkF~p!9wxiTcprLj||Vo%ns|8+#JC zI3JrTtg>(2H{wMwC!e)%JSHH4T`)EuG$9hZ9BnYp(xop@ZhV|G5&4i%_yrDvko6)K z0n$M@-GX3IvLx7Iywg#VBv8o2b_VQ>7?dIj#OBdsqVUy-ru@=?{b;8hmMf$~{&hfx z?8m(9=0Zxd&^2yKx$69dD;5$7Kg@GFe zxKS*9JqsFiiGgYcN)}Y=9;!;SQUvpWiASn=Uq^icTO#QJtVX8QE@T(R@gDL`rc0p* zbq^@*$c*laEyPRw7iwSO&xBu*Jz#LVG5Ha68MESK`4)x0ihhNkkSE{7ix!4g*U}G#5{y8ioM~J(i+no zlcJTR)siYz&Q{Ket^z_FEtsbEtIb91$d2)Gj6}Cd#@nmW* z{MSBvq+?dJ)d^+j8lff33MJwtV#oQ)6)alrxlW}{zIQ~YY0LX{8OKo$7LNRm5A4?t z^#`f5u95=>$_^}PA{i1J;yhC4v!qAMhjtG3jw6oF$MuJI2Zsl)2YCllQzg?J*$Y{b zhbu?+H`lj`2j>eNS?@!gvp$A^&#ES}#x{Mw+BQG;00ew>lQ;2ujsr5nFom;(U4=)& zu*1%9w)-RcFZ*M|SurzM&hYa&My)ZeRhKGXd(M(F$s)*L$Yvz#lWKq7{QQ|5kRmR* zkd*%Alx2n$j&X!p!_;ZEbR^XZ{~H~nj;Yt^3#33~m);H&6;=Tz7dja_GP+&p7`i38 zXM$70Py%U!JI%Rk}`FfdZ}CKSeb~1Ohb8HyS_lZ?lQEc@=9u*tF^gtiW$d7 zeb-%6S{B|w`C|F}SvuDk_oP>hXWc6^R5thw;e>8mkDaNQWjN_FZ3R{`8 z8G$tB8IvYwtJ{N=aWT_K(_qv5V^(OpM6E=y#E+2@)^v^d6=vt3?n%!y_rmuJ_|o`bk?{BpoQLT-T>I|zE?$>ccQI~r zu8yu6?#6Bv*X={IhW!i}3=@w?9^XBU9&zs;4~};=4q7(uWq6D`I6Kn3CPbFPQNotl zkE%NIcow{CyhT8W0ZiW%cttXW0IZel7jjWbNIWJQlS~QV)QNSWw^WPFs@NW%AGlT$ zxqf(ZLcqZwQo@X%gHmu65F!sXHDYV~WsG`oIbXScfvnY!1r(CcM@uL2~Xwh-NUrE0C_HVRz!J~TcQ zKNP?aqvn&RO68JEi>@X=&{2Lh6`Ni&cs6jglL#>q7Z#Tqex8k*-7Uh?7Y<8i*wg!I z`;(%KAuTRFrk%FU+2UYPNuPs>lS!P(Dy#;F)o}IkvVZ$}fFL=O&6i`7myD2!+1_~1 z*ovm%=SoW7kb2@=kN&mtwf5DI2kJ*HFz+tAt{RK?lij5W`xkrV9S0b2f3$8ZWQ|(o z8+KMAXZ^G1*2UIS*Vo6QM|ap+SVp*?z3f|@mqo!ws0ET1iC@LUN%3Mm$jg4t5{JiF z#S&KAR`>I3J;-fPH6*^1c&mPrRaCmswHw|6SEwxrDyWrqOl`I~s@baC(#hYPahXxi z*O1I$dfoguA2!Amovg;BVWc+pleNU&>EQ&=p2GfW??rh_y}EU$qN&I}Wj}d5h3ouM zW|Lr-#~eFJWh5)sZBgKU?LhWsOIvHH^59BAIfrw+4+ z_Qu`gshlJ1?kB15O+EXb6RcX_v`rch9IM*rYHoj7r+464T$`12?06PkR!{8i-N~Jb zR6uC6*)s1OC7Y+3V^j=iT6aWyY|oE{rQkI@G^B5gcf3AHPo=fD)SM%q#jhs)s3 z@ZFvxbetbv9DTj|yrX-Z(<|akaE;&LLF9hbWWTPkJQHHPH({3E!o{xmrXNRz7+k(#I2K}aZ6LbS3pp;Hy-aV9$mwZuK;b3*{<{Z2df81dsLq`4c%wRM`qm$Y!Pt45LD*bnScOk zwS_Y)DF)gdr61JmtF`WgusUdGV&3bk=iKY7PJQP$-E$Ys(i1*3em}0B{6=~;NVQ)Z zLDf93bOQwEyvV*#50`KB)AmtQb7n{wK=&iWP*u!GN(zJun1%*{0L2D@1g1cNCpRe0 z-)Uh`3J~x=^1(nr0!=|6{wyO6y#9Vg0nguc{&fY92>^itenSDCE}39|m4*<_1pg}y z5(K;l!lxi0CI-AJ=-U|@TG^XeJ9LhVzyUL0Y(&-UK|s(+f1jXY@+23)=P#Hlsye7j zNwVu(Thi$oSnCZGqrIrwYCEMey*;bwW9+U z5z+64{(k-IcN)5w{$ER0_J4K@*g^W=cjy`DKGXmGY+zN+-?{9vrY?pSYJ#SgK$!vC z;AUWA;ryfgf8F`N7XPiL>c7?e%=RBu|LxX4t18(W+6h=&0^4-p{=f11v)zBc`DaB= z`rlpuH&Ogc&VS?r1v3Pgw!S5!X~uMiF=g&ayvVg1}D-;Q9LsJjwId zxlcaauY$a z0uZKQppR%Nf?Pn6kEZZf7Akj;76Moispa(900I6`~PkWnDhTP_rJvQ|4En^p9*z4K-auC zUhB)Op5Hjw9gpHHwT+}o-&`Drlc_PZ+U)$D&Xy0SKEqu0pZ|uvZ$x?no zmJ7ey8PflF-*Vp0++7Z~&In)UdK7|p_0KW)fq5W}YP}RzK9}2KV!}d zls8yk_1}VItvHQ}jX|GUrsr-L8wm^U3&kja*+w;7ct^VDuJ$yK3}7I&{eVWfg(PY; zk<6!2Z*feKFUb1>y_I1gc+95BsUSIv+6&-r=+{Xi4- z#bh#y-TBC9Az!k^>$O>x);1vE`26|QLX<(?V7^-?WMkL+zd=?D2CKjvzvrX zSqCyExh8*VzD#H33f5l`UF0XT`KCkRIeb{&?5twJBb5M#D5oyA__ZQKH`YI!)kKE= z$(v2*cD*OHT&asktNBHT)bP>X7Ys6t0Re|4Bm|w3Y8y!uSGCnMnf04dS7)}r1f>YV zz;Lwv{>0RR2Fp}(jd56XxyHRU@d?#0xEa~xg7QW}#DBK)$=3&lgj(h82ka*bQPSRG zFmwo5bei09!ind*_e9|^Ofzvf|G|gL*doD86uUxTi_WPkQgL*zNL4QN4ofJ_HkfM=AgZrI3o0}$_&3|#8T*5Zkw4))r_;C{P757P*X5AU zeU~Sro|wr55y<(69#M%t=P(gIm{MPQ` z)+3;$z@tK;<2xL}@X5Q;u|g&v4k#JxjYjmQ-CZo6Wj>S8rQU){fXeuiX4$p!)i7J;8H$ zvQ$HbJzLXp9mg?%A5Nv>6=nxV-1mHUnwQ4m>{7>GC>~FBbJ1g1BnUGQQo>XqGsAGn z(X(PqSC~2Z^*@Epn?Q=>;G1i|Up|}pHuHhkSeuPXxm2|3bvQ$QZ&DBUnzC?$|BO|GFvMBfl4$-wHmT4NdrE)W^N->|awgs50PHOmW!-iLm zpPvghn_bvSRiW3j-Tc6o>1+F|+w|r3zzo`bplNfz;P;B_xD{*$&h+k{ktJq{KtzIU zz8_GFdquqg-M{Qd5-cT4#uV{0T+7d1tzr8HA}3>!KY${E{QKeSg96>m+uf$*g#NYF ze_*l7zO?==HQUx{^yF+eBGbaI? zUD5}HkQ!Rl75WGwBK(H2ZNa@xYV!vh(x`)0L*3Irj!0_XW_r)3-Vihd=345MA2c4j zqsat6AD%x{5=-!3H(=8>@sJZpNjCo3mt6TJ@L3+6UA&?&^q7Ng_o5X=8_h(vL z5^oa@>K1Ch%2?=IFHqvCRkYCx<}y6RM-u6owr~qIn;6?zJFD3Jw)e-=;!9klQ#twS z%oiBSV7EL}viZk;))nrQJ@*=>d~uz*SltTe?RI>;xNE-%ZB;+)zFk^}st{#&yTPa$ z%Oe9WzQrWO)N?bM)bnGxW(U(^+4gKXu2xMp{W%o4FA{yY_4qjLn$}V=w%$q0%m*W! zX*||dRa>F^%kyO#CMl|}w*@W%C84JRFQXJwv1$YG2Z?9X%`KZHDixE%@$b25El!hM z_p8M9D}G|W<-)h*J5(spB!?G-|1gUHJ`jw8fMizZtV-`_6{i%P`GJtrk4Fd7O*nHE z8?wS`xLAxgZ4P$~WYVIa^u%n{0vZGy&Ze~kIBL%YCpc$B16(ymA7Ee@PmTiLs!MVD zYhg)vUTf3HB)>GUYBruIb$6Rq4d;qXP^cuvxURRmJoN~iOSU+jnr`y%m&fa8yTfMX zl$Um|7_vJ?%$B6|7TE8P%PBfwC~#Yc9?TY{MDK+c{tA~^=3Py+g+c90D3!0Sc;Zq? zt5B;UyFHmw5&A(Eg^AIKR;Y0=7IL&M&_52l&_2b`;Ho~-9O~XPTTW}eZ)#uwMd@Rs zapG${`K!@k!ctWgGaQ$pA4v?QKr(Y@$6#jncFu5$K`U)pQ&)Mz>p8rLj_4nX9e^YX zhD8)5nZiD!3VC&0VLD4+-@p(6d7UU*uGwVpGH}W>nJcy(&WZNT9arGPMm-M_j~hf@ z?nzd0cZ8_7u8d!#{eGW>$Lwk1L%wyp5MsP*l2u4z!%#4)lEQ4U5{}!Yf1;r#hWQPK ztudVna2)wO-3Er6RlGaI@z`sbmmSeB?)qj3@W-Ei(P*`$UM+Z+U=YO*IPSOd#Ijhg z$CW21Gp!dq`?sNTGx7s2Z`%*_lUcnHELR^4o2w4&XH%+j%?CsMMroo*Xw~RcTrX^R zQ0jfTA06^e2Xk`VWYgGXhFjy}-eq47Rx~;sh&wbpQ!MT3F$9SIQ>lYMKkxwrAYy>_ zPH4&}Oah&-YhDI$3C z;BmPCfydixRG}g;{!a}JiZn>^d-xANkUHjMo?Lygy>iemeUfO7cA?I+u6Z<@5&p@s zK&W`I&KVGiNz^uSK>wimIzSL>I=ur^O}b{q-*A@pku|rO*X~!R*QTB0MHzL9%#r^% z)nJmuT7)Zc6vX#|Q)<*p7M#1$SYi#_cE}OST zbN;L=d@pVE70`&B=g=~o9*x)%;8li&*JZQ<>tRAw7rUuykSND@R5Alrz)b66wVHYh0W6%;dD@>xT#s>}!VMbP5D0grQ|$scIbm-^XT#~i#RMOHNsu^Q zcw46pxBMvk=SlUW=)hhKGdeD=vsMyq3~>Y+_P2lwyM%XZ#Pe`5i;3&?rp8WlTshOm zNN^51B;3(O^vZ~)T9?4vK-o9fGDXyE^#QU%#F9Mf!YnSDSQu!9mWE&1-(62YRaN)G zez5(|@$&US{k@?ys8pKWlGp0>LD>PA{R%?Y+i=rqS7Atc{8pB)x;<$LnrVML-Qvh5 zj;|Rut7lKFd{ZU)>UczgMyoElR|O&~v`ABx5TCp?um%7Q5LBe`bT8#iCpcnp)=24zyu3! zxaBj+>w21_xu;`s?$jS!D)pav+#V?j_|@z+d@AuUn=d|{ZL2St3R=yTd9Qo!LUqVz$tfYCZAk>fle-t z%iZbenTI>3+~|0|jQsf3e3$3o-1~jdWZMd;(z2XOZ@HScL@avC%Og~=0 z@6JtWZ7*9&$O$XEe(v#Ki+t^V3tVHcUMCuk<%k?rzw1I#ui0bDSxjBJK3sP{kH6fd zPLK<2&=6n9DN}C%7{)O(-v+7nX9R|zx$`C*6D$Nq;Bgq$BGdR9oFrW;Hs1(bvA;hp zZ1~GwSJ_In_;heO@O8#FX1VWddL4ibL}Wp7MX(NkyKIhJ>8jPq7_@Y+9A+xV`uDURpelhJhJ z?R`23S>V<};j8V{7yZ7Z;jc7d+=wXs8C+aoQvn4F{A~Z2v@M~$vXCfVQ}_?-vOP6@ z_2(TqMGE98&~ z%zF+x?K*R-#RY~bhX!;Pim2QDnFw<+58-n@PAD_GHO#|^fDVl9W;djsK&{h2qhD}$ zi4-NV1cvBWIUTL)Z(W+p7rSmbrLd#v%rdR5dx>(^g8pHjL>uj&&?_8|+cSkiF$xJW zjn||jSoImOF9>Z|VMx};71ktX_h@ydQrQ|*XdivLP0`lyBj$t}>tfD|)plK}qad>3 z9W7J&{u2;j#PH38Az5n{mTPmng~uLOCOV+!)il~E)SX5Rmy?6INlcJPq?1o9kFdlm z9tE0nWGdl>Uo&oZAD%|I_g~#!RE`!ZFrdPTRl$Zdq*CN!$*hNuD?iWFsKnVgdW<)g zGykHGl+P2F>s}15R?}u+u#xo^my%-E623plW-J8@R(I`rbQ;z1dPFmOlr~r55?FnC z(#wtKz(k!1HCreqejdL6w)!wtYdnFUbMD4X9+1tub;>z+8g*gMp{oaWy4uw9tr*HB zWo>0lLv%&p36{Z$fp>(HkGf{IKTZmlA69Nky*FC7+^>(#*suO3mb zu$QrW;aHnu!+5M> zxu&bDbNjpQcGLo|=d3Q~)!X=$E9T3vk0aY=6epAW?kW z_lNqFPVP~85d9RY*11%vn|9faTlk!9t+n;&au;0+(b-mtW`ngT}xy4WPYGg{MSGitKk%dNcG@eQ^lNVHt%yw8% zT>5RDLMKlgE##O-wBOZn@a+902H*Vc%Y%f>*j9mkv?Og`LY(C!|a}=cA;uO9tRL{8kIFh6LBS3F- zP0~`GSfo$F!gjMx5UUGlCTq5vC!XERD!`X2g@3)*VsIv-I?zxF3$X&rC{q(6@TgQw zfSvW!#TaIoYWrBhHBa|)(Q|*(i&|$;T~noc{D5<>1T>P0YP{SzWYh#hk9j6ZV!oQE z%xJ-olpooqx6Bc1egK0}===wW`it7v2ae>$&h>H&lHGR8&tc%$VlJqz$8b0<3)J=p zdmxpn>(#via5uCN}P;^gKjNq;R^BA@G;$mLAUgmDg zm=f|#vd+&G7Rz*L)o+PS7BWVKHXWmZR{(=z8lvkxx-ZJ1s@JJ~j=m&O_x{Pkj^~6b ztc7SSK(M61a>JWinZ<(XVwx$cI_L)EoN#OT$ns>^v-;IJF@-{^OgBM?v@YQ9G&o`I%VK}n?7$!~MN zpG4jiJD}gB%}ZVM>eUF0d;NH4HN#V0p^VD+kF|#c;wuZp&q+R=G4_j!18n`bhT})R z7##5GzHc>_=naDZ(*{Bs{0;$#GU!SPAMy$MjFZ`0xfH`|zUZvEufS>d{m8g`g2T5qSRU1OShpF{wXp-~EAh6!nTv}nDzcT6ZK>>hoQ`LaUv;|3&@i1JV;T#(Dm7tMh8dUSsf5IVvZ@?Zxd^DUl zfd&(sZ;Zqg>PM0V3tqzzj33~#O*|LFs@;5}&Kt*-9BT!(f3x57^bBzgeob66ikM#V z^*5LeNc#PVSSvD%ly}qLG|De5U}NGFW|^PhxaMUnV`a&vWMl7a)ja-|k;**!Q3mY%VsLTs}iy3?5B{a!=qniLlX|N2MxebW&g}6Y}_|V;-_aE>&VDNWItc$g2kELqEBK-k62bp^JX~!aO zO&wx*uwY*>P$U}(UKkQ5oijyz)-Ae?SVof`3t|w?&Yl$GQFfh+(d2zZ7oWhA{X?st z1gjX_DE-nl5HvhIs_k)3XREqmLVw7UliX$jmIO!u> zvY5@eYet5nYV)O1hK_Ud@$+|fc0M+d(QT!JoQ1jzQ`n~XY=DVv_fIIiz1*)^O-UVW z`NP$E^{}(%1?7{BXA%kFf(@OpF`0}cjL{vBrnE!>SqXCuGD=hAvezy9l~!4?S;&}< zx2I4#?N*bIZSIQ3#3v_+5psY07*tR#k}9vfJCgD6EO;pS+h-`w&L1#~Ts)}}k6oX> z*@IvAv>uU`Tu)}Wr@zONOXUG~E!!v{!VZ{t*_MVSL8DgACHx^W*pB-z2$1OsZIl=2 zeiu2Fu`3qI8&WA2eqKxA;dyo44tV*Rn&1?tT=o_>p22f&i&3mxBwi=zzPY(8h(mr@ zfVX10-A~U|?%jaas&Fr~-+5mMM4Aq&28t&I5aY8_Sgoi1;r0)IO+cBRE;Bpaov5`n z&e&w}`yX7I&4s_f>y)#0zd>NLn27p^eu|eOA-B%S5sAzM71?Fk&al$pCz9`%$);!6(Ns9LMF1Z|f$(nS5ph{Gd!l1+D1 ztfgpt&s-Ek;A}84-^#V!q2GtXckv;UN;RuxGqJ(NtH*R74FTqb z`df!2a>Nf{{G~(8i~e79$UJczWDG;jzz`aYGMUpQ(1n~iV8}VCE(A`HFJ?Qc!_mZn zmhIv%qNSf6c4p$Ks3tZyH)naA0J|fJ6LDToH< zNag$fRHH_;`O;~n+4(g*_L9t>f>;za%Ev*`L=o^gc}05DIaCJNs{BlL$=~gi1oztB z)KRIlo(P*DOb@F`^{}QP8ys)Iwg+VLQTikXNuWuPL~ojWKSM)=_`D$+W-beI{EhXc zqe2_{8q5wdDCUp$H~_6w@wZKPcDn~8JT%?6Wdb0J!)$sLFa!ZyFZM%L8vS91_F;%) zty>1S#u?KebWwnFJ7hNBF<0#6V2OIzV8wRxJ4w|VWx*-@_I-oZ8pqO}q2g8=ifFUb zp|lLwTqovUodWbB-HZbzX;fu!z*>v5y!bG__)<&Y0ht_a)$U#%h7Q9iSuzV(bo=v} zh5`=mrEx@2KXApEjm)uSf(_Z}vbo(FmuPCy_gn#@lH~M5!;_)(07w*I&7yj*RL5ee z&%P|U&OcmzMeLzIUZQf2>fCmLbFRLY_nt?VK0ga|-1pNDY52;bi|KuceG<-Ln#vvg$r4?SU^lf=IxmGKP9Y_$Uh~?V@c~F0qqTv3QhsXUNzs(5+ zEbqM}GYTZj!ur)T!l*`o;_Ky+V$+p=oCc=%T7z}Ps?7eFcmkDD@njETVjc=9F16Zt zD!0_Ybi`7z8C^4S6b&>9XjhOhZ>M1A9FIl*_n^Nc4%@#UyC%wS zeR%aq^&&)IanOM*3=OI`kQ*}F$Ofa!vA>6`0#)ziS)o9oO% z1Rnd$j0_KT$zrgf8J!KN^?uTk2w+*(vWa7Z87#QHU~t(~rgahMJP}1H7Aqz{-G)ko& zlvl4AG%ePa=<6>ox(Gr!)|TIp9B4oUcJboka`HTphguY!R+H+{o>kf70klm0HaLMgfB$ADtNAFF>2xcXt}vzAAMHBxcCHJ^Km+zWw$0dhkqq~SlMezuyf z)`p>o?oDV|G=APv!q;f9BCPKpY40t86JRTCr&;mP51FMD7TAMgtpMsmN)C z;s#@4-Ba&l1rv~(%fJ8dFp6prrAH6uQwbZrBP?a zcM`$I+1fhf&uFc*+-S>1N~@(;d`y?Uyl2-AOJdzR6}RrOP3u}@zEBP$!&bJcHE;O# z{ZS&U3g{r`^isx3?*2>W0=^~!b-QP{vcA1*eX}ICDiPNOf0%zEgV|WX!5x`s%s2sO zXJ($8Rnp%3V%Li)Kq8jP=o=FoD`j|-vOiqlxYjHKo3XQzbo7DgI~qw>ZfLzgJa7hT z7BY4={t2c1l1B02-OAi3)A*uPev{-OGnB$wahavImSVZmo>w%3qNJEk9aq6C5E$`g z`sUqyZ#3N+n&|Sfr^tTaYHO{ukfy{s)?|e&2AkEZ%R~T?MyD!Fx#BI(rEXBenz`U= zmkRS-PV)?C;>=dXE@}H~^B`@8p^J(q(n;wLe66RvEC<(?ljGNb_=Y!AG*eJ$JV9Yz zJ=6GBeptfGXnn@t(=xSOm*Gk~eUN58e`4wOTGxRk)+6#U>-G5_>ymf$x8dS2_ydTM zYedB)&?J^{el@FGFSQSgIO20W;-rj~mwywu%&~r#-!xR%MzNwcV&H0?N@g;?IdZ1? z=(`h&}~D^NxY9ag53ESQfybqWTrYzyKA5>C$@F4=9s^O1}QO zVkP&~b*s0Cm&Vrx9oEC%q4z0R!U)A86x~vEIe%9rm=)5;eI6d^eR<`0m>sqpNR&5d z{JA!fX2QzEB!TV((sN;#+%4ibR%`B@Fjgn=7c^0aoEE1${xE4*q;C_9mpLdOr;c$p zH%vQ9W?grBqN8BIn+^a=_ljvN&zE?4~hDTPUw z%>MqYt;sNUHR}8=n!|D;{qba-iXVvGgLs}&Pgtl z&iTbnF||B{!y0|9)m34S$zU*Zgh}?pZ%1RU@G_OA#pRL+xFCfW?DeL)ogLnu&m$*0 z`Cc8lnNjCTcm$BkR>Uy8-X3WjkJp#x@n*bNK2Sh_B27Z9TU`B=CjJ}Vin;=V9sROE zEPU4=gEn2peBLAON;-%donAZjgCJtU0=L%-=I!wYhtMnL%iU)x%|_^CeT>~sp7$34 zi3FP5$oW!bp{p9FQ;b5>*geKE%b#B?B{}J^(Kw`+AAylEMM5L_)n0>9n~IIH$jQKf z6cVA^Gs>BHf;{o~{15Qha#h)VS{_Zneb;ii))$>t`x_Uj+BK!8j%0qZJ`PKH!NY?o z6*Z4Y1f~!qEGNy(XuHC`lLHWkPh@ezvM*&ZvY`15CzmG=R1d}G{|2oLUK40jOowO1 z@K?x`7?`{e);#aIs+WK!W1(e>O@o3YzAv}F^rDUZs07~!a^Qs9Dtj}DPaJvFj*kHo zyEU7mB+70(A73*YA{y2h+i+mB9zFQ#c96x{97f=0&yT5BWpLikRcpKbK`Su^2AYIY z3}-=H20}90@7?4v#aQ_*UEdNBCzwC}X`pL(aDy}HJ0%ae$D(IN)9Qxt@G?HjMc5@% zCsaDa`@|yd3TX9k;eK@sJsUR?ZXyNw7Jwyk) zMzniiX9)G6q)fxWP4Pr^IE6Jsk^qIi7YY%JV&+I>yWe_}X)Yu0`K(0-4LS0M%g39| z;&>9qZYyneAV-VG<)qjkb|xqeM3*$9ih9QXfwy8J45h7lH~$JikOl18cEbt39f&CK!&*oZtLjw9lBbvs_p5#c9=q z-R4_IyOSNMygGnVu@DI!k5S%vKUQV|TGuRnJOw7UsG^4LJF;khcp5Jv=S8N2?!@}q zCmfD$hk^Z@AmpkW8{hBMT#=R{;rL?icPI5+Jd4I*;q1CS^K6Lzz%B+CWEbm(=*CN(7(syos6jmq(C@yKT**CrL%UV`wHt{1{sux>Sd-DUtoO&C1 z*-0`XP+A(iizBK?l+Gn^7BAl6_2oxniU&Mx4H58vZJyp^rz3I_P+odm*c$=0v1)MR z-u3Q?NEL&=cM;hAS51&L7zLQ-9|}sVyo5< zzS|SnkpuKMr$8Ab{32DfO?fNYr)BfYcp5zw&+#3eZcNSNa~|W+MHgLT55uq&{8VeF z>Sgw-NlO5R?%(_Bd6+~)&}fChp%A8wTAYqWJ6^6r$De-&o$&;T$59leOr$cW0mG5_ z_fJvC5S7l4nevx8bOn~gk5Iva0g8FUGqdelb$V>o(ClCimsk4gl}EMdjKxQ*Qr zmB~x>#mD7gL1d4fl5~xA)iG=F70d8m+CkRIX>9qxGE7@_j$7mhabX&o{Y1-pp=# zTdvwb>}bO}s#K@$30%F|p~|XcE7|5GB!5hMVRtB66yDche$>@rLCbmQ%;RDcR=wV$ z$Z}z;Un+OCi6F|+Y$?W4AZM~Q5oqVls|n)L?<`j72h8QhA|qQCxz%AeXZ;k)g=-~A zb?Hy7-0TxdEM8Ft9Im%v#M9sVot#AAt?aV1CZ=mJ?pbjH!viu8XA0ESzs6cFF{Y-w z*XMt^n~^CfQZdl`Mq*t4%^DIcm5 zk%t3Mz>suzE)(`Tl`Ta5bZ=kh(3bWvRbu>!>rRzzY43NO;vF85gS$*{0hLM?0v?Lf zSQ!3fUR(P)K(VDB-oi`mSW{8;av}Pb98gKZ10zuvWaJ$>t^*Ht>y!5in(5Awha`5#1A#x2Q)$(5BhIefg;d z==vYpF(H!^z3sK5T{>^Hw|!wWN>WR+Foh-=3P2B-VF0}qSxan)DW=`7u5X~OsTZR{ z#3`?F2BO^;Y1iCLojX6y;o9l$PlQI3D z;*k6&v^g32%ZAYBPL1}f`HG{jHa0x)I0=XFdFD1p zKBBaD0HZ)=Mhf+M7ws!Be>}O(x;Jq%TP&)wZrlOk58dvsY4@a?y-a(4@H!s5EQEwn zvp|INtb<2)DcG(xVNpr=w4~MjUYh-K8%BwgXQ52vSk6xteoT$<1#Yu9c-sLOC8FlJ zx#ilRMs&$!G{bdIV&&f_@$D`osFf%EMNaU=llSaZtJwjo&Dmk~fuYv(nf1s{F<%nv z2yaejPc3cbexuE9;OB2xnM%2kB(7!J%@v+C1dq8p2RbL5Jr3wZ0Lf8M&>udJhUa4G-y*#1!YPb4~VkoYU#bit5}ST@ToEZ4a$-iEfgjuuL%5!G&cJH1cFED z(Tj@AA8kOsED{(#RZN#clL3^wjY$816#B}qy=l+o7Hh=Q)kj*x@i?{Kj?$y|e@KVkQNyfSPi6eM#zd2ni3c|BduYf&Xq5@Tty+2nLQnU!X~Kb-kw z@Bkr$6PMJ_?qH#BWVjq`JPLzj6|wZm&ySbUecod@m8~Y+Jw4Pz?f%AY%}vj|Xu&f4 z<#9h_Hrr4kv6)CH1ll(zBUE&2x-;gIEK2ofvmuu!@+vmFB8YD^QrfJ4@21AHV=N$m6) zk>1jKK5G$oi_hAlb`y@~2`yU0UQ3*eMih9QE|cZU^jXuPnsi7M4#K`aB#~d?WGVs~({ye0+h<$S8Zb{TqI0t}QG6nbvbnCT z94HhDwJEBnyp0{H(CLsa>)zPPUFkaRrwXBz!D2M9DcSxmk?2)`$KfpN@$x0n4dHIN z%v`2wmaIcrT?;$t<2ldU*%ep5-zFu5we zeu=h%g0-kjLim?Y*~!LOqdK1h>n$D`hgQCLsD`C3eZvFSYO?d!(+dnvzT_b>?OD#` z^#z-4vUhglg&^Lo!i@B9M+JXeTtuGFABvHo^%ZmsU_}_p=Ucn1RpC|ybPt_&jch$4FLDv$?L_+xSOuUSS!z2wiT((9Sb?x`sW4r7lCG5|%(4rdwksszPGyS+9E&GeL-emMQ^vO$xVPccb0Y$gw(ie@u%) zu!tk?lvDy^>S&IDY{U_a;ph)l#j!ycwJ6sFKLX?i16a|t#2vx*c;brAKH~mKjQKk7 zgMf*#H%%cpFeyTyKs9eA27l1&iFs;Zp{atS-At@3e0K2GYS_e_Y752Rn2G;2$;M-ILCq%N{&J`I6k6i50s+ z_>w4HZf}`}`JjlNtUHvjpUKPLw%7W?FJOZH0>yvx7$}{9Yqu|-_{~fm|?1P)iQOd$W-_H8&&I(a$2oKu}i zn5-wt-ob*2QEa3sUciHiQSlCt&U^t?AgOB4yCa=Q3k>%Y;eCArMZEY1=CnaTH*nqc z3F!yKMBs60;!0ZJW1Gyw2fy`+?~riv4)1)^RhAnTIY9q2Yu|wV2Kt^9Z~X?)0*uiV z_4$hT7m^8FdVe2)Q&b<`n7eaAxBsU6fjLMdK>LIbtoQJ5;^f~GrWrsmr`8*B3jDvw zejv~83;6vPJQRTRe@7w!=alF(&~eIrbq~V-8(#nS1cVrHwnc&1{?GsY@h+1CDfZJ1 zftyY!Fr^aZoYMcNj_VGmy8ZuUBo#su8HbFNC_?3!*|H;Bgk#T)V;mXTE7?0j*%{~9 zdt{GebIcI3H#vT{=jr>@_qo2mKU~*`>s-gZKKK28t$QC+$oEMqRG3(xQj>hQpB5}erVxB{@6DhqdM z?+i}4b)js3#1a0B7a1SQXl{VQw|c)T+4k=WHC0=WX2&UDZqW0^+0DybmCBS$c?RUu zt);5*(!LId6;h8FF5@b6UeK>nw<0RX3j}pk4($|rYq6@nbciy@3E(Jp#;qxrj_GT% z04{zCtTHd;c44i=NuTZJ?{M{`VSEVZUhAX=2>(+ zX9?YYQnzga2~h(k`S)v;>w;SA)_k5mFvg~q;3#*Z=a9HxOwql99mTJ+Qt1)}u0PDC z5bu<47n=9xYS_Ef3|)3qt;hwuh!tZ18b>-6;e!ec7wytlcf z=BVw{MOoeJisP51!0e>}7XsRy=Ap^$`R*vK1%_~@mk(g!ADui6*Am~pUQ8n7mgLZ` z64tYtlv?agLHG24lX0me?iWrpy*`?GE4`xf-UnM{2w_VY+@5l*JO0axlrp!D*Jk6I zOMN6zTf%)wf}&XRb!sJMX1cr|P;Qii7S_?$1^j+(Y;J-#&MpC?og-XiH}4vGPs_3W zt}#U+BwWCiIEIe?$xm7$I%sbOyMUoY2(=`9`&*RGTj20XL=)gfvCiMnD|U00{OSt^T1s)ZlNZ|(eDU>w{?W4jJVwwqs9TFw+FW(m4j&WW(&z!!t*d%RhNco;w zU1$fNM#d-bKIt9ABOeOm-`mGD5|~}SAuE!^GKCv(F)VU7D|f;PU;?gUebxJuIUVT) zJ0F13zwG8BB@B@!ae7=R=o>|p{`G6k*0-|)0=cSrY-ln$A+Gu8U?~edaJQ&ZVezws zd>4dpC@g?Hvsa#BxijvSP-Sq84Jdn_g4!cI{}eKtedWf8g2Pjf3oCxS-xL|2`vfR% zHZtUbvh1IMMp1xQl^D}a&6Aw5yHacORdd=nf=nvX$eyqsz_r_4*?!qYC*SH)^o{7# zfpes{htapq^W>DmI*Mcj*_FhvzjUdUzub8<&GM$g+huM07gUu+pf2oHQ4qLC@R8sx zy`y!ZfR1;EH-*&C8T~~`zzTjU{QflAZ>t@n6q@o#;uv3r_{~y}(q{waJ9pPQ00AYh zXEn+MW5%QQZc16P)5==!c(0&#-JLLfd$GH3sG!y^L4T&e16%UKea5~$#=|R~*OWtH zanY%F{KQD}5`qM%;AikQbI6X5AOIpZ0%hU#i`XY#c0=RFd#Aa(MvWmX}PBV>{QXSX+Z@n1q7l0mSB@ zWtVYhN9lWKyJSCrIYuvYEabwR;5rdGKI)xE5uZ@QaKa zf5Kr%d`H5E&$H>9B~SG8aJ8&8*)Y0y&(}7$hB{WDm-T=vAOddf-p7g;e*buOWobyq zq7zp0DhuhdckZ(9&u8mXoCeNJwy`*bt*2#kq5RNfTcExgD4`Qgn?sT|8t24A0#V}O zbCRHTmF*6iE=_t;xt18EjJUy3&YVQXA`yCn8Rou$f3WWYFp<@8VBoT>QHM{P9Tw}b z-luUoY2QwQ3QGH@ya5k&wm`R~5jDe-TgHDwg$iMvz0`8GIWk+V`EnwdSHpx2hz$f! ze{!Q}EjwMXS*PR=ialeBp#bLY7$lvZotX~w3!QOn$P?|m+vx_a%9B-xhA#CD@SQeR z^Vj^=gerzE#ck$ApE1)>aI29Ge4QG*I6wliP;lysCK%DXkGeekdt@I2C7s*$$AJ>* zIeSi8^4b1^TI`*eG3e>f%Pzfbi@DhEPc^|>c%p-d=Fo{h+LMl@ZNR7GNQ^0V?#8-B z-w8MuzmN;b-)8}WisHL1AQ?_XPetY=X#r;MKwA(5g#g<##I1AS7P?>09U%|Mg6>4; zweollgIH9}#-S%2{-tZF2I4_0=pg9Pr{vNmoG#JLD_UU=dTwjVADbj721@m&OztRu zylvE-sDXNQI$Ur%G4}(a0#Rb!+(H4}Bn`yXlvPR34J9fyc&hjj-OP<|S77~V^WZxJ zH$c@G)ap1YKtq;rTqb7$yaN@<7*l|bPpw~Zgj!|lcPl0)z2$ycqR zapGK-d;7f%q$4h0g)y1Ht#Uiffj=n)3deCTbqMO_U-IJ(#QWoI5H7k32n>iCLPfh4 zoAdmz?GA^C;vn-u-uf^jvZ1nLYLlPWujt)CmJm)`=fPt}Y_mW=6UmTd;QW&rEc$yvhy2}(w>^8uqPK^PXtG08A&(t@+};gaOV6HP zylMUL-7FJK-DG8;JSjPEHjy*+8srzLwr_m4Ne`j(%k1)>HoJS7|Tn>rjV0 z9zvV**Vz;A`b>ox(Ioe!&+Y{0S&k$7eFAKC1unIa6!#>jg7pFr=DBXOpq_P)VnnU_{6L{T&%!KqL z7v#RQ(D>(|wvRq)1=!8EuS^I1;yi{}tl)nQewhw50B3hEiJ)#s$NxEPLagAcOF)+E z>l%w}<2I}!&zAyXRqwIEp3y??5>h0z3pS8aQzo*RUZ>~TWMQrA3)`omU?kwIzRO_z z7-O$6+pXkiE0c>uXpQf-Jivzj_$+}tPEe247=anHY+)0c;4rziF^w4My&+J%c$d`L zsEBz|M&>}j?3+E8x_(1&RAUd6(>CzOpk((mebxhn(~rnU@0;Ggsy~`(<7odS<^Q!m zd9j8s;71HoSIfT@>+KK@wXQvp;J9qt;EP%TDvX~QwlX@|QXe_b_A^}~WTWg>@aRy? zYn}(*sa<(gc#gOh=nJ)n-!SS2g;;xQV%_v+EepEuqqGa`k<7B!1C1DR47p3STb8{a zmj&Gv(&Xf)eq!iT6L$H!KdLwd!M+-c6OhHXK3WXRk|xh;+e^N%qBeCxA>}o%UtQC_ zjqISwVninq+VYlFnW7h5&Sgha+m@GC`NDS9abMZp6a;1x`JQ1Hk<1fP3Y;VnvajxJ zDw$VyLuE#2TeS3aJx=6YmYORN`{K!0r%CMJtan_A7%SE5t(^QMYc*1qJUd68EUjwH z(OBG#o#xFHHsDK_7@e8t&yYEhHSRLvl|THD|7zb9F~zA`8s@UR3YX~`ex!zhjZDFDGkJ-O62PQW2@LXXCEZ!HsW zMBe}_o1X-7m*qL4yURQ~LPKuJI&Yrq{TMCXl!QF+ejP6&0`GF0D3czmdMq{k7Dcwe zb<Jr{i z6KO$yxxFI^vGwv>BH%2ZNrFGGA}Q{U=N(PJRj8cjTh^Yu&ReB=GfoaH&+y}|v=Prm zqA%nm^pi&hf<4$BacbfXzgn;g6(&Bvdg0Ea&>#YEk7>gJTLmT}BgkZTnZ#l8niK*G z_d42<9*I!nD~mE2<#%lq!nD+_FV0lvRRCgmKBYyG&*^I_NLJ-3^H zgtXP*HSnjPsRCC3&}|XQnn|?Od3rm%k=?d*9Ol4$7JVzz?|X@Ntj3)+dusq)6zmae zD;rr?|A0pGZEeOlSa~RCmgS${u1Y0N*VE3zUUq)pd{UON_Ay4xFVymN6}A1#AC|`6 zRGjtnN({YJOr8^z_6h0=+=@43)kp6K20t5NXiKSa7Kt~Es>P88PE3>U;qS)sQNr~L z5g+bp@uDL?2Z(-T3#WOsp-0U-foQ#@o2jP9J~h{PEhcg6sZ*0w@C{N~63W}RWe@my z&32^5ieace#s_hU2qxX;(@2#DvBB)YPnHS9W1g=J9Fus|g7ZtHAI62XITEplDmVjcGFI0KEw z^`YJ{FEa%D7mfQK0h2PX2bW1qmin8wWac}BL@<@R5lbKOB18!u*2NB?|ku)jvy1)A)<+-pLjB4D8r?889zk)!AQzQbJR z?kp9Q8OJsGh0gU=mhZ;~mzcVy%%lOO$TosqdAnhPQz>5xG4T1vmlambnhdKyrlCVlaK*34u}o8M8w` zmh*!OPbnrp`pgsIetAOj%&*Oe!j}UD9+9gS)cit8TaDek?Z5HjIXtghXS?2XMG6#V z@AkIBAjS`Pb(cN!;mmYbJ%CWxid(Y9<3=I%Xs@~Me873NtiK782&)TKAH^)HZwlF0 ztYuR(=~OyKHE5xFy)y&e&wkPw59M-R-P(_C%QFUPH^v^VFIxhdHEwZ8(n~l2-s?iYJ}QTu%H7jKMjt8y z{nJQzNaJb6Ek^yl(Uh84-k);E{N6sRIkEhS$q(UBOUw}kD~4D_v7{S%AJ{TzNvWdl z2X&Y=CAz;N%Kza*zpz{3w6auGx=~~#+q9k^WlTO^f<}z!HuZ>tjSNH){F%iR%5_E) z+ve0v*#Mddk~aMFjGzJV8psV$|Al*qyMac`W-Hq0ha@<)lStJo*r~p8yZBxC3;+Z= z^K4h6Gh%TQQQ{L}jf`huTKfglb`8VixqDTU2Xe~X z%Fh*t$XP=#>pG!vNuamKHJsL@I6RxK#FiU0+i7AaE61!W#R{R%MCuaC^w+*NB0$}~ z9z0Mx1zAd-z0Dm>Pc!#zs%J1F<7_cK_WoFSF&Aq1_2N=GW;?6GFz^D{#**m2!XP*S zR8Reydw}tMO!tY^gqVP9dj)gu=nMP9xWVwp>2tNG7)gNh2IUero>Fnwx@zzB#jBP$ zZ;Gm}?xLlI4n$e_9Q1SQKDG*eRSMRXEKVFk zl9JuqG@%Qx;gY*{8wN5w=TNqj`cFaHZBTDloAX#QPIU-6`W|r-M*6IU} z!*$+{48e`<4?6uYtYjnTuhq=n783VM|p5pisV^$}@stui&XD zL-h5!);j?y6{rp^R;Ap@qGD}LsWHJl&xAuN1@4WyGkaMz`o&y^E5`Npm+GR?MW-np znY%*jAI9Tw2q`68M+Dj@2+g|U2TM#gaV#4Ng+^k_Gwv<&sT=#*#-SS7ga&wWJ2cBC z^gMlfl&0vdac-fC>Db?F=j#D0PgwQwp5n7k8&cS3FaO~I6+YC3$w7)}u~fuuZuyOi z6gRUK4uDtdKVrdI)T`-3<;(8-)6C3THAfKuLCuFdOm#6ahnH9nzsr99Ih)9Z`gZJj zk#eG1Dgn2HaKSM01)&kg@raroWu3?7P0%)N(ew+1+1M;@A*BLc%yTsaON?-Tp~$W5 z7wf8UqU)v=jw|0Cj1>x@TZ=sk4{o)7U4aK`yj=T{22lrCdE0koHFo&(cG`^zUX`r( zLTRGFMFgBl=`s{4ku_Ta{#UpP``92d5zE7$YM5kU5>iKXgOFBf;j$ z(VZ07rRS5;<)6(z^+>XBA5!+})>C z_Fj^oMiku}Sbt+3ADq7!EPO;xhn9W5v&ZAJEC53eHsJw2nc(qaN>4j8d({ug>XYYc zhbeGG&?;Nzo5Rd_f>&o37NiTgDU6CkLp+3DsB|iq>BSWhJu}4&Mc#B;o{%SCN_wbt z<%w9YnnUj26wHUBE$(tWGG42_FoN$@6N}4(Ia?K!9LZTrX!2LS>f;0rug)$+qhos3 zy0}6sXy*@@9*FUf;fHp{{QC5;>runJ9_siJXZ+YS%5Q~*J;Dup2s?`nXULv*Fze#+ zZ86>XC4_HcZO1hk&*f^;wG=zZ|8({W+WlgM(R|{xme|Sfp!ZDwT}rD;mV7%58LsXH z?#PgLx0H8Y4wAh^z~u>&(;6x-XQ4e@Bjwv#?TKu~*O=)MkMt>Td6*9)jCJFm>36&@Gre?sGP;+o(evO#_q+nDvriyVv7XfLD-DFr&g7FZ zr@EOHEqpSC1y1cU2y&Tb#$gd(_xhGvakL9tD67`OUd<4%y)kF%vpB9cgO!9A_TgPb z1_r(XBJ;YGa6y{ z%_wu})jY*UclS*969LT%7ht`xZBby-m-f))r9tQQZR$j%)nm)Gmge2{>QjztPBEL6 zdRd!JOcpUMHuM4sorz`UHumU)LRFN_+0riDBZB{DdjRT>93W+s-y^uR$KMM#cy~;B zoQ8BK3*1G`?LIVbT2?-bsVS_R(4rf17d5VRG+l{Q%@MpGq|@K%8~Ra_j*Y1UX+0$Y zD86MEdtSWSILrQrwwkqOh8Ji`lMBW+vZx2(MX!)NXnp-KrJ(CGc1Kl@8(Yxbcj~uZ zzIz)}Hvxw=JR_UGeB8w?CYY;yXb=3k3`$lv*je>FN2qKQ8)H}SR zjq%LIkbKV|Z#$9?pNw_=GWY7phoFlC$8WCVI}bG=t&wC?+gKD1+Jzh+dPpNx&KABA zJ)l#`d|_dynU3IGH;|+A3d>+U9A6?$KIT!Wyq-0>H~cnSId7TU%F#JfWeTB$nHPo4f2UF{4dq2&^-7p0g*+>cl%s)YrHl^EaI-3<5&T1;&hZ39*sCZnMRwt`F@@OypS&5!K*Aaqs zn3#I;Ciqw9Nfm9cf-9ax2}stm<``>QraVrVqwOf(%ldH{eub=VtuZQ9yIy!rl=!a} zoWrR(QtL@ZS^ntFOQ4BAfOflvnhd?fGP2kxQP4jarhSN@ct z|9SrC09w_5MC)_