From 8c88ece3dcbd4f0ba23d21b48e95d3eb4ee935cb Mon Sep 17 00:00:00 2001 From: Rico Berger Date: Sat, 2 Dec 2023 15:52:50 +0100 Subject: [PATCH] [lemmy] Add Support for Lemmy (#94) This commit adds support to add Lemmy RSS feeds to FeedDeck. A user can provide the url of an Lemmy instance, the url of a community or of an user. The special thing of the Lemmy source in opposite to the normal RSS source is, that we parse the provided link form a feed item, to check if it contains a image, video or YouTube url, to apply some special formatting. --- app/fonts/FDIcons.ttf | Bin 8144 -> 8724 bytes app/lib/models/source.dart | 16 + app/lib/utils/fd_icons.dart | 2 + .../widgets/item/details/item_details.dart | 6 + .../item/details/item_details_lemmy.dart | 87 +++++ .../item_youtube/item_youtube_video_web.dart | 34 +- .../widgets/item/preview/item_preview.dart | 6 + .../item/preview/item_preview_lemmy.dart | 71 ++++ app/lib/widgets/source/add/add_source.dart | 5 + .../widgets/source/add/add_source_lemmy.dart | 130 +++++++ app/templates/iconfont/config.json | 14 + app/templates/iconfont/iconfont.afdesign | Bin 42911 -> 50292 bytes app/templates/iconfont/lemmy.svg | 7 + .../item/preview/utils/item_title_test.dart | 4 +- supabase/functions/_shared/feed/feed.ts | 10 + supabase/functions/_shared/feed/lemmy.ts | 323 ++++++++++++++++++ supabase/functions/_shared/models/source.ts | 2 + 17 files changed, 711 insertions(+), 6 deletions(-) create mode 100644 app/lib/widgets/item/details/item_details_lemmy.dart create mode 100644 app/lib/widgets/item/preview/item_preview_lemmy.dart create mode 100644 app/lib/widgets/source/add/add_source_lemmy.dart create mode 100644 app/templates/iconfont/lemmy.svg create mode 100644 supabase/functions/_shared/feed/lemmy.ts diff --git a/app/fonts/FDIcons.ttf b/app/fonts/FDIcons.ttf index cde5a0945d75a66b9606b50acb332378ff9d305f..224e3bf774f189ddbeaad26080dc97a7de18572e 100644 GIT binary patch delta 987 zcmY+CO>7%g5Xa}ew;%Sdm83Y{wb#zBy=%X1g1@p}udUFeRjEh|6wwe6ph%V5h6EJ1 zky1no2Xo;=0;!c2iF2VRkhu5?so%b)%%YD$kPD1sm=A?74EM-j=evk zN1F)LMRpO-U!s>c``340x_9&k>ivTG+Sawpy%SeYuK`FRZ}xk;+aw?#V?B#`@oKNX zeyKQE{u#h702LHXD4FB~h)d)PV#Ir7>y(&+R7S^-09AAe8{htK z>YGT#ttv)s%q4hc+#?A-GU8pjC>vN&;;-pn@g7Z1rmzkK-)?N?@EfKPZG=6-!HB<; z>NNHKP?CQ&2CA6O_URqC1Uv8!+=kC!2wwrDU3G$}iea`4Q!x!wRa6YE;3P2|FCDI_RW?LkP+F^rW@G)=BFA={^eC}}+;l8J+&3W!~6;%f)K8AJCZI&Wr z#=nI7LRk)4HjW#wPRL!w%-~hAI#Jpcj}e8u^zfhtMrK-ZQS7axRA@}vc9+xwLKuHe zWl};)$aKweXj{^!q|RI`RU1ULRCv5AX^KXr4$0duD-)Dx7kr75pw_kR$$CLfwgT6A zY9}*TDey2zRVq$S)4CJ0v-NDPrt9>+uGfrgu2$u#g@m4)sZ&9@!`Dwgarm3X$4@%m j-}CahirevqqkM)DGd{Gdlw{*M=hLLTwchXFz#r=$I_IsE delta 400 zcmbQ@a>0Ira{VL*2F4x+28OWY+{A)2S#Pf~FfiEw@wD`u%CzfiPi$piU}a%o5POo5 znwX*{X7v`R_5l!^WdH@(ZJCpS>^(rNl95|d5&Gf(FQ9o(fc%J@{NzNNJku)-3@kv* zpqHCiQNU=(I2|Z20pu&>CFZ6kDb%|^W?+zh0krT-L4I+`?WaEt85rd502O>@U}Rum z4*H)3Bwzgh_5T<1JCFzp5Ce+@;bD9AG8hfio5K8#IReP% zU|<4?0s+V*F~)9&$%>5Y7)2*vV9Wt}nt>IFnSodbh=HDFtb^KE0Tc!4&;in1U~v`( zAFvu0koXJH$u&&2KqYL84>B { @override void initState() { super.initState(); - _iframeElement.src = - 'https://www.youtube-nocookie.com/embed/${widget.videoUrl.replaceFirst( - 'https://www.youtube.com/watch?v=', - '', - )}'; + + _iframeElement.src = _convertVideoUrl(widget.videoUrl); _iframeElement.style.border = 'none'; _iframeElement.allowFullscreen = true; diff --git a/app/lib/widgets/item/preview/item_preview.dart b/app/lib/widgets/item/preview/item_preview.dart index 9c73410..291ef4f 100644 --- a/app/lib/widgets/item/preview/item_preview.dart +++ b/app/lib/widgets/item/preview/item_preview.dart @@ -7,6 +7,7 @@ import 'package:feeddeck/models/source.dart'; import 'package:feeddeck/repositories/items_repository.dart'; import 'package:feeddeck/widgets/item/preview/item_preview_github.dart'; import 'package:feeddeck/widgets/item/preview/item_preview_googlenews.dart'; +import 'package:feeddeck/widgets/item/preview/item_preview_lemmy.dart'; import 'package:feeddeck/widgets/item/preview/item_preview_mastodon.dart'; import 'package:feeddeck/widgets/item/preview/item_preview_medium.dart'; import 'package:feeddeck/widgets/item/preview/item_preview_nitter.dart'; @@ -53,6 +54,11 @@ class ItemPreview extends StatelessWidget { item: item, source: source, ); + case FDSourceType.lemmy: + return ItemPreviewLemmy( + item: item, + source: source, + ); case FDSourceType.mastodon: return ItemPreviewMastodon( item: item, diff --git a/app/lib/widgets/item/preview/item_preview_lemmy.dart b/app/lib/widgets/item/preview/item_preview_lemmy.dart new file mode 100644 index 0000000..27abc00 --- /dev/null +++ b/app/lib/widgets/item/preview/item_preview_lemmy.dart @@ -0,0 +1,71 @@ +import 'package:flutter/material.dart'; + +import 'package:feeddeck/models/item.dart'; +import 'package:feeddeck/models/source.dart'; +import 'package:feeddeck/widgets/item/preview/utils/details.dart'; +import 'package:feeddeck/widgets/item/preview/utils/item_actions.dart'; +import 'package:feeddeck/widgets/item/preview/utils/item_description.dart'; +import 'package:feeddeck/widgets/item/preview/utils/item_media.dart'; +import 'package:feeddeck/widgets/item/preview/utils/item_source.dart'; +import 'package:feeddeck/widgets/item/preview/utils/item_title.dart'; + +class ItemPreviewLemmy extends StatelessWidget { + const ItemPreviewLemmy({ + super.key, + required this.item, + required this.source, + }); + + final FDItem item; + final FDSource source; + + /// [_buildMedia] returns the media of the item if the item has media file. + /// Since we save images and videos within the media property we have to + /// filter out all videos. + /// + /// See the `getMedia` function in the `lemmy.ts` file, for a list of + /// extension which are a image / video. + Widget _buildMedia() { + if (item.media != null && item.media! != '') { + final mediaUrl = Uri.parse(item.media!); + + if (mediaUrl.path.endsWith('.jpg') || + mediaUrl.path.endsWith('.jpeg') || + mediaUrl.path.endsWith('.png') || + mediaUrl.path.endsWith('.gif')) { + return ItemMedia( + itemMedia: item.media, + ); + } + } + + return Container(); + } + + @override + Widget build(BuildContext context) { + return ItemActions( + item: item, + onTap: () => showDetails(context, item, source), + children: [ + ItemSource( + sourceTitle: source.title, + sourceSubtitle: source.type.toLocalizedString(), + sourceType: source.type, + sourceIcon: source.icon, + itemPublishedAt: item.publishedAt, + itemIsRead: item.isRead, + ), + ItemTitle( + itemTitle: item.title, + ), + _buildMedia(), + ItemDescription( + itemDescription: item.description, + sourceFormat: DescriptionFormat.html, + tagetFormat: DescriptionFormat.plain, + ), + ], + ); + } +} diff --git a/app/lib/widgets/source/add/add_source.dart b/app/lib/widgets/source/add/add_source.dart index 3d95b50..dda2bc9 100644 --- a/app/lib/widgets/source/add/add_source.dart +++ b/app/lib/widgets/source/add/add_source.dart @@ -5,6 +5,7 @@ import 'package:feeddeck/models/source.dart'; import 'package:feeddeck/utils/constants.dart'; import 'package:feeddeck/widgets/source/add/add_source_github.dart'; import 'package:feeddeck/widgets/source/add/add_source_googlenews.dart'; +import 'package:feeddeck/widgets/source/add/add_source_lemmy.dart'; import 'package:feeddeck/widgets/source/add/add_source_mastodon.dart'; import 'package:feeddeck/widgets/source/add/add_source_medium.dart'; import 'package:feeddeck/widgets/source/add/add_source_nitter.dart'; @@ -52,6 +53,10 @@ class _AddSourceState extends State { return AddSourceGoogleNews(column: widget.column); } + if (_sourceType == FDSourceType.lemmy) { + return AddSourceLemmy(column: widget.column); + } + if (_sourceType == FDSourceType.mastodon) { return AddSourceMastodon(column: widget.column); } diff --git a/app/lib/widgets/source/add/add_source_lemmy.dart b/app/lib/widgets/source/add/add_source_lemmy.dart new file mode 100644 index 0000000..8c4e6b5 --- /dev/null +++ b/app/lib/widgets/source/add/add_source_lemmy.dart @@ -0,0 +1,130 @@ +import 'package:flutter/material.dart'; + +import 'package:flutter_markdown/flutter_markdown.dart'; +import 'package:provider/provider.dart'; + +import 'package:feeddeck/models/column.dart'; +import 'package:feeddeck/models/source.dart'; +import 'package:feeddeck/repositories/app_repository.dart'; +import 'package:feeddeck/utils/api_exception.dart'; +import 'package:feeddeck/utils/constants.dart'; +import 'package:feeddeck/utils/openurl.dart'; +import 'package:feeddeck/widgets/source/add/add_source_form.dart'; + +const _helpText = ''' +The Lemmy source can be used to follow your favorite Lemmy communities. + +- **Community**: Provide the url of the community you want to follow + (e.g. `https://lemmy.world/c/lemmyworld`). +- **User**: Provide the url of the user you want to follow + (e.g. `https://lemmy.world/u/lwCET`). +- **Lemmy Instance**: Provide the url of an Lemmy instance to follow all posts + of this instance (e.g. `https://lemmy.world`). +'''; + +/// The [AddSourceLemmy] widget is used to display the form to add a new Reddit +/// source. +class AddSourceLemmy extends StatefulWidget { + const AddSourceLemmy({ + super.key, + required this.column, + }); + + final FDColumn column; + + @override + State createState() => _AddSourceLemmyState(); +} + +class _AddSourceLemmyState extends State { + final _formKey = GlobalKey(); + final _lemmyController = TextEditingController(); + bool _isLoading = false; + String _error = ''; + + /// [_addSource] adds a new Reddit source. The user can provide a subreddit or + /// a user. It is also possible to provide the complete RSS feed url. + Future _addSource() async { + setState(() { + _isLoading = true; + _error = ''; + }); + + try { + AppRepository app = Provider.of(context, listen: false); + await app.addSource( + widget.column.id, + FDSourceType.lemmy, + FDSourceOptions( + lemmy: _lemmyController.text, + ), + ); + setState(() { + _isLoading = false; + _error = ''; + }); + if (mounted) { + Navigator.of(context).pop(); + } + } on ApiException catch (err) { + setState(() { + _isLoading = false; + _error = 'Failed to add source: ${err.message}'; + }); + } catch (err) { + setState(() { + _isLoading = false; + _error = 'Failed to add source: ${err.toString()}'; + }); + } + } + + @override + void dispose() { + _lemmyController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return AddSourceForm( + onTap: _addSource, + isLoading: _isLoading, + error: _error, + child: Form( + key: _formKey, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + MarkdownBody( + selectable: true, + data: _helpText, + onTapLink: (text, href, title) { + try { + if (href != null) { + openUrl(href); + } + } catch (_) {} + }, + ), + const SizedBox( + height: Constants.spacingMiddle, + ), + TextFormField( + controller: _lemmyController, + keyboardType: TextInputType.text, + autocorrect: false, + enableSuggestions: true, + maxLines: 1, + decoration: const InputDecoration( + border: OutlineInputBorder(), + labelText: 'Lemmy Url', + ), + onFieldSubmitted: (value) => _addSource(), + ), + ], + ), + ), + ); + } +} diff --git a/app/templates/iconfont/config.json b/app/templates/iconfont/config.json index 172fc51..f1b0a38 100644 --- a/app/templates/iconfont/config.json +++ b/app/templates/iconfont/config.json @@ -313,6 +313,20 @@ "search": [ "pinterest" ] + }, + { + "uid": "08d314902e3800cf1b17c4c1226f45d9", + "css": "lemmy", + "code": 59414, + "src": "custom_icons", + "selected": true, + "svg": { + "path": "M123.3 176C118.7 176 114.1 176.3 109.5 176.7 72.9 181 39.9 200.5 19.7 234.5-0.1 267.8-5 304.5 5.1 338.5 15.2 372.5 39.7 403.5 75.9 427.9 76.1 428.1 76.3 428.2 76.5 428.4 107.6 447.1 138.7 459.4 171.9 465.9 171 479.7 170.7 493.7 171.6 508.3 174.2 551.7 189.8 591.7 213.1 627L129.5 661.1C125.2 662.8 121.8 666.2 120 670.5 117.3 676.9 118.7 684.4 123.7 689.4 127 692.7 131.4 694.5 136 694.5 138.2 694.5 140.5 694.1 142.6 693.2L234.7 655.6C251.7 675.8 270.9 694.4 291.8 710.5 292.7 711.1 293.5 711.6 294.3 712.3L240.5 783.5C238.4 786.5 237.2 790 237.2 793.7 237.2 803.2 245.1 811 254.6 811 259.9 811 264.9 808.6 268.2 804.4L323 732C352.9 750.9 384.5 765 415.8 774.7 431.8 804.7 463.2 824.1 500 824.1 537.1 824.1 568.5 803.2 584.3 773.8 615.3 764 646.7 750 676.3 731L731.8 804.4C735.1 808.7 740.2 811.3 745.7 811.3 754.3 811.3 761.6 804.9 762.8 796.3 763.5 791.8 762.2 787.2 759.5 783.5L704.9 711.2C705.2 711 705.7 710.8 706 710.5 726.7 694.6 745.8 676.4 762.7 656.6L852.5 693.2C861.3 696.8 871.5 692.5 875.1 683.7 876 681.6 876.4 679.4 876.4 677.1 876.4 670.1 872.1 663.7 865.6 661.1L784.6 628.1C808.7 592.5 825 552.3 828.4 508.5 829.5 493.9 829.4 479.7 828.7 465.7 861.7 459.2 892.6 447 923.5 428.4 923.7 428.2 923.9 428 924.2 427.9 960.3 403.4 984.8 372.5 994.9 338.5 1005 304.5 1000.1 267.8 980.3 234.5 960.1 200.5 927.1 180.9 890.5 176.7 885.9 176.2 881.3 176 876.7 175.9 844 175.3 809.1 185.5 775.5 204.8 750.8 219.1 728.6 241 711.2 264.8 662.5 236.9 599 221.1 521 219.9 514 219.7 506.8 219.7 499.7 219.9 412.9 221.3 343.3 237.8 290.8 267.5 290.7 267.4 290.6 267.1 290.5 266.9 272.9 242.3 250 219.6 224.5 204.9 191 185.5 156 175.4 123.3 176L123.3 176ZM135.2 206.6C158.4 208.4 184 216.5 209.3 231.1 229.5 242.8 250 262.6 265.4 284 258.2 289.3 251.3 295 244.7 301 206.4 336.5 183.8 382.7 175.2 435.7 146.8 429.9 120.3 419.3 92.5 402.7 61.1 381.3 41.9 355.9 34.2 330 26.5 304 29.7 277 45.7 250 61.4 223.7 84.4 210.2 112.9 207 120.3 206.2 127.8 206 135.2 206.7L135.2 206.6ZM864.8 206.6C872.2 206 879.7 206.1 887.1 207 915.6 210.2 938.6 223.7 954.2 250 970.3 277 973.5 304 965.8 330 958.1 355.9 938.9 381.2 907.5 402.6 880 419.1 853.8 429.6 825.8 435.5 817.7 381.5 795.1 334.1 756.4 297.9 750.1 292.1 743.6 286.7 736.7 281.6 752 261.2 771.3 242.3 790.7 231.1 816 216.5 841.6 208.4 864.8 206.6L864.8 206.6ZM500.2 250.2C507 250 513.8 250 520.5 250.2 620.1 251.8 690.7 278.1 735.7 320.1 783.6 364.9 804.1 428.4 798.1 506.2 792.7 577.3 747.3 640.7 687.6 686.4 658.7 708.5 626.7 725.3 594.9 737.6 595 735.7 595.5 733.9 595.5 732 595.6 682.1 556.7 639.7 500 639.7 443.3 639.7 403.2 682 404.5 732.3 404.5 734.4 405.1 736.3 405.2 738.4 372.7 726.2 339.9 709.2 310.3 686.5 251 640.9 206.2 577.7 201.9 506.5 197.2 429.1 217.6 367.3 265.2 323.2 312.9 279.2 389.7 252 500.2 250.2ZM348.5 534.7C323.3 534.7 302.8 555.1 302.8 580.4 302.8 605.7 323.3 626.2 348.5 626.2 373.7 626.2 394.2 605.7 394.2 580.4 394.2 555.1 373.7 534.7 348.5 534.7ZM651.9 535.2C626.9 535.2 606.6 555.4 606.6 580.5 606.6 605.5 626.9 625.8 651.9 625.8 676.9 625.8 697.2 605.5 697.2 580.5 697.2 555.4 676.9 535.2 651.9 535.2ZM500 670.2C542.7 670.2 565.2 696.7 565.1 731.9 565.1 764.6 537.1 793.8 500 793.8 461.8 793.8 435.8 770.4 434.9 731.6 434 696.8 457.3 670.2 500 670.2Z", + "width": 1000 + }, + "search": [ + "lemmy" + ] } ] } \ No newline at end of file diff --git a/app/templates/iconfont/iconfont.afdesign b/app/templates/iconfont/iconfont.afdesign index ddfbd0681bca0fcf7f7f99bcef2b5d15f61a7586..6568a788649f7ae25f5503cb025186c8baed7e82 100644 GIT binary patch literal 50292 zcmXV21zZ%}*Ir=h?(S|7q*1!NyHmQ9(3S2kk&y8YM+Q_I1A*{@?I} zb!KPo+;i?Z=id7~=LkV+%Hu+?Al?D~daUZ+F6)tyhr>1Mf1gSJfBwHS2&BREnKSrr zCg4{S_|^0G3Dg2USykLUx!MK)gQ$^{L7P6tPEe{6N#J8c)}~C27HZICe%-RaTr=uK zp_}yg__cz}@5D`G8_xfwpIk2!`PWj)0kwVF?bgic1wIDxy+>qHCSKEA_Go%w$ShhM zr8-p|m3wv@ZL(}Pm$G|iTRSN(Y@kQzdi%vvEthttSnUBG8b;PKVIC#IDNkBMw8Z%G zBQK|WlEFw-4qlrww?;X%zne!btAamKU(O3 z&fHzDc4K=kO!Jq&+F~AEOsEexPrYnqX%YLo=UN|YjU@j(oy2&)1J{~Q!pGtdPpjdi z)xs-GU=X4uNf~L_5?Ui)+Nm2N!RfARO|&pGHnp-cH8vX-V7-u#aY3+mwMcR8vO-p3 zCXX@u3j!bINg4RMGgJD1qGiw3n!a^oR%NP`|-)ImGL~ z@E%B6mXz0oi60fJCTfL?qEOfP$2H@gV-I{RS3-ySbB|L~CWK7TY0_)=d{|WOy zLBBzRadr6``DH}h=%+FU$35|4CcMiHy@6%9n%8Fj=jmK_$KAROBbl|-jCWrDk)V`R z;P`*TahzOAPGh`H;pEc9jVx3xru|D`PubLcxmu zreX{7o%0W}ANP`(UonCGwzp7VFlAZ3^eUTc^4>t6fPn-(usBm1RVA2~=4+^T&d*=z zQE^HrMz3P`hST&JC~k{xMpZEkRTCL|3JFp?x81JZ*|VdUVi><$*P6`dB!)$m~@WW#_^?`N8}v;yN#PpeNxCh=F_A6RkfiBT;eU{gYhvC}_QXWQ*!v8kAy zZ=cxZL0l7Zp|kX;oJ6dS5eS%$SGNKOgh0C*m7GAS2nzx8*01Iyt8EKVvLHMzIqH7r z{H0K`m2Gtfsvwh0REy})d=$wBB}@30Fg{7l_4>tm*c2PSE%)vGJR2*|?ox#GjL!+F zhz`-KjFKyFPj{C=|LE6+|7CZWZTrVy|MP>9o{vpZ&}x?=m6|Diy9kCjAu|-Tjv@`NG~OVZSIV(F7i_ zQ`pL5W)Ib!LVx>q{?CR<%K%>>q0wBJFJJnp(AjP$IgfWu)kx`&@)k~fs}jJx#94lE zQ5AXg^4Mx*Mx^t z!alZ`nW{8@YqQ3-92qe;_uY7sNR^;@k-WHwOvJECy`vAZ*JZ@3t*CmA<>^17P1;wO zQ5`sY)P20G8%@P=*I4cRxk$+3XD?K)AzVvg*hhvqnLk}`WV<{G+kd4Zec*y2tBu+b zm1u|YpjTY)%TwPSM%TXbF1lBSDqFPep5}_7_EFs9a(@f4acl+8(;^y#cc@93fq}#D zkC|ege20g4$|IsI(Z=w~EE%G{PZYH&pGXxl_|vZJ{&^lsR+`~By;54J0)7!zPuggr zzpzRSg215jfN&P-dGprSUk+XN$Ch|HA;&GVq~hT-baz23wVmy*yFA+=PHa{h-Ost= zQoPW+qH*?fwdaGno08230;rwhw+el0vh8fMzI?e3zgsdl=ldsd$;{k2lPX#8@hNZl zok>>*F-kCRGtG4TyVN9SW@`Dh_4MT9UKbus<<(wdIHM!rTCT%t)^u^ax8ry8BjNl` z`0-o|p1PzfYrbd~SJD%U(NK~IZj`6-Ul;TFS~&pgi*mLdprI{YZu9IWRY|(-O7q$v zH79}gnvAH?v7WWgnoIC@j;E``rLpxI>1Zk@L4$Hp5 z$_+FW?~@1X8Xa5eC6*TcZfDw~SwrTQNI7-b#|zYRoxj#sF&wXY9$!4#m0aGHpA5U` zJEN^GFd7lkHhU5Lt7YmqjfwAb>yVD)z3^y|b!UXi$vJ%LI<(h@w()ONsW}6uQtUAU^fYN=DFn0FUNtq`pydx^5_?=&y+ATZ(eOmj9ZVxfoI(MIj1^DbZlN$c$?Og5olw)#r3 z;opR)`~m7Kx>Cd64(1&vRET37itetu*0#P_V^a%-1|9*pU;Qz!*(Vx;&gkb8d4&;j z$wcX2h?Q}RIOCw){&U|;JG|DrR%o+1G0(8~wgB}sS8Kh9Z!Rw9*ZR-}L}Yp|6kUAM z;(XWj4lk=QpW}>2Ms&tJKhk*|dR(84CJr5=B_>8`N=NaOz2&^wFrr&xz14OmabNGq z@nC58TA$jxDGtE?-0DdIJ5z6|3l0ONCcLnPQu1AI7_=VcoB(4mHRvPrSo0H})oRf9 z)GNEh(Qyn$+S8Yw;bS3?_C+U@_N(VF)HGIrp8i=+0tRV7@{qm&m@L*`Ya)?KK#QI? z_D9x9Pdd_mIgTO-WG@YQYF)N^nocSPrFM&PLN;&kJ(~#@D8F@h!D$+zvi~A|gxs?; zfEKbk2A@|40waSO-}o@Thmxu#k~KM9E~N6Nz`zGBNdMc-1>Z0n1V{t)z+cd!`k(+V z5Ni*Z&>#BL(pAvZ?weFoKuLP$URYgzECpUv@M;zHb87<;<4p?K!=b83A)rG&_@Y5+ z&gQwJ#ucU|9bT3$XV%#FNMv^a^cm3jm1T-xlq~P;3Y&k0tjznKw@Q@uIAtL(R%D4U~9q=m*3_uso(y?u0 zEkJL635Zc!J~zvCZYloATR&?8h`HYJRl&jyJY4AmKh!nLg+owKq4BBDzV>s77@Gu?QD@Un(7!(2*MH&|$I2u1#a2ZxAU$p2-rU8M%zB$~_*w#);Q zZr9NCTic+iLLt!&KhtIZoP9&xb$4g&$E=JwBnD^$ayO7h(vHf*d7mz zSqrGq!gYRsrErNJy0+8Ze+op=8+_4-2oFtO+$3#|>3@!LCAGkzj?R?9p`9=4zSHv< zJZgzrl>{1^;BWkr$Z_fuRajdRC6Dqh-gMY|rEyE<%osGd(zRx??gDlGb zkhJ`GqJ-c*&%*V1xU&-h=aj{JZ;@@V)^FaTuwRx?NwYNn)Ik2@& zbZ&>{%rNmGk$sj|zzlY~Vf5x18|HOHSKs{{Fc>d3j6^{1#h)%o90wwg`l7Hup#6&i zjToRy)A#qtS$p5s?dp^kvpeNAmrJ{$W@Wa;1sNW7{n+X;P;Jtov! z{Zw##UUGPZb&k5KpBRWI4TdK~e(Znx&Q7Yn{zV|KEcx(0xBfK#(7Q%l0~p3vR|g-f zA3%6@`6{jg7?S{u_bVVkhp*LE7oGU`Bt#Xid<+lM6 zsS3k>ND!?lr^=NPFy`GNJBbL=Y|YFRSwBC+u8&vAt>-xjjxlZ@rT9?Sx>kC@D>0(6 z-`NU%Q^B-UavBg(3+!I-Z>JR}=O!o!#QsA=ClE8$iud2}kf|C#!6PYqZDkB@RWcAO z^DlwD%g{V52tlbY-G5er)#t$w>#x|0L!uB7Uat3xfYYjr>(WBOw zDE!>h`*8hYPN~RqX~`gkTneaU!TTn6Edm9l)ca&UV1s2S;w4*(o3*TK2FvQj2R2N0 zi^h0XYHa&SI8Tfx`9CMkMjyyL?314IBmh)}0q3JU>x8`QCT%W(_W7C`7`&e?>O)eRkM;VW__P zjfBozq*^p(Qa&CF)_5UJ07nKSYPu`C*9j+Myp zYR2hD{Xs=9w-Zo%Hsx)}!tKx z&WD|E5o;o_WycAQ*qoPk=mX5glkK#Iw)(Ly3uMV5T#?mMVq;glICClj5I2wj2iVPX zb)&*gsQ(KOvTyxEAPziRGBw`#!sQxmC8qYx0v3ebI4^5+nS?B`k$>ycNg1s zLARZCUIVQ7<5D&#{G`tbjzqY;g3LV+N_PzE19R$EjHK;xu31w0mts8+07>y%{;jd&!V>oWJDZXc4=?PdD-+P>cM>)YlB1@{ zNg0B@_j4aw+!w!6iY3vkay<_-XFDEs$Iss9T@>ZOEM*?Y?{p)|L8CNq>%+mqcc*b& z$s1k7;Uw3d-w%|kei2(Wktth&_gZIG&jE$W2o;(%*3`fcp9^m2p@9V%Q@6J@*QE|O z+AkZgnwq3@(f$1oNqh7XTy#+aAIY09Z{YXESh5f6DF?3$g@>pT=JaRcXGTj$bI0vF zr()p8KM!0yFL<#$J^&_!k~lnWy+R><7D#O|{gq_(A4YDP6@`dq3LKf3c0DE_7_-G% z4DSeQ;^KPn#vA8UlK-sh`AgzpjNP3)Uf0N5M&z+Jx;pU@A&r0|Vj1Sc4Z6#hLT4#L z8+6nLXV3PrqGLrQuI&-(zg0AOG7)$^>7J#k~ zQ%rlX^zh9uvf#XHdW2$l&5X}IWb2I!Litrn+O zqRZ?18i)SMGXr7W2zH_jl z5aKCxh8l_KC&XS%hO`|*3V*_mdlBn8{)e%4Qy>!mnff=sy{$@-5$1tq^wpRs4D;mu zZ6svNmN?4RO1Wb#h}@~Zqp2(2Sb<*vfNDH;>xLE_TH;4oRz8;)x;J|sKNZ-ooz^D5 zs!*yyN_dS6;}huReEvqU7UBskl-J{K&mwShrDn!`O2NhCpYL%TnQ%nM1r;#A_%QvW zU!_a1XQDSqy|R>=04K&(cW^~~8?15pahC8ea{TFx&w)Om-*p2JLDD%-6M6R*m|`dy zJMo`o0(0l9c%(p=T`iJ&xJ6&m*oK}pDMZC8d0#z7@JW(REmH7FT96vj_9aEB8ZzJ_ z1fH;@>FA&_>S|seSeT;U`-mUu<2jsXr2K)MOhBq!wH8SeJ6pN2^cp>Jv4(VbxWXN{ zbda7lwl5qks`2I)8CQPwxy5WvPv;mpnyk*gFq*7gaqcj-YjEtK;$V2psd7;v-!9Qz zyYOz4K6$G4Qu$wtnZLz#IB=hE3&HJE3S81K*xl=vW(TriBqKNFufq9~tEW$9B(spS zD2yr7jzY*=w`>8VEjDs|1U`SahfElEAd6akM@{7ykMtQ(mUb0ATvk=2{z3K=nRR}4 zeS>_RR#~)|_u3Ofh3?-|5`k}$deoa0iT6=ioEa6yG1d4jC6A3 zW&S*l$r`f#!dwvz4%$r^Xv2HI}6; zeHQX#*LlbMrP(r7rzGUlB!YK_NX0_sB;5+cyDzC<5wC?mO0*)^+&bCrk;y5~H9u^b ziydaWs>b$a#?Fay|4S1#w-BNEq!-K{_|4xxk!Sp0fDli$cAe8#1Ia(OXbZK42FeAq zU6SsLheky+vIpOu-!eiUJsYq1OBil0a+dJh7R_&FQt9t|QL&q3mjA{bH5m0P5O8Ku z?NF=Sm1GR0kA#X?`N9EP>IoVOQ4pO)oy39y>Q;?4b0!L`fXH91G+f20IF%MXla@~A zhco6!qruEU^8$nlbF|hwvX?IOh>}EO3_aW1B86HsK65T1_ibcX?H1AZfNI~@0|`ev zt3xP}>Y@|pZ#H#kll`nvZy$e#P9)RQE1cigdd^UdFE4qLspvNgHo?7_YvQcw$rJLw z42GnnnMC2Sh&088r z6#AY!sK9XbDkCthlmdTKq&3q)oy;RQIrEvMr0lfb{=mWALI;;v&}WTu^k3#lZslNU zHK-(yMutp1$iwYXaWVL}#YvOZ* z+-&gLi0T;)KY8KU0Wnwnq~6J=t|S}2FWV1c(!h^>Me6AH<<;=Gu_fr;=jL>4(EMW3f--+ z;pCE2RwUsGM?4t}Z&PBez<)3IJP?oDP95u(AA(0^yMhG|PDo!Fq~nj!E4GY*>Z?KR z&v%R!E|j4rb!iA2;Yc(HT6XuPf~Z161cPeQ`Mows1(V@`>WVU8U1cPieP7sF|8~hqrq?|Ds z27=4;b{K{s`!`vZM8sBs#7j&p%?3rf{Nw<`~E-)fXs6QDISeaQO+UQvyE> z&|A=DI^+2*Od#2EN5q)P-6hiocCa+NP+@q40!<)95Ofm-Is`#D*7bp0p2a(?CgLIe z&m`#R#6&`J@AV)HbS>&NY#F6}vB&6x#{CWv%%ceCa zDpPkp(8j!D;ELYYq=lua{Uuh7pfchAQlhYkj&>>2iN!CTo=g;05~J6}hF+>M;X@P= zTb7RXZLWdvDX_%;a~?LCiUUw%atmgPfKQ0p2A{Ia=>it+8;t*Qx!GIHA3sd0hzt^FV~gOu^QYQs;atA z(PMgr#(hwnMCbMiQO5V5eFI}u#KH5+Iw0=RR{uDLgLllHk;C!<8=7CXBntMkxZ1^m zeb{Q*!5PLV{c)`Kk~m`d?*@PJ?S+HVl#z!qJIU4Kz3DRw)ir=MjKHxtQAU$Zr4SxG zqrhy|ds&*I?x8O`PraRTyTPC7hW(N$zGNlynPIzud>rDra7=j2C3DnFnaGI31vfMG9%j?RS^&reh5W4Wdu~1$zjYL=>|yeI_Azg%G8U-vxX}4go{iBQ=o6 z^2yJ+2glTK{0@J3lnmGfskEg>0nYUGZlIGVAo{a)91cxViZK>#M>EQo$19}_^d9|b9Lv6ct$|= zX!aHRIM~g#!v=BgMLAlzyI0rY7(zBe@^vj5L?3Eqj~I$kQPgOXa19oi$bP3@ z-6v`!sHoAh)9~s}Cg$Z3A>bW2{zG%_s`(U|?d;7cUy~7infCE9JGkETcw}-It}Kv< zO;by`344W^SONv{W~T7=r?d3G(_@?)kC#n3^+JYjTRHlpAPqGOxEyn)9MG>H2U##+ zm~V94{$pm7v!!-Gbs9@eg(C=J=YTNSa#BxXAon{WgW#VqHh;1o+9Z}R#-%0KPzGLK zvnBrsF{>}m7(T+~U9}R9H&NSM!z8f?yWs3}mE08&%{tTZ(4H87Qkn1(!(4}!LzVcU z(hy}5{LJ$h&e$L=9-d$Zln^CmG$YstBb>|dUj8}x$L!7F>`)Sf%N`B&mOZ4Iz{FjI z%4);rF3v3IA>RN7&ug!+w7 zFyC5%-7hsXy1oeC@lM>7CsM4Y59gFp#%84_HZLodKD0Nl=pKL;u|yH2e#>FLdsVsT zJzEGJeG)MXEPQ?gX50i!$`lgM6Ke2ge&7jjOY}GXrqI75T9VIVYITb!|4oSOdS64Q zxYfe9K$i_d5n-42I7!kdrWR=?4%w9ixO~~+fElN2>Vyw0YG9c8mD=Tyy zAr)=Cm21q}-)N?HT5~lRuHt~<&TzhZ>(xG(Kr=)R2{OQ>m(Ck-lbrFXe*|PUBx*^y z18Puu?0ud_tAfp~QTI34jYGyA+kU5F_a><$hM}I+KnhBUDZoZ@6|-p=#!WUCua#ue z6Mp(i9+LhV3cAa%a3Q+CKWiN;-sGausYh%~W+@2HyPKov4Gs7y zg3kXodBEoH#lx!M4u5$Y0F=_pP4ahG-j8FFcqS}Rx3)1&gp2?&H#>gfQBchO9;%@# zj)3|g!aHIhk;BE+CAeEC))82Xp}{)kGRdN8jIRCdaWM;cIb_Z^`0+|mD*aU_KgW=3 zf0_9*H|0Yi^LK9T_9B$NOzPdPSTL~8MU)Wjq%K9T(gPEE`bN5Jr(u|!UtC-`Wqt<; z7*6bULPXNV)R+_$qU6CfO>gN=CpH+wAsF(*ZGTZtSR$3ui2z7UF7#I^__o?B%VO+BEUqKwWp~=#9NWwKylfibIo?ALX!lU+u zJ=U=AdSJPyr)uprzT1A4QuhG*G<`0PacH<)NrFk$Fb=VJ=T?s11Wsp9YtNdau?b~M zeck7p7-RA;J%8(Z91?6*bNBv+S)h-I%>ID;i)i@96Vce0v0Bg(z4hQ0!=n%PMT2&6 zm~XiRaxc^6cvehFh9lp#gS6cDm)p51WnaQYHoRpht50*0Os7D;r^AVP4Uu_!~)GY>Dj!aM8TgzrZ#W z1GpvuB0_9#j;YX^sf#^8liWPl0HEvapGpg%Kz@^4Fh_E$#?(gon1j6HN9zv!RXXTu z1@MkvE)(bOAm<;5!rx|m3y!RDf1&595LGf^D4_8LPY3vucQVE!}ijNAZAu)QU|nGe7$l3wD2Ao1zD5e9OR0k7f!_M$Ta(P439 zm$Kpp;4%y^awal**lJBVz9|YGA%z3U)Kj=HfP1wNV;%s>CB3>p4gfcJbmBGuTw_vS z84duQQ6Y(Vo&?gQz=LPTyya*ZuOq^8X{o~-~l)56iGazM#0Fva)( z7!~2>?mI7vGLfruhFk#b^gf%kF6qO6J5IYjO|+GjDa8}Wr^mH<((K5z(yNIIztbrI zN`Lm4ffxTnWOgL@B3a`AOn`(nsjt>$&(8H$_gL=;>Ja_%7RX4riAd!*FVorl&c9ib zWD{r~3(z2z)upD>|6b#JjhA5q=*fRd3ra>cjZukV_pkA_#VJ9kG-V;cYkd!VKm1%2 zgiIHLtjw;~I=nPj`5Bau?@QNN7YR%|Sqi^b41rwC%F+HNoe`ibYw-dl@MHKpeu2^* zFjNPDgro+N;NVP05i$@y68rb`=9_Q~IC$UpohbqCXGQhnbq(%tD_{Mxk53RA;3uzs z7i3DcfRg?9yzK<&v1avm3od2=fo}LQ&pfr?({x|)bxuvQIU#)qaGqBS9tprm#LUVn zUxF_2_2n)^}J z2e=zwx*A_1&)CU$%X&NI!hH5O0Nf6Kn&mNc5bgR48Nl0Uqz(9(!cpg^4w)9oM%IMR z4(R(?L8Wv|GXH)npI3u0S#p*wwgG{0CM(8ZS zymvE*Y|Ft;LICcKchw$nh6W1Qi5HMGa9`o21`uoQsRiGF;9#mlIeNG&etnGe6DNBN z@TVqC&hfo~wk5rvVF3228+rnep^aIa#zf$m)aU4v9&a*46PR?6vuJJ)DCJ}Edg8mb z-0RtqA0SLwctv%y;&+A)aOR`Ojfnk#VV^z_ANJ!%NQa(2X#lfEW)Ob@{vvOZfgyT> zhB%eZOk00Hf$U#hgE83+0k)Bl<^BAfRTf~s5*r#28?Jf{7jiI9CFtNXtakLbounIZ zMmgmt64mxnnKR^-ANrjgz}(^hU-6wQ9vUV_C;6?IuXuij#7`$rmgJ zhUq{|bBU8!L~Xs5upFbueH?%C1YjEP$BtH#3hFCT(nubQf?@1e6?Hp1(1{`M%^Gz; z%`x?q2sq`iqALOSCtJeKI0TqfB zeT1vV(K~z#4Qyct8~J5rbTbCX|0)(+QFWY9fWbhT5a+EQY1rmX%Hs2v-p@T{ZL$xE z_dr${-wU|#~0S`<{9Sz>fOxt+&BMm8Lo16-@8I9FmRz?s>We z!k=Jg=~qVte@?uAU{kDs!NVz#gkx?LFna$$$VHCmPUC|N{d#i7<~L-&&n*}LJ7kr1 z;(&|aQ|JFoh8)nnV0_4w5&DOuzAPY2oV`WP0-@R)xX}v}KS+N)XcsZF*0P|&fMix^Iq=kV#O4xUmN#DYz~2{9@G2I-gVsBQ4#cn3 zP6XkdKkh-2R}=_4wohs<@ z3C=nR(KIb3XdzpE^aYgEop|5A7X+r>DNK2SbMlj;qX6$yb@+eIAqyc3t}LL`EBF4L zQ9#m6eXYMfF^x9u?duKWMj2tA5Lc(mABPfvz}F z@-w8~2JGmARC`L&iR5ZZdnO)ye;0_Cw0Q>=U49_}A4G<|1eDXp=E@a=fob|>=B9UG zh__SQ#y3iD2R&~=Kx(vt)S!T83=xMFGKUkOY$4v_QcB3Qt99)!(X<(2olo3lOELld znXSEz)KB||6fXii%xU8gn9Hp>S+avm+}2B@QW9?pN$=ke;tCKa;a@WNmj1%x=l0*9 zj7{`Nm895B^caGhQu@U|=A&s(Ha3^vZm#n%8>yS3@h7g2H8USCx#0Re%t;g>VPAEV zOEYOq-q73RV*KP;F+S@N4n|Nw;P~D5zDalnhq`4p3&KX=A=JqTIrk4QF&{WfYlpbHm7qZ8 zbp#p*hTyrwQ(|zexZEX~Ud3esDfkA9Ur+$aD%JfrUX22hp;*6?Pl%38!O$`Ru(|U_3$P&#$6h-nixw5jPIcR; z(7eg;O%n;n=Oeu#@7D8O)v`z*JKgnmI^Zv&lKu=z`k+KjZ8q$4k!NR|W;9mndbkSHUR=*JI({s$bkLQAX^s z_%L9d+Ttq^>!SeJcw@;kJ@R3+e)w4Q_flfi?|vI#`ea9z|I)uX&+klj!)EpN111id zZ+M^VJ6H&lh1rOpdb@MXvGwnXQbnkv;D4GPGjbWE$lyfevZAV{Xq-2EJ@oV5=H#ig+}ma8RIg+THTaw!tQ@wYrt zYl-=J#0@2x{xj+sEyPO))6DRclUJEgc#l4)Nb0P9+O_p1bnu;*xX?oVnvNLZ^;-OXjuQ z+?~+$KKsFR$>o7GkFtogu$~IQO7q#~vNGroZtsU1tEytt)(NHwrUl}x38XiioV<0| z)qEd?M|oR9;xp^GU*3K%|C)HZTDqQV6k+cW!#~~~(m>yNnFa-lM9khGOnwcb8&BZ& z=Y%^X$7>GB^BNk-eX@)D9>9zIXYhr1P~Mmh)^F~tCO;X~ahXO+%V@&11rQzVG(cRi zxVxc{v&;ru(x0%qTH5E4)xcQ?yHB4)v)xy3-phr+i(vl^nZO4JUy=z_Qdhv16a5{n z->Gd~rxxvWe*Xmzm6XPp`pD%SNx~ntQYjThO`tI48S%e&a2LhnA*XB76@G>eiPzef zd_~`Fie9E4_C}tmM33Z=w;rqzSHtm?A^gyu0iTZjQe2)q=9j1KErisNo=4MX?d82s zEVO1Unx-kpG#}9-Owg8g{^ejllN@01vKd&SKj{3%2+N#7_QMI--%#95#9G{j6J8f? zx@gV_sXJVuV)Rc}ahVgn+3QxtU>}zBFZq6Iz)nRqk$<`I%yjsyjpU`tnjH!r&EL3O z_)SA(b58X{?eOX8w~elWtB03RCcK4 z+viJ*l%YSNjq(wjQZi0VrAoL})k`9eT)cHszgCT>RDtC*<0`u35g__JdG4Qw* zAJHF~I7DJ?gWE4ip2ZnAqc0gMF|8$#?B8y0}8XjG^UlxYIVRD8o;O8ZitZTzCcxtA4JG~ZX&(9{$=d$ zR@WdZY}|a3XV@^RXNr}G1VCK?iZFi>CEDo z5=V2!PjodjCaAW}2=MT^a-=o9f}|djYIJ&6nVaxG?+-&Ey_~GtS8*8-L~4PEf0f4! zWS0I-HP;;N@BJ6+)%gk-FNS{qNM+}A#Q=f(6v%U$rQj3Ub`cjnR+iw?=Yp7KlpH7T z5Z)h;D7GW3ZrrH09P#pr&TpP*31QX6gu4=%#4BE*PM%Si>cz#`_j_0tbD8yjo$W$3|*sYer8(7b#{SlBpffsd6Wb2hm8c z_Has=^`ENI4fjoIXf9d??s{EKo(k5 z1p2?nbNcvU@!B~`>`WP4!I3(;=q2See~6?{4~d2C->`M%Vti$a;H3$l zJUc98toAz`gS5gAX~>A83SInvN1f z-<8y9O?}y@MQn55RpRO4<;}Q4T;J6cOWXb_>dP0^gAg}Z?85J&^p8Y*;mY_63ol~6 z6?!#JL~ZH`)9$(jB?pP3lG?b0MmW|`Vtcm{r)La5_2z;GV@Z@uR8>Z(YR#1o^7NOQ zee!+l9TIfJ9lNmt=nMTKjaCDLh=vj>J7>Mb z)ObZuToyiN_~z$wBA1j*rTdcWN9!;PVw|6Gb~67hAFb$6aMG#V21-es@~Mop4XSia z9v};8L-vuGMagvu)10P4zTbwPfTn+D^hg^+TO%6HxG>>G{{*@wJ>!e)F9lHbbj>14 z4zH{arSdSkub;uf4rGX<;l}!9hiO+HxNTN? zVP+sxekmJ74$)oN#8Uv!6@qFbJHy_dTc=SZII!hGsrVV zx5>Gr`sob6+C@Y}9s`hq*0Ha)jXjR8Zjm_jpwVqYDQ^!85^)no95;7rl$9wSx&2P^ zqw;7E7J2^Bfy5N1GBQL5jcV{%bBpw!17^uB$Y}9vN&cxL! zI118ch>l0-7X_ih9^6Hk8&x=nU~dnDRT`2oW{cy9$0Fz?zbU-9iwW8$;_c%$jVZoK z%`h7A<3}iO;u61#(LFJn;M`L1>-ZQXy%COB3D^N!>u6JC$dXGzJ!gc7mMWomjo&rij3%l< zUpTb|9-(yBqCP$6jlUYgB2RkFM^DTeWx>>oSh*@uL=O+)3p7f@gIahNZydRK_x8&* zNwKoc&6}Vvwx48fhT4H*#FUpmf|~KxLlQPaRc+D-N(aUR4&ItWqb8U1VDKXM>|_)5 zLuO$U?b#gKk2QL^ zGl)M$wBl?oQ(b76b zRp0D#4FsaB;3N9hd$LSLSzZ*v5zUuQF+g2d-v|4#C}!r0X5wv|$>hx!8hG93GLL@A z3dKbJO71=A%YuvTC1L0N5Gk1_!GZYhzX%-3Ad#~R3w@swO%n9YE__q}5x3z>SWT~K zP5? zGYLHz|C+yIV9rVgY+jc6sm)qSA@Q#ZH$#muv#GcF>S}{PRj~jREsd#__8>$PX8DzA z&f#iT$M7KXc@s@9u(yz=5WzA|%b)Tzc$~X;*wv^|NA_l+HNR(gS{Eg61cxov-qz3% zT|&t*Qkm%xTe4muQk7AB6PwcBobSUGkzV)_Y6I=v^f;$BO65W01)tFWV!5ntCr%e> zl~VrZOA?8BBJ^ZS&EYk2$t@=A{<~s5S;c|>+}tyMs#4-nj!(Z)HBpQa4W}pH9a8&& z=5tw~i=!5(pf>x5jlXWJQHZFY*k@P-+ZZRywX7y z`j;R0J(+ zSM~bPR&IAKFleTNdNIc#tZn2!^e`SZpxDO{pNIL>K`=6{Ub?wqjPUhK#;2}- zQ_Dxyn6*?S|3#m!qy{i|c+rqS6ke@Ylm`#Oo}WRu)gw)CW$(GlN2dag-baMRBZXykcaJCeCCjqMrKypp?=j(5EUFw7TuBme(vSWu5?{`wx4E8nhJd zqH5EDA|ZDDmmc&K17#TQlHN!3;B3j!UrD9sYnHVeJ_C20zfpiP-qN>6q9!2fXHFc( zBS`<{rd~-;Iew0$Opjb~bhtC)cLV0|Lo`u^35UqSCMnKx@AzRb5TTh!tv`%pRy2{8J3$k&7yV=z~O&80Gq9-v9U)F$=Gey|2j zchhf;oXmkb%~m1T45-;iFg7z)XsBy&Os{{Y_GN(th8_oV8hhESl3x0{Fa;CXKYOh! zAd%}0hwbL>i(wQC>+_-3Adq@8P+lFC{=e!RsR!)dewa0ReV$TGHj{hJ9pK*XpA)KB z%QgT=>)5qgPqz_wCo2zTuZ+wHfRydg!I=l)j*CDs%9}r^SZ|ZbXx>wDTi zKTl)$9&&S$2}YNEp?M+J!!r(y?yuABxlJu=l1ZS zuBVA7;{#X^=2>S`=0f%ir>mJK)CZ*Jb}6NNbZLHt^8O9s%@5{PIDq6#c0B>^d}Jx< zsQOT1c;(hrUbLU8)c75&RQx!dQx0IgygwhWs#<;rz}kBPu+B)D9}j>uHCLz1y{$pK zcJKDG>k!|9qn;WB9W4`>&(vv2K2;szg2PpSp8v>S8V}nB2UJYKe|wSuUb?9h;AiLo zg5J{{-{AuQoGeDjNfs73@dOHhy6dTqC(;oqzoNup_W7nSB`ZR#fByTHsiRa_+(ZQw zcWoFQtuNxGl7f|4ItiM@n9IPptzxh^Ib~!s66S;Nv9l9jzO@Gp^6OJ#?$H_zZlhih zFBjV=z;TYHmZ&A#Qq#jt01M`D<-45#dd0v2xO?>YvT7ec4H(KSL6;i52Q>O^fDspM z3BUsO_3kQ=f3PyJG&6Y%3K}*UqZFjx!zI3q_E3$*ka;V#$k1U@>l-Xq6`*SD8yE~> z+hJ3BKjH7(qF5@VSu<)vo?tq{W1mZ5LN3gEYwV2Y|H_)YGgTu0?2+ifwsu;D!cICq zMt7n-oWgQhneMr9iPa1)=^mKKaLES`faS4xEx-&OHwYE3PcPCh-A&ZgU`3h5O@qSDvx*AusnE@Pex} z14uiy{QL0q2l4*+CK9>yk;h~m)ZqPp{~@in4(XRp%{iAnGMQr<)K~=Y?;bwd)5+CG zDw%Z}>jfN5gp<^qQh@*YVw9zYXJXXBm>#Gk$T2ZZU;Z|9833CbK7+~-yTM5bRoST0^; ze2cXM7tmAljyNRp2KgShptxHQwr)f+Zm0*C5kJg&?JMX#1{hL|0sel!a&#&T7pYxc zG5@?n!{?!qv&>)FP}}M)hniKqCC76hf8UjCWo~P3Y-v5(#IxgvTd(2vX{b)Bb+D=4 zZZ-Wx-4&-|@TBr-cuGlYiC)w^9WNE{nXgU;qNMT=Mx+(29fJwua`hRC0?szujCF-k-jg8X|`82aO->@eJ~ z1f%Zu(Roz{_TWQLU+7KdL{Kb#sPZ4O+#O2vfZ3*$0#!QhUyXQg^}^HP(0@j8oZa|z zLLsO1#6Ccok%R94vG)${aeeLkc5FAcZQHip*lLW%wr$%D8oRNLrm>sG4Vq;CCZFf~ z{ul2)X6Bw*YwvxmS+lwB^STC1WWw>KW;&^YjSpeZcm)pAP%I|p+eu()=n}HCMndb-dds8b+;oTkbvk1((Dj$yq8$6noc8D+*WLu|``T46U>J7Rt(0 zueKeGw1WJ@?qg^HA_z1%X&Z;v7lZ6G$Af$KQ(b?#0Zk5aMHy$FthZ<&bBC%S4LdAvrLSoP&f<@EWpo5CzA9-(W4EexVi?FX3p8-IpG?UpDMSrwN;i%_jmKQRwX z&;DvhhRvUUKjPSj7#poqb?e@qvI4D!XT@*$dcpEDxe zB+rs18TyJMZW@e8jA3_=NbO*HdJR8#MT!mn0Rb(rgqVWlcEOPAENDSDmhouH0kB6U zMtQ5Ewz!HQbeC;1bZ5{Q&xTFNz7{r$AB8Eu;9txpoNXvnN#9E>#nE4|nAZsKj!I>8 zK2IXf;_1+&=C~bAGmv(TXedX>u6XP`EbSx#gMe&RG_lkQwg?OY8v*QjTO7VH2|?Us zsc!u?tXP8}pb>5e>O%m?l-8nYIsk(-w=F4+Zh*`0N7VBzYBG`(_4eOLCYLy`oz9D$ z+y{omTEY&3OvBq7^bbItL`s3pUz3aqQZzx04<$^Bx0msH!1gN`CSzpd4kpNl7Kg@- zrkpSbe?a%(168H0VczV{VC*FD0kCeZP{O2#vH=|VNo3eDYoi!edPBu?#2_*oM74rP zmRn`_pa;PxWuH)+a#_b6*x8Yl3aYqEpC<2si!6Fm!X!E*&+Y;gTP+d@ zZDe+GwB=Lc@O09TYJyBT0(BmH`AYR4ETDWf{$C6AWTTN->QJE2kG|NL*-8fn`Q1W- zt718J@lXRHQpl0D{5EkeYT_HvfmBFUYB@OYO7h)9V}Ied2=%b_7=O!dqNg&=3NCgm zKQ4+NWF)wAo*R2|#Ms{QDB6|HYvSNFV4UctOr64}A4YuR%fC;?2%dY*e!pu>pS;u&ieCILQhV3vy{YleTAR4wHlUIiX9x`+g3;TN@6 zjOevH1n@bSQZf0lND_Q=#=s8vl&t%jz>i@k3d2F#cpZo&%kU~fVQON5)rV7JJOOHl zaZu6AA|{wRNr@m*l7Ofs3Nt5d+xh?mjSv}`4k1}SsF{%J(C>h?D7UF7LQ*mvE5?sx z8df9zT(xTRR+^>XK%&wSW?b`G9zJ0H$tFdf5V|N>G6LP2m6fRl?iH|hZJLe>B!mF^ zvk4hF-p5F<0g_=1WeCx9&i65r6v16UL_LxMJK&I!aaZB8@HBfApA(Jdcf}*5arMU;cY!SQ0GawAp#SRBLOxlO)*x-JX8t&> zqzn^-s@S>JjX(1mK5Do>geb45^UHuIpbFg`7&E<{;5)t-*!2SUMo+x#c z`rR1fy)a&>@*eSBMAlmxqOVCVAEdjPufpZxeWxJ0%u}wh%3GZ9+m{-A|3XS%u2e(k zA-@uOuFJ?5Z^l;YPB$VuZknZr7GPdZm+vjlo3lbJJ6hou6Ntpki4TaNy#r;XsdQ44 zRtcVS)${A_$~T3Ha^`n{%mBcKo2z`5`MLut1P)5_o1X!46Z0iLWMMk%N}30fLapMN z>Y}CA{MbpR@&#%_OfEpgf>%Mg7C?mqROFRwXIY--tS4-50bsY~uoYhrMnSn0C=84E z5j+UIk{nKlp@JB#; zFHDIaYy4({zXD`p4Nq3hA}kcBkNvPIxB-&YEHJ0p7QH3qi3BnoHP1zyN~cbj0|~>W zGi3pi&zo%^(cZGMO3b|o%VnO2tc&+jwfcLrOWejgKsV4=3%AT`X6n%)0L(vI1}Q4nYKq?Pf>wx!M1~6IE!=S+2K$r^$^XoI;tn&n8zu9)gAzcJ zx6{}Hjt%;420`M$v;StF77-4mAO-?a-UB7$*vpNx)Tr*N^QZxuWV(wS&F3*|=N|{a z)F8lvng6jB9B_0T+yjs|ct4w&qf#x#S*s6NEn4Z0!fmSE>EA@u=p4!40$tApC5B`` z#Va9~BQ$RD$Y&zN{DtUc@?L~9K%Wz{J*#e^6W z;HW(aEPd3fBY)&q%RLYa3*=xSd%Kyk_EhJ9_dbGjhjuW8IEk`U%mqZrLxos_5mz_3 zuZ3dV5-7exI1Q7g&`BdsXu?tvY=lX({5UEI8B-=ALcZ(Lx zdIbgBN5JvAkdwc15Ku{>yQm^I563}jwi3WfP+N%^K5%{k9IgTLriHv*^0y24le9?@ zZt2*0U=0ia83J+H%l}AvH)pk%pR0IBW_`DAwVjfBcqN(E3x6LoGc%b5j6(r)R%@*n zXp&H>)N#PuAz>0qB0?t^|;<}1MY1gPQVp`K+TP1w3S#b%O&oY}NRxbrw& z!WK|aXTgxklJHC@T-Pa{02#~A>F2;q!d&(BT$0-?-!OXQt1)~7zas>nG<~5bZnfVg zJYcVyYd%RPeDjot5LoJ3 zgLF)?<-CXtke~rZ7G))_X~9?kNi^41HAe2{#&sYJzrU>P?p0z+zlau)+=KQ}vxtcM zXQvS6{T*p{V26Y@FtFgAC77>PmEO+~hNvQVLWDUKB@#%40XlyF&Uytb++Ltk0}Z)} zlmQY*KWf0(iqyIZ@71^(X*TkHsy|Lk={OJ>5FzJ_pLIN|LX{Q}f1|$wBo`HnEI{ChT6(~Q2sd$}B@hS>3ZoS4PqLVhh<#5$Asn`4!k}~s zF75(^10{LlXc4Z1B=KCr=q^CN;qA!@><1SaK18=8h!x1oSop)#CDqpouU?YKNNo*=uKYtSBC(0a4*l3^6A?aO5b)IRO zAFf&sg1uSQ&hyAZej}O6a+=U>;Y-?lI2TfRN1HtCFJYI1s1G6|kW0dcVZv=m%P7Qu zX*qsxt!5DYF*I^QHS(cq`&6j&;kEJjfDhtUFS?9^KW@BN5kH)IroKK5nn!|e$9~*? zJpfhm-;n7E^L&#C7?jr8Jcv`PE8t72^)Q|H&-8%JvbaNRSNYKp5y#-u_#E+J8e8_vz z?T_X9@1GK>a_0{MxVJb<4*0JC!9~gvi`PqH>ab_Lyi;_gyShAe zu0&0Rp&RqFu>|{ugF4^fQ(@|eXT06SP9cDsGE$AVlH4x>_4?*>LqaE)7oo<-_ck|S z>MQ-gLhr7G5Gs~zrOx|1yOm6;Tput;(-1zW>WdS~nFjDvJQwIdCr+ukBI9=esVfb% zJD~WoSL->ir^+D*$mh#{|M?u3>NFuDTu`6=CW7rJSegT!xOAU13aCgZmz%r;V>a9F z=fFgohf)oYh4cqk>IFFDjEg4w&?+mw16Z#l1gSGenG9+P6MXg&z?Y$7T{cf{oy>bc zPLP*GQ+x4P^DJzYt5RFFD#dBTf<1R;6#->#)E#A7p5LGQ;yS}qy4Hq+c{8lVU{=KAL?<1;MA>5X%dL(|JJo!oM)!`6D}rjOudhnAB%U5bzBBxlmB2{!oMNjfz(EqaC^jUC5WX$4{& z!Uzp~OT>7>SJli_^9$)Ql7MJLD83q7t1f!9KML& zXe(=Bo*S>5uv)e=S8mV?OZXgbSuM0+GRr4aOlLmyDgMOJ@YAgAW|;wfv1TKlh_tCA zl5H92yvRHj2Yi7hh&3PGU8>v=h*qIiMIb1L%uB+W9YqVP(V@70T}1+3G-Zb}I`11KW{1 z{)n-Mxdz><7EVOkSKa0)q+?<$p?9DbY2!fTonAs12t;@<$q);D9y4Ax+XfT{ftzM0 z`nQz89&Lw%cM$|5hIW_1*Ml;*=vM&Nd9hOxM#Y^tUyRo}72dKAgU<=ozuVk`gcoAW9+z)AfcE;0(=)^EdI}E(;u&aWC45cEqYo7w z%39vdY>5pQGAIM^MvsfkHP+YNQOX@i-xO$8#a5EuNr*~4ma0M5Z0Wj>fXaW}FtV=5 zAO8-lx!L|DNz9h31Y8ys`QHL*))ncLU|cZpg;MQUj8f)l(a#kwIv##lPLmrsHfxD7 z|3#>^i?zR~IaffO@_t2t0W355L4$~n@5SQ(QC_TQNL4gJUm=ux|NZB3m|y2+0&*DE z{KM%gwdE|3u*Uo$yNZ-JKIb|k&P80J#)ZKC7Hve3YvLpq_DOgvHMlATey=5A0RA{b zlDB+b08C`p1OdvXL+QKJv&kg1G$@4wnF|{U;zC_9heRT{Q^7yZ(Zq)^FP)V3H==sb zPumq06pRk>sRfgI9EV4t*kjJ}RUk0VWlakq=|fU;!nuR@jSSYisVo*|=5a7W0REaa z6m@`r*9*7E7n>lIouUbYe%W8kz3H@8J!r?$q>0hH0c^k1%^7}Xc9&`LiV$1(##SJ8 z(LWs9S*;?R`IXyz<1~)Q!Goj-OFasLQj1*el;XuF zeQtLk$0OUuYNrx03Q0og@`|qLKh?)=Rpv*c@dpWinq82XV_b^qVe0&5RNgaCVX3;=>xYz2QOqdKB9=DSD!C8NA z3kgEv+5a_6M1scur$i;Z1cyOc6TDLakjGGC-fM((wc-AKnncT;F4|;i4J)_7Tp}?M zNDI`{E<5NpxoEpD3dHcl2)Ag@m*$-AEuE6o26GL7k`pA(BX-c8`9=U#g|~qOz+oE zKk__S%3C;_FGfvE`xhFSCq~y?QupQmCEo}O`iSdEqA7E6a%mj$rArrVeq%Ycek8EA z6#5yO?|J_-0{VI;&tR$T-K2&O5-52PG<5XP>lqb)h){alQJJW~JQcix9ONYjw?HYv zEn=^&sNuZiPv^{3V)7s%SBC#2tRUH-3=%6uI0|4N710|sKvE)16uuZFA2Ra<0TCGW zf;otR(H6zH)?B4EUBe#GY^bF_My9Q`mV{e}Z{_HM_q{K{Z)VNU-@(zI!~pye%&pLm zzxO1J&0`Q79F#;yia|`3HU)th^~#Q)%>))ffZXc^xECcS-QKh6rxs><#k=mWgGFc} z>jQ&V^eO0p_qe-vKNrQ9K^Qk@^28N=B0WA8XUFw+!>wr%c&VuM*k>WPpV~|xl=Y{> z?`>h9qg5&TtG~u^s*0f| zRD=wi$RQvp4t}8r5h?TcXZCi)7<8J!-p-6G%LkYr96fgW3Tb9|-2LE}UR39pkq+6` zU!S3z(3Zh{`|L@-jF7Uut}5I`GIxwBUHF5gT8ER`Bs{2pQ0ha=U+Xi)Kg_R2EpX_6 z;_ikW@NgwYGQ%w66;*#lOWQWJ-R-E>`>?25u(8Ab@AlVMe;GcG`41gAqg@w-7zpGL zx6^{^JGB)A!$8-==kUtAx$E9s^RVm)GE}Md|HO)?AGV`KOefnZ0VktUn~$It(l(^f?~=NR?CSVg0Cf*`u?Y3^C!x_aK{uLOiM>O6vtqrJhF zzDMW*Z?QRaE5sl0TQ1`}uAPNdMBSO%i1$nIcfEXGkQH_i%6bVV{}5{OKvh}v)npSd zCF%Gb7W*jaaGW@1GI%Jq32752uF9~Ws=YlX7(5cD4TP;|tvO#*11%&N7}S3caIkSS zs46%sFm_Rto$IxB?54mSO2x&;j81Wf(WmIf!AbbQLikhVAKIDKa_X5ibre^u? zc!zG@s~3joLj>X3CNNGUvzAeKuea1(OL-zJ5yS}fENcQQ(b@O<7?HhV24qhtc@Cx> zPv!6>sjd*!*LvYZ0dTUdkBnP_q424PmYEJ+EF7wy zMO&Ma-ND=~m{ZqV$#Jy8hH>teco55%5PIkQwTCj6h4imw&dt28PZJ{XeJUoT=AWTq=*oDNHss8f;dTxFtYZ3beHA8&$L5A zOHy7qRdZ8_L$^)Hz>_V*%jKhChGkiyZ4kYnlD;Pr1dNYrtsaq*XQr`&S3bIv>jn75 z`j(DD{l@RW%DUKEA(tHJdRSGQivR@ zF>C7QWTfRv(2hb`mDRIx!)9P!X?KJxegvcy?;Qo#&Y#~excqc5V1BoidGEKm(3Yc# z`bZmKU;8|qy?QyXW^b`WzO9b>znV_|VI@0GL4oD(5QnP}!bDM$@q;t5(#h&wS8h>) zabBhv9lI1OTCdE+*m|nJKae>~*r63tWc%YSSLuXz+nC|ppvlOBTv{}dA|a70WH&9R z1<^tMHCg*tvzx(BZgCQNwV9TNOaHZ2409!BW794ENt~|;<6M^P&oDYmUJ7am?feph zG8Oczsc2`MVos}WBgwv>tmUp3y9M4`3&p^Lp!d2!ZeO|be-nb5a+qd+>CS|I5~b9F z#>syPlx)nY(6;R!_*0Kcp|$v1o9Bm7@gl4Cce^bz zo=;$BbdlPx=$XC@^ZFMNnw^ZD;RZu0vc1gEWoR?Qq=bKo8R^r+*tHR0#7a6{+RxcJxdn0&Obd=h*Zr!{&eiV?*&HG~eP(i$cj zHb=JR?Pzb~5%FBBEK7$DM$Vc^7>D3q(*{z?H&#Q;O^OND+3z**Rc4ih_zYc|{O3}Z zkI`!0d6uO5mR!q~nqm1`;VJxa4P;`sWNE`2+jmNnV{QcV7uY@vvljK=;A`A;G}$%K zY%&1Z9Jnx4P;O+20!4I!m2~O%Hlsm=(ohy@xahrr=VzvAZ~A66ti#OQaOZHcv+{(; znKnDq4!j|0AIIvVw#Iq0wRuusW0&eJ#-G2w1)&wk(7dJbu}%2@Xw?>rewfTq z%5qMetb5gG_K5ioWSPUnt(Rd@%=MpFp#Y`(cnnn%)$Zw6?5}8;2a8DhW&B4vw@T z5hoE;OrLVrawS=Ii7w6b#gqiU9QYbtIObB zdwwlsVMN)`sfO1L&+_fCi}&UBot#%8H4TMrJ`~v=8uK!CppqT%5y0*^M~GFTp5yfu{9=))YNa^u@PM1cX%?IE zVQ!03UUAqig1G(#_w4#JP@Ed*FCw@$4%>l_Eh)yI*kp~vK7i`@=~@cmEb*G4cd8Ne#?kB`{Q z!IMPh5L7!!E9l^zeLUM8hvQj5f5Ma4o%E!Pmp{Acu13`blPz7i=P-XhposQRzNGOA z2}X>R;o6ws)pW?%dY(cRU+Yb;#QuOC+m&(dNMI!0bJAaRv>#Mn zhBat-@|-(p9v{H;_c#H!eBsR#O;mQZ&Fb@{UxI-w>Ad{HC`##-S&j4y!SZmJEnENh z5!Yj8JohiwX}*b`=FamBc8wHvwy#-Tm8t&WYdJSF(uurTRDwHrv69D0f^mjMXjZzy z2IZF~I?;&myxPE`hmYtuhOG9`#Xwega!hKm~*Qiv3DK+|ljeJuC|8!K)4i&h9O zr4c8E|MAuk@5~(xGUGGBQONX?>q8mlWx^*NOWS3g*uQ>DIfgjr18!N+TNW}E46z60 z*Vj&sW?@I61G~0|>Bh%~yhF(l#y-m@PHP>R#>lrct;sR`0>Tluj|S#^B-vgILu!;> zqd(PX&umguW8H)zj6B)6?fjQXZQz^hXwmIH6)Hc8lQP3}MihOqH3&5$x!?E=|G00I z^$RkSN3GKswB3fi-b=n?JenD1=}BnG&Q=Qr6HkL{jSw&z^4|_#4Jj|zvp_C7t{)3h z`*W+ta_)-Yq&o9^W(i@*hJ9ztX&!3Ya?WkW3{l=r_*G2XV&ks_e;yAPV}|;8A(e+k zgst;)$m=)lz7G58JwvZ7J=F4nzC-!UpzKmC=YZO$F-i}HQ$KkLh`s2W{GW`R7?f~( z|pO-gjR3hpq80=U;f7 zwCtTQIHV*TFvh$~|3dh(m?RC~LEmNT(DGjH>E*Z)MyZ-|v=+lsuEdU)I#|E28G1i= zY7LR{5{e1stjpp=j%(D(f(qyAXPa%dRV}@ETld5l^hS11-Fdu^cK^|n3m2>tr*e9n z8Q^@cL)|lJ7NyIN$p>p`K-BW1V%`Bye!_W<7b_OiwfeHFm?Mkq`mek5Cnn^~+Mj)G zT&!#6!iQJ|Fnv+f@0EJR%?<43&6g}wzT;N@%ol>AbOEzuZJl_{21*g~SQgQtHWwb+ zOU6&Pfm~BP$O2upGeO>;BI_h#e# z@JanYzbR6Uat~qB4)cs8;WuMx`}qp>OMU#Y>F}6V*@FdQ>oGYOBdO3S@5q z-_U)3TBPS_1d$_W`TLSTGN{3Mi-uVr`x!9|x=u8Z$$+GUn(+SK%VL0vnFr{)M{K`b)w%gnc` zYiPjd>w z94jWw?AGe=)Ulf!-97#7f4<$k&{u%z(j!|*7K~)r1eAA%S?9&|KRH}ZJ+$rz-aZQO zFw^U_O9HP+$!pB;PZJ``=#mfPpbhJjwaSvEq(-|k<#JSNPBH7|QV^H2spb9TyrU)Ur0ry{ ze6B?q0b0G|+@3aje6A|9$26ws6q4Rb16RJ`RG=z9L-0Nr^=>)w5pm2`klkGc5?T&o z+{M3Km@jl+phoCOO_TD2d?*V0k0zuig7nsGdrUr^$8GrvgNmPlT$_)XrBya+ysG_ef`Fna{r!_IS=# z^ANy3E22#?a|W1qQ8&p$EdQ4GU)O5T1dAY5Z8Xg zU6mP@gLO2pSc&N9mj03P+i}3P$w^0(sDX$?twXSGVk%6fdrh4i3oA704J`6+?ma7g zduu?DAE?$Zv{6a9_9I+N(yD91Z<1}@H}}Wv0Mb0px8d327nf+$@i$nMd25^fe{K#p z@nLr!DyqC5L*vs7Ky#Bqc(04Qht$2mHw|n)CjX;@lfvhZYni%K5vi$?ygWX}H`vB> z?l{mVkBKJL6tr6tUogaCjCkmzoGXQp?C`9D&zuyyI;W`$5KVdwXHKfCYQDu#UK=KYYYeYS@G~JVhGRL?ldqNt8q&_Asg&*aQkRpO}_s4$*FyuGc`xd z@n984hN^Ax(u6uIk;&MHHZp$9c*^G^bqH@PReeg77tv$oIw>zD5@s0P6rqkJ>{)j1 zop2B`yJgR%t@eoQ!g(_`7Fnf`&*RRH639C_$liA!nXsu*G^Y!RocNjB=d2b!geU#4 zSxIfPAezsX!H9!tq^I7m%xptP+Z@rw9r=w=#JtqaH{>_*R0N&OwbAb0s>gULHRjUP zkVLOO&<1{7q5QYqOX1o#f927mm0S*z&z?vsq&QHTs!>;tWEf%@xSK2OIr8&i);=U~ z<}NlY800+b;30)!|F`t}{u@6M^CgTewNRLGB}9X=8~31nqWX&bjRUw4gJ)12sRVgXc-o-{Md6LC9x=Tx!py>z~JW*f~+`NaZaHAete%s zK3TY)r%UrX9ir>s9#B=7ZfzQDKTo{SNTqc_!RGh_j18kaV*hS7Jt4${Pa1@ak83)d znJovp}{@MMK=dKNm#7yk`ZV+PLo&tSHQy94}nXFm(A0O-JxU|u}Ne%hfzG3Ku zpW=qD9*gfj`dJrWF;khvEJI15`jPz78aQHIS>IVsLxa`ptWPuk-W%R_r5+E*QNT>m z=70Yo5Y->&i^GIQLaK@aa zd*?`*X(xbY>Rl*evo|}<2L;Nu1M*|;G*UR!(u8V=ZJQ23T773H4=TnoURqoQ+ zmui<6GzBaCFB?ob3Ozb$RBHo{y_TK#fmV3%>1tQ z!9tfllSGK_9UE4R4CCy0(b{Y-Dka*vCGtDyrP)WoyrzfKa?djxt)+7dZ->$<-MGE(WglE>N$IX|057V5;;Q<^k&c4R~OF1xkCz~i8{<)AskKP4O2SWR> zNlUoK50%F4tFpfrU+?Ca%CA+`61O!^ho$pl{E^}Bz3F^MGJV;Bxb291mVaOPhGM=o z_6Rd!YmzL_w$UZth@s1DyBO=B=ndh3?bY>9mmBU`&$}=ZhxQlmTfQh{uKDQqJgB6^ zyqRi{DT-^CW+sG@j6s;`6ez*$2Am?7~xj4{j@z~YtrW@$g{VC?rWV+rU2 zo6GLONHpDU!54l4Su5&);!Ptbw|$+OVDlm!J0|@U5OFmgdJ;J!kb$kfMlwLeWJr>_ zf^}TO1S7}rohiH)M!tz~0y;UwRS zz8lRg%S@(LFv_C@vEDBn^|aI~99>?LjK?-|>8Z;wQyBhAs7R0*OwphMKYlnrKop@~ zHnkFH3!|y&8oo7ZChX$d@bbKT7w^9g>kQXbI|!``_DWvCIFMzwrNv>-sqw}KKLYa% zG>5&@V0M(qAuqBdHjJnGnk_SKk5^8GA_x^et@FkxL^ry`SJ%{LZ&+2OvLf))b=v(a zR)>wOpf}aNB%Mx%)Gg%2>q941zl?&j)YNnuMQ0PW(bn~X*DJEHf%NL?cZAPdz2^5h z@~xf3nLGpohnBYlm|%(f+VaFV@2B-G^5^2Y5Nr=7bMsgi83&v+9^vFQaJhL5obI<# zvr;15(ThurgSLJmQxra@vbpFv~`XVTCb+nJfgI z2)D%}LKMV?phvm)f+}U3T*U??>gp<2VzilbciEdznnyS_Rd}nv$kEGx4rsn@@+HF< zCS;%Pp;Hh7t2~8K2Xjl?Lkx%)1czvfyZcSV6{csaou_n8N$8M1e_O-&5^T3~-*Zoj ze3Np>y^^Mwnq2Twg&+h?8~VvnxXe}!mY+cerGDby^=M7Bx-H)Tm>(HQV@oOGiCgEY z0~kg?weN*Bb?KR-{2jhdYNf~ejDxK%bYGiJOw~QhSR}7SEk^RUn(XffZ{F9G@d$Aa zGI!Jq)n*x=`6q)JCfnez$b)sAA#Qt3a8?y+^9&>n=POkGl*^l|W3sIK3o?E<-T26C zEkc@2JoObiy{WFfro{-#7xq~?`)xC(>rD9HS9G+V=VrRL>>vJ~Qi9d;Sz%UvY#xb` zN*1p1T4EZDK{c%FZdlHXOcnichYFVdk4n4sGC-@*Hs#xU+9w9u#^|zLmDGF^Or!ML zR^e|k5!^k9Ofp(@iwDodPY*fCtt`opiqJ2q^#2G$*+L6a`uX+v_C$`%XouX55?B0m z+Gur5dFV)`M=f1>tgQQ6_k?oI)fLLWHTm#8W{VA@L^rQQB5FqY|4{Ame2{Xutq^67 z7mVXv;L2F4piGD(&4@mrd%J& zG@{=Na(W9V1%4yT>r%r8s8IK zO_Uf*zYw@AM_V@g8g_qP<9=~bz)Oreg%x$aBSPh7U(4>C#r~3r2q#i2l|4nFuDc*v z{!TAi121sR7+xMFn{nABgcSl|iq(x>*RX$+AUARPbcHk)Q&iG zjTsA^yiL*VM`)p<>Bpxsx-q9qI;Mu33jC9yYHb-lq8nvR7%+;XbWHhWk&wI@@@T&! z!jm=os-7cBi~o!4I(Sv7QJIiS4#hhCGJ@Si)TBe3LT8|{zF|U@H}W3Ktch!!x;eiL zcOW-o?3N*G?|zTl>zFRQ$j}S9zS3bHOA!{r72tk|@}O}a%mR{OM-Eviu<*Si^V z76t_2iaa`P>NhM~Lp%SGpP0KFrcJ`fk>+4ApFLoY3J==(g|OhM$xx!)o$?D@x;;EN zkbMl%l9Y(;QQvuKH@Y}y+EAzVX2NtWT>i#G>2+R?J#Xk?^J$b5r)vC+6V{PBr5+`R z<6SOA>)xLsgJZCUl5%<0zwEafPq=3wRYHOaUrG%273SHXzRb5GKhk2H*d>EcLv_ib zvs^83N|i`-1M=Dn?go7$6XwQKc)Cu{Jb#thGAZ8np$vE9ZlvqbAf(iXllPa=Dh4Ne znq_Hv>J?>%7#E!ia(*og2B#1`i*T=wmU9Xhs6k2}DNt%ub!}4r_JmV-zuY#TDyB0* zl^b^YhemP5j!yf#u<2xROk!nqEi|<{KCnt2R%2{Bf36@aTb?qn4bMZ}hJ%st_=J{nxeHD$6 z%_oewWk(8}l0A-}-rHm)S3F?~U0i&1ZXrMHdlRba&XJ;U*c*pFyI@t12c?b0Jf!NR za#FlI@!wG)xJ|$XIfI3bC*3%I|E?wZI}tAZ^4piB&-e}QaCr)!4F=b{;#1b*y*KGt z`0~0Z#0Mkf42Kz?k0dp+I?(ap@~fko+B7oha$Gf|8oE@uyH)pM0Hsvanku5R8AV}b zI*$cYxf0z0DdXuBuDL!xfAm9Y>TXv?2pmCY`eBcO@a5Mg&-8anJH5j$)yP69dRSel z&FBP!-Vy>F50U9FvAqnaMjJQewlk*;Ide_7s|Ydq)pm30#b-KD51N;Uz#rFIMCWxrb)qs(+l z&()SflT)j+(ZCP#35%?Ndq|riw5`2?+jX~s_It;a?y`Xy6Cd6;6_^-bbh6C8N zPjytI)c+1Xrc11b(2}4=seg|Cz8{Y~)-C;1u zTd?|9MX0lPJGX`xI{ltt7u#=#tG15b7AMv(BEPU&iyV}0<48ox{2n)U`=a4>XKpsk zGRsG!B3`*H&=#M(<8+w510R1>&serZe+TN5b-akc1ihJm~gj2@1n6^h$z z9rOzYv(@GIU!!;-Qv!U&T_Y$zRS$LrHYp z3T8*XF54U};+}8rj6)Z8BrmBQuLs>j+LRVY4Aj)g7{#=-KCp)y4B2N|bRDYK;bS`& zS(xB6u~vQhEBw>5p5MFwRoyXAj1BNm7pGaXPjV+r#-_IBlE?Tqr%RGWAwoH#B0LIe zX0~-%{0nwof~hU~&EJCd6tDUoO?icqh{gEz;P>M*WS!QD1_3x+tg>9rRl7YA`JJb! zW!V>HlBrK)-ZevDyVb%H3^GGdfkT+*1didwQ^+nbdh?z_1PR+a_h?^`tgX77sYbs* z`TZeyk64Vnz1+he@<(As%1nXIOIR?AFXqe^rtT1+0+#<41S)o&P3F3v-r__GsETntiP4O%x1_=zmpU*P!>{(W=Ta$O!ldpfY4RSxNPeCVV{M zU_jyCd-(+v;GJdl+`zz4Mn0b4=?o|YU|^(Ra*|@2-g%eXUL90g=}k9}o)x)ywkeY6 zBcf=SgM{d8Ct>{LAyK$vdCqZu73h}k?xT50q(yL1q#;EmhqRp&*%i6UkN?ach#F@u z|MzG6-m-7EV{?`L9gQ`pLnBSP2h8Ncfb%}J% zZR>>3cWej5O$OQ7NILMcAb+;r?<9BNdp8+rP|6)N(Klf=u{EKy`Y!hqKyX9}2cB02 zR${z8_YMe^z7suP*$2mFjLtmdsLP1_1apA>4KJ9|u`7bHUbK6{1i=hD3(Jg)wFWT^ zEuxbGl^X0AM3foL6eI^N@`$o4{_Z2;{IUpa>wWG4&w>`j@MF!n>eG3`-`eY9=el zog$G62OhkBvPqoB^b<6XwA^2vZy1l@Bs3L@^6DC^V8Y1L<<9}l#{1ePh0%WSj$F`B z7-|^b&+<1DT@ano5~$NP*W7pWN22~#{2L62Z$xi7(HA(68S zmm9E;(o)O)^9Vzh0BewNk~oVCZ*z2^0F7PT+hi)>6s+;DTPFO*i9b@#JIp_RCbX0(?RI1-@K}T4>ece@9}~IeuB?85+#lS(7m%3vU^|kn}!GIEHU<%TwM&Um3p4FtX z8~yMnmnC-+ZVVm>8Hj(21w%IfuerDWYqJUZMiaESwYU}uPNBF~uwW@p@zMgtp}2?A z0)gW0En14ZL)r!?UYue{(W1cv1Ub2%_dM^vaL$j(XRh6uxpuFao%zn}bNCn{{+HGC zAF5Uw2)DUC{>~C_f$sHWp>g?3B^EqCpt5?``?pu?a)kkITwtM-x2wtCQ#Z385wtrB z6Su&z$1o7Sqd{1&+HX-{=x7q_q52c?uakkc4q zbA&g&@#_^mGqu+a$geXRu-mMpW0Z`wV7M6n+^=3bwGUT)Z&2BAF&M^7H_ujMszBpy z%EBw(B9FI45c7N2tO4@-fu*@WAH(WNd9lYOH|bX{hjFSmt4jxf6^d)IBlb=XH=;dA z)m3ZQ#(2*MGuYAbP+{e9RE#*s<4l-w|3&X8PpohJz@tOXLpTmeG16On7tDSWymDUb z28$cy77RZag@@Ci&n=WXl)m$zW)RKqy73n8Xpg4LKmsxVVru-OcM607Y)5S&)H)#b zhMvL>5Na7-38fPXE9>_lop@E%D=E!*hUC5rRw{DnYhbu43s<9{OH9^qzjwe*bPxH= z=c@HnZ1P>G(2@2FUnSxTF7cT546=xEfC_h+2-W*|=pC>?-*(Xh^o_^_r}4QbV*^Z7 zwAx7NHa6ks* z0ICouLlk*~NyTS|kAwod6Fa6d$9W4BDR(fku&<>_*oAgLfNQn74*qRMJ8+H`A9Noy z;0y)vIu?oXEOAPs7TNXrcrt0 zN_!MnKa26>J5sj%TfbhL>8+eT`{DAv*K(YX8|N zg882Y4X8+{cqXwkCV2vhPs!y@&dkBP{OoZI&|j)2HMw3r=xh9-%FJ=yBp9vLRX&`4 zSP1pi1}%FTMzrde?@Ti_wIaNx%IKQe&OrrP*V)&J$Dg|Dld{04)uqTqy{6VQHwqWp z-H&N2Xc-!8a2LJ~@r?X>=wxRMe}XB3{CK7QI)f2ja`ZBuQMM7<074TYmbW=`pXOkr5|ILztWw+^e~mGe>3)(K6z=dP(#YK4i<@FHecMtrf2yo@j%IFg|@6`={72v z;)9Q4Y>aZ+*kChXvuVY1fk`%u051O`ZYK80-I@5|%G_FG%!g@%uz~ow2!s3r=-N@vaM*I5^*E?I2 zH#Utd1}&_YN^lFtrR1CTs^_Qeay_YiZ+e)p_GO5JlD0rIzZ&yZ42ljEeLI#(Z{tzpEpjbQxebU5ls;*r`A@$#Olp#ooNl!DS!l0g%!3 zwA=CftKAkAHuafPqq)%P7(6BoI<>@{o+QQ_npWDiX9ZfFQQPj`p2 zBZ{#Ox*$P;jJIp)h}X{PQm~LIsbFgzkC?36v>f;iV$EzuJkm_HLY3H4aX)LZljKNs zTbQW!P0hq@TN3|Kmz1wA-#4C&w^JN-t2h`W&D_{DdS5Z<`sikooI_csE7~{|T{hAN zMNf{bjZr`&VF|zDdM45@*bX1=d}5F-dchK=`K5is{7dAolbi0UOsa8lu_MWlQ)Ee| zVVSwrQA%pDVscjT{!&Qsu$PFqvc21oY}1RC!p~M~EJTAmt3(oK3fDi6m2CrU_7YTQ zzTS_68RLs-EhS7U#(&lC4cgrAA-Z_F>6VZMuKE(n=|#R>NKf6!Y;qq%J$yLEp&^_D zcZ7gu$yl?!lt4t_$%CRD2g+dlfh3H;PdpSdW)9{& zc8+M4J?jjWd~G?E>5qTtTl8Be7EPVrJl!>b2clMc`Ysz%<>&9-@8+({>hDoL)A&w<)|+A;CU|Ib|*<4teYxDz5CXL_m1tQAwt+{CtYXKvui zZy42Tgl}2q#k^RMwx3+C%wzzSKpD}SR@0LRw}@T3mM>i`-0B%Mg4 z#SPA$pkAJ$g^Cqm$*ZP`|9vDyj^ecMBvqHFUDcKt-Q{+ATZ@*8Px&m#LbCsrZ0VxV zxE!3(;=|XXCov$>-r+Xg(m!cm2T~*`*TRYlhP#EZ;fl~xf66~DG(vG2K>s8R+h4iU zmQRPmtKA#M*(XjC8Pp7?HZ=B8HX2o&ZR%854WSn0qo7@C)FLAFYmL~?5bk=wOaSSg z4xixt&Fkw+#I#5AID_V07*e``s)O_B`9T?r+H0bjnsuA!C=0raYbMn%ak-DTUML(q zG-HD@)4s4S` zIW;~bgL*KIN8}-b-PMAwkmEb^piwPlZ|0-j&8v|@3vPDKmBug_V_us`!l#4SK}2e8 zD>d3ctW04_Q|w_GwPwiw9M`V{AOe&Q=BV3!xXez}hzxyf%$}Y6Me!b8Bq#wWQYe!r#LPrO&%pT%L-?a8y z1-#;QFMCv4il{WJId0+<_lSmjF)ZQUYc#^;OtF_(sz*HGx|)pj zcf!zpL(&bKZY`|Pu4b9~U%zicUylzj9=c9)2(>TRV7l@G2(l^-FZqt#3>K(A^j=wKPh-U0dBBvg7T#s!lb!^kU{rHwT^eZonpjitb}l zmz?o8DcF%P$j~7_-rS2`e@1^f&HVhb&0eOB^vF!ozSx5P?bn@bbsutFf4vGX0rB5` z{+EJIbg0lKtnr+g7xz(z>2mV}rvW&=@X7sC5*W*f@s#=KLKeTmq7O)FqK*E7RXpDK z+kQR#FMMAzT(pXR6TkDp0`a%qXOjsZL7!IUBVa6*?ecj;3#sm1yLnV0909b-E2at~ zoYpjX&rh}n%#NZAC`^4TK7OWT?XLIWbsy;*x=nFm+oAOmIHDYJPIYb^0Ny>Hp7prO zW8#Z7s|epyUpP7xo3Sw5%vjO76Gch<>d`*QpVb@zk)9|rh3{8d%<>Wyt*Co%jSrfQ zd_(Fytm*D%rweEL^V?`r@JIfOhIHo!{lW!eh_&|lq+$A3B?30I_QN?f>0IT16dgun9a*@K0FxdHQD|U6jjG}Hg3L5E z#9oQ~g4cKKClcSq7}wCE{liM{9U4C`tuA6JRt8c^0WAEY7k$Dh{tfv(bTW4Td49PU z!x{=Ms*u0Zi%kXGX4FL#rh62U<~&s-t@1j$ld5yecL0aJqWAK)?vU7GEy}C!*xEY1 z?JgvCIx*V!fG`8+Ph?M^$ zwG~214EgbsK_T@c-wacNB$zJzSEbA=y!}M=-3*tHNP_Nq(9uo$A2>vi%JwZvo{#Ot zZo?g&l1acXl`>A#Q8>E+gjCHkmtM(shtK&#@aXwM+NLx+>=jV=Z6lv8+K^up*9nQY zs2W&r(MBy!Jy;k?c0VQ(^F=9L+Z95AYP3RzdFM%3Tftgbs zl;2R^xIdi?vvX^jys~!)-Xq2qU>LEh(OWF8!$Hoq;g@~wps%UWe3<-Qdo}Qy$Y!J2 zYKRU>2r!+*vLTX5IBMiuiY&X2uu#)!m)H{V5x{Mn#MXryoO@SFjV|rD+XkqAuV{{f z)vza2tB$w6!5WtE_aTbrEa#yUua@yi*GEQ`l5@F)mEO5HF1N7lj~k2S>`I^Br6a6}zw&OEZocn2OFtWK200PhIxvsBs38c^>4{g`uL>5ZCX|-{_A$qiK+@d@vWwn z%mdljuF#+H7gw!L70B(MfU=~PrF9Wm>N+Qj)bMpQ+Owp0TC5DOm(zp8OPW5?Wr$k8 z_{$vH9q6@Byc(w?N1aEtk|(8^ODbWK_o?y%eB&VKv^$Xa07u$SSrY2u7{4;VMJLk| zUSZ<=kq!S*_Qy^}&FKc%w`zYptucaXB+AzgoH znxO13f*H{|rkU)`EU*5D&zBkoSc;t*e3z?pB^;kDOI3LdW?oE%s+C|KlSM?Ej&&D~ z@>HLqAL-Y=Iv!HyAL#rXnUY&Mv7%KFcgF_LNcYa17Ku(S@0IKDTMgY~D+%X_PTY$0 z8$Ep53UJ|*GUYY_ojWGb9bf)OsWb)cO)ek*Q~B=T=B>zN_ze}lLLvr#eB|(z%|UxR z^M2#H98IsWf)_ad>@Di)BsO2=uXBAxkNOqn(HD6o?3)YtN7(_z8G3lgWN%z0bVhJX zv|>^DNdX5(ZB>2%N1$Y2{~MjR-^;j;$>kL&(6;)jR@nD$QBV2RiR6>>`o zo!Y!$6-GQgQ0U!VK6}m2+QGx`KjD>pSKsk$sgC#V#;5fx4UoUi$WE7=>CpJKyyH@z z%R!F}V-#Aase0+=n=%QA=BWcScDu;YUA(1(N0e83Arx{nxpbuqh8V0dqPYu1Y_Dm{ zc%ihG75??^#O`UpcY{M)Ax^!?RCsc{fWGYlev?r%6TMg-*x$8ozALw z&nm;YyCGM^x74hOiOE|z!Guf&02LKO39<-K3EyMD`NL2fB(bXjPEDaMw4S2dp;K`# zpcV1p6vvUiM~6$6V75YmFD{ zF861N1HO8s_ITv`2~?yFq?X^!sp#T`J?+`u1!?ohk+mtmP8oyTnX)9`rfr0*+NP8k z7}$`A@sza-gcO9#&A14(E$pt8s1&iY-I)kZP!1h^ut(xJWR~nq3S(oO8}h;DoYSiP ziSR$pn{NMoW2VtPaV`n7dS@zV61vQul`DR!hM;6JsxU6RHCM3* z;~ywaURA%|DPJP31<^YV``&bM1O&{`1F(*oAwI%%DpfR8`jXY_Ats z+hEu6SYG|$&xQNy3(6fFW}QK^Dfguxx;ZU`Vnp>-37JX3$X6<)A_}fy6Xq$7yZ!>_)W$-Io&f%*r|=^8YfOxK()EY_5ZE(s-S8 zkX+R&yU}xiU4Vw+!4;-2NOyag`miurc-5uO|mtCz7eke4YY|13(*T!LpHa)Z|J_O$N)&=zwS z(o11`|KE=ey=`;NDTYu!K_0sgZM*-IlXPF(T;=xYN&r`NG}N=p0sHAJ^|guBWw}r(4F!w%hZ?$R34wlq;{=Q?NZFMB^vm1`i{|*_~E=| zUz_@jPggR?n17k3^t*UZUhRs_Kmv8fOLUl!8+}sn1ROmP3vla&#}*~NBXuG&H{@a6 z8DpR>PtOb7=EzBM+1^ad8-x!-RpOIP2W83TKR?5o+w;|Dc#X0t=?M1*!zagU_v4k; z739q=@Xb>)u9UkmUU9Gor_SaNWEn3so~?BEQ#qjnnpdNsR4*KjHX3l@DUzL)z)~Yk zOM)tWaZ~V4-)+g+Xku;JmaARVLO$&BoR$oV`TZSFg;$ZiE$7PS$0KpK4NVkHp9Ry$ zxS-KS4%3m8>2RERhlq9`E^@<~$=G#98t2+*11$ea`;FzmA#XRyn20g}1HkdmIIRa9&J2 zv6)WACdK)ZzZ>K04Gt#7G8Pepj&5%X#r6Ug`I;O#b%~Y1=1zl4UhId~wvFryCo><$ zyE~%CQ%lN9Oca;h-xs#>>Q|$S5aXjv-VuqvM~x{h)?UHK-`)2#Ph z6mGK)12y9P9l-`FUw>Pj1W64>s_i} zWiKK+?~Jet__tO$h*-9*UA%jN?$k~B#`5s0&l=lxXXX%W7@-8E!Y`k!0sSmq8`nND z0;Wc^0%WGH8M=$wSY$KI+8jZX#DIhR*IQr%HOJqD^YgOH+sFPR+$O@7Dr;c|d@T4j zJO^Vr$}isa`8OPJfxmG#^LXasWNd*)y~HHNn&tAVPWYUav;HLqfUTNH_j3y7w3oC# z$yhu->Cq=_gg%G5yuE$0BV{7ZVUn`2!#uJAGko>o~C7Wz2Br7neci!sIG1BisSQTn9m>O zv*++lUY2TiX1szYMs*z#n^dz?!_uZHu|Z^`nBqC04UipjdNip;0qg`8avd<|%6f*I zbfu>ljgdK(p}W$)(qd)1{s~30#SFacEw=9aUTf@>&68da^1T|mgbTp2upV(LG5|HT4r2qENj`dz9B%qkEeQ~DqSu)idDGWj|9 z(O-{HycbEh-=)exO(sQduv?Nr>>La9eHV~l=!^u)<7+j<8s-5YJtq1r>;d4R=otLJ zbJ&MEgCoa40Fe!fCoc_i^`4|KXB-p2U5uU{EH%(e=0ka;gg1ydOQWDBKUknao#|cw ziv?)t0wziRGqA>8F!lekQ@R4UAbn~uH>!1E@qcEknr4Bf(P^aQNXIpq0#*R`*KxB{ z$NHWKkJBj$Cy*!o|Iq~_0311D3J}@E zji8L1`BwEzk2Dq0yr$AN&8CxD}vHdmC14 z3DY#dm)5;l?1St6ulk>%&Oh{Ga4d*w2jY1?o{0WN?Ex6lZjZ#N@BjQ~)gmm(hx_k@ z2&Z$cc3_*b1wC`B3}B;l2`BXv1Ji2V1tSNX*e67vyV6*o#u2{Wybr+-lobDmtq~UJ zv4KYYK@u++_}lITEF4YoTE>*)_<4RKYW5DoYnr!N2%__E$586TeA{whHeCJX{+C?WD$q1Pk zz73|nkUHeEbzVN55#Po0Ak-t+e0=nJUmoQGpMphrM!sbWQZbE=V8O|n?n~TVNKFQP zd1mN7ZG-|8B^eBjPBnND9!e0kde6?A5Gp@g_;qH##yS~J;y)3mx#%%~b8`fD87K8( z%V#0&;#j=QWXum0ldUd|YNCqfvKO1`-af35ApJbiOHwE7Za2<{8j?@LHT)_*Gpuo! zI1C)JzR(zWhC&I77_w9oUl+&^Ea0uGzoyQEEc7f?gbf+IR7mwR$TLw|>o5U@3Cwg{ zBqnf2IBn#9rT;^Nv)Tg-;giU<7Y_K^|3dGU5*nwbqxtBHr-GHl>1iWft|s{4YLebZ z9Iz=^F7;V&C=~nlz)XSAtTI3-*Nf8$yIGFoXh$}oDRs^F%uv*w?~oy<`yvrhf3aJP zREk(p$805}ZjU?7mnXH@oa3A>qk&Gaf?Sxj%0^LCjKXc1!rH`9c9Dolsx+Z{+2w0j zo*wg-_L*vJ#R{E2APeJh^KWlVC-oArP^Oti(JgLCBuV0fT7f@rrR?bMgeRxU{*~Kw zc|3HpvBZ7BDhdSPRwem7!KULKpR6=lgpDLNX(O|zReJPJ24>9ap|>xO6@01D;W(v# z+YJXRfD@_;-_ev$hHSYwN;0zRT@`PqcnrvA6OOBnz$E1k;V#@WvcHJG>4*_fG-d zt4O5!Cz2GRAI>EV+?TdzRZ|qexyfs>Y8V0?yGJrpCpOBVLI)EX-is=70AiA64?K*< z&7IAhjp0K7Ruq2bzwJrQe=A%RuKftp=`nSE^mroRO|p{y7>lOI38!fG5@`?K+p$F2 zyD*p4(4b78ZLhtUK_3qlA;t1-f}r2cc~n~0SUH3|t20yvFe(?DHJQ0;B}ZHF_N0vN zpT6k{`-_9uD!^zZaBx0hD`4S1%otF?k2tc&NCaD7gKo7Z~B5V~DL zg{ZI(nj$&yV4S1(S;LC|q?_0xbih0JSAsreT&Fp z8Ny8wa1DvFOv71AzYE%J!&fULRk>W5DIE&}{!-|tvoq+b{lM^)Q=2;^;ei%Jtpdkt zbY+YwP{0JlKHB_pQK5BX+j%8&Pt?|W3Vix`bYNkuq!()g2$6m+YG4y6S@)qSC5P(w zfj%O5Dx_k@+OCsU;d$Rp#%5wZOg&c!SfCn&O{gkpo~9W{4SOHj9W=WpgWs08sqhDe zC{;WE;4B-nnOF!zbT|3;4;q3!kk4#~ap4)OdeAoL51wuA0t^Blcj_t5*Su(J=#=KY zsW2bCaLQgza+Nq_m|Wa~t2puAKDmPVg`8ClpqnL;6M8%aFC1jPrm!;9m>=yt!*b3n zYI-c%q5d}0Wp-=^u5as{SL9#FRzDSfKkehFP|$Xtc*t)#LNc5+9^_u0->f(b8o$ix zxT=t(j)JNrhyAcp3$Bdqj^0#QIzq&0rB3XW|NRE;k{de zUXJ-!U7+9Zn>_a8bC1bYZpnyWbJ~(kwXEG%excx1VROw8sP|)TS}!DTmaAV-a+xGC zL1l7mpk50@x*#QTXlM7rb|W^`Ejz-NiQ=| z(XG)+3olwq?HNkqF8<0(wP0{}5i3hV`wmv(!fj{ykd&=AuDg|hn2JQQw=K_mi03PO zp3k&_5ot|)iOub*_TAD~)PV~D(v(H%Db+-lkb=~P>RLQN0l|{`W42>sSzV_jouYOS za1NL#f^JWo?WgDugF;sUrq>>@%yNnAGTlwt17fErIznq?>G(d;D7 zWY;Tb83WE%<#kSDq=^qe~X&3`%my=a zp7qYZVfq_Or4dK&$9W}W5d*kTsOdQV7+3db95nT4xg^6w-t&d| zMp#6=3ti*AO@NHZ4Tf};?}?VUDyt3mz+x1_ODZ~?-Q$F1xW+#kA3f4k-3rurvyf3@ zufyelpQpM4d`CRz`k}-mfD0GkR)}GF2hMiG3n6cd2w}LHs0ReRD{awqUP(a6e$2c1 zWrrd_T_WT;Qi3E&0_erRI&`5s4OgXY;{-)gr%TRaHlnr9L31?P$>TNCd=+9<#9a(+ zDaQ;q_G=-wGsn7V(@9Qnbj4h`Fd&Rlk!>IsjLS{vUppwDiCq`3@hj?=hNZjsPFSzL zLs^;m8sgdUU?bp!lED);(#qBi6DiC`lsRaND40O{UEG=^?@j#QuByrS2ScXwNr8rS^98tx4fOy%|h)jvrwKvhogw>l@vYT`A6o>ebxwLc-naSnhFXc}LKp|CyH65Qq{kee_vGL zTRuA(c%EQ}mxtGNKl8w3SclJ~68k`(q;fm8)F@AT#Qa6*E^Rue2hK^b?ebC*cYt@$ zo>lAl_cQBCy5lLUUC*a5H*(={J8Io!kXZ904clgNtlnCq{GptkQP>nRwAPFGFf8QZ zi(zL(;KC`!TAm&_KqDl!X?9=Nyn+i=0f)f!k97+PbP?N4-aB?GOnBBB*9%Tp*fAV- zv9#KF>>Hd(^3G~5!6gP*!NP}r>O}4Wj0R**UVm4fzy&xNQVe03i6OK&!eCsNL#A|< z-*(D1Sex5HzZK!Z@)~$ZhY~PDsx$2og+!l^f3cFr0V%dKX(Ao`2oA=snLxnDLC9wF zerm7OOHP~{Qo2TIi&X5?MT}lltluPT;@5uZG|Up?8Y^$6J+CDC{S9sb?VY@SsyNY> zD*I|6C*kb=v5lo3qP;_|O1o>^_3EO6&4#GVaXviK)!6Ps$QasQ{4hnou%7gg2(>p- zXo!PFgdz5&|0-2RGzc6Tqu6s)-h!CJAC_5H@6}%m4ccU)B<<>Qf*M(t3o7%O!@ry2 zb(`l(Fl1Ne?Mg9W zP1~g-AllYf8$%Ho{TvnQ0XiJGnBaV9`T&d=vTZ-Vm|h`rssR8n{Qy z)8Nu7-7czNpUwRh4e}N_@e{w!gFb}fMvhAZk|0mxzIJ=m#f-O**OyRRrze&G2ilXt zIgnPhGWq;_#tY+<%t%m{fHN_KU z$2{C*sf_*PMv`bi$`}Oda47DY-UXm2D7a- zJOk!O?G2;GIOE+&yrlWPK)Twyn`P8^aLduiWzTcdj4&uI|)7Y0~LP%M%1h0L% zpEt)79#NRw_907szG)j#89(LJqH?RY9revhx;Ptu-?ga7#G-P`O;vcoplE;V_n1Gl zG&JWLd#rB9{3^GgN{5h=?=Cfg7w#?CQcU6Zc}Zxf#qv6{8DBr9dY!IxqYoq41QC&l z3zC{c6DJV(eVc6XVKF?ITN+)@9hxVEaHFwfeF(8t>DvA_=|i_;c9~W@mT6bjNNb&T z!QjlvvADapjnHszLDkuRh0zg-GjFpNHq3_DjTn-w>&gXk4a$E1dL(}KPOVfO+vjt9 z8{1i6HvUD(nsiC6=ll+`d|H`{gA&*iVSP7Nd#eU$9&>1!4&!dI00hZhQk7h)elJiG zYAH?|jSv#>pS+Q|Q4&QV2U}~$0J9ajVe}SB==4e2qE$;3^IS$Yn;lD+-Pd zni=e!z4+G_7l8f)3DYbHJ$Ze#_Fg6~LP8nP znv9!QH{#QE;uqqFy#H?g!$;nJmXeW8vjm8 znk7sq-n%@tA}Wsh!Gmf?WYwsB@<0mn70gpQKd=;et&4gr99}m_yXyO0oAFbsvv4Xb z&Sy|>H>9Iicuxk5q{^g)SYM6Ku4iwa@|rRTJ9u-|R$Z~;uGy6&vw6K`~hLSit8#{0~0A((49yjO{xCB=GgvwWtp zpiKZyEMViar&shZjmP+e(GK<}C4cder{sP(MI*!Zeu&>$RqhGbdU(l4EE2I}#NmLbnm)oFG~6@a^yH1A&G(va3W&`IPhB=F;T$x_2Y@oN(O-X0fx zF5a{H8<_cBsRBGul_s&p=vOeF(|&vGttel!B1`glSO~D5)oW^&i~fnA@j$rG5?NQB zUL%i_-FXRSCzdXL*hxcR9FshoKs5ttmkN8j&=c%%lXf>wUEk%uGgWxhpRW2>0_Xv!9F$B*jm60HS9gOfl&@W2}w|a;tNQqNgd-K~qq)er;r)#>mfF zC4OgGPh1Me)M%{LZI)-hc_KUgWch<^jf>&|2dwXZ=t(N+7+THq*EN^OyFLcR{d3LC zLer!lyEZ+R#-bVnOK)J_Y$6sL&KbHevQ?Toi2_QkodTa$*=l- zWypeZNWk}{GTPD#!#Kr_n8F9HcwXGN9ja2W^m9v>$Xerms`C}&p47_B^G;rY%H;|} zytX%aR9$JX%yr$0o3LpDmCC|=9W?f6k0fMF2Q})0{h@-(iw!_N@28~A$is05U#892 zaO%>~ITlB(Av>G@D_yL4LMi4Z;IC{;FQNGIqtdsAENk+stZ60RqGAT-dF5La$lUz9 z#5pdM>wk~OT4o+HshAJ85D!BBg{oM0=ebb=#~*4*m6J=1(3H~*7{c5*64!t{#u**= z#*SBYR`vJ4z?VNNzkYZmV^{jK-lU+D^Hpa8@S^-R?)ie&k(OD&3eYm6Zq(9C>F~HT zP?wu1EaM^%ljtF%ZP1|<@o^pf%bi%7?M#k^TDw~MhRmI@jrc;a?&j;YK>>8S<~7ox zw;0F&^`zV06CIK+u~!!DcFOfHCaUZg+6nCo+(mfCz+gdVrO7fk5wVQAYdfXR6zL67 z|2(2D@(YI_(xTRX64*HfDm4no@^TI_?Q62Ol@FSHZH9#TeDLdTWBnU>&fIAaS%!S_ z3atknsc5`gJOocKyH&L`!sfIV6g1t-FVPZGqQnIXW9MOCUQmL>kFteRBt6tpQJxY`THT*miP7qV7qAdz#Rx?nC(8mn;fLYT zzGRO&qeEH<_4tz@qw|%~ewbX)#5Lx(%Qf|U+kl@3>5>U&xf-Hf5d6|rGg|{47f}w{ zY>^RX=-Q5ZDpntEw}}1TJ9UkDG$BhfFY_w#1W0-)qZa9@t9P&lY-oYC?avfNgiax(17$1e}9;7N4-GGmZf-=ym+2!;ER0*3% z+E*dF-)~~>Vpn-gtSKa-%CdB(Y#L2q>0>l!^@juaGuvs>O;IqlYJpJwCL>B zxsX(;q*NH$o_^i(>p*6E_ZE**Ohjx7(eL{xpCO+bj<53xG|%BD5jZ52$F^BZ+WzPH zPku%LtZX2Bi143(=@-A=9c#r;G2Ka8;1C-s{8KdfPZ~dJMM1YFYKFXisxmD;J$aCW zME`^j`_PGk8sWEeuybG7vvHMBW`s1ZK6_dLWzCtap?OTX@h?cZZ7`||mwl=#t z&@rs=VJ@W*?@ip~`M5~Amo;zCMY+mGv?jBpi*;Vk5>7Me%*4$=Ta#NFY@A29iQZGh z)=rFsSwBCrb;#6q2I(Tjh4am}1pLYeLQ~tm;1Wx$<0>wGz%hcDHC9|8- z@A#NA@jO7YiT`rA>?+o1u^Vv@7P%@mv_$lSa9^c9zjf*Kua7Q-c7&BrbLB^!bt?1^ zir45@=Wf}3(EZ*ocL8%L;T$4dV}W3NTvdeLvA+ZrUSj2Z!sIN`is}fB*yTN}Z!@#e zpU3<%`)GDlC%o}r@3woV;b!`@6{20t>4`4>*cYAh5KkQHqXp>6=}B~1n70JE($l3%GiW=jPjF7fS?ou)=`ROqE0u$AGnp`acA{R25FIKkB@qH zyqBqlP`tc>N;yjxy?PE86Y#DHE5%_Vn-SXlQ(r6xZGFdz-6%q06b;+LAi^0__AV(N zN>LWD-0G*ze4Y>N$Npp*xki^nx#@Pvj4mgS;ImuQv$>_asP}n5x6{4H?Oz|)3|%aA zY`0F1rM*--VlRRuO>a58aQDhhh^ z1zX)z+9Y{!AgNeYgTqN`)ph!YLtR7b>{vSNq;OE$yy4oac}j44)$?r3Efqik$3v#; zv)jHXJzz`apO|z;JZrV=Z?NzIC+Fc4{?(=7?r}7(&RTPayRd9TEK24-M!Iocc?g#$ z=&FiqnFEmqT3pvA0<7N|R00=qI7Xu$Cj7hb()>+=_C`7%sdtfQesb-__&ZYh!q zJECxOa2;rMO_FS-=kzi=MQ-3) zrTUof)&bxhh3J%7fv&Ewp->NBlu=IaJ(&k+ZRAJhpTl6Rb=ZISF<#wrj7^@63n%ia zIR1t7sLdyrei8VJoL@o4uFL89@)Ex5?311p(#892Q83?oD*b;RO6_S|GUoQkW+to& zsE|GL8e{K6^yCspY)L0qmB`P6b_Q#!9-G~}CbqtIG3SuY*%X`PT?H<5XX&ft=v5uI zen`jV$$=0LK3#D0K3SgT(plocy#r2p3Wf`(F_yvJm=~#DqIJ(_l}ca%5{E*oWnq8N znEYJElM{xEjXnxE7h;46j7$4p!6V=tj7U_? zq!&j$&(TzUP9YE2*p;X&^XdU10}Z~WO}zFq?feZCYlVs{;U49l4*9T@A3OD zA8z;dcHh34H#2X(-+2oG)MarXn2;B~KHAKxFC2ZnAP?L5|M$%Q-~V?O0x6oXaX=i? zf&XaWzqXI3A0N19R&sIYXy?0ws4PdIguRJ%CD9^;sL>&{k#?~cJjK9q8V)x3=J!n{ z=mwYPXWEz??9_;v1` z>l;dVpeBhfNjxcE&`;S=lp^hd1EZx6rKL>Js)*zM4^1SQB_%{H&pV( z1v1m?idVy9D0d@{^Q%#5#b}=t$2H_ET1QbiZWc+XihhPRC{+%2Loy?8!m^qa>l2UM zL~%@MiAaxoJP!y4SkSj|qGCQ0x=fSW4Dp$vTS^T>U`O{x4sHj7<`{c-jqB+4qN68C zNLK^I9T8}}-Xm|VSbg5fBGtUu1h@o#`(|FEyt%b9n8eg3)7}o)9N|nkf9p@@%{-Jy zyhF%;)mN67Ni#+!uwFkw$;ZWi)R`?+jPXW?S?;|JI}7?SWpRIY*-)gf9rBA#N<9vh z9n8F2!(rQmP6m4dI?bW)am3o_e@{AW4fK2<=xwbry!OtzgiBYZo13UL#J;BWDB`Y6 z(BkfJ7qBrX|hyt$7&C)P5NxiG>qTguDnzug#g4`5Nij6rwX9j*PIyF{jd z=5slshDj%}54A<*NqJ=71c^%b8^S*%z1(BDTpC3|E)G_gqSy0GJg~bt$tsEH=X^wf z&4tB{{z*VaMxH=?+c<8MW0caaA};LO(fzQHeI?CdrKWDnd84DgIK_C7)J`Q?yLrb( zc#;?@@WQpRiN(k`%R%C>flO5?N2_wtB~URFW&`!s^9}tuUh1*Y;n6??eu`{%=Hno4 zu*o>`dt$L$!;jUbNL)d}^nAU;!|m^hF!Lhfyj*B$ipg$&s&bZtNk?*(M}$&t1jR+48*N zU>42bPg^{qtulmrIGZMBX?&D+KbDkUBov~h%O76@8?t+EK9qZLx_3^r<@5)*#C76h z;z(|L0YH`6<@vKdkBx52s)>=F~q@$N6}iXm-$|)BO4) zQvVhkX!9b@-!rDuj*t8b|2k79ndOJU2NOltLfmi(Fl${$MHOpQjFV^tv`a-cTM4`m7 zkq#ySYG(D?uR>uS8vzaVhQiqs5>Blhrt>lPz(&pF#YhW}WO;Z@H6AEo<-`^(V!-cw z{Z$IT3MQMxcgrNV@O;!dV)AlQfC`LTh`#lml{k3%K0PJFIc(z!lqcVm7c`Vp zE=z&;0;hBcH#x`x4`0w}J{m0Wos}l*U{1mtrotl7Cz#s}+;Uc}?4#%b+{2-+emxef`e^H-4wAtjt~5WuZ(p zlkG}+jP?0Dsh4qwv~tph2m$;v&7b)rwo5%?o~A)$9J|x^PJ1)?VxHT6q-K{Kpale| zEuZ!AAoLWtKM!s?w?P+eD(Q2G1~v02YWFqFoDnVAmy-SX?< z!`7eq4(w$|y|6suSt?%b*)626C>)qx*`~9Dg2-x-dUsrvbZZ7N1{5 z18QMDs_K>0&)d5&gRA=Jga^gU>l=p1r1{Qvn?-}}s0Z&w`qKOIH@epE(O@O1qEGB? zFMTXnD`hs9E&5bngo*7f)$Us(OxK*&1hlvxahrgZrq7~4+C!fcGi$eS+vvXbZ*U(J z_|i;@@F^97t-kmCf>1ek$fk1y?8b4?_88`5Q1FE3BIxqL?@%gi z;hlGH7D=0qDPr^UvO)%|JgYxM`xAlcH&k&q!7wAFwq#$u{}K;UXN zD*>e)^j7^v^^!T44O9SqUEtebv)|Wh1;+|+O`H^Q^H>0*tHyiCAcaFs>-hjX`}XtW z0~WOQJ<{cT)8o4UEp>yZY`wx`sD8FJ89q^NT%QGfn)M?$auI=)4daE1xER$a2W}O$ zB+Ea*Y(`_F<79I=u0@+&9!8(jPMr*1cI$DN^AKu>3H={J(fq$A&^E8|#-aqqgYZs) zaN$T?J)CGHTga!`TT>lCyUA@{LJ5g5!~2{e>|sp_z_C* z35-LJlev>`J=$oFY3ec1z=_lZ|1^Ewf{vvHH1reeH4-k+nlMJnG{GUE!;Su31GeO7 zM1wy`(#4wEeH%8ihzLZ}te)(M_|U_-0)EBNSYQ;fjz+RK$s?)y@ClU|KM#MuXOerZ zRW6VqG5k=BY5tFe0*I{h>8s({%P5nlN`KzX9AvoxDKcIlpTs z?raV_Wns7HW8^MU)dS*8?qNXoDAJVnOad1d?>6kqDz5ushL#_PAbk~ zbl_vk*b;8Z*@%i+6B*LBvP7Au(?#5YImwKV(9NNd4vnh9~d0?U1PWdmABaA*{b!cMS!ht9q2=xdh=C zwwr-#8N@JZPcQS6W-_%ONP7N?p(K1>znPF(+l#Vf(#{JGyF7*P5o4sV5kHFYxNZir z-reFx=4o!DI_4JV@rVoNKf7J~Xeu9*^=yX5)SEM7;ad83 z9<-OM4X5d5_L>fQhc>3Epwrq!ky>_>=LHIAxw4^>@!GU+KyAdsWE4@K z3^SkJUgz75m8+~Pj&JrR$f(|(uxIarC2`X9SheIQn+x#TUEjot)DamId#>NjdB<*6B$9SU~a?hohEM_=~Dw^1m< z%$`K_?7GG_7oFgbQ-1AOINy(tXBN4#aR&9qBj06Or<2tlmq5G}xIxUJ5lQs+k{Stnp6&SRf#^x%H}iyTA}u!g{{^~p0oGy<~I zwbT^m%U#=tHREVTB9DWHqIa(&o@;Aq=}11##hE{1LyqQhLe6xgfDoHJ$Pe@)M z5>7+CrwBSJWEQ^!3`Vl4;B%#Q+OfQcLMe7Ykx$FTEVGP*(2gK9pw6LW`jkDR z-ts(X!hR4#yE#m$j?OS0hb%VBx4j3z>8c3^I=hzVKKBBNr{N@GSrXj^Q%!)ZW&lNy zQIvK%Cw@J(Wg2RQS`!Z*A8P1y`)yIgtBNlTYE$u{dK!|wq+=}0X0A~gKBmaKMN1hZ zqyfj5AzG`Z4Ksy?3&3}?+b3+-D|ym1K%)^6%!sP6>W#j8!|E)km@p&&BjJ6I)#X*U z8aTO_*EaJ%y*7Y9Ye1kh5N~Ea>EB*vwEbojDs}?Sj9N#+RbZZZHOq0lapG|e3;+gj z6&QGC3yMevzTF#n(15eg#uxZK5}7Sj0BoKLY#yjdgu}h)1nb8B3PB!(i9h>S}%1`d!O^Xp7@}l&sD-u`(Khmls zR~ns`?xZVPyKe<0&Emr@`*y|5z^abB&ORIX(DO?`^B)kc zUqn2)$p~0&6LJ0vC!_c)gdBJr9y!2v4#b}V8z{)>7WV@f7Xq5vLmnoVL092P-}RVs zCAlOx+6roy0i3NO>{9?>R$%>Ac^~+(=EE%jLtOBlhDB9jQRnEKb1_T)fORHKK74kD zkt|5Ta0|fx6gLK7^n|BP${+WO@X*IUW?^dg(+_UTlHb)P$emUTHt;d7&;w9XCu)FI z*F*RFXGyp4(V=@Qi85-kVVL<2Q+B{e67@t-ou-{uY$gf|KIG%HaM>#?9dZB;OYIKW z9s4*1o7uVxe;;Bf#S5GP8#W3+v zv!{1~{4SvJ4AZXB{rf+bU8J?)`8(~pb-W0y}vQ+s^zW4VG<4lyhx9WSw>Ww2t zRnHmQ3)$uE%ew;lH&rwIGOS#3N$!EZ$1g`1r}MMT z-j&gqF2sR3Y+*oa;&7(2Z+)r|-u%mgR;AK1#Zm?dK?LLST1nz#2AH(QJ-woQ7BR)~ z9(yM-4n%)RJqnG@BDs3~688O+_Wj>FEy<< z2p;72II%SW3^5&@+bg|m8`_URKqpx@S%GW^^`;S!i@@VOG?WFe7sc^qX5!Jn5caf! zYIqnRQsH2g%w%FM4QKl|_RYHukGn_5$b_i)*AR?^`N8YVr#%u9gL8(Qza7E01hkH+ znIjK?11YAU)45Nx!Zi2yhhS9GlE?{&4RUctZxl~`Z)tcU%l-1;f=nN)TFzKY$24xF4VYe8K*0 zOB1!JK%p}1II(1? z1WKOn^pTHKslN;|gfNZotP5UKRGnmZ#ku#ujCgrEf)=~5ngUq7tTG0ru?kF=RO=9M z5x#v7;F=4wd=P5g455xieFS4%Vz&MDOh&#+d5K_-@R&$IKu$pO?p?_9KKgqJUV-b7 zzVbrS08?bq%V2eFJxN@$Z=UL?u zu9vHw`(-$VQ)>n5J+KTWBb zT*t3+%0FpW9{|tIPj*_AK+~db1`UupSi+tI^uMfV%hRbh{!?YNiP+AJq9AWooynbq zI_JVDvs)4rS6(GUBQOQhXaQ{dkA>Db7a0&-L_0rWpudl6kb7I=JK$OVwl6PuR(a#s zph+~>s^|k}EC0OCz@+F2g5g{B@jCX39XoC}WF^RxnC-xD%A+k1+muoG<9J~X`}A9b znuDx+Ac{eQxFE`dKS$9cFxYE@cwci`A;SuhRS2zSSPy}N_Tp5<773ARS~{^rzE>>p z`dund$R)xIQkteyD^Un0NgXk|(3pxO^y7{CHIN3DXHEwJiTX%rXD;Yf?Zt1|G%6RX zi3es7?ktpp3d9|=(Ln{iRJ+XugOR1SEfWlt6ydK5K~pLYo|ziU^NnJt0HJ-N z73p*xC&*FgKl3(zZxiFIG%N9lh8i@?z^gtca6p!SguS{;LJZ1MU~3>h+-H_bwb4dI z2na}wTXg9SLtAeh6AhA-jy4R#8)*1AzK&U0(NQD=i4(Np! zqiEbrHB(eNe)vYKHzO!ykv@CDKR~JTH{|heKW>RV}~fz%SArU|8*RvdepX3}&}7`JuIz_xVXS!a(Q z6cPu}6$e)-yc`ek2hodk${AsagAjLS?*gUKe}BWBZQHw zMV|~&eyynOdkR{C=Aw;z!5z?<7~*{oswKZ-Y)wQM!Ob#; zC)V41o>Pd?;^)+o02(`1!8sc7nC?39+r5I{COE(I(ptX=nzsG|Trtk2EUcmDdT!mI zN1tqW7EKoTKK))tNmq5|gbylY#R#lFJy`gMuJ0w5!Qm~t2@|>j z#8SbA$>VPW@@4K$I@tgK9Y#YYPUA)GLq8-|QqHE4Bga7ef7D-SLanNp|>6x`z_IF8}!7 zqt4{Xr(>+7=f>zmEwf&{=%2A1gO5<0SJWt!y;>v!s?MN_PySuf&NCX+)@ibPTE#MB23(wIlr0x#26e3Gx-CO@ih)x?~;%{enf5}`uaKp zr0g^c=R-sg5pbrAu=u}}f|r5(PS2jegox8U2{Y7dzFykQWEL2xp1*;~V!c{Gv{g!m zv|rHLJio@IYDkL29AM9-kpQ-p@*^`2VS1Wj*ClZ(#GK5U4){UiP@8s-jg`5n4grU? zbQ=EGArH^DOajk#41~ta;z~8@FC%f$D*MiAFr;7;OjYw zba4@a=FMQx;Bty`xofy9R=Ip7T3IRS)&vVwS}uo)ot3&7?T=J{APC75`y1d@dnOO) zH{C`wUYw3BHXiz3iYM6AV3uc?{Hp>nNfs`ZXn~#Z;B!GBHPr_ikirR38%beV_r>iu z(X3oNYMT)bdXF3|gos)P36yr5ON#WWQ*$i2NSYb!&%gAqaU%kL=fB>_JAh_l0}5ih znODC8!0`BaC4Fn5P4r)f86~1ZBz_ODF9qhObie^%)U!3^8;G*$z}~Q5&UBPizt+bF zkH0i8kb}K<7y8DLkAEu3g(%oG1iS%fj^o z&6=AyWZ9wWt2>a(069#=kG1=*&sr~pCJ{xR_er7m6Tiwp%=uB2uv1ZWS@KKHz(@po;Yfz1|9 zZi%-d(w=Y5_NdQiC7gs>pSIYEC;$9NDcAt!Ia<=DRLRUVb|ZE_IKHani!Vrn!p-XF z!0nvf>}+APRPE_coHd!9Z9$H?+WbU7SQ-dlzM?dQ3Sf?o?*-8{ zGlIdYGWpHUfeHZ7q|B_*3)ne>s{TPrA+JP8$Suc$d#pjKWaKUp@&tD zA=%}nR2A_n*5|qQkfrFceHM>V@?tzm_*2_2lqbS$4@+P?@AfPqMZ|a!KASj@LHgP` z>8E3>0McIAUMYx`3KtaJ3Ex+Zru|Ke^nqV%fTnU+WBDBMl_>x&Wg|+9A3r3-4FFb`IfKON z`HYXQ)Hzw6f?X*zp+b)bdmyjDj=^7Mt(3zU$iUA%VhN3`6J z(K!+s&lyR|(|M^A38*-1`=^SB@oim$^Afv89+68hy9#0s~8BrALazhZ^ zb^PAHW%?kzsYl|&wF4*nAeRn~K}xUZV}z;`7o5~Kf5{NZ@9I?~H)fW7V{cBM_nvGSh+g#6a^ce=$T;>*oB@!#ZpM`jeO|2%Hdt`9gZ^-H zw`Vmec&GfY#Tgoe?ilxtLQ!O85hIWsMs5Q#kn$(}-DT2Q#_Ltiq9q#kAO%S%HKP<$ z7Do5d-y17)s>H_wMEp2+U3zJ4+oexh<=G=pj}DdR(e~&GI)eJF&RjlhXr92zvI_F@ zz{-9I$h>Ok>T0NK^;TOEOrX?UDL9z8VZ-{7xgUdF1xo=NIw1Aj@aQi}AaW$516_34 zqaZXn=7p}8-Ugw{0xBJu!rwr=l8NMERW(#H+RMfRowUpp zi*%MVC7*(b#ln9i3h{V_Q1$l-GRn>hd0D$@Ew5!W_WBEDomH7I_fU;qT_cJF($!~7 zi}|z|A=`4#RMU3T5X9@nhQ$;6QLGbcXR$i4PEJg2$!@LE?YXO_pVeLg=_6;IGJQ+r z0)~g^`eQnpr>?~l>#(2AbwPyDR2XXp2Un2J>ReeILu*dAh zg?N(lwS8n`xMW0!UjDCt0gnbp(_mR?b(IpSigqjEFb;5{`7WFK4FCiXWiWD_zqP+q zRYlH&pTS?ah>eY!{SpBY8d5o|23%`k;KFU&}-d+ws<^Sr+ZbG>@jH=+2(guqNe<@Sh|5i@x-9^OUJEfjnL0Pgc(W^ek zZU0IR7MF@N610Un&RYYxE|*=!;Sq6!B}&U!RV*s(*6Py3Sv{+ZND$$1_^@2!*jz>7 z0-WBcr0T*~7|v_InB6=+Hr9+DYAZ3=OoTSo;@}$>GJpNUD5n zmKT{#LP2KR>P=OGw~!G8U%-yb!5KkSYBhODXcv@V;la65KrT$6>)g?T7PU^gQRP{U zCuB)Q`7*B_gI3VNKV!3V5yA(f`@QywuqIBJ!*T+uDF|g3?cW&@ zn2FQ>%W@FV^B1>GzzYp1afOhpF?_jdEVR4b(J%h=B!a{VHSW;Us4p@TX(i=ZXqFRZ zH>KnjP9q11WE~4Va6j`jfm0wz8$p}dE`YOUb~nZ~{@r-oDQDGxnF%1q^mRfM|KElu zSc6k(!%P$BplYpsJm0u2- z$P=wQvhjb|Zeg(^JH|wAf;!e;^=Jem^E@#Tm{v*mo61vPmShm8fJm1*R^Ti`AT|V% zmz&i3Uz@Ho5<9pjfe?3!7N7Ka0*T6Y8J1o*c1o7|7l4#NVQ$oJ__;dqyWZ@#8^>pPX@HB}XKi=>S%SbPTNO6GH)*ldNRGM1=YEJuVWzyz+WKN*q1_=g6k8=cw1Sav2W@HQ}}^Jzhr_WpmBhA$9<^icehJ?dzukgYgIG-VFgH z1b&DKd9>=RD*X^gCs<{xmCnPL5&fBeSD57bu&25@N5*Wkplql*mJBM=T$PM3++ACl zyj zUWO0##ZtW-Of@X=Ru=N%$=mYiNt79;Y$~H)6=p-9nY=k4$_So+Eh{=FQczzrAiyuOPwIVz> z$Bt?0%Hs8NLz@?o00ax`CzF9?a9WZz7>w=T+D0us@s!3g(oTPQV1Egj-^)cUzCI@PmP-YDyDB@JIXOzDRqR^pm4xLZh9z&kzA;A6o#OBj7 zhY!>cm5;pZi~|k(hu1O$Wk81_sm!;oYg1hvF%0ogKQxrykf)|vo-nmo2G@)L~J=75a4W5@fh(@anxdjFNv8E;j9Qx zS}!?%C=(avU-E*xO9kmlCZx50&ZRelN)YAO2{fW%wGW{OR5F8mYx@S5 z9!eu1gtS{%RH(usHlMxybMmTarXz&^o(R!AB+krg@#V(F zCcbemD1_6=p3T+`A&rMNibX)wqwJ&D7FY(X%eG@{w??B!5z8RhnCz0%N=xZ2{fx7D z85+tQuC_ulkdXv5RfN}w4{#n47T*1#*yM^qq}C2N%XNY+gcI)$LmOoS<`{-mzWcPV ziXkUhD~%ypEL~xj<0cU#Q6KuiYsuOlVWoZcYG17Y-asN6wdbuPdCVDL^Q@&P1^2j-|R4=PU%&{{EJ4h_Slt`(=Wt zF@L@P!=;Fe$Xh?+5dD%w#XtSCy1IJj;gH>;E}GxNqxzn*qhzcsCW3jK$SiDG6#37Fd>6$-@mIg)kcg8esOt2UigG-Xqqf&!F_biz zn^ed0gpsxYm&Sa%$vyyXzd+Z+<@S;OhW{HzGBfR8R+K^QRMsp}=@@2|2uflwU0-5$ zQude#;P8gq>dxu!z>u3iIM=1;3d()!Od&jK9$j#(N+GRsti&=Yvj$)gM@)pUcXtD_n ziSs!3_CA9{&PN`rjG>94-WRZp`8;8b| zksk=8UbHa3n@le?@okp=Q z9MSyIgP|l;+oKR`d%ixo?osy?&1*cf@b}-7)zkfEQ!TGSgpo0;12;FUVJYXy$ZSIQz_;wpkSD_KMsr2kYhtBzgE>RHK z-Ts*tDVHr4Njec-cIQ&;H?^TF5JX6>eJ%H?jnKq+C`nVf+#LyhTdn`Bl_4f4GK!P? z3H1R7Hk3~0-@BLp*-W|8%VFH^kn_WIStPv3aiUgv^_cT-$bZ;-!LMUc-w6C=aO-F!?{KGN7+#)rmk0Z-8mbNN zPI1rdqR6X{M^zc_og0y+!6Es3CGAkPnbz)=` zk0wELuFk5nU$5c^`Pk^XB;q9(92TVD;bn6=GD%gFu-_6k zK?%1ZDxq?$YqP|06^7-e-$|1nTtnOdDx+9YQ9Bbe^1@>-YCHPo)`?VvVGwDltNFMx zPQEes+AeVg9OYNsJHa2S6 zU5%pnr`{an?XXLv!#HZIuq)5GH$loxD;(31-nCXq8O=s480YzG>pM|jSO zKGA5*quYw1LaDxK&%WRiV_rK%8MxSBNGLh9bitg_*cn{qyBIUaQOj=~*>s9c-Cvv5 zqmsw1PuX7^l-_u-)ym*Ckr>r0jqwbl;o~Qg)hk{4eSofG8)@>!q4#`=VOVq}s3MDq zAN;c1p^39+GMOP|L|@Js-wu2!2Z^vJ8ZFoY{t%;z;cIV8F3xmg z#RWw(#ot(Fc*$*2D~^>Lk<{c6RZXWwFXLUM!`-%7wM`T6Zt>x+9;4;bM zj?D3|b@X$0kB<^;(ohM^Pk!7OjG$@{d3BR8I5-Y4KBe4kQ>d(i;Kvch%nB zc~nrgKxD9pFV_w9e*93zJ8tp3UP zRf}j7a&OHwL3E;k><-PMx!(*F!ZakIC~k3FPnLd+mGR{)*1vH$q@%c2s-0Dx0C}jrnTqWn15+S}aTUG^9b4OWrZbr8H^YS0Y^3 zY2KBX_Xh9`=nW@l?@^45Xgo@oe~V))P7`)DaD_ zPZ2*!vDb_H%W;;r<;M$|{`QwEs()D_>FB8*k8Zw%maQRQ#)^V| z))YhLu!+b27OI>+;g+WQrswkr@(Zyr8K3r2h2BJYq@HrfB^}-_CY`sBwZD*-K0YCh zA|rc`gi|7pH6i3T%~oV&ExWmX_?$JTI?f!pqAcvm7-8Et0_ckd7Y3B>CIptJx-h>! zBK8N=ktrkul|(M@>=*Ey7>26yXQB_2$dEun?2x=8GNa1s@~&VQVK)K3vDD+pkBBy3 zF^Hi;F-OCeuUggdF%_I!OY;@zq4g9j-Or2TXtdt^yz^Xy(6RR)OD$gs#glPP)HBXc zS5gwfX0=@wHQI~3e0AL-nqavmkxaFFCH+N)%7+P=%ql{GERc$~azFcvWZ0#OkntMYWh36Gg3jLBhuY-xY}cxF^M9F52STI;m%X$IxNj|o`5W0zczP1$m1 zrV|qW996_28=elU!6)%6_Ylk~ew5fKtIHGnB(u`0EXN1ZKuJOAu{RTy1SW=<&xTq)EW^#oyl>GeRA8bwV$Kzd@2E z6!g$9x6D1ZtzA)U&-?Rdk@iazhn^bcA4St(aQrNEIUs*$u|HJNpUeA?NKl^8l^sJq zV3^^qKi7B{8WAH=St!fDZ9jt|JTNnAJ-HD)Y}hFB5IBD#-{+56Y=PJaZuqL139Va% zB@YjSUtx_%4sux^H=6aJI);J{V=L$RLv^oQP~7K)>8!}_&Eos zavy22>YthMCK0N!up8&k;2`=F(7wC?wWyvNRBu&%h@uS3Vv7(MhhN>caQ+&^x-NYv z_SO-*Ib%r_W8Ga{rUlb>wm~#glhZ`TBqQtI<~5|^Bc>m{Gbdhn8B7N9t3OxZjWru8 zNqv@@gw2asWYK?uXb{ra*9HYv2FJ@i>?n^x0;bf=dVaze|9=)T_w_a2ViD`9S&ezbhe8f*`DAJy2N$Fpk0TVuzX`qX zs7>wNwNS6nQmhHzZ9wDL(kkPzLIZ-H4w4PyFyC!>VDNig#w7O{4xuS>izDfPiy$?r zM8Bl9>%}r|rm5OREi8+0MTr{e1~h3ILAY&+EDTfKQo>qXdeCd#EYi9D6zxA@;BWT-Z5lMV)c3nkb{*>b?cBv;zMkr1QJ zBr&wEPO~1Y@RHrI>9QpS`5`j#m2>>H`-+AQR*gtfpQrAk_U(;Xv&Q6ZgtjhA>|o(> zFdUU<6Z1_lt}Q#_Frq$6U)AGVo%%6I3_$~t*k|;xp4UNqV&XQA@yrojo*iYFqJ*{) zihMSQ(tV#{2c6~Nd4le}jNe%wiDJWqFTp{;!(J)q0R87xo`#*PR4gv<+W z;*U8@hp;A=9cfwweB^Y@8_^;em5q_Cwc+k-Xpa`!)GyX^-*G>)C_Bx^Q^azV(6H+)V4v#M(bPYh}cMZl(s1* zq>f}+<#a6a*!>9u^6NvRP@xos>ba@nxlc^A$~94IcbPm7z&XLebsyy3mb1B8-Cml=A#cMJAuIm4k z4*89t5$Ex8Yumpy4>OyI!4UF7!4S^RA?FeNE5~qx`ZGb{3xJ%e!ni;a`_v3G#rYpu ziqdv?F=C?XsdWt!+*w^io<%CT`k9 zE>oF$@Kw0fgnSVOPuJDG3lu|57J^s00vjON_ow#e9zmnKaW!(+e9X~yGSqHeisbF z0d;>M99xPhS@v0l=h4?+E6ax;%l% zD`NCTD`D*RZa~sfoM@?8&Z|acN>Lw4oA+Hp0p=i29{SoAna0&X5^W&n2kE!(NY#xF z$3w58-kj24abU%sqGlwb>(g8T@nHkER_LeI7ysl3;DA}_81j{ZGU}W-PAL+pw$Ze< z0ZW9fiV`+z!yJ;VK!i066M0+V=hz*Pk4X)_XX)B>h;AWeJlLmDmR@~(qDJ0%|HzrP z!7@x~@8&k#tcpPaRRMxc&W^4!G@4XYvwI(oeXR985Rmi(9-;YHUfzc5Z2|*W#oWEJ zYQt~vWkrQ8WNy~@D zyv7tnt|GvG%AUmEtjs%j7oOPV$s&CPY(-4i3OQreOK}w?+q*>VTX_3!sBnP?x@md9$x_k zY>y?bG?fl(Mui{eT2G-~KSI@KN>@{AWo*gu6Rf|lJjBaaDktmVqSLtZzH}qb zf1#Zgc$w@A*Rqr^^W{ho2xd8SQfRmuFzkh&0Xv%j1u|3e41+(ecCL9osIcI0GLC;# z05Egsx$C4L`o0PX2ek;?ym|H&xbgyzd*1)lxL&#&FrP0MaB*teXZ{Ucv#0)8^XB@~ zE^4+{%KbBftARAH6sGr815>QvD_H|0--sLLw;JDiIouC;y>!_Bb{|Nxw{ChCPWK|M z`{JY_`_okQ`=@1I)$c8bS#_`E``WbrVf;xmG?%?PW~}!E%CFOUzK@}y9iKXk@f3?zq((i0cgeyay46-O@& z(&Ni-0k|hlPD}}Rx6jtV_9c!bo0W^g(C_Y_P2dXl{X-8Qgq>2TPHSud`MC;?3&2Nn!9-c$6APE`T=?7S5Yg!S zS_M`?-ihh%2C(UHld*q*#HQ6c-&t7rGlpM4q%zCG$M6y^2$?#B3k+bVrv|^X{rfHf zz~`kfwJmu*f85XN*iT+r&V3Lzx0Kd{y zn_yPOgkM(3u(4i@`ks*cNwtHVMWB(tV4|il(d$QDEQa>9v6{)!X@mwc*~wkkui@BS6uvo|(#{&#fk5^4J-sq*LmUv2Ja^$ z-vcJi5sUnhQdM^D2u9w%m#)z3x&`!_U#sq%0!z(lKU$s7A^pYy~PQi z@V^4&K;@QyhsnmGe9T#`;5p1r#n`I{&W7*8NuEJJh#VSB3YKZzouwX`-G}2`se)?= zvzimhF5shC&6960DhJQ4PE1?hEGz?t6NkTmvEdfEdm!f)Fl8(S1H-Bs2k!lViL zGNDsm(-Egk#P1y-u|Y(g^Uf5@X#YeaeYgThax)fv5*Bn10K0M@z!)UI&AwU|?{GnudJ|Xq)(fFcS|ybBczR?X4!D6GE5lBs*Xl zud)?h8bUR*!azD`W2&FXjUyo?_!5YYn%b|qz|m)0y+vVLtpLC`EkG-Mmgd|G5cr03 z2|OudG&Sr8WQ@mq@nb{1&+m)0nVlfygV%&;v+?DCtbTA4^d((SWOVHBNEGo$)Q6DS zcrLG}w0G<+a!T21S4M7=zkik7gS)Sw8(a;Tn#=3}I4N!mpmo>3?Yw`MlOJ^hRI2H9 zaclzerVc837M7Q0g5*Hy-*A)|?%!SI>Bj%w%nD*vEY|L=LuKv^xWDv(Z<^e;?$Uj} z10r4AT0a6P(F*w%OTc}EOg(Vr6E3q&Q1ub*Pg7lh*gbG&B9P3!X+`j{#%cKOGHMY1 z`r{p1r1>EHG#ukN73c4UMX`3*68OQfjMdumW~|II8(etwP1o`+>hYep#nC-H+a5c! zzuo-RlZG84iHi|&9(;?PDTT#iZ>;$HS`%k;6V*?yCEh2G$!J%-k4Ahdu;RZHRO(O$ z#EvrN+!SRC%fCBz?;3SI2*b@)WO!Z5e8Uw*U*MuDFJiHXjH)#F=c2u!D;U!T{VlQ8 zQ)BSd&{OYAR5UD8oq&gR8kk5`VQIQ!;3^DxbTy(H#LHJ8<)%|DP&)j;TXR>*Jrw_! zlrAIwD{n}FxsHdrLp-<~&Y>FduKcV%VjZd-7nhhjxR=x^My$=R)J808cBq`w-cfH* zk{xCRtpQ`ZMhc97`Y#o1TaL_BDFiRbFHut20u7H?liwHH(Pe6E5$uU5h_e1|yveB5 zNxQMyAImGK<`;W~{r*j!xzg=TR1-&fOC7s%;TPK&XA=YNN{&|cPGIef(8%n?oI+ra0u>h3&GtbED7#TaQEOE0_?ZBp8Ngz&9Qro^h|Y4 zRm*gDomKD+VZ9V-lxZhX1ijm$-60G{B@YrP|3E-1=5cPp`ad>dRrkVn99ppd8YH=Q z4g;`!u{Lt_5xMTIvbPz(f_|^9DwuOkR8hQw%C&z~-tYWdhkD%kl%)YBgLQ;ZiLk#w z+N3Th>pavKElSo0M}BU!^I53qslIr8J$!g0aXmO~P4wh7N24J^^WYp>x7ch$bk_?r z4S9s>*Q(pep2L!=Vm_Y2;6o~SwZ<;DP*i`C_s3t4$Vo9!!sYXmug3lGUlnNZN#m5| zg_*fhClonjQ3-svy>k$7Yh^e$89$_vA)fOg@oiqFT8ua^p^Dq_q}gTdLPGn zk1}fTQK80hFrNNTaF*7>MO4EhRk+58QQE6%>`2S+Yp9Wm1+1^wtg^yE{n4XLSkzTF z-O{l?3^wqD)iG+KUyD%F4oS|V#q*_8lINFRJvZloKTu$ny(0{pMN&orqeEjYX)_H) zTdFEXfz^Em%}1#2IrJ|cX|(Ym0$jMlaWqsYIS(RDxWuD+1P!0$rB@co9`uefDkE7U zAKS-{vtuWW8_X>k|6?g;xNldhWSN~({=9ESI*~cZ%WyS3K4V3iV=VHDjDoquR|;Nk zuxCG@i5I9CS7Nw&>_x<8p;tYYfcqh^NqW2GKt8z@;&#@C`XX@^jm;u{;7YIpgYGnW zaIub`$TfT&Ik-?R*U>>Vz7LYkkSs{Qh|;S^*2Zm04I5@NLx4^JT~L}H3q>s`@0c0m zWW+r#iLc?FoiY9l_t7CIkiUypr05tP@3T~8_2jFdr~FJ_qj<@lyo-E7!2UfSZJbEd0J+V322A?74tm14udppXKA>97 zdRaq(lQ%ATbhq;zZ?x*})bOy~@X!qW#2&6!J7dX2sgV_@fWW?;#VC(}K+Bl7C)}Sc1MPXwV%FzF)&jQn_jdg)kdB_ zVjgl6C_A=e^d=rl9oW{yDv!6p%|a3&tsQLscSGt>B35O|4nB^m@*XZN0cqAO)ev8a zYt}&O-L3b0i66gcKu9=Ed;ood%^+{dLXMeC8SQnUi_ZNzFK9zB| zy6#9&+i8gyUUe>M;r2KtZ661P+B>_KK6onG~F z?8nM7pe*zGBy(+lp=e3{HW?f{s31M5y5vqM<}knq5y1zgs@_k$2*@i;Eu%xIu9$X# zs&WKEhgu^L`*W80Yjywn7KKQ#lQ{ae}mhy?Z?2j7)##1RkMw{>ov+Z6!fi=3g-Cq>P)vNAA0g;Ne#)%%V-B= z`!r=J; zl`2bSJMM-5Ud?DYt$tfj?rT&B06c7NxUa)Q!o$9N0f96Me|dKp7%{2+?#vzD;Wf8d z3TKX0(eX8IKUW)p+8VDL6K#vGv2?IX!!E^pr;STN)vYKp43r*hWv{&?z62FN%%+=4 zK|?^}%>uBJ#kHdHHyGXJqP^_weBGgT99pN0+xEIyU32gRMTJQPs?zcCXPKLCxC&!N zt-7#OyVbpuwiH}RB{)c3tcmMn=NnO>$T)$BNGbhw2C9NJIEbFiALxe*SkPo%a za-;V!_o7N)1Bu|59J3~g;Kj>wevLVz^$^{1Lkz2BlZpLY_%n?l7yG5Mz>$s>w)Dk^ zF!gfL7)yo@!w8Q^?H8uV(g?hpR^I+T@IA`NI4f(`k(8T8ZMtaC)d2sW0Y|wvet6+m znDIJUXAL6Fd*)#&)C}TI)ku72c5dE-d;mXx^D^L!Rd=zG`O7V4z7JZ+FuaQ<{`tqT z*c8+eIzyu~8ZFh29KwIgFKAfzqUZ*#OV=;WAOJL__v;UYm@jrsY>{tLU_{R_qjm{r#@%S#{>^P6XAXy6#k7T>)K)&;^q zY(QdxmK)SY7*6IRY3K4G`WF~vQ4sGdPi(Fc3^Wm2BM3x+nICpZamCWt!OW?I>;$Y} z-$0~yJyz1Y4o5oS4NHXWO-MRhw!aT^nP7JKLISriJj4X&t%}Akyb$4kjo2A8$}CH| z^YJ{^hkr|-#q{OVV#LTvTIGAkSY!2)^wf%T1iXXPCFokBq@jdn)aCqy>ObEldphES zP|)z5o*l%iLPer#n1KKQ!hb(Fz%VvK`5PNR)f1f&(dz?4->q;4I$9XdB35^`;^a$U zSz#A>YkyLBv;V-rw2CXeOd)QsMT^7Y@&NQlEs|Qp?j=1f@!k&}DBNI6OTGE2+Ql zDX0V)oy;Zq__T~7PTO^e!V9+f%O{t8MQvs*{ce0jM&kop{<_e28IZi6P-bVlf73yt zxNr&Y_RNWStwUa~jcr(GoQ0xjI@TiP_$yjXbt$ycohhbDHC&;&qYoHAwL3`F-0;WS zqH=_RnejInJcV*<-Tuz1B1;HaOrkW2RoBhXpEh9}^@sD8$j_x$cb{vHAb&o4ex6Zr zWFNA$q|ynCl|50U11}TYQ0c#1^XlycM(1@nLB|Ys6VP1v@sTWqTO-qgX>A3pW6+2V z3C>zag*=`@H`$pDg&oW_BntlM&i=YHJbyc-@Fq-1(B&@{oKd9}FBF$Nbc_H#?e`0{ z7tNHEdw+HU?y8pnF&A;$0ElrU>de_+qxin3y#Jj|>gc29$<+sCj+A(^y3|9f(4b)+ z7u|S=*{ynkVgx%o&}5iB!KBl-(JJhlbm6uUXQJB%qDq4{?fg}Jwzd1R@DyIZqUVE3 zIAPVd)SZ0m@`mje}*K6J9^4a1)UH{MBSet(OS7I0B!o!!caZq_#y@N2|6 z2QAVjYPK4po#Dfo3*f9+{N}&ut8lIuAE|Boeq9Ykj{#CO(Q{DxJnb;P1i zzEXT>`{V(aQbS}PFrSa!=*`^%J`ph^iW`kcux?(j@43HmZ$z)4Z5l>$U;0uw|GSKW zNROLnkrqpHS1ou`=wkGXY3&9OW}Q8u4IcPLFB}-A)v1g%;BidXi_$^1de}tcx1HP5 z8u^WYfw%pDXOHcC$zM<2wq{$^wWv8QB6@IbJa`U6-VW*&*5%-I__3f5PMAUE>)ReX zWRTH4NM+mrj>z6siv06DRW*nDdB8i5lAR?4<>_(LdpVqD7-U>r)-FebBZV{|UttQ0 zcU*RO4Bb)q* zS8n+m3|Gp@${dpHLE{}M4^a``?Uypw&D>)VQ+%Qequ;s$diWFGfBC2g-)dV9-ISpR zx|o{q{D4PS-CzweA2x27So^Z2{7hR>ZTQ(PARXT~wVvVUlf12Gs0#_9ndJ|M5Pfgu z&XsqC%>nY>{3f-R+r%GgHFgCb!HCZTdeibagq~2XpN3a*9 z;`WF0FVapJ?>Q?LX?C(~6fwUn586k448vQ3*(x{y*4w!F`~Wt$l2)1?FA=-#?}KwA zU3a)&iXy&SQ99Ygev$gAZD$@xQ-*@&vU?j2C-qT8ygL<+seI57KZHFG-fG)=JT84R zDbn+>iJrI*tDo{(A5C9z{0hc(<_6ct;_a7)7!C7_~!;JdJXPwQJy zxbsfquqGF5u!zB7=0$=#$@K9C6So#%#)o-J}FkU968BYm?{8N#*H#)^pOLbql6%!f{ zF0qVvQ?lZiCC@Za-aKZn#e|q_i4d|oAs>{>eZwHsOqu|X>0MH@E+^*5cd4?FdVn?E z{l=^crKX3!lvaK*(HJFsuj;c*I-@|RAVkxSIGHqfeJ}1$xfSk{^G%g>X2piF;_$BQ zx?i5uMag(MM@~6$Z=n1u?m=!BmfX51ciO0=@hi8FWZZIXaUSy*{`kP03QL9VMoA10 zrp=<_CggB_=>l6r32s+lAjrh|f-|LB0=`j_((3SCuP|oY{5L;ZlL2aWemH|ezqY}t z2=wI`hKnN*{`_-4LFPzKT4fNOfk#N9Xei;syg|s9ot=`(m2-nT+D{_V69lD1FQ6KUf5vAN%aC69@0#(%qYb1Fbc?6yd!=j64KYl|t z5x)+h)s+XGPF%<(Uym+wCe`v$gikX0F*DLoz^@MFOdIy({~;DPM&(s zR2w7nUg-YiZ@G*CtNc29+n8ak-Jf@p(;;KrkGD-E(gh}dyiU}S82pcqLc05S2JX$d zhrV)r^JAV7O`%MTGTU=gA0oKbxC+cgiT{vJjlEk86uDwZq2;i^8A8Evbh?aB==gdQ z$NdT3p@I4HFNN-j#4am8NoNhJe>)M}A0Xae{=@Wx`8zT8CULD6+jHo@Yn9rpy5 zLLXu)v8LD&Q^YFLf;nt*cjp~%wZjc<2P{*k#LtHKIWDgi3EBz?@{~mVWy3^LzcDzY zT71lZXpR14G)m{Hv~#W%mtBnaU0y+F*m1Z>bM9^65jpXzCPheoy3~VD0xzouMaqOU zz5@ig&8&7qXJxgwO(v2mT*NKYc%5~6r9_t4W8JyXbr25bzb03JnTNm_vy`IykaNPz zuV{brtn|wSnJ0+7;q8L=aVb%W0!WfqI#57ibFpG_kBs74l1(xbZ7JD0uvqQ0EG-hU zJ&)mP;K1*@n4Ek0m~Ms>Hno&(v%>2)lAMh?@Etea9iiOwJJo-jBU$OVkt}`Bim+|Q ztn$`K_4nFlJ5G2?64$~*s(kR+%*gmC&=U!Pq3z@b;{A{;IlzoTEzw|3rl$7RoJ8f$ zjebG(pVFtd--(`a%NlF)Z`KuTmrvliRvC#oK?b>oWL!B4#674(gxbB{hgX#@prfv; z9A=J<+U17(rD>mb_L}*QZ$hc3=kIV?zxBpaM70$29mEwKOQ(c=&poZk-R~c*x~DIU z$+6VLSuU^l>V$N$$g?dVYUCRhAr1IUXDzv}ku@_zf4G~Pr1{1@?Z|%k+(i6l?X+$0 zqYPYaH=*0^_xJFKJ67?Z?cwJ2`euVx zeC*3oL~W)lVhp;97Q~Gysw@S?7KE=JI9btrhO`uZ`)P@g9#woP&ctQe8hseEue?qcf^Vm8lYLbm7ZVCu%X8D{~5U5v_-X)B%R47~r;g zCdjq@qQgq5r;Jo_lI9f^`q;FL|nM({u+9eAzipH=k}j1pa^FidVeqP{=O-L`7ZhLqz36%tnFZ& zWfQmY!?l@rM>?h-jVf1pLmoW3zX#%f){mo__nyB?psXvNFZF&y;w2=`VZta_qvDO$ zauC7o0(mDYj_Pw-hhQ&3Mzp#Ma7FvlUj{M>Biqm>iGW^jn_98H$txeg5L~tWBmzp_VaCat!SI|gC1LBrUtID5W0j4)jsY+5AHE|MvQ_pvcWvB zg?Px=xi*J?^rOMg%kygCS+?xRWxBujlN1B*XfplX6rYnTgF4vpzUMuwhgkR!1@DsO z?#o#i^nZ^pjFq3EcOdy2&OGfQDn4I3U!)X0-qKL{=9Q?Yc%SC)r`5TCPzClmZ5-H){dG%Q#`WbRV}JUN z?v!DN=E2xk-Bi)oaccvy{o!JBV=0%XcDf$}GNbc3ajAms{3tz3GvbpQO z6D;2=M&>_X6c&YIb47BPHVQVSxSPeDDA=dr$H-(+r#k7)vBb-2e;6F^`SjUTN5dci zlv!`5{cPg4Ei+*q)mfXsB?7#{u+rdq-nt?VFWM%Np8{+ z*amy?6umkj0$dwwsIIk=)g;HywNH9}R7vT$Dx7A9-8Uu)mBEkTPXB2x^P2cpOrvk0 zkgIzXcPle?;l6;?tc|#ICbn67H@k6UyPIjtHq9!IYWZ!ElTtIZlOz3v$IanF_?ne} z#7H^>lCueoqy4HkAH8VVTB^r7;>g4io{QRPB8zDp=K%zKAm9l*_#QgSCG zkXD&(4)ZI)j*ujxD#MjdtE^Or9q*OwU~iEZu9Ll(n+EMeTi$uuB1ISrX1L2~gbhQm zE+Y5$T}Sh;m23WIG(M?7zCYDM7+I_;a|1>)dwcC}Cs;9RyYa4fEgvwN&lbFZY9qUz zfdP=4w}}$na;P$&E1KOM{!p!?({3}IBZy(g?IN&$s@qNu&#l4g&Z1QdE$Zx9*p$zA z3grIH3;}CcOtAi;8zyykm##ixfq&Z;y3Bv`r}7G2n2OVmAgIyps_%!l z)76H6L^x5N@Zz1GbNF6Ps-YQNQ3B^5qB0|*cS^dJhT7f4)}jx7KAmE1Qpd%2E^GB^ zrZIRcl@53@KJ!T?IHibZQSV+L11MGns&sIYFu;DFKh2N?;IYebSzx9mW<)bg4O#a( z{$xC^Zd>EEQ|6aIkDj2y4p!_hr?{rPMGh`A(c<64`s$B^h=itXypdKY4`WtL0(knW z;x&?jxD|Z&R1p5wRUOZ`kKgUV{T^r`UwtowtviVtt3J{8Z;q@HSw*;E>LV=>KY#S( z4$$#JKZ^OS6h#?PYOy>d>(fB=aRmF%VR&He=;gJ|LAouX=N_I2D_3Ka3oz`4UapI^ z=Es1LV(xx<(drnoNH8-AOW4~ZkGfM6en#W@jheTeX+On6PR*SR*BUz8h`YK{PY4b641biLvQulm^oYnW^>(=9zlRF| z1u^NpsTO*ZFUI}SL!%^xOL@xZI;L3JjpI#$d;Od^AcUsH1O7z`6D=;zSuAfum9 zJ>&&N8239X3($em4r>G|#l?ss294rDioS-ztA_N_n(a^>F8YNCG z(4?!H2UVF4T2HlXrW?!OtfTq$=V}+>crm8V;D4deWzX>~A9-{9`=elc^Am-T&2UXQ z?iSw7SW9@)g(hzon4=D~^@+rnrDmDEbM%o)it2X;HYMU}%UsXiR>Cb7FqYU2+*};t zTi=+O)yJ}Klt?sC#AGH#T#faJm_W9KVFi?aOvrR*!%lS4Sq51pSakorK}M$A3b1;v z@_bV4rr5p_|G}EAVes^~a-lP7*w0?sAzm!a>R^28x3$jl$Eooz^XEjUwxA(#+g_Qs zsFg3Z=daF((m``UHt!JZlc^~^Cv3;6A7NQSdKFp(up0VedI4TnqGUlITkp*bA%mPx0F7=xZ~S5SziS?!>u+MKH@H< zemY#FgP*so0A`V*#><-~c3Xy*BdYXg05pg$t%ig~0p_j(#0$s*;$IOi>!qO{=4k)urNaN2kDW;jbGoHo>M#G;{-f2(1;pAD3X~* zH%5cowdXoncvD$Pto*mN+(`M4k_T;egORyjCi)mw?62}^MN>(WX^)SZ@Rbg~hA4Fk zBKU}c)M$O*ZCqK3vdw869S(UoDUcly-EBh!#_CQ>*2fEA4pQQHz18A>eXCYbJC6?U zU{W~L+MW?-jxYZkzJx=ovWE!CtEu#05qM@7t(DWcB>GtO9&TAh|6{BkG&)~jQ1A@4 z?0?tpb@F(X%{;iUd<_svQ%k5SYl&jh0wtZ5gjaimv@3G$RXHm6ete9!V7j0z>pz{_ z1_|@|=BXn$RlJxg`cC)v+@s$U87xPfPWqPA^ZcBwQYz`ZB>s&r5Vj>l$jD&Pnea}E zMiF&tbR;WHb@r_{>yMG^VnbGH5w5cJkZ-bSV)4J9nCv>Q5Y!Z|TUs~-evDOH5cQRz z16vDNzG!l}h&PdiUXs(KiNQrCrJ2oSk1Wa5+luQ^&97S-p;%A?<1J-G#_^pigBJ^dABH&5 zzg*s*3oq8Pzj0D0LNRtuQAjo!zCe6DI5*XvMK+2TszYtAZ7CkG+9!Eq#XfYTP!ucMJm6@=%u1Hf z9?U&wt6TQY$s=mJKVA4Nlw)?!1N~=J#DQR$wT|ObQi(0i=aFKBwQe=*Pw-QG-p{T} ztPt6}cLZyWqC-Lq5975QCQ})SmajNuM9|CnYff(t*aSa=^;r0U0BwFNHM!)I>&Z_q zy%A@9z1)^@cP@))>=(P|m74i`ieQcJ0Zi+qHT@?d-|!=RK98B*MW5NqViu`kgvPe? zr_?m6r&3z`+XdB+2lsI_q}fF~HUqx6TTwX1^kA%-x^9^5?$oum64o^vo0bTf#4ur@ z1XM6FQf+TgzuOvcwLYT1QBaR}(E8?u>b26uBXer_hl&Za0rxW9K8uQ`;dhptZD7jp!u;e%d5tE!P6TFM;5}wyDYgkWA-MKrKzKOdeyu3;D!Fnu_ko3 z!_U~dz9BTD74su+i(alPt72L*R@ocL;N=Y9zP+vFA2Kj-?Bykw0QKm3n_PRC1ZsL! z2`QH;RVaMk(R4#*zF`p}z$=qg3esg{shRnHsjD|QYub?(^4Q5^QYV{XaNB~=gkyQz zK1qPUlQ6rKUM5(^ByrM_L$aHgl@tNx)>{7%Pv!BeWL6oq<6!v8Ms;2()B9?Zl|b!P zV?f_0X$Tm?Tls0ji=g3M*7k%d-=lBxN`HKLsaW^pxT0lFOgUje=a+#1f(Lo>G_+hh z%3Y&`(yH2#9UUuWWG9v9_>Md0I$Z0U9>T8{yN~(Fhao-P4?-C9i{hZ=j7a!$vUA8UWuo3=%LwK=sUjSsLH5{uiBB?nq4z93J>CpXV ztyE;)ShS@)k5EjRC%DeX=wa1hNJgI+{xdJ?8M$MvQi{1nRy+b#rfQX|)^0ywU!bBa zK(BDouVr9b9u~yR<7lwrZ*mVQNWG%cJT)*WXsVoO=z6~#cbAOj+$pDBj@1mm$*8-I z5~2K7R}N9T>8}PSQ;4yKgJBFI5{af*(ZRBpW)GP!crkCIhYOURqRZX8YU&+CujUwrB?RPE)EyB(`qLnV0TM5 zgmFg6F4@4`A_dzfM6hs7GM$^b#na7ULf*Le!;bk98-Pxoi}w2)S|(l;b+PggX`U zPw6f`LFsY4DJHT`f({Z z)(5wrSHtb4jDjsR|AkvD!As3Jo?)KxLZ88I*?gS^$ANqnD8HyZ3k^%cnL^E4iVMb# z3xw8WhmrB`(R0@<64gbV@Qf%O*7*d@kV#^HWE10rc*M?HQ9p)wacFJc5C0ZclTY}e zf>9IB`-}WIR6O{I-MGXk2BXHVdY<4tG6Mbc>}k}q8hZKbGwNfM(5myYdp@ekMD;Oe zkOof>p%k)7?N#B9u5M}b#Et2@SW=MNccE{Xo+RDY9T#5VQGN&BWoi%UCe`gC;kZz* zKhk+Lc>)g_KsR~{+3|n??jhGs?dFe$f^*t@MED(Z1_%bGUh9RLzl4sKzL>bUgpuk z5Q@9944hvI^Nuq`n!XKtXRcg&y4#S4&+`a9As(rfL{LIEC=kVU}v<4+N;#npwRU4C)GXsX{Hq`4HUU97z<)Q@uOQnsLxB|k ztGEZ*PX^=6se;it8>JSDv3QI(-Do>6&$!6M_YOM0^m z5T)iqu4$?Y8Y{Gzswi_)t2PPWdz8!Qiw3J7awP zQE_dF{;V^n)V~9UArJ9wse=)_x6)%(^?^ne6;_j+&ekL!&2$e34HI-yVdX}BP1z<4 zx6rIvX5|8tdS@?P^NZ6O4yRQJ3Io0lp{{` z4ZUqG?WxxKIzIGe8s(roBQux~8qudGSLl zb9wnQQYn<@3+eF2UfQMoT`Xym2t{)=F`<7%BosVd+(SUv{%g5%;Xc&M63Z(~VQwk) zKp;I({j`ZG#1A}XnIBU{r{xLR^=LJ3^Gej)D2bM2bTNt4VQJi1Q-t@FN^dv#v5_?d zxG@kf@z?(N_Uf>~_!{o1#yvRr`s}HGX|+k{IZAS1bq43{-zBfr&2Eu*+p$X`?7i@X524HZH$r)}N&JkU}EKcF^w%OI^}4Yd3E+Br84oZV?~hh~H$EA&0`r zL3bOVI=^2D!wR0R{DV9>BgUbyjZR*h9~Lq2zwQ5p6a4=RHwgE?`($8yH~{>Ar;7i( zR^v{@bjrEV=%1pl#=D@$cDu z!T$?n_%AUDb_^G-p{9U=N{R|Q$52v~)dB$EVTbU5H%PGEt>63;Y=`2eXy6F|VD|s} z!=Jb>DewozKv#2d{vPjacncL>vSbR2qk`h^kHvk)=GiD*V0W zJfxQFJTunO@`&2_Y+u4T3$;s8;AL=ZB6zu*i_{DLyfhTJN0{dycI@Zgh}m8|IM!T{ z_P1nCtv{@J_WBlh-sgkBM$QOMa8BseSWflIHP07|z%sZG@(w4=(03^M{90%Ve>}x6 zFBK<@_ow!u&(v;0+{pS`O8`aE^{^vA@{=IWFCTC#e5+A~?(3$bJmT-47F(2Bd~Qp_ z1!GWuLN~NaNqtckOF@9vTU9_Sk`GBmp5D`8o?`E!$`y45PP>1a1XMBGIguYg24LAZ zfQUmj=z`Cco_<{X;CfV43HcaOrErp+BylJok=*$MNz!4Gek<$U-B=KnS<|ovN%lxg z*%s@T$7~OBvaSV?dchXBMZIOVc~ zqe1P=mZteD$1EXrpe99(kS5@0G6smh69w`LDMZ2;@RGkq;m=H9VKsqBG+woP?2_y}4IN`hE*dZuY9>&nF9^O3n@;3vE*T+ytjl zu?Y7Xb6XmWE}s8w+Xy2U@Cl2EHW|E_CEJ-F%zG(ZKiknZ8lQ2-h=~RgT3vqt~ zyD9xR?0w%=pfrJ8;h5m~EJ_r$L|Wm+B@N*?pY)1!d^iv%sVBt$l&B;-aO3##T%yfV z-pnusjTyF-0WTndYV+_uC8K?1kdL5U(3xe4qF5H%C%i}8W33SS3am)LCL$p=bZoK_ zsbT< zqduO#U}Y@35-Ob>(@1ssc~)Td2(Q6fZgC%M%*?>z$b~S;@CtS`aIP{11kxyFiJ(7X zTrnApIe2m~iix)qB+t7e!yjS?TeMVjE~G%1Lhh2l@yp1MBv(vYV<#T#>H+LNxXJS# zT`Bh(rpnJFbB!JqY#?AFm~bW6>uk2`iK8mt5dN8~9w&Jo-Vp#rf2aJ6GTW$J{ud;) zYr;hui5zuutGv|&!JLr-!yAvrST~h^yBfq}R3b z0%2ewt25H4FUQ6G<{O8|f4ABd7h4xYBw(!SM#@4>&F&ePB=% z-xk0hC8OB;WbbamY8!r|eM0`l zCmIDF9EUSOer6SoI@xCc)J)3GvIcE3h)J+lke>qT7|u4YR=3zIlQ2NKEn;q@_A}TC zSQYQ_l!V^6pyjHr*lT26;evGUNoS2;Pvwx4=1DUW1@E(AnJirMNW#5G{Eq$!tM{2f zY~e<+3i+H2cHIL>aur?z0rM*+ZN)-9!p3`1Q)ZyaF30K&_%v|p-_^S^z!3b6Vg};8 zyCA?i`^_hWN6~s8H$tU#o{(ndUr&&Zb~}x4{wRg-$l#cO!8jDMTHih=cqy5gdtqY? zA{DYv!3W6)%&R9ycw-);gbbC0mIn(0_Jxri;WqXQno1!(bOOF$O2gxVLwGD88b}Uo z>N4i|2bvG4MyVFKJ{%QT>0L$mWdjzhc+shJu0=3GUn8QBeQAJW{<#S>g#?Osy0CEL zWr|-P=CLhMK%8cY{J{cBem`j;Y^0&KNj@dozT^Fjg?vtc>t>8gPqT|7>VRx(h&R|- zkBi>9bqBYqN{HlFXtUx%5|}G}LK?4vh_3B2T}tXASwZ zBk{X*;oWS;t4fId?spZ3QG{7cA5%C=>Q`Zw9+!RviBiL7j^pKvBP@TG7W_wnOCPgP z$_=W4Z1`seH`4md$K7x9ovF=sso8+fWg$86(Pj7#^~FG@2*AENKj zj83I0`+KpWA(K7n$*n3uEVad%Df_D{uMv-y)y<+f1>z|YI~l<}cifl$TUkBdX-=v` zL+0EWYet@?@;6A7)Nc~{gF&7(2H-JP$A@PZW}-js6db%=)m$UEV`OX~UmVT38!VOr@2l4qG~qe(??DG;^-m(vTxd{=)#` zUobafvaAbLS2$&?r=nX7etgM;zSwR&S3^#<-gx3_Y;h;0e#VWJ*>Z+LeWuSRLkL?K z5V3x$pCXGSkEwCD{0iHs!8-FmNT7R*IEJm*mgld;CC!5K-Oq`Q4^CS+I}(}3wTO^! zpu4~1f%fcyiMp+^;@>^1mhNsC6+2c?+fyE~tTIlG%-VvGO-^R$w?0Es`l(Jk=2O6D zE{uj@dWyA(IoZ-ZpOU%iKtlV2Z90t#&I0F4{N_4Z~ol-;MoW_PmS1Y`*lTXV}R zz)9qBTG>D(`f#o z*M|oD6S;ohe%Qyrwm@)&DPD*vF7(ft^g8@|N?4W-)rf0q&yhu{-Z=I5+@Y)lPIP9B zR|UJA^EpVQ<`uLB^sh40Wu0(TcPSCx+#6WaD(gt^N!-51?uh{wmP4C&3M{kNR6B!2 zm_(!I-F=g7h_IqDXFbT^eF1t3$eIR>fL_M$Ko=D;^ml>fIBCs|_TZegVu@Afx-2ka z8hEff`VrX6(E<>*D4$7f7X6#t`ZMnJYg^9-&k;c7#W1ItNA6Y%=85Rc?I(*pIu*k! z-^M-6(X7QnA{I_Cq^)!htO;Bt$`v6c%xUY@-U_Z& zh$#yC+}813;_^s&_mT1n+0Tmu(S+x>q%!GnFK#fVohJu;D~X?1spfBmr|Vd8NXaSM zPfRd4q$YF~DM7D*@?TP}%5w;X@zT!Xcdh2#XbGa`j)P=Uh6>zBoL~)wB|LCx0>eOd zL=Iw{o-2u$Td7W-(lZ=|@eqbsOmgM5&CV2xbL}R&c=IgkU+iFRg(dX}N;xH+?66p1 zoQ_IJ9x~JzzP-1K7vHEz_8yZ+9=fsG^E0fD(~23bXip1?6Ec zXn(qdxdPJ>{sAXA-p+9Xo)Pn1XO@R#z=L|Kn574+8dSwu0P9i9D~fQHP?%RVtkd3e z7MZ;>Hm)*Keo#^?(D`c>FkXiVOT5`Xo1CJMZbN2ys=GJA>&0{-6Tu1Vx2V=f_|v%g zC-CvwAIL5k?`aoe3?}PwfqNCchN`dyVm}gI#vf60+@a1Mo+ceppTzGYzxR3|)j3Rb zDW2I91e#!cLTrz}-4`1VY(!|!Z^qqKQ5q^o5U=1j=`p`7(usb}e+(6@Bm{J!ON7a- z5Iv&1(cN*8^$@pX`_a|=0P9rGd=Re=<6F}ocq+J-aDu1h7i`&xdy{|5t`u5}x?e2Q zL6$&0jzKjJb-Pg#zRfL^OvV-|gWlLz$WGepDxHiqR}`qZ^4Zx5L7VAIT3h(JeJnEp zV6M(1%lewT*}h0!29c!4P=U$~!@kFTCt7>su(7D%y1`00FiD8&DG5@`JW4-RpmPl# ztd&f1u8Ks%$_}( z@s1gbj~;9@pOETZ7Jwy-S?`~UW5qXC3?s4LHL^-q2to5q2DYqiP%n8RfQ3_qUU$b7Bh_2s@owv**x5L2ioxChkIzV=jfp2OW&x#iA_E8qp^wzRwo z_qVfpGT{b;_BI-QZ3qB-awKseb?=M@dYs7_MT9H;*pxZ<+64O_n*L z)Y~HNW`ttEnyz5=>~chi`2u>5;gRf4LPP5!StRiiyWh8mISSP*m8u}Bb{bJxwBOPJ z%@>(R)EHT)&-lN@M57$s)x1E2Z)rtAD~GH7zGbRQ7F$_5=q5uwiOo0Ww|{Xo`P_zv z$i+f^I5ZZ@vISsV%FHo)?iPH2F&Q8D)_x}U=z+G8bBIFPGj&(BT4wj>jw-^(Qg&ic~<>2>cZJ7~g#SALf- zAl#Cd?hyI%xLaA{eT}_a`L$XqYYxi5h4nX~KOvaxlyr6?Wb`M$mL<_=qn3tqN(-a3 zq+Z%rGpA0Mvb8ZuSEiunRig{4Pj(B^y$r9J4vx-z{p~)66->|t5kXN&5R^tWIO8B3 zl2IblyoL<&E|w|h%}_wLYp~GkZ-!H3)SC3%920vVu-Cxfm8APF7ncIOpAXmlRx}J2 zV3b>w4D{m+%?X#H*nAV1{}pqlUKM1Ttot6ME-D$irSxJjxaD*-m^Cp7^C0dCC4BFkFibjDDw zffew8c=xfZo9kE1Lgn`5r6VT*s?N$SR9#UWkh&A>R#IZ#L#odw8WwSY4mrAy!^G}G zD(pro1e-#qm^dCwwyPCZm}J&%fZUz5!Styc04L0MY@)KE2k^Zym@|n=5F%Lkt-Z@5 z0O?8zByWbs&_MyUd%5KnX^VR_U``#GP(IRbcs1nn|L&^n=YR>r!Fd+zM=^{TIW|S1 zxkL=+bYdJxT{d!fyh(Al(xr<|R5JDqpQ6wnHfZr97UmL_l@UjBBB!9`!&7?DE?;#5 z$lC%nV2u)S)c09V7tqwnWCtg|uGP>kY;}idhg$gDaUoIH}TC0PlhK z@t8A(O(j77EoTVQ3=OKr8ozzS0Ze5TC=kXOnrv+c;H8t9gI83f=-v#?0yzxRVrod+0^QWV;J2w9SkWRBtktRKP@3)8yB=oiKZVB0^EDsIc0j3U74 z&k1tKc06RDan-`yw^>|t&{JqI1w|pZAYi?X8K#3}fR&4**~AexM#no*$q7a{1-VG( z_nK2mwv}OGQb^Xo#15@8C=Ki}WOy=IZsRHc-oO?huQxBo$shs*n$9(97&M` z|Gf>sZz7694cHU5|B2_TGs1hAZa_nzx5YB^PMb%7@N5bSNtveqvL6(Tg%ugH;Xp*l znbJgVwy&)h0Am8l%nL@3ZT|_1F$3pta2xzJ9MUsG!{1!|eeX&82l`dPFTkF?JdA6R z7ph$sGkaKxm>>boaKOqRc$O5T#R)eagQ?N9UIN5tefX=aY!0hT12b^h+J-=lQ9MA0 z5TLYre_Buw;D3qxPgT6Sqv(+FBY;2?T+}uO$lvXM9GD-r5A3~^FKUn4@2wmx9sw%D zVA5=Y8~#N)14rscsEChSSTUf(ga0akd%RsNMe$*-HR zcAdcqFlYlzGPLY5PCa5o37?dr5+^s{!K>iUVYKe|1z%Ky*#SZMXzG6Ur<^JOw z1M>5q$QeKf%YeO~NM=qjMSO(S0ywl{;QasB)RV_U)%|^EhS6e15weV(La0QMWy&^_ zJV}XUD^JR<8j)>AJx@fUu@#CKWyz8yrDdiPmBQGSWg=OUtz>uK@BH51`}w?oo;l~9 z^WE2T=YE83Ts8q5(;GSb(|lcN4E(oM*`g)x?jIQ5eZcCV`raJk2fTuZ>MjKK-&AGi zu-+NFEe`yRuM8=BNG|@rpqt>_an0LG(c!mwmGytfG=>@+SdS;$8|oM`G)@DUOQ6ks zF!hnb55`Xf0{^;?WLQO?H8_LpObx@8ZE^%sc&Zw`=SrLzoJBKzEiMf&M*>va=J477 zBn3_EHhBELn~OQB{s66ij09jmI!zEbDl=~5`T2QNh zA2bWiL}-EwlbVO6k|7Q7|Up0>umF$}4@=s;uKPw7CC1LNzh5$O)EV`2d8|fCOE_rlFrw(f~|J!M=GXCmgcSFXWEP-nSwf0%5NAS7A=qdDPXhSX745 zGl|=J4|9t|QaI9|K+JY}XeKrM@5!ExB!&Ig2;_-7eKp_M!*f5mn4Q1ZXrmcLE>Ua2 zJxwHVF-pmxuqHSJaxq4__`=EJ?t&-n=SwnI<@<|a7ADn!Y41dQK1FUIk*gkIHoM&% zPUat}gCVa%V1=~T$j<{s+v~ON9&jswXO!*Ek;1SfjzbL9sIObsr8w9er~tfFIV zLCUWz?@sO(bleN5#*TOS4E(0Q>_9GpB|881uJr+5Bo#xCAs(){#(BwA^wu{vB&$u} zwPT6*K9A!LUV~No$iGju4avA0Fwttiyq@Fa!|n(6Ec~=_5>s$6d8xlAc(oymz?tVqARlDV zLNIVO5)J~g$prE$7>Bf_^z9yCulgT>%2x{WU9^yk&8yue;-_@ozl>}k*?ySgc&GFr zJ(f~zxjEIz2E_kVt0{eDxXBG2%)mi~QpxT;fwPl$864L8g`J#BAb*}xeJgHQ8OC%< zpnTUYfG9iDEg?Xmzdp({QKIs2fVSX743L=wMgjMlDBDvkb(A?&EMTGDAs3W;%`4@kD6+>QZU0pQoLXaLpk1Q!iaW7IDM?9R= z&%8fd8F~hHfxj&JWKUXA<5ZWpw7j#tpWB_uL%}~wos~O z0VYIkYHVbK-h#AXz)yp#3!Em{VxvAX_>6cvP;7SDLKzAhc5lth^GAw*!0$Hw_DFXJKD+-i6>EONu5)%j< z(tm^rDQuBQx%f73jeEffkiv zLTXyHapW3F_ll7X;)dG{$<|#+^4Am)!~q95D)LBFbWB!>cg@Sga1dvaRq%3T`g)1b zy9@8n829GY$_KdQE8|H#X9L_6ZGBWyu9-lH?xlmua+lr06OW-6j(=PB6ExZlnqh=@ z2LAi`BF84JSvMZ3h*6uGf+Nl;l%iVz|F1(dRQJn27pQTkydVxM3SRF;XSB#-mxE|A ziX;fX1XJz4PoGdKMd#|SI!0XDINkYBY3wieJL~FnUK_Hk_i#NnyEqW{CXW4MGaZ@c z>QjWN-{aGWT%Xw1qC1n^grtul1?$6e#V%UO+bCoCMi1=WI%%jgn$();Gi$0gu37#E@sx;q4lW%dX zPjm>wqjiy$3|u%A1`=(e{Bq15z8*!tg)YxD-QJDPPHbA9nY>2exSLRGWNmZ6C_Wr0 z8$ql+cQc{k{nPm%!8|0uSA(b>bh|^;s9Ce zIvK{R73};uS_~p$A>{Zz>*ht@O&^Udj*CJZzxZk!z&!xi!FsLbfYx`G=&CW1$yF8pu&|@1T5jhTD-fU48!O}R^^7Y zx?s7{%x!v}N?z>Ik)YCy{4W~P6&eTM%%Tn@LGZ8ORn49u*XNFul6-G93<-0lQkfIY z5L~h_keNBYfAwS)JuiYuu!^=F>Wi-rDV4)UN|SPYe38OwA>I+LqIC0pt54vZo0TT8 zx3XrVf-R#*62%yoxQaELSGMYMcuw$gAlhTj6ujTqt)8+ieSwLyXxNx>}g?i^C&bIhj6kD}7k(r^&(c>yw%C6&U zpb}&b3rI--H=)#AXhcJXF?L5V+|baR;E%|~5qALp9)#|MFs{O2ssto{r`R54Lvx32 zq-{`{qsmp(=(tas^F{7{kYa={uP-|W?rK5W>!Ka543l4fiWflnV)s2qi@>qun1I;S z;T1&o^6s0iI3nS?hURIo&9HWhP1MteB7w(gjE&KQ=bjZVK%jdKRniK~>&x8Vx7($& zQOxT_Bd%}%T)?{Um_J6?k>6;m!Rej|E2I>%ZN&x(A?d0+&X%1tx*CZYZoaElhv$uU z#6wzp5NiSkz$21cv*Wl~8Rl%=gD4$Ph}Swmr7kQ~tIXFgymPF6K?(ssd*l5yRr9p3 z(v-)*?vEqYsYpiKcDXAdr0GF!-D3OpD}}Z)%n}bPc{7*7p1Wo128GENQn95E!Wsn8 z)IUa_c)!sxKgcL>OS^u0l|38KR5&3sdZhj{`P@fw=E3o}!%sKn( zZ>XliISE`B%7n*I-c!m5UDFOg#8ycM;}| zr|Ydd$BwzrAcI;#ua_tdcq@8yYG?3R#M6lGEA!K5!#=%|!93%wua(zydDtnkv&$|` zc3qFna4^p<-iZKBR1+3_ak%a6G2q0<2TX%9bM6007c zG0$1C(A6nAgPJc>^Q~vOudW`~Td=nCkce=mJ&NQv+>U=1-;)+<8u(z>AMem${PdO_ z?e>G8^{yN#H|BR6)M^~9DL+&xPVe1t)kju@{PjoiwfeWQMwZL(^L=KAq3fnmwQ;n2 zcEsaeQTu(1cdTQ#1)j%_>5Hd}7*%r}nlpws(v`+e83alD?3``t7;;W%ekrePr%4i6 zUgP-DUHFIneW6R)y=G3~ z`Ni4_tADq(*Mu{sJEly`mc#mo7L~o8{;kIu*8H_=Z3r^d7tno0qKP>qC~p{=3*43wH?Q_kn-RW6w%lT+1R znby5KK8cidGX?{P4jQBe=ZggFoU$M2Z*U%qTOqJnJuYU;*VH=~GoT}E+^)u1sAWe# zZM!p{9Lq}ay}sMN{rGxD+V5rmvri+=M*2+j{Lq0fZL17TI>L5OJHvaRU)cVgCNpTh2S*or6OSf~#h6l4oGa9St&Q?yOeUt<+=vu8UtAw`=Fj3) zibm7HfkQ_n!o?f|#;Y~f|G;J;cU2-kUeKA;ySb~7bj_4{Tyu=rqIz34O~iG5h-9G7 z^q}+pm9pw;3%i0o%jIhyLPK2ypSxe5E4F^Durfer%%9WB^G7;Hhd$jrS~4k0FE6(& ztzbxE#Vo^cC&rI+uCb~_a_S$kLIt|2qUWsazQXNiq&>6QT%B+8drSBvFa zDUQ}rY4JzsszEClYf$~na{=ELwRY(p#ZnIMk zGzioUlo>6!Y=K*@zMmM`J!xdO_onA{qKaQr(Z$<>4}?Ham~e1a$Di)FNJu|!fj z;~8b|5960DSz^@S*wPnpmjpS1OTx_*(i51Tr%K|8IelHo*3W-fy{}Y)I+b`9kmT)a zdnPNnU|TIKK_a&__uX(?z2kw)hAN?5b;PFmW3)B1P1Z>4MHw$CcWUni?5Mh2P$Ge$ zH!A*=GkDiZ^2X?3wlZ5$yWK8=vT?8pphJO8=9cC5NQZ1QjJXQCQXnr> zfQA*$3IkCKcj~zi`LMpw#5JN~!I{=5WrhKF-%-LDWYgPGdcj_Qj4Q)!_4p%$_2G5-YGdcqzX@9s-K@OwV#^N%@}U&LfQF((u*TCIs5 zNHgU)^Afm*Y=~DULA+_P=OP%I^l0JEBmS1{ifADr|fs5-CSA zm!8(+wL@V~fjLv5SSH};`3QY?Yh2)?&px@L@x?tFvAT%&=X)VN7^D3)@7J~5>Bu5} z%qiEx-oUNu8OEd!U30YA%gZ+4WYqJh_&b<$lJA0|j`hRO2=Y;&uOpC{GP;-b_Q?eQZj-Q%(yHYH z{kB}rw;gq(4O;Kc4jqq+np5~H%t#M%q%l&T{6kZc`(%nevpd;h=!raBTFM$x@P?#V zZ?qXA%||t(Xo?orRnWPYERphc8?T!$0xBtIq`l7F98qu9Z`)^lqx(DOr`9{4pz80K z$-2C1Rl!j0=`C;c+XgwwCUt%eExAtIr^OTPK^#{~?vyAaeWr&W!>W75vK@9OO>|t` zdu-NQ3a-Q$aAsc}Z#$)rcpoTj?RzRSxrmPS9IT-aJdUl{Y8re~f98@%$#ChpE+k)F zA9=4pKv;U%yCMfmwPSadZ=Mfu4-UU(7hvE=xR@C^8N*&@Riv z0Grk3f0#ZMcHHxgK8WF+pnRVxp?uBc zoMoqxdpw-K>j$pi|CLYWSdk1P?dxR|rr|g8z@fW-`Rk))>s@87YpfI&tDM@~xA8u4 zR9LZ>L>Ob=2@I-zCt5$_(Gogo>cg9~dm)GPSv#$rF?Xl>%2LPr=dPjR?N<%YcSVi2 zT2s~wS+MhapFqq#nqvhQU$1BM=h{w8dDjcq3qkj;)zQYol< ztg>4B`D)GCt|-}-8=PQj>pQN;$>RJxjudCT75#@wL53@JnfjP8d+nr9xl$PB0rO=@ zPCe^esOY>}*>G1t8dwARMtZrQ8A)%Pd~Cdl!Zz{~NH5A`-OjH5IvYV1d~$1EEP$pZ z&>?qG!KYkuG;Jh&pkBQ*eQmgG*VF21b7oDGAj8hZaGb2~uFLb_MARlY5N9_BiUtb6 zH>L{6O^U1LJy#c-;QW29l(@Ak%*q$Ozq^78JP|j6)$qS%RSO*J#prhaW+cc6@!g{H z3UK?zqpQy8U`_386U$ni$=di}1D$!J#DY`vhWPjTaZLD{C(QXB@r8LD8_rtR@a%3W zZ}U8fK##TUr`5__Xff_=<)8m1CjDfvu{ZE{56KZ4$3Egp6nfu)s7k&R+Al^G2k9U^ zMm(Vs9o5844f@pnHxFsqS#On?ekW+Z7~%Uycf(Q1)hf8-=0nllWB1q>IT{T?0zYrp zQS7yKh`q+~=d7}-@PCBvT7=yVV`uzUHI2wKeSn)Yzsk%3!6s%2_Q{i!x$mmKTQHp(_`}^WbQbyu!4A~}3~YNQCUDWsP6*&Vki>Wa zeOv~C!Ri3&q+G;x#1c39N=;>qY+&w^lR@m?kJ6vWg={zcM{9Xe%i!@`hGff&$I`~iArHLXn% zx&pBT{*gog#@-k4MO1=f2#ms+@e$;eKYoG_C){bY71t*fFc*Hf**$>c)-^%r6U#sG zEr8Lb2`F_TlreA?_V=KH>dBh`h}%T|I|LKOY}1iJ2tL@dGeBAXbM-HfT@QaoNpTgi zT3CGyl)sdyD}i|O8;zBy&YH#`SM%G6 ziL8Cy$l1-RyOF*Xoq|?hWY_gGmO^X3{bsZNx}fe(@X#-_fF$3V(ttvh&YX!K5@z75 zv`X{mNg066S!qA;^lGsvgoG zM^vB&fq=2~`K|44&cA#>wDpm(&N^s7%;5N~M`|Hx-=h5i9IqE;mVe(*9_z&NJI(36 zYsMkoVUB$hW-LCETc9uC!i^0XDpbF6T-ml?>2R&4ok6ub0k`TSlLJ@KEzsv2BgyCc{|()?^a?3ZyFuAZ&-)`1NPjFyyA8m}AO0l>W!wJ_ zA)&X;)v@I71Yw_iD>U)G+41Xm%r+IEpK>Rj$IbyBf)KSO$jUHGu@CsHzt3N6ppT$e zzN{Y5;8X7A3EY%IpdDZv3(SrD)`5fz@*6}d7G?ZXy^-%Yw;OQkVg5#$(u|}i13-p4 zc3Fy5HS^4MeH2MkPKG)Lx6IoToIR13f<1CT8dgb2;=J4Bn+~k|Qf$2isFxG~6+Jj) z?(PXkF>Aib4bWeS9QhUHry(y+9m|%Dt-<#)`9W2P$1 zHk(F({8tW6_^S_R9MDt=;^x(&OnKH_M8EW;kxD@Y2!&})s0e465eD&`9em>~U*5$R znZTHc0YsncKomw!;igXVOYZQ|Gd?#ur5XLWEqn&(gGDi|`Ll_$#K_|_E1r+8_9tXn z7P=?@s8po@skkY4_l;AB_|u>G(k`JAqKaz@_L{iO#ZnCubr{^+OP5`@If_ZB*uylzE+%p{fmC zxqWGx)JrpJ+Y11i*(F&pH2>v$UK75{uEmAUJ_)ULT9Q^~IK z+i9xQp(!;oVPFD}mds%*WR{m;`PN8^E_=19_RgwGfkY#6c7x4F#7N+IO4}L=Q-g2e zcI{9_8?Ua)QJHPIopzIL=v;c3I#Z>sc^wE@rkqFUw zmw!=XD)VSkQvUZ&RGgFS3GcpSVw$rH9SMPQQ`IbMgvrA5&8fXJHpF!Mi_7Q@6{`2U z1}XnBl-4t1#bh;JB3_{{G~xBVOv+WL(j6Vbe}>osAt%YMurK^Mh0ZVdvUZdCKPf8I z_S-gew^ax15i{liChLPUb<%A$0oQc>nmW}fB?05TdF7$tls_-E<}!f%eOc$l$|8F5 zC>iJrmgeN|^3Ba8&bc6=n<}&5i{EUX6y=EWW;s3ha#()VSD@$P$PrXNAx@3T9IISE zrEq9vAWI~Z;-pDts+{(w^VE2!c*dN%N9R + + + + + + diff --git a/app/test/widgets/item/preview/utils/item_title_test.dart b/app/test/widgets/item/preview/utils/item_title_test.dart index e23c7c2..324a4e9 100644 --- a/app/test/widgets/item/preview/utils/item_title_test.dart +++ b/app/test/widgets/item/preview/utils/item_title_test.dart @@ -1,7 +1,9 @@ -import 'package:feeddeck/widgets/item/preview/utils/item_title.dart'; import 'package:flutter/material.dart'; + import 'package:flutter_test/flutter_test.dart'; +import 'package:feeddeck/widgets/item/preview/utils/item_title.dart'; + void main() { testWidgets('Should render title', (tester) async { await tester.pumpWidget( diff --git a/supabase/functions/_shared/feed/feed.ts b/supabase/functions/_shared/feed/feed.ts index b9f103b..9f4415f 100644 --- a/supabase/functions/_shared/feed/feed.ts +++ b/supabase/functions/_shared/feed/feed.ts @@ -3,6 +3,7 @@ import { Redis } from 'redis'; import { IItem } from '../models/item.ts'; import { ISource } from '../models/source.ts'; +import { getLemmyFeed, isLemmyUrl } from './lemmy.ts'; import { getMediumFeed, isMediumUrl } from './medium.ts'; import { getPinterestFeed, isPinterestUrl } from './pinterest.ts'; import { getRSSFeed } from './rss.ts'; @@ -39,6 +40,8 @@ export const getFeed = async ( profile, source, ); + case 'lemmy': + return await getLemmyFeed(supabaseClient, redisClient, profile, source); case 'mastodon': return await getMastodonFeed( supabaseClient, @@ -63,6 +66,13 @@ export const getFeed = async ( return await getRedditFeed(supabaseClient, redisClient, profile, source); case 'rss': try { + if (source.options?.rss && isLemmyUrl(source.options.rss)) { + return await getLemmyFeed(supabaseClient, redisClient, profile, { + ...source, + options: { lemmy: source.options.rss }, + }); + } + if (source.options?.rss && isMediumUrl(source.options.rss)) { return await getMediumFeed(supabaseClient, redisClient, profile, { ...source, diff --git a/supabase/functions/_shared/feed/lemmy.ts b/supabase/functions/_shared/feed/lemmy.ts new file mode 100644 index 0000000..e575647 --- /dev/null +++ b/supabase/functions/_shared/feed/lemmy.ts @@ -0,0 +1,323 @@ +import { SupabaseClient } from '@supabase/supabase-js'; +import { parseFeed } from 'rss'; +import { Md5 } from 'std/md5'; +import { FeedEntry } from 'rss/types'; +import { Redis } from 'redis'; +import { unescape } from 'lodash'; + +import { IItem } from '../models/item.ts'; +import { ISource } from '../models/source.ts'; +import { IProfile } from '../models/profile.ts'; +import { fetchWithTimeout } from '../utils/fetchWithTimeout.ts'; +import { log } from '../utils/log.ts'; + +/** + * `instances` contains a list of known Lemmy instances. This list is used to + * determin if a provided url is related to a Lemmy instance or not. The list + * is based on the list of instances from https://join-lemmy.org/instances. + */ +const instances = [ + 'lemmy.world', + 'lemm.ee', + 'programming.dev', + 'sh.itjust.works', + 'hexbear.net', + 'feddit.de', + 'lemmy.ca', + 'beehaw.org', + 'lemmy.dbzer0.com', + 'lemmy.blahaj.zone', + 'discuss.tchncs.de', + 'lemmygrad.ml', + 'sopuli.xyz', + 'aussie.zone', + 'lemmy.one', + 'feddit.nl', + 'feddit.uk', + 'lemmy.zip', + 'midwest.social', + 'infosec.pub', + 'jlai.lu', + 'slrpnk.net', + 'startrek.website', + 'feddit.it', + 'pawb.social', + 'ttrpg.network', + 'lemmings.world', + 'lemmy.eco.br', + 'mander.xyz', + 'lemmy.today', + 'lemdro.id', + 'lemmy.nz', + 'monero.town', + 'feddit.dk', + 'szmer.info', + 'feddit.ch', + 'yiffit.net', + 'iusearchlinux.fyi', + 'lemmus.org', + 'lemmy.whynotdrs.org', + 'ani.social', + 'awful.systems', + 'monyet.cc', + 'feddit.cl', + 'feddit.nu', + 'mujico.org', + 'lemmy.wtf', + 'leminal.space', + 'thelemmy.club', + 'literature.cafe', + 'fanaticus.social', + 'r.nf', + 'dormi.zone', + 'pornlemmy.com', + 'lemmy.cafe', + 'lemmy.studio', + 'lemmy.myserv.one', + 'lemmy.kde.social', + 'bookwormstory.social', + 'sub.wetshaving.social', + 'endlesstalk.org', + 'lemmy.my.id', + 'yall.theatl.social', + 'toast.ooo', + 'links.hackliberty.org', + 'eviltoast.org', + 'futurology.today', + 'dmv.social', + 'lemmy.fmhy.net', + 'eslemmy.es', + 'suppo.fi', + 'lemmy.frozeninferno.xyz', + 'lemmyf.uk', + 'mtgzone.com', + 'linux.community', + 'lemmy.pt', + 'lemmy.radio', + 'feddit.ro', + 'kyberpunk.social', + 'alien.top', + 'sffa.community', + 'lemmy.tf', + 'blendit.bsd.cafe', + 'lemmy.cat', + 'rblind.com', + 'bbs.9tail.net', + 'communick.news', + 'talk.macstack.net', +]; + +/** + * `isLemmyUrl` checks if the provided `url` is related to a known Lemmy + * instance. + */ +export const isLemmyUrl = (url: string): boolean => { + const parsedUrl = new URL(url); + return instances.includes(parsedUrl.hostname); +}; + +export const getLemmyFeed = async ( + _supabaseClient: SupabaseClient, + _redisClient: Redis | undefined, + _profile: IProfile, + source: ISource, +): Promise<{ source: ISource; items: IItem[] }> => { + if (!source.options?.lemmy) { + throw new Error('Invalid source options'); + } + + const parsedUrl = new URL(source.options.lemmy); + if ( + parsedUrl.pathname.startsWith('/feeds/') && + parsedUrl.pathname.endsWith('.xml') + ) { + source.options.lemmy = `${parsedUrl.origin}${parsedUrl.pathname}?sort=New`; + } else if ( + parsedUrl.pathname.startsWith('/c/') || parsedUrl.pathname.startsWith('/u/') + ) { + source.options.lemmy = + `${parsedUrl.origin}/feeds${parsedUrl.pathname}.xml?sort=New`; + } else if (parsedUrl.pathname === '/feeds/all.xml') { + source.options.lemmy = `${parsedUrl.origin}/feeds/all.xml?sort=New`; + } else if (parsedUrl.pathname === '' || parsedUrl.pathname === '/') { + source.options.lemmy = `${parsedUrl.origin}/feeds/all.xml?sort=New`; + } else { + throw new Error('Invalid source options'); + } + + /** + * Get the RSS for the provided `lemmy` url and parse it. If a feed doesn't + * contains an item we return an error. + */ + const response = await fetchWithTimeout(source.options.lemmy, { + method: 'get', + }, 5000); + const xml = await response.text(); + log('debug', 'Add source', { + sourceType: 'lemmy', + requestUrl: source.options.lemmy, + responseStatus: response.status, + }); + const feed = await parseFeed(xml); + + if (!feed.title.value) { + throw new Error('Invalid feed'); + } + + /** + * Generate a source id based on the user id, column id and the normalized + * `lemmy` url. Besides that we also set the source type to `lemmy` and + * set the title and link for the source. + */ + if (source.id === '') { + source.id = generateSourceId( + source.userId, + source.columnId, + source.options.lemmy, + ); + } + source.type = 'lemmy'; + source.title = feed.title.value; + if (feed.links.length > 0) { + source.link = feed.links[0]; + } + + /** + * Now that the source does contain all the required information we can start + * to generate the items for the source, by looping over all the feed entries. + */ + const items: IItem[] = []; + + for (const [index, entry] of feed.entries.entries()) { + if (skipEntry(index, entry, source.updatedAt || 0)) { + continue; + } + + /** + * Each item need a unique id which is generated using the `generateItemId` + * function. The id is a combination of the source id and the id of the + * entry. + */ + const itemId = generateItemId(source.id, entry.id); + + /** + * Create the item object and add it to the `items` array. + */ + items.push({ + id: itemId, + userId: source.userId, + columnId: source.columnId, + sourceId: source.id, + title: entry.title!.value!, + link: entry.id, + media: getMedia(entry), + description: getDescription(entry), + author: entry.author?.name, + publishedAt: Math.floor(entry.published!.getTime() / 1000), + }); + } + + return { source, items }; +}; + +/** + * `skipEntry` is used to determin if an entry should be skipped or not. When a + * entry in the RSS feed is skipped it will not be added to the database. An + * entry will be skipped when + * - it is not within the first 50 entries of the feed, because we only keep the + * last 50 items of each source in our delete logic. + * - the entry does not contain a title, a link or a published date. + * - the published date of the entry is older than the last update date of the + * source minus 10 seconds. + */ +const skipEntry = ( + index: number, + entry: FeedEntry, + sourceUpdatedAt: number, +): boolean => { + if (index === 50) { + return true; + } + + if ( + !entry.id || !entry.title?.value || + (entry.links.length === 0 || !entry.links[0].href) || !entry.published + ) { + return true; + } + + if (Math.floor(entry.published.getTime() / 1000) <= (sourceUpdatedAt - 10)) { + return true; + } + + return false; +}; + +/** + * `generateSourceId` generates a unique source id based on the user id, column + * id and the link of the RSS feed. We use the MD5 algorithm for the link to + * generate the id. + */ +const generateSourceId = ( + userId: string, + columnId: string, + link: string, +): string => { + return `lemmy-${userId}-${columnId}-${new Md5().update(link).toString()}`; +}; + +/** + * `generateItemId` generates a unique item id based on the source id and the + * identifier of the item. We use the MD5 algorithm for the identifier, which + * can be the link of the item or the id of the item. + */ +const generateItemId = (sourceId: string, identifier: string): string => { + return `${sourceId}-${new Md5().update(identifier).toString()}`; +}; + +/** + * `getDescription` returns the description for a feed entry. If the entry does + * not contain a description we return `undefined`. + */ +const getDescription = (entry: FeedEntry): string | undefined => { + if (entry.description?.value) { + return unescape(entry.description.value); + } + + return undefined; +}; + +/** + * `getMedia` returns the media for a feed entry. If the link of an entry ends + * with a image or video extension it is considered as media file. This is not + * always the case, since the link could also be a link to a website which is + * then not used as media. + */ +const getMedia = (entry: FeedEntry): string | undefined => { + if (entry.links && entry.links.length > 0 && entry.links[0].href) { + const parsedUrl = new URL(entry.links[0].href); + if ( + /** + * Images + */ + parsedUrl.pathname.endsWith('.jpg') || + parsedUrl.pathname.endsWith('.jpeg') || + parsedUrl.pathname.endsWith('.png') || + parsedUrl.pathname.endsWith('.gif') || + /** + * Videos + */ + parsedUrl.pathname.endsWith('.mp4') || + /** + * YouTube + */ + entry.links[0].href.startsWith('https://youtu.be/') || + entry.links[0].href.startsWith('https://www.youtube.com/watch?') || + entry.links[0].href.startsWith('https://m.youtube.com/watch?') + ) { + return entry.links[0].href; + } + } + + return undefined; +}; diff --git a/supabase/functions/_shared/models/source.ts b/supabase/functions/_shared/models/source.ts index 4c451f6..c84f7ab 100644 --- a/supabase/functions/_shared/models/source.ts +++ b/supabase/functions/_shared/models/source.ts @@ -5,6 +5,7 @@ import { ISourceOptionsStackOverflow } from './sources/stackoverflow.ts'; export type TSourceType = | 'github' | 'googlenews' + | 'lemmy' | 'mastodon' | 'medium' | 'nitter' @@ -33,6 +34,7 @@ export interface ISource { export interface ISourceOptions { github?: ISourceOptionsGithub; googlenews?: ISourceOptionsGoogleNews; + lemmy?: string; mastodon?: string; medium?: string; nitter?: string;