From 1ff3cb1cefa1ce50c73b5d180d179fb16a278659 Mon Sep 17 00:00:00 2001 From: GitHub Date: Fri, 24 Nov 2023 11:03:10 +0000 Subject: [PATCH] [tuya-connector] Connector cleanup (#191) --- README.md | 31 ++++--- docs/Home.md | 17 +++- docs/_media/tuya_cloud_user_id.png | Bin 0 -> 75782 bytes src/API/LocalApi.php | 2 +- src/Clients/Discovery.php | 2 +- src/Queue/Consumers/ChannelProperty.php | 58 ++++++------- src/Queue/Consumers/DeviceProperty.php | 24 +++--- src/Queue/Consumers/StoreCloudDevice.php | 26 ------ src/Queue/Consumers/StoreLocalDevice.php | 100 ++++++++++------------- 9 files changed, 114 insertions(+), 146 deletions(-) create mode 100644 docs/_media/tuya_cloud_user_id.png diff --git a/README.md b/README.md index 78e8dee..a9c4bfd 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,17 @@ +

+ FastyBird +

+ # FastyBird IoT Tuya connector -[![Build Status](https://badgen.net/github/checks/FastyBird/tuya-connector/main?cache=300&style=flast-square)](https://github.com/FastyBird/tuya-connector/actions) -[![Licence](https://badgen.net/github/license/FastyBird/tuya-connector?cache=300&style=flast-square)](https://github.com/FastyBird/tuya-connector/blob/main/LICENSE.md) -[![Code coverage](https://badgen.net/coveralls/c/github/FastyBird/tuya-connector?cache=300&style=flast-square)](https://coveralls.io/r/FastyBird/tuya-connector) +[![Build Status](https://img.shields.io/github/actions/workflow/status/FastyBird/tuya-connector/ci.yaml?style=flat-square)](https://github.com/FastyBird/tuya-connector/actions) +[![Licence](https://img.shields.io/github/license/FastyBird/tuya-connector?style=flat-square)](https://github.com/FastyBird/tuya-connector/blob/main/LICENSE.md) +[![Code coverage](https://img.shields.io/coverallsCoverage/github/FastyBird/tuya-connector?style=flat-square)](https://coveralls.io/r/FastyBird/tuya-connector) [![Mutation testing](https://img.shields.io/endpoint?style=flat-square&url=https%3A%2F%2Fbadge-api.stryker-mutator.io%2Fgithub.com%2FFastyBird%2Ftuya-connector%2Fmain)](https://dashboard.stryker-mutator.io/reports/github.com/FastyBird/tuya-connector/main) -![PHP](https://badgen.net/packagist/php/FastyBird/tuya-connector?cache=300&style=flast-square) -[![Latest stable](https://badgen.net/packagist/v/FastyBird/tuya-connector/latest?cache=300&style=flast-square)](https://packagist.org/packages/FastyBird/tuya-connector) -[![Downloads total](https://badgen.net/packagist/dt/FastyBird/tuya-connector?cache=300&style=flast-square)](https://packagist.org/packages/FastyBird/tuya-connector) +![PHP](https://badgen.net/packagist/php/FastyBird/tuya-connector?cache=300&style=flat-square) +[![Latest stable](https://badgen.net/packagist/v/FastyBird/tuya-connector/latest?cache=300&style=flat-square)](https://packagist.org/packages/FastyBird/tuya-connector) +[![Downloads total](https://badgen.net/packagist/dt/FastyBird/tuya-connector?cache=300&style=flat-square)](https://packagist.org/packages/FastyBird/tuya-connector) [![PHPStan](https://img.shields.io/badge/PHPStan-enabled-brightgreen.svg?style=flat-square)](https://github.com/phpstan/phpstan) *** @@ -17,9 +21,6 @@ Tuya connector is extension for [FastyBird](https://www.fastybird.com) [IoT](https://en.wikipedia.org/wiki/Internet_of_things) ecosystem which is integrating [Tuya](https://www.tuya.com) devices. -Tuya Connector is a distributed extension that is developed in [PHP](https://www.php.net), built on the [Nette](https://nette.org) and [Symfony](https://symfony.com) frameworks, -and is licensed under [Apache2](http://www.apache.org/licenses/LICENSE-2.0). - ### Features: - The Tuya Connector offers support for both local and cloud-based communication with Tuya devices, providing users with a versatile and flexible way to connect and control a wide range of Tuya devices in their home or office. @@ -29,6 +30,8 @@ and is licensed under [Apache2](http://www.apache.org/licenses/LICENSE-2.0). - [{JSON:API}](https://jsonapi.org/) schemas for full API access, providing a standardized and consistent way for developers to access and manipulate Tuya device data - Regular updates with new features and bug fixes, ensuring that the Tuya Connector is always up-to-date and reliable. +Tuya Connector is a distributed extension that is developed in [PHP](https://www.php.net), built on the [Nette](https://nette.org) and [Symfony](https://symfony.com) frameworks, +and is licensed under [Apache2](http://www.apache.org/licenses/LICENSE-2.0). ## Requirements @@ -37,19 +40,13 @@ PHP extension. ## Installation -### Manual installation - -The best way to install **fastybird/tuya-connector** is using [Composer](http://getcomposer.org/): +This extension is part of the [FastyBird](https://www.fastybird.com) [IoT](https://en.wikipedia.org/wiki/Internet_of_things) ecosystem and is installed by default. +In case you want to create you own distribution of [FastyBird](https://www.fastybird.com) [IoT](https://en.wikipedia.org/wiki/Internet_of_things) ecosystem you could install this extension with [Composer](http://getcomposer.org/): ```sh composer require fastybird/tuya-connector ``` -### Marketplace installation [WIP] - -You could install this connector in your [FastyBird](https://www.fastybird.com) [IoT](https://en.wikipedia.org/wiki/Internet_of_things) -application under marketplace section. - ## Documentation Learn how to connect Tuya devices and manage them with [FastyBird](https://www.fastybird.com) [IoT](https://en.wikipedia.org/wiki/Internet_of_things) system diff --git a/docs/Home.md b/docs/Home.md index 8390c43..f6c11a1 100644 --- a/docs/Home.md +++ b/docs/Home.md @@ -1,3 +1,7 @@ +

+ FastyBird +

+ The [FastyBird](https://www.fastybird.com) [IoT](https://en.wikipedia.org/wiki/Internet_of_things) Tuya Connector is an extension for the [FastyBird](https://www.fastybird.com) [IoT](https://en.wikipedia.org/wiki/Internet_of_things) ecosystem that enables seamless integration with [Tuya](https://www.tuya.com) devices. It allows users to easily connect and control [Tuya](https://www.tuya.com) devices from within the [FastyBird](https://www.fastybird.com) [IoT](https://en.wikipedia.org/wiki/Internet_of_things) ecosystem, providing a simple and user-friendly interface for managing and monitoring your devices. @@ -85,6 +89,10 @@ is finished, you will see your devices in the Devices list. ![Application code](https://github.com/FastyBird/tuya-connector/blob/main/docs/_media/tuya_scan_code.png) +After your devices are linked with your Tuya cloud account you are able to get Tuya user identifier. + +![User identifier](https://github.com/FastyBird/tuya-connector/blob/main/docs/_media/tuya_cloud_user_id.png) + ## Configuring the Connector through the Console To configure the connector through the console, run the following command: @@ -111,19 +119,20 @@ Tuya connector - initialization You will then be prompted to choose an action: ```shell - What would you like to do?: + What would you like to do? [Nothing]: [0] Create new connector configuration [1] Edit existing connector configuration [2] Delete existing connector configuration - > 0 + [3] List Tuya connectors + [4] Nothing ``` If you choose to create a new connector, you will be asked to choose the mode in which the connector will communicate with the devices: ```shell - In what mode should this connector communicate with devices? [Local network mode]: + In what mode should this connector communicate with Tuya devices? [Tuya cloud server mode]: [0] Local network mode - [1] Cloud server mode + [1] Tuya cloud server mode > 0 ``` diff --git a/docs/_media/tuya_cloud_user_id.png b/docs/_media/tuya_cloud_user_id.png new file mode 100644 index 0000000000000000000000000000000000000000..b2aef56ca4a87845b4faad30038c2de08ac3c81a GIT binary patch literal 75782 zcmeFZcU05O_BVowGJNIwOZ|DC-NyhN)!oSMr&$>wRR7+Mtf%vIq z=4xT#=w|KYZktx%NgRT`%`07ZT@_^sGbaaLQ*)=c7QEgL&SzCfq`W1FMF$IaQxY1=dg$alf9Fxmb0mu1wcURAMOA7(Z4(Q2erD5w}rjl za~lVu4u}H*hzLCXXQjWs`D@MBZWgYxP7cJ1?tp(Q@t>9d{PM3A|Ix7SzgY^1hzkFi z=bv8vsp{E?CDdGPi0n+yM1D57|9JLKdMUm$ef&v3e<=SSPl?(GT#@4YUo#1CC8xpT zF$u{N5{2haUwNNf%OFj^J&F%Axp5nUL8I0km8l^D>gv=6&)dmbp0qq`cU*f$eL+%# z>cR!das!QPKUuErp9aE^ZYhmZl5SwmVqC7RhBi6GqhNLM|b1hJ6bYw+jIXft#Q0-`95~(^WSm%qYv+w zSpI8Y{?x-7c49-Ii{i|G)9rtfE;)a@{2aUSl`AFw{Y1y~G|P2^Z(_43-E1o$7t_Z(^@!Lo5>=ShAmiIFpoaH0ETe?Mhzyn7PINmNg_&N<@r z{mme4&p2XfZ(jJVP`hvaoEcasBHD@H4YKBp(HzQQa@}*YEhmvl!!_IIjgQ4csz5%{sKtt_o(#bLj9 z!xHT2(9jV|W9-|mt!JktS%a&yFv;1FC%oY1LyS+LsF4Lf@}K0L9V{ zyrAQ%_=OU_Fp`mO}{Ams*RTeSZ7MxYQ-eV@j%$SY3#^_qw?dgh0lB0O7Gkx4@-^|@77ifSK%KON?Ar}GgN+awd;sX|o zjdqh$0x$jDk{H;$B>XZs7_(G@D6up$`V2WZw&crP%wo`X^xmY?iq;3&(^g9E^a+XO z+KYuZTn`*w%e8_sNlw}iF*-6xw%fmpAsHw$JX{d0YGQQzZbBGYtMt_@L@klUs_}_I zwk}oi1qmWBUtQfEvrlnwrxMn2XniG>Ngbp})YoM!S=iuwkIc?tOrP&`0^Wx4Z_NkY zo%du`&dHlediaPwUjK>W(MroUn5coxU?^!xsp}3Dj4~(#peMB@*KA7kot)$uy($|Y zPt}aSSlEA$gYQG!t82uj;Mc{EFXHzhTqj=Djdu78Yc*6(lg4tjqUxq#Qw&ommRQh)kW=8mIj_mPKAdX=craQgJ8!8Cq+nnpaa- z#vKEy)*X<^=y1O}Ie7nuP*kNZT-p)4lofuT&ZfeLxoT1}#bK(~z6(-EK%Kk=%~e=7 zpTr`VG-y>~D8- zim)faf{(izd+wCJYZy2BwN{_WZKoz?U|kw|p@`RQ8+dSTzel` zz@%_L7z5p7-aLMpyElzzhLa{4I_&fdfw}j&m3N-H1BOKU61Eq0Ob}tr0k%dlGLt8V zXy!D(QgLhqUo$AqH^VIGRQd&8DuSMV?j?B!9Gfj<|1$#z|8TX>39?q5K{(ziGmZY7 z-71qCYiJxeO0hrG%VuA3iU&p=nN}k`JEc9_N5z(c(*rGKw35r35BtZA{8aF}JABw5 zN@W#0d<}xka(KY$kjUa?T1n6JfTKwoQA=gjxZ}+%H9eTIRhWMb!h;0+9H z*TTIR>Bf7-hH!+@H3({~!De`&z_)yNL98%sGw-L7#i6|=I%4>@?y8fe8WdR_wI2dW zt48m5wI6-8WDauLZ=z>6e=}fxiD3TDdq=6t$-4T-5x^xVaW@W@CpsU0nxG zo!n>ZexMdK6JeRR=IA+QY-x7VM=QFNhTOq)yuW>lmJ7ey*K{I|eyAu%o*>_Gp-$Ss z+|diW@Vas_(h`#HwBA(Y-jrZ@+FzG$G~+XE6<2Mz6peLDn8amvKF}WrT>Lw`YyJ45 z;phba^Tr%8DT|(qwHpCuAkUc9MQrA+K5e67U-Yrg_cF+=C;kZIR6<~Kz(yK#hT2Ps zo98nIv=(^Ep(574`#C|aurQgE>i1wHv!b&4O2QTz2s#vnAkZfM7Flux>xf5{>VPRz za<9tZeUxOR=;Pf_j;7VWHg$}_Dq@o?A8EZYBBJ=Ust^y_dzpTLwNSAQDNjU{j&7AD z^jSLidM$!OH9bD2YNDt0DxbL*atvjel9MC7HKHz=izsNhKAyT0;~VM2_KhCn*B0xSD^EmC zTR*<>_Sp!I^+Y3ah=<%|Z!S1CJ-q7(aFgxG#534h0sSf*YJ4ySbHy=?g1l23iibN) z{22ETSlrC#waUy%9{E)0eC@a%T>j?4LVt6et1%nvNwW3+SW;a8J+G5!5%)}1*H2Ji zEAi{2Bn0<`_H_(e?!I-5+;PL!3#m4FWqS({uA>h7v<+E1i&N!_#cb1b* zYJ^9pv)s-S)L{oIdW9?uJRQjA=Uk)Oa%zD?6g@w@Q ztLGV@0+S}27!i6!9^)X#&U)Z?MIT(Fp?*Z|IrCqbQr0r+I>VujB$LjMf*pjtx+xn* zA%d{rOovsUFLE*N9?Hz~y@_#@{uj)TLBI#AG!g%k;LGB;=cz@eMWdB&d$Cz6p$3jr zLWCcWL`@8PqaqJ5KrTdxU23wv+y`;1Esa}}-T++k&9|{Wxy3;T8IxZfFMX+aDk$q# zwJ5EERik65=F#)-vAB!?p1es+*tqc}=hr)Hs`PR-(EqR zqHc&aE$cj>BfXcU7!V;xk$+)>l5 zerSy0#EtwJActy9Wi`TRL5{0OSIpM>Rm;POcIibvlgC2nbuP>`=*~Cc_?XA%pRLF5 z!)sSl=rZ_G43;t|b&qBcSz~<0#&dzZXqE~qrRHOp|Cfo`B7ip_wzs-*OQEIjR7XIwxILhx|2Hz`w*xAeoYipJe@H00)HQh^oV`V z8#cWoel_sWA`&WdN*&x9lVwzdsa!t21Cr^Cp~UR%IU#Gt%Q>0qhvgX~t96V6*p%<` zfK_h;R(2L?fLdARuX($dfv$_6VvirgYp}c#JQD3UzH2a~#yz{GuXM#oyqj^jM#uPu zp?u>uoIY0}C#-R^l5wmCLcx6W@=f+my{C8=e7(9vJGkpcmIl*Rz6JQE4GRjNP9aTp za7+rId*b*-cygOxCz=_o#k&=yy?ID(=u_rHDQeQLd@IXtdwJ3zwFKNZLOT+$c^D%O zR&b@t)u19b$w(W2zVpnzj#rHQmr$NsfTIyMwwDdsHb4-q$^yYuEO~<4a=Bltm=Y`q z^*%nnzK6F}ZzHeq@FhIR_;Sg%W4n?Ndpc$-7w z#C13)U+Z)yV7|*|RtKFD#L^{PhVJ|AZsoPrFByEX{;?`^%CHe<6m%1`x6wXZwm4qn zIxbB)!2_nO^jXS4csf7=_yG@26yi=QH=39&1bFIPZVE;H7}yZ;D%(7gLD-G?4G62}sH-c2u6!w=RMGU=ELPxIxF;?3m~Lxv6g~4o;me!y zRMr6y5u?k^U$`fb6Z=avj_DI4$~FuOa$$=x0(h77$%L>6=A%2UpiY|kYv-<H-$IUAsv?eW-lmhx z&3@%kQiCY$$9_TNdHlT#r+bkuyM^_h#9KuAw&#YDTVuy)n=f!|%eu`-ku|VCh0|a| z2tOGdBSj@B(ff!8yQ@_{*~87l3=$cdUG0T|18Gbw)TBg4&K!6H+wOMkr?%_mNUyE+ zHD2hk+E9bu*82y7Z(gR>rEw6x-h}Z?WKjM%HuM?|8N)>GV51>qVd8fehzmrT*~{If z#KV+MK(Oxf5!ki#67+)0Vom@yei&9WTNYUkMiG9Zea)F<4^XhvQyfBlE)CfP$Ux>lywhP+W ze}UvP!uAF)8z`r!ODsLz(V>p3_V2x+$tWI(U;W7O=f!8H3Zv^6DamN5dx!P{igW+C(qn4v*pYrdP(3#>uy!7X01F>k0y=CS3CrI9AV3#Byzc@$XIoXSgDN0F|{cS=h=|$(+CS49~U-Ws{5HYS;M#5@Lt`_R#qc z4@Vt#hPev8`4RTt?eQN^g-Orw+t$~)k$>kFozcDbJ%gt+&)t&#J2jmlg5S7q5CKW* zQbCK4zhgNfL)M7jEsDewMP-?>kSqR^`CiKqG< z%l})Z7!g-&`*`^lwk-xwL-b?7nGrxnf*XtyjA!UikYWpziY0ih$J zVXo4Ui7fSEQK{i6RVtSaYc!{nI(}{>r>AYWN02JmIOu(N|NURx1s1h$PiYy9>9-QG zelxM4X%56>DVFk5Z(Dt)HOe0!0B9TbUCcGusO~MTH`V7vycxnDN0iyOi-=apUYGd} z_wn5zP-0u;3m=N{*3Ier9VUzyG3vlCd-y~#`S^coJWRCH;$A$YF{$V!90hGpqFu(_ z8{_Akn}cI2_e7`r;n)CYU8a%6$Ml3@*q-)!eM4Z5V2XB3S<`-^dgp7{o`GF($=bKJ z=o+z`d*853c*G>yNb}(lS*mV5!`qMPmYpUWyb zw%e0T!X$@ID%YM^HY%-0Hvchk@cDmzOVk~-P2|0;TSlvEK=y|IzU0NRQ z44iUam=iAWsf{aakfg3mufB@W3N0_ovVU0~h$n02?2;*RqHEFE?wKfQbv#S8CV1X?e)*?U!;XLSLZg)aPl&i5HFM z{D7l;#TXQEN#B+;T|VZO&#+!?=Q~^&hRIGh9j~U96L6@YFn@Nx`-Ne7sd2D&ig>7j-n)zvdT9gi?{B zzPm6}V5v!b#kA1&0GsOO^bP{P&Un3&Cajr`GNpD8>y?5n#{fXxi4NFpm>mdH(l<1g#Zb$&C0JjXOnP_sfO)>jsGaBhcAC zEkj~r9OZ9?o5HC-)?u@IH9j(YibI`VGVSRG#=GE|U8_qVgCLL_gs?VBgQy1G*3lhHSm$v_NYE+g=EK@$P{PN5+r28s?79-}NN+u7*8H zw=YrO)dleb$}yIwg3w`8Bj29qmP-{QOawmzncAwDN9GSA?U$l0 zg}e=~GHH&MYdp-ji(jWnuGw`zyw z#>>AS3B^_;nn3+>h>unic4f^8GGbU=eMIgh$GQM@$AxcT2vT*`OvlKt%4S!Sx+d6H z&Jlx4hj$G3OEqV6*MU(1s5>Udr}jlq0|Y}A%C~u?^1F)Bv#E z79)$$SUohJxYK$3kV$%DPim}+Q}GV^ZYe9@C{uxvzFX95?5BS6i6cyjgPPQyeV1zm zj+SvCzg3mog94@_9hRwhcR)nH3`~Fdhq=JR(K}(+?nidN&Zrw(M_oIL%DU+`0yeSqcKbD<|9|e3u9I;jEJ&@0g8jcw^r-baGk2Z>f(O^!`W%tb()WrxoySqaKNF2Cxg<}L zd0E#qI)QH`bX-&E{m78`Z`e5-CXa)b{n<_++|&rNh`y8RW?%*Vk~uWulyf^#s7^$0?exS-Q%dO^z_RbLWF3AGgy)rK zX!PN`9T8HcME4893^{@md$J|;9Z#}ZO#Dhl*Cw*AQ!LgG7{v&a4K{*v>G7q_KJO@M zcbeW@Q*Sy2ceTz=$ItR%n1&5$<~*PtV0b1L4xh$)RcT{N7I7P$`%4I|`mtV*(T1IV zvzb5R!Eb1!YeTIJAy*PmE$Ynaj}_E%XpI!=*M0ah z3(<@}vW)06+eenw6$fpWOd7AVucA>?-sPal^KPlg4JMcC`>XK&wjO}{`~X+`n&iaV zMi3!As;{G#fMqrTz7k)yiE^}b3bFtdiaDhnzWHWCH~?9t5d;RKZgQ5bfP8?^MAY#E=0)5M!Cw$!a~V8QBU)v;8wpUdBKoSkVJ%A>^+fiqo6}KL6AcGw3V>DEKCaqdU412fg!qX zDRo#akZ*laZx49jHgSM}R4CC7qwbk$C{(LP^aJE4g1 zy*FClBjI)lt^jF2c*^tE)ntEk92M%-UW|S%C{z5`S3zW$)EcA}+* zjS{o9u)>LRtxenZLhY~O45Sw(O?}!6#SMJDc{x5>OT$(>^Mm|0tFNuH+vo4N) zReHp9?O9%izyD0ZJbkr(C&&)swMoIto^B39dVz*jJ%PM0o`*6M?uTmyHv9SbuW~(P zcSQ-QRahL?Uemj|Hxku!lmH|8vw(DyWUCMYAx5UR2jvK{cj{#D$ycoqUrKJf{ltni zYvlYoZ}Int_;gobHr2zU6}t8M9Z!%`r*!dRpHNtRrbkRcBpNu(efON1Pm-SRW%}*i za_2JJ_%64$Q1aksQcOv*nE`;i2btd1Z}{D-rtumc^ubFvXE))gzrQ9}db(E(c>$GQMreIA$8Sx`Urq)8+0)Bl!$vFks z>?g&9CwBv>DI@vQEI6u+8ZP^Zdx^J-Z`6LDwF7rMRusnAKIU1gJej^+H*RDpJJsRd zxwEn&B_rt7Uz6c>xI8WDr5aHPLK}V~J8BMq7_D*X3{d)+*49jp@CfpHP5C(Si}s0a zOqH?_c-Mxj?qN@8S3>t_Q^mllrG29hnzb>-7Hl#{zc4@a;1%6*rz#Ezvcvq(#F*gE z{uMXZuFif*dqz3O72|m8AtPE}*!u7=MTKN&z|}sPpu0B09Z~Oklr$wgtEepU^+X!NI0F`7;rvRvoyMeuA%xJiD zEy#`EJKB4`LSC%W$N$ja5pGOJM{G6_T1ZwAQ8vC$$&PZZ%tcojcpihL?7j5sjc ze6+n9q|2uN3TSSK`YHdTv?A4jHsa;j&i$fk-iDbEo}D~8Vg0Ov-e8-?Schdc)W~;P zMw!YvzOU?_|7ieO&J3W&VUfb6i0)ccpj$|&SF=a#`zPy33q963x09-@8s$-!r?rf? zkLWipwuSh*$|*#L4m90PG!b>O9{^DoazAR0l-}zrf8+e+oLRs|ETf;zLuG2NGWPDv z&vFjF(9?CxIV#tVA}=WzZx7yBJ@h&p6-zaI+r`(^Q#Tae8#Yft02oGG`mK_}hb^DycI=5I*QEBztlj>3F zvWLU@%t6<7;ua`{2NFW=82(&u*h`(cr<@f=1{qX{Ya_bA^qz!KnndCnu`Vi=3V9D2 zy{gA+X&1HLg!x2)J*Pi|IQ`-r$MsQU^r)tB?S z`A4S`nlvqYYDRYNo1N}uf_Y}mq*G;}wOU8mz z=pP1(3^&{eaRtVxesNcwu%_IJy>g@w-2ebTO6Wgv=wsTsK0yzOb|3VCg7lH{(%!eS z2Jc3_xTELYG83-kCfYT_!gh2P;Z7@q2ydL1x9IkjbC@H;>RDy9gFJAKuGktI3b7>-r3!nXdt(ofB!D9xc&{S_E%P(#y*AlcQSieZ*t%@5MK-vR z-r;eM%2?A9G>tUtR3nU;dMa9aK1K;z1#|aZ9 z_6efQcAvL#rmq}%dSoDkBHiW`ow*G)$w4PhkryjFWT0t+HkDxTdFym7q54Agw!h?eGN4?4x_ z3nrb`NxpwTSHQBE0~ll1jHeEd|Gt{zb37Q9;@{iLsKqsCNY;JewVnBc-m%>AQd2A+ zOaeFetuK-4Sg9nQV)W*vKM7fld#-M5L7w)du0 zdmI?Zchjx%(z+`>v93FL$8xc)c>+DIy}S-b1)bY^Xycnp>a=@p%a!W_3E=W6$)m3O zb**3Lb_%RA-Li)2O&63|(}Jed)G7n1nZ`Zg(zrhJQcj`pA)FyJU>q_H1#)Ze{l zEo4yS2n&->gNhgFT`fy=QH%<43vPKf$>9^`#YM1io&bCFHx5B%p@9rZ+`b#qd2;HL zYw$iH)c|F`%Au8+3+I#k_V zxYqC~0Pzpy$AlDN;IMTFPh|GjR%5q`t_OihF>ocxT&fQ?4rd36Okfzt_AwTxi21tl z>55_0#R#^Ek%#~QGgY#vpc1d&S)lBon<$tI*;CpO*6#X0=AYlE@@7xcs0$l*VnktWRy*8i^RF*uVoyMSA5p)%0CH$7X-Z1=J4Ubq@$k+D#bWkmSza}Cl zlT$D|XB5GiNk_LdtckuEW&ZjQxUb>76~LRT^DvP1Jk?)u%jErwxz=)d0r1zFBVYXY zzN{?+P>YtF;T-INi#1}6UP~=5N!W#+UPypoKg!5-$aj8EMUk?5m8o;Uln+j2biF#o zDwS(ZE9P;XkfIjP(X{h;d z*$C631xxRL{b3nLVK8Z-W6T^+;)l0>-*JzQ^c&@I5uYREN@ zS^FjtQLKCi%VV_82FV}&kK{nf5`A|jeQZp*Z!5`;rOQ{Z(mLf|6j$wze1w-;c}64dlV1};jE=Lzj>Pk>xsU7PQ!R3`gsswB z2chQ(rikMaa%Ka@gNmB-zeR)_)(f$zxW4@vp6E+yzvHmg#%&;;RZ%G)b5J0I zn#+wQiui^DTXmJGUt7N(vXol4i*YH({PAbr~ zv|8RV$*rtf4mah0Rdct@@9X3_9o6qHsgTZ7ugXapfZ$uOw$?u9_?U?(`iH`nm%EcE z=k$7M($SF=B{TjKDK0W0p`U6T0Ug#vRn?Mw&E9cCX6*X!=vZzc?YbyiC zLDy@aRIW24nbYtMPXzmHo)1DcqOS>9S3ieW6oX12G4MDlr?d>5ph|H=ZzdisFZkdb zl$0g-GsoL8=`yqvF0Q{Egx$aDVD(hsnG+u4#4yv5AQ|uh$Jb`~f^&D75w7fU{>v-0 zu}X)@>S5-!EO9nbH!m$$V7~FDZKv9%7wMvWXwRem?%LcukD7`?$6NddrlqmZO5GUDXg@u0iL~_KShCj4x@KM9bIC?}o9zyDgxvKm z=~&sewBcWbH?lk!e7RhdZj1&XbSS6D6ej`KcoB-gn-d5RTzT>_ps}UHQ2W z=H1g-Sz|W(>*CfXh!X7eLoH#h-5GMGnz40Ng?r#fs|p7ZxIV2Dx?pQpMXsA5`{8;; z&qWR^L=dto8 z$gAY@wj-%Jcl)d~q>K2rF!#FaJKu^&_&gd+rx4`mCQUsap}7@hUpF`Bwr1}&U%l~O zo~$jAI$2un@xzOJXr{=mM1z>L5Iu@Hz4oN`9xbVbpk|%*ulLLRzv69-+(hl?*yza^ z#VmGPuiMr23V7iHK{2Y2F~%W1A%22`hK{Rj3`?6zIk8k$?p+~+r?d};2f8kHe{zG0 z?(UE^eL;+!MC^MpW7bQ#xHAmuQyo^Pi``2D-y#ELs~E@o+eg2gb{;Vy!jN8*Exb*~ z@Hd8O0ig8R`V>gp=UL)xKSU+jwaiZ?e3iTVvLaA>Bl9~=5L_VYNWl(a{<0C*PaiDs zH0zE8^GLV6SL1Dt_c8u_jWds&{P4-w$ZcgsTxVRHX%@H3)uSa>`G=*%>1e&DLv%j2 z^%S)#Q9U9$8%jtm;=UbgYF=_V*n)axmTc%VfHP7q$@+PwoS3D{bz1wMr`r}hqy^8X z_pUJ!!$hJp{rC@8C8KKBT%L{p$O2d1wWw)#O&Tqj&uqD|{~lJbRSr3?6yEb?PipW% zPqnXK*L(bd-?X1+*DUA9?h#7Bx2#6|Ntd%s!mXhHj-dtc^X zjPKC+^94nPrdJ z(j$qFjB^;z$n(UJvi{X!eD}nNiWuG2x&N8`k5Kc#lgq!v_0AGhA%?LB}~lJ)ksbnJQYe~n=Cmk^TylE;22Q2s7x&ChrsA7n9rarG;;sqZ>a(=S0@KX$aSBEjD@AoL*Z&N7NvKE3GpFc|2%?!MFrmH zK6yv=|0x^6T6Dbx2_#cV=8({gLIreW^{QtHphlH>1ETuWYFHlOU3y!+XcTDntr{0=%M)T0-ZoZrI z!(+i$y>$G}?sS8>%Nm9_l#|u5ZfQrCZ{NN>)*KXsU(Sljy&Mh9bykw%?p-v3a_>JE0~+7o~X^@wc_y&Kj%H<`hgiuDSagqVy= zg`KL3`eBr+OajY%81@2|@??@T1PAP=f=+$)P%qd6|Glxkr@Lu=gDecc4uNUwnv(j> zhR_sJ&li<7Rf>%1w)IPHG(5!T;i632LP^`*3tUe&+bBKz#nH)tOT7t1s(Mwx^8|1& zFQgA}xDe+WR~qN6sY$``cz~EHJTCEhqxsW9l1X5N5?|v8Q{cg@gu+Q9Zn}z`*}vS} z(1e(MpU>G$*f;3rA71?#B{qF`RV5$?*Toi-e9c2+#B-Ucps3QsWAyb{y$9xQK=Lg3FE-S#qy$h*vLX%_v2n8r?rjqi-}cS zArnNrV=FcwTn_Ofp^!lp zL@%!w+VtpD1SuCIWEWI1c}$*G;_+khd{}Y`vTbc2eTr{wo+~>B-?!JpHNN$X#58kM(Au1(|GRL^lH-$Q^s$Zh0K*d3%`O=i9j%!4ih8jAzkovUa7n4kw zuDJ;gD5Q$}cm!;pqKF~w z)f}GrqJ2BkTOwu!80zo^*Tw`)L4BXCh_NA*;FCpJrrQUnoHWmwpW zH3!*oS1sPjOsr$!`O}ib-L%$_c3u1^Sdt#O>Me)-3jZKM~I1 zo)uwCzWIs+2&ZQ0H4~@Cy<_4|~HV(?shZrN<<@oc-ms`l0 z8B`_bKCx|M;H>QECj7b`rWE2>%cKT4G>;4{TqI^+*pf4Ozj;tq>Hq`;C?E21JdC4m zN-}g+=t3kKINA`A(!krih2)wGirs~=kLNPA)e@qUWlj#}5AQ1(k(0hOD?0K)IDk{A z6MNFels?Cg6?(nRwqrDs_#Cntph@i{Z~>LA5ciDHdnG4nyXCCn7te<2aGmjIxR2{x zburQ3 zJ$aS(ogd}DqXPIOr&6$1A0z3tZrDztr;qHDSAV;>(R_NH?ZGQ@(P?ip$@SWK<v}=TCnC7;W*}XcQ|eAMegtRT>LO zTPX7$f;U&YyBDkfIERgvG{k7KbmOI&6d{zo1@wB@0{D_HYBbaKV)s*WM(Q|9oOOXH zS1#XrVVf0G zt$7qS{)JW6K8(@x(%x}?R^RjcGBrreY$e5-APMa>OqSm( z8;%#S)rr8IMNYuZZeW(z;DgvOI8~!lx+mP`wV{UPqF6_kMFBc0y1*lu7huhSdXyr`z7r*7eB; zTw3(>U-JlyWywi0mY_Zj@sNORT~`8!*rP6$!FeXsIS1n9*gkvAD3r`QsEDzFIb@24 zONBr^?n9aE;FdUPh);7^MpH+BQ1?&U6->iDsba*ZHtMc)3uTra=x3OV8gNztksiZN zxB4V-Vg|>XQ{rimEwcr$ItHdyJf5;U#Gt-tlJw;A&J?*NBEvzn-jxLVs~O4S8ax@^ znaVRHE~Yu3#RWV+I{}!+{pj_mn~z|!^c)%~yQXme&*>b(uIDK_X37udBEn)=x#Tjv z=RSX%N|-ZHbmO|0^Cvkg}&~p=Lnb6{)T)jC(&fOrA{b zr`a{-iz#XO^nFwFlEUo$;15G_&t6|Ce4uHqsKITKZwOq@GLcS;_)PtpGt>J=2?%cc zw1p?c9Jh|#3D-(^-I2JMXu$g*_eVt3-K679W}k)FrxjCGRN`iH6;tw#9^bT1i_&@KQrg4|KU{+W+#v;U`KWuu-4isE;Wd4^v+5*Anv$(d z6X!~FYHhH_V|!}zM!NlvK;4^qSObsD7v0`9nf|$!TgsV5RA%+l^&3a~SbBK)f=h{2 z>8z-MnGZS z5&H{V{x%O+A~Q7Mn-_$X#*p7#bwCqmWPf3=cu?pWOpF${SDJ_8QP2*Q{r0Q58XYxl zv71?}k>`72lWp?dyiqopHp`SDq|auwPc6esw1a zge*>(tTVp9ci^;+u@OWuINnVjUCUEk^sgv)@;3#wo=))$5510gxPJY_moxa?wVSsC z58Q$hR>gnXchDX;A%>NG#AkZash(J&PE#ja#%t|z#gQzd{c8{tsHZq;joWL38kQuP zokJstnGe2c<+S1u!hPyQx0=P(Accgd1_<`pgL_UMV8w(Dg7m8NtoEHDDGp8HlgziE zO?R=O9YG0i9jQBN9OEZ!7>Tz&#rzJ<#Nv1NyqXo&!et^wAoHYExTgIBFHr;Ar)ae2 zFG}txx;ov1KiziWH=^34*(PHtaiKfQ-L$7Z3uVAv*`x3YkOf)ss3zum%nkN zyv_u=r~iuB^;fkYxPp|qr|BD8{pz$QX~d|3twBT+<)YJ0oDF)jynd}9Zc6S3a_5s| zwISWvz#i`7d5*Q=y3*QiX0H&<$Lo#I9sFGQe&fjz=631SCCJn__1Tkt?qf3vdx%C> zE5(Jw`O^D^6P^eM?x{;RqalJa@xwBKX7RTHc`x29NcWx9PW}vxN&N(QXjnnLUsox$ zwljGCb}2(YGcIQJidg0=Z_34TH5c*$&O>nMxn^I&tc}(oX1=S=xahH`Qma zV2(YDWgIW|Y(#Jua+W%mZc=X47CmE_8u*G*EvMwb78b&8_m~);0MDU7SQvl0i#AU*uNq)xw$(5KZ@vNIdHgYscMH^M z-3f-X2{LPBjaPK2wGS>8IAeeDU;urEXTA)5Qem}&L>YxbrdLV8jc&tFX$ zC$!3qjtpj75O+T&xR?-`UJGPe)sOf*u))9YygZ-XdXVmQT_Q?6wq0>)2pSaJ8&EaP z$8>OMd!kCl9pmgIbN2X`!%8LMwI;1LOCTU6A!n0MAjVc4CjU{l`7TF;Ehw4zgalhv zX+mFhv!BCo5j$}W+-ZE30k1wtO;I&p_M!>e)DK^lD*SI9v#de?JJ#O5!d5oWn{4PS zsO3c+0`B7AXnbO_hJT7Lv>Uk-I!Gfs_EJJ-={(CIZ(YPtuF-z%1zoRBZ7-S8E48XR zz-XJo8s>fVZAor{fpx6c+zxw1V%nyh2)cfmL8&9Mmmg~#86aO~q|H}D&|b2#3y5}D zZ>~;A{YBL=+l?YWYAiaM<~rr_3Qw`D&Jz|LEy2wme1#nII3e<{C|q9|XhG_-=xARd zT)D2APe@5)E~^eD)3zFgB!Gn$mLXPb)th*?$qsu>&Jet^YzUgE#q#7Aj$VJr%{%3Xksm?Czh>;_MM)@;Xz9MqtTuE2)YQahb&{iJEArAuQM(>4Nj_U*;7 zywK+!3q}1p+Wd~D8WTcjHvX;mGk=M;mcFGp`Moj(+6;}J?zc{q? z3yc1dt)}6kJRN4(p;E3clsz(kZW#;=AiYDt?aMuNfGAp z-F*t$xY4j8c>VotFhsWjxD4LkDgl6QPAH6pdLQWuEE;iTWmd!_4k`1EkSto13pKu% zDAVyqu7540U7-T2E0X|TN@`3eNz_eC>XG~*bMurY>2H(3;fyJdh17I3QXE_+$T~I`?bs@fYXhYX8>t zXpX*o^9*kq&ylHF-6&Q|nTzxoP0(D-!od%&^Dq zjwSq18Pg6)rKlHA5t00rT`4ckjr_Da`3sq&_v`&5^z`uIQ~E-S57P~WrY57107m7) z*Dafg1*+vl<+QLAyB@7-OM9g3UP{1<4fee4C9`Mwe|LEBDVWOoCApHj^Q)D0jlm9L zC1_kVN*l(!_e@!$0m|INn-Z`DjaQg1#d@{W1xH`3$EkTi)kIlaJ!Q@7)YKLQ0qSGX z?#0G{0YUwap90bE&>GYi$xiprVkd%V^GFRYJ_OMAc_^81muTed=(RT`ZYfA=B?IOW z+WkXYCR|3n8PHCh9fRWYx?++s-`quv!kPFbS zkGj(dae=Cd$6Vu*Qx@nHsNWSJJXHpR0CJ6Bzh%~u2A|z7pQMDf!4Rx~@|czkQfz#f z*=pwIs-O1=R|+7GIeE1Z(}k)r9_0b;b8RW^4hM`}dhs6AD!EAFA&;dzIqCtDt#3WV ze_d;&4vV#AY}>OkTe8bPvMYX{d<5goD)4i095om=tg%9&(nQjfy5+V}O%T=y)Hm(i zG1#*_r5C_ATj?|Wb<#=FrU-2p?XFclkA9Xb9RcH7&bZNp!|&cM6}OpT7I*2)3oLU4 zN3fobo6j1*hl@#nDhk%^8ZzLF_zO%U7IRJgqILcwe&e{bWFL&FVmHO{%VuO*eE-p| zp!DEe@h=l;EHX`c`5ksLIl6|4@R(DEE#-oqGq991uRdW>+Fe;mo04YstMkNlcFMH% zBx%;@MFCP;?!|a>u(q!PFOf5OE@N+6^7aXfwY9dYg2rpKz-4~&XI)IvplL5llwwm? zvxj^c^;dhlismiv4=^RJymnhd^@oE`7*sXBJ=^$TL}ppm-V?|)mZJ2BiO&+0zbVpK zKpQ;xu1{$u9%a-gJ=LIQ`ucR$j zIF;mR@3(r8<6Ml#)TfqAehE~9jx_i(w(*1P zchUls<#<|16dEZ@_G8vxqdP|&Zb|eEMMVM1R(2WKs-rM5(H1K$41=Do0vlTLwbxSJ z{8V+T*0GnG<5bcX8%t-Gt;(7=Z)X=W^S36oBIAsfGmD>tk(ZF4F-B3rD=%^&z`&lQ z)TB8_S?KgNDf7W42S~aze1WIKeXj3M-}=-f-PXDPv`2W*gn2{p^tHGth+4^{zZs%0 zM!FGo!2u;2OsGW3k3Cem0bP_tdr5vdd4-^v8t0|uPEqA`GUoOsE(I$ggM#o8Ni*?% zXw8DbIkh#zA+grA8#4sMs+!L>&d1X^qbi^#my9d_ij zM~&+B%5)&DU2ZdJnWGokm}D1{Zg{4wpc<*aZ`4kjieB8eD*o~;j?}H~$j?UJzY}sb z;KTzzsO@`p@&V~SdU;Ojr zK{b$M@brPQ1TFHUOoVni#^j}}37baXsZPyuckK>DvQ)rO`uXi1VEC;PE3~z(mjb+FxuZzE)O!#67J%D^B|{6ggDV!jrQwFPf3>&NtvW4 zlf}~jn7xriC$L-vMAiWj<}`8<(Xc5CKF zdg22i9e|F6C6oL8OKacL`>nsTv9YsPtop^9318YMdJzQOw$LeT`~}9qj#8?PQ;d1_ zwd;JNk=aa_+d3-QiI=(8ziuO5EaF1m>fDW-TIcGh9|4}m>yTU*5Pcupj1D1zBmKZB`2gNtibo zy1D`ECAovld3(IUyP3ZdN@@2K=Z(=;lI#8^y?T|$sY6Q6TGR$beukdheF4UPIxn8c zhgG;#EGg4|-C{FVtkBQeDVQuDMQ|)jmCSckADE`!HXOOnvBy`VfTClC4dN*Q%7~{e zM%-Fs!N^M3uR7@{n9!UmX(vIlR!GS!nDGOLDQJ>-Cm++)P^-&UaZ+r}tiNHK_QF9? zJl?=W9aTmJI-Gw(Ku-d?D64Tso$`%2o?^USvq*?(e|Ob|QN}j2`l|1|p*m(qr3KDh zGGAa7yzZ|{nFPl>$?mciL3_*xq_;^DYNR^cR(7|%afL3;7~^JkuQr;CSYHq2X~&rp z!55wdp!FmY7aYLVb6#pY%vLkhcpBKy3$s072G7@#DEY5W*5GiR zBK?4hMHC{pEX6(Vo_R3d2u-c-R&Ay2cbxyre`7E2^EW>w>dkK>UdumB{%lO=t7%ql zn};bN!e2c%2R;fCcv_k~b1c-ZuWg>Up0uv-lC`P%w&Orxt=2g10}p6GpyY76G5J{G z{=0z>O4Q?D2q~pW@{+|fh56Z&yrTUH*a@*XTyAW{g^r9gu2ZFPWajJdQ%tx*H`nu% zKRo3`3uguzL^q}d@&Z&^(@EGqBMW?vz%bk%?SD&D8^{fswG}XFTxCSxve>Ea=0F7i|=ZNs?cXxsfrl4X*zRdqRJr*7qDa zoxCpNQvPbNXp&US1Wmx*{-&9G{6;zo-~Yq|vbUC5itL14u(!?19xKW}UrpVwP18{$ zKqPz9)XlPU)h6D3hnrjcuHp^N5=X0T@wrY;+5}g;&9^lLM&IJ^>?O*YfxN@Nn8F@E z%%s;DY~6e?-x{3d(rQn!MjsXdiuCVJZOsk$Q+9Fu?4t7dbyyyWgJ!jLOTLDhX3L^_ zr&Zu^Vs&eVcc&cY7gNMB5Aups59(%8U%U|0AdLT2p_T*W&~%B0)5+bIn@m19`DShy z6m^o~u~G^Si7w0bwD1pCYAKxp`=75x#;86s{8P&0bOS0CjIBS+)W3V4ICO`Z{DX#r z$C4%WfVJ}m#|(&RgF7wl*c6O*Un#Uz4kYSn)=pdJlXE%Tv|vJM>n$v{`M`g0MtmKb zmn3G)vl7chT@5;*>p&sHJ|aU{Sp)sItht}2lFE(gQQ8O?fW}guEfe66MS0O5na~6B zG{@|E*@_y*G%PdQ_0U>81AmH|*6ZcX&Ia#_MwtAdM~B|IvCi7^6PPeNV@Bj=tDJJ> z$c%@25}l*F-;%tj8m_7YK_G43Z$OC;bsUMN#6*CsZgA4xbT6Vb+b79=g~ejIZjhq8 zgmb7RZ^)0B1A1faHiP^#iJ~kQml@5h*}3+yUY3K7&;4C8zhHww?_qVvFfOg7cTZ!9 zmdHns`lA_su|1;t4OgCkO~U%B+&2r`uj_eSo-~6Up&of>or3*~R#-&GmPc7qwAPKb zC29TfS(_-1+_Dv9R0&=N&|lhxcdxQ`v(f7DMDa|tmK3F`|B8t~F>}LBko2fTGINY- zw48=h`)336!Z66EXdr*h=7?*U@`E<>U+$sj+hY@X*1pEOfn^nja{+g~WNu zK8Wlm`9vI6$cCvbm2Z?Gg$j`B-NEd9O&XLzacn+odtxQ`zmZr)U4!@z#BhP*?(U97~K z+xzoXu;#~Xn$c;`*d9+KG!~%&Mjb~wLWS>f-NdSL`#!p5c+pJGvJ)Y*wZFQw+-hE@ zO;o3sca}G`FFxB_POx~zzCZ$qrlvGiWJ|Kh)(qyz;WBA`z_ng;z(BM=0K)7VpR`FwEw0!7Za$WWGO(?9!9T1qNlmWnC|Wg7g7vsv;v%Bm`mNXe47}>!1g*T!^m<~b~YA@;JTB==k{We%=6hqc`!#^4y1ATYCQz)E-1-&l;a67P_Z;M{m;#X8F611GdM-)1DG}$GWZdaZtWQB3Oqr_PGrtQ*BH;S6?E`2!JyC}z~ zK^m?i9zMIR%N4S}(B@yKTk(tOkl|3q20Zw4%X)Kk`+Nb$>~Yd;JHey=#9G-U^HShY z`)mPT4P5sQI+z^M{Gt;)ZiFjj_;3;9f%{n?jep86)SdL0DudofIR}%qBtCt(F26{l zQ@{8yR4iU_;p0W6i1@5)Z{#)K8n2p`huGQjRCQ3v&$VWnCE%2P-bM*;ZmJ~d;G<>Y zo!^7LD+ih1{GNHQa<7wJkYi)=dy_@y@B$D1G76r*1?Kb2wUV z-`59m^NH>EWjnIOHTwQQ4@e}v$^f{iaUGNK^>C*CrFw4aMX1e<+tz)n7hgZ{urPh( zfecgCap^tl-G0HUBi+lgWmk}AX|4fx3!+Hfp8&9rT41)~-`am@F;$-CFrt&7GSN^x zb1UB1+Lk|w(yHK3iTCe=$x=eA)CNJti5v#;4W}G=>{>kCa@f~o|MEdN%rq%rh$4w; zUjYV_@AXRhKJ_)>DE@F-VsMaI0fcfVp?V=RdBE55vWu}S3XMopV?ml7yJ3zOy; z+#l`)$PmzMjj`);M`OS-qu^H$XDCA8_o^Qkqxx>3DIzJlhXZ9+r zK`o7tT3*s}T9khzGP;wPRtV!yvHP?Mo}@UyEappm2UuCc3X^~GM(_KREpPBDR^ojp zDeeW8#ZI;AS+BA)d7X$?A0s$`OI3siUA(ClMig8w*vy9G%3u&#?|Er&UA9kXt3{^w zlJ-pNhcbPMcxp$Fpy|8syd+wWW8G{xb(*|ZNVPx*7jJ^G{wti?;6kO;gnTT^0?s_Z zKj@eDAp(Xq?+CidUD7I_8^F!C8bWx0n%PiPs()J4j;<}6b-SFfQ=6O{Q-Fxufb(Sk zO2AH7i+j<7#GT#Q$27(laNK*8Pd42Z)~vEwNrINH&y2X@-AOR`QuEzoaNJnC53I3T zNotOrUo`s#Y`aY*e`yynKlw|oL8(fAY-4iIPWTnRl3xXuS|kaxSDq) z)|eyB^k`B7!lV`2hzy*DG`EOBX@C(e~c7N zS*Q_!8S@Q`Fa&E>mu_iTD~kcrRTovOvUrp$tY^S%UI1rw88mIb$3$O^U<_F0iN66H z2uhDFniiOPNYLVxM8JSVrM?8$gLVve%wDw{+?$>!L5^_aKzBZS{W?VRw{}FdOa!5pylu1Y=p$MF3&^Utj_yw!XnhJ127!*5?spMYF-Ef>+b26iaD&IDe&UlVq}!lYeo&Sm3}P@ z(te2gXVixOUk6DT_b1%DI3jnBxnp=+?3Ysq7L;;+#c7CdxRb(!wy`Ee@Bm8{z#rBX zCYiWe9WWGA!|(@{(6Uoj{V>4ezH;j85M?eW^Jd5m&!43W_iK1LA~n`71m;p}iw!Vr z5CgP;*9TYn6${SS#)XW37hK&auPDS{+L9%hEXtxXFrJ5;e^Jr(NAw!Ea}n5Y+KK z)ym4ajdR9AGasKOR{V!#tdnN**FAF4Qhn&3QFZLW$v$b+}@+EpN^2sPoeU)O6dRPPFDOx_S$+&Fu ztU)c$|ITVM$4H~Wm=iE%GSx!#-a{-c&%bcRBfCQ+nLnlbmlPL#o>{5vUMi>{@v4BM@eg+y_ob$W`q zO4(^fK0HQ{fa^33HJFMi)Kvioq*r9sT1^IlX4FJ?M%2C<^6nY3F#OF9(tmop^|YMi zE*@!M=Sc>+jeo&eoq*zcbxUHCXY=e~Pf!un&OTrdEftfNap5z)m585|B6$YVU++Av z@mo~J$zyktx;4Y{hGat8N}l&;#D&ZfxEute$;1_!^_q*|j~8_$kHNikc@}Ij>&|K+ zLhSm>ja7JNSGIWsF+0`)Wj{;Mi+zU?WzjoW&5 z5gM}#;nvpG6I<{b-{Iiq54i%`Npw`+xsBh6ZVExiXjDb5v$d=oeK+@v=k_mXOZ-d> z#Ff2RLEPbkHt4-;|4c9DLW1*X`sGX2B-7}4b8acMlFb%sK4$#)4YPBH4K_A47y+=4 zE1wrziFT?VkSlzeCNU8tZ<2;z`0FBJX_(|y%jtw&@F_YgPafys1<+jZ_isDZQ|f8a zEx9qNCE_I``9}OV?Fj3J!&x?sI~JCvkg);{n4HY9;1CR%&<^_jNye!FxP)>dd9V4F zRkh_*=G_m*>#OAW<%Pqu?TLVE-Gud8p^;YbX@2rf!Mz|+VkQ$APTcoH*?T+1j>hkp zz{%>96y*4Ff#-1sHDT?fW2L=6DMs{^l59F}UXS$;sh*+5WM?u$1vr(Y@7#UxqpWA!$>7}iDFik&7$TV4f=Tdzh12QHGxbKZc0xG0l6GfB+43}WPk}&F67Sg z5U&sw5utrlbrRiFWxp(t#8YDF#EFE$&!c=!_dxF8b$tUK)A7lVZk}M^g=EN0-kerY z$5v#XW%l%?1t>(_Oy0yDIVvXKveKwZNKGnLnc8n%BH9lv-<{74U1Jh)T2AKoPvuPJ zSi#7yRbjTbCtY|GEI7~QB%gHX{aC9Ow7EWh6R?Ra_io4Uec?n}V=!BVp9aot{i69% z_U8k_O6symK-{u@D}HsPpR+Gcz9%j5=$BCrfMBqWkgOumCklWx>MyB%ncR@8>9>t^ zF_OcKyT%!P%dp)CDejqYpQ{lF+I8M@J=HL@l!b!^YVO8C^7B6%N|rMzE*i?>pyS$C zrRI*b8*Bzv*mw2r$i2fQojsTjK?M=_A%Cxia&*;OI@8~fX!t)zA5$C6zHuUY&@wjV9mVCt5)#_)R)?b+?Dy4?~o%TDC_@X*(0IB`N58*i(VFxxYkaj8f!P02?8-u0S(B+2T9Tnc~ z4j~+?`CP@*BPxamxH#79BzX{kPC!Qs`9lu2)%@Cr+N(9kpZHCtw0{8UK`)+;XrNl1JXWe7^CC-t|fnz5ZA>H%GhwFo?Vp9{j=noK>! z1o*1=Hwp`@#L9(3V=cO(MV^py38JK(kUTY1XO2MaKx(Rxx0bwizs*U1RQ=ZABwv@d z^`c4UtiaG9MX+;UFP7fhgZJhYrry6SzIVyk(btfOU%GNrXXSioH(H1=x{HfLEvgoa zU$p?wy`HshIIy9e)}K3^EQ(IkFf+I2p4HJbdn*77SfPSy>H*zx9*iQSJxD7ZtN)lR z)*yawa+DpQ-jLdgH5hQ?YM;WjOfIiBf%NOrJB+9=hRk-EttS)d)ER6Wbl^_)s+>t?9JAymDvozVe3DW4%g|>pO*IdQ!Sj0| z@(uC0C-Fv#JqKiobcTXNt33x>{!oEpPzV39Y@jR0r;-LlpN8X?=7kd9;Kfrp9v(v7 zn_jhL8mOdXIx2X=ds<)~{B?}(&4i%B-OA)Vo5muExZ}_}<4Av5oGA8>(`GG4 z5gGPxth@>eL5A9^LD$c*1OQ~n+nUethUu9$a!r_&t?y4v2lvIN&Y~E+6{zTbWywvd zWQer(8=xVE>W!a}6s{KrVak#N!Cy#`ypVJ#IDtTh`6b`kPj-sE=j7M^wO|7)*Y%yh zj0`aEbZRwuZou~a`*nr}Ou$ecXL3Km~jyWtmdar zfRO0@pz7GFqIY53!ms92|3M2|_w;+89< zLU0&ITX?8$%@gz5TB9cEha70?>HUDxUNixx@LE!b>iG~V;EMY(NT=lVWP+S#^O z_~NlA;(H!O)4;^f%9%BmV!tiuinTUQ`?@m%9me_#E+XT^k^swr-tq5onXN<|EH6~edYG@S}A97qchz$HfZPazwVi8~34 zF72E^avzQ2yG^Ffcu$DB+unI>UovY(?)c;2|g^u3R2W1B*4SdOL9 zIUE%_%G|Gm9EE-&UKEqO-OTlBKM@oN?r~lkZZ&oEF2@V?YW2_^#9I^)$RFX~F*Au-#%OUG75%(dy-4sr(zXI{ z?~3#u5JJZA;%^q6&UrNGx6o1}jfd26UOX+f?b>tg+k?bQTKMssR8=n*H0-h*Dv}!k zfrNcOqc;WFy9F}EX_p!Q-dj)zRiymL>h~q)mL*Ol|KRN zr``Q~`|H1qu-6TD?nZ_)TiySA75iT+`1VJrnZ8u|5?3NceYgfdBd5 z4{3rYANB2|1^?4nA5b^r{+q4+b2MfJI1hzi^E15o4`aQ1kI48xE&2EHdk?6|G86vO zSl=QC-@XYzNum0OA&1zjvB1ZX-8`=zRO*>drW!Sta)Px7l)}Z8=s7>T4!~sJObKtY zGbVV4a7{E0KKWRv^TF&G$fTAE;a2p&O3RzfmAKvF`Of`UJ4XKuM=|xK-uT58_Ub24 zF0RCRDE99hUTlQnQ(PA%Av41@`F@<+5 zg#pVljTRgV^Aa}hB+Upey5fS_AJj*k&i(P5c=`r)~g&?^CD<`~L zR+j(1iM9%MS9SPSL>&M6@P9l6gW8`y$z-_K@%;NHm8IC8Dl_2O0{>oYt=X|^M_FW! z;@>yX(Zcow9rhWe`oD$$r*EOWq*y&vn(g%XpMLniKSL|ousu0!i`mBgb%p<75#DCt zKl#Y2r79Tl@0&nL%H8iqF2J*$Tp^g?Uq{%=&FVDG=F|Z?OcNPCpW!q88wgv8KiTyg;(Xf}>sAGXJ=v z^ygv=<+XZq@LP_oTk#ugOF@h2EpK=b@krBcC2zq9gZzSQSfs7Q5=&k%moMaYP2OO~ zR#kc1dAoghjIrOC@)Y^aUd?6{KhL%E2=vDEU2M35B{xLWX=iSy$kD~T5nNvVVnvL* zj^#sRvs^l+&e|1}O1wB!Xt!IxZa6XpkFvvw>;hu#F~z4(n~x~#ndUPIJ2@~Y zc_};ZZmqc;Yt^7LulfK0e*pYoSOgK`!b3k_gUUH78-gNg5T?oo`)}%*7P78UbTeYj z6G7myEwL+dTm43i@P%SMPjH+zibTqYeLZ0Jz_qi!C|+u5|8RMjNb>Ofx4&^22(^Tk zN`92p$%k?X{3PJu{e921++<&f=UOG{ik3ZzruOMSh@jbB9I~NLGR6Uy6?kft8CMt z&SBKW=hqD?8*|uv-Dpju9#pY!o+Tq6Kh%2Ec|Rgz@5C#?tKc5qF+1MLp)ui|)#{q33zCPb!vsZ*io~|L_>oRzHiPHDWfQ{J&TLDyc(#>$XbseM*SON(*xH zXI!>9u6(ywQ^)Prg&n7d+HKc;97j7?)cMh+F*T!-)jbCu??Fllpx;!`VN`|B9D$lz zZRqtFn4_liC#dZN^|`70^FQh)Km6C;cOylx=>z;10oi_;Slo#^!K0Hh@rHd7V<>ov(tpah(A7g2IEiQ>|t~-q83jkUM;HVVsZjf7y%n_FE zgws$rJb45y)n2ZY!T41SN}IlZ8-_j`le(QIKrjn+Qrdp^&3E@RY5r3YR#@aPIgbnrIO~njeM7VK-R>pBJ~mkAZSPa zl%GRzcP1i}N$f1xTG~0F;Q-226JVfh)j20coH$6ku9gpsjr0R`|C7E2XRArLH`FKO2%C4bs%^3X) z$xHl&4vmA4oE7wfeonFk+|sUcrrs&Yy%0Cyb=%wko@|%|TBTMO&+B()zKRO$8jD_@ ziHu#oT`l?;SGDz_v7zg9C~`n(>Df})fb}|tH`g2K)%3^wnSz>EeXZ$GBdVKNsyBwT z<9IpW<)Ls7j=@;R?`Tf!6^h2CMxzXelm0y%2=l>lYdt6Ss<$lKb6z4~jufV!W8z?N zySy{oXyj_of#tIkm=EwdSSgFVJ{@vp0;%9IXk#G9xg$r#Q=_LBy>kAzG(MVXZ`8&j zI`4B4VuIHzY-0@lbLLBICot#w8?eb{`<%&5^X(vNIM%`#=zB5W_rlps3_6d+uJ?_F zR%tDiic>EUv=WcDn7uupXzBkcX2M4kFUD!i=g%yD^=o55CG%Jc>^@b$p3trK9YdQ< z1p;H)V#HsUVc_`iNzl?a8t1ZBOauryNez|`1n%d$u8)~X!23=8fE_p63*PFOjV_76 z9-gvv{0HP))4|OK2R|n$jd!=w9PWG zwRI+f0%E;k_?H!JvJJs8IWc8%8PAS5D4)zV)yz@#%MXEk8|GAPQx@U6Ceb@9yh~0g zme&*u7vAE{wcxQKn1lJ|eVZY!qn(DyE1>AQhm>2Or|SH1D@(=_dGG6M5vRt6h4QVw z{eD?N4r=RCvO6u4!;lfc?Qr$7co@Qkt>uiHuLzO6k=Uu`C$-M0uj{N-nPHx zy;w0lF|N1l%LH!fiURzyB@283X;mIC`ggK9AzDoMSeQ2ei6Y-hdC_F%OhN5>@UE_;THh6u&L}PD7el^@0pa)am(=&d7Qz zrJc<9YoUulmvqc5HxB;hbMl8n=j-N{K-8$1e%h2;gF(oxa~cuEsk44Ez(H8MJtll39hAsPY zIBoUk1q+fYilcg_f;(w|vQt4S;hT)@2Y<+lR5<3jLSkA|)qh5x`kpmMc~7rJ8X7?w zb-ur7(p1bXyC>7{UvQ~wT}`a7{BdAeGm=na=*9W)eG$Z zi&OXYAo^qVs!bA9)Ab(Q6ciu<9G4W&TekGFt{)x&-j6U!9@D2M;L3pCR*)Mie>1yu zpD3Tn3R?rMkYm(gaBIiyTEF1OUmrL-f0gEmcVZB96Kl7JaGf84k*3Rp9Y06O4l;vo zv*t2jqapr25Hs&-yL!@8o`44Q6#}7hF|%Ro<{0KXM;B=7Hg2{dFbqI^_9va?xL%cD z=tQSrlR2_e@gGrA?dt6#Ae)6tX9Q@>QRI!G;DT#T*^FyL$J|fka3|s#g0eqJJZY(t zyN!Qw;U0YB5chGMY2tv|)U$Cxd^OEj;8v*;4EK2iiR+iJ66EdAqaj~1-)^clnf&SG zd>h@;egENrc2(P4RWS8}t65`{(D9U;AhO1f^nC2RNBJ%T%|S3&TxupNb?Io)j=-db zr)`^uIN=;v4~g$*sfwu%rWMv4w587TXuJX)@A%HrP6(#-M`AD|u=vI{)*G%7zSn-i z7oCwLf9M_vf`!$??@2(C&zg!p4=A0>7SdaP^}x)b7My9=UsX39i zpZ~eSAL-5Gr8ix8(Fxe~R6QrolT6dm4Bf%9@IJ%!$q_wzgc&7JbM15q)VPZzmb$U4 zGzS{m0<++@NynXIqlkN)OwcYJPJS=*L}e;+X#v}@qlvlrv(N8JS^>KfHdoMs1ShDD zUZWAbxu2``yDjUFnJX;8rvyoLm0&YIEbUD5D-oc%+)QT4#G5D_RB|LLw*Va8`*EFR zw44m>cW1f==Pj$`S{11+_$#G zX4BOgjK&=Jn~y0!b|SN2z{D9n$z{PkKwG|Ele*a(3?-CoO7UoD?$cZoahxMje=s$S8Jw;E`S_<>nxou=ZXS5-Nmk=#k&#+hTu+l7YJ z7t=JZ^ywO#`?+rYj>eM^BzT9rR0Z~4oN>HTd&o&7iCG^~*9t~odP&psz$7q9=~klSWU>K7YQa=x}j%)!v1~x{Tn^>rwECxNl?K3Pus@qS}k@ zKG^q0&_}d}D=LMzmH_j(iKk|iRP`A09WE=qx&~-s5avjzF5%LA@4JUM?w*`IXw|G# zm1Y}x78-mR z3y5jD-Z4>%L(dJVW|H60ax5QCB^&S}hoWs81z)&Zd7f1Y+#UunjajvZ90z30RSsnY zy%}`cvQ`@9j!`QU5;_oGb~+ET=^#4WXc3#=7r}cU8ohi2o^xWU7tNBN(it)pIGNIP zg-Z_%T^}um4GSXs53Fffh2b`INrmzQ0-2YBbcduW2T}uvfu?etj9gCSDn_7EJ!*;_ z@a=U?1$PMV!Y)a@IqgT`BH4kXo;+sBZA+nZ(Ez6-m}yYGMkjC&o+&WPj_(_|T{{~j z{_yk{&IHv)$2#VsDP1LK$;e#X{DwLvz81+f5eWY7doZ+n-D7Vv1Z9<^#c`aLeh-u% z{d!aVg=`ohW)uuFo)4oe%e23WBGmi3yfZiaQb=rtuX-HLpmV8?R&XfE&%>fLy$VEA z`<*ka!DGQN<0+T+?Ybx8&=m$kw9}Km-+sOQw;Bm8DoU;?US=Fx)_6=3=;?Wlp9@|y zfT;-6MImh`4JD!Lpn@Mw_a^Y|{xPTyzA|{Zf%tmS9b;lX*K}=+{(TIX z9t)h(J(6Z<$0c1fZ*!LRxG5y$!ga--eI@(t5}J-X`pl*w7-w;|vun`3p_t2TOZ%Un z3d65QZh%<}hjaBu!EhJZJ#S+6>O*h|8X?_drI}m7eFX!Aa5Oagp4FCBr{FP6CT??l zY3PI*PlKB$B3}58T&Hz`6O36vk814Mh0C?tQemwj5WA3wGa?ELn|%P^$uHQ{5s(;QM|Q;-GrrR->Q zSni=c$uCGeHt<@3PTrTAOGH&kV|F??O1L4Hq7857J<$G*Ii^V*z~;{?=v2zgvMWs? zC;WTct+qNGrV7Afe1*y=x-yzT<0R7%#QsXI_JUUt;S8|}p$V3yiFH@=Af}lh-Zw`Y zK;Sjh2n_T~ch2$6Y<)Q&oEA}V@cpig+#h6*Sn_<8#l;#NqQVF>&u13kWH{w#27W~| za;}%2OgPj{r!zEe-``D5OEdB98OCT8#QSq`*yrs>D~|05SLh^v{v2Z@`dTBt1)O(m zTCbE_&?lu1yw>YLh4?*q(a`i9jrxTCvChHt>1KGmQwlMBUj;pvG)=`zM$Qx zf0dln%KMc0q^w79fo2p;QcaFZN}7{8d9;(kKj$p)tg@DK-7^t>+r}|MRKC%F8TG=~ zjFCvtE(0S$aXLVOM!)TG4ek_k)(jMPpL19$7x>WLAq_xm`7kW#lcWuxA9I`q*Z~D# z-?5c>w&-Oy=iOzkv1p}sfzrMM4NaV=5^+XoNv>f<<&f}oknqrLs`h*r1da5Oxqa6y zqZEPQrl#&xBFWd)OhD8|GS8)?ne2x~gvnHW0FSm_j}DkiLjEDJ{%6vu`W}&6-ina_ zTH)oi3v8`;wJI1s#M`lUjc{pG(LN_9=K>y>1oTL8W(hSu-$6pFf(M|(*XA{~KuIk5 zgMI4m43i`%WSdm8g3P6njw=!&hgBl@i{Xus7i2I?)dWf z=A2PJN~w`X=hXgE%|H7r@4Uft;CHR831Km3(cb>8{?7*{eEY3?HgtGJM?amV8C={Y zE-HWMU6j)&^_|#F3@iQ6oc#W6qdR*;)Qj-qjm0qOTD@W0tEow)fGC5P73xS=;!izn z2EQupPj)tWPwHY$tMCIhw3qJt+1m$N940qd^LHq0bV#r^f5zKoUU*z1PLB&>5f$MnS!% z@RkYH8jC@^iQtnYSn#Px0hbt&lTWpY7cy>{X+&z-;$()vcxh{fZwowlaS3Wq1rzKOF4lo)(c16Gq@Zdr++Fvhuq+CMT8 z>3B-o?%LqbFL9)CIw`+QsHNTLSO&0OlgDVr{K(2xJ)Y?IE!Vg*08%91+z4T7gp`Sc z!f&(O7EdO3mMJlRxP9#4n+&k;Y*Ap<1JfuHF znz=II%tZtz2#O%Rlqhz20o8=(F4R2Y)Po{(J6%h~uhPHLcqHPro{cd2yGafL_ZaNxP&N0Xgd9Xm`E(3cOu4$H}?G z_VbuiT`s1$cnFH4dTKa*es>_00lYlK z7mY9qCv!&aXsAb@Iz$O zG<*y%AdLh|2%Ki(Gj&vep&`AoDkYpT74nQLdDl@Ud1>`f(wZyjYVk+g|6}hx!|WLaF*D14h?041{LMm@e&F&D(xT~jgY5gJ3h_(*-u8aM2P=eGN4>lht-v}Eh}&c8xPy=ZBitzL&xY2eLfl}1`f z6-r%ueryC|JLq`l3v18p5~-$|y?0iP$!Fv31Ni4?k|l-b{%4{0Gx@h9gPwMTz(hdQ zqfYNH-uvlgo8_;L4~l0eB`#4vUqm@bzS+#`MMw0efP_VCL~e2aY7n~SmN-R(3J2#r zDZDzRDsV)7FeUH!qU5DS)(rkgzUNTBf>?)am8UWrB`}3QlO$0AHgBVZ>z2=b%jY`@V)O&ybU8uf8(!Z_nV) zdk`5FHoInXN_hNHu;UCe1#t_Xbvb!JF4#cd8|W}Ph;R?(23LW=Aoi4vqI13rJv)4t5Ww>hcxSdRwUcc)Dt$jvf-rX}l0VF9l6Y4H$Ca z8GR4FK%Dlp%KB^PPQ*>(z^kMyw0xot+Nt)|pD$45!{wUtI}%oEpO;@GPcCrneNYBe zg7izH{k$emK$~xG^^Q(W*j!HAreI%f^#R97yEAE2|nxBl}vk%>4U~p}@pt|(4Y17*+)x%$ow{uF^$8WEWaaYZ*p!ZTc z?;m-V<%c$`nY!{o3hW1~0^JX`!rd96X>mWxcYkaWEKGFGIM{^p%-wQY%%Bpqg8Orp z>Hg(7!p$z;A0h_)M?{5=eG&1AcxcVfbCUMK0k;-ywU!f4_F>Pag>q-%KV!t;c=j|H z82Pfsb+?i)I^d_NUjNBYj}gwI+~$Cv=^DYUmC%6WLCuN~Rb@ZPa#J;;PX^Cs!b{^3 z?deIpe!@kho~vxnSoU~xpS2u3=ng*ysSp$ zoPSLv@SEkqnRnr&! z{=Tb3-`4Gvr&MpqmthXQa|3c64p7@5+NuM=(G08VajwaesZ9S1m`LLQ23sd-Dq&+` zXQxYmlX*R6t73KD(8_XW;pWdTdgzvmw}kAZbFC349`*A=_-Zd*g(Wh*v!9QByyBzt zI-l2lm6$uXy~G;#)Oe&Jx8bOgETS`6aZ2Ko3DWn_xRBa-!}KeOAcxcFz{LUO?97^M z#?_97sY02nM1Pw8@C|kU%iP$?uQ9Y)nJ@yZb!R74i+?CpPN+Dex~KP06O&`uiR zXfgwFY0txAUL`G6bi5o?fJvWhHB%)wYPBi|86SU}&7UJeF$H6l)KT_>Jx#AJMt_Lu z>cq{6c_C&gUsb(QV-(LFd;Ox=b^9wl!lc&wu>1SBWpbZu%H*j9(%~A3gtntRCxf#W z#}bxaa+-`Z5ePW%9*Zxxud$NSpwZW&241ytyy%a;^VV@fp=qbbuKI| z`MgK{p>-9RBEeDeL2XGTF$H1(1ghirw+Gx)jNtDl}YU z+@bWGg51jF1EluLZe=*`!~CL9GUG&x{(M$pqM^vT@mO-+ES8+X3R9QyT7Xhbhx0Ns z^bxj3%4gwl|5W9zMI;{`_zo~hf6i`6UjN+2L_~*AO*J6HFU%J zjb=o}uI?9`1xDi>4}-&1D?cT}UkCMD$sV8FGf>diJ!$Vxngy4w%IvX3dl>#~7B_bL zpY%9m#T!_;L2IlB$b0$2XaR-%{~j<%bjeBuBTj$`kLr z-$6p3hzcD5WY*@$ym^_;V^rA3R zuvX(+R8GG|9$Rn&o$DqTE_ zjt&~mZf+^7tk2)E#s`FgNC&=1NUJljW5IL;Rqnj{_4r-d966bwJ{D;6dQRx|h?S~T z`y&Cw^v)}(*{m^nb3B8|H!yqQHUu~>6k=7O~f3-ZJ69)$o>OK)gk z)`nsOc4lVmx^aoAkfZXN5vA3K3iz8Qjg_vEgZtCj-MtU(Yy2sul4oP5p$eP%uQ@2~ zhQAS$xP6Yz2HxJc4|9NKJ!rCHPkD`khWER!(xw{7Bn2uD7cJWLQ@cq~mDC@z9FDfU zP^0-U{C3!Dj#Dpe#qsHpblyM2&i9d=&l;--(Ya8GEJ@`m@+N_$Gq&6Lhtx*QOblZH9H+Rk%NX}~RJWxtmpoB| z%aIl&N*9cIqj3rS^3J{X?^Rl35F`jw@*W# z`dQXW#=UII3v{kmmUe9R%Xr@pJ^?bJlCJP=0NL{Xp@TCiUAcp#Jhv=|)LCTYkXPMa z#mP{@xOT6a0Q5yU5w&@duKYddTSxje2^WGG3(}@F%59VlJKBfVWV*{8n_8GfdT$Dx zMM@_q)g@y5XafG0V|FqTNEVHFA1PO^3_`LQ+=}Mw0B-h!8tJjwufJdX+t~oz5&s;h zMQibV{+{2ld!7;J7LE}cYdjRNJa_Ih;nx^AD=WH-4p*RG)@LD5cjY|gB{g@0rEs>@ zw;5N2J6JgMq-6rc9pio(ErRVpf&)86JvK0`Ce(eb>TT%fG2YMLSZw3z4bgVqErG)d zFYu@}#n}MI&OsyQgAEQ>M`W-&qxPc%@9ca30tHmlCSB0T%b)XR?-qw_?%VY%lsu;{ zJWn#b!G|kXaLTuy9eHiTPV3kv!lPx{+E zCbg$^H6;oxWA3X z_6PvX%|7jT|K~??#ZIAlD#k9^zkS#Lkst6=WC8$~bIvet`tu`N^#06qUil0CN0Tik zocq^?r2YfZ6=h%=XKpj(+%Z@%(9+s?7l3w2Ssa@KZARdN@M5mtU|(;fnQ4GB!ypBR zACv!p%avw0Tdmc8?uXsq4f|h2(8??Q?QX+$#eV>z0iH)2&#=2QBzpkPbmq~^ z%l|aeePAStYh{0yuryNxAil$=T>ifa_4lcH0*g6w_NDOe0{QJf%+N6X3Y+-A{I~V} zmv1f26bg(aA>H|B8VS(zu!|pt|GeBxVI~0h(f5Azzs}%qTJJA$ zI?|bk|Ae020KmYljz4bv(@65bNDNFCf3}1-(!Rh_?tRfC`5##2zx}iU7+vfCDb2sh z<=X!#&7ZCN|CHu`(U-qW{QvzyP&#u*E2BDZ?CqMY0Ck1iu{goCQDZ zCIGCCdNA5T`uRS$EvPw{Lf zvEGY0p0w-LUkp4TMv1e&d106zV|7BYS-8?JcsAl;{M1M+I z+WntYJ}UK90OhsYdQVB)^ONC&P|0J#8RGZzP8*`LV#E!J-p7d94T<-khTQ58^?J;J z+meH@&9e5+Vvb2?#bwglBaE1~rPbcic%-#s&B|C`w&eZ~?~bV1ci!`!7HCOfyP4gB z8YM|tN;@l;R(0Xo$(H2`0LxqLUGx#?Y5})5vZbgIoIUPFu72+nUyl@M@)f9fxKRqX z8<|!$SK;YLXYeGb6`e{tC&jaohu&8|56wE^js`Tq{<{#sjk!&WGmkORTw2l1rs8k# zJI0$Sb~Mbm%cM=f+Mv{15*xF1C^+b>vOz_~IUEDzu%&i`_{1YXwq^rmTY-OAV0BA+Zys zGDqmLLGFZ3cO?M8TxK4VXN?B$y#Zjk_uZDBx9AaF_M3tkUY9>{54TZzA$- zq*m1M&_azW*IJJs& zBm8~{xY;4W6;ar*IwFic;cm|poRFe|CR6Rz#dvndm_U=*Q>!QU@m<8u1u3i86&-gP z*yQ5Hm2vSRB#cG11h76)mz%R2Rs6T3Ixd&0|F&nQhJ#Ke8m`D=O|!LR@n}?{O>%e5 z3gmW;xZIXYi4(93IVvSeqEh`9=42^52~ClxIU6lc#=9fS?3D|pr39E^T~24 z5sq3+&c-P+C|JfIO0`VZZj`E7h>uW-m&75=Avn*9pKf+7-PzeE3IGNm6e?a*ku->m zSs6*S9&)dbUzR#L3|_$1w9C+tz2+_JN+$@686+=_m3M@`Tg+V%Kl39FkoOBJO8B z7D^%lr4{JvM5yn=&hvhks!V$bo*hwMH^kh1vrBUyh=Lc)o|S)3l)vMmkh_;paSFT> z83*wE50(7@wEv5^8N@{fuYvbh=*@sW@GsU5)-qJT+fj|=443sWA5VeFsYJJX?3!!TcT%X81n10$(?Ap|uOqJGCBmOcf&{b=k3IW1}f zw$?KM1CJYTZ2Pl^j_`;RtO^a5El2ze`dl8P=U56yhU38d@0tfT6g*S$6)7n&Lx?yQ zSvWGWB9=(GIsrgAxtE+(jrUhSrhrHMldn5>DOr2MXZrw-nSGw6(WAq)#C{jeiITQR zH%S8)th=f+-IA|;N7o}HaD_I-7gjhp4|)?^lH`jH3|sOV&TZLAW#Fo^0Y>hFRSZme zH$+=`pOeMVq#S)(iIEKp4iQOmX*|;p&d;pH9Q7=vUQG+kGT2@6W=+YquY%&P`Cn>spQ5>KmC=On77=ZN~K& z6*GYxja3T+W;|N&xm@m(BLP+?Kn-N75r%o}gXFsLpwXq6TRA(-GYfp-7Z{ zq2@xFNk{mxGHhdC#M!Uid+XiSHNCh@ec@al^@75cNCK8x1_P5)y}&ZVN!IMQ3-C-DngxkVjGL z8lO{ZtJ<{R)b3>3FONv~ytGW7WUXDb7BZ5SkUNyskE<33#cx8APF52A=HHnmPLtA{ z9B(>$oQ%*p9_$C$*Vv;<&(4P?~O*W ztF`mT>3bZR8fk4$=^RXN@-SKe?F!SAR!JW!Y%dL5^~uLe^(kojeEvv&D7DX7Q0&b% zq#(*C8zVWj#NE5*eXAQJR(D}ro48` zCHL8;x^LG)k0NhO?DU-==9*wb#HQ469vRy!pGsmz-qRJ(2p{ERuT8uxQ?@%?2nH$! zX@z(DdS6s;u=9-Syy$~CHrQ5-JIS&A&>|y)qNCz`*YHmQXIdCtD!<%**fZ`+^r7>3 z9rDm*P3)N3P=Rr_X*RtA!Mr*te`yATKh;>y)?qP)OJzk17Q;|7#bi zreWBKU(9GxF6YUCmS0bvcOT!B=Ih-~i4#-}R4{u_Q7#F9?ttK94R~`oxKSh_6!f}( zSy0u#jnq>zGf5SNM}^^y=HuMB0J*;XLjRCW?aDH?V}!oek0lr=Rv=zGj}aAofGfzyh(YdN8kx}Pl(ihv07Lz3<~rjTt9G*tb6Dv z6@&!yQC@(X3P8eFu29@7x2reddq#cC8M^AXb{#SdX)uCep5cZXD7r;9Yn@V>=QHLf zThnOtb8d!~1_ym1_YAX_it9hcSK6W`B#)EILX~%5EZmEtY2Qx-#8d2&RK-$h5@`X8HBTDXJLX6c{YCak^7E_np74q<-;ZjR`8z0)MMD;NZt#LgNAd>GbfjSY zTY&q+k3S+=b$CMMf7ZR}S zB8sj^IFHTuAKmVC|JJis$LIFL^kAokAe*X4hjkyaMbuH%Gj3m@h3#QZYv}@ymI(fF z$B7^MfmVe#iXc8Z<3O3cLuj{~TZN|mTU}GNGi*4b>WBdUxWi$*o5T8c{EDN$_a2R- z_@*|#c>?B@LU5$=$#IuJ!YXyQ>tgWY^@5&==_Rk9&+`h!R98J*cOfbri=u07IVnK| zDIb+=@2l46C__K|gD=iTver1Bt>F|2ihr#?kJUyfT>@7pS#<44b&|#EfJnu}gvm=s zs2wd&W6x-O8u!R%p*4+b1un zcXQjVJ#vGwvRP&arWpSMXpw->hJ?MnY@PTmkNiQO)8 zQ5KH|dOGI(5Y{#E!R%SN78Wk}e}sTdvj^GWMWxPczZ~43y>?26#c0|kA+hD>aOG={ zYj{5;D}p3`$RIB>2x{-!4swa7D!U|jjCC=;E%xcgJKzgzRP-zsX%z#pyT?};74~eK zsdS5xKt5EzY}dH%V4VH9V8whXTv3YS&}U=Ovgx3+YhvE4ZD2Sny0COZf#Hl5B}pkq zt(Lu277}aFME0)cy$&O8Yy4jMXV3m~pYWbEDhl(SoRvxLBX=oH^Mf<3k84NA&P7*+ z7YvX`k_>?s5?8pdQg#B4WRKmV2t}?SfU$|qsvWNAO-89Ufxlb&JjxAB+~8dqDMGzM z_AF%(_L_+Zl1>FL6=BC}RjWPJL_I7>m$VYAXNKgH+T-MQr23#?DvH}d9+$VIpn@+N zUVFR0e|U=1iMH@Un3|95&FruCR+Gi|b<3J1yn;Ply3L14are?;^isnY<0fOah~M!P z-w*OaC0+nHl!k>vN++E+UguCu{o%o{PBY$;4|j2bSpgtYXh!%osA=ieQ0Vu{+GGj*U7%wy!(U3&#@ zM9X{@j2{b4+%Z&N%M5FP{$=%p6DkUO$w%v=Yri99n66#c%6}68(%-RC;~khPSQHwH z(u(aftq|+&-6ts5tr-~Me~{YA2{_mGns(=3j$Jk}4AfFs3Q0@BCTelplg|{`vqsot zwmc8?;b`TwH|QYiiqtW&$EcYW&=$Vdz^ZVZI! zHO4LQj=iR!vZLhDa)(;(Et*%>iDxmtLdm+O0$r+dgD)J-OW{y-%P4q~Z~MC2X493R?Z zw92YH#%zpnumC6f+;5tJ^&EB>usWiqfecgTy#Y=`P+0H=DJqUVl1{8L*A3i6xYgoCkSqZ_mesukL-sj=yT+U41lB z8Xx9eq+ERWl2!%Y- zpAzDBbg?%vT3BG+E5Nx%dvGkQ32y7waO2?)LV>TLo1WrIlOiq@j-sSbseE{k9DvJJt3L87fG| zR2G}A79BCcv4OY!9@He`Z8?Cc?}#oyy;7IzHjqa4lrmGb7A*+<&<@La%g9W{!>jMp z*2DbXhQ;L33#D9t*a~??V9|$Cd-?vU#eOxuh^kuY zqow!sJYx>DHtIddC|fy>Qk7$Uq@Ao(EXfyTU$#wc99*VyD^|QpnkU8^Cz&<<&@G%o zqVV-4%3=WHBe}gfasY7hWPktec+)e_JSv4-12j}>5C2hK#Vi>}0UFOep#8$Wp6VWi z$vI&@Em$=#+%E8Gc}|!uSuXAP5%I~G47_S+(Vr4$yObYm=2>kF-J|uxEVx>UTHbJwnRPb-O;NeyAOsTR2n~y-&-CFi2Yv`*87I=*8(S zRA1KppPumdLbY^onY(<>v7wJr%l(N5$#W65#`+SBQ`4W(tho8dMMT4v8;$}vI4B-d zQDdN%cSZ}Ru6Q20y}8bs0;|x+y@J@+TibYM;*Snps^3$qFF80MeqQXXFr0hWx!Ij) z5|6g|Sa#^#F|0lP-k^}aqN8dFsC>RL=Pt3@noeyJ>M2uV@Z`tYpc!!f^nkm}M)F=e zfqkq(0VpUaTx95s8ORE&#^bD8R+`c$e2B8Si&B zZi70+9VqyANBOnQDjY~|dJi03j*2 z4(PP(FFu^Gv*--0XyyPSf6xIXpY^h!+E_-rNh-pC#~WeOO0il0&9Qd2n=kvxTs?l(Kz!>XV)LZ&K$%g@#=G~P zxCfR3=r1pSD@R0fxWOmHQqrg{dKkLU?P3*C7wzT_#Rgwk4gJ~}#ivVd30-)vp-9kqKEE;3kJi6Qh-QYgLwmloc>Na_ z03z}y7Y;=sS{zkT9DDtOv-X-2(aK;S2ccXX*CzLYZg1?@##dB%J9lxy=VdoM1U55z z@L+7ogNl?rV{8uBKE)mCRU_nRl~3P{+GhP=$Z*YG+vs~qTQDiFj=txtQ^TTUM-)F= z09Q(TAd7C^Wo1Yd!=ieuLuUpjtv~Bdxs&{y7v2k)1yCEXF$0q4p&78G!c`M zFSjwNc{5bq*#PT;_8_eDLXjJt?c2+$u%AEXn>c^V*s4X5au|J+IVl-XO&qBEaUF_2J!<&-RXbS03O2v6P#mFSR_m~VoFE0;-6nWts`m%1 zr0%rf#$iI2NRdl}PlY}a?P~poLN0*6Xu5K(=ahPOp_HM7f$go3LHygZY0>V^suy=n zJM0aFk!Ip=MV=+Ktt9kWi&F*PK!BYDn=(Rf57Ob21%I zEru}VQv}B)0 zj6WJJt50%rt_UM8DZneR9J=kD8IME7W8!RR;e60iqCUb*)7}bssaGscWs-^CH&1$Y zc;2K`tmY9CUR3|E0Pg!UYQQ`?+$IptVugyt8?*o5>VHs00ToY^@zFK|8m}Aj7rQ&V zeI(kDuJ3B1N4kCMLhiU^+1F_ge7YB-TI5N#@7)TOjN4OR*iOdl9p+KrDW9-=KAr15 z#ck~7I51*^8N*)K`_^%8Kl$c zZK^L$rzp-t{UaqpJ2m@6m^r-1YTEoygRDK_S^5!A;}VEx({iYxoYZKol*J{K%DGyO z#o=849_Sce?}Cx5@kbI*q}GsGim=<`9Eb7z3^|W%Tkv)>;%tsU#7^E>Tmpa2&M^GkY+A=Hk1j()PNm+eT4o zcwSb8hK9|sgqL!6|AC=rg5!bLPdJVZ8k*z3L`NvIRKF&SJ-uDDNz~6+e%0=93Z9=A z3pFHG)#q%Fx!J@d>-Z6((}Z+K?-l!{B;Q5T?r*yd^(NV+JcY&nv{36aopNm0G~UHc zzO9$FgHY%+V;v4@86imKe5zTW|1vRZ!u`GcqhNNE$@avo>7x^KQ&_o=1mwAkrsnZ>WnQN2TZ-MPdfE!+8;jbl7j;YgqF;=`*xn; zqfya$b7LmVp~^x&7^K z*K)L<;D}RiNpawn*f#x$=k4OMYeFFH{Qd1z;^qtST7~Dr1I?F=GoQoVvd?0K*6fM^ zg>JKqMj26EwN-P23S`t)&+S9(fuQQhmUV>Uj3)q*6WwUjiGXx0+$r0eiPzOZ2kqY4 zj*nvuG$vGqFjoP^UD}&^MoonTBPC`+j9o{zaz9vLenK>D(07EtZ82^>F0q1-u&tzi zHZ!>kfdAk41(5BOtY-whqwQ_O%Z)jnCS1Ba#sff0*`1J&uOwL`DadSM2_Bg6Cq@ge zjB~1r?7K9_Es8RHfI64W!K{P5o!ut)S?}bzcAOy&E9vUTTd`cKuiV!ykDonQ?d8u> zuIiS>DZnnUsR|i?to{a+a*c1*C9lLGXt&$&tS)2a=(q`~K#BXCNsy8HjaicsFY|}s zm4keV4atf1ITyX5d4+mgHk<(G%CJc?I@VjI^LLg;jxy=v8~X~*TO1+^oI~9@yJ2oa z)}%YbApbs;`t|-8V}rAR^B+F*I@fLCd!`_by?{MVEPJ8SnIH;b$_+COK*j5Sh=r*( zyO5357r`ILU&yE65{Pw9s>*=7cs}fgP7xuuyWfY465( zhO~`k|8K6plmh7$d#6%lPujiAr;xJe~Cs_&Kla2Qi#8K1FzDd#U!I4Fwya z@D+njsJ*Q*3VOkazulpJn@1du%gdX1z3w^Fjw@ej!OvAU^aH}5J6Qc#VG@ruoKIVM z<swIbHzRaL~;rK%X$64${u{&Y@keajoMx4}EHPbMJspHhE4=h7O5-a{4c zkvWrRfe$)1Z)>(z6<_(?+Vn}OGN6V)>WKv`ToqHUhPW3~RCPFC|Lq0(ipCQ*$y z`X_+W@F{^CL>2W91a48Ml$Fe7NfCbrZ>8D+c(lkuR><#;^53&AsS3bIx#7dz&;L9f zHPk7%a4@3q&mcQBW?&?(HoN)EKjYfiAOPyh9N#wh_wj%8;IHL|pMnctpFRQg#c!)bo-UA22{8_sW023SbDi!+kBl(%YNE~r1iGshW z*l*J@=LAr(cHm*!KR=?a0gM#Y>8A1zynm&qynm=`S*(o0&O zc%m)|YejeXPye_6{M+kI8_#pdeS6V(H3|7|zxy982i^wQ8<%L~>p$-i#g|SgPu~fI z%Km<&{Qb56_n!Z6%E$kt!ku+ZIMVM)~WK&<(+eX-Z<{-0c60}z1N1I|NfR=&u$FW`_%aCFXrq3TzPk%*U-oND2JZ# zHXOd(oa+)#ttE_B_17P)ibEQFkIojdB6%HgsIHTut2=HQIEuOZZ{FxHkX!|OZ50Re zRJRTmLfq9t2_LTCKXiKrAx!i9+w``o8B>@Lb_^7}b`@`=Bo@FJb(S(M{nt>7vu zzR*2l87ezitw9@mEiy|fKiW2U`e+nJT-_#Y>-%AiVTIuB0nJlD2FtD_BVYplolH)} zDKu|43FX%PH=F<-iyU9`_ z83qtPtDz}8pDzlKvVQxuZR%j_hb?^5)RQJ_-#a#znlCl)*q_k;LMxcCsH?5(lmEaHghSc}9C7+rh2g*3E8lw5926d(=+r{ZKtX=F4zI zeQ6=2!l2G;dpRG-uW{*@?phVzi#?@t;;rBP4x-_)v&W&3V$h`rmy2IEgBU;RzBB1H z23JzDYy9AaKRyQ5zsq-jk+uJ0neWlQ+hSJCK9Rjklk>ch(|mW5ZI(h*DH%`Yw|QAk zZSDdT9GhO(h%`g5x7RyrxV+rRDUR8d`xop*EzTW(q``bUF;>Mu*LJ? zFym`aoJ{Im7d1>i=DlqGwtyjM$UiCWWs2-0-EDcG3EwI9~O68F0L5&>d01# zdkHiqM%iHUhshs}{vu2w8JQI#*8;h#8>9}F%T~(!RmvWXdo&G@|J<8TailT!NHfVv z<}LrS*q;L#uk~CRbwO|YeH3mz4_NW9Gv`%AXDKyhirbZ3Cw6}YP>fW*o-P1XFM8DT zS(J>nQ-SkG=h^nXLb%=ZOoZxAlxg|ZBt}lHTvIY?uC>{_euwKpQuF!Quxp>y^xFVK zv5$BEewlS>HpXPt1mhFZZtQy8kqoX$@|=rv8#a&GD~&nVYLmU2Z;*Tbm_t_6Q$OSB z7p2*kppXiy-tQ-JW}R^YEkK`V0zw8bXcRyJJQ9<(=#_(yEs6sUcp{-zV)yIj^4{Z{FYqkZ|JbpSLBMQop?kcbM7^ zOC34RAIoEUQ~iWi(z`OH!E@8%0Pqidus1jguwB(EFM&L8MGE7Q6gYR`B|KHS-h1!H z6UmEL?^rD@r31$0)-5_eWSQb)0odO<{F%deG&iI`7h!xnljp$W`d!yWz{oYqweNEQ zeO5$Od?tILQO#h=FIDiimhE_Ll~fw=dLlIq&3uA{&27x%p5}o6=*u9@6vnB`!wPfk#ie!J^tcY1ZUQc#3aq9{fWYg@g+`~qqQaq zb(c;l#?OpW=hG5Gq3yX-f)fkKuLXz+bA4(d5%59gO18{v?&du}d2n zl-nr_e5x$asa#@#M9E?3$BK+<3S8#9C1X>0JOqu#Ae>h4$1jrP0q#DRiT!)$%4kQl zNwI=^7YQvP^!RhnS{Psjd3`opBA3K`#i&6d>_e$KeKu`5Zz?%9j}JG|l4l+W8pUYk zEoMfjlme$lOH5rBsn$UzQy@n#2PyUmDdWJ3#u`k0?QZp ztSsZFeZGF`6Q}nuZG+Iquh*WXNLv|*u!*FScqLt83&@%ZIDc(bzeh>Gs=|$@%r^WG9wMIrf(kz)!I-yxxoz25o zZI%@oAF_Nw$ZD*BHWnmerLWD@SLP2Q45%VGr1RdF*o5StdFGdYE9*><&E1I8Q!s#8 zt=8kUA4A{1rWnPdVK((84mO>=r@-dzqX>!eJO8{+B3DhnkWq^v{a2n>wi?;{=3pA! z5(e(0|HUg^ZLbqd9G!-U=YG?#Q+U-8-9;;Gw?Nhyu2Mc}Z>Z}{P7Egj&5 zY}h+fS5yJ|32**{qI!UIyNrTw6wS1w-yV_I$Ba5^7CsE;tkINKih6_5kZq7-_OSCJgba|K zujV@y;o0-wc~e=?U)lFvW@Duoe9&DUy>NKRD89v$=GKbbKXVkgRtqhGZS*}K#<6L=*h;NEyL9L^WYRVQX}mJ zaj$x{E-hs4ph=k4`lr(!;EvMSBpOVey3PDusx$Dp+Gx$;k0jSX*PgIMWj%=wT9BY| zZOi~gDU4M^gAYIPa`y6rbaFfBG4FLJi$Pi1JhBQ6(rOIUt~5o?MN9w~tD^xUq}HPF zywRSt6WDdVPDFQ8yk>d`ve+Ke;Z|GAV#Bq3d~A5pN6;;6ebT768xOn4cAgWoRjBu1 z&x;PZvL>>39s)*Xe_w1J5==cQK$1uHj^!7h%>Y{p?$?~*_2)@XD48zt03>Ks4@j@v zBhwprpvtN^)(O8It)lXEGk}m+^MKi?)AgmM?Rh!V?K2s)s?{PkV=@{}k6D$IxFQmA zSOUDP)CTl$SH>?2MQr)VX$557H1lG3@HQy+*Fo)HHH~+MNva*#@&LM|w$x06;_51F zfT2Nnk!N*w6clM55aeI(9cq56_4l=zvgQL*HPp5?-)`i;4M~N)U)XyN=6$liF#MRC zWq>>|+<=L*4sa(W^-}B8F!u}strx*G_$qnyeE{-<6teF7frvRd4P;z|NDEC+Jy4_R z%S#G+Tf(SioW2@4u&wS2YL^`dmzjq|ndDOVB*g^0os$W;(0tK&`{V*X}J$8E)P~Bz^5z zs`I+4&dW?Ie~+7ex9)+iFLl9vMC%A z=~4<-e$-`j&R5SQOW2px-e1TFEl^8)TyJVZlbI^c+|}RqL^+$PO6$C_Owd9$+CU{x zz{Vn*#X_d<+=pyhdw?Pj@uwU#&E1UrIAV#M<5a z(`=L8_Sk$cNR@rHIlYj`A)Qtvq9yPQD-Rx$Ge)P!%nJZ9k!#fc1IaXk(s|+4S{M<> z{J1@!8s-4zKqbhQ3jYs_`gnrLRd13Cwc_h$TJ$c=w7dr0OFdG|yI{3e*Q%?n(6{;h z9^34a8 zrFNBBYQQL}5kK-au8m=BzFCvA6?!fOn@qpruu5|&ds{w2p}nS60p_snJexD z@`NHgzf|2TA|x$Y)b&vNXVybuN)NT$@$G0Ww``eoC^u{_&eHpgjQOkhY_na!tIl+f zXyai#G(PoP>SIS71psRzy`$x??=J-1&a7P=X?Nrfo2BwEzx?jruhjZ!*B8B}LNa~L zPmfBijjuWNbk*BjXOB%KiMvWKc0Tx^wRUj5N0wr*bc8jMKCq@;Z$2!KdIKVd~P0+C-Kt{x8K--2vLZMiOLJof)}EESvISP{@(*jNs*o|v&X z(gy%O%)S{EK+f+o$PJV}sdLKJ4oH@Z9N3p@yi9s$z$jIc^VU}_&>(PdCh?wCbUJN7h$xaQ@|y83#&7$I?c8YiMVpvzntvVYoQlAP}=w%!mHhIF;V)? z%!?O{-g)gTTYq|=|Mcqxf3k3ux7BCzznK_uvg=)UZKC9g7}wo)&$*c~NR^}!PveTG zJff#(`J$NiIDIQSRZ36J<3HM~P2LzPei6{%*87RuuqA4g>CLw^no3}6^9f|cOnt6r zRbBCX>9?apBzj#1{j?lPfu5h}-3%P0+53F6bDHY(Qb;mrMT)ZOEY?OS=g%KvS220p+o|( ze5aX9xwgzl|G^@_ufkLX)W_WgE=c98fvW_~5fuY$#;k@{{WG+e9yKu6Art@4A{1GI zI_A!s8#8TX4KgwMA~|zq$TO9GH%& zsPTUW|9dvIlP=fiKb0u_0g{M~~89yj^#fL^P}S+Q-jh~nTM+OC~C z64^j-H_Vy>eEZMgJf>+Nb?_>Y+4gt-y1%@X|NMigABfbqmIoz&{&S>0>@^TS=kE>| z`g5c{%o>Q)zZ#KM{rTsZC-9|6uHLq6i~sxh|NWK!3W2tkpN_PW#yb7yF#M}TAb$S2 z?3MCAJYoQh6t~k8@%qm)=2rpY=RfsJS^nXX)0}`3Y@to$&tdr6Ky$9U(_H#D|NKbY zX-*&;y!GnN=~?&t7yi$W{-1BQmSVF$L+Jlusel+2n>1Nar^i6s=^6N2!r*^C-sS=( z6dGjgaA=5<4G+M#!lD0i#{ zt_Bu_mW{R(?uai7Gw(9$oZ5(XMl^SoUds@5zRC~#7jW$VOxG#*JpWi~FU+l= z!U%6MQsifWOHNAYn@tpgNd}AWKM3a3Yc8E*3o9a&^8NWsyr6ECI2$wuu{-!gu$!+o z=@K#%DK?8|PB7>7_%zF^ z$*=-tyUhw3Zh`rK+WYcwHrKD+R%w;p(m}Pf=%^^#8cR)`%+*rV5JOER5@V<#6m7Lt zLybkvHAX@aLqZfq&11wA(VE3f5)$FO_V=B$_x^on@AJ?3bNeILlk1Y?d7pQ^Ydz1p z?{zOdktx%gm2dAI7m=vtRESkhi$AJ4c>QlLRcMsuC#U=Z5j>I*u3OHZeWo;F_{0I> zp#!wh=R6Ou#!P2nCzp9-7fOpD(}ib@m|re3{q-O`r6$qUnvjy(K_ zegEg^m7$R5{!kDZXdcpdkqFds&VGVR*`?NO*Xa%H&I!azTBhDx@4IQ;m0BaaIAe)a z?{aY79yg2G)H>B>SWwl-Vko~>x%@jiRDXAi7 zFnuS|B=vUHuhJUFzEjD!;ql@YC8Ob_V#0d?gC7N{zL{~#sC(Nt>yiz@117j?ALk}X z52OLsv~Dub7|;N77+S-i5`L{c=$N?p_jm8-Np{0;)_X?2j6!M(1N2$WbA(=w=#AxXDn``CHQ>K0tJk5D2b7~-S&cy36IR|=uZgF5eKj>72 zUuefC?2k^Do^Rz4QtYIc^kYUkyal#!t3{&Wx4-jFz>)S6chbv-)N^DAL8bPxpR@gL z)hP7&=#_vSj{{?+7ko;FR)V;$@UhZcIr*_K>yPp)I7JiPmM6-+mj$rv^PGhi;W0?q zOe%G%a=CB>M)^gE>*rr=OTB=;2999S?6Cg_pflq*yY4q@0wxjVShr-$)!B;YN8bB- zAz6nHKO3kNJy?=xbv1{2@S z++h2w2l&&|85DKc_Q?GJbIwiAqL{qEK~;Vrm34Q!qzX z`+DiquX-C7mwA$%XHb)72CU>>Wk-_6e;N7Nd=|d-=VNJsL-R7=n2!1-A{NrpYgg{j z6~s1_AZ}(Ic1l>VpH$_M%e>)&BhS0KlrY@$?45_Jhm26BDZi%Ui=H}~m0waSfAZe) z!>4@6_N_oQo%L(9>_GBn)0k55n+o=`t1JrMoy-Y6vvU8bV`;oM_x$visnlba_pBkP z{X92NQjO{e>vJumHu1i)ZHaE2Cm^8{SFq4ey@@6E9ZqqrabK&}`>0k?<#6rF6Iids z5})a|$?sIC7~BG&}V>I_a94+v17f zqTDn+SI|6l{De`y6Z2l+uvb)$4x?q*bJq4q7X++p=2h&`33ibR)RdPnAk7?nTJvUR zWD8PM_NHTaxOg|59hW)|8=)?GjlE9TTCAbfH6NayYp~=zH6)X=ys@tSVOzAvU-vX~ z>P1DkY(V0yP;32t?ZO5gxu+ezGs7mj5-Wk0k;$K|lrBDi+fn!{N)GCd49-!KhNg^3 z&KxsmupkR6o}DQfd+iU7n0gj=NXxE%CBDmk!OYKCwO_YLw#q5qD&{P z*0rZCtui+JhEk-uZZOUIw;lwN;3@z>B-?`tbOW^q$UgJToYUD0@R@8!H&So-!u^%E z*^H2;HW)8~=TnKy7RPH9H7blYZyA@7mW%v)wsAqV`CxwAGf!h({=4FGa{yBmEO%`WY0EckB zW$g4|S5BZ@6J3Q-nI9E6D7?#dz^KT=hS$Dp4eBUzW=2eblKieG|kyE za{C94UuCqw5b2!aQbk~^kfYme6tB~hLl(b=E|-d&P#@0bt@wIKa1KJ+y)GVL87!xF zoANm@8OXU4M1`!w!h(uwCpc*(cG`5R!}_%Nz}%Y=B$=s%?00KEi1-j_*!G?uTGbpO zV*X>9JbC!yLbXTord7u~mBeTLaSDv*N;i4!_8JQbb9T%)`=T7i?GmuuzshVm)anuWO9fJhj7sR=f^N z7;H55ig0P^E+v%8k`sogW66?R6O09e$YF+Hz%!Q`hV_F*7P8uS)M0biohsR1G2Tql zMC1a0^CD$Gd?FX052v3W;Z5lqJ9oQ3b&mN~H${55DROI&FBQ~zKW=uu0g^axPyTr8*L3mb#QBlAMMba8Z;Ta5oQ^@Kr)3^v{s=#f7@0e#{g_jv zcxPJiZe~u-&W(%ZDRiSfy`-Z#s=a!nhdja#Srh%rg-IQEi>pqwo%(uTn@ap9X<9w% zlN{dmfxQ^dWOMrEIUXEy`L_Y&eaorRws+l#p00yy)MQ%08OtYMwXT@siD1xxO; zg$szUq)n?kD<(xnM|``W3%xP{(N5*%UTm&uTz(_1vC0wwzAN@|oF_e>6NV+QmB^{~ zj}5J9uGM&y3DF+QLJ>0bQVVuS3+OLMGa6c(?wBy;8Ys_-RBnxbaPkwH0Q2JiPe(bi1}HE+9XKUrdl;93qawi{_+8%IX~F!+vy$jDkdD&W%Ds+ zf>dNcK0@GFlX7skMoh2vg~$~U33CP73qKjlUTR6dB#PJy-LjMseOnp8Jc!L5$?}3Uw-q|Y83gNY8l!t3?Le_p3d1+y^qVqxxYkT7q&qyF({FBC4hfcW@;RO;Fuzsi!gK6aIF0@6Q6N-(euOIA zRV=r4tJTidKF14m10V+&A`!UcZA&2o;<(23iDvKG+Ev4#~k8{Th*D_va ztmT1&;_(>IrQT|9lHhzr+wNW@eIE3o(&2-Ja2i*QYWHQw72m5=)h_NT_eF%Q=hgCN zS>OR$IX396?zg$n6|mSc2FfR_sMKhkVZe6o7=L=)zadnsSa8L`SJr%W(+0Bh3+71I zGNp?9-cJVAcBjFqiD<{ZrY8qB2$q3ppsbM*|J!Bl_%f-k+kJXmINBa`BJru;u-`E^ z#a=kgzXam>_&M7AswJ+P38YR@=|V+m-rK9qjG{e2&?xWGdGKiESHHKW_5eJG2Egbo zA@z`hNBrB~0h$B7{jd80F(n9)#6<(T;U@X|*~dNOGN3#-Ce_TW#P*%oXp6OQ>WfSO zIqq<|yS_)t0P=|?w|&;00zf|U&TEc3sPGFzfsNeigsYG1XCBu@#tx_e;DGTbk602= zE-_gXldv8N4rW@M5IO1n0M8 zImjex|6$IYI0v2_$;esZ?bbF4t&hJp<_&cN)%0na2Dx3uQci|kSGMYJ!n><{Yes~5 z>>s{R>YmsPsANppA zV(t%s0Z{&`=Ek^*iX%Nz>Vm@-&1Y@0oC-198en&FEPl~KqK<|Y4Yvpz7IO&4uear) zgLnFQ`lySF{&E`gC13jDc!i&m)+KAEL$>A2z3nnlk?vLCr(K~toJZ%vNC9$<94F;l z(bZSy2w4NioZh(waegSP8NV&)KQ}sM!I%tD!`a;n4$od~$h@yDZdUHRic}mfgZ`v0 z-a`2J$|zDMwPd~OE1{Xi^w%gfufV2_B%C?pn(}~P#`cNu>${v_XC|jTTjg7Cr^}Ggn09AVIVr^N@jI?Xr zTZyH!w+7MMnC1vCwIRjPEw?4Xbx60O;3iXF8?l3GOf*dpd6cN=Ey2G*J>C3m(bq48f&<@=WX%G}?nNEyYS0##NBML6X?CK+fk6FuoqzmI@6X!bHHT zwoLgq>Dco6aF9_0h~!JDCUIc2ZfRAGQZ$eeA=2LsFZed2*UYBl4ebDBYM^lX*O6)U z+A9?h@m$qi4@sPTpLs&oYY=(jjRPLm#U)oc6M8L&?5$0>JaYOgl#*t493z#s3IiiVpH!x!J!pM|DlJ`KqwdlUDdxdVKT?XKw+Yi1T{uDn zZBt}?1-AetQBBTQ7srbo{CcaxKABF$>QiUKmIu2tET6{s;?29Q)xVE!)O4gOb(Yw- zEQOrPM@J7Pzk!F1VK_vdtO$JQNry%N1e2+U^XiP?-LE#yrt8zY`0D;o8~~A_91vx( zq!PVJCROfJ+urD-Xh3%1ClG>*0k+cEN!M;)nFse6)Wtpi54A%M2&@gUA_o57G63Iz zGICU=ahJ5ZtOLvzs@guDS+VOGb86#v>fZ2(8Ex(h66h|2vvG(T7EF@BsZ`xM4so+$ zD>Y+o{Yz@`JW<^^e4$C7QW?*6*w7c%`!QE^x4omyYBABhxaZ89-Q_%m&xgzMxq7dv zu%12sXnp^F);kwg@Rct9$bPOdpGLw<<8mWxFq0PQADv#Ta^vMqq0^mi#vOT;u5Wk0;eHZZMoTKW%EdR8w#eH$uk9 z=v_T`O)l;;9|N`^5g^YwSb(9^`IP~17h_yw62riJz0qHAFQ52YeDMvq=tCMZs7PgV zC2*k2B!Al2Ns|fCd?szk(@v^~&}oJv7z?85DbFK)-<8hFy2HPbE8H|0oCapuX+?G4 zRCYXHajk7{_UZI}I)?_SYRaJE`U{@@s)$((3QgNcqtt>GEauIWW|>$vvFkgy{DJ{vcA^Vjr&H>|H;k9KerD)b;qxAwg)@X_ z+B`2KTGL1sw(~Ql&)HrJXW{r}L{D|BgRuEw(kb8wNwZ-W{TVanh++0;AtlN^E|R|Z zW??+IG#~{sBMUjL^Xqq5!YU|s=?vG4sY0O!)+Q`?5Kw`EiYKSpK!}vP#0BC{jKR4L zEfwRT$+FGG>Xlydz>r~-NtF{?urDK5>c2^rZQlJ52cF-zY zjeX#ayy$ND6x!QAJtLWOJJ;x)D)Kf8J0}qcG6pZ6kqVR{ViP>X&*SNji0_YjtL-Mc zR1PcEejf@es&*t3TsFFHePlHIv2trz2my$}WGRhwmO`iwAe#CWxptE_zlc&c8JaJL8Jik{$8R(b(S?}SH7=epl@G?nm%MG zB<>)#9*Wn{7u<1T<4#EpoW8+(`so}8R+zr}8?fi@oxNr(_98TeRFVk#)#S>KIpQ?* z>#PcU3FgA%AT&x7GZ#35m*sF;77X-v^jqo4-M-uY7{wDB9ents=7GVv^LI75REuz{ zDB^^vUmm`>?x8T|jzTziWhRZ&eBYFZO6B_OPr;|kgrw^l31!{~w6O7fDmq&|72Dk~ zGmyB5(i}$X@sZ+LKHEC)i z2`EmfZF@pL4SlWFCRA2lt06*9g3~ zG!ic{w5D+oT1~};obY+}rJyzrH1wgw<%-23qExe}vHb>cN~I6Hq6Zu`Hp&?Y@DfU|>CuYW`5In%24++^~ zw*@GC-o@&bcj5~j$tR$T^u=<=Hd%)KyyU>@817Ik+26-wsHr2rqELg3yIdhfCKS<- zzXfkOO{Is19^sc|jq&%^q^Cn)os4>9?HAP_7p)&)ET*NY+i>z8yOV~~wNN4XW7iN< zPp)Uia}48HPRu`3(=4jP^w+DliF`VCX)z6V;x}6*w_o@8Z@(zs?GqYI;!Vk1&x1zy zYhBEy93posi?T6zf4jrye>DDgNR>V2WfE01&J(>IqJkGSma+m}j14y4tz$~A4Rh;g zw;?z>1OiLai1P;{j|#|U*5)pS^I?ZoYXlaTu)Or~EIsChdA?aqLZJfCek0R~RB(N< zV#tGeQ_XT-ZGZBWf^-Yb*FWdIL2^{zZ|`&hu{VzOV^lQ{Xe|$;M|cbK_1u|rblD*u zYUF8(;UwYaWKA%&;42;n5+jp?uk&43P#Dizz1qL{ezafI>U&<%q9845Ee5e#xD+LQ z>P~UdJm3BO{70G!gLj1-x5yw~(PpfFfse0eZ{?Y~RRSXT7HkJ1D^TOCpC*aRL+iR7 z&<6`aDZ)jIZ2OaeHcY-)lsEAgrWEsIejwkm0*f-0@Inepk3*t>M0Nimz72+cM`iqy z)Zw6uCPF2n7f%bG{}H(pF75&9%UAK>$-DY3r;cdo>Si5^prwR)ExQN3fg^wGM?com zB!0;^lV*e9^|jc}n7Tyu_K9lS)IVGEAR5mJQ zKS_N`2s*qi%b;zl1`T`xziI+A@Vb#Ym@Y2;DFZz(HOg*lrgTjSzxOqbI6b8nOW}~N zk3|$vn>kExxX|tpq2$*Mew9^4m4{EY2(6Rl$Qx4+<#Epb#cCt@eh+j>qQ0pJ?pRZW zCRp7UtF|nZ_VB}$w|M?8KTa<;R(+oBG;jP2-QdSc{07W+N0 z{IW#kB9Uq7@pJO1^G@{;a_|P*Vgy36cto-MA@r-XE~x~DB_BKwQ(hbiy2P^tHV+oc zPrh`SZGW%9i<2fRU-kvDoD%(T*z|thctGdpTR52zj7V>K&-}0Fi^FJ~pD7tAtc3+Nk8isn#SfwC%G>l&Q{LH+(O7ytq29L@0-ZGKhx9^gR<~_A1a{1&m z#U-C^uEE0TuAVvI(9ZmHFaZO|%0B62J2~B+GNZCH)#Ok~ZNmCno34CIU-}574Hh{n zY4~2`Ed98#m8#A4tEw5&r0}XQCs|KQcavv}ni%_&Wk5*&D-V;L#mzgOT?TPQy1|QZ z%(2j&(w$t>8iSmj*&=X3(C1^Cb-~yrzwcw``bk`TNLWE)r9f;yFQ&It^0y7!?CX373%&FFy&&AA8YpLG3FAzOQHz#5FuoQ zF6;8>SV?m`pkBL-c{{uydO;e}s~Yx^TmBd86GwGg%KD7tb&vf|vS-(GSh8}fb`Z^# z>pjLc!kE?LC`y}d>P;fP%-jZ0vRkdYr~7%jsag}oqSH)90$9YtFP6`BpNqR-L1%Un%o|*St6_KZk{7eMF$&rW0sQpqg~#TFBs8qn%RKS zGq!*D(4kShpc5gn`j>+V2RA4@Z=P5`ut8ABD%}=-RW92~#iE+|jUoE0&+aqjj}_Re z-q{Bbnzp^CHAdD#r}RxcPL(K)5OOdsGz-#TlJ~r|p`NJ2Or_gd1+=0te)&?xxB6_c z-u{$m>Y{2i2U#XH2y<3HU6m+sZX(Ge|4QIwy4T#$8yuqEKb(|~ifsz#pTQa_OvM^F z*9Ei5+P9xp*;i`HH>;*ucMxK{&J)XCj<_QZv;1;{w_o87{JWDYxxf%XXDPB8`<+;; ze?{lhIM%c`ePG@~lPKxv{C*-ru`}{w#_a-za5yEsKl6T=Eg>y+yJWAU0JrRZnJxGj zAkML0t;ie6_oSPVM+TRDK*;RQYjclB&c`S02i<5s?4@~NNko2qDV=vB7qJXG^3X4kFtRXn zruMsDg2&g)`~KiJp@L+aDUh6~175K~a-=Q1v}gS%YPF+QX5W%L!BE?_SGBA8Y|Q4^ zy*mEz=JXwKmvSjeu;0waZDVPKzWxL$B^}>pLYcqh1J!_Cz6PLYi55cQv=4~_A_w>J9nb+$=PdMTi}OnwBB#N5 z(b!YWg(iu&I#TvK&-hAbt-b);4Z2@zCv@Q=GynD78M7tI#JOzRuy^!Gv*d%o#WaIp z30;|^AsA+GKS$AHkk>Vm*JFOw8$C9H_jk}{+@r&>y{4yQGvIqyZHQ{rbx{gX> zgzbrkv3}-)Ztt?NJ*2h*xZ=wv8F$!7t*UDK@2B%PKLM?iJYor_!~vJsp4N@$(Jzkp;lp7X zD{eLrE0}H97QeM0$>X}0g6zsVSY(9MM8~tQovu0xx_*HmIH^kx^DpZ9y_TV!g-`wG z7A|t+gr1U1f>(9Rp*Q#`-6C}w44ZWa!qZzT`@DGhlselk-;);~!K+b#rrOzpU_?59 z769>_+LaM!kRwlQ`&0mFE&sY*CKqi@oTFcdo+*noubm`(msDA4RQ4)m1Yos`D1H5} zwi*L!ewkU!dh9x+6{Bb>(=Hq6C=QHe0Lpv23iR5mH4?Mtvl^#{i(>Q$(CGGEtNibM zW1gf2-#0(y-@4|K;d5OHZH)iyI|B2|%)uux$*4nIuuymX#uH2e<=civq@Tal{g4Ob zI(3kiQXk`^t#J`NeAE(6-SpgiUb{U}lcv2=gVR%bwwEhEx@gJ>YTzlHBb%Pivui+0 zY`Pz4OqAAX`?_yB+T$)qLPs zA-FKr_4T8;#05eJaNJb|a&n!*bq+N-Q>i!HeZ~a&f|O9fkq6z3#H^Hrt8cG}2kLhF zSZdN-_@p4;5H4F=mT+b`e7C`~PpI|K#X032yxQ_`pWf|RQ%Z_6P%uVKK8!i9(;%xIg9e5Dwr0j!(i!ITT-sAR@kMa+@%lw zt>dj?MIT(=BOAV$>ZwV6y=OTbdDy9A1*k4$1Q+b(;9+2Xpm0vh9l~)iFWyF9lhk)W zS0CQslnT|!OpX)N`zUu!Wa>sXMHsE}yNcD#u$LHp{g`KLQCTrg6M6h;>9<@rwm;Ad z7YjX!mv}s0FROLXW?=}D2S~lOGM-cOGO-&GAGn`@k;v!Uq(`9G=C5d>-7gjiY9g1d z^bFd#(9Yd=HQhBsdZxTVLIvY%R#))Xp6s{LCyaj>L3%53D@bp73m-pC-p@}a|+mAABD@lkwYKGRuI@KRZd1~>Ym0t-| z;tUUkZKdvIS6^V#oYW2VsW0RQ!2%&t?wz^0h%0 z@-j?stMy8?F`(`P$ttx~fB{*E?W! zsOz57`9dw$Rx{hn!Rd?!HJ3mu$)l$y%`_+56C0AS97#-eO!t>Z2raA*p3;Q+zJoCDr*ALWT3 zrVLCLKxOAU_^;LS%PVBZ0_?apgF5_ddr8p)eXX{G>(T-BGiiZPAXQrCOQFh;IHu2i zFy>i#-aTz~-2pA}_AD#i$~gx1dnv@Fiz{1JrH3y@C$`wK-nrDB6T?rGv<~awo{A`Z z^&~xwe0-_zXO=%VEsJIm?lUg+rQMcuk1Hc|fK9sdQ*ckgYMMFQ01V}Ko^9XJ`})Q3 ziJT5)`P5@0eHeG_%e(q97ZLTU%K;6ATu=l#iF&Czvs@$+S-mII(--qJ@O!`Aca)v{=Uu0KH`Fm zxcb+AGqrmtjgJ=i@qT&Ey@;?cNasrTjB=^5pF@dG3{gj<+anz)ti5SB(6aGSY^C>` z9K5!BURfk?$6p=#V9;alBYRf^yd2F`z1rj&rDt9zT5dy$wDMl4bT|qM zx$4?SImh*D*hFRzT;3xx053ne0s7K;faP?`d!wZsOe~Z>mly|@O|t8-_t-JFCX^8g z9BLiKIUV!{fq;NwJkqE|>!i5zuJfR6Ou%OdVgOZk2Pn{ zA3w!zdoZZmGyh8ndXJ)ca~VRz$TZr>k!iJyJ?A};_E_!3Hk{t@3NOa=XRvx>pu@y8 zlDb%C37LB@6Hhp@u{j`YQ`m;5fQo;7`Fm`W@mZ)$Ds@YnH$K-2Yzh-NS_%7htcyl?@_XOfeZYnZSs-fgdZ~b|{4AC6;?}a0Ox($E2HBpJI`UM4n zwhEOmRU?icSqMMYR%lr9k?N6}WVARov-tTC{VB0c(d4I1Wa){A2>WvwSVfRG(NVD+ zvcA=xqEb8cBSjHMssG`UGm>bm;xq!5snCLvhp6Ia&THRAs7*yx3mwNwA$8HPcmBWD z64pn&9>2S{{^>8P@t3Koeqy^r$kul)_F5QqJYj?^X-uwQjX7QuAZ7cuzY?jX~Oz%G+?h*t)pc1)j7S?6M-#&1M7#L+J9+GZyJ~ zp8-;Vj+kZnTQL67@61%YmL#PfuYa1#AX`15{wL{T{6#-6uzBVyL%N(*RDaNI#N9&( zKWlzJ>M+>(d0MWx_d9*+n8SpBf|j56;s-9-YpGJrvM39iTp6cHlOoFHdS;c)hN2VZ!?sjbW16R zVarnc;raVv*J!;Yadk>5@?O;hq=VGv+%S(HSj$Pi=GXaomDH2`d8ou>@eUhuyGLF4 zQ|F;SIhsFQ&hMj}$*MW*^0VnsBDyWW96K-#8GMeVE$LF_mxrqw1mtPvu-IiuSR;@b}g(a@aPh*PZR)Jde1OA;+mQ62YZdMGjil zA;Equ(N#R1Wa}|J(cikC9M@YR;U#h;{ka-x6>EQ$8aSC3DfZ3G+Wb{>S$U zdF<6Od~QxL|A#t;jJ@iD*qFF~sAIUrb~H>a%ecrS?G~lw&wl(b579oB^T({ZXQR$) zl>B`=J=JSK14)s1y7S++o(qZsbX(Y4f-dp@$JhVq?e{&QpKFw%e`v~g9?__B)LHX@39l->>cg z)73b7Y3OgKqAC;*+=plRUFCmYE5iN`nC|~`dD-Q^>!(5f{)TfO2c~=eR+Q~O=$JeO z?B;E@^2k5b30wlEd&ga<MfsKqW WQP0jAyYB=3H19vWhq_}G{J#KP@Bu3T literal 0 HcmV?d00001 diff --git a/src/API/LocalApi.php b/src/API/LocalApi.php index acadf76..0585618 100644 --- a/src/API/LocalApi.php +++ b/src/API/LocalApi.php @@ -188,7 +188,7 @@ public function __construct( } /** - * @return Promise\PromiseInterface + * @return Promise\PromiseInterface */ public function connect(): Promise\PromiseInterface { diff --git a/src/Clients/Discovery.php b/src/Clients/Discovery.php index e0ba432..98ed6a5 100644 --- a/src/Clients/Discovery.php +++ b/src/Clients/Discovery.php @@ -224,7 +224,7 @@ function () use ($deferred, $protocolVersion): void { $this->discoveredLocalDevices = new SplObjectStorage(); if ($devices !== []) { - $devices = $this->handleFoundLocalDevices($devices); + $this->handleFoundLocalDevices($devices); } $this->emit('finished', [$devices]); diff --git a/src/Queue/Consumers/ChannelProperty.php b/src/Queue/Consumers/ChannelProperty.php index a6c0b6c..e105285 100644 --- a/src/Queue/Consumers/ChannelProperty.php +++ b/src/Queue/Consumers/ChannelProperty.php @@ -95,26 +95,38 @@ function () use ($property): void { return; } - if ( - $property instanceof DevicesEntities\Channels\Properties\Variable - && $property->getValue() === $value - ) { - return; - } - if ($property !== null && !$property instanceof $type) { - $findChannelPropertyQuery = new DevicesQueries\Entities\FindChannelProperties(); - $findChannelPropertyQuery->byId($property->getId()); + $this->databaseHelper->transaction(function () use ($property): void { + $this->channelsPropertiesManager->delete($property); + }); - $property = $this->channelsPropertiesRepository->findOneBy($findChannelPropertyQuery); + $this->logger->warning( + 'Stored channel property was not of valid type', + [ + 'source' => MetadataTypes\ConnectorSource::SOURCE_CONNECTOR_TUYA, + 'type' => 'message-consumer', + 'channel' => [ + 'id' => $channelId->toString(), + ], + 'property' => [ + 'id' => $property->getId()->toString(), + 'identifier' => $identifier, + ], + ], + ); - if ($property !== null) { - $this->databaseHelper->transaction(function () use ($property): void { - $this->channelsPropertiesManager->delete($property); - }); + $property = null; + } - $this->logger->warning( - 'Stored channel property was not of valid type', + if ($property === null) { + $findChannelQuery = new DevicesQueries\Entities\FindChannels(); + $findChannelQuery->byId($channelId); + + $channel = $this->channelsRepository->findOneBy($findChannelQuery); + + if ($channel === null) { + $this->logger->error( + 'Channel was not found, property could not be configured', [ 'source' => MetadataTypes\ConnectorSource::SOURCE_CONNECTOR_TUYA, 'type' => 'message-consumer', @@ -122,23 +134,11 @@ function () use ($property): void { 'id' => $channelId->toString(), ], 'property' => [ - 'id' => $property->getId()->toString(), 'identifier' => $identifier, ], ], ); - } - - $property = null; - } - if ($property === null) { - $findChannelQuery = new DevicesQueries\Entities\FindChannels(); - $findChannelQuery->byId($channelId); - - $channel = $this->channelsRepository->findOneBy($findChannelQuery); - - if ($channel === null) { return; } @@ -186,6 +186,8 @@ function () use ($property): void { } else { if ($property instanceof DevicesEntities\Channels\Properties\Dynamic) { + // Some Tuya devices has invalid values configured + // Eg. wifi dimmable device has allowed values "incandescent" and "halogen" but it also provide "led" value $findPropertyQuery = new DevicesQueries\Configuration\FindChannelDynamicProperties(); $findPropertyQuery->byId($property->getId()); diff --git a/src/Queue/Consumers/DeviceProperty.php b/src/Queue/Consumers/DeviceProperty.php index e84b296..863d8c4 100644 --- a/src/Queue/Consumers/DeviceProperty.php +++ b/src/Queue/Consumers/DeviceProperty.php @@ -19,7 +19,6 @@ use FastyBird\Connector\Tuya; use FastyBird\Connector\Tuya\Entities; use FastyBird\Connector\Tuya\Queries; -use FastyBird\Library\Metadata\Exceptions as MetadataExceptions; use FastyBird\Library\Metadata\Types as MetadataTypes; use FastyBird\Module\Devices\Entities as DevicesEntities; use FastyBird\Module\Devices\Exceptions as DevicesExceptions; @@ -52,8 +51,6 @@ trait DeviceProperty * @throws DBAL\Exception * @throws DevicesExceptions\InvalidState * @throws DevicesExceptions\Runtime - * @throws MetadataExceptions\InvalidArgument - * @throws MetadataExceptions\InvalidState */ private function setDeviceProperty( Uuid\UuidInterface $deviceId, @@ -84,13 +81,6 @@ function () use ($property): void { return; } - if ( - $property instanceof DevicesEntities\Devices\Properties\Variable - && $property->getValue() === $value - ) { - return; - } - if ( $property !== null && !$property instanceof DevicesEntities\Devices\Properties\Variable @@ -134,6 +124,20 @@ function () use ($property): void { ); if ($device === null) { + $this->logger->error( + 'Device was not found, property could not be configured', + [ + 'source' => MetadataTypes\ConnectorSource::SOURCE_CONNECTOR_TUYA, + 'type' => 'message-consumer', + 'device' => [ + 'id' => $deviceId->toString(), + ], + 'property' => [ + 'identifier' => $identifier, + ], + ], + ); + return; } diff --git a/src/Queue/Consumers/StoreCloudDevice.php b/src/Queue/Consumers/StoreCloudDevice.php index 899088d..2740e14 100644 --- a/src/Queue/Consumers/StoreCloudDevice.php +++ b/src/Queue/Consumers/StoreCloudDevice.php @@ -22,7 +22,6 @@ use FastyBird\Connector\Tuya\Queue; use FastyBird\Connector\Tuya\Types; use FastyBird\Library\Metadata\Documents as MetadataDocuments; -use FastyBird\Library\Metadata\Exceptions as MetadataExceptions; use FastyBird\Library\Metadata\Types as MetadataTypes; use FastyBird\Module\Devices\Entities as DevicesEntities; use FastyBird\Module\Devices\Exceptions as DevicesExceptions; @@ -73,8 +72,6 @@ public function __construct( * @throws DBAL\Exception * @throws DevicesExceptions\InvalidState * @throws DevicesExceptions\Runtime - * @throws MetadataExceptions\InvalidArgument - * @throws MetadataExceptions\InvalidState */ public function consume(Entities\Messages\Entity $entity): bool { @@ -128,29 +125,6 @@ function () use ($entity, $connector): Entities\TuyaDevice { 'data' => $entity->toArray(), ], ); - } else { - $device = $this->databaseHelper->transaction( - function () use ($entity, $device): Entities\TuyaDevice { - $device = $this->devicesManager->update($device, Utils\ArrayHash::from([ - 'name' => $entity->getName(), - ])); - assert($device instanceof Entities\TuyaDevice); - - return $device; - }, - ); - - $this->logger->debug( - 'Device was updated', - [ - 'source' => MetadataTypes\ConnectorSource::SOURCE_CONNECTOR_TUYA, - 'type' => 'store-cloud-device-message-consumer', - 'device' => [ - 'id' => $device->getId()->toString(), - ], - 'data' => $entity->toArray(), - ], - ); } $this->setDeviceProperty( diff --git a/src/Queue/Consumers/StoreLocalDevice.php b/src/Queue/Consumers/StoreLocalDevice.php index df103b2..ecb9f32 100644 --- a/src/Queue/Consumers/StoreLocalDevice.php +++ b/src/Queue/Consumers/StoreLocalDevice.php @@ -21,7 +21,7 @@ use FastyBird\Connector\Tuya\Queries; use FastyBird\Connector\Tuya\Queue; use FastyBird\Connector\Tuya\Types; -use FastyBird\Library\Metadata\Exceptions as MetadataExceptions; +use FastyBird\Library\Metadata\Documents as MetadataDocuments; use FastyBird\Library\Metadata\Types as MetadataTypes; use FastyBird\Module\Devices\Entities as DevicesEntities; use FastyBird\Module\Devices\Exceptions as DevicesExceptions; @@ -30,6 +30,7 @@ use FastyBird\Module\Devices\Utilities as DevicesUtilities; use Nette; use Nette\Utils; +use function array_merge; use function assert; use function count; @@ -48,6 +49,9 @@ final class StoreLocalDevice implements Queue\Consumer use DeviceProperty; use ChannelProperty; + /** + * @param DevicesModels\Configuration\Channels\Properties\Repository $channelsPropertiesConfigurationRepository + */ public function __construct( protected readonly Tuya\Logger $logger, protected readonly DevicesModels\Entities\Devices\DevicesRepository $devicesRepository, @@ -56,6 +60,8 @@ public function __construct( protected readonly DevicesModels\Entities\Channels\ChannelsRepository $channelsRepository, protected readonly DevicesModels\Entities\Channels\Properties\PropertiesRepository $channelsPropertiesRepository, protected readonly DevicesModels\Entities\Channels\Properties\PropertiesManager $channelsPropertiesManager, + protected readonly DevicesModels\States\ChannelPropertiesManager $channelPropertiesStateManager, + protected readonly DevicesModels\Configuration\Channels\Properties\Repository $channelsPropertiesConfigurationRepository, protected readonly DevicesUtilities\Database $databaseHelper, private readonly DevicesModels\Entities\Connectors\ConnectorsRepository $connectorsRepository, private readonly DevicesModels\Entities\Devices\DevicesManager $devicesManager, @@ -68,8 +74,6 @@ public function __construct( * @throws DBAL\Exception * @throws DevicesExceptions\InvalidState * @throws DevicesExceptions\Runtime - * @throws MetadataExceptions\InvalidArgument - * @throws MetadataExceptions\InvalidState */ public function consume(Entities\Messages\Entity $entity): bool { @@ -98,12 +102,40 @@ public function consume(Entities\Messages\Entity $entity): bool $device = $this->databaseHelper->transaction( function () use ($entity, $connector): Entities\TuyaDevice { - $device = $this->devicesManager->create(Utils\ArrayHash::from([ - 'entity' => Entities\TuyaDevice::class, - 'connector' => $connector, - 'identifier' => $entity->getId(), - 'name' => $entity->getName(), - ])); + $parents = []; + + if ($entity->getGateway() !== null) { + $findParentDeviceQuery = new Queries\Entities\FindDevices(); + $findParentDeviceQuery->byConnectorId($entity->getConnector()); + $findParentDeviceQuery->byIdentifier($entity->getGateway()); + + $parent = $this->devicesRepository->findOneBy( + $findParentDeviceQuery, + Entities\TuyaDevice::class, + ); + + if ($parent === null) { + throw new Tuya\Exceptions\InvalidState( + 'Parent device could not be loaded for child device', + ); + } + + $parents = [$parent]; + } + + $device = $this->devicesManager->create( + Utils\ArrayHash::from(array_merge( + [ + 'entity' => Entities\TuyaDevice::class, + 'connector' => $connector, + 'identifier' => $entity->getId(), + 'name' => $entity->getName(), + ], + $entity->getGateway() !== null + ? ['parents' => $parents] + : [], + )), + ); assert($device instanceof Entities\TuyaDevice); return $device; @@ -123,55 +155,6 @@ function () use ($entity, $connector): Entities\TuyaDevice { 'data' => $entity->toArray(), ], ); - } else { - $device = $this->databaseHelper->transaction( - function () use ($entity, $device): Entities\TuyaDevice { - $device = $this->devicesManager->update($device, Utils\ArrayHash::from([ - 'name' => $entity->getName(), - ])); - assert($device instanceof Entities\TuyaDevice); - - return $device; - }, - ); - - $this->logger->debug( - 'Device was updated', - [ - 'source' => MetadataTypes\ConnectorSource::SOURCE_CONNECTOR_TUYA, - 'type' => 'store-local-device-message-consumer', - 'device' => [ - 'id' => $device->getId()->toString(), - ], - 'data' => $entity->toArray(), - ], - ); - } - - if ($entity->getGateway() !== null) { - $findParentDeviceQuery = new Queries\Entities\FindDevices(); - $findParentDeviceQuery->byConnectorId($entity->getConnector()); - $findParentDeviceQuery->byIdentifier($entity->getGateway()); - - $parent = $this->devicesRepository->findOneBy($findParentDeviceQuery, Entities\TuyaDevice::class); - - if ($parent === null) { - $this->databaseHelper->transaction( - function () use ($device): void { - $this->devicesManager->delete($device); - }, - ); - - return true; - } - - $this->databaseHelper->transaction( - function () use ($device, $parent): void { - $this->devicesManager->update($device, Utils\ArrayHash::from([ - 'parents' => [$parent], - ])); - }, - ); } $this->setDeviceProperty( @@ -265,7 +248,6 @@ function () use ($device, $parent): void { Types\DevicePropertyIdentifier::ENCRYPTED, DevicesUtilities\Name::createName(Types\DevicePropertyIdentifier::ENCRYPTED), ); - $this->setDeviceProperty( $device->getId(), $entity->getModel(),