├── docs ├── logo.icns ├── logo.ico ├── logo.png ├── compile_resources.sh ├── connect_sensor.gif ├── adjust_hrv_target.gif ├── biofeedback_demo.gif ├── adjust_breathing_pacer.gif ├── bluetooth_specs_heart_rate_service.pdf ├── resources.qrc └── troubleshooting.md ├── .gitignore ├── openhrv ├── __init__.py ├── app.py ├── pacer.py ├── config.py ├── logger.py ├── utils.py ├── model.py ├── sensor.py ├── view.py └── resources.py ├── test ├── profile_app.py └── app.py ├── pyproject.toml ├── .devcontainer.json ├── .github └── workflows │ └── build.yml ├── changelog.md ├── README.md └── LICENSE /docs/logo.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JanCBrammer/OpenHRV/HEAD/docs/logo.icns -------------------------------------------------------------------------------- /docs/logo.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JanCBrammer/OpenHRV/HEAD/docs/logo.ico -------------------------------------------------------------------------------- /docs/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JanCBrammer/OpenHRV/HEAD/docs/logo.png -------------------------------------------------------------------------------- /docs/compile_resources.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | pyside6-rcc resources.qrc -o "../openhrv/resources.py" -------------------------------------------------------------------------------- /docs/connect_sensor.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JanCBrammer/OpenHRV/HEAD/docs/connect_sensor.gif -------------------------------------------------------------------------------- /docs/adjust_hrv_target.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JanCBrammer/OpenHRV/HEAD/docs/adjust_hrv_target.gif -------------------------------------------------------------------------------- /docs/biofeedback_demo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JanCBrammer/OpenHRV/HEAD/docs/biofeedback_demo.gif -------------------------------------------------------------------------------- /docs/adjust_breathing_pacer.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JanCBrammer/OpenHRV/HEAD/docs/adjust_breathing_pacer.gif -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .vscode/ 2 | __pycache__/ 3 | misc/ 4 | build/ 5 | dist/ 6 | *.egg-info 7 | *.profile 8 | .DS_Store 9 | uv.lock 10 | -------------------------------------------------------------------------------- /docs/bluetooth_specs_heart_rate_service.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JanCBrammer/OpenHRV/HEAD/docs/bluetooth_specs_heart_rate_service.pdf -------------------------------------------------------------------------------- /docs/resources.qrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | logo.png 4 | 5 | -------------------------------------------------------------------------------- /openhrv/__init__.py: -------------------------------------------------------------------------------- 1 | # https://py-pkgs.org/04-package-structure 2 | from importlib.metadata import version 3 | 4 | __version__ = version("OpenHRV") # read version from pyproject.toml 5 | -------------------------------------------------------------------------------- /test/profile_app.py: -------------------------------------------------------------------------------- 1 | import cProfile 2 | from test.app import main 3 | import subprocess 4 | 5 | cProfile.run("main()", "openhrv.profile") 6 | subprocess.run(["snakeviz", "openhrv.profile"], check=True) 7 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [project] 2 | name = "OpenHRV" 3 | version = "1.1.0" 4 | # Support all Python versions that are compatible with the PySide6 version. 5 | # See compatibility matrix at https://wiki.qt.io/Qt_for_Python. 6 | requires-python = ">= 3.9" 7 | dependencies = ["PySide6 >= 6.10"] 8 | 9 | [project.optional-dependencies] 10 | dev = ["snakeviz"] 11 | build = ["pyinstaller"] 12 | 13 | [tool.mypy] 14 | check_untyped_defs = true 15 | 16 | [project.gui-scripts] 17 | # command line entry points 18 | openhrv = "openhrv.app:main" 19 | -------------------------------------------------------------------------------- /openhrv/app.py: -------------------------------------------------------------------------------- 1 | import sys 2 | from PySide6.QtWidgets import QApplication 3 | from openhrv.view import View 4 | from openhrv.model import Model 5 | 6 | 7 | class Application(QApplication): 8 | def __init__(self, sys_argv): 9 | super(Application, self).__init__(sys_argv) 10 | self._model = Model() 11 | self._view = View(self._model) 12 | 13 | 14 | def main(): 15 | app = Application(sys.argv) 16 | app._view.show() 17 | sys.exit(app.exec()) 18 | 19 | 20 | if __name__ == "__main__": 21 | main() 22 | -------------------------------------------------------------------------------- /.devcontainer.json: -------------------------------------------------------------------------------- 1 | // https://containers.dev/implementors/json_reference/ 2 | { 3 | "name": "OpenHRV", 4 | "image": "python:3.12", 5 | "customizations": { 6 | "vscode": { 7 | "extensions": [ 8 | "ms-python.python", 9 | "ms-python.vscode-pylance", 10 | "ms-python.mypy-type-checker", 11 | "KevinRose.vsc-python-indent", 12 | "streetsidesoftware.code-spell-checker", 13 | "tamasfe.even-better-toml", 14 | "eamodio.gitlens", 15 | "GitHub.copilot", 16 | "charliermarsh.ruff" 17 | ], 18 | "settings": { 19 | "[python]": { 20 | "editor.formatOnSave": true, 21 | "editor.defaultFormatter": "charliermarsh.ruff" 22 | } 23 | } 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: build 2 | 3 | on: 4 | workflow_dispatch: 5 | release: 6 | types: 7 | - published 8 | 9 | jobs: 10 | 11 | build: 12 | 13 | runs-on: ubuntu-24.04 14 | 15 | steps: 16 | 17 | - uses: actions/checkout@v4 18 | 19 | - uses: actions/setup-python@v5 20 | with: 21 | python-version: "3.12" 22 | 23 | - name: Install dependencies 24 | run: | 25 | python -m pip install --upgrade pip 26 | python -m pip install -e .[build] 27 | 28 | - name: release build 29 | if: github.event_name == 'release' 30 | run: | 31 | pyinstaller --onefile --icon=docs/logo.ico --name=OpenHRV.bin openhrv/app.py --windowed 32 | 33 | - name: manual build 34 | if: github.event_name == 'workflow_dispatch' 35 | run: | 36 | pyinstaller --onefile --icon=docs/logo.ico --name=OpenHRV.bin openhrv/app.py 37 | 38 | - name: upload build artifact 39 | uses: actions/upload-artifact@v4 40 | with: 41 | name: OpenHRV 42 | path: dist/OpenHRV.bin 43 | 44 | - name: upload build artifact to release 45 | if: github.event_name == 'release' 46 | env: 47 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # token generated implicitly 48 | # See https://cli.github.com/manual/gh_release_upload. 49 | run: | 50 | gh release upload ${{ github.ref_name }} dist/OpenHRV.bin 51 | -------------------------------------------------------------------------------- /openhrv/pacer.py: -------------------------------------------------------------------------------- 1 | import math 2 | import time 3 | from PySide6.QtCore import QObject 4 | 5 | 6 | class Pacer(QObject): 7 | def __init__(self): 8 | super().__init__() 9 | 10 | n_samples: int = 40 11 | increment: float = 2 * math.pi / n_samples 12 | theta: list[float] = [i * increment for i in range(n_samples + 1)] 13 | self.cos_theta: list[float] = list(map(math.cos, theta)) 14 | self.sin_theta: list[float] = list(map(math.sin, theta)) 15 | 16 | def breathing_pattern(self, breathing_rate: float, time: float) -> float: 17 | """Returns radius of pacer disk. 18 | 19 | Radius is modulated according to sinusoidal breathing pattern 20 | and scaled between 0 and 1. 21 | """ 22 | return 0.5 + 0.5 * math.sin(2 * math.pi * breathing_rate / 60 * time) 23 | 24 | def update(self, breathing_rate: float) -> tuple[list[float], list[float]]: 25 | """Update radius of pacer disc. 26 | 27 | Make current disk radius a function of real time (i.e., don't 28 | precompute radii with fixed time interval) in order to compensate for 29 | jitter or delay in QTimer calls. 30 | """ 31 | radius = self.breathing_pattern(breathing_rate, time.time()) 32 | x: list[float] = [i * radius for i in self.cos_theta] 33 | y: list[float] = [i * radius for i in self.sin_theta] 34 | 35 | return (x, y) 36 | -------------------------------------------------------------------------------- /openhrv/config.py: -------------------------------------------------------------------------------- 1 | from typing import Final 2 | from math import ceil 3 | 4 | 5 | IBI_MEDIAN_WINDOW: Final[int] = 11 # samples 6 | EWMA_WEIGHT_CURRENT_SAMPLE: Final[float] = ( 7 | 0.1 # set in range [0, 1], 1 being minimal smoothing, see https://en.wikipedia.org/wiki/Exponential_smoothing 8 | ) 9 | 10 | MIN_BREATHING_RATE: Final[float] = 4.0 # breaths per minute 11 | MAX_BREATHING_RATE: Final[float] = 7.0 # breaths per minute 12 | MIN_HRV_TARGET: Final[int] = 50 13 | MAX_HRV_TARGET: Final[int] = 600 14 | min_heart_rate = 30 15 | max_heart_rate = 220 16 | MIN_IBI: Final[int] = ceil(60_000 / max_heart_rate) 17 | MAX_IBI: Final[int] = ceil(60_000 / min_heart_rate) 18 | MIN_PLOT_IBI: Final[int] = 300 19 | MAX_PLOT_IBI: Final[int] = 1500 20 | 21 | # IBI buffer must hold enough samples such that even if IBIs (on average) were 22 | # MIN_IBI long, there'd be enough samples to display for IBI_HISTORY_DURATION seconds. 23 | IBI_HISTORY_DURATION: Final[int] = 60 # seconds 24 | IBI_BUFFER_SIZE: Final[int] = ceil(IBI_HISTORY_DURATION / (MIN_IBI / 1000)) # samples 25 | HRV_HISTORY_DURATION: Final[int] = 120 # seconds 26 | HRV_BUFFER_SIZE: Final[int] = ceil(HRV_HISTORY_DURATION / (MIN_IBI / 1000)) # samples 27 | 28 | COMPATIBLE_SENSORS: Final[list[str]] = ["Polar", "Decathlon Dual HR"] 29 | 30 | 31 | def tick_to_breathing_rate(tick: int) -> float: 32 | return (tick + 8) / 2 # scale tick to [4, 7], step .5 33 | 34 | 35 | def breathing_rate_to_tick(rate: float) -> int: 36 | return ceil(rate * 2 - 8) # scale rate to [0, 6], step 1 37 | -------------------------------------------------------------------------------- /openhrv/logger.py: -------------------------------------------------------------------------------- 1 | from datetime import datetime 2 | from PySide6.QtCore import QObject, Signal 3 | from openhrv.utils import NamedSignal 4 | 5 | 6 | class Logger(QObject): 7 | recording_status = Signal(int) 8 | status_update = Signal(str) 9 | 10 | def __init__(self): 11 | super().__init__() 12 | self.file = None 13 | 14 | def start_recording(self, file_path: str): 15 | if self.file: 16 | self.status_update.emit(f"Already writing to a file at {self.file.name}.") 17 | return # only write to one file at a time 18 | self.file = open(file_path, "a+") 19 | self.file.write("event,value,timestamp\n") # header 20 | self.recording_status.emit(0) 21 | self.status_update.emit(f"Started recording to {self.file.name}.") 22 | 23 | def save_recording(self): 24 | """Called when: 25 | 1. User saves recording. 26 | 2. User closes app while recording 27 | """ 28 | if not self.file: 29 | return 30 | self.file.close() 31 | self.recording_status.emit(1) 32 | self.status_update.emit(f"Saved recording at {self.file.name}.") 33 | self.file = None 34 | 35 | def write_to_file(self, data: NamedSignal): 36 | if not self.file: 37 | return 38 | key, val = data 39 | if isinstance(val, list): 40 | val = val[-1] 41 | if isinstance(val, tuple): 42 | val = val[-1][-1] 43 | timestamp = datetime.now().isoformat() 44 | self.file.write(f"{key},{val},{timestamp}\n") 45 | -------------------------------------------------------------------------------- /changelog.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | ### Version 1.1.1 (December 19 2025) 4 | + enhancement: Bumped PySide6 to version 6.10. 5 | 6 | ### Version 1.1.0 (December 15 2024) 7 | + enhancement: Computing HRV as exponentially weighted moving average (https://en.wikipedia.org/wiki/Exponential_smoothing). 8 | + enhancement: Accepting Decathlon HR sensor (thanks S73ph4n). 9 | 10 | ### Version 1.0.1 (November 30 2024) 11 | + enhancement: Relaxed Python version constraints. 12 | + enhancement: Bumped PySide6 to version 6.8. 13 | + enhancement: Bumped Python to version 3.12. 14 | + bugfix: Improved sensor UUID validation (thanks Mirkan Çalışkan (mirkancal)). 15 | 16 | ### Version 1.0.0 (April 29 2024) 17 | + enhancement: Added docs on building macOS with PyInstaller in order to deal with Bluetooth permissions (thanks cyclemaxwell). 18 | + enhancement: Show version in GUI. 19 | + enhancement: Removed PyQtGraph and NumPy dependencies. 20 | + enhancement: Bumped PySide6 to version 6.7.0. 21 | + enhancement: Bumped Python to version 3.11. 22 | 23 | ### Version 0.2.0 (April 23, 2022) 24 | + enhancement: Removed recording of Redis channels (removed Redis dependency). 25 | + enhancement: Handling Bluetooth connection with QtBluetooth instead of bleak (removed bleak dependency). 26 | 27 | ### Version 0.1.3 (January 08, 2022) 28 | + enhancement: Improved Bluetooth connection (thanks Marc Schlaich (schlamar)). 29 | + bugfix: No more connection attempt with empty address menu. 30 | 31 | ### Version 0.1.2 (May 18, 2021) 32 | + enhancement: Local HRV is now averaged over a fixed window of 15 seconds. Removed slider for HRV mean window size. 33 | + enhancement: Status messages on application state are now displayed in the GUI. 34 | + enhancement: Added recording- and Redis interface features (undocumented at time of release). 35 | + enhancement: Rejecting some artifacts in inter-beat-intervals as well as local HRV. 36 | + bugfix: Made validation of sensor addresses platform-specific (thanks Alexander Weuthen (alexweuthen)). 37 | 38 | ### Version 0.1.1 (January 13, 2021) 39 | + enhancement: Visibility of breathing pacer can be toggled. 40 | + enhancement: Made range of breathing pacer rates more granular (step size .5 instead of 1). 41 | 42 | ### Version 0.1.0 (January 07, 2021) 43 | + enhancement: Initial release. 44 | -------------------------------------------------------------------------------- /openhrv/utils.py: -------------------------------------------------------------------------------- 1 | import re 2 | import platform 3 | from pathlib import Path 4 | from collections import namedtuple 5 | from PySide6.QtBluetooth import QBluetoothDeviceInfo 6 | 7 | 8 | NamedSignal = namedtuple("NamedSignal", "name value") 9 | 10 | 11 | def get_sensor_address(sensor: QBluetoothDeviceInfo) -> str: 12 | """Return MAC (Windows, Linux) or UUID (macOS).""" 13 | system = platform.system() 14 | sensor_address = "" 15 | if system in ["Linux", "Windows"]: 16 | sensor_address = sensor.address().toString() 17 | elif system == "Darwin": 18 | sensor_address = sensor.deviceUuid().toString().strip("{}") 19 | 20 | return sensor_address 21 | 22 | 23 | def get_sensor_remote_address(sensor) -> str: 24 | """Return MAC (Windows, Linux) or UUID (macOS).""" 25 | system = platform.system() 26 | sensor_remote_address = "" 27 | if system in ["Linux", "Windows"]: 28 | sensor_remote_address = sensor.remoteAddress().toString() 29 | elif system == "Darwin": 30 | sensor_remote_address = sensor.remoteDeviceUuid().toString().strip("{}") 31 | 32 | return sensor_remote_address 33 | 34 | 35 | def valid_address(address: str) -> bool: 36 | """Make sure that MAC (Windows, Linux) or UUID (macOS) is valid.""" 37 | system = platform.system() 38 | regex = "" 39 | if system in ["Linux", "Windows"]: 40 | regex = r"[0-9a-f]{2}([-:]?)[0-9a-f]{2}(\1[0-9a-f]{2}){4}$" 41 | elif system == "Darwin": 42 | # Allow for any valid UUID 43 | regex = r"[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$" 44 | 45 | return bool(re.compile(regex, re.IGNORECASE).match(address)) 46 | 47 | 48 | def valid_path(path: str) -> bool: 49 | """Make sure that path is valid by OS standards and that a file doesn't 50 | exist on that path already. No builtin solution for this atm.""" 51 | valid = False 52 | test_path = Path(path) 53 | try: 54 | test_path.touch(exist_ok=False) # create file 55 | test_path.unlink() # remove file (only called if file doesn't exist) 56 | valid = True 57 | except OSError: # path exists or is invalid 58 | pass 59 | 60 | return valid 61 | 62 | 63 | def sign(value: int) -> int: 64 | if value > 0: 65 | return 1 66 | elif value < 0: 67 | return -1 68 | return value 69 | -------------------------------------------------------------------------------- /docs/troubleshooting.md: -------------------------------------------------------------------------------- 1 | # Troubleshooting 2 | 3 | If you have trouble connecting (or staying connected) to your Polar sensor, try (a combination of) the following: 4 | - Turn Bluetooth off and on again. 5 | - Un-pair and re-pair the sensor. 6 | - Reset the sensor (https://support.polar.com/en/support/how_to_reset_my_heart_rate_sensor). 7 | 8 | ## Linux 9 | You might have to install (some of) the dependencies for connecting to the X11 server: 10 | - https://doc.qt.io/qt-6/linux-requirements.html 11 | - https://doc.qt.io/qt-6/linux.html 12 | 13 | ## Windows 14 | `OpenHRV` has been tested on Windows 10, but there seem to be Bluetooth problems on Windows 11. 15 | Have a look at the issues (open and closed) labeled with `Windows`. 16 | 17 | ## MacOS 18 | :warning: Those instructions aren't verified for releases > [0.2.0](https://github.com/JanCBrammer/OpenHRV/releases/tag/v0.2.0) :warning: 19 | 20 | Clone the repository and run `pyinstaller mac_os_app.spec --clean --noconfirm` from the project root 21 | in a Python environment that contains the dependencies specified in 22 | [pyproject.toml](https://github.com/JanCBrammer/OpenHRV/blob/main/pyproject.toml) (including `build` dependencies). 23 | The `mac_os_app.spec` file should look as follows: 24 | 25 | ``` 26 | # -*- mode: python ; coding: utf-8 -*- 27 | 28 | block_cipher = None 29 | 30 | a = Analysis( 31 | ["openhrv/app.py"], 32 | pathex=["./openhrv"], 33 | binaries=[], 34 | datas=[], 35 | hiddenimports=[], 36 | hookspath=[], 37 | hooksconfig={}, 38 | runtime_hooks=[], 39 | excludes=[], 40 | win_no_prefer_redirects=False, 41 | win_private_assemblies=False, 42 | cipher=block_cipher, 43 | noarchive=False, 44 | ) 45 | pyz = PYZ(a.pure, a.zipped_data, cipher=block_cipher) 46 | 47 | exe = EXE( 48 | pyz, 49 | a.scripts, 50 | [], 51 | exclude_binaries=True, 52 | name="app", 53 | debug=False, 54 | bootloader_ignore_signals=False, 55 | strip=False, 56 | upx=True, 57 | console=False, 58 | disable_windowed_traceback=False, 59 | argv_emulation=False, 60 | target_arch=None, 61 | codesign_identity=None, 62 | entitlements_file=None, 63 | ) 64 | coll = COLLECT( 65 | exe, 66 | a.binaries, 67 | a.zipfiles, 68 | a.datas, 69 | strip=False, 70 | upx=True, 71 | upx_exclude=[], 72 | name="app", 73 | ) 74 | app = BUNDLE( 75 | coll, 76 | name="openhrv.app", 77 | icon="docs/logo.icns", 78 | bundle_identifier=None, 79 | info_plist={ 80 | "NSBluetoothAlwaysUsageDescription": "This application uses a bluetooth sensor" 81 | }, 82 | ) 83 | ``` 84 | 85 | A macOS app bundle will be created at `OpenHRV/dist/openhrv.app`. 86 | This can be loaded directly by clicking on it, or if you wish to see terminal debug messages, 87 | you can execute from the project root `./dist/openhrv.app/Contents/MacOS/app`. 88 | The first run takes extra time. 89 | 90 | Also look at the issues (open and closed) labeled with `macOS`. 91 | -------------------------------------------------------------------------------- /test/app.py: -------------------------------------------------------------------------------- 1 | import math 2 | import time 3 | import uuid 4 | from random import randint 5 | from PySide6.QtCore import QObject, Signal, QTimer 6 | from openhrv.utils import get_sensor_address 7 | 8 | 9 | class MockBluetoothMac: 10 | def __init__(self, mac): 11 | self._mac = mac 12 | 13 | def toString(self): 14 | return self._mac 15 | 16 | 17 | class MockBluetoothUuid: 18 | def __init__(self, uuid): 19 | self._uuid = uuid 20 | 21 | def toString(self): 22 | return f"{self._uuid}" 23 | 24 | 25 | class MockSensor: 26 | def __init__(self): 27 | self._mac = MockBluetoothMac( 28 | ":".join([f"{randint(0, 255):02x}" for _ in range(6)]) 29 | ) 30 | self._uuid = MockBluetoothUuid(uuid.uuid4()) 31 | self._name = "MockSensor" 32 | 33 | def name(self): 34 | return self._name 35 | 36 | def address(self): 37 | return self._mac 38 | 39 | def deviceUuid(self): 40 | return self._uuid 41 | 42 | 43 | class MockSensorScanner(QObject): 44 | sensor_update = Signal(object) 45 | status_update = Signal(str) 46 | 47 | def scan(self): 48 | polar_sensors = [MockSensor() for _ in range(3)] 49 | self.sensor_update.emit(polar_sensors) 50 | self.status_update.emit(f"Found {len(polar_sensors)} sensor(s).") 51 | 52 | 53 | class MockSensorClient(QObject): 54 | ibi_update = Signal(object) 55 | status_update = Signal(str) 56 | 57 | def __init__(self): 58 | super().__init__() 59 | # Polar sensor emits a (package of) IBI(s) about every second. 60 | # Here we "emit" / simulate IBI(s) in quicker succession in order to push the rendering. 61 | self.mean_ibi = 900 62 | self.timer = QTimer() 63 | self.timer.setInterval(self.mean_ibi) 64 | self.timer.timeout.connect(self.simulate_ibi) 65 | 66 | def connect_client(self, sensor): 67 | self.status_update.emit( 68 | f"Connecting to sensor at {get_sensor_address(sensor)}." 69 | ) 70 | self.timer.start() 71 | 72 | def disconnect_client(self): 73 | self.status_update.emit("Disconnecting from sensor.") 74 | self.timer.stop() 75 | 76 | def simulate_ibi(self): 77 | # IBIs fluctuate at a rate of `breathing_rate` 78 | # in a sinusoidal pattern around `mean_ibi`, 79 | # in a range of `range_ibi`. 80 | breathing_rate = 6 81 | range_ibi = 100 # without noise, HRV settles at this value 82 | ibi = self.mean_ibi + (range_ibi / 2) * math.sin( 83 | 2 * math.pi * breathing_rate / 60 * time.time() 84 | ) 85 | # add noise spikes 86 | if randint(1, 30) == 1: 87 | if randint(1, 2) == 1: 88 | ibi += 500 89 | else: 90 | ibi -= 500 91 | self.ibi_update.emit(ibi) 92 | 93 | 94 | def main(): 95 | """Mock sensor classes. 96 | 97 | Mock classes need to replace their mocked counterparts in namespace before 98 | the latter are imported elsewhere: 99 | https://stackoverflow.com/questions/3765222/monkey-patch-python-class 100 | """ 101 | from openhrv import sensor # noqa 102 | 103 | sensor.SensorClient = MockSensorClient 104 | sensor.SensorScanner = MockSensorScanner 105 | 106 | from openhrv.app import main as mock_main # noqa 107 | 108 | mock_main() 109 | 110 | 111 | if __name__ == "__main__": 112 | main() 113 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # OpenHRV 4 | 5 | A desktop application for heart rate variability (HRV) biofeedback training with ECG chest straps. 6 | 7 | ## Compatible sensors 8 | - Polar H7, H9, H10 9 | - Decathlon Dual HR (model ZT26D) 10 | 11 | ## Installation 12 | 13 | It is highly recommended to install the project in a virtual Python environment, 14 | e.g., using [conda](https://docs.python.org/3/library/venv.html) or 15 | [venv](https://docs.python.org/3/library/venv.html). 16 | The required Python version is specified in 17 | [pyproject.toml](https://github.com/JanCBrammer/OpenHRV/blob/main/pyproject.toml). 18 | 19 | In your Python environment, clone the repository, and subsequently run 20 | 21 | ``` 22 | pip install . 23 | ``` 24 | 25 | in the root of the repository. Alternatively, you can skip cloning by running 26 | 27 | ``` 28 | pip install git+https://github.com/JanCBrammer/OpenHRV.git 29 | ``` 30 | 31 | You can now start the application with 32 | 33 | ``` 34 | python -m openhrv.app 35 | ``` 36 | 37 | or alternatively, with the shortcut 38 | 39 | ``` 40 | openhrv 41 | ``` 42 | I tested `OpenHRV` on Ubuntu 24.04. It _should_ run on Windows and macOS as well, however, I haven't confirmed that myself. 43 | If you have problems running `OpenHRV` have a look at [docs/troubleshooting.md](docs/troubleshooting.md). 44 | 45 | ## Ubuntu executable 46 | 47 | On Ubuntu, download and run [OpenHRV.bin](https://github.com/JanCBrammer/OpenHRV/releases/latest), no installation required. 48 | 49 | ## User Guide 50 | 51 | ### Connect your ECG sensor 52 | First make sure the sensor is paired with your computer 53 | (i.e., find and pair the sensor in your computer's Bluetooth settings). 54 | Then search the sensor in **OpenHRV** by clicking `Scan`. The addresses of all 55 | paired sensors show up in the drop-down menu. Select your sensor from the 56 | drop-down menu and click `Connect` in order to establish a connection. You can 57 | disconnect the sensor anytime by clicking `Disconnect`. Disconnecting is useful 58 | if you want to connect to another sensor, or if an error occurs with the connection. 59 | Should you have problems with the connection try disconnecting, and then reconnecting 60 | the sensor. 61 | 62 | ![connect_sensor](https://github.com/JanCBrammer/OpenHRV/raw/main/docs/connect_sensor.gif) 63 | 64 | ### Set an HRV target 65 | You can personalize the HRV target using the `Target` slider. After you've 66 | been training for a while you will have a good idea of what's an attainable target 67 | for you (this can vary depending on how much sleep or coffee you had etc.). You 68 | can adjust the target anytime if you find the current target too easy or difficult. 69 | 70 | ![adjust_hrv_target](https://github.com/JanCBrammer/OpenHRV/raw/main/docs/adjust_hrv_target.gif) 71 | 72 | ### Set a breathing pace 73 | The breathing pacer can help you increase your HRV. Breathe out as the blue 74 | disk shrinks and breathe in as it gets larger. Explore how different breathing rates 75 | affect your HRV by adjusting the `Rate` slider anytime during a session. Everyone 76 | has a personal breathing rate at which their HRV is at its highest. Usually that 77 | rate is somewhere between 4 and 7 breaths per minute. You can also hide the pacer 78 | by unchecking the `Show pacer` box if you want to practice regulating HRV without pacing. 79 | 80 | ![adjust_breathing_pacer](https://github.com/JanCBrammer/OpenHRV/raw/main/docs/adjust_breathing_pacer.gif) 81 | 82 | 83 | ### Biofeedback training 84 | Below you can watch heart rate variability (HRV) biofeedback training in action. Note 85 | how the blue heart rate curve rises and falls. These fluctuations are the "variability" 86 | in HRV. Your goal is to get the fluctuations large and regular. As you get better at this, 87 | the white HRV curve will go up. There is no "ideal" HRV, as in "everyone should achieve 88 | an HRV of 500 msec". Try to increase HRV relative to what you have achieved before 89 | and be aware that it can take a fair bit of practice to improve. 90 | 91 | ![biofeedback_demo](https://github.com/JanCBrammer/OpenHRV/raw/main/docs/biofeedback_demo.gif) 92 | -------------------------------------------------------------------------------- /openhrv/model.py: -------------------------------------------------------------------------------- 1 | import statistics 2 | import math 3 | from collections import deque 4 | from itertools import islice 5 | from PySide6.QtCore import QObject, Signal, Slot 6 | from PySide6.QtBluetooth import QBluetoothDeviceInfo 7 | from openhrv.utils import get_sensor_address, sign, NamedSignal 8 | from openhrv.config import ( 9 | tick_to_breathing_rate, 10 | HRV_BUFFER_SIZE, 11 | IBI_BUFFER_SIZE, 12 | MAX_BREATHING_RATE, 13 | MIN_IBI, 14 | MAX_IBI, 15 | IBI_MEDIAN_WINDOW, 16 | MIN_HRV_TARGET, 17 | MAX_HRV_TARGET, 18 | EWMA_WEIGHT_CURRENT_SAMPLE, 19 | ) 20 | 21 | 22 | class Model(QObject): 23 | ibis_buffer_update = Signal(NamedSignal) 24 | hrv_update = Signal(NamedSignal) 25 | addresses_update = Signal(NamedSignal) 26 | pacer_rate_update = Signal(NamedSignal) 27 | hrv_target_update = Signal(NamedSignal) 28 | 29 | def __init__(self): 30 | super().__init__() 31 | # Once a bounded length deque is full, when new items are added, 32 | # a corresponding number of items are discarded from the opposite end. 33 | self.ibis_buffer: deque[int] = deque([1000] * IBI_BUFFER_SIZE, IBI_BUFFER_SIZE) 34 | self.ibis_seconds: deque[float] = deque( 35 | map(float, range(-IBI_BUFFER_SIZE, 1)), IBI_BUFFER_SIZE 36 | ) 37 | self.hrv_buffer: deque[float] = deque([-1] * HRV_BUFFER_SIZE, HRV_BUFFER_SIZE) 38 | self.hrv_seconds: deque[float] = deque( 39 | map(float, range(-HRV_BUFFER_SIZE, 1)), HRV_BUFFER_SIZE 40 | ) 41 | 42 | # Exponentially Weighted Moving Average: 43 | # - https://en.wikipedia.org/wiki/Moving_average#Exponential_moving_average 44 | # - https://en.wikipedia.org/wiki/Exponential_smoothing 45 | # - http://nestedsoftware.com/2018/04/04/exponential-moving-average-on-streaming-data-4hhl.24876.html 46 | self.ewma_hrv: float = 1.0 47 | self.sensors: list[QBluetoothDeviceInfo] = [] 48 | self.breathing_rate: float = float(MAX_BREATHING_RATE) 49 | self.hrv_target: int = math.ceil((MIN_HRV_TARGET + MAX_HRV_TARGET) / 2) 50 | self._last_ibi_phase: int = -1 51 | self._last_ibi_extreme: int = 0 52 | self._duration_current_phase: int = 0 53 | 54 | @Slot(int) 55 | def update_ibis_buffer(self, ibi: int): 56 | validated_ibi = self.validate_ibi(ibi) 57 | self.update_ibis_seconds(validated_ibi / 1000) 58 | self.ibis_buffer.append(validated_ibi) 59 | self.ibis_buffer_update.emit( 60 | NamedSignal("InterBeatInterval", (self.ibis_seconds, self.ibis_buffer)) 61 | ) 62 | self.compute_local_hrv() 63 | 64 | @Slot(int) 65 | def update_breathing_rate(self, breathing_tick: int): 66 | self.breathing_rate = tick_to_breathing_rate(breathing_tick) 67 | self.pacer_rate_update.emit(NamedSignal("PacerRate", self.breathing_rate)) 68 | 69 | @Slot(int) 70 | def update_hrv_target(self, hrv_target: int): 71 | self.hrv_target = hrv_target 72 | self.hrv_target_update.emit(NamedSignal("HrvTarget", hrv_target)) 73 | 74 | @Slot(object) 75 | def update_sensors(self, sensors: list[QBluetoothDeviceInfo]): 76 | self.sensors = sensors 77 | self.addresses_update.emit( 78 | NamedSignal( 79 | "Sensors", [f"{s.name()}, {get_sensor_address(s)}" for s in sensors] 80 | ) 81 | ) 82 | 83 | def validate_ibi(self, ibi: int) -> int: 84 | validated_ibi: int = ibi 85 | if ibi < MIN_IBI or ibi > MAX_IBI: 86 | median_ibi: int = math.ceil( 87 | statistics.median( 88 | islice( 89 | self.ibis_buffer, 90 | len(self.ibis_buffer) - IBI_MEDIAN_WINDOW, 91 | None, 92 | ) 93 | ) 94 | ) 95 | if median_ibi < MIN_IBI: 96 | validated_ibi = MIN_IBI 97 | elif median_ibi > MAX_IBI: 98 | validated_ibi = MAX_IBI 99 | else: 100 | validated_ibi = median_ibi 101 | print(f"Correcting outlier IBI {ibi} to {validated_ibi}") 102 | 103 | return validated_ibi 104 | 105 | def validate_hrv(self, hrv: int) -> int: 106 | validated_hrv: int = hrv 107 | if hrv > MAX_HRV_TARGET: 108 | validated_hrv = min(math.ceil(self.ewma_hrv), MAX_HRV_TARGET) 109 | print(f"Correcting outlier HRV {hrv} to {validated_hrv}") 110 | 111 | return validated_hrv 112 | 113 | def compute_local_hrv(self): 114 | """https://doi.org/10.1038/s41598-019-44201-7 (Figure 2)""" 115 | self._duration_current_phase += self.ibis_buffer[-1] 116 | # 1: IBI rises, -1: IBI falls, 0: IBI constant 117 | current_ibi_phase: int = sign(self.ibis_buffer[-1] - self.ibis_buffer[-2]) 118 | if current_ibi_phase == 0: 119 | return 120 | if current_ibi_phase == self._last_ibi_phase: 121 | return 122 | 123 | current_ibi_extreme: int = self.ibis_buffer[-2] 124 | local_hrv: int = abs(self._last_ibi_extreme - current_ibi_extreme) 125 | self.update_hrv_buffer(local_hrv) 126 | 127 | seconds_current_phase: float = self._duration_current_phase / 1000 128 | self.update_hrv_seconds(seconds_current_phase) 129 | self._duration_current_phase = 0 130 | 131 | self._last_ibi_extreme = current_ibi_extreme 132 | self._last_ibi_phase = current_ibi_phase 133 | 134 | def update_hrv_buffer(self, local_hrv: int): 135 | self.ewma_hrv = ( 136 | EWMA_WEIGHT_CURRENT_SAMPLE * self.validate_hrv(local_hrv) 137 | + (1 - EWMA_WEIGHT_CURRENT_SAMPLE) * self.ewma_hrv 138 | ) 139 | 140 | self.hrv_buffer.append(self.ewma_hrv) 141 | self.hrv_update.emit( 142 | NamedSignal("HeartRateVariability", (self.hrv_seconds, self.hrv_buffer)) 143 | ) 144 | 145 | def update_ibis_seconds(self, seconds: float): 146 | self.ibis_seconds = deque( 147 | [i - seconds for i in self.ibis_seconds], IBI_BUFFER_SIZE 148 | ) 149 | self.ibis_seconds.append(0.0) 150 | 151 | def update_hrv_seconds(self, seconds: float): 152 | self.hrv_seconds = deque( 153 | [i - seconds for i in self.hrv_seconds], HRV_BUFFER_SIZE 154 | ) 155 | self.hrv_seconds.append(0.0) 156 | -------------------------------------------------------------------------------- /openhrv/sensor.py: -------------------------------------------------------------------------------- 1 | from PySide6.QtCore import QObject, Signal, QByteArray 2 | from PySide6.QtBluetooth import ( 3 | QBluetoothDeviceDiscoveryAgent, 4 | QLowEnergyController, 5 | QLowEnergyService, 6 | QLowEnergyCharacteristic, 7 | QBluetoothUuid, 8 | QBluetoothDeviceInfo, 9 | QLowEnergyDescriptor, 10 | ) 11 | from math import ceil 12 | from typing import Union 13 | from openhrv.utils import get_sensor_address, get_sensor_remote_address 14 | from openhrv.config import COMPATIBLE_SENSORS 15 | 16 | 17 | class SensorScanner(QObject): 18 | sensor_update = Signal(object) 19 | status_update = Signal(str) 20 | 21 | def __init__(self): 22 | super().__init__() 23 | self.scanner = QBluetoothDeviceDiscoveryAgent() 24 | self.scanner.finished.connect(self._handle_scan_result) 25 | self.scanner.errorOccurred.connect(self._handle_scan_error) 26 | 27 | def scan(self): 28 | if self.scanner.isActive(): 29 | self.status_update.emit("Already searching for sensors.") 30 | return 31 | self.status_update.emit("Searching for sensors (this might take a while).") 32 | self.scanner.start() 33 | 34 | def _handle_scan_result(self): 35 | sensors: list[QBluetoothDeviceInfo] = [ 36 | d 37 | for d in self.scanner.discoveredDevices() 38 | if (any(cs in d.name() for cs in COMPATIBLE_SENSORS)) and (d.rssi() <= 0) 39 | ] # https://www.mokoblue.com/measures-of-bluetooth-rssi/ 40 | if not sensors: 41 | self.status_update.emit("Couldn't find sensors.") 42 | return 43 | self.sensor_update.emit(sensors) 44 | self.status_update.emit(f"Found {len(sensors)} sensor(s).") 45 | 46 | def _handle_scan_error(self, error): 47 | print(error) 48 | 49 | 50 | class SensorClient(QObject): 51 | """ 52 | Connect to an ECG sensor that acts as a Bluetooth server / peripheral. 53 | On Windows, the sensor must already be paired with the machine running 54 | OpenHRV. Pairing isn't implemented in Qt6. 55 | 56 | In Qt terminology client=central, server=peripheral. 57 | """ 58 | 59 | ibi_update = Signal(object) 60 | status_update = Signal(str) 61 | 62 | def __init__(self): 63 | super().__init__() 64 | self.client: Union[None, QLowEnergyController] = None 65 | self.hr_service: Union[None, QLowEnergyService] = None 66 | self.hr_notification: Union[None, QLowEnergyDescriptor] = None 67 | self.ENABLE_NOTIFICATION: QByteArray = QByteArray.fromHex(b"0100") 68 | self.DISABLE_NOTIFICATION: QByteArray = QByteArray.fromHex(b"0000") 69 | self.HR_SERVICE: QBluetoothUuid.ServiceClassUuid = ( 70 | QBluetoothUuid.ServiceClassUuid.HeartRate 71 | ) 72 | self.HR_CHARACTERISTIC: QBluetoothUuid.CharacteristicType = ( 73 | QBluetoothUuid.CharacteristicType.HeartRateMeasurement 74 | ) 75 | 76 | def _sensor_address(self): 77 | return get_sensor_remote_address(self.client) 78 | 79 | def connect_client(self, sensor: QBluetoothDeviceInfo): 80 | if self.client is not None: 81 | msg = ( 82 | f"Currently connected to sensor at {self._sensor_address()}." 83 | " Please disconnect before (re-)connecting to (another) sensor." 84 | ) 85 | self.status_update.emit(msg) 86 | return 87 | self.status_update.emit( 88 | f"Connecting to sensor at {get_sensor_address(sensor)} (this might take a while)." 89 | ) 90 | self.client = QLowEnergyController.createCentral(sensor) 91 | self.client.errorOccurred.connect(self._catch_error) 92 | self.client.connected.connect(self._discover_services) 93 | self.client.discoveryFinished.connect(self._connect_hr_service) 94 | self.client.disconnected.connect(self._reset_connection) 95 | self.client.connectToDevice() 96 | 97 | def disconnect_client(self): 98 | if self.hr_notification is not None and self.hr_service is not None: 99 | if not self.hr_notification.isValid(): 100 | return 101 | print("Unsubscribing from HR service.") 102 | self.hr_service.writeDescriptor( 103 | self.hr_notification, self.DISABLE_NOTIFICATION 104 | ) 105 | if self.client is not None: 106 | self.status_update.emit( 107 | f"Disconnecting from sensor at {self._sensor_address()}." 108 | ) 109 | self.client.disconnectFromDevice() 110 | 111 | def _discover_services(self): 112 | if self.client is not None: 113 | self.client.discoverServices() 114 | 115 | def _connect_hr_service(self): 116 | if self.client is None: 117 | return 118 | hr_service: list[QBluetoothUuid] = [ 119 | s for s in self.client.services() if s == self.HR_SERVICE 120 | ] 121 | if not hr_service: 122 | print(f"Couldn't find HR service on {self._sensor_address()}.") 123 | return 124 | self.hr_service = self.client.createServiceObject(hr_service[0]) 125 | if not self.hr_service: 126 | print( 127 | f"Couldn't establish connection to HR service on {self._sensor_address()}." 128 | ) 129 | return 130 | self.hr_service.stateChanged.connect(self._start_hr_notification) 131 | self.hr_service.characteristicChanged.connect(self._data_handler) 132 | self.hr_service.discoverDetails() 133 | 134 | def _start_hr_notification(self, state: QLowEnergyService.ServiceState): 135 | if state != QLowEnergyService.RemoteServiceDiscovered: 136 | return 137 | if self.hr_service is None: 138 | return 139 | hr_char: QLowEnergyCharacteristic = self.hr_service.characteristic( 140 | self.HR_CHARACTERISTIC 141 | ) 142 | if not hr_char.isValid(): 143 | print(f"Couldn't find HR characterictic on {self._sensor_address()}.") 144 | self.hr_notification = hr_char.descriptor( 145 | QBluetoothUuid.DescriptorType.ClientCharacteristicConfiguration 146 | ) 147 | if not self.hr_notification.isValid(): 148 | print("HR characteristic is invalid.") 149 | self.hr_service.writeDescriptor(self.hr_notification, self.ENABLE_NOTIFICATION) 150 | 151 | def _reset_connection(self): 152 | print(f"Discarding sensor at {self._sensor_address()}.") 153 | self._remove_service() 154 | self._remove_client() 155 | 156 | def _remove_service(self): 157 | if self.hr_service is None: 158 | return 159 | try: 160 | self.hr_service.deleteLater() 161 | except Exception as e: 162 | print(f"Couldn't remove service: {e}") 163 | finally: 164 | self.hr_service = None 165 | self.hr_notification = None 166 | 167 | def _remove_client(self): 168 | if self.client is None: 169 | return 170 | try: 171 | self.client.disconnected.disconnect() 172 | self.client.deleteLater() 173 | except Exception as e: 174 | print(f"Couldn't remove client: {e}") 175 | finally: 176 | self.client = None 177 | 178 | def _catch_error(self, error): 179 | self.status_update.emit(f"An error occurred: {error}. Disconnecting sensor.") 180 | self._reset_connection() 181 | 182 | def _data_handler(self, _, data: QByteArray): # _ is unused but mandatory argument 183 | """ 184 | `data` is formatted according to the 185 | "GATT Characteristic and Object Type 0x2A37 Heart Rate Measurement" 186 | which is one of the three characteristics included in the 187 | "GATT Service 0x180D Heart Rate". 188 | 189 | `data` can include the following bytes: 190 | - flags 191 | Always present. 192 | - bit 0: HR format (uint8 vs. uint16) 193 | - bit 1, 2: sensor contact status 194 | - bit 3: energy expenditure status 195 | - bit 4: RR interval status 196 | - HR 197 | Encoded by one or two bytes depending on flags/bit0. One byte is 198 | always present (uint8). Two bytes (uint16) are necessary to 199 | represent HR > 255. 200 | - energy expenditure 201 | Encoded by 2 bytes. Only present if flags/bit3. 202 | - inter-beat-intervals (IBIs) 203 | One IBI is encoded by 2 consecutive bytes. Up to 18 bytes depending 204 | on presence of uint16 HR format and energy expenditure. 205 | """ 206 | heart_rate_measurement_bytes: bytes = data.data() 207 | 208 | byte0: int = heart_rate_measurement_bytes[0] 209 | uint8_format: bool = (byte0 & 1) == 0 210 | energy_expenditure: bool = ((byte0 >> 3) & 1) == 1 211 | rr_interval: bool = ((byte0 >> 4) & 1) == 1 212 | 213 | if not rr_interval: 214 | return 215 | 216 | first_rr_byte: int = 2 217 | if uint8_format: 218 | # hr = data[1] 219 | pass 220 | else: 221 | # hr = (data[2] << 8) | data[1] # uint16 222 | first_rr_byte += 1 223 | if energy_expenditure: 224 | # ee = (data[first_rr_byte + 1] << 8) | data[first_rr_byte] 225 | first_rr_byte += 2 226 | 227 | for i in range(first_rr_byte, len(heart_rate_measurement_bytes), 2): 228 | ibi: int = ( 229 | heart_rate_measurement_bytes[i + 1] << 8 230 | ) | heart_rate_measurement_bytes[i] 231 | # Polar H7, H9, and H10 record IBIs in 1/1024 seconds format. 232 | # Convert 1/1024 sec format to milliseconds. 233 | # TODO: move conversion to model and only convert if sensor doesn't 234 | # transmit data in milliseconds. 235 | ibi = ceil(ibi / 1024 * 1000) 236 | self.ibi_update.emit(ibi) 237 | -------------------------------------------------------------------------------- /openhrv/view.py: -------------------------------------------------------------------------------- 1 | from datetime import datetime 2 | from PySide6.QtWidgets import ( 3 | QMainWindow, 4 | QPushButton, 5 | QHBoxLayout, 6 | QVBoxLayout, 7 | QWidget, 8 | QLabel, 9 | QComboBox, 10 | QSlider, 11 | QGroupBox, 12 | QFormLayout, 13 | QCheckBox, 14 | QFileDialog, 15 | QProgressBar, 16 | QGridLayout, 17 | QSizePolicy, 18 | ) 19 | from PySide6.QtCore import Qt, QThread, Signal, QObject, QTimer, QMargins, QSize 20 | from PySide6.QtGui import QIcon, QLinearGradient, QBrush, QGradient, QColor 21 | from PySide6.QtCharts import QChartView, QChart, QSplineSeries, QValueAxis, QAreaSeries 22 | from PySide6.QtBluetooth import QBluetoothDeviceInfo 23 | from typing import Iterable 24 | from openhrv.utils import valid_address, valid_path, get_sensor_address, NamedSignal 25 | from openhrv.sensor import SensorScanner, SensorClient 26 | from openhrv.logger import Logger 27 | from openhrv.pacer import Pacer 28 | from openhrv.model import Model 29 | from openhrv.config import ( 30 | breathing_rate_to_tick, 31 | HRV_HISTORY_DURATION, 32 | IBI_HISTORY_DURATION, 33 | MAX_BREATHING_RATE, 34 | MIN_BREATHING_RATE, 35 | MIN_HRV_TARGET, 36 | MAX_HRV_TARGET, 37 | MIN_PLOT_IBI, 38 | MAX_PLOT_IBI, 39 | ) 40 | from openhrv import __version__ as version, resources # noqa 41 | 42 | BLUE = QColor(135, 206, 250) 43 | WHITE = QColor(255, 255, 255) 44 | GREEN = QColor(0, 255, 0) 45 | YELLOW = QColor(255, 255, 0) 46 | RED = QColor(255, 0, 0) 47 | 48 | 49 | class PacerWidget(QChartView): 50 | def __init__( 51 | self, x_values: Iterable[float], y_values: Iterable[float], color: QColor = BLUE 52 | ): 53 | super().__init__() 54 | 55 | self.setSizePolicy( 56 | QSizePolicy( 57 | QSizePolicy.Fixed, # enforce self.sizeHint by fixing horizontal (width) policy 58 | QSizePolicy.Preferred, 59 | ) 60 | ) 61 | 62 | self.plot = QChart() 63 | self.plot.legend().setVisible(False) 64 | self.plot.setBackgroundRoundness(0) 65 | self.plot.setMargins(QMargins(0, 0, 0, 0)) 66 | 67 | self.disc_circumference_coord = QSplineSeries() 68 | self._instantiate_series(x_values, y_values) 69 | self.disk = QAreaSeries(self.disc_circumference_coord) 70 | self.disk.setColor(color) 71 | self.plot.addSeries(self.disk) 72 | 73 | self.x_axis = QValueAxis() 74 | self.x_axis.setRange(-1, 1) 75 | self.x_axis.setVisible(False) 76 | self.plot.addAxis(self.x_axis, Qt.AlignBottom) 77 | self.disk.attachAxis(self.x_axis) 78 | 79 | self.y_axis = QValueAxis() 80 | self.y_axis.setRange(-1, 1) 81 | self.y_axis.setVisible(False) 82 | self.plot.addAxis(self.y_axis, Qt.AlignLeft) 83 | self.disk.attachAxis(self.y_axis) 84 | 85 | self.setChart(self.plot) 86 | 87 | def _instantiate_series(self, x_values: Iterable[float], y_values: Iterable[float]): 88 | for x, y in zip(x_values, y_values): 89 | self.disc_circumference_coord.append(x, y) 90 | 91 | def update_series(self, x_values: Iterable[float], y_values: Iterable[float]): 92 | for i, (x, y) in enumerate(zip(x_values, y_values)): 93 | self.disc_circumference_coord.replace(i, x, y) 94 | 95 | def sizeHint(self): 96 | height = self.size().height() 97 | return QSize(height, height) # force square aspect ratio 98 | 99 | def resizeEvent(self, event): 100 | if self.size().width() != self.size().height(): 101 | self.updateGeometry() # adjusts geometry based on sizeHint 102 | return super().resizeEvent(event) 103 | 104 | 105 | class XYSeriesWidget(QChartView): 106 | def __init__( 107 | self, 108 | x_values: Iterable[float], 109 | y_values: Iterable[float], 110 | line_color: QColor = BLUE, 111 | ): 112 | super().__init__() 113 | 114 | self.plot = QChart() 115 | self.plot.legend().setVisible(False) 116 | self.plot.setBackgroundRoundness(0) 117 | self.plot.setMargins(QMargins(0, 0, 0, 0)) 118 | 119 | self.time_series = QSplineSeries() 120 | self.plot.addSeries(self.time_series) 121 | pen = self.time_series.pen() 122 | pen.setWidth(4) 123 | pen.setColor(line_color) 124 | self.time_series.setPen(pen) 125 | self._instantiate_series(x_values, y_values) 126 | 127 | self.x_axis = QValueAxis() 128 | self.x_axis.setLabelFormat("%i") 129 | self.plot.addAxis(self.x_axis, Qt.AlignBottom) 130 | self.time_series.attachAxis(self.x_axis) 131 | 132 | self.y_axis = QValueAxis() 133 | self.y_axis.setLabelFormat("%i") 134 | self.plot.addAxis(self.y_axis, Qt.AlignLeft) 135 | self.time_series.attachAxis(self.y_axis) 136 | 137 | self.setChart(self.plot) 138 | 139 | def _instantiate_series(self, x_values: Iterable[float], y_values: Iterable[float]): 140 | for x, y in zip(x_values, y_values): 141 | self.time_series.append(x, y) 142 | 143 | def update_series(self, x_values: Iterable[float], y_values: Iterable[float]): 144 | for i, (x, y) in enumerate(zip(x_values, y_values)): 145 | self.time_series.replace(i, x, y) 146 | 147 | 148 | class ViewSignals(QObject): 149 | """Cannot be defined on View directly since Signal needs to be defined on 150 | object that inherits from QObject""" 151 | 152 | annotation = Signal(tuple) 153 | start_recording = Signal(str) 154 | 155 | 156 | class View(QMainWindow): 157 | def __init__(self, model: Model): 158 | super().__init__() 159 | 160 | self.setWindowTitle(f"OpenHRV ({version})") 161 | self.setWindowIcon(QIcon(":/logo.png")) 162 | 163 | self.model = model 164 | self.model.ibis_buffer_update.connect(self.plot_ibis) 165 | self.model.hrv_update.connect(self.plot_hrv) 166 | self.model.addresses_update.connect(self.list_addresses) 167 | self.model.pacer_rate_update.connect(self.update_pacer_label) 168 | self.model.hrv_target_update.connect(self.update_hrv_target) 169 | 170 | self.signals = ViewSignals() 171 | 172 | self.pacer = Pacer() 173 | self.pacer_timer = QTimer() 174 | self.pacer_timer.setInterval(int(1 / 8 * 1000)) # redraw pacer at 8Hz 175 | self.pacer_timer.timeout.connect(self.plot_pacer_disk) 176 | 177 | self.scanner = SensorScanner() 178 | self.scanner.sensor_update.connect(self.model.update_sensors) 179 | self.scanner.status_update.connect(self.show_status) 180 | 181 | self.sensor = SensorClient() 182 | self.sensor.ibi_update.connect(self.model.update_ibis_buffer) 183 | self.sensor.status_update.connect(self.show_status) 184 | 185 | self.logger = Logger() 186 | self.logger.recording_status.connect(self.show_recording_status) 187 | self.logger.status_update.connect(self.show_status) 188 | self.logger_thread = QThread() 189 | self.logger_thread.finished.connect(self.logger.save_recording) 190 | self.signals.start_recording.connect(self.logger.start_recording) 191 | self.logger.moveToThread(self.logger_thread) 192 | 193 | self.model.ibis_buffer_update.connect(self.logger.write_to_file) 194 | self.model.addresses_update.connect(self.logger.write_to_file) 195 | self.model.pacer_rate_update.connect(self.logger.write_to_file) 196 | self.model.hrv_target_update.connect(self.logger.write_to_file) 197 | self.model.hrv_update.connect(self.logger.write_to_file) 198 | self.signals.annotation.connect(self.logger.write_to_file) 199 | 200 | self.ibis_widget = XYSeriesWidget( 201 | self.model.ibis_seconds, self.model.ibis_buffer 202 | ) 203 | self.ibis_widget.x_axis.setTitleText("Seconds") 204 | # The time series displays only the samples within the last 205 | # IBI_HISTORY_DURATION seconds, 206 | # even though there are more samples in self.model.ibis_seconds. 207 | self.ibis_widget.x_axis.setRange(-IBI_HISTORY_DURATION, 0.0) 208 | self.ibis_widget.x_axis.setTickCount(7) 209 | self.ibis_widget.x_axis.setTickInterval(10.0) 210 | self.ibis_widget.y_axis.setTitleText("Inter-Beat-Interval (msec)") 211 | self.ibis_widget.y_axis.setRange(MIN_PLOT_IBI, MAX_PLOT_IBI) 212 | 213 | self.hrv_widget = XYSeriesWidget( 214 | self.model.hrv_seconds, self.model.hrv_buffer, WHITE 215 | ) 216 | self.hrv_widget.x_axis.setTitleText("Seconds") 217 | # The time series displays only the samples within the last 218 | # HRV_HISTORY_DURATION seconds, 219 | # even though there are more samples in self.model.hrv_seconds. 220 | self.hrv_widget.x_axis.setRange(-HRV_HISTORY_DURATION, 0) 221 | self.hrv_widget.y_axis.setTitleText("HRV (msec)") 222 | self.hrv_widget.y_axis.setRange(0, self.model.hrv_target) 223 | colorgrad = QLinearGradient(0, 0, 0, 1) # horizontal gradient 224 | colorgrad.setCoordinateMode(QGradient.ObjectMode) 225 | colorgrad.setColorAt(0, GREEN) 226 | colorgrad.setColorAt(0.6, YELLOW) 227 | colorgrad.setColorAt(1, RED) 228 | brush = QBrush(colorgrad) 229 | self.hrv_widget.plot.setPlotAreaBackgroundBrush(brush) 230 | self.hrv_widget.plot.setPlotAreaBackgroundVisible(True) 231 | 232 | self.pacer_widget = PacerWidget(*self.pacer.update(self.model.breathing_rate)) 233 | 234 | self.pacer_label = QLabel() 235 | self.pacer_rate = QSlider(Qt.Horizontal) 236 | self.pacer_rate.setTickPosition(QSlider.TicksBelow) 237 | self.pacer_rate.setTracking(False) 238 | self.pacer_rate.setRange( 239 | breathing_rate_to_tick(MIN_BREATHING_RATE), 240 | breathing_rate_to_tick(MAX_BREATHING_RATE), 241 | ) 242 | self.pacer_rate.valueChanged.connect(self.model.update_breathing_rate) 243 | self.pacer_rate.setValue(breathing_rate_to_tick(MAX_BREATHING_RATE)) 244 | 245 | self.pacer_toggle = QCheckBox("Show pacer", self) 246 | self.pacer_toggle.setChecked(True) 247 | self.pacer_toggle.stateChanged.connect(self.toggle_pacer) 248 | 249 | self.hrv_target_label = QLabel(f"Target: {self.model.hrv_target}") 250 | 251 | self.hrv_target = QSlider(Qt.Horizontal) 252 | self.hrv_target.setRange(MIN_HRV_TARGET, MAX_HRV_TARGET) 253 | self.hrv_target.setSingleStep(10) 254 | self.hrv_target.valueChanged.connect(self.model.update_hrv_target) 255 | self.hrv_target.setSliderPosition(self.model.hrv_target) 256 | 257 | self.scan_button = QPushButton("Scan") 258 | self.scan_button.clicked.connect(self.scanner.scan) 259 | 260 | self.address_menu = QComboBox() 261 | 262 | self.connect_button = QPushButton("Connect") 263 | self.connect_button.clicked.connect(self.connect_sensor) 264 | 265 | self.disconnect_button = QPushButton("Disconnect") 266 | self.disconnect_button.clicked.connect(self.disconnect_sensor) 267 | 268 | self.start_recording_button = QPushButton("Start") 269 | self.start_recording_button.clicked.connect(self.get_filepath) 270 | 271 | self.save_recording_button = QPushButton("Save") 272 | self.save_recording_button.clicked.connect(self.logger.save_recording) 273 | 274 | self.annotation = QComboBox() 275 | self.annotation.setEditable(True) 276 | self.annotation.setDuplicatesEnabled(False) 277 | self.annotation_button = QPushButton("Annotate") 278 | self.annotation_button.clicked.connect(self.emit_annotation) 279 | self.central_widget = QWidget() 280 | self.setCentralWidget(self.central_widget) 281 | 282 | self.recording_status_label = QLabel("Status:") 283 | self.recording_statusbar = QProgressBar() 284 | self.recording_statusbar.setRange(0, 1) 285 | 286 | self.statusbar = self.statusBar() 287 | 288 | self.vlayout0 = QVBoxLayout(self.central_widget) 289 | 290 | self.hlayout0 = QHBoxLayout() 291 | self.hlayout0.addWidget(self.ibis_widget) 292 | self.hlayout0.addWidget(self.pacer_widget) 293 | self.vlayout0.addLayout(self.hlayout0, stretch=50) 294 | 295 | self.vlayout0.addWidget(self.hrv_widget, stretch=50) 296 | 297 | self.hlayout1 = QHBoxLayout() 298 | 299 | self.device_config = QGridLayout() 300 | self.device_config.addWidget(self.scan_button, 0, 0) 301 | self.device_config.addWidget(self.address_menu, 0, 1) 302 | self.device_config.addWidget(self.connect_button, 1, 0) 303 | self.device_config.addWidget(self.disconnect_button, 1, 1) 304 | self.device_panel = QGroupBox("ECG Devices") 305 | self.device_panel.setLayout(self.device_config) 306 | self.hlayout1.addWidget(self.device_panel, stretch=25) 307 | 308 | self.hrv_config = QFormLayout() 309 | self.hrv_config.addRow(self.hrv_target_label, self.hrv_target) 310 | self.hrv_panel = QGroupBox("HRV Settings") 311 | self.hrv_panel.setLayout(self.hrv_config) 312 | self.hlayout1.addWidget(self.hrv_panel, stretch=25) 313 | 314 | self.pacer_config = QFormLayout() 315 | self.pacer_config.addRow(self.pacer_label, self.pacer_rate) 316 | self.pacer_config.addRow(self.pacer_toggle) 317 | self.pacer_panel = QGroupBox("Breathing Pacer") 318 | self.pacer_panel.setLayout(self.pacer_config) 319 | self.hlayout1.addWidget(self.pacer_panel, stretch=25) 320 | 321 | self.recording_config = QGridLayout() 322 | self.recording_config.addWidget(self.start_recording_button, 0, 0) 323 | self.recording_config.addWidget(self.save_recording_button, 0, 1) 324 | self.recording_config.addWidget(self.recording_statusbar, 0, 2) 325 | # row, column, rowspan, columnspan 326 | self.recording_config.addWidget(self.annotation, 1, 0, 1, 2) 327 | self.recording_config.addWidget(self.annotation_button, 1, 2) 328 | self.recording_panel = QGroupBox("Recording") 329 | self.recording_panel.setLayout(self.recording_config) 330 | self.hlayout1.addWidget(self.recording_panel, stretch=25) 331 | 332 | self.vlayout0.addLayout(self.hlayout1) 333 | 334 | self.logger_thread.start() 335 | self.pacer_timer.start() 336 | 337 | def closeEvent(self, _): 338 | """Shut down all threads.""" 339 | print("Closing threads...") 340 | 341 | self.sensor.disconnect_client() 342 | 343 | self.logger_thread.quit() 344 | self.logger_thread.wait() 345 | 346 | def get_filepath(self): 347 | current_time: str = datetime.now().strftime("%Y-%m-%d-%H-%M") 348 | default_file_name: str = f"OpenHRV_{current_time}.csv" 349 | # native file dialog not reliable on Windows (most likely COM issues) 350 | file_path: str = QFileDialog.getSaveFileName( 351 | None, 352 | "Create file", 353 | default_file_name, 354 | options=QFileDialog.DontUseNativeDialog, 355 | )[0] 356 | if not file_path: # user cancelled or closed file dialog 357 | return 358 | if not valid_path(file_path): 359 | self.show_status("File path is invalid or exists already.") 360 | return 361 | self.signals.start_recording.emit(file_path) 362 | 363 | def connect_sensor(self): 364 | if not self.address_menu.currentText(): 365 | return 366 | # discard device name 367 | address: str = self.address_menu.currentText().split(",")[1].strip() 368 | if not valid_address(address): 369 | print(f"Invalid sensor address: {address}.") 370 | return 371 | sensor: list[QBluetoothDeviceInfo] = [ 372 | s for s in self.model.sensors if get_sensor_address(s) == address 373 | ] 374 | self.sensor.connect_client(*sensor) 375 | 376 | def disconnect_sensor(self): 377 | self.sensor.disconnect_client() 378 | 379 | def plot_ibis(self, ibis: NamedSignal): 380 | self.ibis_widget.update_series(*ibis.value) 381 | 382 | def plot_hrv(self, hrv: NamedSignal): 383 | self.hrv_widget.update_series(*hrv.value) 384 | 385 | def list_addresses(self, addresses: NamedSignal): 386 | self.address_menu.clear() 387 | self.address_menu.addItems(addresses.value) 388 | 389 | def plot_pacer_disk(self): 390 | coordinates = self.pacer.update(self.model.breathing_rate) 391 | self.pacer_widget.update_series(*coordinates) 392 | 393 | def update_pacer_label(self, rate: NamedSignal): 394 | self.pacer_label.setText(f"Rate: {rate.value}") 395 | 396 | def update_hrv_target(self, target: NamedSignal): 397 | self.hrv_widget.y_axis.setRange(0, target.value) 398 | self.hrv_target_label.setText(f"Target: {target.value}") 399 | 400 | def toggle_pacer(self): 401 | visible = self.pacer_widget.isVisible() 402 | self.pacer_widget.setVisible(not visible) 403 | 404 | def show_recording_status(self, status: int): 405 | """Indicate busy state if `status` is 0.""" 406 | self.recording_statusbar.setRange(0, status) 407 | 408 | def show_status(self, status: str, print_to_terminal=True): 409 | self.statusbar.showMessage(status, 0) 410 | if print_to_terminal: 411 | print(status) 412 | 413 | def emit_annotation(self): 414 | self.signals.annotation.emit( 415 | NamedSignal("Annotation", self.annotation.currentText()) 416 | ) 417 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU LESSER GENERAL PUBLIC LICENSE 2 | Version 2.1, February 1999 3 | 4 | Copyright (C) 1991, 1999 Free Software Foundation, Inc. 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | [This is the first released version of the Lesser GPL. It also counts 10 | as the successor of the GNU Library Public License, version 2, hence 11 | the version number 2.1.] 12 | 13 | Preamble 14 | 15 | The licenses for most software are designed to take away your 16 | freedom to share and change it. By contrast, the GNU General Public 17 | Licenses are intended to guarantee your freedom to share and change 18 | free software--to make sure the software is free for all its users. 19 | 20 | This license, the Lesser General Public License, applies to some 21 | specially designated software packages--typically libraries--of the 22 | Free Software Foundation and other authors who decide to use it. You 23 | can use it too, but we suggest you first think carefully about whether 24 | this license or the ordinary General Public License is the better 25 | strategy to use in any particular case, based on the explanations below. 26 | 27 | When we speak of free software, we are referring to freedom of use, 28 | not price. Our General Public Licenses are designed to make sure that 29 | you have the freedom to distribute copies of free software (and charge 30 | for this service if you wish); that you receive source code or can get 31 | it if you want it; that you can change the software and use pieces of 32 | it in new free programs; and that you are informed that you can do 33 | these things. 34 | 35 | To protect your rights, we need to make restrictions that forbid 36 | distributors to deny you these rights or to ask you to surrender these 37 | rights. These restrictions translate to certain responsibilities for 38 | you if you distribute copies of the library or if you modify it. 39 | 40 | For example, if you distribute copies of the library, whether gratis 41 | or for a fee, you must give the recipients all the rights that we gave 42 | you. You must make sure that they, too, receive or can get the source 43 | code. If you link other code with the library, you must provide 44 | complete object files to the recipients, so that they can relink them 45 | with the library after making changes to the library and recompiling 46 | it. And you must show them these terms so they know their rights. 47 | 48 | We protect your rights with a two-step method: (1) we copyright the 49 | library, and (2) we offer you this license, which gives you legal 50 | permission to copy, distribute and/or modify the library. 51 | 52 | To protect each distributor, we want to make it very clear that 53 | there is no warranty for the free library. Also, if the library is 54 | modified by someone else and passed on, the recipients should know 55 | that what they have is not the original version, so that the original 56 | author's reputation will not be affected by problems that might be 57 | introduced by others. 58 | 59 | Finally, software patents pose a constant threat to the existence of 60 | any free program. We wish to make sure that a company cannot 61 | effectively restrict the users of a free program by obtaining a 62 | restrictive license from a patent holder. Therefore, we insist that 63 | any patent license obtained for a version of the library must be 64 | consistent with the full freedom of use specified in this license. 65 | 66 | Most GNU software, including some libraries, is covered by the 67 | ordinary GNU General Public License. This license, the GNU Lesser 68 | General Public License, applies to certain designated libraries, and 69 | is quite different from the ordinary General Public License. We use 70 | this license for certain libraries in order to permit linking those 71 | libraries into non-free programs. 72 | 73 | When a program is linked with a library, whether statically or using 74 | a shared library, the combination of the two is legally speaking a 75 | combined work, a derivative of the original library. The ordinary 76 | General Public License therefore permits such linking only if the 77 | entire combination fits its criteria of freedom. The Lesser General 78 | Public License permits more lax criteria for linking other code with 79 | the library. 80 | 81 | We call this license the "Lesser" General Public License because it 82 | does Less to protect the user's freedom than the ordinary General 83 | Public License. It also provides other free software developers Less 84 | of an advantage over competing non-free programs. These disadvantages 85 | are the reason we use the ordinary General Public License for many 86 | libraries. However, the Lesser license provides advantages in certain 87 | special circumstances. 88 | 89 | For example, on rare occasions, there may be a special need to 90 | encourage the widest possible use of a certain library, so that it becomes 91 | a de-facto standard. To achieve this, non-free programs must be 92 | allowed to use the library. A more frequent case is that a free 93 | library does the same job as widely used non-free libraries. In this 94 | case, there is little to gain by limiting the free library to free 95 | software only, so we use the Lesser General Public License. 96 | 97 | In other cases, permission to use a particular library in non-free 98 | programs enables a greater number of people to use a large body of 99 | free software. For example, permission to use the GNU C Library in 100 | non-free programs enables many more people to use the whole GNU 101 | operating system, as well as its variant, the GNU/Linux operating 102 | system. 103 | 104 | Although the Lesser General Public License is Less protective of the 105 | users' freedom, it does ensure that the user of a program that is 106 | linked with the Library has the freedom and the wherewithal to run 107 | that program using a modified version of the Library. 108 | 109 | The precise terms and conditions for copying, distribution and 110 | modification follow. Pay close attention to the difference between a 111 | "work based on the library" and a "work that uses the library". The 112 | former contains code derived from the library, whereas the latter must 113 | be combined with the library in order to run. 114 | 115 | GNU LESSER GENERAL PUBLIC LICENSE 116 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 117 | 118 | 0. This License Agreement applies to any software library or other 119 | program which contains a notice placed by the copyright holder or 120 | other authorized party saying it may be distributed under the terms of 121 | this Lesser General Public License (also called "this License"). 122 | Each licensee is addressed as "you". 123 | 124 | A "library" means a collection of software functions and/or data 125 | prepared so as to be conveniently linked with application programs 126 | (which use some of those functions and data) to form executables. 127 | 128 | The "Library", below, refers to any such software library or work 129 | which has been distributed under these terms. A "work based on the 130 | Library" means either the Library or any derivative work under 131 | copyright law: that is to say, a work containing the Library or a 132 | portion of it, either verbatim or with modifications and/or translated 133 | straightforwardly into another language. (Hereinafter, translation is 134 | included without limitation in the term "modification".) 135 | 136 | "Source code" for a work means the preferred form of the work for 137 | making modifications to it. For a library, complete source code means 138 | all the source code for all modules it contains, plus any associated 139 | interface definition files, plus the scripts used to control compilation 140 | and installation of the library. 141 | 142 | Activities other than copying, distribution and modification are not 143 | covered by this License; they are outside its scope. The act of 144 | running a program using the Library is not restricted, and output from 145 | such a program is covered only if its contents constitute a work based 146 | on the Library (independent of the use of the Library in a tool for 147 | writing it). Whether that is true depends on what the Library does 148 | and what the program that uses the Library does. 149 | 150 | 1. You may copy and distribute verbatim copies of the Library's 151 | complete source code as you receive it, in any medium, provided that 152 | you conspicuously and appropriately publish on each copy an 153 | appropriate copyright notice and disclaimer of warranty; keep intact 154 | all the notices that refer to this License and to the absence of any 155 | warranty; and distribute a copy of this License along with the 156 | Library. 157 | 158 | You may charge a fee for the physical act of transferring a copy, 159 | and you may at your option offer warranty protection in exchange for a 160 | fee. 161 | 162 | 2. You may modify your copy or copies of the Library or any portion 163 | of it, thus forming a work based on the Library, and copy and 164 | distribute such modifications or work under the terms of Section 1 165 | above, provided that you also meet all of these conditions: 166 | 167 | a) The modified work must itself be a software library. 168 | 169 | b) You must cause the files modified to carry prominent notices 170 | stating that you changed the files and the date of any change. 171 | 172 | c) You must cause the whole of the work to be licensed at no 173 | charge to all third parties under the terms of this License. 174 | 175 | d) If a facility in the modified Library refers to a function or a 176 | table of data to be supplied by an application program that uses 177 | the facility, other than as an argument passed when the facility 178 | is invoked, then you must make a good faith effort to ensure that, 179 | in the event an application does not supply such function or 180 | table, the facility still operates, and performs whatever part of 181 | its purpose remains meaningful. 182 | 183 | (For example, a function in a library to compute square roots has 184 | a purpose that is entirely well-defined independent of the 185 | application. Therefore, Subsection 2d requires that any 186 | application-supplied function or table used by this function must 187 | be optional: if the application does not supply it, the square 188 | root function must still compute square roots.) 189 | 190 | These requirements apply to the modified work as a whole. If 191 | identifiable sections of that work are not derived from the Library, 192 | and can be reasonably considered independent and separate works in 193 | themselves, then this License, and its terms, do not apply to those 194 | sections when you distribute them as separate works. But when you 195 | distribute the same sections as part of a whole which is a work based 196 | on the Library, the distribution of the whole must be on the terms of 197 | this License, whose permissions for other licensees extend to the 198 | entire whole, and thus to each and every part regardless of who wrote 199 | it. 200 | 201 | Thus, it is not the intent of this section to claim rights or contest 202 | your rights to work written entirely by you; rather, the intent is to 203 | exercise the right to control the distribution of derivative or 204 | collective works based on the Library. 205 | 206 | In addition, mere aggregation of another work not based on the Library 207 | with the Library (or with a work based on the Library) on a volume of 208 | a storage or distribution medium does not bring the other work under 209 | the scope of this License. 210 | 211 | 3. You may opt to apply the terms of the ordinary GNU General Public 212 | License instead of this License to a given copy of the Library. To do 213 | this, you must alter all the notices that refer to this License, so 214 | that they refer to the ordinary GNU General Public License, version 2, 215 | instead of to this License. (If a newer version than version 2 of the 216 | ordinary GNU General Public License has appeared, then you can specify 217 | that version instead if you wish.) Do not make any other change in 218 | these notices. 219 | 220 | Once this change is made in a given copy, it is irreversible for 221 | that copy, so the ordinary GNU General Public License applies to all 222 | subsequent copies and derivative works made from that copy. 223 | 224 | This option is useful when you wish to copy part of the code of 225 | the Library into a program that is not a library. 226 | 227 | 4. You may copy and distribute the Library (or a portion or 228 | derivative of it, under Section 2) in object code or executable form 229 | under the terms of Sections 1 and 2 above provided that you accompany 230 | it with the complete corresponding machine-readable source code, which 231 | must be distributed under the terms of Sections 1 and 2 above on a 232 | medium customarily used for software interchange. 233 | 234 | If distribution of object code is made by offering access to copy 235 | from a designated place, then offering equivalent access to copy the 236 | source code from the same place satisfies the requirement to 237 | distribute the source code, even though third parties are not 238 | compelled to copy the source along with the object code. 239 | 240 | 5. A program that contains no derivative of any portion of the 241 | Library, but is designed to work with the Library by being compiled or 242 | linked with it, is called a "work that uses the Library". Such a 243 | work, in isolation, is not a derivative work of the Library, and 244 | therefore falls outside the scope of this License. 245 | 246 | However, linking a "work that uses the Library" with the Library 247 | creates an executable that is a derivative of the Library (because it 248 | contains portions of the Library), rather than a "work that uses the 249 | library". The executable is therefore covered by this License. 250 | Section 6 states terms for distribution of such executables. 251 | 252 | When a "work that uses the Library" uses material from a header file 253 | that is part of the Library, the object code for the work may be a 254 | derivative work of the Library even though the source code is not. 255 | Whether this is true is especially significant if the work can be 256 | linked without the Library, or if the work is itself a library. The 257 | threshold for this to be true is not precisely defined by law. 258 | 259 | If such an object file uses only numerical parameters, data 260 | structure layouts and accessors, and small macros and small inline 261 | functions (ten lines or less in length), then the use of the object 262 | file is unrestricted, regardless of whether it is legally a derivative 263 | work. (Executables containing this object code plus portions of the 264 | Library will still fall under Section 6.) 265 | 266 | Otherwise, if the work is a derivative of the Library, you may 267 | distribute the object code for the work under the terms of Section 6. 268 | Any executables containing that work also fall under Section 6, 269 | whether or not they are linked directly with the Library itself. 270 | 271 | 6. As an exception to the Sections above, you may also combine or 272 | link a "work that uses the Library" with the Library to produce a 273 | work containing portions of the Library, and distribute that work 274 | under terms of your choice, provided that the terms permit 275 | modification of the work for the customer's own use and reverse 276 | engineering for debugging such modifications. 277 | 278 | You must give prominent notice with each copy of the work that the 279 | Library is used in it and that the Library and its use are covered by 280 | this License. You must supply a copy of this License. If the work 281 | during execution displays copyright notices, you must include the 282 | copyright notice for the Library among them, as well as a reference 283 | directing the user to the copy of this License. Also, you must do one 284 | of these things: 285 | 286 | a) Accompany the work with the complete corresponding 287 | machine-readable source code for the Library including whatever 288 | changes were used in the work (which must be distributed under 289 | Sections 1 and 2 above); and, if the work is an executable linked 290 | with the Library, with the complete machine-readable "work that 291 | uses the Library", as object code and/or source code, so that the 292 | user can modify the Library and then relink to produce a modified 293 | executable containing the modified Library. (It is understood 294 | that the user who changes the contents of definitions files in the 295 | Library will not necessarily be able to recompile the application 296 | to use the modified definitions.) 297 | 298 | b) Use a suitable shared library mechanism for linking with the 299 | Library. A suitable mechanism is one that (1) uses at run time a 300 | copy of the library already present on the user's computer system, 301 | rather than copying library functions into the executable, and (2) 302 | will operate properly with a modified version of the library, if 303 | the user installs one, as long as the modified version is 304 | interface-compatible with the version that the work was made with. 305 | 306 | c) Accompany the work with a written offer, valid for at 307 | least three years, to give the same user the materials 308 | specified in Subsection 6a, above, for a charge no more 309 | than the cost of performing this distribution. 310 | 311 | d) If distribution of the work is made by offering access to copy 312 | from a designated place, offer equivalent access to copy the above 313 | specified materials from the same place. 314 | 315 | e) Verify that the user has already received a copy of these 316 | materials or that you have already sent this user a copy. 317 | 318 | For an executable, the required form of the "work that uses the 319 | Library" must include any data and utility programs needed for 320 | reproducing the executable from it. However, as a special exception, 321 | the materials to be distributed need not include anything that is 322 | normally distributed (in either source or binary form) with the major 323 | components (compiler, kernel, and so on) of the operating system on 324 | which the executable runs, unless that component itself accompanies 325 | the executable. 326 | 327 | It may happen that this requirement contradicts the license 328 | restrictions of other proprietary libraries that do not normally 329 | accompany the operating system. Such a contradiction means you cannot 330 | use both them and the Library together in an executable that you 331 | distribute. 332 | 333 | 7. You may place library facilities that are a work based on the 334 | Library side-by-side in a single library together with other library 335 | facilities not covered by this License, and distribute such a combined 336 | library, provided that the separate distribution of the work based on 337 | the Library and of the other library facilities is otherwise 338 | permitted, and provided that you do these two things: 339 | 340 | a) Accompany the combined library with a copy of the same work 341 | based on the Library, uncombined with any other library 342 | facilities. This must be distributed under the terms of the 343 | Sections above. 344 | 345 | b) Give prominent notice with the combined library of the fact 346 | that part of it is a work based on the Library, and explaining 347 | where to find the accompanying uncombined form of the same work. 348 | 349 | 8. You may not copy, modify, sublicense, link with, or distribute 350 | the Library except as expressly provided under this License. Any 351 | attempt otherwise to copy, modify, sublicense, link with, or 352 | distribute the Library is void, and will automatically terminate your 353 | rights under this License. However, parties who have received copies, 354 | or rights, from you under this License will not have their licenses 355 | terminated so long as such parties remain in full compliance. 356 | 357 | 9. You are not required to accept this License, since you have not 358 | signed it. However, nothing else grants you permission to modify or 359 | distribute the Library or its derivative works. These actions are 360 | prohibited by law if you do not accept this License. Therefore, by 361 | modifying or distributing the Library (or any work based on the 362 | Library), you indicate your acceptance of this License to do so, and 363 | all its terms and conditions for copying, distributing or modifying 364 | the Library or works based on it. 365 | 366 | 10. Each time you redistribute the Library (or any work based on the 367 | Library), the recipient automatically receives a license from the 368 | original licensor to copy, distribute, link with or modify the Library 369 | subject to these terms and conditions. You may not impose any further 370 | restrictions on the recipients' exercise of the rights granted herein. 371 | You are not responsible for enforcing compliance by third parties with 372 | this License. 373 | 374 | 11. If, as a consequence of a court judgment or allegation of patent 375 | infringement or for any other reason (not limited to patent issues), 376 | conditions are imposed on you (whether by court order, agreement or 377 | otherwise) that contradict the conditions of this License, they do not 378 | excuse you from the conditions of this License. If you cannot 379 | distribute so as to satisfy simultaneously your obligations under this 380 | License and any other pertinent obligations, then as a consequence you 381 | may not distribute the Library at all. For example, if a patent 382 | license would not permit royalty-free redistribution of the Library by 383 | all those who receive copies directly or indirectly through you, then 384 | the only way you could satisfy both it and this License would be to 385 | refrain entirely from distribution of the Library. 386 | 387 | If any portion of this section is held invalid or unenforceable under any 388 | particular circumstance, the balance of the section is intended to apply, 389 | and the section as a whole is intended to apply in other circumstances. 390 | 391 | It is not the purpose of this section to induce you to infringe any 392 | patents or other property right claims or to contest validity of any 393 | such claims; this section has the sole purpose of protecting the 394 | integrity of the free software distribution system which is 395 | implemented by public license practices. Many people have made 396 | generous contributions to the wide range of software distributed 397 | through that system in reliance on consistent application of that 398 | system; it is up to the author/donor to decide if he or she is willing 399 | to distribute software through any other system and a licensee cannot 400 | impose that choice. 401 | 402 | This section is intended to make thoroughly clear what is believed to 403 | be a consequence of the rest of this License. 404 | 405 | 12. If the distribution and/or use of the Library is restricted in 406 | certain countries either by patents or by copyrighted interfaces, the 407 | original copyright holder who places the Library under this License may add 408 | an explicit geographical distribution limitation excluding those countries, 409 | so that distribution is permitted only in or among countries not thus 410 | excluded. In such case, this License incorporates the limitation as if 411 | written in the body of this License. 412 | 413 | 13. The Free Software Foundation may publish revised and/or new 414 | versions of the Lesser General Public License from time to time. 415 | Such new versions will be similar in spirit to the present version, 416 | but may differ in detail to address new problems or concerns. 417 | 418 | Each version is given a distinguishing version number. If the Library 419 | specifies a version number of this License which applies to it and 420 | "any later version", you have the option of following the terms and 421 | conditions either of that version or of any later version published by 422 | the Free Software Foundation. If the Library does not specify a 423 | license version number, you may choose any version ever published by 424 | the Free Software Foundation. 425 | 426 | 14. If you wish to incorporate parts of the Library into other free 427 | programs whose distribution conditions are incompatible with these, 428 | write to the author to ask for permission. For software which is 429 | copyrighted by the Free Software Foundation, write to the Free 430 | Software Foundation; we sometimes make exceptions for this. Our 431 | decision will be guided by the two goals of preserving the free status 432 | of all derivatives of our free software and of promoting the sharing 433 | and reuse of software generally. 434 | 435 | NO WARRANTY 436 | 437 | 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO 438 | WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. 439 | EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR 440 | OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY 441 | KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE 442 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 443 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE 444 | LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME 445 | THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 446 | 447 | 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN 448 | WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY 449 | AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU 450 | FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR 451 | CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE 452 | LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING 453 | RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A 454 | FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF 455 | SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 456 | DAMAGES. 457 | 458 | END OF TERMS AND CONDITIONS 459 | 460 | How to Apply These Terms to Your New Libraries 461 | 462 | If you develop a new library, and you want it to be of the greatest 463 | possible use to the public, we recommend making it free software that 464 | everyone can redistribute and change. You can do so by permitting 465 | redistribution under these terms (or, alternatively, under the terms of the 466 | ordinary General Public License). 467 | 468 | To apply these terms, attach the following notices to the library. It is 469 | safest to attach them to the start of each source file to most effectively 470 | convey the exclusion of warranty; and each file should have at least the 471 | "copyright" line and a pointer to where the full notice is found. 472 | 473 | 474 | Copyright (C) 475 | 476 | This library is free software; you can redistribute it and/or 477 | modify it under the terms of the GNU Lesser General Public 478 | License as published by the Free Software Foundation; either 479 | version 2.1 of the License, or (at your option) any later version. 480 | 481 | This library is distributed in the hope that it will be useful, 482 | but WITHOUT ANY WARRANTY; without even the implied warranty of 483 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 484 | Lesser General Public License for more details. 485 | 486 | You should have received a copy of the GNU Lesser General Public 487 | License along with this library; if not, write to the Free Software 488 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 489 | USA 490 | 491 | Also add information on how to contact you by electronic and paper mail. 492 | 493 | You should also get your employer (if you work as a programmer) or your 494 | school, if any, to sign a "copyright disclaimer" for the library, if 495 | necessary. Here is a sample; alter the names: 496 | 497 | Yoyodyne, Inc., hereby disclaims all copyright interest in the 498 | library `Frob' (a library for tweaking knobs) written by James Random 499 | Hacker. 500 | 501 | , 1 April 1990 502 | Ty Coon, President of Vice 503 | 504 | That's all there is to it! 505 | -------------------------------------------------------------------------------- /openhrv/resources.py: -------------------------------------------------------------------------------- 1 | # Resource object code (Python 3) 2 | # Created by: object code 3 | # Created by: The Resource Compiler for Qt version 6.5.0 4 | # WARNING! All changes made in this file will be lost! 5 | 6 | from PySide6 import QtCore 7 | 8 | qt_resource_data = b"\ 9 | \x00\x00A\xe9\ 10 | \x89\ 11 | PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ 12 | \x00\x02Z\x00\x00\x02Z\x08\x06\x00\x00\x00\xf7[\xe9\xea\ 13 | \x00\x00\x00\x01sRGB\x00\xae\xce\x1c\xe9\x00\x00\x00\ 14 | \x04gAMA\x00\x00\xb1\x8f\x0b\xfca\x05\x00\x00\x00\ 15 | \x09pHYs\x00\x00\x0e\xc3\x00\x00\x0e\xc3\x01\xc7o\ 16 | \xa8d\x00\x00A~IDATx^\xed\xdd\x07\xb8\ 17 | uEy\xf6q\xf2\x01/\xbd\xf7&\xd2\x9b4\xe9E\ 18 | P\xa4\x0a\x88\x02Vl\xa0\x09\x1a\x93hb\x8c\xc6n\ 19 | \x22\x9a\x80\x1a\xb1\x80F\x05Q\xd4\xa0\x02\xa2 H\xaf\ 20 | \xd2{\x95\xde\xab\xd2\xcbK\xff\xee{f\x9f\x97S\xf6\ 21 | 9g\x97Uf\xd6\xfa\xff\xae\xeb\xbe\xd6\xcc\xce\x1b\xaf\ 22 | d\xbb\xcf>\xcfy\xd6\xac\x99\xbf\x99\x0d\x00\x8a1\xbb\ 23 | \xb2x'\x0bw\xb2\xc8\xa8\xb1\xb3\x902\xbf2\x8f2\ 24 | \xef\xa8\x8c\xcc\xe7R\xe6P\xfc\x9f\xd5-\xf6\xe2$y\ 25 | AyVy\xba\x93gF\x8d\x9d\xa7\x94\xc7\x94G;\ 26 | yd\xd4\xd8\xf9K'\xfe\xcf\x02\x80BPh\x01\x98\ 27 | \xce\x0ceye\x85N\x96S\x96V\x96\xead\xc9\xce\ 28 | u1\xe5\xff)9{I\xf9\xab\xf2\xc0\xa8<\xa8\xdc\ 29 | \xaf\xdc\xa3\xdc\xa9\xdc\xd5\x19?\xa7\x00\xc0\x94(\xb4\x00\ 30 | \xb8S\xf4jeUe\x95N<\x1f)\xac\x5cD\xf1\ 31 | ]1\xd6\xcb\x8a\x8b0\x17]\xce\xed\xca-\xca\xcd\x9d\ 32 | \xdc\xa1\xd0\x19\x03\xc0\x97'\xd0\x22K(\xeb(k+\ 33 | k*\xab).\xaeVT\xe6TP\x9c\xe7\x95\x91\xe2\ 34 | \xeb&\xe5z\xe5:\xe5Z\xc5\xb7'\x01\xb4\x04\x85\x16\ 35 | \xd0<^\x07\xb5\x81\xb2\xae\xe2\xa2j\xa4\xb8\xf2\xda)\ 36 | \xd4\xef!\xc5E\xd7H\xe1u\xb5r\x85\xf2\xb8\x02\xa0\ 37 | a(\xb4\x80\xbcy\xad\xd4\x86\xa3\xf2Ze%\x85\x9f\ 38 | \xed\xbc\xf8V\xe4\xad\xcae\xca\xe5\xa3\xe2\xdb\x93\x002\ 39 | \xc6\x971\x90\x8f\xf9\x94M\x94\xcd\x94\xcd\x95M\x95e\ 40 | \x154\xd7\xbd\xca\x85\xca\x05\x9d\xeb\xc5\x8a\x9f\xa0\x04\x90\ 41 | \x09\x0a- ]^C\xb5\xb5\xe2\xa2\xca\xf1-\xc0\x91\ 42 | -\x0e\xd0N^`\x7f\x8d\xe2\xc2\xcb9W\xf1\xe2{\ 43 | \x00\x89\xa2\xd0\x02\xd2\xe0\x9fE\xaf\xa3\xdaV\xd9\xa6\x93\ 44 | e\x14`:\xdej\xe2\x1c\xe5,\xe5l\xc5k\xbf\x00\ 45 | $\x82B\x0b\xa8\xcf\x1a\xca\x0e\xcav\xca\xeb\x14\x16\xab\ 46 | \xa3\x08^l\xef\x82\xeb\x0c\xe5d\xc5O=\x02\xa8\x09\ 47 | \x85\x16P\x1d\x17RoTvT\x5c`y\x8f*\xa0\ 48 | l\xde\xd3\xeb\x14\xc5E\xd7i\xca\xc3\x0a\x80\x8aPh\ 49 | \x01\xe5\xf1.\xe9^\xb8\xbe\xab\xb2\x8b\xe2\xa7\x02\xf9\x99\ 50 | C\x9d\xbc\xf3\xbd\x9flP\xac\x05\x94\x9d\x94\xdd\x14\x17W>\ 52 | \x9e\x06H\x95\xb7\x8f\xf8\x83r\xbc\xe2\x8e\xd7\x93\x0a\x80\ 53 | \x02Qh\x01\xc3\xf3\xd9\x7foU\xf6P\xbc\x88\xddg\ 54 | \x03\x02\xb9\xf1\xd9\x8d^P\x7f\x9cr\x8cr\x9f\x02`\ 55 | H\x14Z\xc0`|\x16\xe0\xde\xca^\x8ao\x0f\xf2\xb3\ 56 | \x84&\xf1\xed\xc4\xf3\x95\xa3;\xf1:/\x00\x03\xe0\x97\ 57 | \x03\xd0;\xefk\xf56\xc5\xc5\x95w`\x07\xda\xe2\x12\ 58 | \xc5\x05\xd7\xaf\x15\x9f\xdf\x08\xa0G\x14Z\xc0\xd4\xbc\x97\ 59 | \xd5;\x95}\x94\x8d\xfc\x02\xd0r^@\xff\x0b\xe5(\ 60 | \xe5~\xbf\x00`r\x14Z\xc0D\x0b+\xeeZ\xbd[\ 61 | y\xbd\xe2\xa7\x07\x01\x8c\xe5]\xea\xbdW\x97\x8b.w\ 62 | \xbb8\x14\x1b\xe8\x82B\x0b\x88|\xb4\x8d\x9f\x16\xdcW\ 63 | \xd9]\x99K\x01\xd0\x9b\x99\xca\xef\x94\xc3\x15?\xbd\xe8\ 64 | m$\x00\x08\x85\x16\xda\xce\xbb\xb3\xbb\xb8z\xaf\xc2\x01\ 65 | \xcd\xc0\xf0|$\xd0O\x15\x17]\xecJ\x8f\xd6\xa3\xd0\ 66 | B\x1b\xcd\xafx\xdd\x95\x0b\xac-\xfd\x02\x80R\xf8\xd0\ 67 | k\x17\x5c^\xcf\xf5\x94_\x00\xda\x86B\x0bm\xb2\xae\ 68 | \xf2\x11\xe5=\x8a7\x16\x05P\x0d\xaf\xdf\xfa\x99r\xa8\ 69 | r\xad_\x00\xda\x82B\x0bM\xe7\xb5V\xde\x92\xe1\xc3\ 70 | \xcaV~\x01@\xad\xdc\xe5r\xc1\xf5\x1b\xc5\x9b\xa4\x02\ 71 | \x8dF\xa1\x85\xa6\xf2\x86\xa2\x7f\xaf\xf8\xf6\xa0\x0fs\x06\ 72 | \x90\x96\x87\x94\xc3\x94C\x94;\xfd\x02\xd0D\x14Zh\ 73 | \x9a\xd7)\x1fW|\x1c\x8e\x9f$\x04\x906o\x13q\ 74 | \xac\xf2-\xe5<\xbf\x004\x09\x85\x16\x9a\xc0g\x0bz\ 75 | q\xfb\xc7\x14vl\x07\xf2u\xb1r\xb0\xf2+\xe5y\ 76 | \xbf\x00\xe4\x8eB\x0b9[T\xf1\xed\xc1\x8f*K\xfb\ 77 | \x05\x00\x8dp\xaf\xf2=\xc5\xb7\x15\x1f\xf5\x0b@\xae(\ 78 | \xb4\x90\xa3\xe5\x95O(\x7f\xab\xcc\xe7\x17\x004\xd2\x13\ 79 | \xca\xff*\xdfT\x5c|\x01\xd9\xa1\xd0BN\xd6R>\ 80 | \xa5\xf8h\x9c9\xfd\x02\x80V\xf0\xd3\x89G*\x07*\ 81 | \x7f\xf6\x0b@.(\xb4\x90\x83M\x94\xcf*oV\xf8\ 82 | \xcc\x02\xed\xe5\xa3}\x8eS\x0eP.\xf5\x0b@\xea\xf8\ 83 | \xa5\x85\x94m\xae|Q\xd99\xcc\x00\xe0\x15'(_\ 84 | R.\x093 Q\x14ZH\xd1\x16\x8a\xbf@w\x0c\ 85 | 3\x00\x98\xdc\x1f\x94/+\x17\x85\x19\x90\x18\x0a-\xa4\ 86 | \xc4\xe7\x0e\xba\xc0\xda!\xcc\x00\xa0w')\xfe\xfe\xb8\ 87 | 0\xcc\x80DPh!\x05\xeb+_U\xde\x14f\x00\ 88 | 0\xb8\xdf)^\xd3yM\x98\x015\xfb\x7f\x9d+P\ 89 | \x87U\x94_(\x97+\x14Y\x00\x8a\xe0\x87f\xaeT\ 90 | |\x88\xf5J~\x01\xa8\x13\x1d-\xd4aY\xe5\x0b\xca\ 91 | \x07\x959\xfc\x02\x00\x94\xc0\xbb\xcb{\x1f\xae\xaf(\xf7\ 92 | \xfb\x05\xa0j\x14Z\xa8\xd2\x02\xca\xa7\x95\x7fV\xe6\xf1\ 93 | \x0b\x00P\x81\xa7\x95o(\xde\x87\xebI\xbf\x00T\x85\ 94 | CwQ\x05\x7f\xce\xfeN\xf1\xc1\xb1\xde\xaa\x81\xcdF\ 95 | \x01T\xc9\xdf9\xdb*\xfb)\x8f)W(/+@\ 96 | \xe9\xe8h\xa1l^{u\x90\xb2v\x98\x01@\xfd\xae\ 97 | V\xfeU99\xcc\x80\x12Qh\xa1,\xeb*>\x9f\ 98 | l\xfb0\x03\x80\xf4xK\x08\x9f\x9bz]\x98\x01%\ 99 | \xe0\xa9C\x14m\x11\xe5;\x8a\x9f$\xa4\xc8\x02\x902\ 100 | /e\xf0\x13\x8a\xff\xa3,\xe4\x17\x80\xa2\xb1F\x0bE\ 101 | q\xd1\xfe!\xe5\xb7\xca\xeb;s\x00H\x9d\xbf\xab|\ 102 | \xdc\xd7\xbe\xca_\x15\x17^@a\xb8u\x88\x22l\xa6\ 103 | |W\xd98\xcc\x00 _\x17(\xff\xa8p\x86\x22\x0a\ 104 | A\xd7\x01\xc3X\x5c9L9_\xa1\xc8\x02\xd0\x04\xee\ 105 | n\xf9\x18\x1f\xef\xbf\xe5\xa5\x10\xc0P\xb8u\x88A}\ 106 | @\xf1Q\x17>\x9f\x90\xce(\x80&\xf1w\xdaF\x8a\ 107 | o'z\xa3\xd3\xab\x14` \xfc\x82D\xbf\xd6P\xbe\ 108 | \xafx\x1d\x16\x00\xb4\xc1\xa9\xcaG\x94\x9b\xc3\x0c\xe8\x03\ 109 | \x1d-\xf4j.\xe5\xf3\xca\xcf\x95U\xfd\x02\x00\xb4\xc4\ 110 | \xca\x8a7]vs\xc2k\xb8^T\x80\x9e\xd0\xd1B\ 111 | /\xb6R~\xac\xb8\x9b\x05\x00m\xe6=\xb7|N\xab\ 112 | \x0b.`Z,\x86\xc7T\xe6U\x0eV\xceV(\xb2\ 113 | \x00 \x9erq\x9e\xe2\xb3\x139\xb3\x15\xd3\xa2\xa3\x85\ 114 | \xc9x\x0d\x96\xbbXn\x99\x03\x00&\xbaIqw\xeb\ 115 | \x9c0\x03\xba\xa0\xa3\x85\xf1\xe6W\x0eQNW(\xb2\ 116 | \x00`r\xab)g)>\x0dc>\xbf\x00\x8cGG\ 117 | \x0b\xa3\xb9\x8b\xf5\x13e\xc50\x03\x00\xf4\xea6\xe5\xfd\ 118 | \x0a\xdd-\x8c\xc1S\x870?Qx\xa0\xe2m\x1b\x16\ 119 | \xf6\x0b\x00\x80\xbexsS\x17Z\xbe+\xe0.\x17O\ 120 | &\x22\xa0\xa3\x85\x0d\x94#\x95u\xc2\x0c\x000,o\ 121 | p\xfa\xde\xce\x15-GG\xab\xbd\xfc\xdf\xfd\xbf+\xde\ 122 | \x17ki\xbf\x00\x00(\xc4R\x8a\x17\xc9?\xa7\xf8\x88\ 123 | \xb2\x97\x15\xb4\x14\x1d\xadv\xf2\x1a,\x17X\xde\x1f\x0b\ 124 | \x00P\x1eo\x8f\xb3\x8frw\x98\xa1ux\xea\xb0}\ 125 | \xf6V\xaeP(\xb2\x00\xa0|\xdb(W*o\x093\ 126 | \xb4\x0e\x85V{xc=\x9fF\xffk\x85\x05\xef\x00\ 127 | P\x9dE\x95c\x95\xef)s\xfb\x05\xb4\x07\xb7\x0e\xdb\ 128 | \xe15\xcaQ\x8aw4\x06\x00\xd4\xc7\x0b\xe4\xdf\xa9\x5c\ 129 | \x1ffh<:Z\xcd\xb7\xbfr\xb1B\x91\x05\x00\xf5\ 130 | [O\xb9D\xf1by\xb4\x00\x1d\xad\xe6\xf2.\xc5?\ 131 | P\xbc\x08\x13\x00\x90\x1eo\x10\xfd\xf7\xca3a\x86F\ 132 | \xa2\xd0j\xa65\x95\xa3\x15\xbaX\x00\x90\xb6\xab\x95\xbd\ 133 | \x14\x9f\x9b\x88\x06\xe2\xd6a\xf3\xf8\xde?\xb7\x0a\x01 \ 134 | \x0f\xeb*\xbe\x95\xe8'\xc2\xd1@lX\xda\x1c3\x94\ 135 | \x83\x95\xff\xee\x8c\x01\x00y\xf01hoW|\x8c\xcf\ 136 | i\xcaK\x0a\x1a\x82[\x87\xcd\xb0\x8c\xe2[\x85[\x84\ 137 | \x19\x00 W\xe7*\xeen=\x10f\xc8\x1e\x85V\xfe\ 138 | 6S\x8eQ\x96\x0d3\x00@\xee\xbc\x8b\xfc[\x15\xdf\ 139 | RD\xe6X\xa3\x95\xb7\xfd\x14\x9f\x12O\x91\x05\x00\xcd\ 140 | \xb1\xbcr\x8e\xe2\x83\xa9\x919\xd6h\xe5i\x0e\xe5\xdb\ 141 | \xcaW:c\x00@\xb3\xf8\xbb\xdd]-\xaf\xdb:U\ 142 | a\xddV\xa6\xb8u\x98\x9f\xc5\x94\xdf(\xaf\x0f3\x00\ 143 | @\xd3\x9d\xae\xbcMy8\xcc\x90\x15\x0a\xad\xbcx\x7f\ 144 | \xac\xe3\x95U\xc2\x0c\x00\xd0\x16\xdegk\xd7\xce\x15\x19\ 145 | a\x8dV>\xb6W\xceW(\xb2\x00\xa0}VS.\ 146 | P\xb8\x9b\x91\x19\x0a\xad<\xf8\xbc\xc2\x13\x95\x85\xc3\x0c\ 147 | \x00\xd0F\x8b*'+~\x10\x0a\x99`1|\xda\x5c\ 148 | \x08\x7fS\xf1\xa2w\x8ab\x00\x80\x7fo\xef\xa1\xf8<\ 149 | [on\xfa\xb2\x82\x84\xb1F+]\xf3(\xbfT\xfc\ 150 | \x03\x05\x00\xc0x\xde\xa8\xfa=\xca\xcc0C\x92(\xb4\ 151 | \xd2\xb4\xb8\xf2{e\xf30\x03\x00\xa0;\xef$\xef?\ 152 | \xc8y\x221Q\x14Z\xe9YY9I\xf1\xc2G\x00\ 153 | \x00\xa6s\x83\xb2\xb3rG\x98!)\xac\xfbI\xcb\xc6\ 154 | \x8a\x9f,\xa4\xc8\x02\x00\xf4\xca[\xff\xf8w\xc7\x06a\ 155 | \x86\xa4Ph\xa5c\x17\xe5Le\xc90\x03\x00\xa0w\ 156 | \xcb(g+;\x84\x19\x92A\xa1\x95\x86}\x94\xdf)\ 157 | ~\x8a\x04\x00\x80A,\xa0\x9c\xa0\xbc=\xcc\x90\x04\xb6\ 158 | w\xa8\xdfG\x95\x1f*\xfcw\x01\x00\x18\x96\x7f\x97\xec\ 159 | \xa5\xdc\xaf\x5c\xea\x17P/~\xb9\xd7\xeb\xf3\xcaA\x0a\ 160 | \x0f%\x00\x00\x8a\xe2\xdf)\xbb+\xde\xf6\xe1<\xbf\x80\ 161 | \xfaPh\xd5\xc3?\x04\xde\x88\xf43a\x06\x00@\xf1\ 162 | |t\xdb\xbc\xca\xa9a\x86ZPhU\xcf\xef\xf9\x8f\ 163 | \x94\x8f\x84\x19\x00\x00\xe5\xd9JYV\xf9\x83\xc2.\xf2\ 164 | 5\xa0\xd0\xaa\xd6\x1c\xca\x91\xca{\xc3\x0c\x00\x80\xf2m\ 165 | \xa4\xac\xaa\x1c\xa7PlU\x8cB\xab:s*\xff\xa7\ 166 | \xf04\x08\x00\xa0j\xeb)k(\xbfU^\xf2\x0b\xa8\ 167 | \x06\x85V5f(\xbfQ\xde\x1af\x00\x00T\xef5\ 168 | \x9d\x1c\xabPlU\x84\xa7\xdd\xca7\x97r\x8c\xf2\xa6\ 169 | 0\x03\x00\xa0^>Kwo\xe5\xb90C\xa9(\xb4\ 170 | \xca5\x8f\xe26\xed\x8ea\x06\x00@\x1a|\xa6\xae\xef\ 171 | \xb2x\x0b\x08\x94\x88B\xab<\xeedy\xb7w\x8a,\ 172 | \x00@\x8a\x5cl\xbdEy6\xccP\x0a\x8e\xe0)\x87\ 173 | \xd7d\xf9v!E\x16\x00 U;+\xbfV\xfc\xb0\ 174 | \x16J\xc2b\xf8\xe2\xf9\x03\xeb\x85\xef\xbb\x85\x19\x00\x00\ 175 | \xe9\xf2\x93\x88\xeb(n\x0e\xb0@\xbe\x04\x14Z\xc5\xf2\ 176 | >Y\xde\xc2\x81\xa7\x0b\x01\x00\xb9XKq\xc1\xe5\xa7\ 177 | \x11\xd9g\xab`\x14Z\xc5\xf1{\xf9s\xe5ma\x06\ 178 | \x00@>\xbc\xed\xc3\xca\x0a\x9b\x9a\x16\x8cB\xab\x18~\ 179 | \xa8\xc0\xc7\xea\xbc'\xcc\x00\x00\xc8\x8f75]F9\ 180 | >\xccP\x08\x0a\xadb\xf8\x80h\xce.\x04\x00\xe4\xce\ 181 | \xc7\xf5xk\x22\x0e\xa2.\x08\x85\xd6\xf0>\xa7|&\ 182 | \x0e\x01\x00\xc8\xde\xd6\xca3\xcaya\x86\xa1Ph\x0d\ 183 | \xe7\xa3\xca\xd7\xe3\x10\x00\x80\xc6\xd8A\xb9W\xb9,\xcc\ 184 | 00\x0a\xad\xc1\xed\xa3\xfcPa\xd3W\x00@\x13\xed\ 185 | \xaa\xdc\xa0\x5c\x1bf\x18\x08E\xc2`vQ\xbc\xeb\xbb\ 186 | \xb7s\x00\x00\xa0\xa9|\x1e\xa2\xf7\x85<%\xcc\xd07\ 187 | \x0a\xad\xfem\xac\x9c\xa9\xcc\x17f\x00\x004\xdb\x13\xca\ 188 | 6\xca\x15a\x86\xbePh\xf5\xc7{\x8c\x9c\xaf,\x19\ 189 | f\x00\x00\xb4\xc3}\xca\x16\xca\x1da\x86\x9eq\xd6a\ 190 | \xef\x16W|\x00'E\x16\x00\xa0m\xbc\xbf\xd6\x89\xca\ 191 | \x22a\x86\x9eQh\xf5\xc6{\x8a\xfc^Y-\xcc\x00\ 192 | \x00h\x1f\x1f\xd5\xe3\xf5\xc9s\x87\x19zB\xa15=\ 193 | \xbfG\xbfT6\x0f3\x00\x00\xda\xcb{l\x1d\xa9\xb0\ 194 | \xf4\xa8Gl\xef0\xbdo(\x1f\x88C\x00\x00Zo\ 195 | m\xc5]-v\x8f\xef\x01\x85\xd6\xd4\xf6W\x0e\x88C\ 196 | \x00\x00\xd0\xe1\xce\xd6\x9d\x0aO\x22N\x83\xd6\xdf\xe4\xde\ 197 | \xa8x\xf1;{e\x01\x000\xd1\xf3\x8aw\x90?+\ 198 | \xcc\xd0\x15\x85Vwk*\xde\xc6a\xe10\x03\x00\x00\ 199 | \xdd<\xacx\x0d\xf3Ma\x86\x09(\xb4&ZL\xb9\ 200 | PY%\xcc\x00\x00\xc0TnT\x5cl=\x12f\x18\ 201 | \x83\xa7\x0e\xc7\xf2m\xc2\xdf(\x14Y\x00\x00\xf4fu\ 202 | \xe5\xd7\x0a\xeb\xbe\xbb\xe0M\x19\xeb`\xe5\xedq\x08\x00\ 203 | \x00z\xe4\x93S\x16P\xfe\x18f\x98\x85B\xeb\x15\xfb\ 204 | )<\ 229 | \x17f\x0d\xd3\xc4[\x87\x07*{\xc4!\x00\x00H\xdc\ 230 | \xd2\xca\x0c\xe5\xd40k\x98\xa6u\xb4^\xaf\x9c\xae\xb4\ 231 | a\xdb\x0a\x00\x00\x9a\xe2%e[\xe5\xdc0k\x90&\ 232 | \x15$\xf3+\xd7(\xde\xd2\x01\x00\x00\xe4\xe5Ve=\ 233 | \xe5\xa90k\x88&\xdd:\xfc\x96\xb2}\x1c\x02\x00\x80\ 234 | \xcc,\xa2\xb8irR\x985DS:ZoPN\ 235 | S\xb8e\x08\x00@\xbe|\x0bq\x1b\xe5\xbc0k\x80\ 236 | &\x14&\xf3*~,t\xe50\x03\x00\x009\xbbQ\ 237 | \xf1\xae\xf13\xc3,sM\xb8ux\x90\xb2K\x1c\x02\ 238 | \x00\x80\xcc-\xa6x\xab\xa6S\xc2,s\xb9w\xb4\xb6\ 239 | R\xceV\x1a\xbf\x85?\x00\x00-\xf2\xa2\xb2\xa5\xe2\xcd\ 240 | \xc7\xb3\x96s\xa1\xe5j\xd7\x9b\x9c\xad\x11f\x00\x00\xa0\ 241 | I\xaeU6T\x9e\x0f\xb3L\xe5|\xeb\xf0\xf3\xca^\ 242 | q\x08\x00\x00\x1afI\xe5\x19%\xeb\xbd\xb5r\xedh\ 243 | \xb9\x8b\xe5n\x96\xbbZ\x00\x00\xa0\x99\x5ch\xbdF\xf1\ 244 | \x1e[Y\xcaum\xd3\xf7\x15\x8a,\x00\x00\x9am\x1e\ 245 | \xe5\x908\xccS\x8e\x85\xd6\x07\x14\x1f\xb5\x03\x00\x00\x9a\ 246 | o'\xe5]q\x98\x9f\xdcn\x1d.\xae\xdc\xa0\xf8\xd1\ 247 | O\x00\x00\xd0\x0e\x0f(k*\x8f\x86YFr[\x0c\ 248 | \xff]\xc5\x8f{\x02\x00\x80\xf6\xf0\xd1<\x0b+'\x84\ 249 | YFr\xeahm\xae\xfcI\xc9}\xef/\x00\x00\xd0\ 250 | ?\x1f\xcf\xb3\x89rY\x98e\x22\x975Z\xfe\xbf\xf3\ 251 | ;\x0aE\x16\x00\x00\xed\x94e-\x90K\xa1\xf5Ae\ 252 | \xe38\x04\x00\x00-\xe5\xe5C\xef\x8d\xc3<\xe4P\x15\ 253 | .\xa2\xf8\x80I/\x84\x07\x00\x00\xedv\xbf\xe2\xfd4\ 254 | \x1f\x0f\xb3\xc4\xe5\xb0\x18\xde\x87F\xb3\x9d\x03\x00\x000\ 255 | /\x8c\xf7^\x9a'\x87Y\xe2R\xefh\xad\xab\x5c\xae\ 256 | \xe4|T\x10\x00\x00(\xd6\x0b\xcaz\xca\xf5a\x96\xb0\ 257 | \xd4\x0b\xadS\x94\xed\xe3\x10@\x17O+\x7fQ|L\ 258 | \xc5L\xc5?\xd33\x14\xef\xa6\xbc\x842\xaf\x02\x00M\ 259 | \xf4\x07e\xd78LW\xca\x85\xd6.\x8a\xdfD\x00\xb3\ 260 | \xcdv\xbbr\xa1\xe2\xc7\x9a\xff\xacx\xdd\xe2\xdd\xca\x13\ 261 | \xcaT\xe6SVTVQ\xbc\xd9\xdfF\x8a\x1f\x8f^\ 262 | Y\x01\x80\xdc\xed\xa0\x9c\x1a\x87iJ\xb5\xd0\xf2\xad\xc2\ 263 | \xab\x94\xb5\xc3\x0ch\x9f'\x15o\xccw\x92\xe2u\x08\ 264 | \xf7*EZAq\xb7\xd8\x7f\xd0\xf8/B:_\x00\ 265 | r\xe4ZaC\xc5{l%)\xd5Bk\x7f\xc5\x07\ 266 | G\x03m\xf2\xb2\xf2G\xe5p\xe5\xf7\x8ao\x07V\xc1\ 267 | E\xd6\xee\xca\xdf*\xdb)\xa9/)\x00\x80\xd1\xbc\x05\ 268 | \xd4aq\x98\x9e\x14\xbfP\x17PnV\x96\x0c3\xa0\ 269 | \xf9\xbc\xb6\xea\x87\xca\xb7\x15\x7f\xf6\xeb\xb4\xba\xf2\xaf\xca\ 270 | \xfb\x15\xaf\xf5\x02\x80\xd4\xdd\xa7\xac\xa6<\x15f\x89I\ 271 | \xf1i\xbe/*;\xc7!\xd0h\xcf+\x87(oS\ 272 | ~\xad<\xac\xd4\xed\xaf\x8a\xbbiG(\x0b*\x1b(\ 273 | t\xb8\x00\xa4\xcc\x0d\x1a\x7f\x9f\x9e\x19f\x89I\xed\x0b\ 274 | tY\xc5\x7f\xd1\xfb\x89)\xa0\xc9\xbc\xee\xeac\xca\x0d\ 275 | a\x96.\xaf}\xf8\x9e\xb2E\x98\x01@\x9a\xdc\xcd\xf2\ 276 | C?\x0f\x84YBR\xebhysR\x1f\x1e\x0d4\ 277 | \x95w2\xfe\xb0\xe2\xdbs\xde\x96!u\xde\x81\xd9k\ 278 | \xc6\xfct\xe36\xca\x1c\x0a\x00\xa4\xc6K\x1d\xbc\x89\xe9\ 279 | \x89a\x96\x90\x94:Z\xab*\xdex\x8c/r4\xd5\ 280 | \xc5\x8ao\x13\xde\x11f\xf9\xf1\x06\xc2\xc7*\xfe\xab\x11\ 281 | \x00R\xf3\x9c\xe2\xa3y\xbc\x1dN2R:T\xfa?\ 282 | \x14\x8a,4\x95\x9f\x88y\x9d\x92k\x91eW+>\ 283 | \xdc\xdd[N\x00@j\xdc\xd5\xfaR\x1c\xa6#\x95\x8e\ 284 | \xd6\xfa\x8a\x8f\xdaa\xd1-\x9a\xc8?\xf8_\x8e\xc3F\ 285 | \xf0\x1fD?Q\xf6\x093\x00H\x87\xf7\xd3r\xf7\xfd\ 286 | \xba0K@*k\xb4~\xac\xf8\xb1r\xa0i>\xae\ 287 | \xfcw\x1c6\x86\xbf\xc8|\x0b\xd1\x0f\xafx\xa7y\x00\ 288 | H\x85\x1b6\xcb)G\x85Y\x02R\xe8 m\xa9\x9c\ 289 | \x17\x87@\xa3|N9 \x0e\x1b\xc9K\x0f~\xa1\xbc\ 290 | #\xcc\x00 \x1d\x9b*^\x17[\xbb\x14\x0a-?\xe6\ 291 | \xee\xb3\x8a\x80&\xf9\x8e\xf2Oq\xd8hs*\xa7+\ 292 | [\x87\x19\x00\xa4\xc1G\x98\xed\x16\x87\xf5\xaa\xbb\xd0\xf2\ 293 | \xde<\x7f\x8aC\xa01\xbci\x9e\xffxx!\xcc\x9a\ 294 | o)\xc5\x87]\xfbV\x22\x00\xa4\xc2\x07\xe8_\x12\x87\ 295 | \xf5\xa9\xfb\xa9C\xef\x02\x0f4\x897\xcb\xf3\xad\xb4\xb6\ 296 | \x14Y\xe6\xff\x9f\xdf\xad\xf8\xacF\x00HE\x125F\ 297 | \x9d\x85\xd6f\xcaNq\x084\x867#}0\x0e[\ 298 | \xe5,\xe5\xbbq\x08\x00I\xf0\xad\xc3\xda\x1f\xd8\xa9\xf3\ 299 | \xd6\xe1\x1f\x94]\xe2\x10h\x04?\xe5\xf2\xce8l\xa5\ 300 | y\x95?+\xcb\x87\x19\x00\xd4\xefw\xca\x1eqX\x8f\ 301 | \xba\x0a-\xdf7\xbd(\x0e\x81F\x98\xa9x\x8b\x92\xbb\ 302 | \xc2\xac\xbd\xde\xa7\xf8@j\x00H\xc5k\x15\xef\xd5Y\ 303 | \x8b\xban\x1d~\xb6s\x05\x9a\xe2[J\xdb\x8b,\xfb\ 304 | \x99R\xdb\x17\x1a\x00t\xf1\x99\xce\xb5\x16ut\xb4\xd6\ 305 | R\xaeUR\xd8Z\x02(\xc2c\xca\xab\x95G\xc3\x0c\ 306 | \xbb+n\xd7\x03@\x0a\xbc\xc9\xf2\x9a\xcaMaV\xb1\ 307 | ::Z\xff\xa6Pd\xa1I\x0eV(\xb2^\xf1{\ 308 | \xa5\xf6G\xaa\x01\xa0\xc3\xb5\xce'\xe3\xb0zU\x17<\ 309 | ^${\xab\xe2M\x0e\x81&\xa0\x9b\xd5\xdd\xae\xca\xf1\ 310 | q\x08\x00\xb5{VYI\xb9/\xcc*TuG\xeb\ 311 | _\x14\x8a,4\x09\xdd\xac\xee\xbc+3\x0f\xbc\x00H\ 312 | \xc5\x5c\x8a\xcf\x9e\xad\x5c\x95\x1d\xadE\x95;\x94\xf9\xc3\ 313 | \x0c\xc8\x1f\xdd\xac\xa9\xbdIq\xc1\x05\x00)x\x5cy\ 314 | \x95\xe2\xef\xee\xcaT\xd9\xd1\xfa{\x85\x22\x0bM\xe2'\ 315 | \x0d)\xb2&\xe7\xbd\xf2.\x8cC\x00\xa8\xdd\x82\xcaG\ 316 | \xe2\xb0:Uu\xb4f(\xeef-\x1df@\xfe\xe8\ 317 | f\xf5fg\xe5\xc48\x04\x80\xda\xdd\xa3\xf8\xbb\xbb\xb2\ 318 | c\xd2\xaa\xeah\xf9\xec7\x8a,4\x09\xdd\xac\xde\x9c\ 319 | \xa4\x5c\x10\x87\x00P\xbb\xe5\x94\xb7\xc5a5\xaa\xeah\ 320 | ]\xaaxgV\xa0\x09\xe8f\xf5gG\xe5\x8fq\x08\ 321 | \x00\xb5\xf3\x83:>o\xb9\x12Ut\xb4^\xa7Pd\ 322 | \xa1I\xe8f\xf5\xe7d\xe5Oq\x08\x00\xb5\xdbT\xd9\ 323 | \x22\x0e\xcbWE\xa1U\xcb\xe3\x94@I\x5c`\xfdO\ 324 | \x1c\xa2\x0f_\xec\x5c\x01 \x05\x95\xd5&e\x17Z\xbe\ 325 | \xbdR\xeb\xa9\xd9@\xc1\xdc\xcd\xaa\xf4\xd1\xe0\x868U\ 326 | 97\x0e\x01\xa0v{*+\xc4a\xb9\xca.\xb4\xbc\ 327 | \xa5\xc3\xecq\x08d\xcf\xdd,\x17Z\x18\x0c]-\x00\ 328 | \xa9\x98Cq\x8dR\xba2\x0b-\xef\xc2\xbao\x1c\x02\ 329 | \x8d@7k8\xa7+g\xc7!\x00\xd4n?\xc5\xdb\ 330 | O\x95\xaa\xccB\xcb\x8fO.\x1e\x87@\xf6\xe8f\x15\ 331 | \x83\xae\x16\x80T,\xa9\xf8\x16b\xa9\xca,\xb4>\xdc\ 332 | \xb9\x02M\xe0\x05\xf0t\xb3\x86wf'\x00\x90\x82\xd2\ 333 | w\x8a/k\x1f\xadu\x95\xab\xe2\x10\xc8\xde#\x8aO\ 334 | }\xa7\xd0*\xc6\xb6\x0a\xc5\x16\x80T\xac\xad\x5c\x1f\x87\ 335 | \xc5+\xab\xa3U\xf9YB@\x89X\x9bU\xac\xb3\x94\ 336 | 3\xe2\x10\x00jW\xea\x1d\xb82:Z>8\xfa^\ 337 | e\x810\x03\xf2F7\xab\x1c\xde\xc8\x98\x85\xf1\x00R\ 338 | \xe0\xef\xf7e\x95\xa7\xc3\xac`et\xb4\xde\xa9Pd\ 339 | \xa1)\xe8f\x95\xe3\x1c\xe5\xb48\x04\x80Z-\xa4\x94\ 340 | v\xfea\x19\x1d\xad\xf3\x94-\xe3\x10\xc8\x9a\xbbY\xde\ 341 | t\xf7\xf10C\xd1\xb6R\xd8\xc4\x14@\x0a\xbc\xa4\xe1\ 342 | \xf5qX\xac\xa2;Zk(\x14Yh\x0a?iH\ 343 | \x91U\x1e\xffQvJ\x1c\x02@\xad\xb6QV\x8e\xc3\ 344 | b\x15]h\xb1A)\x9a\xc2\xdd\xac\x83\xe3\x10%b\ 345 | _-\x00)\xf0\x1d\xbeRj\x98\x22\x0b-\x1f\xb5\xf3\ 346 | \xbe8\x04\xb2G7\xab\x1a\xe7+\x7f\x8cC\x00\xa8\xd5\ 347 | \xfb\x95\xc2\xd7\xae\x17\xf9\x1f\xb8\x93\xb2L\x1c\x02Y\xa3\ 348 | \x9bU-\xbaZ\x00R\xe0C\xa6\xdf\x18\x87\xc5)\xb2\ 349 | \xd0\xe2\xb6!\x9a\xe2\x9b\x0a\xdd\xac\xea\x5c\xa8\x9c\x18\x87\ 350 | \x00P+\x9f\x7fX\xa8\xa2\x9e:\x5cX\xb9_\xf1A\ 351 | \xd2@\xce\x1eV\xbco\x16\x85V\xb56Q.\x8aC\ 352 | \x00\xa8\xcd3\xcaR\xca\x13aV\x80\xa2:Z{)\ 353 | \x14Yh\x02\xd6f\xd5\xe3b\xe5\x848\x04\x80\xda\xcc\ 354 | \xa3\xbc5\x0e\x8bQT\xa1\xf5\xee\xce\x15\xc8\x99\xbbY\ 355 | \xdf\x8eC\xd4\xe0K\x9d+\x00\xd4\xa9\xd0\x9a\xa6\x88B\ 356 | \xcb\x0b\xe0K\xd9\xe4\x0b\xa8\x18\xdd\xacz]\xa2\x1c\x1f\ 357 | \x87\x00P\x1b/\x88_2\x0e\x87WD\xa1\xe5#w\ 358 | \x8a\x5cT\x0f\xd4\xc1\xdd,\x9e4\xac\x1f]-\x00u\ 359 | \x9bCy{\x1c\x0e\xaf\x88\x02i\x9f\xce\x15\xc8\x99\x9f\ 360 | 4,l\xf1#\x06v\xa9\xf2\xbb8\x04\x80\xda\x14V\ 361 | \xdb\x0c\xfb\xd4\xe1j\xca\x8dq\x08d\xcb\xdd,\x9fi\ 362 | H\xa1\x95\x86\x0d\x95\xcb\xe2\x10\x00j\xe3#yn\x8b\ 363 | \xc3\xc1\x0d\xdb\xd1*\xed\xb4k\xa0Bt\xb3\xd2r\xb9\ 364 | \xf2\xdb8\x04\x80\xda\x14R\xe3\x0c\xdb\xd1r\x9b\xff\xb5\ 365 | q\x08d\x89nV\x9a\xd6W\x5cp\x15\xb5\xd7\x1f\x00\ 366 | \xf4\xcb{\xfbm\x16\x87\x83\x1b\xa6\xa3\xe5M\x1d)\xb2\ 367 | \x90\xbbo(\x14Y\xe9\xb9R96\x0e\x01\xa0\x16\xde\ 368 | H\xd9\xc7\xf2\x0ce\x98B\xcb\x9b\x94\x029\xfb\xab\xf2\ 369 | \x9d8D\x82\xfc\x04\xe2\xcbq\x08\x00\x95sG}\xcf\ 370 | 8\x1c\x1c\x85\x16\xda\x8c\xb5Yi\xbbZ9:\x0e\x01\ 371 | \xa0\x16C\xd7:\x83\xae\x7fXN\xb9Ka\xfd\x04r\ 372 | \xe5n\x96o\x7fSh\xa5\xed5\xcaU\x0a\xdf5\x00\ 373 | \xea\xf0\x92\xe2\x9a\xc7\xe79\x0fd\xd0\x8e\x96\xcf\x01\xe2\ 374 | \x8b\x0f9\xa3\x9b\x95\x87k\x94_\xc7!\x00T\xceu\ 375 | \xd2Pg\x1f\x0eZh\xed\xd1\xb9\x029bmV^\ 376 | \xbe\xac\xf8\xafJ\x00\xa8\xc3\x9b;\xd7\x81\x0cRh-\ 377 | \xa0l\x13\x87@\x96x\xd20/\xd7)t\xb5\x00\xd4\ 378 | \xe5\x0d\xca|q\xd8\xbfA\x0a\xad\x9d\x94\x19q\x08d\ 379 | \x87nV\x9e\xe8j\x01\xa8\xcb\x5c\xca\xf6q\xd8\xbfA\ 380 | \x0a\xad\xdd:W G\xeef=\x19\x87\xc8\xc8\xf5\xca\ 381 | Qq\x08\x00\x95\xdb\xbds\xed[\xbf\x0b\xda]\x98y\ 382 | \xe5\xfd\x12a\x06\xe4\xc5\xdd,\xef\x02O\xa1\x95\xa75\ 383 | \x95k\x95A\xd7\x96\x02\xc0\xa0\xeeS\xfc\xf4a\xdf{\ 384 | \xfb\xf5\xfb\x85\xe5\xad\xe8)\xb2\x90\xab\xaf+\x14Y\xf9\ 385 | \xbaA\xf9e\x1c\x02@\xa5\x96Q6\x8a\xc3\xfe\xf4[\ 386 | h\xed\xda\xb9\x02\xb9\xf9\x8b\xf2\xdd8D\xc6\xfeCy\ 387 | 1\x0e\x01\xa0R\x03-\x9d\xea\xb7\xd0\xda\xa5s\x05r\ 388 | \xc3\xda\xacf\xb8Q\xf9E\x1c\x02@\xa5\xfc0`\xdf\ 389 | \xfaY\xa3\xb5\xb8\xf2\xa0\xc2F\xa5\xc8\x8d\xbbY\xde\x05\ 390 | \x9eB\xab\x19VS\xbc8~\xf60\x03\x80j\xb8\x9b\ 391 | \xeeZ\xe8\xd10\xebQ?\x1d\xad7*\x14Y\xc8\x11\ 392 | \xdd\xacf\xb9I92\x0e\x01\xa02\xfe\xe3n\xbb8\ 393 | \xec]?\x85\xd6\x0e\x9d+\x90\x13\xd6f5\xd3\x7f*\ 394 | /\xc4!\x00T\xa6\xefZ\x88B\x0bM\xc7\x93\x86\xcd\ 395 | t\x8b\xf2\xb38\x04\x80\xca\xf4]\x0b\xf5z+p\x0d\ 396 | \xc5\x8fV\x039q7\xcb\xfbf=\x15fh\x9a\x95\ 397 | \x95?+s\x84\x19\x00T\xc3\xdf=\xb7\xc5\xe1\xf4z\ 398 | \xedh\xd1\xcdB\x8e\xdc\xcd\xa2\xc8j\xae[\x95\x9f\xc6\ 399 | !\x00T\xa6\xaf\x9a\xa8\xd7B\xab\xef\xc5_@\xcdX\ 400 | \x9b\xd5\x0e_Q\x9e\x8fC\x00\xa8\x84\x1f\x0e\xecY/\ 401 | \x85\x96o/\xbe.\x0e\x81l\x1c\xa4\xd0\xcdj>\xb7\ 402 | \xef\x8f\x88C\x00\xa8\xc46\x9dkOzY\xa3\xb5\x8e\ 403 | rM\x1c\x02YxH\xf1\xbeY\x14Z\xed\xb0\xa2\xe2\ 404 | -\x1f\xe6\x0c3\x00(\x9f\xd7\xae{\x03\xe5i\xf5\xd2\ 405 | \xd1\xda\xb6s\x05r\xc1\xda\xacv\xb9C9<\x0e\x01\ 406 | \xa0\x12=w\xb5z)\xb4\xfaj\x91\x015s7\xeb\ 407 | {q\x88\x169@y.\x0e\x01\xa0t=7\xa1(\ 408 | \xb4\xd04t\xb3\xda\xe9N\xe5\xb08\x04\x80\xd2\xf5\x5c\ 409 | \x1bM\xb7F\xcbg\x8a\xf5t\x0f\x12H\x00k\xb3\xda\ 410 | m\x05\xe5feF\x98\x01@\xb9\xfc\xfb\xe6\xf68\x9c\ 411 | \xdct\x1d\xad\xad;W \x07\xa3\x1c\x10\x87\x18\x92\xbb\ 460 | \x84\xb7(w)\x0f)~\xc2\xd3]\xea\x17\x15\xe4\xed\ 461 | \x8b\x9d+\xba\xfb\x95\xf2\x8e8\x8cF\x17Z\x17)\x9b\ 462 | \xc4!&1\xfelH\x00\xcd\xb1\x80\xe23\x10\x17\x0b\ 463 | 3\xf4\xea\x05\xe5B\xe5L\xc5\x7f(]\xae\xdc\xa3\xa0\ 464 | \x99^\xee\x5c\xd1\xdd\xf9\xca\x96q8\xd1}\x8a\xdf@\ 465 | 2y\x004\xdb\xa7\x95n?\xfbdlf*\xbe\x0b\ 466 | \xe2\xbf\xdc\xbdE\x06\xda\xa3\xdb\xe7\x81\xbc\x92\xbb\x951\ 467 | F:43\x14\xff\xe0\xd0\xb1\x99\x1a\xef\x0f\xd0l\xf3\ 468 | +\xeej-\x1ef\x18\xefV\xe5\xbb\xca\x11\x0ak\xda\ 469 | \xda\xc9\xc5\x04&\xe7=\xb4\xbc\xcd\x83;\xbd\xc1\xc8b\ 470 | \xf8\xe5\x15\x8a\x08\x00m\xf7\xa4rP\x1cb\x94\xeb\x94\ 471 | w*>\xa6\xcd\xbb\xe9Sd\x01\xdd\xb9\xaeZ6\x0e\ 472 | \xa3\x91Bk\xc2\x06[\x00\xd0R\xdfS\xbc\x80\x1b\xb3\ 473 | \xcd\xf6\x80\xf2Ae]\xe5(e\xcc\x8e\xd7\x00\xbaz\ 474 | U\xe7\x1aPh\x01\xc0XO)>g\xb3\xcd|{\ 475 | \xc8\x07\xba\xaf\xa1\x1c\xa6P`\x01\xbd\x1bSS\x8d\x14\ 476 | Z\xcbu\xae\x00\x80\xd9f;Dq7\xa7\x8d\xfc`\ 477 | \xd4N\xcaG\x14\x1fQ\x04\xa0?^\x8e5\xcbH\xa1\ 478 | \xb5t\xe7\x0a _>\x84\x1b\xc5\xf0\x01\xfbm\xecj\ 479 | \x9d\xa1l\xa0\x9c\x12f\x00\x06\xb1T\xe7\x1a\x8c\x14Z\ 480 | c^\x04\x90\xa5\xc3\x95\xed\xe2\x10\x058T\xf1I\x05\ 481 | m\xe1\x13\x19vT\x1e\x0c3\x00\x83Z\xb2s\x0dF\ 482 | \x0a\xad1/\x02\xc8\xce\x1b\x94m\x14vm.\x8ew\ 483 | 2oKW\xcb\x9f\x9b\x0f+\xb3\x1eI\x070\xb0\xae\ 484 | \xcd\xab\xab\x95\xd1\x1bn\x91\xee\x01R\xe5]\xb9G>\ 485 | \xa7t\xb5\x8a3\x8f\xd2\xf4\xcd\x9c?\xa5\x00\xbd\xea\xf6\ 486 | \x19\x22cs\x852\x81[\xc5\xdd\xfe1\x19\x1b E\ 487 | \xafWF\x7fN\xcfRP\x9c\x8f)\xa3\xdf\xdf&\xe5\ 488 | +\x0a\xd0\x8fn\x9f#26\xf7*c\xcc\xae\xf8\xa0\ 489 | \xcfn\xff\x98\x8c\x0d\x90\x22/`\x1e\xffY\xa5\xabU\ 490 | \x9c\xb9\x15\x9f\xdd7\xfe=\xce=\xde\xdd\x1d\xe8W\xb7\ 491 | \xcf\x12\x19\x9b\xe7\x951\x9b\xc0\xfb^b\xb7\x7fH&\ 492 | \x06H\xcd\xb6J\xb7\xcf*]\xadb\xfd\xa3\xd2\xed}\ 493 | \xce5>\x04\xdaG\xaf\x01\xfd\xea\xf6y\x22\x133\xe6\ 494 | \x18\xafu\x94n\xff\x88L\x0c\x90\x9a\xd3\x95n\x9fU\ 495 | \x87\xaeVq|v\x99\x0f\x8b\xed\xf6>\xe7\x96G\x94\ 496 | 1;W\x03}\xe8\xf6\x99\x22\x13\xe3\xcd~\x03?u\ 497 | \xb8p\x1c\x02\xc8\xcc\xeb\x14?m8\x19\x9e@,\xce\ 498 | \xb3\xca\xd7\xe20{\x7f\xaf\xdc\x19\x87\x00J2\xab\xb6\ 499 | \xa2\xd0\x02\xf2\xf5\xa5\xceu2\xde\xee\x81\xaeVq~\ 500 | \xa4\xb8\xab\x95\xb3\xe3\x94_\xc6!\x80\x12-\xd2\xb9\x86\ 501 | Bk\xd6\x04@6\xb6Vz)\xa2\xa6+\xc6\xd0;\ 502 | w\xb5\xbe\x1a\x87Y\xf2\xbe`\xff\x14\x87\x00JFG\ 503 | \x0b\xc8\x5c\xaf\xb7\x05}{\xf1\x8dq\x88\x02\xfcX\xc9\ 504 | \xf5\xb6\xdb7\x14n\x19\x02\xd5\xa0\xd0\x022\xb6\x95\xb2\ 505 | }\x1c\xf6\x84\xb5Z\xc5yN\xc9\xb1\xab\xf5\xb0rP\ 506 | \x1c\x02\xa8\xc0\x98[\x87\x14Z@^\xfa-\x9c\xe8j\ 507 | \x15\xeb0\xe5\x8e8\xcc\x86\xbbY\x8f\xc7!\x80\x0a\x8c\ 508 | \xe9h-\x14\x87\x002\xb0\xa5\xb2C\x1c\xf6\x85\xaeV\ 509 | q\xbc\x19\xe1\x01q\x98\x85\xbf*\xdf\x8eC\x00\x15\x19\ 510 | Sh\xcd\x1f\x87\x0020h\xc1DW\xabX?Q\ 511 | n\x8f\xc3\xe4\xf9\x96\xe1\x93q\x08\xa0\x22\xf3u\xae\xa1\ 512 | \xd0\xf2\xa1\xa9\x00\xd2\xb7\xb9\xb2c\x1c\x0e\x84\xaeVq\ 513 | r\xe9j=\xa4|7\x0e\x01ThVm\xe5Bk\ 514 | \xde8\x04\x90\xb8a\xb7j\xa0\xabU,w\xb5n\x8b\ 515 | \xc3d\x1d\xa8<\x15\x87\x00*4\xab\xb6\xa2\xd0\x02\xf2\ 516 | \xb0\x99\xb2S\x1c\x0e\x85}\xb5\x8a\xf3\x82\xf2\x958L\ 517 | \xd2\x03\xca!q\x08\xa0b\x14Z@f\x8a*\x90\xbc\ 518 | \xd1i?[C`j?Un\x89\xc3\xe4\xb8\x9b\xf5\ 519 | t\x1c\x02\xa8\xd8\x98B\x8b5Z@\xda6Uv\x8e\ 520 | \xc3B\xb0V\xab8\xa9v\xb5\xeeW\x0e\x8dC\x005\ 521 | `\x8d\x16\x90\x91\xa2\x0b#\xbaZ\xc5\xfa\x99rs\x1c\ 522 | &\xe3\xbf\x14\x1f\xb9\x03\xa0\x1ecj+\xff\xe5\xf32\ 523 | \xe9)@\xd56Q\xba}\x16\x87\xcd9\x0a\x8a\xf3>\ 524 | \xa5\xdb\xfb\x5cG\xeeQ\xe6V\x802t\xfb\xcc\x91\x89\ 525 | \xb9W\x09\xdc\xd1\x9a#\x0e\x01$\xa8\xac\xdb|t\xb5\ 526 | \x8a\xf5s\xe5\xc68\xac\xdd\xd7\x94\x99q\x08\xa0&\xb3\ 527 | w\xae\xc1#J\xb7j\x8cL\x0cP\xa5\x8d\x95n\x9f\ 528 | \xc3\xa2BW\xabX\xefQ\xba\xbd\xcfU\xe6.e.\ 529 | \x05(K\xb7\xcf\x1d\x99\x18\x9f\xc8\x10\xb8\xa35\xa6\xea\ 530 | \x02\x90\x8c\xb2\x17\xad\xd3\xd5*\xd6/\x95?\xc7am\ 531 | |\xe0\xf5\xb3q\x08\xa0Fcj+of\xd7\xad\x1a\ 532 | #\x13\x03Te#\xa5\xdbg\xb0\xe8\x9c\xab\xa08\xef\ 533 | V\xba\xbd\xcfU\xc4\x07]\xcfP\x802u\xfb\xec\x91\ 534 | \x89yB\x99\xc5\xf7\xf2\xbb\xfd#21@U~\xa7\ 535 | t\xfb\x0c\x96\x91A\x0e\xa9Fw\xbeKp\xbd\xd2\xed\ 536 | }.;\xfb+@\xd9\xba}\xf6\xc8\xc4\x8cy\xea\xd7\ 537 | gvu\xfbGdb\x80*\xbcV\xe9\xf6\xf9++\ 538 | t\xb5\x8a\xf5.\xa5\xdb\xfb\x5cf|\x14\xd0\x9c\x0aP\ 539 | \xb6n\x9f?21\xcf)\xb3\xbc\xa4t\xfbGdb\ 540 | \x80*\xfcV\xe9\xf6\xf9+3t\xb5\x8a\xe3\xae\xd6\xb5\ 541 | J\xb7\xf7\xb9\xac|H\x01\xaa\xd0\xed\xf3G&\xc6\xb5\ 542 | \xd5,\x14Z\xbd\x07(\xdb\x86J\xb7\xcf^\xd9\xa1\xab\ 543 | U\xacw(\xdd\xde\xe72\xe2#\x80\xd8\xa6\x07U\xe9\ 544 | \xf6\x19$\x133\xa6\xd0\xe2\xd6a\xef\x01\xcav\xac\xd2\ 545 | \xed\xb3WE\xe8j\x15\xc7]\xadk\x94n\xefs\xd1\ 546 | \xd9W\x01\xaa\xd2\xed3H&f\xcc\xadC\x16\xc3\xf7\ 547 | \x1e\xa0L\x1b(uv\x98\xe9j\x15\xebmJ\xb7\xf7\ 548 | \xb9\xc8\xdc\xa4\xd0\xcdB\x95\xba}\x0e\xc9\xc4\x8cY\x0c\ 549 | \xcf\xf6\x0e\xbd\x07(\xd31J\xb7\xcf]\x95\xa1\xabU\ 550 | \x9c\xbfQ\xaeR\xba\xbd\xcfE\xc5G\xff\x00U\xea\xf6\ 551 | 9$\x133f{\x87\xc7\x95n\xff\x88L\x0cP\x96\ 552 | \xf5\x94\x14\xd6K\xd2\xd5*\xd6^J\xb7\xf7\xb9\x88x\ 553 | sT6\x9cF\xd5\xba}\x16\xc9\xc4<\xaa\x04^G\ 554 | \xf0b\x1c\x02\xa8\x91w\x81w\x07\xa4n[)t\xb5\ 555 | \x8a\xe3.\xe5\x95qX\xb8\xffT\xf8\xfe\x06\xd24\xe6\ 556 | g\xf3/J\xb7j\x8cL\x0cP\x86u\x95\x94\x9e\xfe\ 557 | =OAq\xde\xaat{\x9f\x87\x897E\xf5\x1f\xca\ 558 | @\xd5\xba}\x1e\xc9\xc4<\xa0\x04\xfeA}!\x0e\x01\ 559 | \xd4$\x95n\xd6\x88-\x95\x1d\xe3\x10\x05\xf0\xbehW\ 560 | \xc4aa\xfeC\x19\xf3\xf88\x80\xa4\x8c\xe9h\xf9|\ 561 | \xacn\xd5\x18\x99\x18\xa0h\xa9u\xb3FBW\xabX\ 562 | {(\xdd\xde\xe7A\xe2\xcdP\xe9f\xa1.\xdd>\x93\ 563 | dbnU\x02\xff\xb0>\x1d\x87\x00j\xf0y%\xa5\ 564 | n\xd6\x08\xbaZ\xc5:N\xb9<\x0e\x87\xf6e\x85n\ 565 | \x16\x90\xb6Y\xb5\x15\x85\x16P\x9fu\x94\xbd\xe30I\ 566 | \xbe\xa5\x89\xe2|\xa9s\x1d\x867A\xfdu\x1c\x02H\ 567 | \xd8\x98Bk\xcc\xa6Z\x00*\xf3\x05%\xc5n\xd6\x08\ 568 | \xbaZ\xc5\xfa\x9dri\x1c\x0e\xcc\xc5\x9aoK\x00H\ 569 | \xdb\xac\xda\x8a\x8e\x16P\x8f\xb5\x95\x94\xbbY#\xe8j\ 570 | \x15k\x98\xae\x96\xb7\x89\xf0v\x11\x00\xd2\xc7\xadC\xa0\ 571 | f\xeef\xf9\xe7/ut\xb5\x8au\xbcrq\x1c\xf6\ 572 | \xcdk\xb3\xe8f\x01y\xa0\xd0\x02j\xb4\x96\xe2s\xf0\ 573 | rQ\xc4\xda\x22\xbcb\x90\xf7\xd3\x0b\xe9}\xe08\x80\ 574 | <\x8c)\xb4|\xd6!\x80\xea\xe4\xd2\xcd\x1a\xb1\x85\xb2\ 575 | S\x1c\xa2\x00\x7fP.\x8c\xc3\x9eQ\xec\x02y\x19S\ 576 | h=\x16\x87\x00*\xe0\xb5Yo\x8f\xc3\xac\xb0V\xab\ 577 | X\xfd\x14N\x97(^H\x0f \x1fc\xce:\x9c5\ 578 | \x01P\xba\xaf)9u\xb3F\xd0\xd5*\xd6I\xca\x05\ 579 | q8-\xbaY@~\x1e\xe9\x5c)\xb4\x80\x0a\xbdQ\ 580 | ys\x1cf\x89\xaeV\xb1zy?/RN\x88C\ 581 | \x00\x19\x19\xd3\xd1\x9aUu\x01(\xcd\x5c\xca\xf7\xe20\ 582 | [t\xb5\x8au\xb2\xf2\xa78\x9c\x14\xc5-\x90'n\ 583 | \x1d\x02\x15\xf3/\xcc5\xe20k\xfc\xe2/\xd6T\xef\ 584 | \xe7\xf9\x8ao1\x02\xc8\xcf\x98&\xd6V\xca\xe8\x83\x10\ 585 | \xc9\xe4\x01\x06\xe1\x9f\xb1\x17\x94n\x9f\xa9\x1cCW\xab\ 586 | X\xe7(\xdd\xde\xe7\x1d\x14 5\xdd>\xabdb6\ 587 | Sf\xf1yk\xdd\xfe\x11\x99\x18\xa0_\x8b+w)\ 588 | \xdd>O\xb9f\xba\xdb]\xe8\x8f\xd7\xee\x8d\x7f\x8f\xcf\ 589 | U\x80\x14\x8d\xff\xac\x92\xee\x19s\x07c)\xa5\xdb?\ 590 | \x22\x13\x03\xf4c\x0e\xe54\xa5\xdbg)\xf7\xd0\xd5*\ 591 | \xd6\xd9\xca\xe8\xf7\xd7\xc5\x17\x90\xa2\xd1\x9fS2y\x16\ 592 | Sf\x99]yQ\xe9\xf6\x0f\xc9\xd8\x00\xfd\xf8\x81\xd2\ 593 | \xeds\xd4\x84x\xfd\x10\x8a\xf3\x06e\xe4\xbd=\xcb/\ 594 | \x00\x89\x1a\xfd=@\xba\xe7y\xe5o\x941\x1eT\xba\ 595 | \xfdc26@\xaf\xfeS\xe9\xf6\x19jRvVP\ 596 | \x9c3\x15\xbf\xaf\xaf\x0f3 M\xe3\xbf\x07\xc8\xc4\xdc\ 597 | \xabLp\xb5\xd2\xed\x1f\x93\xb1\x01z\xf1y\xa5\xdb\xe7\ 598 | \xa7i\xa1\xabU\xacm\x95\xd3\xe3\x10HV\xb7\xef\x02\ 599 | 26>\x9bt\x82S\x95n\xff\x98\x8c\x0d0\x9d\xff\ 600 | R\xba}v\x9a\x1a\xbaZ\xc5zU\xe7\x0a\xa4\xaa\xdb\ 601 | \xf7\x00\x19\x9b?*\xb3\x8c\x1c\x05\xf2@\xe7\x0a`0\ 602 | \xde\x90\xf4\xa7\xca\xa7\xc2\xac=\xd8W\xabXwv\xae\ 603 | \x00\xf25\xa6\xa6\x1a)\xb4\xbcF\x0b\xc0`\x96S\xbc\ 604 | \xbe\xe6\xbda\xd6.\x9b+t\xb5\x00\xe0\x15cj\xaa\ 605 | \x91B\xeb\xfe\xce\x15@\x7fvS|?\xde\x05G[\ 606 | \xd1\xd5\x02\x80Wt\xedh\xdd\xd3\xb9\x02\xe8\xcd\xc2\xca\ 607 | \x8f\x94\xdf+K\xf8\x85\x16\xa3\xab\x05\x00\xaf\xb8\xbbs\ 608 | \x0dF\x0a-\xd6\x05\x00\xbd\xf1\xcf\xcc\x07\x95?w\xae\ 609 | \x88\xbe\xd4\xb9\x02@\xdb\x8d\xa9\xa9F\x0a-\x1f\x11\x02\ 610 | `r\xde|\xee-\xca\x15\x8a;YK*x\x85\xcf\ 611 | \xf5\xda%\x0e\x01\xa0\xd5\xc6\xd4T#;\x97\xcePf\ 612 | *\x13v2\xc5\x18\xbc?\xed3\x9f\xf2.\xe5\xe3\x8a\ 613 | \xcf\x05\xc5\xe4.T\xda\xbcV\x0dh\x03o_\x80\xc9\ 614 | \xf9\xa4\x9d\xb9\x95\x17\xc2LF\x17\x0e\xf7)K\xc7!\ 615 | &A\xa1\xd5\x0e>\xa3\xd0G\xa2\xbcS\xd9[YP\ 616 | Ao\xde\xa4\x9c\x18\x87\x00\x1a\x88Bkj^\x9f\xb5\ 617 | B\x1cF\xa3\x0b\x87\x8b\x94M\xe2\x10\x93\xa0\xd0j\xa6\ 618 | y\x94\xf5\x14\xdf\xfe\xf2\xf1'\xdb)\x0b)\xe8\x1f]\ 619 | -\xa0\xd9(\xb4\xa6\xe6\x133\xb6\x8c\xc3ht\xe1p\ 620 | \xb4\xb2g\x1cb\x12_\xee\x5c\x91\xaf9\x95\xf9\x15\x9f\ 621 | \xac\xbe\xac\xf2jeEed\xbd\x22\x86GW\x0bu\ 622 | \xf0/\xb7\x1d\xe3\x10%b;\x97\xa9\xfdJyG\x1c\ 623 | F\xa3\x0b\xado(\xff\x12\x87\x0000\xbaZ\xa8\x9a\ 624 | \x7f\x97]\xa5\xbc&\xcc\x80\xfa\x1c\xa8\x8c9!d\xf4\ 625 | _\xf1\xb7t\xae\x000\x0c\x9e@D\xd5\xde\xa6Pd\ 626 | !\x05\x13j\xa9\xd1\x85\xd6\xcd\x9d+\x00\x0c\x8b}\xb5\ 627 | P\x15\xff\x1e\xe3v\x16R1\xa1\x96\xa2\xd0\x02P\x86\ 628 | M\x15\xaf\xd5\x02\xca\xf6ve\xed8\x04j7\xa1\x96\ 629 | \x1a\xbdFkv\xe5\x19\xc5\x8b\x85\x01`X~\x92\xd9\ 630 | \xb7\x11\x81\xb2\xb8Yp\x8d\xb2V\x98\x01\xf5\xf2~\xa4\ 631 | \xf3*c\x9e\xcc\x1c\xdd\xd1\xf2&[\xb7\xc7!\x00\x0c\ 632 | \x8d\xae\x16\xca\xe6\xbd\xee(\xb2\x90\x8a\xdb\x94\x09\xdb_\ 633 | \x8c.\xb4\x8c\x05\xf1\x00\x8a\xc4\xda\x19\x94\xc5wa\xbe\ 634 | \x10\x87@\x12\xba\xd6P\xe3\x0b\xad\x9b:W\x00(\x02\ 635 | ]-\x94\xc5Gc\xad\x11\x87@\x12\xba\xd6P\xe3\x0b\ 636 | \xad\xeb;W\x00(\x0a]-\x14\x8dn\x16R\xd4\xb5\ 637 | \x86\x1a_h]\xd7\xb9\x02@Q\xe8j\xa1h\xfb(\ 638 | \xab\xc5!\x90\x8c\xae5\xd4\xf8\xb3\xfb\x96P\x1e\x8cC\ 639 | \x00(\x0cO \xa2(>\xf4\xdd\x9d\x83U\xc3\x0cH\ 640 | \xc7\x22\xca\xa3q\xf8\x8a\xf1\x1d\xad\x87:\x01\x80\x22\xd1\ 641 | \xd5BQ\xde\xa3Pd!5\xf7)\x13\x8a,\x1b_\ 642 | h\x19\xb7\x0f\x01\x94\x81\xdd\xe21,w\xb3>\x1f\x87\ 643 | @R\xae\xed\x5c'\xa0\xd0\x02P\x95M\x94]\xe3\x10\ 644 | \x18\xc8\xfb\x94\x95\xe3\x10H\xca\xa4\xb5S\xb7Bk\xd2\ 645 | \xaa\x0c\x00\x86\xc4\x13\x88\x18\x94\xbbY\x9f\x8bC 9\ 646 | }u\xb4\xae\xee\x5c\x01\xa0ht\xb50\xa8\xf7++\ 647 | \xc5!\x90\x9cIk\xa7\xf1O\x1d\xda\x82\x8a\x17tu\ 648 | \xfb\x9f\x01\xc0\xb0.V\xbc8\x1e\xe8\x95\xcf\xe0\xbdQ\ 649 | yu\x98\x01iyIq\xed\xf4T\x98\x8d\xd3\xad\xa3\ 650 | \xf5\xb8rk\x1c\x02@\xe1\xe8j\xa1_\x1fP(\xb2\ 651 | \x90*\xff\x11\xd0\xb5\xc8\xb2n\x85\x96]\xde\xb9\x02@\ 652 | \x19X\xab\x85^\xb9\x9b\xf5\xd98\x04\x924e\xcd4\ 653 | Y\xa1uY\xe7\x0a\x00e\xa0\xab\x85^\xed\xa7\xac\x18\ 654 | \x87@\x92\xae\xe8\x5c\xbb\xa2\xa3\x05\xa0.t\xb50\x9d\ 655 | \x19\x0a\xdd,\xa4n\xa0\x8e\x16\x85\x16\x80\xb2\xb9\xab\xb5\ 656 | [\x1c\x02]}PY!\x0e\x81dMY3M\xf5\ 657 | d\xe1=\xca\xb2q\x08\x00\xa5\xb8Dq\xc1\x05\x8c7\ 658 | \x97r\xb3\xb2|\x98\x01i\xbaKyU\x1cv7Y\ 659 | G\xcb.\xec\x5c\x01\xa0,\x1b+t\xb5\xd0\xcd\x87\x14\ 660 | \x8a,\xa4n\xdaZ\x89B\x0b@\xddX\xab\x85\xf1\xdc\ 661 | \xcd\xfa\xf78\x04\x92vA\xe7:\xa9\xa9\x0a\xadi\xff\ 662 | \x97\x01\xa0\x00t\xb50\xde\xdf)\xcb\xc5!\x90\xb4i\ 663 | k\xa5\xa9\xd6h\xcd\xa7<\xa6\xcc\x1ef\x00P\x1e\xd6\ 664 | ja\xc4\xdc\x8a7\xcd^&\xcc\x80t=\xafxG\ 665 | \xf8\x99a6\x89\xa9:Z\xde\xe5\xf4\x9a8\x04\x80R\ 666 | \xd1\xd5\xc2\x88\xfd\x15\x8a,\xe4\xe0Je\xca\x22\xcb\xa6\ 667 | *\xb4\x8c\xdb\x87\x00\xaa\xc2Z-\xcc\xa3|:\x0e\x81\ 668 | \xe4\xf5\xb4\x96\x9dB\x0b@*\xdc\xd5\xda=\x0e\xd1R\ 669 | \x1fV\x96\x8eC y\xe7w\xaeS\x9aj\x8d\x96\xad\ 670 | \xaa\xdc\x14\x87\x00P\xbaK\x15\x17\x5ch\x9fy\x15\xaf\ 671 | \xcdZ*\xcc\x80\xf4\xf9\xa0\xf3;\xe2pr\xd3u\xb4\ 672 | \xbcY\xdc\xbdq\x08\x00\xa5\xdbH\xa1\xab\xd5N\x1fQ\ 673 | (\xb2\x90\x0b\x17X\xd3\x16Y6]\xa1egw\xae\ 674 | \x00P\x05\xd6j\xb5\x8f\xbbY\xff\x16\x87@\x16\xce\xea\ 675 | \x5c\xa7\xd5K\xa1\xd5\xf3\x7f\x18\x00\x14\x80\xaeV\xfb|\ 676 | TY2\x0e\x81,\xf4\xdc\x84\x9an\x8d\x96\xad\xad\x5c\ 677 | \x1b\x87\x00P\x09\xd6j\xb5\x87\xf7l\xbcMY\x22\xcc\ 678 | \x80<\xac\xa6xy\xd5\xb4z\xe9h]\xa7<\x14\x87\ 679 | \x00P\x09\xbaZ\xed\xf1\x0f\x0aE\x16r\xe2\xb5\xeb=\ 680 | \x15Y\xd6K\xa1e\xe7t\xae\x00P\x15\xd6j5\xdf\ 681 | \xfc\xca'\xe3\x10\xc8F_k\xd7{-\xb4N\xef\x5c\ 682 | \x01\xa0*t\xb5\x9a\xef\x1f\x95\xc5\xe2\x10\xc8F_5\ 683 | Q/k\xb4\xcc\xf7\x22o\x8cC\x00\xa8\xcce\x8a\x0b\ 684 | .4\xcf\x02\xca\xed\xca\xa2a\x06\xe4c%\xc5\x9f\xdd\ 685 | \x9e\xf4\xda\xd1\xf2\xa6\xa5=\xed\x17\x01\x00\x05z\xad\xf2\ 686 | \xe68D\xc3\xfc\x93B\x91\x85\xdc\xb8\x1e\xea\xb9\xc8\xb2\ 687 | ^\x0b-;\xa5s\x05\x80*\xb1V\xaby\x16T>\ 688 | \x11\x87@V\xfa\xae\x85\xfa)\xb4N\xee\x5c\x01\xa0J\ 689 | t\xb5\x9a\xe7c\xca\x22q\x08d\xa5\xefB\xab\xd75\ 690 | Z\xe6\x16\xaf\xb7y\xe8\xa78\x03\x80\x22\xb0V\xab9\ 691 | \x16R|\xebe\xe10\x03\xf2\xf1\xa2\xe2\x877\x1e\x0b\ 692 | \xb3\x1e\xf5S4=\xac\xf8\xcb\x0e\x00\xaaFW\xab9\ 693 | >\xaePd!G\x17)}\x15Y\xd6ow\xea\xc4\ 694 | \xce\x15\x00\xaa\xc6Z\xad\xfc\xb9\xc0r\xa1\x05\xe4\xe8\xa4\ 695 | \xce\xb5/\xfd\x16Z't\xae\x00P5\xbaZ\xf9\xa3\ 696 | \x9b\x85\x9c\x1d\xdf\xb9\xf6\xa5\x9f5Z\xe6\x7f\x7f\xbf\xc2\ 697 | \xe1\x9f\x00\xea\xc0Z\xad|\xb9\xc0\xf2\xda,\xaf\xd1\x02\ 698 | r\xe3cw\x96\x8b\xc3\xfe\xf4\xdb\xd1zY\xa1\xab\x05\ 699 | \xa0.\xeej\xed\x11\x87\xc8\xcc\xbf(\x14Y\xc8\xd5\xc0\ 700 | \xb5\xcf O\x10\x0e\xd4:\x03\x80\x82\xb0V+?\xde\ 701 | \xca\xc1[:\x00\xb9\x1a\xb8\xf6\x19\xa4\xd0\xf2~Z\xcf\ 702 | \xc5!\x00TnC\x85\xaeV^\xbc9\xa97)\x05\ 703 | r4S95\x0e\xfb7H\xa1\xf5\xa4rV\x1c\x02\ 704 | @-\xe8j\xe5\xc3\xfb\x0e\xf9\xb8\x1d Wg(O\ 705 | \xc7a\xff\x06)\xb4\xec\xb8\xce\x15\x00\xea@W+\x1f\ 706 | \xeef\xf9\x00i WC\xd5<\xfd>u8bY\ 707 | \xe5ne\xd0\xff}\x00\x18\xd6\xe5\x8a\x17\xc7#]\x8b\ 708 | +\xb7)\xf3\x87\x19\x90\x9f\x97\x14\xd7<\x0f\x84\xd9\x00\ 709 | \x06\xedh\xf91\xc7\xf3\xe3\x10\x00jAW+}\xff\ 710 | \xaaPd!g\xe7*\x03\x17Y6h\xa1eGw\ 711 | \xae\x00P\x17\xd6j\xa5k\x09\xe5\x1f\xe2\x10\xc8\xd6o\ 712 | :\xd7\x81\x0dSh\x1d\xd3\xb9\x02@]\xe8j\xa5\xeb\ 713 | \x93\xca|q\x08d\xc9{\x87\x0e]\xeb\x0c\xbb\xc6\xea\ 714 | \x12\x85]\x9a\x01\xd4\xe9\x0a\xc5k\xb5\xfc\xa5\x884\xf8\ 715 | \xf4\x10\xaf\xcd\x9a7\xcc\x80<]\xa0l\x11\x87\x83\x1b\ 716 | \xa6\xa3eC\xb7\xd4\x00`H\x1b(t\xb5\xd2\xf2o\ 717 | \x0aE\x16rW\xc8\x12\xa9a;Z\xab(7\xc7!\ 718 | \x00\xd4\x86\xaeV:\x96RnU(\xb4\x903\x7f\x97\ 719 | \xac\xa4\xdc\x11fC\x18\xb6\xa3u\x8brq\x1c\x02@\ 720 | m\xe8j\xa5\xe3S\x0aE\x16r\xe7\x9d\x15\x86.\xb2\ 721 | l\xd8B\xcb~\xde\xb9\x02@\x9d\xfc\x04\x22{\xfb\xd5\ 722 | ki\xe5\xc3q\x08d\xad\xb0\xda\xa6\x88B\xeb(\xe5\ 723 | \xc58\x04\x80\xda\xd0\xd5\xaa\xdf\xa7\x95y\xe2\x10\xc8\xd6\ 724 | \x0b\xca\xaf\xe2pxE\x14Z\xf7+>\x07\x08\x00\xea\ 725 | FW\xab>\xde={\xff8\x04\xb2v\x8a\xf2\x978\ 726 | \x1c^\x11\x85\x96\xfd\xa2s\x05\x80:\xd1\xd5\xaa\x8f\xbb\ 727 | Ys\xc7!\x90\xb5Bk\x9a\xa2\xfe\xf2[P\xf1\x16\ 728 | \xf5\xfc\x90\x01\xa8\x1bO Vo9\xc5\x0fG\xcd\x15\ 729 | f@\xbe\x9eV\xfc\xe4\xec\x93aV\x80\xa2:Z\x8f\ 730 | +\xbf\x8fC\x00\xa8\x95\xbbZo\x89CT\xe4\xdf\x15\ 731 | \x8a,4\xc1o\x95\xc2\x8a,+\xaa\xd0\xb2\xc3;W\ 732 | \x00\xa8\xdb\x17\x14\xd6jUcy\xe5Cq\x08d\xaf\ 733 | \xf0Z\xa6\xc8B\xeb\x8f\xca=q\x08\x00\xb5\xa2\xabU\ 734 | \x9d\xcf(t\xb3\xd0\x04\xde7\xeb\xb48,N\x91\x85\ 735 | \xd6K\xcaO\xe3\x10\x00jGW\xab|\xafR>\x18\ 736 | \x87@\xf6\x8eP\x0a_\xdbYd\xa1e\xdc>\x04\x90\ 737 | \x0a\xbaZ\xe5s7kF\x1c\x02Ys\x81\xf5\x938\ 738 | ,V\x19\x7f\xed\x9d\xa3l\x1d\x87\x00P+\x9e@,\ 739 | \xcf\x8a\xcaM\xca\x9ca\x06\xe4\xcd\xfb\x81n\x17\x87\xc5\ 740 | *\xba\xa3et\xb5\x00\xa4\x82\xaeVy>\xabPd\ 741 | \xa1)J\xab]\xca\xe8h\xcd\xa7\xdc\xabxo-\x00\ 742 | \xa8\xdb\x95\xca\x86\x0a]\xad\xe2\xbcZ\xb9Q\xa1\xd0B\ 743 | \x13<\xa2x/\xb8g\xc2\xac`et\xb4\x9eR~\ 744 | \x16\x87\x00P\xbb\xf5\x95\xb7\xc6!\x0aB7\x0bM\xe2\ 745 | \x07\xf9J)\xb2\xac\xac'r^\xa3\x5c\x1d\x87\x00P\ 746 | ;\xbaZ\xc5YIq7k\x8e0\x03\xf2\xb7\x96r\ 747 | C\x1c\x16\xaf\x8c\x8e\x96]\xa3\x9c\x1b\x87\x00P;\xba\ 748 | Z\xc5\xf9\x9cB\x91\x85\xa68S)\xad\xc8\xb2\xb2\x0a\ 749 | -;\xb4s\x05\x80\x14\xb0\xaf\xd6\xf0VQ\xde\x17\x87\ 750 | @#|\xbfs-M\x99\x85\xd6o\x94\x87\xe2\x10\x00\ 751 | jGWkxt\xb3\xd0$\x0f(\xc7\xc4ay\xca\ 752 | ,\xb4\x9eS\x0e\x8bC\x00H\x02]\xad\xc1\xad\xaa\xbc\ 753 | 7\x0e\x81Fp\x8d\xf2|\x1c\x96\xa7\xccB\xcb\x0eQ\ 754 | ^\x8cC\x00\xa8\x1d]\xad\xc1}^\x99=\x0e\x81\xec\ 755 | \xbd\xa0\xb8F)]\xd9\x85\xd6\x9d\xca\xb1q\x08\x00I\ 756 | \xa0\xab\xd5\xbf\xd5\x95}\xe2\x10h\x84\xa3\x95\xbb\xe3\xb0\ 757 | \x5ce\x17Z\xf6\xad\xce\x15\x00R@W\xab\x7ft\xb3\ 758 | \xd04\x95\xd5&U\xfdUw\xb1\xb2q\x1c\x02@\xed\ 759 | \xaeR|<\x0f\xfbjMo\x0d\xe5Z\x85B\x0bM\ 760 | q\x81\xb2E\x1c\x96\xaf\x8a\x8e\x96\x1d\xdc\xb9\x02@\x0a\ 761 | \xd6S\xf6\x8cCL\xc3\xb7Z)\xb2\xd0$\x95\xdei\ 762 | \xab\xaa\xa3\xe5\xa3\x1a\xeeP\x96\x093\x00\xa8\x1f]\xad\ 763 | \xe9y\xc7lo@]\xd5\x1f\xe5@\xd9\xeeRVV\ 764 | \xbc\x18\xbe\x12U\xfd\xf0\xf8\xf1\xc9\xef\xc6!\x00$\x81\ 765 | \xae\xd6\xf4\xdc\xcd\xa2\xc8B\x93\xb8\x16\xa9\xac\xc8\xb2*\ 766 | \x9f\xbcYDqWk\x810\x03\x80\xfa\xd1\xd5\x9a\xdc\ 767 | \xda\x8a\xcf\xac\xa5\xd0BS<\xa6\xbcJy<\xcc*\ 768 | R\xe5\x0f\xd0#\xca\xff\xc6!\x00$\x81\xae\xd6\xe4\xbe\ 769 | \xa8Pd\xa1I|4`\xa5E\x96U\xbd\x97\xccr\ 770 | \xca\xad\xca\x8c0\x03\x80\xfa\xd1\xd5\x9a\xe85\x8a\xdf\x17\ 771 | \xf6\x1bCS\xccTVR\xee\x0f\xb3\x0aU\xfd\xd7\xca\ 772 | =\xca\x91q\x08\x00I\xa0\xab5\x91\xbbY\x14Yh\ 773 | \x92#\x94\xca\x8b,\xab\xe3\x07iM\xc5{\xb2\xd0\x92\ 774 | \x06\x90\x0a?Y\xe7\x8dL_\x0a\xb3vs\xe1y\x85\ 775 | B\xa1\x85\xa6\xf0Q\x80\xde\x0f\xee\x960\xabX\x1d\xc5\ 776 | \xce\x0d\xcaqq\x08\x00I\xf0\xad\xb2\xf7\xc4a\xeb\x1d\ 777 | \xa0Pd\xa1I|\xdcN-E\x96\xd5\xf5\xc3\xb4\x91\ 778 | rI\x1c\x02@\x12\xbc\xb4\xc1\x1d\xf7'\xc3\xac\x9d\xb6\ 779 | SN\x8bC\xa0\x11\xbc\xf6rC\xe5\xca0\xabA]\ 780 | \xbb\xfd\xde\xa7l\xa2\xf8\xa0R\x00H\xc1\x82\xca\xbc\xca\ 781 | \x1f\xc3\xac}\xbc\xb1\xf4\xef\x94%\xc2\x0ch\x06\xdfA\ 782 | \xab\xf5t\x9a:\xdb\xc3.\xb4.\x8aC\x00H\x82\xd7\ 783 | h\xbdN\xf9S\x98\xb5\x8b\x17\xc0\x7f)\x0e\x81Fp\ 784 | 7\xeb\xb5\x8a\xd7\x1c\xd6\xa6\xee\xfb\xf0'(o\x8aC\ 785 | \x00H\x82\xb7\xa0\xf1\xad\x86\xca\xf7\xdb\xa9\x91\x0f\xfdw\ 786 | q\xe9\xae\x16\xd0\x14\xeef\xbd%\x0e\xebSw\xa1\xb5\ 787 | \xa9ra\x1c\x02@2\xbcxv\xef8l\xbc\x85\x15\ 788 | \xaf\x99]%\xcc\x80\xe6p7\xeb\xf28\xacO\xdd'\ 789 | \xb2{\xf1\xe9\xe6\xca\xaaa\x06\x00i\xf0\xf13>\x0f\ 790 | \xed\x9c0k.\xff\x0epQ\xe9?z\x81&\xf1z\ 791 | \xc3\xff\x89\xc3z\xd5]h\xd9\xcd\xca\x87\xe2\x10\x00\x92\ 792 | \xf1\x06\xc5\xdfO>\xef\xaf\xa9\xbe\xa3\xbc;\x0e\x81\xc6\ 793 | \xf0\xda\xac}\x14?xW\xbb\x146\x0d\xf5\xadCW\ 794 | \x9e\x00\x90\x12/\xad8\x5c\xd9=\xcc\x9a\xe7\x0b\xcaG\ 795 | \xe3\x10h\x14wi/\x8b\xc3\xfa\xd5\xbdFk\x847\ 796 | \x0b\xf4\x1e\x17\xec\x16\x0f 5\xcf)oW\x9a\xb4\xd1\ 797 | \xf2\xe7\x95\xff\x88C\xa0Q\xbc\x0b\xbck\x0ao\x8e\x9e\ 798 | \x84T\x0a\x1b\x1f\x7f\xf1\x8b8\x04\x80\xa4\xf8\x10\xfc\xdf\ 799 | (\xfb\x85Y\xde\xfc\xc7\xb5\xd7\xadPd\xa1\xa9|\xa6\ 800 | a2E\x96\xa5\xd2\xd1\xb2\x95\x15\xbf9<^\x0c \ 801 | U\xff\xad|F\xc9\xf1L\xc4\xf9\x95\x9f*o\x0d3\ 802 | \xa0y\x9eUVS\xee\x0a\xb3D\xa4t\xab\xce{\xd7\ 803 | \xfc0\x0e\x01 I\x9fRNR\x96\x0c\xb3|\xf8V\ 804 | \x8a7\x88\xa6\xc8B\x93\x1d\xaa$UdYJ\x1d-\ 805 | [Z\xf1\xc1\x8f>\x06\x03\x00R\xf5\x80\xf2\xb7\xca\xef\ 806 | \xc3,]\xfe\x8e\xff\x98\xf25en\xbf\x004\x94\xcf\ 807 | (\xf5\x9d\xb1\x87\xc2,!\xa9->\xbf_\xf9F\x1c\ 808 | \x02@\xb2\x96R\xfc\xb4\xf4\xff)\xcb\xfa\x85\x04\xad\xaf\ 809 | \x9c\xa7xM\x16E\x16\x9a\xee@%\xb9\x22\xcbR\xeb\ 810 | h\x99\xd7\x11\xdc\xa4\xb8\xbb\x05\x00\xa9\xf3_\xd2_W\ 811 | \xbe\xa9<\xe1\x17j\xb6\x82\xe23\x0b?\xa0\xf0$7\ 812 | \xda\xc0\x9b\x9f\xaf\xae<\x1df\x89Ia\xc3\xd2\xf1\xfc\ 813 | (\xf5c\xca\x9b\xc3\x0c\x00\xd2\xe6\xa7\x12_\xaf\xfc\x9d\ 814 | \xe2\xce\x91\x9f\xa2~F\xa9\xda\x1a\x8ao\x11\x1e\xa6\xf8\ 815 | \xec\xc2\x14\xff\x90\x06\xca\xf0O\x8a\x8f\x91JR\xaa?\ 816 | \x88\xfe+\xcc\xa7m\xaf\x1bf\x00\x90\x8f\x99\xcaQ\x8a\ 817 | \x0b\x1e\x1f\xe1\xe3]\xaa\xcb\xe2\xf5\xac{(\xdez\xe2\ 818 | \x8d\x0a\xc5\x15\xda\xc6g\x19n\xa4\x94\xf9s6\x94\x94\ 819 | \x7f(wT\xfe\x18\x87\x00\x90\xa5\xbb\x95\xdf*'*\ 820 | g+\xbe\xcd8\xac\x15\x95\xed\x94]\x95\x9d\x95\xf9\x14\ 821 | \xa0\xad\xfc\xb3pF\x1c\xa6)\xf5\xbf~\xfc\xe5\xe4/\ 822 | \x12\x00\xc8\x9dw\xac\xbeJ\xb9T\xf1\xedE\x9f\xa3x\ 823 | \xa7\xf2\xa0\xe2\xe5\x12\xee\x84\x99\x97tx\xad\xea\xe2\x8a\ 824 | \xd7\xaa\xba\xb0\xf2m\xc1\xf5\x14\xdf\x12\x5c^\x01\x10\x1f\ 825 | HqG7i\xa9\x17Z>A\xdfG\xf3\xcc\x11f\ 826 | \x00\xd0l\xde\x08\x95\x05\xec\xc0\xf4\xbc\x9e\xdb\xcb\x8bn\ 827 | \x0c\xb3\x84\xa5\xb8\x18~4?\xaa\xb9\x98\xb2y\x98\x01\ 828 | @\xb3\xb1\xc6\x0a\xe8\x8d\xb7\x82\xf2Z\xc8\xe4\xe5\xf0C\ 829 | \xbd\x90\xe2\x8a5\xb7\x9d\x98\x01\x00@\xf1\xeeU|;\ 830 | \xbd\x885\x8f\xa5K\xbd\xa3e>\xbb\xe8\xafJ\xf2\xf7\ 831 | a\x01\x00@\xe9>\xa2x\xadc\x16riS\xfb\xff\ 832 | \xce\xf3\x95\xcd\xc2\x0c\x00\x00\xb4\x91\xb7L\xd9&\x0e\xf3\ 833 | \x90\xd3z\x00?ms\xa1\xc2BQ\x00\x00\xda\xc7O\ 834 | \xeez\xcf,?$\x97\x8d\x9c\x8a\x16\xef\xfa\xfa\xe38\ 835 | \x04\x00\x00-s\xa8\x92U\x91e\xb9=\xe1\xb2\x88r\ 836 | \x83\xc2\xc2x\x00\x00\xda\xe3>eM\xe5\xf10\xcbH\ 837 | n\xb7\xe1\x1eQ>\x11\x87\x00\x00\xa0%>\xa6dW\ 838 | dYn\x1d\xad\x11\xa7(\xdb\xc7!\x00\x00h\xb0\x13\ 839 | \x94\xdd\xe20?\xb9\x16Z\xab*W+>)\x1f\x00\ 840 | \x004\xd3\xd3\x8aO\x89\xb9#\xcc2\x94\xc3>Z\xdd\ 841 | <\xac\xf8\xb6\xe7\x1b\xc2\x0c\x00\x004\xd1\xe7\x94?\xc4\ 842 | a\x9er\xedh\xd9\x0c\xe5r\xc5\x95.\x00\x00h\x16\ 843 | \x1f\xc2\xee\xed\x1c^\x08\xb3L\xe5\xbc'\x95\x0f\x94\xfc\ 844 | \xa0\xe2CX\x01\x00@s\xb8\xb8\xda\xb7s\xcdZ\xae\ 845 | \xb7\x0eG\xdc\xad\xf8,\xc4-\xc2\x0c\x00\x004\xc1\x81\ 846 | \xca\x91q\x98\xb7\x9co\x1d\x8e\x98G\xf1\x06f\xab\x85\ 847 | \x19\x00\x00\xc8\x99\xf7\xcb\xdc@\xf1Y\xc7\xd9k\xc2q\ 848 | 6\xcf(\xbe\x85\xf8r\x98\x01\x00\x80\x5cy9\xd0~\ 849 | J#\x8a,\xcb\xfd\xd6\xe1\x88;\x95\xc5\x95M\xc3\x0c\ 850 | \x00\x00\xe4\xe8[J\xa3\x8e\xdbk\xc2\xad\xc3\x11\xf3)\ 851 | \xde[k\xa50\x03\x00\x009\xb9YYO\xf1\x9d\xaa\ 852 | \xc6h\xc2\xad\xc3\x11O)\xefWx\x0a\x11\x00\x80\xbc\ 853 | \xbc\xa8\xbcOiT\x91eM\xb9u8\xc2\xb7\x10\xe7\ 854 | W\xb6\x0a3\x00\x00\x90\x83\xffR\x8e\x88\xc3fi\xd2\ 855 | \xad\xc3\x11\xde\xc8\xf4b\xc5\xedG\x00\x00\x90\xb6\xcb\x94\ 856 | \xcd\x95\xe7\xc3\xaca\x9aXh\x99\x8b,\x17[.\xba\ 857 | \x00\x00@\x9af*\xde\xfd\xfd\xba0k\xa0\xa6\xdd:\ 858 | \x1c\xf1\x80\xe2\x9d\xe3w\x083\x00\x00\x90\xa2O*\xbf\ 859 | \x8f\xc3fjjG\xcb\xbc\xd0\xff\x0ce\x9b0\x03\x00\ 860 | \x00)9MqC\xa4\xd1\xfb`6\xb9\xd0\xb2\x15\x94\ 861 | +\x94E\xc3\x0c\x00\x00\xa4\xe0/\xca\xfa\xca\xbda\xd6\ 862 | `M\xda\xde\xa1\x9b\xbb\x14\xef\x1a\x0f\x00\x00\xd2\xe0\x0e\ 863 | \xd6\x07\x94\xc6\x17Y\xd6\xd45Z\xa3\xf9\xcc\xa4%\x95\ 864 | M\xc2\x0c\x00\x00\xd4\xe9`\xe5;q\xd8|M\xbfu\ 865 | 8bn\xe5B\x85-\x1f\x00\x00\xa8\x8f\xb7r\xd8B\ 866 | \xf1\x03k\xad\xd0\x96B\xcb\xd6R.Q\xe6\x0d3\x00\ 867 | \x00P\xa5'\x95\xd7*7\x85YK\xb4\xe1\xd6\xe1\x08\ 868 | /\xbc\xf3\xb6\x0fo\x0e3\x00\x00P\xa5\x0f)\xde\x0d\ 869 | \xa0U\xdaTh\xd9\xe5\x8a\x0f\x9d\xde \xcc\x00\x00@\ 870 | \x15~\xa8\x1c\x10\x87\xed\xd2\xa6[\x87#|\xeb\xf0\x02\ 871 | e\xdd0\x03\x00\x00e\xf2\xba\xac-\x95g\xc3\xace\ 872 | \xdaXh\xd9\xea\x8a\x8f\xe8Y0\xcc\x00\x00@\x19\x1e\ 873 | U|\xc4\xce\xada\xd6BM\xdfGk27*\xec\ 874 | \xaf\x05\x00@y\xbc_\xd6\xfb\x95\xd6\x16Y\xd6\xb65\ 875 | Z\xa3\xf9\x00\xcbE\x14\x9f\x18\x0e\x00\x00\x8au\x90\xf2\ 876 | \xbd8l\xaf\xb6\xde:\x1c1\xa7r\xba\xb2u\x98\x01\ 877 | \x00\x80\x22\xf8\xe9B\x9fc\xf8b\x98\xb5X\xdb\x0b-\ 878 | [J\xf1\xfeZ\xcb\x87\x19\x00\x00\x18\xc6\xed\x8aOc\ 879 | \xf1\xb6J\xad\xd7\xd65Z\xa3yo\xad\xb7*3\xc3\ 880 | \x0c\x00\x00\x0c\xea\x19\xc5\xbfS)\xb2:\xda\xbcFk\ 881 | 4\x1fl\xe9\x03\xa8\xfd\xe1\x00\x00\x00\x83\xf1\xe2\xf7S\ 882 | \xe3\x10F\xa1\xf5\x8a+\x15\x16\xc7\x03\x000\x98\xaf+\ 883 | \xdf\x8cC\x8c`\x8d\xd6Xs(\x7fT\xb6\x0b3\x00\ 884 | \x00\xd0\x8b\x93\x957)\xad_\xfc>\x1e\x85\xd6D\x8b\ 885 | *\xde9~\xb50\x03\x00\x00S\xb9A\xd9B\xf1\xe6\ 886 | \xa4\x18\x87B\xab;\x17Y.\xb6\x5ct\x01\x00\x80\xee\ 887 | \xbc\xe8}3\xa5\xd5\x9b\x92N\x85\xa7\x0e\xbb\xbbI\xd9\ 888 | Ky>\xcc\x00\x00\xc0x\xcf)~\x88\x8c\x22k\x0a\ 889 | ,\x86\x9f\x9c\xf7\x01\xf1\xd3\x88o\x0e3\x00\x000\xda\ 890 | \xbe\xca\xf1q\x88\xc9PhM\xedre>e\xab0\ 891 | \x03\x00\x00v\x80\xf2\xad8\xc4T(\xb4\xa6w\x9a\xf2\ 892 | \x1ae\xed0\x03\x00\xa0\xdd\x8eR>\x1a\x87\x98\x0e\x8b\ 893 | \xe1{3\xb7r\x8a\xc2\x99\x88\x00\x806;S\xd9I\ 894 | \xf1\xfa,\xf4\x80B\xabw~\x02\xf1\xa1\x1c\x1a\x87\x18\x06\ 904 | \x85\xd6\xf0\xceU\xe6U\xd8=\x1e\x00\xd0\x04_Q\xbe\ 905 | \x1a\x87\x18\x16\x85V1NU\x96U6\x0a3\x00\x00\ 906 | \xf2\xf4=\xe5\x93q\x88\x22Ph\x15\xe7\x0f\xca\xaa\xca\ 907 | za\x06\x00@^\x0eW>\x1c\x87(\x0a\x85Vq\ 908 | \xbcp\xf08\xc5;\xc7\xaf\xe3\x17\x00\x00\xc8\xc4\xcf\x95\ 909 | }\x15\xff.C\x81(\xb4\x8a\xe5\x0f\xe8o\x95u\x95\ 910 | \xb5\xfc\x02\x00\x00\x89\xfb\xb5\xc2\x96E%\xe1\x08\x9er\ 911 | \xcc\xa9\x1c\xa3\xec\x16f\x00\x00\xa4\xc9\xcd\x81\xb7)/\ 912 | \x84\x19\x0aG\xa1U\x9e\xb9\x14\x7f\x80w\x0e3\x00\x00\ 913 | \xd2r\x82\xb2\xa7\xf2\x5c\x98\xa1\x14\xec\x0c_\x9e\x91c\ 914 | \x0bN\x0a3\x00\x00\xd2\xe1\x07\xb8|\x9c\x1cEV\xc9\ 915 | (\xb4\xca5Sy\x8b\xf2\xfb0\x03\x00\xa0~\xbe\xdb\ 916 | \xe2F\x80\x1b\x02(\x19\x85V\xf9\xfcA\xf6_\x0d^\ 917 | \xb3\x05\x00@\x9d\xbc\xf0\xddk\xb2\xe8dU\x84\xa7\x0e\ 918 | \xab\xe1'9\x5ch\xb1\xf5\x03\x00\xa0.\xde\xc2\xc1O\ 919 | \x17\xfa\xb0hT\x84B\xab:.\xb6\x8eUVV\xd8\ 920 | \xd4\x14\x00P\xa5\x9f(\xde'\x8b-\x1c*F\xa1U\ 921 | \xad\x91MM\x97Q8\xae\x07\x00P\x85C\x94\xfd\x15\ 922 | 6#\xad\x01\x85V\xf5\xfcA?^\x99G\xd9\xda/\ 923 | \x00\x00P\x12\x1f\x10\xfd\xafq\x88:Ph\xd5\xc7\x07\ 924 | Q\xfb\xa9\xc4\xed\xc3\x0c\x00\x80\xe2\xf8\x8f\xfaO(_\ 925 | \x0d3\xd4\x86B\xab^\xe7)\xf7*\xbb*l\x1e\x0b\ 926 | \x00(\x82\x17\xbb\x7fH94\xccP+\x0a\xad\xfa]\ 927 | \xa6\xdc\xa0x\xbf-\xfe\xfb\x00\x00\x0c\xc3[\x0a\xbdC\ 928 | \xf9e\x98\xa1vtQ\xd2\xb1\x83r\xb4\xb2@\x98\x01\ 929 | \x00\xd0\x9f\xc7\x14oDzF\x98!\x09\x14Zi\xd9\ 930 | @\xf1\xb1\x08~*\x11\x00\x80^\xdd\xad\xbcI\xb9:\ 931 | \xcc\x90\x0c\x0a\xad\xf4\xac\xa8\x9c\xa8\xac\x15f\x00\x00L\ 932 | \xed\x1ae\x17\xc5\xc5\x16\x12\xc3\x11<\xe9\xb9C\xd9J\ 933 | 97\xcc\x00\x00\x98\xdc\x99\x8a\xb7\x0a\xa2\xc8J\x14\x85\ 934 | V\x9a\x1eQF\xd6l\x01\x00\xd0\xcdQ\xca\xce\x8a\xd7\ 935 | f!Q<\xe5\x96\xae\x17\x14\x1f\xfe\xe9\x8dM\xdd\xe1\ 936 | \x02\x00`\xc4\x01\xcaG\x15\xff\xae@\xc2(\xb4\xd2\xe7\ 937 | \x8dM\xefR\xbc\xc8\x91\xff\xbe\x00\xa0\xdd\x9eS|f\ 938 | \xe1\xb7\xc2\x0c\xc9c1|>\xb6U\x8eQ\x16\x0d3\ 939 | \x00@\xdb\xfcE\xf1\xf6\x0d\xac\xe1\xcd\x08\x85V^V\ 940 | S|N\xe2\xeaa\x06\x00h\x8b\xeb\x95\xdd\x94[\xc3\ 941 | \x0c\xd9`1|^nR6WN\x0b3\x00@\x1b\ 942 | \x9c\xacl\xa9Pde\x885?\xf9\xf1A\xd4?W\ 943 | \x16T\x5ct\x01\x00\x9a\xeb e?\xe5\x990Cv\ 944 | \xb8u\x98\xb7\xf7*\xff\xab\xcc\x1df\x00\x80\xa6xZ\ 945 | \xf9\xa0\xf2\x7fa\x86lQh\xe5o#\xe5Xe\x85\ 946 | 0\x03\x00\xe4\xce\x1bW\xbfE\xb9\x22\xcc\x905\xd6h\ 947 | \xe5\xefRec\xe5\xec0\x03\x00\xe4\xcc\x07B\xfb;\ 948 | \x9d\x22\xab!X\xa3\xd5\x0cO)G*\xf3+[\xf8\ 949 | \x05\x00@V^V\xbc\x1e\xeb\x03\x8a\xbf\xd3\xd1\x10\xdc\ 950 | :l\x9e=\x95\xc3\x15/\x96\x07\x00\xa4\xefQ\xc5\x05\ 951 | \xd6qa\x86F\xa1\xd0j&\xef\xb7\xf5\x1be\xbd0\ 952 | \x03\x00\xa4\xeareo\x85\xad\x1b\x1a\x8a5Z\xcd4\ 953 | \xb2\xdf\xd6O\xc2\x0c\x00\x90\xa2\x1f*\xec\x8f\xd5p\xac\ 954 | \xd1j.\x1f4\xea6\xb4\xcfI\xdcA\x99S\x01\x00\ 955 | \xd4\xefI\xe5C\x8a\x0f\x86\xe6P\xe8\x86\xe3\xd6a;\ 956 | \xac\xa5x/\x16n%\x02@\xbd.S\xde\xa9\xf8\xce\ 957 | \x03Z\x80\x8eV;\xf8 R\xdfF\x5cD\xd9\xd4/\ 958 | \x00\x00*\xf7-\xc5E\xd6Ca\x86V\xa0\xa3\xd5>\ 959 | {(\x87)\x8b\x86\x19\x00\xa0l.\xac\xf6UN\x08\ 960 | 3\xb4\x0a\x85V;-\xafx\xdf\xadm\xc3\x0c\x00P\ 961 | \x96\xd3\x14\x1f\x97v_\x98\xa1u\xb8u\xd8N\x8f+\ 962 | ?U\xbc \xd3\xc5\xd6\x1c\x0a\x00\xa083\x95O*\ 963 | \x1fU\x9e\xf0\x0bh':ZXW\xf9\x99\xb2~\x98\ 964 | \x01\x00\x86\xe5\x05\xef\xeeb]\x17fh5:Zx\ 965 | P\xf1\x9a\xad\x19\x8a\xf7s\xa1\xf8\x06\x80\xc1\xbc\xa8\xfc\ 966 | \x97\xf2\x1e\xe5\x01\xbf\x00\xf0K\x15\xa3m\xad\x1c\xa1\xac\ 967 | \x1cf\x00\x80^\xdd\xac\xbcO9?\xcc\x80\x0e:Z\ 968 | \x18\xedN\xe5\xc7\x8a\x0f\xa7\xf66\x10\x14\xe2\x000\xb5\ 969 | \x97\x14o\xdb\xf0v\xe56\xbf\x00\x8c\xc6/RL\xc6\ 970 | \xdd-\x17]\xab\x87\x19\x00`\xbc\xeb\x95\xfd\x94\x0b\xc2\ 971 | \x0c\xe8\x82\x8e\x16&3\xd2\xdd\x9aK\xd9L\xe1\x5cL\ 972 | \x00\x88|l\xce\x81\xca\xbb\x94;\xfc\x020\x19:Z\ 973 | \xe8\x85o#z\xc1\xfc:a\x06\x00\xedu\x95\xe2.\ 974 | \xd6\xa5a\x06L\x83\x8e\x16zq\x8f\xe2S\xe6\xbd/\ 975 | \x8c\x9fL\xe4\x80j\x00m\xf3\xb4\xf2Y\xc5;\xbc\xfb\ 976 | ;\x11\xe8\x09\x1d-\xf4k\x15\xe5\x10e\xc70\x03\x80\ 977 | \xe6\xfb\x83\xe2\x8dGo\x0f3\xa0\x0f\xac\xbbA\xbfn\ 978 | QvR\xde\xad\xb0O\x0c\x80&\xf3\xb19~\x9ap\ 979 | W\x85\x22\x0b\x03\xe1\xd6!\x06u\x8d\xf2#ea\xe5\ 980 | \xb5\x0a\xddQ\x00M\xe1\x8dG\xdd\xb9\xdfS\xb9\xdc/\ 981 | \x00\x83\xe2\x97#\x8a\xe0B\xeb\xbb\xca\x16a\x06\x00\xf9\ 982 | :G\xf9G\xe5\xca0\x03\x86\xc4\xadC\x14\xc1\xe7z\ 983 | m\xa5\xbc_\xb9\xdf/\x00@f\xeeU\xf6Q\xb6Q\ 984 | (\xb2P\x18n\x1d\xa2H\xfer\xf2\xd3\x89\xde{k\ 985 | \x13\x85B\x1e@\xea\x9eS\xbe\xa1\xbcMa\xcb\x06\x14\ 986 | \x8e[\x87(\xcbZ\xca\xd7\x957\x85\x19\x00\xa4\xe7w\ 987 | \xca'\x95\x1b\xc3\x0c(\x01\x85\x16\xca\xb6\xbd\xe2\xbf\x16\ 988 | \xd7\x0b3\x00\xa8\x9f\x17\xb8\x7fB9#\xcc\x80\x12q\ 989 | k\x07e;U\xd9P\xf9\xa0\xe2G\xa5\x01\xa0.\xde\ 990 | h\xf4\x03\xca\xc6\x0aE\x16*\xc1\x1a-T\xe1e\xc5\ 991 | \x7fA~_y^\xf1\xfa\xad\x19\x0a\x00T\xe1I\xe5\ 992 | +\x8a\xf7\xff\xbbD\xf1w\x12P\x09\x0a-T\xc9E\ 993 | \xd6\x99\xca\xc8a\xd5\xeet\xf1\x19\x04P\x96g\x15o\ 994 | =\xb3\xb7r\xa2\xe2\xef \xa0R\xac\xd1B\x9d^\xad\ 995 | |Yy\x8f\xc2ml\x00E\xf1\x86\xa3G(\xfe~\ 996 | \xb9\xd3/\x00u\xa1\xd0B\x0a\xd6Q\xdc\xd6\x7fK\x98\ 997 | \x01\xc0`|K\xf0h\xe5\xf3\xca\x0d~\x01\xa8\x1b]\ 998 | \x04\xa4\xe0Z\xe5\xad\xca\xa6\x8a\x0fo\x05\x80~y\xab\ 999 | \x06/r\xf7~X\x14YH\x06\x1d-\xa4\xc8\x8b\xe5\ 1000 | \xbf\xa0\xec\x16f\x000\xb9\xe3\x14\xdf\x22\xe4LB$\ 1001 | \x89B\x0b)\xdbH\xf9\xa2\xb2{\x98\x01@\xe4[\x84\ 1002 | #\x05\xd6\x15~\x01H\x15\x85\x16r\xe0C\xab?\xa3\ 1003 | \xf8\xf6\x22\xb7\xbb\x81\xf6\xf2\x22w\xaf\xc1\xfa\xaa\xc2y\ 1004 | \x84\xc8\x02\x85\x16r\xb2\xba\xe2\xe32\xde\xa7\xb0\x0f\x17\ 1005 | \xd0\x1e\xde\xa6\xe1'\xcaA\xca-~\x01\xc8\x05\x85\x16\ 1006 | r\xb4\x8c\xf2\xcf\xca\xfe\xca\x82~\x01@#=\xa6\x1c\ 1007 | \xaa\x1c\xac\xdc\xef\x17\x80\xdcPh!g\x0b)\x1fQ\ 1008 | \xfeAY\xce/\x00h\x84\xbb\x94\xef(?P\x1e\xf7\ 1009 | \x0b@\xae(\xb4\xd0\x04s(~\xa4\xfb\xe3\x8a\xb7\x88\ 1010 | \x00\x90\xa7\x0b\x94o)^\x87\xf5\x82_\x00rG\xa1\ 1011 | \x85\xa6\xd9Rq\xc1\xb5\xa7\xc2\xf1>@\xfa\x5cP\xb9\ 1012 | \xb0r\x81\xe5B\x0bh\x14\x0a-4\xd5\xab\x14\xdfV\ 1013 | \xdcOY\xd2/\x00H\xca\x03\xcaa\xca!\xca\xdd~\ 1014 | \x01h\x22\x0a-4\x9d\x9fNtw\xcbE\xd76~\ 1015 | \x01@\xad|\xb0\xfc\xf7\x95c\x14\x0eyF\xe3Qh\ 1016 | \xa1M\xd6V>\xacx{\x08/\xa4\x07P\x8dG\x94\ 1017 | \x9f*.\xb08\x1e\x07\xadB\xa1\x856\x9aW\xf1\xe2\ 1018 | \xf9}\x15w\xb9\xf89\x00\x8a\xe7\xdd\xdb\xdd\xbd:\x5c\ 1019 | \xf9\x8d\xf2\x8c\x02\xb4\x0e\xbf`\xd0v++.\xb8\xde\ 1020 | \xaf\xac\xe0\x17\x00\x0c\xe5\x0e\xe5\x08\xc5\x1b\x8c\xde\xe6\x17\ 1021 | \x806\xa3\xd0\x02\x22\x1f\xed\xf3F\xc5\x8b\xe7\xf7P\xe6\ 1022 | Q\x00\xf4\xe6i\xe5\xb7\x8a\x17\xb7\x9f\xae\xb8\x9b\x05@\ 1023 | (\xb4\x80\x89\x16P|\xae\xe2\xbb\x95\xed\x15\xb6\x89\x00\ 1024 | &\xf2\xb6\x0c\xa7(\xbfP\x5cd=\xa9\x00\x18\x87B\ 1025 | \x0b\x98\x9a\xb7\x86x\x87\xe2\xa2ks\xbf\x00\xb4\x98;\ 1026 | U\x7fR\x5c\x5c\xfdJ\xf9\x8b\x02`\x0a\x14Z@\xef\ 1027 | VR\xbc\x88~/\x85\x1d\xe8\xd1\x16.\xae.T\xbc\ 1028 | \xa9\xe8\xaf\x15\xaf\xc1\x02\xd0#\x0a-`0^8\xef\ 1029 | \xfd\xb9\x5ctm\xa5x\x8d\x17\xd0\x14/)\xe7(.\ 1030 | \xae\x8eU\xd8P\x14\x18\x10\x85\x160\xbc\xa5\x15\xaf\xe9\ 1031 | z\xb3\xf2\x06e.\x05\xc8\xcdL\xe5\x0c\xe58\xc5k\ 1032 | \xae\xbcs;\x80!Qh\x01\xc5\x9aO\xd9A\xd9M\ 1033 | y\x93\xb2\x8c\x02\xa4\xea^\xe5\x04\xe5x\xe5T\xc5O\ 1034 | \x0f\x02(\x10\x85\x16P\x1e\xff|m\xa4\xb8\xe8\xdaI\ 1035 | \xd9D\xe1\x09F\xd4\xe9E\xe5\x22\xe5$\xc5\xc5\xd5e\ 1036 | \x0a\x80\x12Qh\x01\xd5YX\xd9Nq\xc7\xcbYE\ 1037 | \x01\xcav\x93\xe2m\x18\x1c\xdf\x1a|L\x01P\x11\x0a\ 1038 | -\xa0>~\x8a\xd1\x05\x977J\xf5Q@^\xeb\x05\ 1039 | \x0c\xeb>\xe5,\xc5\x1b\x87\xba\xb8\xba]\x01P\x13\x0a\ 1040 | - \x1d\xab+.\xb8\xb6\xed\x5c_\xa5\x00\xd3\xf1v\ 1041 | \x0b.\xac\xce\xee\x5coV\x00$\x82B\x0bH\xd7\xab\ 1042 | \x95\xad\x95-\x14o\x96\xba\x9e2\x87\x82\xf6z^\xb9\ 1043 | R\xf1\xbeV\xe7+\xe7*\xeck\x05$\x8cB\x0b\xc8\ 1044 | \x87\xcf_\xf4\xe2z\x17]\xcef\xca\xf2\x0a\x9a\xeb.\ 1045 | \xc5E\xd5\x05\x9d\x5c\xaax\x1b\x06\x00\x99\xa0\xd0\x02\xf2\ 1046 | \xb6\x84\xb2\x81\xb2\xe1\xa8\xac\xa6\xb0\x81j^\xbcA\xe8\ 1047 | \x8d\xca\xe5\xa3r\x85\xc2\x117@\xe6(\xb4\x80\xe6\xf1\ 1048 | ^^\xeb+\xeb*\xeb(kw\xae,\xb6O\x83\x17\ 1049 | \xab_\xab\x5c\xd7\xb9^\xad\x5c\xa5<\xa5\x00h\x18\x0a\ 1050 | -\xa0=\x16QF\x8a\xae\xb5\x94U;\xf1\xd3\x8f\xec\ 1051 | f_\xacg\x95[\x95[\x14o\xafp\xbd\xe2\xc2\xca\ 1052 | yD\x01\xd0\x12\x14Z\x00|\x9b\xd1g7\xba\xe8\xf2\ 1053 | \xde^\xbe\xae\xd8y\xcdO>zw{nE\x8e\xe5\ 1054 | \x8d?\xdd\x99\xf2\x1a*\xc7[(\xb8\xa8\xf2\x13\x7f\x8e\ 1055 | \xcf\x06\xf4\xed@\x00-G\xa1\x05`:~\xd2qY\ 1056 | \xc5E\x97\x8b//\xc0_JY\xb2s\x1d\x19{\xbd\ 1057 | X\xeeOE\xbe\xa0<\xa4\xf8\x9c\xbf\x07\xc7]]<\ 1058 | \xdd\xa9\xb8\xb0\xf2\xd15\xfe\xb7\x000%\x0a-\x00E\ 1059 | \xf1\xf7\xc9b\x9dx\x17|\xdf\xaa\xf4u\xfc\xd8k\xc8\ 1060 | \xfc\x04\xe5\xbc\xa322\x9f[\xf11E.\xd8|\x1d\ 1061 | =\x1e)\xe2\x5c\xe0\xb8\xa34r\x1d=\xf6\x13y>\ 1062 | \xaf\xcfyf\xd4x$\x8f*\xbeu\xe7\xeb\xf8\xb1\x17\ 1063 | \x9e?\xac\xbc\xac\x00\x00\x00\x00\x00\x00\x00\x00\xd0:\xb3\ 1064 | \xcd\xf6\xff\x01\xd0\xc0\xe9\xb4[%\xeb\xc0\x00\x00\x00\x00\ 1065 | IEND\xaeB`\x82\ 1066 | " 1067 | 1068 | qt_resource_name = b"\ 1069 | \x00\x08\ 1070 | \x05\xe2Y'\ 1071 | \x00l\ 1072 | \x00o\x00g\x00o\x00.\x00p\x00n\x00g\ 1073 | " 1074 | 1075 | qt_resource_struct = b"\ 1076 | \x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x01\ 1077 | \x00\x00\x00\x00\x00\x00\x00\x00\ 1078 | \x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\ 1079 | \x00\x00\x01\x8a\xb8SU\xab\ 1080 | " 1081 | 1082 | def qInitResources(): 1083 | QtCore.qRegisterResourceData(0x03, qt_resource_struct, qt_resource_name, qt_resource_data) 1084 | 1085 | def qCleanupResources(): 1086 | QtCore.qUnregisterResourceData(0x03, qt_resource_struct, qt_resource_name, qt_resource_data) 1087 | 1088 | qInitResources() 1089 | --------------------------------------------------------------------------------