From 2e46d026e0b3c5a6e429fd4f30adf71fb6224f4a Mon Sep 17 00:00:00 2001 From: Mikhael Korneev Date: Sun, 10 Jan 2021 22:22:13 +0300 Subject: [PATCH 001/107] css bump --- landing_page/mainpage/templates/mainpage/index.html | 2 +- landing_page/mainpage/templates/mainpage/projects.html | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/landing_page/mainpage/templates/mainpage/index.html b/landing_page/mainpage/templates/mainpage/index.html index 8ea4e0dc..07652c8c 100644 --- a/landing_page/mainpage/templates/mainpage/index.html +++ b/landing_page/mainpage/templates/mainpage/index.html @@ -16,7 +16,7 @@ - + Learn Python - Курсы Python в Москве и онлайн diff --git a/landing_page/mainpage/templates/mainpage/projects.html b/landing_page/mainpage/templates/mainpage/projects.html index 2a393697..ee56b910 100644 --- a/landing_page/mainpage/templates/mainpage/projects.html +++ b/landing_page/mainpage/templates/mainpage/projects.html @@ -13,7 +13,7 @@ - + Learn Python - учимся программировать на Python за 2 месяца From 9f7bb0d28626aab62783da18754a7a2d775a5a22 Mon Sep 17 00:00:00 2001 From: Mikhael Korneev Date: Mon, 25 Jan 2021 18:11:16 +0300 Subject: [PATCH 002/107] Fixed error dataLayer is not defined --- .../mainpage/templates/mainpage/index.html | 37 +++++++++---------- .../mainpage/templates/mainpage/projects.html | 4 +- 2 files changed, 20 insertions(+), 21 deletions(-) diff --git a/landing_page/mainpage/templates/mainpage/index.html b/landing_page/mainpage/templates/mainpage/index.html index 07652c8c..9405fb00 100644 --- a/landing_page/mainpage/templates/mainpage/index.html +++ b/landing_page/mainpage/templates/mainpage/index.html @@ -93,7 +93,7 @@ + href="#counter"> Записаться @@ -144,8 +144,7 @@ Контакты @@ -239,13 +238,13 @@

Учитесь онлайн {% if today <= online_price_ranges.0.price_range_end_date %} {%else%} {%endif%} @@ -273,14 +272,14 @@

Учитесь онлайн= online_price_ranges.1.price_range_start_date %} {%else%} {%endif%} @@ -345,13 +344,13 @@

Регистрация закрыта ввиду эпидемиологич {% if today <= offline_price_ranges.0.price_range_end_date %} {%else%} {%endif%} @@ -379,14 +378,14 @@

Регистрация закрыта ввиду эпидемиологич {% if today >= offline_price_ranges.1.price_range_start_date %} {%else%} {%endif%} @@ -1472,13 +1471,13 @@

онлайн курс

{% if today <= online_price_ranges.0.price_range_end_date %} {%else%} {%endif%} @@ -1506,14 +1505,14 @@

онлайн курс

{% if today >= online_price_ranges.1.price_range_start_date %} {%else%} {%endif%} @@ -1546,13 +1545,13 @@

оффлайн курс

{% if today <= offline_price_ranges.0.price_range_end_date %} {%else%} {%endif%} @@ -1580,14 +1579,14 @@

оффлайн курс

{% if today >= offline_price_ranges.1.price_range_start_date %} {%else%} {%endif%} diff --git a/landing_page/mainpage/templates/mainpage/projects.html b/landing_page/mainpage/templates/mainpage/projects.html index ee56b910..d170db39 100644 --- a/landing_page/mainpage/templates/mainpage/projects.html +++ b/landing_page/mainpage/templates/mainpage/projects.html @@ -74,14 +74,14 @@ + href="#counter"> Записаться -
+ {% comment %} +
{% endcomment %} @@ -188,7 +188,33 @@

Регистрация закроется {{course.end_registration_date | date:"j E" }}

-
+
+
+ Оставтье свои контакты +
+

И мы собщим о начале регистрации на следующий набор

+
+ +
+
+ +
+ + + + + + + + + +
+
+ + {% comment %}
00дней @@ -205,7 +231,7 @@

00секунд
-

+
{% endcomment %}
@@ -1555,6 +1581,10 @@

Частным лицам

Наличными через салоны «Связной». Связной

+
  • +

    Для оплаты зарубежной картой свяжитесь с нами learn@python.ru.

    +
  • @@ -2249,10 +2279,10 @@

    записаться на курс

    -
    + {% comment %}
    -
    +
    {% endcomment %} From a25e3c2e458be1c5aa9929386d884e5b5fb44f06 Mon Sep 17 00:00:00 2001 From: "alexey.shtyrnyaev" Date: Tue, 31 May 2022 02:37:35 +0300 Subject: [PATCH 050/107] fix spelling --- landing_page/mainpage/templates/mainpage/index.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/landing_page/mainpage/templates/mainpage/index.html b/landing_page/mainpage/templates/mainpage/index.html index c168bc2c..96ab8667 100644 --- a/landing_page/mainpage/templates/mainpage/index.html +++ b/landing_page/mainpage/templates/mainpage/index.html @@ -193,9 +193,9 @@

    action="https://cp.selzy.com/en/subscribe?hash=61i59irnnggz3cu38hroqtqh4niuuaoh88i53ydj6dzkixzkhekny" name="subscribtion_form">

    - Оставтье свои контакты + Оставьте свои контакты
    -

    И мы собщим о начале регистрации на следующий набор

    +

    И мы сообщим о начале регистрации на следующий набор

    From eef2b10dffaaa49b3012f12da28ddacfcffcb6e5 Mon Sep 17 00:00:00 2001 From: "alexey.shtyrnyaev" Date: Mon, 27 Jun 2022 18:58:42 +0300 Subject: [PATCH 051/107] hiden from subscribe --- landing_page/mainpage/templates/mainpage/index.html | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/landing_page/mainpage/templates/mainpage/index.html b/landing_page/mainpage/templates/mainpage/index.html index 96ab8667..f509322e 100644 --- a/landing_page/mainpage/templates/mainpage/index.html +++ b/landing_page/mainpage/templates/mainpage/index.html @@ -188,7 +188,7 @@

    Регистрация закроется {{course.end_registration_date | date:"j E" }}

    -
    + {% comment %}
    @@ -212,9 +212,9 @@
    -
    +
    {% endcomment %} - {% comment %}
    00дней @@ -231,7 +231,7 @@
    00секунд
    -
    {% endcomment %} +
    From 28464178a12dcb2d73861ced3860a9c06aba3ae2 Mon Sep 17 00:00:00 2001 From: "alexey.shtyrnyaev" Date: Mon, 27 Jun 2022 19:25:39 +0300 Subject: [PATCH 052/107] hiden from subscribe --- landing_page/mainpage/templates/mainpage/index.html | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/landing_page/mainpage/templates/mainpage/index.html b/landing_page/mainpage/templates/mainpage/index.html index f509322e..f01d5b27 100644 --- a/landing_page/mainpage/templates/mainpage/index.html +++ b/landing_page/mainpage/templates/mainpage/index.html @@ -148,18 +148,18 @@ - {% comment %} {% endcomment %} + - {% comment %}
    + {% endcomment %} +
    @@ -2280,9 +2280,9 @@

    записаться на курс

    {% comment %}
    - + -
    {% endcomment %} + {% endcomment %} From 062ee5afbd8ac4ad2709764340d21390e02fde5a Mon Sep 17 00:00:00 2001 From: "alexey.shtyrnyaev" Date: Mon, 29 Aug 2022 23:07:49 +0400 Subject: [PATCH 053/107] change description Simon --- landing_page/mainpage/templates/mainpage/index.html | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/landing_page/mainpage/templates/mainpage/index.html b/landing_page/mainpage/templates/mainpage/index.html index f01d5b27..d3fd76de 100644 --- a/landing_page/mainpage/templates/mainpage/index.html +++ b/landing_page/mainpage/templates/mainpage/index.html @@ -1171,13 +1171,13 @@

    Валентин Домб

    Семён Осипов

    - Активист MoscowPython сообщества, Data Engineer в Semrush, до этого - Big Data Engineer - в X5 Retail Group. + Активист MoscowPython сообщества, Team Lead в Gett, до этого - Big Data Engineer + в X5 Retail Group и Semrush.

    - Активист MoscowPython сообщества, Data Engineer в Semrush, до этого - Big Data Engineer - в X5 Retail Group. + Активист MoscowPython сообщества, Team Lead в Gett, до этого - Big Data Engineer + в X5 Retail Group и Semrush.
    From 2a427e205477472ea51eefe98e5f8b8fd97ae503 Mon Sep 17 00:00:00 2001 From: Ilya Lebedev Date: Wed, 16 Aug 2023 11:06:13 +0400 Subject: [PATCH 054/107] remove stale code --- landing_page/landing_page/settings.py | 36 +- landing_page/landing_page/urls.py | 15 - landing_page/landing_page/wsgi.py | 9 - landing_page/mainpage/models.py | 20 +- .../mainpage/templates/mainpage/index.html | 307 +----------------- landing_page/mainpage/tests.py | 3 - landing_page/mainpage/views.py | 60 +--- 7 files changed, 26 insertions(+), 424 deletions(-) delete mode 100644 landing_page/mainpage/tests.py diff --git a/landing_page/landing_page/settings.py b/landing_page/landing_page/settings.py index 77d9b334..d227ba8e 100644 --- a/landing_page/landing_page/settings.py +++ b/landing_page/landing_page/settings.py @@ -1,33 +1,13 @@ -""" -Django settings for landing_page project. - -Generated by 'django-admin startproject' using Django 2.0.5. - -For more information on this file, see -https://docs.djangoproject.com/en/2.0/topics/settings/ - -For the full list of settings and their values, see -https://docs.djangoproject.com/en/2.0/ref/settings/ -""" - import os -# Build paths inside the project like this: os.path.join(BASE_DIR, ...) BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) -# Quick-start development settings - unsuitable for production -# See https://docs.djangoproject.com/en/2.0/howto/deployment/checklist/ - -# SECURITY WARNING: keep the secret key used in production secret! -SECRET_KEY = '3=dgm+l+a*q98^7(frp1^q6fm_a-b-!pa758g$e34boojl3j0b' +SECRET_KEY = os.environ.get('SECRET_KEY', '3=dgm+l+a*q98^7(frp1^q6fm_a-b-!pa758g$e34boojl3j0b') -# SECURITY WARNING: don't run with debug turned on in production! DEBUG = bool(int(os.getenv('DEBUG', False))) ALLOWED_HOSTS = ['*'] -# Application definition - INSTALLED_APPS = [ 'mainpage.apps.MainpageConfig', 'django.contrib.admin', @@ -68,9 +48,6 @@ WSGI_APPLICATION = 'landing_page.wsgi.application' -# Database -# https://docs.djangoproject.com/en/2.0/ref/settings/#databases - DATABASES = { 'default': { 'ENGINE': 'django.db.backends.sqlite3', @@ -78,9 +55,6 @@ } } -# Password validation -# https://docs.djangoproject.com/en/2.0/ref/settings/#auth-password-validators - AUTH_PASSWORD_VALIDATORS = [ { 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', @@ -96,9 +70,6 @@ }, ] -# Internationalization -# https://docs.djangoproject.com/en/2.0/topics/i18n/ - LANGUAGE_CODE = 'ru-RU' TIME_ZONE = 'Europe/Moscow' @@ -115,9 +86,6 @@ USE_TZ = True -# Static files (CSS, JavaScript, Images) -# https://docs.djangoproject.com/en/2.0/howto/static-files/ - STATIC_URL = '/static/' STATIC_ROOT = os.path.join(BASE_DIR, '../staticfiles') @@ -129,5 +97,3 @@ MEDIA_ROOT = os.path.join(BASE_DIR, '../media') MEDIA_URL = '/media/' - -WEBHOOK_KEY = '0001VypAArY7lFDgMdyC5kwutDGQdDc6rXljuIcI5iBttpPe200' diff --git a/landing_page/landing_page/urls.py b/landing_page/landing_page/urls.py index 0f50e6ca..65c77bb0 100644 --- a/landing_page/landing_page/urls.py +++ b/landing_page/landing_page/urls.py @@ -1,18 +1,3 @@ -"""landing_page URL Configuration - -The `urlpatterns` list routes URLs to views. For more information please see: - https://docs.djangoproject.com/en/2.0/topics/http/urls/ -Examples: -Function views - 1. Add an import: from my_app import views - 2. Add a URL to urlpatterns: path('', views.home, name='home') -Class-based views - 1. Add an import: from other_app.views import Home - 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home') -Including another URLconf - 1. Import the include() function: from django.urls import include, path - 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) -""" from django.contrib import admin from django.urls import include, path diff --git a/landing_page/landing_page/wsgi.py b/landing_page/landing_page/wsgi.py index e3b2e0ca..2f859d21 100644 --- a/landing_page/landing_page/wsgi.py +++ b/landing_page/landing_page/wsgi.py @@ -1,12 +1,3 @@ -""" -WSGI config for landing_page project. - -It exposes the WSGI callable as a module-level variable named ``application``. - -For more information on this file, see -https://docs.djangoproject.com/en/2.0/howto/deployment/wsgi/ -""" - import os from django.core.wsgi import get_wsgi_application diff --git a/landing_page/mainpage/models.py b/landing_page/mainpage/models.py index fc1c73c9..f633f46d 100644 --- a/landing_page/mainpage/models.py +++ b/landing_page/mainpage/models.py @@ -1,5 +1,5 @@ from django.db import models -from datetime import date, datetime, timedelta +from datetime import date, timedelta class MoscowPythonMeetup(models.Model): @@ -225,16 +225,16 @@ def past_due_date(self): class LearnPythonMultiCityCourses(models.Model): class Meta: verbose_name_plural = 'LearnPython Цены на курсы в разных городах' - + def __str__(self): return f'Курсы в городе {self.city_name}' - + city_name = models.CharField( max_length=50, verbose_name='Название города', help_text='Какой город указывать в списке' ) - + long = models.DecimalField( max_digits=9, decimal_places=6 @@ -244,37 +244,37 @@ def __str__(self): max_digits=9, decimal_places=6 ) - + early_date = models.DateField( verbose_name='Дата окончания ранней регистрации', blank=False, null=False ) - + early_price = models.IntegerField( verbose_name="Стоимость курса в раннюю регистрацию", null=False, blank=False ) - + early_installment_price = models.IntegerField( verbose_name="Стоимость рассрочки", null=False, blank=False ) - + basic_date = models.DateField( verbose_name='Дата начала основной регистрации', blank=False, null=False ) - + basic_price = models.IntegerField( verbose_name="Стоимость курса в обычную регистрацию", null=False, blank=False ) - + basic_installment_price = models.IntegerField( verbose_name="Стоимость рассрочки", null=False, diff --git a/landing_page/mainpage/templates/mainpage/index.html b/landing_page/mainpage/templates/mainpage/index.html index d3fd76de..481231ba 100644 --- a/landing_page/mainpage/templates/mainpage/index.html +++ b/landing_page/mainpage/templates/mainpage/index.html @@ -159,7 +159,7 @@ + @@ -189,8 +189,8 @@

    Регистрация закроется {{course.end_registration_date | date:"j E" }}

    {% comment %}
    -
    Оставьте свои контакты @@ -213,7 +213,7 @@
    {% endcomment %} - +
    00Учитесь онлайн
    - - +
    - -
    @@ -916,15 +794,14 @@

    Что вас ждет

    - Онлайн- и оффлайн-группы занимаются по одной программе и получают + Все группы занимаются по одной программе и получают одинаковое внимание преподавателей и кураторов.

    - Каждую субботу оффлайн-группа встречается с преподавателями, а онлайн - - созванивается с - ними. Затем в течение недели вы изучаете материалы и пишете код, укладываясь в + Каждую субботу онлайн-группа созванивается со своим преподавателям. + Затем в течение недели вы изучаете материалы и пишете код, укладываясь в дедлайны. Как только накопятся вопросы - пишете в общий чат или куратору.

    @@ -1411,111 +1288,9 @@

    онлайн курс

    -
    -
    - - -
    @@ -1582,7 +1357,7 @@

    Частным лицам

    src="{% static 'images/icon-svg/sv.svg' %}" alt="Связной">

  • -

    Для оплаты зарубежной картой свяжитесь с нами Для оплаты зарубежной картой свяжитесь с нами learn@python.ru.

  • @@ -1923,25 +1698,6 @@
    -
    -
    -
    - -
    -
    -
    -
    - Да, такая возможность есть. В этом случае вы пропускаете оффлайн-занятия, однако - вы - сможете общаться - с куратором по Скайпу. -
    -
    -
    @@ -2062,10 +1818,7 @@
    - Да, обязательно иметь свой ноутбук или компьютер. Если вы учитесь оффлайн: - приносите - и - уносите ноутбук с собой, а мы обеспечим розетки, стол, стул, чай и печеньки. + Да, обязательно иметь свой ноутбук или компьютер
    @@ -2108,24 +1861,6 @@
    -
    -
    -
    - -
    -
    -
    -
    - Можно перейти с оффлайна на онлайн-обучение. Сделать наоборот не получится - - места - в оффлайн-группе ограничены. -
    -
    -
    @@ -2157,15 +1892,6 @@

    Контакты

    -
    -
    -
    -
    -
    -
    -
    -
    -
    @@ -2174,19 +1900,10 @@

    Контакты

    Наши контакты

      -
    • Email

      learn@python.ru
    • -
    • -

      Адрес занятий для оффлайн-группы

      -
      Impact Hub, Хохловский пер., 7-9с2, подъезд 3, этаж 1 - (м. Китай-город) -
      -
    • Наш сайт

      moscowpython.ru @@ -2208,7 +1925,7 @@

      Мы в социальных сетях

    @@ -2218,7 +1935,7 @@

    Мы в социальных сетях

    diff --git a/landing_page/mainpage/tests.py b/landing_page/mainpage/tests.py deleted file mode 100644 index 7ce503c2..00000000 --- a/landing_page/mainpage/tests.py +++ /dev/null @@ -1,3 +0,0 @@ -from django.test import TestCase - -# Create your tests here. diff --git a/landing_page/mainpage/views.py b/landing_page/mainpage/views.py index fe13d01d..b072fd15 100644 --- a/landing_page/mainpage/views.py +++ b/landing_page/mainpage/views.py @@ -1,23 +1,15 @@ -from django.shortcuts import render -from django.conf import settings -from django.http import ( - HttpResponse, HttpResponseForbidden, - HttpResponseServerError) +from django.http import HttpResponse from django.template import loader from .models import (LearnPythonCourse, GraduateProjects, LearnPythonCoursePrices, - Feedback, Curators, GraduateStories, GraduateProjectsVideos, - Podcasts, LearnPythonMultiCityCourses,) + Feedback, Curators, GraduateProjectsVideos + ) from datetime import date -import json def index(request): - '''Docstring testc''' template = loader.get_template('mainpage/index.html') - # Course data - # Fixes #3 LearnPythonCourse matching query does not exist. try: current_course = LearnPythonCourse.objects.latest('course_index') except LearnPythonCourse.DoesNotExist: @@ -25,57 +17,20 @@ def index(request): online_prices = LearnPythonCoursePrices.objects.filter( course_type='Online').order_by('price_range_price') - offline_prices = LearnPythonCoursePrices.objects.filter( - course_type='Offline').order_by('price_range_price') - offline_prices_penza = LearnPythonCoursePrices.objects.filter( - course_type='OfflinePenza').order_by('price_range_price') - offline_prices_spb = LearnPythonCoursePrices.objects.filter( - course_type='OfflineSpb').order_by('price_range_price') # Student projects data student_projects = list(GraduateProjects.objects.all()) - # User stories - graduate_stories_list = list(GraduateStories.objects.all()) - - # City counter - city_counter = len(list(LearnPythonMultiCityCourses.objects.all())) - - # User podcasts - podcasts_list = list(Podcasts.objects.all()) - # Curators data curators_list = Curators.objects.filter(curator_status=True) # Feedback data student_feedback = list(Feedback.objects.all()) - # Closed sessions - is_online_closed = current_course.online_session_closed - - is_offline_closed = current_course.offline_session_closed - - listed_cities = [city for city in LearnPythonMultiCityCourses.objects.all()] - - offline_cities = [ - {'name': city.city_name, - 'coords': [float(city.long), float(city.lat)], - 'early_date': str(city.early_date), - 'early_price': str(city.early_price), - 'early_installment_price': city.early_installment_price, - 'basic_date': str(city.basic_date), - 'basic_price': str(city.basic_price), - 'basic_installment_price': city.basic_installment_price - } for city in listed_cities - ] - context = { 'course': current_course, 'projects': student_projects, 'online_price_ranges': online_prices, - 'offline_price_ranges': offline_prices, - 'offline_price_penza_ranges': offline_prices_penza, - 'offline_price_spb_ranges': offline_prices_spb, 'registration_closes_date': current_course.end_registration_date .strftime( '%b %d, %Y %H:%M:%S' @@ -96,20 +51,12 @@ def index(request): } ], 'curators_list': curators_list, - 'graduate_stories': graduate_stories_list, - 'podcasts_list': podcasts_list, 'today': date.today(), - 'is_online_closed': is_online_closed, - 'is_offline_closed': is_offline_closed, - 'offline_cities': offline_cities, - 'offline_cities_json': json.dumps(offline_cities), - 'offlice_cities_counter': city_counter } return HttpResponse(template.render(context, request)) def projects(request): - '''Docstring testc''' template = loader.get_template('mainpage/projects.html') try: @@ -117,7 +64,6 @@ def projects(request): except LearnPythonCourse.DoesNotExist: current_course = LearnPythonCourse() - # Student projects data student_projects_videos = list(GraduateProjectsVideos.objects.all().order_by('-project_course')) context = { From 325d2353a2cdc8517744a0793ff9158b3925639c Mon Sep 17 00:00:00 2001 From: Ilya Lebedev Date: Wed, 16 Aug 2023 16:09:10 +0400 Subject: [PATCH 055/107] refactor index template vars --- .../mainpage/templates/mainpage/index.html | 39 +++++++------ landing_page/mainpage/views.py | 57 +++++++++++-------- 2 files changed, 52 insertions(+), 44 deletions(-) diff --git a/landing_page/mainpage/templates/mainpage/index.html b/landing_page/mainpage/templates/mainpage/index.html index 481231ba..4158b95e 100644 --- a/landing_page/mainpage/templates/mainpage/index.html +++ b/landing_page/mainpage/templates/mainpage/index.html @@ -183,10 +183,10 @@

    Ближайший набор прой проверять ваш код и давать рекомендации.

    - С {{course.course_start_date | date:"j E" }} по {{course.course_end_date | date:"j E" }} + С {{enrollment.start_date | date:"j E" }} по {{enrollment.end_date | date:"j E" }}

    - Регистрация закроется {{course.end_registration_date | date:"j E" }} + Регистрация закроется {{enrollment.end_registration_date | date:"j E" }}

    {% comment %}
    {% endcomment %}
    + data-count-down="{{ registration_closes_date_formatted }}">
    00дней
    @@ -254,8 +254,8 @@

    Учитесь онлайн
    Ранняя регистрация
    До - {{ online_price_ranges.0.price_range_end_date | date:"j E" }}
    - {{ online_price_ranges.0.price_range_price}} + {{ enrollment.early_price.date_to | date:"j E" }}

    + {{ enrollment.early_price.price_rub }} р.
    @@ -263,11 +263,10 @@

    Учитесь онлайнот 3500 р/мес Есть - рассрочка + style="padding-top: 5px">Есть рассрочка

    - {% if today <= online_price_ranges.0.price_range_end_date %} + {% if today <= enrollment.early_price.date_to %} {%endif%} @@ -1224,8 +1223,8 @@

    онлайн курс

    Ранняя регистрация
    До - {{ online_price_ranges.0.price_range_end_date | date:"j E" }}
    - {{ online_price_ranges.0.price_range_price}} + {{ enrollment.early_price.date_to | date:"j E" }}
    + {{ enrollment.early_price.price_rub }} р.
    @@ -1237,7 +1236,7 @@

    онлайн курс

    рассрочка
    - {% if today <= online_price_ranges.0.price_range_end_date %} + {% if today <= enrollment.early_price.date_to %} {%endif%} @@ -1975,7 +1974,7 @@

    записаться на курс

    +
    + + + + + + diff --git a/landing_page/mainpage/templates/mainpage/include/index_reviews.html b/landing_page/mainpage/templates/mainpage/include/index_reviews.html new file mode 100644 index 00000000..d40ca62a --- /dev/null +++ b/landing_page/mainpage/templates/mainpage/include/index_reviews.html @@ -0,0 +1,74 @@ +{% load static %} + + +
    +
    +
    +

    Отзывы

    +
    +
    +
    +
    +

    Отзывы наших выпускников

    +
    +
    + +
    +
      +
    • +
      + 3 year +
      +
      +

      5 лет

      + курсу +
      +
    • +
    • +
      + 11 sets +
      +
      +

      1000+

      + выпускников +
      +
    • + +
    +
    +
    +
    + +
    +
    +
    diff --git a/landing_page/mainpage/templates/mainpage/include/index_you_will_learn.html b/landing_page/mainpage/templates/mainpage/include/index_you_will_learn.html new file mode 100644 index 00000000..6eba2485 --- /dev/null +++ b/landing_page/mainpage/templates/mainpage/include/index_you_will_learn.html @@ -0,0 +1,101 @@ +{% load static %} + +
    +
    +
    +

    Вы научитесь

    +

    Вы научитесь

    +

    Программировать, а не кодить.

    +
    +
    +
    +
    +
    +
    +
    +
    + +
    +

    Делать сайты и веб-приложения

    +
    +
    +

    + и сможете написать «клон» Avito: доску объявлений для одной товарной категории с собственной + базой данных +

    +
    +
    +
    +
    +
    +
    +
    + +
    +

    Работать с данными

    +
    +
    +

    + и сможете написать первый data science проект: сервис, который будет анализировать успешность + постов в VK по реакциям читателей +

    +
    +
    +
    +
    +
    +
    +
    + +
    +

    Создавать чат-ботов

    +
    +
    +

    и сможете написать Telegram-бота, который информирует друзей о курсе акций и криптовалют

    +
    +
    +
    + +
    +
    +
    +
    + +
    +

    Писать свои проекты

    +
    +
    +

    + Если вам неинтересен типовой проект, после 3-го занятия можно предложить свою идею группе. + Кто-то из однокурсников присоединится, чтобы взять на себя часть задач, а куратор поможет + вам спланировать шаги на каждую неделю и подскажет, какие технологии и библиотеки вам пригодятся. +

    +

    + Каждую неделю вы будете добавлять функциональность, а на финальном занятии презентуете + рабочую версию проекта. +

    +

    + После 3-го занятия вы можете предложить свою идею однокурсникам или присоединиться к чужому + проекту. +

    +

    + Вот какие проекты делали студенты 10-го набора (май-июль 2018): +

    +
    +
    +
    + +
    +
    +
    +
    +
    diff --git a/landing_page/mainpage/templates/mainpage/index.html b/landing_page/mainpage/templates/mainpage/index.html index 4158b95e..3d01dba4 100644 --- a/landing_page/mainpage/templates/mainpage/index.html +++ b/landing_page/mainpage/templates/mainpage/index.html @@ -1,2020 +1,330 @@ - - {% load static %} {% load l10n %} - - - - - - - - - - - - - - - - Learn Python - Курсы Python онлайн - - - - - - - - - - - - - -
    - -
    - -
    -
    -
    -
    - -

    Курс программирования на Python 3.10 - для любого уровня c упором на практику

    -

    Ближайший набор пройдет только Онлайн

    -

    - Вы создадите Telegram-бота на первом же уроке. Познакомитесь с основами data science и - веб-разработки. - Напишете собственный проект. Опытные питонисты, имеющие опыт «боевой» разработки, всю дорогу - будут - проверять - ваш код и давать рекомендации.

    -

    - С {{enrollment.start_date | date:"j E" }} по {{enrollment.end_date | date:"j E" }} -

    -

    - Регистрация закроется {{enrollment.end_registration_date | date:"j E" }} -

    - {% comment %}
    - -
    - Оставьте свои контакты -
    -

    И мы сообщим о начале регистрации на следующий набор

    -
    - -
    -
    - -
    - - - - - - - - - - -
    {% endcomment %} - -
    -
    00дней -
    - : -
    00часов -
    - : -
    00минут -
    - : -
    00секунд -
    -
    -
    -
    -
    -
    -
    -

    Учитесь онлайн

    -

    - Версия курса для тех, кто много работает, живет не в Москве или за рубежом. -

    -
      -
    • Те же преподаватели и задачи, что и у оффлайн-группы
    • -
    • Индивидуальные созвоны с куратором в субботу. Telegram-чат в другие - дни -
    • -
    -
    -
    -
    -
    -
    Ранняя регистрация
    -
    До - {{ enrollment.early_price.date_to | date:"j E" }}
    - {{ enrollment.early_price.price_rub }} - р. -
    - -
    - {% if today <= enrollment.early_price.date_to %} - - {%else%} - - {%endif%} -
    -
    -
    -
    -
    Обычная регистрация
    -
    С - {{ enrollment.late_price.date_from | date:"j E" }}
    - {{ enrollment.late_price.price_rub }} - р. -
    - -
    - {% if today >= enrollment.late_price.date_from %} - - {%else%} - - {%endif%} -
    -
    - -
    -
    -
    + + + + + + + + + + + + + + + + + + Learn Python - Курсы Python онлайн + + + + + + + + + + + + + +
    + {% include 'mainpage/include/index_menu.html' %} +
    + +
    + {% include 'mainpage/include/index_hero.html' with enrollment=enrollment registration_closes_date_formatted=registration_closes_date_formatted %} +
    + {% include 'mainpage/include/index_about_video.html' %} + +
    +
    +
    +

    Что дает этот курс

    +
    -
    -
    -
    -
    -
    -
    -

    О курсе

    -
    -
    -
    -
    -
    -
    -

    Видеоответ на все вопросы

    -

    - Почему мы учим Python’у лучше всех, как мы это делаем, - чему вы научитесь и почему наши выпускники - уже практически junior программисты. -

    -
    -
    -
    -
    - -
    -
    -
    -
    -
    - -
    -
    -
    -

    Что дает этот курс

    -
    -
    - {% if 0 %} -
    -
    -

    О курсе

    -
    -
    - {% endif %} -
    -
    -
      -
    • -
      - Знание основ Python и навыки работы с Flask -
      -
      -

      Знание основ Python и навыки работы с Flask, SQLAlchemy, Jupyter Notebook, Mongo DB, - HTML, JSON, API популярных сервисов, другими технологиями.

      -
      -
    • -
    • -
      - 80+ часов практики -
      -
      -

      Много практики: от 80 часов с преподавателями и самостоятельно.

      -
      -
    • -
    • -
      - Видеоуроки, которые остаются у вас -
      -
      -

      Видеоуроки, которые остаются у вас и после курса: свыше 30 часов.

      -
      -
    • -
    • -
      - Свой проект и портфолио на GitHub. -
      -
      -

      Свой проект и портфолио на GitHub.

      -
      -
    • -
    • -
      - Сертификат -
      -
      -

      Сертификат.

      -
      -
    • -
    • -
      - 2 месяца поддержки после курса: чат, митапы -
      -
      -

      2 месяца поддержки после курса: чат, митапы.

      -
      -
    • -
    -
    -
    -
    -
    -

    Кому подойдет

    -

    - Мы учли интересы всех: и новичков, и продолжающих. -

    -

    В результате вы можете создавать:

    -
    -
    -
    -
    -
    -
    -
    -
    -
      -
    • - Вы никогда не программировали или делали это только в - школе. -
    • -
    • Вы хотите автоматизировать свою работу в управлении - проектами, тестировании, маркетинге, SEO, системном администрировании и - т.д. -
    • -
    • - Вы уже учили основы Python до этого, но где-то - «застряли». -
    • -
    • Вы хотите сменить работу или попасть в ИТ.
    • -
    • Вы учите Python как второй язык программирования, ведь это - лучший второй ЯП для любых задач. -
    • -
    -

    - Курс подстроится под вас. Поэтому мы собираем - небольшие - группы, а куратор следит за - вашим прогрессом в течение всей недели. Если вы забуксуете, он объяснит тему - дополнительно. - А если будете опережать других, вам придумают задачек — скучно не будет! -

    -
    -
    -
    -
    -
    -
    -
    -
    -

    Что вас ждет

    -

    - Вы сразу получите результат и поймете, куда расти. И так каждую неделю. -

    -
    -
    -
    -
    -
    -
    -
    - 80+ часов практики -
    -
    -

    Практика с первого дня:

    -

    от 80 часов с преподавателем и самостоятельно

    -
    -
    -
    -
    -
    -
    - 30 часов видеоуроков -
    -
    -

    30 часов видеоуроков

    -

    и презентации в еженедельных рассылках

    -
    -
    -
    -
    -
    -
    - Куратор, группа 5-7 человек -
    -
    -

    Десятки интересных заданий:

    -

    создание сайтов, ботов, работа с
    данными и т.д. -

    -
    -
    -
    -
    -
    -
    - Интересные задания -
    -
    -

    Куратор, группа 5-7 человек

    -

    и опытные преподаватели

    -
    -
    -
    -
    -
    -
    - Код-ревью -
    -
    -

    Проверка задач: код-ревью

    -

    и рекомендации куратора

    -
    -
    -
    -
    -
    -
    - 2 месяца поддержки -
    -
    -

    Свой проект

    -

    во второй половине курса

    -
    -
    -
    -
    -
    -
    - Готовое портфолио -
    -
    -

    Живое общение и Telegram-чат

    -

    с преподавателями и однокурсниками

    -
    -
    -
    -
    -
    -
    - Знакомства в отрасли -
    -
    -

    Поддержка в течение 2 месяцев

    -

    после окончания курса

    -
    -
    -
    -
    -
    -
    -
    -
    -
    -

    Вы научитесь

    -

    Вы научитесь

    -

    Программировать, а не кодить.

    -
    - -
    -
    -
    -
    -
    -
    -
    - -
    -

    Делать сайты и веб-приложения

    -
    -
    -

    и сможете написать «клон» Avito: доску объявлений для одной товарной - категории с - собственной базой данных

    -
    -
    -
    -
    -
    -
    -
    - -
    -

    Работать с данными

    -
    -
    -

    и сможете написать первый data science проект: сервис, который будет - анализировать успешность постов в VK по реакциям читателей

    -
    -
    -
    -
    -
    -
    -
    - -
    -

    Создавать чат-ботов

    -
    -
    -

    и сможете написать Telegram-бота, который информирует друзей о курсе акций и - криптовалют

    -
    -
    -
    - -
    -
    -
    -
    - -
    -

    Писать свои проекты

    -
    -
    -

    Если вам неинтересен типовой проект, после 3-го - занятия - можно предложить свою идею группе. Кто-то из однокурсников присоединится, - чтобы взять на себя часть задач, а куратор поможет вам спланировать шаги на - каждую неделю и подскажет, - какие технологии и библиотеки вам пригодятся. -

    -

    Каждую неделю вы будете добавлять функциональность, а - на финальном занятии презентуете рабочую версию проекта.

    -

    После 3-го занятия вы можете предложить свою идею - однокурсникам - или присоединиться к чужому проекту.

    -

    Вот какие проекты делали студенты 10-го набора - (май-июль - 2018):

    -
    -
    -
    - -
    -
    -
    -
    -
    - -
    -
    - -
    -
    -

    - Проекты, созданные во время обучения -

    -
    -

    - Смотреть все проекты -

    -
    -
    - {% if projects %} - {% for project in projects %} -
    - slide -

    {{ project.project_name }}

    -
    - {% endfor %} - {% endif %} -
    -
    -
    -
    -
    -
    -
    -
    -

    После курса у вас останутся

    -

    - Новые навыки, связи и полезные материалы. -

    -
    -
    -
    -
    -
    -
    - Доступ ко всем видеолекциям и презентациям -
    -
    -

    Доступ ко всем видеолекциям и презентациям.

    -
    -
    -
    -
    - Сертификат о прохождении курса -
    -
    -

    Сертификат о прохождении курса.

    -
    -
    -
    -
    - Чат со всеми преподавателями, кураторами и однокурсниками -
    -
    -

    Чат со всеми преподавателями, кураторами и однокурсниками.

    -
    -
    -
    -
    - Портфолио выполненных проектов на GitHub -
    -
    -

    Портфолио выполненных проектов на GitHub.

    -
    -
    -
    -
    - Опыт работы с Flask, SQLAlchemy, Jupyter Notebook, Mongo DB, Pandas, Bootstrap
-										(HTML/CSS), JSON -
    -
    -

    Опыт работы с Flask, SQLAlchemy, Jupyter Notebook, - Mongo DB, Pandas, Bootstrap - (HTML/CSS), JSON, API популярных сервисов, другими технологиями.

    -
    -
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -

    Как проходит обучение

    -
    -
    -
    -
    -
    -

    Как проходит курс

    -
    -
    -
    -
    -
    -
    -

    Что вас ждет

    -

    - Вы будете много работать самостоятельно по вечерам и выходным, а преподаватели будут - рядом, чтобы подсказать. -

    -
    -
    -
    -
    -
    -

    - Все группы занимаются по одной программе и получают - одинаковое - внимание - преподавателей и кураторов. -

    -

    - Каждую субботу онлайн-группа созванивается со своим преподавателям. - Затем в течение недели вы изучаете материалы и пишете код, укладываясь в - дедлайны. - Как только накопятся вопросы - пишете в общий чат или куратору. -

    -
    -
    -
      -
    • -
      -
      - 1-3 неделя -

      Изучаем и подтягиваем основы Python

      -
      - -

      - Каждую неделю вы на практике проходите блок базовых знаний: слушаете - мини-лекций, - пишете код по примерам, затем выполняете проекты и задачи по теме и - выкладываете на проверку в вашем репозитории. Кураторы дают фидбек, как - улучшить код. -

      -
      -
    • -
    • -
      -
      - 4-9 неделя -

      Пишем свой проект

      -
      -

      - Вы продолжаете изучать материалы и выполнять задания, а параллельно - начинаете дипломный проект: выбираете идею и напарника, каждую неделю - добавляете функциональность. Куратор помогает спланировать этапы разработки, - подобрать технологии и решить сложности, которые возникают в процессе. -

      -
      -
    • -
    • -
      -
      - 10 неделя -

      Финишная прямая

      -
      -

      - Вы доводите проект до рабочего прототипа, который можно показать - коллегам и друзьям, и презентуете его перед аудиторией (онлайн-группа - делает это по видеосвязи). Если вы презентуете свой проект - вы - получаете сертификат - об успешном окончании курса. -

      -
      -
    • -
    -
    -
    -
    -
    -
    -
    - -
    -
    -
    -

    Программа

    -
    -
    -
    -
    -
    -
    -

    Программа

    -

    - На курсе мы учим программированию на Python в целом - "Основной" трек.

    -

    - Параллельно с основным курсом вы по выбору можете изучать один из тематических треков:

    -
      -
    • Веб-разработка
    • -
    • Анализ данных
    • -
    • Чат-боты
    • -
    -

    - Используйте переключатели, чтобы посмотреть содержание каждого трека. -

    -

    -
    -
    -
    -
    - -
    -
    - {% include "mainpage/include/track_main.html" %} -
    -
    - {% include "mainpage/include/track_web.html" %} -
    -
    - {% include "mainpage/include/track_ds.html" %} -
    -
    - {% include "mainpage/include/track_bots.html" %} -
    -
    -
    -
    -
    -
    -
    - -
    -
    -
    -

    Курс ведут

    -
    -
    -
    -
    -
    -

    Кто делает курс

    -
    -
    -
    -
    -
    -

    Кто мы

    -
    -
    -
    -
    -
    -
    -
    -
    -

    Курс организует сообщество MoscowPython

    -

    C 2012 года проводим митапы Python-разработчиков на площадках Яндекса, ЦИАН, - Мегафона, - Mail.ru Group и других компаний. Записываем видео и подкаст для питонистов. - Объединили - свыше 5К человек в единое комьюнити.

    -
      -
    • -
      - 3 year -
      -
      -

      5 лет

      - курсу -
      -
    • -
    • -
      - 11 sets -
      -
      -

      20 наборов

      - прошли обучение -
      -
    • -
    • -
      - 400 graduates -
      -
      -

      1000+

      - выпускников -
      -
    • -
    -
    -
    -
    -
    -
    -
    -
    -
    -

    Основные преподаватели и организаторы

    -
    -
    -
    -
    -

    Основные преподаватели и организаторы

    -

    - Практики с большим опытом в разработке и управлении проектами. Разработали сам курс. - Ведут занятия. Записывают видеолекции. Помогают со сложными задачами. Отвечают за - организационные и административные вопросы. -

    -
    -
    -
      -
    • -
      -
      - Михаил Корнеев -
      -
      -

      Михаил Корнеев

      -

      - В коммерческой разработке с 2001 года, с 2009 — работает с Python. -

      -

      - Cооснователь MoscowPython. Тимлид в BestDoctor. -

      -
      -
      - Сооснователь MoscowPython, Тимлид в BestDoctor. В коммерческой - разработке с 2001 года, с 2009 - работает с Python. -
      -
      -
    • -
    • -
      -
      - Валентин Домбровский
      -
      -

      Валентин Домбровский

      -

      - Евангелист и сооснователь MoscowPython сообщества. -

      -

      - Сооснователь Drylabs, компании, создающей open-source проекты. -

      -
      -
      - Евангелист и сооснователь MoscowPython сообщества. - Сооснователь Drylabs, компании, создающей open-source проекты. -
      -
      -
    • -
    • -
      -
      - Семен Осипов -
      -
      -

      Семён Осипов

      -

      - Активист MoscowPython сообщества, Team Lead в Gett, до этого - Big Data Engineer - в X5 Retail Group и Semrush. -

      -
      -
      - Активист MoscowPython сообщества, Team Lead в Gett, до этого - Big Data Engineer - в X5 Retail Group и Semrush. -
      -
      -
    • -
    -
    -
    -
    -
    -

    Кураторы групп

    -
    -
    -
    -
    -

    Кураторы групп

    -

    - Первыми придут на помощь на занятиях и между ними. Помогут спланировать и - распределить задачи в вашем выпускном проекте. -

    -
    -
    -
      - {% for curator in curators_list %} -
    • -
      -
      - {% if curator.curator_photo %} - {{curator.curator_name}} - {%endif%} -

      {{curator.curator_name}}

      -
      -
      -

      - {{ curator.curator_bio }} -

      -
      -
      -
    • - {% endfor %} -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    Поддержка трудоустройства

    -
    -
    -
    -
    -
    -

    Поддержка трудоустройства

    -
    -
    -
    -
    -
    -
    -
    -

    Что это такое?

    -

    - После окончания курсов мы помогаем нашим выпускникам с трудоустройством: рассказываем, - как - проходить собеседования, как исправить резюме и причесать GitHub. -

    -
    -
    -
    -
    -
    -

    - Все участники получают нашу поддержку по трудоустройству. -

    -

    - После окончания курса мы проводим бесплатный вебинар, на котором - рассказываем про особенности составления - резюме, прохождения собеседований, поиску работы. Мы также приглашаем в наш закрытый - чат, где мы делимся вакансиями - "из первых рук" для начинающих. -

    -
    -
    -
      -
    • -
      -
      - Шаг 1 -

      Посещаем вебинар по поиску работы

      -
      - -

      - Через неделю после окончания курса мы проводим вебинар по поиску работы. - Мы говорим о том, почему надо ходить - на собеседования и как их не бояться, рассказываем "секреты" HR и о том, - как составлять резюме, чтобы на него - обращали внимание, причесываем GitHub. -

      -
      -
    • -
    • -
      -
      - Шаг 2 -

      Корректируем курс

      -
      -

      - Желающие могут заполнить анкету с резюме и ссылкой на свой проект, - а мы дадим персональные комментарии по составлению резюме и вашему - GitHub. -

      -
      -
    • -
    • -
      -
      - Шаг 3 -

      Работа с партнерами

      -
      -

      - Ваши исправленные резюме мы показываем нашим партнерам, которые проявили - заинтересованность в найме наших - выпускников. -

      -
      -
    • -
    -
    -
    -
    -
    -
    -
    - -
    -
    -
    -

    Стоимость

    -
    -
    -
    -
    -

    Записаться

    -
    -
    -
    -
    - -
    -
    -

    онлайн курс

    -
    -
    -
    -
    -
    Ранняя регистрация
    -
    До - {{ enrollment.early_price.date_to | date:"j E" }}
    - {{ enrollment.early_price.price_rub }} - р. -
    - -
    - {% if today <= enrollment.early_price.date_to %} - - {%else%} - - {%endif%} -
    - -
    -
    -
    -
    Обычная регистрация
    -
    С - {{ enrollment.late_price.date_from | date:"j E" }}
    - {{ enrollment.late_price.price_rub }} - р. -
    - -
    - {% if today >= enrollment.late_price.date_from %} - - {%else%} - - {%endif%} -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -

    Как оплатить

    -
    -
    -
    -
    -
    -

    Как оплатить

    -
    -
    -
    -
    -
    -

    Рассрочка на 1, 6 или 12 месяцев

    -
    -
    -
    -

    Рассрочка - вид кредита, который предоставляет «Яндекс.Касса» и её банки-партнеры. - Услуга доступна гражданам РФ с постоянным доходом в возрасте от 18 до 65 лет.

    -
      -
    • -

      Начните регистрацию и выберите пункт «Оплата в кредит».

      -
    • -
    • -

      Откройте «Яндекс.Кошелек».

      -
    • -
    • -

      Оформите заявку на кредит и дождитесь одобрения.

      -
    • -
    • -

      Погасите полную стоимость обучения в первый месяц, чтобы избежать переплат. - Либо оплачивайте обучение частями в течение 6 или 12 месяцев с переплатой 3,9% в - месяц.

      -
    • -
    -
    -
    -
    -
    -
    -

    Частным лицам

    -

    (оплата сразу)

    -
    -
    -
    -

    Начните регистрацию, чтобы забронировать место на курсе, а затем оплатите курс в течение 4 - дней - одним из способов:

    -
      -
    • -

      Картой Visa или Mastercard. -

      -
    • -
    • -

      Электронными деньгами: Яндекс.Деньги или WebMoney. - yandex money - yandex money -

      -
    • -
    • -

      Наличными через салоны «Связной». Связной

      -
    • -
    • -

      Для оплаты зарубежной картой свяжитесь с нами learn@python.ru.

      -
    • -
    -
    -
    -
    -
    -
    -

    Юридическим лицам

    -

    (безналичная оплата)

    -
    -
    -
    -
      -
    • -

      Начните регистрацию и выберите опцию «Выставить счет».

      -
    • -
    • -

      Свяжитесь с нами по любым вопросам, написав на learn@python.ru. -

      -
    • -
    -
    -
    - -
    -
    - -
    -
    -
    -

    Отзывы

    -
    -
    -
    -
    -

    Отзывы наших выпускников

    -
    -
    - -
    -
      -
    • -
      - 3 year -
      -
      -

      5 лет

      - курсу -
      -
    • -
    • -
      - 11 sets -
      -
      -

      1000+

      - выпускников -
      -
    • +
      + {% include 'mainpage/include/index_course_details_mobile.html' %} + {% include 'mainpage/include/index_course_details_desktop.html' %} + {% include 'mainpage/include/index_you_will_learn.html' %} +
      +
    + +
    +
    +

    + Проекты, созданные во время обучения +

    +
    +

    + Смотреть все проекты +

    +
    +
    + {% if projects %} + {% for project in projects %} +
    + slide +

    {{ project.project_name }}

    +
    + {% endfor %} + {% endif %} +
    +
    +
    + +
    +
    +
    +
    +
    +

    После курса у вас останутся

    +

    + Новые навыки, связи и полезные материалы. +

    +
    +
    +
    +
    +
    +
    + Доступ ко всем видеолекциям и презентациям +
    +
    +

    Доступ ко всем видеолекциям и презентациям.

    +
    +
    +
    +
    + Сертификат о прохождении курса +
    +
    +

    Сертификат о прохождении курса.

    +
    +
    +
    +
    + Чат со всеми преподавателями, кураторами и однокурсниками +
    +
    +

    Чат со всеми преподавателями, кураторами и однокурсниками.

    +
    +
    +
    +
    + Портфолио выполненных проектов на GitHub +
    +
    +

    Портфолио выполненных проектов на GitHub.

    +
    +
    +
    +
    + Опыт работы с Flask, SQLAlchemy, Jupyter Notebook, Mongo DB, Pandas, Bootstrap
+                                                (HTML/CSS), JSON +
    +
    +

    Опыт работы с Flask, SQLAlchemy, Jupyter Notebook, + Mongo DB, Pandas, Bootstrap + (HTML/CSS), JSON, API популярных сервисов, другими технологиями.

    +
    +
    +
    +
    +
    - -
    + +
    - {% if 0 %} -
    -
    - -
    -
    - {% endif %} + {% include 'mainpage/include/index_authors.html' with curators_list=curators_list%} -
    -
    - -
    -
    -
    +
    +
    +
    +

    Стоимость

    +
    +
    +
    +
    +

    Записаться

    +
    +
    +
    +
    + +
    +
    +

    онлайн курс

    +
    +
    +
    +
    +
    Ранняя регистрация
    +
    До + {{ enrollment.early_price.date_to | date:"j E" }}
    + {{ enrollment.early_price.price_rub }} + р. +
    + +
    + {% if today <= enrollment.early_price.date_to %} + + {% else %} + + {% endif %} +
    + +
    +
    +
    +
    Обычная регистрация
    +
    С + {{ enrollment.late_price.date_from | date:"j E" }}
    + {{ enrollment.late_price.price_rub }} + р. +
    + +
    + {% if today >= enrollment.late_price.date_from %} + + {% else %} + + {% endif %} +
    +
    +
    +
    +
    +
    +
    -
    -
    -
    -

    FAQ

    -
    -
    -
    -
    -
    -
    -
    -
    -
    - - Зачем мне вообще Python? - -
    -
    -
    -
    - С одной стороны, умение программировать может быть подспорьем для вас в основной - работе — вы сможете - писать полезные программы для сбора данных, их анализа и вывода в удобном - формате - (будь то веб сайт - или бот в мессенджере). Это может быть полезно, если вы работаете маркетологом, - аналитиком данных, - системным администратором, seo-специалистом и так далее. С другой стороны, - программист — - востребованная профессия и наши курсы могут помочь сделать первый шаг в её - освоении. -
    -
    -
    -
    -
    -
    - -
    -
    -
    -
    - В течение всего курса вы находитесь в плотном взаимодействии со своим куратором, - имея возможность - получать ответы на свои вопросы и отзывы по поводу своего кода. Также работая - над - своим реальным - проектом в течение курса, вы учитесь командному взаимодействию, которое является - важной частью - работы разработчика. В целом курс выстроен так, что вы не попадёте в ситуацию, - когда - вам необходимо - построить синхрофазотрон, научившись закручивать гайки — программа выстроена с - учётом постепенного - вхождения в программирование в правильной логической последовательности. -
    -
    -
    -
    -
    -
    - -
    -
    -
    -
    - Создавая курс, мы старались учесть интересы тех, кто не знает о программировании - вообще ничего, так - что можно смело сказать, что он рассчитан на самых новичков. При этом, однако, - формат курса и фокус - на практике предполагает возможность «повышения квалификации» для тех, кто учит - Python как второй - язык программирования или же уже выучил основы до этого — вы сможете заниматься - в - том темпе, в каком - вам будет комфортно. -
    -
    -
    -
    -
    -
    - -
    -
    -
    -
    - В каждом наборе курса участвует порядка 70-и человек. Все они делятся на группы - по 5-6 - человек - согласно уровню знаний. Первое занятие — интенсив, который продлится с 10 до 19 - часов и в ходе - которого вы напишете своего первого бота для мессенджера Telegram. В дальнейшем - мы - будем предлагать - вам лекции для изучения в онлайн-режиме, а практические занятия будут полностью - посвящены практике и - взаимодействию с куратором. Каждое такое занятие будет проходить по субботам с - 15 до - 18 часов. Также - в течение курса вы сможете общаться с «сокурсниками» и куратором в - онлайн-режиме. - Первые 4 занятия - курса вам даётся домашнее задание. Вы его делаете и по готовности показываете - куратору. После 4-й - недели вы планируете свой проект, разбиваете задачи с напарником (куратор - помогает - это сделать) и - каждую неделю добавляете функциональность в свой проект. Здесь вы сами ставите себе - задачи - (куратор - поможет, если случился затык, но не будет ставить задачи за вас). Презентации - проектов будет - посвящена часть последнего — «выпускного» — занятия. -
    -
    -
    -
    -
    -
    - -
    -
    -
    -
    - Да, вы сможете постоянно возвращаться к той или иной лекции по необходимости. -
    -
    -
    -
    -
    -
    - -
    -
    -
    -
    - Для начала работы программистом даже на начальной позиции требуются опыт и - портфолио. Начать - формировать и то, и другое вы сможете уже в ходе занятий на курсе. После этого, - если - вы захотите - работать программистом, мы рекомендуем продолжить формирование портфолио и - профессиональное развитие - — все необходимые для этого ресурсы будут вам предоставлены. Где-то через - полгода — - год - самостоятельного развития вы сможете попробовать себя на позицию - junior-разработчика. -
    -
    -
    -
    -
    -
    - -
    -
    -
    -
    - Нет, не критично, поскольку материалы лекций будут доступны онлайн, а - практиковаться - вы сможете - самостоятельно, поддерживая контакт с куратором также онлайн. -
    -
    -
    -
    -
    -
    - -
    -
    -
    -
    - Во-первых, мы — не школа программирования, мы — сообщество - разработчиков-практиков - MoscowPython. У - нас нет профессиональных преподавателей — в течение курса вы общаетесь с теми, - кто - имел реальный - опыт участия в «боевых» проектах. Во-вторых, наш курс сфокусирован на практике и - не - требует знаний - программирования для того, чтобы можно было начать учиться на нём. С другой - стороны, - опять же в силу - фокуса на практике, курс подходит и тем, кто имеет больше опыта в - программировании. -
    -
    -
    - -
    -
    -
    - -
    -
    -
    -
    - Да, посмотрите эту историю нашей выпускницы https://youtu.be/p3BLRyDsvyk -
    -
    -
    -
    -
    -
    - -
    -
    -
    -
    - На курсе мы не требуем этих знаний. Вы можете начать заниматься и так: часто - программисту - важнее разобраться в другой отрасли работы (например, том, как устроена - бухгалтерия), - чтобы написать хороший сервис. -
    -
    -
    -
    -
    -
    - -
    -
    -
    -
    - Да, обязательно иметь свой ноутбук или компьютер -
    -
    -
    -
    -
    -
    - -
    -
    -
    -
    - За неделю до начала занятий вы начнете получать сообщения, что и как установить - на ноутбук. - Также мы будем делиться полезными материалами во время курса. - А пока рекомендуем наш подкаст - Moscow - Python Podcast. -
    -
    -
    -
    -
    -
    - -
    -
    -
    -
    - Да. Если ко второму занятию вы поймете, что мы не оправдали ваших надежд - - напишите нам и мы вернем деньги в полном объеме. - Также, в случае форс-мажорных обстоятельств за небольшую доплату мы можем вас - перевести на следующий набор. -
    -
    -
    -
    -
    -
    - -
    -
    -
    -
    - Мы всегда рады и рассматриваем новых кураторов для наших наборов. - Если вы заинтересованы - пишите нам на learn@python.ru -
    -
    -
    -
    -
    -
    -
    -
    + {% include 'mainpage/include/index_how_to_pay.html' %} - + {% include 'mainpage/include/index_reviews.html' with student_videos=student_videos %} -
    - -
    - + {% include 'mainpage/include/index_faq.html' %} - + - {% comment %}
    - - -
    {% endcomment %} + {% include 'mainpage/include/index_register_popup.html' with enrollment=enrollment %} - - - - - - - - - - - + + + + + + + + From faa039ba9ba40b579d827205d8087a1bb2c7bd94 Mon Sep 17 00:00:00 2001 From: Ilya Lebedev Date: Thu, 24 Aug 2023 16:21:59 +0200 Subject: [PATCH 063/107] index texts update --- .../static/images/mentor/teacher/lebedev.jpg | Bin 0 -> 106569 bytes .../mainpage/include/index_authors.html | 49 +++++++++--------- .../templates/mainpage/include/index_faq.html | 29 +---------- .../mainpage/include/index_hero.html | 2 +- .../mainpage/include/index_how_to_pay.html | 30 ----------- .../mainpage/include/index_modules.html | 11 ++-- landing_page/mainpage/views.py | 21 ++++++-- 7 files changed, 48 insertions(+), 94 deletions(-) create mode 100644 landing_page/mainpage/static/images/mentor/teacher/lebedev.jpg diff --git a/landing_page/mainpage/static/images/mentor/teacher/lebedev.jpg b/landing_page/mainpage/static/images/mentor/teacher/lebedev.jpg new file mode 100644 index 0000000000000000000000000000000000000000..8d3d15a443271d253a1f5a1f313137f89ed75751 GIT binary patch literal 106569 zcmb?@bx_+)_iqRuq_~IT65Ij=Deh3*3KR>F5-5-aFArYagNNc8Tnd!7xH}YY3vD3; zs3EndeR}Ep&YkzY_m4YsXMQI$yJyet**$yq``!I)c9Y**zxM$QCI-d^01_YoKyv*7 z{C*E8xAeP@zK`;|AH=61EelZ5F*YY71N@;_9-uFPMaNM8uK(QtM}5P9d!doKP>hYD z3J*{W;Ax;^t|u!eD=X`v>M84e9n1R2Dti2hJw25F6|2gtDE&!8RaO3-R#t)kNh_&( z|10ew5C2!JsO01INA962tMaEtMb&HZb^QAc%{OCR-Mg07w+)QV^Z_K-7SkO6G40xZ zKtLcm#M)4Y&(X=5k8&G83g8B?0)zlJJ-kpsf6Dw{bglcp>C48Sz5@VjQh!46ZyK-K z&+Xd6b$+~?O;Dx#Bl~|4gEt)Ib?rXA>oO6Z*NtEE!`D2Er>(W_HNOr3P|#0w z;3n#i1C8}{p>nEFsFb{v9G@rB!^@u!<>i6=Q|tdU{TZu&*C|v90Nl8?t#8Q-6B7Dw z8QGtR8~_5`0I&c!0lWY~fEYjuAP-Omr~$M9`T!HaZGbJn3E&3s0{8&}03m=dKr|o@ zkPJu%C3tI0T#mJ^{V}{w5(Ip(LRr zVJ6`uxk(~SB0(ZgqC%ocqEBK*Vol;i;!fgA5=ep}i6%)PNhir8DJ7{QX(H()86X)U znITyr*(Nz4A(EVv`~Z>yX@M+2Fi-?215^QO15JUpKv$qIFc=sKOax{Di-FZZJg^Tq z0-OWB0PX`%fmfseQW{b=Qhrh?QWa8N(%YoYq&}n}q%ovvq=lr_q-~^wq*J78r2C|2 zq~FOX$e79a$fU^B$c)JB$h^pc$zsSd$V$l?$@<8~$=1jY$Uc$%LrzD|LoPuMBR3{@ zB=;o`BTptTB(Ep$C7&RFL4HX7g@S^DjY5<{nZk&|iQ*nb6h#IFj-s7nm|}(EEyWcj zB_$`N1f>S$ZAuSHG-Wbn2_>HLIpr$lA>}tJ8mgOA@>B*?&QyU^@l=IW%~a2*R;dV7 ze^WD13sb|WZ&Q0yM^I-|*HRBsFHs*-{|#aUiGnmhwxD~UI8ZUD4KxAT16|P2&t1H=$YxI>5b{V>HnfHqwk|%rT=h)`iAfg?Hg`4B5xGl=)SRZRKBW?g14<^<+i z<_YFQ777+o7GsusEa@z*EQ>6kSeaNAS?yWFS<6_TvhK5yvWc)6vmx2C*}B*^*nY5s z*|pi>?5XT+?5pfwIk-8rIN%&<9PJ!0IDT;Qaq4sWbLMhB=6uOT#s%TB;tJ!c;F{n% z<7VMjaxCA@~KI3KM)#AO!TfqB_mw1!; zrshq=&4QcHZ=Ue6@@exS`HK0*`9AUU@Eh@C_^bFA`TrIW6|fVC7ibrFDF_l&5%du( z5F8c!By>~ATqs(oMQBHuT3AKcPq;{UO8BdYsEC8eLy^ZK$D$mf#-fp;Euwp3bYi!} zg2k%E*2O8rRmARdQ7w z)xT7SRKLTZFf^{>V)X@>U`CO=|0dM)+5z3)JxM_)MwJS(=XM3WguYS zYtUlw$xz8K%5d0-+{n}@*J#riZ0u#+Wcm4 z-+a$P*doy4@om6uPFxZCYc?(X2;?Ecf^wnw$cm8Y?1x#uS@U9TdqQ*SNr0&gN* z1D*#b_-Od#`5gOd_~!c({ciac`kf(k5v7RF_l)j6y7$%pwts{FZ=?gVJ%B2}JzyY^ zDbPP~{66pf@cS!45<$s9`@yhaZ1ATL(~x=;3Cb1Kk7l`EVCFGmm?X?WsAgzc=(jNY zuHOvM!1&$}4I#nm;-&`rv`~gQ^&k7|)o|zXbnE{Od5*Ft#xc z6z3ne5HA~_7k`=HkT94CPK-@_n`D^Ol1!f*lDzp)?ct*ovJ^zhVyZ%FN$Njo-f6Sx zvgw8CKQp{CW;5k7i!*;``D86-L$fP#C~^XGHga#}Hs&$rMdrQDH_z`Y;44TgxWwMY z&J-#ZJ}LqgVT$&P&5HX=gi3NsewO-`z9`cvYcJ<1Pc8q7^Tw@KXjQa50zXQB^rI3{ zxm9IY)mJT2U06d=6IydrYhOE6r&8Bc&sCpZ|EnReVZYJ3alA>nsi~Q#IlBeef@vY* zUGU4TdaeC!Qf*c3Z0+eCfDTN@NvC_~Mwe;VXtzptTaR#0c`tKsS|3SYMBk^!evkM2 zo%&Y>Oa?{=)dqW?NIz*9;vXt|%K9|>8R%K!v)|7npI;3J4WEtpj=UYcJGwjOIJQ1+ zHNH4uIx#(IFgZ4*J@tHAV|r)?HZw4*GW&QAI@dR^G~c_Rw9vZ~T^?Lf zUwO8AYjtEzZ*6kjczy1L#fy~-K%<{?h}!gZVc$Z+72$y*+)0diV1%@rdrIkZ_aGbS!^7L^L2SpWHb)JPkVi z`z-lA7ry*I%mDsJ zkCY7nAXT_VueJY?-LD1!RIaY&IVglL-ycm~Yg@km@`IE$+y@>454`TGJpvwv2=u+~ zf1o!4jkq7khY0+G-u~mJ|D)yqfy968{10YE!^5v}<+YvngCar@zJ6#v<3Kb#B+%oJ zMIOk1jZVlP8&UT|&xMh^LrPd3!tW;q@tvtrlO((fv9Qd*>BL((b4m;urjg>@Cpj@^YZZt zLzJY1Mdii#_@r;i$SbR=tE&r1=@@9k43yN=RsU2%0s?{PY3aFd+~8If;S*8)|EAxg z07fdZO0r5)fB=Amkp##{@_QV>b#3T1iu|uJCjpWI$jB+K^Em%xT+@HK|2mV5{Qs4; z1E3|n-a9Y?8Lz_w&It4z+UerCQfg9f?(WzUI67}Bq|aVVKJ8Az2l%S1Ny+4|I=gJwrzpD#U1C+4pEVI~At79O1;nmrEx8-T zEQ2DI3|9IibxLJGw0#jBw=_q6r&l<`>AQ`{QrjYCyvyjYuhHz8p^K2x`Ix0%;M3B1 zE~2lp%wKGnt-YhsGHA&1i4B`&FOzeLSBr3}Fitv2z4r_oak{;P7gy|p#apMt+W*46 zEVBnkycW{%GbMz*4cYq@(rhixN|v{O>0`0B5oUnIQI$lbBmbJ@9ySH@vlnp+i^<2SwQ;!{ww2a7j&P6I z)>2E*md@Fk@TlD6_ylUjwzkgIjKT_fho862zv9E9=1bJLNAj?{?cr*UZ0K@^$zqjB zGc3>zTXq0eu!|5t--2ut1??&V)_bWd#M^$2t%|9^Y~QDipvM;0Ow~UVKkuP75P0?8 z#wXI4HN)D+PLeP43k)p?tQ)FvUeLnQaQEUWvz}FQUMJXQ$=sqCCeU{Pu@SlOy0C~f zH`7M@@YI;+Z0NF*0R*x-PO*3v)h$c54b*#yWfZHFde0bQ)-EIJNEkS_6?(g?>YcG* zTx@bucZb}5R<~1Y!iu=~#a5AN#S12Ir^1ffv@oE~n6(Slyti4cBx&hnnPNBa$~no4 z@gbs9A4X8zc3|WzFb@pOGH4LaoU+K@{L8RpO*Be-?NRBcvX~Nd1Fv`4l5}cB!$#sG zP!%>$^RE`Q3W{TFp2cfb4YiQVQ>FCVYQ+-DmRwX52IJdC+O`uR9mA5;U5qtOA_!>R zFgv?No2zGDHDqvCi8Wt?2Z-0L4~WeoU7OxiwzI|0QO|9#39l%ALJWS7vZ_O&s4r8k zpxrn;JfrQQ27TFbKUPAy-div(UqYiOy>`hwZ zz-n0~oh0zPnR_Uh%Dgr&yQb z1T~?B*;b3ad-~v&l=Opl=Yuva6}cSZ^|s6w zaDPT*E~)WCvVAE>>_KH_LW1K)l2%VSTQXP2+%n(HEwvXHkgq1Rt#}$UieWx?=8WO$ zt{m*7by~<m;lFtLj_!@ zSySjaO$D;+KbOH>v`F~o8>@;rSm&wQ2bJP@+rTId**0a!oZ_(T@LSG7OTVIr0^8vl z-X;#_6nn?M;HHK;{6={ox|#VdZpolrsigLKH> zojjaCy-3-90z|oo#Rdb0r_9R~TN@SpGl~vN)i>Y4Zc6TY!&NwjPv)DmGK@9llZP?n zp$HDa8X!BeNvEx8o3}OORoGul{5USpdIZjqwm*C>0~oik7uBZ8y}3*(B?emHFYBk2Nwch> zpF+C0#5clj=^e7Tq7b=oLHos_oSj)GaYeZW3C}Xxv|#-4YW=pwj)DXbt)ItkvagdV z7pWR4dB$-+mC!?_{#wI@!a=Y^oRG9Z=h5beTR=N&S! z?~baNEbFx9S+O8*IA^Viio7+m( zPgo$xJ35sCR2kU!)jJ_+`WD!C$1ocYdWeB+ZK`epg2TY2g_|i;Szo?|=R@h@d3qZZ z5*W_G^F>&8NF?&;#1_Om38^`(GBCgvdczT{>`oEKASJ8ALllg-7l=VM8VFjld*!$2 z%&sZ+w(~CjA_1ApCvh}7c$1??oqTH4_i7(eo3Rxu8nC_FkUnVi0Sj;ul8SSCH&D6fP;k&+c(l$R55+XFVo7NkoUCgFx$<*4izG;rM-n~9 zFAi*~JZ`E+?#r;&DILA^M=j3{T#2&MwxXuNUuPfCnEL?VLd~!R3T5of?%8H_IpT^# zPsObU?>gcjjj78DjVqCxd4)PogIU7IN;8A&M{X-J+?V62Ee+~_Go*hBYW*?vTG#RT z;>pllabm_!jRnES8Dd8YRDdM1kuwe-uO2Nid(XPW*;J7|G8;a5x7J`wXC>hV!v>9u zI{~Y`V(VZY+mPFxUL}JrZ^1i5U*1nKp2|&D#PeiF%77!2W zPT4}}lY}61VBgdasrb)U2_6an#EYA1PNXlo+lBw$ZyxDfelyfzU=oQURw#5%qH)~`EbC1hS2*PAVmh%qapIIq zC>vpOg@*G<;K%o44Jf(gpw*2n92DOplwt{$ri`8z;8j(pVeSt8H#9*mfo)c)Y zwp|dqw^#tcpPBbz;)b_KJyn7BvoDJH-jU2!yIkZK(rI|hZbJ0Q>G%fMO+Z=?>{y&7 zX-^6VSL&>dHbQAg#NlG!og7pQqTfi_sWxoSSgYEEV8)N|rE~VTrRUWGEBd#Svt2S1xj(MA*r!6^PG3TDBMzNoFS2M{y!pisuLX6=0TDIl+ky(p1*0+m1jA zEo^44->2XL7RSpFC;lQQ$UMWjUdfBlDG^TxOIf>GsYAPNvzC(F0MTUh?5+x)!`<)R z#g%}&&!K`S@xcVw4)Ll{BvvF5bUpIj9qv_&>)+vIDgmju zFvuScYpA~*JerF!N1>)gS{Ovq1*H_XqKl*DuRTicGRICZCvj#!@xHa#hk z=J%CY#R*RE5pwo~U%;kQyVK6W%C3X8D;_}4w=1HO7Q_K*b0$SyUbs}}2Q9%;=hs>h ztEHd&{11a?^w*^C)y;GwYFlhmo*B!*P5haCJ-7yI?=fU%_9@@8w4jRQAs$^sx-_Yj zTD2?84t8oN8xmGANg}Vs#4Kq6&SYbxb@p4rTvMPb4ihR*Ty)rLh(XS#>OuWB`Ur0~ zybB7IGlN>!!gcdtA(B#4HSQb+y0y8Y0QgrRpXTGY5{)IGPBS?NmOj#CJ$rzt*w$2T z1p0o7N8aDK)#){XzI?}wDo$Z9SRI1d*P7o9f4bOb9AfR`TClM#7I;lD7C=>0Hr=ekbY~=;wkm&clZOIt3zWipgwT z_E1wnt3lzTI?E{3`bkV=CO7H0Qaoy|J)?xe2(?kl>*lB`6=h(ogZOAtObR=# zRXN%L*US&W)B&g%i&y67T5mOc)y(c)tlq&-n|g$bxa($h$j!)px6K2fBQ)}#eV>4N z>%?KZn(cLJbk3-jhgCrUt@cDkYR)a5k9wUuk}V@I zr%*!Gr;vl>N@PpKmDEjuKuCtHtOJV;wI$*>Tbw5ApDec-pS~zj&3+j^mCH z5nt3Cis~2Ws~BpUySmE%QGR}KV{TVRcWFX z@Vs$5-mvU(Zeuxo%VP&=yX5$u){a>!qeBt%Vi4vturPpDICZIq^Wxpj}^j8@{fFcBc3wH8a$l%u z?g6SxZ<{!>MfRy34gHeqWJ}FT05*6U%kU#anpwh~V{ufxcy|{QjF^4F9Cr|P}i}J zPAd;_y_Y_)xIq)XfvM3hak)HhS8OsTnSF@sPrJCdx)m?!vz#>^a(B zrFv;(Y~@oEe!lm0fv2W-)z%B2XC>>*Y?}7&B{go&G9N79CiOxdISlXP`#^^+VyNOT zvC)5=Y=VFJ-F|W7U}i%Vcts!LXoRC%{3_K!V&71UU|hmh__^80S6IY$N1BrhuXy9S zx|?Uu507EOZg(Kzg94|tw{DqimiJ+&F^Vs6H>_3;C(tlSM8pps!b@cEV@K7)zz}0o zI$foP+oF1#{;1MZ<89G}twfF)$%vk(rrZ*F$K2f4GfQ;^&miAIq+h8z$QAM0I4qb0j3QctfAIfjp#*teTWQ@T|HNySb=0;v_HjoK22vui`vg-0|i3VA7| zbH%ldAx_7pk7^5kMAR9YI{L%rCYE-m@NE=F?aCSsIFVR!8mNstyegN|&MYy0tyl69 z*Bqju#u3Mf#QUXETchqUDLJr)YuGi|dXye{6y6nm^cbh15;_^62otU_7#ii2QcQFi zo!g4|5h%PE(Y^XZR6`tFYYV}1*?#Au5pTY{*p22g8aSSyhcU%AmULz;EHuq;D$2Je z6}WUbfpsfTt}>HruBJ=)3wq`|Jf5{`?nudbvd1ekD_k1$K@YqhF`5{ZBFXTzsd~YV z%^wHqOpr`s`c|shCx&w+cGF{L+ty&wM$}H$ zZbC3QiLU9%x53_74Hxh)ReI@Hv?uP;YRgsJ6zY2pjvk$Tle=V1@+xu$H0Etl!7u{7 z#Vc|(>dH1rn-nLi3B{fYxFINOrl?A2N`K&$TOz?5#;53Vw;Jp`Ro*|^CXXeEU~C3R8yq4ELOe?>3WsdY=!NW-9pNf z!?EE}U7x<9&E8)8=;u7HX6lU4Ib73iDExw1E34i=znpZ7q&PgDJ?>uDDMP-@Vs#ah z6)Xr>0c0l2d!&f)t-dbF5BU5FKrnWJ`P%qT^65G~ED#G|}2L!V3IydCD$-^x@E9|Lmd} z_w%Xv^+pq$lx7O)i@?80jy4L$1i37jt`IY`@I=V#vO3Gl^pw&?+sq>xt+`F3jVX@h zDS;X)+<^&3?3vzW*PuxsPn{MWaJ4crV$jLdP|!W%tEGb)TvZngfY>>3?8;KllDb0$ zK;j7`W))N9rpxr@Qb(9i0LF^G22pLZdN*?P1_f-SkD8OCibGmAt~14}qvrIH@(o`a z{m#YDmYOc&$biliiM+&wWdU3~sZ*c8n`Q~#o_0eG$;VO=Nf%EoSOY(*Jr$cZga^sa zI;ywLjtQ$W7gfBOs5$V#?w@lQu+LTDD5|gA0m-baOe6Sj2230E`lfdwg#K z2Y~sFZgvl`zR!FU9;XrP?U!uXEH&Z#9R3wsB+0t5oqbR+wh$rvk>}|+*ee+<|L0Ii z%5g(bP+q;p-BWf9!jr{Qoi1GuSFH}h2dDxcmogm>(X7 zb3k2A2rrfwqV*BFZrzqoW$tUh@Z|w}GZUtX<&kV|F%}=3?!Q=C^WfV~dkd`He`Slg zU^1&VMWBUqeP#!Ggz333)Z1fg3sQYs@AW05y@LxsTQ;u0=vyVp7bl(VJ)yDp(#Hn?{WDLUTfkUA4$lCthRMR2vE2r^-k ztJb-NLmMR;hJ5o?*5l>-oNwal8TDHWlIrUc+bG>bAIsFB4yT^a6~5$AdOR3WSrB~6 zmC@GRuE2hLL}X$+a#I}ofXS=sd5Nemd^OZ(QF`IRM`V}JF-_Iiz2`$_)4}>C;^&KU zJ3sun!poM)NkZC#^6gc+0xoZh%ct}FJ1r#31M9tgVY6DLjXO@O0k*SV9{5n@4b`H0 zW}~1fLyl81*AF7=54?(xePfCY!I;d22-C5J7jsJM%R?KGDYYizNClm3`Zxv$5+n7V z;4&*LUq3;R9hb^Kz7@ul*WZ*GsH1`{w6&|Z!MV(i(!(=oIG2TZO`%83w!Uoln(_-UFB^PN{X(GcTGewqpMh}rE7-weeWyiV%Gcpe< z)LVSCIo``P1A0UMA%uPfcQN%CE4{Tn3cCwCmpKOC7XKyXTcncCQRyNJ7@u-KW7wxX zwQJ3(zFh~`8#>EDGuE@6LY)X1cg>M?zMeGx-D6v4xraf0ikP(4teE1xGv;6}Z9y-E z%E>|l4fVV$bzB2~ytcK2?nJy9ORvwYNGm%U)Yj-d5m(~kYd_!#g1ZA{Yxwf^e67!C z)!vThp4@tbX*2gyezc7Kpde%UPIvH?KJqdQmu;+mrC}10fmxgPyYxQ_Ei^nd3^Z3- z--~||My*CXT>t2%gQHtWe=aBE29?fPbG0eY?+($xQ3y4aIc`&5l=)|7c?xiEuf#YQy|2g~LD*0cg^{Sw_|38xn>Z#~3JJSX8|TGQJ`>|*T9`HPp) zdqixhlT|FyvwXWD1Q+d!^6aXD3DYYMB}XhdAuo;Il1S^pS9|3TPakS7|&DvD7gdL%u z6}FVfTh7rF)5I(T3YhcLXRm%DT9OMi2A;r^YP6NO-eR}RchyYiam;O);}QjZ1NTuM zs|Ig|1h0UEzRqO3alepkMZ9fwj`a9eBa~`aDm!=5ev&NC&G%6j$rfKa6cExM&|xH= z!jA;fgZ8Uj4eZ1!iTLRek7V)WlQ(C&gdfk$v8<)V=!Ak*>Xj-C$38eKwS^JgDCrz)089OPqD9Nfbz-h^3?y^rvQrv;G22?wvw%N%YhhxnJ z`=lm8BU?^=WA5gC98ENyK9(6JtQ{h|r1Hg3#;hU+EqcoPHv`IMucD*WoRzWEfTPpg z8MJOQvPx{En$cnejd#Vic%>fMj&vn&fxhv*n=ha_k|Xm z*FiiQ6Icu4;onN|q~K6Fs0h@wR&}=Lk3Abz z9aZs25ooEpS^DE{k=xHZFv}U5-HBJ(^jT`fs{x2Hb8ru9P%Q(cWpO!ON-(590jOO} z>6ySFw*}eK(i*eOb2VlM;^NXB2a>P9!M??uS9s4=kMrJ?hDm0J{+Kkmc^`CZ_^tfG zjs>S3ySzGGTrXYzP^8t*f0ks={OoFXf|2b;oR$>DSW65azRPAzw;`d8unB>Cq;?&2 zhWye{!#)>fp1Iu-$5d}lHW#jbj36##fsfjmF70$987JP@$v3B3G=~?U= zBb)L{=}4M;*e-Xyr53e)oAx16g4`;;D-ZA^+`TeDU2S5HW2o7LKis8nH1Fpx;w{ma zpC{XI>6&0I)f)k8v^dM-$;E-sahv|+Z)QF!2H=kDp+Y760A$q~>nu%=q?)ve`YYT@ zGD*@lg+k>NgJ-=??LRieXSS#9;D(yP@@M4)A>zJQ_rq#7(JI1^e3w`E9ax^S9rogA zvw9R5X33r~d6gD1#1+`dCx&G*%}IHg=Q$wa-vo;6*gG3rA?94C%Bt8fPTs`FrF1#z zlEE1s zTf7W5uq0Q;rT{ap|40gRVYWpIKw7@BLs2~C{V2LRi%*OO1;lCt=weYND^n4r-NKX- z$qE8}{K3g%94zvP^1Eth-=>$8d(Y)JS3lD(t&A-Z3pHFmiXWX+e|lb7q#iimKLl5? zE$L>E%8?alu`GXJ;gxe`h7Gx)%G7VAYir8zu0i9-z^pK^&Biy7Fw|`^z!Xpy-q+=) zCyq3=GUukD;WsTlG0YWXO9F8hag;BAbZXOBwNO|$L#GjCTa`Eox>etg3j#y$K&HDs z2ZN(c6n9z1Sw|8~MoOkgRuZ=_hn{_jLeLnEd&G)Rav*)|X(VW8FE7jJrzfX43o>JG z3X&MHSL{8+5-=z$G{)Cwsixuq&t@EK1M?$>y{c?y86hS-jX~>Hu@|m8?J*-8<*S?p zGh?Dy^;6eVbsuFfUrc&nFjYc!<8W^U&In>eJVpriBEMe9TG(2sXDYvd5YWdm8#(1> zP)cKFa_+CVXNltn3wX}LD_tk@>5L<;II>`Q`O76;Clfv&_(X`}b1pase@>(8w`dy$ z^oY-^M?aE{nbiQV za$(w9mZUac`V=dOT`>erACu0MFTY}E-xY|d7T`iE;@l$NY-Hwl{rtMnvM}jBOqVFrL_Y!##_>q@Kj;`{j6digZL|@| zy(RH{9!oFXHSC{6n{FSjzE>tZC=V0_aO+B$DYZq+xpzrNDvnx=*!9k4<(CcRxX5z5oUF8|l`|pgilQAD zgP_wN>d|7Re1~00W<(PS-^Y@t8sD?^1|3`9B8e|K!pbscb)c;&G!z^)v|3^;H;Opp z@miOE~cBDlsVkIvWTE{q>-2_f8Sx&8wec!0 zYw|3^@;o{_*ufEzx5oZntU%Fq3tD0nk3OT{qmo%#`(9KG}uh*fS@fR&iE*|H!el1-_cIa$rWVU zUSUmi^+tt;R69$UFM`h4N~2sdLTE=K9g&eQP2%b|^WNPl6Ccm(8k*#n<4|Lk9U@W$ ziSH2P8L$ZJz|w`Np~?KsK#T2qZ9t<`N6XSdEmZv&lBvF zwPZkPJ`;b6ZJAuXgh;-m?VT%NSJI(n6$;7ru?LB_DlKNKJ(Os!wp}s+GnU!Q1npXf z#yo=MKMKUb$r4pKY*I+2GKmo}2}*?K?RnPjn$9H`1ND{U0ccr43Gif{kom^$FafdV z{kUaF*JsLM@B zcKxiTxY}Bq5a81je0mwqk{uTDfa!~$Y5>%kMUd6qGXaqoAL87=&WbDNb2;dMPSz5o zpv;}K_?|5{uYeFIzhx-$iootwJm_YsHXM_JAvChPgqgT+a^cn{ty4s82Yt<#oLV~W zBpBHvk4gd`X&gP3n%Pvy65|YEh2LKG~?~+hbviu zdj|HY>Z<3Of!955% ziS$Y4diMry@7`-;yqWU8jhlg1=Vaz!-JMm~mDk^3Z&N5fiC~{W6cpct%|&0bV^ObK zlOKrFTzs65Pd<;C&hYQVzDwY&i&Xt_^)MRq@a;)5W|oTZnw63}Ve_E|&xm9-#q>aY zyVUndoyUPqB8^SG(?c0gOO>V?N{C=ogOc^W`iFVW`i$8H1wjeqn#;)5yZHPLCmCg7 z39n>;NCFe;b#aS-x;&!JQd&Gtk7IA&mTx~GA&%SAQ?754jN3h+Gx^Ve(RJFwOF6pa zoGoJ6OIcU^i(5X;U(zmt~V z9)gmN!kBnowB_$zIy`FNP3N2-96Mdf!&V2!80MSTWI$nUVWVnfo0PEksL;X|h=pXA zghN6ynCJYW8hTNXPD0KuOJml%+=yDyzLRtu2mAhmS>wB3Sxh7+ORs7RlnT;?>2Hav zST%4Bs^iBX70}EsANgH_)cjczB(U%@2^WA)LWdlM;Egyr4na}|?JU5s8Z%u66?DrZ zk=+3Cc@24iX`rbArhJvYsl;fO)~jGCDShvusYRAs#t-3z6}sRs6JfXoV%;4x@_E`p zy32{zpXWSdR*dTnu3QQCfZp}kt2&f4{0TB+dV+;a&CC4;wO^*hw3KKTa%LprUOU~l zGtZk=IHP1@oT`eM_?9{PuRe1M$Q zLo}z+0GV~bDa?0eI%pFc$0A2D4&Y&`RrB(?zV`$1=rEexB}E2wXj9bA_llR|XWJaC zoJ`pSp|bL=hsHf_DfzWcZFg$&y6e*gapIKXOT8I$9(9g<6L{x9{8cP*twH`uP<`h~ zv~_Hz6KA_~(@J?hld7-C7}+Gvo{AK&Jy$J$U;_@3o3v+_#X(ze-LDP0hL+^o}T z2j1z63`)D*fK5|Sb=6&&b6R0t-OsVHM>|PC)Z$m0*a1A1@klLKSDj5?)E$dMS5AK? z8{RB<#K-wv?%Y0E6~Og_mdw#ay#>;t>%w(jzxdp~Eb?VYCONCbU1?Cif12VfTfWJD z^Gg=k`05iN>t zmfo!;Ickpd-BLh;4<@x{|+(>Y0GIifv3(U06&W_E_jBc)Jcvp-}-j&CI zEJ$wy^3GyY^+jQnH{WsK%%#`*O1nbsIqo~>a;wbZ_YX%jN~@jhH!OTMdDB8J7oYOq zdDO+``W&3)G?QTA4Dq;Z#%mR&)??-Y!XTXt-r?*;iHXNW9AftN7CZAibMo??W?2tO zYf9?d7q%CabCbUj3`=_%KcA2sHM9FCvZ*x^t&htTUqCK zl%g*Q<6yZVgA96#?O-xV5FFys^}Yn!b5%g*8|CQFj6cn)vcPUBo-Q;F5<2JGgo>LT z#R`R+g(a31HcQt|RC)~ts-inEK1^%JWvwC##J~V>uxD!qi$4n~qrdF9$g;+DhoDi8_y(uot|Yjbc4x6> znDEf}uFL!0B*#oQf8U;~>e(*ttfC}^W4!-@QpRpfWR+#+LldDb@pk348MCbAves!b z{@Ohc?^piYW4kAx#~$wNPkz4<(A_Q>ss8P?^x)eNVz$BOHO+^Y-=i_;&r!);TQ~*c z>0Fh#jA7Z*jiHzwgPe}lfTb4BXOWhfuBei0)}f)IdK+x{p)T?ZcG&LMWz{z# z_A#>=oaRY$UAEJ!vaojt8NoaW6$#F34T?YDZ8i(V4q)?%Z98#r#EvLlQ-Jnn~w{u+gz1^ z-$T_Mon^Gs7)_YZT+ht1qkfESC|WriPQSt=_vG%{7e{~BJKVZkGc{xIZs8=*c=u!! zTs9@yzLY8Ug0L1AQIYND2G>4ZU#P$H6!uip?(K*D?!vTZcdgBfvP1b|lS`%KpNb8l z>9fkfFtXZ@N`fwq0m=sUOW_n1{cGZI3fr*&_-L-H~mGm=J8hf?*Etu|^ypGm zD&ptHjk!TmRM*7Q=eNpoYmTnyW7^z!6SqEp2nM+OU{_P7i3a&=w$$|%aB1l1!Fk7_ z*>QL6c0f`w9cN*WJ{#IuVnG^sP^9uwZu@f8r0Iboe7>*$<-p6f$yCDGla@hki`RL! zAj0v&R~XfXFIiyZ>|GVR$FroB3}6YK^DbA#rlo*+^cvi@QX8-0vH(InmX~nlvm1C> zXev;{vv#-e`>Ez#)515>J)45`ZSG(L8x_`6+eKD6Y90Abmp;JT74Z${ixacGWzjG< z%VUj-_M4*cvUcj=ND2JU*S+tecyD_J{U`^2i+I*hM*RG7?dY<>&Fz8c-CMPhJg>52 zZe;x8y)7lUcJM=L;`saaYS-G*G2C;nR}O|O;S4n14&9OO+Kbgs!d9gyL@MPm=*NQT zRv>-eV;Y?CI~1Gg_z}ytfl0;ljxBC#di+TJtD%u+3A3AQX9veifx~~7S5(3+h7Cl; zt)7_|(I;7$;g56S1C%tN!Sp`weZ-eF|2`djqa2%(JN!i3CDKD5iss*bKj9tl{r=46 z9899-G8*Xa!**IxNeu&b!7~`J)!TaFv;P=ND>}!Ot%DLOumr=4y zGN(4rHKZT>lD@aJd2s&puG-pEpmN3Hz>BJ>$G*48Y}WVF&W~S~V_!u^pAY@;H9?&@ zNx;PT>x0&UIeQ7_T>+_iDe1*qS%|n&J?!v8V;Zir()zzQP3y%xOOh#PH^Nzi231Eg& zG?6ZZ(lvNo#q?R^NF+lJd{dyo5jwWPT85dcC=Bl*${G6?8QwBf-;vks2X_rnYJ_fw zz!YG{S2OX6o{15IY1$n-?5|-VUq9Wyar*7mv+s*wIpR{<7Z>#03Sn&3-oF$V<0HkT zVH)FxB`zglfBy3jefEAV{=tw-R8g5P8ZT8b>;>JWs2%wT7+y=;f8E z$Xr_EE}+Lu0$W0|1|+aYIr2{WfRm$IU(4zH>@$Uv&Vf7n2>F!$^!fMranCe#H~%u) z*nzS z4+`n(D0pV0e%z|n|6w+@4cYIX>g~m|y@Kc+@C)=AX}eRcSa$g+yW!FEg$}}I+17Hq z)JBB&4H5NJ*wsZ`W{H!Sn=3QE#OHC!vc%$7Nv}3>=&-xb)bsy7N^=g z_!+Sp>aIVxn2$ArdQye1ImQF@iy1QGpyM*vQ~QrDy6+#KJ$UBOd-!9>>T9%2r1;T~ zXw7UT&bwCM)CNAc`C%^3KQ!r08ArbQt0s7DYJ1}NBI1E8@jNO@272{v=!52~yEl8G zdr@no&<2Ku)v0R5UF`PRcc8V0^v&D;INHwDuInTXtO;p71_&MsYPORE++=!v{E zw@b=|sTu*_q+e#8d@u{cwwt=NBKEQ>JWy*#kuFTTYv)gS?p0<*k?CEqZnl$6NY*ws znebPnki+(8M@2h2lQ)=ZgPiY$H-G-Y-zi0kbdv45*Fflc zXUOR3%SyYp`=)o9-F>FTire7D3I<4kvALG72?uet+pfRHxJ|;ysRe_2&D+P{;AR{d zbN@C~I8D~G-vH5N0ufG^rCZiTebmH#)Vwp{zLCRNM_Ytb%8ERfg17m4PESb`Mr`Ob z2}n_NO3sD2Aw!j=27bJ9FkUO;{5TgeSiSgJyK^I03RmSL0-^R{FW$AsH%WMM&(}LQ zG52u!#@xMA^Y97rXG;sGYHry4-%R%m+o>X{G_$J;U7kYxK*HPdpl$_UGc< z-+ncuufAKXK3?sGyL=rct})Cka`-Re>km5=46pxHpgW+=f{TX{ns!`M63PWg8mk1V33ob#8(T3`<4Q!e*4F|V_-AugESuvA|3%e%Mm3eS@59WD&Y*xmh@k{wNC-s& zc|eMVG7>^>L4`yy41plMi3kYzsFV~!F9HHXs45}}s8J&*kkE|Mq=^VY5Ck;zP=x=P z-}8QX*E%0g);eovpWW{3zOHNUlbH;;fXzcAI&RvS+;qNTronz#R=@}zEE+d|R#5!) zef5nQ6q?qX(>Jw{y|ufSQ9@k58a3h*8i_s-_pa~}aiyz#7LK#_M0G&gkePKfu3U$&N{q}*1WxS!fT+?UU* zY{gApe|;OQZ2vj6Q6)KV>hC`ZC=;TQZ=C|nnR(?O{gQn7I|_HgzbFp>#~?TA`3NoN zseqR;NeOG(MAIRej^TgZ1jD((2!{fv33tRlarWJg0ljL2~U) zN<(^GRE2Wf^L5f=1MB`_oj&ahNA<4y1NTYP`3HtiK3q7Vcm6&ceC7%V!WtF}=X4#! zopGjo?CLwVm#X`GqYD?-Q*t0`Iciy1d_E-Mhx}-dHD@b)Wesf|yxG)GtB*$qrTp0x zu4ZlJ&FXUoW3f2>yu9;^N!1RA^51q>eDVEcvbI_uTHJF+!UPedm1|P(RlK=-%tt2p z3@CQ!OUNyn{i7=-?sHq;vBvDRZI$az(c#;kIn2MVb}RoJf3EgW^FImAZVtA0rXTrT zC=wrA&5Nw?!!ukDDu$jl#D7z8fB3cUU0D9F3s?WR%ZY=WFM;JcEmvub&V!?dP0ymA z<}Rg)H-_Bq^!eva&6Q+78im6=J=QdzVSh0;!=-QKr%v0|sFlvDgV(}=jqfX8KfHT2 zQ6nFGC+A_Qm-#W}ZMy$hbP4HM>910=;ctAeiFc=22MD#IyW7ogI46MEf3>bUJ?Vlg z$ZCE2x>5BC!DN-#H_XqLUwCX>l~Z=RAaA|(%CGs}c5=9S=E{s8&FOrn6VrP5cyxGw z(1&Nm^Y3lMuazd&A9)u)66H`S7`@&#WA^|7kNzcy4-P7^imiK8-CyIBbd7z|SN$mS zV_DrjKk5toJLRYqTRblFD)IKA`;r3j=pHiQd;aJSmue`2|DAjFXxpXIoGMUu(VCfy z{D{@M#Y)V6{HWs4wG{O_Z)(1>`MjAPKK7mzq2A?OSJaov&z^-{wM8r$U@4ED<@=Zf4ti|Y!@zp8s%oqsAj}(np`8ZE0YZ&x1dm*0#+tC{*BX!q)w+4_~J}0bs1M zI-n!z<%cqJL3dBYnm>Q1b^Aqh__bx{-TI9BnEzZ1e#BrA&V*bgb0rHy?)bd8E$boi zK3LDTy{1OO$6eyogYKw@rjk*mn8B9()ylyx$?d7DQ(Eam>h_?bqI)Ix^#h*$^1;|| z2=qEi_uR8|(fSWGZ~k+^n4OCvs*@xLjgwO99{S1%4Wa$%rgNINGAi#}Q!?QBbZix2 z`_6E{yE^?c-k9_5K;WC|mkKJ0bM`C4dVkG7RwL=^pEI_7t>Ag@gyyeou2To5-lvHyrY%A5g8~Cg*@EQcIl(rdlZxT_C8r7QSX^|-Rlh1rK z%U(W-y}H3KGj72i-}ryH95xg`S*CneH_( zUHJ2B{+STp`b*+hgM&(=2#FNWH@yw*YaKe<5YwKxBjFy83JR`sV(%}g36>L1kFLBN zUU^cIo1D*j_4n0@@lP^A_q-o#!*#&A#+EWC)PsF$9oL2k4r?O?&H>RQ?cbn=zhZ*J z^?OhJP5es%(BPR*f0wLoS5Oucxwb3by2WdgoM}WKGpz9)nf(3D>*8N!#KXaDe-p*p z)Y^MBCA)_tc_(-G#UetR-7L^kK@xU&v!gTf9nY5zzZ;xddp zvnk0w_gKF)>yNog&fvVxZ^4*)yE8{^kcFdf?eFSI=oFsSyhD@}uefE5_|M5-*0th)9~nzJ(o}`) zOkO@BebJ^<`g-e=32@O;@3;4j^~XK<1z{#GrEgk?$j@14JzIc1)W>DSe*N{A1Hb-q z@c*`8|GUc?*pw~v8|Y89|LC7RAO|z}>x88%7>?c_6B7qEVgGXQ*PT0sqocmnr}WQu zrV2K52BDTDa@r-Ou?y_9sBW6Z)Ka zq9|Rfs1w%?m3DVic3@B1B5S3advrlJ!h(UDZE0 z*2+%5+^YVFp}K3Aew~dQ#koVnc+@JP%g14GCqO*wy4H4`8n5G61Pr_T8vb=0PBGO3>b?!I-cO2F-8)mL*);5EA(01{CzycSkmso zw9An1sA`1bOLmELV|0Jqt4pCUv#K3Kd$Z`Wc88@5V`DoO9G;TIaf7ILG8($SCowTm z+c558G5jlWMZaS9*Hv{pnRrdvd^{;DDwNq?Lo+!{O2he9__fBxqom8DZN`XJuvBme z`Zn0WadiRe(>AdNfb*b6u@KI7pF}(vvLy2cTlvC5&gc$H=m+glH{I*Fl{TeQt zPtV8KD95wMeqM~dTM!+628JgI{{71sN1vW}L@Jr-$m&6|dX_zY@3M_Ffs${ywepx& z7sNBGFx5^F{loA9*2NGoFZ!$`VR}I_gi?^7#5S5_@kWV6UpkxIWk8ib-5RCo z;L^(+*mlGjm+(S&JCEC~^o9ZsLaLy1xj)BZq(Mm8{I8-`r-EF-7jJf%y zS(;(4-j3Jn?p_>oV5oOS20=8rL@I)3-xZM6Z``ML11lRdrblao(e?T^9XmE3uC^f3 zJYg=4Bz>9)B&%!K^@x=L{nA3=bw1Drh`adzuDuXqmh@8b2NERlu{O4BXuOp>opT*U2wll=ME&e*+gI|tM>kt1>uss z!p8c(*k#m(&y@0;l82N^cMSqSgP=%bcX^v}lS2ls#=Q*23p;Dx%Uu60%*D0fd0gT1 zK~fSdg{sBiJT=BlWv|!3E@#hov|%Dyd~N|(*2u#BWm@ex>bN|~Z==WESEaZE8L30ksBdZ0W=Lesj0-?JddGmkFQ$7x#0{gANkrBNM9$6Z=tM(YDes$4Ey>8DKA%=i>?l?7nXWWXI)S_89%lj}n9*YvS(n*$rlx9p%(YkF9(N?opku=%N(%Zdh<5M++Mhdv z{kj$3q4dR_B$`*C6cP`D1IzR`Rf2}Q)B)S4nw+~mcxt}D zWmGsELGZ)JaGqq489J{>qPlO+BWy1yk}>1J|W8!t{z#BAK1_%bc>W6`dVWK`tj z1RPz8a1gX4E&paqrVnR{%h50zm%ruR{J88rmwuEI4Ud-LcuX^36mWvo3!3bGbEg@f z33;C=_2cMJ%-T!%am1*Pa^p@mMkl2MXo@;x?l}7*GEX>iNdpACQJnzaj=$1#jV=@}2*7Ulp$(iv(9wyzs zszLp2o^{M{233bf?oGiph)~f+M7sIIa!DrH@7)X}fMH39o8)&`m0ir9H~(<5GVomv z1lnvHpWW_5Ra;W4n091Dn7ip1hG^BfmL|vtsLB*9n}girBGxBkGL)uC0u0ot%9~kz z>cmxWA)EF+0m6T4^JHa|#2RIfhnhh7ty!FjFq7g`cm(hpQ%o~~(z{DZ;P+1vc2Au~ z8bl^t$okI=3CV(mN~YB-wT!`nFIi~okH@JxDjlL1tmKhpcTDL$(qN@F1kahk6BS87 z&(Uc~eA9`bBH?IE{h608_jw)uDRKz)ArD4kyMqYXqE}IAGVOpGbO`~+za3c52s7At zMWpB)&#-A6C<`1Xd|Cb>?(ayO#$1VbY4WDt;Lo{6w+)zq*sb-T%Am4LZLf$e7V=+>o z3n?!}{`+EnYSNz@dmCD^W{wVbL)6`oF1+W%in3GjbHr{GKi2aKS1m)+JhkM>Ic{mmNQw~$mo+mq+{n#E`lid$9x zm_=K13n<>gm<%Q<4o8HbBr^_D-#4xYB};)aLJdca0{^HX8o_Wc;Q~Tgo(!faxnOsb z=bPYVXz``lF-9~=krJ2}{E=dT?dSouS>iEZ*DUM)0V6)eDk&*yWmCqz7O%_4tZRX0 zZnoZKqUI@jh90}}Z?;89^v#R|NGl)MeV0KW%u(tT=IA7eiV^1iZYM{X`xL|47t@N{ zBggsd9TwJMt$;F30SA1ux<@|KTosgnd`whGNqLlunDh*83bPg!e>hd#15QS?Vl`^# z2Gdo{qxQuvec26eMh>XnztJ79D%=i|NGip8Lgd<(y;9f&%~YBo%gR+W(!eAMxGBIW z9DP+>*BD-Xxn$M=b%I_qkfrw3ZahJLwmu4bzyKeEW9IEjZ#bMu68515%y`!o(c^>D z^^#lh&2Au&A{tn54%<#7w0(#2+X~r^J{u_|Mo;0pRA0j?n1%CuRzh`1c83){cALD1 z)krP*rC$2I8bm`)RT`z$A{fBMT2Dv#%r-6@5@1#x2UwaM|%D5SnT@ZwJsmb08=zq4?=F3!pKuQlS2?xk#N2~ zC57!uui%RysJ3`Qbg>IYkSMYdr@pPe#2X6EG5=^jPOlpaAsqr)Iq8SzQp`*1=qr#7 zYlGwdJM_bL0_qg%BCTm(3}W7=8YDs{q>;NpKLl{qX0Xwu^=C*~bq`95!Bn?^wzhqZ zwfd={ZyT2MN=V2$fOJ~7w6r8wq^D|SV5QIRRIlBTg;?QokRM9&21@%DI@9ax$U)yU zRcn*dv*ZIJhrNpC5`|;{!IDL2^H`&I2+=>HcyCh{K>~=VrBL_;lGTw+?`ZVzLs%ld z!8Lzq0l+{dUrDQ4Jq}?c_uU!y`Pa2?b}9{b$ypH9ns07Yx$*V$fpz`4QA4>8uBL1r z6UId%S)v5Dj(0vZ0sHgeugdyUEAjFLK~Ca9(r0Mu-C!FKRqLUWF_ZhDfM$}f(V>AK zDSQdxY9{sQ77(G_>?zr-O;z0GJeuZ-N{92Ij<=sXYX=6R16hk(sgLhUNDk67oS^o` zu+x_P%zz4_F(Q|pV7Y6vSgv-}Q>)I_tpdOnup}zPzq}*I6QY7@6*4j5VYJE2pI**d zuEwhVBf(}yBfZ(i@Id1V;0nMH){W)l&_4U6~4X?$-l~lTJZk0OGfe#icHBv$I(5pY2dIcvT2ljBN;H|}hq6S$!$ru!Mj7`$knydXd-cY zFrJU9bQ@<`+Pv;NZ!+P^);niiww1#QoL>7@^XP{(y(ngoD*>9qM6?)2G<_W0F6dbP zt{MP7xq{X?N^K?4IQACV87|e7I3Kki*Dq0s)OTeI@3tD9h_KVhtGDGGD=v^?HR>J} zWyTE9T`uf-s(7%8F`V9BPKLxA@mzN!pRJpy*2^4+9C;|1w|J*}$u2sSqpM@y*A(a1 zXGM~V4v5vU_yG=bS<}SsO9kil>DGxg@NRn#Yba;&l1tL z4s}qZ0Kj+iVf*j6K_SYxSO*ZJ^pB96Kb=^55T{wQOe)SOLhK-XnN@j{462gFgyvvt zCvS#v??6;ns{ytb6Jp^LR#Zr~bPQef>F zWl+4YugM@m&IEk-llP~JuhZxIm%i!oEk3q3Hf3wj%`R#h4#F_1zxwFn(KsAI`_Wj& zJpbhR#PU5I3F#zEVYzq=@n)B$iK>3ghYkIk$_awR=9|er0mC}>ruqb?>zZdpv>MXW2G?d|(w6j{Xw9lVaoY|!#+;DjKr)0K2H zLcRy0@U)SlC7v?6h=u5q@+gn$B|XceuDe?0L(CPUZ7 z<#?>1l|Bz2>_-+b9HJ6GhPpCT>*bHOI{G_EvU=o9tag~@0u%i6iXU&|it5tq$ekau zs`XqXRI$2zeLAsc>X*zb?PWooB4&)cQagEH>^RIgNY?Aa@9H<3cxTDE=geY0muLIu z*I_rER<3+$PX=pM1Zvq8D^yUd9;im9noxqYo(Da@65%t2k)11eWHGwE@$--n&)P!j zN5)!RD7L2C(#kESnFa^w&Qg+I{0benpVj*M-ZLbCh48DdFdp6DR_p2qs0Ls3ceSK` zg}qF@<95ksu}=T68P?Oa)8>_P#V<5z8U&RrBIqcg74>-JoxPJA(aC-_F4v}1Re9a5 zhE6V#!NFEuh}2xQZ1sjr>JMo0iSRPbBxJLy>kb92c<@t{z^GMNl4<>brLTjMPn{g| zNNFIe<=V+v&exyk*Nt^+7vq~4$#MZ3@1JT7X?;kUkBdSr)`el~W2+REMJ?%3k}KEkrq)uU{wT%U@iO{U!W zkn!otq&#&uH5LA~5AHJgiSRD(>}kI*rwTOA+PYh{fO?En&!42xcmqV^Iu8U@*&YNC zkU)OdRCfc&uTuJ{I^q$H-g9AWI_UDNGhQJzPlkz(<9JeWDvS${0H8m6BEE*+e&)1Y z^JcoO^QzxoyMCrk#dr93czEHdC4`P)LW?u;ZsG5Cn|fXIxo5@a2InkW1u5nbV_Z@a z5`TqYZ2k#sC(EA|0>d#Fy%(rsG#-H)qt}kmYeS#~r3a-BUvhef#(?8YpbcE(P^9l= zP)^oHv9aBusF^2(ui`oB!<$HdXYz*ic>`bH!jpRrMsCk;FVTt~>v(h7N#c+c z7-`BoAEvP{ma;YKH+#v%;xyrC3P&buDK5fi9W`pu!_CJNV}c6a$vv5|lv(~rR> zE^+_!#pA9riQde@MUvFf6r^d(X`h=bNc1v#a5})E+se)=!VLPn#+PmL`5=FpX)I)t z)_~BnFP4#{ZhJW`G^w43n?RxNp!RwQw$kffFW2Wdh6bo?M61fKM`}@HZ(;0WIeER6 z{nJJ?EWVSFWkn%-e%3%Owrl~+nXN@n8WUn6X(miOpUzejC(iQ2maBNuN_S)l9{DY^ zk7p3QKtv`N!pob&YE-KxD@=&wQQ{*lt_V%JmFN7UEZ^TBch}Yx?^&4?VLCX7C(56 z@j9$!OAPo1Xj1sxz^kq$hBAxDG$K>v-o{`t;q^zmS)8yo92%Jn!6!NZV{e*7J33Kg zoqE5$=)R3)c?6O7#f(rKcG|h--EM8Y$Ge*qKYPg=A#ljWrnwK%eFuli6UvFtJt#VQNH^nEOK{9PW6(gA>(sqJOtPjLZ6~Mzl{)qLw z?p;iu1tt@Ky~Z{3yH40$zrt&}VVQS?=!1gR#??lKwK29=>K*QYgg?={2Wh%l9}K@L z`gjb+nSd4}j9ImgOmp{8B$He|+hY>Z7+$yx>yjnLyPJTnPht*%Jus5iZ>)0T!u|T$ z0mZIUSH_H+1cnCsOWp?d{FFBDCr~>r#>G3=yCV9DH(QekDBk-A36aj^1hmb#+a-I_ zVU2!Q^U)1{Qc~TB))9@irDCZHn&DbUwHbU#+7YXM2IMz{fl5^mc%yA9MxT^Wm^$VI z%8F0&-pn*cn+LlXz-%+5YV!+$xRKDfL^VY2=tx>Bu%BCNR6n7A&X;C0Z~nU4Rputb zHf47k`nhSLbv^i!xxv(F;#+^>X(cqd4@k7baX$b3hYBp;zm@m)VUCtm9ntzo6^xX^ z^dWdsJ|P5xk4k8Zjd9$tV;T6ZnVokypZjsu^ejyj*40Sj#C~ya%EcPfQ^##SSq{>4 zBOQU$>9KNHS!6=(1D}|zrU;m8#n&xW)hp%Rl1vVa-<6?N$6O|8@5qp8TQ|Op@NMju z3f@GfrEG=F#Jc&X*On|hzMTE3Zm1{jpWu!BoJX2bHK)iZ`n1W$haD2|c6&hWR%$mL z+Mo;W(KZvRC3;}}m87|gwDz>SZX>=YzX5w_c>R%@8{gdbB2^>Qq_}}; zsQ`FCZFXgS)@kL@nXHzS9@HHlqbL7)9uEv1zm!I0fYs}riM^bQZK}ijUQ?25zQ&hX zhXW`5rp`L(CUL4h-V)b44|(|kcss|uLL&5)2O z?X$BuZurwS%V!xMW7EAh!nA6jyrT&p&ANUs%+iFN%WAr2So@_JV* zKa_@is8kNC#j=XvwHl>CugP(~oDc(wzWA1%k=8)EA1u=NsYh}gGN)A?ACq`Mjlm`m z&Q-Xa-`ovN81@Vm@JVfWSCPV2@+iB;kx)5^!0q( zFzEB4L?|*gp-ywkLE1==UO|!a@8QRjjvE>AKF+8>EDYds-c7iIC#}D&A!}kC-Gt@h z{sk|EqrSeUNzxNA9M9Z^*7gA?Laon6tRG`wHjf^sWRTPZCqc@l4(k`qhHXt%akkFnU!>PQ*%3SLC=>4;e!O=Upg=4Yugn=rRi9*}7VL}tGUL~K3ZEauB#f-D+eFYapE(y?DGj8#FwN$K$DE4$(z;WsWHlznDFn+O@Ny zj>W~`%UVRw1nAaQ6~do&Xw`!}yj21n2Mi(2egH?~X6||)o%DeNS!$P#3Kpq0M$(H!1J8-bS!%@W;|4_P=+6ouK0@xk<_z{zrx`bWqnC< zy8g95`zEn%+RA1UBZfDks*co`kd_!{Vn~vfh>Z0_;ZJW_nJ=eehh(EP$pYIL#=#6Oins^v z((x=r{We9KTE;Qdo&5ctpM_%0^w{%t=3O@|)rBd@A^B$ox%%Qh@-+qXHx1hUJe$D%zUfn7Fb3c6bvZG z%INavua+QYTI|4JK+A_62g%!@GZcMtJeEk*K*c5=lAT;>5cOGtKwP@eL8S|QI=;67_h4n6T{DHsWT% zoA6AwX}Pdo7SCKx<#d6p65gyQVU=5AIqnJ#Y;%dUl;`FyBL8|>Mb(IGIn9GcCr=8@ z_r-=H5KA`zvL|t@<-yyd-Qq#_4RDDE^NLZgx5_2!u{b7EZ8-&=x)@a{@`2fvnkujJC&{RC6G%Y*d$kLvpO#h^wNZW(NAewKAjrI3F>t>}B<^6rl! z%r!oQfCQ#I+YOwDdni59$sPN$9DnyEm$D4d8Nl#Y@j3ttU#$;I{|KQGx3BJt=@|Y! zS-394F1k6LU~%8dtnI`4BMloVe1%l)mBAf=(eSKydAp@1jY=-2^~};BH6En=fZ^1D zCScw{oiO$X*q_t6NJDoYN;?K@ZU}&)F7M_3pJpe+Z$A9F*5V$-E3bZ;QEOYodfMo8 zUD;{r+>I)*U7|9~fZDcdj&1AV(q~A`IvI6V0~-uL+qCCj9ol&1@J^)R?yeqR4%%Sr zp{Q-s72C4MJDx-7P8bD?IMlLv&F)2wq95m$hcb73jbO>^vZ^28=iJZ1e?+1O(>q$> zlRt;^Ry;3F7SN$q4Z|1cFqK*cRoSWf?Z4B{d`7s^l7f=N`6j^tlqe3Sk*W~A9{UGz=6?A+clkmg{^UbeyxyxP1JBs8~B_GeJF#zK??4a@N!$92G3 z`WQ9oJL&Q+_N3ME(0}Ddj;Sj*^(#i0SZQVTQ|Rf79F2|tvo807?8d7=gyzF)##5G_ z^;Y|bp~xg7;|zjh$g@qUA)9e0j2lEogo;-!&&3inx!#;+K$pTdj{Fk^a1NgE#nAvB z`9)m9R&Pp1uAxznzrX|W##CQ?aC0iA*(Igy+1P~PZGvE% z^$pAeLBj|0D5@6b*5=}2=1iPT#b?1`{{4{ zz({^y43EU4{IYjF<33zQ`Q3A&hY^17+$uBb@@DNChUjQn7c15#9}h372a-gr8qt!! z>XIkrp`o@fc33OubmGRy2g87yX{lRg0{XLu$fgtXpSar}yl!uhtrB!y!df}+I~zVD z@>DKG(l^R#emM21;ynvx<$7XTOcRXWOp$N4Hmpkf0pi_Uz`htg+GAhrtjq>QPr|7Y z?eyBOe6Mda@W4yAO{89sF(B1FvU+P@uluZW@>d*Zv3O!nO!FZ&(e zPa1}2q2pKf>Izq@6YS<*dY!7{sO_v+OarNepvUA;=G0=*Vk8_U2VF9?yNdQD&xjsU z=LjiAxsK>*;IOJ1ss3GhC}#s z?v~z+Ug~KR$})j9>@a~?pvHS0O)Hdaw~(7%aafj)1oF8}4HH27>pA`@)k zGWK?hJ5`3#mAKPxcSE$oz=#YxIf%%jTfjFa<~5~^5(qVcwh#Vn(KVuAb^f~}d+_6B z7LI8S64p${S3u+RvE~&{GJW^R{-)z1a5^`3`4^cLw(JcGQmJsLOA4Mwg!hEmW%YUS{o(w|Cs9Si3y>8f* zg>TPuJ99=AqvOlreGj&M3==xm)dRhwUzsc>?y8#WAe#xDe> zuQ-D!|NGo<>3r;C?W`=2SFYT*-zTc?Gn5hYNDlT&bCkPJk#TuPiomiJ@#DSEWao@h z=)KDz6~!v)4m>;nF>!lA&WgGGUA-9lWmiHs#_d_vu?Jiz*v{q<6Ju{M--E@tV0)6m z!6b7N8Zzv5l%=m*M8y3#F#oKKC!!z&?+H>xbWAdsi*+pmPj~aEZ8%!>RlT#mz5V5& zz{E>AsFnWnCpL`C*q!A{jzvah;kZPT)c2MOw$_4+xi@$v-?wWVM&r-dUQAhw;#c=| zaOG^v0{+_Z{U_wR1Wh3)bNj33u(mL02cA&^JBEq2__S8N!Tn~};pQGqN4;}cb|<4_ zp9P$fX0F9$KlmWX99}sanw|cErko7bvVCD*efcUQz3-THG6Dve9&V|2xLkL=NzsR$ z;#k;2(-~zF9d#a_M7-a0gl`!*CH1Fm;@T&(k5NsZ_r(-IOZJDKbJ4O+jkO*!tTFpzo}~$%mG$%Wwqz6GPj~}qtOT)tIL`4>TRNunQZ2el8&MKpMg|KRf@ zZac06aoO8Myt-l!ulQseUt>X z*BUvS7}x(JqT+Z!whxgcNI~&VQPeUqwDB@Tmyn~jNdYRW3sq?HO-M<&vsmUkz}AFy z=_p05WjupB8HSql)qYoUi}R~%{!;lsU1Il1!g6Auv0WK4*vrYl!k$~%w^4f$du5E= zBnTn@LuVRW#krcdOYaITR;~8MdgS)S)LnM{Z(6_K9YFUN$>L(NAeO%W#Ho!4E=*K~Exh{u)Auay+Sfhbn_vIiT;>Rr^4q=`(q`?> zb^rsL8;jJW+&se5H8}16U~dcq%d)L>JKf>wU+1yDqgk$~ROCiM;H?m%&O2OBzlVpd z@(q8!WeR;S`pJBiBpNSAvwr zep{fu>$7s8N7SL@AB(;L!#CqL+fHfQy=bi6=9BCV&pvgS%9ntgjZW2no&2)@bMpWC z>umxiloK2$IrG>P(5<@&U8MOt;A!P@duiE)BG!-kYy69LmgLZl=4ul*d5Ish&j z`ada1AGT)%@S^|9MgP7mkfQwWf)M-x{={Ovch@ckMF+@Mu*V-O(f=~Z|4TgpcSvIl zfW#Rbl=SZ17I-(o=-uv*8JjNHZayk)&kfaKiZUt?e(omNO~pPGSmbh|T_mO-L$|Oi zc2iedK*GrLqXYdEIv;Fv^ag#5vWMBG5%jka4cjRXh$y% z>TKp#O_ATwIe>d;{Fkp4DNV(D-P$GRcm`7&!!)cBKsBNEt+yIRCxhDX=&fu4-~2`_ zt8;TY(H<}z5sYF802?KMt#oEdLt9rJI^x6L#P@QVoMe_;5Hlb-k^I+;ytIszp6*p! zLf|S>;;oQFn*kUD5la3|=IT=o(A-JLelQDFRVQv5&XTS zExt@-vgfcbCMbLBwJ>_~uz45K6t#wIp+s2+taTlqxjE<2h7ke%!v(TQlzb~y>+y;p z`GB(_SHd`NIV^cA7yCr|u~f$75R8xendw_Wa{U5yBb6HtZ0EpL1T^xW6yryjtS(Dd z)-ze_9??xSc$CAEV?}bs?Vzq7VtR$t6&@snu~hstyO@-jt(=WG)2$*yxgjz>C5d-V z=>Y>W_lQGX&6kYgh#f^@#>lXBzrMq$DMO^aE(|k-2l~hP_0y9`O+PD!%qYG0Z~{PG zoq&I-*Xh&jz57{<*P-n7nxlp^Cx4U1LIERAt+D=T6TH?M_KBf7&^6}PD;23Q;mhMx zRzqeU5!>n**q8{Nd?n~eO8#w~S)D>ZS)JGvhw~qxoPt<(MQJ~7d<;0)2#Aqsv?J~g zE8g&D&SeNeR#B?YH)>OQw3Y+G$Nw;*5sQ_d5kX^#Q{Tq;`Fh-aG3oxm05&bDp)vkd zCS5LObVL2_cN87VZZ@9ybGi0I{9(T92cf5m%rZFO2CtTJa)=Va9WJ|3Cy@=cXMb+xo+G-oioD_!R&(2Z?F&n;{g>YofIDRhD zs`EPblc-mScuwr>u|Ui5*3lxepTLQOweDwD^IaCLimOtS+nhr+DxbwdLCW@!61s=@ zzL*;h18}lgV2hi-NG$`xrIl}v`chUND345%NiM6(?)M*SFFUT2eVHQHj@SB*zHqlY zHR*Xpkd_qycxl`|;Q{A&KSNopz)EqWChHSNiZ@@0Tg7S@vd385{dE}XJsDQV8=$w)KgzPVC zCPl5t0*+b+R*!=mXSTe6X#Ja@J2bAZSwljMb1~3tBO??ohH?xKPZY4YJQph3CF$5& zmo*J;5Q*d@03BqctCW)e_@~Mf3H*sTO}%8}yJgm^Zk8rDK@y9slSOcfgsN4XPq!ck zl7oOyeg7W$An*8cIT-BP-;QxCEs17_K6$qVUolTLEF+Ghz9rr_xNxLUuJ7SdA7AW! zbH2%y=EK%|WI>{^&?kXDL!_!f!TymdhIueoH_gMaT}j3ZnPp|WHAB}d=87jsr3~Y9 zA=IiVY}Cx8X0+!1bJg5esu?;_fiF~Q77NhO+Vsnr8SVkgzL%k+n#HP840QWxbfGTB zddfB}k4WH`tbQG30az$&JdyOQCb%1&I9h}%qmHEfa*y!#Hlj0ZV ze3u0trl2*Eu6gB)Oiokg*F?S<%lGLH{2aoe!fB8ar#_eTh$!W~EyJK{=FOFc83tRP zcgokUOcY#v8fu-JV`P|PNx?*HbUyIynTv6BGXfbGM{;42P5&ZQ&F&ykk>;0Xy5@#) zfJ5VG&45vfj$ui6SEIWhZ9&{kc}ezNbs{A)qp?r-Eb~ezY%Zz(z%g@P7AAav49q8> z2x438sDJsC$Xf!Tt43JV{s9G@do8=`?)cP=1u}CDGnXIg(qgc=-ftt{L5Eu8Inbaxqp18Ydq*o%Lj}l%nWPElqBLdtQeBBV~pNQ7pINcp*_Y_O1Z5HiEO>DzZi6K_Vm#VB6*I* z)zGyjFMMVW_*FWc+!uqNkJsRzEF#n9A}{0ybZ;B!TaUd>kefnQ^$Jt0GMEb<>&jn5 z_Y+j^E*$FPzb zA%|!QQbm)pvUc!0cwMZ+VKWfj8;H+Wb02w=1S_9-+|-3+N}Xv{H?_5!1a->ADk9`A zy7Q}u9mw_xXOGsNx4xSGgE)fy6eiq7)Js#}g3+r#9|XgzPo|~OPbQ>mXD1VVz3~5! zrZHd7*_xn5RthM(aXYI4sI%j?Mv!DHWo)6hn_^pYqZRhF0&krrmCN&BTUL*e9Vi51JE@7BHR*UY-`kp)*COiXGmgOeWx0l`4 zvtk^g@8I{s^?KGWb4mX@2h%6d{>o6;{_p+f=LWw_ zUHE&jsEm0l%)(3SSaaZM)4x5qzu#Bn`aE9F`)|X@b|K&p-N6v_*1Rh1-&-u5*2+vk zEb!hr;KZ#hRaTYA{~4%pJ?u~RsK)sj?zS@ zLTIQXr5UAsODuIsjY}-M0?-lx5jVZ}{YH-fAUIt*@Xm9e^QE2h0iOa~D+Br}13Xf> ztFb2Z9Uf;sN~a7i+%^u(Fs}>?+#YFq^3YdeAPkVKvq+Pggy19u{W*%56z`u^+Ho}X*kZHHKr-E#ZYeuK&m`AE*tJ#k{Ie+ zF2(5$jJ%r!K>TnmX$EhCbDJ%YB}`5dG6n-6+|JpMpTQC?Ic>x}GK8C(cvNYpmc)}${p1=Ft=9ZWV=jh%D8rt`) zO4l7NVRDJF;Bpuor&7?eu?C6rT7Z`DTelGsKsZXnv z7GNIRxqPOcczbeNrUOQLvwm<#jrLZ?g%q|}>KXt-#9Hic)9&;=XadQM7 zd(HGp;H6bBm9Ix&Hs~u7`Adh6;lDi+pC@D3biFGE2wj)za@wt)57>jFWkkIjogcq! zeWjZmhI=a7HdQ`6)(|pW?u&-&%f8-G184~sn_y?N=6vevesSMr0w5=Jbtz^@lf0-C zatutypVzIix)D;d+c&Kb1P$2qdK1xf(p;AA^V(p2Bl$Tpz_upjX=BeZ!p+^yP66g$ z5&|x_NOp;rA3dY^`w*_LhcgGrhK)*_0Ln^$|Jkbl??!!t77BvdWRjTW=(IDO1jQXP zjrc3Cyh6#0NB@7qdlj!upR5#juyEIP2B_v|~qsg zcWP&}LDkj8(kNvc?Z?xHJDc9*R`NpqZH_)y-lk`@Wn#H|3D&I3eQzGA+te@Z4@RFx zucbM6OY1L7B#Zd0x+SFx)~l-S`xhSe9Q0`afC{~v{hotVoqwr5<8mZBV(+er z(kcDAKOk5A(tG_+-A{3;Wjzl5!DoQ)$p^c7YNwFe(~S|#MOUJp#f?F<|_5M#&`P1mA^YOGNhg)uA9zSb6 zKKuCC%Nw7P)_O^;xfDyJg*CIBG$&o^)iKnrMk?im*k9EdQ~jv3YWg<5()#Fwt1UTu zPmKRUlYSLke{c48=K;SZd$--8*n?PAT4pm=C0fTN_0bP0`|`!xczxfIn@JHhb3N{p zm#-$)N#y9CCa2L(P1|1iT+b2s{B!QTvpT1XKgcdW6EKBJFu6?K8RFOW1mSJvfuust z10xUbW>PjRI?epM3u=UaTu62&8GnZ3a)c?uTB!_K=%UV0=o1!Oq)OiKj1urW60$ zz^-|tKkZ}Z%p&Mo7YQ-+r3?Yq{U{hGQ0b{6l5^FpdVxDoR-FGmpR=7^_+ zo{U!ZScgicF`vw}0&bn>lN*#?q#3@@r-#Z|51xV%ta6 z=1#zD>Qw_PY{dK_@^?r2*RY^=E3@-E6!k+uZ}q!|2~8D}N1DK8UvWv{)R}Jq<11YO zw{AQ3z~;wqZBd@kMekM>61OOmW_OI78a=k{+?9eYvpaO$&rLKf zfh|0JB>X>{4y6t2_~-vFrT>i?S`ZY*1Q$VaJd{_llee%el!OZu|G!O#7b+OTjR+vo zLW1Ut3Omxua}3qx3^Fx%OY1?L(O=V}J$k{QVU$nHC&o*VU6nA&m$?sh)iK~Xyit49 z8y!7s+mazt$L?X{F3UqHkP2{#-VbeU%?X1tyu~*-rYLB#z zh#BAQRq}YPKN~Mx3&vrjA3?mqI7+B4a?2KMgkWpd0erSU`WQQr8r4z~{i-5C<%Nqw zi;rbN`j$L<(zed^(d$M$fFPIiE)NmtagxwQ>;f?%@}wqLrA!V^EI9+-{xD*6!K!=a&7l(_hE75(?(T^w!{BHAT7ZgwFMVuYICm=g;#sN!y z+T*K77dnziHvmpZ!y#%XfqEsle-JvV>%#&e7N=>ICPf%wy0g2leH3}Y(rH_b{?GBl z<>@u=3YW}Vp}oGj;8ASv&bRWyE<%FoPY53R(e(7_lUZfWi$$rM&yv&VfIBRjk(BQY zA-P)t>d;2j^5dhybV4jY5Cl@EKd~=ZWx7q7>7DmaRrQHzEuSsXFE-_{H69T5EM$!f zY(3%*vJOD<3El`OLPU<$$jUBMW68cO|CF4kX0Jq)i0NANz56-pC!vMm-)39nc^!-f zE5!YOAh85+Zf#yid%;ir_<~yHef+7-l|O8zEv`0V3DO_>-&t|iWbgRliWlkw=<@9B zU62>zJ{Ni|b2cbQ?+r>`3|2x@Ntp;nzq`AZIfcc$cS#;=v(O{B2~D?fBz@xuf3iUc z=ZHSbB9jb^0Afw^Eg=<0v?DcNuNf6^bhO*Xz45JXg%}*O%H9pCQ%l%H>3Cx9&s3L& z?#waQEa&wkH5lK^@%d>$mDO303$rX~$(|GH&T+PPt0Kaq6?ndF0$yD6H@I5@)qAY3 zUWH~UC}mlB=%M_`ZjJ0+_PEBBEx{pzg?<P@Cd-Zp&NLk?knX%i0z&wgb}i6*;ZGL7~BFcEx{XjYhBk(5+4*;V&oY} zo?S~`$2${vHSt&m6WR%F7C%RjGp+q32z@sAlu%;ImjKPZ@kXve#rPfNv!#gUDajXt zcqO9|+}($A$_0TUj@F10tUP%2cTxEy44S8(9Y1LTNvn~7pmTj zjsTMW-tQmDVpXV9rRKOuILEinB>=WLC~muSj=+1zm@1#%#yCPQ0PDGSX7Aqml^`T3 z_N*^%t4B3=G-VYXuPk31yLI>%;XKKO`d{(BI;nZ?So7Vjz zd}MFLmVW|1-jcxuEnGsD^jTWTh_r#nAS=JGTjfcq{H~VpLyA*# zW>2p({oH}Q(2@kR0Yzw>JDW3-{}*HV#(@bg zm5LjTE84EyY5~_A9lB#nH!|0jl$!#-$v!wTM}6#d12O8}+lq$U^=cxC6?2x1LUEjJ zga__JMsev%v?t`LM7i(4P)lv$()R38X)!lWS+?(9erQYDl8@1_)*P}sB_fS15Z|U+8-G?{8jecc@dUVbk`Ko;UCmN>bUEDgu0)j zdee10hIhHmlO?!>yaW?>_apeR9TC{=87yb41!K@sul}%t4BkADCgamc#mq68Z-iiR#i+&X)pgcAR(Pqw z_#}$g3Ed8R(;PEe;+%BSr5NOv4oiFrAu_PkH1;NMQ*C6twa-Kn5;QQDik{9Xko73W zd7l9JcvY9p+`R6uxz>2;OcBb7T{wt33q`PKJL@a%ch~hiz0zDMTdUw14T0A@YsQa` ztYm%o!+bRMSYMp>^K@}$*;3?Dn+)Ba3vKRTz2!oOYN?4l zz^Bt6Z3r$uEct3{!6yTAl7=BeFne?%^Uvmxf(N*QP|K4=rS+GU3kvvGXS~+@#1{`3 z0PI$xeuLyrKE&Uu!(WQ;`hO(f>e~_IBOw;%?7(je{{pSB|S;GvfDx!RuGzT{!lC#ZUYl8*XeG`anWaYS}VS*?n@55$`Smsw}+4O79sm50i$19K0~|kYLa{4?YiksA}ldne4eEd$^4 zGBvdEvi^xGq+sXlv!T}uaPF&3A$kR;hQ0*{r?JGlFBM+=Z^O=6JM*n4;qCd^z7Fk( zu#_7Q$th1N*oC!+2b|^>CqBdnnbe@RI$<)|LR(vyXG-`=PdwIr^t7fL?n*gguzf8v zJY7Gq(?-S>N zQJ+s21rAB#yhvHvoK=fc)_lf~c<_#Qqs}K0xivqLnFaRMw_)O+%3pS1H=0~SAo|j0 zl~Z#OB;q`X#adLu(`2)YLAHGOK_kd;zjK@=QbR-UMbZ(zaq;KPz4D``iQ<+dWRe;o zoujNfklDhYgQoJpCnVqoq%vI>={N{!0=`p#XDHZG0qTcozqxrrMaS$1;C#C_bR`+1Q{k=jW__JF0wAM#iJ`v%`{`q^5sw=RH{`>I&&G_8FY+xkjx!eWd`* z-{q7vPZZy!yX}Lvc+O6ZDqpqS-4e!^mWiAGh6Z=xSF{f>MVEumYPA?9XHUnb5{cBd zDR&D725sPR6ehmu0D9A1;po5OO=!s**u@GLH1gIeMngJUGJpp*LBhP7@YoYI%w0L~ zzF-F5Q~f!TEm^2WWM4`ExVSA}=#k#hf;(PmaqTg3f2)*ZDq z7?`=3RzEO{oSe`Mwu191GQkaVIuO?B<6j9vRF#|qHc@<6okubh{^;Iye@L{yk8?=~ zDR3Xo^DGC<0r8G|M<>ZUp5-4R+Wif>cZ44uD*)tzVJ3MOyNPxFCLh{O`3T%OZ^$T; z{#=i#s1hOh_yCf1f40O&WMl5ivn{k>!)O$g@(z&ZUym`Lu5iwoo=RgS^lVpH8tx*- zR?dI}cy&8%Fhr#}h_1hy)FZf_T9<|0+4g#V(!e$6XPt*y1{%z!v60&)UspK4Sy%L` z!&xehe|z!4y0LJGV#xR~#XrcJiK{bWqWI|u zAiX;<(l4MSn`*1$#PH5JmJZE_NP2(=jFvxv*|X)L+N~FFmGq$!Zw6Q{hi4x;#cAz$ zP>IYR2i$SPp}u=pcmmpp&w807JBFn9YZfWaCtag0?tRu~Hdzg+lt;*S$zL00WTziu zUAXY%De|x@$AJ7)_X!k1r;&{{*kCsL!#{|L$vRIpgx+kfmQ32ylOiOI`ny0~g&{oO zbh$9Wta+#}{3k<0UcjPc&9QQvPSV}IL*UfT=U0?G4!?@i6iCLAz_AU>6*Sv zloeMXDaz7ablmz~?a0|RNe_!ttUT~1aGTungXFeagC_}8k6Lz##%bs^Ks(9<$40%9 z?a4)l?a4IyZjBFeKfx;%cj@_h{(l>kLR!MbZLo1WH3_#C+=?A_FOMap2A_oUBNBNbaNU!#0{?zBw*Zxr^lq^g z9lKy5k+vtDvGY(`!+lcnBnKpMcL z-&H=SlyQ@wf9U_Z0mX1N_TQTS4o@B-#j3}Z*XF%@(`M~g$TZ79CI$vX$Z#IkXEx!j zgP5$O=c1v-QzMX`YG-FrOCuOKE&4~h&EBCzZ?=HBuJgL-$r)fU3R_*rDK(m1cuJkv z5+T4I1v~_-WI3Ek$%V3)q>N5EvB)76nEsedx$xK!f5w*rxq`&>ydDgWC4(SeAz zrV4yfc1HQ1;hqTD8&4x~C27&+Hv_sI7{Y~i7OG5)ue$KOv19U~3@0g`L__7wVIx8U z0<%vK{mp)Z%`XFasahM77PP~(sW(EvN*SCkHSU9{p1NISf6N_N0v@O?VO`ujE1VwUyJ9EHQ9e47eiP&P|H^#Q+)N?mTGT{&eIdzf;4ix zDi=taMsvwV4m$%*zgKYTr|p&Gvmj?HKC4z0YxS-;K@am`*ikWi40T$Ku^Rb~OO}Y~ zcni_)0<#hLvbSQM1jLk(hfzRNNIpbSsKyD>B<4RyqZMiF<7v4U*~>E~#*1T1!B=}D}rCairI(tJl`%vBeIG6DA_6w))B zI}S-%<{rNnTP4rR3Wf_v$GMPl8ubQIN`^2L{1a*F*HjjV(1j`>5Ctcsl*cEMbvxa) z0NFvn>Z;e90qNSY)Y`CCue{%t^6Q!ah8#Rmr^G>bx3k;P(hO899dg0>B-*alHfVMu3~0&jB!LXl*lUAnj+ zu|B2lDxkP}qilmVy4gma)v(0G3aQa{J;`MqbK8cdWwWPs1=sH%T9Tey3S1cvRa+2R z-Wm!@dIP!OGw}U>)y@c2E5NUg-LaBL>X zYFushI-rmTtR?o(p4cpYB|o(pxs(pMc7Fd{lss4CQDTB{_pk+cpIf}RNmZioVuBf>NH&wV>xaLtLMZ%qk$Z@mwqh7+H!DHOkHN#(H%CJ=DzK=i%xr)uGo z=gTzRZfl2Ws)$%D7Kg+3cEb)XpiPUeB@O*5Y4aYrY8hT^y3_(k+U{JA-&;b&ft?NJ z$F#$#AGf_mp_W!vbKD@K&6+=UUk$w%Tr_GW-NE7yjx#2+09J1+wnnc^v_QiR67oy%IYR=f?KT7$rVA#& z(+cJB+U>3{cv!EVg{%Z34rn|AR0$(6n6*>hh1*&AQTqQviyGW8+1YON=n;ueiv3*wMN-Q%~KuiAp;rj*hIl%*?*Ju@aC@ z$VE7H$&)gSClD_ks~yi_~vSDo!Ey>&beps>)<|XaPM9K_vmsCNsUg)Sy&7 z9O#X_+XoJbg)Q%)`fU3B#!7{cmxzb-gZ~8#`O$%9d4UcEIyKk=K`P_bW}fT4=QlQG z-1Im&%5(!RTd8nB@$j%XU7RyyZ7lC(IV0?C>R{)Q$4HymRgs#M;k8;CKg=USvJSDW zW&xVJ8kP*%Op8S zfDh#aPzNCSg)O~)OmWiR;Xfr&3pTm#uNrAIREf(^@@KKGxjaC zdm+r04O9p$MT}gK)HdNlXBkf{ZRLEq< z8rg*NcAu0=2O{lwStb~yx{c~=H)FT}rg!l5GxlG%X*UhTq2D+t)Gf`Al(pPV4@)sc z{Dp3-Fn%7Rq6FHWj%8dXG8?jCcLYxpHr;d)F=}d< z(ixP<_9ZS+)frG9xZoXk)%9FpW9JmUXhiyV5PICRn4Z>Vu(mLQa9aS3x)|{)^Q#u z-C>@UsNBS*y3$8x2;~#@hzeSvX9Xxk&qE`NplOXKPJp?Yqe}> zB;rM+jO!mok8?)flGTcrD|xAor`FBYN*y!mYy7DlA);rBC_FVd;?4C3#tXjE98zgg@OU*(EKRNFM8kb5T)Imy1*Bu z%ud=STTEKUYqbODT7~z0>SjA$>IVeSA$TEBHiO!8J|G~oizQ<#LWfTkdc3{!WpkiA7pV>DoA8bZ!b@S1un13FTD>|CtW_I zbR-zQ6{jT436ZVnhGm_UQR-wPR0hHlnI#F;xLxsh#UUZVEbz~=Wdns-bcqqQ-;#l+ z9#uPCz)PKnoni{y@0MuX?P6%>pn4imUlHB%0i34OGSMn431$QvtynTII;_J>q1k#^ zF;5y-Mh{prdx;c3t5>3)M|FNmFuSA~*+jA{EMMjlFF=^vnS2%wJQwbV8jU?;OeTrE zg*-N;2)#uty{?*YkK0cGE?F&k+*El<#WyG0SZpr@poBEc2hPrY{&$pSNSgIVV?yVV z+ZrjhzqJp()uvg-Iq1_K_y_7mc%shI;!q1qr`3Z-Q2b&i7$O8zCZHt%JnUJ*=#LFW z%9J{Tv-nU`F{_7Cxz3bzM|GZh;AuwUo(3hZjDX-T$CF7q z&09YdhZea-WykcmGw)lCLX8g*%?f$$U;Z5F&-&{)%XDPG!g4UP^>}Hgze!yTYrAZ8 zcsUn=uJ3$cgppf;wd7d^<9|V={U%n~)h*RICN&YYo*AT^T zyp|fN%Rm9nSK}e{YDit93*lPt%jZZ`ZPdoQn{UhsFu&C_fwVB-CJU9K!U{|&SnuJe zb=KlR(3M1KmA0NlTAPo6ir`3CtH?UgGmBv)kh>8`YMSc@PxyXTVQ0@DO&Keetm<00SN^SV=I$aR=3N zi2tIZq})EIGP!TGr-f>c;+>|Bsc8H#86@wP@uiC02X{MTnN|h%mbQ2lAWXTIStt=K zg(%zRFoz&j!a$F^Itxcyj0q4V(9bcQ_3j^nE(blULfm^o9j3lxT#dW@NvQFrEV*EW z_y)Q<0V&xAtcbZUSqfV^r7Jr_Mk@L0?hxD?u=JfWez=`^{xy8)$^9WeUZu5vXb8ij z^Y&tQI;x*Izn%gLc|pn|^*9Ud)Gtv9lMamo45%Ao7JZ%Wr{VxwtLyF=>ml%Vil!PF z_WBCHnT6ys^0=-K`u$^5|DVRZE}luu*iVc8yV5_3b3>)dSK5A;A98$a^Sj;s{f{8k zLq>&0sgmrp?3sae&d+gl2Qv^aZRxgt{JRs6Kd=mvcv_1T$xa`7eT2yEM zN=}5a)z5QY-;J$*pS$sMG-?#NlKTL^gCVewyjD=~;CAyD=K#pd=kgWDinHa630`;e z87-9TWufdw7352^8F^S+pq(K*oYTFX)JA+PCc02d2!5%EOY|n@Wgn_QYF@ zJuhH>J}o=b_mST`s*^rfIBa^8y4T=aSubGV^b1v^&FC_og(AdYxJ4|DH1vl2@g6M{ zJ^6QgMv+VDLx|>~g{|U-(OhtOuZ`(KH!(rk2&TY;fzFQzdB?)ew_?H)@~R(m+aApN zu2Sq@65^rflnHCE_-nW^X>f zSiXGQa55Is2u+-a*>T8?#sdw;DRjH~#&JxEsg|ZcHH%2Jt%$-8iDFbH)rkXhIy6u9 zI=;yVWR}U1>Y|b5L<%9WtmC7r_1tgZza*3 zM;VdB)-NzWqUyNhIRrMfRF!Tl3?rnft(o*Q&i92={F}Z4>RuMXGmr=dbF_FIaMwmXa{tu1d%`J8|7(yGmVqJ=+9qrZHz%`O<| z#3KRR1@t~dipWqE3PP(|gx7B3$;H>gQ<|i9?2sI6&7;1Pm`gCo7zglin;rv-mZc+y zjk?Qv-_k5$_OVuU!^x*w$N9DX=1)YSMZX2a2qc?CT16>67kp)9t!<*!JGpXb3VZimiqE80R(CwvnUO? z^6l~iORtm;^b4Lbw4nwqRpy>bo1;gZLpNvW?}|iPsYJx|9+f}83ht7!NIl(SJ6!4V zpx#{$a%lwc5={3Y&5Q1r@8+Vx9z*YD%10Us zOzR*{(WC=IQ}zypz2w{qW#{c;e5q~rp7HG5hZ`MVay{JW%54HavGoA8d`_#KSK^{3 zo|RNe+aqvLOF~u^zNk!^;yrSWJ31zLLyqbVIFCs$xQNIWdAw^OofSUxJ|^Ne6S{Vnl?od2Ts_)j}8%_lJOhMbrDQT0(+^ ze{*U@kY;s1pCCY3QUU;7+C%1&Y|Lo~ks!6K@Uh-~u$|mtap>52Q?w+j)qJivC^+m` zjwvcl(`cDm76ur$UFsgdEC93z&2I*u{9Y}a*B5qSKo@*JepY`afF<3owo-io>chVB zo*{%cDrF`u?T~0DrET0qzM#i8RXBxqpV|6-Y!zDd#c$lpqM(a>+E**k{9m&-fdS^V zx+An!&*T9nXG@ z$pQ+6$Re^AdQ3mGn-2?wcY` z7`>?cc%cQ|&0MkNMIlVOe|^@wQMl$HBg5fZxdV(fW5$SHBfLko6w9C|(O%>ujPy#$ zy7#KrB{a{G^ZH-x8K1Q8-5Hr4Q`(ctuNdl#=qaNo)iO%J8X9yVpSHB~P0qL(eJBb{ zNr72sF((<5ewDkxVM9l-VXAQs_j(4;i%a>Mf4E&w{~Si(ji z`OXw6x3tmEcOS^4{{WyteeyPU|0AFM#U(_CLtc3K9CB9Y4$6~@l-{Dhh8Z$1>(v{A zP0CAJyHlL}!Uy~riW9*D0eP4>p9t;K&q?eL#V!F+*b&G+Zx57xjXo=IImxw(zG ze-0;Jc_vcOkG6>$$hNgBLQRLTM>HXH$nqJeqV2y8%CvqD_8toTYx=tfHY9M((Zbem z>{{miAhMB8O_;!SX$6Hlhx@xp4gV7c{!zUHux8l8tb~tFSqKd%vXG&fsj^_(_Ww5g z`BpN70PMHSZ{ny%E*6n2gG~*=UG5RI7r4_~3MPJSQSf@!P@TBWFrDcvW(k#>&c}nJ zQD(NKYCQ|^mf6F$4{js*(FcP$0!69t=tF`=J#}&BKI>-@45=;>f$^f-yyCl6q67=Q$meego zlq&5)9*{s!UX63M2$x0QT(~zs^;iJayIJ%TIUWXKEbm6bL|^X~q`=g)+rHwQ*ou&f>#n}KNuHpY=&TWOuYSSemH}F; z9wYdQr}m;DQqN}Vif2(~gtjO6W||25D>&?!aklyg` z$|`81tD5G;1c6tcT_mVbvib2pBj@DjmXNi@7WfbBEH1@IB$s&EJ+QRYI;`jxKPwSw zK9XWkSvBf$Uc=pMhuFgphkaMWNKlA26w{$li08&_?p3t+Ec8!3$_b9_O3q3B;zbZQ z){&=oJ&``4ui$`N3!rwKrj&D^8vcxi`Ofa_D+b-9WT&g!I^@HR?5%x+Q73S=9uiE+ z2_Ne$0T7+z>Wd`#2y2%m9`?au_xPqoNgAk8sXQ_h>vfvNEEqt1gTVf*Q>%G*(ClQbiRrhHy*q9N7YHkCDgcjRw-ZVtuH6g8UjR;$$ zzf~lInPR+O2N)R+sh8O)D>Xg*Dxrqn$#{N{SGi2-ORjRr8K!F^SoAlFN z!w+@wq6APrs!$LaqGXigFmoPE4H6F2(Kz%p*^m#MvYN25MBi9fEU?;yts)01_DTi&){p8VpuwUb`EX@km31h~kP>294E zqXUlt$yYYFO`w3m*(rk{jlC*TWt zTfI3AFjWPnXR*40jnHtBz2XlNZOC~{Nv9PX8Ol+nD@%AKvJqJ8)_cE9Xo$qjH#pM3 z>IHEEy;O%WI@}o!HNJ;)xmR+Ym;t7{6B6?3p%qr%f#OW>UqGkWVL`6_`r#0ef5L>? z1z3lYbFRY!&;e!<7kQ)R zR;n?;FL>R>SKskOYh`Z+3=Wf}FSdX>th)`~+Fs=K@s&a|%SXi%|AS zbRYBq29R}97dR{Y%?OTcAy$G-m}kKQY>0u zvQ!(lJgLC^>}8r0y8{i?^5xg=pC^^RKEw(mJ(!7^c)ZS4h9fEt~u$;#CEH)o&|7n|hb^796I$wq2_;n71AyUDc&m z_acucQD(-83c@G!t^6Wc-E_=&aNW2v!;3;M^d|16u9I21$ zoZ8(I+-k0O$J)Dl8PEmfO5S(EL98_tAAf7w5@^+uR&I<^xK{5P`t#}UB#Cuk!I94yZwpgS_@8tbpxnR zx-amN*u; zF(<%1)6Uj%$|=Zu!9N_E@lU|ELRYmL=Fv3_0;$7m3uCf?N!de-6~TFbyuTD%z0Vq+ zh#2g7zq&(v^DC%^UR|MBF4-> zhG5JX;=R`MTFTvzX2IH-qGUc0J=%%eTzJyLj3GZlsUZ89 zRkgiQ_p8)tdyJ#Rv1TO1w=*yDIkHFM78~rFHh9to*S8nUkV;{c^P_{|*NYRG9kLUd zXg-wG;E+PD{X+5=B`Z*z0en_k9| zisG>2HWmou+#6SqVLk6PE`_fAnLP6umib$huwTLSh&=23=TX21tXBeKWN0Er^)J>H zY%KCaDeuZ!1}IoPUPCvJD(7;1oTY^i%tO>fuLs@6Msdkc-JOFyaNt9pPR`JZrEF&R z7ktvt0$fd5R&1ahnj{EfSYjNBkT!i2`2oL#(z`VlUw;Bl{kNg_uHM}+Md@hqk>6v> zcLz7xSvY?pX!O5Y6t|p?by-M#;ZOy;%}RpFKdKGx#p5-88lk>#W_QNgX%adm>gFTA zU~d|25lu<^xC0D#JrW3iuZLkpA6ifM-c?kkU+Yax6LT>wD8^Au!p=c|0f;HC>!Gz~ z1@9RJ5{D|NFDBZ2seIR)^5gwk=Bw{pmp%+Sjx91gtmw46n*~gJb|Gyg z$Ma0hU_}cgsN>WxrO&m*JszONqLm$GKzw5Gkz$Sk0?nlRaq0%l#J3&+#vTv*n#@E= zpOV`iclq*8)#|cCe1@o@&BOK!%?~TRl;4~CuY2aB?wW9Oyp;b$uGNH2=6_PetvkBs z%X@^T#(&jp)5S=?F>tp+HTJUi7wY+pd^fkeU-$NWN!?be{1eY*Pd~_qFhq@m=QG`Y zKs`(q$_w{j)%kzpn6fp(V*V2I-F~q}u&;Iwn_xiy(sR_GlM@bqvB9_D-GU>y{_F$V z2>nsLKL7hT)=dmaa<6Y6nN!Ma_ss-m@rRP47bIU1gXp!f!N~G^HG3(sN&DXuR`m{X zo;D2KFM*N$2t^bhvvp71#q?p6g7Du43~2#HRy}=D`*f$Rmqp$cS#vs}f{%Dt%w@w8 z`AiXr_!A+9Q{DI`qly?2TlFKKTsTaZMVKkcQ^jt-8K8d8jrF~+WQ(p^ax{v zKlBFnQvJP2B(-J(5=pZqM)+e98Xn#qZ+HzIpt@>L`K(*ka(A;{Fcy+#KYF3Mkat|; zE2y68*QF~fJ|Ti1{S!-wkME(<2%@3ouz{ltY@~1zAs`vP)pe0U_>M<>U6EUqRXzmR zz^q<}dW2%o^pn;;08>A%w0RGx_vmX#(g`w3xx~s(xIhBF{BJ|uEqawYG2R=)z9(Bn zvGe8KlK?v-j*;5E8$2~NNZ(1faK{TGPu_TO;;*af*@u`@O3NTsw2n%WmYl@ z-!4oCVzK&sup0W4+B%ixwdvPC%PXkn5qj?lnqQ}_hu#lVa~W;_aCyE4);5~xBC4x9 zW+|?#c=DZLZ&a3y>qHGq6-r!Wf->t8EXRyoCW?D3pklTj%20mXtmvf}_)IFk%a|iC zjKT-QzT6cR(uLWCSj0T2*RPgg?!*x9wj5n@5ugOlA?2w9VXAG*{y|{b-*&*0uww*X ze~!DGi?#2(x|@xr)#A@(FIap=;wg0jvj^`Pn$`WKj7GepGRZKjpvto@StG-qE$lgM zOX>awSw2|Q9j{d!Aq!z84o^ApMzd{zG%a~ps*(j~D4R&b69-Nkq?|G+$cKn4ijoLP z5gu_Kyni>#x}V7!VJNH%!(Q!zQW5b4@rSh^os-)czOB`{%3>iwQ&Z@g&T7K%JgxOQ zcArj;nqE}&o+2t+qx|O^P0=R}jY3b-I}9bHnYkVxyQS6U@jyJ}u$|do(xXW4>-6xp z|BtEn4omWX1AonJ?hy{$+rpfwnR}ZWYJEzy+&ButRpBl-IdFxVrfH@POF_ei8#ivv zKupD*BXMs#e9!q^=Nzu*Kd$G3XWh^HzVG+@_0lkq1YPmPZJ!6|ZtDlpDciuqHt%*Q zr)DZs_}$LjDS%WQA9y#}TKPqeuCcdbwwbQ8sL{w-GMo9@VfweB>nO#35xlXZ-~0Fo zz67~FkWxTj=hRTrHx!vn;1r?cO6M} zq3rPxq*saz3yNdL{=V3^S(F2IS?EBXFG07u4I#`~>E3*d{v3VpgmKLLDJ?@Yu`UvDP0Hxxp-h8xO@Jdt z9Dp>l6#06EAc9Y-PhotdXrRhU{z~9p^A57-Tnvi1qU2PC$G0wmqKlx6a?=AD5Ejr(@H+rTFN@W0B69;c4&m5^J*@Ii#rF zF}L=Cz}kbW{BaRd67)9WT}k%nYleAjrB<{8%eL9?^g?6{$y9C%s1Mi9-1;1Zb>N%A zJ`lWRMsDde_400q)0eT_jcAY8>oIO~sv(#Ilyz=}wl2rmsi}DWkd7BgP`naQzjkNd zA`r)LtN+Nyv;B%^y(P$1g?7{8&D!JBw3&*I6tWsvr0c$_fmd#Q-Bkd zm_&Q7N?-8&zIE*_u&tT70pfBI$ro@Bcz&go<^51*7W+k7pQ^@z`ay_>Fne(~8XC`j ziuMllxqUi!G2qnJ^T)u8Pw%s@y*_>*9c^V< zj?@F$R1z7uBj3?lPzJ)KipgmUrvgplv$$MhjFJ}}UbqQdDSbmGTfSSgjsiq%nj+d0 zMMJs`=iK`aw5w5P3I4ZWgKIY}R8wK*rY{hAXVx7LCHSSxlF1PVLh`Hy*W&mN0&2_z zsyw>YG&>e&-u7^^b`Hi|ikr5Ii!Pc;0&u-oWS4%B$l6!SE|AVHav+%!u5oD4%xoWM z#2%&?BL9ToSi7~gJ(Izf<#YedE2X_C*v}05&1M%sH#4xd{4(c#8CYUKe(h0ep#hgk zf-|~SIj|Vc*jm|WuP37BeUuVtarcT0j=Lx=GweB&(9Fir?cyU1jzZ6N>@Rs|K80lJDlgzN z^oHN{biR&cts8}2nztegrR5UD-jB;*-_-=h`uq@cP)X&~?IJJxgsrk@E2yhfb=x@F zYP@d6?HJ16TC zrR}zKhK*H|<~_a_DuS1Q)od*rS<5lX;f>)LYx zrOZ~)y(6<#!PhvkOe?@`AV-ds`h=hvyS;sxw^&7=NVvT@A!tO6>8;?ExuKKWq8l9N zWj?Z-*kNa~U{T^iqba!)hSHOQ!((F~%WT|SX6%hrJSZI@bpshE#mTctL0aRt*=P3S zt6oHsK)}1wbgOY zorIbO!`&~Gz2R&EHyI_z_Y(NL32nmLvqsaOnCBaDgpKDBQnT{9301D$Q)#P(^P$i4dC{&zIjT z=}nchWwQB6{kFExSt^^(UK{7V+x?64I&1rt^ZJq^#Zs0->0Kf*G0E4R(_rWeLiYp& zd9TJ;;y9o|0nuH& zr==Z+@$Oko(dg>#-z83;2kPiUQB(bQc9|(jG8@dg^L!_^;K9~+Y+ z0p0zJXTvl>l`SLB@{fKq4~~|Y%J+g;OTQ0)x9tvPBCkOb(qUN~#U~}`YS|v{ncNbT z)~v`G_ceRnUT*`K-E)h^w4;P5&NpkFACq#e+#l4@Eg4+CGQ;XyOLX(a^NGZWqV@1pb%#;OHiCx&$53Q*t!voeGsj& zd{KY83XPa~Z#K{~UwRZ)ny*Yj}X|?S$I^12YN!ca> zXm`F{?wO$Z3CCrQ)`y=>ei;7!^ThtqoV--Jc=Fhe z7pK*SZb4o);{-LD<3o78v;_5~ymh^8JXAJ_1w#=M9Iuq(21TX!X&xvYMd4N`)$j8A zc;UZbo0u6o?d<8CzSC(V=h%B;&)iIK=?kIx*R#VLmn=i!=5LRMZd!i0xMcmk$BNqk z`v=|R<^ta|zuIPq=E?eb&vI(Ckad0S;tuK=N3+>&F;&3AA;<}p4SXSxu%d_6DSbWm z&SU~eN~rDRexF$7DpI49SgL&Ic~YIWkK?9cm15ZJ8#G~U-gGfBu_VU7`9hBAO;+NQ z6;!D1_8WSM5zgJU6FKW&T^(<^yJPGxa?^I0d?bFtA(Ewr)oEXizfHMDvp3a$lwA8O zjsW8Odq<;n19V*w;f?QYSNYBki$ zGOqPIH!J@!kUjTcwJ*g`l_+eG2~8(v&Q<$T+0Mm^p}oxUhTgj+?Dka#N?EL(n?X4| z;P_}1-_5vM3#)#owf_)RV7A2~>oT_VR5F+Svc1P-=nnARK!v4*gg~{R&?=y-w89kj zU>VjcPGz@H4FYoroDU!-Nft|PE}&Ow&eTx)>JJXfI=%kPCWMESlET`N;Rdt{ZjIf$ z^Y>c(RpsF}7Xyeh+Wd6}@r~LybH2j_>8&=4ZA(dI{7&%r;6xTrCS~|Sq;`&vN0z{( z&OzdT>#IWFkTRm@IrtLZTfYg|XN_gBeOLBb<6Y8awBJhs60PQ|OjzIx-8T^DT<1Ao zVaq7~6n{?PZi+6sbnMZga(=eYv;9lH1>Y)uTx`6-E!ktld?`B2XU^!^7lMnfwYTk? z%tN3{kRRGq+?I9`0cW>AFggrQ2-84!sHh1HtSG&P?t4rF0A_-AKKyk5-09V+d zXA)ho^A)SYQU#PUKN3s-QPSG@_~?wc^a2$a;p1m9mi8bzYp8zm$$`1hFDKHkQhG!D z*2O^WIrHo8o%Yp?!d4)IDeJ{UnOG!2CyEb~ZMYoa`?B?g*AQ&hkefcWIm#&OHIcCf@(r%y0N!xq(#*7FRtj^1<%VLVv>mP z3sTE#9V2PPIP*=u8eHlu_~OHRlGF;Rnu|MvJ6D|NWh=WWzmrlE{rU?Fv1_ zD>d^`wM6Coq)&3_VQGc(&bqsc?4^0U{!FGblaZ2}trsmaXimwg#fgIwLS1@creb2m zlaC!wIe^eWVP>DXtzVCT zUlkf9e3W;Gw%>$p)1u zSA?S3ZDkFk8|RnfdwU5dfd@`{UGZ63lA}Yv9&;6c5SgA3k8w;t_j#O$|Mg0_%bjkc zisJUTqbsM%#}%{5uXWn^Yw{5-`E>-s=Jl?Av1pp{H>CXmv1`w0_&Z1Hq4}?JK6~k} zvewD9WhtU#m)iJX1)sNczsJA3@~aJaCB*oFn_rqf~rx)Bex>} zR+eI$`YI!50KDuSBPGvEB29#jT(R0`x^tS!u~d4-tmvHX+yn%aos|ab?r03N;rRm2 zx|gR*p+0}g5GAV@=0!${7G%<54nceCTsVI*29h@Ghjot>74$0H` zvo`W=Vrb8sju(e4DDo>xdshf%qDC_C!E!N{*AwFLP8P~PD|AEg32*zqN|#piV(95u zqKaMW?C|n+A+UeVG|jjJxOgFE6D4lb%#0wjV=uJDK}V5h&e8l4*2~fCM{%OH<7XYw zYu9fE7I%ZIPo?~iq`C!9F3_Tx4hnX(Hl&cpQp0qokYenz*#22k3}0gcI`(JoLzJ=c z%v`KX_TB$ZfII!Ehz@R_d>BIP;!bes@*6;t^_Rw?;UhEme+-GW_~sEM@mL?Azlh2A zH&AQuU5iiIqm@pUW`?i7D_;fzfx@gqHQvWvX_*7ebaM!zyRqW_e$s)<0pYCOML(_N zO^jjgC|jM*ODTiplM!#vO|Z@NVpoB3rG#FiniLI9XQ8PpH1wM|I_1{*PpG9a_2rJU z@&hX10?O$EO-FeO;F$U{?CoH~Suzf07L(Y0nVaw75-FqXA4BkVGxo`a<(p`4XU?H3 z>yjz3$f2;$GaBrT*iV7FSoK4T z(!W*)dP?7z_byKw?s%;Ee~l12tcZ5G>A*M^O=oKywcT<^yfl=FofM#%g6QD8w{2A~ z1!7&I=g046mZ(2gxBX}KbT5JQ?C7A?PNbNl`2CS+w8i)Mc@=vZk}8%iEt0=CpT}DWO&9fx}9fD1Ok- zzz?{}L%)Q&bpxP;+kl|IE8L~hJkdXH%7q|^IlVFKp2#24wBpPhaBkSdEx$~vqVqdv zQ|S7g{7L7E@7GOLczlXOmvS!%&o4B?oNar_mxd0#Np9046t*@^TC zGO6kYBF>_5LI1&q3YFIP`}oftcv)PGyUVaim7Vx*w_5vp9hx~)Qyl2SY*iA>=@>=2Xblk#TDzJ%bEV9idjLA0q!=**ZlLV26&^%E!U3PfVG_zxh z1w%W-Db{1GP7C$ky<6(nyQ$GljV}N7b!Gm%nEQ1azUTV#o!oy^ETqGQ zOZJ9_%o5$DJkVq z($~C%$_N_ayS(;h)7vlU#yqX-cba~Rshy=k;OPg2XyQzda#%%Ria`YV0b_jprTh=o zYPXud)&$H3(}T>*xuxyi9(xz*>Ef8bYPsS#*1JyIpnT#|qYKZ+CNKWs1Hjt1!}Lo) zxdnG#oxg$ijTPSBykxQUAje=DW@MhxyG}$$+!?!l_OL0AV|02qMEcD;!}|O-3pJ71 z+X*pas#aTztpa?c(bDLzU+z4_kS$|dBuNuaW0p)Ul#E(uDk{- z8F}}rHEdK*$yQR|Q;mu%M`*E`zxHV??PV6;S1yRtQ}ugwe^_M0auYXwT__#hFETRI z_i{4WTwyl&)^U!`TJ`&yoO>t{bc3VImzye^QB^Dw$w~JOnW>+Xr1=JV0Qa}Guif_* zrAnOqV|ah(fik`vlt5t(tngxe;*fMlMv2jJsO-8>F<`w)Y2tn9xu90POVb}Y+yjq? zZwd55Z8Fu7W!e-LJEbM!<$nynUI5 z`|F$0>j|2574JWYV=W3)0xydH?MxpN&jP3yLGrD#F;69|#dsTL8iU6&jI=xUtNd5{ zefiF{n2xoVSUa`5)<5(g^#lu90Ovnl4r<1+&orbIS8?IcEI8nox?G(prbQ z-yM&@!V#1YEF!Yt@cug{zL6S!%z-aVT4U~FN_fPx1j0jae6J~In6>wFjA^1wh9`Y! zFc0{?RMI3-u#^q)&FYuH6C`DS-a2;vQ5`K&|IESqU|8eJ{37F}Z(a_**#SyF>ijM} zmpg~33a7qibrua{qfdU^SKc}gQh$1yS0hV*O|HGcpqj4+@AWgTC6TY} z%=-O=0>UfTrpK+lSow!!pEGmUa^zi?H_hU29ZgEImQl0`Yket^RQ$8;fyi~v^##rB z4At-RKkp&JqHgC|yk?=&UVpxQWHQ?p-p=b&C`QRH@rPhRhV3gj+;4^4+m+ zy{Bp$H+fAwZB+cHv@VucUn-5`aSbc?0BIjV19OX!OiM3YAHO=blfVwp_SP0P_dS5f ziefo+J3xN)KxQNSKcQ;XmJH*_67B;C>UE`PB4k!da#!u#RY;N95$_Wvw=Y(!ep1W;lys-%ph&(qH;NR56c z<(Zp~9wTMpZWqX>ar4O0=_+~Ho!<<0Zn2fD#>YmPPBYMAh~1T*kV$2`GXQw6*fdz*{>ogWaxb9@@cDu2#GT48wd4mgX|k}C~p zmG$GNJZ(wB=-K$v%1cI7ww!GSUC(6pZB+5R3*h}HBfk7+|Gg*-;~Rq{Xg%3y@wMp` z(rJ;E8i0b6pao6|Cdm-;+Z9XfcB{DGA-wa`%99 z?glq3_8qc*OgOK1!)xj<5*pKGx{PCrfPqlHI0PWOG&OizUiqjOM{v^p1lm$(Fvw`1 zQgQqo_w+-!cIOfMkm(E0s$-v0@uAGSH<+dmQF$)<&+S4DIPd30Un&X{@h+KhBEHpp z+Vc1F^Y`D0Fy(jmcDGvVHguZ)(=zfbtxVuJE8uf=4K~u#ss45JF!R; zU0lqHMOp3!s9}Jw8yIdo+n!8+cvYJpc&9i!PiE!r4(97WhR?35PRp_tln;*qkypH9 zk6#>~y08~tiq^t^pQ=+wylxhglM(o@3=j|6Uf?Zq5xV*e@~QQvY16%jSNk?}yb!;|>YXEl`{ zE$(I%Z2^1h0v`R8clzXTzrz-ueq-m>ih#*ebA#6vt~O^TVj@Tz##gn>7V$1S&%rruhtjQK8*rwUA~8YK*e zc2|n#?WeA!ez%PnAa3@sJY_HY?x}iBQso1KTtY;2MV|G-omWpREY@$OReX?flv8IM zjN{hYy{U&K6|TNz?h+Yh>F{c%kHC1qnv$=Er;5JIBy>43bU>vtpN$weDUxG{{gq>) z$}cXD#d}esn6WK7uT9t_n(fxa)Qq=5a^T7XrYj#F#U1ZuZ$W+1EPC)JnY!IvxVm}NX_8Qyy{ zc`a^0q|tE6ry8{qUmO>$?l;9)j&0XDXB`(N9;e1CDLBZ>T@6w1ySue?W?)n;6x^J9 z#3Lw>@ZxW7zQmOw0m!2z|H`%m^j3U;;oV2kRRvl?wrdVAicLScjw}rz?U%#toANIj zj*7=XmBYVC9<^&y(mE|}N1A#67a0%F9NCRmqeZ3@LpVO&AT6(YhO=`@S4+EM>^O2D zFy)uJ9hI}s1Ezwv?|f~0;s&24eJ`#3^nI2n9gM!RZgdH(`gb~J3&phDHZeIZqV}4T zk7ISC^1flpjo&gJu{idN8iu_pU**LA8xc!l%lIjyd67S8a;|inrhZwjQBWR}9S2nn z`yL!RXjrtpxczro@ufcQ3v&~F5tghcXBYJacJ66cg_+0IF)g)gy9(L&%6~k*W|pQg ziz%2*I`V%W#L73B`X99E%!#FvP4K43Xz!*5KtWfnrRXF56%7mhDbjcEi_%9Y-Mcb- zS%JyHbQiGtKZdHq-#1I=!1)$F!)+Q}L~~P3zAP(jlVmu*BOMAZ&42Fy|Di*{&oTTz zP;hl86R-cz^T)?~UNE}B$gawo^e81q6+bcv!e%JMn!I=$p7vOqTBrlt3uUQg?Z8dJ z2IrZeJ%W#qP`KfTZddE)KpE+FFVw@>GB1HIW*>GHxB9SPAS^it4+jmgo=~#{aLqL) z-{3zD`r@paW<7btcE=HeOrLdifX_mKuYzn8etf)}+Lx1JQVV*Tfy7>s<-K}B{WIPt zz>=7V%0$X>)K64i`31Nlb= z6`-@zo>NAy^)k8LC-Q-pw@Ik9eb8*syYQ%0X+w?Qm`8pd1U0q#lAd2*Yy7XWWg+pT zLOWZw!lHH2Og@NusvRh9fXA%^edjc0i)egKvWk!F|EKTa5e*Q-sz=L^0wGc*;6xu% z56j1E+?lS4syoS%6hw&K)trUz;3I)Z&M0dtJhvvCD@I2o)qiTef&Ed)!;R^dLL+G{ z(aj?Beh__jC8~8RvW5b0e%fSL73(~*U84BCzUOgIEO|5e2Z82>FuE!?Z)ccGf#W-E z*Om`BDrX?bR z8i@1RcE1h;PIS695T9m6404`(c%1+sox@3>40Qs0&z-WK+ngsUPRbDOffsM+7|TV} z3>aI_N#`3jXU?f!>-+Oe)>^K9tXEcKN;nnT+#NAD8sVznoK1=a&%yDoU+(|>_!wnx zPs)6va(I0GVP{uj`2l~mnv^f36VHX#af9Ra0byFHh#Bd{{|U|g4-JU&xWQpxxst3T zDFux2dI58`hZ@}GPI^KDORA11q}IEoq2>kdjM13Q_PA?Ltn>6ls~9$r`UK?$i;H@G ztSsaDMW}Cp)TP-Y!)$eChvi<}^F#Y>N}L z7z#f%&wG;2lh4=!dV?Gn)?4isX0*dn)9}H8fQIJGm7?UjY=ane}0!B4)MS_1XC?SBpC>sAawet z)!_!=bZ<;AS@+ihQil>aJc-lmax>bc<)C$dP&_Hl4&LBai&&6eh2{EPhDstZWb9U39DIdAIjjvGXcIo+DruxDLUaB0RC~27?%?@fXJ~F6d(B;4}s%7 z)HbN}ha68KpfnEjf(yNj@$Ds7cVXZu3E8RFxbBvzY=RC20U+n8J>=ADFieHXW4ZA( zO$x8%rxWg^sgk^J3PnKw?bAHFIYw)f`MEU{2-e%`y3J`_rtZmGBa_9!s^}7F`R4N4 zN+R@2VumLD$28_olPKmqT?-lF#H$Tcm+2Y8m-|z2e9b4bya#BVbsd7FCL~g~T@O@S zXw-T@g2ma%=RCu|M%>%6>D>9#Mu|AP7rNND^iGSn<-U^`<wwkcjOz<`q34F4Ue~<8Gb}DwZ_n zE+PVf(m2T_NqBQ!;SqZ{tM&X7uao8(w=)^&7Gli-KP4zmH-hqjfht zl!}`s98B*4BU+D0^bV4$7an=GH%(0<`T$&W_=4UHYI;wTg zyxTJbJGacPkze`A?P6S7st!lYh#^O|^d?YhG{&?*GxzF6n^S1X{BBKOV=@c}tI4EF zD8(X-MLvxG#>?LRiIjDRDL9fqNGN)RC2;slywr&epmv}yrvlx_Q8vwHkP>3o~9`uQbtve21-Cqyp=x^Ow zvkF4}V<Nm2 zarbg>2dq$7Y4Z#nckI26Ck{|z;TveUyr^bL8{{6nPRBwe#*&A|UEc$S)Td3z^#!uhd}w~d*yx5f=I(O-;AV?9q`Mm>wJpAf|EyY#||)#XeYqxrS4J=5y zCmN?Wh_bqAz)8NnnY`$MaCc|acWVpZY(SE1JLXp098r}#>SzwHHRE`~T{hCNf0S8| z#RHUN8HW*$4a?yfR3roSaqesQnl)l(*F*3%h4@qCn)o|=LfCA)zH10)`KIz`+XL3i zvA`y`5dJvuf!Y_|ElRu2QNHRNW*@=7NLqnq)}6@ zrlSCp((|amJ%>YHRdFww(Vj-#&w_^vKBrIfY7VT$8*G<^hVj0yb8bOIbk!=g1bqZS zpbIc{liHMH4>6F zx8<|+fUwoeKIN_AdVh(NzCB64QxCd!X;)yHo=li8;kAJxwC$i*)SXQ9ga z1}{ciw?6O65;5|y5$>wpw!2Iht?f3<3a;l;Fr2HPr!F3z{9A+G2Vvk7$^-5YhNN?n zjZMLUHFFFmzR!%h3ol+k>qz-5v`fNVMtz6_d!4~=Q5NCtbWlf15cIi-vrl>Q|$8lJ5ZDlrh^J&1XgX}-7 zgOZ9HDoQ|xiB}%#luXfUO3qGE9h+@>jon7CX^kH#!ii5^{jd)`9y3R$7W~07p5$!} z#xkYn#L36X`pd=G#rmXjXj8^!2_M5x&~DND^2s7kb=);Q$DNBYU`wL&yfiYoKb|!_ z0Fi)MXY>4Y46jolf9NoPv*lj*3U+~pQ-nFSUNtV~?d2hc$X$c23*`T_| zTgfYaSF>Of8Nz$!%Iot@gh$H9{FhnY(&p`^SP5M@O2T8F2&6!?X&dAgTfw2P#zTq^ zRm!K$Z9?;`FEGDw^=Y%3w-QKT1grb)oiC-^QPV*92046pZDwN6P3niA!&i$xbw2TI zen-hGDyg1ljY`inflmynf{2B9pDlibQR$6OaHIC)t_CtcHp}~r#=d1!-5m^U_Dup1 zb$>nECr8SwKL!fYMUNw{Nv6TQg2lDnM;X{QMHXZaq^Rpw3X(TdlOEe60 zZSDU)|3~%6CoQ9)ZffH6e@Zm}Q`YkRihFXXy3bX7q3P%wOb0RoI$?lfY@s>L3^80h z$e$PpG_Rg5L%f}Nuows}+N;Ucp)f1)Yq2_{>cCvEEd+$s2*oxMN0Ef7Ib*WtYx=Mw z(v+)>!k&5GpvlRiuOz;@jj$d^wtmCzu8#H`AdY;C~E)@)%vZeAJC`} z1>$-IL)sh^>)mz;JF{=b9_fU*y8t-|=4GI&Yp6mkQG<_oPb8uWKSud26M@!D9 z5RTt`KTiBzZQk*Zfit4Z?a9NjC&_9EOg&i*^S}ELZyHhCPVK5XfEJ5N&Fk&>9En+d z$|?r)G|7u2Yqn$gP#H#u#k0^Kkz~-oMpg@XlLW_$;-}k@NO0-`1~S)xZ0zyRq#&N1 zGIoP%TenDC5k#eq+V<6hXk?SQ9nVT9@HLoJUKW=HUTe{><7itJcl%6A` zzv9%R%}G7$)Zau4O{KzXjyLJGS0C~2tC_nBuVggYm%h@7phXBv5k0x?R_goHUtA1w zGa#zfxj90W_z}S^`drnbk^X#C z-w9L8w*MQ!{T~SP(oSg8RsWE|?KSd2lhRC|n_4jirZbq;hZ}6&l=^+DV^HiH45}UU zs;6JmlS;|vSp!kIH1I(*m`7^1`yYeKBE8JogBLwv99VDUH10i&jE9{J>Q(|oH?`1= zgIu@){-qL(>1aESsI+CwMgHb5zyZqcruv`5K>7!CMCI1(5DN*3i5R3W_^E*?U9hbK z!G-(N!{-0Cp2#n}$$Mxfba59`f9-)33e-`KqUm)#DMVyY1fdwqBzycc6PjbTrUoJz zu9S87H*_VOJ$z#z7*5+md0~L?#zM`V!p|At8~g@SfgIB02&*6XO>e>37_janK+mBj zj^YA5IuO^#uZdW_#&IcXjO%UBb;qbN%8Z!CLEH9c_M?h?NxPuh zmZkm%xpu0CSFL=_j|hRasJXt{f)QK7rW?|pcHeRjPoczl+R6h!Iel}x^O=;t222S} zm6HI|`PTaK!qx*rJ%|@-=?^monO4A`CqEry&HIi<@jh$k14v9}Xxi@fC#M?dedF0y zgklW62l*FGJCQsTZPl7pcx@xVj9Z}&$&&3q%ja@(E{X_?ui{i8RnKr!?< zZ=(t4)F@bl=UlcNUDL7uGgz#n<3esBL3!`Wwi#XXMM8`CBAS|?eC*$sJlF=!Kr~?W zeWA4*hL zaWH`b`ciw1zUPQ|2&W9o3DzB&R|f|FE`}BXp>tjB1b0ccb7(nztRGniL(xkJ$Cyt> zW%zSsXmntVTQZS2_Z~&I_j2Mu*i}UZpw10uA{@5^--YkC@~CfEbq#FfU?^HqvCsa} zZ-yXy`>(DpTQBlLBJgVhVD>^8-)y(pxp7;ycS$68eyX1FokEyBQjG)UOPJQQnhX){ zjt;xGIG~}9>z*4Ivoj2ydCV*PY$$HTB6y{2>&Si%EQ-cZ07PN-Xg63jLV8Xy z$gNF0$1MuMI^ry`Vw(Ij`zza1h`);}%SN%!)`}TrWPzE%sQ}N7w!bL%LFxAC&oku-jzEgvzek;{x zew2)m18ED+9|!();K+28n7Q=Ec_)y zByTv9QSO~h+U&4-+}Q!&(>S8y)w~|)MxFCQ_BC&-`R|dn1W@*YX?aT=QU4;@^K_|Z z9Y5jf*4gLX9pc|KV8PaCiA$dR(!E6>^XbKUS&<%FB8F-S=1h0;U6cVs5SkYcM&feHR4 z%Fii11Ia;mx$57h*c5=!frrsxsRn7>4Sp$PjGFfiFS%jjv3tR5k2~Li2#E3FRNp@a zoo~OkRPmIR@Kdw^1dfs?<@W&g`x0{Nl89>AqY3-MTi)Q`_#H*w$6ymQcV1N!AY;gQ z9e2X&~fG|EF$wsaH z^n+76@2m4@&NooXqDRkOG8`WqY2HVEERKHC4aJb)s5vPFHWT`sl#oBVmVUpZQhc|I z%(Xb2dsGV`%)~HLB!M9O;5nn9*)#IUfjMtTSJ^=?$se_act0mj_Nz%Cu!5swv18A} z)_LUbcv%M=d&EvNcKpnYc-x33*M$i5AF+`uAst4l|LMyX*$+y*oi4}VtBSveJ4qbn3?U5$-7Nka1Br${9i9N!3JkN{geto~XU;OUh^}Vj| z=SpfQ4MJffB`@!oZk?CEj-1ncD0P3)MrT-atuV%jt>B&+k|(oruJst$mAIk8jlgV=)eXqY*1Z7J zJsKt9FQZiAXrA7#s3s@AkWSgQH^dc^OdK@UXI-e#SE{|flsN%tZW*w{r+EA|o3qt9 zhjfd8BWJmLxm7bCdB0fV!^scsmy07R^nnu3y@`?o?CR{o9N4HPlJ5|A4s|B zC|lP|gVbL5p(iTmu{MbxFXxGwPjG{u$w`}{wF z@qg`Kxm(5pm%<`GSGM*|=NN5)uKxcUp#?g(wRu}2UY#`*?D~{Ci=Gv2xsz*Xjr)@6 zvx?FRJi(B06>i~?GVZ4MNur5drXx+6(17R6^qEAM^fJ_+d^^9F8shVuyJGO({Y+o+ z|IM=4j|3X&?fl1tq$-q^p3gGU^oY_~)6#}QWB6-*5;27>J^u5QpLO@(DQaQcCR{A= z)FumYmQ}TmuxC75CCChShu81V)f$+4n#97W7fKE~kV)O;#G*0*vz$(v7IemL$c-C1 zTDQxVID!seA;h1^xpSy8-lb;vb4|Kp`Jyk$q%;WY-U63o&B%IqD=xOB!u~qs*Fv55 z>{6K5obZ{Y%#{pxd$#2-$=Vj%Q%VkN@iL{Lco5m;xHHs)1rmL)_9&39lWX8QCyGu} zsSLQ?)t~uB6lPUDZ2SIipLOTQsVhFSH5WZaf+MLZh!lYeY(ZLXxgh%eOFoNWrUi2R zb?|4d^XGDD7nS%!+~?^}H}YpOZKQ!mgPcB@^zEB+XTrfr-%d#!%bRYusqMP_&MA}~Sg{`5P(=lqB5+BLC zAvwxdNDMM@H#Fx$YqgYQ+%*tmG8w1bu>tJ6cz@7+8lTC=a4by`3C|wtQ#*Zf(%!>| zRgst{x0{L2e;UaMNgfXTkAmf3diZ;10QL>jDK&ul4@IT8rQwX8WJY2k@6L#&m z=D7XJ=;^U5hD~bICtruNxL6XA6|v5-*Ufem#(3eEankZWWjLgug6G|w2>+zh095&q z1tFTW1W7X>39D>9yB2^~l@Tpp(P5JJEwTFLCWr>X_vTLW#-!0@=C2=QUXzmm*p+ z`c|DtO8~A2r;WNj;fxrmu*%x0dRpD$TcD!Iur*A3F%Ur3Xj=E|TamUcdOE9S;wwws zSZ3=P=@Y-AMV;I8>2h>wo~}h8ivH-%wx**#0aBWtv~3D8b%!rkmS#NU1PxwJ)E|hB zOmY7RRvGdk&y~z}i>q6_EIf$%8{dE$auidPDsC#9wFxTxa+>|+GL`ifma_cSScr*F zT?#4|EN8U0{)|AFp@`%9|j3QVwS;n>F$1nm+xeLa{5p>0rwE|sAwoPz}3 z0JtI0X-AV~XEQh6S%`aEe(XrOfS)-! z)wjX&JevG72I`;ywwD{&E9T%du^T9dDlqJwbAEbt>6IJ7d`8mm@8G`#AE-S>R{MAe zMh|NNuh$=P?>eTp?OO*$m%5Ih$y^DP%oxjRiGJ=_W8Ta0_Z&9ig#z>qWHV%5D%^cL z=7+QmKcKlb7UNz_xOqMV8f>*H%oHu?e`%ST-X;9O`4(Ma)XiN>MdZK|v9kIzeqF6% z^J)aFd(!Rwb3Y%b-`q*!&pNf@`-dEZIutDRsRS1Quf@;Rh<8`|$fY<%T&`E^4nT+t zS5YRNfQ_Hgj|X-6?aytGpLe1P2I|)QmlJ|84@-?mUyL=!2in z1kX2rR{F}YcAKx<|FW81-JDfnDSd7}Y8$M}syD6azHR)!CNOU_Ky{t*$II!q3*K@3 z{Lx~dUsX-QI62yL{#?MHo0BRUfYq(o8BD=$o4pYXS${#77P%Xd zky|nI4j2m*9|#U~3~E~SapsGC*bMz60`pK*xjZXtN1+j`S*^L=p(C`j2UK}q5^d+@ zu|l+j%b?;k@V)I=1rGNN2Zd;iW*(@psiQQl!Vi?|&u6ui(Sb;fmYGx^q)Oel0` zrZhi1A=6sj(_-8wCEj2Tgylxcc+%=e>a7YiJ&|fh>K8(-vIyuRCy9mKc&`%LLl%O- z!O|BR_lgDx8ZSul{_o1E<`?NV=5HMwc@qO<4{^GBE?-5QCd9?uaM!{Dy!W!O*8b{a z_$Ic1pB=|U?f?g`#OJalWb58tSdG4(z@|aCq4@G3#H`b_u<^c>Wb^%FZ%%+6*Csun zDRk=M5ddc{=cL}L;_$|AJz6cS?f{k1?^n^RXkyx1PkBdDK$tzM^{~Bz?%PGmlO!B* ztnrL#U!WxTQ!h_*Y&dIkP7&efJF*9jyUGsPQ#`w3@7||uSXr>P61Z(N?hx@T+sO1j zzL=Ttd3CpD-BzUba=K$H4BF{iu}j-3R>RE2#aMHh66Y(LM1*>!9cIUCR35fa;Mu;b z@)sL!-`-0rEFx-xjs0@p1|{%0fJ_;l`~}nv8^@o646ZM;_Md_|pfvgB({>#+ux`q&0+< z`RuY<4E6$tT+{Q$RK@MJPE+UQQkZxH{7|6d{{{3tyy}e@bRU^(GwJ(}i6^wO2M=lX z%7MO*C*wrZ7iZm8hXXTjk<8&XM$0<*=VP&y8vkP93khvzt`<_##YZ;}j!!uCDG~03 zj;&m5ovoGJayNZA$IUryoN<4BG)MTzYo2}(UccP_sW9Tr85Z@kiwTy}bTXI{Fy#0Is9wPwAp@ zDP@Ymx@^7G*-c;`(}D#4%EHO=h->34&1A1ZF!Fs>P(@3j*O~k93FlS=)}*(?0o;V%>OxQh-&S^Y zEOWwiNY06x#C0=;9)b-vL@AH_WQhK&Cq2q1sM$j9IO_T(7r)Y77Wcza_}y8qY`DTj z5`7#*OF?s|qPA*oE1wUPd_LmFGcmqu&S`{N2k_yvwX}bbSow}yB%U4e)E&}DvHD?O zA?eJQH72rRzDd=%QLWMCuLQ5WN!p`|I=W0)4tiLg5NCMRy;5PNw+Sw82n<^YqVtycl%=FX1tDIj5wz=^oy`H!}5~;MZ!%JDvL*|OS!)scQ3Pdp&7mts>vjAWp&f9 z*n!CggH1hw7!8Eph0-^H@^WxD^Sg7Up0(3glHd&N-I66dxsS>&#E=F)7=sbQcd^)2GonTe42F+#E7{8Wp>r`p7-a{otgd zs8!NOO$Rl_!Vo{!8|z*z#o#qH=q_fN5aTGu84m~~cvPi0(*ezrNR zyouhV^mE1uUsXwKY+Ept?V>D=ETDRfb9RV!Q3D~hAPq;zX4ru5Nltiy?I-C#k;$8C z96tt5nrCuQ`E)>t`yiAycek)`L08;BXVwh)BX%O#lU^eB>-%a}3Rm@!M!6TUGHG#| z$GRp(mvb!nxRB1Fl5ss;Ya*WyrAf7@EKMd|gpHbc!u~B>xxSqv-44q>6`3d= z+=+vbI1AYA%c(`(WLZQUe~gPReDT+|OuUv5cVo&}Ele(7Ygda{FJ0O0tTY=f^(Oh_ z>FD}-1iHSyzv)n_V2>8&Qtt^m)~PMX!xlKNeM3zkUFU5kfvm^CC)Es-eEe5<~(chk8QcdVm5KU(=r*oMLmE8VdtC9s@GI*=Dv@x~j98Wq- zjubs4u>E9oQ~Osmi5ox*nI;DgyD*BdPK0V<8uMFl;0OAK$x!-gv(qn$-=nN7og(}b z@9VPpB^EVu0z!21dIZx}|MpKB8WcQvk!g5n3Wf9`jA^5Y6q-t7RSmNvyusWZ#W z>wW|Y4R0~;r6{DD9>ma2t*{~2xRzIwUauwN5Yj`>{g@y~oeRsVia`hMgWSJ~^=Aw% zf1K+e zft_W;h4Hb*uz=63RS6HJi>J_XsWoV7*MH?M|bK(S+ik2F3 zaZSt@d;ELgUR!zB*@hQmXwcuW+GE+LnNC(VTSsUodyz>jzemo*0oKF9s6woP~ zB{X00j{Bn=ob5Bo8~ONieu0nwnU_H9gN~@S^gm(-p9qUzIpBN8=Pk{L=Q5>t6Efb= z#p~qrPuiKlqBoBslJ0)4rl3a$cBd`kYI(twHJK8#*|lyrks;iN{kjjYCHM2Y3jkM+ zWT77$*u>`^gLn<`zQFt*oV3EaolJuPl<%Jt-H?X1BFsf*$h>=3WbWwD?5^k}$2X)x zBRUV^s>VF&s!xl-k1USDUg*^nI0#mSO}6YQ!*Ypt_X6a-m^0&bX)SD6e!r}{%Yaa0 z1;#9#*o4T9e5Etew%P_EgjB~3=O;V}zz+GGieGKp;(*pJ?ohsxQj8qy)r4-%7kCc^ zs1)e}Y69dVIbma8e>YC8eDQC>tvl;8^F<`-)MxZD-F+DfH^fS!Z#~mW%{b0;*~nvF zcLm>)k?_%y2}tifc*d<`*U*4e*eiMy|Lv0d!fw|3B=JkLP?dgSHEgzY3L(4SZPW1Y zfm9SsCJY;h`tjsD<_}=$Z}(TD(#ZF5=tZ7;GCwzi>;3y#J~^^GZlKA<#yW>o{^jqs z^QRoMUznPI`&mqBzXMjYZ)F#%K&`5q{r3J?@k9s5#h=yKrn$v8S9l|~l0VrK{dR^~ zDESLM4F&%0#WVwbn9_uSlcMDJV?On@7ofP*KD(dvTF4c72Iu$S`$zDoYxg3BL5l5| zXXnv!mYYl=lW&(Rn<&v_+#V;l0tkONWVDY|D4+mUj#!GHewp!WbxhZZV%)oZsZ2xG zK5I)|EZ~PA_;7;e$BxxL_%3rZpOx+GEZ5DSnn$WNm!#Q`))qzYg1gm(sBpKXf|3Ba zk9%Bm@6_xl#23kPdb;}dQZ8GG_UD47pXNGwF1Lb!*0a-x)Wnf*x3`v=4x?D;uxI=Z zft{Yyc2+W!ky;j%Fdf0NMc-Z%0`R7UtA`{Hv21S2SZq^YocDNU^Jw^2&!aS~n0~aE z`edC8dM1D~tY4pC-YC3V38|e>DbdC{#!Xj+Bls$%N%u&n-B~k*_06vg50FsQYw*Y_ z5~zIKMi4|Znf4d~OPO(&nv<(>XRq#V4Y9ybYxl2sbXGVY8>zIEUfIvl#(cm({5ZFA z=UVu5*T@-~t{*NX(t8KI29v@qdip?PZ%Mm-RO54VqZ*)AG+#S_DEeu{T@E_uAU-5# zt-{L*k=sW$WWqn@hI+WK`__FyzN=>Z@!slM%3+#bHcBYH~-XM>o7nFt091zy~Tk6PR1Y3 ztzL9-)Cs0BH^vg{#JY97CPJ{P9+Qv?F7=mo3Hub0aTOc zYxd&kLCd&ubjIVo{lcreIHFs8qqvtY3>5jvkKp;~uvl;Gl|HSupdg zO6~#uvGD35M~cxR#rP~S=@$NT=w^g2Fa7xnNaRCZFU{k-^w%q#XIQ{viJM2ZK2^VL zw@sY8RD>OwGI2a~&$0Hqw^Wb*3Rkcx-oCYlVi`m#+bn{tw695IzBLm+0!2Ftck%zn z6z0*~?0o=kZ>=*ZoZ+`zoa`c`mKiju!_HNKi+4o(b`jZq`zyPlEdA>XKQYUD&5T|j0WKvUXfn3*b*TJejTdqf+h9u)i+tD`hz?Nh{m;9^eg1K z$&-|ex6ln>(dx?8g|Cx7MH2qd)9)G%KS`bEwmK50ZSQ9}Bl8VxH$WX5Y=o*Zf!Bdy zPkf(4*DZMCPA>xlj;Wy94QPA%GsYkHHhcopuAL~_5_Tvj?33`3XN5oWRuAe7m_Py^ z?u&HcKN|*ol9tZOs=dxXn7g}Ty^gJOyU-IH-@%`?=Do7B&nbbamDx0K$es3gzNwC! zYXg7}C``ElweW7@n-}L1)9MvI<$InXP0Yeu9&!dk2Ha?t0?{`yHw1PPxIXh|$Yi7p z3nsB@23}PENd1jUiRSVc?|*&q5s6wi?Y@we&X2hl=2I1J$4@Z zr+XM!Z~yQkYvw@WWU4GaCoG(sx3uh9_^^F&LzG-U&dOV;du$EYB0JObk@?pK9nwT8 z=kE!nwH}GMinqE9pkUIj3{z{#JCJfDe1m(*#~UOx!7sAZwy^0DW7H#NDWkLjo3-$1 ziStRo9~vE~+K1VE{z*O`j%+8B+LS@0`HkmCu+p8y8cFzE(g(wZrcm5AmqTKn6sYfD z1X_DB&QSK)q(hxOcAMTLHS{^D!@ zhw$N}R7kLVd5lpftch=0tY+4B6$0b>S$cki2up%T5dWu<(ap>*f({@p1G) znJ`w#8ra9r?7PD)yLXogKFVtRY7%4hDX}_!uas;NG*Sgqi{GeJ0O@d|3(t$Gut zo72|VQ9p?Bxp8x$p`pS!ce!lt#iOX?IVkpSI7*}*hJ!;`$%q(nGb7XKj#`^XJI&l8JW>Cx4Klv-jbZtf~IW9??dJ)7S$;Fl765t7+2v(od^>YFopBm^>f3}TJq^!YAYx4M3}`V;t(=6vmL-6#@i4MMnstImUS=MRPhh*RQudqPiD`Hm=Z_)uS{Z`7MG8`W)+&u2hSY@mC zSvXWgRf-xrOV>5q^>@ z$eCx2)VLk21y}elpMyV&mybl?*UlQ-48<(9&c8-{k*YcD)99ZWQDnvW<)|8x+~FHr zIeI5GQJ&#AuQPfo$3G=d2ayxlF2bCN-kc)TT}!3pd*JKTF5`WwZXjb!uUbch(|p7P zXR-XL!pOQ5INU!oj0X(35+lxh{J4(uT%^7>Eu=6LohPx(ul*7iPjo(XH742POjsqM z$*Yygs|L0HS74qpV1a9G-q-=j9s*l;nT ztZN(0nNvFImD7WK9?qB#0Xa@GQneF(u1E8!F~kDz;-a@%SFgZG!t;7n|)e3$BqNGuN&N@HMZ3%fG_$ZeN09rujA}~4$?eY|L$9V zbiBo4)U$hzk9SKY4`)(UoBRz~=94$g7CUaPdj|lHQStbPT_7CBm>-tTQ+&~Z>i zxBnAvXyyKihDVG!3ZQAf$=3mjx^Z0iKdYbH#;pZ){aP|?C8nxiiGl(pG2vp*joTxc zsxb`Y*oo~WJSl#;WHVe;mqARW5TP^)g9sFKUF!Z?i16ZRtCjnnUg)%4m4A_Yl-CCQ z%jiI7-96r#?5Jig5kkN8HeC`fm2agjHE3bcQ*`rlsNKlK7XXTHYyLeiy=Iu316j?s zNF`vz_%&ol5)F(|hqVif#0}2zXch|gpyr2&`N}K^H_L)&(L>-wzg`+z^fJuSa3t|t z=}I@MET1LXRD3PYu4!fk3VYF7X)yEpV)>WMA}vxs_+kA~j5ymG%h9lGey#EVi`{7clC zPj$17Z1>ipiTv`|qujbV<1L6Zc(wUO%^qxWL^%s(Zc+dHr2(dKar7_*{fG}{KaRv- zme%n8OgUnE22Km@viDl&(L8y1B#{vtl<7lA2!#y{wVt_TA&%=vsbLe{lZ_Yt7o2WV zs$ZKOSV+TcC_lq_@#7+Af7K4%Na;Byp`L;GrLaR9??p8~dZZ0h5RA}=n#dSr+LV@pJ`;dD`I$k5*6JY(h@uwiyu9=c-G?dpBn`7>dt_(f3?J z<^zD%q(HWc*9h52LR6@MNaAeGeUMcl_jbr$L%B93J6`3@@^Tx?Cl7-dH{r#xg#nCD zwz}=P+h@|c>@{3vITSA+UEQn2-n^avL#rR;XefeY`S}AO#xHwlE6stW@%J>mnAn5f zB#JpE&#JpSNESf0Dz|h6B5v$jW1l~VFZNWd22NT(V#bed0(OTENi~TPTi*nujyuu>XRyu^gyz?$uUIT1Q@L2uE?B>6y7Ni_ulg2y0B163OF9PDk019Jr*dhr zCTXlAl?-^k>y-l%*ILC+08C>Z?&^L(MbF9zur`ZiiEe=E^7x!Ead~p-PHr@JjdiJ& zO=&&&Rcj()!M^Y`vDyaGE3)*--sH;{f9W`}m{IB7orLbOH%hwmT7>{}Qt518fURlBsng+XL&|w~;THV1b=AF%FVVZbtIf(N-%4yfDN@2$C)+xHV`zhm|6@`bm0P~K9?@<)t*{B9oX^4@o~2fb z6OkcAsY55!sStG5P7V zh~oW~PYK#(PM35ME^Qjx#iu##EpkAn_!bocKG_BT1|-Q|K))Ur6hB{I5HJSe7=qn@u*zXf1zrbTF z)%vBZEw{YBil-TOe8;~$`|-r^mHuchX^i6OtEJkCFjJ-S7IaUx@+gcUgFq?!s{&n8 zm1CZixIE^d7FxGYE>tKU`Fl70W{AeVl%bWoxRpRvh?(KYf~wMid*+b~Sq*gmUhaW_^u1!C z<6Lc{5PzAcGd$<_=yX1vP-s_7kD2Zvo=6Yu3%D%(O?1z8f<4{t7quiO7P!2eq6XYJ zbZPt6{xo)I!0MPaKT(9OBVqF`i8LvBd{YI&@;h&`ewslHDWps1u!d9Kta$T$&(mKq zV~tN(liMn|`>wXI3O2uqNzfcR%~gR?G0kzvF6}>Muw;p&$W9;X%{`9@pcZub2*D?TL6EWw?ow4(@+BI= zA?dLKykzkp{!RSx6~m`t^D326b=TmAl5W-nRf-47THCt+kz|>tDuDRv+KxL%AwS;Z zp7dA-K*mfqN#EaAs{jVLHZ8Z+SiV){56G~jFBco5=qZ(mZYdW?yZVhYWQ&CRqY z&fzwyu%H_de)}tr?Kxl{2#=zLteSn)Ojq#RA_gWcb1LiZ+uyYgr|$r%7I@IWuDOI?4r2T0nI4mj0v90hpH276712S?*kD}^&p#1U4Fv- z5sNDhHZA`CGM`=a9}~T9`Pa|+5OWHVn!Cx;cNXQnm(wL6e-I#-ZL7%KtVFG%&I)b~ zk5A~+HE2;eBZXZ*23Pk);tebo*#|qNrbRBk{%tsM(7fjbaF+JyQ{~z!DyC0fA$-u`>bN77JjHlIZO!-!H|QZtVxWFB9>B!BdP8W+@o~7C z+GRr7RvNC>bniFUeE{%4>P<6`Y_v(#?pUp_u!bpJGnD97;rG=K`$q0CfGPH~bdS>Q z7e^7vQ;jl|;Z}VXhaNb$I0{$ZuI-bo3}k^m`aO#%&!V3ww4v+hHyGy1;<~$YD&Yi=x9AUJ*{tfQ_V3NFN59j^Lj@dy4ol50)U z&jcbCVrgd|HOR_?-P(Scs4qn;@hQakI}%NKKMcINv2IEPvhaXzXg3XbTNl>fhNq?mOjxb+ z+kYf_rK5=2Y7FVU54%MO+v>+sh2itCqi0Xu->uJGm$_Q;#bSji;4RY0Q|_BhNzNWq z&+OuOR-yH)HH<5)$M6x$hJJtXi+qoCs+o>Mk1a6tS_qV=o=%k^%(vFqpEBZRSQ7H>3hAQcUv7!1GOX)n=zTt0@>R8 z@aWt>zX&b&XLN3B*}K0wG(BR9K>PQhG~3|ID@s$2>ziTpYB0>-=_Hdz7BL;Gd%B~= z?q;OPZ{7UbvajGToATn$Qs!M_RF6OyA8EN{{+t}t1>L4NAgkHq&oUvyKJ^Do;{P!T z+*{js)&&>&tD$E46Dxw$u8S^2#4~_wYfod;Ya?jZR@+??&tgPbP8&=Y20t2~(24;Q zoB6gV&dho5^f?hkT*Q|F2T)dAZJW$S)2I;oh8Dn^6*Ze#--=24jxE4(vscDs^NK{>U;+M*h%z__Jk#4_!yGJVAt}YORuf|oE+}G^Q&jvOgJ-NL4d0H zPliuIzPN{i!^fX!JzdDV{I|GKr>H0)9@zQDzocp6r50*CQrC)r=k$*ER$y|s&me&wVBOCgl3pU3$lkzeMAxx#ndc|drdCvm@|877cg@1__;lW#!rI^f4 z8#qcP{h49N<)tq#?4Wcf8wCHYs`QBi`GKK(To!lno~{2ft^OYqCz@fJ;uO+WKOY;I zk)_MEE*f-h8x8)vIGoU=*WJ5ceN%x4A8Yl2!<#pL>;wgDpgWArZMIf_qV-3!BDWk_ z_RSRym;Zidw$_7I`F>iGllpgyh3(GE>*w=2Bt2lh)AlTf;&x@2`1Pg4*5f~)o;U~L zW26$FJSi2TfsSsX#OjSN)bhEmsVfKrB?b{-GUc6Ar94o*7Z4{i*Eq?=|_iiMgz44(v=9h_xlmj+8g!6 z!Kg0AuepCiDgz(mKfAg-LzBkHD)xbQ#J{lBlb1cL{i8-|0$u#6$?NBrgTIGNW!mT6_Yf-5pn8^Q)ge;pqNZl=JUvD!jit+V zIOR|^3aZ-Y3^{Gsx5Cv+- zjs`8#irY)iXva1c++bEC7G_&iIY`CM$3 z%j>)sM3prB^m!L)wlCT`GPcSh{IqTr-1Dd;c^HTe%ED|))v#?&{i;3!2Z57?)8xMJ zm6saSWo9z%od~XY6*-k;FqZq!4heHTZPZyr&Qj9flBNgeY%*e|LdpHZ!?JS?o} zdA~ht;}`&!8mX-=7R6^c_%{(f^eb}tzekGwOK;5`&@B}g)u}xgKVrCly3%SBi-iKq z$j2AKMg|SvUE!B*oa-{bBe?|*^L=N|hE}2UXJm3$W^u@@n49TQcRk_o0*Y(cuoU8F0#Y&4I+Ya@9 zKHOCw3)Cs_Z%qu5Ijo&;@JQ~1;VD$HD+RjS*ycEL_GEu3Do=y}6aK)(O#@%I<4N6nZuyvyVOL|mCj4ReC?b?DTZZx%U7xs52ov&#nRUYe$NJ~4twFJuU#a~+CdjR) z`tn@-aA$rVIWEtZ3$+NwC4k|n&_w=oO%3-4&!K62-%_H*X7~*~l(Iw6s$b{ia*j#v zBkkCTTaVmteshKAHxMb`|D^M))PrJ&#*ShR#RWdL6hsJE7&>bWM?r2hD!LS@Urb1l z6vBLKd4Cv!z6l>^e~{-3(;HElWKQ)=Txxn4p|lApx<_-Bp6H2uQc_)(xdq1LHU``ktDl|)QCLtaKQ(c4doN@7)8a*H;h4Y%mxJOB8m?|)Jd4Gs!A8t{p$sj%~eZa?E$|Bnf4 z1onNA*_bmk)P*lJN})^h0EiI{(9!(-do|;tj-0^=O1i4dQrUwd1rt)_!NZXVZx(yC&N#r^ioU zxt)1%GoEE}aPTB4ZnIWnNPTW{gPpoD5C51OS}53OTlBd6+%4~6`ny|Hz7N#Fc>qTz zP#Xo;Um0=#yr^T17PW`awX-{q_zk8nI+8533$I;2G#OI!{f}v#oejhz7IB)c%_X@P zH7!wvIuNG-|7gN2gY0^CiD;yne3`*qMT!LPLkg9f<9*UrJdKWfpLkNof62>s2y84` zD+r)#x9R)im2wH#ckN*hJxaA#uKT6PhL#t=8q*eVPoq>nERIhNAsR{D^ZIcF0mp-dAP&l_CHhvaj_SCK3^1-nVFVlIm9I?bvows*omSjD#W*X`L#aGA z7#`(*sU`_swu)j>;GQt%rP}ed5uFcrEGZbd$3$RI;PZXMPl@DH^KW^6sHLvAEni%j)L^@K5#iKS1y12tVKOS%i51$$!mO z%J)F~VD8fnl52;5i^Yi;Eg9!qCpZu6*;6a07OPm37DDT5e&L5fU!}nrDs`7DY76H2 zNT;ap$G5fm(HT4e;z1s$`(JeMgVu0~#p^BrVjk=nCtbuC-Ul+7IaACN<6qS_ow)ie zq5}Ns#ceF!0`AVw9sEMdTD4TT8?FV9;EQGr96V7SbAHfw*6f!S!0C8Cljv0eou6;Z z@P4?nE+4OFy+0sKtJ^EYLSG~t{8cvhv&u~l6n84*J2j1j_uW135j+UwzeROHV@+h% zfn2(Qb?j3@{BPM2`dpqHvTN)8ZzHAhx7`OrLYnrZ=PV#+-F&=pP@`UyEvFsu?@d?h zv31hQHTMhIo&zl=8cqjMr?=EIx>Gvx^gpI)!TF4B*Cjl9`w1Fr?xZMXa|tJE1z+-ZF7e+S~o z(bCFu@r`-h;xH_9dRi@W61kKzk}eU1bZSDf)S@4dcyO;o>=NyT(adY>V!JwmTb!tn zn@^*j-U>Maa2v|1kWa+dC)=#mNS7sKlj!KJdG37xuIdXTI(XF!aaLkL=-ts5<=oNe z2j40lTdl$s`OCt+(>zaVOg6l-6CkGrEX2w1=Ogc`g(&TA&~L?|ztoCnpUm$C%a^XR z9lE$ZvZ1S#TF+r;Y_!YD)G2#8^P8AmxLo<%Ic~YsPz>QgLyCT0oYQ9gUQ8Gl?Baqv zFDMunNwFGjsJV>2aO%9v3`T;(kDx&ezbKv5QEEMtsOZ&*nSP_Qdru842seP}z zdcAVBrahgZN+duY^_<*Zm9{RIaRh|c4HR$7xHH#;;iEu{x_v(>xa&fj4s$ zzrZk;AVV_64u73F#b(&G*4I7*`5NxmcFJ=zuZXL$O23Fg1TB*XJeks*gHN|UApH%_P_MOk_6p`nf6RPyb=tnGlhlC+esjq=QtI`Y zR+li7Mip@~u~qdwF+R7^jX#MKQyY5Td-`c^QgtCIylWue>cv1Y@G=4l5T?A`W9JeL zFW_!xFV0e04!A%9l3I}Sp{M_1g}|EaNjUPGz**7KE*%qJ4~ABlW-nSIS3*Niy$^Ir zrxW4unkWpufTz+$w5r$F!J0DLF4Xb`Q&~#%_#|-f22A+C-$iRvTj8W-yMTXjia&4~ z2@xIQdyUFXbTZS&N-T1l>^+5iLCJG(eix}Op0-EIZ_ExOR`RdUl1nRi>x8=z&~|o@ z*++Vb-FuP)zM00kX19K9$hoU?*peAxJxL4^x7A4%8M2Ry2MggOZl37kCa*`y(&Qjp zJot}EJEB!WMbhy>g)`&}j`~*^*;|>=#a>|dAiI}xS?gslIJ@~!ZN(@qH{0oFoHqSN zXKSHKngZ_Rg%8qtz;%xYh7OOe`V_e%?HiXIF z-^fxmBQ)3DNY{_0jzviBarRg5Ye@g%TP>5+qxIO@2V$we)PL3iz(D0~4pC3@?Z zoMaF^@Z9D?&9Hw_Yd(M1V!`PS`vv4O)>Mb%|2)gF4m>rDU^*`>aZlSYJ*skLF}R_S zefl5~NsYlW-L^c}kc9@78fvk;FBa(@s+qX((X=p5+)1w)@7JXM`|$K!->1%&fZ;tRBw zT5Jt<>fwVJF_PbkBWb!h>~E$`wn{x*!N`7H;(-?H=`5kIWm=$;(PugrKecPhHlbe>l4Bi==nUaK{sWE<-Q%2#N025t1J0~V zI+FpEWNrxHIVnP42i=37lXk7fX~E!9Z(nAg8`4@d}|1AF*xo zif&*pSmn1_{+&uITG5VHo*7AAd@RzXV#ZEBR`;ORGf0tiec9t$U;Kb(4^maQLM*Tp z1&DpsJWz-Xo)1~vkTcb7YFl;>FN(1oE|T&L)Ms6rmQk(fPfL*wFgMa(QvCcBfjiB~ zn$cF&qdyaByF|5|cbK-bB~ROPE99&UXYanS_ki9b=R~RRO$oTk6Vxev;zu&Vm)*$% z>maXow)M%7^*;@ptzGI?ELpKZ9Qetb{gp_;jJ;=C7N(w{xpd7!A2pgg_h|C?{oy>C zUCMITpTEP;d-M7;#7n3>t1UH2yZa^%ofUVjZC^_JAx|a_~edMOaJ0ht_m6N zi)h@9lN<~IC{6qP8`s>zxT;wkcIegvr~7_)5upxnv_JR|LF^@|0&g7wxebk~C%66& zMduxt-PA934jvG}q~yh@%{dkXfl&dODqBntL~JD?*}Xn&{EQQK*^H9>>g8 z;6?=pp;BgsfeR7Kfglc4v>(4e_~UuOKiv28yzc9{uFvQFnGL_V8>nrv;lP>Yq*QelUY>SV#zjG}2Rz>F@{@zp0 zwOR30Sl$IWa#@X2o#la~fg}^q!9H~0oi9I+gtSwcLHka(&VPNa5Z!+-AtuWOeX4xu zF7C)u@Y*AU?cvIG2vw^J4JwZ)^R_CxL{{oF98sqCKGV8B9q|~>T`%S9#e$#G{g{*` zgVk9>@xW&6{P09&uI(*zZGuH#m(P!B&Ci#Ysq;r*c~>W09f0>tr>u_$`5Mi77h0CS zyvBXXe6=7afxDG}4Gm_r1aaX&4XkpbQt#)1sD`Bv?v;Fp1MOY+2z82=+H8K}wmS$m z4V`ZfT3ZS9*8J{z9~gT7$S*cEI?{E}$L3>zJ#I$ajo@j@E9{d(8etU<-a%$6c1rYW z7IgozREJr1$k%KuTbZd4J2uQat1oHp@lV3_VwRyz;MA!_l%n+K-HS8o)9n-PeU0JzaV&9 zomj^k^1kt(s))DgUQcz+9x-gu)TMC(+9gw3cv{bPBQyxsX6ouD8#l64g zew}MxLq9vli!EP$%4{LC+PDFP(pbZAkS%PAqb_j)l>Wpo*D1|QIXn7f<3n(8yD^h0 zfP!vUhwmm6#YQN^69S;1o41c2a0j4A_|YQ_No;AH#8^GLCa_66Q0FMcicL{iZQert z7RI)_OO<(gEE!z)@zhY3SNuceEGrLZN`07y#UJ^{JePuo)CL6|O?o<_sB7TOqgdHS zeeNmZUlF1=b*9MSaowgu2`FmUXKM3Y;i@5xMz!AEK=5=2260_rG!?%OQ@QH9(lWLh z9Lfr};hnPEcF~IvnL>2HF9SEV0NFX_Q#R|7tAp(R2Q3Rh30JU2z5GU`nqPid-m84q zZY!U_g7@c^$ci}!X?EeL`kgYjHCHE$`^YIoUxH&vW&QQ)h~PS>m9ACo=IY0pWBzMk zY3iFK5X;|-ZrDMcS5f$e}KI6S##d<*$gytsjARsp868k3Tz==2Y4T+wJAw2 z@69>6T)z3#ZWf>yb&HD3A1%L^$1Z@^V7P(v*650Y*FWL3#oP0g}Lu~!~3)NEdr`wWjOs1CNi zVq3}zWbdb*yvUTHq=*%kr#;M1F13!ULNdP@7gn5%>^}(!h%5=UOg*1fTb~$32s>T` zp`toQ2TX&PqwZ_O8uwc}tzX-8xE5@+B(L-WII(F4ytH}dxEZT_>j6*K$s9T`g!KP= z2O8mt;SFE4{yc9;w>_|G<%9-cUf}a}P)1|Ju>IlgQDNTc(%HmOd@6FMBD4NhRy^J< zXfHHs(Bcarw%K&TiSms-TX?2IfGK&S&2+W~x#A3{scWsSc?@Cw^YI?u$9XiTuvOF( zU~`}`)lxcA23{fcLA`3IUZy+r*iQZ5W#h6HQmY%Bspt;u8|{MNM7+FbWJE2(&cgFD zCuW8%ERt8K(mCkT>^!;aT=xjuBIVql@u$7&Kuae$pgzv*%`7gR1F7u0*SRUdUN+3^ zR2|4b5c5HIVC9oI<8hE97gw8W$&{8HIf5K-Lh3Sym+BHW z+#bPO>NZmeHrfD`(!DS*T!0t-W4{E{RGmDP`8lQvW9W$J`!=-ZN@nX5t9MFYwVAoX z^=Ms6nVY&M{j8novS~wtG9fVnE1AE)sdFrYsY{`sozr~7-OwwpLU;q;{2-->l^~~w zkGLdGyV)-R{;=*bume9X$j%QLw_n8?5wVxX+=S9)_vVdp-S)U{+)!EbETP&2a00V* zcRgmi9!v|H$w=IQwMk+^oh67!M8K9+$;sxe=*IS&!3ZbN*!gobYH9jmlTLqTmzi23 zM}fFtpw#3RHUQ#9-%htcY_}fu&flf+?DPqqA4DxER6P4ra|NpM72ykyzuY`UNEHC( zgbl&$v|m!$I-O~L7*KNb3dAeVt^_dxlkM9k5M{=>?UmU~z-B%8UZDJ_1$IA2So&0E zKXSSD8%2|h(@Mp)f#M_q5n@T%DE95|QI$RR9$%0q*{Uw255)ARsXlq> z@45WMNP_abP9+-Zp>pb8_XtY04^}e3{;i8beqFy z#RUzo!UeJLpubMnT$htDYcN{>p4$U>lud^nRdLWE$_2z0bVrd@=AQBOIs$)Gl(K_z z3|G2Qd8 zVWf^o2Rug=G;UA|yP6Free2`fftHu3nAev!zHblvcbGV}-FUg(^2HF1m~rz9k7SM^ z>-TuYn|iL%9S{%fn@{lzT}yG_S}qqZB_?}cb<(=~@Rk7SGTtr0-amY7)m7cU7qlKC z2a87r1dy_KqS_wkD%?4@F+1vW36Oj4yybk2)rS3Kqh1cnk}t9W1>?XPRPzu}V_2>c zV-NubX5!U#lKFq%O^+ZbxHIx}??q5UHHTVa#)0x=1M5Ct2b^NHV+_DUJ)at`qPChd zljtaGldD}V7amv{O!r3zPM0QqNUcOavpO5>=%^*gy~&5*m7zzvA^j%bP)=$=y~)oi zPN2mKZH760vf4^s7do$7-J{i)`#f=|hU+=TV268BQ0YA(Yc9V{2cGyA#uA#Ns=IiB zEU3;&Uz(&3B$1qX=alF!)qaV%ni*Bs$@2DROb!9nk;4#@ir-wdReOCBEpqm554pFr zs0bbsdkq#>V)8&)M$IhhKH;LJPH9Hx;Icqdi4V0!B z&}=Qv8;Y`bnfVT2b|4M38yM0%uymq=l_TRQV~LpD2GItXumYOBQQJ{r)a~D1`pDNX z<2%x5mHia~($GAgjqa)wt)Fa!*StXG^36u$U=2KdZ)~413##p)N_C3reU86*3B{vB zqrsJtP7;L-^HJk!mFDlJH<9fWyo}NX5dGc!7$Eksh05Fl0hU{5}-%K zuvJKvs}F}X2y77JK+7px&&k>?k#sJ)ac}Y8sdOE$?~<;!zgTPr&g#E{BVYg-a(Q3h z3Pb>CaU}w%S+npX$NCBF%37Ol#rO?d=6s%QuzivnC)_Qyq@RLifT&$>KDuY zEYzqYVU4DlDJqNRxdx4vvE~{~b6c7QTpLa(Ar`GhFB8Pe4cID-3COIYIKM^A1ggqZ?%AyCr`Y&zaHlpv2?Gj>zE~H z!wrI#$`gRSu_3o2`a?n_xTXXYdxlMe)|vb~@*^bObo~6*ech20-MFmDuHP1>vWj1I z4czWU7)T!t5g6DpV>_RfU2Iq0jGerh@upbP2ej41_I)yA#W7>6K0J0hpXQ3-DrjCX zDNPbth97Vt<|BNKvy6&{cxQ|vO0B=X&iE^$mix*2Te{_gvZ67#$QWasQ5eG4=$xA> zKmZMv>@QNpHdFmI362SzEZmF8Zfb%MS@a5Eml*@7ww-FVgoluBCtfL6k|~82HEiQn zC(q&Kxo!@OQT=>Uk0EmT_7bK(h%L9_Po-3#Rwuti1xESX2;~pberU>DRHv~{C0=M$ zwEgQC`wvj`k1xY0mGxOwA#&D&%vfx^ft5Druba-&g=^pCyqe z9z$spC{mvMyji|pq9BYiFP-@*ESUHu1yC~Ql(?E-D0An~jPN=*g5;L-ar0&VkfbdH z-?GrTJ{VGp^DF&Rtd2JXsum&~Lzi+C66Y%J9>@nA^A;A=R4=`PwW(0&=VC!UhemO? zhaNUG@iCVQk4$l84~(mS18(1cF%s&SSRjDxUNwu@HT?+|y}vZO0C}n5+P@wZ0?^cd zCUfO21b+RFu8wIu9wD7tze8(#NRES3)>YtH=vr7vH;V;I?dKQt{$&u>e=32h+s8QeWRa5c{X1uIGK1OnA;WcfS8Z6B2e5>Ep z2!Y^?E+}UyZ;g#DV=Dt6`{$VQvpTRAjYpE{Wi@1`>#TXX0ASu_eCtCFxR3fwF?>B5 zSgB=a2rcx_LA5}f9g=9?cCu?_hRa#6nvtb#$b0p^hNgo)5y>=5F>GD0T~#M>GlWC! z?)NZE^MTKF{;@~#i_f!g->%y(O;@26k&$d*AK zhovaHnmh{LTE^KlY@u(~bLlO&S|A%fiV2L^+I$BcFLh9m^~^drqNSG0k`ILr0P>gG z%T&dV^7^ih3!f=|ag*+8tf|h7!Gtfm?Srrg@|#cN@)fjDr|MpZV7|6|75OW}Exp#r zZ884lHl{+lc}z;caOz4i`k~}9=Dbgd%v!osHPvRf88YM;+qV(;3QydVI42~ID5*Kh z*wjSL{)0%O-E&Tdxo#pm2|~v%jr|dE8*P2q)9Hia{tD2&@8)6A?E_TuNo?*CfGrj#a$B+}~q@-L}L5XScFF74us9@cmRxw>-kMNz4ul3Cz6(YZhW#qt8t z@C>sZT-FBKNi0WJv~salpRz*YcJ%wp&(O0;eB;0AYVi}I9ONe4=`mDl&qAijBETVJ zhC6VrN=gU@W@wkt6=UHKgmvpFzofvM5Mb}zHZI?`M`~T>_8q<;vihBL_}|@E9X6$H z4VX^QBWY)p)V}6Wv?D6_^A6FJ^EDV01qZ|Tf+vfI`9ctfwNLNc?nbQ;KHgEWuIGCDOoId*m(VEveWT;X0tCwjO^)q}?Yf7W- zO4c;0&@Zx7zN19MELOVrupwErAjmy=e774D@LmxP2@T)B?W6yDFt5fn%^(nd-EzL| ziPhGbu^`q-u+K)`{pzBDo!wtjUx^GK=cy~YqZd|;nt?Ar|LnB>0Uw{y>-?nnqx<5z zf#dvaw>(bEImd|v5>4GmN!&Mbm~I_0x;nQ*%Gp!_BEXIoI!Y^vx^{Ij9kkByFNAZH z#+>JnQ=X+!??7)SKEUCD-=SS$ihtM6A{kNw_|t~B8UXqvW96%_$ncnD#> zA;v7mH!E(gGhYd=7upnx>XDXeGdjArcf_edY;!v{jI1-6|A?TEDttd5dwC$^;JJGU zOAPUm!_Iw@6AYl#GpiGPj4p{kH9+@%WosEw7a8UU_3rv_spv55C{gBT;QoB9-N!gV z>fGYn2WxG|^oubysOUD6xZJpP0cyTj5_CMjao?tzC$X*{WJxvvFzTWbHNI~$#t+LK z1cPNtk;VtDWl+H!6=955HPo?_2Zzp3(#Cy&2^v^A>bt9u9}U8PJ~7Ey z2r_n?RN-Dct(a`E7Oj$}eKyBZ4lhW)4a;kojVVtsP#%9#%-m5bm!Ku26?K85so|nu zQu)O~^CTtb$f7r-mb;f~tf}UAxfhLcrw3c3_g(cXmJR;^naZwQ*yl(9XkJimUrO^Y zu_5z6>NOEZ1`@<@Vl10P;@%Y1fO*+vtqplo9`fP0S8550~jSlk=5*_TW|O zo1v|+3P4dX!drQ8Jov9qZ|4>If~a&2Clo0=Y6X zG@zrwPK&6`!D#s!*Y@5^d6T*Hy0jsj#=CCYzfld>%{0{eWA@BbJ0uFkTJ&HF?!T*H50xxSZqKen$qP z0nL>q_s;aMp5_Cln^yl}>+BRjvwG#hUjC8zR`wi^Mx* z3BB}@i1|!;E4!wl>@f@Fqn}vXfHgX%zk0oNF!5_~bbptpBJHJJ%sHJ+!)}6WH8UqF zc|G_CEDpcqJoD!KyQW^!#8;yCRDsEtX+5Lo?Ss=<33PlwBk`Bd}o1L7x| z&+3hnTBkdD{4x+>U&3W??>BkC@odqn@MUV*6m4`dD?+N;Ad`AH)WDl>EgH|iLZ|l^ zzq}e`rEk0%9H1|Z?r*zdcJVz6q`cRQ0m0(K$Kk*;hJ4v|O@5(Xx+Q>|!1r5lKae;y zx=i8R9BjM-GEDUtZJ9{EyD~~4!6YY6jmDHe|Ta`PR8-sk< zhlMX|*39jjHz`$n`y`EJl}?<6CZSbR^bQ5_EAp&(Xl;$fiLu}TFYcJHw}$6cW$4^Xv?jC zuob)D9KDfX-ddmL-U#73z&RW7kn8=;BZx~`MpJ5+**eLONfX?A|DSd`jr>nfBe6y0@QiKcM6kjR!peIfjLvD5aZ&YaTUBO;q{sy}CT7dISfl zIzNwF!t1Q6&WiU3UXWqR8_&JwY(XMk^!YJIEpJYe_fr%2VzSY3p>FV0iVB|!2QlcZ zHo@r4;3|FV-;O`p#<#ue zeEeHg7LeC2;w;`PACrbBTxC>P_bt!u%}tpf3Q&vsB^70VPrl~QCyc<{sS8v8%00V& zwZx0NpoPm=vsv}xb;sH2097?Vmp;p=xuS7qsr|oSQq~gx!nd8alBK8mmeAY}6|>WK zK*ZuR4vGd!y&dG7GofGGBq@T(Lc%Hf<@2?F8uff|uI%XWURAChYFQx&xA3fuH3RXZ zdhP6{J!z6m*6sDY{`beB5K;Y}FnX1Y6Ns@?b~o()jhwER?C!anH8XX^Cc zbD1FC62zY!@r}btH0-x(P9`0^DwZYJpOM#H@W_7@U;qN;4?X>Uf zkNmde_fu4ArendhOV`y4C&Uc~!0`_%?l-Dk{7}3QbF~kAGS;9Wd+@8Vf2ee}*8w`| zHhlH68gx3tAt86G5EVG$)Yv?Pvmdl94m3I`U;|)ngY{U#abYC@`1)kWb)2;gMc&7% zv2T%eYTL?B@Qd4*8U-lKb=Jk9+hk+G2FZ2xMmppHYJe2RSPoK|Fg*XO-(r2a; zz7z(y=CN9)Fp-P=80RErI;OqOV*Ql#&0r>R>$eAYQ+Snhfp7`&+<$=OOBf0e6QLWNpm z2M#tteAksiM*J}lKLS(m1(L4saoHxNXn7Xps@GV;Qk|m~KtAVeMLh1#Xa=`oTbx>) zymG@}Drq`}{rjJt0~iOP0Q1Mz1p#K$?GZf_P4J!>Mo@aKG67;`p*{93UxmT7ofaWI z4I_PvRw@CBWh%^%`nWwr-*_iiq-FC`Z-;bkDwcXim|jC;R9Kq)Im;mc6=lONa0W%O z(G0}QfD1qBaMKdY9DV~3XM1%)PH{9_ke@uX^C)R4b&UTcuZ{FN?3w-QMXRH(q;C ze_8(1orBQND?_b|!07&y1vBvBt?Rv&%SV6aLDZCr=@d74r-_=pqZW&wt^<$WWg zLill2cqM)2{)mO(rP>(e?6DOl$`4+tvTADJP;KT;`^#X&P2BRVg zBd@z8%#yEL5bJC7{MCrhgFs)HWx8hQk;F}%AM`-$l)mq@BTbZi?&krDQk`ag%Ad^8 zUMS8gU3-PPlBk}^W==bXfJo9+S>G*Vb3@+PqIgHf2I`ZK`H=FiWT)-2#7o^&gb(fB zajZTS6($CI$d|MwoMuM_f93hvMAwVu{S;g4vs)h)5`3VK-*1aHj}^-@JCUc_V=cpu zZ4wCjU6I{ywLw#O>@l5JgR`uHL<%Wk>g(rWkLo2Ybj6AP&EFkQ;??!6bVWZAoGq~v zs^49n!rzIgS#Sd)!i-zZwJ|2M<2z4n*s=c~~}3nR{4mq`oD z%TfcvKKN4o2T^!2ml+A1&`@xV(QWq}KCBu=X3={vxX(RtDbovkuaugSmI+~Ze&S|V zfxxFf0zclu^R~Aeq_6c4XEgtk`a8hnql=A4R-o2Pb00Dz)bOxO;| z{F|Ci8(nsW$rJR;hopA4AjEW?kX0GOhGP5oF+q2k7nbvAq;gJzw9USyVo6bFy6wTb&rZiRt8l)e!;_j1DDhLbgZ|vDONFBzByZ}NK{iyO z$=C{qw7%s+ve{optZE;@UVPE9+yn_o3mjL2ky-ZwATQ6 z5^85zj0kYx#w*?5Hz2a?3Kt=H@O8T&M6^gsi2y-|9E0s2Fs;H-0$r5DbqNih8z#>j zz9F+3sI8~T`p4Jx+JgR0`{TK<_oXbyhBnB9Wx3PivH2hUROY6jE6@qopdKA~<3K3| zIvq}uCLWHpbq1B(=u>|r(E25Hd!84S#RswFIZH?D_ay0&u}LtAzL=N~p7|x!Fq`q$ z2Ifc5?LOdd>9x?d#aVgQ<4FwnW`Jn_>+l2$yB)V?+;1$pgO-`b-;~#&=fxFW)L_}? zkW}hEw0_?%C2RyVyB7DzE=A=AI9jNG5s54Y(J0zzQKjdE^$}BemCmsg+Y`F5^7)0e zvJ2Xcq82k{iwTZD-8KW~x^QSy=9iQU@~phgjz)@n2UA{hwM7yq{*nsz&nV6i{r=)b z#{ZW?v8&y`qzF&L1kc~NY!RK9djOGzk!xQ*GUudwuux@UZflAKi{(j4;JfkFB<^&b zh6(mix3%Od%Wt_1U~HTyceV4ki(y^2J{%auwZ2`iN1}41pPmzS$l#nt1$WML?=!04tTB*&_p0ewVDDj8rCk~PxH6s1!gC2+DsAJ(k-6v?^ZWe2n zJ${hzgAN&p%V`TgsxL3fP3b_$}?F2)~q$2QvjLe?IxJ%#jM#pJJ69o zefTHy>=3TZZpa43A8Ha?f19qq0}}iARhw*Nv<+qc5RJoNIc+M%Cx5W*7k~Cklph@Ek zNDF}OESlb(aK%q`PdKR0kffO~iU>xI_$BrGFDbEHQ;$yixeiPjugi5oeWFicp5isU zbDx&A48m4S_#*u)v_fKWKMGwNyrSFj3f*kMc%^`b2$+m+@`}?nzNqVS3Pn8VI*XT% zYqeQ`8)b?<*u_LQR$c8+N}M*|3+n_cJ{Ef^?0u0Nh|2%ig}adM)RWAejjEkf2Dl0L zU8kJE)~sC~ba_!wZ`h~SMt-83=X$XiW}bg+S|4o_)(`2r6$45@8Xw(>D5!xh~1pw+-X(p=0;%KY1l zlMNVoaog`ZRUrK{h6cL1QgjL7?yshrhP2eO{BG&WPK$FJezjBiemRkf*n8AEQaNg; z?XRiPC*1CF8Tph^kqaY#7dCBqBZB;*xQE$5om=kIC;L^$#(+;>>hDepAnAY5D?wlI z>gJ=d)(Ld$TVe4KUB5oztk^`>#$v3+l>o?S& z`%B8>T*SOV_@v>wc6A=ibzS+S`j{Z;WqV8MWR&~*9!beM z2&>{l?cmO-*@Z>y71i09 zm*MNp#Qnk}KQ&d>+=n)Uw_14(i;O}#5U$y`8+@QZe66PgVZ7h-bqIU>A(q-LE3vV z;voJwN?;YA#7V(Y+KWx**`B=$tm^-@~pwT~UQFt-tqV-tpA1K~8mL#^} zjYDb&+Ezy@KZ!5U4QfGKqe(^p7}=mP0%s%!W{GVDO_2Vlyp)#cFTRH1^9^{*FVjHy zM<*ZkKKq7jljnQNZmG?hwNKj9js6h_dfi^>`Z?1yuRWjn{`*e-K%tkLBO=EFh4npC z`7sR-8pTvT7w+c_A?uDRY=nfceL)4*(#QZ-f6uJ zOd~;FI6D6(3oWwg-61R}E!s4a8FA%pC})~+b*D5?^DKune|8~~j+s4T_)AKfPp3*w z$A*X#h%*c0radS~1T})Ie(EQd%I+$B>(Dx2I;NZ3B1mE^9`q@^*fY|HQ^jBiK%MO- zhy(*H-({1UraDS4Jy>8rX{m2Wp3dOR#r$l_p%~_!yl;K95i+h1+#-~f@O{qpmkS&l zA_u0dk)lT_l#s!;>gW4OSK72J@}KKh(y|My&C=zx=so*^k8+NtVvFx`wg9A>$Vj)j zPN-MK3Mi^euWCjQgwKSre@SIVHvlF6s8SfWtrG zBWNG__YHnpc;e<)MNwHuTv1aP4xS7cw4BVyO(}a@bukwFl{4@ANcM78TEYs%^G!Fw zvx>A&zbLI!DmBFGb?=hX)%G*Gx1Eoem72OUswtu-b&JZEp_gpw6o>H5i6^sg7{XPj z^hn49?n#kGcH)(0+e08&+zgxhy9+?ImAVL1hPV#+LO`ih2h!zP&dT;=cmnX3RF>In zG~q}@nK;4yh%m9dy!}i(CgpnQ$f_s>Ll&{Gx|HRtiXc(%1*?Fz;8#ke_8R#yXs2#? zSoJbr0@e?Elc2$TCz&fD!!Yya|LWXC>!iy%qp8)t@`Eca&h_57=53NXin^(}&OPT^6<0Nv46kia>{%D}lwZGHG(qoWP+GhCu;2*=#xn(;qaQ4&h-j zZv)juYADSIgUjO9C~H|toR5v45Pp^R?zv6c_el-WQZr(a^{6a0)i|mmDnA{Q|71P< z&bhO5)iG1Hwt-5lI%yK?8|Bc_ZO?+nkHanXJ6XmsrHx|!*@vf1m}K=Rgv`wSO~SiK z>PPhNz>x~Nd+&dnki9T0rNJb}kbfO&81CAYir3cZhOH;`k0-#)+N$9QeWPg)*e|IZ zXW(zXTY!6IVreDF*M)7E)Fy#|t$O{Oq+tgwq@*zelP5(Fx4G%;;NC z-JRQ;>K>Y8Xb$~*=O`)Va#)X3s}vEH7W>R1=(gzUjTH!nl9+R`-M|b!Z-%oDI?&hy zRJtaNpkP>a1V8=s^gK02Q1q6Ti^@P)aR0qv`5gEBC#8lUBWhCK^|4HaNDu7fF>5!fk_+zdY!>bOn}_9(C8xyfd$ zeT>Os9X|~Lcbmj0Y8@Yti73eAU-3)Tb|Nz<0tjIcUs=k@z&vO$m4tNh$Yqss)Vt~L z+)TBJp=<44d0#yY7HADnakYD)p|a?-A#%lRW-9-}R(syhlnZlz1|hRdHkR(b@6hd*mF$Ji zWo;xrFCJN^+0!YX|8bpGr*L+xYg}?l15TG|Z^9 zAHt}!O|$R?9gy=NX&Nk@M76f5sh*ZYWoEaeyQwH%B*{#6#Y`%%i#GXDHpK`0!)?HW z^l_th)%XAKTTC;~0`On*KlQJN9-V=OD}<^zmaq=u>^rMHG*cSwnX9zJEhz`faP;;RvXH07l}$fLZY8zS^PMhI3N6RSxkPiscl=Y528Wg(&@&l=((?^ zl~%2l+2ewB_}u%aW8ddStS_Xn1p)zk#|?b;vo8L5pMZZ}oVWo#+{AJdvK#&EnvT77 z!5`cu)YsoZOwu*K7Omtd9!#KHhw;gcfWO9{4i(PB1LRr$!&viY8kh{O%WQ0yMQ-rq z)U%TI=bQ1*&dE-b5)aST=7_uT8fW-Bf zWi1%&Lf(IHA2Oc&dkf1~BkC-j>vmM-Z}|QL=WzgEiFtbMW<+rIt-FYU?Z#V%MB$Dw zso_=kUidlt9#}ZWTqF=Eez>F87~Ad69I{w)C9B}o^<&WK0r(3};|>i!Ax(b6d>q}* z0;>$2{jU%u3;U$RRN7GL&3y2Ah4)WpW}o!ra2t|z`5X1b`Vbel%hk9Abq ze5{l+nO8LcNGxUqw+ZvO5U<=NGv=z$Zq?0s{e}r|GI%Lrr@1~<5?rG^#8qFa=zMbM zKyfjL=6gN)AR{yYmzv4%x?jJUc%Ar!W;phlbN9gViytAyzQgiu`%LuDPz>wXu00%| z`Nq_LsuBf=@tyOw{fje5zr%?A`D5dYy6J`_h4`?7Hf2XXo#I4n#1yF_1pMbkmBBMi zw8D77R^9|`bk#_FVGs?J_q`B~#RtjKAJ%`rvOw(umQO1$TdgU7(n{3l-k9w}jr6A} z{>!V{d*=a}xNL~^JLLAt`tqG0>svVz=WSU~8JuPr9b21QBL56wdTMMCI7YkD1=ZKq z6={ahF%NYdtkt4d9@PNCcOIpd6cVuTZ>+`}r~V}{dyw$2X`jNyRt?_$xcvU^n!CL8 zmsEl5J7`#sJR)vO$wP2L{Y&@L)ndP+4=rq zNsr(X@XGyXTP0{x8x$Pb``}AK-aCD@)gGU`%^THCyDEB!&(O&zp}x(~))Pjy^8|H$ zO<7KT@W*&)qoi5NI|u2YzqS;THipBvi;D+%&=8>d2+Agyqa|TPL{VO}i&5Z2{&U9a z=0RUY^t~80IHwBpIy}{W6Iw|t=_byXBFUWYX-Mf@$W0TFO^9lQdQWIDvljaH4aVfz zb_-0W>C4Lm^v4tVh{fr+RaN5T z%`t9&@*jcDnWM!Aoom*WFUhm%MG-5U$&ok?n8=qL zj&#bifnQSdqZR2!4Oi~Zjh!G1ep9z;(UmWQjZR9F55SL3@$8-YyXkRhH->U`-YmYO z#z|(T<&JD(HWBma!}!!MDZke;Ys6QZs5`m{e#sFy10len6-1korC;H61X`iM$H*K% zt7{?1fkl0~>4dpnD8#mh$-6j}>3Xq&tFWk>%yf-FzGwz=L7t@>92txe?(+O-I!bn5~9w=S`9x~yfeZ9q$G_hP*e1yhb# z4Iqrf_UF#RU@GoS`#x+Q#if`B;6$vXnAoE9bE#knuNuQPMDvhc5UbQ4m3 z+9~NhKl>v_led~3pZ=_s^t*Ce@V0F?9Xo*smo4mU8Ge~9;cQ__L>89@qxPAy)~|<6 zYt)y`2om@0VA9SlX})HO2M#TKo(M<#nhamv$#p!Y|9n1Txjams^5lTd%{V{m9YOLe zj}d6uXk*`A=aAqQ)xC-g1j+__r%VUMha6YWN9N~`n9Q(;@>Z9;C^j1znX_DYk;G1D zk~J*~Xmi|WCX6HPTc6l7H9~{&pF{MQh1JXbN~hxY=9Ho2o-=xK8EWFfXEu^uEJo-5 zeJf+(O1=K`{RPMOrY*MJ*61qE&@u1YUEogiv;@q!+>p6$Wz>A;1gl{4bP~R9XkOqe zyCt^0mH#9;Dz}@EA_i(s^*J*HVdhgAfMx+Sy8T&ck6tv*fxG5ucBPWl6^uT#6I1UX zXhDhncV9rSv}E(67Nml$|Hi;IgKf%w7s^7;rv*LL6F4r&_2$mukLp)~Qy2|SO`epz zX$}It4ZPCQL&ENSEuKw(lFlpqE-GVsqpFvHEVE-SP`j-kyr(DQB&Dc}=}$IWy+b z{nZ}vv!r#nDQw4-o4Bcny)d<0zqv}j48CUjNpGM`P96KTvY+zq>Tn_5M;v%(fXucI zjvd{t_U(fz0$)mi$O)GkHZu2pk56jeG}mtEoeOsq29qKljZ@lW9oe)~;^Dd+uNRW^ zCX%jE&&5UU(d1@(>B8GYdj$XAS9+Xhdb>fr!DhL4essKOJq<))@5nIR_^OJtbrPWq zVseTn!`%HY4C0AvE8CPU+JjEZ&`lU-d4Rw2!>BhG`WGa2Mf5n}UVWtCr;Qgvp6zGL zYAJhbHTg?wdKM_(7pUQJ11D@$^qTngpe%$RSVxR_o@1CC^7FmJPqWKbI%*U0n(l*B zz$?$33}tpq;;Q6NB=OB&Ef`vpUcY6f9w$gSyfrl=@N zoxNH%2+%|f`ky`tjQa%A?emDab}>M(Eb$r}YE=s$egZh4f;ELqH zj4ZqW=FOS(=%@b~ZcmcVsKKB1uuG1^4>qU|y;`Slmyi8N=aHZMlq~Y&dCl!imxX@} z?>4(h3@MiXy9E$69=g25fyxvb2E*+B;af_6rY4-;M-k7z`Nu-(UHj>Oqi|9xX|#F| z#SL=S;9jgFs~Hd%CTia+YX++z+`0W!B=C1)sp_JB)ZLzdFao~h;`MN}{9`}SpA}>3 zC$~D=f_NrBzionsGUDnUFk{~R8N@sL@OG8EPNnwWv@C-hN3rWb5`4qnQXaTlG~qM6 zYStmjHeR8T5_%>B8YdH+$Aqy8>+fmif&YxKe`=fqfdN*S-Vq<>lyc&1f_Q{u%m3I; zC{G)nqmEdq*bUkXuj`5Ei3~^J3|SAW&U1q5)$@4)*ze(%u#_@mRUvs#QLdvx^Li$U zsW*JnKyfHIe2$k9m$AXv^?xeVol{qeGAc^a6NEua*e17Kb(F1ZH&Pw{*Vv{A^6|?3_{J+;!MH}VxOLsD5Kd+zsh^tv&z-fF ztLH;I8NK!O8uQ$~Z@qYyrN>5p=3K53e3j8Qjty_4?!^RI3lkhnnQyqsRtBNkbrUms z@J~2qhwD5JP>0<=qwD9>cifSHH3$qBE@WuMiy%eq?@Wd+@{7dqw)h)R+OeLb39EUr ztzVvu7VqP=MvThL(#+z08$ zLClae9n>l$FvYXyaCdeazhnEh1v2RV!n*m%@qs>#4zzx!f3|>8M=4loo(`EGfxb1b z;!nD;mt%8PI|gRW%tSdS5y+VHTYl}Ojr82b;IEwYndGA@({4-wyLCHQzFTiF^Z-os$X~%=+6wO`dknP5WshtbvApDo>UKBZ^3+!n? zIO%D}Gbz2B+8r&5FJ5KDnGS9_#Y%dT)eTUnc|Ky0DWmjGt@c@wXNx71 zk4VfqnR2&gd{b%W=B9lJCoaCH%b~co8#x{rO8Yb`NgHTPf(9Q?yV}|m0D`=t+On{@ z3CpDH4n-H&a#zIcz06k1=2RbazVq3%i+*Y-kIG=uyNk5nhq1ZBgU_fangY@L``X!-LSb}iuBep{=o9M#*YL@W2T1Fq0W-g0<3*rVuREkVoE;q!#Tng+{Ucqcj|0jrotLtJn2<%EeBL72EH5>RV^T0HKPVx(Ze_ZNH;K)vnNGZs#p7AxC2Qvw zRcyF0MXJ&cQ{u)u$gtvU`n$2|2i)&=6yr2K#PXuLkAbhBYJ}UDg^)NoM=0U%FfRfx07oqM^61tH+i}f zYcrA-6ANp`1U-|1KbgzR@;W^J75BM1^$fu=qM_^oyZ&KqnUF8S!=Rn=hCsfK?Vw11 z57b=J(^c|#u7)8~LFnM0Lr(YrqJdJOLH=3i<~m$33-a#Q%E#9(u2B;YUJwX0r}v%$ z3_{51wDLfAMr4L58W8>T9V`0j#LZ-g7!WoeHY8!A787i^9tnC|J(ej%Dfj#YsN%lF zR46BbA2o_r<)h7L{JNTFa1m2&^|&*yjVA+qvHsykNbA>d+_8 z-*=3`jN?~>lKjBRS75KX9DI}7o*VwdjI>VzN2lPIl(7~HazU2g`1XZgY|WS5ChP=r zwY~ZcT9v$MALMz}oZUB1?xKavi-RQp8Ul40?0w%oc914{mJgSy_T1Dm$h^x3)%oLd zy|P_fAgeN*;)Mhl_$$WmDll#q#`ZQ9vRWX@v;D@7@yTYdY5SM%TohQZ;j<1lv=mWS zkOLu5Lb|c|v^{h004;#e3XHl`!FRYZ;g^J}te?8lWQM(WUD;-KJLeP4fYD0)-=~a! zDVT%{*61^W-0PxtTg9FCsS9Gly2M!nc&sywDnj0hXwov857W;4lvrZ==ua_j9t+rN zpT@0?Yi-&cS~vJ{fK=qgajj_0gx>>D4qadRzW{F+km!JL$4fAb%gfkwGt&+e@DFmG zoKNO@Ci}Jxzdo-opI-<053=NNoz~bkIV|FBwj7osKU3c$E9m^#ofaDYBYs!;EI{e| zAwkFGEk!KmvTP>A8OGkJt)uj0hs*Xs>EGEAdNQ7FUwN6BrPI{2v$9Q{KFJtvUt z1#l*LTM_4w2SX+a^SAUO&)EoYXX-TJdt2Y}@O%k= zKA;Ea7bnkKk`E)rka_dZk0|)xf#s2dwpoqDdn~-SUxCR~4~TrYhrVst>?=>jgUyG7 ze{jznks802)eSQ3b3YOZG0BFbyLZF%V0lly&^pdqC+xcRa83HLCEfe9PjLsd7T|z; zI&mM(%~kk%%hKJjOt>?p9&a||_FM%-47yJqcf_2YAs%e(9tN2koAh{* zx#J_hXgP6{#mcx>p8OwzAs=MA33GTdqvjle3f;6kNwIft}ePtde_XW*A%^V4^uc z3Im$R9E5vqrtynHubSG?d~PqUa)u6{WSBfmjL`Naek1tz!%<9HP0|_5->|v zLjXdI9BGOF01_Dy!^8c~Jwr@J0G>ATjDv5awzUH8t1KmD^CIt`m*&nT{cgFBlB+L z>)UJXwfp!SNY$4oM_2i`iX-W?20xn|APMaDQ}`?wH1T;8&9T$O0euPn(0|0;Vs$68 zVg}zc*{P6k_i~?!XParJ8jr>Oh2ob;elfy3Y}wg?!)G&o6~^R5NO}@u1uxs5!eojoGt_C|@v>No?LY`=&niQv28d`l3|dw0HN z!-3d!0k8bW6!Kgpvu7br!W?YudACFA8txpIUxp2B!pF>>?C$T*_FR?ay=UeaMDey9 z4p@M$4?G(a7JE7A*JGWE(3A=FT2P10t;}l ze56Z0GCYQfCs&Kl%9q3~pHMWK?9VU{#PsYAljhL}qrv|GHm8IjU|Jq%AFB`pt|9%A zi#TWWY%&>-!tLWbve)h^FqKb7yFfmD-i`+*TTrt=}SKkRAg%(|WJ%157z&_we8Oa!UiKP9FxxgQeM((2r zKk&Ab7<+A0?5s(rYtcVz^*m{8KLQqif}UEEc|44NiFW8&`x_QD+=oDN^X4nYS=-p( zfDsEcOQX9nwvO8AWsuSswu5xrHa)kNw%xW*HjeGkB(co7@aMzpFnU@UA9w2#8>N54 z2D86*Ipc3W?;zMQ#UxN`{7)|O*kdt3LcyN{&ux!4+#+xJLbH(H7`{^px19}t5ug%) z4zUCWH9aipo($!^A=f(q>}zTzGsz~*lAQBk_(-06vi|bntCJH&Vjoa1e|DPhqgqsJY#>c4e*~Um!plF%!Cj6?$o4zSDW*xTRETwHJoUQ^UU z{!1}{dw1|HgG|O9&m)ifj?-N+^nF>-IIt6}ysdNY!D9WbyRO02Ir_BW(q66XQ}H9a z;{pZY;@iKOI$B%nwnGdH?#?r24gM#u_h)SQDbK&n^?6-?DEN;OX%X2xVbLYw5oPuc@-foYwpRy@oi?sMdB<$%Pzeh2i$AY@ffu=aWGcRc(vY3>F_W;$@+ojbZG|p zkDkyx8MjMAk=XI|Z1InRKfs@zVOXTdBMneTKf7bAp?DDRo}-`>GOkmVxo-ae6WN22 ze<0)H(0UJkteOsF{{Up15E(USbG^9Gq@iN}0CSwQL%KGGy6u9y?}=6BMR_4Jx#eL{ zUAWp#AI0ST#kR|^a^w63{5;+f6Tu5&Pn@!ED39?e`V0ueNdr{dn!lFmvHP9}pScdQ zcb76$`Q?+y>~4k~w^Eny_ZYmsHcgC>Ek1}9`r-OreEdI+$hW=sZzMB!HtrwSmM;)_ zOpm#!2=Jtf`CbR=cKyk>vgN$A+i}TOq1Mi?JdibPj|{bNMy;14g4)^GFfM&ub{FtT zeIM2MU)A(7=#rbTXQ)n_8;vdG{h_REILp6+Kf@;9@F9kKweMnmL>*aNA@0SSs* z8v&kIlvZA{!rZs>VCAni5D&Y89{dr{J32h$A+5#p^=v{T?#tK9o+rl-Fg&>Xx^8UD z((U3m6OjRn0X}SBfCKrJE8_9b5GzSG63DQK&*J|i>n zAkTs_qq5z65&j;h{CutWY_iNuv6wU>9$}!&EZeGU;~~Aleg&WZ08m`uY=1z-A4i*7 zfxqt5K)p^3HuL@4fzsT1qy5-6@Z7g~jC5E@Lh#TmRfu&uSh;T|_DK;psFP9A@nD+I zG94Vl#ozg{i(PZXac|Pucje~W&yzkEg}ZpbY;>8Q;qLLDT>k)wTo(a(gh)Jbymg1i z6@Ui_8lG+bWb+QBtB z*hfK|<_H6i_hqA8Bn0V0_cuT`db7yDnJee&3xV`8&m9+&U!)qSAepb)KQJy{T!(J~ zZZqt>@(F>bh-*BDlfjSnmfgL<&yFM|oo7E8WSpDI2wy{9tQpA9xjm$4ZP|D62w~&g zwrIT6@oV2*{{Y#1k1jkCzk=IOxQ02QJ~NOWCiON$ufX=@rRW4bkoe@@k|)8kM$2qH z*f-_%d&y_~L>=aj{99kJ{{U7v?>;hB?qRYm#I21vAG~&%T3Ph-0E$=h2D@TxnYIKx z{^5mt5Hr$=JFVwwD|uvV7RQ0Bej@rlm3mfo0t}1oCo8T+ZHtZHT*^C!n%RB`7{77Dy zHll%AAMJN(kiM0NiUXP^VU020^xkO}C)kz%nPXNDo2(Df*bT;hFDtfrlGor_5?#GV zkB1|1-*7X;_EhmXolEh*0E2?|@S%6ryVLPA6aCM2&uzeZb9tNf!2 zhnsD)Y)erth|}9;^V`Jn^E>fR=E>&XLV46<#x&5JJ|!3NlZT7MU4kLzY7sgy{zMZa zH2(nbUiT1bc%1Up>KgdMVt)(9)A<2u{6HCScneECTnXmTep>+cvnKvV&8T>`PxOnc zuiV3jOU+T7U^N9$wlnk$?-ukK)0}zDN6(@cqiqML72VpcnQ%@Tde&@lM*FE-3qr7FVCTp$a=RY$XDzyBsm~cFPKcAdt#f}!J zTgmJ2bKrgye8h`J%RVQMej9AKgj1Y-vQYB{K9~W~EqfkhJTAU@VDE1Y=@{1q#p2!8 z{-*Q6a_k3?vVQ&p5|c}>O|k*w?q8!VM@t10vPqwV#0Bm)4xGG3ZHdo!6Ni0A@Rso; z1%?1P=naRxpFfyTDfipVK3Jvp?W@klevtj2+;5Cw>S1k{yiEL=sgHH<^4@aM%UFc) z7Ck%>S@18u{mas-zkdbgKN0i1hV>VeuJZ4xjy@p+$*>}J;M%W(?4Ndl5qgh;*;{YP zWS`*Z^3eN_0Y9meNAVgz^I!RU`2PO@^5@t>G<^78L3eHxbo#Mlw}^G`^Lg++<1Yap z#Qn^;h}ob>pJnMcypwbej%24$YAb=D9u`PXAN3=h@n+sg*y|4`?d_v}*KuJ8+sSY1 zE=Ql1J^%@gz_c>JR!2M_r#NxzX|>VNa`Y2ZKk_?8_H z-~RxML#O`$pQ+~m0F?g#)vf&Tf8?tZA4%U#{9cjzZG7B<{8kv;cJOsPT#`SF*&lFx zmVZJ?z5_V%G$i2;zz`&N?&=(FZ|?hNm;h~ueMmnxom(BetcfWXpf3LaI8S`bh7sJt zKNq_Ov5WAwB7^pg@)hxMTe}8s+x2a;4^yS5;9-Wwva_PS$ zd>;?zeg<29GS~rT&S7!f-8c4L5PufV1iXhI&5v#Rpg%il*O|wR$IOR`uiPfC{w&9z zHywal;|#OEL-A;JAAGQQ1NWB>r{5*}hv+SF80m>??0&=n7zlQF!UvMiM}C|C082@K z>VxO{Y(8JqkGJ(Ky?<6e`lEmPum1ppKDYiYJUjbCf9$*;_CNCSf%{+i40rc${!Z|J zm;V4J0#E+{A5i-@__=yV*oFT9ly0^^vk?1%`>`gg`?sg(FAklt3Hfgwm#m-SP7Zp1DS8G ze>P7q^(f)FKa+FVKe-qFGT(3HFaH3ZSo!{xGtcN+dVhjRGx|#p{FZ;=kXjS^fjs`0 zUxfKdva18;K7LXOgRaQrxt2lL=Kk#jEw{4kuszROTzQ=vF3s7GxX&;i&~T3rH#*)+ zT)L=-iUHIDX2=+VeK1ej03Y)R@jM`-{wGc#`trEy{aa(9AR9QcJ0WylFGZ!&gYjUV zHq)z~?d{k?bQ>|&SSzK`>0-VRZ^OesH>nXG$MFg-L;8`?Za5v7zfg;>__pcg^9M3j`lh8@7)UY2zRv^?u2=rwBM_1?q^x?As-O_C@ww7czC$8kjKpO=hTl-JNdX~7P9)7 z#FWnx&vc8J_3VXIKaNJy$H?2Om)IDR?fkF(O971k0NL=4;=10(fsNXdH5MNXHh3G$t;|mPlv5;GjQNw)19FZf$z2)eQ$lqq%U=yAU zhd$Uz9eL(@F029Ek`6@P*}i!i54b7cY*BBC=FMMMS3OS>qI&@Gb7bs>d5swWuob;; z)vo;)i|Wh%A;-8fJu}uXDPg`Z0Ly&88GGKsP7)b&+RwW=csXjpu2?6rEo|%0ClA1u z2-}d1J%q%3#ut4<<#OatHs!geESNCkk>d5nc=@okisNXP9%X>_5&J=pBj#VxBA=^= z&sRP(@ssz$@{!p52A_dq@WRf6m_SPRx0GNXcYB^8G@k+P5E-gdILMoXDV7<#kk3T- zHeL8#gMvNkUINQ9bo#WXqV6*rV?EsXhngB&L~(dZfrs&S z$Oc;Zy0k^pk5o5*Cp5q;dJLdYA zAC$6UJJ#{n^=q0~y?J9Jy=Q&qU#RiPeG0N~9J8IgxV#$r?X1(u2p@BfUQ1r&*3%aT zli?B@(#$@geVrulh?qW?kh9(qqRyNxyW=e3-du@$E*tK4&{gk`Q1|(V9G-sRf%e@b zfV=f-cR43By^E4%!+qVGA_w9b=aI*#@q5f$qdnSp>U6K-94Dyx=U7aU=Q)-P1I(9? zV^}igjBYs{IgcZb_T%`R1;>_w;P)S#9+P)#;rg}H2cB-THdj5Q-6wa5 лет

    11 sets
    -

    20 наборов

    +

    29 наборов

    прошли обучение
    @@ -53,7 +53,7 @@

    20 наборов

    400 graduates
    -

    1000+

    +

    1500+

    выпускников
    @@ -83,57 +83,56 @@

    Основные преподаватели и организаторы

    • -
      - Михаил Корнеев -
      +
      + Валентин Домбровский
      -

      Михаил Корнеев

      +

      Валентин Домбровский

      - В коммерческой разработке с 2001 года, с 2009 — работает с Python. + Евангелист и сооснователь MoscowPython сообщества.

      - Cооснователь MoscowPython. Тимлид в BestDoctor. + Сооснователь IT-рекрутингового агентства Geekfactor.io.

      - Сооснователь MoscowPython, Тимлид в BestDoctor. В коммерческой разработке с 2001 года, - с 2009 - работает с Python. + Евангелист и сооснователь MoscowPython сообщества. Сооснователь IT-рекрутингового агентства Geekfactor.io.
    • -
      - Валентин Домбровский
      +
      + Семен Осипов +
      -

      Валентин Домбровский

      +

      Илья Лебедев

      - Евангелист и сооснователь MoscowPython сообщества. -

      -

      - Сооснователь Drylabs, компании, создающей open-source проекты. + Евангелист MoscowPython, разработчик в ANNA Money, до этого – технический директор + в Zipsale и BestDoctor.

      - Евангелист и сооснователь MoscowPython сообщества. Сооснователь Drylabs, компании, создающей open-source проекты. + Программирует и преподаёт Python больше 10 лет.
    • -
      - Семен Осипов +
      + Михаил Корнеев
      -

      Семён Осипов

      +

      Михаил Корнеев

      - Активист MoscowPython сообщества, Team Lead в Gett, до этого - Big Data Engineer - в X5 Retail Group и Semrush. + В коммерческой разработке с 2001 года, с 2009 — работает с Python. +

      +

      + Cооснователь MoscowPython. Тимлид в международном IT-стартапе.

      - Активист MoscowPython сообщества, Team Lead в Gett, до этого - Big Data Engineer - в X5 Retail Group и Semrush. + Сооснователь MoscowPython, Тимлид в BestDoctor. В коммерческой разработке с 2001 года, + с 2009 - работает с Python.
    • diff --git a/landing_page/mainpage/templates/mainpage/include/index_faq.html b/landing_page/mainpage/templates/mainpage/include/index_faq.html index 88d063b8..04f3661f 100644 --- a/landing_page/mainpage/templates/mainpage/include/index_faq.html +++ b/landing_page/mainpage/templates/mainpage/include/index_faq.html @@ -68,36 +68,11 @@
      -
      -
      -
      - -
      -
      -
      -
      - В каждом наборе курса участвует порядка 70-и человек. Все они делятся на группы по 5-6 - человек согласно уровню знаний. Первое занятие — интенсив, который продлится с 10 до - 19 часов и в ходе которого вы напишете своего первого бота для мессенджера Telegram. - В дальнейшем мы будем предлагать вам лекции для изучения в онлайн-режиме, а практические - занятия будут полностью посвящены практике и взаимодействию с куратором. Каждое такое - занятие будет проходить по субботам с 15 до 18 часов. Также в течение курса вы сможете - общаться с «сокурсниками» и куратором в онлайн-режиме. Первые 4 занятия курса вам даётся - домашнее задание. Вы его делаете и по готовности показываете куратору. После 4-й недели - вы планируете свой проект, разбиваете задачи с напарником (куратор помогает это сделать) - и каждую неделю добавляете функциональность в свой проект. Здесь вы сами ставите себе - задачи (куратор поможет, если случился затык, но не будет ставить задачи за вас). - Презентации проектов будет посвящена часть последнего — «выпускного» — занятия. -
      -
      -
      @@ -138,7 +113,7 @@
      Нет, не критично, поскольку материалы лекций будут доступны онлайн, а практиковаться вы - сможете самостоятельно, поддерживая контакт с куратором также онлайн. + сможете самостоятельно, поддерживая контакт с куратором.
      diff --git a/landing_page/mainpage/templates/mainpage/include/index_hero.html b/landing_page/mainpage/templates/mainpage/include/index_hero.html index 46a33bba..60290816 100644 --- a/landing_page/mainpage/templates/mainpage/include/index_hero.html +++ b/landing_page/mainpage/templates/mainpage/include/index_hero.html @@ -11,7 +11,7 @@

      Ближайший набор пройдет только Онлайн

      - Вы создадите Telegram-бота на первом же уроке. Познакомитесь с основами data science и веб-разработки. + Вы создадите Telegram-бота в первую же неделю. Познакомитесь с основами data science и веб-разработки. Напишете собственный проект. Опытные питонисты, имеющие опыт «боевой» разработки, всю дорогу будут проверять ваш код и давать рекомендации.

      diff --git a/landing_page/mainpage/templates/mainpage/include/index_how_to_pay.html b/landing_page/mainpage/templates/mainpage/include/index_how_to_pay.html index d16ce0af..863a707e 100644 --- a/landing_page/mainpage/templates/mainpage/include/index_how_to_pay.html +++ b/landing_page/mainpage/templates/mainpage/include/index_how_to_pay.html @@ -12,36 +12,6 @@

      Как оплатить

      Как оплатить

      -
      -
      -
      -

      Рассрочка на 1, 6 или 12 месяцев

      -
      -
      -
      -

      - Рассрочка - вид кредита, который предоставляет «Яндекс.Касса» и её банки-партнеры. Услуга доступна - гражданам РФ с постоянным доходом в возрасте от 18 до 65 лет. -

      -
        -
      • -

        Начните регистрацию и выберите пункт «Оплата в кредит».

        -
      • -
      • -

        Откройте «Яндекс.Кошелек».

        -
      • -
      • -

        Оформите заявку на кредит и дождитесь одобрения.

        -
      • -
      • -

        - Погасите полную стоимость обучения в первый месяц, чтобы избежать переплат. Либо оплачивайте - обучение частями в течение 6 или 12 месяцев с переплатой 3,9% в месяц. -

        -
      • -
      -
      -
      diff --git a/landing_page/mainpage/templates/mainpage/include/index_modules.html b/landing_page/mainpage/templates/mainpage/include/index_modules.html index 0d3b2de7..501e27b0 100644 --- a/landing_page/mainpage/templates/mainpage/include/index_modules.html +++ b/landing_page/mainpage/templates/mainpage/include/index_modules.html @@ -34,9 +34,9 @@

      Что вас ждет

      Каждую субботу - онлайн-группа созванивается со своим преподавателям. Затем в течение недели вы изучаете - материалы и пишете код, укладываясь в дедлайны. Как только накопятся вопросы - пишете в - общий чат или куратору. + мы проводим созвон всего набора, а потом каждая группа отдельно созванивается со своим + преподавателем. Затем в течение недели вы изучаете материалы и пишете код, укладываясь в + дедлайны. Как только накопятся вопросы - пишете в общий чат или куратору.

      @@ -77,9 +77,8 @@

      Финишная прямая

      Вы доводите проект до рабочего прототипа, который можно показать коллегам и - друзьям, и презентуете его перед аудиторией (онлайн-группа делает это по - видеосвязи). Если вы презентуете свой проект - вы получаете сертификат об - успешном окончании курса. + друзьям, и презентуете его своим сокурсникам. Если вы презентуете свой проект + - вы получаете сертификат об успешном окончании курса.

      diff --git a/landing_page/mainpage/views.py b/landing_page/mainpage/views.py index fbf335e9..b85450f9 100644 --- a/landing_page/mainpage/views.py +++ b/landing_page/mainpage/views.py @@ -6,7 +6,7 @@ from django.http import HttpRequest, HttpResponse from django.template import loader -from .models import Curators, Feedback, GraduateProjects, GraduateProjectsVideos, LearnPythonCourse +from .models import Curators, GraduateProjects, GraduateProjectsVideos, LearnPythonCourse @dataclasses.dataclass @@ -43,19 +43,30 @@ def index(request: HttpRequest) -> HttpResponse: 'projects': GraduateProjects.objects.all(), 'registration_closes_date_formatted': enrollment.end_registration_date.strftime('%b %d, %Y %H:%M:%S'), - 'student_feedback': Feedback.objects.all(), 'student_videos': [ + { + 'title': 'Путь джуна — из геодезиста в Support Engineer', + 'youtube_id': 'YySKSlNHDXo', + }, + { + 'title': 'Как становятся джунами в британской компании на удалёнке', + 'youtube_id': 'TsqEigK2WQk', + }, + { + 'title': 'Python-стрим - вход джуниора в АйТи', + 'youtube_id': 'wvijeR-eINA', + }, { 'title': 'Как войти в разработку за считанные месяцы', - 'youtube_id': 'DkHWpgctTuA' + 'youtube_id': 'DkHWpgctTuA', }, { 'title': 'Личный опыт джуниора: удачи, фейлы, рецепты', - 'youtube_id': 'vKKqsJ8IvAg' + 'youtube_id': 'vKKqsJ8IvAg', }, { 'title': 'Python для врача и медицина для программиста.', - 'youtube_id': 's_ZNqjIW3ZA' + 'youtube_id': 's_ZNqjIW3ZA', } ], 'curators_list': Curators.objects.filter(curator_status=True), From 04fcf825bb0dec19fe23dbd060f166bb55012593 Mon Sep 17 00:00:00 2001 From: Ilya Lebedev Date: Thu, 24 Aug 2023 16:37:51 +0200 Subject: [PATCH 064/107] remove stale models and projects page --- landing_page/mainpage/admin.py | 21 +- ..._delete_graduateprojectsvideos_and_more.py | 62 +++ landing_page/mainpage/models.py | 492 +----------------- .../mainpage/templates/mainpage/index.html | 5 - .../mainpage/templates/mainpage/projects.html | 210 -------- landing_page/mainpage/urls.py | 1 - landing_page/mainpage/views.py | 23 +- 7 files changed, 69 insertions(+), 745 deletions(-) create mode 100644 landing_page/mainpage/migrations/0040_delete_feedback_delete_graduateprojectsvideos_and_more.py delete mode 100644 landing_page/mainpage/templates/mainpage/projects.html diff --git a/landing_page/mainpage/admin.py b/landing_page/mainpage/admin.py index 6aa6402e..b2309ebe 100644 --- a/landing_page/mainpage/admin.py +++ b/landing_page/mainpage/admin.py @@ -1,25 +1,6 @@ from django.contrib import admin -from .models import ( - Curators, - Feedback, - GraduateProjects, - GraduateProjectsVideos, - GraduateStories, - LearnPythonCourse, - LearnPythonCoursePrices, - LearnPythonMultiCityCourses, - MoscowPythonMeetup, - Podcasts, -) +from .models import Curators, GraduateProjects -admin.site.register(MoscowPythonMeetup) -admin.site.register(LearnPythonCourse) admin.site.register(Curators) -admin.site.register(Feedback) admin.site.register(GraduateProjects) -admin.site.register(GraduateStories) -admin.site.register(LearnPythonCoursePrices) -admin.site.register(GraduateProjectsVideos) -admin.site.register(Podcasts) -admin.site.register(LearnPythonMultiCityCourses) diff --git a/landing_page/mainpage/migrations/0040_delete_feedback_delete_graduateprojectsvideos_and_more.py b/landing_page/mainpage/migrations/0040_delete_feedback_delete_graduateprojectsvideos_and_more.py new file mode 100644 index 00000000..a90895a8 --- /dev/null +++ b/landing_page/mainpage/migrations/0040_delete_feedback_delete_graduateprojectsvideos_and_more.py @@ -0,0 +1,62 @@ +# Generated by Django 4.2.4 on 2023-08-24 14:35 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('mainpage', '0039_alter_graduatestories_story_section'), + ] + + operations = [ + migrations.DeleteModel( + name='Feedback', + ), + migrations.DeleteModel( + name='GraduateProjectsVideos', + ), + migrations.DeleteModel( + name='GraduateStories', + ), + migrations.DeleteModel( + name='LearnPythonCourse', + ), + migrations.DeleteModel( + name='LearnPythonCoursePrices', + ), + migrations.DeleteModel( + name='LearnPythonMultiCityCourses', + ), + migrations.DeleteModel( + name='MoscowPythonMeetup', + ), + migrations.DeleteModel( + name='Podcasts', + ), + migrations.AlterModelOptions( + name='curators', + options={'verbose_name_plural': 'Кураторы'}, + ), + migrations.RemoveField( + model_name='curators', + name='curator_github', + ), + migrations.RemoveField( + model_name='curators', + name='curator_motto', + ), + migrations.RemoveField( + model_name='curators', + name='curator_social_network', + ), + migrations.RemoveField( + model_name='curators', + name='curator_status', + ), + migrations.AddField( + model_name='curators', + name='is_visible', + field=models.BooleanField(default=True, verbose_name='Показывать на главной'), + ), + ] diff --git a/landing_page/mainpage/models.py b/landing_page/mainpage/models.py index bbe6a9c2..5ebb3a8b 100644 --- a/landing_page/mainpage/models.py +++ b/landing_page/mainpage/models.py @@ -1,293 +1,9 @@ -import datetime -from datetime import date, timedelta - from django.db import models -class MoscowPythonMeetup(models.Model): - class Meta: - verbose_name_plural = "MoscowPython Митапы" - - def __str__(self) -> str: - return f'MoscowPython Meetup № {self.meetup_number}' - - meetup_number = models.IntegerField( - verbose_name='Номер митапа', - help_text='Введите номер митапа' - ) - - meetup_day = models.DateTimeField( - verbose_name='Дата и время митапа', - help_text='Где и во сколько?' - ) - - meetup_link = models.URLField( - verbose_name='Ссылка на митап', - default='http://www.moscowpython.ru', - help_text='Ссылка по стандарту, можно менять' - ) - - -class LearnPythonCourse(models.Model): - class Meta: - verbose_name_plural = "LearnPython Наборы" - - def __str__(self) -> str: - return f'LearnPython Набор № {self.course_index}' - - course_index = models.IntegerField( - verbose_name='Набор №', - help_text='Порядковый номер набора' - ) - - timepad_event_id = models.CharField( - verbose_name='Номер эвента в Timepad', - help_text='/dashboard/event/909971 <- вот этот', - max_length=20, - null=True - ) - - course_start_date = models.DateField( - verbose_name='Дата начала курса', - help_text='Дата первого занятия' - ) - - course_end_date = models.DateField( - verbose_name='Дата окончания курса', - help_text='Дата последнего занятия', - ) - - end_registration_date = models.DateTimeField( - verbose_name='Дата закрытия регистрации', - help_text='Во сколько закрывается регистрация?', - default=None, - - ) - - course_day_2 = models.DateField( - verbose_name='Второй день занятий', - help_text='Дата второго занятия', - default=None, - blank=True, - null=True - ) - - course_day_3 = models.DateField( - verbose_name='Третий день занятий', - help_text='Дата третьего занятия', - default=None, - blank=True, - null=True - ) - - course_day_4 = models.DateField( - verbose_name='Четвертый день занятий', - help_text='Дата четвертого занятия', - default=None, - blank=True, - null=True - ) - - course_day_5 = models.DateField( - verbose_name='Пятый день занятий', - help_text='Дата пятого занятия', - default=None, - blank=True, - null=True - ) - - course_day_6 = models.DateField( - verbose_name='Шестой день занятий', - help_text='Дата шестого занятия', - default=None, - blank=True, - null=True - ) - - course_day_7 = models.DateField( - verbose_name='Седьмой день занятий', - help_text='Дата седьмого занятия', - default=None, - blank=True, - null=True - ) - - course_day_8 = models.DateField( - verbose_name='Восьмой день занятий', - help_text='Дата восьмого занятия', - default=None, - blank=True, - null=True - ) - - course_day_9 = models.DateField( - verbose_name='Девятый день занятий', - help_text='Дата девятого занятия', - default=None, - blank=True, - null=True - ) - - offline_time_lessons_start = models.TimeField( - verbose_name='Время начала занятия', - help_text='Во сколько занятие начинается', - default='11:00:00', - blank=True, - null=True - ) - - offline_time_lessons_ends = models.TimeField( - verbose_name='Время окончания занятия', - help_text='Во сколько занятие заканчивается', - default='14:00:00', - blank=True, - null=True - ) - - online_time_of_call = models.TimeField( - verbose_name='Время начала звонка', - help_text='Во сколько созваниваемся?', - default='11:30:00', - blank=True, - null=True - ) - - offline_session_closed = models.BooleanField( - verbose_name='Закрыть офлайн набор?', - help_text='Поставь галочку, чтобы закрыть набор', - default=False, - ) - - online_session_closed = models.BooleanField( - verbose_name='Закрыть онлайн набор?', - help_text='Поставь галочку, чтобы закрыть набор', - default=False, - ) - - def get_date_after_first_lesson(self) -> datetime.date: - return self.course_start_date + timedelta(days=1) - - def get_day_before_last_lesson(self) -> datetime.date: - return self.course_end_date - timedelta(days=1) - - -class LearnPythonCoursePrices(models.Model): - class Meta: - verbose_name_plural = 'LearnPython Цены на курсы' - - def __str__(self) -> str: - return f'Интервал {self.price_range} на {self.course_type}' - - price_range = models.IntegerField( - verbose_name='Название временного отрезка', - help_text='Мустанг / Гепард / Панда и вот это все', - default=None - ) - - course_type = [ - ('Online', 'Online'), - ('Offline', 'Offline'), - ('OfflinePenza', 'OfflinePenza'), - ('OfflineSpb', 'OfflineSpb') - ] - - course_type = models.TextField( - choices=course_type, - verbose_name='Тип курса', - help_text='Выберите тип курса' - ) - - price_range_start_date = models.DateField( - verbose_name='Дата начала интервала', - help_text='Когда начинается данное предложение', - blank=True, - null=True - ) - - price_range_end_date = models.DateField( - verbose_name='Дата окончания интервала', - help_text='Когда истекает данное предложение', - blank=True, - null=True - ) - - price_range_price = models.IntegerField( - verbose_name='Цена', - help_text='Сколько стоит курс в этот период' - ) - - @property - def within_price_range(self) -> bool: - return self.price_range_start_date <= date.today() <= self.price_range_end_date - - @property - def past_due_date(self) -> bool: - return date.today() > self.price_range_end_date - - -class LearnPythonMultiCityCourses(models.Model): - class Meta: - verbose_name_plural = 'LearnPython Цены на курсы в разных городах' - - def __str__(self) -> str: - return f'Курсы в городе {self.city_name}' - - city_name = models.CharField( - max_length=50, - verbose_name='Название города', - help_text='Какой город указывать в списке' - ) - - long = models.DecimalField( - max_digits=9, - decimal_places=6 - ) - - lat = models.DecimalField( - max_digits=9, - decimal_places=6 - ) - - early_date = models.DateField( - verbose_name='Дата окончания ранней регистрации', - blank=False, - null=False - ) - - early_price = models.IntegerField( - verbose_name="Стоимость курса в раннюю регистрацию", - null=False, - blank=False - ) - - early_installment_price = models.IntegerField( - verbose_name="Стоимость рассрочки", - null=False, - blank=False - ) - - basic_date = models.DateField( - verbose_name='Дата начала основной регистрации', - blank=False, - null=False - ) - - basic_price = models.IntegerField( - verbose_name="Стоимость курса в обычную регистрацию", - null=False, - blank=False - ) - - basic_installment_price = models.IntegerField( - verbose_name="Стоимость рассрочки", - null=False, - blank=False - ) - - class Curators(models.Model): class Meta: - verbose_name_plural = 'LearnPython Кураторы' + verbose_name_plural = 'Кураторы' def __str__(self) -> str: return f'Куратор {self.curator_name}' @@ -303,14 +19,6 @@ def __str__(self) -> str: help_text='Где и кем работает, что программирует' ) - curator_motto = models.CharField( - max_length=150, - verbose_name='Девиз куратора', - help_text='Через тернии к звездам или что-нибудь такое', - blank=True, - null=True - ) - curator_photo = models.ImageField( help_text='Фотография куратора', verbose_name='Фото куратора', @@ -318,143 +26,9 @@ def __str__(self) -> str: upload_to='courators/' ) - curator_status = models.BooleanField( - verbose_name="Куратор для ближайшего набора?", - help_text='Куратор работает в текущем наборе?', - default=True - ) - - curator_github = models.URLField( - blank=True, - help_text='Ссылка на гит-хаб куратора', - verbose_name='GitHub куратора' - ) - - curator_social_network = models.URLField( - blank=True, - help_text='Если есть, ссылка на соцсеточку', - verbose_name='Соцсеточка куратора' - ) - - -class Feedback(models.Model): - class Meta: - verbose_name_plural = "LearnPython Отзывы" - - def __str__(self) -> str: - return f'Отзыв участника {self.feedback_author}' - - feedback_author = models.CharField( - verbose_name='Автор отзыва', - help_text='Кто автор отзыва?', - max_length=50, - null=True - ) - - feedback_author_link = models.URLField( - verbose_name='Ссылка на автора', - help_text='Есть ли ссылка на соцсеточки автора?', - blank=True, - null=True - ) - - feedback_author_position = models.CharField( - verbose_name='Должность выпускника', - help_text='Кем работает автор?', - max_length=50, - null=True - ) - - feedback_author_photo = models.ImageField( - verbose_name='Фотография автора', - help_text='Прикрепите фото автора отзыва', - blank=True, - upload_to='feedbacks/' - ) - - feedback_title = models.CharField( - verbose_name='Заголовок отзыва', - help_text='Большие буквы заголовка', - max_length=140, - default=None - ) - - feedback_text = models.TextField( - verbose_name='Текст отзыва', - help_text='А сюда пишем отзыв автора', - null=True - ) - - -class GraduateStories(models.Model): - class Meta: - verbose_name_plural = 'Learn Python Истории учеников' - - def __str__(self) -> str: - return f'История участника {self.story_author}' - - story_author = models.CharField( - verbose_name='Автор истории', - help_text='Как зовут автора истории?', - max_length=50, - null=True - ) - - story_author_photo = models.ImageField( - verbose_name='Фотография автора', - help_text='Прикрепите фото автора истории', - null=True, - upload_to='stories/' - ) - - story_author_position = models.CharField( - verbose_name='Должность выпускника', - help_text='Кто теперь выпускник', - max_length=50, - null=True - ) - - story_author_background = models.CharField( - verbose_name='В прошлом автор был:', - help_text='Прим. "В прошлом: терапевт"', - max_length=150 - ) - - story_section_choices = { - ('Никогда не программировал', - 'Никогда не программировал' - ), - ('Хочу новый навык или работу', - 'Хочу новый навык или работу' - ), - ('Есть опыт, хочу освоить новый язык', - 'Есть опыт, хочу освоить новый язык' - ) - } - - story_section = models.TextField( - choices=story_section_choices, - default='Никогда не программировал', - verbose_name='Раздел истории', - help_text='В какую из секций историй' - ) - - story_text_before_course = models.TextField( - verbose_name='История пользователя', - help_text='До курса', - default=None - ) - - story_text_on_course = models.TextField( - verbose_name='История пользователя', - help_text='На курсе', - default=None - ) - - story_text_after_course = models.TextField( - verbose_name='История пользователя', - help_text='После курса', - default=None + is_visible = models.BooleanField( + verbose_name="Показывать на главной", + default=True, ) @@ -478,61 +52,3 @@ def __str__(self) -> str: default=None, upload_to='projects/' ) - - -class GraduateProjectsVideos(models.Model): - class Meta: - verbose_name_plural = 'LearnPython Видео проектов Учеников' - - def __str__(self) -> str: - return f'Проект "{self.project_name}"' - - project_name = models.CharField( - verbose_name='Название проекта', - max_length=150, - help_text='Название проекта', - default=None - ) - - project_url = models.CharField( - verbose_name='Ссылка', - max_length=250, - help_text='Ссылка на Youtube', - default=None - ) - - project_course = models.CharField( - verbose_name='Номер набора', - max_length=5, - help_text='Номер Выпуска', - default=None - ) - - project_description = models.TextField( - verbose_name='Описание проект', - help_text='Краткое описание проекта', - default=None - ) - - -class Podcasts(models.Model): - - class Meta: - verbose_name_plural = 'LearnPython Подкаст с учеником' - - def __str__(self) -> str: - return f'Проект "{self.podcast_name}"' - - podcast_name = models.CharField( - verbose_name='Название подкаста', - max_length=150, - help_text='Название подкаста', - default=None - ) - - podcast_url = models.CharField( - verbose_name='Ссылка', - max_length=250, - help_text='Ссылка на Youtube', - default=None - ) diff --git a/landing_page/mainpage/templates/mainpage/index.html b/landing_page/mainpage/templates/mainpage/index.html index 3d01dba4..5bd93e05 100644 --- a/landing_page/mainpage/templates/mainpage/index.html +++ b/landing_page/mainpage/templates/mainpage/index.html @@ -106,11 +106,6 @@

      Что дает этот курс

      Проекты, созданные во время обучения

      -
      -

      - Смотреть все проекты -

      -
      {% if projects %} {% for project in projects %} diff --git a/landing_page/mainpage/templates/mainpage/projects.html b/landing_page/mainpage/templates/mainpage/projects.html deleted file mode 100644 index d170db39..00000000 --- a/landing_page/mainpage/templates/mainpage/projects.html +++ /dev/null @@ -1,210 +0,0 @@ - - - {% load static %} - {% load l10n %} - - - - - - - - - - - - Learn Python - учимся программировать на Python за 2 месяца - - - - - - - - - - - - - - -
      - -
      - -
      -
      -
      -

      - Проекты, созданные во время обучения -

      -
      -
      - -
      - {% if student_projects %} - {% for project in student_projects %} -
      -
      -
      -
      -

      {{project.project_name}}

      -

      - {{project.project_description}} -

      -
      -
      -
        -
      • -
        - -
        -
      • -
      -
      -
      - {% endfor %} - {% endif %} -
      -
      - - -
      - -
      - - - - - - - diff --git a/landing_page/mainpage/urls.py b/landing_page/mainpage/urls.py index d5712b47..88a9caca 100644 --- a/landing_page/mainpage/urls.py +++ b/landing_page/mainpage/urls.py @@ -4,5 +4,4 @@ urlpatterns = [ path('', views.index, name='index'), - path('projects', views.projects, name='projects') ] diff --git a/landing_page/mainpage/views.py b/landing_page/mainpage/views.py index b85450f9..c72c6899 100644 --- a/landing_page/mainpage/views.py +++ b/landing_page/mainpage/views.py @@ -6,7 +6,7 @@ from django.http import HttpRequest, HttpResponse from django.template import loader -from .models import Curators, GraduateProjects, GraduateProjectsVideos, LearnPythonCourse +from .models import Curators, GraduateProjects @dataclasses.dataclass @@ -69,26 +69,7 @@ def index(request: HttpRequest) -> HttpResponse: 'youtube_id': 's_ZNqjIW3ZA', } ], - 'curators_list': Curators.objects.filter(curator_status=True), + 'curators_list': Curators.objects.filter(is_visible=True), 'today': date.today(), } return HttpResponse(template.render(context, request)) - - -def projects(request: HttpRequest) -> HttpResponse: - template = loader.get_template('mainpage/projects.html') - - try: - current_course = LearnPythonCourse.objects.latest('course_index') - except LearnPythonCourse.DoesNotExist: - current_course = LearnPythonCourse() - - student_projects_videos = list(GraduateProjectsVideos.objects.all().order_by('-project_course')) - - context = { - 'course': current_course, - 'student_projects': student_projects_videos, - 'today': date.today() - - } - return HttpResponse(template.render(context, request)) From 30ad878eb8186da35d40284da7e14dea7c26fa72 Mon Sep 17 00:00:00 2001 From: Ilya Lebedev Date: Thu, 24 Aug 2023 16:50:21 +0200 Subject: [PATCH 065/107] add enrollment model --- .../mainpage/migrations/0041_enrollment.py | 27 +++++++++++++++++++ landing_page/mainpage/models.py | 11 ++++++++ 2 files changed, 38 insertions(+) create mode 100644 landing_page/mainpage/migrations/0041_enrollment.py diff --git a/landing_page/mainpage/migrations/0041_enrollment.py b/landing_page/mainpage/migrations/0041_enrollment.py new file mode 100644 index 00000000..d368bc7d --- /dev/null +++ b/landing_page/mainpage/migrations/0041_enrollment.py @@ -0,0 +1,27 @@ +# Generated by Django 4.2.4 on 2023-08-24 14:48 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('mainpage', '0040_delete_feedback_delete_graduateprojectsvideos_and_more'), + ] + + operations = [ + migrations.CreateModel( + name='Enrollment', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('timepad_event_id', models.CharField(blank=True, max_length=64, null=True)), + ('start_date', models.DateField()), + ('end_date', models.DateField()), + ('end_registration_date', models.DateField()), + ('early_price_rub', models.IntegerField()), + ('late_price_rub', models.IntegerField()), + ('early_price_date_to', models.DateField()), + ('late_price_date_from', models.DateField()), + ], + ), + ] diff --git a/landing_page/mainpage/models.py b/landing_page/mainpage/models.py index 5ebb3a8b..c876eed8 100644 --- a/landing_page/mainpage/models.py +++ b/landing_page/mainpage/models.py @@ -52,3 +52,14 @@ def __str__(self) -> str: default=None, upload_to='projects/' ) + + +class Enrollment(models.Model): + timepad_event_id = models.CharField(max_length=64, null=True, blank=True) + start_date = models.DateField() + end_date = models.DateField() + end_registration_date = models.DateField() + early_price_rub = models.IntegerField() + late_price_rub = models.IntegerField() + early_price_date_to = models.DateField() + late_price_date_from = models.DateField() From bba99b19c98e93270dcd303a5cffa64787695d7d Mon Sep 17 00:00:00 2001 From: Ilya Lebedev Date: Thu, 24 Aug 2023 16:52:13 +0200 Subject: [PATCH 066/107] add enrollment to admin --- landing_page/mainpage/admin.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/landing_page/mainpage/admin.py b/landing_page/mainpage/admin.py index b2309ebe..7c000024 100644 --- a/landing_page/mainpage/admin.py +++ b/landing_page/mainpage/admin.py @@ -1,6 +1,7 @@ from django.contrib import admin -from .models import Curators, GraduateProjects +from .models import Curators, Enrollment, GraduateProjects admin.site.register(Curators) admin.site.register(GraduateProjects) +admin.site.register(Enrollment) From c98f6bce392a43c7f9fec844d243f57a86ecdc97 Mon Sep 17 00:00:00 2001 From: Ilya Lebedev Date: Thu, 24 Aug 2023 16:57:58 +0200 Subject: [PATCH 067/107] config csrf origin --- landing_page/landing_page/settings.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/landing_page/landing_page/settings.py b/landing_page/landing_page/settings.py index a0676491..23b1b84d 100644 --- a/landing_page/landing_page/settings.py +++ b/landing_page/landing_page/settings.py @@ -8,6 +8,8 @@ ALLOWED_HOSTS = ['*'] +CSRF_TRUSTED_ORIGINS = ['https://learn.python.ru'] + INSTALLED_APPS = [ 'mainpage.apps.MainpageConfig', 'django.contrib.admin', From b7561fbfd5623a060efdb910092916a8dbfdcf51 Mon Sep 17 00:00:00 2001 From: Ilya Lebedev Date: Fri, 25 Aug 2023 16:17:07 +0200 Subject: [PATCH 068/107] move enrollment to db --- landing_page/mainpage/models.py | 9 +++++ .../mainpage/include/index_hero.html | 12 +++--- landing_page/mainpage/utils/__init__.py | 0 landing_page/mainpage/utils/typing.py | 8 ++++ landing_page/mainpage/views.py | 39 ++----------------- landing_page/tests/conftest.py | 19 +++++++++ landing_page/tests/test_index.py | 3 +- 7 files changed, 48 insertions(+), 42 deletions(-) create mode 100644 landing_page/mainpage/utils/__init__.py create mode 100644 landing_page/mainpage/utils/typing.py create mode 100644 landing_page/tests/conftest.py diff --git a/landing_page/mainpage/models.py b/landing_page/mainpage/models.py index c876eed8..3e2fe529 100644 --- a/landing_page/mainpage/models.py +++ b/landing_page/mainpage/models.py @@ -1,4 +1,6 @@ from django.db import models +from django.utils.timezone import now +from mainpage.utils.typing import ensured class Curators(models.Model): @@ -63,3 +65,10 @@ class Enrollment(models.Model): late_price_rub = models.IntegerField() early_price_date_to = models.DateField() late_price_date_from = models.DateField() + + @staticmethod + def get_enrollment_with_active_registration() -> "Enrollment": + return ensured(Enrollment.objects.filter(end_registration_date__gte=now()).first()) + + def __str__(self) -> str: + return f"Enrollment ({self.start_date} - {self.end_date})" diff --git a/landing_page/mainpage/templates/mainpage/include/index_hero.html b/landing_page/mainpage/templates/mainpage/include/index_hero.html index 60290816..02e026f2 100644 --- a/landing_page/mainpage/templates/mainpage/include/index_hero.html +++ b/landing_page/mainpage/templates/mainpage/include/index_hero.html @@ -45,9 +45,9 @@

      Учитесь онлайн
      Ранняя регистрация
      - До {{ enrollment.early_price.date_to | date:"j E" }} + До {{ enrollment.early_price_date_to | date:"j E" }}
      - {{ enrollment.early_price.price_rub }} р. + {{ enrollment.early_price_rub }} р.

      - {% if today <= enrollment.early_price.date_to %} + {% if today <= enrollment.early_price_date_to %} @@ -72,8 +72,8 @@

      Учитесь онлайн
      Обычная регистрация
      -
      С {{ enrollment.late_price.date_from | date:"j E" }}
      - {{ enrollment.late_price.price_rub }} р. +
      С {{ enrollment.late_price_date_from | date:"j E" }}
      + {{ enrollment.late_price_rub }} р.
      - {% if today >= enrollment.late_price.date_from %} + {% if today >= enrollment.late_price_date_from %} diff --git a/landing_page/mainpage/utils/__init__.py b/landing_page/mainpage/utils/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/landing_page/mainpage/utils/typing.py b/landing_page/mainpage/utils/typing.py new file mode 100644 index 00000000..bebb5f57 --- /dev/null +++ b/landing_page/mainpage/utils/typing.py @@ -0,0 +1,8 @@ +from typing import Optional, TypeVar + +_T = TypeVar("_T") + + +def ensured(value: Optional[_T]) -> _T: + assert value + return value diff --git a/landing_page/mainpage/views.py b/landing_page/mainpage/views.py index c72c6899..3e77ea95 100644 --- a/landing_page/mainpage/views.py +++ b/landing_page/mainpage/views.py @@ -1,47 +1,16 @@ -import dataclasses -import datetime from datetime import date -from typing import Optional from django.http import HttpRequest, HttpResponse -from django.template import loader +from django.shortcuts import render -from .models import Curators, GraduateProjects - - -@dataclasses.dataclass -class CoursePrice: - price_rub: int - date_from: Optional[datetime.date] = None - date_to: Optional[datetime.date] = None - - -@dataclasses.dataclass -class Enrollment: - timepad_event_id: str - start_date: datetime.date - end_date: datetime.date - end_registration_date: datetime.date - early_price: CoursePrice - late_price: CoursePrice +from .models import Curators, Enrollment, GraduateProjects def index(request: HttpRequest) -> HttpResponse: - template = loader.get_template('mainpage/index.html') - - enrollment = Enrollment( - timepad_event_id='2441413', - start_date=datetime.date(2023, 9, 2), - end_date=datetime.date(2023, 11, 4), - end_registration_date=datetime.date(2023, 8, 31), - early_price=CoursePrice(price_rub=30000, date_to=datetime.date(2023, 6, 30)), - late_price=CoursePrice(price_rub=35000, date_from=datetime.date(2023, 7, 1)), - ) - + enrollment = Enrollment.get_enrollment_with_active_registration() context = { 'enrollment': enrollment, 'projects': GraduateProjects.objects.all(), - 'registration_closes_date_formatted': enrollment.end_registration_date.strftime('%b %d, %Y %H:%M:%S'), 'student_videos': [ { @@ -72,4 +41,4 @@ def index(request: HttpRequest) -> HttpResponse: 'curators_list': Curators.objects.filter(is_visible=True), 'today': date.today(), } - return HttpResponse(template.render(context, request)) + return render(request, 'mainpage/index.html', context) diff --git a/landing_page/tests/conftest.py b/landing_page/tests/conftest.py new file mode 100644 index 00000000..170bc68a --- /dev/null +++ b/landing_page/tests/conftest.py @@ -0,0 +1,19 @@ +import datetime + +import pytest +from mainpage.models import Enrollment + + +@pytest.fixture +def active_enrollment() -> Enrollment: + now = datetime.datetime.now() + return Enrollment.objects.create( + timepad_event_id="123", + start_date=now + datetime.timedelta(days=3), + end_date=now + datetime.timedelta(days=10), + end_registration_date=now + datetime.timedelta(days=1), + early_price_rub=100, + late_price_rub=200, + early_price_date_to=now, + late_price_date_from=now, + ) diff --git a/landing_page/tests/test_index.py b/landing_page/tests/test_index.py index d4ecb422..4e2a29fd 100644 --- a/landing_page/tests/test_index.py +++ b/landing_page/tests/test_index.py @@ -1,8 +1,9 @@ import pytest from django.test import Client +from mainpage.models import Enrollment @pytest.mark.django_db -def test__index__shows_up(client: Client) -> None: +def test__index__shows_up(client: Client, active_enrollment: Enrollment) -> None: response = client.get('/') assert response.status_code == 200 From 99146511db1c138ece929768f972237b3da528d0 Mon Sep 17 00:00:00 2001 From: Ilya Lebedev Date: Fri, 1 Sep 2023 12:26:22 +0400 Subject: [PATCH 069/107] make site work if no active enrollment --- landing_page/mainpage/models.py | 5 +- .../mainpage/include/index_hero.html | 150 +++++++++--------- .../mainpage/include/index_menu.html | 2 + .../mainpage/templates/mainpage/index.html | 134 ++++++++-------- landing_page/mainpage/views.py | 5 +- 5 files changed, 155 insertions(+), 141 deletions(-) diff --git a/landing_page/mainpage/models.py b/landing_page/mainpage/models.py index 3e2fe529..13d43ba1 100644 --- a/landing_page/mainpage/models.py +++ b/landing_page/mainpage/models.py @@ -1,6 +1,5 @@ from django.db import models from django.utils.timezone import now -from mainpage.utils.typing import ensured class Curators(models.Model): @@ -67,8 +66,8 @@ class Enrollment(models.Model): late_price_date_from = models.DateField() @staticmethod - def get_enrollment_with_active_registration() -> "Enrollment": - return ensured(Enrollment.objects.filter(end_registration_date__gte=now()).first()) + def get_enrollment_with_active_registration() -> "Enrollment | None": + return Enrollment.objects.filter(end_registration_date__gte=now()).first() def __str__(self) -> str: return f"Enrollment ({self.start_date} - {self.end_date})" diff --git a/landing_page/mainpage/templates/mainpage/include/index_hero.html b/landing_page/mainpage/templates/mainpage/include/index_hero.html index 02e026f2..32878e67 100644 --- a/landing_page/mainpage/templates/mainpage/include/index_hero.html +++ b/landing_page/mainpage/templates/mainpage/include/index_hero.html @@ -15,87 +15,95 @@

      Ближайший набор прой Напишете собственный проект. Опытные питонисты, имеющие опыт «боевой» разработки, всю дорогу будут проверять ваш код и давать рекомендации.

      -

      - С {{ enrollment.start_date | date:"j E" }} по {{ enrollment.end_date | date:"j E" }} -

      -

      - Регистрация закроется {{ enrollment.end_registration_date | date:"j E" }} -

      -
      -
      00дней
      - : -
      00часов
      - : -
      00минут
      - : -
      00секунд
      -
      + {% if enrollment %} +

      + С {{ enrollment.start_date | date:"j E" }} по {{ enrollment.end_date | date:"j E" }} +

      +

      + Регистрация закроется {{ enrollment.end_registration_date | date:"j E" }} +

      +
      +
      00дней
      + : +
      00часов
      + : +
      00минут
      + : +
      00секунд
      +
      + {% else %} +

      + Сейчас регистрация закрыта, но мы скоро регистрацию на новый набор +

      + {% endif %} -
      -
      -
      -
      -

      Учитесь онлайн

      -
      -
      -
      -
      -
      Ранняя регистрация
      -
      - До {{ enrollment.early_price_date_to | date:"j E" }} + {% if enrollment %} +
      +
      +
      +
      +

      Учитесь онлайн

      +
      +
      +
      +
      +
      Ранняя регистрация
      +
      + До {{ enrollment.early_price_date_to | date:"j E" }} +
      + {{ enrollment.early_price_rub }} р. +
      + - {{ enrollment.early_price_rub }} р. -
      - + {% if today <= enrollment.early_price_date_to %} + + {% else %} + + {% endif %}
      - {% if today <= enrollment.early_price_date_to %} - - {% else %} - - {% endif %} -
      -
      -
      -
      -
      Обычная регистрация
      -
      С {{ enrollment.late_price_date_from | date:"j E" }}
      - {{ enrollment.late_price_rub }} р. -
      -
      - - В рассрочку от 4000 р/мес - - Есть рассрочка +
      +
      +
      +
      Обычная регистрация
      +
      С {{ enrollment.late_price_date_from | date:"j E" }}
      + {{ enrollment.late_price_rub }} р. +
      +
      + {% if today >= enrollment.late_price_date_from %} + + {% else %} + + {% endif %}
      - {% if today >= enrollment.late_price_date_from %} - - {% else %} - - {% endif %}
      -
      + {% endif %}
      diff --git a/landing_page/mainpage/templates/mainpage/include/index_menu.html b/landing_page/mainpage/templates/mainpage/include/index_menu.html index 6241773f..4df44738 100644 --- a/landing_page/mainpage/templates/mainpage/include/index_menu.html +++ b/landing_page/mainpage/templates/mainpage/include/index_menu.html @@ -64,11 +64,13 @@ + {% if enrollment %} + {% endif %}

    diff --git a/landing_page/mainpage/templates/mainpage/index.html b/landing_page/mainpage/templates/mainpage/index.html index 5bd93e05..103a97e4 100644 --- a/landing_page/mainpage/templates/mainpage/index.html +++ b/landing_page/mainpage/templates/mainpage/index.html @@ -213,80 +213,82 @@

    Записаться

    -
    -
    -

    онлайн курс

    -
    -
    -
    -
    -
    Ранняя регистрация
    -
    До - {{ enrollment.early_price.date_to | date:"j E" }}
    - {{ enrollment.early_price.price_rub }} - р. -
    -
    - В - рассрочку - от 3500 р/мес - Есть - рассрочка + {% if enrollment %} +
    +
    +

    онлайн курс

    +
    +
    +
    +
    +
    Ранняя регистрация
    +
    До + {{ enrollment.early_price.date_to | date:"j E" }}
    + {{ enrollment.early_price.price_rub }} + р. +
    +
    + {% if today <= enrollment.early_price.date_to %} + + {% else %} + + {% endif %}
    - {% if today <= enrollment.early_price.date_to %} - - {% else %} - - {% endif %} -
    -
    -
    -
    -
    Обычная регистрация
    -
    С - {{ enrollment.late_price.date_from | date:"j E" }}
    - {{ enrollment.late_price.price_rub }} - р. -
    -
    - В - рассрочку - от 4000 р/мес - Есть - рассрочка +
    +
    +
    +
    Обычная регистрация
    +
    С + {{ enrollment.late_price.date_from | date:"j E" }}
    + {{ enrollment.late_price.price_rub }} + р. +
    +
    + {% if today >= enrollment.late_price.date_from %} + + {% else %} + + {% endif %}
    - {% if today >= enrollment.late_price.date_from %} - - {% else %} - - {% endif %}
    -
    + {% endif %}
    diff --git a/landing_page/mainpage/views.py b/landing_page/mainpage/views.py index 3e77ea95..86ef4146 100644 --- a/landing_page/mainpage/views.py +++ b/landing_page/mainpage/views.py @@ -11,7 +11,10 @@ def index(request: HttpRequest) -> HttpResponse: context = { 'enrollment': enrollment, 'projects': GraduateProjects.objects.all(), - 'registration_closes_date_formatted': enrollment.end_registration_date.strftime('%b %d, %Y %H:%M:%S'), + 'registration_closes_date_formatted': ( + enrollment.end_registration_date.strftime('%b %d, %Y %H:%M:%S') + if enrollment else "" + ), 'student_videos': [ { 'title': 'Путь джуна — из геодезиста в Support Engineer', From 4bec0455b948913223d61be33e59a98d5e3b53d2 Mon Sep 17 00:00:00 2001 From: Ilya Lebedev Date: Wed, 6 Sep 2023 08:24:03 +0400 Subject: [PATCH 070/107] hello base platim integration --- .../migrations/0042_enrollment_platim_url.py | 18 +++++++++ landing_page/mainpage/models.py | 2 + .../mainpage/include/index_footer.html | 2 - .../mainpage/include/index_hero.html | 24 +++++++++--- .../mainpage/include/index_menu.html | 24 +++++++++--- .../mainpage/templates/mainpage/index.html | 38 ++++++++++++------- 6 files changed, 81 insertions(+), 27 deletions(-) create mode 100644 landing_page/mainpage/migrations/0042_enrollment_platim_url.py diff --git a/landing_page/mainpage/migrations/0042_enrollment_platim_url.py b/landing_page/mainpage/migrations/0042_enrollment_platim_url.py new file mode 100644 index 00000000..bb1c64c0 --- /dev/null +++ b/landing_page/mainpage/migrations/0042_enrollment_platim_url.py @@ -0,0 +1,18 @@ +# Generated by Django 4.2.4 on 2023-08-25 15:01 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('mainpage', '0041_enrollment'), + ] + + operations = [ + migrations.AddField( + model_name='enrollment', + name='platim_url', + field=models.CharField(blank=True, max_length=254, null=True), + ), + ] diff --git a/landing_page/mainpage/models.py b/landing_page/mainpage/models.py index 3e2fe529..7327dd73 100644 --- a/landing_page/mainpage/models.py +++ b/landing_page/mainpage/models.py @@ -58,6 +58,8 @@ def __str__(self) -> str: class Enrollment(models.Model): timepad_event_id = models.CharField(max_length=64, null=True, blank=True) + platim_url = models.CharField(max_length=254, null=True, blank=True) + start_date = models.DateField() end_date = models.DateField() end_registration_date = models.DateField() diff --git a/landing_page/mainpage/templates/mainpage/include/index_footer.html b/landing_page/mainpage/templates/mainpage/include/index_footer.html index e268e86e..5707d67c 100644 --- a/landing_page/mainpage/templates/mainpage/include/index_footer.html +++ b/landing_page/mainpage/templates/mainpage/include/index_footer.html @@ -26,9 +26,7 @@

    Мы в социальных сетях

    diff --git a/landing_page/mainpage/templates/mainpage/include/index_hero.html b/landing_page/mainpage/templates/mainpage/include/index_hero.html index 02e026f2..c4fc6cc8 100644 --- a/landing_page/mainpage/templates/mainpage/include/index_hero.html +++ b/landing_page/mainpage/templates/mainpage/include/index_hero.html @@ -59,9 +59,15 @@

    Учитесь онлайн

    {% if today <= enrollment.early_price_date_to %} - + {% if enrollment.platim_url %} + + Купить билет + + {% else %} + + {% endif %} {% else %}
    {% if today >= enrollment.late_price_date_from %} - + {% if enrollment.platim_url %} + + Купить билет + + {% else %} + + {% endif %} {% else %}
    diff --git a/landing_page/mainpage/templates/mainpage/index.html b/landing_page/mainpage/templates/mainpage/index.html index 5bd93e05..5c460b27 100644 --- a/landing_page/mainpage/templates/mainpage/index.html +++ b/landing_page/mainpage/templates/mainpage/index.html @@ -224,7 +224,7 @@

    онлайн курс

    Ранняя регистрация
    До {{ enrollment.early_price.date_to | date:"j E" }}
    - {{ enrollment.early_price.price_rub }} + {{ enrollment.early_price_rub }} р.
    @@ -236,11 +236,17 @@

    онлайн курс

    рассрочка
    - {% if today <= enrollment.early_price.date_to %} - + {% if today <= enrollment.early_price_date_to %} + {% if enrollment.platim_url %} + + Купить билет + + {% else %} + + {% endif %} {% else %} + {% if today >= enrollment.late_price_date_from %} + {% if enrollment.platim_url %} + + Купить билет + + {% else %} + + {% endif %} {% else %} + {% endif %} {% else %} - {% endif %} - {% else %} - - {% endif %} - -
    -
    -
    -
    Обычная регистрация
    -
    С {{ enrollment.late_price_date_from | date:"j E" }}
    - {{ enrollment.late_price_rub }} р. -
    -
    - {% if today >= enrollment.late_price_date_from %} - {% if enrollment.platim_url %} - - Купить билет - +
    +
    +
    +
    Обычная регистрация
    +
    С {{ enrollment.late_price_date_from | date:"j E" }}
    + {{ enrollment.late_price_rub }} р. +
    + +
    + {% if today >= enrollment.late_price_date_from %} + {% if enrollment.platim_url %} + + Купить билет + + {% else %} + + {% endif %} {% else %} - {% endif %} - {% else %} - - {% endif %} +
    - + {% endif %} diff --git a/landing_page/mainpage/templates/mainpage/include/index_menu.html b/landing_page/mainpage/templates/mainpage/include/index_menu.html index 6830e997..5d3b2258 100644 --- a/landing_page/mainpage/templates/mainpage/include/index_menu.html +++ b/landing_page/mainpage/templates/mainpage/include/index_menu.html @@ -15,14 +15,16 @@ - {% if enrollment.platim_url %} - - Записаться - - {% else %} - - Записаться - + {% if enrollment %} + {% if enrollment.platim_url %} + + Записаться + + {% else %} + + Записаться + + {% endif %} {% endif %}

    В процессе оплаты вы можете выбрать вариант рассрочки от 3 до 12 месяцев. diff --git a/landing_page/mainpage/views.py b/landing_page/mainpage/views.py index d111885a..c33173ae 100644 --- a/landing_page/mainpage/views.py +++ b/landing_page/mainpage/views.py @@ -48,10 +48,15 @@ def index(request: HttpRequest) -> HttpResponse: def advanced_handle(request: HttpRequest) -> HttpResponse: + enrollment = Enrollment.get_enrollment_with_active_registration(enrollment_type=EnrollmentType.ADVANCED) return render( request, 'mainpage/advanced.html', context={ - "enrollment": Enrollment.get_enrollment_with_active_registration(enrollment_type=EnrollmentType.ADVANCED), + "enrollment": enrollment, + 'registration_closes_date_formatted': ( + enrollment.end_registration_date.strftime('%b %d, %Y %H:%M:%S') + if enrollment else "" + ), }, ) From f62e370e319dae2c24ee3b3f2bb9848b6fe4716b Mon Sep 17 00:00:00 2001 From: Ilya Lebedev Date: Sun, 10 Sep 2023 15:48:38 +0400 Subject: [PATCH 075/107] fix str method for enrollments with no type --- landing_page/mainpage/models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/landing_page/mainpage/models.py b/landing_page/mainpage/models.py index 00fcabdb..44b1622f 100644 --- a/landing_page/mainpage/models.py +++ b/landing_page/mainpage/models.py @@ -87,4 +87,4 @@ def get_enrollment_with_active_registration(enrollment_type: EnrollmentType) -> ).first() def __str__(self) -> str: - return f"{self.type.capitalize()} enrollment ({self.start_date} - {self.end_date})" + return f"{self.type.capitalize() if self.type else 'NO TYPE'} enrollment ({self.start_date} - {self.end_date})" From 793a29709dbc0aee18bfd0d8e96a7019390409cc Mon Sep 17 00:00:00 2001 From: Ilya Lebedev Date: Sun, 10 Sep 2023 16:20:08 +0400 Subject: [PATCH 076/107] add missing var to context --- landing_page/mainpage/views.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/landing_page/mainpage/views.py b/landing_page/mainpage/views.py index c33173ae..9570551c 100644 --- a/landing_page/mainpage/views.py +++ b/landing_page/mainpage/views.py @@ -53,7 +53,8 @@ def advanced_handle(request: HttpRequest) -> HttpResponse: request, 'mainpage/advanced.html', context={ - "enrollment": enrollment, + 'today': date.today(), + 'enrollment': enrollment, 'registration_closes_date_formatted': ( enrollment.end_registration_date.strftime('%b %d, %Y %H:%M:%S') if enrollment else "" From c4404e68a073e83ea5a4197f972d4aa22a518840 Mon Sep 17 00:00:00 2001 From: Ilya Lebedev Date: Wed, 13 Sep 2023 16:53:06 +0400 Subject: [PATCH 077/107] add limits message --- .../templates/mainpage/include/advanced/index_hero.html | 6 ++++++ .../mainpage/templates/mainpage/include/index_hero.html | 5 +++++ 2 files changed, 11 insertions(+) diff --git a/landing_page/mainpage/templates/mainpage/include/advanced/index_hero.html b/landing_page/mainpage/templates/mainpage/include/advanced/index_hero.html index fe025c1f..2d15a4aa 100644 --- a/landing_page/mainpage/templates/mainpage/include/advanced/index_hero.html +++ b/landing_page/mainpage/templates/mainpage/include/advanced/index_hero.html @@ -21,6 +21,12 @@

    Регистрация закроется {{ enrollment.end_registration_date | date:"j E" }}

    +

    + Всего + 25 + мест в наборе – успейте присоединиться! +

    +

    Регистрация закроется {{ enrollment.end_registration_date | date:"j E" }}

    +

    + Всего + 50 + мест в наборе – успейте присоединиться! +

    Date: Wed, 13 Sep 2023 16:54:45 +0400 Subject: [PATCH 078/107] fix typo --- .../templates/mainpage/include/advanced/track_unittests.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/landing_page/mainpage/templates/mainpage/include/advanced/track_unittests.html b/landing_page/mainpage/templates/mainpage/include/advanced/track_unittests.html index 29beae03..c4273f02 100644 --- a/landing_page/mainpage/templates/mainpage/include/advanced/track_unittests.html +++ b/landing_page/mainpage/templates/mainpage/include/advanced/track_unittests.html @@ -1,4 +1,4 @@ -

    Юнит-тесты

    +

    Трек «Юниттесты»

    В этом треке вы научитесь всему, что нужно для настройки и написания From 35f32170523836acc74d5e424f2f6bb4f6094620 Mon Sep 17 00:00:00 2001 From: Ilya Lebedev Date: Sat, 16 Sep 2023 12:51:08 +0400 Subject: [PATCH 079/107] remove projects from menu --- .../mainpage/templates/mainpage/include/index_menu.html | 6 ------ 1 file changed, 6 deletions(-) diff --git a/landing_page/mainpage/templates/mainpage/include/index_menu.html b/landing_page/mainpage/templates/mainpage/include/index_menu.html index 5d3b2258..68fede65 100644 --- a/landing_page/mainpage/templates/mainpage/include/index_menu.html +++ b/landing_page/mainpage/templates/mainpage/include/index_menu.html @@ -58,12 +58,6 @@

    -
    diff --git a/landing_page/mainpage/templates/mainpage/include/advanced/index_footer.html b/landing_page/mainpage/templates/mainpage/include/advanced/index_footer.html index 5707d67c..3bb23d84 100644 --- a/landing_page/mainpage/templates/mainpage/include/advanced/index_footer.html +++ b/landing_page/mainpage/templates/mainpage/include/advanced/index_footer.html @@ -15,7 +15,7 @@

    Наши контакты

    • Email

      - learn@python.ru + team@python.ru
    • Наш сайт

      diff --git a/landing_page/mainpage/templates/mainpage/include/advanced/index_how_to_pay.html b/landing_page/mainpage/templates/mainpage/include/advanced/index_how_to_pay.html index 863a707e..749dd9df 100644 --- a/landing_page/mainpage/templates/mainpage/include/advanced/index_how_to_pay.html +++ b/landing_page/mainpage/templates/mainpage/include/advanced/index_how_to_pay.html @@ -47,7 +47,7 @@

      Частным лицам

    • Для оплаты зарубежной картой свяжитесь с нами - learn@python.ru. + team@python.ru.

    @@ -68,7 +68,7 @@

    Юридическим лицам

  • Свяжитесь с нами по любым вопросам, написав на - learn@python.ru. + team@python.ru.

  • diff --git a/landing_page/mainpage/templates/mainpage/include/advanced/index_how_to_pay_by_platim.html b/landing_page/mainpage/templates/mainpage/include/advanced/index_how_to_pay_by_platim.html index 85a37d66..b8d44bf8 100644 --- a/landing_page/mainpage/templates/mainpage/include/advanced/index_how_to_pay_by_platim.html +++ b/landing_page/mainpage/templates/mainpage/include/advanced/index_how_to_pay_by_platim.html @@ -57,7 +57,7 @@

    Юридическим лицам

    Свяжитесь с нами, написав на - learn@python.ru. + team@python.ru.

    diff --git a/landing_page/mainpage/templates/mainpage/include/advanced/index_register_popup.html b/landing_page/mainpage/templates/mainpage/include/advanced/index_register_popup.html index 1c0b5355..bc7ad462 100644 --- a/landing_page/mainpage/templates/mainpage/include/advanced/index_register_popup.html +++ b/landing_page/mainpage/templates/mainpage/include/advanced/index_register_popup.html @@ -21,10 +21,10 @@

    записаться на курс

    первому занятию.

    diff --git a/landing_page/mainpage/templates/mainpage/include/index_faq.html b/landing_page/mainpage/templates/mainpage/include/index_faq.html index 04f3661f..bc226ea3 100644 --- a/landing_page/mainpage/templates/mainpage/include/index_faq.html +++ b/landing_page/mainpage/templates/mainpage/include/index_faq.html @@ -261,7 +261,7 @@
    Мы всегда рады и рассматриваем новых кураторов для наших наборов. Если вы заинтересованы - - пишите нам на learn@python.ru + - пишите нам на team@python.ru
    diff --git a/landing_page/mainpage/templates/mainpage/include/index_footer.html b/landing_page/mainpage/templates/mainpage/include/index_footer.html index 5707d67c..3bb23d84 100644 --- a/landing_page/mainpage/templates/mainpage/include/index_footer.html +++ b/landing_page/mainpage/templates/mainpage/include/index_footer.html @@ -15,7 +15,7 @@

    Наши контакты

    • Email

      - learn@python.ru + team@python.ru
    • Наш сайт

      diff --git a/landing_page/mainpage/templates/mainpage/include/index_how_to_pay.html b/landing_page/mainpage/templates/mainpage/include/index_how_to_pay.html index 863a707e..749dd9df 100644 --- a/landing_page/mainpage/templates/mainpage/include/index_how_to_pay.html +++ b/landing_page/mainpage/templates/mainpage/include/index_how_to_pay.html @@ -47,7 +47,7 @@

      Частным лицам

    • Для оплаты зарубежной картой свяжитесь с нами - learn@python.ru. + team@python.ru.

    @@ -68,7 +68,7 @@

    Юридическим лицам

  • Свяжитесь с нами по любым вопросам, написав на - learn@python.ru. + team@python.ru.

  • diff --git a/landing_page/mainpage/templates/mainpage/include/index_how_to_pay_by_platim.html b/landing_page/mainpage/templates/mainpage/include/index_how_to_pay_by_platim.html index ee981079..c7d076b4 100644 --- a/landing_page/mainpage/templates/mainpage/include/index_how_to_pay_by_platim.html +++ b/landing_page/mainpage/templates/mainpage/include/index_how_to_pay_by_platim.html @@ -62,7 +62,7 @@

    Юридическим лицам

    Свяжитесь с нами, написав на - learn@python.ru. + team@python.ru.

    diff --git a/landing_page/mainpage/templates/mainpage/include/index_register_popup.html b/landing_page/mainpage/templates/mainpage/include/index_register_popup.html index 1c0b5355..bc7ad462 100644 --- a/landing_page/mainpage/templates/mainpage/include/index_register_popup.html +++ b/landing_page/mainpage/templates/mainpage/include/index_register_popup.html @@ -21,10 +21,10 @@

    записаться на курс

    первому занятию.

    From 006f79369d41e6aa6bb2daf1dc74da16484638ee Mon Sep 17 00:00:00 2001 From: Ilya Lebedev Date: Sun, 19 Nov 2023 11:30:07 +0100 Subject: [PATCH 083/107] allow to show website in iframe for metrika to work properly --- landing_page/landing_page/settings.py | 1 + 1 file changed, 1 insertion(+) diff --git a/landing_page/landing_page/settings.py b/landing_page/landing_page/settings.py index 23b1b84d..09aa7834 100644 --- a/landing_page/landing_page/settings.py +++ b/landing_page/landing_page/settings.py @@ -9,6 +9,7 @@ ALLOWED_HOSTS = ['*'] CSRF_TRUSTED_ORIGINS = ['https://learn.python.ru'] +X_FRAME_OPTIONS = "ALLOW" INSTALLED_APPS = [ 'mainpage.apps.MainpageConfig', From 31008a911fa7f0f6bb4bd40aa553b888da033900 Mon Sep 17 00:00:00 2001 From: Ilya Lebedev Date: Sun, 19 Nov 2023 12:24:49 +0100 Subject: [PATCH 084/107] replace videos with real feedback --- landing_page/mainpage/admin.py | 3 +- .../mainpage/migrations/0044_coursereview.py | 25 ++++++++++++++++ landing_page/mainpage/models.py | 8 +++++ .../templates/mainpage/include/index_faq.html | 21 ++++++++++++++ .../mainpage/include/index_reviews.html | 17 +++-------- .../mainpage/templates/mainpage/index.html | 2 +- landing_page/mainpage/views.py | 29 ++----------------- 7 files changed, 63 insertions(+), 42 deletions(-) create mode 100644 landing_page/mainpage/migrations/0044_coursereview.py diff --git a/landing_page/mainpage/admin.py b/landing_page/mainpage/admin.py index 7c000024..3e6dd497 100644 --- a/landing_page/mainpage/admin.py +++ b/landing_page/mainpage/admin.py @@ -1,7 +1,8 @@ from django.contrib import admin -from .models import Curators, Enrollment, GraduateProjects +from .models import CourseReview, Curators, Enrollment, GraduateProjects admin.site.register(Curators) admin.site.register(GraduateProjects) admin.site.register(Enrollment) +admin.site.register(CourseReview) diff --git a/landing_page/mainpage/migrations/0044_coursereview.py b/landing_page/mainpage/migrations/0044_coursereview.py new file mode 100644 index 00000000..ad76f100 --- /dev/null +++ b/landing_page/mainpage/migrations/0044_coursereview.py @@ -0,0 +1,25 @@ +# Generated by Django 4.2.4 on 2023-11-19 11:21 + +import mainpage.models +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('mainpage', '0043_enrollment_type'), + ] + + operations = [ + migrations.CreateModel( + name='CourseReview', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('title', models.CharField(max_length=254)), + ('text', models.TextField()), + ('review_for', models.CharField(blank=True, choices=[(mainpage.models.EnrollmentType['BASE'], mainpage.models.EnrollmentType['BASE']), (mainpage.models.EnrollmentType['ADVANCED'], mainpage.models.EnrollmentType['ADVANCED'])], max_length=10, null=True)), + ('reviewer_name', models.CharField(blank=True, max_length=254, null=True)), + ('reviewed_at', models.DateField()), + ], + ), + ] diff --git a/landing_page/mainpage/models.py b/landing_page/mainpage/models.py index 44b1622f..416a892a 100644 --- a/landing_page/mainpage/models.py +++ b/landing_page/mainpage/models.py @@ -88,3 +88,11 @@ def get_enrollment_with_active_registration(enrollment_type: EnrollmentType) -> def __str__(self) -> str: return f"{self.type.capitalize() if self.type else 'NO TYPE'} enrollment ({self.start_date} - {self.end_date})" + + +class CourseReview(models.Model): + title = models.CharField(max_length=254) + text = models.TextField() + review_for = models.CharField(max_length=10, choices=EnrollmentType.get_choices(), null=True, blank=True) + reviewer_name = models.CharField(max_length=254, null=True, blank=True) + reviewed_at = models.DateField() diff --git a/landing_page/mainpage/templates/mainpage/include/index_faq.html b/landing_page/mainpage/templates/mainpage/include/index_faq.html index bc226ea3..f260f8e0 100644 --- a/landing_page/mainpage/templates/mainpage/include/index_faq.html +++ b/landing_page/mainpage/templates/mainpage/include/index_faq.html @@ -265,6 +265,27 @@
    + + diff --git a/landing_page/mainpage/templates/mainpage/include/index_reviews.html b/landing_page/mainpage/templates/mainpage/include/index_reviews.html index d40ca62a..80818364 100644 --- a/landing_page/mainpage/templates/mainpage/include/index_reviews.html +++ b/landing_page/mainpage/templates/mainpage/include/index_reviews.html @@ -40,21 +40,12 @@

    1000+

      +
    • +

      Telegram

      + @v_dombrovsky +
    • Email

      - team@python.ru + lp@python.ru
    • Наш сайт

      From 19e239c242d574b82b08fda81ebc3874cace77c6 Mon Sep 17 00:00:00 2001 From: Ilya Lebedev Date: Wed, 22 Nov 2023 09:18:27 +0100 Subject: [PATCH 086/107] add description tags --- landing_page/mainpage/templates/mainpage/advanced.html | 1 + landing_page/mainpage/templates/mainpage/index.html | 1 + 2 files changed, 2 insertions(+) diff --git a/landing_page/mainpage/templates/mainpage/advanced.html b/landing_page/mainpage/templates/mainpage/advanced.html index ad8a9614..1ddbd54b 100644 --- a/landing_page/mainpage/templates/mainpage/advanced.html +++ b/landing_page/mainpage/templates/mainpage/advanced.html @@ -5,6 +5,7 @@ + diff --git a/landing_page/mainpage/templates/mainpage/index.html b/landing_page/mainpage/templates/mainpage/index.html index 08d237ff..e4b79b31 100644 --- a/landing_page/mainpage/templates/mainpage/index.html +++ b/landing_page/mainpage/templates/mainpage/index.html @@ -5,6 +5,7 @@ + From 43d5b454ce83e2ab447d1613b4df08d95d64cebf Mon Sep 17 00:00:00 2001 From: Ilya Lebedev Date: Wed, 22 Nov 2023 09:40:37 +0100 Subject: [PATCH 087/107] hello sitemap --- landing_page/landing_page/settings.py | 4 ++++ landing_page/landing_page/sitemap.py | 19 ++++++++++++++++++ landing_page/landing_page/urls.py | 9 +++++++++ landing_page/mainpage/utils/github.py | 29 +++++++++++++++++++++++++++ requirements-dev.txt | 1 + requirements.txt | 2 ++ 6 files changed, 64 insertions(+) create mode 100644 landing_page/landing_page/sitemap.py create mode 100644 landing_page/mainpage/utils/github.py diff --git a/landing_page/landing_page/settings.py b/landing_page/landing_page/settings.py index 09aa7834..29285c74 100644 --- a/landing_page/landing_page/settings.py +++ b/landing_page/landing_page/settings.py @@ -13,12 +13,16 @@ INSTALLED_APPS = [ 'mainpage.apps.MainpageConfig', + 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', + 'django.contrib.sitemaps', + + 'memoize', ] MIDDLEWARE = [ diff --git a/landing_page/landing_page/sitemap.py b/landing_page/landing_page/sitemap.py new file mode 100644 index 00000000..83a36418 --- /dev/null +++ b/landing_page/landing_page/sitemap.py @@ -0,0 +1,19 @@ +import datetime + +from django.contrib.sitemaps import Sitemap +from django.urls import reverse +from mainpage.utils.github import fetch_last_commit_date_from_github_repo + + +class LearnSitemap(Sitemap): + changefreq = "weekly" + priority = 0.5 + + def items(self) -> list[str]: + return ["index", "index_advanced"] + + def location(self, item: str) -> str: + return reverse(item) + + def lastmod(self, obj: str) -> datetime.datetime | None: + return fetch_last_commit_date_from_github_repo('moscowpython', 'learnpython') diff --git a/landing_page/landing_page/urls.py b/landing_page/landing_page/urls.py index 65c77bb0..73a8d8ba 100644 --- a/landing_page/landing_page/urls.py +++ b/landing_page/landing_page/urls.py @@ -1,7 +1,16 @@ from django.contrib import admin +from django.contrib.sitemaps.views import sitemap from django.urls import include, path +from landing_page.sitemap import LearnSitemap + urlpatterns = [ path('', include('mainpage.urls')), path('admin/', admin.site.urls), + path( + "sitemap.xml", + sitemap, + {"sitemaps": {"static": LearnSitemap}}, + name="django.contrib.sitemaps.views.sitemap", + ) ] diff --git a/landing_page/mainpage/utils/github.py b/landing_page/mainpage/utils/github.py new file mode 100644 index 00000000..75af065a --- /dev/null +++ b/landing_page/mainpage/utils/github.py @@ -0,0 +1,29 @@ +import datetime + +import requests +from memoize import memoize + + +@memoize(timeout=24 * 60 * 60) +def fetch_last_commit_date_from_github_repo( + owner: str, + repo_name: str, + timeout_msec: int = 500, +) -> datetime.datetime | None: + response = requests.get( + f"https://api.github.com/repos/{owner}/{repo_name}/commits", + timeout=timeout_msec / 1000, + ) + if not response: + return None + all_commits = response.json() + if not isinstance(all_commits, list) or not all_commits: + return None + last_commit = all_commits[0] + raw_commit_date = last_commit.get("commit", {}).get("author", {}).get("date") + try: + last_commit_date = datetime.datetime.fromisoformat(raw_commit_date) if raw_commit_date else None + except ValueError: + last_commit_date = None + + return last_commit_date diff --git a/requirements-dev.txt b/requirements-dev.txt index f1e7934f..73c4fb51 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -4,3 +4,4 @@ mypy==1.5.0 isort==5.12.0 pytest==7.4.0 pytest-django==4.5.2 +types-requests==2.31.0.10 diff --git a/requirements.txt b/requirements.txt index bcc4ff27..a56b32c2 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,2 +1,4 @@ Django==4.2.4 Pillow==10.0.0 +requests==2.31.0 +django-memoize==2.3.1 From 2b0614181a407afc28171e7b760dacc05cf6507e Mon Sep 17 00:00:00 2001 From: Ilya Lebedev Date: Wed, 22 Nov 2023 10:03:15 +0100 Subject: [PATCH 088/107] hello robots.txt --- landing_page/landing_page/urls.py | 4 +++- landing_page/mainpage/templates/mainpage/advanced.html | 2 +- landing_page/mainpage/templates/mainpage/index.html | 2 +- landing_page/mainpage/templates/mainpage/robots.txt | 5 +++++ landing_page/mainpage/urls.py | 2 ++ landing_page/mainpage/views.py | 7 +++++++ 6 files changed, 19 insertions(+), 3 deletions(-) create mode 100644 landing_page/mainpage/templates/mainpage/robots.txt diff --git a/landing_page/landing_page/urls.py b/landing_page/landing_page/urls.py index 73a8d8ba..e05589bd 100644 --- a/landing_page/landing_page/urls.py +++ b/landing_page/landing_page/urls.py @@ -6,11 +6,13 @@ urlpatterns = [ path('', include('mainpage.urls')), + path('admin/', admin.site.urls), + path( "sitemap.xml", sitemap, {"sitemaps": {"static": LearnSitemap}}, name="django.contrib.sitemaps.views.sitemap", - ) + ), ] diff --git a/landing_page/mainpage/templates/mainpage/advanced.html b/landing_page/mainpage/templates/mainpage/advanced.html index 1ddbd54b..db424bd9 100644 --- a/landing_page/mainpage/templates/mainpage/advanced.html +++ b/landing_page/mainpage/templates/mainpage/advanced.html @@ -24,7 +24,7 @@ - Learn Python - Курсы Python онлайн + Learn Python Advanced - продвинутые курсы Python онлайн {% include 'mainpage/include/common/counters.html' %} diff --git a/landing_page/mainpage/templates/mainpage/index.html b/landing_page/mainpage/templates/mainpage/index.html index e4b79b31..943711e8 100644 --- a/landing_page/mainpage/templates/mainpage/index.html +++ b/landing_page/mainpage/templates/mainpage/index.html @@ -24,7 +24,7 @@ - Learn Python - Курсы Python онлайн + Learn Python - курсы Python онлайн {% include 'mainpage/include/common/counters.html' %} diff --git a/landing_page/mainpage/templates/mainpage/robots.txt b/landing_page/mainpage/templates/mainpage/robots.txt new file mode 100644 index 00000000..31734444 --- /dev/null +++ b/landing_page/mainpage/templates/mainpage/robots.txt @@ -0,0 +1,5 @@ +User-agent: * +Disallow: /admin/ +Disallow: /success/ +Sitemap: http://learn.python.ru/sitemap.xml +Clean-param: * diff --git a/landing_page/mainpage/urls.py b/landing_page/mainpage/urls.py index 6dd2cf1e..50d49783 100644 --- a/landing_page/mainpage/urls.py +++ b/landing_page/mainpage/urls.py @@ -8,4 +8,6 @@ path('advanced/', views.advanced_handle, name='index_advanced'), path('advanced/success/', views.success_handle_advanced, name='success_advanced'), + + path('robots.txt', views.robots_txt_handle, name='robots_txt'), ] diff --git a/landing_page/mainpage/views.py b/landing_page/mainpage/views.py index 558836c4..e6c0912c 100644 --- a/landing_page/mainpage/views.py +++ b/landing_page/mainpage/views.py @@ -58,3 +58,10 @@ def success_handle_advanced(request: HttpRequest) -> HttpResponse: 'enrollment': enrollment, }, ) + + +def robots_txt_handle(request: HttpRequest) -> HttpResponse: + return render( + request, + 'mainpage/robots.txt', + ) From 81aaa248efeb8703b5375ae2676b024c8581b3b6 Mon Sep 17 00:00:00 2001 From: Ilya Lebedev Date: Wed, 22 Nov 2023 11:24:46 +0100 Subject: [PATCH 089/107] update robots --- landing_page/mainpage/static/robots.txt | 6 ++++-- landing_page/mainpage/templates/mainpage/robots.txt | 5 ----- landing_page/mainpage/urls.py | 1 - landing_page/mainpage/views.py | 7 ------- 4 files changed, 4 insertions(+), 15 deletions(-) delete mode 100644 landing_page/mainpage/templates/mainpage/robots.txt diff --git a/landing_page/mainpage/static/robots.txt b/landing_page/mainpage/static/robots.txt index 6d286774..31734444 100644 --- a/landing_page/mainpage/static/robots.txt +++ b/landing_page/mainpage/static/robots.txt @@ -1,3 +1,5 @@ User-agent: * -Disallow: *lessons* -Host: https://learn.python.ru/ \ No newline at end of file +Disallow: /admin/ +Disallow: /success/ +Sitemap: http://learn.python.ru/sitemap.xml +Clean-param: * diff --git a/landing_page/mainpage/templates/mainpage/robots.txt b/landing_page/mainpage/templates/mainpage/robots.txt deleted file mode 100644 index 31734444..00000000 --- a/landing_page/mainpage/templates/mainpage/robots.txt +++ /dev/null @@ -1,5 +0,0 @@ -User-agent: * -Disallow: /admin/ -Disallow: /success/ -Sitemap: http://learn.python.ru/sitemap.xml -Clean-param: * diff --git a/landing_page/mainpage/urls.py b/landing_page/mainpage/urls.py index 50d49783..5d2d0066 100644 --- a/landing_page/mainpage/urls.py +++ b/landing_page/mainpage/urls.py @@ -9,5 +9,4 @@ path('advanced/', views.advanced_handle, name='index_advanced'), path('advanced/success/', views.success_handle_advanced, name='success_advanced'), - path('robots.txt', views.robots_txt_handle, name='robots_txt'), ] diff --git a/landing_page/mainpage/views.py b/landing_page/mainpage/views.py index e6c0912c..558836c4 100644 --- a/landing_page/mainpage/views.py +++ b/landing_page/mainpage/views.py @@ -58,10 +58,3 @@ def success_handle_advanced(request: HttpRequest) -> HttpResponse: 'enrollment': enrollment, }, ) - - -def robots_txt_handle(request: HttpRequest) -> HttpResponse: - return render( - request, - 'mainpage/robots.txt', - ) From b50f67c32050b2fedbaa9b7a1fde097f714e01e3 Mon Sep 17 00:00:00 2001 From: Ilya Lebedev Date: Wed, 22 Nov 2023 11:29:25 +0100 Subject: [PATCH 090/107] update robots --- landing_page/mainpage/static/robots.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/landing_page/mainpage/static/robots.txt b/landing_page/mainpage/static/robots.txt index 31734444..3865dbed 100644 --- a/landing_page/mainpage/static/robots.txt +++ b/landing_page/mainpage/static/robots.txt @@ -1,5 +1,6 @@ User-agent: * Disallow: /admin/ Disallow: /success/ +Disallow: /lessons/ Sitemap: http://learn.python.ru/sitemap.xml -Clean-param: * +Clean-param: utm ref source trk 1* 2* 3* 4* 5* 6* 7* 8* 9* From 1b37a8900d3b00eb9694842501abd97380277a3e Mon Sep 17 00:00:00 2001 From: Ilya Lebedev Date: Wed, 22 Nov 2023 11:32:27 +0100 Subject: [PATCH 091/107] fix clean param --- landing_page/mainpage/static/robots.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/landing_page/mainpage/static/robots.txt b/landing_page/mainpage/static/robots.txt index 3865dbed..979a6b5d 100644 --- a/landing_page/mainpage/static/robots.txt +++ b/landing_page/mainpage/static/robots.txt @@ -3,4 +3,4 @@ Disallow: /admin/ Disallow: /success/ Disallow: /lessons/ Sitemap: http://learn.python.ru/sitemap.xml -Clean-param: utm ref source trk 1* 2* 3* 4* 5* 6* 7* 8* 9* +Clean-param: utm ref source trk From f7d4771b4906f58949055b55932ed93fc5e68178 Mon Sep 17 00:00:00 2001 From: Ilya Lebedev Date: Wed, 22 Nov 2023 11:37:05 +0100 Subject: [PATCH 092/107] fix clean param --- landing_page/mainpage/static/robots.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/landing_page/mainpage/static/robots.txt b/landing_page/mainpage/static/robots.txt index 979a6b5d..918dd501 100644 --- a/landing_page/mainpage/static/robots.txt +++ b/landing_page/mainpage/static/robots.txt @@ -3,4 +3,4 @@ Disallow: /admin/ Disallow: /success/ Disallow: /lessons/ Sitemap: http://learn.python.ru/sitemap.xml -Clean-param: utm ref source trk +Clean-param: utm&ref&source&trk From 704e6a63b6b539fd3a1a1c6dded6893a0bffdc02 Mon Sep 17 00:00:00 2001 From: Ilya Lebedev Date: Thu, 23 Nov 2023 11:30:32 +0100 Subject: [PATCH 093/107] add chat --- Makefile | 2 ++ landing_page/landing_page/settings.py | 2 ++ landing_page/mainpage/templates/mainpage/index.html | 9 ++++++++- landing_page/mainpage/views.py | 2 ++ requirements.txt | 1 + 5 files changed, 15 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index de5cc2ed..09bc7fb1 100644 --- a/Makefile +++ b/Makefile @@ -12,3 +12,5 @@ run: cd landing_page; DEBUG=1 python manage.py runserver shell: cd landing_page; DEBUG=1 python manage.py shell +migrate: + cd landing_page; DEBUG=1 python manage.py migrate diff --git a/landing_page/landing_page/settings.py b/landing_page/landing_page/settings.py index 29285c74..c1506d8b 100644 --- a/landing_page/landing_page/settings.py +++ b/landing_page/landing_page/settings.py @@ -23,6 +23,7 @@ 'django.contrib.sitemaps', 'memoize', + 'waffle', ] MIDDLEWARE = [ @@ -33,6 +34,7 @@ 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', + 'waffle.middleware.WaffleMiddleware', ] ROOT_URLCONF = 'landing_page.urls' diff --git a/landing_page/mainpage/templates/mainpage/index.html b/landing_page/mainpage/templates/mainpage/index.html index 943711e8..c5e4143f 100644 --- a/landing_page/mainpage/templates/mainpage/index.html +++ b/landing_page/mainpage/templates/mainpage/index.html @@ -267,8 +267,14 @@

      онлайн курс

      {% include 'mainpage/include/index_faq.html' %} + {% if should_show_chat %} +
      + {% endif %} {% include 'mainpage/include/index_footer.html' %} - {% include 'mainpage/include/index_register_popup.html' with enrollment=enrollment %} @@ -291,5 +297,6 @@

      онлайн курс

      crossorigin="anonymous" referrerpolicy="no-referrer" > + diff --git a/landing_page/mainpage/views.py b/landing_page/mainpage/views.py index 558836c4..20962449 100644 --- a/landing_page/mainpage/views.py +++ b/landing_page/mainpage/views.py @@ -2,6 +2,7 @@ from django.http import HttpRequest, HttpResponse from django.shortcuts import render +from waffle import switch_is_active from .models import CourseReview, Curators, Enrollment, EnrollmentType, GraduateProjects @@ -18,6 +19,7 @@ def index(request: HttpRequest) -> HttpResponse: 'curators_list': Curators.objects.filter(is_visible=True), 'today': date.today(), 'reviews': CourseReview.objects.filter(review_for=EnrollmentType.BASE), + 'should_show_chat': switch_is_active('show_tg_chat_widget'), } return render(request, 'mainpage/index.html', context) diff --git a/requirements.txt b/requirements.txt index a56b32c2..c080ccbb 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,3 +2,4 @@ Django==4.2.4 Pillow==10.0.0 requests==2.31.0 django-memoize==2.3.1 +django-waffle==4.0.0 From 283805684cd6e88382cf83bebd4338063ea761ed Mon Sep 17 00:00:00 2001 From: Ilya Lebedev Date: Sat, 25 Nov 2023 07:12:50 +0100 Subject: [PATCH 094/107] change x fram options header value --- landing_page/landing_page/settings.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/landing_page/landing_page/settings.py b/landing_page/landing_page/settings.py index c1506d8b..8c759562 100644 --- a/landing_page/landing_page/settings.py +++ b/landing_page/landing_page/settings.py @@ -9,7 +9,7 @@ ALLOWED_HOSTS = ['*'] CSRF_TRUSTED_ORIGINS = ['https://learn.python.ru'] -X_FRAME_OPTIONS = "ALLOW" +X_FRAME_OPTIONS = "SAMEORIGIN" INSTALLED_APPS = [ 'mainpage.apps.MainpageConfig', From 4d7772bb4213f37adb73d6bc6bb94e5c8ee2e02d Mon Sep 17 00:00:00 2001 From: Ilya Lebedev Date: Mon, 27 Nov 2023 08:36:59 +0100 Subject: [PATCH 095/107] hello calltouch --- .../mainpage/include/common/counters.html | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/landing_page/mainpage/templates/mainpage/include/common/counters.html b/landing_page/mainpage/templates/mainpage/include/common/counters.html index 33e273b2..62e3ea04 100644 --- a/landing_page/mainpage/templates/mainpage/include/common/counters.html +++ b/landing_page/mainpage/templates/mainpage/include/common/counters.html @@ -42,3 +42,40 @@ + + + + From e9e678d7cea484395f266cb235cf7ab932039f64 Mon Sep 17 00:00:00 2001 From: Ilya Lebedev Date: Fri, 1 Dec 2023 08:24:18 +0100 Subject: [PATCH 096/107] hello new favicons --- .../mainpage/static/images/favicon_lp_120.png | Bin 0 -> 1651 bytes .../mainpage/static/images/favicon_lp_16.png | Bin 0 -> 377 bytes .../mainpage/static/images/favicon_lpa_120.png | Bin 0 -> 1816 bytes .../mainpage/static/images/favicon_lpa_16.png | Bin 0 -> 379 bytes .../mainpage/templates/mainpage/advanced.html | 2 +- .../mainpage/templates/mainpage/index.html | 2 +- .../mainpage/templates/mainpage/success.html | 2 +- 7 files changed, 3 insertions(+), 3 deletions(-) create mode 100644 landing_page/mainpage/static/images/favicon_lp_120.png create mode 100644 landing_page/mainpage/static/images/favicon_lp_16.png create mode 100644 landing_page/mainpage/static/images/favicon_lpa_120.png create mode 100644 landing_page/mainpage/static/images/favicon_lpa_16.png diff --git a/landing_page/mainpage/static/images/favicon_lp_120.png b/landing_page/mainpage/static/images/favicon_lp_120.png new file mode 100644 index 0000000000000000000000000000000000000000..98e5ab00b04a294bb388bd3984598df6d6f881e9 GIT binary patch literal 1651 zcmbtUdo-!j+bB)KBr(enP3$+XCJa$Z z2tTEzGLl$&n0aLKiXMzGzxm_$&+qi#@1FCypL6d$=RVH8=cXKTbJ(b?sSE(XMw}xS zFXKWPiXe(IjmdgQlhHb|qxX3LSg*bY5Wr$@lQ}`>@eZ~?)obl>nIRu+<7xu{_tV!e zpHct-MFm)$U*}hbY*(wL%*BL*S?@Q*f`YElZ@ybqS?|7H ztMIbx*_!v7(pdzqW1ipgNF^X9V1^lMnF}%bYSQ*YtV8W@l!QLe-Jy$diQGKgBAm3I zj{M7%ssYCY`V(55doKhZ&{TteKU3d*Z>jw9NJ$3-gs5hfhjk)t!B|zDp#h!F)*ie( z&5zh#G7F0!973Wm3HRd~esIp-F|c2OP0T*)9Nz!=LT^86D1dUYX=`*yI^bOL&Z_Kg zokc`@lHOs#wVVwk_L=&WQ6qyvWiLfWxxRIM7eyZc?JDcuvSGE`Jo=njI+_eMci7TTJ$HFmqJfX@PFVQ zr4Dz?c67E)SJ();4Yv*nv(v!=6y~VY{1`YZXW47Ny{0!wWQcL;xq&GNsmUC@Bu`6O zZYq?I4w&}I9)rS5Oj%A4y(R^YSxZcEqAmt&7oS6wrkR?jBZ;EHg4?@kndniCH!fj-V{}kqzNm zYOUMASQG(AbcRpX#l57-MoEu5vM*-3Wo1eNRfD&AV(FC{J^Tl?a-dP9rNf)%#z zrlfQnqB_&CKve0K8rw~cH8KhS)Mp1Pjg!uFlM*H+c*i@XV-eCs4nkaXopeyShIH<0 z&;W#tTO?E>1-$JuA%}w$lQ<$G(i}RNY37q(=W`=;epa6&9?pV|C#S~!0os)@)cSb~ zw?S_yX_fo%EW*n(Gl^bBSJ5!01atSCkGm##b9~>rdx5y;Q-4npnRTvL+j+hvDgj1C z^&`|~*2UOZ^g>52!1vO!tD)hAbvB<&wNGg(7U7qUpsy3pxW+?JSqqk6>6 zvAbDicdhsHv2e8nW4y&1-?@s$?YSs0Z|^ucjnpj6%v6P22`Hw?2e#MGR%N&F4MDAw zjiC+GLwA3sJUl3oZnTN#kC77($0DSqee-ur`C0TP2-)UKa_v#s9irQciP+0KlhY+Z zgZ>tV;~{B8Z&kln{U1ieA==J)gbq0b5{&iyceS?>YpbTw0q7Rc{|&G{OdJ)o!<%DP zud##d@07OvRQWtO@F35bTX-Qg{zcghf@E^u+*}ehN2GXA&@3bQC`4G3#p+^t;RSiK zE43e0Z>IgH4~Ej2%zR8HulNPk`rb3f@$VJN)nl6jK;;v1-q9>8VZ-~yFSZaUH|0UMbXTjk3nzg&3eE8!E0VN ZY83?4R+93JU$0-YadvLlDqFvVe*j-H>8$_& literal 0 HcmV?d00001 diff --git a/landing_page/mainpage/static/images/favicon_lp_16.png b/landing_page/mainpage/static/images/favicon_lp_16.png new file mode 100644 index 0000000000000000000000000000000000000000..eb69d5b48ce83cbbd69a2e4028f37e938eb9b501 GIT binary patch literal 377 zcmV-<0fzpGP)<{Z+6&a= z+ZzG4m{qHzMzv_HsB!|9N7rxBY;yQ@hhYDG0YC_CAQNcE*jW7o Xk1SaZY^lvB00000NkvXXu0mjf_zIR6 literal 0 HcmV?d00001 diff --git a/landing_page/mainpage/static/images/favicon_lpa_120.png b/landing_page/mainpage/static/images/favicon_lpa_120.png new file mode 100644 index 0000000000000000000000000000000000000000..e1f001fca6f98c6698c616f1678e18814f1d48af GIT binary patch literal 1816 zcmZ`)X*e5*7EO$zwH9TbX{Ed>Qnf}*h+2!-q7o5AY$Zjlq12k^S;kg_4i(f=(juW+ z5yV!aYF}DvXG&tL<_%+KjQ)H-=6>I~=ey^-KhC*-ZmONFx$q^KO8@{s7-3;*f6kHL zA;5RuVfUfq=X5dH!ifj~2ugeh5I`>a@mvHF?ahq=wZm7}&j((Dk&O`mP@g4u;&A~0 z;G-c-jnI+6t+{tWk`7n-|F_5;YAn@giPrFi|BSb=W}!38QkR1F3Fh_G!-YnxwMR^@4tFRo?=()_oq60J zcwG2+Cyu*6tH5*a;h&1MDzLx!$E0+Gg#BI3NOeNQ@HhW)s1yEK70QUn@hLvJKi{Dp z9u+UcWk|38tGQ^drlY7s-JGg(3U`)HFIkA9*<6_wTVklq>C+0@W%h(yM)TwJm|RHa zvx|XL$fCNAS2aGRKx)T$5yEdb6IoY0{)?;r!G0LcjI%oCB1?59?i|n@k@iWSk`>)` zH;(u){V<9+%;w{R1pf&-#Z;pNb$Rh%b?@tTcam3retc1?uc@E*yo?ks-DxB?`ho8g za0N83%4BjH zi^@cB0zg!%Mn+BLOf%Q6v@W+2tEK4Ou4oT8xne|0QUAP(SqsxIIOa`9PF>M)003oc zWw(AGkR%l#?>*kl$LwQ5Q(ujJ%U{R0GwILt9alJKwqMa(xt26HE3a+4<+Y+i#Y#iw zozA4moy>??o4%=UUCQOGA_sGuP6_ce`Mo3Wnh(@pZ0>NnRU5xTVl`u5m;m4Vr8P3K z9QP)y!KkjMh!C^v`Vo8j?ZM(~FaD*tb6;q&_J!MdcvZa6f}PB)|7-otbliw#ufcfF zWpLRC&`=W;iW^jsD3Zw9l^?)64xyFi&u-J#lyi?oE~ju*I6@>cZ1nnx8fTf;tehCzwz0lP$E7exEW2}TiG3b zmhSfk&9Z(uyjkgrDH+UqtSlH8BkhUjq z$)8v)HZe7jYZIT8wb*%mYH#1`br5PK>P%QuL+9O&(+-rBBf|_B50~wMbOdZ~h znO?Y+du$0dFNTjuyMR=BhO^0JO8?5n%9=L2@=3_@Pwp;ocTR&+TA`1ue<7R^#zm!4 zTB2ys`s*&617--~7gvybBSDr3UDJ?gJ>JyOn>X0ImVAry7c*b?4sc6)94&1*^OUjq zLy>=MWk~5nMSxG?Mp(W5w4PWDRfk;+g7T%SARQnRNjVUbj9v&V{p@9BwGjqf?Mc1!x5fE^3BCbC|m% zs~k={w5hGVMvP_>PpRFEtyAXaf@JoOLEVzB2}qRdt5FI(OAGsXKmM`f!oZEL=}WZ1 zvpCLB#-rDP9{-tNejZpY=v}xynA{IrRs55x%`WD4EE3Whkx%U^AvSimp*ogr{|#au zo|}FX{>48ff6$4FdmO<~u8ZePAy8ooASZROoK1Myb^uP8zoWeAuoQ%uP*C6bir~WA041ged3@zQyP!3uqIM_?#{w=(;KSwq@BUhG; zz$&U#(FK%N%=S{Bvxf=kH&t*)+=mb*SLB#}E7FNUGVr9%6Y3C|oEkhXKs?;w=bJ>~ zft}Q*h-egsan=RWa$cQnDfjM~F4ihENSSGme{i}}&c8nDyuO2V uo_L?UMyIlu|0wM>-);W*Paom`bcZ9*QGA9^3ID;}?>geHt!b^Xd&1vh^``W z$lZxy-8q?;Kn_c~qpu?a!^VE@KZ&eBIRQ@>$B+ufw|;xQ4+jYBul95m_f;>fuIqJb z_B-1DLtNs>-Ca9gy;+nm;9e@i;_i4cr8FQgT`-nK@QnhCOGen#J2Nk{McrC>q3D7^y`?2i8S*8#( z1E+<0vmE(%95i5juid)4K6hp0FTdr=>lGJBYJLB=i`76qe2&Qdr3Vrfk~P0Xa|t** z6*!;x9JbE=mMqKG3HLVDJlSihv?2Sd@NIq7pZxLqr&ccxpD>?i`=+};-!!`OXrB?e z-7)*G=lqQC|CskxC7-LEU2@4u-v0P0lcG$c&l|-v{Z8oI - + Learn Python Advanced - продвинутые курсы Python онлайн {% include 'mainpage/include/common/counters.html' %} diff --git a/landing_page/mainpage/templates/mainpage/index.html b/landing_page/mainpage/templates/mainpage/index.html index c5e4143f..cb6cb585 100644 --- a/landing_page/mainpage/templates/mainpage/index.html +++ b/landing_page/mainpage/templates/mainpage/index.html @@ -23,7 +23,7 @@ - + Learn Python - курсы Python онлайн {% include 'mainpage/include/common/counters.html' %} diff --git a/landing_page/mainpage/templates/mainpage/success.html b/landing_page/mainpage/templates/mainpage/success.html index 86a7c20e..fc44c1ef 100644 --- a/landing_page/mainpage/templates/mainpage/success.html +++ b/landing_page/mainpage/templates/mainpage/success.html @@ -22,7 +22,7 @@ - + Learn Python - Курсы Python онлайн {% include 'mainpage/include/common/counters.html' %} From dfe262fe46561996c9a125b0d0cc7fa1151a1dc5 Mon Sep 17 00:00:00 2001 From: Ilya Lebedev Date: Mon, 4 Dec 2023 06:41:28 +0100 Subject: [PATCH 097/107] add advanced promo --- landing_page/mainpage/static/css/style.css | 5 +++++ landing_page/mainpage/static/robots.txt | 2 +- .../mainpage/templates/mainpage/include/index_modules.html | 5 +++++ 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/landing_page/mainpage/static/css/style.css b/landing_page/mainpage/static/css/style.css index 801879af..0334c792 100644 --- a/landing_page/mainpage/static/css/style.css +++ b/landing_page/mainpage/static/css/style.css @@ -4762,3 +4762,8 @@ ul.installment-plan li:before { text-transform: none; } +.advanced-promo { + background: #252526; + color: #ffffff; + padding: 15px; +} diff --git a/landing_page/mainpage/static/robots.txt b/landing_page/mainpage/static/robots.txt index 918dd501..8c3094db 100644 --- a/landing_page/mainpage/static/robots.txt +++ b/landing_page/mainpage/static/robots.txt @@ -3,4 +3,4 @@ Disallow: /admin/ Disallow: /success/ Disallow: /lessons/ Sitemap: http://learn.python.ru/sitemap.xml -Clean-param: utm&ref&source&trk +Clean-param: utm&ref&source&trk&&5030bbc2 diff --git a/landing_page/mainpage/templates/mainpage/include/index_modules.html b/landing_page/mainpage/templates/mainpage/include/index_modules.html index 501e27b0..424478fb 100644 --- a/landing_page/mainpage/templates/mainpage/include/index_modules.html +++ b/landing_page/mainpage/templates/mainpage/include/index_modules.html @@ -137,6 +137,11 @@

      Программа

    +

    + Ещё у нас есть + продвинутый курс + для тех, кто уже освоил эту программу. +

    From a4dfc8fd8e9ca1e6a79beaac749317862fe9b289 Mon Sep 17 00:00:00 2001 From: Ilya Lebedev Date: Mon, 4 Dec 2023 06:53:56 +0100 Subject: [PATCH 098/107] add reviews for advanced --- landing_page/mainpage/models.py | 3 +++ landing_page/mainpage/templates/mainpage/advanced.html | 4 ++++ .../templates/mainpage/include/advanced/index_menu.html | 8 +------- .../mainpage/include/{ => common}/index_reviews.html | 0 landing_page/mainpage/templates/mainpage/index.html | 4 +++- landing_page/mainpage/views.py | 1 + 6 files changed, 12 insertions(+), 8 deletions(-) rename landing_page/mainpage/templates/mainpage/include/{ => common}/index_reviews.html (100%) diff --git a/landing_page/mainpage/models.py b/landing_page/mainpage/models.py index 416a892a..b34a9eeb 100644 --- a/landing_page/mainpage/models.py +++ b/landing_page/mainpage/models.py @@ -96,3 +96,6 @@ class CourseReview(models.Model): review_for = models.CharField(max_length=10, choices=EnrollmentType.get_choices(), null=True, blank=True) reviewer_name = models.CharField(max_length=254, null=True, blank=True) reviewed_at = models.DateField() + + def __str__(self) -> str: + return f'{self.title} ({self.review_for})' diff --git a/landing_page/mainpage/templates/mainpage/advanced.html b/landing_page/mainpage/templates/mainpage/advanced.html index 570adfa2..e50837bf 100644 --- a/landing_page/mainpage/templates/mainpage/advanced.html +++ b/landing_page/mainpage/templates/mainpage/advanced.html @@ -231,6 +231,10 @@

    онлайн курс

    + {% if reviews %} + {% include 'mainpage/include/common/index_reviews.html' with reviews=reviews %} + {% endif %} + {% if enrollment.platim_url %} {% include 'mainpage/include/index_how_to_pay_by_platim.html' %} {% else %} diff --git a/landing_page/mainpage/templates/mainpage/include/advanced/index_menu.html b/landing_page/mainpage/templates/mainpage/include/advanced/index_menu.html index a21c5368..bebf06a3 100644 --- a/landing_page/mainpage/templates/mainpage/include/advanced/index_menu.html +++ b/landing_page/mainpage/templates/mainpage/include/advanced/index_menu.html @@ -52,17 +52,11 @@ -