From d5a4d1ab588416a357680974fa71fa000149486d Mon Sep 17 00:00:00 2001 From: jupiterbjy Date: Sat, 9 Jan 2021 01:36:26 +0900 Subject: [PATCH] Preparing for repository separation. --- Demo/PyCUIAttrbuteViewer.py | 33 +++++++ Demo/__init__.py | 0 LICENSE | 21 +++++ PlayAudioFile.py | 166 ++++++++++++++++++++++++++++++++++++ README.md | 18 ++++ __init__.py | 0 demo_1.png | Bin 0 -> 27063 bytes 7 files changed, 238 insertions(+) create mode 100644 Demo/PyCUIAttrbuteViewer.py create mode 100644 Demo/__init__.py create mode 100644 LICENSE create mode 100644 PlayAudioFile.py create mode 100644 README.md create mode 100644 __init__.py create mode 100644 demo_1.png diff --git a/Demo/PyCUIAttrbuteViewer.py b/Demo/PyCUIAttrbuteViewer.py new file mode 100644 index 0000000..969478a --- /dev/null +++ b/Demo/PyCUIAttrbuteViewer.py @@ -0,0 +1,33 @@ +import py_cui +from pprint import pprint + +""" +A playground to see Attributes of widgets which document is not complete about. +""" + + +class TestSubject: + def __init__(self, root_): + self.root = root_ + + self.widgets = [ + self.root.add_button("test", 0, 0, command=self.passer), + self.root.add_block_label("test", 0, 1), + self.root.add_label("test", 0, 2), + self.root.add_scroll_menu("test", 1, 0), + self.root.add_slider("test", 1, 1) + ] + + output = {type(x): [att for att in dir(x) if not att.startswith("_")] for x in self.widgets} + pprint(output) + + def passer(self): + pass + + +if __name__ == '__main__': + root = py_cui.PyCUI(5, 5) + ref = TestSubject(root) + + # root.start() + # Forgot to use type hint, it would trigger pycharm to reveal all available attributes. diff --git a/Demo/__init__.py b/Demo/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..2651b64 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2021 jupiterbjy + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/PlayAudioFile.py b/PlayAudioFile.py new file mode 100644 index 0000000..87830d1 --- /dev/null +++ b/PlayAudioFile.py @@ -0,0 +1,166 @@ +import sounddevice as sd +import soundfile as sf +import py_cui +from collections import OrderedDict +from tinytag import TinyTag +from os import listdir +from os.path import abspath, dirname, join +from numpy import ndarray + + +# Assuming relative location +AUDIO_FOLDER = "files" +AUDIO_TYPES = ".ogg", ".mp3", ".m4a" + + +class Device: + # Singleton? is this correct? + name: str = "" + frequency: int = 48000 + channels: int = 2 + + +def play_track(file_name: str, blocking=False): + data, fs = sf.read(file_name) + + sd.play(data, fs) + if blocking: + sd.wait() + + +def stop_track(): # She's so smol + sd.stop() + + +def extract_metadata(abs_file_dir): + tag = TinyTag.get(abs_file_dir) # dirty trick + return OrderedDict(sorted(tag.as_dict().items())) + + +def fetch_files(): + try: + # check cached path first + file_list = listdir(fetch_files.cached_location) + except AttributeError: + # initializing path first + path_ = join(dirname(__file__), AUDIO_FOLDER) + fetch_files.cached_location = path_ + return fetch_files() + else: + return [fn for fn in file_list if fn.endswith(AUDIO_TYPES)] + # I love this shiny new suffix / prefix search. Only in 3.9+. + +# ------------------------------------------------------------------ +# UI definition, using py-cui examples. Would've been nice if it followed PEP8. + + +class AudioPlayer: + ellipsis_ = ".." # 3 dots 2 long + # EXPECTING 5, 3 Layout! + + def __init__(self, root: py_cui.PyCUI): + self.root_ = root + + # Doing a trick, putting button and scroll view at same position, + # then update scroll menu to re-draw over button. + self.audio_list = self.root_.add_scroll_menu("Files", 0, 0, column_span=3, row_span=3) + # self.hidden_btn = self.root_.add_button("U Nya", 0, 0, column_span=3, row_span=3, command=self.update_meta) + + self.meta_list = self.root_.add_scroll_menu("Meta", 0, 3, column_span=2, row_span=5) + self.progress_blk = self.root_.add_text_box("Info", 3, 0, column_span=3) + self.play_btn = self.root_.add_button("Play", 4, 0, command=self.play_cb) + self.stop_btn = self.root_.add_button("Stop", 4, 1, command=self.stop_cb) + self.reload_btn = self.root_.add_button("Reload", 4, 2, command=self.reload_cb) + + # self.hidden_btn.is_selectable = False + + # just for ease of clearing + self.clear_target = [self.audio_list, self.meta_list, self.progress_blk] + + # Key-binding space bar to play. No, no toggle yet. + self.play_btn.add_key_command(py_cui.keys.KEY_SPACE, self.play_cb) + self.meta_list.add_key_command(py_cui.keys.KEY_ENTER, self.wrapper) + + self.files = [] + self.playing = False + + # callback definitions + + def play_cb(self): + if self.playing: + self.stop_cb() + + self.playing = True + play_track(self.abs_dir(self.current)) + + def stop_cb(self): + self.playing = False + stop_track() + # Just to provide consistency. Double-wrapped single line method, yes. + + def reload_cb(self): + # clear widgets + for widget in self.clear_target: + try: + widget.clear() + except AttributeError: + print(f"{type(widget)} don't have clear()!") + + # fetch new file list + self.files = fetch_files() + digits = len(str(len(self.files))) + 2 + + for idx, fn in enumerate(self.files): + self.audio_list.add_item(f"{str(idx).center(digits)}| {fn}") + # Actually there is *add_item_list* but I think this is more clean. + + self.update_meta() + + def wrapper(self): + self.progress_blk.set_text("a") + return self.update_meta() + + # TODO: add exception handling later + # TODO: fetch metadata area's physical size and put ellipsis accordingly. + def update_meta(self): + # clear meta first + self.meta_list.clear() + + # Extract metadata + ordered = extract_metadata(self.abs_dir(self.current)) + + # calculate average key length - in case it's too long. Maybe violation of KISS. + key_average = sum(map(len, ordered.keys())) // len(ordered) + + for key, val in ((k, v) for k, v in ordered.items() if v): + formatted = key[::key_average - len(self.ellipsis_)] + self.ellipsis_ + self.meta_list.add_item(f"{formatted.ljust(key_average)}: {val}") + + # redraw scroll_view + self.update_widget(self.audio_list) + + @staticmethod + def update_widget(target): + # updating target to re-draw over overlapping widgets. + target.set_border_color(target.get_border_color()) + + @property + def current(self): + return self.files[self.audio_list.get_selected_item_index()] + + @staticmethod + def abs_dir(file_name): + return join(fetch_files.cached_location, file_name) # dirty trick + + +def draw_player(): + root = py_cui.PyCUI(5, 5) + root.set_title("CUI Player") + player = AudioPlayer(root) + + root.start() + + +if __name__ == '__main__': + + draw_player() diff --git a/README.md b/README.md new file mode 100644 index 0000000..60ada84 --- /dev/null +++ b/README.md @@ -0,0 +1,18 @@ +## CUI Audio Player + +--- + +Just a tiny project to create a script that literally does its name. + +Originally meant to create a testing bed for learning *sounddevice* module for use in project +[VirtualTrans](github.com/jupiterbjy/VirtualTrans), turns out to be this was pretty challenging and fun. + +Therefore, I'm planning to separate this mini - maybe micro - project. + +Current status: +![](demo_1.png) + +This impressive pre-stone-age program does whopping 4 actions: +- refresh audio folder +- update metadata +- diff --git a/__init__.py b/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/demo_1.png b/demo_1.png new file mode 100644 index 0000000000000000000000000000000000000000..246710a9bde1f796fdbcddac2c6476d58e264436 GIT binary patch literal 27063 zcmeFZcT|(>)-M_tD$Ava6$Auac0ph%O}dDJiu6tdRFoD1B7`2IvIG?Y6%_?3N(+Hd zgb)cNK@m{tq(MRw6ln<%S_mX0xxrQU`Su=npK-r^&K>uj{E=Cr~7&IiT1gpQL^-Kr{jS=|x5lDI-UybrX~ z&QcD#N3sY2U}h34GBa7o=#gKu`fF2-xxMuFAI|(JS?h^k;`;&)2=U^cvdTsTMKo-K z)qUMB;NN|JFLqcS*5h;V=$zQtwpCq>{B|y-1J>-;|9EpDIu`U&SA6Glwy|ZU zc+o}3dsvU;Oyn&p-8KXOw0>NDKlbK*be|Ti65puw zv7^1JY1os;q9q`9?sHiz7wxq$_C=&Ec1mJJnF%s5c=_?M2rM_-jazbgV?4n|r9cz* zreasL4Sp%n>WJ?cs;g!!+pL%4B+bH$gu22N6m!B%`ygw|wqo`4d-uVm09y*S-r=yg zZel0;!K7ruX=w=i0l(@VXPnDyEH)eM&vQU`t?T}qrc$km|@}nK~0j3xFjH9u|htZdCN#7zVT4EC?5793n>$q+rpStxI zeDW`IHj`jDzeR9x1p5a7z|iWuWV;W-rKcUl_1?=QRZotCY-345zRG9M>AVDy)d9Oj z8~xw_ec_5(jqZoIN&$zP<=>bj?`aNw{5WCRXKqO_>BXdo3U`PHqSWEy3fNHY%DVI7 z`7-|SP+!%EM2q}aHRr?lz*_E*HPZsJgJ`wm8Nw&ej7`BuxA2+_I2Mys{_)pMlWics zJ$df=6?nnZ$CerkcK*mb@#QF_h!*byv=>{DUsjm{05_NRd>7tK9C0JbXde*DsOhq_ zbItS-+IqD~Q(MRF%tDQnrsAfKtmA%4H4$rojIKQ4v|JU$Kxk3kp8@I`#->)1f4aS?H=d-a8{Xho)O!wj((XVk9Sy2on@D=FDv9 z6utAIE3^8HLr5UAT9oN(7xIcHf|RA^Zw8#avX!_7 z5PeTZwYPcGSEz1PM&de&-A()~k;u&BH@W?c2Da7$o1y)lx{3&^=C}$C-w{Fb!`r+1 zaG>}*TmYs|{*V9s(Oh};(*XI^t4Ur%dsjs)d0qTfa%;)!X37@H-6gNd z|JFsmBJx8DwR#sv<-Ei+{O!q?W>xgK^R>7yuUMuUuJU$SJk&84Ss;^kJ*MQwN~J_h z`Qesg5|zH-E^tem6Rors2IYjr=HEZkOLB&~F?t3x)?Jo->}A+Bdov93qSJk|0A1sf zC|aDckQmjsdme>DRu*AvngqCOy6LOdCjq?Me1=v3M4x;n_>!tJ~|S?4=LPJ zgDY9+jaMn;qjwZ1qgtHyz&Tzow=+f+D%L^3{xo*k{bojn&vJfqJ_B<4h2Cy_NlKK; z#N-PnPo1!buv`;j+-S%YZU&{PYvL+I0TF81Kg*h{N=*LnR_^03FDi5?m7tKwE1>N@ z_RP|qs7#lay0-1CG(;n!UIXr*89@5dU>L<#BIUqcdOs#GC>cMc-|^Zo(6jRNb1T2t zTJg=vGP6+fa<(jFaZo`cXPfu%nx>SlPwpW~#8jf_{FIq{X@QwbYW;9&R^G7Cpx(+Z z{IUYe54G--D`h&c4*aV9N6%a{I7eNH5`sA@G-%24SCxtGHf;8O)ydUxkcRBL_Sn^v zV+L^#AIl7!#l;1^4Lh}6yCddcHyNX(VOSH2wX{1-{D6WOdcw{WH5*Nobn<&GmB6*D zZ(1JNHrO4W79T#J3mf}YA5IA+EaAQT(zr&>SpP@GQ~XvXqD(iy2APo0B4s>%nN{k& zE*bLmtDekpw#GgKuX9HxSU!F^4tZ0;D98Kt4A<;K)`Ud{VR3|m0P;3*UxuCZ89Y(m zd*q&%Jm9+0A>VqaeO~O@Ory8{D>I+twE_6b&kyU8M&mq94Lj>JA{5Nq*+VMaq)}_N zNv3ABpu5~knJ8UB5{;@lyRc}1#c8F)u})?n-5E6I2Px3Z(08~?&c?xvb9pXHwkh={UF;-onhl;XFnd=Ltof=cF-K`GScLkk}yo2Bv z6HCrmxLhB9Wd^q+u|TO=Mj!QMo3))lN?K)bADVGN{Q`YvM_@B@{nJg8g<5*-ldIxe zG)AFPL0^1h{3jD*{cuTkM|P-7yd@O^P$mMsq(r#oFg@ESzzG! z@!QYFWLbHk9>fsL2G%3~T5~!~!E?NefH~SZQ>gAcY6~_C_sN{DgTI=%6%?7NUPhlY zyn;^nepr$>nl;(aN$U=IOYiYHH0xJ%zrdW*5#v2C4>Mx$=s5XMMt%aj$}%n%VV!>A zK+)AQxZW1xM(5ssvb1W=(C%PWqKuu-h^AQ)m7N|@1o66}?!0CwW^uo7J=k9M><1G! z^|z|>DdrRtWl2`8eRAF z+af`UUZayAfDhvAPw)aXfnPotaahMKY0-oGBOM^pnN|9e3HT`!?7^}Krg9E`zMvA! z+=dODK8#5_N@>-Kw}YBRiC%wBv5dhd(q|UPH|wQcyu>HnrcGUi+y*LlHlF+SXUPJG z4qTBZVmTX(xx&$XIVMr&>VBK%lV-^i0=cr44{kW%24N;zDOaReH&+{^q&nd^tn8ve zE3`?i-iZLryt(1>o3k0Zwn~O1ufP1-f3NHMjuC%!UVUK7#iC46BxyAOKfb5LAi&6sAu$mG`Z z_pi`SBLZc*cOWs;uShK^#VoeY0VI9wq4BBtG+1RjBro7n(3nuCc#>D)CW!G&L*`s! zX4)2SJgZoJ#wshJ=atK_C&k3kr(CalT$ew-#Ds{Rp*p()1{ToV*c~)&$LudJ%HOoV zqD?+O7||!ke*p;jcJ(NXWlles`Hw_;ZcuC_!2v`hqkY z%i@;wc9;8v)QwN}V%1*Y9XCcX$Roux&nNP@2l*od#M&f(glje!5~mk*epWhxKr$+t z3LiHRmn*m`xnxmlz`2pah4s_YRLo~H{F!7(2QX@6fY;)OsT)Zne8se3;#u3TLDH{e z7s-QsEmAaJ_E#Frx1$h?AlUvR>|rp|lW+^x$cs7fDh6|zxy z5uktL_%kzMes06LJbhRJDr3dWzr4pboZ)id#br+F(~Jbg(s0y-Yf5CW$!pB$!SMVU zaAU;*NYII>3+y1Vo&RPeX#s+U;J(~HZ^d6v&_l}M!sZ`!k$lJ)1K)Tn4Q;m| z^gwcs5_y6UF6+$fFGLh==RSk&nJ~O^hpa5jHlSOOatx5yoM>sLw*9jw#?M~1SvEon zAG~dRc>U$o>4)jM;(THIT<5#0i*ZO?hw3_pXPOzgN$jdjy zwtU{JsOLN3L8lpJ&l`uIPdT`Gu2Qg8qf(#gR_|a9;*^R;p~?du73C_6w2lfbS77&x zIA`cGkfg5@L_#Evj`g_e44~Eka#epbT)5O3TV*7Nf8XerSLV|ifdiQci zrd+6w;pY$R6VC5yXpS3crG5&mqY)~Qkb09=c!1apB3g1Cxt0_ho~_r^DM5NWGq|jn zxGB`9G&nfxF(&(!{*;uv{16v*<)m9P=qqPmXIc(<%CV&^|E0L20a( z>a_S1KabxK2MDfARL{ItXj0M*y(?U-1%YxXU#)`zM6StE!F~NdV-qud3G3f_l>63? zD6HpBcoKT@4eFI;_uHPB@E^Tz89rlNv7vO|f~Zu^i;8NBt0OBBm3W}jY|E)ik7Un? zNb6hmue6^&Hn|Y^Lh8w2Xq6+A2HI?x9&cn0vuC0|=npOZ@LK$1fx^o&8nP@D7+)zv zI7M!DLTH$q)BR#Z*W<5q*IwH}VO^Y;0_Q#*$?giX*CO(@fDy6G^{FZ*o`EJbug4=* zT3~`8ZPW_5`&V!cW4q3^*|{!DgpQ+i?z|!r^Klh!V6g`3(`Z!)tOZx# z!7G|MGXGTt$evRmyqO~2C>Xzuja%}lu9%6_#@co8dZTs_H9m2s2=X>K^`8_wz;9q9 zYneN5eTvDd=Hy}gLeNR0VnTI_Y=@Xh_+0(Y|DDAEsg_*Cv1Vtv#6_e1x}KN3p0XKT z$>vfXjm{mH1F@&%atvzE`E~@Bgy1eG4GQ?zUsp2j6T27Nr;nF<`e)(w*w#MoD0a$J z#1Y@xnQuHyEarS-dE##Epa{~W|Iqyp0sO~L8ax{mJGle(CqLx`+cnfRtzc5UU#}aX z)fP>^QmjxR8)2!>{3(B(z4!Tc<%$p!LzS~H@1pXOO7MOvE9Np1&Tul;CzZ)hRjimI zRdwBty-{&6p${G|y49{9z5K)VJ#gu+4zz4r>q8mC!3x+dQOJ=^^}E${;53bH)ij_F zzR}6xRzaI>BIb~nf_7Ap;DrDafo_T0@zyV@{!RIs!OK3>QDtD*7EI?P^%UA410kX& z9u#v`iu<-}V5*QG&=!k!^5gzDb-maM5SX~UV4lt&IjqqvB5!KI?Mft1JY41=t}u-s zMAe~9``aocAsGM=m4e!Q&$7J5t6u~!NdDCFRx5!Kv4fcUz!4m>;&2F|AM};D&4zjX zjC@uWYEqe5#IU@fT9p3$wfVBTb6`@J`XRl;1sPIntBJLi({235Wvd#^@gu%hP+i%V zqt6Y!nVp`mT~6a1U+&^h0P&)%H2{@PEpSTl4+{pB$MLp<_-TEeF}-PbFgLb1Pq#<~34u z{J3Ylf^e0o1mQeq0>1+~YcGzEd_jOB=Vp7wxA${DIxG%)hA*dg=2#~U<7$z>;1+YX zp1Sgoz`*xSv6fHeZ2h7?5o_k}HhyV7iXWX&AIT8fX8SKUSMeV3eW%=Yt@o8fW|Vrm zSw7e8Id>s0=Df*^5D@R=F3EA2$i;@1!D-d*P{CN>H@*@^?nl-tnyv%91(rk3>Ri#7 zju*U*6cj}9K15hz3!oQu!1pfYIB>R=XtP>tn=xPUI)j36M7kJ-1T~T5MsG!>jA~p_CLv zo`))eDiA$#;I>2>a&Eos@$6S68ckUD<;yO7DpHM@AZn(5+$4T5iT01qKDHo*L<}N% zH-zm<9z|M>v<{p`MEy;r7Q<)2+yr}BH z#X}HTS(aWq2<8)g9w(Q}H>YS$_t|qyJeOm|L|-p#^u?n2&$WXXA5p73Bd*#4eWqtl zfFz~?(<2Il?kKcw)U7V>ii;8OODDPnk8>*>7y=HI*Wy({A8k;DP0}v6%QECR>zM^O z3Ljcux~@Ja)UH|EabxGH!U_=wLv$`VB5E&q@Z^)4w%~e2Waj-*qC&DlIv3gTVL`}mK?`(OtX+k4AD zuiUVIT7`Rfu|;`m_;sN5ul*c{ZikRZsDyUsu+M{)-b)wHjPh;b4_R4uSt=j181)Ee z`UFo4#$b`wnOS&Jv4@a4`l!ZMx?@k=T*mt;1agU`4}fZ zb+b#{b({lyMt%rEzChrNM8JY82w<1^A(&!A;8oiOCNz6$z#+T0t$bhT3)<3n$j(g9 z?iftyBJa)paW-nM<8tw)>c3!Lebw=wnmcHt-9*d{FJXp$+QPp`d3Zy3q4$lc_OcN9V1rUZWQ zOvXDPrJ(H!7#tE;l{7VXDz{cttWcP)FV0U?XU=x*L2whIhx-$23p#z=A8C zW5~v9p8oU1sD`N*+%I6xjS3adUOq9F6S1!yHM^1N#O%(&!*7T=mvqcckW0^59TPzm z8(BV9;(H)Q=IF`l&nj8S{hW7cp{Pj5F)-lfnANJ4zuXaJQp^bw=skJ^HIyKL2Wanf ziWI?;+6Ey%`|;B{t42w(;Z3ZgJCeAy*?0X=Bzkn6yC8z?T4#Evp>}u>>J`NImS-u| z1`b4UOh~xE8eJq`N%x`|VpjQO&)wSTNL?^GiX4>T0eUG3D*d~1CcpelJ(!KrsK zXG{_gx0D;hl>5$^Ir+!pk57HASa&K-eH zYA6zh+c&7`-)iEizDO_o>SF&cENPq^7)0xLRJln|zvRP1FO-tb|K~ zT?r~ibd%nu${50UR?0x5pUde-4kgoNul%IeFj(Hw?3QwG@YU1jD9 z2kJZsxaGwwNFHSt;0R7gss z*6v9#%y-E6DMe%<&xtRo8DlvcMxN|9UekDDHM%l^E9HL4f-dEzCDfhLMz07DY+^;B zPG}{}uLS_6w{*uIX$k}rt}Pz(GQyc-9k2YhGM9zrecDHpD{G)McMa1xAD4}-2w+h0 zaX;1GPf1Y4+$-x=K7zpno~vyOm;`lIOE+5*+~x<`So6e_3gE6WbxAyv3E40?IGpZ` zjeYaDGiLE+jQt^;F=AH4`yqOEH8*8$-%aWN8pV|l-_!2F3r>u6{BrDj)k8-IR`jNt z+%&n7wewnB1pLb@iQ>GL_1{cji`Fc0C$}LD1nONKJ8McWyOujBMPgz~=w)iCW%8NM z&kLP|3K_u7Oc!Hz(M@-dlCLAGE3SJ;1W#%(tIh31bxDLMQajNf8Hq*|+VwAlJl2WK zPNR!l)) z&W1%<%zE^=?4?2miJ&^p+|}R&kw*vGzj5)E3!--()R@bAd(8L%f4nO*D{nhPAE1@w z-gcwiNtQKb!p;xbU!s2GfS0hnT$@#c72BSln2@Q*0aom#)$Tue_NGq(DRNsHbbiHBK$cS@W%*xDWhu%YVH$NGwPA{pn=5jPcd+jw zNs$or4XhN#3-~P|Nz?4DR^)sKX>gcX8cRAIQ(pJD00COO6V_1Ib4^nHKYs2sb_WQ& zea3J0obGP-iV9`o!K6bLgvEL@I6l{{0-234kMzWtNC$WfYm^J6BCNqDoeXk}Dcy1!jp+~PdqavZbk`><>#H~%}x>!o@Y}5HU0^_~W z1u}pCK8@seE@mf{*8jC3t7anCGNaQ}nQKzZUm)E!MJiAJB>%PQ&-LTbHR zC3SkYnnCg@@wt0l)CW&qWz`OI3{i29`YgIaqKJNlU4&7ferHUfAR%oFksx=`UifO~ z`9*w4;f0hrC(E=C~{1GyK2PVnG|?>QUSyriMA zD~P1^h!$_=4_bIeLl`+%B$U3R9d*p++zLyF%%^SC8*)y_>mhX7jZ5BV-jY$vI01<&)Ii5RKSPmFEZ&%rZiWL@pv ze_CHvsDYq7O&mFIy%B4L9R>u`fqzym{Fo-oJE@Mq(#GkzU+A&8TOcXjcfX0M=(sJI*12x^Wl8YBf6 zy0-H-z#TpTkFwW3O?viY45$`c;lRG1l!S&f&1@nJ4*Qe^UB+RGuSVw;i(0seicf<` z){$W7lZHA62uex!mj%b@hPrPTAZ$rBb4@+lSvl4cdb%i0SA{&jxCS5himWSg${zd1 z)}qI$Lni%Pn88G2m4niaRT6j5y$5bb$ztQ;ZcvRHk7EwSQp4V?X(VtpT$k@vMofgH zC}v4rZp;Aej%EoutqkL)Z@YGkubgAwim3p4AuVLm_e#0~Mw_cjs;q+8wRz-Pj`KwS zRA_Bn@7;XS=`8=ltND?wU0F1Vmz_C&&mX&EsJ3q6FkHz*4g_l8ENmWp?}iSvWXJ6# zZOTC%IMvsGo}`z6%t?7&xi#a4eA(+ojv)sLwhjE!FpyKX98}r^RK!#Gfwy9-h9!EF z?9C5}jt%-S8ix=>$My@Sj|}UNXJqgqL}ZH`6PQC;%G^`pIpqyQ%Ol^D`zDWG2H%VZ z2|S-%l6HOYQygdhYv<)`$WoU>Dre~ang&U({<~cd+S4Ri`v)1-#)$m1%=F&4(z-a= z<16{rlu&jCuMJ^6^kcP+(kfvY`t+Y^LD=SEub-4qm^CWrBIo}rs{Y=WPlV?q>QA#D z$&n?b1`ECgsUbxNA4%H%4 zseU;PTqKKS8}x4J)@4rEUb4)k=weVO7wGv5k(bb{4P=LSQ3itr6EfW=G_cq0+O24K zP7LLDVzZF-yjRR$1iuW#&& zTAGBqXzVHrDSh$zIrQ`)rNzML^9wm?`^hpV?a@~D>75x8j@UG>mCJQJDY;KMm<%-7 ziFV<6lp5y_O_3e4zbI4;By%Rl{nd5C+nI^CF(f@siZm5_Md%uiD7Eb<)$J&MH|^h4pnroqxSp z;k~gd@VdP|U&E2aJ*d&yU6s=n%TY=^kHQpB1>Nqe_Fzz?%W+6-O8C{nCqdy(8K%D^ zRvmle*oF`zH0cKiy0o|XIzP1~?(R$WR~i36-kBvFF!6#{_Wmkbgq~9~E@s07ZV!`2 zE1mVo2@TPi*(I6jswBCKu7vniFQ_owj`+?OX`g9W(fMLTl2fo9u9{a`-a* zbJ}5lue0`cP@kt!c7f-E@?AS9?+GwUpTqZ7i*++MRtYvYU#0aW?~zg-=z`~O$KDfT z4}(kXJafJ#?XesQG2MDO)po;XR?;Es?NM|}uZ$D7SpNgfCbMWlfG52}5uRM}vaxqB zz?3yS&3;*|pJEH29-cU!6x>scu>>DJ>z3((GQ@LU&HT<@E16VJ z9b>ne%?Y7N?=H}AyFN{vKYz|md|c987tFzDIL7j29ZyfEd{M|RCCUClW7STSOV~%? zL;Q)V+x+EyN;)SB(3sJRzQtBQ4TXVEhS4{4c}r0UZ(RqKvb+OUE|kfQx9ZrJXnOW{ zbeW*Gug2KG3J`jQgy^sFHgG6U%sFdrk`<$vyUB(ozneHkc{d&Yv9A`(tA#E%u*fDB zCjPs7vZyzcc&umj7L(=*ua1m(%on^`&CHN*KK=*^GJ zl4nM;3G^WQPfas*L%acve=5Y7OVNF#&}EmLN)Kc%`O}?_r_?FgzDV%Y*j590I_0aD zZIGup?RIQ5Fn|eY99+$wbRUH)9kI|2Y-2)#czcVYZWL>IR)^f|N{ppp``>|G?L&KY z#Ur1kGt&d~?HVR-3n(K00*WIva@r}?Gs4}vRkN?nrA5&z2B^-c=2(v#u0!TY>~k=) zY2i^~Y#Vg8vl;DGZe0)UsC$Rwd79HbBLmE)+<(4qbN0u#KacXtz|1g(Eb zV3kSim&8QDsf-&yNb+Y=H_XS*_ycCmrtcN}!ZR_VHF^Vv>Jvt9f>nQ|N?Mj~oP-cg%SXKr#sq91K4L}ZL! zfbFjd1{+xxx?}wkvobkz#DuR_^Ub}%x?)uZz?l`ohyu!k6jcF-!^YT`4&AWl#OEqY zb3d{#2@Ez}EEDS6mF+QVhBcgeMP@$u%4>;?iOjS3&O)0~jxxB950I$`qp3?%!@1J9 zp%r)eN*J={S!*&zQg6{)RRK97c-jID+Bl_jGc#L~Qz?~(G!v}qK}s%e4GvPnE6yG6 z`Zsyr45%ywekF_NjoidGWtPP)M6ykqw%)eyF=0t9O#AyxIA41u4nWZ(aB(+zmC){} z(Ejp$hNM{8>vi{oLfP|Dc}Lm^J~fepJ&(5g0T0b@@+!&a*2u6P3AQ~q{j+Um+=Qjf zYsnfTvINxnh?kh6=Pl+5cj}0)YLyKftnF<~5lH0el2czfPnix7dl88x8+h(Q_+X z-uW@jE;ORM@8)YE0=s=q@ECu_N|6H++^(xktO4edR3^g5%VhxGaIyJD4+r|G1ti19xZ|VGM7uY-4L_`U6gR#xxAKgKm7}{O?nQ@M{&NAw73&r@A1Qj;FwOs{_5MYzvX}qJx4eU;Ag_2N>nDTB zUyQ7DP48kjL>@EmCCYVUc-e1(SS; zlMWV`x*O~M_IXKjZvX!hW-Q6x?KviC7X6DJCuN=v(mD{cw35*=wS})Zvv;*+9`M0j zlHzN2`Yo|{%06yj*Tizx-0Ybggjc2aT1YB&E{ZfgQ2t0NHVO64i=U}VdXJ_h_@|=v z%l!NU`vrs39=z<;w&N|*tAYP|E>1mkeDc}tDvHn5B>!5u+>l-_UfAwxG4Eh=*J&oF zN;^76cckbt6n;ciS5dKW=&k|v+F_On zGMk}QuJPoHLP?P%xwkytkH$YTJl*^($Cch9rP#Uipz?9!@Y>Re$3F>Zp{mW=9@jFn zQPFROf-9GI?3NJ#Q?7=a&)h)b3)X9IQOcDR2&b1q`-5b?{B#=UjjzksiDU_HzPeShGjo^pc_xp=fo7L-EXE)5BfZP1Rn1?a;)lr^c@#h#O~!yKGk z@+PGuNA~EQJ%f@(B_!NIgzk1sxX%gKwRD*{-T5;#di0iUu-B`BJUZbHU(sepx~}l& zjkWxFza0Fsy(C%Q+jqo3w7lF^?)qe^_f=9dCVKh4=}Uuh-L?2*aOW~m7G#=?MwA(q zN=QBus^GPJ(k)vh&I`18GxJfVgsY_{q&P#c=d9*Cv z_64!Abw>3tv80E1GnNOGb$)!IxA4==k~@ED{uLRPK=eGsgtRYAFy>wal{bxIb= z|F!Eye)6*sLGzQHM0OO&9dE#gzj8=P8Ve%77h2|QR?BB$gL+4`_rKJkzvulBQu$YV6W2vF?s})AJO2E{9CUn7)bAXz_ zE<9KS1WQR0LbniZcCK#>yee-u8-|5tuV1D#|HK+g5AGRyz+h!HNcxYmQCACv5oFH! z%bigS-2M`-L*8S>oV)x7e0?gq&c2j97J{@W;54O&3UN-{D@>>{N0Q%Ls1bD#4 z1dw+QRzD(!?9seIxlzvg`Y~ezNvmNTGMoBNXL}h$bg^iCbS#VBtrEz5Y|PYgwKwyA zrIH)3eU}(`-ZRTGc-hlvOm2 zQ1H9?8vIL>=om0(N{?H`V)4`}tuBci)^kN<1*T_e%H`}US+pne$p577FNpZcpHjYP0v0LDJJWAyE>RLyIt*>0`sBIiHxkq`B$b#ra?wI zs7}*HMupaqjSCa>fW+7aDH8@Hpl7$ZZrYFy*HrN-$@Rk{ff`-$p1Vl;vi&&@JdsBK z%a+aD{h1BPoh4BF^tqF##xWn}2jqHJXLf#b3b*+gFRJFBc}z+(wUlHyBX1qnPu6L3 z-pS^^nFiA@ZV@!Y%kxdg+}q5dLs%k-QR0xLS} z)|iP9=Yu+NfZcri>cuZ779`$(tWK1a>wpI4av5@7HJX`t+Uvx2tJ-Y4U~_2jCYp}x zBQmO>t}3sy`)djx{CTkubb&;n9y4p83*y--Z?6pnWz;7mLJ1z`*kLL4M#;POfyl&sBd`zSkt{p~_o%dfc;~O?$H2k?m2TC`L_) zaB^o$BwtcGB^q>0^ays2}e+NY@!eT;wL$=(DK zzMu~nxIKzBpM6NDnr_09_!jOjOe53@!>%>a40iTvvj#GTf)KR59AaGa514)#ECeMSA>Meo-oOJaWg$ z*O#wq_LNYvU5;s#Ol_EST4b-(+v(=(E_r0Sn)QgT#VnfB2|f}^t%n}@i&9t5=TCe2 z4NZ*dt0tLnv8YNF_PfZbvCHVjhxW{I=0 zotMi{1+UIo&spGrrd!{P#pcz9m~e%Y^);S)kbot^%)a2v!cT&T>FIRC+8fRvjfHlh z_~nl;$JQaA_b&b_JZp}vnefcxC(Nr-tFM$HuDo4<(pf>uLD4%Fh&(c{a7U0Z6GrHB zSey^i%96SwnE|=npgm_hs?_+PfAf2kJRcHnxABjjek}tTmR3Pi(RgG_^pMHyQ4CG< zR;W>;YA4S!s+bM`2^u*9g5s{_I$klhSgzf5L{f}GdbU-l_8N(j-yb+nmL7{h%+{&- z$)vE}`9&Z1I_SzS=e@hr3ue3LvbX4YNlW)^3$ql)Z2xVvVJ1Q$&>%MM>)SdGA#wwg z@I{r)QfBh*;>8u5TY>k8alwz)Up>vU*EUv=^wWgVRLAG%qTW+y7XCL;|Mh@qQ%NFu z!|L4HcgvpH0e?N4bUyjC&)^!sV9O_W+to>pyNQyDzU}?rha&#^^tmu;z;*e*jZkPA z9GR9>#lK!XdgxDgai~QZ(BvhFf&OHy-wNMK0p6x$RKNVwC;!_wDx2DVG05N1*ciEDyj=`ad&uDv6kV$E^^7Ar9BVEZtYjG~1lC6mpGIJ#dco z3W48CCy9Sop-pyw)O7wgDcpbK5lGsDBxWEPkRtrUGXW%jdHdfoDRtJ_oW6_yC@2f) z?D2BzYJu$L2cmV-Av@n^mChlSo)UQvEf4+OivP$2Y=i#4+2;SfBao=ps&D}_5&s8v z|J#A+|G@5l()0btVfVYM%sl?jrzD$-{yE43GXK#vUqAAv(_e-0kL#5~LVBOQUs#>( z1MDweopJrmk^g&h<$uf*OD4eWzE6MyTOf;!Xwuw{cp1rKFt#2LKspB3Of6rpvwUtgcGds$ zS(U;yuE2-9Cj;u=C$xVX(;f-@KBisf{wK{r%dpnmdpjn1(#X)6$CAkCk7fN6AWBzT zRg9sD@IN;Hom%}(RR0;4@(&Pq)B0a{&>_d9l9M}A^_>m(^Z&-XD94P2F4t!y!{|au zl&*mxUlj>rQI^rKl?ESl45%52>_|Yui^xW^!;>a}8RP4J+uD$4l7AhUjwxDaQJ_jZ z>gA_OKn*Jq)eqE7tWGHZ(FiMHKyO{GBsqZ#t^*@}F8`28yigg}cl82aJVh7QxNxCb z*AIrTPr7w$&HD9Mo7V7VbWE>nO3NPqsNI}loKvv(>*2lk_gd}PiVAcBVHr1HpDPYL zZc8XB1ZNpS&%SJB?AI-(8tc^O3^EwSHe-5$*mL3Hd);)|u_jZ&Bz7_K(-qikV?wln z3eF!!@ni}Im|SShqUTD&iVIhbZ#N8NiqCO_Vud@oMMm8pQhfO4jmtT(d-{x}8!zkQ zXwShv6z=c-y7^}9w-@c}AbUKJiTw0o*)B6Vp-|~7xy?IWpCP=mySyP5_m!AA41~>G z9CYWoEIV@QPKfTn?wJ|$>=)>bKa*vlM;J?^oDU3_9J}WLH_u!NoeBJ;ow<>9@{Ol7 zSGBd0;UTDTtJDW&azkLeRXinb=8DeGlhe@CGoa-35 zZTPUfU5NydLlwBIGZ_c>t9Bx)pi~z0-kmW?=)} z^|aU6@AeTho$t*uQO=7U8Jq1Y<0kCFH==y9>k4UaSp38wvOgIYKzMco=;{Tt@8ow- z<-t_Pkah%H_D^fmPK*s~8~d8dx;Jh%Ot%y5Whk2-6Hb5e@=cJhkozC*d-bpT`q`^G zd|+;|_}iL(Uw_VDxHIhf*LHqi{~tCl*}gPj=yUtO1O&kU6fXS>?UgifX2wbn&j__z zak@fZ>QIo&f06T_>MWY$ZfJV?)L)bH3q0?^MlGmWSIA_e?^&<^vWdS;y`6Fh;O4rj z0RDq&uPaizz!Ts=t0D<5*$EpJ(;Q;rt0=yb<>Ho9gPTUfRdJh~Yc?wGFnFgX7Ofk8L+gL3atE zjf*{{<31!+n(B(`tSz@2wl&l^KDYx^zw-T%cUL|G#~(Bm^}_CkHqLp+Pu)R(y(1;? zJ;x~uqsK1@X1T92e7)O7zFYoSG6^2uR%VtGnk(>*XXWk-^QDiydZ8ZXeT18P&koPG zed(Er)fzst74nyT@pn1{gM}9H!64YOIP@M{|7BXH&r)FgVj5T;=Fe#sH&m_LS@0b+ z3{;-RqTBBIi}vA`dMv6j9P&7R3O&rtWIm8);cV65J_g@yJ;6QIG^#w60j~VO!LFpw zuB27tX%`-i?KFqh{#~KD>hOeW-8p}O?MeXg2L$PM&_JvI@Wm0<*E{07mDm~X5(*j@ z1ZBi(;_T69)wn8YJ{rklyWQ?)#j=(XKr<6C9Ls;@vH`YCW3o@g`%~h!&pI8whqu~$pSc3q-i{}y!5qRd>3!Zn>t|@ zeTnE2oAv#|^Ua9aK?fFHt|VbXezsmRhm_#oJP|!RaK2N#pAkRZ9u_2c=1>_5@ebsA zlmX#-f#d%Ak?P7J)sBbm13g*Js|HFP~5g${PxSu}g`9MN&c(+yARpS0;_$=r*-u z6~$K%gwirpV0OO}HaQ;_OzU!Yl`pm~3%Pf#jND3=R&yh&mWg0z4qSILRZlk-5|;XA zlYO}?nQBp*SxRNDAbzqe!Bs5}&--ep5@XD72csF@A#oGj6K_Aqk!-(1ma1z(w=(+* zY0+(%=OfCSRVU@4TW4#;a`or9LPK$nmuybjgL8CGX zB+g7l)r`lRway0N-2~6vzODc_^?!A9rBO|uY1`H*Ol#FvDj?F(QGrn? z7}=MET12b@5!v@P5yBQCOV~nSgsG@(ZIw-d6cGdxLLm^40C9n&tU(|NB#=-eVM_>0 z5|$A1McU4C=9_coJM-`R`JVHh^PcBkuKT*4=Y1}_)i-KlFT1~2>duK>l6_3$6w2D$ zQyEu(Z9PK^eru_HTpr%JGde#rCG7k`>UWH+xH4CEO?)zTIc<8$8+07|@wll9EdCC_ zluR8;_k_#(dkn!ulJemyeD>Kj%-Io~@|ZY%O+{#u&wKe}&IDr?#INh})cI9(WmMV@ zsTH;zir<5E8u=QpXd-q6!XMD$-qk>T^J9vN>+eb(tkQRNGK!gZwQ(o5cYf0GB6EUs zOevDW_C`u~zB9nw>QP#H?Qxc1t`JYZyc9n?!FuZ470llZJoNjVe2YGL=POHV4%ADv zUgv0a0}NS>db_Deo05>)1B+czu$4Csv|=~KSDoM;MlUt}815~m(N}8|)_<{%+iYq_ zZGMnimy}^IZNl~%9tzZ93C?#(y}tArU;nLLA|*b&joy2dHR9%rE_pWRj0HA`=1Mp6 z!xrYo=Nm0fs^IMJ47~A2x6JKZRlJ-w`Yvm}kxc7s*)81UA3*jl3YBkuLrj)YQCVGe5n0c}HMM(cF)k`>tj$&{Ufz<7mzbXpvTh zlu{=WRt8p!Gq;`oxyY~bp}5jfw#Vx0#+~@I_)VkS4Ak1IT6^R9XZu5P95NQVlI7KU z)Tj+*SlV{=tMgqgi=Lg^YYxGk{+G~u6`Jp3lvGi`+njLdwKD0{;%y?uJzH_%deW;; zTOmEP3@L53p&vv>wPgmT{vf5$LO@D}H5s>CCw9nPKb!{M-JC+NGM|c*7tz^!6J_V8 zNc*Jw-iLd?jd!@i)1C;Fmmh>2Qr&Io+T2#f|G@sLrH;vz>a{slCr{3mt z*+HvuYf=8s>(e_ju(9K=8cHna!;x1_du9C8{^AR_*{>$^5ZCugV~@)W|HjbP@-uBC zjHHADbj9XZI}1%@TFW~Yc|Q8@?EB2?zn|v+UY1^RKHoKtJ~50{#+3QJCENt>z3BcU z8!k>QpwW~9*7U>X$9!&Bm}{3i5M%o9Ka0Zx`kae6>SD~x`RGez&quAAwA@m zhBZ7;XVjqh1>@1b(2db@Y#yc7M3#O8shr{QMZfg&kf5&kLGioa)f_%o3|CWO@6JKs zKk94$}B}C=l^1~=V|(1tN;H4J^S|w{g3t;{vUkl`U_Ek zLgj(IZ{PIZx$Ij#b7^p9q|cWUn-py?6RLI(_RYM6T+QzJklXsF8rJ}ghi)IJ4u#JG zyt1}uMjT@m!uNr{oYcEh5NK{wq`P@T?c3*-Waz3hA&2pPaFece9Naj--q66c?2~(N z)10I7TmABY!St9AD~c=_Qu5K*w%&X@Vr8PDgf*rSZ&_BmYk#)gphn`7r@y~f2oKJ3 zbcQaBZ^e#bS`|9Fwz}0{v8eU(F*ZFl%aPtw(|v3f=)jg>AeD(p_>hn8`Apjh=#6TA zsB%UTYi8sszKmzxHk^A@-43lJNPM-Lx;in3z-c~#R+!X5USgcf@vWeIn>SfZRB%dE z-5>p=rK9QZ-jLQGSS0ed9eXRTd&Jsko^jIFO+B$)?2>O2RY0w9rc*2Im^6H!RS!Em zXPW-Gf*7E7FATx>vHNTHLBIBsiN!D92pH?o;moM_qyt~Cyjlahl^(YO#B>*&9$(J> z=3_RVU>AX=MBWU$Z2alqMtaaflL-{5`67EAik@8hP0x8sS zJ}HKf2f7}DX>B8M+9QI9;F~@@<)Vf&~ubgh{ZH<4@+tU{heO@yZ zi=bD3+yCs9<4f9E{hDEMUN;%5OB99qBak=dZ~B5^ZpMBT%P`18T@AQ#el?mCa!gOx z7GO143K$UU9wQn;Io)I^XZ3r26qtE5%E#q)R16nz0PcF{j)$N(Q|b)mt;qaEbGPwd zkK!9N$B}tQa|k)z>iw-|$WY?|n>pxJq(y}vf0Pis7S4iuA0*k{GWO%(9Aq|Q12izk zeeA&mrOnD9nD}`jQ;`xTA|)f+8p#F%M2fK*1d!_lTCabev9jz6#4LOvbVzBLm5(I5 zNY!GZVeEDYQp9A!;)oYr*pKVs$JxnzbD#TEFq(pA@*EW-Te zn((AZtn>2i&>TU}<2dZS0S-BR#tEjjANo_ubq30bOHVKoMb0+)3h>kn$?K8K=lupJtyfdQ+KR)hESR3x1y(F|*^%Qm>yj;q=EiHYt zJfFaZMo$CLLzr0-F_tsaQDU=IErP@WVc{WRc zKevI7k~at@NSI@E6!FpkH#qc_XG}o6bquaWw47IW&xdv^k>&%)amB%VAHTQsx`?c2 zS};`2qw6ePMu%3~M69YVgzrQPDM=9Hl5>VJ?PN=)D#VY)dnKSVJ^*WpSw{gWN@fZ9 zwak|Yy=+kn&x14DuQRUj!KgDhI$mec_7)Y9(B0MF1i3q@Xoc~*;Ea+7wZ{99ewL>N zF@SnG5zj^_xPS=^%q0kOO07V6yLVlaib7-aZ-R_q)CaIqu_GUt2kwSLXWopx^vPMS z+f_d6gV!He!DAwX@B}P^`?sP1UoSu}7Ja8r$CV1I6LkP)o^um0Nf7$fMQKMT$*39XdwKd_kqnRZqNO0`TB zlWl5(@WpulNKm#pz~f2tlC2WnQHb~N*IA;bU)(4S(vTx5`ZYuI1+E2UXEq!@7ewn~ zfR!m25|>UD?f=3~WlfH4Kg0BaWNy%!BUnAI8%#Iz!j;(R$4*U)H^UHxM$eLHGSYcP z!d4GU!%TjNN~(I|{NAWB!)fqEc`Rq-PJ1j@8ar?Y4&&EH05domuCnTM2P644R^r-l zd*X{r6Lp<2-$)Lrzj$7WhV|WFdek^{!T^mfbQ;6^#|T*5K4AxsDPxwruiEjG~1q5_*2t7EaYg$z~ahkfeEx3uL2izb|R&*5d@ z`<#3xVxv+4%z)bXjw7C6M3xyy9JWwj9jg2yBQR-z>f8Ct1>w{Ugz?1Ib-~-dA2OHw zt9BR7yVE60?5@KR<7vUJ;@NTvDACJdOvKA(!lpaG0eM&W-4Ur)!5-&aq!3WybvtP@KbOZU)_Q@M#mDodq|Y=F>7U8k-WU4ilu$8! zZ2C4@5{b}Q1l;zBMMx}dYTV`LYUtY{M)$4cmn#@*9*ukF`MoDF&Tw}LFv3p~GDR1_ zg53SWEkg!dx%BUOeZOS_8WOFYYH-MY%~RKUD_Qcn&ilV+g3Y)B5N$_$W%-|B2`v?pcg`4^y;RIq7M9^Ta@Tpb+6)9)tACyoD@ zcTnYz`3LDXX}}@Ok3TYDxkxNU0R|$E+iEPGFH zVlV1C^5~tXg^3pKz#BI(F6C$cBtSGM^oQqJ1r79%hh!T2xQ&N0QzjB^a-xRdj53pqPjD(Y7Hgs$|h0EDtbkYzF{U%osC&Vpt~L>l&CSuiRucE z6v92R1-b<&&T<|2#|BwP<$TbH21`T-EcMeHG#|i1tYndn-e)72-Uk+2k%8me_D3-+ zW{5iy{C2QKbam>fNDXXDk`l`Yoy2$(&gFHTDGzZCdLSHo9 zX0u|}H%M$tqLnwk+lFZ$XY4)o)9D!BPV*RW1qJME9`M&N(G~tuK*TQivHN;T=z9;` zxPL2bLw}?x+MZ~>M0_-zZh7F#!p62ne`}zCV5fsV6T;`(Y~#cY91~?p-lxUe>me|X zI^_{KIl*VJw8cKATNypx9m=rIuxzZx+dN(^u`TpsRb_}3m>N!m_Z662hzD~R7iP8P zn#Htkv7iJ9Lq&&A(88oPk0#UKeI{p|zeJ`0CNkD0Co*`$aVr6%miI$VpyxJ- zx~H_fmS2%GHUVASl2oA3bJ^n|fEAtgXIVMk_)H@8k<&xySQSF1ACGR(a?MlZE)zR% zlz`1N#i^%cpzQ>qO$$iiMfh;47{n}Ok^IBML~}ojJ-d%g6B9y&5pjb5 zVtnec$>nF2p97=%CB7qXurDKOEW=vST1Fe6c`tLy&LQ4_B7=Tyk5`;1%!jQoQ_A6& z8{c{JvODB2)WwrW%nXZZk_&w3SzKZOr7g>`5NQ*rVOEScMJf}f(iE8`7RoHf+-(lY z_7&tIC}}g(O6iAE(y#bouC@yz(lI?x_uENQH8pohzNYg zMxS=FBq5qNt!I{MtLpi=?{a8yetQ$CJgoJ;1v9TvuM0bA(S)YmEwRrC5L)|feXx^T z!b}p^A{DLmbZ@!Ms4Sfh+m{=HP&t1*Q?zDq$dejgOV}CPl;P&~-DfZ@$mOiVQ=b~$ z;?x8a&ut$HO6^~+xakVakd4o8U4pojkv=0##|igiq+QeL%!|)NXk3=phg9<>tUw0FTn)5cvL5?b+RC!8Wk#yR6C0kkfbx_7pudi}^jKiJ z9F_78xbn!mI?FzY>V>Y(mr8Deq1bVtX}Fe-kBxXTD`V%vi@Y(abv$=ggFgS+*DKg; zM=2G*?B#vhVWxR7!~)6k?kNdnz;VC<+k#NiLC~>>R`}b;JPe%Z_fwi~@R`2$sy|;E zcgifXJp+e32(sdJvuQV+zv_yxsHOhSb9H3Fw;qD~1#`lcMD-{K-j=7cbTZNb#~F+T z?EgBgUQJ4M_=8C!`^%0kN&z^zS>}3oRvmk6?4qp-FoKd4k4u_ll|V!S?IxPkgRdxT zBJ{QCHM83<1nvLg!5>iV@9H!r$4cwK>tA1#XMb=FznFCd=L1APf-hP$g>zPOe5gcr uxZAHUt7PZzC;D}2(*6w9^Iyz&GC-LZ9CgP&JMvbRe&ytLf$-(mng0Xfu+*{u literal 0 HcmV?d00001