From 28d75db1e14c2abf738c44742e3d584f07c01911 Mon Sep 17 00:00:00 2001 From: Johan Zandstra Date: Thu, 5 Sep 2024 12:12:30 +0200 Subject: [PATCH] Initial commit v1.0.9 clone --- .github/FUNDING.yml | 1 + .github/workflows/phpstan.yml | 25 + .github/workflows/tests.yml | 28 + .gitignore | 3 + LICENSE | 21 + README.md | 377 ++++++++ art/banner.png | Bin 0 -> 203812 bytes art/preview.png | Bin 0 -> 65263 bytes composer.json | 61 ++ phpstan.neon.dist | 4 + phpunit.xml | 22 + pint.json | 3 + src/Concerns/OnlyIntegers.php | 24 + src/EasyMetricsServiceProvider.php | 13 + src/Enums/GrowthRateType.php | 21 + src/Enums/Range.php | 73 ++ src/Metrics/Bar.php | 8 + src/Metrics/Doughnut.php | 149 +++ src/Metrics/Line.php | 8 + src/Metrics/Metric.php | 168 ++++ src/Metrics/Pie.php | 8 + src/Metrics/Polar.php | 8 + src/Metrics/Trend.php | 318 ++++++ src/Metrics/Value.php | 88 ++ src/Result.php | 77 ++ src/ValueResult.php | 65 ++ tests/Pest.php | 3 + tests/database/factories/UserFactory.php | 28 + .../migrations/create_users_table.php | 28 + tests/src/Doughnut/DoughnutTest.php | 367 +++++++ tests/src/Enums/Gender.php | 9 + tests/src/Enums/GrowthRateTest.php | 36 + tests/src/Enums/RangeTest.php | 201 ++++ tests/src/Models/User.php | 30 + tests/src/TestCase.php | 16 + tests/src/Trend/TrendTest.php | 904 ++++++++++++++++++ tests/src/Value/CustomDateColumnTest.php | 35 + tests/src/Value/ValueTest.php | 345 +++++++ 38 files changed, 3575 insertions(+) create mode 100644 .github/FUNDING.yml create mode 100644 .github/workflows/phpstan.yml create mode 100644 .github/workflows/tests.yml create mode 100644 .gitignore create mode 100644 LICENSE create mode 100644 README.md create mode 100644 art/banner.png create mode 100644 art/preview.png create mode 100644 composer.json create mode 100644 phpstan.neon.dist create mode 100644 phpunit.xml create mode 100644 pint.json create mode 100644 src/Concerns/OnlyIntegers.php create mode 100644 src/EasyMetricsServiceProvider.php create mode 100644 src/Enums/GrowthRateType.php create mode 100644 src/Enums/Range.php create mode 100644 src/Metrics/Bar.php create mode 100644 src/Metrics/Doughnut.php create mode 100644 src/Metrics/Line.php create mode 100644 src/Metrics/Metric.php create mode 100644 src/Metrics/Pie.php create mode 100644 src/Metrics/Polar.php create mode 100644 src/Metrics/Trend.php create mode 100644 src/Metrics/Value.php create mode 100644 src/Result.php create mode 100644 src/ValueResult.php create mode 100644 tests/Pest.php create mode 100644 tests/database/factories/UserFactory.php create mode 100644 tests/database/migrations/create_users_table.php create mode 100644 tests/src/Doughnut/DoughnutTest.php create mode 100644 tests/src/Enums/Gender.php create mode 100644 tests/src/Enums/GrowthRateTest.php create mode 100644 tests/src/Enums/RangeTest.php create mode 100644 tests/src/Models/User.php create mode 100644 tests/src/TestCase.php create mode 100644 tests/src/Trend/TrendTest.php create mode 100644 tests/src/Value/CustomDateColumnTest.php create mode 100644 tests/src/Value/ValueTest.php diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 0000000..d90b29a --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1 @@ +github: sakanjo diff --git a/.github/workflows/phpstan.yml b/.github/workflows/phpstan.yml new file mode 100644 index 0000000..714085e --- /dev/null +++ b/.github/workflows/phpstan.yml @@ -0,0 +1,25 @@ +name: PHPStan + +on: + push: + pull_request: + +jobs: + phpstan: + name: phpstan + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: '8.1' + coverage: none + + - name: Install composer dependencies + uses: ramsey/composer-install@v2 + + - name: Run PHPStan + run: ./vendor/bin/phpstan --error-format=github + diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml new file mode 100644 index 0000000..1e951d4 --- /dev/null +++ b/.github/workflows/tests.yml @@ -0,0 +1,28 @@ +name: Tests + +on: + push: + pull_request: + +jobs: + ci: + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: '8.1' + tools: composer:v2 + extensions: mbstring, pdo, pdo_sqlite + coverage: xdebug + + - name: Install Dependencies + run: composer install --no-interaction --prefer-dist --optimize-autoloader + + - name: Run pest + run: ./vendor/bin/pest + diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8cab567 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +/vendor +/composer.lock +.idea diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..d5124b7 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2023 Salah Kanjo + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..3176e39 --- /dev/null +++ b/README.md @@ -0,0 +1,377 @@ +![Easy metrics banner](./art/banner.png) + +

+ Workflow status + Laravel v10.x + PHP 8.0 +

+ +

đŸ”Ĩ Easy metrics

+ +

Easily create metrics for your application.

+ +> ✨ Help support the maintenance of this package by [sponsoring me](https://github.com/sponsors/sakanjo). + +> Designed to work with **Laravel**, **Filament**, and more. + +![Preview](./art/preview.png) + +## 🚀 Supported metrics + +- **Bar** metric +- **Doughnut** metric +- **Line** metric +- **Pie** metric +- **Polar** metric +- **Trend** metric +- **Value** metric + +Table of contents +================= + +* [Install](#-install) +* [Usage](#-usage) + * [Value metric](#value-metric) + * [Doughnut metric](#doughnut-metric) + * [Trend metric](#trend-metric) + * [Other metrics](#other-metrics) +* [Ranges](#ranges) + * [Available custom ranges](#available-custom-ranges) +* [Growth rates](#growth-rates) + * [Using value metric](#using-value-metric) + * [Using trend metric](#using-trend-metric) + * [Using doughnut metric](#using-doughnut-metric) + * [Available growth rate types](#available-growth-rate-types) +* [Practical examples](#-practical-examples) + * [Filamentphp v3 widgets](#filamentphp-v3-widgets) +* [Support the development](#-support-the-development) +* [Credits](#%EF%B8%8F-credits) +* [License](#-license) + +## đŸ“Ļ Install + +``` +composer require sakanjo/laravel-easy-metrics +``` + +## đŸĻ„ Usage + +### Value metric + +```php +use SaKanjo\EasyMetrics\Metrics\Value; +use App\Models\User; + +$data = Value::make(User::class) + ->count(); +``` + +#### Query types + +The currently supported aggregate functions to calculate a given column compared to the previous time interval / range + +##### Min + +```php +Value::make(User::class) + ->min('age'); +``` + +##### Max + +```php +Value::make(User::class) + ->max('age'); +``` + +##### Sum + +```php +Value::make(User::class) + ->sum('age'); +``` + +##### Average + +```php +Value::make(User::class) + ->average('age'); +``` + +##### Count + +```php +Value::make(User::class) + ->count(); +``` + +### Doughnut metric + +```php +use SaKanjo\EasyMetrics\Metrics\Doughnut; +use App\Models\User; +use App\Enums\Gender; + +[$labels, $data] = Doughnut::make(User::class) + ->options(Gender::class) + ->count('gender'); +``` + +> It's always better to use the `options` method even though it's optional, since the retrieved data may not include all enum options. + +#### Query types + +The currently supported aggregate functions to calculate a given column compared to the previous time interval / range + +##### Min + +```php +Doughnut::make(User::class) + ->min('age', 'gender'); +``` + +##### Max + +```php +Doughnut::make(User::class) + ->max('age', 'gender'); +``` + +##### Sum + +```php +Doughnut::make(User::class) + ->sum('age', 'gender'); +``` + +##### Average + +```php +Doughnut::make(User::class) + ->average('age', 'gender'); +``` + +##### Count + +```php +Doughnut::make(User::class) + ->count('gender'); +``` + +### Trend metric + +```php +use SaKanjo\EasyMetrics\Metrics\Trend; +use App\Models\User; + +[$labels, $data] = Trend::make(User::class) + ->countByMonths(); +``` + + +#### Query types + +The currently supported aggregate functions to calculate a given column compared to the previous time interval / range + +##### Min + +```php +$trend->minByYears('age'); +$trend->minByMonths('age'); +$trend->minByWeeks('age'); +$trend->minByDays('age'); +$trend->minByHours('age'); +$trend->minByMinutes('age'); +``` + +##### Max + +```php +$trend->maxByYears('age'); +$trend->maxByMonths('age'); +$trend->maxByWeeks('age'); +$trend->maxByDays('age'); +$trend->maxByHours('age'); +$trend->maxByMinutes('age'); +``` + +##### Sum + +```php +$trend->sumByYears('age'); +$trend->sumByMonths('age'); +$trend->sumByWeeks('age'); +$trend->sumByDays('age'); +$trend->sumByHours('age'); +$trend->sumByMinutes('age'); +``` + +##### Average + +```php +$trend->averageByYears('age'); +$trend->averageByMonths('age'); +$trend->averageByWeeks('age'); +$trend->averageByDays('age'); +$trend->averageByHours('age'); +$trend->averageByMinutes('age'); +``` + +##### Count + +```php +$trend->countByYears(); +$trend->countByMonths(); +$trend->countByWeeks(); +$trend->countByDays(); +$trend->countByHours(); +$trend->countByMinutes(); +``` + +### Other metrics + +- `Bar extends Trend` +- `Line extends Trend` +- `Doughnut extends Pie` +- `Polar extends Pie` + + +## Ranges + +Every metric class contains a ranges method, that will determine the range of the results based on it's date column. + +```php +use SaKanjo\EasyMetrics\Metrics\Trend; +use SaKanjo\EasyMetrics\Metrics\Enums\Range; +use App\Models\User; + +Value::make(User::class) + ->range(30) + ->ranges([ + 15, 30, 365, + Range::TODAY, // Or 'TODAY' + ]); +``` + +### Available custom ranges + +- `Range::TODAY` +- `Range::YESTERDAY` +- `Range::MTD` +- `Range::QTD` +- `Range::YTD` +- `Range::ALL` + +## Growth rates + +Growth rate, expressed as both a **value** and a **percentage**, measures the change in a quantity over **time**, showing the speed of its expansion or contraction in both absolute and relative terms. + +### Using **Value** metric + +```php +use SaKanjo\EasyMetrics\Metrics\Value; +use SaKanjo\EasyMetrics\Enums\GrowthRateType; +use App\Models\User; + +[$value, $growth] = Value::make(User::class) + ->withGrowthRate() + ->growthRateType(GrowthRateType::Value) // default is `Percentage` + ->count(); +``` + +### Using **Trend** metric + +```php +use SaKanjo\EasyMetrics\Metrics\Trend; +use App\Models\User; + +[$labels, $data, $growth] = Trend::make(User::class) + ->withGrowthRate() + ->countByYears(); +``` + +### Using **Doughnut** metric + +```php +use SaKanjo\EasyMetrics\Metrics\Doughnut; +use App\Models\User; +use App\Enums\Gender; + +[$labels, $data, $growth] = Doughnut::make(User::class) + ->options(Gender::class) + ->withGrowthRate() + ->count('gender'); +``` + + +### Available growth rate types + +- `GrowthRateType::Value` +- `GrowthRateType::Percentage` + +## đŸ”Ĩ Practical examples + +#### Filamentphp v3 widgets + +```php +range($this->filter) + ->rangesFromOptions($this->getFilters()) + ->countByMonths(); + + return [ + 'datasets' => [ + [ + 'label' => 'Users', + 'data' => $data, + ], + ], + 'labels' => $labels, + ]; + } + + protected function getType(): string + { + return 'line'; + } + + protected function getFilters(): ?array + { + return [ + 15 => '15 Months', + 30 => '30 Months', + 60 => '60 Months', + ]; + } +} + +``` + +## 💖 Support the development + +**Do you like this project? Support it by donating** + +Click the ["💖 Sponsor"](https://github.com/sponsors/sakanjo) at the top of this repo. + +## Šī¸ Credits + +- [Salah Kanjo](https://github.com/sakanjo) +- [All Contributors](../../contributors) + +## 📄 License + +[MIT License](https://github.com/sakanjo/laravel-easy-metrics/blob/master/LICENSE) Š 2023-PRESENT [Salah Kanjo](https://github.com/sakanjo) diff --git a/art/banner.png b/art/banner.png new file mode 100644 index 0000000000000000000000000000000000000000..4b7e40bb689612ea30f8b753041d0e70645c2b3e GIT binary patch literal 203812 zcmaf*c|4SD`~U6hjY_ynLPbTI7P6&5i^^JI2n}r%HA+Qs8EaFzrCnLFlqK8HCSk@> z6j`#DW$a^&Wn>0(88g508t(1+KF{m-$Ng&R?$un&c^=2-cz-^p+jces%--Mk5?(bI=4Ewa}^|mmlM{g|^FDqVhJXCUPx!Rpi2LwQg&>)R93I2 zm*nr?r~2#tZPll9ayd8$?q;Y!v>EeFPC@Yeubo^g%7Nfa3A=|$Q|&I4FS)Nt%h4mF zwZGc!TLzU@JR?2k=qc#2BlnfE61)AI{D%p9U`_U8ZDx~x<0>occD!|D1^a`cX>;Lo za(YE6Eqi2Sf~B!QhJDBa7w3d_n=Ft8Y{>>3Dt=NaMQHCKkJ%r#Xw*RyPK)0=+sZSc zTAL3FJAJH@PqrjHRNX4xnsSM7?9;GHJyQ>Ine!H6-m;>Y2M&k87zhx9muOzY8{K5y@*F~bg?O@epL42(wYfI8KFN9i_#Tb8pQae3u;De^b7t47b2h&MB^5&AuB+)Xlb zmZX-au~~Pk{X&=DwxpX!^T#LE4!$vsZ4g(qSzFU1*wXn}NF&dLa0aD0pJ3R+Kd(CDUBLscFoI>V0<$GvEG1q8`M%C$ zh{J9+CLO=M-QNWPD@Jhmxd=(@UWfRgGJy*c&!NwO;6nARVUspkKX@S4 zv8hqh3l8NoLI)x-?Exz<{s5(lSnD3aQW)H~`WlS9^bz~(=A+j@> zcvIF8a+p)k#Z9W*Pbbm>W8r>IA)~T@^?2@_WPTwjG)Wd-r{AskA&z-rth!afB+P*o ziI=VP=Q0^o{FH<14YkeO9}U5ZTgjaEUi5`X$@5dkT#r1&9&GUzitd`3=mmF`GC4+S z7BHUPs|r2j)F^-z5udMD@I!xJV3Yn{cX$V9O(M-3e$TMfVz$Ii;ox21#-EZ{;QbCu zSc9#(xKOm1It)A!mSxsg#j0!CG?Hy-gDX<&wxoo#F-y^q^y=fT zZbv9t%#|bADbrh(UIvcd(Xtuuvd8+AGZm)y?hgSw3=RGfRV|?{%wrLcS&yS#;)83wYtM$wCt~_&F*lP*-PABVQWeWxtSiX z{oygmfaeZJflAkvL?TvH`tQ**X&Cjm&g-M*-EqLEuK#LvQzuHiv$r9-dK3MY)U7{; zs#_({hC*3)E1x7YE^JjlrVJ@_tk3M&C7xx|BDU^k2-b{}P@e<--Dl(zux7<6`E{-O z8Gf=wewFRu*H@&6<7p@dovexJhoLF&R|K~(KesUxb({&A!$%7?2(SNnV;`hGAP$f6 z*OF*!JTtN$K0rN^Y9nh;D$s+-KSsx{^u~q-aZpYt&8e($0yjhKArD3SY$XuhqaHm$Ht95)r&L~Z zl^^wLNN!|*FDQ?ELR@y7u;p07uob(KAR6|@lzUnG-e8E^2)KvkS4x>z_kGS3dP*{3 zUKL4XVVh^KMdSp2Kb=QXf-Z3vVm;fGvRE?gqEU-xCEAv%>oD$1g9AE?By8`N|728| z_HAl?Ev+`VzJKm}!N{q&y+%6~4zr@8Hq%{x#=L=TCT3ou>e0g){b2Q4-&G21QQBeT z$LWw_C2}5**4EtQXoTC0Xzz(hw!vB~I|3iRS_PjSz_j_ljvuYHFR_3q!IU9_0I$Z^ zWadZG!tS|-JgvKGN^2}O8VJVCDGS@%h#wU5we|`stN(?R{INXLC*eYx_8!-}xy;CK z5w8}PV>uJ_XrwNCLniB*3-5tXDA?w@IB49c&Aw-$`xLj4&PLPb*h_eGNH|UwR*ZB` zAx71&zg;E7k|E0Cr>JP%MWGN$z;DQNY!#HYb1h{=*eRVImwePusTIj8$M#SD0f)JV zw1VB>wZ{F9_EXXgu>DOy1=K-l5=^m=r*B=eh-n6`E=2Ai()U_fqN%F0y@YQ8mzF`< zO~;aPN{N#AEKYJZs36CX+V}Pq$z*=2baY;%&_a{=a&l}>22L*VG1K~&HfE$1FPzx7 z4<45FNyGI8b*@_Ze*P$tq1#z4d@|dnQV(<%-`REGyoEY3gfhQ*x1kN^k1XYv0Z?;r_YVm&Dk~ z?h$Fw#}ZlAUvttX8=WcY%LTGgQXA4x$8;K>$!=Lb`<)fpXp4gg$Dxe#%5>u^ZThQ8 zQeewya_TsC>8LAhO20$m?){!j(I6*htX*R)^Wo+ACjT1rCs-5p$75z)6)_q0YNz=f zk{L(-``)>ag`_uuHk1?_Y}f7!keM09lq%A~9D=tS?XI?^8Gos!D?$&A<~fqu-(y>f zVo8!=iqIR5@(8_$eVZz(J@?R0gL>v`baa~7SdjFo3|Z&0)_dsJLe7_N>($ErV4M`% zx3YV>PNH6jed&wXl#Gm@aIdMmp&EBuVSh>)CXa!*vwAf*X@b+*|#Ybv2Q7)s=Msat@B#c`D=S zrbKJXIPVu?uokJkA1%UqAHIC1YS(4h7dWE*D)}qcybKh3zX@eEh2Vp97vm65wxQ8}Xn$WE zDIF(`ruHyfhfo_j_F)GLZ>z$i@l0VOSaCYmo+)vIrkr3QnH}mz@9c=l*3QcWg-d3` z0Oq3IL(*d-CCry)YaA#M#nW`{sqAtT(;IY9eX#%^h|DN)XYHf}ajV76ez$Ga4>24I z4mra)hwa@r;g%$Ka3|Wr6KE(M(8OHi^4(#_>HpPuz2O}bGdaXE-e%^0Bky&^cHM_4 zA@9RU`#mrtosXU*kW{Yhf>MryhL)2%Ik+`r`VS0B+VR591D7gRinjk=roV7gf5po% z)oS{cja~}S&R}coO`yeRU*ci}ubzV52p5KtzC?c{ZNVQZuLumD?8&sZ)>ZzSmWBTW7>acg`FytEYBFILu6|_Q1mYJ>?*lk?nEQ^Q?rT8M0TG5 zta!J*PB0Fr4?Tqm@I@B>MAQKO7^JW!j&z-u(Ome!bUpcH7|o?YE**Cl$c4dJ`)$y% z-~F8)8;FRS>9RFMT%=RK%F*#^HK6UgtUMb@iZdd<-@gK^dzDV6n*&w`?J}CZ-Arj3 zvtm=)dK$i2^t>p+8kXY3lh)~{qxLphf+iW)F(hg~5Rkj7Hw(65VTw#AxW2W$q%&K!EWBE1kkrCfGm7s?z ztHV!-H%JC6Q5c7B=>oxYgLbD2bi#I}UecZrg%w~L%6KCNRV2~^eW6wUKumU4p*H8g zTM`i(qE=YFTg(eyPieIuC=W>rGP=;JS^8*T;7y0Th>v9tq*jHU4PC{HmndP0fcnoL z2P$Fs?75Z93x}oCQ19)kZCh)%p1#_opR5P9v&A-nuS2gKak=-Ue>4hqq}@|XWx82< zIt2SXUeRGmImxX7qsU=yTvQxKW1q^uN4KY>-_TD<>8Piq{8SQ4maXEr1wSC!xPKYD z@3LJOuDcJsN92N^0#Sbcm!(v~^$K06As6*45SA+e<@Ol0RWZ}!yFR=8IM@g2$UcZ8 zbu$%asfUB31^nRiBlnsyk*ZDb`5=#yG*YUsHMY4hGRcpOf-13+FISmbt3^kRR@iMc zHCK}v6lwDPH0-Gj`H7fwvzTKCDLuxzn)ua{_T$xY9P`u@!ajqJ&XilKR@i2xEM;(S zHT^q;a(0f;jf*pw4p+S33WyeOod1}#N~k%uk2+$7b%Qph($Z+17;F`pwWy#mQRUDK z*b$hF!;G+yI8o<7)6Wx|!GaZ>nF?)ZzSGHG%~>IYOk`ScfhJzk%p7Z-*uaq?eFy`; zE3bmj&;2-xoucYkbIrr7NqzglFx>?I)Suhfq9n556s{`8tOGk?Rj_+M#fDOAbI&ZU z@dRumQp%L6e}N1Uqws5vhA1e7>P>^TbDg(I;qyaD*G5%7Zr!m=uEW|i!X+rV?aHV0 zf+?%5d3njWW5;V)i9K0LL&%LJ=X9zlkV~>_G9roTQ8Odv6 z!Kcb$cv$LU8m>WZ-)t7{3>as>B+@!vuw%~~G0hE%up*)wG(;pJhiP&s>HUjU*HVZ# zlM+aW5?$ty%AZXY4ohb5KFPtsqWgY&oFufi37rEtVobU0Pafe3O8GyAfz?7Sy`CIa zoBrkO9NZ_lkKmE&C`1}5shgdK9e)+tue{st;N(pCp_4{Ttpp02?X8uQf(t{mK9Rqp z{H`Dyvx2|9Qcn^bR(d!`4$nQ4PmWjHgI3(PobYs;9#X>m4Xl@jQy^7rI_{93Mb%~W z$+B9RduheRIL1ze!bRfnjAHM#MBqX?XgpM z22R2XV1skyzMWw65&ui&?KqBo`9|}#w6l1tzU2#K&0L1BHC~s7el$3PN3T$yi8P}( zD_QtFiDXb#Z1|)~Bdi zW|NCkFaJjY?!Vr_R8ZYo?Fd(-zCrY=Y;!x)A%Ye^>kTV{Ix)7NvU$=SzH87Yt6fEg z_O^g3oR5Ms@L6Td$b}$NA<^KmdS-VF=@?g`fG)a8hPwjq*`j2RR-59FoP~{rn{|vE z{iksZW!8l@XE3e#gORqco>{kCg1w|Q6DI=7hb=aTW-T}Yt$D@%uhnf!>%=AGb$PTJ zgy>srMZ3zD3*<>2AvFJc&I2WREnpE}Kyg-r0)y0kz97lS>;%O)u&FRLG#xd-9Rtfc zjx^56mxr{q6OLf5(Jmt{T`_uWONkY5)-YZedWc;)eHT>Cwv<(~5xsG;g(Hoh6?Q0q zrk?bo^C3wjlvc~AOr+P&>Hn+sq~k#Etf*(Uwmd6wuP`cP2+NbVHMD{k6#?%``^?li z?{$e~GTM2Bnn1GX*xv3`dWe$6p)##Uy23zT>Gb%#=pzZ6L^U< z4_yV@I~`|2zAOrQ1tAZXok-%o%^r|(|~K+~t#dZY}lK+&O`^dh9{aTlW%ru-oc_)!H!A!q-sH9k!*` z4bW;ds2(47LIB+We$f;0n3>ppb&=Obv6UBCh(ghvu%VcTIj{f$y!Dvn_T0nal_yWo z_265YNY>Yw3#SOD0L8o^V$r_TEJlUGNy0uho}j7*3+F(4Ps8u0+CiVA1MLp>{)Ik7 z{?XaxV1veyq7flYzcWpgXjZbKCR@c7^|xr|J68AO0_=iHKRxy~D4dB9q{_LpDu3W?rQ zAH{?fy$6jiW@RfmX8vYt6~Sz!H+GDdGtYolasHR|?YnunLGddr{-m0QE0kPS{EsCQ zd2BR$q>&jp-=y#Ft_|%3i=?vQ`!i&GA-^=Yg;oIs9WwN!>^x!3`%zzhLpkzB%69H# z@S#v4JfYS9GU$WZ6PcsQxFb&$;PayiPRVTpglN`d`^G_(xHXP;fj$o*6Qz-PKqt9uP#U!PI5@jOZ5!i}xO$L-MC4=+_kZ0hNhYTbi!7oz( z7Wf}f5K8G$Wjd^=+rd23HD18$i3hqi>dV&C6SkC(DvtZd-GyqPy)Q#sF;DzdT+UT| zYua>W=BB<4%)-3zKCpUrb&kd=akE734fr~PJ!Y_>vW)$H3$OMuvt3u{+}-y zAC7}-I9JIbVTjS7Au7e0ZNdb6SOe-swggh85QuJ*H+g}e;Brbva0PebvZyoQBq@cY z;Qh^*Sa2hB!IeMf{8;ZB^^?bwaZe7IVe2m4XhyAh-&9ye1PZ*<4jV1!`ngqsm3!DW z6!h@P%Vr-lNDrb`bIi%7d;VsS*jsQ4^ z)3k>%dAef;gamwM{uI3bZ^)E>G8O9qqE!7E&*xnL;0VeD@uz z1U7$0jqia+1^i`0uYX z@Vh?d2rvUi%HRXRrWncw&?#Pw8W*EuNrf&#t)ll;w_056?K!;68f@KM;{=YcA(%ce zz+`wz0?b>;g-&1oj1&nz1%5BA7ViN~yKx%;apaAV_UeEGklxiEbBgsf`^}>+D~DxS z4nu^*k@)OC8A#<;QpiC=pKs(3s)1`~iz=lyS}lKM8YgppwUf4ONWWA%aV_~}S(|VU zc(*tu`Aki;+VN)polqcp`le3fsjw%@ynaawPp||xFY4g325|+Mu{7LH@;$F(P~hF> z8kNCJSj;G#M0zuyKr*?~^MVvETfKMIu$*YC?IBLa=F2jY>&AZ{^1Pr{sId2Ptu!r=*XZNRc+YG~4haqMvfI zQ1xUXK$)h(^GKh89K$r~|Gsg;fl?Lh>ULjkBn|K;YrBDWXMvo`Z7KQy41;Ra=Eh?b zb1*Rehmh*R_pfr)5NvrXAT1KLQQ(?wqJWF^OEA#qUlkW=E{t1rMgCsNh|y!0f(yli z)#Gmty=k4v#91WzFUSPTK^h_mZ|zbFUTyG()H?8vzZ|e5=YPoq%k~0uyc@6IIGb#o zb2HjF;dRpMkhrK=(c!<r*WhCG6#T;{<2;I=~A1K?&;iWrv)E zpRCzhy>@=l`anDvvZiUw7ceqm@){lZdLHpW*4SXjdYE+{*Ka;PT5>(bSZYGrJxm)g z{+zw-)9vzY>+mD#odP{z zizEHd&k6Et%@$q{I-}+2?jh{*Vvax?cs*gpZT?#K`E{ei4I45t{e*>`>bq=!Ftoqm zMhjh;ceqzeD0ChA8Z`^8_H|DF$~0MdK>>r>tqwF^(u+!?4sMq1! zj0mzBlS}ZXXK!~`!VsAmONG+qu%|T;V6j7(EO%In?XeLa)*4knNxyvoDvJ$V&uO$k zYA2$l#ep0YZB}w@L3)SuY#MH&%n{yttwdv6WoClvao;Vs*6rippgT%M){25?qMdS? z2(8;6Y|9HRL?DvmNcJngS(KVu8$e5zhbSi#_2#@KZ1RXz;$vW~jA~02nqg&B9OuI% z+uAY6NG2_bqyv@~n6~7fr1%7UfO9XUxMWJifg8alkLRCXadWiS#ottPgM3F<`0soy z2GA1di`H1TVD<07n>QLw!#%(j0f*X8^^2|tMIcKtc6ov`r7JX-S;t@A7XH_uRpiCR zyBgN~hdKL~i=W@|2^pEb4~nnE_eo;E5nWT*oYOx84?y~CF*F7-pw&Qnp}t7;yaFH$ z-mKO}k9WA6YQUov>~h4)BwAyE+7g_*bo`%033J{K5&7DPhF?Sqz>-|CZc!4)Pp_92 z*|%iZ?)z|uB@3FCpb4b?++)9_fJ(&kt|6n#8wG`a$_ky%R)D>Ki(w^oo_hgoR|F<$ z*EBpw227!5rTW}|P$U^I#f~~GfB{Si z2b_6getNVXNzOC_O_dXYzF-z-jL4)0K&uHi1@z`3 zxw{gePf5;UbE_QVuK;A^1(z9@YEubKA@;xr{oDPd)8o@N=j0(Pv0^P#G^yLLgCd?^C40g(#a93qmVC;)e}bvA!N~#pS@7yL{=-~m z^%PN2z`n3rDr!m9b)bAsfPjkZ#&$$3qXvS7Ax!D|6r?=dR1j^*|5+)S&k_KR z{i}QGb~e?pa1K8_u{V+=8f;Bj=bterkdS*#0CM0oPK+Q0xtJTWp$U+QbYdL8iITUu zccvTxOBk^#PaEsLeoJTvNhT&hNty=mzxZQ+?Y)3<9r1lGJ8YR@RSHG=5?XgrANK@EPOE1i}DHYZF8_1jh zyBWu-_Lj_5*54LWdzZ6h0dV)RADES*U5Bs%gRWGBKoHm zClE+CX4BJfte_l#zTe;il-VikOu^qw0y(O`aMCsO1;Jgvq>+kwIr|lH13GyZtiMpi6$fC`86`Vaf|QOu9wV@pH;7AjsNHaTE8$7$e;xLHs~`#dce9$$KjxY zKxDi$N1|HVn8nv?jkN>p_1Fm6@S7Bn{q;I_*$jl*tS?)j8GqnWGrEi@%k0dxuXycB zij+hR6QTs97gnmb-!~pnE^=to?-zH2oR`|s65eoeF4@v}7p|X>%R(Ab7y=Uoms-&O zPhr6{?G8}(?}{Gzq%LL;G<*4Km5Y0!K%$zrqZfi*tP{tTg&ILE2ee_eyzWENu;fRe zi`6oSQL-%tGAi}!M_%yJx+33twZf{S?MFI0lCp(ej!?P+Qf|AQFlDtUVP4+Soiilc zqn`tiRNRUIoMH!GN%$A^q#*kQ3k_f;y9R|HtlPKIbg%H8Y$X_DjFks)Kh-?=%I+ID zZNM5b76eKjkW%@Q{x2(bN#8FPDGzUu=Ro3UMXbcG@k10LfLQJq9~+6!O;5&|9j{69 zIAg4voS~LO?xFNjnGSs*{Z{-VMV&!$@RSLzLcN-Pgck*Tw4abT8owTKUg)`~%l-yH zFUAWaKyKYzIrnHzG?<2vY3?5j`Tq*7-Ooq^J9A8r_<|ru`NMJh6(t`(=7%-0pDKN{ zAXH5>^rR>QYo)L=B)U5uOc*P|a#;>nPQw+!EC=8JVp4%6wg_K%CUj$kulyv)TP_j> z%zsYe$YzhKI6UYP+ZTShLR)g3;)!0Oq1BQ^en&bQ+;N*!B=wlHS|!MmpLgu8yK4v- zi%{os=PwA8${Kh}lb&z&uOSQF%|a&s5WW+o#}w^Fd!A$L4J9o;O4I)!N0;oOj7PeF zU4Za{Hz&zT$(2R-^%?8g+QHj4C#Xj3o-wblfT4tFNZIZ!g7E& zY?cX}6cNDZg8V7VHUYER9rtSTtn`z^a1=E>mo=U_-A&V0Zv=dMhy*~6HMXGG25^L4 zC-^XDrMg**CFRTiM2g8f5#LfDLA`zrd;M$ z2{dF91G&}i@L}25Q!xum?1+Y5Hhu*AUk9{7e`)BUvfv{olDJ#4-uZe1z>`+~5M@2u zRnhR>0nV-`Z!0^@-D8~7_A@1Ay9Y-4;rdOtRi(_XGWLnv(|XlLKmZRc!&Vg}75pDA zoR$#C1&amQLl1*ZEwE3pulkPwW*(U-IW@~@- z2i9F=6{91>55D&O86%^HZ$U1mqtkIn(6zL`-xTzx;>krVy2O!_cRnSZ1e7BK3`h5A z(i(7&V$QBf5a9(RNqQX`khM=f@RMnMF|S1%&EHfHG6W*N8M73<+c5#6BKw7bKep+c z$|6zoHy+kqa-=BC++n4~IBO|6{21%N9nLoJ#cC+flJ)Gvu#a!#x$fz5@p`XzCT zSnwYtNr_5EvI9T$OY-aV=L~o{9AANdL}pM&5CR2&P-5BN7HcLQsR%i1GUA0>2dMr| zKST@8Us@%&)7?9@TIw~njv3iZQ)Xn0%)G?)MS#$m$%yt}8Ik{R>I{-d*5`hNlH8PD znlTKK{CI^8GLXaq{C&lepLheLwb(V^z6rBi)hCx&q8dwC@nw!e)d%B7qzHc!FnCW| zfz}b6X^S1}FyKi6g!DHI2N(nw;O5f$afs_!r9W zV2}ddl{^Ut!-vbRTNI{NVCZ5aF`~xmw>kFn$3?8xYvHbeH}P<~#1+ zWFF+CUY7QAz@|^Yf3StJ=N^Mh;r1<2@UzJGbmbkoi{olKKh<%RvIhw0>o*Ios2F`X8&X4C288T3@CK0-CqL6XywIs1 zf+!l#HYIjk&bBm=3G$KFj;1ErOyro(!{lP&xSpEqjBx4OT|U5YpQdvYqyj23q*RdvvlE z8?o;G0z?jpgqXa)g-}E*-(1`VZRYXYLmF-%z)j_MGk*GPZH0`aX78ZV;U z!Ta-F0@>vNE-V%F3E^j&Af^(upC32^MI}bE1qr_YPa}=7m8HY@Get-SYUd*1ad)Mp zvze}OPxn~k7l+Kj_L1Hh8FzIglQ>hl-#-Sd(KxUSw@pnR!ls7Nw3)&XuqiF29A{1; z^aDg9({X6XZ{M%VA*VywK^r$f;$E7D@?MNC?#!p8ngLyxGG?N0r$^cd(TZ_cFlvRP zdPsV2QKW=Sx&QU@)9@%w`Vz^SvID&z7`*@eO2f)$m#_)*4xj@ExpBBOrD0N%lmt$oP?8#F&^tgsTsU?;tr3xfy_ zM|(4GIdLB6(PX2Hs4V+L|atb|8K^pu6V2@#&&w~@jv^&C0 zZTepU+KeTI);E?l6v?qlb(~bVYwM}J4`xS@6yc!JwHR58DOGE%m&EKC2$-AxRhs@f zZc)yRyozRk^e=JUK6sbzH()Kx!{@;%7B|-2h@~|9d2T}<@#Rtk&vEWZhlc~-4piTp zy!E%MLTcHPN2;5935iz8rK};T3u!1*Sonb^+GlsD76|470xxyWwuoP5eR7C@Ho%7i zkq-b0x(d|J%8}0fo)t-2|L4HlpUWPRviv9+(#3v5PA*hj`e<0TlkT!~9lkrDB&D3- znkkjM&+7IPf1O841?Cy{Xzw?89T_CBsUbIr;9P+*|? zT|AsbU@>#oq9TB(a8AYXr%F!Ijg+vTLI*|KBXZTk zL8fgnkE=s%0NS5_=W#}!8~bg55{P7P9R_xVCwz@J~*l3=Q3(6po?|#VGnxiN9r`-*54Mo7wq~8Iv^5@U|6MV<0T|)1KjK=eizYvyMcqRR2 zM!+&rKzQ_)4yWv8K{%<-$QwA@M*bkZWX4Zgqdv)JLc*C}{uc!TVU8xb5ilzj@ap&kNzN~)T!X~#E8i=h#E@2?GM$Dt(NdhUIL=63(59UiT3D)p{0 z&YI1rA;Fyr*>+osYk4jcFd|?N)&OvE-?+JuU&*p-QR+w(W^tXYqy-k|Z%$UN+yxz* zc+5)d|3rkKhe}n47xXPF2bD2Ci!7#)BlMkFN6${#J0pEVbdcHV)T^~vFAUugx^H8I zGR}D*lW7%@sxs6%tLA%Bz+w6C#n|lipl&QRTjhLdCw5pO^KF3+Z; z9tHQFU#il`@xw_?05_M8AA<56xEA^>y80iv=%w68yb#{feQ?>n>vb3;lX6fZb@Lz4 zUV)Dw$f-=v?%S9_92VHxW_AQyCs=}HH)l^I_q+qgJql>qqxpv@hZFB;p9VHue7v0Q zC4VpvpJzxfT*I1@Fi@ljpTe#}qVQz`J4574%t^=y~ ztSCDm@9qm}|26+uE52bH6rVlmOxetf+6MJ?@z3tyLU~dU&bArEy*$1OIF4-2}pSzytn=Ob4fQo?ZVSnLZhe(Cc*K)4w-=3KA>q0eg%n z$tXb*XPh&IxxLW}R=zh?cTF@#E7-gurmk;Rn#m@HRqh>$f8~W73haK))IcPX>Vzw{ z3ZzyM*mCoqN9&Ls`ymqGt|MvX2(%y$@3x|4zk2hU6w_|Bt*!Jpvx+l)rz0#UTuye1 zdPh9?io_{x4rcYWBE8z}zj?yp0zwiw*Os<@->Q0-tY1l}&Nz8vJdm4VevW05MVORUE z&gsElD05QqXR}A|)}w;hJfEKVerZNuY>y~@Bz!Vdb)mzOQH^FxabBT0f^)s|J&#FT zl@&@|EiB*fEL8eX9wGFc+8K4Jz*jb|xaLre{sY_%(yoRTEpXL6wJnMG$1II&P98DQ zDtRAncn~nEa+^YvDFJ@TxMkdWG*^gIfm)Ca8ph&f_AvY8DzzthY9*Xs+KlJ3B)Jno zQ~Lt~`XXyLi;Ag6Qs0;<`LhLScip?cx@VTPc)b5*2?>bN$)0;>V@zh)=Z`u4lv(wG zdTD`{=--=L*b||Dg15C~=BH|zY7pIFZdjiriytLmL(%iqd!+Ca6gc36X$m`1#CW&v zUDdiu+t2WUV`%v;rsrl(X;Eb0Uk&+MHcu44!>Qb(n7Nd)H10Ib2I)uAt$Z&xFqLImU_^+ z-d^UDQ$OxiPc&WkgnPPaC2zz!eN%snWVc^&lKafoPq8m3j?wqe!kyw$cqFAhc~#z? zfCh^_l8lMY1GjL&3)u{I!-5v)hbn#*H=EaM5lg46jrq2`ni!DyvZ$I`9$9!+bqBL@x|UrXrY*a<)O$T*y{_Wj2Gw`Tm`F*oT1-m zjGY(az)B>MQM>lpp2nx9wY)vaEqIy79a~C4-mqB@oKpSCI4W@l(&2T6)sZDz6yh`5 zhbiykc{omEbzj;f{zUSP_CR8xRPY3brxD~cr^qSf^~F@m1@(6CckP}h*1!k)Zdk}? zvSddxa8%FBn6dn*bz8C<*P#7`5;$w?pQ}vhlbILhp7Cg^l>@bC0rcG7q>rT8dT(qP zcD@T&5s!o9u5Ay=_8$qX{<+ZJ7|}EEMqMt=BOo!vCUZ7X*RLF;Al@|RqP67Dvnh)G z92WvDs;>Du71q+5?M9IV&@=0k!j$&>A`ppqYGJT^54Q?e$z!N49GSZxQyNpW_M+(| zw{y+by>_2ak|D=!%^c-ZS$9Q2h)7XfPvNadro@M00TKM9r{iM%);kW4 zzgX+YohLo($P@43a`dHz*;vw?3u73wM~*j*|5e>=oO@#y+scwfQtZvJFtfRE`mR=2 z0#!7dJXWJ*x*B!QWnGm>4Ld~?q^itYz@ZwN5WbH*Pheb_?Yr*Ts*j(=^cDus(v$Hw zmCW5Jft79G(TRBQa@*SPRS(lj{GiFaAI9F9GTJqEPx00SmR$l~{-8p!G4BF*yqlxS z<;s;4xL?T7!t9xh)_Ka@4h|8|wQVsR>&C}VS1ub2UTNc3y1w}P0YNT&pi-#4@?D7X zs*TDVGcT1hx6j`mWybd;RX$%5kN-3Kpb~|EJt^Mw{-3KUv;qp#fLvM4nb1!-kPV$Cw)o-^p;M2Iu9l|ft z*aU(0vWbnZYcm?~INi}eYB%05pY0!UHKqGCZ>>sv5-)mTcBErBZ+kGkmJ)&ER-v%G zg>W=yJwstOcrF{wQ+`|7vruS&jv%iQbl7+tA5tO{B74;PxALUPjUIk#?fUtwQ^|8X zWy}d{FV5#|`8Q^0#LV+!t9ck3NT3Of;7#GSXmb7IO-oS)u|Sss~KE&5|ld4AHg zV~l3j@>TR;u79t$fDOUb`~yp7Oim(R*kR-O@L8pI&u$quCskUL8%hKR!Y!UaQyf9VZ4l& z?!EqRKg_d^QOWv7-^kNc0}u1?%4Vu-exIAr%&E(Hru}fF32*XaWyG?Vg}3g!&KB+U z8y>rxf1OL8qLUZq85?_MYglGuN$_`70+}nv)8IVAPp{v^4HG*$MXjO^8jOdpLS_AG zn44}l{^G(m2(D5kDQ~%&?LMv(ek9nAv=iR*N3DC0YQ&QOZA{RsfgfF}4us<#5r3e+ zIMJlmpZ1Y$Qm8T%i&Aw-O3Jst8@48O*G7?f&|NWobp%ZBUR5rMO3%{oYu_`goP75* z=bn^y{N4F*-O$_nWFvGkFM5e+tG33RS!frLPcE2$>k;SUB5aUPLT-M{mC_9Ed$qiQ zo#P1;l^C-KSBzyn`OC#0_!!wkH6QPyR|~FjqSQ@OZer)78-#-BsQ%wSvWUdyf=B)l>mPp;T?oM8G$u+i+YwII8>$1L)~l&n?)&-H%3j9l%G zcBXiWMo*0bcGTb?{?6dSk*lfmYMaq&E{VH;m?RwG`Zav?nE1Zn!s~7Cdx)N^Y{%oN z-q;X*$_?d~@+!GVxJNmm?Cgp|GpJ3?<#uxCcy+8(mn^oIuRB<5T{untb2*k4_(6IV z#ooG__trEIwaP@h54~X*YVT6T4+{R~+2;R-Q`lEGSt?9n|DxvcxPx+#6t@i(?JwXk zi~VXKBg$U>9Q(uba^RCxiF=G@`m?V4E@72CVV|AbkI7t#KoeyEN(JfTZ! z!@EkY$l$S_H`RDYkW#uI+IV$PpCr6kb9k^)j~UJ&$Ze#5&R@jf(KRf<)r z|C>QL?@0GN;Pl&K1(Gabst|Pc{&*7-mmKABQmKea{8hKPv`%aPX<@ z6W+VB8jKMy&V7GJ5a+&lZ+*_>SvIbEsLeEBx|8usyP-X6a$y-K5zn267xXiQMcGpe zFUJI|jdO%lR){||&S}KjD^73hr7F8zgu=Ve?PpJMt{dL?!?9>9Dt@wW-;>QYe(4;+ zf(qL5^OVX}3RlZa-ek47y=_u%JOX}rh2vInGQ*NAtU5opF%MS?w8t5(m8t7gHV|-= zLZa|%U5y3(@*{R#y`hhZ;AMzf<*$m50gGtP^-=eB8#LE@l)tOhI@NODf z|BO5DyPomnomj@bseFxY1^`Z=h-hyCpZ&xBe`-PKC9$um20-~KKKY%=PK zISvnl4V2z9O(ct{vPY`(CWC3USW&%gzhdcusNZ+IR|^&P(BaV+Z?f@*B#GJ*A=Y)3QvsxF z3lc%Y)5K9GrJv)g(5R~LqH1ThrlpB~lpB7N0Q;L(2otWHJJAMnBBJM%T*#GK*F-O? zIjXh#I|=3+=ZLu~p4PtiJ!@0z%@kkJ9o-2ARN(@l+nhn<4Pn_F{ocp3c*c#jL6aGU zaCJ;$*h-i}w!dEfuXEqXbqe)&o;Op@3)&@+y0`BF3TBJU{De2L{7wV!273t8>xX4S z2Pfag!yGrEHrdJT;)Pdm zyv;QV*lbD%{!pNrmoC2DDGVBCwG;0s#(KA-py@iQw=-?-51(D=eJbB*yd(5A-`y~F z_wZNlxlqcuA^C>B#+e)FDn(-3X#@T~k@%QY1@jW2FOH^Hi&WHJiGGPxyP%k|>Z8-Nn#KXLnO?=Q(#SOgT^PJbyQA9#CW6n0-idG@-Ou}id0{-p{-L7q! z$MiJ%l3M^uxW7IlQQw5)hZoC+(-CMoubBqo{o|!OdHxDLYyJC<9BYR{UuF%H8)-A3Q6i_8r6+@T)Q zEdTB?h$=1<-S>LA$N2@1gUin6;(oh5b6{%cf+W>Ab*PHk$Xk!Uc0=2(DbQfO+5e;K zz2n(z!~TDJR!}u+Ybm8hi`uhRt2J7CD@9wiNzK@_YIN9pmD)vXi&1+QMU8~mGZ9LN zK@6Qn|O(dPoHAoY)*7JkGrEco4L;~U3s3+Lj za4U~2_d${>ma|O9=H061jGeER_I&~dMdCnT|W$8p`e#Wi}w)Qq21{ME+uAC zdI+Mc$CfQu#{G0;#-UfBHiI@|jyx%syRF(BgFY))Ul*aJXMO<8`eC%McJ><6R^L2}pwsAs|r9D69EALeelpywzP__iHuz`fKTctrU zKBkHo)YA5wvo79xp{!aE*y+;^hU?YULio@36fDl%f!fxH@kMX$=X&8|Sl#CQ2fX!N z;2hxMxJ5U%9>zF$2HbGwxbx6V2%j|1y=(Xwj+*ZP^3mu|MEMJh1`7Q4um-2seN}NL z4be?Q?^n30e{3AT!^Z`z)>L1BnsRW;5{hNQGFt?jFWi9Pv=$HKR z>8J}+rM$ZAPSSYhE>9`e2?t!CR2`sBvRp2Xu(_p);H7Gzrp6TBA$kBx1li;5<+Ln6 zLMGMdU2$)4L+h}}%MNHl>Bh|^ic!%(OCRmc!apEgxq0($W|##4D(7~P**opxI$fHrX8zw%vx8>(8Fa!X*`xjt_d(rT0J+K zd*Lb0CimG{ip7C_!5@k>^yg6===*4qkwEojl9y4hif4h6BL7j?1eoDc>E{Tb;eLF< zw#rlUs79)2vBXjyXm}=$r(JMWKpCo^i(lGQ#NU|~#m6U&LI=in8e2!8gzD|)1?MaD zf!sQ*INvQOc+t?;x~O?>UVJ1uVeH4TUza!+i+9MkCBt6o3SVvWvNprIv_HZsbu?%d z7QAqFDQROXolQW91_^Db31@`&_dcbprB{A3?2d(l@1RC!AEpsBZV4N|^4WHiTgqW@KBs`X2&xLe#3(8LTm*xiZ_ke8@$1cELbX7X=R!Q_ zPf6`a|3r{TkL})U0KFi1%;gH?v)XQl8mCZW4BCWlzBrbYe}G)SL8b}{>R*eES23ha zy918MxT*m-HUgn*wxkt7@fWG}(NxKcCDjOppFkUO(%X5YWQ_~FXKp)$|DF_-;FNpS zA9#gD>wR*kN%FRdveaSO`ucmN6X3G5qoC*K9)as;YwRb)>yJ#C)-}uLE+fcWmcpv~ zJi_A+6S4PM@{ng*ZwO0B`1Rxt$Q*MA;e7{pgq?pLWBi6UHp!Cl61#vkJp3Vcc1*R| z{MO{s=!wS-F#MA4R^E&8WucJBu&+t<2W%0J`j^xd@*l#eQXtkfhsl3zFEKrg9NeGG z8U2Z)Z6p0nA&P})C%Yp;axf4W zW6`X*Cbm(2y+lND=)OPb8!V+h+*v&*>zAo?D89AU6Od!VC7znPOMUth+#8R8ZY# zk3LY&yMupRlq9YYx*UFQ7=^s(xE!5X5EFR!E;y+qS|@DbnpDhruXA8LD`iYESJ z`w6n@J~meILF!#{B3tgw)%t;QF(H_nwn@9=Eoq;79G&UhV=_KR3{<5){0%oDi%^ zYRJL-N9O;#ZQH#H~^TaVO+w2SJ_5uZ3vbeO(y=y8{0W{xfxvx_gQhHq7 z$(vWoLJx$y8q^!ug(<|E5CvP_w$s9Hni*wR!Lc;^DekPRDpNg%$|65M#@kYhw<1Ye z@uWQACv8V}TF;dZqWb#!cFx_Q7k67Ry*tRogH{R{?w8DRHh3v4$86>GmR!P#QXh)M z>hR*vJS;E)5x*gegUcnD<|1BOYMJG^v-KgoIe8op4H^2{)TLBqj$lQT1vDE`ylvM& zFct+@y3oVrc`k=zY;{z`X5eq&M=#mib=w=AT~8@UDuS5N;+c5$;4wg6(?RyW z-Nk=kVSaATGs_~f$#IFU+iOwbmJH4s=CkCBGJ3_9zJVMM3caXZ&hztwI=n+gpt*W% zo7=;lbM$SjINv=#y8$+n>#qvRPklc^-Wn4qON`P~_CjdC~K z^a>On`Cza_N}1B1619c$5LvsRn?vHlL_%^|N`gh!BI?%o~(00ZV%ABZ&vY?;0DR&r1`DYXgYI!I9{j@!< zRJ$|KJ!H9hit=aJQOInRLP0a1r?9nHMZ`Y=xdodHKd z!(+Moz`vhCj6jl@_Wjc4SwSeM2QLK$e<9Uhf*LZ_K~!f!jl2BK3;U*Vx{I{hft^O!&GBu)RPyiJ zqefonA@=)VUA3ga7<;d6i8{L3R1HI7R3xo91cp3{Pl{;dS(P|6o!} zDAmV8tN8(kNazBO@VUXaE;ci#Z&lBt4C{aDR7#K(fpr*sy+D>GY&{BPs;yl*`=teb znw zWGxOoX=)Co|G+xfuNjQ3T1r>0U7Q%nzXY_0e>-}q8~=RVtE(;8x2bzB`*BufCUSV` z|L#2g4BzpY&O0`W;ucLP^U?Pz+X-JMnr*=E>>(2YG_`X4Gdha%wS{j*?=T=FYn#YE z_~yZns9-^Prma>^QSWO2CEcyZQ|u!um9%LEP>)m#^hWuN`Rhoiz9jcf(cBq=UJ1-N z%}r8)CIveG*|AbLz0VOm&zNev+@dsVMaf!4TVlhRrCM+2&8Z$N7>JSX*dhIu>=B1x z+-Io>GQw-#6*RM>V=P*v%zI*y-SL1_E^pMg+tdXdpS>eOw^IYW+*-i{x4CZNU-Ajg zAKxJA8|x;#)P-NqcmGH0d=<=fwsCa!Jct(4-4Z|k4gC?U!vd1msk-^P2sfKz1?lH~ z`vxvFXBZ`F`Quysm?M{vtWuW@&n$E2!l1(*jU!SfnYfL)zm!hn5-_6I$Gd>J^A{I8 zsr>}(c;-&Y3%8p)pXJ?x@MnoX+L|SXIXiDAQHj)Wp>Xs;IujF>w`KGyWoMa)T!Q;# z$YtJA zk#@qC9mbZn!nGJ(O>GkSbN^nlxpe5qt-n&PbudDj4!ZAiL5n&*aB)u^SZ4E{d%pJh zwoAdGXyl$RPR(nC1ViVi%INDA`&h$c_eBiz+4UWw{xLjqL^~i^{Ob?d>JM~rZBsn9 zH$>xxU#ulV`YmrhE)P64B?&+Ern^V?@X#R+`yP`c&l3_VZ&4hSf!kYueW8HQg33Qw zx=xEZRX_xbw_OVGklc`gqP~U8cY9~2hR;L^N_0}2juPB@gAWFaLASCFgE%j_p4{4m zDhsM=iS^AYXs88fTD4dDRWNrD6QtQTV8AVH_mEbIY4@AjcE{tc$R%T3^4CG^yw!56 zSupnCw(=9@pnn9A*{|)XFJY9dHCCw~#b^y=KIXmK2$uQHC;#sE`9npiogMYKM9m$J zC{UqKfV z&S(B$WZ5W20mtdxTWSP%=az(;5^xKD_P88uc?jKc;?aP0VOu_C`RxI^Ar?b(3$N5M z0v+&YyPQf2C?rLT+Lb&b#eX$)lUl>-E*oMN_Vx{0a?l2z41n)-8((GNa ziiH459|LUenbTbFpR=9Va)-=)>IN-QSj1e@8b@lNLP)emIrm!5Lw zY9Q-dE)HtCkQa_v|DJn`t>I#Zod;iE$4sC8wl=MaZi*21ZJ~`It;x=7 zA;KXrc`9^P6}**MWCKFFR=OgVL~hr_3SP4Jm9}Z;`t;map6aM_x9=p#Jkcu(Y8o}y%5;-11;HV}U zKrie8y~0_G<6k-?o&_9Nj}a{PIxgwt?#%tzCyBz#Xb27+j%zKn8)na`gR_y;1d{(A@3w^;-9xX zFZB4yWjx?xQUxxe*>%-sUWa5k0JG&)AM^UKF|C`heWZ)fWN<4nz5@BKHs|!}Vz{id z>q!Bf+L97PpEkeyWK^Elt6p>|$9VVDH09 zgM4aG>&uZKP5^gE-h!_3X4OUWMye{L2l*;Y3PHwTSB;pp|SWs@SNRirYm+e*JLAq;o}C?*CVKw zQx0W9`w}Zn@6OaXGUh@Q8RjNtiynD{?It_21y+Q^@kT%pA9*)S^ zP`+A~d%g?{LeL$2Q-yWhSb2>;&e9c1Yy&CDf+HO9myclik8DX}du4w4(b*k`{^}tV zsM$Mz^#TIOVH;q#m)gCj zY4yE)WhW?m4?~ShQsH&|ep4g6ly1p(%IVs=O9+`=-^Rl6V?En4z5T@1F|yd-SRDxI zo!{kyGGFUx%Qy>?wSC@M+OGy_i6jb$gzjE;bb2OftW>wM#q6WHalzh>Plba+vHpAQ zp6}MG#;O9?bKe}31$Kd}Q0>tbhR zP;`bnRp~XkA(KXj{$~2I_jQY;d9vPq+Ibna8PV1N4LIp5AulXx?L?|D4v`^uS}b4>JAty;VUz zPrBT!CmuD!=V50zHnk91qtqH9Z=mjw9pldl?gI9TeW*Rt{3|oEQn_-zZxEJip1Txn ze}xvuMZw&q5dzuK^ts{#erepru8$%Yu%P)SZhh(|CCtc1TW0ys?red|?V_0GIGX{(3H#P=M@D1yt=-w! zd#nUkY$aBYitGnAh2ZeVrYHCcgnn!Ig^dKso!TIeW*z5y9d3Z)sDhfBk6|GYsG{l8Ykr zpIC65yMNygt1$;E*pl`(cICrn)YZ}MrxD$7>&IgUL|lc?$!&Q*|GQ=oGpy{Y{*;wl z8|nGy?Nv@MgruBa;oXfRE~?C%dcWS#_(P`j$~|J3El^LvM$0Nha6b!-(4wJnbGNWr ze#C3?Bs68Ds2Q>2g&}9>TQSBV?1@yn^snG+Sj|^pM7{tlaQ>NZ=RxomxC%P;w~M6o z5NRBS9bD`SBs5TgU`{KiOD9#FT`Tvk(5SZPpdk0Z3!a&UAV8!7XF1%j7Gu`Uq(gz> ztpAHnEZ;Ffrq0{zg|w3l0ookKYUwe1hMkvenCK&CLkmk%19}$@*A)Dc*%KgB=lrFW zOD`3#5;f)u+G(7%iPL-5_I3O4WcA`aK=8?Fz?YAQF^C)6pQ_w7c5deQMym9g4<F(w&v~ zHrpgs-ompYVd<}W@M_Un@L#ZsLt*CR=&ynhP6qmvY$_uao}8EgdH)wE{P4+FiO@=h zwP&tDWgZ+SZ!Qp5h=5yCe22aY7F2jshub}}4~72@vxFcqVR5-|_&(dm1v!c@*TPZ$ zI?o@TBJ>i4D8}f`i7yOqYwhULP9q9V>r0p2$b&hEMRznsLa!!ab0FJS`YR^3DFieYMxwhlbG8gZA+MXD! z5_Ec(7%)8QU1x*~o^hGLEw^Mulcqy`pf%Mf+1?{E8WK zg;f(yWSk%?2`u(j1G3U+FHYA&qs^IMm2Z|F*Z}O7&=yC~D9I51w+>-5mziB)VVKj_ zy8uL_!@ikX?5Yh%hCApZzVflXthiSwr4k!-vfO6<2 ziGQ9e#bogJ_S^v|hv=H07|R*h5SQz8H5{!XFCH^tJ)3+II}|=7lgnzegb$;S5(&U~z*(lZ zxd89o>W*d-2u5v)4B?w~1_jd~b@FL;nx$7E89$rRDF0XWtN3xWCyj^<1HH_W<&3jw z7_Hb|iSG7uxs`y6;EM)*DQn%p1Hnwl{D8E<4(C!pOoYaI<1q-*dZ}V8cR(gE#HrW$ zaXZlU2q|{iigoZU3x3Tz)v1!G^~eX5S7Gb%%Z(AcG%Tqa!6AHt{XJ_bmUj?A)e;3XF$Bb?}FAa-yQU>JvFLy=;_3o{*P(u)F>f& z9!l*4oGy!<$O1ik%h>Sp{L`39;?o5H95W&4N>ei@%kx@gPkX0uy)-;IQUu`n*$9VK~CQD8NUIuD8dK~q?$Upg>$yyrN zwkowW)hn9HGm_Fo{K>l%oaH(3d`;+%^7aPQi$G441GWf|tC3RVz%z}fLEiYMeR0B= zl8D&8P>v4A%#i6mMK2rv)mhM6U$_)z8l)7BPA-qEf!Zmnw?%)>i{P8VM5J6@1E|X!UEb|4RYtky55VwCq03br!XVDsp@lcj2uJ;Aa=J2yFD5SxPA@hX}liKhNbI5!Mz zfIQAn&a}a_2A6Z<@nofBELr278$31GYPta|N3e}{3jc_C_qz{nh#BHdS^Uxj8kzMPeScY&kRRzrITOuvkr1gy^*BH~8HB11k&llfpeGsCVixk}RM&x=png*@a;}{Lh~E zPn!TN=6kSWY7foyT`; zYg$(kJcx8Zi~IXRL&qgkT&n%KK|#GJ!F5~D6X(b{kl=c-R~u=;lj-qBvjY5UX*%CK-K z{GP0glD}2<+J(ifV|0G%OUnFdz5R