From d9008f64424792422470e9e600477e2a2d14c55e Mon Sep 17 00:00:00 2001 From: Florian Date: Sat, 13 Aug 2022 18:27:39 +0200 Subject: [PATCH] Global update of bundle to support Ibexa 3.3.* --- .travis.yml | 14 +- README.md | 68 +++---- composer.json | 22 ++- phpunit.xml.dist | 12 +- snapshot.jpg | Bin 0 -> 132415 bytes src/Controller/LogsManagerController.php | 167 +++++++++--------- ...Extension.php => IbexaLogsUiExtension.php} | 24 +-- src/EventListener/AdminMenuListener.php | 35 ---- src/EventSubscriber/MenuSubscriber.php | 31 ++++ src/EzPlatformLogsUiBundle.php | 32 ---- src/IbexaLogsUiBundle.php | 26 +++ src/LogManager/LogFile.php | 48 ++--- src/LogManager/LogTrunkCache.php | 150 ++++++---------- src/Parser/LineLogParser.php | 40 ++--- src/Resources/config/menu.yml | 9 - src/Resources/config/policies.yml | 5 +- src/Resources/config/routing.yml | 12 +- src/Resources/config/services.yml | 20 ++- src/Resources/translations/forms.en.yaml | 3 + src/Resources/translations/forms.fr.yaml | 3 + src/Resources/translations/messages.en.yaml | 9 + src/Resources/translations/messages.fr.yaml | 9 + src/Resources/views/logs/index.html.twig | 89 ---------- .../views/parts/_pagination.html.twig | 43 ----- .../views/themes/admin/logs/logs.html.twig | 128 ++++++++++++++ .../themes/admin/logs/pagination.html.twig | 42 +++++ src/Security/LogsUiProvider.php | 25 +-- tests/LogFileTest.php | 44 +++-- tests/LogTrunkCacheTest.php | 45 +++-- tests/logs/partially-invalid.log | 24 +-- 30 files changed, 581 insertions(+), 598 deletions(-) create mode 100644 snapshot.jpg rename src/DependencyInjection/{EzPlatformLogsUiExtension.php => IbexaLogsUiExtension.php} (50%) delete mode 100644 src/EventListener/AdminMenuListener.php create mode 100644 src/EventSubscriber/MenuSubscriber.php delete mode 100644 src/EzPlatformLogsUiBundle.php create mode 100644 src/IbexaLogsUiBundle.php delete mode 100644 src/Resources/config/menu.yml create mode 100644 src/Resources/translations/forms.en.yaml create mode 100644 src/Resources/translations/forms.fr.yaml create mode 100644 src/Resources/translations/messages.en.yaml create mode 100644 src/Resources/translations/messages.fr.yaml delete mode 100644 src/Resources/views/logs/index.html.twig delete mode 100644 src/Resources/views/parts/_pagination.html.twig create mode 100644 src/Resources/views/themes/admin/logs/logs.html.twig create mode 100644 src/Resources/views/themes/admin/logs/pagination.html.twig diff --git a/.travis.yml b/.travis.yml index 104956d..3bbc5e8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,4 +1,4 @@ -dist: xenial +dist: focal language: php env: @@ -8,15 +8,15 @@ env: matrix: fast_finish: true include: - - php: 7.1 - - php: 7.1 - env: SETUP=lowest - - php: 7.2 - - php: 7.2 - env: SETUP=lowest - php: 7.3 - php: 7.3 env: SETUP=lowest + - php: 8.0 + - php: 8.0 + env: SETUP=lowest + - php: 8.1 + - php: 8.1 + env: SETUP=lowest cache: directories: diff --git a/README.md b/README.md index 7b6d2c3..7c90d6c 100644 --- a/README.md +++ b/README.md @@ -1,21 +1,26 @@ -EzPlatformLogsUiBundle -[![Build Status](https://travis-ci.com/fkeloks/ezplatform-logs-ui.svg?branch=master)](https://travis-ci.com/fkeloks/ezplatform-logs-ui) -[![License](https://poser.pugx.org/fkeloks/ezplatform-logs-ui/license)](https://packagist.org/packages/fkeloks/ezplatform-logs-ui) +IbexaLogsUiBundle +[![Build Status](https://travis-ci.com/fkeloks/ibexa-logs-ui.svg?branch=master)](https://travis-ci.com/fkeloks/ibexa-logs-ui) +[![License](https://poser.pugx.org/fkeloks/ibexa-logs-ui/license)](https://packagist.org/packages/fkeloks/ibexa-logs-ui) ============ -Symfony bundle dedicated to eZ Platform, to add a log management interface to the back office. +Symfony bundle dedicated to Ibexa, to add a log management interface to the back office. -![Screenshot of EzPlatformLogsUiBundle](https://i.imgur.com/Dlr1LFs.png) +![Screenshot of IbexaLogsUiBundle](snapshot.jpg) **Details**: + * Author: Florian Bouché * Licence: [MIT]([https://opensource.org/licenses/MIT](https://opensource.org/licenses/MIT)) +**Available translations**: + +* en (English) +* fr (French) + ## Requirements -* php: ^7.1.3 -* ezsystems/ezplatform: 2.5.* -* ezsystems/ezplatform-admin-ui: ^1.5 +* php: >=7.3 +* ibexa: 3.3.* :warning: Warning, in its current version, the bundle **only supports** log files in `Monolog/LineFormatter` format. [LineFormatter from Github](https://github.com/Seldaek/monolog/blob/master/src/Monolog/Formatter/LineFormatter.php) @@ -28,38 +33,41 @@ Open a command console, enter your project directory and execute the following command to download the latest stable version of this bundle: ```console -$ composer require fkeloks/ezplatform-logs-ui +$ composer require fkeloks/ibexa-logs-ui ``` -This command requires you to have Composer installed globally, as explained in the [installation chapter](https://getcomposer.org/doc/00-intro.md) of the Composer documentation. +This command requires you to have Composer installed globally, as explained in +the [installation chapter](https://getcomposer.org/doc/00-intro.md) of the Composer documentation. ### Step 2: Enable the Bundle -Then, enable the bundle by adding it to the list of registered bundles in the `app/AppKernel.php` file of your project: +Add `IbexaLogsUi\Bundle\IbexaLogsUiBundle::class => ['dev' => true]`, in the `config/bundles.php` file, just before +the `EzPlatformAdminUiBundle` line. + +Like this: ```php -// app/AppKernel.php - -class AppKernel extends Kernel -{ - public function registerBundles() - { - $bundles = [ - // ... - new EzPlatformLogsUi\Bundle\EzPlatformLogsUiBundle(), - ]; - } -} + ['dev' => true], + EzSystems\EzPlatformAdminUiBundle\EzPlatformAdminUiBundle::class => ['all' => true], + // ... +]; ``` -### Step 3: Import EzPlatformLogsUi routing files -Now that you have activated and configured the bundle, all that is left to do is import the EzPlatformLogsUi routing files. +If desired, the bundle can be activated in prod mode by replacing `dev` with `prod`. + +### Step 3: Import bundle routing file ```yaml -# app/config/routing.yml +# app/config/routing.yml or config/routing.yaml -# EzPlatformLogsUiBundle -_ezplatform_logs_ui: - resource: "@EzPlatformLogsUiBundle/Resources/config/routing.yml" - prefix: / +_ibexa_logs_ui: + resource: "@IbexaLogsUiBundle/Resources/config/routing.yml" ``` + +## License + +This package is licensed under the [MIT license](LICENSE). diff --git a/composer.json b/composer.json index 2301ff2..878d839 100644 --- a/composer.json +++ b/composer.json @@ -1,9 +1,9 @@ { - "name": "fkeloks/ezplatform-logs-ui", + "name": "fkeloks/ibexa-logs-ui", "description": "", - "keywords": ["ezplatform", "logs", "bundle", "ui", "admin"], + "keywords": ["ibexa", "logs", "bundle", "ui", "admin"], "type": "symfony-bundle", - "homepage": "https://github.com/fkeloks/ezplatform-logs-ui", + "homepage": "https://github.com/fkeloks/ibexa-logs-ui", "license": "MIT", "authors": [ { @@ -13,19 +13,23 @@ ], "autoload": { "psr-4": { - "EzPlatformLogsUi\\Bundle\\": "src/" + "IbexaLogsUi\\Bundle\\": "src/" } }, "autoload-dev": { "psr-4": { - "EzPlatformLogsUi\\Tests\\": "tests/" + "IbexaLogsUi\\Tests\\": "tests/" } }, "require": { - "php": "^7.1.3", - "ezsystems/ezplatform-admin-ui": "1.5.*", - "phpunit/phpunit": "7.5.*", - "symfony/cache": "^3.4" + "php": ">=7.3", + "ext-json": "*", + "ezsystems/ezplatform-admin-ui": "^2.3", + "monolog/monolog": "^2.2", + "symfony/cache": "^5.2" + }, + "require-dev": { + "phpunit/phpunit": "^8.5" }, "scripts": { "tests": "phpunit" diff --git a/phpunit.xml.dist b/phpunit.xml.dist index c27efb7..efa067a 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -2,7 +2,7 @@ @@ -14,15 +14,9 @@ - - tests + + tests - - - src - - - diff --git a/snapshot.jpg b/snapshot.jpg new file mode 100644 index 0000000000000000000000000000000000000000..98ad61f28db4576241569869765caf2563c58f16 GIT binary patch literal 132415 zcmeFZcT`hb*Ebq_*Mo>CMUE7aen11#&yfxShZ0JFAYBrgp#%u!v4FI|0Sri2Itd|$ z5LyyYIz&K90-;I?y|>W)IL}+h_`W;txOd#~{&B}M_sHJAtX}6@YwkJs&%vKR0Ke#K z>uCc{odN((om_yQlcyi*X=vF0X=<#k_e|@b9;fdBPU!4!0Dz~LAKX;u>91DS;9viC z`wwz(^7Z)-{C{|!q`SlTJ9Pk{PwM~R|9|In$=Su%=_JtF$!;b$ABm8{)PQtYP9p1?Y{x=>u!782}{(tB7H~n4W zt1ez3vy-RQ$&U}<3or%f0G^)U|4-?^+S5B10C=(u0G#>jzuX+t0D!6p0N~Ehf4K>N z1ORTl1pq3$eH`Ep|18Yelly5`R{&t62mrWd4FGU{2LLYH{6|6mEAD^w#s5WJe?5uA zcT!L9lgka@0dN8Q3eW?10h|ERCrA$P8$cEy|8p3i0XTE|Z~FUw=7i3kKl?XbJb(V& z`AZisU%qtl(xuB+Z(O~6<@%LNm#%SKyME)BUpRibeDx;h&0jcA@GpNSa_aAxXU<+c ziTKNvOIJ=@{~yxNF942mJabAAaGK-P8IDswn*jVL-FN!TsT2B-766>RaPIuY z6Sqqz-j=@rPMtk{>hzhjXRn?;ec{~c8-Tz6oIB5P;U?#;`xik;yrQjryf1s^4-AxF3O%g&&*e_4&TJC?c<+)i}BFa|m$t%t=K#&Ts(K z0mmi(_|HuLe+e|cxfDNt$xTetOX0Cv=p7~s0_~W$JS|m61jX?eV<>{~XR=76%c^-+ zw8ckOejKbhtK50;7z-tW`erE@x{x)p<^-MjIM%&vVTa%kxZ=7)u(32Dg(~ddS>`NG zPcS9;&iE~5;LY(4&^GoT!nV3782Sm)#ImPz`#{y0!(Uk=Ns?M39~T<@K{+~s?A08p zbw+Y0FXeG!N7St7!`RmGj?m)bbP-$Eg#0ZXBxBz#2sE^!Aari{Gd0B0nb!m|TdO&h z#+d@gZ9$8mFNYi8Rlh6UN8+q)K;EpmyZ2n^D)BfLDO0&bw)YzLEGi%LaJfa0Kr00>tZ5>* zQVteJ?nswz(OfG(9A4jhQ{&zn`0Q1x^`!1k0E7bt(n1W@yFD26J-@xAQ*wNx6IPTK zhx1_R9_laGIFxHSEN@SAFa!y-*4(08@uNrsCKAU~8A~8cRvp|HX`AP$ZQ6MNvd+h# zf-$PLb$G{?EfC09%X*{+2!ts&%g(50kMRTMJT7 z#B4%HgX4lf0kJmS(#GpXe@;+ z7JcZK;F;YM>ftmp>Mb8C<9K}ID1)?Yz~nC?8SIYnnVLi_?F89}8RF=kzzp5vgb#+~ zfc`B>dt(eU6M+I)MF@Jp91$7g+PpIk%q3{*m z$ZBt>)6&uw%*BK`@y}4p>_&}^m%2Za^^Dzzj<6N`WzEFSW%qtMNdQxkN$~P7P+1lo z9*X}7C|vzeLadDpt2E|^=xB))lan4$i({r&;DRz2i?RDPM$g2z$8&M*p*N|Pbd~Na zw6K&nq$jiQE!hFN`!Yo;nRx??$n!^ZKACa>9YI%4NTbfJ+n-9eJ#N5Tl2tb)LhbmT zK|ov}JHZ;uno)`u?I(bUEiA!HX^sYnx>A5ACBQsI9~yBdv<1N9W+TkkxkA;SI3;&H z+!*ii&Kv6*r}yAIZDbk9=>U z)>GL(ppPjR=wYFJt$e&m1~Tn*?^bl2NZf-Mp+Om#jH@i2juCMlMY0bHoccMkR+%XNRAs=b|WPW z4I4wNx7|qw?E}I#|0tSWXkq6tEBWMK;eSk*y!kTa+r#W&rYL|7UVhsdSVCb3DH@A{ zn7kn4;*%+@0t?k2WlL>Bs-jZ44L~$^w7j)DGh)Nq8zqFSPQ*lyFz}b=a0ei>rOCRb z&jyn78y&{#7Y%4{bks{@|W?<1$IYsIBi*w=2lqd7VnZxf@>jCy>{M0h7;sb@2__CI-6R9muVjl6#kT7Mu>eF z^LF$Q4qEEGT&GW-Lf*9zaXkw|TfP&Ne;{P}7Np7Qz;>j#gGaI)S4{5yTTSt2l0T7>iSeI?Vas?joRE zQ&}tTQJn z;(I0Bul8Bg;QZ#-1_Yoxh(&oqujY5ra4vGxJ|>UzR}l7 zGqDGoF~l<0!H5R~;dhTKSHO|#!6oSfzp;ITUr)@ws#r4MN0L@MCuF%GF?0E_G;x_( zQU3S?dPzj)%ay}qw%#M(<9MT+ba{%I`+lL_^CC%q&Qiki-ttX;Ut^m=5B|^y8Kv#_ zuhyUKO}V%v5bNt}D>7-_d;xejiH7GzJJ}hE_JCz&4%18JLlM{N%-fs2T=S%b4yhJ< zFLD~uj;XaeJ}B*~Nc9>MT$fGiRP2rmD+RM?s1&a5wv#v8KJfeLPfh+v|B(RO>t`(b z7N#;%>F%Dl?J|;d3qLYldw7R*lBX2FY|_Qkn2Be7|+*xh`p zZ7@t#<=)w zBhz8_Sxs^8H=_W*oNx?)A_vo>#olXtvcLSuoYXI_T!H>={w%WuxGPSA$-GmD?h;EB zx(z~FMhAkH_ZND#CWk`p9~_=cJAAIIeA0fk<18d8e7OwAA8=XJVJEJAYA1yCOs$eu zJ?i`DI#07RHo#!Oas#6BUFk{I6&ryVifjkwC*aZ{R#EFw^-A&TUT17E*KgnewK3)2 z+YA$|di#=AEc{yk@Otven?Dg#+sK0t#>l9lj1;Z!ifQol5&~Uv_EK{=EeOxY{ikx4 z>IIqS#88W)+dbtOwzM+V#&6awQ_ma!Olh_O$tk!wbAYIPOY5+8VZsJmJAQf9JfVjp z9N|^zc_iED6&}fR{D5I*OBWq}s287Njt{s4vXPYWh#ut~TD>t)(>9&Ry|7m7eTAaD zxv4)iYoPY#W@9X(IiCu)GbrZDRxjaomGOTA8h=@R`M2rqMe?6`HI&!X7`NG zouYmmf-`r4DMEcub_HXYDGTbgH#me);J*|tv;%5J+s80*-gj*;faGa*PrRnet@=Ng zv&v!iXMjxC*Sr-2TV}%gWr@A|C?u29675I;fhoBGLyZfSNlfZE42K2r@;XsVN}_g70b9w zM^Mx^qk}AJjMMZ6 z*idXSZA!N3g=JM2%uLtu4Co<%vlCW$+L_(dKrw!NSw=vjhI{jje~8^^GB^h?mtpZO zvA^C-EJ(a%%Xg?OVi_r_ zyP$ehlYm@&tr~l66h;0WpxJBhGWDyFrA9*?&b_`#$}aEVzn@NKL&9x;t5jNS3{F6$ zWKk$X9>JS(iM6_;w?aE>7mnIyYCPp$C?|4(5~3~pmfHN?{6{yBl*eTpUVd2El{8Ev zNF_4zJ(+e_QO{o@R_ zDC_$aaVKp2MQ-nbEq$K56`tgcH~n$Wz_^&)WhU!u(Z5#hVyjja+o`9f-A|j8O6iKe z>=O^i14s9C#Mjw*^iYK(ffsKOeZMKA!QHs)2woc@J{g2Gil{x12MXIZT2Yk$(Fc1s z3z_j5+VL!G5jV3{HBH(y`Zfq?|MKr`{6G1)fg<}CgVML#)2;=t*IGLVuQ6mxXqi~H zprCkW`_laKIs6LscdE@gE|$q1)M~{nam2bH3&>|O*-hG>A)&zfh8XY)a7?5Q1VEsjk1Z%8bX zmeDZXGcuc4<+xL-D#`-dB||>qo1LXBV!kPO_E}Bq0Bt0=>K-NbuodyzJ{TM_J?W7h zY`oZf;W|yn;%ocsc?MYDVi?$N13l#UdbYP#ng@sKbf&c;;HsTd3!)6`>j%Z#Yb(dS zl0$EAu?hxI3M)M%iFtlaD&*G4hKxPqaKbKQ+ivR)LpT^&c<2`h>Z+_ z$AVUZbA_^V(!z4LuZYP!o9?aj6yFZblL{bVD^d*na9Ugvri44w2&wG|uC{oPPE|Ze zapsSyzS;1pO{4t$++^fW0HV9Bxb~|hEbG~@FZudR3ZeE`!loCVB3p?crR=CRl;@k} z=eRk`Ry9KvS3p}jKK&D1L)7?cPX@uJQkhqc2os6wcV^0_slW$AA!bclPD$FidaX{j z1EkTiSvu}uT{ZWuY<*AjL2%l6u6j(Rj9 zoe-wo$t6zzbz>Q1)dSkl-;->K>h}dlkFA7ZfP?c&6E!vggx5{;)iX*hRz1rs9+nnp*)lYSb#S%4xRJMaXhZK<6x^5QayqUN zsWF=Hbda5uUdP=9+ikI{!S?w_Z455TK<-*JnaK(?)Gr9v@q$;lzytTMvnv9cU(pe9 z3>%x0Fhet|WarnNJZy&&xz^E1^I#?_CP^U@qsWC!XF(VN7%?}=D|UhF6Fr9&PCVE( zwoJ3{hRgBQ2SrXEHE}k`P!$&gv-U|1$Xh)6a|2Ebc8{HlpmJw}aN0+i_cJ6w$&$|b zI6xqJC0?|xElVPuZtldToLRya6_4)t35dz%y6_Y5ZKY^eV^?gKyZT6WYR_AA`s2Ea zQMf_^?@xdLF~R<`Fw-kG>YgAnKRQWGRC5-{WwmWIgE^u#VBk4FFz?C%Cr6bw+or8q zXvfrS$nBB|8LQV8GS{8sUai0q&6do~wd6If)%++JdVIJ-I=l4Rwo;ycTYn1#n)Iq>jxIuz1TqVeY)O9OzB%Hk(dw4WG|&fdUbvurP*iEhEu5UjL~lV z&A#Xu%1^+tHgySE=eSi`8D6LyvOej}tYpFp3Ors^-rZBYZz+Bpo`yI z)`P3wqkAthB}pD{mZ$ms%fGY&d186*4i(pj_s<@0-eAbM94TPfqdBjqKS+*H0@?Rt zn_c30qQ-BEzy&daq8M@Uqr?4|8>1P_P$F>$LaSox?As-|H&e~%kkl_nyxv=Hn0Caf z1C7r+HT9FDpPE}<8cw{2X7huCRq)aQrG|@P^nHK)(BMvHCJ;8@Sd)nDYtA~9;b<8r zbwN}))SE5eYMD=uyN)WT_Dc#_2GmQb1}yC!SPf;B`?Px)CF$x#+nK$$ox=aqFABjrWWMrU;kAb}}Jjit9bV3R~{3jqT-q@IQ3kMuO%JB^Il0eRy z3b#$cYB*_Tm^oJVBQwc9eEvu=+}M-A5XE=dVb`B1;_e{VrLH2CD|)Bmy-( zjyhKOD3Y-qGAu6T{dyaQ|B?C?OFQ~H7vaN@hqeZUtPJiyg0X98JJ?h-hy?<2fhp~O?C!@QRAiHaycGt!!t(4KOp2p& z(xakMm&t7ZyB2*&O(R0{nc+R z2g#8TT}N=&g1oJjx(Jx;mIdttF|K2rn3TW;qt#OHE$PPVIOVyx=VLZLN1yhJ$7nzxr|G+OPpEbJD9TQT z6@tscu2EOloz`#8_8PVY2=2U`2<+5eZ$-EjA=Ison8CnOPlW)Ry(@dV(?g${8(-c} zd8|A9)Xm_=I~sR{rK-sY8=m=ccqd~{utWTc)|$ac(wgL${0Paj{`T@d(Jl-X9X6aY zlG0qS{GpN2U@U+PdGPgWim+397A24Fsn>zQ_@K6oxU-~lh%*wWq6Z$%k&g#35XKr1 zn8K1>)P`{rwv(fr%4r~%S1VAq;=RH2Y0LTu?HVxnO9`n+#^9)EhW21)#a=1wTSy|# zsRDdUzQwDYC8r>VYS4I-WN3s$DXL zR;5hklnm;dI)N9BkcG>^1Dm>ZzXbTB)+KMm#eS%eY2$f!U_>dA7T{TxYSC66K%$lD ziR5T$Cw$uKJ$|SB>${R+FSjceSoiOZE-G<jEzRdGapynz2Fie6O2uixo+Hc4Kp5CZz`+&4w-3Fep zq6#m~VD&|b8WtB%#-EpZ3mPbLv_k!A3$5{x)mD`wyLC!OrxHg*TWflC8J9Vtrnp4+6J^lLkl%oyd%Nab~^kXwHRd_Z@~NsxI*|*S!y&}yL51^lYDVG zfMGE;-|R}dAXF1`{ww6k9n5Ua0xP=9w|WHx12cwxCj{EH&L+fGd54k()IfGnv`@j8 z9z<6>R8>1g$D`an#B?!D%2C%LjX>Czk-YK1qQr z6|(Z4Q01^X2}>+wD!GQEcv$$R!Oe!PLdweFy7Gd8 zNCUPZeZyV-EQptzm`%(n%D|oH%zR_&lHI0C_=R0@I( z?bO%{ic9bhraTn%5>Gu_D+02WxC+M2^8_ts*Hwjjb8d#{cX_>m?MWJevs;NvcS}>? zJ95iQokbv*nwt?RR@l?RzscQx+Db4Zo$LU0w?UT5)gyUy*&Z)>g@8_{ZtE6}m=Ng9 zuGlSjyO3>ktLkWP4Oh_ATVrFY@9!CX6KnVYjg{(^!#;NYKLrVU-Mod7x*3lqElJ>{ zNAWY_MMIgnMPkPfi$hQGke-QJr-zJ6Gg$K!)!&>4a$6XsTv8m-$JfV`hPPU+|Vw zW;Sl3OUD{OCpXv6{-7jIH&%M?1hv?#wo2}^%8L8SN2LcgZy`KFGt$nt)|qbviNtFQ z<+`CaMjC0{B&2Fs6@qb4y~WFI;D40yYZ@SG*w$wK~e zwnF4gE|BY9ox@QFrkJAe)))d;3L|Lf^{)*Dh{JC7e*KP*$BVoJ_SQae(gs3snp*HY zGqk4W?25*3*Ax{H^=tL9vZ|GRFEB=1TjrFM-vQ3k|C3Uif6MFC+fkrO*fwT*Yl)QM z^CxY<-v9=hYZtge6-MzDQ-p?TAQQz2T0`zy$r{toL%RFHX{1qh=@3I(1$9Xr3!YIV z)QM_RJI$@eZzXBZtS<}%i;D{uHk}LEx&gGa%q{@M?jXN9&U~@-S|%As^lz9J@#qOI7iv9(zq;`g@MzQZ4Z+Xe zf|*08J31_d5vO0?RSvsKC~~fzzaMf*KoY{kdX+Ut!Q_%7yo&@3r~(Xc7`cTgwUiDT z#~FJI@6ZIIIa#kC^8JN(yQb+OWxk>lj5#W4c(8Tp-Yj#k?*}DTxQOfSi+?ir&Ihy4 zY_?Lu74Tl<^YuxCrF}#w{Z^46k@hrEUS7UA$a-+5h{3|Fgo1Ih(sM>4A3R)?c(dDe zWMVt52JdD^xZ~Qry4r=ZR#9|Dc^*?@2&Zep*#nL$X?Hy>oVy${pZY8XtaR-`$^5~w zWRK*QH;9V!swFK3DbBB^6xJmB7CJdQC;f3tVnV{|WYZB5Z)7rVlS5MFoJyEu04wDz zcS6aI%oUflB-qYuyBf1{jSiR z9rB9rp98?`Wc6zqhYtp8V=I=KQDU7>Bfd45pkA&$E499PXTjn%&^P7D9&(T!s;OzN zWp202X`FK-!14>Dz;)%VgYWfrTK)3yb(XZj4e3kH?R)wwuQTzmX%Cn_MZnIU&ubN8 zOLvq2)lrT|=PLG=gj0z z!_Uxyy059&U&-m5Jvts!Rcm~B>URL(Vx3Vd)iXpkIMGgp<4Uk_!8Da40-16(Io@uiFMF@^gPa$|ytBlwjepzeVxN6zB;#)zawC%O0 zPp0#lI#0jp-A}VWgIVGwb(MN%P)oV)EYAWjd^uwk@)@kA&$^N8*4F$qQjL|7I2bQZ9}Vsuz$DQG^Mo9C+J&Y;6LD@T;x#8a zm4$h&vyAeo!Xlt>Uvj&&+Py`~#-JCci-wg-`uRj~*9+B)`ke`+nc0@^TQvcS(VP#N z<*m&UJjK+p(=yWDgE5)#Y4h062L{mE9fVi{L0?gJ_bMvH2t3>CpOpVC z{mG##qK1QelWcN?c}+Ax9@dEkrojKSDk!k8|8dCi@^sE%=%=tZVe?+svt8w$Wamsz zwYsiY5>6|peua3=3Hm1XVy#_bW-wKKn;_b@8I-ORi%_T<@0GvybnJ|%CI5Nwc^Z`W zT6SrHbVUqi18fybP8wj*6hBVX8Zn!e$RPjuioctF|9(mQ+h&!(w9wUbcyrP$xd{0GxfF0xYzK zgR$O)wu34pzIVJv9{dBly8XrpOC0PK-)dR@wk;KQEpkM5`iBRHmM}w5H_7tls3?#Q zjvC`8(`{NsQ3_?>mj@p2IrqY=OVy4{4Xmy(W?tEgmkaRUm6U|nO7AAFLN`{m*H)U% zwMrD-H}PM0KZ(9sb}7Ob20uPDc*a$cWly&BHhgryNRqqEoa%Om!NTg#Ta*KB+ds65 ze<{-uB!$)b#KaU+1Q&ygtOD#}b>^i9NRuuNHe+yeM~^316N9t!YVt^Rw4Rf18n-NF zhhQ={LtI=Ri4_{RsBR7;x+BwkYP}=&CBhfN#!iK~fG{S#3+)_c}Rg}{pe3Qne_UQMl^ zt1QF*kn^WF*Ucx@izv zEtmfFg_U%nOXaspt@O$S*O?oddILSZ*XatXw=-!mP&c z2v(}BjRenEekC~+eC@1qo6Nf!NKQ25imc752}~0~*$(!7J-Ac64OdtcLMA!}^iDx= zBC99TXoHCHT{G_yS_PMfsy|K$>NedkC+p7Ml=?EztrS@8|IT`&r{lBl*k5X4La-w{ zS~|;77TGJQ8Xoc;(pgnh*c*8*XmNV9BV@PqOgtjLj?&z z52}vAYX=69hY2FFh}F#lnYOA^9~VbWGoYi7cq+NUmW(gX{HV6URG~AHe+X(P=-tMP z{{);H$pv;4m(AAj;3jDGXII1xbUyS{ul=)YPPGqlTe4LupW@Q(U__$lZA5AOJw^;k zHa@;mknbDaUP&Z)iF8>5RGQkHVhIFsaB(?9dE#ESYk3#UEV9>xv+qpq_0)e^`~_5{ zvNG|t#?QV0LO#QAShrRa`paXBkTFvAt`iF$u*cZ(N zCynNArCreJzvJH-oXN;7Yhh2!F|7`*xk}^Zv8DR6;+XXjl#U{p{!N)}E5i^An$k-3 zXKbCQI2-OcAimVSG9(V!Kr*h=xYn-)7_TL)fnRWo+KK()58F#oWSh_g-tMBaVxr1? zr(wz*Be~!~n>60t+MSKTf|lV#>?GZKSRt|)lbzt5muSLa5^h@bFt+1%mc6lg`j&eV zo$(XUMV(Ln$JvJ`t@YRt>)JULO!&0;xNJ9YgdRdk{kS$*C-E_cTa((6)wyg*-UKPm z4kRi3KK8Z9Um&FIg%yit$*@Vno(n2vChqBP_25v-=(u%|^0Yb2M3r}bVS4MgD-0%l z_!bW%G0*u?rR3sc`QifqVrUauO3jrJ?>q25c|+|)LlUwIf(jNJE#t;B*bffx1i=RA zG9gLpQUD8}(&+8xd-&Ulh12Ei9S>#Vn1y>TcG{g}MPJXJ6%ULRj%p!L+b{!oIFQh8{ZC0Mx=h|Yyq>I+j*2miSLY$_0q{e3yuC9M6=S-0M31MO1Y%W|0qBFVoT_u&umz}**OC|sC< zYI$5EzKzDOkYrGobD4sv2}1|NR$sghGz_g`ia3{X`0|+~Wcx z6Ylq-7ydHZ1OQIn6`dw7sL?7Q?ldSAAGDhhx8o^{Yh$L3mh6XC1*=wiRs;9w@B@K6D)eVEMq9&V!EySWC#kfc z81rSpV*HVlmS1d#ZrzPspOYOCreDj$t?@RxQWo0AU?7yh(Ft-iTAA70PL1b_%EZ^d(9h_+X4ExN=?eTcybjzY)MgvIR!x$NFJ~&IuVh0mPvOcV5rY8S@sjP}0)f2$Cx1=G>s5ZXtpAky~zQiRHg#w@~+Z$=8yK+Ar0DVte?;9HB;e+5W4$ zDqC$I(Dn&gmIkC5o8J$i7!sFF117j=L0$i3=$=p?(DRK<(t`B*YqED!-n#&xnAQYI zMdo&GopEV2tp|$&fY0 z&?B`HOQRFebId~DPiZ_Ss(aIWzQZG9VY_3sW<&C}uH;;3)n;kOV)bYt?{fMRiAMr( zz4QSpgp$`Icw${6POe|kt})Y7C^8QJy8EDGqmnJb4(ku;dGY3t`Fiuh1@q+5=0%A8 zjav+fprYyLp;1MVS|~??T})ZTLNRs-Q>JNLin7-T6YLai@_zBp7Lm=6hu0BstN@#r zHEWJ9x`QpMmVE_Lkm8)FMtuz-r_#aeNz6rt4rZXRz4t5Gg@_5|*O=3c_`JJX*ec>z z)1e*H@~x74ag7D7+Hf|t9?r*%U#VrQOQ)LK7TjsJLHAC9)*+!rug?iwFt2)8i>)Y9Mz8GZQ9#bnR-eqaW*tQ?kcelf z(Sqv*-Z!7eQU`FpGT9}u`V1n6s)`tRR-D}ug9@ix94%|Hg5WQ^JRj6lP+0HAlYhvH zd%yPFm4qw}++>`OppSGNMb8(+m7$*oxF+fAxrlv9^)ScmO&KH&M1xCIdVVLW#w{U` zANrRNs@RV*X5~CNhQq|UEX|q|vk;H!Oo;)dijwXG8-@FLVYzY~bdfK5^4OWcCV{v{ za(!xJn$~chGV)1lRb}aGz{Z@3oR0qbQ?}cjm_6xqSp1N0EmR40)px^M%N0WAzhV_r zu5-rOqI3gTjBUND#VU@$P=sG75i-3^13a!R2WRpWlHcT|Wk@b&K5LutEK*$LhO!l6 z=A!z|PnN?V7Kf0#sA%rM7nO8dzuC@A^2w{9JgQWb0DxNO(&3sNl}~+?tE$?+FHW zPAF=EyzzOd5kHaRmnC?bpt*kot5lNPjd)(q-@MJ%)Qm;PPuF5qWc&DejjBM%LEt_mv z#Q$))R!75*tBp}>-`>_j;)!k&$0I=|cATd1A_by9Rw(^8w%BOi!hv^a(dp^r8QUM2 z$;HlRGX~bpFZRRC6rG@7+p|kXh5fA|7g_O&HV)nP?KNd++_DkN5+0Q)SaW}l->eEI zo7iVk>C2q;sPPMtLUUAqbGDd9C4JjIYzei$F26p)7F^3JP5g#ce7J6ST>9P~JMb*$ zbd_G+HPOk;)WT(7tuNOd7;H$MtHs#F2Xb=myi(>U^bQlfiko)qz`6a7PVaXD-Q^L= zp=E9(Q?s9F5``B@u5vA3IyHok)C%1P?-ENM+loXoH}GhQ%}J?%!5LukW*s&&&O$W! z)A;N3@!jHjHlBAhEseIYQ_fU%T2J~3a9W#9bU&S+Gb95k?lh@fL)=ws&#HPuys6*3 zFSWhAr$Cd#^AW$*QS^o~HBus5DPPW8WpHsTaId7P?wDH3 zE-ta;F!N{vfySrfhwR1DLr25>k5Z>Se*K$OohtM=IB(D2A1ZpvX#Aaq^ho+>Y$J5H z?v|uqxV2dgMI5s)?#tfLUc(Ccc|D(vFZZ_zr9W8A`%U@6d#{YX(g4KeI*SW?2EAp* zO&N;>@aalJVL&a-a(2vadShp2K>EbjLY zOee|3V=B|96L}Kg27Cb=CM)Jz@oN1>tXZTLHGW{B07sg{kDJ$2ykvS>3_Dl$^yD83 ze0ANITR11xXY^?$!`>3{n3QA#&UMNolubF|uW<2ROIy@ah;2|@eEeCpb0ysIQKR{Z z)nPfjuIKS~X}|>R1>L#C?azVH^3HS5(8y?@Hn!*63MwqWn1GiupQ0<iiNfVerbZc&*A?ZcxR1t$Y{Lh7;|C zu9FN=SOkuc--(k9RjBspakRQ%v*Jk)gZl1fx| zexyJ7^jcnZDa{GAly*~lquXL14;yV*f7^dl4CKcPy^SQ@*3p5!{H7)UcCOzhO6Vcnay$d&AD?juXdu_JSrKsoc zk#POuYTow2qorAkKZF-jILRAVt;pE}qQMx22&ke-tkOV*+T}>BflN{ZP3KYga{^W; zniPC7vF4%*2+i+cHzBOYCucC;Ek4GZR%@Wyj^acnN4#u3%#6*?P&AX(qk)A{1B0Ic4urvgJs~rc^Wd&Dr`yB zZxFlaJM{HM@yM}^Pb)O-ng8%N-HFgN331gV;(MeWS1}sf;Dg`q+{e%#R`$bAOv@kX zsb#Td_Tg#jLKP?j!}UsP zQ)seBUVJ&0?w+c?EF$J>4An4ey@$OU2`2OrxlPuKYK((Qt**ycP^ zjlOlLHM>;K--%Zt`SbA0K*{iTBdEmW0BV;xNNZW@AD{>6DO=b^$y(>~NxbQk!q4>? zo(I#1L*KDpTN+&sN;&TiMVAhpSjl3OLDC`bjxHB?b*UJim}jh<=<;@VPbFYGmY?;K zl`<4e>XK)hzv@J6gxz2=9X12&L=ofT!^6XD-|i7lfP$CI7D)Po&rd*+jGZ>u*fFCX z7dxIa4N?}+k++Kt8?H=K@Nj-YEiy4Qd8lwnaIlntdnXqzJ41$0ck)5rZ^uk{qKb>l z?Bb=f0xc^t>Yw@U@@og%)!F|91g}e!-&;Y}74c_{gn9){waYj*KKeX>%94Te9+>^eugsXnJc4$#^-BGY#sQMHJF zT{1o?I(w8E9_{`HID%B|o)TS6-kgJ)`UdO;3#aC4$@X=-EyZWSEW!++jn?=QQ(}C{ zJsF7pjjCHc!d@x;u_{>Mp8yaa-rEUeyKMoVwm91Eikw{!9ycb1w5)4y8)dM5)Wn8{ zJX&m5eIjOT`cM?~dCMBk_K|ykoX_wae|%_GaVXHJ@teIR_r=T7j%cKBGL}Agq(-SC`3eCe2khcbt_!eom42L!|q+Qa@RJl)2_BysuRYmdc0E zvCkblADh`*e+gNaHsrBX=hnVH5m@t>`eO%i|>do9vdx@uo(H++20)W>5dGN zkf#=#QZ}UC0arCE=)Yt82_jw9i*mrIRY2F(9_hBj8Ef!*`FYZR90d zeOtBV?z&ov=YE+bm8;_5@PS9OsXNF`b^sqs3Udd($KRmZ$_0!ATjBKsrW`)bJ&17e zPK#bYQ9`>OJ&rzEZXFf9eiayc6C0LP+94fJFpYTZd)rBZHjh;-2o&h_n0F0Sv9;}v=9_WIrB-Zc5en7`bV zYnu4NrCz5>ez!FV;hSGgBnK;7wd?7vJJ+qs{;Xeqv)2B7c15I1w&&mmjb5GxJ|}ce zQif=tUfI>_5gDK8l{Ui^S{QC0SphgK6~Ifbt~qAwFN=8ED~HE6eLHP@6eMY72*SS^ zP6=Dz5u~pip6LkYggea)IfcvK_ta>d`O0$h9ui9oR;SPbn#~4k68L)-A3?& zScOfCPg$sJbN$VPyrILIjuBXJbKnV4u4;W^ky$C^A*@Ns6m{fhJqVI6f{8RrhU5_K z7)Ue^NZ$8DRlpQa!o<&v54h~IDtiB;AUU&6mSNp9(6Aj8Es*FcASs*d>fur=zo-?u z(elj=3!u=&5LxxeG;P}r(Kw%(TPKc-XC8}bbJ>mlqqsLnO5GERzp~2*6U7##=WX-2 zm5tKw7LqhNdA)mRgS%hrX=Y3}NoXl2E@|EREn#j1k+o**B~DK*v2v<=7DiJw%&lK$ zab}Do5PpdnsZCmuu1hi-ZmxRyVO=fQ(izJm8~{AIlxogRncDF_Qd#)|&6OMBA2a0_ z{Gci_Ri@_=83sIQmfdm>Yq|N;zE0cA+|%Ul>Gd93*S>;4w#~Pe@Q@56JsfYPv5LRvzGQ9N)3(1jOWGX6(hjPcvDJ z92PjJJf`g)?i>~Ye+n>>^u6m0nN(G)Sj?>+o7gaS=BorDVW7YeO#9^z$O0E-df%dv z2o}AvCoKx+cQ$mL6r~F~yKM)llt4W2B4bO=-u@QTHNvflA>kHx8L!$6;mr0+wr=1I6$+AHtzq^_^db9WY zNG*X%!xX$V_^a7Lr}p9!({-dU>~v|-(O0hW_VI*;lJ}6iy{Dq$ixQxa=RL&C zmsyfkyGmxbOiRdEdAGK7sLsiT{yuDg~6E z0YdD0|FlNu5PCb}VyGDP_-U%j*0<7FY=mF?GT#0RbUWos%61Bx9q1_Y(xh&3{jAR1 zDZ8Y}UB1Qsa%_;$c$3iOW#fhm^an%B`B$vK0sbKs=$-{b)E968F#=O3IqsC|P5+gQ zT~6B*l&bF@bycwb`jb=Ew(6)g z^M2ZQ-SNSU-)*Dnz!h-c_~295K5+7zUlRw_4tv;uc%4?=lP+EiIhqQ^|6I|Z}WT*^lc*}fD#gBQ8YaJ%18k^%~kiU@MX zmI@vxd$p^;)60SFb>jBln>hFAJg3fNyqZ>a6n&3Qt{VR_T6e41d{iAnhDu8l1$+*i z@=W4ca(VAfGop>;R%}kg*>{UScTquk9atqWDFl|*eNk8#c;|3vaV+2m9GxBES+WuN z@Rm{M^HC>L&J1IYmv3rGPZY3R9ZhIKSA9BZL|IEnW#h_Ltz4&QHf<_Zdz=BVL77ns z?PAs!B`=W5+_`ki#OkiDZT-y;IyW1Hc0kMAUinlDr4)oI>2DBL;nM2ZvrBQMR{fvW z&cZE75=~^N)$W$G>TOo*FIr0Qxnw|C;l^QctR11`kHunZM0LJ(BvtUDccU0>J&%A`>yuu)GhI!0WLJ%Qc0BVG@0Px6iQ->dV24IY+~&tne;>Y zz%0(JlWo~bJ$m$VXf4~>)X&dDnpHoP_bi}i8*ZI)ksnITu2_%~N8M4Hh`$oIP?*`D zJ$$cOQ0#}3{h0=QKz@efM7@E5;{!j0XE``(OFHAopw6A>wSaG4YaGD!JQfJ>S;=Z5 zfS~>SqlOE~uEb|m4Pvf7Yx;y{VmJ@)AIa~QH>~$egDy=eSSXkI*OzxX)Jm`goe*rB zO3bMV&kVxAWI7QpU1d|xR5LfXS37SyHGg77Wa*{=sbs6&`|5pw&RkD)AU*Z!HDIE>3QRGbz~EXQPHY(YSJgdN zQU=Ncw6g;*o5mij06r8)-7^Qdcfui{}#|Sz?f}+qwAQvyt=`a!?o7S=Ih!dk@_L$%uM_F z$NS z={k11EK^45EnO>Pxvl&!TT{EJovsDFE@C|&#gu1c{!Ed0&~f=D&X&WL09NiPjhoT6 z{P+V?Qe}#>?uL@4YGyN|Zl*Z!AZA*%k$rQfOM`-vPbpOgt84K;!5RmSSb8pE0kyfZ zn*%Ef$voEuDx#)|ce)jJt#v=Yj9pUJ@^^Qfu^aq|n(*>iXDUo53FWvxr=>O;tJo#! zq4{EluK|N)!@S|DM2Bv>zv3l|>g*f^2s*0EX_?%YKGcteTfe}IujDnLqjd`M48F^7 zZu2=)Evqx=8Rmr%&zwt?wFU9q>mTG zSyyt=#EJ2L>;^THb<7hBw7Rm$9<2P&&2byW8qUCnh})-;zN}k>{5BUqKM3Y=61k+? zc0INnA{I8>3UJ6pS%ZqanGSJrF*&kY8wK!n)T)CEp<0N zpfdI8E6O~adX!QOnaN}F3m>huBBUgn+MQ$tP&07jx$TQ^Q$R;^ijG8jqElp?^!GK*z*VV0^fZlJ# z-ldu&Ja?K78X0xBUws5Nnc0OY%{Ai!uc0C?J=FleJ`vq8kI#;C; z6hv{?ZG&xelWS8x5iCRuXWTvXaVCN+HuAVhZOvD+WLRs&K2y5MpOEbuu+4vsoH!+A zs-o^5hmP~JboDdhGbZOI2Hpg}Sfa-AT(_{FuFbg33~v2Aw%@69&bq8~i5%jwW?yTAGW(Zx|5c$o}Y- z4~x|Sc$cZo3>0Dy_RS9}C}>Qc{MDU#Y4aPZjdqmgc6;taXi!rd&{ufNzs-(IVstUR zn2J8epmd&l-+cN$6}4zY5~=sG=m!s+=+0hO2hOqc|NQA6iD-W_#Q$eIcW2Jzn0jKY z=^2Um$`xzQHKBDdddB|Bbt8$-nbG>i>MySS|Lcr%Gbn`(=dF8N#iuK0;+kAPMm%gK zMRpW+rSIbp-feRI=K}w+!GGq#fBp;q^Y9=qWqc_oB>&*<_IKx}2F;I$Pkst5`^pvi zmFt!8Pv7kASe@-~h;N0Uk&MXCZ#uZbo5wkXmtVO)p3lnP=X`35OW0RgXG3T6(L%}T z;@O3;U;cHKt$#pd2$#^wKXBCG?+_{V`R4!q1{d-luqpI+%q;o+n~i^%DdZoZo5yv& z_3yZA@&9(ke}fDBp9jvlS?9aIPE%y8o18qMTA~C2xbjdGE2flMpdjbO!y9${?%eu? z%qtZ-w}|!;W6$hs`9aq#z%5`7V!Rk$pD3^> zYL|mwffq;~lLdFQW#oj0siAF7tb;GnVUu7U?nu0hd*@9{Y>jv_eRwTMf~N+ zaLRg0$g!om&^)su?cusU{;ErOOH?Zytr-<;-D=5yU(3Sr=1AcLQ%}##BAho$*ZHvE zvUM55a4M)s<;ETRhn}*}&wBZqiOa(i^Uj2bamnHC#kfZc*v0hWAFN~po6{6Zn#>Gf zO+gC~fSo6+S2XMglD!BPlJv*wCY5y*nG`J3R>G*6(rUg1(56o*UBxy%tVhF~`3u~@ z4r%h^kgU=QT{DaRzJjfNk-Hv`OQ68*ANxLHzd#xf!#r%g?~MXe^N`2&i%t1X5ey@* z_GfdiGzeeHYHye9SaiKr=Id=jpNU8ch#sRI>3iFlR?jBez}9Q)PDXfcIbk>X`=IuC*b^IfMz&_LhvwzD zSvBCXn%R$L?O%kyZ^U<61*kIcM83bsUhCGnz+|=AzEV!Qt&Yoejl;8zkB4Zv;iT@l zC1aO;Wr0=%-1-<$r{YZo7rj`$)+dWQ(o-_rrShDXA1^rH;jLb^yGPjH4=JtC`*l)R z*X$?m@RPIIea}3XEs%t4&v+^kFoNy3n2Eg9>Q}r1?-aJI^Sz<3n&xt_Zf*XR>)V~6 z`;%HSrh^VakCn=v`O@H`j#`-OCL#rr7dS*B;7_%Vosn4s9*(h7!4hk{P$z1Y5~%o5 zA{4ZmRM(zpNNy&%tuLaTBASpuHGX*$rJ%gyoFIB6H^d$VDF$7%>zVUKyQ2JQWo(K8 zsVA=0;9(kr5zSDBKmyuz7EGpN+k$rXq|z$Xz?ZiAbNX zrlp^kQCy322<%dn?%73Ec*g**yTKUiz@7?g13y|0+)m<7qfdfocuZQj`NgDO4ti&sRHwym9_08+2|7-B#fB!%(?G%t)y8^LS^9R0c zQvAyQ@=_&E+PdhI+|sbg70IMl2oOBNJ6<{Dv3K<=*XM}BuUyAN6Rk((vbUs+v_^cp zZ}K)&^Bbv^QVzkcdj%vSCS&wH<)vPuk>?qgludK&i4w|8*H1P27 z5=!?)q^04pebNZNYvk3zah#}0k8hT9%?1$8zrgpdK_Xl(%S0`EPt=99+44GbwpMZz z2eW4lV_D6J9sdM~Tv1g5-1nnux)_<=w^Nbf%Dim=&e|!?SIOE8wiPtKX33HyUYpF^ zGao_3k5ND!Yp0e?D5~G6R-UZQF~v2&-!Nw0+S;XC!8cf&geh%x>0|}}ia?FXC$2df ze9|gv%tudd*2{o!N-l#q7BAlf+8y-QLID*a>0c1$s|QIg#mq0}u31f#HQ=jgTSls% zQ$dIGnYpRZMG-)&TxToMc6XBo^3+REl`hI49jjnCfCoJEBW8T9ow< zW89#67-9Y?vu@jvdefW(puPZY@ehU`~=tl&Zz>kS{; z1l_`5vlbeV_2#;Z?^s+$T}qa(9Vej;qvqP4GETtUWn&A!tZ-%_)4RMuWd++r?>*Js zdp5Nh(R+05<=EcG^r<6TB3OXu0n^bhYstK$qIo5QrB-iwK4c?2Q@b34GAQy!3E+c$?~OC9J|JHHz=;W4 zH4bqi%vO_DgmKrwM`AT-i=_%LT&%@ug)bb=2})W-e2JQA3|-5oXcOv1Ef>+^;7Yr$hO|EWeCIW|@^_evzS|g9HP1ubkw*v0cbkN#9vS5Mnyb(oYmWA$i5bc{k$FU5Jdj5s;KIEBoSv@U z8q=zQH_FU-FOg(Y${5p-v_RbbblUWbgI>InkL}5aZyk8N(2^acXb|rnuFT;~o5PTO z3IsZFC)Se#n?c#-UjhXLWUc`&>R$;rB!`09xvwXfN0qu=JN7Q}pt;p0EvwYQ8n(aG zEp4kkc0YUXRs2!%(Esy3w3_Q&?B5jH{?q=AEO3sE1FQ4pL-FTldQFa>oMC=3_%2CY zVNL0%bldW5Oa~MH-3!Bi^#1vF<$q52yLtX&hks0y|JdO_cKAC|{0ATY9dI(-t>VBg z5l*xKCq173M+ND>9#`k__V651#cs zl5{-15vh7C_1);-3&8(tWJ0s2GCG+$I#4h9xS zsDyS#lk?DH+g`CzTm(=PtRm51D}1jsDfmLO0=^*2*HWwY=-eoM#&)bWybCKjK^X4S zxyzj^YyGDU?Px{DhN`pOvr)FZCn>X3HYm7u_4k3#)oOAZA2b$iD{~z?mjnEEx3l)j zPx6GNhsJ|P_U%d+i1s4kZU|-meuvVtaou6|jeX$5mYM+33i~?4+MK!46mR8XFx*kpunW=IK_%FsD(oOBQxr@^uTd zaYqu2%;JhCtU+q2ov&HV3i50@C!QBS;%aF_67%(kcqPGZV<^gwtVN>saC1fWTKa0u zacGv@N;KiiXORGELsjWG%mL+m^(1JZxq&-|+~0Q^%{`TVjGu6UxNr4|a)EXD_ zg1fAW#rB0-;O864t~_6q$>LBY=sE$wY(8!K;ydS$O^%h_pDuIcE0w(s?tb6zHz&*_ zjMWzMf9J2oKgFNich*I+KsL;c4-Kg;eAynvZySRb`4$nF;fhfc4?^OIJN@``vjTT; zE-0Z@Ighjpd$G)BU{*-_?RMi^SWzFQqfQhLn8SM9&xlz7tf)peTn9Hai)`m~eIgYc z-5qDCC#0p0C+Pp$^6ihR@4zH7-Le(h)RkN{S5)*8AkSM0$U)A+H-*r?qo%Wv!wg|#`&>lZ0 z9h~$1KBbtr0wkRIBqSODgdGXsie;QXeUiq6B2Ik=ALQL@D6eYdghbK19n--;RquJI z(du44Se7Dz^DUd*X=ls?rKJtUjc@`O=f<tysTePyAJ;1YkJ75N%y zDOd2AZ*BMkeEHONO5;4(ka$yVtAB)eR@Z4eRIAlo)<16c@SWO3-9Bul~HNBt@@4WFN zzWukFA6nN$7H28)N?8Vmq=ZS$jwM#?SKLu5ZH!zqS^dgImV5t@^kdmU^9Rq>u(#v- z{oLh>Ir|zs$tbU$+zQ|(nZZf1xNbNlNgS?rDkLl@3nrD{=Ccj^&L{OQa2T2Uqp#oq z6K9Pa%eSFnc4tG)_2yCot|-{6o>d)dv48Yx4@8QqTH=FnP zo4D7cxS1PfOXM&WVh%x)IDv27Aun~S^s<_XQCb!661Gqh0Ap1ybLi4hT zAMpBUcuWFReHt$yNm&~jQIq#H=`6X4eUgRVF|i9GUe1~0DfHWH28TIz%9{Z})n~u6 zd1;~rBnfv#`md~OfNLimm!a<-s2EA4eP;%8zNFHy)L~BSi-}!fndRehC0}`KpZCou zsW@9yvJ0>*Pw2%c3$$?4;${eg$3QJ0_u8(ya9N|uA?En;C~JI$tj5+#(t95rFFAIi z7gmh%?}%BX622oY`ag?Y6wMk2bLgDbzR;F%S4|2Ll17b@FPC|({BOb=uEdu*PuwTc zgYEqphl1ja4yZNk#6UCzssP1sAddZ;QO#E_BfOLmSYp&v8}WQbyvEyk&-bKkMt2)V z*_M|tXFtFj2lB2~t%QP(sX-@?nzgWXlqt<6j~YLYIhb(+%)cE>ynG-~jUNjP zHck$K?{{_UNy;p9G&q_@xT73Eb8AUf7M+1_yib055=|Nth%${x_%!9rtCWSlodSXe zN$XF{$a;ap-PrKGqZc*#`dDvAC6>hDxX|yrl4Z2+Cs-)AxySca5ZRVJ4;PQK4d&h4 zQ5qs>j|ddNnF$XIMb9=MANt0x{xp<7yEWW8e!kz{ua|<@l3T^%YMG_!tIV?sh(!b$ z@*8U$4)3*Wk-1509A0gEu;Le(D{s^{4ashCeV*VLq*Fk>^OkQaVCNFk{yO2TUXRNgZ?Ay>af-6S5 z1I;hP)L&M=oDh7Qm+)Ixij0E(l1&28%$`A>70PY()dZ&+QRQpcNS~Dr(<2L_Cqm&?YL=swbLk5@trPL`$EPS5BT}BOOqBM{7VRM-fVM zJLBw41pjXPdnDDlwjz7g)^sPB0|#C!fy+9}$}UZ9g$8YF8_=p--Tg?QU1DSb<^`x_ z@L1b9kR=4xA+JXTVp=VaUK)2vhrgC9(M~((_-8U{px6%FhfkEZP*1i?OwrS`HZ!wv zuTTVwUxpo<8WlAf6)`fNb=mHwCZx#}G1K?0P<6dUv>AT}8rN#J$C%my)zIf4%gRr{ z#z(PLIyQf~+o#z+xRUFdq9#djgy`3*3v;KAOcT|e9Aa`OTk4Qc*mDJg!@do9zeB7( z&=|&iR*ZDFq-6km9-Ul_*;I_9)HN)(3(dp7a=pP6e^a_F_-ts&k$>+=>j>k z;WZESD%)<^5LF1vHV@SAM8kVkBv*@wa#P<~xwB?KwL=B$E;~W%JFe9@2@kiWB+4}LH%0c$V6u+y3_5*G~D&uLpPQtOW zz|Rn&1uc{w({+|7qT@7Z!*qW-*b?Di!ItDVCfnKHl5PP>?y3TgC*P7>MMi(d7u=$^8nSWjzENey8;#NgsA=XGdFY!TWqKqwBF_?rGIt!?6Fv zLb$crTxFw2USaifHBE|=*&sAvv6Mn>bAK+*|4!6H*30sjxH7&1Wi?-!<&WqeYR!PH z@&NV<8V+ubf1WePPtQO9A+Ij4qV8si(P?Edi&`UBku-PYfo}W!mFv9QgknQNYdB2( zg6*?PF;wY-XkqO7#u^x-Zc$1qn~pB@pNjW?b@tffb@74f(gBJ2P`x1NulWgKSeIdQ zkkuxVrx`CL9Em89-szUk77Y}v=14qANvvme*>46S95QzMaZ+LFSv#zabKPs3CuTFa z$>Ct3W`W-1#$K&WLCR*g0)LL( zF-Ryn6bB}X+l-*V%7U^L(5A$2^;L?DuimYh)N<{IbcS)=*z}q{r51aFn~5q0<}|33 z_vMX{g2;&X1)h%XOL>vDf@&)L%(5V_~S#0%WjBn^z$)}7SOB@#e?95e{eXkPU$bM=i`lxea*4;8@|NF(Z6 z2En@)sn%;}LNL2fr%*Rv-c#9>pt1;Ua}!&N*-jDHZH@n0u>H^Kd{f{>4_Fq;M_0d| zP#ti+bICD}!$K3VO<6ayaPu-`CXG>7{Mw|YkEEq)pH?3@7IHglRWM<$1j>lx_n1+! zd5N10+SU!GUReh=< zbE}qi<@VLP)P8#2tLlop#yfAJYTD%i8;~vTt2LC|5fFze1uM)y_e#DqtOAmi2vbXr zOSGQtnFnpZX*Rb$ip(v0*W;pspkSUsYndz8iDy?7)e|G7*=A&G{id`6OkE<+^~V9( z$m-3@T35^Y!;*S(^zhC39So5FqFXbH^dc z@?nCB;iOV;V~Vmiwh`znfodS8o<`SOAsYV(mU0Grvq-)2FLhUfu~`J(sW2?GOXQZHV6><` zjoL62%Sy7=g^aBQPqgOeCG~DX%=5sTI}R2u@3cEteaBGU0FS%%K6Im@XWopXU%l1uni-I*h)Z#+c6YkS(}LDM9iDQZ-fp@2klVx{%?B*(2H|WWgNW4 z{)vCqL2^tkeGsJ6G{!0fg8wjk;yr}l9g21t`hhX`E1+iP^T3b;&a1f~M2k~=pn!=m z<#EdQ{f?YgnH}>G^_8ov{!~;drqkrJ%zDEf-c*T9_|)CqX7uc|6wBiL;#M2}XN>En ziD$#Vcg|zKz}0PJrmCG_oDF%u!wVL-j09RCHjIVsMQKUQ4YKo)vv$(&GtN3XJRN=K zEU5^>7_Ms9W)KN23!=YKuWai;XjsF5eS4zGfWp~|FS^Y5wgPGVd-h*!RbASHp^qz5 z;$Be`vnd_Pe^DDmA;J^u`+hX?`d6+fAdf|;t~FbxU*hVYJirLtLUp<_`L8)?0|VDd z_wG4nro+B%CpFq&*!wyU0GZ2Is6D>s@6fz2!tV~iXleC(nT>BX`Dk|m#Zqp*OagAC zJX|oGI0HECl`JY_FgXhMa_-rlY@2WG^k@3p$n?jgGv`cNvwPqseO8#dSKV=)D`l%mUbv6Yn$^f ztCv2#KSD_v>ddek6B`5vStnkU$XuJXdh?=-$P=mymMlQAhg!nA77m@$*Hu14C)P`M z_vHuxtFE>B<2%+VhL%5Qfm;m6GDRT=Ye-st4uzvQ*Ie+Tq+N-8mIXUR+Gq~V>f`zp z%hPO_@LC~0{3>#U2bXNe@t5$3l8Lxmf%cs~s$8Lvti8giJ#}?+Gp!$gkqrIwUwHgK z?iEb(9a!``ih3eZog4uWuVF63Mx2vIjr}H*`5$iKr8*L##Qk~mhdH%76E+-WVeZn6 zrmk#f=jAAse%IWKB*QXGg#Fq-pc(-tt*EX>i-k*|jhIWMwmTzpCe z_Iwmn9cYr>jE$Rl-@Kd!B8;6PYVoCCe(s)Ik(3hfW+$&4j%v-o7)-W5M_KgPx~Oro zcr{&Pv2<fD0Gy_5plDeDZ%H(eM(maFN1rd_t20#A zaxMus9CA$3iTP`eWt*GPM7i7W3{9h!D~U;`HaK)ETxBv^O5^*4YupCeuY=k=K2RTI zcq>>{%m12PMa;FNKtyL7ZxLv$(s1K61O9HWryCb5)>jO*RWmT&Oj>Z>UgYqW+ zOsQsvrRhx~6LEr3v8iO|YlTQR$aRNF-iAJ=FH}TB9*iWE2l9q6p0#W3^BPd{oublZ zO%@~@LX-8RH!&SXVo>!E=5^jrl@A1^!ZKrbX#2m_a?0d>y(ik&n`CVMB)-5!v8r#1 zrwHb@stav-=y5M5AMPh3Gm3HsBoDj#KX9&X61r7!ZPh3D_RJ4W3t@1@0bQi{dTu`> zaTi3ixNe1B%CcBI1nkh;U(R>e?5TN;-{|d<+Um1cmFa~=o4PXsVPb^ar*%kjuz(MK zJfXHBq6Ho`Mcjb+ZGZBXBpcGj;6>GaNiJ1pmSzin6Qww|-ji!s^4hELMd8Wn;iVVAkL zhsry##%&_z0-koalO1+pfFgwY3N5eISI0EC2>4<$4CE`3Z?UTy9<}XgOb1-dVzUCMXYG4=MDLl& zpY_lu9dqCSn#9Ky>dO3!dXGU{VyQOozJ6CjrP!!`3})P`N+%j$atQ^uT_~C}H8AlG zC@l`#Rzp7auA=qHxLM=%Y@M8>EW`FmHe65H^T^f$^M$WmZa=41oW<&7pT2wL$;I_I zPU(NOA77lI^9S--t^=+*#U4A7N0~~p=Y;e7%I-9j^(iJm zrLpL6?lbpa?m)>RA5v>A0YdSWpO*4qcj12=UTv3xS9B*Q7MW#%?Gig4)HWNAgVjY6 zB|65<8*)xrE<3ajL0#{E*sA{gK&5>3*i2QXa_-ME@z@m?k;wbjHa2nlwPJ?3qI_hh zMdN0LvQNK|$A}G>&GOd1biKjM^0JMlt=9N3h4({K-j3Bi#BoxcVDUm(>)qeqW1fye zZ#?MCkVLOMJQEfifQ7jN4Mb!t@@@G_OS2h+Wld5l)gveRd{A2MZPAAG%u03QJl4_T zZV}aw#^I_E%^Pf&HxTrnF3@o?>j>@@6KDwJt%)vOU!(*ECZJw@sar= z<0L}Lv#0h;abn*0)`m#rh$}kPxU5^6F+3i~CFY}Q*BBwyd_-~7K#ymUc$;LK$!zrx z!>0RyYK=0y9x)9!ZI@)?<6PL`Ek z0cS>a86lP8T!4{xWOg70aoMwF1bzQVx%q&egbKqNd5^?)RxP ze#g?@_R+9!DrQobw1k%u`0rxQCM)ccS@UoHn5D<^1O)poluUKg1HLtuHu=%nrv6C5 z9y$5*v`qU*8G^_(@p}y85IZ~wSTv)sHCsga-|Nek; z8%Yg0l3M-K(W*rg()HyaAwjxEl)oHKuDm$G`rv%=J@|zx+0-f%%hQ zVuvvSHV@}HH4e=uA$W7~+y%XxDTz#z_SZWRzCn6CV}lUS?m$t6y2U_s>HgX|kKQl0 zDTW7|{@AP(DjEn(9#jguC^WyOhZKXtQOv;As{(me#>@HUbDwJOrSfOs-_d*=I|jL* z5go+{3RqhFgMKCOb^=G4RutKQc)0vjk6sSIw6;w-og9pY`LwVZ$E`f(+p}IpReV0d zKFdkJ1)WeNrjfU1<0|_eibXM8a@7hWQ?ZlXa6{~&fiidg4WOAe=CK3Y3$6r3Q*^{tQ5(Mj^+C5r5hFT zQ|(#UeQe3Xrk2>)(IY&h!n!&SFL0;%kNXX{;u{1plFa;EbiYW$2!SVbJ@wtL%T@qa zO1XmaVee6c$0v`Vs?%Nt>Hac{HM07hQqfNV67=|m%BK27 zU;izke0iAmlpW{4Ic=BitG{L2ve;W@mQGc>P74z5?_K++1Y~S z8EC_--6!}*wE)}&i_f1CL-|ws?0Q^2l)jyQRX9S}lCf}LW&z=?I}WW`iweQMi%$Yo zdXwLLPa1AEdiUm8Lk0nrevRJ_T2+<@N0sy7s=;c7^u$A@PRR~Lj@a+SlFHDXp%C%{b?act~37+kS}EZm84<1 zGZb6}Ch|XX7SI7gz#@v=XkW4(>mtMm5@x)pEJXH|vEY|+of^~--d z}%0;+UdXYwr$9+DAc2{N^=|$rEPd8 zAXy-%0I+&|<15#_Pz@boD-ES8-u-K%%zO8N&bH`-W~u2MHIP}zOMw&dU;+OD5FJ}_5uFjLdRcE{dJP{7oOWFxzQOBKzG z4wA{YL_-t9KPao4QESIm+Az&q(=9ot`C2d>NASSj2d2UraZimHoW6Ex$7*}bZOK3& zEu&)H+TS6ms;lHeDeJ*Db~*>zSZC5$@}7OJtjS#o{94rNI;u(7?9ZJM5n8sW65att z-_VUJ^StXponsM!>bj4I%qQI!%En~%az$Nf52jiQmBY@oF9WVHjMqV`2Wb{RC!c*6 z;pY4-u31F28@T(p$hBC!CZ%Wx7A?6FEloR>AP%%Aq#)H6C`Mat6*E^%i^I5;>Vk!; zyaaz?MF4DP0!@+J?@f(0wwNz&*n9O#Xv>%fjH!$pckOHS_DL2Xjy7TT3N>|>&{>T~ z&9eb4e3#eJ+F+qqX9(QHNBVwMR$t9@j!Z6}U05j@T8>I0s=?p0hmo?gjm7nB4_C%R z2S?2hA0a#t>)}Zph}`$!QPNAm#5`CX=axYh=$yst1{Y?ngM&JrHYQd1hTmtXoNCBE zImiuGH_*8f{BxQ#Wiea~CAx;d&ZYMEEo{c&d@r0)5jRwCrk!n=w95>KHxkiq=9*3W z0%Ox-%!W`c&ke+K9`q}hg@UU_W(n)4%lMB8EiAa-y|A$>1hd$7WaMNxou~_v@zw%r zbAmjqC<|WO#u=UJRr?`6MpMc(oWDGae!JWv5MkW2y=|f2z%SCkvlfpI)&V;2NlR83 z{I)Fo+mRoYw&!P~+Z!-^9=}lZS0lflc$O7CuPCvz2(E=GhpqH1Y{+99l)1k z>v@6NW~irZFREFUjb?>HnNg*w-P&qc?zq^HQK&l%JCTf?yjhwE#Q+)-^$SypU{8IE zNsdH)m?aV%+;nfHvHDn2u-b33uR6sHi~Q?!9jgVW3?6mc&*Y5Mg!fy&MAIwRZl7GU zM0W+7{%SC=grgutPHhX56J1WH>+-Fwbp&ez0cBIQ!xaH@fLL-RUm(TBhw1%={+1Z| zb7hq$~>&v@#)MVO0{pNr#k}RAoK8@KND#J zGuxjqebLyL=>xqPH0^Uk16k3TG~_z5zwcO#3cN6%lwTTuqhH~g?k>>a1(t>Kop^q5 zwLfHr<*P0SQTU_HqGQ3e?OBEEy_WGXYxsk;Oq)p;a0E~Sh1!5hzDfkb0e^HKKiECn zHz(3D7mvb)k`0t=rurfGpV;N^N~h>uzD@QvXt|{j;Oj)uvQR&MVqh#kzdNXe9FWVa+M54 zZwt)Y9A6wt9h;uFZ%K^=Eorr6nczvw)$S!tiAaASs2OKhO7t>O9y)&T!1qS~?FFpB z#xVT-(`uXgP!Hv?Cz_66M$^E0b`tOU8=1i`IBGB*Q>$Urm+ zURP|;0ai28kz_iL%YZfUhUJa%`npeiXG^$r> zLv2B$w#k|xWk*_4tOYA3r#f$b>1tYWLUaTAy`|0#N)@MoDr`xCepJ7dLx6g(VE6z=J9$l!{?kvV|CX4KC4q^r2N>}zC_VFttZNng5 zEn};bxiJ)M`L8iCJrm86GOUuBQb#=o`!xSUmXi*~E>A048zAR6?`Dk-WJDE35)-371%76ymeKM7QJL@Jlno z6sWX*nGW_zK73U3d^Ll6wWmUjyDs_6YKKxjq5-y zGA^AXDSUSxCKF^)Hff&R9kHY8Ng!j~V$z_szh(c5_FCpAVvd>f5482X^^uqDeW?Ve znQs@2NuKq(*0T(OiZ$m3&aURFbYnO#eJ|GvL&m_AH9}4Nu@)Ks4}0$&)nwZ4jWT1I zQ7i+BD0QTWhBkooHZxL$P(%o!2Bk_ukpKx0%4q)q|lU&dJ+|QNk`jyL2>kr9lh_5iLICY!l;_L?5Qz_qW0X~`gwDh? zRcCHg%x;a|F=R{QdP>ZrMV+s zdM6i^7ON-KVU}vuqVfFf9d?I-xtTIxG6xEh^@oQJ ze6_0Thg#TxZqM`-ioKJweCUFN2{l4x$MQz=W>2qAt|hhJ|L8gnDgj3hyC>F%+#B4p zUkl}YMne)3pj7W&xsM$sj*6(TKff_W^5Ao_4=x%!?Uqa-m28MRUuIkjkJ1O=06sB` zZEHh>R?45P-j|1&t~=Psk+eum6qpu{X*aKEBSYqbCu1w-@$6MKg=X;e1(;_2Y4cuy z`q)q1M~(mEY6I(O(Wz=?ra|zKc}*;dvX&_WKD{fD9UYbp ze^H&I+sNs2|EY=KM6s{}I4;Y9WR3x;gLquKGHf$X;={gC(*3EbF1Ui^n93uN;2^BT zQjC~vHpkk_wQpY&)cw4pZZYJ!BWyXPm0k|5MhZu_9JoJUiK>qmFTi^kmbb*Wb$}A! zxFy@>eshwGzibIgNur2vo{&S&)>0CT<&PYbwQ|au(Hc87$q)dD7>^W7(gIhYEg680 zsEM;`$zfj0dgYZcE$VLVQ#bzP1o1LAR%axpO|R}lDiJr-KAK9`FmOh*tdFd)*eRmU zxAXlg(?j(Le(PqarsGJ(F9YN5^U?wP$3W*uOC(TpSo4c$ew+XUd9jqWfT8K=h~6wnWfH?bDyD|7MjQ z`i&{zpM58sFE`|(1++*@J);sjaiG&`8V+rFD95{Mo`USeZ!L? z+SVL2kFY~Xy0;lX)mBM{{64)rbn-IVnz>6+0Wmf@<`3~!ubB5R|IAKg6*z&?+o z81@1wILpk#zW8UI4r8_XmHy`@#Rm~aT585HPJPiz5A$z=>V=tI9U~u#9oqDCN*{{F z^`Y|gNIg(R5Gp}3o28zACEK}He+c$|r9khJU0{!;W4L0`_z)cwr3d`6VJds=uVP*S$=Xj9*Y`AjY=4Qs5t30j*TR-u<3h_XEbx+*y`^oo` zFpeFq-fvo=>Pb2s&-iwk75>`dbj<~u(6Z_5+~M{21}n{u6ORJA@9#=A{M2xxK|jyf z!vob%U?(K_*7?p6ok;VwJ}qD5*Lr`F;4_T4cmxUg2vZ3P zP#*H*YPjcYfH$n{*kM~J`ell!3Jk$>^y+W#p=0TqMerKw-xu_2mlD6VYxi>lRl1ez zrG92?>q{YXgG7ipIp(gS1-&*bemQA!GM#E3f~|3A;)F}{B@~$cAfpZWu$QCyE*CB- znPkSdl>hM9K;4Y1h)#O_vgSOw26aT0I($m$rVt>zWG7$}-0Q;hE2Ql-5?J!qs=^-e zW!{j)Mj)dv>dNZ&cVAh}rNh4%BzHxpYVwMtY0 zN^;p~+)BmwBkH%d@>;#}rE?vb88}&IO!%tBcaArqyjy`*WP70F*x_U()peuz3O;`} z%Z+=Xo4=mrNcA&KDd(|kd0DF(QL4kTHJ#0zGBPR)}N2c%ek6(ffcR%nX=hW=@)_m8l$%sb(C)koQR6 zjOxvw&J#Wu>EsLcj%LK%? zVcl$OD`O@Gz4#Z@7-nNnzjJT~2rjiH@mF`3`-kPmeM9t)`!;!|F*2}H5a`|CfU%iT z%6rS@%yLHMh(@WqRNW(Z!_|A5 z565}EGiD|`-9h$Up^ia8hlUd(%Sbz>(|wJshg*Cmm&wpuQY?Li_;%xO&5xU<#DiiA z9o;ks46b{EJK{vGN*%z@2i>XeQ`GQ#T1flN*buOo=IWuV`efwRfza>ArYJP@bdctu?|7_(r>j`Tfbq_B?v-g zQ>Eu@8guPo7x(kU`XQ#PqIDKuZjz{;D9>c00|va=S6MwDl7~<~kipL94k_>%@lgje z;cx%8WUCmNS{#(sL$>B1uMBuv&1Jku55#JLEE4Q+}%!|bi?UOmBa0E1HeOz4+KW?LV=yOu=x*k zG?Rc;TGT{0Uk2LMls{d+AwOETJGMJS6#H!-gW>B%21o6|+qOhRZP?0|T@mf8laHq4 z56{a&#vPrxXC~k0KTze*1)(HuL0UIaon$n8KB=!{&u? z3erx`X;KA(F{yF+DORNo+(?QIeQP4K)I#To_OsSNT%*JwKvS!P7Ha;y=UW*~1eU<| zqY1>oxFz=WA-D2CCr0YM7V*$b#T3gVxGfo0JUjmUvB^;d_4ED1Wj5RAD~AB)!~gjL z=>MWR_SI+cxywTr?) z3-1;mCT??Rf$)}v5I`cc{p>I0qEUC>qn-F7n-q&OBiMil;eVo}UX4vCo@e_uC%x^J z3cW}j$&`3Y)uc>&du!E)WMn;INAfBf>VGc}U2J)i+gk8`BtI8rQ#H^xC6)wYb0I8_ z{;yd7u#t%c%D%Bxe44bA^{r{4T%f!$++-ei65WJ@XTga~txp_RW3DfQf(I<|mt-p? zq7`x-6`jL=#`akpfnVz|LIQNyL;mTZrFd^B`wX-ne>uPgN5I?><%`1M>P3QraJcUr zy*i1@Kv({FTKLwmzSv`O1Q9LR4p$5vT6nz>Tl4xq&-G6e|L=S9FHvGOD7bmN*)q+- zLSI6laR2a->lhmwG`8<}aN+mAMbE9E=)=vt9UA}sTJ_HjChZi@V7cJ8kzH&j9_M+edf) z%eVi%?ewv5dv(3&;k%QBKaXu$+B+u=Y%Iu&?;PFw|MXeBKRAWmyE;1#;W~L3+L;|H zy(fHlIvrN=={pA__n$wE@)xGb`fIyVtJzjlJ?LO3e(szT!X`}w1p3agkz{`S%jgS%^plR3 zBgmjT?~UA+o+g{qc{bVEE(bzb0(m{40k4 za})S$+5B~-+-&%3bNK(s1}psYlVl0WEQEUkMjaBPW4duj(AE0-3m5C((2*wpKuzRv zaD4a=nT=-izhNZg-u(kFS;lepKMeT)`r*HpX3zH}JXI?nYRH_JzPrP8Z(A7F%p^Xp zC;9Bkd3xGmaqF#OSBT%#v^w5nR+ETFAfYJzc+bVRS4eANF9x3E-e*k<&5TMwV zYTqV(=?1!@ISuC0T}y(%7c;hmK@}~g zfq?fHy*)6|CTlR}n*Ug%s^&>B&6OnT7`{n|?ul_Kj0;C#z(Ki55z{5WrR3hqIuGW{ z3XSCEJN#ZRFS#muDXNRw>1m!`0xHDC$wBrg=7}bDj2TdfUk=OQWN11e3Puc+uL1Su z&*y#T80*fszPk3zU}t&U1NG*Ww_yAL)2wTbIov2%l)~$3eY1KtiA!}o{???J7tAh_ zZ)36xz}oWvF=dvYe=zO3Gud%oD43D%L(u>vjf;v#*X<^Q$tOiwex?p}ba77^?eiy{ z2bzn@){W`7J)&aE*k=cp;G<5*nx79*c}uDc;>_65GF`}AN9b;p!9nJbqUQ7Sh z!cylY3t>B4G(c}rz&E_vZ`&clz5t z?)SS_Ek)@`f^Kxi^y*?>JSri?U1^)r-J4%u7E_SR zw*QWHmxiG>jj=gbxR)9&f)0v0zj)!-1a0f8X4OXD9cnAQ$P5p_IbmIu4a{g7O1YyW z5fLnq*;M`EdO>3t(H`}xAdu*hyz_YaO8|D``O3h!VeKsTwPzd6l04Y}=)S5boXx*~AWM?3oij#98?ZKVAtLZgpU z!dn=wG~j0m?OAk*t(~}AuZfGw$ic~S?gFx7M-ICqmv;5>w&xCy&g)6vxn!IU(r6Zo zu6P!xQ_QEx6IHxC2ZAj4wEuKxy|TcV8UCj2&&fh z6~9Vjk#>l+q{v?TS*l*O^5%kUMBls|Z+yO|F7#y2z~5VpghGEal(9`|I>v)Pe*A2` zjD_@i^UM61T>hc9?I*6(%9o9CDbi;VPs-2G;x(Z`WDyp07oQmmm$ZvnwJ_Hn3e6r` znpYN7?!U2h%V*S%0-{@*FG!&5G-V@zM1~Cm0Smx@rjcwRPYiTdr|!|k6m&3D#wpw9V+(7pdNlIZFl19jvI~I5gG+mu*pL@aO9u6szPn5 zrL&1M9e9!lRv%yLa=!$)p(NE^2T2b1zM@z7a`#cWZ;J13PIX=ScMfHV$xfW7&B5^3 z=59!6r1Ik6Vs8tN{vU^_4Lbmg2AjsDpdo#=M7p zSF{MZ&tier_0qnB3`B<_Kl=<+&bUm)$M}*$k82r)Z)(61stO~`xH<`QW&7cEZ(Ja| z&CtmII6-bSB#IDpaC4KW>$jexFW~L>a7wFkBqF*=5yS;@*>P}Ordos)&M)40MH9e; zM-Ja_Y_dhl`G1Y?9Uq|1H1j80sz;<{07xnZkjyYDm$E5Ra&aU?W66{}Kg0;p=A0Bxgd&yVMcZgdHb8D%(9446s zYjbtQSnODsa9w1cTeYPTlt+>3)$=tM1EZCd_m*l+7|8`AIW@7tSVE^UKOZ`-oRmNo zY`GjWU@#$uqgN>&v9f2Sw}KEnBXhZ8WwH zt;wTNfo7fxood=Q7KE;cP26$dNQ-n`K|?7Z`%5c;ko@(asrSxzcut z!M283X$z^bC77S8Z0?f%4U}P>`#C-591@pzd(yA@h1eD#6l|q6K*0@A9ODVm;nsB) z$}!RnE*q&pzlXA+@2>aR&5PuemY1U*cqkY9O-l}j@U{J^S@VSSrUOKQ@(m7UR^6aO zF$_C&QUx6@83(G@s|W0fM1_)=5WDXjqQQZZ+l^{{(Gxto2SdigMlGFK!a$v>jmojx zfVD(>3gO!9Dhw<3i(+@rKsi5^zCOY-e+$@*B+e>d*cEdS^f$?QB9YH^}GpvHk2l)8roeS59`=ae8*t>cI-B^ABh6Yosh&P`i7W) zS$w3IV61tQisaurHhd-gWz^q@Xn1>Yb=XeZ zF(&%Adz3jzjc4+W^6@O2zp>$Ub~f?zOrm8`VJ=XT4MtytoWFr?n=Kpqwe_3aPSF6a z1#^*><6)-La>Peh- z_4#>DC>?$5X4*RBNe_ykh;t`ixHoKMpnY-hHYsYX%`6#hegfuXhLf1ZIXiVcw3r1W zU#rlF`Sp>IrWNCt;l~vn?=1B-x%IdBg^IRg8_Q7w*vb0Bb6jkZtuNZoCWY%x8w2i=^|og0iG7e z?dq8-I}2nvvbW=D=e|Y}3cxEFCEGlx@rLs(<=kR{4W<#Q44S}Nm$_-&oSwXnAif_W^MXH$lrK0ssE%#c%-eBt#`Y!cUq^f%nEcKGT~1c;G}Z>v7_E%# zvXjcI=@lyt`hwSJ!AVh5CQ7RDmCLFXR&gZ^yCKjlx*MN%#oOnVUEi{$&xS`3!acR# zNgl9`e>!!k40yKGQFVi~P6ddL4NKaOv4%w?!C`0Z*;LQIWB9&Q)v(m$Dn21$3g4_j zfdp-JUiZ?^wVi%EN|`^5)4F;lag229{))epW-9Eoov zjtgXm3vJHc>4r@NxnrjQOIAUA=k;3gj~pwii3ai3a@7DOOR1#nhwAq7vacz}xfu;2 zl3c<8uO1~|$}POAyp|BE`7>QSOWPus6$KIWVw(nLH9q4-2*MOhe{iy`OzoU6PgNVe zRnMfa){I)+DO%);S+Rypb5+)n`KF69h+GP3Nb?;?-h$eTf#cBf)M$@V_F_JL)s%S7#&!SFaP0vi!fX^?3JwA9Dbl7ct@&kATg6L9gR$hZK&$VSwE$Y zuJC9jeZJx?=+%}>nyV(fY);#MJhX?O-l(tR5^M_CGbfe8pSQ7>XA^@`bf|!3W&sDy z=)O0XRn@Gas%aZ@-+~im8mfx63GO9_-JGYVT%j%7kEhP1`<5CjcH&@NaomOnxZuIM zt!m$4y`bB)OAdAllR?V~+Y?$3B#57h`r$)2kVC0)UGaf6mIPETLwUJ!Fkyyn z60wu7M&*TQW>(h5++vOmrIkW3U#e|E>j4c?N{;>r@|2`N{qy3coRC7jAA$8bHIl&G zx~-Pu%?WONJ&OXUFC$9rWq@l?zoLGB8j|Jb?RNUktJY&bh}()xKGD=1L-!erP00`I z;@Tf3Wh`{WLNzhIW|36)>0MlCP#U=`D2 zsRC)$UD0vN5!q_OiO5=>@phL8wrxP)r}^Q4h8^z}j48eT#`o6<3#}P@{a#T!K}4I~ ztIuTWToliaY^vN;#Hmbzq-ryGL{nP*;KHgbTc+=leoF@gyeEWJXg zEFgN3%&J(bQ(_BLOctu&Tv2 z?p+l}Goyv~E0Cw4xGr^-cGqgqq}k_F0k(#jLQkOw)ZXb6i(ZQ@{K^*96fC@|hY7pz zj%xjq0t8t)T!9YXGGL`rD#;kw*VsfS9-fAxr^DIleWU{S0qEX(AeLx5UdmF==`fb& zv*zS|{LMN%zFmMAPS`44pD1t4x{&QwavuNLIQfHfNp0? z8||&D`9tkRt;e_tP_=M-SgX$d?zh||s&(2b+Bi7fF`1$wY-Xzgkyo<_GO+FgpBnrTtKPgH?R=Wc%IL`h@BK3d2K_NMKiHmi_{WH=|2X)2?`T6l>oe_?G5za54*qAe?H?ol z8v0iR{))g~5%?icB;HM_u3Ew2CKREf@b1GcmY!6m(sPOZj|0O^a+ao~d zt!!kub`mk6SZV?n;E`I2ytjKOvI)G`m$tp7KYECij+w8)#P{q~*zXP0-ExT?&rKiMAPk-uQ$N%ZtK)%o)RTBo)B3cdN2mC3bk#D zFId8X(ZJq*{(RTt%dnz4P0E8ub?NPYTp#9Jd{QzRxPENy;^7J2V2(v?gLc^Jjza|TPotmYCKn@|QO_!>Nb^MAsG_M>3tu)m{yE#dQfKF}m*-;RITuw7n7{NM8|Gy6WvF;M29WD;?j2Wz{i2q1zAZjl~=A*hy4o z{`-rrCIu_xi?zujl6&r>U9f)F3gx1wVjV`MNSIBVF25aJglvafP-JsZRQ}H7eH)@n zilN`DzT*TBG-6~JRZg`TTr@r-64z7l&Y*d`OVob63qEJT_@(r++5&{Mw!f$=M%!!z z?gcAKum9O>(b3-qE>7-Nm+(@;0X@G|^CSg2K-x|$51(gd6{We%v9*i-^F#Qq6uokq zQKBpRW(R!|tB)XS4MDV8zjJVOgR<0@D_Ts_#B_t7ZG#ngSJ?2qi^>J5Kl@>`q!Sv| z9z>1GxC%;6G+L_rt#qA+HP@a)9v_R`$$ejgU$I3#f+uAhrH~LF++gGwcFU-&1(#LH z@5tsgcN!MwO(lh*htb-}`gou%(Sk?|z@ELBU_PlluG*ucq?OnW?rxSWRSI$K)4JqW z%-x`U#jTvHAD>XkluQcL)!q4ez1z9lLH zDVo(4M11DsgUPMw0%BPQ zn5;o;_Yfy@l=LEXT`XQX{4=EEOY9EuN{qJe%YI z8oW3SvpfP@Y4s%weiO~0!6;^d`ig-phxJ*+xtcBd$-$1eY-SRxJG*FnX)QMHmAa{S z@0T7Wy!&XQLpRb6T?+D!=FhfDvMEJgq$`>y9ibEW4fdCRc^to!UK&opJ9ej4bTn2m zpd!BPMiiUV^W!7lq>EGk_0Qek>fR9a{f1YVsr;7s&o2F%E+zAM1V6Zv9v;-|8>Sk$ zn{#;U!wZXcn8_ zyWyss)$O4KrN?7IooYNDT$)_M&5r1Z1ywFCDx0%pqIzUp_S5^j2qwJ(&OB_R0E1lw zTp@%uP>+T4_3|$d0GboP5lpHXmsJ~nDw4V{QUD9c+su$->9;k4vo>r4eo8CsJBEGz7@k-z1Nu6CZ2jR|kSk%>-y&TW#g+NV z@mubK4;2lvogs-u_Qu6Jv&EleFVc2Q%wNf`@{!&?mFRMVlQ~r+DzA)s z1j#Gakhqvliu~-^CgyoTrEa#Ngis*0=s1t; zwVhNf0u;lb#-h-(<*2Dv6V+9Cp~hhA}ePsZH3WgUpg)@6kQ z_Hcl$U7x1gWk1w5_z@8gLXMfC$GzY)xz?Yge$lU6u`IGc_k#-^4VOE{2$ngLse`&a{GZ~ z?(+Lp*3C`cjPlv}LV9^|#s2IcU!)XW<>L zJE;C0K>dIFXEuPk&uR}ujFQa=>=s%kZRl>rvnxV>P54&~|5`Txbea8irTn!y{I$XU zH@c?;-_EqQBZS<`Hc@2-m79e%FOw~f{`UL7a?Aa@nBJ8K%{!7~hBei6wsyRzVq`0m z{|c{kPys1&HB%+Kl;|wq>(Zm&DS3pV@sH7SNGb~-%hq~5_Nq>R~kIA|#SVC>{Ur&Y0=c|Y%EOu7psp_3K;6<%L)>Quf)rF~1dgC*J`Et6cyD=Dt*mysc$cld=mll1G zj?h{KR5W#SKJ9ahSm+o9bK|eembLoETxHZjMgFL;1g=uc5KDP0ri+xQ<@}Nr! zm(5Qj2@;~C+?L0c_A_nmM8MEdpasZ5*XTQkK0>DY$mmEFrV93daVX>~m`I5kt9ZWx z3Uq7eiZ|dcF-h3;pJ2cQ7D%`V%7lnScJb$?HUEQqDyn|Q{sk31acN14xkP0F1Akc4 zrpNLpxNzmXHxcWy^yWK9>DNPsY;wygwH12uNBV_x(YFMgO?0rf!k43TO-tz1rcGR9 zu}UvW+H>+@R>|b!rDXl$;o7+TWg)|h>6Z`Js{`QPP(l<$N*Z>DjlhXsbIg$_6fGnbkHMd04kVYw6-ip)-^HM#Q z4sh)p_QmJo@{HqEd2TLoP4+o^u`T_MQ|{Sa-*ar9O=*{2d-H7ZsN(ZUitM?4tmPGp z-B2djCVx@!@`5COzBXr~Vfv2xIj@=|La2SnCZaiX{ANTOxn5OZiYs6hj5sVlGj_B= z9Td3INjGwD1)N|Z_{R@3)HREfzG@#++FjJkQ!>}!Zje~4{i;j94- z7BYt;k#M=cg;^Igq>+&M&XZG#+ivz}FeimI8T07U8Km^ySjv;7P$%iq3OiRqMDrgS zzOGJei9}0K_!{blfry(k24=fVnE-6Swug)Doukc`ZfK*HXc@b1UhQOr(G;LX$dpUe zQNP04EQ)}Ph|1W9qVw@Zkd)ub78BxQj%4@{AB5O4nF^E#H(;* zL$>#rH>6DM{Hs;>_Y<`*oM11j9ZWlCmO*WwBjSSfNqrCB(<$$?v;^8qVnGaoF5{Zu z5UbA3XR3eFa5(72s%G^z(V}Ux)$EfJrXmHLoL?GS%qDxMc7D}6j?N(O0dKiCM{pI*I+J6xM{|Joe2(N%VubYlE; zA$!|&ajFx@xq6XRWwU-{gSETzd#BevbYvyG-lfRfIMxZWZ?&Ui0VZW(n+nI)>f-%F z*wRKey|o9>wKrKy)6-1~S>@m?awy~Ibhc~kJI5u+$jD0axciDh5t%Jk@qUd*H*a`o z%=`NDF)L!7o63ps%4YJpF%YxRVHJ*S4y6A&x4Tee(`wV@$YApgoH4#P>s9UOTVwTw zcN@1%DL*Uj0hHveN?=dnGL|_u9#M0vXr59Fb~Q3~2)TWydEa@r@L3F_a#thsl2rH^gV3w6^(RMyY9PIkbmIgON3`D z6-a=HPAmv!*0~pyBcZXe915ApBV10!&rCaYJ5R<~7>rFputn^8;0TVT{VDF0=Y(|c zPuYcZ^m9DOYfB{+MZa!N9ZqsWMuq*5alj&~_NkOE6z(`ML#Lud}{LtC2 zZzgDY`A%EO+FSyQ6VXS;+YZBv{?d(`yvD*+{}t;OW5>TX;-i3ySDn$P8j zt~{zGxg4&54D#Gy5VlnY957O1C>=7FwqZaFbj=XI+gLjmEbn(>yvP&#s0LxSEQ2nx zn3f-#*n>wb;ZJ`aB?HyDKdZ;b4si0O5G3ZXvU!;jTpQ!f6vv}KoRu%TU41paW4tB( zW^?>Jzo47oIjB6X@p66AGjW6DpiLv%!#TDJY`hjvASB?AbLdv-&E{{+4gdBeGv#5) zy<;`sq3R#-tVzS6ppZGIkyQu(lJq%GfJzUj9y|VXi*DQs;qg6J-rHkSH(`%spb0}6*r50=)dB|NSSdB7jiMK#Nc>Y2LD9S z+|ftn%hR6uc`#)Ja0hNFilaW<*iW~SNXcnAbbww`g9ePZ29LJItMdwctlguQN# zyGO)2;zWy7%vV_CmxZRpSa{h3hLj zM_k7XgToAzwEQJtk(+C7IixR zHkFAqS@-*Gc-5}g+HU7OndHk8p%c{*j#6hQ3^}wH+wW_Y=f!@2?*jc(7f=e^f151bq8HoQ00?) zXQ(i9bS^tlU!OnTrnk*Li)1$ka^rr$Uzb+Y2*w0}bQ2s(HRWn>c2h79h0Ygv_p03b z2^UiAZG{Omx=LHTcRQ|6uWh*)@Q^VR#n|S7o+5*d4OFT!ci5HMtDmMmXFnL$N(B-i z#!tDJd`gPJZhV)+tJ>yrQ%EtJC=He)?Q= zTH32kcl)G#Ut8-6G3Z_g+G@0Wve{-q6x&>9hO%$M4)>+7s0FT`uq^^=lNtA(BVWza zVGN>KX@C553S-BAtFlIRNmpPmM3nF8@TRnW7%Nlc#6)Ylt1#?m?i%|Lo1@W~FF6;InNmJFS zkI#bWy;t&6UwOXSN&hnYA*t5O(FQ(}f@zbV1rU(F)CIAqp_vIBg2;u$)htnsHHOnf zp-P#nf&QDW$3NtIg}5yBy};seE2B%fea--_9RZM$KfcDRsXZ4$`by-V!}czad(ox7 zR+yk1#ZtKJ{hG$`ql6I7+S363qWhd7{!3`P^PEm^6~n}BUBl^e{u?T`qx^IcHzCnu z>@$a_Xf%irXV1s>3%5EQ28gtbS3j$LHNZbk1lA@cHp`QM;13;+%QWlchoW)9HUZw? zlxB-KN`>CysH8wE6b}-3gQz%s4|Eq#^k?X03zsB1)-3f@ykNuWV`G~9!fdAZj;U{I z%5RQ(7>%*wZ7o-Hg}GYKN`pJ4;H>M^uB7xS#{{X7}BE24_Sc;BtZR;MdhW_&nhy6+1hY^_$Sea5845+HXv zuA+zSTvVqqFK-c)l%=?O0j>OVYkRnGlA~65NkW%8B z*TbYMkXB*)>DT#V{R3yB9=aKnP`{B*pEd|Y&IGlJNb+XkBlhxNz}E8Ew5(H4$lQ=q zl4fNi9r8TI zXAa`;TXsrz1;f-HY zG5#3mWEF;9z%!bqWWQ0#QoH)##-@Ynhf2@q2gg@lo>#Z`i23A{E@LhlAC?qpIj>g- z8!PWNXZBtbjV$kIgr&t*hBMS{+b`Jr=azzk%#vw7l99dR35qF1n?c<2fl-WS(QfzT zOt&SkoEr}{8Wrv|A%8jOzZNeWE&f^>Z2a77HgxDuHxwzZ(Uzn?VdcrA2p`jzr0_nTf- ze$&dt1*K<|m0$7++RZ)6vS?CFrEWLBvv)LP!l!3yUNdUSdgmyiCLWSR6I3p`;q_>E zWp0KN>kJ>sPHwhunQ%5`+>%WpUw>R;VoBlFftK5~i^xh_08N;oIW+5Pj%V*N)!Pe- zB>KRzi~OTGVo7Ig$b{gbzdYm`Dr;`Fms4{5FoU9TOL(FMTqvz;5owzTj;FNkUZh`r z#zNb4-{C8rI#}?s-{<6Rjrn*uR3V-9$&g+m2E1%7EPEM!2c=;$k5`ZD1-YE$1}VSl zbtW;7JTR2kwOzLmmaP*NJr=PKX&ADYnQD?F+;D2Nz*2`L+?-N=Qhl#`Wnr^Hve$<@ z!1i%hqxP%KV9vXIdK+{|*7m$hv`1s&OO>3BRU7=PMnwM2#z3#u00$n+jh(sz)HM>% z#BNUU`}VbzmjAazFYW$lRr5tePQ*e(mc|;2$=l5z($DA9?PARkF>IYu?Q6K%`>VR>Gy|z- zlN-4NV<$2i=8|kl3eBloCaF4ntpDT5DFGP@hfR!axMW!Nk011E2bq5Ms{3{_JHjN? z%q>d*{XD6r*#o7;E9g;$Yql=Lg7USvjfNq`u^}sG*yJ@8Fu5VBsBt!BG9*RqGkWqc zI({i8M3MR=DCKQ_L`83Fbv<1~ZD-)Dv(R;KkMif45{`JSTIC%$1%7GZ^NS^m1Dt_G zr&#>-JgW}g+OU>e=jrQhKlN}y`lrzZce-+E;>ZXhNEK_FSNr;XkB#Q$L7i%9T)Bb! z1|D_m+7oZ*F#A4}(6y?e+UEYNu#;wDzrVIErN5_-Tz1xV?x6zHd7&p#OZf)&5DB_dp2tOGx}8G#F?U77;bt=9mSB5NF8 z>d^|Y3;XozhxzfS+6*kRAan9Y(Cwt9P)_kLlYli(jZkh+Yd9$4y z__=bebb9Md(wF6%Cj}n(^tb3RHAFK+sj{c>^d1k}Ym*B%^q`ExB>$FdT|6T`Y7;0! zj3{Ns3I@*49gkCUzWNd$Jr5m6-MMHF;}L$~TA13@YI^7BJBPs*Wa8bfjg|GteD~EL zvXg-dQb3d}A0ocEW?9Qyuw9v-WG4z4@mZO}<9lVM^m zR|9^R_u~Z`eK&o**8avFeSZ8z8br~%^x>RWfuHDD_t?4TX>MQzP4SlHj~R^Mda^M> za?>UMp%AXErE`3yX+dOtL3B9$NY%uq?kYshebt9HW@~C#e&ChxXo=N@HT!Hk@o2GsgAxw!a-BNanzy z=V>7q^3tlW3fc-@ia$k-Uh+hjBKL91NeUc%85461Y3uiYs;d;~>%QZ-b^qUgCtto+ z5_T*H{?73~hnYnMNmpW zf`IgqP70xg9vDFgJyMd;kzNyefKcY--RHc&ea_l@t+V#K|JctTNmf>p=U(^oh`r2Ocz=Z-XX!Y~Kv`A;!PwQ=`UCb|s#Ait#8m#W`!RW* z^5jtZIJ4Dn$MM~^_x@zfg9ylEb-6KbbVd}PdGt8$oUrfcX;w7x6~|T&a~U5AT+nF7 zVVFld$AxM3Sg)i}+`2{c?K#N@B7DFt{m>#j5|COyvR<%9)@c#*VrB-(ArzEVp2gJ{ zl%)+hEY5B3Vv^^yd858qa}-?->)_736ef62DSTnaqbMx(w0~Bel(8MOzf!}1(Vy3E ze)Dcr&Ks_<81DsZXVdKO&!ViC-Z7lqjc-ZaCK~w+-9yu(J(T7ZZhOI7ZPqQk(l@*6 zXeOy+(01B3CMlGYV-SzXxpki%k{->6Y=L4!zE%mBb#qjL;>nFdNicQ&c|*3iOvF38 zbJ_i5WK?GMir9blP2ad~G^Nz>ou@XzgCUx!-q2`2VZ2>$)aW${&sCoB)YswS&bqOY4zd zr2>JSLB(43WmP-c>&x9}nXYqwzK;en;ss}?oFbqNvH!7K=+F20jvj4tP>K^L8tv$W z#)+cT(gUZ^)Z7{A@(hN&YoBAznbOFKeYtrbbCj{Tf*P+Id6FB;R&j?~&q*4ErEKcM z#W_boMBmzaUeV7)o;(piS?i!qXQLv%y9cloDv?5p&pFeFEkOvn*waWR;na5R&LXG& zN_9|IAk?r?w|`(SC(!B3>xG z7nM9vlV0JOQSk_!O(yWK5ke-Az(FfixC(Iqx&0s1VtKJ3v0WX|h~kGw$^Lf?`cqtl z6Pte;e$u_ZXN%0I= z(PSd8FBSPkb9*5?5@M*n9-N>id(pwVzU%ne7So1m-Db-~zQnw5b1t0<_>3cuM94f4 zmUxL;!o=r}^e&#qGjEP3SD#)d+}a2e`HZPLv&&|rdWQ+c<15LpU)lP!f9Hxk=-bZz( zH6fn!Dd2!;n+=_Tnl)A}%E_cYakR$V!@{eA;`5PJWSov@61yTBK7i6)6XnECd3#AM zfu&ldt&Ip#=a~Z>gj9;qK%DqGBM(b@HtVp#kO$MTyO&%HqUHP6mu|0L(y1V#7f^ z+Rfh66HKA5$L?dr14IS0w8{?Q4Jb<7NpJ&@RoO_Ibs6G4Rch|=ISj1v8Ll#;K#F#B zq>vG1N&29u9i8v}!#OX3X;Rz{zuR|Lh&+*0jklPKHLC z*2#{26HSf6Xj*`q-!S}}RIpu-B+~HM4XU2+*eXV^e@(Nu1%WIAXGne&da3xcB!12k z1l=dEPl(0cH1k0pTxo;Y)*(J68l=Uis-5P6!XXTF{T&!TB3r_}y~jdBVL*4(Z`tM4 zfTWqSE3ZwjR1l1{$)GHyBMb}81WZIk?j)~JqN(sK55)j(4#WeOJwvXP>t`6P&J5Ce zToi9?sW-R~jBo#%Qk(nsHL3uU$2Ym4zGV%Sm?CQqsYc@WP1H%=J8l6}xiV^`RMBe} z{F6Lgy)qO&jGOSP2oNg}dH8@PCKGZFn#}FR@>VqdAiiBzd>Dbm9Zk@anwA0Ty2D2k z70JL3$!epUhSqH1nw3!WV8Pmu%8A$9ukDjvk)q21dU1dO*%Z^B9q*{b_|$G{lFgAX z52R7u&+)}R-4b88+7JP&5V-o-^LNtzU%g{JhF6n0MXn|gq482S6M0C&Blp(hSi--_ zcpF|HJUlx6Yxv_12~N6kC{@~m2|fF^35ChPvu64XVi-Z9S!kAXarqsxnd7M3@3R+e z;>!W9d8)(^Uti}&(O&U~SkBf3tCn2GvhzW@2H#&lDA_)Ia8!~N$v6gB~yQaSSf}RTZmx=<8~lfJdPVTt=q(fPFjJJ=f1W*(xJy zU3SlQyiN@Z+3~=!cS{rt9r<;Rir70kR2=yuRvO2lFqBUx~DdB=nD2iFn z0ZMuyWnUaTq4ti>D%o7C2UE$6&5>HKnd`TO5r`f?L_G+8HKi;a*K}#Y-36zc=B(K{ zS5;5M%-*n$_?!FkYXgA(w#gKB>GrGI;n|b(sE~4osKgp*E0a*=ldCYgcMSJ(4cJ=x zjfl62K_MIQu4n~^Q4TFcT)qHPo>Vn*`tdBVkSc#8eqkM+{!%->V()=+-CTBhsjshx z7YsX1(F&EH$X*riHAhbe%;z{2x_z`70Y`)?(=jrr{8D@O#@6}Jm|>nU^UC!jY_R<& zhqUrnPlNr&z0<0$9&Au1rQ_*ARnM)W;-+V)zSmz1f}2V!_6h25zAPMg4N@ANdYt+d zm*LbaH=P0qOmB}me4NyiMpWEX_bEtJdXYLKxA~n^`?2Es{IHp_ZfV7uaSk zggv-Z_Q8>C!z=Ye^`XcTCP`@IKs&beGGEoI?G=GC!?+2gEFPUiw60ig-TxPaXg185 zNd3)HtIXqD0oMI0c_01JTK9C_+_wr`KIgl-T5XYa7#}CIKa_Q8$&S9vRUZxYe$)48 z=sb_ZrkH%C0f81KCx}7@(yJ`wMG<6*FQC1d*!v#aEJ(y2bwa!uYop3nnHvR*g5s{&GeGkd)-=TH`{&J38pT55p|X(|Lg=+t-1Jw4sx z`tjyUKUrVnvrb{dzP-@2xj%_6ky_)T{qT>kA;tmKO05V5l~hF2gJO6eKqAenN)4hu zL~tguKpu~KX4dO6nn!DF6`E)g@<~-9)w*Pk!3;3YCYNJGl9oS(S#*MIC-m-+ek>U_ zdDl+j^`7^e**cv#KL7qA7dEOAf#rQ$UlJjB58*I4GC;+rR!N1{wMh9n@hvB*iwP=p z9~c(-&UMe&m0^6J_1TtwDV@(HSeXrI3wiFt^FQky%sSU!H?7KlyNfu2m34+>IvQR^ z^=e8;Z5Df4cD$)>y>%}W-Ni{jdZ^qhdPR{(7V^RnXI9ie(F-M{hg~kui$9Iej%v9Z z%uhE4)G1>a7nbarrHEg*xb(XtYmc8YC+r!Xu? z!${=(xFAWessgUSKU6rIw>oR$r%}@LVL~NW=W3v_vD|0adVst-vHJ)DI_#WGja7b4 z8bCBUH#)TJk?+)V$)pP+R%A9xoMeq)YcC5nzQwFP5N zf}I+c%>>6caB1~3`98wS$h7kP6Pou@MO*N|5*;WxDoeMWFLX;RPjb59-rOEnp@*2F zkx(99B%PlmSxBUl#%VZ`#P5kS;a=I;%ix))Ca!rH>s|zE%@7+cI+kodPAWEYyF57! z4)f^Np}HZTd_BdgqeAAwU|%7a?f8%(4bz6OX><1lFi(2t)}&;nfn|847SbZ(3Nc;y zYRY@6wf_y|EN+G_O~4e`{`nzT`AkGdbaq@n)z6!>i`)r1F0>D{H?9m7fmzuMXKe6E0tA;7f>94~~AOX7wS zoJ@E^eLl#Hn0toWQDe?&Hk_#c!*$^sAT@NSEkEy`g)uhpcdkGFy%PP;73u%p^M6%q z_P=*luB+G1D#u6t&5{wNKlxE&zD{-P-)v!NZ?~`URxHqCAO-Rlo_f3<)EUT|p5|pG zyWR@Dt@{N}WPnaDK_GQTj%=*SYTqyCJaea^Sl(+%0MNrsKCto+dJBiJ(f|%^Gq3Q^ zbx=*|_-M5(7JAX|r+WN!StVHtoOL3>Y?A{S5df9$*%c67Mbt{dr6U8A()eL0h&{!Ip$!og8Ga`>o6diwDYd9j_U zfs>~Lj0ip2e(sNSi#ktPi}vAC(G8HlL(f$Z(X#ysms|9z?gE zC+^mIeaGZ7ZkLgB-3dC_#*WNpN80wjv&rS*=K1 zhbjM}4Be{k`}n3dM5Cp+aH$Nh@s9| zzTxNiv+>;}nAATqe9q?Cu+VZl=rkG6%<4<4($~)~s>HNJxcWL56sB+zj0vaONSL?9 zN{UZS6woOeT;i6)1Aej&x*kIO_?24tvD5vxq!>jtT(R{VYG5zbA3Voz!_pRF-XW`F z@JPQtYd$Z4mEI=T&;K6)!~f(CJI`oVWInP=2rNx%I~W zuF=q!<@1_DERlp$+zH2)7sQIc|5x0H4q=xhl|q}YQXYim5HGLJSM6wv)YLkCe$i`T z8(n;e^)%V^&xYgl`)6-ziV|$6-Mi-t2=SRw`jHPNJt&XITGVa2HFMjE=H?-)-rS}W zzvaSa1H-A2?Ati^OGJ}a$*BEugubQ+?5nk(n&0Gc_j}Sz&USImRf~>yE5^t8a9(K< zq(xY3=srmmzLi{^2V3EbWUM-whGD<6=i&ZnO0wj=fWPlC6bHp^nQkcM7e% zl3Z+-IRpLRLecLCignNQ#7f9Y=>8S%tIqqzO&Hwiov4;2t;3oX3!QgEua3g~6?>}5 ziy9vnYxvAlz#o#O+?{Y+z2}yLbc344;QHQBpj9L3GY4z1H{^{qr@lH50-#IA;Pf3^ z!S@_TDzYCH57u)cKCOD~sP^3i;9JaG3#9Hm@0v`d;*R$=3byqFvPWy`HC9S|p1PzQ zB^oqle}+@uf8EB}WJMSF!U@Pjm0u$4;^QXQ%X|G`OQGg%WS+BZVFKA#DtbM!IZyM} zNtNM#u{6Y(iGX2nN&2qUjd9YxbX3`rvpmvYja&M*oP}rbfVb{w#%tFqDZzrX%*WHx z^G`$Mz-5lc{md{1b|caGOdMSi)|>FTNk{NvD#e?>3EBd;mHi0xq`3G@ zWB`2@f5TO{*lp>)l0YS;ol1vUTW=gh?oM+}6)iH-41eaj{eQ}Z=l{?|{XZEO{tvzN zUni`qH$zx|=ObAkyY>zFM?{Ds*9`LhfKOhs6|*owTS8T=W3gk&+h_wU?-m4u(Trt> z7F3x%LS*kk&UiC>ycUw|>|k=k2OdwNv)DU~3yjM{PgHnVWW9jw2p!sHr!Yek&gfnQ zkow_fS9Pu<1e-v!JiQgx@SR>6nJtq2MmYPLs$K$&Hl0QZ;8r)`P3#&^d**MN)+)Kz z*RF1UH%??lTzaw{ng1fbE7g7irZ{}$xHS?Plls(KyQl5v4O-hPM085fb?@m8?y#U~ z;7qDz?|yyBBp(p}PI0q|`~gjl6Y=YVwZ-E7#QpL5hU)w?@$oqXA4^OteKN1UiP>}r z+L!Z{Laoh^pzeKB6t8P!qYqdu6A62LRLtsu!FDdw3be#n$WxD?YEyKtbo#z2Ma1Fc zdcMF(tU{B7y41Or^=B3*E42~c;Bm4rJ=6}56;#?+sGi&A>zSiCFD;>d#Z>4y!Pc~` zc_V}{?-7nKHcD%wOyM4ZiO}D-g95Y-`R`Z)J~r0W3C`%ni9Jsf_wqpoN7<^UCNZ`7 znD)vnAM-pLM;$Zwy``gydlFL0IetV$$(HuC*d_lL>KV?g+Q~qz^NgZ>z7nE}=sWnx zc*}T#Dmvg+)e)UltaP{tG!Y`DIAEkteg#@S=zzmiNzd65#7iu%*xQwS0 zUVVGE%(y<`fjOb2Ha~j5>I!8i7kJ6i<-c!u6uRAZMV6jPr7yyzV@Iw1GAAnZ^v)tP z2V)PmLZ?I1>i3`sX@J8R+zrk*~ z+~lFU=2^db5q_t%XGY`{dA78E4auryk%DS`6nfsSRX8Df9>KWjuA31K-dCyzKNuW) z1NbXA5kQ2CGk_$5orv4W*?8wvmz1}n5m2xu6bq29IuJ+jT2y8AG$ko!ec^UPngAri za#kc75JEH7QA~ZwC4R|j-|O+m^vB?)Z4&&H`|Hii#-s|OTt=x9lLT?&xd*rRVq3*$ zh$7Qk5`FaGv|JqchAMk|2`(Pk$RDAua2CM&llAACL|sIO=r;$m!Thy>Bt(d2GvIDL zI>tQySmy68%_&DxRu$@V!B_VGEQs>$CAN*eNBg zHo>Sg6_U4Z9kTnCQ0^7|sovM~`ipC6o58}F%H!q8VJ(1f1E1D(|oL*GAdv=QGqVBqx{f~ z$+zX_jdF|J{X^c96>4(fY{$pvZ+~7tBQhf1 zRYv3!Ss9*Y9qv^?k=dA90@g5cpfUqKL3ZJR*=F0^&+l^I+G^YVb{f5t*?h8fTC02a zSo$=at$JoKdk`3PT1q-cuqeaH*=K0h#UIe?%k;RyhX&^nE`%S&Nj(E8y4U?llwytQ_q|U&^Z*{}Lcg--h`7}7*iQB>Gbev%}N9JBXzqonj z2E|(SO2AURhxYhQS=&2XfEz3#Uz(FaWa0P0s!g;l);wED08tf89ZM@%Hh4urMu12C zIT7q@cRD5?Z>U6M)T*syy%p-Yx5pmnDLJ}FuvBELPB^byzS)Vo@Yn0X>VQ5a9<}Nl zj4G9uVH|Hav0#p(Z)F88XAeb0b{sySU!@6r4M1kQ1{9~2v496I2fi{nyNL@7eXWM5 ztFVCyZ-HLXXrj87t=vc7rghs0kLeJT=$=nehO8l*JQ{z-OxXT(+pD2pSLy@upLtJ= z9ZVGLFbx-=aA-`pLFhK#%Hv92!eKslZb08RSG4`)ZDHr!0~poWQ&V6HylmzEG^$Bb9b}12!t3 zrhx{B{S>(y0AaG$HclrnbRo0UxYd9*eKmjq6upoOd+4fvGNh^QMAX@8G31E!9az}s zcRD6=W)jv5eP~h{G}tT7cI*1``M9i;{gv~*>C`FzC-+T*AS~?m;}7L|Zdtn#?u3j4 z;%dTr9!meDLB3|a^?if}D{4fw{+;tUC8i zTU9u=Wfk3MNfokvY*pNNzI{^tG8C8Z$OUBN1M8iun-0u;jo8R^lV6FutaEgH{SYu* zRkNR^&F{fpr3HJ<%{t{*-K00wkD3umD(Cjp1|IW$YPawG*171O50o;o&h=RY7KZ;; zhr{Lax-*d)HYDM8KT2^t5)Oc@1qAHSO}fM7SLVu}bN$Q(^p*%dRp|Eik4)H&ioQMm z8)-&2ZdnuYMKys84~)#Oucz;YtkB<%F~*b9j4F(iAdiHLk*W;NcBm!l4`X8m%TS9* z9=pgtv=3u7CSeao4s`zh@**rrsVvmsLPYx)_|-^qB0dc(T0*Q*d@%2oh#0EyGw)6U znTwQD#;~l+5x=)}$d~AnxZ4k;qzbt%Nd33I$QrFdgkm_R`Kjh+c>akMrOdDKXaP! z12zEQJQ<*E%?%EB$-scNtHNZ_AySZdb1LO4AbG(-AMW6nZN zLQbtgp`dE4M)nhq>f+0hZP|Ag;lWa5W*4nH_>Oc`%z_@B74$N9D(DsE7mAqk?dYO8 zxtts+O!rdFgdyT$Z7j-ehwH+To=bHBD zKAB+j(fbub7&Mj@dRFEo5pcSFyf=h8*dwp>{omVmRBGEbfG9%xIlz6d0e!63ol^aFDYxw4 z`ZhLX#-CE4MfmPGVRcIRw6z!MoD&$)D}D6p40!a{bD= zy8m$q9h}mpoq{``m96RcI@TNaAMVW>>5HXQc6!8IPPf{T+To?ZSOgx9r2pxd!N&32 z-b$hH#!50J{VySRKv|p7fv@wL@3(WYZ?{a{Jt!eb;l8SJWv9B=iJDZ1B`IkcZ5;^Y7HuuuzHfJ8B!40c`cX%H)l*Z@z z#Dt>)ZQv>pva)xW`6|`QP+VPI&l(hYpgdw$!5^s#^FK{|Anm|xkvYYOWIp4ue=(zb zi8ZYWVaxZQ3pf(NzL6zq>6G_t3W-_7`H7TzoN@mo3PKv%R2B z|2@aRfh>X#9N%mlUyT)7(=ve+;DxqVfSTreK*x<_h&~VnwNRieL&@&k#IQz?5GKBbEh_U< zSWV)Q6V4$@Sc#K9dGuwg||swa5WS&s3a^rh*GGH~nhB`^wF5 zK1`>llx=$9XR9zeY3J}Ili!~Fz~=?K-duIo6Qk*C`7&@0J3OFMp_ta=sUg%Ta&R=U z!Gbpq7<6|j#0mOo^E#CImpvRfv$GyJs-0i+sh!^OKjbNjtTx-}YahYRTA{z^r0*RM zG1p6*20LJ@ zC~!~PWJ2a3yXee#;yi}_YK)n_Si7m0j)0)m_`dp6;?#^Fy?&iZHi=9ty?slz%+Gjz zz#y8mUl=R*(i0XwD>K?WK%!0i43sM$l??Zx)s=+t0jU__f4Ketf(RQ>dx3;#GYXuv z*!*H_keGMTxCdbQ#eWE!uk>lqTrdX27j4ceS@+p!4zQlSJE6f%%gHc$iPU$IIWx3Q zpJ%9;3riqyXPYh$h}N3TA}iVhRMv@t%odnkeu3Wxf_ZL)8_WM z2jNcI;gi&ySq=(J-fBYC$<49QaU`InA`IX>qwsC0%MwkEOf3qGz}D?A9b}TnvM+LG^W#C!6lJcpRu~$rTpP$$p>9 zR!aP;-Cb$d_#+GFoun6fNYXMm1X>5rnYm2pmN)x8)##K4)&IlgkyPi_WP-6z@|0O; zC)VF4I-IzXUD zbrTK(0ru$S!H2BOu~1JcK1eif>g=NiBfa}kjQ7B+SHXanWKh^|Rg75QAANbyUs(pp zuDDPI`_=fI&o296+M^LB#;dKRbWo;yo!pAl#RlBU{rS17ORYFWx-L)&`d(z!It81# zx&rLkINX1F#l{Lf)O@%$FykBX>q30?RMs9r-&Rh^V{ZimWCloJZ<%fV6*;KwGRkgc zys6D#iM|uo_R_jJ7AKm_>z;0mAsck<%mFcrAaiTzJ0p%jgY8RlR}H_1-+Vo~ac0{+ zj`~DuO}`UdwbekY60e(FQ#9z#q7}#^f$F|j@^?hpSBpMc1p!7JwiojjD;LvQGsW=b z<$Ag)0Vb~Q^ObuXXVr*Zv|`t08$@{k7kAFdAmsAE>t{-SEl<@ya?#;3Xkr&rW;^=u_qgCKT+ z%**oLh(V{8W8adQeumB%TX*8*x=WH=(f3j7VqaPOFzjKn>iFb~z({({1VdDEPhI68 zk}+uOr?#1!bqZmtA54mO^0h5M17*Y`e65)$sRy@O{6p4Qp^dk80`K=ovL-!Sub!dw zU0QSwNxkF(jtwTloNwgd^Keug_{8ko?NtVixs$xX#Ic=awX zy}r?(Y6w6>B{!Y0y;z5q&{BBB`yyP081PY`klHOmu}7zcfwX_JtzgIf1J~{t?n(^p}LsG7tU2HqJeov>19l=vnM9L}_)C%^f8}D)MtVY)^Is($p-kADyiU4y6s~5Sh=%SOnj#BFOHRUi9^*th3Pcy0MfcCw3h97 z?3W5imlxIZOu1phB<#}a3#zjobL}qt2_0)seyG1A)Ka=xKI-&8_D;St>-tDV2XWHd zWwX0)!w%U=9Cxp=a2(f{ebrtxOyOA{FJ}?lK?=!qh%hFxeuboc2l0A902sb>RQ629 zJf?D?Dt=tdmz08!8`;2$yf0f({fFzK_2Oxj31ZO1qB9sbT>I%4fQ>CS)ObIwdzI>t z1BB(<3LeNrkWK&dBK`N?xppGv7NI*<7Ih38XoyH>WlOWl8N%QfBjo$#+7H%pmBbu3 z@j4`$eNioDI!($@)uh7c6EWHNX2q~^!#yb@57dCafJ=5dv9~O4dbQ=emg9}4CQ-BI z@x8Rl@A3z?Y)x*T)=L~50Ii^F1tTuK%$5;9`-f|EE&prjSqaB#_8+b?-5dF=?9+_% z&s{oS*#4|nV+_)#;#&=Kq&mtCMKmuD(LP`^-*RGQ48lOdx zQa@>g$~yUCLZiO>m(E+Bk3^w4Z4&$U<(l199T_MRp!jY!^t{;etgaWb7WDHhqV10) zy!0ghdSY0;qmHiutFqj%L7_;K_Jaqxpe_il4H7=->P-*MlQ9yE-J&2>)3Y-(A&)X&~BhJ*Od58XNARzA`Fp1)dOr;{9*{DPGXX9ZN+hdk<%dFp97 zp^|=SP1Z>6x+9}?eEh^p<+m}gz|9eF9f#m=Tw>MvI{zLb%p-W#Xd6kSDvw?J^QHI2 z_jW3$lI_v48X79UM*b0y1X}aN6J1eODI()Tf*&Cm)o-QRg|F-bm+E}-4fhMKx61-C z1GKIBQgy95i?6?R{IrHlil`w&@1R0^<1X-048I;27)eeiFR`D?6XN5z_&f1Ky-Fh&o~s{hT~6-}(o7`5PpE_X2D0z5KZ-tT$jjc}xZSX@ zcR~SeELT@AE2O+Q)?mC5JR1CbVLMflE^6G8V<-ahLcyhiwi8j9T$>*Qu5zQ;GvTzj zr6>IrW-90K>hF1Y5AW(vELS>U!)9Rlst0J(Q!OmppS7b_{wn1g0Pnp&?e>|%9*M9qa_Uz`u*N&Ji*lV31dAM}(G zt!Y(P`852-3fh>x6k*V*o%*$*zE5S^zklgkiYM?lodH{K)gnjvs^Wvlyu>NTleRaC zbH&7rq-t^>Qt^w3%2Z8Z4qDMx_#ox1J7LO=?TzzHUI%4ltR@@#*_qm~>!Pl1&WnDQTe?8-7xb`?8 zAVJhg*k@WJ**`cu2kdoY@m`p@y;#664rMFb@oe6jH2?Pr-@eC5{rqJ)y?m=jdc|lr zyj)5PnY+BdWJX*H2%~`}y>~qvG<5&}lxQ6!R-}i>T7nn5RKXj^*<#QiF#9FU znh#_~K<=oWz)Pr-*}zwtwsh^1SBlNx7s zGGaTNf&Kbgmo5m~i=xQC_flmbaT4)Ae|k@=LirZjz2_XhcYMGO*mSFz%?aif@!P^1 zv} zl;Ego?NE(8)(nAE^Y4TP3vx!zKXePXO}6(+YL)KKcb-+~Xzb9MoJ5G)g(l-l$63dw zP^iiPy!NV#Q&K1GYY!~IPzIZ~VO5gG-(5y!q?ETy|D4c^e?{8I-X7KU)B@ru)>WBQ z%$n-mEN*k7d-n#4Nmr^h6$pzSe)dx=Lm72mb4deE*2#PMYO!Tvo57j$!qJ3m`h8*- zNhp$Nx}4irqTz$e8v&9wj3~@A+4ebki_d?U{?sgT6Zx=`{AIxce>E9WT_1OqV0j_qc1^6u5`nQA{%M}jbkd7ubPaD?Ru69+ zx049y$<)l()jvHvuj9r|-0q$9l%7j_AJ|DZx@A6}%F3D=aVWPiNoUo!407mxM4y=f zAr)1tzgG$g(e>|&>z((6e2j+8jD^a^7XnrEvCgMFY2O-m+7FCudW7N>B?~=40|F9;V;#&7|{7b}F^lAkmFN9fCtql2o$Rlh#E_W{Ib!O13lE}Jm+51o@ zXV|zq2T!>95l%M~8q zb)%a>0-IYA$GqWgu6;t{GCdtr6@He4FFh(HE3Md}(v?V0zgCnqKMy@}xh1QQAmvaq zBpM}*KZv}yAtZUbn-C!-$0(H_K20L!mynyk8jkl)p;8v9TSz@TDy6%8;=oV>R+82w3tez zwzfB@agcZ`BcDfR_HJck#d@LIo6bOUhhYpWp*U`qojE$~;<~mh?fh9v=++ArK(I(F zl7`8%|C(oqBXd$O!YTKR!Uf050Xd`4bF-lqCbDHL^zw*ywkmo|@n#Kmb2*2;B;MtH z+cdz0>E)f=)Cs3aym7M`qp8ElfUHqOqn@6ENF^s3aUKCX<7w1}4xSz{ry$B~vys8i z2YK8q|M0-h5khCWc&lLR8Q+0yb~z5ChzA*Lh(h7 z0C89T4LV99{?^2Ml#9@)9)d#+ckW`k+rC+F{1lv&vi9vh7E%tF_t#@KvNeePeIVe2)$y$xBz9df;EZq`!<1o)H1 zwEiHMoGH}9PqS?!)4tp$Yg!dI=$1Ql#{{ycy0=B0(7TvPt*65^5~Z=2W)c&rE^eJ? zP#`Yznf_a_NM(hKVO$a%*aoYU8oh(kGgNSrlD1=n7GN841=C&0{(NLKk;hRCpyklm_SXDsMd=4W z>w)Ea3ck1sFbFQx1NiNR*1Etj*(O+MiSO%HNn z#Ja8`^87QkAn@As+j+59RQNgZYVQY&8FkRds*7tH_jFVML;2RARG{}tNmjBsp9mwX zPG8p9J$&ECMe$G}eWP&`qJ7)BsLB}S2Ysj7Oq`Ow-y$u5{J0dyu`ZcLKhS?}X9?qh z4(_FHpJ~#3_aR-xk=%fz&9rmO9MWDu%&x=rCF|wOfe!>g0r>I zem7KrLX$4#q-$NPcGre<4FWbsA1pKG+y@b%r{<6N88ZM>nU664~ z7wycAO=G2wFu~t0$Uyfa) z`Q3Jr&Z0A%=k2R0s8A?EP62%=!728WeL)UA@(Hch^DxZU{Fgrb7XWBxb;-Gkv1FN! zd0D>dmz^3NKPO2zF-EAKt2*2;d}5K6I-loI>B)}g)E%moj=!^_?y^h&@FV>;a| zCy|%6x8WR_%rWZc&0RB+3oJNuJ#Et}#b82jdxNe2US)Ry%&27{vN|`4tnSlxoTQ_F z@;0c--GZu5iHjqbter@vRkOZCdox^J%23_jN*}V%bZsUiC-CK~H;MI6}yFxSo11R`bkz+9^FBG5a%&^e8F^|0zaRo~B4 z@M)90y-yoMqH;yU&qE0vq2@kXO#H)M#6J15u)U6Yg+AQIC@XR2Ihd~z1#ez2kcLKg zy<$F}HFM$)%D6J!y;~RN!1r|+A=|JLveWub$!sVQ{4|tO=f=()DfPOkD;Rubl&+-D zde9S6?J5AHJxSo(tZB@*k4aZfGv_atXs*r8w_U&E1X?9k6l}~I%{?2!cBGeA?r+_# zCp&3X{f;?NYpT&#y0>X$H$E$ZLRlEd$FA|U)qI(-H?=_G*JxX9CqdME!Rt5CB!1XG zT#Z{_^6w2oiNmKAPLEg9tKiEWRSPn{e3Ok@YFg>PjPCS7?~cQaN3^|Yn8BlsLbs@E zD7#K;#E?K=w|{BDw8C(m7UZ#Bq>0(!;%Cx5Jk%!AImQUBHWp_u3TcV&rfwHi%*Dq^ zl&B6BPOS?G;jw4I3khTbQg!n)nnPT@7H^;Q5(IU|Mr`C zP29wRiSm5Xg0mBki`(k09!*h}j?N-{XFV^rZ6w$5b~4LnaQ%#b&3Ztrd}polX?K5C z_!vL{DO-WF@}_rQh2+mm<`{`E^`H_%45neO1-EK~80%o2Fu#S8-5tpO$T8odU!92j zh>Z;g8LZ|d2gY`M=-oe~0>k6s8Sn~uVU9V&XFEn|a3lhiIXclHxhG5Y}Rx0D6Qgin}&ArxI)+;HkJkdjU??dl7lRDbO)i@CocN_5?Ztj=OZ8p@cH-Y=N+^u>UzWo+8;qnjMdunp-#HCXV&mu{0m zt(#MKE~h+N*`K~3JuFtrzB|&jA>faz_PzxNV9hE3TM)P`Zd>-tg_OEqZ2?W7QFxs` zdlve!f?ax5SgD~2uYNMan%~siu^F6lsi$x1D@%=BmyT)U>F-ftm;XdF&I64roWH()T zjaujB;yphr=b7H@7H%~AQ-79}KFV&9fmV_KxkX+?{yru))o51vXuC}?M(T@9>z<@$ zO=1JW*0;7ruGM>HA)C*rd+c3VBiLO|3{c{-D`dG-Rn%aj_Di+xVhS_<#rN6|rZp?a$j1dB&tUE)W1m2p9AA7U%|Mq*L!I@j~>2g za=dh1{n~<3O|{k9phc1~QH*V>Wj7{Wnd17{FZ`j!{k%?nl=-bL@lyB&g<$uRdMHU_ zbv@HVN1qdDIV#62bN*nR0t)7 z9wiQTj+~q%HUg4tUBbQ6TfRZMZ1j?(b-oTdKdG+jT~@hc$z1Wym08Pw61s!_+pSvD zUDt}dt_c(dS+xcD=wJE0$HH3QzrVZaK50FkHdcvUFSW{=ftEIv_#wzXnel;4*Q%cr z^iy5ET605qMdCC)ae0o?dMON}7F}MB!CBCq*wJa_!`ewZdgulw75wdfC&X6D$mfK( zIG?pbmZ8407sJF&a51nE5Mke`%A&_?LTk-3!$yO4vVIu ze0Z8mHDS8CaaF66HT8X`0Xj|*bFol+h8f>gj2h(dPXoEzeoPQfiQQ@>yMd= z7WXcHSO=91*X9*k#yLn|3knLFCgaThFXrAms;RVJ`)3|!97jb5ks|dGM5GT$2%(Nj z5fBhaLJ!g-t=(#SN=Naxm_v`?Rm4eXtu=p8v^-Xgqb9dg(W}24l+(_hk1x9*0(;g6;2IdXT;4 z;p-(8c^4AWJMonO6$m8Ytd7#<2RI{!E^0@YQdz8d$|(B;qoZNkV-(Q@2N6)-8qgv* zJ%CZR88#bkCa|^0b?e;4?7Fur)mA{?_KGmi5Vt%|@w{k@sen```X*uJ9{(qWrcc-+o{&H@AIVy+0NZzZl$GH=lmK zFh(;|2sb*v#oFUpXH3>i;rTzIBge)vwYw*L0l`o65-TDThUDP|vIWEoWr?ciAN~5_ zuvx9+zE;UOB@=05m_@qRnA@;sa(!GCMBpgx_y7Fj|C`_a58dBFo_1}=*)zH)nY}TG z6|qYftDl^iA741;M_CS!dj(sBUamL#kQ$=B0S$%qw&&XlGX0M7gw7f$lsC|-8Lv~v z1Ptc3!J#8(Z9*TFqM6f12-7pOKH>S5&28rEJN~v)-xB0mp;>AYlrv2w?ZprvzfD=V z;p&1I83nc3{06rRC5dVZCp~lBXt!uU5XMZ?ff#5PJ6z0+*raaUpo)}?<6So$ea|^o zR!u%jzjof_r&n2Og(((1y`zTy`L;qiyYa7%8Pl6*qnq=XFxJ;okb3D)0^ibXkwfMR z>{MjBRK`4g-nwhI^6m)X$qqy5ceYr`fSFFdvv3ZE(6%fpM zmgy&8nr;YVTPlns;S#bDrN8XINB$rsP;*pUJ)pF?X^s&Yq1?v0L9^4+!rM^Pirq$- z?8fH1yHl#GCt@SHz~`;maj}BIBJ(4Ht6gK$E7Ih;pHMvNNbnNk(X!FN+ztz}(;wAu+&}5^ zvr`yOCE~&@?E#jF$@xrU@l8@Y2HNcwgidp3mJAQ$!(KCTrT{fgfImMqq`LYn+Rw{h z=y5rDlV(ntxMxCe=-?zmNnH++i9F?bo{Mxg9M>Zp3Xmg#0H zam#>*G;n7II<0?ceKxt>ZX(oY;s+Yx=g?#TzlIz(D97Gwo;mhPN-y)YUO}=n6{uVZ zTOxWZ@8&y4iK7uVxfO5#@21|@Q=p6s58CFRd0GFxoyETtLeBN$e{UoIpPubswTWHi z@K>!3H(3c9m(UZlEsav)@}~DI%(0{qHGIyv6g#H<#y)QjnHKK?Bt8W z{EW^-pyr!n>zAxe@N8JxXg>T56IA2TQtl1>7OJ8ik+N`CCjQezw_yTa0@*`o6`UN) zDqmwZ@3ilwiv(j+hA8K z&>kfT?d%0VjKD=)J6Q~jSi!M8Cg|Y75 zGW@LJWpC?33W*bx0wh^jggO0AF{*E%W3V)eqt!hlH7t|ZVZUm-r|_qhI!6RP_`+#5 z-2|`us!nd!pHAWZGd9vE9fptUjb{wu$L9_bIrb(4oRY3z!A{l+M^a<>sBy+s2|cpq z=G^xLs#{cL>ku@mNb`=z3r}4q=tCQL!oZ8VP9pCtd}`D4+a@V1!^*eP{G6t?`YQF` zURH2toTV}h_b=z#nZz1beof>-Zu5?c~co!1m$I4k&K#v?6(+kJD*bl%@C z-WK;Ud(l%rI;!BVb~$1}1@Wppts9Ynb1iL6wxKn7oABBtZy~bR+L5oBMpIEA8fD&Z zfqZk8eAYt(KkA+v`h=z{PI-%|dfkc|iUk6x_@Rk?CFbKaEc8@chr_*9L{|#!PHlBJ z-J83S=_0tCoYy0i>?hN{UEUiZ)=hQm&VqmWXJgW3v6&ij`P@Wm6wuc8wzmRWe4JT^ z?bprkGw-I3aJqKH|n-P;pG#@!hk~ z?_7_fHNJDL4;{{&-u>D(_nqs@(5dIyH2phQ5<9wFcfWJle&?zuedn4N|Ib~V57s!(Pu=C1J@P#9jFZ2R`<;s- zz7w6#5_cQ}p{QH^uv(DRE=DeTv_06WI!_7ZT>ARy|^nBd*xgmGX3 zRLJp*Ai^r~#o)>Ffsxg@>ixWD0s?QkJe5g->JDg!Se+C38t9a5w*1}C?7~b*F)Fm7 zQeWRt0w=3<$5_r(!&!5H>xX}QR4#$`(4RTp+Aa^JLzE^rmF#Let9_>ZGSL*f%Y zRCnWK!NO zq>zMXd)f7IvY~-}s5I;)pvmK1=pOLTf1L6MUWJU#C(7wH;gh+KLNt=hs^C)%*_VIQ z8(kbiO_tF}JRk@}@4h9cqCWrzgBSU9wy%ES;^KMguAB)ST!$GDKI1i+gQO+zgzNn< zap5Ki3P#<75^+%r@B6tP#3{#DVQXHzkTH9Nz2j2lku41$x@?Ibk#1FmEs@ql;;GQG{TsbVQ|v0vD$^#lg9IpJqKlYSPCvJjo(O__mk@(y4EUpS7J#{3tQp#TNc zDPVWn``zEJpEF}<)D*)t`FzZ!bzG)h`W0#xwht~H+W!635LCr>BuC{i1k}BNC|)-V z(R~FY2Yf_B6=t~gDIIO|?|w9N5Ag0ad=YJoN2>g_W9tgol%biAAEP@Fq{luS*`qFYsoD%2BJ1v$udbA$JuHBYB zu9-#j6CsKymCAkE;YjvJa`&a}0nI^u;4$R&VPV*`H8*T@7$ES*pw&Pw1;m;a*tnZ_ zJ+C%Has4-G`whp^G}4jmkx{*zoqgo-h$VdgX?ex|Rv&iD^S74ZPblD?9F%tJFT^44 z`o6<7--vv<`6Y~N$P@?1-+c7xz1t!o-3w7D!7#ivoiZEcOu4WU@ucXnh&sku(2U~+tF znVf8mC$<)vG}Tbt-MmpJ7`M}t6@mL9{hhgSUMrPxnY~j;oq_e(2D8qD$@uuhLvf*o zzIF*Do-HA&mWmm1T%1C_$(oz!>$sR0iO2?de`N=NzZol=KeubGoAQVJwV0&%px9A@ z-8H&fy(y?MrI}GM&;dVuedA89aWABfigK-*nr%7bh4e96n@{sfG{@(OjL@3os%Qc4 z@h6^dht_Yrq6F}Jx`#R#DRieOCCC=ue5KhCIS5ABZHB`Z^w+)H43A7cAUlH8 zk$m2G@ zE_dKq5=H}J-ffEdj74M=E=Ig=hCH*jr`J%Gn$E>mmW?^bJl~gFSnRiTJDFy|Zw7U) zZ>*o5R~fu^<<%ZrE4Zhi%B2vHXmokxbMnJ!_ASTCz-vZ4xbj}fDY8g;>Zk^AL@aNi zsDDLUj>4*V`Gw%6FuNV>)qjBPUPL?b3N6C%b}h|2eHPL4#*aD0#L)&>;|wh9BXW9E zy`E1jZS@99>h<*2!cpBs6Ia}W5!hy_acV-UCCg%DoKn+G{C!8`tWisHda(SDfZ+XJSczH6rfVwz_+ zkW=rwqKEc0fK@?Ga=2hWZ(?GGBeQU1nr`SC6>$uU;;UBclZH)i@rW|2fN#vNa!TZh z*;h%{4yuYp>mYHrbweuvw;5^X>h`{C|Dx=uyHE}ZnhVa{*x6_iq7g5Y3&(&g!sg59 z#ixLfrU#EWGcRZh{$&9!!w82jA^)IsDK31T6eZ5-YSuh&R|X5Cs-uPDE>>XztlO03;y zQhUuES>eFkiP55#cWhJCj>Q%Hh!Vn4;6dkXaH%2S7aDeX@u^0QR*frmq;L)~he)Z` zBjcOR?3trFVnesjYL#m&}&MG>p?&l8F9D$@)PiBd$*p2|ydVS2yV^nnyArcbJF}ijSw27Dz$MIk!gvytP$OgnaZ;&1PJe?aqws17`A!qPUYNFh(Hw_A3$Tgw@XU>0ld z?mMBJH$@9r>85A7ISzj>l=e{w`}PlC^uLc73xbosbH&Pj=laG8)m-iN^C%xpx?=A9 zSEm)kPcdpXYG{1?~B=+>s_`7A$y-^oJGtEeTVj2)S6#oZNOc>EE({3cZEh)6sjuIXllhz)EAYbO+?Uh7Nn-WuuPY_94a%qqsFklh(oM<*1ar6)ON~Sv-e@xUTpKCR z@3pDIMB@Angj6coO&RrLMI0GIfO?5uM;gs3hv_5477Qi6aqt;AO5$GSmSaSfN70>k zi?)CB??@&I5eui6dXtggxe{d!PaikEU+D^|xgi>*kzxLO9UcWm&;^X!=^z}`e zYTI$(MZxx(vf4FSMe2H8qVB=lQsLvCi6-=F;WzyoDZ$ImJA&$IHvzGhY0?^0^oTAw z4VxfJ9*f5{f9Hz(nc~{h283gvmm}+W4g_ohC8}4Nf4OETS+vIrb#2(=j0iWC9yVIl z-P2s}Aash1NZK6=t6o@^Icpr982Zc^WWi3aXHt+1GlvJ4jUe>1sCEIw8 zTev_{?8>j_i7V_mnd4g9%9_@K;yg;0bn@_aKN|{t?!-J4BDgd)*yU&rYqo@)Mwfm% zz24ud^urP4XT4-wO@Tf+6qSc>GLVgvi1^O+TqH!4I3cXQK6jeNa8<~=UMiaO=0n+l z>PVs!+!PlsWArqo+`CEB{3y&LxAYd3Doxz#E_KV>6jsRY@07>9OP@+6i6e1(bc2~I zdZ!McFsJQ+r5jEmTKt-SU%icct2Q26J+Zq%a&6!x4J~S0w6@~UbR)h6mp%;f=mdl? zNvU$;#V$rad*{XH+iJE%@$k}FV$v(qpWwCNbtXXS`HypV@{X9@lh`QnEP?KhCJRQy)vfntZ8$>C*ya|xL zPQjfGajSBj+qe3+N%%jui|59-ZjLV5GGr`A0pY>!Gi*NrX+^S&)(fjund2s}VgZ9q z(UqKWGb{RVbUBW-MmR2M@$?<9y}Y^dX3vBbK-X%~j@FK!a$-Dg)>3ruH%PjBy+y4yWkMC%^8l(L+bO-Nu)D-MTiF0XXg zxHsZ3O;(%FS`8`ub7(x_Nwyr~7d!h@gQ_rN@}ng=DqaY$4w)yRqK6*X-!6Q?pJEj3 zCAFBgoE5TK8ZxvdRr?0{d4VqHbD%{FUxnlntZ=rXWCx~zY4t~+eFZ0h58f7Ech$w^ z^!G{kgy|#9-Ia3nT0)=?i-HAY~~qmlZ%dgLsuFHN)1=F`0QcO zrs(d19l@3)^9I7K?qAu!XPqq+%Wd%5K$!h();H5=ba2SG-Qceu7oCFX(M;|u@0q!P zktd8f4_Dzo`^Fn|w_bOsulpe@E@p??5uA@=D5rGE zz=vaM6?M=zhoKM9*|(TMkY7z!GADtN&<={R$>0q8^UYtErtML{X^>}U@;1O( zyrK?pAAg+fXggc5-!Ql+%*GKJ?=53R9nXNXCb9$CCpGe>CDo@?hmGZMK-2wJwzEy7 zPI0wpZxlgddZT^4c@wuP-|~hDI6Z@^&u$`8Y|6TTuRJg26r@`}_HU3sd!O1h7m`!i z=DrOYXi7?~NaF~z@jP|TSvn&5kZ>2`rIoVQ67#End_sINvj5@L`=nTFz^L`!(JK3Ft4v_0@Z10r!u-AAQ4mgTM+7I zZBWJ-S)8iTR1)YLtyIE72Ki^+DO1Y@-7H9cSQuyhiM!Z5HpVO>fm0W#V5F_?CN=bR=^%ZBk|18c-a$`EK*K zp04X9MSCaoN?Wb97hhI2Q9!}9<5TqtV&drg#wOapJaR56JafysFXmB)H4URUXWV4r@I<>dN;^rQQ)ZvSJGyfT)I=5!=?mb<2>*auZ7B0 z>>KyOJ|PUs-X+2+RJWmfLM4J-^Rn7|?{(3>n!RRj>sz?hx`2hSr^0Rin#xDk=kEIxC3|siu`u?V?5OJu#NM+dgK_&B1VHM6 zZ&OL#RIr{t_|(9OJGNu(Bkrw244?T8^n2bXc(WYt*b5SHf105%j}WaOieu-Bt+ETn zhcahkNhWd6L{L4YSV)-Ed?AWN2{$?hFS6Hv!o2mUHMJDY);96ZgR3X_NvVF^>sW}n zohHX2g_deJmtJg^z+0fw><3t=pspZ<9fQ?!EM31)Kaf`^h6>tw%TW0`BWpA_T5dN{ zn0O;o9_Colrb=|Hme6(wKg=Bg1_)NX*(10GU=>W!x!#o2FuQ$drp=Ok3a(T>)OC7# zfde#OIOclBx_+)%ne zgUM({R3apciW54wU&F%657f$^ep>(wX2VA6R23LMzHlSE?a0{Q#5;@^erl6UgGwj3 zU}IfH75uo@#9xjJiy$RE_w)lbr)u}eL(a1`N`J>u2t8+Cf@G6R?Rl+6Lx`c z94vcw+l}W#NZr$i#fTKB>b&;VN6HZfHK?m!a>TIj99rb0B0nH5M_F?KJArGo^m^2B z6i@GWE>0b|XT|L(`2Cy)qKq=?Uu~)dnNs~Wo-3F-QKO1U4_`0ngZPlw6+v;ra; zcnGtQa5G*Ocdq_DlaN-EAwc*6!@EB%tl=PFcYCdYHzX+og7ZLpDqiJ;M_yY}_O|Qw zW)SRC82Bpj)+y zT2S0yafAA*3W=&n9sP$nXHM57-{$Pwdz=gSqN-EyIF4_WTl!p$B~isDw$4?Ud#o^n zWIs(arb}p&202y!S%}W=)42mDbV){9>0o(Qc&V*pn3d^aMT28OGedDR{V2I2$R!S3 zJ;twTUz1st8(RlD^se~AVW0}z13ak+3n^Qv?XUWa!|Vf}MbUQ;MmH-w9Vw@pqNDuu zG$jsncS`kf18T5qt8y^mZ!JuheG0% zg9Ep>p0YjHVt-a1T|dpN%?wl(4$-io+4NC-bwDG+PqC4zdOK7cbN$(gavKLZVJ}{m zxiM6r{cGRG8(_ue)}N_%JP=aG3w~;`Xu{kxHy7*JqALht*`7mB$#8h+LmIN&kN#;E zUiVFQPUik(QDxq)p(EPF5)@C?f$^?2*wILkNnD|Y&gb74bdw{m;yJ&ss++lM>hc~| z`PwEo;)&2p4)s-$HuElklX~WFV2w@k))88xLJlEYSB^p*1 z5J<+LJ?^nD!|bXyH4)#pfs+CyuGXY(8CiS|pOxEWrlmS6zZ{EpIusg8mIe<58Gu-B7Iu$yBv7Kkf~P zK1re{*f#X1Vx5fg8pw`FLYl{r`}j}EoOG65#68JPYyZTVyY13M**5TTQ;DNm^wM;p zZYhIO$6=HYDc){eu+Y-I`m$zx?kt%Z9lCTBl^5IlurZ1ExXPqQDmqWVK1FEDh_LZ* z=!3O32aFG0RiXHds<{g!92dL$HdRh+qE=h4dX-hjuTn zLzniaOE;&q8KK;Y-i@$c@4Yp<<=;$!dsw+scZjs4bYY%^VdXunT`5e^t!)uTJ`Va?xLxn)evW^$->#3u8>XPX{_H|?J zf2>H62MLagcg$~Wcn0SB`sfT!Y0pGdNn2?=Bdj&)$q?!7&@K;ue+M5=vWHiChqw|_ zqT#jyPLlT*en2hzXyt-WH*ta(8oV)>+C&Eu2hrg%Z`sesHQXA|xSWt>(z~r<}9Qnc1EJP)#ZkXe)r6Zu2o$u_)!d%2gix8}4m#0y zD1I+8?^eHy_UVvbU=ubRDM2j1`6fF(Gs2O$V`q)4sPQPtDYOVq`xb0|0%{zdj<~+` znljZW{uI4B5=;-vm2qXQ@fN+=ewtBe?Err6JBbVsl7#TMY|nH|^-)of7Jj`rzSo45 znhYWu&v#sbkyFdOWUsoO+|+@XPMBQqLmgXKQyRjK!RgSA$4Opw`#D?nPmdK185#VH zT)#k9hy5G~eM-R#%uP{rJ!<1!Lrn0e(j(VK;P zSWS<+oAi9`W<=@5B{gV+5H2sLlz9GUAVqk>Z0lvecV@FUV-W9?sl|V#Qp!11ZsXOk z8iL>P?g+H%7S`1*Ko4yVa3F5n*AJDfj^JqLdswC}eXot`v$?^`wYK$U4aIzpqMj}K zwP{{_gT~QyhNC)}d$DvIf<;v-Ww${ggQMHHM#l%*!SlXj8-UbLCE-BOX zHMJ#u`Eld9B9=+H(9%w;^LF-mP1xs!fQt6T?d|DUBOepnRcC&f9a&kfp`67Bk#Yjh zznc6Op_5U)W>n%G5z8w_ER;YiTLWP~Cc^VJBqEI&b`*=3dL5n0C5SLK{=>JFVCnT1^b+g)B`Gey3` zHibwd_mAV^km_3)Y<}9hK0*lBg(HG0ahpL$G4B@ZvNPl%#si6h`F1tlk5-qkf3|mz z?E@0`jUM|G5Az=ol!p>Zn2a>^fKax9$bKz!UW>+P?&<@%richwx>Nu7wPe2Lng*>kGq2bC~s^mHP*YY*Ch-{&9*a*NHSJ|U;(v**bg zlL+@ogn(GnpaYqO!rR=57$UkOj~zmTMSoIraAkM znunXq>2fBnB_CUBS{(zC<3}0xn&|$oCy|3P0UsdGbL+{xvr$*C0J7`%$|Y>F%pl!M z>}VHXL0Eba+5WTbUx*eEbtkL|n{PHCYZI|;oz+C`J;)apLenr>w*OQK&UL+@08%f7j8?`|$vXXLR;F#!@ zpDJ7Z7y{-Rgj^;8v6ki+?Rjw>0v|1TN5Ga#igf4d<`^EBL5ytwRsbsJji%CSwEd@I zt^^Nc+YD}|F%JogSvA*K+R>uXlxw3{Y0UYs{6}HKjlc%6HptMc!S#m_9*vl*oGIv7 z?}5X4*}S`=rg@?fZ@zl});=`uD#$5r9Y_dmz>@b;F&%!s#UmRAtsy5pE;KWFDG&QR zFt$c=A@j!ca#)314i2|Zsyw#1zEUhsu&iW;IuP6!vYLAL(YVfE$`+>R@_CWvq>{yt zxNo9{%qvQFKLnYEWVD6!dPCCey6XrrLLz*FtGS4Fn-ggTgL@H*4rIyP%c9K6G}?N% zk4D!e=>&QWN=GHnN_Dw2soZzL!lqkCt+42!D?}eV058l*(w`N`v8R36S2oT%$3q zcxHb7@K)y($qeLKa40+>`7WiqGQnX~4+1Z}lOywrQ`jd@X4pZe4}sZWxfbar4d%Dq z=G3X{_2XEsU*G-j)!6^i>%S_p`7fQ6i|gE?#{e8s+<^S-fA5^Ae0A?0LekX=8;FhK zz#Slv-*q@wr|MW*8O5 z#V01PT$e}B>h-EC9@)O7JtXL(>^7GQTle(AW>zO*=7)j<_Exl@BtBDD^S>TX=buxb^lt3#}WbR`zDEb@m@?@3pz~+x2_Ocy6g}T>5WW!NSSf^xr zF-SL_Sz*%ziGpyqiIyQg=Dt>_bFJ#RVh!SZs>ET(MtWEyvM+|nvg=7=TLXH_`LM7D zuhH$wv#ATIxMf=?%Td-yD^yJFu&IeKv8A;Y5;|mu`OekK0{%4I@<66;p(_6sI8ZIH zAu@stn_BE@`B2BNT`?zMOx%H06*?pcr*Ob1U^k$`x8KKi4-9>6y$3JdpJ1`_2I{N6 zweevSo}?2pg%ait!`(4KsI<14`UYzZbiRK0N~Zm&a+b>4w|lSKZK9g(aSJ}y_4h+T z%+)9LBIqh!dS?osy@b+L=ox%FN_Nkwgc_7IWX|i9>aF-WwZu_=rbZjTnNmjX0W{pQ zzh=a7y*ymyTS3D)-q(PpkR?*n!Z)-0pNy-gN*T`gz9!jEnX*jP8kSKtl^2$?TM$eg zP4R}slCcu=E;BXT#z5XIjIq^iedP~fk+ z={+qeAdueOwAP(U+Nu8>s+)sn;$E|NOL|gPe>PL8V*WZqolVug7*?@HFe-*yq^h5& z$x47UhlR<7$7yd6A2;>D13ry;Z7qlll0vEYa)9lf5jn_-b>|#_Pm~6=_@uCnY9!)(PGG~St{8xWuk zWrW$Nht&Zsa)8cLm(=aQa>5-UzsQ+fX_`5Z5?)K_vacj8fe$O{=oIbOs4oE%m43=- zKXae;gVpK~%g$!gkGZ#u6EsRu_B>AWA z91;GgrT^6$_Sj)GfxX^)cq}w7hK6hNvq2#b#B4&A1-*QN6exdj_J;}j!K>pyOuXST_#`*c51R7V% zP4GLaI$SU((^!Sfq`DlFRiSf zaJg|*!v7=NziLbRA8G9WiW^!VKR1^&AS zvYCSZ>>BXRHfK<5MY_#+(HT^BU+J{lxCTzRla5Mvd43D5A4xPI@maq#1D|7F2=oZx z+x=~JxtD@Djm6L64jE|=M~@*DkWKKO6ZpaI8G`$D`URD6IC!ykv-^hDI(npu1rRBp zZ2S5L@4Y#%_XOVMDmjTnRcq}nB!FN}!?n5my5TJ-qymZE^nDes!zau#uHh&VXHLo&OK?S$O z_KddKIuML-{o^*ce0V4T0^&-)ip_?2-CqOBcm60p-)ICwa{@Y~Wn1G0&&-7r%T8jg zZrbHSCFDx0_|XlLLu!BFMlBnFWZ-KlS`e_x?_NkAOg zs&NLxB0>ccw@sasQr*9E?Fixf+BStWge!6`+|XiQy|`lgcHr^5HO2K;^5bqMl5JKf zEXZm5K2lZ|`FiDtqYIaZz83Xr{wxN6QT@m-u)MC1KcsZc=5SN*JJ(0Mp(m?mOnM+# zu76syFuhN3VG(3zVg2VXUr+S)^}sNT=uX|=|M}+pQNGUe#`E&!>bh*0*n$hlu5z*O z->4n9)5L%c(L&d8HOmQhLfL)Ui8Ldr&iYhG)BD#LMg|urzM7sV9`uiB@1NQE{TY2% zHTmBXe6km`fBrVKGIRRC`8!vr=dmI7BzHm=m%(g%R(sC+#KTLBBh*mZ4R;Hc0;|-a89_h^Iy1~b~1}loKT^ezyH%-c`=;j3#RbZ<0f5( zc+XVLQF%1}K=^k+OqWLrCyIy?$%!KR_r1=-PlY+NaBtmBj+pIfjC9Blv-pVk)rX72 ziT}@&|HpoZ%X@xj?>X$Zrkd0D|7x2(bc(zzyT>N7{S?7^o6n)8Ea-M@KT6jV$9*wEbT&Fj4U3Cli=P%~}AMY>h|2q&u+VS6q z?;~9Q$817u_TR_qZ@d3DB7ze&#pTa}W%f{JP796{*3*}>8OUS)nw)Njwl~;jQp<>% zpaeQTDe=yD2dD0}h|1mH&TY3o%u9qf4Avs1g6se6tiQ zs}_Om$wdgspwRA(78uMjs?ZiG+XStvnSL7^vSC79Wz=S9zJw|IU0`m+W?7TUZ3(kg zP1^P3_8sA?p*ZDgX|Wtx|5tH^dxnp`09#&{sT zDl)SYjBJ2RH=lNnY4Knb28Mhz+YBe-u3FB=15PhvbSGy;sAmBW+g0P z(2G?^vx=e6`=7}l?CKpIHvSfBz1)ezurfDY(}NSm#1a#6&7l&k%GLFIBaX`RSSRb^JLk9f?ofU(I9Yfyuy0jS`KSR4Mi{#3Hrz3%Qst4H&;=yQ+boWP5nL- z)KJG529Mzowolg}y<}l6wS$UO8NSNxv(g}V=LY1M3T|)1CxzX@BjFbncFMJ;g~Ao( zS8wk$7@~Z4>vBd@*MxdEL8KCrAK1@zU+0e?^YK2tDS7XdV55)y-s9LU3`$+rzZyZy zp)U4YtEg4kZGmn1aLv2=?7o%#-$&3VYQiOt*K^&NfIAuD^iT_~kXDI)7F;rK znRqAPbNZ?MP!&JEk!1y>37rP4i4pS$$s+s$oYHx*h`%zy;FI{TawE5(`yp~vO)Pkg z6u{UJo{}*(-J+%L7y<2ovg+&eckU_dBw5-Mp(ne`v1;JgBUz{!Qc3QY*2WOuuok64 zWgB$HVWgT0!Wp|<-%g}OkhDeGY&9*SM;C&AzB=5}H`eh>4jY>%Lc>!YO+#uuyC*XK zisV~Pzaz8+SV`BxrzD|K4YLG2rw`4cN^YVL0^j3W$ySY6%s4>H`(s#0FKDUeZbVLg zQR3ug!T@LRX`lBQ?8LdjmqnY7x%cw@S7~V@>(K*E@V5#VLnpgxoO;PWrZNIkraeM? zuIGM}JkFz+!bxs1;&2Hmpz0P1Rb5~EW`}+~SE{plRr2vm=yjTrV(t65t43PW>y_DZ z`JR|Rm^Z}Y{Ai72oC$uf&u?73&IR!3)gk;Y&+FH5U8~1pGr!z2kes^KL=r+TkM^Mi zo{r6Q0WFStD5jQ2P-+c1^En6H#5dHr~2nSg*O%uX1^q=+PYk$j<;d zRYo~ZN~FFhyDMDh-ScPRB}hNgNW_R&(+zIOz$_0}A_JIkMV_3ja7z=XVdEKrRNKXU z60ZNfzj2N4j3Qgsfv;&bL%2Yf{eF)T*`|j)HEL_}6gB_x?aCcQRrlD=21#LMT&jVm z43lO4%PHCrN6NRg0EHH{d7q%}3Y$NWnFDB?8jQ&f`Sy!yd>q{k$Mr!7>7Pe*-xh3Z z^HpN`aFyWMD2oWgN=HHJ={pUdlvUrw7&&vkwDjg0)1-9ub%1kbYCUO0c|(trS{n{O z3S>u>NaCUg8ALErW3a2qfP(kVNerJg~dCR=N9vZA5Q;rgYzTHsV2pD@hbn`gna}Z2QI| zz0?Pl?aPIw9iN2hZ}eQM22!*|r#JbUcT-Mlj&z5;Tlz6IWqVA8-zSKhypOBaZQs?tKOsj*|gL9{S)#in3cAZdPT2?5+J%h zJM#wPU@}LdiU5xSb3P4I1e`5IturfLcZ9yDV`|qx19=9GyKBdKL515Bhkw>5GQV^E zlD|zF1e<@XiLq6mqoC{-1##x!YzH5y7_afa=SVQ<8nZb?8w3UENa5guLJM}mO0M0J zws$W|#d7V+Xe05y>#$O85di5onmLl+r5n*>ym0SRh%xR#wr;vS!eUT_n z+X$?Z(*Ja<*_*`v1sPT!-i#NdqLUIFa3AC?N$VSsJ%kl?(!W8JIDVyW+)ju;s-SVg zGJiOD#~Kf1yiMvRUpEpi%5VHRP#$gGtKHJV#NlGc6WBo`te2}B+Dd>LL>MMVt>fwJ zPNt!u@zJAc(Pf(jNd6jf4+4fQgQCK}j$}-V(Aua^ z5N$@o$vr+@8#4N)Ar3ui*tj~n^3phZku>|z9N7niv7 zzu0@vsI>C^|2OB%WHOU_)Tpsf#4@%RHEJyAnbIRzh8cduJfK);rc1$y+XV%a^mDLxMFH@F~xfF zK)!mq9iQTvo!#s7X#qd4741uOc&SeG{&76TLPRnf0WCucR=vr6d5EC-rRk`)thJXF zKi2YX`TxFfH{`$9Vv@>k-!2@%1TAcnk@Mn|gP@t;a;$h;23e7qS8mIy$`d8I4v_PG zM_z)})*rAYr`EVs(qTfu z+^?_uq`j}E6IESa{YESYlldl~X?uzWP#IMJ<5$2Wxv|T_s=6Z1)jMe)wCCtUEn94V zex82zu%qM7dA$nQ*vI|%`B2(@{r#7DA1i*JopdX}-z$|2vU5Vb`R2tjtwDLaRc|AyrDu<`88DJBbRKeFx;>5aghW*|~#Yh>_yn7DIm1Qyn1Hi^j z*Hci^uFTOto;?g*^YCk$*mS^2@1fBPg7>Oh?E-@lKEC`64=kBFPY>~LW*@X;KRUMB z^nb8xRnD;0#$8o?WbYG43~i;bV~&4$-^SqZs}YK?l>1++P30tA6}tm=uOB>^E4r;zP$1Ggh$P9 zxaDGsJ?<3I4gRH0tHJ7Kh@(IUCAdTJyJt7Dfq)xMw|eaYx*%qVaJ!uCpi0z2L3qd#hO7Vy|-&P{k2*Y zh(HezULcC1KAYHuPH54jJ)7Ya?0I(1hC_=E-)ctL7u%W45V)()FW*@+=&zk7n|E$Y8J{hEa&fDG236y_iyShZF2t4$Ax%V4DCV4iZ8?2TqO$0{ zy?^@t++8K#VF$Q*t@)LZ2f(P!+)|*i%Umg`?L9Xxj**=_QLkt`Ptlq*yByBjeqeWX zeJ(G*JDt(A{y4s8$gVMFsl;Zf^y@g@9Y4FVPrgWYlmZyY^0#W{(9$l=}EYD~W*82iWuw z>*<&MFe^e~j$c}~d8DYwXcAs?|Fr$a_3@f!~ZO)A#X#<-y zkur$pbhOQh+pxwDKB%4b-jquE z^Fp$@-2bDej}*7ui7!PZ3=cN=8`4k#r1n4p2(2FK_*d^${iP5g)t*j^x1rg@a6|__ z;!}Q^SrFf}>Fj!Lh>mZ#Qo2UG3e?UuJp8Wn$V85nK5dUoxbij1QUH|NeXvZ+6)ZmYqeslE5$)K$xx!LjaNew}Kvcid>U0DAeqMv`OD6Y+fU9TgPSNakOtzzrk z8#5Oq?R_K-fYRBnT$6EMo~A{8v-0$o~sT;0rnrVkN&37P-mgB)7NL=Az zt@P|KcZt#hPNx8q5v2JSM%&RS95MB+-#L)|K#i*;Wa6JUnsI z6yNn!0>R1{D7UQXifZUvv@AbFCHijGM!|u}2H7KPUY1i-yZeTlq|}FBUt(YHp^X$U z>ENa->h&;ym^;p@0whol9~-rm)Q?Gd)itO4t+PDlI_J-icQgp1XC*^+(V}RPsppDQMHqS@eh_vE=NqdX3N%aR#`9ilH*l(dqlHg zMqs8U>%RBB4qP)8Knm8aB83ZborYbPc-EIw_^3em5yc~kNS+e!)G}6iY5`TZZmJC8vmfD!hH~%u|x^I{(Aq?4Tk-dD|G4a!*g=r zow-u72SB$Pu3!_qJ5ugb;i8o;sNS3_>g4n=V0J9+09Xhd_u({q=^HlXOTjm8^aH~{ zi0PyGLN&^od3$a`2CG77bslK+9{GkkS2NiI!~1S5h54^R(#iet3%5fKJk$9K=~pAV za(pQ0Tg>yfX5hlG#!kg>$IC3^HtTU`*Bz2nWfJvoX5mc|<<4$>)Yz;YwY_C1V{?o>NI>}Jr}I&I@*w#RUg*Y@y-m>?;?uyhOFew?tEs_{)VP@F#`iph+hmw zHUCv^V)<6*XtY9hm}$;`=v_K>#lM@7Xv zg%j^9a^4#zDPkSqa}X6MpEo#-{mn0^+eUP|S3P6n;D7?yL#1V4OtL1MWE>Uv2G<4& zdUZg_0dUcCl3??Ga!J=+M)h0{Pn+Q_M~q0H+e|^3Dano9$qpop@`Z^`lJwJpZbKsmU*&I3u(i+ar%55i}nO={a zhZ{)mnPW*&0f}aJ^5Kc#>FwC>JC%Ob#VP3}puz59HZa6;)oDojj={!S==1eW*Faw< zqGQQ$<|22tq5aqH=<2vG_s?-b%azcp_b5}}|JaUQ@VKd1fI+TG6KzZltpr|YOd~!; z19hy~vo{m(7XaZPKDI@5c%oQ3zfBsJ5P1fLN9y(ZA*DlAT5Cy~PJ@1ga)SZ-CK=p> z(TcO+O7FQkh&l;5J#<*7Css(&oK{(m_wYs6lX`&1XvcnTNmlPz73(MzGTf(bz3QV} z0q|2T*5xhhq#U|g=C(#PTx&G73;VQDr1a*UbKQxl&2Ni!%M&%rD0SgaVL$zisX3Qr zsVA;`qdn=7qvHwT4>$W+L?5*ZhgFv9E@U-&xUOf-%Z5|4v=uK#D}RhcrM!;Z5c%2db=<4sggw4P_uxyQa14N17tt z(^GEd1~MUv=`vkOQcwZdO0uUyBmys><)5-4>IO!`dwpGG-I=X3udmyy?vIziGJd>G z*PYT~;G==xbQ1zD`O_B$V2#3%Np-DX)IrVxlW+X7!Zx#Pb=z#T8s3OzlrNBV8*hSR z9A58zQlsA?BjV3*zh8!AG`W>zAHqt;ff%a=w?;4lQ9cN88b+!~ay;wj?(5|5J$uyp zAC7KTewb&^{trV%60!bRkzCoPXigtCErWSr&Ts&ML_u+%9TlSnT3&b1Ob+jkT zl&{+=+saJb)qFSi&cOTC0{PAqgcXQYSt+FfcjL0XHRHSu20CX)z}h zIh)~`W97o+Q&U0c-DQp0WZrRGZ%% zxYy>bHafmo;IVfph@TUFn`}W9><`R8p3>f5^9-0na`B0|-V;AReTbG)uty=F1oZ@6 z5LzUM(E#IxQT6_AG16*<`8iveH+DJ=>dQ@MLsXCV>#(3U<%%|M(L^B-1ZT*mJEewX#4t6)PwpJtV|jv10xIb)Z8BvH@UHMAVPcIy*J+o?XbP`&w!FJ6>7Q135tx@^6&WFHN zZ_Xjj59__L+({+lv+R>6l|!ZuF7~;O9z4W}Un=+LwR_!}-MpgMo?l46mMg~@mJyIQ z3F<=@4&1ySRPhSgUYkKHp!Kqv*z>nWL^Q|nKt{bctJdMFHnaNL^K9kx+B?7S56`dI->bF{Eh>AoB`NpvBvP)?eYfOX?n_IDqt?_^ zuZeOVNi+4hzc)GDq%HE}cKLqtq|SHaYLiRXjU?MWasAFAFNMQAgb}Wf3F0uL4)@1- zJ~CcvLhs(HZrX_QhG&WJxpxzZC{dS-r1{zfttR;p(ctml-+lPr-a)c&0S1851r=qX ze=(?~uOZWsw}vVtsB4m?AJS9cfA~MiscYz{8(`$MVWv`I6<{s*r!!UlEK9huH`WkNSpRqi7I}I(pr_Of)uJz{K<#OA*UX`M${c2%) z`U(tDMscl<1cz)Oi&6V_LBVg9^>s)?AMnRu(95~Wh||zS&6U2!#G}JSb(5Pf&f~VU z)_?ba=|D=5I8w=UjAK zf17Q-Ej>G+rx^BjzUsXIaOo;i?-qfG#umWsQ9d%st%my_SUO>=osj1Byz_4t>=H(` zUOWCJg>f!4P^h$cG>AOwH zSiv^EWfS|%<91eP+`6OmRq~v7if92wy%f+I7k+gvX`H*pt`0A>c-SMNl0thv4zo7- zPq%;Y-+VvBFabcMjm`o5mHy&J*>+h(;WtISYcl8>Ue%DlHYPcak0v9?i&_$e4P&jK zjYwxVKR9KGi_Zxcz`a#fHSvO+gI9S*{}X7$Y_B);T2UycV5^N5Tn)6X{%4_BI?Zd8 zw{d3EO0!R;z}&ZCaZN@#YGH{5}Ec<+6SK{kN;59n1*NsT2 z3!8|DMTkmyC<9>DU@JrTj-$8L$G-VUzTFipne61W$_X)$ea#o&2-bV-wfW!xnbwfm3+4ZIGy@L zTT<_bW^%3X-Dq87v4(*!@xuOPU!lC_kg-Oi_|3`@Bv)u_lF4T_xH+y{B zqvw;ERZO^emEX1-xTC{{Z2w0)JV?S=i?U{^{~@#{sqyXH$R_M45kDVrSQq-T#V7yE zjEg_7y&aRkFk|8{tR{<N9QiWv{qm0Q+-P?qsqEy@V(8Px_<+`^pimp=q`zY&7Iy`X3#7gQCL|x1l>pP~E_v z0CH2BEDJa)6l5q`KUrIvi=H^RHow%H?Wx;(T#M+|(c%vr$9mXGZa*m5h-9q6te0aB zflinT?G}gM$#8w+kTSPJV0{H5E_O9wt~)k@q%rR(O#CH45CNziTtsRj@#Un;xSJiU z>(PgV5~kEl@Jbe{aV|;M?vtnID)A)jg-F@Kn>Y3Q4ylgoRp~G(_QaDb;QHO~TSepi zLB5LlH~-ke93J4eAA3)5a=`$MuiZqo*7@g_a}zkFfNsxxc-;sVGn)ICVYiYqA&%u0 zF_4qf7-Bmjw4>}dZcVq^DK@A>D-Cxv-0v7Z$C1YPTe?l1c-#$&L(4b`dV89Ge(bB! z#-bal`ReDaF8QuZQ&PC6AzrzIAB;M3i8qB!x>FjWK`+ilAZep{K<~wzux@7i>DFQB z>Y=0IgQ2HOm06Y8(wVi*KZr)^R%&^zM!yw;8VJG_?sIkUl7VA@cTZ=+_(^ig7!nPJ zhz6`Rtg|bJy+c#ULpjmJi%Ao$(2T6L`tG>_F4v3S`(x?56D7b;tsx#<4}G~m*nd`B ze7}eWi|G;kLJ*Pwr#^gMYwIgbV`b^Y^fmaAxzMIXa7A02mf=sc3PYfEj4XzNUy>IrOx6Z@Gm(VG#l2v` z-0Tf${}R|MRpcclxaMF20l?Dz(}kd{BjKZ(Ma)e9O-@=C*KfUD=uP7W3I#V>V%0+j z=lOGy|9ZSs)3N*cbE?cq_YYB%R+sWE@25+F!1tEpt?rK~pzFjyrzoUfNNCox3 zjIv+Eg`*Q$ylrKi&E$xkU6lv1v^t`MygM9j*p`+#*IwHT-)f6E5ZSt4 z_UDt>uX1CM9aAet2C2AHKRck;SExgQG-tGklBP{7tKzG?JV-anN|5s1*rT1}uR6;A z`7!9fw=n;wAO3&pZ~Whvn*=Dt69s7HM1ip5A1D9QukiondH>U3-2d_#;3e*ToUSMm zauBv|1LkTZ17L02MwD&afiVLT{A?g2t)}zu&;aphmg&`d(+8Ey#?|AogKnEzb4R5& zvPCL3*9By{jpZDdQWLr=UFZ00P0)^^Jg~0->gaR+L%-uU09TvNDok{Ech&CsqgV&UoEKb)Pg?k z+q0-WYFD>@Z-@3H`PPZrO?&^qj$)#%u%2sviw(5Lw4E^Dy7sXBij1{S&;}l|$^a%p zRv2fJ)1&MKF!w#y;r%3 z0FR#TrttlGXq17JwqfZVRZne!-C0-8P*0Fu(={?W9R)$ts?%EbDRa#~?#qmOcCq>v z^oqkS>B0o?J1++EE-+~Ncj>ex)P&`OmDvFb`h8?R1?-^D=Bw243cc*@5>iUX%R6r` zYBM8bfgX1~F(ajI`_2KhQIZykUXWvD-V1ooB^*${Tuq5|oKab8?E)X1F`>;>!@p*1 z5gw79ZZ);FTiGrvJn6WHkvuM5HW&dVr8GLou1=FTEQH%UO+bGT=giM-j6T1OAc~Q8U zYK1&APm*l^S|ueXQybK5;fEZ+cO`@(&(a66LXfWp_tush&XqN-s@#rZ(g{|78vfwp zqr#yLY!6<1WueJ(yyg>DC!*HTxkPJAjCTIOV?H|?T^)}6_ld{KNEP9&Z1`W>ZFgi@ zk?d*C=FmdU;;A_{WYV#{a+|2o!U-mV)15rRz&I$&r)77>9T`up`aQDdEV6h1hUj=E zw5O2o;h@cd$i%3{fTjJSORfau42st9uY9{;ok{-eh8d{mO7yDj=918^(3jDn@K~CD z!J*1M_+EJ{AYx}4W@ynkuO?>s5j(kxZO1RJgXQsC^Id%_KGxAX-aO5*4!JM)6L8A? zN76@}FhRk|*kO|}#f=s8XVB;L1(tLFp7`*B_E0s|#!gFbew}p#<1f~(#XOagv^*+4 zSITzF(>kw%=t1PwM1{Jb-9R%Dy z#`0&XP4ql2vCPpcI%OmnZj$fipiB26r&l|uDP86;`CZINROD(>2|WIVMyY2^pzV&> z-Qyabp5x^iw*&>u7lUa-gIf(++lTT5KO_JXi?rvNqhe+Z+guAC;DT6%P4gFlo#WGRJG6YV-ZN)n$Tc823 z@THwhD|R6yE%j^msMFup+ zA|P(!{|Jcwmrtty#p(a2=_9+jl7HOEwpQSGmOCy9xO_hs{`R0PlvO zlvPOE_-eoxetc~%zQdiyTRiEw1fK}XB*FHQJ&)nMgH8P3Iq#(t)$(r_ za(to>Jo!K9qj-1hsTIi2hr}l>KkFg~gbtfycjDfl2 z!R#9wO^6O6>t@gcVsCV6RZBoWW8j=25pwaNm|+`~ zbGcc*S{(UH7u@RcCZf!Lx34tY+&o;h?MX(+?Jr}m@Zcqkax^0gU zJZ3|`uwYtD&`e)$WNCJ|Obuh-aNQX+T6KQ#pmx~}!J*e`6)>t@tES3c!(j3-8d{S%^HDxt zn0hDu)Xt^@ewI9noY76K4Q2Qth zB>g$`{AqVqj<&MA12H$HTfUl!2%L)p`Ou34+HuVrZylLowNZlrI)BD`Z2yMhMf;Sq zSPx?ZeZg=|Q%sDKACugDNOlq#&%4MeL`S)=q(CZ<)L)rJ5!#!!k8CLZ1I!GZfrP3% zT%FukhfV%DE7D^nQx#v)>N*9)okXsSj%Bi>?pru zmVuF;74_Z+#nU_vkzrc4$PtCSkxgSY6R4MF2WN3Rz~*l|bm*R2J&g}O=PiJ$lh-fs zAWf+c?12Bqy%NyVu&|q129fG7@6rM%Vj}mxIe@Zah??_`$gvB z@E+B^Gou>YKT)Bs3c}!B2@z#wOK#f zhLZb&=;04H?tw6bQ`2Yy(RoiYWf#lX^>PaH3D1{#O7$3EcHZeYHhSC{nq}_m$&t

vV84R?Kl1xtaw>%w1Rq*;SuHZq*rUYXi~ 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 HUs?YFr>F7t literal 0 HcmV?d00001 diff --git a/src/Controller/LogsManagerController.php b/src/Controller/LogsManagerController.php index cb84e77..28f171e 100644 --- a/src/Controller/LogsManagerController.php +++ b/src/Controller/LogsManagerController.php @@ -1,133 +1,140 @@ - * - * @package EzPlatformLogsUi\Bundle\Controller - */ -class LogsManagerController extends Controller { - - /** - * @param string $name - * - * @return mixed|null - */ - protected function getParameterSafely(string $name) { - try { - return $this->container->getParameter($name); - } catch (\InvalidArgumentException $argumentException) { - return null; - } +class LogsManagerController extends Controller +{ + /** @var int */ + public static $PER_PAGE_LOGS = 200; + + /** @var int */ + public static $MAX_LOGS = 10000; + + /** @var string */ + private $kernelCacheDir; + + /** @var Logger */ + private $monologLogger; + + public function __construct(string $kernelCacheDir, Logger $monologLogger) + { + $this->kernelCacheDir = $kernelCacheDir; + $this->monologLogger = $monologLogger; } - /** - * @param int $chunkId - * - * @return Response - * - * @throws InvalidArgumentException - */ - public function indexAction(int $chunkId = 1): Response { - $this->denyAccessUnlessGranted(new Attribute('ezplatform_logs_ui', 'read_logs')); - - $logPath = $this->getParameterSafely('log_path'); - $cacheDir = $this->getParameterSafely('kernel.cache_dir'); - $projectDir = $this->getParameterSafely('kernel.project_dir'); - - if ($logPath !== null && $projectDir !== null) { - $formattedLogPath = str_replace([$projectDir . '\\', DIRECTORY_SEPARATOR], ['', '/'], $logPath); - } + public function index(int $chunkId = 1): Response + { + $this->denyAccessUnlessGranted(new Attribute('ibexa_logs_ui', 'view')); - if ($logPath === null || !file_exists($logPath)) { - return $this->render('EzPlatformLogsUiBundle:logs:index.html.twig', [ - 'logPath' => $formattedLogPath ?? $logPath, + $logPaths = $this->getLogPaths(); + $logPath = reset($logPaths); + + if (!is_string($logPath) || !file_exists($logPath)) { + return $this->render('@ezdesign/logs/logs.html.twig', [ + 'logPath' => $logPath, 'currentChunkId' => $chunkId, - 'total' => null, - 'logs' => [] + 'perPageLogs' => self::$PER_PAGE_LOGS, + 'total' => null, + 'logs' => [] ]); } $logFile = new LogFile($logPath); - $logTrunkCache = new LogTrunkCache($logPath, $cacheDir, 'ezplatform_logs_ui'); + $logTrunkCache = new LogTrunkCache($logPath, $this->kernelCacheDir, 'ibexa_logs_ui'); - if ($chunkId >= 2) { - $total = $logTrunkCache->getCacheSystem()->get($logTrunkCache->getCacheKey('total'), 0); - if ($chunkId > ($total / 20)) { - $chunkId = 1; - } + /** @var CacheItem $totalCacheItem */ + $totalCacheItem = $logTrunkCache->getCacheSystem()->getItem($logTrunkCache->getCacheKey('total')); + $total = $totalCacheItem->isHit() ? $totalCacheItem->get() : 0; + + if ($chunkId >= 2 && $chunkId > ceil($total / self::$PER_PAGE_LOGS)) { + $chunkId = 1; } if (!$logTrunkCache->hasChunk($chunkId)) { - $lines = $logFile->tail(1000); + $lines = $logFile->tail(self::$MAX_LOGS); if (!empty($lines)) { $total = count($lines); - $logTrunkCache->getCacheSystem()->set($logTrunkCache->getCacheKey('total'), $total); + $logTrunkCache->getCacheSystem()->save($totalCacheItem->set($total)->expiresAfter(300)); - foreach (array_chunk($lines, 20) as $index => $chunk) { + foreach (array_chunk($lines, self::$PER_PAGE_LOGS) as $index => $chunk) { $logTrunkCache->setChunk($index + 1, $chunk); } - $logs = array_slice($logFile->parse($lines), 0, 20); + $logs = array_slice($logFile->parse($lines), 0, self::$PER_PAGE_LOGS); } } else { - $total = $logTrunkCache->getCacheSystem()->get($logTrunkCache->getCacheKey('total')); $lines = $logTrunkCache->getChunk($chunkId); $logs = $logFile->parse($lines); } - return $this->render('EzPlatformLogsUiBundle:logs:index.html.twig', [ - 'logPath' => $formattedLogPath ?? $logPath, + $logs = array_reduce($logs ?? [], static function (array $carry, array $log) { + $carry[$log['level']][] = $log; + + return $carry; + }, []); + + return $this->render('@ezdesign/logs/logs.html.twig', [ + 'logPath' => $logPath, 'currentChunkId' => $chunkId, - 'total' => $total ?? 0, - 'logs' => $logs ?? [] + 'perPageLogs' => self::$PER_PAGE_LOGS, + 'total' => $total ?? 0, + 'logs' => $logs ]); } - /** - * @return Response - * - * @throws InvalidArgumentException - */ - public function reloadAction(): Response { - $this->denyAccessUnlessGranted(new Attribute('ezplatform_logs_ui', 'reload_logs')); + public function reload(): Response + { + $this->denyAccessUnlessGranted(new Attribute('ibexa_logs_ui', 'view')); - $logPath = $this->getParameterSafely('log_path'); - $cacheDir = $this->getParameterSafely('kernel.cache_dir'); + $logPaths = $this->getLogPaths(); + $logPath = reset($logPaths); - if ($logPath !== null && file_exists($logPath)) { + if (is_string($logPath) && file_exists($logPath)) { $logFile = new LogFile($logPath); - $logTrunkCache = new LogTrunkCache($logPath, $cacheDir, 'ezplatform_logs_ui'); + $logTrunkCache = new LogTrunkCache($logPath, $this->kernelCacheDir, 'ibexa_logs_ui'); - $lines = $logFile->tail(1000); + $lines = $logFile->tail(self::$MAX_LOGS); if (!empty($lines)) { - $oldTotal = $logTrunkCache->getCacheSystem()->get($logTrunkCache->getCacheKey('total'), 0); - if ($oldTotal) { - $logTrunkCache->clearChunks($oldTotal); + /** @var CacheItem $oldTotalCacheItem */ + $oldTotalCacheItem = $logTrunkCache->getCacheSystem()->getItem($logTrunkCache->getCacheKey('total')); + if ($oldTotalCacheItem->isHit() && $oldTotalCacheItem->get()) { + $logTrunkCache->clearChunks($oldTotalCacheItem->get()); } $total = count($lines); - $logTrunkCache->getCacheSystem()->set($logTrunkCache->getCacheKey('total'), $total); + $logTrunkCache->getCacheSystem()->save($oldTotalCacheItem->set($total)->expiresAfter(300)); - foreach (array_chunk($lines, 20) as $index => $chunk) { + foreach (array_chunk($lines, self::$PER_PAGE_LOGS) as $index => $chunk) { $logTrunkCache->setChunk($index + 1, $chunk); } } } - return $this->redirectToRoute('ezplatform_logs_ui_index'); + return $this->redirectToRoute('ibexa_logs_ui_index'); } + private function getLogPaths(): array + { + return array_map(static function (HandlerInterface $handler) { + return method_exists($handler, 'getUrl') ? $handler->getUrl() : $handler->getHandler()->getUrl(); + }, array_filter($this->monologLogger->getHandlers(), static function (HandlerInterface $handler) { + return + method_exists($handler, 'getUrl') || + ( + method_exists($handler, 'getHandler') && + method_exists($handler->getHandler(), 'getUrl') + ); + })); + } } diff --git a/src/DependencyInjection/EzPlatformLogsUiExtension.php b/src/DependencyInjection/IbexaLogsUiExtension.php similarity index 50% rename from src/DependencyInjection/EzPlatformLogsUiExtension.php rename to src/DependencyInjection/IbexaLogsUiExtension.php index 4bbb935..50b3702 100644 --- a/src/DependencyInjection/EzPlatformLogsUiExtension.php +++ b/src/DependencyInjection/IbexaLogsUiExtension.php @@ -1,32 +1,20 @@ load('services.yml'); - $loader->load('menu.yml'); } - } diff --git a/src/EventListener/AdminMenuListener.php b/src/EventListener/AdminMenuListener.php deleted file mode 100644 index c10f886..0000000 --- a/src/EventListener/AdminMenuListener.php +++ /dev/null @@ -1,35 +0,0 @@ - - * - * @package EzPlatformLogsUi\Bundle\EventListener - */ -class AdminMenuListener implements EventSubscriberInterface { - - /** - * @return array - */ - public static function getSubscribedEvents(): array { - return [ - ConfigureMenuEvent::MAIN_MENU => ['onMenuConfigure', 0] - ]; - } - - /** - * @param ConfigureMenuEvent $event - */ - public function onMenuConfigure(ConfigureMenuEvent $event): void { - $menu = $event->getMenu(); - $menu[MainMenuBuilder::ITEM_ADMIN]->addChild('Logs', ['route' => 'ezplatform_logs_ui_index']); - } - -} diff --git a/src/EventSubscriber/MenuSubscriber.php b/src/EventSubscriber/MenuSubscriber.php new file mode 100644 index 0000000..9dfa87e --- /dev/null +++ b/src/EventSubscriber/MenuSubscriber.php @@ -0,0 +1,31 @@ + 'onConfigureMenu']; + } + + public function onConfigureMenu(ConfigureMenuEvent $event): void + { + $menu = $event->getMenu(); + if (!isset($menu[MainMenuBuilder::ITEM_ADMIN])) { + return; + } + + $menu[MainMenuBuilder::ITEM_ADMIN]->addChild('logs_ui', [ + 'label' => 'logs_ui.menu.label', + 'route' => 'ibexa_logs_ui_index', + ]); + } +} diff --git a/src/EzPlatformLogsUiBundle.php b/src/EzPlatformLogsUiBundle.php deleted file mode 100644 index 00dc82b..0000000 --- a/src/EzPlatformLogsUiBundle.php +++ /dev/null @@ -1,32 +0,0 @@ - - * @license MIT - * - * @package EzPlatformLogsUi\Bundle - */ -class EzPlatformLogsUiBundle extends Bundle { - - /** - * @param ContainerBuilder $container - */ - public function build(ContainerBuilder $container): void { - parent::build($container); - - /** @var ExtensionInterface $eZExtension */ - $eZExtension = $container->getExtension('ezpublish'); - $eZExtension->addPolicyProvider(new LogsUiProvider); - } - -} diff --git a/src/IbexaLogsUiBundle.php b/src/IbexaLogsUiBundle.php new file mode 100644 index 0000000..882f9e0 --- /dev/null +++ b/src/IbexaLogsUiBundle.php @@ -0,0 +1,26 @@ +getExtension('ezpublish'); + $eZExtension->addPolicyProvider(new LogsUiProvider); + } +} diff --git a/src/LogManager/LogFile.php b/src/LogManager/LogFile.php index 0849422..4bbc83b 100644 --- a/src/LogManager/LogFile.php +++ b/src/LogManager/LogFile.php @@ -1,39 +1,28 @@ - * - * @package EzPlatformLogsUi\Bundle\LogManager - */ -class LogFile { +use IbexaLogsUi\Bundle\Controller\LogsManagerController; +use IbexaLogsUi\Bundle\Parser\LineLogParser; +class LogFile +{ /** @var array Log levels for Bootstrap classes */ private const LOG_LEVELS = [ - 'DEBUG' => 'secondary', - 'INFO' => 'info', - 'NOTICE' => 'info', - 'WARNING' => 'warning', - 'ERROR' => 'danger', - 'CRITICAL' => 'danger', - 'ALERT' => 'danger', + 'DEBUG' => 'secondary', + 'INFO' => 'info', + 'NOTICE' => 'info', + 'WARNING' => 'warning', + 'ERROR' => 'danger', + 'CRITICAL' => 'danger', + 'ALERT' => 'danger', 'EMERGENCY' => 'danger' ]; - /** @var string Path of current log file */ private $filePath; - /** - * LogFile constructor. - * - * @param string $filePath Path of current log file - */ - public function __construct(string $filePath) { + public function __construct(string $filePath) + { $this->filePath = $filePath; } @@ -48,7 +37,8 @@ public function __construct(string $filePath) { * * @return array */ - public function tail($lines = 100, bool $skipEmptyLines = true): array { + public function tail(int $lines = 100, bool $skipEmptyLines = true): array + { $handle = fopen($this->filePath, 'rb'); $lineCounter = $lines; $beginning = false; @@ -75,7 +65,7 @@ public function tail($lines = 100, bool $skipEmptyLines = true): array { $line = fgets($handle); if (trim($line)) { $text[$lines - $lineCounter - 1] = $line; - } elseif ($skipEmptyLines && $lineCounter < ($lines + 20)) { + } elseif ($skipEmptyLines && $lineCounter < ($lines + LogsManagerController::$PER_PAGE_LOGS)) { $lineCounter++; } @@ -97,7 +87,8 @@ public function tail($lines = 100, bool $skipEmptyLines = true): array { * * @return array */ - public function parse(array $lines): array { + public function parse(array $lines): array + { $lines = array_map(static function ($log) { $log = (new LineLogParser)->parse($log); @@ -110,5 +101,4 @@ public function parse(array $lines): array { return array_filter($lines, 'count'); } - } diff --git a/src/LogManager/LogTrunkCache.php b/src/LogManager/LogTrunkCache.php index 6009260..629f65b 100644 --- a/src/LogManager/LogTrunkCache.php +++ b/src/LogManager/LogTrunkCache.php @@ -1,21 +1,15 @@ - * - * @package EzPlatformLogsUi\Bundle\LogManager - */ -class LogTrunkCache { - - /** @var CacheInterface */ +namespace IbexaLogsUi\Bundle\LogManager; + +use IbexaLogsUi\Bundle\Controller\LogsManagerController; +use Psr\Cache\InvalidArgumentException; +use Symfony\Component\Cache\Adapter\FilesystemAdapter; +use Symfony\Component\Cache\CacheItem; + +class LogTrunkCache +{ + /** @var FilesystemAdapter */ private $cacheSystem; /** @var string */ @@ -24,112 +18,85 @@ class LogTrunkCache { /** @var string */ private $cacheNamespace; - /** - * LogTrunkCache constructor. - * - * @param string $logPath - * @param string $cacheDirectory - * @param string $cacheNamespace - */ - public function __construct(string $logPath, string $cacheDirectory, string $cacheNamespace = '') { + public function __construct(string $logPath, string $cacheDirectory, string $cacheNamespace = '') + { $this->logPath = $logPath; $this->cacheNamespace = $cacheNamespace; - - $this->cacheSystem = new FilesystemCache($cacheNamespace, 0, $cacheDirectory); + $this->cacheSystem = new FilesystemAdapter($cacheNamespace, 0, $cacheDirectory); } - /** - * @param string $subject - * - * @return string - */ - public function getCacheKey(string $subject = 'logs'): string { + public function getCacheKey(string $subject = 'logs'): string + { return $this->cacheNamespace . '.' . $subject . '.' . md5($this->logPath); } - /** - * @param int $chunkId - * - * @return string - */ - public function getChunkIdentifier(int $chunkId): string { + public function getChunkIdentifier(int $chunkId): string + { return $this->getCacheKey() . '.chunk.' . $chunkId; } - /** - * Determines whether an item is present in the cache. - * - * @param int $chunkId - * - * @return bool - */ - public function hasChunk(int $chunkId): bool { + public function hasChunk(int $chunkId): bool + { try { - return $this->cacheSystem->has($this->getChunkIdentifier($chunkId)); + /** @var CacheItem $cacheItem */ + $cacheItem = $this->cacheSystem->getItem($this->getChunkIdentifier($chunkId)); + + return $cacheItem->isHit(); } catch (InvalidArgumentException $e) { return false; } } - /** - * Fetches a value from the cache. - * - * @param int $chunkId - * @param null $default - * - * @return mixed - */ - public function getChunk(int $chunkId, $default = null) { + public function getChunk(int $chunkId, $default = null) + { try { - return $this->cacheSystem->get($this->getChunkIdentifier($chunkId), $default); + /** @var CacheItem $cacheItem */ + $cacheItem = $this->cacheSystem->getItem($this->getChunkIdentifier($chunkId)); + + if ($cacheItem->isHit()) { + return $cacheItem->get(); + } + + return $default; } catch (InvalidArgumentException $e) { return false; } } - /** - * @param int $currentChunkId - * @param int $total - * @param null $default - * - * @return bool|mixed|null - */ - public function getLastChunk(int $currentChunkId, int $total, $default = null) { + public function getLastChunk(int $currentChunkId, int $total, $default = null) + { try { - $lastChunkCacheKey = $this->getChunkIdentifier(ceil($total / 20) - ($currentChunkId - 1)); + $lastChunkCacheKey = $this->getChunkIdentifier(ceil($total / LogsManagerController::$PER_PAGE_LOGS) - ($currentChunkId - 1)); + + /** @var CacheItem $cacheItem */ + $cacheItem = $this->cacheSystem->getItem($lastChunkCacheKey); + + if ($cacheItem->isHit()) { + return $cacheItem->get(); + } - return $this->cacheSystem->get($lastChunkCacheKey, $default); + return $default; } catch (InvalidArgumentException $e) { return false; } } - /** - * Persists data in the cache, uniquely referenced by a key with an optional expiration TTL time. - * - * @param int $chunkId - * @param mixed $value - * @param null|int|\DateInterval $ttl - * - * @return bool - */ - public function setChunk(int $chunkId, $value, $ttl = 7200): bool { + public function setChunk(int $chunkId, $value, $ttl = 300): bool + { try { - return $this->cacheSystem->set($this->getChunkIdentifier($chunkId), $value, $ttl); + /** @var CacheItem $cacheItem */ + $cacheItem = $this->cacheSystem->getItem($this->getChunkIdentifier($chunkId)); + $cacheItem->set($value)->expiresAfter($ttl); + + return $this->cacheSystem->save($cacheItem); } catch (InvalidArgumentException $e) { return false; } } - /** - * Deletes multiple cache items in a single operation. - * - * @param int $total - * - * @return bool - */ - public function clearChunks(int $total): bool { - $numberOfChunks = ceil($total / 20); + public function clearChunks(int $total): bool + { + $numberOfChunks = ceil($total / LogsManagerController::$PER_PAGE_LOGS); $chunkCacheKeys = []; for ($chunkId = 1; $chunkId <= $numberOfChunks; $chunkId++) { @@ -137,17 +104,14 @@ public function clearChunks(int $total): bool { } try { - return $this->cacheSystem->deleteMultiple($chunkCacheKeys); + return $this->cacheSystem->deleteItems($chunkCacheKeys); } catch (InvalidArgumentException $e) { return false; } } - /** - * @return CacheInterface - */ - public function getCacheSystem(): CacheInterface { + public function getCacheSystem(): FilesystemAdapter + { return $this->cacheSystem; } - } diff --git a/src/Parser/LineLogParser.php b/src/Parser/LineLogParser.php index 0593f2c..9795b88 100644 --- a/src/Parser/LineLogParser.php +++ b/src/Parser/LineLogParser.php @@ -1,32 +1,21 @@ - * - * @package EzPlatformLogsUi\Bundle\Parser - */ -class LineLogParser { - +class LineLogParser +{ /** @var string */ - private const PARSER_PATTERN = '/\[(?P.*)\] (?P\w+).(?P\w+): (?P.*[^ ]+) (?P[^ ]+) (?P[^ ]+)/'; + private const PARSER_PATTERN = '/\[(?.*?)\] (?\w+).(?\w+): (?[^\[\{]+) (?[\[\{].*[\]\}]) (?[\[\{].*[\]\}])/'; /** @var array */ private const PARSER_GROUPS = ['date', 'logger', 'level', 'message', 'context', 'extra']; - /** - * @param string $log - * - * @return array - */ - public function parse(string $log): array { + public function parse(string $log): array + { try { - if (!is_string($log) || $log === '') { + if ($log === '') { return []; } @@ -41,17 +30,20 @@ public function parse(string $log): array { } } + // Json extract + $jsonContext = $matches['context'] === '[]' ? [] : json_decode($matches['context'], true, 2); + $jsonExtra = $matches['extra'] === '[]' ? [] : json_decode($matches['extra'], true, 2); + return [ - 'date' => $matches['date'], - 'logger' => $matches['logger'], - 'level' => $matches['level'], + 'date' => $matches['date'], + 'logger' => $matches['logger'], + 'level' => $matches['level'], 'message' => $matches['message'], - 'context' => $matches['context'], - 'extra' => $matches['extra'] + 'context' => !$jsonContext && $jsonContext !== [] ? [$matches['context']] : $jsonContext, + 'extra' => !$jsonExtra && $jsonExtra !== [] ? [$matches['extra']] : $jsonExtra, ]; } catch (Exception $exception) { return []; } } - } diff --git a/src/Resources/config/menu.yml b/src/Resources/config/menu.yml deleted file mode 100644 index 0dc619c..0000000 --- a/src/Resources/config/menu.yml +++ /dev/null @@ -1,9 +0,0 @@ -services: - _defaults: - autowire: true - autoconfigure: true - public: true - - EzPlatformLogsUi\Bundle\EventListener\AdminMenuListener: - tags: - - { name: kernel.event_subscriber } diff --git a/src/Resources/config/policies.yml b/src/Resources/config/policies.yml index e76f3f3..1145714 100644 --- a/src/Resources/config/policies.yml +++ b/src/Resources/config/policies.yml @@ -1,3 +1,2 @@ -ezplatform_logs_ui: - read_logs: ~ - reload_logs: ~ +ibexa_logs_ui: + view: ~ diff --git a/src/Resources/config/routing.yml b/src/Resources/config/routing.yml index 0fab085..21ca4ef 100644 --- a/src/Resources/config/routing.yml +++ b/src/Resources/config/routing.yml @@ -1,9 +1,9 @@ -ezplatform_logs_ui_index: - path: /ezplatform-logs-ui/{chunkId} - defaults: { _controller: EzPlatformLogsUiBundle:LogsManager:index, chunkId: 1 } +ibexa_logs_ui_index: + path: /ibexa-logs-ui/{chunkId} + defaults: { _controller: IbexaLogsUi\Bundle\Controller\LogsManagerController::index, chunkId: 1 } requirements: chunkId: '\d+' -ezplatform_logs_ui_reload: - path: /ezplatform-logs-ui/reload - defaults: { _controller: EzPlatformLogsUiBundle:LogsManager:reload } +ibexa_logs_ui_reload: + path: /ibexa-logs-ui/reload + defaults: { _controller: IbexaLogsUi\Bundle\Controller\LogsManagerController::reload } diff --git a/src/Resources/config/services.yml b/src/Resources/config/services.yml index ca9c668..9b70a4b 100644 --- a/src/Resources/config/services.yml +++ b/src/Resources/config/services.yml @@ -1,7 +1,17 @@ services: - EzPlatformLogsUi\Bundle\Controller\: - resource: '../../Controller/*' - autowire: true - autoconfigure: true + _defaults: public: false - exclude: '../../Controller/{Controller}' + + IbexaLogsUi\Bundle\Controller\LogsManagerController: + tags: + - { name: controller.service_arguments } + arguments: + $kernelCacheDir: '%kernel.cache_dir%' + $monologLogger: '@monolog.logger' + calls: + - [ 'setContainer', [ '@service_container' ] ] + - [ 'performAccessCheck', [ ] ] + + IbexaLogsUi\Bundle\EventSubscriber\MenuSubscriber: + tags: + - { name: kernel.event_subscriber } diff --git a/src/Resources/translations/forms.en.yaml b/src/Resources/translations/forms.en.yaml new file mode 100644 index 0000000..8f90f38 --- /dev/null +++ b/src/Resources/translations/forms.en.yaml @@ -0,0 +1,3 @@ +role.policy.ibexa_logs_ui: Logs +role.policy.ibexa_logs_ui.all_functions: Logs / All functions +role.policy.ibexa_logs_ui.view: Logs / View diff --git a/src/Resources/translations/forms.fr.yaml b/src/Resources/translations/forms.fr.yaml new file mode 100644 index 0000000..fcf1bce --- /dev/null +++ b/src/Resources/translations/forms.fr.yaml @@ -0,0 +1,3 @@ +role.policy.ibexa_logs_ui: Logs +role.policy.ibexa_logs_ui.all_functions: Logs / Toutes les fonctions +role.policy.ibexa_logs_ui.view: Logs / Voir diff --git a/src/Resources/translations/messages.en.yaml b/src/Resources/translations/messages.en.yaml new file mode 100644 index 0000000..dafb53b --- /dev/null +++ b/src/Resources/translations/messages.en.yaml @@ -0,0 +1,9 @@ +logs_ui.menu.label: 'Logs' +logs_ui.text.reload: 'Reload' +logs_ui.text.log_path: 'Path:' +logs_ui.text.last_message: 'Last message:' +logs_ui.text.show_more: 'Show more' +logs_ui.text.is_empty: 'The log file seems empty' +logs_ui.text.context: 'Context:' +logs_ui.text.extra: 'Extra:' +logs_ui.text.pagination: 'Display of %perPage% lines out of %total% in total.' diff --git a/src/Resources/translations/messages.fr.yaml b/src/Resources/translations/messages.fr.yaml new file mode 100644 index 0000000..8022f95 --- /dev/null +++ b/src/Resources/translations/messages.fr.yaml @@ -0,0 +1,9 @@ +logs_ui.menu.label: 'Logs' +logs_ui.text.reload: 'Rafraichir' +logs_ui.text.log_path: 'Chemin :' +logs_ui.text.last_message: 'Dernier message :' +logs_ui.text.show_more: 'Voir plus' +logs_ui.text.is_empty: 'Le fichier de log semble vide' +logs_ui.text.context: 'Contexte :' +logs_ui.text.extra: 'Extra :' +logs_ui.text.pagination: 'Affichage de %perPage% lignes sur %total% au total.' diff --git a/src/Resources/views/logs/index.html.twig b/src/Resources/views/logs/index.html.twig deleted file mode 100644 index 0f21518..0000000 --- a/src/Resources/views/logs/index.html.twig +++ /dev/null @@ -1,89 +0,0 @@ -{% extends 'EzPlatformAdminUiBundle::layout.html.twig' %} - -{% block breadcrumbs %} - {% include '@EzPlatformAdminUi/parts/breadcrumbs.html.twig' with { items: [ - { value: 'breadcrumb.admin'|trans(domain='messages')|desc('Admin') }, - { value: 'EzPlatform Logs' }, - ]} %} -{% endblock %} - -{% block title %}EzPlatform Logs{% endblock %} - -{% block page_title %} - {% include '@EzPlatformAdminUi/parts/page_title.html.twig' with { - title: 'EzPlatform Logs', - iconName: 'contentlist' - } %} -{% endblock %} - -{% block content %} -

- - {% if logPath is not null %} -
- - Last message: {{ logs is defined and logs|length != 0 ? logs|first.date : '(No message)' }} - Click - here - to load the latest logs - - {{ logPath }} -
- {% endif %} - -
-
Logs
-
- - {% if logs is not defined or logs|length == 0 %} -

- The log file seems empty... -
- LogPath: {{ logPath ?? 'NULL' }} -

- {% else %} - - - - - - - - - - {% for log in logs %} - - - - - - {% endfor %} - -
DateLoggerMessage
{{ log.date|raw }} - - {{ log.logger }}.{{ log.level }} - - - {{ log.message }} -
- Context, Extra - Context: {{ log.context }} - Extra: {{ log.extra }} -
-
- - {% from '@EzPlatformLogsUi/parts/_pagination.html.twig' import pagination %} - {{ pagination((total / 20)|round(0, 'ceil'), currentChunkId, path('ezplatform_logs_ui_index') ~ '/') }} - {% endif %} - -
- - -{% endblock %} diff --git a/src/Resources/views/parts/_pagination.html.twig b/src/Resources/views/parts/_pagination.html.twig deleted file mode 100644 index 7564aa7..0000000 --- a/src/Resources/views/parts/_pagination.html.twig +++ /dev/null @@ -1,43 +0,0 @@ -{% macro pagination(total, current, url, nearbyPagesLimit = 4) %} - {% spaceless %} - {% if total > 1 %} - - {% endif %} - {% endspaceless %} -{% endmacro %} diff --git a/src/Resources/views/themes/admin/logs/logs.html.twig b/src/Resources/views/themes/admin/logs/logs.html.twig new file mode 100644 index 0000000..f88420c --- /dev/null +++ b/src/Resources/views/themes/admin/logs/logs.html.twig @@ -0,0 +1,128 @@ +{% extends ['@ezdesign/layout.html.twig', '@ezdesign/ui/layout.html.twig'] %} + +{% block breadcrumbs %} + {% include ['@ezdesign/parts/breadcrumbs.html.twig', '@ezdesign/ui/breadcrumbs.html.twig'] with { items: [ + { value: 'breadcrumb.admin'|trans(domain='messages')|desc('Admin') }, + { value: 'logs_ui.menu.label'|trans } + ]} %} +{% endblock %} + +{% block page_title %} + {% include ['@ezdesign/parts/page_title.html.twig', '@ezdesign/ui/page_title.html.twig'] with { + title: 'logs_ui.menu.label'|trans, + iconName: 'contentlist' + } %} +{% endblock %} + +{% block content %} +
+
+
+
+
+ {{ 'logs_ui.text.last_message'|trans }} {{ logs is not empty ? logs|first|first.date|date('d/m/Y H:i') : 'logs_ui.text.is_empty'|trans }} +
+ {{ logPath }} +
+ +
+ + {% if logs is empty %} +

+ {{ 'logs_ui.text.is_empty'|trans }} +
+ {{ 'logs_ui.text.log_path' }} {{ logPath }} +

+ {% endif %} + + +
+
+ +
+ {% for level, filtered_logs in logs %} + {% set active = loop.first %} +
+ {% if perPageLogs < total %} +
+ {% if currentChunkId != 1 %} + Page {{ currentChunkId }}. + {% endif %} + {{ 'logs_ui.text.pagination'|trans({'%perPage%': perPageLogs|number_format(0, ',', ' '), '%total%': total|number_format(0, ',', ' ')})|raw }} +
+ {% endif %} + + + + + + + + + + + {% for log in filtered_logs %} + + + + + + {% endfor %} + +
DateLoggerMessage
{{ log.date|date('d/m/Y H:i:s') }} +
+ {{ log.logger }}.{{ log.level }} +
+
+ {{ log.message }} + {% if log.context is not empty or log.extra is not empty %} +
+ {{ 'logs_ui.text.show_more'|trans }} + {% if log.context is not empty %} +
+ {{ 'logs_ui.text.context'|trans }}  + {% for key, value in log.context %} + + "{{ key }}" => + "{{ value is null ? 'null' : value }}" + + {% endfor %} +
+ {% endif %} + {% if log.extra is not empty %} +
+ {{ 'logs_ui.text.extra'|trans }}  + {% for key, value in log.extra %} + + "{{ key }}" => + "{{ value is null ? 'null' : value }}" + + {% endfor %} +
+ {% endif %} +
+ {% endif %} +
+
+ {% endfor %} + + {% from '@ezdesign/logs/pagination.html.twig' import pagination %} + {{ pagination((total / perPageLogs)|round(0, 'ceil'), currentChunkId, path('ibexa_logs_ui_index') ~ '/', perPageLogs, total) }} +
+{% endblock %} diff --git a/src/Resources/views/themes/admin/logs/pagination.html.twig b/src/Resources/views/themes/admin/logs/pagination.html.twig new file mode 100644 index 0000000..5b2d760 --- /dev/null +++ b/src/Resources/views/themes/admin/logs/pagination.html.twig @@ -0,0 +1,42 @@ +{% macro pagination(pages, current, url, perPageLogs, total, nearbyPagesLimit = 4) %} + {% if pages > 1 %} +
+
+ {{ 'logs_ui.text.pagination'|trans({'%perPage%': perPageLogs|number_format(0, ',', ' '), '%total%': total|number_format(0, ',', ' ')})|raw }} +
+
    + {% for i in 1..pages %} + {% if 0 == (current - nearbyPagesLimit) - loop.index %} +
  • + 1 +
  • + {% if 1 != loop.index %} +
  • + +
  • + {% endif %} + {% elseif 0 == (current + nearbyPagesLimit) - loop.index and (current + nearbyPagesLimit) < pages %} +
  • + +
  • + {% elseif 0 < (current - nearbyPagesLimit) - loop.index %} + {% elseif 0 > (current + nearbyPagesLimit) - loop.index %} + {% else %} +
  • + {% if current == loop.index %} + + {% else %} + {{ loop.index }} + {% endif %} +
  • + {% endif %} + {% endfor %} + {% if current != pages and (current + nearbyPagesLimit) < pages %} +
  • + {{ pages }} +
  • + {% endif %} +
+
+ {% endif %} +{% endmacro %} diff --git a/src/Security/LogsUiProvider.php b/src/Security/LogsUiProvider.php index 5218ad0..d666b40 100644 --- a/src/Security/LogsUiProvider.php +++ b/src/Security/LogsUiProvider.php @@ -1,27 +1,16 @@ - * - * @package EzPlatformLogsUi\Bundle\Security - */ -class LogsUiProvider extends YamlPolicyProvider { - +class LogsUiProvider extends YamlPolicyProvider +{ /** - * YAML based policy provider. - * - * @return array + * {@inheritdoc} */ - protected function getFiles(): array { - return [ - __DIR__ . '/../Resources/config/policies.yml' - ]; + protected function getFiles(): array + { + return [__DIR__ . '/../Resources/config/policies.yml']; } - } diff --git a/tests/LogFileTest.php b/tests/LogFileTest.php index 1c9bbe3..6cf6f1a 100644 --- a/tests/LogFileTest.php +++ b/tests/LogFileTest.php @@ -1,19 +1,12 @@ - * - * @package EzPlatformLogsUi\Tests - */ -class LogFileTest extends TestCase { - +class LogFileTest extends TestCase +{ /** @var LogFile */ private $validLogFile; @@ -23,7 +16,8 @@ class LogFileTest extends TestCase { /** @var LogFile[] */ private $invalidLogFiles = []; - public function setUp(): void { + public function setUp(): void + { $logsPath = __DIR__ . DIRECTORY_SEPARATOR . 'logs' . DIRECTORY_SEPARATOR; $this->validLogFile = new LogFile($logsPath . 'valid.log'); @@ -31,11 +25,12 @@ public function setUp(): void { $this->invalidLogFiles = [ 'partially' => new LogFile($logsPath . 'partially-invalid.log'), - 'full' => new LogFile($logsPath . 'full-invalid.log'), + 'full' => new LogFile($logsPath . 'full-invalid.log'), ]; } - public function testValidLogFileReadingAndParsing(): void { + public function testValidLogFileReadingAndParsing(): void + { $lastLines = [ '[2019-06-23 16:20:29] php.INFO: User Deprecated: Checking for the initialization of the "ezpublish.siteaccessaware.service.object_state" private service is deprecated since Symfony 3.4 and won\'t be supported anymore in Symfony 4.0. {"exception":"[object] (ErrorException(code: 0): User Deprecated: Checking for the initialization of the \"ezpublish.siteaccessaware.service.object_state\" private service is deprecated since Symfony 3.4 and won\'t be supported anymore in Symfony 4.0. at ezplatform\\\\vendor\\\\symfony\\\\symfony\\\\src\\\\Symfony\\\\Component\\\\DependencyInjection\\\\Container.php:364)"} []', '[2019-06-23 16:20:29] php.INFO: User Deprecated: Checking for the initialization of the "ezpublish.siteaccessaware.service.content_type" private service is deprecated since Symfony 3.4 and won\'t be supported anymore in Symfony 4.0. {"exception":"[object] (ErrorException(code: 0): User Deprecated: Checking for the initialization of the \"ezpublish.siteaccessaware.service.content_type\" private service is deprecated since Symfony 3.4 and won\'t be supported anymore in Symfony 4.0. at ezplatform\\\\vendor\\\\symfony\\\\symfony\\\\src\\\\Symfony\\\\Component\\\\DependencyInjection\\\\Container.php:364)"} []', @@ -51,17 +46,18 @@ public function testValidLogFileReadingAndParsing(): void { $this->assertIsArray($lines); $this->assertCount(32, $lines); $this->assertSame([ - 'date' => '2019-06-23 16:20:29', - 'logger' => 'php', - 'level' => 'INFO', - 'message' => 'User Deprecated: Checking for the initialization of the "ezpublish.siteaccessaware.service.object_state" private service is deprecated since Symfony 3.4 and won\'t be supported anymore in Symfony 4.0. {"exception":"[object] (ErrorException(code: 0): User Deprecated: Checking for the initialization of the \"ezpublish.siteaccessaware.service.object_state\" private service is deprecated since Symfony 3.4 and won\'t be supported anymore in Symfony 4.0. at', - 'context' => 'ezplatform\\\\vendor\\\\symfony\\\\symfony\\\\src\\\\Symfony\\\\Component\\\\DependencyInjection\\\\Container.php:364)"}', - 'extra' => '[]', - 'class' => 'info' + 'date' => '2019-06-23 16:20:29', + 'logger' => 'php', + 'level' => 'INFO', + 'message' => 'User Deprecated: Checking for the initialization of the "ezpublish.siteaccessaware.service.object_state" private service is deprecated since Symfony 3.4 and won\'t be supported anymore in Symfony 4.0.', + 'context' => ['exception' => '[object] (ErrorException(code: 0): User Deprecated: Checking for the initialization of the "ezpublish.siteaccessaware.service.object_state" private service is deprecated since Symfony 3.4 and won\'t be supported anymore in Symfony 4.0. at ezplatform\\vendor\\symfony\\symfony\\src\\Symfony\\Component\\DependencyInjection\\Container.php:364)'], + 'extra' => [], + 'class' => 'info' ], $lines[0]); } - public function testEmptyLogFileReadingAndParsing(): void { + public function testEmptyLogFileReadingAndParsing(): void + { $lines = $this->emptyLogFile->tail(); $this->assertIsArray($lines); $this->assertEmpty($lines); @@ -71,7 +67,8 @@ public function testEmptyLogFileReadingAndParsing(): void { $this->assertEmpty($lines); } - public function testInvalidLogFileReadingAndParsing(): void { + public function testInvalidLogFileReadingAndParsing(): void + { // Partially invalid $lines = $this->invalidLogFiles['partially']->tail(); $this->assertIsArray($lines); @@ -90,5 +87,4 @@ public function testInvalidLogFileReadingAndParsing(): void { $this->assertIsArray($lines); $this->assertEmpty($lines); } - } diff --git a/tests/LogTrunkCacheTest.php b/tests/LogTrunkCacheTest.php index 0f760c5..8fbe811 100644 --- a/tests/LogTrunkCacheTest.php +++ b/tests/LogTrunkCacheTest.php @@ -1,54 +1,52 @@ - * - * @package EzPlatformLogsUi\Tests - */ -class LogTrunkCacheTest extends TestCase { - +class LogTrunkCacheTest extends TestCase +{ /** @var string */ private const LOG_FILE_PATH = __DIR__ . DIRECTORY_SEPARATOR . 'logs' . DIRECTORY_SEPARATOR . 'valid.log'; /** @var LogTrunkCache */ private $logTrunkCache; - public function setUp(): void { + public function setUp(): void + { $logsPath = self::LOG_FILE_PATH; $cacheDirectory = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'symfony-cache'; - $this->logTrunkCache = new LogTrunkCache($logsPath, $cacheDirectory, 'ezplatform_logs_ui_tests'); + $this->logTrunkCache = new LogTrunkCache($logsPath, $cacheDirectory, 'ibexa_logs_ui_tests'); } - public function testGetCacheKeyMethod(): void { + public function testGetCacheKeyMethod(): void + { $encodedLogFilPath = md5(self::LOG_FILE_PATH); - $this->assertSame('ezplatform_logs_ui_tests.logs.' . $encodedLogFilPath, $this->logTrunkCache->getCacheKey()); - $this->assertSame('ezplatform_logs_ui_tests.tests.' . $encodedLogFilPath, $this->logTrunkCache->getCacheKey('tests')); + $this->assertSame('ibexa_logs_ui_tests.logs.' . $encodedLogFilPath, $this->logTrunkCache->getCacheKey()); + $this->assertSame('ibexa_logs_ui_tests.tests.' . $encodedLogFilPath, + $this->logTrunkCache->getCacheKey('tests')); } - public function testGetChunkIdentifierMethod(): void { + public function testGetChunkIdentifierMethod(): void + { $encodedLogFilPath = md5(self::LOG_FILE_PATH); $this->assertSame( - 'ezplatform_logs_ui_tests.logs.' . $encodedLogFilPath . '.chunk.1', + 'ibexa_logs_ui_tests.logs.' . $encodedLogFilPath . '.chunk.1', $this->logTrunkCache->getChunkIdentifier(1) ); $this->assertSame( - 'ezplatform_logs_ui_tests.logs.' . $encodedLogFilPath . '.chunk.123', + 'ibexa_logs_ui_tests.logs.' . $encodedLogFilPath . '.chunk.123', $this->logTrunkCache->getChunkIdentifier(123) ); } - public function testSetChunkMethod(): void { + public function testSetChunkMethod(): void + { // With default TTL $this->assertTrue($this->logTrunkCache->setChunk(1, 123)); @@ -56,19 +54,20 @@ public function testSetChunkMethod(): void { $this->assertTrue($this->logTrunkCache->setChunk(2, 456, 1000)); } - public function testHasChunkMethod(): void { + public function testHasChunkMethod(): void + { $this->assertTrue($this->logTrunkCache->hasChunk(1)); $this->assertTrue($this->logTrunkCache->hasChunk(2)); $this->assertFalse($this->logTrunkCache->hasChunk(3)); } - public function testGetChunkMethod(): void { + public function testGetChunkMethod(): void + { $this->assertSame($this->logTrunkCache->getChunk(1), 123); $this->assertSame($this->logTrunkCache->getChunk(2), 456); $this->assertNull($this->logTrunkCache->getChunk(3)); $this->assertSame($this->logTrunkCache->getChunk(3, 789), 789); } - } diff --git a/tests/logs/partially-invalid.log b/tests/logs/partially-invalid.log index 1de66f3..4bb43c7 100644 --- a/tests/logs/partially-invalid.log +++ b/tests/logs/partially-invalid.log @@ -1,17 +1,17 @@ [2019-06-23 16:20:06] app.WARNING: ConfigResolver was used by "ezplatform\var\cache\dev\ContainerAxajx6t\getConsole_Command_EzsystemsEzplatformgraphqlCommandGenerateplatformschemacommand(@ezpublish.siteaccessaware.service.content_type)" before SiteAccess was initialized, loading parameter(s) "$languages$". As this can cause very hard to debug issues, try to use ConfigResolver lazily, make the affected commands lazy, make the service lazy or see if you can inject another lazy service. [] [] [2019-06-23 16:20:06] app.DEBUG: Changing SiteAccess in view providers [] [] -[2019-06-23 16:20:29] php.INFO: User Deprecated: The "ezpublish.siteaccess" service is private, getting it from the container is deprecated since Symfony 3.2 and will fail in 4.0. You should either make the service public, or stop using the container directly and use dependency injection instead. {"exception":"[object] (ErrorException(code: 0): User Deprecated: The \"ezpublish.siteaccess\" service is private, getting it from the container is deprecated since Symfony 3.2 and will fail in 4.0. You should either make the service public, or stop using the container directly and use dependency injection instead. at ezplatform\\vendor\\symfony\\symfony\\src\\Symfony\\Component\\DependencyInjection\\Container.php:282)"} -[2019-06-23 16:20:29] php.INFO: User Deprecated: Checking for the initialization of the "ezplatform.view_cache.response_configurator" private service is deprecated since Symfony 3.4 and won't be supported anymore in Symfony 4.0. {"exception":"[object] (ErrorException(code: 0): User Deprecated: Checking for the initialization of the \"ezplatform.view_cache.response_configurator\" private service is deprecated since Symfony 3.4 and won't be supported anymore in Symfony 4.0. at ezplatform\\vendor\\symfony\\symfony\\src\\Symfony\\Component\\DependencyInjection\\Container.php:364)"} -[2019-06-23 16:20:29] php.INFO: User Deprecated: Checking for the initialization of the "ezpublish.signalslot.signal_dispatcher.factory" private service is deprecated since Symfony 3.4 and won't be supported anymore in Symfony 4.0. {"exception":"[object] (ErrorException(code: 0): User Deprecated: Checking for the initialization of the \"ezpublish.signalslot.signal_dispatcher.factory\" private service is deprecated since Symfony 3.4 and won't be supported anymore in Symfony 4.0. at ezplatform\\vendor\\symfony\\symfony\\src\\Symfony\\Component\\DependencyInjection\\Container.php:364)"} -[2019-06-23 16:20:29] php.INFO: User Deprecated: Checking for the initialization of the "ezpublish.helper.language_resolver" private service is deprecated since Symfony 3.4 and won't be supported anymore in Symfony 4.0. {"exception":"[object] (ErrorException(code: 0): User Deprecated: Checking for the initialization of the \"ezpublish.helper.language_resolver\" private service is deprecated since Symfony 3.4 and won't be supported anymore in Symfony 4.0. at ezplatform\\vendor\\symfony\\symfony\\src\\Symfony\\Component\\DependencyInjection\\Container.php:364)"} +[2019-06-23 16:20:29] php.INFO: User Deprecated: The "ezpublish.siteaccess" service is private, getting it from the container is deprecated since Symfony 3.2 and will fail in 4.0. You should either make the service public, or stop using the container directly and use dependency injection instead. {"exception":"[object] (ErrorException(code: 0): User Deprecated: The \"ezpublish.siteaccess\" service is private, getting it from the container is deprecated since Symfony 3.2 and will fail in 4.0. You should either make the service public, or stop using the container directly and use dependency injection instead. at ezplatform\\vendor\\symfony\\symfony\\src\\Symfony\\Component\\DependencyInjection\\Container.php:282)"} [] +[2019-06-23 16:20:29] php.INFO: User Deprecated: Checking for the initialization of the "ezplatform.view_cache.response_configurator" private service is deprecated since Symfony 3.4 and won't be supported anymore in Symfony 4.0. {"exception":"[object] (ErrorException(code: 0): User Deprecated: Checking for the initialization of the \"ezplatform.view_cache.response_configurator\" private service is deprecated since Symfony 3.4 and won't be supported anymore in Symfony 4.0. at ezplatform\\vendor\\symfony\\symfony\\src\\Symfony\\Component\\DependencyInjection\\Container.php:364)"} [] [] +[2019-06-23 16:20:29] php.INFO: User Deprecated: Checking for the initialization of the "ezpublish.signalslot.signal_dispatcher.factory" private service is deprecated since Symfony 3.4 and won't be supported anymore in Symfony 4.0. {"exception":"[object] (ErrorException(code: 0): User Deprecated: Checking for the initialization of the \"ezpublish.signalslot.signal_dispatcher.factory\" private service is deprecated since Symfony 3.4 and won't be supported anymore in Symfony 4.0. at ezplatform\\vendor\\symfony\\symfony\\src\\Symfony\\Component\\DependencyInjection\\Container.php:364)"} [] [] +[2019-06-23 16:20:29] php.INFO: User Deprecated: Checking for the initialization of the "ezpublish.helper.language_resolver" private service is deprecated since Symfony 3.4 and won't be supported anymore in Symfony 4.0. {"exception":"[object] (ErrorException(code: 0): User Deprecated: Checking for the initialization of the \"ezpublish.helper.language_resolver\" private service is deprecated since Symfony 3.4 and won't be supported anymore in Symfony 4.0. at ezplatform\\vendor\\symfony\\symfony\\src\\Symfony\\Component\\DependencyInjection\\Container.php:364)"} [] php.INFO: User Deprecated: Checking for the initialization of the "ezpublish.core.io.flysystem.default_adapter" private service is deprecated since Symfony 3.4 and won't be supported anymore in Symfony 4.0. {"exception":"[object] (ErrorException(code: 0): User Deprecated: Checking for the initialization of the \"ezpublish.core.io.flysystem.default_adapter\" private service is deprecated since Symfony 3.4 and won't be supported anymore in Symfony 4.0. at ezplatform\\vendor\\symfony\\symfony\\src\\Symfony\\Component\\DependencyInjection\\Container.php:364)"} php.INFO: User Deprecated: Checking for the initialization of the "eZ\Publish\Core\FieldType\ImageAsset\AssetMapper" private service is deprecated since Symfony 3.4 and won't be supported anymore in Symfony 4.0. {"exception":"[object] (ErrorException(code: 0): User Deprecated: Checking for the initialization of the \"eZ\\Publish\\Core\\FieldType\\ImageAsset\\AssetMapper\" private service is deprecated since Symfony 3.4 and won't be supported anymore in Symfony 4.0. at ezplatform\\vendor\\symfony\\symfony\\src\\Symfony\\Component\\DependencyInjection\\Container.php:364)"} php.INFO: User Deprecated: Checking for the initialization of the "ezpublish.image_alias.variation_purger.legacy_storage_image_file.image_file_list" private service is deprecated since Symfony 3.4 and won't be supported anymore in Symfony 4.0. {"exception":"[object] (ErrorException(code: 0): User Deprecated: Checking for the initialization of the \"ezpublish.image_alias.variation_purger.legacy_storage_image_file.image_file_list\" private service is deprecated since Symfony 3.4 and won't be supported anymore in Symfony 4.0. at ezplatform\\vendor\\symfony\\symfony\\src\\Symfony\\Component\\DependencyInjection\\Container.php:364)"} -php.INFO: User Deprecated: Checking for the initialization of the "ezpublish.core.io.metadata_handler" private service is deprecated since Symfony 3.4 and won't be supported anymore in Symfony 4.0. {"exception":"[object] (ErrorException(code: 0): User Deprecated: Checking for the initialization of the \"ezpublish.core.io.metadata_handler\" private service is deprecated since Symfony 3.4 and won't be supported anymore in Symfony 4.0. at ezplatform\\vendor\\symfony\\symfony\\src\\Symfony\\Component\\DependencyInjection\\Container.php:364)"} -php.INFO: User Deprecated: Checking for the initialization of the "ezpublish.core.io.binarydata_handler" private service is deprecated since Symfony 3.4 and won't be supported anymore in Symfony 4.0. {"exception":"[object] (ErrorException(code: 0): User Deprecated: Checking for the initialization of the \"ezpublish.core.io.binarydata_handler\" private service is deprecated since Symfony 3.4 and won't be supported anymore in Symfony 4.0. at ezplatform\\vendor\\symfony\\symfony\\src\\Symfony\\Component\\DependencyInjection\\Container.php:364)"} -php.INFO: User Deprecated: Checking for the initialization of the "ezpublish_rest.root_resource_builder" private service is deprecated since Symfony 3.4 and won't be supported anymore in Symfony 4.0. {"exception":"[object] (ErrorException(code: 0): User Deprecated: Checking for the initialization of the \"ezpublish_rest.root_resource_builder\" private service is deprecated since Symfony 3.4 and won't be supported anymore in Symfony 4.0. at ezplatform\\vendor\\symfony\\symfony\\src\\Symfony\\Component\\DependencyInjection\\Container.php:364)"} -php.INFO: User Deprecated: Checking for the initialization of the "ezrepoforms.user_register.registration_group_loader.configurable" private service is deprecated since Symfony 3.4 and won't be supported anymore in Symfony 4.0. {"exception":"[object] (ErrorException(code: 0): User Deprecated: Checking for the initialization of the \"ezrepoforms.user_register.registration_group_loader.configurable\" private service is deprecated since Symfony 3.4 and won't be supported anymore in Symfony 4.0. at ezplatform\\vendor\\symfony\\symfony\\src\\Symfony\\Component\\DependencyInjection\\Container.php:364)"} -[2019-06-23 16:20:29] php.INFO: User Deprecated: Checking for the initialization of the "ezrepoforms.view_templates_listener" private service is deprecated since Symfony 3.4 and won't be supported anymore in Symfony 4.0. {"exception":"[object] (ErrorException(code: 0): User Deprecated: Checking for the initialization of the \"ezrepoforms.view_templates_listener\" private service is deprecated since Symfony 3.4 and won't be supported anymore in Symfony 4.0. at ezplatform\\vendor\\symfony\\symfony\\src\\Symfony\\Component\\DependencyInjection\\Container.php:364)"} -[2019-06-23 16:20:29] php.INFO: User Deprecated: Checking for the initialization of the "EzSystems\EzPlatformAdminUi\Tab\LocationView\PoliciesTab" private service is deprecated since Symfony 3.4 and won't be supported anymore in Symfony 4.0. {"exception":"[object] (ErrorException(code: 0): User Deprecated: Checking for the initialization of the \"EzSystems\\EzPlatformAdminUi\\Tab\\LocationView\\PoliciesTab\" private service is deprecated since Symfony 3.4 and won't be supported anymore in Symfony 4.0. at ezplatform\\vendor\\symfony\\symfony\\src\\Symfony\\Component\\DependencyInjection\\Container.php:364)"} -[2019-06-23 16:20:29] php.INFO: User Deprecated: Checking for the initialization of the "EzSystems\EzPlatformAdminUi\Tab\LocationView\RolesTab" private service is deprecated since Symfony 3.4 and won't be supported anymore in Symfony 4.0. {"exception":"[object] (ErrorException(code: 0): User Deprecated: Checking for the initialization of the \"EzSystems\\EzPlatformAdminUi\\Tab\\LocationView\\RolesTab\" private service is deprecated since Symfony 3.4 and won't be supported anymore in Symfony 4.0. at ezplatform\\vendor\\symfony\\symfony\\src\\Symfony\\Component\\DependencyInjection\\Container.php:364)"} -[2019-06-23 16:20:29] php.INFO: User Deprecated: Checking for the initialization of the "ezsystems.ezplatform_admin_ui.ui.config.provider.image_variations" private service is deprecated since Symfony 3.4 and won't be supported anymore in Symfony 4.0. {"exception":"[object] (ErrorException(code: 0): User Deprecated: Checking for the initialization of the \"ezsystems.ezplatform_admin_ui.ui.config.provider.image_variations\" private service is deprecated since Symfony 3.4 and won't be supported anymore in Symfony 4.0. at ezplatform\\vendor\\symfony\\symfony\\src\\Symfony\\Component\\DependencyInjection\\Container.php:364)"} +php.INFO: User Deprecated: Checking for the initialization of the "ezpublish.core.io.metadata_handler" private service is deprecated since Symfony 3.4 and won't be supported anymore in Symfony 4.0. {"exception":"[object] (ErrorException(code: 0): User Deprecated: Checking for the initialization of the \"ezpublish.core.io.metadata_handler\" private service is deprecated since Symfony 3.4 and won't be supported anymore in Symfony 4.0. at ezplatform\\vendor\\symfony\\symfony\\src\\Symfony\\Component\\DependencyInjection\\Container.php:364)"} [] +php.INFO: User Deprecated: Checking for the initialization of the "ezpublish.core.io.binarydata_handler" private service is deprecated since Symfony 3.4 and won't be supported anymore in Symfony 4.0. {"exception":"[object] (ErrorException(code: 0): User Deprecated: Checking for the initialization of the \"ezpublish.core.io.binarydata_handler\" private service is deprecated since Symfony 3.4 and won't be supported anymore in Symfony 4.0. at ezplatform\\vendor\\symfony\\symfony\\src\\Symfony\\Component\\DependencyInjection\\Container.php:364)"} [] +php.INFO: User Deprecated: Checking for the initialization of the "ezpublish_rest.root_resource_builder" private service is deprecated since Symfony 3.4 and won't be supported anymore in Symfony 4.0. {"exception":"[object] (ErrorException(code: 0): User Deprecated: Checking for the initialization of the \"ezpublish_rest.root_resource_builder\" private service is deprecated since Symfony 3.4 and won't be supported anymore in Symfony 4.0. at ezplatform\\vendor\\symfony\\symfony\\src\\Symfony\\Component\\DependencyInjection\\Container.php:364)"} [] +php.INFO: User Deprecated: Checking for the initialization of the "ezrepoforms.user_register.registration_group_loader.configurable" private service is deprecated since Symfony 3.4 and won't be supported anymore in Symfony 4.0. {"exception":"[object] (ErrorException(code: 0): User Deprecated: Checking for the initialization of the \"ezrepoforms.user_register.registration_group_loader.configurable\" private service is deprecated since Symfony 3.4 and won't be supported anymore in Symfony 4.0. at ezplatform\\vendor\\symfony\\symfony\\src\\Symfony\\Component\\DependencyInjection\\Container.php:364)"} [] +[2019-06-23 16:20:29] php.INFO: User Deprecated: Checking for the initialization of the "ezrepoforms.view_templates_listener" private service is deprecated since Symfony 3.4 and won't be supported anymore in Symfony 4.0. {"exception":"[object] (ErrorException(code: 0): User Deprecated: Checking for the initialization of the \"ezrepoforms.view_templates_listener\" private service is deprecated since Symfony 3.4 and won't be supported anymore in Symfony 4.0. at ezplatform\\vendor\\symfony\\symfony\\src\\Symfony\\Component\\DependencyInjection\\Container.php:364)"} [] +[2019-06-23 16:20:29] php.INFO: User Deprecated: Checking for the initialization of the "EzSystems\EzPlatformAdminUi\Tab\LocationView\PoliciesTab" private service is deprecated since Symfony 3.4 and won't be supported anymore in Symfony 4.0. {"exception":"[object] (ErrorException(code: 0): User Deprecated: Checking for the initialization of the \"EzSystems\\EzPlatformAdminUi\\Tab\\LocationView\\PoliciesTab\" private service is deprecated since Symfony 3.4 and won't be supported anymore in Symfony 4.0. at ezplatform\\vendor\\symfony\\symfony\\src\\Symfony\\Component\\DependencyInjection\\Container.php:364)"} [] +[2019-06-23 16:20:29] php.INFO: User Deprecated: Checking for the initialization of the "EzSystems\EzPlatformAdminUi\Tab\LocationView\RolesTab" private service is deprecated since Symfony 3.4 and won't be supported anymore in Symfony 4.0. {"exception":"[object] (ErrorException(code: 0): User Deprecated: Checking for the initialization of the \"EzSystems\\EzPlatformAdminUi\\Tab\\LocationView\\RolesTab\" private service is deprecated since Symfony 3.4 and won't be supported anymore in Symfony 4.0. at ezplatform\\vendor\\symfony\\symfony\\src\\Symfony\\Component\\DependencyInjection\\Container.php:364)"} [] +[2019-06-23 16:20:29] php.INFO: User Deprecated: Checking for the initialization of the "ezsystems.ezplatform_admin_ui.ui.config.provider.image_variations" private service is deprecated since Symfony 3.4 and won't be supported anymore in Symfony 4.0. {"exception":"[object] (ErrorException(code: 0): User Deprecated: Checking for the initialization of the \"ezsystems.ezplatform_admin_ui.ui.config.provider.image_variations\" private service is deprecated since Symfony 3.4 and won't be supported anymore in Symfony 4.0. at ezplatform\\vendor\\symfony\\symfony\\src\\Symfony\\Component\\DependencyInjection\\Container.php:364)"} []