From 88a41b1939e8d8f3adef9d2100d43654dfb5e238 Mon Sep 17 00:00:00 2001 From: Radek Czajka Date: Fri, 14 Mar 2025 09:05:15 +0100 Subject: [PATCH 01/11] update --- requirements/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements/requirements.txt b/requirements/requirements.txt index 10498cb2b..084f0da8d 100644 --- a/requirements/requirements.txt +++ b/requirements/requirements.txt @@ -40,7 +40,7 @@ mutagen==1.47 sorl-thumbnail==12.10.0 # home-brewed & dependencies -librarian==24.5.7 +librarian==24.5.8 # celery tasks celery[redis]==5.4.0 -- 2.20.1 From 76d3bbd6c7c2dfffb227f8fce87da80c62f61799 Mon Sep 17 00:00:00 2001 From: Radek Czajka Date: Fri, 28 Mar 2025 15:56:36 +0100 Subject: [PATCH 02/11] Some new api. --- src/api/urls.py | 1 + src/catalogue/api/serializers.py | 9 +++++++++ src/catalogue/api/urls2.py | 4 ++++ src/catalogue/api/views.py | 15 ++++++++++++++- src/social/api/urls2.py | 16 ++++++++++++++++ src/social/api/views.py | 16 ++++++++++++++++ 6 files changed, 60 insertions(+), 1 deletion(-) create mode 100644 src/social/api/urls2.py diff --git a/src/api/urls.py b/src/api/urls.py index de3dba77f..62d4fa7f7 100644 --- a/src/api/urls.py +++ b/src/api/urls.py @@ -16,6 +16,7 @@ urlpatterns1 = [ path('login/', csrf_exempt(views.Login2View.as_view())), path('me/', views.UserView.as_view()), path('', include('catalogue.api.urls2')), + path('', include('social.api.urls2')), ] diff --git a/src/catalogue/api/serializers.py b/src/catalogue/api/serializers.py index 60e52a052..059fdd04a 100644 --- a/src/catalogue/api/serializers.py +++ b/src/catalogue/api/serializers.py @@ -352,6 +352,15 @@ class FragmentDetailSerializer(serializers.ModelSerializer): fields = ['book', 'anchor', 'text', 'url', 'themes'] +class FragmentSerializer2(serializers.ModelSerializer): + url = AbsoluteURLField() + html = serializers.CharField(source='text') + + class Meta: + model = Fragment + fields = ['anchor', 'html', 'url'] + + class FilterTagSerializer(serializers.ModelSerializer): class Meta: model = Tag diff --git a/src/catalogue/api/urls2.py b/src/catalogue/api/urls2.py index b16af6651..7dc131d23 100644 --- a/src/catalogue/api/urls2.py +++ b/src/catalogue/api/urls2.py @@ -19,6 +19,10 @@ urlpatterns = [ piwik_track_view(views.BookDetail2.as_view()), name='catalogue_api_book' ), + path('books//fragment/', + piwik_track_view(views.BookFragmentView.as_view()), + name='catalogue_api_book_fragment' + ), path('suggested-tags/', piwik_track_view(views.SuggestedTags.as_view()), diff --git a/src/catalogue/api/views.py b/src/catalogue/api/views.py index 0e758b15e..e45f80e75 100644 --- a/src/catalogue/api/views.py +++ b/src/catalogue/api/views.py @@ -501,6 +501,19 @@ class SuggestedTags(ListAPIView): def get_queryset(self): tag_ids = self.request.GET.getlist('tag', []) + search = self.request.GET.get('search') tags = [get_object_or_404(Tag, id=tid) for tid in tag_ids] related_tags = list(t.id for t in get_top_level_related_tags(tags)) - return Tag.objects.filter(id__in=related_tags) + tags = Tag.objects.filter(id__in=related_tags) + if search: + tags = tags.filter(name__icontains=search) + return tags + + +class BookFragmentView(RetrieveAPIView): + serializer_class = serializers.FragmentSerializer2 + + def get_object(self): + book = get_object_or_404(Book, slug=self.kwargs['slug']) + return book.choose_fragment() + diff --git a/src/social/api/urls2.py b/src/social/api/urls2.py new file mode 100644 index 000000000..822bea340 --- /dev/null +++ b/src/social/api/urls2.py @@ -0,0 +1,16 @@ +# This file is part of Wolne Lektury, licensed under GNU Affero GPLv3 or later. +# Copyright © Fundacja Wolne Lektury. See NOTICE for more information. +# +from django.urls import path +from stats.utils import piwik_track_view +from . import views + + +urlpatterns = [ + path('like//', + piwik_track_view(views.LikeView.as_view()), + name='social_api_like'), + path('likes/', views.LikesView.as_view()), +] + + diff --git a/src/social/api/views.py b/src/social/api/views.py index a29930423..2c81286c2 100644 --- a/src/social/api/views.py +++ b/src/social/api/views.py @@ -12,6 +12,7 @@ from catalogue.api.helpers import order_books, books_after from catalogue.api.serializers import BookSerializer from catalogue.models import Book from social.utils import likes +from social.views import get_sets_for_book_ids @vary_on_auth @@ -32,6 +33,21 @@ class LikeView(APIView): return Response({}) +@vary_on_auth +class LikesView(APIView): + permission_classes = [IsAuthenticated] + + def get(self, request): + slugs = request.GET.getlist('slug') + books = Book.objects.filter(slug__in=slugs) + books = {b.id: b.slug for b in books} + ids = books.keys() + res = get_sets_for_book_ids(ids, request.user) + res = {books[bid]: v for bid, v in res.items()} + return Response(res) + + + @vary_on_auth class ShelfView(ListAPIView): permission_classes = [IsAuthenticated] -- 2.20.1 From cf1362af5032adae4453d272043da25adcb04763 Mon Sep 17 00:00:00 2001 From: Radek Czajka Date: Fri, 28 Mar 2025 16:04:14 +0100 Subject: [PATCH 03/11] remove weirdness --- src/social/api/urls2.py | 2 +- src/social/api/views.py | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/src/social/api/urls2.py b/src/social/api/urls2.py index 822bea340..790e8e580 100644 --- a/src/social/api/urls2.py +++ b/src/social/api/urls2.py @@ -8,7 +8,7 @@ from . import views urlpatterns = [ path('like//', - piwik_track_view(views.LikeView.as_view()), + piwik_track_view(views.LikeView2.as_view()), name='social_api_like'), path('likes/', views.LikesView.as_view()), ] diff --git a/src/social/api/views.py b/src/social/api/views.py index 2c81286c2..d34503da1 100644 --- a/src/social/api/views.py +++ b/src/social/api/views.py @@ -33,6 +33,25 @@ class LikeView(APIView): return Response({}) +@vary_on_auth +class LikeView2(APIView): + permission_classes = [IsAuthenticated] + + def get(self, request, slug): + book = get_object_or_404(Book, slug=slug) + return Response({"likes": likes(request.user, book)}) + + def put(self, request, slug): + book = get_object_or_404(Book, slug=slug) + book.like(request.user) + return Response({"likes": likes(request.user, book)}) + + def delete(self, request, slug): + book = get_object_or_404(Book, slug=slug) + book.unlike(request.user) + return Response({"likes": likes(request.user, book)}) + + @vary_on_auth class LikesView(APIView): permission_classes = [IsAuthenticated] -- 2.20.1 From 12296279a15dac4d8612b5bc405ab98fabc83242 Mon Sep 17 00:00:00 2001 From: Radek Czajka Date: Tue, 1 Apr 2025 15:23:28 +0200 Subject: [PATCH 04/11] get all my likes --- src/social/api/urls2.py | 1 + src/social/api/views.py | 16 +++++++++++++++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/social/api/urls2.py b/src/social/api/urls2.py index 790e8e580..b150e6183 100644 --- a/src/social/api/urls2.py +++ b/src/social/api/urls2.py @@ -11,6 +11,7 @@ urlpatterns = [ piwik_track_view(views.LikeView2.as_view()), name='social_api_like'), path('likes/', views.LikesView.as_view()), + path('my-likes/', views.MyLikesView.as_view()), ] diff --git a/src/social/api/views.py b/src/social/api/views.py index d34503da1..22a0e9c52 100644 --- a/src/social/api/views.py +++ b/src/social/api/views.py @@ -11,6 +11,7 @@ from api.utils import vary_on_auth from catalogue.api.helpers import order_books, books_after from catalogue.api.serializers import BookSerializer from catalogue.models import Book +import catalogue.models from social.utils import likes from social.views import get_sets_for_book_ids @@ -64,7 +65,20 @@ class LikesView(APIView): res = get_sets_for_book_ids(ids, request.user) res = {books[bid]: v for bid, v in res.items()} return Response(res) - + + +@vary_on_auth +class MyLikesView(APIView): + permission_classes = [IsAuthenticated] + + def get(self, request): + ids = catalogue.models.tag.TagRelation.objects.filter(tag__user=request.user).values_list('object_id', flat=True).distinct() + books = Book.objects.filter(id__in=ids) + books = {b.id: b.slug for b in books} + res = get_sets_for_book_ids(ids, request.user) + res = {books[bid]: v for bid, v in res.items()} + return Response(res) + @vary_on_auth -- 2.20.1 From a42fd9db14f15b7a2a838a1bb9ef4eb053e08a62 Mon Sep 17 00:00:00 2001 From: Radek Czajka Date: Fri, 4 Apr 2025 12:21:11 +0200 Subject: [PATCH 05/11] missing abstract --- src/catalogue/api/serializers.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/catalogue/api/serializers.py b/src/catalogue/api/serializers.py index 059fdd04a..a90d2ef9c 100644 --- a/src/catalogue/api/serializers.py +++ b/src/catalogue/api/serializers.py @@ -156,6 +156,7 @@ class BookSerializer2(serializers.ModelSerializer): 'epub', 'mobi', 'pdf', 'html', 'txt', 'fb2', 'xml', 'cover_thumb', 'cover', 'isbn_pdf', 'isbn_epub', 'isbn_mobi', + 'abstract', ] class BookSerializer11Labs(serializers.ModelSerializer): -- 2.20.1 From d98bdffdc284351da05e2ee467ace50e693d1fb7 Mon Sep 17 00:00:00 2001 From: Radek Czajka Date: Tue, 15 Apr 2025 15:49:15 +0200 Subject: [PATCH 06/11] fix for daisy save --- src/catalogue/models/bookmedia.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/catalogue/models/bookmedia.py b/src/catalogue/models/bookmedia.py index acb1881e5..0a1544fec 100644 --- a/src/catalogue/models/bookmedia.py +++ b/src/catalogue/models/bookmedia.py @@ -70,6 +70,8 @@ class BookMedia(models.Model): return f'{name}.{ext}' def save(self, parts_count=None, *args, **kwargs): + if self.type in ('daisy', 'audio.epub'): + return super().save(*args, **kwargs) from catalogue.utils import ExistingFile, remove_zip if not parts_count: -- 2.20.1 From eb6c65f96fd1b467f4ca1a9e477aa9404574b244 Mon Sep 17 00:00:00 2001 From: Radek Czajka Date: Tue, 15 Apr 2025 15:50:39 +0200 Subject: [PATCH 07/11] More civicrm exports. --- src/club/civicrm.py | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/src/club/civicrm.py b/src/club/civicrm.py index 20b287a28..dffeaa766 100644 --- a/src/club/civicrm.py +++ b/src/club/civicrm.py @@ -27,12 +27,12 @@ class CiviCRM: d = response.json() return d - def create_or_update_contact(self, email, key=None): + def create_or_update_contact(self, email, fields=None): contact_id = self.get_contact_id(email) if contact_id is None: - contact_id = self.create_contact(email, key) - elif key: - self.update_contact(contact_id, key) + contact_id = self.create_contact(email, fields) + elif fields: + self.update_contact(contact_id, fields) return contact_id def get_contact_id(self, email): @@ -49,7 +49,7 @@ class CiviCRM: if result: return result[0]['id'] - def create_contact(self, email, key=None): + def create_contact(self, email, fields): data = { 'values': {}, 'chain': { @@ -65,19 +65,22 @@ class CiviCRM: ] } } - if key: - data['values']['WL.TPWL_key'] = key + if fields: + data['values'].update(fields) result = self.request('Contact', 'create', data) return result['values'][0]['id'] - - def update_contact(self, contact_id, key): + + def update_phone(self, contact_id, phone): + if self.request('Phone', 'get', {'where': [['phone', "=", phone], ['contact_id', "=", contact_id]]})['count']: + return + self.request('Phone', 'create', {'values': {'phone': phone, 'contact_id': contact_id}}) + + def update_contact(self, contact_id, fields): return self.request( 'Contact', 'update', { - 'values': { - 'WL.TPWL_key': key, - }, + 'values': fields, 'where': [ ['id', '=', contact_id] ] @@ -89,7 +92,8 @@ class CiviCRM: if not self.enabled: return - contact_id = self.create_or_update_contact(email, tpwl_key) + fields = {'WL.TPWL_key': tpwl_key} + contact_id = self.create_or_update_contact(email, fields) activity_id = self.get_activity_id(key) if activity_id is None: -- 2.20.1 From 36a196056014e663e57176d1dd70f4a5ad8e56ec Mon Sep 17 00:00:00 2001 From: Radek Czajka Date: Tue, 15 Apr 2025 15:51:33 +0200 Subject: [PATCH 08/11] Basic docker. --- Dockerfile | 57 ++++++++++++++++++++++++++++++++++++++++++++++ Makefile | 14 +++++++++++- docker-compose.yml | 22 ++++++++++++++++++ 3 files changed, 92 insertions(+), 1 deletion(-) create mode 100644 Dockerfile create mode 100644 docker-compose.yml diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 000000000..032024ba7 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,57 @@ +FROM python:3.8 AS base + +ARG UID=1000 +ARG GID=1000 + +RUN apt-get update && apt-get install -y \ + git \ + calibre \ + texlive-xetex texlive-lang-polish \ + libespeak-dev + +COPY requirements/requirements.txt requirements.txt + +# numpy -> aeneas +RUN pip install numpy +RUN pip install aeneas + +RUN pip install --no-cache-dir -r requirements.txt +RUN pip install --no-cache-dir \ + psycopg2-binary \ + django-debug-toolbar==3.2.2 \ + python-bidi + +RUN addgroup --gid $GID app +RUN adduser --gid $GID --home /app --uid $UID app + +RUN apt-get install -y \ + texlive-extra-utils \ + texlive-lang-greek \ + texlive-lang-other \ + texlive-luatex \ + texlive-fonts-extra \ + texlive-fonts-extra-links \ + fonts-noto-core fonts-noto-extra + + +USER app + +# fonts +RUN cp -a /usr/local/lib/python*/site-packages/librarian/fonts /app/.fonts +RUN fc-cache + +WORKDIR /app/src + + +FROM base AS dev + +#RUN pip install --no-cache-dir coverage +USER app + + +FROM base AS prod + +RUN pip install --no-cache-dir gunicorn + +USER app +COPY src /app/src diff --git a/Makefile b/Makefile index d43ff1e6d..77d345df2 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,8 @@ -.PHONY: deploy test +.PHONY: deploy test shell + + +UID != id -u +GID != id -g deploy: src/wolnelektury/localsettings.py @@ -17,3 +21,11 @@ test: mv ../htmlcov.new ../htmlcov coverage report rm .coverage + + +shell: + UID=$(UID) GID=$(GID) docker-compose run --rm dev bash + + +build: + UID=$(UID) GID=$(GID) docker-compose build dev diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 000000000..89b2216d7 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,22 @@ +services: + dev: + build: + context: . + target: dev + args: + - "UID=${UID}" + - "GID=${GID}" + volumes: + - ./src:/app/src + - ./var/media:/app/var/media + - ./var/static:/app/var/static + - ./var/counters/:/app/var/counters + depends_on: + - db + db: + image: postgres + container_name: db + env_file: + - .env + volumes: + - ./var/postgresql-data/:/var/lib/postgresql/data/ -- 2.20.1 From 19737175c371148a884b1f302ac7d3c3f7057178 Mon Sep 17 00:00:00 2001 From: Radek Czajka Date: Tue, 15 Apr 2025 15:51:54 +0200 Subject: [PATCH 09/11] Minor import form fix --- .../templates/admin/catalogue/book/change_list.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/wolnelektury/templates/admin/catalogue/book/change_list.html b/src/wolnelektury/templates/admin/catalogue/book/change_list.html index b9574d9c9..db3308460 100644 --- a/src/wolnelektury/templates/admin/catalogue/book/change_list.html +++ b/src/wolnelektury/templates/admin/catalogue/book/change_list.html @@ -4,7 +4,7 @@
{% csrf_token %}

- +

-- 2.20.1 From 7fb028526a456c9e0e666733924ff4a6694c121c Mon Sep 17 00:00:00 2001 From: Radek Czajka Date: Tue, 15 Apr 2025 15:52:18 +0200 Subject: [PATCH 10/11] helper script --- manage | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100755 manage diff --git a/manage b/manage new file mode 100755 index 000000000..1077a0396 --- /dev/null +++ b/manage @@ -0,0 +1,14 @@ +#!/bin/sh +export UID=`id -u` +export GID=`id -g` + +if [ "$1" = "runserver" ] +then + PORT="$2" + [ -z "$PORT" ] && PORT=8000 + EXPOSED=127.0.0.1:"$PORT" + echo "expose as: $EXPOSED" + exec docker-compose run --rm -p "$EXPOSED":"$PORT" dev python $PYARGS manage.py runserver 0.0.0.0:"$PORT" +else + exec docker-compose run --rm dev python $PYARGS manage.py "$@" +fi -- 2.20.1 From 00ea692a2deeaa10ed01d332d15664e76e518511 Mon Sep 17 00:00:00 2001 From: Radek Czajka Date: Wed, 23 Apr 2025 13:34:50 +0200 Subject: [PATCH 11/11] ElevenReader links --- .../templates/catalogue/book_detail.html | 5 +++++ .../static/2022/styles/components/_media.scss | 2 +- .../static/2022/styles/layout/_button.scss | 8 ++++++-- src/wolnelektury/static/img/elevenreader-21.png | Bin 0 -> 12838 bytes src/wolnelektury/static/img/elevenreader.png | Bin 0 -> 19016 bytes 5 files changed, 12 insertions(+), 3 deletions(-) create mode 100644 src/wolnelektury/static/img/elevenreader-21.png create mode 100644 src/wolnelektury/static/img/elevenreader.png diff --git a/src/catalogue/templates/catalogue/book_detail.html b/src/catalogue/templates/catalogue/book_detail.html index eb1ab8a7d..6c89f1884 100644 --- a/src/catalogue/templates/catalogue/book_detail.html +++ b/src/catalogue/templates/catalogue/book_detail.html @@ -169,6 +169,11 @@
+
+ {% if first_text %} + {% trans + {% endif %} +
{% if first_text %} {% trans "czytaj online" %} diff --git a/src/wolnelektury/static/2022/styles/components/_media.scss b/src/wolnelektury/static/2022/styles/components/_media.scss index c4af4ebd1..9c5f34f94 100644 --- a/src/wolnelektury/static/2022/styles/components/_media.scss +++ b/src/wolnelektury/static/2022/styles/components/_media.scss @@ -10,7 +10,7 @@ .c-media__actions { display: flex; - column-gap: 38px; + column-gap: 20px; row-gap: 10px; } diff --git a/src/wolnelektury/static/2022/styles/layout/_button.scss b/src/wolnelektury/static/2022/styles/layout/_button.scss index 78b33bbae..b1844d896 100644 --- a/src/wolnelektury/static/2022/styles/layout/_button.scss +++ b/src/wolnelektury/static/2022/styles/layout/_button.scss @@ -21,12 +21,16 @@ @include rwd($break-flow) { @include font-size(16px); line-height: 20px; - padding: 19px 20px; + padding: 19px 0; } .icon { font-size: 21px; - margin-right: 15px; + margin-right: 10px; + } + + img { + height: 21px; } &:hover { diff --git a/src/wolnelektury/static/img/elevenreader-21.png b/src/wolnelektury/static/img/elevenreader-21.png new file mode 100644 index 0000000000000000000000000000000000000000..86e433d74b56751573096209b3cea962e9a8530d GIT binary patch literal 12838 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 QCZo^jMd z-RNMUyujRLyd=+J!!W|GExvwQBdDCc4NNn4nfiE$Ygkxhxf|VNTad>dtXnYl*YMpp z>4Lzu$jxcCs3e)!%j&GE6-JR-s)lK2`xeFyKUY(u<&-SVuj_qmfswzWJBgf?|ER_I zTYyH6>$Wi<4LK~SS zc*rnLd*G}|y?3cy-YBn~0Xqr+Tne^*@j?su;>AB5BD#?l5F@MH@sy#}fu0JshJbk^1ub{Hpr>*t_?X+G-XSdaTCVx{M6S44&P(0Jz>uyK9=; zNqF>uwt|TPvpm<_GbjD@jqVqlt4l%OP&QJ@x2o#(1W!K$KHgTK3>K;imjtS0Z=N=U zM3q5bWsKuyGjq&;m{9J8cDmYp5!)x-|LdEh%RJ}Js@UQ?nbevo9?zDPO1YU3u6zwV zdw-QD1Ci7rpC#zd{bm#i~OFVarS%ylyFE3DbWU%_#NE)cyQh?G-(_8F!UwQ zvv=37ipIZs8}YbA>Iv;gb>{jKvnTFO{av?&w%&>$E|K0+<_jtq)Sl*Bep9a2<#iv| zv?y1Wy6YmFk%s|W5 ze)Pn=^R^}Cm!Z0v6v)|;&(hl23e4y2=t4|906<3G+r<)O5B6ZO0z+(_WLb9`5v(k> z*0QVyqUr+bE-%1uY?Xc8z&gGfx*%VBkfb%Myc~s$w-gb;5$s{f;_c|*clvLZN(6VLoR!2*04Dq$Iz95WkQRFHwTm-N(tp(wo=Go$WWo-xvyDcaWQ{ zi-)bV6U%Q*ODktj4_Q`LVm-@0?Q?WdSN|8hllwndAo9WQZRx@<$S1(>=*a)?E!;g` zdJ#eXVbK4vg}W}XoAPUe-JLz%K;V~NU?&f@e}}LJ{j0r;r<=nccdSADU|_?RU)|cmCZFV)K9D{x|7=`u<0l zD5b70rQi(m{B0gkL6-Hmekp5bkgc`UpIcD@AqgRnm>{pPu$3^ch_Iz3ucaVZfLBDq zO2kS+L{vyj)au`$fKKinmQEn>Zzv)-pDhtb$VyzoM$8h-DVvJvK$u#^zz zwGsi_h*{ZytU)4@f1s>EQi{%Qj+Vr5+B#Z7!2B*wkUtf_372}N1(anK;uH9<5-kTy z4;x|wSynY$Cr|JHs?fD{1nYQM{$^89Ttrk@QdCG%R8&M#{xPdJ_oZWPtogHLZf1AYeyXC*C)rsB7+S0>P z!O{av1Qiexl@bt<5)#%G6p#`SloA%@77&sW_&0fHYg-$i|1as^orgu{?~p6ox)b&L z{3-goN9llF|Niv%M+e(KU5SO|Pp6Qw1pV!TyQLTS?_d$J{;mSOv2=ofiKE9q()FL^ zw*QAzkObR+EG30)ctr(8C3r=w1toc{gl)ulg#;|E!9rkBD=aTuFfe~2;c`q(kRs)x81nB zLV)Y*5B7vB+-51S*ndV&)b*e1|6K-P$IMP`kzC?29vmC`?(olh0UvS;a`S$cX8*(H zy;zV_8@K;EXRZxhZF+naJ1#Rf^_qc}%K80L@RNc>56(=$>sL?zmNryscaG~%h}Agy zvXJUL0p?W z(b29LKRz7~biC{WY_l=CC+|*O>jj6(Vz{C5^kyg(cc}X9O90km=>Q|(Ip;+)1&&$p zagZ)*Nz)|q7~}baPbPQ8JD1AW?X#V;``WLr9-PvzUSnFRxhS6YL0)_H{@E1^ z-i^11gv!Obt0wmB+t>^B@Lf-~(D%#$7JWpVb{g;53fgU(DsC8{?b6b5>dP#ijU$N_ zhR8! z8-SpSoS2J2&DfR#Y&br7-!s$e)JTV@K>UWg>hJzBGQOi|q8g!zSJfNrE4yg49%lvs=IDDUt7yp)?zPu(6vGYh5)gyWVNH(Tp z3LpWrW`%PvibJ`95ySb=nj4tT_4C9g4WCVhX=xz=QLGD0|Ka~aI| zTj!j@h=CIc0KoqM)LtfbK3jUnGjI5K?$sQTE&)Iu7bX-%)P6VuJoWS>o!=}rd;N-` zskxPa{V;qyPQtB3#0XDf+qnW*@UdmT;KCS>izp1NPy-Km8-xHDdM zdXj4;4z?=-jTnaWKPp*)U-qyi=DR3#Kz64`SAPxj!_?6*vZYDPyisR0x4v=Zm1;lN zMcs3%NoQJotP4YIkAf(IujGP9|c5zpOP^w->Gi5X$E5?Gdrt~aeL>pC$b=1g{Sqp>^Y)d+Je zt*lue83hR-$h=Ga)G>3*-iQMSqr>%YWK7z7!qCCbBy0OxOiPnxU`zoj~Ss zWW__s-OEI$J}2#=h`dw+&(GYqc`nC#nY8g?zUgAt$W=z{$_}rXw@d`Y2Jq(h2P{?) zGlDLw-bDFa2e#>~7U#kw1^`@J`W;|B>?5qPJ~yto_Bex%aEL0D=IeP88&GnnMN|q9 z5WyECpq~*VyYEw}0Ih6TVu*MCk~(D%%SDf@8zglTE^2qAczXDVE$D&rMDN}n01;6! zhy)s9nip57pL!;3ne6s9s-4f#;||<5?T-krZ9N!0l~$*~zZoTVB8%@ocl5m)Z8IKl z65F@(ElvhhIyVdNa%`+Ym>=XwYdM`EjU46QwC_q+Gw>2Uiv8V#Iy`UhH&Qr>0{~Hx z>T=_J)01|8@*^aJO8bH7W@v5dI8VgRtGQ>A#vE8PTVK4Zc>X>B(PQ8yE|Z zX2^__{wNoqVKa->h?r08xF8tW1I}z-t{U`%jxgR92>s<+>30yitMU-bTd#Jeq3ULI z)^PObO&O<0vbTDfUfVD~uTPLpe6|04n&R%_K0efxR!$&|rk6yZk z`V-~sro_dwg8DPE9yRHNao3)EcetnXYr0R1axrB7-HxZ>J0y{lHuTI@>$Eo=0SK-g zqsK%KPTM9Okb?o}6W?=Z=0yYlBVhqd`cLSxbN$GyDJSh?L&DDwKX)qg7dZ8WvKh;h zG)bAnfut1)Sew}-1lp%{6_tr31)o$qICTU?x4k4J9u#?S#AFQXlG#@4oOO%o01aYG zPwY&%p!_J_wcR)s*qJW@C^OsoM^4?HsW1&=679WiEf#e?O}^TtR!_-TXxbPr!?xl;o-TwqyrQ$(}fj%9%IlN zMtoFcsYP62=~>u}9yBkUeJ%*G3ur{sQMC-Rn{w)sXjlifjGN{*_`B?ZME2gW*LPl? z3U#g5yu$~ty2U0I%h!ILeJG^IP+D;s0nA16zQ{D;7+S;6YuvDFU&05DZfqqVurVDP%mhx;&q%$T{)Fz7Bu|S3mC8rdhPQalX7~qV_uiwCkb{O^a zRR!w@YPF09dDScZu_eFi4cWAY5BvEN8S*d?DN?D+q03A`%vr&@ofd;B%fgy!h3Izp)&=KF^yWQGp8I~*wfVyguqXp1T(xt$C#D+J&w8V zDNHT-)S+5n+n0fzqL(NyYp*uRN4SeH(PB~zUFjbSqlzIj)~8zOxEVpxCuc#&7?AA`mvwqj?#V3E zGd(H^YV?JtXgT}nXzOv&h*?0Dt-!MpXTvRO=9WR8cmh|7Ovd#< z-uj3K6lW_N?3?#;F3f0|pEo6sI;Xtp<;F1$Sbsqv%Tk(|$J~$X&wdo6;5m=w*+X(O z(UI1-*)Lk!I|$G)mBtxg6B?o=j~QP|7a34qB+)8fGI8{u10yj%&asWC!Bo815Chq$ z`pUC2qi?IPC|*>2);pWooNU4h=<5t;1^IX3kA zv}&L%+0PcC(=Kfb7qS%e;yJfGvlF@=}aZ%IC_ zkVBO1eCNZA^B+ro!HYygg!(CKD$0UQWuqeriuav)e#rUB^tBv&6(Vvoo!Q(GXkp+P z{8(=1Tr3E0C&Ar-I}}`DyscS7e)RCH_}X=`$glWZSR4$c8*Nf`30+of)4IufpKMfi ziJxVfZ0d?R=s~X61CR4@+lYP9%oA^f$}$qMk;NA{Tt|HN7dn!M#tv-Zj$oz58ZFAnFZ1YTgrm>lMc8S({iKi17Dw_H4Tgr~=#g!;1@_EMcaU^yM!J&y4Qg$533{J&vI?|1h=wtB=m2 zS=Lyw<=ZT$YK{gU6J}OIQjhOEDpB(s=ng$oE4LUPR*N9BpyFpIdrg(6T1iz--eM(Z zP~)!+sn8SHAX9?G$|>BRtwE9VOPv;*EVrI02*!PFDK#wpZe+W2GnplfzPfZJZUidb z)Cc1V9P*{#kV@x*=GSlf-Xc)lSR0fp$Ryu*7$yiDr)w%_`)POndZyq(uva1ctw8KX z{{H!)oX)JZH{*HxY9c6zwfbenFZF`{fT7trYr_=qU;NTLxV3LdM@2Wd^Hu@H^Lq<1 zTO=PJO(do$j`XA>A%~aRo{v0FkPZ_ul%gVuenI97tyDivh>5#4(bkFYYpHv-S;G!L z{6%J-DOcJY-G1(iS~>2yT@5N4>gGAda^;;|i!V4wReJECIfyI`wkn zk5U^I6YRsezK<8>CLw;*{kh!aN@%=JVmiP+rk2nsW|$ZM&MRywqSl;usFXG` z;Qd?lyTCVdZRbyG!pESVPr9#|ByGp*tU7ggn%t~Z?O4k}jt4kCIL`7CTC$a1jccVo zTTbp*7Bn(HH?uVgk;vf3;UF-SP;17lg zgu-R(QuY$!+{UD__}#>6oMN;!^V7X?g78-GYS>UMsx)KM22d%`GB_H&SI%V7Bf(!Z ze>h`v``v`%NTUWk{p^Yt8@8iT-qyS5g4Xg@#mrfTD%>&}r|xQi@0@$5iT3pN8(Tfh zaF(voU7dePXC1h6aklR4iPn}g^2gdeIF_K-39;w93%Tn38dtJo@}aVB<||Li9_6^N z|Jx3qPgNBCpfW!~%cw$&xxz8zO%zYu@|tC3ydDfGq4CRZ1b9B)zZpH!SfiL-W{no@ zYjIGk45*6Pt`~d)JrTTY+4vqeYx@3~pRG5JS&A;Gb86zja&ZhbajcVNDX-i?H!>>_ zq`tuTQ7s7I(@|tkg8j^zufkcBv%yA?U$9MmtO22$%)v$GP;0ECX7~HQ+XwrW}34;!L()GfT8mx#?VN zrP(3wU=wNga0}&JgDM9#dFO4yy3Q{~2Oh6^oLeWZ8rpd6v70pcG35swEN2(}l{uHZ z)GT02({E*|MM(b`b5s?X>XfrJbV&Yk0Fo1a*Bp~43p!%$d=~g#o-jI#TT75-$Fnor>M$ZlBl&%RQMt>3-P*!O&Eu3)r$U2ZECK)(?uO47W|$uzCyk z`mqT005n;XCF{|(A3O?p1qUZKPe(p5?+##<1J3K_7D%@b{@p0QTw_v<0yo8#`soo-eF zldYoNSK4c=N)9^saC*c=w*gLT&}?J(LOsD6@89X1Z`a{`ItFYGg{O;8T**Ja&7qHU z3BLy`N$PTZ4{3ced8HV4GxOzG)o_4YzgxSLvQMZY%&na{!fn9|ld}@&6bM8J#Ze6R zc*YWkwSE7d%(H6E@18M_jlLw>LQz>_6>>ef8s&VLn7Z0hPRWxBSAC=NR&hn2d+nR# z@A`i{|GF#ZrglDTQ7%){gu=H zYvv+mUU#Xuw+@@lG4i15onItTncJ;-Kq2SOv_>Ouzg@Cyg31@|O8%M#3Xg%xADi}j z56|f3iY#{3LJ$Q5=fp=a$FnHhmVdK>i9O<7P8qMXcx7ry23^xt;qELh+D*t<(zA@> zL1vzISs!Y=dja07!y~Y_3Fmq(Abs15`WzKHEG#r`$^G4ma_GTvMMI@q&4JO=k#0@F z*9v@L98JxWPxup8T~Py5(@7sz-Ce&n!N<&v**l^#&(Mfo=I#bc@okNf$~gGimiaT~ z^W!ptbtdzWMn}*Y&lQNlurw8mhAEu#E_Uk{FZ%tC0RzK?IqxbYxP zY`Ouxlh22}XLGx*7O6J7l6x%7wc6Oet5T1USO8Bd76li>htbDwaDV9<5r=#Yj8ne9 zl~lL8*XU?_km_o}UYKi%XM9Oh>dXy!V0@24Wai_Vrin(Tz_}7jQ|^S_`Uw31RF#SE zKp>e0ez7j;2+jp9>kpu)vIy`n7QV5TuvWjpKfQ+haCWyg{DSg$-=9}`L2s7sEA=6y zfxi~zivqswAXTnKWep0I2p?w<=Esgw&P^8`jWpfvKQ>dsi4nq$lcXW1d60s7Y2=V6WWY zU=^>w+EU=g9A0}<2GcsIFv4G3*Vocd^RNx0mw+{qYlG7KLVpXX`(#Y^R)U9&x#&tQ zg)uDfUT7Huk{;;X`U_<<@ZKD~-%8bi99&(soIoDBCw6CQw)69wZL zKog66Zc6r)h3}#6k!aLdcn zWbAXL-Bt3O&S<$w-&+-1HMAyW`rGzOT|2=ca-?IbmOOT6;=bB%))Av0b!*`5G7GS$`crGx!bF77An*}MabB?ne=PbxMj5dqYkqk9lqE_+6b z!?rh%`g|S_F;vynm#3-ob_Bt z9#xT3Hl(T_qZ%|Oe|1@}P>Bni49*|i=U{BA%ekRZa=D{2$9}6}cbpFLm zq|;H$a!kV-P{SEGsz*7af{*whI5=17kgpA#GU2%JLIlE&E01f>bkDC1B;8%P1N|0z z3e!4wF!-ML>Sm(rivoWINw@i@!Wus>{v$hfeW^v5x&1$yuJvY-oyV_VU;HYh>iR6YU z{D6vl7?}&g+8l%OfO>v?J^%6Qk>u(6Vfj3o`l|l+N$SnZ9dsyPXQ}hFqsyMyXPr?B zzbc4N1za6RgyT5fM`M_td6VHF{#pb_jGuiyt5@ciN8OSpw(K)Mo#?$9^HSb_QS`0V zxxbmHlC(<4l6Q(8QP|-0N;M3ab7g%CF8D!Yz=1|N_Gq*6(yZJxrcNEhGmB}FuGGGL z(ngX@X8y!8C}IRnVOw86E_X-IC_t2fJ%N$Z zjTgJ~vYlkZ=F0JuX6f-E?QB{Y5 zyYptymrW((j?@#d(rNpQRf8y)0au?d_QY)x`zC$C@lMgQdOI@n_^?*RL9p9x3@jK4 zVGXH!Vk|2I8=3wobSpzeic0lalCM8@H#Pz0r&mkdI`RFTA$NX}L~~-_4yq-n<~74F zN=$1_6P>4|kKA?U2JM+$&O*Nndb3$DaM&SFOJ|?sWf0w`(!8jG@lP`a1P%{$&dqP| zF?RgyD_S2prN;B({s4^?xQ1})Xb9%UZO-6GX$Fs@@uvyCGK8`i^UzlVnPEqI>^L*~ zAhfEK&Z>qrhIH-=aj{dYy4Sxo&YmnamXC~D{J@zW{v@g+lC^xR@g6xuZkf zT4Wl%C^fnLH4$jyn((N`u{$$yMi1Qf&O|8Q;mX2db(CX9$fiB19mXa#91v#zIH`GBH zl6pJy0=3I$_kRMUYusnL{ad`_7DV%mnW~kR>!My!!?r09v4bIlXP=)xBkumJ{yq!f z^Hk%JsZJBJVF|zYI`VtRF4y;}`3b+OH3Z~d7Bl|ii(f*HmxuHo_>}cG3r~@D0ixY1JncuO(UvX@{DO)A7_M~@HRifFp@kEP#l!VLZB{L zi95iLHN;wc@Sce%A7`mEQ^1g8Dn0@go!b|=Dxp~PK9gIOphYY5V7A9xL3Z@;F{RM8 ze!=1_5TZ>O(A0TwW5F4Ep3f~VO8KT?YVbNKAm~E@7v{s-b$%;ORTV>ZvZHn75pwt? z5`|{cp_&IBNIBK-5k*hz0OZmTD{)C4CLhL7{{G9K%m|TPCrXq$Pc~vvfGpwPyJU7b zF!#cK_4bKH$25BUNC$PQY4bz+*3we;InO;wYFQ4~`S*m^@8w6Yz}6swk}-E?E;>oi zvUr~2;{4mows}-{WJ$j!9<@3GEXG<4kCNg9KFxap>_r!xM4+BZ2(qXC1CbevYiI9a zPY6p{RT&u=;$t+6xP;$(2{5%~=nj3daR6L1{VdEI9i@nOC?NwL-{iIiSQv=MrVT?f z-=x0J+@5X}eM!0SQf{yz!K0|(^rLIX8dLX8;c2EC0O09Fq`22S?CGoZ$tx^X$I35F z3<8xKRxQi`x5*kJ7Hj9VQH(G5Cid>ldw6Gl=WnH(QLw!|(}g?$))}hkm5P`TUjsb- z7HPiSip%tR*`^ys{*>jLaTNFIwJpHW9Fx&eFv@APMha1u9dNb$p1jlP_kP@?%+s*d zV8i5anR0Iq#;b4u$hG=~l9~NZsR(qJ9j7@WeHQ#SX;$$IrAz?s;Mj3z-gbu}_!WS> zeCD~>^udof;$G))%VmkbX6tVuy4<`LRNqOE+I$-EcO5gNhOtY%Wn$c&PA+S2&AJ(3 zm)*0C(23x-ZxNz!7*v{gT8r{vUV(4i39>9M-o(2pkT9g8H{eBLiUD&b&GFtZ zqf&m!$@QfB_wS+t^Usej5SCPrabcPbdiBX4)A#Iyv!uJca~Ptd0>kAA@77AFuTM8M z<-~j7+6m5{u*@zmvw>#{CG~!qqF3&SK)LmHa&ocCXz!Hur(X14iVs`v_Gn!Nw}~Fl zij6Ww3{|`W8~1a%U-XM3ShLmf>h;?>HI$c(QddAfZ?N?CjRy~}C6eI@*usJyfE2^^ zG2*MnNR=TPpuvIEwId-9AB(T0K{e}%M>1S%aQt!p><-B432I0a1%G|g64Y5B|*3qb7 z99d=Ow|y*9?>)Q@0o*dkpM{8aPbMunYu3mVqu6R2qJ~_LoEb1D=xh`8H2j^Gm2e_Z~6REG&z6_%n^tV56}2<^@0ahsu9ZI|~;NjDc7@ z-QnSNC79KFOtNKy&0MuZ&13S06JcZB(V(5G5w7d2LHq^K3ixf~)4+4z9fu`YZmO_F z5)~!G4GXOcHW3!~yaxND2SE8pqQniEwyWkZm6@_r7mCGx1z2qG} z4w{0SS4Fzp=8J{JT+>*d$FdcEj_FQ&B1iUe3HcH16E7mW95+dU=%KmUG}cjj`_D-o zCiDJ9vRc5FQJKUP#_{8n!^1GgW<=%8J2!hTgDptm^+KlTCPV5TY>jYBx*a8ox|=Jt zOZiIXmlIc%U#bW2FH`EpRVgrQ{d?A6h?}i&IIV*w0D@ml*1xj|_s09JK_j2OQ+RNOi^_;%-2k5Qh6OT;sf3;}a?nuKa ztWy*=)#&?|8@Vt#30PwNHDL~b8+p?ZW2$4bCfv-Vx&nH8Clb6MmA!i@)|nZk5xy&} zQSOw#?k+xgebX>sIXCLD@Z%UdZa#VTJ!ws$$6?H~Bpw9>-e!c;sH_f5*b=0Ay3q%y z){=IwX~88W1pq>>w&Q&&@3S8<`|Iz-IdHlV-zGScf)hKzrw3|qYU%4uy;C-h?CF!Oy7%$dUo@Y9so|3I>VDG>o&|XZtrkyFTKFcT(>^+fFD&y z5ixK56jL@lJAGvt?;dh@U9-K_;o(L;7ejS++AjTlCYp8IS5I~y%)aTW)HYT*YG zyWrWi<@efW<@0$XYm%@D^xQRs#IK`gg|lmWVsnT`0deMvrj)06BmR5MjC;+g{hUF> zw|(g*9L60{Y)eg@HrIN-dj5J7a@p4@btm~_jXKmMDTe7JimeH*2`AvKvHXhtQi7vB z6QAhz*QwsOP4%PDh$~2^u~#^|0aaR^g7)~ju8xlRP<{)b8}|y)MA9Y&%*8d zRJS*~lOCg2%x?+~>^!N_^eqdE3p&28^qOjUitjaKUd-VRC{>#KB16J=^&$PT*xWYL zQ!H^OV%e_zS$)ZusTc3e=Y06#aN zTIU6EAuINYex``ds@wzgVS&{nT1Ot%0L|Ooo{8XBy}M7tWh-Pi_NFV%JQ;S=`Xo@Z zoAdLR)617{Ty^C_Tm}`omd>JVSTNKV8Z$MLZnw)q(NoZ7psg2R(=vyMiq^$;7F#{4iylu`j|3#mMKZndWAR zDlVOCvFsjt>Sm?$uqNa|^%G^z&s$t7r7t;)b!beaz5RP=W2Kdl*% z9urdC%yNIf>^NDzW-_p(yv61e=^D92*Zo0ST6@*zLG4B&>omMid!#XA9)GIA^D4k8 zdeVu2!w;O8H+djGU%EKkeXKITDO!R`EBje=)1QTbEeo+x-(=Oi;biU^g$|&x+`9z| z!aize`D%Ij`V@ByFrbyLDE+fw+k}UR5nUtN%W?}fXE<3F-(axQxZv;89Zqdyd7X7Y_?3@*(?=>2AZ*W^%Cw%rtk`yOyGlkD_r|CxO_d7kQ}j@w0Z z8(*m!L&r3xy9)4CkXPsNPTdj_OPY%51Dq*x4Blm7E=S|fJB)a!r6akX8~MwX^KdK* zx7a`Sxgoy~!8ybirp<|Y5W?$kch>bu-GOvEj3zga&Zcu7ESM|%G7Eb5*UtuJe~NjW zT)1hZj~<2#mk7QqLn#dIe5&9Q4q?ID5^A*5fJGnrEM~|$`9|ixQguXk+EGzy)^*zF zr@fLsmb8-gOkRgL7G1-25f}A3CibH=c@iEDV{}~g`I=$sbM>z-=xpv}gnH#qc!Z$m zIf`Li_zDxTZLJH)vdk<7*mHakyp(=j@&w8xvuWsx`L%ZU3(q4{MafA!jKzxnh@(VE ziLCo=gcXqgV@Kw)E6u~`C+x(du^R4B?;fLi&BYYZ4_|W*U9$mp(n}jPVUrJkmX}iV zQO@&GW$Yhk9*SD|@O{ba1}y(dBb}K%;9jAaDNx?lO*^DE{~SQOC?{q~IrZMR(YVOu z!^O&*>?8d{bt%8WrLHt&LYEr;D)+Xxe|zg7&0=QXor?aV3Y zxO>JF{IcynMouz)t;n37>@9=UjV_jbi4y((x)-UY{+!L_z7(t3PK?!8+FlSq`@L5e za7K224V7cNz78VYDR=~QO3-h2PVU6*lZ2{v`GhU1jU;nH8z+Ni$^;}LWY&#Bx0~oP zyahd1ImmkUqPBIzU;IR^bXy_4?7sFaCtF3X@V^}MbTgltJ2>q@uqKDikX zZ{9|igC|gK5C0fk-mt7u3U*D~Q+ZF<77|!hgeIM^#;W>TxEFafCT6a3cRbA-JB_Uu zjS?g6fsZq1-asjyH!jxX&h~XctzXv`Ud6ieC7pi z`7uk8eKSD~^IB1AC*s?FccY0)#P1jJvRy8D!(&Hy^DrB_| z#r7yLYI`gXC_TQ*C4Yhct2-sFV{>)*Li#o{T-NTnpU1tK@t?^j>*}8f`Lf}c5{q~I zrd>~^YZ9*M&)lqLI-(FDu<#w#$uv_^Eo>qR5HMyAO3UyzDnW zb)_7H4p1WVyLUn>(E@ZwmX#1 z0W7}?>Ng@d0C#GPY~)GG#p;b*{I%OUl%Aeu)}#V(I@;Q2B6s%x|XPJ7yN_jgbF1#gix= z)89TB(X{j)*)4J`6fPNX+?$~+<}+74j}z|$<>Et+WM6iA*?m&FUA?Vqj0-`aCDYj8 zv6?5mVi&tFK8vHlcR<9xW)m}DHS!{vN93gDVS}fDTX&u~IBC+%G!Ue*`S9u*r z%G~(I2zO0o;vSzXy;vDoiPGZ898+4VKnb>Xee9Gxak)TQ42$QQQmWiP8#k3_uW*Y} zP$==@`0f^`)uYjYHf4Wg_ls_C_pmm)`dT`kY&GfBjYUWubJlP`2j zif!S7wR@bBykW6Py{ojf?XkH%b`J=lPaFV?k!*U2zgQhyjk{maDGop2#&(O+CQIk{ z^Rmxz>e8w|4s$(ejsnLnD|EVWV5!|M)PnVPjGn5Vm8im-WG?ZGC~T)D;ihR5Qu~o( zHRP=U?`lk(c=jCf0}~A`WV$u*iugxL6=NiYJrNfw?}Vrgh-mi_sbP$cI{tRd5VK#WCXBWGhd6}Pj zAMQ`Smq=E~e5+25V3zixbr|i+ju;`HIBANmZo$FFPE=2r>tb4~((wtoMYqD!xk_lR zd9JU7G~bzZ-ZbT!7t2k(G~Z#YUD8kEt9C&X`r0(Lyk#|9Zebe2{t*VRkge58vW!k2 z;lk>Ds@WwKbi&FO+^*7`@{Dym1%~&`JreFxzt}dWCA{H*1t|6pF(r`KD8UcbcqZN@ zFGn!yt!7B~l<|Hct5Cl;(H5I4P;O$5gBKjWAr)zL(+w)YNi3jE>Cu~dUy=F`!fAYG z_2naE=;+<$-JWbXc6xbCT`JyXQ`we#HkM$#q3O#Pfofou#n*CFdCfMUf!S)>r#Srj zmliB7T0;`Zw`FaMDwqo1W|%49!@f^;;1sjph6^3E)!_*V7R8bYXjAR`UCA{UgY8|B z$VN}}KHD&4WrJ?v#ivv&jaU&&N*7MsG!o?&KfM8mNKnNQX&8o?CzjmJyU|H8}dDSCEdm+at9dZK#080q8iZoqaf2~v{^ zf7t#)@?q9Xj)-_e3d%26-^6hS;u{w;FO;IH^dc?_O)d-OitWWQ8PGTR{LIALmoSw* zH|4l_`BqLk*K^`=J?R?bP2w6(?e6s%@1H+}F^Smw;@vzMq5LS{mRufR$0##jGqD;a m?r!3j5&m=iKg>XMErIL>$;iopN=W%{Gl4HP6iT04y!&4i#p^@> literal 0 HcmV?d00001 -- 2.20.1