diff --git a/CHANGELOG.md b/CHANGELOG.md index 3f0adfd18..a7ab1b99b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,5 @@ ## 3.8.0 +* Add configurable DCS-BIOS git repository - #533 (@emcek) * Allow checkout remote git branches for BIOS - #530 (@emcek) * Internal: * remove `psutil` library - #531 (@emcek) diff --git a/README.md b/README.md index 249a4783d..3b6f2667f 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -[![image](https://img.shields.io/badge/pypi-v3.7.1-blue.svg)](https://pypi.org/project/dcspy/) +[![image](https://img.shields.io/badge/pypi-v3.8.0-blue.svg)](https://pypi.org/project/dcspy/) [![Python CI](https://github.com/emcek/dcspy/actions/workflows/python-ci.yml/badge.svg?branch=master)](https://github.com/emcek/dcspy/actions/workflows/python-ci.yml) [![Coverage Status](https://coveralls.io/repos/github/emcek/dcspy/badge.svg?branch=master)](https://coveralls.io/github/emcek/dcspy?branch=master) [![Codacy Badge](https://app.codacy.com/project/badge/Grade/5270a4fc2ba24261a3bfa7361150e8ff)](https://app.codacy.com/gh/emcek/dcspy/dashboard?utm_source=gh&utm_medium=referral&utm_content=&utm_campaign=Badge_grade) diff --git a/SECURITY.md b/SECURITY.md index 2e821ae1f..c2d0c1f5c 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -6,9 +6,9 @@ Versions of DCSpy are currently being supported with security updates. | Version | Supported | |---------|--------------------| +| 3.8.x | :white_check_mark: | | 3.7.x | :white_check_mark: | -| 3.6.x | :white_check_mark: | -| <3.5.x | :x: | +| <3.6.x | :x: | ## Reporting a Vulnerability diff --git a/docs/bios_live.md b/docs/bios_live.md index 2cdf45e5f..608fc7d35 100644 --- a/docs/bios_live.md +++ b/docs/bios_live.md @@ -11,8 +11,10 @@ DCSpy basically copy latest changes from DCS-BIOS repository into your `Save Gam Another option you can specify is `DCS-BIOS Git reference`, where `master` (recommended default value) means latest commit. But you can use any branch or commit ID. +You can even use own DCS-BIOS fork, just enter URL adress of repostory. It is requre to click **Repair** button to remove old repo and clone new one. + Example: ![image](https://github.com/emcek/dcspy/assets/475312/7d1da9db-a123-456f-bf7a-78d70344ba8c) -![image](https://github.com/emcek/dcspy/assets/475312/5e088539-a086-4375-8e1e-161287a04f18) +![image](https://github.com/user-attachments/assets/e2aca438-09b9-406d-88bf-5cf70b45b44b) diff --git a/inno/dcspy.iss b/inno/dcspy.iss index e665c2925..8905b66d3 100644 --- a/inno/dcspy.iss +++ b/inno/dcspy.iss @@ -2,7 +2,7 @@ ; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES! #define MyAppName "dcspy" -#define MyAppVersion "3.7.1" +#define MyAppVersion "3.8.0" #define MyAppPublisher "MichaƂ Plichta" #define MyAppURL "https://dcspy.readthedocs.io/en/latest/" #define MyAppExeName "dcspy.exe" @@ -33,7 +33,7 @@ LicenseFile=D:\a\dcspy\dcspy\LICENSE.md ; Uncomment the following line to run in non administrative install mode (install for current user only). ;PrivilegesRequired=lowest OutputDir=D:\a\dcspy\dcspy\inno -OutputBaseFilename=dcspy_3.7.1_setup +OutputBaseFilename=dcspy_3.8.0_setup SetupIconFile=D:\a\dcspy\dcspy\inno\SetupClassicIcon.ico SolidCompression=yes WizardStyle=modern diff --git a/sonar-project.properties b/sonar-project.properties index 4c410a993..1ff620665 100644 --- a/sonar-project.properties +++ b/sonar-project.properties @@ -3,7 +3,7 @@ sonar.organization=emcek # This is the name and version displayed in the SonarCloud UI. sonar.projectName=dcspy -sonar.projectVersion=3.7.1 +sonar.projectVersion=3.8.0 # Path is relative to the sonar-project.properties file. Replace "\" by "/" on Windows. sonar.sources=src diff --git a/src/dcs_py.py b/src/dcs_py.py index f8f40be9c..7a35886f0 100644 --- a/src/dcs_py.py +++ b/src/dcs_py.py @@ -5,7 +5,7 @@ from PySide6.QtCore import Qt from PySide6.QtWidgets import QApplication, QMessageBox -__version__ = '3.7.1' +__version__ = '3.8.0' def start_dcspy(cli_args: Namespace) -> None: diff --git a/src/dcspy/migration.py b/src/dcspy/migration.py index 3a3fe96c6..c4e2be4e2 100644 --- a/src/dcspy/migration.py +++ b/src/dcspy/migration.py @@ -10,7 +10,7 @@ from packaging import version -from dcspy.models import ConfigValue, DcspyConfigYaml, __version__ +from dcspy.models import BIOS_REPO_ADDR, ConfigValue, DcspyConfigYaml, __version__ from dcspy.utils import DEFAULT_YAML_FILE, defaults_cfg, get_config_yaml_location LOG = getLogger(__name__) @@ -56,9 +56,18 @@ def _filter_api_ver_func(cfg_ver: str) -> Iterator[Callable[[DcspyConfigYaml], N yield globals()['_api_ver_{}'.format(api_ver.replace('.', '_'))] +def _api_ver_3_8_0(cfg: DcspyConfigYaml) -> None: + """ + Migrate to version 3.8.0. + + :param cfg: Configuration dictionary + """ + _add_key(cfg, 'git_bios_repo', BIOS_REPO_ADDR) + + def _api_ver_3_7_0(cfg: DcspyConfigYaml) -> None: """ - Migrate to version 3.7.1. + Migrate to version 3.7.0. :param cfg: Configuration dictionary """ @@ -70,7 +79,7 @@ def _api_ver_3_7_0(cfg: DcspyConfigYaml) -> None: def _api_ver_3_5_0(cfg: DcspyConfigYaml) -> None: """ - Migrate to version 3.5.1. + Migrate to version 3.5.0. :param cfg: Configuration dictionary """ diff --git a/src/dcspy/models.py b/src/dcspy/models.py index e76c3ddbd..61e234a14 100644 --- a/src/dcspy/models.py +++ b/src/dcspy/models.py @@ -18,7 +18,7 @@ from PIL import Image, ImageDraw, ImageFont from pydantic import BaseModel, ConfigDict, RootModel, field_validator -__version__ = '3.7.1' +__version__ = '3.8.0' # Network SEND_ADDR: Final = ('127.0.0.1', 7778) @@ -40,6 +40,7 @@ LOCAL_APPDATA: Final = True DCSPY_REPO_NAME: Final = 'emcek/dcspy' BIOS_REPO_NAME: Final = 'DCS-Skunkworks/dcs-bios' +BIOS_REPO_ADDR: Final = f'https://github.com/{BIOS_REPO_NAME}.git' DEFAULT_FONT_NAME: Final = 'consola.ttf' CTRL_LIST_SEPARATOR: Final = '--' CONFIG_YAML: Final = 'config.yaml' diff --git a/src/dcspy/qt_gui.py b/src/dcspy/qt_gui.py index ded0c85cb..613c88ae7 100644 --- a/src/dcspy/qt_gui.py +++ b/src/dcspy/qt_gui.py @@ -83,6 +83,7 @@ def __init__(self, cli_args=Namespace(), cfg_dict: DcspyConfigYaml | None = None self.ctrl_depiction: dict[str, ControlDepiction] = {} self.input_reqs: dict[str, dict[str, GuiPlaneInputRequest]] = {} self.git_exec = is_git_exec_present() + self.bios_git_addr = self.config['git_bios_repo'] self.l_bios = version.Version('0.0.0') self.r_bios = version.Version('0.0.0') self.systray = QSystemTrayIcon() @@ -170,8 +171,9 @@ def _init_settings(self) -> None: self.pb_dcspy_check.clicked.connect(self._dcspy_check_clicked) self.pb_bios_check.clicked.connect(self._bios_check_clicked) self.pb_bios_repair.clicked.connect(self._bios_repair_clicked) - self.le_bios_live.textEdited.connect(self._is_git_object_exists) - self.le_bios_live.returnPressed.connect(partial(self._bios_check_clicked, silence=False)) + self.le_bios_ref.textEdited.connect(self._is_git_object_exists) + self.le_bios_ref.returnPressed.connect(partial(self._bios_check_clicked, silence=False)) + self.le_bios_repo.textEdited.connect(self._bios_git_repo_chnaged) self.cb_bios_live.toggled.connect(self._cb_bios_live_toggled) self.sp_completer.valueChanged.connect(self._set_find_value) # generate json/bios self.tw_gkeys.currentCellChanged.connect(self._save_current_cell) @@ -239,18 +241,18 @@ def _init_menu_bar(self) -> None: def _init_autosave(self) -> None: """Initialize of autosave.""" widget_dict = { - 'le_dcsdir': 'textChanged', 'le_biosdir': 'textChanged', 'le_font_name': 'textEdited', 'le_bios_live': 'returnPressed', - 'hs_large_font': 'valueChanged', 'hs_medium_font': 'valueChanged', 'hs_small_font': 'valueChanged', 'hs_debug_font_size': 'valueChanged', - 'sp_completer': 'valueChanged', 'combo_planes': 'currentIndexChanged', 'toolbar': 'visibilityChanged', 'dw_gkeys': 'visibilityChanged', - 'a_icons_only': 'triggered', 'a_text_only': 'triggered', 'a_text_beside': 'triggered', 'a_text_under': 'triggered', - 'a_mode_light': 'triggered', 'a_mode_dark': 'triggered', 'a_mode_system': 'triggered', - 'cb_autostart': 'toggled', 'cb_show_gui': 'toggled', 'cb_check_ver': 'toggled', 'cb_ded_font': 'toggled', 'cb_lcd_screenshot': 'toggled', - 'cb_verbose': 'toggled', 'cb_autoupdate_bios': 'toggled', 'cb_bios_live': 'toggled', 'cb_debug_enable': 'toggled', - 'rb_g19': 'toggled', 'rb_g13': 'toggled', 'rb_g15v1': 'toggled', 'rb_g15v2': 'toggled', 'rb_g510': 'toggled', - 'rb_g910': 'toggled', 'rb_g710': 'toggled', 'rb_g110': 'toggled', 'rb_g103': 'toggled', 'rb_g105': 'toggled', - 'rb_g11': 'toggled', 'rb_g35': 'toggled', 'rb_g633': 'toggled', 'rb_g930': 'toggled', 'rb_g933': 'toggled', - 'rb_g600': 'toggled', 'rb_g300': 'toggled', 'rb_g400': 'toggled', 'rb_g700': 'toggled', 'rb_g9': 'toggled', - 'rb_mx518': 'toggled', 'rb_g402': 'toggled', 'rb_g502': 'toggled', 'rb_g602': 'toggled', + 'le_dcsdir': 'textChanged', 'le_biosdir': 'textChanged', 'le_font_name': 'textEdited', 'le_bios_ref': 'returnPressed', + 'le_bios_repo': 'returnPressed', 'hs_large_font': 'valueChanged', 'hs_medium_font': 'valueChanged', 'hs_small_font': 'valueChanged', + 'hs_debug_font_size': 'valueChanged', 'sp_completer': 'valueChanged', 'combo_planes': 'currentIndexChanged', + 'toolbar': 'visibilityChanged', 'dw_gkeys': 'visibilityChanged', 'a_icons_only': 'triggered', 'a_text_only': 'triggered', + 'a_text_beside': 'triggered', 'a_text_under': 'triggered', 'a_mode_light': 'triggered', 'a_mode_dark': 'triggered', + 'a_mode_system': 'triggered', 'cb_autostart': 'toggled', 'cb_show_gui': 'toggled', 'cb_check_ver': 'toggled', + 'cb_ded_font': 'toggled', 'cb_lcd_screenshot': 'toggled', 'cb_verbose': 'toggled', 'cb_autoupdate_bios': 'toggled', + 'cb_bios_live': 'toggled', 'cb_debug_enable': 'toggled', 'rb_g19': 'toggled', 'rb_g13': 'toggled', 'rb_g15v1': 'toggled', + 'rb_g15v2': 'toggled', 'rb_g510': 'toggled', 'rb_g910': 'toggled', 'rb_g710': 'toggled', 'rb_g110': 'toggled', 'rb_g103': 'toggled', + 'rb_g105': 'toggled', 'rb_g11': 'toggled', 'rb_g35': 'toggled', 'rb_g633': 'toggled', 'rb_g930': 'toggled', 'rb_g933': 'toggled', + 'rb_g600': 'toggled', 'rb_g300': 'toggled', 'rb_g400': 'toggled', 'rb_g700': 'toggled', 'rb_g9': 'toggled', 'rb_mx518': 'toggled', + 'rb_g402': 'toggled', 'rb_g502': 'toggled', 'rb_g602': 'toggled', } for widget_name, trigger_method in widget_dict.items(): getattr(getattr(self, widget_name), trigger_method).connect(self.save_configuration) @@ -261,8 +263,9 @@ def _trigger_refresh_data(self) -> None: self._is_dir_exists(text=self.le_dcsdir.text(), widget_name='le_dcsdir') self._is_dir_dcs_bios(text=self.bios_path, widget_name='le_biosdir') if self.cb_bios_live.isChecked(): - self.le_bios_live.setEnabled(True) - self._is_git_object_exists(text=self.le_bios_live.text()) + self.le_bios_ref.setEnabled(True) + self.le_bios_repo.setEnabled(True) + self._is_git_object_exists(text=self.le_bios_ref.text()) for logitech_dev in ALL_DEV: logi_dev_rb_name = f'rb_{logitech_dev.klass.lower()}' dev = getattr(self, logi_dev_rb_name) @@ -895,13 +898,13 @@ def _is_git_object_exists(self, text: str) -> bool | None: :return: True if a git object exists, False otherwise. """ if self.cb_bios_live.isChecked(): + self._set_completer_for_git_ref() git_ref = is_git_object(repo_dir=self.bios_repo_path, git_obj=text) LOG.debug(f'Git reference: {text} in {self.bios_repo_path} exists: {git_ref}') if git_ref: - self.le_bios_live.setStyleSheet('') - self._set_completer_for_git_ref() + self.le_bios_ref.setStyleSheet('') return True - self.le_bios_live.setStyleSheet('color: red;') + self.le_bios_ref.setStyleSheet('color: red;') return False return None @@ -915,7 +918,7 @@ def _get_bios_full_version(self, silence=True) -> str: sha_commit = 'N/A' if self.git_exec and self.cb_bios_live.isChecked(): try: - sha_commit = check_github_repo(git_ref=self.le_bios_live.text(), repo_dir=self.bios_repo_path, repo=BIOS_REPO_NAME, update=False) + sha_commit = check_github_repo(git_ref=self.le_bios_ref.text(), repo_dir=self.bios_repo_path, repo=self.le_bios_repo.text(), update=False) except Exception as exc: LOG.debug(f'{exc}') if not silence: @@ -929,25 +932,42 @@ def _cb_bios_live_toggled(self, state: bool) -> None: :param state: True if checked, False if unchecked. """ if state: - self.le_bios_live.setEnabled(True) - self._is_git_object_exists(text=self.le_bios_live.text()) + self.le_bios_ref.setEnabled(True) + self.le_bios_repo.setEnabled(True) + self.l_bios_ref.setEnabled(True) + self.l_bios_repo.setEnabled(True) + self._is_git_object_exists(text=self.le_bios_ref.text()) else: - self.le_bios_live.setEnabled(False) - self.le_bios_live.setStyleSheet('') + self.le_bios_ref.setEnabled(False) + self.le_bios_repo.setEnabled(False) + self.l_bios_ref.setEnabled(False) + self.l_bios_repo.setEnabled(False) + self.le_bios_ref.setStyleSheet('') self._clean_bios_files() self._bios_check_clicked(silence=False) def _set_completer_for_git_ref(self) -> None: """Set-ups completer for Git references of the DCS-BIOS git repository.""" - if not self._git_refs_count: - git_refs = get_all_git_refs(repo_dir=self.bios_repo_path) + git_refs = get_all_git_refs(repo_dir=self.bios_repo_path) + if self._git_refs_count != len(git_refs): self._git_refs_count = len(git_refs) completer = QCompleter(git_refs) completer.setCaseSensitivity(Qt.CaseSensitivity.CaseInsensitive) completer.setCompletionMode(QCompleter.CompletionMode.PopupCompletion) completer.setFilterMode(Qt.MatchFlag.MatchContains) completer.setModelSorting(QCompleter.ModelSorting.CaseInsensitivelySortedModel) - self.le_bios_live.setCompleter(completer) + self.le_bios_ref.setCompleter(completer) + + def _bios_git_repo_chnaged(self, text: str) -> None: + """ + Show info at statusbar when BIOS Git repostory changed. + + :param text: Git repository sddress + """ + self.le_bios_repo.setStyleSheet('') + if self.bios_git_addr != text: + self.statusbar.showMessage('BIOS git address changes, please click Repair') + self.le_bios_repo.setStyleSheet('color: red;') # <=><=><=><=><=><=><=><=><=><=><=> check dcspy updates <=><=><=><=><=><=><=><=><=><=><=> def _dcspy_check_clicked(self) -> None: @@ -1016,8 +1036,8 @@ def _start_bios_update(self, silence: bool) -> None: :param silence: Perform action with silence """ if self.cb_bios_live.isChecked(): - clone_worker: QRunnable | WorkerSignalsMixIn = GitCloneWorker(git_ref=self.le_bios_live.text(), bios_path=self.bios_path, - to_path=self.bios_repo_path, repo=BIOS_REPO_NAME, silence=silence) + clone_worker: QRunnable | WorkerSignalsMixIn = GitCloneWorker(git_ref=self.le_bios_ref.text(), bios_path=self.bios_path, + to_path=self.bios_repo_path, repo=self.le_bios_repo.text(), silence=silence) signal_handlers = { 'progress': self._progress_by_abs_value, 'stage': self.statusbar.showMessage, @@ -1083,7 +1103,7 @@ def _clone_bios_completed(self, result) -> None: install_result = self._handling_export_lua(temp_dir=self.bios_repo_path / 'Scripts') install_result = f'{install_result}\n\nUsing Git/Live version.' self.statusbar.showMessage(sha) - self._is_git_object_exists(text=self.le_bios_live.text()) + self._is_git_object_exists(text=self.le_bios_ref.text()) self._reload_table_gkeys() if not silence: self._show_message_box(kind_of=MsgBoxTypes.INFO, title=f'Updated {self.l_bios}', message=install_result) @@ -1241,6 +1261,7 @@ def _bios_repair_clicked(self) -> None: self._clean_bios_files() self._remove_dcs_bios_repo_dir() self._start_bios_update(silence=False) + self.le_bios_repo.setStyleSheet('') def _clean_bios_files(self) -> None: """Clean all DCS-BIOS directories and files.""" @@ -1335,7 +1356,8 @@ def apply_configuration(self, cfg: dict) -> None: getattr(self, f'rb_{cfg["device"].lower()}').toggle() self.le_dcsdir.setText(cfg['dcs']) self.le_biosdir.setText(cfg['dcsbios']) - self.le_bios_live.setText(cfg['git_bios_ref']) + self.le_bios_ref.setText(cfg['git_bios_ref']) + self.le_bios_repo.setText(cfg['git_bios_repo']) self.cb_bios_live.setChecked(cfg['git_bios']) self.addDockWidget(Qt.DockWidgetArea(int(cfg['gkeys_area'])), self.dw_gkeys) self.dw_gkeys.setFloating(bool(cfg['gkeys_float'])) @@ -1367,7 +1389,8 @@ def save_configuration(self) -> None: 'dcsbios': self.le_biosdir.text(), 'font_name': self.le_font_name.text(), 'git_bios': self.cb_bios_live.isChecked(), - 'git_bios_ref': self.le_bios_live.text(), + 'git_bios_ref': self.le_bios_ref.text(), + 'git_bios_repo': self.le_bios_repo.text(), 'font_mono_l': self.mono_font['large'], 'font_mono_m': self.mono_font['medium'], 'font_mono_s': self.mono_font['small'], @@ -1698,6 +1721,8 @@ def _find_children(self) -> None: self.l_description: QLabel = self.findChild(QLabel, 'l_description') self.l_identifier: QLabel = self.findChild(QLabel, 'l_identifier') self.l_range: QLabel = self.findChild(QLabel, 'l_range') + self.l_bios_ref: QLabel = self.findChild(QLabel, 'l_bios_ref') + self.l_bios_repo: QLabel = self.findChild(QLabel, 'l_bios_repo') self.a_start: QAction = self.findChild(QAction, 'a_start') self.a_stop: QAction = self.findChild(QAction, 'a_stop') @@ -1747,7 +1772,8 @@ def _find_children(self) -> None: self.le_dcsdir: QLineEdit = self.findChild(QLineEdit, 'le_dcsdir') self.le_biosdir: QLineEdit = self.findChild(QLineEdit, 'le_biosdir') self.le_font_name: QLineEdit = self.findChild(QLineEdit, 'le_font_name') - self.le_bios_live: QLineEdit = self.findChild(QLineEdit, 'le_bios_live') + self.le_bios_ref: QLineEdit = self.findChild(QLineEdit, 'le_bios_ref') + self.le_bios_repo: QLineEdit = self.findChild(QLineEdit, 'le_bios_repo') self.le_custom: QLineEdit = self.findChild(QLineEdit, 'le_custom') self.rb_g19: QRadioButton = self.findChild(QRadioButton, 'rb_g19') @@ -1930,7 +1956,7 @@ def __init__(self, git_ref: str, bios_path: Path, to_path: Path, repo: str, sile Inherits from QRunnable to handler worker thread setup, signals and wrap-up. :param git_ref: Git reference - :param repo: Valid git repository user/name + :param repo: Valid git repository address :param bios_path: Path to DCS-BIOS :param to_path: Path to which the repository should be cloned to :param silence: Perform action with silence diff --git a/src/dcspy/qtgui_rc.py b/src/dcspy/qtgui_rc.py index 077e16b55..69a42fc71 100644 --- a/src/dcspy/qtgui_rc.py +++ b/src/dcspy/qtgui_rc.py @@ -622647,439 +622647,445 @@ \x8a\xa9\xd1\xfe:LOFg-\x00\xce\x86_\x89\xe9\ \xf8\xe2\xec\x1b`\xda\xa4\xb5\x84\x8bS\x0a\x8f\xff\x00\x1c\ ?\x09m\ -\x00\x00\x1a\xee\ +\x00\x00\x1bM\ \x00\ -\x01Z\x1dx\xda\xed][s\xe36\xb2~\xdf\xaa\xfd\ -\x0f,?%\xb5\x91-\x89\x96e\xb9\x1co\xcd=S\ -\x19Of\xc6\xce\xe4\xbc\xa9(\x12\x96pL\x11\x1c\x12\ -\x94\xad\xad<\xed\x7f;\xff\xeb4@J\xe2\x05\x04\xef\ -\xb2\xa8\xe2\x93-\xb2\x89K\xa3\xf1u\xa3\xbb\x01\x5c\xff\ -\xfbyi*+\xe4\xb8\x98X\xbf\x9e\x0cN\xfb'\x0a\ -\xb2tb`k\xfe\xeb\xc9\x9f\xf7\xef{\x97'\xff\xbe\ -\xf9\xe7?\xae=\xbc\xa3:\x07*x\xa6\x5ck\x1e]\ -\x10\xe7\xe6\x16\xeb\x0b\xed\xff\xfe\xab|1\xe1\x1f\xaa]\ -\x9f\x05\xcf\x19\x89nj\xae{\xf3\x95\xbe\xd5\xdd\xeb3\ -\xff\x07{\xfc\x84\x8d9\xa2\x0a\x7f\xf0\xeb\xc9\xd7[\x0d\ -[\x7fa\xcb O'\x8a\xa5-\x11{\xde\ -\xfcZ\xb3_\xeb\xcd/\xa8\x93.n&cx\xe6\xff\ -\x1b<_ <_\xd0\x9bq\x1f^\x04\xff\xfb\x05\x9f\ -mK\xbe>\xdb\xb4A\xd8\xa2%\xb6\xf0\xd2[\xde\xe1\ -\xff\xa0M\xa3\x5c\xf8?Z\xf1\xa8\x9f\xbf\xe2\xed\xd7\x19\ -\x15?q\x9e\xddcj\xee*\xa6\x0e\x8c\xdd\xcd\xdb7\ -w\xf6\x1a\x0a\xf2\x7f\xe5.\xea\xa3N\xacMI\x18\xfe\ -wa\x90\x1c\xe4\x12\xcf\xd1\x81\xe6\xf4\xf4\xec\x07\x9d{\ -\xf8\xf4\x87\xa3\x9flza\x11g\xa9\x99\xe4\xe1\xe1\xe6\ -\xea\x8c\x7fr\x86\x97\xf33Cw\xed\xf5\xf4i\x81)\ -:uW\xf3\xeb\xb3\x9cdA\xa5\xc2\x16\xc7\x84\xe6/\ -\xfes#0:\xb2\xa8\xa3\x99>\xcd\xa6\x0b\xa6\xb6&\ -\xde\xee\x8b\x0f\x0e6>\xf1G\x9b\xaf\xe6\xbb'\x9b\xfe\ -@S\x96\x8aC\x9e~=\x81\xb9\xa0\x13\xd3[Z\xec\ -\xdf\xe0u\xa2\xcc\xef\xaf\xc9s\xb4L\x98'\x14\xeb\x9a\ -\x19-7(y\xfb+\xd1\x9d{m\x16\xed\x11}\x9a\ -.a^\xec\x0aH\x0e\x9a\xee9\x0e\xf4\xfb\xa3e\xa0\ -\xe70\x1d\x8c\x8a\xb7\x9c!\x87\xc9\x7f\xf0_\xa8\x90(\ -[\xc5\xad\x895E\x9bM\x0d\xb4\xc2:r\xa3\xd5h\ -\x14\x04l\xe6Q\x14\x10\xe2\x9d\xfclH\xf2\x89\xd1\xb6\ -\xddb1q\xf0\x0a\xf5\x96\x9eI\xb1\x81\xddG\xa9D\ -\x89H\xc3R\xb5\xe5\xc2\xb6\xed\xd2\x1e\xd1\xd0\xe4\xda\xd0\ -l\xe6\x98\xcf\x91\xc8,\xcb(\xbd\x80@NGqF\ -n\x05s\xb8\x13\xccA\x9c\x81q\xa9\x22\xc4\x04\x09\xdd\ -\x0ed\xf03\xfaQ~\xb9\xca\x92\xadT\xf9\xca\x961\ -{j\xeaF\xb229\xf8\x87)Cz \xfc8\xa2\ -\x12\xc2/\x22\xda!\xd6L\x00\xe9\x8b\xd18\x8a\xd7a\ -\x92\x00\xae\xd5\xcbQ\x14\xba#l\x105(\x959y\ -\xe6R\xf1\xf9$\x99S:Y\xdaP\x99\xd335\x9b\ -\x12[6\xa7\x84\xa4\x829%\x91|a\x0fMm\x86\ -LA\x17\x83\xf9\xf4;Z\xcf\x88\xe6\x18\xae\xf2\x84\xe9\ -B\xf9\xf4\xe6\xadh\xaaeUZd\xca\x0d\x06\x22\x86\ -o\xe7\xdd }\xde\x89\xe4\xfb\x9bf`\xf2\xda\xa3\x14\ -\xc61\xa8\xcb\x99M\xe7\x83\xd1j(\xf8:iUh\ -\xcf1\xab\x22\xce\xa6\x9d\x8d!\x94\xe0a\xff2U\x82\ -\xc3\xf6\xc7y\xaa\x0cG\x8d\x11%\xa7$\x0b\xfa\xf2@\ -,*\xee\x04{#n\x9eM\xb0Ey\xe5\x83!T\ -\xb6\xfd%$\x9e\x11\xd3\xb8\xa1\x8e\x87\xae\xcf\xf8\xbf\xc2\ -\x9e\xa4\xd4U\xa8'\x14=\xa7\xf4$\x10\xcd\x0f\x83\x91\ -\xb2\x1a\xa6Ij\xd1\xea\xc4 P\x0a\x07\xd2\xa1\xe0\x03\ -\x13\xc9S\xdbJ\x05\x80\x10A\xca\xb4/\xd3\xaf\xf2\x92\ -=\x18\xaay${\xd2\xaf]\xb2y\xb5s$\x82\xfb\ -\xa8y'E\x8f~%\xf4\x18t\xe8q\xdc\xe81h\ -\x1dz\x0c\xb2\xd0c\xd0\xa1G5\xf4\xe8\xd7\x83\x1e\x93\ -\x0e;\x8e\x18;&-\x03\x8e\x89\x1c6&\x1dh\xd4\ -\x06\x1a\x15\x16,\xa3A\xbfC\x8d\xe3E\x0d\x18\xdev\ -\xc1\x064X\x8a\x1b\xdb\xf7\x1dp\x94\x05\x8ea=\xd6\ -\x86\xda\xe1\xc6\x11[\x1bj\xcb\xac\x0dUnm\xa8\x1d\ -h\x14\x07\x8d\xeb3\xdf\xbf\x9a\x88\x01\x08K\xc9\x8a\x00\ -X\xe4\xb0b\x00\x83\xd103\x060\xe8\xb77\x06\x80\ --\xdb\xa3\xbd\xc7\xc0\xcf.\x0b\x01\x88(\xf7\x1d\x01`\ -n\xfc}\x04\x01\x86\xd2 \xc0y=A\x80\xce\x89w\ -\xcc\xaa\xb1m\x1e\xbc\x0c\xff]\xe7\xbd\xabhO\xab\xf5\ -\x80F\xbf3\xa8\x8f\x195\xfam\xb3\xa8\xfb\x19&u\ -\xbf\xb3\xa9+\x02\xc7y=\x0b\xf1\xfe\xa8\x03\x8ec\x06\ -\x8eQ\xdb\x80c\x94\x01\x1c\xa3\x0e8\x0e!\xdb`\xd2\ -\xb9\xfe\x8f\x198&ms\xfdO2\x5c\xff\x93\xce\xf5\ -_#pTX\xaa\x8c;\xe08f\xe0\x18\xb7\x0d8\ -\xc6\x19\xc01\xee\x80\xa3F\x1fG\x95\xa5J\x07\x1c\xc7\ -\xed\x19\xed\xb7\xcd5\xda\xcf\xf0\x8dv\xc0\xf1\xe2q\xc3\ -\x05\xd2\x0c{A\xac\xd8\xf6\xb4\xc3\x0f\x1eJ\xe0\xe5\xd0\ -c\x87\x9a\x07\xf8\xdd\xdbq^\x16=\x14\xd36\x1f?\ -\xfcm[c\xe3AC\xf5\xa4\xf9\xec]\xf5\xa0\xbcx\ -\x97\xfdN5\xd6\xa9\x1a\xd5\x969\xf1T\xb9\x0fO\xed\ -\x5cx\x87\xe1\xc2S\xfb\x1dj\x1c\xb1\x0bOm\x9b\x0b\ -O\xcdp\xe1\xa9\x9dA]\x118\xeaI\xfb\xbfP\xd5\ -\x0e8\x8e\x178`x\xdb\x05\x1c\xd0`)pl\xdf\ -w\xc0\xf1\xb2\xbe\xffI\x07\x1c\xc7mq\xa8m\xb38\ -\xd4\x0c\x8b\xa3\x03\x8e\x17w\xe1-\x89\xe7\x1e\x94\xfbn\ -\xa8^\x1cu\xee?g\xb8\xcci\x17\x22h\xdeSw\ -\xcb\x87\xbfq/\xdd\xf9I\xf3\x11\xac\xf3~w\xbc\xcf\ -\x11\xab?\x18\xdev\xa9?h\xb0T\xfdm\xdfw\xea\ -\xefe\xd3\xfbG\x1dp\x1c3p\x8c\xda\x06\x1c\xa3\x0c\ -\xe0\x18u\xc0Q\xa3\xa7\xae\x82\xc5q\xd1\xefrf\x8e\ -\xd9S\xd7o\x99\x8b\x1f\x1a,\xf7\xd4\xf5;\x17\xffA\ -\xb8\xf8\xd5\x0e8\x8e:\xa3\xa0m\xc0\xa1f\x00\x87\xda\ -\x01G\x8d\xc01\xac\xe2\xe3\xe8\x80\xe3\xa8}\x1c\xfd\xb6\ -\xf98\xfa\x19>\x8e\x0e8\x0e\x22\x1bi\xdc\x01\xc71\ -\x03\xc7\xb8m\xc01\xce\x00\x8eq\x07\x1c\x07\x92T\xd0\ -\xc1\xc6\x11\xa7\x14\xb4,\xa1@\x9eN\xd0\x01Fm\x80\ -Q~\x89\xb2|\x1e\x0d.;\xcc8Z\xcc\xb8\xfd\x1f\ -\x18\xdfV\xc1\x06o\xb1\x0c9B\x04\x1dx\xd4\x10\x8a\ -\x1dV\x89\xa8t\xa1\xd8\xa3\x8e\xa8\x0c\xdb\x16Q\x19f\ -DT\xbaPl\xd3)\x8c\xc2\xa7\xc9r\x05e\x0a\xbe\ -\xcc\xbeo\x13F\x91\x82|\x96\xbepS|\xb1\xa6\x15\ -\x91\x1b\xdbA\x0f\xc8A\x96\x8e\xdc\x9e\xbbv\xa1'\x91\ -\x84@+\xde\xd5F\xae\xd1\xbc\x0b:\xda\xd4=\x9a\xe7\ -\xa9\xf7hF\xa2\xef\xec_\xd7\xd6\x04z#>V\x1f\ -\x1c\xe2\xd9\xa1K5\xe7\x9b\xdf\x19\xb7j\x0ax\xa0\xc8\ -n\xec\xcd!\xf2\x85\x18q\x91\xac;o@1\xce\x82\ -/\x9e\xbb\x88jM{65t\xd7\xc0\x8eH\xe9\xc6\ -\x19A\x88y\x8fm\xa1\x86\x0d\xfa\xff\x89\xe8\x1a\xc5\xc4\ -R\xc8\x83\x82-\x97j\xa6\xe9\xff\x066)\x7f\x11\xc7\ -4\x94\x9f\xfe\xb0\x91\xf5\x1aQ\xed\xe7t,\x97bE\ -N\xb5\x11\x1a \xe5\x01\x14\x17r\xea\xa9/Ms\x94\ -Q\x1c)z\xc3o\xae,\xc97L\x91\xaa;$\xbd\ -J\x03\xdc\x14\xbc\xcd{\xc3D\x5c\xde\xde,\x90\xfe\x18\ -\x9ar\xfal\xaay\x94\x80\x5c8\xb4\x1e\x81\xbbcE\ -)|\x12B\xad\x18YTyZ K\xd1l\xdb\xc4\ -\x81,\xf2\xea\xdc\xfdH\xdb+\xe8\x9ebj\x9e\xa5/\ -\x22\xadj\x8d\xec\xfd\xef|\x89,O&{a\x8a\xbd\ -\xca^\xbf\x90\xec}\xc2\x16zg\xe0-\xa2\x9a\xa8e\ -HW\x9aOj\xd59\xea.\xc8\xd3\x14d\xa7\x1eN\ -}|P\xd8t\x80Z\x90\x11\xcc\x09`\xd7Z\x81r\ -,`\x9d\xe2[0\x0au\xe0\x99f\x19\xdbi\x8cM\ -S\x99!6\x99\xe0cc?\xd3\xf7\x0ez\xae|\xf8\ -\xf3\xa3\x0f\x22\x1c8\xea\xaaz\x0fsw\x85\xd1S\x0f\ -~\xe9H3\xc10\x5c\xc2z\x0d\xeb\xb2\xa9,\xf9`\ -\xaf3{PUb\xb9xMW\xa8\xa6\xc9\xcdQ\x9c\ -\x97\x19\x08,\x94\xec\xb2\xc9mx\xec\xbd/\x18\x9e\xbd\ -G\x95\x22hLk\xc4\xf2\xf9\xc1]\xf6\x1c4#\x84\ -\xca\x841A\xf6R\x22X\xc1\x90\xb6\xd7\xbe(\xd6#\ -\x86\x5c\xd0\x15\xcf64\x8a\x5c0b\x1dE\xb6\xda\xa8\ -Y\xec\xfc\xcaY\xa5A\x03\xda\x05\x83\xb0D\x86\x92\x16\ -\x99\xe8\x17\xa1k\x5c\xe2\xc4\x9e\x8b\x9c.\x8a\x9c\x88\x99\ -w\xdd;U+\xae|\xd1\xcc\x9bW]\xf9~\x87\x86\ -DW\xbe\x80n\x14,w3X\xfd\xaa\xe2\xd5o\x19\ -%a\xea\xc6\xd4\xd5\x1d\x84,0pjZ\x7f\xdcj\ -\x8f\x88\xddn\xa4\xec\x0aV\x10taM\xf1\x12\xf9V\ -\x84?}\xc0\x1c\x9c\x13b\xf0\x09Ea\x04f&H\ -\x1d@\x1d\x14\xb2\xa7\x85\xf0\x9d\xb6\x8a7\xb55S\x1a\ -\x93S\x1b\xdaK\x1eL\xcdA\xe1\x7few_I\xbf\ -\xd9\x93r)#\xa7 >3\xe2\xa2\xba\xd6)\xf39\ -3Y\x96\xc4A\x0a\x08\xa2\xf6\xe2r\xf8\x86\x98&\xd2\ -\xa9\xdf\x22\x93\xcc\xdb\xa3Xt[\xba0\xde\xbe>`\ -\xd92\x18hO\x91\xa5\xcd\xcc\xa3\x15\xb0w\xbcw\x0a\ -\xd7O\x0a\xd5f\xed2\x5cL\xec\xd2\x9e\x81\xa8\x86M\ -7\xd3zI\x12\x1f\x8a\xec\x09-d\xdd\x9f\xfaS&\ -&'\xf5!\x09\x17j.{\xad\x19\xea\x052\xed\x9e\ -6\x03\x0bG6\xc6q\xaaV\xda\xa7\x83\xa2\xf6\xe9l\ -\xca\xc2\xc9n5\xeb\xf4=+\xa2\xd1\xb8\x8c*\x8b\xcb\ -\x9c\x17ZN\x0a\x81\xda\x98\xa6\xc4\xf6\x8bN\x13\xcfE\ -\x8ak#\x1dk\xa6\xc2\x8a\xe4\xd0\xfc\xbe7\xb8P\xbe\ -c(Gy\xfb\xee\xad\xf2\x13\xb1\xcc\xb5\xf2a0\xf9\ -\xb95S\xc8\x80\xfe\x90y\x8f\xf5\xbe\xa7YF\x8fu\ -M6\x99\xd2\xe9\xf7\xeahP\x0bI\x86\xc0\x8b\xcd\xda\ -=e\xbfj\x10\x0d\xd6qbj\xa7\x94>\xec\xd7G\ -]\xcc\xe3\xf7\x89\x9fB\x13>\x92f:\xac\xa1\xf7\xb7\ -\xc8\xc0\xde\xf2j\xbf=\x1fV\xed\xb9ZC\xcf\xef`\ -~\x98W/6\xe49\x04\xff\xce\xc4\x06r6=_\ -\xb8\xd3%\x1f\xac\xbc\x98H\x1c\x16D\xe0\x11\x19!\x1f\ -\x90\xe5-o\xbe\xd2\xab\xab?v\x84WW\xbf\xc1g\ -\xff\x81\x0a4\xf3\xfa\x8cST\xb3S\xb1\xfe\xf8\x85\xb8\ -8\xa3\x11~O\xaf\xae\xeeC\xe4\xfe/\xf7\xd5\x8c\xac\ -P]M\xf9hQ\xe4\xac4S\xd8\x14\xa8a\x86\x9c\ -\x9b\x01\x80\xa7\xff\xdf\x01F\xaa\x04s\xe1\xbc\x86\xb9\xf0\ -\x19\xa8\xf6<\x15\xfa\x15\xfb]C\xaf?i\xce\xfc\x05\ -\xbb]\x06\x01L\xd6\xe4\x0e\x00\x8e\x09\x00\x86\xd5$\xc2\ -ej\xac\x93\x88c\x92\x08\xf9Fw94\xfa\x08Q\ -\x038\xf6_\xcc2*\xdeg\xdf.j_\xa7\x87U\ -:\xcd'~;\xfa\x5c\x9bKeXo\xdakr\x05\ -U8\xf1\xb5\xf7\xfa\xe3\x1fw\x8d\xfaX\xc6'M\xe6\ -\x22\xce0\x01\xab\x02\xafj\xf2\x84\x7fCs\x0f\x10H\ -q\x90\x894\x17)\xc4QX\xe1\xdb\xe4\x91\x9f,\x84\ -\x0ce\x8e\xe9&a\x0c\x19{\xf2\x88\xff\x09\xad\xe1M\ -\xd9\x0c\xda\xa6MW\xad\xf1\xf6\x00\xdbd\xce\x9d\xed\xeb\ -\x97\xcbHL\x9f\x92\xf9\xfc:L\x1a\x1bIO\xdc\x0e\ -:\xb6\x14\x16\x046\x94\x0fP\x8c\xfbbp?(\xcd\ -\x9e\xbc\x93\xd5\x8fo\x19B\x06\xcd\x80y7\x0f\x9a\xe9\ -\xf2\x0dM\xf0\x7f\xb5\x99\x97#\x99\xccZ+`ca\ -`;f3!\xd8\xbaq\xa5\xcc\x1c\xcd\xd2\x17\xbf(\ -T\x9b\xff\x02\xccY.A\x86\x95;\xc4C\x1a,\x11\ -\xd2\x86Y\xe3*\xef>\xdf\xbf\xfbvz\xc8\xde\xb9\x94\ -,o?\xef\x81\x8f[\x13Yy\x11\x1c;\x80\xc4<\ -\x992\xecr\xf2\xf6\xb0\x16\x10F\x1c[\x01\xaae\xf6\ -\xb4\xf8\x95\xb7rcKo\x85\x89\x89h\xf6\xfe\x96\x08\ -\xe1Ke\x83V\x91\xbc\xc6\x93Ak\x04\x9d\xe3\xcd\x07\ -\xb5\x10}\x22\xcecO\xd7\x1cC&tI\xba\x97\xda\ -ZUI\xe6\x1cdk\xf9\x10/c\xc4\xbf\xf1\x82\xda\ -\x13\x0fF\xc8\xc6V\xcf\xef\xbe4\x10\x9c$lOb\ -\x85$||\x0d\xab\x0f\x1d9\xb1<\xda;\xfe0{\ -\xb5/s\x8f\xa6\xf8F\xbf\x07U\x08\xdd\x91\xe9\x0e\x80\ -X\xc5l\xbf\xf8o\xd8\x02[\xdf\xa5\x06\x0c\x82\xc8\xe6\ -\x14\xef]\xdf\x9e\xc6\x90\xb6m}\xb3e\xfdrl\xd9\x1e\xed\xcd\xb5%L\xef\x17\xd8A\ -\xfe\xa1\xf7;t\xb0\xa9\xfd\xe3\xc3\x93\x1cS(\xbcj\ -W3\x1ci\xf7lM\x19\x1b\xa5\xa7`\x90\xce\x0a\xcc\ -\xe0\xf3\x9c\xd5\xc7:\xfb[\x22S~\xb1\x0dM\x04\xcf\ -\xe3b,T8\xf9\xf2\xf4l\xd1UM\xb9\x8d\x96]\ -\x82\x1e\xdb\xec\xc7W\xb4` \xeb\xc84\x15X2=\ --\xc0\xaac\xbcHU-2\xd4\xcd\xa7\xc4\x22-\xd8\ -T\x5cS\x95)\xba\xac\x84*K\xd1d\xc8\xc0\xb4g\ -x\xfe\x0efi\x8e\xbb\x882M\x97I\xee\xb0J\xb9\ -\xfbK\xa8\xc8J\x0b\x95\xab\x89|7\xc5\x85\x8a\xefc\ -\xd0=\xc7a\xbbDmS\xb3\xe0\x17\xb1\x1e\xf0\xdcs\ -\xb8^\xda\x83T%\x9b\xd0\x0a\xb92\x88\xee-\xa1\xc9\ -=6\x14=\xcd4\xa5V\x92\x98\xf8\x00\xa4K\x90\x07\ -2\xaeE\xb0\xd8\xe6_?\xd6\xc9V\xf8\xae7\x9f#\ -\x97\x01\x170\xde3%'\x08\xd4'X\x9f\xb7\xb5\x07\ -u^\xd5Q\xa9f\xe2\xb9\xc5\xc6RX3\x8c\x0c\xb3\ -\xec^m\x88\xde\x9b\xda<\xf8\xf9\x8d\x99L\x7f\xa7\xbd\ -\xbdw4lB\xd3R\x09\xbe\xbfA,\xc0\x0c](\ -$0\x89\xf6\xcf<\xc3X\x8b\xda\xae\x07\xbcqmP\ -YK\xdbD\xbc6\xbd0\xc7j\x17\xd1;X`\x84\ -<\xa2\xe1\xf6eK\xaa\xfcx\xb2\xb4c\x9c\x02cx\ -\xd4O?\xc3i{\xff\xe1\xc5x<\x1e\x0e\xd2/A\ -L;\xc5\xa9\x88\xa0\x1f\xc4t\x03\xcb\x96\xb1Rx\xbd\ -bVzC\x91j\xfc\x11\x93T\xc3V \xd5\xebY\ -i\xa6\x87$\xb5\x0c\xcb\xd4R@\xf8\x85\xabX\xb9\xb5\ -\xdb/g\xedJM\xfb\x89\xd0\xd2\xcd\x91Z\x97C\x93\ -\x5c\xd4\xa1I\xee\xd76b\x06\xa7\x8b4G_(\xa0\ -<\x99\x89B\x1d\xe8=\xf7\xa0mL\x07\x0d;\xba\xa3\ -=\xd0_\xfc\x9d\xa2\xbc\x17[s\x19S\x97W\xa8`\ -\x17\xbe\xb61\x88\xbd\x01[\xc7F\xe5\ -\x1e\xb8|\x10S\xb7\xab\xd4WQ\x89\xd0s\xc6\xb6\x9c\ -\xdcUK7\xe4T\xd9\x8dS\xe3\xbc\x1b\x94\x8cW\x02\ -n\x84sh)\x12h\x81\xbc\xd6\xb6\xd8\xd6\xceki\ -\xe7\xbeq \xeb\xb6\x01\xa1\xc5\x9e{\xb0a\xc5\x8a\xfe\ -r4\xfb\x96\x18(m\xb07\x5c\xbb\xba\xfa\x14\xa2\xbe\ -\xba\xfaL\xd8\xff\x15\x85\x0d\xca\xe6[\xae4\x9d\xc9\x10\ -[.\xbb\x02d\x0fV\xe5\xf7Ij\xde(\x90:]\ -G.\xb7\xa1_\xaf\x7fGk\xbe\x06\xf8;\xff'\xb7\ -\xc4sQ:={\xf8\x1a\x04\xcfEN\xe8\x9d\x9c\xde\ -\xcfZ\xd6r\xb6(\xfe\x05o\x90\xc8U\xd0\x8c\xf2\x1a\ -\x16W\xd2\x93JJz\xd0oF9\xe72\x0e\x13O\ -b\xe5\xc4\xe2\x19\xc5\xd3\x0e\xa2\x07\x12$\xc2#\x89\xd8\ -\xb0C\xe6,\xb1\xfd\xb5\xb6\xb5\x0f\xec\xe0\xd1L\x8bE\ -G\xf2h\xbc\x8d\x1a\x12k\xa1\x14\x0e\x8b\x86/X\x96\ -\xc6\x8b\x97\xee\x17\x10\x17/\xb2\xd0\xe3\x83\x97\xcd'a\ -\x0c=yrz\xbe\xd5U\xf4\xbct\xc9\x99\xe4\x05\x18\ -&\xab\xa2J\xd9\x828x\xc1\x18xJ\xfc\x9bm\x95\ -\xd4z\xb0P_\xcf4\xfd\xb1\xc7\x99)\x0b\x81\xa7\xd3\ -\x8b\x16F\xfb\x97\x05b\xcbEA\xbc\x0d\xa6\x8cD\x17\ -\x962b7-d\xc4n\x87\x8c\x11\xbb\x90\x88m\xc8\ -\x0fA\xc2t3q\x0ce19x\xf7\x8c\xa9\xe4\xcc\ -\xe2\xeab\xf0\x86\xb5\xf0 \xe5\xc0?\xd5\xbe\xe7.<\ -j\x90'K&\x03B\xd2Z\xc7?a(D\x09b\ -\xaf\xc3/#\xaf\x225\xc5%\xe8\x16,\xe3\x90Ng\ -wD\xec\xf4y\x9c\xedsD\x96\x88:[\x17\xe8\xb5\ -\x03\xc6\xe0\xb69\xcfL\x99?o\x7f\xae\xd9\xcfm\x97\ -\x83<\x87\xc98\x9e\xe8\xb0\xc9nP\xd5X^\xc3\xf5\ -\xd9\xae\xf48\x0bE\xbd\x08w\xe1=\xdeY\x04\xf2\xfd\ -\xd1[\x8f\x0c|\x11\x93\xc8\xc4\xb8]k\x86\xe1\x1b\xc4\ -\x9b0]\xa0\xd9\xcfd\x04\x00\xf7\xa9\xef]dk\x8e\ -F\x89#+\x02\x04\x1aQX\x04>h,\xbfBZ\ -\x99\xb6B\xbeG\xbbb\x95?<\xbc\xedUTP\xb3\ -8\xff\x1b2\xedb\x9cg_\x94\xe0\xbc\x83l\xe2\xd0\ -)v]\x0f\xc9\xbab`W'\x8eQ\x91!\xfc4\ -G\xff\xa8\xf8l\xb2\x1f\xb4bm\xfe\x91\xf4\xc1\x86\x1d\ -\x19!\xdf9\x92\x83\xce \x16\x90\x94\x1b\xd1\xef\x18=\ -\x15\x1bQ\xf6E\xe6\x88f\xd4z\x0f\x1a\x0a\x80h\xca\ -\x01uW\x83\xfc\xac\x83m\xf4\xce\xffXq\xe9:1\ -\xab\x05p,`\x18\xafv\xcaNW\xdc%\x89\x0b\xc8\ -\x98\x8e\xcbI5C.6P6\x9dg1\x17\xecv\ -,\xa3Z\x22\x8bk\x11\x17INf\xb1oJ\xf1h\ -\x09\x1fN}-(\xed\x16\xa734\xe71\x9b\xcad\ -\xf8\x9f\xday\x01\xe0\xb1+o\xa8?\xda\xe9\xf2\x9f\x94\ -\xa7*\xd3s\xcb\xe7js\xdc\xbf\xad'\xb2\x0d!\x8d\ -\xca@+\xac\xa7\xcd^Q\xf3\xb8\xfa;\x93\x10\xf09\ --#\xe00~\x96m>\xc0\xaa\x91za\xa7\x80\xcb\ -\x1f\xec\x86#\xe1\xde\x84q\x08\x91o\xc6Nlo<\ -a\x0bL\xab\xfb\xb0\xdcF.\xf0S\xd8\xe7\xb1\x8c\xc3\ -\x84\xa9\x10\x0f!\x90U8\x82(\x0e\x1bf\x15\x12\xbf\ -\xb13\x92\xdd\x19\x98:\xea0\xcd\xd2\x19&,\x9d\xdd\ -\xe7\x89\x9a\x13\x814\x9f\x81\xaf\x1c\xb4=\x8b\xd9\xf7\x81\ -\xde\x13\xfb~\xf7.\xec\xf2L\xc4\xd1\xd2\x0a}\x0d\x1f\ ->F9\x93Xp\x0a\x0a\x93[E\x19FQ\x96\xf5\ -\x919\xb9r\xd9Ay\x95lN\x1d[\xaeU\x89\x19\ -\x9fs\xc2\x97\xa9Ld\x1ee[G\xd9\xa6C\x99\xb6\ -$\x8d')\xa6\xbc%\xfac4\x14nN\ -~\x0c-\x8a\xe39\x00%w\x12\xc6\x16\xb4Y\xed\x88\ -\xb9\x15\x02\xac>\xcb\xf7\xf1\x83I4v\xdd@&\xfe\ -d\x14\x83@\x019\xbb\x94\x1e?0\xb3\x93\xa9\xab\xab\ -\xdd\xff\xef}\xda\xf0#\xe6\x9a`\xfa\xe1\xef\xfc\x9f\xbc\ -g\x0d/\xf8\xcd\xad\xaf\x85B\xd1\x93\xac~i\xa6I\ -\x9e\x90\xc1\xb0=\xd6\xb7H]\xec=K\xe64\xa3\x8f\ -\xdc\x025I\xb4\xae\xbf\xf7S\x09rE2\x14o\x5c\ -\xc9\x18\x91\x16m\x8b\xde\xe4\x8dE\x03\x01I5#M\ -\x96\xd9\x95\xfd\x86X\x14\x85\xce\xa1/|u\xd1.\xce\ -\x14u\xbf\xe5>\xa1-\x9c\xcf\x9cy8\xdb\xf6\xbaE\ -6\x15E\xfb\x86D\xde\xa3b\x190\xfdD\xa0\xc7\x8f\ -\xad\x8d\xd3\x12C\xb2\x0f\xf0D\x94\xe9x\x8a^\xcc\x91\ -\x9d\x9e{P&\xf3 \xafG3=\xeb\xa0|\xceA\ -\x81\xbaS\xce\xfd\x94\xef\x89\xa9\xe8}\x96n~\x1eJ\ -\xc5\xe6\x9bf`\x12\xf5N;\xb3\xe9Js0\x13\x0b\ -\x10 d\x83\x91\xe6\xb9\x07\x1a\x0d\xf9\x83]\xad\x80-\ -\xdd\xe1\xa7\x02\xf2\x18&\xdf\xf0\xf4\x84\xa9\xbe8\xfd\xe7\ -?^\xad\x00\x03\xf9\x955,!x\xd3-\x85uK\ -y\xb4\xc8\xcce'\x09\xda\x84\x81\x11fnS\xe4\xb8\ -\x0a>E\xa7\xca\x8aq\x92\x9f38s\x98\xc2\xb7\x90\ -\xeb\x9e6\xe4i\xff\x1ei\x16\xf4\xe6 \xbd\xee<\x01\ -\x11\xecF\x99\xbb=J\xd3@\x9c%\xc8\xdaI=D\ -MzN\x87zR/\x5cI\xce\xe8\xc89X\xd9\xe7\ -s\x88\xb6$f\x9c\xcd\x91u2\x87`\x03b\xda\xa8\ -$\xce\xe4\x90\x8d\xcaE}\xf8c{\xeeb:\xf3\x9f\ -\x1e&\xf0\xb0c?\x19\xa4\xb0\x96*~K\x19X\x04\ -\xfb\x0f\x18\x8c\x00\x04-\x14~\xf5\xcbP\xe1z\xb81\ -\xfc\xf8\xb2k\xc3A\x22\xc7\xef\x98R\xb4\xf8\x02\xf6\x10\ -\x92\x1e\x1e\x94\xa4k\x0cA\xc6\xa9\x00\x92K>_\xde\ -\xb6\xcaH\x12\x80\x1e\x10\x0b)\xb0\xec\x07\x84\xe2'\xe7\ -\xfa\xba\x91\x89,[\xa4\x83\x90>\xa2\xd3\xe6\xb2T\xe8\ -aF\x8eY\x0c\x18\x16\x82F|)\x9dE\xd6\x98\x1c\ -\x8e\x9a\xb2\xd9\x96\xd8:l\xa3\xcd@\xc7d\xb4Ao\ -\x0e\xd7hs\xd0\x12\x965\x99v[\x98\xac1\x81W\ -\xeb\x13x}\xad\x9b\x87\x0a\xc0oX\xdb\x14\xbap\x88\ -7\xf7w&r1w\x95\x07\xec\xb8t\xb7bag\ -\x11S\xb6)q3\x1d~Q\xd8 (,c\x89\xbf\ -\x84\x19@\x839a\xe2\xed\x9cX\x12(\xc4\x9f/P\ -&\xa3\xf3\xe7\x05\xb79\x1e\xd8\xde5_,\x99\xa1\xd7\ -\xd4\x04\xf0\xbb\xe8\x1e,\xd6?:\xfc`\x10\xcdA\x06\ -\xf0\x5c&\xfd\x22\xca\xc6&\xc0\xb0\xbe\x09\xc0\x07\xda\x87\ -{\x10\x9fV\x80\xbd\x1d\xf8[\xe2x\x1f\x96m\xcf\xa4\ -\xb8\x07\x84\x01\xe5\x0b\x8b\xf9\xfb]5\x87\x0a\xf2s\xd2\ -\xb3\x1d\xb4\xc2\xc4\x93\x8ay\x82\xac\xb9\xf5y#2\x0e\ -\xa0\xd9\x0a/T\xabe\xfcP\xbdO \xbc\x16t \ -C\xbew$\x8d\xc9v\xbf>\xd9\xf6#\xb0\x07*\xd3\ -\xf7d>\x07i\x9d!\xfa\x84\xc0>\xd9\x08\xb5\x9be\ -\x9a\xd0'\xd2\xe3F\x81@\xa8\x9b\x92_\xbf\xad\x07)\ -\xb7\x9b\xe3\x13\xa5\xe6w\x8c\xa81\xd9\x9d\xd4h|{\ -.%\xcb\x97\x93]\x89]\xca[v\x90\xc2`\xf3\xad\ -z:\xeaAI\x9et\xef\x82\x88\xb29u]\x0a\xd3\ -\x04\xf7\xc8\xecW(\xca%\xe7G\xbf\x89%\xeb\x97\x8b\ -%_\x94\x8b%?\xb0\x91\xa7\xe2\x9b\xa2\xf2\x04\x943\ -\x83\xe4\xe7\x856\x0f\xc6\xae\x81c\x87\xde\xce\x89\xb3>\ -)=\x0f\x83\x02\xae\x0aL\xc5Z\xf6\xdb\xc4:b \ -Ww\xb0\x9d\xadj%}y\xbb+\xe3\xa5\xbb\x83\x0d\ -\xe6\xf6z\xc0\xc8)\xdd\x9b\x8f\xdb\x22^\xba3\x8ef\ -\xcdQ\xe9~|c_7\xdf\x05IH\xb1\x0b(\xd6\ -\x1dP,\x86\xd8Q\xeah\xc2b\xe1\xec\xc5 \xa1\xb3\ -\x89\xec\xbd\xc7`\xdf~\x1d\xf9{\xedO\xc1k*\xa1\ -\xee3\x89>\xa9'\x9d\xee-\x17\x0b%\xb9_\xe6\xc0\ -r\xe9v9q\x85\x0d\x85Q\xcel\xba\x18zo\xa4\ -Zf\xfe\xc4\xd0;\x9am\x9a\x82\x14\xf5LyY\xae\ -u\xfa\x86\x81\xf8\xec\xce2\xf8\xd3\xaf\xd4\x5cx\xb3\x1e\ -\xd8\x1e\x8f\x19\xbb\x94E\x94\xc5\xf2yC,\x0e]/\ -\x04\x9dUxg\xa5B\x0bR\xc7\xd9$dY8%\ -\xbcq\x8e\xf9\x99\xfeO\x0b,\xbf\x95!AV\x99W\ -\xafX/E;\xa93S\xcaAI\x7f#!\xc0\xf0\ -\x95\xfa+\xddW\xe6\xb7\xc1\xeb\xab+^\x03\xfb7\xba\ -\xdf\xa3\xe8@\xfc\xa0\xcd\x8f\xc2\x0f\xa9\x87\xed\x07\xad\x95\ -\xe7_i\x93\x0c\xffZ\x89\xe5\xd1\x8d'\x8d\xf3\x9d\x1f\ -\xf1\xe7\xa0\x07\xf8z!\x1b\x81$]\xe5\xb1\xf07i\ -\x09/\x9e+\xb7\x95 \xb8\xce.\x7f\xb9\xd2\x81\xe0\xfb\ -\x8c\x1a\xe7\x7f\xadG\x0a\x94\x19\x85\xaf\xd0\xcdZ\x98\x9f\ -v.DVq\xee\x024\x86\xee%\x1a\xf6\x86:\xe6\ -\xbf\xbe\x96\x1f\xbf\xc8\xeeOq\xd5\xfc&\xc7\xea\xfb\xfd\ -x1;\xcfR\xf9M\x835\xceif\xb8d\xcd\xe7\ -\x1dMe)\xe2\xf7>\x04\xcc.?d\xb1\xb3\x0c\x1a\ -g\x14\xbfi\xc9\x03\x03<\xf3:\xa6\x1dQ\x0d&\x12\ -k0%\xca\xa6\x9f\xe5\xf9\x15\xec\xbek\x9cOT{\ -Fn\xef\x01[\x9a\xa5#i\xa8WDY]Q\xf0\ -nVD\x02\xd9\x16\xc1\x9ap\xa0F\x8e\xa7\xee\xbd\xcb\ -\xa4\xabg*\x8b\xae\xf1+\x0b\xe4\xafL\xfa\xaf\x0f\x15\ -GO\xea\x229\xd4\xe1\x13:_rP\xd63\x84\xbe\ -\xfb\xa0\x16\xd5^\xba<\x99H\xbc\xad \x12\xbb\x1d\xdc\ -\xcd/\x0f\xeb\xbe_\xad\xd4\x80\xb2\xbb\xe9\xbe$\xef\xa4\ -+;\x9e\x19W\xddU2\xd9\xee*\xe8\xb3`\xbfy\ -\xf3\x83\xeaW$\x1d\xca0Iu\x15\xe6\x97V\xcb\xe8\ -\x05e)w\xc8Y\xa1\x0a\xd6V\xf8\xdc\xc9\x06y\xdd\ -\xd0\x01\x8d\xa5\xa6Q\xf2\x14\xcb\xb23(\xf5\xc8\xcdb\ -#\xb0=\xed1#Z]\xd2\xd7\xde\xe40\xd6q\x06\ -b\xb9A\x8c\x9f\x12Yz\x0cS\x0e\xb4,2\x84\x91\ -\xf3?\x1a\x1f\x84\x9an\xbd/\xc3\xf6\xd7\x1f\xff\xb8k\ -\xc6Y\xd3\xcb]\xb4t$B\x87r5j&\x8a\x98\ -\xc3\xc2s.\xdfsW\xbe\xfd\xbb\xd3\xc2\xf6\xde|v\ -vwv\xeb\xf3\x0el\xbe\xd2\xb2y\x11\x9c\x89\xf62\ -\xdc\xf0+\xaf\x8f\x1f9\xca\xcb\xe6\x88\x7f\xfa\xdb\xcb0\ -\x84\xd7]\xbe\xfd\xa1\x03\xdc\xda\xb2\x88\xe3[j5\x97\ -f$P\x86h*\x83\xec'\xc6\xa0Z\x84\x8e\x97\xa4\ -$O\xef+\xeej\xf5/\xc8\xeb\ -a\x8b\xe5\x0ad:f\x05\xd4\xd5-L\xce\xb5zl\ -L^T\xb1\xa1\x0cg\x13\x5co\x18\xe9\xfad\xd8\xd2\ -M\xcf@\x8aIt\x9e\xba\x15\xe3\xef\x99\xff}\xe4\xa3\ -k`\x87\x85x\xe9A!\xbb\x07A[\x5c\xc4\xc0\xfd\ -fs:8K_\xe1\x0f\x82\xb7xni\xe6\x0dX\ -\xca,\xca\xf1\x13\xbb\xaa\xcd\x7f\xe2\xbfv\x90\x8e0p\ -\xff\xe6+}\xab\xbb\xfc\x5cf\xffw\xf0\xb5I\xe8\x0d\ -/\x96\x7f\xc9~\xf9/\x16\xec\xbe\x98\x0d\xbb\xd8\x0f\xc5\ -\xbf\x01\xcfo:\xbf\xa2\xe3$tz\xf4\xc5\xe5$z\ -~\xf4\xc5\xc5xw\x82\xf4\xf5\x19+AP\x9a\x81\x5c\ -\x8a-\xce\xabD\x91\xe7\x83X\x91jZ\x91\xfe\xff\x01\ -\xfb\xceb\xfcK\xe5\xe76[]\xccP\xca7\x0f\x18\ -?\xb1\xa9\x96\xca\xd4mr\xb3\x98\xb1 \xe7\xef\xfc\x95\ -\xe2\xb6\x98\xd2\x1c\xbe\xbc\x8c\x9d\xd0\xad\x8e\xaar8Y\ -\xe4\xe5\xa8f\x0eoOD\xa8\xc0\xe4\xf0\xa1U\xcd\xf3\ -y<\x19\xc6\x982\xac\xca\xe7\xc9(\xceguP3\ -\x9f\xe7\x13~\xe3MY\x16\xcfg\xfc\xa287\x95\xbd\ -o\xb1[\x13\x7f\x07c5\xca\x8c\xa1z^\x91\xbfC\ -5\x86\x14\xc3\xda\x91b>\xe8\xab\xed\xe0\xef\xf9(\x0e\ -\x9b\xe7\xe3V\xf0w\xd4R\xf9=\xbf\xe8\xb7\x81\xbf\x83\ -\x96\x8ao[\xd8\xdbV\xf8m\x07<\xa8\xfd\x96\xf0W\ -\x1d\x8c\xda\xa8\xde\xd4\xb6\xa2\xefp\xdc\x06\xf6\x9e\xb7E\ -|G\xe7\xad\xb4\xce\xce\xfb\xc3\x96\xc8o\x7f\xd0F\xf5\ -6j\x0b\x7f\x13\xf0\xdb\x0e\xfe^\xb4\x05\x1f\x12\xf2\xdb\ -\x0e|\xb8h\x8b\xfc&\xf0\xb7%\xf2\xab\xb6uu\xdc\ -\x0e\xfba\xdcZ|h\xc7\xf2b\xdc\x96\xe5[R~\ -[\x81\xbf\x93\x96Z\x0f\xed\x90\xde\x89\xdaV\xe7\xc3\xf9\ -\xb0\x1d\xfcm\xabvk\x05\x7f\x97\xcf\xa3\xc1eK\xcd\ -\xb3\xc3\x07\x88\x85;5\xd0\xcc\x9bs\x1eM\xd9\x89\x1c\ -bV\xbb\xfc\xfa\x93[\xb2\x02>A5\xe9!O\xd6\ -\x81\xe9$\x95\xd9\x9f\xbd\xe5\xe6\xfb\xd2l\x1e\xaa\x97\xb1\ -hr\xff\xb2\x22\x9b/\xc6\xa3x\x91\x93\xe2l\x0e\xff\ -f\x14\xd7g\x1e\x86?\xff\x0f\x85jM0\ +\x01`?x\xda\xed]Is\xe38\xb2\xbeO\xc4\xfc\ +\x07\x86O\xdd1-k\xa1dY\x0e\xb5'j\xef\x8a\ +.WW\x95\xdd\xd5\xef\xa6\xa0HH\xc2\x98\x22X$\ +(Y\x13}z\xff\xed\xfd\xaf\x07\x80\x14\xc5\x05\x04w\ +IT\xf0d\x8bLbI$>$2\x13\x89\xe9\xbf\ +_\xd6\xba\xb4\x01\x96\x0d\x91\xf1\xebU\xff\xbaw%\x01\ +CE\x1a4\x96\xbf^\xfd\xf9\xf4\xbes{\xf5\xef\xfb\ +\x7f\xfec\xea\xc0\x03\xd5\x90P\x91g\xd2Tq\xf0\x0a\ +Y\xf7\x0fP])\xff\xf7\xbf\xd2\x17\x9d\xfc\x83\x95i\ +\xd7{NIT]\xb1\xed\xfb\xaf\xf8\xadjO\xbb\xee\ +\x0f\xfax\x0b\xb5%\xc0\x12{\xf0\xeb\xd5\xd7\x07\x05\x1a\ +\x7fACC\xdb+\xc9P\xd6\x80<\xa2_\xb0Z\xa4\ +\xa9i!\x13Xx\xe7\xbdZ\x02\xb4\x06\xd8\xda\xb9o\ +\xa5\xa9\x05T\xec\xfe+M_\xee{\xd3\xee\xcb\xfe\xd7\ +\x8e\xfe\xda\xed\x7f\x91:\xf1\xea~2&\xcf\xdc\x7f\xbd\ +\xe7+\x00\x97+|?\xee\x91\x17\xde\xffn\xc1]\xbf\ +\xe4iw\xdf\x06n\x8b\xd6\xd0\x80kg\xfd\x08\xff\x0b\ +\xf6\x8d\xb2\xc9\xff\xe1\x8aG\xbd\xec\x15\xfb_\xa7T\xbc\ +e<{\x82X?T\x8c-2v\xf7o\xdf<\x9a\ +;R\x90\xfb+sQ\x1fUd\xecK\x82\xe4\x7f\x9b\ +\x0c\x92\x05l\xe4X*\xa1\xb9\xbe\xee\xfe\xc0K\x07^\ +\xff\xb0\xd4\xab}/\x0cd\xad\x15\x1d-\x16\xf7w]\ +\xf6I\x17\xae\x97]M\xb5\xcd\xddl\xbb\x82\x18\x5c\xdb\ +\x9b\xe5\xb4\x9b\x91\xcc\xab\x94\xdb\xe2\x88\xd0\xfc\xc5~\xee\ +\x05F\x05\x06\xb6\x14\xdd\xa5\xd9wAWv\xc89|\ +\xf1\xc1\x82\xda'\xf6h\xff\xd5\xf2\xf0d\xdf\x1f\xd2\x94\ +\xb5d\xa1\xed\xafWd.\xa8Hw\xd6\x06\xfd\xd7{\ +\x1d+\xf3\xfbk\xf4\x12.\x93\xcc\x13\x0cUE\x0f\x97\ +\xeb\x95\xec\xff\x8au\xe7I\x99\x87{\x84\xb7\xb35\x99\ +\x17\x87\x02\xe2\x83\xa6:\x96E\xfa\xfd\xd1\xd0\xc0K\x90\ +\x8e\x8c\x8a\xb3\x9e\x03\x8b\xca\xbf\xf7_\xa0\x900[\xf9\ +\xad\x894E\x99\xcf4\xb0\x81*\xb0\xc3\xd5(\x98\x08\ +\xd8\xdc\xc1\xc0#\x84\x07\xf9\xd9\x93d\x13#\xbf\xdd|\ +1\xb1\xe0\x06t\xd6\x8e\x8e\xa1\x06\xedg\xa1D\xf1H\ +\x83R\xe5s\xc1o\xbb\xb0G80\xb9\xf64\xfb9\ +\xe6r$4\xcbRJ\xcf!\x90\xb3Q\x94\x91\xbe`\ +\x0e\x0e\x82\xd9\x8f20*U\x08\xe9DB\xfd\x81\xf4\ +~\x86?\xca.Wi\xb2\x95(_\xe92f\xcet\ +U\x8bW&\x06\xff e`\x1d\x08>\x0e-\x09\xc1\ +\x17\xa1\xd5!\xd2L\x02\xd27\xa3q\x18\xaf\x83$\x1e\ +\x5c\xcb\xb7\xa30t\x87\xd8\xc0kP\x22s\xb2\xcc\xa5\ +\xfc\xf3I0\xa7T\xb46IeVGWL\x8cL\ +\xd1\x9c\xe2\x92r\xe6\x94@\xf2\xb9=\xd4\x959\xd09\ +]\xf4\xe6\xd3\xef`7G\x8a\xa5\xd9\xd2\x16\xe2\x95\xf4\ +\xe9\xcd[\xdeTK\xab4\xcf\x94\xeb\xf7y\x0c\xf7\xe7\ +]?y\xde\xf1\xe4\xfb\x9b\xa2A\xf4\xda\xc1\x98\x8c\xa3\ +W\x975\x9f-\xfb\xa3\xcd\x80\xf3u\x5c\xabP^\x22\ +ZE\x94M\x07\x1d\x83+\xc1\x83\xdem\xa2\x04\x07\xf5\ +\x8fa\xa2\x0c\x87\x95\x11)\xa3$s\xfa\xb2@\x06\xe6\ +w\x82\xbe\xe17\xcfD\xd0\xc0\xac\xf2\xfe\x80T\xe6\xff\ +\xe2\x12\xcf\x91\xae\xddc\xcb\x01\xd3.\xfb\x97\xdb\x93\x84\ +\xbar\xf5\x04\x83\x97\x84\x9ex\xa2\xf9\xa1?\x926\x83\ +$I\xcd[\x1d\x1f\x04\x0a\xe1@2\x14|\xa0\x22y\ +m\x1a\x89\x00\x10 H\x98\xf6E\xfaU\x5c\xb2\xfb\x03\ +9\x8bdOz\x95K6\xabv\x09xp\x1fV\xef\ +\x84\xe8\xd1+\x85\x1e\xfd\x16=.\x1b=\xfa\x8dC\x8f\ +~\x1az\xf4[\xf4(\x87\x1e\xbdj\xd0c\xd2b\xc7\ +\x05c\xc7\xa4a\xc01\x11\xc3\xc6\xa4\x05\x8d\xca@\xa3\ +\xc4\x86e\xd4\xef\xb5\xa8q\xb9\xa8A\x86\xb7Y\xb0A\ +\x1a,\xc4\x0d\xff}\x0b\x1cE\x81cP\x8d\xb6!\xb7\ +\xb8q\xc1\xda\x86\xdc0mC\x16k\x1br\x0b\x1a\xf9\ +Ac\xdau\xed\xab1\x1f\x00\xb7\x944\x0f\x80\x81Z\ +\x1f\xc01}\x00\xd00\x1d\xdcy\xf6\xec\xec\x22\x17\x00\ +\x8f\xf2\xd8\x1e\x00j\xc6?\x86\x13` t\x02\x0c\xab\ +q\x02\xb4F\xbcK^\x1a\x9bf\xc1K\xb1\xdf\xb5\xd6\ +\xbb\x92\xfa\xb4\x5c\x0dh\xf4Z\x85\xfa\x92Q\xa3\xd74\ +\x8d\xba\x97\xa2R\xf7Z\x9d\xba$p\x0c\xab\xd9\x88\xf7\ +F-p\x5c2p\x8c\x9a\x06\x1c\xa3\x14\xe0\x18\xb5\xc0\ +q\x0e\xd1\x06\x93\xd6\xf4\x7f\xc9\xc01i\x9a\xe9\x7f\x92\ +b\xfa\x9f\xb4\xa6\xff\x0a\x81\xa3\xc4Ve\xdc\x02\xc7%\ +\x03\xc7\xb8i\xc01N\x01\x8eq\x0b\x1c\x15\xda8\xca\ +lUZ\xe0\xb8l\xcbh\xafi\xa6\xd1^\x8am\xb4\ +\x05\x8e\x93\xfb\x0dW@\xd1\xcc\x152\x22\xc7\xd3Z\xe7\ +a\x9d\xceC\xc5!\x00\xde9\xb0^\xe4>\xe4\xd3\xd6\ +\xef@\xfc\xcd\xaf\xb1v\xaf\xa1|U\x7f\xf8\xae|V\ +f\xbc\xdb^\xbb6V\xb96\xca\x0d\xb3\xe2\xc9b#\ +\x9e\xdc\xda\xf0\xce\xc3\x86'\xf7Z\xd4\xb8`\x1b\x9e\xdc\ +4\x1b\x9e\x9cb\xc3\x93[\x8d\xba$pT\x13\xf7\x7f\ +#\xcb-p\x5c.p\x90\xe1m\x16p\x90\x06\x0b\x81\ +\xc3\x7f\xdf\x02\xc7i\x8d\xff\x93\x168.[\xe3\x90\x9b\ +\xa6q\xc8)\x1aG\x0b\x1c'\xb7\xe1\xad\x91c\xb7\xf6\ +\xbb#\xda\xef\x18\xc3EF\xbb\x00A\xfd\x96\xba\x076\ +\xfc\xb5[\xe9\x86W\xf5\xbb\xb0\x86\xbd6\xbf\xcf\x05/\ +\x7fdx\x9b\xb5\xfc\x91\x06\x0b\x97?\xff}\xbb\xfc\x9d\ +6\xbe\x7f\xd4\x02\xc7%\x03\xc7\xa8i\xc01J\x01\x8e\ +Q\x0b\x1c\x15Z\xeaJh\x1c7\xbd6h\xe6\x92-\ +u\xbd\x86\x99\xf8I\x83\xc5\x96\xba^k\xe2?\x0b\x13\ +\xbf\xdc\x02\xc7EG\x144\x0d8\xe4\x14\xe0\x90[\xe0\ +\xa8\x108\x06el\x1c-p\x5c\xb4\x8d\xa3\xd74\x1b\ +G/\xc5\xc6\xd1\x02\xc7YD#\x8d[\xe0\xb8d\xe0\ +\x187\x0d8\xc6)\xc01n\x81\xe3L\x82\x0aZ\xd8\ +\xb8\xe0\x90\x82\x86\x05\x14\x88\xc3\x09Z\xc0\xa8\x0c0\x8a\ +oQ\xd6/\xa3\xfem\x8b\x19\x17\x8b\x19\x0f\xffC\xc6\ +\xb7Q\xb0\xc1Z,B\x8e\x00A\x0b\x1e\x15\xb8b\x07\ +e<*\xad+\xf6\xa2=*\x83\xa6yT\x06)\x1e\ +\x95\xd6\x15[w\x08#\xf7i\xbc\x5cN\x99\x9c/\xd3\ +/\xdc$\xa3\x88\x89|\x16\xbeq\x93\x7f\xb3\xa6\x11\x92\ +\x1b\xd3\x02\x0b`\x01C\x05v\xc7\xde\xd9\xa4'\xa1\x80\ +@#\xda\xd5Z\xee\xd1|\xf4:Z\xd7E\x9a\xc3\xc4\ +\x8b4C\xdew\xfa\xafm*\x9cu#:V\x1f,\ +\xe4\x98\x81[5\x97\xfb\xdf)\xd7jrx \x89\xae\ +\xec\xcd \xf2\xb9\x18q\x13\xaf;\xabC1\xca\x82/\ +\x8e\xbd\x0a\xaf\x9a\xe6|\xa6\xa9\xb6\x06-\xde\xa2\x1be\ +\x04B\xfa\x134\xb9+\xac\xd7\xffOHU0D\x86\ +\x84\x16\x124l\xac\xe8\xba\xfb\x9b\xb0I\xfa\x0bY\xba\ +&\xfd\xf4\x87\x09\x8c\xd7\x00+?'c\xb9\x10+2\ +.\x1b\x81\x01\x92\x16d\xe1\x02V5\xf5%\xad\x1cE\ +\x16\x8e\x84u\xc3m\xae(\xc87H\x91\xb8v\x08z\ +\x95\x04\xb8\x09x\x9b\xf5\x8a\x89\xa8\xbc\xbdY\x01\xf59\ +0\xe5\xd4\xf9Lq0\x22ra\xe1j\x04\xee\x91\x16\ +%\xb1IHj\x85\xc0\xc0\xd2v\x05\x0cI1M\x1d\ +z\xb2\xc8\xaa\xb3\x8f#m\xafH\xf7$]q\x0cu\ +\x15jUcd\xef?\xcb50\x1c\x91\xec\x05)\x8e\ +*{\xbd\x5c\xb2\xf7\x09\x1a\xe0\x9d\x06}D\xd5A\xc3\ +\x90\xae0\x9f\xe4\xb2s\xd4^\xa1\xed\x8c\xc8N5\x9c\ +\xfa\xb8\x90\xe8t \xb5\x00\xcd\x9b\x13\x84];\x89\x94\ +c\x10\xd6I\xae\x06#a\x8b\x92\x9eK\x1f\ +\xfe\xfc\xe8\x82\x08\x03\x8e\xaa\xaa>\xc2\xdc\xdd@\xb0\xed\ +\x90_*Pt\xa2\x18\xae\xc9~\x0d\xaa\xa2\xa9,\xf8\ +\xe0\xa83\xbb_Vb\x99x\xcd6\xa0\xa2\xc9\xcdP\ +\x9c\x95\xe9\x09,)\xd9\xa6\x93[s\xe8{W0\x1c\ +\xf3\x88K\x0a\xa71\x8d\x11\xcb\x97\x85\xbd\xeeX`\x8e\ +\x10\x16\x09c\x8c\xecT\x22XB\x916w\xae(V\ +#\x86L\xd0%\xc7\xd4\x14\x0cl\xa2\xc4Z\x92h\xb7\ +Q\xb1\xd8\xb9\x95\xd3J\xbd\x064\x0b\x06\xc9\x16\x99\x94\ +\xb4JE\xbf\x10]\xed\x12\xc7\xb7\x5cd4QdD\ +\xcc\xac\xfb\xde\x99\x5cr\xe7\x0b\xe6\xce\xb2\xec\xce\xf7;\ +iHx\xe7K\xd0\x0d\x13\xcd]\xf7v\xbf2\x7f\xf7\ +[d\x91\xd0Umf\xab\x16\x00\x06Qp*\xda\x7f\ +<(\xcf\x80^o$\x1d\x0a\x96\x00\xe9\xc2\x0e\xc35\ +p\xb5\x08w\xfa\x10up\x89\x90\xc6&\x14�\ +\xd7\x89\xd4\x11\xa8#\x85\x1ci#\xfc\xa8l\xa2Mm\ +\xcc\x94\x86\xe8\xda$\xedE\x0b]\xb1@\xf0_\xd1\xe5\ +W\xc2o\x8e\xb4\xb8\x14\x91S\x22>sd\x83\xaa\xf6\ +)\xcb%UY\xd6\xc8\x02\x12\x11D\xe5\xe4r\xf8\x06\ +\xe9:P\xb1\xdb\x22\x1d-\x9b\xb3\xb0\xa8\xa6pc\xec\ +\xbf>c\xd9\xd2(h\xcf\x80\xa1\xcc\xf5\x8b\x15\xb0w\ +\xacw\x12[\x9f$\xac\xcc\x9b\xa5\xb8\xe8\xd0\xc6\x1d\x0d\ +`\x05\xeav\xaa\xf6\x12'>\x17\xd9\xe3j\xc8\xaa;\ +\xf5gTL\xae\xaaC\x12&\xd4L\xf6\x1a3\xd4+\ +\xa0\x9b\x1deN4\x1c\xd1\x18G\xa9\x1a\xa9\x9f\xf6\xf3\ +\xea\xa7\xf3\x19u'\xdb\xe5\xb4\xd3\xf7\xb4\x88Z\xfd2\ +\xb2\xc8/3\xcc\xb5\x9d\xe4\x02\xb56K\xf0\xed\xe7\x9d\ +&\x8e\x0d$\xdb\x04*Tt\x89\x16\xc9\xa0\xf9}\xa7\ +\x7f#}\x87\xa4\x1c\xe9\xed\xbb\xb7\xd2O\xc8\xd0w\xd2\ +\x87\xfe\xe4\xe7\xc6L!\x8d\xf4\x07-;\xb4\xf7\x1d\xc5\ +\xd0:\xb4k\xa2\xc9\x94L\x7fTC\x83\x9cK28\ +Vl\xda\xee\x19\xfdU\x81h\xd0\x8e#]\xb9\xc6x\ +q\x5c\x1bu>\x8b\xdf'\x96\x85&\x98\x92f6\xa8\ +\xa0\xf7\x0f@\x83\xce\xfa\xee\xb8=\x1f\x94\xed\xb9\x5cA\ +\xcf\x1f\xc9\xfc\xd0\xefN6\xe4\x19\x04\xffQ\x87\x1a\xb0\ +\xf6=_\xd9\xb35\x1b\xac\xac\x98\x88,\xeaD`\x1e\ +\x19.\x1f\x80\xe1\xac\xef\xbf\xe2\xbb\xbb?\x0e\x84ww\ +\xbf\x91\xcf\xfeK*P\xf4i\x97Q\x94\xd3S\xa1\xfa\ +\xfc\x05\xd90\xa5\x11nO\xef\xee\x9e\x02\xe4\xee/\xfb\ +\xd5\x1cm@UM\xf9h``m\x14\x9d\xdb\x14R\ +\xc3\x1cX\xf7}\x02\x9e\xee\x7fg\xe8\xa9\xe2\xcc\x85a\ +\x05s\xe13\xa1:\xf2T\xe8\x95\xecw\x05\xbd\xfe\xa4\ +X\xcb\x13v\xbb\x08\x02\xe8\xb4\xc9-\x00\x5c\x12\x00\x0c\ +\xcaI\x84M\x97\xb1V\x22.I\x22\xc4\x07\xdd\xc5\xd0\ +\xe8\x22D\x05\xe0\xd8;\x99f\x94\xbf\xcf\xae^\xd4\xbc\ +N\x0f\xcat\x9aM\xfcf\xf4\xb92\x93\xca\xa0\xda\xb0\ +\xd7\xf8\x0e*w\xe0k\xe7\xf5\xc7?\x1ek\xb5\xb1\x8c\ +\xaf\xb2jQ\xc9\x0c\xc9\xb6\xab\x9eCTOp\xd8\x9e\ +O4\xd4\x89\xba\xe04\xe9\x03)\xc6>\xe7\xc9\xc6\xb5\ +\xddR\x06\xcd,`*\xd9\x98\x942\xf1\xbe\xb1\x82\x9a\ +ck\x02\xc0\x84F\xc7\xed\xbe\xd0\xc8\x14'<\xaau\ +iTbg\xb1\x1f\xe2E\x05\xe3\xfb\x01b\x09\xcd\xff\ +C\xad\xf3\xfea\x85\xbbj\x86[\xd1\xe1\xd2X\x03#\ +\xa1~\xc24\xaa\xc4\xbd\xdaS\xbd\xd7\x95\xa5\xf7\xf3\x1b\ +=\xb4\xf2w\xd2\xdb'K\x81:i]\x22\xc1\xf77\ +\x80\xeaK\xa4\x179G3\xd6\x85\xb9\xa3i;n\xf3\ +U\x8fC\x1e\x22\xd1\xd1\x98v\xd5cB\xc5\xa8\xac}\ +2\x87\x14\xb9~H\x8d\xcb\x899\x81\xd9\xfb\x85\xa2\xdb\ +\xec\xe0\x19\xf9\xbf\x9c\xb6\x9b!\xe8\xcf\xd8ID\x17\x86\ +\x04\xa0aPj\xa5\xb9\xa5\x18\xea\xea\x17\x09+\xcb_\ +\x08o\xd6k\x88\xaf\xa5G\xc0\x5cO4`\xd5$\xf8\ +bK\xef>?\xbd\xfbv}\xb2\x0du\x19X?\xfb\ +u\xaf\xc8\xa1\x0f\xb7\xf2F\x9e\xfc\xe8l \xd2\x01N\ +?\x00\x12\x22t~'\x1d\xac+\xc1\xc8\xe0\ +*\xc3\x14\x0a:\x16\xe4\x14O\xcb\x13\xc5\xb8\xc8(m\ +\xbdA\xea\xe6\x98\xc1\xc3\x8c\xd5G:\xfb[\xec(\xd5\ +\xca\xf7]{\xcf\xa3b\xcc]\x22\xb2\x05r\x9b\xbc\xbb\ +\xfc2c\xf1!\x82\x9b\x9e\x06g\xa64\xa2\xa3\xaa@\ +\xd7%\xb2{\xd9\xae\x90\x0e(/\x12aW\x84\xba\xd9\ +\x94\x98P\x0b\xf6\x15WTe\x82bZ@/MP\ +K\x01Y\xa3:\x9a\xe3\xa6\xb8\x10\x1e\x82\xe2Q&)\ +\xab\x82K\x0e\x13.\x87\xe4.d\x85\x85\xcaVx[\ +\xa2\xfcB\xc5\x0e\xba\xa9\x8ee\xd14\x02\xa6\xae\x18\xe4\ +\x172\x16p\xe9Xl]:\x82T\xc5\x9b\xd0\x08\xb9\ +\xd2\x90\xeaPm\xb8C\x87\xa2C\xb6\x8aBW\x17\x9f\ +\xf8\x0c\xa4\x8b\x13(8\xaeD\xb0hv\x087\x18\x86\ +Z\xb8mg\xb9\x046\x05.\xc2xG\x17\xa4\x98\xa9\ +N\xb0>\xfb\xb5{u\xdeUQ\xa9h\xafu\xb2\xad\ +V\x8e\xf6'm\xb4\xfc}\x96m\x92%km\xea\x80\ +\xd5\xa6\xe6\xe6X\xe5\x22\xfahB#`\x15\x0a\xb6/\ +]R\xc5\xf9+\x93\xf2\xfcy\xca\xf0\xa8\x97\x9c\xe4o\ +\xaf\x0e\xf7o\xc6\xe3\xf1\xa0\x9f|KnR\x9a\xbf<\ +\x82~\x16\xd3\x8dh\xb6\x94\x95\xdc\xfbw\xd3\xe2\xdf\xf2\ +T\xe3\x8e\x98\xa0\x1a\xba\x03)_\xcfF\xd1\x1d \xa8\ +eP\xa4\x96\x1c\xc2\xcf\xdd\xc5\x8a\xb5\xdd^1mW\ +\xa8\xdaO\xb8\x9an\x86\xd8\xeb\x0c+\xc9M\x15+\xc9\ +\xd3\xce\x04T\xe1\xb4\x81b\xa9+\x89,\x9eTE\xc1\ +\x16\xe9=\xf3 \xedU\x07\x05Z\xaa\xa5,\xf0/n\ +*\x01\xd6\x0b_]\x86\xd8f\x15J\xd0&_\x9b\x90\ +<\xa2\xa6\x7f\x1d\x9asD=4\xc7\xd0sL\xa0\x16\ +Y\x81r\xe3i\x06\x7fw\x86\xb1\x1bU1v\xaf\xbc\ +1qy\xff\x13\x0e\x0d\xe5\xcfG`\xfa\xbe\x01\xed\xd2\ +\x9fe\xe9'\xeb\xea\x1c\xcd\x98\x0en\x1fe\xe9\xcfp\ +\xd6!\xe6$\xa2m\x0c:\x89X\x9b]\x89J\x17Y\ +\xba\x12\x7f\xa1\x99\xbbvI\xda\x80\xc9\xdeJ+\xfa?\ +\x95\xd7_\xaf\xbe\xb0\xf8\x16\x0bhW\xd2\xe6\xf0\xf4=\ +|I0\xd2\xae\x90E8\x07\xb0J\x14\x08\xa2\x15\x1c\ +~qh\xa9\x93\xc7{K\x96\x9b\xc0\xaf\x04-\xc2m\ +]\x19!H:\x01\x90\x94\x96z\xa1\xac\xa1\xbe#{\ +\x7f\xc7\x82T\x06\xbd\xdf\x9c\xf6qK\xa8T\xcbi\xcc\ +R@M\x09Ii#\x98\xdd~\x9f$\x9cc\xc2\xcf\ +\xa7*}\x876$\x15}$]\xb4O\xa8\xcc$L\ +g\xb9\xe0tv!\xe8\xec\xa6s\xff\xfc\xa6\xf39\xac\ +\xc1\xf5H{\xf5\xaatU\xbe\x04\x96C\xa3N_\x82\ +8\xb9\xc9q\x1c\x0a\x89)\xcb\xaa\xf0'\xf4\xaf2\x9d\ +\xdc\x10\xfb\x108J\xebm\xea9\x0d\x9e\xba\x18\xcc\x83\ +!\xd1iy\x97\xf3\xa0F\xb9\x13*iI?bG\ +\xf9\xdc\xc4D,\xb7\x81\xcd\xb1kd\xdd\xb7\xef\xd7\x86\ +Q\xc2\xd2\x90\xd9\xe9\x98\xb4c\xf7+\xe8\x95\xad\xc1T\ +\x96\xe0\x11\x03\xb3\xbe>\xf0\xad\x01\xbea\xa3t\x0fl\ +6\x88\x89\xe7\x19\xab\xab\xa8\x80\xeb9\xe5\xdcf\xe6\xaa\ +\x85'6\xcb\x1c\xd7\xacp\xde\xf5\x0b\xfa+\x09n\x04\ +c:0\xe0\xac\x02Y\xb5m\xbe\xae\x9dU\xd3\xce|\ +%M\xdau4\x5c\x8d=\xf3`\x93\x1d+\xf8\xcbR\ +\xcc\x07\xa4\x81\xa4\xc1\xdes\xed\xee\xeeS\x80\xfa\xee\xee\ +3\xa2\xff\x97\x146R6;\x93\xab\xa8T\x86\xe8v\ +\xd9\xe6 \xbb\xb7+\x7f\x8aS\xb3F\x11\xa9SU`\ +3\x1d\xfa\xf5\xeew\xb0c{\x80\xbf\xb3\x7f\xf2\x80\x1c\ +\x1b$\xd3\xd3\x87\xaf\x89\xe0\xd9\xc0\x0a\xbc\x13\xd3\xbb\xc7\ +%\x94\x8c-\x8a~\xc1\x1a\xc43\x15\xd4\xb3x\x0d\xf2\ +/\xd2\x93R\x8bt\xbfW\xcf\xe2\x9cI9\x8c=\x89\ +\x94\x13\xf1g\xe4\x0f;\x08g\xac\x89\xb9Gb\xbea\ +\x0b-i\xe8\xd5k\xc5\xd7\x0fL\xef\xd1\x5c\x89xG\ +\xb2\xacx\xfbe\x88\xbf\x0a%p\x987|\xde\xb64\ +Z\xbc0~\x8d_\ +\xf4\xf8\xd5\x1a\xd9vW\xe1\x0b5\x04\x97V\xe4`\x98\ +\xa8\x8a2es\xfc\xe09}\xe0\x09\xfeoz\x96^\ +\xe9\x90\x8d\xfan\xae\xa8\xcf\x1d\xc6L\x91\x0b<\x99\x9e\ +\xb71:\xbe, S,\x0a\xfc\xb0\xcc\x22\x12\x9d[\ +\xca\x90Y\xb7\x90!\xb3\x192\x86\xcc\x5c\x22\xb6'?\ +\x07\x09S\xf5X\x9e\xe2|r\xf0\xee\x05bAR\xfb\ +\xf2b\xf0\x86\xb6\xf0,\xe5\xc0\xbd\xf6\xa4c\xaf\x1c\xac\ +\xa1\xad!\x92\x01.i\xa5\xe3\x1fS\x14\xc2\x04\x91\xd7\ +\xc1\x97\xa1W\xa1\x9a\xa2\x12\xf4@4\xe3\xc0\x9aN/\ +\x11:\xac\xe7Q\xb6/\x01Z\x03l\xf9&\xd0\xa9E\ +\x94A\xbf9/t1\x7f\xf1\x7f\xee\xe8O\xbf\xcb^\ +\x9c\xc3d\x1c\x0dt\xd8G7\xc8r$\xaea\xda=\ +\x94\x1ee!\xaf\x17\xc1.\xbc\x87\x07\x8d@\x9c@\xc3\ +\xb7\xc8\x90/\x22\x12\x19\x1b\xb7\xa9\xa2i\xaeB\xbcw\ +\xd3y+{WD@\xe0>\xf1\xbd\x0dL\xc5R0\ +\xb2DE\x10\x81\x06\x98l\x02\x17\x0a\x8d\xaf\x10V\xa6\ +l\x80k\xd1.Y\xe5\x0f\x07\xfa\xbd\x0a\x0bj\x1a\xe7\ +\x7f\x03\xba\x99\x8f\xf3\xf4\x8b\x02\x9c\xa7g\x05,<\x83\ +\xb6\xed\x00QW4h\xab\xc8\xd2J2\x84\xa5\xfbu\ +\xef\x12I'\xfb\x81K\xd6\xe6\xdeY\xe2\x1dX\x15\x11\ +\xb2\xd3\x1e\x19\xe84d\x10\x92b#\xfa\x1d\x82m\xbe\ +\x11\xa5_\xa4\x8ehJ\xadOd\x85\x22@4c\x80\ +z\xa8A\x9c\x0c\xc7\xf7\xde\xb9\x1fK6\xde\xc5f5\ +\x07\x8e9\x0cc\xd5\xceh\xfa\xddC\x908\x87\x8c\xae\ +q\x19\xa9\xe6\xc0\x86\x1aH\xa7s\x0cj\x82\xf5\xc72\ +\xbcJ\xa4q-d\x22\xc9\xc8,\xfaM!\x1e\xad\xc9\ +\x873w\x15\x14v\x8b\xd1i\x8a\xf5\x9cN\xa5S\xfc\ +O\xec<\x07\xf0\xe8\x9dh\xd8\x1d\xedd\xf9\x8f\xcbS\ +\x99\xe9\xe9\xf3\xb9\xdc\x1cw\xafs\x0b\x1dCH\xa2\xd2\ +\xc0\x06\xaaI\xb3\x97\xd7<\xb6\xfcu\x05\x04lN\x8b\ +\x08\x18\x8cw\xd3\xd5\x07\xb2k\xc4N\xd0(`\xb3\x07\ +\x87\xe1\x88\x997\xc98\x04\xc8\xf7c\xc7\xd77\xb6\xd0\ + \xaa\xd5SPnC7\xbcJ\xf4\xf3H\xc4aL\ +U\x88\xba\x10\xd0&\xe8A\xe4\xbb\x0d\xd3\x0a\x89^\xe9\ +\x1c\x8a\xee\xf4T\x1dy\x90\xa4\xe9\x0cb\x9a\xce\xe1\xf3\ +X\xcd1G\x9a\xcb\xc0W\x16\xf0\x93\xf5\xbb6\xd0'\ +d>\x1d\xde\x05M\x9e1?ZR\xa1\xaf\xc9\x87\xcf\ +a\xce\xc46\x9c\x9c\xc2\xc4ZQ\x8aR\x94\xa6}\xa4\ +N\xaeLzP\xd6E6\xe3\x1a[\xacU\xb1\x19\x9f\ +q\xc2\x17\xa9\x8c\xa7\x1e\xa5kG\xe9\xaaC\x91\xb6\xc4\ +\x95'!\xa6\xbcE\xeas\xd8\x15\xaemC\xa7\xea\x12\ +\xdc\x8ei\x13rp3J\x98\x91\xc3\xdb^\x9e)\x99\ +\x1e\xf8\xcd\xab~4\x18\x0en\xc7\xb5\xb4\xc0\xc5\xc9\x8f\ +\x81Mq4\x06\xa0\xe0I\xc2\xc8\x866\xad\x1d\x11\xb3\ +\x82\x87\xd5\xddl\x1f/t\xa4\xd0\xfbhR\xf1'\xa5\ +\x18@\x16 \xeb\x10\xd2\xe3:f\x0e2uww\xf8\ +\xff\xbdK\x1b|DM\x13t}\xf8;\xfb'\xefi\ +\xc3s~\xf3\xe0\xaeB\x01\xefIZ\xbf\x14]G[\ +\xa0Ql\x8f\xf4-T\x17}O\x839\xf5\xf0#;\ +GM\x82U\xd7=\xfb)y\xb1\x22)\x0bot\x91\ +\xd1B-\xf2\x8b\xde\xc7\x8d\x85\x1d\x01\xf1eF\x18,\ +s(\xfb\x0d20\x08\x5cT\x92\xfbn\xbb\x83\x9f)\ +l~\xcb\x9c\xc23\x18\xcf\x9c\x9a\xbd\xd3\xbf\x8f\x97N\ +E\xde\xb9!\x9e\xf5(_\x04L/\xe6\xe8q}k\ +\xe3\xa4\xc0\x90\xf4\x0c\xcf\x00\xd35\x1e\x83\x93\x19\xb2\x93\ +c\x0f\x8aD\x1ed\xb5h&G\x1d\x14\x8f9\xc8Q\ +wBbh\xf1\x99\x98\x92\xd6g\xe1\xe1\xe7\x81Pl\ +\xbe)\x1aDa\xeb\xb45\x9fm\x14\x0bR\xb1 \x02\ +\x04L\xa2\xa49\xf6\x99zC\xfe\xa0w\xef@C\xb5\ +X\xfe\x1e\xe6\xc3d\x07\x9e\xb6\x10\xab\xab\xeb\x7f\xfe\xe3\ +\xd5\x86` \xbb\xd3\x8c\x06\x04\xef\xbb%\xd1nI\xcf\ +\x06\x9a\xdb4\xe7\x8f\x89(\x18Aj6\x05\x96-\xc1\ +kp-m('YF\xa0\xb9E\x17|\x03\xd8\xf6\ +uM\x96\xf6\xef\xa1f\x91\xde\x9c\xa5\xd5\x9d\x05 \x12\ +\xbdQdn\x0f\xd3\xd4\xe0g\xf1\xa2v\x12\xf3\x99\x09\ +\xf3t\xc8W\xd5\xc2\x95 GG\xc6\xc1J\xcf\xcf\xc1\ +;\x92\x98\x92\x9b#-3\x07\xe7\x00b\xd2\xa8\xc4r\ +r\x88F\xe5\xa6:\xfc1\x1d{5\x9b\xbbO\xcf\x13\ +xh\x82.\x0a)\xb4\xa5\x92\xdbR\x0a\x16\xde\xf9\x03\ +\x0a#,9\x0e\xbb\x1bl \xb1u\xb86\xfc\xf8r\ +h\xc3Y\x22\xc7\xef\x10c\xb0\xfaB\xf4! \xcc\x00\ +\x1d\xa7\xab\x0dA\xc6\x89\x00\x92I>O\xaf[\xa5\x04\ +\x09\x90\x1e \x03Hd\xdbO\x10\x8a\xe5\xb8s\xd7F\ +*\xb2t\x93N\x84\xf4\x19\x5c\xd7\x17\xa5\x82\xcf\xd3s\ +L}\xc0d#\xa8E\xb7\xd2id\xb5\xc9\xe1\xa8.\ +\x9dm\x0d\x8d\xf3V\xda4pIJ\x1b\xe9\xcd\xf9*\ +m\x16X\x93mM\xaa\xde\x16$\xabM\xe0\xe5\xea\x04\ +^\xdd\xa9\xfa\xb9\x02\xf0\x1b\xda6\x09\xaf,\xe4,\xdd\ +\x93\x89L\xccmi\x01-\x1b\x1fv,4[\x1e\xa6\ +\x87\x12\xf7\xd3\xe1\x17\x89\x0e\x82D#\x96\xd8K2\x03\ +\xb07't\xe8\xcf\x895\x22\x85\xb8\xf3\x85\x94I\xe9\ +\xdcy\xc1t\x8e\x05=\xbb\xe6\x8a%U\xf4\xea\x9a\x00\ +n\x17\xed\xb3\xc5\xfag\x8b%\x06Q,\xa0\x11\x9e\x8b\ +\xa4\x9fGY\xdb\x04\x18T7\x01\xd8@\xbbpO\xc4\ +\xa7\x11`oz\xf6\x96(\xde\x07e\xdb\xd11\xec\x10\ +B\x8f\xf2\xc4b\xfe\xfeP\xcd\xb9\x82\xfc\x12uL\x0b\ +l r\x84b\x1e#\xabo\x7f^\x8b\x8c\x13\xd0l\ +\x84\x15\xaa\xd12~\xae\xd6'\x22\xbc\x06\xe9@\x8a|\ +\x1fHj\x93\xed^u\xb2\xedz`\xcfT\xa6\x9f\xd0\ +rI\xa4u\x0e\xf0\x16\x10\xfdd/\xd4v\x9aj\x82\ +\xb7\xa8\xc3\x94\x02\x8eP\xd7%\xbfn[\xcfRn\xf7\ +\xe9\x13\x85\xeaw\x84\xa86\xd9\x9dT\xa8|;6F\ +\xeb\xd3\xc9\xae@/e-;Ka0\xd9Q=\x15\ +tHI\x8e\xf0\xec\x02\x8f\xb2\xbe\xe5\xba\x10\xa6q\xf2\ +\x9a\x1fW(\x8a\x05\xe7\x87\xbf\x89\x04\xeb\x17\xf3%\xdf\ +\x14\xf3%/\xe8\xc83OB1\x87r\xaa\x93|\x98\ +\xeb\xf0`\xe4\xb6\x03\x9a\xf4v\x89\xac\xddU\xe1y\xe8\ +\x15p\x97c*Vr\xde&\xd2\x11\x0d\xd8\xaa\x05\xcd\ +\xf4\xa5V\xd0\x97\xb7\x872N\xdd\x1d\xa8Q\xb3\xd7\x02\ +\x02\xabpo>\xfaE\x9c\xba3\x96b,A\xe1~\ +|\xa3_\xd7\xdf\x05\x81K\xb1u(V\xedP\xcc\x87\ +\xd8a\xeap\xc0b\xee\xe8E/\xa0\xb3\x8e\xe8\xbdg\ +\xef\xdc~\x15\xf1{\xcd\x0f\xc1\xab+\xa0\xee3\x0a?\ +\xa9&\x9c\xee-\x13\x0b)~^\xe6\xccb\xe9\x0e1\ +q\xb9\x15\x85Q\xc6h\xba\x08z\xef\xa5Z\xa4\xfeD\ +\xd0;\x1cm\x9a\x80\x14\xd5LyQ\xacu\xf2\x81\x81\ +\xe8\xecNS\xf8\x93o\xbfZ9\xf3\x0e\xd1=\x9eS\ +N)\xf3(\xf3\xc5\xf3\x06X\x1c\xb8#\x9atVb\ +\x9d\x15\x0a-\x91:\xc6&.\xcb\x82!\xe1\xb5s\xcc\ +\x8d\xf4\xdf\xae\xa0\xf8V\x86\x18Yi^\xbd\xa2\xbd\xe4\ +\x9d\xa4N\x0d)'\x8b\xf47\x14\x00\x0cwQ\x7f\xa5\ +\xba\x8b\xf9\x83\xf7\xfa\xee\x8e\xd5@\xff\x0d\x9f\xf7\xc8;\ +\x10?p\xfd\xa3\xf0Cha\xfb\x81+\xe5\xf9W\x5c\ +'\xc3\xbf\x96by\xf8\xe0I\xed|g)\xfe,\xb0\ + _\xafD#\x10\xa7+=\x16\xee!-\xee\xc5\xab\ +\xc5\x8e\x12x\xd7\xb9f/W8\x10\xec\x9cQ\xed\xfc\ +\xaf4\xa5@\x91Q\xf8J\xbaY\x09\xf3\x93\xf2B\xa4\ +\x15g\xaf\xc8\x8a\xa1:\xb1\x86\xbd\xc1\x96\xfe\xaf\xaf\xc5\ +\xc7/t\xfa\x93_5\xbbr\xb5\xfcy?V\xcc\xc1\ +\xb2T\xfc\xd0`\x85s\x9a*.i\xf3\xf9@SZ\ +\x8a\xd8\xbd\x0f\x1e\xb3\x8b\x0fY$\x97A\xed\x8cb7\ +-9D\x01O\xbd\x8e\xe9@T\x81\x8aD\x1b\x8c\x91\ +\xb4\xefgq~y\xa7\xefj\xe7\x13V^\x80\xddY\ +@C1T t\xf5\xf2(\xcb/\x14\xac\x9b%\x91\ +@tD\xb0\x22\x1c\xa8\x90\xe3\x89g\xefR\xe9\xaa\x99\ +\xca\xbck\xfc\x8a\x02\xf9+\x1d\xff\xebC\xc9\xd1\x13\x9a\ +H\xceu\xf8\xb8\xc6\x97\x0c\x94\xd5\x0c\xa1k>\xa8d\ +i/\x5c\x9eH$\xde\x96\x10\x89\xc3\x09\xee\xfa\xb7\x87\ +U\xdf\xafVh@\xe9\xddt_\xe2w\xd2\x15\x1d\xcf\ +\x94\xab\xeeJ\xa9l\x8f%\xd63\xef\xbcy\xfd\x83\xea\ +V$\x1c\xca I\xf9%\xcc-\xad\x92\xd1\xf3\xca\x92\ +\x1e\x81\xb5\x01%\xb4\xad`\xde\xc9\x1ay]S\x82\xc6\ +B\xd3(\x9e\xc5\xb2\xe8\x0cJL\xb9\x99o\x04\xfcl\ +\x8f)\xde\xea\x82\xb6\xf6:\x87\xb1\x8a\x1c\x88\xc5\x061\ +\x9a%\xb2\xf0\x18&$\xb4\xcc3\x84\xa1\xfc\x1f\xb5\x0f\ +\x82\x01\xf0\x16Y\xcf\x1d5E\xab\x88\xd3\x95f;\xbd\ +i\xbd\x1ecM's\xd1\xc2\x91\x08$\xe5\xaaUM\ +\xe41\x87\xba\xe7lv\xe6\xaex\xfb\x0f\xd9\xc2\x8e\xde\ +|\x9a\xbb;\xbd\xf5Y\x076[i\xe9\xbc\xf0r\xa2\ +\x9d\x86\x1bn\xe5\xd5\xf1#Cy\xe9\x1cq\xb3\xbf\x9d\ +\x86!\xac\xee\xe2\xed\x0f$pk\xca&\x8e\x1d\xa9U\ +l\x9c\x12@\x19\xa0)\x0d\xb2\x9f(\x83*\x11:V\ +\x92\x14\xcf\xde\x97{\xccXj\xbe\xa6\x0c\xd9\xdeD\xee\ +\xd8&0\xb4,\xc6\xf4 ey-\x9f\xf0\xaa\x1a\x15\ +\x9f\x14T\xc5\xe0y\xf9\x17\x9b2|\xcc\xd4\xea^\x90\ +\xd7\x81\x06\x8d\x15H5\xccr\xa8\xcbk\x98\x8ck\xd5\ +\xe8\x98\xac\xa8|C\x19\x8c&\x98\xee\x19i\xbbd\xd0\ +PuG\x03\x92\x8eT\x16\xba\x15\xe1o\xd7\xfd>\xf4\ +\xd1\x94\xb0\xc3\x00\xact\xaf\x90\xc3\x03\xaf-6\xa0\xe0\ +~\xbf\xcf\x0eN\xc3W\xd8\x03\xef-\x5c\x1a\x8a~O\ +4e\xea\xe5\xf8\x89^\xd5\xe6>q_[@\x05\x90\ +p\xff\xfe+~\xab\xda,/\xb3\xfb\xdb\xfbZG\xf8\ +\x9e\x15\xcb\xbe\xa4\xbf\xdc\x17+z_\xcc\x9e]\xf4\x87\ +\xe4\xde\x80\xe76\x9d]\xd1q\x15\xc8\x1e}s;\x09\ +\xe7\x8f\xbe\xb9\x19\x1f2HO\xbb\xb4\x04Ni\x1a\xb0\ +14\x18\xafbE\x0e\xfb\x91\x22\xe5\xa4\x22\xdd\xff=\ +\xf6u#\xfcK\xe4\xa7\x1f\xad\xceg(f\x87\x07\xb4\ +\x9f\xe8TKd\xaa\x1f\xdc\xccg,\x91\xf3w\xeeN\ +\xd1/\xa60\x87oo#\x19\xba\xe5QY\x0e\xc7\x8b\ +\xbc\x1dU\xcca?#B\x09&\x07\x93V\xd5\xcf\xe7\ +\xf1d\x10a\xca\xa0,\x9f'\xa3(\x9f\xe5~\xc5|\ +^N\xd8\x8d7EY\xbc\x9c\xb3\x8b\xe2\xecD\xf6\xbe\ +\x85vE\xfc\xed\x8f\xe503\x06\xf2\xb0$\x7f\x07r\ +\x04)\x06\x95#\xc5\xb2\xdf\x93\x9b\xc1\xdf\xe1(\x0a\x9b\ +\xc3q#\xf8;j\xa8\xfc\x0eozM\xe0o\xbf\xa1\ +\xe2\xdb\x14\xf66\x15~\x9b\x01\x0fr\xaf!\xfc\x95\xfb\ +\xa3&.orS\xd1w0n\x02{\x87M\x11\xdf\ +\xd1\xb0\x91\xda\xd9\xb07h\x88\xfc\xf6\xfaM\x5c\xdeF\ +M\xe1o\x0c~\x9b\xc1\xdf\x9b\xa6\xe0CL~\x9b\x81\ +\x0f7M\x91\xdf\x18\xfe6D~\xe5\xa6\xee\x8e\x9b\xa1\ +?\x8c\x1b\x8b\x0f\xcd\xd8^\x8c\x9b\xb2}\x8b\xcbo#\ +\xf0w\xd2P\xed\xa1\x19\xd2;\x91\x9bj|\x18\x0e\x9a\ +\xc1\xdf\xa6\xaen\x8d\xe0\xef\xfae\xd4\xbfm\xa8zv\ +\xfe\x00\xb1\xb2g\x1a\x98;K\xc6\xa3\x19\xcd\xc8\xc1g\ +\xb5\xcd\xae?y@\x1b\xc2'RM\xb2\xcb\x93v`\ +6Id\xf6gg\xbd\xff\xbe0\x9b\x07\xf2m\xc4\x9b\ +\xdc\xbb-\xc9\xe6\x9b\xf1(Z\xe4$?\x9b\x83\xbf)\ +\xc5\xb4\xeb@\xf2\xe7\xff\x01O#\xef\xfc\ \x00\x00\x04\x8e\ <\ svg width=\x2264\x22 h\ @@ -649122,147 +649128,147 @@ \x00\x00\x00\x00\x00\x00\x00\x00\ \x00\x00\x00\x1a\x00\x02\x00\x00\x00G\x00\x00\x00\x05\ \x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x07\xb4\x00\x00\x00\x00\x00\x01\x00\x9a\xdb\x5c\ +\x00\x00\x07\xb4\x00\x00\x00\x00\x00\x01\x00\x9a\xdb\xbb\ \x00\x00\x01\x98\xd8F#Y\ -\x00\x00\x092\x00\x00\x00\x00\x00\x01\x00\x9c\x06\x03\ +\x00\x00\x092\x00\x00\x00\x00\x00\x01\x00\x9c\x06b\ \x00\x00\x01\x98\xd8F#Y\ -\x00\x00\x07V\x00\x00\x00\x00\x00\x01\x00\x9a\xc6\xbd\ +\x00\x00\x07V\x00\x00\x00\x00\x00\x01\x00\x9a\xc7\x1c\ \x00\x00\x01\x98\xd8F#Y\ -\x00\x00\x0bD\x00\x00\x00\x00\x00\x01\x00\x9d-^\ +\x00\x00\x0bD\x00\x00\x00\x00\x00\x01\x00\x9d-\xbd\ \x00\x00\x01\x98\xd8F#Y\ -\x00\x00\x0bh\x00\x00\x00\x00\x00\x01\x00\x9d/\xb4\ +\x00\x00\x0bh\x00\x00\x00\x00\x00\x01\x00\x9d0\x13\ \x00\x00\x01\x98\xd8F#Y\ -\x00\x00\x08`\x00\x00\x00\x00\x00\x01\x00\x9b=\x7f\ +\x00\x00\x08`\x00\x00\x00\x00\x00\x01\x00\x9b=\xde\ \x00\x00\x01\x98\xd8F#Y\ -\x00\x00\x0b\x1c\x00\x00\x00\x00\x00\x01\x00\x9d(R\ +\x00\x00\x0b\x1c\x00\x00\x00\x00\x00\x01\x00\x9d(\xb1\ \x00\x00\x01\x98\xd8F#Y\ -\x00\x00\x09\x5c\x00\x00\x00\x00\x00\x01\x00\x9c\x12\x02\ +\x00\x00\x09\x5c\x00\x00\x00\x00\x00\x01\x00\x9c\x12a\ \x00\x00\x01\x98\xd8F#Y\ -\x00\x00\x06\xa2\x00\x00\x00\x00\x00\x01\x00\x9a\xa9^\ +\x00\x00\x06\xa2\x00\x00\x00\x00\x00\x01\x00\x9a\xa9\xbd\ \x00\x00\x01\x98\xd8F#Y\ -\x00\x00\x08\x98\x00\x00\x00\x00\x00\x01\x00\x9b\xc1\xcf\ +\x00\x00\x08\x98\x00\x00\x00\x00\x00\x01\x00\x9b\xc2.\ \x00\x00\x01\x98\xd8F#*\ -\x00\x00\x0a\x80\x00\x00\x00\x00\x00\x01\x00\x9c\xa4\x8e\ +\x00\x00\x0a\x80\x00\x00\x00\x00\x00\x01\x00\x9c\xa4\xed\ \x00\x00\x01\x98\xd8F#*\ -\x00\x00\x08\x1a\x00\x00\x00\x00\x00\x01\x00\x9b\x10\x96\ +\x00\x00\x08\x1a\x00\x00\x00\x00\x00\x01\x00\x9b\x10\xf5\ \x00\x00\x01\x98\xd8F#*\ -\x00\x00\x0c4\x00\x00\x00\x00\x00\x01\x00\x9d\xed0\ +\x00\x00\x0c4\x00\x00\x00\x00\x00\x01\x00\x9d\xed\x8f\ \x00\x00\x01\x98\xd8F#Y\ -\x00\x00\x04\x8e\x00\x00\x00\x00\x00\x01\x00\x98\xd3b\ +\x00\x00\x04\x8e\x00\x00\x00\x00\x00\x01\x00\x98\xd3\xc1\ \x00\x00\x01\x98\xd8F#Y\ -\x00\x00\x0aV\x00\x00\x00\x00\x00\x01\x00\x9c\x91\xd3\ +\x00\x00\x0aV\x00\x00\x00\x00\x00\x01\x00\x9c\x922\ \x00\x00\x01\x98\xd8F#Y\ -\x00\x00\x05X\x00\x00\x00\x00\x00\x01\x00\x99\xe3Z\ +\x00\x00\x05X\x00\x00\x00\x00\x00\x01\x00\x99\xe3\xb9\ \x00\x00\x01\x98\xd8F#J\ -\x00\x00\x0a\x96\x00\x00\x00\x00\x00\x01\x00\x9c\xcd8\ +\x00\x00\x0a\x96\x00\x00\x00\x00\x00\x01\x00\x9c\xcd\x97\ \x00\x00\x01\x99*\x8f\xb7\x94\ -\x00\x00\x05j\x00\x00\x00\x00\x00\x01\x00\x9a\x06\xd2\ +\x00\x00\x05j\x00\x00\x00\x00\x00\x01\x00\x9a\x071\ \x00\x00\x01\x98\xd8F#Y\ -\x00\x00\x08\xcc\x00\x00\x00\x00\x00\x01\x00\x9b\xee\xf0\ +\x00\x00\x08\xcc\x00\x00\x00\x00\x00\x01\x00\x9b\xefO\ \x00\x00\x01\x98\xd8F#Y\ -\x00\x00\x08\xae\x00\x00\x00\x00\x00\x01\x00\x9b\xe9\x9f\ +\x00\x00\x08\xae\x00\x00\x00\x00\x00\x01\x00\x9b\xe9\xfe\ \x00\x00\x01\x98\xd8F#Y\ -\x00\x00\x0a\x06\x00\x00\x00\x00\x00\x01\x00\x9cu(\ +\x00\x00\x0a\x06\x00\x00\x00\x00\x00\x01\x00\x9cu\x87\ \x00\x00\x01\x98\xd8F#Y\ -\x00\x00\x06\xf8\x00\x00\x00\x00\x00\x01\x00\x9a\xba\xfb\ +\x00\x00\x06\xf8\x00\x00\x00\x00\x00\x01\x00\x9a\xbbZ\ \x00\x00\x01\x99*\x8f\xb7\x94\ -\x00\x00\x03|\x00\x00\x00\x00\x00\x01\x00\x98\x1ap\ +\x00\x00\x03|\x00\x00\x00\x00\x00\x01\x00\x98\x1a\xcf\ \x00\x00\x01\x98\xd8F#Y\ -\x00\x00\x09\xc4\x00\x01\x00\x00\x00\x01\x00\x9cl&\ +\x00\x00\x09\xc4\x00\x01\x00\x00\x00\x01\x00\x9cl\x85\ \x00\x00\x01\x99*\x8f\xb7\x94\ -\x00\x00\x080\x00\x00\x00\x00\x00\x01\x00\x9b7\xed\ +\x00\x00\x080\x00\x00\x00\x00\x00\x01\x00\x9b8L\ \x00\x00\x01\x98\xd8F#Y\ -\x00\x00\x08\x04\x00\x00\x00\x00\x00\x01\x00\x9a\xe8\xdc\ +\x00\x00\x08\x04\x00\x00\x00\x00\x00\x01\x00\x9a\xe9;\ \x00\x00\x01\x98\xd8F#:\ -\x00\x00\x09\x16\x00\x00\x00\x00\x00\x01\x00\x9b\xf6\x90\ +\x00\x00\x09\x16\x00\x00\x00\x00\x00\x01\x00\x9b\xf6\xef\ \x00\x00\x01\x98\xd8F#Y\ -\x00\x00\x05\x02\x00\x00\x00\x00\x00\x01\x00\x99\x8e\xde\ +\x00\x00\x05\x02\x00\x00\x00\x00\x00\x01\x00\x99\x8f=\ \x00\x00\x01\x98\xd8F#:\ -\x00\x00\x0cZ\x00\x00\x00\x00\x00\x01\x00\x9d\xf8\xbe\ +\x00\x00\x0cZ\x00\x00\x00\x00\x00\x01\x00\x9d\xf9\x1d\ \x00\x00\x01\x98\xd8F#:\ -\x00\x00\x0a\xdc\x00\x01\x00\x00\x00\x01\x00\x9d\x0c,\ +\x00\x00\x0a\xdc\x00\x01\x00\x00\x00\x01\x00\x9d\x0c\x8b\ \x00\x00\x01\x98\xd8F#Y\ -\x00\x00\x07*\x00\x01\x00\x00\x00\x01\x00\x9a\xc0,\ +\x00\x00\x07*\x00\x01\x00\x00\x00\x01\x00\x9a\xc0\x8b\ \x00\x00\x01\x98\xd8F#Y\ -\x00\x00\x04h\x00\x00\x00\x00\x00\x01\x00\x98\xb4z\ +\x00\x00\x04h\x00\x00\x00\x00\x00\x01\x00\x98\xb4\xd9\ \x00\x00\x01\x98\xd8F#Y\ -\x00\x00\x0b\xb6\x00\x00\x00\x00\x00\x01\x00\x9d\x928\ +\x00\x00\x0b\xb6\x00\x00\x00\x00\x00\x01\x00\x9d\x92\x97\ \x00\x00\x01\x98\xd8F#J\ -\x00\x00\x0b\xcc\x00\x00\x00\x00\x00\x01\x00\x9d\xbd5\ +\x00\x00\x0b\xcc\x00\x00\x00\x00\x00\x01\x00\x9d\xbd\x94\ \x00\x00\x01\x98\xd8F#J\ -\x00\x00\x05\xda\x00\x00\x00\x00\x00\x01\x00\x9ab\xdb\ +\x00\x00\x05\xda\x00\x00\x00\x00\x00\x01\x00\x9ac:\ \x00\x00\x01\x98\xd8F#Y\ -\x00\x00\x04\x08\x00\x00\x00\x00\x00\x01\x00\x98e)\ +\x00\x00\x04\x08\x00\x00\x00\x00\x00\x01\x00\x98e\x88\ \x00\x00\x01\x98\xd8F#Y\ -\x00\x00\x04\xc8\x00\x01\x00\x00\x00\x01\x00\x99S\xc0\ +\x00\x00\x04\xc8\x00\x01\x00\x00\x00\x01\x00\x99T\x1f\ \x00\x00\x01\x98\xd8F#Y\ -\x00\x00\x0c\x00\x00\x00\x00\x00\x00\x01\x00\x9d\xeb2\ +\x00\x00\x0c\x00\x00\x00\x00\x00\x00\x01\x00\x9d\xeb\x91\ \x00\x00\x01\x98\xd8F#Y\ -\x00\x00\x04(\x00\x00\x00\x00\x00\x01\x00\x98l\xa5\ +\x00\x00\x04(\x00\x00\x00\x00\x00\x01\x00\x98m\x04\ \x00\x00\x01\x98\xd8F#Y\ -\x00\x00\x03\xd0\x00\x00\x00\x00\x00\x01\x00\x98%\xf7\ +\x00\x00\x03\xd0\x00\x00\x00\x00\x00\x01\x00\x98&V\ \x00\x00\x01\x98\xd8F#J\ -\x00\x00\x04R\x00\x00\x00\x00\x00\x01\x00\x98\x82\xcd\ +\x00\x00\x04R\x00\x00\x00\x00\x00\x01\x00\x98\x83,\ \x00\x00\x01\x98\xd8F#J\ -\x00\x00\x0cp\x00\x00\x00\x00\x00\x01\x00\x9e\x1ag\ +\x00\x00\x0cp\x00\x00\x00\x00\x00\x01\x00\x9e\x1a\xc6\ \x00\x00\x01\x98\xd8F#J\ -\x00\x00\x060\x00\x00\x00\x00\x00\x01\x00\x9a\x97^\ +\x00\x00\x060\x00\x00\x00\x00\x00\x01\x00\x9a\x97\xbd\ \x00\x00\x01\x98\xd8F#Y\ -\x00\x00\x0b\xe2\x00\x00\x00\x00\x00\x01\x00\x9d\xe7\x9b\ +\x00\x00\x0b\xe2\x00\x00\x00\x00\x00\x01\x00\x9d\xe7\xfa\ \x00\x00\x01\x98\xd8F#Y\ -\x00\x00\x05\x94\x00\x00\x00\x00\x00\x01\x00\x9a\x1a$\ +\x00\x00\x05\x94\x00\x00\x00\x00\x00\x01\x00\x9a\x1a\x83\ \x00\x00\x01\x98\xd8F#J\ -\x00\x00\x04\xb2\x00\x00\x00\x00\x00\x01\x00\x99*_\ +\x00\x00\x04\xb2\x00\x00\x00\x00\x00\x01\x00\x99*\xbe\ \x00\x00\x01\x98\xd8F#J\ -\x00\x00\x08\x84\x00\x00\x00\x00\x00\x01\x00\x9b\x94|\ +\x00\x00\x08\x84\x00\x00\x00\x00\x00\x01\x00\x9b\x94\xdb\ \x00\x00\x01\x98\xd8F#*\ -\x00\x00\x05\xc6\x00\x00\x00\x00\x00\x01\x00\x9aDg\ +\x00\x00\x05\xc6\x00\x00\x00\x00\x00\x01\x00\x9aD\xc6\ \x00\x00\x01\x98\xd8F#:\ -\x00\x00\x04\xee\x00\x00\x00\x00\x00\x01\x00\x99[\x07\ +\x00\x00\x04\xee\x00\x00\x00\x00\x00\x01\x00\x99[f\ \x00\x00\x01\x98\xd8F#:\ -\x00\x00\x07\x88\x00\x00\x00\x00\x00\x01\x00\x9a\xd8\xe9\ +\x00\x00\x07\x88\x00\x00\x00\x00\x00\x01\x00\x9a\xd9H\ \x00\x00\x01\x98\xd8F#Y\ -\x00\x00\x0b\xa2\x00\x00\x00\x00\x00\x01\x00\x9dn\xcb\ +\x00\x00\x0b\xa2\x00\x00\x00\x00\x00\x01\x00\x9do*\ \x00\x00\x01\x98\xd8F#:\ -\x00\x00\x0c\x86\x00\x00\x00\x00\x00\x01\x00\x9eF\xed\ +\x00\x00\x0c\x86\x00\x00\x00\x00\x00\x01\x00\x9eGL\ \x00\x00\x01\x98\xd8F#Y\ -\x00\x00\x06\xce\x00\x00\x00\x00\x00\x01\x00\x9a\xae\xe1\ +\x00\x00\x06\xce\x00\x00\x00\x00\x00\x01\x00\x9a\xaf@\ \x00\x00\x01\x98\xd8F#Y\ -\x00\x00\x08\xf0\x00\x00\x00\x00\x00\x01\x00\x9b\xf1\xc8\ +\x00\x00\x08\xf0\x00\x00\x00\x00\x00\x01\x00\x9b\xf2'\ \x00\x00\x01\x98\xd8F#Y\ -\x00\x00\x09\x92\x00\x00\x00\x00\x00\x01\x00\x9c8\xa3\ +\x00\x00\x09\x92\x00\x00\x00\x00\x00\x01\x00\x9c9\x02\ \x00\x00\x01\x98\xd8F#Y\ -\x00\x00\x05\xf2\x00\x00\x00\x00\x00\x01\x00\x9a\x8c\xab\ +\x00\x00\x05\xf2\x00\x00\x00\x00\x00\x01\x00\x9a\x8d\x0a\ \x00\x00\x01\x98\xd8F#Y\ -\x00\x00\x050\x00\x00\x00\x00\x00\x01\x00\x99\xdb_\ +\x00\x00\x050\x00\x00\x00\x00\x00\x01\x00\x99\xdb\xbe\ \x00\x00\x01\x98\xd8F#Y\ -\x00\x00\x05\xaa\x00\x00\x00\x00\x00\x01\x00\x9a?\x8b\ +\x00\x00\x05\xaa\x00\x00\x00\x00\x00\x01\x00\x9a?\xea\ \x00\x00\x01\x98\xd8F#Y\ -\x00\x00\x09|\x00\x00\x00\x00\x00\x01\x00\x9c\x16\x01\ +\x00\x00\x09|\x00\x00\x00\x00\x00\x01\x00\x9c\x16`\ \x00\x00\x01\x98\xd8F#J\ -\x00\x00\x07\xea\x00\x00\x00\x00\x00\x01\x00\x9a\xe1'\ +\x00\x00\x07\xea\x00\x00\x00\x00\x00\x01\x00\x9a\xe1\x86\ \x00\x00\x01\x98\xd8F#Y\ -\x00\x00\x0a\xc6\x00\x00\x00\x00\x00\x01\x00\x9c\xea\xfc\ +\x00\x00\x0a\xc6\x00\x00\x00\x00\x00\x01\x00\x9c\xeb[\ \x00\x00\x01\x98\xd8F#Y\ -\x00\x00\x0b\x8c\x00\x00\x00\x00\x00\x01\x00\x9dA\x00\ +\x00\x00\x0b\x8c\x00\x00\x00\x00\x00\x01\x00\x9dA_\ \x00\x00\x01\x98\xd8F#Y\ -\x00\x00\x09\xac\x00\x00\x00\x00\x00\x01\x00\x9c@\xa2\ +\x00\x00\x09\xac\x00\x00\x00\x00\x00\x01\x00\x9cA\x01\ \x00\x00\x01\x98\xd8F#:\ -\x00\x00\x05\x18\x00\x00\x00\x00\x00\x01\x00\x99\xad\xc2\ +\x00\x00\x05\x18\x00\x00\x00\x00\x00\x01\x00\x99\xae!\ \x00\x00\x01\x98\xd8F#:\ -\x00\x00\x0a>\x00\x00\x00\x00\x00\x01\x00\x9c\x7f&\ +\x00\x00\x0a>\x00\x00\x00\x00\x00\x01\x00\x9c\x7f\x85\ \x00\x00\x01\x98\xd8F#Y\ -\x00\x00\x0a\xee\x00\x00\x00\x00\x00\x01\x00\x9d\x1aD\ +\x00\x00\x0a\xee\x00\x00\x00\x00\x00\x01\x00\x9d\x1a\xa3\ \x00\x00\x01\x98\xd8F#Y\ -\x00\x00\x06X\x00\x00\x00\x00\x00\x01\x00\x9a\x9e#\ +\x00\x00\x06X\x00\x00\x00\x00\x00\x01\x00\x9a\x9e\x82\ \x00\x00\x01\x98\xd8F#Y\ -\x00\x00\x03\xa6\x00\x00\x00\x00\x00\x01\x00\x98\x1f\x02\ +\x00\x00\x03\xa6\x00\x00\x00\x00\x00\x01\x00\x98\x1fa\ \x00\x00\x01\x99*\x8f\xb7\x94\ -\x00\x00\x09\xe2\x00\x00\x00\x00\x00\x01\x00\x9cp]\ +\x00\x00\x09\xe2\x00\x00\x00\x00\x00\x01\x00\x9cp\xbc\ \x00\x00\x01\x98\xd8F#Y\ -\x00\x00\x03\xe6\x00\x00\x00\x00\x00\x01\x00\x98V\x90\ +\x00\x00\x03\xe6\x00\x00\x00\x00\x00\x01\x00\x98V\xef\ \x00\x00\x01\x98\xd8F#Y\ -\x00\x00\x06l\x00\x00\x00\x00\x00\x01\x00\x9a\xa7 \ +\x00\x00\x06l\x00\x00\x00\x00\x00\x01\x00\x9a\xa7\x7f\ \x00\x00\x01\x98\xd8F#Y\ \x00\x00\x00\x1a\x00\x02\x00\x00\x00\x18\x00\x00\x00M\ \x00\x00\x00\x00\x00\x00\x00\x00\ @@ -649319,7 +649325,7 @@ \x00\x00\x03P\x00\x01\x00\x00\x00\x01\x00\x97\xfav\ \x00\x00\x01\x99*\x8f\xb8+\ \x00\x00\x03f\x00\x01\x00\x00\x00\x01\x00\x97\xff~\ -\x00\x00\x01\x9b\xe2m|\xb3\ +\x00\x00\x01\x9b\xec\x0c7\xf7\ " def qInitResources(): diff --git a/src/dcspy/resources/config.yaml b/src/dcspy/resources/config.yaml index 50f84e300..aa0e76137 100644 --- a/src/dcspy/resources/config.yaml +++ b/src/dcspy/resources/config.yaml @@ -1,4 +1,4 @@ -api_ver: 3.7.1 +api_ver: 3.8.0 autostart: false check_bios: true check_ver: true @@ -19,6 +19,7 @@ font_mono_s: 9 font_name: consola.ttf git_bios: true git_bios_ref: main +git_bios_repo: https://github.com/DCS-Skunkworks/dcs-bios.git gkeys_area: 2 gkeys_float: false gui_debug: false diff --git a/src/dcspy/ui/qtdcs.ui b/src/dcspy/ui/qtdcs.ui index d2da613f9..440004460 100644 --- a/src/dcspy/ui/qtdcs.ui +++ b/src/dcspy/ui/qtdcs.ui @@ -216,8 +216,8 @@ 0 0 - 152 - 105 + 657 + 385 @@ -409,8 +409,8 @@ 0 0 - 152 - 74 + 657 + 385 @@ -544,8 +544,8 @@ 0 0 - 236 - 105 + 657 + 385 @@ -1102,29 +1102,39 @@ DCS-BIOS - - + + - Regular release or live version (need git installed) + Location of DCS-BIOS in Saved Games + + + + - Use live DCS-BIOS version: + Repair - :/icons/img/git.svg:/icons/img/git.svg + :/icons/img/deepin-repair.svg:/icons/img/deepin-repair.svg - - - - Location of DCS-BIOS in Saved Games + + + + Git object reference: + + + Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter + + + le_bios_ref - - + + false @@ -1133,20 +1143,6 @@ - - - - Auto check DCS-BIOS version during startup - - - Auto check DCS-BIOS - - - - :/icons/img/xfsm-reboot.svg:/icons/img/xfsm-reboot.svg - - - @@ -1175,14 +1171,54 @@ - - + + + + Auto check DCS-BIOS version during startup + - Repair + Auto check DCS-BIOS - :/icons/img/deepin-repair.svg:/icons/img/deepin-repair.svg + :/icons/img/xfsm-reboot.svg:/icons/img/xfsm-reboot.svg + + + + + + + Regular release or live version (need git installed) + + + Use live DCS-BIOS version + + + + :/icons/img/git.svg:/icons/img/git.svg + + + + + + + Git repository address: + + + Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter + + + le_bios_repo + + + + + + + false + + + Git repository with DCS-BIOS. Edit and press ENTER. diff --git a/src/dcspy/utils.py b/src/dcspy/utils.py index cef674456..2bc540c43 100644 --- a/src/dcspy/utils.py +++ b/src/dcspy/utils.py @@ -255,12 +255,14 @@ def check_github_repo(git_ref: str, repo_dir: Path, repo: str, update: bool = Tr :param git_ref: Any Git reference as a string :param repo_dir: Local directory for a repository - :param repo: GitHub repository user/name + :param repo: GitHub repository address :param update: Perform update process :param progress: Progress callback """ bios_repo = _checkout_repo(git_ref=git_ref, repo_dir=repo_dir, repo=repo, progress=progress) - if update: + is_detached = bios_repo.head.is_detached + LOG.debug(f'Repo at: {git_ref} with HEAD detached: {is_detached}') + if update and not is_detached: f_info = bios_repo.remotes[0].pull(progress=progress) LOG.debug(f'Pulled: {f_info[0].name} as: {f_info[0].commit}') git_ref = git_ref.split('/')[1] if 'origin/' in git_ref else git_ref @@ -274,7 +276,7 @@ def _checkout_repo(git_ref: str, repo_dir: Path, repo: str, progress: git.Remote :param git_ref: Any Git reference as a string :param repo_dir: Local repository directory - :param repo: Repository name + :param repo: Repository address :param progress: Progress callback :return: Repo object of the repository """ @@ -284,17 +286,36 @@ def _checkout_repo(git_ref: str, repo_dir: Path, repo: str, progress: git.Remote if is_git_repo(str(repo_dir)): bios_repo = git.Repo(repo_dir) all_refs = get_all_git_refs(repo_dir=repo_dir) - local_branch = git_ref.removeprefix('origin/') - if local_branch in all_refs: - bios_repo.git.checkout(local_branch, force=True) + named_git_obj = git_ref.removeprefix('origin/') + if named_git_obj in all_refs: + bios_repo.git.checkout(named_git_obj, force=True) + elif is_git_sha(repo=bios_repo, ref=named_git_obj): + bios_repo.git.checkout('--detach', named_git_obj, force=True) else: - bios_repo.git.checkout(git_ref, b=local_branch, force=True) + bios_repo.git.checkout(git_ref, b=named_git_obj, force=True) else: rmtree(path=repo_dir, ignore_errors=True) - bios_repo = git.Repo.clone_from(url=f'https://github.com/{repo}.git', to_path=repo_dir, progress=progress) # type: ignore[arg-type] + bios_repo = git.Repo.clone_from(url=repo, to_path=repo_dir, progress=progress) # type: ignore[arg-type] return bios_repo +def is_git_sha(repo: git.Repo, ref: str) -> bool: + """ + Check if a ref is a git commit SHA. + + :param repo: Git Repository object + :param ref: Git commit SHA as string + :return: True if ref is SHA of git commit, False otherwise + """ + import gitdb # type: ignore[import-untyped] + + try: + _ = repo.commit(ref).hexsha + return True + except gitdb.exc.BadName: + return False + + def check_dcs_bios_entry(lua_dst_data: str, lua_dst_path: Path, temp_dir: Path) -> str: """ Check DCS-BIOS entry in Export.lua file. @@ -480,30 +501,33 @@ def _fetch_system_info(conf_dict: dict[str, Any]) -> str: dcs = check_dcs_ver(dcs_path=Path(str(conf_dict['dcs']))) bios_ver = check_bios_ver(bios_path=str(conf_dict['dcsbios'])) repo_dir = Path(str(conf_dict['dcsbios'])).parents[1] / 'dcs-bios' - git_ver, head_commit = _fetch_git_data(repo_dir=repo_dir) + git_ver, head_commit, remote_url = _fetch_git_data(repo_dir=repo_dir) lgs_dir = '\n'.join([ str(Path(dir_path) / filename) for dir_path, _, filenames in walk('C:\\Program Files\\Logitech Gaming Software\\SDK') for filename in filenames ]) - return f'{__version__=}\n{name=}\n{pyver=}\n{pyexec=}\n{dcs=}\n{bios_ver=}\n{git_ver=}\n{head_commit=}\n{lgs_dir}\ncfg={pformat(conf_dict)}' + return f'{__version__=}\n{name=}\n{pyver=}\n{pyexec=}\n{dcs=}\n{bios_ver=}\n{remote_url=}\n{git_ver=}\n{head_commit=}\n{lgs_dir}\ncfg={pformat(conf_dict)}' -def _fetch_git_data(repo_dir: Path) -> tuple[Sequence[int], str]: +def _fetch_git_data(repo_dir: Path) -> tuple[Sequence[int], str, str]: """ Fetch the Git version and SHA of HEAD commit. :param repo_dir: Local directory for repository - :return: Tuple of (a version) and SHA of HEAD commit + :return: Tuple of (a version), SHA of HEAD commit and remote URL """ try: import git git_ver = git.cmd.Git().version_info - head_commit = str(git.Repo(repo_dir).head.commit) + repo = git.Repo(repo_dir) + head_commit = str(repo.head.commit) + remote_url = repo.remotes.origin.url except (git.exc.NoSuchPathError, git.exc.InvalidGitRepositoryError, ImportError): git_ver = (0, 0, 0, 0) head_commit = 'N/A' - return git_ver, head_commit + remote_url = 'N/A' + return git_ver, head_commit, remote_url def _get_dcs_log(conf_dict: dict[str, Any]) -> Path: diff --git a/tests/conftest.py b/tests/conftest.py index 9fd063506..73a82b01b 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -308,7 +308,7 @@ def default_config(): 'verbose': False, 'check_bios': True, 'check_ver': True, 'font_name': models.DEFAULT_FONT_NAME, 'font_mono_m': 11, 'font_mono_s': 9, 'font_mono_l': 16, 'font_color_m': 22, 'font_color_s': 18, 'font_color_l': 32, 'f16_ded_font': True, 'git_bios': True, 'git_bios_ref': 'main', 'toolbar_style': 0, 'toolbar_area': 4, 'gkeys_area': 2, 'gkeys_float': False, 'theme_mode': 'system', 'theme_color': 'dark-blue', 'completer_items': 20, - 'current_plane': 'A-10C', 'api_ver': '3.7.1' + 'current_plane': 'A-10C', 'api_ver': '3.8.0' } diff --git a/tests/resources/config.yaml b/tests/resources/config.yaml index df6ba9936..c779a363d 100644 --- a/tests/resources/config.yaml +++ b/tests/resources/config.yaml @@ -18,6 +18,7 @@ font_mono_s: 9 font_name: consola.ttf git_bios: true git_bios_ref: main +git_bios_repo: https://github.com/DCS-Skunkworks/dcs-bios.git gkeys_area: 2 gkeys_float: false gui_debug: false diff --git a/tests/test_migration.py b/tests/test_migration.py index d3f64767c..2427afaa7 100644 --- a/tests/test_migration.py +++ b/tests/test_migration.py @@ -5,11 +5,11 @@ @mark.parametrize('cfg, result', [ ({'api_ver': '2.9.9', 'v': 1, 'font_color_s': 6, 'theme_mode': 'system'}, - {'api_ver': '3.7.1', 'completer_items': 20, 'current_plane': 'A-10C', 'font_color_m': 6, 'font_color_s': 18, 'font_mono_m': 11, 'font_mono_s': 9, 'v': 1}), + {'api_ver': '3.8.0', 'completer_items': 20, 'current_plane': 'A-10C', 'font_color_m': 6, 'font_color_s': 18, 'font_mono_m': 11, 'font_mono_s': 9, 'v': 1}), ({'api_ver': '3.0.0', 'v': 1, 'font_color_s': 6, 'theme_mode': 'system', 'git_bios_ref': 'master'}, - {'api_ver': '3.7.1', 'font_color_s': 6, 'theme_mode': 'system', 'v': 1, 'git_bios_ref': 'main'}), + {'api_ver': '3.8.0', 'font_color_s': 6, 'theme_mode': 'system', 'v': 1, 'git_bios_ref': 'main'}), ({'v': 1, 'font_color_s': 6, 'theme_mode': 'system'}, - {'api_ver': '3.7.1', 'completer_items': 20, 'current_plane': 'A-10C', 'font_color_m': 6, 'font_color_s': 18, 'font_mono_m': 11, 'font_mono_s': 9, 'v': 1}), + {'api_ver': '3.8.0', 'completer_items': 20, 'current_plane': 'A-10C', 'font_color_m': 6, 'font_color_s': 18, 'font_mono_m': 11, 'font_mono_s': 9, 'v': 1}), ], ids=['API 2.9.9', 'API 3.0.0', 'API empty']) def test_migrate(cfg, result): migrated_cfg = migration.migrate(cfg=cfg) @@ -21,7 +21,7 @@ def test_generate_config(): migrated_cfg = migration.migrate(cfg={}) assert migrated_cfg == { - 'api_ver': '3.7.1', + 'api_ver': '3.8.0', 'autostart': False, 'check_bios': True, 'check_ver': True, @@ -40,6 +40,7 @@ def test_generate_config(): 'font_name': 'consola.ttf', 'git_bios': True, 'git_bios_ref': 'main', + 'git_bios_repo': 'https://github.com/DCS-Skunkworks/dcs-bios.git', 'gkeys_area': 2, 'gkeys_float': False, 'gui_debug': False, diff --git a/tests/test_utils.py b/tests/test_utils.py index d9aa01ae1..0289f0c64 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -88,7 +88,7 @@ def test_dummy_save_load_migrate(tmpdir): assert d_cfg == {'font_mono_s': 9} d_cfg = migrate(cfg=d_cfg) assert d_cfg == { - 'api_ver': '3.7.1', + 'api_ver': '3.8.0', 'device': 'G13', 'save_lcd': False, 'show_gui': True, @@ -113,6 +113,7 @@ def test_dummy_save_load_migrate(tmpdir): 'toolbar_area': 4, 'toolbar_style': 0, 'git_bios_ref': 'main', + 'git_bios_repo': 'https://github.com/DCS-Skunkworks/dcs-bios.git', 'gkeys_area': 2, 'gkeys_float': False, 'gui_debug': False, @@ -190,24 +191,24 @@ def test_is_git_exec_present(): @mark.slow def test_check_github_repo(tmpdir): from re import search - sha = utils.check_github_repo(git_ref='master', update=True, repo='emcek/common_sense', repo_dir=tmpdir) + sha = utils.check_github_repo(git_ref='master', update=True, repo='https://github.com/emcek/common_sense.git', repo_dir=tmpdir) match = search(r'(master)\sfrom:\s\d{2}-\w{3}-\d{4}\s\d{2}:\d{2}:\d{2}\sby:\s.*', sha) assert match.group(1) == 'master' @mark.slow def test_check_github_repo_remote_branch(tmpdir): - ref = utils.check_github_repo(git_ref='master', update=True, repo='emcek/common_sense', repo_dir=tmpdir) + ref = utils.check_github_repo(git_ref='master', update=True, repo='https://github.com/emcek/common_sense.git', repo_dir=tmpdir) assert ref == 'master from: 13-Feb-2021 21:48:11 by: Michal Plichta' - ref = utils.check_github_repo(git_ref='origin/test', update=True, repo='emcek/common_sense', repo_dir=tmpdir) + ref = utils.check_github_repo(git_ref='origin/test', update=True, repo='https://github.com/emcek/common_sense.git', repo_dir=tmpdir) assert ref == 'test from: 13-Feb-2021 21:48:11 by: Michal Plichta' - ref = utils.check_github_repo(git_ref='origin/test', update=True, repo='emcek/common_sense', repo_dir=tmpdir) + ref = utils.check_github_repo(git_ref='origin/test', update=True, repo='https://github.com/emcek/common_sense.git', repo_dir=tmpdir) assert ref == 'test from: 13-Feb-2021 21:48:11 by: Michal Plichta' @mark.slow def test_is_git_object(tmpdir): - utils.check_github_repo(git_ref='master', update=True, repo='emcek/common_sense', repo_dir=tmpdir) + utils.check_github_repo(git_ref='master', update=True, repo='https://github.com/emcek/common_sense.git', repo_dir=tmpdir) assert utils.is_git_object(repo_dir=tmpdir, git_obj='origin/master') is True assert utils.is_git_object(repo_dir=tmpdir, git_obj='master') is True assert utils.is_git_object(repo_dir=tmpdir, git_obj='36f6ecba128e256b4ec0a884b0ec398ea629e3ae') is True @@ -220,8 +221,23 @@ def test_is_git_object(tmpdir): @mark.slow def test_get_all_git_refs(tmpdir): - utils.check_github_repo(git_ref='master', update=True, repo='emcek/common_sense', repo_dir=tmpdir) - assert utils.get_all_git_refs(repo_dir=tmpdir) == ['master', 'origin/HEAD', 'origin/master', 'origin/test'] + utils.check_github_repo(git_ref='master', update=True, repo='https://github.com/emcek/common_sense.git', repo_dir=tmpdir) + assert utils.get_all_git_refs(repo_dir=tmpdir) == ['master', 'origin/HEAD', 'origin/master', 'origin/test', 'v0.1.0'] + + +@mark.slow +@mark.parametrize('ref, result', [ + ('1a8ea4faa11e65aec62281bd9428df59b6b48869', True), + ('1a8ea4f', True), + ('v0.1.0', True), + ('3a8ea4f', False), + ('v1.0.0', False) +], ids=['long sha', 'short sha', 'good tag', 'wrong sha', 'wrong tag']) +def test_is_git_sha(tmpdir, ref, result): + from git import Repo + utils.check_github_repo(git_ref='master', update=False, repo='https://github.com/emcek/common_sense.git', repo_dir=tmpdir) + repo = Repo(tmpdir) + assert utils.is_git_sha(repo=repo, ref=ref) is result def test_check_dcs_bios_entry_no_entry(tmpdir):