From f210a7e84b47898872b546d04905a909e0101a66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Y=C3=BBki=20Vachot?= Date: Mon, 24 Jan 2022 19:58:19 +0100 Subject: [PATCH] Create: db1 --- .github/workflows/docker-image.yml | 30 - backend/Dockerfile | 6 - backend/app.py | 8 - backend/application/__init__.py | 35 -- backend/application/api_functions.py | 364 ------------ backend/application/logs_model.py | 41 -- backend/application/responses.py | 35 -- backend/application/routes.py | 345 ----------- backend/application/sessionJWT.py | 39 -- backend/application/users_model.py | 37 -- backend/config.py | 43 -- backend/env.sh | 6 - backend/fictive_users.py | 47 -- backend/init-db1.sql | 13 - backend/init-db2.sql | 14 - backend/requirements.txt | 13 - backend/test.py | 542 ------------------ docker-compose.yml | 78 +-- frontend/.browserslistrc | 17 - frontend/.editorconfig | 16 - frontend/.gitignore | 49 -- frontend/Dockerfile | 6 - frontend/README.md | 27 - frontend/angular.json | 113 ---- frontend/karma.conf.js | 44 -- frontend/package.json | 44 -- .../src/app/admin/myProfil/commentary.txt | 7 - .../page-user-list.component.html | 67 --- .../page-user-list.component.scss | 18 - .../page-user-list.component.spec.ts | 25 - .../page-user-list.component.ts | 152 ----- .../popup-create-person.component.html | 47 -- .../popup-create-person.component.scss | 13 - .../popup-create-person.component.spec.ts | 25 - .../popup-create-person.component.ts | 95 --- .../popup-update-person-admin.component.html | 57 -- .../popup-update-person-admin.component.scss | 37 -- ...opup-update-person-admin.component.spec.ts | 25 - .../popup-update-person-admin.component.ts | 87 --- frontend/src/app/app-routing.module.ts | 31 - frontend/src/app/app.component.html | 2 - frontend/src/app/app.component.scss | 0 frontend/src/app/app.component.spec.ts | 35 -- frontend/src/app/app.component.ts | 10 - frontend/src/app/app.module.ts | 72 --- .../components/navbar/navbar.component.html | 108 ---- .../components/navbar/navbar.component.scss | 59 -- .../navbar/navbar.component.spec.ts | 25 - .../components/navbar/navbar.component.ts | 32 -- .../page-profil/page-profil.component.html | 53 -- .../page-profil/page-profil.component.scss | 45 -- .../page-profil/page-profil.component.spec.ts | 25 - .../page-profil/page-profil.component.ts | 110 ---- .../popup-delete-profil.component.html | 14 - .../popup-delete-profil.component.scss | 0 .../popup-delete-profil.component.spec.ts | 25 - .../popup-delete-profil.component.ts | 68 --- .../popup-update-profil.component.html | 55 -- .../popup-update-profil.component.scss | 37 -- .../popup-update-profil.component.spec.ts | 25 - .../popup-update-profil.component.ts | 108 ---- .../common/guards/admin/admin.guard.spec.ts | 16 - .../app/common/guards/admin/admin.guard.ts | 31 - .../app/common/guards/user/user.guard.spec.ts | 16 - .../src/app/common/guards/user/user.guard.ts | 31 - .../checkEmail/check-email.service.spec.ts | 16 - .../checkEmail/check-email.service.ts | 15 - .../fictitious-datas.service.spec.ts | 16 - .../fictitious-datas.service.ts | 47 -- .../services/hashage/hashage.service.spec.ts | 16 - .../services/hashage/hashage.service.ts | 19 - .../services/message/message.service.spec.ts | 16 - .../services/message/message.service.ts | 38 -- .../services/profil/profil.service.spec.ts | 16 - .../common/services/profil/profil.service.ts | 42 -- .../page-login/page-login.component.html | 40 -- .../page-login/page-login.component.scss | 271 --------- .../page-login/page-login.component.spec.ts | 25 - .../login/page-login/page-login.component.ts | 78 --- .../page-register.component.html | 49 -- .../page-register.component.scss | 21 - .../page-register.component.spec.ts | 25 - .../page-register/page-register.component.ts | 98 ---- .../popup-confirm-register.component.html | 2 - .../popup-confirm-register.component.scss | 0 .../popup-confirm-register.component.spec.ts | 25 - .../popup-confirm-register.component.ts | 13 - frontend/src/app/user/myProfil/commentary.txt | 7 - .../page-registry.component.html | 45 -- .../page-registry.component.scss | 9 - .../page-registry.component.spec.ts | 25 - .../page-registry/page-registry.component.ts | 57 -- frontend/src/assets/.gitkeep | 0 frontend/src/assets/logo.png | Bin 201990 -> 0 bytes frontend/src/assets/logo1.png | Bin 5798 -> 0 bytes frontend/src/environments/environment.prod.ts | 3 - frontend/src/environments/environment.ts | 18 - frontend/src/favicon.ico | Bin 948 -> 0 bytes frontend/src/index.html | 13 - frontend/src/main.ts | 12 - frontend/src/polyfills.ts | 53 -- frontend/src/styles.scss | 3 - frontend/src/test.ts | 27 - frontend/tsconfig.app.json | 15 - frontend/tsconfig.json | 33 -- frontend/tsconfig.spec.json | 18 - 106 files changed, 1 insertion(+), 4925 deletions(-) delete mode 100644 .github/workflows/docker-image.yml delete mode 100644 backend/Dockerfile delete mode 100644 backend/app.py delete mode 100644 backend/application/__init__.py delete mode 100644 backend/application/api_functions.py delete mode 100644 backend/application/logs_model.py delete mode 100644 backend/application/responses.py delete mode 100644 backend/application/routes.py delete mode 100644 backend/application/sessionJWT.py delete mode 100644 backend/application/users_model.py delete mode 100644 backend/config.py delete mode 100755 backend/env.sh delete mode 100644 backend/fictive_users.py delete mode 100755 backend/init-db1.sql delete mode 100644 backend/init-db2.sql delete mode 100644 backend/requirements.txt delete mode 100644 backend/test.py delete mode 100644 frontend/.browserslistrc delete mode 100644 frontend/.editorconfig delete mode 100644 frontend/.gitignore delete mode 100644 frontend/Dockerfile delete mode 100644 frontend/README.md delete mode 100644 frontend/angular.json delete mode 100644 frontend/karma.conf.js delete mode 100644 frontend/package.json delete mode 100644 frontend/src/app/admin/myProfil/commentary.txt delete mode 100644 frontend/src/app/admin/userList/page-user-list/page-user-list.component.html delete mode 100644 frontend/src/app/admin/userList/page-user-list/page-user-list.component.scss delete mode 100644 frontend/src/app/admin/userList/page-user-list/page-user-list.component.spec.ts delete mode 100644 frontend/src/app/admin/userList/page-user-list/page-user-list.component.ts delete mode 100644 frontend/src/app/admin/userList/popup-create-person/popup-create-person.component.html delete mode 100644 frontend/src/app/admin/userList/popup-create-person/popup-create-person.component.scss delete mode 100644 frontend/src/app/admin/userList/popup-create-person/popup-create-person.component.spec.ts delete mode 100644 frontend/src/app/admin/userList/popup-create-person/popup-create-person.component.ts delete mode 100644 frontend/src/app/admin/userList/popup-update-person-admin/popup-update-person-admin.component.html delete mode 100644 frontend/src/app/admin/userList/popup-update-person-admin/popup-update-person-admin.component.scss delete mode 100644 frontend/src/app/admin/userList/popup-update-person-admin/popup-update-person-admin.component.spec.ts delete mode 100644 frontend/src/app/admin/userList/popup-update-person-admin/popup-update-person-admin.component.ts delete mode 100644 frontend/src/app/app-routing.module.ts delete mode 100644 frontend/src/app/app.component.html delete mode 100644 frontend/src/app/app.component.scss delete mode 100644 frontend/src/app/app.component.spec.ts delete mode 100644 frontend/src/app/app.component.ts delete mode 100644 frontend/src/app/app.module.ts delete mode 100644 frontend/src/app/common/components/navbar/navbar.component.html delete mode 100644 frontend/src/app/common/components/navbar/navbar.component.scss delete mode 100644 frontend/src/app/common/components/navbar/navbar.component.spec.ts delete mode 100644 frontend/src/app/common/components/navbar/navbar.component.ts delete mode 100644 frontend/src/app/common/components/page-profil/page-profil.component.html delete mode 100644 frontend/src/app/common/components/page-profil/page-profil.component.scss delete mode 100644 frontend/src/app/common/components/page-profil/page-profil.component.spec.ts delete mode 100644 frontend/src/app/common/components/page-profil/page-profil.component.ts delete mode 100644 frontend/src/app/common/components/popup-delete-profil/popup-delete-profil.component.html delete mode 100644 frontend/src/app/common/components/popup-delete-profil/popup-delete-profil.component.scss delete mode 100644 frontend/src/app/common/components/popup-delete-profil/popup-delete-profil.component.spec.ts delete mode 100644 frontend/src/app/common/components/popup-delete-profil/popup-delete-profil.component.ts delete mode 100644 frontend/src/app/common/components/popup-update-profil/popup-update-profil.component.html delete mode 100644 frontend/src/app/common/components/popup-update-profil/popup-update-profil.component.scss delete mode 100644 frontend/src/app/common/components/popup-update-profil/popup-update-profil.component.spec.ts delete mode 100644 frontend/src/app/common/components/popup-update-profil/popup-update-profil.component.ts delete mode 100644 frontend/src/app/common/guards/admin/admin.guard.spec.ts delete mode 100644 frontend/src/app/common/guards/admin/admin.guard.ts delete mode 100644 frontend/src/app/common/guards/user/user.guard.spec.ts delete mode 100644 frontend/src/app/common/guards/user/user.guard.ts delete mode 100644 frontend/src/app/common/services/checkEmail/check-email.service.spec.ts delete mode 100644 frontend/src/app/common/services/checkEmail/check-email.service.ts delete mode 100644 frontend/src/app/common/services/fictitiousDatas/fictitious-datas.service.spec.ts delete mode 100644 frontend/src/app/common/services/fictitiousDatas/fictitious-datas.service.ts delete mode 100644 frontend/src/app/common/services/hashage/hashage.service.spec.ts delete mode 100644 frontend/src/app/common/services/hashage/hashage.service.ts delete mode 100644 frontend/src/app/common/services/message/message.service.spec.ts delete mode 100644 frontend/src/app/common/services/message/message.service.ts delete mode 100644 frontend/src/app/common/services/profil/profil.service.spec.ts delete mode 100644 frontend/src/app/common/services/profil/profil.service.ts delete mode 100644 frontend/src/app/login/page-login/page-login.component.html delete mode 100644 frontend/src/app/login/page-login/page-login.component.scss delete mode 100644 frontend/src/app/login/page-login/page-login.component.spec.ts delete mode 100644 frontend/src/app/login/page-login/page-login.component.ts delete mode 100644 frontend/src/app/register/page-register/page-register.component.html delete mode 100644 frontend/src/app/register/page-register/page-register.component.scss delete mode 100644 frontend/src/app/register/page-register/page-register.component.spec.ts delete mode 100644 frontend/src/app/register/page-register/page-register.component.ts delete mode 100644 frontend/src/app/register/popup-confirm-register/popup-confirm-register.component.html delete mode 100644 frontend/src/app/register/popup-confirm-register/popup-confirm-register.component.scss delete mode 100644 frontend/src/app/register/popup-confirm-register/popup-confirm-register.component.spec.ts delete mode 100644 frontend/src/app/register/popup-confirm-register/popup-confirm-register.component.ts delete mode 100644 frontend/src/app/user/myProfil/commentary.txt delete mode 100644 frontend/src/app/user/page-registry/page-registry.component.html delete mode 100644 frontend/src/app/user/page-registry/page-registry.component.scss delete mode 100644 frontend/src/app/user/page-registry/page-registry.component.spec.ts delete mode 100644 frontend/src/app/user/page-registry/page-registry.component.ts delete mode 100644 frontend/src/assets/.gitkeep delete mode 100644 frontend/src/assets/logo.png delete mode 100644 frontend/src/assets/logo1.png delete mode 100644 frontend/src/environments/environment.prod.ts delete mode 100644 frontend/src/environments/environment.ts delete mode 100644 frontend/src/favicon.ico delete mode 100644 frontend/src/index.html delete mode 100644 frontend/src/main.ts delete mode 100644 frontend/src/polyfills.ts delete mode 100644 frontend/src/styles.scss delete mode 100644 frontend/src/test.ts delete mode 100644 frontend/tsconfig.app.json delete mode 100644 frontend/tsconfig.json delete mode 100644 frontend/tsconfig.spec.json diff --git a/.github/workflows/docker-image.yml b/.github/workflows/docker-image.yml deleted file mode 100644 index 7b13ff2..0000000 --- a/.github/workflows/docker-image.yml +++ /dev/null @@ -1,30 +0,0 @@ -name: Push-Development - -on: - push: - branches: [ master ] - pull_request: - branches: [ master ] - -jobs: - build: - name: Push Development - runs-on: ubuntu-latest - steps: - - name: Checkout code - uses: actions/checkout@v2 - - name: Run tests - run: docker-compose run test - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v1 - - name: Login to DockerHub - uses: docker/login-action@v1 - with: - username: ${{ secrets.DOCKER_USER }} - password: ${{ secrets.DOCKER_PASS }} - - name: Build and push - id: docker_build - uses: docker/build-push-action@v2 - with: - push: true - tags: user/app:latest \ No newline at end of file diff --git a/backend/Dockerfile b/backend/Dockerfile deleted file mode 100644 index 2987276..0000000 --- a/backend/Dockerfile +++ /dev/null @@ -1,6 +0,0 @@ -FROM python:latest -WORKDIR /data/backend -COPY requirements.txt requirements.txt -RUN pip install --upgrade pip -RUN pip install -r requirements.txt -COPY . . \ No newline at end of file diff --git a/backend/app.py b/backend/app.py deleted file mode 100644 index 50e795c..0000000 --- a/backend/app.py +++ /dev/null @@ -1,8 +0,0 @@ -from application import create_app -import os - -app = create_app(os.environ.get('FLASK_ENV', None)) - -if __name__ == "__main__": - PORT = os.environ.get('PORT', 33507) - app.run(host='0.0.0.0', port=PORT, DEBUG=True) diff --git a/backend/application/__init__.py b/backend/application/__init__.py deleted file mode 100644 index b68cd09..0000000 --- a/backend/application/__init__.py +++ /dev/null @@ -1,35 +0,0 @@ -from flask import Flask -from flask_sqlalchemy import SQLAlchemy -from flask_cors import CORS -import sys - -db = SQLAlchemy() - - -def create_app(flask_env='development'): - app = Flask(__name__, instance_relative_config=False) - origin = app.config.get('ALLOW_ORIGIN') - if origin is None: - origin = ['http://127.0.0.1:4200', 'http://localhost:4200'] - CORS(app, supports_credentials=True, origins=origin) - if flask_env == 'production': - app.config.from_object("config.ProductionConfig") - elif flask_env == 'testing': - app.config.from_object("config.TestingConfig") - elif flask_env == 'development': - app.config.from_object("config.DevelopmentConfig") - else: - app.config.from_object("config.Config") - - if app.config['SQLALCHEMY_DATABASE_URI_1'] is None or app.config['SQLALCHEMY_DATABASE_URI_2'] is None: - print('No ENV Variable for DATABASE_URL_USERS or DATABASE_URL_LOGS') - sys.exit(1) - else: - print('ENV Variables passed : ', app.config['SQLALCHEMY_BINDS']) - - db.init_app(app) - with app.app_context(): - from . import routes - app.register_blueprint(routes.bp) - db.create_all() - return app diff --git a/backend/application/api_functions.py b/backend/application/api_functions.py deleted file mode 100644 index bb67cbd..0000000 --- a/backend/application/api_functions.py +++ /dev/null @@ -1,364 +0,0 @@ -import hashlib -import os -from datetime import datetime -from flask_sqlalchemy import inspect -from sqlalchemy import asc, desc, or_ -from .users_model import Users, db -from .logs_model import Logs - - -def db_create_log(ip, action, message, has_succeeded, status_code, table=None, id_user=None): - log = Logs( - date=datetime.now().strftime('%Y-%m-%dT%H:%M:%S'), - ip=ip, - action=action, - message=message, - has_succeeded=has_succeeded, - status_code=status_code, - table=table, - id_user=id_user - ) - db.session.add(log) - db.session.commit() - return log.json() - - -def hash_password(salt, password): - return hashlib.pbkdf2_hmac('sha256', password.encode('utf-8'), salt, 100000) - - -def db_login(ip, email, password): - user = Users.query.filter( - Users.email == email - ).scalar() - - # Check User and Hash Pass - if user and user.hash_pass == hash_password(user.salt, password): - message = 'User authenticated.' - db_create_log( - ip=ip, - action='login', - message=message, - has_succeeded=True, - status_code=0, - table='users', - id_user=user.id - ) - return {'status': 0, 'message': message, 'data': user.json()} - else: - message = f'Email or password invalid' - db_create_log( - ip=ip, - action='login', - message=message, - has_succeeded=False, - status_code=1, - table='users', - id_user=None - ) - return {'status': 1, 'message': message} # Email or password invalid - - -def db_register(ip, email, nickname, password, is_admin=False): - user = Users.query.filter( - Users.email == email - ).scalar() - if user: - message = f'{email} already exist.' - db_create_log( - ip=ip, - action='register', - message=message, - has_succeeded=False, - status_code=1, - table='users', - id_user=None - ) - return {'status': 1, 'message': message} # User already exist - - # Salt Hash Pass with SHA256 - salt = os.urandom(32) - hash_pass = hash_password(salt, password) - - user = Users( - email=email, - hash_pass=hash_pass, - nickname=nickname, - salt=salt, - is_admin=is_admin - ) - user_inspect = inspect(user) - db.session.add(user) - check_inspect = user_inspect.pending - db.session.commit() - - # Add to logs - if check_inspect: - id_user = user.json()['id'] - message = 'User registered.' - has_succeeded = True - status_code = 0 - else: - id_user = None - message = 'Internal Error: User not registered.' - has_succeeded = False - status_code = 1 - - db_create_log( - ip=ip, - action='register', - message=message, - has_succeeded=has_succeeded, - status_code=status_code, - table='users', - id_user=id_user - ) - if status_code == 0: - return {'status': 0, 'message': message, 'data': user.json()} - elif status_code == 1: - return {'status': 1, 'message': message} - - -def db_user_update(ip, user_id, nickname, password): - user = Users.query.filter( - Users.id == user_id - ).scalar() - if user: - has_succeeded = False - status_code = 2 - if nickname and password: - # Salt Hash Pass with SHA256 - salt = os.urandom(32) - hash_pass = hash_password(salt, password) - Users.query.filter(Users.id == user_id).update({'nickname': nickname, 'hash_pass': hash_pass, 'salt': salt}) - db.session.commit() - message = 'User nickname and password updated.' - has_succeeded = True - status_code = 0 - elif nickname: - Users.query.filter(Users.id == user_id).update({'nickname': nickname}) - db.session.commit() - message = 'User nickname updated.' - has_succeeded = True - status_code = 0 - elif password: - # Salt Hash Pass with SHA256 - salt = os.urandom(32) - hash_pass = hash_password(salt, password) - Users.query.filter(Users.id == user_id).update({'hash_pass': hash_pass, 'salt': salt}) - db.session.commit() - message = 'User password updated.' - has_succeeded = True - status_code = 0 - else: - message = 'Only nickname and/or password can be changed.' - - db_create_log( - ip=ip, - action='user_update', - message=message, - has_succeeded=has_succeeded, - status_code=status_code, - table='users', - id_user=user_id - ) - return {'status': status_code, 'message': message, 'data': user.json()} - else: - message = 'User do not exist.' - db_create_log( - ip=ip, - action='user_update', - message=message, - has_succeeded=False, - status_code=1, - table='users', - id_user=user_id - ) - return {'status': 1, 'message': message} - - -def db_user_delete(ip, user_id): - user_to_delete = Users.query.filter(Users.id == user_id).scalar() - if user_to_delete: - is_admin = bool(user_to_delete.json()['is_admin']) - if is_admin and (Users.query.filter(Users.is_admin == True).count() <= 1 or user_id == 0): - message = 'Can\'t delete last admin' - db_create_log( - ip=ip, - action='user_delete', - message=message, - has_succeeded=False, - status_code=2, - table='users', - id_user=user_id - ) - return {'status': 2, 'message': message} - else: - test = Users.query.filter(Users.id == user_id).delete() - if test == 1: - db.session.commit() - message = 'User deleted.' - db_create_log( - ip=ip, - action='user_delete', - message=message, - has_succeeded=True, - status_code=0, - table='users', - id_user=user_id - ) - return {'status': 0, 'message': message, 'data': None} - else: - message = 'User do not exist.' - db_create_log( - ip=ip, - action='user_delete', - message=message, - has_succeeded=False, - status_code=1, - table='users', - id_user=user_id - ) - return {'status': 1, 'message': message} - else: - message = 'User do not exist.' - db_create_log( - ip=ip, - action='user_delete', - message=message, - has_succeeded=False, - status_code=1, - table='users', - id_user=user_id - ) - return {'status': 1, 'message': message} - - -def db_admin_update_user(ip, user_id, is_admin, password): - user = Users.query.filter( - Users.id == user_id - ).scalar() - if user: - has_succeeded = False - status_code = 2 - if is_admin is not None and password: - # Salt Hash Pass with SHA256 - salt = os.urandom(32) - hash_pass = hash_password(salt, password) - Users.query.filter(Users.id == user_id).update({'is_admin': is_admin, 'hash_pass': hash_pass, 'salt': salt}) - db.session.commit() - message = 'User is_admin and password updated.' - has_succeeded = True - status_code = 0 - elif is_admin is not None: - Users.query.filter(Users.id == user_id).update({'is_admin': is_admin}) - db.session.commit() - message = 'User is_admin updated.' - has_succeeded = True - status_code = 0 - elif password: - # Salt Hash Pass with SHA256 - salt = os.urandom(32) - hash_pass = hash_password(salt, password) - Users.query.filter(Users.id == user_id).update({'hash_pass': hash_pass, 'salt': salt}) - db.session.commit() - message = 'User password updated.' - has_succeeded = True - status_code = 0 - else: - message = 'Only is_admin and/or password can be changed.' - - db_create_log( - ip=ip, - action='user_update', - message=message, - has_succeeded=has_succeeded, - status_code=status_code, - table='users', - id_user=user_id - ) - return {'status': status_code, 'message': message, 'data': user.json()} - else: - message = 'User do not exist.' - db_create_log( - ip=ip, - action='user_update', - message=message, - has_succeeded=False, - status_code=1, - table='users', - id_user=user_id - ) - return {'status': 1, 'message': message} - - -def db_users(ip, user_id, query, by='email,nickname', id=None, is_admin=None, order_by='email,asc'): - # q= or id = - # if q= then by= (default: email,nickname) or email or nickname - # is_admin = - # order_by = (default: email,asc), (nickname,asc), (id,desc), (is_admin,desc) - - users = Users.query - if query is id and query is not None: - message = 'Query or id field' - db_create_log( - ip=ip, - action='users', - message=message, - has_succeeded=False, - status_code=1, - table='users', - id_user=user_id - ) - return {'status': 1, 'message': message} - - if query and by: - if by == 'email': - users = users.filter(Users.email.like('%' + query + '%')) - elif by == 'nickname': - users = users.filter(Users.nickname.like('%' + query + '%')) - else: - users = users.filter(or_(Users.nickname.like('%' + query + '%'), Users.email.like('%' + query + '%'))) - elif query and not by: - users = users.filter(or_(Users.nickname.like('%' + query + '%'), Users.email.like('%' + query + '%'))) - elif id: - users = users.filter(Users.id == id) - else: - pass - - if is_admin is not None: - users = users.filter(Users.is_admin == is_admin) - - order_by = order_by.split(',') - if order_by[0] == 'nickname': - order = Users.nickname - elif order_by[0] == 'id': - order = Users.id - elif order_by[0] == 'is_admin': - order = Users.is_admin - else: - order = Users.email - - if len(order_by) > 1: - if order_by[1] == 'asc': - users = users.order_by(asc(order)) - elif order_by[1] == 'desc': - users = users.order_by(desc(order)) - else: - users = users.order_by(asc(order)) - else: - users = users.order_by(asc(order)) - - users = users.all() - - message = f'query({query}), by({by}), id({id}), is_admin({is_admin}) and order_by({order_by}): {len(users)} result(s)' - db_create_log( - ip=ip, - action='users', - message=message, - has_succeeded=True, - status_code=0, - table='users', - id_user=user_id - ) - return {'status': 0, 'message': message, 'data': [user.json() for user in users]} diff --git a/backend/application/logs_model.py b/backend/application/logs_model.py deleted file mode 100644 index 53ac617..0000000 --- a/backend/application/logs_model.py +++ /dev/null @@ -1,41 +0,0 @@ -from . import db - - -class Logs(db.Model): - __bind_key__ = 'db-logs' - - id = db.Column(db.Integer, primary_key=True) - date = db.Column(db.TIMESTAMP(), nullable=False) - id_user = db.Column(db.Integer, nullable=True) - ip = db.Column(db.String(), nullable=False) - table = db.Column(db.String(), nullable=False) - action = db.Column(db.String(), nullable=False) - message = db.Column(db.String(), nullable=False) - has_succeeded = db.Column(db.Boolean, nullable=False) - status_code = db.Column(db.Integer, nullable=False) - - def __init__(self, date, id_user, ip, table, action, message, has_succeeded, status_code): - self.date = date - self.id_user = id_user - self.ip = ip - self.table = table - self.action = action - self.message = message - self.has_succeeded = has_succeeded - self.status_code = status_code - - def __repr__(self): - return { - 'id': self.id, - 'date': self.date, - 'id_user': self.id_user, - 'ip': self.ip, - 'table': self.table, - 'action': self.action, - 'message': self.message, - 'has_succeeded': self.has_succeeded, - 'status_code': self.status_code - } - - def json(self): - return self.__repr__() diff --git a/backend/application/responses.py b/backend/application/responses.py deleted file mode 100644 index 03e11a6..0000000 --- a/backend/application/responses.py +++ /dev/null @@ -1,35 +0,0 @@ -from flask import current_app as app -import json - - -def send_error(status_code, message, token=None): - data_json = { - 'status': 'error', - 'message': message - } - res = app.response_class( - response=json.dumps(data_json), - status=status_code, - mimetype='application/json' - ) - if token is not None: - res.set_cookie('SESSIONID', token) - return res - - -def send_message(message, data, token=None, token_delete=False): - data_json = { - 'status': 'success', - 'message': message, - 'data': data - } - res = app.response_class( - response=json.dumps(data_json), - status=200, - mimetype='application/json' - ) - if token is not None: - res.set_cookie('SESSIONID', token) - if token_delete: - res.delete_cookie('SESSIONID') - return res diff --git a/backend/application/routes.py b/backend/application/routes.py deleted file mode 100644 index 70d5160..0000000 --- a/backend/application/routes.py +++ /dev/null @@ -1,345 +0,0 @@ -from flask import request, Blueprint -from werkzeug.exceptions import HTTPException -from .responses import send_message, send_error -from .api_functions import db_login, db_register, db_user_update, db_create_log, db_user_delete, db_admin_update_user, db_users -from .sessionJWT import create_auth_token, check_auth_token - -bp = Blueprint('myapp', __name__) - - -@bp.app_errorhandler(HTTPException) -def handle_exception(e): - return send_error(e.code, e.name) - - -# Login -@bp.route('/api/login', methods=['POST']) -def login(): - post_json = request.json - try: - post_email = str(post_json['email']) - post_password = str(post_json['password']) - if post_email != '' and post_password != '': - ip = request.remote_addr - res = db_login(ip, post_email, post_password) - if res['status'] == 0: - user = res['data'] - token = create_auth_token(user) - return send_message(res['message'], user, token) - elif res['status'] == 1: - user = None - token = create_auth_token(user) - return send_error(400, res['message'], token) - else: - return send_error(400, 'Empty email and/or password fields.') - except KeyError as e: - return send_error(400, 'Need email, password fields.') - - -# Register -@bp.route('/api/register', methods=['POST']) -def register(): - post_json = request.json - try: - post_email = str(post_json['email']) - post_nickname = str(post_json['nickname']) - post_password = str(post_json['password']) - if post_email != '' and post_password != '' and post_nickname != '': - ip = request.remote_addr - res = db_register(ip, post_email, post_nickname, post_password) - if res['status'] == 1: - return send_error(500, res['message']) - elif res['status'] == 0: - return send_message(res['message'], res['data']) - else: - return send_error(400, 'Empty email and/or password and/or nickname fields.') - except KeyError as e: - return send_error(400, 'Need ' + str(e) + 'field.') - - -# Logout -@bp.route('/api/logout', methods=['DELETE']) -def logout(): - token = check_auth_token(request) - if token['success']: - ip = request.remote_addr - message = 'User disconnected.' - db_create_log( - ip=ip, - action='logout', - message=message, - has_succeeded=True, - status_code=0, - table='users', - id_user=token['payload']['id'] - ) - return send_message(message, None, token_delete=True) - else: - return send_error(500, token['message']) - - -# Update User (Nickname, Password) -@bp.route('/api/user/update', methods=['PUT']) -def user_update(): - token = check_auth_token(request) - if token['success']: - post_json = request.json - post_nickname = None - post_password = None - fields = '' - if 'nickname' in post_json: - post_nickname = str(post_json['nickname']) - else: - fields += 'nickname ' - - if 'password' in post_json: - post_password = str(post_json['password']) - else: - fields += 'password ' - - if post_nickname is not None or post_password is not None: - if post_nickname != '' and post_password != '': - ip = request.remote_addr - user_id = token['payload']['id'] - res = db_user_update(ip, user_id, post_nickname, post_password) - if res['status'] == 1: - return send_error(500, res['message']) - elif res['status'] == 0: - return send_message(res['message'], res['data']) - else: - return send_error(400, 'Empty nickname and/or password fields.') - else: - return send_error(400, 'Need ' + fields + 'field.') - else: - return send_error(500, token['message']) - - -# Delete User -@bp.route('/api/user/delete', methods=['DELETE']) -def user_delete(): - token = check_auth_token(request) - if token['success']: - ip = request.remote_addr - user_id = token['payload']['id'] - res = db_user_delete(ip, user_id) - if res['status'] != 0: - return send_error(500, res['message']) - else: - db_create_log( - ip=ip, - action='delete', - message='User deleted.', - has_succeeded=True, - status_code=0, - table='users', - id_user=token['payload']['id'] - ) - return send_message(res['message'], None, token_delete=True) - else: - return send_error(500, token['message']) - - -# Admin : Create User -@bp.route('/api/admin/create/user', methods=['POST']) -def admin_create_user(): - token = check_auth_token(request) - if token['success']: - ip = request.remote_addr - user_id = token['payload']['id'] - is_admin = token['payload']['is_admin'] - if is_admin: - post_json = request.json - post_email = None - post_nickname = None - post_password = None - post_is_admin = None - fields = '' - if 'email' in post_json: - post_email = str(post_json['email']) - else: - fields += 'email ' - - if 'nickname' in post_json: - post_nickname = str(post_json['nickname']) - else: - fields += 'nickname ' - - if 'password' in post_json: - post_password = str(post_json['password']) - else: - fields += 'password ' - - if 'is_admin' in post_json: - post_is_admin = bool(post_json['is_admin']) - else: - fields += 'is_admin ' - - if post_email is not None or post_nickname is not None or post_password is not None or post_is_admin is not None: - if post_email != '' and post_nickname != '' and post_password != '' and str(post_is_admin) != '': - res = db_register(ip, post_email, post_nickname, post_password, is_admin=post_is_admin) - if res['status'] == 1: - db_create_log( - ip=ip, - action='admin/create/user', - message=res['message'], - has_succeeded=False, - status_code=res['status'], - table='users', - id_user=user_id - ) - return send_error(500, res['message']) - elif res['status'] == 0: - db_create_log( - ip=ip, - action='admin/create/user', - message=res['message'], - has_succeeded=True, - status_code=res['status'], - table='users', - id_user=user_id - ) - return send_message(res['message'], res['data']) - else: - return send_error(400, 'Empty email and/or nickname and/or password and/or is_admin fields.') - else: - return send_error(400, 'Need ' + fields + 'field.') - else: - return send_error(500, 'User does not have permission.') - else: - return send_error(500, token['message']) - - -# Admin : Change User password and/or role -@bp.route('/api/admin/update/user', methods=['PUT']) -def admin_update_user(): - token = check_auth_token(request) - if token['success']: - user_id = token['payload']['id'] - is_admin = token['payload']['is_admin'] - if is_admin: - post_json = request.json - post_is_admin = None - post_password = None - post_user_id_delete = None - fields = '' - if 'id' in post_json: - post_user_id_delete = int(post_json['id']) - else: - fields += 'id ' - - if 'is_admin' in post_json: - post_is_admin = bool(post_json['is_admin']) - else: - fields += 'is_admin ' - - if 'password' in post_json: - post_password = str(post_json['password']) - else: - fields += 'password ' - - if post_user_id_delete is not None and (post_is_admin is not None or post_password is not None): - if str(post_is_admin) != '' and post_password != '' and str(post_user_id_delete) != '': - ip = request.remote_addr - res = db_admin_update_user(ip, post_user_id_delete, post_is_admin, post_password) - if res['status'] == 1: - db_create_log( - ip=ip, - action='admin/update/user', - message=res['message'], - has_succeeded=False, - status_code=res['status'], - table='users', - id_user=user_id - ) - return send_error(500, res['message']) - elif res['status'] == 0: - db_create_log( - ip=ip, - action='admin/update/user', - message=res['message'], - has_succeeded=True, - status_code=res['status'], - table='users', - id_user=user_id - ) - return send_message(res['message'], res['data']) - else: - return send_error(400, 'Empty is_admin and/or password fields.') - else: - return send_error(400, 'Need ' + fields + 'field.') - else: - return send_error(500, 'User does not have permission.') - else: - return send_error(500, token['message']) - - -# Admin : Delete User -@bp.route('/api/admin/delete/user/', methods=['DELETE']) -def admin_delete_user(id): - token = check_auth_token(request) - if token['success']: - ip = request.remote_addr - user_id = token['payload']['id'] - is_admin = token['payload']['is_admin'] - if is_admin: - post_json = {'id': id} - post_user_id_delete = None - fields = '' - if 'id' in post_json: - post_user_id_delete = int(post_json['id']) - else: - fields += 'id' - if post_user_id_delete is not None: - if str(post_user_id_delete) != '': - res = db_user_delete(ip, int(post_user_id_delete)) - if res['status'] == 1: - db_create_log( - ip=ip, - action='admin/delete/user', - message=res['message'], - has_succeeded=False, - status_code=res['status'], - table='users', - id_user=user_id - ) - return send_error(500, res['message']) - else: - db_create_log( - ip=ip, - action='admin/delete/user', - message=res['message'], - has_succeeded=True, - status_code=res['status'], - table='users', - id_user=user_id - ) - return send_message(res['message'], None) - else: - return send_error(400, 'Empty id field.') - else: - return send_error(400, 'Need ' + fields + 'field.') - else: - return send_error(500, 'User does not have permission.') - else: - return send_error(500, token['message']) - - -# List of User (must be authenticated) & Search -@bp.route('/api/users', methods=['GET']) -def users(): - token = check_auth_token(request) - if token['success']: - ip = request.remote_addr - user_id = token['payload']['id'] - get_query = request.args.get('q') - get_by = request.args.get('by') - get_id = request.args.get('id') - get_is_admin = request.args.get('is_admin') - get_order_by = request.args.get('order_by') - res = db_users(ip, user_id, get_query, get_by, get_id, get_is_admin, get_order_by) - if res['status'] == 1: - return send_error(500, res['message']) - else: - return send_message(res['message'], res['data']) - else: - return send_error(500, token['message']) diff --git a/backend/application/sessionJWT.py b/backend/application/sessionJWT.py deleted file mode 100644 index ef228fb..0000000 --- a/backend/application/sessionJWT.py +++ /dev/null @@ -1,39 +0,0 @@ -from datetime import datetime, timedelta -from flask import current_app as app -import jwt - - -def create_auth_token(user, time_second=1800): - try: - time = datetime.now() - payload = { - 'exp': time + timedelta(days=0, seconds=time_second), - 'iat': time, - 'user': user - } - return jwt.encode( - payload, - app.config.get('SECRET_KEY'), - algorithm='HS256' - ) - except Exception as e: - return e - - -def decode_auth_token(auth_token): - try: - payload = jwt.decode( - auth_token, - app.config.get('SECRET_KEY'), - algorithms='HS256' - ) - return {'success': True, 'payload': payload['user']} - except jwt.ExpiredSignatureError: - return {'success': False, 'message': 'Signature expired . Please log in again.'} - except jwt.InvalidTokenError as e: - return {'success': False, 'message': 'User not authenticated.'} - - -def check_auth_token(request): - token = request.cookies.get('SESSIONID') - return decode_auth_token(token) diff --git a/backend/application/users_model.py b/backend/application/users_model.py deleted file mode 100644 index b932328..0000000 --- a/backend/application/users_model.py +++ /dev/null @@ -1,37 +0,0 @@ -from . import db - - -class Users(db.Model): - __bind_key__ = 'db-users' - - id = db.Column(db.Integer, primary_key=True, autoincrement=True) - email = db.Column(db.String(), nullable=False, unique=True) - nickname = db.Column(db.String(), nullable=False) - hash_pass = db.Column(db.LargeBinary(), nullable=False) - salt = db.Column(db.LargeBinary(), nullable=False) - is_admin = db.Column(db.Boolean, default=False, nullable=False) - - def __init__(self, email, nickname, hash_pass, salt, is_admin): - self.email = email - self.hash_pass = hash_pass - self.nickname = nickname - self.salt = salt - self.is_admin = is_admin - - def __repr__(self): - return { - 'id': self.id, - 'email': self.email, - 'nickname': self.nickname, - 'hash_pass': self.hash_pass, - 'salt': self.salt, - 'is_admin': self.is_admin - } - - def json(self): - return { - 'id': self.id, - 'email': self.email, - 'nickname': self.nickname, - 'is_admin': self.is_admin - } diff --git a/backend/config.py b/backend/config.py deleted file mode 100644 index ae0e613..0000000 --- a/backend/config.py +++ /dev/null @@ -1,43 +0,0 @@ -import os - -basedir = os.path.abspath(os.path.dirname(__file__)) - - -class Config(object): - DEBUG = False - TESTING = False - CSRF_ENABLED = True - - FLASK_APP = os.environ.get('FLASK_APP', None) - FLASK_ENV = os.environ.get('FLASK_ENV', None) - - SQLALCHEMY_ECHO = False - SQLALCHEMY_TRACK_MODIFICATIONS = False - SQLALCHEMY_DATABASE_URI_1 = os.environ.get('DATABASE_URL_USERS', None) - SQLALCHEMY_DATABASE_URI_2 = os.environ.get('DATABASE_URL_LOGS', None) - SQLALCHEMY_BINDS = { - 'db-users': SQLALCHEMY_DATABASE_URI_1, - 'db-logs': SQLALCHEMY_DATABASE_URI_2 - } - - SECRET_KEY = os.environ.get('SECRET_KEY', 'default_secret_key') - ALLOW_ORIGIN = os.environ.get('ALLOW_ORIGIN', None) - - -class ProductionConfig(Config): - DEBUG = False - SQLALCHEMY_ECHO = False - SQLALCHEMY_TRACK_MODIFICATIONS = False - - -class TestingConfig(Config): - TESTING = True - SQLALCHEMY_ECHO = False - SQLALCHEMY_TRACK_MODIFICATIONS = False - - -class DevelopmentConfig(Config): - DEVELOPMENT = True - DEBUG = True - SQLALCHEMY_ECHO = True - SQLALCHEMY_TRACK_MODIFICATIONS = True diff --git a/backend/env.sh b/backend/env.sh deleted file mode 100755 index da2fa7f..0000000 --- a/backend/env.sh +++ /dev/null @@ -1,6 +0,0 @@ -export FLASK_APP=app.py -export FLASK_ENV=development -export FLASK_DEBUG=1 -export PYTHONUNBUFFERED=1 -export DATABASE_URL_USERS=postgresql://flaskaled1:aled1@localhost:5433/flaskaledDb1 -export DATABASE_URL_LOGS=postgresql://flaskaled2:aled2@localhost:5434/flaskaledDb2 diff --git a/backend/fictive_users.py b/backend/fictive_users.py deleted file mode 100644 index 6f97529..0000000 --- a/backend/fictive_users.py +++ /dev/null @@ -1,47 +0,0 @@ -import os -from application.users_model import Users -from application.api_functions import hash_password - -TAB_USER_WITH_PASSWORD = [ - { - "id": 1, - "email": "riri@gmail.com", - "nickname": "Riri", - "password": "ririPass", - "is_admin": False - }, - { - "id": 2, - "email": "fifi@gmail.com", - "nickname": "Fifi", - "password": "fifiPass", - "is_admin": False - }, - { - "id": 3, - "email": "donald@gmail.com", - "nickname": "Donald", - "password": "donaldPass", - "is_admin": False - }, - { - "id": 4, - "email": "daisy@gmail.com", - "nickname": "Daisy", - "password": "daisyPass", - "is_admin": True - }, -] - - -# Convert user with passord (uwp) to user -def uwp_to_user(uwp): - salt0 = os.urandom(32) - hash_pass0 = hash_password(salt0, uwp["password"]) - return Users( - email=uwp["email"], - nickname=uwp["nickname"], - hash_pass=hash_pass0, - salt=salt0, - is_admin=uwp["is_admin"] - ) diff --git a/backend/init-db1.sql b/backend/init-db1.sql deleted file mode 100755 index bbec183..0000000 --- a/backend/init-db1.sql +++ /dev/null @@ -1,13 +0,0 @@ --- Table: users - -CREATE TABLE IF NOT EXISTS users -( - id serial PRIMARY KEY, - email character varying(320) NOT NULL, - nickname character varying(50) NOT NULL, - hash_pass bytea NOT NULL, - salt bytea NOT NULL, - is_admin boolean NOT NULL DEFAULT FALSE -); - -INSERT INTO users VALUES(0,'admin@admin.admin','Admin',decode('e5ed79b503704ed20a1d250770db68182118de7fe0236db9bbfb0dd9684087d6', 'hex'),decode('7012f69f1ac7c23c5dca498c30fa94527b507cc9e40fab9bae284d1465a37724', 'hex'),TRUE); \ No newline at end of file diff --git a/backend/init-db2.sql b/backend/init-db2.sql deleted file mode 100644 index 02ebdc9..0000000 --- a/backend/init-db2.sql +++ /dev/null @@ -1,14 +0,0 @@ --- Table: logs - -CREATE TABLE IF NOT EXISTS logs -( - id serial PRIMARY KEY, - date timestamp NOT NULL, - id_user integer, - ip character varying(15) NOT NULL, - "table" character varying(25) NOT NULL, - action character varying(50) NOT NULL, - message character varying(512) NOT NULL, - has_succeeded boolean NOT NULL, - status_code smallint NOT NULL -); \ No newline at end of file diff --git a/backend/requirements.txt b/backend/requirements.txt deleted file mode 100644 index 6317cbe..0000000 --- a/backend/requirements.txt +++ /dev/null @@ -1,13 +0,0 @@ -alembic==1.7.5 -Flask==2.0.2 -Flask-Migrate==3.1.0 -Flask-Script==2.0.6 -Flask-Testing==0.8.1 -Flask-SQLAlchemy==2.5.1 -Flask-WTF==0.15.1 -pipreqs==0.4.10 -PyJWT==2.3.0 -pytest==6.2.5 -SQLAlchemy==1.4.27 -psycopg2==2.9.2 -Flask-Cors==3.0.10 \ No newline at end of file diff --git a/backend/test.py b/backend/test.py deleted file mode 100644 index 2aa595f..0000000 --- a/backend/test.py +++ /dev/null @@ -1,542 +0,0 @@ -import unittest -from flask_testing import TestCase -from fictive_users import TAB_USER_WITH_PASSWORD, uwp_to_user -from application import db, create_app - - -class BaseTestCase(TestCase): - - def create_app(self): - app = create_app('testing') - return app - - def setUp(self): - db.drop_all() - db.create_all() - for uwp in TAB_USER_WITH_PASSWORD: - db.session.add(uwp_to_user(uwp)) - db.session.commit() - - def tearDown(self): - db.session.remove() - db.drop_all() - - -class FlaskTestCase(BaseTestCase): - - # -- UTILS --- - - def login(self, email, password): - data0 = { - "email": email, - "password": password - } - response = self.client.post('/api/login', json=data0) - return response - - # --- LOGIN --- - - def test_login_NoFields_statusCode(self): - response = self.client.post('/api/login', json={}) - self.assertEqual(response.status_code, 400) - - def test_login_NoFields_message(self): - response = self.client.post('/api/login', json={}) - self.assertEqual(response.json['message'], 'Need email, password fields.') - - def test_login_emptyFields_statusCode(self): - data0 = { - "email": "", - "password": "blabla" - } - response = self.client.post('/api/login', json=data0) - self.assertEqual(response.status_code, 400) - - def test_login_emptyFields_message(self): - data0 = { - "email": "", - "password": "blabla" - } - response = self.client.post('/api/login', json=data0) - self.assertEqual(response.json['message'], 'Empty email and/or password fields.') - - def test_login_wrongFields_statusCode(self): - data0 = { - "email": "nimp@gmail.com", - "password": "nimp" - } - response = self.client.post('/api/login', json=data0) - self.assertEqual(response.status_code, 400) - - def test_login_wrongFields_message(self): - data0 = { - "email": "nimp@gmail.com", - "password": "nimp" - } - response = self.client.post('/api/login', json=data0) - self.assertEqual(response.json['message'], 'Email or password invalid') - - def test_login_success_statusCode(self): - data0 = { - "email": "riri@gmail.com", - "password": "ririPass" - } - response = self.client.post('/api/login', json=data0) - self.assertEqual(response.status_code, 200) - - def test_login_success_message(self): - data0 = { - "email": "riri@gmail.com", - "password": "ririPass" - } - response = self.client.post('/api/login', json=data0) - self.assertEqual(response.json['message'], 'User authenticated.') - - # --- REGISTER --- - - def test_register_noFields_statusCode(self): - response = self.client.post('/api/register', json={}) - self.assertEqual(response.status_code, 400) - - def test_register_noFields_message(self): - response = self.client.post('/api/register', json={}) - self.assertIn('Need', response.json['message']) - - def test_register_emptyFields_statusCode(self): - data0 = { - "email": "", - "password": "blabla", - "nickname": "blabla" - } - response = self.client.post('/api/register', json=data0) - self.assertEqual(response.status_code, 400) - - def test_register_emptyFields_message(self): - data0 = { - "email": "", - "password": "blabla", - "nickname": "blabla" - } - response = self.client.post('/api/register', json=data0) - self.assertEqual(response.json['message'], 'Empty email and/or password and/or nickname fields.') - - def test_register_alreadyExist_statusCode(self): - data0 = { - "email": "riri@gmail.com", - "password": "blabla", - "nickname": "blabla" - } - response = self.client.post('/api/register', json=data0) - self.assertEqual(response.status_code, 500) - - def test_register_alreadyExist_statusCode(self): - data0 = { - "email": "riri@gmail.com", - "password": "blabla", - "nickname": "blabla" - } - response = self.client.post('/api/register', json=data0) - self.assertIn('already exist', response.json['message']) - - def test_register_success_statusCode(self): - data0 = { - "email": "loulou@gmail.com", - "password": "loulouPass", - "nickname": "Loulou" - } - response = self.client.post('/api/register', json=data0) - self.assertEqual(response.status_code, 200) - - def test_register_success_message(self): - data0 = { - "email": "loulou@gmail.com", - "password": "loulouPass", - "nickname": "Loulou" - } - response = self.client.post('/api/register', json=data0) - self.assertEqual(response.json['message'], 'User registered.') - - # --- LOGOUT --- - - def test_logout_fail_(self): - response = self.client.delete('/api/logout') - self.assertEqual(response.status_code, 500) - - def test_logout_success(self): - response = self.login("riri@gmail.com", "ririPass") - self.assertEqual(response.status_code, 200) - response = self.client.delete('/api/logout') - self.assertEqual(response.status_code, 200) - - # --- USER/UPDATE --- - - def test_userUpdate_notConnected_statusCode(self): - response = self.client.put('/api/user/update', json={}) - self.assertEqual(response.status_code, 500) - - def test_userUpdate_notConnected_message(self): - response = self.client.put('/api/user/update', json={}) - self.assertEqual(response.json['message'], 'User not authenticated.') - - def test_userUpdate_noFields_statusCode(self): - response = self.login("riri@gmail.com", "ririPass") - self.assertEqual(response.status_code, 200) - response = self.client.put('/api/user/update', json={}) - self.assertEqual(response.status_code, 400) - - def test_userUpdate_noFields_message(self): - response = self.login("riri@gmail.com", "ririPass") - self.assertEqual(response.status_code, 200) - response = self.client.put('/api/user/update', json={}) - self.assertIn('Need', response.json['message']) - - def test_userUpdate_emptyFields_statusCode(self): - response = self.login("riri@gmail.com", "ririPass") - self.assertEqual(response.status_code, 200) - data0 = { - "nickname": "", - "password": "blabla" - } - response = self.client.put('/api/user/update', json=data0) - self.assertEqual(response.status_code, 400) - - def test_userUpdate_emptyFields_message(self): - response = self.login("riri@gmail.com", "ririPass") - self.assertEqual(response.status_code, 200) - data0 = { - "nickname": "", - "password": "blabla" - } - response = self.client.put('/api/user/update', json=data0) - self.assertEqual(response.json['message'], 'Empty nickname and/or password fields.') - - def test_self_update_success_statusCode(self): - response = self.login("riri@gmail.com", "ririPass") - self.assertEqual(response.status_code, 200) - data0 = { - "nickname": "Ririri", - "password": "ririPass" - } - response = self.client.put('/api/user/update', json=data0) - self.assertEqual(response.status_code, 200) - - # --- USER/DELETE --- - - def test_userDelete_notConnected_statusCode(self): - response = self.client.delete('/api/user/delete') - self.assertEqual(response.status_code, 500) - - def test_userDelete_notConnected_message(self): - response = self.client.delete('/api/user/delete') - self.assertEqual(response.json['message'], 'User not authenticated.') - - def test_userDelete_success_statusCode(self): - response = self.login('riri@gmail.com', 'ririPass') - self.assertEqual(response.status_code, 200) - response = self.client.delete('/api/user/delete') - self.assertEqual(response.status_code, 200) - - def test_userDelete_success_message(self): - response = self.login('riri@gmail.com', 'ririPass') - self.assertEqual(response.status_code, 200) - response = self.client.delete('/api/user/delete') - self.assertEqual(response.json['message'], 'User deleted.') - - def test_userDelete_lastAdmin_statusCode(self): - response = self.login('donald@gmail.com', 'donaldPass') - self.assertEqual(response.status_code, 200) - response = self.client.delete('/api/user/delete') - self.assertEqual(response.status_code, 200) - response = self.login('daisy@gmail.com', 'daisyPass') - self.assertEqual(response.status_code, 200) - response = self.client.delete('/api/user/delete') - self.assertEqual(response.status_code, 500) - - def test_userDelete_lastAdmin_message(self): - response = self.login('donald@gmail.com', 'donaldPass') - self.assertEqual(response.status_code, 200) - response = self.client.delete('/api/user/delete') - self.assertEqual(response.status_code, 200) - response = self.login('daisy@gmail.com', 'daisyPass') - self.assertEqual(response.status_code, 200) - response = self.client.delete('/api/user/delete') - self.assertEqual(response.json['message'], 'Can\'t delete last admin') - - # --- ADMIN/CREATE/USER --- - - def test_adminCreate_notConnected_statusCode(self): - response = self.client.post('/api/admin/create/user', json={}) - self.assertEqual(response.status_code, 500) - - def test_adminCreate_notConnected_message(self): - response = self.client.post('/api/admin/create/user', json={}) - self.assertEqual(response.json['message'], 'User not authenticated.') - - def test_adminCreate_noPermission_statusCode(self): - response = self.login('riri@gmail.com', 'ririPass') - self.assertEqual(response.status_code, 200) - response = self.client.post('/api/admin/create/user', json={}) - self.assertEqual(response.status_code, 500) - - def test_adminCreate_noPermission_message(self): - response = self.login('riri@gmail.com', 'ririPass') - self.assertEqual(response.status_code, 200) - response = self.client.post('/api/admin/create/user', json={}) - self.assertEqual(response.json['message'], 'User does not have permission.') - - def test_adminCreate_noFields_statusCode(self): - response = self.login('daisy@gmail.com', 'daisyPass') - self.assertEqual(response.status_code, 200) - response = self.client.post('/api/admin/create/user', json={}) - self.assertEqual(response.status_code, 400) - - def test_adminCreate_noFields_message(self): - response = self.login('daisy@gmail.com', 'daisyPass') - self.assertEqual(response.status_code, 200) - response = self.client.post('/api/admin/create/user', json={}) - self.assertIn('Need', response.json['message']) - - def test_adminCreate_emptyFields_statusCode(self): - response = self.login('daisy@gmail.com', 'daisyPass') - self.assertEqual(response.status_code, 200) - data0 = { - "email": "", - "nickname": "Mickey", - "password": "mickeyPass", - "is_admin": True, - } - response = self.client.post('/api/admin/create/user', json=data0) - self.assertEqual(response.status_code, 400) - - def test_adminCreate_emptyFields_message(self): - response = self.login('daisy@gmail.com', 'daisyPass') - self.assertEqual(response.status_code, 200) - data0 = { - "email": "", - "nickname": "Mickey", - "password": "mickeyPass", - "is_admin": True, - } - response = self.client.post('/api/admin/create/user', json=data0) - self.assertEqual(response.json['message'], - 'Empty email and/or nickname and/or password and/or is_admin fields.') - - def test_adminCreate_alreadyExist_statusCode(self): - response = self.login('daisy@gmail.com', 'daisyPass') - self.assertEqual(response.status_code, 200) - data0 = { - "email": "riri@gmail.com", - "passord": "blabla", - "nickname": "blabla", - } - response = self.client.post('/api/admin/create/user', json=data0) - self.assertEqual(response.status_code, 500) - - def test_adminCreate_alreadyExist_message(self): - response = self.login('daisy@gmail.com', 'daisyPass') - self.assertEqual(response.status_code, 200) - data0 = { - "email": "riri@gmail.com", - "passord": "blabla", - "nickname": "blabla", - } - response = self.client.post('/api/admin/create/user', json=data0) - self.assertIn('already exist', response.json['message']) - - def test_adminCreate_success_statusCode(self): - response = self.login('daisy@gmail.com', 'daisyPass') - self.assertEqual(response.status_code, 200) - data0 = { - "email": "mickey@gmail.com", - "nickname": "Mickey", - "password": "mickeyPass", - "is_admin": True, - } - response = self.client.post('/api/admin/create/user', json=data0) - self.assertEqual(response.status_code, 200) - - def test_adminCreate_success_message(self): - response = self.login('daisy@gmail.com', 'daisyPass') - self.assertEqual(response.status_code, 200) - data0 = { - "email": "mickey@gmail.com", - "nickname": "Mickey", - "password": "mickeyPass", - "is_admin": True, - } - response = self.client.post('/api/admin/create/user', json=data0) - self.assertEqual(response.json['message'], 'User registered.') - - # --- ADMIN/UPDATE/USER --- - - def test_adminUpdate_notConnected_statusCode(self): - response = self.client.put('/api/admin/update/user', json={}) - self.assertEqual(response.status_code, 500) - - def test_adminUpdate_notConnected_message(self): - response = self.client.put('/api/admin/update/user', json={}) - self.assertEqual(response.json['message'], 'User not authenticated.') - - def test_adminUpdate_noPermission_statusCode(self): - response = self.login('riri@gmail.com', 'ririPass') - self.assertEqual(response.status_code, 200) - response = self.client.put('/api/admin/update/user', json={}) - self.assertEqual(response.status_code, 500) - - def test_adminUpdate_noPermission_message(self): - response = self.login('riri@gmail.com', 'ririPass') - self.assertEqual(response.status_code, 200) - response = self.client.put('/api/admin/update/user', json={}) - self.assertEqual(response.json['message'], 'User does not have permission.') - - def test_adminUpdate_noFields_statusCode(self): - response = self.login('daisy@gmail.com', 'daisyPass') - self.assertEqual(response.status_code, 200) - response = self.client.put('/api/admin/update/user', json={}) - self.assertEqual(response.status_code, 400) - - def test_adminUpdate_noFields_message(self): - response = self.login('daisy@gmail.com', 'daisyPass') - self.assertEqual(response.status_code, 200) - response = self.client.put('/api/admin/update/user', json={}) - self.assertIn('Need', response.json['message']) - - def test_adminUpdate_emptyFields_statusCode(self): - response = self.login('daisy@gmail.com', 'daisyPass') - self.assertEqual(response.status_code, 200) - data0 = { - "id": 1, - "password": "", - "is_admin": False, - } - response = self.client.put('/api/admin/update/user', json=data0) - self.assertEqual(response.status_code, 400) - - def test_adminUpdate_emptyFields_message(self): - response = self.login('daisy@gmail.com', 'daisyPass') - self.assertEqual(response.status_code, 200) - data0 = { - "id": 1, - "password": "", - "is_admin": False, - } - response = self.client.put('/api/admin/update/user', json=data0) - self.assertEqual(response.json['message'], 'Empty is_admin and/or password fields.') - - def test_adminUpdate_notExists_statusCode(self): - response = self.login('daisy@gmail.com', 'daisyPass') - self.assertEqual(response.status_code, 200) - data0 = { - "id": 99, - "password": "blabla", - "is_admin": False - } - response = self.client.put('/api/admin/update/user', json=data0) - self.assertEqual(response.status_code, 500) - - def test_adminUpdate_notExists_message(self): - response = self.login('daisy@gmail.com', 'daisyPass') - self.assertEqual(response.status_code, 200) - data0 = { - "id": 99, - "password": "blabla", - "is_admin": False - } - response = self.client.put('/api/admin/update/user', json=data0) - self.assertEqual(response.json['message'], 'User do not exist.') - - def test_adminUpdate_success_message(self): - response = self.login('daisy@gmail.com', 'daisyPass') - self.assertEqual(response.status_code, 200) - data0 = { - "id": 1, - "password": "roroPass", - "is_admin": False, - } - response = self.client.put('/api/admin/update/user', json=data0) - self.assertEqual(response.status_code, 200) - - def test_adminUpdate_success_statusCode(self): - response = self.login('daisy@gmail.com', 'daisyPass') - self.assertEqual(response.status_code, 200) - data0 = { - "id": 1, - "password": "roroPass", - "is_admin": False, - } - response = self.client.put('/api/admin/update/user', json=data0) - self.assertIn("updated", response.json['message']) - - # --- ADMIN/DELETE/USER --- - - def test_adminDelete_notConnected_statusCode(self): - response = self.client.delete('/api/admin/delete/user/1') - self.assertEqual(response.status_code, 500) - - def test_adminDelete_notConnected_message(self): - response = self.client.delete('/api/admin/delete/user/1') - self.assertEqual(response.json['message'], 'User not authenticated.') - - def test_adminDelete_noPermission_statusCode(self): - response = self.login('riri@gmail.com', 'ririPass') - self.assertEqual(response.status_code, 200) - response = self.client.delete('/api/admin/delete/user/1') - self.assertEqual(response.status_code, 500) - - def test_adminDelete_noPermission_message(self): - response = self.login('riri@gmail.com', 'ririPass') - self.assertEqual(response.status_code, 200) - response = self.client.delete('/api/admin/delete/user/1') - self.assertEqual(response.json['message'], 'User does not have permission.') - - def test_adminDelete_noFields_statusCode(self): - response = self.login('daisy@gmail.com', 'daisyPass') - self.assertEqual(response.status_code, 200) - response = self.client.delete('/api/admin/delete/user/') - self.assertEqual(response.status_code, 404) - - def test_adminDelete_no_fields(self): - response = self.login('daisy@gmail.com', 'daisyPass') - self.assertEqual(response.status_code, 200) - response = self.client.delete('/api/admin/delete/user') - self.assertEqual('Not Found', response.json['message']) - - def test_adminDelete_notExists_statusCode(self): - response = self.login('daisy@gmail.com', 'daisyPass') - self.assertEqual(response.status_code, 200) - response = self.client.delete('/api/admin/delete/user/99') - self.assertEqual(response.status_code, 500) - - def test_adminDelete_notExists_message(self): - response = self.login('daisy@gmail.com', 'daisyPass') - self.assertEqual(response.status_code, 200) - response = self.client.delete('/api/admin/delete/user/99') - self.assertEqual(response.json['message'], 'User do not exist.') - - def test_adminDelete_success_statusCode(self): - response = self.login('daisy@gmail.com', 'daisyPass') - self.assertEqual(response.status_code, 200) - response = self.client.delete('/api/admin/delete/user/2') - self.assertEqual(response.status_code, 200) - - def test_adminDelete_success_message(self): - response = self.login('daisy@gmail.com', 'daisyPass') - self.assertEqual(response.status_code, 200) - response = self.client.delete('/api/admin/delete/user/2') - self.assertEqual(response.json['message'], 'User deleted.') - - # --- LIST OF USER --- - - def test_listOfUsers_fail(self): - response = self.client.get('/api/users') - self.assertEqual(response.status_code, 500) - - def test_listOfUsers_success(self): - response = self.login('riri@gmail.com', 'ririPass') - self.assertEqual(response.status_code, 200) - response = self.client.get('/api/users?order_by=nickname') - self.assertEqual(response.status_code, 200) - - -if __name__ == '__main__': - unittest.main() diff --git a/docker-compose.yml b/docker-compose.yml index f5519be..1dc0990 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -14,80 +14,4 @@ services: - POSTGRES_DB=flaskaledDb1 - POSTGRES_USER=flaskaled1 - POSTGRES_PASSWORD=aled1 - restart: unless-stopped - - flaskaled-srv2: - image: postgres:latest - container_name: flaskaled-srv2 - ports: - - "5434:5432" - volumes: - - ./backend/init-db2.sql:/docker-entrypoint-initdb.d/init-db2.sql - environment: - - POSTGRES_HOST=flaskaled-srv2 - - POSTGRES_PORT=5432 - - POSTGRES_DB=flaskaledDb2 - - POSTGRES_USER=flaskaled2 - - POSTGRES_PASSWORD=aled2 - restart: unless-stopped - - backend: - container_name: backend - build: ./backend - command: python -m flask run --host=0.0.0.0 - ports: - - "5000:5000" - volumes: - - ./backend:/data/backend - depends_on: - - flaskaled-srv1 - - flaskaled-srv2 - links: - - flaskaled-srv1 - - flaskaled-srv2 - environment: - - FLASK_APP=app.py - - FLASK_ENV=development - - FLASK_DEBUG=1 - - PYTHONUNBUFFERED=1 - - DATABASE_URL_USERS=postgresql://flaskaled1:aled1@flaskaled-srv1/flaskaledDb1 - - DATABASE_URL_LOGS=postgresql://flaskaled2:aled2@flaskaled-srv2/flaskaledDb2 - - ALLOW_ORIGIN=frontend - - SECRET_KEY=default_secret_key - - frontend: - container_name: frontend - build: ./frontend - command: npm start - ports: - - "4200:4200" - volumes: - - ./frontend:/data/frontend - - ./frontend/node_modules:/data/frontend/node_modules - depends_on: - - backend - links: - - backend - environment: - - NODE_ENV=development - - test: - container_name: test - build: ./backend - command: python test.py - volumes: - - ./backend:/data/backend - depends_on: - - flaskaled-srv1 - - flaskaled-srv2 - links: - - flaskaled-srv1 - - flaskaled-srv2 - environment: - - FLASK_APP=app.py - - FLASK_ENV=test - - FLASK_DEBUG=0 - - PYTHONUNBUFFERED=1 - - DATABASE_URL_USERS=postgresql://flaskaled1:aled1@flaskaled-srv1/flaskaledDb1 - - DATABASE_URL_LOGS=postgresql://flaskaled2:aled2@flaskaled-srv2/flaskaledDb2 - - SECRET_KEY=default_secret_key + restart: unless-stopped \ No newline at end of file diff --git a/frontend/.browserslistrc b/frontend/.browserslistrc deleted file mode 100644 index 427441d..0000000 --- a/frontend/.browserslistrc +++ /dev/null @@ -1,17 +0,0 @@ -# This file is used by the build system to adjust CSS and JS output to support the specified browsers below. -# For additional information regarding the format and rule options, please see: -# https://github.com/browserslist/browserslist#queries - -# For the full list of supported browsers by the Angular framework, please see: -# https://angular.io/guide/browser-support - -# You can see what browsers were selected by your queries by running: -# npx browserslist - -last 1 Chrome version -last 1 Firefox version -last 2 Edge major versions -last 2 Safari major versions -last 2 iOS major versions -Firefox ESR -not IE 11 # Angular supports IE 11 only as an opt-in. To opt-in, remove the 'not' prefix on this line. diff --git a/frontend/.editorconfig b/frontend/.editorconfig deleted file mode 100644 index 59d9a3a..0000000 --- a/frontend/.editorconfig +++ /dev/null @@ -1,16 +0,0 @@ -# Editor configuration, see https://editorconfig.org -root = true - -[*] -charset = utf-8 -indent_style = space -indent_size = 2 -insert_final_newline = true -trim_trailing_whitespace = true - -[*.ts] -quote_type = single - -[*.md] -max_line_length = off -trim_trailing_whitespace = false diff --git a/frontend/.gitignore b/frontend/.gitignore deleted file mode 100644 index bac05b4..0000000 --- a/frontend/.gitignore +++ /dev/null @@ -1,49 +0,0 @@ -# See http://help.github.com/ignore-files/ for more about ignoring files. - -# compiled output -/dist -/tmp -/out-tsc -# Only exists if Bazel was run -/bazel-out - -# dependencies -/node_modules - -# profiling files -chrome-profiler-events*.json - -# IDEs and editors -/.idea -.project -.classpath -.c9/ -*.launch -.settings/ -*.sublime-workspace - -# IDE - VSCode -.vscode/* -!.vscode/settings.json -!.vscode/tasks.json -!.vscode/launch.json -!.vscode/extensions.json -.history/* -.idea/* - -# misc -/.angular/cache -/.sass-cache -/connect.lock -/coverage -/libpeerconnection.log -npm-debug.log -yarn-error.log -testem.log -/typings - -# System Files -.DS_Store -Thumbs.db - -package-lock.json diff --git a/frontend/Dockerfile b/frontend/Dockerfile deleted file mode 100644 index b0c17cc..0000000 --- a/frontend/Dockerfile +++ /dev/null @@ -1,6 +0,0 @@ -FROM node:latest -WORKDIR /data/frontend -COPY ["package.json", "package-lock.json*", "./"] -RUN npm install --NODE_ENV -RUN npm install -g @angular/cli -COPY . . diff --git a/frontend/README.md b/frontend/README.md deleted file mode 100644 index bdce2f4..0000000 --- a/frontend/README.md +++ /dev/null @@ -1,27 +0,0 @@ -# Frontend - -This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 12.2.10. - -## Development server - -Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The app will automatically reload if you change any of the source files. - -## Code scaffolding - -Run `ng generate component component-name` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module`. - -## Build - -Run `ng build` to build the project. The build artifacts will be stored in the `dist/` directory. - -## Running unit tests - -Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.io). - -## Running end-to-end tests - -Run `ng e2e` to execute the end-to-end tests via a platform of your choice. To use this command, you need to first add a package that implements end-to-end testing capabilities. - -## Further help - -To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI Overview and Command Reference](https://angular.io/cli) page. diff --git a/frontend/angular.json b/frontend/angular.json deleted file mode 100644 index 99c397a..0000000 --- a/frontend/angular.json +++ /dev/null @@ -1,113 +0,0 @@ -{ - "$schema": "./node_modules/@angular/cli/lib/config/schema.json", - "version": 1, - "newProjectRoot": "projects", - "projects": { - "frontend": { - "projectType": "application", - "schematics": { - "@schematics/angular:component": { - "style": "scss" - }, - "@schematics/angular:application": { - "strict": true - } - }, - "root": "", - "sourceRoot": "src", - "prefix": "app", - "architect": { - "build": { - "builder": "@angular-devkit/build-angular:browser", - "options": { - "outputPath": "dist/frontend", - "index": "src/index.html", - "main": "src/main.ts", - "polyfills": "src/polyfills.ts", - "tsConfig": "tsconfig.app.json", - "inlineStyleLanguage": "scss", - "assets": [ - "src/favicon.ico", - "src/assets" - ], - "styles": [ - "./node_modules/@angular/material/prebuilt-themes/indigo-pink.css", - "./node_modules/bootstrap/scss/bootstrap.scss", - "src/styles.scss" - ], - "scripts": [] - }, - "configurations": { - "production": { - "budgets": [ - { - "type": "initial", - "maximumWarning": "500kb", - "maximumError": "1mb" - }, - { - "type": "anyComponentStyle", - "maximumWarning": "2kb", - "maximumError": "4kb" - } - ], - "fileReplacements": [ - { - "replace": "src/environments/environment.ts", - "with": "src/environments/environment.prod.ts" - } - ], - "outputHashing": "all" - }, - "development": { - "buildOptimizer": false, - "optimization": false, - "vendorChunk": true, - "extractLicenses": false, - "sourceMap": true, - "namedChunks": true - } - }, - "defaultConfiguration": "production" - }, - "serve": { - "builder": "@angular-devkit/build-angular:dev-server", - "configurations": { - "production": { - "browserTarget": "frontend:build:production" - }, - "development": { - "browserTarget": "frontend:build:development" - } - }, - "defaultConfiguration": "development" - }, - "extract-i18n": { - "builder": "@angular-devkit/build-angular:extract-i18n", - "options": { - "browserTarget": "frontend:build" - } - }, - "test": { - "builder": "@angular-devkit/build-angular:karma", - "options": { - "main": "src/test.ts", - "polyfills": "src/polyfills.ts", - "tsConfig": "tsconfig.spec.json", - "karmaConfig": "karma.conf.js", - "inlineStyleLanguage": "scss", - "assets": [ - "src/favicon.ico", - "src/assets" - ], - "styles": [ - "src/styles.scss" - ], - "scripts": [] - } - } - } - } - }, - "defaultProject": "frontend" -} diff --git a/frontend/karma.conf.js b/frontend/karma.conf.js deleted file mode 100644 index 3635639..0000000 --- a/frontend/karma.conf.js +++ /dev/null @@ -1,44 +0,0 @@ -// Karma configuration file, see link for more information -// https://karma-runner.github.io/1.0/config/configuration-file.html - -module.exports = function (config) { - config.set({ - basePath: '', - frameworks: ['jasmine', '@angular-devkit/build-angular'], - plugins: [ - require('karma-jasmine'), - require('karma-chrome-launcher'), - require('karma-jasmine-html-reporter'), - require('karma-coverage'), - require('@angular-devkit/build-angular/plugins/karma') - ], - client: { - jasmine: { - // you can add configuration options for Jasmine here - // the possible options are listed at https://jasmine.github.io/api/edge/Configuration.html - // for example, you can disable the random execution with `random: false` - // or set a specific seed with `seed: 4321` - }, - clearContext: false // leave Jasmine Spec Runner output visible in browser - }, - jasmineHtmlReporter: { - suppressAll: true // removes the duplicated traces - }, - coverageReporter: { - dir: require('path').join(__dirname, './coverage/frontend'), - subdir: '.', - reporters: [ - { type: 'html' }, - { type: 'text-summary' } - ] - }, - reporters: ['progress', 'kjhtml'], - port: 9876, - colors: true, - logLevel: config.LOG_INFO, - autoWatch: true, - browsers: ['Chrome'], - singleRun: false, - restartOnFileChange: true - }); -}; diff --git a/frontend/package.json b/frontend/package.json deleted file mode 100644 index 43ae649..0000000 --- a/frontend/package.json +++ /dev/null @@ -1,44 +0,0 @@ -{ - "name": "frontend", - "version": "0.0.0", - "scripts": { - "ng": "ng", - "start": "ng serve --host 0.0.0.0", - "build": "ng build", - "watch": "ng build --watch --configuration development", - "test": "ng test" - }, - "private": true, - "dependencies": { - "@angular/animations": "~13.1.1", - "@angular/cdk": "^13.0.2", - "@angular/common": "~13.1.1", - "@angular/compiler": "~13.1.1", - "@angular/core": "~13.1.1", - "@angular/forms": "~13.1.1", - "@angular/material": "^13.0.2", - "@angular/platform-browser": "~13.1.1", - "@angular/platform-browser-dynamic": "~13.1.1", - "@angular/router": "~13.1.1", - "bootstrap": "^5.1.3", - "jquery": "^3.6.0", - "popper": "^1.0.1", - "rxjs": "~6.6.0", - "tslib": "^2.3.0", - "zone.js": "~0.11.4" - }, - "devDependencies": { - "@angular-devkit/build-angular": "^13.1.4", - "@angular/cli": "~13.1.2", - "@angular/compiler-cli": "~13.1.1", - "@types/jasmine": "~3.8.0", - "@types/node": "^12.11.1", - "jasmine-core": "~3.8.0", - "karma": "~6.3.0", - "karma-chrome-launcher": "~3.1.0", - "karma-coverage": "~2.0.3", - "karma-jasmine": "~4.0.0", - "karma-jasmine-html-reporter": "~1.7.0", - "typescript": "~4.5.4" - } -} diff --git a/frontend/src/app/admin/myProfil/commentary.txt b/frontend/src/app/admin/myProfil/commentary.txt deleted file mode 100644 index ef51b49..0000000 --- a/frontend/src/app/admin/myProfil/commentary.txt +++ /dev/null @@ -1,7 +0,0 @@ -La page "admin/myProfil" contient: - - les informations de l'admin (composant "page-profil") - - un bouton "modifier profil" pour modifier les informations de l'admin (composant "popup-update-profil") - -Cette page est la même que la page de la partie utilisateur. - -Ainsi, on a rangé cette page dans le dossier "common/components/profil". diff --git a/frontend/src/app/admin/userList/page-user-list/page-user-list.component.html b/frontend/src/app/admin/userList/page-user-list/page-user-list.component.html deleted file mode 100644 index 483b6db..0000000 --- a/frontend/src/app/admin/userList/page-user-list/page-user-list.component.html +++ /dev/null @@ -1,67 +0,0 @@ -
- - - - -
- -
- - -
- - Filter - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Pseudo{{person.nickname}}Email{{person.email}}Rôle{{person.role}}Actions - - -
- - - - - -
-

diff --git a/frontend/src/app/admin/userList/page-user-list/page-user-list.component.scss b/frontend/src/app/admin/userList/page-user-list/page-user-list.component.scss deleted file mode 100644 index 78b21a9..0000000 --- a/frontend/src/app/admin/userList/page-user-list/page-user-list.component.scss +++ /dev/null @@ -1,18 +0,0 @@ -mat-paginator, table { - width: 80%; - margin: auto 10%; -} - -.btnContainer { - margin: 50px 10% 20px 0px; - text-align: right; -} - -.btnAjouter { - border: solid 1px black; -} - -.filtre { - text-align: center; - width: 33%; -} diff --git a/frontend/src/app/admin/userList/page-user-list/page-user-list.component.spec.ts b/frontend/src/app/admin/userList/page-user-list/page-user-list.component.spec.ts deleted file mode 100644 index 6bad939..0000000 --- a/frontend/src/app/admin/userList/page-user-list/page-user-list.component.spec.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { ComponentFixture, TestBed } from '@angular/core/testing'; - -import { PageUserListComponent } from './page-user-list.component'; - -describe('PageAdminComponent', () => { - let component: PageUserListComponent; - let fixture: ComponentFixture; - - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ PageUserListComponent ] - }) - .compileComponents(); - }); - - beforeEach(() => { - fixture = TestBed.createComponent(PageUserListComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); - - it('should create', () => { - expect(component).toBeTruthy(); - }); -}); diff --git a/frontend/src/app/admin/userList/page-user-list/page-user-list.component.ts b/frontend/src/app/admin/userList/page-user-list/page-user-list.component.ts deleted file mode 100644 index 6496d7e..0000000 --- a/frontend/src/app/admin/userList/page-user-list/page-user-list.component.ts +++ /dev/null @@ -1,152 +0,0 @@ -import {AfterViewInit, Component, ViewChild} from '@angular/core'; -import {MatTableDataSource} from "@angular/material/table"; -import {MatSort} from "@angular/material/sort"; -import {MatPaginator} from "@angular/material/paginator"; -import {MatDialog} from "@angular/material/dialog"; -import {PopupCreatePersonComponent} from "../popup-create-person/popup-create-person.component"; -import {MatSnackBar} from "@angular/material/snack-bar"; -import {PopupUpdatePersonAdminComponent} from "../popup-update-person-admin/popup-update-person-admin.component"; -import {PopupDeleteProfilComponent} from "../../../common/components/popup-delete-profil/popup-delete-profil.component"; -import {MessageService} from "../../../common/services/message/message.service"; - - - -@Component({ - selector: 'app-page-user-list', - templateUrl: './page-user-list.component.html', - styleUrls: ['./page-user-list.component.scss'] -}) -export class PageUserListComponent implements AfterViewInit -{ - displayedColumns: string[] = [ "nickname", "email", "role", "actions" ]; - dataSource: MatTableDataSource = new MatTableDataSource(); - @ViewChild(MatSort) sort: MatSort; - @ViewChild(MatPaginator) paginator: MatPaginator; - configSnackBar = { duration: 2000, panelClass: "custom-class" }; - - - constructor( private messageService: MessageService, - public dialog: MatDialog, - private snackBar: MatSnackBar) { } - - - ngAfterViewInit(): void - { - this.messageService - .get('users?order_by=nickname') - .subscribe(retour => this.ngAfterViewInitCallback(retour), err => this.ngAfterViewInitCallback(err)); - } - - - ngAfterViewInitCallback(retour: any): void - { - if(retour.status !== "success") { - console.log(retour); - } - else { - let tabPerson: { id: number, email: string, nickname: string, is_admin: boolean }[] = retour.data; - tabPerson = tabPerson.map( person => { - if(!person.is_admin) return Object.assign(person, {role: "utilisateur"}); - else return Object.assign(person, {role: "admin"}); - }); - this.dataSource = new MatTableDataSource(tabPerson); - this.dataSource.sort = this.sort; - this.dataSource.paginator = this.paginator; - } - } - - - applyFilter(event: Event) - { - const filterValue = (event.target as HTMLInputElement).value; - this.dataSource.filter = filterValue.trim().toLowerCase(); - } - - - // Appuie sur le bouton "create" - onCreate(): void - { - const config = { width: '50%' }; - this.dialog - .open(PopupCreatePersonComponent, config) - .afterClosed() - .subscribe( retour => { - - if((retour === null) || (retour === undefined)) - { - this.snackBar.open( "Opération annulée", "", this.configSnackBar); - } - else { - if(retour.data.is_admin) retour.data.role = "admin" ; - else retour.data.role = "utilisateur" ; - this.dataSource.data.push(retour.data); - this.dataSource.data = this.dataSource.data; - this.dataSource = this.dataSource; - this.snackBar.open( "L'utilisateur a bien été créé ✔", "", this.configSnackBar); - } - }); - } - - - // Appuie sur le bouton "edit" - onUpdate(personToUpdate: any): void - { - const config = { - width: '50%', - data: { person: personToUpdate } - }; - this.dialog - .open(PopupUpdatePersonAdminComponent, config) - .afterClosed() - .subscribe( is_admin => { - - if((is_admin === null) || (is_admin === undefined)) - { - this.snackBar.open("Opération annulée", "", this.configSnackBar); - } - else { - const index = this.dataSource.data.findIndex(elt => (elt.id === personToUpdate.id)); - this.dataSource.data[index].is_admin = is_admin; - if(is_admin) this.dataSource.data[index].role = "admin"; - else this.dataSource.data[index].role = "utilisateur"; - this.snackBar.open("L'utilisateur a bien été modifié ✔", "", this.configSnackBar); - } - - }); - } - - - // Appuie sur le bouton "delete" - onDelete(personToDelete: any): void - { - const config = { - data: { - id: personToDelete.id, - email: personToDelete.email, - me: false, - } - }; - this.dialog - .open(PopupDeleteProfilComponent, config) - .afterClosed() - .subscribe( retour => { - - if((retour === null) || (retour === undefined)) - { - this.snackBar.open("Opération annulée", "", this.configSnackBar); - } - else if(retour.status === "error") - { - this.snackBar.open(retour.error.message, "", this.configSnackBar); - } - else { - const index = this.dataSource.data.findIndex( elt => (elt.id === personToDelete.id)); - this.dataSource.data.splice(index, 1); - this.dataSource.data = this.dataSource.data; - this.dataSource = this.dataSource; - this.snackBar.open("L'utilisateur a bien été supprimé ✔", "", this.configSnackBar); - } - }); - } - -} diff --git a/frontend/src/app/admin/userList/popup-create-person/popup-create-person.component.html b/frontend/src/app/admin/userList/popup-create-person/popup-create-person.component.html deleted file mode 100644 index 15a27f5..0000000 --- a/frontend/src/app/admin/userList/popup-create-person/popup-create-person.component.html +++ /dev/null @@ -1,47 +0,0 @@ -
- -

Ajouter un utilisateur

- - - - - - Pseudo - -
- - - - Email - -
- - - - Mot de passe - -
- - - - Confirmation mot de passe - -
- - - - Utilisateur   - Admin -

- - - - -
- {{errorMessage}} -
- - - - -
diff --git a/frontend/src/app/admin/userList/popup-create-person/popup-create-person.component.scss b/frontend/src/app/admin/userList/popup-create-person/popup-create-person.component.scss deleted file mode 100644 index a95b14d..0000000 --- a/frontend/src/app/admin/userList/popup-create-person/popup-create-person.component.scss +++ /dev/null @@ -1,13 +0,0 @@ -.myContainer { - text-align: center; -} - -::ng-deep .mat-radio-inner-circle { - color: black !important; - background-color: black !important; -} - -::ng-deep .mat-radio-outer-circle{ - color: black !important; - border: solid 1px gray !important; -} diff --git a/frontend/src/app/admin/userList/popup-create-person/popup-create-person.component.spec.ts b/frontend/src/app/admin/userList/popup-create-person/popup-create-person.component.spec.ts deleted file mode 100644 index 29a8b97..0000000 --- a/frontend/src/app/admin/userList/popup-create-person/popup-create-person.component.spec.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { ComponentFixture, TestBed } from '@angular/core/testing'; - -import { PopupCreatePersonComponent } from './popup-create-person.component'; - -describe('PopupCreerUtilisateurComponent', () => { - let component: PopupCreatePersonComponent; - let fixture: ComponentFixture; - - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ PopupCreatePersonComponent ] - }) - .compileComponents(); - }); - - beforeEach(() => { - fixture = TestBed.createComponent(PopupCreatePersonComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); - - it('should create', () => { - expect(component).toBeTruthy(); - }); -}); diff --git a/frontend/src/app/admin/userList/popup-create-person/popup-create-person.component.ts b/frontend/src/app/admin/userList/popup-create-person/popup-create-person.component.ts deleted file mode 100644 index 11f0b1c..0000000 --- a/frontend/src/app/admin/userList/popup-create-person/popup-create-person.component.ts +++ /dev/null @@ -1,95 +0,0 @@ -import {Component, Inject} from '@angular/core'; -import {MAT_DIALOG_DATA, MatDialogRef} from "@angular/material/dialog"; -import {CheckEmailService} from "../../../common/services/checkEmail/check-email.service"; -import {MessageService} from "../../../common/services/message/message.service"; - - - -@Component({ - selector: 'app-popup-create-person', - templateUrl: './popup-create-person.component.html', - styleUrls: ['./popup-create-person.component.scss'] -}) -export class PopupCreatePersonComponent -{ - nickname: string = ""; - email: string = ""; - is_admin: boolean = false; - password: string = ""; - - confirmPassword: string = "" ; - hasError: boolean = false; - errorMessage: string = "" ; - - - constructor( public dialogRef: MatDialogRef, - @Inject(MAT_DIALOG_DATA) public data: any, - private checkEmailService: CheckEmailService, - private messageService: MessageService ) { } - - - // Appuie sur le bouton "valider" - onValider(): void - { - this.checkField(); - if(!this.hasError) - { - const data = { - email: this.email, - nickname: this.nickname, - password: this.password, - is_admin: this.is_admin - }; - this.messageService - .post("admin/create/user", data) - .subscribe(ret => this.onValiderCallback(ret), err => this.onValiderCallback(err)); - } - } - - - // Callback de 'onValider' - onValiderCallback(retour: any) - { - if(retour.status !== 'success') - { - console.log(retour); - this.errorMessage = retour.error.message; - this.hasError = true; - } - else - { - this.dialogRef.close(retour); - } - } - - - // Check les champs saisis par l'utilisateur - checkField(): void - { - if(this.nickname.length === 0) { - this.errorMessage = "Veuillez remplir le champ 'pseudo'."; - this.hasError = true; - } - else if(this.email.length === 0) { - this.errorMessage = "Veuillez remplir le champ 'email'."; - this.hasError = true; - } - else if(!this.checkEmailService.isValidEmail(this.email)) { - this.errorMessage = "Email invalide."; - this.hasError = true; - } - else if(this.password.length === 0) { - this.errorMessage = "Veuillez remplir le champ 'mot de passe'."; - this.hasError = true; - } - else if(this.password !== this.confirmPassword) { - this.errorMessage = "Le mot de passe est différent de sa confirmation."; - this.hasError = true; - } - else { - this.errorMessage = "" ; - this.hasError = false; - } - } - -} diff --git a/frontend/src/app/admin/userList/popup-update-person-admin/popup-update-person-admin.component.html b/frontend/src/app/admin/userList/popup-update-person-admin/popup-update-person-admin.component.html deleted file mode 100644 index 2c2e58c..0000000 --- a/frontend/src/app/admin/userList/popup-update-person-admin/popup-update-person-admin.component.html +++ /dev/null @@ -1,57 +0,0 @@ -
-
- -

Modifier

- - -
- - - - Utilisateur   - Admin -

- - -
- - -
- Modifier mot de passe: - -
- - -
- - - Nouveau mot de passe - - -
- - - Confirmation nouveau mot de passe - - -
-

- - -
- - -
- {{errorMessage}} -
- - -
- - -
- -
-
diff --git a/frontend/src/app/admin/userList/popup-update-person-admin/popup-update-person-admin.component.scss b/frontend/src/app/admin/userList/popup-update-person-admin/popup-update-person-admin.component.scss deleted file mode 100644 index 1317c7a..0000000 --- a/frontend/src/app/admin/userList/popup-update-person-admin/popup-update-person-admin.component.scss +++ /dev/null @@ -1,37 +0,0 @@ -.boite { - font-size: small; -} - -h3 { - text-align: center; -} - -button { - font-size: small; -} - -img { - margin: 0px 0px 10px 0px; - width: 5vw; - height: 5vw; - border: solid 2px black; - border-radius: 50%; - font-size: xxx-large; -} - -// ------------------------------------------------------------------------- - -// aura -::ng-deep .mat-checkbox-ripple .mat-ripple-element { - background-color: grey !important; -} - -// contenu coche -::ng-deep .mat-checkbox-checked.mat-accent .mat-checkbox-background { - background-color: black !important; -} - -// indeterminate -::ng-deep .mat-checkbox .mat-checkbox-frame { - background-color: white !important; -} diff --git a/frontend/src/app/admin/userList/popup-update-person-admin/popup-update-person-admin.component.spec.ts b/frontend/src/app/admin/userList/popup-update-person-admin/popup-update-person-admin.component.spec.ts deleted file mode 100644 index 431857c..0000000 --- a/frontend/src/app/admin/userList/popup-update-person-admin/popup-update-person-admin.component.spec.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { ComponentFixture, TestBed } from '@angular/core/testing'; - -import { PopupUpdatePersonAdminComponent } from './popup-update-person-admin.component'; - -describe('PopupUpdatePersonAdminComponent', () => { - let component: PopupUpdatePersonAdminComponent; - let fixture: ComponentFixture; - - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ PopupUpdatePersonAdminComponent ] - }) - .compileComponents(); - }); - - beforeEach(() => { - fixture = TestBed.createComponent(PopupUpdatePersonAdminComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); - - it('should create', () => { - expect(component).toBeTruthy(); - }); -}); diff --git a/frontend/src/app/admin/userList/popup-update-person-admin/popup-update-person-admin.component.ts b/frontend/src/app/admin/userList/popup-update-person-admin/popup-update-person-admin.component.ts deleted file mode 100644 index 1bf55e4..0000000 --- a/frontend/src/app/admin/userList/popup-update-person-admin/popup-update-person-admin.component.ts +++ /dev/null @@ -1,87 +0,0 @@ -import {Component, Inject, OnInit} from '@angular/core'; -import {MAT_DIALOG_DATA, MatDialogRef} from "@angular/material/dialog"; -import {CheckEmailService} from "../../../common/services/checkEmail/check-email.service"; -import {MessageService} from "../../../common/services/message/message.service"; - - - -@Component({ - selector: 'app-popup-update-person-admin', - templateUrl: './popup-update-person-admin.component.html', - styleUrls: ['./popup-update-person-admin.component.scss'] -}) -export class PopupUpdatePersonAdminComponent implements OnInit -{ - id: number = 0; - is_admin: boolean = false; - newPassword: string = ""; - - confirmNewPassword: string = "" ; - changePassword: boolean = false ; - hasError: boolean = false; - errorMessage: string = "" ; - - - constructor( public dialogRef: MatDialogRef, - @Inject(MAT_DIALOG_DATA) public data: any, - private checkEmailService: CheckEmailService, - private messageService: MessageService ) { } - - - ngOnInit(): void - { - this.id = this.data.person.id; - this.is_admin = this.data.person.is_admin; - } - - - // Appuie sur le bouton "valider" - onValider(): void - { - this.checkField(); - if(!this.hasError) - { - let data = {}; - if(this.changePassword) data = { id: this.id, is_admin: this.is_admin, password: this.newPassword } - else data = { id: this.id, is_admin: this.is_admin }; - this.messageService - .put("admin/update/user", data) - .subscribe(ret => this.onValiderCallback(ret), err => this.onValiderCallback(err)); - } - } - - - // Callback de 'onValider' - onValiderCallback(retour: any) - { - if(retour.status !== 'success') - { - console.log(retour); - this.errorMessage = retour.error.message; - this.hasError = true; - } - else - { - this.dialogRef.close(this.is_admin); - } - } - - - // Check les champs saisis par l'utilisateur - checkField(): void - { - if((this.changePassword) && (this.newPassword.length === 0)) { - this.errorMessage = "Veuillez remplir le champ 'mot de passe'"; - this.hasError = true; - } - else if((this.changePassword) && (this.newPassword !== this.confirmNewPassword)) { - this.errorMessage = "Le mot de passe est différent de sa confirmation"; - this.hasError = true; - } - else { - this.errorMessage = "" ; - this.hasError = false; - } - } - -} diff --git a/frontend/src/app/app-routing.module.ts b/frontend/src/app/app-routing.module.ts deleted file mode 100644 index 6fd371d..0000000 --- a/frontend/src/app/app-routing.module.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { NgModule } from '@angular/core'; -import { RouterModule, Routes } from '@angular/router'; -import {PageLoginComponent} from "./login/page-login/page-login.component"; -import {PageRegisterComponent} from "./register/page-register/page-register.component"; -import {PageProfilComponent} from "./common/components/page-profil/page-profil.component"; -import {PageUserListComponent} from "./admin/userList/page-user-list/page-user-list.component"; -import {PageRegistryComponent} from "./user/page-registry/page-registry.component"; -import {UserGuard} from "./common/guards/user/user.guard"; -import {AdminGuard} from "./common/guards/admin/admin.guard"; - -const routes: Routes = [ - - { path: "", component: PageLoginComponent }, - { path: "login", component: PageLoginComponent }, - - { path: "register", component: PageRegisterComponent }, - - { path: "user", component: PageRegistryComponent, canActivate: [UserGuard] }, - { path: "user/registry", component: PageRegistryComponent, canActivate: [UserGuard] }, - { path: "user/myProfil", component: PageProfilComponent, canActivate: [UserGuard] }, - - { path: "admin", component: PageUserListComponent, canActivate: [AdminGuard] }, - { path: "admin/userList", component: PageUserListComponent, canActivate: [AdminGuard] }, - { path: "admin/myProfil", component: PageProfilComponent, canActivate: [AdminGuard] }, -]; - -@NgModule({ - imports: [RouterModule.forRoot(routes)], - exports: [RouterModule] -}) -export class AppRoutingModule { } diff --git a/frontend/src/app/app.component.html b/frontend/src/app/app.component.html deleted file mode 100644 index d5d92f3..0000000 --- a/frontend/src/app/app.component.html +++ /dev/null @@ -1,2 +0,0 @@ - - diff --git a/frontend/src/app/app.component.scss b/frontend/src/app/app.component.scss deleted file mode 100644 index e69de29..0000000 diff --git a/frontend/src/app/app.component.spec.ts b/frontend/src/app/app.component.spec.ts deleted file mode 100644 index 74b5b3e..0000000 --- a/frontend/src/app/app.component.spec.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { TestBed } from '@angular/core/testing'; -import { RouterTestingModule } from '@angular/router/testing'; -import { AppComponent } from './app.component'; - -describe('AppComponent', () => { - beforeEach(async () => { - await TestBed.configureTestingModule({ - imports: [ - RouterTestingModule - ], - declarations: [ - AppComponent - ], - }).compileComponents(); - }); - - it('should create the app', () => { - const fixture = TestBed.createComponent(AppComponent); - const app = fixture.componentInstance; - expect(app).toBeTruthy(); - }); - - it(`should have as title 'frontend'`, () => { - const fixture = TestBed.createComponent(AppComponent); - const app = fixture.componentInstance; - expect(app.title).toEqual('frontend'); - }); - - it('should render title', () => { - const fixture = TestBed.createComponent(AppComponent); - fixture.detectChanges(); - const compiled = fixture.nativeElement as HTMLElement; - expect(compiled.querySelector('.content span')?.textContent).toContain('frontend app is running!'); - }); -}); diff --git a/frontend/src/app/app.component.ts b/frontend/src/app/app.component.ts deleted file mode 100644 index 0c5a793..0000000 --- a/frontend/src/app/app.component.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { Component } from '@angular/core'; - -@Component({ - selector: 'app-root', - templateUrl: './app.component.html', - styleUrls: ['./app.component.scss'] -}) -export class AppComponent { - title = 'frontend'; -} diff --git a/frontend/src/app/app.module.ts b/frontend/src/app/app.module.ts deleted file mode 100644 index ebfbd59..0000000 --- a/frontend/src/app/app.module.ts +++ /dev/null @@ -1,72 +0,0 @@ -import { NgModule } from '@angular/core'; -import { BrowserModule } from '@angular/platform-browser'; - -import { AppRoutingModule } from './app-routing.module'; -import { AppComponent } from './app.component'; -import { PageRegisterComponent } from './register/page-register/page-register.component'; -import {FormsModule} from "@angular/forms"; -import {BrowserAnimationsModule} from "@angular/platform-browser/animations"; -import {MatFormFieldModule} from "@angular/material/form-field"; -import {MatInputModule} from "@angular/material/input"; -import {PageLoginComponent} from "./login/page-login/page-login.component"; -import { NavbarComponent } from './common/components/navbar/navbar.component'; -import {MatButtonModule} from "@angular/material/button"; -import { PageProfilComponent } from './common/components/page-profil/page-profil.component'; -import { PopupUpdateProfilComponent } from './common/components/popup-update-profil/popup-update-profil.component'; -import {MatDividerModule} from "@angular/material/divider"; -import {MatCheckboxModule} from "@angular/material/checkbox"; -import {MatDialogModule} from "@angular/material/dialog"; -import {MatSnackBarModule} from "@angular/material/snack-bar"; -import { PageUserListComponent } from './admin/userList/page-user-list/page-user-list.component'; -import { PopupCreatePersonComponent } from './admin/userList/popup-create-person/popup-create-person.component'; -import {MatTableModule} from "@angular/material/table"; -import {MatPaginatorModule} from "@angular/material/paginator"; -import { PopupConfirmRegisterComponent } from './register/popup-confirm-register/popup-confirm-register.component'; -import {MatIconModule} from "@angular/material/icon"; -import {MatRadioModule} from "@angular/material/radio"; -import { PageRegistryComponent } from './user/page-registry/page-registry.component'; -import { PopupDeleteProfilComponent } from './common/components/popup-delete-profil/popup-delete-profil.component'; -import {MatSortModule} from "@angular/material/sort"; -import { PopupUpdatePersonAdminComponent } from './admin/userList/popup-update-person-admin/popup-update-person-admin.component'; -import {HttpClientModule} from "@angular/common/http"; - - - -@NgModule({ - declarations: [ - AppComponent, - PageLoginComponent, - PageRegisterComponent, - NavbarComponent, - PageProfilComponent, - PopupUpdateProfilComponent, - PageUserListComponent, - PopupCreatePersonComponent, - PopupConfirmRegisterComponent, - PageRegistryComponent, - PopupDeleteProfilComponent, - PopupUpdatePersonAdminComponent - ], - imports: [ - BrowserModule, - AppRoutingModule, - FormsModule, - BrowserAnimationsModule, - HttpClientModule, - MatFormFieldModule, - MatInputModule, - MatButtonModule, - MatDividerModule, - MatCheckboxModule, - MatDialogModule, - MatSnackBarModule, - MatTableModule, - MatPaginatorModule, - MatSortModule, - MatIconModule, - MatRadioModule - ], - providers: [], - bootstrap: [AppComponent] -}) -export class AppModule { } diff --git a/frontend/src/app/common/components/navbar/navbar.component.html b/frontend/src/app/common/components/navbar/navbar.component.html deleted file mode 100644 index 2d09333..0000000 --- a/frontend/src/app/common/components/navbar/navbar.component.html +++ /dev/null @@ -1,108 +0,0 @@ - -
- -
- - - - - - -
- -
- - - - - - -
- -
- - - - - - -
- -
diff --git a/frontend/src/app/common/components/navbar/navbar.component.scss b/frontend/src/app/common/components/navbar/navbar.component.scss deleted file mode 100644 index a64cc59..0000000 --- a/frontend/src/app/common/components/navbar/navbar.component.scss +++ /dev/null @@ -1,59 +0,0 @@ -.navbar { - background-color: black; - height: 60px; - font-size: medium; - color: white; -} - - -.navbar-expand-lg { - border-bottom: solid; - border-color: white; - border-bottom-width: 2px; -} - - -// PolyNotFound -.navbar-brand { - font-family: cursive; - font-weight: bold; - font-size: x-large; - margin-left: 15px; - color: white; -} - - -// Recherche, Mes Playlists, Historique -.nav-link { - color: white; -} -.nav-link:hover { - color: grey; -} - - -// Bonton deconnexion -.btnDeconnexion { - font-size: medium; - margin: 0px 10px 0px 10px -} -.btnDeconnexion:hover { - color: grey; -} - - -.monLi { - margin: 0px 10px 0px 10px; -} - - -img { - border: solid 2px white; - border-radius: 50px; - margin: 0px 10px 0px 15px; - width: 40px; - height: 40px; -} -img:hover { - cursor: pointer; -} diff --git a/frontend/src/app/common/components/navbar/navbar.component.spec.ts b/frontend/src/app/common/components/navbar/navbar.component.spec.ts deleted file mode 100644 index f8ccd6f..0000000 --- a/frontend/src/app/common/components/navbar/navbar.component.spec.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { ComponentFixture, TestBed } from '@angular/core/testing'; - -import { NavbarComponent } from './navbar.component'; - -describe('NavbarComponent', () => { - let component: NavbarComponent; - let fixture: ComponentFixture; - - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ NavbarComponent ] - }) - .compileComponents(); - }); - - beforeEach(() => { - fixture = TestBed.createComponent(NavbarComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); - - it('should create', () => { - expect(component).toBeTruthy(); - }); -}); diff --git a/frontend/src/app/common/components/navbar/navbar.component.ts b/frontend/src/app/common/components/navbar/navbar.component.ts deleted file mode 100644 index 19d0c04..0000000 --- a/frontend/src/app/common/components/navbar/navbar.component.ts +++ /dev/null @@ -1,32 +0,0 @@ -import {Component, Input, OnInit} from '@angular/core'; -import {ProfilService} from "../../services/profil/profil.service"; -import {MessageService} from "../../services/message/message.service"; - -@Component({ - selector: 'app-navbar', - templateUrl: './navbar.component.html', - styleUrls: ['./navbar.component.scss'] -}) -export class NavbarComponent implements OnInit -{ - @Input() pour = "login"; - - constructor(private profilService: ProfilService, private messageService: MessageService) { } - - ngOnInit(): void {} - - onDeconnexion(): void - { - this.messageService - .delete('logout') - .subscribe(retour => this.onDeconnexionCallback(retour), err => this.onDeconnexionCallback(err)); - this.profilService.setId(-1); - this.profilService.setIsAdmin(false); - } - - onDeconnexionCallback(retour: any): void - { - if(retour.status !== "success") console.log(retour); - } - -} diff --git a/frontend/src/app/common/components/page-profil/page-profil.component.html b/frontend/src/app/common/components/page-profil/page-profil.component.html deleted file mode 100644 index ad7d8a3..0000000 --- a/frontend/src/app/common/components/page-profil/page-profil.component.html +++ /dev/null @@ -1,53 +0,0 @@ -
- - - - - - -
- - -
-
Pseudo:
-
{{person.nickname}}
-
- - -
-
Mail:
-
{{person.email}}
-
- - -
-
Rôle:
-
- utilisateur - admin -
- - -
- -
-
- -
-
- -
-
- -
-
-
- -
- - -
diff --git a/frontend/src/app/common/components/page-profil/page-profil.component.scss b/frontend/src/app/common/components/page-profil/page-profil.component.scss deleted file mode 100644 index fa50561..0000000 --- a/frontend/src/app/common/components/page-profil/page-profil.component.scss +++ /dev/null @@ -1,45 +0,0 @@ -.myContainer { - max-width: 100vw; - height: 100vh; - overflow-x: hidden; -} - - -.boite { - margin-left: auto; - margin-right: auto; - width: 50%; - margin-top: 10vh; - border: solid 3px; - border-radius: 10px; - padding: 20px 40px 20px 40px; - background-color: #ffffff; - text-align: center; - box-shadow: 10px 5px 5px black; -} - - -.myRow { - margin: 15px 0px 15px 0px; -} -.myLabel { - text-align: right; - padding: 0px 5px 0px 0px; - margin: 0px; - font-weight: bold; -} -.myValue { - text-align: left; - padding: 0px 0px 0px 5px; - margin: 0px; -} - - -.btnContainer { - text-align: center; - margin-top: 40px; -} -.myBtn { - border: solid 1px black; - background-color: white; -} diff --git a/frontend/src/app/common/components/page-profil/page-profil.component.spec.ts b/frontend/src/app/common/components/page-profil/page-profil.component.spec.ts deleted file mode 100644 index 958b80e..0000000 --- a/frontend/src/app/common/components/page-profil/page-profil.component.spec.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { ComponentFixture, TestBed } from '@angular/core/testing'; - -import { PageProfilComponent } from './page-profil.component'; - -describe('PageUtilisateurComponent', () => { - let component: PageProfilComponent; - let fixture: ComponentFixture; - - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ PageProfilComponent ] - }) - .compileComponents(); - }); - - beforeEach(() => { - fixture = TestBed.createComponent(PageProfilComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); - - it('should create', () => { - expect(component).toBeTruthy(); - }); -}); diff --git a/frontend/src/app/common/components/page-profil/page-profil.component.ts b/frontend/src/app/common/components/page-profil/page-profil.component.ts deleted file mode 100644 index 23e3d43..0000000 --- a/frontend/src/app/common/components/page-profil/page-profil.component.ts +++ /dev/null @@ -1,110 +0,0 @@ -import { Component, OnInit } from '@angular/core'; -import {MatDialog} from "@angular/material/dialog"; -import {MatSnackBar} from "@angular/material/snack-bar"; -import {PopupUpdateProfilComponent} from "../popup-update-profil/popup-update-profil.component"; -import {Router} from "@angular/router"; -import {PopupDeleteProfilComponent} from "../popup-delete-profil/popup-delete-profil.component"; -import {MessageService} from "../../services/message/message.service"; -import {HttpParams} from "@angular/common/http"; -import {ProfilService} from "../../services/profil/profil.service"; - - - -@Component({ - selector: 'app-page-profil', - templateUrl: './page-profil.component.html', - styleUrls: ['./page-profil.component.scss'] -}) -export class PageProfilComponent implements OnInit -{ - person = { - id: "", - nickname: "", - email: "", - is_admin: false, - }; - from: string = "" ; - configSnackbar = { duration: 3000, panelClass: "custom-class" }; - - - constructor( private messageService: MessageService, - private profilService: ProfilService, - public dialog: MatDialog, - private snackBar: MatSnackBar, - private router: Router ) { } - - - ngOnInit(): void - { - if(this.router.url.startsWith("/user")) this.from = "user" ; - else if(this.router.url.startsWith("/admin")) this.from = "admin" ; - - let params = new HttpParams() - params = params.set("order_by", "nickname"); - params = params.set("id", this.profilService.getId()); - this.messageService - .get("users", params) - .subscribe(ret => this.ngOnInitCallback(ret), err => this.ngOnInitCallback(err)); - } - - - // Callback de ngOnInit - ngOnInitCallback(retour: any): void - { - if(retour.status !== "success") { - console.log(retour); - } - else { - this.person = retour.data[0]; - } - } - - - // Appuie sur le bouton modifier - onModifier(): void - { - const config = { - width: '25%', - data: { person: this.person } - }; - this.dialog - .open(PopupUpdateProfilComponent, config) - .afterClosed() - .subscribe(retour => this.onModifierCallback(retour)); - } - - - // Callback de onModifier - onModifierCallback(retour: any): void - { - if((retour === null) || (retour === undefined)) this.snackBar.open( "Opération annulé", "", this.configSnackbar); - else if(retour.status === "success") this.person = retour.data; - } - - - // Appuie sur le bouton supprimer - onSupprimer(): void - { - const config = { - data: { - id: this.person.id, - email: this.person.email, - me: true, - } - }; - this.dialog - .open(PopupDeleteProfilComponent, config) - .afterClosed() - .subscribe(retour => this.onSupprimerCallback(retour)); - } - - - // Callback de onSupprimer - onSupprimerCallback(retour: any): void - { - if((retour === null) || (retour === undefined)) this.snackBar.open( "Opération annulé", "", this.configSnackbar); - else if(retour.status === "error") this.snackBar.open(retour.error.message, "", this.configSnackbar); - else if(retour.status === "success") this.router.navigateByUrl("/login"); - } - -} diff --git a/frontend/src/app/common/components/popup-delete-profil/popup-delete-profil.component.html b/frontend/src/app/common/components/popup-delete-profil/popup-delete-profil.component.html deleted file mode 100644 index 9118e3b..0000000 --- a/frontend/src/app/common/components/popup-delete-profil/popup-delete-profil.component.html +++ /dev/null @@ -1,14 +0,0 @@ - - Êtes-vous sûr de vouloir supprimer votre compte ? - - - - - Êtes-vous sûr de vouloir supprimer {{email}} ? - - - - - - - diff --git a/frontend/src/app/common/components/popup-delete-profil/popup-delete-profil.component.scss b/frontend/src/app/common/components/popup-delete-profil/popup-delete-profil.component.scss deleted file mode 100644 index e69de29..0000000 diff --git a/frontend/src/app/common/components/popup-delete-profil/popup-delete-profil.component.spec.ts b/frontend/src/app/common/components/popup-delete-profil/popup-delete-profil.component.spec.ts deleted file mode 100644 index 8743fad..0000000 --- a/frontend/src/app/common/components/popup-delete-profil/popup-delete-profil.component.spec.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { ComponentFixture, TestBed } from '@angular/core/testing'; - -import { PopupDeleteProfilComponent } from './popup-delete-profil.component'; - -describe('PopupDeleteProfilComponent', () => { - let component: PopupDeleteProfilComponent; - let fixture: ComponentFixture; - - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ PopupDeleteProfilComponent ] - }) - .compileComponents(); - }); - - beforeEach(() => { - fixture = TestBed.createComponent(PopupDeleteProfilComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); - - it('should create', () => { - expect(component).toBeTruthy(); - }); -}); diff --git a/frontend/src/app/common/components/popup-delete-profil/popup-delete-profil.component.ts b/frontend/src/app/common/components/popup-delete-profil/popup-delete-profil.component.ts deleted file mode 100644 index 49d6b5b..0000000 --- a/frontend/src/app/common/components/popup-delete-profil/popup-delete-profil.component.ts +++ /dev/null @@ -1,68 +0,0 @@ -import {Component, Inject, OnInit} from '@angular/core'; -import {MAT_DIALOG_DATA, MatDialogRef} from "@angular/material/dialog"; -import {MessageService} from "../../services/message/message.service"; -import {HttpParams} from "@angular/common/http"; - - - -@Component({ - selector: 'app-popup-delete-profil', - templateUrl: './popup-delete-profil.component.html', - styleUrls: ['./popup-delete-profil.component.scss'] -}) -export class PopupDeleteProfilComponent implements OnInit -{ - id: number; - me: boolean = false; // on se supprime soi-même - email: string = ""; - - - constructor( private messageService: MessageService, - public dialogRef: MatDialogRef, - @Inject(MAT_DIALOG_DATA) public data: any ) { } - - - ngOnInit(): void { - this.id = this.data.id; - this.me = this.data.me; - this.email = this.data.email; - } - - - // Appuie sur 'valider' - onValider(): void - { - if(this.me) - { - this.messageService - .delete("user/delete") - .subscribe(ret => this.onValiderCallback(ret), err => this.onValiderCallback(err)); - } - else { - //let params = (new HttpParams()).set("id", this.id); - this.messageService - .delete("admin/delete/user/"+this.id) - .subscribe(ret => this.onValiderCallback(ret), err => this.onValiderCallback(err)); - } - } - - - // Callback de onValider - onValiderCallback(retour: any): void - { - if(retour.status === "success") - { - this.dialogRef.close(retour); - } - else if(retour.status === "error") - { - console.log(retour); - this.dialogRef.close(retour); - } - else { - console.log(retour); - this.dialogRef.close(null); - } - } - -} diff --git a/frontend/src/app/common/components/popup-update-profil/popup-update-profil.component.html b/frontend/src/app/common/components/popup-update-profil/popup-update-profil.component.html deleted file mode 100644 index c28fe07..0000000 --- a/frontend/src/app/common/components/popup-update-profil/popup-update-profil.component.html +++ /dev/null @@ -1,55 +0,0 @@ -
-
- -

Modifier

- - -

- - - - Pseudo - -
- - -
- - -
- Modifier mot de passe: - -
- - -
- - - Nouveau mot de passe - - -
- - - Confirmation nouveau mot de passe - - -
-

- - -
- - -
- {{errorMessage}} -
- - -
- - -
- -
-
diff --git a/frontend/src/app/common/components/popup-update-profil/popup-update-profil.component.scss b/frontend/src/app/common/components/popup-update-profil/popup-update-profil.component.scss deleted file mode 100644 index 1317c7a..0000000 --- a/frontend/src/app/common/components/popup-update-profil/popup-update-profil.component.scss +++ /dev/null @@ -1,37 +0,0 @@ -.boite { - font-size: small; -} - -h3 { - text-align: center; -} - -button { - font-size: small; -} - -img { - margin: 0px 0px 10px 0px; - width: 5vw; - height: 5vw; - border: solid 2px black; - border-radius: 50%; - font-size: xxx-large; -} - -// ------------------------------------------------------------------------- - -// aura -::ng-deep .mat-checkbox-ripple .mat-ripple-element { - background-color: grey !important; -} - -// contenu coche -::ng-deep .mat-checkbox-checked.mat-accent .mat-checkbox-background { - background-color: black !important; -} - -// indeterminate -::ng-deep .mat-checkbox .mat-checkbox-frame { - background-color: white !important; -} diff --git a/frontend/src/app/common/components/popup-update-profil/popup-update-profil.component.spec.ts b/frontend/src/app/common/components/popup-update-profil/popup-update-profil.component.spec.ts deleted file mode 100644 index 6d2a26b..0000000 --- a/frontend/src/app/common/components/popup-update-profil/popup-update-profil.component.spec.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { ComponentFixture, TestBed } from '@angular/core/testing'; - -import { PopupUpdateProfilComponent } from './popup-update-profil.component'; - -describe('PopupModifierUtilisateurComponent', () => { - let component: PopupUpdateProfilComponent; - let fixture: ComponentFixture; - - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ PopupUpdateProfilComponent ] - }) - .compileComponents(); - }); - - beforeEach(() => { - fixture = TestBed.createComponent(PopupUpdateProfilComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); - - it('should create', () => { - expect(component).toBeTruthy(); - }); -}); diff --git a/frontend/src/app/common/components/popup-update-profil/popup-update-profil.component.ts b/frontend/src/app/common/components/popup-update-profil/popup-update-profil.component.ts deleted file mode 100644 index 4d92bc2..0000000 --- a/frontend/src/app/common/components/popup-update-profil/popup-update-profil.component.ts +++ /dev/null @@ -1,108 +0,0 @@ -import {Component, Inject, OnInit} from '@angular/core'; -import {MAT_DIALOG_DATA, MatDialogRef} from "@angular/material/dialog"; -import {CheckEmailService} from "../../services/checkEmail/check-email.service"; -import {MessageService} from "../../services/message/message.service"; - - - -@Component({ - selector: 'app-popup-update-profil', - templateUrl: './popup-update-profil.component.html', - styleUrls: ['./popup-update-profil.component.scss'] -}) -export class PopupUpdateProfilComponent implements OnInit -{ - personCopy: any; - newPassword: string = ""; - confirmNewPassword: string = "" ; - changePassword: boolean = false ; - hasError: boolean = false; - errorMessage: string = "" ; - - - constructor( private checkEmailService: CheckEmailService, - private messageService: MessageService, - public dialogRef: MatDialogRef, - @Inject(MAT_DIALOG_DATA) public data: any ) { } - - - ngOnInit(): void - { - const person = this.data.person; - this.personCopy = { - id: person.id, - nickname: person.nickname, - email: person.email, - is_admin: person.is_admin - }; - } - - - // Appuie sur le bouton "valider" - onValider(): void - { - this.checkField(); - if(!this.hasError) - { - let data: any = {nickname: this.personCopy.nickname}; - if(this.changePassword) data = { - nickname: this.personCopy.nickname, - password: this.newPassword - }; - this.messageService - .put("user/update", data) - .subscribe(ret => this.onValiderCallback(ret), err => this.onValiderCallback(err)); - } - } - - - // Callback de 'onValider' - onValiderCallback(retour: any) - { - if(retour.status === "success") - { - this.dialogRef.close(retour); - } - else if(retour.status === "error") - { - console.log(retour); - this.errorMessage = retour.message; - this.hasError = true; - } - else { - console.log(retour); - this.dialogRef.close(null); - } - } - - - // Check les champs saisis par l'utilisateur - checkField(): void - { - if(this.personCopy.nickname.length === 0) { - this.errorMessage = "Veuillez remplir le champ 'pseudo'" ; - this.hasError = true; - } - else if(this.personCopy.email.length === 0) { - this.errorMessage = "Veuillez remplir le champ 'email'" ; - this.hasError = true; - } - else if(!this.checkEmailService.isValidEmail(this.personCopy.email)) { - this.errorMessage = "Email invalide" ; - this.hasError = true; - } - else if((this.changePassword) && (this.newPassword.length === 0)) { - this.errorMessage = "Veuillez remplir le champ 'mot de passe'"; - this.hasError = true; - } - else if((this.changePassword) && (this.newPassword !== this.confirmNewPassword)) { - this.errorMessage = "Le mot de passe est différent de sa confirmation"; - this.hasError = true; - } - else { - this.errorMessage = "" ; - this.hasError = false; - } - } - -} diff --git a/frontend/src/app/common/guards/admin/admin.guard.spec.ts b/frontend/src/app/common/guards/admin/admin.guard.spec.ts deleted file mode 100644 index e982f62..0000000 --- a/frontend/src/app/common/guards/admin/admin.guard.spec.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { TestBed } from '@angular/core/testing'; - -import { AdminGuard } from './admin.guard'; - -describe('AdminGuard', () => { - let guard: AdminGuard; - - beforeEach(() => { - TestBed.configureTestingModule({}); - guard = TestBed.inject(AdminGuard); - }); - - it('should be created', () => { - expect(guard).toBeTruthy(); - }); -}); diff --git a/frontend/src/app/common/guards/admin/admin.guard.ts b/frontend/src/app/common/guards/admin/admin.guard.ts deleted file mode 100644 index 701b288..0000000 --- a/frontend/src/app/common/guards/admin/admin.guard.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { Injectable } from '@angular/core'; -import {ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot, UrlTree} from '@angular/router'; -import { Observable } from 'rxjs'; -import {ProfilService} from "../../services/profil/profil.service"; - -@Injectable({ - providedIn: 'root' -}) -export class AdminGuard implements CanActivate -{ - - constructor(private profilService: ProfilService, private router: Router) {} - - - canActivate( route: ActivatedRouteSnapshot, state: RouterStateSnapshot ): Observable | Promise | boolean | UrlTree - { - if(this.profilService.getId() === -1) // si non connecté - { - this.router.navigateByUrl("/login"); - return false; - } - else { - if(this.profilService.isAdmin()) return true; - else { - this.router.navigateByUrl("/login"); - return false; - } - } - } - -} diff --git a/frontend/src/app/common/guards/user/user.guard.spec.ts b/frontend/src/app/common/guards/user/user.guard.spec.ts deleted file mode 100644 index a657320..0000000 --- a/frontend/src/app/common/guards/user/user.guard.spec.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { TestBed } from '@angular/core/testing'; - -import { UserGuard } from './user.guard'; - -describe('UserGuard', () => { - let guard: UserGuard; - - beforeEach(() => { - TestBed.configureTestingModule({}); - guard = TestBed.inject(UserGuard); - }); - - it('should be created', () => { - expect(guard).toBeTruthy(); - }); -}); diff --git a/frontend/src/app/common/guards/user/user.guard.ts b/frontend/src/app/common/guards/user/user.guard.ts deleted file mode 100644 index d357d34..0000000 --- a/frontend/src/app/common/guards/user/user.guard.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { Injectable } from '@angular/core'; -import {ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot, UrlTree} from '@angular/router'; -import { Observable } from 'rxjs'; -import {ProfilService} from "../../services/profil/profil.service"; - -@Injectable({ - providedIn: 'root' -}) -export class UserGuard implements CanActivate -{ - - constructor(private profilService: ProfilService, private router: Router) {} - - - canActivate( route: ActivatedRouteSnapshot, state: RouterStateSnapshot ): Observable | Promise | boolean | UrlTree - { - if(this.profilService.getId() === -1) // si non connecté - { - this.router.navigateByUrl("/login"); - return false; - } - else { - if(!this.profilService.isAdmin()) return true; - else { - this.router.navigateByUrl("/login"); - return false; - } - } - } - -} diff --git a/frontend/src/app/common/services/checkEmail/check-email.service.spec.ts b/frontend/src/app/common/services/checkEmail/check-email.service.spec.ts deleted file mode 100644 index 49250c3..0000000 --- a/frontend/src/app/common/services/checkEmail/check-email.service.spec.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { TestBed } from '@angular/core/testing'; - -import { CheckEmailService } from './check-email.service'; - -describe('CheckEmailService', () => { - let service: CheckEmailService; - - beforeEach(() => { - TestBed.configureTestingModule({}); - service = TestBed.inject(CheckEmailService); - }); - - it('should be created', () => { - expect(service).toBeTruthy(); - }); -}); diff --git a/frontend/src/app/common/services/checkEmail/check-email.service.ts b/frontend/src/app/common/services/checkEmail/check-email.service.ts deleted file mode 100644 index 0ed4cb8..0000000 --- a/frontend/src/app/common/services/checkEmail/check-email.service.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { Injectable } from '@angular/core'; - -@Injectable({ - providedIn: 'root' -}) -export class CheckEmailService -{ - - isValidEmail(email: string): boolean - { - let re = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/; - return re.test(email); - } - -} diff --git a/frontend/src/app/common/services/fictitiousDatas/fictitious-datas.service.spec.ts b/frontend/src/app/common/services/fictitiousDatas/fictitious-datas.service.spec.ts deleted file mode 100644 index 17d518a..0000000 --- a/frontend/src/app/common/services/fictitiousDatas/fictitious-datas.service.spec.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { TestBed } from '@angular/core/testing'; - -import { FictitiousDatasService } from './fictitious-datas.service'; - -describe('FictitiousDatasService', () => { - let service: FictitiousDatasService; - - beforeEach(() => { - TestBed.configureTestingModule({}); - service = TestBed.inject(FictitiousDatasService); - }); - - it('should be created', () => { - expect(service).toBeTruthy(); - }); -}); diff --git a/frontend/src/app/common/services/fictitiousDatas/fictitious-datas.service.ts b/frontend/src/app/common/services/fictitiousDatas/fictitious-datas.service.ts deleted file mode 100644 index e4eb760..0000000 --- a/frontend/src/app/common/services/fictitiousDatas/fictitious-datas.service.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { Injectable } from '@angular/core'; - - -@Injectable({ - providedIn: 'root' -}) -export class FictitiousDatasService -{ - - getUser() - { - const id = (Math.floor(Math.random()*100000)).toString() - return { - id: id, - nickname: "Riri"+id, - email: "riri"+id+"@gmail.com", - hash_pass: "blablabla", - is_admin: false, - } - } - - getAdmin() - { - const id = (Math.floor(Math.random()*100000)).toString() - return { - id: id, - nickname: "Fifi"+id, - email: "fifi"+id+"@gmail.com", - hash_pass: "blablabla", - is_admin: true, - } - } - - getTabPerson(n: number) - { - let tab = []; - - for(let i=0 ; i { - let service: HashageService; - - beforeEach(() => { - TestBed.configureTestingModule({}); - service = TestBed.inject(HashageService); - }); - - it('should be created', () => { - expect(service).toBeTruthy(); - }); -}); diff --git a/frontend/src/app/common/services/hashage/hashage.service.ts b/frontend/src/app/common/services/hashage/hashage.service.ts deleted file mode 100644 index f76562e..0000000 --- a/frontend/src/app/common/services/hashage/hashage.service.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { Injectable } from '@angular/core'; - -@Injectable({ - providedIn: 'root' -}) -export class HashageService -{ - // Fonction de hashage (faible) - run(input: string): string - { - let hash = 0; - for (let i = 0; i < input.length; i++) { - let ch = input.charCodeAt(i); - hash = ((hash << 5) - hash) + ch; - hash = hash & hash; - } - return hash.toString(); - } -} diff --git a/frontend/src/app/common/services/message/message.service.spec.ts b/frontend/src/app/common/services/message/message.service.spec.ts deleted file mode 100644 index 1db761b..0000000 --- a/frontend/src/app/common/services/message/message.service.spec.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { TestBed } from '@angular/core/testing'; - -import { MessageService } from './message.service'; - -describe('MessageService', () => { - let service: MessageService; - - beforeEach(() => { - TestBed.configureTestingModule({}); - service = TestBed.inject(MessageService); - }); - - it('should be created', () => { - expect(service).toBeTruthy(); - }); -}); diff --git a/frontend/src/app/common/services/message/message.service.ts b/frontend/src/app/common/services/message/message.service.ts deleted file mode 100644 index 4c4ec1c..0000000 --- a/frontend/src/app/common/services/message/message.service.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { Injectable } from '@angular/core'; -import {HttpClient, HttpParams} from "@angular/common/http"; -import {Observable} from "rxjs"; -import {environment} from "../../../../environments/environment"; - -@Injectable({ - providedIn: 'root' -}) -export class MessageService -{ - - constructor( private http: HttpClient ) { } - - post(url: string, data: any): Observable - { - const urlComplete = environment.debutUrl + url ; - return this.http.post(urlComplete, data, {withCredentials: true}); - } - - get(url: string, params:HttpParams = new HttpParams()): Observable - { - const urlComplete = environment.debutUrl + url ; - return this.http.get(urlComplete,{ withCredentials: true, params: params }); - } - - put(url: string, data: any): Observable - { - const urlComplete = environment.debutUrl + url ; - return this.http.put(urlComplete, data, {withCredentials: true}); - } - - delete(url: string, params:HttpParams = new HttpParams()): Observable - { - const urlComplete = environment.debutUrl + url ; - return this.http.delete(urlComplete,{withCredentials: true}); - } - -} diff --git a/frontend/src/app/common/services/profil/profil.service.spec.ts b/frontend/src/app/common/services/profil/profil.service.spec.ts deleted file mode 100644 index 5cee000..0000000 --- a/frontend/src/app/common/services/profil/profil.service.spec.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { TestBed } from '@angular/core/testing'; - -import { ProfilService } from './profil.service'; - -describe('ProfilService', () => { - let service: ProfilService; - - beforeEach(() => { - TestBed.configureTestingModule({}); - service = TestBed.inject(ProfilService); - }); - - it('should be created', () => { - expect(service).toBeTruthy(); - }); -}); diff --git a/frontend/src/app/common/services/profil/profil.service.ts b/frontend/src/app/common/services/profil/profil.service.ts deleted file mode 100644 index 71fac4a..0000000 --- a/frontend/src/app/common/services/profil/profil.service.ts +++ /dev/null @@ -1,42 +0,0 @@ -import { Injectable } from '@angular/core'; - -@Injectable({ - providedIn: 'root' -}) -export class ProfilService -{ - - constructor() - { - if(localStorage.getItem('id') === null) this.setId(-1); - if(localStorage.getItem('isAdmin') === null) this.setIsAdmin(false); - } - - getId(): number - { - let idString = localStorage.getItem('id'); - if(idString === null) return -1; - else return parseInt(idString); - } - - setId(id: number): void - { - localStorage.setItem('id', id.toString()); - } - - isAdmin(): boolean - { - let isAdminString = localStorage.getItem('isAdmin'); - if(isAdminString === "T") return true; - else return false; - } - - setIsAdmin(isAdmin: boolean): void - { - let isAdminString = "" ; - if(isAdmin) isAdminString = "T"; - else isAdminString = "F"; - localStorage.setItem('isAdmin', isAdminString); - } - -} diff --git a/frontend/src/app/login/page-login/page-login.component.html b/frontend/src/app/login/page-login/page-login.component.html deleted file mode 100644 index 493e7b7..0000000 --- a/frontend/src/app/login/page-login/page-login.component.html +++ /dev/null @@ -1,40 +0,0 @@ -
-
- - - - - - - -
-
- - -
-

FlaskAled

- User Icon -
- - -
- - - -
- {{errorMessage}} -
- -
- - - - -
-
- - -
-
diff --git a/frontend/src/app/login/page-login/page-login.component.scss b/frontend/src/app/login/page-login/page-login.component.scss deleted file mode 100644 index 8924202..0000000 --- a/frontend/src/app/login/page-login/page-login.component.scss +++ /dev/null @@ -1,271 +0,0 @@ -html { - background-color: #56baed; -} - -body { - font-family: "Poppins", sans-serif; - height: 100vh; -} - -a { - color: #5E89FF; - display:inline-block; - text-decoration: none; - font-weight: 400; -} - -h2 { - text-align: center; - font-size: 16px; - font-weight: 600; - text-transform: uppercase; - display:inline-block; - margin: 40px 8px 10px 8px; - color: #cccccc; -} - - - -/* STRUCTURE */ - -.wrapper { - display: flex; - align-items: center; - flex-direction: column; - justify-content: center; - width: 100%; - min-height: 80%; - padding: 20px; -} - -#formContent { - -webkit-border-radius: 10px 10px 10px 10px; - border-radius: 10px 10px 10px 10px; - background: #fff; - padding: 30px; - width: 90%; - max-width: 450px; - position: relative; - padding: 0px; - -webkit-box-shadow: 0 30px 60px 0 rgba(0,0,0,0.3); - box-shadow: 0 30px 60px 0 rgba(0,0,0,0.3); - text-align: center; -} - -#formFooter { - background-color: #f6f6f6; - border-top: 1px solid #dce8f1; - padding: 25px; - text-align: center; - -webkit-border-radius: 0 0 10px 10px; - border-radius: 0 0 10px 10px; -} - - - -/* TABS */ - -h2.inactive { - color: #cccccc; -} - -h2.active { - color: #0d0d0d; - border-bottom: 2px solid #5fbae9; -} - - - -/* FORM TYPOGRAPHY*/ - -input[type=button], input[type=submit], input[type=reset] { - background-color: #5E89FF; - border: none; - color: white; - padding: 15px 80px; - text-align: center; - text-decoration: none; - display: inline-block; - text-transform: uppercase; - font-size: 13px; - -webkit-box-shadow: 0 10px 30px 0 rgba(95,186,233,0.4); - box-shadow: 0 10px 30px 0 rgba(95,186,233,0.4); - -webkit-border-radius: 5px 5px 5px 5px; - border-radius: 5px 5px 5px 5px; - margin: 5px 20px 40px 20px; - -webkit-transition: all 0.3s ease-in-out; - -moz-transition: all 0.3s ease-in-out; - -ms-transition: all 0.3s ease-in-out; - -o-transition: all 0.3s ease-in-out; - transition: all 0.3s ease-in-out; -} - -input[type=button]:hover, input[type=submit]:hover, input[type=reset]:hover { - background-color: #39ace7; -} - -input[type=button]:active, input[type=submit]:active, input[type=reset]:active { - -moz-transform: scale(0.95); - -webkit-transform: scale(0.95); - -o-transform: scale(0.95); - -ms-transform: scale(0.95); - transform: scale(0.95); -} - -input[type=text], input[type=password] { - background-color: #f6f6f6; - border: none; - color: #0d0d0d; - padding: 15px 32px; - text-align: center; - text-decoration: none; - display: inline-block; - font-size: 16px; - margin: 5px; - width: 85%; - border: 2px solid #f6f6f6; - -webkit-transition: all 0.5s ease-in-out; - -moz-transition: all 0.5s ease-in-out; - -ms-transition: all 0.5s ease-in-out; - -o-transition: all 0.5s ease-in-out; - transition: all 0.5s ease-in-out; - -webkit-border-radius: 5px 5px 5px 5px; - border-radius: 5px 5px 5px 5px; -} - - - -input[type=text]:focus, input[type=password]:focus { - background-color: #fff; - border-bottom: 2px solid #5fbae9; -} - -input[type=text]::placeholder, input[type=password]::placeholder { - color: #cccccc; -} - -.bg{ - margin: 0; - padding: 0; - height: 100vh; - width: 100vw; - overflow-y: hidden; - overflow-x: hidden; -} - -/* ANIMATIONS */ - -/* Simple CSS3 Fade-in-down Animation */ -.fadeInDown { - -webkit-animation-name: fadeInDown; - animation-name: fadeInDown; - -webkit-animation-duration: 1s; - animation-duration: 1s; - -webkit-animation-fill-mode: both; - animation-fill-mode: both; -} - -@-webkit-keyframes fadeInDown { - 0% { - opacity: 0; - -webkit-transform: translate3d(0, -100%, 0); - transform: translate3d(0, -100%, 0); - } - 100% { - opacity: 1; - -webkit-transform: none; - transform: none; - } -} - -@keyframes fadeInDown { - 0% { - opacity: 0; - -webkit-transform: translate3d(0, -100%, 0); - transform: translate3d(0, -100%, 0); - } - 100% { - opacity: 1; - -webkit-transform: none; - transform: none; - } -} - -/* Simple CSS3 Fade-in Animation */ -@-webkit-keyframes fadeIn { from { opacity:0; } to { opacity:1; } } -@-moz-keyframes fadeIn { from { opacity:0; } to { opacity:1; } } -@keyframes fadeIn { from { opacity:0; } to { opacity:1; } } - -.fadeIn { - opacity:0; - -webkit-animation:fadeIn ease-in 1; - -moz-animation:fadeIn ease-in 1; - animation:fadeIn ease-in 1; - - -webkit-animation-fill-mode:forwards; - -moz-animation-fill-mode:forwards; - animation-fill-mode:forwards; - - -webkit-animation-duration:1s; - -moz-animation-duration:1s; - animation-duration:1s; -} - -.fadeIn.first { - -webkit-animation-delay: 0.4s; - -moz-animation-delay: 0.4s; - animation-delay: 0.4s; -} - -.fadeIn.second { - -webkit-animation-delay: 0.6s; - -moz-animation-delay: 0.6s; - animation-delay: 0.6s; -} - -.fadeIn.third { - -webkit-animation-delay: 0.8s; - -moz-animation-delay: 0.8s; - animation-delay: 0.8s; -} - -.fadeIn.fourth { - -webkit-animation-delay: 1s; - -moz-animation-delay: 1s; - animation-delay: 1s; -} - -/* Simple CSS3 Fade-in Animation */ -.underlineHover:after { - display: block; - left: 0; - bottom: -10px; - width: 0; - height: 2px; - //background-color: #5E89FF; - background-color: #5E89FF; - content: ""; - transition: width 0.2s; -} - -.underlineHover:hover { - color: #0d0d0d; -} - -.underlineHover:hover:after{ - width: 100%; -} - -h1{ - color: black; -} - -/* OTHERS */ - -*:focus { - outline: none; -} - -#icon { - width:30%; -} diff --git a/frontend/src/app/login/page-login/page-login.component.spec.ts b/frontend/src/app/login/page-login/page-login.component.spec.ts deleted file mode 100644 index 28d80c7..0000000 --- a/frontend/src/app/login/page-login/page-login.component.spec.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { ComponentFixture, TestBed } from '@angular/core/testing'; - -import { PageConnexionComponent } from './page-connexion.component'; - -describe('PageConnexionComponent', () => { - let component: PageConnexionComponent; - let fixture: ComponentFixture; - - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ PageConnexionComponent ] - }) - .compileComponents(); - }); - - beforeEach(() => { - fixture = TestBed.createComponent(PageConnexionComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); - - it('should create', () => { - expect(component).toBeTruthy(); - }); -}); diff --git a/frontend/src/app/login/page-login/page-login.component.ts b/frontend/src/app/login/page-login/page-login.component.ts deleted file mode 100644 index 54ce267..0000000 --- a/frontend/src/app/login/page-login/page-login.component.ts +++ /dev/null @@ -1,78 +0,0 @@ -import {Component} from '@angular/core'; -import {Router} from "@angular/router"; -import {MessageService} from "../../common/services/message/message.service"; -import {ProfilService} from "../../common/services/profil/profil.service"; - - - -@Component({ - selector: 'app-page-nickname', - templateUrl: './page-login.component.html', - styleUrls: ['./page-login.component.scss'] -}) -export class PageLoginComponent -{ - email: string = "" ; - password: string = "" ; - hasError: boolean = false; - errorMessage: string = ""; - - - constructor( private messageService: MessageService, - private router: Router, - private profilService: ProfilService ) { } - - - // Appuie sur le bouton "seConnecter" - onSeConnecter(): void - { - this.checkField(); - if(!this.hasError) - { - const data = { - email: this.email, - password: this.password - }; - this.messageService - .post('login', data) - .subscribe( retour => this.onSeConnecterCallback(retour), err => this.onSeConnecterCallback(err)); - } - } - - - // Callback de "onSeConnecter" - onSeConnecterCallback(retour: any): void - { - if(retour.status !== "success") - { - console.log(retour); - this.errorMessage = retour.error.message; - this.hasError = true; - } - else { - this.profilService.setId(retour.data.id); - this.profilService.setIsAdmin(retour.data.is_admin) - if(retour.data.is_admin) this.router.navigateByUrl('admin/userList'); - else this.router.navigateByUrl('user/registry'); - } - } - - - // Check les champs saisis par l'utilisateur - checkField(): void - { - if(this.email === "") { - this.errorMessage = "Veuillez remplir le champ email" ; - this.hasError = true; - } - else if(this.password === "") { - this.errorMessage = "Veuillez remplir le champ mot de passe" ; - this.hasError = true; - } - else { - this.errorMessage = "" ; - this.hasError = false; - } - } - -} diff --git a/frontend/src/app/register/page-register/page-register.component.html b/frontend/src/app/register/page-register/page-register.component.html deleted file mode 100644 index afa10a8..0000000 --- a/frontend/src/app/register/page-register/page-register.component.html +++ /dev/null @@ -1,49 +0,0 @@ -
- - - - - - - -
- - - - Pseudo - -
- - - - Email - -
- - - - Mot de passe - -
- - - - Confirmation mot de passe - -
- - -
- {{errorMessage}} -
- - - - -
- - - -
diff --git a/frontend/src/app/register/page-register/page-register.component.scss b/frontend/src/app/register/page-register/page-register.component.scss deleted file mode 100644 index 293c5a1..0000000 --- a/frontend/src/app/register/page-register/page-register.component.scss +++ /dev/null @@ -1,21 +0,0 @@ -.contenuContainer { - padding: 20px 20px 20px 20px; - width: 30%; - margin: auto auto; - margin-top: 50px; - border: solid 1px black; - text-align: center; -} - -.boite { - margin-left: auto; - margin-right: auto; - width: 50%; - margin-top: 10vh; - border: solid 3px; - border-radius: 10px; - padding: 20px 40px 20px 40px; - background-color: #ffffff; - text-align: center; - box-shadow: 10px 5px 5px black; -} diff --git a/frontend/src/app/register/page-register/page-register.component.spec.ts b/frontend/src/app/register/page-register/page-register.component.spec.ts deleted file mode 100644 index 847bd4f..0000000 --- a/frontend/src/app/register/page-register/page-register.component.spec.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { ComponentFixture, TestBed } from '@angular/core/testing'; - -import { PageRegisterComponent } from './page-register.component'; - -describe('PageInscriptionComponent', () => { - let component: PageRegisterComponent; - let fixture: ComponentFixture; - - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ PageRegisterComponent ] - }) - .compileComponents(); - }); - - beforeEach(() => { - fixture = TestBed.createComponent(PageRegisterComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); - - it('should create', () => { - expect(component).toBeTruthy(); - }); -}); diff --git a/frontend/src/app/register/page-register/page-register.component.ts b/frontend/src/app/register/page-register/page-register.component.ts deleted file mode 100644 index ebd1e62..0000000 --- a/frontend/src/app/register/page-register/page-register.component.ts +++ /dev/null @@ -1,98 +0,0 @@ -import { Component } from '@angular/core'; -import {HashageService} from "../../common/services/hashage/hashage.service"; -import {Router} from "@angular/router"; -import {CheckEmailService} from "../../common/services/checkEmail/check-email.service"; -import {MatDialog} from "@angular/material/dialog"; -import {PopupConfirmRegisterComponent} from "../popup-confirm-register/popup-confirm-register.component"; -import {MessageService} from "../../common/services/message/message.service"; - - - -@Component({ - selector: 'app-page-register', - templateUrl: './page-register.component.html', - styleUrls: ['./page-register.component.scss'] -}) -export class PageRegisterComponent -{ - email: string = ""; - nickname: string = ""; - password: string = ""; - confirmPassword: string = ""; - hasError: boolean = false; - errorMessage: string = ""; - - - constructor( private checkEmailService: CheckEmailService, - private messageService: MessageService, - private router: Router, - public dialog: MatDialog ) { } - - - // Envoie de l'utilisateur au backend - onValider(): void - { - this.checkField(); - if(!this.hasError) - { - const data = { - email: this.email, - nickname: this.nickname, - password: this.password, - is_admin: false - }; - this.messageService - .post('register', data) - .subscribe( retour => this.onValiderCallback(retour), err => this.onValiderCallback(err)); - } - } - - - // Callback de "onValider" - onValiderCallback(retour: any): void - { - if(retour.status !== "success") - { - console.log(retour); - this.errorMessage = retour.error.message; - this.hasError = true; - } - else { - this.dialog - .open(PopupConfirmRegisterComponent, {}) - .afterClosed() - .subscribe(retour => this.router.navigateByUrl("/login")); - } - } - - - // Check les champs saisis par l'utilisateur - checkField(): void - { - if(this.nickname.length === 0) { - this.errorMessage = "Veuillez remplir le champ 'pseudo'."; - this.hasError = true; - } - else if(this.email.length === 0) { - this.errorMessage = "Veuillez remplir le champ 'email'."; - this.hasError = true; - } - else if(!this.checkEmailService.isValidEmail(this.email)) { - this.errorMessage = "Email invalide."; - this.hasError = true; - } - else if(this.password.length === 0) { - this.errorMessage = "Veuillez remplir le champ 'mot de passe'."; - this.hasError = true; - } - else if(this.password !== this.confirmPassword) { - this.errorMessage = "Le mot de passe est différent de sa confirmation."; - this.hasError = true; - } - else { - this.errorMessage = "" ; - this.hasError = false; - } - } - -} diff --git a/frontend/src/app/register/popup-confirm-register/popup-confirm-register.component.html b/frontend/src/app/register/popup-confirm-register/popup-confirm-register.component.html deleted file mode 100644 index 6ecf288..0000000 --- a/frontend/src/app/register/popup-confirm-register/popup-confirm-register.component.html +++ /dev/null @@ -1,2 +0,0 @@ -

Votre inscription a bien été pris en compte

- diff --git a/frontend/src/app/register/popup-confirm-register/popup-confirm-register.component.scss b/frontend/src/app/register/popup-confirm-register/popup-confirm-register.component.scss deleted file mode 100644 index e69de29..0000000 diff --git a/frontend/src/app/register/popup-confirm-register/popup-confirm-register.component.spec.ts b/frontend/src/app/register/popup-confirm-register/popup-confirm-register.component.spec.ts deleted file mode 100644 index 37dd0bc..0000000 --- a/frontend/src/app/register/popup-confirm-register/popup-confirm-register.component.spec.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { ComponentFixture, TestBed } from '@angular/core/testing'; - -import { PopupConfirmRegisterComponent } from './popup-confirm-register.component'; - -describe('PopupConfirmRegisterComponent', () => { - let component: PopupConfirmRegisterComponent; - let fixture: ComponentFixture; - - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ PopupConfirmRegisterComponent ] - }) - .compileComponents(); - }); - - beforeEach(() => { - fixture = TestBed.createComponent(PopupConfirmRegisterComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); - - it('should create', () => { - expect(component).toBeTruthy(); - }); -}); diff --git a/frontend/src/app/register/popup-confirm-register/popup-confirm-register.component.ts b/frontend/src/app/register/popup-confirm-register/popup-confirm-register.component.ts deleted file mode 100644 index f40b648..0000000 --- a/frontend/src/app/register/popup-confirm-register/popup-confirm-register.component.ts +++ /dev/null @@ -1,13 +0,0 @@ -import {Component} from '@angular/core'; - - - -@Component({ - selector: 'app-popup-confirm-register', - templateUrl: './popup-confirm-register.component.html', - styleUrls: ['./popup-confirm-register.component.scss'] -}) -export class PopupConfirmRegisterComponent -{ - -} diff --git a/frontend/src/app/user/myProfil/commentary.txt b/frontend/src/app/user/myProfil/commentary.txt deleted file mode 100644 index 902847e..0000000 --- a/frontend/src/app/user/myProfil/commentary.txt +++ /dev/null @@ -1,7 +0,0 @@ -La page "admin/myProfil" contient: - - les informations de l'utilisateur (composant "page-profil") - - un bouton "modifier profil" pour modifier les informations de l'utilisateur (composant "popup-update-profil") - -Cette page est la même que la page de la partie admin. - -Ainsi, on a rangé cette page dans le dossier "common/components/profil". diff --git a/frontend/src/app/user/page-registry/page-registry.component.html b/frontend/src/app/user/page-registry/page-registry.component.html deleted file mode 100644 index 6c7f471..0000000 --- a/frontend/src/app/user/page-registry/page-registry.component.html +++ /dev/null @@ -1,45 +0,0 @@ -
- -

- - -
- - Filter - - -
- - - - - - - - - - - - - - - - - - - - - - - - -
Pseudo{{person.nickname}}Email{{person.email}}Rôle{{person.role}}
- - - - -
-

diff --git a/frontend/src/app/user/page-registry/page-registry.component.scss b/frontend/src/app/user/page-registry/page-registry.component.scss deleted file mode 100644 index 7440dcb..0000000 --- a/frontend/src/app/user/page-registry/page-registry.component.scss +++ /dev/null @@ -1,9 +0,0 @@ -mat-paginator, table { - width: 80%; - margin: auto 10%; -} - -.filtre { - text-align: center; - width: 33%; -} diff --git a/frontend/src/app/user/page-registry/page-registry.component.spec.ts b/frontend/src/app/user/page-registry/page-registry.component.spec.ts deleted file mode 100644 index 1851010..0000000 --- a/frontend/src/app/user/page-registry/page-registry.component.spec.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { ComponentFixture, TestBed } from '@angular/core/testing'; - -import { PageRegistryComponent } from './page-registry.component'; - -describe('RegistryComponent', () => { - let component: PageRegistryComponent; - let fixture: ComponentFixture; - - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ PageRegistryComponent ] - }) - .compileComponents(); - }); - - beforeEach(() => { - fixture = TestBed.createComponent(PageRegistryComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); - - it('should create', () => { - expect(component).toBeTruthy(); - }); -}); diff --git a/frontend/src/app/user/page-registry/page-registry.component.ts b/frontend/src/app/user/page-registry/page-registry.component.ts deleted file mode 100644 index 6fca3ed..0000000 --- a/frontend/src/app/user/page-registry/page-registry.component.ts +++ /dev/null @@ -1,57 +0,0 @@ -import {AfterViewInit, Component, ViewChild} from '@angular/core'; -import {MatTableDataSource} from "@angular/material/table"; -import {MatSort} from "@angular/material/sort"; -import {MatPaginator} from "@angular/material/paginator"; -import {MessageService} from "../../common/services/message/message.service"; - - - -@Component({ - selector: 'app-page-registry', - templateUrl: './page-registry.component.html', - styleUrls: ['./page-registry.component.scss'] -}) -export class PageRegistryComponent implements AfterViewInit -{ - displayedColumns: string[] = [ "nickname", "email", "role" ]; - dataSource: MatTableDataSource = new MatTableDataSource(); - @ViewChild(MatSort) sort: MatSort; - @ViewChild(MatPaginator) paginator: MatPaginator; - - - constructor( private messageService: MessageService ) { } - - - ngAfterViewInit(): void - { - this.messageService - .get('users?order_by=nickname') - .subscribe(retour => this.ngAfterViewInitCallback(retour), err => this.ngAfterViewInitCallback(err)); - } - - - ngAfterViewInitCallback(retour: any): void - { - if(retour.status !== "success") { - console.log(retour); - } - else { - let tabPerson: { id: number, email: string, nickname: string, is_admin: boolean }[] = retour.data; - tabPerson = tabPerson.map( person => { - if(!person.is_admin) return Object.assign(person, {role: "utilisateur"}); - else return Object.assign(person, {role: "admin"}); - }); - this.dataSource = new MatTableDataSource(tabPerson); - this.dataSource.sort = this.sort; - this.dataSource.paginator = this.paginator; - } - } - - - applyFilter(event: Event): void - { - const filterValue = (event.target as HTMLInputElement).value; - this.dataSource.filter = filterValue.trim().toLowerCase(); - } - -} diff --git a/frontend/src/assets/.gitkeep b/frontend/src/assets/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/frontend/src/assets/logo.png b/frontend/src/assets/logo.png deleted file mode 100644 index a2290038008f64276a53445781a399dc4a45a6ca..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 201990 zcmd?R1yo$!wy24OK#%~zAxLm{*ANKq9$Z6kcc~EE-7UC7u;A|QE`__hRn@Ef=iGDt z`(BS8?{$yvzTLgYShe?@%h$HG=KOYrDk(^!Arm6Qz`&qMONpz%z`zy4z`))hy@qPe z=gz?}FsL>bVq!|tVq#=Uj&@%ytj%Cxq(T!l5w%o@aIb!8|NbHz^8;Zpa6Ctb0^cEIp;cF6 zzec*0K^RxwB1X>&OybIAVEoc70lI|$ipV%SAyXdUTbWOQy=u;A5v8=07LtkHd;z!Ij>)k zfM_25K`Hf zVj`*L3q6Rh(z&y$djZ}OB0;-R{J<7zY@|ZpiycxCCQiqOVfFEZaYQykWhsIl zx5nhPP5#xZ&o3GnG)TRhT{6Dqv^s=IKWkVRV$k-&ZQh0PveCD8D5YTMl%u}=7=kC#um?^;v^KjWuvxGLqN1HISkrx?=8Nu7@; z9~flRD*9BBH}}-8wwL0%8!62)+#Q&C*cAxS+p)#rxshN|$$}|RoSk2rL<7*7 zcf;UGiN3{vp-KE||M{ph0$(3Xlc%VPx_E@kO8|3`ff7y-@cUHWN^GY-tbxc&&n3gR7 zUlf&Md0WCA<}6sU#|q=UEicwR!RU6n&?a3@=0%8o=A>w&kf<6t=)>^TPx!0g63f_I zA0~UE!NX9*ZEy@R`}R{KrhT{2Pf}bGBq6U)OgcCXx%3gFjgX`+H$^csN!Jf~J4QQX zHEYofT<v87C^#(&o<%ls%NZk3EVb_pO3t|38q#?>8tgAohC+z#zG@S(Yn7XeQy7U^o_`75$;n)3y zUx`W~q2*8ng%B7=@{-#kVZHhIDfSyBth5+=?0fNu!Pvt=-Te1oqRKyWQ*aFm=fC0e z%aB}-T^SV1NAd9Y{=}9Lc9ct9jK=@YESHfJS^m>N4&MP~9e!povjoGGr8Ay(bk;|f z+=Z#PH&n~vuyVvR1EXv-5uw%9T8zXa{rQV><)~$yrPci91j74eT8Q(JKE0v5#O50c z_K1=jL%itO0TaD=n^u>^?n1uE9bqE9UKdrb2)j}?q%NrJkxY>I0)_%qJ|P$pZIW$r z3d&{%xQUZ1XMdBu2{LDkOp(oy&=uEJTon^ku%;2FzKfHh6pN!6%Ep%6ibIwz$mhz} z%Qwkq$XA#~q*(E^jysXH}NVl(wT;-{e%5umMLHrKnya&8gEo?^uq`xcn+^c^%qbCSr(Ot$n9P|W5 z_(FUAdzgEU*JFD&dp@|oaffiJaJ?AMbW|8qla`Vgm~zhsFe}C0R zsnFEPuJ^Swv5L3k02X%bHC6aA4g6mGJ%5))JjOg}8>d&l#^seOG$TCW+Xga2ob8$s zJy6=UAHsCGam41Ubh9QE#oy%kB$(^jD^F93HBvHIGJlv;+wN576zb%ET^6fBF(b)L z(x0XnvtiY7o)Uejcntts|gPK14NM%qyW<& zd#}y{;8O!eXGb$rvzw|{Ep6>^X{_`#(4)t6#=M5mx2ksB-n<};AWYPNYLm@HCN3ww z#LiHmVrw9^e72s_o;qF)S&eKuzc#-9y??u3w0BOY#4yPC?cH(6b#D=MnnDJ9wcZvj zU81wxRc4)~N;IcTvwYBC{}3UH%ci7H*{T9K{>4c7qq6!`@DN=*y4+M2dDb-loY7Ht z$wXLB7$7xBaa-Oh)mGSN{3e(~i-UVY{Oi{->r^v7tM&5nrOjHm(VWqt^lP0^*`cer zj=jQhn=Es7ySvr_kwA!=PN_0IQyU-94&0CM05|pHciih=2+HfKOJ$syo(}!BcL$nzA$^jx!#nITamcn zdOE!5;^8)U*3VzmJmz(CpKy-gwd-YYGP3Gs0+ebbZA4G&&WWAUxZXd>f4J% z7bmAu<`>tomu9C=7Q8QFu5(U<$Ivy2rvz$tXm<}<^FRY((YGYY@6Ux}owgiC0+L#2 z1~OV*>A`9%hs87d;{lm`9!V~Di+m8L;ECrfyXMZ;N&Bf|W1lkf<1U~eKwxoiP6IIX ztg>yEJu-Hhw;ZkirqyxFa&V4gfp>vfKe}n%m*TO%BAtLo!1mHks3Q~be4Cjo;NxZv zq*!HWsdDMq^1Jju0-geZGn;b`J4S;&^OB*_XTp0zzK`N}J5KwpMRi3u6Qfykf^J^E zjSS_-SK-wx{01`mcP`1`9MC|srfZcih~r>lK8sB#v#Ox#8OZ2q_2Bw!Kmw@0>Aw|r z*Sx4a_gO;hK^G8a7s&!8JRN=k?o8xQBpRG_Z~`KqJgYi>b{KRgIwA@qu<}lxSi`Ja zBYsbM4MTiqlTbaZZ~qa)48s4t6VN^E>+rD^rq~~Nez|sWyhjb=)zE#1a%I)6&lUCh zV;uU&wYA_N8PlaRTN!5h6ICSir)OYyR%9LAcNW>_=jYPr=MHPXuI}~AMy(}(`T!)a zAo(1F8swVJ4oow^lU|g_x*s_l`o%WLfa^Hsq}hXb6}tWiGt-j(DlZR14?RYLc?C-d zg8)5(g$7|*qJJGrz|z9N|D}h6feE&NdG*gU3ef$ZEe0C?tZkk6-G#{iO2H33 z{-b6gC;Kajvy~9Jmb?;~n4O~;88jsuVmqF zX8lFn!Uj5K&^m;R%+3Z{rL*wA zPuD*)|2^`b83kGX^!#rl@sDBtOA8%mVPrv;f1NX7WC7nm59n!pZy~Oz2Hit1vcI+` z=r1ia{MkRjz(&=zhxbaszhdpUCk0%*&VNOAF=J_s>x9Q`Sw<**=VR#Vy zUIjao{0xUqS+m)T&c?b|!uq6P4N#rUZ7fppsX4cpszjD!$3BDiz5nHFeE0JA5< zZztCoqwyX!>z-b$F;Z{8Gj3FvaMT{DeVsonAB|^PyVhKDd<*HBBLCHg=D+X2^38Af zq8Rt0^{GOqbEvoLns#GnXp=w+Ccrzt#v^tCPA@y{T{K(80>duebMlk<3TnEx1)u;z z2VxhT#)~^GK45POIt1DnlSvS)6 zs%l_#AUN}7w@VvCkMhE96M+vI*;#4Zprk8XyyFdDDM}6^$(wO=l%H<8k8Z+Fk=iN) z0n@FWABLUiL?T%6o*^wqz}v3lN{C}e%c{u6Z`+k4S8L$j+Y^zE@eICgg>1fKej4Xy z0@b3X%kSoj*$zeH8LpYz0=g5e!V5fhSvtSHQ+0lumZS@KMOhIb&o`} ztt=n~5C%|(>l-kY#yWtVT74Z-{B~;=8?x^T>X6L#9)1S!8+*C~lQsx*lS3sh2m^n+ zD-|0(CY3PLVjoN`Go~gehTGi+<)!5mFp<2Q|0VOdPJ8K1x||L8h}L7$?CH{}CkPnQ zYjy6jS*n?{S(6!X&KB@_suOTJD?d(~-2FP9vdPacuvwnvTBMNWyglI7?9q0ud)}(w zVBF{UqS4&6=A`GPlWt{4x-Aj8rBgI3QvJ~a5b2|1uY9(DCz+S>&B7@4K-npR~E6zO4-l*4hRCMI&Fhv_lv-H~Y`~I8d|C z6JrLyI+?T@CtbP^->)t2Ntj?eU+kgraJtVB^LdV*F8&@nU99fO6m*%+WnAqf*Zxj0vBUtaxAq&}tYjzOty4UD20 z&EPakdCV`>84jk(_dpbwV*Qz(vRIprl$tQ$V+tu-sBCWYx^MP*XoGAb+O8cRuddj& zoo2n9#GlnF`t}RmT=duuP50RzPMg`vc?rnHTT;op988Kf81+b=7LJ58L(tu zbUg0^U4YNw=S_TTYn4_n?mTZPiUh+z+sA5=A6$nN?v+8|@(YANR{@8Rk>`no;uo+Km$?f|HW3k<;J50~#I-gizRwk)yFG3K{H|n9eZvQi4RZ z%NphkBVGqa8=2mbcZvD1SS`y}W z+Ag-jqda^;Rt7GBA2%qtjLvKJ3g(8kN2eqOVD&TsG`Hyaj%I%4EWoZq^1cCE2mxK> zDfwJ}IhgX!#^j6VJ3(VUefs^sH!glddHCLy796eix`cxFmRWa~sk=|HoFe$n_)@i; zvFj_cbM?D-Dov?rr8=|-$a!Z~6nUxGXdFKayzz-OSneQ;Pi|+ceD^0#9S##h&qNJG zPO>bzt=}K>G*|B-S1had?U3ZH6i3*ZgW)3gQy;ta*3icS|CD&o9?(Uwh%+Pt2nIc` zVOcFS*DIF0l+BmBGH8~6_iz4Loi%T-QqO$b;o#hh&qy%L3a`Bk_{Z}N-~sVDd9GUa zD73vjbBElF2Ajx`)?TW%`w(DMxrxo7Y0ATIV2fWyosFJUanu@C zyesAcwpl@Hk>GDfIVKtnKu4NqgRyx?mpdB)zniNdLkp`j2B1=%R`+VgfMy3146d@i zNK4{V?almYWg8o-#0xbsEy}*8Qjy0)#Z^V$D^<6RPT2cNfAnT9bioahezotC7dp+} z9`R{!W|E)Wfb$|vmsc+%*P1A+<{-Ng$ghtU5bfvmM!PXkbQVI{PFtAz<3j@axzb+B zYfwU2gM+0GotU&<-uaBDUl>lmH%HJ1)Y4`?2Bl%O;$h4`I*ndGP8I)B+i~OscAQej z0R5lFfjACik+VNb(`(@h;cBdbM4owvT@(_57{QplBhg?ULeRXK}d-PPt zC0r+*WM1)6g5|54Xse7s!S$}gX@Tma`;ypFSjXKIeR{@ zHTw2c=-fAZ;e;2B8@hnIKZl#vB`O^53qw5aFT~Kd;-<5$BNuqy(dc>gVk>`(*R-#i z)~!}n*`?$+4x=qku#o<{T!*0X|KfPq%_8r14Ny}4$6mI?Y4yYyM1%Iu+w_(&p@r5o z^`9{oMA5W3lqwR+9szVPe0}3#t{cy$Hj{y@}g*Kg!lFJyzIqR)_lx5HNCrigc8^z29zq>26n!1JV4z_Ji z&9m&SG^%1-wFE#$$2MD~YB`pVy|F56Kd+EH5}pi>M2@;`<{@eT@6(d3de_9KfkK=L zqtSf9PbAR!?OkxQ(z1ay^3jcj?B%IAU0{}ukYov2Y?x(RhzY$FW+RowNU@IAOFryf zopCMw(FuAS8z)Y%?pk=8qg+=16S-EM=7&ZOg zT-gHUhOee(vQFFANH3TUNs_MjGm<2IQA!L-OLgmXjJFfoWHzfx%RtaHc=%com-e=! z6%Y>Dg#2n*16LtJZ=?6aA#?_1lBTjMWS7K5v9r@@hNT2}6F<5>CtNB84i3i3y$=o9 z8Rkl`OuA}Yn|nK@X8H5)TFWNnyi$5`i73-8DRD~8${e-$U460lGixpPhILNSEA2il zEB%I#E3S>z#3p(JiwsiD~U-rp#M~XU1T-2sH&9s}hnzx^ z9hxYPVL_?1WS2gov=oDYFD{eLC&Dhk9c}q$+jAN(z(8SW8R)k2eXE zVGnv|29ka@(ZD(Vj* zU|3RN%{ViA=9tCWPj$qc4L*j>4DP07&vugm`_xXD*uD)Hso;alytCd*teUGV?$BV* z#BL@cEIZ6wD7QmAGaE8Z8@y?;C-+^<+jitHRSs^?go4B)1vz~Z{k_4FfdwGP zWhrQCvR49|&?XOWDkR|!5k<=?0lY8L4ms>f$`>TW6)_7c`cXWW*;+VPHKU@hu5*yq zn`GuNMkC5X{H3VrcYc|)^%q=4KDxaEisRx+je~q9E%LlvvoC`5;=Qtx^P$5zqEt3r z?+9?1Mz)kckn8i;D5!z`6BP%X-QBf(SI@zbJnQy$ZI4L;eu=l{3fbM>GuLP2u8v#i zGLCvGLmm{KYJzHKcQOnhPGfgKP5S;Jg>O`tXVpAPtaPfCFS7a@oP- z@X2NKM^iwE1f`yz;n)Lqsa%d?nrc?jI}wNZZ{nQf+^`p4y-Q2}sf|++7MmhMfnEXg zhMnn`C57yP!WIf1Su(;UAUmVmch>@5dl>@G2Qa?DYgSclQNS|Wh009!wBgK5+skyz zp4(rX6Sunp4emoK_Xd!?j*WYfCW6|pjq}R7L(w>@Y!#OD*1kM+@|E$bY3N24fb5$` z8X_G5`pP7YgGauC=72tMAJ|P3qIm?kp3kt3Ki*NZfDFL_7QrkCi`gAp^N?!*#Na{g z(FMSC`Q|gFo(aMT*Ujr6D%7tqsWlES+=l5@ZC&BvL1$OH;kFprSBRTG*Lz!Mf_mJGMv|DEL>{`(SAn24 zU{i@|k;Gi)utYjJalsQ~M#dm$fcRJy3o5~id znle`!nrsAIo7V)~8i@tmnlf8lW${a7AMyda!-*-}lC5sd&X4T(4Ukj2%@nZBUWx`Y zANAZ-VoqJ~T{&Su>8{6NCDzw^go$`@hr|k~@_jsvGSh@?0rmf0{r~QQAWLEzYZ;S! z7G+qOb%9Xbe#)y5OAmc|E+Y+{3qfgY%_SMHZxd{9Fy^jW)hxTqe{Xoi(N@+Z-c4qi zyd#5FUoso;#ir|;Qd!rG;WS5Rfbyf-$hAtzo7&|c`_lhuObS%~pKEB=1g0v9ur9W{ zDbUgG_ULa*Okn^gwHa9VXEQc_#dB?EarJOp@EKZI7wnW?vXSh{5DdiT7>`z;!L z80kf{i}@zAC`Ue)VELypL4mhNpiaE_HqNu;J@s-h!)@@|(Fx{?Jc5N%bp+4= zax5u#`O>^!^(nLggV~a!l2K=C3;3Z`-%H*R6!f9E$YU=S{8833jP54w?u1H%Up1UgE%H@7+MKU44|%B#{twSIbCNXhj2c)zD(fvUj<1MDF{9J9 zplG$Ms%JafDKslKYIsN+t(!E}>+0d3!T{$$Cq zs@=x>=^SW~<3kRpTj6M~#=KFevJau(|L6M_q)n=zGrdN5{Z1g|G=3SLZU`mjA^mui!>JbEc|pZ?KF z<&*PMr6YqI{M;uM5?(PZA>DBqOsonynOz$bDcc8n{Tp8mP<=6 zJ$Ag6Q8`G7#;JtF(Z^-h9HZj<)$bdbm0jKkM|EUY#QQ){u=0|fq4Mm; zM$GeVmG7zV4GZKX%j?VoKP)l%wS{1zV)hw{?+)huVqSE!nQU@XpKNlYM_Zfi&B2uI zY_al{Y_?oe3^HIN=lvcvCfsDy0bUC(iwPf7ND+Tn$Gmc7ef?N{Lw$?J&H_6!fGLQd zbia|6bZCye^Ar;Yt~N>I>vulZz;7fYDz1x+&96c*oJQ{ufBh( z?!Z@LS}@!2y(w$b5-jj??0QVSv^Y}{w4Jghymo8SbTf*20ry%L>en4%_2%(af9N=A;nmYVCmIe(O zht!IxaESF|k+wFU_1DX$2uqc!X1Xb5QxdW8r2QA6cX0>H5nzw8XaS8L>FCoTq-=~@ zd$2B{kbf7nuqs1tfk7nk$EKeHIqXZyXJ--yKGN0ksTu^R7MRRfV{?PS)L}HsL{4)BQAkPGeoX2++lah5_O2i8`k50wq%~=0=ek{bcY-|t?QTy#q;oB zZ0AIga4km?@yypp6K^;3x9BePGV@qWoAQ|SbMpA~qb{&jib*KyNH#Q!^5*m`x`gTE z>5FlGx6-U?I$o$6i5BFG0X2?0*e>r_*h|o~;4o-3s+VaRVY_A#aeOT&68IWH#Fa+M z+1+(~2U%}eYL z%o!YO*%XszbwbnMA+S-h!vfB1^WL2K{Ym;f=ZIQjVWH6D4ui#ep z9n_$%xjWN=k6v`gc545AAZ#3JMXr_sAmfU;G*#Q{3S6{Ay%31p(!Za!lJYuTR^MF1 z@4fNM5k-}&1~)W1Kvz=>`JuK~y`i>qrRuh0M~JJrpTk$7CaKkvFSWV?5=QBf#)tI@ z`{=R(dz)p=8V`mas1UByjsS;%k>{dTz!c_B;N+Po|7##0HU!=^lw^Rk3v#62C^LMY zeRY{D*qR-lJsm5;DMr9)0sK(tLC3kY!ze~DTMQ&9g$hmoYXZ0D<<{o`^@r!XGZ#DK zvgw6|wli+)2c!y2f^EpoQ2bg3pVLK?Z|1oi)8gs{zoKKJX0=PgX>+$~HxzZ-p??}iL4>K1i*^G7h00FO1hwkvn1wkyAF&R$JV zO7DD&&kB7)kjvW~bu~&9&iGP3D-u1mSi3*b1eV2HgOQLU5O8r%8UMC>@#RfzOVPmX z)u3Cfx)nuBsE(mDK#Dvu|bW{4dJLzx1JIR0?#! zW%3505<&~KvPA=Vvk0uI5OFJNg^Iww46rE|d`l43yT5vOSiqbzQe(qNz{TBO!2S+R05m%bXBEQerl31CM!yNrC z@c3>YFEpM;v3aIQ@sF#dC0h8?`x&(3wJ!hQ)oK&TE|G0K79-dh$_Q^LR63+QlP4L~ zNFf>3?6g0T2S<+evY$&?*-IK8J6!->FMkflYvHq(p)p=R6!%UN@wzL2i88Kpfvo%3 zPOPu7JJQ$7d(l*Q!j5OIL_QV>*;2iqDZ)%TDl^D2;pelos8E;k+d|HBgg545tPF#C zx{hyw_gUWSyN@(F2~X!tN`I{O*(8uMuMco1+ks4*xr+wG$PRKoKr?|~-z7D~>&yV; z_^R-JBJ=?1Z}6Bh*txjku+ilq-nowIe1)%7hC4(~CJ+>Lxb6B54!$-JP~@*%tOQI= zqu|fA1}UEMu(BkCM@pDnz7v^nQ^1erE6hA2-@#+UOT7NvX0QyGi5uWznfO^2@Kgk} z2X@+le>|pO@%PtnVu@tx@^`klojV+_YwgdswU6sHdk<-HmyE3Ml?MwxAb#O_KXaC4 z8+5!Q)Ij0KxY%Aw`YcJx0j_^Us9FQvge->LdWJ~9OD(5eX!6Ub-1LqP$=ZhlUq zhat_MvboYF;_Uo|UXx&OVxS3OeTi1T>`58&ki{iM)9uQb0K+yIfjk>XL>`?x097ju z=A^iEYadUq0Zi=F77Tkn>`Ao5v$(va{xMFUh4w>g!0Vs<@(w$V6Tv$}s%zPxrG_=P z_G{t=fhu%1X=QSH+6EpWuf6h>aCUvKU9M3hpE12=XTGZ4K}OV0nMWU}Vd4h@%IeWv z*;;b@4b@AQBUUvly%on_78Fk`OO->23`BDQB7HlVT-135W&#haZ3Cd5nAUhMU2I9Y z+K~n!g9B8i;<7X8tojJd#ZpPldKDj;$C7<{+z2iIw%mY_WpyJA`V!WoHG#W*@9|@# z8E4QFneYs0SJAW2!>Nmx>$z)-+o@}Cmw*>x_R2)23lHYJH2Uk`MLl$|*PGtc4yO9T zFRE!2rP)^lA6_4pCNiwCkAAMtUgIme8BTztsagYz;*$;^BZa|s43naWm z2{{w~y};MnXm^=H{vQ`PyGvQ=O;t)TwKV8D79sJoBK+wfczmihcY^Tb-_1Ph?y4HV zY+jG<%B zg=0`4#wYni21!TSiSB&z9{9kfSU<2GEpj$5T#efzD-@AZII?zy!=Ojgt$qo$oz6lO zRUjq^wVAZXn7%4)d7n1skQmEmJN`@)uc2rt%1p#7n;3O`9QFceYv)1p;9ppDPxP&k zF1@n?h4YkknFUPDu48?E1#(r9wIFaMzdVGnBFV@i9O{9GvK>@M|wwV3QLA13*$uryu$+)5~`a#*dB-o@4N~r^^FSZ)kQWGDJG1A*=+!nxnx1 zBJ5;G6P?bnWSw3BBFLkxyAiQa`*qVXt);}bDC{5=9~b}A6hYd3#e?8cbSdwS@ynLl za(2B;uk16!siNdApE3RU;Mrpt>x&b^t3`AQwCNZnyE=q^`q}qGai-!XX|LG`_I4R) z;}frlA{PSwA`P&hE`OD0r`0QJ;Z$I^?qrW-w4w06Z$#Xgb5+|DzpImHUuN&o!^NG{ zxsJ(O4HjQ+3?rEK>5{-7?53*~(gV^a{FgGA!eK1$$CdlK>1-wWz2nnTl1n}4InA)< zygi#+^z01K;Z9iGtg>Gso=2DKZI|mTYSOXYa^ny*?NxT$g5tT2(=+wit`oedv42SU znl@vv6-)rv)m;?{jOqo~$(Zjakl$`6fJHPAG@yLJz(Vdz##~9n;H?xFl#=KJPhoSa zRf|;E>qu%8vFEaR`12Biq75L;e8$6m!%f$kS0?_cCiI#FXZ@?640Y%d1=qy!9dlIL zd4BD6F!MqnF*7WzNM@$;DGP zHkHIv@Hd8cIRcjpk&c9KX%n9S=W_tz{Xe`6%PFwo$0R;sv&fY!#Levn@CQ~HW=TZ- zHBsn;6rSBpI);YMEqM1De9B&PL+Rd&SDZY|r+Q;4$YVqk7~S=ms1J8;)4 zL{8pv6+Qdh^EBd(DT@p?pXPLa7sA4~tWk#+yd$98q^s)^!Az%>4eO|&+9f~y(s&H& zQWU=@O+(n(o)ouc!j*W1On#h4#rO)vrpUv^YLi;o2i~oFGe|Uap;7Q6<0jVg3wdy} zf?|JEi5_zEyTdt6LxU$K72IxWaW~80yP+7C6R)L7MUDk_@L-~fCaYa^i zJdr60DBz&(%c&ui_faB_OdOe>M^)7Yr2xZdHgcR`EdN^yEYoh!K_7VT$!)V6A;52W z`|e}~W#Go;P_Gll`XK{lvsS=J`!QcMTY&4z|Jf(+g=VT+MZUtTD6KplPCe zs1tGcluX3aE~at9LHNyf5^u z2Ra{fNa}~gEWa0`Hz$zF8CZRUXa+7fBA;VDXLk+mNZ7K_>qOYvllordtkioYSHHH| zKTeDAEfrsqDH|YsKr=r0lGT^m=g6r0MELvNt{qI*3!nBdDg3cPv$wK@l1BxNVy0u! zL(l301H7imVOmSSidhVRKX1nTL3z<(5nSgl5)gBAbmaKQ8Su7zIeU^1Rz&VYXBAcl z6sJ1aL>%NaVS^KJg)SX07pE*EOhOp+y#%3_uqRSAq!O$`Ze;Bz;H*OFZ`f0>L_*jv z_tFp@9lK#r@;>Ce7!qMJ>>2n^uA=+%T;1=#xC2wO(YJpfgW@hT zChzWjyW{x^TN+$pVt!{@1w1p7@*TDNV3qGbKIJm1he8eMYz=|u=3W8lFG;&u-dEE1 z{-iG-eZ^`XEGG5Z1<9fg2zYa!-@dnhzCU$(zB`rt1rf4kam{Q-3Qi3F%?o&Kq^PV= zK&Goz|KhOS-#ipwXxIl9=P^6N=5ZNT<8fJ5<3YGqecaYn=dXh<6aw;=11r>N3=>>_ z9HWkxpL`2^-n9h0*4wS{I(9EVvl%Hvp3X0m3ml~uXoYeac{2U10snvEGUz64y@&Uo z3(ahS^xm62rQVu{uRqq)P<&VT3*j`9utf+pj<{C~(=bTe^( zm%pL>SB{74R($mS@Cft#Z+b)LpY%q@Y_V&)-R~6L7%Azu;J;Xj7h}L|VA_)#8Uv6; zuaPz{ngw##@CTv6Z4qqqODRZMc|*{ET_MozSxAYj9)apl?SbR}4iEW>aCwWw=LGXU z8E}br<^{M+)=E_@`X#pKvX0-nxu3eFZ3+)F%GHLte~m1BpDpMyOw8}C#0|gLZql;y z+a-M)=|XDP=`DSOyp4^Wi%p)+8to{}?#mSSR4hyAPRQ%aRf~}#z}dyTqTNlti*ANm z%&n29DJR+M3Zytf)y8jYoTF4k$rG__ya$<2tLj8%<3*I7k0S*{jAW;ilpB6MNW-6` z^IJ|f(`TefV9^OHKBa^whF0wf`v?>(+J!}r^7(F3Nd|-R$ahTiU01CnvZ=Rp*=#NSwuDsBaRE}S~&>DI5N>{+lL?iOU zFmbBw+E#J7lNFQ-1U`;u57|B4l-NGi9kQQuAVl5WW)F*r@vM<`>t^<5sQS(W+nkbD z8ZG=+ei>m2-=4c@R&&g$pBVOG0-Y=N;K)lC@ClR#4wzYxg4f^TiA8SCmuL-jm`)it zI3Kb%prVv&7#l%tj|^)G((!C=F6B_`YsOG9rj1I^&*BBq6wQ_%Jx!xjzgsWhrnJ0My>Jv)%b3-(_iTDIk-cp=}ymutpGW16ZWI`-$Ly`P|L_AKt&*=3h9&#O1G4!WM5hI zBtdN}HR?lKG~CQD4}|yfW9BiJb+;Z`El8Dy>F8w^;#7IKWtZ4RVl_HmZ2y-&%_sko>>fB zY1n`__{P7o_+6$Q&JNq5kZN$_8Cpo+G7!*LRF%NuaUnCfkNLeu>ZwdVB5HDfx zf_9$j9j6DW8)pK{!2}y1k3w-J>%75k*M$vLEOR(f(VhYJ7 zUV#KYSsSC7Fdj|)2a1wy`Fy@oyI=!sTC-WMTWY($TRF>gTaRUx@0Z7#MQ5Jpb!`-A zw{1lDhT0N=w> zK(Z3fjOFvXH<*RUk>+OLOE3Q}ZYgwPGJtf5`A97Ii!`suYt8mV+vT=flqM(lOrpPIxnsG7K8X&otOpD|v7`TE7#{s^M1&UO5+r-J zXuJq;@lH>6pa4t$D|MS3t9Lp{eX0uo07c65e5Y|4W0j|B7)fx*x1edncQ+(1m9dlZaswV& zb44yUi);-DPeeR+S31R8s^Cqr;5Co(*?mi&sNO;fUBkC=DJf0Cx-sF!{jsX+`{KQ# zpzdTS-}Kye-fZ`B$g^Q88b<2k9--S%>b5h(DWF*&SV`Ae!?>PO1%+keRn(#Ke?oee z*)33#28+La!Hq`7yqu18$#oP1#XEC_LV+GSn!Z+NQ{p+M`~M}JhJbC?YA`y*QFeOl zGB9COS`LpnRhOJFR&Xe!ic>ysl4gu9U5^f^sLO*J_D#IJ>pRc3s=OJp&veF>VB#v; zu9NK^2_yCLZ<`h`(5)sE@t@yRh0cpQZt5ODsP_uM@a%1my5CQ0@r_}6R!a$V@oTN? z`l)V1ZAV_7&1>a+YqtG$bhb}71n&m3KBV*;n%*womW9CB_f!}_VxMg+# z(R;&yS6c(ouDQ&T%C!^E)ivS)si}Dc+4S_P2l2ZJL-fJ~d6-ini?0eJkaeV>BXqoz zAYa7Q^S^->wd8=77!>YPoNj%!&P(}s!ENeV(aOutR*^_GuF;_*r8Y)fe;H(Q z1FU2-EH|7kZvM7j-dgv4W?IU<;oJ(onp_}jW8@Esxa9jPN93xJ<`+9ffTSS8MVOkG zlZnO8mb(~AoJ8IHCIn|VGs)SF>P&S4L+*u5gx>)Xoy3{c`=Z_J9E84_9~#f9!jBmq zy7%N!RHkW?2v(DO(`hT8g8TCpvRIvGFVWCAmd^d*H24g34@~Y;y!^EFS#sQlJn{{N zq@c>!>w3f=lB6EJKG*5McZhQXLZ3%x6#Auh$5r&$m&>9`3)QravTbti-JVSbPKiU5 z1Zsw1b8jFjU+O?sMC>er6Jf65QYsaOO%i{;G# z^v5b1;9~vcqta1Vzaqy$KZ5=8~Y@3V3J!>-jRpYq;(B88bN{YR|ztOT_u% zmjH~U3!{Wuw&xMuJ+|=a{oR;T?XR{2O5V<=t3nrhzM91r$#k*dMY0k+j^;W?r>MVsAE0f=}R$tMCkK+MQc@+oB zi;8%7^LQxl4sVH&LZY>D{gGl6y$|+ST`x>MGmL=q%1DMlZu%2hk?}Qg>uInbYU>JkXu6J{e56=&?A-eQ)H z%%F*)A}G4CMblnMUv@PXUv|8+MMT~B3yojSZgmCvM??pLXf|P^ldo|`Xm>{#M$;$> z&%t$&kq)mVAuPC)?0(nmeKu`N6TdJIrA>mFS`-D`|Hj>02F3OC{hPSE1PE@y-F1R% zZ~_Fk0D<6c1HmP@1b26WyL*`61b27WnVsCf|GjnZQ}y3^wsv1UwN<=nPFFRYo|-4s`J^*3I9HoG9XAGAYS#1c#!Hrp#O^x(z(@%x-e41BV)r`8$n_TyZw>F zMfV7$vDRXY10Y4kDX2$%hjm`)ArsK-Q=PHC5N4S2rp0K&Fe|{h{UYr})V*>k1V^X6 z*2EV3jkuG)9iWLLD~hfLkcCi`3lWyJPPz7gCMwEiob+eIjyh$T|1X!C`odFI*KsoY99RZ5BKdS zuhq^@gTeLvCr6HGtsbwEg4S<2X_mvUdXNOvu~)hKPb_AY@wEvT`BZ6Dk$k1PvbA-V zgExNxQd3WczeL#+Low%F_-XMs-csG6^P1O3Tusq#Xt_Xbs|vbh$RXb0!Kzuk{tuTm z-OhZ-RQ%g^>A%od&=8qCyJBDTt`<{|g;b;Q?Dz0@To@8!zj&}egRUHA2;CON#f24a=QJA)(J>#UI%6`+ zp#ZR>ml%0odfjiKbF}eryHUR}_JO2n*$){PW%eV=k&TU~vU{-TRQLG)L0+Ma6+fcr z&1V;`Gx!5KRUd?zKrYhLe{dGfX)#0VT*>Yn7^9`YofG)yCKz=C5}=@)Hmw9l-Bq}p zbR(ven(FmLLDKnYT( zf5woSDS=X<8s58}Dqhx4rKGsp{QujD`F}aU9bWa=ey)lV=v#6#&h_&7i`IuC^A)w| z{O|!XF^%1Y=`jpWtjGV-Jl0d&Im z|Ni`iOOhgc|320M`iSrQ4*Pk+C3q7W+Kv8kxBasdb7n_#ZA}kgx9sef_VW@o$7kk# z^4R^S6{wf-6ypyF%q=U=ac|t`8YqE^J?K?NW|}49Q5{^G9(;(D_|AM>O>lbqVY`oo zWX{fGx!J)(zt-~$?cQt`G@^Od>9OvS%3<7RD3EeqWBfH?9kYTcBW;NxRoLL%u9YHY z=dM>TdqD(rJ8|qLM)qg02EU-SL)<9!Fh1dtPpY+YtPxS8^>W($t-RtZku7hddIKSj zxS5#Qw;r6o%w6tYnnd2BF-B>MZD|4Rl72`)Lf{^r30CCmoamRPD{%MuQjVQMVU2uJZVV3w9=TRbQp{Egq;MNnG$OLBRc_PK+Lzhp3BT{LYaodu%~_B3Syidl(9=@ zf%W$)2gHJTcq2LJv7FsW3koAL@&%5k4xP6t`u9)Ax(By`&_V*y8;w&po$BD#eAyPD zOMGMLS~=SA*3!dampR$TLvyqNglJw4{Vuq6eX%`?eiUZ80Fu=JtS?`x(uI4W>%nS# z8}ToVC(3m}JvWo6D{us#6mAtYTC#&_0{z5TL{y=K9q}MEZ|#S+WX#b-muz$SIH{T^ zobkk*$xJ?bWF-AT+x#t+T3d)f2c>!aw*VcUvS}`bg4}rgWPG?H4RFai_=Ls5)aHc~ z3S3~DKdXX~!fIKj316y}Sbux0`w)qUb#7yk2~s(|SIzo-GVQ3<$-0XlnP{`JP)Zsn z|12%})(Cx1r>U`5eJ4|OND7)4UCrY})s~c>dQ1*cbfj}D5`n*Ud7l2`sAlymZMO}V z((Nu2+Q2=ba8V$k)Q(Z4-+TQz_29;8&3Et~8WrQazZ!?^t@)jcc|2^Gdf-TaYs}w% za~ggX$?=*aZ%IAkMfCEC*bkQ8GfG=ogIw*7uULs+3;hjXjwA)Gof!!bQrFRSvFsH; zd9{Frk0aSnyZ@qtuQ&JIb*CSn3Pw_~g2beR)63rxx?AqP>c3ESXkNATGt-CwHV0#I zHHWw?TS}|)`W{koyncZr3DZWL(7c|}^vY5c(RLzaHk{#%2Wc+)F0L>$-vI~pUNyR! zLz^uJ^PyJ{&*~v;(I#s>l62KE`_?7^@kZmb?h~l$AiyvIi~4Ne|AeDkm8$unBU~td zHt{hJ>|W%JFe|9P^_e8S)JdaLL24;?8IOAVrgb&IY%t{;np+*}Fc}KXs&ME8k z*glAaKAcMaj2!OsG%0f4c1t=xUJSSFVK?j=3=8zyOThecCgAw}B5?(RVaLnaT?4wk z{goOHf4$G)c#VTsK~&J&8SeO-zu0guCuVw3-4|y1;Jo@t=LsO%lCDnh6>Xj)Ue1n0 z>uLfPi{6gu9;CXL-PemSdPG)f5r+tNW4aE}Q0XlM=lxN}@xRWFj@5s&4 zQza8WOhOyqpR)4)HkAH*4RpPJN99(lmtC2g<+Mp|C?Qi+dI5k+1$!)7?jD>H;(+nxp!7+u zRXW%w0JLiOkk{@T;i7yR&%Ov9(5)AOaIcD-ey?f;B_{{%M-%A(a-L`LVU#K4H7}W( zp{@3L&xrRwQG&vageBzm)Pu>HjA+sGUc*e|&SYSbvk)I;CZgsU+Pe&13nrr)L%;&$Q6^3v2*4lwQN>+du%Xwz1izRE2c!!H>J!H?-?5^)&B zsjG+Do7t&_I&3+>cy_kF7Z|j9H&!ZYcUC6mmI@Te*gXPc^`lSmz67Sg}FCs6X-$S94$&emYrD#dSR2Yva>B=s|{Wf!%>#O<3 zPSe;3V^$rD&eN&`@L6O6(~snyZ|7r;(e`|$9;TdqN=8WX6PamMMc&$BsHV?D_%jMA zs-tTIX+Z-zE@|?m^t$ghCUnEH#(eUW+5?GS1bO+Q<@H(hROu~E$!~dY;G6Q#(#iJ& zRi79fzrYnUDa#_j4h3fcfZ|(CTVe7DGsQe=5ao!}C9Z7EH^KvTC5dBREhkQ3-P>3X zow0vy!Tycf=5^))i9DJ2|9B*Bp;h_E=wn7zd|ZRLa!3dGspy%vFm_>LAEp#0%zwtY z7>Nwudxvu%&e)Y!2%+a0r^O9g4As`HwOnRP7&W7SB zU)M?k0r~kNdzN-71cj;T+Euzq_9~LD!<>oB3-JKPo*|&sN*H-umb^ z$yKd&XL(k9j@N*TKVe{cji`704eqFYL*;bFSe=YaBr^IFX7mtMDTTGKQ=8}C1@3B^krAX?*Q zh;QI!Sb97Dh0bcsMEOI1zu3J9aO2ARj1t}mMNpqBUvEvc#Y>V+2ejZ%mQ^3?L=>}B zi)c5a7$GeETJK~Kr_Xnf=PAlfyoACM+9aYAu3UJ{o$OcJwA}$) zjE7USaw~^3Rx1&j46F3MZ3{uS`zcz29}%2G3d}@)?|aQ^g9yo9=>QZ38Htx^URML7 zS7q6k%B_ib*fB8E>R+%`5`E`~4;bX`?45Sr#M}@cjKMJ=>^Xe3Tx1f~b}hZ(064L& z>au#L&khO}LZQCs)>(sLmHJD&S%e@$$!SjL zHWpZG$)@*iv#VCM@UH<`vg}WC2cJv64*a3~e!Od-w-`5h#VU9+Q|qElB%4lx7d6Rv zo^!2fc|4-H=XC&w}e%X=QALsk@t z#`+i0Vfi{bpRATs{=PzOCrBMyfi;C@Q^b?N!_8RhAC;rjwKf=zp&QIOjT0RHaAUYL zm5-l598HtKvxHVfU1-OIND&EWACRZwjF|v)FBXg8e2XlK;iZ9uNO=ip1r(ZEM#kN8 z&&E=vC9uBpU5=Zg-?qBL)qD0=Q>yeW2;#5bIXK2XRV-LQyt^=Vxck|3dt!PYvOgk- zsxr1S^r~m_yR?~m(pJ;#yXP2gT+WEXAG?5_B?fpp18v|JoW7^l{x}eo6#|(?X-=;1 z#JZSu^6d3XD$q_-FdM**UT!m(kg8T{$i4Sw$N3bAD5<$w+WD}Yx}wCN|kdh zq`gV{S9`P9+;vFdbK)dumHCEK-0ptVM;@8{!7BTa-oM*fr^ayb7HgD|wqNaX81(SW zN%+l0x8lA==(`0-SA#PvAYi7faC^jdJ5wKkO>`{_m9zZWiFMDT$Z`{|F4(NR5*D-! zS{P%~ci4zcC`&9+^kj;Wg~|v<{%)|kxLS>k+z?3f<2>ibOmBX5=bc?pR%dDHqtepY zq$~rMm~Dpy+=kf#i+pF1KmM`^H-l(E)aVN}9wxW$AHYg;)eVr}IOflZgQ}hwY^#1y zd&^F(-b>QNAQ50-bI|q?d|2cXRM}S=m!Rg!2R9By_I>X5$)>i4Ra>OOuv>{P^`5*= z78`8$*~>D^WMRz#fn!uuSxIcbx=+KrrNge~Tzw4a@i^5H%hueP_<$+U`}YrrC|>D40wdnfQJ1H(Fvh@jyfkgHODlWO?g!(KWG%t&*>; z^|@{XROkS$*VnC-Lbocoa<;?NScldss_*~2O^?i3lB4yLLnhOVwsuBlW0mw$w*Kii9J^77UzD8%7IS(pn(ddFuN6q{BD!hiE+5nGgMxsq)3{M`H-eqf zk+NTAuUs{8^&5QbvA^})htKdJ(z=m5c36Zl%=Sjrk3l-xM>v%pltC9-WW5$R5DCFt zooWm!gE_wFGprH!qStT&s^|MP*+moezeRWXTQF8o3- zo1PGdJCXm&`@neghp^z_&A$0c=)O#X`s^W3ahQzNwxyGv?}mrXYnbVS$@W*eLT{;* zCQo_w{x;GjU@K6xh=*-`osDTHJr`E+U1p_4Q))l(2W(t9Yp7 zB`Y1xFd)$er4K8a+l>=?cw10Kk*T8VtT6L2rmbSUq=tel%_OQ}{1IVVf|w%V5fpJ& zrcHT-Uk0-5C4QI>A089XN#RUAk*VM0XsfcOiOwn7I!28qOuD;zW(mD zx6dj(w)oC`rO|ha!eAZFlgW0nS_T!b~<=9GMPR zY3Q%`oOkboHz~oruiF4{5b1zCU5MK~C|-qf16Vn6z9WC?Y8N&3Rjm~lX1}Y6hwP24 zs10_^7w2GC++s3TqYf1PXqEed$_KLbq4?kKF`;G@>|^-INd+m^Dh=a|v*Zo};w+RF zbIVGzozXGG__eQ>fElT|$?k~5@5xTXmqukA&o083r zqmqjl@wl~VuqB36=t4iBw!t;Dc^V10go#PL^y_}}?O zU__ROwjH+oTV_cvGL@+zbsBkS787jqydBPzk!}1EOcaJ)OWEdCCSS_)gfw!j&X!C+ z8ZLVaMbb@`0r|=w#~gT#@Krv~L|ZHWrizh;yov+e-;1_%KReWh?-vmn_jUZ5iSb#x zH=iuKak~0_i`L&*K;cR?fdhDSc6AiZOsv}$-dMpj1v3zVGd*-JQL|}7U+B(RCfNiK zD~^S78cLdxZC+MB7{SZ2l3?HRj(ujG{fVNT9BEl(%erpAe#qze20IFiM01gsIu?f4 z0g5qyiKGo)z;SVf0SpOean{Xny*r>KX7f9VmxIdpYR&uZdQ71C_*MSTc`PlBlCH zHb%Uof`?($#AY>+@6SCra zE0$54r51E=qZTX#*jV$otbju@$+o-Ws_40|wlUCYD1zkS4!D}3EmcLlGL}=Mec;J2 z*Sq$Nd{u&`=dm%18oKRcer%Dia(jRkNjBtNl#5bPIwKBE;g%K4b`Jkq|B|mdZjD!Yx*rfTGg$CqZ;&z-AraUD z1IuM(nj1eRcJ~bhS!WJ-H=&kBOjMRehjj{8tv1%2S`q^zY}^qZLcJ|$RInVO#A-zxfw0{ z625D9PO8g;5~sc2m{b6|!58W)>JjaVQ(oc`>t!>#0U?joRvRNOH;F3CbO?1;C>572 zs%HZOUilcGL0)O~+XNTxp^a~s-`#^$Ukp5(EXO}KW7018+?{%aVNtl2#Ge;9hEw{S zs6#cFiVF)1Ve6t!cY;{~v<;aqK1f)n>h{R!C09_)oxA?A2fkuc-d#zE)fn>h-94c0 zXbFNE4Da)tb7%G%pU%k?d0Z zqu!xU1&uPu@=)O-ys=klH|9H)^NC1)gW<-FU|ydQO1+m0YlM&4wTMPj z87SSDE*jsssgm@ak=go@E$n1)_FaWW&Zu>KmbKC%Clqv(<)}z<0yxtOnbHyt=T0Sf zyrOt0Gr}@}*svaWpEl~O*w%FK309d=X3i8ia#Id9goRNIo#%zE1pPQ46RIhQGkU{e zNRA_S1JwxDALU#Jt8S#Xm>fGv6;B#2d)uWl(aZRSi0pR!~_%qd(P>pf7k)(9z&9suEy^0C%1%mjdQ4A=nAn@mg=ZCNvK1@M#L+48@IRqiJ zG1XBrYO(LQ15%5p;T6w^E6zkrPL6sKdO2IT#F)M{zk}KO_Ug+Aek1)-wBGPJr1Pz| zT4atvnGD{B#%AB&-rkzhLnM`D4pQPxV;Eh+pl|zol635a=>cV!80*pu(X^po4ZLD; z)vJ4~D%H1M>{Oeh125fNL-~Pct@}9mw?eFKgyhVCe!?szrp%M0)_D0MKuzIzdvgS{f-RE|9ZnPI@;AItQ zHVl(g+?n$0%gE_!yUrlooCRLkoBI(ac+J{!Aey9u6C$8QxYpnCNJ^j@$S3^rZ3t?0$%=@Wcp#4)|+N8TEWMn#~(v%`8F=CXAc zy$ij^*-*J%aHO!yUPHIB!P2+K>s_9^{J|)?*=gV3nIb|kVc`Y&%XRs{&bQp;czYa9%775fX#T!GV^-enOjTi0G@v8MknpN9~gh?<6 zROrK%CDAn7)G<)jo-}EEsne|-RQ*M^YjFaqGZ%y;wli)fUN5?zBn2aiw^*J17$CeP zW6BP1El9-Ki{KJ#HHk#;BKBxZrcOVIHnS9kjNV!mC2q(FH~<-9a$G^;_m$7TeuB)Z z4~)74FeVuiF}DX8k$|^4kipkmV@Ptl<0YQiBn8oM(hOb8B@9vSuO8lSdXDKNQAsn* zf?qOX;>RhwM%nk@Wd43V+g*R1?|fNaAC+g4vk;1%r)+irrmQZ6sXjjpoCB`!&CG+u zoqkyL+hhknj$|J7sJ<3RN(Wj90IM{LC2ozJ|NrX>@{GpC` z$^46ulwMmUpSC!>Pcbd!=0Dn!`X-3?|Iz;6Ul%IrhSXOg?SFYNY`-&uonc4abiKTi z@xZOLPmqhzsEB6`ZswVixV^01ckOrGub#Ihh8xsUwktSoCZ2F2mgqHM4{jA=MekgB zKXwQ@m&qBuZ56Vz9zlj0%UnwSA}ELckK;MxR z;HJ$VlMg4KBItCC8o*o4#xmE<9Z+2+TRk~G?pM4gI92P8^DOM$9ggut?8a{j1EIVkRA!(1$^Hqc7&GFtwZKYu9L!qOA(9#mpepXK7 zt7#7Dc|JJzBV<=;am9qEDR7ll9TTgks{zogzxz|K!879dO_TiVU32$o%VGq20=rSm zPD;(j{uN>Uf|$z!o}Ypu)6L3JnmS1f{Oo%OVYAJ(?7jH_rzNW<((?Xg#7Pa4q-Abr zD><`A+ZJ4D7^T0ie+3uZ1Pb!YRGR%TnSni)TKAG>O-`I#OTJI;>!tn8nJ6ApWM5u~ zGh~fw_fe^e=@#IQI8C4HY^`*83$?E132DDiLc?P!D1vHP?{!}POVq~4MGN$$IS_cJ~yullyb3t4Xzoz7(p8|ng;`7{QZU4*>L9;6bVb5T;Xzw{!bj#bGN zgq|rNvVld>XZ46*!Uepk_f7A1A~#J!y40f-A$4+%b&)4|%M6eVYE+)(3w7S=eWG_m zfB##a1&)#Nm{E%_@M5Qs36>OFIOp`Vs-6_@zIp#m#>)qoN!&rK_f9lil!=?spG_tY zFa!%SX~*JCR76c!XQ+cs+k`~JpSSO_7W!v{E9!5VN*E5#-#Jd6?zm@@*_<9{#2VMw zRUJ7bEo4%X$yD0{7d9R!dtWBEhhy7j7*yL`_HDMKYGKFv9rmL2pjF~zJhUS?_i|yk zqoimRP&OZWLHAFK#%>OU<*dF~4(N_%z`beUjFIoqI#j-PKQ0IbFFn$w&qVA%P3f?xWt7!Mpj`(4dfs6jOO?%w7U=zYPIlT`psvFK4s zv@i;pk;cleEkVVq(f}NzD~kW(R{hKbnX!dXN5f#5#A5;$&IVOfqxD)*0qn&>1Ag0^ zzRm+N%Ypfy`}F$nk{!(s;;>9*gvoy%zy}L&7{X<4Uz7=>deKYp$;G_PgbO|QZ?(Eh zaWQ2nNXvx>t_mT$J}C=IT|Zs4dS+(`*$Tfwcw9`!aFAwj7HvZOI&3igQLtzqnogY( z$Fz!lUZNaSg*%`P2h$@}%k}smLH1KhD?wMzgNV+B@z+9Dpma7CP|n|6D#=TViS`Ra z6{O+%)^@?d8{u^P5VwJA-0U;P?0(l;!yxbwPq?CL6SXB-267!DR zdHu7mFY^wI8%^ffmsq~jl)OMsVjd-~_?U2x)kMKdMMDpPL&qX+Qp*M0>hV5@MP)*qJ&!oui-^|B39{iH7D9;s|r7MCw-rNBW zVFkqH{QPMmq@~~DYYCR?WkZi#I8ZEHe-|D0G44P0zH8{WvC!aA`@e!mQ(pr7fQjA} zYiJ~@=UqeZZ!42hO$22eI^Rir{1|7|q0!~=%GU&~A0Ml~BUS;*L*0ZgFnbZxhr*~< zCpV*-^_T~DUmfK)k~lp@i8^ljxuSq`Bj1Bl*i;ytj&#%v#|dVWe8}p3S|sbrA*T8 z$`3aVxH>3+Mr~r-L(qxlR?;lXWWa);oPt_UU1y+c&mmb?)0tcI+3f-@(7j?7HD*Ln z3(=ZeG#T*V>bNp=UE(r&h*Rar3r%AMo<$iyC6Mm8q6l_G?>Hj4i@QDXx+fpG zN2Rhmp%bw>CSJs;(f$xj@7p|jAbG$5xG~?Q?K3|z zEn1?Y+ggMO^wGNYF`Y^p{6Y&v6?h-C2-+W%@hp` zF>svaGERxlB+mE=uU~QXS@-Tkbb@oYr*L_uix-I|X$vf@hg-gpPWbYuV0QE$AuAPu z>aURw%y+#9m@_{Cw_cet^BBQ~VFGsI=y^7r&{r zV&4xwLbv=k#>zp`98FIzLc<;enfKz+27qtml@$I5rfKdys(0k%=7UpKTChtwE-FHMoJZqKKJMdP*@Rk!E++ZFM~r}Xt) zqC{zEPwi|-=lzRMEj?3g=%DJKp#LWZVfRu6{aR^R8K}=!D?A(;Ny1N-3d?RlRI<=& zV2zRs3HOBhdndmxH({cGg@y`W6gY1&>vhBcADVyLNFZ)oxwpRm)!s{r8ckN(6ozS& zuo(HpY22dzJx|Xo&5K}8qLXa9Pa9Vlu4&dqhVb`_LtHpC+I(}atv$KGA8}bSQ4^R& zKL-P#Sn-KdMs5Fe_G)_^pGAvDOeMQ<{VbbdmvWy37af6|`Qu?Gdd`DF4(&uLPGG=t zjI%w{e!X)xlbhG~%>8neDgx2IvZsdNYA??e%gdq4PFFf|70fuw?CZNMk(KuIj_*H; z&Rb7KaA+`c&OzqLXX!BZ;iS6jSTDw}H0CEWe+qY`-d=-f#2RxiskQEyu1xXLHk zKJITna-G?bj{RwHO7y{>L1`&E(&@TMdWMF)81*y0e7^H%t-eA4fWe7pugl;$q<;yF zO~&gVAfPoLL2Gro*X<9BA@ppfqv$6IiF7gw%*@0sB0r5hIs75D>!jzCWGY<9`H=w# z5~E7G&Yw+3FP?qNOWG>-y|T4GN_(!8cotVwRJ2>Q`F#FT!D21KbzAgxMyoi*+mcy7 zDa2d}?Qy!vCaLKM}Yr+lSsHWpX7KGrVAUxf1q$zSCcJpw0;VrEhD1?xQb2ft+AR6bgTDM%JSn636n zJp4cs`Hs?6zc4;UrvLB zw8ICa>J&3y=9*!M{5%yxvO55B|-}%eXPYU}6yZ657lvafc8o|k1Nhld;sD`{J z{!PWLNofbV54C7O?lk| zZr&6hKYwIhKk2QnzsbX{6I*-%W8vzL@&!vz_9fvj(K=LfyY3N8-osJJO_H&xD4WdGd- zoniumL`GKU=;I7L*Z$@Ug|ZbUu?{6#qHs~q=J0{i+y#dsFn>#*AVJUpV`qW#9IAca z&t34OG9POTcs%-p59XUf)@E-7SKxI0B=t>o4?1RW;z1OUa}|@>zh3#=g|S}gS|(G* zVkoJeJ_bJE(E1)L=-QzVToFIc5iY>+uO+oFo$u|5NVtO5<|D8DtNWoI>z*xOy?m~X z@*H8_=T;m>!%lC+vqJVM&f|`j()>xb0v|pBfp$O6gl$UESy0g=SxYoZn7S24MiZr!D-GFUS zpMLn9SXzXp31?DfnXxTJg54i{A%x%ZW~Qo{rg4`zAd9sxRD*?sqTfG_45&W|C7q>H z$&iX#!;q~c3WcmO7Fnb{(^GnMHp{;sUD4`Yj8NX;Bc{y5jn{A=`glR#QkQQ;$JTXt z6oJG~PQ^uk&D13`#gMk36n7UNzl6Oy{pp71+ZPxVv2qb?;WuCvPZchwSy}=c9>yxX z$ZP9g&$HQ5gfNP`PIU_?Q*MMVE6xo4zJz7O#7?9XPjxzh1-D=@`~`o&^ByIAMc1d@ zkN%H{o~Ot5IMGd^67*(ZDeQ5FmzKJ;oi^LM;c}foL2UBh^Vj>qTw=~UaUyW{dEV`pEisFfIz0;YE5_8iQ(#1mJfV-Rzzszv1UFd5OcaV2EyQFYzT zS72rF*+DQm=Yesz^6J+yx7Q<%11<@=je1_WDTkC7O#NqN@!4@$db&62Hyo^$@re|%hlT+~sm$k!6IcKj}IRk4!{Wgwf zdhCVy$wZna^pxOieBJs9Axs|y2Kk!+F;-N|?QxEad}u7jYCLTib?eGG)`_kAGd86w za$cLn?RWU+%?8TpY4kWcV`O;71m#L}MV|96pJJb@(e)M?Rn~9N@9hb6uyqe5BAE~P zL_!u5eTa(@-pzhgxgIi3tokHUgvBC8N+t>Pxjzp&yP~M%t8D(dyozf#m4jgJ`zD$@ zW3$((#NVFC?vke-wrHaPyx@PhaH9%*N__Ff%sh2OpQf>YeJCN)x&gL#Li*Zz`%t$+ zYAxX6J`{`&LsjOIX1IedMAxzR#fEsMw<~{+K}yO_4!7SEoqQJhKX!F4z#zXrU!y{} z@yhlZ04W!0%4@3HfVu`!kOg5B9dO{DL_wmF;8(%L*tD1*#frEyf}z6xf&4Ivg)Gz)S)TOTnia4-ANjj)-crknklsC+!Wt z47?9r-p(@Z{UCQVe1J@#@$=e*rg62h{GrJAA@A{w+HP4zvhpS`&M2Ym1ZAkb z;xTRJ@~yl61fHw1=Ln%4Z!xHE<6;0bYq!kj6gT#u-p-iD@X@#teO}!H zj-{h=cD&uA%V7#PbV@(g3H%xsS5lbHPeC|PSa#2ecKh7+f^7Ns69s-GjZH^=<)=y| znyQ+wcqLzL6b-xw_#6ClF$3l~QDFVDttdVL?%q;s&ftf+*hw8DFTpU@NuV5DL*@8S z&}A?!JzFr-ob(gmH`4nEOv(2-`)OhGvCvh2_GV!7?+|}y-|nAJMuR_eMJX<3z}jC7 zoyTr~RWtkN@5#G0ufgT!6LS(A{%2%7(%=Ab5D#`0rO)@cvcrgep{BfB_^&WYi~oG| ztY4u|5Xv7^$tLSCt0=AEa|iyJ8L8u8=tB0zd&@EAtM%)9QW$#v|MD;VT%#yF-0?Ajhu;G;;X!$?L^jBJnZ5vCQ{maH7g4bnfM9oMYGHEqj)CZ%c%C`8~j~+vlPec~!a; zpOak#x&kHN8XmD0le2u}U|E@A(}n0%8@cc2RVd6MJ|&5v+t8iw)6oq@4>eLIsL7Vl z&??&O(sNebAS)VIyd@4$K7RbDsA(es651y>80Pm&jz+!pgzn94`(N+Wtl-D}(9lT* z8`_)Yd&aV~7$0C<^|Zm zWfKKg$y-EAD*y7#i}x83$y6M!?xWq5+LBqIxnA&O5GRb z|9Z>((uG9pg0rq~&t!otG!$nlVALF|zhXgPp_C;kPkhMOX>6E98h|1f^bmCR&X9SI z<_P!IbN)Tt{o#I2JN<)t$=nT1))bA;K)9>`T>OuB?_-^qiD%1ZiWSM8g^9)Doh&K+ zt5PQcMSioXyZkSDoWiqCJMP?UH=`EQJtc(ESZVxkJ^i|NT)6Ho?JnI+7572F#ShuM zQzF~Qi67ue4@X`1<%X#I`=0P~YRSxWZR=#F9AK0?9&mRV>tKL^V*vZaZMi3O6GfS~ zXnSXLtDgd?>G2hV8fi^lnj;j4_?sOZc#b@S82-rirp+8Wi51-^fms2BeO_}gs3yt6vvU9l*E*|aCy>m@pAJT1gPtk1afgf$6^2i0^Dip?b z-JR*w@z7a@N0KqYV#F#gs3=TFQ#%8v|#q4)KwIFU)#``g(IL9~ln~BX* znpiyfEL?@A3HlP*fKZYS_k4~q{wx8H)cb2njVpMm(cg{j}z*HgDyQVD;$&$ng9?a&_dnHtcqHePh#L)ER zjjF|L0AhD8+XcGfVF|HMV3T&fO78~BQ<_!om?IK1rt7OKg8m&Zcbno6zMr-^tDx%Y zrham$jNg~%fU+Qe_UNR^xU>>#g2L*|MBLxwU#+bj?^iu?e29+-u|+QeL<<26*Q!HF z`uDR+oiKCoiYi_Z9YOKme!FhYYa;!}lBy43r=b9?1F%w>ZCc*T^Sc~u7rjqvk*EW> zFjF8mhztZQ6dh!U#5~lk3q*uaua9%9$}!<firPzm z{Xy;*T_glYq8g@ET;xi`$^T5ak|tOT!>Ae5*g(JRA$U#fjo;=c2U7kDoA}N5rww>J zx3Hq`&>i9!o1~oOky=a6?h>1^(fN=To3>_RfrLqca<34yQaU6nC_#yeFqk!(kF+m@JLZ)lc&t$3mw@d?)NO{F<8y<~4<$u!t2L3CUqHvM z3{-R%StFW){`Q;bOE-D9O^j{^-@JSWMS{VNh|ZDx?ug?Y3?{l<-s(1l&?pQBH~Ut4 zAlCAsMXi1>qqA+sQ_3v7xL@d-Yqm2wQTh|W?~`qQR=b;kZVs?v;QxGw<0>-2Cdc(G;eEljXM^rxd6G0EqMEmNB zmrHN%B-kqlI6=KTv~smi$+hMgNz8rOqF~K=N!f_n&WZv%?|ErSbj7B845d7P#yTGNC;^JfiOJ^kBom2Qmwhtdzn8tQ6tVfoS zzv!o@f7D1Cg{9-6^A0uf7avY}QsU^`S%WJWu}Vt1%;jslCscqZ9!fb!E&h(1d}J!m zYcZm>5I!P`x#&$P>Wbs4=y&kpiL!{$&x$+7gt%oF#J2x)F+mLeUWudos@`WeS!dbt`m;?^27;+)lAZTgzA9J&69vlv=n zb{BE)ZSO%m`1nnt-De5oVIz}6Rs|CiQ;n3E+CI0%5M->6-0hNN7nv;dqdO|@vqs4+ z+6t#(Czj|e^2m!9Fc0h>Y)YdUWtFt;kJy%w1V+VAwzjts2R4y@T52Daol=OQBsR!Mt83>xb94;EqvI_e!najNd z{w4`davpyp)^uotGemi;HtkD*q@dqypRCp}jN|NjLL7`7LhyJ-!n4wO|0@9}&osJ4 z*LAx7a)F!e$}5p4ce+Vru8EfqvxpJepmv}v{c7{&lY;s?tM^iC;%dv&vkeLP%98=1 z9e%k@MP)YhGHIExm|oBC|4ysoe}7s@e#bRq&q4>PD*V44Nb@p;{@*Tu|1~JnCxzD^ za8n(&(8RkMa}$PQB!UAPJaIseoSd>napNOzW0IZ%iPjWA_WjTxh6)V4V@M@Kl(W~d%s3*+&DH*AV~q08m@ z$ct%Zv7XYQv6CmD0^=iSg^&{B2!sr;<3bOuWD>Yws!_(iQ+=JSJ8)nvbibeMSXjkm z+8-H`bvjb10M?q@(C?J$jKaV|tw+J-FnwixVp^J-i6Te^44<-iq?wj;=Uz|#xD1q9 zE!I*y%4pGgN14{r;!xT1BznR1DPFkcCC|=wHNlu>Uf8Mj-_shBVxz7H|1zC$ZSJqnhJ;!g17r_!kweJ0QK_ytR z?cpsYpi}MBQMtzNIXq|;+HN$tixi)E2<*`m-ARo)vHe-{MU~zuP{N&_I$KZwM(xLs z-8mIpMb>%0my-So)65aAcF{LfIja$lM&}-f0FWi2L8(V@qt^$5A4Be*57k< zd^)uqbl3tJTPdharLD1G6O!f`7ZiC+fBmjj{M=G^>QWKj0gpWKtC%l8xj_YQmp(MD z8!CrXs6-){r+&1V5et__#wqk5V?s|5p~N^S*BdKHRA8MVF3URFkRE5@GhyA5A#MY| zJtdH07~UN$5aRM}-w-7SNA4gVK!}M*j4mC-EHo+%vpo&;TfuU2hB`1NyOOpXWXVPB zX6_R~Fb#V_FaqW@UppQ328oT>KkMW4I68f^7=VgT`|{f$Mco@+NCx>i{HABmAqJ?x zJ{0iVE^Jgn4OzIR3B+KSMy&*yGagy)kZZ)d6esD-lT|H5r{L8i8R>E++C*QrqL~Q` zk8cb6DWxQ@>XdD4HC3K}r&rUox-L86q4D-|z!vYe`uUAh0&S~bnQmO(=7S9b;JdVX z+k;basdVq+QuS*^vpOaH`A<17rN^1@68v!hpkAlmC-p*fMs7!j-Go+;zZ`Fm6TC%q z`&~-wx5GCY!poodHrYDn*K9MX@#XO78s&30xK({u${!xqG`sSKg6>Iqe?edg4quff zG>kF@f;&;&S#g9@9yR?2-`pE3w9P#A?GboghUh2zrVn8b~ z{qAkNM5F}$qLI>>sG?>RY_j%bVMb2Hxjt~~YZ3u_bsS<=FNs`ZJ?@;`z66L46=L4F*v$xUq)@?PY~qa;eF*LH zbYbk>QC5-Y$-@_e0eFK*w(Wc%8DWZUiQJAZz0+dF_FW0Z9z0+R^yK($&y`obCCg-$ z6`Q8EPzBBBhO%LK39K03OX@)iaJ&K8x^#=@VfK78*DsN9$>-7HR~2%e!~j^pDbdUm zKsbz)5<^%$-TjPBd+)N}-kDP{_iQ5W@GIHOMbT@3pMu02!LG0or6%KF8f)ZdOyj>CZcwKH{h#zCk7jm3w#rwPKK>}d@E-uSK7AEHJ*N4=v z69Pe}a*-!l-)hWhiR4Pyu(Z6|KMjhbo8DhHL$;GA_X=v~fZCjVEg;(9{ z#jLsdnXn*RWeQ27sOx^0Q{r?pj^VFUlANHCF1oe+)6VFg#5mO6Q{C|StP*k0!zqNx z>i|kAoi!U=HDQDND-M<_w?U> zPvnv<#6`C2l@fr$cqP}eSqlrF&1z2QnVejtBDUW$sR_$-Y*T9D?03H|qI_+-ARp|s ztw*gG@bhXeG2myr$*_T?>+O}Kw9jw*QAMWTRQ%@qjG#x~;FTR1JUz+PFN4;s}sszq` zNtj1{s~@yGCnl>xu`BMMNrLtb@zBylL2zOQT3kG}WE#S(m^3&+G zAzoQ4->N-EV!$Vb2JXnnwg|HngRuQg**4WDeZCb->aB^+rN9X~|GM4lVzAln-EKtg zb$YJvW*EE<`y1CSs#!Dr@@{y9UL$9y(|nWcr8pn+Kn<3hoqKQ6pHTMCjA_H(+!55J#Hu0d{G7jn);;{#ec$kQG&N>+!`Byp9#pW7vM zoXxTkPwf2sem&8+atI6}q3VT5e|v3tmFc_rgiov#=zx0VhGN##6ZjT7B=2w>^#G8o zHxFhvp_4T~xTKqks4j)r%0|lF3U8YLz|FkH@&O03=Zf8_DP#-!#GlS98?gXXV8TFk z&98n**3WER3!kL&!XWT*)8`0UD-%Rn3QXFc}%5p}H0DCe{McE@Q zk(6sb>2G3|UpXAArA6POrE##iiF}|6bfBp%CEFIv@-o_aW9ap4+Eo^Wl!QHA+TI=y zNe#^$ji=vXJcVT6VQicIqp)C#6kn^ja(XeP$^Rh);SJdXYL}t^eUB@h_{D`ypgst428eQf3y=F*Wo%IR(ZHUU zn%{b#Q6(2Vo{)VOXd%QROYKYOGd;ZXSs3&7Q`PLb!n#aN&P=MqM0<7RgnP6=`FK(p_O#z~Y!k{|ZNT&}k{#FS zeFNd)LQMGV^DWh{;pqC~;*hcc3J1kF#Fscfx)NA*Zi?TO-TUr^SE*DN>QGNq*4c>F zV35Z;SW)|){ESAk#9%zg)m&Rud8-5a#1M=wNA#B{F{5$@mzBqflZ}x5X***jt!#92 z-6d1R;JQR;N*X8dEa;34}diuQNy8^9nF>nex1;S8qtKFwfCn0R>6A6as{XZ#C$ z{EkLxP2S(x|9ouy>wNZtvd6Fd?FSX4D1qn~->PISwbggHo;S}gnxDV@!eiFH|FJ>9s}rqzAT}enhl+ot=?DNqo3 z_{(udP9{V0;lA=|$$;T4v;GhlI0`E;Rd4j{?>)7xj~);%e#-ycD+sBvJ^dwji(*%* znj0qc3&NW>MTJj=!z4|Au|GA5y4|&s+2xkRKZ}u7{XPa85vG{2J4eiMO~}w$(5#f}6qcY5`)h*SX$Yo)S|WCOO(Xp&BBjkCv4qXswoWK($RZhRFiX!udmv zF^5^u+TCev?iCWl3C4uHKP6KtA=73unYdNqSw96KU)(-`9{N4Tj6m5rs=n65kyA~m zEdrEBqtD09*P1lqwCw$7kEti|)Sx3Q`=ipv`hk_lLCK#2@h6?cVbQ3P!dFriXzn-fgkv1vmZA{)P|y?i2LV` zvlbbBCRi9a#8iWIb8|Z7MI#P)3GxJ49m&i(h8`R z#?JlnCJQJi8XyuFLrO;DeWUmCJv0bU0p~7JzV=XemWzQ~&TK+o_Q|z57-7RBajdMG z4xxLG{Ik-U_KUHp6xLC@nOx@P{nqO7yJL2S5#%-#^jH~wK1MyFpJkd+yasZ^UNQKa zp+5(DCWu<@iF{!mRb#PW{wdXw{o~rM0pd|MjFC@dEo#coyKL8jXx(cnB{LHJphU;z z+cvge0K;As;%JK#Z5JSP|Ju~x5p!QONs~AKV|E1(_%j#pr_xjs+cX9R%}Rdj=pG+M zPBeB(D&koEh`ZDKvH11`(+PHZvT?qO&tQQ2WRkPZ2^H#ff`lJ?p9p~-_z2>{l7Qcg zT=n__-3NR>I_$SIuC6b>c=TG>6&@jHUaz#9rM8V=BwE8xVRR-0Sb`qU9<@Sr?-q@* z3f(o?Kl~s>BcnS0k&>uD(KR=Q$LL1*ej+&DxD(52<9x8d`Bu>m>=>8rhOCu0J>@F;XzHvl`n0QF>*%(5yt1bG>2`{E=`b+C#=c*G>$JYUa2j;W z{AI9ij%|z%9X@7T`$s$oJ;|&N;D7#4iHc@wDV>rGtn*NxC^o_-LpWgk9k-loyXT2C z*&|x+qHBWM9E1tGuRSN`YfAQ?xkVB9!v<0ivK}7fgnwVLpK>^xBLb%bEI<&~O=KGT z(glLBBkLB&c&nZW%!YHx9?#XT6!P$67iFbbtGh2x_G<)5>KO}#69jj%PwkF=Zik>-g ztG5GWXc+aag{^ivEY1EJXZ#h*Rq(-0GHF3C>xX%S6%GFkTixtr69a-9;fb#j6@JUJL4@p%XXcLDSJ&J zh^<@KJ8spe;iTES zAohy{@B4+7Z^@$D=4rMXBWcOR{pB7Xh_$!1y}*@QPZUgG(2E_`Zq?;U9;}!68#h{8 znBh;?FzV{SaE^}eF}5-MMFRDg5{(-&Gcg$|F-m`IEE76+O@WySZevgK7aB0u;1Lv_ z_~`*3(!x<`+2yV)W>+r{!gHZvnA!r7%@>w}BSIf&o#v#D@FGe@g%#}T)Cr>T&^}%M z1kyNp9ZdO>gCUo*fz?EUGz;%+qbB5{5p_FUdO^ap`e`Qi-}7%OJyl6YF14lL{lrV>gpfjiF8 zRX;uF?(DuU@Pks^)&k+U5TMe#HfqOTW(ue0apBZgsi>^KP#mHgrxK!y%b!xMD3zvo zFOAsCqzxll1C6Jw!d)iz6?ZfNIIEo z7#|H5mBVsW$s7O#M4#j{g8qt_VT65P&Klx>uAew9u|zCrEhA)TXDha@G*>Pc82o}Q zhpGu3B#{dmUI{_$m;cUb2bm1l_}NNf`IXp9Jx8p4-$)0N*+%Vf+|FwW;XA?hAdh44 z&09#~WmFjYnJs$C9%PuVG5vfm;=#m3^pbH%Q8p@J53EBCH!F~2c<=ZK$DugVGkc@a zR*S81j?eD`pw1bJ}-Lac;Ff-!OKoiALr!g3-ky z7#piX&RDixU`qb>e@GOPRn686Yg>L$JS7K+M8q8tFjYDGO}?{+?8*{l-B(%hCA?yg zeEA+AGFOa7#7Ypp<`7@nKG`&~Ju5XU^60`IxT+VG#?~@}6LH zsQ2^4<~n;h2}=sXsXx-$r9fg}o2ylM;_4sU*eIT^i-UJJGay9j!}@6ypSG{-qp$u} z1@EzTBkRAddff<(9gt6zAauqZb|yeIfOm?=(1?SmUTD@)$A8RXIhR)7&B!?4s0uZx zH?%7oE80zIYv7S6o3E+kuT|H{ldAgX&%aT+S{S{SuhucJ(9JI5^;M6Ip>i+c``%i! z7_C`c(fXcM!elE8_C#P=-0Z!JPW}IZE9L*kiQ+XgTHQa=1_D-uXfolqNPdZKD8FD0es-k6OP-(qM?{2)8B@H2Vb@;Iu&}wEJu~?pji=15QLp%# zJr7q)>!P55IO|E#3X%UAkMQdwXyo?tC%e;U4XeKg(5GiB!qQZJ%+!LTzRF%N8hHt? zsaz{rUz@7W*@maDBAXPu0ut3lCP#UWRC{a^b?-Ja*`;G^DesllwNI7!VLffGF+6n4 zhR+>Vs!YSmnIf;U+h@4-*9L&$ohqH(Do=0|Gy$^jU*!RPexn&Myh6>a2?^P3Y;5eh zf@f^IsJ)u^0pOf@wpk7iwjj#&fG=0NCYXbLUGj0p!l@<(G?P<$jVcEIk}nU+dd++v8=!vZVZnU!-$*S?=1weK0O)va0ekQuof_$!bh*kqgla z(a)y8u*vhDS-ljW|gTJK{y#&Q#_Y8R+=;R7e= z8Q%kvfx_GgYNhZKCyD_1fl^ITNE1(G;`o+K`ls|K5k!t}cfEqfv!Xlso^ulS|*fR{f7w zi^6%o{`X^kD9O{1)o>Y}&ynHW#i)v|aegpr+|2n1%TGz#7 zVHoxUTAWB;X&weQtu&*zP8fpXJX}(I>&_49RISsk4ibacmX^xCy2}b7-s55;iO!jaK@(#E$1$;&5jHlUxShY78LW!rN+pIn(esAA z@gG8dv%ZMo`K$PnAkF+#u7j-P1Mo@`^&*d7Vhm6=ptas)cH(|?G)4UNpBZKw!beF3 zd+bkUIpJMf&&#~cHRV*U%gC$VXMI@&-^DfR1UGcjhu`$& zMtkj~r!{0Kvdaa(!iF$VDUmQR);?{i%Z_2Z9IU*ub$7hdqs1E6kANMqUL&@dknFb9 zb;I)Y0@Y&!kq6u_;66w{jWSbBI|Kism1k`9nwU5}>LivfG@0`cLaSuW(keC;_no{SA7Qy;~`{!)@|{tf}R<=H{BF_ah>4l>^g@d@6OfE(t9-ly;E7w!ra_$3S7Pg58p_3jeQ)XZ^>*tbFy5o76bg$ zy6Z^UT;#Z8tR{zFq3b}YRu3>W+&l#U*6ML?pC#-EA)Km+~bR5DL;b>6-iLSzHPWOS&sqQBCdt%yg%P3xYNt7z&C>-!9t(UD)yIi z>YFNP-&lv;A9V#Al`6IrtKoj%F(>c%|Dds&i!(w9ovCyuU{BVrzjk3{IOL-wD0CY*Axq! z%j1K@je$Bds%wDf*=HcyP`M;?WUsI?*7Uph2sCDq`1bteGn$I%5T%2X3dqa9r^yVrThid*(komk&Inn;539eV<3Q&86K3b}o4hAtHPKJ?bZiArZ|g z8BQ&;fPhlzRbC!fcLfLn`1TJgBh^YpmZ+(I7?W=@&)G0BUuE_@OEQd=PVDIB@*H#iFr#w_J*3>iW z1dd+c#KxF0shjs)+Yp9l9e^tyA!*rXUwcBF z4-9YT`Giuo?!ow$cLD{9O~P*?sc_fEN1KQ+H$TO&g}7o1P~X zt)de3AQ}ZqrSSLFqv5s?ldJWli8+?%TK7=ofOE3>{^_s2)wxV=h5;k8uNxIA5Wg9j zOA3NQ&K?uHCclpZk9c11I!8p{UcqPxeYZc#YPXN+v_JP%htVIY?IJeiLXa5B$(9Tu zFD%Oz$Vv=VMXO56yz5tyWl`~?FK+|!4K^_#jMDQX4? zG42_@63vs*TICmSPY{eoCy_4h%e!o%wzxXo;HJ++Evdrwm*Z>zz2=H5FCEH6g=8^m z0zDf6NMz(Tkbp%aG#3EmAlG}s!WVpzn?FFGw{@|YBV_cmg1_N-bn#uMj!~iIVP3rl z3icG>`4<4SjQq~pAumFQBk*-Nh8b<3-Lpvk{rU53%d!H(I4YM-c@i|cUJNY#qk(%> z{!8em$~;6^%WJdN(97K(HO8pX^f#o&3ymd?ByAt-H59`bm2tjpHV-lp^^b0jkU09k zk|l6EjQ?qayT0_T*yQxN)5*MY-%wUe#*0|d+xd~M`v%MMA1rm=88%xoVby!Xn;lpgN`$ErY_=yfteod7 zCeT3)z?YA!HOZBm2mjAM^tlU;U1W1P@KPk;VSk(W9DDTLi5Ude@$k(%DxIW$gd_`X zz-{we^zwa2M+fU9;;E_|(}PK~`|A(^GF{0T=QMSn)|J4P0E5k3S zE>yOU!Dce^|4b2-s#r*6R4Jl9l(xFxf836}=8n^u%qW2!{tTJ^4!Mia@4f&W6kr-1+pe74{p?#&I;X!LuRsF+sIDhTj=|I3V67{wP3xma{4kmYAU&3C%%uYXSu)ZkZ@2XLsw3V3Xf=(#goXg^#Z zWwy%MtA8BbD&-}qo;W^#>~K8k^i;`0uXAWffMHdypyVq4GqShz>{~NK0za7dpT7()VY1f!nZ{2EsLfz1uztD`uBq`;^=CEM(gQ7(%s?PT4K++bj z5wMXn_&p~<@vpFLf&IiNE~@j-teW3pF}Meqx7zE?COWB?Vy?Pu^ar;4v5Xg8g?&Pk z`F@EzbzgsL@?oXOFe&f~c_ch@mV6By1MhyfG>djZ0zz{8f)sw7(8;r|HLPku$-S5;qK5GoX0@qN1-1!}= z?XVuTzry zRk`P1>RWP9?9Kg$fJMvwF9f#MMA4V=Qz&@FzwU{Ay^J7=l+h9p{va$UTe1g^L(X(< zgiZA)Z>UPGLU3Z)d-D!8x0!``*WKa?;j@jiZ65JM^SGl$wL3wpYU2!=jt+KwBh1_7 z1zn$NT(UV8^QGg(XfiBI3@-bS?J9kcgwo&0WK-6JRCFw7A{LQG- z?-0gweA;kwHnc*Squ5*Qn0o$d<8F^Odv`v6YdY++?8GlN6ufD1JIgZ-HM5I67#Q_l z=qhHXI7Y8?l)0W>$cmH0sBBkYmDm_?O4L@9px+nc|9iOfvE1shgN_is$<=%e**~9H zLsK_^QL^5FggExlH7Rn_MvM%Ov(-z z39AAq%(2Lfc=#1tI@K=-@00Pvght9Z8B5QdY`a$2R6`gnY)ctAex>l3>M>g_h!@QM z5o^)4f^S65$ewK86Zbv8e3`225ee5#hBlz%#MJsf$;etdf zO7!5zAyg@t)N60=l$}*J5=$a|Mh>~=x!U@TL8_f;4y-%aeT=KF0QONjI$9sX$fac> z!+xL^Y}YJ+5*|q^=JXDwdw2w-mWB)qL|hr1H!%OA9BjDkCO@(3x^M{!L}h_Zu@&?W zJ}%g0CA2Y?Do_|tGP(w5Wjp(7XJ zlRTBLfAPlDvhA}XislT`vHiHSKt`6z4Wp*|MWg|M*u8w@c@95|C3e`qD7U)&CLQd9 zjPih|inyEa@K7RxvPkv7P)%b5%xjcNqmi!hlbpdZ$B1!`MEAstj93wKLsX-L(&Uz~77! zX9{M-q# zrt&>H1xB(^!8g24!QB~}V2JaHGtJKq3U^L@++-DsOS@^HvU-q4+?Y`VgxQv0n>?E7 z5AyRUg_G5W6ir8C;-`oOWoH!uL(akfKyJ#mEb}~7^|kG;c8*gR^k~(R|6$owkWuu1 z@h#M}jjEH}=#>~CD9)`K#kn=5E(TC`dO{m4*i2y?jxRt9U33ngqBw+8Emv#zRiqSd z#;eoXu-OQ#v6=7drpiqs1l=S*7Uey?XijLO8l{b(;2%{R5-_oof}bw6QKh{OZpXyF zxHC!@IdmBM)2Il{8Bn*f`aU#x)VzwzRNpt4wJx^p)vX>jEsKL}P)a0<891;P?h)TQ z2N|`w+NJ^@r9@IFwkH-&-Obds#(F+y7g$=_jX0uNRZ-CV%lBnQAV=K@b&|C*|K$PE zxN)nC#*1-;dYM20*67>cn;XdP-41PhVk8ueDZ>We9igHsdpdAJ2Cu%%Ic-4$*Wz$b zMAWsIEYQX&5LSu97#NjdW0l8)aA=L}CMdMMFDgOe2(YdC6hEzvn zwbv;9+90aB8P3|POjpF1sz zpneQOrA3DPM$aZQH2lFZZ9e%q4mXxjkiBuwibW(ItY=vv)=DmL-l5A(C?5pwnuBc+ zgWH7Qm*5j75E6U*PaU*mEHV=yGK@@+WIi;)`0e0z?-y4e?*wlmVZ0Gtdu3o40sX@R z=)ye7R^t|7NZAlJ!wVE!C zX*l3`g+nPC_vatp(r_9=qz6!9KFK<@o9yN8pK!ar3QJu?q^0$TZ8vl1)*E1{JKFlTY7=kL3L? zaX2qHE6=sbKNx`+<2z2>c&C?Q=!8L=3u z#%ygbXG_<0IbwLdD z3GaM&z7~9wES^c^t;Vb_kf%o{p@eVzIiE;9<_{3I8l3)=$X9M=8#>m1amY9O%_Du= zizR~iV)aV&^rC$5>3R6jNQ%+G$>qV%2k}?LLgQX6gM@q{<_=xvw z&kai`L`bo0`5MDtS{~5A5RjI`2$ z^}A1%mJ>e0l>|1Lk&6kWgg)IH%!1W_T`;9U`L0@Q78bEvXB+dUj z*gHP_!{xx_Y%Vrz=ysPx*mN8H_`cQ@#$IYeDrjn+8POA zGr%Cl7C!({ujxY>XSTWO6Rju@APLJGHvShg6E7+^{OO=B17HkCTze_1hoIcDwoVpJJo5PC>t; z>h!1moys<}x~#5nrwVbf8;wrwe1d<#ZY{@mGrYF$5=C00JBi<86TS&3%FE@dSdl~; zJ_pU;RNKfEVJTRmkT#<^)CvJL!M|hrjB{4B2#x&=c$^yghiTh*3dzfC8XDk)iKMGp zPW~YP)UV>Yp;)z-C|2!%7ix-5u$K4QTS(l?7qBAHf_tJ?c>S@$dD!c?qvpWin}!Gq zxF5lz%kooG9Oz5$=9O>V@Op^@hA z-lVFzUOBIDP)wkCi?H{?*Y{n~?zNYZn*IlSd1Sk7S;7lwA3ODgT7E!Rfq}4gVGw~W zS}5OWquik}NI8{O*axk1K2!*J-t1K5uA3S`3>8V_TEC#2T5si;TH^#rcqaP8cXwY( zGFaViN_rL*zhR0Md@mJ6kL9G(yagg&emos^o6-!6L*P_s z7LUGInRWJ$NWH*P^X!#~UI&`0mo!mAQQBsw=js|4Q{-Q{$2+Is6bH2-b3@|mmI=n- zOu>k0RD|geA(;f4$3db4vAjH~(r$^>LoJJj+>=Q@j%*B4jg%B4OC{SJZA?E&N64ci|?!~J+!voG6O6gSjXabYLG4z(K>Z?1d?!=XDx3{Y}Zg%1qJANb&QGB=tX-nVrYZexz0y3UA8TQ9()u zKNfH5zCs~pYeh{^X1qnLuF%WiVf*-|x2W*Y>k$t87y>~e2>TiuoXR2Y$bW7%eMl%LU8e1tbQ91uQ}f@Q4qB-BCSNce z)!H$=Z@i|+_08A(57UdFwd0lbIL}9kBu8b21^;30`QwGiTg4|*{x!vNp1plXjg$8J zErjLx&)14={H>3;2M_L&w*hba?~bvYqyd7t33rI{j9E;pheVRbz+j`dv+ZRw%gb$z zOa&)A_9rL9nQ8SI7B~BGj7H4Ic4`vykKKExPafZ1gxxCO=_KEE*&9wu&6ET~_E$16 zN38MJZ8X#Ca|XA$1N=8aE(32lp9tw|%J>RyOglt5=d(5L9$vcj4`KipUuoABzrr zEGhAU`>-V_>-y1Lf9)NgOXA+pen?+9xycj?f3? zA!N1djx#Q&>l@^f6ZcV>k80*cr_1!l57O5d+@(nH-o3ZGYRdV{_-Av_*k$57lumk~ zD;^|95NjeAub)-$AvV$}k9g(miOBWe)b}~y+$l*3id+g1sngx|(`E&Z*>SA}GCbxK z#J1u<$pqMUDfo2#IOufcIA6ey*9t}_>5=qy8aw9_R~uW(ZBM$Q%3wI?V!YY1`}Nin*Xm*2a zkzq(V0U+{RcT2#st{b_AL-`+fETkP0v27{`j_`hbn)NSg-jDs~4)8)tINwR+aDzn&PUtzu%cWt?T4e zsjfF!$0*gz1W`KKpBr&(SK7@mT$-Cz`h+F+v%O8DLaIb|bqk*ASlmNhK{A(4(N%sB zd^I1RT52&Kf7UZQTP@xoji1m$ndUC>>1L?;7e?|ys?fl`ZOA63!(#8Sk-UkCgrGP< zJLJ_j*6Oz~hO7dwjR7Uc?_jCGC$L&5seh?Kc0#WlJ+->J`)|8zDS~8OC1?j9;M~D} zH-SZ1e#@4ZNCT@d!jRd9a>DdVv!Jv8}>rVsFyo#^6#`Qut0_wa`VHN1X1_q9_LexeCSO(X- z{BnIuS-H78Bs~p_P*`g6Z0`%B}#(5V6U7w6tNa+9IwT> z$n{ND?9}&m3raZOPnh+~>qoOe!HAfBg6vxhfz?ar{H8YwRoP^PON`DDb3tm|u@z#E zVzqk7CkGnBeSg7bY9Fs^!J#PB+UFP;?M(xg96-@6=z%DKvH#xpz_z_5}Fw~FHuyQ=^=ijc8m&Yff;%V)^15)|1U29sUF|LAJ0uZM35m@UkTDw zD32iK$gUiu61!nU@0kEftg^~6IRV`jcrUy1zX&Qi^t-jhCF&iz_E3Ck_!LeqP0p&r zW6!t9O;$ypt=k(b~1xE1n!W(&<*n4|A3>+lPGG%gkBj)3+#d=M%mDJdttnc~|-&1~K#gIVMJXhu622 zCE;CZ{&}|#iqrAbaiKW6vp;4F)-r6vl~;)P-y7sAxX}&Z>;6LwqQ7V70X!!~RlOT&+s%+_07 zw8rM(JiC33h!x#8}kjk&3-zcnV*=U^m1k*8(Z-C5?ko z5sOXSODuPXrmDy!zjqaG-f>H!8bC|%es{W*FTo@>k?0LwO_)R0&zC`=z|~7NlZ0hc z^^$V6ug^am{6axJW(TLLuv%Llo1jk?I^$PmFR&$WGLW&vGW(2!-haNR(o}5S3;hC( zJ#5G=?eg?tY#=Z6SB(m9?F_9WkoX9$Z9*QA9qjLPKnI5q><8BE^R38Bj~^<=xcME4 zilLu#wB6Ek99dgsHi^9q+N|EgL9tGtgWo2D>`EB~g@i?5 z&=~^zy@1w`>FSG3O|vQ!UNFmPtyY7 zi@W&&%Q%)7pISgs{5umqFo+THCaOOwe_$MlZJhESy}l@s+7V3=r(;{?;CuwEJlYvDJ!VH=6!V5owy0Z-j8OK z4#8>6C+dw=Bi2}~5wpk1bJ%PnS=qGnaIWbAh*hau481Z{f@ySMBw!pzyB`x+YT6y4 z21X9*NXn?%OHnERXm7ju5k0NCGx>%i40P}Th`>Ih$CJ2vS*%R;j6xp=0 zgXg8=F(6{%z0G=~W*4wi!(S&4+~)KHg0EwzLlxvm>8w#$t2%DqXF7D71H-oZL=^aNSqsszJr3uhQV6asC0jv8G} ztN)EEK{b=bUNM8f*EX*U7X3Y7m;fl7|4$rrZ?ykcxv8J zo7efejpwP;{^zlRq2;_iOre-SEUr3=RM?qXE4DNBT9&uteeVu-^(_#n=}Ph zo?O+%aqbS+OXWdgsmcEEqqNpDCN+RR21kcBwvU8br^MxKo+%{|Ma}sZY4-E$7`8kq zl)@sW{!^D6vX}4^hli*#)D&x4Qmpv0F;2i50qRxyR1z#;m73vop{d0NN*7sjP6E*DA}ocug~#W=W`AjSFCKx7s7;T;_*#Rr1v zq%Guv5;1NOXikQxTi+rQEcO`CvEuRtWc|PNF$2(bb>;AqJ``f}${R&1k2sSsl;(KO ztIJA;jrTym@1Ju8-=G+fhaq;`=iP|A3nhUS)4P4Ws5Z|}0p45)493))HA2L5pOKeH z(q)g6*g1XSpZ$o75Ga-Gm;2RAQe$<)P%A@Rm=@rkcZTd_I}2Q<@t%uWi?hoqf*CZ^ zz4{RPYbY75Ma@2xBDaE{+R;vf*qOdZJw!1NlxwAP=T{dD@)}FL;RY1XGDAqiUyR<# z#-o3H`2l)`HY3~GsYI=R>F85iN64>et=b1v1%W|wU(}0~-c`7~Uvne?CX#&#&+3i4 zRU7ogxcI6$*Ll_AhTe-tv~mk=!=$L!Sq{a=y{Ba7*}-RqiU{wY66T(Fm-1Ep<)I(N z2N2BHH-b}BF?XL-;2KB``K8Y?&1K)V7T%W_`(UZ#HVWRvAk7Wey3)2eN!!XZ=B=@i zT{xJle_x4%lFUSO6nDMtdb8aXi>#l2gzxT9Dec!30AjQz?{&E-l>uO%5MfW&{N(V9 z$E2YXapT*-Cwr`Ix%*H$=dhWy1p02n@Q#a%gBqbq#3uUPhmSGJE7~K> zBaZ)kbs?}#aOx~9&7>P)^&5ED&(fz8H%+o#hJc2f9OXV=5&2e0l zPrDgbY)Nlb{C1Yzf7J`ok2AYwy{XHI<0?h7(gHLr48N9Zkx}BO1N6(~J{47YF9P$z zFA5lW@6w)@_DpRoHJCv&i5DzshteQZeC@R7~Eq8#g_o$foKd)n`9uPH!JyY&bU)hkl=Vr)jk?g&%(mSYLS2e>{RxD}P~D z91%QTi|iUq<%O9q@tP|$5v(`t`^zV`O19ow-QRRyL|}!Hz({7#3QJ&>W2swjiOiF# zN^G_u-o0$EJa5TGv%VH{t;|n7fv?}dzf4o!ewV5-xvCi%I!_r8dHZ4^e&19jyT;tn zbiDhia}iV9^;xCeTft5z!YA-# z7dW+&XEC!$j637V*bUdJqK!~aJGX}Qrd_zCSeBYR)?$_B4Sw}H{BNkygv;ZHV)tIg zIEi<|WGM<4vGqs^@lvY9*2+z&26w=aVKvi$dQI@$EH9xBe;)8n@L|nkD&`Qj6hqlX zy#M|t@!zZp&t}Dl|G!xk6`=3*e?<3ke(yh`Th=Xd^dHgv;&AgH(Va7;xcxVAb0Ey? z`#;Uyye8tF>VP2Kj<7(Oz6`}f#nDt` zfLO5ClyQvcVn9}txYi<@sAL5UwJi$4P^uhsgo((TCzkY}8-L4Z)1W77D1iTlR}+?{ zrC`T5VAEoKz>+7f7V~UyWEM{q^3)n|C*tv` zBmK4+3=3~;3<=B2-xHRVG7 zF~C4g@PxhU++La#eJUFE=R%{!EHRHB3Q<4wB@dM3P0)1dz#Tf#UfaC*CO*$&Ov}U} zWG_0!Wnh#b>bbek`D=d%F_L;@;po*6@Fnc!Jf=GgvQ%*tlH!WhNna+?Frd)^>{CBV zJeGfQpUo+w$OimFv`i-cgV|VsFZUj5^Z)oP{=EaDL>PULf0O*smI1MNt5esgJU$eTLOPYYNB2KM-R9P?dSu_X244>j`RV zjv((TfiMb#w;{+X{+Dh;#|Ppn_5sh?Mk8c?1oTxhr{7Z& z;U#Zg@J8(VPhSQJU&MZuuB>)UIj=Vm=w7S|K`@i$HjRB|K8uEKe+XNxt-%UN?2~v) z=?*~zOFNzZ`ALbZ=&!ABP8@dL+NB^xk;d{0LpBNo&kS8OPKkM}wz#;rQ;U{vL;b6; zej`%`sK;iKn0W!<+%K`noV@)XE+Vzv+h4rrS~>7v2-_;*Wr_ssXFn`WPY2gkW7H7J z>IdY3xd$reDre_SIEQY30Dx9MN7h<%L{B3yi9?6ArHoZDiVS+OzX`K>i_C2VE-zS* zrS(RhRhKxqG9gR0g%71INkmic}eS`Eh(cESE&7GX_^Zu7 z=f&8bA;+g`a!o|Q?paTf27-tZec-id25D~g)!Q6l%-t8q#Z3;U{S;KfXeQ)N;)|j^ z6mD#o-0W`^nik|+mIGL!YEp=FC{g(G-=yeanA|gSG#$FLkTm}vE+yZR+_H=iPzZST zbiSQ9UVL9N8EAP^b;t7}Y>U~)3|w&dG>qJnejCC$J*-i@Ud~x;^vCVQo=^Oz9&&N< zSOZ2E1_i9H#E|>MlH*z_OZu8M5v}o8j{uh^Jqh+E79v&>K8$eKxllO@cPPaX>^d=1 z!%t+?*1-J0c*2`>Y-UwCrdQMEaX1xCTEcBRY0=)Un{#0r!NTaCfViaQs9Wn*+4Y9z z*Rr~{e4TjJN0K|Je3m|_wO%K)N$!#qXF>hfqqTEcX3i z>?D>x;OR>9TH{@C!~i>rmjqAdn@J7AdtOUJ8nhF(GHz?m*(4AIB8nWpDH_PUETn4g zLj6|e1D{81FJ9O-f4{0b3Vc2*e;G4<+ZoQ;fNB)q#D<+t>Fg~Fb=b;t90<6^-bBq^{JKg=qi(f60jxN;OJ(mq+%enj(7DT}HE31o?0oDb(6Cl>S~$ z6Bnq^{*}tNq$j&&IK0C2JmvnnFFUi-;0~`ymE*GisH9EDT1UIw7kK&luWqZ2Y0U@cLId#-}R@*{ERPVyeJkgKJ4?lBE!R<33@Pvoo1^j5n+GKf% z`7kn+Y7q2s^~fr`HYBO)MDr_lwlNjK`Qfu=drpL0qpc+i@PdpV9d|sBgR4lGQFPgM z`gnYi@=uKkLZdf@M)EHeVDPpK^(UubwYel(xoCP+d8^6!l^zx@kW5MJ8-_5ng?@DMOHE zc2?Hf&HlW*5t8jSM|h|Nt{1Jp#K}^-TD7zb39N#nr6q046@vo8kGJX9GqhH9WAj@C zO|t#VeDp6Y79(@RCtHPo+~T|E&Yf0JQ5iku>-X2Ol-XA+LUbVMrZt{1@4FAvJ{q2U z>{-b}XTT@x2iWmuh?svX+!XQ}HJ%nG-+KP@<(NSK4&-MqumHC{*BGV0fPwz#CLQj8 zKiFisoSDd?%sv;ZeJr|%rn1O$18IC9kJTYn`sL{7T4os**L%BRD5+3fniw>9`C@*# zuI+$}OZ9cbpB)xG!@`fh%+hC*zw)o~anA0CE`Ee41UX@0;g#>QEcPP8ba3_&*D&$= zSU7J#NwCNeZ~RbdWxAHWc2=$--)`yNg>96-zPiuQfc{`@{u#XGXfQCwow$Lzq*;i) z-O_Sf^rPUo_;yz#33z~wz=s^ips7Rp9rd2JEkbFtxHwo}@k4QB6k~m*r~Dg0F7Oz{ za2b9zfZd_Ns&8p2{yL0LL&wyLe)yv<1{*UzUVPPnI}X6Cz;?%q99fQiFUn+P=vby< z@Y><)5E8I}6H$)sjeuEK%{wQsBj0g75BKzw7F~n-428@L`aAc2;LGC@cK2r%xHH$k z9Rp`8orVph4nyovWz(R?lAi@6mn_- zHuO7OKK#p$-j^m8LcO1k#5(?FY8;C+HQ=k-&-o#{3o`9#{!yH;(r~Y58fXZ_vT{8! znI%^hCEr`Zr%uZFmb%iD<)hSl3)@r+Z6qJV_494lr`1z>~yP7?r5cC)P z1eyrQa3dRR)}szs3hG*|VgssBX+$0Lkd`jV~lj8)BV)hN-e`)RI_R5r}?6F6VM62w> zx?{K3n*ohHc{&`Sz%*=h@#k%YGG~JosomzfcF%wngMMl3Ay(vY^mjfv;z~LRGqbb( zj@#}K(l@QsR;+kY@QhY&OFqAq+JHJ1C+B;4sTIs49>eIwH6DZV{vD}>FgKaf zFmwn2_v;H5zU>cOl=AUs?exF-1*QAgMc;7w_PT=Z5e?!-YC^ljm;=o;3>LiZ5Q2Ntiw~BaW?@)eH$ce67nGUw?xogBeLIvu@ugJw1c(^ z3aDup@2IhNVyW#g!}U#fkV8v8>J!Rujm_W7y(^ zL!IWGGZJSn+5Y~0wgvcTV1pu*oVWVc1)%9IeI|As{3rEC4hudXXxkm&b4A5%Hx0Aw zg&7tsgm0jNz*tNHc=c7Fm@MGvn)=X$96 zbDl4B=E5FUc-eF!zx}NCbBd$K`~BdnWJ|Z4z69vNL0gq)=b{e3|11 ztg56)q2BahOSD0z*~3ePw>L4i%WfYst??$U=?qzJ&4b*08;V)ff&9Gv1#GU9oVGk0xV|oxCnT2kR z{zZIYS*p_YJnrm9BP94u-`f?l_dpo*iUr8vCWw{!miIVo6}c?bL*a3BWlm#8_@1@| zmn`h4GYDnu1Yen$`I~`qnx8&t>>OUbn!f}Qxu`>ll`lz@$Sv^xITJP7|L3+bfo+v}_b^D+B0_g4xB6gRs*9F{RVMGz4jguDIy512ZqOcL# zESR$($Q?%+^P8ELV%OFZuE|q9+sIKlXY^tl+n>PYY|T$O-KT^!Qx()@aZFyLG&z!C zEU_5vu;cTUvHEVP6*_u^fgB+EMBtEyN-IL)ukfg{tL(#=Xaz zYUS9JjD{NCAiB572)(?LYweb7&w$r)KUD!Fmc$WhdxfHAmoc|m@_KFN7*MevV+o-^ zP?V$Uf303(!WL)~9?IRR%d@$Gv6phB9oN&gH^`wd8S7-iNnxVF)+2R|;D23mr!Yb= z^qMIbq^O&FuBD7TaI3xkHznJk)%w?$NSHbw2j$;?-86c1QZJ=ax?;(4vA-IlI^oRH zlPi+v#}nmEh|llARfz_pD`t3tZ8ISFdyK&vM;1L^4zp>jpKvE&!swm?P+~=unL<|+ zC`8dDckMovL2fG9Ck{;m>{Th)-!qUoFw2mHwyGSe=2Gj&%aG00m&r}#q4a7a{3z3{ zV-dw1`e|vwRcHPx+el1eAg{wk__d%e}r1D15vMU(KB_b9e4O%>=wuWBfg%3aT>a^S?jiY&SO? z7k_c>dMeB0bxgBUuE22l+rZm2V8p7n2}t{qR?Yll?7W%(?**G=nLXc|9L7v%ujr2R zPjf9chkqW#r66`c{ZL!hz_&*<)L+2(CJFGg^~RH!(|k2h!-pLUiXtZtx#Vj~y-kYNHGmumPtwy~wQwOi@+XG@V% zx3gs>7;`y-a*o$Zdsq!y=2?wf&@q+whdWJ}ln(urNyCj!{0)khCjEeNFTY8m=LIej4)jdJU6bFfeW z9kE1fk%g64LuT$zGh8=#dRQJo0gUP!djWY)4RP-9w4$_BiSu`8Z3xs=Z+TB@u!Bf( zhnBJX0bD$O35I3v5c#*@o~&+Z$#MZ>>b@7K7JK5`cb4%8FVb;R*A5$#z;iDg<<%yM zW!ANKS)BbX!4N`9nzy{uhxgg>kfu)HT4#zq{$%NL73e#9GIr7ipPoAs|& zHuLr{@`77fNpZu&JVT+beW@#}U$!5%a&Toz4-0RmW`xACP_f}wgdWyzAKe0wTDp;^ zJ|j7pb~=22f_mhPgAqaEk|%OBQ47v6SkB>UB<~LMqf_WJFGLl`VV9jQLI%(KM^Y@f z{V4kK;^&CAGYtNi|HSw_!98d@XZICj0uiFS4UpwY>KgRdwnLdy-8I# zSjeo+97&=72D40NUQ*sW4{FszWTQsVj6RH>RwtNFrV#ur4L9&`u`qUfrh#TS1JZ9W z33F3-?4Mzx?9=r?`5t%Vj+w2O#hywoO7Cu1@t17?>Xf=srnb3J=9(XrXk96D)j8ze zlmD`X_aw8}L;j90gAWJBV}4a-N?9K{Vzuo?W(u&^O;Kn)uc7`ZcIzW|3PXqWU(slg z2;J|Foc_4k@%2jI&B(CXraChwwF#Z_?qoc3xQQ1J_C7M}{@jdot)^PQ%l!aB)L%e) z1-33>QgekB78*=2q~=s@sP%z*zdQdIntcV?O{p{LD)|{qDdv9*_w1AHQ{p55poTxI zDG0S9z-%wiYtsuxbSw9za#ys*RXmh+QYQB7!X8`J4f7$%8uFl7Hts;Fwrb+! zwJ~HZ1T8h8!k_c=-d-FwS+A)?SnX&Edo-<%j8tB&atHuK`L6|8s}r~orxm?J&TZjQ zQqXy2VCyk20*z7X=MUth>{SD;ZEszv9ZvNc-G<67hzgOelQBSqrULLT!9C3tGSq#1yDIEfzUtc3fD3g=% zv4TxU0ceLmqEIh-VG6L~(#*5_x+bJn%1WE8c#xyEsOK&9nZN#DRz1Ppw{KcKejn;N zD6=p~`Q!t}zFsZX^g$*+|@jK8g75FmsTl$dtQFUzUdm|Ki3%ZsjPnD!=gJbp(_>?2O};~=1B>Oxw!UR?B%9()6cz7suG8M zw>GfBhS^>fNi9i9i#>oznuOfGf)GT2#!1PkEMHAHL|dk&_RYG`xITSJ&BVwgk~@RN z7VR?}B{p~=d`Bm&ut*+gBSk-m;}0W!{0O9k5L-cBD7*OqY|jb}uro|2i|2;-7^JAV z21hD*8rt3zb2Y|Y#5_J6T=W>B!IAqOB{-e%{*!Uo0ZX-}ScOS^`HK0BGkTpu@|Dr( zvg4vto+X||7SoR@R}@f~B{e*+NH?ve5eNRCMF4Y?|SWi_M+WkXEBmPumbU8T+tWXk&v5 z;NKxdl>-C;5+3RCkPlbDsTxr?yXOT~!+J96bXD`;uc-)s^r%%_@V)Wte7e@!*?u;d ziTMwru`x38c;*$UFp#IlTU6w37aghN3$N&~CL*g?iLxf}hp0Ft;93QrY^={q6!_a@ z7uBu7)$7=QS^24>gu1awXfQ=sZ4d>cjIo(SD=+n}zTCJJ<3tpk5dmU#GR)kLf@9mQ zjHd+jc7R8fXu!IExKD6`uzn`xqUD`p6)+t<^2pf1kQy#yMWKcmT|#``VhT_S1+cI( z5h!~aWmJD*IMtkk|knu)Y-2g!3G0=vl6nBo+iQWuC4yACm5_2g1jBu1WPh;cgin6KJzDXbbMg! zeHBbnH3I=-^9Kww1xvKT_)uffWyV>g6gXT&O~1BHIemund5RNZs(#fQD(Qu<2Ti_8 zD23Rbzh|npJ_bEGZ|Q$E{WFL$@!I|%Lu#lwzkYkZw1ofuJuQbAng5kA>JY1q$4cuL zcAoB58AC-jYG)PV%~a}&4aumI5iOG*!F7V|r;kqhu6?ZA^kiW~x826bD4lK@MF*+9 zr@Ky=4zP?2FAUxe6g_m_^?GqN0M3kCB1-ylL^A=N+H~(utgB*`D&wr7*Wfs&-K?63 zKdX?JsY9EM4#8m;Ufl*m3<{C{+w;w-+w*n3+3JYbfk;#bSfbe_w8gF_bfM_tPy-mG zy=M4kcD68+opNY&VSUfV&y~gs(gm2IClNOhR)3l0I--k5gC3T+ggFmA%RZ|S4?QJy5XXX41eHbe%$z0(!AGWKOGiLLvjK1=ghFcX3)KZIPY{Xq-r z$nR6*@`sO|g&JX_{$3^UL1K1VKpTWQ}aiX#^4ox6+pAu)3*c9+4mFWQLb;hS<5^RPRk{)`= zX64rw%~OqEWY~*d$cA8M)3EdCx%E@)@S%@EhT-G*XR>z`tO;626gd?{k9kX`@9EL+ zI3ldvzJ;3~<4B&0UOf_a920}PaVCGD(vb1=HKTxv%$p0eNCnWg8&`zmLQF9Vd~3qo z4Ddq*-$)StLclTXTUUIhebN}DoNMS`%|`c-z`U{6&9mH#8tOI@3YA-7vdBU`8wo} zwG0Xioobj;%nV+3F3m$&Zk&mKi?uvXpW^p;$gd~h^Q}E<(`2mj=~C?5GAWYYi6%FVtzk2T+|v^?1F@ zQgp!fnxhb+#TAEi1*({WS9({w$t^02;1PNOmXkSxjxIf!-&XX6=oEf2S|#m#_7Y6H zO`rsX^gQq16weXn<{Hr2oIst0u+(ntZPp&^^)I^FLzz0?n4nsoVIZT6dr+LRq0iHo za1P}VUH;r=1KirWG{x*se%}mR8BsRF7w@|Sym_V9bltChF2U@6qE7yNz?;E&l@Pi6 zEA68(nzFmX7XhG`r{!n#^ShAcM4E8|o`EHI*CQv{YWA4 z&`a#0?@Z>%S=3Syii*pHb-d09<|1c$%rmM(vs@+b+_yO?FqtIvpO`F7FV{LS zB1`75G1XQD!+zt9)T)x2C+Okeaf%l>mVS2HW0IC%^JX7`tfo%a@M8hCx#Dn{Y&Z zPY`Grs2mr{;%LO&@=V=)@#myMS84BUB6`FTh|!+!k7=yp(isgBzZ& zlwQ-*1uDxH&56mubAb;Xny;3twilg42%I7Oz8d#ak+paeznVd=q($8_Su<50jV z&*B$zg!hg&qP;A8A1RP@Hd~Wpz5NRS!6qW{Botl87~A8!8}*exUG>qzsh)~$c*aSr zKyE2Y*(Mf=zK~ut74pyzs9EPZU32<8m*(oQ%Cpo@9i(MjS*Ag4>xSSm><_1WD4~#D z1IQUjt~XWHxbNl}Hi;9={;7 zTLm&ebS^1B?t9>$LRm7Bxr|4m_#95>Cp+73*?G!8n$t95bequ;=40PxuV1s5xECde z!JpX>QhN<#;|vyNXRLqc1F0dd5-$qdsTHE{Ssw|z5qCuPK87?>9xkK9eWDzE|5ben zPO@llKm_W=%q4W5E>I*gaYkyx4Y>(*>o2t)WGKDI$H~IpK!qc668}rdj}|1gO+6WW z318p8_5-VdOF~NCyqZE}-&e@!XBS5M^y|w*HhEo~wV1!(rIwVwwzic?@GE0(&SZ~n zn#8N?dK=$ zSICkZ3#Us}UjS*3q;jFWQ@{Bhx^GszJO~2113{QgCHh^F1uR)wC|~DYX2sHM&|dB@ zxnqDvR?tqR1-(k9(}vG026xb!z%*?NLC~UL%v5*%P|t@DdQ5yjCh$f?-1+(H7k6hY zw@ri5&ee9?gijrI^-o?;nsXTSO6}gK%qz?9O?+mQLoi${?Of&_umnk*f!m-%O8*C% z;T*N&$EmXy{!WO`;GPEb`?Wuc;o#~0A;VgBM`%&d%~wGJ0l?GhS1c+Mb#R@>yX#OC zZ(?Uu=^|!1w2w+sQHn#r`$x5jHF8#KZjM(ntKckA+m^qbj{M+kr*S1Tag1xnXbu&l zm9j<+IRWzKkOw~&gm!4Bh<6rP6Tx=KIj#mk6;vuEfz4@YS#S2S5Ko>!^-eTu03ORA z1p;9u?J2YCQA4R(_rNRw?{Ttl=Q9dBS$@|ID?XRC4_VVwZ?CQ(pxDc}w#1lk@kxZ8 zbT+RmnzNNwbesWlmh34i`}#^({nE53g=6hD`ZyBNw-fZxrw0TqyTiZen4ho;X7*+U z=TbgDb$$$YcG>1m!RWou#ulo`EhW?~BI=1~~L+p%y4*%T;Ds0ZNf~*zpwStc-!xtMq4o?)V>M zVZ?B~39QGgBF#m^=dQoPf6~95=ghzf z2z#+JNuU(Z*zmw@e;HW59d_LaReH?pg*FHh{ZICov~<0RLKj^dO1fQMg+?xJM;P)m z5&+Lc2I^&7B_{Jxx(yPY5f-Y6$jHp`A4!FubDw|+e68(YE<>*Z$>4GpNVHHyjonH3 z3K-n;zLu36*4txI4DkC;x=@M$zZ7P6zN=>M1kp`Y2r!!anlu&oM)mrcI9YxVFiLrxjKAU`{h(_pZMrmVuzC==((@8^s>#<8#N9S7 z2Z_o>wnCX2Y!#5pn(fGeS0mb?snv#TQ)uf|vA4)xYbU)wL8hDMfVoHbtXP9_H-p6K zq>@BYYoBk0hX+j0;cw4a`z&EEYu>abN*V6R*j<*^0y)WdwLAvV^7zs4SSGt zA@A#6quO}n7P(f_ii#>B6>&t|!tJXRJqpWkauoN>Iw2BH99uZsVBz1iE+BlF563F# z@K??xpssI{<>GfKXzHfdgKiRMmE`QJ`*P`&X%9YD#1tiOS&rG_6DlPgso7>1*oxvt zV88W}mH|Jzsb2Abns`DQAq7AV*!jyn3A7P4xS5;64i4g4{o=xHJCy^~s`CHT>vpbFm(zMoMNAJugUlGiMnxi@8VAfkd4ll z@n?)vX%^-7rCxaCm;;}=G8LP-!MHL&5i&Zd7`_c=r%VsDkZiu4QX+f`FV#lrZ|&bl z4ZJHxo<`E!dRC?GI>U4iGH7#R;%PKi$?pnOuFdN-YfyLkw%xN(>S1fwD4gkizWOch zj5d7IA{>^Uv|us&VGnH_?t&&0=G?(>ca50<^wK`Vyh=i7X#on<1w3ay;jbK| zRU1-S5$=p@Hs-j8UW2A|W5{tUtu$?U@RGWK!w4)ZHXMv8kqXLZiTZR3nbv;LPliL& zXK?8hCDe>_K0}gX;xx20AgH?|uA+mks8!)AB6`}KCE7_;&T{@;^v>_!&FM}b$yUlb z8~ce5i28~=c*=GSF@r_bXdw3Nze)HaPZw(l+6No{L{20XTe~$Cnh6=h)p{soR{)r{ z(8ar+XE!=0T&L+T!tii&3oywZF(_Vjim#!5*}${p`0S<#fu(yaG#y zvy#Big;13FyK|mV{|=|bkw%`2zY$2AA4^Ej4igxXB6`49L^H6ZmVY>18tQ<&b&vaB zb}>|F9PdxE$}6k*VV>iQgQ)wP!=rlyKYawSD{bcrdxxJpy+^SUqL}(-n_)`?HT9%{ z;V_VRxS$hgy{I#-mb3^pw&6#RLmf>JsQije7Ku(_l_8_RrT5jiUf89>#i+whmVkQc zC?8n;fH1d9;{+Y7E7@^#9JN3=_K=IiRA6hbhH}-ZYzkJqKK)KRdT|88Ns5L<0 zDSr|$jsU<|+f5b&T8%Y=-k4ZJ22<(3APxk&>-b)cZvIe&|1w7q_0g~r*cMAZg~tB? z+g#m{fMdXQ;ZY#kdnsPO`)NBZ-t`IFUC#&KQhPp@26+V!jEOItN8qvrfnUyaks~V1 zz52X~Y3_(cR$!+mNJz0|)Icc~@XL!nG*OEZ?wu6>Oy)3BS+{jOg{XzD8B^f?x9`)+ z8_A%i+!s;TMofjO>ebh%B--(kXl&)7c&YIjnz_zlw6f1#A$2~m8`twR&{_mO^QU(& zg?G9jdapL0CvU*A8%V6F^b#qQsX4MlFyJWB{%e&g-84^&>*fa8*Rnefg!4gp4@DI# zN|cpYGAhf_NpB@+N2pbKjtX2~@Xy1X{?0l>33iqJBJ~ zyI6Co(%9XRVn-P=Y}eJRtsnlRhOdRXDYjdnRq3&ta(Wz0$bE?L#XW*_K5TMBLe=xJ zsM}F@D`Z3NjfY_1TEdS2=tJ>PNvk9t?d|%ZxPRzoh{aH2A6qZ5F#3NjAxsc9O3k-1 zt3*NEY(^Y^^}YY`PtH+ufyPQ1PpCiS4jJ-xM~b5?PgK)vDV!cTq5~1WIkoh|S|c%r zp)5Muaz#a5g=bDcOXUxcOp=r=3BTW3Tb2lF@|XYJ3qbrK4&`hTe2lKf<8x&;qPI!H zBy3Ol330-jfUM9!T-+J++)`$M2`WGYWKeFS=pf253rDNFQFw^`W|RDIH83zx_MQhg zzNL*GXXUO?&vayDCgd4Pk7x3Pf8~Q>>7nVi(c+c;7qvIDFkzI+?1YL|HkJcAK>+z6 zko9n`DwsNNQcBA}SC>BIQK=qX%;k(|?p-M3Im?5@?wGPR`T+oCMK!{7=Si0~JT*K% zbP4?AaX7A!fss>Fo`|iyw0#{!X<%N4Yb{#^9Re?rVnpw*!O(MS4t_*++hLZCpl7X@ zgJWjj1nBYtfU%-}4Lc=*A!j-ri{FbljX$EoEF=H%x(-0z35e`PupkO|w{e|~Gp{{* z)WMiwl5)QmB5GWar7cG`zbpIg4NqN)jg|HgQ}0OGhY&oero6O55pOqPxPyh2t}pH{ zn<)mF+5=IpZMzi>PHQS$0{tKrj6E@o-vMWbY#{29_^0Aa2vo%Tcg8Z{jmXUO!u>!q z$kXIASNN0t!wq-TO$ut|Pi;(T3I!*=A`Pv?m zqzj{r5EdSzPI~@u-gY(#byHryKHY51M+l-s`9X=MGjH?F4DClTn_;VDar^3-RCzgv z*1~WS?L;Ky?9(y)CqLV&IjQMXim!`}=w+yuX3STM*{(Ep5FdAwm9D^SD?<{@xLr50 zO7jxN>2+}=ItM~xzi5)#v1yLkZF}J$uPqt1c73#n(=GfKw3Qt+lp1)q8ZZWlz%V+o z5Q3_4;GLp}NLS_*B}85TQ6m2#G~P}rDK3Vu>~`;PknX8az|=t@atkX07A1a@a?+x0 zCfFE=MW=Esg`?@Z5g~=oQ;vIx&#B5zeY(We&t=@=`FkyE$+pwnrt>=D7`)678+09;f$vl7J{Z<<>kh2!*MLA&BO48H7Vj@MFQYWA1W?)Q(l4jQEJ?NA5}ch zwCt=Z3G<{j{YGO^+K?b>=NMHAmVmF|Bxh6woJCQm6QO;}(nRZzC00y$$j3faXeBwM^zUS4E4Q|r*3GB(V6hUVx9A_e z2`5#R>6BD%R0PClLY#Jy`hhYIOMci*w&OW2Hp=--VB5zUU3pUymurs%hi~&-BI0JN z1rr8B4Ma5M2nDl)8X77|2F&#=|CKJg_@5GvFwD+m1Pk~TrMT_0e0Gg#(Ff%uO-TQL z|0zok9P2)4E@!E<971a|ELf`a1e<%x2&)k1PsPWkD$-U!iWXr|zTiV&b5cMd$w`7t7;J z#rjuWZU|c)NGmeBB>zoCOv3lE*k%4mLv|-4=%&7(uXO3DE6|@#|J9n+81S%$09rJ3 z&5o|K74<)0rNPQcD|pE@fjoQiGd^X2CT5&c-My zh&IMqe9k0rvubjT6<#)iX{%Tl0J{@j>AJwCJDCVpv=J#P?e~NR<_iu~ji7v|8A1m^ zc9Sl~3JWF?2uk4>9E;422s1@z?%ZlSJs~6}#fseXm?+fJ($0p@X+vugD_Ra&_HT90 ztGa8u%%r?9KwdKO#hT3^VMcp-Q@>*Z(9IZo)(%aEh9?`x`HeY4<-ghFQR`Zt(24vukPPTv%x&&_;=Ej_zmdI{?DX!T~Hx5jgu{!vnsgsji-GWTp}+C zPIGBe?n&OGA9qr)2w0auv&$5$`tu(*%DP=386`)7gBPNDGlQBB2IGSvDyD-oD-dR=&2B}#fO*A~)k)US* z4tJn_FD;%uCkW{&p*(9xMNQ4cCg}M@$pO$EUUtq0*RzCUTey^j3A*Dq3G10P3H?0> zYPYmS@gx_b$#}tNG+*~?4BGYc5Ko)JqD_2Z5_Wc2jwI2^G*3i76_*+*0C_h2jOn?) zGanndQoC)r1Qg`|4!HjI+w&<|z<}+|zW!6Ijq?Z4LFSC5Z03~MD}LYc51WOb-)#_c z>W>Qg(UrzO4?y?4Q=8!TKfg)|1ajusy&|EwB-DFCweK1K$iH!Z+_7-7ZE-g3gQ4{K z_?OKfcJm)5zE1?)UeDT%9xs^Csf^j1*xw6qLj&o!K6**@JQwPZ{)iMyzeAR!%|`F3 zRZ9=_F;;0>S}GQ3Sly1jKW}~ap|#UNnV7(Q?a{sNl{~>342wdk!+d~m5;5OJA;IDY z4|Fq1kw=QTl7n|vtnhMqhx}vF4MEudps7N@i)7`95VzKQc29w0>WC=`S!jEs&DMk{ z1zL=pfb!Q@7pG`nj7lB=osbN?sjUb0T*!0P>HF!7nvWnn&E$gxUxY&j3@Du?$=LX= zg;{s(3Z+Ss)Q~v?O0>fg%-E!TvFkL)N4%>l%foUGz27@L(Jx?h_x*FBL8UpgWgk)oeGcZE}K)x z`q2G;5MoounO-0m=2pq(<(=S^O(~1plE6HqMTs4^@;s&AN$9H#Sghio$abCNl8Qi2 zddzAr2EteXf%Q zzhIK=c^pm-ut22)_#?Rpgyj^w{sCpUmE_| zNtXh_+FirvH~*VWAXLfjLCDhb_rO&kyAjHXj$K9FzCd`yAYY+(oExLbQ%5xc%6q!( z_94uu&2v`XQha}}4$5ZF62&cScdErRX3Qu&+X|-A_{vgR9k|FS_<9>XckvtnB^4$w zqyK}uw+yPQYu7b#3m)7xNP@e22oT)e-Gc>p2^xaCy9al7x8UyX4r}$y_wL=jzdom{ zy3grT)zv?lHLF-P#*{Ii@m$xnpj;%vJ?h&3(~`Eb|=#?!AB#k>q+Cc;5$CaeOq&(I+_B?83+q7o<)bR&{rKB zn^vGQxfEW_jtUu-I=eTj-qYX|dchxXsBI5s?{P#8jn5CGlwMH^(ac5pSf93F(CD!R zb*gujhWzq}t{ROPNu>OJx)ZO;XmMF+3Wv4G0Z(Rvv82Y40CJ z$I3ZvoOutdFG<+@_=T=`5NqQdzX_-FyC4yWgXo#>Vezw!S=is(N*+Cm=cL^i9TUyN zL~ApUe-iA%e2q1h9IK&}yplA~oy|36%SW+gf)bF0_n;(F)&3N7&}eJi4z5l2yM#e5 zz!d;1WK%8!t=D!PkJ~cS&PuzMQ`O{;^N`a>ydy4O)47NF(cTAtzRb0s%a65$fJ}G@ zT0Y#lJY^Dc#nQ|i8E1(fj7|(3d@@qjUM`z^ef~&P=JPhMcGuT=OdVy zGpI$mXy&T6+us)Q_98M;<0SQ^W3+vy+j}1q(@1d{#T)XYC?+n`1<=#bE0uIqg2=84 z5R~-8I?lT?ucHw{u+bsp4NKgqPB{h*QZi+ByfKb{kh}nFc*2+jA^P$$d(d#)P`o(9 zwj`;qi6H2bvex#+6`@L-Jf2ug&I6%UW8z|i)Kb7OjVC#E!2-mhjcM$|>O(7LHXR2h zg1Y7k$zH%}KIEgw_9iFlqE%pJpO5|B8wOWBX)|#B_Q!T5*1zOSkB(y5*!Pl9R8rQ) z?ss}_#@qt3L5c1Zb>mo%c-fszO&V>_F0VTB%rP5*KQ;8d@9LkRKENg`v6$ICo9t|zLot+}CiEp@KP%JIrrgW z(KGWc2G74*rc>yCp6Hv@)}l_tPZk|saOTmII+@-Rx>WxF*847`LRX|AFNbXCZHqbQ zXatG$uRwbGz-Re=XVOz5A$JflnX@4S@y3MWmef$PUmi|*4NEraA<>~K`7xd@zjjF`GP5w`m;DEY9fD@NM zC{XRbL*J#^<}iS!4bX&{`XtQXz2#_EAN)XexgNWDcl*=#{OO?2(Q@c#&gCK#d+=I| z;nHiQg|I5~FsAf{cu;j}PIZ zO#{3wB|;tUW}Wl;s%MwMW3{ftv9g&dJp)7k?-zx|hG^`UKhG$~J0sT5#mk=FM6ob` zD)lJkG(ru3DZtr&nv5$^Ju#BXWHB=z_kf;;H0#OFrTa>enihhm+-lZP+U|KD-p-`l z#@Zr$FriBpgpv92TFyT5b@Yl*TI* ztQ+Lu;0&|;C)M&*QOc^soQGRHxcWkh{4a1ib9^$d{BE}_ni)7o>ELHukurcGS>-0r z@Ux1y2OYa7x(o6zA1V3T7c)t1V@2t9v1IIex@gy6w-mm4YpR$!@{Him-qQvsvCVji z0xTM(XegGsSf_ks@-f~ZNp`_NXY_CJ)2d}rto|VyJMyu;1GwtW{H{9$$nB>xXwTsg z6v8hECAfNC(``Ydw)EN}-)*4{FGEQv$o>!gjDLYXvkJs z_>@)WQB2%K8>rI3!hNRo<^~1<4g;s5mksdiFP>LfRx{;&oYqKas<-oy?fDLC$T*VhB~g@jjN|9)J>3S#}0Wy$HuO z&p0%f<0ii$N{Iq-$px8vo50YgWc**uS>Z(|Rbzf;usb<@kN^$#Z-5D=wH*Qf-#T_i zdeCX{^(r=+z3{74%Yrw$ms`-BBONy^JTIBgm#8c(fzL9Y7Hv4LNzwA!?;7K!{&1V| zkeO(F`Po%lI%r`jwOxN%J=hB_yWAFZ#kvpEfZC|`Y1eGFN|(izQWf>77JPV?9P_LcQy)qZby+fMY?+!7M_zm z%AkqRXU8QUkR(wCI%>n|( zWMS;|_>A+P-GTOIjt^{2a7^Hn#|pn6eeyzJq?@4eZ7kP!#?izAI4PANQ?vG`5R+=7 zF%@3nBQ?0%KxlM1CcP#Tyz8QiG*S& z?)c8}EiS)zkPYmNbI9??N(|1r1W8?VdJ{goS1J5!H~(=LjntqM5AyzsPJvLFrt!P5 zxy5IE-((jkNt2q-Dipm0x}d9!euO|K6Q~O`2ZeMB;tfGzc^a_2sFN#d=HBbHp7Yf& z3A54tigP{Xo6mfGlb(KP%JFa18% z1lNzh=*EdXPHW32iA;(pd-mlA+H$ipjiX;_Xn~Dgos90OcyUDQFbwtKfOk7@Z^6IKx1HIqwjCz#}E$fVst&M&dEI^MlPxmap)?A z&q*pLCw#^64POL7Oe3DJw;G?Xc35-TE}Q(R)cq(0YcZhUZ}607==stOPnyiN;UNR{ z7)RrhEj#}tSsVEc;ZVI&&maHu$G8~oY6dN4IUDQC#+0QW@kM-F`3>e5B#1W>{x1n7 zRbTeY>EiVLE@PZ_(Hvo{mbc9_1;Hb}TbhwP#rYTda*Tl$H|;h;LbVro@0>qc3;uB+dFkV-S09dneS^eSF8?pFy!Jy-6}FvznxV6Fo-&V_;m-K4qcJ}@MQ zP$3~V-vQ;G9rlxO19~%fZmkWN8O^4Mtl!rE;H&@N22~aQSCO?5MFa6^C_rMM#FHR9 zY!-wJjkuvY6uj+B&fJw|n`}y-EAd{Ay&ye( zi3>@TA=}$_Jr_Um^hSc#Hp0~5WHGS%YlRjirHVFwCxo2B8d7V@pQnnkoItE_H1d-< zI;X8%>;XLZgr_}x_=M3jt}?rB%hHdhUp*<)RB+2ogB6CwA;u!bSF}DRKRfLov1WVI zSXib6hX))vA=qso-`ANJs}9`REj4J?^%kLvbY(j6iAmbThED#M0>lBq_Kr)3c>H|GZbmMhq zO}(hi+=8W&A1z|^csO+X7IzmD8s@Gv=M1J~Y!NaI>SqzmqqvI)ntyt2y4f!Y58%*Q z((P4gGkgtV`GI7_i%vaXb#5UHx$k=?DkAuvPw1o+6d0`H&0^43GXSu8{GqsY2U8eM zD(uT(5*^X+zM6}pU9ecbsK+A&&mZ#a8M#}@{4Je`#rz~DebKM8ACtMzViW6Fh-_0S z+7HsI?Y%~CMJn$Jxhw}Yf8Z64j`v*P_V_pkrj?k;+w8o<94dB@ty4Zzn(D{ua%v;4 z^LTo)B|ohnXi_(Q<(rD;^e>Djx#=~KW+o9evghVaAmyJi4Q@PP3?eso)Qi)ijQbz;p{h8})_L4~LV4Wc6Kr1#Pz^Y-c~k1-F)=y{Z(+7!X^ zM9pPDmLE$5Ms_B_+P(wD^HY-kxctscUs6g0iF>NHJarxSJAOX#{7mRCzK)-s>G9~)Lz<+T2 zymC+Ah06`AuhVWK zj=rn)l6G`LO~D|wpfAnJ|G=_o;9Ym#;JUi_t@VbWGgMc<8F&Op+YC>;qsK(F?zp3K z(=HzBaOp|0y{tSJKN8G;z|EtpdSYKnn3;mnB=Y$~IA#BzUuiapeIlTUcq{cANo)vH zVviUWWl@8YxPPP0kF$MDtYY5q0k>Oda%c#`QV1vuaCwGIYlc%L(-5>|3ZS37w`4i$ zn`0E(n2LBM3jmQ0{JP;WVcEX&+KUQI{JGp7J4EPvcWvr~h$;i`v%-Wba6*PP`yR~6 z9*kVRfv`OKjIw#B-&pAmlk>BeMU6fqqV!0FG-@(4*xcnrSQ+7fCP>fYvYG&D-Fr6M z&U^6(Y9d~CARHPe^vgr&+Y!W-Rgr=8AYI{C({hy$Na*8CL9-r*d5~Y<5r`(+p}Z{Y z&m|jS?S&o$iZ)Q&(7YlXXv&fkDx%wo5PG34TZiOXA#EiSXszT3CAK%e#0Y&T#W)h? z4iyTdzQK|%lrMPd&1`QSe|7)r-2$<^FdZh!ER&wKEE;BqLb&maZdOorna?f!9eXCx z_|;FYbxNt_$C($Y2Ppavq=)c7taIUD=s}63g(Y2Y`-NDHTOF#xGX!~dh0~;LjQrq( zm(mxR(GmxH?H*TnKH($iAistQfyQ`nBHGdG&5bxYLxNaG-9L=<+&|O4GRqG>Oqg_O zZ|gaK!=oNF^ZC6%gG<9VUz7Kr=xrutHzY;|Q4zc(z?^8kJ63-uiBA6e z4>o?n6$PI73xo)72eTN@1NUPmJb7M&-5Nc9%zY0}m|^}Q`9uX{;+nqKk;DxYyY(2> z9Av5ph|_j8a`Uy5tPA8}vCEhuqw%4raCTjVWZ1p0EX=;G9R;1cqt2Y}y8hv(!OK|= zhiTReGb41r(~>Ui2qZd$q*#~{Ldlq%sguev_ryY+)rV z+kjB~a6XF3S3maJEZYhvS{XVBX_l&=!0MhoLl330mvMD&jK*h~)b4#Lhl+0>gS>FW%)D z5KY!&{txS%C@B2%S|6`8eRR{Q?;N>}kF1R}JaXjwmH4H;(y#6KHzklFca(UXa8-io zwo=ar_>WOVuCl1;1oC)W(BhYv4)Bl)NDRH4!2ruzCo5w)Y=Me?^e8{}W{yLP|OWq zS#d9OvcX!F_M{*aNbHShab?Ruzb~PL$y=-TH&J-`X2RU!ddHidN?(vM`UrdrK`BCo zpc2AG*%CWl_eo8k&hS|7h0pKv*Od#%$WRY?kE#I$Sx(Heo%422D)rX_nWoIXfu_8* zpE8-8CCCfTNcZXHn?EMem2Ur#a(LuF9R{MsnjXK$csv)5`0B4%mp5g^`oJHoc>IA> zWJe1n%8?|~5-}1@)@grcfiw+lLPCmWNC6HH9_81^KIQAV{$o)4hFAf#9jt{zF$5`x z6dSE-WWK94R3scLcx8&!JsxH16h~eZGy{;Zsq|?76yeyMB`903JLLL!LrlJn{T!Gd zXEXrdn?DJDfAbppAb0We|3pdOf{Gr55`1qR9Sa1>wOT?TE^SGWQeor&^1c`Xe@S1J zv0pnWS-Iy>9vjx*X#d0oEir3G_Zr4rCgiKpoFtxdYP!Lja+(+s)xZnKM}v2-!ThZF z83KdIGNC9pGvFX*1?28NL~VGmboHs8(hM}gtpAXR&@{i$mU}*2{RBH7#-jJ&{Taec zCp2en(pk{0+q&4{M>Jxksv^!pT?1q3)-lehpoVUxYnD%OY?buT8_J_@&=X&s!;h7w z@OK`9{FxD;@8f)#1Mf?TkdNg>sQ3~ZbtE=Q=DgADJ6LDA z1lN#tnRpO#lf#)Ta#O<74tJ1qb1)I{IsQ9R2IWu0R-s(sVK}F6_DBxl0Sc;*{Mx* zQu;fRueNT$NA1joJw4bY0ZeuCzJqw`KLFtvz2tMkP~Ozvuhio^Q;jqDhp6bhdK%CvlGZOl&>S+qzYHjOb%9x+7Mq=Pq-hFQj=XkP9J$r!kJpUaRGk+djU zgq=)I=tIvg)9pKeez-CJT21X?Ox5MqB>do$-TM9Bd~$E_5X!zR(AsnsZBhauVpSnM ztosb|Cc4qbvrReM;JKdumzXZW*XkD-N&5Ll8HZs{jDTO2BnDi3!T$0Spn#px3~V9) zGOStuLkw#%?taCA(uE~L-dv&g-MIR`_!FWdLheC_O>#SMsk}cU=KykYI#5M^6Qzy> zzr#(v*h1)!&!JEJ_WPy)uS!OK5puF9_#oDHwzm!j#a3j)`#|^Ry!ApF!bcWzgzWZ} z*slmQlJJq52s3z$ms=>>_uo~Fh4p_|p(187~ zW`(C^_@n92u?O#AGvMRH#{+(S=!TC%b@ua0zD=tn)!rzD4l+&r^QqX`%R%@NlX=h| z_51Ooe46;ax4BuKLiMckQ+~2gDK_dco-UvZ zS#{%GowsT{5*?rNJ`C0aDS(qWjP`q@-x^&ngUi|SJeJ#qoyX?jm|~J6C<&b+;!5Wt zFnV-zZk;nkO4zW`?w3(KdD-z?l#<_w?ft{@nhhE^ZT2_r_KxrPN}n12VVp6tE2iVS zNJh8KR1<>Uwn@>R6z2jXn3ptKoJ*dtg?K%tx5{99fH>V$AaJ{gsc}h8cOEhTjez(N z!mWZN@8Hlw3WD5pE*_Se;a^AnoV}Roy()*eCW*IN#ItAYBGWIp+xdZ!x_^1zu-UFhE0&)C+`ftS1mCr%4jFViVI)4VL#WElWm!!gWme6vt z33?$*HRC?az-I*Ey{m(SnqWKhQcgx^{$MGCQ0--Kn||g#GHkXK>?9bJaLbeq#zXZ` z-Xag4uwJMVb<(2l2Dziu4Vw;B%BD4Ro#W&*kBp#0HxQuektU-Fy-r<%zRlMDVa1gT zV{=`KM*0EjIY}~{xw@0Oc4OV^JP-!9w(2hAuf0p)Sp zfC;lW_@Le+5j#r5L0xjmXkq}v7Y`j@>s#t92_3c+cU*x3B^lg7xtK$ASu~((^q1WA z0uP7XEIA(8?+Mvrx}C53@13og9o%OORdtM>uD8p;u%7d}9NP>;6MyXV`SP$tc>e?I zzT;`%`nAJ9+X;_F!d^_H-PpcijM{U&P1Noh9^)XOV&I{haAc%FTqDr$L$w4krwupj zCzPaW)xe+6PF)a-gW|r1io$zO>J%Jw!Bu-Q>SXcryjKmKkTEYSVes^dYUCx+_yPlw z_&9MX86+)Y?Z8AoB2kq2LP9Eq*lIz%C~mW zJq6T96P>qDo{<+DMSE|`2vuIG^RSTjy#=qI zs=$4L;sr{#DA67G=LtJ#I9MQxu7gQmh~Zp6HJ(ITHUOs;q5}G&1;O~mnOD4{(L^jO z{yaXFfE!-y!XooP*n!4K!(&P@wuLxEQ>&oX_UCs z*i15OB7}tB)XLA!a)K>;94^)crfJ!rReGOM$eYxq=Ac91wE>gO;%;WJ_c>qnn)gjb z<1Sj1+0@rrpQJ`wZ;*>m0Pd#bGpK%&CQGli(lATUJ^ij`ATZO%7g+tUv*qHpWUwew zTgQq(ia&#%PBw&eMh<8hqv<#bYmNvzo_?>k*u=Eb%&wH0&gH5ytPuunWb~a-5^wmr z^BWV#cQY-B3gefX&K0XN5U<4z`&toC>T)v$?0qm%)vEhm^R$q?ff01j2q~ohRFCHjT?q zI-S09Sz`y2QXTlKlixa6QXgO4WbrK|Opchm!Qh<@ph&heNb_=E-U04=LQKj~SD1^z zB=3=Mk1Fxi-3<1}4PulJd8BG(UB(O(S4G9uNen>;%m|ZvLN{ZxDPdcAoMfDbZW~NN zm)CjY!Z0X00v71ayK69U^v&sXh(*eMcyG&grNOwvQEhMiQ4*i@ zesSOdNY2ZYw%A62?>d6#WOpkY#!TpBIUNN_d~mL7$P9P)O){`MqBgil}2nf*v!uj z3|?mW0{&lA1f+mpf2S_!J2s~Jg?vc>^fTI`;6OiIA18q=oFeW<0l;V#+0 zd(=r8MzTfII%@PEr9^a1pHRq;tNz}v{MzKTc`x|6N+7V)1~?t{=nZVX<_j>Po`O@! zTHWkk)I)V$azeqwoD-?pDZ9Tl^H)Nj?Ii=$bVHSN9Lgnwp@SU6V_^$uOw+1?T1TS- zews32?7vtnfQk7XdHQ;@leSV2s{tQJ5^}~Z5O|Sdsa%v| zNEyc%NqsqZEpz~jJru|9106^=gJP=J0*tkAxUSJ4LT(g>#g(E~A_`Ydsg^K=U|)Y(Dn-`D&|mD!X_g z6*vDhr_*lO)};-p-<0f`LDtd)k#OeA1un<{XA2Lh`PT#S%}*@?km?5~1~nM$=*ocd z>^#nGZ1LfaWK0*J(*!+IUu39A?Xe!csH`0UyWVqB&+(EcEc<0pKK&;rTyoU_n>u1n z-S1M&)OGc7ZFCz?N`?bR3srfth7A2MQ?h3LJp9TiU1iolzsFVjcuYm z;>+cZ3UZw)*KHjr4~`qdSd2_0cg7-)Kzi3gaif$Iqyk8Sw&FiW5!rqw_dd9a8ytVw z@V3VhB^+$Z28dx}TAHL*sR-x|v&C}-EYL<4t&1>~)q78%qXG)Ct3(B%t+w_H-se8FpR*a|Z7ZGJ?$s*qE z+j{uXWg4wBy z#*%ru!AW*G;Yu$2vL$^Jx%DV!yj*8#Bt+C1Fs5~yYLu{%V|ugU^5$U$=*T8tWuEML zeok~cgWiZQz@H}dAvp?P#oA>Yg&197ISW~3^289Fpe2G(wU>-ecnGArP{yxTrfF zgX^O6A(O}VD)$M{(_g(ztTwsyt_HyUa*d*|{-Hy6^NtV6<2zY?lrr-I9IqfZIim3| zPH~9W&yV%C3u@aXe*#hHi5n*}1kBIL*yq}hJ@=;rL(%zTeN=J7H_$R6U~-^xdKVCbx(oGKDj;Y{lxaC#AwM5L*3CGM(k5h2dob zpG))fM7aS3yhFciNdN>B#c&sPGP_QXON{7Zag2iyc&~C?ud1`feCzoMbf^72IHJg{d91XiO##>vnVlzU>6}KIj`FvKQ)h$A%F_y)nvBHBuD+V-nXWSIO(#ufxo19GQUKR>Xyz_oNFtYH=nnVVeb&y2-uGaN-|D&p$^4y!Tz1J;pR_l6 zFShb%>*;xoi)lSJ9?sSzZ9Wc0;zMhXR+w=b)iCOI=&J`a4dFF{KsP8e_3@;7G-XvzvONL%I3qP#YV8@oHT1<~>z ze9h#CV6~AgC{t$X@ij`g@g)#W-VWtOEc8$!da>8+r;Rlr;r zKVD78+`i?0VE#gup^X~G{0*eQB?LUDx zPyP?4rUI`=J3?pZWmm25TE_s;f7J^W?OY5VjUw8DW)_1p^XofaqLkzovIbh{B{oTc zq(7dC_ri?Nn6)-XRc1%OP4~&7a~iGzo&fBfJ$yunI&dcfoA=%|Xz zDA+oCGhbsIN==9i=;G3Xr5^Y%3r{R{VNnKwOXxWz#XR$8FKE&PRJ38KdM)O~eU)`6%jKrIJf(0Iki~V5Dk{qPiPERif8nYRsd-jY1pkjtEu%%!xh?l~ z=p^V_HcDDLT7UEWr5Gmjpp5?VYk4+-#cbf|qjOz9 zOPCpulQzhk{gIrp2O(k7yh-BSE4lP`a=7kC8*M^XX$V$ARk6!<*SFMW|DOs)B|HM& zS}^l6%u-DrPxS1a>V4&YPdoVQ;lnVzl>Nsiwd>5aKWPns#P+`?J+rG{SycI$w#M)j zl?MPFtdZzQVTQ%gMQRC6@uztcu6W*YVX zl{N~2{$TKLw2{$RwblPl8v%q9GW^%B|B673_9d4qahslwMx}A4j1LKQ5^4=mhQ@S> zb&df&_=<^MpLZW0-)r&lSoMsYMK?AO~;Ok!FfJSTyhf6EPL^z?uN&07$T2umB{ z*@{z9r8qcq{W;L!-SFN%7nw?fXj5?_dL{vv9c|D4n`fAIcyd8wO`Uw2y2pWjo3lue z3exbPyn#D-AI0gt%V~7zt$#)@K^KcPftF}!K8(J~AI57*)G16Dt7qna^mLn4(kgXg)c_MHv(EF9aQiU52GZ5=@XI$$SLM3gYk$}dD1iufR zF4oIHUDz)+bw>tXUIS`xVNaf~P)no&9&-xsBt!G)cTI{oWA$FuYvO&jUU{7Ekztfg z5|N5Dm{&dtE@Yyi78YgXxT7aakMBywjZrP8;286C6c=mo-^7Kgs|y89eMfBgywG3PFju+T#AM`&OH*iJ$*+YZKUh)|)0`)NUZs%$?XtX9^z#5h84Z_g8AaYA?<; z_!%rmy6>8LnlO@cgO}KfsK59YMQ414w+K%Yp)DdVUCuq8H6_(6!x+#@1mjCbAVT1A z`o+Rod@z93()+|j0NspgWH5z}zW6@kOt%c8@`ILr$PKTqF7aI=Qw#w=CGlz`>MJSS`S^jqYTy(Q!s#Sw;OlI8c5#yid)wA)QAW9yT$w?j z7NYE-3(SnKpMuiExoR&=w*R6kE9VL5?PaV~wQP*H&z6BnGFpF8eS>U)M zPgexxn_WWM@TMTruN3AcHZ-?D+eB3CrBFUv+mH-|98ZJ?ns%JuY%!d^z3761gPBCrnEK?>$zs zp_xP`iRbUEJUw(afiurW=BXOlPNY+!!5c!p0LRk#$a)t!lMANfY&lJ>F_zbKu%<&HS!p95IOx91#}S!b+@S2vh(Bh3m@>x!>OP;SM!HoWMm># z2i(X!UqZ->F1+RMN_gixGcg>z&r8=XPk@TQ%Hiz%nt7>Q*HO^~SbJ)v&HEs6rO`es z=JdA8w^P98MyI5+#^frUF zV7Uz5r<9+q;JRI05n?EMbs6m(r76Uug;qDxC&zx3fsBmip4W?1U#t+IXja-^ueSAG zS5$G&Xn0$~?&?Lamh6VAWNVfBim)E}otDxerZ7`x?)k4m~5*Dox{8Xz4e1Rq*>d1XS zxnP*h4iTFTX9W98Fl{^HGXW#Ngr3vhCCsfvS{hnQflOzR&}=`2MMpS#MrU^wPFYbP z9E#)H^WB|1O6htaVL6|}x-Xij8BJv9bP;X*OcM)-Pk6>?I0Fe4Qt=#9JG8nwe`#51 ze@;7?kTzN%`Z81qjP*r6lbfy-A9@qjid%((*QN5?Mpu*VnifH$ZJl}{{ZxL|H<#2PKg(G^_p#VU5ht2~ z4#VG>3~TSeIVTuWmXx3FVgNoONPfchTK+>b1b(NeNTPZGa#eq>P$1WPN@mCY z#GZ|GbF)_S1HqHRuPHznpkc1B^yuTn{QM=K7OWx0$7FOoIz^H4((hfjJ~I|4Pz`_N zMY3GCdV-A*Bp%d}Wu-eykac;@Zt=MA1a){w1XNVJPVTuexGzLC+EH?D1S8uIcjCRB zD@(uWl6xuPCY3_#c;^p7KZoy)Hc(au@6_2^lM3EZ&R-RpCN%SN+~7`TxV1iobpf2m8( z1x2WwoZe|HHtcPAMI>P1#1$oaiNNES8m_1<3Gr+;&kDv+EL_k1V*0mn9+{SI4;aBQ z-CF!5+EM3CP{8mq=_GRvJ622kPEwBkpUL?+JVeQjXy;f(WNgw;3;m%UP{Gs0mihviETt$hjU)lm2 zrtR3uCat$#(T%&El(wZ1nv5GIxLWmHD7Y5_Ew%=kNP|-Cy1mA9+=HEUTjRUMh2Vin zeNsyuE|Z=x(bK%${7BWRX8FDJkn$s~>Eg_iQ>H)jLcVHS2R(s@U&1UZdLrHPdYgOi zNpufc_<-z!y$-H_GH*TyM zx?rtJs;aUz2@eQ!5~H3`k|AfCratGgn-8(91NYF*s;}pTG)UVn{)XvWwin1p>LTmV zpc4}H{_2}L@$BVVm~c8J53P5~A&uD|=p10|2xw@RMvv5; z>(t>qD!-`prueA8dWcNz{`p2)ey`hspsN-nyH}JR8)0Q_y|&1bxAoXL97V!6fD**a zjUY-6D_W`IG5D}AXdVNdr#x*55v+`4k;Z9@ne)7OwWDz-KtKI+J%AFV$u^HS^pS?& z&xLQEXi;dTNbd|W$WFlHwkgP|J?KhtktmRb1;$F~vWRewv~&x@&#s(NzlCD95(vOy zt~_3;yi$JN6?}fpv+AdrLIYtvR9Je&dAd#zadlV*AWQ<2=cLVPA6zlsmwC&GenVUT&$O zw1N&K`1`UDpB$lzu=Z{qoW6sUgbJJ12CI$e<>g#Yc5I^+SU)C9nSZ98$m6(B_C!^s zCx~eOJf!rl9OVG%+G2bq6C1azFnQ5Bh{6`GKvmR{q{2OG*{K-FC*x^|n8f}&j?I_BRP;8zec9ZPchi_2A9i@y6ZCs2ce#IuW+#NDj zrqSA<`fp4n_J;P?&vHD!oCa2?wmh}Q< zw7OZ~mZZD9E>ib~kF7}EqA!Jgu7gKC1sX{&-scqq7SHAqdHy2;0?F>FlC-AO+`AS$ zA@T|_eXMZ%-mb&0?!a^O0CXY&pPmds7pSt_#=bA*s2-*HhIk9zf$)f=_|gg5&ly{T zbuHndZfI9YBi0q%Guk-eHx}bB?3pn{JOK(dGFOuQNx9d|hCSjyA~#uxcBDl;5V`ZP zWS-R&9D&=4;gF*mIwT+Wp_gIN>oGETV=+@9Hk%&m$rSBO-Z3>sfaatVKSk-O{5tCa z*jKjB`#MXXLlyI|b@=gWi2d$$``%WQ zIYAq1>S2|5>t`wG!~q8?h2_t?=m|L2kxgQDEj4Yx)KKLmsWMU zzQY)});^4#*@XX==ehlZ#vt<6x^Z(a$;9-$R$j=3kkf9gp@AtJB2iX^>NE+(+zG>= zFQ3_Ib>L#YHc32z0J%}x1v!PMP3@N2?P498G`-05W1D9qNhNMi=)M2RhstuLi-gXc z#p5D5YG1KXRNU@z`%Xd34Lz?=vq_Yy*s@IZY9!CwMMs1}c&etZv(`p~a%Z$Z_r%o8 zSUW@dB9F??knJAz^8yd6I)HuINn`qK|NeC4W06lR;bsU#Z>rKKL6p0{3eDW6~4ewKKaNr_RCx+cxNH^tysNxG9AL!(^H8(7uwvg4HC16h;&SuM zx8-BbgzlTygRp#|KRogf^SjCm%s=unI7vFeA`F67o9H~fBX)-t511`tEZn;(nl17I zeeQbv5u-FgFC>Qpu1@g^7!v>DPR4*@NU0Zc4Pk;-Gkj2H-4W17F#E#Io@B1y#8m`5vDXKI8 zLxrED1FTU5QQE{ALAxOYj(*Yax(oY#ic>BT|H||P?%fb_{EaQ_+LCaCMpTXbbd@R8 zX%z0My~2zrAc&y-WcdK1OpT=TjmrSsfHi(ihIcICK>zb9ImdiLjpkhVvMdghG2 zk4m!iTAR-%}Ix zj{ioO@tn+Y$+C>b7$YZ~%!is2J#p+knn^lBxbZXY4E!7tTbbh%ZZy z9aX5(?>=PR%D#N$_-4@7qosdadWV<5vqBTPefAA~pEs;tC{L3G`D5el-&n$?1P|;9 z@Jo|fDFhMsVXziLgSlMRe!_779BNhE&n#Ky4+JrXnmQuw@c!PE>a2}6uJ3bhc(AAI zK738ye7?Onfa|IeYJ7TAC6Co+qS^bU)7U8&LsR~~4N3*61$1^F9C`NS&6wE9pdO`(mB+S2w5`P(@SmwU z5g@%Y%}KO`fH#iv?E6qB8?h7kWeD1ue}3)MbIk%mN@^x|x-p@a&=j2T4-`@1tb>%$ zKQX{6WA1-r?yaNZ{JuR++}#Nd!QI_0xVuB};I4&xfDkOWySuvw3-0a^+@-4Pdw+M< z++Me5P0#I~S@UnLIz_P$RGs(TpJzY!L%SCWHYu#rxaTrTMeu}VFZ3n~%PVU9II!eR zC&5BJY_(%dO4##qOP;HumkqsB6Ybtq;4>wfYG3~L3^e>>`*3VphqQA&7lc3#Yj;y$ z_w!zC12}d5s^tX}f4)4>y^z6eKV0`k8#HFZ)q(cz?y#^F|EkMoHgIx^THQ$^OucP_+ zxfSAgq14n3wJV<{&im6~H_f!k{bqo=zOOf&qodmQlbKp>#G%Ods`vrjvy&ed829mm z)+h9s8LKqtsa}ykfx)@~{(pIU#ZP9IReM9<_F`FyL$TvR^W<}@e%38+tD0O9RQ3qo zn=zuH&8ldbXr}8Fsa%Q4K95YDUoyCd*+#4A7~ea{Kfoc4EzEDiKS0B&KYz;CqmR;X z4giK9lj!)2#*>_%vC~vYYYO47rJ!lv#!Sv}(c3`7?7*T|6GA%hDL{++`A|>Haj|FH z5Rucp;akxi%L7A69{GQl$itdI4Z5?`=TJ6sDNVeTULXp=7Wf0hh=RExRcS13Nlnsq zzNVH$Pl_VS#n9|)2Xe;cHe{N1PI6nuLRE34a0(_qAJbr2!NQq^&FV6?*w8uD_ti5= z_)yZ9)A2+#fO79Yj(ONDX2=HZ4rz1!;j-rvET{i`vDqt%c7)L8BIG}%bmvZE9&8Z_ z6PVk!sPcZkTnN4LpN=_D{jA<=eulXqi(FaWjwBboq+(+pF~FR?tC1Lp1vVXe_i+A`EZ_ zI!)JeW&L9)lbuZDU5B4`(;hC3WO6#FD%;#K7m+~K_fzs-20C?%fV%cok|Fuij^^z) zr={ATV@4`s&H$v;7Y(yw5KLf~a>Gjef!V9d$?szj?ZOkoL^9 z&!gGH@n8(ok?lQy$@Dx!V|*cU$Dg?p!?Ro)%*~t&9{Rogag({M!h0EwP$Ovdujuc_CSWF1Y z*Fn|Rg-1Dw%;*~P7Mi<@25W7a(txj>WT zeZ2hJ>G<{I%XJ~CZ@t?FR8^D;z|NPTkLn?p$S?DI)2fZ7I5kbvCrFHxtK8h>H(4h~ zAJCl>%we3|?-vshki!@N>je?;*>pHLQ1O(-F3mqmT7Qv$VZ;Pe{~N3}NbHDIVM=}i zyR+|DaL~Tqq4r{1XoVWoAE$YZ=r*iU(#Q16=z7}+GeR^rjU`y}qu3GMygFCFLp|%V z_bJkA(+}XSV#pnEvx;-^t88~j;-EE$X$mrSrjaghuF{zE% zUBS|e4!mqX-spO{Gfn5hw6F;Z5}4yeeE4X*nE9rH2L7Ej1ZPBJ==0Q-c0b>{tIYL_ z2+=W_)X!DxH>-!)A}!octzlQdcl$oN*Y>>HSKan7uD|v$0#f7stpoi-j>@xvoUgYZ z*pBq+usOm5cgM~C{N)XjPO{^G>-sD}7VhCwZ!%!*C&-S7cAR(8>2Tk{zbZUXaXa{ zrwyM}Xhz|zLoz!2I*Wj2&^!*8;cn5+=%O5{`?)(=Z&S2xzvN4o<}jkSNOcKE^?s+> z?;cv1x*uFgpH?A6%dUCl;Xl}t3ykfLr?ZDwqAL(LJbS%&LmUQLGtGKxL1!#ls#Mod z*UvZmyOb6E+zZQ+CSLV#qoW{a!PYDH{Sn@F#QhPAw|B%p;n^HM^3H(adZF9?^9N|R zCk)k~*TSZS?GV+XObpGSEf~+isl}WCzl{LL7Yh&E_`bXeF^>qA%kX29Ak2kKO4a!X z+;FW3{eY9fd)9q6+~%>u|C~PNqQ~Pqt?Ji8nchSxoN7j*=M!Ga2!;)!mk!8Tb!5ipD7rCsvE;OJ(i74rLsmL7m3@BH zM~$TeO)uqfu`%u-@$wJ$)R2^&JHcP#`+VztBvlj9W36>;m$>29N})N9=c6sYKL3hq z8!y(Fp?;iP^OG(}{iMJnkhiM9b1+r#LHzBH1gSvd6XvPy@w5X*kJq4hp#6!=I%1Si zB2^ib$|qCj#i;EA`k$D$?k!=$A2>ZGp!Z|Z&gRPHFJCJI5s><3^Y3?TTvj{O~7(i-lKaDRMkJe^K^M!d$5Y!$pPDs!ML9;qT$sY#B zMP1f4;77G?P4q0&vHKvvlXMg*BEz$RU+FpBA?4-&_2dQso4iS@qL0+&v%fD39k}u& z{h0$0aOC&6?4b6Kgdi;uug9;9AV_V+Q`6i?k}h(T=~Viv@;U92)PVu{XtO-PCObok z&D#jxAN$`T%{X}472q#Dw$VFc%S3&@lNhD&Sc!siVz z>QJcH1p+}sQI81cP23ShF5k0wtxEx6b#(s^H0oCWL|n;4D&fURHrPXhSgH7TKN-c%UfkU zr)&E)pu2MPijVk-OjNlrztK6=9XEcrHYPYh5v;nup&C79yv07I|d#X_elZlIy6KGi3UGa^K+RuQqhXnqko z1kbo$C_jh^Lrb7Kzs;^TpuGy){hnuDT);XH>(ZGv9{4ffYKUK7;cm{&|Z*yYf~i>djZ}w zF1j)8$9)b~_^}O%8}vxHDPvoPns)#g2lU{6{Fp+K8(;UX@aE@5D)4K8bF_zCKF{8J!(Yf(1ej$kc7Hlo^@m)i-+Qa<*Z z^LQqj%D)EV>72I@m5^hsJA4P$spr9fK#Dt`R`m7yGBxsfHwPdSxR)wCSWGIka#04~ zm5{HAi4h#Ac%`NVB~XHX{qymUj)zAIfvpP>C;{L-+WoXe=EAJHc(Oo9VUhp#hVXH` z`dNz^D+>HSb6Holg)a;k;IK3v2l&kXzA}0FnAwV3C6Xq?cngu+MM5GEM7$z%JiKGx z|DFrsI?VM;MEh33ho-$?M(MLgi(N*FjrROC>^|@3r{~mt_VDdHSc)|i-w~?2NtF1K0S3VHy<@A}oDkCQ>wh+(dWQN(Z z`=>*T^*TJel(HV`UzFWSlkLDLoJEr`(^s^^1jp32YL)!7zZ&5|mw9dK{?M2yj$2*d zw>?$^t>;@n#=^esG~WVvxxc%CB@>v8pnhkSW;}6t?ZF?yR2<)f$+QIOtaa5R#ESvC z6|#mwY%`%FvLAI0z-hs2PY6)yhW7Cp^Y{MuCd&k~0=eu&)DwuP&N6MjwNj_ms~*8n z(a$|U5%eSLvbSANFoYOYjdqg}YEh^egJD*nGxF@KTDN=^0=YKM&_C7#KVC)EL5FXp z{-D%t(Ex?7=-MwIH&@jmZo_Ys`G1}=O7!xrxKUZ9dgy;2C(Ps$h?;%!EUO;X774N# zd8WTceLp}-KC{>JcP0B0nfq%AH!8-pT0_-T%@RZnBJ%=f_c|-X3=Xd39C-q7EloPW zFpVklr}#ZHH4!}D5+z;s3*^uoEw+$Xq(8|glOM!3Uk{V9KmAlo^1i(zX8k*@n{pnu z$bZHiqv2g8FgK-^IXvu3})BRQV-la$N1;96F+Dh`6%{h3Y2 zKyZM&FVgyB%-0KE`IOKorlv-!6mQ@GHjGLbHBD`sqU-pj@wlGSUwNXDaTeSg{V`w& zc#l9OJd>G~J2CqSRxb2lw` zDMujX5!qv}gK+NJdm)MPYN$Oz*;W;V_kzRYw3`rO-$sL&9wfp_Ne2N9{cWY`k3-Oe z^zVGD+KwPxZO3yBw!fR5t(nL=+FZ_sK|;QhHoU$ICkNs80Uz*32P67DfQhG>{T{%3 z?7&QwE08+DV))KP1n>jev*vwnOH`G4xE0D|aG}4)5|PmI4sSYLH)u|v2f?}%Sk>j^ z#?7*wH)YUvVZx`{my`s`p%>cjfHlcYGsr*p8UA>v1-Jn~Z=xGL;CUDse}Xa~_Z&~S z+kTk0O{F-i_U={In(p=}+%usM<_r3amotzNlt9IVF{nh04snM6ruk;8@s!k2>X%1Z z=eJC%n>nb$fD$iY{+4U-$J{jB3d@3YyNYYXvx7p@rq)>4@^I#j#Uar%H)AAa)z;k5 z0~%@r7s1JzJZ=u+41Bb%X)o3z-X|MII!3J8FmCt9wdiIIm2s&P1T#hrbIXjm7TGfy~B*snP`*>pIS}%t|`f~!PXHoU<)DY38h?- zU4NdzX&Bw+9;6GBPh({yPm9@|E<8f-1f6$5FlC5`H-h+-+)^EFU-L=70 zw*++=>`07*Vr&`77J0Tr-N8CLlSq96(Hm%=E?Bh3!=2>4AKi&xBf@R16!u1CZ5fTf zNn9Q?{6>NgHTS2xubqnn@05@JE!o}C&C#~ex0fv`F1nf?<`CopYK63c>N#bv%$uX& zTyFc4Z>RHsW4#j|*XAFuCEJeAc)lq_W?x|_&>S|x6Q;hZimT?>+pLbO_|~M8HN-+xC4k9ARbmU5_lSQhl%3F_oJ?uwR&9{msy)W+^?gy zMXI)nHEQj!8cCy)@!&|jxj%v9|82*+>_PsuAquP=TfWIaetp1?FMN-qS%7cS@v>ck zCeiOBYL6zjy;%Tn45`VVvXp)t?}b0Ii^+q9Wu_1B;CX@&(ZPgF*4wrZ$ay$<8{g?2 zrhis&<%!oM2RdHaI*81+)4KghpL$$VyONG(K*-+`L^vZ4)KSjiVH?ky;NS`_punkK z)S(Lb^Jyrx^oIuWJzhEB^&pvc!|m>E^f8dC+m{OOJG$$cuUVPCTx#y@f_B{K*>yB~^Sj2-{X1AamnR-7rE>cjX6bht zD@9ice%6PAC8wOsEu{rdT zjaxm3tuI#_o%_?df~-&^)qh(Z){km?i>2Gfas(uBgV!IkD{YyEj>$v`G}ID)E?0+1 zFK;&+;6L@h0bBvEJJ3%DP2~k|Yq+nqIaFoiXh`uFk3;5^4aZ~vDg}^XdAIjz$VqBW z@U*Shb+VZT_#Vg^@Zo0kk__~&t3AMPB{NY`vIebP?!#&V_=_5*{qg<$PiJJI2(yRl z-#^A6GrFqTk!J@3Bw7a=!r~}fX_u2Ge-NB@q7gM{zvzXO?w5vKNrSnxi>WU^2#Rs6 z#TBUaujDQ#Y=DT_iO6eg-3zSHtG+Ski&9)>Y!1JErnDsAJBFa9l6`8M}DM`(Suf}O}693ve5^|!@4w}!UM^{Gf_L*e+J128O zn!qG(l7Fpw8)5&B!E(MqePVCi;jgyVh4f6hR^sOKDtxHzo7>ZEv@PY6~e->Wu(?6*{6E*iQ$~J2*e#J zc-_OR1!-hgN`9uwq>#wT&kw(L^S7feWDt}jPR6|*p-B*X;N{Oa2MaH@?{@L~KyMf| z%3`1-iKBRj^-XhxoY*v`BA+LybZ(p=!f_RQuGWlrl?sILWWMO>_RmtkdN$iKVkTWUDGLdtV*>CgN$;+6+;Rw3Sj`&6_ zX2@9~kG9W<-F;u=!wVnwi_LyM+YB>&7FJdJQWcS}vmN+RXSc3msDMf)VyKB!Vp;{x zeOZGR3Kub|1!zhRVy{&=6|uvN%7cBOUJE$^NF}4r+hu|V=+M=#ufFU@`ptGJ`w0SN zC`f%;Hy_UQ&G=A!9&V>fL81a%fTPpW@JO83P&IA8k4TpvV`SscxGxB{>L#>uC!=W- z{1kB{O~LUn+tAeDDuYuhFW1Q4pp++3-p$`HxfW4Apok}lM{jbuBNZu8uH*$!&eKek zj7;FbwaxobJ+VUs*?fq&+*LzTh{OW9i@{fEs_&r;`q^yUl=!Pu$76C`QQY-Hy`=2jyV|Vz`Au8!iJT#K7YujsCW6`o-(4p~^5yE(Hj5Xs z!JVP-V`W~wv141qr{8UNDB<#QhAa2qnL0(%x8 z&NHH;GF#VPc*bzbvr))ULW9L~M3Cv^5|3c@=5PZ2_g1>GnxNXX+8%v0v&XEHp1G^@ zb+B(?%lD1BDoh2ow$5CdWUW9P3m;xzPVJwQp2`a_#k%Mnn0Bj@c{Mx1Tk2CSvhkLS z_GlTe<#=da{rh*i^9|dYU&8s5o<2iW&Z5lRkreCOjIPO;nA>3Enom96^WcQ9RA*Du>4K(k>@K} zqEX-{mpZrF)22BPLmh5VGjc-)cEC=)VBom+h2_{mDNXPqtz&>)`eS69N9r#Dcy<%|RyMOJYRGi~%Ms zoE8i2cU5Hn9F96jlvU%GMaIiR9b;FGQW5I+Qa`5Ng16t9pxrG5RpVYE7*k2`g->m$ zdmy<^Ab@k^x>(oetBR^6BsGd-KElp9Fe6xJv(Thx?~EB=b;?rDbEY*Dm&v zH~Kmn-8$u(mhz}&P4o=E>D4u;(aKq8&6V7S^_G%9soH92rfL+G$P=rZJf|Op2D@()36gOR#MYb{*l4p@+BY`&pv~3x}jttNItWmA&Zh* zYcKH?irLDStkRCFEMM!j6`{60aL~8a{#d!yYn$|G^H<}weN2jCn@NR2&bV`V)S{-v_h! z0>L?8Odxm+t?5ZKnmF`Q2i3}iHJzF-%}(n`FE={_nxd#ki1jZ~J3Bk66w{41c8vJZ zK17hsvubrXCg#0@S=i9xpBx0UHEg`+1^VK;QTv3*<1W!i(z{_j{W6;U!u?*=y_QZc3x%GfQv1(>HpU9RO?^o)lX!X@WD1Y8CBL*?#Sp~< ztbUbk4d3q!b!Y~Mm68|9`Rf zOI$ixmP+OS^KTTwzCL9}MI&0{y{jiT+5|XzDX^Jj0(5u>F9}28Ea^6b+opb zbq${rqF*5B^K5HWG9NxWU~8vJO%}(dZ3I?PUTy;*;8eF`Ai&3V$Dz2$V9WwC;qXQ7 znyem(G)ebHceI)mG;%H)BPC|zE?r8p&4?S!k00v2^|H&PlwZ|#_Y=&xS@%Xy6gHqr zffj-1S<4c#?{P;9y#UlRLyYs6rSt09yO9pYmdae8SHgOxT=ec`3SDO6u=L0K#%2t~1X6y6_-7{z+}39d#6^5d^1&A6bT&vc8QL~_=VESL-`c`Y zM2D{@9znjIV{&=MSHSulTKd9A8@~zSk|M|&in0(9PVrD?ysOg zWl_)`@0?E|`#nRIp%0Kt6(`IIPSm!so}GNh8*$6D2YtXTP9Hh91P zSkj}{COwro9y3chQtUfObuo=~GqlHlE9t?%-o?~|ZDUT6!@xw65X}*EQBXXzY<# zwA2)B41KN zrK3`7R-9xo|JVmbrmax9yWG_I{P7h*^%IlYNkzyHHQHyf>>!uP3~4X5`TFVv1g(7x zJ2!}dZ!tS(2J?)ENGyXta|8n5MwBDTvs$8hRYrb^qAcs~1(8)o3!pvD;Ep?gO(3{~ zId$?tFf?=#%%xBO=QQ?5;z-Y_7`WqIgnj!-@Xj={gYSV+g*Vl7B1$O}+ck-tQs6RB z5gGD;uC{_lAzcPNG+wV1yVVd%_OS5)FvNBubRssq=HZzFL)F#QxA1*#;MR)QrJLhU z-Y30)5`|iG`8w(>RC{?;l7NeH5w3Jm+A_pCz4k=L+ z6k;hf0Suo%eB)Jw4LF%!E#z1FxERlsEQg@59>W<;mgNTp%H26hMZJe57Lf>u1l{}; zSb3VK04$v*?crA1*5H_k)`txvnI2kaOs8*GbNpW?xe$87Dnz+bob{x0(Z*{8M$B^SA` z6{XZ$LNHngC0zb%!7kg8#eUv@+=w}7L<;@28z3o97cd#%Rtjn>DpFmXi2zLQ#>X?6 z@DCx!hDuXn3;D*?B3>D;iZ{>fIig6*U1VJe?%2bzJI|IvsASOz%!l8lr-arc&F|Ybd9lN+~2~8%i>Zue@1Xa`1UiMn9JWS3;}b&WJ0PAaW(!R zGvntsjX=O8*^hLV!>47@_QSgw9o?I^!5;eVBt*!ruUom5JknWLym%KjO=R z1B3t=^1s#OrO5=5{-3!}i{vpd=o4`w6(Q93LbBBDdNbhEsS%=ZzQjn(w1B+1f?H7LLuV3J_Uq3kXU2Xs=UFVmUsHS+E_o6*X+%U=3dac4n%kQ^O`*~9h~=m(dftrBekUPz#jlZ2mi6EF{>r)e}EA-Uw94j zk@62}5gWaq?U%%=NcL^{`%r69Z*dNfug1;xsUkEj$eO%rCeW&-vbGkVs_YYz*9KOk zZ#lw>O_pol(~Zg7pJWU3T-Pu~h^8U@LYFO3q_V&)KI;$cHZ%`}j_r=16P@#=0BDa0 z?#qqUJIA3hfn|t5yRnr&-@or|$;05IyqdkK!2PszFY?{YfYblqTJ4}O!9{#up%St1 z50cg27P%4`#Knrl)QLGDzeFRu%9nrGefp9@POeT)kM;|qXb6_Scp;GcfANpt8+$7l zF+5d`#ntFZS?uqjZ72d-d~%;)@Kq8lpB!$18K8e})|R^f1&vSZUl@$7fr&K}faUa4 z3E{RFErv39x(;VDE$k1;sVM}tm_;dq$*RacIq{VBD`e1WCJ`Z;l6iqiSFlmJLF}(#;YCB%%#A?{JGacxq-Lgd(avwV*>LwdcdIv?!a-Z$B9SoTF0(VL} zisDdvop&Xk(nLY4%=%3jEZ^HwCUJ!t;As78PtNBJ>bx+`qG~c6sUEwC>5glnqlOy- z_9|Z_K(C16fwz7 z4<}M?1)=s!-=41aM!5|zD24$h!6f#PQpI|yaKt*U^#1df^Gtj-07OVcg6Wjh+eM=t zvmiLN*@pvB;adjy7$?D$;FmoJII(LU>*HKQ91`e62>7=igh6hZwY6sZ$TtE8A~Mjq z1uv0|C3wt^?9)UofEp67!~9|^9LN3_I7|S6rHj;ll?pnV3+Kt1QAXE@gI=wKVpDq$kgh{IE}%x1x&;UP&;5=5OHV~nfX6GW(hKt z)_s6i?Af&GKB{Rl#??_$NM&+Sz+-iRubc2ZoUqg*$^OoK-@YPIdTC>^Pj|!k`j_{7 zvotsGEEUj9ygrP->2s3EQB;ONZPUc+pZXX&qb_5$$3R_uFFnfDiL3pL>H!T`Z}CFS2gm|-bjUg_SKuN?H~%Mk@b)9~IQ0NI-5N}8W@(OrNzTG1YS7(Al0W1f z)5O4!pGYrrkG9Dz2Y?)dBv#X$s`S0^jOuib&!_R%!Lb*ghdl6VLesUu``;8(Je6|7 z98*qfQ(4>qN&<;4z3;~y8zFGvu+iIa_|DcC2~zvhw+6`eUq?fo7LBX)U0buD0FGjJ z=O=I(H+k8@>_pr#)`uc7pMVuYv{~bex_Z?W17{R44d5`?gk5=+rYlG}2U*A+;$=B7 z8KQZzRLCnbNH#b+P^Ht9vD-e4LHC$9nyB*lSd_I#sq-m_Osneo)CC^SNRy~7+PU-? zYfIJ7u#%hYdy&(74+0ZY3Qj15a#eq9+N4!W(#VyGsG1N8h(8^4P`4|*(yc5 zY_gplHu}?|uH=Ui*(zXm%_0Es0oDNn{`3bz6JP8%<_nbEpfv|n z-nSIv_(C_%6=D2Rtd~jKZvGxak9h`5o^+I#TyU|il9vP;2>$9yK0p0#KRiLdiR`e^ z2KgtcWuP30_VOTU==}-AW#;i$>m(D1B>GBssQnUn!osm}Z2W$*VkD6>aHxU9v;S3# z{qu$2DTJhWkyaTI@%7Wmmd1Ow=c$D7OihEn05aZdqglQR?Q`7F5S@}C$w3TFk(tnV zo2Jm$)}3@9o+g4#ey`;njp4dgD?Cv5>0;|#IY&smq9EVy>2I2)X7-;ecNi*fBvD^< zf*^L(Fh`c}tra`BG1FIs#Cg17=Z>2vSIwCOUTSO!U}x0iIeBCPE>sZ?&e-YPIaAop z^fldVE9*d!`C*0~x?%f~{7pPb=Z3O3?asrMEP?K8e89tUZ|d7x6z<8T@Xk-Xfp0HB zXum@sofmW`V^DGdxH*5d{d{cgAJ6B&rm^M&vcjI8sbwpNQf0rw`JtYCcXiAL`Uf1G z2ZMulv|qZWFy|04=iIHDqP02xt2E&M190#^JoSyCwGJ2X%(lryf?N8=^lDkn6%b%BsX6I1B3_Ya7dug z(@q|DQR&|5fJj+PfzG_WH6QNN}qGTUzGm(Ou$eCe})_Txim0Bx8Rg1IDU} z{G2Kgt&ub{_&Spec*OG$2Ka3PNOG58@VbHI*zLJkZO}O#aKD_eAxjnrv-xGx_PsXP zcyIF5kT7ePMmgtzMk)OuVj0!#?U5s7K_psEB~4?yPZ;yqIed21lW%-oSd7X;jmQ)* zRCbK#=3rEv$$xJ9G+FhF&HL=aQ*6<6rbgIt;RG&hmH7D6r=2wHeWIunRUF+9JN!-y z0J`ah$MoMpf>XZ~#~K1uyQ{5ky5D5Bpj*WdDOnN)J#>Ek^_|{ti;@V%r4U17JCcJJVOo*rgwsW5mkp+Aw33w8TMekpny4PaJ5i>VRzGt!(!S7kw4@K#ZB4~%g zp?PlBeeyj&QVNUiKD0S_OzV9g24}M;TokeModj_I^jJ-Y1+Pw?x}tLM8S}BiM#4|6 zCd-u{h-d9IW*ok;UaO_+IltyVZQpet0Qf;{?G4sTDx5-zhj(fFa);2*x%cni!Pou% zo*I?@oF@fo-`dW9A?S$@zRGl=972v6Z_zk)DE1*?#e&Ha%%z6UY_$gfj4NmWlqw(S z1p5x{yS3w{=lV{r`*>0@TbTYqkD#A&OO#%xi)Lu069F~esoRlhio@P#ui!)cna&T4 zSDtSxJ3Njn2xKMKCP?odQpD!n2RjPbV@z@}QIlVVcLYs~YvEhY;KkZ1T=p?Pxnot` zwR4;m$~C`gX;u|2Nk9}rjFIWM-py>|o@nM2tXKRjrAV&<$Fr(D1ic((b!W7rY& zBEg^*kC^(qnVyU+YSi354lytq1qy!yopLA7Y!`}v2f8$DP;G#k0>{AziPc+~bV*1$ ze^BXNX%=7ra*$&NGxp1NFFh!5A zz5qYiIhY=o&KsZgWmMTNa0D^LWXo~rtWVVF%Rb*sTI*>)> zBh4n8aBr4)oz^KO&ZZp%O%DU%44wnN5&E5jE1vanHcR? z$@&a=q1LzZgf)@@f>h07+oh*bX!eK>xEW}je9*)WgngZPhsSTcwg!RS_*_0X@%Wmm zXZpd_dsa4Q5{PRpD)@=Q>q*9^O#Ni58jM6sc_Z;f6mtO$;5Y|;6&gbZ48Hku(^gZJ_C=iwU_GfReuT~oid0R~k z6&RvRDuy8xQK9vbwzADgS8hVZNd73j(89A~LX!J;gi8+0TkH!_!u>Ig>cySq{IDBF zT7~OH&Q>~enEoXUFT!TxF*B3PDlw^wz-~DFO(crofjM$x*`#)W=VrMfM&4+~Z`SD^ zK9`C^NSLqtCH-aD){=jd*#$S@=G^v01o=;ym54C1j10G~4>5V_o1xFw3$ITk9!0o9 zEsGDqhp9d9JFXt*EmMxzVVBj;UA>X7^_@>`mDM_?pFQANstIbE8bIz%e-Gao!tu=? z^tnB1JiW6s`D}%>m1z4}85b!_Ix%(sRE59-;47dIs5p3Rc)>B7-56fji_BKX2{KIC z-Pp(HdJ8NWkBb#{tdNDf{opW%Vr!@~SXL7_qdnZ;X5i?ke{t=Ki_-qihbeIwFrR}) zO|5TbjL=vK#ywH*6WG+osFqqHXSt5<^D$S*Q$5Hq$;k0nw;p#{`_Uv2FmdJd>Kz^_ zP1eLTwU2!FZ=78&;9625DWv#UCmn$(_uw;qW?1SWzxG-I1fvqQHFR_!enV^Lo`n)4 zj6JJ@IeKBFhYUIq7=w^t8GqvkIJyHI8r#y|5-ljem#cKv6GVBrK69nfH6c z3Xb&e#w>arI0oB-8;gw9m!AfV;v?8+4rp_nRrYwHT3>*D^5aJ27#(`mOj!3d3vb7o1mI4HaoM zuBs9m;UjsmEqLu)NwY*QaAJ}dzj8`tun{7BByeS}^i#<4v1R9JzDiVyZTZX%dQc~u zOrd>QrB3bMmJyzU|80bC30FwcE1z0(aF3-5IpuPi35)dS+S<=5#*dMCqHZIKyvQM- z^m>co^jOEvHjXW05ST7}arw9MCC`8WLw6?L+d*7j3@YXmYb8lZG3KFkR{$T7!praP zVqerRmp%Xx5D*|x3|o7^|1nSQqB|0RC!55(g@r^%`I#aF3MmNUN55$(Hrh((dEJxo z%KF>pm7CvFZMRozYrmOOwnI|?0h22hIRzqx*w;i1-`?%B@|;Vb9NCeowBbjT$@#@a z?oCc^Vb0<+Bp*~}5(_wkr`18G3mL^6ZB?4{8u~^G?ENSU2q_C63xWZ%&yLdstk$K! zP=68Bn!wKAXaJAX0fmL=Q=vaFIXMK(MLrHR?oLZ{Gr&&tjQ;-LRuFzZw(aHR)jXWm zE$Lp{0qb30*-uG%{&-v*iUq(_1bB~qH$F<1x!LKJS-D)3!5FGD848c?el$#761b&H zS|VW0#3OZ@Fh9a2o4TTdO-oDhPt}Bap0-t-QF7h)SR?}lB7kb?YD2qo(j?12a;J; z))d5k&$DsCj$iMC31NH3?FHym*I}fYX7|W89j**3>rHl|n*hg0*R-~^vx->Gj-B?nmZ(uV*>9%N( zYQwkjNIE^Q$glrc%3M%_z~+gZ>EqgZ4+=-L>FRt-kt=GLd8%9SzE%!A{FjoM-|Rl# ziM+^6Clv3V;&+jeJ1%i!SPS6UXNW|vnhEmQuD0gqlY@Z8b-RiQkh;%m!0O%qE$_olohF*3%g^HH}ALiyX&O zwYzNM4349xrmmtynVTl*59(ye-@hjm_4L|*sq+p`W(&?V%{cI)K5$NguhEq@o61W* zg`9uAIOHn@BLz0Y;oiyoGCA$+?t>Sibu$;D-hIR?t?0|GGsOJcol4Xl9NI}inM%o{=cepk}aLu4g8!AoTe z=4S%H>vD@n(Cdn$)9aE89-WjUQV>0JdNA8+v2iBjxQ=z$XUg7**R5~8p+P;1H-3Qh z+gE%ibRJ~iC;~$6hVQ1YK!t5kIzl>c^eSc4l^d`V@@t+uuy|&B9t5@^vRP2dgnbB7cVPB z-P)0!{17EA3$Q(Xz$)m;CVTNoAj(g_y2dqIr^XW%7LEAmVZ0@^ac_ zhYg3dQeXUh2NpAC;G6jWnamY6X$n-DeJ6>9S(%{DYrX8pELrlBxOAJ3?w+lSDF|OTt zH^eq*B-O&X(-|nV#^U{H?>UTFs^3{L>=-PW$N&pQewlPVAm26e0?_(b{g-5Sb z!G%i}AAKPtjW{Cuw5MjHft<%Z6{@N@#mQZ^P>~}zdMBJ9O8J=aK-9}|-mA~LJaA5N zWvth^R5fgD#7UU3Y>v6IIU1PdLe?%EQwEx}9q*%XKBNwq^Dn?)3q}?`l2Xu#q zHez%wpNPS?ZJEb?z^$pM&KhXm(7P2DNq-Ucg%= zz%x7}1i6a=&zo0Mpm*TY5knX!3lY8w6HhE2GY=TxV~@oLt34oD^_#w=Uefnv^LZ}# zzpfseBe8LD;W+Cs_(~SwRnsU4&+dI}w@G_cW7C4|&(y^w6}}C6Z&+bRY0DX4bmvz` zhX6w8yrKw9gFiyx;Nakqxk>Hm)nCqS|GV!mFh@uxPHP7_KhHAk=0!?3Co_Z%xFQ!w zmsE0tEnX*wV})l~Bu*m4{7zJ9U$25px6pQ-CW-l+`-p{{XE!4CBt?7+JrgsPNm3iO zrm>We1@O`VpeFz?=rMDfuYc8!`T+q;#sDw531Q3LeJ8ygoT7g0q@Nh&R>grRu&yTACI-A2)`qw0G(ppG<;k2zXLSD|={DFBH~TRsbJ zBmsxI#>Bz0T-Np%@-Z3q;A(t~!K$A?-~{L!nDK@pZgxD*gWYJd4PC7>D?AnO!y8zY zUZFGQ{Jwx^Ub^$Rhdh&spC?{CJNm)Jl>~M)^!QwTh-QEXp|2s9s+5X;P_A&_NZCk) ze&++qI|zNZyI;}RDIlS3E^9oV>{q`xoZsNUUfZDgbE2H7Z4DmKhqT)~WJpRJwt11a z+TjuVa+fR0L&RH^Ffz``g^gi`r$2>nqfu)?2r_r7C2Vsa*Ob6E z;4Vj6=A-j$ZmK?fxXYrQya~^P24Ld^)Un=JdKWygN4mHNGs?20D}s zd^V$;&ZL2U>>&AdU;O@uC!nG^uH51TD4ap6%0_~##FTc2j2vUiqsk;v(XI0|^@D13 zvgA9_eu{%(1;1p{C$QT%6RqS&8lFdM9@ zHEwpjdM6_2M>~Y*Zrm;hi^YP3&H};;@aTzgUmtIXC!F4tC6Vg|KZ$|&41nvt(UpW~ zZjJa?&bIJN|LqvX3OOl1l;5QA9*W2NkPF{!at!AT2SSNc?_G@#^6$CfI#Ff@hD6If z(0eV23-kg2VN2{-3a);=9AVW{{^CR7#$uH@aWfvRK4wQwCH$Fe@q|1Hv&l2jux6Sw zr3tmVif!J^ZH=dLs;POBg9P~~^M!qI;5$tA|LdV6L4PhL3owhq19JhNcl?QV?*IS(Of;Zs| z7CON~(*d$qNYRrjkEdzjI3LuvMC_BYA0MKCCxyG;UI5#YnRLgB-EW$DYSEHD+`c!M z7piE^$C=0k5l5cSB3W~!ap{rhBc||zNZ1Gnm$OXx1N3${Picx5rm*-Z$ZmwP0jGD7qs)P^(kdg{&oB1h`qf2p08EFhJ2MINox-C>;H|pw+f2uZMS`K z2->&=C%C)QxHS^o-7P?n;I4rH!QCZ<;GW>_?(P!Yy?gh6ec!6J&brtar_SDWs<@h6 z-Br9#_dDPDJY$TX+qApIldo`C^|z_)^R?FZ#*YuR@#0GcrW^i;gaD<@VA;>8q(y)G zLLr@yo6fO7$bDzN(JA-CHjE5Ljw7^Jo!5vX@oR-JoNWS4LJ42KwzxqwAxN3&#|k`4 zNQl+!nDy+;nj-;=F6GPE0UZl8sh?qzRLrl>aieYcbg33fiFGmV3Bbx6Kn4u8{!+ey z@tIN06B-whtGv8%P{QS@(W()w49PjGG!Q^~ZC!HfKHUri#7QHMkH0^HZ_1$oprTO~ z6N;m>dG8{HwS%lpO~u&~7dKZHkaF8u;rul;l5FiNe*WCM^|opW@q*v^BL<J}s-VjX+C)^g~Uf7Syk-hO>3P1A0?rL&a{gdSkc&LjCl zO*n608ABUmNg98a6zyV1A7@=}Ugg2oE z2FMKlDEH79pCg{7v{XssP{zQx1GGhqmw-W~7wUO}uCHNBv&JMXmJw9h>PHii3-tid zm3tJ9+>ZlmZi@kQ4gN;Vl_k5QKl-HAEp6i`e|+wK9$#E=zxk)-Gm*tPh31n zq6g-I)qlWEP1-k@Jmb!tZ%x^%PG@-1I5i>V^2>qH(CwzI?M`yZF6+SCnNFX#Ok&a& z^G}UYZ;{?9+Kag^>hgh-OBFdY<;}`xnFv3Mr-qC|jcHX7pkb~`jx)=;FuH4u8 zIvf@$S~;anRw%{O)137VhnP3>IwswG zZp=K6>r)MPQB$()=a>Q{mHOc>QVzLEUS+FaDA({(o61x6W`OOlZccuTSG#zQuh#Ii zGOrdVwu-2w*xv3zPB!6GnM6$GFqpuw<3h+FKT((v=nOsXzsoi3CW6RtJ z@`u=NO(*E5y46vP()?Z?RVOSWPk+{Fo5nM(He`k>zijv;-~av=g=Jtt*KK|G;s<^L zQ(~P)ZptSkMu2zJMWr0a^MqBYSuTZ+Z*T7w0ZIkD>&;)PkA)VkCbGq7dalt?t|}|* z$Fim}t9<>*s+xz5kYOR&B~(!Gn?)iEh8UAS1d1Q(e0pJjhM&$$;|gxii)})nR#QF% z3Q&p+_YhIsY50Q8^ieyu9EgyX9`t%zcNhJ2544s@3-Ij9uTD-jQ|Jy&;DBh^78UbYkbU+x@#9R zjDjE%zItmuIMI?jkD@A*6s}iq)6MupS!9t|-F{|I(W_^Zf3a3109k){+n2_ghz?69 zU*YWJEYh<{6}(iE56Z37YhMwGX-B$;rmgG?#B*KLy}mo|#a1AgYaWLr(W`9bp79@I zuly`2LG1CU=cP)ZeO5R)nzlF~@?6P2U;l&5*Z(48S~8{l?R*7#SWN?51>M)8cd42Q zt(_{gZeDnU5iLXq?nbYUUvwb$XiMd8^s>+B_uEm_Xo@d2%8$wyKnNRpGxYK8hW*)s zo|6;6hB~48x(IVfZ;u9T(3+a?iK(v@E`Lx>_Z@ppm3M4(ngO8H5zutb&<51yqURbZ zX}(oVi7kmRk!@bZA$e~_)^HvujRX$j``_q^z1w`HFe44yzRMd5#4 z`*d3ruLNvxp2JfIy!Nwia5=Z%G$E`XUf*@?ODvUq3YCNSgz2uZ&aSMaU1xi%1Z-=0 zfggWFQ!*d@_~wPEw$c&BV~rYC>|;xQQm|e$HKbdBRpYmgjOD{t{Xo5@K`{b-Ql{Fl zYqW&}je=-}ae5inVZaCDCy8WVH!+`)v?O(Z{rDL~suy%}DhGTcvKtfPl}N9Qh^WUg ze&QkAdUQ|z87`Xw=gb6~nhHQKHI_y*YHl)_YXhM<9E1!+KZ;njeQnJ`_C(j{ze@%|~WNQFx#>VerK3_CsKp(}AlS zVF)2v_J+?1>kVIaekzMzte3)N@?dA>rXw%K+Y?Q#(VpB^fxN$AO@51cU}FtdPOh2z zIpuUiUSG@ZV}8`-NWg%lw?7*~$#VUHI7gT%s;{~b3}@7l%H;de@$jQqv$ZU$S5 z1eh^)A`2uuhRI#wpITla6UBrQcxzc!Nl%vWqt*(7r^~z*J_*o#iu%yS?A9#Fp1e=v zIKp{Pol}#H8tf(P_gJ$W+)^S(nXeM02e16zy64JXun>dA;P)ERc4UIM+z(aY3m#uj zUe|~1U&XHN-Y2CQ7|O?v(t^5eUc@}@6=U@kx!nCSGUhR(4$n11_kSRMu%WudfoKQr(6weOTE@t{-mDFAbi?IIid0bQn$1rv_WQjF#F$IJ z#=7&d4A{9FB4vzSAR?pbSCiD`UAeX4d^5e9wSBkC!1<0;)W zzzh;)gfNC2E5#h3(WS(DjG-PyeLLJ_AkXAPDO=n|@87yzh`0q@kLRUk-#}aFt)ENu z8eFJ$0-MqaY~jC1NAd zYpU-9?8#59GYX>h`=LqXnZke$XUYiXw1aZd^WHiLt$@mOQYZR~S}8*bhXIyGgg(k( z%09j|PS_-qrD`ETni?7rqv>bf)HkXGl|4>fy7*cDzwK1;w@kzDHFtYl2cav#grDgF z*5CkoJb&03%jL9D$>Ayk9DL2(Cp7VShmD*|$c>nZ%Yi^p|3xify%Q3&98deEQKp(P zjMq^>mKzF$=~E%(>-X?z?3qM0tjH1);sZJR#l%ezVr+VVkH4?9SIR9}7RePa=EbRE zG8CzU%Wl}gOktA|6S%2YF>*F>CG#1{Vu51u$^2CazT|grvr9OK;5li?1$W6ld00Xn?Bjcq_vlg-9`5e)LZH&dwNS&`e^7-_uQ!w9WPNXK z(f)f9ctT9%vXm+yVVS3%KHcwKOtbjFWTQ}4p&&%~xzXg6T*Dz7Gw>p=>QZoW&%2X+F8@2 zzB9A3CYUrGCv|HeODwIyJ9uU3lp?l}MWozl(LM!b7C`LpY&;Mr-XAQ{{h~@EeRlFe4HQw~JE63084>A3; zJpNfO0AAM4_wluVNiH(vliqe}obwZ)eO(=Fp@@J>YmW7m^eBDHAb-nCyQSo2@|ubh zlDU%p^zO9a2G`qt8=VU%Xe~2n+g(j1Mk*50*E*EE#%=|WuzWe0D~f$5YKc$^Wt|3& z98e%8JJiUuA$4ECn1A7#e15(&+2#xuN8XOzICqv@^1iVFO2tmbSR?m<&NiAC-Se79 zkI{ksB~IslxdLzXPOYnntlo8gs=;#tP0sgfL4zot@C z31-n@uV5Q~>J&V+p&KlrtrIHow;k9a|9qc>EOIl(jguaT6MC=u6VL3PsiCH!Q8eIG zpzSd}`rwwW?J)x`Syc#v#$MAlZuJ`ROkA3SsZ)O#RfH#{qUNi}{;H6YvU4l##2jv; zK%uAsXQ`KX=IaNx`_#=-A6x!>B}YL+c0y0x@I~D8Tz3hUJIvdft)b6656vtWPPATc zS|jj1HOs9c!!I#g?a|s_z|k>@h)P<(N*aqEs~w~ zyiY}Q>DvbJv#X$$70?=JUp-ff4v#$3<0HliXz zBr+-z{A56Le{H0=7jo67>Lm8X+qY5ZCWoMiD)>;t{l)-4=Qa#BzmUO}CI;Tl>lpJ^ zxBVv2?~}ZWupybs$zSbo6SnoC4SGRApztknRcV`d-8Kqyz%i62XsGWgxm7^%nLJg% zL%pFSo%T%1REqfO1M{MS+M|T4&udqQ@O2VCcOsreDQsB3W{8?za%j zY%ezI=!KG=e(XsRUvdxo7aZfWa*q&cu zUrwl6Cb}l}16Fbq1Lrzqv4YPgUcQ~@M_!4GdKcovV4*;YhW8S!sY?k#Eyl-^Mz zGFnt_$l-rV@Xr)j-Y%AV$4q?3wEAjF-oedwepY}8+Nxx9 zIQHe)Rt9l+jg-`l_paOj=$$vCZ{ZAgA!<~2u zhMJo4cYUT>W+y0WFvB+Pr*Q=`lT*}J`>(NzsMdxP2OZGf{i(2Nkr&};8+1&eQ_Wc! zwWxsneuWKu90;)lLyi1dNi}Ykzdjy(E_)E>M~#Y2vtK-6oZ6n=BicY>VZf2^B!jav z+eYB__Yp;C_u(cc85XgnK-+e4N25c4MtvvT<}1DSO@I{Xsg*QJY@gXaX06V$@|AfS zvKg#S+)N`EVJ4@f#tbBx73yai0Dge^p4(|jhPZ7^o1@=g)r0=J`VH5h;U~NLh;Na& zIPunS=kNzsWvpVd?yt2LRu-oP&`z|Xj-K@QF9SWRzZP`C79!ZzX1`q#$zSpUUdx|Q zz7xff3o|wSx!nr9>L=`93(nk!?jK>3_T8;%L&sNZ_1`8(YqA#q2J7hue?>`F`R^pc z|NY9(sYe^xy>HMPm3Gs-(--|{C-pxdk3XTGs`$RJFq67b(_Ci-$!URWnpCS@`~TjT zgt-feW&dVAU1zfm#@g|6WU<6Ae!?Re=HDbax+-CLSXNw%XRUwJ0i#ba)x|-9T?mf< zrUSaJOQ70j5Y1Nq8B}sz~ z`mnUq@jvrJYXrLsL=iH<f*>UeBqudK2=kzB#l%{m0c|laOj6yB))cN^O4T^R0%E8T|Iay5D!i}Vd zfd)K-bL5-dpT%BEk;Up|IpJVtngEBn56-gKdZQ6!xdLG?8#5I z#!ZwlKJp%cq_jCB?Co3l*uWXQuqiYUGh`L_}9f$cl9R{m#J4~<)Kk^2G{qz=08ob^$ zl=9+8#@1Tph#yZdh*2Oj=9d(W|0e?QUxoW`guj0kj$fb7^#4&f!C(IgD*RXBeou43 z{`XRk{x{6vzY6zX6v2PJ!y5C1BlQEnnKcLpcaf|(DD_i=QrCYkHJ6)iWbMCTlj$wz z`6yfJVn9E>E-@HvB`aH6tKsng^7YIlzM_8kcKs+TEbxIoq6=@lv@1(%$u3%%$GGY; z{DfD&4qEMAerKyTtl>C~8Yxsd0_pq)>D5JQ&PY7(UPxX}T8NS3PkU;G;%xMLpxhK?WuM}Q^8R3T3VIG3x=?R7n8XQ?QJ7<^y4WMX_{uwhxMk6d`kqEW3WrSXqfR}a4yX>09Ua%wOX8%jpjDb#;{Jq`BC*vj-3glGzxds>*pZ+X$YHKMIxJA{f!ACY?*RGdrP3*tM z17!rtfMktHWn9gs`QX{u`GH-t{$sfYgI;JYGkeLQVI;6*_p;*t8E@)58a7oy&!%+LYqJG-QzuK(f3h?ITp=|%e#gsOaNC{KP}hwpUN)eC!y@9 zVC;<8Xs0)C_z$*$|DNCk<$9k`bS>PVB0!&~Cj$4G;I6O?gDJfxPQydzHbh_gYQO4> z+LPBiPowoZSfZ33U!vP+1}!eMe=-g{^Wa9aMvw`QdjAz&<@q)0<3NqpRQAU2;QZ(2 zDvP%FQ3_?DQIoNYPW4k-tivhyC5)Zs_3sxgga#C>XZo+CAxktS$%N+|Kz2_ z-CUVmuYsY{Q;`qei~PM=e`-6XMe6?&-=LdkPYhlQZe(wPt zG)aq-l1Tcgd0hx&&%xe*aK!KY{_IX2vZbS$DiKt{eL|UD6-qPN=Iyq9XB@7iTEm+H z#5qIG@=S7XD@^EL`Wb6BQd?!AWDP9Tb}`-JGLNXS6+jZG@vk zW!A3Z;HHu$z;|tJ2MikGQn|rU6|?o!{veDq-cQ*tZM7@4la6~@kso3SA4qu*6|)@x zPP1y&1jQPM@Qi*ql_X)0BmD&srj%miwJ}~s^8?#9k*|>XIQmGDA&>Wrs|dL!R!-y6kXEsl%tgriT#$knj-$TK&bt8z1n zx>8i$BX1QOc*+*@$jlfg`kC(lr~2bvNtqbg58Dcmgy%)>`eneT!-Uydg^t+)Ons!? zEM@Y}Qd1LOy zac0oL-7}gY|W+5 z@w~y8N!KREX(Rdh=m+|9I9oGM4>~!47&|HP&bYhji4bj$#%A&JNT^1lP;J)t10Gez z)BtdoZ@_Yz`6J*QfE;E!H*j7-~yqzcsE! zT8~G<`sJt{G^Z5ou6Fu&qPU$m{8+-9%@q8a7{hf$ouo268;Cp$i)X#Enkam~RJsVo zqHA4B4_-gh+NvP4_pZTgR}n#OP!-w!V3`wl;MJ7hJE3+vAX$TQM%ClRx2E5t4r9M~)80dh78VVL3;uGKmB>Im-xj zLy+gPq^}$@rh8C!un8!ybL^1)w{mpPp?)Fb40&_aO*J;7LaUVk5Rp&?j%xJYg3C>vCk?s3z|%0!6=IZx3JIrRJabYwq$>aqiJ<3t)6k`vg}(?I zY$thXe)osi7B}y2@DWzYR+~ek{ZPA)Yoanh4E8ib*=Kczn8DvLrJ+hDJ~RSWybDh@ ztyzaoxDX@!u%35-)VFUBZs>dk4O0G>E^}*QK%<=bD7HRbypfi@3EIE`nRbNkrcSKo64OW@{7mih-lMEx6b6`ybTO&aLq^NE z9>EwjH~}%uksehcvu|R4loq+6Nejg3N=gHb93KdHtH;b`SXtVih=1gPF2SkUmFms% zc}hG>Jq}HrnG$jQTXq88P-r2+yS6~2o`+-ZvT>Nxa1V=H*bR6g|H`m?cfor>7n~x- z9v*3je9O!;i-WvGEQd~4JA=WpVP)1qE5RkXCzrJ($tDj!k`m?3K!r~VqG&gM$ykF> zhiFqA)FH|UNm@(vAvkzqpokMJPk@$0)=mRV-%5MOGKTw&vBT>7Kr*9(uv=TmyzB5u ze=ug$MUZ&wrQ;kQ>sf)>_)bH3Ox*8eIsv&;7zj*P>*a^p|9pX#47d;Zk`vgl+2;CI z+J~{;VpsGu8wp`2%q0`KuSp=M2`WXk|{9`4wOG*zAhmo!Oa0lc9CwH zZZ}F&ha9MrRvZcpY!P($O%=_~!R#(`LTK9ovjgMSHwVf9aS(QJJ}jIQT8}U*XPb(U zk`~P=9$7ak+Sd=7_=tC2v-C!wRh$KL`)l6S8`ZKV&}`V z02S5#oxVoD{?GO1f^|0CR6j8$3}Y?DzkPz8m=yZd?@SwLDO&HiJIW!zEo^-K!_aHS zE-UqZspjAz?d^H?%HR0;l?3aeIh+*BAs`UiFnogkfd^pk4FIMT&cuzJ9v78FmwAaW zm=tvWLDY%)*eOFbGV_zJaB2w@m?(yeIvG-%L(g0sy^iTJ+KA(vRuQZL#0sNY4{+_Ts-FfI|`6ViZ> zKh&x@ZShhoEhq`-^71Y_sw<6;jA@Mt$!zEJKpyVE$0sLJ32zn$42et}0+2YeRVtS} z#AX)AKeKaf+g?Ti?oc>ojj|oAP$*WmI?4A*I5F5GSRC*XZcb)@a z6s=sZesJz-pplaAWG2~GuFgO_BB7kam>9WlRC)Samw?4=X@~VxaJ4W(kh-3sh&}q# z99(2%%fSczlcw9ibt)*=a%V@)VyKKjK%|eCepQ+NnMNA9MN?-A|{sWxU>dbqLn|3OkNMy#rFxRgDEr1NXg~s#Nb^M-#h%9 zzZKPrlmRP>Dj{dI@dY`%VE7k+j$6!f$J={1B+%mFL~bbmYr=>qmo`g?K10kbY2qd*#cgy_uMf}4+x#IF|FLvRQ;$g#1TyrLXb3L8IxAd6&B z$|(yQId6oYeQ>Xo;s1qil=`;TMY6npm`Q6& zYGpg=?8c9*vj0dTzhc&TyA6kIR4?93r3a$7OWXXYx0%eWG-y_oXRxOt=KC6wgu)0Y z{rlcpzO-0!$v;4}A8{7nk-@3dowXQHbgfaDjO5}5E#?wy5+c8zxkncmpxD!h0;uh^DaEiYBpq$Z) zY4!xb;Zc;YtEox3ab3Rx2%@N!cwZox9asB9!U}~U7v7t4yKZYux{@Ys0Bc+S&i$?8 z((L<$n;}Hg3p_g=bEUd!_GLxPhD}mn9IujTH=lsO^(p&Gb$9=5&>Mmdtbya=?J)5J zhd-U(OkxL{#uN8YU@cZ}cD3iQhcNOMn>eqB0J-=;=u3ibrf91hZ2B4-5NJbsT9;c8 z4npKIVY@-vod0mr2*m+*ip>ZC6Zdy7f#m_rh>gg7jMcP}#+ zlkrzCH&U4pWtV^*LnW{MKQ_ECQs-41I8@xm2qGJ}>_&g!3j^AJ^IO7LCp<>E`+0{y zvbc_co-T~5gJvW_X?DZIrJHtJmO4a@c~MELOUHj)XB5= z0GA^S)$WTERy;?(?(TzM0_3jC24batE3ffvY)M+}`l;Onyadwv8gVl0U+fh|nMY(8 zO23FW86U^0jMMohC8$qn$90JWU#XT0w!bsGo=`R2@%N+qFPPE#<*5oeC&*Yj-&p>G^2XlfG*l{^vtMA}kHw0DB~{ zIDSJTZz3WZ=t)=1+0HIP^n&XYM0;napinDK=R#%$pB!B^F2@l{fZ(|_fZ2Qhg`IS@ z1&V^CP{WJMpowzT$C3!_4hg5mqmUF}EM+fgYPJ51kzM$+b}W8M|8mVaGC?tG_lfLA z8Ifn%j~SGV6eu8wO!566(Fw&tG?2E<`?;YVvcr#~qCO#b68(pHDE*u`${h^RJ?xxM zH~+-nz|zG+>;`%QC%e|byPtcZz&ho0uI)I>D3v9orp`bbSp)urlI7o$ONtvDvNyZ? zjUq$B^GRpb8F#o23a%%og~ZE6!-AS7Og{Pe2?dPNOQIKc;=|rHJFi+}l8Q4hgsBO+ zzJ8cV0r$M(WEA8Y+_Z%y{0!g4Y~N=DY_xhCq(%e5d$=h4IT53Sb6r18N2~(pbD1Ff zbkYwJla$MJUlbbR@WOOMVH9D)Vk1#Oy2o@_iR?i5rk#kHpAAd9$K?A%(notDTi^8+ znWHi~l6C1MLnH~_o78g<)=;t`(D+2=_X5YiAeDI`0Ep}hydOy)$EBZmEzLLqK^$Jd-?>IVA8;pA&q*S+<2 z===M-74t|~_@{KfrrL6-oSV#rz`(&+@1?H1DhIA2+)qP%7BM^feLw8-pw7E+%Qfl+ z*soZc@*pbo0LPfkb5rCa*#BD4$YjWsh?+cT|D)jwLFalm=0|%hs{G2EGy@?B3q?TG zO}z2bD|nB$$ust9l`bRi^liSP#{(9-z1=7Y-kd8q@$r|3jI5RJqhCW#8FbbS!5;72 z{{G^!B4JDARYTF2c*i!-z1EIv$I;rb3QJ{`d#pP}HTvSNZ=Qdzwv_EDxg`iw`M&qV z9mwS+;N6a@4FghXnZ+D_AD-2-Ig7wYn@8s|lhe`xI9=G7MSwnVeWF8=b#-yEv?Mn^Xo22mim=BTFH=)Mem#Qn(`0W~xjnTKVnY8rII1G}sjHvp zncLX5q{k^hcMMD|6vqBjb)}D8Ihb1PjDs#N4cCr32Ug1nT&v zx|gA^%iMeuJd2v+_)?XD$jU@kYI_6X{z`p{%Yod|s^J!NG6JXIxA2>~h>N97qOgPF z>N#Bh&%*48zK*3pjrnej(qOX)qD_GG1@H}iM7hC*M4&;XKok6UydJ2a@bw*leLpW4 zsu=;aM8k@kkmx@FO5Td&_N|rGtL?UpJJ$-X4Un%GDV?MZXXC_ zm8BX#7IZZU-q)P0q`StgQ?IaF{ zp;5Cx`pDlXd$m}56Q6NTHA?3sQLMA)glo!0Eua?h;I3yIvuh597mjiGmg6V-0ae42 zl5dz>cZU);@*65F84RA;^MH;#8N4tZ6K|P1Ev+uUU^=9R<2zu8v0VHu*lZ6mmzk{V z{$dl$>5~xg?t+G-`|YI{<%w3v>^PSWcc&(N4`Iwu=EBc9#>eW6+4?SX z9G1yLCmT-g91G(@i;m4 ze&7hi9h^Z|`~koIk^@>V0q@Be(?pMlIjes=7j4l^1S)o;rZE*g6Mr3kh(*+sOT>^L zRDFW*X9nUC4$2OWU1BN(Vh#F#_NWa6tlhN;=I#w3%Wl+@C^i$~Nd-S`T-;y$ZC9BE-*?BBWy;DINqT5Bl*14UW5;lMPR&7( z$K8l0?M*&h@rU?HT{Dbh6#^X-o zN8hJ0)M7lN+A$vLu=!B6EXJ5)kSZw<*6Es9KqDvZ^`<%ByHO35+?vcpD84FmF^B30 z(jhZFE8MX|b%(WfXUz(alHAXa(sT@w-&lDo5ap$q46gl?ei<-9VJmx(cTY6icww{f z*6cl@WU_rBjwD;^eWsNRl|i!ZA@eG|(e}rQC7&TCe%pu|kuK^Q3Cllm4(ZI=03MVY zE~tZtc2?$V!vio;{}@}|6goToBrKN`vDE6$F^3(8`UG}}VAP&ptpdRxZg9c!p##aT zO2lk`quS=B^|c5N9+_3L-kS50oYnwysT;^aA3Du$>oE2kWYLl5ce& zTKHyH^BuNL+mYZFz{zFbu=Z>)32}eDeMt*|T)FJDDvMNxJc2fWz=(@LsZ}`dlI0RV zm!dy0u1dSCmYF&?UFpx9RR35Ev;IG{7Oc--RznHBVPpCf*-*YAJzbAUeMWU z{XiRhWR6bFsfgY62X5~fOO_KtDo5O%>>i6FsL87}O1E$ju=fUy&EPTdzrzpfuFyVr zwZR415-2VZQ{zqW;hK)>rn6_19Wko1(mELoQahEmG2Z^x`yBIoW(ba@zx-XG{O}c^ zu%DAzh^A@zu|&2FYzNefDS2y++8<6(`c+{?Zp&lin)hrHs^PF{cpu_cn_pJNZABTGXvI zJDrg?IG*J})odQQ_!XE};j2M8iiY(jcnf36*x57_V+VVChp_<+dG#7^cxtw_MBhn< zcay&i?Q)G8M_3G70DMFB39LWYBU(tD{Y2yCSpRW{rcd$pbaq)_9~nQ7n}pBKYFSE1ew|Q086Qy2qCI-UK>35WcN-A-FkeB7 z(vZn=hZ6G;xSQIQ%PZ*sR7_C|$;W|xvzf?dl(?$+9@2n=X@X~(@deBxX@SvG9;I)1 z4jx+JZyXx4)G{_UNB!Vw|J|D-#6^3m22h9HwRh9D*y zo@^D<>^N`2TuHqv45i+Nih#MH6rFK?VZnMue^rTWjMAQJh-(!emzaZ~f@Sb0>PU_% zOz|YeQh{3pE&oNFp7do_2``!=CicHPxwYm>LLHMaL3f-QQtnmo2p7CUQ?QJX?qQ0N zSLYC&j&v(m#=PTaBGWtrKj9LRtyjKqsKYTS;UDK=b2mFc58&pGy71LAU744R}4Xs7sbjk^&h>+hLxW z?kxoicjnG{mdejagRTmXBB$K!Jp)Pa!wJOpKFu~KN%aLe?1akWk~`jiZ$Oj&zNq0R z4%1qMyL2^JW}U7E+tM~UrGg$X$)d`?H9gr-*4BX>l_Mm1;fHFnQQ|^*ZHB}}^j zn>MqXccob^>E?&{qQz2yW!QmGdE(@2ykR%9ZTEN1u1=}L>q>pN=Wb?{JxjgMgH@^+ zHaF`NsWw)lNc3jXN@;_>dV0q<*9@N&(34V?%cFeRa=SzPa=UMHpJxe%9d;oRIyyS_ z&mOCHSlTEy&E~dA#3rc|&c)?vr-m3&3pFs)hy z5Luv@7Xr}wQCdlSLxXiHewtf)Jr&K-hDfhntF`h)1hxzW@Gu* zg<6=MfTjF_)Sn0(m6|A$TB}Ym^YpHVejGPyS3N+i@a3>~H!n^CH69bl(F^#Pk(#`I z9Z8i(l%4CUc$Ho(VHyw-f5e=~nvH<)YrEniqH#{)8$#nWXP# z3~X#`)8XM{kPuob+>wmd?wT@c7_XFKTKt{K7{ySt@=Na~TQ92XEhQ;ktVtcgR@OZq z=}wLB%l#g2)u1s&e5`)4i{`sFIVcm9Z;?C5{WTeK{5l)S;KNnyqWX@+U&QW>PxO8o z^o1v=?CQxOOh*jJXB^~T!8s3dC)}cXMcbB>E-?h1kQL-7&n+LJZJdnx(lRZuH=;$t zQ?vkk?t;xb@D>K@~_l{}pWcoeCQOH7C z2)Jy-55{dUa#M4T|O=7*#Zs~mCIOKcZux9TIW>a-FjJD5S{@^N2tg6Y)DLV0TxJ^X5kS}PZv_zh6M=I(wM=I#E zbo+4Md(c23c?+Y&g|yAX%K*CJnN3I8PR1rmPY7=MGncEKs*|4KRQXs`+~2@s;oR+K z>qHQs&X8xQ746WxT^k1U@pUPh{pV!4?HGg^GbA{0BoiG@kajZ!iQ34Au(N|jfwP5y~lli zp$;M0Rc+{NM|HPp*O2HdlhnHc&NkmewzfOF(4|PcVuOUxH@EuztjbcnS~fe?@jz~USrcw!;!LG0I%B^gU9U>cCFO@_+mz1e9W4sFijmqmPb8S zDlb74*FPMY&rHxqEOhnD7;ZuG%Etkl#&^gnF}O>jOJRwGjT&1~ni|ZY+u2%86XaF> z0e`E)U}FL4<0dF&cbcv`gq1CH#?7WHkdDL)hQ2n7zuKacb`Tm+vgF#_(sql0<3)i(%Xy#GDD(oaLJe3 zA`URk0c=bQ=>zf1L=o?pNZ`$K{j1J2$idJ5)6khW@@i2^GtgFyJ4SA+(y0$gS^jNR z;kC*gJJT0kQrcLu%roiOL|jOjJ;PYq)I_kc-iQOp>p6~2q8|gdqud6#0C}oJ0WM4Q zrz}sk!?kJ*JENRSh0cHQuCPo9B^6-h|Lm!Meup4Jhrm$MZlgf#D2wK}2W!j0=s1xv z{(4!DO^(`nO6B$W>Gz>z^YQs{>X_=-v-|r@Nmt8|(!@cYIsSB?Ft-)@161UE;&azs z4U6A+E6VnQgsigGWim0Af#+MsTx84_tLhPg%y0is}w? zW0}NI8|_~l7~e?$7$eMy+((oCY`b^Nf=nddBZO$l3g#z_yzLEZ94uW~9DFcu&K2~P z&2IOKxBbZh{Ull4{LuH|cjm@rfEmTOv9WFf<&x;hCj4-rv`J2O)J&7J8F zjKo{Za-&1@X(&-7aaCVmcW2ZQiGhIu)ob(DtxgiX!i8Vn#&rhM26=q>-2=PchBbP{ zFLxV()O}LiD&5HwdWIb~eAO}L)r@ITAScGzs(aPxr9FGxi(R-!H0**cW#6M4Zx9Q%0pzVZW|h zcYD>outXiGYMa5ZdZ`_mSYdM>&0Y=jzBuZ4puV@5kdCi(!d*eJFuTyf>{A^HjA!J0 z6ELu&Y&>_Z~L1WUpBmv$zO(W zcnic+1HVWCR-sAD%Yj>zbyyxGZ11@{=qQ+1(zvEN{psF9CP@$9t=35Vz>(0NQhR@e zTBvEDwGuMnXwQRgx>=jBu{&klbMJZr72V&h!x@YOTve6HztGhgv?Ea^l5`HYL@*Vj zmV6vx(WXyuHyxZHOLWe~1kF+fDQEB@mMd;A$2qFceV`k(xi1fVTMXodKsv#JrDWcR zXj??uD1#h&9YDW6Qt_73^{LeJ5CVM!bwd#u_b-*xv@ZfHci`tdNdN1zPA3;Pi4CQz zczKxX%&3h5!3ag?j7}^So@3l1DfgPJsb^QLK{LP)!hmqm?)xPxG!kyP}rgfe@!#?>u$T;0pYxFA|N?toGO%(jGu@j%n%ftJh01#+*5mh zZrezo6)|c5O7z}b9@p`MrQGoyvg5R(4@Bc>*Y11g56*q~PdRy%L@O{a(+=9?mP!Wx z8y-mU8c2}{DPy5rnbDWVVsO_r?ypJ*`&|ek7)%++mOM~P)Zc?ml!nq?ng?2691Vl> z^>#wfXt_S}EA&(Bo1&7Ha*x?Dv`L_|Hn3B+p{!y5S2*$)okhJ_j}A1F-kY7Ajc>GW zD=b{G*t`)97Gyz(LKgmUJz=JJDnirVbS*gMipC71R}oOK%0 z%pFL+Ant7Utsfe&k)+m5LO!Pq2qO+VYtrv$o*KUQbBQS9{H$=;YSBO>ex%~*FN*5+ z8O)Zlr7h*zS8po534>4bu>8&9!5~HDjK4*i;0U8{YF+KKO^fs^kl6FrO@6IY7?P_{ zoxB>2x1JJW+?7baM|;T9kFhTIlLcirEWY;UTJFiWBcdYsEmA=L7S*E!>)xn?Nvhat zMqOj8%yY3zQ8dCUJxEa2SXZnt`KzjxS)M1}?)32S`J3=m^1YNsK({;19-)(+Zvkh? zaQD<5mD?Lhon7}_uvx=DmM9ZL9<`knF8tGMK|Tk(C)G$c)Hw|fLZZGvoYY6+hh(!M zO>wufG%-l_*5_VQX0Hm;&{O~S7mJ-`oBLo;-lwVCmlIuyf#O#R=Mh9FVCvJN_%}xU zlsi^3L&s}JB`bSr!ZV{!VfO|KmM4NFMaJ@Y2NCnezYeIg16NAh>k(w)s91#LEQC7t zVV07v^YT9D*iHL&7hl)L>A{lKss@0grSMKMTIa?~o=lSL zJ5ixS$BJ3;Nuo-vq0b%{=l&>DfR6hHZ^g`;sjCV0Z0R9f|9oY$GbMHXPz3di}vDLl=`QFVWJy&ccPM~c{`lExy0Jd6xvy5W*<9_$ztysNu?2fHn*lGeXOXXZ3l4tRY+O$@lf3dR1O zX7*FVu-UNLzRmk+FYU+JwJxM@hE^250h4Kao-sQkxms*g82#+1`j6lw#6b}wrUyZ< z^`ubRl7`{R<{(k@(`Ny7WRn*Zo*e?qB@=U4Cp8M?8zyTnI-d@W<-$Ov?X)RFA@sGi z^hT9na&CZnO2*214DnrUynR{tkFXN2Q$vW1O&~vvGM1a4069SLxd;|_q*M}v1h{(8 zEcwGvhQmtvd#_>vFPWYM<_tygyi5~*zl&(7M%`8DBz?{RUHbJC!AY_ejc@1k|^X7FV6G{owbhR3i1)W0K4xKDm%G!6i;BK;H-Z$oAPePbJTa=I8ux z-}eOo;-bGK;EW1be`QnC%IM1kO z?~jJhd)7bL>wMCbiqHs(^;XKo7ar$L>7-y8V(}dVi^!s4LX{|cV2-csU??dE%=}f~ zP4c_wBBXO_RZ<8Rr{aql!TU|Q#tx4AN5#J}vGg#=LTzhSO;NwyW)p|7?vvxxl)&;t z*Wu`7>1#T}rFWMQ?~g=^FPkC(<*S zsS-)!=nacfXp)Q(@q9jn(IS6O$*CAhGO?juTBs^P) zax>@5EG!GREHh|_wr1DjJ(8{MlM#qyF&f&570%bJKSVa_J;^1FKDH3*0< zKot+CAF3xg-?onXStBoMB9tzho=hwAxKW$xHX z&PkoZB$5z2XCkPUCeiO6?T+*e8x`=`@ut&N(fO6n?=({~qYnHud zbXZeg-Cxn97ySL$pB#1399Z!<57m z4*W5;=K^{Wf(ft45%iEV0qQb{tXWpiZ$sXO6pNxAKR$69&0{@!o$Hknk~05fXv{4< zck-4GZZR~yAGIgcRML5}JFRTX%9yRT{7I66ao}}9=Z$(2OkI+ExXd(V%LpWSWtt^z zP|C3BK41Ion;IjwAb2uz9 z<$0{@dtU0vd->-3%~KwvYlaU*jA`_!Gd8lOwv%q^B08flrPh{&h zD06o<92F?X`!j4jb`A{5hAyD|Iha(lh)Il*3Xf0!vRrr9kCrsP=6T-BlAI~!7>)NJ ztVBaM_Ik)hFqL3~S`tXEo?N5`Mb+0VXQ?~HvE0eDHvrBxZ8}_>I=SN|>A@kKQwUYg zgqx%{FPIWjQkQ|wSJh)Lmw?j%y)y+;WiWLGi(=DdtDA(eX$S9}OW0U(_lkt^^5cP! z-FVD+Kv84Jz(d4l&&fBvpxm@09tVt2?JKd8TeTuK{azdl<_ioClRtq_V{WBfCnj2q z!`6Eup$}E}rnHO+BqlP>BzoG&%{Viq5+SS0GZt3O6H={pGMpuGu0>xO$M-Dv%=Nh4K9jAEb&z83mpWfSXf10X^MAKv9 zhH{-341{Q0BjzhvkDJ?bMcVDBX#X|?N)ulzU{1F*;;>uNAB}@T_|;fH?0_av(Br0* z(^nD)2i+k+ujSP2?N?W9tLD$_|K_aY@{(XvrP~Nn{=**c?e}?#kAB{eg(s90TT0R_ zr}?i~bZiqt*Ey@`Tch69eCqhgb%RQ%>U~UxIO>*v^62R(M=!4N!H@#EL^aii{l2M? z{TXqu6|!R~Z?QSQxqu&csY<3}maq6mUgB^KW{6hU6zQtqO!Oe7dIIswLfFY>hqc;y zp{>9{Y~g?xzQ%-=FcAR-7e8Cm74$Qla?8JoLL?GpL&?-O>1Z<<;Swp|3L~Q{T?}zV z=@FHC+ms@nD7p;CK=a9ltJcPy0Wt?TE!cNOv_-IfiWv@mDX}OC3@N)BUbxTNe8|5z zc=yRP!dP@Cm^5a-2h}v}vk7SkdW}NwNp*5O%hRP$dveF?KyYELFG~D$hz1%$Mhy=e?iJ(paOuM47Ou+(*Nw`GAkQ_qdFCSl51W%b zoZ709<8tlB&v)C9P?Ds8Q5fQBmg9U(L-30&-$)e?{?^x4_Y*wtx3_Jwx4svM3IWv{ zxdB}>$PKaBL}26LjyNTlx`o#B)uYqRZv>qDuHyH`{cqGZ9BK-G$|lfXP&lbaz)-T& ztVyYHN4y0{t-ecH!=(u2lEQhKl=TEhSQH z?W$#!nsP^^z!9saxT6lkwneg@w&i4A&Z-Svo0*|A&0yGC;6xf<844S^{4ArSib!fb z)r*9D#C}hibCg=cn>Cr$^Zj-I^|HW)TWI=0U>;D8j3yH!JH}N6X-FDvO*@Q$CF<1I zQRt4ew3hks!`e`^k!de$+!JmmA5Ww5E2ZMDy9OvqR>*RNi0|&{_9Ox@Rx)3S6`lga z)U|swBW*f?)O8q9@U!*m)odjCyR$pIDzeQ8Su~o7z&z4Srh2axsI=b(kat%SllC;H z$eIBWrpC-1_I4td*r#5`9K%VPvaq=a7jKHX?CG48N=~5;0!pgrcbkpA|8PfJy%FyC z;bwYIDsSkEa5oeqCT3l>k0&6-y|uBZK&Uf3ob$n&{>@afis3#|2h{wU;33^QmNd$d%OrCQ0`GM23UafYCj2Zi_}l zwzzd8@GZ?a3;1~3BL|T}vpGe%LZEn0PeeUc=mFkcDfYalW4QCAm~|v*qmB= zEu)`3?ym5f(dVIu+bDVK{tMCVkU`LS;p^B|Ug6d(@L21uR(()SsE1`gbzgvYdm`%b9BpI+VRA5 z(_6dVeliHu2vhe3FjC>EaM6*vT1w>q-=Mh%lmOl=N<225)Bvw6c=feM z!Ak5fahEJOH@OunY++DfaCQ7|+qA{&N}o6FWCY6v@>7fkV;?dnsATq9{{MXLdCid0 zj+@`*p#CK$nl74*pVA}xhpVK^GW|i`A1I-DWG62jXyGx6GwSN;YhP+!&(`w$_~|o= zZJqZUTe8A*>T~{xAdn8sMD@9*Zx@$oGKU08uPGy&jZl0IxZKX0c)kFVqmlQsImH{$ zqD%iAFn(Mx;9206<0}DWD1)j>a93OKkgnWdc5}}J7+2dAYv;`mi~i!>Tie^v*zA{; z*p+@jmcW$cy)~AAbW}Ivvt)A$>oAlsTPmO7*xcC;7KHXwal=l;afRAh(9mA}4u382 z?Eh6zavtx9*?aleFN2Nn9b|U-R9}xg%d$jeurLjLa|JgTcZOMBq{@ZpFx|8PEq=>4 zh(WZ3r$uFqKFNHB9rh}TgiqVeV7Fx~Ke``cKD(v(CsgasNy&5MclO28cW(FdjL^3 ze?dU-`zGW7zSv+RHpQ^JqTv!XQ$gI`WfMBPKU)jgd-R|2QRdMoUC21j)YC9hqk*B{ zWmaF_O8g8TYsUAiI^O2L=F#9k;(-)1ZTIEd3y9HK%bp_xHmDQz2L&(PFE8-K8GVhkHZ{V z^o!EMtD?FZmor!hu~ZhLVCzy%2Iml$BIdw^7a4w*d^bi#FCGi#51b7at%PL6a#<~v z#bI6s#&WK7{;PEYd_`RWG!2GL_#?D$+PEo#E^oo;Di)=%0D^#++^b&oqpWyNbL+Zv z@AvvR8nS~Q{KrBZa%Y2yZ%g_-(aLp$4q^McsjqA>&(KH#2goeSmhv1+z zBINSSw@e7n5J1#d{ol~&lWoL*&GFWN{wt2x8B)#Pwkr&C)J;EtV8Hvu{{~V0>%s9b zNbsEJzW3+s5FNgt$KB_PzP_XG6p~AxJ@0|W^<>G*d?<+^b#=XdqZ`tlVvn3Kc_@)( z0~XqYzsUWR-Fy;|a^~=SKaQJQG+L6a*0O9OvU|r1n$A-sqAFLP+g7am$%NgB5q|uE zkB$9N8F=L&FJoHdd7U_ne2N&1Q|%7!m_~k_gtY$J- z8hX)zRP-ke7y9-O+k9aMF3v2gsNJPbG^-@r5QpQBHj~y79xEhy@N&6T3k}(w@z>iE zEDk3RTvuxHw&k)2^M5T7%pTAGG%OJd2PjRbo^PR7ctwB0!gJ=NXk<3-?(b|nNB!0P zJ5bc1b^h!3HLqP1@f+-%#09_Q(mJR55hY}@q~cVcRA>n0`|STusykJ17fiRWm#BBF zi*~0bLVRERZ_Jl-S}Shcr517lt+ZkGkSkDlKHQBS#+g64`#;=9yM8!3`u3+iq~sV0OQF2+C(f$)=?oNyKV3+qA|3@| z+x23KwSxF{hzgd~2Pk*qdX-p*IyiO%gHX#aHe_v^(jOSUuM-dy%v7ov8OX@4od4w= zo|$SeCmk?m7Hd}}^3KoCN6g&*5_z&3dnu<~ZGdM@&n=EP1^>F@YBkbqEWpp69)Q$1 zIwi={vwZ+G+A(0PV_I`=^enQGhoyR|(_Qh!N`Ba%JjC z{4+)IQdNlqs@)sr=Jad4??OVO(g-br#J9n9GsUM@Uzg1uzTN;7NS7NxgJ}K%ZLeF? zXH5dRD@e_5CPKkNryu{b=*KHO3?I(VLGkELs&WZ&j%4`}!qBd&@{g=8qY%4pHGTdl zHkC$p3#IXK3>iSF{93;xf*_{AA>65|uZhMI>s|Usu!STnyNFEz9BL1G1C&+xHFw^5 z9})hg$POk6JI-;L<#w6ZRX_7>m(9b%n4~8Az z8?$SRI=yog-+x=FcDNfxN>%6xVXH~fH|832Te(4h57BG4FV9dDHLT9dT@@A{tq!#p zZIt#qYg(E(spsBpL>-)4$=3BvYjp%|Nd%7N zWsjckX~AzPM+pJIGeN10s|c`YjCoW@M*;h-Pd{h5*_V&MKE0{*zO+*Oi@n`^`1Fjo zmDc|aLi-jwR4>GlNW|aPd_G?x;|I@RU_(gVNYkA-Y*bSfc3lCHi|A?iJZFj}v+9xm z8S2yj=2JiYA6cFJ_mPb(uSaKM&)l%*Zt>vHgye(>NLZcnYJ~Es+=ZLCBV*ijF;Dow|IRj6vDXAFI?e2O2Bp2bx3o_a-YG=iT$cj5axc-5Qyr);`Spx9 zJB=#NO3mPd025bsRi}2Ez(`rbK?>U=rp9~?mvYLJLR@Gb+ zlkRSm`Csz+r4dK^?DYtTbODV>NIbIrxVd`<=4Kh!vyw4-**|TPpe0`BWy!py`j0#S z^?zvaWqD4+t`3cvT%#X%@Q;L$+Q2u^7VPE#K_tiJfnlwwb}_ZodA_{igkE$k6StaMgWVRA9b~ z!BLYKcT?XPLtATfTqopQ+L#z$;~2Z}{==9xZX7Vc5XTQEPYy^Ud0M;^F(8|A%@e5o zN$!iQ<*=K%ZpYR4iVBlUbfF~82*tBI1a9@HU_H-7mUf_5+HMkB$FR?a^ZX2;`nWrt zTHDEh`l-3l>x9bdH0|y}c*ydz2$dcsOh`j<2`5LLx=>h3ZEDqbX4)Y5cneTB?uIlBuSxx_4X{74ikp=t*g>C2V^x#BfYyRuoME5rju5f@M^5iO;K6kF{HfoKX~VcB^1TNU zaQlZyB#R(yYmag)00OEm2Mr79tAXgWlW2PAC!(rrF-E zcZIJIvNUe8w5_Z&8TBM{nih=Hk}&k@wT=CiJ=|G;5j{@+Wk;vlO(6zYeM1p5zo|`a z@RQ2q$hN4RrCL~sA+~Slrq2tMpP854BeMnJjaYF85LOg9utxMc#aAtr{^P&#j%p;YC@xmC zlePgF#UY2+qQW;XpZLmVVVB0u9o-TrsxTq0Ea;|)Z&ZF%`2lpU@t&WPyKe8+@Or?W ztZ!OmYzT(E$(M3&FmPXg`-xIG-eM!u0Od0^|FZBvdULr+br?L*%0<2k{l#Mpo=low z{_^Tq0hAD0E5rEOEwJLVVqM)-$IdFkW>YI-c+EUGnIo#V#cOQ6-t(=pxa;M5Twp1U zS!zX?gEONBJ%=iD)w&MZSf@}>{Z!1}Gp`WKUfnG?r-KymPdZ>VUhV@5b?B{%F9CX?_SRm@qHur4GD_32Lkf~%(Mu43rh3t~8}a-E7|76Hr% zF?8qmox!L}I#Vf){H(o_*R9k^nq=bUv?sN!Ioevmev*P>9d>}sBRxQ2T16S4Qz6Y= zo-ec7$4m+)V5)UmI@z>aP4Ff`0E>)Kl|W5?8@w~f29Qhsta35)gRQbBe;DqLho^o!+z1!)k*7lZMk{>=`f z`IR{wmLW9-m?wj;FkP{v{WC)-eFjN)1lW-TNW);u>GlYKQxj^HgI3i7ytbaFP-`G1 zytd;3PSi<0@yJa6MZm$I{VLDRZ)hYU>sXqr zc@9xOBTxC#*9+uTJHuxr0G_TTa?n&$DG}EYYlqPaagEj}dt+tvq^W|QmR1JV1>O!{ zNy;xg@|(iCz4dL9cf>k-4~YP++q$n|F3lZu`X}H?c@pr&4d!>(`L(AA3CT|Dd!q(s zBgV;l1He>Wk1(yiWg%|u;%)H$uM6LGM%H zSp-0@Jy+}Ll}2}bE1T}?Brva@W`{&^xDCsg7zJlpG+73^g~FP=Kk3H9%zN*<=}VJi zO>3Ayi}5X*(tTXwb*R#PsmM4X-d~0BVW^=pPG5cs)~QU9SiBH z?&MwTlTUlCN(Z*P9l3;DDhB#wo6*qHru2LkmleOZ92w>6s5$wPtqh!a=yUPo?P%MW z3$ytm^awD5cF3b(1Ygz)?ZV_MA*av@4Av2ULjN&mU~N(&hn+AGKD98qg_o5)e8mt}UO z0)<-HXGjZ|ON*Ia;UYO~S%g!GxLG2M%XkaawerzV~eYeBw1sxRjlCp3psi4xlQ0M=bC%Gu!NFQ7PG?#IzzK@AI`GFMdsqi|--#->Y zS8_J^;Ha3W&W*6V$#_uehN(WE>Xum%%|Xod%9thp;)iU?P=>LntYe#k$2iu$yrr&{ z&ytXG6U8_<^X~L|(SHThW3>i4li9xA#{<`2{sP}ySGqjok#KF=F<8>4n)%XvW?F~8 zN+7bSkiJrVq_n`WC!@HnpMYnPR~&k}?(jHE^f+Sop3Ix&VqiS(q=xqR4T?WW6J6B? z&B{A)Q~v4g{%cc@uiRpLqf&E|*VI-;)U8oyj#J>^b=mMjb0v#OsC%-3k1r;tH)lXI zk=n0YXFyB3rgVm-cQ_UkdSvJFL0#}hNrxG3ZE>zq**>%OAr~>bru(UaKaE-A5wiBr z&d#>)ek1GI@H?{ut}BVO4hc0~eYf4qXPeFC@>@fu^}iA#q!DM# zT$Cd^12y9LDUSr&yh9BM1T7_uD41Ld(iuj)k)Vkt*+&Fvvorbfx!y8Xt##+YSnBtq zc&=pqcN?!DQ_k0tF6JC>6%E+-YClO!h3%@JKx zhtkt*o<_eFsv9#eb-DcH^G`^RghxKsM4N}rm)SzfViys&7*+XqzmIjF>8N14*@ho< zOr%SBjeNVjuRNJ}t^~1v`Xa!f+$c(x;Lv`CITA1gb7$7SpL_Nc?E!kMb03Ds7kXM$ zD?V6gx3{my)nMe^KFgjBd0#?5B3y`m5h{^F36Z8JZQ6YVC9ixVcI!m?Qi%X3-?n z#K0|Hmod7?Bdu!dMr$r+pPH~OsmmAmXnd|p?NMmi5xMM1__@MhS@MA*;8T652GTs! zp0}lp#v@j@6J>OZut%99cbH1&m*4UuU}D;zlCo%7V$o1BGg04ht5#i&y{5F_DJO8m zk27irdEd6sGfxLx6eQ&gSj3ZY(^I2H#{bd{GToJHSS#@fF&3okO0Dr1?RIieIpjUy zAE+3*awNiHIoqbmJs45+IS(;Z9X6V!H2Mvi8QSv{8p)@H9eG~mIhige6;cbkA6vLe z^dya_DCp$Qd8PkG7;OYf*|d{ECxG)(dhIi{Nzgqi`P4{;Kj(L7E}=5>bY9m{ni}h= zYhexu1v?KqW22`aBKB@!e2uJ97-bV=ouDb647G|h;gJx@S;BeKckEj1ER4XZv2(AL z47cc~-1bp8z}Ov*0PDz$P3f1%ifVPQ-j1@Y;9sZ)(?ZzfS7|ha~B z1<22{>b~t>GIdTV1sDEM9Rc}mh}tTavo&*%%{GX0@xZ`yq`6-6Cylsr z7hIh(N35u3%BoC2QH24#)?Z!(8T|yUszx=DC zMu)E{mAz3f`@J@da}_B(6=Rwv(gCg}jkthC1tQHohFZ!Vezw)9M%$9u3dji(Hi#Gb8Xv0mlRCTOztExf5=BqqFPp3 z^lSTL6^BRHPn}TJi#1}yv|B6K4snm#pAIUd&&sF#OI7-gnPZxa+PsX~9s3Ejx`^fb ze#P{zPqJ(`*jh00qqgRm>u_F%jBv6OY-}MWmgOybf2K#2Z5a5QQ8J%;D2a@kGgDHZ zlV6PMl=QqH;!~DU}4i@h1!pz5WW9>K(W=$g`51SJ^cBfLU+Cw4)#=%O$=^G>3Uzs@@ zp1F!||Gnoe4YA>o(QHHhIqHZO0|_s^{}^5sDIUZc6mbh0kKTh?ubL^0_CBhbVFVLm z->OXXrdzaJbIa*9t`L(`K6Nupn0)yDHdN+i0~*oam*4qDOW!#TPo=75^-#eULNMxY zIS9-1U$g*lC!AjGj4Vj4O{9(x7py0NaHt^Y3>eENym0(@SD&(#7V8?VIG^#RAzVCE{~p<}glArqKD@=rwl)R{97T1UZ-VX~5|)CLnXAfmF}xO26^+S66) zW#DFKBBQ~@WZv!ek<&#llOqU6c|{Z8wfjl80FVLdKFYJ?!2F6Kbf6$cA%r#m!uWY+ zo4!Y$CpYVM02(O?`KbgL`eka4Fg8TfR!{Sn{!;a?5Md%7f6>!9ZnzJXE3yj_dXrfy_vGnDI3>9U;4 z_*WB!V7}E0oy(vwdlHAQX&qDm z-)YXGf{o1q;$Aa&R+ih>IX)IvOQB(R;S~`@#*s>(QcXZ~YIa)tY@!O8Gd;-f5T5hR z?ZwM>%qgx+9G7aJSo$9OK{89M2o;J z%BmyVZ0?!0MI3J8P=SxPHP3_1vpBm1f>9!R=Pi6uK9Ho{JKNjwvkGr963KcZS-?ZW zDM|b)2T1f~Ta;V$sT61%cSJosjB>}{RjkVla2Zdvcy3YZTfNs8nsCL+&hZyes1aw(lxBxG;yp|5vX+}OnAX6mj#xJa@je^S(xdPtm4kWek(AAZ*6Y++EKRb69 z$0b=DvsF_jy`b9=We#6fdh1%&Z@GL*ninGsZyZ^jC^DuX)w#FE$9YHK8nHhO4aPqA zS#~ZEajWO)wkE4(!)u`NXSy_o@K*ngv}^CvVvUhaKuJpEjNB@_bIzfXV7w-gu&>_z zbdz3}OmmiA56Ri8Zian!8e4REpE{B!`nQc@yW6kezw;`*Yc#Z3@~<<2<{%T(%wp~m z)`Q3fb}u|WpS|5-&}#|xW{)Efe9g#uB+vswC*&vVdTa+RCCNvSnQh4G-%&omy$wwJ zF$F*FMg&iDDe$wX^8H-l<}&J|Q+Qr0Jt9K|$DOTNX4VyDthZ~DS?XI-I_JS@00j8a zhU0h|i~abrg{#mJs)%K31Gv(`_!FE-@WVV3qIyR9-I|yrJalmkQ=W=91@)?Au(x;z zg!GosvOZf|LHqdc*U|g_g#9w^;p~T;l(PvR#4e?{->v&ln2o| zW#~KZW+nriq8C*rdE2Gx?m(oevX6r)T?JfAc=-pA(#xLyBqB%3>K7*&%dPKE5FIA{ z-hUDZ*GkG%1BpTk=MXb3J`yfhGU8V;@kgZ5cNcI%=pv_lt@y6_)R$tP+4|$@pQp0U zgMFme&_j>we08&2`aH38s5{j2*WGV^-a^g9;x+^FwZ-VUPUZ0xMD)i$ z9h=;1zxaT}LBACgV`*O&;Ik81qT(C&5ks|RK^@dL`78Qy;N(M5oaxQv*Mp9Z%_OVL z)@rc5&$`*10^=xx)Xnsm7Sm$8%=~L*@wQcs|TcLHuccIW(pJ@z<#d z`dG%vC`ATEcCvT)TBTVg8tV8eCd3AwW`QMO+wff%*167h)DP1FO^j*9!LZ+MDcP$!;>ff@@mA!e)wrZuDB%(kcH0Y0s@uzaR*gx-RP2^@2g2pP zyN%~XAuh@0eIK*&RdNJO@0l`}a?tIdV`RzHnEs$1hcxe5$v<)SHYOn^nh*)g{$$m z0Nz$){C>rz1mlv(Gx06LLCZB026Kw?{n1?F*qOgKf95|E6(i}@sh&_0xuYU3BeeE?+?LEI|E4lyIbpcq z@z!*`*@CCvZ>A@w1KwPp1AEVtj(kE5Kt9SCiCdALFIE{k_NhhF#c;nT^=bER8deJ7 zn6wS%hNAHaTl`udN#TM~rjHeAoa)Q^!z?snR-hkUT^8DBvin!QV8SB`hvDVs4aF@s za(Oh~T4_hxjk(t;CT&SAbgT=*O)J8`r>V+y&OW+2Bf1ExWUuvW{SLMA|C(WLRQpP#nKKSuRpU?-QRoo~Ea{3uKKpg)mI| zaX*|;W}t{f@c~M5Yn2h0F=>#B-`9QE_~i%lpV+i~&cjbvD9gje!P!oc`Zy9FFW&o; z1U27G8S)z34rqgHl=N$Ao+iLf^u1+EhK9#XrypxZWo%VGkp*f2(E5 zIH4DIou?Sk4hWD)XfrjeRe0mi{k~o)lQp>yWmJGjjrI_5h7pLyJvSETKyxqTqeiJS zp?@gnr(b3UhlbDkED5`YZtv$>laxF@>C-kPSLn@s11&CI%!|(VT_VN1c*)w7AgYAj zIVHg1J#fhCvCi*ALgaPXQxv=?iEU_b%upP!nDv{}omBLRmtOB37aT(})G(@TpPL;( zi>9Vda$z&Cxc=-bG<_57nBQ$7jRDONvc<~Orkj=fH!RjtPA#vXscyTLW3 z^kFbbA3@)DJ5nR?dFQ}90&3x=4Wc=s5aQ4IIa0G7aeJ*$mBwwjlY=K9IqOsWU$6Vw zy7)}S1UY>;wMur`^c7txlXa$V1(eMUosqPpY9*)7mP0(m67BiePhVRn!TmV}G$aZI#2J*h_+t=q1?m zGJD2onYf7Fx=mk6n9ZS&<1z39Qw%s)1y# zR>{MYw(|is9H;_I@y=H2`Do)_XsmA2ec*9K&<^jx$V14*WkeX_7QLQpwdlxX_@tKq zXW^1VY!#ua{sAraabyBl)%m>ey1RXj}=$UB4VY+(Xk{_w04WAyoLEPsIMp2A75B^ zhw|U5NjZxmeD^3h)+2%mxnp`b-n{Y(A-)>;;fdIp6@Pk+rxfcQ1sP0li;d#=lrRMV zk*QAx49v(H&q^2URV`9_e2vbXy$_hGWTsHDN(P;YezfG+Ha-d*#A`|$+BC=6$ znSD5>oL{cP)d^6!n|1Iah^-EtLTPXS*1e+aaDO|+MJD@lV;Ce1~JOLyK+JpcnW|oe1d>Cw_`vB!Dg>qd3@Sr5$S`Kx<6W_bi z+ibVAYj9sHhOgLcRfCCB`mm1eR~=UPGy;6dn?!#<3U^T#unH#E>pc@}R(x2eQEpB} zObJ95jVKwDfK_^~)(`*D{zYRYo#3HD>!+7nPyd$!f2uhsLS4|0NC!bj5u?L%z?5^} z$IzUaU~KU~OJ#n?omex{;2(ZkqQjs1(N|50_rIJ#^mgD@<8j`OBmt@HNOVg}HF}f4 z&ifW6g>gn@R*iE~TKAGrHhx+8ACzdU_*l^EjYaJ@p}Le@zb&~ySpD`4`oXj>-G!Sm z!whOPOjFEy_HinDrf}TEi&i&Od#%=7?xIwEKU!O9h%*CYYY$deK3QMp(EExYALjW& z%d#{sh7Q-aR$)CwByMHu0?Z#(=bdXWVR^RvVtQj@r3PluMM%@`Zem1WFd>Z$)(W|? zo=8iha2|&9I%X-V7V9nFzU`{Pw!Zl(IsJJM+rkR?>7kQ~7t7FD=uk}`ryqT5E)FM= z;II%rtNnh+IH}!zt%+2*=BFfA7UxMYVs>A9Hkwi;gF3x={ZjR)-nyq+^E2eoqAGD) z24|s6lo|KW_N2hXVLv}TH$I=reAv-=rq`9KFS9*GZ?GIGCear@luE#L=I0hs?DiqXki}Z z?ao~}ts~xc9y&|a0~`ULFy*wyKL-Zh{FDhDMuA3{+;8{&JvM7UcZ%!@5OA*(!N8Mu z9c`@3=~?x=P0`LId;d!d`4Hc6BISl>!d~CWIz8{!_$w+HsiVJFe4$iE-_EDbyQ_2Q*XNwQWlM@+4=Td@FJ6WZ^QrjW%cXxQ#(8E z+t5MJjNf+K0kxB3LweD@B1)TF|0gmj8~PQD?C+3c*!uAQ_UI_9vTRgf#w?H3tln2r}f(;m7wj@ z5$^qNvzOhkd+c(~yY)pWMG2?km@Y%S57z98i=-YkHp6*7Px6yCelw>V4YERl7L4Dw z1BYG-ck_aVMqnMn@<%yZlua3*w?1Uv2Y4~{I|!YL0sWN-CH5BfodBIDW^DA+aNbq_$oJS3(aYCxC+8t9DbBf7VmptX(uWi* zVkeKjqcD8tll&ri{nFMX8&@a7?V)iLU@E zh_KvBCpIoPUCC08OK67MW-&asWIGVS?~X4mIClF3k^Q_QdDX*9UcBH4zBjil3?kY#)M<7~Wz`O|#fG4ip>wDHbQ zk=Kca$$2b$3@In00jpbC(HB#2Pryx&8%f*=+)Z{Wxr1Wc7*P(?YZmXfWY;ws?0juG zy0CXdIvc;Xb7G?LqHtwr%hE*ee zy0G&wy~ypNnQ(Q?_aCwI%=O_cEq6Y;{3Iw)NHO=fP9Q2mQ?WwT!t^l1WjWwp4`t>f;G3f6uyg4A1UIoeij6l!|xs0+kCk-<^_UV-qS?Ta+7))v5}wV zACA5aJOh6KcVLlX>07=FiUKaZ17B}S627^0c(xbWD0OR=q#S7<;)ZMis?a#)xMiM7 z*YzBlIbJ{b47JS{yiXu6^IZ0bdJUWCnOFR4PixR-!0xpD>CN@NrTs~v9rFLf+*?Pr z`F-oYMT(Z<(BiJ86n8C7aCa*boZ^}Sp|}=z3Ium)p->!JoZxQ7-90(!{_TD4caJ;H zJ^P+>#<=(2Mc$Q}wL;!^&G|f^2@AcENS@iYyMW14r&rNje`&66&E;tWkJ~IeRaw>Ye5OG+{nyq88|U46sOH zZLFxA0n^7n7192A|C|R6QpL3yvD1N>VTbbEIQ2c{=CdPV4ca&gF-sc^&d2@LOg%II z_l6>e@mops_iGYlzfuhCJu4`hU=ax9>Vwq*^@B=kd>9E1tDyvM97bnt&~bq1rCS8_ z&aRDClD7BbPh*2#0kHnzn{{{$st&4dV}7N!&8V~z4oMttLD?RwtmJL2?@haR)(z1l z@uDNelD=ecY!G$Qtf-rYxA?v5MV1-786h(=n|gAe8oW>i=kda3BJ$=qBp%1#-$w{C zF?YWo3BS+(QE6>mQfy)CtH(nSrhof*emx-Vspg^y=^*x-ggs`J`itOMpiu+@y zBMLnHY?cg-pKb2WPSJ{q5u`065q;Idt7dEs;4sf`uACqr)bbg$(;<_Edj&0)K)#1>J8_3#{Hm746_qhli9^`noQx-{a-060~5 zQQ~lg55Lb=noTwkWF&hS=Xi5>{~oBRJ*yqILVWOor(OG zABQ+W)48?Yaov?V#|xbgf_ic>&&I3K$;Jj+Kbl+v*K`B99b2S0n*yW9f6v8Bk%p*! zGQ9d-i}NHxP2e3X&mmWA$!Ikmwnmu$_mwE{99(Z2_=K^g_h%c7#m>*wvtC>OYc7oWqI30(lj{(3{j?H#QDAKU)tNDFHqsp5<*@a3Gk=diRaYB3QeC$ zxz{wF%iu{$niQS=sgv`Rl~ulFIusWh?5gZf0$XC*2ufS%{r)afEB%A?l+J|ENL-sN zkhce-F=b}vfk2?KHt@9mB!sP}fUh^tec40+QTsI&UT zi+JGe+w0gE3CNaS_tCVr#W3`9JUV^+IA(y0-z(FJ3Q;q_d5SI}xrNps4H+D)Ze^(?5d+!XH-CV)t+}ZHw`nw=6x|>l~V5 zv6>CWT0jmgQHDg6e{epuhnI787QmxuV|eR|`bxDcKfGwg3qYPKSNrVr0xsZUwZ%-V z#t^$#(0)ER)~nle=tIV1nUZfxDX+^$^h>zzu(YO7+IzWy`ri_x9gEvA_Y+GM&vUxT z%T-1dlw9@v#~Z$4_)l=HzH$ywr5i3OKUd^`qID>z!t9bd;~w2u*8AA2ioZiesLr5` zFOIpW$Q#zCJ@4aI&p_`LpjCg+!%l`n9WsvubdRIZWua4vrsXoBbIgM^WP~NS#+eZ5Q0gqIR-{8)&EV+yB7rEPy`a4NX+&yBiuuiUmdgT>7+H;krciVGsk_pU-A3p8 zHSb||JjtLlPB`=tpsIt&u6z*2xj@1yu}HOI&yu1yNT-eTaXR8G|c&ib?)CkRF+OM-E_2kvM)#D?0s{ zua;`GMURe@vI$WkJZDfi*8%gV#wJsT4;hU(X8oph-S;I#E}0+R_i=l-xj^%Wb~sFK zI&8|9V3(m27=XVKgZnIckv%x`45YEpKSXeUW>+(!i1C}a&T2y8Yew$}#^&C^U%J2_ zsLZTjd!OiK{!C3Cku~G1F=>RlYobAYKqb#-`@O?JwL4#G5ffL;Gm8LCtoV$Hced=Y z8oZAIg60Q^yv>O~K^@G*cWN#<@?C#>dVpjt`S})-Hx?kfRHT!jFVk z_RdL>u8$}lwC;c(=FFc_i5XT4#2KpHB~EKOFp6t!XoHA6R)Qt~=X=VP|?|gzSe}wm= zSy&;;h&C60NZdCh6(lRdwD2e^6c+RxzeWA}eL}AIa_uG)Q|>anv(Wp(eJn`IbkodH zSFz{nfD};^O%V%8DKz!E`d~pENQK6qdS3wpmQ4(Gaf8y zrS+?I2Cz){@^|~sA*-tGFfQA}w=6B?t^!WMaRIIZ>j#$AX_$~0!ay1>)z|LseA~nP zT0W!zuHUzFqj}FRx0^Tzm`AC_mmJ}45miYt$g3A3jyGd>Wbh*m$& zOII*asGggeD?!i0>dDc{)(_<^>Wy@6`>m9kvVho^*rZ!y<0SD5rODVIimJ#yw9!P- zk9^>eNh#~hcPi9;n~;d+rrM4eJR&M_)G-W}T9hj`rlH5#$o7*Wl3!p|oiA@h4sDKA zYLS#9>lL~RVTo(h%C6S|K1XvRPx%-e!yDng|6GFtSR!a$0mXW;z|XdY{2GY2Gll(C z5UT1ns9Q|@s?kY%@Hsb>X0(h{#;qu4Be_b6{hi(7zr`e#t;HF!p&-)7YLudDKHjXs zO8QG7RItPpudfJouiyQ(#SXnLOOgp4)y;s~FS)Z<$}Fw1EUMboRhbS{-PjE28(eK& zjYZ^{nDf6?>=xV$A(9ikw58llWOZD12R|6PE<#dIMOiKOVuGlZUdho|4N}B!S$%vd zRP`zzBfodSxZOUs54rCPB{LOj96Q!)57VJK0ujQlyBJh6%TiPA9~j>-%s2V9j$NS( z(!B5V30MtRTIxNQ&T2)<@eZzzz7dVA9eq=g?0HLwvw^7cFl18+25G5{;;v^ z19;&*`i(%1U5>xBXO&Thsq`Mt$fTOMQ(JCo^NXWA>=Qiz-bx3k!(?D2t3@vBisZXZ z*Ci(UwsbZ{Q4ya>nNDG6RGnYlQ{Jh zj)QO6@0QPnO~}?aR#VpcL6?}$kpg5(ZSHgr)l}FWX6pnMXgf1)@Q=RomZT9eMWsV# zFY&*84k3#hb*_X9(m_G-7abX}i8a{BD$MBu1W$uQMQpZo?rSG8lyL;M(SrVf0NW2|{hAFSE^_@1&;v7hi-xivj$O#NA+*L`J! zDtB(J8MH4s;4^YW<8dvD$ZwzSAVpHG^Ve83P}MxonSWj|L+NGC{90{}bI(#q{5_J) z!d}Cu@INnT?Rj~~u!;G=Xae|c%koJxG;DN*zFHRC}q zDLglXsdsM}8UA>>5-@XF2{dx(au}rM^vgCRvAg$Z;mt4`AHo?KqCck@=s!c6*R4Mm zSlRD2ZUoAUO}I*){WkEHq?HtDE}dhdO89nnd=n9UUwx<+pDrn4R!1x__xi$7prWC3vVd|9G5y!Hnmfx(dW+bK{e>=x|TGQ@?2NeEr zqFli)<(kp9WYC}T>g)C)y*Oa+)@Y%*^~;om+DFvFxi$V851)-XHvDQLy0Q%kWKvJv zAqP-Z+fJU(W90Ua)d%N`9EpcG-h~=OJK4Ljt;P$Zd3h?$Qb;I?;ySC)K3;=I9_n}~ z`nB>!ORevAne89IMUhbV0X%WgVsaP<6JZA^)bPA`fvo zd!9j3q=T*jDTvtCK4jnx9CrKoR{E;h14geLN=eT?!?8759@M_1yzrGqv`}#oJNKfF zhG&%B$*_fOG5s;-fwO&1YH9q|VR|HkTm){6BdIeG3*x;2-FSm$A7?urYDP%6QsOCV z9F)s;DIBGOqmsM1vcAMHAEtS5G3FIKqobS@u>0rs`lVfuY5$C6cLX2--tpO>+A7RL zJ8^RSi7JYaD~!pNv9D57GFzhVobFx1e+e?lT zhv|TvK77ad%UOMZk3)ruKP-EIadPV3UR3aH7+Tu* zwCy5#5q&};zN_f=t#fO3$B~b`$|Ymj%@N3R(CV4wYt1lz?g8o?38yQ5O7eQV!r6Y? z-c-wz;n(>q1wq|prjDxpRJJk;#E3?*kD&u1D(rRSthR*Ojk<>Ki>9 zPGukMbQaN!D-qB0MhbZ%T%AlM(Sy1)22q^c8;mRxPA$&fhd*zc+~_C!$+zAhdKhP9 zCzG60VOMu3amu;F%nkJ?k4fF8#*=adN7h8$r9z7OG8>EEsVTln4exLya}%ZIXW}ox z(9a^Sq(Z{3akKQGW1xRynd+*l^#q8|ld6^JYzD$7nbh+LMs=H$oQ|xgTg)e0&#BV3 zBX(#wJwsN$WVLjkr&2XXlsO-AVp^&u_-{DHtw6CW-u~H&?=6ensSq zM9-1UjN}>Cm=67*bjxf^`na>y-Szy41wwdgxhWUMNU(a+B7dfVIrG!91w8jeBD@NA5<#;etHNuZsT|sQ?zMSbf!*t!)k?M7Y0vt3TxT?JM;dnXsvPQUH5L30h z>A6Z+TjYhj^bS7PW!^1N@suALHSju{{vwf)DW*Cxhj-L9>(Z@3@#bqRZpMP^lK?9j zDzy<K=Gu@GM)Fy9fXEgss_cJ7-@sqww^6|Z=R9Jase)CxM|m`ulS zu@P;l1bnA_oot@hc7*Z2o^Soj3U!v$9(W>=8Y&}cT_*1+eRDWpsN;BTcOUpI)nJL^ zN3WFuN+jV+r1g_o?Z@WdRU?1?@C%*UE&Bj93??aUiNSNS_1M`ZTU;EsBG)0n1oO~H z-Bh1E|0(gnI=p8G)0-Gq36L9v?#=?U_03b{MLz-8EVZPaw81<&`7a)V%F$nY`;8&6 zJaKo;g|P-3@lUC#W$NiccIW{t5tVp#itb`a$vin7T1><@taQ(+xKjeP$xfaga0g#(27>A$ zQe9QX#BPi)4tZp#6WqVFopMc@PnUsU6Y;$jJpI_&Ir|(pX$eAkNSvpY*Lhuct4B{+ zp?a+_8FF(sq+y9yq;r;5R?1VzfcF7R7S$$d(x9pi@4%n%=0Teb+*U=|nRMn7{%>We zv1p_Y!z3pz?4ubkV#;*JrCyJoe^F4vK01Eu*D!LLrrlQOpHI|}B7ydZNAB4{U^ zE}}H9ne}3RG6oLO9G%Z<=K1WJiE=#@@2h&fWDrk2U#M&8F(|OYn9tPt z!s2&0sX8%|>iQqsKiYTu2gX8R1qLimEL~HWyC4lRZOBN*Hgix>Sce9DuCpGCxPpD% z={Qb}bmTY2qOQ@3#t~isrBqrPKU$*CvAeOLMIA)A`@na4Ap27(D)q1J^HSb0pT-L- zm8&+!;Q0$+OxE~wW9-zyP+Mip_~?YOY(wkU?*><@-}c8m%L`W9@;n!Smmaedp97+0i!LI{{eWCxa%bxsWyp!E#Znr7l$aD6F`61z&bMz3uH601_^F-o`fe0Z)6Zf#HhdK__6>CnFAfhVZS zgxQ_Ec*%unDXL_cpmyF}=EwTo!8Zt3aRU!kF|#vKlWX3^#kXla;ZG#T?#H0+w)3k> z9&#o`O%_#EZOTVCoQj?l(p$2*^4AeO$jBJr#`Dp z92g%@Ub1&fs4AE6=9o=iS2r>TklJ9l6Pa|@bcAd~+v;H&a>DxhlaEJp;(u*|Dyk>D zY&xomsYwG~n5SWbc2~2(+CXiyLf1x@r=ZU}E>8AoS*Qg^&U@7IZLu-HK#$swB+ZMc z2Lk{UcO2C5t$Jz`h))r_C)`}QRgwokz0G_(Sn*c?Hp+H1VSbq#c9 z>xKT7us|CK8u)D1zW;JAV7WW0_3z@tXdYLK7!~J@-%aad?3CQUv!5$965(tYS1B7W zZhnjyKlcLfaLcaD{IQvYq!O{UY6L4#uI7nljib{_e^jfq}z>P}_aZ7yPL zPnVLt&3^Gqxkin!vFG;Sj|AP`De}Aogm(N zsk_^L$VQH7Gwa3!gX9Y5$rH}a3Uh&53Pp+TV&<})&RrFN(9|BO9;KiaPk3SeqaST5f>l+T=I_CTQ{! z++W$e{8?;xROInYTOeC$JR5%@n$Z^bxA8_PH~=-Mn%$^6327iLBpJ6C=X$lwX}-1M zh3(qtQQmY7#>Wm#X{H9u>n~`@r*;9qXk$J;%_?00vH5-_BKiS4UL&CkWz?Au5~zlN zg{;~L->1)qt1Ud5zV&XDV$7!&JjFIYb!!rmd>j3~&6f-HU3&^SkerHxfBTm^ zk$_eIKE}tvbmJ-6q8-z|Yq_xHxV;zh9ke2~7gV{(6ZY&rBpvx;+MENRZMc6Kr~Jk@ zvOgX;sFFp+yTha_*1Z=_dhxNn&Fws+B8}rr$t^)RP;SUFcSbWQ6CyVho|;mx)m_&* z7DVn3f}Ay; zWq?&}2=vWq4;u_r?0@nWV)H`W295GrpPpYVxy8TsJ5;eM7dLssxVg$yT&XfSnv$AN zo!bG2jjc)~KWZQ!sQzG806Up_zzwHVdEvmSpmL?$@LT)R|Ho>>Z6?BJnc@wf*pA?> zz$jh9jlK*Clu;FpKU|sz47x=DZB6IEh25skVaT0hSqBRY*%CfTR`C7c>#cXic1S07 zieopIi%xM`Kep!F0dHog15#O$ALYoKsNy{^(cajy-r&1q2zdeO42jKi*PiAYz8Y9Z zsyrR+w!Qrw>$2ad#btHa`L$1NmtGI+UM=gI-DY?kW(F)oXCQF2Z%UYqY~`~cX8^*ng{z|Sw0jT~HAE?BoZ5Z0R}PkpjUUb?C+?qRIt z);Ee37iYUP7mX`v!pr0ZmxlS73u|`YwZ>)Te;y0D7Tc3+A&@BrD(e47ktrdAZpE|6 z(^F{QD*kM|6+X|Mc`%lhR2QoL*ZX^=7%$1nuT1*oRbXJS4WyXRGa56g{CV-+h=N`qGQ(0ReiOPeQ1=i$R~QEerJpR*E(>wk;s2(x?Fgonaw*LLB)rXZyz#Dcjvwg-l4#Z1Sun6h3pduhaHequ?I(S!+Sb zw})pdUQ($|TXY-uw|juDArnPa1gueER2?I?Z8$PI>gI`CNTr27!ck*Ov`JeFrd;GE zeeprMs?m^JJ!J_3EBY<1&ZG~sM%C8D#OL8jBT^b9B}z|fAmK0Rb&?&zjuB&uMt;XP z)L7}hlD5Mesqu;!CQ@SPpiU)rl+p0QIR@p{>3f=KD7QQ!Fkui2l2B30K}Q%%!ah? zoUTji4Cs#tbTLrG#&S76yNJ-Bi8B=!p# zFrifk;dEaDrm{#^>{S~E?J%u{WYmj>sH;KG7CQ7YAZEW~Rny#h#l1m32FAtoEHS2O zx&+>Jw1es*qCB8*z)jA`6zNxXL}>9@r(h9;Z(0?$WLv(lk4&-I-!{|d-5s;cSyK2w zlo<(p@I06u%$6}dClEGJ@~%SF=;p0Tod1=yMI~ezi8?O}wt@5dAFvx1*$siK zKEX##f#@rs>?BOTB7*I4s<256WJ2Yy1TR(_(+S4Y>8uASMW#0g;`knJ@CB|uJ^vGa z+%}j4w|nVZCn9imC_g#)F&35F3{i4IPEWh)oyCtZj?=A}txRejCVfuxNho*-|F})X z1t)fG;1N&Z3(3qzwbH4iLK7&RXq&h?@6u1z{P(Fj z8m=|D<=I)Cn8U1B8hJj;HOY=3qiQJebX}cGO&tr?wl@nUA_zFU`c!?^zfivkz?~E| zbEGo{|3YtgF*b}9Hv{OahLGP{KaZ+cs4CJkrY)Cx<*5)#2W@@xmwCeyJ*DK=M{KzZ z`VQ;4jbCIeaSNBp#AeG+CN5>;AOHKe4U!i4+w};rZVC}jvSv30t?0TG=tVf&{5k%0 zq<%@|aW5|~ZPB=FR9%rL5W6s-oa zbnNCwvuDoBg};6INF>7C_1Ja_9+qy1v>D}t1bOb|xo?K6yghPz8_j3ZmM%VxyQ3t8 z%({WU{{hSd-W!5Osa7mwLnR5bQpGVlL4e5#YDI-&5ULgGytQ%$)YPUq4dBL^GVZSq zA$_<$X~4yl_&P^F)e>R<%GR35RNyFaKciM*r#`{jsd$~Aqeslv)_o za}*R=eMHv?poUZizJ{smLAAZ?icLO%K%T)Q z=dKmE8eYXIt;s}oRrLaSxF-{DW^S6j-J+Gl&8W1V+I_SU__Td zAoAD7G(o%h#?}R{5y}t-i`wyAHk?@Y$;)hJugJMKqib!Rm{LakC7C}5vb%<{dkMd3 zT%z#Wa-#C)yayOO5Os{!eo8R>4;Fy@PA^X`x4zSufAQ=)wS?=qi#&WauDn`Cl`Yh3 z*aJ0hc;jtn7d^sv@Nm7jffn#=PRS@UDaiFA)UfYBig4G|XMHu3H0bGI`&NFSj}4Tk zy-|9Fi7W3+5x?>&!_>D#MN&!7D+JmA#qZj+W&Gtnf(NUcmc2DredcEpK8>Yxf-Pis zXJmv-s&Z#5+E+Z)E2k$A>St+nx*A7$<9Pa?ml zzkPkQW|vS@NbOG+gn*;{CgnVbBJE>{a?k@kdj$1qY5oFWBqJ#?srz)-!rpSATke{v zjU9;Eu%QX-(-KJd(%yRJJO1^ne||V=@PXxDy^oO1=NVx|f-xp<411W8b+SIc_qK&J zG}BEhV&8)dCm z8p=N8b`T_Q;(y@e7E`m#%-HbxdAjn6Ir&bg6p$(V(7+48(N^>|dYP&@$!i9L{5cJ~ zL#=S46m`uP%3t+AX`5`T+A^P*b6${fy;T{RaWcxP`eMX))n0$Mrv{pNJlv6JD8+&$ zeBmUKuFXNYH^`wLwNu*JD6*~Ue-a*ECWJ~`$8k)-iI z1+^&CAd^ns02DWCd3oro%7fDGev=UT1BRcCqirOF7(C0p#W46Yp=7xj*^f7JIPCz1 zDy_L`efmRL(~L*5Q@T0JH?`qRn z;jA%_Z-vD%)zNTbu$$d`Ns}@MzQtbcCMPIX%o+%}suL1}tXc~xRwc$B+oN{y84j3q zQ)z9#ajf+|F(tGUdNGRc9x;yhgY*G;mI_<#JL51ji+seu%1p^RV<#sGWk}oUW49uX zg-4_`U%@hXhx$MtzdRN_>3CglZvJbN&1py4!Qg0DHEyP3S&XW++(mJ_BG42c{zWbkFzE7dY1?IhW^%8~@#~T~jQTUe~FP1scz3%h_re zms~0;S7Qi97z9Uqb(X?5P7xy#!$C>KM_b9VU6(^ zniwB^rou-U_{%YDu6uH)!Mb_%d7-+RA#ZR-Gyp0H;DRL%+|>hzVwt)xD4c4cj%Y(!I;*Qi;y zaGX2rP2xCbm$oq;HEPy4CsOVd*zYXNiUbg2#M@#m^YR8Xg5B})DhNS`NuGWepp)M9 z;=@nU;ZAraDc=qym4-0#mG3F2q3!%`_gh)Oj3HB}_+lvxg%qfww^h66yt(edH>PoL0FztO<#9EuCtv-dU7$;;z8 z9*M?8Hxfq^CFP8D`z%wK@Hs5N4AS}M#rli^3zz)1kOv0U1f)=!NXg%7A>T09G1e57 z@9V%r?DaZ*uVXG+WKcgv2gRU%*1Nh~lAoLIZCPNb)JZ2DC+%M4Td&(G0!c7of(b5% zN%XAUWeY1OK7WdIjZAf)u*?wng*NqEoeurG+$3Mg+{Q*NgGz}kk-9cgV-~bOb9)N> zQC2~+7JxV(52VEK&Oy~2qR3t%eg%2jK%Z}L;|ZH1ov>G_U$A+koxzqB!#=rgN2Bxkv>cs(L8`EUJEhPw#WhO{ECpmAVW4TO z|Jp8G$Y0cFjfBLvailCL`(WplA&dusjfhHlpjA+Gy?#|f{jDsAi|oEp@=@5Qw3gIhEaC57SPPO{qiwt`RalWC5eP>;J{=C=3)QylWQlt9woX=wCD`&P|?#z@veN z7#DKm<#7;9fgxG4+_nTW)cHbjuB3v%W90fv*+o&9^};e}E<}lb$U}6&$ei~ZH?_Ge zi)Dss(tx<3F>e8QmOG7^YJ34O-aDbBZzS`qi(q|%Hy)z^tFGvKF8>yX1<^XEqsVf0 zXCXG&i%8|z5-fN4Uds;hd~U(s0tIrtQ{k8h9`&_v0Q^u+ps4O>{}X<5LIWZ~N*3Xz zO6V;7M)iCQkB{Ie!1Nql>+W)6R1J9|z4@)#@hqQ~gIT1jcHc?8 z^EdJYTM_rz#PMdk7vFWhBo0mndPA0W6cV&mrHgil@rU>z+iPJw1Z2kG5$*W0!2L{m z5}&~@pC?_v@{p?no+X_goEck(sGrUHb|TH}2GGg~iNZhMfFev{@MCe%&eN*|ObtD_ zs_9h15@Q?5^4hPDp|Fv=$en@SRFkDdEK(g_NQTP>GcE-cza!rY-gLFzjFd;c?xZU{ zmi^Sf4%j$1)VMMCE$U)^gAGM;UJ)Ymnzk}hv8{x;5^bA4XY)h4wxdG94aK7F89O7U zQ*7!zVFulcc*y(Z^Ce1+DOfWw-s$)ewxfvN58^0z!hBY03QU>YA{xXBFZtL=O(RLy zUg~cv^ohtxfRz+8nPNWU0U>C*uiN&g8tLkHLS5$|P_(NEsx@?(yuyJvN_TPBk^|@p z=4^+*svD%|jz_f@2Peg^LZjyj-ZMyT7^yw>e0lQd*~1m%y5{s9nQEFFD%-wK;&l!> zc>1zL$G%9l6=&v->}TjbDd)RmfuCKZZ=+y7bLgBY#QKAsUmQ%Rtjh+bDC7NEw&%!Y z=Xfjnnm&bOjpUvxRqo+G`QxsX5DEdX-@_3OR2(v;s_^^255X=zuoq*ii$_m|HMF4g z=@WfZ_bPPb9gA5GCYP+qttT3I;|l&Lo!h{NxZe6~W3BHjLK0^Jb)IPyyfwes&5*90 zLW>=}tf5W69jle0))(CDb|wk~b1Rus&VRZ}v2h~CqkO}sS{oj|`Aa_5OPsCtiCx=K z6R6=c$o^tuU0@8bq-RMSD_*j97xHD<-`b5$;je1w1*Oo|$i?HiJxxdpsyeB!V*NW4 z^gI0D9yi+?RweAVeBl|~;oe0+cb}4Twy9gv-rNyaCG6%{uCIQ!#7*RX@-o?9S8qx1 zLf*~gbNi=y zQj&lL%LVGnr%g*5u%T`lZPhNN8^g9Aonr+FMhY zo%r|B9Mj$H`0Ypp_Y=WfvX`uDvMsIbjgIx0hU-#!Kb1oG zn|2L$=R8^lJl1!)!c6D)SJ#1|=nKCR(7~9Ul9(4u*ls^W@E-&OOfR5v_ z8-|(^Ep9twI7uHc$uFptPqW!kFWm^=J;NY%5+D?yK~JILFZQf37p1rlFZo*}+(BmZ z?stWs>3@7Hla%|a=VE}W8>T>++wracVW2Tp5#!I3H^)4Wysi~Y-R4Jw&$QI8tbd}=jDDzJq{6*8^gtk86Eww2LDJs3G{O{0$z#GlI# zHSd$%G;@y)6z@~o!cSR+3>T|$jmJn}h4|}cP&f=pxE@!W0i!^)JE`JuL{Fhf{9Y&rj;b(Xr zLs5q_W(NA=VSr-hymy0JBkfOZkI-fwE>2hI`Ts#j)spr5)IF=W=I9*Y(5`Fs_y^K9 zbS|{5+-sO4|W|V={%1vcD?h{t^;!g8kR*EV2zRn z9fjh|^;Z2t0VG}Z zZIFH6@2c1W5EpuL(OH_{2VW)+Gz8i=o=cR&y#J;t6T{(%ASjxW?y)~Uk2!9 zSoBC{lLJR?brppTwj_((+uR3D)%1}vIe~A2H?UtE%Wz%(B$jF2kF&odIOJj_KpW}Z z+`d~5Y-USbdAn z(0%um>}1sO+|NRRg+d$`;lGZ9V}WOXeFTM#fqFXs>z0E=uPCi%wyOXCdn5i&1X_Ig zYn^_iZ!dbJeru?SVE(Jk8C{i<&Cs9z4IB&zfqJ1*QOo+XzmAbusPQV^{~ON-GBau(lvW>I8rc4uQobmf_3p)UJm9hgx>wQ}_=$j2X+pX_ z6YIciY`FH2TKPUv^}uo%=q1X~)o9i->7VcqefH6nA>Mxy_d!y*`~K}D;D1KNv3y1IPr>)XK@-h?nsBcgUFe^N0MnZ1>;Ifk z*<0+_KOF_vejFJ8oY1iKK3;gX`$=Pldj*4h7e3E_fZ7AK#&GU)Zy_ybl$rU!5ya;;KBSpZh*6*X))2Fo6 z)OWPjKA)XDzUuF2C;WWlLh^hgHBzJ)wEE6Q&ZQ*|NyxU>4p36UxjVr-0RBrX6No0^ zNX=&(*`qLHOH0sXQJG(8q9-kz^tfr6`jlPq3t4{9%R3f6;=9Gnp(re00DgHC`|M#f z?pSK%mh5}sclV0yj<+9&P9L0qz2Jr`5Nh7WNcle@-1o7(U(o(* zVg6^;we=-AkO?OQ(a5K2Bm1{xmXFNae+v!x|5a!-Q6v4@Cx3tqJSI%*9vPS=ZCNVs zawJxD6<(m1+A;3ScO=T)F}DvE{+vMQmOt`re)_l7zx*G4EKe@2I~xuz+E~`SbA0pF zNPA7pOnc@ye)AfTAfL~^(E4$+T2@p4Z<#DTtJdMq#WvXEn7sV8vsd=>1w zrOdz>$C~rQ+>lZojpvzxuq#S~%@oVR2i1g|S&m`tsu}l`7q3imu&G{Gzb!TNIBg9h z_LN0vMwdL`z3=*dUY3iV+m7t*DY>6PpHHT$W|+5jLS6*0tx{WtO>}_Z96xn!7tt$z za;FDpiNg!v{J0MRxPZSCym%xs%St+PCp+=7$Y8{99|R&{IPut zq7eJ|JtN87?>HNE(t3z7`|UT@zy=;`HZuub5ZzbS#nZ=$COq~-%;_M&YtZ0vYgib7 z!wH&HezE1f2T03;u ze{IYK7sit!;dv(Qetno>(|1lx!f!thE#}XW$g920!^=H*gLpWF5*QeieuMdM`*Ht zD7D&Aei)R?QJ`ENo#u0a!-PWPYY5ovn_E6wLoz1V)JQ#0jK9CD+EN(v9p(*#`21=+ zKX6C?`83uMDCbs8e+BibuI9?_Adl0d7&J$-|BOi$9{y&K?yCGKd-Lmu-3~%3CLVSa zz8=*0|InX~x@mC#O?*6QWQD6E?IY3qJle5YJ7pq-smI5@FshUbLUC$a)x6YZ57`E3 ziR^q54%2-^CkItbaz5t8jsHg6dq*|(eT%+U5CH)J0Rd5p7<#Wl6hs69p((vcm0ks@ z0YRiAy%TEaO*$w6q)6yR=^$OYgc?GUyZL_4`JL|_@0|1Q9q*2J|IOHYt+{8`-fNc6 zTr+ZcTH>*9)aMtO6FakWy|7N)ZBv-$d8RLMskCx$ODWxww?DC=1{J zofdB*DzT{V+NCnpn`4n3&vFDaf2ukg-_=rGwfjZg@7WXmu|#Z1h=9lS?7stg$$4J+ zKL;!R|Im!?|Guzx1F>w1s^;F)B8WcGOr+-f;tY7Gb+c)#oYbIOlubXc;#-PtfwfSwm`x4ZAR0K=S$p$B(HawIVKIxxNEQ zwFnW$bjl4C4uQPU;oSLR+_(2J90}<3rrcj=qbX|KJYD1C2_%SjI6=!QzaFt_e!;4x zf}kI*T#TpuR`lSIeeqeCcQe@#e3Pp0>w}Qmcbc@Ef7D?3Tk8wRHBqZZe6xak3{z6~ zVQvPT5>hQ_6nHQuq`J(n`FQNZ0Y?g-eZElQL43V0lzb09gvPZ1o#gKEm8>S3kn8wN z>0o{u@P~bpx%>O?PI4qvFI#tWLwtY^X2+WgU(t+St9{)G#l9aRJhZ z7HvCs-r_fMv8huwnD|E%2 z&;Gt76L;6eS{6o96%)0wF=m~X*q1EcXJOt9c@Gj!Bc(%ONEo%!QR~rhH;b*5tQP*9 zU`+JainiyIEf+iyKAe&k1$w`6U3C?n9!K6MmyTMfC_XP)y)yA)E9dX=ariB^;=auJ z3&Lm*K>GdzSKA5)P^H4Me@BlF{~bO0?;3W!K2LPHt)36SwcbibS&L-X-u_#2xBYcr z`fd{j&dUmSnYfBAvh&hV@HibjND^G`T6s=O0Q>A+`8}mEP6C%6lCFG4sT3lBay%YBj(o+1y8cv- z?HX-eq|(IUU@a9j&r|ido0*(vULvX6D6spb7PJ?7Y~D(o7;%H{h@PmhFNxRbRfTTY z08}DQrpW09@D;#rghoM41C)WMLmMr0D33MPfu zC@KnCD&U4<7%Py#*%W7-2OD8REvK8y>=^Te9XdZRMop(((hoqwT-iasDIE%n*ziiz z1FgHkX-*^qHbiVgfBO4U_Q`G*cHIgdzLE5Cn4Ro-)?#Y1;4%Y^S_JbAMGY|L3B|o} zhOw*5#49gG=g?6gad6be8mF(RUw5k4ftH37yPRs&s=$HJT7U43i*fSafJ+6&S^Sf~ zx`f~-SZqBgPt8v8`&q9;k0^tl#{gH}!E}BYGb8R8CVay;w84=MDT1puky$IjG`?R(!q z)S>2FEofdt8aq8kjl#LOe_cKer{%OSg8e33KRl&1i0g%q=cv0K3r z9h$OGm|0`ds_uv(p92@pfjM4NYs9*}sK``0rN}TCpJ+L$$&wh?<5r7k3V<~1}lLTwvxE(crvj9J$36r3w z8_L^*>)GxMN$6x}5F9uF#ivCeKtqIb^xgAkANpth;5_s97p9M_!}{DoEO|M^yRVtX zd=vR@6$e;tTo&Z+Gkt_$|DgRO=+v|*(NZ8mGfs{x`>C&7f-vG^HO7Xi5AzsfV{((O z%ksSE9Xn8ySFZb^;CyW8kE^oi16p;udoo;vmLg% zk5f&ggL+u=uy*%5N3EB#m7K=igEUEd%_Fjn1O11W*cTG{emb zVWH{wOD^M%yPh;WBSe&|%qzd5=U{czR5Sr2LnS($HA2l%1-`c+p5`YD^m1B{L!2NC zrm)0olVJ1TFcFon>m&LD_YDS}gMOwtT-+F^h{V+>$m6Eyx4Dz0$FZ!6BMec=fg77vAYw!x6_>4`7`T8>~$hdU#N{dIh8XgA=8;tQi$X0!|kR(CT`qs@4I}P z_lXd9dT2Nye;Bpysi0y?6?a}}7H3bm8c#a4a=Q0L=MX-g)ewi^q2Q=*c+dWMSknnP zoUnKx?gIx)#?izp#5_g?f;?82S2)S5V%U^iHsc3Va`BUwM1PCg6T)T)?AxgIlgS5d z{)Q+DeoDK*O@%?dHrJ#vqby<4ux~;HLy5#Y7UkzR>)D@#UhQqlhr5_HCBP^Z>^ zlvVSeuCb$N6#7Js&J%VaUYNQx7T5l_;1JjI)VB~M|_%iK8K($ zf#qlcribcLUW;aqL1k-OL-wO=^id|kWAHm}AQr+v!G4dSHv#xy$m_(I1Dndy5tWP+ zR3*UZ+dzMP56W~&chocseDzh6)4h#`0Vo+=9ZL-Ydwjo5wpEb%n|*PY;A-SXssyID z(#rx?PoleDo$49vHHVkS#uJw{k@J1}TPQjTU8K0gHo-aK)|BdW7_Rb zn}n{;K;Eu~a2V2ftn#l__?n<9ySee7sH=&@Qc{vce!KQ-BsM&O5iAd=n>)WxYl)4r z-JnafhRiv+3o==-V4r)t)&F`}VsPWR($ko6Wo3?KzXs zRBbvP3YmfNaOVMWtX+ENiyGm(>GZK8EYq+zu&Kh2JC*l7`QMYqRuLkIb5%ly2!Bpa zbfdr$=FQyKC&7W7;MX8HvX9&ObU?FP&?v(S;!r$kY!OgBR4?U1xA3Ms(o&DKoUqKU z$();f`Ph!X%e}MfsDPNdHWfo-KZ$hvD-y0B&=|LVPpY4z_&+1-# zY<_)0Of>TSLJIoD=pkLcKD|TqsbLNH$3)wEJDBk7G`YjnzH5y&r%I1lOk?8JBI;X` zD&7huBD>$#D|hl<6Bv(?iwAV`3?V=FQc|Md#qHgnl7{Ft4&|H-)jLp_nuZTRV}1ks zm%sjp``8Q#{Sao1N|Li_vjh^lmWuo7@sknd{;`^wy)Tbvwr~jYvQYHgfIYa>q z9u!x$`?^@Y3QQi4{IX>&JSCxdj@=7^Jghvh3}{~d*n#KL{FdT?|DAjZ3+(H^v@bR# z+#FMiD+u0#PBzz(1@0F|$P?@eQ^7m@FfUvMKo#6q;+kwr_G(+&s_hwXj8o4N4xUI9iLPD(aE0vV2W!ly13AB z#lr5iTl-7GV+O;N@3ATmR8Iu7Kr~!KRt=i^@N@65v_#i0>fi3sD(}9wwd(aTJTiao z{Y7$;sasR_o5Ida&j8ei(v(oWmM-0srr~~0d)fy{M#uANdMZ}rWUMo-NXv`2zS%8pn*?*GP;QyMk9=nh@;^INAYx*6`w!c zQe9x*@H4ASY@>5OJy$)$NZZI*K?GU5A~%Q{9j>`R_Qq4W2*O-G4MPihW@csIhpzEY z6z31xop^zkHy3CChZr`HcY>0gvfDd2>?Ms;He5|iL@mbACOVLJ`;Lv^0tzy5yIJSLP6YP{73=ppii8>bC1B+> z7AcNu$|407KKc3EiifLf2ni^Vjh#>B+HUZ9(OZRuUYlbQt%9p< z+E8GwM^WZd;Sx4^d74fL$`EmmZbmY&8 z^(i*OF?(<9C-u0}_iy2BNLalCzvrr(dNYvHKxA#KXBIrbqqihO0!X;>N zUqg7a*8!W(GIGio1ER8>;>Zgi>B?v}?jKn@4i}0*2@9?-l#;_<~W!*SUR49=-QG4QR`yjqolya=u4-NkM zO?5IyDAJ+ItkB{Y(YS?*rZU4wHi@)$NcDlHtj8*w;dtv;Z2Fv!pn13xgoSY?Obrmk z3L>3^E+^xaDu{eDd~`RL%$!lgajGbgQ9Yhl31s;!=;5|HL${c2wU&_cRol-Tpo{B* znYq4A5^;Md6FELnt!FPtpdwGJlDDLvG3`?8Z6h!0P0CLY%6&@hQ3MQEHVI;Ayev8u zm!SDv7vmhW9#5;`b@PWu7ZDF5WzctVCpKV?wjV2XCEf4f*AVx`tRgg){nx1qw> zb-P)exCB|1`laO}yIFh4)&YU}9b2E-d*Hm&8Vwm?&Wt+RiiEp`CA1HBbza z+(~&rWS}qn6u5sTBQ0($n!!w<)b8~^XX7nT&1S{DcTiL9wdo-fO!-kKK)XR_?`Es4 zCJhXh^b?}~4`KQ@^;5zRN$Vv=ISQGDJ55#W9u~bonx<=MxlRkplUcpxh5Tc#ssd5! ze~MDmdb;J7@Cr*nUKC(b?>E%cR$d)Iy>hGER*mRb*m83^`eD&jA7daQzvRku-!mlj4w zUec#*#^x8$rfpVJ_K&-?d=WO-R%D}N1mDreQtYtQgR`J87&(^E;Z2}`6D0S~?HV8X znuj}UaGtgSPCH=mmFcBfK@KW>u`k7R@viGZK_N(3JPrpYQNj310$;+pX7a_{6;~E% zP45;q%Q$-CjgRdl%|#>97w=yE@p_2y%nJnXPH`eY;e8L)~CeOr-LeaOCI9-hVTayA4T$;GT2{_*hMak z#vUr6dDAl=0>l^q=V+4fhdPAVj87JZj@qa&8UReC_3pwSr7joW=L1HqTae^mx|+M+ zhpuY*F_6Jwwc>`acN~XJ64&l?CcLn41Ht{QEqJXUdL{P$W{amfFtEn3zP<{_j`k~V zdPiA<={s4;XB$F%t9=!|!4cCfFn%J$jjEWy4RKF19ob~`Sey3O0#7&SQ^qr-_f~51 zndxzXX(MkfzOXXt(EcwSo1DwUM9A`bi^skf0}QDJa97cow-QUgpOV0=)fP6n1>IA{ zO&C%15V2E}&`8?XsWc9Yg62(Tf4L@%P_a};jlmzn2AHun@jt~TniQl_Lj?V)#Fz)5 z@T1j*D@yzwO*_|do-t^_>2dUiys`i{`FT%U)X@WiF~Gb-r&X(OD9@KXbePZ z13o!G4rjOxO0v?bq*dVa#RAlu^P+1H!8hPY+>VY)rdMPZ6N&u(5*H2%4vSh6xIu)G z#e(=Tcb;DH)@AJ>IyKPAMq`hhW>1+1fVQ`N3gykzW&JM>hUJTmvcGMLFypET3Rt>D zVm!&hS@2pI)Yt4FpHrq7Ljmr-}Fx#W-|>k_Z8!0I{+)5_lL6v_v#8K z3Ec;VF{;NwH>&x)tn^_5QrVVs=C-n%U=qbRw5@|b7g=FI=-WAMA(W>QLwQn?yW-l5 z@W#aW99PbyjpQU>=2SM&QWN{P1nFu>+=pQaqJodNSib|-+3Ff6;Pv?*p}?>%i-%c#qwiPqNuO(W z8nsaYS1ora8WCm|_K(-XRdp;rTwWIL_eQhgF*8n1gZ^v6(lAJ_3{`S}mueGr-wIis z$e8CsUBQ&|o#^ZcT8ktuztuz?F&(3~w33S@Dr9B1YLk*`Zk8l-WxX_XKj{#w>VwH=_Gv zY4$yGP?@?9*GmdG=3*t|ShG}wAb{8@_A>@?m27V83XhX5QUEmwPBrDgRWRl^=(;Wf zEkJZdG#Ra^m|g(HeLECf*5mu>hrrk={c0JuEQ8UiJac4!$`S@DjCdS(*oSr$tz($} z*pibLEfv>weJd~C=5bJ39RxHWA;k6zBS#f`r{-`JWRXT@+bu*(n%;`zSsZ>E5^*)I#UcIEWD=@pH)g-dlF zN?xigW8*7*!IEjX%_8AT6Suf__u25BO;wk;ME{75l>XScuXwc51#9$m4 zhtj<1{qPgp2KeNQTe^W$)60moV4Ok2FA5??=b-@qa{v0*lvt=NCVy>~E^A^qiA82l zK_bi=Wc#ZAwUF}_DGr{Prvon$304_X`177={mi%dqjKczg6D$+XF!sYv z;39wwSlGTFcvkt_HD#^$70(TVKSyrw$VzcUS_^EgQ;)WuEr6TKq;&K=dPTFIt|k?y zEKhC@T|R~?1o(ZC+-B4|F?epqOZr8mo9qSab?UJ36fs-|Dc7~2N^bALU%DVcpof(X z{^>2q<&!<>02sE48%EYg)KZmDd3B7ITPwg%97Wa8@LV}e&mN2&m2)KI*%Qhe=BLkp z$Kc;=-t)R-it7RivA$XPfc+ITLv`Dd{29tPA)a>bCTUediZ@|qG%c0%gHJ*FS~z#b z8!@MOrj&3s9heSCtD3+^_G^%f$eBk_+mO~m8I9a>h(Iu9c3I2^>$VIZ4Enux>*Ixg zDp6g-aqo1b+DpAd=@=ljtiI#lZv9k(zuOtYmu)Bfh8OM;*R%W{T@(f7%E z8AkD5Xln2c=>Q`PanA`5d}y&apk7Xy7DwbwCc>;9eQU-X9vS%2bhngVHPck?(-*!| zaGk$KqUE81{_8J3ckVwds4WvU*Uee0sT-rIikQO>L`!=8h?-*d1Z=sKpN_{^?l1I3+IS~<^B=2X0W3byyA6Go>-(_+$}sQ8o+xXn3#Y4+2f>)Ro5w$crl%s z=^4rSzK|aFi28#-yo@Std*+pRkfTAFEh%(V=4?n8=Iyq+R+t8zLEf<)VA^r4ipx$AI%7h8< zKfB#UlMbM5L`Ad%Lcr=b370@fV3e#N1>!1qcDk!mZlNuXdOAM;U??3Q=X0yy5Pn~f zxB6T-wYdt=rk>dA9l2nQ_={o9!<5$}LHy)&*Qe`!cF8E%B)B-`svosqgBp&FwiFqnDCTrRDpAhdv^~iO}f*=Py~X(q8)!!X+SHv;2#3=DhPh zmRn~-6aNT^it2qPV`QT1y{CwEh&w6!5;F{oIJsR8#Qch7VOv$0upw9-_d;{{nTRx4 za*D*}#+2=i#Dm2T2h2)QbfZr#1M8o$zINQ0xX2WG-vC1XAeIX|x8&-WEodQwa)4H! zy`L8w!TG8`v_7Ss);{c6$FRRw_pi7HlY?9K-qZPm^3(qFyZjAO19`P8d?zwq+>%;_ft%a%VOprObcm0fQ^cTPdnPXVb_}q+$AmblB0r zK+D31Q0fS0DT>uuh~h&_WYG;hZA8`8`E{Z(z_ivQg%zF*U;yzY$6Fy~}*Akwb zbthcax~J6aMkcME{J?Phkria9fA99>;wvfEH3hZ(+|;kf)&}~B6s6wj@1C<%)VHoZ z6&;YSoSMKZ_W0x5-8Mmmq9=1O_@w=DDcv~5Cc_UW_YZ6XTm0{g4qDUalfO@WTm$!| zOXnv3%CI>CFHv`HLACTlm)RtG;M%d|C15@So=_`O@VJc@DUq5^TH z?=_M2IeDFJH>4_z*_@R_s;`m+J=eKW64{x+eZu}*;-JI7b#wI!8^t`zRqIuvif5jS zHP+-cXkj#XhkFJlE)L#j)G`##SvX9RdMb1C82-_z9DEu`A;OvUj&QQ! zGkbQTuf5MsTg%ircDm4*a(ByL8iUCGt;vf(-cJN1wTCS2SqS}AhaOGYr4)ZR;^>0* zPyc=vfEYNls0BSyW(Xv=f#4)^B!Y_1wi>c7sDu7YQ&fN+wEGP^l0WwDeuxIk^cZ2t zZi~B)+Ava>YgJ~QYp;Kn^td6_N2Qfzs=5bZ6l}kJjpNnBYm-#YdV`Vd3|IL+-N>|I zd#L+9yAu`AM)uo!`{`67>~{c@QnM3FH2Z2B5T3mE?U(zMP}X_vXUS#vPQih%caKsT zaAr}HX=GxYh04Kb0TdWc}yxCtv&V_p|L5>Utd460a^QX&2*bjWePte>b>dv(v7^8J227_M*ZvgD z?Vv5M+#=`4b*RAat#L30#*HZ-aU59W(Ujbyy1bZtyw~Z{PXSwAT-!2%HDVe*63V?! zw@jQ`ebHfVMCpos(b&P%up*An z*>uX1=+czqFPMn-vfmd-g6jSytV#P?;UU|0^kvP|+j`OIkR*>JHrDv-)H0NEoQIGn zkPg!ohAb}z;jE{NwUdF)G)D(LOTV6G3d#uhXHNnD{@+A`QjbX>McI&qu#-R6X4JEy z;%X)<gv8D|<`_|aTXzh)Mb@iEy_#OiFilaguEH-fKF}gc1-x`X~pU$u4 zM({nm`t%n)m_XK0>yqcc?f8;Zo`FqN$Mj(A<>WcdLd)Q_xUVVI-#Pg*?nqM-Rl&HI zQXD@y>(tec5|WKQY}|J0CRSZ?BA`$tZM;hFzq1vlFgsJ=_?sf(dgaFL(Y`dh$`+63 zI2b**O2dK+v8+rZZR|Bio83=)*&0LIKZ=ltpY@a_Mj!7QsCCxtSFcG9c|{Ab`*5+T z5Xn`64~)u-V|aSpKn!kHa={lMg*rhHMp*f&z}8Nf5ioCNOow|2wBggJDZg6Kwh97< z6O$6KH>)J`k+?wINY`KW>#lJ z4d!mf5dNgWQoejOAH=`lh`(8iyWq+1ZSFueXzzlhn3>xK4#2ok<+PZq+czC5wUboK z;1Et~eNC=s6kjIsS{^rcOgP@55G&01tR^NiODXqy z0mXaUxXrztSPf^#T5n-vgr^uWJ3N`Gd^XX;54WEr8=pO#eET)*MurXHfTqOL=zy&nYjL8=YtkmH6P zma`}jkUV!a+hhnZ79tT6=9{p#hOcu7GTZ|CQpWfMVP%DrY*f%3 zC4nHLdz<{&x|LPlZ0J!IPm>(?qq{d~s`8)Azv$SK7>VK~v&`*4rx)jY<-!+~nWQ4s zH2|20fZw+w7rt8?L^NRSH7`k*J1|<-9 z|3IGd26d4qN1A44LOH7g<5)!^XEZND`jt^yd|d0wZ8AtD(xdx`g%`^knVd!ynR6Ya zl}`X<1t+VX)|K zET^QFQB3EEBWy%xVH=b60Oya6?@y_)`Dv=&d>bz5q7EoZg}x`@@^QgQlV;QxF~J3$g~8y_DN%&f^cpMJ%6tRYUmHay~fb4@1yioON? zeGRg0_o(`s1XUeJIi|5%j1AFIiypIO(gn}*b%oilB;-+nsJZPc0GWxprTaH_bHTr) zC>QT2XBKXo3hZd!YFvi=(YAZ-O&)U20V-@gj4`n_cENL}`RujmWYVAyF$7K+nlqik zR9<`Qvl%&2;QuaebHTw(#KV7n?}eraGIzBlxBywCAybXag_K*GLCP?m4qau^;(+Iv zK<5i+C;va79m)dW+NYCulF_9Txo^l*BlQ2~R#f^D&bkZ|LZ2l-zTAp)4!)NXEwxl& zsazPM9`;Dm4@Xu7II}?m5+18=rp=_nh!zO})yu~^6{bvDj46X<{@eo>ER4XHg~@+I zSX_)!g~nO@1YZ(hXli)dNaT8fy^&kg>}2g{uhWIrky(!!hXEDi_ovZEwEkUQ=kxNX zt>NmG(bI1~J$v;R81r?f`P+%NSY|9m_7 z0t%XHU*SkL9yN^N*wcO1Y4nkedG=OZDCu83&XEgBlcyL5ZfVAGHfF7A9Kq8+kJuIffO-B47LD98u?-E7`Jb_n#tEiiddVN?*P@e^O z9`;_=zX72{kUVaL?!#7%mWrzhQ4TR8FB&pUU`p8(M@Xkp{{bL8*{?atuR%w5!-yrz81D&v(-W(v(mM>>UrHLDB48;s~-Tr1F(*xZol9?u7qiSBlh` z9XRji?wr;RfggtHOOJVNuGqQ>UqpBvLC>EZ6tbLW_YZ?Hy-*uGZh;^pEokk&{Z)K^ z((v7gLQgHBD^;=~fd7iDKw~XSq)2k%CG3b#2&22a{)>drMv_~2eD77e%CEFs!yyo_ zZg;Dr^jAk(Ia2JogQ4j!X8ddV&W8+zPH8&P8*PXBWT!v?(kSc4^nJT3Qf{@%cF6Am z@r8cWqRC6ioHa1R9e(3k-`zcYJ*L$fr|7)&qaG%7R?bIc9>#I+0!@;~Y55UG+}4zW z)&|5P0fqE#!)`%(hAZy@T+u0;ku^j|Tt!mAC|X@3q8g*Ll(H5R(yUw?NBbOrowR>K zl^dSzF8&l(9n4Pr8KS|u^iZ ze2DCB|368iH{RrQZz->8MVN4+*}b zL-AQ^GOOCYcZ3|58#b-=VEN#)kr*+4pQ*miLzD9Y6Z?6$Z&AHi42L4({App(pm9m#QBA)5>F~}r~@di>5r{K0;T6t2Sl>??-oPVhvcF9Z5eb7hrrSMS1rtAF(%+WWW7aJ~ zBO5w)I0z>Al8`IZ8|y2!lhXnQ%$^r`eD*kX=#8UAiX%3?ySVL5w>r!_zbmj;_{yxx zuV+%%*`Pvd8*5F0x(L9VMlWFjW3o_oBNDWb8d)njDH`j)A9ACS zCV_ocDVj|C@(_7`JxuI3n4|@bIXCYfzp@Q1`6=e9Qxv6|Z9+|k<7cdlQx85gt+DUb^!o19Gq_@%=@#wDVKo4EUvu4k zl9E+3Bx|q|-F0BCvN$~x&wK?9p^L9i0MBF*fM_u5EbUOjgy-wD--)$fn5Y9)zE99y zZA|hMg*G;@M=u^M&=RS5hv8_yp>n8=!l5*c&nn)Mi;8Lg8u26SP44dvc*2HG#AaMF zEZ~G7gLI%9d(A)%92cZXcv0yh+`e(YzaB4sj{EU*r2ZzaRZ&~-30M!M$TY?*eJ}B8 zG0Z$I2~D?nSlDHV>Vdi0oD0Sy!M+rKr1X!0G|=9ix$|oP;o0>^(AG+|q_niD=EaEc z!~5w>ur#id0XAGcCTubH*c@TEa1Q`o0Qx0`w@w0)At*!53C4)VY!8WDu5tNv_~*k2 zUf2>0Ce}mx`?>9XJyDKz5!jRp__Co&Xu|9);F(RQkh7WRtNbuMf5Q(yf(wDL_P!{L<|~A*lUfWGCk95 z-4K;f#dTqui-JJ{7l7Dgo(Xhix+un0EN{52(-I_W7qPh7%t~9G|1_DgpI}8;mpy4( zYZ~&aIA4TsX}-z;84vl*Q-~4{>IubrISiwf96c=zZv^&vY@CZ&qDPW!WQKZv;iwm4 z#xK&Fw@rbhX=znL%<6e!s3q58E)a_q^jyVi`imNe4eae~l9wB*+;wl-I3mc^u|ope z*~E{P0zLYX&?o0 z37a9vJQHSwx$%n|0A|{Hp^a1&pHF$lt5$4IiZ!!`w-Wr%T@ z6T}OxwM|!dnb%mMC@#+E4KpzKcRYagl8O)*&34>uZa#C8t!swrAQR>3w|EZ2)j4Wj z5PzHDU|_$$(Er8EbeanRJORm(;#Al<|A&0Wn6f$F)x;&@(rgU4Hu42wVBtLK+B}_% zh8`Dp+{04vTC5qDTw*^fFwxyju*WjRV9KsC5Dst4PS}&j^Bw$2F95RB?_AOZEqh8T zCas!WYSberl7^+|V{3<}SvX@m_)kT-u5K$P4;KRn-O8U^ajP14c3p66mfUNBQ4g#5 z1Q2Yp6NdnJ$+sHAWXK^nBckCwJ*HyP$c<3D5T;$_vA18#Cx7;v?b)lBvmw~Bly~o|b`f47$?DpEYWn{W z`$=Fo96y>&G%?fk={aO%D)u0U=+zz@@{ z%@yHIf#Z)7re7e{E{p%C3tlVpI+M%qnKA}?KMM@7i2eckhOa%=xUr#$V% z>fDIg*FiR84k&P5D0v%!n*o74Q&6YV@?s(FXF^W|HeXLcxJ8eCJbO^t7>A$sXGlQ| zK=q^48SZ={x*ciW%-{mC)<^zu89s@zpYPE0FH8Q_PKG}kO5NOYcDHsQxF2avxSuZ+ znk1pUfZhz?o+LDJv|ieF%QY3ugb8VjI_cNi=b+d?iR%qEhp?K24@uLX2Ny6qTU56< zg=n*-zK;^VU_Y?KQ(N%uN0x**oYU?mSJrU+>{-CcBo;n7h%=7G$z?+K^rN`3h&c+mOrz$oQ6B zKFOcw&XLQ^1HxJRk$L#@xu}A3a;8f!&uTu_mPna5Pi@V8ppoUh?XYntJ^1oG_>32k zrG4A_-CSyKAy6}8C#-drXQ_~?z^V+IH;bp-UO=%aVTgl_s=h_z*p&u40HjQy<`X zASM0icSqyMu6vswD?3R>V~8AJo?dlgS3FKas6-Nzpp`~kWziJ@zGQsM`m#D-%k&32 z!$-oEsVet`B|e>h0X2QJ(KPj}BmCs`EC>W$3&Im$a_ch{~Nt z)I0ZL^_i5?7TkMH#>Sy9^)Bnr zdR@I%qjl1YHp&RRPJSu}=}1g^mMT+1_#b@qlK<&PSYy-97@SDDA>1nbZsJ{kl_mdL9W z@U3HtqmNe1Z3Ot~N?{s{%*hAM8$HooUHB_^+ZWEsz#OyPww6RI zN6Rb|?){y|QBx-tPGY>I&U&Gy7g@$K7UnEecQC2HM8_-rZ{QdHCv>)J1A0F0NRyLm zVH!@4sAqUg>-piD6uS z)TpR5m8(Vj6Uc9-2`F-ZywJth92HocbqH!}_oN0#zAk13K+AD>qW51k*cnc!C)Riyf363+cw80P3 z9fKcv;{^NeY86-+BQaw3t<20kP%~d{SH+sW;-Z6pJAu1XVlp(Cni$ZOb44&mv6t{6 zHyb?tGWGW76$wP(q?}uI&n^Zw9kTZZZ)xXyCyq8zuwm9!#Vw0@C!Krx^HZJMpBRL` zEg&&iERy_Vawkx?lTgvFi5K#yNG*=XW- zr?Vj^+X_PF!tMs^CxoH64(fJ&B0~=MW}n*S6`~Y10^??k8pUYdAxAwz+Z$?OaAvIot(eL+7z-4q}0R^fjM; z?eG^^%kvl&3~GE6;r|4{^)N>D{Kc>}c*1IY_^p8Qmko1s>5&adfv!lK z9?jOo9EC!F2W~c&PXIvQZr+8G|BtwC>p_~G^Ju)IH*5J>7;QDj4WNzycOni2VxL-K zyx+rxQ&I+q@hbq4i|dE3CbL}EpLlW5#XmpdyEg`>G7cza=N>lYuKeo>Z$GtK8`W$) zU{jq>5L-~`StR6}LUe0#0E+MQ3)+O_V`tkK$Gx^-5DI2En0pP1?mS6q_ zSicmR{R_HQ2cYX5Df4ia&=uGaG5az2o|3m8H*jQH-F@z<>}0KfGT9RC6u!TZ;@~4K zFdOI$Zsx6blak;xTb0v9EeNYiyd;I<{)@9NJ|w$P*dYJ^GC2I7u-E-_AqD3~HXu0T ziwPjz5}sHp;1cYt0pNNEV@nDuA|}6;jVsuKHdv042)&2`-)4`M;=+s%Lyf?9CkgE) z-IQ*Z@9s0O)yJkuqm@DKWTxUP=sU;HkB64&b&{*x7!V~nYmp{-`v1NyrD zS>F8dX+di@313Y|&~-Z)5SM17iG9Oixi>E}pp}IlU!(F>DFCBZk{`v>y#^7U^K48c zC%sByu$<0F%e7&=gc)u(J}wqejTX6UO5oDTY1$IXoZI)WwEXMI)|LQjnWIEq5}vZiy8$=Ah-nti~znz@Nyea8Dg1sJk-EV9G<)}`!~crd{F;isQ?y{e_*kQ@BvaJ_wkDUw|6iF`@^=iqmeI+W1sRC!eBH0&8hh9xHcap)%vtf0B~ zrNvzO@1FKLQgI0_Xi0%12}JLjml-l8*70ZawAW+WXOUvCX)t{j^6RniW7 zm@M3WQ88=rB$GR|P>TKgvSlRYK{YNeb2G?-Cq8)YKW@kzrrW`^Lu$&K*nfhJaZ|e#U%Pl%1V>pot{ZJ7MeB0*QB%wUlhz!_EkF$U}~6V~S;( zUe8HJ-PrGgwf6k>qCS&szBxper?{-RmfWIgK62~qDe%3gq#TC+tj|!^sEEPUTwkoP zFmiqJ}iBf(ngA)V`(wpOhhJ^pi(b7~!SU>eXes5zu4>)58k=FnQVLMUv&uX(!sUO^4q1J0yybGP<-C-_L}0 z;s$d`bV7(C?{prV>h1LnWcd9>vO9c2&Yjv>$U-n~V<1`JNjd)naknrW)4z5+<5Z~- zewdAqX+fF?YJfMI6OfYOG^g2T<&=H=Hc$yOGv1=~;H5|#Be#JLaIa2 z&_G;@vRD3cGvjNQR@@9y<|u(L`|C%hc1;(atrJ2Y%x3V+8duc7?oi=PCG+O%9lF0ABb)h?%eaAI!aXSX1q~ud5;;h@kW$pdcc> z_ogB}^xmWiNJpiY1OY+1)KH{I?;YtxkzPbVdPf4%CDimY_`bR3UT2TQb=Q#C|+ssGLeBNI*&pRoZa+T|z_>(w*phI~nB?_82U>8_p_gjQ- z9$+k8?2YBYyVL6%oQyyVaIa@C>v5O`C?g@9mVvjn<>3pW!FyY!>}+)UZzrO%x1gFQV5z@kr`vQTQFAr!LUA=!M651)?-%BxPo-1I7+q_rI(0CY50pGNC}S833t4xN9xl2TS#yKnvpEyMi=dKukSH z3||i!e0cLS(Z2>Fqt){(v2c;Pji{lBk>8mEoGT@$)beN~J)V~lzz6sA{mNGv{mI`p zSaArOPKn(Y86c8UVZOv85>VPeX{f_2E0^>e*F9THiPTtxrJi!dKLY3O@E89@5I_0F zebM+Q+n>U2)C1>ND-u9q+V$`1=k&T{<=Xn+k*H$e_O;CbI}OhK=g@j3R@CADk=~#D zSVTCiMi*Q7zCDB;$h!BvD=Eb5=XPhD35+<-@9N*s45Al#iTgu=uSL$~qFYIF#@Tlv zquQOt$kkl14%0wSGK)s_liw-CtU*7tL-kN6`!FT~87Zl<2}hqy98XP0ed|tn1#iac z$*C_k{bgA>+j{Ej2X#COEK8;fw}qb>ak4~>7?;F-_|4}t^yZEO$isCs-C4=mL#^%G z<0MI{j&X-jj=-|nlQ(?^2@edJsg_FebK%E3r8&aanzc8x4}%=vAmJvjzSy7ccS8vJ zp}3tIT=~Ee?Ql%XP04(KVgNAytbcuzk*Kw3Nh&^Y#mD|4j8J&Yx}H4oWxq9316fco zst4!;*7949qYB2;R2pj9YulRIPDHFK^?DZUr#U`zuoVGtMPw+zB=Bmy0+5H~H&YWy z2Lrq!#hxCSLh!^wt2AOsI{S1t3z8zqo%bZ1vnremenes#8S1?^($Oej!etm4oftoG z`}n1**Qde6^v$<8;r?aQQF{I(1HoSV&CM>XySnojM&Cx^Nvm;6J%~>hZRL+cjz%gV z5?4tB?}R@1eMA0xf88evHz>ULUiuGQ30I(*y?guq=S?8Nb`@cob1@i_Dm$_0H5oTb zNM})co$6Hfq2mw2*xPwWlC|wj8hx*lHBTih3!cC z(3i#)#;TH3l~Uu8aa2$DF0tugIZEJYRNE-}t4ZcK8RJ;q#Bj%HZI}xXl-IXNG?fC?mR; z?=Jp0ap>>dzu#P!(5U>rZ)$5*iXibr_pi^`#ELZ)%o$og?F1=ZHI=n4>fxPE021p` zf`p5(!z;M`Z@`t6muU}h*pP#aD?wM!mL92u_Hvl1kJzH;%4lDswZGybJtromd#vyF zvkD=2(=-ptZt}O}`5$UZY@>Bc!89S_m9MM74Ha0fj zNhkT!7^#o&qlY62#F)Dv@ND7n3p*xYFBZ4|e94o|N5`}vH#yQ{{IOE$UgzL`I8Hn z!jh9@?tAN+#}xQK6r&B_{f&ZNbP7&7Ue{0=RW2Brl8nq5hVS$2Y^dp2y=+NdsWEv^ zHJStx6ncmJp3xd-bME`yCVgkc3r;gSW$Y$y8)4*Ge8VW2FI$Z6*ov!J%}Ka9ppRQ@ z)Cf&|KTa^YnOmp`_(qH0_15y@aJqVDM%LTZ<4Y`{Xi81nI7_d@R(a~mp#;7SYR~w5 z#E4pA8~Fp}?D({&qLZ!+!Y(2tL?xE}*ac6MkVARn_&tEt@Sm!9PS{$18PG4gARFS< z`kS%HA$+gK#pg0=l0w@tvc8w;>h$jDz%(R1WuksMR>|q>Fz@&3zhI32mnYtJ2cUuY zi}f3|0zmt;?jz)yQK6COFmPWD;#yA!Zv7cTsq!4A4jb5trdl(zp$Px}@3@zs=}e(2 z(-x?qkFw_H#%{lJ-p4858T6ks@{=~YoiCE4NqvJqdqm68LK)6UsLq%W^n{b?dhVIl zI`bD?bVdzo`&vYFy{9gw4*)p<;)AGo@wAyzq_`xvj>R&kM$6(W^b#Z}OStdRaFwe) z1;|)@+<_1uF$*UY0Vhb{$v4!`TeE4dM&dFxaZKNx4?1EXs)%cbD1rykU>n&VG4l5_ zq8EbCml8}TC;v20KKZnZ@GMJKx{SMw2L7?L0%u9J;93SBI#-;&Ii8%#s(E^ABBZ|d zjVIQY*FCHYGK4aB3O}LcDVv#3)^eWy1`CGnl(<|}#^N^)K2jMv-Z94e9XmqKww#;1A8FE@!*IJW_nhO8Tg5Y5f6hJb<8iVf zK#$wzm?~^fWP}MI$m)0?gGu(c;=$bw?}yP+(gi0fx1+&o_YseMO(*7!v6!f5k2JhtK1bIrrZvvOamH}NP)Rte^usH!Rss3Iz(j9-w1hDJ1QReVTO1potV z8xO#KQ>-xoEkPjM=?L<+Hsgb5G3B>DjR|kHhm8C7#J-GSu=slUY;CjxwoF@0z;Es5 z+KsNkk>}lrb?en64S@=x_YXy8kI%c`Sj`5Zl5;7mf>ARcLo{_3nui}gLXtFdXF9)4 zp0Og^yAXcr@9gFTxtm^IJ~xi5_urNIrYFyBHErP%xXl3-of#y5RoLtJTHj%%lY^2( zWd=7L>!i(WZ#|zWlpTaVr>@v|S*^piHgE=8RRI^a?u+Dd85Z`{iL(Lp-r-(OQ^F3> z4{c`L4aXN+jga9*+O+{(Zp@iRNN|P_fO+Mh!Vf{l0B&C@HN2s!2N1?@%i^yJg?pUd zar43-_aWoS7OX7pVD1O=ta$ZNcUcDRn0}Dn(?ANv{E9cZ`u1LFvHuoFwq7l-WBL;t zItlo*F5vNq$F~h8JB~AhQ4|0mc3%qVgnxSy2l$X=lf1U*uU+sfwv_6Qq~|bL*)ULS zmcRS^FklO+8g3aupx!;<1W$A{kG~Hi9IF^^N*T^x;sS^D@#&s_V-BV` z;Bs)kgcObSd?TMmt$_GMp#jEy8jNYM!!Z1K7RFIzFS)(_764EKk|qE_o|xLLLi`wh z4E*g=%)#v%=owTw7$(#m`d>@L<|;=5sz77m*R`vaB+T zzNL$vr}-QqX6GpTTLYwdXcmSaWDxFbnJdn|$DZoC< z04@N!g8=G4$R|>oE0%EjX7Nsi>)(HbTh4gbA7hrtkBKZ&+l_G+ViSOGP+myOUA#Xw zyy5PkEq6@dnd-oYjR(2*TD8}i{qKE=4;g;#@F3OY3nAqvzy=5e`BO|7Zl_70kc|aA%MOmino>AzxbyYo{?pBhr?Z0^qu5*}e9~}ih zt0k8GsZhfp!8n>)qiojMerZBeM(c28g1<)d=ACxe<7B499^f~EYOm{`L3Ho)F!po? zo{O!#UXL2>!lDz|!k|r2#eP=dKNN`njN%8_K0>sfJ_;LLLsO8O-aEAVd}-}_DMi^2 z6b*_`q#thdZbFei$WQ;H`RFSppj*S-S4o=iX0gWeTsZJ~cmF;aN=<~f z3^vN`vY|#CzxLb+|3mq`^>x$};d;Wcj@YTEm-fQ7M>|^yQ(wcR?E<54*-{lKaYG8S~<_nUPU6AUp&5ADBUWK2{N{a)xiO-QJ$5+m1RE{;d9r;m)6F zSX+_QdB-uSk9%({%{A3a{o?gTd{*rS27*60)GE!js}R5dv1jf6*c8jwlvswbJWp<) z-Aex(S!HPne@I=yZKPSb1G{an>liBFZ6};HrN6IW|H(9nlj{ZNw6~rJXPch9DvOCk zk>{;M4;H-`@gpj+{hMe|WtzZ&Bz?I z#UPKc5oGwoYI4p=&n1CkqTeupugi4E`Z^#Ydo1iA8}^sl@g=0;77+afaN4k|XLs8D zPj?J2`hYw!02v#Vr}0}-uBT@@zG006@CES`SeMKY)UO?1^)0c`qH366vSv9Wm|^3c zNr`3s=u3SIN%q@G$JxVXw3yH-^OsrU#T&NFGJPofzLfg~eH7~gUVsVm-WObs<*0j) z&=S`x5Fjq^R;o*Cy5lX)s3%#TJ*C9{I(9#yoRD=#00sMa;zgttfZCDs)JD-%fk7Nm z3o_MU;_fuhIszt}A0-<#zGoB`DN-r-CXG^7kJ2z>V;8{};UjpAHhvMaor|MTefpSs z6O;sMjNxy)EtBIeo9Qd1JSy)&94$L{9lrk>^l z^aiA~N*oFS2!m6N!Gt}&jL#SPP4@-|Q*?&XX7+vTfDbaJlGJqzkIgmF!`FJMgI?~mSm4J1?98uk`bN{!o_7E;nq8*oUE&gsB7XOa1o zvN-{uN}TY3?4Pd7n+jrb5T({~otsJoZ=a@74=}0uF+Xgpd-n;%%*SK{1XP+SBgxqf zsD0!PR}_}_`t>Fc0*;J_qXpdaSu-|E_YPO$@-x9Z06Nt zA;v$f3rU&!q3{>Tg}sw-zs%k~Dfz09`mo!BsyQKZ;gOz{KZjB)F!rCuUY|ZQ*SqHd zKZek0(M!98xwB-d;%SUs5$tM3x7$sTdi)iXH&W^VAVVG7M;jqra)KGW!q1`>E!<=N z)&7~l+QI2=T_E#}g&*FOUOZ#jOsFMng${WWObP(PaJ+92?eEYvwcbPI<%U^{ts zw*NOEg7fiz0wUn|Z`&=JI+rtibhZYJp_-MsIJ4hakNp75Ckh219@}yBMUED%jM)k< zPZf6Lu?z6M4CPn-k5K-9CGaFB--8wfMZ~NN^;ggY247DY$&~&kH+)a7h(qNMUL_>^r5xQKFLxw(k3Ga= zYerF%Gc(`Q>i;s68cRR21>P3?zX5wxUI(Nva!99JzMF6QyntF`A7CkxH_niT2{9KE zrQ%G&>r!a-uErq<)-HQ8s{i9v-ctv}B%!r@{BYwMrEx}Kx~AI!*3vugp=n&%hoL&I zDWDB%I%DSM^t zov8Nc$@MqSjc1-rT)m6$uGwm9kQ*7B&7ZOI?VJf~j9*vPGA3>gd(i!tP4p7Qr~^wm zd$V_)*6&<#Ztsx+e4?ok%h}Z2T}9r@W!hk>#T1|VLnC4}$){r=q7lexh1EW`jC(e@ z#O5)Ih78nRW07+#quO0@;@I$p=o^`^)xUrie~VAwwPpj@Zl70VCF!eQ$z-5A{L$k& zEj*Ar;_~pKppBH!r%v(G!Y2xgg&y%3(y?WsLmrEN0U;P-|5aT2+4cwDxQ7X}Behac z{n=t+d>6R-{U4cb#lO6zOPI!+f8Bxrk}d>mNNJ6a{e&OqJq`K#Us+4tu!jM3;&Rx4 z*^?gPx6DLP)DyZ=&X40K{mZU;vyAog3!kWyQyPl%@T_$tJAt(%>brBgr62M~?|5WN ziby2lh5-p|`hsUz@cbL?PtTwytNXdc)6dcQjGK5_JLv|L=58KtX6W<2M0?{R4yV#y z-CK>xn6`pCJ{O@k7oJdsOgH3AErMlm*4_3vXgFo#%_|Usc#qB}@g8mq3e4E*;Y5>f z@3X$>;9Zf}OP4B7Mgrop2{;4jEJpPJTM)a!Pg_@Tl4LQm;8QhiQ<~vlGS_cs3HvY~ zxodmB&b7Ohj)H?>%xc_SG3202#9>T}B*6V%?>Y5Z!ToFe@9L=z9;g%-&V&QpgIy7; zrS>Eh#J zG-lz8bYL0)eSKO?6%dJ8{ay%`a3&piapEx-Ko|O*y^D7@x4QZa>fy*|kwU_9RZAHL zrg%A|AD=E{#QPh)0K+b9&W(Y|A5r(&Yu^7ssg46Wl|X|SE^w1WNv@jg-81Q%ak9lF zKK}0aCifxwla&*S*fMk93o8Jpc`?qO@Y*`s5(y|02=;)o>qk_fNbx|z2i>seiuiMM z?#JX>p4>472N2&E@N6nYO*=sqVR^(xg00jr!)to(58s4w`-}oq?;9yS)Ix5vZv4{+ z+n5DXt%%>Cy2_Ql8WT2Js=p^c^p<)em61mBaTYTWKwoOQ|E%5XY7976&KmJz}ySI zcdUb8^Pya~G5mCuxlqVL9!u62Jk;9Z2xWW4kvyp~yE*Opjs78AwV=s_#>Ts`=-Q#h z)C8(3Yv{D$p>6D^YrrQs`R7?9n*~ug`y74(+Ev+#+{_XizK+G4=l;3a#04Hg!Mkwd zfqSS^)2C0;Ojqj~Af>sTUY_{jOHTY?_NbIh9m_P?m;$>|qQJMQC%@wJa$)U)vu!~d zyNYvk0$O?s)1%strR>beSPQl?3fkIOnt5$gMbjk#cdWKxE_`Pz@W17*O^*xPU|wgo zdEN}Ht!jecmxb@eJJk=7s#n|vfK`%w*+NT7+@6b5QL?+i@pV^1isf`fx2@ z+=GATM}U>VVtD~q^F*%7?XXVBLEjfI#b|DwQs^_`Yb^rsv0B`Eu%$s>k!mYn{T+4m z>9gv%1ANyRjJMa3&p@MlNG$yUuagdGajrU6J>&xxar0Bh)c)9*`geJ>t1JcYN8>YC z(G97V&Q0bSQP|lo3>fb?8VgR#7T}q=bo;LADBKkZ#QZzXVK9zjgmHGY7TZg(Ngj4k zg24=La(YE2HkG&*M&9A)9!n39Z=i~d(H*zwUcHNU>%RwF8NY_45 z!r86Z?OCl$OPdwol`=`|_$S?vLoyeA<%;->+OsDH{~#S!?C~>QXHA=h-jdrSBELH} zYCN6%)pl-;!F?e!z7qKG0vdlMSn1=gWgvj$yaiQlB}=_IYm#T%G25#YZE<>p zN=d&W8pgoIL6b9=z=GO_duIFRdlor9gsf`a?pilp6Dy%jeM_3BBg z!tSV1ox=WtAz<`R@qgxEqJ;UJ3eP8}R=8cRJ#8H9L7fD)KM1?Nk(Dvi^VX>X1H9WJ z(qL4<-ZPwpOy3`tV3bJCIA#}*vO--q?Y!#!G4sa2pQ;s9)nyevW_7!wY3!MO*%#H! zSg=Eke_{IHcm;b>1S(4jja{18-W2xR-nH;**o`0aI3yZIwxebbuy|CO8|B7INl1g&guem zj`7^FE$^L`OuHXt$(p5Me;@ANX*jE}!bZzG1c?IkE!aa&e#h}!jmy5b zL$I7*cqHOclZ;EzyGt8>7J=O@%SpTYDbA~ z;bEx>G_ODfMh2SPC{kkwq9!nz$wEOIe}2YQF6(s!4n4DqaLkm}SaRW1jpVi~o2vMa=NXlt`%n=0qW;+sRc*ZB!A zRGX1FbOAGUPR0v#h55rR2vevNi(AQW^RGp^4lr;wU=!ag@p{0Oc8qNA2qOHI9uMdp z>v-YERNT*<-2iBZEngyuOYQ{XsjmF%xSv5^eiiUP3pm`W&27t&q-4-v8Bsd1Q%YkS z|2}D({KZQ0kypyxW)v7l1G(|_)a`ikIq(J&3)=zRBz>2SX&OMeN(t;c>i4;PYJxOo zUz7lqmUjYvZ@oOoEl!Gx9?NtF{1&V6*F3)Dsz+Y;RQz#DeCg;`r}o z=xpt^lwbq(f({3@c-2EzEUmsax6sPVr6eH|AYfb^@7abjgf2Ty;HrQVQmav&QD?mR z40iH29x(&jffieTI=J_6e#UAEVLX}u+nKsW!ILq7pKe~p9{3KsI_VnI%2=cO8ENck zqaGFc#mN0s_;E}pXMWMB`m8Jp3$*Y1CG7x?t%V0rBa+pQT{;{9x1%bmuaUn=$Mk{o z;Ew72ECfLZ#CGuA5Zj$1YL7a{L|oHHA^5Ye`r1p6Ah)+XKt*YTnbuF)RQTVCE`0+P z>6FSc&8n~MhBvSs39~r$_&;GwWQX1bT-RJ*Ztnd%7^3Ejl|x$!E8m0fF7XSH4y?lP z32eu(#`UtCINUy9W`fJ?BjBP?WCLt|&0=GL%g6C9Xc%(T!yUZaEXk9`kC_^yi=2^3 z#II7|^8A+sI<$5@>WS_zo?_gVUK=x}KmE`^l8Q}R@_|S8e=+GlMGD9({b3{w7Z9KQ z&T;5c1EZbdd`s6^GBS68Td03GPIR(hRp#FD?riK8C|ShXm6G zD*!VNo&aB}d^NWidDEwtDgLwgcun&g<@AUD&|*XGo-7P%1MJ`mByX;PVkP6?Nk}kI z;A(y2C=wm70POP}5vqFU8sg=pkcZlgJP1}|bR_Cc0~mYXJwTcv*K6+(u*mVro&KD> zy+X}7X?;)UqDEw)Zksdy_H5l3u)Aju*+dz3r30MzJ@=)v8fk0aEoBv~n?raDzWK`@=U5OU>0XBw1Hd=4A74vU|!U^!_~nO_aW`^g8_z7yQfwFoMtMz)&`{NC=t$ zNQVK2A2kgmrjI&nwBaP|-zwDD3lZf6_6JG~qA1{fS6d=4RO zM_9HX8b@A)kWjn{Xwt46;uu_fWC>x8ylX0Wn@YO>bkali)akB(Avx%DgEIo~)E5`L zPZkGs;KesS1EQ!`=q4Co?MOJo6QxnbXllRoM9g7-ot`zrI$JS_;Z(1W3wUDOB*Yna zaEO;TqVTiaP2AM5>Q>X~BH=caQ=8}x@ELKqyPK5HhL99o3Ob!?IKbMS&Y*~RuBo&5 z!mWIlJeu}qg0|&jmLcQSLn%7&yZxfK&0mUFEaBdH(((=@sbcYmKvg(P0(Qzbx)OZw z=H86h&Fv8Wuf?fjxKYQf!~R&OB|NE8@{fdTfa3NK-;&H6PrEm2AJT}0xdj4x;IIiX zAlndOdS-tS_dGN?SD98INig_$9Jd@H7XecMKnJ^#Gd=L@R)YvXUx^Xs>Vl|&#tMeq^hloQ7;%!Hj_EEe&xFOasWu{S&;cjTYygB&82CH=wB8p9Gy>|4*h|=qFWhRV82>z?08m y}C>p=LM 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 diff --git a/frontend/src/assets/logo1.png b/frontend/src/assets/logo1.png deleted file mode 100644 index 93b93755e49963d09c63cbd0df33669376c8f90d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5798 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 diff --git a/frontend/src/environments/environment.prod.ts b/frontend/src/environments/environment.prod.ts deleted file mode 100644 index 3612073..0000000 --- a/frontend/src/environments/environment.prod.ts +++ /dev/null @@ -1,3 +0,0 @@ -export const environment = { - production: true -}; diff --git a/frontend/src/environments/environment.ts b/frontend/src/environments/environment.ts deleted file mode 100644 index 0dfd866..0000000 --- a/frontend/src/environments/environment.ts +++ /dev/null @@ -1,18 +0,0 @@ -// This file can be replaced during build by using the `fileReplacements` array. -// `ng build` replaces `environment.ts` with `environment.prod.ts`. -// The list of file replacements can be found in `angular.json`. - - -export const environment = { - production: false, - debutUrl: 'http://127.0.0.1:5000/api/' -}; - -/* - * For easier debugging in development mode, you can import the following file - * to ignore zone related error stack frames such as `zone.run`, `zoneDelegate.invokeTask`. - * - * This import should be commented out in production mode because it will have a negative impact - * on performance if an error is thrown. - */ -// import 'zone.js/plugins/zone-error'; // Included with Angular CLI. diff --git a/frontend/src/favicon.ico b/frontend/src/favicon.ico deleted file mode 100644 index 997406ad22c29aae95893fb3d666c30258a09537..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 948 zcmV;l155mgP)CBYU7IjCFmI-B}4sMJt3^s9NVg!P0 z6hDQy(L`XWMkB@zOLgN$4KYz;j0zZxq9KKdpZE#5@k0crP^5f9KO};h)ZDQ%ybhht z%t9#h|nu0K(bJ ztIkhEr!*UyrZWQ1k2+YkGqDi8Z<|mIN&$kzpKl{cNP=OQzXHz>vn+c)F)zO|Bou>E z2|-d_=qY#Y+yOu1a}XI?cU}%04)zz%anD(XZC{#~WreV!a$7k2Ug`?&CUEc0EtrkZ zL49MB)h!_K{H(*l_93D5tO0;BUnvYlo+;yss%n^&qjt6fZOa+}+FDO(~2>G z2dx@=JZ?DHP^;b7*Y1as5^uphBsh*s*z&MBd?e@I>-9kU>63PjP&^#5YTOb&x^6Cf z?674rmSHB5Fk!{Gv7rv!?qX#ei_L(XtwVqLX3L}$MI|kJ*w(rhx~tc&L&xP#?cQow zX_|gx$wMr3pRZIIr_;;O|8fAjd;1`nOeu5K(pCu7>^3E&D2OBBq?sYa(%S?GwG&_0-s%_v$L@R!5H_fc)lOb9ZoOO#p`Nn`KU z3LTTBtjwo`7(HA6 z7gmO$yTR!5L>Bsg!X8616{JUngg_@&85%>W=mChTR;x4`P=?PJ~oPuy5 zU-L`C@_!34D21{fD~Y8NVnR3t;aqZI3fIhmgmx}$oc-dKDC6Ap$Gy>a!`A*x2L1v0 WcZ@i?LyX}70000 - - - - Frontend - - - - - - - - diff --git a/frontend/src/main.ts b/frontend/src/main.ts deleted file mode 100644 index c7b673c..0000000 --- a/frontend/src/main.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { enableProdMode } from '@angular/core'; -import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; - -import { AppModule } from './app/app.module'; -import { environment } from './environments/environment'; - -if (environment.production) { - enableProdMode(); -} - -platformBrowserDynamic().bootstrapModule(AppModule) - .catch(err => console.error(err)); diff --git a/frontend/src/polyfills.ts b/frontend/src/polyfills.ts deleted file mode 100644 index dcd18ea..0000000 --- a/frontend/src/polyfills.ts +++ /dev/null @@ -1,53 +0,0 @@ -/** - * This file includes polyfills needed by Angular and is loaded before the app. - * You can add your own extra polyfills to this file. - * - * This file is divided into 2 sections: - * 1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers. - * 2. Application imports. Files imported after ZoneJS that should be loaded before your main - * file. - * - * The current setup is for so-called "evergreen" browsers; the last versions of browsers that - * automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera), - * Edge >= 13 on the desktop, and iOS 10 and Chrome on mobile. - * - * Learn more in https://angular.io/guide/browser-support - */ - -/*************************************************************************************************** - * BROWSER POLYFILLS - */ - -/** - * By default, zone.js will patch all possible macroTask and DomEvents - * user can disable parts of macroTask/DomEvents patch by setting following flags - * because those flags need to be set before `zone.js` being loaded, and webpack - * will put import in the top of bundle, so user need to create a separate file - * in this directory (for example: zone-flags.ts), and put the following flags - * into that file, and then add the following code before importing zone.js. - * import './zone-flags'; - * - * The flags allowed in zone-flags.ts are listed here. - * - * The following flags will work for all browsers. - * - * (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame - * (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick - * (window as any).__zone_symbol__UNPATCHED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames - * - * in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js - * with the following flag, it will bypass `zone.js` patch for IE/Edge - * - * (window as any).__Zone_enable_cross_context_check = true; - * - */ - -/*************************************************************************************************** - * Zone JS is required by default for Angular itself. - */ -import 'zone.js'; // Included with Angular CLI. - - -/*************************************************************************************************** - * APPLICATION IMPORTS - */ diff --git a/frontend/src/styles.scss b/frontend/src/styles.scss deleted file mode 100644 index 29ad8c8..0000000 --- a/frontend/src/styles.scss +++ /dev/null @@ -1,3 +0,0 @@ -/* You can add global styles to this file, and also import other style files */ -html, body { height: 100%; } -body { margin: 0; } diff --git a/frontend/src/test.ts b/frontend/src/test.ts deleted file mode 100644 index b4dd603..0000000 --- a/frontend/src/test.ts +++ /dev/null @@ -1,27 +0,0 @@ -// This file is required by karma.conf.js and loads recursively all the .spec and framework files - -import 'zone.js/testing'; -import { getTestBed } from '@angular/core/testing'; -import { - BrowserDynamicTestingModule, - platformBrowserDynamicTesting -} from '@angular/platform-browser-dynamic/testing'; - -declare const require: { - context(path: string, deep?: boolean, filter?: RegExp): { - keys(): string[]; - (id: string): T; - }; -}; - -// First, initialize the Angular testing environment. -getTestBed().initTestEnvironment( - BrowserDynamicTestingModule, - platformBrowserDynamicTesting(), - { teardown: { destroyAfterEach: true }}, -); - -// Then we find all the tests. -const context = require.context('./', true, /\.spec\.ts$/); -// And load the modules. -context.keys().map(context); diff --git a/frontend/tsconfig.app.json b/frontend/tsconfig.app.json deleted file mode 100644 index 82d91dc..0000000 --- a/frontend/tsconfig.app.json +++ /dev/null @@ -1,15 +0,0 @@ -/* To learn more about this file see: https://angular.io/config/tsconfig. */ -{ - "extends": "./tsconfig.json", - "compilerOptions": { - "outDir": "./out-tsc/app", - "types": [] - }, - "files": [ - "src/main.ts", - "src/polyfills.ts" - ], - "include": [ - "src/**/*.d.ts" - ] -} diff --git a/frontend/tsconfig.json b/frontend/tsconfig.json deleted file mode 100644 index 6815c14..0000000 --- a/frontend/tsconfig.json +++ /dev/null @@ -1,33 +0,0 @@ -/* To learn more about this file see: https://angular.io/config/tsconfig. */ -{ - "compileOnSave": false, - "compilerOptions": { - "baseUrl": "./", - "outDir": "./dist/out-tsc", - "forceConsistentCasingInFileNames": true, - "strict": true, - "noImplicitReturns": true, - "noFallthroughCasesInSwitch": true, - "sourceMap": true, - "declaration": false, - "downlevelIteration": true, - "experimentalDecorators": true, - "moduleResolution": "node", - "importHelpers": true, - "target": "es2017", - "module": "es2020", - "lib": [ - "es2018", - "dom" - ], - - "strictPropertyInitialization": false - }, - "angularCompilerOptions": { - "enableI18nLegacyMessageIdFormat": false, - "strictPropertyInitialization": false - //"strictInjectionParameters": true, - //"strictInputAccessModifiers": true, - //"strictTemplates": true - } -} diff --git a/frontend/tsconfig.spec.json b/frontend/tsconfig.spec.json deleted file mode 100644 index 092345b..0000000 --- a/frontend/tsconfig.spec.json +++ /dev/null @@ -1,18 +0,0 @@ -/* To learn more about this file see: https://angular.io/config/tsconfig. */ -{ - "extends": "./tsconfig.json", - "compilerOptions": { - "outDir": "./out-tsc/spec", - "types": [ - "jasmine" - ] - }, - "files": [ - "src/test.ts", - "src/polyfills.ts" - ], - "include": [ - "src/**/*.spec.ts", - "src/**/*.d.ts" - ] -}