From 3a28f2f0a2ae15b56557fe924f24179310e25616 Mon Sep 17 00:00:00 2001 From: loathingKernel <142770+loathingKernel@users.noreply.github.com> Date: Sat, 18 Jun 2022 21:45:36 +0300 Subject: [PATCH] Implement image manager Signed-off-by: loathingKernel <142770+loathingKernel@users.noreply.github.com> --- rare/app.py | 15 +- rare/components/dialogs/launch_dialog.py | 87 +++-- rare/components/tabs/games/__init__.py | 30 +- .../tabs/games/game_info/game_dlc.py | 11 +- .../tabs/games/game_info/game_info.py | 17 +- .../tabs/games/game_info/uninstalled_info.py | 20 +- .../game_widgets/base_installed_widget.py | 16 +- .../game_widgets/base_uninstalled_widget.py | 19 +- .../game_widgets/installed_icon_widget.py | 51 +-- .../game_widgets/installing_game_widget.py | 23 +- .../game_widgets/uninstalled_icon_widget.py | 39 +- rare/models/__init__.py | 3 + rare/models/apiresults.py | 22 ++ rare/models/signals.py | 29 ++ rare/resources/images/cover.png | Bin 0 -> 314684 bytes rare/{shared.py => shared/__init__.py} | 10 +- rare/shared/image_manager.py | 367 ++++++++++++++++++ rare/utils/models.py | 48 --- rare/utils/utils.py | 113 +----- rare/widgets/__init__.py | 3 + rare/widgets/elide_label.py | 25 ++ 21 files changed, 652 insertions(+), 296 deletions(-) create mode 100644 rare/models/__init__.py create mode 100644 rare/models/apiresults.py create mode 100644 rare/models/signals.py create mode 100644 rare/resources/images/cover.png rename rare/{shared.py => shared/__init__.py} (88%) create mode 100644 rare/shared/image_manager.py create mode 100644 rare/widgets/__init__.py create mode 100644 rare/widgets/elide_label.py diff --git a/rare/app.py b/rare/app.py index d78fd3b5..33144b48 100644 --- a/rare/app.py +++ b/rare/app.py @@ -8,22 +8,24 @@ import time import traceback from argparse import Namespace from datetime import datetime +from typing import Optional +import legendary import requests.exceptions from PyQt5.QtCore import Qt, QThreadPool, QSettings, QTranslator, QTimer from PyQt5.QtGui import QIcon from PyQt5.QtWidgets import QApplication, QSystemTrayIcon, QMessageBox from requests import HTTPError -import legendary # noinspection PyUnresolvedReferences import rare.resources.resources -from rare.shared import LegendaryCoreSingleton, GlobalSignalsSingleton, ArgumentsSingleton -from rare.utils.paths import cache_dir, resources_path, tmp_dir from rare.components.dialogs.launch_dialog import LaunchDialog from rare.components.main_window import MainWindow from rare.components.tray_icon import TrayIcon +from rare.shared import LegendaryCoreSingleton, GlobalSignalsSingleton, ArgumentsSingleton +from rare.shared.image_manager import ImageManagerSingleton from rare.utils import legendary_utils, config_helper +from rare.utils.paths import cache_dir, resources_path, tmp_dir from rare.utils.utils import set_color_pallete, set_style_sheet start_time = time.strftime("%y-%m-%d--%H-%M") # year-month-day-hour-minute @@ -54,8 +56,8 @@ def excepthook(exc_type, exc_value, exc_tb): class App(QApplication): - mainwindow: MainWindow = None - tray_icon: QSystemTrayIcon = None + mainwindow: Optional[MainWindow] = None + tray_icon: Optional[QSystemTrayIcon] = None def __init__(self, args: Namespace): super(App, self).__init__(sys.argv) @@ -63,7 +65,7 @@ class App(QApplication): self.window_launched = False self.setQuitOnLastWindowClosed(False) - if hasattr(Qt, 'AA_UseHighDpiPixmaps'): + if hasattr(Qt, "AA_UseHighDpiPixmaps"): self.setAttribute(Qt.AA_UseHighDpiPixmaps) # init Legendary @@ -102,6 +104,7 @@ class App(QApplication): self.settings = QSettings() self.signals = GlobalSignalsSingleton(init=True) + self.image_manager = ImageManagerSingleton(init=True) self.signals.exit_app.connect(self.exit_app) self.signals.send_notification.connect( diff --git a/rare/components/dialogs/launch_dialog.py b/rare/components/dialogs/launch_dialog.py index b79acdc1..812d5074 100644 --- a/rare/components/dialogs/launch_dialog.py +++ b/rare/components/dialogs/launch_dialog.py @@ -1,45 +1,77 @@ -import os import platform from logging import getLogger from PyQt5.QtCore import Qt, pyqtSignal, QRunnable, QObject, QThreadPool, QSettings from PyQt5.QtWidgets import QDialog, QApplication -from legendary.core import LegendaryCore from requests.exceptions import ConnectionError, HTTPError -from rare.shared import LegendaryCoreSingleton, ArgumentsSingleton, ApiResultsSingleton from rare.components.dialogs.login import LoginDialog +from rare.models.apiresults import ApiResults +from rare.shared import LegendaryCoreSingleton, ArgumentsSingleton, ApiResultsSingleton +from rare.shared.image_manager import ImageManagerSingleton from rare.ui.components.dialogs.launch_dialog import Ui_LaunchDialog -from rare.utils.models import ApiResults -from rare.utils.paths import image_dir -from rare.utils.utils import download_images, CloudWorker +from rare.utils.utils import CloudWorker logger = getLogger("Login") -class LaunchDialogSignals(QObject): - image_progress = pyqtSignal(int) - result = pyqtSignal(object, str) +class LaunchWorker(QRunnable): + class Signals(QObject): + progress = pyqtSignal(int) + result = pyqtSignal(object, str) - -class ImageWorker(QRunnable): def __init__(self): - super(ImageWorker, self).__init__() - self.signals = LaunchDialogSignals() + super(LaunchWorker, self).__init__() self.setAutoDelete(True) + self.signals = LaunchWorker.Signals() self.core = LegendaryCoreSingleton() def run(self): - download_images(self.signals.image_progress, self.signals.result, self.core) - self.signals.image_progress.emit(100) + pass -class ApiRequestWorker(QRunnable): +class ImageWorker(LaunchWorker): + def __init__(self): + super(ImageWorker, self).__init__() + self.image_manager = ImageManagerSingleton() + + def run(self): + # Download Images + games, dlcs = self.core.get_game_and_dlc_list(update_assets=True, skip_ue=False) + self.signals.result.emit((games, dlcs), "gamelist") + dlc_list = [dlc[0] for dlc in dlcs.values()] + + na_games, na_dlcs = self.core.get_non_asset_library_items(force_refresh=False, skip_ue=False) + self.signals.result.emit(na_games, "no_assets") + na_dlc_list = [dlc[0] for dlc in na_dlcs.values()] + + game_list = games + dlc_list + na_games + na_dlc_list + fetched = [False] * len(game_list) + + def set_fetched(idx): + fetched[idx] = True + self.signals.progress.emit(sum(fetched)) + + for i, game in enumerate(game_list): + if game.app_title == "Unreal Engine": + game.app_title += f" {game.app_name.split('_')[-1]}" + self.core.lgd.set_game_meta(game.app_name, game) + self.image_manager.download_image_blocking(game) + self.signals.progress.emit(int(i / len(game_list) * 100)) + # self.image_manager.download_image( + # game, + # load_callback=lambda: set_fetched(i), + # priority=i + # ) + # while not all(fetched): + # continue + + self.signals.progress.emit(100) + + +class ApiRequestWorker(LaunchWorker): def __init__(self): super(ApiRequestWorker, self).__init__() - self.signals = LaunchDialogSignals() - self.setAutoDelete(True) - self.core = LegendaryCoreSingleton() self.settings = QSettings() def run(self) -> None: @@ -106,14 +138,11 @@ class LaunchDialog(QDialog, Ui_LaunchDialog): self.quit_app.emit(0) def launch(self): - # self.core = core - if not os.path.exists(image_dir): - os.makedirs(image_dir) if not self.args.offline: self.image_info.setText(self.tr("Downloading Images")) image_worker = ImageWorker() - image_worker.signals.image_progress.connect(self.update_image_progbar) + image_worker.signals.progress.connect(self.update_image_progbar) image_worker.signals.result.connect(self.handle_api_worker_result) self.thread_pool.start(image_worker) @@ -124,9 +153,7 @@ class LaunchDialog(QDialog, Ui_LaunchDialog): # cloud save from another worker, because it is used in cloud_save_utils too cloud_worker = CloudWorker() - cloud_worker.signals.result_ready.connect( - lambda x: self.handle_api_worker_result(x, "saves") - ) + cloud_worker.signals.result_ready.connect(lambda x: self.handle_api_worker_result(x, "saves")) self.thread_pool.start(cloud_worker) else: @@ -159,13 +186,9 @@ class LaunchDialog(QDialog, Ui_LaunchDialog): self.api_results.dlcs, ) = self.core.get_game_and_dlc_list(False) elif text == "32bit": - self.api_results.bit32_games = ( - [i.app_name for i in result[0]] if result else [] - ) + self.api_results.bit32_games = [i.app_name for i in result[0]] if result else [] elif text == "mac": - self.api_results.mac_games = ( - [i.app_name for i in result[0]] if result else [] - ) + self.api_results.mac_games = [i.app_name for i in result[0]] if result else [] elif text == "no_assets": self.api_results.no_asset_games = result if result else [] diff --git a/rare/components/tabs/games/__init__.py b/rare/components/tabs/games/__init__.py index 9a38e74a..91a91a8f 100644 --- a/rare/components/tabs/games/__init__.py +++ b/rare/components/tabs/games/__init__.py @@ -3,12 +3,17 @@ from typing import Tuple, Dict, Union, List from PyQt5.QtCore import QSettings, QObjectCleanupHandler from PyQt5.QtWidgets import QStackedWidget, QVBoxLayout, QWidget - -from rare.shared import LegendaryCoreSingleton, GlobalSignalsSingleton, ArgumentsSingleton, ApiResultsSingleton from legendary.models.game import InstalledGame, Game + +from rare.shared import ( + LegendaryCoreSingleton, + GlobalSignalsSingleton, + ArgumentsSingleton, + ApiResultsSingleton, +) +from rare.shared.image_manager import ImageManagerSingleton from rare.ui.components.tabs.games.games_tab import Ui_GamesTab from rare.utils.extra_widgets import FlowLayout -from rare.utils.utils import get_pixmap, download_image, get_uninstalled_pixmap from .cloud_save_utils import CloudSaveUtils from .cloud_save_utils import CloudSaveUtils from .game_info import GameInfoTabs @@ -41,6 +46,7 @@ class GamesTab(QStackedWidget, Ui_GamesTab): self.signals = GlobalSignalsSingleton() self.args = ArgumentsSingleton() self.api_results = ApiResultsSingleton() + self.image_manager = ImageManagerSingleton() self.settings = QSettings() self.game_list: List[Game] = self.api_results.game_list @@ -71,7 +77,7 @@ class GamesTab(QStackedWidget, Ui_GamesTab): for i in self.game_list: if i.app_name.startswith("UE_4"): - pixmap = get_pixmap(i.app_name) + pixmap = self.image_manager.get_pixmap(i.app_name) if pixmap.isNull(): continue self.ue_name = i.app_name @@ -216,15 +222,15 @@ class GamesTab(QStackedWidget, Ui_GamesTab): ) def add_installed_widget(self, app_name): - pixmap = get_pixmap(app_name) + pixmap = self.image_manager.get_pixmap(app_name) try: if pixmap.isNull(): logger.info(f"{app_name} has a corrupt image.") if app_name in self.no_asset_names and self.core.get_asset(app_name).namespace != "ue": - download_image(self.core.get_game(app_name), force=True) - pixmap = get_pixmap(app_name) + self.image_manager.download_image_blocking(self.core.get_game(app_name), force=True) + pixmap = self.image_manager.get_pixmap(app_name) elif self.ue_name: - pixmap = get_pixmap(self.ue_name) + pixmap = self.image_manager.get_pixmap(self.ue_name) icon_widget = InstalledIconWidget(app_name, pixmap, self.game_utils) list_widget = InstalledListWidget(app_name, pixmap, self.game_utils) @@ -242,15 +248,15 @@ class GamesTab(QStackedWidget, Ui_GamesTab): return icon_widget, list_widget def add_uninstalled_widget(self, game): - pixmap = get_uninstalled_pixmap(game.app_name) + pixmap = self.image_manager.get_pixmap(game.app_name, color=False) try: if pixmap.isNull(): if self.core.get_asset(game.app_name).namespace != "ue": logger.warning(f"{game.app_title} has a corrupt image. Reloading...") - download_image(game, force=True) - pixmap = get_uninstalled_pixmap(game.app_name) + self.image_manager.download_image_blocking(game, force=True) + pixmap = self.image_manager.get_pixmap(game.app_name, color=False) elif self.ue_name: - pixmap = get_uninstalled_pixmap(self.ue_name) + pixmap = self.image_manager.get_pixmap(self.ue_name, color=False) icon_widget = IconWidgetUninstalled(game, self.core, pixmap) list_widget = ListWidgetUninstalled(self.core, game, pixmap) diff --git a/rare/components/tabs/games/game_info/game_dlc.py b/rare/components/tabs/games/game_info/game_dlc.py index 7f0c375b..0cc325f7 100644 --- a/rare/components/tabs/games/game_info/game_dlc.py +++ b/rare/components/tabs/games/game_info/game_dlc.py @@ -1,14 +1,14 @@ from PyQt5.QtCore import Qt, pyqtSignal from PyQt5.QtGui import QPixmap, QResizeEvent from PyQt5.QtWidgets import QFrame, QWidget, QMessageBox - from legendary.models.game import Game -from rare.shared import LegendaryCoreSingleton, GlobalSignalsSingleton + from rare.components.tabs.games.game_utils import GameUtils +from rare.shared import LegendaryCoreSingleton, GlobalSignalsSingleton +from rare.shared.image_manager import ImageManagerSingleton, ImageSize from rare.ui.components.tabs.games.game_info.game_dlc import Ui_GameDlc from rare.ui.components.tabs.games.game_info.game_dlc_widget import Ui_GameDlcWidget from rare.utils.models import InstallOptionsModel -from rare.utils.utils import get_pixmap class GameDlc(QWidget, Ui_GameDlc): @@ -90,14 +90,17 @@ class GameDlcWidget(QFrame, Ui_GameDlcWidget): def __init__(self, dlc: Game, installed: bool, parent=None): super(GameDlcWidget, self).__init__(parent=parent) + self.image_manager = ImageManagerSingleton() self.setupUi(self) self.dlc = dlc + self.image.setFixedSize(ImageSize.Smaller.size) + self.dlc_name.setText(dlc.app_title) self.version.setText(dlc.app_version()) self.app_name.setText(dlc.app_name) - self.pixmap = get_pixmap(dlc.app_name) + self.pixmap = self.image_manager.get_pixmap(dlc.app_name) if installed: self.action_button.setProperty("uninstall", 1) diff --git a/rare/components/tabs/games/game_info/game_info.py b/rare/components/tabs/games/game_info/game_info.py index 4eacbf3b..18b4dfd2 100644 --- a/rare/components/tabs/games/game_info/game_info.py +++ b/rare/components/tabs/games/game_info/game_info.py @@ -1,8 +1,8 @@ import os import platform import shutil -from pathlib import Path from logging import getLogger +from pathlib import Path from typing import Tuple from PyQt5.QtCore import ( @@ -25,20 +25,21 @@ from PyQt5.QtWidgets import ( QMessageBox, QWidgetAction, ) - from legendary.models.game import Game, InstalledGame, VerifyResult -from rare.legendary.legendary.utils.lfs import validate_files +from legendary.utils.lfs import validate_files + from rare.shared import ( LegendaryCoreSingleton, GlobalSignalsSingleton, ArgumentsSingleton, ) +from rare.shared.image_manager import ImageManagerSingleton, ImageSize from rare.ui.components.tabs.games.game_info.game_info import Ui_GameInfo from rare.utils.extra_widgets import PathEdit from rare.utils.legendary_utils import VerifyWorker from rare.utils.models import InstallOptionsModel from rare.utils.steam_grades import SteamWorker -from rare.utils.utils import get_size, get_pixmap +from rare.utils.utils import get_size logger = getLogger("GameInfo") @@ -56,6 +57,7 @@ class GameInfo(QWidget, Ui_GameInfo): self.core = LegendaryCoreSingleton() self.signals = GlobalSignalsSingleton() self.args = ArgumentsSingleton() + self.image_manager = ImageManagerSingleton() self.game_utils = game_utils if platform.system() == "Windows": @@ -281,11 +283,10 @@ class GameInfo(QWidget, Ui_GameInfo): self.igame = self.core.get_installed_game(self.game.app_name) self.title.setTitle(self.game.app_title) - pixmap = get_pixmap(self.game.app_name) + pixmap = self.image_manager.get_pixmap(self.game.app_name) if pixmap.isNull(): - pixmap = get_pixmap(self.parent().parent().parent().ue_name) - w = 200 - pixmap = pixmap.scaled(w, int(w * 4 / 3)) + pixmap = self.image_manager.get_pixmap(self.parent().parent().parent().ue_name) + pixmap = pixmap.scaled(ImageSize.Display.size) self.image.setPixmap(pixmap) self.app_name.setText(self.game.app_name) diff --git a/rare/components/tabs/games/game_info/uninstalled_info.py b/rare/components/tabs/games/game_info/uninstalled_info.py index 05dd63f8..e41e6d78 100644 --- a/rare/components/tabs/games/game_info/uninstalled_info.py +++ b/rare/components/tabs/games/game_info/uninstalled_info.py @@ -3,15 +3,20 @@ import platform from PyQt5.QtCore import Qt, QThreadPool from PyQt5.QtGui import QKeyEvent from PyQt5.QtWidgets import QWidget, QTreeView - -from rare.shared import LegendaryCoreSingleton, GlobalSignalsSingleton, ArgumentsSingleton, ApiResultsSingleton from legendary.models.game import Game + +from rare.shared import ( + LegendaryCoreSingleton, + GlobalSignalsSingleton, + ArgumentsSingleton, + ApiResultsSingleton, +) +from rare.shared.image_manager import ImageManagerSingleton, ImageSize from rare.ui.components.tabs.games.game_info.game_info import Ui_GameInfo from rare.utils.extra_widgets import SideTabWidget from rare.utils.json_formatter import QJsonModel from rare.utils.models import InstallOptionsModel from rare.utils.steam_grades import SteamWorker -from rare.utils.utils import get_pixmap class UninstalledInfoTabs(SideTabWidget): @@ -71,6 +76,8 @@ class UninstalledInfo(QWidget, Ui_GameInfo): self.core = LegendaryCoreSingleton() self.signals = GlobalSignalsSingleton() self.api_results = ApiResultsSingleton() + self.image_manager = ImageManagerSingleton() + self.install_button.clicked.connect(self.install_game) if platform.system() != "Windows": self.steam_worker = SteamWorker(self.core) @@ -104,11 +111,10 @@ class UninstalledInfo(QWidget, Ui_GameInfo): available_platforms.append("macOS") self.platform.setText(", ".join(available_platforms)) - pixmap = get_pixmap(game.app_name) + pixmap = self.image_manager.get_pixmap(game.app_name, color=False) if pixmap.isNull(): - pixmap = get_pixmap(self.ue_default_name) - w = 200 - pixmap = pixmap.scaled(w, int(w * 4 / 3)) + pixmap = self.image_manager.get_pixmap(self.ue_default_name, color=False) + pixmap = pixmap.scaled(ImageSize.Display.size) self.image.setPixmap(pixmap) self.app_name.setText(self.game.app_name) diff --git a/rare/components/tabs/games/game_widgets/base_installed_widget.py b/rare/components/tabs/games/game_widgets/base_installed_widget.py index a775ef42..f9d64842 100644 --- a/rare/components/tabs/games/game_widgets/base_installed_widget.py +++ b/rare/components/tabs/games/game_widgets/base_installed_widget.py @@ -6,9 +6,9 @@ from PyQt5.QtCore import pyqtSignal, QProcess, QSettings, QStandardPaths, Qt, QB from PyQt5.QtGui import QPixmap from PyQt5.QtWidgets import QGroupBox, QMessageBox, QAction, QLabel -from rare.shared import LegendaryCoreSingleton, GlobalSignalsSingleton, ArgumentsSingleton from rare.components.tabs.games.game_utils import GameUtils -from rare.utils import utils +from rare.shared import LegendaryCoreSingleton, GlobalSignalsSingleton, ArgumentsSingleton +from rare.shared.image_manager import ImageManagerSingleton, ImageSize from rare.utils.utils import create_desktop_link logger = getLogger("Game") @@ -25,6 +25,7 @@ class BaseInstalledWidget(QGroupBox): self.core = LegendaryCoreSingleton() self.signals = GlobalSignalsSingleton() self.args = ArgumentsSingleton() + self.image_manager = ImageManagerSingleton() self.game_utils = game_utils self.syncing_cloud_saves = False @@ -63,8 +64,9 @@ class BaseInstalledWidget(QGroupBox): pass self.image = QLabel() + self.image.setFixedSize(ImageSize.Display.size) self.image.setPixmap( - pixmap.scaled(200, int(200 * 4 / 3), transformMode=Qt.SmoothTransformation) + pixmap.scaled(ImageSize.Display.size, transformMode=Qt.SmoothTransformation) ) self.game_running = False self.offline = self.args.offline @@ -140,11 +142,9 @@ class BaseInstalledWidget(QGroupBox): ) def reload_image(self): - utils.download_image(self.game, True) - pm = utils.get_pixmap(self.game.app_name) - self.image.setPixmap( - pm.scaled(200, int(200 * 4 / 3), transformMode=Qt.SmoothTransformation) - ) + self.image_manager.download_image_blocking(self.game, force=True) + pm = self.image_manager.get_pixmap(self.game.app_name, color=True) + self.image.setPixmap(pm.scaled(ImageSize.Display.size, transformMode=Qt.SmoothTransformation)) def create_desktop_link(self, type_of_link): if type_of_link == "desktop": diff --git a/rare/components/tabs/games/game_widgets/base_uninstalled_widget.py b/rare/components/tabs/games/game_widgets/base_uninstalled_widget.py index 1354cdfe..de216578 100644 --- a/rare/components/tabs/games/game_widgets/base_uninstalled_widget.py +++ b/rare/components/tabs/games/game_widgets/base_uninstalled_widget.py @@ -2,9 +2,9 @@ from logging import getLogger from PyQt5.QtCore import pyqtSignal, Qt from PyQt5.QtWidgets import QGroupBox, QLabel, QAction - from legendary.models.game import Game -from rare.utils import utils + +from rare.shared.image_manager import ImageManagerSingleton, ImageSize logger = getLogger("Uninstalled") @@ -14,15 +14,16 @@ class BaseUninstalledWidget(QGroupBox): def __init__(self, game, core, pixmap): super(BaseUninstalledWidget, self).__init__() + self.image_manager = ImageManagerSingleton() + self.game = game if self.game.app_title == "Unreal Engine": self.game.app_title = f"{self.game.app_title} {self.game.app_name.split('_')[-1]}" self.core = core self.image = QLabel() - self.image.setPixmap( - pixmap.scaled(200, int(200 * 4 / 3), transformMode=Qt.SmoothTransformation) - ) + self.image.setFixedSize(ImageSize.Display.size) + self.image.setPixmap(pixmap.scaled(ImageSize.Display.size, transformMode=Qt.SmoothTransformation)) self.installing = False self.setContextMenuPolicy(Qt.ActionsContextMenu) self.setContentsMargins(0, 0, 0, 0) @@ -32,11 +33,9 @@ class BaseUninstalledWidget(QGroupBox): self.addAction(reload_image) def reload_image(self): - utils.download_image(self.game, True) - pm = utils.get_uninstalled_pixmap(self.game.app_name) - self.image.setPixmap( - pm.scaled(200, int(200 * 4 / 3), transformMode=Qt.SmoothTransformation) - ) + self.image_manager.download_image_blocking(self.game, force=True) + pm = self.image_manager.get_pixmap(self.game.app_name, color=False) + self.image.setPixmap(pm.scaled(ImageSize.Display.size, transformMode=Qt.SmoothTransformation)) def install(self): self.show_uninstalled_info.emit(self.game) diff --git a/rare/components/tabs/games/game_widgets/installed_icon_widget.py b/rare/components/tabs/games/game_widgets/installed_icon_widget.py index 5821b32e..5f39ebd1 100644 --- a/rare/components/tabs/games/game_widgets/installed_icon_widget.py +++ b/rare/components/tabs/games/game_widgets/installed_icon_widget.py @@ -1,14 +1,16 @@ from logging import getLogger -from PyQt5.QtCore import QEvent, pyqtSignal, QSize, Qt +from PyQt5.QtCore import QEvent, pyqtSignal, Qt from PyQt5.QtGui import QMouseEvent -from PyQt5.QtWidgets import QVBoxLayout, QHBoxLayout, QPushButton, QLabel +from PyQt5.QtWidgets import QVBoxLayout, QHBoxLayout, QPushButton, QWidget -from rare.shared import LegendaryCoreSingleton from rare.components.tabs.games.game_widgets.base_installed_widget import ( BaseInstalledWidget, ) +from rare.shared import LegendaryCoreSingleton +from rare.shared.image_manager import ImageSize from rare.utils.utils import icon +from rare.widgets.elide_label import ElideLabel logger = getLogger("GameWidgetInstalled") @@ -21,55 +23,54 @@ class InstalledIconWidget(BaseInstalledWidget): self.setObjectName("game_widget_icon") self.setContextMenuPolicy(Qt.ActionsContextMenu) - self.layout = QVBoxLayout() + layout = QVBoxLayout() self.core = LegendaryCoreSingleton() if self.update_available: logger.info(f"Update available for game: {self.game.app_name}") - self.layout.addWidget(self.image) + layout.addWidget(self.image) self.game_utils.finished.connect(self.game_finished) self.game_utils.cloud_save_finished.connect(self.sync_finished) - self.title_label = QLabel(f"
dlKB z<^&SQ2A9>UqqK##IYjbMFiOgl#$U{Y>bg;9mI?&j1WQcO)6~}6*i|k*RbIf{Gb+YH zm)r7d4+|f~DaC$DrepH9sZD;3jiaX46A!^s#cB^sz8j*|iq200o50d#YwrlKk}d;~ z6KN^;{|<~&O5Mk40|*O|4Uz%G%Y z+YXzxsab)@HR)c9lMx*_Li#kpZv+3V>F5%C4}R4*+>%t8|AH4+VXB-{<;ou~y6y$= zq|8>@g#`nG$=4T|`ZlS&f(nRWZXU4EVA80$zDBU=lVVsYu|C)HQh9;Vdm^(!HI%G5 zj@@1&TUTOioirFNtIGy~r&ao($@ZgFLL`?rrKspb2aG=WLp~0Qo~J{bf{xB+66s5B z0rb=J0L?r! #H2-h`FGe7jT75YfdE<{;IH(K2bY!aOlZh*ZvItsQ|E36_*VAAGNZ?Kkjq% z!GA>vyVH*~B%f?4e7ipfWVCVh4ukWcjSr0o`ye(7!!yO|O<_@qH4}TK8)VA ^EZFfB#;lF3l`XSHuyB}|E-SC(+1y!L8=kGYRb*W$bwf&)Ft3l^6O%CQ z_I@qNxf_rvYH+AWej7El_gV!A78gZFf40D52|3U>9of743BCoGV3ZOGN8mG3{(yq_ z>q1hHFhAkjksc7 m84 zMr)))$=hpCH~e|Li$+UF>M^{Ux@UCbKXmc5A}O_V-0bnlhb*?QM80lpc|Dp!?VF~% z8D^IOby{ex3ES3B&6i%*$2nTA&EJ#_@k%(1D>bz|cr|2DWM0H@=iRVdi9a8}cOAq= z2(3>1dQ}Q}Q4YlsA=Q8xe6hE=t{md^%Zj!w%hPRsIe{xMfq;mj6It~ > zA!Yjz$B4>U=G8Vaa%^o;v|@M$D=7qCHHB w omBVGm z JzrN!IitZ{LC=M!sEA$Snuhhk zaoTA!!!0zRA?Bu;nb`SMAv6TbhWZq=ECM0W WRI(}P>)IRHO`dyMpijPg4>wVGh&kP^y((W7^{ks7Dq zN|T+#OO0#+HX=Xwlq)2pd@V%KI}?<#cwLvwkz^6#sRa(lcS1J_KCx&!dLIvX^ax=L zzGyneQwFXOKaS9)#IZ_#U`iZKc1X?<2?b6fpbbNs4AteC!f<=AIZ8;2esJ?!p5Db~ zcq*8B%E8@UW_jNNBML1DW1^a0Bq8@U4teBEIgp*QscVG_(A=*8u|E(r6Ge|X>Kjk6 z0|K6v`_&3l0bEf3k{Y>_1T~IYvU=4dc~Sy$;~N|=gmxPvhU{|Ko*ae}1IclYI+yH} z*d&20mZLl<$UtA*%H1E40d2k-Y<*DDowqP{ZOA30g3uO|3y=s%2JCA{Dh)% !KvT8qK5m`E)To z4At?XA7Sj~POn1_Yt6e6F3ijEC?M_|uMr^l_|HW2=MP}|i|#>*ASsCsu8{L=C`G(! zY~Ysbq*@~zm61RR@K#J?i30_`$0{Y)$ivh;44ydeYn-Z46xpw*y
Oym)N7l$EZWhU_yuhMl7*P0|yzf(#6vL4hdm396 zAOxTmm+T_e7Bma*QgxnzF7qh?Sjc}jV#gwSs7pJmeCaoOBEc$Kd{%y$MxV=O~9qQmLxEP-c(;aZ3faMV^gv z%`A7$DM2zQo?27-^H1{cVHk%#|Chu08AA3HSr?%skspVDxK~s$7;Z kYoh5hrd}PfuR>HOWT;%tY?Lz zS@J@=W&35H20Iv4=qVU%kTak%{gLwmgPBpP2a_U>%Y~#P{m}%4+8*UO%4@jRUg=?( zn3t1b{i77W$#b3P)i-X`emd 5{xuHZY( z=OOnEC7nDE<%m#Nu@0*?99-lr#-v(?OJc_C#>E{f3I1_%B+Nr?GF9bJ6xHmjCMS^} zg|?>FL^%jSFr7R|0gtH)5q(WvT5bzy2FQ0m1Y3JFX=B#PIatJ4+yk*UO)KO`OpWTj z=xc_b0p7b>brj(yjELn1E31XQaKO_i1QRVev5PdC6eZyU? bNzGSPlz$1% 0Fo zm2t4eK@t#x?aD`$8~=xLOU<-US;+tg=%Ok{lIR*mB0wM1xFl%W8^5IX(Z25)S($W+ zrU+@l!(NLEoU8>8Fz2T7AWW~c9b3HM%DLz|%U^A!;U3tOQiyKF>`WFbrFj;i8w`|$ zQ{Du5c?VskOYwAEINq}t`M%4-pKrdAF-eb1L>MbgcR>cb^JBa3F|RoIMZ->DJ3D1_ zVfPYri=a$YwYb0~UdZqVk%YQla9mWg38!cnZCVp$d=beqAH+`0Y}I55Hy^7dDyH&{ zKR*W&Y1?L18^JmYeel9acZDWvr%0yiZ5U=>^7pdB+}m;4AFA1*V%Nd|^}66K=U0|f zj8-^UDp`yb wc2 zIOQCrxe6N&e9bXzdBaRmEmZVgL^^lns)pWW1;uUyIqgtF|M9Yt_ILgz)YTO;7}Y>& zx6s1S)B0h ILEY^vfcnu9|#_ zga}XUctU}#&{39>3i8rH6-O>|FiEZfSv6JFFSvsYd6xYAp;Y5Ur(XrKAu)(t1>{C` z=)cjqgOB&tdUD7@N$Lbc$pN9z#DBI)2*46#jQQdoJcnF#0&NF%{iRiS-oF7ns msj!`q*|~<1@)x=ALg^e;Y(%KcBHSSmCW;*oa$07)}0yTueo0$Z538D9ZdU5e2&< z+ItimM|ufDEp7Fqnr4*C*m%@VvS%m1(hRXs)fI54+)+Rn8X(ad(@~xuovaueX{>D5 zISj@iNtiK4)&n_}pf!Gqf%hYXgOWAN +Lo^GQBvbhG$7JyQOnk`Cdl4jKfb22TPEzY$6(aAZ$p)hzQ)$X8TO@iZN&cJjMEJ zI;$WIA}+Mjt5DKD4iUnuLun{oJGnNZ@-d7IQLkk0^C74BZJv<*hKK^$sG-97N#uls z`MaAXl>pdn^dSrd5vCCUVHA+yf-xU#n(@St7#zC`0l*X-j>In(eE%4MEsjaiS=oNg zE1&Z9P+}DT5&GbbtgFYIelB}(0vEndq~)hwEZpQB$nl%TG;aFo{#Et5yDYONJ_==o zgoScg&mg8+purvyzm<&Ukd9mekML#BB;?oJmI?@z=yz&+I9N6qtL8i?$!BY?q_#T# zZ%|lqd+@aIwwuU<5G*1ru|Te4;29YpiL e`#sN9N1BZ6^@rXg;6T!VB(;$eZYb(44hx znc8Ft&NB&ehIhhgaR4)ioruFUayb~?Wd(r)yOQja^k5P*(t3<^KR4VLPgZ^OY|`vZ zvI}W;nXs44c<~B)aHb7f*UD^uHp@k={g<3t$C)%OF#b+(xsmQ!jp>x+hA4SKsdK3! z+b;n@>oq`_if05hzCinZRVriRYMpbpi7LoZmVI7hso%;ATr`sv7s5=FyO4#jS6J}< zA!aJAN?Qo=5U vaplUU#%lqkIw1BXB5s_9e_;Mn+)CZ({(RE?a|SZM)OD k?!%o|FRLxgV z-#&H+66^0hz6~xM+AQ~rfLeuGk;za&rXF4|9Kx o zviUxsY8EvSEj!A=`WuyrE#b+D+i0fEj(&SQ*+@$W Jjm>P!5OJ(hcJn{Z=? <2#6yL~<(E$Q~Nh)|Mg{ zgmch=wDYE~&1;M)MO5XW!0>6o-Y~6A0bJ>mWp~1;VHcp)4+8 bR121rpn6>JOVO zKI+7F0uon`uoM84wwnUkK)?>-19bCkHe5KI#6E6nD^g~*Y*^|q&V-TY(v3I;@vYj5 z+sS1pTT>!c54gv@IX%4lx~dZhYoAF_|4eh?-<4qT+1iR28IxS_#U@D<)-|Q|C|Q8J zS!R;{m5)hW4L-b6WzM!564GjAfnBT7CLiPynp7pS$jX%h-+DrM&Am{eVRc!l*Rt5- zYU~g!5{z}-vIFUzjALDETEUDm{ ^L9$uM$*g3;!IaN5P5BBlNWRr3}_E5{18!Q>aL$i%xP&)c?s(-)7VJvK`w)SX@+Z<2Rnu*PTKCNKnSPx-3wC?{{FeF4z^$DE2TJc zCbPNhMhE%ja}T+w!VvQQ>t@gcxt??3Y+5>2HDCIXrc zYQI$`pVL&>o_qYQz3`4wUSw?I>wT?r>%-WHNJIs)&aZBIXitgZ+OGVHN>+?iar`2< zMYR=P42FjV-J4y-YWdzq(_c;Qwk2v=sgQ)lnr^GRdw=E@23O_3(6&UVc)-M)LFdvB zMfW^O&VL;yH%88pEmJ}NX``qSOq|51&5*s6?kL7)=j?Y3(aS0qSz`l`uI|-HRZmk` z4 >WL*4NK!r#~M>$V%Ed*32ASDdOzj3<}7{3NX4t_*(^ILbCgZ3A{b<2^k#3O zToDkO0Gp=Su=p4S?X(x$kU$ZgT{NGiVQ `>Z _B$wQAjlXaK jXh)Fw+TKuSwe%;X0msQ+qf7XHLm$os !s{epW%@IYZh)09Stn|9F)h)mI@|0n@^P+u_lklhye)R}>`;F=6E<;0C2q z!p`#o8=?ez#5(|1G%Kot@E)wR6k$uK7 R(M>a4%cc1unFV3aK2LWNWVCQ2kV8 z5NJG!E^}Q-i3_5fuFpEHvN@^v>vZ4UyXCCY5~{V9H$w{VkxGXe9o7NU)*MDotC(82 zA3D3V%3Px+k(U?PxTei#@8lJ0x02X4WYMOi#o-!iB^?jTNzh7unm|SCMO#v|4Gk_^ zqK0N`x0w!$J7P7MA4Mk&L&0cgAG5Oha?8tqv{lT5a1GTTRtNjq+Cy)@mI6whU}+tR z@!fjO&RDD&%tGN8h%HH ?NqhrGc8AXi?ngtK+MA0+)>|2!?O>YXp)f z!wh=fspfNqijNdC-dz@OL;PBy%M+w9nwfW*0~;S-QY@+l%kfZ6`AZGy={N;<+X-*a zz~$g0Kmj1Tm&awH^@|ldt{Gn7=7rB?mE(j$1^(T4vhTiTJNtQ+B{GpW_Wfq^m2%$% ztl{_ENT2$(jM}Zbq6Sjz57h)+G=sRG*}%Y}(Z2V(v{>G~N`jrAo7T34dwd==EA!o_ z=O6w3=bCL33ixh)5ze}_gtpJ7Yi=H =VS8k?i|8%o>I!?nz>S)a;@PNt3UrGEr(Q z(aF|}j}2m6yaaq%L=@M!#kIA;M!xZspcr&dlck3~-0}=9;00;fCzLGvMk (Gq$N4}o*Y&W;FJU>1kTq@=1KAT`I}BFv1=wQI zI64iPQkC@a{>O~W)~DpBi+sxH4(|Ga%gd@yO_xV(Y^6l`gWh7XR-9nTCN5sbtKiY= z6;fgajyLttLebk&xNh;!yEHS~BvM;*Q8ET$5?$_0E?h;Lo!sbd3>MB{6j@9cPmbXb z!8qPB@hZYt8@ NanR^o&f@zo6SuZz40cXCL%~YWYsa>Bq_p(1 za}8%$V}O_o4sU)9;|fVkvmuVetJR7CDc5$PDVD;4?R7`>F$JujV``OG)oN(q?U4F| zlowJX3B>kvVD@r)zItbTk_W)gh5@)}3l}X>2J0;J7W!l@sb|3w5E|M<7=b(qEK~(^ z1m04EWlL71-zqO9>C4|$rSi&fa<5f`>P5-0%6>&K?-u3MiqEd9V5?663S` H>&V*tvr1%i5w6|py&T~nSlF)!@CrrJ0)@X=oxW8QfZ;e zg8H}ccJ(&sGSC=T#{>W`2_@(I%Yeucf=;ke)M0daK9AmRG0y`FLp9|aKm6WI3t_UL zRs)SeWyu#}SWhn2J5)YiRnU=BAVrkc%k{lVTK7dY+maG8rm7;ZU&|jnbx1Kc39zbO z2;OMCpSRFMKh!@)19E-Wde1e$Oi}o9VG-BMyM<^4)%J%k=wO|}I3U7C1UL#SSmoGv zk*BFai_aF+4o*D+qr8s3H0^ODEG5^`N-cEG2ZHTHpjnI6Jb2Y6ezBF?oAnRF0^YP0 zzHQZKUCkfg<;=0eIABnsx_-CJlU#_A((FFdw7d;3tXmhvZLE&z{SuAhz=LLnt$*p6 zB3(`&S5u57VcIZ%LXTQ}d_3&CKtWhS(-3c4Bf%Fd0Ti$;r5q3idE`O>vrz}nV+uvv zNj5+5$9%I{;rLxZaT*N{QId-C% i=UBXiiH`FWa z 38_Jke$VFXULW>9VZ*Nh&9};iG zD6-?m^%>%$C{w(gD|c>yR8CwNdQccjB%^FYSp;4^L%Js4t h3fXrNMrBm(0SJ?K%{^6b(Y =SY?eYF?je;g^g47`vzPh)`mR!PEx{EANTB=+l%kynwg` kFE}%mCai IV<| z0}lHm+GErq0Z3=~HJU*ubW=HNm2Rg{beC?>guO?#q8QkN+w2pMdT dZyqUJ z3~S4LC&QY3+G}wjD_<&@5rg)Qtq6Z0__4liZ_h+GekLuHe{g(dA98IZnaXKn6y91m z9NevirHWG2j|Hogu1tbDBEy(GfjfteEvv0m+U!KqF95_f(BTi1{M=u
tsIRR!^;4Vl4iXM5;w+Z<`vw1;taL|6!U^u@J`m(wLw&8^8k zpG$IYI8t3S#%J^uk882A7CSyNyhl=v9SPcLR_s=V*!25*K_b&7Ta_%3^zz!?7?Jm? zrXm*l{Rc!j@^w*IDzhpAE)oiW>EJR s6((lsGzZhqTTDTTYD)qb|z79ZPpvIZi! zizp_nJ@$TIJZNs=w^(-ZQ|PrGuVT_om=-+2#g&EaPxMS80IP#> v^%%Nk1?7y4ERmr|U~vb31dqBY1FJgd9Hx+cN0 zko(O|8a?qwz^sef{jN{09qDjMWY{q5e6p6x&D=OINM!d_tlVt7R=&wpb5o^?zYqxk z5s$dcR&7uqcStu0Q8&y#N7$%x@x=4VyybqULQ$sr+`oVnt~Cb(inQ9WvhZS++hxl9W_c z3aOVE?AM_$$M!f%tL#G&t=GD=?r6lvU8`cNq}42Kl3Xb|5}SkT-d{=ZfzLSjphbPK zp)y|$JR~cl9~3+qiQm<=+Ys3RNX*~p`A_-O6~;ATf{BZ1IZFudUtm zE!E8yl}i+DsV^4m)KUBQ1f#k`H1cOxLU!5P)IhktJ~}MwA`ua(<$?_bXb|=(KI5!2 zV;L=?ZH<{wC48kC<|+(xC{k6BQst=i7~y;8xF=~H?WdzH& E@BFxesCKY(H5Wpg;-~o%61OCU&S2}yet@YQ=4z!VtDw?+f7=pnBz9+bV2RhNl z(w`Q^OiJ_!RuwRSD|vy@uLz;IpDZ-bQnzA(Idb Fi|=dt^^=wxydG1(I9BLdpng#WiXojqm8Asi;nh3Q&vEK1C(w*VtEsO}%yn z&r SJcK&q{vOf2T)YC+7-$j->jAmMG}$x12+OU& E}4{f5qqEtf25Oct^K?vhc|VledX86AL3VlY;}(zgxJu zOL%^Q{4=2ctA(5TXAd@$s)d`AhpU-|gr|k0JK4WOn4A5}-r2*|{_k|m&6q6gEgU{o z-9Ejt{12B>G78H7viOSvD;o#rzpXyW{vVp|HkSWQ*8hm@uaUpg`S(CR&Hsh_KeYcV z_rH}twG tf6 z@i1_6n{qRonVVWzaIpUyl#HXByNRQj#a~dL;EXn(IBYx?Y%G>M%nTNsmK+T17VM@B zCd`~%3>+M6>=w+N%*@Oz9RCKP Zv{#VNXsjmOf^}k}^f2I7N>iYkUF4+Hm;IVN0 zJOz1uKF+8+X(E0;3PGC6Nr?kK{(2YneNFq6z&K0mxB&ogXn%b{0J(YCpF${i83hTb zLoj?yRAhR^pgsVA7$74qqV5e`?vrV;-|!%8?@#l&3NYxa292&4E+&IU7Qk!DGG0oT zN^}l?OXL5&g@(j``wdOXn^Zy@7KuGs3@nO^9xwiV@a+bdkD#vHe z@M4>42ZEqGdbmg7aO(Sc-)cvH+iJ&k&c}ODNi=i>DQJlOM~N~qH<8HJ!28|dRTfd| zulB37eYVEUso6NJ&>!Rg#esb1XTq;RN;`3Y?>BreTp-{}{g}^fuD-J;L;;RLPfQ=> zuVWvt1JFmeec|L )&A&RRq-3opAYH zT`SN1Nrq074{^Y+dib?ax&qE3dLJJrz`rl|UiCsUUiH;NwK+=&KE@GE5`7?jlwLa- zKF#YW7JLokoFA(v>irG2Fi#kqtluE9|H?L=RF3#k3>{cW*ec+}IiQ~jv34|gO>@Av z`-(n)Pva}FHT=Cn!b}19Q2JCSbZLul_AvG2L8a&M^g<=>-Q$r{=%nsIy8c4|{;F^w zaaep*sZH?e7N~p4VRPP@y`~=&ak;_t0&8m|*%0;2m(Cz9B(dRlYq(G6YJdeDuyNu| zzuHVb4^p~1SR1k(S=wJv|3-LiasCMUJi_9KztTi{z34AY^y3dbnp?-r0z8bkInz;8 zy!B#+m#+Y=IqydgZeCo~jC{!p`Qv;m7x=XI+5GNr>WQ_6gToCrkC68TWlPpq0U$zZ zgUneiwSIi&&B(}gu_)v0L)bfuemwf#NLcUl<-`8TksuZ8MHm}%#gl*jxdF&4(N?$J zJQ?p8I5G))ZHXrS3e=YsG@M~JYfKcLUSEbht0DFbZ)czWQtp&LPMmX=9IXkr750FE zWv**~Zn%2cVBO#v6*I@ep1wQtUZ$3S)DXHO_UYRa-5_>9B9rh&Q961};V_7oCu%I2 ziIl3Hrf}Y4?kH~hQlMKEk=4O+kGG?N*J1EMY}gM>YI=F}UhSf^ojQK*meq0tH)d{D zL}lRS#IAPZC |eC}ct?o{Y2P-`(Qtb5jZ pf@27Mxr9NicXhm82jXfh!>Lx_M{b;ec;c=?4K1=J=8W}ihj;6>XE!n3&w(JC zmghmEIqxImOvGD(WI W^B}RqJesS_LA?M*4kp6 z-`du8gHn4pBF*QJT2wQBuz2t5JD}t7iR8L{rDENU!P2d0r;Py_pXx^8AB7cf8Zpy@ z{uWIt6M{ZUl?K!sI>1T~kmkXBsD 2xI7Y%}NLOv|@=4|tQ>$-pxDh}@k@YpPYj z^B1)mAWo|mD+cPNm2R~ZQMJBg#wlQj&b)n9z%exlRz8E9E)wkJ4ZEFM2I^Qvu5*lt z-)w6`Mq JnEG%ER&)C{)35oljOCF0xnG5T41M&Ci8c^bvpTHOrHs!;ivN`! zbJ&=SYeYYnM_G>EhzhSw3+_iKqKm-6oT#dUnqr6}c1>w?Zt1t`E35|v2?J1b^WEFo z^A^uomdJ~OzS`PIY-Aof4z1yYHPc2-$+^geJ<(#)+k~t-g*vN4_+o1l7c 2o~S;!F4a%10-Uy17102Xb}D EZih0o8AY$E d?YSQ=_Kg313~B!^ z=#|aq*-fYen>ubZ#gcW^N=mF*G8mV#E)JO<31BL%O;#kh`HE;V2a))kPlV{|@16Yi zBfooX4u{Jl7#=6_H>t@I ToyVYp(%qu*2>W6pk%xPlLx59K1FKe zHAd-Rr^XC@R{pb$ctjgxT&{IKL?pn*7KRb-)U}C>CWm^54LUqoGn z9E()~G}6>%zlG6Axj$cR`;r~$VL 64{Nwph?eQIz1|a z^9xSQO$P1q%F!-7VQYK;U_8Q(l{2d%vGQoE=Rt)bpLRbQE=GsDcqTJ?GAFusXwd8? zIR6JlSaHG-IOYkV?TmD>G+*aYtNIA5&KH~#77+~FupKx*v2Wpmghbr2Ekmt}8v@>t ziFh&xOv7i*y$HjQ!s&G^ce-{;C?-Jh9XDO|ELP2U;YVk6`(mn4@=SCgwx*SDI;1dz zf?$9M6Z=Y#v{P5B1rmwA&LSNXa=SE25yBOPus4DQxsm#fuG_wZ$z-^}SY;j!U`Hs= z{hq~dv|M)CbftpO`fzesxJEkrEOeUNJ?h($zVib9#UFttiv3CLOcHjm?nOp4VBQPj zly^(;m>j6I=z26Q#NS0H-wI!=_+M9yrY h&kOPUKgt&L`uog9(m-R@$FNGz{UYjfRL6nRhy`CM5l?C>0gj*-mfUTpg49sR zku;pGiD&f7p3}RUjU%K~a9d5J)ZvfcV;0@{?qW9^p-Ro`IGE4;F}HaKe;!| h_fI^p%LVRmcp<#bsK=n(;@nhY0|DX!0P-#j<2x}Xzjw!A!(Y{z8J&g;e zgL8a$7f(tEp7+nZ@C~B~I~sHD9mx7In_%1lS8}iNqv6owD7U7yqQTXZnOD5-P~io) zIT5lmWiD#2x{`fB`LM8;siFVlWBOu(5m)(-c>eF)uZ&z_11c{1O_=bK& UNis$l}TLC&vubfo7B(}HTsw6 zXq@pNrsm4t0|?80!Fq*)vRL{Ah55QzlpY38R^}_A>?b&qA;i2Zz5CEX>n`B#yjq?f zo9(We(UAgF2oGIfRY6ctMMzxWn#<~ct8JonRYYMZ YPe+h%6-*C-} zmy>r%uFLB8rr#v6?rB+YcWwI^hW3C}94=7p#YF9$=y&Ax_+r2-thmzvz3wSM%3~y- z=G^ZdDIv(jW&xHQS7V~V71#{<#SX4NLs*z ;;0TP8Q&&fkNa)qk-#9h0>txEOT}q6L>28586Q*(+Zl*~D+!2mH zgGE+;=;EO*S2I6DdtPCEcl+9d2+0ZtAA! 4_WINoC0;**l`)f}wq9yMvSEi!`)a 2T zeBs`;zOBfN DOx!|xl$X)c97TPG>l6J ?G!JTKqxzD< zmbRz`i0@xx2_>(6{1&Qrhc_jLUo-}nWGyy;G8KMo?gPbmJHSpeij$2LA-#JO#}(~8 zkJ8J!@M8odk|JR#Z{reqW@DMNXj}*E${18L!&TE+hZ08&ajp~9WzJYr+P4Vkg_u08 zeOngAaUyS+QMG3|L&bq&L~Jz@o#bYa##v1hM@3#@IkSG3^q_i$ElbnFok47r7hzH7 zh_ZX0zPR&U)R~ga1P4{d{e!+Q1&J>GP-7bCAOv?Oh&a`L%v0u5N#cMwGASmY-TiEg zXY6dfvj{*Y(jnypZFd%o I|RyK-@7frzmB|Vf#FOePv6&{@w1& zm;Sb632oM4o4N58=KmPAlVVl)5jxp_;%A&LX^`Ea$rlk z$Rhpw3cv$$^F+OV@oVz1#9Y3vG~+V77I&p=`RuqeK#mEKi@>M7-@T|~wIkbxFBK-G z0}Z~{ekyy3qMK5^n-aa82gAmWKLDuSK^y-^QY?0h3erX1imqc`!9&Bc$)reHvGJN$ zMry?RLm*5}f3r5SNPvbFBsNHlr8+{qc1xx8SihZ#e8Do5i<)w=Y6uKc8-tJZELE2R zvk)2hwx=)@yjLohM)P}RDDgvcnxt~nAW1s%oGm+PWf~>FZUm#0EBm$vagJkLR%;?p zZBwQ+6tzQ$D6D#}!eCpvL}py#vS#R8!Rc~2^RM{p^k;57D$pjADeE97?_Ak%pUjb( zwdSCE^+Fyg+=XL#r+OYVJXDUE>ZuRv6TD~|a(V3VW#gwYD>!F00w+q@xL3w)*^jbd31rB~#b-wt?~hfigv@Ag LJIOtw>Tl<{Hir)VNc|eB0k|Z62X;#C_5X6PyqbCt_P^}}O zliQ3mt*Tv%BB{nsVgep%ILDpUq~uR!P4_TlsPvA^6Ra^d$3TmHEwY*nf>YBYGUmkE zN_G-HKBEAY#?Lz0ORSREUN{+;APwBvr=(X0_YyKa`G!p!RkCz9%p*q<4`vNX?d#GE zE(exeapp guq)Ym4U~ES2jJ>|^g6sbF19|nQ ze Qg)eEkBhj3r7EH#~c2otKZbxC; zkx_Jan)!o3mI{+%9Tu!gV|xQb^(Y|AE5dm#zpT3v>`b&7Npx8p%q_cdY$ddrgA*{% zElV6u*}=F}evRT87`<%zXS|3Xp@$&HDgzTjeoDJtMs=Q-3y<*iB32ha>C0j}zJ8Et ze{(8;ms+uP>(*x$jd4qa!Z^xR`i~6Sgc--!0r){d*M9hie<&}$^^3B5{ya{Om<;i$ zW`YATZsuUewW|{3q3#cyY(~SNp#oI?FNfFn!kH&gTjNwoujYP9y~IPQJDoI ;HNy0zJ8Jf@Qt24u7}z-njv!PJZZWA?m?w>s4d8>0?u;Pj5QYT?VHy8tj!j`#Pn zfAU0?9AJnDAKBh!F)+u`%D1OG#Y;AzG=MDaJW4VQa`^Kf%Ip8|@8#K-zbu(pk*lvb z-^3R8 DFQ1nnaT+S*~w_;c*=SrScyTw*nB*$at$eC!vNq1SH=OFQFP;tt(^o) zc SvWu%@nL z-Ll`ja(On%&7qZGJXQqQyIpzVaDo0^_QT|@sJJMa1x{D5N_z(cLP9PW)nC>14;#p~ zK8O1C>cqzig#!i)ljv#QsK@#Ye#Q`C+tEuLu|SI}aFVTt$~=F_@!`Z`?QZu{i1Buk z7 >rYh@5NFgI$n02AifJ r<~Pkhhi45l lAM{N|U8;>uE(`h! z&xi0iAz&L2-t84Pt)OtlJ!ktxT|?V`LfhujAE4|R;vP1Kzy%Ct&1WLf!XXYe0B-2) zhb^^}<|Zi6L=Gl}J=@KI4K|Z`o9|i%Su U2D5LK4;+SVS-ap9x$z8rqM g{00BJ=DBa~_D_hr}V;+F7oP^LRMQd_2nTJf|@X<3rhvK`MZ`m^OwRO2&S-7U5?@ zOp+ecuoLd@>Z?is1q$kv4%ZWa?Jm-1O}9tgSjk{IwJX}R1ra#H{0=xvgE-+?2CGD0 zePN`KPo03>hji%|9b5;aw}DbH66Ruu($UJM`Y~tG>xaO1QTvW~D&DyILfJ(!5Nn0r zA>-C^#y1`>#n8^R3{xtPad{n3>Lh34BMfZXP*_XJ#l17_h+ew98$ q>7G76gD7M5Ia^z532~ N299tDtZ}muW8I!ufi#g^R_QW~tRW &loN#v7hQwuwzv9$lve{eNq#qEl|XSD~0E>K_9-pVl`p5V5*6;=cA zBq{;AhOw4Jgo#L7=WP~(D-=G}*j!SD?bx|1*}wqV`uZz(9|ya= -ur1zOeHbFu}NyYX~yN-I%Qx<(qY|&SOQ1t8CZ!$Qp>sV6vk2wvY^OYO@_0Wrrq$ zJ3)euBTXH9QT6Ty8r$MV7C;Qi&OoH#7W*fSS<=e0&0}%<_N>1NnAlGS)e+Tn41shs zCk;V+rEK4Rv{i7kbOGM<2!(kI>jzLe`S5%=%Y6SJyC-*}TE$JVv&lfWG{-Wkpms7* zt1_wua7jreyR-!>wO%Rw_=Hvi<>5iz|HJRd^Dli#aC75)5Rz+X{P3cMs=EuBh}WXy z=AvXtlQPKauw+m#JPZU*-yI(wgvVL1+ci=djiy Wo|jh!f<#L{P?rq?qGVe*OoIizz78i6Lu3a z2^!p%Lm0AnXN1^6ErucbfH)Og7P6Clhq=-1FevA9!n%;MgAZvf%K#d=WL8m7#*xzR zCM79t`{BLi!X#+`&xHT-plyp1VE4>R)zhRLGHKvQ${ov->5u%%M=b5_d_5*6DYX<0 zr)Hz8^0W*{>b0|~a{`79l08-Znn{ii2bpg6%UG1~>7fRXODzFv!BjsVJg6CCu_=?4 zVIvL>#uaR>A9SSn`g`A#`yc+L+`aeSse26=0@AAJ*=ndDQDSD2&geX0Bs0(u5IY#! zwf4o3d8Ql>2bp#|i*p6(QbEGBBo1X*Ry|XwWdEKq5UVy$gyXl~8ETYlRLx;ZpuApN z!IjN{(?o%8dk 0y_J) z# RAV)3&eoCn=a*0@3~q1MnVLySSQH41a=4wR#|k!d z2sm!tNO?xK?TiiLMryhIa4p$--;~WwHwe=ptOQrQ0IYcyX`=Ix2VzPhxI||v*JJ%x z5F#vxECTU#v1Hea!nmE^(~d>y1wf1(J0qviZzb1yAQGn*Svj&Q9#2%EgV8MQ?5gEu zKY3q1_>(`DC+~e~Rd&Z}WSP?E=KP!bt9WK9!g{x?H*U-&YGj8fgh3P+d&vjkDNVS) zy Qc*dP7mpc0cw z* 4d-Ei wctD$&qbz`jh0e23d9;a22zUp*im;OGM{hMjX(I;|4I(;f6x?!OHkC_E(fUB zsr$S T3En&`JW`ei}DS@d9(xeAac0KHMj_qBU5^0sA7`s^SZW@oFOn* zy#eO5sV}voe}o~6$ziLCZh~OEqN&Ocjk0|i#G?eW0n#($B3l57^@ZZd-#RXupvo1# zW88~re$Tef4lH7tI =2EcpI{4<1Ra6?1Ub4)1AjOn&K{P|zXhyU*T z%{`34t^ BBQjuG+PS68v~ivscj7jwH>sMj|`k$Cr3L*|8rwCCxhNaBw-~yKyYo#ew|3D z$CSn4NIwg~;O~l!qOAAa4*03|b8kQ~r5fxL$*I`XB~^ZAWc &bv3uJLxEl^h2aBJ^Gdi|HpJrs7mu{B|KFWPfx^|~T$ zx65nW!ed0Bjoye!@hE$`ejM09p*^#mzLe3V`!xT>U&@dF=|7X>-+rK+3!KAS0g<>i zeZ)>uGS;idILIo~FinmHvF}IboYm{6(0R5_<#2!RJM798=Z!im+PAb5wNCZL*i+H8 zRO%xPQ)`IV6f;_@xu%DMy#EJ(AbfaO*++BFG?0l5XS_~gxrYFliG;6#l72wKu(hCH z3;-0j9$=m6 QB^(Gdi|d+B8On)RG7pXNEj84!o89E7A7*rKp2cd zew(&yz!BSGK?J}BiEu~D)RE@e>8_zRyMYa1??GHg!A&BR*MImO`K$lyU&wqsERnsK zluwqXL-xHysUwrRQ}3C=)Dc8-eWa9ikkBEw#}wz3PfP_5$I{SifXxmN?#B-3GU5yz zV9hMhf%So6&!CP46nXt`|5#rC;D={tG&N+81vc?>Ml(M$G&BupL(6mu6iXE*m0F;T zgi(X0j$N8q#OQfhCHk}I=)=LVA?Ey(u34uL1B3uY71Nr!5^}3oV-P*ENvj)-4PAkT zfk_1M`etF|VP<+UoK_Ooso8oebkdQOq~OnA4J${*=5zcDDXne~<8xwgMC93zmRr*$ z0I?i_TCRv#DlI9{@^kSym~@M(C&Ne+T)@E60TB0DE(L>_1?g#7HS8J(@l`*^Afc$X z^s)ufIbaaDFkxMqtWBut!j+k 14h>X;C #^bSsK`$0VKDGC%Fy$8=U{#ON_D5=0XCus9y6 z*I~p~i4NATW4wFJUyS^!(lZ-e>`#oyEb_r?`Ky2OkLB*;ACqVAeOf{}KjcnCNq1b6 zDKQ2-)P^$0&L(ZEjoWs?H=SB)L$tb3 qy#5W-=`)VU^Ks8wYHTW*mW4kH=UKo8I$YM* z+_GP6QfZg-u#vA>x$~-V4Htyq{F#mOdYFV=N2&!JP_p0^#FRkk1I3C9_Ms7%CRpXo zt_D_7UtPcbKW ~6hQ*(c$oULKc2?PcQmnNj8+ z{z!iOfBaL~|F{30?4Cc@>A}b$H3LRZ4}nHkDQPhdq#0rm7mlv&GB{=21O(|RjS}bM zQRc%@b~k%>07_jmg3be?16mD`U>xbNh}?Q&^08JgoWN*og-@3I_`@H|hu{Cc+ A x=C;7(7XgP z)6Fv09k~DG$K)fw`;TPW-<(-C-&x5FT+%NzG8vIh#uN=(hvgYRXTi<;bcEc#*QXaw z|IBC5*8s5#2qaGca-N09S$I4OA0FiR!Ta+5|NR}2zy7e1&~A0C=#oebAeU7xN5GEM zc7Y}T&Oii(1t{W%z11VU44hLyiwRei&pM?HY)EroJOI_YW<~cPta`Fn4bTIT6C~Er z=7nSdwjF-i$W^#~b9qaU!aE;>q`_&0m?$M|@)^sjHNbQeA^I3YP`N>lonxO~47_OX z=YD^8uWZxdd;gF8;D7xa*}wZUf}0z`&F$&m{f$hw=kITBWZLad>ejnSFzp2UlUOJA zdy(D#RGdET1k-eS4JN_v{4+!qud9EJb7A0RU5Dm*fzggl$j~*cmPkYIV^#3RZYR@j z(ori45z??T6lGF}g>yu38BvOaQV$ymz3M`FvvjtA2oDGO+kgEB^46DsL8jX~O+ybb zS#j110n=GW%#i- sRV87Mhof-jDZM=$a&^EDjNq&2;ka%6%XTwUZ5;1( zdUu@ P_h)Bx z23hmNz03~>!QGtzyFhZZPVU&jU|zF7?zLp+DdqqTxqN9bdTLVuftWyTHUGQ}ksXsT zva{GTcKtnZ5waW>U$duS~U@RPnjsa~X#bW&y$u*g~Q bZssLl>m8*}RX6W|Q8rgL#L zPrz%pKmG3JMzFgP-0Vg6cPD^$dn>rTTfm%5)9L5kB-8#zWVaLSZ%%bq6Hedn_JaLR zWZEr2Z~5%~egSnSEv{2~XS#sAro$1Ywqib~3Qx`yic#@tMhSD<=n}|HV}#1&WmCfG zMjFKNW!4E6sRJX8uG_`=`n%tg*FXGAdHS=TRsdiDHEkY05?Lyu*lZz>R@OvDE*k-b zVZJvwpLsqpo41pUx`6I$7(`iEK~|xkTeV`eba9YMh?r$60aXU;cYb|;PQzV-cr;Ga z3j2+zdxy`3J`Iy~fdGT^7z3xq>}_aSFS9eybn7+I{zb!%Gf#|`@>ls}hpfQ`j_;1k z0IUL1B_1hZp?oFjyVd=eqWBAdX#)o%#0fL~He!^!U~YKOSq#wqC^aMi$#lwzpFoub zyWz9HZ1 lWki*nUFa+Rk!U@>z_9FZJiItmnA~$z}o4rgo zcc+ Cm*KUdZpsEIg{s zou (gEO54{pSoM5IN$SktXGAvpG*+TM ze}DgQs=>RwqM19#t`lt5yJVxWA<-x)W^K^65rqj;%+_&6sg)HJvXNg`(>DmePfTz` z@{}q(99;NdYabDWHb|sekN~Bc8?}nt_B#egg=T@T+)<3?GA)=H9UCXkMj>5aIV~Gy zgi_)J5gbKelPFo)Y9O5`8T6wiowlaUFz|giR8NwbeT pBYE; -C_X`;OJFu@=@w|ciA#CIzHa$Uird42_a>SqlX2wq>aUTo*!lO1 z5s%&%v0!cSHO8tkERe|-%PCTyMdo9jg1-3U3C78vAA)IHRr+ku&Q%P9f_A_tgW<&N zCP`FreH$M-wwY+ob^k?$pfBw(p?h~In0nJPLb+@KyFTa=F?$mLoet$_HPfMCt z8lbw2R1z&N$^=Nbn!N=ix9!D2mzLGm!XS8ooEjjGN13MmdMCLJSfO!%6&G2d?YY zJU3ho?qulPmgRMvPwY&qZHCj{xHu@a^ c$6hI-J<4%;-%rIP}94`ydVuzIHgb6w{ zFx)E%Utfi!oC2l$W3XDI>#RF)U5O8EPvh9=pcSN>1dqca6^Jh=wn$Yr(@n@mzo25- zFMcg}a|_avnSW~C8X{zQ4vMI0!wjw*E89+f3T19CZ(fWvg+@}l)zX{Ig+{XNJ#f`C znXIQ?2fln?B6gri9!r>y?zdl3*KXNX{U!oMR{5WM#4FQ}V`SkLCYMaO9d =w9 z;KeA4GaSg82{y2?1ZaR9CZBo|;dwmK {YO3~Z+-bI>v*InzC{t- zq*Ka0fS(V?(`Un`SI08_REEZvEbD0kh(S=3Mmz;JqeOTx)jf&eUAOFU7C9cx{lhvs z1s*agPy(Ou@*SyB8VSLvGw@l6DH7}O+pa?Bb6J9yOD*Kmfu&O=DVuXVYAqr0X;-U2 z6*jTJ1BSAmN2KJ)=wMvMxKuUQhS@~Rc0_)sBYdXvuo^KVOlf9kthmx4LZ}tmHOgN# z5DGG&RW_~#u4T<6voee3zJPhEE~7UCUxepRWP0aLj(_%N=lk6 ^>BEQJ??bePhPn|X_{qB z6u7ig>vM>e-(}3INSxyECF^GO9Vzp}A>THPjbgdefZ_cYiT|?Ml_8N5w8;aEYpR+f zUDAgqrxCDR!Qp|kW*74-W(%?ku`C!a<`U_vtZSpRen}C=;s>oOL_&JdKRbAK%k4s< zOfj>!2$p|sN@-VEOkX$F^SRN^MB`r&FnQIO4kjk6O29&@6dwlnF2~-&l(Q4r?d0X} z{)WuQ_vLT?!yhF3Qrvu1gyW8MkLZXueJt799?;p00FYtAahq=6yN>}+RCm>(CL0m6 z#$s=}KM3+R7+HsotYN2qXIm<#22CRl6mBN@RU2&R`~w)m%Q@t&AmPAYY9~(BS%p=c z&)g^1*ww~4ge}eSsW8?ZEiF6P#?$lt{Ygrs0IC#me^0g60 >?gs$?lcnfe;l z5!<8&^?qQ4+?-XXK=^Px3zO=-xb({Hk0QsPoF`_q>Hd}HBJ?nzC6qx#5m9)VP(Yn~ zV;Uj`O-)Ps1!n6rNZ#q@14Oa3dS?L6RH==r&y>Az{u!fZFYY{gvQm9EuIk|IAT-9o zT3!1+;6K7XCf1S*m8l7eQE$KSDS7MbzaW3}2fv?Jve7cXwW2 KC zlfg`CDa=f?O13ax`__Rl*({r{h)hsZe)Xuvi+5W?i@Un1CacF7NoN>tyi@89J>yt6 zF>VYYLezQ1W)_`w;OlK_OhHo|tw*-NrsCH-lTJ2)%PiaFap^{@bZvYG@cNlN+{^s% zZ~_4rrE%ou(+SRI03;FDosWl;+W)}#qTUMA!uiy`CSYQ&BXO-NB2~8-LcKYY4m!@~ z!QVls>z 0y(W#bsIQFiv&Xe>pE~HA~Lls6~xYBy8 l>v(uSknr%@bYIPkWvw20OA?8_RNrDG*Nbf&w;rx9QJ3Zy+Wqowk_0)rLt2;W53G zXtCO+)CdO;qZ2d6kitb#dp;a=_uoe7;|4b;VyVZ&F?3$N#p#A!>kH8X$rA^49TRSq z%)RnAO=ExbIrGCIn8}-rEWeE2ux 2l+1-h8N`^;|!-94aq85G7YYl~jEF1^tnTgT$M!klp z*-Ca;i-rSq=EZ+@U!o-|QG$%>k_N(3iAjmdI=LxJf!<^Gr#3c1)7k9jzy3{m_L-j* z;v}N0rYERpkA9*k^G{4bW-|C3QcqxEhnTDW#sILk8J283 PwgyYpGqU8`Y?6}U45&5fI}L9-hU z%tu+L{n4l9dS;$egrZn)U9wVxEp?CWXEp<3b?*;+FG8bE!k(BA#CJ5BAaDU)jou!i z*Sj0z3k^*u6dsOosuB>{O)@=u(rx$}4?xSQx&33H8WqC@!i}6?3-hv}^pIFESwtf3 z?JjHr`s( =u@#9@Q{aTJ{BY}GCT?SOFat}thlw>p|e+qTnAxOgoU|j^@FuuhZtt8mGiDDRI zILTRsg#SN)A{mZvwiz`V5kV?834-PUAu**D`k>JD5kaB%)nxjkk-Fs-&DbJKiE^OE z(lcLBrA&x@Tu7Fo6Ok@o$D@!Z25UYZg9AeEPS_6)#^kohQ?Vy!Rrh&roW7R3kd8Bw zuwc}5LMJoYx--+llzDLd0Rx9rAL;bneE)EUdYX+T)@Ys>h~S|au63>{*5dbeSa%4} zn(KmuU93vUrhQ$@e6@(Y0aq>K%n&=aLB?6C;qVaHuk+fvy^-nZ6US}Gs~Q6~39=8_&U1yJYkN50un{p69)GR0fQ8pN9f=$gNs8Wffihik~zyqob^8g zmJ+M=R3$A+w)G!3J9+zee^YMWe!GciXH`>cdDP{4Tp-bqvPS>A)BiIFUF4kT6_BVy*$8GcTRq7*n(cij;v|R}NEK$Hxtv;I*d>jKIfDAT2c>Xpg<7 z_OvnuWlU-hW&{V4$d+pZ;c{!yA%WRoU !=D13@F;Z}5e_c~Ft3bJQ zZ=Hbae1BhtMAlHFh~8XUp*g|h!{JOb(?~1yS*%dcD5x2$QikbTi<&-!mSS{{vaJ`& zWL)Q051yz-hY@U 8q9IU@u6_WkzU% e39 z5ho=PG3%8%V8llHPLNu^AT^Y}3-akN{=B^S`JYn_Jg0QFDCRLLX(u&HDH0TlQ>;Q& z41TD;cS)RJNDO=&vyn9EoW}@JymhOdk3BsyVre!vt^-Dqaj2^9-vD@xrbWl|_3=9Z zUE8*zccy@^QtpOX$g#dkQ%@BXL^&$DfHjs?soIs@^J=(Vz<>zk6ma#3jXwVA=XqZ4 z=X`%Eb_cbnsAcBbbdx1Um=Q0Rv>qVyu^ov*lPK9v1z&`Eff({3R3G24^Q|`u%IJCn zYER(Rr}13iggn% Pe0H@GT$6E_kykB*Y_?k`6sT3!J3^X@ktJ#czOxLv4kU!*WeU_6|MI zza_3OwJ1cUkG_z1e(Tpx QJDHUAKW2)Rn~$i8Vmon&4tT|zF`}H?VZd(S zba4&~JJGN$>$nqd^vOJ{BMDg(ZVC}I9w>Ru(B`NrH&$tc`FND${k;ZlC`9}M^9Yx2 z@=kg_&N3g5=b~kV>{RVmbfLc1wi1^vryFSM8K!F@EejI#ZP5psU%eJD&0u&zCG;98 z>FXlbtiXMVsH0+d+l Hp?e_gR=Fc=4nk%%s#s zuO?{B@a2p+{I M#vL|v&{GXm`gFpE#9!;tDE8L;p}fp|tX6>MBq?pYVXM|nZY zP#=xeNP~z>keA>7HM#rPZcB!gCGQgFBvMu}q-R-U}E|We1`wt_515Ag#4xNE(*H z^; ~RF-AOxs5slUY&R@U(%y_B%C@r_VLI3qfzh%-5zfYAJOk>rcm8L7eV^|Ngl%jc zPB`WWkB7sM1B;*NWuyw@`DEevPmVdJ5eXC&yaOpwLj><1%s$pkjqNN_QyW5v*{-Fw za}`NXqr|| d z0$%QvPe0s!<+JkE*T14?r(R6v;XbtsC@dH&K*>nFTBr6FSI>N?xvkT;Nvvxsh=51H z1{}v+cvOHDqy$#EeAaisr57Tfh)1~@kN>4fZYCRa8DiWlu4=*LWvvKV5<4yyEw$Z< zDgv?P#WMGg3DBc@%wcg~)u0zF6=cz(^m6UKAd@py>B4+Gp62Ft7DTMw6?oHxK$s85 z04*YYimICiZBcJDyXK->#?Gp!LpCd_>W(sAJ|^>ruT~*VSEObcBE*cgW0-;vLFXGZ zU=&-mj08JFbs*;F=Fb&o(7U~02B}< Xw$z6w?@}0$zZ#|KB zzWtlBfBIC{zh3a#aSlPY8YMMYc~I3yRSG;P!rQH-;hR`2$%z7vs-$$56Y;1FmaB%= zX_jk}ppSul{w^REyy1_B6Bn0G4J6mrX}i_>;-~FMgSInJrwCC;Kd_b*P3I$*;%;d- z7xk#h)>gB#87{|gHB!aRQr$(zgRt%Dn`b%R--{El?5@3Sz {l zIWu0Fo^QBQ8P?`yHMJ^Yef6plV=ap4I)w~WU}!CbKglj2u0>nA4h<4Qg!US8E0W$Q zQ-2VfGL%rs+yYpNEIMH(Hov_Q+};e>w~9?gv8nnJ0P(njt%j3Dl~_)*Q2LVy*xHqX zoQvYQs2D!8!E48FmMSzi3KgS#dY+ZgsQ#H9UVOkVMe|eL02auL-}+^F^4_O>NP020 zjo58#OVKcDQKA|n+TZ9eCl;_40ddF96s ovWt>B%E$8IQ_omQ8gW)Uv6d!c-Sh(pMM!~#qgXRc|BMaRtn zpOVUmyrGc+SjxFfUK_^B8$}2;PN)Tf^GOHGT>&6?_9W;ajPyyETvXt((5}gj8k8GP zwT<1<{m-$zK{PD9VyoT2?zlk$g S;A1537){grhv>u#-2x-hcKJ z^75CyDVTPl(IqK79>SaeC0Fq8b@D~PD)N0%XQ-cQan)UsH@T%48c#5OBKt?9aN7P# z1`Z>d4;bah{&T@r3F+I8Pl(1LUWO@4HuoACoba(@JIBl#2bg=i3j9Hn4MeyhFy{B& z@YD!cE_G-@m@+oSNK4i!C6C2n9GAh!%V!^t^1*-lPxA0rKMKdD$fYGbnzw>WWC{Ui z5lqeVyM!mF2lnuzzZSlpll876%=R4N(o`cJ54||PU_PSo(E!fH@?FAVBNcc!o+L4> zjNs*MZcn$W=1j-`w4-ZOEe3S`MKg{$ugi1;k!4l)Uu+ZtPKIh8p&pQqgh4&Cx`6O_ znkL{lXTo$4BBo|S3DRP83HwPHs>y@QC(Bh!hkcRJ@;NlJTd>S?2o_r4NnK_MP2eqq z$pgQ$Fybcoy9A3Er4-!sB8K-f8~4t^-Hhb9#b_!~*#ZPl_VUi}{HENzd`r* ze9AG4f*)V#I= z`YhDjF|2LtQ*TaCZk`p>bh)3$hlBj!fBWBM{^4J504jDpuk~rN0OU)$ZzsTBAUny5 z%v-QvM~JLOYD?9Bl`b4%w2I-SVLR)(>gM}<;XF6kgAz}_^uQ791&4a9lWx#}8i+%C zk0XU^1PmZ>#!h &(IS nC9S3$3qNALr0K#vbrtpN%35 zlOHntebAKo#OOVb+ePSBaxX8IymxcOS)AT^EJCao>C_^39#BNLfeSN(a1b%es?%1e zv^A{IX^M+}5lxY%YQ$TG7j0dFpIZgh07~&9apfkw<_Truu$V%Bd-LLjJp20BgtG{b z6jA@p>-Y2dzhm?7k*CtCnd^J!v$EzaB1fEmHo9VFV6&ZPEbVhfHI$+y?YEA}>5WQh zdYoET&QIEF{+mw>*3#Y$qi=?qQOVTU1Gy12b5PoD#Pkki1@{>vVMIl>kg1nvKv0(j z1E_gCp4N!H{S#z*dMB8s^S&CbM~$0V+%*rc0c)t@S|=1sh}r!fJ_|N=KpIDBVJle- zi%&_>b(O)vo47BN9Jom3!P#}r2wsmu$hgQJCz#>nZ2J1z(UcoVWHu0 z^%_R(&h^aOK=j8nu58my9^^5Lp2DzD4~B*KVd-lvN*h7hD4nXOamhlMO$*bpsUpkE z=QmxCYu!~O7Rpr9B$%3W b zS}P}7x*pGJl*Qt#5{}zZQM%LALi2niR(o$4&2>+nui-pRz}@cMPVnT3$h12#W2G19 zh1oH~7y})23?nufP&M1Tn%s;$YXj9Knk+ffgsY3H8L)CNdkTgXx|($J(hlbFs1#+m z!~78ujP+KK5F0qk_CD?>dHFlPDYqZ}=xME!0h77fCm!y7;AiyOmBi2pyOZ?3sC&|3 z%StHFtMQUiO~sCz8H6V(=`V{6S)Csq?{YAB7lF86#BPlh;k?0#y~$S;J+2e#*CECT zZgy<+*>>L*Getu|dos+;qXBuEiC9^y<@c<*YgX{(YP(>f2exEE(r%5I#k!7|3=9>T z?xcAZX{N)sk>}mVKQ6bQ`+McYH!46 &&i9gen~JvH9)zE zAs1hAJccBK+HD*9&?r82SPoE-j$($924Z##izSKFKPT71j*r?hpavonYa)4k`vF0_ z`9@~ydhh#Fg;%X=IwhJuFRr*UeV9%9qpgk7ix7^(@W~hb8#v_^xPoF;Gmx}tP%&1} zh3}|`tX8PsfvZOW$juYDjLM1b`Tj;;eB e7z*K1e?DgR zA&`$tX}S&JXq)vl5n06J9MoWm;OU)UzdPe72GK_39#9#ie&~H|3O;*Fl*P`J+9Bin zER*YkNeNLmh0rl~z81<#)%5JrP*4xgM5{t~wv09Vj-Ble8wA59XGfU@Z$CY0Ufn(M z&*8#CwOI^`$l)Pol92bVxBN(o6KEQ)w@m**3!YIvvoRHZam`O7aHE$N9N~%6S%j4F z3n)J>qB;xIzkSue(TQ$2Jmb80A-0)jMi4`Uww5Ux`JhtQXq`IMOhP+Nie$?Awdu4~ zA4_lciy@1eKBB0k4eHYxQ9L#Qd72FGj8v1*fBMoV*RkRtbSxvx_>F z)5vGo5fjpa8D-49;2<1ur7Im#_q-h;0FCgFrtzpsc{x)HxFQi#9qeEL>`-OYp>JrB zMb9m?jU &t66+8Fn2vv_+ftveHm!*nP)#T*IDcEU~pZ(59zm&WxIg3E70nECXsJgK3ht zzWr i+3skJZzNO~cHeZ9xb?1g#0F_1ak{8H ziqIEks;$RPNO3hJ*$E{j)GV3Kd_rxT--Nr0qd#*Z`?ubbXJ7w{o0nHRE`Kj!Qr)Va zi|n_z(9=?@P8fYEuUBY0BxgiL1=!_AbzT;vw`?axcsvh$PQZ!T)39l~RzwtoT~=-` zWUiF2>I9>7p&8~40}|Ez!*)+O0eG0$UWA8(_QU7zrx#DeRRo2Brb$7kEEfArOAoj8 z=1IruFJ1g6(wB`2NMXHH8_T4I4KuJI3>-b1*`#J#6H;Puu*D2D_EMU{qSr#$iCx(@ zV8}n+eDTxr@>^dQU|K%RcAHzM#+i$fJL>d}OQG3`Qc?EC%IH*U0mc15G9^ff5j5L| z1*Rb5XW@bFK*#L>RKd9-AdOr{n4JW*_`6jJi*^Cj;}=|U!*#0Ysht*XhVx!nAZ%0v z7tv|MKt9jS2&A-HPFTKox;G}IXnC%+4PLrT3=Q2KYofr{YHh&6eSrZKfNEVwq!%!R zK%Rg3%O}CdmQLs@4hK%pFtcqJsJ660(Rq0OvA1G!L)@IRmK8G$UX(VC6rI?BJ%$dQ z3sI=&JnDVg)+RaO$*g!c1W#FrXqhW9!=)oqGDu%G;0e}tLHv+u*F|W~LFC+BNfj{* zAoBE1WQvOMeFvASj| cto7p=+ zi!7PEc1f5y;I4emmsD_QSiEwp&+p`&-~9)&fAPHbrLNO&URZyXu@I9|E8@kfx51`m z+cM8|Mktf5ny^kbvrc;3I!c6-v9f&6cej2pdg=5i*)_LP5{?))vA%^byV5vZ$%;S? zMHU|gi|-y(2DB m()OWz# zSluBR&w--~E$GtGEZLHiRKxuGK9$~A3}5pan4%jELFO)7O0epn<-K$PR+LCnt6R2(;~T*xPSqYDC|Zyg_z&I(8+^g1!OxLON-A z3wUEQ(n+(u7rm b zT^BruXi`^*{Kn79? V&6Zv~2CL z9@vc#5V=uE@!3ff!oVGY2FU4jVw4X#e)uY8pBn4J;=!*YmOQJ|Dz#sjLRg!DfzY%a zC1-&hg5z0LeRKdw8-8B^)%}CGrhwZUneOhI;`~Xg-J9_~I<-%4vE9Wb;43vu2CqeF zz&Fqjx~37%8#pusGXjQG)cB+&D78MNDOp&v4x`{{yhumMjj*uQl(<&Qbd*y#lv&xm z_YryLSASWi{az7j5Pw2z2}dKjved2GU|I)PVM#?h4$ZPffmyJA&XQ!XV3=9)Il}D= z c*5ZC^=4i-Zd>1^x&xuvBH9-B4zi63 z`4G%0pq&6l2El2RiqSkrtJ#HALZXQXFYWL2$*t~?iAMoaJ@F9Zh*bSoQ J#pRb;EiMdJw1APY zQ2D@jE3t4<%^$AQ3Jc?Hm#qcM4f7T3JxHL#l}!6xI*ebvHXP+Fcy=ea-3N0H;m9Xx zp1vzG%GeF73Y@Y}MP3ZsZ7zkmt>*?8!Er-EYWWb$z|y1)RNX9kr#J|#A|+`RkWdrn z4K)+i8D+8;rp$mg@VVK^JOAZx%k8^wyKzQLQYK1xlvE8F%F1!w11mAW^ls5GQdLu| zjbFC=>==5E2o{V$4-BT2ZJdpu_MD_le1jYtM*o6>z4|G9Az(4aK%>pwVoi &wbuz>bS(OyU~ZpfJ_VXNR$JEqr9#EvPGiT`^$`K7OiS9dXPEf6a3<9iH*% z6pGxu^R_(u`d8iHW`y7kTAxWhH^$8z*ce14s}Tt_()*uH>cor0psZSs?>0h9v<46q zk@?kY!?+aoAen03^XXBcye*gqA`m4(SgW 2!=4>acFORzDE+^SLJY&Q&A=Fc8eEUPsXwwnx?DwbCOi zJHPEVu(MSe*hK0vQrToURiZ$*WL*h!voxOk(wF7Mm%iwVVd+o@V{PxtXfgAgX>lR* zq)CbCi+mwX9VrmYYlP&c*wJ3q9N(7U#Tfjc?`2@5*_OB>drPNleI>$&8Qt*>!+oyz zM{ZC8H`ohRdDYO!cJ7s9p%ImcG(&0zubGLq3~XnU!SD;jBE!L{u*JsET~F%!Jowk? zD2k63uVFdg1f>NL{fX|TNq S#) zU5F&_00aWcr11Ws(GffU`Nfk)ui+$4+iE*tl)&W`ud&Qc)EVgW)1wPCU}0;vi=jt~ zVgQ^$EC$(M%fj2B1iC+gTT?H+eazxv@G`ct8JR^TaEdhBV?O;HEKeVOOFr@sf9sTb zb{;HV07&Q@``JS!c+5)?Qd3RIC5-4hJrVdM2E!|| $rDdXK3?&U1Xrq`^W 1X56?iXkYhMsJBJ@_Fq<&zE<_(|Wa-El zB#8#p@Q$gS;^5BXyn%WD&~zVCI88D=dwLS3Rci6UJx1hFi+$58@a@z_AW7l4bL-9? zkyLP5{T Ar*VtvpzwB1%T5V)NtQ2fCSt?2rwJM+6Md=;MW+{#io+}we}HQ z4!@h^?cez=x%>Ffgh03b3@0Je{*C9EtI;#YxMk+RvV$>3YzINN;L&sgM*cF^4b- ?SyvT)tNON|2B`Dvc5s@nO}dW$Qb)%X#x;ZrWG!R(x7WPqoe zTY2$|-w^C}ZnTOkyoRQiou1Xu(AbfiWO@J_F~zkoU3dKet;P*QV!}n5xG mm%;K|07>jJ{WgL oM^UOi9f@RfL5wp1NJFeOfLL_2 z!nvuM>0-kA00HnXmnOPG%n{qB8DKpMNKchJo$uXOJ})o7`BlLLiJDwS!`0K=%vo=9 z%P2`*? n0SXUD+cU6517yxhG+|Ra(++|z zkyZvM&F7Ly*yb#*ANRxid*OUEA)T(RYMon~p0EO)5X9-dp-4o+aMTlN&>lhJG=j^I zs{;D~7_|Cw$D_#MxIQUNB6l}}CwC_2A?fIyc=lN!p+Qf2r4ew}B#Vw=#g&GYNy4gE z44)X~2xL)wW;2Uzn2ZC{r5rLq19k*eIG|&92Kp$3sH3Kviv^h8dLr-s&Tq@^*;8}v z%wxGMy?YrgW(eXD7v;tY5BM|+ORL@1IfeC434qz6{$U$g9<6GLo+Q0|-ZT=ZWL;<8 zQf<( s$&RZ{B`eo_*tMZbt*1=#8 m19htpu=%kL8bPX)Z7MQyDTf}ZKDRo@*` zg<>9+si8ym8dEH98B0LSF{F_Jftw4(`FH|ZO%iu{_Ed1QcRVv99mh ^vwEF%pcT4Q>csFBk4*r1VQOlGtMrDAdR{XZXuKn0JMpK zY~)(TUPVu>2R{JWp8o0#t+v-SjQ|#I%t_m;Lb8&(jWM0q_gXziD|#d-j>{=*ge1$7 zjldNhHjIGfN*~jvqe$fxE;;)(E!h~8(10+s kNHwa&J#!J^ z;VARNAruj MCTZTtc<~eVxQ!AJQe<*d)q`rrnjC8 zrrmn2)3gRI)+sPS9Ec)r)FVg`Y#UpQSB=a;XFGBO7OB#e0k}joY!gLVsG5+~wAyQB zoe_Ul6|Rq^Awof!&Hx9?OkMtW^Vv_yJHPrXg57S&Zo+j_ny-r}^GIbwQ#0ja8+uF+ zNy__7?G?<3o8f`XVdF_JuMt14E>T`A0e79Is)RIMgl~q?nI>FWm~xCbql85s>RymQ zCrTZIJtEB%-BD{}*mluDqK?(*2CUwU)Qa6`4J=o7aV<4LI!7rJ{>%l{%4*PIAlX%u z?{0~zUq! Qu3x1l#&wzzW zH+dssqYMWFndQUrJQgNkuQ8BsC~@{Gjlu>{Q}S_mXxC#gEZWZNOg3N4s2Fxk|9k?S zGMn0r=TFX^a|r6ER*eP*#d2-AR;#ho$s)Saf!r{%TS&fni}qT}q5}9R_+z9O5FZax zOM&^Hw**8H6wZD``ffiKhy9P_s_})VxAN{k`iFA!_FHP{v_T{zMn4Vi8kvR!0H{G2 zNzmqI($i0os<5kyhYLUx6{C}VAy5WvXX@LHBEYhTJJtKj+yxrVQ*R>LINxvuG~ go1QUVQ7Dr!a#Iz(`yCo?m|pg7qF^X`Hs;j@D?E(@iJ^ zbx?nHG|Ni?!OOSDS$KG;yEihh1NdrH#KBLiAgx76jesN|D40JFw8ZObsVM;PR@at> zK@S4w;n1XAPND1c;<;d&&gVG=%`59qFm#S}$km9(@JYi1Ds8LK-) )@gu z9wc3-@GMk|i&K-=ltM57OqCETgT}|Qln{x$oy6>68XD8v;SmL@fl)cw9L#h-HT34& zgWU`eMl+{rj5Y%{UXps>mD=p2KnA) a(Bw!dmQ}g#M_`GYE|kUN?s}QCZa4J`<598CCB=+Z30eZZ|}y z4ad~X%b7Ai+y_zbhMA)91GM!pOIfL#=>7(xZE)jng4=C|Lo;HnR0nD<&v0R+C=@vy z^!nRPf+tUx8H6VdtaS`b*IZK1RZ;s8xs7teh@EO$^A>i%Q90LeBh!@`W{J}hNOK;x zSbBUgvbUuJ@qD)cp54#2cb@5c{8jBf{*Ju+TfZT@+glHqn)#%)?F{A&&PL-7W0DIg zQNox-r7@F~+`c(Bi@|c17~qNDx{i% VcZJDVc*XXX*hO+ZtXw&Hm7z(T8@e zPml7!Xf$p(>bnsb=F*ojEehY_bKL!JQZJDML%K=D$oVIA2UjZ2kB=rpaBh&g#i=q? zG)}dl#L3RXh1ztGld}8Mul<5n*)~_OKG#^31xcJ6uE^e{y5Zl3OfczcrEAHY2G<6G zA+yC^(*07GH}gDqZ ?!fqIr7ZG#ztxUR{*ThJ9xBjoV~* z2Fyzhddzl1DUjp-B~zYUDrHzKn{Sf0zV=m-r+11S9J=16mVjxzI7GX;zcZAh3d^yK zFwi3T1a#6IdGxIHuL1+f6N8o2O`r{IOxK-G%_Tr$M3gkBv+|{p$SuDCAbOxJ{Omw! z^|EZU1%wX=1@NaA&jmL(r}s@$IM{mVdMid{py4*`$$$ 42p20m4t%X@JhtZ+%H#e)UVMPocG_45z730*MA=Ku+oG zb+lL|XQ!GKCFvSuUWl$L0)l7OHX*3(3ZEdzN+jEo0mqtAE3-dlRz||Wb^ZLQ_5+Db zLS%fiO0>#}Y )Kw{HJxW+MBUwE}7}rX30%|*{M+% zc*H8!x?V6&QMgdJ$Q7wP#QHT;=7)!~Q`W71EL@2X@SquHo8oKKlwp+s03ZNKL_t*Q zg`!!6cG0%S@IJl}CN*8IfH_~4vP1|dc{u3bo$Ie6jW62@Z(^#rE)p@gkLvI2$d9l< zo&noUarG1|>U4scG~qHr)@7L1cj*2sN`JsT6YkiKbF{T?P8Y5Vc+t(9Kr!u=W`-W< z-nb%}-hCnO{ulp1c2Ay4o>nYU@}Yj%3LtqrIC3GZkSXT;If xMF6qHl zR_7&2h8%$(kI0h<%7g?+upA;tGl|sNbbW?tLtZJOuD9ZjVtL!quTI|vt15Qdk<~I2 z1FRO11F|<0>}rZ=88M5dcQ(+@8BXIFy{-&+UH4=%esrX-yR&1VJ5ixVOz0kBWugrR zobK-A#kam8vYR?rfestRjt>cnWGnP$Q$c|aD2?&5>d=j1RtlP!20wK5fXnai?+p-u zsFW?%^uyXo9Hb5-2WU93aAzQ-%$$|XSR<>5PNU3jQ-aQ|L8Avg9F!;6y?lPs2ZJb} zrS8RG$U uD!}ZBxylr@fPCLPb*M+VY83~`uenjpeT}; zajXs01dKN;P_b Yg8 z5~TJJ6tW|m@yE13Cd4qV_P?2F7-fkO`azvl#sJ*8FlUqHb++Py(axO|XI;sYbk8Ny z2U0zm!9sx Y*-n~A47_CMNrq-{;OSAU zND6=&`ZI_`+tjad5^&&3yYgpW_<~FydAYt$%?v9Z9{Smma@8~7^pPlznto_KPJ>E> zHdmos55!J-APi^EKOaAQ-AD`|P$<;b2@D7>0Uj?UWqJ_H3e^hmD+3m=TBWDSqA>mX z`PHi?Y=z+26P>EXDOG6u!5KKJ2s<*H&?NC#k<`2-k#ST2{03fq{QbrgPUm_czf$39 zgVCgImF>&po`|qic86Qq7axluFlT@F^PiD-e(9U1^^z&xJ8F_)P;9}@0+?o|ZSD*j z9HO hn(F8P?Q zoS}D+Df4s c2fw4^CnO2HR==(nV|2{lW)31m@rK~CA&U1H;}n1HWi)v90O8Y z4bKL_KDH{=dW9ermy5!YG5!CGLArhCZF%<1uLjg)uTw96_ $LrolCy |-{p9b9bX73TZ< z^ MDlj8zH|Xv&g5E5mOXNtSP+e57o_6x$t6vd3xpDpQNFOE*H!f@2{_wplhF426 zdqVo&PiMPgx}xr9Vq;9b(j_kdt9+yg=I|wH!Y+`H3pmo|IcX#oirOnw8@B~s>T?Xp zqX=K!uXp?IR;DLU)SSguK-H$QT)j)h{br0QBrHVk;hK@H?Fx-EkXGSxkufpS;J%=T z+gd4+uwJV(J;+sHBVf=N?>%lX>^(9cA}@aXm*x5AKO?qQGfDI{jC%kEgBW8G%ASw8 z_*6LDyjq9!3{Tq;YO^d9U!D-mAVk2#L|vkzg1K#t8#`+%s`rXC=4hlMY%SN6?F9y` ziB+n0#z`3?)SO;sB#OH;qV@r$aTAP=hwhDJwP8?XI^k^n8-GEHl+fZ7;f4&; Ws=PyRwLVyxKm2f=spkaFwFCkT)I((2+8U@dI~-VfQyGp1 zz{SFa=m?|+d#5c_Z)zjagw=fAFnZ6P%5;09yY
I@)McBVmi6T-~lbn8e;~l zU(||zZrBN9@x+GIMPESP?zu?OGzoi*SErfl$8;-lJc?G*A8m0O6>+ft*^kM)zwv7_ z?Qe8R?IL7MpO7GZh9fH6r&j4)7_3k IIMJ#kU$-71%v&Z*CoQv*7m>z7tMRZ5d+pQhoxJtS z-#XXI*w-M|!V=49ZtO6yAzCSw?JW|?`dRUsbFJF8Pxp8J@IxV2<$Pv^K!A^=(WZ37 zxJOgq?!-t_O^5*OqZ=TFHl$*?T!atdJfC#I&c~VFdLgpg8PM3&U!_2{&PF-4?1U|% z=#OHMDX_pivyG`L!AMWasOhj?8R%lOs2|U^L?8(4TK(Fn!?GPYmW@62u@}d#8;C?2 zPhYn?dH28iw%mT?9f_o+Tl??p@O DlNfw!O7U zX{EKfX0Kb&; *_VcDZ&hIBlM(Up!UFns83*lbX zU oF1%hvFV7bos@8;ci 4 zh`ZI)?Rs^8HqtHlmx6DuA(LxOLN-1pTH9zuGud7H?Rr9?!vcHX9e_LE%j5Ah>{&!) znq+$MLXY{u3bdRmwoUy-3e`W1LZm24tT4{_se&&&qhDuH`Cl)M8h zs+D4rR#KoUa&ibd4VCw#E+&dnhb7CWQS0 hdoeW^0G z8T1NH_MAj#(|gK0=y9g%j|wPIuZM+EoWM?pU?(#=hOwfmRr(x(5;F8`%1{3bgV411 zkdeozSxV3@{NquZRy$&@Crb kx-I5GK2pC|Zg?Po+ z=L`)lL=Hfl!mH% v8nf|1TGRbyS{-h9(2G(mj+yf8B_0+ zCXX)C7x&|+!nUOHIoI$#b=U``_un0GI?7-@3h=5X&W =LH)u;*!g zFFRWl8F+7m5+eo&eL043JY<9yI;z|udxSwV9*{notAfzz`b8|mNTp{rR2vE2aRVC} zG42Uz&!E#V(hj(s*fh!A*S;t(fAQ<5G_o{f(6WjLSNnA-NKf`NgUP5&Y*9AkyQ;(( z>E|&;=x(HJ1jdnL#7LyHm8=2c;4z$Wn4GiK^z!~6s%OY{53agyT?cXn^&2^dYwNIF z(7UGp=pu2GDx|qC8wOdTXmnfx`{Bc*b>}sk2euPwix}YOwO!3Xjs9JC`*3JRMUxO# z8 =%l_F@WeZzh#c<+6ZZ8<2i6HGr%V4E4 z=qSf8GF&M6V^@*~)VGrzyq0Z8GG=-?60;_YMzgt0nOF;|OtYr0!LsZKI&f=Kf@34) zQ|o)0A+jto4fN Sw~zi&(M316(niq zAI!4=EI-{VjQem40(tSJFUs_hx6)_Hlyb
2ytDJ-hk-;k5RIvU~YbWSZ8$ zFW_n_2ATWFnt`vgDUP;AWfY4?-G}X3=t(?ftt_1hqsfd1J=B?r7sY@% @$CFDP4fTA>4IcqF@9I#wr3`Y-VS&^Ux~0 z#m+(whHtnv!Gu+$kx0N8k>QT_{}K0QO}AxNmDn8nobNVyGnJB3P(@D>2C57KBnOm> zG67UW*kS*h`Z0d<2sSu)~g`ilP%B(MU8xP2T%8=j>4ryPNG=>wGtbGeWxe ze$8q2S$nN9#~gDE?<${U4x$%w&PYa58Pk#l#)NATYOvw^zPHBOJm>tc0@qQzc=|jy zCd>~cxTIM&tAi%^8NSI;as`rPXk>vAKR}R$(KlErB9i%Ej9n36pe}XZNL&F{J%!}j zJASuyp!ww&z94UY`4`N+kTX2abElGS-1@nV#UjX%KNn;1)Fiw{94W7}@afSpNW~jy z^`$z%jLByRL1b}*Fxj$NdOB#I7*5s9?j=E)mAXWMy=J>yL}n4eB-7_VT3dtacP2Q0 z0G962y#lT3o(|bDN!^wVKu)4_Hl(%`rU8bvsjoM`WkY~c2?knan&*{|Hsj%yCq*og zv<5qp0}A3V&`6HUa)s`G>PO@YzxH3rbUvw?(eY)}th}F=WX?)fj1^t;biU?xVZFVm z!C E<;gKz;@q;P^vA8rEoX=f^Q zOisnRlS3=C!zSTb`%HGZP>}T+Q)IRh+4^R3E>QX5F;Eb<-5OD!-V)9aUgS#9Rph3p z11J>*`06ZQ{GH#F7axBvy@19VHTV^16VOICqvcOPS=i^%u2MA&Aqk`EZ95Vh7GIkC zsaIx$XHM@_X%9UsWh7rQqdgu=dZ>VLPxMhfe%Rc*5==EGfqugWC>Q+jIpH1yt=mFh zy X3mRwLk#@A0|^FG30&Fm~~n)~c;l;2V8t zj3}pLfVs eGQv&$-xQxBuon-pp zjmR`bVZ6B0XxxMOw(SV*UPEi^@Jq%-_@vjYJ&%9}yQH5r!!;OK`(^8pY(RVnM`2ec zD!U~(7y3Dlo$kYb@hkGt&;M+)2h|oT#^S&`wKE31(`?KPnk-(Q`lz0b` I z%t}NUrmPjdX`b3wPNTh*_4iM&Udcya{gs7 3A$>-Ep`KmJ5M`Hg=mr@I&Vok qIy(B?Yn{0ii8c+b z_t-rTA>Jh@9WGBM^h(y>Rywwq_Vmpk lF zcI$Z&jVcigGCi-eO&{*eaCNshM#mO734p8KoX@K3I;>`5Ac)+Z Fe{MEJ*u{gsXiuSTV%wQXGnzI*jQ@K7mmutiB!>3h$bZ$+}GI4llliS?Tqgs zOgfgY34KHLn{&fPCf_L0cbNr2?<)$p1(^jUyPrYDJn;xHRqMr5`>a5Jv6;U7;uqzE zul%BPCj=U6#CuZrI}N?8cP1>SBw8z`Y%L|*iD;Mu_7JPc3b3*qN#6p9g$~UImN=^e zVS*4YPtMz5RZSs%7?=oZZ_nVXRkz6+Diql74n97K2<7zAM@xHf_rS7|KETwx4ZT%Y zW?-A0{~VO`jn4bVbBsgmk#5`Hwq?S~+XCWaf&rq;01d_rQrLr3#=6b<8q^oC=)Dsn zuYdVx<>N2^vluEVBDv*$5x%E77`io>< zg#p5WF|y2f zKzl$*=>~PDW~N1aPPmUUlhVefo;tgy=~}8q7+LmQ$m6%KYD9N*{;WDaLPC0FR47SX zkB4hFG`wvH0#KBbByVG;K5HPB(Y2KJ*o=%2A7jG)!L-Sw{S~=kUt!SDv-%NG3XR({ z2`)&w)l?s{;a}Q3AAk857iV{Qp4CWwK#h)#3_Mega|Xy*yDJ@;d<|lCE#Kycha`;I zu|?=?wwaD1^%kn*l7ex2Dp*H4NNU#y4cJeMoa7D6504^%Odo$Fz-eWx*2kT6#-a3+ zr_(yI(=K~nO ~uVsbsj{6|19GZN!(77N{Eb(ak?&y?xEGb%P_e+ zec?m- J3+w*2;_e>7JjO`6J`oy WgooqTVbQzd=}PwE)qlo)iqK-m7!;AI=EGpXE&TFa!p&5$*}=9@CU~- zZHI$x;e7BDKQ1r+$&U>o;q9g?t#HaCYha$aEIDa6gi=< z1LOK;-)F-V`V( zfl$mE?8Z{TQ%O=p@4&E99!1eVmj9lmt0eXnk2el@5V;;^kB=hLB&Ux*TCJPc>A`6_ z{I6POKEsKA@}568R`#~Ss7E>#E%vHTM!;=dkWi>FE$zaVKT7vCZndndSvMjk;c1f3 z|EvE-KKSt;jYpB|69z_>dQVb!u@2;Dgm#iYTegE~ApwM`? V#{rg z2@@sBq}ylBIE{sw58dR3g+u28wgiLk^>*rLnEtL5SFP5|`OhA$zNT|Y-}eqPnB^Si z_Gd(wJ<-2Mw+hd%U(3h8`qjlivd82xk0k4R6=w>>IxM8ehtWLqaToiIsRDm2iY)!c z=C|)eIIkNdg^2;^#)cUtscYp>R!VIg@7AquTpLqTCvJy-?7)5{_k{Y8d4Dgso0bVe z1H=%_Oy8f%t^rd(UH{wEgSe-JJ0jjT#}*jfAMXt5 {!D^qHb&Il8r7x z1t5}}>*de?q yM;mt=##Q{Ve=v(qPo~i+sK0?7p#FANwdW&1d6- zQ2NE>tn!XIEnh53DR_rxxC@;uJlaLx=-4MGnJ;t`(WB0&Da1y&ler%9;Sdwy!#cAg z86iBVJwjizN-P#Dm0NCq(eN|Mx%o`UuWYAk{mf@fxN+bPL&?N+=5&=73rUrdO~7e= zzn2AYW>Uc*OrzAt9pa6?{`141{V!zt KfEKI-K*npS+pO?MudsiXt27? zx}X32?(KTbmAWNVqqN5RlCVi4ohTeBDhcEaS7mJ45cM8Yt*{zT&-nR$c%Fs#k0LK$ z$n^U4!dOi G}22PqQz>pYQL3d8`*Z2dI)sw*0VO<<6cUB$RAdtVkDeeU=K1SQ2Xe6_Duq zAehzz`teDo58uf2;%)`>n>E8^#O^#i2;O5KxPfsR+3dQYhBv<^ri>aKNQ>oqxc}KR z2gRP~fkeg 4!M?dpVf=M)z2{~pNM$8LM{R=ez zSJ _h<0k&TKALF{D3;~ 4!!i9 02qlNGw8NieOxQy~c82?>*t!kc8s=X5&D$G`MtfpK>C< vN|q9?}GRZ{Z*f zk1VIwP39fq`$OFD-7c-$^~=QjRrqv~(-%H3I30Q`Op_A3qtJ8W=3TP9Px<_NyjK+6 zvVUolYLq8)?sH{YT}(VjZsgZlF(^CChD(4zbLy><&sDnQ^N;@{`Q%^z*Gu?!{bKAH zO9xdUv8|{-Zz}LaSD=~yX$EXw!k(EFC?l7;C-cja3VZ{bl20K@?hWqOI2@iNW1G%{ zrkxl<9!*uAG19S5B&}LUZGlsE5QIa}m6n#hLi$9FnzFOW@mN@%gRA-&Bd1yR^W+#3 zeAa&R8L>^bP=(oN@~pSgQh4?}uV6N@%$G-l5;~M@rwQ|yMOH?KjC~A$7$fmJa(_4L zSK*L1Klu}K_tQVtzGjS77#qOK&Q6X8fm69UlQfUvH?)yxoVeK_X&=&DOg=rzytNw4 z|16+t%C6E%7=}qQfGh##8g#YSrUhzd;sJ59)$Ky-5TZsRuFGL{`uNSE^)nhTWoW9b z8piISqFhhz)7!~y)&=f+#6QGb4s?FbGoTSYvr%a3fhelqU|J3)CQh2YB5U{Z-iAv1 z_;`6IpZvG~T3&wgh5G83HVvlI3IC?rSm<>Ouf<&e03ZNKL_t(>&br~)H@p{CqYqbE zE-(R|`g^F`SCGSGmxFtde_Hri6zNYCn&hzHuYeLbQ#sPphdn1OTb0l^H8F|$aQykf z41ELTQJl_psjF=erh0|hK(2v_nHN+l+&f^asaW0@OqDm?d(us<{jT$RIh-w@L9@ &;WY7e`ghv7;ga(UalhZ;(>)p0jtSI`yibnWS0f)-M#P6Ty=UlpSXrYZj! zdRT_ra3{U*Q$hDrvWBDty&}^#Tl>y|zrP^z=GVR~AOFJ7nZ1wcPEAGBZU1KCPA(y{ z(Y)45zhwA{&A^Vr`I^5bNP7+^Yu~dWZci=}S_};Hjs|?SsX&=x+}H*x&VfK}(ekAD8=c4zk# zt3eVM_3BPqK`9z6gsE29>txi2T9;MLjI=r}sHe*s8f&4po~UHef{Gb^5lD|OZ);9! z){vPblvHyS3N*DafC#otvG(+|cwoKxXpP3%0F|<65CyX4u_?ba!!QHE7y(VaUQhN} z^jIvWpLwNpLGgU>O)8zY*O`-P-Mg*Cg#MP=@Fgp{x_U>Me)#k9rQiNdIlX+9#JgqS zt@xS-Q_TNO4GKdR>G3CNSwmc&+MN${8W-97&!*lW?P>pPDY~)5EK- (D>0P!o?Qp@w4)ft(%q;@QmNt;mwxkNTB2YI^edJ2!nN^7JZVhb) #?F_qe@3{gKatrUayPX6%|_+kApo=&K$5P zsjZh^`b6G*^~>gcP`|(qzUM$)pWPws9w^1rvp3b*UM6S^8SpwUCYu|S$;ciz&8Y#i z*1=Tk3Kgr0&VAgvPYYkH-7Ve;vEW8m^+V53kAl0COs`&vC{erCY+-^bV5-k>WWu!9 zYZ$-Z>!L{#+E7ZsmFE-W`vgm9WBVd#bt4AfrEi&I7+`kxNY;MN5D~dM$ru0aZ^;Kg z^26n`jlZFYB0|of0-|*KEgMJ10~pM6@N4pWFK^XcVGzZ(T8TG^xhrG&z1TKfjANzq zX};qMB<)G_^`ydu7`|x#{?tYE$RSllYPVg0Z8Zl4h7dS?{f5y787Ri7*YE8uPRRIl za FWp|bh}p&k!d=~=YQpw1s}YK>utbvufGJDqTNs>t;`oYaYp<5N?ge!dxPTo7J`S% zRrvHM(QW}{mxq!}4F$`MW8!RF&WQSKSH_|{Wb^$`Z^00H4t7u3f984>eE6Z@<$1Z* zr)lv^+riZ&rOkX}A0d0O44);3p6L;?@VQR!C#5`Sz;YKvcD1yP%7yu%+q~BdRpUaz z9XF3&g8`6NU;a7y!dHK3_sq+DvRF+HZ|y=_CU19dSNW@UyU;Dqh6TiS8_yJ(uhDGR zH-#`rL{Q4md1hu;1MSD^v!+OyO$y1vqG7BnDsI&$0WcZHJce&5Nq9^Qxt7o(Oh8i6 zm)To{PGi#D2H;IAvXKEATK;$k4WWCZh -JsKc4-ahmP$ zGTSn8CTefJP