From 24d126a125e7db3afc2293cd30783da2fa355678 Mon Sep 17 00:00:00 2001 From: sh <37271604+shumvgolove@users.noreply.github.com> Date: Mon, 16 Dec 2024 09:29:38 +0000 Subject: [PATCH 1/6] flatpak: update metainfo (#5381) --- .../flatpak/chat.simplex.simplex.metainfo.xml | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/scripts/flatpak/chat.simplex.simplex.metainfo.xml b/scripts/flatpak/chat.simplex.simplex.metainfo.xml index 9570f4bbca..9b915532f7 100644 --- a/scripts/flatpak/chat.simplex.simplex.metainfo.xml +++ b/scripts/flatpak/chat.simplex.simplex.metainfo.xml @@ -38,6 +38,25 @@ + + https://simplex.chat/blog/20241210-simplex-network-v6-2-servers-by-flux-business-chats.html + +

New in v6.2.1:

+
    +
  • fixes
  • +
  • offer to "fix" encryption when calling or making direct connection with member.
  • +
  • broken layout.
  • +
  • option to enable debug logs (disabled by default).
  • +
  • show who reacted in direct chats.
  • +
+

New in v6.2:

+
    +
  • SimpleX Chat and Flux made an agreement to include servers operated by Flux into the app – to improve metadata privacy.
  • +
  • Business chats – your customers privacy.
  • +
  • Improved user experience in chats: open on the first unread, jump to quoted messages, see who reacted.
  • +
+
+
https://simplex.chat/blog/20241210-simplex-network-v6-2-servers-by-flux-business-chats.html From 6ad6549bdb391e14414d383d6274d0d1174b28d9 Mon Sep 17 00:00:00 2001 From: Evgeny Date: Wed, 18 Dec 2024 13:05:02 +0000 Subject: [PATCH 2/6] blog: digital IDs (#5389) --- blog/20241016-wired-attack-on-privacy.md | 2 + ...eak-law-lead-to-mass-scale-surveillance.md | 53 ++++++++++++++++++ blog/images/20241218-pub.jpg | Bin 0 -> 232845 bytes 3 files changed, 55 insertions(+) create mode 100644 blog/20241218-oppose-digital-ids-they-break-law-lead-to-mass-scale-surveillance.md create mode 100644 blog/images/20241218-pub.jpg diff --git a/blog/20241016-wired-attack-on-privacy.md b/blog/20241016-wired-attack-on-privacy.md index 3bc69c8176..1c2961e98a 100644 --- a/blog/20241016-wired-attack-on-privacy.md +++ b/blog/20241016-wired-attack-on-privacy.md @@ -10,6 +10,8 @@ permalink: "/blog/20241016-wired-attack-on-privacy.html" # Wired’s Attack on Privacy +**Published:** Oct 16, 2024 + The [Wired article](https://www.wired.com/story/neo-nazis-flee-telegram-encrypted-app-simplex/) by David Gilbert focusing on neo-Nazis moving to SimpleX Chat following the Telegram's changes in privacy policy is biased and misleading. By cherry-picking information from [the report](https://www.isdglobal.org/digital_dispatches/neo-nazi-accelerationists-seek-new-digital-refuge-amid-looming-telegram-crackdown/) by the Institute for Strategic Dialogue (ISD), Wired fails to mention that SimpleX network design prioritizes privacy in order to protect human rights defenders, journalists, and everyday users who value their privacy — many people feel safer using SimpleX than non-private apps, being protected from strangers contacting them. diff --git a/blog/20241218-oppose-digital-ids-they-break-law-lead-to-mass-scale-surveillance.md b/blog/20241218-oppose-digital-ids-they-break-law-lead-to-mass-scale-surveillance.md new file mode 100644 index 0000000000..8a8fffffb4 --- /dev/null +++ b/blog/20241218-oppose-digital-ids-they-break-law-lead-to-mass-scale-surveillance.md @@ -0,0 +1,53 @@ +--- +layout: layouts/article.html +title: "Oppose digital IDs – they break the law and lead to mass scale surveillance" +date: 2024-12-18 +preview: Starting next year, the UK government plans to introduce digital ID cards for the young people to prove their age when visiting pubs. +image: images/20241218-pub.jpg +imageWide: true +permalink: "/blog/20241218-oppose-digital-ids-they-break-law-lead-to-mass-scale-surveillance.html" +--- + +# Oppose digital IDs – they break the law and lead to mass scale surveillance + +**Published:** Dec 18, 2024 + + + +Starting next year, the UK government plans to introduce [digital ID cards](https://www.telegraph.co.uk/politics/2024/12/08/digital-id-to-be-introduced-for-pubs-and-clubs/) for the young people to prove their age when visiting pubs. While officials claim this system will remain optional, it's part of a broader government initiative to move more state functions online so that people can prove their identity for everything from paying taxes to opening a bank account using the government-backed app. This will be a step toward a society where every pub visit, purchase, and social interaction becomes a permanent digital record linked to a government-issued ID – a step to normalizing mass surveillance at scale. + +Digital IDs are promoted as a way to fight law violations, and some politicians support them as [a way to tackle illegal immigration](https://www.telegraph.co.uk/politics/2024/07/10/id-cards-inevitable-tackle-immigration-lord-blunkett-labour/). But digital IDs themselves break the law. Article 8 of the European Convention of Human Rights says: “Everyone has the right to respect for his private and family life”. It means that not only our right to privacy is enshrined in the law, but the right to have our privacy respected is also part of the law. Asking to present a digital ID when visiting a pub, even if it is optional, disrespects our privacy, and is therefore illegal. + +Digital IDs would not stop people who decide to break laws. Pubs already can refuse to serve alcohol to young people and require the ID in case the age is in doubt. And illegal immigration can also be reduced without any digital IDs. But introducing digital IDs and collecting our actions, names and locations in one government-controlled database will result in making this information easier to access for criminals, and being exploited for financial and identity crimes. + +What starts as a "convenient option" is likely to end as a mandatory requirement. The digital ID systems being pushed by governments and corporations aren't about making our lives easier. They're about tracking, monitoring, and controlling every move we make. And we can see [where this road leads in China](https://www.wired.com/story/china-social-credit-system-explained/), when IDs and social scores created for convenience are used to prevent access to basic services and bank accounts as a punishment for legal social media posts that the government disagrees with. What started as a convenience, is now trialed [to track the duration of public toilet visits](https://www.thesun.ie/news/13154812/china-installs-toilet-timers-to-broadcast-time-spent/). + +The United Kingdom is a democratic country, and the law protects our right to privacy and freedom of speech. If we accept digital IDs as something required for simple things, like buying a drink, it leaves the door wide open to a range of privacy violations. + +We call on everyone to oppose the digital ID systems. Do not use them. Do not install these systems in your pub, for as long as it is not legally required. Support local businesses that don’t use them. Protect your privacy and freedom by using software that respects them. Demand that your privacy is respected, as required by law. + +To make your voice heard, email your MP expressing your rejection of digital IDs as a violation of European Convention of Human Rights in three simple steps: + +1. **Copy the text below** or [click this link](mailto:?subject=Please%20oppose%20the%20plan%20for%20Digital%20IDs&body=Dear%20%E2%80%A6%2C%0A%0AI%20object%20to%20the%20introduction%20of%20digital%20IDs%20in%20pubs%20or%20any%20other%20public%20places%20for%20these%20reasons%3A%0A%0A1.%20It%20violates%20the%20European%20Convention%20of%20Human%20Rights%2C%20article%208%3A%20%E2%80%9CEveryone%20has%20the%20right%20to%20respect%20for%20his%20private%20and%20family%20life%E2%80%9D%20(https%3A%2F%2Ffra.europa.eu%2Fen%2Flaw-reference%2Feuropean-convention-human-rights-article-8-0).%0AAsking%20to%20present%20digital%20IDs%20when%20proof%20of%20identity%20is%20not%20legally%20required%2C%20even%20if%20it%20is%20optional%2C%20disrespects%20our%20privacy%2C%20and%20is%20therefore%20illegal.%0A%0A2.%20It%20will%20not%20be%20an%20effective%20measure%20in%20reducing%20the%20violations%20of%20the%20law.%20People%20who%20want%20to%20circumvent%20it%2C%20will%20find%20a%20way.%0A%0A3.%20It%20will%20increase%20crime%2C%20because%20combining%20a%20large%20amount%20of%20private%20information%20in%20a%20single%20system%20increases%20the%20risks%20of%20this%20information%20becoming%20available%20to%20criminals%2C%20who%20will%20exploit%20it%20for%20financial%20crimes%20and%20identity%20theft.%0A%0AI%20kindly%20ask%20you%20to%20oppose%20this%20plan%2C%20both%20publicly%20and%20during%20any%20discussions%20in%20the%20UK%20Parliament.%0A%0ASincerely%20yours%2C%0A%E2%80%A6) to copy it into email app: + +*Dear …,* + +*I object to the introduction of digital IDs in pubs or any other public places for these reasons:* + +1. *It violates the European Convention of Human Rights, article 8: “Everyone has the right to respect for his private and family life” (https://fra.europa.eu/en/law-reference/european-convention-human-rights-article-8-0).* +*Asking to present digital IDs when proof of identity is not legally required, even if it is optional, disrespects our privacy, and is therefore illegal.* +2. *It will not be an effective measure in reducing the violations of the law. People who want to circumvent it, will find a way.* +3. *It will increase crime, because combining a large amount of private information in a single system increases the risks of this information becoming available to criminals, who will exploit it for financial crimes and identity theft.* + +*I kindly ask you to oppose this plan, both publicly and during any discussions in the UK Parliament.* + +*Sincerely yours,* +*…* + +2. [**Find the email address of your MP**](https://members.parliament.uk/members/Commons) and copy it to the email. + +3. Fill in the blanks, edit the text if needed, and **send it**! + +Public opposition changed government decisions in many cases. + +It is your opportunity to tell the government which country you want to live in — please use it! diff --git a/blog/images/20241218-pub.jpg b/blog/images/20241218-pub.jpg new file mode 100644 index 0000000000000000000000000000000000000000..0acd5d7dc1dc288021459830bc9310da96cafd68 GIT binary patch literal 232845 zcmbTdXIN8N`!|}=QOC+CDhf&-MNyh4Es98HY>0>`9Rg&OUP6Wr5|YPJK~%^90zw2v zX+j7{36YkJR3QYUMiN4#g&LAjQb;@7|9hQtzMK!|eK%M36|U^;thLu#_pjXdQhrl@ z2mN~cru9wGPg_8spMXD*k_oy7+Vazn{?}KxY}>kZ+pZnkcl^&K|63>Jzo7lUYz6%c z+WON;(3br_ZQcKqvK<5l+PUq2ng=xYe;q$<+4}Rg?K^;G>;^6%{t7gI>sFxA+kh4W zS0@0UgMQw>?ZAl(zi(H)|6s?-u!BaA)874}b+!8QA^QRTDdUIXf9>3LSnbGB_0!sC z&g$rzn3_Q@UNXOS{l-nJTh_N79G#q9T;1HgeSH1=0|J90BBP>XV&fh?dHO6d>3Q;t z^o-Y;S=n!La^Dvg6_=ELC@Zh2ts~ZxJ~cG9wzYS3c75sY85|lO8Kr+4V@ys>&&+b> z<`)(Pt842ULXlXq`J-Py0sZ{HkN?kp?Fag`<;NK8_|dPQw!{Fht^0r8cH+YJ1Ha$j z@gPj~q|xJF4qi=rSN(aXma#qm(8KV7U58JZOr93}=-U7E?EhcK{`x=a+5gkA|F>TZ z(4MV70fV=7KL`qvSyy|0lodpO@RX5mK$-Z>M_;}wK}}9oCw)Inpt;fE($X@)fhsE4 zuE|z#;Jx@9=Xk-Y0IYaAd`?cVCUiG_CN0R|0naFc#sBy|7X`izKF1&xUptliRP&l* zjpj+=VfH#Q+s-^96&9T2!o{RcsuGmo;-xX2Jnbkxh0aidK0_=trfjcus0)h}dr~pW0Nq`w-d1t=Rm|vW5B3JbdI;*lNE))dz{)N z&J1qFd@npu@{VsMj2NA)cU)`Uioecu2<2cs8ah9YviMADMpkWZSKa&@dp@2nL9(Z)7VxDrn&WKS7Sfv$2b{H zq>LPUgyu-c$_fYJ(Tdl_ssU>e2fE4-(kGmf*dC6K?C67l{V|xJTMK8To3Eh+{pBh9 zjc@oo5?@wAqFY=(#NC)FAG~(z6$##?FsL9^SI#PqOjq@FAX+pjx0Ij|yW>H?RQ!Ae z75KgXK&*Oao71P4ZOGaAc`9PhpW~(#E?}dTjL7p=(ryh!9G&y1XR!$?;8a?k!AhgX z*#FilK~E{tSjw@!LencPpIL5!e{$Z|HqvR~1rh4`g0DA>woMf|OUEkFSAHMCCEUp^ zoO^M}w$PO^E+rL1dxaHFqh`cgjrC~xv3Kg7YAl%)mAh{I%<4FIzq8JE zJF+F?4!fbehOGr*yTeIWX-}C}Iz>U(-qgBR=~MV0WKJde8qY=)FVvBeImPR5Na@mS z#Zz(;v<5>C8MXT*rS99K2L}dSU#DuGjt`7TJG}F z7u{Rrk9ReM9xeLhoPvwct;$|An`N*ks{V%A#YVRlM4@?7qR9UV`LGx|S+y*h%F{g# z>6ZHcyVu)()rXQkM@`F`uroJc>*9^AHAmnQ|1%=|KanynNnH^x(EW#6Pk?Qfni zKgNf4D&y+?StABLLJ2x#IHvIYM9_vIaWloSlZsRBWQTJBw|at6F&})eoL1+yYrAzM zx^;iIvabXldAs`R4(Ao3=oZ{Gfgr3!Wvaqf@Uwo$isMd12ia2M%$+D&6PXA!QoQX% z_?guCAOT?`6-)xx}eQMPY;)EahQst&9@gLjAt{bzTXoi%H}e zDq_(cX7aLzOmshlRkd$ejk~8w2}&L#yC^|HEhs1-o8D<7T7@W%cAH|8r$-L-*%X|1 zVjP+B3sehV0Tx^^PYL=pa5Fmz`aPY&{tI>gj|oIUa^0uXYq*FmlbCD`N>Yrh?ipId zC!n_SCwR*)5N`4l%!6^s-3oS-uM>hTUUHd-KDU5iihvb#7Ugd`+n)P0BX-WNQSmi> zf$YkW?xC)dq|6vIjwE>g<9+O~AF9OCA@#vkb}#A?QG&KEaOFvdw}@c$hA_Mo9CUthNJ3)qlm_C*iCKC zNn66KlfT_$IU1b17wSH0&pCQ%<$X0`U}be0UT4*iLt#iM+)$=Fo8gQ}76}@I>m_8EBcPH3y zy1CD4lU*!>p7|+`)9MMaH6zP1-?FhMBIFEQ_UJ=k^gJm|wv6YLQ{?MJHh3Bg(LvA4 zPY;;xKCY(Nd0zniY*^A&1AT#)c1E#7sbT6BVU_F+OcdIgxn_#OoNS!K(BPqB2Rj=> zu@)B1DSp~RdmEIoG*C2uN%I9g`(l5DxHdiGU zh!gb?+?zaH6l4xDY}mtYHk}SHT=X@pyIZ+M3DS+t@PG6;bibwCX7@Gi#VWs6(~~xH z+e;HlC!VI71!Y~1^c#DD?$t7kd{z>Tvgc_gR-Ar+zBm}_Nxc8u>fs5B5=6fxRe~Dq z<(Z10YX_HPhfp8j0YS2g_YJ%k_g4ni*L7Aai~83vHBC4G>?;4R#jB(@P+lCccyv4s z(^2o!|?X4;0a_*<)%qos{6N8dsa(RZ`(rz0k-#C;87H9WN*du zl!8pWd*>QQaxqBwQ5;)f{Hp7&HaY2^j$_Pz#T8G#%%ZlPo{z0$`x;o9NTc6@u{vH^ zYh4?s!4r6KGz)ZAFD0G~*Ai^By2}g&$2yK?DE3PUQW#QJi_9e(@-4#L6g`+phWPgs1^KSi63jc6Pu#FO=s&igSLNO^5r3?GDy7wb5B#!RG%NY`NwD3RDowtYW zM*GLORh+s3?cD88nKHuxdT_#mR$z&I4b!rQVVlmY7a1PITwXC@A97`)E(!b-BjeVO zM7HC;$0W{5Es)as6dxQAX=6CZCI#(};E9WgeoD|)TPY=x;!5>Zbf^lB(Iqm`rrXV*cKOylKZ@73+q3BKr9WJ18?s-#!&ChJa9TRJZ{uMa z+|;}-3ijd6sF!sPu1KlQkxJ0^h5FTpt2cV+*2PLtE2OxlsS7L}@%WN#m7UeqUBGwN zLxi)1{~6VA$+D{*k4>_B$w4+Ui;(gxidjixBKz}s?V^G;!wDN?y)#pLsp=e5I{PjS z!z-6x0*K#`7;pPYo|s|v(N`sEy5$NQzET0%3xAWF_(_=mQ~dyMoz;Ej*~C=}?br3Hx@6!d)pmO*f-vgBAeWV4wfaF)Z+T*?2a~lZp0aFv)N! zr{+}3SV5nJ1f3utw;5(voT|Ormw){)Cne~=L{y*ZMEiBA{s2s4+R;>h=YW|APvY*C=mH zhO1{P0d7vXck+L^DauClfpiX)0*OI zG5;>UPQMK4lVONX+9Qxq_UedDiu?Y@Yc7yW^o>AGsJFJ3d+LHi-;%?EZVFOn`k=0$ z?iOqR)nsMFzX;IU{{1+#qR$;os0Jzr89FM0baLGe-d{Gz>AomhuXBAm~%1e_Jy zUUp147kJM9rTc+dZ|$~Ye%idD1pVALYym5g#SWfm;J=25*!*Wp@P}9%N?JjLl~F}H zrvK2I8CM~qdbue<+sycTpekrJnd(>c2=d|+8^I~NxL`dK2i+wH)WC}3Fv|-Fdq0;Y z_OYjhnS1M>1Sbglf1HWo7L@hEnj8!kp*nt=9Kf=)h}GU|_c9*V-AEUIcTcTUaz`GRa^ zqu+EIA2C?$dD};dOOg`#I~D{4)sn_s2K3XCQ|>Ldl!v<)a>xn8v(4zgYNY;m!uFdT zic$I7ULV=STd(-QD^aM(_vJUf>S15eQBxl<9UZ(eKRl@+7q|sh*g9BMIQEX3{u9`t z)wy93BSkAgrdW9euGUU5JU*;`vu^Jfo+4qvQE}pGx)^Fjxy~30a(STy@sCUc5L#Xy z^mqM5PDO0bDr4#2M!nVo^F^1QB|uzFGhMDtU##8r!ts^LK0?K)%SnHy*io}&A7m!k z4_JJu^iPUji26&EZ}rE)x-To5($;Wyi7_Pm@B(2b(F~crg1TiIPWJ$zN&c4XZX3CVa)7oKZF1b)AoA(eE9YFau zlkiz;i_%MKRf0bDzdDB=i;MWM=%vC}6qcK=H@P2yIi?l5j-c0}&2YmQ8WFd`t?H{E zc(9oKSk92|5s!V}jYEFZ>QMa0?x-c@a2~(V_S2B5X@Tf~Ti4WC?o_&|6FjrfPtHU! zb8;!>I4=oKoQKayo~5N+vD}e)c6P8KFf!IBq!|1yh#ii%A|Ot+*l0GV@ZhGs3BA6z zvK9N~%re3xPr?bhwXqbE&`~x$`i^_o{@jHk7x_u1UU~M;tDjHmj4@($A3MBI)NRm+p|+W> zc4_j&s-|wM1Gp7~;LqNB*uN4Qo0Ly^MCRHOBlKV;Vkjs#dDm5{00M zpaF;`w2;BI&jZza^*_keqTbLz zz(v89`eo92O>E*PyNbz0DLdf1ti>8Gzw~}x?uL^)nciv2C%m~lXd1*XSZS^15vj^;Bi70oC z>;?l6ta)U9Kx~)Yfzfm^=RJLNH?3?jW~m$=clG%8)$6Vbsr4+^iK!S}ly9ZiVUGmD z`BqBM;l0kEAAW2Ucx5e_^mJR~dqnFp-}^eJ0I=MIVN~@)6YDc9OT!IFyRj$D9s|NP zPjeP2j3%J}D{~Ww+OdZ*pD)X<7aUP&w)sMslZeZX)r~1G&Yxf}CduTQLcn;x5^> z^#GgefiQ8pZ-2k@JHfR|-sRj*tiNa!7(@e|@VpCzi+Kmp`m6>>rEagKcD)~4zBub_ z!s6M7fY~PDsTY%vCy-l8SA2R%vVA33``SG8CjH=H1g$1yS7f-C9ttZSN`b~|y?A|> zR#cmod>t-bd7rD{_b{`^D!%O84BHOtIIPCwLHWAm`w78Q5N+bqIbVl#*3s0Se;PZe z5K-VlIf@;TJ9@z=8jHMjCzyPLAV1^GcW!FBk&8!9K?m0{+5PclHjMLl5mV?YCL-X(L;KDlBJz zj9J;ARMJY#N>I;NTwhb_De3YeTf912no4l66>tcC8G7&8y=f3BG`eQ}gGE_p7he(| zE$3xYr0TrFqqnQSJ1TzK44i@{g2ym?8{P{qGfG3V^|ZM4>y2Ht2{pq+bbg(#$I^4lw~;!gbSvqH)g|N&NYc7sA0U9$>Je+U#4VMK--`r<3deRA-z#OO0qaw^< zo*~b`F>qDdWoEp8*XxFxsL-Jm2iHNaA|_#}e;s2tvD^{T=9mi&nPr3F|C z`USFVEa=`aH~?uHwgkIXIOt2s&dsSe5tLSZqbWdYT^`#!OsfSOpyde{q^IZ6C;0s` z)d=BZoHZZqUi@{qDndndruy6S_T@U)htHmTS@OJ_jmlaL zv6F9UVDFuW7<-&(z+_7aUMZ7#YQK{tD@E97c9R$FV!?@5gx+xW5ku2w;uF)msljG! zmBdP%Jg*78fx7?wGG?!>)F4*cQ~wcrFQeUDe`i!wBtHD3LQotqjl>~YQp$w8lsV0N z-h2hY-`e@{+QZ7ZR?)6%C8*ynTMPudJ|$?M^`uSJW3RKs(dCMpA55wHgHZ_MsN<9j zqxwvs?JKAqFPc|m{isJFDY zg4zT~_zzLfy{_2%=*Z&B`=0Ek#)RT7rU_+~2`NQpi^@B)_E4pgP^^vSp~o~;0Mnb< z$=+*v*+1nFdPe{>$Tjp(X7q|Do+L(#s4@eOl4O4W??VPLY)QzEu|ZDv?{iyF`7Vdt zUON?!c_#eR)5E$cGToqa1Yq#~L0ly$F1JSGT5|vdM{$Xyd_BY2^E`3Ek>J zg!g&o)e2~fR}{f^?V!|5O{_O8vwqjMPn0I9xGAN z>;r@B3lb_xzPa!+iE$Bs?``2qKFhme>|5nJgLt~DJx_N8hGt6_$x$O{h^srkiCsmN zU0%Wpc5qJ=pPSsn^Y zDmE<+Fo>=g5Wl~a7PBJBx&#%lbIA|Ld_{IJpR-$%mOt5Snh+JHy}{aTI@P7#)g*=i z37ZWB%43*kx>vJbdV4lc&Cyeu5zUz85@{~2nkuARrqvJ<%_{XY!I#4-$_dAqs4pT^ zIhA8Yl2T03@%hf1o#*V6Hw#q0Q)>AaisG*S-B$xyalAJ ztk`6XO#ZRneq9(A`pwOFv5INbAv2WTi7og&E{D+(@-P#}gUD>SXkf1RHPeWMif%7p zIczfz_S6$DieHwv!t~9Ajm6E@dqSF=ocq|JEJ~Xa)PZU7Qa!{GO7zx$8J2hR>lV5u zIA-TelN3Ko%HQU;v%4I98XKV6J*DRx{Mf4l+@tqP_t|qh39~CP(JaM=J<2*Re(W2B}=WtX;HOt(!iNm+G>@v;`Nvfj|=$FIKTna=`}Xs;FI0;Nr> zzs_jY3YMh=p+A}&z2rk+I!XFAW&g;Nww?>fW&5ugFjr($56p9dD4??m&5&NPN3LI;(Xb8MBM z3A}pr#v8KYfn>n#lO&k@+Phz)K*!#48T++ge7f|nsFwJt`jqlwx-g;6@|RK7kQkde zQbw?rwT7NyPeqNPAXLGPDB!zr{cY*ZJNTtijq9nj6BL0zHRx5fb(3r0;aenKQdUn7 zlfqD_cgP>hf(2Ubm?H+1Nv~MvP5>LF+d4)%Gmdcsa-TwtsNkF?X$654w8C6-i35hI zXlPvn3qt7#oRf<%{?<_+#JPuRVNOrFof@&TPEM|)&=pCrOm9^-vN86wDx+Q8eEeeD zbG!a%`1diI2HL|Zi*%z1YiDG=>e3osyRPZ=%-5eKbJA{G)a@5uXLIjsfz$E(%DYqBXX#^lgFQDS6OiHLWdkr%;U0KpV}># z?y*-K!ZDxNnU}>-_59zlp0b3+g$-(e%lFizvXh2yCr%H)2P|X%Wxf(5u=Qw1kdkgQ zN4U_bfk4t_C5YqQ=t%*Ttkn-+2g)J@$gC{2#Qqmbk+?@E&A0_^UOcJ#d@ZJxJHVT* zxAsfAo-06c;OC&{E@?!dD2sHe1m9M-fA7m)kq&3&$&7*dFma6eJrA z9$B|Gu;@OGjf~lSEd7Rt9zsqv394Yniwd}is*;{K%W73lt)1x7H)(;e5)rf{)E4w7 zPVr4SPYQut(JrmVTB*|vMqrd~x8I$ceq>tW%nmlzt-&KCtd#@a$ldSH0zU(ky}~UOzOm>3qy?Wm@Z` z7?SI{(>2F$j<=?e?>4UF<-bdT#~hS5p+o32fSQbTI%uaZ28dAWJnm7zPtSDnO&I0^ zpAMYOrWwt+w|}igmSuaP)1AF96HeBOim5$Ngt1f9jJIM?2_iXIP5mVA=?uK$z%Qx5 zekprxv)P_9kGl07jgjvw29PKRrUWr65hV%3`em}6R{B>jmgO0VtJP-gT0Hk9O%cqH zNebio90;rXL8$~rLioXe$FhDLkS3{g+yzMuki+~=v?gnaveaWCqQc$BY?#k9|O|i;peI5Z)3T{MEfHvZgNl9BxhjvRi!>YYl>s6uQe^SC5=C zSeGWO6jki!G1$xWB}^+cseclaB!VdRFe8NhV=vp&>%!q*Xev2{ZL@XzyQRcuSvruo zAc_&GcSM|ln9_T*j7V3L9GI+-tN6PP(CwhD4Pv(+cx$ zt-BGC=4Mt2#Je}5{VL7C$KvACE12RF-mmf)j`4XqOK@5MHlsmm%gE%|D$L^o$QA=QY-s)uHh z41okYa1Z%!@)A?SUt=>AJC&fyZ(d#qsb-pbQ0|@Qg9dNISnjP9zjV8t!t?+iWVW0z zB0=!09ADZBqFt+$^UW(%g7TqJlq7k9>=DI*640OIwQ~UT2N<|ztC!||^#!%N zDG#MFx=XJ<(nz5^1E*%9GcubRw5hKqd$|ZUz|Ja0|3Qb2$0j)CK!y$f$wHU?-%oj-eIu&Bk1b+dip&uuY@!~$9)oJ@#v;kchRyrEPUc}J zU^}ymcO#6PW^*)5@YS_adqnmWkQT3+4nlxD^}_Iddsa01b_ZvH65wZ-lUZr-!$|r!6C+q;?|9C^znk$BA023m&YU_VHY%M7&}F!9 zX6`Qtbeo3NtgOi`TF#~DlBn?ikW*jwr&D+?UdXf3fbsss^L?&?-IxnKUB_FoQ$gw4 z4bJl;LuS~0>%ml}J}N@~n%I*0ao>Q$F4P!3ct+VQA=Jv1mClQKJZp?9FwCL z`*u)RqG#QJ?Y?GBB+mws68-!`ijC~{(&Rmi3zuefn>)7oj1&7&cT=VZmi_L=c-?Bk z0QqHi#@^m|^xfb$;xhjTMCn4bip<5{2&f!z0r=tL`wpzf7DKNSrusXnu)N(J^jxRu z&egWy;H?NJ2?ktBhzBGm0o<4Xh_tWtA3+S@!7C@ zX}P_6kmAP!FN(su8tI=&b_dfjyAe`$2RxVVlAR6S*?cVpVw?Sy_=8Jcd+Z& zi*kV8<5z`T1&>b$Lj4iI58aJCpy=0x@MVzm4UPQv0gG^m)J7CM#X93`WA`{$ltjet zSP+GESKvQaSsnCS1&`Mvoc+eD0e{JvY?JJJ)WxH8jGuDpew)qP)t10!n*HR!#qpjd zjL?0YKXbkdQ+O@n@cfE8lvOTc3-~>3zF}5%R0=>X=qk^)(hyC-@t-e9a#s=oj!%Z+ zA`U1)OggQe?7f@!PzB$P*hE4XcXKf#GmPtV!lURwP`4jdjn}d{9h#@h5Y;t&Ep&~)(OzS7V+tt z1Q~4U?Xcy!VETBQF+vG?^eMAJLXqksnQ5>BS#*P@?#K7C z(`FXH!Rd{Ixqsc1_A8PcxD6>SFZ583BPE{O$G*-wZ{QT$h~>CgU$yVK;&gzZubC{h z+YZXv>v&9#i((5~G;(d)_BJErRRr%5>6K&cb&_4f-A0W;1!=zhmZ z>e@|OLQpSF(NC>!w(w~v&#RMvYZqWnzYh|rjP0;%ZWcd@DqNWFyi~Cc{A`?zky+Kt zq$F{w4x}{KQ*(vvZ-urH%Hh{VD~C-7NfpqzY^gmB0H7wX=pFJ!?J=zMRsTE6_YdKL zWKB7ltP^-^v6bB(4@Zi!Ccr?+K$c@Z zW^+q*m&|E$eFYuZ60GV>QdDh;XCFwD?__vI z|DiQ4XS@fLl2gpXLZ*5Gd}5eWXSO>Gm?qIA#N4aPs7zX5{OCel<&)@%4@Al9!j*y# z-+dwvha*XzWmFf))ZP?idExt%`ic=^@x)0PmUw#<`dn*G%^m<#T6v(%D*B=1V`<)( zF5Y{m6f>R5(DWk?J01a$3M*ID9QkF#`}R)cpMPRzEA%UXJp6=9u~l}yndME`EjeI4 z{$(TfZ&Sy1jwVg*NL)rBy!oSL2k&*Oy&*>$%vADLS_!0CKToz9yU76%I`MS{zb;t* zBn~SPmw)zJq<46odLnf{8gt`MvJXOvUFjlb&q^tPLG&ZTYdieCNnUh<@A3k5@!Y6gLhT(SIQH@6u)!R2 zt6suLs!GluP65nWXT|BN@=hvFf7WvMHYMn^2J}2T-WanB(8-?FF3c9y2q##grT6iI z7zVNV@=P7>xa9`Q${1=_2u20jnjqFn6_@N%r(@WOBsDwI-~5*jl`lis5lYZ+6%8$G zBdOr=^I22OnEqXZrQevmR$~3cQEbeY*R%X|2;cNTcC*KyB_|mRHKEcv-ZJaT(x0(6 zc8s&^;5$Ceamrq|2!>j}%ymBTV_V7wA&FcZV2BSIJ~?hD2z}SA1!#GF)`!ccr(9&ID)WpS8#;Q#Dud)V~c4YwZ1{-II6xP?elqtGLKlTgk zZVkk^jh9pjX=VX_Oj2(;tGNWhZmlS1^VK&k>hGtXJo5#hYG=rVOQ4jL`>q3d}7e+T)Sj048_<3RLFxWpCuRT1ZurpbbXGxe~B~1>*u40$FfLz zz)(kc?#L-`Wm5)zd`%b3-P=T3Slz0aMQ~5(9O-;Ad)@+<35?-Q*6jh>s}KTxSYLz^ zeq&lOD~^(9FWo+n^ER;4%5s1r6Cj35uC(mO|Kk?<-ZBBGetZ2WS zFd?Vc%Z%s1J7eogx7ez)e1SD0^)XO_-sz4M69-HBS$Jbt=Cw)a0doG*T0k(TTnUQu zOCe#ViN)Zlx8E9}pVHc68xGj1dMs!3T^3oqlymW(XP)Yx%y3VifcYj&fOBxYo=jLb z5+`S8^IQxn^#_(nxS^l&G7A-lDqpryujCgQ)>&H)Sv<1QuQuc59!|-+;RO5&p8Xjp zK$E<>jtSEeZ54(H4w_s3wRvik?f{h;+dcnJ{^}I{%U=LJsYWoV^=UaMIqgg@6NaS8 z7iFfM%*#lF^M1q>K)1s)gExPc=b%*O)qsz5y;%^GcyPj&ueo?e>N|{SNVGk-XbM9b z;DTy(B`?_R_*GdGo{zQXhh(juuHVotZ}J&a^f6M;Doik~5&SEcZl}Nn$I9jGhC99y z3U1`??_(s0z`>u7n5yblf>89{%3yH9a<8FraDq;-TQeA4Buly9J&D^`#FZyQ^fk=Ux$^g9JXY|0&>mHJaY=$;$%^#n9I0!Q%aup zOLqA0G%R;V1-h#-ehFST_vA#w+7asyHE}p0mr;|zUK7>RlVTSUWP@SNgZJ#mx(P z6cw4)oB-PC@50}Gt)6ayoMb_kFVNz`rY<@?NQSfL~1W!UP4Yqu-M*xK}Yvq=|_-nJ$q*Lp3Bp+$%P#s)xNb_DOrb%Fz3Up%DGq z7pwA=s)9hWUES4zFL(_M^$KBDK3etlrTpsJw7*PMV|qus+w!@(>EQR*;^Ix)35}a; zT=yVqLv$tJJ|$=wQddbL@Dv9N) zfWK*4BVrgOTnSl@^6=(;k%}McuEux$uJYm?%~mDZAcq{`F?4E4q=TQsY%at@Q6HwY zqXbJr8gR4a4L|6wZuM4F5A(d5giTy;jth_I7?^o1aw_Iyuy7aC(piF`xDcYKmn;*2 zlAQ#4Zt+MTk0J_k8ad~UB#&5jUO1QUOFeGqLL8|R?iHbt!g6`b#uGEzk{1+N#qMgF z10)&}e_o8YPpO?VwHp~2u`_#R=S@0H-^J9d(_fbco&q<+aq@COEc!oirnQKv*u;-w zREcNfVt}FEQb8{7>$x;?4jC(wt6349sP9|iu-IZ-wW-qN^$*L8g;UwqQu9h)bInb* zs0T=y!h-kpPej9;%p3bih@IFu*cTG2DTgws z2Jr9?GB;#I@buohjJ3ebDo!AZ(j>|W%-{2uuVCBTFLA*iVleSBZ}5#RGN|-3UyK#S zg%{xAnikM$D)?JcXO%D@RAvh9*eHi!4iLU`3Oq}k6EF2)VeZn(xjPH z1K3yUC}YfL1N2$(T6@;lZ;NT-)k9JXh!>Ja9@`TE6lL5QDe`j~r*IP%Wh_K=KSxS2 zO5m>7<|7G(L*E-;7iLj$lH{W5T3?@U_e1Hp2e*sFs2me19C6D2gt~{uY729LycatLB)Y|JLyDb-g2UAI&AlmgMge9@(6^WWu!(&I zkp$D1kZe(NgQZ^}1k%$}PUL$47W+Cqhb07zBRmf%*X+0Aue15rD9Md%VF>nv?E@sz zprd8l`Vg7<@(MvzFQcs)0b4kTg41nYajz6GGoXe(;aUn%t7U1WD->qybW`~+T5lkp z6Mts^!Yy*B)~j}_bPAgxjpiMn=|NBLqWIofKkcwzH4&(`vBW86&5=)Pb?aM4<`0v) zH9|B11EG%eg$j_@s|4?);@$}AA(z*yalnQin*sw3IqP+&7*1#t?Z=NY9qLnUS6((P z-No8}WZWMBHXc-sOgD52G9Shcp`e02`fM%Czv=IAt>hC=ky2xbY)cD?n|p^QQUk9z z0uucXnrITM5aWfvYDuqpls>L6ATUV%{%2&{-yoyT9(vi_?Ike7PR5b6ih|wLNl#Fa zFv^U(ec?G|^bISGomLacGr~tBvi!pWn_jN8V9&VaC{TY1WbRxpz3V7*SM)zx?vC1Z zBWmh$B*|%&;ijf=H$KPhDF=$QHw@Kd&-L5!?OvQ)-hZtsX+6{cC7er_Z<>5G0xwM99rwFiZX3y*S_-c#BRi97f93^N0@7({_ z^|p3~(TU45E6GuBD%>;ugg-kBS2Mpq%Xl7P^a{Y;^| z`Y}u{ySwaIc+8{-{Te_NAJh$etXJ1}8j(0{Lf1SvlBKwT%(7OqXH-y@xt?skuGoIf zgVKx;L4ZmHzPZ#vu{)=T8EfS#)|p(|k@IdycAD_}&vX@Oced1x5=)gqJAOcVE103_ zH4N;dS@PEH^eBD#dRFZII-%lypg|WeW|{K@*kdzT!?b69TK=Hn{JVz{!P%-s-9%?O zSdu@S5-A(C$ZbW9c-h{U0QPe#@lM=~OI`61oW0j6#1N-kr2f~0m@b z%RM5Es_B(%rYpEdY{Q$i_jfx{d#viS4Rth&GHinQ%?2lL;T|f$xNx9eN4Bd)&m+Y` zLwd<;Uh^cMol$P`Yq|BGgcfgHFK$+`!f}#dULvJ>9(OZJm_dgd^Jcr#4)ogu4rFEr z+XDP_gz_DR;pI+! z_`0D`wcUcy%hqORwJZsLsvh0|W7RR=xNk~@iK#Vmb|%b`C}l6pxg+26-BNJzel1cV zsP5w^G=O!0u^Q-oAZYWdF^oG-lb8Ll6C2sOB&liJW5DmQy8A%!z5g~KMe!3?x?~4o z)0dgIDk%JXIEpHR8_C(i;5k~~AWDiKr+hEEKP{AtyJlnqfR^YO&IUYAKe&8*v&-_N zl@8qIsNHM+{7_O&@)2x|V{s}JxAL&WH3l+XmNjDh*gc+8UE;DTtlDfuU68S(E9BY8 z+u>c+HF_74k6Lrb7ndF!EUaDa_ zgK2(Nh|KY3YMJo>KPvo3%8F239?=-XPr0uo_h>1%$pm_U5nNg@`1>tyaH5WeREM>Pf0IIv0 z|90Z27`m-@bbnWv60{p*Z|zr`nPo6xgPL&WFlY@V%)h}))o7uc_xF#@e@`7Lctf(u z|Fc1%Tm4UMSD0eNDF==`WQIGF5k~Pv9V0>S7N2uZx~m=L%nf~O7OZ*YT2S7`Df3}n zOp|MP;kQ&RmibwvrKp?hV!(sMNP_c7bZ!oL7Dl31P$TYtiRwC}T9_(0ikrdj?|nfD zbN~2&u79Y$sY<@#{En`#A*L&&Wzw6&g7dRxM+YdgDb{;{?W+-hMhmZfFj_aN0PGO* z;`pOyPYO1u_jzCDOWo6ocVA19>J^A*PrqgF46*DoZEQxLMF^XKdCMdK8^Yv_Z;7jn z-xUqf1V7XtL+iuhi;OPe)f~#C0Wp~efv|$(ph>_es3@KQd8~2^#qbR6^sYC?oiZr$ zjPRp%2JbpM9w5KBy7|FJbp}&sQB2cM0b@BNgeP^)P=FelQ>aOI2x}|} zX7kNuW(WxyK{1H8TP`g-O-Ze&06>u-dj)8< zD-)kI3Y|O<(kuMhWV|BHbhnB8iaIkz(6i^4i{m0OyJ=BjrSsLgV>N`S*4pdrIG2zx zyfK1B#6SKd05CSRvY>CoDF(%UL@^LV?0!zjz3Mo&NqJ2CxE}tZnblW&Z%}p=Rf&Co zB*}YbO|e_V`_`cIhm{~hKG(gRF_*~O9cSJJ-WVWWe-U>QtIk zul>Pkort66bFCE69k}B3R~dWRAZ)YiGZT@F ze!dGZU9)PV40kMkoD%`{997P#zR$4?i`+N*2jB7Yx8l)#mYOMf`wyz{5S7S#^1SuR z==b!d;6_dSVYw0{qDADU#SzCr^nAKo#$#X#{^7|Ik*m ze(6#|{NCY+6~sbr33G%z`{+Wi?pvdtk4@KCkCM09s%+*lDeMw2l+kdr)_1n*A~I+Q zR{vMeB0I{Z7p~B5iK{fLmjls4v;UqrVtTJx@E2|+bW$yifF95-ih$&RML1xK@z;N+ z0V;Gb?ovJMYW^07?Fj@PVy_WU3W<-b_m&uE5FLHm~HvBm7g&q zKSnmQ{LYWrO!mWm^nLaH%Rl>Juf6vC@pwKSkLQ_pSECYZMSuhUJL(^nthB``2iIFe z!v%9_N&aW2(80Eg;RVw?H$z2QOZjC%V?GJ6;=U*ZMG|BO#Ioa@Yp?q%e&y7MCs)Sa zG+8n-X<5EgR~7LIDW%D=(^|cu0uS3F{fP9^31M@=)B1gEv10%6zRx8bGVkhz*{jDN^8T2JK#ZT(sW2Iht{XYzJpn z1poA6y0I*oW-~tg@L8Pj+91#8Rl`Q`fwS)uM_b2kiJo4$2WZxuSCY!Y=CHA#@IFv# zK%YSFUK#%=#UBv8FmN9#Q{9SwOw{QTrm+N-?iCZ2YI^khg)G;ALW6e4m@G9!>RUyEkS%rZOGMN`Cg8dcvY)piqgJOS$6L#SGgtYc#Y&dnP0PO^K4G)Wx_>#tsGQ@ zf7W2vrk5RpZ_a{I+R|#-Ilda%68-59X^YP`Jp)lcwaw^ID&cDdY=fU9%gA1}gxh2C zVW(pd3MP`&N8z&WP3jDhwAVD>>s_=shUtXngWd1*^RsJKe6 zDGh8NZhta9tSShREb|CtEfg;!kVSYg7`U)P)WKEB>G%&%So>>syU%Lmulb6r=t4VEf&`DapOmWv zpUXe=XosaoVD2?U(%P!l9D%>d1Mb^)!}6)4Kmu zyX~N>&V9LI!~ZJM(aj4PpzZ%d(e9o%n+&_>Icat}Mb(|{F%^78AH5lq^;^%gCC?|a z>z1i8j$?OLnVRZ^SUX96J66)388nad2bx>ofQc^QQUrL(DA)dFspARCQ}macTrqBY zV!FCrB7AMY)>hb&6RZ!XJs2Pn9TrEWI5 zU~Y9er_QL~z27MqA+E6&$7}mhA9X0>W^FU^{2+>oR+6Cl-;y_ekYeE-<{H?sw)K=n zj3F7INEnJk2FCb;esyki&a*V~9Q4}g8AhyDPcx=(!yjNf%#17@x*OPljPx?Z`ZGLNX3l!GZ#1j-Lvp{T5K*N-s#T_Vpi6s6C0PI`;z+ zHwr}6fmKxZ#{4j4KGc6s#c5<^NLvf$_kWv;QD1M4-*ICOE_Gf#_#&j(=zLl$x0kU7 zeYBwiu<5ySe?}3Pnfm1$jYiTBug`w)KU!Corqktb*-j3@r)7EWYK%AJo@LSna{crs zFTTCsW~(k326OGv8{}fYFnz!qD{_K4Ck=L$-t^N7c8M>rs$LfsogX7~?AnK$uDsu2 zygq25i?J+}$8K2j(4lcLw-w7FOdmQA^9XL}ej1zAW7gN&h6Zkv$M}pl)*xA<- zPAZ;_<7hqD3(O3-;?|UH=DzMi^Lme?0@yku7NeRkU;i->rwNZPprowrZBI;mF`xD{ zKOE-M!c2%CZBv~NdJ$F%KUk@|wnMP8kp-JaJzs^b!*XCVk(&ck>w09OWc?T3L!Wq) z7!?r9${A@(jOmZ7=nc}N3n`eLE0Z@xXnxB;Aqbslny1GdzUqQO5}Mo_mF1Ai5Xq=OfUZufXK1u@Hy` zzr)$yV=ic2khsOooh9H3e3)Pvx}%fF7UL*U)x^A`536g^Fs68GIX?BMdV3LhU6=N4 zAVaL;E>5GMSxJ~>xBe-fZB^(Te%WsjtqzPd3DwF~Uogf1-NLhW^PbNg>)wC*8`g-~ zh#zS`1ha7&|NRfCi!bE+s2b3-LC?a25f|{QV>ySeYY>`5{gU1HDAS-MsR@qjGmX34 zyLf&hixn{b+uv$~oRsJAztA zEB#RxcGyYOPnTbC_I|8yI#ueKU%dASOMGa8L0b2JsqJz#_R+-+YPYye zc&iJ&*;6f?zGhY{4b`oeQ+x2Ks*fE~r}|-Hg23~6{dr3iJr_8>+^*sLut*}hxeOyZ2SbzPfXM=Ky>h_pU)95H zAlZFI8QiTnJv1pDm=?Er?)3LXkRM^Ur^$Ls(d=fGFA%-=3s`av?z+3pNhMHcbIC^0 z_0H8*zS DQ`)Pc73<-r#bZ^sDutViF_XT&N_v|uTDm+s2{p(dMTy@1GXQ>hpS*Y z_YO{U@Nwvo&s$C%oY{De?bhyWsLSGH)I>d2zf*V!9uEgTY5Ln+Dm##*Sw}q1m7m}L zq~OtWmA9}JW(Gdxi#DlX7 zuZJ6*G;E+U?W>x!cOr?9q5_D>Ga;O>MlhH0)SzS#qv^l$Pt0xJzK>^&SUZTC*AfO@ zYtP*=vL_-*WkFOuP;d2+UXS$0a;Q*Vd)(`TuT zd8>hqNHO%T8uH@e*0*bbrSuf82y>?)KamD(!5|J*ArZC*BZ7)TCGx-LpOCagX-ku5 zu(K&#>Wa&$*`H?kG;qlNqE!bAAbq$LmB{=9t%^QVsydj}Y9TG%$i%Ijx$k*2??h6K zk!j2O7wc)6J{p4nZN!3qO>+YOIlTENzndkchC^AjwU-Q@s5jr?C#Gl;ZCHHWOP5}fy6O?mdfTGh)H+>s+&lJ!j1 zjGr1yJdj%sA*SVjsV~V;2y&~##U>PDfBChtsN)e)1?R$HyyifE45xXH0>0zFHm%42 zO^&P9b{`G|g)29A8qt-H5Fx4)$<}Mf0o}iuiEd8ve~XuR3A2mM6c%eG?I+(y{UHbp zM#++l(XSXegU||8N@yBu322Gp(U>OMMuytJ|8-L|cAJs&@TD4O@xAZs7h@if!wwdp z&E9|BlEI$nV{6&glCjb0Bb-9xZ(lTF-S$eKmahAMOM=~Pa=gX;mxwZ+zSf# z#?6ba);9{a8^M%|g@3Si*H@(D@c)cR&E}Mghjbs5MOHO2CZdyyY(6Ez-(~&)dE=Ls zeW)ZZ-cNR4cKwuoYKcb_LoZ}8D)I>rBz}VFy=w3kH8;Vwi**;D8?&h3zv1ZH9{&4zf71m zA~qw$*iov3ird%oVO)=Sfyc!<#a99(xx>b}_<};{iDomR$%ww@7paeDM=L{YTNjOx zPx&0P`eu`fnnq}Ve<`m2=7DIOMMF!PuzAg>1hc2xyrXaEqOe2QuAMRj1WV*paf`rY+ZfZ|TK>}SP`ou9X;eO5Pi--eG!mkp53jjtH%Pl?-$7&xh2 z;3&j8T9kXna2_T=W>`L5j^5|;xF5{VZoX1bc4yQ)xc@xqkF6H_GhTb!;z2=X%p-N_ zv#zhPK6t^K{6+Vs$xyWXcppnNmic+h)ny&|is@IH-mrkB3&OR9|55S_5PueqL;g=Y z()TP)w^GZ8w>??ED72QW){v0=%$d?=e>Mk|+fa<{oXv3jU{(2g?et;Xa-oiZ0O~Mu)N4;ZiUxwE#{H6Wz z-{CMOf9goV)?B3Z3eY(#%lPUGEDLmPwbi!wV-K>Ax7*9!pZU4?YzoSyMtWqH-CE6M z*oy(%h&Hsyv#jB~Z2YnBgd#e^ZNHM}bL#V!pMzQ8Cii;jOonVD^?41Zjl0VGgw|T8 zV94!+Mmviq4i`qnKW19j3*bDufQ0P=`T%(nNH;UUM6J4=EvLJ`fz8Q$A!(q}E5ex# zCs==-96Ru{B;u)VogzLi5>kY+g$bL7_$Y+uQ8iYXe&zSlc#;k8qAWi8q#*R8owufzsNe-G`wVFj7$8z{Z zaG%wBk$NvUSRsOOY$uKVZK+qYzgAhh%c4zlr3KQKq=+ZsBhN7ugtC+?V2}cO<#q3;rd%*91_c z8Qh(}NaxSLHx)__ai{e^Z#h7_B~9Tv;}2NNF=<>K3-X@1;@=8Serzg>_b`!H@BC#l zJW=?CG7gSe=VnwAM#bH)D3VcF>-g6e^~L(t-uvf&F!y-Ns~8RX>iu}&F#WKe?RL|1m||kHVU4aJ@a=@-$h(@ySyIQb%VDQ- zZSD>qv>@I{H4wAdel_`22P*)yca`iKwOV4U6ZXu{SvhAQRd)BUf%0tkmJmb=`a1JS z-c__Y*<2YX%F}+`2L|6`{jBe;zDg#}mYKT_rkp|}H$_K*hf&Ce#6RR6R%h*g+vdPs zbj5be^qC{5=g=fu+{IM?dA<~o%jYS(6}N1HQDb9kWvNzno_A={vAF>4JANWKI@DmB zdRu>3scIedCI{X=m9404sVcWtaSn^ zugy2pb`s$|*6)zJyaG~1`_mwf#8G&eMIAza-ZDtpUvbAS9Pop8%`5%qqYTA%X|B7F zl9J1c>Pd*C6aW3y<2rc=G$$Oz0Z6o%U*zg%r#P~Y&qwA66 zegQ+1MXZ}z<5F>J!*g&JW`?s*EskzTyWZliA*H{NWi{g;Oqwz}h8LSjs_OhM^|=w6 z_@0q@WO^E)7v38Ms>KrR+9x3+sz|26tvk?R5OT*73Jho@)wVacsVhN(2;v-pF;GDwtQY0Mn zITZE5`EChsbgC!`TQ%&?(0;Y2;Mp>-W!FF!N&#C5pp@2YWj{ z)=%Q2uGM|PUN8!hjk1@lnS)X~Q>=eP_vc+I8hsdN^;4~Wspv$|kYm8q;Jo&mN~@Am zkKyPsheJ~Q0J?#k@+#b{_S?~-Pk8@Z!-ovq!{np4rh-psIJAEEG#j8CWJA-rwKK{+ z(W9sD#qaaf`3l{#KeFYSLc`I7z^~xkIBioou*a%K%a`#r2c>PV2SKE|{rS<5{X&ZH!tip?+xDfnIfc8!Ephi(H78pPt0?lS4#@XL z_R67Jx3xXJkm9Q~xVk>;7q7eX+8n#pk_8R1t95uIc=vQhMs2WOL^?F5EbTd~1vy>2 zDV#PVRt-7E!l%{Y(+z75og8x>`)tOgzns4L>nETk>W^{_G}MgSGt^t_J7DvF`n7kJ zw4@|u)$YAKR$K8G&po24NoXeC$ZBMUe?jYxwioz$zHmd=-HQqZ#vbeb?lUNai$kXY ztY>%r+)|+~8c<|GZL?eDM7C%@$#<_poJmm9j!c5u)foqpqZnAD6&OyE_m=3gSITgm z%WoQl3VV4ctSLC_V?$w=qd9_;viqUbT;OJiEm`MW&4hwx@**fjSI6e!ko2@~X4k!K$pz>WejV+;fCjaWNyi+qTO4@y@Q1n!mwajV#j+pIvE2{ig`Dp(`T; zE}yr2v3)qTInwAgI>LwyznpeS4)Y6gU2$M1tn7~crjOUri7L=1m*^Ygq@1&z6ZiJ?^F0@Rc9^o(ij#IC29A5S9{|T!YeIe zttKKT$-}hRhcl-Z9*+hj0yVdFYTp#{J4Ji{*?8l0d4+fyc_zv77tlb)N$@_}_k&h@ z27Fi}d7j(@Q*almyQ(ulD_5^8S`F<^x1(92l|K{}i~o5VODiHgdbpQ!HT zijfj;)aVE#W+3AxtnP>5_rb~ZQ5YkOFUOz44pJnva|mnM^G6Xl+15xdM1mCWb(_ZD z$8Vn;a4TpV$LUwUMD(djVhV?21o-_K}W0nsP}3%v?7j#n7C&-_PJm|AU}RRCYBY8_(Zwtb#HUL#`28>$tLS z#}Nqu(2lU#O1Ib*zEO>32^%q75h^n2x!!VeWU#&Q)r+T8B|$*e(~6sbtgH8;A73LE4XA=J0stCwxy%?=aO%}&S+ zM}b@t6FovzK&}hz=K7~JyysJMhjDeQMyawidl!BGks3yGw0+%KWA&%tJ`O{xgs<3r zL;{xS4)xD5o0m`d#MK7>EMxD7L6H-T)fqHU2m@2s=QwM?c6p=SJDd<~kFlDgJt5EI zb&lh$)!Pz$Oy4adzu8#KouA|f1YeLYrPSIL+^Q{G*9&}>5j(29nuAYgUR!?Mgpw+SK0Qb8$3TZ8M7`9M5>Rxe1nR$%zF!Z!67{I} z#A}~N8)Ba4)P$p4bYx8jnfAuoIi7qW=Pjs|Szv*@7`#jZVJHP^Gwl@>}n)O5z)-)<|z zOlA=-yMJY%>4~^_d_Bt!6@~kL?Z~GGwv?TqcR?#rA|2!L$T!9NAFyODjXGbHo}{Fw z3jg-#cjXNb%Ny>N&b*0B97&1QH9VEoY5aZIO?S**2qz@(gAn*A|8kZTGHP{7Bb=hR zmrQTHSJuPqABW~^&yHX6RQ+;l_C%Aa&Mlt%nLljxMe3 z*1{-a>%wdNcATEVJ#sZh1p2Q881rI_rqcQMs-E9fu$Oiip3by)S#=&NX$MOH<0I0L zN*~wqAgIqx_j#*~^^2?|bnsY1&0zKOOq#nVx<2FA+Ke9669qd=iZGczRPc$bNfB^w=CFte4B z!dx#v9wqtZlp1kZZRTf@rxeQv3>Pm?R}f$~Ft47zxK29vl!4h1tJ=73$D7#E{&#>> z>wcCK=#@HJXw5_)xbx|_s__B~Z9hYutG%*&&o4C`Z>HHDYv#jp%; zkH#1XF0%eh6PY`q-%gqj@{>4>#PLFm)+LC>%K8!7UC7W>EmyAncNs|)-kqThmj2^5 z9c-4sG{nIKrYPXt{UvfUqtB#7=V#XJc;wg7@Ei=cQw}=0MjZ*~(H2Xn_PKUwOn?uy zx@|w2FVC%xV{H18EzS!Q632+ws!RB~;&Y$3z=aMf1evO^mhtg>keu?1&(|u8bEu*~ z{WGPxJ|qn{dh;SnQRixWXrBgtUQ@SL*`B(gA*#Xjr!m{<4AXGQTk2-vVOD-HYr(v` z5egH)&U2wSv~Uti8PHc?o_Uyo1p9sjjhvzkS?>0bc*$4r(=K5vx*sL@wkIvz--lyj zO>@n{heiH3P>u9%wG%>Y^H$i7EGl3fYB}lBbaCBUd>EMzWF#|j4Jb{7bH;FTu%FJs zBS@6Gi=YOPYG;29v&|kOkABkKR-t+%qN%#YA7>JkkjG5EhjG8-30gg@3&a zMSSl*B5^P7kz{Sfodqb$3yvh;kod{NI){;xikpMJVrI<0zc2RR$gF@|YFBkX4#C={ zCMxa6ppv9F4vv@%HTpY8X9uSioBkm$NWsf0#w14OKd;2!qjSmp2H1@}MM1fwrZ}q> zo?Iwe_b@J;N^wxeuv&tJ^07%E(Oj*au#D=Zv?PyL=%+gxElynmrht6-Ez25G{o)2HGI-#~bZ;?I9!Ljd?n|TLt<|Hr|IyClqTsy{3%06C7#Ym| zLXq*Sd@GwY7~0672TZ!0eU^!4+0?J*_^)b4*A28vN<|x6=xV6DI+UXV`Sa_j;o2MG z@yORa`P~)t{wYauIi^epweh5uH7Ncu*Ne|enggDG{Ph&JW)!Zr9d))i;X^ZgK= zi)?1Zr|~od5OYo`?n5Ode_>n?LGEmLQg$Ixg~RV{G4x^2BI32HP>ry+<{+6C$P%b% z%JSOebB1ZZOaZy)F|1N=2H9-fCo~@oI*S!c(>7b$==7ZV# zvLQOU=St4P>WJ4@t2N)14(xl_4Mrok_~`QtgS8JPG&m}SplbNIlB8$+#3~@|+03yg zN84PCfHr!qFg-LmX>}CCjM^KIec3MUVs*-K;BLSr=qtynH@1hSRl|@il*XhqaUlSA z{>AND9!~b3Hu#Ix@MD(ckE0tN`cwF1VN3RDSrsr1o5o6eiu^HJA4Ih3G`KCtFwZGFB@`GPJmn<#^XrUw2kC%*MB!J zon9}I^IR+EQoZ8)-YN{`z>}ovnpDN3mT{j1=EwjNGp7|DmE|#dkOyXrQUWwv^P{AP z0mHrH-3H$~_-6QWpix-QtCeWiG@+yK+}SRgUxfAd7*X5EeF~QQpeiGY&9M@-`aUfE zJ}bInqQ`6rngpbm?Lv;G_8}Ff*3^Q{q2u zpTG>!u4`s3O|6XV>6y1u-sH4>w$DlC68Rj<8sJI%-QK$7rTIi`5MG0ZhZ8hUMuc~k{_e8>t&eH$&M>*{pyc9F;)X@<$A?Wlz39<(HDeg$xJ1s@wWSkF-FB;f3OZ2N=)L!1cr zMk^@RyZ?qIanoVDc!uQpj?@Bshq$;n`|^XTtAswmLA3E?_G#V`U`srwJ)pjsqwW;S zaU$=qeeC@|{?Qk7eaN0ThY$}Q67({J6{kXpr8rjmP+it(>PW%ixEu(dVvum$k=FaR zS-8rDp#{&C2AZYkgC@&C8-kP*U$yda-sIq<_E!Dy(Y*nlPWLJRvVru?PwZ?A!<-CD z2Znb1!i00?55hbj4P~1{%X{ODTxp)hhS9QtMlQyRmBJERbJp=I+=1lllSt9EOS-Jl zD*S5@^KUYoQ{wEpv+aT<)Zz9xUPQjSb+d)f{AYeRQFxIvK7>(NJtt(MPpA z*G3@qIS)=Ht2`6X!saZ*Z%ydBT4A#s|G^VUFuV$szDfRM-^bBcOtCUA-y4!914x6} z;+S@uhvr3mvsleq;RbM3LrT0o;)_D_oVht$_0fY4MtW;b6UI1s$|3U zUCoKYDZgZl%DA0joh%=~q$JQlM*$5)u)$^h4d|l5u~8dR154f%n>XHZVTR=Bn29$P zgoGQ#+Xp`-YDfuLSK6V}zhSvrspSQy^sHF8UbYw0XAP|+B?+_#*6VcVaveXak7ju6 zI5%M5#bbsDfRb?&IM$q!bZSktOby-+6M6X49?@RU>E z0h@GHGw4g0Ab3@tP1t2Ev@Ex^ z?EL!rrH(-6ujKFBPdW6UzOY!!KeE0FF1sX)+6U&+vAmTV_*;4Ax3!%AANNc$3Qt~t z!8T4_b8^|{+ltBMi}8uHYMk+M(nW`(Y%MocoB_}Z&6TCNoh{~FKCh}+c8MI-A;qxA zFutJ{P3lqc6UWfb2g^-39bwP?2rbxwO0}ia!yx9c8p^0tI}AfvX*v+~*4BFC+c#k) z_H0hIuzP(ppOAq)a-~v(048?n&P;a#!s+QgRV5*c`5(gV;ZKQ)+T8_B!AGZj?pd2& zrVkZCCgGo!gTvn3L}AW{3e<+av=!~KWQ;eOWWo;~WKVI6?P9bP>!xgDHw{Vc^PI66 zF(Q!5#!{w`?={vZWh$jT^f}HY3KlJl2=DYU7M(7ry6A$xg{msvnsICz)*mN*FBwoA z!?*3U_#nU4q7(mb1xCEFEY8QFCxiYFp;;@d6l<>52>E$SyOV+tLi(8jELinYeEUZ6 z(w$iqSywfyb5JFnQmEx7vLwEkOe)q_lJR$X|6FF*=PkbBdH6NkKY&nz39a?%h<72Z z;A@W1^UIcaH*n5P$widFIU4e)JZa~__*hs(xM1FW9SwsiQR^+s1;wFOejAgAWcfB# z*GoFEJ+`MjO!^j9saE0wCI#F?hsAdStpL9(EWV_!X&J{ccqF1V<<)uIS1kb^C54+po(!Ii@jVUYP@x0djAM=Zu&a_H*u;OJ)S^f4Q4AJM7XP#^O)^)RhpS#0?sBcoa{b z(G>zoX!!CQY!psp0s0~BMwEg-lTiDTGn)+=k6sT(bb?@b!ly;p&TKCI>72dev8l>F zhu@fq`A>Fp0^@_6(l#?aUlg$tAB=QmM;Wf3d@+AdaPTgvU_4pMJ&2}Z+OG89^%rVI5%Hga+a}Pc2$X(t4;D@BpPjuCWjc?U~X#TYgW6C zZZNl+K{9PW-MRSec}4PdgWz8{gANd0>H8Y3v?e;aO)#41b$=bY(@Zcr-5&~wV3AoM z52VWPU)sO*aLMtq_>j}t`|Ot4SG~q8syybaF;Y<#eD|hHU#%+9j_ln0OdzF5#@yBn zSN22`NiCN;6ErPD^&-BCCBp+M&7+~2qF8<1SJgd-u{FT0Bc#^2u=pr@l)y4s_EDG_ z-)`}Ip&fM9Tk}t^t@-roIMyGd*HLhDASaP+`c7SURDj9HiPE|OdcgDNy6#ovqDZK_ zAE;bsCs}H0WkgQIy7iB_ptXwdFezez{87S^_@t%WVDa4BUNS4_ba{x)@b4{r{e|GV z`i5S%9E{aggz|w&yd(&z!{e!)*1VsFRrMqyyd=&mV?JhcNSifyxS&~+C<4=5HWCU^ z8l0M1>Y8x7sQ$MpBT0C+e}LGi`Nh~OLaE=R^R~}|rQ#A&jEmyr7BjntDvhA4|G=qg zzQu*pzGpS_yv(t7N3uI}UjRiORZR_iyJ%xBs_y>pMB*O+Zfi5Y_UTblTJN37H3tme zUw`S403s&VM%?Ir*cdjYIz#B8Q}_zkwpd?k^@eG-_u1$`#b10#I}rPfcuw1A9Q6fm zntT_&`3Qaoy4H1G&=9D2#_^b31`immp*(01ih(#Ku-ErtHZktsaECXKuA*OpB;Vv^ z_~t<29o#pH(f$DhtWCYSuASlf#T-6A`kfnu{$Rt@6iVtJ$L$#t) zGD7=J?@E;FSaM$b0pT4Pav8aeW@#xl;r>``mX1zxpYt^CeW}d#P|=m79!eJ(KVH~1 zWZqR`5d-5hR>xKb01fZIOq%Md@#s(7ywtx0Y(5 zfRcV3qZ_DyHLK!16J@cgBzMeIql4^{J&eyzc?Y{0-l?usce5{nJEZF$-yy}nhE^Tb z5OF_sReuB!`U!H@F7u2D=p@XY=v%cdh{&V;xmeo9eB%c&C9+4V%w2@5{w2wz*PEu-9ngtyE(lrG4^c{?rK@i>bs&G8K!zlf-q80(!7;L! z2k+ikK6Y3Vr^R97>`ICpH6OLGtinDd@TimHkiFn8!85$ZfTUyuS|Ido%7g-1P(%)# z<&FQ4E7#XIGQ{jLyZ2q8`~Vvt(}S{N1M7znWf4xiipMjwo6%~LqGrm84TLvGha=9p z)7H+Fe_h9rh?7pLoz`VDu~X8p3+xdl@GOCxT5&mSoe7ggB8;Z|EUkMg|0~?sEUbL#nJv(l^hRrvcz4w3+t#FF0 znG8ve_oct2s$6PTYf|YD?4G2&x89+K3__+dut}#D>6>ZX?v)->F{YfajQXRmZZ*mt;3PF+uwa&XPZP`7 z+2$R8Ide(s<{;~fF-zB?YYqw>G#hkQ7}&Y^*DMYc{lh+Y0QxZgbNPDBDly@jtcOPQ z0xWcr91oxn?Saj{CgcjWPSUv0ob_}G=TJlLF_JISq9o(E^;KBblcpfI9|Ux3?ccD_ zJ9>~f;IpXqFfN^Xu3fS@H8m_x>v(~u;>XD~$4>y%$q#7~`~JRPU;p#rdpj2I)(m>t zd)jK}oCW7^4j*tAjFttx{C4K7Kx(;X*C&f4q5G~$?!R{)h2k5}|5JVefw3J$H~!ln zvhpo_Z_}L&OwcfV(IKrjrZ9K+tB1OM7s&kZ*u^G{tb$Z|jo8_cH%`0rBJS&xnz^c>WeQ)}wQs&cC2t1>|o)^ZE^YoRNw@7-jS5 z>Q(JfRwQ2|JcF8e!zQ-)Jnq6bz10M28fnJH6!o5V*icK#2adr-A4P!cp}&qfpTbd4 z$%Ea88}1tko99!C!(x?X0InjhZw+`7@GnrbuOQVw30E(ZLD%C%ljhT>PF>D#}2SO4g&OfmWl?khT!ipgANoWw8A**IwzN5ftQ?jE{ga>(zM#{ zK6>2xM`FLu^VOOKL4urU_ewy+kMmeyvJ?TId86W9xiMp4x&72eyNo`%=kpfr&WTL0 zkdT^xgI#jB$$dPch&5(4T2!WDCBR`kwp2|<{!<~~FG#g;O(94Hgk)p@6Z|!e!dYgt z!2xn`G|RSeZg3@GziAfOa(T4~=G9ll48nJ=$EvDmiUrf~KsqR0{|lGZ+?3|5@5eOX zv9P34eyt?^#&ztPOSy2J$9V^psur%6`DY6pFr15YN$nE;{k(u!;Iy42=BiECFZ_Ds zxA>+U21aS|%Ru{jkOx=-qvF(oc z3z=sjLP7AZLdoYXUJOVJ_&*X0&Fy5)gU+?aI!peK)3Rwdz*o zC1Qb|-GJ^V?F!i!rpgauUB&gE%&sIXh3GU&Ft@NC@%R`H#*Ac49HjKIm`Du?eOcm@ zu@M~qVc_mYvx|K{Z@?>+OxD0X6C-lZ!2(26d72QQJ66TY`rvQp2AG?c5{uef6ZaCLu9X=l%t-x>gpVFjaYE+(Cqc(-LU-9rgPWw z3(n}ly~x^fm`@RY93B|C)_;6K@cQj0QoAFsd|c5k%dT%+^UnY#VbyAb%GaC6b9>A| zH&?A}=~9-#_|5U4@~c*n>C6O%M0`7juQ}V4kDsFWfcx_zN+#R^eCyaHTciBW*SUXa z-IX>OJ0C$D>yMb=tXtSt1EUJ%yz$;&hHy%`gKA^rbaL0_nO-dSpg*;|H%ThEmY5=~ z2IH~(s29^644CINf4y$LB9jBI^IAfL5KhelbK*I9U+LY2+l|@n?h0DUl;&r*B<|tq3Aa;so|KZszhN#6!*|b7I(}?;2d;0>cZALPp8Fu zlK+}o4L$c=AHM+7dKpN8e>8R~V{12Vy8nq*pFGsmG8tmw-!Yu*5jw8ZzV06se(LR9 z)~Sx!Jm0L$Ah7U|W*8hqQPY(u^61P^d9Kfqna=nz*>gUYh*Op{vU{PbU-|U}dWo#^ zxC6`Xhj*gNlsz_L@`Fm<-tXms3&ymo4zNjGNd?__Ry#71j~yV|@#rcNp#Q&Ufj(2% zEXYzv6BbMBvL_+?(W)Eq)R5qFReacK!&pGF=b>4tb7dOx5vh9Thx59Es{&27)`?wsIemxrozU*-!E?Gp1fC0StkcMR)DrZC zcr)ziq;RsT@IVMT;i$Oy92&H4ss4fk#w(r@L3P+>ow*Wjo! z$C#L9HFOEz@pF4Wi#xUVfU9nQu>t?BA{w%FqJbn#6a!rV)^LY9&;NzmTN0Z!rMZAv z;k;;+RgE3C<;#lxLYxEs^8DevbvfOKtW* z8$B&`QkhRD%D6DG1HOVah?WN9cg8!SS!^)LZ=Vu1_oURbcGO5p z-WA29iFO#BPS;;vwTxJ#52wi99gaWJR)wdkI%~vt3u>G0a59^#vI}>l{3GU(i1q@F zpx!dxZ`Sdou4eYZ?o8$(Vt2=87diRC5ctj7emh9#=3S?YSgTZP%|_6#HqNN;R@?jCRY!69`s8l9@vE6Xuk-m6DsR|HFSM)9Om(8Td$w;Wc2d&ued|Z|=S` zIodUiw|kmJ^B|tlBPq(F4Ca)HRU#D`iQsSwJRd2VK205$?KCbZ+-u5~-hfvOr}%Bt z>P3HywN2fMUbGjnp;pe22(}b2v_$USACd?;e(hci?N;4SXdV8HdyxiROxUAxjJ$os3ND7bI3cyEWkqnng9&XL5BZ(8Uy1#)`X{8y6C*}KX^gDk!ueO434A-)XH}CjRz%;ZsqksGz)*ZO zPhd`z2k`6BFn}NAF2_@CYDb|FS*&s1AlZNLgNf>WiD5S5W#LKH->UDI;X-g;p_fOj zunrXi)!kDXxAVh=J|hLm$5&?RUKIsiMUvv(9aoji2m(ejHj~8?=}rq=atBu8FNQ*q zr;_@(n-rC0C_E5@0tEl)Adf?H53)4eEckg-@Do7!&!45- z{$wojlAq{$Fo*_mu6f-qZVelCp*m&5N$r?0<4vhAv~Dqbq6$v#@5FhT&!FK1*}FCW zzPx}Sz))?jR2aXx?xvb0B!DNU$9;H#`&9~37f%u8woRR}yr(!+vi|t7kiM01L+H{V zTwSTK7KP$Cty4wrDw<$XxD~6575u?|^LkWSH{!mz*)^{;4YT z-oF}74(7FFJ7VtZUq3%kPlj}4xq1O0uM=S)+`!-Tg$Z9ODgxy2SgG;V6zOJv z`MI@uVxKVa8RkG#P2*Cy#PZJPE&oiB!`u{p#N*Dex1BjeqckC>@+^fY&0BD z!?j=_^#3^e@_?l8@c+KMmoryQEv@*LWu>VruS%2e=F-&6WqG2qGEYSE)Ap0|jb2dP!1RVyqa)YXp5*B;Tqt_W zd8z_DD!*mUL5`iQZK51@)A)H`P-4;_)!744dy6(qKL+-pUlPn=`!~L7_I^XOxehp@mPSU{(igM7If4blfL=E27d;qB@J zs}tW-fBZjIbhXok$QsZVq`Xd=FRsCa@6F0D>=u{^)V)DAj@#+huX^qBD!x*Iw zE5I0#`%Ctsa9|=H$FTYaU0sOnq>7}Tm4EVG)O zw3GK@`M$N_lBhpB+a8bY<9gUYdPF;r>7`ql|w%<>}*`v1oBG!gpaBy}4IJiHAk2r$A3)KVic(5^W6?a0`lpy1|)2aEfp1YYw z41&78tx1X&@cCYtebd~Z=1Y#cvolpM2nhO`z}TA2P}G2n#S`0w470=?f=}B=)MVE< zsVU+{g4d^EW-n*$QGA$nrilsV9QT(NSZao^30sIn0;e?-+Ujqr)nD97yL(iHjw?M% z?E_ultkxR2QU-<~m!EEamc$xWsmMr&^{M`u1k+gPJBfE#<2!z;8sPb3oKyLa`u>{!9_&LlrF2tEfdLg-x4 zaht!294o%uSuPtsK1MDS>Sy0V2gHi>dQLG*`!|89-S#q%HCcE4UWJi^%r`1)2qOFA z)X+|sN;LpAnRwn$vr;lcfOeFYI_mOX$jp1Eym|bk$ejIG6J2l%8}; zg@GbAw1xNtI+OX}3+^VDSvhSoGM#h|rIZd^{2J`{eaUMv8ntGj^Rbdotir=wGvWxZSFc5XH z|7*3nh3|MxRTlhEdN?iu`_ZyIEPuQDmtwbrKV#-Fv8Tavzlr@AM=*S7fgD_}iS9JX5$i^YqMIj-`%Nd${hRP@u;acO6=nDI{rMp~x zw+EqJx>SZoDcj6|;vxtWT6nfNhGi6u7cgl z227E@Ry@*w%mkv=7S~rU`_@|d`g7EUE!ktk=JNaG&PYJ-z=RKsQjSkBzf2^$zjod0 zA`ls;wZJkHJ=X&_)Z0|6Nh`5h8!$&jl+U%z1n+mwD8??~_7|W2bE(v#GpYV1TJVMq z2kQA>yd$=tnR+T!Nowg!>?|Ddt}Au|vit$z&GB^YS2SUe18i`mt!z$P<>{02Q`ms- zk&If$w!{C1ORhpSd5M{R>!lSTbIBr81R#r4aqBD?9>o4I{g_BD4>;Z2Q?N{I8{n*q zF$L^DLSSG6{8w8BE7HVMU%#8Ms{UT0bO&2U{D7K`OTf3PeZ;6jX225#;?BxPl*~AY z0QMP-iJVxAQOw)IAH(A7e zf6KGSlap}A?69t^kZdweGF-d7UWA>l7>=;*HLv$=`38M)1N+$=?P=Ko0|$@xkI&cg zlb)jh#rda@=pI>d%X{>X`Bwja#wm~#J2oX5J6jqI7(KgOk30Xy@)7S@n~CFlp{IOy zUPfv~?d_CyS+<$%6O}s8(asm>F_&hDw63=EGRJ@3F45^^zs&IVG7G_}bChX_{y}lN4x=8;V;RWC=ZUQi*h+*lcYPK*gvFrZ_ zb?3X%@XEgxcaY>0wZjY$w*uL0X<%9={yE9io0281om-7NgT`8NRBZxV5=7Y`_dwHe z2s40|fU}C&jNsu{Mxj2vpfUUQon35GYUu|2)XB5Q7B->nbfyY4a)(00tb1D7cafx1 zl;4#<#r`GcpJ?c)sRf;sAUOe~qki4wl?t$meYWj@!b#c$1YmveZC}ZvJ67hTS(dHI z-x@YEWH5@KE&G1|hwj(iwZlLzTg346L0-H~>OUT0$)uzSarP@@$h>10k8F1`4f!G$ zgIc>Sy52WfImh4E6T4a6PK zS5E8EYFC~RP=MQg6EBWP0}n2)A7(TXZ5IX}@QLZ@E5QQW9~Tvz7pSP0zLegDhKZad z=EXKqVIH?H-=uc^W2n%Z5op4t7`8l1jqa<{~hy%{-0%Q2X|bLKKtar!yc`F*WheZ@if z#>grkuW#Heg9R>zf7xde!`(;RdF-)+tmDmUmhx{7?}#Y>kd$9<(_!mnx^t-%e9af{ zS)Ja6bkvE;p{FF%At}SG-yhyZfSY;2`4q{xX5)QTfmFiunugETIfr0Q*llHL<>&?5 zhSegt&&OXb(XQQv>BsYgkvup{y+7J4Ga>>V<`Z44n%u zQ;{M@-A=8zoa^7Hn=~1BQxz4rO(T-@2FLFa*X+7cGOhlAY2D(R*|^8uj?#uJq#f_| zQxoaTa~~(n{-&`RJM7vGz9Zs%p*B!jl?5qC%`84>`zi0Rva_g1+d~@4Q7~!-8A5 zr2C^6I(P|@q0(~^YPoTpbNAqB>&iq=IZZEU;m^uhI0YJB|C$xE*N(md8J+pquI^VOQnrE3?q z>_z;3`!U1ROX@;zE1R=c?uWV$tIf62N{_B1Cnohw)Ul7r^nznnZxBfXPXr2uA1Q!;c;MCfp z4@K_@UaDQp2>yKeec4Nj@>EWyic>fGuiZsf`Yhy0q3) zh!lb@=l6*-0xgs@;*Y~j>>TBq#4!!k29bR2kz((huQn{TdpE~u^JgoXK6vJ0#C(=D zUu{-g>2WsZ%^>ZF``>b0N!*#6ac9fZ7d={XJy?q`C&=idIlbuHOJ7yo{j2j;qk~QN z#>=Mk@Lt0uE0xe&5dPnuf(;+e>bB$cnwL|cUr)jgu>-OtD8JVY-Tep!EoSvWe)3fhvZz$^Bx{56f~+p)e3O*2UM8dgH0?v0bo#I@r( zOq5N6lA1oi-%#>^bML0tJn@Z_*%tP(-U6+W=RV=nlI@cpDWW<-z~@v4C{&O~J6y)9 zcZ(pqk}+XYux)Z;ZlmXBh~nz=1or?3(g{YtqOb&{+<_=-)(MQsN6cwl598yyMJ;sz zkgV?c80K9?DIdI^i*t6*Du@41U#&;zVXPz%@vacaiNjOdkaO39rcrvYdIRUMMaTZF zdCJ8;_Oe;kN1_M9-sSGv*4(u-sH&Hd=Te|&@Ft(=Of;NGd*0aNJ>CR_DQy3~Yy_EMDCW$FZ0G zYe>NAr+ILN$N`)N0Gn!m+&cSw`@F|)$#ubg%7O_}ORyRgB~$1*ok-R^J!i=#cpYIttOv7!E9WTlT`FTWsN&p}vtQbJ zc=y|nxOJ^m8$`64pwPzaKdw(?ieD5Td91vI9t7Rdxru%hK?&YYz@?p6eRMX5i`Jy3 zAiBJGIu4=AORsFY8$^nlTEN!seC!Ccp~VxQBI)3{pftnPYHD(*QG;j<*V z&+2GMLbR$sZ;cD>Q58hZP86-38=qGn@D`gM4^ge=0>l^04)_G+mk8^*N74(4FARyU zdE;S?Jl!XU^%MHui2=JZ62L8=)n2hnZJp&LBTgIPGpKKrmh0kzO4)<%p)S`dzm(E> zM<;EXVcMl)rz+I>g23!@oX|skim$YkgE#tR79+)4y*FdMjwiB9P7FfKg>*xRKlKdN+6B*rwvtq69bx(+HzpBcrV>o=>Jm$+6}dF-l}Tc z#G@w*b`}gMpXGd(dWd^^`mTA_Rn!BAuAaxj+?-uD{?~X^KEl#7$2xejp)!rF&1jEv z_|aDGS>P0YCamtHJTHG$rr0(`)8%Ierb9lX;HUpLgFL$SuKw>OceB3AV)o_{q%b1_ zn)U^DW1O56#t_HXq+*c5(vxzgdg0}H$d5{j6zhw=pOm=)vLl8pwJ~$ULc6soz;~cO zi%DK=RljBGCmBix>#ZlJEoHeUHCn|Yq|OpP0Tiq&x_}Pg3(P?0x-0h4=DLfyI(tX? zRvc780^ILY2v!Kf7~2}4Qb3fyNU&)pjU}gha@jjy%3h$ZD6MST_~fd_WICgNK@{u> zl37&Tbr#p$<@K=ABXA!s?C$Fx?Gey`-xF={`k7!S8w9k^oOsZ0Fch?lNzv@mNTc(@ zOIn&dRq3u*^5MDr2&Z`JSYY$R-gGyg zqL&~B04F30)7Q-Mk1Z=bB$2On5=PJ)$AdOGMNIg44?4+fH62)n)D1%SOjf0?p4&nk zMa&r1SEr;6e&sO+oeOx~$cq;#`t{MZyy8px;Xv{uN11Vg(ZNY(J5L z6ln0YRpiT4|L9!=EY0ZdC((`dO14x#?ixKI&sr=3j8jY7sTYTao`&GtHG%61#7w&a zFsgJrlg}2gTyiq} z(a!ha$pc7-k19B~-B#1bVX+|PiO@kcaEY((y53^>p#M$6c`VmD`2e7I~Q z!D>NKFV2ImMTWm~wL2{xbuH|Eby8& zK6T@AET^W9IJ$Bry{dlRKcPvZ1)+|g;eA=%hc)j~ANFgJh1`xvmD6nP`*(WFu z6l(6D{^^cZSN2g0dfq8`qtOx>@~jmDH(TH}V?5=g&FdzO#^AzT*-F@19=_E9l{lv8 zI<_&H92l`un%7fyIg8W(2zDl-_;gqcqN#kceZEv+5AmEoL9A5hU z%!;zcw%&kci=ldXR{Rk9iYj7ue=Ph;|sDOKvzzTJ41XBI*JPAHPtI zhJ4OnZbANewW#ix{)M15^QFEeUHG3)QqBuCfk>atjvI z^?zlAlEr$Qx}uYL(^k0vTvo7_iyHs|XD$$@{^3*33m1Ep`VKpj#XOpf*k(Z_CE&%E zzN-aQjBDtTjm=!hg@F@y&})&!Gb#6YPXKP|?;u>N`|D5qo0~H8e*;|GoWS^b41aF_ z(r$UeJD4bK&Js8DM-eQ#yLLcuK}k|tN@_70bkscWlUruc?DAO6l$(Z8_pP$@h1|Rm z9}!YwVsGI6<79o5dLi~eqAA4e0|q+%YF?JSn9_riCX8ol+}=7>^y{Ui7o+}|8)S9Y z&EoONXRCE1ZmHA@YM}$5Mb(rGG*A=qJxEU5{q4Ikx4Z9rh(6CNvlhs)+$wem4ddwh zu|kHb{<&uj+ul${_@|{7(PrcIOW5FPP3QMXM=Ch2RL{6BQXwj@^;=*@vp@ws21lRr z_3}+ziMg-C^BgDVuc4^$(vTr9&uPe0CFz!Rx~0c52o$hFLOeX=vq2UWVnyXU{4Kof z?anw}FuH?6>zg$q#N+hh#UC(NTiHzr+w&DI}%loM#IVUBRFt$wD&fRIhl?6t=2KFFu zGYXN_Y^=pM_dM@W;hwgFb|MqS!2aukF?m71r?8`Db%p=Ov>tE7j>D1B+)e76!5FFA@6eg@0LWM@0r%zm zljj1dBWqRoRnaDWsVo?jkl!ilRN#yW*~V#7{vqfiA^*hFy;f>2OxI2y&k>5}X33L2 zf!WwZ`ica*x85@}AXlZk0$o3UlrpH$K2;kv_KfLizt zx=tvg_3@WHu`-pkvB$#qv>%U=)B73F!Cz!JJJxd^eDHCpK1>-_b~VTf(R z#~6qO`Q`Q6&94l9x$WQ~FJg+9RbKz?c^IpPEYrEfF1WU9g#}PMRax?2#=Qq)oXoX- zbj;R3S{z8CR8~GY+BH3ScpoQ}i7Fzy5DdZfm3L-;!)sVo&#W{pFg#II zdm2*er0&1KQ0{H$bpGK^(&5D)7JbuCUUz|hwfrl$8`o;Y2~_V-F8Q|uSj0Al3nVVY zbQk>;f-_HedWdGX;+2I4E8jokWvE$oW&*ad%)GmGG=WcP>xeq0rQPp(P1()-DW`MO zqeybwPNQgIV8bi!!b&F7eLdqzx1T(~~%3~xevu&5h+shiQ@gd1cnNmatYo-Xmjj?Wr z5W04!$1UCpR#)gIz3{Tjc16f?AICePgaZ~H9==LJR?JYs@?X$vGdYkQ4wC_Wq&BfN z2+t12T$Ph*WNsQ*lnd}U0h-ifx_O+u7F6o_$F@!v(5x;v;V$#wu7Qbgr~ZucE>3+K z(y6o@;MO>z&gB_`+rYZt->uubX9t9mBcA10=M5qs7BY~u9=F*mm;c+dpP+E|>x`T4 zjpb=tg}`tPtpnAY<|#xWIJ4@FwkLB*WF(Rmvq2f!G~@HYO^^YECzX`SQFIXU%JU5v zJF0RCb%Rsfa z_@VRpVwKQCK~q2#S7e!;$4w>AQ{nQn~;2uu$PDEYWvWiD*jX!@ejVhDDft z7-X0e)8}K4>@U8)$@&I;ieUe4WGE0~0z%iHp`B)0<Gt&MNJQ*HzRz?Hf^=-S`dAT1+@^QTOR|2mNq~dvPQ3OriO~i*Nst_0Gy0 ziC<5k934PlAh0>dfb0^SooJJt7o(0<>N(aHUYyO zEQ0qUiAkj537Sj)rEeVNh@HpXF}dq;;fg~a6QX*9C*Q9Z=VGb6Mnu3}<{6eJr~@WO zfXa{rx>&}98z*G_$W!VW2W3y4H~A3~C|&~ab)mbpf_ndH(riXqi+Tu5VW-j;c#*@k z)*1%j>I**1^i=Ek%EO`h;V+m@MTqxydVT?kD?2x3sTRfgCf$TNvY`_)FwO(8u{;PW zay<##-io{@8Ljd(wSN=1KstSzsoYBUUb~Wkdca3j|B;K!9ACoJil?`TPmbO+psZ zP}bQWTzx0pN-q{#HF-}W=lIGCNgIGmV2QrE?rft0*9}N%nEXX>PD=v`KUGlf&yw~5 zNgMnnh-Y(!><3lDOnI;l6ze73kshrq%dlZ260PW8dcnw#9qBp7uLqt6ZT_SUlGj3y zsB7LN`KqeIlA`6;-kk5ssHe3kjL}rrqtA^`W~)c7mU}X)`x;;Lq5ip89%S#{iPo!0XX92Os&na5LHUDj)0i+hGF>g+`CcBg|4kiti#+{BHW->xH8_ z4fyV%?57Lsoucs3Nsf7T1oUh`@cPvh}IZ@8a$Z3635^0 z@|O_13lr#=)9R7bQiqY%xhIw>r2DMM)beZ)_XA4nPc@H1h6VzkRR4UteKbe)%G8AB zc9_SmoP0|R87514A`kC-LGl8C8|+mI%oLWri2)mf{l1%R&!j!~Yx1u1=u~tKkXQu+ zaOZ#O@H=@U5wy?Nrsaj)Ec3|RJ2*6e>uk$? zbo@z57{;F?=YSTlbod4V{PUyiRmNMw?Rva=cU1Ig(4fK-Kzg9=R`y+m<9e*!fw98T z8*P$;H!XvBRAg^VO60qm#!MiHXT~_U#w&TOG$sVp^YNs2;JdCdk6&TubwrY5lOJVc z(=J)G0)@}&1SUqe|KMUG3a|J%%I+r2g3mU?(_UMRTcnW))U=taKN{08vs=|h*Dy3A?DSzxt+BlLoW=YK^d6 z{a&ozdleUx(svd6I5TPM2R6$pJW!)FSE5`OE<5#ieGW|E6@vmih-0>v*+>OFq`^5U*BYor4$SJb4 z%%3IOQ1%C$U*~lus1I}W7TuH2MTSQw-CR6IN4Sasxu6 z{3gR*2ZXz>-?D$wJs3zG$Z_#03k8o)_Py)`P=!yZxN<_5*ThCRUMFE^pi*CMEmj+< zO@NZU8u-_Q=omM?^p`~9zpAczeiHXVMeNIlM~X%+&@k`S{c6jRwy0U+=O1^b^_xZ` zEx_E$yZyS7s+uBSA z%r`zbg*g-A9^hZ}EeN{>pQqkab8*X<-RA>%9Sp)4&Am|}^mE*(Ti9%CQlsXOKoLp? zP#nK1W|k_3*Sf=}q5ErNVb4T&QfH=Ce!wOGRT5PzZA~b*^75(t$k@5;-)L>6FUwH6 zIm&_LvsIlT7=aCQdC(nyepC<8#Z1uF753fRWE=e}Mpkp$;bn*_jKqe?ov3HfJ>`7F zS!YKNy;$aOc>ih?LmV+iL%dg2Fs~t-YPiWh9oB1}D`sy-NRZej=n7 z1h%v;s7+}2>O_y@{FA_XJ=U6we;lcA^J77FHEg*dQp<|Z89j1t!07H-XTu-3u{vvt zEf6e;Okkc%cV?)bha@Ad#zWxg)&eA9wY3N>3iCiWLjg$A3gX57Quh(!rOkc+?KwaT z1p?L|r_qO5<6R0^BUH=weeHY;u!=je%x*51W0q?`wrAG@4SC~vHOKaON4b%^U68EA z_A(>eF~7AJcZ232$1i|f3-xGtzbvGx#IdXR)I-t4TnCQZQuxlk~cBMbme^yrivVGx=Dfvh^*SQgKjNdm5Qqb1CK6oh&q{OIM zR3QsU@@Fdb?s3hO2fBCX2MZdL;ZJsr!s@3^7d9AsQ?KKV`NujHr1w5_2Xp8Yu;2D%?Qk-klqNTwNI$nS-3qA-Qrz7O z3uhcFr_Bz7de0$UId$?W3fp=e35!8LCSOOa6#Tab1k!rv>Xk0Nb1ZxB_$?N%t=V>l z0dKmh*v1*Yc!lm=1Ogn-iBzN=$L#sn>$gmw=j3!-=f-uO+GnSHt|$F|twY$W{d#ET=BgeifAj^|G` z6&32bwidS74B>Qi$TM2$c=e(BKapmg#UovDiA z!W0Rmk5DsRJ)3e&FeiP8wk;fgP{nK0PD=VB&rnG97KzJ)!0`|VA<0T3+6UpU3zazg z&u9qZsEQYD!$MBwkbw&LSZuuX04!;kvdd;vVR_LGiml)HRX-+Rdv3wF9b~nw9 zAcQ3m#1sWdN+Ny<5%fGu6iAb+!btpdr8c|Fdi8LG5awgZQFCcCA=kv9AnyN=(@KwoLw8 z4rHqfem1_2qhK>slyi_W!Ye@Suz{eot9h>MV)W;S?Cwj=r1`+kC-`a2It;HT_LQ(>Eu*x!?k+Q z&?Q952`C8}U1uQMh_-u@RknH}v4Xih_VpxS-A1@lq@*nXEl4CxVh#FcD|P)#YCuYv zJHxxNph?9aJ(r9h%CVA{fvFWs-SiS-iJ5N*y$W*c0%deaX5D&iSZsI7AD(@|g)lyb z^fml*Ht*Vhdq!##lCZ0c^+-UpSSz_8n7g*QS?5MNswE=Nz-%B~-rTMCKQsNNEt#mP z%J(~BE)yj0>=k)X_K&yi)3e&RgXC-xdqjrd)P@ovo#Zy;1zEqlU;$`?m>@X_+vO2txAsqOJe@%A-#zP<<|@fh3>+G-2vMapjYg**Mb)s{&Iho^fMb1xN)m+jHK!!jmNhV#3l)&8FQYw zt|CriE=FulQA+O<`7vpf+p`(7CO_5XEyInIp zi;*pFlbcqlt}K}defp44JM^miA6sp@_>nHJr$WrGMP;=>aj1ewT`>HqkGIC|DF}KF~2dq)dOHxd>+$d zsx^LM$x(TfR3TUaL$c!^FNc-Qr+^scWCO3&IEfGmbiHJ$7m&QuiT!VK!wEn;*hJS0B$x z!Oo0o?L(ZedV>ssIb^Q31mjU(m}~&KfNLL%9|WfA&wRxc{ojN`mut(;-9CXC@$>0y z%qA4J!FC!)kgVB&@Vbwz^=06>Ev6+WJ8nFU2{@|=K7*T$uU+41$YrgMQy|AtE9?7C zJ<0JK>dUA_FPR>_oJ97+W}d^2P&X#9-(l`WGrJTbKm3#9{3Ipx0V|=?aVkT0)G5rs zYxYKdOKhK+l=OPN{Or-D^o3f=qh0LO;J6$SGWP|v-K|w=^RZfKpNl>{2~fJD)~jmW z=4NagSk=Fom`uj_P4p5a*I~DDv-7UhLM)gSj#6s18UHJQKVG+PCtOplJv8Xgf1~~p zbF@A_Z7hwKMEK@Z}k46ENWS4}_N$771nJLdSmRDs4%gDw`> zT|jeRDvA8M;30H;*G`Dk6@(kDKhZ@xIfMA9t|zUI)R5h`MRp)hzyzB9Y#Xs=pubbc z#LBKUexP6DiH;qvPx6Hl!h2dleF3jT>VDGRcHSntkFx32rXB~bsl?6)*xzk$wp;?1 zfiM@N9y3YL|L6X*WZQ}GXMh^it{=`^-nrj^J1db1=H6}#Ceu4&5_#Rlcb8fUN`7aw z+zu4n;nA1@IW8AddE% zLMRY15nSyFAXG$(8^xw#j*M=>PX6AxAyRc-1ElnBrRX{KOfFh(L|9K zMF#z~d93kS9qM91Zi3fr+wts5ICHlN< z`NtL^;@biaYnt+Mrw6AhX5LWMC}T9!MbO!j3q7} ze-tcP4;LRo>poaxXoL%_m0z)nhj`)3M{n&^u9pm$))G-cpJ*7AkE8P(MW^JUdsB1D zv)8#LtQiwH+pULCO~YjcoE>A3l7On{0!V8g;7F8OY+Ju&$lr5MU*KOIap~A_NURI# z(lI+pJb|V9Kf2E<3@3B4E;tKL6szDGx1P$CS0Q2I(gzlbg5Wn$GezTgeKUWv6ZG)S z0gt&y^Btu+dC+~l>(lW30NgmvT47Cy8RWSUWcv$Pd`h(HIod3#4#UQ3+x5hJr>jZ& zc>n57)$MEO?hP(-pq~aV1ML`y!2sJHBrFMMrLgzlQ`mFAl0tZ>-t=gtdM)ax#*=Xg!@T9YG6rHNz7F=GM_a zRZQ}JuC_TDrdwpnpT65r2X4;NxQw~C>Ylpro8TN7zz2xNARz*J9vJ>gbUrYo*czVWh!5}pwH(rF2X(!9H9yq?8Yfid{0oUoj7q)akz5WxGn5wjosp^kzSSchY z1=gG+g_9#kjL)q|kvlyn8bD7UxvZ=J|M78X{YNa_Ix|l{_z@f%!nd`tQjYp`nuAY- z+TyGNVt_w?3zb5(p?9EJWI@;RO^9BDl?|_+g26VVHjmow)ax| zx8&plBj% zcdAdr(WS0TL znYi(ZK$U%8&-hCF%JhjKgBDx_)*7ti|Jx(5M9qCwqyFD9!;)1lcSW?3@=`Da+#k|` zNB3>z>9|16ce+c~1K`q-VKarma^U^HF2y(Pu-f$s80e%;CbBn|-R2-)dB3+LrqMJ! zaBgF50(xYAgy;G%Y@tytfpI|$pHAV^)+dy@$u0^rCd`ALj%z3%N>aaJ{^j33EQg5yB3E^Wgc$lGf+h>Y(VPLh+LB$^ooyBo*`OxvNp^C zwdq}%_0$W|XywpgRq=GFKx}!QEYy_hG0}>(=$rqmxPZMs@+Gg!?SqSo3pW-*4Ltu8 zW?j><_*HOXgw{$$7la|z@p8S2oFOm*a-OzN#_T(<_+|gnrjuIaLzA%C^XQCCEX`NP z%B=Zy!Ml%9s?v`(FXvS?Px2OQ&ipErrO6y;j1)2s^8{TN3NQ?g-#oiHor~fFu*Zr{ifx>0}>px~WmM5>p`F|87C3s3ZiIY`7 zOWwA3UHXQa;hUzNS#7<%k)vAyAOiuA>Jv)L)@hMo? z@gPQ1jtvg@;r5)yGZX`TGzlY*C++nz^qfI?>!1}Et)Oduz3or);U|| z$ve&7yZ~zG1D5mK6=$Z7dC0u->Wv?wMzUO?>3F>>Io0=e>x!u_m;a)TFb1aK&sefG z(2D?A%JFw4v?4LVQx>7tAERmB^Fv#Oo^EStVT8@+9JLBo_2f;%^8{fJ7f{oY00iVv zI!X@s|9tk?^rY=VE50xEUS>3X0ZH2hbN3hXGJEW-0=EzGfRb(auw!CeGTrr}w!yFe z1Dz0eBtOzaj{FeH@rY-z83nv+jup*v+3ko;y<^kflfY5aI5F~g1UbTGX`dTug-=e3G9Brs^~5bF#}&%5rB_M2Aq6zlZ{PIS++ z!3)oCvROtQB6Cp5|!E{Z|r{Tzvt^B*R~E@klmpf$8-^FJH!xJV6v!@#}&5G z*#4_IB_-uu0kZldiaSqzt`*pXVB z*ky6*cna$2*w8kg~}o;Gz#qS8w`?`@i%ir*?2QUP*=)H$7Sf|+^ot^7UI+aNwe3y+n(QhcgD+Ecb zj54+M%iSJn!e@~O`{YHRYF)oC^k5wg*wBU7Q`eCV?=|3>{z>F=!P^OZF8R4}%T;7w zJqg`U^Ah*MuRM3;XRIwWNO2iT|2QEc+P)r5Y`hK(iM=9)a8+Te+3$9GERHP-wR0xe z6KCJnN1}1<#!AI{d0u ztwlps4y&84{D{qedq5 z8~^PQd)>vip;qN?+8_riwE!;UsTZy>507)2Qqz^6F>@MasE{3x1gby#mXFf%b>8*% z=fU)>;QM{QW^AS_4R)u_zm5%5kM}_vwsA8K&^51N?qa9SMWoMx!OMdZK?eb`RP5LQ zfcodJK)8 zI|nZLT@ryjt$@s2 z$!QC2LeUcWzdh-}iaBM}sS)f)s7xwl23U9LA?sDezp*5O%n0!Tw@Yy)cDg|bpSG1W z6-e0R;d?>C<}~H;8y8ijqu|c`;X8K|U2Bi|4H6EKklqaJ!IU*sA?r4DhR;6+--rJB z;hUY}y#m|f#(0Up$!KJn8$E1A(X=B9l9x@frI>AuSLey$-h)+zl~>5Ry|e_c<uSAZ!x^K8T{iZNdHE{|92i_U;KOPU=pv)Fhb_$xEHh6QfAeq4IO(Q30)@`lt`s#o+9i`=;nLB#uo{qblyE(`Dj%w-1G89J;$XPjR z7E25k)zCKKS+@E~vnB2>8qd6pcmb?XCPewe2=jjvy;43HP2WW#Y3m`%A8d9YV|IGn z=|tX7>4Rww)5EI@njrnnuO(jJ5UpV=&f&E?cHdh?HZa8FRa9EcDObx@s_r$8BcG&) zhA!#v4I&L^U9WL@woUnS7tSp@`oD?++SXC#pC^WS-&6P$W7+3_+de6}+R-qUL@~r{$1rDZ6eXj$)Uw&KaeMUh0k_ADaY)N z=VlZD7TorP^5BrYOLFE{z(Wam(fkq{@3y+-sAx5wLA^Je=-uFtisf3J)>wdr$n;kd9 zgKnh|?xupgbWganjaAHe)1&$`MAHdN2m0*E_=$&@DSXs><#CP_%8gWbrbSz8Yi(=EJJnKDO|?l%kWsZpq-w87-f0I_#fxH4 zGODyhC=o$Orq))3+A9$uidrIxB?(#P_ss7v=h)84XL;`XzV2%g{p$8Pb=KicChy^% z_4ruxsz19jO{z2#e6m>YZ>su)x^gHJmAze%x~AM&nM;ky1jjD?bd@9E<(kdP$K>4a zKm12=;I+-!FS>if6>S$eQbS%ATzT=9l2WD8oV?V_P!?tN9%M*T1`FmncLwanzP~B; zXv2dpAGGDiUzPfO1k+rSCBu3OtinYe99=S2w-Fmf{guzS{0i^5feS@nPsv`0=8E3uo-{%) z&Tli=wH98ocjCQW!%3CORW3d`|2t^4CZ-#s zF>T0=or3*=BWhF;*F*EaH znaQ&R9q&)^Md;(6yl|2v(d!h(1V7I$Ck$jT(wS(EH{-CK!9)?R9$n?biu^IfH{0c; z>vw9XvS!$h)9>edpo84UQ7^_V9L_#OUru4HLtPOiF8p_1n(%>fKLxV9Y7cgjl^= zm((smkp<|)>f6Nm+%l7SppCr{w%*%OgZq&%@~lXb9sK%T_3jMMd$7mS`iA$6jy?{t zPUMjVcJ#{rm3rI`8NN;xQB`{=a(~6QBU`qRKag4!0px0?^7U{u~=?hC{j{P7!GO|8?v=*Q^;*FLq^BecCR>>uU8#27Tv<_{SRbSKv+nc+WTsKK(V;^8NH=4rpp*B1 z%o=dvs_Rn_S!5fTix zifC(l!7paJ1g>0eXd)xlIu(?@PBEf0wqB^}0iXu{fr%CUQpldZv{{fTUjzm1OopHT zNdGzU0?qc!ns)iwdJnmYZ$y?T4k3pBP0)!SR2`xvGVL9fd!^~oMB@jS8+@+Oz+EGT z%;rGarNzo>v90jghP7~&_k$_qvEaDeiy_x!*a&`^8$5tD8p9okzx!h}*Q~2RJQcQ+ z(?>EgBpP|wJY_87f|NYq1zVQ-A}C=p^HQ?wiEO*l_0X5a19XqlrM!avt5bcf7W}5+ zvSlI@wcR+%7%fXgn=T(qv?7EzIJZ#E>lAxhLTiGu^B@xd|6_)zmI1Z)mSY9S=rr3* z!E$zcV|?l@t9v^d&OUOvQIz${P@;Lpla&c=AVV0 zd{(18!~Pz-fBJ4C$J+^TvCs<4`8DQE$wgqhCrHI!ze8o#S3Kga0FDj zFz-u?gQ?2ozbY<^or=kG`Nc8S#fg%~ooxQ#!UydaiHrv%+P`Wp>xJ!tg|HEO!uUDy z=L3h!-TtqzFQ#JceebB9%|1iUEvpjiXAOAZEwV9J(3x~u{1>@p^iZ4tta|qttIQOa zru7x z@P|%?HpAtI+Klk5Kk!E=OKaQWDPHljlhw)5e^PBrq_v4Zg?`Jsg zVk3!|WEhb(BM$_r6}LUHcV&0iEkOGakPOI!)2@25dQne!g2TmRnmDP(U{+>Q5vx*Ycy}OjLHC&?6`;Q+=39A3V2p$oEnK50Y<--KbCsvi@$BVw8c;uXcASD*|J9+)0WVU zV>skR#*7gRtEOK3*YXH*1$TI4OAp39I`M>c6mNvz)9}wOxhq3tdc*w}OXYtiCs~WX zV4?xQ&!ow4Ncr-g#Qi0oZ-v2f?a3CqVff z3d-W$x{LO)BgkNf^C9M_h0UMLgwIAGZWjp5`e``W6h)#_CJzWHH6Ps)?!t|zz7r`N zj*MHGHO3=*bu=d0IA|N?cULn*3cVN~r3jA&BWHONM^%rAd6-b*f&OE`SFQ9zl@f7D zs?yLcY9;*L9x)x9Z2UPpkG@X&1tYTYYer`UO@egbDQ_JDD6Z@W@i~KCmvqb=LNv8x z*p}l9+jJ?Ht3aUkc5CWB-b4terb9Puq-E{N1^?{2T$hDCGUeip!@oW&yFf7e zf^Seu-&(SE3BI#CC`$lPc`LMGdJKd8i^iHHpF*aZ&!$~$oBp!N@6`5+&^l2J!aoShe>|O3-FMvG3K=NhDWgOg2wAF+gTToEied~>(z9Oq;1Wb!~GpN@E{docCk85|1L7UdLUj=cL^B{ET zAnO0yytD0dP5m>cru{y|i@^&;+|XJRsB{Yv^K}hbPj%pM1Dy(@(JOIJt(9( zCn_5+i70Ej=z!!l+8iXKH?-#0B}%q}FeEg#{Abstb<~C6l+XZVWB7IeM`6oIVO+(} zWbzJMsioUUb;-{hj2cACY_|lWCA)I`(ar!0ksh7$9lE-P?7rUH5{K>M#m&pZ=@n;& zUL=;!L_M=xzVV_=axY=d7im&`d5uMhv&AO>z(L^`oU>ghA(WtaTZ3P(=;$`L4993| zx}j+BkP2!pD#6yP0IWOq$J_KUjsA?W&kFB@Ov%SYqoEJ@m8-bsWv9xoiWlT(dPSLo zW^4HUe&Yrl-7^%Acd)^evp)wRX;PH4HyPhDkDtpM6JMLlI(_>5V=F0Z-E%LC>sgsI zpw6Y+15|WmZe%1v`5bGm7G0%1GD{aAD5(7Zg=dgqtDB8Q&@0yg=xg*wH2B9%5wdi$ zSoMEiu0CYb5(i9URKAEuRWt;s#vpPVXg2*yP@NAjh3vc#@h65Hj-N1GZUil2Y}|f% zu^I3PyYr-LCG&t!>fqs!OI;c3r%Z(s!)ta%H8JaP_`gw02*P7Y?8?R`yqaRY#^l!D z*5hHq{Zw$I2cv^e-1^_r{8Zys_UwarYo%A@0Vp8~P>Md#P2=%*L>_5nE#sCNr%LB; zqTbZ%1?I(kA1nAb-6zKTqB^~q@^O=x@kM%WQHX{k^I&a6)gG%ze!3T3>kGSA624yd zNb9|?)$uiI;XE0yJ`W89L9isz)@#qI&q1HAdH&S`a-=^PubGvqIy$aw=%f1>F$g6= zg8G7#890@QY`O^){NpwwF8Dy^(rxo=9g2Gz+uSos9rX-r#xQ!$2?Ieb%Yw9`=U$3)HXA z6S5{Sva`~zEDae%avAwM-9q$TK_w>)d6b0SOl!194Ax^-x%TCSq;k%B=VAnanqb%1 zjEiiZv>Rky1Jd1^nanVyxzs@UKYUQe-Nh@-Z;Nja3n}WE%dw#dmA>SBO-{r%)nf!Bbi*&v6GyWIv-R;!fxfSk8nO{Ac-PpzgTNYkk6IuCA+VK7QUzz2**znsUkRXM$1Ni z&odlZNPPJ$A=C8*0ccmzwJXTx#sXOI0EULpbg$(cQ}&Jdf(Z@SGAzkcAEy;mo0@Wl$=Uh6M~IAAPvQ(0Lq zR!hZQ2-_jOxD-OAirTlvx(Z-g1*>AtB=I^heqgPG8OohQ-$F0n>^w1$dy;H!-o)FG zqQKG!<#8}RLRUTh_f<<`XMpx-k@=J(j_;A0qZEd_C6e4H$Hd!fvV)ir2&-oK64%8;AHBEN|tLeyjoIRcU5_)SqvZ?+`_ zcd@N$eG)II&Egs^y% zajWKHW>Yq9GmH#;R=1asdQ+DRp3$rYlgO+8PI)*zpJm8b;4!>oNjl8m>v1^b-11>g zZ%j*UQ|Yv)KqXykW6|*Ql|l(>(cO9==zkbaN)iVygV9qSJ+Ck#m;npkSkq5m&Nap) zx{26HRk5(1tl!cP^!gNyj%>D55fW4OX8H9F%3bv#Pum#R0=JKfo)zy2@5B$f?~B7E zspT~Mx3RY>6RZrcEMRZWN>Ml0e;eba()W0nP%9T|v+jsi`iTd+gKEititCO! zx$SVb22TSf6$!b90^}^mZ$gfDMq_4lzX_3^y*p?%ULT__%*%Hl>ZxHVjN}YO43S0u z`4bqfL{$|-W|bdj-ip}0zvVx4DA#BD`C3@!T;s)I@>x{{0npnJ$B`wr_J3Gfr zP2-=NN@{$G+nA5xA}jEsUxa&>98QTPc`>zL@=;cduKoHa6RTny|JR5Mu#Bu@QSPOv zgJdd0kn6PJWUE!Eqg#Kuo9#=3(zkGb;NKZK=wTruoz#RmwKN^IX1Dg^-QIpxN?P!d zgq?_j1t+Qr#mmb-^rv;UM=_>QXWo}GRDeIiwVRqg@hQSf_a;jBuu9J_o_vQKmlI$> zPB3c3cee&%3Y3Jx(6`HkW2Uu_ms+9kV&qTXj|m;rWr*1{tFvt`FT-HcaZSol|=j#(=2>h42n?&HxsB!%9sgPhJ@3=w;lkvOP!?l7XkS~$CnV#w5Hz=};}XuCSm zk7?x?S*Z5x*G+9?Jie5ZRAgfk#)+*Hqw7$qQAojw+rc`odm;%3Jo`e|dz|NVNCA?h z%ON=A7D*cBZaSzuixcv^eO+hu+6omVBuUD47)GtZrRwCRq{X`7r7lIsgVaf2b6y$^ z**uD4#1PqA-w#=iyXP$s$Q88SN&^}GQM-pXCAJZh4I@8KQr*&U1;%`YS#3yvAz{7- z|0Lfw<{FtQG>P&1fs8*lWAdBgMmlrsBrxb?N>SGo*jJ;^ld`w6R&PZ%jh`*cQYB1q zinKR*lS|SpX3NSf@6&?7BzoocmAn1v$N(Asc1vbIpfye+iy||0!WMZV(^L88&NHVK zCpyc$e8F+xTvr#Na66G6JiA}rE4r9ic@<&bV9CL^4M)IK!oIO>mN;{+Lwa~A&OxiC z$h|d6ue#o_tGZqQ%K$EjaX{uu+4(x z^87TA)D1d4t+U@eyXPKpEl{;Su~`PFeD%whN~!Yw@#!~5F?wA(fS8|L0Sl3I>Wp)w zd9e-EfDR=K>2@pl+Tw>E&+f~M%U4JLbUxdNRtc~G8~gU?XsKGN&08g(gId-oU?yjx zKAXwTNWcVo^!hk=^55~KCf=K1?QlAyXRGD@fyHh@Fy}Q$CIb{mw@8Buslx{R_E76m zJ7hjDD!+NZ?bA# z3%`S_w_3dypW_qs;AXTVo6Zv5dbwJMky@_s3d0N-A+i7SbwvVvH7jTb-_h=H+@pAP z<)2-Dkselqe2itq>5B!{!N02hnEi8o{vhP>kBV{3MQ(wT-EL4(lW^vL(=IKDxIzXB z=4Q#Wv#G+2^g4U}bJs_@CE{p`TpyU;(q z$C~u}&X-T0{u9*sKl0c42IRKlXk$(rC8)BKf6YHAYxU!6se%$17B{&%kDTHN|C1Leht*8%kX?chbSJOBuZzq~}iEbvvPik%>ci(`W&I|9S z{ambU!qD92ImB>hq*-Ez_Ck*4Hayj2jeH$g`lXZpH z0Y20XgG@>~Cd>{Tk@v6Mv4KG{V!KT+kIgt~&WPg;g`8$2-kaX%>5om5$-u9S++>#A4cgen*uVNU@_UR(*m` zf>w&;#j8HMAseC96N5s76!!GARYB}{L6i;HM+(C59Z6QDtjnBEHl|Qlk=Rr9ZzvWD z1J*V^MwU#Agb_2ad4ZYCnVhU+2LznvX32^gCApu^-+bmfkn17NuRk$p(H)VdS3S(` zJkC4`h@)aSyawwu7F`_87{S`Vu4o^znS@PG;QIjLKDI#JBMJ12msks1c}7smFcw+JO= zxhSO!PXQcLE>Mp*Uu^p|=G&G+)c`dE@?pMu`#Ph0eL|glokbqN6f2)*(?5~uM{`xO zH_z;qcS8ld^B?a_`LyxGi~BN%!JFBq2+EY1u-)MW!7q-2oO>MP3c zt@F5qwho+>TM6_Seinw9?68)WnE6xeD6BK0;!6`dB`c~f3=RoyfoGTm0LG+^*a9}8 z_-QAp`?Q;3Tf54VW(sE7FT6)!-V{*yG#@QHeBh4$2Gh!)1OKH>ZmS@;KiN%TURlG=a z!u_1(eXN#pFMx2)*4g_aps3%YtSgxmsbTNBfOuR-f6V(zi#+jE0&T2#VVlwJEf00$ zo|BwsoFAHYss2Un6R&gP<}do=yhdNQlVl4l4RB&(*NCkt`6}JkBx}q*BX=$Hw&Kru z2vy7b22-JY;cblBQ{+L4z?$Pe+UB2NlJSft2nXkEoEAO-zBZ0t%&_x_(Yn0TJ+48f zRHzJlKYd(~xmQheJy1BcecGr@v_ImR^CK^64PDKU4swz0(DH+vDUI1-%6Dl^f6@nW z!-iC`5tb4AW{GYnwyz|Z78PxE{d!$qbRiH^$Y_W9kD8g>n=Z&XJxH5JH@1XEg&r=y z#0Yc7U|zN1G>W@aZqA|mJ6^NRtPEh;g?YgF1SjG0Y@|4Fu7x$Idiid}UNIR)&aLO1 z1oW$8$HS=7*fp+CuOylO9x`(52y6Oj6%B=dSZuT7Brj+I?@D46mIihlrFWu`&vCx0eTNf%KDTr{`^_prrB4UaYhvu}lHO&1w zZn9Q7uyJL=a- zEVnC1No_7~Oju(b?V}IO3Xk=SPmxZNu{;~Fc?h$Aagly_4pz5uaQR_{vL>_i#$R-V zAm6DS1ThS%lGlOhT0YO)E$OVO(2|sJ8kORfP_&fK4pa%bau6}3D=L*$uXGN@oBQ6q z(D+8E8bt^AX6O;Dg@w2v?k%5qp=Z$*m$Dqxg|)V=`sTc%3!F6taC60Zd%kw{1W5

gUP#h@>?(m^6J8l=PXG!gil#@UilD^KpJ*ce2Ts7QWe^S z`kE-*#zDC%!J!J*ou_x6Id}JaH;Yr#G^cIRhl3i|=L3$FWR_bm0G9@?1s0fXg>1@| z54<8UCa+L=u^ZlQ8T~9Npb?Ck=)sE?w5f+37NIK5hStg~)6%AibD;6sK$FgnROm)` zc$RoP3E=LHfA!Y=Vx>oWlgk~mLU1kX*i(KXO-+P=Qpv#1MQOJUyA3E@0|U_<0E$Ua z)*8kJ$pnF*9r-!Aq%c%kdQyI+Zv*?jih^@pde%;84LGy07A@eb0e*UrlA$`Bgz86+ zF!k6QIB~I@NCTWrVQfS!j9uXC%HN47I*8nsmX7k8f*6YnSfZ=|1Hw+^_uh9rkj zQ(UlFWIcVu2uu0H-;GfGoNYzyv1{usoAk!s_H|-U4?@RHuFg+P3g+Zk+qOX|%p(ua z4upaipk{dl>sFtDUYM|ACL=1Jo@K+^(}0Y+cA zc1Y7#?%#?5g8Z<^*RHn~=D#1WV~Vv$9gJn^kw=U2i}`LnDbvdrG~%i)pY`|A;0r;> z0vVp>t9Qvvusg=`?NVz*dxE8zE?fPAx>Lq0-ytHJ3(m7JU|=|}-b$G#b=cVyWb0vC z_2texO{y)-RdFI8R)UH|2hX*8A8Q-Umn@NlkZ~VV0U6&$D+Yj6SQa-*@v{K*x#!U=r-&vGzcTXA!)Zbs*lKHmfP+P@eAv_sp!o9>^jhWV8`Q9@gW|W z4#!%W@cR`Wqcy6Y9Q~S1F*T>bddZH$Q6OM%g{qVBsj&Lyk(d^e(4c6m_H=9OV=4I> zFM*o0d`$Cj;cfAcZ~U( zKodk|&{jDh9=A^3{Abq|!Jvp|~;rs?=$!!DKWHe3VQjd)9c(@{7P*wV;*K3`ZJT zv4;dmA&g$Z_fYe>?7*5SPKb*x7Rc{`(>ZKN)6${eaiw{{T`zWm(3qN~c>Z?O!7#qz zYDj?qM)d>&HQa_1QOQ#ov=DR^FfpNv`9&8TLJOmTWT5wPE1E;uld6?tzC_j7gC^Wh zZPe_xV%zBC;<)@F?AWojH`3h3j$?NRRRTzWtNF*i%F~BD?HbHDOR?(I4-#9}z~FiU z!4M#~#G7b*{eo&NKKd=I1zVipRfxb$t4wIPty{x2TP0yE-jyMP$h&m3vICS|li0QG z0vW8Kw#^-Xzi#nzdE8XU2nv4nqN|x>=IuGNXo-i8Y7*J#(X$u5y90U5!L+jdwajl~ zm41TSn&xMFY+b>~gTk5HFo;}w$J?W8@JA%lx~OP6XOI@LWFplg0Jl`y2I!0yW8+4Q zjmV$3Rk6hJmFlIPJbFb1YVVN*8b1V>XE55~hNYrguU7{hN4A6qr$VKEKdU}{yqg@j zPEvenYYL?%jrsCo8?^Y9?NKO6FKu`d1_M^LzTjSUP3)EkSGRRnM+^=7`qPzcMsS!^ z{flVjekx`=hyz8ac4}JMRRJ&U79-0Q&SK-zpQxhw`P!^SmNDumJ}l^8g#*B0q^Lx` z)jzwQ(KWe_5`yfiQ1wye-5Zdw&=`e3ng|8G^DKtX_47DDszMA1(N!kYLWhOo*aZ+! z&rz~#*%a32wF2q+k_oNSxx|DF)%bF4S@Ky^NT;9`@H4C1k$w)SDcbeRL@oDkuO zc-Up3XvIB=M2m8>=E;}aRs=9qK&0gaB%FpO9e<&^TU{p~`_GMMAM7sGM4Hn-r)c+) z;5S~CpSl=zP0BJ;?b*$j&B?VC`X4_B%6VeT!ZXdvR;!h&LAJw>OCpBIaM|1(yfjvG z`8x;lFcnSp)~|+rr+l&bD;q{;as(rVG!+`lPWtoTxG%R4qM7J1jYWu z*163JvCb<7b>b=M-Xu`c_PT82Qw2FTDti}*;^-;MY~sLgc( z)|T94$K2y$DrhiRs3LLPscndYmJ}~GGB+A&0-q2g`>))O_ltu4~CTOe{lQxvPY5UrGOhpm7lVx zBE%G6AcorU?xnZ@LRul%*jF_sY4ZM)Gptgc3VBs}@oqD@6`p?#2IEp?u<9mC6sD3{ z`N{9{f=gT*fs2&jY0~P{(;pEE;;?RK2Z8f8_wJ`?6iSrZ*X59!WJ9}C8 z<&Dh~UBkw3w+#!Ig@#%lO@Y93>z;!7|3^gVCGFKSB9_%w7w(oNLXii$EHSpta{@Q9yB>YUZpWd+aGJ!l@aQ_%C z@d?&lFWW}mfCh(QR>Yfd$jn=KTPybeD7j2@L+^nmo|$4VGi=-Kwv3zjCPbprIY((K zkw{9H2YP1PXuxAJIvWVMH2aEsi*EM?rT#r$6}3=92%)CY(ZJG#gl{DF&SvXQM(c~O z$o+V#y+29!(c@O<56q+KNQFKL*w;f-V-R3cm}xra{eFA|*MDY>v{8dI*=B6IV~L6K z>!EN>S4V%*a*sW<&W=O6`4=pZvtA9%!!qsvT~c$X*23a2eqFE8euU#_bW*^(BA=bS z?m3^Ub&g@oOHF_{vR$yY7F3;yekwQa@v=UEyeD_S$V^nl=Yb@sgAjkv_MpS>c*cRG=6MW&^CihV3~A~djei=f{T$&^o+9$o|?w^ z8o93v1VXJ<^%YauTvh}x51|ARvtmmNN2^YbQ-s$J-de+(p_HgQN7#w zB?yKKGS|p9BgmTEk<_y>E zQ)bFM$(ypmNx$jPIJC+vA53B;I_m>*sXg~wEh0F2h@u7qN=D;G%(n^~Q${2Z?8wLF zZ$GPm#BVK)%Fm}66u(lo9>MP~>3v>TKMnvPI+3l~uke+9Et2!~Uu20uq5D-NC?PuI zE0zZ(Pqv)4n@D{`Jkd+t8V1@n;ISAx@yJBUYGV~k022tf%|%=^Ab9OL}WBfkiKr_vNbvh1LLGK18F^lybx~j5xx`Z)FjwX*WHgf8Br&qQ@Kf8qWu-mf9sd1aBMmxAOy_ya zjU25Sb2Vm>rF`48V}%T1o$@>2&G9;OMR0acuc>ml5p!CoC1-75$2y-eMHkrhd3ToM z0=F~$^J`tNE2*+b0KXo@b?T^%A@7J!cL>veea*c#J7oNM8!!49FJ_bE0Ka$_&G1)a z8~rVHI4pV&IkcI`{DYknrgJbO2O@2H&q6+f`V|Gk}Cl3be>w&H?}mtb}`8>%y@mn6~fUK?q=Uogeo&kYrVZ3E}-6QV0+^_X#_>0 zlpr@jit4&`Cm%}Y28QVuxt2qN_tcNxyWBUo`_RfgURLt$k@|MS)CrTv%6OlX3&?e zS(zP2Q9V$my>hh_gZ0n88~|M|fZJ?~8U+l-M|rq+m-0(9@gdjHr5@V>k+a2s!M0(H z{#SlBm(-gEX{7W{)R~k~H}tvo?KSS2*BHP(5!|2uPTa(ZPq~suCIuA1U8A0$V9wD8 zS3oJ>2gI1fs}4W)xNK;+{n4=PI19OFrzMY4y*n8h#%S98IA=!rxw)||oe9{5McNb= z_Kvac$Fa#-1D2IZvH(0#e6IIvbZfX5~WG!DS(YGp6 zM_6PH4dWK~P9JVfaT^r0yG|o*q~1xS>JMlD(q&V@X9#M_I>;|KdOu&V`#1d~63)zP z#W9}hhec7*`1D{mzVY67@i=*?N~5jS32^Tc%aIaP@SK@Kd%ygrc-u}YjIoQZ5l`#U zT#fkXJ%x%TfSD&Tuc?2;MGo9v1T=Wezs?UGE_m(k?*8#UfgX(y3%Z@99OHsTtes>0 z$a~X(oU6sk@CP2Ji~#MI>j(3Hnjc^q_PQePbF?{QwzOEhA;}Q~SBOJmqK~Xs{Bqqs zv8(hXpnsT|{oJ}6GL?t5MQyg3`&%QX(?bwej9Kb5J5dDCp7kHcUA*Z$M!yz!(Ag2=IMX&R0=brrwG zaX`vf(?}I1M%_XtuyM@92zqRqhAgK83q>fb%&Hq zc(lhPlHZ$h(?JvWv2?$9FDsJ99NzlkRmP#k3X8#W_&fgZLe#cg7AOzI2Fe0Nui;=n z#ycTPzmdr7Cb;E#j0Zh3vdUFH*mj-vDJ}rrzmVxOFYM+%u-)(GtOBBf?qFoKEurKRu~xEtt5=LRSz^Lbl-Xd*aXGJp*Nq%(rwYEFds7#X=<#EG z&V_)ahU)knfuoreE*)clY|ESCJ=1?1Q0u`&*{0AUUJNf+Iw zPbsgv+C0lznUFjPMbovHMBLC3N3+R^^NeX2n_=?MgB|CuGX~u1wo$VFHsu=!y?E5a zct<`jGl!4KU!QG*M$?0(ZS4(4cplOU6^f^t_4*pHj5i0_x_qn3ZFo3A^rxS#`Pvkd z3Q(^}BELStwwtdHC-5DFW?f@{`vwyVW?6JD9G4T1GyUSkhLaOMxk0>qZ;@F2Sv2H79Ye_; zPv$qX9_#EME87s7Vt^7q5G2*DhOx3%^J@>*YHJMtOBwE1r3Nw-d9Op-x6zJIA@xor!9x4?nB>>9jN#X%Ue&%2Pr!md_uN z+qT+3CsC==++wgp{aZ&Hwf@BYv+GkOsBU!P`$|d)6z9PQ0WHMj=dZ8>mtLHmm`}re zXi1s1TM1nEVvL((DQua=?CUPw<5PPfyJX%bw_-Zp1?$DSoiYZ%NAWzyB+gthjAaPm z_7zK#NH2^2paa5!bA#jgjfC;`m@)` zpuoTkZ|fjnPmOf>Z-+9>r@`PMS_Qbe&l{OBCP0PL=p`)Jr}34KLsy~w^987{5e4cymyA1s~Dc@ z@3h@UODzU>(0j2_{^XXYJiX<0T?0O_g;XID3M-#A^=)Hu{>UG+{+92fo_WXD57j*> z<4GLEyE`QzZSK`eA0l62 zhV2AMN=JNaD@$}^d4+NI3BjFBk0!jG`-D>@Z-0w@SHpbxq}-V$aAytb<;MmqW%quu zNo~CHN9|I~RWWqVr%rB2N9KZ%;1%W?eeY7f_ls8G|DM;>9jWt%MN^XK-V>aMTciQf z3}lLSAq1Gntk@(+;AaivwXMwv3TVZNKrh!>gkFVi!j+kDNRYNagCB_Ik2%Sirzh_P zfhUa$cbq|f!XsoQ{O>pIZF)rOKdXH(0o8I>HUDt; zDr#1FM5Vs)LJ9yH?Qt$;G03awwAy88s7@`iv-wiqO!bx>Ah`i*1teqIpx)Q<7unqG zWLx*t+o=$EI!F$l$We_jM6P(Yh2(~awV0-eQ$8kzTFd?TbDgc_2@*L-V9GWpqJcMl z-BQ8K?#GJ#2{XlBuiuhkA$f6z#E5OwJ1_yggpiSsus3JS4px@LRTPXirv24QXlJ#S@PM!<$Szl4tH2{KMU2M0qiM$U(^L;gOgtL(wSw6Lw?%!|UunNOt+>J5NLk`-!my6Lz*A91H;mu=uBlk6|wT`DpFCMs4zP%`pQyi?56p9R* zr+;LKQ-5FNZX~_bs)EF`R7@lDiGUfT%-T$%kR{*UsY{JPCKJ)8S;sk)l?w2nfACf& z4AT!TArH~dwI}n9-`3>-=UGT65)*&x-6e;|vp*Ue3)GKgj={rf*~;UGx|;iLpY74r zW!tR=c|7VEP--aZu|QA!=%{J}NxtzH8`D+HOSLIxjQM%VGMB)09Pv=(mmcQzZhSBt5hq==9hYEatV(2gV?w@!dfZd zVt#z-RL4o&#~sZ%`T*sn6X%-=7CnK5 zi6kdKvEa9cef#E(2zub8epd%#d`)z$+frwHf3N(Vj@d+N_dH`rM^XR!1N8GKNW~Ek z$rEL!$?I0xm}qH}V`0inLfjZH`1SD`8Li}C8F8|F##`s%=oO(_QqgVSjN|=`SjI{G zObcEOYf=8`%Ti)sM0kZ*n`R3Ty(1QA7*_$>PJ5(QzSu89JX!^dj3fjU?9HEv95t-a zay`94AK&mhU-I)kkJ%uVNn?U-WYN|jd-p6R8EeKLJj98QSU-oxLL?} zP6t8-herqdbZ65748{^2H4ilLQHBDQnGpU(chyJ^Y@|l){6*EAp6MeaG3j+jQJ3&( z1fLY?U|x)V@~fPyAW3zq;TM{+T5`YnhtaHy8+WFr^Rw)+MR}d_4#_z8>>tgv~>}~or)#f;Ee`_{gSm8@y$yOx$m2c@kE(u7A z8_MT6gZSVZFt&91C(+foli9 zgq7aDjx&SLR>yod-O}Rld++!d)&YF4?$h3^Nl15VZz@dnqiN+-G5z*7s+g=S!6sCY zD+V6l|6d(1$a_0ptbQOq+3imyLV3Nb=lQ+CzB{TP;wzo*Oydu92&DchPDTZIOYkW# zF^}jLDM2m-mj?{)cmPsa#Bf&WV{Lw~DAHXW^9oQIcofm^%L->WOnWcx>Ks>>B{lj| z;ac}rGE~rtPkGTYwL|0#9bUWQBD3;CDYBiNnwX%!!W{$Is$_zzeR0eVz1<1i(GGB**m z2i~M}LY7#@v14s;dc$aNW%YLc+^k3ECm^kneeE2ll73QepJF@-DD=#@bLiP@;2%}5 zvQpc8XOQZ$@AyU-jW4-gT;Efchzb}0v(=bBJ2m~RcCFZDDTbr=?qNi7O^9Yn;Y;KD z%jZ}aIin!@X&(nKp6B@8n!~7d&T8MC`y~ZqRelE_4}y}0Y6xg=@9|F$( zvkOk_3*fN1XW(S=#&v>)={Tq@yVJ^kRHGuJnOV=QqsA zef2H|T)-C%+-889{~N9c|D8f#448ftMlXmwPCu)UN>3L+I(gyb<~wsi$+ZhjfjND= z=z4U>!~(ky~@y@FH zf)PTUouQJl0GVckDzK=TMtQI1x?2*AlwY}9X2C}dzgNZ+aAi|J$ zp4-n|n?FDA@SkFr;g@7M;L4>;qZqT4b!#B;z0Ug8G)t|7EWgXu!i{>F+(RlJ(nrYa zxbe5I&b`f*;kwmS$xW?;-z!WW-)T!Mv3X}rjk1wOkAXX$xF)E5*ivB(X}|cOBw7|r z^7un`SlhhA-N6gwC;T*mk1|s{B#k6&;9DDw&l)VzC&SVhauT4MMR1X2^fNNZ+_&K} z!ruo!Ie~BL?){7Nuah++%4HV+-&h?zdeNZk$8bMH2CZ0b4KgT&cp}FqlE3d8O5U|R zQ}tfbMUR2W>1m_Kp=jddhZaei`bwP2w&`Va<6H7cj37PER<%rY20bl&*^eYQlu-I7^IwI?d$v4!_#}ZJhsJq(&l0%Dbus@ z(-P6V8zMsdMg8ZAW>RQ=TY#kEqyLy9QTIuswv9X4M$?7^Jn)+pjDr4kRUjaq#BAf` zhJxoLi-CMy?td04>{ zK!b;e$EWuekh2eCT8FXKECqB}cGdFC{57F~1mkOEQS>L6Ed??-@N5Rzp^d^)-eC?0o;Jv)a0!pm(w5Z?v8#TnsasOY*T)vgbs-e1~_Fh2rCb6XHT$ChP< zWOAflp#al=C3CAY45jZAefJo1>42C{ckBagn}^0fv23sgAtA#60&+#&8z$#D4^ znI8%X8r1ClubuPkb~<+2x3(SQz?0I$n3zBChfL=3?+rPOV07P8e+Ai+yj9gYeGzoW zGbY>~j}E2fcVK6}{w=6uaqz3JRp2lp>rhpMH}PLxyNBUZ$0Ls6g(Vyma#eFZjiqy{ z)0q#kO3AIRZf7FgKlgBSFb(fvf0U-iHst5=nL`Db@NR%l{ zWQ0IM2s0=Uk}xvJ=zIHq{D*&pjQe};bFOm@<_P+%=)t5li}Z+?YJxk0_=sc&4XeDe zuf6M{&9jM3R}{=7(>JISJ5rNQT_O5zdP1%V3=VdftVacU0-Kq?sh#F)Zq2Q~Q} z=qxV1T;xY{ITLCa&zKBwn+xE;D-HHArvBz_Wdt&k*!nqQ&nrnCm}9I*4d|U^l8{~%nIbNxP(#0eam+r{WmdoTj;NPbWy-S06N z?`rGnlT&w8fu&xuivS=A1Z?&0g#n}GrGMV47bme^%B=+V z!3V2zJbpi3+_x=`@e{0t(S@N!P*#@#Tf4Jm+xgSDy$slJh zT^X0-4kASr_bRa;tQda`y?Ou^9ECQg49akDr;|Rn0foTrB=>Sf- zPe;9@t6UCXnIDZM{cqG}=R5I(peu{?&O>O!Wrxd__Y(j2jxFmPGl?HV-_}!a1|+_0 zi2m7M-?|6ZUhvH4*Fo``rHV(pHDMn32X@cy?Hl=1+tJ<%L@INK2 zvN@HiKCW+>bIVmVRt#7DST37Y?*QA8?}gcILqSdO_j+#wAimh3D>I6>MNqsjl+7~+ zmAR={u|-R(&nt#y95D~w!DjQ%mnICOQ<+gJcBb>F&Ezta>rD|b>I0Y8UZcO0sj6Z$ zFV%zm$EO%aIpH@t_z71^Nq6O=Xsav!&VWZSA0m<;Zpw7*OCwBh*FwpAD7v=@rZ{pd zGd<)MQ6ur9JpiVk`_{j4iOoAa&iM9@K+S8pRnhEk5a1d$3OsolF+K2_1cqQo#G_oQ zX78b#nU083kBMLN1yS;%0Ezctn?Voh2oYNe&&@d(L5BS1O#abI&X2td**{XHJRd&l(S$F+Ig*{B!2e2g#x^c%Mk z1|lb(%qSqcY+{^)>2<+2$A1|{SXx>D^oADB8sMK59Aq3iXo<7JmGp$~x*GiFCL3=G zYwNdv?_)UpNYZldE=fZvOTBkPj#3_HkfdLtg^g&LGK8!^Z{Sj zUtyT;$DOa5Skr~`*=+h4qegivhDcS=-1A)3@+#MMp6CWZ^GlgU>V7+ifEslFLCh}z zWfq=hjrlj6YxuI(E>m)}98F#pTdwH?Jdi|c@)A<6&BZgCo0IxMz4wxamcJ5Nq|~db zO?9UxXr<}YZ+WoMk@3@D)ck%;rlYk+klkqZ2JrnBr+Abxh>1FMiZPWB-AVqKF)#z6 z9t1S~dkD`cu*)06Y51PIEN68z`uX;Zi<=E<2RgsbrXWqG1D~1aFY!~(tk(x*My;%A zMTc^zEA?EGS2JCkHRL!XxpQ_H?mx547IiDH_eygao)8V}hr@PzBZnyp{}-HX+}L6Oh%!=vt>-r! zVj0%Tko|)Da3(TPe7s!Y5c3wclQwW|%W2LROFGWpjg2kET=CA^RWMI`sxhtF z1eq`+06}N4|I!NxMCJcF>w;t|4vUJ_yPwJkGbZH(a1BzV2`N^znWW!E3H+~mp~3>h z>56ZByPdOG<$(dkW3-*@Ue#ie)(B*mtmcfq<8WkY%X|iTzO&}q~=X{n8;J#28+>p2L>@tO8AHe4-I2w8NrN3CygIktYD@f^*MLQRGCIv&|8>)nP z^(z%7yQ#V4xp`^)d^`i#!!K%#^{RL9#KV$mmcUL=G(3HiREb~@Uu9ot`tb;;s57F2DPDdPw>=yO~(*Bx!YQsLxnod|Qe$wCW4? zzuQvcA4Ev44Tc;s^!;)!sX)bB{t7`UqskrbRdhA@1W^le>gz#BI767P3KAzNHEmlV zn!`g2_Nv$Dm}xBYw=hZ6H4tg!%&9MtftA?zWDzgzjja@_uXGAlkDT+SSz;+`r&+Xv zsXB+;*Ot<1%7Y_Tubv?lk86yDrlqePQ4(E|euIX1zfqmPCjjS`Uj;c?do zbW-lYcx90Q7a@}V^!(6uLu??xRl#txDIc1~ zxZQ6Gd&KQxq{4MvdAPJ|0kD~tz%BVdR)XEYmYe9Tz|TV&MtiTHe)ABK)S`NhEc6St>*3!VXI1i&Br^pyGxzmijEcG+Ru5DB~MB8WQ&O4@kl9fg2#$<|(654?kYz<>kJG zhj@@vC|!Aink5yl1#Wh8Us-bKZAi^v?(U*XBVUcx}R44GXc!(R2+^WA&>O+iZ1!cqSY{c!)GCTH5dY#YU zIJHFIGHzEXW6R%$G<%#aV_Qhnshf?j+ES4>f zx-!ikak`K+=X}Tg--_n4l3^jnK5n+~5KEt-9T9Upnj=46A}4Ygp#wjTb1{SLoVk-9 zFBj<#dHZF-EyKG*NUH+1mRcwRi$_oLPIvaWdR`~IYEf=FQ&&D)vY!ywR(JT0X^COK zxpq*1(9@~(h)Z9Bp3 zZapw2%Tix(M;(vi9#jw_ckc8^KXLukIir-4+vrLKR1%`fKnIFxt<~_a_)}dpp*-i( zEPi=*mN$NL5xzf23V9@1>l~`$Rxm-AEV>D07f&xFpdtBD)e)gJ7LzXW3WoA$nxstT zJB!*f5$v&RaKek)Lpp?kAM`=qIhS)FQ#CH_o+_Uzb}^X*J3-LExC=ArdPABYHbZkz z`?~g3)S~++?J*q5Cz(K8+kQ=bQv4v>qaVUbpq{Rv0$%GhIS1fc%EqBN#;1YCrCJf; z*(=56?TV<69FQYH{`}TYH~#EZU?+U%Q^nndKj#Q_>CKiwrxvN3Z&0R~U$RD9JI|{9 zxqK_BlM-t4g%u^7R#0XfkB><%ij#c{oo&s9Ex?@Mx~zIif!a+WZ90YWf<{6i>~||J zE-nSV0l<461=@=m=E5kb36xdx@qB2`QG0J*Y<)d@bNL{0|0*G$e>$9OxMVPfbr^mG z(+pxk%tV!tD9UT^-%yeFEc%Z||K5-IzQ}{DtZm5RpcIuH;`$xQmxfXGPUSY4^9<21 zGg1KU^jI%{*e?wTSOfUfdrtuA0MiwfstB{&QYlCDndpeK%yilVB3hlj-z&GupnP z^HiMrjO7yMWbJsE(dOG}?mSt!EfNziD{#UJ%m}}-31%Q9P#P*}y8fUbn4HsN2bu18 z(Ny#2roMlNoUXIwn8qWOCUDpY5ooqzYybegA2C>r=FByNeLcNejQ@7X$ZhIFaVp!+ zrub<$s_DbtMxvP3o)w$5Ew;c!>8TDNst+Y0$=z0c{i+2n9F{5?w&3ESdo;r`d5f zSCS8>!4aPSaXitjCT*DsS0d4zXAmm1F1GUtstF}K^e9)tGjY*LWIf6oW0<(!O>OjC zVa;z8_up0Hd;Ec?z%7!bw{~6*`UTl>i}p7%2XVy(7ykTh8@V@C05s4YaSwCf)eTVR zD|2LEaNF**PR&Ktz?&*bYp(raKe!%j+j0(8zA}BP?qt^OOx4eDH3zeO2)&Og-JJVX zfn|Ji`4c&l**kBjUQvindQMCi#F>S_py-teo(&I}1+>5oIusAlx5Rg$W7#oTU#9@z z!U309S4BxiW7v$qg*)6ATii^=7RabKDtNLbYxMCeA97Bf`8Z?zNm)A9*Jk?a>C2NM z>6;jPK_gOCsDPmz<97ZqIcZCG_t4=U4C_8v;EaJw=-~Lov_EtwkKGQ!rbZ|UZAvGf z0fj397bY&AdCCSh;Y;La*^YBv=aFt`z>Z&sgBYTjckDJvs{6Z|1VTg?zeb))1==lZ z3^_sOtGPM>w!k}O22XXKx*^Zx81E5w?G zvQEL=WQqWpDyeyk*ks!4+=ZI)-trJjpUE!0&SYtS_g`rx-(&6-U59&Q*)JKi*<2MZpWh}TtDkt;3fx2R z`WjgP639J4Lq>AQRR`S$xdFAvm7sUZ6Ub6 zAANOZNHz!A^Raf9HYCS`JaL;34a0mNjQNq(Y!tMK%{D##f0gNAeN4ev09=T~ND6Ge zhE(5`=OET1rYr>WvxEe-4rOqXGjMG<#JJZdfsEl6L1pR11AmBAStqhly=Iu5Po~f_ z?q#;)d}!&?f}8uDg*&pFfwT5cloyQBEFd3tAsaa>DrSgWQ}R;Och0+=dh%jL?<#Ag zUOMm=mCp|d4B$2r7ohBJ-yr_D(pj-wBbz>b>^gR@Jk;cntIms_hZjuLJB+?DvPHt> z=$TmbR`G>#E63ghe>#WJi^9tg>jN`XrS=oatk$17(un zMsHyDE#!J^M*SuItjt1kq_(azXYt$aRlmR?bln|iAo;mAr%QB4a8|EDt8`ZJ0AWy< z)am5diS^oP)|qbV!Xs}nZf zm&R{fWteCtm-k!ZROLr%-OySQ5&j21qJKLHxxeD9Vgoq{#e*Iz8${mI$e`#Ut#!H+ z%{0#b9wYK_j%TGW2 z&bq$T;<-`>W`<=Bk@unVc8Tw71U637@Q3qpx!Vu#EL1@JxU@(NxC=fQKR~U+w(??# z@A3EpMFl7cFozmmsVB|1v%OCLhB}I*^#ui_z;kl&d>3*rQY(~>cyY_MTV9x_TQ86U zrsi+t5va`29A6e=G+Xs*8nz<_!}3aU|18)jJQA?>ORlbA-h&0t0B=S>182dazp=hs z&5YOHGI<+fYb85OW}j6+Q#~f~cT*+V$I=E)>${z+507)TOFd3 z9qr-k^St^N9mj0-v0}m$`OJ``ine0W@00YVd;aUR+M8xl5B^8^;>Y7*VE0sEj>Kd>dVXbxlxiLCE@G*7a3t7mg|TL@@`E*_C&-2UmdiHYXIe2| z*Uw^{lDq7Sw)Nzrl8~6e0}nvh>E;F~Xep|k=KoYEO>4vn|9+QLxw7I16phKAsD5~k zfp)V=h0B zs1vEtN=+_xf5#?7`(wP(0YfP0v`ur?yp8b$GBQNPl?{t(&I1EUZu?#jCjyt;3uOmN z;^|_Y_Edr9<izU4Uzl~C08q}xswx2yPPY&=V?2U;|VMhs8anYg3iV7ac;~D3|FQYwFg%}&O zWrpo2`ah9c^#i#9AW;q^?tS={2Q*+W)-JT3gWRsdAM3~k2nDX3{<)`Dy;vm#*&-^! z&b)hJL;PaH)wH&)$!(uQ!m3+ky~_;ta8NEgr)BQpq%b+xjF$Hb7sZocoWBj`7Ok7d z__Z_pO_$FA7RwnkcRWA68CdbHC@HpSk47nC(`5hEu7lNG`&K3xi@pKCb0C1Ek?{ES zSM1)p*tsjtICm=c^cC*hN9wJ55a@~|V|VLbuY_f{$JM+e=c}a~`1u0mDv58OEIiOK0Tm2`9jLjRwI6SO8IK$n4!@@}Q!_i8@Hy zAMW^Qpg`X2c~SP~`?#QWD5NZ5QysXBebM(>xpx-29k7p{p>4wgvg14RqDYayx2s*g z`HoK*P!0a4Gzk|q zJsX~Wd08TSen|!8 zKY4}v8{at8-(3gQ19XGR!cpZhgbh)$`*&4}CzfJ*V@R1D8*#ddsn+7uGhFJdK{j6{ zFThohDU{c*0NDckr7Qi|;L#MR6XQyObGD0IH+#O;xhd-^XB99E@f60S+E{+`S4VE9 z#O|1RXiU+qlI{mhPk*0is`S(?fv?m9a#w`JnIg8DgbZb0tF0cHZ(`Ody4PFW=Mcz? z`&YCLj^#yBC;b&9<#~|Z{+p^uyqL7mYgI|G;Bu++)SlO0>1cUsih1Z4)t=Ahmw5NktHK z2SpHSL+zz7m{mMH!u6#W52LkC7QjU}wN(F5;&#Jan@37Qpq2X$?f3W=_h;J`RNC>CV5uu;Nm^&#;oGDXd z;PN>dl8^e!A}|!Lpp5tHUjNu*ZDbI$@JmCIj2rFT8#nhKDnkvu8`^v-Y!6BDeWUsU z%~j~?A1KmSFToU#y}H+q3o19l%l7Bl>-Aean%^+HxZ~%aBeh7=Egt)kAQA~Y^F&KG z8LDE8YiAMO#}M3&!t5HIMrDOUY4t6;F6{4`v_nT3YaNZsT>8EHmvKgtjB!8-ejhbDS>Rjc{?T@w)ObIpX!!a1*vhLQaN0%xeut@!EEz`GEg^cX z^L78pI)NNluhu=FJkfte>Qe3lu+rn=h9*YQRUR#Ra)Na0z^VGulrqy9j4k%VC2T+} zBLJ6Cum9Z$*}_`kbbr*z(Wz-WFN71Os85Or4b}-Ki*3d6Y`J5nw&bx-3GiWI1VvH{ zU&GI8fsyMXc}PQMS|Vwzz>L9nnkwz=NS9!ubn0^fq#eoXS9GGLoz+r>wTRFK-@|c} z)rgnvj#(4NH%`z8!z87Vc~oQoJO|^=+uR4H(=MB|;Mr2_|2-7Ikk4Ch+wngwZl610 zO?^pRlVe+%Qi4+R$y8awN?oiqPy35auLQRRk)NisS6Sn+l0Q1y6C?rbAYJoPHsF`> zR!Ha*zNpPoR#q}<+wLYDh#*?jYToE&yFB{RCb+g){5}dRN{B%?iI#P2 zv%D%-9Urk^-_|aS7!J^9gp(EL5trKUcy)(HH@{E|C&{EL#vjB(cYcp|&XD`z`(t(H zT~HFlD-m@0%0CW|m&k7NY70>fYwksnY4_Jzf9JM*`=z?@&5`gggXunZ(FVoicK9oU zdMb98>{;u1-NR!aayU+0%Hd~HGr6Nr$ZW=5+uyqgdW25mmr z;RV-hJN`)JxDqlvIuF%6;PKG>chW&k*|5 zTW?2T_-50EFth=$mxAcS2E;`i{G@==+!-QQ(#?1y^^OGb@a@{h)l%Ga>Dy`>731+C zhQfxejC*!rc|7|_Wr$iM0$$4dMwus^>V{zL5h z;!&)bT?g0h^l4=+2uwy)+fQ7;MM0KMS_SPIro4Ik={Vd(y{R@<{|%iQHTd%!Gzl6= z&{l@VDN>h6j_$bM-ZeB_QE>|^L;AoH7MTxI%p>H3A{YE_=`-Z3yrYpBZd^kywNFmm z1i-^z-^*;;J}^W#3=-FZH;u+R8&MHNudC(K()@r4o@{Z{O&({rbN=jod39#8BwZ^#CB${dTiL4r0#k4XK#fArC*fyXUwx?t`5oi$Q&sgh z>_w#llEHg|dQ6qHf)4qRydFbeS2mr`Wa$G^E(tl+WjJ0?yP^P650^K6zM=;;M&ip%xWtK~u$SWZrgbVGQ0C%xLx3 zax8dq%=PGH7W&EMd;@$`Cy}QS3K#Fi&-A7t z7LXpB`br-qRHx+xEG-)ax-Lj(bZ+Ch71iiUBtG zmu7T6jC_9J*IfT+n3Rs1A;V;WHA`)hFMpFoOhUQ`hPPV|?5-v$n`Wkmj9+Y-s^0%~ zxXZv!32kCE+rD*(xEFC+ph(?S37oLclN{T%F;PUTKCt@ATq=`!z8>>wUEA&&-S4c7 zM+G8|ex@^F)8zlUAJ<_keC~{@Cp$dx1zfvaq&av*e*C+w8M}uqgy?>;#pjo#Q~Jyf zkXn`fJ|!Zf={?Caz0de@XSnsD6U?Pe>U+kXFHLCHi3e|8ChgaBWKl%d8>_)8A7|LP zjL5AibI`NE0)qteMm$@OzvPg32JrMy#}v+VzT$3XcbI`{O%K#8%tox&!=^61eyNMc zx{$royP#bs-)lJb{5t1CZ4G&IDV10b?4JR- z8c)`3oT<(^ThU|xnNe*d&@S34KI*eqe5@)@Re*?;tQC7*Il@^SteP(xbEopX$oV7#m6N=10B27KYxKh zhw54&Ku$HY6T6IXPWA6QDbKb)J|3mySz!gp32^fdTX5RispnYBucqQ{+s_@fd7M*4 z4NczN!eZYBZ@<wn5{N*+qr#G?ykxUqLNoAm~{SB=_t zdoD+r&A(PM=bL=eV`tK12i1H5?=cPjjLj@S!OmXCwzyAj^~-?OwNdh$(XBoMlgXvp zCp%ozVAo{!igTr}P$2zE2@S(0)=?~W0W!9pc+2&7e;T4JZ&6*;2KY~aJLN$W{sl2k zyM8;C z2Gi}z-ZN#!FGl|v7)2#u&VKfLmpE===%N6UoB;!o8!l~9PsCU*nCWtqdBB#FwOso- zjd@W3y<>{*LPfvhQrPC!cMBrAq@Z_*aP2jqvIJkn(UKIALgw3UA&EO{@Zepig6fJ( zd;fdu{rPA73(Xa0`mP>06Ksad3TVzpEHv|QXY+{VGGEJn(#2yFac{yC{;3Y>2y5r78*4#gK=ks~ zPJJX1sg$nl`H}hM#x%p^H2>Zc`pJ9BcZDtY@SC?u2n}n+*(*xsqIOep9|K#oF+-?} z{P(*a1vg~vS?^-g%NIWG_s?d|-l|@6hWt+X{M8bf_WB&_sD&+34iS<j;T=U`{*5(=H8p}Cd71_w~- zmt2*afbM;zK2;GdgWX~bd)_#QZzUe`kQ_1_HEM3int?WbGa%zC!RoOMo?Ubx$QRIx zL-%W#^s6}aKqxE4a=A417C4Df4QZ@c;?467p!>(J zqy2_9U$rpKY$7F!HR2Ed{x#YrcBLT%T{yFZs$F7r{|Khz_MxQ*2&oIS&WVcj3kiI1 zmN@x~X93{Jzngd|f7~*&qLyx6=0&UW`$y)u8X{KzO{m}w^y&wwxA*DO%6=_N9?OfJD%zX#_y2t zm6t`GwNnPi5kbFK2=wr(eC0dYmWO}K{tPIDX3#rD8XZf}U0=)st$~Y33mhlr@7$Zx zZvVF`;%Ot~^{inR;9wS?yNP=fGln>D#G>FKa4rJaPqumoAPsN*MYOGrkq`yhA$C?= zvL<{S1O$8)Th=S77vF`LGa+LJ*j!#@elz|({q!)}f_QB9V|8o<@wBk&*}PU*tf{Z$ z^+Vs1gv8T#7ev?8slaLCjwkvS#i9AsP6tGo_IyDodw6JBXsw;a=WBl>QoYAklLZ^1 zz-ywyqNMVe#7|toAjSm?^Z~Di7*qei|1;RqAY-bSr#8P)ZTtWDA$Wau9&QwZ~rE`R6Q_1I)`}!ucl8{ABU3 zI8DSAm+VLBw0Uqld_(<*8}^l&yOT}$^D5ZDnZM4AO&t^9o?uSEFGbGw`>Ou)3NG*; z*WmiACJ<6A$OUAVOl@Bl&<_Vo@wr7<<;{C*zJYAUk|9d50DM3{abc;ByVPe!SDXbr zwb7}XcmmkC6Vn;8idGR)D8XhRwFcdx6hl1Ui5GQEihYl9Ci5N^3ET*|_Z#D%<0fom z*nh^A7GmekV+D)1V*?kgMw1nO6G3n;n2Jox|N@)OyJ^2D=>iXs_lFE^z$nU#W>p=ig ztk>mv)0J(c4-)kUVi|lyu9#LnYnqMa8LyBXM<88cp*A;2tE?n;h-*G_*sFN7klOCp zUlv!7oh(WHV0XFLaJ;wn+PxEF8`~e;3pf*5(X^3<2(;iTa^7DOADEA5;iwgFS0IO- zVt2mz)bF*v+So}x#qqQ&x&8cgV8|_6$jxM`(6tWJY3op?bfJvuBa1v$U<~>nD>;@I z(iBXr0|Q)g^9f??+kd}g!T5R1QBVeO+3c;l`o^TWbXJ7xz1_5~khf48+_CM<0k?D7$zmlUqX@#V zO0_xtCfuc@E9KSTD@fF!dlZpUfR!S4&IHIF5i$X?gP}LsRYU%Ji=X)gvPJA%)Kcl` zd9mmoq6F{>;6(?}QIEYTy8MZ`{vuEIOe=GEVlE!}euO6u>OZbIEi&p+X z{|5|aUNN`h10}CThlVb9hiPOyikS((nmGpmoHYQT*;P`bWdL&w{mH5R81(y7sFT^)&EggdMMDk%pYoyfgMl&3V@Nd{NJt{a5YZgOtrt@`?7% z`x+d}wn4Gv#dvurYat&ykot$;r@R^LwT&{ZKaag)} zL`tc4vu`CV-k{F=NzC5}gJ9a{(|Dp*dSte?eb`aj-o-^7ohM zMa3*uwi|V9hh^VpG0qb5c7zdZrs+mQ5bDiG<2fOn1o2v1jRQkq0?M^Koa59y0UZrg zZ4Ort3k|b<`^KtX^lT$|n&H~xy-U##L=)+2ToWvXP7z=%f=-(Y>xkI*#QAh>CQI#k z4LTJ$G)}BKc!L9y51)0tm?0;m-H+d9+fn#Kfc&_}whpKNTKh%A8>PgydpN$FA5uF< zv)JS#%Uydl6NYhT#ZskKjfB$$tsi*$kA0$vzldJ2MLty1*~4<8MObW7I3R{WRgQm@JyCNX+Rb%k7`_N%o-$6{rfAi)SFMr5Wu=tmHnm` z-K*kf%NR-X94d&nT}5?}Amfw*)xE=aj^;O~Hyxt6*aQSg1nNU1c+P@>a2Sf79$WPj zoe`LGAxxB{$Qevs*T9LxcEGDZ!MO<2iHUm;(Tj*P8b6jaqo1TzXY14e_w1`~?dzw` zud<`qB#I{j$*pJnLOL4R06TN?>I5K*2<(-bglnRzB*h^a5c5k4z(0nF+vZk_4Dxdm z0N)PO3OSe2CM~VnF_h!A)vZl%d70?){M4gH8i7VXIK1BLZT$;1GNxF51W75lu*#0f zL00y>7=O31YV;SlhD$Nq!5xZtg9wh)>TjudL-)GDd80O--Vn-uz0mGsrsfS!HN|Lq z$;0c}$~}zj3zP~EtEkLP8-4l@pCU-b(5sli?_K&5ID_Si^;&>w^VQV$@F=s zq8jufy{xJ?k)(gU8$ON;^`;ZKpVYa zt;{uy36^H&d;Q$CFJ%2dO(9`CpZ6)9NA2}-1+QAnU|R8HNA0`xTFm=PeW!P41F3No zl;TOWRlwEE#{ zQozzF4t)8jBRLzP0;W_^U?8I)E-CbU+Or4fdc9_VnZ)j;h5)0KelOuOLzsY=lrYl4 zr{<`8SZ~x@=yo*|!=i)0g!%QTUXW*a4^2W9t#IKiki&;L9DMv!X~n|`Wkv~ zX%%15ug;)!0dLL5%luaclG!oqi#j(8RHHx!ideIkj5I0iyOM3NKO(^lLtHQO(6efM zsWA;)*BPg<2nEh^b{;G)7DWfKY`+1V*cjgQ6s9dJv{`y~N7b~Bd%7e+?Ersy*m!l| z8F?Y(Z-QjB<<9itvM4xPG3dHT`KB1TU_Wb1>9!+mtgCRV7J`yeCbg)oY+}edUTzkv`N6B;&gZ47RMJTEk*722?m+b$c`!H@s1S zF~EgpYbbtYZ0`0kp`|E~x6rGPW3NsX_a^+Q^iXbXx)#|mAT6T*DJzW1jyYENUsaF1 zYf9DXzS!FWSz^`1%y#5P>uUu?leucuy}UaB_Y&5GysSG4mBh7V=;`4yT|*ZKMTMih zWLNV7M3zjiqSXL5Iwqi~1J7u!$0 z3*gH^>s550c=DpnJ%$9yT$c(y4;cORXlD`d;W%xf{w+kF9OcRVzqNP)hp+$;TzcxU zG?$-b8HRY9KjsiY(yD5oOSKE$6$KaxKfnX{3K@!!&nJ(7r~!>6QmDm>onE5oIuW`vFa>Z=`!DmhpJ@7ffuCqTvovMI-U+ z0hVX|DLJ;xQF8Vdj*&7B>FjQ}YKuf2YZd|v72+YZAU4v9Q>X?K5P^ZrB=Ff$@mAdb ztd9;g(@@4U+i=nc#M5kcWm+Y1wUZMKW~(3Txx_Ws_F6By0^pQN{W{XS}INj{tx2PMnOagF4-IYYj>*k;OXyZ1lzu*_s zV`%-iMxoJEX@5PvRwILWz`o1(WF5Wwge4oJCEMID@QaE4hW&~$BqU%Ku!{^&KD zdHr<8J>9ED^Sq2Y{BWe_iG2Y%=BByveT24e8e1`3WZaW7scSY@9}Tzd&%i1cqI*3i zPc!TpPhj~!xKM|SYbMC6^<0Lna%(Zi&31>$4Vu9Yqm=?a`FXJt{%B+AK|ECfLA#4x z5=7A7MB7pxtb<*|Zl|~7Ku_l}d6N-3jM5D~U{i+=se9Oc8aRdU`7Ry`vSdyKN&ZK9 zc*q)e?i!yiwu&HC33?HsZ1e-7G%u>wR&7UAT8psDYcq8Xs+{#Wjh}*l|LEJ4xi_HJ z{iuI>KwhXJlCj!(6^8;EW63r_NxWFQOM)DJpmeURD%l13WjK_y0dkwNHa|ICaM5P> z5JBpbYp9S$jqZi}>fS8!E*GT`Y~r@}%5ixV3k|Lp9F^GWfEQxsqixmay{Sp-g;8Dh zo&|+JERO5UbC2GjEHXq+h0tkSy4{0OeWS+OOzuAEcEzrBf{`*lcT3)_*W?gS?Boj#Aw@^!)s4c$f4sp`SUFBb;mCCsSl(5 zuKC3wY~d?PvX`_&n4)=YXv|%#gqpCj`{N@c!-u`-{Hox)_){GzUA?}gOvvGoCQ6$y ziVZ&JFVG+Cyzd=)pZM>0;A1!4n0-k6$Sg0V@CjiHK-={mk*bxj`5_mc2h(sZBm@Ox ztZE0>@r?EB8ElKWHNkUQ2{Z13=?3j^OLzk|&Kax|TmroGz0_ zk78111#wQyZ~a!@_wTq@|NYKZq~wA9XDq4~e`>`y;@|H`x983=aIC8XGuRXm2*xx= zS!@J{>e2(LaLOfpCg|>gd?$x&N^g$;Z5b^zo1wZn=UOXz`i*+O-4L(QHd?XFE5 z>J~)2O$phd(HA}`SoOF%L8A-vs7g|7(Odn1`q)DI?gO@p-lGKNZB}t&+6tO(n0p&C z0NSNM8T|GL-8d%6Y0&P%ev>Jc15(X=L_E;14>}+5RT4E?xlO^8k_Dt!V=>VmAp7bE zt3u0ytz(bH5z8^F^@PCHPDX152dGL#IHjif()A|UlbL>#j{2V_C|yrB=4+dS?8Xi_ z9MCl^2obOcyVtUl zu{RrfuJh{c{@6cam~D2Wl^KgXGc-rcc3@DBkAZcATJX3@dAWYo{cs*u*dzwprC}$c zw^KOXXY{c+qVn>wLmG^a4|BdMhU{h>nw$UOcw^hnD*MBswACh-Mhsb!q@audPTOjv zU;H9*mG$TTuA3$!a-QGNqFB%P^FJ|*MNZF=)aJy=)bPPg*qUuMv;Pd!m zy*%x^VsI?KH@`9IAI~ehhEsck{Z^O9saH8sRiHcTB5t%v_EL-1ByVIevX|`fr`1*7 zG=>m(?@-2DY8Xe*kREMSt*q`|!ZV+lQ_7X#(zRC!c~qNG?{}tgcv%iW5uKjLza{J~5@_sns;A@-l$E3&F_?AjgZ%-$)t}W5` z^Wq72k!i)q=*J5g65jn7}yTgA?d-aXV9f`mzozCQYj8uG=eFjxn4WuJ-s zFgLtKiqYu3cX$1atFW`~K&^lANKdtFyxuVAIucZ#cek%&XN{so3$5km@voOO4Bvi83 z@s`;jG^aOxpOynz?@=}|t?QyLI73m&x#G)7Wny!j=#hAE7;$K61uU3TJguj;G*e`ez^^@(j> zSr-VC6xXd?T!FI&ya0%eLsCDCR>NgOt>dQ3uWy)!t{L{Iy!yxjXPB*sTGScJ z=Z?=d#JH{iR~3fn5Xd(7kZI`S0>!m$sG0rl$WrkkGCQw?UEQ@{FJ+9AKc9R#MATgM z3Zz|hfd<)WPV;_}SxD}Pjg-eH^%FVnbXoi^s=oJ7&%0X0-m0;2SM>!JO2H|JRxtE2 zL-|j5ZZ+}Ka6j3mZXJA_I%7I{fRUsyQT*^}dh`t4-HhYrHWO4JG!3Z+bU*{JtrTH9 z1!2PHWxX|xmOXak6YgIgl3=pS1Q||e_JB4WgbXGd^CI#-(ty9noPU-=Ia%vHqt|u^A9mjT&d*#aFE@)5b9AsSDRUS3x4N$ zyBuODyUHF{j#a^DhPDoQ&fW6vv$1%YKTAJ(QPW92h~Uga&K*(iY)}t~fEwVndZlL( zuHb8Lw@P@sB74Eyl>1o!9}e(} z#~nlK`9G38{_j|G&-S6PpAo>(!w}dbjv(Mh?S!9?#N&UopUCUv5GgYt+RsC3FqSJ= zR$Iluo#GET@+dJl7|rb-Z1U2PNn@ftl^-B~18gJJf*AkdoqB*F3n+;ktjNBhl%gtc zzA&A%`g;iE^zbr-NtM{gmIdPYm>f|wWE)f?BO5xQ5;1RIpVDS=Nn%p7N} znJXo+k2?p@!HE_4G?fMTwNHu*Bu>o9@VB}Cq3rM+anTu?hKVpOa326 z-x=5R)&AZ4Zmm_SRH;xvNEHNSR%9q3`PTs=ATIVul}!w(>=BZ?RzO5Z0RbTbRhAG! zgb*SGlFF1NG9w8PnX*C_WRTJ4_`Knb@*%(9IXUOLzSno?63ikXM}~QQ-s7RcDWSet z<)OjBxH(=bbJwXaP-h&~pZEU#8PE-EB*Ix@(GEPemMx^a_`261*flI)B zo+C%;+#U9y(AdBPPHtQEPI^P^54?=ME&;EZ?#R&R|UV$VZ`^hykoa}&Qhb;Vi1u= ze5tgLNET;85q^9SmMXf{RpToaYpAq(S~VhpNAdr6D37Fh^W!>7yOFggo}X^d!K?Xk zJn|)|UJvD$YtKXKh~Neppf_^+icB7yZhkYC^3WOa6j&ru0JEf>JxgSbNDQ&*h;~qo zelx&FEYD_VzkgAmh;@4$aM68YvGu{6diaueP%b*4uJOVUy>p1#0!WkpH>RKO{zm(j ziY0GLir$(6o(3q;9eK#&WROHyR|zo9u)8_gZdm=X?*OCw4Pv=uB)YCo`^qRMfaT+B zo$W(k0~kp>(d=9dI_#YxlQv?o9S0NDihYZoJ0#S%PKHU@-=&$2X3z9{`s=2 zZG}qT*GIicaTnpUM(<#3shIDG@@s^508gg>CXu?Z9ZGm8bl{(=GQ1y?GFV-``wy>< z^8p}r(JgV+n9Yy)cLcu9)4jcOu#6Qn3!W=6)}BSVngLNLyr#sBrd_0L^;F#iXFB)M zO|GW)##yJC+;Q{8|C5PDVHwI3W?aSYgrcdK1FYZ6Gn@7@2YE7Y1RK1ri+Q!m;T9Rn z1~@#_fgyRvzLX>% zN6sH`FhEjUY46GMMD&pF0ZJC_mvF5E<3pKA806QMn4|<(a59p-L~%UUg%+OpkL}XK z?@e>3*W!7X>Tn>W9n?i3M4PjK0(aNMB&o3|vufec(i&(Cz$b<-y0ZV`i9{ar&<7isjx%&Uo1Bi1FO`Dj;`5*_5nr=k7o&e>r#6GMqK$-pZ?^lfhHk)2F zsG1&Fw?e!>wx^m^(ZiBW&Y`9vvcRI)D&rWmaW&k6((D6*Jht`<7>$aNm!IvtMjFyN+9tS%5E|a0qu7i z764)};~DA{g7)(zV4rtAF@B zOtv1P&&}bSc#NtI(bNayw&U{Jz#FMQ|JnPiGJpVrM!hnw)wDcm#lGks&CxD6uFAT~ zF?aYW0(zWML^M}sMM~q>&mDiGJoG#R?32}*+nPh!7FOr)Ku+64q1ejf-;}{d7=I2oLEh|)L({DJ-T5ee;hAT1~ ztn5@2H|^}ak(`qCiGYh_-z!1s0!_^VKd!Oym3p#BYSIetdn$4LT^ zn8Au{=MbR#Srna)M2NK>yu_gEH_9N6z=5rPx&b6Trfw+NBfer=(wyI;fQdcCYo%Al zGe0ey?5&C}%Lo+>-I4(}8W{56aIN!lm#~BwrrpT?Y#Qfq7#p`BUk4rWku$2HvGcrN zo^~uCzmbG>Dw3A`?&+rb)Mc_|Gyl$uj7OYpil50CXmH7=KnN+_`%2I}oO z2tL(hgJ!Kf(QuZpt5-e^#&np;fx~~+p(6N!?|+j2iij%wP)}_*?nX_B^1;Q}$gKKk zFP6P4d-PbMUWg^E8#qsK;-Km!z}DG!oOMxTg9~i)3dIxzAq%{=6l@SzQrGK}0#Es& zEUtd6%YlO@7Zi5P=(tDdMnE*4)NF1H7*3QoA&Sx)>+1PL)f1M&gmM8BtcP-5-` z+)Yo^`-PYPhLf3J_HG&MAXcz`#{+(=p9hM5MpEEOBQc|wEyB95J`X7$gUvadlR)D@ ziT_RFA938h8__;9TxOGL%HGGo&+Px?j$`?5d@n55j1f9p&o*POZ0lU?f}d=C*hPlL zAR0!lNHXVH@xck%?lM2P;K|Jww~la93zo2RwT__R0U@kNUWO0Z(`6V8)8^{NQ0DZU z5KOU#VtpHjeWa_w91%SOyg;Il4f}_7`*)*?CUq6q#q^=NfzuhM=7TKOuZe)>Z?D8K ztj+{;@3NGhnZJUk>(awgA)Ua*YilQKUxkmSDGTr+cO?B`RsA%U-*vp$D>WM0yq9yT zZlmlg+^^{hA74{?GOeL7=wZP@FG!-~iKkCa4XjK}?4D(RCsvsFfCGuKjBWyBmC5I0 z4qIe{s{1RExBNF}feXgFBG^U+aJh0^}GXHKiFR650R2q!Cz0Dr z0tn4WEmvmsY`u(54N!ejt?pp<_`NW4#F8G)q-YndfJ$=v1X8x%dZek9B0HVNNM>)c zw7~U6hJSyqBV1N94duDn0TV&KOCU%JJyNytp=*Bl*Aobro8ju`$Bg=yiL?2UQVbQ@ z4syUpBqnJJ>nQTZbr1qL$5* zd*+tfDd!Mqoed3_u;nWsQX8Wxkj+t2Aalwi$f0H{u!0iWf}#rdwrua{wl`4{y~}Is6Hf{T89K9Hue+2m*ano9Jg0K!zvxkc8(*t z@c9_S6P`1Do0|GBZmFVg4clM6ImK6A^I2y++;Jz(#?{fR5tM8hxlXAQE}u6XBuBoA zR#cQwOzJk{mHPZ|7$ph$+W$ZE+6V))i?o1MG?##V}Pe@yAv+^ock-bklI1}{lIr_%$xf{DfMk-G zcnxXGoQ4f5wdR+mehwtI;nZ9285=!I_Gm6{(AM-)#IQO8GY`## z?L)lxr2aG!NK30&qaYZ~?2ddIWn9ie$q0}kuLm*-G>iWA^kw+#DJ>%9p zTkWGorp2k0Tf8}+xu&>-8;ljyUQ#ZjI5K!-Nn!rNYUq{VT%!GtECax?!N&P5d*%a^ zg~lduzD0J-%}Ja9Nv$zZM-~M0Subhw>CELK_qhGobfw&g$ke3Rh&|#7DXj+_{O<_t z{mkx>F80v$1AGP-5pKs4Lj{{H`h()ikQ`8q^u?3!$WPNqAMBH=;95Hw%)6AydHBaI zZL!<_cLXvpv%>YMhoAyXhfAynvyve95aI-9!IZKNFnuTA7tlHjigAN1%SgJ- z5Zz`FC?GCQIZPkBx{H|?ryZ003humq$=gprGS?8=JcWWrs0Cc6EN2tG_;G}Zvy`G0 z02*hSS?pa*kBqh2IR&cWE;h zM0zX3>XsAE)e?$g3+nHN3}yY*DQW1MuTLRg&R>>o_}Aax>TjUT*Ci#ttoDjpZYa6` zOJUy!hoe};V}pS?3Mr}DqXE-(A5+n=C(hR&vvy=h)88Gta85(75p6u8wDyx)n-r|; z22Q>unoFeCEcHvQz)}A8(skZK2mK$I`W$8ix_|vzx#ZyBmkPSu7cu5530#KG>r$u! zPLOG0KegX8n;uV4tjjJ$ps>>keO~)N>b+%V$oGm<;0xY&+%En@`Cw3`ZvzegIEA=R z*3S-7a%F?CW8Ijes&D3@^TW?A2Xb8ly`vKvIBc6aVm+Xw6fk=}XMnA9ey^LdFMWML z);)FKKfvF=83{k*b~M*b_e)q=VKgAn5tNKUK`^jBs5)8fAoLmo@~UTuD0<|`_iMXZ zO)O_TtFBJL8J%@9ScZucqKF!1%43_Mw5>zsA0SwBlLdZ5&7PqT{Wj(MDL}YV_qs1I zVlivjdd_CL*%~l?>*-lq&2#%Ctqbn^y!9?0DV@0Q*E_bwq`6{x6kG)^E{5S%RMOOx zbPmd$f?Urhz8`rrz~}k6oxGGI2x~94M)=-Xl?l^%)`M>LwC-yk&80Byr zhWBL7yE|d}HG*8~dilhbOU&%x?>ov<>f5sym{TEEFBVjPxWG)=oE4r3Sye(NtyGpX zHsN447S(JYG7m2`bU)+Vj8GmS8f9NS(r8aPU-ztSOLsH&Y~c^=0K2x-^-jKH{{HEq z8|n>a9S7=1=#iW{-Jd6qQAq`haS%iC#>VT|W%mNTMbc46oexDe-AQ{NnYtzewm^qJ zF|*>p&x#O-&i(s2+E z`nCMBMUm1tp|D>m7{1oFVWaTJMe}g%V|utVf=pzobTi!+`?Q>@Pm_fwn6xkv+^B^s zE`Tp9Qrud}q?C*joA|b{)J8X*$r~iBnaRF?s zw#UVZ;`kR4gpNhDz}r!T7_vIQw%+)>`&JzRbF`dyjjqZ{!~xftz)UMjsY%(f#t@}wxjhX8ig5O${9F$9 z!p!1Tl$@lbft8wXJikS~DOTl&>V4RP$r^2xf5M((n)gg3K#p2{b|c6{#7USAus{BB z_OtAlFaMgy{>dOg@^)b_MyiP1MSoSp9g=_UPKvpD=&UAv%>H&JNrGouJ`=5qelK4L z@#SZqM~!Fz08teeI9)^B+RO*;M%RuztVweqL3WG!a{+Z1n}E_^V?59$E5iCWOS;S| zk=^U8Q+%B>3;4_E&O&8yA-MJ3Frr9437KG0ycwLkGJHIhRo&OpueL1ph(s*P(*Gt0 zvEQWQ*37MeKb$ zeg}!N7MMgOidat64f(ImbCY@yu|7*hq)f*qML-Uf4VF+&Q|9g5IjTQJ#A_8jpCUzi z@-6VF;no81{JZ8NGv3RMIkQO=21MF6NHgP=tIGuSA*HE*=9cv z{FziTEvA%5$#Bbp>EQp*3|KS&I2cHkVEBH0XkE8&b;4ZRT1xDwewm)uIhS*N?b49* zf+fWQ2W)Xq`Ye&$zbuoKt3H=~Jf&MDOSWn#=5;c=u8(e2PE_)paIerB@nD6 z#h6WoFL?wED;sDR;O~6gpKXYNtCt^oZj=qY-4vfQO$^%LaeS&J-m33e{V-$*FE?o< zS!@NcKzTAC&Jv!U%Yy&Ba0bsjkh6V`Xp)9#rM&8fB`_<(q-@mM2Wh+ays zmYIRTKPjkwc&X2mur=8c-K)onHPH%pWb9*h>gAY7=FoO<0iDX}QBI@(^Y&g$H{t#cB7V_tl2Dm4d)1?C0Z=hKK?)oTUjjl4 z)@q}1k0RouU~O#ExVf{`6ntDunLtB5ULf5TLMw+0$ey zC{_2I{(y4+M4yJZOd<)C^&4w6h|FW#CNS6!HCUzSQ=CRnF`ta7T(7r~Mnywb>cTe8 z8^}mPUYF@Od%{yWqQs!$DsKQ!2pCE!u^scNDnIfTy7#ptish7R$@&s>E$Cbv37!3( zp@w2}E&{(>@MzsEG_0XUHdO7@xv*@Mq&Rg+F2yc<&I;-s94Ra{>@`=fE8i|euzT8C zM=UaRc%tSnkGrg=3LDcA_*{UVf;ZuF)PuRelMWy=}_(>uIu)Kh##r8d3{G z5amETuX0U0hIoyj6)1gGW!DH1+Gz61`CQH7WVM5%d(l z+_0qf71Dd!_~rAC#gZDb$T6W%;7kg=27-#u&krg}>cjaJFtl`Itlg$&HP0Jaa%9*e zQt-s}_c!kKD5nzZe9V5X%=%Q`75-w@>QWm_8~z6I!A^SdF_(L1 z9N0KXVOs~;%;nNT4&;!|LR6ycddoN}WQkUQ)U(1T`Jn|{l=RJDkgmWaH47;ve}gT*AzV-YL_4v&eRWs zDRk%LwwGL;xhR9oBmW0+8;?57M5@muQ4Saz^&el0Pbmocf~^j*{3P`Bb{CN`_97VZ z^pqXL9PyhuFHVzRVdS!UTB8VydFKlJqA5kKzK#Nsd{7RX-6l#*GP14Qfd-SeSJanL zk^b3zYLVi0wKrg@=nxp4u)z5vXT=kXs4HKHwCj=nEv`-a?TUHRm zLWUEhd-YC6ztFm_W|nBdvP1|0UnBX?&qi|WV+r$VQpe)<ohVhTlTfmwq24se{v>u3`-)3dIxTU{`o`};rx5kW?iRv0=_f0r!$X(Tx!<#IPK5(C~lqL>{^W$xrE_*jVG1^Lw=N>4kKo ztv2Aps7{1V9&4q9`n>oEjNf5bB}ZsRiG$K?P1*&Tdyy^11iA2=D# zG%Q}_$36F?227yJb!ApRqWw|)9yYw_hIX`1_N3P?xp zDkKcDsJwTj%x+a8J!G*|4vOmE&?mbkyJIV+G~ z_Ks@smTv({h>QNXBRdttt((la_#q&X?hl@_6sUH}9*v=jjFp0^gbYDxE^rpNpp(sy zbhIdT`R>fR_d2(Ftf3JY!-VweBtID|6sf>PGDbaVDq~R&%L|LhS>o4<7JG|Wj8=F{ zJfuVBlonN7q?p!h0lQtmK)akA)Z8kEb~nJLYaS+cGB#=Y%`Gj?y5^g!?4kT+z=Hy@ zrEN_p=zi~Y-i*|QE2@q_V~UW)U?9B-ED2Qlq4Nf$r2PN78L+wLiZj{tZG(F3fmsCO z=QJe-O%psO${S(dO6|5qXAHL{ORqD{cEJWr9mB8kIMKupAf&!-nG-J%1H#b|Gzm~pl# zB6>7Wi#1(4G3DQ|8~ysg_N(Rdr>>NoF2q}J6sKL*VAtLaAelyN4pm0}{-BMRz78^6 z_hGpVy~A7g7(Tq^Ms$XP3=oRb#ax=sUsiRf=W_DoT6PO^zTr$4s1YN|MezD@igcO{ zb1CeWy#HBT8RcxV^}cTf5Y`{f?Q7-VlxOzItj3%T2PV%yEawnX_Vx_~4hdjc4o7is zApmsG$qNyxDG${alq=Sb#4~zq)Z1>CY0}!u_+?2}E{UHgX+^*}KVSJZ84ldZ1TbUK z4gUDSU5l3#af1H^P-mlzEBdR4KM`DlNBhtWfs6954d4_6PW+A*+L=eovTf{#H@-HV zq~RCY%M-^lR`#uMzyLCt2Hy7r4=`0`vdM-STOgFtYFTc>Bh*I+B*BlyU|y0i9V<3q zj2%k5PJVNF;zGPng4YC_=i*2o2URyjwb!y=pY&#Gdorm2vp8G0K3lZH68nj9^l1lMWl$z;vU1~B>bLd$4~>Mi?sh_vs<9hkKD;%2o zs_pF(*vYzh#H=q<{E(xyV3}xx_e$VlKRsbaJ%%>x1b_y*;XPwM`_BMDy|Tbw_STpBA{31Ah&`$2#^LifDcadJ|?pWBR5f zaM1mO>q%UE4=_X=;iy?Mi?XUoAK#=0(5+0$k9bzw+K-8^`CA)qY%hPOw?x)Q#ZsWS!!3C>(L&) zKcPIowJ15gWrb{+wVSdg#FmFcIJYW_r?ZNb``=IML&LwN|Jv18xcAeW-8{m%tB%X1 z3r_HHiLvobn$Y0>eiXf%O4~W~zC3IhEOO&kaBc%2AskeYJKX;$L!FZG9o!{v>r+XK z>?dF@f>a-7`M-JK4e%+9HOr^KO92#_;A1v1hLt9KClM`ub=RQefwlL`H|dji%YY!9 z&Mo+ItuWezoqy_wn&c*C&%7J z_1e}npRu&xk^)S`STpVwP!no9d-)iXcy{*5o%iK&)8-HPC$>gr9kM<|*;9YI1tN7{ z-~*!4)F7tO$$@{bA@^UAp|6h8Xi59Mif%ecSMQ`QhWX-<88F2FMRvA#quzA~Tki@! zZVp98Cdtk_{KoIpFe&BbZ zw^LS|S(hTTk-Nhebb!+nIW>TH*F<7A3he-vY7#r;!LoMx7bL2XawdX`8FM(cdf(+} zHn;#9azQ{tm9N}MjT_1q@n!FQwwCx#LTqhf!lr`;*025b8}~V>I)W;WF}B3vl)Jv4 zw)AC}yK|0pCXqh|IOZotF(b%+X%RIM4uh8THjf#09412o&uYs+O!TYH%&_3>+WM>~ z?hW)$S!fN+VW1_yL_0j)AKH+YI5z=kPaef|kq2=j)wBSEs;gKDB`!ND56H)E`GPOQ zOSwVX_!8^~HwX6a=dd#vk%z*&X7|N5QNy-~{tdjS=bYPfAgrs^Vs}#BmkZz0x3%Pd zNeW`cki%9RW%Z0E6d+nCA|zCs>2{4*HVRvc^1-B3ZPA%Fx-cBN?647d1;Ea!UQFIM zsnhS|lx`nK?`Pfr@YuUfkJXfI4041K(6f`$+hK3v)b9S(;lRHyt|mga~e>-b@px)(KYW^ zQ6d|RvHbofHB@PUw8H}(ggf^Y13nLv{!UGIG4s(mfS1PC8V-t$AMr2RGdmUR0(>1M zcZq~3=$GW#D478`^e!Xw8uZZiPXI9ck!Bb{vgry43|49ffWYxYlkB6v1JfgD3GhuX zA=)|av+Et^ERxkME^tknDa&27@-OVgSjP1#~6F(sAT z5y+8Qe>@Pg2z@L+n;kVp3TLP;51SW#Mkp5KL-ZaYirxdWo4LG{c_M>r)v)BD)TyJ= z0m5P^iYx58DG_68;LO`Lhhd3#%9!VLa(x|1*+ns60q_9;=)rn@T!!{!@~4TidTg-b zW&3}sY`V^w#im-r;qeT@7Q`KkEP#LZtH*gEz1J4cH_#lrhPKS5L@H7;nduv-LVV$uAyKf|h;`y(rsmHG`~|0pdTr(R-C z+^2)LM#F!g=_TfMZgf>CKUPGhvVqO{jg^_*bB@|&=JgTQ@j_dBqa*PD!eb8zj*ssU zf6y;-mvQq`LmS8{HbsI_zS_0xmW6v*SkuUG#MqgB-yy9f=$A{Lwl)gSET5&zza`~% z*#2d;NOsQOcW_ZT>^fC;Rn7z5c5;4a@>Ch)YE*n0P$rP=os+7p9s0-=O#JKRWl7Gn zfuq%Td-JTkDYw7WsDG2vR~)6L#aNluM7Z)lQ#)1D$U8y|+1rC~wY*2KtxSt>d8->p z97|HbY{1_Y+X{_lc`2Cqis??K8)0cGa>30htdI@vF%SUL2FVG8(0RlsX7clOtkjZl z4kxU@Pg22>TMe&%uv@i`@%8Vu&%RS6&Z0(2Qve(70x@OJ$%%*l?wLcU2Fi?X~ zdx0wt+O?}9yFQ#$2Z~y*DVckq&q|hP^nPte#ZP*|FDnrkN#clrn9H_EVhqagLIjc6 z)hmr1`Cp%)ek)fx!9*4t{QFfKHL`wcl^|3w3tmj=72HWVr@bU&&($SASif2i*mFpL zt#>x~T)U#UEZ_f*Lpve~>q;)HC)OiEkn@pjNzXjyyNLK>+iVjXaS&0L!XRgxeHyNr zX-2dZ*CpcpCR0~gA|&y_oK6GpF&?Qu7pPzx zV-Eb9n)vTm7IyrA+iQZ=-#zh~jyiEPqTRY-r zzcQZ!fFP_B!`|lp@eF}dw9fl5uKGq6xzo^5>)VuMV`5Dg;~{vLXB#!oWY3#SH%R^w zyH)8`2*iOdQ$kmB3}z6zooNk3n#L5wZ<0T|HI(|3H4~+JF6nJyvs#E5_8b9nIEnex z_CML@Xs`23SuIJCPciHMs&aMhT-iTl<$6uU{#M%B@~+DzFg%brsBdbz~J6IbPn9>9Fh<;1%9!Fv&w zv%b^x;v=P<%vs+d+FbD>Gq9s`Bjpu*g z@&qtOWcU)xaK<-1JnTT@v6bp{O`I|SXQ_7bT@xwPeO`+HdmMc5i?DoQLx5-alHE8Q zBv3_92?xm^WoV9T#X#)*@_=^<<}|LLk}|Fw|NXGFY|@RGAA@?DUF#Or8y=tTJ2Gce zdoo4`f$e%a@p3K?sN_l--ty2Z?yWY1{sq|X(z_$SR1Q8KYn1fY`+-gdFxH-T5ESDt zOI;y`?XlLF?{>TaLJY3wM_1D%Lq$_7nl#VI{uFdg znDyTLLW6_kD9ci_Wh-Or0(FCeDQHo&f~|N(9+qE7wQ6RGNu+EDr^Q&-Q9ovrZ&)le z#;Bm^Vn8WR>9*Z=_?c2{tKO7rKhg%s765Roc}&=}oF*T*z*KjxXrp)oZ(*_D5K^dE z=T>Ziu*WcSo3`J=lid~revJt`D1DJxQxt>B?OOpAa3#8j`MnmRsIxJ(Dq=0^;Gaon zOWrS>^YJ}GY4^yv94Zha1XI?aOY&M?!M<_}Q{B~B)KAbRAoT#m;d2ml-|?W9XDZGs z{&LV<3$*1?{y@3EP+%_?E_U6Fv|XA4o1QP3Y7wh^PD-IC5>_0k=m2U^qMSaMIt(DafJi*mM_oxE%Q^$&j4J^3*leJi)db~xot21WX^wf;=&lkn`&y9!D>@Sr#^!?|Q%bx#+1At~H zN;43epBk}--kW++jN6Fsn-3N{DWVzrbC%#J0>wXd^+jCx0wWyNN=|AbmRbfwejwczt0OoTX z!=hvEg*EHVCq$PTe|n{;s3S|p7r%2HX=l&PdJ>fOiEY+%Yvqz7_X+WJr|z^pwCT9? z+7kM7>|DB$g#>$vqWIh1y%jTB4CN4_*&6ouKs3A6u;ERAxX z7DUC)ZO+y$y_5!HjfLZiIyW=sk8`2pNWH=%05p;HfI-vWlXqSxCZAc!EW3jx`W@&$ zp3wt`sX8sVKqQU^=__p6;h*vcL%_L*Ib$PEu#qaY7Mpdl7QREY5zDnwN5tSoZjw{3 zf8g4i*LwTFdK=xWao=-W0tT0xwqWwOx}5Y{c>RT~$Cxo%JZxSH9EJ)zN)C%h@(5f< zr*&9&_(~(Fj+0SI|9<7{l}0=5U8i88ogfX%s#mqc2T#n zD)6FdL0?aRwcm*}aa|`U$CTUAm=p;*Qqo{8jRqA%$EItLQEu-1GWmqt6`EQ8N|oQk z8PFMUv zVcmrlT(`KImzaMV3Tehv0n+{lFAjewbkZP+v#9(@1V;BTVE*s)!@pm(LtgM|WW}G` z5U<}%ycE8;>kt|b;Hov4#83zOnCzZY;+4Kluy%UgK6TIUW(d-JQx=-$c^O%>g}0IK zr-kqo)ZzMz2#Yh7I2_=KwX*<5BKuRhPxaFV5`qe*WVlTfxw}Arh_I+GKRA^FQfWMZ za@^Rah>|cspaQJ8x&0iBzc`e9Zld+~=-gdnfWrRDL*`hyS?r5-yikclEBX%>4sP?-m6E~f;`dC9#9_$d*9^mR_A|yB1;&RTZzQQg%U~! zlpLEgU}Sjl+3ziC77vp~v<(*913h$a)6{nSepR&74*9Mo;krc;Mm4(~8-)#lY*24~ zQkA&AXmJaK8V<8o06&J!^;)?XZ)0r0`{GE1F4|0>(qiv?QD&9k=d1m0)o!bFubmH3 zeWb|ZYj8$*Xz1RKB?rq!p|63|Ghn!lb_IkqxqTW@gEM@Iti{1IC;+;mVBgzhLw48b z+&10!0yoxZoq&Cimw5I03@EF+UDI_-Uv>6Pl#FmR=e6GjXK-?t^V%T`Y@oM|79bmG z|9({-cb~sTF&dT?YrUk7ZUsw~K<%{|J@X*_TmN@bds)u?a|AP|!)K9)JZStn#w~pY zgmZhNYR=eZ_slJvQwJ!rb!Ql3<6`&s_}fot$Le0aR_s>jXNs!aa10UvYU=-XEe^AII~q464e#%fChaUz-ft=YAL-!zS0?j4T<~zb~H)O1ej-^Etq> z6v&93M>kOr^~$0RtEIfUrY^Hp5l0FvoYs{36StJ=WgQ3JPvjN_hJ+#)gj(nE%8^+q zypLPY-Q528A|Y*o-HM`j!15NVl%r?Fu7|Ocr%F{f*Mh7VJ)DE@S#Eg?K4zMzXSY&7 zUIS>K*rqTN$UqZ6v4`>?pOkpQTx!kDcHX7@xp(9BWkJsO+Z=@sLevmDWs9*u>`b-R zxz($lBrF>AG1DO^Jwwt^!*uZg1%TeK*@qi)(fj2ZV`U@#;b=`i+Eh{eiVznARvsA8 zu>J7t`MC%WhcnsdQXfWnW-NxbupN4=LZMl`nS9XvUG~^H-VH(%Jj4 zq@RFYTVA$9z`?1$g%!L$&S6;S0X>{JCiJER%dBluxrKl8(1gE->n`qDnanKqD8_GL zr{N-m#GHT8DF>cqXO~SkoAd~+zyH&_-{v{`cidG>LIS-Z|6QYYmHq{gL6lXzu8LQ{ z4Vyk#H3{?92EE6%IvizlP~=`N8}tv$p?@j^H#ky$mzU6uX}L+Nf;rzcxNNTV(HS z$O?`PCGy3Qg3@Yg5~T|mC&8-~IAugx@HNdz_*;`89Y$DvB(i2TIgYgY%e%5$ zsb$)gGwdXKBGpe(E{}hsDDx^2TOjIO4VmChp-W3+Z zIR$7`h$n105V*o7qA_)ltIA+-T7S%TNWn@@QPRy&&o3hX-cW6&XDKuyDd2yNpRp_h zSqzI|u)fS{*u(-oTm?&#+fOJl(m14I4_^Z z$E=#d@^>GWx3(s*TB{-zd;hoAw?39DRfSBf^qtJ)DNvk5sLT&PZEu?Z{|c<75ucu6 zw1MAuMhs`PTVNJ~g_t<_*2X1?k=^sK?*2Rk{5LQ}CGUXyS}#%=QgT*SM}Qqol!=)l z@Ob5qWp<)N0pbrpMS22IkKq3-m`i`W?U0ckGF;Lv(~LJsg{GHu89N`vP-WZGekx7$ z{aC*0YLEP<^6r)#_S)zs5Wczo{%-0t9RN2&+i`IddKm8c{@T%ho_PVSP~+Y-s53);HGkYjZ?1zoJpi`WS6eCAc{5~qxUt4 znis6if7ZFd@gnRm(U3>Xi;?Nc1NS^FA`XMlPJvM~JET+Z%O<3C@iVe4Q=wgyw%g;z z%~OYuH*f)&e#s@|GNs@kXR|y3BlB4OEohJrIrm&J;Fw0APHR9OqL6VY>INHqFoLn0 z(2F}2I5wwTKz?U}^Yos)gCxlb)D_??nqb3YJXov07kD=C{ao-H58dE$402dNNG85b zjUHn!sHU_1r-}*YvE`(`JrjuI^0~WpO(4@S6!5r32=b29m7b!uNIEP0kh@*PIcCCu zeJ8*3ORG16gYM*542;!}nT*z#`K7W=tMlA(%3=8uWRw)({p`3>_+RNxxjEgD2|yMP4b7t=XP;nS zWjhaU78x=*iw!PH>9S&&vG(5rQs= zRoo2@CcK#V;YpjW^uVX8!%!Yj%L%kaYj-#y%8u!4Wyr zCB#sDZIS76go;hRifM>n-gWV{cBAJo`Ha{S zYA|JXPmGBxN1$U?3H*|tgtaze0cC4S(a<5g;;dpQKcQw0EMMn|c|!u!wG+Y%s2cWi zt4Mo~Oa63>4o0r7(nZtdu{p84M9=WKfsMCqC>eqsO&l0t?;b#nAFM1?LNa8hG~Gpc zo1T~sifmB16A#lQpbh=uxp4Mj2}SwbWsRjD#JSfeI%oxEBW zb`>+{a02Kf_l&7OMh;5F?Ue>pPxq*Kqm zJDLYEZIN)DvdOP88uOl(JE^k{9QTusH*)nyp9tO3k5XV%&&hsssV>Zex0Keh2yKl^NE&S)ePE)4A8_&c^u*CHqNJRJy;dX-t4Z5xDf4{n$*fn1Vk54{ND-sPVbQe5GnT5u+`hIwiH`v&0 z%6o5hXB*U9kk{n=5@;m#QBlXCJi4n~G45gC<5J3^C`JR6`PJT-P~#z-18kvz_zw^p zZ|mILHI8WEvV~2In)Py$!&9dFuH~o#6xN?7N&9a{3a%)^_CED`dJgQ6skXBdIcm$Z z0ei~j#~WFj`Gd0o24tB%NMaguF49)I5pP9cNIy+z-jSt%DD|47of+o8R6Jd%^7Pe> zSg0QR)7CF3OjhvcQJh6i!FI!+GSzBwM#_6AGx8%<@y9*WAmnxrz?U~P!xFD3DiV29 zA*W)zrJkYlw5xxBgk%b1tfXiYAR#I8jdv`h%p=!uvu~bz=5C-PooCBD*PwM{<(JyO zf-3kBsI#C{aZ2`@D)Rc^1tGbon=(GPXMbTvm%Kqfg6xmQsP(${){GFXSz_IoG$sDM?Mzak%qKy? z7U93{WumOx(wG-jOx)tM^v+-ovO7TgLBRPXOlW!EL7^8vGk3D^{`MKE!%yE)w0zsO z>6tB{%e(C~cf2yh{9!MpF-hMgT!}f|VuVL{Ah}lPT=YLSWyg4sF37=|;g?RYru&0_ zZwu%lC^4y)rY+Vm^OX!R53>fYZ?IBZ6nmQ94t(e`YXVq)D?ZjOY#>&K#iRS%G(^PC z0|yrdUErm*i=DUJFyGs_eJ>I^jynP;dErIb2vzLUKCpYVBybyBJVMXVF0+z_C1xoP zyECzU$+ORmaxtAwztgGlA^C74k}(EMG{AlRMq5WCPzGVmlMr}eROG7CA>x-+Of%$3 zGiENejM2@wafy@)^5j72pAa=mUenT&ghJA(D*_a^i9=LTKw&o^gEXTO#``=nXNWx< zL~;K6FXTE%H^&n(7o%8TRDO8;F}b8CDynkdz2ezhn|C9Q#wDdzye3Q1630+n!Bhio zVQGSRShJd0&w?#ASg^a$$BM;WVN^xQ^f*dw(J?nrTa|jdb}W-VgiN*r|J2_#kx zn0U>Xvu*9icQ45rjz}Yf7p+P^)TJJ#W)FOVDcIe zdv!aO9j{b;d_I9}!>xRm;6+SK5NS$4!EtbKLHoRsWu{lc+-#u7!pQdqL$8 zzey9(Wgdg>nit4{-Z;;VI|Y)L#r00fmnm3{dSp5F<MaQa?&SzjoP zZpQ29x#?#MF$pnNFi+^eaH6FgmQt;`^)>VVadh2rN$3B+``&Dr*Dy0HzGdZ=>&jJW@V$m+ zW?q(}qH<+wib&?95U!z?W@fIGlq*+?N)E&c{TG#9opCqBoNf|l%?#T*6$bQ9T zT4&AVNqicFjyEGx{+p%oX4M=#=3c_W#sClY$)Pg5;8Ynh`R1@e>YQDNa=k!G##AYC zJv9+IAA(-B^Y1s6oOGxtkP;Vf zA1?|pKlVOZwl_ECs%@_}SGN@&g{-2JL;Mwpn-yS{#dyJ2n&5oz44&XI!=n4!W;^@s z7*P>1eo9va?}GB&f^O=u^YSOo-hAP4qnVpkjY^YlKsEAJOD-9v%g6%BXxMFM#$-LN z)*SNN&*k}5*dB2!vw@(rlxnMXA}$TC;w|R~y+@Dp1ToNG$}^_A5tpZP+03yXnmh{Z zV3GQAKYAb8kYgvBvF>IxgNj4}9F2)Lc!(&Zfb1@BpPjX7+S%8UjRlgk%wS3%~DelKinLuDRW%uvN zO=l;40@AN%d+4PD)uk0!aJt8Tt}+UiR3Y;Q$=ffJ(qiB{un&t6+DR5V!O&sy4tYll zQ-!LjZ55vDTC{Y6Ji#2Ax$28sg^aoaHR0P zDoh$tm$la*rhAa{zv*JTPz$q0kI9)NRi@|cimi8n1McN>nIAA$0QSw0K+Hh+`gH%Y|1E|IRh}5nnlwYH_ZuE z<_?X>K-Oqz#`+^1vMI#kq4Tq0_*oux3W0@hNf}{$;l4}#XVU>C2#i&pH_0GQGUCp< zr3V~n1YOv+aP=#0&5ZZJWo{IF8vcoh_+G@SuIHsyA(#R8Dx5I)`kzg^Pjl-s)n$yi z2s~MZ9jfL&q#H z0Acr#r|NVYV>(@s<=4)AYMjCX)YK}hmsxnlblfy3| ztG{l%ZZSApNh8)XPA}nYan}X__;EoL(@dzEWnaqIu#x&}j1*gh!Lov8KD_fYJF`9? zX>nVTpFGU}LB1$}J}TnQ*Bm?)=ND_$a5fw$#9a?x$Nvy@W_(j;(I;2V$BCBQn9AorVqZI0$dygp}!pw~aj z(@6eTvGOm6ds-5*|K&kq>wOZc<;?Ig`q{mBOt{>)eOQ*cFN7F|4X?tc0Gnh#1wnaY z%7g{ILul|eODaG1l7B5uJQLz4uF10(m!iBl6wZ-R?al@$K}w#^G&{2~2)n|V;1YIv z$<3u3RU&jvdPE77G^ynqk;CAE zQUM(PNvJJ+qAw0s4NHQah|XB5vYvb!oJn~z&sQky!0DJkTfsU^Z`Se zeY!xN>BMiP_%v2saZwuPIB#|_?7|zTOpA8bqnmq>0h$(g%`p2eejrcgSW~OzE43B+ z7eq+kU`D+e_58?s=kIX`Mb0hC);b|0(evaMRYFf4D&CTE;lQ8i-$nYFQ~vB|FU_ov zY0w%9L#R?sVNLYc4k>vf@mS2H8zl=cnYY+F;g~65 z^nt3`>rBF|%wuE5^yFu;-6_~>CsWK?|EMcKtnQe{kT1pUPL8=Zt}Q%B6By+yEvpV! z5vHgMLOH(W^G49v0>X}^EM-YpdCS^tA*?~3kPGQYmmWe9(_WwzIoTDBXpz3tpib#p zSpoPT0C}OIqYuvvC^$BRVbs)O-(@?z7^Kf>*01^=blP5g^X+pp%dP6$lZB0Au32nx!7%XKk#*3|qqWJc8eQx2dt33wZyYRo>a03HR+2-2`Cb%2#xG=a`wSa0r>2z8A)dIq z!oKJJLS$k%0R)svm>&YouViL>3;OQXkVES{kMFVMYG=)=7;VZ7N+z(kyrplhCMHYa zGnBu=c|Uv+A8`9@@vzKlV9GAr==74GY5HkGps=X?i0ZeQO>_m962$0Usaafx3c~&VWi17(e)z$zB)@thwaKBon`i_`#*6JF~EsVR=**zZnGDs$+$(k3e>M+9_%Yb6$+x+%U zm>d2ZN6Na@mIl-nNL3opwGN3ZE1W^{c+7cNx3=vKIJk&X5~uQ9v2$O{yKzKv4alzii1;iaT(2LqmUkA^KQi_r#UH($>36)jG! z#@b@udj_A3HbMKj0>CkgM)>L~`JNGft8r*OY3CQe*LDNL;$|z2SvsiU;NHz?aUtLM zcC(v2xlLYp@@2s3mPtc-#D~CTK@ZlfbjoVSIE^?57)R;p8BPH4w`H$dD~*r@In03} z#4Irg!Up$&JVr*K8{46FaQ$eVV{GcueRHG#XVVQB*^8F}Wtu!e(w?W0gc*TS4*Kay z;#1VK{MUTU3a-w!?_?H!6^P_k&HjwUn~0p3xM5}TkS_;L9IL-Wt%#MClIAliEmBs{ zf1haYSF_N3OMGG+t}X&8tdaybpY%xo>7Px}esfERyf&NW+`Tly#$7Viv+|faeh^M~ zw1H{0_ZgrsQ9e==lYX#5XTBm+dT0-pkusEZ3-p(PYV`wM%>Y&5f%ku)+O;ct_GH=V zcGz7_dR~TKW%G@+#^fLW-G4*nb8dfME6LVsywcTxLI+LQ0#fvMO`^EWBOjTQ&-ya{ z*(CnL@WAPbB%g*4YG3vrHXbQOcw}Wp+&gF`rwRvM>ND=Jg1Z8MGQ%RQkz+3ZsW{E= zeu~0KkUV1OGmr(GIo_nsXqN9m535tD-pA}6s*6)K-yln%XGOB+<;wFLWhGUF8tMdT zccX_;>TGEeVH5?@o=hIfZKohEUX_ogrcPb0w@$l*$1RY)^{)!BcPa($I>h8yb9)(d zJw{h_Lej!c?Uicln_I!6y!K~1sZz~biaH4sI_rBM$V*aYXP}Nck3L_Q-@#twZ(Sjb z7q$pjU1G0YuhPssJV=@#?eekCLKmr5SK*ibQtcNVRSyM5CnPo~)4!hITSB@cIdS1f z=kZx6F7*@s5GGgO&R5O4@-F86f~S|piJ3cy4ExIX5g2$j?QzUOFZ0r^aV!aJ`I`^X zZv58d?aycGR~3!*;|2TD-mSj9o_-=#=4_hdqkrJA-XR5^6`s%|Ugl8&Sa%p~|17nW zje}v6|Bd4`i+qkf<}*_xXL(ebi3gAf#W$ZtGb=IX$b}t;OF}SBC__z8O{FawV?`u0 z(H8s%f^*92nL&!sN}9%&mA*3wXGp_0Ti1v*Ea>h(zwQa@U)Xi@?U~m{1EJ_~-xD;E z9eB30=^5(UMspyrp)JjBlyYuZE)C3w6$~B;$^iXDaHAi>*=$B>%Fj3lrXcTbs>E!` zh5-7nYD#=HVdn*mNz#mZO?RjFZ^{oiCi4KBsU8LlJq?z^ME*}R>UmB*x5OusLhVrAWaeE_t#ar1p((&*#q=td;1+J_s-CjT*p(i_Wco z&JIv43}=a^I;`$v;zCeg-qE>+vJ%c>?hRi*zxA^att0}~NafX0JgQ;wcL(DyheWz~ z<3|WOvu+L)z$Mxc7h85^(XV`|rPsf; zkYP7PH8k@1E-cm{L^(;`ewtSf1!DSzC15p@=EPryyV_drBW$}C^k&TU*04xj?>EXS zS?+kcdWfcURPmQsT4x2b!!zFf=gmZJW8=RxD!+;E>Rv0G>e{;>4<6a{@YA4tJPwhQT{k@>~7M3yo{CEtjx%HD+++b+*ri?Hp@AV$ve9M z<$(@R55G|mL<{dq12=BMZfEPd&!svkFLitw_r2WTC8j8i>Z_7vj%fweFC4RO_*A{d z)U=CvL5Ko1n<>Kst_|Zi#suklo$!am0&X<=R>vc1;6Z_75~IZ&3lNj58dq;%@$bp7 z-2bM8Y=#{USu(cuSfOxnjUnJua2VUwPGo0TzU!1S1x!>qk}wL!fq z2-+~t6r_kpm$1d{bA5d3dZ`tIYM5NQobsB7a}DpJ&F~s9y^JL=(0;6LNb;O=a>URo zJ7^&swz}M+N3AQZls|g!)n(v_5fo=}oEnJXp)^3d(+bUNgt&O?dn3L4 zx-a|&58YE}WSv{Mm4m5njPnT{Xo&CM7L4Z~=gX9fXO|kyMGa1|*ZEh#1RR0tEZ0S8 zB?EJH<>@<|V-X*U>^Ya$=oKy*9TbFSAp2-SJn`Zm`pW*B6&hCV9@;CI)DZSCvRk}* z-~t*G)NsJF7HejGQekB5zg;sw7~8wp{s8h9QVTZm7v!frIesIgAV7+>Eo*Qy%OVTR zI5qvF= z!?NFSc04&6H*t}F?kEeuKjn9kBN?c3Esmkn7yj9FPJc$pUs~b1vT*I>edh#$c&Ly% zBM6BbUkJdELipJ*Rb*43-H*&6S>O&i?dspbrE6rg)faZJ=1W!p>Lyq_8FC6;IeY+t z8NTN0J1d(p{86x`MLySjn%SvfqHV6jG{S7z&a+*p$7XA*?!_fEj>ms?X;cFe;2 z3ja%1if5$5D125tN(9TF@@&X{XY(CBo%p}xEy`WZ452+R8IWV_KT@fWF*;vQwV`~& zY4~s=Jj~%#6}Z$(lL3!43XLvpfKRN0B2L7w3fbd$W8#$o!bB3?`#kg3Z1hN%RK(Dqx1Kf#FSeeiqV?-o-O^x=o6tZH;i=!3af``2gINOUGKfdRT+eKkgjz#CY{j;esU5u@+tMDW_r*^2*+JyBhtRL2R%0eYY z(*x&{gpTt|jfXzmg`N;)JY{bf;2dd>QSLLT!J!J&tVMr&LpH=r9!1#6ZacWk{SG}7 z&s+98au?7V66k9WJn(s7DP$lR~3s2+U7oS-`Kqw=q#Qo%G^()qv>7*G1E1&oFj?(Q4p6Liq)it zJq6w1;w%}Mefi#CtcECnq4;f^o-92E4nT7;NA9}5z+#gR=K96EB&KPXmqHImYh!>{ zT%U6B_aOd`#-kYhb2&={p&n|+D8_CEYTt-v@OU@4d>?b|wK{F3W%_N}FFK_Id5=hhZ8XMC6kka`?QTAsyc%YU5Y98YOWYVf=pXMl_lnydCHW)K=0~CeTQ`MZ#4H|VI)I_@?mSX=uI}b^J9o- z6)wRFSRxAEarI44L)pnGtO-veR=9+CD+#eBi(z&z%KhS+2R2%rvpAYSY8k>cOYbmx zpNJpa;OQSoGhLP9gC<~9v#BbpFH6rY8nS_K0yR*bV`(zWh<6%36bgDAFNd+>UhkgMC<%K1{zKztyBRA=yrxEAJ05*Tm3!~@?CK7x|xol^tBfjAH;3L>@O`D z_y4MD*GPx`f`A;VPI*psjZH-xv_kg^omv7>lUfH%MhUSQOgHBy&G3RMUVb4&9Nj(W zH}$_N$9?8zP97 zzXD%;WbI?C8+zXYo3U+gCMb8jsH zt~5IEipxxj9Ke7-tv)w#&*vQd6hX-H1Y?mPDB|P4)as6>d^7ba&~q_vXe@EZXZ?Jnidn!X3aFW)b=MBdliwQ6!JdR4PILOAGFi)}R29vP*B zpd|N>=fVVvahvgz150)9le>;puxP(3_rC#;n_dudN$tA|cHRy&z)o$D{;7Vp3jJv*7Od7Nui$p+;&F#4Du#&GE?Y@CA9e)%pT*;a4r_OH}?;_0-QspjRia}O4r z4|DCaNa}X7Pz966M?iAW6UzBr%AQ>Wk>#4%pX-$W5P~jAi>NX48EJHhBxRDt_L}Xf2e%C3E(vX}3h#S9%XDBH z)+(WVLADN{NO{r`R(*!ZALg(8$i6r1Y79kfmK5Tz%E#MvYHP&!#s8JEo}dm!{4^;! zIqO(8qdCADh!zM~lv0B#JM?hHDo?Zg$9xHilhQn2Yw^z}D~|jn>S591Yq|CyNp4`5 zau&Bo-d6%lSZHyQOO>b(-0&9zr)u~zLR5n~!*j#6{8+F}A9_R@JfKSW#Sa%0*Y19yjixMQBbOnfNd7eR1UO#ROz%CJ zN_U)Rm8*71DUr~maur61u8qT4wk&X+dj`o_oM*McS%c3+{THvZ#?e1pQH|=W4 zeiYw&*0P7wVOi~CO3PfTJVklK#9*id9>t^eDS+ z-@~45iL!U@kt==xUj`16goe|(dra^P_M`MeBAwW|cu0Fx#?N1)oF;QT)=+yr&mg`i z;p30s>Pz%lp0W*@9tBSa1@7}z`Z;D{%dL{do!(}zKtL8_5!i9mG?}%JYt;;dH(<+x zry2(%I`iv4HVy{dK_p_|(f!64;?L<>zTSKzBlzcE7c)4)xM zarnKYcjbm{J=c7{qLMk2t9tzagC(C*N}txSpz7RiVVh|Ctl~h)Wz}zz2W}PJ_o`=B zQj9_W>7weD?vXQt+a6y?xI@_c4$M5Z@D$23#^W5YEB%jAOgCEzO}jcpbWB_ClY4L0 z$E6IVsO}MJh45FP;#}IIdQ)UCu)u(07yl^#^qdYBZ@|`_%J1YaM7j15IOe}UVuYb- znjd{mg1>jfhQR^cgPc8#o$8IFf4=J}zW#*_nn1XSD?smfkG_m%$zx3)}pso7csK# z?d<&$#e=vbl9#v*gX2~**Kf=FT zi-9ii+%8W^bbA!|KIvVVwakrS>tC&5iY{tv<f`bu}w~LCW9;FWV{g;G}ub{f)Nc zX0uSAT6G@X%Ih+YzrUBj05@XOP3}}jo5LwUM9k_1ZkiJ-1{}V>{iGje3aB4V;9M~& zmjTPr-a>XBgWV`fYK!rKioW)1`bqjHrx~q_ZO=g-savhQO9Y)yWQw*Z7@U7saA^`4 z`(}T&fqdS6Yy1mJCw#cVCAmG)Nwljys<(?UMeK?q47S|NILpqmQZgS1oMi>&M!hvj z40aeuMxhON^A|JfkGH3v3H#-(nCx?XIN-xqx~Z@|w`|Udp`PO*Kpoy|3keX%WFa)) z_#9OiY(uMHtC$aWSSk4m$UmDPa$B5{Noc+*_a`4TO}0*&iQ%nhLf)4C=U+#!qh@Hg>X@lB*JJe_ z78aCd3g9$Q4KQ}%h3X0K%lYF^7!H==4#e9^P&-OWtaHA4V{p73k zd(l63!B7-3*3CCZ`vq+*nKeC15!K4M7LSCm%v0qXzUI>6D75m;sLJAFaSHu`Vl&2I zC2!T_{OJHp&W>VNWY`fR>aPlF4GNZ{Yh$!WyjvO2RgGJ_|JTgLMBiF0=>fG7Ce)y@ zQEMfU1Y<%27jYJrU>Y8YIYQwnS*K>7mz^G%lRXQ8?pSaPmEMia;g6SBH8Uz#pQ|qI zi^)2v`Le+r&>T4u)fHBJ_7w&2N9LsYLg(0Woz+9gjK-^x29Rs8`sZs{yzcR0)otf* zKpj7gLkpho)O(jIOA=!V8s@{OI4}{uINP>%SK>8hx|&7wpDCv6gWq%p;$GYDayhU} zd1J}iB1~>l)DmMg`mXBI2}TRZT5s_Mr{TCV1v(z58~e+EEI&HF)meU|5&BJKu4wfb z!A$O9#eObNm7)j2^%}Ewz)`Ah)*7-MDL10ULH}!SZ1wZ9#M*45M3LG`s&0#aM%`?R zfvA1ey!1ss%hPdXHiGTjFdH-@AU4|*9py4` zXTT>Q$-6o|Qp}$Pw;W3IpE9333hv^dDk5)TpPS;FWXIZ@9MU+r##+m;q{Ji9A=M)h z?jE2`mtG!Nar3S+<%4Xv!EcwbF_MX}K$mnRZ?9EF({L*NqLRI(!j3GlRwz)b$s=>NI&&_*W<62dKTbLG{c z)-Fg7RkM!Cj~52vbsK33j+A&=#zqolBqK7*H`{+KH$b&@rLs~DLJ#4?)BLs+A$HpL zMCdFOudXdU=FHtHFk#k=W?*)7GLOI(WELmYJhBYcGdqYGwK_`Nx1lS|{#X?+eJ#p~ zs|dhoH81p5mcmY%txTc0433i3;XeA+c-*H`gtUIq{?PVja&@=3llAGh;)6B^<4Y6; z2m2zNzyPvRw3jd4A~W*d)zaJGTjMpHLyA+KYq&Gq<5k&v=FWp1oeFxtWM~{RL|kz< zzfl^_yE1GSIq2~((vN%s)ss8A)j|Sey`$7T>OuyrO8ZZ|_=HR$=0km%?D>1E-yV#?9S?#Dfdm@#Aq zeOaB(m`H_H@t;{-Hd_Z5>xD1_!@jyb^stj6?Qb)~WyzkT?^sF4ua(x_#zW*!+=eKJ zMx+4$YpOry*^(aO<}8;0J=ZssuUvt%YR97VcCBzIWhDAPUwBenX$8CusSlgTf^BWw zMfMtP$!kBX(JJ<;Meh7~x=!2^w$B!FB5gIEbW-t~x$|^oOgha?OTc*BDV!v)g}JGp zst%S)|3=v9&{un0fhKbzeXhe3h5Wh^)V32G2?wa>MlS>Q?q#NlK`%2pY}ca#ri=X? z@{RD%RhKU587kUn`PY!G-w)QXG+?@r5=0!?D#uZJlJIz6TRSmKTxHnZgM>vV+COv( z>Fzom9p2FHh7`E^VKgV`@uT8Tioh%T-xivFV2dpud*we%`PyG)rsSIwrnqE?LwscM ze$ynn!|+i6h~pZ_#q47>^{+X)v9~dD`#kQyq3u2M65F#?IFiL{6#gJg1A zB^8kGk_XLnfMXX-c$uL$?#1tj!iG+*YFAmDB45(pI12>(7(f)27=g1-MQ%COfcr`^ ziAfhY>43)SafqDc)IZC^7`7(qa1JC?wCKmYzvQk#5@mRwRhb+8{s4aWc#zREUpH8r zL`7Xs%UgvU+V0+NziU4r)O=#uI+#0FOj0h@%Fk~^5S_4F=9H|*AbF1eyV#5Tec3sZ zMcav2GryLtDcfCU51!}^U4E5ML@_jwQ2S~dXT4Mk;MdSj?`E$%SI?uRVLMrg4==N#M(u^s=_6)E3# z3f?DTZcm-m{~8j`3d~PHvmtGoip-h+U#-EH1Mdk{R$zGHHOmftRHqR?S#vnh zS^gqnjcL1JB#3d^x8UHq;_Ej!n|i-|m>a^de$&gx`g)fkf0Bntx*B3uY4=a8P>Nx9 zE)8aWmIfYs+IggLSZ94J*2B$CY4mRpL`0^{hNz^LJ2KawY@0o~QC`?S{R;QII%XjT zkkW@zXpvUFXN*`6wZEDB8C< z`zGh9gB8n(Z?&+LchI+^&28q)v*7hJmCyY<)I6pg)wg86{(yRJWF#iHIlxZYK!{|m zC%3@jpqpwd5X4UO@CW=LQmb)Sp6W+Y2Dt!nVa|S%7;opz;N|H6Z{YIKiIX=npgUkE z8f($(n{T+p2JrGjlq5jmHIt%J8?%nZ`d7uBG=9B;F8WM7Fk}l^>)*?fl<(Gq9S%gIOiL=Tm>3bo)q6GhU z?#bcF!O;PXT&Owh#0ed)^P>^87Tj3M zg|LgR*}n%IKr}A8z7|W>-ov!5w3^QH>3{wt1%Lo?cZv;yWFaEDT7^cist zOtTBL*UV#Lx0<53_?BI%J6^uACPk`8Q>t(Y^%ZnhysRoe!5`9{PMVhUTL;;SX z-DaY#&5I`4mFjn8JQ|vkP!_)U6MyAIc1&wz1^FmHd3pQR*BimVzdZ>=9cI<~}0H*m7Le(2_u{BCTBFIU12 z(baa`y50RC`btWx>uk!P=i>O06uM)VuDXoXkf*YfrxaTCV0L;PLJD3^l3!9AqY-n8 z3@SQ8i6Tq{Ez0~v`y zW%OOFR~mT}w$En*Y=DA`Z`(5-)!9o%nh-vpw~SuLJR65p#Ja%@TV8m2z~aN1KGr|q zczO@Ed2K)BK~~9qXpB5|+wjIro>X~a_}~*O-hJH^{h+as&;~iGR8*6S4kcf(A{JjT z%)CR#SI?A~3Dul6-uAxBwXFB{5n_&~+RWhdt+`CeHN#2O z^%ps|!=W#ded47mIlt7ShFA&`JuZ`MiO^;2O4F2+b6a-m;yyCjHmQz9h->O;W_+W8 zEI_ppK&WE3(jPL$z=XNLtE74qs2D!qP3um|zIgj~HscF*L@eb%zFk`z|CA{jN_T!v^tZY2@G6C<`Y ztv+AbPg6R1un!s!>uKAn}^WS}}oZmIIhZfDEu@2Y;`29i*0+y}y2VND8 zmwX(>OTN@ygEb((?4CLf;l9p1e#HiI3N6ukU%bG1jA$1&FW`}@u1sHe+@8C)uFO!k zQmV}-7mG59leQbIV}1)aY+u88V}0%$&7e{44&bSWF*0Dw02fQ@t0H0}hai=mi5Gpl zvC)+1{6t_8d{s|lkY@bZ>;Df8K)gs>$$z;2hT@vO2UAIQlZd zBns>%-a)s|Gq&Mw8IS7^<5 z;OguJ!Pf4ykbCz!j04Qm-KDfIYruP<<>`Y2CuK&B3aE%#`52NMHSM>eG8`S0&GzhO~o%Qw6K*|fv;%<-PI;eMQ%74?Hj zEbS=Wb3hc;%!4;ScrbpIn9gW&!5PKOARAf3La`9jzJ*sn5tkTPO_pLWpXPQu0)Z_3fcnD>|Wz=&#R zAx#!ZhJV%^t*RSb3XU*hTK&(o486M3&d;0c|JuqAv$DcPqBLE!>^H)sp|h@IR&?)w zHmM$KFg0H1hb0c%UIB_>4=spH_!P+=nei-cM|R`lB21A13phusrZBD6ztyal*j*S= z%&Y=r&mMupth!DyR@vhl$fYpl$*#$0%Q=y)8A0lnG3lR9h~^UIp7a2@S~xek`Xpj8 z^Y3x1YQEU60X4ID%V1w+0Q;86Ya}|?9urf>gKbz5BMg<-Te(4H?M;OJecRi&Ghz@k zT%@~(2|jY@_jmDI3Cmy6!_G#4L1E3K9Fu<>-y|X>`PT`XFYJb5cw8!RwrKxuEH-w% zq)}D$n)b{LmNa6mbav8=HS($`O6vTBjz_q20R@WT&W6z_IB9_slV+Y_uk7<;{nGw6 z$=Bt6ibDjd9h0MvcE*HaEfQx6b=4)~LS+2fx$}NXoGL`K9-e!wLYR?UL>n1D2k^Fi z?MNK~X5amp+55KtZ2CQbc0;)mv>LZsC`QbcQg-+pZ5wQ=#4(lz*NE{+_=`bje9fYt z4apKWp61?RGIChnS%*{b*N*G`6`0Ojm>aqE`lLj~R4>qdT#j}f-xXNDjWe8dR~opr zlOt|@MeCWxF*dY3`+sZRdI3^4w}xa(os$S2PF`|&hVAn`z7^VaJ_ zyjq0$J@n>R+dmmt;eLsw)<$*R;~S20CgD-4?-3C(*F|uLfe6f~S$p<)R@mH|2*%Hz zBX*U`jt@_-8msDbmEApck>pdV-X4{!IN;O6q=PbnecU^G#;F?F?;PVOZAplSwGkRA z&7hM+na>M{pxfn=W}0TN_nB~IPY26@TI=@s4AD7-c99DYzwe}P1q|C!3qr`ssplfa zTiB%Cj~xx95GE<|6~>!ISTe2Uvr;2mYiSYx+8KJZdx@be!geb|8p{+8K!e|~5z5sw z1H^5nWmkvxI5pjU?vh!1xjvt$ajK@2Tpe?`>6?^Q;{0DgYrHOeW9MR=$Q;8)?9beu zBw6WD4t4&sY52PP8_8kIN>b9vxM5hC2`nw^ z8jdb94i?pEPGrGn0!BuGZwmRJO?x)d?`Wlg!6Z9Vb|KfF9g8sym#?3B7yG6r#hg$j z%R>@1-}QKE&L&@}5=xWlT<1DQ{a{&CZ^Io#gh#nf=6z5q+_O#oe%S|)Lzh$rZX;${ zqZJu>BHj4HWc!+-Y6lZsVj{w0MX#JlU|N7`FT;Bph?Iq-KW0|Uwv6VR8yKVSG3yA4 zK=uXj8sIX{Ptg2$^vh$$?L_x8>Bnsipt#?a>DIUjodRw}prR|hy&NnC5bB)B_TIlK zZ%g@67}b`hv65?V^KrAG+JV<>!97p4B3iPSHw(Bq)=nsQ0#&DMa-3O*d&7>LRn*iB z2Tl5Z9D05A?38+81s0_JTpJ})wzeP!vYTfeM?8)8)JpJu+M~C`Q#>`V0S|bkk5dKy zZz@l|DZ}B<=6FmUHCVGPDcqO)pM#<@U^^BW+i||wf(0XsLG)Gt+9f-v}6gJg9xgwf= z1rqRpyOF$6(z2jQ!NcLXoxVt7@S@rFH*E+Jl{O!Ao>TO^YZzG=zYkg%;cG~v4f*~1h8f64w9z(V@ z>L0Bs6F9nMb}J6KQ9AS~9E0}YBEK)g8gX||P2IULLB|Wr+3+Dt#J}=tXDtbQ$pd;L z!*56O5i^5H$=Kq7w|(h7JZQSQ5oAm4nzDbf4XPby5x2)LP$zSil4kpx$>3t-F4z}B zh1nCpvtnx8O1y%0StObFj$&4=7VPMagVTt$Sbtu=ml5{GzmixoM!gxK`PL`ySW$Jl zAo^yYxP7bz=bEoh{=F)cHX~#;)C_CP%mDX9$Ez^A82cf3gujSiix@)ft3I1iu;nm* zPI-*w<81V=y9IDcFGpRfddTz~=ZsD{_}6nv`e?mlApaIX6*nhm4n}9OWq;xS49Xq` zpw6~$KVSwu2c0mGuc)1hQf7oj=-BxI(^Z8(-7$v0YIzT)t@55++$;66MX5KI8=XtP zYRuJ-eH*I=GM$IOD%G+d&kE4*?F!KM7>gNB)jT-W$&|#bDrXzNv4B@82IlmMa`M8Y ziyQR(?mSc95!LmnzAfW{6s=0TGBrP=u^iQju}nUzgFIfKWQBbm*NyjNx#-pf@Kh!; zFz;lxD7Cdl+bpY3#%q?t+r0)3-<;a3W10p34O0(`@Oc>8L;-0xOz-i6rtm#{+Dt<2 zWb}wT1!N64*VijYO1-ZvhV2_nC*DlHjlk0V3%#!@Gt~=ZOlZ!)?m}-L^eYUk!}XwV zuGd&mu7+jZ6)IG=NJB`Aw!hs2IL|jUif%nh3E9Lye1zctdeX&YKqDgdVj6r}l-Eu; zOloWGHcA(L&(=H(5;B7XD9R5Ugwxhr$Pn;IE}IjUSYnU249=aHYw(rHt7Xt}JvaDB zt5L^{9Yw~Na9!_PO2!62KC91SmORRyT0NNN2d7vYncMH9WN`5dE3Oz|^avRmx22rP$9f=UxoXaQr=qF2B}Z8s z9&qA)D=acEh|*0Bh0D$;P|!Vu+Vz6{A%~{nLlBFpoiPW-p|FG^ddjr%`gvx~9owPT zm)Gnwjyk?RIeR3Yz;x+g{IiL59YGsc90%iKS9$FcHXUjfp6(&LnP||;Z*k2=mt8|V zYFKeA+@D9WJYI&F26C^GVUnO{-H+H8+@WTdqFtPrP8BJ-nP)U7IH%IC?MuVvKL|+_ zHMDu+2>uRl%#`anq6<^j&mvZ1@do{?tJC5Ti@@|z(n=Y4g@GIvQM9=b8UH|RD7rg< z1|4xiRoieT>yGUY+cViyAe+FQJU=T^y@@P;#nmftjbTJZ@&*5Tu6li!xj9t)Usp)f zi~{wMin7wMV%#`q9NjNVtFAHt?Z~a}c#Y#etj+)6%93?OzQ%mL6Sw1>f%IHe_M-HW zFm;KOB(QOf;RDNt293gvGN}E`+DE^UMfD(c`Kk-7S7FcTm?k6hfOL`v(s zadf~}Cw+hN4f|htZP!UvGZy)Erxiv8@-X3QD`}VIyMpKt?wsaWK)HjzQ`w?-{AYer zChU9M&D=vZAC(c+_sPy7eXP-LZu+#}lR4K-zO9VikEA~B>(kzW=&i59THD$&&H@H9qro+NZ-_tZ-R0{qm}cWj za!t9se$vbm6<;;!8U;%JCwvfj(&%ka|D@iFVp$X+N=5=2?PchN)kViK*zbf}X4@Bc z5kA{iKOI>1!D7I`I@l+Trn|b*Xi0dC3@l+S0TZG5`za+>Z&J7}Ji(=5U8UA4{YT0( z(HOy;YL~qu8+Yl}vnf$cg-MCkFwFb}5W|5kJO)74+l+(*fy1b@lt@}<1t>fM)Z#~5 zc;<{8=?fRw&*;&%`e(g_x_;>3r6_DB{*`Nb4}@C`2HTz_U$t7sths^3+h1%wfe}P+ z!82_TDZeeZf%VmQU;5W@N@nw$`mN?bG`=l(xq9yinkzX>4Tb5@zg1aQV9uzlL$pQK zuc+m^Ny6v^)vM>9Urbz$)Ye)KFc7&p>9&f%HI)z|)ZUN*hFq!==95H^`C(C`0?VXb z$TBfbTaLNc5fER-k5ZrVOn{B@CmXCYG&)bUH>Rn}gwizUAJxdVD~8jsXQdJI#y-3I zO|5~)dY8|2N_0RgEC`$0!X`%H{@GOfF99zqoG^-*5uiUOyq^3$LA6il~tdlwF3A@fqeSzOH)&vd*on>p9FZf=?8 zJVl2*%f6Y4my-!!EtnTN&Z7HUP4fVWi13lW0?wTOhjI6&dQwg--su{RPPll*65l`M z<#QpNnMFRf-blqvmY!ZMzn!`|L*SPWHrH#_H2oAi>jJJ5H@v zjq_ZoWhp%4kc2X+YtX8t^EV@b{f+e7IUu;HO%7Q72e2mZlq6sH`<%<2vu)RO#;}z-@|pGp~;sc9SB#%Vb1!WbV#^ zU`T8B)oiWmsGox}hv_#%m({)Fk+ZRkiQ{0Q4{vxhBdxIYf(w(Y*Op-|cs(_7dEHgW zYdo74>1MSU?-zM@HQx;Y7+9li#-)rEDoCO?`jnl{Xf^TIzayaqrJizvfQ|ZkQ|YPb z3lorMZfKBKZbggverdql!iCE_U*!M+Cn?VIrGu`TrCE-~Bw0FcMeYZeZt&j?-WDss zj)X_e)cl7_W;|;eGrnfJr)aaFD6HMo*07|d;mcJ*lP4b1M7)H_ISpKKlG~w220i)H zmrT5ZIYpc(9MO$_{-n}yRNVabWu}kFGPk(s6fnKMNBcdaG3p{RYhjH2tmNU)mM()W zX8@(>%$1$8e6)PKH9&(&JU-GDRqqt{Zo(#KwG!E9LCMp5re=b;FWJ>y~KsK1L|(x4VjNf;@;WA?a4TDGO3Jtj<&K2U&8GY z9B^^Ui1eZQw@^qYF1p!Wda%yh?J=eggNmE6bOM!;qY#0Ot^%&+QoB5%LgG($Goi; zlROYzempTn1P}Qk-{@h#?O2QUSxdAzylvbB7-g}W>%HIp+@h6}(>_!YtGRn?Yyb`F zsiz&Kl;Mxu;Wh65bpw1Op2!@sG=Umzb;oD|vu?Thb7lWW(Uk`>{r~^Z_xJgH>eC^g z(w+F0(%~v+A^U!lgya(;=RW1$%*rjZeLtU)5Gz86edLN^IksW5eIn$}G0WC0caGVW z9d>+vul}vj?7i3P`Fx!DkduDuO+p6oE4rU{{amC`9C-nOKh7fnr+J9VOEfp5&b^~5 zJ~~)bRe-cMjA)O8C!GiwAkx+uY)}A3W1lJLFcIJmyy`954S*Z5#?pJj!P~1vS&yta zjCM@;P%|7ul*0Ai`%1{OTYLyQ@LW3IY6$Awr?8Yc&&mk^(qN!R4Q{NeINYv)u!opX zkfh{vj}TXd$29dpHL`~0+;*SFRV;kI6j-(2OuZ}|F3@j0Qv2VkLChBo52tEb>Ev<) zqQxa^P(kf>R{a9XMRBQDd|XN{o2N=rE1XZICvq~i`|48UBLM?cpqvndpNU>g`1}%A}hV# z8dD8I+q#P~=JO5muTF>x8t05=O1z+LI}EG@Yj{h$-OSv17x2m-blf%izsdb_qr9w$ z<@QS?UXDGfDRIvEqM_Trp=q>J1xt^o=p4KRBvDf%N7r1oaFyE!0yq9zCLNJCdw~fK zU)emiW+fle5=>SDuf8G3v$*RwJnI96Iy8o&U?}3V zzyQX~1A?}~ScS`gDrz{Qf%?LMjM=zf3%XEO2f=0cFGA2Z50>M!UD(m9=CFQ!`ro*n zL$hv~r3c3YMK%$}gt-V`L_Np=(S1+n$k8y>ZdDc4xOBJb)doaEX4>T<+*(+uln!iC5tkJwP_7C4)N^dBm6-%Fepc~lFPuE2bh*LNNV((91wDtan z*Za~O-tR;F?s`?yur8B&D8&W<&Ot*)C&$t@T6gdWv_xL zxwHhh8!#u7U*)bTiG@i5&%?fb3bXi@4+4*yU?8KiVLgdJDiLq$^BF-<#R@N=KPKzycT>d zh|MBu9($p8@j4sBuY%Fb>W4~b6@uOpmR}S=eHf>*%oPaz-fJoLYsjROu<9oJ#so)Q zmVPJ@!?8)tick@@J>HpR4x>vmKd#`5S>1GfBu;_2`{=SOKAvUSF@@441Ei03DrNKk6R=6om=CokM^^{4Rlzpm~Xle~md>g8!x9>;{Il$yJ<^ z6baFJ^GzqLpC<2jO6U`@x}?RbT9NDT{NjB}cQ2;YfiBNeklHKbW6a?+v;?Lf;hB-d z*ph2j2P>@hcQnruc|$-6BV*xM&WidHmj>(jiwn~V_&@RQ82T+^!w^v+H>*W;0F{8l zV87s>qDKo_UWEvc8aJAMyxfpo3qPf}EG#4swKu@ni$vdkzpwyC_1V2`|NQV0Q(~TL zz@JkP(Qcfsj@64nD#1`V_bRw2wo{m_qhPokYZ0}dn3e5DZgl48n(3fh#QbNY>P{-A?yat=u zxJQ%fa}!Z_$T{KVNDjf{h|jgVZ?3sl_E7W9dt&d!l=qF|%l zw2KVuTfkeXQ~k3uq+SW5{`^}G1@p++&lD1gwV|64XgsRcTlKA63E#X?idZ|uNT^FN zvnl}5gWSAAFAHb^Qs`Zh7^)t2+v7(Z=AX6szzV1rM?rz)@?Q!@mS(nZtVzA=Yn9q=zc`*&qKR5~q;{`7Q*2JPWBrslC3}3-y zPd*?3(aM(+R!G*;<8Q^9vR0Nei}Vmpw#?F$T+cDj)aO$Nf&7I7YF31*g~??|bRh^- zZ!S0^dg)p@7!TEmizsLAmXZeos^4ROb*(WxN8`>AtOeSsguK-AGjt zVj7i%93dN|8I4;gpmjFk0R2weI@xHRMXzI zcD&`tnuP5z`LOO9p!$ACu<@VD#$&HR@BW7_9g3LxTBP?PslL1(LY#G!9H63N6z&ne z`2{n$U8IT}M=h9DD!4Nv5UahYfI65}>5t=)I;`mv5ebIz%VMhmax6|dl;Q!_+~dTz zqbQp%j>Oc+BTiM!@Ay; zAHsZwB<`qH#EK_PDl}zspj(uCH<9lGAUDQZ-Z%^~|EC0UJx9Z6d6vcOx@gLWR9lCM zBdHc)vRc1GEtG3Hi&GxMsxE%usci-a1X6LF|q zwUo~$^%4uBCKX(Z_yuC6W07O=%bB?+FV1`zB+5Kyt5yAqM9rRG z$s@0?m8(h^+S3PwCm@(BxoR1Kd}0ixWu@#2`pjLc|F6{_%0u@l>XVHiAipN?Ma;{7 z$8^6`qq<;}?r!o*$XJ!4R_{p2eQaFZQ?{$zXJ>T|Q_ z_xztSH}lHhgsb;9d>wnNn`rzE!viW-$kV8P0w{kP@mCebrZ^QIYw}XhnKCcdpnJ$h z;;ube+%6KOX70>DP;Y(S>={MxNPlYpz`Lx4M(87}G1evnRUnl*uxl1MmC&Pelw1`2 zc3O|1D;s~!S?2CQ*&~t=O~|*16mFNIySCeT&$|y@|GHXli@G&Z0y0M#VKuHX(t@k1 zF@QtRDgK6|E%z4GVsF3SoBg`*FB4F#%M??x0%{Rme>^Dzl-lCOeWd#m? zQIqA@X~{w~1LBZoF}#XsLhWLD6G3ld)X93O1wS)H#>tTbgb4^ zS6b2VhB5Rt(+!_E2IrkxOBRcG4R+ICuX8U!vzHIs+Hr`WEv3%|Z%I2eRQq*v7W&C` z!4#ZT;G8jjC>-xCLfxxi<$HRpGly7qtwoXSJ!JZfH8sc5E>u&oG3v&#RXW%q-2Sq? z^BsA(H5$^~ks2^%C%yzQf?1b76XKZ$G_;Vm;oT|>S(sf*dWn^;+VFObnN9YbFYouu zc6&L|*wa~;ECVVl+*@d6 zBJiM|x-?v9*6wO{d_c1pxyS>}GHfvdK%@_7`q*y1F2-;A5%#mD>}0iapY=aKsJAVH zq?09CKzSg_Joolnp=HPHzYP2C)e2gywu36pv_<5s94%pOGT-3@(P?XhOP!~lDh*~e zPFrnG9R>}E%6PhASkp&0rIwil!-zCt&8lZt->2OQP0w9Wxc5*JFkDwPQ^EK`J5KdW zGJVR%upVq?T-@dJv~1*pqIZcXj*QceEZerMwW%!_Q63mkZxhcBK))fM#*?C(0LwCA zIG+wgIX#n*FL>Q%tM^Cm?7|8?9NSWHFftB0JW=%GEc!}z8N!J%vU#H$n5QvD2Lq1| zfDZcEheuupHBPjhGTTH5ba}@F<=r=HBWR{$ivT1ohy^25v-e-&cE*DIH=W^e7v^=p z4dLa1W576Gf83$iQRr0@E>uk!@qPS2u~6g?o?q&3n?piT1Hp zc*yl^jx;!Wv?lOXB*rsP8+RoXs=sJy2)d1ZSJw7_s(PQo*n9DVshLKDN|bq*DQI?vcqHx|M?MOWhf^^DfL;@ci3t z!=)9)-|FWuPH@Fq+N zDCNN1k->-!`eoq7`Mi_vKbpV9j9XeGIr}+84r)KMs(BJJv$NRw@jBb9omCpvKl<5t zA*&oYBd>re7F$#F7xWnAh2y$izO-FAaHN)xM&v0eN%92Tju6)CB8*yct+7WUodOjCkEeEiwM&Qq6pJl@2rMA z_3eFyOX5kBkZlPmrI5UM5Rs9bmyHwdaFT`1(lyw&@Nlx1^rl~nGZ|u0H#k6Em)rQz z0=RKrZP@g{e~mRz{iRaN`z<-QeW(;iNeo4cty^TZm|}r77IVd*a?)>CFgR50bWslzVXUVTqc*aNXE?2d=F3{8StKSOh zUqz!NF!)`jBls2MTU3X=R`yDbd|Y-btFNE46}@=nGQC5A#FT1_VQO&15P~b~uwjt2q6ie@ikI;Ry5P^IBK6CCLw1aKe z;+=FeNO(-kBo8Ryn7t1IvMX!>Z$|*U?%d33G0C#b85n4p7YNwMQy|yo*uX(xlRMyIIE57Ybtciu=_g{oo zgs#}_VO6J$a2jmh>l}EVpqBf#55W|EMf<0AL^aslMnqjT5ug69d8uZ_{72q*6Mwk+ z$64212SdQ6`!%j_`f{dT3TurBy08jMK<2o?n{cb*;;rf*{VguK*7UfW9=Y2bgs|K1 zW+sD0m>&RvDC!??kUv5Pp}34CnRAw%2h@R@8Y~}cPrmfuV_qYJ6oVa(0!p9071Ogy zcH^QI_%X))!_gBfsdmAMZoL1NXJYr+;ddG|QZKf9BIV(DeI8@RI}1&UAGhCe`6(ry zEJUbHln-cWDtybu7Tg{OQy*2?kxt%OgA@ik?l1t5ltY2X>H_>%567i0sEdy~M7`}^ zGy#oCgJ6sR7Ld)zo%A>@@hcWiaVyL1Pjx&{z+8R|FFrU}Q~@_(9rg6R#I@v0FtQ?* z)<;|2FUTEAt%(+{1}o4pCN3GdFF*I>M2_5`y}JVR?|6BIirDLfL85$05MiE(J`)}> zdt^%+F*h(PiWVC15#$CytOh7?=+}L-Zfm%-_N6D0Yir2K)%U*=Rr4RlMo7rFeOq&e zh(#7z<*D9L+;;jjq4C{6KYVB)n}~2bu>btqhrFDHiQTrcjlf2&~Llm<$5PY^@+yY5AI7P zr#XpX&J4qOaoyZNO1}`AaoEs$7xhC1{Q+%IhEdq9?uih~a6R$&S*)JoSudE}MDnuO zDR=g#k6-z;eW6gq90j=@zVc4kf;J%HKRSg*AQWy{JBni_OTHHBW=<^QXC#?ykCA`-OIQ@XZ5p^ zcz@x1!LhNvCiqRAkpjf6R`U7vPlfe<2va|NT=4bn$%*LS)p-?Ljj}_09opq%EmfK) z>7U;q>p~xkLm?UMt|nb?xqewQ@%2y>QBDjzN~lx^*qfmR1=*B7TdlC8_zNsXzbw<$ z#U=}9fZFhy z;Q8EG5UWvHSHI9J#^5@n_#^MouDuy8ii`A2Z!CI2?vnsIb?9?h_cyYT@3mkN+6h{> z4bFnMeE%o4??Q{s1&{YP{pp2@fqJ?gPo(yp>*}`^+MI{{gdK%u7X?|?UvUkKIbesPd5}^nN7W@*&ZgkhZWyq>1Gn?n$0K7oK*864+z>(+>^07 zx?_?2dWq}yb@fJK>tOALk;F~IU2%p#T?~%ZIiM=D2(ZA6A+318A+urxfSLEytiKXi z@ByOR4{Xx{A_~*Kk$eA3y)%P8S`|V#TjlViypiudYiktFa_oq}v~0n)1r^0vOn#;7 z*jf(EkCS+=V?^GVws8?&kF|p29u}myDEpqQ6g!`zF>A6>ZZ` zxGS_c`h zP){qZdWY`)2+6rVOL^5(uc2&g=$Ntm01#a;-~FndE4-u<548EfMFdHc(1M?C_p2<^ok?KLD%|PBh~Q#= zl(-OIt>JdmZL3KnN6Gk!5nR;(9UK-&CgT=yIRwD7Mm70!WPOiJ6iF zMy%y0>G>B3%05h5f)vk_p>dYFMW>diE`jG7un^)cu{DGA-13|6H#ZIS;HIPv#1MUd z4v1+&tr`8sFGu;&g-{9pvm}~>v(mm5vi_>h)SAr2-|HjuCt=OaNc_#d_S$2o|E4yf z*pSCnWFozgK3X@Q!UcI8E!4*s4-B&d3kBTwrF)tRb<~ND3L`%c?D;-l_X`T>78yz8 z_6@ORhOK&0{|kDb@>(nBgx$ebpfrl7RmU(O+wk%^>S` zAVBB6`0U-<-Zk70m`I|aOL>DFfgJDJbJ|m0NH$RqK+D?$nC}!l zihN43f&yb^%*eboQ>%)mjN*IfN%8Bo3kw(Lus9EqckgpqDbqh^WKGL_6p!Wszg-a| z{2-riX8`9S|GZYryIDc1D-MWfD~X#iaWnKE6Xzt4U2I;Y)=kd%U|2}Ab>`nVf&0PO zNfn89%6?`}gV=$~Jbap@q*Jmjya0gVOY=_eVBLiL=L^-5Ofb^iDU6$SM8Z#4>-il? z^}dQMtbi6`__(}U!Xx$gee}l)qZ6k7R~tr~0Cx+HgRh>*?#=F@`TRbMdWvx={{NEB zBjkQDn6;tb5-kq~xA}Reme?`0DVX#ExB-eQI7!H?|7_ImD9)ruITbD$FVu&>-Q)RhANhS~|4x{JP)S!2T6R%%lhe!v>=;<@o)BECLK zLoXUIlpd9A*zUL2Zh4o&ixP>25>(5Ajt42r$LWv@y(qdzL35pGWiiYzBw5-tum*TX z(jr^n@e(t8oTZ8_L(hPfJ=;2z8uT`>(Ix<}aCJ$$b zNE_G3`pDVfh7U6fr%O*p4orQJZM0m9vg%qMi~8q>=;D*vmBfIV=axWL2z8g?J9YMD z-;`Xq!%^|_9$Ep1E-m)jE#k#H^PaY>qo6@FMc0%1`!lwgfhQiQBp1e!pE^4noyS3o z%5r2GNyWggy?swVZlc^~ARoKEep`fNOhhM6q*0T4iUm<3A$<&rorA5IL;trK$Pr%$ z4WbT6Q$u_+jG(aixEy_XfOe(({zR|KTIplWGhHH<xoJ#(TXf#qWT8LA9!Y#&YQzh~Zj zG5MwRB2tI_gx*0T#~#}0JAbZshix?M9JyG9xP8Zg zy@-zrRs#nw`wrS19po`%_ga=!y8@!~*zCZ|=}G&t_@8(SUU}u=!H+L6@`@L*3vvt# z_7P#3;y&EDu*Twqj@SF>aVZNT??oVZN?92caOm$!;O|DKBS`Raf8Qql*yKvYI`RbE zGNArQlxMajD3SA|CxK~N>iydHD?e_g&0A6q+NW6J8yzM$=Ry&mEeCox4UI&85nf@)(HH3cp1A-AJD3~gyz|3VOOJ#AYv}8Mf7kvtP+A)p)ZYWdZ`b`4*#*oY0jL zv?lrm{tji@w{v6FZY!g{{26NXJ5;#CwA}jnr8*6_#J|CXRt){;hj8^EDG{;)-Y>3f zEl&{tM~(f_cSMm7W;VdIic94hcz?zSesdYP6ePLRUTDcDPp(aYCzd(@-IeHgSv@H{ zeo{4(r~Apcun-!>0fB>Stcoxk@4 zu2GuCH?})sPtY%xWIB|(K2w#)k`L&vU>H0kM=dX;A=jA$?YD{}*?n!d9=qNQ$+zH8 zVk5!ubavB95(#3Z1hdnfbB;lAAgtQyez@X9Dm5RZDbx;vLY9I>Pr`(0QgquDCEgO- zrYqD9L!BC**8MT!+=|xK&};^ZYs4tvTlEv!tgZ+!U(|RJPRTTDA%Mm|!%xs_>RamJ zc1{NYzYKh=ZiD@ETIdE?Pw{f*lN5r45$Lh`@NvglMuC+mJq8|Hm+<;~aCKIk#UoSe zVo+ZZu7+r7{llnIL^Vj z{5kd3fRorKrTc=D3Zh0j0^>r-yi>!t2jp1Ak>bav`Q(MV&v91Ozs=I&XN=>rd|3;& zt>xG*E8Xx=43!oQf@B{4_LeH>cx3s`Z%rck3I;K8R4z~>5CT*c=2C@2^(*1J`dzzX zNLm<*MXHAab@6`JSJ2Obos*R4IE@ifP@j~w}&kY|oD z5uRl(V!AGQ8mj*tE`>zimaL8r7|(z1r<8kveVOO0+ASEO6~94QO|D0d&Gt`@+yd}= z3|#DR#OWx3Pg3#fXm^36iGLBlCR%^+a{F7X2=`-AbeCzF3127czGXJquzF#y&)H1(`*I!=okaQ|$0k;b>Ij=Z8H@vu*Tuz|A5do?5o-I)bxJ{Rp& zj6h#&bv)#E;9@I|_RkLu7ZKWf?=DDOO`hod`*HZxjHq`+wJFZB@6puGPABV56G8+` zrB*eFl8K#;C)Z9buW-ALTMYyZ`z7HmzO^uuL9_RPg&7vmJ(1>pQ-PK7AX`#wEh zf$|FJNsIt?0l72(y;s5{Z|Crs4XQ>vnFeEiL~AH-2=hVE5_MnFaVup@jy|9}d-2Od z#>h`;U#RS{VWvC9OAd)!jAHw6_t3wT?UzX4K?3~W@$uo50^Xi06#BQr(qs9*3q-0_ zySqN?L7CX~zwYa5VD1*n3jidmMTEZXBv4@Ff`F|V7H(7HU+U?(Gq=)i(xH@v>VbAD zyc?=R#mwO!s>riWC5PyYE>V4S!dN>#(0}kvrqUg=@0Rd_tu5iIzVqXtbgbe^wqiD{ zmwzyEWpegVmBJ{eimQKE4(Vn7`Z+PXJm+Z?&iws90$PiVl+v^&DO>-`A;agq+X!3nlmjaq!~W8{nX z(Njk|MsoXd7zHsX3fv&DvDA_zE)xgmx^PGbX{%9Cbw8;^zDHv4GCq2ex44eXgX?1=r>jo ziD`eDb9pWSzRRO!>_ylfdyNT1n@_&w<4cry!XVcOmAnhcKDL=pYSy_Tcb;F#lsw@v zfZey@C6>(je8hg}0x)GP39bn*W&VWGP1CD=rDO^3h1TO^Byrp<9h34V_{Sa_El2f-5hp_vz1O`O&n+%o)SA^m zkWV~e8ys+NEuFn9J<|pf40a)m$F3s55q7jrBdAN%cWNC0YMzQvAF=NPtj%h6T-8r| zh@|yaVR4|&Fp=%09uwwQMjDm>^TRdb?bkU@D57UbCH8^s@XOXI5t8jT7AXuSKl zJuS>eCeih*Xhb>`T33vQ7Q+!p#d6Kv^Ls0uM~`RkA|9rGu5{D(UG_>S>RKjmUuh30 zqF7Cf4_`>I~c8_ z+^i%eg-)TYGoL2r46B`r+?vgdQf%dVdW&ygsRzr-$ax9$h5FV|FPd}rIB&hISSlGb za6bxYNyo(a(W^I?%<+PfEp4&5sY^g)-2MFURk=Y0)A(4jmY65E<3+>R!N}aWxLXSs zBHlNXpc2g4W$M`m;0~ksH#d{x8gQNUYV2Z2#Hh*cgKUoZVoIBWxHGHGZNz=h&THsD zT#UG33OpQNpIcN|X2f!X_Qjq{#BVTbib%?B|g zi)CmXSXOEOyW&K9bK&y>)q?LA+X&e6m0yoX6(CaE*V*EvVoyLfF5^FSZN3?eLA!#MD9~apCV-Ro*sW6{a&H1-S#HNbZELrve`A&r)gkw z{4sKt1twk;bBw#ENAj$Q9jk;$o$Ea)x-6*JaGYx2cG5--*2LJ zG|M!7X)*6o*0n+T!rJ@A6!uh@CG^@+*9d-4M9t2GNReq1s)RGx3RMj0C_gmic#P)F*?Kr+Ym(3Ez9=GFoAe?$iD)+HaP8G2^pEs38L+ugkYAF>sP)eF{R}Hi z#|^AI%WWh8;?eaA$NE%rZ7Ec+x=imCk)@?%szL0thHq(6tZKq^5_e_JmpH>dmFTJV zZ5@Af`F4f~Yi8}q2)rH%us}wadXx!;$sF%tkMj}kO!bdaeC=baZ09eKh#?8!c<(Cc zmd(1V4I)sK78vhxm={W3%K9Bs?Nc!D3aDM%W|gKw`X^d8~9HO`e}#k^-44x&fC;Fm`MEZak0 zQmuTATraiAvQiQya>GhDjWRj+*PGRT2O@Osl^0dj4Y8-ugOcyf91oi8%u%6kI)2J$ z08f5E?Q$&KhgMnLes+!K3(@5>>AZ`7p+*=HJ;4V0lT+CIIz!5XjNz<5^SSO(@f?ps zM@^sZh`!EKVvOu;()EzfC5+46t=-m_)Cm9JD{qRt+9xZc*jgUX0bhx)MqL&nvL{H) zDo|a$2NmwN0V!~699ztXf_W=BWRYtG7(6ejczS3}z+YNPCzW;jq6lC?Jry@@zeUG0n z?)7c*7t|B3E4hi?44j!d1+}_SyzjQb*^vj*Z;aOHVcdhyATr3Q)JFOtPb$Zq8 zO;r{icG8XXgRVDyFDdqcmyb zZpTk|D+kh^ZyE_bZna=%db>2Y_^ph7wo4Oi_MAZ#dggFIKi>T&)q2SExAi{Ell0*h)Zaf(r?Gw>U&ld-< z`+ar?yGhAjR4bi;SsyMhcDkO@FE0Qd&v|*YAxEm3Y{y_)qNN16=Ud2edUpGBQ)f8m>7Z)Wt=QW27-+7;?kj$BvPvN2PH09nFc z)Aj=H<+h@@gj`o>J3EimcN~<+D2Q|U(^eD2W#l)7hQ(i{u7R#zqTyl8bRXP;nlYqZ zoM8M3oEda;tKhjxj^VzVxLYm5EhGUBZ?0k zzBJfG=I^f|J+#1|D`6rP7WhghkN}`q?fzZ~@wN1T0Hnz~?JSTARU=e}?7dhsNK5); zMpg06Hcg?wqY9Bt!LWQsTE`K0o|j{cNUBXKZa?ah;OJABxB zjaRE%Y-!Ngnv&4W){``Q8aLmUJ^s zu9?w2ul5|j>s#P|eN=`EuhZl5TZOmeuj6ml446Fm2wHX6h4fIP6x}6JNOM7gG=A{A z%=b!re%XwIYyHl$Vd`G@jL&!%-aptC|Cp7>vYo1G83G z&2|(R+yC`7|3NlcMa3hvP1=2q#4jKyehc6Cyh4D$pY`o0;ex1IS1D0tv0xL;JWfo} zQk?$eJ0d9Xm{^Y$@TylJ;bO8Wk$Qg!X`XqQAZUSocc?HnLtRX!aRp1domd&Rf_8M} zaGl-mw~vw2*5xKIK?PxtoX%;;VgFW`R|=-AUVJ~*N{E|b{-LzdOpOb08)zddMh900 zYq_S%0riGon&gel1xC9*e)anbhCWrgu(9xp@!~G#GU$qbobBSgr(o*R(Kx($U!sri zn-yP?z38|xgiAP2QxRwfyUZ??6yc=qZ~62{x~Bg{7o=tsbaTNY_1)~556kaEUz~MN z^!~NVWELDD*-Po|8~rO@QqyZ_5m`a(fgwhMLRJ>CYe5jbFW@T_)gmz{6 ziXp`RzDw$=KlM8nZ+sAylq^WnVLaL<2<=Unj4d@6d^R;r0%P?0BpL@!Tv|%dZH^MU z3P(DP0@G3B;eqY-Yp@L8v}JCUSym#$fkT6+{Li#k@r=O} zGG^eaE3v*p`I`(mvuri>)xd_pk$bi8Fk!8TU9oEqPNkKlB@DFXlQ$dopO;nyX?vL_ z>li4U60K%U9?y;uO?1K)?ur|&E=Keu8iEakF2a<%n+KIvyNYABR}ALYlj9fJiXK9u z3Qs$qh@ahPc%(iNcV+BLdq)2?Olk#ok)s|;{FzarF0SCy6^68g+{SXC#p@t1HniI| zVp~ya8sOB z8S?fxlGh@O+eWpo9DuQ0$B3`a;t%%`NwqC!C!c~d#Ea0>w-P-Q5;W7Cfga!YF1=Z)*j(hxyMY|rzM68y!WMo+8fP>*-x ztW$RkURGn!Fs zym3Uo_cQ)>%(i7;Ty_ilVxi$h136{u2ar3I%m+h{N`HeD17 zn1>l(+_PIRD(*&5HuOzm#L~|b|4xUZK<#!m}qV;31PnyNzh;kNd9*z6Ff=1Gt030JqTJm>r)I-DYkOXOmx~-OhJ)7Y#KStrz#-4sFbF2nm617_@<2 zn|1JMfX}QR%CUJ87TaG}J4~U8n3LRQZe}cZr_zKOY23n~yloV2?@NYv{9dpI32VL0 zvQ)4W5T9%5okadT<6@=WVl!?=@3E?m>QKIdYw^w`8l9O-_OUR@0mpQH770=aE>)um zLRpRjKS0WJii$H~X?AzAM*7(JYw3ppm^g_9|0IO1j%StzMwlQUB@k@Bw{0^zG41a= z%2)Fz?<*Csq2A2;3PoOV(99B54lqd}=o#OA3M2)$)@8rUnjl_4mYX!o&d?6HeIvA~ z8DLL$Qja{U?(eJ?l#1h;{;M8}_;FiIOmTbKlh84+)8gV^(#)w4y>B%{BjZE!nn1HP zasR6XMiG1V->UeHNK5AVoQfS8lHx~WRlcm@ZY@P$AO@~&x%sDZmDI9<@6u?`OrpVR zTsV6}c9g8=-bW5|NM}tHFJLtw&}UlvgR*Li1NUgh0&d3)=x|I zJo6AC;@`1RrFaprYg$f%6f~Z`~h}mstP>nPQ{8vz1q?&z|pldynvF(elK{Sf_*5mnm;@yR2=Z zpNWAhQDdAS9CNMl$9tIzKUY`!89gd1yCnVdo1${6@iH-JNKks{VI=&!i5V1sq5TuvyubZ1lXHL+R>3 z%Hy(}nM1TI`1+aT{D2v|Rn^LYF0&NDQ-ks%NAsZdm_y*TIv_V<=@BW@47A(M_N5SO zh$h9tBvFs*W-jZ9+X2hm*(YrY1=9h1k)WS3f|$L4*~lKuTg7P~Q+H32U&!e*I-y?b z)uevng5YQ}FBqCrblrYwP+aS4BWutAwf<$%kyq4+0ZWsY%4?&Qm3*Aa8gIa0?Il zd;f_@fPWM#FO?ixDkW{lf>@cKG?@*q;q;9qgWa@HXUwLNV`7i3H+Pu zq8a?6^cRVpd}Jlpap{cu@K?|bc*M_k&9{?bxR{RZQ}gV#rRNFNeLgYK#iI9L*DbzY zFCMjneZfR%`0)b&)kIF++YHOn=S%V}>r-0`tK{5;hEsEM*V}c9=V_J$_tZ*vtki~l%SDC^qaK9>VCkER6O-x4%8v$9Aw=1IxZtIIUyUz95n{faYbh) zdao&41taeu>4$TZ&dKh6F_9MOvjaj1Ye?b4+gbXqXI^Wl!6;qBocz%EGiA8IOS z?!3B`m~Qm8Msh4^tZXNq=y|tcq~Yq#j|=4wC3$W`oKupYWi@XCc0`obX4vgZc`%#SYYW3ezQw*U9^uQA($V^+;J2e4^>Ph8hs>QlYn|bxc7wh$U z884nL6nv8R0;7l<{Nf4S2o4dGo=-8-Rd4H^SuU5C5#q+8jDzo}b6dQ<|LPcdX&Hzj z60LKecR#6KyPN0*cDtWO1Sy@5+DIN0;BF5C=ceogp^M{0a{axoUTN_S@@V#I2M*K4_D6>?zZrtctKJQVevq525lT$Qy6&!BfJe-fs3?ljsI#v_FMmz1DS~uywqcO_nP ze^@dc<6F2u&Nz_zziFVTCZi9tAQGx&dgO3$a`I!jl_~xj-9&A38+{VNES^y>379tp z&=6+Eo$=EBocl&aQBZ0fbNA%!q-aJuKM3-N-UjYHS8$b%os2&R^YuKP2hh z&!Gh;gFB2O_RdeFsJG!1w`E=ty6WAn>p76(Sj+=@GG=BQsac?UdTy$Vbi^i(tsd(n z4kea%J%FD{cuNMl1qW!r!=WHw?X-o1?G|r0D)r>+!c%L#3WxAyuDcBR2F+I|F^|4U z)SWfXX^4Ytf&Io)DE)AZ_(?*j zY1Xx`Nf;J-I8X%HLiG%aK^}7{zWDr~AC@b268{KQAl;ERFi?&&0;OygtYs=JWVydi zCpr&FQ&f{cL-u}h7w~5PRH?!$|DU7p4rDw3|G&@O=SGLRwx_C!PfM$%XwBBj=Q@mP zs->~Xp;jVN)DHPxuZmh96h+IaRf3dAjF8-!EkcbL2}x1Z2pJ?H<9@IH{wMGKdOe@d z$9jlgjfFU70#mS3tfpR&Q`yBY3xelPDVMVQ(VP&<$nli{iOI3`+-;CdlthRflK64u*5cKLnk<*q&+|%MJBI|=zi|3t@Rr8| zN3T~>jtiEF7hAE%8mM{YZy1~Wcx@~u?ECW0utaJtzCn0>sXtsIs$T zwp)>BLiM%?dEmD-yRE8XSmr3ARZRcXXQ9prgltwtLQYf8#=7>EDnQL{Cl@b=SOh-^lGypG3ejZ=lJ-|x0K31RDvko=; z3y1oYsNGi_(_?U6I5J{oGBqNrjMLZG49v307W>0s=t9X5+#Yk3JG!}{*rSRTd&n&b z@8}eIcr(k2;>6r5i-+XL=yTX6m==~kkCI$H`llYP)9}_}rm6fKF+HYGs{naAlxjK! z%ZzU3)RmfwGrukun5@en+_7>3&qg&)$mD7Y#Pc z!;u7A9umvOcfpU(V=(kE>Z8&Fj$7{Hl{PZZE?x%g+_3SHv;&KPKO1rUG-CFlS!ZD?r%4oGP z>cVfxgx0;wU^p4k74Hr;4;N>fx^FHIC%BaJJQpU9g%aL%U`2209kSCs&Myg3KR}7g zy6#Z236`f>EltN( z0yyWlhsP&4E+_bxCN|Tk=}`&PO^HqjMR~G?Ni$tvtL|ufa>0MD!EE0$Q-EoZ5MlE^ z4huE^i#3t9G#8svp2p?fBv<4VMb~|epO%<#AkDW{YU^SR+`0YvzQ_nsj&~fvKK_GV z$tCQDCfE-O5J>*$vfz+9XOc>B^I0$U}((p#&gwCxfCPg9)bT#;ubVx`LF+O zJ>+SmG>9xs5r~tRfNGpsULej3!8$AZ=Ns9PeEcy;85j;wHlAONv)egwc~jr=kvrxE z>Hd9#41G@t@q>N+4fUk>G-9R8B4P^sP5;&RuOnlh@B{ZWRO{SKhGb0jzyZl_e{1T` zuQDg;ykFA!M-WRXMK8ktmvMJR4bZ*zwpBHNbAg)63H0k}$oA9^z;-|hQK0Qag67nP zxilt8Jg9`WgpjrX6fvTkb`#F{rQ-Nlo;xYId5bEdJ19QC#F1kyz}AR2B~IcE9^Q;A zL7GIz8$30hzdpb*Q#Le^=uFCS*OX89T81oYa1u`DLG6|kqKaKIsp%q=&%;8z=_|8t z=2BZ`RRFdyQWs=^e(?~N1XQpadjms^kpp{h36QS|VZC#<3R6!+7f)5s)H4C82rvsJ zI@8co7|MoaMu208wO>t2{v`|)nb1@cU7<19Kx_@0hx=h56KLtL3*M1EK3eU3n=;%Q z_gDYZl8QF|=PZYpQy>=vvu4e~pent!;zipzMM-q>vSbJd@DcqiHHUlCot6cth;*cB zWloR&6wGZU%N_`zWwQ_#zGmng#Q#E>c2R^Rm=s5 zs{0M9hNjqJo+BGme73LszGkKI*}ih_(WZ-RMU24@<%a=*)PUz26j#o;5%!_U9e3b? zDD&M8`rjiOj$IOq&Anf1^@%|_x6NJJ#!Dw)2+oAJK! z8E5n>5k`I9o z2Xqa|eLrGrh;S&s&(mD7YJu_kDi_vgU*Cf617lg1{_v7a7q=XE0k0=JD7IW!om!XtQh+qZC;0tw+10CL5)eQ|0ue{~*nb z++{gbq81aW&LLCNTFq!gs?g(8k|s^@!}1#`an+BStvT~||CPV{idc#tx1)Y)tp@K( zASsaRQ%Su#_w7_l_uhXpV>)zA2iF@L7hvcdH<$ZqElJ>ih3D6hU?#hxXKN`4TtuG@PVNR^^0*tQp_#M?o2}mG_dwFey(o$tVL-! z?z*tq-0DFST^|)@w%u4U;BopgbMFJ4`s`f``v9%hbMJ#XV>$n--IwH$2{BaFG1aje z7{MOf^>q7c6nufwP7h4M?!VroCM=`#5y{)hXu9yM^A7W7D+P&^4V9{*d;DXeoavX2(3Cbv(y|Hjym43a;g%%H%1{pVjv6B> z@m!H};!nbt`Umn;MZtFazyx8X3;T&Z%kKF&*U&j;kXDh9j!VFsTG49yai9><)sby) zW7wt)ZkgC~YKU)98;D2B@SWNV997}nkGp8awUEG#r3=1KM(7mB62~l%Ydf4Sg%}JH z`Nuuy_H@2vcytiVF*A8(=lkxK9xu>-YtKtN6ZjJd5rUyJ9F5Snc*`d&zRRpItohTanaJ~zr_bPpq*UfDFByx zH%Q7B>#5J-%AJn9gj=no=|<0?Dt6k~r`nFz5heCNU@d|Q?0l6BjMaW2sZ z^Qy)wyo!as`YfkKQdanxG32f4?U}f9JDqcaS!AjkRu`E{!Cx5B9)-8ONTq1y&VGUy z+GKA73yUQr+PLs2KNE{SG7>mE4RlPbA`#y4}(b5CB0nYYO;y2l2Nz0gMBiR?p zVGZNpn@LYTlA07+rkGO>4VhX1e56xV^_)f*4E``?cHOpEn-aJbEG|NdO=LSr2}!<1 z|LWT^Xs$if=uy4Pm$S$!SeD0r$|C8Ri2WnxU~%Zxz;~0K>@G0esWAjxT?iTPtOp>s zqR%TjhJF9#rDqyJbN6yUgvvtW=mI_^^vu+o$H}g;YJfO(Qkwv=I7Wv)DK(iSl4%kD zb|`4PAaM9OzUhUgEzA0a_w^Ol$c31#gDpKcM{=O76J}*SzWjK{KFhsu+r(~)>_Hh- zR7ucWxNHX?JSjp~q(H8ky%&xL5o^lhp{*ERcBLY@Aqgb6VIeB2LHzZMK6dR? zOHEOP^w#M4Wnk3a?y#WTnv*jY4csKda0->{_nCE`n*Sm!WkeRAvHkvIN>+dopiaIx~|&8G!&y$$bY*)_q1&=NQS zd?r!zckfw8syQDuXbu)TZic_h_6LplWap1+1Urp@@M6W3%~Mgcz<5a4Cwal!Q1x2M z$e&oEmv}HYU*GwC&)+f-tZ56jJ;M+%c7kWd2n8s9k`fY1mQcTN;O}|u679mE&)YW7 z&1}#>VzL_v98#b>V{2t_JA9>4R8}Ko!IS-8s+n|$31F2kFlnW|W@~P#gGEC}%}Z)j z3|0}OK^<^1T+JV)^R3X^ii`bwzrR#y-v6TY@&|sW;mroPUeXMfdlNkyDJ&h|Du(<7@URH! zN5lzTB97w;DpfkF((vZ|#!~Id%(_zCi|jGTyLTpEZpsxOGgFF4mibmaC`4^_>$d4R z&jRMKWZTD8$9gKG=E6|}$<7Iz)nVL}x<8%V}WRvtX|LIu7tE51f?Tm-NKD*mct)@r`L>Zv{i_dx?#44w*hGUtPYH8OW%wW3yabK=1Qb z9Pmbr>NJR{x5|7yS@v5NV4irC$lZmxv*xP?j#cYz<%eD18vyF}S)r8L^bj({# zCosFa(zbeJ$U#kEh-;xt)eShIjt?2Jq9m?rS8>n>D21Y%GTx z)XQ5V(4#L)kUAk}vaU{i*b^CY8W%Ob`yxP@j`Qp2JuEjGIx76gZsh5PCLB&trI+6n zv0|RB@Ws4g_4jT4Py;;=#uVH%mf_v3Yb($P8+uHP+`^|zqBrZ~@bCSC^a@(sxxU7? zIku-kXLv%Ri%40=v-SY6_IHcH&+}_dU75|cD|5OS7E)(RLXMvPSl0YtG#njSAJS_6 z!kpIC%S!BOm@e!%K`1IB;dG4=V_{6W2sojt+@!|+f_WB3ovnOSMvQ7~sFpez`FIT& zj|Ue-)a0F*5$<7o!V%ZFI6VE!w}7XU+?cVx0o}m=#bJQUAWKP*YFX!dX7N?Lrhsb z8U1st#xU1n9d5SYKp#k{psA>dpHDnJy6ALg!?Yi}*kENnqMF(>%y~X6u^{qNmiGei zw%qCeLlN~Z-`%~R;peY%*Vd9@lSSH$;h5w+`pBe7%8K$g+UcF&DZK8?(g2-GQd@dD z#J~vvaA?$n_Un!>Hy*>*1@xS5308Q{l@-yTzHBticSySCl0R3J**+0U};rf3=+fCiI*O?zX^Dn$QI&` z_`k_;a4l3c`IyivfVBYP7j*-uR|sB@O)vM9&)pI6_BN*^XMhvwUJ*r}%9Nd(|e~l6)x={MKw6bL5 z6VqX#p_|K-*oB`up36_JX1{OE<3LaCMVJi_5n&W~i7X$Vjk#v_y1{dng?T&Ov>gB^ zgNz7^PfP_}$#EEor}(U4dy{#ytzdA`qKePKkgM}Xk}CoO_8y|Y;tTjUgUkB%8b(F@ z!SI!<*tASp)e^^VMK!-&fM>V|W}4!{m|)(EGJTJ%6DJ2LWM>iGLe)x7bOZ(hYZ@96 zlq<#k$ZRF1>53C%M#$oR9p`tLS{^&&!@G4a}k6)yUML)_@4U z(Hz2a0zF9oWl80@C(Hcx4+E%d?xeL2fr;#LDnjBCORq4a&Ntx_8~erp$ly8%*^7Yu zC3@fd;<3jlZ~3pbN##H`6=rEsn^?Lg(=j;aW!3*DUhQaFMwO%j$IWWF^mrFqW`Z(H zt!{T=CBa3w{IMm7@3$>}UK)#4n=%0+s_JB+s|){g&@7Ek2Q&tfqT4P6y|PykqH? zhiF!qF7rRnt6usFGJ>c%By+I6tNhan^>2NQTROT=AwJm2aqrOkx(Vx*00x=*$z(-t z%@!u#08A$Kfa!ig8Bf)VM2BO>)&=Oi6((6$CPb!)e?Myi2%sHpO&Z&VR(G_hGZp0o zF6T8Mg9inTdi&qW#gyrVTYnc6?5diyI^UQNT&A5*3Qk2v-u!HR(Nt@eKV|U5t%2J= zM*!EHcIRQ)cc_3^6Yr?+CDeo{FF#*{)ZGoMbNYJsxzxzj+Vk8wBO9hQqQti7L@)Z* z(7E8a_f4|ChNYu+%dUT4RGWVFrMz{kp~PEX$-6|yVWV=+tLoPym1e)p!p>lyu26J6 zsv7WHV@ZgVzf6;oO1gw)1w}l>+UM3;{z@a}TE6D^%>?C@+uiqd%KE)f>I^7z!9!4% z>O%GBB@df^T!itb&cnCOzIv15&Te^w*k=5|F+dECd&|62(%GL31Z_Z4FzESO>8$HC z^NzJbR|zL)2qM+OUMhhsmlaUWWIMxD?y2mBP}8I0x9*0^I_GvI3vsyG!27fAVvqqcJBzX zO-IO4jk(*}pkio=5!S;AjcE&+ek&~b%2MxCjB-bQL-)|>;f_$9cfCWRd{~8x%N}mT z62gu7wS({s-83NSn*%ViOOja#DIU^|J+x5_OLzMX;WZAojvUPuybeeTM^pu|A?kG?kOaR{_qJ8^0>%e$Rm)Z)6 zl$qqQLrzb1Ct;PsHB^*`KY9)&vd=|M)tnrdH(#54Q5mP*b8;cC?_gGXwkaidVn<@q zlsrBg&A}H_PQIq-fN67V#c@+C?S;3syv2N1dvx5x<2_aD(EY^1p+YfYvP326 zI`NRrV#l!m(NlA+2OQMe<>naG+1gF~tI)dCcE8)CoK~Ci$0GDn-_boLL4@cYFtV{i zv=8t3j$jrfFb^+$mcg-K<^VkalP{t1Klnh={u;s;2BwoPX(gikH8|0xJW{(a(di`i z@rDu}KuT^Ke|&s6rnhTAK#&rIz3+4FMKEeIZl&p%Y;Wtn{OIe2x1Zal8}j^5G9SPI z!xI^m_&aH=bRQL&{Ku-dy;)Y+1UX5qnh7nXe# zk}8e+&hob9>mOJUs%%XK#|&tD4qaQpDqvVFkwBj*kq5|Np_X*dn|9YbXoI!&`obIN%CaH+t>i=A-EX-iTZp; za!tj*gW5FLAieWdtMXUUE~51>&t0g*TEwlJo?UoUM>=IWX054`vEO)wVVmU@YaOB) zlxzyxt+3`wLh;BA_5O26z^VFa-Gvk;QQdNVE^cP6+E1S+l`J#<`Nrze5*XM7ZL5>u zuWq+?1f|zDe3tQz4(3|fYpR8lw>WsX*q@u!GvILyDm2w2$o#6;--~l3=5u1}9*Mmc z@GqV6Ztw!H*=}6iVic$^KIX#%!;3XCEN@hNpx)*wOah;g2Jg{lSj1?iTy0>+GV;+N zl~ow^$V0J5hVFA!zxyPEBd0^_FdE|5f4)zeSV(_T#>y7su8#HDveLRjT@EA=teQ2pKo@?4djE=Bg$S_qlB6v`OriK@B3!3DrSxp?bcFtjNSV6;)6yMw{ZhnThcN$N9sT z@%iVc64_>8oZ`8NiiA#LEMh`aXXQ$B%ox{ihee(~=q_T6YfeT3M~8LA%JRs!S9QFa zv?leB-=_#jiK~16e8a$F!Eq6AbNMv;aCuv^^XanV80+ROcz!g?_Nyo&VFh1$%Gkw( zg}K&A9bf9A?<5SRySGec30dp&qz|XZIBv6^;%Gux{Ug3?xiaK=%|)l>G+EKQT#MV| zHGH0qifL((cfjB!^6$N3GE7Dl>V`gVoM>dvySq^HK{X4eE;f)*z{~`Wd1g!OG|gzq zxPC<|Nb2%*p>knpX5+vk$Lx6U{SdXtR3T#LavR1(h5d5RD-izDPjj#ydrN+Wm-5WA z-wu5y5WSBe_99Mg<*%A2QjW?uray&Zzy63z0NP?P-FllcTv7sTW8W@;tFB0zz6~Y} z3%+3x4psu&5o3maylYuAxOnx(7YIewBuViK`sjZmD|6-*xi@DIlXS zAYXsQMMnWcaE?t#EoJM;2?A)^akxQ|8CglqUJtOniD5+h<#&Q(g$x*%rH=QED|C3`s>Rk*=n(Q zJ`mnL@u&-VUJ%yNnF|)tfnrMZH6@L-VTn>kA3k~@bxm?MZ?)m1(Cqg6R`v>(?D0;2 z8DC^QaU?9*LO#~TYKdyN9!$?$uBWMWlGyy+>UF+leT$8D&=uQzMW5lX*Xwmx!T$L# zL}I_trA}DCfhpsJ!Rj&+1-ba{hhDk^8O4M{nirt!RYgg=rt?W-acWJ;=`G|W56^VR z=9d3awyy;+2HE;_kL`+~k+@@`Y(Fs;y#yP3*ac|i*4PhC3la}d?_reu#v@B%&Zz^ zl-No1X6v)N$g(=746i*ArKb&+q!!&@T0MvYONb$dG4xfP9R+NIEPUi=EoZ}*7G!gA z3x~-ep0dHiS(CHYN%>&iJ*@cWeL2@)kR8$JrIT3rXalCKGlN5&-@uj@8md*F%N~+O zO}G(=jr+@ISPddbRtM4)+q4a|n}nR{XP1UdmoJtrynWnWBMBNw@)&8O1mvtkttCic zyV-LOb+<;(`6DXoVx#d`*tS$@Wc`>`{?aD4pq_zrnQ*VuhI{-q6;$j{Jv5b5bMm!V z`k-#yWJl)5!!Cn_q7kIS3PRwuJ(F%QN@}RjyK$=1@9laHv;%aaQMfmytD{qe9Z~8E z6Fa!kBh7GeJo3r(9g^z_e%&7GpKmVFTd{E@upo6g3+rL4`goQw6<=`FwuZ|(gFY8m$a@FY;Fae`9AQQrd*>S!_4*?Z>YM!`;Z6=i?qLA}H zx^?owZ?`stl|l&HfmtVVu-gEyi2#S8RA`G3y?d{w3=32$fXw?zrfIfzCPpLjO&t25 z_(UJ(y|XC7lno~Bft1JNch_<(aMP_x%whwf4RK-UC93F{;N~;efczrQ<-Dye`6({P zEPfuV$iiEg!#TM*UmkX{oinrghf|{=L%k!leG;tnd~NXtOhcCMgm?o#wtdXv za<&NP_P+a798~7t>+EH#W6|)aRe}6~&6n*nI@|0kum%m01f#}s-~>~#s50$ABmE65 z_*SAax+W4COhORS1l)mlQPn`*?w9|)-MXc&Df33$nec^q4<7r6 zFr9N-((^mAne;klQKQ}?5v8Ce@BfmZai zNDB{^P&YF2Q^1`K@CHd2_T{ah7Vj7Gp`xM!#||KP(ls%U5M^wHx=0Q)%+kwSB&OiW zvipZl)eN283;!T6NmQ#4!?r9n>yW3;=U1~%MkSpT@4&0cgfsVSCC&#BqVpAIDe^f_Em%d`Yf+<|5q03qnl)@$Z_HzFd&}OC#0fs&C${E_N#<00`{p z4;{SSk7_)d@JwQhJOLixC~&hcxj{WZmRpu=O)Dg-wK6MWoq|G)rA$0TXVivr_!|6K)Ic`JUUTfWWVq9W8aF@+o*& zB6>pWrl?x%;4x+5$~!l73w7j=)!wGPjNw6?sI!ZzzuhI@jh}_{tS0(~_Y#ZDGV$e; zmZ-WprdIN)U22>rW|*zNf-Y#os>T7Mnp&}-rxv{gy{^*vlBN9MpKomUfRCT|Fjc%8 zH=Wt?LUNBE=mcTZ<7|9bP8QtVYmb_23VX>CP?SN*g_( zsPFlT-~V4)FrX%FST91(6dm1&7T6{zMH1xu^(ARJ5A}JC^!oMtFQ7}Q8C^4_Sl(@0 zRYzV}1O6HRfbpbb;g&0e=dm%|cI0T1ELg1UL24SufVTr#e82Dt@tTKi4Eo3nKe`p* z8$M9pDMvBhU&YI-t&rhBn@po{bZGV&5$6(!gB9sq<2vQ4h%k+a-5t zs#SM(n_Mx%*lSHg)skr)^#y>%eTu^vuA`5ExJbenCTd}lI^l6MgtMgPERX4hVt_B9t724V%I`1=NbUViek^3U_oDarW4N3- zs)&YuBGTdhQ^=_wtrV;NI)OeKM9%Ju)C1;bd+95BnI&cg>^_ZcC07}}9{q#3 z`0o}sUsm1FG1+Q$(i9_MjiNMR97D>fgsXUeAEJydp!yO5GF`>6uU4zeLUV)X^_xB2 zc~>PvK8@#{_CNexXajM!nqsYwEUntVXk{_IsC}E*Za_;tD;@HQ3tGY}tr?mzP?azb zY?}2s>xRlbGe}$>0_UQn6RGxK?G@NCu_b-!gs_zYN+zK=cylou%XJ+oJ1j?^_|FWk z9k*6urNned@rAd;Qc`gag^NE0MYPp&7K`l-?|Z!LxWg>;!w?&47z1djhKL^BZ#iIG zHT>(5;(xxGW4b`|@c%Nyafr19i6vq5b4_W4loj`0$A;P7kTdiEhs>~>rKo$ zfh|3i_u-k%EMXZ@d-HzncA1uZa#|sdm+tnA@%@q7FhJlcp)EmvD*4*Vq=-~#?=)>v;-*q(G0A7_h5sXpp6M5i72$DNyd%p<7t7Z3VSOhX2^w9o7V7^vbgCk*_{CP4 zfR6hJ2@)qwEd6xzH$oGMADL@tH2TEo7EIxWZF^hZ#qSdz#O*2O);hCta`ea_G`7ZZrlrr_ zj4h{KYs4tgSxXBj!r=FDJLW@Oz^e=voTlp})D(GrDSenpK+x?wtq0kWQSnd96j@ig z#-b;kV%62yT6&%~&W56E+4^l<**bm;)kJ#h6=I(Io~>yH=#9FcW=NX}p~cSJsSz8t z5DnxSMP-+?VlfPFDHf8;2B{~Y2{~?W)|+WZ{oxk^l*)-S5fKM^ECT1`KG;u6+!#(; zn2@U02@Nc99h&rYl&mP>k6RXQ9o>3p46GgEUX+}e!=#IJbYoc#O$Tq}vUQv*vqctc z$qUZ;>x>uJU3&ENhi>ySS0~GNlafgJ0bb=B=|$f6%Y(W<&>Nh-NAIr+T#5EovyG4l z;(|ugW^v6k`2n{3jHhw`lB-J~484#X&G{N4S_Mcbv8@qrLY&Qp;8g(;8JELXAi5*v z7njcYH+GJpswY+)&m{%p7B#Yq(KDE+h@3ZX=h*v7i4h$&8J4*}l$ZjdAD!9)`+*^O+&FGF2a3@) zWB~8;%CeQEX_OPpU)_K4b@bR~edB%M3ZyV9GW>n69d@oUyYKtY1ZvLJd4qYh2v?A- zuJqfhu-oE{&^Vp4KYiosoL0`Zv4TP?Q1GqkkWb|IkGGGApNyq7QrLV*()Uv> zcG8Wq!)Oq1m(Q{N?qX;h%;-X2!a(M#6WDsyQLXYeqFn#5Ub$f+|zI4mhs???+q@s&sC#SLX6OOYJILK+CHL@{dWh+ zbD+4pDHB{aC8Uh|&Lmm$;Z?aTYCyq(b2_5e^@VI=RYi5E?Y&%QiijHfbnf2d8M|%k zyNKOaM)oH!9txyhDm=3vt$uF9UCpH=T)Rk{jWabhGgK(+aW+VYNOiDJk*CD){S+tseNT=EFtx$CSr0 z4#q~899Lw^Z}|Is{z714Bfw#!8PDz59Gx;w^F(DPXJ)A(-Yu?F>2}gT-(1{)|HSV0 zc-_H>t&<~TV4he4Q#yWUuzpNRE<|kACK<)rY%MJapIxf|T)bDRf>w^9shV_Rb?|@{ z)G6t~20GND8W#l>#d?FoObiKLgqx8!0zWty# zVtL$hPG4Qg=xQ&w$WnXp1U&C%8(IkE1-K&EgN3ZD>R5^acflzp2O(jPE*-vEeJ z4(-~%i0cWSm%?b`k~{LDY5h%&$V*7U6mhy=&jt04i6JKebK7>=4VQM__w+v5=>Dwo zDq^ZkbT`yiTR$1BZRWzX>WwkzBJ`N*(8V{%xT&S+8ByZY9+vFW#MQVx5oMruK5Zd& ziTcX&h#V4IE;!;+Q=JoN!~Kt?Wo!O$>G3 zn~Y5cjwof9RArYjuh4+m*JXasV2{d5CAYX zLUjiTnQgR;E^R(_F$S}<>l!%wtcII6{CH}Ax4HW(;hT|6C-%-O)n%6E#XTZV#K=VU z;Xx)iL&)$XLyaa8 z`95hZEUQewjFCwYi{%pwr!ytUKpt<~;sr%}W(M?~EyakU7K zid1_^w0nSy`&|y-3$7o!du93Mx&udf`%+kF6b?&D+$AKx$)m~GwAL*!-bc>Xmu$-a zJ(YL6J!1ga6UL{*X4|Xz3+O8pA%~g}10)Pt2S$P0pvdcn`JbPow`o1s~BRB@PtWj;>tE zT#RI$C$#7F7RnzF>B^d+e1jqKO8xfchr;N8zIoyLYoo&|a{Bj)K`^uc(j~Tzlz!L7 zCW{htTpFk0{4`r)c}KTF@ADqd=|+g*+ndo13gp%YLkA5;?++t4KL^x1hwZKL&0bdN zeEztV`=^8J9Q!uK4`KVFTniiY`^p|t6AFHKvJJ|%LLm?G7#*9y0Z6V&jP7K8p|TpT z`D+&3H%DR%)JjfN1$$SpojsX1z$SSFF*viAvm_1{Uw3>l$ox!5WaL!mxGpnqEx#)D z$Gi~l?42-=$i9qm(nXA8dkgl|tOJ?@VIa30F|{}{T$1SD^QcI_UgbX>nK5?tI8i>8 zEC3D5EaDzek_rH#Fk=)Z=fpL31sQGJqcxQc6LaDDl=VF%5zCvZ`#m%G6}xCz%Io19 z%+LFPnQ_cRGsY_hY;jIj(XE{0Zi`@gW5;5Wc-UuFgS2)k84mH>%=;P412>Uh;7>>$ zE?Eo~F>WCh&8hepRy?)fAFKt}XAgxamB`(<&?R5}&#yhe#>Tqi4c=X*7>i2<5i?MM*FE#=jvnMB$%*DSy?(Mz4=k6+D zmS+}G=TU6ENMW?3Vc^wsr1>}?DdkM0e0_FQj>4~=D{VA0$@S%jKaQY?=WEf+TQe?i z4f)LODa-eDrEBA2tYgZ964`k$Q3xcXfB5naRNJ&ejmsc}n$NVl&Y!x`Bm{%44)`JQ z6J8+O7$7a{75BQUuH80QPhWCO%l1EeLwz!!7GuQoJGq250f+^nbECIVgW-BxGSdv; zgL}zg{&}BCh#mjb7mn7|DucE}vy3ym^Y_m)+es7UT-9~eYKJmuQYZP>Nn)23bu1T3 zjc;v`#x0rb9X+YI?ULJYyArJxu!$Tm>=;I86d&G)^^2lFDyIvf^LPcV{$^@P4tDk} zCb1rQYWLGKxv69q_vz)X_laMM^j-q}eu>i+VNJtbn7?A|dJFsMJJK|}t7Ll%Z_G=6 z!7#`&(bKsZ$lr!x!Im_&Q>N~7eYPX{1?cc%wp|Owf_w5QadN}D%lo&1op9Y4=?~5Q zHdoTBPdLBGGP{>NHIE_Z_jrXdh*Pl_Lm>-V6Y35>I2y7QR}JgJ_)JlzSBsgmZsHRp zGA6L_v*7qP@Fbd$tB3;y_Ts|wnpBLHYFFPTg2w_;fp$~3_FU2Ppy?l+iZxg)_lG2F z0)QTQ=oj>nFU56iS;JOmNR(b*&w2J0Ea5R7ZXhp`HV~<4(bKk{*oS8k>MEp;;%>;U z!&kGOzmw>t=O@tRV_T2)G&bX-%AW6j-IH30! z7wel$s`pIdBq#-F)RRl2)n64HpSNi6U)X-OqDZ0LFM^PLV7$nM%x8IiBGdO&uFeca z%&GO6i~D)zj;FlcMKP=MK0fvjXwk}e3dBnpMg zDm=`vs(IbIHT~ZDJGepry*JvlmFZcQ;>3KX(Rb1+X;sx9ss6^POpdy06kH4T16m)N zg$(46@G57WK2%m--Wxqwi`ZE@KAL&sAW|y;&Wdy-{%i}}n4?=coSpejZIjpGHE-rx z=0p0mY;J8N8qeS8I*Pcu^T-gAo_HndA>qM=lDmTriQy}Gt57n0YobtFD=oVpgO=D^ zv<~2pUH?)uR0y~f|JMzKIFDEt(m&Ak$Hv@!-9*ztl3QlN!T}8>FL%(!{jUa8(?KGn zm+N!iBD8@#3WXmXYT3s-6L!q*3H4*zdd)e8ka5QIcon3c1` zerm1$EWsq1*|Uz<5V?a%JIFKQ;IpMBXd|x>SBrytg|`7pg)Kw^(fq@t83z+;cebL} z94DybBWBi9R(n1~6+mTp^mp=Aqg8VsK^RK+QEUCmF4-Z6awb&Os@cYLQn#5dPbBJL$J4vNzHWmsl~XYK-k6f5s1IGlWv$ETf!hdKLhZ zqlUUz#lbq_e#JRDafOzOlQ5(uvg#mDc1EfGY-?z#0p((=yu%Qz&P2i7uTtYg$Pw%b zTZOaT?*xXj!6s16qdXrtAP<@3CayQxQnyX+<*GHw_F3G+7ftJqTK;{hkhGqG7hvo6 zaLZpX;nt0K@&TirR{4Q#E@fo&(@Cfw4cdb=G}zXNnTNT6cV-J8)g%sI*xp6g^i#L0 z;tDr)(Q!c%%US4Kuk8Yqhk%AI+15qjQ3N;7)wlxc?Y|jUW6N>^Vdr)~*p>g-15v2g z&zbF);!YVz zF)r>I{+maJpSMuj2jhdJ#|wL=)X#GLw5GzFm{Qm}mMHo^K>JEIQ$E{mZ0(GpgUy!f zU{RU(E8hp*(ZHYn2qy{)^pg}=p$w)UBG$+KxAy~s;UkLwNA;8GGara&3MRVi%YxB` z0AZ~)hx8;UZkB{3zl!DK_#)vsxWN+FmQmLVHvMwfjnZdA_RQtD-?4N(WWJ>3b7Z)Q zy~J*2Im}vh#t3bv=_pq4Y~t!AH^#hamE6wnN-!%V2QvO-tme`r%XlB}(L!Of@K?x_ z$JHs@c$vT_Mq(R#eq{O+J2lMddl~KNaOPKta(jiBUpB|~L4ziv{SxIHah_ zz&6uIJuF))qkcOFX>f+9blx}A%M^5ASXe-PNyG|G-W%vR2J9j0c)x_PG}_rfkEE}Z zCo3z$<-(#e1n`0-t93pk@^4#NspctV^e!Y0H)XBScNqJF)DhcsCl66@rFwfyI?Uex zb~=wa7w3AQ%US@yC1~Iu3s$nSArdN{4cd$76M#8V`^kUk!K;V+ z_PVnz5iZ7UT(eYO@ce=)BizU)cTjZ1x@PH*--(L9C;Y+|6?FMS#k3`w2?;(61wfQ! z?r`}j;5T43TuaY~N82{9v%i&ItF@8nRWv$!$zJXx^u;)!YGlQO=P6XkJ#jY3BM=8q8H2{lmn7a3>v(oW;Pnta9~% z_RKn)3E^i`Vt^uo56p3jY)=xVa;+w7ob84+&{KfO0RKdV~uYC#$}9 z9y)UrSw?S|51i#o>0?eswCj~s+v?ZA1a$sYE;^B_=hZ|YkkEMrVCgI+;mLtgCt1Fx zMiTYsl^5CU+Oeu*-XHN?%%t8B4)Y`#8Q_KXru!h1=U?3R;SsIf`uj+2MN~S^e)Y~! z6MOk#Kwur}F_;Kf&GG$FN3$tPRgzlGKPYg09!s%H_>6&biAr~!2^?K3yO7F#C3A4!v*rDPToxa^`(#8c)THG1+D^*C7$-lBQ5%$N%*_ zoh_oc;9Z(O5;HYy-J;y{=RH_UKubqShGBX0#AS7bE8W(dw$v5dT-#wgZfk4Ea*-;^M~ihs5HGs z-+cF^QT;*5p{2rpbPD_g^`YlO9w|SNQPqXhYCVn$$^j1l?0AX-kwPNoG)B1>Lgv}- z*qyi*PN+hQd0)4C&6a-~szJ6q z@48b2-z@bz=R5BOHQo{^cGAfUvz8l)srg$rmhUng^J?@F%{fW~soKfUZTZC&*0l+b z1`BPS^M6d*;kEO_`I8m6~$eY|_-!)XDWsPA-`_Sz?OH zm|Kd-xNjh5rd&(SOifA6OidBV1#m%_aZM2&7bHa_H_8Q2aDiCn_xAfIudB;T1>Vo| zKF|H!OHtJmOR$zt^rk$OlNOUNKgG_xN`VVf7w~FFdIR)Iel80qP`NpiZXFa0su5`K zu^)kg;p@pn(xRf$a%~TAeOg^ualHRqt>h${`T08%2EXcGt~7bZo7ttugA?LUT1Zi& z&yoNm&x=d?I9jdV^tIa$%3nTi1c5CbC}CAz+-p{&m&Pmu^-vnn?4)#3}AYQD+liAm>Wh z&SpQ_&pac?nn!}?WpFiZaAgQq7`{2saM;k?lOpDlZ<-|8mC_fU1*Rta_n~;&BYVN4 zO_4=UBiys{IFV}T052Trs#mR|X{-8$+F!|*Zuy$sakSF0WT_ps>rb3kSPFTkkc}&b z+LPHHZj%#(zfejch}M>Bt4#&rc9SuIzMz}GF@(4v_CtY2%Sh8FF$$R4;A7TC?U#9Ptn-%mp2;{sIK(=;R3dPrPdP}s$(wpD8R z=tR?)sXY|zGe2pj!vAO!SkTngQNOOo?!u39avK_Gai+3IJd=42DHtW^QxiQ{8ng1B zBvoE6A)p!W7t2Oit9m+e~%v?qRL zxUlG(*RO3R-@|s_beX@6v-i!LcN=SuNMaqmB5}O)&lg$qrhFqpnXBIRwVHSoDPObd zPz~|~Qhj&|&QR;83ll&O8v3k8<5h|gX*(%arGyq<%^3CnSh>gaYwj%L=6H3G{hShC zPLCHbe<*!3XNznl`B0|H6VGw0hdeIT{($iQg`+{@J89%ok6F2zD~Ds|&qQxDNKihO zkr7X4-OW}Gm*oqyqUwQZZ{o+y;+7}vss5*LW%^A}IIb~!zOe>_2#KZ0_$pkHicGNX ze>MIwCC6sN=}n<>jUNZs2}tq)b_}PlwNl&5h8+wR=^e_tN3QgC-^7&HWyY0jyPLR9#K|+nRk?}gNFSY8 z=RF*1m~JK{J`2T-Nc3iAZtzj1s)$|q1IthLRW) zn%2C#j!QOZT^ilS(o+h}2QF-Lx~Q^OzTaUbH%{CC(KH#a zUIJKA6&6VnIx@xd(V;`(lF|f~I=LBTa#ujO7pHqJBL95ahdqPA*{aAiK`gW=P_FY9 z=R+29y@fHyCD)uENf!rZsQ#LiVQ(zgcSrr8G?du}j^5uaSV(gDoJqan%8YmcP#Z#t zk^^xk|`TkO7t$lax$KTd`BQN#?XwIqr z>vb;<X9p3C2&o|LBb&} z0aA)0m7svlbfy%+vfa0M&R*+xNEGipVlHk;u$=t;+U-28Bh1apKc^ARm)?Pio-~Gb z-}K11fIfHbouJwuSPl9Ytt=-V7G(tZc2w&5&do^!Rv-l}L69~-SAEJVD>!%7VFA=e=vT}3 z8VH+w8?RE7=8Vz86ECq=+TJ{Yn0suf9v!@O?s-Dr>^2kp;mKb3EGj8ON6YhA?%=Fu z0&!kWfJ1I67oAz2s{Ma|EQ>1ARpr{HFV5NKLT1S=D!xaXm5{A0$HV>8IP(c5o2|Xt zUL&TmHy@+_T%-4{2y^LME5uyt0h`{}J~MOr(8V=}^Cc^@3^O*HxA{xG24uf9N(WU0 zbLUAgd}#O?xboZX4Z3nT?Dzb9ImUeXjw+m^pjQA2?~nMiDrU0DQUJVw z^FrOQ-%%XE7AfB(Uo@)dRnEzA^1HLM7S5bXkrzidqUWlN?<>)Dyn{;=hK61$i|S5l zN&6HMsM^8A1*31*Gb*2LBNpoB&SOi|yy7_0Agat#&=fOxJM|gZw|r22>DjNw7i=;q zs4eLD+^91$nE-?Jba8Kk54OR1$uM{>PoBAlFPJ(*Fa3I~sNn$OH-`KJa!S^5JvnV0 zTx&hyNSoyIlCSIQI-Mwp*MV|Yzt5^wi3Td&-XCb033L-L(rmVvxQFlr)V0%u9Y%4x zOWLorG+r_NVw&-sVN#tB{XAWucb0}VR}xL>(gx+#{N5JkB`b3bNS`Zcvc;|af3Io%hHN9+T`0TLElN*J&%HJNj z8%viWs-%gSgZBF41%hW*yH8`HxMDIGuom$jE^Yxm%d5ufjaO;4X>YAthvYV^KkUxC z4Pi0o3PE-=60{C^?D}3zEJ~YR8gN@jy)a|3nfrm@sp)nuw2RM z|D%h%8Su?t&X&0))s@=&ulp?3s7B+Kw`I{;>)7|tKDEvap8C-r-$^T1){?TK?A3XW z0DXInS|nyW{K}2_;9mA~x@3>G?oC6dY_XPkhlIbDh5kBjC7i9^Z?dZ)(RSD*97T`G zPw^b<6e(8b=eV5!vK_>4?|Dc|1N91{^8We4>M1>eZs-s?15q8FR!TpE`d#1%af9N` zR{#Fzi&rg8vmb|RQerMAM#s`ZrTy=!PmY8bt)0H%aH$;_q~-kBY;2De<8 z^xrHY`lkJ@;@i7c)SF8W#*IR#Gh!mMqk{IUvX&l+Qje(EH?4pmPqj_L+FZI+!nIxE z_a?goS-a|H<-;KS4j^a(*G*iX{g+$uV_Eu{@r@HgPJlg-PCKhtZKEC1tKgb?u|w4B zW9k{p%0-a*gx%KWb3Wvf&!VLF`I{RTI|W?(wGW~5&20Yh?8_d{lqpXGzlkZ{h{Kw@ zmcX2Iskqng#W22{2a0wcyXv0VX$8auoz9D1w3N}i$=VW_O`VVJ{TRlHM_o(sPS!{3 z>)mgkWH=~lK{DJ3fn>`<7<>vHQMR4^t)t}Auwk^H%8u>wH%W6YNB7+`adj?$#A zpM{w0A;ug+FGF0V;bART|M|iz;C_75^~MCdwA}PM^}r+IM?EC3oPsd~w?T8ocn!K|IVVS!(LJ)fo@JQ+XtnLYelhtMAhwbDY300)T4Jh6?GYvSBKIT+_Hl<=V0Zq6#sHzNw9Q zvvHLW{r%E+e@;Jrkp!7-@&=}be~0(i7W@_*5wqIj!sFHr*3p>~_WOc&s=Vxj5gc0b z`L$*t{^F`JliEU*Px<-ObjqG|66LUZg{QIYecPw2^h?dv_3$Uvg}+R^Kvk@O4P9`> z#m(&q`l=C_i88VV(95?8ZZqxAZxBucINbfvD0-JmCZD8E#;YIdMJCH}j8r1mWlZ6~ zZ5;dF%#q-SnnMqI!=)ONXDFt#gO{cmmHA{)vc~awi-S=EAc!VJg>Xov$tsS^^LcO9PI|&X12JL$*jB zCg;ab{4@!_z}6^n#h+Rn4ISI^`f&%bqt)*qj|hQSoS?p%s@FQOt3`p#O_8^{8{UH4 z!|PKw*Cv1vtTtmo^h|X9YYL$L=pJ}uCxG&q*6nJ|0 z-!pexnYUJfP(b7`Pdp~)ZE6y~FF-$Y9vbe7{2D(L( z?xRVcxqa?4yiQuKlF(+SfyyK<^3>irhXbIaare7kapU8*m@6$HedeDpoIcmo4@i67 zXvf1e5#6gCOZ(Z(BXNK1n@L;DBA#GzA&qzX99PWdNBH|Ly0n!fI^9wr&M^YEAA3l%T&iD8-`bVo)P1Nn*@xj2~>}z+KvVKcS#@&>#s_?PV$)PEo5?GHA64xU7jJ1 zYrFF@q1{*)sJ~VlbF5ehJG&*Be!i5pswGF^7#lT8pRZ$_9JXIrtWe*~>&Cx*!wGNnmd-rs zHt)rLbA}WhOA!1_uyb3a{DC&E9qT<>Fl5Dr<|3YK?dv0IB;~lL&;C19rG56e&ds@L zX(vsid6P>ks<{xuIIA#})4Ns8iQbPQCV<<+up{!^6Sklw6jfB3CP>g`D^fs=*;wbU zMW{;1_iD1a*~tndm3`mpgS4IYpFC|QREei=N{0vR4FWNwF=yq3vxQOfd1Yvz~=?e?)kJHh7lylc{?okf+-vJ zu-{5ii^m?)POR(MZVsk53hw$O%o`Wm`;=CpKQ{O|l~nYr4I9f@G3>D60n?8J;bf`l53Wt|~Y*k>}nm)Va+iO$W>&HI8Oe2{We zuQ{@LL(Y=4i}nUEQD5IIK6*AZj1oG0>m16)!Ojtb;SW9V=)UPFALx&ji>>$jvP$#E zt|ye))-p-9QO!HGmW*rzl}50=Zmq*^S$cc?-Ad#0RUjb6f#EydiFrN^Wa7pV)y6?u zsePTu9Dn1zYm{A>MQ#BkyirE17`1zB&jKV)!ZKTpo`$#)WE^nUrwX(NGrqH!M#BTg z;<;V~K_H4}qhP76?9GU?y-hNfubm{q9KXK*TJ|>{*;)W7|6&H_Yc)ss1PaUQ>x{K+ zNv2z}04+rIGx7S?zq&u9?-=EG;BMePCrsG1Qag&`IBJ_c1*>Vd%rUD+-9h$cz}n^R zC2h`$3%HYyH)ON~IWb@bkXke%d?62rFD8DK{G0uF?)p|=!*~z5fo_QXR`vw!Z2rXe zX@8%$zBlwV93~{Cn)EUq|1wd3;SfstExWn+ zn*G$~)>cei)hf+w>d8|7vC&<|5#p1IYakI!7{vL!W^0tE=9|ddl4e-~w0}~%?aP)y z(2yPb^lVMX=R3}h-*i%Tn#wsr+o3(*G{tcJ9_NFs!6mdcsC(SE#pGmZslP!BZ~n9y zs%PR+I%A4k5LX+|i|oSATl>6FC=-LPI~8@s>dBBkUi$n z1h9;O`e5aKkxmX$4Lg&?;!5R1%iNH(N3E9K4VM~t;!y`{2V?8q%72q8chx#kbDGD} zhBqA^76usCzf{&Dw@9k0l_>Wvm;i32*cYQ92_T11gpB)9`BpX#^ng7Dy-g zMVFO#rE{^x=%;Z$SY?n7HAhTDCewUdPx}l-`0Fz)qMwA9J)N)|>-KCc<5o~8`H5)l?h8osTuigBXNP=eaBvl1|v#khPgY<^>dC<4Y!cD53Xn+k{g9* zP;KcEN9RY~Uj1$91lbkMO zkMlNfR`0^IERTlk@r;??eC!^6_Af@sm*#!_v2LcnORibYfC$pbU046IR-gv!PO|G1 z6b1>1Dar!DJo3N5d&*+0#Cb0>AW&hF^vSD9W6?dU=!VLPQV3dBS_H?3dBFUYQRnNS zXsg+M&vUx)YcJ3bsuiz_Q;KU)`h6h%fK`QBd?<%Mws*IKj@p=aUu2D~X)ha^y*wwk zAe!opJ>zB$l$cqK0lar=`jce-dNw`eSD&@w$lPwW#i=#d6Ad48K-R;}0$bYZYMI)U zHRfTIjDZ=(D$Zm_|5kr-){1?)T8cv((W7QtX8TMPsvC$}i$lIoWqGS4#*dLR^Vb`i z1U&96Np^X0{DZBdfhN%y7{Ta$CK_!&K^=!#JO@(cp=DQ4xBm2{U$XsgtJO@wr;Wly zIh-0H%R5zKb$-XzMlT@99=U!zX`KYN((9>ot&f)4`NhKtU4sgP#ugXw1m>~7pHx=H zxZtq!*EUqTh|zhg33$K+l>_tk=Y`3%s!=8U5RhKV>m^eUnwXHXw~yy}1fJebeeY0S zr`WeSP`3AGgi-reUM;6zny_NPnx)N49iBqE(Qg1tLtWr3IAnPCV7Zo$m|dt(V?0-1 z-&$PE`01X?6#A9wTg6X3n25jygO(U;xk%^ECBz5oW+<@~i&FE{b#y$Gg_p4F+=Chh ze;blqL@oGkVP`)Ltf1{^E0-Iay&R%XR~uD-v-mPp)n}fZQk^RW{Ob-hIvDk@xkye& z0saI1-E^3Lc$G>&1xPm!#DcA&A7>JD?=`>gy)iR1&o>U!srXWEuApmXs47yiAHDWc z=6r^#2Szl2WN~zE{iR(X|Z(nCak!BRt_c6y6_UpzQ*>$80OP}BT#)JXTmv3az-nMOUZyDZIq z2~YCcwjz6X6{wtKiAE_Kxd#T|qr?&*w*Ls#_0_5_4MsA=?84`6%3|m4-tARtT*#5X zNCO=z2ANzaiV6j#8$As}H+v~#!pbJ>R@*k_9{RL8t?Q-*!Im8SY9POzOrH(5+0EG| z9vVAX@zq4Z5fOX@oZ83hOhK@$z=6tIt$>hS&?dEXhJ5Vur0SCl(PgMQJ9=UmzVTrk zekkof`nd}>sp>@ueRwemHMn(m)F~JXvH>s@V2&#AJkCdP2^Ug!-lFJCO#cP%)>mlV z>vWEneP%0gFSq-1e(f-Q7FaGtrhPHB@$>8eUfW?_xlB)>8R7ampO9_&YRa{{NlX1} zjoE~e`c`QOFn$)^(h3&WSM8Q$TZl3~U5Ih4m1a0tNz+oK#HDFMU_;WP^Bdf#JI}_; zY3o>aD1(Lvv30X=NFLT}@4H7A1qye+q>Z=+q=`^Bd61&q#EA5x}D9`VBi!H_uJbuZ28o_5PdSqPHliy*2;@NBqF ze|UgK`+1T5kxX@i_Io~kQiOfuANp4aVUq1a^mpQiUmjFL4f+y-+)W_}_?J^PSDV^eDoaXR(dBa(w3peR#own59V*&2u}u^_F^| zj0Gl=U+miCYdDx}%PT4hmcdjqqBUg#8jh^6@~4O0F7{aPu`(m1!2I1`-=h?)wluA_ zaj)!Wz5M43zxhyph)TrJ#T+{1&|a{#7{Y*_%Qm11M4j21yCPNmr5_%3K@u6zD8l61 zc^qgy6xE{P4{vB++FPlK?-G4`JM9tn7M#<^@Vm}&UX>?9E(a;M@CnhNfn_rcZ%-8)y;ul)L%9*2uA9ofI_bXydBo>d9*_ z&Yu?IElsJ>Zml8%udBIii-b|DCtBqYh>=mvaHuy`Qavl`;uG&k)n7=x``p!c`?*vN z-{EFVo~uttXShy;V3r_m65&A8-yINQ2*YITOY2&e_|UoVvhD-B*w(W3fgvQa-XOrW zwv9~D(JBqi^(s+)2{@;-yJj>G!q1Y}A5@FZRcI``s&HXWrJeED6SjxkuDiQ0Rz|;v zNIoO61QFtC1dQi7!BC{tT+7}cK@tY-HtXnb@?GoSS;&i?QwBn$2SZRFGpc?(>PTV8+H z{fU82e+FWb6@~$Fxt;Xb`;7d}(e;2WJH@%1W!$o}W&T|-BwDtVpW{1#TXbU}zupQZ zOMHGURDBf?seHG7nq6(2jMks8lv~S~G``AIC7JFf{#E(aJ4#6dk0XRH5{(KMDY;Gd z9s(#_B#0R4+;Ywq;gsjRK&CM(vujINqlB6o;k=0jI4owN2)OlB5VqF;vi7Z%I=8(8 zu+X7*_+G^-zXUK>6M)EN3V9W|lrPo1?DBTI+->)dt*BFKI>-l?PJ)t43lMOy zu>dXmgnoH5Tb%qVx%$Y{t(SB2NyW}McZ3<4+$C5>j?g>&>3i(?#{TB=z=)5uQx*-< z3Fo|-YNt2NVNh&WC)Xz;y``ovue68F1pEWu8BDQ{YURjtTnc4Q25p+9yoBa_+y$a} z@>*z3ow5ja*C?i(`bq;PM6Rr9rZ3DbR{PZY&)-GULB42bh|J$|`oT!>lVlw2n%9(Z zkjm0aCHPJ>H?s=;6&AQRS$43)$q@7Mgxf8jw~v8s?6r_So4Y7|?cj^HnK|tn?k>3L zmLDm+Zfv&?yM)sOL&x#VmYp=J+B3HD=jK?^C6}&u1fKH01%Pyk?j~jKWIps+VF3CNF?iXr&};np9Nw}tKQa22_+`cs21JJOtV@b$+#LNq`m7}4F*Q1CF;|ZjB6~Flf<#p! zreC_aivC1$x51(p-B8&ZKzJ`-w_*O&Mo5{Rp4fG;iK3W>=WAzX zn;Lf|7tcTCc^k#o(KAE6SA1*gospPtW*^?XGo)5IwESK~IDHyWE=4Tu6H1mreQo7yVrx-#2s*_SqSXqP7dpv?jZC zCGf>6FVODcBPr6Y=D}Rmmv#))A|WZ%=b51<=uZypV%j^JS!ds17fQhUmD1jkj3^)9tA{vofPiL5 zLU-6;J!IewU++C=RG;sm#bx!~;&|fn&zh^42?NfRKgd@&@h)H;clCx9hSiX!&uR+# zD99JGy6u-D@qB%&+nv)-N)GRv>1gPw0p|fh@$WU_X6iRYr#$xnoopp~BX>MMjvp~Bv~LkA*E0qMP~8kB1T zS#~Nb7;^!ee#Ci!^pGR%{drQ4={6J}#haJ;hJa5I!KJ^i+M7@8&mbpyi+}Y3^DYSB zGmtu?P|3tq?V4A+(bSZumV3owzcf{d{EFZnTUzAh+ePGbuA0y;&f7gNX#0gcRz#l# z@x7dY|++eRetC7sKjts#%CPXzM>Ne)d?36nKxuMPd^g-}(0PBMWu~ zDsAX=ZGkVuJW=j-L-(iC-QR%r5MvzdL4S*2s?PwvB&arZt@nZ-)s?q-`CnVnr+8=Y zP9tem)~#q6;d)2NsSjCa-2C-F-GSRg>Z9l&$7hyqx09OLb@30m<*bma+GD~Kq&>0? zg<%5#E#u?5G5~=a3IAs8@qaqfAulw;QM#9jO_2YP?}cBodK0WvEMpJ8?De* zP>awx)&%KM}(3gV<< z4cx7m@I(*pBag8L=dzf4LT~3c)O6dY@G=@!*=1{^R{6)w;#FeYWPBEMD%r}wADfQo zcZfoIy5;}N+MZWx5bZ}B_N#d>tIo<^1ePHVPv%eYV%DkxfE~zSZEf>Ha^&`_xsA`p z(rSxcJ$q%qXV(SrAVtC~DS!n0$P`FbX8<#RWz`sn$KXHRFHK z*|1>9`8}|gso2Vt6K|2mt5`|@K4 zG;|!&E$3Ymr|6l&R_`JOR#_Ye(RHH0!)I)*6*dp0Fg z5Pq(FtFYf@SBQ{KuBgO>WdA9fSHw)hkYKF&L2_VyqI|T5883y`%Xc1iYH}3e; zmLXP~gtST?_Afnb=-3e-hUI;tAIuN9J&->O60)nYf9Zp8cFHfJQqtW*5L z;q|L>YLtgWc>cnHQ(!&He~1uzv`P@Pb==7Px#~<5sj{%tvu%A zncov)wp8GKsogW&KH4j~BVsp?6B;b?jj7JifAWsw#Iug7pPpu;-aeFgh3luFX3K;9 zl?I2}#ra#2IHT>=7uUZgAuIP-Kh^ajEh@`nW4~=fiVe|?3}`&F@?DDG7(}rRmXb95 z;a7&*`lE&sF?-6%C-i~1?8ZB$=c{1JKeP;}+-@-W$j_}ySa0Gl>lF~**_J31PC2w!7C9@cI%q3D(tb6t$YYapN^iDqn_m?rX@?=Sd-ARj6W#q1Y~BkT)`%Ug~;pUC*yL8Hn~)@}$h zVJ;1YQ}Vh%5W#up!$(F3oXZ~MqooBecuD5Fn60Dv4S$72zn;Ix{?4wyaf@*xVQbCp z)Q}GLVC3*H=oLZN_%MdefbQKg+(*V#VY?Jw0^WDqZ?Vm2cxc(7eeZd*CdWwcbvA z$ambc6k=E)K5of>v4&Q9bk6>hOc>5sv@g5)C~yQS-=A+nkN?jvZ9I}aw?I()I$0Cg zL_hEQ_?A0eYB}`%#w;hIts*YQlqa4fcrAx6Hb%cA1?eo`vgqfc=!Sr-?ZiFb+3R?g z+&9ZR`>%p@gg)m1aK7mzScau~jm|CyrM;i`1n3`2z;V6M&bmJt~j{iN-p60 zfukM~J}Aq@JI|f`8#312;?gFazb87q|1@SAWgf*-4JylaME{;i%E27)-@LQQH>zV* zrB_oh&9FJMA#EX7EbxkldZ|oGq=>iM^6WOvjLU`hNGw~P=}TF$2bG`_aft!xSd!x0 zV%Yf3!}vG20J+z5dq-qJP@WSMio&5p_9*EA@9~hBytlHEe&?qhOH4~$lfK+A^-ndE zku#+@kyW7tEGJui685rBjAZL`=ch!+&Q4iNV3uHiafK8n(MjO`jmPpFEW(_{BmVQ$ zgNgFxj{G{t3iJLW_tcDd*|bMlkrzKdwL5GGLn^Wo)~Nn2O>=+leeOJmIdaYR+06Zy ztkk!O*Sk*Q-!LQBB?8UBs0+qF_6U7x&{IVX3dR9}FD0yw14NJOx1*jOAkNWd^=UZa zX+d>S;VFLoncpn?bkf6|%^R7`=R@=O;hL-C%oWO*H{`+aE9}!CxI<}67{`}vwd=Ou zS;)hbOUl?;@ove4s`RV~=4O7+Uf~@Ti|XW>7$w64 zXF==w$(79W>qk3V0(`2KiMFV?AZ--}dVm9c6Z*r766s2er8 zn@2;$0lt9DtJF~AM`2Lcp~`*()&Y<20^IeOa_sx~sv6#zTR%%&np6>ruC)-8-(KG; zxxB^B(@(`_m-S8Puj;@$0ct01jo)96))!x?Oxe98@1miMo1_zx5or-2AQFxXXn)7+ zpXx~RZNx$|OOwuv&HLsXt%1oV^`9~vx-iVVLt=+;_F$LRM1 zpOtm`m*`(Aj+I6V3UDLXC)c(R2Qmvq^euM1;;cB3nkl&T!>k*NC4WDXjA|KKW?gN7C%Wz+lcRT0cMfOnM9fwVdtyXf(TM1x~{43?t zK_~Thy|`zx4Sloty0?qr#`Ur0sEjB>s7`%tmOg;<{YLZg_de|m7S==@#)C%EfDqy5 zh<&LjM9Z<+cp&#YE`P%}j!I2VOCiL+zS4@Ck$AZgqL+i6<9+iMzsDUajP=&i(*3%! z(eZ+V_3b0q3-Fy^HKi=NB2`PR=*ol!&ib*6AZPE9^dBVXQwk{SEIcD+XUx6xXWl0@ zGy-#C!lh1%t|8*nEV!NMAGQv1*l}e61E5Bku^9>V$kVpwQ9;cxC9fN9`kb+sIkCL8 zQd3`vf|UGLf7uTlVT#ln(a1|G3mz9xXamq$PTDS)E(PWix|Ppbt)s&3;M=9{AM6Pj z-3J`4n%t5I1>^I3lc%6tM89{KKa~(v!?@x+YiTu9JNOmpIU_5Qz#@}HxFLUrPbcLe z>4zqI42R-{AQ&U<#o@F`opWVOQbZee#`Ag?4=jdS9?_0h9uvw3VGEG&11@2^CEtl; zz~eg_-o~$2f7k}uc3_^$MdGcSL`CZ# zD-TG!er6pT1%2zm%0x`^kG@kiM^;UL^Z~JrcKU04USi6}$Q@U$%u4Mk-vC1O(4oF` zpLLi!rIjj!tPs7`^@4i)u7y?<)~!;$gV^cBhnr;Bj#bPb1>@CJ=OG;OL~yUfO71oJ zaSyQXoz;f1kWF^8v-*CBUCzk4>&qxxlg2371+5b0Fr!oI-H32IadBoN{H)5P8}1~9 zyZ&u*(&rT#B5awSOWQv#A|ZlZy!Q&5rhOYq(INX!Tr%%y{P}L$zf_ac6id1`75>#y z{YB}^wetXtO7fP-=frv6DSrpg$zUJa#6;azV`V~@{-*oNbLZd-FcF$mgsEGD zDloWs414%ID4`8iOtJ4wC0)2Yi`n$z!4TBx)c{JquW;&4*_ zgHDN~1pT-*%2%$xHY&b~+#Mm@){5`8UkJ?zx5Q7>J8Aq5WQ@d&Qd#!W*i8OXNssF? z$gH_vTX9^q!)k=fjbc*NvqVNha^yWOTsVUBrTY^t+|+zck&76;`BjJYVm|T5tq&VE zn~){V=dC_7gMrEC=4MqeP~({f_9J^gd^lYHYAm02Oz{i-k9(>Fj!KzI%uwl{8LmJ0 z&lfhxCc{DO8;5?6`_0UTk2b`O)1fF6kwsvVm4B)hjY*gpLV;eAaoHY9SURmewF+hF zy`TTV?G+dx5^kz?+)(u&3r&X1v42*y`=9&8{hGrzqUf{v^Ie{6@@cVWe9$QcCt{`f z!*unxVekDOnp=(H8VHf}Ga3b`IWy3oqqLDZ8M+ov@khdDL$%nbp}A0NlF zh@CKAxqV(dy_ZE{F0}Kc#jC~5jZ3cjl#H-ZImtl&F&fH zSb~!6v-cg<;GH|Y*WY3a9yn!;ti9?Dt3TQjkB=A6?6F6os!RD*x%PgxK7YLP{*RaP za-yl`Pt~$A;wqx_iUjL_rPUnsMfOS@JQyO{O06zkaU?>%w+mRfm_f}F&#lplt98_MY>&qWXYQKQ{=cZ60^ zKt>Mlf~gKBSF=>XPy9$sd7A$+K7aqrAZjs_T4rZC zL)B@pD{o9xJJV`5heVa2giByu^g=l+dpS;?#nZ++jzzF1u-_3-76h2U{@mZt1G%uD zST&vU6Kf3JsTe;)3=fAeBg*0ZaC2C%)yyQ;%d1JTYu&f-Hr~_X%&))x`xcQxdcF7} zojmwxYR~hu@9!&Y2KeZAo=CrK9)upX>t3_#Dp|fp3Dc7~fLxz=i3@-=4|`snn>*`% z;vPYK7S>Kl50Ys#7@(QA?Qfg81fw@na<MI_f^mOBETJNwB-2^F@rC54$bbSd4L8ST4ENav`RV792g$1xwuA z;3_|F2H|c+F%rn-XU<&p9DDV)O?oz=aYMA!!ChclE-Ztr^$Ay0M+v~LrDC>S^oa}j z7K`t}U56+ESv{nY;v+w;tRAIB%-Qpij1KI3o3s#s2DNx@&0d|C<9kNVs#rf%UM;x> z_sYJMAaAly^n=#T2vlRaz*5()sfzQ9J0=D%cF-K$EU&3-rsj6*LQ9WOk6;v&Z8)N7 zHV(WJ!uhtOko-|uqUXOJB~}D;4x1}3frauU>JE0kzKTSq;ILaL!f{j^50^IS^_@BO zgV*i))03g?#lYMTfr*;DB2S=fvXXo@RLMLC(apo+zL0^!*n=K>2(!htd&@Io0U_5J zT81h(V!--6ez&%uKtO-*Md=ro-p;-Y0@L*bdriC+vIuChCBFb)IIe{yfV{4Pt%M0z zhHs^o@$K}t^ld0UE?wC77JWR}OLC>vFz+KA7|zQYsv+n_!jXOMlw{HmY3QhSu%jC+ z?%rFV)x=jx*HX`Hrk5+HqW!{G&*B@*-j27Lqj||tP)Wl0#C_wzWjtu^?)d}8TpoCa zBD&>00XpNhKDzAeg{|vWzOSM$wagCgK|@NhNzAUOnbYCNRA66{jGt%Nt?GRpv{|U| zq&!(#{F?G1z~WD&D^747=j&1Aov5+_P1f|O)r2EXO=8O(LVngSBeWlBV|^VE&XJVAz9Z`M!GUO* z5qifBDh{<|zh12-cakKuNRn6HkYzK56=4%6$s5&-fLt8yt?*5^)r5l%VmL>CyrRdX5cZxoEriskk=Tf667edtU5Z&xsDnM+afiBWlmKrnVDWA>=5#-9+dkLVhk{Mt`hW7}4E zv$UL^UK)&24Ybt18Cg%ZAOG#JCPgUcaf$BIePGL>(dONucG}OW2Yz<9X{EpmmZ-ny0wwGjS!jof-=Ff4R5f6oWl0lt>TM_t%X3gqqi-lKCl z=0-kKMxINdY*|_77Kn1nJ7oLr-rVf?HgHIB?HVn!NKhHEVmuD5zIp38VaF4ATcH-@ z4}FfVKvqCNmaj+F$%&P~ONJ7o>+bf4$t|!uEA}IFBMTJ2bT-(-m>A*9FN#KW8gLO@6bgNPLHohAB70z{c668Vz+(_NJeĪlZ4yX^;<&M~tH@0C*$X4@S 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%0Awn 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 literal 0 HcmV?d00001 From a73fb89c446c02f072a19cee891a3b8f738ef25b Mon Sep 17 00:00:00 2001 From: Evgeny Poberezkin Date: Wed, 18 Dec 2024 18:25:05 +0000 Subject: [PATCH 3/6] ios: update library --- apps/ios/SimpleX.xcodeproj/project.pbxproj | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/apps/ios/SimpleX.xcodeproj/project.pbxproj b/apps/ios/SimpleX.xcodeproj/project.pbxproj index 759b16b196..4fde84269e 100644 --- a/apps/ios/SimpleX.xcodeproj/project.pbxproj +++ b/apps/ios/SimpleX.xcodeproj/project.pbxproj @@ -167,9 +167,9 @@ 648010AB281ADD15009009B9 /* CIFileView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 648010AA281ADD15009009B9 /* CIFileView.swift */; }; 648679AB2BC96A74006456E7 /* ChatItemForwardingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 648679AA2BC96A74006456E7 /* ChatItemForwardingView.swift */; }; 649B28DD2CFE07CF00536B68 /* libffi.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 649B28D82CFE07CF00536B68 /* libffi.a */; }; - 649B28DE2CFE07CF00536B68 /* libHSsimplex-chat-6.2.0.7-3p784Fmu4gOAiEiFcsHj1E-ghc9.6.3.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 649B28D92CFE07CF00536B68 /* libHSsimplex-chat-6.2.0.7-3p784Fmu4gOAiEiFcsHj1E-ghc9.6.3.a */; }; + 649B28DE2CFE07CF00536B68 /* libHSsimplex-chat-6.2.0.7-1UFyc6WJuaw6s2eEIvrMnW-ghc9.6.3.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 649B28D92CFE07CF00536B68 /* libHSsimplex-chat-6.2.0.7-1UFyc6WJuaw6s2eEIvrMnW-ghc9.6.3.a */; }; 649B28DF2CFE07CF00536B68 /* libgmpxx.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 649B28DA2CFE07CF00536B68 /* libgmpxx.a */; }; - 649B28E02CFE07CF00536B68 /* libHSsimplex-chat-6.2.0.7-3p784Fmu4gOAiEiFcsHj1E.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 649B28DB2CFE07CF00536B68 /* libHSsimplex-chat-6.2.0.7-3p784Fmu4gOAiEiFcsHj1E.a */; }; + 649B28E02CFE07CF00536B68 /* libHSsimplex-chat-6.2.0.7-1UFyc6WJuaw6s2eEIvrMnW.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 649B28DB2CFE07CF00536B68 /* libHSsimplex-chat-6.2.0.7-1UFyc6WJuaw6s2eEIvrMnW.a */; }; 649B28E12CFE07CF00536B68 /* libgmp.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 649B28DC2CFE07CF00536B68 /* libgmp.a */; }; 649BCDA0280460FD00C3A862 /* ComposeImageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 649BCD9F280460FD00C3A862 /* ComposeImageView.swift */; }; 649BCDA22805D6EF00C3A862 /* CIImageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 649BCDA12805D6EF00C3A862 /* CIImageView.swift */; }; @@ -516,9 +516,9 @@ 648679AA2BC96A74006456E7 /* ChatItemForwardingView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatItemForwardingView.swift; sourceTree = ""; }; 6493D667280ED77F007A76FB /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = ""; }; 649B28D82CFE07CF00536B68 /* libffi.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libffi.a; sourceTree = ""; }; - 649B28D92CFE07CF00536B68 /* libHSsimplex-chat-6.2.0.7-3p784Fmu4gOAiEiFcsHj1E-ghc9.6.3.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-6.2.0.7-3p784Fmu4gOAiEiFcsHj1E-ghc9.6.3.a"; sourceTree = ""; }; + 649B28D92CFE07CF00536B68 /* libHSsimplex-chat-6.2.0.7-1UFyc6WJuaw6s2eEIvrMnW-ghc9.6.3.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-6.2.0.7-1UFyc6WJuaw6s2eEIvrMnW-ghc9.6.3.a"; sourceTree = ""; }; 649B28DA2CFE07CF00536B68 /* libgmpxx.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgmpxx.a; sourceTree = ""; }; - 649B28DB2CFE07CF00536B68 /* libHSsimplex-chat-6.2.0.7-3p784Fmu4gOAiEiFcsHj1E.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-6.2.0.7-3p784Fmu4gOAiEiFcsHj1E.a"; sourceTree = ""; }; + 649B28DB2CFE07CF00536B68 /* libHSsimplex-chat-6.2.0.7-1UFyc6WJuaw6s2eEIvrMnW.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-6.2.0.7-1UFyc6WJuaw6s2eEIvrMnW.a"; sourceTree = ""; }; 649B28DC2CFE07CF00536B68 /* libgmp.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgmp.a; sourceTree = ""; }; 649BCD9F280460FD00C3A862 /* ComposeImageView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComposeImageView.swift; sourceTree = ""; }; 649BCDA12805D6EF00C3A862 /* CIImageView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CIImageView.swift; sourceTree = ""; }; @@ -671,9 +671,9 @@ 5CE2BA93284534B000EC33A6 /* libiconv.tbd in Frameworks */, 649B28E12CFE07CF00536B68 /* libgmp.a in Frameworks */, 5CE2BA94284534BB00EC33A6 /* libz.tbd in Frameworks */, - 649B28E02CFE07CF00536B68 /* libHSsimplex-chat-6.2.0.7-3p784Fmu4gOAiEiFcsHj1E.a in Frameworks */, + 649B28E02CFE07CF00536B68 /* libHSsimplex-chat-6.2.0.7-1UFyc6WJuaw6s2eEIvrMnW.a in Frameworks */, CE38A29C2C3FCD72005ED185 /* SwiftyGif in Frameworks */, - 649B28DE2CFE07CF00536B68 /* libHSsimplex-chat-6.2.0.7-3p784Fmu4gOAiEiFcsHj1E-ghc9.6.3.a in Frameworks */, + 649B28DE2CFE07CF00536B68 /* libHSsimplex-chat-6.2.0.7-1UFyc6WJuaw6s2eEIvrMnW-ghc9.6.3.a in Frameworks */, 649B28DD2CFE07CF00536B68 /* libffi.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; @@ -754,8 +754,8 @@ 649B28D82CFE07CF00536B68 /* libffi.a */, 649B28DC2CFE07CF00536B68 /* libgmp.a */, 649B28DA2CFE07CF00536B68 /* libgmpxx.a */, - 649B28D92CFE07CF00536B68 /* libHSsimplex-chat-6.2.0.7-3p784Fmu4gOAiEiFcsHj1E-ghc9.6.3.a */, - 649B28DB2CFE07CF00536B68 /* libHSsimplex-chat-6.2.0.7-3p784Fmu4gOAiEiFcsHj1E.a */, + 649B28D92CFE07CF00536B68 /* libHSsimplex-chat-6.2.0.7-1UFyc6WJuaw6s2eEIvrMnW-ghc9.6.3.a */, + 649B28DB2CFE07CF00536B68 /* libHSsimplex-chat-6.2.0.7-1UFyc6WJuaw6s2eEIvrMnW.a */, ); path = Libraries; sourceTree = ""; From fcb2d1dbacff79b5d1425ecdbfae946764fcf5cd Mon Sep 17 00:00:00 2001 From: Diogo Date: Thu, 19 Dec 2024 10:48:26 +0000 Subject: [PATCH 4/6] core, ios: chat tags (#5367) * types and db * migration module * chat tag * store method proposal * profiles build * update type * update return type * building * working api * update * refactor * attach tags to contact * simplify * attach chat tags to group info * get chat tags with supplied user id * get tags fix * ios: chat tags poc (#5370) * ios: chat tags poc * updates to sheet * temporary display for other option on swipe * sheet height * only show preset when it has matches * changes * worst emoji picker ever * simplify tag casts and collapse * open on create tag if no tags * simple emoji text field * nice emoji picker * dismiss sheets on tag/untag * semibold selection * all preset tag and change collapsed icon on selection * default selected tag (all) * only apply tag filters on empty search * + button when no custom lists * reset selection of tag filter on profile changes * edit tag (broken menu inside swiftui list) * create list to end of list * swipe changes * remove context menu * delete and edit on swipe actions * tap unread filter deselects other filters * remove delete tag if empty * show tag creation sheet when + button pressed * in memory tag edit * color, size * frame * layout * refactor * remove code * add unread to same unit * fraction on long press * nav fixes * in memory list * emoji picker improvements * remove diff * secondary plus * stop flickering on chat tags load * reuse string * fix reset glitches * delete destructive * simplify? * changes * api updates * fix styles on list via swipe * fixed untag * update schema * move user tags loading to get users chat data * move presets to model * update preset tags when chats are updated * style fixes and locate getPresetTags near tags model --------- Co-authored-by: Evgeny Poberezkin * deleted contacts and card should not match contact preset * fix update presets on chat remove * update migration indices * fix migration * not used chat model * disable button on repeated list name or emoji * no chats message for search fix * fix edits and trim * error in footer, not in alert * styling fixes due to wrong place to attach sheet * update library * remove log * idea for dynamic sheet height * max fraction 62% * minor fixes * disable save button when no changes and while saving * disable preset filter if it is no longer shown * remove comments from schema * fix emoji * remove apiChatTagsResponse * always read chat tags * fix --------- Co-authored-by: Evgeny Poberezkin Co-authored-by: spaced4ndy <8711996+spaced4ndy@users.noreply.github.com> --- apps/ios/Shared/Model/ChatModel.swift | 31 ++ apps/ios/Shared/Model/SimpleXAPI.swift | 55 ++ apps/ios/Shared/Views/Chat/ChatInfoView.swift | 2 +- .../Views/ChatList/ChatListNavLink.swift | 479 +++++++++++++++++- .../Shared/Views/ChatList/ChatListView.swift | 364 +++++++++++-- .../Views/Contacts/ContactListNavLink.swift | 2 +- .../Views/NewChat/NewChatMenuButton.swift | 8 +- .../Shared/Views/NewChat/NewChatView.swift | 1 + .../Onboarding/AddressCreationCard.swift | 2 +- apps/ios/SimpleX.xcodeproj/project.pbxproj | 17 + .../xcshareddata/swiftpm/Package.resolved | 11 +- apps/ios/SimpleXChat/APITypes.swift | 34 ++ apps/ios/SimpleXChat/ChatTypes.swift | 35 +- simplex-chat.cabal | 1 + src/Simplex/Chat.hs | 29 ++ src/Simplex/Chat/Controller.hs | 20 + .../Chat/Migrations/M20241206_chat_tags.hs | 47 ++ src/Simplex/Chat/Migrations/chat_schema.sql | 30 ++ src/Simplex/Chat/Store/Connections.hs | 22 +- src/Simplex/Chat/Store/Direct.hs | 60 ++- src/Simplex/Chat/Store/Groups.hs | 72 ++- src/Simplex/Chat/Store/Migrations.hs | 4 +- src/Simplex/Chat/Store/Shared.hs | 86 +++- src/Simplex/Chat/Types.hs | 13 + src/Simplex/Chat/View.hs | 2 + 25 files changed, 1311 insertions(+), 116 deletions(-) create mode 100644 src/Simplex/Chat/Migrations/M20241206_chat_tags.hs diff --git a/apps/ios/Shared/Model/ChatModel.swift b/apps/ios/Shared/Model/ChatModel.swift index 6b6b0ac03f..8cd8b0eece 100644 --- a/apps/ios/Shared/Model/ChatModel.swift +++ b/apps/ios/Shared/Model/ChatModel.swift @@ -100,6 +100,34 @@ class ItemsModel: ObservableObject { } } +class ChatTagsModel: ObservableObject { + static let shared = ChatTagsModel() + + @Published var userTags: [ChatTag] = [] + @Published var activeFilter: ActiveFilter? = nil + @Published var presetTags: [PresetTag] = [] +} + +func updatePresetTags(_ chats: [Chat]) { + var matches: Set = [] + for chat in chats { + for tag in PresetTag.allCases { + if presetTagMatchesChat(tag, chat) { + matches.insert(tag) + } + } + if matches.count == PresetTag.allCases.count { + break + } + } + + let tm = ChatTagsModel.shared + if case let .presetTag(tag) = tm.activeFilter, !matches.contains(tag) { + tm.activeFilter = nil + } + tm.presetTags = Array(matches).sorted(by: { $0.rawValue < $1.rawValue }) +} + class NetworkModel: ObservableObject { // map of connections network statuses, key is agent connection id @Published var networkStatuses: Dictionary = [:] @@ -342,8 +370,10 @@ final class ChatModel: ObservableObject { private func updateChat(_ cInfo: ChatInfo, addMissing: Bool = true) { if hasChat(cInfo.id) { updateChatInfo(cInfo) + updatePresetTags(self.chats) } else if addMissing { addChat(Chat(chatInfo: cInfo, chatItems: [])) + updatePresetTags(self.chats) } } @@ -858,6 +888,7 @@ final class ChatModel: ObservableObject { func removeChat(_ id: String) { withAnimation { chats.removeAll(where: { $0.id == id }) + updatePresetTags(chats) } } diff --git a/apps/ios/Shared/Model/SimpleXAPI.swift b/apps/ios/Shared/Model/SimpleXAPI.swift index 51be3191ec..177f3e884f 100644 --- a/apps/ios/Shared/Model/SimpleXAPI.swift +++ b/apps/ios/Shared/Model/SimpleXAPI.swift @@ -318,6 +318,20 @@ private func apiChatsResponse(_ r: ChatResponse) throws -> [ChatData] { throw r } +func apiGetChatTags() throws -> [ChatTag] { + let userId = try currentUserId("apiGetChatTags") + let r = chatSendCmdSync(.apiGetChatTags(userId: userId)) + if case let .chatTags(_, tags) = r { return tags } + throw r +} + +func apiGetChatTagsAsync() async throws -> [ChatTag] { + let userId = try currentUserId("apiGetChatTags") + let r = await chatSendCmd(.apiGetChatTags(userId: userId)) + if case let .chatTags(_, tags) = r { return tags } + throw r +} + let loadItemsPerPage = 50 func apiGetChat(type: ChatType, id: Int64, search: String = "") async throws -> Chat { @@ -368,6 +382,34 @@ func apiForwardChatItems(toChatType: ChatType, toChatId: Int64, fromChatType: Ch return await processSendMessageCmd(toChatType: toChatType, cmd: cmd) } +func apiCreateChatTag(tag: ChatTagData) async throws -> [ChatTag] { + let r = await chatSendCmd(.apiCreateChatTag(tag: tag)) + if case let .chatTags(_, userTags) = r { + return userTags + } + throw r +} + +func apiSetChatTags(type: ChatType, id: Int64, tagIds: [Int64]) async throws -> ([ChatTag], [Int64]) { + let r = await chatSendCmd(.apiSetChatTags(type: type, id: id, tagIds: tagIds)) + if case let .tagsUpdated(_, userTags, chatTags) = r { + return (userTags, chatTags) + } + throw r +} + +func apiDeleteChatTag(tagId: Int64) async throws { + try await sendCommandOkResp(.apiDeleteChatTag(tagId: tagId)) +} + +func apiUpdateChatTag(tagId: Int64, tag: ChatTagData) async throws { + try await sendCommandOkResp(.apiUpdateChatTag(tagId: tagId, tagData: tag)) +} + +func apiReorderChatTags(tagIds: [Int64]) async throws { + try await sendCommandOkResp(.apiReorderChatTags(tagIds: tagIds)) +} + func apiSendMessages(type: ChatType, id: Int64, live: Bool = false, ttl: Int? = nil, composedMessages: [ComposedMessage]) async -> [ChatItem]? { let cmd: ChatCommand = .apiSendMessages(type: type, id: id, live: live, ttl: ttl, composedMessages: composedMessages) return await processSendMessageCmd(toChatType: type, cmd: cmd) @@ -1746,24 +1788,37 @@ func getUserChatData() throws { m.userAddress = try apiGetUserAddress() m.chatItemTTL = try getChatItemTTL() let chats = try apiGetChats() + let tags = try apiGetChatTags() m.updateChats(chats) + let tm = ChatTagsModel.shared + tm.activeFilter = nil + tm.userTags = tags + updatePresetTags(m.chats) } private func getUserChatDataAsync() async throws { let m = ChatModel.shared + let tm = ChatTagsModel.shared if m.currentUser != nil { let userAddress = try await apiGetUserAddressAsync() let chatItemTTL = try await getChatItemTTLAsync() let chats = try await apiGetChatsAsync() + let tags = try await apiGetChatTagsAsync() await MainActor.run { m.userAddress = userAddress m.chatItemTTL = chatItemTTL m.updateChats(chats) + tm.activeFilter = nil + tm.userTags = tags + updatePresetTags(m.chats) } } else { await MainActor.run { m.userAddress = nil m.updateChats([]) + tm.activeFilter = nil + tm.userTags = [] + tm.presetTags = [] } } } diff --git a/apps/ios/Shared/Views/Chat/ChatInfoView.swift b/apps/ios/Shared/Views/Chat/ChatInfoView.swift index 9b6b9b73e8..1c3203920a 100644 --- a/apps/ios/Shared/Views/Chat/ChatInfoView.swift +++ b/apps/ios/Shared/Views/Chat/ChatInfoView.swift @@ -332,7 +332,7 @@ struct ChatInfoView: View { .sheet(item: $sheet) { if #available(iOS 16.0, *) { $0.content - .presentationDetents([.fraction(0.4)]) + .presentationDetents([.fraction($0.fraction)]) } else { $0.content } diff --git a/apps/ios/Shared/Views/ChatList/ChatListNavLink.swift b/apps/ios/Shared/Views/ChatList/ChatListNavLink.swift index 6c5dad1f74..6bf86840a8 100644 --- a/apps/ios/Shared/Views/ChatList/ChatListNavLink.swift +++ b/apps/ios/Shared/Views/ChatList/ChatListNavLink.swift @@ -8,6 +8,7 @@ import SwiftUI import SimpleXChat +import ElegantEmojiPicker typealias DynamicSizes = ( rowHeight: CGFloat, @@ -43,9 +44,11 @@ func dynamicSize(_ font: DynamicTypeSize) -> DynamicSizes { struct ChatListNavLink: View { @EnvironmentObject var chatModel: ChatModel @EnvironmentObject var theme: AppTheme + @EnvironmentObject var chatTagsModel: ChatTagsModel @Environment(\.dynamicTypeSize) private var userFont: DynamicTypeSize @AppStorage(GROUP_DEFAULT_ONE_HAND_UI, store: groupDefaults) private var oneHandUI = false @ObservedObject var chat: Chat + @Binding var parentSheet: SomeSheet? @State private var showContactRequestDialog = false @State private var showJoinGroupDialog = false @State private var showContactConnectionInfo = false @@ -85,6 +88,7 @@ struct ChatListNavLink: View { progressByTimeout = false } } + .actionSheet(item: $actionSheet) { $0.actionSheet } } @ViewBuilder private func contactNavLink(_ contact: Contact) -> some View { @@ -124,6 +128,7 @@ struct ChatListNavLink: View { toggleNtfsButton(chat: chat) } .swipeActions(edge: .trailing, allowsFullSwipe: true) { + tagChatButton(chat) if !chat.chatItems.isEmpty { clearChatButton() } @@ -145,11 +150,10 @@ struct ChatListNavLink: View { } } .alert(item: $alert) { $0.alert } - .actionSheet(item: $actionSheet) { $0.actionSheet } .sheet(item: $sheet) { if #available(iOS 16.0, *) { $0.content - .presentationDetents([.fraction(0.4)]) + .presentationDetents([.fraction($0.fraction)]) } else { $0.content } @@ -185,6 +189,7 @@ struct ChatListNavLink: View { AlertManager.shared.showAlert(groupInvitationAcceptedAlert()) } .swipeActions(edge: .trailing) { + tagChatButton(chat) if (groupInfo.membership.memberCurrent) { leaveGroupChatButton(groupInfo) } @@ -206,14 +211,25 @@ struct ChatListNavLink: View { toggleNtfsButton(chat: chat) } .swipeActions(edge: .trailing, allowsFullSwipe: true) { - if !chat.chatItems.isEmpty { + tagChatButton(chat) + let showClearButton = !chat.chatItems.isEmpty + let showDeleteGroup = groupInfo.canDelete + let showLeaveGroup = groupInfo.membership.memberCurrent + let totalNumberOfButtons = 1 + (showClearButton ? 1 : 0) + (showDeleteGroup ? 1 : 0) + (showLeaveGroup ? 1 : 0) + + if showClearButton, totalNumberOfButtons <= 3 { clearChatButton() } - if (groupInfo.membership.memberCurrent) { + if (showLeaveGroup) { leaveGroupChatButton(groupInfo) } - if groupInfo.canDelete { - deleteGroupChatButton(groupInfo) + + if showDeleteGroup { + if totalNumberOfButtons <= 3 { + deleteGroupChatButton(groupInfo) + } else { + moreOptionsButton(chat, groupInfo) + } } } } @@ -306,7 +322,67 @@ struct ChatListNavLink: View { } .tint(Color.orange) } - + + private func tagChatButton(_ chat: Chat) -> some View { + Button { + setTagChatSheet(chat) + } label: { + SwipeLabel(NSLocalizedString("List", comment: "swipe action"), systemImage: "tag.fill", inverted: oneHandUI) + } + .tint(.mint) + } + + private func setTagChatSheet(_ chat: Chat) { + let screenHeight = UIScreen.main.bounds.height + let reservedSpace: Double = 4 * 44 // 2 for padding, 1 for "Create list" and another for extra tag + let tagsSpace = Double(max(chatTagsModel.userTags.count, 3)) * 44 + let fraction = min((reservedSpace + tagsSpace) / screenHeight, 0.62) + + parentSheet = SomeSheet( + content: { + AnyView( + NavigationView { + if chatTagsModel.userTags.isEmpty { + ChatListTagEditor(chat: chat) + } else { + ChatListTag(chat: chat) + } + } + ) + }, + id: "lists sheet", + fraction: fraction + ) + } + + private func moreOptionsButton(_ chat: Chat, _ groupInfo: GroupInfo?) -> some View { + Button { + var buttons: [Alert.Button] = [ + .default(Text("Clear")) { + AlertManager.shared.showAlert(clearChatAlert()) + } + ] + + if let gi = groupInfo, gi.canDelete { + buttons.append(.destructive(Text("Delete")) { + AlertManager.shared.showAlert(deleteGroupAlert(gi)) + }) + } + + buttons.append(.cancel()) + + actionSheet = SomeActionSheet( + actionSheet: ActionSheet( + title: Text("Clear or delete group?"), + buttons: buttons + ), + id: "other options" + ) + } label: { + SwipeLabel(NSLocalizedString("More", comment: "swipe action"), systemImage: "ellipsis", inverted: oneHandUI) + } + } + private func clearNoteFolderButton() -> some View { Button { AlertManager.shared.showAlert(clearNoteFolderAlert()) @@ -484,6 +560,389 @@ struct ChatListNavLink: View { } } +struct TagEditorNavParams { + let chat: Chat? + let chatListTag: ChatTagData? + let tagId: Int64? +} + +struct ChatListTag: View { + var chat: Chat? = nil + var showEditButton: Bool = false + @Environment(\.dismiss) var dismiss: DismissAction + @EnvironmentObject var theme: AppTheme + @EnvironmentObject var chatTagsModel: ChatTagsModel + @EnvironmentObject var m: ChatModel + @State private var editMode = EditMode.inactive + @State private var tagEditorNavParams: TagEditorNavParams? = nil + + var chatTagsIds: [Int64] { chat?.chatInfo.contact?.chatTags ?? chat?.chatInfo.groupInfo?.chatTags ?? [] } + + var body: some View { + List { + Section { + ForEach(chatTagsModel.userTags, id: \.id) { tag in + let text = tag.chatTagText + let emoji = tag.chatTagEmoji + let tagId = tag.chatTagId + let selected = chatTagsIds.contains(tagId) + + HStack { + if let emoji { + Text(emoji) + } else { + Image(systemName: "tag") + } + Text(text) + .padding(.leading, 12) + Spacer() + if chat != nil { + radioButton(selected: selected) + } + } + .contentShape(Rectangle()) + .onTapGesture { + if let c = chat { + setTag(tagId: selected ? nil : tagId, chat: c) + } else { + tagEditorNavParams = TagEditorNavParams(chat: nil, chatListTag: ChatTagData(emoji: emoji, text: text), tagId: tagId) + } + } + .swipeActions(edge: .trailing, allowsFullSwipe: true) { + Button { + showAlert( + NSLocalizedString("Delete list?", comment: "alert title"), + message: NSLocalizedString("All chats will be removed from the list \(text), and the list deleted.", comment: "alert message"), + actions: {[ + UIAlertAction( + title: NSLocalizedString("Cancel", comment: "alert action"), + style: .default + ), + UIAlertAction( + title: NSLocalizedString("Delete", comment: "alert action"), + style: .destructive, + handler: { _ in + deleteTag(tagId) + } + ) + ]} + ) + } label: { + Label("Delete", systemImage: "trash.fill") + } + .tint(.red) + } + .swipeActions(edge: .leading, allowsFullSwipe: true) { + Button { + tagEditorNavParams = TagEditorNavParams(chat: nil, chatListTag: ChatTagData(emoji: emoji, text: text), tagId: tagId) + } label: { + Label("Edit", systemImage: "pencil") + } + .tint(theme.colors.primary) + } + .background( + // isActive required to navigate to edit view from any possible tag edited in swipe action + NavigationLink(isActive: Binding(get: { tagEditorNavParams != nil }, set: { _ in tagEditorNavParams = nil })) { + if let params = tagEditorNavParams { + ChatListTagEditor( + chat: params.chat, + tagId: params.tagId, + emoji: params.chatListTag?.emoji, + name: params.chatListTag?.text ?? "" + ) + } + } label: { + EmptyView() + } + .opacity(0) + ) + } + .onMove(perform: moveItem) + + NavigationLink { + ChatListTagEditor(chat: chat) + } label: { + Label("Create list", systemImage: "plus") + } + } header: { + if showEditButton { + editTagsButton() + .textCase(nil) + .frame(maxWidth: .infinity, alignment: .trailing) + } + } + } + .modifier(ThemedBackground(grouped: true)) + .environment(\.editMode, $editMode) + } + + private func editTagsButton() -> some View { + if editMode.isEditing { + Button("Done") { + editMode = .inactive + dismiss() + } + } else { + Button("Edit") { + editMode = .active + } + } + } + + @ViewBuilder private func radioButton(selected: Bool) -> some View { + Image(systemName: selected ? "checkmark.circle.fill" : "circle") + .imageScale(.large) + .foregroundStyle(selected ? Color.accentColor : Color(.tertiaryLabel)) + } + + private func moveItem(from source: IndexSet, to destination: Int) { + Task { + do { + var tags = chatTagsModel.userTags + tags.move(fromOffsets: source, toOffset: destination) + try await apiReorderChatTags(tagIds: tags.map { $0.chatTagId }) + + await MainActor.run { + chatTagsModel.userTags = tags + } + } catch let error { + showAlert( + NSLocalizedString("Error reordering lists", comment: "alert title"), + message: responseError(error) + ) + } + } + } + + private func setTag(tagId: Int64?, chat: Chat) { + Task { + do { + let tagIds: [Int64] = if let t = tagId { [t] } else {[]} + let (userTags, chatTags) = try await apiSetChatTags( + type: chat.chatInfo.chatType, + id: chat.chatInfo.apiId, + tagIds: tagIds + ) + + await MainActor.run { + chatTagsModel.userTags = userTags + if var contact = chat.chatInfo.contact { + contact.chatTags = chatTags + m.updateContact(contact) + } else if var group = chat.chatInfo.groupInfo { + group.chatTags = chatTags + m.updateGroup(group) + } + dismiss() + } + } catch let error { + showAlert( + NSLocalizedString("Error saving chat list", comment: "alert title"), + message: responseError(error) + ) + } + } + } + + private func deleteTag(_ tagId: Int64) { + Task { + try await apiDeleteChatTag(tagId: tagId) + + await MainActor.run { + chatTagsModel.userTags = chatTagsModel.userTags.filter { $0.chatTagId != tagId } + if case let .userTag(tag) = chatTagsModel.activeFilter, tagId == tag.chatTagId { + chatTagsModel.activeFilter = nil + } + m.chats.forEach { c in + if var contact = c.chatInfo.contact, contact.chatTags.contains(tagId) { + contact.chatTags = contact.chatTags.filter({ $0 != tagId }) + m.updateContact(contact) + } else if var group = c.chatInfo.groupInfo, group.chatTags.contains(tagId) { + group.chatTags = group.chatTags.filter({ $0 != tagId }) + m.updateGroup(group) + } + } + } + } + } +} + +struct EmojiPickerView: UIViewControllerRepresentable { + @Binding var selectedEmoji: String? + @Binding var showingPicker: Bool + @Environment(\.presentationMode) var presentationMode + + class Coordinator: NSObject, ElegantEmojiPickerDelegate, UIAdaptivePresentationControllerDelegate { + var parent: EmojiPickerView + + init(parent: EmojiPickerView) { + self.parent = parent + } + + func emojiPicker(_ picker: ElegantEmojiPicker, didSelectEmoji emoji: Emoji?) { + parent.selectedEmoji = emoji?.emoji + parent.showingPicker = false + picker.dismiss(animated: true) + } + + // Called when the picker is dismissed manually (without selection) + func presentationControllerWillDismiss(_ presentationController: UIPresentationController) { + parent.showingPicker = false + } + } + + func makeCoordinator() -> Coordinator { + return Coordinator(parent: self) + } + + func makeUIViewController(context: Context) -> UIViewController { + let config = ElegantConfiguration(showRandom: false, showReset: true, showClose: false) + let picker = ElegantEmojiPicker(delegate: context.coordinator, configuration: config) + + picker.presentationController?.delegate = context.coordinator + + let viewController = UIViewController() + DispatchQueue.main.async { + if let topVC = getTopViewController() { + topVC.present(picker, animated: true) + } + } + + return viewController + } + + func updateUIViewController(_ uiViewController: UIViewController, context: Context) { + // No need to update the controller after creation + } +} + +struct ChatListTagEditor: View { + var chat: Chat? = nil + var tagId: Int64? = nil + @Environment(\.dismiss) var dismiss: DismissAction + @EnvironmentObject var chatTagsModel: ChatTagsModel + @EnvironmentObject var theme: AppTheme + var emoji: String? + var name: String = "" + @State private var newEmoji: String? + @State private var newName: String = "" + @State private var isPickerPresented = false + @State private var saving: Bool? + + var body: some View { + VStack { + List { + let isDuplicateEmojiOrName = chatTagsModel.userTags.contains { tag in + tag.chatTagId != tagId && + ((newEmoji != nil && tag.chatTagEmoji == newEmoji) || tag.chatTagText == trimmedName) + } + + Section { + HStack { + Button { + isPickerPresented = true + } label: { + if let newEmoji { + Text(newEmoji) + } else { + Image(systemName: "face.smiling") + .foregroundColor(.secondary) + } + } + TextField("List name...", text: $newName) + } + + Button { + saving = true + if let tId = tagId { + updateChatTag(tagId: tId, chatTagData: ChatTagData(emoji: newEmoji, text: trimmedName)) + } else { + createChatTag() + } + } label: { + Text(NSLocalizedString(tagId == nil ? "Create list" : "Save list", comment: "list editor button")) + } + .disabled(saving != nil || (trimmedName == name && newEmoji == emoji) || trimmedName.isEmpty || isDuplicateEmojiOrName) + } footer: { + if isDuplicateEmojiOrName && saving != false { // if not saved already, to prevent flickering + HStack { + Image(systemName: "exclamationmark.circle") + .foregroundColor(.red) + Text("List name and emoji should be different for all lists.") + .foregroundColor(theme.colors.secondary) + } + } + } + } + + if isPickerPresented { + EmojiPickerView(selectedEmoji: $newEmoji, showingPicker: $isPickerPresented) + } + } + .modifier(ThemedBackground(grouped: true)) + .onAppear { + newEmoji = emoji + newName = name + } + } + + var trimmedName: String { + newName.trimmingCharacters(in: .whitespaces) + } + + private func createChatTag() { + Task { + do { + let userTags = try await apiCreateChatTag( + tag: ChatTagData(emoji: newEmoji , text: trimmedName) + ) + await MainActor.run { + saving = false + chatTagsModel.userTags = userTags + dismiss() + } + } catch let error { + await MainActor.run { + saving = nil + showAlert( + NSLocalizedString("Error creating list", comment: "alert title"), + message: responseError(error) + ) + } + } + } + } + + private func updateChatTag(tagId: Int64, chatTagData: ChatTagData) { + Task { + do { + try await apiUpdateChatTag(tagId: tagId, tag: chatTagData) + await MainActor.run { + saving = false + for i in 0.. Alert { Alert( title: Text("Reject contact request"), @@ -585,15 +1044,15 @@ struct ChatListNavLink_Previews: PreviewProvider { ChatListNavLink(chat: Chat( chatInfo: ChatInfo.sampleData.direct, chatItems: [ChatItem.getSample(1, .directSnd, .now, "hello")] - )) + ), parentSheet: .constant(nil)) ChatListNavLink(chat: Chat( chatInfo: ChatInfo.sampleData.direct, chatItems: [ChatItem.getSample(1, .directSnd, .now, "hello")] - )) + ), parentSheet: .constant(nil)) ChatListNavLink(chat: Chat( chatInfo: ChatInfo.sampleData.contactRequest, chatItems: [] - )) + ), parentSheet: .constant(nil)) } .previewLayout(.fixed(width: 360, height: 82)) } diff --git a/apps/ios/Shared/Views/ChatList/ChatListView.swift b/apps/ios/Shared/Views/ChatList/ChatListView.swift index b18e9295b9..d3ed26161d 100644 --- a/apps/ios/Shared/Views/ChatList/ChatListView.swift +++ b/apps/ios/Shared/Views/ChatList/ChatListView.swift @@ -31,6 +31,29 @@ enum UserPickerSheet: Identifiable { } } +enum PresetTag: Int, Identifiable, CaseIterable, Equatable { + case favorites = 0 + case contacts = 1 + case groups = 2 + case business = 3 + + var id: Int { rawValue } +} + +enum ActiveFilter: Identifiable, Equatable { + case presetTag(PresetTag) + case userTag(ChatTag) + case unread + + var id: String { + switch self { + case let .presetTag(tag): "preset \(tag.id)" + case let .userTag(tag): "user \(tag.chatTagId)" + case .unread: "unread" + } + } +} + class SaveableSettings: ObservableObject { @Published var servers: ServerSettings = ServerSettings(currUserServers: [], userServers: [], serverErrors: []) } @@ -117,13 +140,14 @@ struct ChatListView: View { @State private var searchChatFilteredBySimplexLink: String? = nil @State private var scrollToSearchBar = false @State private var userPickerShown: Bool = false - - @AppStorage(DEFAULT_SHOW_UNREAD_AND_FAVORITES) private var showUnreadAndFavorites = false + @State private var sheet: SomeSheet? = nil + @StateObject private var chatTagsModel = ChatTagsModel.shared + @AppStorage(GROUP_DEFAULT_ONE_HAND_UI, store: groupDefaults) private var oneHandUI = true @AppStorage(DEFAULT_ONE_HAND_UI_CARD_SHOWN) private var oneHandUICardShown = false @AppStorage(DEFAULT_ADDRESS_CREATION_CARD_SHOWN) private var addressCreationCardShown = false @AppStorage(DEFAULT_TOOLBAR_MATERIAL) private var toolbarMaterial = ToolbarMaterial.defaultMaterial - + var body: some View { if #available(iOS 16.0, *) { viewBody.scrollDismissesKeyboard(.immediately) @@ -131,7 +155,7 @@ struct ChatListView: View { viewBody } } - + private var viewBody: some View { ZStack(alignment: oneHandUI ? .bottomLeading : .topLeading) { NavStackCompat( @@ -161,8 +185,9 @@ struct ChatListView: View { } } } + .environmentObject(chatTagsModel) } - + private var chatListView: some View { let tm = ToolbarMaterial.material(toolbarMaterial) return withToolbar(tm) { @@ -197,15 +222,22 @@ struct ChatListView: View { Divider().padding(.bottom, Self.hasHomeIndicator ? 0 : 8).background(tm) } } + .sheet(item: $sheet) { sheet in + if #available(iOS 16.0, *) { + sheet.content.presentationDetents([.fraction(sheet.fraction)]) + } else { + sheet.content + } + } } - + static var hasHomeIndicator: Bool = { if let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene, let window = windowScene.windows.first { window.safeAreaInsets.bottom > 0 } else { false } }() - + @ViewBuilder func withToolbar(_ material: Material, content: () -> some View) -> some View { if #available(iOS 16.0, *) { if oneHandUI { @@ -226,13 +258,13 @@ struct ChatListView: View { } } } - + @ToolbarContentBuilder var topToolbar: some ToolbarContent { ToolbarItem(placement: .topBarLeading) { leadingToolbarItem } ToolbarItem(placement: .principal) { SubsStatusIndicator() } ToolbarItem(placement: .topBarTrailing) { trailingToolbarItem } } - + @ToolbarContentBuilder var bottomToolbar: some ToolbarContent { let padding: Double = Self.hasHomeIndicator ? 0 : 14 ToolbarItem(placement: .bottomBar) { @@ -247,7 +279,7 @@ struct ChatListView: View { .onTapGesture { scrollToSearchBar = true } } } - + @ToolbarContentBuilder var bottomToolbarGroup: some ToolbarContent { let padding: Double = Self.hasHomeIndicator ? 0 : 14 ToolbarItemGroup(placement: .bottomBar) { @@ -258,7 +290,7 @@ struct ChatListView: View { trailingToolbarItem.padding(.bottom, padding) } } - + @ViewBuilder var leadingToolbarItem: some View { let user = chatModel.currentUser ?? User.sampleData ZStack(alignment: .topTrailing) { @@ -275,7 +307,7 @@ struct ChatListView: View { userPickerShown = true } } - + @ViewBuilder var trailingToolbarItem: some View { switch chatModel.chatRunning { case .some(true): NewChatMenuButton() @@ -283,7 +315,7 @@ struct ChatListView: View { case .none: EmptyView() } } - + @ViewBuilder private var chatList: some View { let cs = filteredChats() ZStack { @@ -295,7 +327,8 @@ struct ChatListView: View { searchFocussed: $searchFocussed, searchText: $searchText, searchShowingSimplexLink: $searchShowingSimplexLink, - searchChatFilteredBySimplexLink: $searchChatFilteredBySimplexLink + searchChatFilteredBySimplexLink: $searchChatFilteredBySimplexLink, + parentSheet: $sheet ) .scaleEffect(x: 1, y: oneHandUI ? -1 : 1, anchor: .center) .listRowSeparator(.hidden) @@ -306,7 +339,7 @@ struct ChatListView: View { } if #available(iOS 16.0, *) { ForEach(cs, id: \.viewId) { chat in - ChatListNavLink(chat: chat) + ChatListNavLink(chat: chat, parentSheet: $sheet) .scaleEffect(x: 1, y: oneHandUI ? -1 : 1, anchor: .center) .padding(.trailing, -16) .disabled(chatModel.chatRunning != true || chatModel.deletedChats.contains(chat.chatInfo.id)) @@ -318,7 +351,7 @@ struct ChatListView: View { VStack(spacing: .zero) { Divider() .padding(.leading, 16) - ChatListNavLink(chat: chat) + ChatListNavLink(chat: chat, parentSheet: $sheet) .padding(.horizontal, 8) .padding(.vertical, 6) } @@ -363,80 +396,97 @@ struct ChatListView: View { } } if cs.isEmpty && !chatModel.chats.isEmpty { - Text("No filtered chats") + noChatsView() .scaleEffect(x: 1, y: oneHandUI ? -1 : 1, anchor: .center) .foregroundColor(.secondary) } } } + + @ViewBuilder private func noChatsView() -> some View { + if searchString().isEmpty { + switch chatTagsModel.activeFilter { + case .presetTag: Text("No filtered chats") // this should not happen + case let .userTag(tag): Text("No chats in list \(tag.chatTagText)") + case .unread: + Button { + chatTagsModel.activeFilter = nil + } label: { + HStack { + Image(systemName: "line.3.horizontal.decrease") + Text("No unread chats") + } + } + case .none: Text("No chats") + } + } else { + Text("No chats found") + } + } + private func unreadBadge(size: CGFloat = 18) -> some View { Circle() .frame(width: size, height: size) .foregroundColor(theme.colors.primary) } - + @ViewBuilder private func chatView() -> some View { if let chatId = chatModel.chatId, let chat = chatModel.getChat(chatId) { ChatView(chat: chat) } } - + func stopAudioPlayer() { VoiceItemState.smallView.values.forEach { $0.audioPlayer?.stop() } VoiceItemState.smallView = [:] } - + private func filteredChats() -> [Chat] { if let linkChatId = searchChatFilteredBySimplexLink { return chatModel.chats.filter { $0.id == linkChatId } } else { let s = searchString() - return s == "" && !showUnreadAndFavorites + return s == "" ? chatModel.chats.filter { chat in - !chat.chatInfo.chatDeleted && chatContactType(chat: chat) != ContactType.card + !chat.chatInfo.chatDeleted && !chat.chatInfo.contactCard && filtered(chat) } : chatModel.chats.filter { chat in let cInfo = chat.chatInfo - switch cInfo { + return switch cInfo { case let .direct(contact): - return !contact.chatDeleted && chatContactType(chat: chat) != ContactType.card && ( - s == "" - ? filtered(chat) - : (viewNameContains(cInfo, s) || - contact.profile.displayName.localizedLowercase.contains(s) || - contact.fullName.localizedLowercase.contains(s)) + !contact.chatDeleted && !chat.chatInfo.contactCard && ( + ( viewNameContains(cInfo, s) || + contact.profile.displayName.localizedLowercase.contains(s) || + contact.fullName.localizedLowercase.contains(s) + ) ) - case let .group(gInfo): - return s == "" - ? (filtered(chat) || gInfo.membership.memberStatus == .memInvited) - : viewNameContains(cInfo, s) - case .local: - return s == "" || viewNameContains(cInfo, s) - case .contactRequest: - return s == "" || viewNameContains(cInfo, s) - case let .contactConnection(conn): - return s != "" && conn.localAlias.localizedLowercase.contains(s) - case .invalidJSON: - return false + case .group: viewNameContains(cInfo, s) + case .local: viewNameContains(cInfo, s) + case .contactRequest: viewNameContains(cInfo, s) + case let .contactConnection(conn): conn.localAlias.localizedLowercase.contains(s) + case .invalidJSON: false } } } - - func searchString() -> String { - searchShowingSimplexLink ? "" : searchText.trimmingCharacters(in: .whitespaces).localizedLowercase - } - + func filtered(_ chat: Chat) -> Bool { - (chat.chatInfo.chatSettings?.favorite ?? false) || - chat.chatStats.unreadChat || - (chat.chatInfo.ntfsEnabled && chat.chatStats.unreadCount > 0) + switch chatTagsModel.activeFilter { + case let .presetTag(tag): presetTagMatchesChat(tag, chat) + case let .userTag(tag): chat.chatInfo.chatTags?.contains(tag.chatTagId) == true + case .unread: chat.chatStats.unreadChat || chat.chatInfo.ntfsEnabled && chat.chatStats.unreadCount > 0 + case .none: true + } } - + func viewNameContains(_ cInfo: ChatInfo, _ s: String) -> Bool { cInfo.chatViewName.localizedLowercase.contains(s) } } + + func searchString() -> String { + searchShowingSimplexLink ? "" : searchText.trimmingCharacters(in: .whitespaces).localizedLowercase + } } struct SubsStatusIndicator: View { @@ -500,18 +550,20 @@ struct SubsStatusIndicator: View { struct ChatListSearchBar: View { @EnvironmentObject var m: ChatModel @EnvironmentObject var theme: AppTheme + @EnvironmentObject var chatTagsModel: ChatTagsModel @Binding var searchMode: Bool @FocusState.Binding var searchFocussed: Bool @Binding var searchText: String @Binding var searchShowingSimplexLink: Bool @Binding var searchChatFilteredBySimplexLink: String? + @Binding var parentSheet: SomeSheet? @State private var ignoreSearchTextChange = false @State private var alert: PlanAndConnectAlert? @State private var sheet: PlanAndConnectActionSheet? - @AppStorage(DEFAULT_SHOW_UNREAD_AND_FAVORITES) private var showUnreadAndFavorites = false var body: some View { VStack(spacing: 12) { + ScrollView([.horizontal], showsIndicators: false) { ChatTagsView(parentSheet: $parentSheet) } HStack(spacing: 12) { HStack(spacing: 4) { Image(systemName: "magnifyingglass") @@ -578,16 +630,21 @@ struct ChatListSearchBar: View { } private func toggleFilterButton() -> some View { - ZStack { + let showUnread = chatTagsModel.activeFilter == .unread + return ZStack { Color.clear .frame(width: 22, height: 22) - Image(systemName: showUnreadAndFavorites ? "line.3.horizontal.decrease.circle.fill" : "line.3.horizontal.decrease") + Image(systemName: showUnread ? "line.3.horizontal.decrease.circle.fill" : "line.3.horizontal.decrease") .resizable() .scaledToFit() - .foregroundColor(showUnreadAndFavorites ? theme.colors.primary : theme.colors.secondary) - .frame(width: showUnreadAndFavorites ? 22 : 16, height: showUnreadAndFavorites ? 22 : 16) + .foregroundColor(showUnread ? theme.colors.primary : theme.colors.secondary) + .frame(width: showUnread ? 22 : 16, height: showUnread ? 22 : 16) .onTapGesture { - showUnreadAndFavorites = !showUnreadAndFavorites + if chatTagsModel.activeFilter == .unread { + chatTagsModel.activeFilter = nil + } else { + chatTagsModel.activeFilter = .unread + } } } } @@ -605,6 +662,179 @@ struct ChatListSearchBar: View { } } +struct ChatTagsView: View { + @EnvironmentObject var chatTagsModel: ChatTagsModel + @EnvironmentObject var chatModel: ChatModel + @Binding var parentSheet: SomeSheet? + + var body: some View { + HStack { + tagsView() + } + } + + @ViewBuilder private func tagsView() -> some View { + if chatTagsModel.presetTags.count > 1 { + if chatTagsModel.presetTags.count + chatTagsModel.userTags.count <= 3 { + expandedPresetTagsFiltersView() + } else { + collapsedTagsFilterView() + } + } + ForEach(chatTagsModel.userTags, id: \.id) { tag in + let current = if case let .userTag(t) = chatTagsModel.activeFilter { + t == tag + } else { + false + } + + let color: Color = current ? .accentColor : .secondary + ZStack { + HStack(spacing: 4) { + if let emoji = tag.chatTagEmoji { + Text(emoji) + } else { + Image(systemName: current ? "tag.fill" : "tag") + .foregroundColor(color) + } + ZStack { + Text(tag.chatTagText).fontWeight(.semibold).foregroundColor(.clear) + Text(tag.chatTagText).fontWeight(current ? .semibold : .regular).foregroundColor(color) + } + } + .onTapGesture { + setActiveFilter(filter: .userTag(tag)) + } + .onLongPressGesture { + let screenHeight = UIScreen.main.bounds.height + let reservedSpace: Double = 4 * 44 // 2 for padding, 1 for "Create list" and another for extra tag + let tagsSpace = Double(max(chatTagsModel.userTags.count, 3)) * 44 + let fraction = min((reservedSpace + tagsSpace) / screenHeight, 0.62) + + parentSheet = SomeSheet( + content: { + AnyView( + NavigationView { + ChatListTag(chat: nil, showEditButton: true) + .modifier(ThemedBackground(grouped: true)) + } + ) + }, + id: "tag list", + fraction: fraction + ) + } + } + } + + Button { + parentSheet = SomeSheet( + content: { + AnyView( + NavigationView { + ChatListTagEditor() + } + ) + }, + id: "tag create" + ) + } label: { + if chatTagsModel.userTags.isEmpty { + HStack(spacing: 4) { + Image(systemName: "plus") + Text("Add list") + } + } else { + Image(systemName: "plus") + } + } + .foregroundColor(.secondary) + } + + @ViewBuilder private func expandedPresetTagsFiltersView() -> some View { + let selectedPresetTag: PresetTag? = if case let .presetTag(tag) = chatTagsModel.activeFilter { + tag + } else { + nil + } + ForEach(chatTagsModel.presetTags, id: \.id) { tag in + let active = tag == selectedPresetTag + let (icon, text) = presetTagLabel(tag: tag, active: active) + let color: Color = active ? .accentColor : .secondary + + HStack(spacing: 4) { + Image(systemName: icon) + .foregroundColor(color) + ZStack { + Text(text).fontWeight(.semibold).foregroundColor(.clear) + Text(text).fontWeight(active ? .semibold : .regular).foregroundColor(color) + } + } + .onTapGesture { + setActiveFilter(filter: .presetTag(tag)) + } + } + } + + @ViewBuilder private func collapsedTagsFilterView() -> some View { + let selectedPresetTag: PresetTag? = if case let .presetTag(tag) = chatTagsModel.activeFilter { + tag + } else { + nil + } + Menu { + if selectedPresetTag != nil { + Button { + chatTagsModel.activeFilter = nil + } label: { + HStack { + Image(systemName: "list.bullet") + Text("All") + } + } + } + ForEach(chatTagsModel.presetTags, id: \.id) { tag in + Button { + setActiveFilter(filter: .presetTag(tag)) + } label: { + let (systemName, text) = presetTagLabel(tag: tag, active: tag == selectedPresetTag) + HStack { + Image(systemName: systemName) + Text(text) + } + } + } + } label: { + if let tag = selectedPresetTag { + let (systemName, _) = presetTagLabel(tag: tag, active: true) + Image(systemName: systemName) + .foregroundColor(.accentColor) + } else { + Image(systemName: "list.bullet") + .foregroundColor(.secondary) + } + } + .frame(minWidth: 28) + } + + private func presetTagLabel(tag: PresetTag, active: Bool) -> (String, LocalizedStringKey) { + switch tag { + case .favorites: (active ? "star.fill" : "star", "Favorites") + case .contacts: (active ? "person.fill" : "person", "Contacts") + case .groups: (active ? "person.2.fill" : "person.2", "Groups") + case .business: (active ? "briefcase.fill" : "briefcase", "Businesses") + } + } + + private func setActiveFilter(filter: ActiveFilter) { + if filter != chatTagsModel.activeFilter { + chatTagsModel.activeFilter = filter + } else { + chatTagsModel.activeFilter = nil + } + } +} + func chatStoppedIcon() -> some View { Button { AlertManager.shared.showAlertMsg( @@ -616,6 +846,28 @@ func chatStoppedIcon() -> some View { } } +func presetTagMatchesChat(_ tag: PresetTag, _ chat: Chat) -> Bool { + switch tag { + case .favorites: + chat.chatInfo.chatSettings?.favorite == true + case .contacts: + switch chat.chatInfo { + case let .direct(contact): !(contact.activeConn == nil && contact.profile.contactLink != nil && contact.active) && !contact.chatDeleted + case .contactRequest: true + case .contactConnection: true + case let .group(groupInfo): groupInfo.businessChat?.chatType == .customer + default: false + } + case .groups: + switch chat.chatInfo { + case let .group(groupInfo): groupInfo.businessChat == nil + default: false + } + case .business: + chat.chatInfo.groupInfo?.businessChat?.chatType == .business + } +} + struct ChatListView_Previews: PreviewProvider { @State static var userPickerSheet: UserPickerSheet? = .none diff --git a/apps/ios/Shared/Views/Contacts/ContactListNavLink.swift b/apps/ios/Shared/Views/Contacts/ContactListNavLink.swift index 898a47cc86..242b492e83 100644 --- a/apps/ios/Shared/Views/Contacts/ContactListNavLink.swift +++ b/apps/ios/Shared/Views/Contacts/ContactListNavLink.swift @@ -20,7 +20,7 @@ struct ContactListNavLink: View { @State private var showContactRequestDialog = false var body: some View { - let contactType = chatContactType(chat: chat) + let contactType = chatContactType(chat) Group { switch (chat.chatInfo) { diff --git a/apps/ios/Shared/Views/NewChat/NewChatMenuButton.swift b/apps/ios/Shared/Views/NewChat/NewChatMenuButton.swift index 6f973983bf..39656c1534 100644 --- a/apps/ios/Shared/Views/NewChat/NewChatMenuButton.swift +++ b/apps/ios/Shared/Views/NewChat/NewChatMenuButton.swift @@ -186,7 +186,7 @@ struct NewChatSheet: View { } } -func chatContactType(chat: Chat) -> ContactType { +func chatContactType(_ chat: Chat) -> ContactType { switch chat.chatInfo { case .contactRequest: return .request @@ -207,7 +207,7 @@ func chatContactType(chat: Chat) -> ContactType { private func filterContactTypes(chats: [Chat], contactTypes: [ContactType]) -> [Chat] { return chats.filter { chat in - contactTypes.contains(chatContactType(chat: chat)) + contactTypes.contains(chatContactType(chat)) } } @@ -279,8 +279,8 @@ struct ContactsList: View { } private func chatsByTypeComparator(chat1: Chat, chat2: Chat) -> Bool { - let chat1Type = chatContactType(chat: chat1) - let chat2Type = chatContactType(chat: chat2) + let chat1Type = chatContactType(chat1) + let chat2Type = chatContactType(chat2) if chat1Type.rawValue < chat2Type.rawValue { return true diff --git a/apps/ios/Shared/Views/NewChat/NewChatView.swift b/apps/ios/Shared/Views/NewChat/NewChatView.swift index e18d932278..6e898f4cdf 100644 --- a/apps/ios/Shared/Views/NewChat/NewChatView.swift +++ b/apps/ios/Shared/Views/NewChat/NewChatView.swift @@ -25,6 +25,7 @@ struct SomeActionSheet: Identifiable { struct SomeSheet: Identifiable { @ViewBuilder var content: Content var id: String + var fraction = 0.4 } private enum NewChatViewAlert: Identifiable { diff --git a/apps/ios/Shared/Views/Onboarding/AddressCreationCard.swift b/apps/ios/Shared/Views/Onboarding/AddressCreationCard.swift index 2069ca9487..c8d0faafa7 100644 --- a/apps/ios/Shared/Views/Onboarding/AddressCreationCard.swift +++ b/apps/ios/Shared/Views/Onboarding/AddressCreationCard.swift @@ -21,7 +21,7 @@ struct AddressCreationCard: View { var body: some View { let addressExists = chatModel.userAddress != nil let chats = chatModel.chats.filter { chat in - !chat.chatInfo.chatDeleted && chatContactType(chat: chat) != ContactType.card + !chat.chatInfo.chatDeleted && !chat.chatInfo.contactCard } ZStack(alignment: .topTrailing) { HStack(alignment: .top, spacing: 16) { diff --git a/apps/ios/SimpleX.xcodeproj/project.pbxproj b/apps/ios/SimpleX.xcodeproj/project.pbxproj index 4fde84269e..ef98ddc678 100644 --- a/apps/ios/SimpleX.xcodeproj/project.pbxproj +++ b/apps/ios/SimpleX.xcodeproj/project.pbxproj @@ -203,6 +203,7 @@ 8CC4ED902BD7B8530078AEE8 /* CallAudioDeviceManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8CC4ED8F2BD7B8530078AEE8 /* CallAudioDeviceManager.swift */; }; 8CC956EE2BC0041000412A11 /* NetworkObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8CC956ED2BC0041000412A11 /* NetworkObserver.swift */; }; 8CE848A32C5A0FA000D5C7C8 /* SelectableChatItemToolbars.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8CE848A22C5A0FA000D5C7C8 /* SelectableChatItemToolbars.swift */; }; + B728945B2D0C62BF00F7A19A /* ElegantEmojiPicker in Frameworks */ = {isa = PBXBuildFile; productRef = B728945A2D0C62BF00F7A19A /* ElegantEmojiPicker */; }; B73EFE532CE5FA3500C778EA /* CreateSimpleXAddress.swift in Sources */ = {isa = PBXBuildFile; fileRef = B73EFE522CE5FA3500C778EA /* CreateSimpleXAddress.swift */; }; B76E6C312C5C41D900EC11AA /* ContactListNavLink.swift in Sources */ = {isa = PBXBuildFile; fileRef = B76E6C302C5C41D900EC11AA /* ContactListNavLink.swift */; }; B79ADAFF2CE4EF930083DFFD /* AddressCreationCard.swift in Sources */ = {isa = PBXBuildFile; fileRef = B79ADAFE2CE4EF930083DFFD /* AddressCreationCard.swift */; }; @@ -636,6 +637,7 @@ buildActionMask = 2147483647; files = ( 5CE2BA702845308900EC33A6 /* SimpleXChat.framework in Frameworks */, + B728945B2D0C62BF00F7A19A /* ElegantEmojiPicker in Frameworks */, 8C8118722C220B5B00E6FC94 /* Yams in Frameworks */, 8CB3476C2CF5CFFA006787A5 /* Ink in Frameworks */, D741547829AF89AF0022400A /* StoreKit.framework in Frameworks */, @@ -1186,6 +1188,7 @@ D7197A1729AE89660055C05A /* WebRTC */, 8C8118712C220B5B00E6FC94 /* Yams */, 8CB3476B2CF5CFFA006787A5 /* Ink */, + B728945A2D0C62BF00F7A19A /* ElegantEmojiPicker */, ); productName = "SimpleX (iOS)"; productReference = 5CA059CA279559F40002BEB4 /* SimpleX.app */; @@ -1330,6 +1333,7 @@ D7197A1629AE89660055C05A /* XCRemoteSwiftPackageReference "WebRTC" */, 8C73C1162C21E17B00892670 /* XCRemoteSwiftPackageReference "Yams" */, 8CB3476A2CF5CFFA006787A5 /* XCRemoteSwiftPackageReference "ink" */, + B72894592D0C62BF00F7A19A /* XCRemoteSwiftPackageReference "Elegant-Emoji-Picker" */, ); productRefGroup = 5CA059CB279559F40002BEB4 /* Products */; projectDirPath = ""; @@ -2387,6 +2391,14 @@ version = 0.6.0; }; }; + B72894592D0C62BF00F7A19A /* XCRemoteSwiftPackageReference "Elegant-Emoji-Picker" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/Finalet/Elegant-Emoji-Picker"; + requirement = { + branch = main; + kind = branch; + }; + }; D7197A1629AE89660055C05A /* XCRemoteSwiftPackageReference "WebRTC" */ = { isa = XCRemoteSwiftPackageReference; repositoryURL = "https://github.com/simplex-chat/WebRTC.git"; @@ -2429,6 +2441,11 @@ package = 8CB3476A2CF5CFFA006787A5 /* XCRemoteSwiftPackageReference "ink" */; productName = Ink; }; + B728945A2D0C62BF00F7A19A /* ElegantEmojiPicker */ = { + isa = XCSwiftPackageProductDependency; + package = B72894592D0C62BF00F7A19A /* XCRemoteSwiftPackageReference "Elegant-Emoji-Picker" */; + productName = ElegantEmojiPicker; + }; CE38A29B2C3FCD72005ED185 /* SwiftyGif */ = { isa = XCSwiftPackageProductDependency; package = D77B92DA2952372200A5A1CC /* XCRemoteSwiftPackageReference "SwiftyGif" */; diff --git a/apps/ios/SimpleX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/apps/ios/SimpleX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 7fdbff38af..2bddf5b5b8 100644 --- a/apps/ios/SimpleX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/apps/ios/SimpleX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -1,5 +1,5 @@ { - "originHash" : "33afc44be5f4225325b3cb940ed71b6cbf3ef97290d348d7b6803697bcd0637d", + "originHash" : "07434ae88cbf078ce3d27c91c1f605836aaebff0e0cef5f25317795151c77db1", "pins" : [ { "identity" : "codescanner", @@ -10,6 +10,15 @@ "version" : "2.5.0" } }, + { + "identity" : "elegant-emoji-picker", + "kind" : "remoteSourceControl", + "location" : "https://github.com/Finalet/Elegant-Emoji-Picker", + "state" : { + "branch" : "main", + "revision" : "71d2d46092b4d550cc593614efc06438f845f6e6" + } + }, { "identity" : "ink", "kind" : "remoteSourceControl", diff --git a/apps/ios/SimpleXChat/APITypes.swift b/apps/ios/SimpleXChat/APITypes.swift index 884993f542..66edb9f2b2 100644 --- a/apps/ios/SimpleXChat/APITypes.swift +++ b/apps/ios/SimpleXChat/APITypes.swift @@ -40,10 +40,16 @@ public enum ChatCommand { case testStorageEncryption(key: String) case apiSaveSettings(settings: AppSettings) case apiGetSettings(settings: AppSettings) + case apiGetChatTags(userId: Int64) case apiGetChats(userId: Int64) case apiGetChat(type: ChatType, id: Int64, pagination: ChatPagination, search: String) case apiGetChatItemInfo(type: ChatType, id: Int64, itemId: Int64) case apiSendMessages(type: ChatType, id: Int64, live: Bool, ttl: Int?, composedMessages: [ComposedMessage]) + case apiCreateChatTag(tag: ChatTagData) + case apiSetChatTags(type: ChatType, id: Int64, tagIds: [Int64]) + case apiDeleteChatTag(tagId: Int64) + case apiUpdateChatTag(tagId: Int64, tagData: ChatTagData) + case apiReorderChatTags(tagIds: [Int64]) case apiCreateChatItems(noteFolderId: Int64, composedMessages: [ComposedMessage]) case apiUpdateChatItem(type: ChatType, id: Int64, itemId: Int64, msg: MsgContent, live: Bool) case apiDeleteChatItem(type: ChatType, id: Int64, itemIds: [Int64], mode: CIDeleteMode) @@ -198,6 +204,7 @@ public enum ChatCommand { case let .testStorageEncryption(key): return "/db test key \(key)" case let .apiSaveSettings(settings): return "/_save app settings \(encodeJSON(settings))" case let .apiGetSettings(settings): return "/_get app settings \(encodeJSON(settings))" + case let .apiGetChatTags(userId): return "/_get tags \(userId)" case let .apiGetChats(userId): return "/_get chats \(userId) pcc=on" case let .apiGetChat(type, id, pagination, search): return "/_get chat \(ref(type, id)) \(pagination.cmdString)" + (search == "" ? "" : " search=\(search)") @@ -206,6 +213,11 @@ public enum ChatCommand { let msgs = encodeJSON(composedMessages) let ttlStr = ttl != nil ? "\(ttl!)" : "default" return "/_send \(ref(type, id)) live=\(onOff(live)) ttl=\(ttlStr) json \(msgs)" + case let .apiCreateChatTag(tag): return "/_create tag \(encodeJSON(tag))" + case let .apiSetChatTags(type, id, tagIds): return "/_tags \(ref(type, id)) \(tagIds.map({ "\($0)" }).joined(separator: ","))" + case let .apiDeleteChatTag(tagId): return "/_delete tag \(tagId)" + case let .apiUpdateChatTag(tagId, tagData): return "/_update tag \(tagId) \(encodeJSON(tagData))" + case let .apiReorderChatTags(tagIds): return "/_reorder tags \(tagIds.map({ "\($0)" }).joined(separator: ","))" case let .apiCreateChatItems(noteFolderId, composedMessages): let msgs = encodeJSON(composedMessages) return "/_create *\(noteFolderId) json \(msgs)" @@ -367,10 +379,16 @@ public enum ChatCommand { case .testStorageEncryption: return "testStorageEncryption" case .apiSaveSettings: return "apiSaveSettings" case .apiGetSettings: return "apiGetSettings" + case .apiGetChatTags: return "apiGetChatTags" case .apiGetChats: return "apiGetChats" case .apiGetChat: return "apiGetChat" case .apiGetChatItemInfo: return "apiGetChatItemInfo" case .apiSendMessages: return "apiSendMessages" + case .apiCreateChatTag: return "apiCreateChatTag" + case .apiSetChatTags: return "apiSetChatTags" + case .apiDeleteChatTag: return "apiDeleteChatTag" + case .apiUpdateChatTag: return "apiUpdateChatTag" + case .apiReorderChatTags: return "apiReorderChatTags" case .apiCreateChatItems: return "apiCreateChatItems" case .apiUpdateChatItem: return "apiUpdateChatItem" case .apiDeleteChatItem: return "apiDeleteChatItem" @@ -564,6 +582,7 @@ public enum ChatResponse: Decodable, Error { case chatSuspended case apiChats(user: UserRef, chats: [ChatData]) case apiChat(user: UserRef, chat: ChatData) + case chatTags(user: UserRef, userTags: [ChatTag]) case chatItemInfo(user: UserRef, chatItem: AChatItem, chatItemInfo: ChatItemInfo) case serverTestResult(user: UserRef, testServer: String, testFailure: ProtocolTestFailure?) case serverOperatorConditions(conditions: ServerOperatorConditions) @@ -590,6 +609,7 @@ public enum ChatResponse: Decodable, Error { case contactCode(user: UserRef, contact: Contact, connectionCode: String) case groupMemberCode(user: UserRef, groupInfo: GroupInfo, member: GroupMember, connectionCode: String) case connectionVerified(user: UserRef, verified: Bool, expectedCode: String) + case tagsUpdated(user: UserRef, userTags: [ChatTag], chatTags: [Int64]) case invitation(user: UserRef, connReqInvitation: String, connection: PendingContactConnection) case connectionIncognitoUpdated(user: UserRef, toConnection: PendingContactConnection) case connectionUserChanged(user: UserRef, fromConnection: PendingContactConnection, toConnection: PendingContactConnection, newUser: UserRef) @@ -741,6 +761,7 @@ public enum ChatResponse: Decodable, Error { case .chatSuspended: return "chatSuspended" case .apiChats: return "apiChats" case .apiChat: return "apiChat" + case .chatTags: return "chatTags" case .chatItemInfo: return "chatItemInfo" case .serverTestResult: return "serverTestResult" case .serverOperatorConditions: return "serverOperators" @@ -767,6 +788,7 @@ public enum ChatResponse: Decodable, Error { case .contactCode: return "contactCode" case .groupMemberCode: return "groupMemberCode" case .connectionVerified: return "connectionVerified" + case .tagsUpdated: return "tagsUpdated" case .invitation: return "invitation" case .connectionIncognitoUpdated: return "connectionIncognitoUpdated" case .connectionUserChanged: return "connectionUserChanged" @@ -914,6 +936,7 @@ public enum ChatResponse: Decodable, Error { case .chatSuspended: return noDetails case let .apiChats(u, chats): return withUser(u, String(describing: chats)) case let .apiChat(u, chat): return withUser(u, String(describing: chat)) + case let .chatTags(u, userTags): return withUser(u, "userTags: \(String(describing: userTags))") case let .chatItemInfo(u, chatItem, chatItemInfo): return withUser(u, "chatItem: \(String(describing: chatItem))\nchatItemInfo: \(String(describing: chatItemInfo))") case let .serverTestResult(u, server, testFailure): return withUser(u, "server: \(server)\nresult: \(String(describing: testFailure))") case let .serverOperatorConditions(conditions): return "conditions: \(String(describing: conditions))" @@ -942,6 +965,7 @@ public enum ChatResponse: Decodable, Error { case let .contactCode(u, contact, connectionCode): return withUser(u, "contact: \(String(describing: contact))\nconnectionCode: \(connectionCode)") case let .groupMemberCode(u, groupInfo, member, connectionCode): return withUser(u, "groupInfo: \(String(describing: groupInfo))\nmember: \(String(describing: member))\nconnectionCode: \(connectionCode)") case let .connectionVerified(u, verified, expectedCode): return withUser(u, "verified: \(verified)\nconnectionCode: \(expectedCode)") + case let .tagsUpdated(u, userTags, chatTags): return withUser(u, "userTags: \(String(describing: userTags))\nchatTags: \(String(describing: chatTags))") case let .invitation(u, connReqInvitation, connection): return withUser(u, "connReqInvitation: \(connReqInvitation)\nconnection: \(connection)") case let .connectionIncognitoUpdated(u, toConnection): return withUser(u, String(describing: toConnection)) case let .connectionUserChanged(u, fromConnection, toConnection, newUser): return withUser(u, "fromConnection: \(String(describing: fromConnection))\ntoConnection: \(String(describing: toConnection))\newUserId: \(String(describing: newUser.userId))") @@ -1172,6 +1196,16 @@ public enum ChatPagination { } } +public struct ChatTagData: Encodable { + public var emoji: String? + public var text: String + + public init(emoji: String?, text: String) { + self.emoji = emoji + self.text = text + } +} + public struct ComposedMessage: Encodable { public var fileSource: CryptoFile? var quotedItemId: Int64? diff --git a/apps/ios/SimpleXChat/ChatTypes.swift b/apps/ios/SimpleXChat/ChatTypes.swift index da1ce24b73..b81b0b7662 100644 --- a/apps/ios/SimpleXChat/ChatTypes.swift +++ b/apps/ios/SimpleXChat/ChatTypes.swift @@ -1334,6 +1334,13 @@ public enum ChatInfo: Identifiable, Decodable, NamedChat, Hashable { } } + public var contactCard: Bool { + switch self { + case let .direct(contact): contact.activeConn == nil && contact.profile.contactLink != nil && contact.active + default: false + } + } + public var groupInfo: GroupInfo? { switch self { case let .group(groupInfo): return groupInfo @@ -1444,6 +1451,14 @@ public enum ChatInfo: Identifiable, Decodable, NamedChat, Hashable { default: return nil } } + + public var chatTags: [Int64]? { + switch self { + case let .direct(contact): return contact.chatTags + case let .group(groupInfo): return groupInfo.chatTags + default: return nil + } + } var createdAt: Date { switch self { @@ -1545,6 +1560,7 @@ public struct Contact: Identifiable, Decodable, NamedChat, Hashable { var chatTs: Date? var contactGroupMemberId: Int64? var contactGrpInvSent: Bool + public var chatTags: [Int64] public var uiThemes: ThemeModeOverrides? public var chatDeleted: Bool @@ -1615,6 +1631,7 @@ public struct Contact: Identifiable, Decodable, NamedChat, Hashable { createdAt: .now, updatedAt: .now, contactGrpInvSent: false, + chatTags: [], chatDeleted: false ) } @@ -1910,6 +1927,7 @@ public struct GroupInfo: Identifiable, Decodable, NamedChat, Hashable { public var fullName: String { get { groupProfile.fullName } } public var image: String? { get { groupProfile.image } } public var localAlias: String { "" } + public var chatTags: [Int64] public var isOwner: Bool { return membership.memberRole == .owner && membership.memberCurrent @@ -1932,7 +1950,8 @@ public struct GroupInfo: Identifiable, Decodable, NamedChat, Hashable { hostConnCustomUserProfileId: nil, chatSettings: ChatSettings.defaults, createdAt: .now, - updatedAt: .now + updatedAt: .now, + chatTags: [] ) } @@ -4210,6 +4229,20 @@ public enum ChatItemTTL: Identifiable, Comparable, Hashable { } } +public struct ChatTag: Decodable, Hashable { + public var chatTagId: Int64 + public var chatTagText: String + public var chatTagEmoji: String? + + public var id: Int64 { chatTagId } + + public init(chatTagId: Int64, chatTagText: String, chatTagEmoji: String?) { + self.chatTagId = chatTagId + self.chatTagText = chatTagText + self.chatTagEmoji = chatTagEmoji + } +} + public struct ChatItemInfo: Decodable, Hashable { public var itemVersions: [ChatItemVersion] public var memberDeliveryStatuses: [MemberDeliveryStatus]? diff --git a/simplex-chat.cabal b/simplex-chat.cabal index 29e748c4e8..b72e84084b 100644 --- a/simplex-chat.cabal +++ b/simplex-chat.cabal @@ -155,6 +155,7 @@ library Simplex.Chat.Migrations.M20241125_indexes Simplex.Chat.Migrations.M20241128_business_chats Simplex.Chat.Migrations.M20241205_business_chat_members + Simplex.Chat.Migrations.M20241206_chat_tags Simplex.Chat.Mobile Simplex.Chat.Mobile.File Simplex.Chat.Mobile.Shared diff --git a/src/Simplex/Chat.hs b/src/Simplex/Chat.hs index f74e5ea070..288b05b38d 100644 --- a/src/Simplex/Chat.hs +++ b/src/Simplex/Chat.hs @@ -847,6 +847,9 @@ processChatCommand' vr = \case . sortOn (timeAvg . snd) . M.assocs <$> withConnection st (readTVarIO . DB.slow) + APIGetChatTags userId -> withUserId' userId $ \user -> do + tags <- withFastStore' (`getUserChatTags` user) + pure $ CRChatTags user tags APIGetChats {userId, pendingConnections, pagination, query} -> withUserId' userId $ \user -> do (errs, previews) <- partitionEithers <$> withFastStore' (\db -> getChatPreviews db vr user pendingConnections pagination query) unless (null errs) $ toView $ CRChatErrors (Just user) (map ChatErrorStore errs) @@ -894,6 +897,26 @@ processChatCommand' vr = \case CTLocal -> pure $ chatCmdError (Just user) "not supported" CTContactRequest -> pure $ chatCmdError (Just user) "not supported" CTContactConnection -> pure $ chatCmdError (Just user) "not supported" + APICreateChatTag (ChatTagData emoji text) -> withUser $ \user -> withFastStore' $ \db -> do + _ <- createChatTag db user emoji text + CRChatTags user <$> getUserChatTags db user + APISetChatTags (ChatRef cType chatId) tagIds -> withUser $ \user -> withFastStore' $ \db -> case cType of + CTDirect -> do + updateDirectChatTags db chatId (maybe [] L.toList tagIds) + CRTagsUpdated user <$> getUserChatTags db user <*> getDirectChatTags db chatId + CTGroup -> do + updateGroupChatTags db chatId (maybe [] L.toList tagIds) + CRTagsUpdated user <$> getUserChatTags db user <*> getGroupChatTags db chatId + _ -> pure $ chatCmdError (Just user) "not supported" + APIDeleteChatTag tagId -> withUser $ \user -> do + withFastStore' $ \db -> deleteChatTag db user tagId + ok user + APIUpdateChatTag tagId (ChatTagData emoji text) -> withUser $ \user -> do + withFastStore' $ \db -> updateChatTag db user tagId emoji text + ok user + APIReorderChatTags tagIds -> withUser $ \user -> do + withFastStore' $ \db -> reorderChatTags db user $ L.toList tagIds + ok user APICreateChatItems folderId cms -> withUser $ \user -> createNoteFolderContentItems user folderId (L.map (,Nothing) cms) APIUpdateChatItem (ChatRef cType chatId) itemId live mc -> withUser $ \user -> case cType of @@ -8391,6 +8414,7 @@ chatCommandP = "/sql chat " *> (ExecChatStoreSQL <$> textP), "/sql agent " *> (ExecAgentStoreSQL <$> textP), "/sql slow" $> SlowSQLQueries, + "/_get tags " *> (APIGetChatTags <$> A.decimal), "/_get chats " *> ( APIGetChats <$> A.decimal @@ -8402,6 +8426,11 @@ chatCommandP = "/_get items " *> (APIGetChatItems <$> chatPaginationP <*> optional (" search=" *> stringP)), "/_get item info " *> (APIGetChatItemInfo <$> chatRefP <* A.space <*> A.decimal), "/_send " *> (APISendMessages <$> chatRefP <*> liveMessageP <*> sendMessageTTLP <*> (" json " *> jsonP <|> " text " *> composedMessagesTextP)), + "/_create tag " *> (APICreateChatTag <$> jsonP), + "/_tags " *> (APISetChatTags <$> chatRefP <*> optional _strP), + "/_delete tag " *> (APIDeleteChatTag <$> A.decimal), + "/_update tag " *> (APIUpdateChatTag <$> A.decimal <* A.space <*> jsonP), + "/_reorder tags " *> (APIReorderChatTags <$> strP), "/_create *" *> (APICreateChatItems <$> A.decimal <*> (" json " *> jsonP <|> " text " *> composedMessagesTextP)), "/_update item " *> (APIUpdateChatItem <$> chatRefP <* A.space <*> A.decimal <*> liveMessageP <* A.space <*> msgContentP), "/_delete item " *> (APIDeleteChatItem <$> chatRefP <*> _strP <* A.space <*> ciDeleteMode), diff --git a/src/Simplex/Chat/Controller.hs b/src/Simplex/Chat/Controller.hs index 593c328d0c..ffefddd701 100644 --- a/src/Simplex/Chat/Controller.hs +++ b/src/Simplex/Chat/Controller.hs @@ -294,11 +294,17 @@ data ChatCommand | ExecChatStoreSQL Text | ExecAgentStoreSQL Text | SlowSQLQueries + | APIGetChatTags UserId | APIGetChats {userId :: UserId, pendingConnections :: Bool, pagination :: PaginationByTime, query :: ChatListQuery} | APIGetChat ChatRef ChatPagination (Maybe String) | APIGetChatItems ChatPagination (Maybe String) | APIGetChatItemInfo ChatRef ChatItemId | APISendMessages {chatRef :: ChatRef, liveMessage :: Bool, ttl :: Maybe Int, composedMessages :: NonEmpty ComposedMessage} + | APICreateChatTag ChatTagData + | APISetChatTags ChatRef (Maybe (NonEmpty ChatTagId)) + | APIDeleteChatTag ChatTagId + | APIUpdateChatTag ChatTagId ChatTagData + | APIReorderChatTags (NonEmpty ChatTagId) | APICreateChatItems {noteFolderId :: NoteFolderId, composedMessages :: NonEmpty ComposedMessage} | APIUpdateChatItem {chatRef :: ChatRef, chatItemId :: ChatItemId, liveMessage :: Bool, msgContent :: MsgContent} | APIDeleteChatItem ChatRef (NonEmpty ChatItemId) CIDeleteMode @@ -587,6 +593,7 @@ data ChatResponse | CRApiChats {user :: User, chats :: [AChat]} | CRChats {chats :: [AChat]} | CRApiChat {user :: User, chat :: AChat, navInfo :: Maybe NavigationInfo} + | CRChatTags {user :: User, userTags :: [ChatTag]} | CRChatItems {user :: User, chatName_ :: Maybe ChatName, chatItems :: [AChatItem]} | CRChatItemInfo {user :: User, chatItem :: AChatItem, chatItemInfo :: ChatItemInfo} | CRChatItemId User (Maybe ChatItemId) @@ -617,6 +624,7 @@ data ChatResponse | CRContactCode {user :: User, contact :: Contact, connectionCode :: Text} | CRGroupMemberCode {user :: User, groupInfo :: GroupInfo, member :: GroupMember, connectionCode :: Text} | CRConnectionVerified {user :: User, verified :: Bool, expectedCode :: Text} + | CRTagsUpdated {user :: User, userTags :: [ChatTag], chatTags :: [ChatTagId]} | CRNewChatItems {user :: User, chatItems :: [AChatItem]} | CRChatItemsStatusesUpdated {user :: User, chatItems :: [AChatItem]} | CRChatItemUpdated {user :: User, chatItem :: AChatItem} @@ -1068,6 +1076,16 @@ instance FromJSON ComposedMessage where parseJSON invalid = JT.prependFailure "bad ComposedMessage, " (JT.typeMismatch "Object" invalid) +data ChatTagData = ChatTagData + { emoji :: Maybe Text, + text :: Text + } + deriving (Show) + +instance FromJSON ChatTagData where + parseJSON (J.Object v) = ChatTagData <$> v .:? "emoji" <*> v .: "text" + parseJSON invalid = JT.prependFailure "bad ChatTagData, " (JT.typeMismatch "Object" invalid) + data NtfConn = NtfConn { user_ :: Maybe User, connEntity_ :: Maybe ConnectionEntity, @@ -1603,3 +1621,5 @@ $(JQ.deriveFromJSON defaultJSON ''ArchiveConfig) $(JQ.deriveFromJSON defaultJSON ''DBEncryptionConfig) $(JQ.deriveToJSON defaultJSON ''ComposedMessage) + +$(JQ.deriveToJSON defaultJSON ''ChatTagData) diff --git a/src/Simplex/Chat/Migrations/M20241206_chat_tags.hs b/src/Simplex/Chat/Migrations/M20241206_chat_tags.hs new file mode 100644 index 0000000000..2476512814 --- /dev/null +++ b/src/Simplex/Chat/Migrations/M20241206_chat_tags.hs @@ -0,0 +1,47 @@ +{-# LANGUAGE QuasiQuotes #-} + +module Simplex.Chat.Migrations.M20241206_chat_tags where + +import Database.SQLite.Simple (Query) +import Database.SQLite.Simple.QQ (sql) + +m20241206_chat_tags :: Query +m20241206_chat_tags = + [sql| +CREATE TABLE chat_tags ( + chat_tag_id INTEGER PRIMARY KEY AUTOINCREMENT, + user_id INTEGER REFERENCES users, + chat_tag_text TEXT NOT NULL, + chat_tag_emoji TEXT, + tag_order INTEGER NOT NULL +); + +CREATE TABLE chat_tags_chats ( + contact_id INTEGER REFERENCES contacts ON DELETE CASCADE, + group_id INTEGER REFERENCES groups ON DELETE CASCADE, + chat_tag_id INTEGER NOT NULL REFERENCES chat_tags ON DELETE CASCADE +); + +CREATE INDEX idx_chat_tags_user_id ON chat_tags(user_id); +CREATE UNIQUE INDEX idx_chat_tags_user_id_chat_tag_text ON chat_tags(user_id, chat_tag_text); +CREATE UNIQUE INDEX idx_chat_tags_user_id_chat_tag_emoji ON chat_tags(user_id, chat_tag_emoji); + +CREATE INDEX idx_chat_tags_chats_chat_tag_id ON chat_tags_chats(chat_tag_id); +CREATE UNIQUE INDEX idx_chat_tags_chats_chat_tag_id_contact_id ON chat_tags_chats(contact_id, chat_tag_id); +CREATE UNIQUE INDEX idx_chat_tags_chats_chat_tag_id_group_id ON chat_tags_chats(group_id, chat_tag_id); +|] + +down_m20241206_chat_tags :: Query +down_m20241206_chat_tags = + [sql| +DROP INDEX idx_chat_tags_user_id; +DROP INDEX idx_chat_tags_user_id_chat_tag_text; +DROP INDEX idx_chat_tags_user_id_chat_tag_emoji; + +DROP INDEX idx_chat_tags_chats_chat_tag_id; +DROP INDEX idx_chat_tags_chats_chat_tag_id_contact_id; +DROP INDEX idx_chat_tags_chats_chat_tag_id_group_id; + +DROP TABLE chat_tags_chats; +DROP TABLE chat_tags; +|] diff --git a/src/Simplex/Chat/Migrations/chat_schema.sql b/src/Simplex/Chat/Migrations/chat_schema.sql index 94ccc65b7f..5f48f4d63e 100644 --- a/src/Simplex/Chat/Migrations/chat_schema.sql +++ b/src/Simplex/Chat/Migrations/chat_schema.sql @@ -623,6 +623,18 @@ CREATE TABLE operator_usage_conditions( accepted_at TEXT, created_at TEXT NOT NULL DEFAULT(datetime('now')) ); +CREATE TABLE chat_tags( + chat_tag_id INTEGER PRIMARY KEY AUTOINCREMENT, + user_id INTEGER REFERENCES users, + chat_tag_text TEXT NOT NULL, + chat_tag_emoji TEXT, + tag_order INTEGER NOT NULL +); +CREATE TABLE chat_tags_chats( + contact_id INTEGER REFERENCES contacts ON DELETE CASCADE, + group_id INTEGER REFERENCES groups ON DELETE CASCADE, + chat_tag_id INTEGER NOT NULL REFERENCES chat_tags ON DELETE CASCADE +); CREATE INDEX contact_profiles_index ON contact_profiles( display_name, full_name @@ -929,3 +941,21 @@ CREATE INDEX idx_chat_items_notes ON chat_items( created_at ); CREATE INDEX idx_groups_business_xcontact_id ON groups(business_xcontact_id); +CREATE INDEX idx_chat_tags_user_id ON chat_tags(user_id); +CREATE UNIQUE INDEX idx_chat_tags_user_id_chat_tag_text ON chat_tags( + user_id, + chat_tag_text +); +CREATE UNIQUE INDEX idx_chat_tags_user_id_chat_tag_emoji ON chat_tags( + user_id, + chat_tag_emoji +); +CREATE INDEX idx_chat_tags_chats_chat_tag_id ON chat_tags_chats(chat_tag_id); +CREATE UNIQUE INDEX idx_chat_tags_chats_chat_tag_id_contact_id ON chat_tags_chats( + contact_id, + chat_tag_id +); +CREATE UNIQUE INDEX idx_chat_tags_chats_chat_tag_id_group_id ON chat_tags_chats( + group_id, + chat_tag_id +); diff --git a/src/Simplex/Chat/Store/Connections.hs b/src/Simplex/Chat/Store/Connections.hs index db787b0112..6783dae99e 100644 --- a/src/Simplex/Chat/Store/Connections.hs +++ b/src/Simplex/Chat/Store/Connections.hs @@ -21,11 +21,14 @@ where import Control.Applicative ((<|>)) import Control.Monad import Control.Monad.Except +import Control.Monad.IO.Class +import Data.Bitraversable (bitraverse) import Data.Int (Int64) import Data.Maybe (catMaybes, fromMaybe) import Database.SQLite.Simple (Only (..), (:.) (..)) import Database.SQLite.Simple.QQ (sql) import Simplex.Chat.Protocol +import Simplex.Chat.Store.Direct import Simplex.Chat.Store.Files import Simplex.Chat.Store.Groups import Simplex.Chat.Store.Profiles @@ -93,8 +96,9 @@ getConnectionEntity db vr user@User {userId, userContactId} agentConnId = do (userId, agentConnId) getContactRec_ :: Int64 -> Connection -> ExceptT StoreError IO Contact getContactRec_ contactId c = ExceptT $ do - toContact' contactId c - <$> DB.query + chatTags <- getDirectChatTags db contactId + firstRow (toContact' contactId c chatTags) (SEInternalError "referenced contact not found") $ + DB.query db [sql| SELECT @@ -105,17 +109,16 @@ getConnectionEntity db vr user@User {userId, userContactId} agentConnId = do WHERE c.user_id = ? AND c.contact_id = ? AND c.deleted = 0 |] (userId, contactId) - toContact' :: Int64 -> Connection -> [ContactRow'] -> Either StoreError Contact - toContact' contactId conn [(profileId, localDisplayName, viaGroup, displayName, fullName, image, contactLink, localAlias, contactUsed, contactStatus) :. (enableNtfs_, sendRcpts, favorite, preferences, userPreferences, createdAt, updatedAt, chatTs) :. (contactGroupMemberId, contactGrpInvSent, uiThemes, chatDeleted, customData)] = + toContact' :: Int64 -> Connection -> [ChatTagId] -> ContactRow' -> Contact + toContact' contactId conn chatTags ((profileId, localDisplayName, viaGroup, displayName, fullName, image, contactLink, localAlias, contactUsed, contactStatus) :. (enableNtfs_, sendRcpts, favorite, preferences, userPreferences, createdAt, updatedAt, chatTs) :. (contactGroupMemberId, contactGrpInvSent, uiThemes, chatDeleted, customData)) = let profile = LocalProfile {profileId, displayName, fullName, image, contactLink, preferences, localAlias} chatSettings = ChatSettings {enableNtfs = fromMaybe MFAll enableNtfs_, sendRcpts, favorite} mergedPreferences = contactUserPreferences user userPreferences preferences $ connIncognito conn activeConn = Just conn - in Right Contact {contactId, localDisplayName, profile, activeConn, viaGroup, contactUsed, contactStatus, chatSettings, userPreferences, mergedPreferences, createdAt, updatedAt, chatTs, contactGroupMemberId, contactGrpInvSent, uiThemes, chatDeleted, customData} - toContact' _ _ _ = Left $ SEInternalError "referenced contact not found" + in Contact {contactId, localDisplayName, profile, activeConn, viaGroup, contactUsed, contactStatus, chatSettings, userPreferences, mergedPreferences, createdAt, updatedAt, chatTs, contactGroupMemberId, contactGrpInvSent, chatTags, uiThemes, chatDeleted, customData} getGroupAndMember_ :: Int64 -> Connection -> ExceptT StoreError IO (GroupInfo, GroupMember) - getGroupAndMember_ groupMemberId c = ExceptT $ do - firstRow (toGroupAndMember c) (SEInternalError "referenced group member not found") $ + getGroupAndMember_ groupMemberId c = do + gm <- ExceptT $ firstRow (toGroupAndMember c) (SEInternalError "referenced group member not found") $ DB.query db [sql| @@ -141,9 +144,10 @@ getConnectionEntity db vr user@User {userId, userContactId} agentConnId = do WHERE m.group_member_id = ? AND g.user_id = ? AND mu.contact_id = ? |] (groupMemberId, userId, userContactId) + liftIO $ bitraverse (addGroupChatTags db) pure gm toGroupAndMember :: Connection -> GroupInfoRow :. GroupMemberRow -> (GroupInfo, GroupMember) toGroupAndMember c (groupInfoRow :. memberRow) = - let groupInfo = toGroupInfo vr userContactId groupInfoRow + let groupInfo = toGroupInfo vr userContactId [] groupInfoRow member = toGroupMember userContactId memberRow in (groupInfo, (member :: GroupMember) {activeConn = Just c}) getConnSndFileTransfer_ :: Int64 -> Connection -> ExceptT StoreError IO SndFileTransfer diff --git a/src/Simplex/Chat/Store/Direct.hs b/src/Simplex/Chat/Store/Direct.hs index d5396a0fef..7697f5d5d8 100644 --- a/src/Simplex/Chat/Store/Direct.hs +++ b/src/Simplex/Chat/Store/Direct.hs @@ -79,6 +79,8 @@ module Simplex.Chat.Store.Direct setContactCustomData, setContactUIThemes, setContactChatDeleted, + getDirectChatTags, + updateDirectChatTags, ) where @@ -180,8 +182,8 @@ getConnReqContactXContactId db vr user@User {userId} cReqHash = do (userId, cReqHash) getContactByConnReqHash :: DB.Connection -> VersionRangeChat -> User -> ConnReqUriHash -> IO (Maybe Contact) -getContactByConnReqHash db vr user@User {userId} cReqHash = - maybeFirstRow (toContact vr user) $ +getContactByConnReqHash db vr user@User {userId} cReqHash = do + ct_ <- maybeFirstRow (toContact vr user []) $ DB.query db [sql| @@ -201,6 +203,7 @@ getContactByConnReqHash db vr user@User {userId} cReqHash = LIMIT 1 |] (userId, cReqHash, CSActive) + mapM (addDirectChatTags db) ct_ createDirectConnection :: DB.Connection -> User -> ConnId -> ConnReqInvitation -> ConnStatus -> Maybe Profile -> SubscriptionMode -> VersionChat -> PQSupport -> IO PendingContactConnection createDirectConnection db User {userId} acId cReq pccConnStatus incognitoProfile subMode chatV pqSup = do @@ -251,6 +254,7 @@ createDirectContact db user@User {userId} conn@Connection {connId, localAlias} p chatTs = Just currentTs, contactGroupMemberId = Nothing, contactGrpInvSent = False, + chatTags = [], uiThemes = Nothing, chatDeleted = False, customData = Nothing @@ -636,8 +640,8 @@ createOrUpdateContactRequest db vr user@User {userId, userContactId} userContact ) insertedRowId db getContact' :: XContactId -> IO (Maybe Contact) - getContact' xContactId = - maybeFirstRow (toContact vr user) $ + getContact' xContactId = do + ct_ <- maybeFirstRow (toContact vr user []) $ DB.query db [sql| @@ -657,13 +661,15 @@ createOrUpdateContactRequest db vr user@User {userId, userContactId} userContact LIMIT 1 |] (userId, xContactId) + mapM (addDirectChatTags db) ct_ getGroupInfo' :: XContactId -> IO (Maybe GroupInfo) - getGroupInfo' xContactId = - maybeFirstRow (toGroupInfo vr userContactId) $ + getGroupInfo' xContactId = do + g_ <- maybeFirstRow (toGroupInfo vr userContactId []) $ DB.query db (groupInfoQuery <> " WHERE g.business_xcontact_id = ? AND g.user_id = ? AND mu.contact_id = ?") (xContactId, userId, userContactId) + mapM (addGroupChatTags db) g_ getContactRequestByXContactId :: XContactId -> IO (Maybe UserContactRequest) getContactRequestByXContactId xContactId = maybeFirstRow toContactRequest $ @@ -819,6 +825,7 @@ createAcceptedContact db user@User {userId, profile = LocalProfile {preferences} chatTs = Just createdAt, contactGroupMemberId = Nothing, contactGrpInvSent = False, + chatTags = [], uiThemes = Nothing, chatDeleted = False, customData = Nothing @@ -845,8 +852,9 @@ getContact :: DB.Connection -> VersionRangeChat -> User -> Int64 -> ExceptT Stor getContact db vr user contactId = getContact_ db vr user contactId False getContact_ :: DB.Connection -> VersionRangeChat -> User -> Int64 -> Bool -> ExceptT StoreError IO Contact -getContact_ db vr user@User {userId} contactId deleted = - ExceptT . firstRow (toContact vr user) (SEContactNotFound contactId) $ +getContact_ db vr user@User {userId} contactId deleted = do + chatTags <- liftIO $ getDirectChatTags db contactId + ExceptT . firstRow (toContact vr user chatTags) (SEContactNotFound contactId) $ DB.query db [sql| @@ -1018,3 +1026,39 @@ setContactChatDeleted :: DB.Connection -> User -> Contact -> Bool -> IO () setContactChatDeleted db User {userId} Contact {contactId} chatDeleted = do updatedAt <- getCurrentTime DB.execute db "UPDATE contacts SET chat_deleted = ?, updated_at = ? WHERE user_id = ? AND contact_id = ?" (chatDeleted, updatedAt, userId, contactId) + +updateDirectChatTags :: DB.Connection -> ContactId -> [ChatTagId] -> IO () +updateDirectChatTags db contactId tIds = do + currentTags <- getDirectChatTags db contactId + let tagsToAdd = filter (`notElem` currentTags) tIds + tagsToDelete = filter (`notElem` tIds) currentTags + forM_ tagsToDelete $ untagDirectChat db contactId + forM_ tagsToAdd $ tagDirectChat db contactId + +tagDirectChat :: DB.Connection -> ContactId -> ChatTagId -> IO () +tagDirectChat db contactId tId = + DB.execute + db + [sql| + INSERT INTO chat_tags_chats (contact_id, chat_tag_id) + VALUES (?,?) + |] + (contactId, tId) + +untagDirectChat :: DB.Connection -> ContactId -> ChatTagId -> IO () +untagDirectChat db contactId tId = + DB.execute + db + [sql| + DELETE FROM chat_tags_chats + WHERE contact_id = ? AND chat_tag_id = ? + |] + (contactId, tId) + +getDirectChatTags :: DB.Connection -> ContactId -> IO [ChatTagId] +getDirectChatTags db contactId = map fromOnly <$> DB.query db "SELECT chat_tag_id FROM chat_tags_chats WHERE contact_id = ?" (Only contactId) + +addDirectChatTags :: DB.Connection -> Contact -> IO Contact +addDirectChatTags db ct = do + chatTags <- getDirectChatTags db $ contactId' ct + pure (ct :: Contact) {chatTags} diff --git a/src/Simplex/Chat/Store/Groups.hs b/src/Simplex/Chat/Store/Groups.hs index 36ce7f3575..98173800cc 100644 --- a/src/Simplex/Chat/Store/Groups.hs +++ b/src/Simplex/Chat/Store/Groups.hs @@ -122,6 +122,8 @@ module Simplex.Chat.Store.Groups updateUserMemberProfileSentAt, setGroupCustomData, setGroupUIThemes, + updateGroupChatTags, + getGroupChatTags, ) where @@ -130,6 +132,7 @@ import Control.Monad.Except import Control.Monad.IO.Class import Crypto.Random (ChaChaDRG) import Data.Bifunctor (second) +import Data.Bitraversable (bitraverse) import Data.Either (rights) import Data.Int (Int64) import Data.List (partition, sortOn) @@ -249,8 +252,8 @@ setGroupLinkMemberRole db User {userId} userContactLinkId memberRole = DB.execute db "UPDATE user_contact_links SET group_link_member_role = ? WHERE user_id = ? AND user_contact_link_id = ?" (memberRole, userId, userContactLinkId) getGroupAndMember :: DB.Connection -> User -> Int64 -> VersionRangeChat -> ExceptT StoreError IO (GroupInfo, GroupMember) -getGroupAndMember db User {userId, userContactId} groupMemberId vr = - ExceptT . firstRow toGroupAndMember (SEInternalError "referenced group member not found") $ +getGroupAndMember db User {userId, userContactId} groupMemberId vr = do + gm <- ExceptT . firstRow toGroupAndMember (SEInternalError "referenced group member not found") $ DB.query db [sql| @@ -285,10 +288,11 @@ getGroupAndMember db User {userId, userContactId} groupMemberId vr = WHERE m.group_member_id = ? AND g.user_id = ? AND mu.contact_id = ? |] (userId, groupMemberId, userId, userContactId) + liftIO $ bitraverse (addGroupChatTags db) pure gm where toGroupAndMember :: (GroupInfoRow :. GroupMemberRow :. MaybeConnectionRow) -> (GroupInfo, GroupMember) toGroupAndMember (groupInfoRow :. memberRow :. connRow) = - let groupInfo = toGroupInfo vr userContactId groupInfoRow + let groupInfo = toGroupInfo vr userContactId [] groupInfoRow member = toGroupMember userContactId memberRow in (groupInfo, (member :: GroupMember) {activeConn = toMaybeConnection vr connRow}) @@ -333,6 +337,7 @@ createNewGroup db vr gVar user@User {userId} groupProfile incognitoProfile = Exc updatedAt = currentTs, chatTs = Just currentTs, userMemberProfileSentAt = Just currentTs, + chatTags = [], uiThemes = Nothing, customData = Nothing } @@ -401,6 +406,7 @@ createGroupInvitation db vr user@User {userId} contact@Contact {contactId, activ updatedAt = currentTs, chatTs = Just currentTs, userMemberProfileSentAt = Just currentTs, + chatTags = [], uiThemes = Nothing, customData = Nothing }, @@ -624,8 +630,8 @@ getUserGroups db vr user@User {userId} = do rights <$> mapM (runExceptT . getGroup db vr user) groupIds getUserGroupDetails :: DB.Connection -> VersionRangeChat -> User -> Maybe ContactId -> Maybe String -> IO [GroupInfo] -getUserGroupDetails db vr User {userId, userContactId} _contactId_ search_ = - map (toGroupInfo vr userContactId) +getUserGroupDetails db vr User {userId, userContactId} _contactId_ search_ = do + g_ <- map (toGroupInfo vr userContactId []) <$> DB.query db [sql| @@ -643,6 +649,7 @@ getUserGroupDetails db vr User {userId, userContactId} _contactId_ search_ = AND (gp.display_name LIKE '%' || ? || '%' OR gp.full_name LIKE '%' || ? || '%' OR gp.description LIKE '%' || ? || '%') |] (userId, userContactId, search, search, search) + mapM (addGroupChatTags db) g_ where search = fromMaybe "" search_ @@ -1362,8 +1369,8 @@ createMemberConnection_ db userId groupMemberId agentConnId chatV peerChatVRange createConnection_ db userId ConnMember (Just groupMemberId) agentConnId ConnNew chatV peerChatVRange viaContact Nothing Nothing connLevel currentTs subMode PQSupportOff getViaGroupMember :: DB.Connection -> VersionRangeChat -> User -> Contact -> IO (Maybe (GroupInfo, GroupMember)) -getViaGroupMember db vr User {userId, userContactId} Contact {contactId} = - maybeFirstRow toGroupAndMember $ +getViaGroupMember db vr User {userId, userContactId} Contact {contactId} = do + gm_ <- maybeFirstRow toGroupAndMember $ DB.query db [sql| @@ -1399,10 +1406,11 @@ getViaGroupMember db vr User {userId, userContactId} Contact {contactId} = WHERE ct.user_id = ? AND ct.contact_id = ? AND mu.contact_id = ? AND ct.deleted = 0 |] (userId, userId, contactId, userContactId) + mapM (bitraverse (addGroupChatTags db) pure) gm_ where toGroupAndMember :: (GroupInfoRow :. GroupMemberRow :. MaybeConnectionRow) -> (GroupInfo, GroupMember) toGroupAndMember (groupInfoRow :. memberRow :. connRow) = - let groupInfo = toGroupInfo vr userContactId groupInfoRow + let groupInfo = toGroupInfo vr userContactId [] groupInfoRow member = toGroupMember userContactId memberRow in (groupInfo, (member :: GroupMember) {activeConn = toMaybeConnection vr connRow}) @@ -1482,22 +1490,24 @@ updateGroupProfileFromMember db user g@GroupInfo {groupId} Profile {displayName updateGroupProfile db user g' p' where getGroupProfile = - ExceptT $ firstRow toGroupProfile (SEGroupNotFound groupId) $ - DB.query - db - [sql| + ExceptT $ + firstRow toGroupProfile (SEGroupNotFound groupId) $ + DB.query + db + [sql| SELECT gp.display_name, gp.full_name, gp.description, gp.image, gp.preferences FROM group_profiles gp JOIN groups g ON gp.group_profile_id = g.group_profile_id WHERE g.group_id = ? |] - (Only groupId) + (Only groupId) toGroupProfile (displayName, fullName, description, image, groupPreferences) = GroupProfile {displayName, fullName, description, image, groupPreferences} getGroupInfo :: DB.Connection -> VersionRangeChat -> User -> Int64 -> ExceptT StoreError IO GroupInfo -getGroupInfo db vr User {userId, userContactId} groupId = - ExceptT . firstRow (toGroupInfo vr userContactId) (SEGroupNotFound groupId) $ +getGroupInfo db vr User {userId, userContactId} groupId = ExceptT $ do + chatTags <- getGroupChatTags db groupId + firstRow (toGroupInfo vr userContactId chatTags) (SEGroupNotFound groupId) $ DB.query db (groupInfoQuery <> " WHERE g.group_id = ? AND g.user_id = ? AND mu.contact_id = ?") @@ -2053,7 +2063,7 @@ createMemberContact quotaErrCounter = 0 } mergedPreferences = contactUserPreferences user userPreferences preferences $ connIncognito ctConn - pure Contact {contactId, localDisplayName, profile = memberProfile, activeConn = Just ctConn, viaGroup = Nothing, contactUsed = True, contactStatus = CSActive, chatSettings = defaultChatSettings, userPreferences, mergedPreferences, createdAt = currentTs, updatedAt = currentTs, chatTs = Just currentTs, contactGroupMemberId = Just groupMemberId, contactGrpInvSent = False, uiThemes = Nothing, chatDeleted = False, customData = Nothing} + pure Contact {contactId, localDisplayName, profile = memberProfile, activeConn = Just ctConn, viaGroup = Nothing, contactUsed = True, contactStatus = CSActive, chatSettings = defaultChatSettings, userPreferences, mergedPreferences, createdAt = currentTs, updatedAt = currentTs, chatTs = Just currentTs, contactGroupMemberId = Just groupMemberId, contactGrpInvSent = False, chatTags = [], uiThemes = Nothing, chatDeleted = False, customData = Nothing} getMemberContact :: DB.Connection -> VersionRangeChat -> User -> ContactId -> ExceptT StoreError IO (GroupInfo, GroupMember, Contact, ConnReqInvitation) getMemberContact db vr user contactId = do @@ -2090,7 +2100,7 @@ createMemberContactInvited contactId <- createContactUpdateMember currentTs userPreferences ctConn <- createMemberContactConn_ db user connIds gInfo mConn contactId subMode let mergedPreferences = contactUserPreferences user userPreferences preferences $ connIncognito ctConn - mCt' = Contact {contactId, localDisplayName = memberLDN, profile = memberProfile, activeConn = Just ctConn, viaGroup = Nothing, contactUsed = True, contactStatus = CSActive, chatSettings = defaultChatSettings, userPreferences, mergedPreferences, createdAt = currentTs, updatedAt = currentTs, chatTs = Just currentTs, contactGroupMemberId = Nothing, contactGrpInvSent = False, uiThemes = Nothing, chatDeleted = False, customData = Nothing} + mCt' = Contact {contactId, localDisplayName = memberLDN, profile = memberProfile, activeConn = Just ctConn, viaGroup = Nothing, contactUsed = True, contactStatus = CSActive, chatSettings = defaultChatSettings, userPreferences, mergedPreferences, createdAt = currentTs, updatedAt = currentTs, chatTs = Just currentTs, contactGroupMemberId = Nothing, contactGrpInvSent = False, chatTags = [], uiThemes = Nothing, chatDeleted = False, customData = Nothing} m' = m {memberContactId = Just contactId} pure (mCt', m') where @@ -2301,3 +2311,31 @@ setGroupUIThemes :: DB.Connection -> User -> GroupInfo -> Maybe UIThemeEntityOve setGroupUIThemes db User {userId} GroupInfo {groupId} uiThemes = do updatedAt <- getCurrentTime DB.execute db "UPDATE groups SET ui_themes = ?, updated_at = ? WHERE user_id = ? AND group_id = ?" (uiThemes, updatedAt, userId, groupId) + +updateGroupChatTags :: DB.Connection -> GroupId -> [ChatTagId] -> IO () +updateGroupChatTags db gId tIds = do + currentTags <- getGroupChatTags db gId + let tagsToAdd = filter (`notElem` currentTags) tIds + tagsToDelete = filter (`notElem` tIds) currentTags + forM_ tagsToDelete $ untagGroupChat db gId + forM_ tagsToAdd $ tagGroupChat db gId + +tagGroupChat :: DB.Connection -> GroupId -> ChatTagId -> IO () +tagGroupChat db groupId tId = + DB.execute + db + [sql| + INSERT INTO chat_tags_chats (group_id, chat_tag_id) + VALUES (?,?) + |] + (groupId, tId) + +untagGroupChat :: DB.Connection -> GroupId -> ChatTagId -> IO () +untagGroupChat db groupId tId = + DB.execute + db + [sql| + DELETE FROM chat_tags_chats + WHERE group_id = ? AND chat_tag_id = ? + |] + (groupId, tId) diff --git a/src/Simplex/Chat/Store/Migrations.hs b/src/Simplex/Chat/Store/Migrations.hs index 65fe8223fe..aaf7ecdca1 100644 --- a/src/Simplex/Chat/Store/Migrations.hs +++ b/src/Simplex/Chat/Store/Migrations.hs @@ -119,6 +119,7 @@ import Simplex.Chat.Migrations.M20241027_server_operators import Simplex.Chat.Migrations.M20241125_indexes import Simplex.Chat.Migrations.M20241128_business_chats import Simplex.Chat.Migrations.M20241205_business_chat_members +import Simplex.Chat.Migrations.M20241206_chat_tags import Simplex.Messaging.Agent.Store.SQLite.Migrations (Migration (..)) schemaMigrations :: [(String, Query, Maybe Query)] @@ -237,7 +238,8 @@ schemaMigrations = ("20241027_server_operators", m20241027_server_operators, Just down_m20241027_server_operators), ("20241125_indexes", m20241125_indexes, Just down_m20241125_indexes), ("20241128_business_chats", m20241128_business_chats, Just down_m20241128_business_chats), - ("20241205_business_chat_members", m20241205_business_chat_members, Just down_m20241205_business_chat_members) + ("20241205_business_chat_members", m20241205_business_chat_members, Just down_m20241205_business_chat_members), + ("20241206_chat_tags", m20241206_chat_tags, Just down_m20241206_chat_tags) ] -- | The list of migrations in ascending order by date diff --git a/src/Simplex/Chat/Store/Shared.hs b/src/Simplex/Chat/Store/Shared.hs index 851078ec1f..c6ac85dbd3 100644 --- a/src/Simplex/Chat/Store/Shared.hs +++ b/src/Simplex/Chat/Store/Shared.hs @@ -9,6 +9,7 @@ {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE TypeOperators #-} +{-# OPTIONS_GHC -fno-warn-ambiguous-fields #-} module Simplex.Chat.Store.Shared where @@ -391,14 +392,14 @@ type ContactRow' = (ProfileId, ContactName, Maybe Int64, ContactName, Text, Mayb type ContactRow = Only ContactId :. ContactRow' -toContact :: VersionRangeChat -> User -> ContactRow :. MaybeConnectionRow -> Contact -toContact vr user ((Only contactId :. (profileId, localDisplayName, viaGroup, displayName, fullName, image, contactLink, localAlias, contactUsed, contactStatus) :. (enableNtfs_, sendRcpts, favorite, preferences, userPreferences, createdAt, updatedAt, chatTs) :. (contactGroupMemberId, contactGrpInvSent, uiThemes, chatDeleted, customData)) :. connRow) = +toContact :: VersionRangeChat -> User -> [ChatTagId] -> ContactRow :. MaybeConnectionRow -> Contact +toContact vr user chatTags ((Only contactId :. (profileId, localDisplayName, viaGroup, displayName, fullName, image, contactLink, localAlias, contactUsed, contactStatus) :. (enableNtfs_, sendRcpts, favorite, preferences, userPreferences, createdAt, updatedAt, chatTs) :. (contactGroupMemberId, contactGrpInvSent, uiThemes, chatDeleted, customData)) :. connRow) = let profile = LocalProfile {profileId, displayName, fullName, image, contactLink, preferences, localAlias} activeConn = toMaybeConnection vr connRow chatSettings = ChatSettings {enableNtfs = fromMaybe MFAll enableNtfs_, sendRcpts, favorite} incognito = maybe False connIncognito activeConn mergedPreferences = contactUserPreferences user userPreferences preferences incognito - in Contact {contactId, localDisplayName, profile, activeConn, viaGroup, contactUsed, contactStatus, chatSettings, userPreferences, mergedPreferences, createdAt, updatedAt, chatTs, contactGroupMemberId, contactGrpInvSent, uiThemes, chatDeleted, customData} + in Contact {contactId, localDisplayName, profile, activeConn, viaGroup, contactUsed, contactStatus, chatSettings, userPreferences, mergedPreferences, createdAt, updatedAt, chatTs, contactGroupMemberId, contactGrpInvSent, chatTags, uiThemes, chatDeleted, customData} getProfileById :: DB.Connection -> UserId -> Int64 -> ExceptT StoreError IO LocalProfile getProfileById db userId profileId = @@ -552,14 +553,14 @@ type GroupInfoRow = (Int64, GroupName, GroupName, Text, Maybe Text, Maybe ImageD type GroupMemberRow = ((Int64, Int64, MemberId, VersionChat, VersionChat, GroupMemberRole, GroupMemberCategory, GroupMemberStatus, Bool, Maybe MemberRestrictionStatus) :. (Maybe Int64, Maybe GroupMemberId, ContactName, Maybe ContactId, ProfileId, ProfileId, ContactName, Text, Maybe ImageData, Maybe ConnReqContact, LocalAlias, Maybe Preferences)) -toGroupInfo :: VersionRangeChat -> Int64 -> GroupInfoRow -> GroupInfo -toGroupInfo vr userContactId ((groupId, localDisplayName, displayName, fullName, description, image, hostConnCustomUserProfileId, enableNtfs_, sendRcpts, favorite, groupPreferences) :. (createdAt, updatedAt, chatTs, userMemberProfileSentAt) :. businessRow :. (uiThemes, customData) :. userMemberRow) = +toGroupInfo :: VersionRangeChat -> Int64 -> [ChatTagId] -> GroupInfoRow -> GroupInfo +toGroupInfo vr userContactId chatTags ((groupId, localDisplayName, displayName, fullName, description, image, hostConnCustomUserProfileId, enableNtfs_, sendRcpts, favorite, groupPreferences) :. (createdAt, updatedAt, chatTs, userMemberProfileSentAt) :. businessRow :. (uiThemes, customData) :. userMemberRow) = let membership = (toGroupMember userContactId userMemberRow) {memberChatVRange = vr} chatSettings = ChatSettings {enableNtfs = fromMaybe MFAll enableNtfs_, sendRcpts, favorite} fullGroupPreferences = mergeGroupPreferences groupPreferences groupProfile = GroupProfile {displayName, fullName, description, image, groupPreferences} businessChat = toBusinessChatInfo businessRow - in GroupInfo {groupId, localDisplayName, groupProfile, businessChat, fullGroupPreferences, membership, hostConnCustomUserProfileId, chatSettings, createdAt, updatedAt, chatTs, userMemberProfileSentAt, uiThemes, customData} + in GroupInfo {groupId, localDisplayName, groupProfile, businessChat, fullGroupPreferences, membership, hostConnCustomUserProfileId, chatSettings, createdAt, updatedAt, chatTs, userMemberProfileSentAt, chatTags, uiThemes, customData} toGroupMember :: Int64 -> GroupMemberRow -> GroupMember toGroupMember userContactId ((groupMemberId, groupId, memberId, minVer, maxVer, memberRole, memberCategory, memberStatus, showMessages, memberRestriction_) :. (invitedById, invitedByGroupMemberId, localDisplayName, memberContactId, memberContactProfileId, profileId, displayName, fullName, image, contactLink, localAlias, preferences)) = @@ -592,3 +593,76 @@ groupInfoQuery = JOIN group_members mu ON mu.group_id = g.group_id JOIN contact_profiles pu ON pu.contact_profile_id = COALESCE(mu.member_profile_id, mu.contact_profile_id) |] + +createChatTag :: DB.Connection -> User -> Maybe Text -> Text -> IO ChatTagId +createChatTag db User {userId} emoji text = do + DB.execute + db + [sql| + INSERT INTO chat_tags (user_id, chat_tag_emoji, chat_tag_text, tag_order) + VALUES (?,?,?, COALESCE((SELECT MAX(tag_order) + 1 FROM chat_tags WHERE user_id = ?), 1)) + |] + (userId, emoji, text, userId) + insertedRowId db + +deleteChatTag :: DB.Connection -> User -> ChatTagId -> IO () +deleteChatTag db User {userId} tId = + DB.execute + db + [sql| + DELETE FROM chat_tags + WHERE user_id = ? AND chat_tag_id = ? + |] + (userId, tId) + +updateChatTag :: DB.Connection -> User -> ChatTagId -> Maybe Text -> Text -> IO () +updateChatTag db User {userId} tId emoji text = + DB.execute + db + [sql| + UPDATE chat_tags + SET chat_tag_emoji = ?, chat_tag_text = ? + WHERE user_id = ? AND chat_tag_id = ? + |] + (emoji, text, userId, tId) + +updateChatTagOrder :: DB.Connection -> User -> ChatTagId -> Int -> IO () +updateChatTagOrder db User {userId} tId order = + DB.execute + db + [sql| + UPDATE chat_tags + SET tag_order = ? + WHERE user_id = ? AND chat_tag_id = ? + |] + (order, userId, tId) + +reorderChatTags :: DB.Connection -> User -> [ChatTagId] -> IO () +reorderChatTags db user tIds = + forM_ (zip [1 ..] tIds) $ \(order, tId) -> + updateChatTagOrder db user tId order + +getUserChatTags :: DB.Connection -> User -> IO [ChatTag] +getUserChatTags db User {userId} = + map toChatTag + <$> DB.query + db + [sql| + SELECT chat_tag_id, chat_tag_emoji, chat_tag_text + FROM chat_tags + WHERE user_id = ? + ORDER BY tag_order + |] + (Only userId) + where + toChatTag :: (ChatTagId, Maybe Text, Text) -> ChatTag + toChatTag (chatTagId, chatTagEmoji, chatTagText) = ChatTag {chatTagId, chatTagEmoji, chatTagText} + +getGroupChatTags :: DB.Connection -> GroupId -> IO [ChatTagId] +getGroupChatTags db groupId = + map fromOnly <$> DB.query db "SELECT chat_tag_id FROM chat_tags_chats WHERE group_id = ?" (Only groupId) + +addGroupChatTags :: DB.Connection -> GroupInfo -> IO GroupInfo +addGroupChatTags db g@GroupInfo {groupId} = do + chatTags <- getGroupChatTags db groupId + pure (g :: GroupInfo) {chatTags} diff --git a/src/Simplex/Chat/Types.hs b/src/Simplex/Chat/Types.hs index 77a02a4bc1..716925a0d7 100644 --- a/src/Simplex/Chat/Types.hs +++ b/src/Simplex/Chat/Types.hs @@ -160,6 +160,8 @@ type ContactId = Int64 type ProfileId = Int64 +type ChatTagId = Int64 + data Contact = Contact { contactId :: ContactId, localDisplayName :: ContactName, @@ -176,6 +178,7 @@ data Contact = Contact chatTs :: Maybe UTCTime, contactGroupMemberId :: Maybe GroupMemberId, contactGrpInvSent :: Bool, + chatTags :: [ChatTagId], uiThemes :: Maybe UIThemeEntityOverrides, chatDeleted :: Bool, customData :: Maybe CustomData @@ -380,6 +383,7 @@ data GroupInfo = GroupInfo updatedAt :: UTCTime, chatTs :: Maybe UTCTime, userMemberProfileSentAt :: Maybe UTCTime, + chatTags :: [ChatTagId], uiThemes :: Maybe UIThemeEntityOverrides, customData :: Maybe CustomData } @@ -1637,6 +1641,13 @@ data CommandData = CommandData } deriving (Show) +data ChatTag = ChatTag + { chatTagId :: Int64, + chatTagText :: Text, + chatTagEmoji :: Maybe Text + } + deriving (Show) + -- ad-hoc type for data required for XGrpMemIntro continuation data XGrpMemIntroCont = XGrpMemIntroCont { groupId :: GroupId, @@ -1791,3 +1802,5 @@ $(JQ.deriveJSON defaultJSON ''Contact) $(JQ.deriveJSON defaultJSON ''ContactRef) $(JQ.deriveJSON defaultJSON ''NoteFolder) + +$(JQ.deriveJSON defaultJSON ''ChatTag) diff --git a/src/Simplex/Chat/View.hs b/src/Simplex/Chat/View.hs index 8b6a545637..45dc6408d2 100644 --- a/src/Simplex/Chat/View.hs +++ b/src/Simplex/Chat/View.hs @@ -96,6 +96,7 @@ responseToView hu@(currentRH, user_) ChatConfig {logLevel, showReactions, showRe CRApiChats u chats -> ttyUser u $ if testView then testViewChats chats else [viewJSON chats] CRChats chats -> viewChats ts tz chats CRApiChat u chat _ -> ttyUser u $ if testView then testViewChat chat else [viewJSON chat] + CRChatTags u tags -> ttyUser u $ [viewJSON tags] CRApiParsedMarkdown ft -> [viewJSON ft] CRServerTestResult u srv testFailure -> ttyUser u $ viewServerTestResult srv testFailure CRServerOperatorConditions (ServerOperatorConditions ops _ ca) -> viewServerOperators ops ca @@ -149,6 +150,7 @@ responseToView hu@(currentRH, user_) ChatConfig {logLevel, showReactions, showRe | otherwise -> [] CRChatItemUpdated u (AChatItem _ _ chat item) -> ttyUser u $ unmuted u chat item $ viewItemUpdate chat item liveItems ts tz CRChatItemNotChanged u ci -> ttyUser u $ viewItemNotChanged ci + CRTagsUpdated u _ _ -> ttyUser u ["chat tags updated"] CRChatItemsDeleted u deletions byUser timed -> case deletions of [ChatItemDeletion (AChatItem _ _ chat deletedItem) toItem] -> ttyUser u $ unmuted u chat deletedItem $ viewItemDelete chat deletedItem toItem byUser timed ts tz testView From 143be1edafb3d64a9d2390a9be93d77d6136d8d6 Mon Sep 17 00:00:00 2001 From: spaced4ndy <8711996+spaced4ndy@users.noreply.github.com> Date: Thu, 19 Dec 2024 19:59:34 +0400 Subject: [PATCH 5/6] ios: don't show what's new after import on onboarding (#5394) --- apps/ios/Shared/Views/Onboarding/CreateProfile.swift | 1 - apps/ios/Shared/Views/Onboarding/SimpleXInfo.swift | 3 +++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/apps/ios/Shared/Views/Onboarding/CreateProfile.swift b/apps/ios/Shared/Views/Onboarding/CreateProfile.swift index 14ad9dfb08..409cb859ea 100644 --- a/apps/ios/Shared/Views/Onboarding/CreateProfile.swift +++ b/apps/ios/Shared/Views/Onboarding/CreateProfile.swift @@ -174,7 +174,6 @@ struct CreateFirstProfile: View { } .onAppear() { focusDisplayName = true - setLastVersionDefault() } .padding(.horizontal, 25) .padding(.top, 10) diff --git a/apps/ios/Shared/Views/Onboarding/SimpleXInfo.swift b/apps/ios/Shared/Views/Onboarding/SimpleXInfo.swift index a8704e964b..40dd29db53 100644 --- a/apps/ios/Shared/Views/Onboarding/SimpleXInfo.swift +++ b/apps/ios/Shared/Views/Onboarding/SimpleXInfo.swift @@ -89,6 +89,9 @@ struct SimpleXInfo: View { ) } } + .onAppear() { + setLastVersionDefault() + } .frame(maxHeight: .infinity) .padding(.horizontal, 25) .padding(.top, 75) From 9adff0bfd1a2c91aa523135c381c6136def34fa1 Mon Sep 17 00:00:00 2001 From: Evgeny Date: Fri, 20 Dec 2024 11:43:11 +0000 Subject: [PATCH 6/6] ios: track unread chat lists, avoid scanning when adding and removing chats (#5398) * ios: track unread chat lists, avoid scanning when adding and removing chats * disable favorites filter when no more favorite chats --- apps/ios/Shared/Model/ChatModel.swift | 111 +++++++++++++++--- apps/ios/Shared/Model/SimpleXAPI.swift | 6 +- apps/ios/Shared/Views/Chat/ChatView.swift | 2 + .../Shared/Views/ChatList/ChatListView.swift | 78 ++++++------ 4 files changed, 139 insertions(+), 58 deletions(-) diff --git a/apps/ios/Shared/Model/ChatModel.swift b/apps/ios/Shared/Model/ChatModel.swift index 8cd8b0eece..2784551361 100644 --- a/apps/ios/Shared/Model/ChatModel.swift +++ b/apps/ios/Shared/Model/ChatModel.swift @@ -105,27 +105,87 @@ class ChatTagsModel: ObservableObject { @Published var userTags: [ChatTag] = [] @Published var activeFilter: ActiveFilter? = nil - @Published var presetTags: [PresetTag] = [] -} - -func updatePresetTags(_ chats: [Chat]) { - var matches: Set = [] - for chat in chats { - for tag in PresetTag.allCases { - if presetTagMatchesChat(tag, chat) { - matches.insert(tag) + @Published var presetTags: [PresetTag:Int] = [:] + @Published var unreadTags: [Int64:Int] = [:] + + func updateChatTags(_ chats: [Chat]) { + let tm = ChatTagsModel.shared + var newPresetTags: [PresetTag:Int] = [:] + var newUnreadTags: [Int64:Int] = [:] + for chat in chats { + for tag in PresetTag.allCases { + if presetTagMatchesChat(tag, chat.chatInfo) { + newPresetTags[tag] = (newPresetTags[tag] ?? 0) + 1 + } + } + if chat.isUnread, let tags = chat.chatInfo.chatTags { + for tag in tags { + newUnreadTags[tag] = (newUnreadTags[tag] ?? 0) + 1 + } } } - if matches.count == PresetTag.allCases.count { - break + if case let .presetTag(tag) = tm.activeFilter, (newPresetTags[tag] ?? 0) == 0 { + activeFilter = nil + } + presetTags = newPresetTags + unreadTags = newUnreadTags + } + + func updateChatFavorite(favorite: Bool, wasFavorite: Bool) { + let count = presetTags[.favorites] + if favorite && !wasFavorite { + presetTags[.favorites] = (count ?? 0) + 1 + } else if !favorite && wasFavorite, let count { + presetTags[.favorites] = max(0, count - 1) + if case .presetTag(.favorites) = activeFilter, (presetTags[.favorites] ?? 0) == 0 { + activeFilter = nil + } + } + } + + func addPresetChatTags(_ chatInfo: ChatInfo) { + for tag in PresetTag.allCases { + if presetTagMatchesChat(tag, chatInfo) { + presetTags[tag] = (presetTags[tag] ?? 0) + 1 + } + } + } + + func removePresetChatTags(_ chatInfo: ChatInfo) { + for tag in PresetTag.allCases { + if presetTagMatchesChat(tag, chatInfo) { + if let count = presetTags[tag] { + presetTags[tag] = max(0, count - 1) + } + } } } - let tm = ChatTagsModel.shared - if case let .presetTag(tag) = tm.activeFilter, !matches.contains(tag) { - tm.activeFilter = nil + func markChatTagRead(_ chat: Chat) -> Void { + if chat.isUnread, let tags = chat.chatInfo.chatTags { + markChatTagRead_(chat, tags) + } + } + + func updateChatTagRead(_ chat: Chat, wasUnread: Bool) -> Void { + guard let tags = chat.chatInfo.chatTags else { return } + let nowUnread = chat.isUnread + if nowUnread && !wasUnread { + for tag in tags { + unreadTags[tag] = (unreadTags[tag] ?? 0) + 1 + } + } else if !nowUnread && wasUnread { + markChatTagRead_(chat, tags) + } + } + + private func markChatTagRead_(_ chat: Chat, _ tags: [Int64]) -> Void { + for tag in tags { + if let count = unreadTags[tag] { + unreadTags[tag] = max(0, count - 1) + } + } } - tm.presetTags = Array(matches).sorted(by: { $0.rawValue < $1.rawValue }) } class NetworkModel: ObservableObject { @@ -370,10 +430,9 @@ final class ChatModel: ObservableObject { private func updateChat(_ cInfo: ChatInfo, addMissing: Bool = true) { if hasChat(cInfo.id) { updateChatInfo(cInfo) - updatePresetTags(self.chats) } else if addMissing { addChat(Chat(chatInfo: cInfo, chatItems: [])) - updatePresetTags(self.chats) + ChatTagsModel.shared.addPresetChatTags(cInfo) } } @@ -596,6 +655,7 @@ final class ChatModel: ObservableObject { _updateChat(cInfo.id) { chat in self.decreaseUnreadCounter(user: self.currentUser!, by: chat.chatStats.unreadCount) self.updateFloatingButtons(unreadCount: 0) + ChatTagsModel.shared.markChatTagRead(chat) chat.chatStats = ChatStats() } // update current chat @@ -634,7 +694,9 @@ final class ChatModel: ObservableObject { // update preview let markedCount = chat.chatStats.unreadCount - unreadBelow if markedCount > 0 { + let wasUnread = chat.isUnread chat.chatStats.unreadCount -= markedCount + ChatTagsModel.shared.updateChatTagRead(chat, wasUnread: wasUnread) self.decreaseUnreadCounter(user: self.currentUser!, by: markedCount) self.updateFloatingButtons(unreadCount: chat.chatStats.unreadCount) } @@ -647,7 +709,9 @@ final class ChatModel: ObservableObject { func markChatUnread(_ cInfo: ChatInfo, unreadChat: Bool = true) { _updateChat(cInfo.id) { chat in + let wasUnread = chat.isUnread chat.chatStats.unreadChat = unreadChat + ChatTagsModel.shared.updateChatTagRead(chat, wasUnread: wasUnread) } } @@ -656,6 +720,7 @@ final class ChatModel: ObservableObject { if let chat = getChat(cInfo.id) { self.decreaseUnreadCounter(user: self.currentUser!, by: chat.chatStats.unreadCount) chat.chatItems = [] + ChatTagsModel.shared.markChatTagRead(chat) chat.chatStats = ChatStats() chat.chatInfo = cInfo } @@ -782,7 +847,9 @@ final class ChatModel: ObservableObject { } func changeUnreadCounter(_ chatIndex: Int, by count: Int) { + let wasUnread = chats[chatIndex].isUnread chats[chatIndex].chatStats.unreadCount = chats[chatIndex].chatStats.unreadCount + count + ChatTagsModel.shared.updateChatTagRead(chats[chatIndex], wasUnread: wasUnread) changeUnreadCounter(user: currentUser!, by: count) } @@ -887,8 +954,10 @@ final class ChatModel: ObservableObject { func removeChat(_ id: String) { withAnimation { - chats.removeAll(where: { $0.id == id }) - updatePresetTags(chats) + if let i = getChatIndex(id) { + let removed = chats.remove(at: i) + ChatTagsModel.shared.removePresetChatTags(removed.chatInfo) + } } } @@ -986,6 +1055,10 @@ final class Chat: ObservableObject, Identifiable, ChatLike { } } + var isUnread: Bool { + chatStats.unreadCount > 0 || chatStats.unreadChat + } + var id: ChatId { get { chatInfo.id } } var viewId: String { get { "\(chatInfo.id) \(created.timeIntervalSince1970)" } } diff --git a/apps/ios/Shared/Model/SimpleXAPI.swift b/apps/ios/Shared/Model/SimpleXAPI.swift index 177f3e884f..7eb78edf74 100644 --- a/apps/ios/Shared/Model/SimpleXAPI.swift +++ b/apps/ios/Shared/Model/SimpleXAPI.swift @@ -1793,7 +1793,7 @@ func getUserChatData() throws { let tm = ChatTagsModel.shared tm.activeFilter = nil tm.userTags = tags - updatePresetTags(m.chats) + tm.updateChatTags(m.chats) } private func getUserChatDataAsync() async throws { @@ -1810,7 +1810,7 @@ private func getUserChatDataAsync() async throws { m.updateChats(chats) tm.activeFilter = nil tm.userTags = tags - updatePresetTags(m.chats) + tm.updateChatTags(m.chats) } } else { await MainActor.run { @@ -1818,7 +1818,7 @@ private func getUserChatDataAsync() async throws { m.updateChats([]) tm.activeFilter = nil tm.userTags = [] - tm.presetTags = [] + tm.presetTags = [:] } } } diff --git a/apps/ios/Shared/Views/Chat/ChatView.swift b/apps/ios/Shared/Views/Chat/ChatView.swift index 90c277ce76..ac4066d23e 100644 --- a/apps/ios/Shared/Views/Chat/ChatView.swift +++ b/apps/ios/Shared/Views/Chat/ChatView.swift @@ -2007,6 +2007,8 @@ func updateChatSettings(_ chat: Chat, chatSettings: ChatSettings) { do { try await apiSetChatSettings(type: chat.chatInfo.chatType, id: chat.chatInfo.apiId, chatSettings: chatSettings) await MainActor.run { + let wasFavorite = chat.chatInfo.chatSettings?.favorite ?? false + ChatTagsModel.shared.updateChatFavorite(favorite: chatSettings.favorite, wasFavorite: wasFavorite) switch chat.chatInfo { case var .direct(contact): contact.chatSettings = chatSettings diff --git a/apps/ios/Shared/Views/ChatList/ChatListView.swift b/apps/ios/Shared/Views/ChatList/ChatListView.swift index d3ed26161d..9cb87a4b22 100644 --- a/apps/ios/Shared/Views/ChatList/ChatListView.swift +++ b/apps/ios/Shared/Views/ChatList/ChatListView.swift @@ -472,7 +472,7 @@ struct ChatListView: View { func filtered(_ chat: Chat) -> Bool { switch chatTagsModel.activeFilter { - case let .presetTag(tag): presetTagMatchesChat(tag, chat) + case let .presetTag(tag): presetTagMatchesChat(tag, chat.chatInfo) case let .userTag(tag): chat.chatInfo.chatTags?.contains(tag.chatTagId) == true case .unread: chat.chatStats.unreadChat || chat.chatInfo.ntfsEnabled && chat.chatStats.unreadCount > 0 case .none: true @@ -665,6 +665,7 @@ struct ChatListSearchBar: View { struct ChatTagsView: View { @EnvironmentObject var chatTagsModel: ChatTagsModel @EnvironmentObject var chatModel: ChatModel + @EnvironmentObject var theme: AppTheme @Binding var parentSheet: SomeSheet? var body: some View { @@ -681,13 +682,13 @@ struct ChatTagsView: View { collapsedTagsFilterView() } } + let selectedTag: ChatTag? = if case let .userTag(tag) = chatTagsModel.activeFilter { + tag + } else { + nil + } ForEach(chatTagsModel.userTags, id: \.id) { tag in - let current = if case let .userTag(t) = chatTagsModel.activeFilter { - t == tag - } else { - false - } - + let current = tag == selectedTag let color: Color = current ? .accentColor : .secondary ZStack { HStack(spacing: 4) { @@ -698,8 +699,9 @@ struct ChatTagsView: View { .foregroundColor(color) } ZStack { - Text(tag.chatTagText).fontWeight(.semibold).foregroundColor(.clear) - Text(tag.chatTagText).fontWeight(current ? .semibold : .regular).foregroundColor(color) + let badge = Text(verbatim: (chatTagsModel.unreadTags[tag.chatTagId] ?? 0) > 0 ? " ●" : "").font(.footnote) + (Text(tag.chatTagText).fontWeight(.semibold) + badge).foregroundColor(.clear) + Text(tag.chatTagText).fontWeight(current ? .semibold : .regular).foregroundColor(color) + badge.foregroundColor(theme.colors.primary) } } .onTapGesture { @@ -757,21 +759,23 @@ struct ChatTagsView: View { } else { nil } - ForEach(chatTagsModel.presetTags, id: \.id) { tag in - let active = tag == selectedPresetTag - let (icon, text) = presetTagLabel(tag: tag, active: active) - let color: Color = active ? .accentColor : .secondary - - HStack(spacing: 4) { - Image(systemName: icon) - .foregroundColor(color) - ZStack { - Text(text).fontWeight(.semibold).foregroundColor(.clear) - Text(text).fontWeight(active ? .semibold : .regular).foregroundColor(color) + ForEach(PresetTag.allCases, id: \.id) { tag in + if (chatTagsModel.presetTags[tag] ?? 0) > 0 { + let active = tag == selectedPresetTag + let (icon, text) = presetTagLabel(tag: tag, active: active) + let color: Color = active ? .accentColor : .secondary + + HStack(spacing: 4) { + Image(systemName: icon) + .foregroundColor(color) + ZStack { + Text(text).fontWeight(.semibold).foregroundColor(.clear) + Text(text).fontWeight(active ? .semibold : .regular).foregroundColor(color) + } + } + .onTapGesture { + setActiveFilter(filter: .presetTag(tag)) } - } - .onTapGesture { - setActiveFilter(filter: .presetTag(tag)) } } } @@ -793,14 +797,16 @@ struct ChatTagsView: View { } } } - ForEach(chatTagsModel.presetTags, id: \.id) { tag in - Button { - setActiveFilter(filter: .presetTag(tag)) - } label: { - let (systemName, text) = presetTagLabel(tag: tag, active: tag == selectedPresetTag) - HStack { - Image(systemName: systemName) - Text(text) + ForEach(PresetTag.allCases, id: \.id) { tag in + if (chatTagsModel.presetTags[tag] ?? 0) > 0 { + Button { + setActiveFilter(filter: .presetTag(tag)) + } label: { + let (systemName, text) = presetTagLabel(tag: tag, active: tag == selectedPresetTag) + HStack { + Image(systemName: systemName) + Text(text) + } } } } @@ -846,12 +852,12 @@ func chatStoppedIcon() -> some View { } } -func presetTagMatchesChat(_ tag: PresetTag, _ chat: Chat) -> Bool { +func presetTagMatchesChat(_ tag: PresetTag, _ chatInfo: ChatInfo) -> Bool { switch tag { case .favorites: - chat.chatInfo.chatSettings?.favorite == true + chatInfo.chatSettings?.favorite == true case .contacts: - switch chat.chatInfo { + switch chatInfo { case let .direct(contact): !(contact.activeConn == nil && contact.profile.contactLink != nil && contact.active) && !contact.chatDeleted case .contactRequest: true case .contactConnection: true @@ -859,12 +865,12 @@ func presetTagMatchesChat(_ tag: PresetTag, _ chat: Chat) -> Bool { default: false } case .groups: - switch chat.chatInfo { + switch chatInfo { case let .group(groupInfo): groupInfo.businessChat == nil default: false } case .business: - chat.chatInfo.groupInfo?.businessChat?.chatType == .business + chatInfo.groupInfo?.businessChat?.chatType == .business } }