From bdb8c6f5357702f74f0f28941244edabac750a70 Mon Sep 17 00:00:00 2001 From: Thomas Date: Mon, 2 Oct 2023 18:26:49 +0200 Subject: [PATCH 1/3] Added django-prometious --- app/content/util/event_utils.py | 81 +++++++++++++++---------------- app/content/views/registration.py | 19 ++++---- app/settings.py | 8 ++- app/urls.py | 1 + docker-compose.yml | 6 +-- requirements.txt | 2 + 6 files changed, 63 insertions(+), 54 deletions(-) diff --git a/app/content/util/event_utils.py b/app/content/util/event_utils.py index 034b98cc4..f60ac0805 100644 --- a/app/content/util/event_utils.py +++ b/app/content/util/event_utils.py @@ -17,50 +17,49 @@ def create_payment_order(event, request, registration): and creates a new Vipps payment order. """ - if event.is_paid_event: - access_token = os.environ.get("PAYMENT_ACCESS_TOKEN") - expires_at = os.environ.get("PAYMENT_ACCESS_TOKEN_EXPIRES_AT") - if not access_token or datetime.now() >= datetime.fromtimestamp( - int(expires_at) - ): - (expires_at, access_token) = get_new_access_token() - os.environ.update({"PAYMENT_ACCESS_TOKEN": access_token}) - os.environ.update({"PAYMENT_ACCESS_TOKEN_EXPIRES_AT": str(expires_at)}) + access_token = os.environ.get("PAYMENT_ACCESS_TOKEN") + expires_at = os.environ.get("PAYMENT_ACCESS_TOKEN_EXPIRES_AT") + if not access_token or datetime.now() >= datetime.fromtimestamp( + int(expires_at) + ): + (expires_at, access_token) = get_new_access_token() + os.environ.update({"PAYMENT_ACCESS_TOKEN": access_token}) + os.environ.update({"PAYMENT_ACCESS_TOKEN_EXPIRES_AT": str(expires_at)}) - prev_orders = Order.objects.filter(event=event, user=request.user) - has_paid_order = False + prev_orders = Order.objects.filter(event=event, user=request.user) + has_paid_order = False - for order in prev_orders: - if ( - order.status == OrderStatus.CAPTURE - or order.status == OrderStatus.RESERVE - or order.status == OrderStatus.SALE - ): - has_paid_order = True - break + for order in prev_orders: + if ( + order.status == OrderStatus.CAPTURE + or order.status == OrderStatus.RESERVE + or order.status == OrderStatus.SALE + ): + has_paid_order = True + break - if not has_paid_order: + if not has_paid_order: - paytime = event.paid_information.paytime + paytime = event.paid_information.paytime - expire_date = datetime.now() + timedelta( - hours=paytime.hour, minutes=paytime.minute, seconds=paytime.second - ) + expire_date = datetime.now() + timedelta( + hours=paytime.hour, minutes=paytime.minute, seconds=paytime.second + ) - # Create Order - order_id = uuid.uuid4() - amount = int(event.paid_information.price * 100) - res = initiate_payment(amount, str(order_id), event.title, access_token) - payment_link = res["url"] - order = Order.objects.create( - order_id=order_id, - user=request.user, - event=event, - payment_link=payment_link, - expire_date=expire_date, - ) - order.save() - check_if_has_paid.apply_async( - args=(order.order_id, registration.registration_id), - countdown=(paytime.hour * 60 + paytime.minute) * 60 + paytime.second, - ) + # Create Order + order_id = uuid.uuid4() + amount = int(event.paid_information.price * 100) + res = initiate_payment(amount, str(order_id), event.title, access_token) + payment_link = res["url"] + order = Order.objects.create( + order_id=order_id, + user=request.user, + event=event, + payment_link=payment_link, + expire_date=expire_date, + ) + order.save() + check_if_has_paid.apply_async( + args=(order.order_id, registration.registration_id), + countdown=(paytime.hour * 60 + paytime.minute) * 60 + paytime.second, + ) diff --git a/app/content/views/registration.py b/app/content/views/registration.py index d899e2031..6c8dcb2ee 100644 --- a/app/content/views/registration.py +++ b/app/content/views/registration.py @@ -65,15 +65,16 @@ def create(self, request, *args, **kwargs): serializer, event=event, user=request.user ) - try: - create_payment_order(event, request, registration) - except Exception as e: - registration.delete() - raise e - - registration_serializer = RegistrationSerializer( - registration, context={"user": registration.user} - ) + if event.is_paid_event: + try: + create_payment_order(event, request, registration) + except Exception as e: + registration.delete() + raise e + + registration_serializer = RegistrationSerializer( + registration, context={"user": registration.user} + ) return Response(registration_serializer.data, status=status.HTTP_201_CREATED) diff --git a/app/settings.py b/app/settings.py index a6b0176ac..e70ce375f 100644 --- a/app/settings.py +++ b/app/settings.py @@ -77,6 +77,7 @@ # greater consistency between gunicorn and `./manage.py runserver`. See: # http://whitenoise.evans.io/en/stable/django.html#using-whitenoise-in-development "whitenoise.runserver_nostatic", + "django_prometheus", "django.contrib.staticfiles", # Third party "rest_framework", @@ -128,6 +129,7 @@ } MIDDLEWARE = [ + "django_prometheus.middleware.PrometheusBeforeMiddleware", # Django Cors Headers "corsheaders.middleware.CorsMiddleware", "django.middleware.common.CommonMiddleware", @@ -141,6 +143,7 @@ "django.contrib.messages.middleware.MessageMiddleware", "django.middleware.clickjacking.XFrameOptionsMiddleware", "django.middleware.locale.LocaleMiddleware", + "django_prometheus.middleware.PrometheusAfterMiddleware", ] ROOT_URLCONF = "app.urls" @@ -170,7 +173,7 @@ DATABASES = { "default": { - "ENGINE": "django.db.backends.mysql", + "ENGINE": "django_prometheus.db.backends.mysql", "NAME": os.environ.get("DATABASE_NAME"), "USER": os.environ.get("DATABASE_USER"), "PASSWORD": os.environ.get("DATABASE_PASSWORD"), @@ -285,3 +288,6 @@ CELERY_BROKER_URL = "amqp://guest:guest@rabbitmq:5672" if ENVIRONMENT == EnvironmentOptions.LOCAL: CELERY_TASK_ALWAYS_EAGER = False + +PROMETHEUS_EXPORT_MIGRATIONS = os.environ.get("PROMETHEUS_EXPORT_MIGRATIONS", True) + diff --git a/app/urls.py b/app/urls.py index 2b540d666..104b27656 100644 --- a/app/urls.py +++ b/app/urls.py @@ -31,4 +31,5 @@ path("forms/", include("app.forms.urls")), path("galleries/", include("app.gallery.urls")), path("badges/", include("app.badge.urls")), + path("prometheus/", include("django_prometheus.urls")), ] diff --git a/docker-compose.yml b/docker-compose.yml index 6bf689022..e5701e541 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -5,7 +5,7 @@ services: image: mysql:8.0 container_name: db platform: linux/amd64 - restart: always + restart: unless-stopped ports: - "3306:3306" environment: @@ -19,7 +19,7 @@ services: depends_on: - db image: phpmyadmin/phpmyadmin - restart: always + restart: unless-stopped ports: - "8080:80" environment: @@ -35,7 +35,7 @@ services: - ./.envs/.local image: web container_name: web - restart: on-failure + restart: unless-stopped platform: linux/amd64 volumes: - .:/usr/src/ diff --git a/requirements.txt b/requirements.txt index 89dc0a813..1771ccf2c 100644 --- a/requirements.txt +++ b/requirements.txt @@ -34,6 +34,8 @@ django-rest-polymorphic == 0.1.9 django-mptt == 0.14.0 +django-prometheus == 2.3.1 + # Code quality # ------------------------------------------------------------------------------ pylint From 79c2ff369736dec08d37a865b3bec79cc683affb Mon Sep 17 00:00:00 2001 From: Thomas Date: Mon, 23 Oct 2023 19:44:51 +0200 Subject: [PATCH 2/3] profiling --- .github/workflows/ci.yaml | 21 ++++---- .gitignore | 2 + app/urls.py | 2 +- compose/Dockerfile | 3 +- docker-compose.yml | 27 ++++++++++ grafana/alerting/1/__default__.tmpl | 53 +++++++++++++++++++ grafana/grafana.db | Bin 0 -> 962560 bytes profiling/stress_tester/Cargo.toml | 12 +++++ profiling/stress_tester/src/main.rs | 78 ++++++++++++++++++++++++++++ prometheus.yml | 9 ++++ 10 files changed, 193 insertions(+), 14 deletions(-) create mode 100644 grafana/alerting/1/__default__.tmpl create mode 100644 grafana/grafana.db create mode 100644 profiling/stress_tester/Cargo.toml create mode 100644 profiling/stress_tester/src/main.rs create mode 100644 prometheus.yml diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index a43c4af48..424f3d933 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -14,7 +14,6 @@ jobs: lint: runs-on: ubuntu-latest steps: - - name: Checkout Code Repository uses: actions/checkout@v2 @@ -33,40 +32,38 @@ jobs: test: runs-on: ubuntu-latest steps: - - name: Checkout Code Repository uses: actions/checkout@v2 - name: Build the Stack - run: docker-compose build + run: docker-compose build - name: Run the Stack - run: docker-compose up -d + run: docker-compose up -d - name: Make DB Migrations - run: docker-compose run --rm web python manage.py migrate + run: docker-compose run --rm web python manage.py migrate - name: Run Django Tests - run: docker-compose run --rm web pytest --cov=app + run: docker-compose run --rm web pytest --cov=app - name: Tear down the Stack - run: docker-compose down + run: docker-compose down check-migrations: runs-on: ubuntu-latest steps: - - name: Checkout Code Repository uses: actions/checkout@v2 - name: Build the Stack - run: docker-compose build + run: docker-compose build - name: Run the Stack - run: docker-compose up -d + run: docker-compose up -d - name: Check for unstaged migrations - run: docker-compose run --rm web python manage.py makemigrations --check --no-input + run: docker-compose run --rm web python manage.py makemigrations --check --no-input - name: Tear down the Stack - run: docker-compose down \ No newline at end of file + run: docker-compose down diff --git a/.gitignore b/.gitignore index 5bcf46ad2..83aec8514 100644 --- a/.gitignore +++ b/.gitignore @@ -26,3 +26,5 @@ mysite.log .coverage celerybeat-schedule + +**/target/ diff --git a/app/urls.py b/app/urls.py index 104b27656..2a11d1221 100644 --- a/app/urls.py +++ b/app/urls.py @@ -31,5 +31,5 @@ path("forms/", include("app.forms.urls")), path("galleries/", include("app.gallery.urls")), path("badges/", include("app.badge.urls")), - path("prometheus/", include("django_prometheus.urls")), + path("", include("django_prometheus.urls")), ] diff --git a/compose/Dockerfile b/compose/Dockerfile index 3e7579d93..5cf40b352 100644 --- a/compose/Dockerfile +++ b/compose/Dockerfile @@ -18,7 +18,8 @@ RUN apt-get update \ # Requirements are installed here to ensure they will be cached. COPY ./requirements.txt ./ -RUN pip install -r requirements.txt +RUN pip install --no-cache-dir --upgrade pip && \ + pip install --no-cache-dir -r requirements.txt COPY . . diff --git a/docker-compose.yml b/docker-compose.yml index e5701e541..236bb2930 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -57,3 +57,30 @@ services: container_name: rabbitmq ports: - 5672:5672 + + prometheus: + image: prom/prometheus + restart: "no" + volumes: + - prometheus_data:/prometheus + - ./prometheus.yml:/etc/prometheus/prometheus.yml + ports: + - 9090:9090 + depends_on: + - web + + grafana: + image: grafana/grafana + environment: + GF_INSTALL_PLUGINS: "grafana-clock-panel,grafana-simple-json-datasource" + restart: "no" + volumes: + - grafana_data:/var/lib/grafana + ports: + - 3000:3000 + depends_on: + - prometheus + +volumes: + prometheus_data: {} + grafana_data: {} diff --git a/grafana/alerting/1/__default__.tmpl b/grafana/alerting/1/__default__.tmpl new file mode 100644 index 000000000..b8633d168 --- /dev/null +++ b/grafana/alerting/1/__default__.tmpl @@ -0,0 +1,53 @@ + +{{ define "__subject" }}[{{ .Status | toUpper }}{{ if eq .Status "firing" }}:{{ .Alerts.Firing | len }}{{ if gt (.Alerts.Resolved | len) 0 }}, RESOLVED:{{ .Alerts.Resolved | len }}{{ end }}{{ end }}] {{ .GroupLabels.SortedPairs.Values | join " " }} {{ if gt (len .CommonLabels) (len .GroupLabels) }}({{ with .CommonLabels.Remove .GroupLabels.Names }}{{ .Values | join " " }}{{ end }}){{ end }}{{ end }} + +{{ define "__text_values_list" }}{{ if len .Values }}{{ $first := true }}{{ range $refID, $value := .Values -}} +{{ if $first }}{{ $first = false }}{{ else }}, {{ end }}{{ $refID }}={{ $value }}{{ end -}} +{{ else }}[no value]{{ end }}{{ end }} + +{{ define "__text_alert_list" }}{{ range . }} +Value: {{ template "__text_values_list" . }} +Labels: +{{ range .Labels.SortedPairs }} - {{ .Name }} = {{ .Value }} +{{ end }}Annotations: +{{ range .Annotations.SortedPairs }} - {{ .Name }} = {{ .Value }} +{{ end }}{{ if gt (len .GeneratorURL) 0 }}Source: {{ .GeneratorURL }} +{{ end }}{{ if gt (len .SilenceURL) 0 }}Silence: {{ .SilenceURL }} +{{ end }}{{ if gt (len .DashboardURL) 0 }}Dashboard: {{ .DashboardURL }} +{{ end }}{{ if gt (len .PanelURL) 0 }}Panel: {{ .PanelURL }} +{{ end }}{{ end }}{{ end }} + +{{ define "default.title" }}{{ template "__subject" . }}{{ end }} + +{{ define "default.message" }}{{ if gt (len .Alerts.Firing) 0 }}**Firing** +{{ template "__text_alert_list" .Alerts.Firing }}{{ if gt (len .Alerts.Resolved) 0 }} + +{{ end }}{{ end }}{{ if gt (len .Alerts.Resolved) 0 }}**Resolved** +{{ template "__text_alert_list" .Alerts.Resolved }}{{ end }}{{ end }} + + +{{ define "__teams_text_alert_list" }}{{ range . }} +Value: {{ template "__text_values_list" . }} +Labels: +{{ range .Labels.SortedPairs }} - {{ .Name }} = {{ .Value }} +{{ end }} +Annotations: +{{ range .Annotations.SortedPairs }} - {{ .Name }} = {{ .Value }} +{{ end }} +{{ if gt (len .GeneratorURL) 0 }}Source: [{{ .GeneratorURL }}]({{ .GeneratorURL }}) + +{{ end }}{{ if gt (len .SilenceURL) 0 }}Silence: [{{ .SilenceURL }}]({{ .SilenceURL }}) + +{{ end }}{{ if gt (len .DashboardURL) 0 }}Dashboard: [{{ .DashboardURL }}]({{ .DashboardURL }}) + +{{ end }}{{ if gt (len .PanelURL) 0 }}Panel: [{{ .PanelURL }}]({{ .PanelURL }}) + +{{ end }} +{{ end }}{{ end }} + + +{{ define "teams.default.message" }}{{ if gt (len .Alerts.Firing) 0 }}**Firing** +{{ template "__teams_text_alert_list" .Alerts.Firing }}{{ if gt (len .Alerts.Resolved) 0 }} + +{{ end }}{{ end }}{{ if gt (len .Alerts.Resolved) 0 }}**Resolved** +{{ template "__teams_text_alert_list" .Alerts.Resolved }}{{ end }}{{ end }} diff --git a/grafana/grafana.db b/grafana/grafana.db new file mode 100644 index 0000000000000000000000000000000000000000..2c718999454156d770c44001747a89fa59264d75 GIT binary patch literal 962560 zcmeFa3y>R0dYD=0R{{MT4u^x8r8vxK?ktI6H`xzzNH&+t#dL!lEc-#Cfgw3u4p0qL zch?X=fk2_j9uAkT?wMV!tj8%7=djNTOY%c15TcS2T-E zE6*vBi1JxN6s7BVMN$3`{^x&@ABHbI?l1T^B7AT270Nh~|DIlm?H~CSn&x*#zCQAw zM*d{v{~Gz~$iEr+-$(xC$ghq3%FuTAZwno;KFXgpj(QH<&yixMPUY^aQlGzkVFV3ZIkV3ok1+uhA3SO=P zIacrsDg!Dp*i|!6+4={%q=UDnqVj(hJGV zO>!l5lO%K5rSu}?Tu3cu$>I|HpPQfWA0vegz1}d)s-I1aY?Pa81(HqO2$+y?Ao(2N%cd7n0RfveC{`YuSUsS|Palfds@FqieJ$T?=ym7A zD7nAm;m&cR+@wy&xS_OPSV4d^VfVbC#%H0T)2yQ0wN&0s$G#XPw-7h@0Ix5%n7)?t zbfQDXaP71xsC>*9qqtv12X_xYdL}9QmK6yCu$Wt3H6+__tigl{RfkkbXm!8(af)i^4?VI8#mX~R`QzcGX zNmF=4V*A|~Gml>yVA|=G>U|juYN{8$M}2h#a*e8Jw>p~6fT{@gR@8B>$aT}VraVa0 zOd+$|(;2S{1g8Ww1yUd?L&CZKH) z3#}>{4YmU6Tn;1zUDz;+pqb8^jJ&zDG@nW?`n4tA?(2&u4n!V$vp1XB85{ad<;oSF zto?M3P2zgzU@aux?v<6xl!&J6?OZNbHfmDca-E>W-~)vYf~9?Z@z?f8nx5EH52yiw zf1ht#wwuUXQBX6@%ub@z4+{vGar^~@XCIxp&HFjTix(ENUYt7(hUNlilq5t)8DCa3>LgWP#3ds#cW6^HB!HFVzo zNZu`pt6hEZaa!#%@PiTbOZHpv`SL_k-s+bBO^cHB&S&(^S50;5LITs)EgU`c7_L`CWufqAPhO#m>fS7 zfSbO=_Kv9=>E-NlaHYBzjq5bZJFX*kv0e}jf;#~V`x3!Mz|es`fuv)flGUF-hYLb` zi@tDd;{4Ra)b#k|#Q4N1GI@4p;_S?+$*s@45LNW;2hiy`w(}>F8NO(io0TfDOj2!@ z%XF2HoX^6Mhhy8Bf+XkW$n4U5ZefvFu&Dx_>AXfb-=DimMRe3_IhB=WyC9L~e1E9& zxy;g4xAw63k_?&DViL|hItZLyl2t7MXbM@hlD)EiHH9U`zR zgvAfr4}YaaBm%wvd{nt&54rNtvor?z1e?%LQW;LL@xn*4u;id|)SMbsam_(P=|t4B zAdqR3t?Y{`Y5SmCxxcF1HHDolM`g{w@SLigaeJd;G#YS_;3yeAE~6Vg;#qSEz2*p| z*UcLsE}D1O0x@UHa$6?#o5QMd@i^4V2O(w7jc#!rCU)H#A7`dEle(5mXHs(#(e1vW zsFL&GbF~w82y_7Z1wTd+g?zi!z{NpTIhTgU%+<{rG0P?15~f}olWep)rUT{=ckbYk z1xdrUHU^@~#gFzuiAA%vNoYsr8)ma!)L}}Zt=gDMFD|DtSvu7&`OAAgpV0LRj4Nl` zMt``gKl>9aabQA7`Y{Z+wYPmQ(Yo z*(?!{o>}_uq*UZmW@*8JmEV|@fp7Gy%EBXxogEnyw&Er9RF(A>YaAH|`rMT4dP66( zA&pqaN*UW7RO<8rJ9eeQ`UXro4Q>~sQRVa(n|@nqCU@E6w$D>qy8RFpcaO_TSNCKq zM6N{P#pW*7I-c?d4??~h&PJrYtf{K9bQAhGqtl@-m?hUV!a$(9H7PDJ_$aKi~BX;ux` zn{j!m>IaqxPh?zIyF1p$ORUH$Km{PxH%kNo|S zpBVY0k@rVRBiBYQjvOC3GVVDCXXG(l^w-pZ<7$u={uv?stNF$Ke{#TD1Z<;ypLe zeKg8Wk>DmMdU4y@*B@wyRxEeD5bHh(Xxux``I*kXXm=v2RjVdk6s9*FK#QM`bRX^V zPYa;j$p78n*L^Um)r|Zdee>ns?sHMUpjzGBFzCJCa6xLY2Vi<504k*_N7AO0Z$B!C2v01`j~NB{{S0VIF~kN^@u0v~SzFZINa z$Jp(P?Bla=bfT5l&4%Ud|Nl%G`7_0N2FMZnG%CBCuAe)5c0xO+pMFDIJ-zzI*_AV;$snw~|Z=5YozoAVQ zCsxj`yz$1$>Z#S!XD3(QIJbIg;@nhm;@pIOW_9|FQ`2Wl+8d|OoI9sYPn~^(MxUFS z){B$Hv!}J9R(j*i>ExSd&b_(%-q}g(ed~^~nO$E>WM|00|%gB!C2v z01`j~NB{{S0VIF~kiauUfNuB?D7Tg2-y0em{HKHS1AjK~HwP}pZbpAUYWDr7zMt$n z)cZTVE4@d0e!SPFTp`3bw+{LBkc zMc;k^oz7j4hds~>p3keza#>p`>!N>L<|$e5VQ*Dx(6IW3Q3UymMYCD8$eT+`^Qq*b z@45bbf9~pBGMjSLYdMuAvTPSfSeo<45-~iYVmUZ5J#Ks>-=EG-i(az&6Vz!O=Fj&1R$3bEPi2 zQE%f@duwALs$BeNACy=$Ynw#yTLe=QZPmt9dT}|G$x<`CU8|NF?3?F8oyIfA>8t>=Qq!uNEJd>h^5`Y@9cBU=?Ti%q%^5}s zvYeVv&1OkK@U~2&zoSx-OPQqw2UZ*Kjeb>Gpf184U~S!*PjOT7MEry|VjU}GY^jg- z$5iU{0SOy0sb~1@Vl=9p{$kT_t1tq+sywBoBT-b`J+60L-Sbxu!U};mz?u7naBi7H z;Y@jhO9fAPgTYLVgF%kM2g8b7$%CPt)@YtOOB=)l&qJGyRRhM0pN21)taTlRU$8cJ zq&^w{;+m=|OE;m9GdiUum?hUV!a$(9H7PDJ3RD#eV0jml3n}8-mo`IYxldKnvrt8e z+CFFY&0R}5Q!69D%4ar^&%D9tg2b{f_jV}M8xW3RZ7tMMBT1pv9#xs8gB#YEq**oY zHg$2ez+`=r*G_#GNWMp-?3Y3Jbs;m`xLcNmHj72Q0h>i{A1ENy>vhxH z#R=h-QPE+OS*eK&L^obKP0{`TOUe~xWBAd~*N1*)XnF8I4*r*erv`pH_V;5a zqyJ5GTK$>6mwW$7??TU)yZ=L1HuCS4Ux5tazYoUgwnfcVEBB~^hKm&c;Yg>7n!`P#zG$&K>HWT$?16YsH$xn$DLVhs=M z=-nQH^_qBiAOt_rQ7~0G4%YsjPsX1_sN8JgqEi&-6JB$O}iL36k#Re>CihR|rLBCh6-6~s~tQl+tz$6#{ZI^!!1E#>hBn%C7|5J%Y6OnM=i zxk;|1Zjxj!yOdsprYxiu;mk|ue^)%|s0~OQP9bf>dq<;+JwlHPmUYMfDQP&@LtT6TNr(l0ygsRxG&^ss1 z)1#-m_rT-rrhHc{ODS0)PHn&VT2wjzQI7Tp-6DJW>T~V z#s=G|hR-}%LgAQ_C37~w+`!Thcc|0v(EId6m40QFI_IOopY%A?-!DIXvhiKBM^NZO zS;sv3WK_9n$NX{PPqTgz4i|A#E6lU4$(%v!h0-46TxD85xp{;h3Pm~#!1PzxQ%kFN z>?B=%2P$X5(yAYg?x5|Csyw#sT%*_`BTzk$kP7g@t8LdfUKx%xe{B7ZB8IDX!lkuu ze?VYj{Sq}We2wE(>YrXnw;*1+Jx;GKEZJhz9gkrn>5fWw+7xWBI3@E5Ph1MQbD%Jh z3YocfhL_S$$#s-gO8)UWwM_2uUWk{FOxpc+?_pJGJcQm4oHlrUOOG79AA%KO%k9AV zgO@6B2;qeac_kKTGXILI>pvb@kqdN#yauZX8MK{}2ZkQ9IU6R?;U4)#6je1*O9 z)BVWHQRVi|XA=KXt<;#igEC~!JIy5zUZMtlhjYne1laX#Vn^aT03c|Ccdc3qz_pPf z06aoEroZrFRJkSJGLmBzTvrGoth6IoR5`L!%GV&!i4@)f>7s zK28>wvLutbmP=<+bD`TEPEB3DtSV_)VY@BJe(6$FDcX}DSF%(hMzy5hC#z;%5YM2& z!fz0FHj_$bQzX4Om%2d;>A4&EKx>3wMyWuS7D*uxUm(YX07#NJFKMH_KNVGS_UVvl zwQ_UKsODSb>Lim{UxVa%FJp^LR30ZuVXWXMl1gRGsmjtLE>qDgH!D@*WeI@N%9dW| z{oyyaK$3HFWOivjw*XkYoCT6i-N=%~-26O|u=rp$sw~+-AV`hrxOR796(5# z@5V^m+;}spr0qzs(UPin(qgwFP@Zh+aw^ld$&Zpz<(91mD=pS_7(1o>%4PsH87CW4 zJE`5zUwFI#pOpyEWP^9_0{HnKFTh(DRpt6&0N}LD8$u_*erUupNkuOi&5EVpx5&oi za%w&`n6##PcQF26B3msz?>vdK5+VN72lsT=9#?6Np!Hzo@b zrQGVj5LM1^Ux0FpW^L0q5g-i}Z(}OGxSYylDd{DlI6B-m^m@ZEtA+kCQfR<sn!SI-}$)(KFf*?KMlEJX!pQeWN zB!$70l-ttWwUl5Exgnx0W;)9UYi==pE$7+Owpk?O)-ziSqIC2=Iv-VT+Au{11q)hj zryNlxsd4Ak1x>nOKBWR|&CNuW=?~BO5_q}?I>Hfn+DB);kOo2({RL{cT&r<4lU_(> zZjvjhnT7Z28Rv5x^=oob?o!Ub+>bU!^!|MCD`+Xwhe>-r295jw+gcv2zdj1~pFy)(+seW8 zk^3nCcn1S_iY`xH=JGij>b3ubUkH~;YS{c#o#l`c+PX3wRnC2w1PQq9_p0ATZ$G^@ zPK5KVw{v#iR8+Zb?+2O-##){3m9%o1WOS`Wma64V^0uMhgXIG?c>HVbDz&hL+Tvyd z7TwFKEUBBYp}IhhI!TU_>u;qpDKFG7Emblsvwl>vzPU81Dwl;#mRI~PH*3iWRk;u> zha2x5@An>^Y&(a$Qn8lPO%b*GVO4KU=BT+FN=F+dM>hvj6}Jzah$?IL8DGWynZPY1 zPrrci&pJFN6PRwhX3nmrvESce`@eR z-`#9f$=(aYgG1Zhzcujg;P-b|yT01>DDtby?*EvOs+XQL;%fW?2oq<*1Yg|b3**W0a`^2JUR>T!|Ckq@Y`y-X z8b5qE^5GHox(lxa@5@WPn(*6&zR7nrL0A54{OHlh*5P2y^mRC1?exd@w2|Q3|K6O{ z18V&Ap@^+|J>y5^w8^zx;#)GF?f{TW=*%H*S;B7W7VecEYe9LqvBGXqUwJMdMnL=i_ zr=6FU3K2$i!*E{E>02{TWL^!EDBsYlmj6CK@y%p@d>-BqDZC!f6;rR6mY%1>u2ow0 zzBS=Bfo`#6E_ErHn}^q9($@ldZ{G7H<1G-9B|gmbsPO{_B41Wn2U8PF|L+TSD-GIX zk9O>}vI(!abz3L!-9>NKv_|8eSqB>4t7U298}K&KmY}*;Ej3!gie{yzRa@;(CoMD@ z&?Vroxl^Y?n~haN7kh|zs=X z!O&d5sgzWh3=Tx>0dKxx7+Kq#y!3ZZxQ5nbLFNvdF_%4TBKA>3@x6U7_puFyZ9T8X z4;_kZpLZ87%ob7{wBY@`KE7^tgZF4fX!drmcx26J7bzNh!NBZ!%q8r;5jB1paQk~E zm?rA(JP>$AD2;fot>U!J=JW%NrmEyNZ!Gw3&V+q%m|5i`g z#UZ;w?W?~-k&;hb?dppkKOVX1$ac33({9fX$*2EwjvRg z?w7Wctjr2~X(GH_IS+~&_|X+8uMmjaqx$(}(AI{Q10b_3v{{6{umnlEJUN^mY zT~JKRsOZpVm6~Xy-S`B3|9{uWzg0&5ANasOB!C2v01`j~NB{{S0VIF~kN^@u0!ZLv zO5nM!9wqi#={>EwW{y{k`$n}t0wFIuA$0%0U&$$5e>(JwL+=d!@nC7-Uk$v||Bquo z6#c#EE9%dwmwJApXQKNjyULNTK(h4UnaI0sKy=?eelTK3;LLFA(MdIa@L=Sl96MOi zYDWH!zRCZY2p*>J&^;cbbUMWoFVwi_9dJ$pl1PqLp7g06J&?IyGvKnPa9ZP>jKfi; zc-kF2g>;gzqjfkfE44dXuj?D;oxsUDWE9TJ?dQkU_|lPxebGC@rGA+54YOH?gLVg7 zo}SU`t6H;c36bNxe}sc$AvT=VIa?Hx&?83PFJtU7fKx>wVfT!w@gxW}>79oQ+1!$w zMo9=g#-$0L>L@Z zq^Bo=o@6N!=Id(w90)SfL9YZE5<5|*PJNd6Xf&b5j~t17pL4xfC|me?oLA%BQX@8D zFDKQV>`KS$kJe_*yA&)Koi?@zE_ku?+|c=Nvo1UTZF6Ok9;>@14a|UZm=2a#Yj~pY zU7Z+Xjny9mh}da+s8^D;>w7OsPr;Np21rU>th-7(43bOg`o{bCcfqiXy-T$bA} zj0)FFEihR%%O$<;UEnw>8x*1B?x^4qbS!#B6%wUSwO$DHiqA7oeBRF^ooeGw`%v*Hdu zs54=YzN*G^Fy3ynUJc%5%GWl|n4{Vl91etIk}W7)V)7zddNMFMdbLpxhs+ym;sfH` ze41!4BU|e5N=J7t7c)hnA?q!11xnx>% zwlLv0kOs$M!d71aS)jY7C9-hVo(~!xKEdv&``+20&G3qU zrHy6SqcP~X{&|X>!-6$w=S7+t8s`=`@Q^K-BxmY(yR>yl;47AYrx=vv+X6pB$hJW` ze>U%&Ze4>L#EP&U^j0LY(uDPiBQ+FXYp#@yVyBGk`hO&PLV^GA4+$UvB!C2v01`j~ z5&~bl7&lf+xK5^G(vNCl1;z|C}n@Ivpc8^v|9 zY8K(pt3k{vSu-}^{DEl1tsNrkkXI*-P5Sr^Iaa4Pi8idp7%8ock)j4$%ESqhw&2cl z!dHEy*`S5cT(_KxoGT@_kF8r)tub@*?}t%o~$u;AdT{t!GWMY#FuDnTfH{b)%%unpF#~ zKLD9kIKP5S24tu<%jGcuRlNh@w{DM(!czr0O>^tPXwfW}wORuz;ThZj$j3w0>PG3R z$zZQT?PH_&MrWo@jg8)CwQj;Eu&4D*2_-`8wceK_`Dl%5MZ*C!zG zlftjDQF!#BTmnq1#u`;0e$j%pP9Rj#YBlIa&dXYdi!bYN^2U-?;CUPr@cE1mPQ6xd};uj~}yEhsPX*xDyi-lMku(HbFaC&bv_7LkI|R2jIYc z5*T~jCpq`&K?c!^?MGJp03fI3FRkK+w9s7Kh5IDtQ{}N(Q@AUjTAoCfR^g~(KDzQ-fWD!!(O-QMzJ9j_VCtJ<+f8} zg8q{jBNJ3vK3|2Ozz1wog$^$m3>A9&I`mfqf{iK+G3e||S`myL8$9YOMoG986}1q4WkD zNpwJg33G=Mj55IrJi|i?1`uJRhK(QRt2cZ~D|!7sT-<=iBG}j=-stc~L(ABJ3I6|d z-v9p%c>kYdy2l_SfCP{L5`{rN+ zkN^@u0!RP}AOR$R1dsp{Kmter2_S(Ndt=d)G3Vws;nqC*{C`}ztBl+m{@U<+!^)67 z__e_w9K1B}ef=A;pNsxg^>@|h`aaS7uyLT?|xJvpGp)Vs&-AFHIm+4y~y~KNbd_{bbf9n$!^og^MkGJ6C zz5HSR(8DO~VLkUX(*DbU`J*Z{)_Z$&I5u&9YGP`7d~#xZ;uM)YJ2P>1=G4@qccV(u zeialYSt`NJnpfG=EbR79?jBsn)nW|!u33-D^*9X$v`Bm&sV z?WnS3A8;k8mh}6<>ggL4oX34SJ;CKAl02p6$4MF3-Jg#t%XS<@DCuS0g1cJjTUi|` zSU}0YW41Aunong@3riU%hD2qzz6(Bs8bf4dBldT}@^v3n5lG|d2+N^E1shey}63ZkTQ|ZO!R3=N!!jdo&TL|#i zSW{~tJ{?Sd!-K{2A75kWt2zkRQs-&zon~`1S}1Bat^VBGF~yGA6+q7CC-%@P33`tS zlqkx~o_#0d0Hl-tb4bY=t<+hd$EccOQTFolRDJ`2jOKXZ0Q5`4Kui%Tz)MR+J&)^qFgsxsT) zIGnW%EiO=}d~p+8WJ8|EtYqx2D^cZ&eJEHLf4F_u_3hxHc-eBw?)@B0E8eDpH`r)g zVsGf#wG{s9J+vS4-wq^|qc2Uj7VhST%i+B_VAq0pIXgY-QBU+5S08q%A7KCfA}|sOGAG&R2>-a|2zG? zvA-RADf%~}%j$nnt-inL``*4!^!`Hc>pdTJzti=5UG>Pnj%-Fom7j%-@K<@DD!265 z&~!$xY89PW+Dcg`TFuDc(Km@@x?l4flVqH1OeW{EsSL>`-<(g80#8;Tnbcx(Aw{xF zUKpe=OifHpk55jFPn;r?XJ;nP&YYUAyss+7+fZGpZq|rVE$R13?pi9(OUi4-qS>rk zd83qP;?OGRGD}xUdT}mwgA_WXl~tG9RFx~K_SMlgcB%s6WyKcntIEygV6o}B8ak)_o~>2WFll9*&8U*H_em@B<>hs9{b+-?wN5{~yy~rE zR#Z8?{RrwV)^*JiMg$!nyiR8nq%V=hr7TI^NH1rXMX3D+qf~&-$fhpCkhz*kFC;TJ z$(7VilFVh7(u+{aLTWL~axdoQ=ljPXx2OMpPFlJf&$@caAK!L zAle-0Og0VUR;-~}D?xjuvC>|$M;lRP%}(-eYF3TAO`U5il%zGxX1%EA&H5T0)J7v; z(pR-+*$Vd?O`UI-+)*1L3DsJsP|#SvSb2ZiFVv&TO?w)IOu|@tjF3&E#H9-lC_w_Z zO_02^bTomK-SxYwGQI{vajtZ9 z%qU30DVdwk zk_jTQ3QaSr%-REfJKk%U)jTbp+%v3oQf-#YjW$j4lU^W4A3QutuD_Maq=+AEG+2H~ zwT)_2xy+2wg0WVogS2d}tr^udQfkndt8Cse;A@+Tt<9QFpiY{~tbh}$fU02(wWqpq^SGvQLUinn+~~# zUToHN)~~x~99pCHmo5|dROPR##N6BfyQ`|H z-B>th)}c!Vp~QdzZog!(dsm~%ZKekS`RGh7l*WxIT`#$!2~&DFVJC|#HHja7MhB(% z-a|eop-|o_Ue#Vdh%>v89@@T_*`3c<-kLz1clo#s>la-XP{ZUZ{o_{yu!ztb4N3ZD zy(|f>X^qA`vksG(WAph^q}kBxEkTsPiq`N%;VB`=DCV`MwJw+5kIzdA6=K^+BFyem zbTYd@sXf_+&cl+b+@V%Duu~G0g4$u>r*y|8#0PdwLb!bAG}SCZ^>m}wvU3u1`m4wG zyQdE6CFW)7&WfsNw}RES4qd-m>2^n6qpULflUh{K?aNRd-SUK%X?%6K`CT)uD|05$Y1^&Z7B!C2v z01`j~NB{{S0VIF~kN^@u0?$4H+ls`MSmf1LFB;_POa6=if*mz z&Bj&l8-(58T(_*+%*m5wv#6EV&4x8|c4A`Uq@VmGWUCv+#)DCsaskRPOQSQRSC^Kv zqhq6fx-1;c(QvQyKv zkw1C%yBJ%D1dsp{Kmter2_OL^fCP{L5=l_-GzMGnjZAAh|00|%gB!C2v01`j~ zNB{{S0VMFHp3C&%}Nqc1Hc0`o-SA+dJ5EtNVZGzSI3u*WJj!i~JyD*zw=iF?&CFeA|8qt`4~O zmb*<8{5m;q0yiePe*>w%6qfQyc}fwSl7JsE!OsYfu(bM`Zn^$S1Rp77qhdg~>xNBq zx$~2pS?pjH|4{pW4xfu9%E9;h?2R}28Gn7^Vz%Li|pV#7gsWnwl zOiAHxH$&gc#Jp;cfK$tW7pvAPxB~Cknbo{KtSWihxsL2UJC`kOa78Z}&58vQgBPQY z-FnC#iYgU*(jQlj7ZJy`N~^TYZ4RhCb+2+-=2E0x2G`3;YdrNXLS6CDp(JxHGHs9B zgHfenUuhMPI^Ya9-tBnsLnz89bD!5LijcLFv|O{=I*YVlvInT|n3FpccrTJNFN=;B ztkzagplxN_e#h>QD%ZbAeI#-#8b;`v)YIS#tdms@=iH---IXgz0e{$`WGA;)u9is+ zusgKn=Gl#<=ENQGf?@YSNaFPSHKVSB3oNON%O`91SM8XpEa#zbnP(l@~s!1U~SKn~4Up3`G-F7?Y0beT?19UW)BZ}(9bzpgjQvevMusW0U$U>x|1GxuH*1@oN`lKu(20$y^x|?VlcmPpcl}N0LOvx>FMMpCp^th)6WE!`p(#WOE(gHYFcD$O)9qdip`yNG=ynWQSuD&Bp zH|LI>Xi73Ts~a96FzV!Q``#C*eW3of`MM!25*?m`)6DRa%N2#C42vI?+ZQK-G8a;kCk8VN{=)L{$TJw^-mA|ud#m~ zTO9b&b4MWgkDogdu}7E|(Y~zJ^;NwNn@YXG9k2=^Z-#doLM%`3sFV;cXm$cBJefQg zQCNMAyJZ9RhTtaDWWVzba8e5Hi}REG%V)MW&Z+T4BJ$BuX8mgACU|p(WR?X^orAy5 z2bMR5VB{Vb#ICN2Hk+CpUN}8<2sp*2ae9@m55)5bVTD>Vs?~OJ?R=JYaCJ=U+w;=Z zZ-?h-*7Nq7ut#Uq_;Mm*=UC6sJzkKg>+0M?5sdyc?~SnW38o7b!?h>S(Sibv3G5U0 z$XPXhB_6TUo{;Q>$t{%cH1f_#5Q{q3R;~^?9huz2D|aRv^Y+VQ1%B3)*iz1@@pwG4 z4RwMRuq^E3Y*0JhvYv=Vf`tTCgz&zKM|^t^!tCKU)OdO_VxMH4()suzyeT@vK?yTQ zIFWn$;dD$mo+^xsBVoUCT8%G(K)#lQa|mY+;m9}IDor@8P*5l7gxzz(j-68DNf2<{ zQ)5ZFFfoTi-J_rIFbk*6d((Y5jsjyd|MnNA)%fIO2av$;AMfN?IO9#+n^NQF4@T_QJY5Vf+?cCm z9^{@VgtbqS#~BU&V$3(AtfLbH6UvVqhl(Siia{}Xw&}J5(XG(aaiO9+9}T?8tn!ze z%qnYTy>79OxuEK@FhN`ENnio1qy3&G6IL~@4HAN8d2xd65@Ov94hSJ4V6Dv0s_}2@ zip+lhGivAi zWtY;6kb5Dum?h%n7Qc)(>!mhc?l-h@({nj53}(x)%Cc~9WlufVd&@XCOJeXV%0G!8 zIuzNu7-+mJ*F|}g_t@Gt2F<9#r4ne7J4{{SV63(^T#4~d_r-Uyj=nvq#=k{_i|!ZS zo#=~C9*jKl#)&%|od)n5BiW*(exg09Xp)5sq#`029LV z|2w{-j|q_g5P`U|B+0!RP}AOR$R1dsp{ zKmter2_OL^uonWj|KAHW%!34w01`j~NB{{S0VIF~kN^@u0!ZNFMF98zAFuvGX^{XD zKmter2_OL^fCP{L58jY#)dXO(#nwB6t}k%(W}w{y)Qx zT!o}N^K*QDYGP`7d~#xZ;uM)YJ2P>1=G642{d!bM+56g7@3FF;Ez{q`w7qMC$UUY(Mv|NVu7D+vN5@wnorGU$%L%L4f|MB zS+Ki#Yl>#MS*gm)b*g0ELtBJS&drh8rTN?fw8j&|^%M*~Nr?pG1N&%H$=SWZihY-+ z(3heZJFDE!{+QZ7us@|L#RpJ%t_J=~b;5nD5)Od*Zf>;5kh?mU%%()C$Z{&{X1y>$ zuD_Maq}<;my-XIN@iOZ7?bo8pQfuQ~8TQh0sgGD0_q6>DrwA z>SM~C+Eck#Y@#aHMD-KBx9?T~FWHAx<+7x--4?X<3Hue8RJJKdSChG5g!-8048%Pehf|TXY`f zip#xsJ0*6~*Ke_#ZyD-&`(;&G4h-1lno-TebYmISHO_s<6Oi3+zZ6w;dq1?Et_9uY zOPLkQUA@!wP|XS9)ii>ui9lR|h^rZ%&vP2j9HG-$T{gAar|o!Dxo2PZ`@&g}=B}mk zK?(BCtmTFpB{B{RHQrgd#q_lt%#@3BsT-uQgUkiO){!mk@RpKe1ztH!uF^?lYr}q# z&f`PA;6ZU8uS>!7dmQMYsT@G}!!+)TPn-@A?4e%OR?2!w;%A;_G^*8hak7Oft*oIJ zn{_?kF4`GnP#;|jX44BPww$3VK{GemYEl|2B|mE)P?e-G9_}_xOWXA@IBvfXRZN@O z7j6W6#bYJ9`o_0Lc}uIW=~ic@>yXh=IF>-zvWyjY@rAL1Q-NIF@cw_?#v=hFfCP{L z5n|9k0!c4s zQ%5E2*0#naeJv7op&V)MAzuxR{%t?;j%tv%Z!WbJ5D&IH$69v5pXW zy>0e}UbXU?MuTczzOFaS@`j$TK)+~fx>mOII>#Z=y8=nh&5_xq z`P>4?)TWGZ_ma8PrDSeCOD2e zH-GC*`z)x+hqV3NW`$LAj~44&V5ywJkxktQ8aHdR24f}^4CcWys%v0;LQzgz!HUj- z3C^Y$QUPPxWVS~dD;;p}+GkWHbsHF#>Sm4OayZtTFybt2Ex$22msz^%Tl=7;7m^iZ z>hh}nMpQ}J8to>tw#f~Tn+qlrVwq%PD!sUz%4F%(u;khgHx0ENj!0nW>5M>yg0Bg( zoSIL~X5I9`SaK<|wBSa$ML}DnLKZ=t6+6dlBv&TKO!^kjE5a3pu`xEtQs)x z0>;(NaiTTH+f$FRu5M0lY>g7HOSG9sZQP!WDtDM7 z?@}$lLpu4YJpnptQxnutCwH*ubU`um{UkMP(>_UU*glZ4Wd%h_T4R01)aoU$NSq+= z!1UY=-eY1KVF=Ta8;Fu>chNqfDrcIKsv8z8Guze4B3mkR!lbn{?Qz<|n4}tSSqQeS zU2S{?NEhPX`j0lx2``M%WxurEkEZQ0SWSH2eyErmUe!meputCnDw zCU1K~2Q-GYDU-w~!^%<@Sc^#X`+Bj-wu^ebZbIoHiS-SwoQJ)U=Em_Io*ND;A%9WB zM29EdtcK@B&e;a!~QdEDq?%jdh0p+CW5+5CYQ;o;tk?%X?>n0OpPNIQ(R60DM#sg~qMyC!3)O1+W<97G@2fa5c zVOQqW_`?e@?{peO&bc`^<<2;QYt6!KQ{l1Y9L6v0W`sSq7U7~%VBk4*1%{t1BwSJw z#4IGXzHmj2U$_wYXv80plCs*hhu(PR-_gde0SD|2Ys4Oha;N#jYmnc6!i5d7jnV{M ztk9*Fj@E-KQ`El*+9R zpT94)E7?mX^fWD_j`5J>iVi)r&lW*`DTON0xAT}+NrD>H(_lX zy{5*~@b9#j(_hWHYYeyN{FtmnT5m1enyuqn*Dbq{`0)L!YW&q#BVWGgsHaz+U+prl zHnc<7qe|}5F2TG)Z_eR3gA)#o5H&I!E4gCM3xu1D^)<7;8N8g%Bik&bEyF6yZk)69 z`*1sN$Q)L5t8NtC2wpTO#D+V?gmQS-o!v}=RTeK{3&DELEUpU;7ozI=8oiG?um=Mv z{5u>0AD95|em{tV5bv6`IJF1zc*}yeDVR`sxH~m0m|s%Djx4G1S+L&1UXNKB*XViH z+fi6II3pPd@_fSZ&AYkjIQ9pComf=k*DpluEB;sv?cn&m0B$bl-|$4e&`z#!Qm3Ie|7tYsx04&4NWIYB~moY%}SM6+FFBHCef-@)6y)%q(LiXT`OC9-T6ui zeq@0p=jO=l(tK`VkrZg=0?DRsWXWP~ex6KCOihnZPK-~SB9mulCeF^BI{mJFT~*E* zQ0ZLVtdXK->1$?vGjEiLQ7!5B=Q2xINqTWEb%PYrb2svSRe7_%2Fdb5mV%@LyWf60 zs@%2@2HREF*Pt!5n!Ps8E1>}LWmA_^8K;qRsY}V+e3nc|ntSRkJEtmFj)N?@S_#@3 z;!29^TD_rLcL3 z>NT^tULZ@*VLsggIaY807sd)sio|)D6jSyxNU;@bC&ly*r6_5Q^%YaAmuR2Xw5ndF zUmh=;m=8pCb3R7uVLLD>-XR-ux z8KU-8D#Ph^GED4H2Cb~uE$F_Ea(IcPvTQ%Fm!eAYOD}^g#kwvXDjTP{dS{bw&V!O) zVnZf%BfXqmZqeob0+q%cr&lxSg=FR?xstj`lDX_sdJzg*NG*byf-y%;RsR@q)!)k{ z#(Bc~u{>9^q1Rc{-OAkJ0*V^S=IL!HMpT_pq|@7ug%w1%466)U5DwSxTaw_4Zq<#V z8^Ie=tLq#22H1RAK~?=;+c>amnp>726CcVR7B@=T{nzb9RY@&D=d)?SESE&f#%3V0 zaf(e2Ugt|XUS_cN+Y3=eX9JDSb5*lC-mDsTo4RX3nex_~Wjzn`SKjSui6xaM z%K_HJ6EJ&OM%7t1RP>V3tXQCS%c=R)EX<11No2qMxu{aH5AnwHwMRoQHtTxcE6=DB z2cjrza3R8|i_yUaNlS^Ymde*Ar`GK>OxAZmsEl4QH*^xv6TbYYY872vq~xxpc$bJ` zxQi8Ey~f zVqd1xQsd0mF_6|>GHz()rrvxj(533EEA(8+yF~wqMW|Aybp>DN1<_)GIX4Lah#Z zHnllD>SkzPs=YCU2_OL^fCP{L5F@lYfr zfCP{L5$%6ds_tgo0_ zy_DCA<-m{fY$lb=rbssV=6s420&xX$tiNEC3M9RlOJuB2{~WG=gu zUWD8Wsl_Z=T!Q~|^Yi^m+ljOUc}PmYkxJ)y=YAAlcLnU)W+@*DM{{I0qE6>4j9FDa~4`U2MWWcU_Gq5|OQO zhFGgsO-r*tioB(*1%KTNLJmgmk+M)oJCq${La*OF}xfG0zxzr6(*m;2kva~1;G+qyY7DgYmXRP4HBR< zX?4A7x&0cp70g2D4a={0Ufkk&?9ddxEbt-U-ig%SVuIR# zKQHZU53ZXgVfWsAyd2z~_+`Dl6FEE^)j|HP1l<20P>V?O1nOc@iAxsw^Ll4Na%3bYg4h1ZIl{DVpVG zrAjQ5l=bSGwN6e=oO@$AHJ_Tzl8N(E6I0XUlM~|;r^w{lnTfMAr%u~3yB1Y6`v4S` zER_h;1+r?^iMv`OW|jCB8LENxZCEk<6gyl3N`>jQO;vex7i7uk6>~%9;_$JRkGCQ_P%qU;JN*j6DF4IQZu{NqA7MrhWRlN** z7^ks&Rhte)%2epCeMeR9+-@Tu>&(4M;%reQYMZp*QfxYbL@6zhF^EvlThk3jROHT1;chE*%W z(!nu-!TnBhZjQ_@&F2vi74#>Vb zC1=MuGnW)Sj-kEg+j$4qj+Dz~5m>uEMy-166;TeC%Qq#5+wxt=@xHC8ia{s$9J>bL ztS|%&4ftLn4c&6iy#bM4saczHjb=yV7s%10@5x*zWB*CQf6tPwb1;=lvLb%_Pa2H8ul8M zmt8U9i>)1=hmdhXEo8H5+-|DY4fE2Dr1tpTJh-CEJpSItLDov*Bd(qnOxXOOYz6mPJYtB!C2v01`j~NB{{S0VIF~kN^@u0v|sD!t?(hKjBegB!C2v z01`j~NB{{S0VIF~kN^@u0!Uy-1aSYqBTSeG2_OL^fCP{L5Z z?*Bj5-G{;>0VIF~kN^@u0!RP}AOR$R1dsp{*bxDI{(nc9FcA_!0!RP}AOR$R1dsp{ zKmter2_S)wH37Q+e<4y)hTj|f&B4imYyJO6EE|hN2i2cc5BL4EzPEaRspoI>jCL2h ze!puo^8Z3Y{M$PLyJxGHzPx_`Ua(1DYsugK@B6W!@A;&j9Jrqk=Ut$I_Y4cM1tPx1 z+AlJU@rru^#@+TE7rhY zvCXA%{oS;Em+9lPI&a?<(ghq8@Ot1a{;um5=__hCw-oxGn*E8=}2w&8djHS z_(i~w(`n0ITz*OwOtHTZRTlggmy7RsWa89-YP~jbu5@(FC?)t?!f7e# zW#*VqR_nX=2dZ+;2pSQZhu0M{ok8OPDFvT_GSgvq+Yh43l6{bCe|YS2Wc1a|J7W7- zFF&$&7VY;{T@UHgAhxFa~4GlbdcwQmA(g`aS)YJ=cy@EPc4XO~|JReHcf2=>|2O6cZ{uq}R zz6ITkLO@;gDGI+iLjN211BD;l`6qm%()B0$omL7ponSS26`%0y+m@Vp0!4KdS zxscnMmrxGDH7~r0pBLlUflyj%-u*x@h=S8!8BqI>ZPB%3k~hzJN4#HxE3_ZtO*+Eb zz>nqW10wHKRH+r)e!*^l$^Pg92*|Bis5Wnmai&tM7Rt3p6X%!HZmkd;ufp0{u!w;n zEKlNf^zN-DHwaJ4EwD^+wx74_QRUo6OMbt2-hg+qlH(4A_t**OIJjRrTIl{i5`Cn= zfB1(4kN^@u0!RP}Ac1cOfj_QB29;Pe8k>#{*}r>SbOm*8=JfQ;>8S^!zR#n^=*)vr z@SJFk&fL2FaBQ@sH;Q$mW`Wnt(V5YtzjXrVmzqT?X4SCFdV|cpr&ZTX*yb6b5K!$3wTpj~Z)jJS=>-N|v^QcO{KNy8;4rQ&@(7g<90OaFE ztksRuRg=M9huX(R?~Tq(of;dx&uZO-Phd~$nG#BdTIxDDiif^&s&{^+!2u_8T^bC| znD=PQoRp1q^Iq1l${>@|aLf5Iy42|xV64h-97AXM)-?H3>NQjLVA0i1zl-g~eh$@oR1W*uAph&f4r-1HG9B;gt z-RvZL^4LvwGf6yW@|fLBCdt{!Yi1{#UGHR)Op@8jOmb#6o7b7lY&=fqjD6Po-Fg>L zASpK6R!e_aW&?Ha{qA>v_q*S{7r2ix_JD4fr}uP2>cIWM*9X}56;-8H$+L&gyFLvL ztjkhCBuwk_1~VT~S{G^sRWF^3P*EtCsTxgQ>LyLMHkE>?M=R1DtRz-gtI}=FszkYy zagAOUNMJex)to!u9%bkD|_ZTs@ zxyMZIaZlwcdIQikrMgrq^M<;HE~eR-&jd1AQsuQ8-BG%}Ydx%~3O!URvQ$#dx*8CS zhg7UuURreJAQbYfChuWBkaJ|p;bCe?Vc?;xvXAunD2?575vw?BPqV9<&4nzE*c z(tkbASq`Tu*``EaA8uyJKjgQj+#j-=N>TbunXbO3%%xg&$ZGbIT9NZrm$3V<3>RND za*VM5LG3 zTJb4TMOtU=Z6GmlpDN30U(1Gf<8QEA$eCRmsK`o6l#l5R%$8Oq(|9fX-Gq(S~qwnh+{lg0cKmY_l00ck) z1V8`;KmY_l00cnb5hT#r84ers|F3a{H#p-7R(fM(6K#CIVXEgB?#(93H@u#SWwSr{4mqmVv-;PZ$Cll!;pIVqnuJXBk z)8zQY1wLns&GF}Qx_Co!ZqWE7i@C@pq81;DMTepzd~9MWIx#gerhTsdp%6FOh&Z}3 zQ9KjDtHN4AGSx{ZuFR2ASNVm-G@o2et)y4Hx%T8J57IiFoJ}tC*OycCiRD}Twd5^6 zkx4J67D&!~av`m!U&zeO^$eQn-N~46E6`mEKAl|kCe=e((v}bdIfcv+#&l{v>164P zV7>lKkel5i0AfWc^95x?E@cH(m5OCGs}{@IJ7iGm?#%Myb>6065oi}X=g0cv^$&)) z>H0H_wNl>oW<@p6s|vq8oLX2(E~gpEMLy?|&+1k#X9ZELNY!eN5hMZ@$dXW$auI$d zIhUMHQ^?*C`K!x|^G)(yrS;YS$$Ec?leE*0tvGh=QB=2brVlgd;Z}q8k8D`7CybSt z*`rZ5Ujr`JKM>+BHNuWk9tlqVcHOxx*b|p>JFFG!3bxv!s}foRZ9}yhjb;7(O!8_X zGneM0J-!yJ_1B*cb6Tg?ONCyRbkKTRZL%mbCr|lY^{acD#9W%1s==k%(w37832Hhm zHt3S!XCqtn_Xj!Q71B#@Ob4-#nBKBn?#`>TUHyJ7s=NMFh@00fl3Io7WZ-7DVN2T0ZVQE))oElF zQcD@TE6Xe;vlJ_9$1)l`Jz~wAo>FI}r*6|#U8p}1;)d!^IgBak{$vgLhiTYMrPgL^ zsMz$}zn#YGeQY3blQjpaAkjcT$QSqu_4rkOU8(TKLy;GS>gJjvRKzMTltcL0A1 z3~?KcAyT_4Y)ho(x=<^qF6HHtOBB;ccRxMuuFIowPxxFpyi9O*+PxwY+E|XlLhv$Z3gY=J&4W2cIeP;*HI^#m` zhX|8mB^Vw&Ym6toaXhIhBOf+eu-+TuQW_gCIkxW<$0F$s0Z(mbolmlu z_3~+Tp-yC0!_FrsX&Y_bQK=U9MmSjy9Y%RC)(2AFf~n7E99^l9tTi|fXvjNg%y;OW zKlvx?!4Q|(vt_vD?PrSaxCdeDt5p4d{TK}q-egU~oE6$~bWlK&fGr;A;D6NU*-C~Mt|@E0T2KI5C8!X009sH0T2KI5C8!XcytJKcXo7q zBhb~^5&niT|Njct_n-T|^5_&0B>@2t009sH0T2KI5C8!X009sHfybV}v91n|rvKga zAI$$Bduspy5C8!X009sH0T2KI5C8!X0D(u9fM@=1?EjzQPX6G@Cws*cKX>BN@n1SV z(({u&&xd~{^rs>D*qRa47p{%+<~9l1v+fffp>4ukuz&h|Ks%%F#`PX3pekEZ$vBii7WExC`o?aJ^Q9$u5N16x~Zrs zX0xES$~9$}i)c@MHrSscB`>#C(!tY|E2kY;KSxGe)m%{`jk){5{`2PpZ_Vr0*OYJ5 zNABCacGwhr$ZbQq6wk&Vm;JePZQ2z}mfOs@HHM+#hEyW+Z9UAPAX7kAF8hQz`DUw< zRPr%?%AbXJTZXy0sG_KBN2xc=RjNH(6$v)CAGJ+S#!PLiNj~Kr(T;y6*gt!wLz}dX zjP@dK({{vylHbZIv}H4 z8<#7x>+NT~HsuOAq&<0+Xsvdl!8QZ?S7|}0s#$4A%GVespE!}%?gjhDPjzU=eLS9N z%67ZBZXHu(ysgew;9iPS%_ zJ(2a#>;(Hyo$7dV*6T3rtarTiX+J+?ZR+Xw^bY1>G_4hF>D(H!_vSyvJVPg+r;|{! zdVgVg2x?>0Jk1CdX`TAb%{^imJ)pW1Jue*t;A}zk$Y+~wSr_U`8@Ycs*q=Dt zp`Ee~!gIKTZdB~d4$sqjt=8ZPw^JEr;0d$r(KsbVyRjYYKYP|{(Vm!|54&C~@Pxes zOL*6gLJ`zp|HY>|v|ih9dQOv|4|mNHwGI(HF%5*qxe(rSC$wNS*#8veQPW!vMWKJ& zUQR~3cl$gEt+NvBPm&d#wXMk6pUXCWJ3DJV&uguALF#^LxDvL}qv^PTd*xvNi=@f3Z8R~rAbYf^?x%&lZ<(E;^=GTo&ey9Q8qPcZ55tqzJl7+jgyev zzUwFf?PJ9UP}UEdau{VTSPyn|fEF&$Xnzmmc9+t5PmQm%U)?&fS-0q0!Ja6QdTvX1 z+HZVLcRWrY<>vWNFtawNnVzsiI_<~gOaNp3|Jz*O*ZbanRKM^*xj+B}KmY_l00ck) z1V8`;KmY_l;4vl8)yZ`PIy<>A=KqhW1)$g<00JNY0w4eaAOHd&00JNY0*?cMruqM$ zaD9K$_n#hzf}@Ne00JNY0w4eaAOHd&00JNY0wC}R6FAY;@l3}zjO$$k$LT}(8^-0Z z#_#`s&DQ__^&?z<6b%GG00ck)1V8`;KmY_l00ck)1Rg^I>;k|5t^W^)+4+Cm6OSPR z6d43S00ck)1V8`;KmY_l00ck)1Rf&-?Dv1n{~x0YM^Qll1V8`;KmY_l00ck)1V8`; z9!moF{r|D7b`%-}KmY_l00ck)1V8`;KmY_l;4veB`Tt{9;V3Q$fB*=900@8p2!H?x zfB*=9z+*`O>;E6iYDb|#00ck)1V8`;KmY_l00ck)1RgU2nEyX!6^`P900@8p2!H?x zfB*=900@8p2t1Yq*!uquaQ_|G_p^P`lRt4X();&%KYHRz$A9+thr{!sF9rW5SUC2_ z$HLt^U7zUu`<;t{zwB6|$ltt|cA*{%ai7x?;oi6)io9GBr5*aq3k9j7W<_aTF3GB_ zlz8^9vXPZVUMPvYDys#F&ntymu~eO2PA1YxKD98DT;+4AnbmA_>a3A8t0&9xiwk_N zIZBQ{mosAJ26INd$fe=vaC|5h9g2?dv5BeZ#MH=Gusr0r8?aso*u2ncz9H_@_Ysd>Gk`Rb-Z)>^9+ z$P(C7!!UWnI>hYSF0byEC02e-zNJ#u6N5EFUvgS+{d|bKshu@z zu~w4r)Fjit<%RsFlx1!0g7J1s+HG5zPUNf|*>GV_2&+ve&|jg|`o}`trTQ(WDxLI3 zUG7zpPF%evoy?2|>h@Mvqi0wRe{yAR@ruV|NIPY@BKbIqeXGL1Y@PK8gZ&hhEkV6V zMcP)jB$29$H92)t;%ilEl|oJ3qz7A4$=!ByEG)~yvU*sKPt45l(~EPNd1^3@D3@JO zt@A$4fm-gl5VxqkVAi?OnKg;OpntX-udCB)ikLMc8g<-YXlsg1>9S4f+G^Sy&tKzH^^b5{Tosf!$bN-U5b0S;BIuTVtBhx*1DSOqBVx0;f7QqSLo?|^~PC{ zDIhDCeZri4bx-MPFs@OFzYitFDvHX+7+(MCN@#g-kNPGz=ogMJ-b^cMb?wTFf^Ay)@;2o{1v-XKNI3EH|Y8<%g$Uv z_O~%tqID~3OlMa!uhmfX&Bch*mbxL37aGjqdpTY1u)!yM4j#KhLZbUeNe+-{z1 z%w?z8*J_8?P*WpE7CfR6U<)wunbHg2eX8Z`g6=DSVIZJ4267Ns#f2bDH<{k zq{K`04+puM&LqPIe?fP#WRGMG1*x<_EhIJ>-D@_1-~YdPUuGaD5C8!X009sH0T2KI z5C8!X009vARuN#o{|EYhmh1b!=nq~X00JNY0w4eaAOHd&00JNY0w4ea4-bJeo!#7v z9bM)cW~CtV1%;Lk^Ma~M#j;xMl%D%1uRR~==BC44`GO>rYGvM7Qc0`h?M04N>A5eB zvfuv$eZR`}{Sp1a3j{y_1V8`;KmY_l00ck)1V8`;K;R)I@LcDM9qqpfIMq4bvBy^c z0rvZU$H{-g(LcOE00ck)1V8`;KmY_l00ck)1VG?DN}ztK;|VUT_0s?Do(^}>D-@Ta zYm>3H_2CI&ePm=!nux~6V&df3=;%mnbZj!eHZd9>j*Uob6XRp+YhrYLa(ql2$xp70 ziR)uy6XR>*xUepWvFJoh932@Q9$t@4#3%B?T69#5kF1Z8(6PJ_9a$4%VthOrT^paw z$Jg`m;o;c$=!h^nuiTRh1>xf8g(!b+UdYpFUrKfJ5}%?&(h591;1^f;RX!HY#zwQ_ z5k65a7o?lg+BI3dI2s?n5Fg{uU3)1#KR3u1V9euyZ(LcOE00ck)1V8`;KmY_l z00ck)1V8`;9zFsyU34DhJN-HX^Z$phVxbWTfB*=900@8p2!H?xfB*=900_7U==1+~ zx*Wln|9_q9`?^aq-hu!KfB*=900@8p2!H?xfB*=900=xX1UftE0#PbW$I1VjqknjT z00@8p2!H?xfB*=900@8p2!OzQnn3-Tj$>PmtDRl!?0ZQZs!G+WtdyqW|M}t3k?4pxIx#Um`TD??ToMPS2E6G81_$IaJ#{wK)00|Ns$_)?siacK zw`7k$DNzurYPKp#CDLIyIvgL0MTepz>Dc7d$mG;$?80btI5sgp5g)%jaR2OgakT&c z4~^gdzs&W0`8{35P#y$800ck)1V8`;KmY_l00ck)1Rfs(!<}1U?{^jZe#e3N|KnpG zC@Bbl00@8p2!H?xfB*=900@A;FB&`q0T2KI5C8!X009sH0T2KI5CDNkh5&y5e`Kl>1pxsN009sH z0T2KI5C8!X009sHfwlyCyZ(|p*%9Hoey(fcLYly)*p$*fS2Dr&Y;D@fUGsltw3G(ISmjjSvh?`!nN z3~Y_geed*gGLcU5nT6C+CdsE3W|FIX?hvwb{Ne(iYt13YpUdeA8am|$jZdT%y*2g9 zMcz8DJrV4W#R6Y=Q5Dt-QmdTSC)|Hy>Yh$qnM=0GyC+8(QL)m=+2k^ReK|FsSiZ$y zOWxuWne<|6fkezF7t;K~BKYMFD>unvfn}jWCtg~W=aj;uid0pViX>*&D@xHniUrxXDEW#cs1lWA zhO8i+nooL2sIpp+d^F1|B~ez%+eiySg6iKYcn-zoa)}C(L=rz2R-NP6+AH<5GgKYol6UuwNn!M#ia`Rkz18ot!9C zH`f%QBC;k%a7$8w>cMdr-1nF{n!fEpq%=D<#>w_$o{Y(vSy|^IT3kCB?9Y4dwfGyZ)#2??r*iNP$$wJlJ?ZxlQU^=Hw~TS}53mHxj5n zbr98cS!9NLmf^p6pfdQ2JXm3@w5{d(xE4ItzZhxPZ+od{W8Tl)7aHT*v0#5B5_s#Z z%Xe8+n__?7&xcuYnI9W)Rl$H`k50=pA`sVsy@t`=5tozN9ExQ(sr&b7_1+ryX28ac zp73l{CUb2axv_})sqYdSxT63qXa-;YE>3!kEYsY{8`0nvg_;~2pvH$PbcON_5 z_5Gbc5%?E@SjTsF1Ssk|cxg}6uZFlg+Ed})IIXp!rRTgTt((g@cvazDD{^?b#Cuot zB<9kzLf%-C=ndhQlM4x289u!@mziI1%S%qgOGeOAs-o9F5?VNUDQ zdiTXKGL@nFbgHPCsZqY_zH8?k2~7-L zyH1?qp36D$TUW{XnrW$?pfbhk%rF@E2P%_Uy}Upb<2B|(l+P4)h;o`K4_4wvp#I4a zH~r=dRA6I?Qo?U<*}=*$Vs@$T{2{@Vk624!Q~czv9F zOjw&WeN3$+->F%nZF_9yWXi_b#=arltupuO9jqL{rJ5Vr^d{hJjB@g5T_^5m9NOjj z7^&W?EgnvFeTUPbl{fcC?W?}IN6xPRpRJG56i2d*t!e1!;AoHBe~ROzbT7qk9g&Y| zo%Ipw*E`sNT(|dws^CF)P$di!K5FFaanj;=`_aXbj4HHq_2Cfrx;ANA%R$T9YT+$& zN`K(4DTWi_V5ZIH|L+g%aD6)`zo++~^Z>%G)P_ur^l!H8J@~$A z9Y`UsoISLP`D(RNzezn=zjnt0rGM9D_r5wEyWbt;Jv%w|ZrIwu+0>o2cq&~_v-|Z( zu{XfG2k|Vn$6(tZ9w%vATOf1~>>e<+AoDZ;P zrF!C1rM4fjjDN1aLOpf&t5l?lq<<^x87{K3MBEO-WwM^axJL|4N5+`8*>0>bUal_( zxod1P==z$|_~ys?Zj;eCP_y-ZWz?o7U#~BPxQuPa=2xq(qdpFiu`BgHcJ!J0^$?fT z`n@G)p4j6&4^-TJ4lwa+NS~@N2D#5Q56u|hqZpKpYnl22wUVc_-3MwV#<@6yyy3YI zFhXnJKJ*ZCo4+%dXHPwzuep)9lKJ{R?Ya7Vh*PvSUtzK2?T7Ub(Ab;iP%V11aDN5Q z)aOE6RU1DD_;=)wjJE6=4Yw${hsSwisD3TPUHXnrQq%M0k4{kk*<$~%n#~LkbEcEw zk6ay&YbUu`FwYqi`X2EIKjjEVWE|p1CV#trqW-e=W2W9knCC|rd*-dazakabktEEA zdVYBEaih-9L+)=|tW+&q@%@~rmZ+yf+^$yiv^8dx<^;X@=Pmn-Y%6oq##_d7R`?Mg zbm8-D#kiKMzr?<7sXyJm6nc@!|X&?XsAOHd&00JNY0w4eaAOHd&@Guf!^Z%zhPIA4UJ@Mx8!tt&iHT=inT<8}< z{lQ;8_G8C-yFcIc|8}K1KOc}geu1Jr;xFx7y~wWgoHj3>G;d(8N+mI?Uw>WA((R0N zTY723xD7k6l-A{qT18N0rR2HN(>I3qZh5cR)|+4VykLGpJ6|ubYjtNmmt?ln&2bg5yzj&8!W2IYNvx3@MZ7kfpW!FF4myh=G`fDMsrft}!=d!Hqrcm9q zZj`le<8E(!KE~-aJx@|yx>Z2))?wTB&XyE)Xjf8)@vQw$g!X)04sow* zv1W7h(Z#&b+rG5jELpp&XT8c=_ar-4XnVrYc($axOWY=A(X>!D=6Y>3NfXT40;$yVPv5R$S-9r-#Jss3s5ynTk}Ri*YVh8G1@a9LJS66IP^ zm3DOBxUYL9C-y4cYksZHycoMNUM`6eHQJJo5jb6>ZhuCfGH6^3UJ{B@wJhYNEW6-a zD2c{n-S$oGs_ptxcSH1C<*o;KBpboHRAby{I8V0(*4euBvu;86h_N0Tf_$BrR;z!C zz{Kj$zB4cu4$I9Mc5boAETon)N#4BKKC_fGhV(`;%_OZzNT%bkoiWD&C{Ri&yXEYC z3;xDu>#u~kYoBKg(-;)DH3hRm(}^o{REDeis3N(VT1l_)Ip2yo%y8IUmjuc?eqkM% z9)T6i7-F;zZR|*18}LTABbmmf4^S*wEU+w8q>}1z_f<{f+<%O&zD+d?5*l~`(;O86D0 zq-0t8Y?VB6bH?`A=<$gmv0yJ7jJS9FmHHTo@RnL}3bJJG$0(Dc&nq#O%6K5Gm;( zZ{)}J8VtNj(eJY~w&*HL!?F$!=rQ)qN!KE4Z0ZxUmWJj&OGjFGfObGIy$ux|>AK#$ zmCg!Pcgw8U1Flkq2juFEv8$3o)Jjd#3mYD&N-A5d&+^h0C)H`AP(`X%CH8FKcTGMmEtD`SOLTL+28v*1Nw8n=YG$2OnUB1aVa`FJRyvaj!%q4<8eV6UyF_A zN1_v>F>zvYWMZVZr^@vPV%%{tTs!u@(8s%#uHDWb4g7c@cJh4ihfgGWzL)z7cbi*k zYXHpw!5{AUBmG%Vwd41K{i*W-EursoVjFG>@>)fx>}I8cRAd`GjBQP98&gvV_v7Y% zm)1=?O)*_Ej9p4i;jaC_gE_WyB|?gQBG{iu1RD4Cz2;2`Sap}AJlo^ZK7{)_p8Ytv z_Aw8+z0@Maw%Yh@7uh1F{vnR~v=6dP6l0rdo2@VA#u#dIKB*(B_Mu?^_?dwAj9sh7 z_9MAS8|CSEge{2}O`p9!wMxO~sYR5X7T~+vNZKjO)X4SY0$L+PwCmaj zgZ;|+K>bM@dby%(6X_D|0%Q(`c`KzNdfsnIyJqWXip>4@Z7ZcI=H6nB3TsNjD$S(~ z+x};$M(WT9b9a11t7!ef{`2Ppjc4=WvU1z))MwkPTuQgrzPo&_ zp^kFRwh+-yX&(so&yNSRq+OG~=UJE)=NrcTVB6~Rjc>{_YRfkUt23)&8ppM#g8lJ$ z;LS^}mPTI1*}-l!E6*eDzx7s-Pn1Jek}m0+y3w9${{Y7nP^@>e zqV;PZrfxJI&@S5+;{(^MW1kT2``cQJPi&8^_=LMHr9P@XO?|<5;EkYeDZZxV`;hwq zueJC_I;6d{s}$C#^#Yl;bfibRknDq><`dEGY3~d5YrU~R{YAY}Q!}dv+KlYkRO{NG zZB&$dPcrv?CSh~C^E=JK-8Z}QVfNtOHB8>VR*j`>Ryj&0{7v$vwB8`&97vwk=d^?V_kbr@5jHr zLw5pAgql8b|D(6zHwC{7P2Q;$-*Gf6O=}OXS6}Pn_JeLV1oM$2O4WQtF1Oh)UQ|SB zkKtmQv7$AY^c|j)A2N@gYLnVJn5tds_FLv7jV0~bVE^=V;H|Um1_s$pnQhA7H7u~H z=QD!1|G{ekdqh2AYjAqy=B~hdl9Eq7HkE`9<7$dz%l11ii)H7PU{h{6`M|2(b_a_c zU|_||1|-@M-Tu35C8!X009sH z0T2KI5C8!XcmxUH_y0$*Qc)xj009sH0T2KI5C8!X009sH0T5^+z~=w&=jz0Vw@;V)7U_7Bi67zI?249rv@JM#P#&C2vJ`{@% zMMwD9#8h-*YGh)r!3DYODUvJ{RH?!@9X3Ka(fJ!pa#0fHT2YmD)Rp91ayrdNFZqbO zUjJN>d*wWdlS}NFhAQPQ?C`ELKKO!E+E6!{$l>V7#Ly7Gu$bnTlS`S@a&pE;q;|Ug z*$|i4rkReS$clKUCh_`_H!bQK2OF`&65F2q(o{n0I2-+tlf?x(7Q%b}qUZP;7AfLa zZtZUUewfpqtiNb#>8qaW*hJnryl{venKDF&UzjH<(&;z{R^FA$5vZT<d&xAPPjc2Lk#>pJbwc^T$*H1;^w_~0IPEuEOBS@~M zR?;giHQ-8q$kR?-CG$Ptru~^U-tzkq29qcPJWH!jn4YL5O?j{nV0dmki(e8A#Gu=qt9#< zK8Jd;Q-g30lHN`iGIMk603G{;o|eN`eGPl5zDr#V>%@+(`_iKIoe;OHT{9bt`%E7` zuM}#<66$lbB?FDa!Vvr6{Y!JV^ne4vNS9yvEg>eUeU z>YECc-EfS)s+(xDx{>bHar%|pOnk)N(m5UL5kDu)w`E+bSAyKDtUIgL%4MaZ@-!;n zpwV+?d9F$$Q`1`Y^O=oCu-BMbd!l|P#K{^PK(!2T$@KN(l^uWJlDdyK&|~g@Y_wmO zUGJ}#L)_&?#U>YG@o2Zdpehg z;!tTnG}@=@3Jvv-*Pk-$%kWX;_jIozukZ5boP&`E*-`h_q0@uruq|SCP1Uv)=p2vi zIj!1#inVicwJ}_4O2WLmD{C6kJ4(?9vv2S<@A`>)Da0ik<4)x_2{(*-F9T>waK!G1 zIUQGVT2G;Lm%KI9QLgET!X959SpR?IUuZxe2!H?xfB*=900@8p2!H?xfB*#FGfRd|cWQisgdzNnO~5yi)wc04relKKpxLXFz}M_uTK1qNBqT z!uaU;#7HzA7o_pE*l2zvIx!j(CniTGMz&+pb6<+n|L>{{PXcPm~4(KmY_l00ck)1V8`;KmY_l00jI9;P-z&DtHD0AOHd& z00JNY0w4eaAOHd&00NH|0sQ{|Xw@f50|Fob0w4eaAOHd&00JNY0w4eaegrW8_oISm zAOHd&00JNY0w4eaAOHd&00JQJXc5rQ|L=R5qknjT00@8p2!H?xfB*=900@8p2!H?x z>`Oq4cZ4(Hr(aOx@#OmWgg6n4MTdk~Y-DI;Or&=s()iHi+QfKNT$>a`X|19tYE{Zt zB=wrKdtp2Fv0FE9+?%_(P`tJAv73|Q>(_|5)@bvfn?Vo@D(?9rasgL)?FI@cm zNcMM?zAt{}%Reyp)Nj1{zTxO_e2B7%j_||Lsc3vEHoWJfi!9Smx^rc}|9ABLK1cuX z0s#;J0T2KI5C8!X009sH0T2KI5O|LfINO;CALLtz-rlcrPjPQ^fz*lrbmEocgFSDD z|1$K4p(~x=9{kPV`R{!c z+DXlOxrUR78tNOo-d z4fl&?vUK9gT$0b(0XhC$PfiwdBrlzuO)m4-ms9hJfXRKj#>KI!Bc+0tUcCQ7O#6b(xH zJ6W_JaKF$>$qvk#v2*<50-v)V6A9x3X&0$aX{UnyiA11rUng3S*D69~H!BsSqEu4Z zMVcikugXfPeF*n=yv*CjJY*$U%Cy6|MfT)WthKoeG zVE^gUfj9egdS$6nl&e*u<-Fs5+Dpd?IV6oeElberD#xdjt6oE{=9RMK^L+2(*UDl$ zLnSx{cTZOQO!8_XGneMio}~zas#fGRxA;%_-CkG%UD*HRwGsC0kk+BA-&*~mRLxi9 zGHb{dWYfdZg}%&Seaw45_s5!}r}CM@d?)rK%GGi~*wri35=~l?RO3ovciD{Ro3cp8 z)2h2|V9|(nT8jkxS561CTejsmZO||xScb;%R(`tN9s1<)N6(ZU*+DC)^i_ZnLB^%4u zcDAZ26)Ed#RMoPOm$F;Zt`*4rR9hrg6yNlQHdd6DCa32^WGE-aX- z1C6YX!}ukLE|{jqrdGMX=Y?TD{wA|vS7z@A!}K_Zb`gs*pP^aRt2PvSsBb|wCjwT-V25)*-?prFoHjCyGTE^_)n#T!C9rzD z$fkCYhHs>0P}h>p=Ipd)4)$m6ADUXZrhayy8M%G-5t<}ka8DBLr1l%`=gbVuNunLV z+WQet5_Q?k#{GPQg~vB=4>uWM>;L!~xM{67+#44}k=N^(x3OL@A?#JH zHmCM;)l05L60wP?=)}~>q&C{<4{?f?HFK_&%F6=Wu&g^-A-~fwUS=(euePf zXeWLQb{p>xaW8899`bribh@>+meCZ?a6{~&#{ug7m0#XkXXB|5x2QeqXRdD9Y}k1q zC5$-{GlCW^^dMg|$T!{>A>Qufj*(*;ayHl7G_mtOZ~K3Ua2 z(dY|t7vG3cW@htYWcF`4X5Ad7(HIrnGS7baC-lBHp`C4<3~@KLSIp}2_-ozDn&#qd z8$s)Q*E5GV%+!g*+NUX>#wE@3Z=be0p>d7g5VxW|>8GkA_<||bRMa(QapG75uf3G= z#Z~`c<3xzN)VSpsoFjFAvvcAea%5u>^Btg=5WQ0gHh*b1<=JCIL#g)ouF;pxXB)>u zoYwg&p)r#3qEOvjQ-q3`B?rt4C6O-+C876nSY!uBvirgMvzmDzGoZXcDdN zm98jnRP=~Gjz@c;(G%ic(N;_YF-ASscM+y99b)ZQ{{mr%W~Obe*-B-NRP0o2K5Lkb z6~)uj*zwq`fqix2XUX-8jc|y&{6@E9MV2tr|8B=j&5RLoQ@?LTKBN&@BNe|9u%myg z8R;c&aePPr^@<;|S|b$XUSU0CMPfRVjhNpp@MKM9U$!RXw|G_IS%kz~ntoI=Clq$% z9KW1gNYL*)RW-a;ZYM41wrusbofVr}yM!tHgoKMC= z<5-Z(rkI5&g205wl<5Lxz2vRaz$N9rgawlWrF0B$7dSdAugpoMVYW!g1bPv zP#c@4$F`s5c=!0gER*|p4%gQheglPaqbtZQ`PQjh6)K%9J}_9SSf3Kt&o(+k+-T!I zORV48}IqA?0h}CvHyRD>zjGk zrt}aD0w4eaAOHd&00JNY0w4eaAOHf71OaW5eiIL$KCSJ>NWR_Pq7nklO?xu^eWih(5x}3fu+?ZX6reosE3(3*3 zrJ{OUDDEgXx5S&m%KV+1H^iIL*3K%$zkPeRe0}BW^1VzlmdxC|dj0PB^3uJz^zCRg zRjA&}my+jKljrZczC>zsHo(Z#Xq?UeyL&#u_5IlK6Fq;oXN}(C1p*)d0w4eaAOHd& z@YoW#LO-*HUwE!J9v5hTky;c=!Uo&rQ=o zy!FiI(dR!H2vZKDf9q+VEGV0yacM-1=EsEb=)}a>7@g~;Qn=E_`Z zTHgms3+<<`>A}4{H;jEzQ~Y9CDp9-(uT}Z&kqfctg;;OTv{Gc-Bd7RHRV`PiE?%U~ zb*1t~`L!xr_R-tZ+p|-iPp+2JtE)TnSFepElZom1Wa{qH6?rkUw7EUIHZ!+f5|h#O zpY5GEIw?yO}pWAQ7=-P__uV(WVPUVQng*xNIDKD{+_^R|3%CNJE$x_NJHMjVYs zchh&Jok}@X5mTkR(-&W>Y*fc@?_P|JZcbcFj83kuX12s)y0_=nm9g~l`NhQK^0oQo zd2#w><=(<f*Kane^(ga(8mQrX(v1BV$*jYsIGhmyS6lzcsaf?cVoLKDYe^TCK|t`+!&d^ zC8Q^=t(9KRY~5bEy>&;tH(Zey3%e@|smbZtxN@tw-P@xSU&|!admD+3(saI7S)ZM| zy|p#JQz+h=m`N-tFWDjw?6Vn@8#C&}#Ixm!_Q@3mR z=xYgLd*kl#jyP8txxIAfdSR>|yM&EF~9RBld)OUjb4ad&Z|I#F9IuI={rT&v9` zCa>Ond278^TVAT1U!2@{X=~=jv~({n$kpQbz2eJP?xYsw_=K>K*m&*b_?j|SkXBZP zUt7LNZESSmj(qKgJP}vr)tT$1{LIp=>$}Cp(){MlXkmQ%Mq>Q#YvZFYRjzJt7nV~O zN9Gfi!dmtAuzICL^&QKPZclDs9N8SZBPA|h?(Mlev#_?@+oL;xMW zLB8+w`004u`C7qP)-i9bD_fy;Xf;|eS1glLr7i6~QhXk<^Z&a0u5*3=s_&=zzRF5C8!X009sH0T2KI5C8!X009u#hroxr>HE?Szi&&sPf^fWPmt$J(5^Gx^zCNH zp5JYDo~JmYt#SOmoD4kQP2U)V_xZkn{r(?5af|EwfxhvR|NNxT`yYG1(EGxPe?*V) z0s#;J0T2KI5C8!X009sHfrAmqhkLk=^DFUqZ*Om>eV#^jiuSIHu8(xS#+3M)P})$2 z6goh5TbAw)y|#7tj{B!dwyMQqLE3!B~_$D@aWV->lBab)H};Y z3{o~jt=ZhI(6Nz6mP`JaL(E;6BPFJE_i*8)Q4~k>3(om2)v2Q`RjG?IoZd6TBQ2oV zN%@&3;S_M{h%F)?pj=FgaOHBe=+-(Y6SE1qGC5LQ?Dzk0-*0k#U+;Un@2~p)eczw< z{oB4j==)uIgck^a00@8p2!H?xfB*=900@8p2!OytN}#*5qoXs-{suz&-=O~YSXXDb zqnrKdVt+c>pFn44n7*W=`G4=f=K4;a{Pn(-zF+VA;>rG#Up%=&kMIHk5C8!X009sH z0T2KI5C8!Xc&`wc?4}hM9fw$b5x&$-%PKnDs}K(S1A1txo7PHr(jN3@@t~owJKF>P z*nKS7O{*F@oL|WgwW6VWrkj>3w3Bi`Rl26SY5jpq$idehbWV2Dq5^l)gOUr3chgD% zTI_G$TXW!bHf;TW=gIHo`o630ee@r^KmY_l00ck)1V8`;KmY_l00cnbn@M1|^8~lj z8wzLG{*jPz?x;AmR+9^K?P_(3Z4;3yQ?6YLYwIKHQhq!(6kQX?hek%@($ItuA0ArI zM@3;$S`(u&&xv^L_mu1g_RLxmWmWNHEsc+^OCwTzXe2%&4vmaO$A%{2lhV-e$RwQ? zDvnQ##SfVEosJXSbW5pgRXRX)D&{V&D6L1u$+g(f@Y?tYD{X#gA~rcXBna!{W8(1o z=tMMjupKn)_y5kmzcSbVe>1BXd4T{3fB*=900@8p2!H?xfB*=900_K$1X|bsclLde z>-)LBFZTV>yO%2@g8&GC00@8p2!H?xfB*=900@8p2v`Kpb%j?t4zSvx(?4SC+JwNV zuJCl&lIXLN!1(?DEw1mazTfZrDN7Ih7X&~61V8`;KmY_l00ck)1V8`;K;Y;Joa@YV z9ApPWCyRKH{RV-votf}Kb_uZk|J)NtUm{2Z0T2KI5C8!X009sH0T2KI5C8!Xcz6h~ z-~TcHe|YKxnt%WZfB*=900@8p2!H?xfB*=9z`H>J^Z$2)DrABH2!H?xfB*=900@8p z2!H?xfWX5=0Q3Kct3IF&2!H?xfB*=900@8p2!H?xfB*=*8wA+?|Bk*t=I9?@AOHd& z00JNY0w4eaAOHd&00JNY0`Fx4&vYE)!r^dyI6533ibaQ_BYbRfYBWAII?U$(ALhQm zo&5UAw|c+an?A8{{Qo$<((`LQGvP0U&xd|F^lWhL*uOir+5K<3Z+HDpXC?51fw7LS zcKlR_((yd^dzA3#Ua7`NkXwv|d*ebus;F{lgD)wnye{VjRaQ!TS*jG}YL(tr^NJ|( zMR}v5hq#M1F%_Md8ku~#5f5@pOqN(t%Dj020>7>lM5)5(E0Ul}ypU&d_ZRk3V>rmo z>%xTU=9(f@M7J`0O%{2QQkM1?b-57>a^r19?OU$tMl{Gxv-GMY6ssOJY##ec`9$Ml zkeg&uDr-WX7v-w3R**!Ks8ZQifY`VY;8!<53_tkk(W!NwBya? zf>PPY%HohwrA+>iD5yeJsa5h)mTG2tIhjZ&`P9Npa+S}eW>&KvEwe`YtdlsN9f0bWY zO!LXr)Jl4#RiB=mEas??>Evv3nZLfAnolg>;;$ud@rg`&F||Ol=93F)UB*IYZmwsL z&k>v)pH8lNpPB`;WwBhX6ivlzP3(f5_FCKm-c{P!lOY>*X@_vmd(1?V%l*SsXBbygg zwIZ+8$PGT28g{y-s@O-1oyNHk_oDW+SBWjEga^!@C3&!{KhrqN>fuS#8cc_@DT`FS z%nwx*a$P!nPd%{5-Wo8Hv|6rR^r$cY(Z)wZ+$&nu%)eHW$(T)FwpNo1)YD~IX2zeA zP?Suo%q*mqGPdi=EG4s5NfNUH^?@5D)=ski$qj35ipxya9i6o zq$ZH!rlVpqc_)8^+FpLDRf!(27G6_kZpqQADa=>N&BpUV?!~))Y?+`7P7lyZQ_o5F zg3QIUPYe=!;G5N}jWa=RWuCHHmWs-@#CvK|7iM-QBw}WH@w(ONu$pTM&iOUe(Z)cC zQ?#sKVcb<`^;x=1S=42>HJSYq8ph&|<>}tcJWOlx2lJW6Y3k7Qw(a!NZi!|m-Rf-J zk<3!xs*yTNZaPKCH>t=FtZ zW6yT&E%D0-dxqhK}SUk{&ae1tjrXWD0M*5*DHVb!@l@^Nd$EW--)t%`b} z@f^AN1{+$MF2hXEvvm9Wi>BNTGpu15HFXfSTX7GPJmU_1LO}h>42>1jsrjULpj4)T zkK`NbOJTe5;Z_4+cdzNSdO?5ZH!!uMWX&js0oadq@5IEk^HADo<@4>J?P zHQD;Ky24%t-f_O2Z(H|a$MED&3`PNgNYdjO; zCL8A+Yh`H=vnE(F;*Z0?bfAQ!P5G4Tt5C8!X009sH0T2KI5C8!X0D;GrKu_m09ma}+ zK)Canu(3?QnE$^`=l}P;{n(O0!9f57KmY_l00ck)1V8`;KmY_l;L#+|)fw&x===YV z)w%a`U*>v$;KWx?e0$Hw!ap5;G4$)9j|6|?Sg`9Kcm8!}Z}5rZpFj3{eSf>J|Kv;D zmrtaQ@9IcqJzxSW9hdtPX9C(O{kl_j&3ay`RHTBS%1SBgT*vNu%Kh`!dq`cuu0+NS zlddp!v!f$37unE~!T$J}H$JYt6zm@w3VcUIzt33|s+((yP!Y4`+FC)*H-F}S+tk3g zV|}1Ge1JdKsZND*0S_YTdTJw%dAVwSLQ_aj$9C6K;yO(z2V{_qr4{ z>y2QhmaAE*#5AT$Q>{zsEn?2)xl9M4R8mykNDh>QQkcXFQeHQ$1LQ-As+&Tk`Bqq4 zk+X(%oQ-IbmI(I8Vu5;9w;y)t{BCwruF`&*-7Gz;v_9efcaII_T4Rv09_D^fLy*5k z>35H|yUezox!L87MYNZ-PX_z%oDI~2c6;?IZV1U*X0W!Kr8{s1r_Fg{bHCBrl06Zu zD`(q^Gg`POjqCQ-!JLzju9Ed?l8e+|)LsnspFJCR<5Fw2d1P|`+a8s5$a?axp>~zP zY`#hVrfbeAf~&MG&4&rF!dcsEZeDu0Qe@Y|`?v%~Lw5YgVwzuIO*XQleInTZ;^~0) ztZffvsZx~bs(EtXvPjb8by=!754m4&t#c>TmBgr8Cy3RnBQO^^KEY*z{lfWxc1O?q z;P>1&T`tf4Q&S_l!gx%ZIo6*#6X0}_)jI{5+^A4f75%fPZ;HA474DyDW7?Hq|EsZp zCfnM0Oh|VF)&N1dfik}7H@xyt8Q@meFd3iN3ade#h|)%*udZ^KM5 zvZP%)*8jrOftszieo-)mvHx=apshAmG$Tj$Nza4H)IO?B1^Y8E1hiLesqQPft#+-8 zFmIxFhjag=ZLaQUeqs!5+_9KeX0sZ!uOT zNR7{v=dT_2lR(3sTmy1bI>E%$$V;ktszEZu`uYq-Vw1E<^e=@MvEvmvQjS2t!3;tIl= zRPae4O4WQtF0;{>PiS5#t;-u$0Ersp-Q(tSygr~F^yn0cY-yv^j@|)Io3#bsux9(Q z?$XR#)g#&&ZG_w!W#_mxJErA~^arL-BP+ARxqoC<0d+G?e%+4KMuv}0wnHv$|j_E0VL1jP07+SC;n4#%72U>Yb)Ej|Xz^gvlCeXRCRoY}sL}({XYyvFyFumfR8y zH`ElJ`6G9p)L4u(^hVD&=Ue02Xk#P9y`ok3Ekj8tO8lCT-)iehnl$njK;O*3WE@m` zCxNfx^|{7+h^xLqH`m8&hF5LMpSLCOd8JS*mRJ>+Y6aTPQjijJ>EtqRID_VNiJ2LG zdT}l@zrd@-a@G-ZBe6XFQeydBY%&_Lw*awylb3oj*V*Q1mj&r{$gd>RO)@S!YF+Bt zON*K1#p{+DwhDVESxzn_=95+;ukPtZSH?aKgRTD$_x+B3{$Jl;_5J(4KkfT>egCHK zU(zGIKmY_l00ck)1V8`;KmY_l00ck)1Ri1nU7fuhVfH7){sh^dW9&~i`_sk#bh1Bm z{$FpH{r->j{||9xLNyQo0T2KI5C8!X009sH0T2KI5I6z??Dv1n|BnD9M1TMYfB*=9 z00@8p2!H?xfB*=9z(Y&`zyCkPl>^m400ck)1V8`;KmY_l00ck)1VG@32(bD8)7&oC zH*j*R_h0muPUMgOhvQPuS9*?xel2t@_>;lQ-G9?P-&O7WTIZ(&U+Z|Dq8`nQ&hbgH zV{NACAP4i<7UKXJc0sZzR5#ZYp(19DtJ&$oW_GJ6yULIs;DmGzUk6Q zeVD^%ic+>Jsj6Jss9Fctn5W68Qn6g1b5*k2LPciBWHd(*@_DIR&8o_l!4$+El5*;yLt6dh&ZF0_@{8^KI1SF=)yY3#Z+)Jkk0)e-IS zIZ9+?GS`?5a+hVQ)R~G>ZmLH85>x#w4!a($Q-hpZ@EB*V<#dgaN$r`&)i9^^YC+0{ z?%^(*=Tx!lsoRLLu8wtrEu+`9aa~sJ#PI0hE5J{=S|b_cw%DmZF3k?o`rL}_6W=di z?M7pUpggJFr>s3q|1el$tw&5f5E%W^>ozHvSFkVWb>gtb=W9{q)20vW)2wo|9uVYY z?5$_r2e5lx+eFyYr_~dUE9BGOc#7(vvae6Gl(X9cYh(Mhhi{QjbKMMFk=83xbu-J3 zv}*NCwtt96_0zfbbb`M1U1}tP+%4OK(7|(bJeJvWy<7g|lSk!GV(w=Ape@g@UDp~f z9?GA16gh-Hp#$JP5#kngQ{Jz0h9UbJvL-h!hqy$&=6GcDR&D(PZ94dEzoYcr(e=>` zI~^~zkWS9hd0X!B%s2NQZ@=N3()f6gn`NC3I}6TrDYi9)GmZ@t3UmaXQShd#vt0*; zriex{zp2Dq*LnJZ$}iD!&wU17}MyMlcy`c7kt z>RIb?cTn99|lA46K_iUN2__}fFI<#E&?kariA&aU| z*^u<(Kbr=>bS|7!u%5X(51&&Rolv($pQ8aTm7UJpQ)-pGUWYk8;)_CTOwgH!z3eDY zw|UV4rj_07rd(AO`frs~&C=0^WRCjrb+xKg$w=7-3=Ki~)(qY1+s4?GG5O0iyxU9D2F+NXT z7tFE_8BYmo+nJsxox#jZoV61hO{6uZJ~A?>QnfkJed|oS-53pVOZ8b&+w5LiB_7C% zTaz8qQ#u;A+PMkAalY1c$bS-q_5Vlnbq1t>00@8p2!H?xfB*=900@8p2!O!DOaSZu zALiPDZXf^xAOHd&00JNY0w4eaAOHd&a5Mz)`~T5!gcJ|}0T2KI5C8!X009sH0T2KI z5O|mgVE+Fw*A8?80T2KI5C8!X009sH0T2KI5CDOrA%OY+(Qt$m5C8!X009sH0T2KI z5C8!X009tqmB- z-=Y8i_R&a&6c7Lb5C8!X009sH0T2KI5C8!X0D*^vfNTE$u&4w*KmY_l00ck)1V8`; zKmY_l00ck)1df;h+yDRJjt_BtA3d4v{pH?sC%*Ie+sAi${N8A|xbzO<(rQi#*~UJv)iD^gL}miSsp zzEhKUxg<(E{8~*esB$S=Q3{grrz8|5eob0eDiU9+6$-*yfzp&kL6v5f7q9cFg_-0k zpUW&IvsFnFvqH5hZy3Pf%V^zZ-a=lLmC{jUZb;fE_l3qMpGcU>|UMUrJ`E{irN|lSEP~BWpgo?C)2BFML!b)oWD<))N!XA?Q=Cgkl@|(9Mdb|*t9(T&OH`kt zBY59zUT)-q+!D*humygjqSVT!6_K%+IaF!|i7H_qowe>pHpIff+MCZ#5` zPkgx`>=xvzI=!4sq?3GRA+?lAx=qiDkX0%hSy{|dx*Weq7GMSB_;WcUEH{{Ap^-~I z@YWlj4sw}SNsWwd;d=h29c~MSnpAables>_w6U__SCVO#;BvVlm(=xhXI~J{4$7i$ zMzzMPAugfyng!0JW?U9$3G~>x_3;01?^>7RIIi;;lDQ;fm946%w&cXoWF?h|a6w`L zf;6Bg2?&4`L|iBkyoqFngWbmN2(vTGnOPDbgs4UvyYdwI<#JV?AP?Xw|4SUl&ZQD3 zv2v-Tl9$Li-90@$yR*Q804NGP{IQrzUrv90`rP{TFw5Y4oPxcVC5z9_U75bQuxgIx zG5d7qe!=)doVJzA(=(C*OuohiQ~AN3v-L^mUcq>@F9uT#yJzEbolgqJRlV_)_rrbg z=St^p!Ps~U1}geSapFZFl|l{ZCaXE^=9=rT!5Rt7#jP73FWi`0n41Cg^4MdhbEjY| zVxu98%$6NBurZe}MP!V12V^6cOS`oapX}T|X?zf0f_Bmxrc>LT5^ZjiwP8I+Oxea^&f<$qDFv%9m6kAd}Mhbe`|rJY~d%crq8X0M(6< znkg>kx*bM|@C#TJI1De)f*VN71r#+emR0kmeW4C3(BEdeXQSe><08;2h76 z+JWtwt&QC$JDo=^(2&~f^yc>7DRyq0G|vB^nw{9e<`mi&)7d>YFq0ZN8M%YA+!w^2 zlF4FxXkK1ezRZ~l^)ogCyj{=fw`x}#%))wLo8-M0%iF3sVapF4)Q&l>7wNfRcN4 zesM0-wO9fD-iFRoKz@E{b?)liN~T`ZX)-I?YQgL5NOPy=YG+US8(|E64NScXOQ^e$SAAh^Ee9~Bs$D#ika~TLTKWH^<4=fuwD%Ep13vwQm_m!39 zMN>UZ1}{dMJ_a?*CwzX%JR?OrKFU@e&Lio&oh2k`UP2Nfr-VQow=yl}p%Gh?6SWVF z^4saihgt?zi ziI`9n2lD`OWgHKYI1Mul)JYKMWPW zVH?whUlkfBzEoAR7hn8#e5X)+^Ua|@eVxah#MXlNHNKRQ4jEMvPkG23HyxAs@b#7X z#p#v1=C!%I=Jd_g<@qJ3wm7#0yL8D;2L!t@gwYixVH?b%c#88m3*;#xObf=lJ;SG^uGb~l<2iN8gntmf+mmU_Q1+CLD`!CdRM42-bF|W1 z1wVfT%?xkFD~00w-y4eGRkM(6ZYQBZ;ML@j@o#xR^L&$}h*nF45tA1f2UT%H9xaSd z#2*)mGj9#W6RLByi9(2Njg4Q8uNR7M0VOwu zh)FhfRh!1YWG3*4c3WXjb-7Snd}AoS#1YwRM-<63ekCb8++EaKyi_PwfRfj;bEB~1 zegE_Bv!M#7laR%K`1FsBpA?ECBSU{S%#lw6$|6kNeQ*3CGY_Ti_qdWYL9PpaU2vz> zG)b(fg58Ba-!_VHcQ6FuAHNdc12%p$!^S*m$m03|*pcs4Lr+p^{a1g~^6N?X_)7#( z=$&%1$IDmKqxh3T@e)w+y>!AvYw%jGO41Qai)VM4gkHhZ+FlaQCF;Fgx|OI- zo5S+M@ps~n3dL(Mg7G~8hYD$JF&D<)?;Gb`$>cQsQ9OU5cw=P9;1q?ATqk0d-Hv>I zuZ>vpL#2nRUw-Sh@jjPBKm3gW<k!WwFO_pw)! z1la^u?6LfL|GDWW;1(zwKj}}Yq~XuvD~00p+e7hNN-k9WAYdY&%?kZ?P-U1&sXaA* z-n;m<*IFeZO0{>WMA9}N4%g$kLUA0re?A+zE&^BvnPu4Z}(fP zS{19J-55WMpT;wV;@fWzbtd_QYcI7+Q>4b;fI#>=`n|gnHJ7fW-+=^E)*xoY6UrB^|6L)(H_ckb4skbC@lDEk z5dwq&AwUQa0)zk|KnM^5ga9Ex2oM6t5dq5oKaR6XVpT&dj2mwNX5Fi8y0YZQfAOr{jLVyq;1PFoShydmPAIDjxF%bfU03kpK z5CVh%AwUQa0)zk|KnM^5Sp;bRKZ^(55dwq&AwUQa0)zk|KnM^5ga9Ex2oM6t5drf5 zkK?S;m^|6MBI_e}opQ-AG)Ke=Ce2manqp6=Xx$Fc%DVwU4Y zEO>0Y53u;~eQ(%Y+cM91c9VrIyUNNYRD;K*a%tTUns!v0Dn(9{Ss@D?7Q*ACfh%@3 z@`KXUSh?h~I`e8*lJZa}VC(ZWs5)KRc~FK1BA3D4tR2~FcF4@-7Pb@xwg;UC%!6Lm zZ8v1_Y^#MO!w7obDQ}l*P$l%+K^33Aqul|04s&ZWzPIkwOH)vit=nxk3h~-?ybZXx z2Yol~R?G3~@-AuwENu90jTdYBHEh;i3w^g8F(4_77?3t~Z@X0WT^wDh9x#Sz0Ay__ zJi7B>r(9}#4g%9+K$jQsyB&C351iU{pEunoOm+>s!ggcI3lDA125H+@LKSlz14h zTD!`YwH|D@iX$w!b{H-B(Nf!WOMnwc6JC^(vBEW<6CgQan~~lZJZib^y5rqqK`6Sr z1l1xts56`ZfRAmq5WTS7G|wQXA@7MR)2w}Jdv)Kc+SLZLpoZ0OqR@)`$ac-`go_nN za$Z(>4sGtf}sm z18W9W&KN8pSUT_)R?Y;Ffhz}I32B4N90;v@)8VSUhTyn(WY-n7 zEi8=KwxMwlH2fYelhJ{sW&y*+x$gQAG!d{CLpd+U!{z+)V-|ogL;6sNa@C+uI>_hh zMnXFZ%@(UIzz|e7IkF(|+g^%ERfSJ5Q22Z8u@Yq6(_d)yP!B5%yy%O1*@mJF{R&F4Zq1gYX$Hd zHCQ_w5rS+4ZUd(pYNE+B1+7TM*ty@+-tEq$l3rXgKRioF=C4N+Ql+5k|i6MotSgSl9rI4%C`dE?k#@!sD94lD4qp)ttvp zt!=x&8;OC;jY4Q^)82GINN<r(SYp*d--J)sNuU`fu9yB>x*PudWkElYW4p9mdO?YM69K1CklUwGl-9iGS zN&};rKL8x%ldK^QbatB)mBbRi1Papjm@5@sRu_u9d2pDdRV{`m9A=l1LF~a9E`MJfD!8sCjlVv`@AYdvclB$Q_f#)%>vgG zLJvK@-C*8bfB$ahUgZf74WYA_b+>pVRD?sjyeuACz@R5MbQr4;+WnbgpaWWptA5K& ztOj$ALt&n&JQ+sb6b1tXQ6b);rt0V-H5e5fAW$P&8vp3hv4VjN9vOa7Vl_t;j=@Eu zg<+%(`aI(>vdaMjF%2h-e6UfP)}uBswd1lgqvs~XirphL1FQ2`a9z#6K56WrehwosNO_$;3M%QWvF}a_OjEPZm#N6ICMIYwQ4$QQ+ zvjMVFI_kNIPEK$cNQi1%Lz5Hz5zT}?@)4aRM5RboYJPIEKcWz`*o#Le3DQJMX^@`V z1=QJt1%hTTn+ss3dDSgc=wF*i5ZaE169qb0OFRN}#2Zx4X7+qv#y!vsdd_AKCIWz8 zprUSY-MvjkrVrnbPTdquEqD7OGL8eb4(!QUVBUDFD&jdD#Y3`jCd58BV=vU+mFzJl8z(;yEcLCL%aL;HFOw+05@4^6-wxV1wIbB|p}gc1a5k2KEB zvkh?4_Xu(yvFL^{%0Mn_CbwWrMPVT0;5m!#J;e44lwI%@xV3UuY_Rl#M4;;_1-oP# zDJibv?|oAS@)M2n6Y8{G{Cr8i28k2kvL4Vgg|r@F_RHpW@l6N9rRjt!)#B@o%p#0r z7ihrAJcy4Zu3mel33XAKwOM8olV$&#+hZ!mJ7RY9?uDNA=1Uu5mhSKHcw`R2Cu6$ z9%x0RT4o-C;>3J0o`05ce8gV59`=XS%Ot-N%_bfogC5dEAsl2fVhD-`5EO+i035rF z=xTciBCPA)66vO5ce$5(jb`xibz-{r+|(c-Y#MX$q%4=?DlH}1ztC(Ga%de@ zLJn5RNGOmyR^E~&(h1H;sk`qqt{p9khvDu%m|UEDFggg@h>(1IlHDds~=mD*7iUZ`Xbp4e=j zH!*z@(+S~S8*?ENG3CqWBcE#z!inBcm70%H-6<_|(K$&ZF6% zOM#bZ3Ecnxg*`2~?r;ZflT{(1{jhSX^G%)Ia}o}FyH;(9(b)lgr&w{aJh33NgoQ$* zvjcbzMoGY~1e@M7GIVx89@L?;1Ipx*rV^bUfU^~Fnu5*_a61YtCrz5r*#XE=OyUeL z#i0&5JAg@4O0#zR7V0c&|7@%yI&DK|2e|1+X9v=}e37(=nZ9&(;43*MJwReLogENo zqMz;T0Qmp^S7n+(0_Mqn&JP^6uTEzNFlq(iZT)x*ogL_5aXLHD|LYcXb^tvJIy)e~ zpF(E`zUuEhPy!uKpv%q6rn3Vo=TjvS)7gRads2sU8iURb96F-Aq`A}CfoJ;m+2kah z9q9gw#KAKDA!@Upd|B>bE%6A@5htJyn19-JWb%M#2QdF%d_M0;wyDVUp|b;!!$M~V z@;;FRr*7!%Ky;vQ6zhyaG|pUgM9*y&JNJo w0sb96Jzc*~K0Tcs*ykr;>Fj{`8dY-m String { + format!("{}{}", API_URL, str) +} + +#[tokio::main] +async fn main() -> Result<()> { + let timeout = Duration::new(20, 0); + + let client = ClientBuilder::new().timeout(timeout).build()?; + + let admin_token = get_token(&client, &User::new("index", "index123")).await?; + + Ok(()) +} + +#[derive(Debug, Serialize, Deserialize)] +struct User { + user_id: String, + password: String, +} + +#[derive(Debug, Serialize, Deserialize)] +struct Token { + token: String, +} + +struct UserClient { + token: Token, + user: User, +} + +impl User { + fn new(username: &str, password: &str) -> Self { + Self { + user_id: username.to_string(), + password: password.to_string(), + } + } +} + +async fn create_user(client: &Client, admin_token: Token, user: &User) -> Result<()> { + let res = client.post(api("/users")); + Ok(()) +} + +async fn get_token(client: &Client, user: &User) -> Result { + let res = client + .post(api("/auth/login")) + .headers(get_headers()) + .body(serde_json::to_string(user).unwrap()) + .send() + .await? + .text() + .await?; + + dbg!(&res); + + let token = serde_json::from_str::(&res).unwrap(); + + Ok(token) +} + +fn get_headers() -> header::HeaderMap { + let mut headers = header::HeaderMap::new(); + headers.insert( + header::CONTENT_TYPE, + header::HeaderValue::from_static("application/json"), + ); + headers.insert(header::CONNECTION, "keep-alive".parse().unwrap()); + + headers +} diff --git a/prometheus.yml b/prometheus.yml new file mode 100644 index 000000000..f38b88b24 --- /dev/null +++ b/prometheus.yml @@ -0,0 +1,9 @@ +# global: +# scrape_interval: 5s +# evaluation_interval: 5s +# +scrape_configs: + - job_name: "lepton" + static_configs: + - targets: ["localhost:8000"] + - targets: ["docker.for.mac.localhost:8000"] From 7d8bfa5d4cba070de698b788c58679f87197b505 Mon Sep 17 00:00:00 2001 From: Thomas Date: Mon, 15 Jan 2024 19:03:42 +0100 Subject: [PATCH 3/3] Checkpoint --- app/content/serializers/user.py | 2 -- app/settings.py | 8 ++++++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/app/content/serializers/user.py b/app/content/serializers/user.py index fb7be4982..7c41beb9e 100644 --- a/app/content/serializers/user.py +++ b/app/content/serializers/user.py @@ -20,7 +20,6 @@ class Meta: "first_name", "last_name", "image", - "email", "gender", "study", "studyyear", @@ -30,7 +29,6 @@ class Meta: "first_name", "last_name", "image", - "email", "gender", "study", "studyyear", diff --git a/app/settings.py b/app/settings.py index e70ce375f..32ec17320 100644 --- a/app/settings.py +++ b/app/settings.py @@ -291,3 +291,11 @@ PROMETHEUS_EXPORT_MIGRATIONS = os.environ.get("PROMETHEUS_EXPORT_MIGRATIONS", True) +CACHES = { + "default": { + "BACKEND": "django_redis.cache.RedisCache", + "LOCATION": "redis://redis:6379", + "OPTIONS": {"CLIENT_CLASS": "django_redis.client.DefaultClient"}, + "KEY_PREFIX": "leptos", + } +}