├── 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 | 
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 | 
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 | 
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 | 
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 |
--------------------------------------------------------------------------------